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 ) );
 
  367                m_result.AddTriangle( prev->
i, aPoint->
i, nextNext->
i );
 
  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 )
 
 
 
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.
 
const std::deque< VECTOR2I > & Vertices() const
 
const std::deque< TRI > & Triangles() const
 
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_SET(int aSimplificationLevel)
 
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