46#ifndef __POLYGON_TRIANGULATION_H
47#define __POLYGON_TRIANGULATION_H
65#if defined( __MINGW32__ )
66 #define TRIANGULATESIMPLIFICATIONLEVEL 50
67 #define TRIANGULATEMINIMUMAREA 1000
69 #define TRIANGULATESIMPLIFICATIONLEVEL ADVANCED_CFG::GetCfg().m_TriangulateSimplificationLevel
70 #define TRIANGULATEMINIMUMAREA ADVANCED_CFG::GetCfg().m_TriangulateMinimumArea
73#define TRIANGULATE_TRACE "triangulate"
100 if( !firstVertex || firstVertex->
prev == firstVertex->
next )
123 wxLogTrace(
TRIANGULATE_TRACE,
"Tesselation failed, logging remaining vertices" );
139 std::set<VERTEX*> seen;
140 wxLog::EnableLogging();
143 if( !p.next || p.next == &p || seen.find( &p ) != seen.end() )
152 if( aSeen && aSeen->count( aStart ) )
156 aSeen->insert( aStart );
160 wxString msg = wxString::Format(
"Vertices: %d,%d,",
static_cast<int>( aStart->
x ),
161 static_cast<int>( aStart->
y ) );
165 msg += wxString::Format(
"%d,%d,",
static_cast<int>( p->
x ),
static_cast<int>( p->
y ) );
172 }
while( p != aStart );
187 if( !aStart || aStart->
next == aStart->
prev )
222 }
while( p != aStart &&
next && p );
248 wxASSERT( aStart->
next && aStart->
prev );
252 while( p != aStart && p->
next && p->
prev )
322 wxLogTrace(
TRIANGULATE_TRACE,
"earcutList starting at %p for pass %d", aPoint, pass );
330 int internal_pass = 1;
332 while( aPoint->
prev != aPoint->
next )
337 if( aPoint->
isEar() )
361 if( *prev != *nextNext &&
intersects( prev, aPoint,
next, nextNext ) &&
366 "Local intersection detected. Merging minor triangle with area %f",
367 area( prev, aPoint, nextNext ) );
386 if( aPoint == stop && aPoint->
prev != aPoint->
next )
397 if( newPoint->
next == newPoint->
prev )
411 if( internal_pass < 4 )
454 double prev_sq_len = ( aPoint->
prev->
x - aPoint->
x ) * ( aPoint->
prev->
x - aPoint->
x ) +
455 ( aPoint->
prev->
y - aPoint->
y ) * ( aPoint->
prev->
y - aPoint->
y );
456 double next_sq_len = ( aPoint->
next->
x - aPoint->
x ) * ( aPoint->
next->
x - aPoint->
x ) +
457 ( aPoint->
next->
y - aPoint->
y ) * ( aPoint->
next->
y - aPoint->
y );
458 double opp_sq_len = ( aPoint->
next->
x - aPoint->
prev->
x ) * ( aPoint->
next->
x - aPoint->
prev->
x ) +
461 return ( prev_sq_len < min_area || next_sq_len < min_area || opp_sq_len < min_area );
471 struct VertexComparator {
472 bool operator()(
const std::pair<VERTEX*,double>& a,
const std::pair<VERTEX*,double>& b)
const {
473 return a.second > b.second;
477 std::set<std::pair<VERTEX*,double>, VertexComparator> longest;
482 double len = ( p->
x - p->
next->
x ) * ( p->
x - p->
next->
x ) +
484 longest.emplace( p, len );
488 }
while (p != aStart);
490 avg /= longest.size();
493 for(
auto it = longest.begin(); it != longest.end() && it->second > avg; ++it )
502 int divisions = avg / it->second + 2 + pass;
503 double step = 1.0 / divisions;
505 for(
int i = 1; i < divisions; i++ )
507 double x = a->
x * ( 1.0 - step * i ) + b->
x * ( step * i );
508 double y = a->
y * ( 1.0 - step * i ) + b->
y * ( step * i );
528 if( !start || !start->
next || start->
next == start->
prev
540 std::vector<VERTEX*> overlapPoints;
543 while ( z_pt->
prevZ && *z_pt->
prevZ == *origPoly )
546 overlapPoints.push_back( z_pt );
548 while( z_pt->
nextZ && *z_pt->
nextZ == *origPoly )
551 overlapPoints.push_back( z_pt );
554 if( overlapPoints.size() != 2 || overlapPoints[0]->next == overlapPoints[1]
555 || overlapPoints[0]->prev == overlapPoints[1] )
557 origPoly = origPoly->
next;
561 if( overlapPoints[0]->
area( overlapPoints[1] ) < 0 || overlapPoints[1]->
area( overlapPoints[0] ) < 0 )
564 origPoly = origPoly->
next;
568 wxLogTrace(
TRIANGULATE_TRACE,
"Splitting at overlap point %f, %f", overlapPoints[0]->x, overlapPoints[0]->y );
569 std::swap( overlapPoints[0]->
next, overlapPoints[1]->
next );
570 overlapPoints[0]->next->prev = overlapPoints[0];
571 overlapPoints[1]->next->prev = overlapPoints[1];
573 overlapPoints[0]->updateList();
574 overlapPoints[1]->updateList();
579 wxLogTrace(
TRIANGULATE_TRACE,
"%s at first overlap split", retval ?
"Success" :
"Failed" );
583 }
while ( origPoly != start );
593 while( marker != origPoly->
prev )
596 if( origPoly->
next && origPoly->
i != marker->
i &&
goodSplit( origPoly, marker ) )
609 marker = marker->
next;
612 origPoly = origPoly->
next;
613 }
while( origPoly != start );
636 bool pos_area = a->
area( b ) > 0 && b->
area( a ) > 0;
638 return no_intersect && local_split && ( same_dir || has_len ) && !a_on_edge && !b_on_edge && pos_area;
643 constexpr int sign(
double aVal )
const
645 return ( aVal > 0 ) - ( aVal < 0 );
653 return q->
x <= std::max( p->
x, r->
x ) &&
654 q->
x >= std::min( p->
x, r->
x ) &&
655 q->
y <= std::max( p->
y, r->
y ) &&
656 q->
y >= std::min( p->
y, r->
y );
666 int sign1 =
sign(
area( p1, q1, p2 ) );
667 int sign2 =
sign(
area( p1, q1, q2 ) );
668 int sign3 =
sign(
area( p2, q2, p1 ) );
669 int sign4 =
sign(
area( p2, q2, q1 ) );
671 if( sign1 != sign2 && sign3 != sign4 )
703 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