46#ifndef __POLYGON_TRIANGULATION_H
47#define __POLYGON_TRIANGULATION_H
64#if defined( __MINGW32__ )
65 #define TRIANGULATESIMPLIFICATIONLEVEL 50
66 #define TRIANGULATEMINIMUMAREA 1000
68 #define TRIANGULATESIMPLIFICATIONLEVEL ADVANCED_CFG::GetCfg().m_TriangulateSimplificationLevel
69 #define TRIANGULATEMINIMUMAREA ADVANCED_CFG::GetCfg().m_TriangulateMinimumArea
72#define TRIANGULATE_TRACE "triangulate"
99 if( !firstVertex || firstVertex->
prev == firstVertex->
next )
122 wxLogTrace(
TRIANGULATE_TRACE,
"Tesselation failed, logging remaining vertices" );
138 std::set<VERTEX*> seen;
139 wxLog::EnableLogging();
142 if( !p.next || p.next == &p || seen.find( &p ) != seen.end() )
151 if( aSeen && aSeen->count( aStart ) )
155 aSeen->insert( aStart );
159 wxString msg = wxString::Format(
"Vertices: %d,%d,",
static_cast<int>( aStart->
x ),
160 static_cast<int>( aStart->
y ) );
164 msg += wxString::Format(
"%d,%d,",
static_cast<int>( p->
x ),
static_cast<int>( p->
y ) );
171 }
while( p != aStart );
186 if( !aStart || aStart->
next == aStart->
prev )
221 }
while( p != aStart &&
next && p );
247 wxASSERT( aStart->
next && aStart->
prev );
251 while( p != aStart && p->
next && p->
prev )
321 wxLogTrace(
TRIANGULATE_TRACE,
"earcutList starting at %p for pass %d", aPoint, pass );
329 int internal_pass = 1;
331 while( aPoint->
prev != aPoint->
next )
336 if( aPoint->
isEar() )
360 if( *prev != *nextNext &&
intersects( prev, aPoint,
next, nextNext ) &&
365 "Local intersection detected. Merging minor triangle with area %f",
366 area( prev, aPoint, nextNext ) );
385 if( aPoint == stop && aPoint->
prev != aPoint->
next )
396 if( newPoint->
next == newPoint->
prev )
410 if( internal_pass < 4 )
453 double prev_sq_len = ( aPoint->
prev->
x - aPoint->
x ) * ( aPoint->
prev->
x - aPoint->
x ) +
454 ( aPoint->
prev->
y - aPoint->
y ) * ( aPoint->
prev->
y - aPoint->
y );
455 double next_sq_len = ( aPoint->
next->
x - aPoint->
x ) * ( aPoint->
next->
x - aPoint->
x ) +
456 ( aPoint->
next->
y - aPoint->
y ) * ( aPoint->
next->
y - aPoint->
y );
457 double opp_sq_len = ( aPoint->
next->
x - aPoint->
prev->
x ) * ( aPoint->
next->
x - aPoint->
prev->
x ) +
460 return ( prev_sq_len < min_area || next_sq_len < min_area || opp_sq_len < min_area );
470 struct VertexComparator {
471 bool operator()(
const std::pair<VERTEX*,double>& a,
const std::pair<VERTEX*,double>& b)
const {
472 return a.second > b.second;
476 std::set<std::pair<VERTEX*,double>, VertexComparator> longest;
481 double len = ( p->
x - p->
next->
x ) * ( p->
x - p->
next->
x ) +
483 longest.emplace( p, len );
487 }
while (p != aStart);
489 avg /= longest.size();
492 for(
auto it = longest.begin(); it != longest.end() && it->second > avg; ++it )
501 int divisions = avg / it->second + 2 + pass;
502 double step = 1.0 / divisions;
504 for(
int i = 1; i < divisions; i++ )
506 double x = a->
x * ( 1.0 - step * i ) + b->
x * ( step * i );
507 double y = a->
y * ( 1.0 - step * i ) + b->
y * ( step * i );
527 if( !start || !start->
next || start->
next == start->
prev
539 std::vector<VERTEX*> overlapPoints;
542 while ( z_pt->
prevZ && *z_pt->
prevZ == *origPoly )
545 overlapPoints.push_back( z_pt );
547 while( z_pt->
nextZ && *z_pt->
nextZ == *origPoly )
550 overlapPoints.push_back( z_pt );
553 if( overlapPoints.size() != 2 || overlapPoints[0]->next == overlapPoints[1]
554 || overlapPoints[0]->prev == overlapPoints[1] )
556 origPoly = origPoly->
next;
560 if( overlapPoints[0]->
area( overlapPoints[1] ) < 0 || overlapPoints[1]->
area( overlapPoints[0] ) < 0 )
563 origPoly = origPoly->
next;
567 wxLogTrace(
TRIANGULATE_TRACE,
"Splitting at overlap point %f, %f", overlapPoints[0]->x, overlapPoints[0]->y );
568 std::swap( overlapPoints[0]->
next, overlapPoints[1]->
next );
569 overlapPoints[0]->next->prev = overlapPoints[0];
570 overlapPoints[1]->next->prev = overlapPoints[1];
572 overlapPoints[0]->updateList();
573 overlapPoints[1]->updateList();
578 wxLogTrace(
TRIANGULATE_TRACE,
"%s at first overlap split", retval ?
"Success" :
"Failed" );
582 }
while ( origPoly != start );
592 while( marker != origPoly->
prev )
595 if( origPoly->
next && origPoly->
i != marker->
i &&
goodSplit( origPoly, marker ) )
608 marker = marker->
next;
611 origPoly = origPoly->
next;
612 }
while( origPoly != start );
635 bool pos_area = a->
area( b ) > 0 && b->
area( a ) > 0;
637 return no_intersect && local_split && ( same_dir || has_len ) && !a_on_edge && !b_on_edge && pos_area;
642 constexpr int sign(
double aVal )
const
644 return ( aVal > 0 ) - ( aVal < 0 );
652 return q->
x <= std::max( p->
x, r->
x ) &&
653 q->
x >= std::min( p->
x, r->
x ) &&
654 q->
y <= std::max( p->
y, r->
y ) &&
655 q->
y >= std::min( p->
y, r->
y );
665 int sign1 =
sign(
area( p1, q1, p2 ) );
666 int sign2 =
sign(
area( p1, q1, q2 ) );
667 int sign3 =
sign(
area( p2, q2, p1 ) );
668 int sign4 =
sign(
area( p2, q2, q1 ) );
670 if( sign1 != sign2 && sign3 != sign4 )
702 if( p->
i == a->
i || p->
i == b->
i || q->
i == a->
i || q->
i == b->
i )
constexpr size_type GetWidth() const
constexpr size_type GetHeight() const
SHAPE_POLY_SET::TRIANGULATED_POLYGON & m_result
bool intersects(const VERTEX *p1, const VERTEX *q1, const VERTEX *p2, const VERTEX *q2) const
Check for intersection between two segments, end points included.
bool splitPolygon(VERTEX *start)
If we cannot find an ear to slice in the current polygon list, we use this to split the polygon into ...
constexpr int sign(double aVal) const
void logVertices(VERTEX *aStart, std::set< VERTEX * > *aSeen)
VERTEX * insertTriVertex(const VECTOR2I &pt, VERTEX *last)
Create an entry in the vertices lookup and optionally inserts the newly created vertex into an existi...
bool goodSplit(const VERTEX *a, const VERTEX *b) const
Check if a segment joining two vertices lies fully inside the polygon.
VERTEX * simplifyList(VERTEX *aStart)
Simplify the line chain by removing points that are too close to each other.
POLYGON_TRIANGULATION(SHAPE_POLY_SET::TRIANGULATED_POLYGON &aResult)
constexpr bool overlapping(const VERTEX *p, const VERTEX *q, const VERTEX *r) const
If p, q, and r are collinear and r lies between p and q, then return true.
void logRemaining()
Outputs a list of vertices that have not yet been triangulated.
VERTEX * removeNullTriangles(VERTEX *aStart)
Iterate through the list to remove NULL triangles if they exist.
bool intersectsPolygon(const VERTEX *a, const VERTEX *b) const
Check whether the segment from vertex a -> vertex b crosses any of the segments of the polygon of whi...
bool isTooSmall(const VERTEX *aPoint) const
Check whether a given vertex is too small to matter.
bool earcutList(VERTEX *aPoint, int pass=0)
Walk through a circular linked list starting at aPoint.
size_t m_vertices_original_size
void subdividePolygon(VERTEX *aStart, int pass=0)
Inserts a new vertex halfway between each existing pair of vertices.
bool TesselatePolygon(const SHAPE_LINE_CHAIN &aPoly, SHAPE_POLY_SET::TRIANGULATED_POLYGON *aHintData)
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
const std::vector< VECTOR2I > & CPoints() const
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
void AddVertex(const VECTOR2I &aP)
const std::deque< VECTOR2I > & Vertices() const
const std::deque< TRI > & Triangles() const
size_t GetVertexCount() const
void AddTriangle(int a, int b, int c)
void SetTriangles(const std::deque< TRI > &aTriangles)
constexpr extended_type SquaredEuclideanNorm() const
Compute the squared euclidean norm of the vector, which is defined as (x ** 2 + y ** 2).
std::deque< VERTEX > m_vertices
bool middleInside(const VERTEX *a, const VERTEX *b) const
Check if the middle of the segment from a to b is inside the polygon.
VERTEX * createList(const SHAPE_LINE_CHAIN &points, VERTEX *aTail=nullptr, void *aUserData=nullptr)
Create a list of vertices from a line chain.
bool locallyInside(const VERTEX *a, const VERTEX *b) const
Check whether the segment from vertex a -> vertex b is inside the polygon around the immediate area o...
double area(const VERTEX *p, const VERTEX *q, const VERTEX *r) const
Return the twice the signed area of the triangle formed by vertices p, q, and r.
VERTEX * insertVertex(int aIndex, const VECTOR2I &pt, VERTEX *last, void *aUserData=nullptr)
Insert a vertex into the vertex set.
VERTEX * split(VERTEX *b)
Split the referenced polygon between the reference point and vertex b, assuming they are in the same ...
void updateList()
After inserting or changing nodes, this function should be called to remove duplicate vertices and en...
void remove()
Remove the node from the linked list and z-ordered linked list.
double area(const VERTEX *aEnd=nullptr) const
Returns the signed area of the polygon connected to the current vertex, optionally ending at a specif...
bool isEar(bool aMatchUserData=false) const
Check whether the given vertex is in the middle of an ear.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
#define TRIANGULATE_TRACE
#define TRIANGULATEMINIMUMAREA
#define TRIANGULATESIMPLIFICATIONLEVEL
VECTOR2< int32_t > VECTOR2I
VECTOR2< double > VECTOR2D