40 return std::make_unique<POLYGON_TRIANGULATION>( *m_result );
44 std::unique_ptr<SHAPE_POLY_SET::TRIANGULATED_POLYGON>
m_result;
93 if( triangleCount == 0 )
97 for(
size_t i = 0; i < triangleCount; i++ )
99 const auto& triangle = result.
Triangles()[i];
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 );
183 const auto& result = fixture.
GetResult();
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 );
575 const auto& result = fixture.
GetResult();
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
const std::deque< VECTOR2I > & Vertices() const
const std::deque< TRI > & Triangles() const
size_t GetVertexCount() const
int GetSourceOutlineIndex() 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
VECTOR2< int32_t > VECTOR2I