Formatting.

This commit is contained in:
Jeff Young 2020-12-12 03:43:16 +00:00
parent 65f9212f46
commit 2c2630ef9e
10 changed files with 1486 additions and 1473 deletions

View File

@ -56,4 +56,5 @@ void BuildConvexHull( std::vector<wxPoint>& aResult, const SHAPE_POLY_SET& aPoly
*/ */
void BuildConvexHull( std::vector<wxPoint>& aResult, const SHAPE_POLY_SET& aPolygons, void BuildConvexHull( std::vector<wxPoint>& aResult, const SHAPE_POLY_SET& aPolygons,
wxPoint aPosition, double aRotation ); wxPoint aPosition, double aRotation );
#endif // __CONVEX_HULL_H #endif // __CONVEX_HULL_H

View File

@ -59,8 +59,29 @@
class POLY_GRID_PARTITION class POLY_GRID_PARTITION
{ {
private: public:
POLY_GRID_PARTITION( const SHAPE_LINE_CHAIN& aPolyOutline, int gridSize )
{
build( aPolyOutline, gridSize );
}
int ContainsPoint( const VECTOR2I& aP, int aClearance = 0 ) // const
{
if( containsPoint(aP) )
return 1;
if( aClearance > 0 )
return checkClearance ( aP, aClearance );
return 0;
}
const BOX2I& BBox() const
{
return m_bbox;
}
private:
enum HASH_FLAG enum HASH_FLAG
{ {
LEAD_EDGE = 1, LEAD_EDGE = 1,
@ -92,6 +113,111 @@ private:
} }
}; };
int containsPoint( const VECTOR2I& aP, bool debug = false ) const
{
const auto gridPoint = poly2grid( aP );
if( !m_bbox.Contains( aP ) )
return 0;
SCAN_STATE state;
const EDGE_LIST& cell = m_grid[ m_gridSize * gridPoint.y + gridPoint.x ];
scanCell( state, cell, aP, gridPoint.x, gridPoint.y );
if( state.nearest < 0 )
{
state = SCAN_STATE();
for( int d = 1; d <= m_gridSize; d++ )
{
int xl = gridPoint.x - d;
int xh = gridPoint.x + d;
if( xl >= 0 )
{
const EDGE_LIST& cell2 = m_grid[ m_gridSize * gridPoint.y + xl ];
scanCell( state, cell2, aP, xl, gridPoint.y );
if( state.nearest >= 0 )
break;
}
if( xh < m_gridSize )
{
const EDGE_LIST& cell2 = m_grid[ m_gridSize * gridPoint.y + xh ];
scanCell( state, cell2, aP, xh, gridPoint.y );
if( state.nearest >= 0 )
break;
}
}
}
#ifdef TOM_EXTRA_VERBOSE
printf("Nearest: %d prev: %d dmax %d\n", state.nearest, state.nearest_prev, state.dist_max );
#endif
if( state.nearest < 0 )
return 0;
if( state.dist_max == 0 )
return 1;
// special case for diagonal 'slits', e.g. two segments that partially overlap each other.
// Just love handling degeneracy... As I can't find any reliable way of fixing it for the moment,
// let's fall back to the good old O(N) point-in-polygon test
if( state.nearest_prev >= 0 && state.dist_max == state.dist_prev )
{
int d = std::abs( state.nearest_prev - state.nearest );
if( (d == 1) && ( (m_flags[state.nearest_prev] & m_flags[state.nearest]) == 0 ) )
{
return m_outline.PointInside( aP );
}
}
if( state.dist_max > 0 )
{
return m_flags[state.nearest] & LEAD_EDGE ? 1 : 0;
}
else
{
return m_flags[state.nearest] & TRAIL_EDGE ? 1 : 0;
}
}
bool checkClearance( const VECTOR2I& aP, int aClearance )
{
int gx0 = poly2gridX( aP.x - aClearance - 1);
int gx1 = poly2gridX( aP.x + aClearance + 1);
int gy0 = poly2gridY( aP.y - aClearance - 1);
int gy1 = poly2gridY( aP.y + aClearance + 1);
using ecoord = VECTOR2I::extended_type;
ecoord dist = (ecoord) aClearance * aClearance;
for ( int gx = gx0; gx <= gx1; gx++ )
{
for ( int gy = gy0; gy <= gy1; gy++ )
{
const auto& cell = m_grid [ m_gridSize * gy + gx];
for ( auto index : cell )
{
const auto& seg = m_outline.Segment( index );
if ( seg.SquaredDistance(aP) <= dist )
return true;
}
}
}
return false;
}
// convertes grid cell coordinates to the polygon coordinates // convertes grid cell coordinates to the polygon coordinates
const VECTOR2I grid2poly( const VECTOR2I& p ) const const VECTOR2I grid2poly( const VECTOR2I& p ) const
{ {
@ -405,136 +531,6 @@ private:
} }
} }
public:
POLY_GRID_PARTITION( const SHAPE_LINE_CHAIN& aPolyOutline, int gridSize )
{
build( aPolyOutline, gridSize );
}
int containsPoint( const VECTOR2I& aP, bool debug = false ) const
{
const auto gridPoint = poly2grid( aP );
if( !m_bbox.Contains( aP ) )
return 0;
SCAN_STATE state;
const EDGE_LIST& cell = m_grid[ m_gridSize * gridPoint.y + gridPoint.x ];
scanCell( state, cell, aP, gridPoint.x, gridPoint.y );
if( state.nearest < 0 )
{
state = SCAN_STATE();
for( int d = 1; d <= m_gridSize; d++ )
{
int xl = gridPoint.x - d;
int xh = gridPoint.x + d;
if( xl >= 0 )
{
const EDGE_LIST& cell2 = m_grid[ m_gridSize * gridPoint.y + xl ];
scanCell( state, cell2, aP, xl, gridPoint.y );
if( state.nearest >= 0 )
break;
}
if( xh < m_gridSize )
{
const EDGE_LIST& cell2 = m_grid[ m_gridSize * gridPoint.y + xh ];
scanCell( state, cell2, aP, xh, gridPoint.y );
if( state.nearest >= 0 )
break;
}
}
}
#ifdef TOM_EXTRA_VERBOSE
printf("Nearest: %d prev: %d dmax %d\n", state.nearest, state.nearest_prev, state.dist_max );
#endif
if( state.nearest < 0 )
return 0;
if( state.dist_max == 0 )
return 1;
// special case for diagonal 'slits', e.g. two segments that partially overlap each other.
// Just love handling degeneracy... As I can't find any reliable way of fixing it for the moment,
// let's fall back to the good old O(N) point-in-polygon test
if( state.nearest_prev >= 0 && state.dist_max == state.dist_prev )
{
int d = std::abs( state.nearest_prev - state.nearest );
if( (d == 1) && ( (m_flags[state.nearest_prev] & m_flags[state.nearest]) == 0 ) )
{
return m_outline.PointInside( aP );
}
}
if( state.dist_max > 0 )
{
return m_flags[state.nearest] & LEAD_EDGE ? 1 : 0;
}
else
{
return m_flags[state.nearest] & TRAIL_EDGE ? 1 : 0;
}
}
bool checkClearance( const VECTOR2I& aP, int aClearance )
{
int gx0 = poly2gridX( aP.x - aClearance - 1);
int gx1 = poly2gridX( aP.x + aClearance + 1);
int gy0 = poly2gridY( aP.y - aClearance - 1);
int gy1 = poly2gridY( aP.y + aClearance + 1);
using ecoord = VECTOR2I::extended_type;
ecoord dist = (ecoord) aClearance * aClearance;
for ( int gx = gx0; gx <= gx1; gx++ )
{
for ( int gy = gy0; gy <= gy1; gy++ )
{
const auto& cell = m_grid [ m_gridSize * gy + gx];
for ( auto index : cell )
{
const auto& seg = m_outline.Segment( index );
if ( seg.SquaredDistance(aP) <= dist )
return true;
}
}
}
return false;
}
int ContainsPoint( const VECTOR2I& aP, int aClearance = 0 ) // const
{
if( containsPoint(aP) )
return 1;
if( aClearance > 0 )
return checkClearance ( aP, aClearance );
return 0;
}
const BOX2I& BBox() const
{
return m_bbox;
}
private: private:
int m_gridSize; int m_gridSize;
SHAPE_LINE_CHAIN m_outline; SHAPE_LINE_CHAIN m_outline;

