Use a polygon in the format of the ClipperLib::Path and process it and create multiple 2d objects (POLYGON_2D and DUMMY_BLOCK_2D) that can be used to represent this polygon area.
381{
382
384
386
388
389
392
393
395
396
398
399 segments_and_normals.reserve(
path.PointCount() );
400 segments.reserve(
path.PointCount() );
401
403
404 for(
int i = 0; i <
path.PointCount(); i++ )
405 {
407
408 const SFVEC2F point( (
float) ( a.
x ) * aBiuTo3dUnitsScale,
409 (
float) ( -a.
y ) * aBiuTo3dUnitsScale );
410
411
412 if( ( i == 0 ) || ( fabs( prevPoint.x - point.x ) > FLT_EPSILON )
413 || ( fabs( prevPoint.y - point.y ) > FLT_EPSILON ) )
414 {
415 prevPoint = point;
416
418
421 segments_and_normals.push_back( sn );
422
425 segments.push_back( ps );
426 }
427 }
428
430
431
432 unsigned int i;
433 unsigned int j = segments_and_normals.size() - 1;
434
435
436 std::vector<SFVEC2F> tmpSegmentNormals;
437 tmpSegmentNormals.resize( segments_and_normals.size() );
438
439 float medOfTheSquaresSegmentLength = 0.0f;
440
441#ifdef PRINT_STATISTICS_3D_VIEWER
442 float minLength = FLT_MAX;
443#endif
444
445 for( i = 0; i < segments_and_normals.size(); j = i++ )
446 {
447 const SFVEC2F slope = segments_and_normals[j].m_Start - segments_and_normals[i].m_Start;
448
449 segments_and_normals[i].m_Precalc_slope = slope;
450
451
452 segments[i].m_inv_JY_minus_IY =
453 1.0f / ( segments_and_normals[j].m_Start.y - segments_and_normals[i].m_Start.y );
454
455 segments[i].m_JX_minus_IX =
456 ( segments_and_normals[j].m_Start.x - segments_and_normals[i].m_Start.x );
457
458
459
460 tmpSegmentNormals[i] = glm::normalize(
SFVEC2F( slope.y, -slope.x ) );
461
462 const float length = slope.x * slope.x + slope.y * slope.y;
463
464#ifdef PRINT_STATISTICS_3D_VIEWER
465 if( length < minLength )
466 minLength = length;
467#endif
468
469 medOfTheSquaresSegmentLength += length;
470 }
471
472#ifdef PRINT_STATISTICS_3D_VIEWER
473 float minSegmentLength = sqrt( minLength );
474#endif
475
476
477
478 medOfTheSquaresSegmentLength /= segments_and_normals.size();
479 medOfTheSquaresSegmentLength = sqrt( medOfTheSquaresSegmentLength );
480
481
482
483
484
485 j = segments_and_normals.size() - 1;
486
487 for( i = 0; i < segments_and_normals.size(); j = i++ )
488 {
489 const SFVEC2F normalBeforeSeg = tmpSegmentNormals[j];
490 const SFVEC2F normalSeg = tmpSegmentNormals[i];
491 const SFVEC2F normalAfterSeg = tmpSegmentNormals[( i + 1 ) % segments_and_normals.size()];
492
493 const float dotBefore = glm::dot( normalBeforeSeg, normalSeg );
494 const float dotAfter = glm::dot( normalAfterSeg, normalSeg );
495
496 if( dotBefore < 0.7f )
497 segments_and_normals[i].m_Normals.m_Start = normalSeg;
498 else
499 segments_and_normals[i].m_Normals.m_Start =
500 glm::normalize( ( normalBeforeSeg * dotBefore ) + normalSeg );
501
502 if( dotAfter < 0.7f )
503 segments_and_normals[i].m_Normals.m_End = normalSeg;
504 else
505 segments_and_normals[i].m_Normals.m_End =
506 glm::normalize( ( normalAfterSeg * dotAfter ) + normalSeg );
507 }
508
510
511 if( aDivFactor < 0.0f )
512 {
514 }
515 else
516 {
517 if( aDivFactor <= FLT_EPSILON )
518 aDivFactor = medOfTheSquaresSegmentLength;
519
520 grid_divisions.x = (
unsigned int) ( ( bbox.
GetExtent().x / aDivFactor ) );
521 grid_divisions.y = (
unsigned int) ( ( bbox.
GetExtent().y / aDivFactor ) );
522
523 grid_divisions = glm::clamp(
525 }
526
527
529
530 blockAdvance.x = bbox.
GetExtent().x / (float) grid_divisions.x;
531 blockAdvance.y = bbox.
GetExtent().y / (float) grid_divisions.y;
532
533 wxASSERT( blockAdvance.x > 0.0f );
534 wxASSERT( blockAdvance.y > 0.0f );
535
536 const int leftToRight_inc = ( pathBounds.
GetRight() - pathBounds.
GetLeft() ) / grid_divisions.x;
537
538 const int topToBottom_inc = ( pathBounds.
GetBottom() - pathBounds.
GetTop() ) / grid_divisions.y;
539
540
541 unsigned int stats_n_empty_blocks = 0;
542 unsigned int stats_n_dummy_blocks = 0;
543 unsigned int stats_n_poly_blocks = 0;
544 unsigned int stats_sum_size_of_polygons = 0;
545
546
547 int topToBottom = pathBounds.
GetTop();
548 float blockY = bbox.
Max().y;
549
550 for( unsigned int iy = 0; iy < grid_divisions.y; iy++ )
551 {
552 int leftToRight = pathBounds.
GetLeft();
553 float blockX = bbox.
Min().x;
554
555 for( unsigned int ix = 0; ix < grid_divisions.x; ix++ )
556 {
558 SFVEC2F( blockX + blockAdvance.x, blockY ) );
559
560
561 blockBox.ScaleNextUp();
562 blockBox.ScaleNextUp();
563 blockBox.ScaleNextUp();
564
566
568
569 if( extractedSegments.empty() )
570 {
571
572 SFVEC2F p1( blockBox.Min().x, blockBox.Min().y );
573 SFVEC2F p2( blockBox.Max().x, blockBox.Min().y );
574 SFVEC2F p3( blockBox.Max().x, blockBox.Max().y );
575 SFVEC2F p4( blockBox.Min().x, blockBox.Max().y );
576
580 {
581
582
583
584
586 stats_n_dummy_blocks++;
587 }
588 else
589 {
590
591
592 stats_n_empty_blocks++;
593 }
594 }
595 else
596 {
597
598
599
600
601
602
604
606 VECTOR2I( leftToRight + leftToRight_inc, topToBottom ),
607 VECTOR2I( leftToRight + leftToRight_inc, topToBottom + topToBottom_inc ),
608 VECTOR2I( leftToRight, topToBottom + topToBottom_inc ) } );
609
610
612
614
615
619
621
622 outersAndHoles.
m_Holes.clear();
624
625 for(
int idx = 0; idx < solution.
OutlineCount(); idx++ )
626 {
628
630
632 outersAndHoles.
m_Outers.push_back( solutionSegment );
633
634 stats_sum_size_of_polygons += solutionSegment.size();
635
636 for(
int holeIdx = 0; holeIdx < solution.
HoleCount( idx ); holeIdx++ )
637 {
639
641 outersAndHoles.
m_Holes.push_back( solutionSegment );
642 stats_sum_size_of_polygons += solutionSegment.size();
643 }
644 }
645
646 if( !outersAndHoles.
m_Outers.empty() )
647 {
648 aDstContainer.
Add(
new POLYGON_2D( extractedSegments, outersAndHoles,
649 aBoardItem ) );
650 stats_n_poly_blocks++;
651 }
652 }
653
654 blockX += blockAdvance.x;
655 leftToRight += leftToRight_inc;
656 }
657
658 blockY -= blockAdvance.y;
659 topToBottom += topToBottom_inc;
660 }
661}
coord_type GetTop() const
coord_type GetRight() const
coord_type GetLeft() const
coord_type GetBottom() const
void Add(OBJECT_2D *aObject)
A dummy block defined by a 2d box size.
Represent a sub polygon block.
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.
Represent a set of closed polygons.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new hole to the given outline (default: last) and returns its index.
void BooleanIntersection(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset union between a and b, store the result in it self For aFastMode meaning,...
int HoleCount(int aOutline) const
Return the reference to aIndex-th outline in the set.
SHAPE_LINE_CHAIN & Outline(int aIndex)
SHAPE_LINE_CHAIN & Hole(int aOutline, int aHole)
Return the aIndex-th subpolygon in the set.
int OutlineCount() const
Return the number of vertices in a given outline/hole.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
static void polygon_Convert(const SHAPE_LINE_CHAIN &aPath, SEGMENTS &aOutSegment, float aBiuTo3dUnitsScale)
static void extractPathsFrom(const SEGMENTS_WIDTH_NORMALS &aSegList, const BBOX_2D &aBBox, SEGMENTS_WIDTH_NORMALS &aOutSegThatIntersect)
static bool polygon_IsPointInside(const SEGMENTS &aSegments, const SFVEC2F &aPoint)
std::vector< SEGMENT_WITH_NORMALS > SEGMENTS_WIDTH_NORMALS
List used to test ray2d intersections.
std::vector< POLYSEGMENT > SEGMENTS
Manage a bounding box defined by two SFVEC2F min max points.
SFVEC2F GetExtent() const
void Union(const SFVEC2F &aPoint)
Recalculate the bounding box adding a point.
const SFVEC2F & Min() const
void Reset()
Reset the bounding box to zero and uninitialize it.
const SFVEC2F & Max() const
void ScaleNextUp()
Scale a bounding box to the next float representation making it larger.
Handle a subset of a polygon.
std::vector< SEGMENTS > m_Holes
std::vector< SEGMENTS > m_Outers