Polygon boolean operations on SHAPE_POLY_SET: Add a parameter (aFastMode) to speed up calculations. By default, the transforms use an option to create stricly simple polygons.
In 3D viewer, this option can take a *very long* calculation time (minutes instead of seconds, or hangs) and they are now using aFastMode = true to do polygon calculations, especially for zones inside zones belong to the same net but having different priority (which creates weak polygons). aFastMode = false is the default for other calculations (zone filling) as before.
This commit is contained in:
parent
cc2fe47c95
commit
c63f6aa3c5
|
@ -61,6 +61,7 @@
|
|||
#include <reporter.h>
|
||||
|
||||
|
||||
extern bool useFastModeForPolygons;
|
||||
|
||||
/* returns the Z orientation parameter 1.0 or -1.0 for aLayer
|
||||
* Z orientation is 1.0 for all layers but "back" layers:
|
||||
|
@ -702,7 +703,7 @@ void EDA_3D_CANVAS::buildBoard3DAuxLayers( REPORTER* aErrorMessages, REPORTER* a
|
|||
if( bufferPolys.IsEmpty() )
|
||||
continue;
|
||||
|
||||
bufferPolys.Fracture();
|
||||
bufferPolys.Simplify( useFastModeForPolygons );
|
||||
|
||||
int thickness = GetPrm3DVisu().GetLayerObjectThicknessBIU( layer );
|
||||
int zpos = GetPrm3DVisu().GetLayerZcoordBIU( layer );
|
||||
|
|
|
@ -63,6 +63,15 @@
|
|||
#include <CImage.h>
|
||||
#include <reporter.h>
|
||||
|
||||
// An option for all operations on polygons:
|
||||
// when useFastModeForPolygons = true, calculations can be *a lot* faster.
|
||||
// but created polygons can be not stricty simple (can share edges)
|
||||
// Although stricty simple are better for glu tesselation functions, I do not see
|
||||
// any issue when allowing not stricty simple polygons.
|
||||
// But I see *very* long calculations when setting useFastMode to false.
|
||||
// So, be careful if changing thie option
|
||||
bool useFastModeForPolygons = true;
|
||||
|
||||
/* returns the Z orientation parameter 1.0 or -1.0 for aLayer
|
||||
* Z orientation is 1.0 for all layers but "back" layers:
|
||||
* B_Cu , B_Adhes, B_Paste ), B_SilkS
|
||||
|
@ -139,7 +148,7 @@ void EDA_3D_CANVAS::buildBoardThroughHolesPolygonList( SHAPE_POLY_SET& allBoardH
|
|||
}
|
||||
}
|
||||
|
||||
allBoardHoles.Simplify();
|
||||
allBoardHoles.Simplify( useFastModeForPolygons );
|
||||
}
|
||||
|
||||
|
||||
|
@ -314,11 +323,11 @@ void EDA_3D_CANVAS::buildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList,
|
|||
if( currLayerHoles.OutlineCount() )
|
||||
{
|
||||
currLayerHoles.Append(allLayerHoles);
|
||||
currLayerHoles.Simplify();
|
||||
bufferPolys.BooleanSubtract( currLayerHoles );
|
||||
currLayerHoles.Simplify( useFastModeForPolygons );
|
||||
bufferPolys.BooleanSubtract( currLayerHoles, useFastModeForPolygons );
|
||||
}
|
||||
else
|
||||
bufferPolys.BooleanSubtract( allLayerHoles );
|
||||
bufferPolys.BooleanSubtract( allLayerHoles, useFastModeForPolygons );
|
||||
|
||||
int thickness = GetPrm3DVisu().GetLayerObjectThicknessBIU( layer );
|
||||
int zpos = GetPrm3DVisu().GetLayerZcoordBIU( layer );
|
||||
|
@ -414,7 +423,7 @@ void EDA_3D_CANVAS::buildBoard3DView( GLuint aBoardList, GLuint aBodyOnlyList,
|
|||
zpos += (copper_thickness + epsilon) / 2.0f;
|
||||
board_thickness -= copper_thickness + epsilon;
|
||||
|
||||
bufferPcbOutlines.BooleanSubtract( allLayerHoles );
|
||||
bufferPcbOutlines.BooleanSubtract( allLayerHoles, useFastModeForPolygons );
|
||||
|
||||
if( !bufferPcbOutlines.IsEmpty() )
|
||||
{
|
||||
|
@ -574,15 +583,15 @@ void EDA_3D_CANVAS::buildTechLayers3DView( REPORTER* aErrorMessages, REPORTER* a
|
|||
bufferPolys = bufferPcbOutlines;
|
||||
|
||||
cuts.Append(allLayerHoles);
|
||||
cuts.Simplify();
|
||||
cuts.Simplify( useFastModeForPolygons );
|
||||
|
||||
bufferPolys.BooleanSubtract( cuts );
|
||||
bufferPolys.BooleanSubtract( cuts, useFastModeForPolygons );
|
||||
}
|
||||
// Remove holes from Solder paste layers and silkscreen
|
||||
else if( layer == B_Paste || layer == F_Paste
|
||||
|| layer == B_SilkS || layer == F_SilkS )
|
||||
{
|
||||
bufferPolys.BooleanSubtract( allLayerHoles );
|
||||
bufferPolys.BooleanSubtract( allLayerHoles, useFastModeForPolygons );
|
||||
}
|
||||
|
||||
int thickness = 0;
|
||||
|
|
|
@ -208,11 +208,13 @@ const SHAPE_LINE_CHAIN SHAPE_POLY_SET::convertFromClipper( const Path& aPath )
|
|||
|
||||
#include <common.h>
|
||||
#include <wx/wx.h>
|
||||
void SHAPE_POLY_SET::booleanOp( ClipType type, const SHAPE_POLY_SET& b )
|
||||
void SHAPE_POLY_SET::booleanOp( ClipType aType, const SHAPE_POLY_SET& aOtherShape,
|
||||
bool aFastMode )
|
||||
{
|
||||
Clipper c;
|
||||
|
||||
c.StrictlySimple( true );
|
||||
if( !aFastMode )
|
||||
c.StrictlySimple( true );
|
||||
|
||||
BOOST_FOREACH( const POLYGON& poly, m_polys )
|
||||
{
|
||||
|
@ -220,7 +222,7 @@ void SHAPE_POLY_SET::booleanOp( ClipType type, const SHAPE_POLY_SET& b )
|
|||
c.AddPath( convertToClipper( poly[i], i > 0 ? false : true ), ptSubject, true );
|
||||
}
|
||||
|
||||
BOOST_FOREACH( const POLYGON& poly, b.m_polys )
|
||||
BOOST_FOREACH( const POLYGON& poly, aOtherShape.m_polys )
|
||||
{
|
||||
for( unsigned int i = 0; i < poly.size(); i++ )
|
||||
c.AddPath( convertToClipper( poly[i], i > 0 ? false : true ), ptClip, true );
|
||||
|
@ -228,21 +230,21 @@ void SHAPE_POLY_SET::booleanOp( ClipType type, const SHAPE_POLY_SET& b )
|
|||
|
||||
PolyTree solution;
|
||||
|
||||
c.Execute( type, solution, pftNonZero, pftNonZero );
|
||||
c.Execute( aType, solution, pftNonZero, pftNonZero );
|
||||
|
||||
importTree( &solution );
|
||||
}
|
||||
|
||||
|
||||
void SHAPE_POLY_SET::BooleanAdd( const SHAPE_POLY_SET& b )
|
||||
void SHAPE_POLY_SET::BooleanAdd( const SHAPE_POLY_SET& b, bool aFastMode )
|
||||
{
|
||||
booleanOp( ctUnion, b );
|
||||
booleanOp( ctUnion, b, aFastMode );
|
||||
}
|
||||
|
||||
|
||||
void SHAPE_POLY_SET::BooleanSubtract( const SHAPE_POLY_SET& b )
|
||||
void SHAPE_POLY_SET::BooleanSubtract( const SHAPE_POLY_SET& b, bool aFastMode )
|
||||
{
|
||||
booleanOp( ctDifference, b );
|
||||
booleanOp( ctDifference, b, aFastMode );
|
||||
}
|
||||
|
||||
|
||||
|
@ -496,9 +498,9 @@ void SHAPE_POLY_SET::fractureSingle( POLYGON& paths )
|
|||
}
|
||||
|
||||
|
||||
void SHAPE_POLY_SET::Fracture()
|
||||
void SHAPE_POLY_SET::Fracture( bool aFastMode )
|
||||
{
|
||||
Simplify(); // remove overlapping holes/degeneracy
|
||||
Simplify( aFastMode ); // remove overlapping holes/degeneracy
|
||||
|
||||
BOOST_FOREACH( POLYGON& paths, m_polys )
|
||||
{
|
||||
|
@ -507,11 +509,11 @@ void SHAPE_POLY_SET::Fracture()
|
|||
}
|
||||
|
||||
|
||||
void SHAPE_POLY_SET::Simplify()
|
||||
void SHAPE_POLY_SET::Simplify( bool aFastMode )
|
||||
{
|
||||
SHAPE_POLY_SET empty;
|
||||
|
||||
booleanOp( ctUnion, empty );
|
||||
booleanOp( ctUnion, empty, aFastMode );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -54,68 +54,69 @@ class SHAPE_POLY_SET : public SHAPE
|
|||
* Base class for iterating over all vertices in a given SHAPE_POLY_SET
|
||||
*/
|
||||
template <class T>
|
||||
class ITERATOR_TEMPLATE {
|
||||
public:
|
||||
class ITERATOR_TEMPLATE
|
||||
{
|
||||
public:
|
||||
|
||||
bool IsEndContour() const
|
||||
bool IsEndContour() const
|
||||
{
|
||||
return m_currentVertex + 1 == m_poly->CPolygon( m_currentOutline )[0].PointCount();
|
||||
}
|
||||
|
||||
bool IsLastContour() const
|
||||
{
|
||||
return m_currentOutline == m_lastOutline;
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return m_currentOutline <= m_lastOutline;
|
||||
}
|
||||
|
||||
void Advance()
|
||||
{
|
||||
m_currentVertex ++;
|
||||
|
||||
if( m_currentVertex >= m_poly->CPolygon( m_currentOutline )[0].PointCount() )
|
||||
{
|
||||
return m_currentVertex + 1 == m_poly->CPolygon( m_currentOutline )[0].PointCount();
|
||||
m_currentVertex = 0;
|
||||
m_currentOutline++;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsLastContour() const
|
||||
{
|
||||
return m_currentOutline == m_lastOutline;
|
||||
}
|
||||
void operator++( int dummy )
|
||||
{
|
||||
Advance();
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return m_currentOutline <= m_lastOutline;
|
||||
}
|
||||
void operator++()
|
||||
{
|
||||
Advance();
|
||||
}
|
||||
|
||||
void Advance()
|
||||
{
|
||||
m_currentVertex ++;
|
||||
T& Get()
|
||||
{
|
||||
return m_poly->Polygon( m_currentOutline )[0].Point( m_currentVertex );
|
||||
}
|
||||
|
||||
if( m_currentVertex >= m_poly->CPolygon( m_currentOutline )[0].PointCount() )
|
||||
{
|
||||
m_currentVertex = 0;
|
||||
m_currentOutline++;
|
||||
}
|
||||
}
|
||||
T& operator*()
|
||||
{
|
||||
return Get();
|
||||
}
|
||||
|
||||
void operator++( int dummy )
|
||||
{
|
||||
Advance();
|
||||
}
|
||||
|
||||
void operator++()
|
||||
{
|
||||
Advance();
|
||||
}
|
||||
|
||||
T& Get()
|
||||
{
|
||||
return m_poly->Polygon( m_currentOutline )[0].Point( m_currentVertex );
|
||||
}
|
||||
|
||||
T& operator*()
|
||||
{
|
||||
return Get();
|
||||
}
|
||||
|
||||
T* operator->()
|
||||
{
|
||||
return &Get();
|
||||
}
|
||||
T* operator->()
|
||||
{
|
||||
return &Get();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
friend class SHAPE_POLY_SET;
|
||||
private:
|
||||
friend class SHAPE_POLY_SET;
|
||||
|
||||
SHAPE_POLY_SET* m_poly;
|
||||
int m_currentOutline;
|
||||
int m_lastOutline;
|
||||
int m_currentVertex;
|
||||
SHAPE_POLY_SET* m_poly;
|
||||
int m_currentOutline;
|
||||
int m_lastOutline;
|
||||
int m_currentVertex;
|
||||
};
|
||||
|
||||
typedef ITERATOR_TEMPLATE<VECTOR2I> ITERATOR;
|
||||
|
@ -245,17 +246,21 @@ class SHAPE_POLY_SET : public SHAPE
|
|||
|
||||
|
||||
///> Performs boolean polyset union
|
||||
void BooleanAdd( const SHAPE_POLY_SET& b );
|
||||
///> For aFastMode meaning, see function booleanOp
|
||||
|
||||
void BooleanAdd( const SHAPE_POLY_SET& b, bool aFastMode = false );
|
||||
|
||||
///> Performs boolean polyset difference
|
||||
void BooleanSubtract( const SHAPE_POLY_SET& b );
|
||||
///> For aFastMode meaning, see function booleanOp
|
||||
void BooleanSubtract( const SHAPE_POLY_SET& b, bool aFastMode = false );
|
||||
|
||||
///> Performs outline inflation/deflation, using round corners.
|
||||
void Inflate( int aFactor, int aCircleSegmentsCount );
|
||||
|
||||
///> Converts a set of polygons with holes to a singe outline with "slits"/"fractures" connecting the outer ring
|
||||
///> to the inner holes
|
||||
void Fracture();
|
||||
///> For aFastMode meaning, see function booleanOp
|
||||
void Fracture( bool aFastMode = false);
|
||||
|
||||
///> Converts a set of slitted polygons to a set of polygons with holes
|
||||
void Unfracture();
|
||||
|
@ -264,7 +269,8 @@ class SHAPE_POLY_SET : public SHAPE
|
|||
bool HasHoles() const;
|
||||
|
||||
///> Simplifies the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
|
||||
void Simplify();
|
||||
///> For aFastMode meaning, see function booleanOp
|
||||
void Simplify( bool aFastMode = false);
|
||||
|
||||
/// @copydoc SHAPE::Format()
|
||||
const std::string Format() const;
|
||||
|
@ -316,7 +322,20 @@ class SHAPE_POLY_SET : public SHAPE
|
|||
|
||||
void fractureSingle( POLYGON& paths );
|
||||
void importTree( ClipperLib::PolyTree* tree );
|
||||
void booleanOp( ClipperLib::ClipType type, const SHAPE_POLY_SET& b );
|
||||
|
||||
/** Function booleanOp
|
||||
* this is the engine to execute all polygon boolean transforms
|
||||
* (AND, OR, ... and polygon simplification (merging overlaping polygons)
|
||||
* @param aType is the transform type ( see ClipperLib::ClipType )
|
||||
* @param aOtherShape is the SHAPE_LINE_CHAIN to combine with me.
|
||||
* @param aFastMode is an option to choos if the result is a weak polygon
|
||||
* or a stricty simple polygon.
|
||||
* if aFastMode is true (default) the result can be a weak polygon
|
||||
* if aFastMode is true (default) the result is (theorically) a strictly
|
||||
* simple polygon, but calculations can be really significantly time consuming
|
||||
*/
|
||||
void booleanOp( ClipperLib::ClipType aType,
|
||||
const SHAPE_POLY_SET& aOtherShape, bool aFastMode = false );
|
||||
|
||||
bool pointInPolygon( const VECTOR2I& aP, const SHAPE_LINE_CHAIN& aPath ) const;
|
||||
|
||||
|
|
Loading…
Reference in New Issue