View File

@ -58,18 +58,41 @@
class PolygonTriangulation class PolygonTriangulation
{ {
public: public:
PolygonTriangulation( SHAPE_POLY_SET::TRIANGULATED_POLYGON& aResult ) : PolygonTriangulation( SHAPE_POLY_SET::TRIANGULATED_POLYGON& aResult ) :
m_result( aResult ) m_result( aResult )
{}; {};
bool TesselatePolygon( const SHAPE_LINE_CHAIN& aPoly )
{
m_bbox = aPoly.BBox();
m_result.Clear();
if( !m_bbox.GetWidth() || !m_bbox.GetHeight() )
return false;
/// Place the polygon Vertices into a circular linked list
/// and check for lists that have only 0, 1 or 2 elements and
/// therefore cannot be polygons
Vertex* firstVertex = createList( aPoly );
if( !firstVertex || firstVertex->prev == firstVertex->next )
return false;
firstVertex->updateList();
auto retval = earcutList( firstVertex );
m_vertices.clear();
return retval;
}
private: private:
struct Vertex struct Vertex
{ {
Vertex( size_t aIndex, double aX, double aY, PolygonTriangulation* aParent ) : Vertex( size_t aIndex, double aX, double aY, PolygonTriangulation* aParent ) :
i( aIndex ), x( aX ), y( aY ), parent( aParent ) i( aIndex ),
x( aX ),
y( aY ),
parent( aParent )
{ {
} }
Vertex& operator=( const Vertex& ) = delete; Vertex& operator=( const Vertex& ) = delete;
@ -136,7 +159,6 @@ private:
prevZ = NULL; prevZ = NULL;
} }
void updateOrder() void updateOrder()
{ {
if( !z ) if( !z )
@ -232,10 +254,6 @@ private:
Vertex* nextZ = nullptr; Vertex* nextZ = nullptr;
}; };
BOX2I m_bbox;
std::deque<Vertex> m_vertices;
SHAPE_POLY_SET::TRIANGULATED_POLYGON& m_result;
/** /**
* Calculate the Morton code of the Vertex * Calculate the Morton code of the Vertex
* http://www.graphics.stanford.edu/~seander/bithacks.html#InterleaveBMN * http://www.graphics.stanford.edu/~seander/bithacks.html#InterleaveBMN
@ -653,30 +671,10 @@ private:
return p; return p;
} }
private:
public: BOX2I m_bbox;
std::deque<Vertex> m_vertices;
bool TesselatePolygon( const SHAPE_LINE_CHAIN& aPoly ) SHAPE_POLY_SET::TRIANGULATED_POLYGON& m_result;
{
m_bbox = aPoly.BBox();
m_result.Clear();
if( !m_bbox.GetWidth() || !m_bbox.GetHeight() )
return false;
/// Place the polygon Vertices into a circular linked list
/// and check for lists that have only 0, 1 or 2 elements and
/// therefore cannot be polygons
Vertex* firstVertex = createList( aPoly );
if( !firstVertex || firstVertex->prev == firstVertex->next )
return false;
firstVertex->updateList();
auto retval = earcutList( firstVertex );
m_vertices.clear();
return retval;
}
}; };
#endif //__POLYGON_TRIANGULATION_H #endif //__POLYGON_TRIANGULATION_H

View File

@ -60,8 +60,8 @@ public:
* Creates a segment between (aX1, aY1) and (aX2, aY2) * Creates a segment between (aX1, aY1) and (aX2, aY2)
*/ */
SEG( int aX1, int aY1, int aX2, int aY2 ) : SEG( int aX1, int aY1, int aX2, int aY2 ) :
A ( VECTOR2I( aX1, aY1 ) ), A( VECTOR2I( aX1, aY1 ) ),
B ( VECTOR2I( aX2, aY2 ) ) B( VECTOR2I( aX2, aY2 ) )
{ {
m_index = -1; m_index = -1;
} }
@ -70,7 +70,9 @@ public:
* Constructor * Constructor
* Creates a segment between (aA) and (aB) * Creates a segment between (aA) and (aB)
*/ */
SEG( const VECTOR2I& aA, const VECTOR2I& aB ) : A( aA ), B( aB ) SEG( const VECTOR2I& aA, const VECTOR2I& aB ) :
A( aA ),
B( aB )
{ {
m_index = -1; m_index = -1;
} }
@ -82,7 +84,9 @@ public:
* @param aB reference to the end point in the parent shape * @param aB reference to the end point in the parent shape
* @param aIndex index of the segment within the parent shape * @param aIndex index of the segment within the parent shape
*/ */
SEG( const VECTOR2I& aA, const VECTOR2I& aB, int aIndex ) : A( aA ), B( aB ) SEG( const VECTOR2I& aA, const VECTOR2I& aB, int aIndex ) :
A( aA ),
B( aB )
{ {
m_index = aIndex; m_index = aIndex;
} }
@ -90,7 +94,10 @@ public:
/** /**
* Copy constructor * Copy constructor
*/ */
SEG( const SEG& aSeg ) : A( aSeg.A ), B( aSeg.B ), m_index( aSeg.m_index ) SEG( const SEG& aSeg ) :
A( aSeg.A ),
B( aSeg.B ),
m_index( aSeg.m_index )
{ {
} }
@ -289,6 +296,7 @@ public:
if( Contains( aSeg.A ) || Contains( aSeg.B ) ) if( Contains( aSeg.A ) || Contains( aSeg.B ) )
return true; return true;
if( aSeg.Contains( A ) || aSeg.Contains( B ) ) if( aSeg.Contains( A ) || aSeg.Contains( B ) )
return true; return true;
@ -355,6 +363,7 @@ public:
private: private:
bool ccw( const VECTOR2I& aA, const VECTOR2I& aB, const VECTOR2I &aC ) const; bool ccw( const VECTOR2I& aA, const VECTOR2I& aB, const VECTOR2I &aC ) const;
private:
///> index withing the parent shape (used when m_is_local == false) ///> index withing the parent shape (used when m_is_local == false)
int m_index; int m_index;
}; };

