40        return std::make_unique<POLYGON_TRIANGULATION>( *
m_result );
 
 
   44    std::unique_ptr<SHAPE_POLY_SET::TRIANGULATED_POLYGON> 
m_result;
 
 
   51    chain.Append( offset.x, offset.y );
 
   52    chain.Append( offset.x + size, offset.y );
 
   53    chain.Append( offset.x + size, offset.y + size );
 
   54    chain.Append( offset.x, offset.y + size );
 
   55    chain.SetClosed( 
true );
 
 
   63    chain.Append( offset.x, offset.y );
 
   64    chain.Append( offset.x + size, offset.y );
 
   65    chain.Append( offset.x + size/2, offset.y + size );
 
   66    chain.SetClosed( 
true );
 
 
   75    chain.Append( size, 0 );
 
   76    chain.Append( size, size/2 );
 
   77    chain.Append( size/2, size/2 );  
 
   78    chain.Append( size/2, size );
 
   79    chain.Append( 0, size );
 
   80    chain.SetClosed( 
true );
 
 
   89    if( 
result.GetVertexCount() == 0 )
 
   92    size_t triangleCount = 
result.GetTriangleCount();
 
   93    if( triangleCount == 0 )
 
   97    for( 
size_t i = 0; i < triangleCount; i++ )
 
   99        const auto& triangle = 
result.Triangles()[i];
 
  102        if( triangle.a >= (
int)
result.GetVertexCount() ||
 
  103            triangle.b >= (
int)
result.GetVertexCount() ||
 
  104            triangle.c >= (
int)
result.GetVertexCount() )
 
  110        if( triangle.a == triangle.b || triangle.b == triangle.c || triangle.a == triangle.c )
 
  114        if( strict && triangle.Area() <= 0 )
 
  121        const auto& vertices = 
result.Vertices();
 
  122        for( 
int i = 0; i < original.
PointCount(); i++ )
 
  125            for( 
size_t j = 0; j < vertices.size(); j++ )
 
  127                if( vertices[j] == original.
CPoint( i ) )
 
 
  149    bool success = triangulator->TesselatePolygon( triangle, 
nullptr );
 
 
  164    bool success = triangulator->TesselatePolygon( 
square, 
nullptr );
 
 
  179    bool success = triangulator->TesselatePolygon( concave, 
nullptr );
 
  185    size_t triangleCount = 
result.GetTriangleCount();
 
  188    if( !success || !isValid || triangleCount < 4 )
 
  190        std::cout << 
"\n=== ConcavePolygonTriangulation Diagnostic Output ===" << std::endl;
 
  191        std::cout << 
"Success: " << (success ? 
"true" : 
"false") << std::endl;
 
  192        std::cout << 
"Validation: " << (isValid ? 
"true" : 
"false") << std::endl;
 
  193        std::cout << 
"Triangle count: " << triangleCount << 
" (expected >= 4)" << std::endl;
 
  194        std::cout << 
"Vertex count: " << 
result.GetVertexCount() << std::endl;
 
  197        std::cout << 
"\nInput polygon vertices (" << concave.
PointCount() << 
" points):" << std::endl;
 
  198        for( 
int i = 0; i < concave.
PointCount(); i++ )
 
  201            std::cout << 
"  [" << i << 
"]: (" << pt.
x << 
", " << pt.
y << 
")" << std::endl;
 
  205        std::cout << 
"\nResult vertices (" << 
result.GetVertexCount() << 
" points):" << std::endl;
 
  206        const auto& vertices = 
result.Vertices();
 
  207        for( 
size_t i = 0; i < vertices.size(); i++ )
 
  209            std::cout << 
"  [" << i << 
"]: (" << vertices[i].x << 
", " << vertices[i].y << 
")" << std::endl;
 
  213        std::cout << 
"\nTriangles found (" << triangleCount << 
" triangles):" << std::endl;
 
  214        const auto& triangles = 
result.Triangles();
 
  215        for( 
size_t i = 0; i < triangles.size(); i++ )
 
  217            const auto& tri = triangles[i];
 
  221            double area = tri.Area();
 
  223            std::cout << 
