Protect TesselatePolygon() against degenerated polygons (less than 3 corners) to avoid crashes.

Use TesselatePolygon() to draw polygons in Gerbview instead of GLU tesselation, much slower.
Add helper methods in GAL to know if the current GAL engine is Cairo, OpenGL or something else,
useful to optimize drawing code.
This commit is contained in:
jean-pierre charras 2018-12-18 12:49:14 +01:00
parent 7f5503a783
commit 388397f97d
7 changed files with 32 additions and 8 deletions

View File

@ -1872,6 +1872,9 @@ void SHAPE_POLY_SET::CacheTriangulation()
for( int i = 0; i < tmpSet.OutlineCount(); i++ )
{
if( tmpSet.Outline( i ).PointCount() < 3 ) // malformed polygon
continue;
m_triangulatedPolys.push_back( std::make_unique<TRIANGULATED_POLYGON>() );
PolygonTriangulation tess( *m_triangulatedPolys.back() );

View File

@ -260,10 +260,20 @@ void GERBVIEW_PAINTER::draw( /*const*/ GERBER_DRAW_ITEM* aItem, int aLayer )
for( auto it = absolutePolygon.Iterate( 0 ); it; ++it )
*it = aItem->GetABPosition( *it );
if( !isFilled )
// Degenerated polygons (having < 3 points) are drawn as lines
// to avoid issues in draw polygon functions
if( !isFilled || absolutePolygon.COutline( 0 ).PointCount() < 3 )
m_gal->DrawPolyline( absolutePolygon.COutline( 0 ) );
else
{
// On Opengl, a not convex filled polygon is usually drawn by using triangles as primitives.
// CacheTriangulation() can create basic triangle primitives to draw the polygon solid shape
// on Opengl
if( m_gal->IsOpenGlEngine() )
absolutePolygon.CacheTriangulation();
m_gal->DrawPolygon( absolutePolygon );
}
break;
}

View File

@ -72,6 +72,8 @@ public:
virtual ~CAIRO_GAL_BASE();
virtual bool IsCairoEngine() override { return true; }
// ---------------
// Drawing methods
// ---------------

View File

@ -75,6 +75,12 @@ public:
/// @brief Returns true if the GAL canvas is visible on the screen.
virtual bool IsVisible() const { return true; }
/// @brief Returns true if the GAL engine is a cairo based type.
virtual bool IsCairoEngine() { return false; }
/// @brief Returns true if the GAL engine is a opengl based type.
virtual bool IsOpenGlEngine() { return false; }
// ---------------
// Drawing methods
// ---------------

View File

@ -86,6 +86,8 @@ public:
virtual ~OPENGL_GAL();
virtual bool IsOpenGlEngine() override { return true; }
/// @copydoc GAL::IsInitialized()
virtual bool IsInitialized() const override
{

View File

@ -650,6 +650,10 @@ public:
bool TesselatePolygon( const SHAPE_LINE_CHAIN& aPoly )
{
ClipperLib::Clipper c;
if( aPoly.PointCount() < 3 ) // Malformed polygon
return false;
m_bbox = aPoly.BBox();
m_result.Clear();

View File

@ -974,13 +974,10 @@ void PCB_PAINTER::draw( const DRAWSEGMENT* aSegment, int aLayer )
break;
// On Opengl, a not convex filled polygon is usually drawn by using triangles as primitives.
// Although CacheTriangulation() can create basic triangle primitives
// to draw the polygon solid shape on Opengl, it is not used because it does not work fine
// with any polygon. It must be a simple polygon.
// And unfortunately, calling shape.Simplify( PM_FAST) is very slow.
// So for now we just use GLU tesselation (much slower, but works with any polygon)
// This section is left until a better way is found
if( !shape.IsTriangulationUpToDate() )
// CacheTriangulation() can create basic triangle primitives to draw the polygon solid shape
// on Opengl.
// GLU tesselation is much slower, so currently we are using our tesselation.
if( m_gal->IsOpenGlEngine() && !shape.IsTriangulationUpToDate() )
{
shape.CacheTriangulation();
}