View File

@ -82,7 +82,8 @@ public:
* Creates an empty shape of type aType * Creates an empty shape of type aType
*/ */
SHAPE_BASE( SHAPE_TYPE aType ) : m_type( aType ) SHAPE_BASE( SHAPE_TYPE aType ) :
m_type( aType )
{} {}
// Destructor // Destructor
@ -121,24 +122,20 @@ protected:
*/ */
class SHAPE : public SHAPE_BASE class SHAPE : public SHAPE_BASE
{ {
protected:
typedef VECTOR2I::extended_type ecoord;
public: public:
/** /**
* Constructor * Constructor
* *
* Creates an empty shape of type aType * Creates an empty shape of type aType
*/ */
SHAPE( SHAPE_TYPE aType ) :
SHAPE( SHAPE_TYPE aType ) : SHAPE_BASE( aType ) SHAPE_BASE( aType )
{} {}
// Destructor // Destructor
virtual ~SHAPE() virtual ~SHAPE()
{} {}
/** /**
* Function Clone() * Function Clone()
* *
@ -173,8 +170,8 @@ public:
* event of a collision. * event of a collision.
* @return true, if there is a collision. * @return true, if there is a collision.
*/ */
virtual bool Collide( const VECTOR2I& aP, int aClearance = 0, virtual bool Collide( const VECTOR2I& aP, int aClearance = 0, int* aActual = nullptr,
int* aActual = nullptr, VECTOR2I* aLocation = nullptr ) const VECTOR2I* aLocation = nullptr ) const
{ {
return Collide( SEG( aP, aP ), aClearance, aActual, aLocation ); return Collide( SEG( aP, aP ), aClearance, aActual, aLocation );
} }
@ -248,13 +245,17 @@ public:
virtual bool Parse( std::stringstream& aStream ); virtual bool Parse( std::stringstream& aStream );
virtual const std::string Format( ) const; virtual const std::string Format( ) const;
protected:
typedef VECTOR2I::extended_type ecoord;
}; };
class SHAPE_LINE_CHAIN_BASE : public SHAPE class SHAPE_LINE_CHAIN_BASE : public SHAPE
{ {
public: public:
SHAPE_LINE_CHAIN_BASE( SHAPE_TYPE aType ) : SHAPE( aType ) SHAPE_LINE_CHAIN_BASE( SHAPE_TYPE aType ) :
SHAPE( aType )
{ {
} }
@ -273,8 +274,8 @@ public:
* of a collision. * of a collision.
* @return true, when a collision has been found * @return true, when a collision has been found
*/ */
virtual bool Collide( const VECTOR2I& aP, int aClearance = 0, virtual bool Collide( const VECTOR2I& aP, int aClearance = 0, int* aActual = nullptr,
int* aActual = nullptr, VECTOR2I* aLocation = nullptr ) const override; VECTOR2I* aLocation = nullptr ) const override;
/** /**
* Function Collide() * Function Collide()
@ -287,8 +288,8 @@ public:
* @return true, when a collision has been found * @return true, when a collision has been found
*/ */
virtual bool Collide( const SEG& aSeg, int aClearance = 0, virtual bool Collide( const SEG& aSeg, int aClearance = 0, int* aActual = nullptr,
int* aActual = nullptr, VECTOR2I* aLocation = nullptr ) const override; VECTOR2I* aLocation = nullptr ) const override;
SEG::ecoord SquaredDistance( const VECTOR2I& aP, bool aOutlineOnly = false ) const; SEG::ecoord SquaredDistance( const VECTOR2I& aP, bool aOutlineOnly = false ) const;

View File

@ -41,7 +41,9 @@ public:
static const int MIN_PRECISION_IU = 4; static const int MIN_PRECISION_IU = 4;
SHAPE_ARC() : SHAPE_ARC() :
SHAPE( SH_ARC ), m_width( 0 ) {}; SHAPE( SH_ARC ),
m_width( 0 )
{};
/** /**
* SHAPE_ARC ctor. * SHAPE_ARC ctor.
@ -50,8 +52,8 @@ public:
* @param aCenterAngle is the arc angle in degrees * @param aCenterAngle is the arc angle in degrees
* @param aWidth is the arc line thickness * @param aWidth is the arc line thickness
*/ */
SHAPE_ARC( const VECTOR2I& aArcCenter, const VECTOR2I& aArcStartPoint, SHAPE_ARC( const VECTOR2I& aArcCenter, const VECTOR2I& aArcStartPoint, double aCenterAngle,
double aCenterAngle, int aWidth = 0 ); int aWidth = 0 );
/** /**
* SHAPE_ARC ctor. * SHAPE_ARC ctor.
@ -60,8 +62,8 @@ public:
* @param aArcMid is the arc mid point * @param aArcMid is the arc mid point
* @param aWidth is the arc line thickness * @param aWidth is the arc line thickness
*/ */
SHAPE_ARC( const VECTOR2I& aArcStart, const VECTOR2I& aArcMid, SHAPE_ARC( const VECTOR2I& aArcStart, const VECTOR2I& aArcMid, const VECTOR2I& aArcEnd,
const VECTOR2I& aArcEnd, int aWidth ); int aWidth );
/** /**
* SHAPE_ARC ctor. * SHAPE_ARC ctor.
@ -145,7 +147,6 @@ public:
const SHAPE_LINE_CHAIN ConvertToPolyline( double aAccuracy = 0.005 * PCB_IU_PER_MM ) const; const SHAPE_LINE_CHAIN ConvertToPolyline( double aAccuracy = 0.005 * PCB_IU_PER_MM ) const;
private: private:
bool ccw( const VECTOR2I& aA, const VECTOR2I& aB, const VECTOR2I& aC ) const bool ccw( const VECTOR2I& aA, const VECTOR2I& aB, const VECTOR2I& aC ) const
{ {
return ( ecoord{ aC.y } - aA.y ) * ( ecoord{ aB.x } - aA.x ) > return ( ecoord{ aC.y } - aA.y ) * ( ecoord{ aB.x } - aA.x ) >
@ -154,7 +155,7 @@ private:
void update_bbox(); void update_bbox();
private:
VECTOR2I m_start; VECTOR2I m_start;
VECTOR2I m_mid; VECTOR2I m_mid;
VECTOR2I m_end; VECTOR2I m_end;

View File

@ -35,11 +35,14 @@ class SHAPE_CIRCLE : public SHAPE
{ {
public: public:
SHAPE_CIRCLE() : SHAPE_CIRCLE() :
SHAPE( SH_CIRCLE ), m_radius( 0 ) SHAPE( SH_CIRCLE ),
m_radius( 0 )
{} {}
SHAPE_CIRCLE( const VECTOR2I& aCenter, int aRadius ) : SHAPE_CIRCLE( const VECTOR2I& aCenter, int aRadius ) :
SHAPE( SH_CIRCLE ), m_radius( aRadius ), m_center( aCenter ) SHAPE( SH_CIRCLE ),
m_radius( aRadius ),
m_center( aCenter )
{} {}
SHAPE_CIRCLE( const SHAPE_CIRCLE& aOther ) : SHAPE_CIRCLE( const SHAPE_CIRCLE& aOther ) :
@ -122,6 +125,7 @@ public:
{ {
return true; return true;
} }
private: private:
int m_radius; int m_radius;
VECTOR2I m_center; VECTOR2I m_center;

View File

@ -63,7 +63,7 @@
*/ */
class SHAPE_POLY_SET : public SHAPE class SHAPE_POLY_SET : public SHAPE
{ {
public: public:
///> represents a single polygon outline with holes. The first entry is the outline, ///> represents a single polygon outline with holes. The first entry is the outline,
///> the remaining (if any), are the holes ///> the remaining (if any), are the holes
///> N.B. SWIG only supports typedef, so avoid c++ 'using' keyword ///> N.B. SWIG only supports typedef, so avoid c++ 'using' keyword
@ -76,7 +76,10 @@ class SHAPE_POLY_SET : public SHAPE
{ {
TRI( int _a = 0, int _b = 0, int _c = 0, TRIANGULATED_POLYGON* aParent = nullptr ) : TRI( int _a = 0, int _b = 0, int _c = 0, TRIANGULATED_POLYGON* aParent = nullptr ) :
SHAPE_LINE_CHAIN_BASE( SH_POLY_SET_TRIANGLE ), SHAPE_LINE_CHAIN_BASE( SH_POLY_SET_TRIANGLE ),
a( _a ), b( _b ), c( _c ), parent( aParent ) a( _a ),
b( _b ),
c( _c ),
parent( aParent )
{ {
} }
@ -171,7 +174,6 @@ class SHAPE_POLY_SET : public SHAPE
} }
private: private:
std::deque<TRI> m_triangles; std::deque<TRI> m_triangles;
std::deque<VECTOR2I> m_vertices; std::deque<VECTOR2I> m_vertices;
}; };
@ -189,7 +191,10 @@ class SHAPE_POLY_SET : public SHAPE
int m_contour; /*!< m_contour is the index of the contour relative to the polygon. */ int m_contour; /*!< m_contour is the index of the contour relative to the polygon. */
int m_vertex; /*!< m_vertex is the index of the vertex relative to the contour. */ int m_vertex; /*!< m_vertex is the index of the vertex relative to the contour. */
VERTEX_INDEX() : m_polygon(-1), m_contour(-1), m_vertex(-1) VERTEX_INDEX() :
m_polygon(-1),
m_contour(-1),
m_vertex(-1)
{ {
} }
} VERTEX_INDEX; } VERTEX_INDEX;
@ -291,8 +296,7 @@ class SHAPE_POLY_SET : public SHAPE
const T& Get() const T& Get()
{ {
return m_poly->Polygon( m_currentPolygon )[m_currentContour].CPoint( return m_poly->Polygon( m_currentPolygon )[m_currentContour].CPoint( m_currentVertex );
m_currentVertex );
} }
const T& operator*() const T& operator*()
@ -320,7 +324,6 @@ class SHAPE_POLY_SET : public SHAPE
return index; return index;
} }
private: private:
friend class SHAPE_POLY_SET; friend class SHAPE_POLY_SET;
@ -504,6 +507,19 @@ class SHAPE_POLY_SET : public SHAPE
~SHAPE_POLY_SET(); ~SHAPE_POLY_SET();
SHAPE_POLY_SET& operator=( const SHAPE_POLY_SET& );
void CacheTriangulation( bool aPartition = true );
bool IsTriangulationUpToDate() const;
MD5_HASH GetHash() const;
virtual bool HasIndexableSubshapes() const override;
virtual size_t GetIndexableSubshapeCount() const override;
virtual void GetIndexableSubshapes( std::vector<SHAPE*>& aSubshapes ) override;
/** /**
* Function GetRelativeIndices * Function GetRelativeIndices
* *
@ -1307,7 +1323,7 @@ class SHAPE_POLY_SET : public SHAPE
*/ */
bool IsVertexInHole( int aGlobalIdx ); bool IsVertexInHole( int aGlobalIdx );
private: private:
void fractureSingle( POLYGON& paths ); void fractureSingle( POLYGON& paths );
void unfractureSingle ( POLYGON& path ); void unfractureSingle ( POLYGON& path );
void importTree( ClipperLib::PolyTree* tree ); void importTree( ClipperLib::PolyTree* tree );
@ -1378,33 +1394,17 @@ class SHAPE_POLY_SET : public SHAPE
///> Returns true if the polygon set has any holes that touch share a vertex. ///> Returns true if the polygon set has any holes that touch share a vertex.
bool hasTouchingHoles( const POLYGON& aPoly ) const; bool hasTouchingHoles( const POLYGON& aPoly ) const;
MD5_HASH checksum() const;
private:
typedef std::vector<POLYGON> POLYSET; typedef std::vector<POLYGON> POLYSET;
POLYSET m_polys; POLYSET m_polys;
public:
SHAPE_POLY_SET& operator=( const SHAPE_POLY_SET& );
void CacheTriangulation( bool aPartition = true );
bool IsTriangulationUpToDate() const;
MD5_HASH GetHash() const;
virtual bool HasIndexableSubshapes() const override;
virtual size_t GetIndexableSubshapeCount() const override;
virtual void GetIndexableSubshapes( std::vector<SHAPE*>& aSubshapes ) override;
private:
MD5_HASH checksum() const;
std::vector<std::unique_ptr<TRIANGULATED_POLYGON>> m_triangulatedPolys; std::vector<std::unique_ptr<TRIANGULATED_POLYGON>> m_triangulatedPolys;
bool m_triangulationValid = false; bool m_triangulationValid = false;
MD5_HASH m_hash; MD5_HASH m_hash;
}; };
#endif #endif