"  Triangle[" << i << 
"]: indices(" << tri.a << 
"," << tri.b << 
"," << tri.c << 
")" << std::endl;
 
  224            std::cout << 
"    A: (" << va.
x << 
", " << va.
y << 
")" << std::endl;
 
  225            std::cout << 
"    B: (" << vb.
x << 
", " << vb.
y << 
")" << std::endl;
 
  226            std::cout << 
"    C: (" << vc.
x << 
", " << vc.
y << 
")" << std::endl;
 
  227            std::cout << 
"    Area: " << area << std::endl;
 
  231                std::cout << 
"    *** DEGENERATE TRIANGLE (area <= 0) ***" << std::endl;
 
  232            if( tri.a == tri.b || tri.b == tri.c || tri.a == tri.c )
 
  233                std::cout << 
"    *** INVALID TRIANGLE (duplicate vertex indices) ***" << std::endl;
 
  237        if( triangleCount > 0 )
 
  239            double totalArea = 0.0;
 
  240            for( 
const auto& tri : triangles )
 
  241                totalArea += tri.Area();
 
  242            std::cout << 
"\nTotal triangulated area: " << totalArea << std::endl;
 
  246            std::cout << 
"Original polygon area: " << originalArea << std::endl;
 
  247            std::cout << 
"Area difference: " << 
std::abs( totalArea - originalArea ) << std::endl;
 
  250        std::cout << 
"================================================\n" << std::endl;
 
 
  267    bool success1 = triangulator1->TesselatePolygon( 
square, 
nullptr );
 
  274    bool success2 = triangulator2->TesselatePolygon( 
square, &fixture1.
GetResult() );
 
 
  288    hintTriangulator->TesselatePolygon( triangle, 
nullptr );
 
  295    bool success = triangulator->TesselatePolygon( 
square, &hintFixture.
GetResult() );
 
 
  308    bool success = triangulator->TesselatePolygon( 
empty, 
nullptr );
 
  315    singlePoint.
Append( 0, 0 );
 
  317    success = triangulator2->TesselatePolygon( singlePoint, 
nullptr );
 
  327    success = triangulator3->TesselatePolygon( line, 
nullptr );
 
 
  339    zeroArea.
Append( 100, 0 );
 
  344    bool success = triangulator->TesselatePolygon( zeroArea, 
nullptr );
 
 
  353    for( 
int i = 0; i < 100; i++ )
 
  359        bool success = triangulator->TesselatePolygon( poly, 
nullptr );
 
 
  373    int numVertices = 1000;
 
  376    for( 
int i = 0; i < numVertices; i++ )
 
  378        double angle = 2.0 * 
M_PI * i / numVertices;
 
  379        int x = 
static_cast<int>( 
radius * cos( angle ) );
 
  380        int y = 
