Added GAL::DrawPolygon(SHAPE_POLY_SET) & GAL::DrawPolyLine(SHAPE_LINE_CHAIN)

This commit is contained in:
Maciej Suminski 2017-01-24 14:31:57 +01:00
parent 1eb7e7161e
commit 80956ef1e6
5 changed files with 153 additions and 89 deletions

View File

@ -3,6 +3,8 @@
* *
* Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de * Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de
* Copyright (C) 2012 Kicad Developers, see change_log.txt for contributors. * Copyright (C) 2012 Kicad Developers, see change_log.txt for contributors.
* Copyright (C) 2017 CERN
* @author Maciej Suminski <maciej.suminski@cern.ch>
* *
* CAIRO_GAL - Graphics Abstraction Layer for Cairo * CAIRO_GAL - Graphics Abstraction Layer for Cairo
* *
@ -30,6 +32,7 @@
#include <gal/cairo/cairo_gal.h> #include <gal/cairo/cairo_gal.h>
#include <gal/cairo/cairo_compositor.h> #include <gal/cairo/cairo_compositor.h>
#include <gal/definitions.h> #include <gal/definitions.h>
#include <geometry/shape_poly_set.h>
#include <limits> #include <limits>
@ -253,6 +256,13 @@ void CAIRO_GAL::DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEnd
} }
void CAIRO_GAL::DrawPolygon( const SHAPE_POLY_SET& aPolySet )
{
for( int i = 0; i < aPolySet.OutlineCount(); ++i )
drawPoly( aPolySet.COutline( i ) );
}
void CAIRO_GAL::DrawCurve( const VECTOR2D& aStartPoint, const VECTOR2D& aControlPointA, void CAIRO_GAL::DrawCurve( const VECTOR2D& aStartPoint, const VECTOR2D& aControlPointA,
const VECTOR2D& aControlPointB, const VECTOR2D& aEndPoint ) const VECTOR2D& aControlPointB, const VECTOR2D& aEndPoint )
{ {
@ -1050,6 +1060,25 @@ void CAIRO_GAL::drawPoly( const VECTOR2D aPointList[], int aListSize )
} }
void CAIRO_GAL::drawPoly( const SHAPE_LINE_CHAIN& aLineChain )
{
if( aLineChain.PointCount() < 2 )
return;
const VECTOR2I start = aLineChain.CPoint( 0 );
cairo_move_to( currentContext, start.x, start.y );
for( int i = 1; i < aLineChain.PointCount(); ++i )
{
const VECTOR2I& p = aLineChain.CPoint( i );
cairo_line_to( currentContext, p.x, p.y );
}
flushPath();
isElementAdded = true;
}
unsigned int CAIRO_GAL::getNewGroupNumber() unsigned int CAIRO_GAL::getNewGroupNumber()
{ {
wxASSERT_MSG( groups.size() < std::numeric_limits<unsigned int>::max(), wxASSERT_MSG( groups.size() < std::numeric_limits<unsigned int>::max(),

View File

@ -30,6 +30,7 @@
#include <gal/opengl/utils.h> #include <gal/opengl/utils.h>
#include <gal/definitions.h> #include <gal/definitions.h>
#include <gl_context_mgr.h> #include <gl_context_mgr.h>
#include <geometry/shape_poly_set.h>
#include <macros.h> #include <macros.h>
@ -619,123 +620,75 @@ void OPENGL_GAL::DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEn
void OPENGL_GAL::DrawPolyline( const std::deque<VECTOR2D>& aPointList ) void OPENGL_GAL::DrawPolyline( const std::deque<VECTOR2D>& aPointList )
{ {
if( aPointList.size() < 2 ) drawPolyline( [&](int idx) { return aPointList[idx]; }, aPointList.size() );
return;
currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
std::deque<VECTOR2D>::const_iterator it = aPointList.begin();
// Start from the second point
for( ++it; it != aPointList.end(); ++it )
{
const VECTOR2D startEndVector = ( *it - *( it - 1 ) );
double lineAngle = startEndVector.Angle();
drawLineQuad( *( it - 1 ), *it );
// There is no need to draw line caps on both ends of polyline's segments
drawFilledSemiCircle( *( it - 1 ), lineWidth / 2, lineAngle + M_PI / 2 );
}
// ..and now - draw the ending cap
const VECTOR2D startEndVector = ( *( it - 1 ) - *( it - 2 ) );
double lineAngle = startEndVector.Angle();
drawFilledSemiCircle( *( it - 1 ), lineWidth / 2, lineAngle - M_PI / 2 );
} }
void OPENGL_GAL::DrawPolyline( const VECTOR2D aPointList[], int aListSize ) void OPENGL_GAL::DrawPolyline( const VECTOR2D aPointList[], int aListSize )
{ {
if( aListSize < 2 ) drawPolyline( [&](int idx) { return aPointList[idx]; }, aListSize );
return; }
currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
// Start from the second point void OPENGL_GAL::DrawPolyline( const SHAPE_LINE_CHAIN& aLineChain )
for( int i = 1; i < aListSize; ++i ) {
{ drawPolyline( [&](int idx) { return aLineChain.CPoint(idx); }, aLineChain.PointCount() + 1 );
const VECTOR2D startEndVector = ( aPointList[i] - aPointList[i - 1] );
double lineAngle = startEndVector.Angle();
drawLineQuad( aPointList[i - 1], aPointList[i] );
// There is no need to draw line caps on both ends of polyline's segments
drawFilledSemiCircle( aPointList[i - 1], lineWidth / 2, lineAngle + M_PI / 2 );
}
// ..and now - draw the ending cap
const VECTOR2D startEndVector = ( aPointList[aListSize - 1] - aPointList[aListSize - 2] );
double lineAngle = startEndVector.Angle();
drawFilledSemiCircle( aPointList[aListSize - 1], lineWidth / 2, lineAngle - M_PI / 2 );
} }
void OPENGL_GAL::DrawPolygon( const std::deque<VECTOR2D>& aPointList ) void OPENGL_GAL::DrawPolygon( const std::deque<VECTOR2D>& aPointList )
{ {
currentManager->Shader( SHADER_NONE ); auto points = std::unique_ptr<GLdouble[]>( new GLdouble[3 * aPointList.size()] );
currentManager->Color( fillColor.r, fillColor.g, fillColor.b, fillColor.a ); GLdouble* ptr = points.get();
// Any non convex polygon needs to be tesselated for( const VECTOR2D& p : aPointList )
// for this purpose the GLU standard functions are used
TessParams params = { currentManager, tessIntersects };
gluTessBeginPolygon( tesselator, &params );
gluTessBeginContour( tesselator );
std::unique_ptr<GLdouble[]> points( new GLdouble[ 3 * aPointList.size() ] );
int v = 0;
for( std::deque<VECTOR2D>::const_iterator it = aPointList.begin(); it != aPointList.end(); ++it )
{ {
points[v] = it->x; *ptr++ = p.x;
points[v + 1] = it->y; *ptr++ = p.y;
points[v + 2] = layerDepth; *ptr++ = layerDepth;
gluTessVertex( tesselator, &points[v], &points[v] );
v += 3;
} }
gluTessEndContour( tesselator ); drawPolygon( points.get(), aPointList.size() );
gluTessEndPolygon( tesselator );
// Free allocated intersecting points
tessIntersects.clear();
// vertexList destroyed here
} }
void OPENGL_GAL::DrawPolygon( const VECTOR2D aPointList[], int aListSize ) void OPENGL_GAL::DrawPolygon( const VECTOR2D aPointList[], int aListSize )
{ {
currentManager->Shader( SHADER_NONE ); auto points = std::unique_ptr<GLdouble[]>( new GLdouble[3 * aListSize] );
currentManager->Color( fillColor.r, fillColor.g, fillColor.b, fillColor.a ); GLdouble* target = points.get();
const VECTOR2D* src = aPointList;
// Any non convex polygon needs to be tesselated
// for this purpose the GLU standard functions are used
TessParams params = { currentManager, tessIntersects };
gluTessBeginPolygon( tesselator, &params );
gluTessBeginContour( tesselator );
std::unique_ptr<GLdouble[]> points( new GLdouble[3 * aListSize] );
int v = 0;
const VECTOR2D* ptr = aPointList;
for( int i = 0; i < aListSize; ++i ) for( int i = 0; i < aListSize; ++i )
{ {
points[v] = ptr->x; *target++ = src->x;
points[v + 1] = ptr->y; *target++ = src->y;
points[v + 2] = layerDepth; *target++ = layerDepth;
gluTessVertex( tesselator, &points[v], &points[v] ); ++src;
++ptr;
v += 3;
} }
gluTessEndContour( tesselator ); drawPolygon( points.get(), aListSize );
gluTessEndPolygon( tesselator ); }
// Free allocated intersecting points
tessIntersects.clear();
// vertexList destroyed here void OPENGL_GAL::DrawPolygon( const SHAPE_POLY_SET& aPolySet )
{
for( int j = 0; j < aPolySet.OutlineCount(); ++j )
{
const SHAPE_LINE_CHAIN& outline = aPolySet.COutline( j );
const int pointCount = outline.PointCount();
std::unique_ptr<GLdouble[]> points( new GLdouble[3 * pointCount] );
GLdouble* ptr = points.get();
for( int i = 0; i < outline.PointCount(); ++i )
{
const VECTOR2I& p = outline.CPoint( i );
*ptr++ = p.x;
*ptr++ = p.y;
*ptr++ = layerDepth;
}
drawPolygon( points.get(), pointCount );
}
} }
@ -1341,6 +1294,63 @@ void OPENGL_GAL::drawStrokedSemiCircle( const VECTOR2D& aCenterPoint, double aRa
} }
void OPENGL_GAL::drawPolygon( GLdouble* aPoints, int aPointCount )
{
currentManager->Shader( SHADER_NONE );
currentManager->Color( fillColor.r, fillColor.g, fillColor.b, fillColor.a );
// Any non convex polygon needs to be tesselated
// for this purpose the GLU standard functions are used
TessParams params = { currentManager, tessIntersects };
gluTessBeginPolygon( tesselator, &params );
gluTessBeginContour( tesselator );
GLdouble* point = aPoints;
for( int i = 0; i < aPointCount; ++i )
{
gluTessVertex( tesselator, point, point );
point += 3; // 3 coordinates
}
gluTessEndContour( tesselator );
gluTessEndPolygon( tesselator );
// Free allocated intersecting points
tessIntersects.clear();
}
void OPENGL_GAL::drawPolyline( std::function<VECTOR2D (int)> aPointGetter, int aPointCount )
{
if( aPointCount < 2 )
return;
currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
int i;
for( i = 1; i < aPointCount; ++i )
{
auto start = aPointGetter( i - 1 );
auto end = aPointGetter( i );
const VECTOR2D startEndVector = ( end - start );
double lineAngle = startEndVector.Angle();
drawLineQuad( start, end );
// There is no need to draw line caps on both ends of polyline's segments
drawFilledSemiCircle( start, lineWidth / 2, lineAngle + M_PI / 2 );
}
// ..and now - draw the ending cap
auto start = aPointGetter( i - 2 );
auto end = aPointGetter( i - 1 );
const VECTOR2D startEndVector = ( end - start );
double lineAngle = startEndVector.Angle();
drawFilledSemiCircle( end, lineWidth / 2, lineAngle - M_PI / 2 );
}
int OPENGL_GAL::drawBitmapChar( unsigned long aChar ) int OPENGL_GAL::drawBitmapChar( unsigned long aChar )
{ {
const float TEX_X = font_image.width; const float TEX_X = font_image.width;

View File

@ -120,10 +120,12 @@ public:
/// @copydoc GAL::DrawPolyline() /// @copydoc GAL::DrawPolyline()
virtual void DrawPolyline( const std::deque<VECTOR2D>& aPointList ) override { drawPoly( aPointList ); } virtual void DrawPolyline( const std::deque<VECTOR2D>& aPointList ) override { drawPoly( aPointList ); }
virtual void DrawPolyline( const VECTOR2D aPointList[], int aListSize ) override { drawPoly( aPointList, aListSize ); } virtual void DrawPolyline( const VECTOR2D aPointList[], int aListSize ) override { drawPoly( aPointList, aListSize ); }
virtual void DrawPolyline( const SHAPE_LINE_CHAIN& aLineChain ) override { drawPoly( aLineChain ); }
/// @copydoc GAL::DrawPolygon() /// @copydoc GAL::DrawPolygon()
virtual void DrawPolygon( const std::deque<VECTOR2D>& aPointList ) override { drawPoly( aPointList ); } virtual void DrawPolygon( const std::deque<VECTOR2D>& aPointList ) override { drawPoly( aPointList ); }
virtual void DrawPolygon( const VECTOR2D aPointList[], int aListSize ) override { drawPoly( aPointList, aListSize ); } virtual void DrawPolygon( const VECTOR2D aPointList[], int aListSize ) override { drawPoly( aPointList, aListSize ); }
virtual void DrawPolygon( const SHAPE_POLY_SET& aPolySet ) override;
/// @copydoc GAL::DrawCurve() /// @copydoc GAL::DrawCurve()
virtual void DrawCurve( const VECTOR2D& startPoint, const VECTOR2D& controlPointA, virtual void DrawCurve( const VECTOR2D& startPoint, const VECTOR2D& controlPointA,
@ -397,6 +399,7 @@ private:
/// Drawing polygons & polylines is the same in cairo, so here is the common code /// Drawing polygons & polylines is the same in cairo, so here is the common code
void drawPoly( const std::deque<VECTOR2D>& aPointList ); void drawPoly( const std::deque<VECTOR2D>& aPointList );
void drawPoly( const VECTOR2D aPointList[], int aListSize ); void drawPoly( const VECTOR2D aPointList[], int aListSize );
void drawPoly( const SHAPE_LINE_CHAIN& aLineChain );
/** /**
* @brief Returns a valid key that can be used as a new group number. * @brief Returns a valid key that can be used as a new group number.

View File

@ -38,6 +38,9 @@
#include <gal/stroke_font.h> #include <gal/stroke_font.h>
#include <newstroke_font.h> #include <newstroke_font.h>
class SHAPE_LINE_CHAIN;
class SHAPE_POLY_SET;
namespace KIGFX namespace KIGFX
{ {
/** /**
@ -117,6 +120,7 @@ public:
*/ */
virtual void DrawPolyline( const std::deque<VECTOR2D>& aPointList ) {}; virtual void DrawPolyline( const std::deque<VECTOR2D>& aPointList ) {};
virtual void DrawPolyline( const VECTOR2D aPointList[], int aListSize ) {}; virtual void DrawPolyline( const VECTOR2D aPointList[], int aListSize ) {};
virtual void DrawPolyline( const SHAPE_LINE_CHAIN& aLineChain ) {};
/** /**
* @brief Draw a circle using world coordinates. * @brief Draw a circle using world coordinates.
@ -152,6 +156,7 @@ public:
*/ */
virtual void DrawPolygon( const std::deque<VECTOR2D>& aPointList ) {}; virtual void DrawPolygon( const std::deque<VECTOR2D>& aPointList ) {};
virtual void DrawPolygon( const VECTOR2D aPointList[], int aListSize ) {}; virtual void DrawPolygon( const VECTOR2D aPointList[], int aListSize ) {};
virtual void DrawPolygon( const SHAPE_POLY_SET& aPolySet ) {};
/** /**
* @brief Draw a cubic bezier spline. * @brief Draw a cubic bezier spline.

View File

@ -137,10 +137,12 @@ public:
/// @copydoc GAL::DrawPolyline() /// @copydoc GAL::DrawPolyline()
virtual void DrawPolyline( const std::deque<VECTOR2D>& aPointList ) override; virtual void DrawPolyline( const std::deque<VECTOR2D>& aPointList ) override;
virtual void DrawPolyline( const VECTOR2D aPointList[], int aListSize ) override; virtual void DrawPolyline( const VECTOR2D aPointList[], int aListSize ) override;
virtual void DrawPolyline( const SHAPE_LINE_CHAIN& aLineChain ) override;
/// @copydoc GAL::DrawPolygon() /// @copydoc GAL::DrawPolygon()
virtual void DrawPolygon( const std::deque<VECTOR2D>& aPointList ) override; virtual void DrawPolygon( const std::deque<VECTOR2D>& aPointList ) override;
virtual void DrawPolygon( const VECTOR2D aPointList[], int aListSize ) override; virtual void DrawPolygon( const VECTOR2D aPointList[], int aListSize ) override;
virtual void DrawPolygon( const SHAPE_POLY_SET& aPolySet ) override;
/// @copydoc GAL::DrawCurve() /// @copydoc GAL::DrawCurve()
virtual void DrawCurve( const VECTOR2D& startPoint, const VECTOR2D& controlPointA, virtual void DrawCurve( const VECTOR2D& startPoint, const VECTOR2D& controlPointA,
@ -365,6 +367,21 @@ private:
*/ */
void drawStrokedSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle ); void drawStrokedSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle );
/**
* @param Generic way of drawing a polyline stored in different containers.
* @param aPointGetter is a function to obtain coordinates of n-th vertex.
* @param aPointCount is the number of points to be drawn.
*/
void drawPolyline( std::function<VECTOR2D (int)> aPointGetter, int aPointCount );
/**
* @brief Draws a filled polygon. It does not need the last point to have the same coordinates
* as the first one.
* @param aPoints is the vertices data (3 coordinates: x, y, z).
* @param aPointCount is the number of points.
*/
void drawPolygon( GLdouble* aPoints, int aPointCount );
/** /**
* @brief Draws a single character using bitmap font. * @brief Draws a single character using bitmap font.
* Its main purpose is to be used in BitmapText() function. * Its main purpose is to be used in BitmapText() function.