View File

@ -39,7 +39,9 @@ public:
* Creates an empty (0-sized) rectangle * Creates an empty (0-sized) rectangle
*/ */
SHAPE_RECT() : SHAPE_RECT() :
SHAPE( SH_RECT ), m_w( 0 ), m_h( 0 ) SHAPE( SH_RECT ),
m_w( 0 ),
m_h( 0 )
{} {}
/** /**
@ -47,7 +49,10 @@ public:
* Creates a rectangle defined by top-left corner (aX0, aY0), width aW and height aH. * Creates a rectangle defined by top-left corner (aX0, aY0), width aW and height aH.
*/ */
SHAPE_RECT( int aX0, int aY0, int aW, int aH ) : SHAPE_RECT( int aX0, int aY0, int aW, int aH ) :
SHAPE( SH_RECT ), m_p0( aX0, aY0 ), m_w( aW ), m_h( aH ) SHAPE( SH_RECT ),
m_p0( aX0, aY0 ),
m_w( aW ),
m_h( aH )
{} {}
/** /**
@ -55,7 +60,10 @@ public:
* Creates a rectangle defined by top-left corner aP0, width aW and height aH. * Creates a rectangle defined by top-left corner aP0, width aW and height aH.
*/ */
SHAPE_RECT( const VECTOR2I& aP0, int aW, int aH ) : SHAPE_RECT( const VECTOR2I& aP0, int aW, int aH ) :
SHAPE( SH_RECT ), m_p0( aP0 ), m_w( aW ), m_h( aH ) SHAPE( SH_RECT ),
m_p0( aP0 ),
m_w( aW ),
m_h( aH )
{} {}
SHAPE_RECT( const SHAPE_RECT& aOther ) : SHAPE_RECT( const SHAPE_RECT& aOther ) :
@ -188,14 +196,9 @@ public:
virtual const std::string Format( ) const override; virtual const std::string Format( ) const override;
private: private:
///> Top-left corner VECTOR2I m_p0; ///> Top-left corner
VECTOR2I m_p0; int m_w; ///> Width
int m_h; ///> Height
///> Width
int m_w;
///> Height
int m_h;
}; };
#endif // __SHAPE_RECT_H #endif // __SHAPE_RECT_H