static_cast<int>( 
radius * sin( angle ) );
 
  385    auto start = std::chrono::high_resolution_clock::now();
 
  386    bool success = triangulator->TesselatePolygon( largePoly, 
nullptr );
 
  387    auto end = std::chrono::high_resolution_clock::now();
 
  389    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>( 
end - start );
 
 
  405    const int numThreads = 4;
 
  406    const int numTriangulationsPerThread = 10;
 
  408    std::vector<std::future<bool>> futures;
 
  410    for( 
int t = 0; t < numThreads; t++ )
 
  412        futures.push_back( std::async( std::launch::async, [t, numTriangulationsPerThread]()
 
  414            for( 
int i = 0; i < numTriangulationsPerThread; i++ )
 
  422                bool success = triangulator->TesselatePolygon( poly, 
nullptr );
 
  431    for( 
auto& future : futures )
 
 
  446    bowtie.
Append( 100, 100 );
 
  451    bool success = triangulator->TesselatePolygon( bowtie, 
nullptr );
 
 
  468    nearlyCollinear.
Append( 0, 0 );
 
  469    nearlyCollinear.
Append( 1000000, 0 );
 
  470    nearlyCollinear.
Append( 2000000, 1 ); 
 
  471    nearlyCollinear.
Append( 3000000, 0 );
 
  472    nearlyCollinear.
Append( 1500000, 1000000 );
 
  475    bool success = triangulator->TesselatePolygon( nearlyCollinear, 
nullptr );
 
 
  501    bool success = triangulator->TesselatePolygon( 
duplicate, 
nullptr );
 
 
  517    int large = 1000000000; 
 
  519    extreme.
Append( large, 0 );
 
  520    extreme.
Append( large, large );
 
  521    extreme.
Append( 0, large );
 
  524    bool success = triangulator->TesselatePolygon( extreme, 
nullptr );
 
 
  540    std::vector<SHAPE_LINE_CHAIN> testPolygons;
 
  547    degenerate.Append( 0, 0 );
 
  548    degenerate.SetClosed( 
true );
 
  549    testPolygons.push_back( degenerate );
 
  554    for( 
const auto& poly : testPolygons )
 
  557        bool success = triangulator->TesselatePolygon( poly, 
nullptr );
 
 
  571    bool success = triangulator->TesselatePolygon( 
square, 
nullptr );
 
  578    if( 
result.GetTriangleCount() > 0 )
 
  581        result.GetTriangle( 0, a, b, c );
 
  590    for( 
const auto& tri : 
result.Triangles() )
 
 
  606    const int expectedOutlineIndex = 5;
 
 
  623    std::vector<int> testSizes = { 10, 50, 100, 500, 1000 };
 
  624    std::vector<long long> durations;
 
  626    for( 
int size : testSizes )
 
  633        for( 
int i = 0; i < size; i++ )
 
  635            double angle = 2.0 * 
M_PI * i / size;
 
  636            int x = 
static_cast<int>( 1000 * cos( angle ) );
 
  637            int y = 
static_cast<int>( 1000 * sin( angle ) );
 
  642        auto start = std::chrono::high_resolution_clock::now();
 
  643        bool success = triangulator->TesselatePolygon( poly, 
nullptr );
 
  644        auto end = std::chrono::high_resolution_clock::now();
 
  648        auto duration = std::chrono::duration_cast<std::chrono::microseconds>( 
end - start );
 
  649        durations.push_back( duration.count() );
 
  654    for( 
size_t i = 1; i < durations.size(); i++ )
 
  656        double scaleFactor = 
static_cast<double>( durations[i] ) / durations[i-1];
 
  657        double sizeFactor = 
static_cast<double>( testSizes[i] ) / testSizes[i-1];
 
  660        BOOST_TEST( scaleFactor < sizeFactor * sizeFactor * 2 );
 
 
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...
 
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
 
int PointCount() const
Return the number of points (vertices) in this line chain.
 
double Area(bool aAbsolute=true) const
Return the area of this chain.
 
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
 
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
 
size_t GetTriangleCount() const
 
size_t GetVertexCount() const
 
Represent a set of closed polygons.
 
SHAPE_POLY_SET::TRIANGULATED_POLYGON & GetResult()
 
std::unique_ptr< POLYGON_TRIANGULATION > CreateTriangulator()
 
std::unique_ptr< SHAPE_POLY_SET::TRIANGULATED_POLYGON > m_result
 
TRIANGULATION_TEST_FIXTURE()
 
static bool empty(const wxTextEntryBase *aCtrl)
 
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
 
Numerical test predicates.
 
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
 
BOOST_TEST(contains==c.ExpectedContains)
 
BOOST_AUTO_TEST_SUITE_END()
 
SHAPE_LINE_CHAIN createConcavePolygon(int size=100)
 
SHAPE_LINE_CHAIN createSquare(int size=100, VECTOR2I offset=VECTOR2I(0, 0))
 
bool validateTriangulation(const SHAPE_POLY_SET::TRIANGULATED_POLYGON &result, const SHAPE_LINE_CHAIN &original, bool strict=true)
 
SHAPE_LINE_CHAIN createTriangle(int size=100, VECTOR2I offset=VECTOR2I(0, 0))
 
BOOST_AUTO_TEST_CASE(BasicTriangleTriangulation)
 
const SHAPE_LINE_CHAIN chain
 
wxString result
Test unit parsing edge cases and error handling.
 
VECTOR2< int32_t > VECTOR2I