36 wxASSERT( aSegments.size() >= 3 );
39 unsigned int j = aSegments.size() - 1;
40 bool oddNodes =
false;
42 for( i = 0; i < aSegments.size(); j = i++ )
44 const float polyJY = aSegments[j].m_Start.y;
45 const float polyIY = aSegments[i].m_Start.y;
47 if( ( ( polyIY <= aPoint.y ) && ( polyJY >= aPoint.y ) )
48 || ( ( polyJY <= aPoint.y ) && ( polyIY >= aPoint.y ) ) )
50 const float polyJX = aSegments[j].m_Start.x;
51 const float polyIX = aSegments[i].m_Start.x;
53 if( ( polyIX <= aPoint.x ) || ( polyJX <= aPoint.x ) )
54 oddNodes ^= ( ( polyIX + ( ( aPoint.y - polyIY ) * aSegments[i].m_inv_JY_minus_IY )
55 * aSegments[i].m_JX_minus_IX )
71 for(
unsigned int i = 0; i < aOpenSegmentList.size(); i++ )
133 if( fabs( rxs ) > FLT_EPSILON )
135 const float inv_rxs = 1.0f / rxs;
139 const float t = ( pq.x * s.y - pq.y * s.x ) * inv_rxs;
141 if( ( t < 0.0f ) || ( t > 1.0f ) )
148 if( ( u < 0.0f ) || ( u > 1.0f ) )
151 if( ( hitIndex == -1 ) || ( t <= tMin ) )
162 wxASSERT( ( tMin >= 0.0f ) && ( tMin <= 1.0f ) );
168 *aNormalOut = glm::normalize(
m_open_segments[hitIndex].m_Normals.m_Start * hitU +
182 return INTERSECTION_RESULT::MISSES;
253 return INTERSECTION_RESULT::MISSES;
270#define MAX_NR_DIVISIONS 96
276 const SFVEC2F r = aEnd - aStart;
280 const float rxs = r.x * s.y - r.y * s.x;
282 if( fabs( rxs ) > glm::epsilon<float>() )
284 const float inv_rxs = 1.0f / rxs;
288 const float t = ( pq.x * s.y - pq.y * s.x ) * inv_rxs;
290 if( ( t < 0.0f ) || ( t > 1.0f ) )
293 const float u = ( pq.x * r.y - pq.y * r.x ) * inv_rxs;
295 if( ( u < 0.0f ) || ( u > 1.0f ) )
308 wxASSERT( aSegList.size() >= 3 );
311 unsigned int j = aSegList.size() - 1;
318 aOutSegThatIntersect.clear();
320 for( i = 0; i < aSegList.size(); j = i++ )
322 if( aBBox.
Inside( aSegList[i].m_Start ) || aBBox.
Inside( aSegList[j].m_Start ) )
326 aOutSegThatIntersect.push_back( aSegList[i] );
333 BBOX_2D segmentBBox( aSegList[i].m_Start, aSegList[j].m_Start );
343 aOutSegThatIntersect.push_back( seg );
352 float aBiuTo3dUnitsScale )
360 aOutSegment[j].m_Start =
SFVEC2F( (
float) a.
x * aBiuTo3dUnitsScale,
361 (
float) -a.
y * aBiuTo3dUnitsScale );
365 unsigned int j = aOutSegment.size() - 1;
367 for( i = 0; i < aOutSegment.size(); j = i++ )
370 aOutSegment[i].m_inv_JY_minus_IY = 1.0f /
371 ( aOutSegment[j].m_Start.y - aOutSegment[i].m_Start.y );
373 aOutSegment[i].m_JX_minus_IX = ( aOutSegment[j].m_Start.x - aOutSegment[i].m_Start.x );
379 float aBiuTo3dUnitsScale,
float aDivFactor,
380 const BOARD_ITEM& aBoardItem,
int aPolyIndex )
399 segments_and_normals.reserve(
path.PointCount() );
400 segments.reserve(
path.PointCount() );
404 for(
int i = 0; i <
path.PointCount(); i++ )
408 const SFVEC2F point( (
float) ( a.
x ) * aBiuTo3dUnitsScale,
409 (
float) ( -a.
y ) * aBiuTo3dUnitsScale );
412 if( ( i == 0 ) || ( fabs( prevPoint.x - point.x ) > FLT_EPSILON )
413 || ( fabs( prevPoint.y - point.y ) > FLT_EPSILON ) )
421 segments_and_normals.push_back( sn );
425 segments.push_back( ps );
433 unsigned int j = segments_and_normals.size() - 1;
436 std::vector<SFVEC2F> tmpSegmentNormals;
437 tmpSegmentNormals.resize( segments_and_normals.size() );
439 float medOfTheSquaresSegmentLength = 0.0f;
441#ifdef PRINT_STATISTICS_3D_VIEWER
442 float minLength = FLT_MAX;
445 for( i = 0; i < segments_and_normals.size(); j = i++ )
447 const SFVEC2F slope = segments_and_normals[j].m_Start - segments_and_normals[i].m_Start;
449 segments_and_normals[i].m_Precalc_slope = slope;
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 );
455 segments[i].m_JX_minus_IX =
456 ( segments_and_normals[j].m_Start.x - segments_and_normals[i].m_Start.x );
460 tmpSegmentNormals[i] = glm::normalize(
SFVEC2F( slope.y, -slope.x ) );
462 const float length = slope.x * slope.x + slope.y * slope.y;
464#ifdef PRINT_STATISTICS_3D_VIEWER
465 if( length < minLength )
469 medOfTheSquaresSegmentLength += length;
472#ifdef PRINT_STATISTICS_3D_VIEWER
473 float minSegmentLength = sqrt( minLength );
478 medOfTheSquaresSegmentLength /= segments_and_normals.size();
479 medOfTheSquaresSegmentLength = sqrt( medOfTheSquaresSegmentLength );
485 j = segments_and_normals.size() - 1;
487 for( i = 0; i < segments_and_normals.size(); j = i++ )
489 const SFVEC2F normalBeforeSeg = tmpSegmentNormals[j];
490 const SFVEC2F normalSeg = tmpSegmentNormals[i];
491 const SFVEC2F normalAfterSeg = tmpSegmentNormals[( i + 1 ) % segments_and_normals.size()];
493 const float dotBefore = glm::dot( normalBeforeSeg, normalSeg );
494 const float dotAfter = glm::dot( normalAfterSeg, normalSeg );
496 if( dotBefore < 0.7f )
497 segments_and_normals[i].m_Normals.m_Start = normalSeg;
499 segments_and_normals[i].m_Normals.m_Start =
500 glm::normalize( ( normalBeforeSeg * dotBefore ) + normalSeg );
502 if( dotAfter < 0.7f )
503 segments_and_normals[i].m_Normals.m_End = normalSeg;
505 segments_and_normals[i].m_Normals.m_End =
506 glm::normalize( ( normalAfterSeg * dotAfter ) + normalSeg );
511 if( aDivFactor < 0.0f )
517 if( aDivFactor <= FLT_EPSILON )
518 aDivFactor = medOfTheSquaresSegmentLength;
520 grid_divisions.x = (
unsigned int) ( ( bbox.
GetExtent().x / aDivFactor ) );
521 grid_divisions.y = (
unsigned int) ( ( bbox.
GetExtent().y / aDivFactor ) );
523 grid_divisions = glm::clamp(
530 blockAdvance.x = bbox.
GetExtent().x / (float) grid_divisions.x;
531 blockAdvance.y = bbox.
GetExtent().y / (float) grid_divisions.y;
533 wxASSERT( blockAdvance.x > 0.0f );
534 wxASSERT( blockAdvance.y > 0.0f );
536 const int leftToRight_inc = ( pathBounds.
GetRight() - pathBounds.
GetLeft() ) / grid_divisions.x;
538 const int topToBottom_inc = ( pathBounds.
GetBottom() - pathBounds.
GetTop() ) / grid_divisions.y;
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;
547 int topToBottom = pathBounds.
GetTop();
548 float blockY = bbox.
Max().y;
550 for(
unsigned int iy = 0; iy < grid_divisions.y; iy++ )
552 int leftToRight = pathBounds.
GetLeft();
553 float blockX = bbox.
Min().x;
555 for(
unsigned int ix = 0; ix < grid_divisions.x; ix++ )
558 SFVEC2F( blockX + blockAdvance.x, blockY ) );
569 if( extractedSegments.empty() )
586 stats_n_dummy_blocks++;
592 stats_n_empty_blocks++;
606 VECTOR2I( leftToRight + leftToRight_inc, topToBottom ),
607 VECTOR2I( leftToRight + leftToRight_inc, topToBottom + topToBottom_inc ),
608 VECTOR2I( leftToRight, topToBottom + topToBottom_inc ) } );
622 outersAndHoles.
m_Holes.clear();
625 for(
int idx = 0; idx < solution.
OutlineCount(); idx++ )
632 outersAndHoles.
m_Outers.push_back( solutionSegment );
634 stats_sum_size_of_polygons += solutionSegment.size();
636 for(
int holeIdx = 0; holeIdx < solution.
HoleCount( idx ); holeIdx++ )
641 outersAndHoles.
m_Holes.push_back( solutionSegment );
642 stats_sum_size_of_polygons += solutionSegment.size();
646 if( !outersAndHoles.
m_Outers.empty() )
648 aDstContainer.
Add(
new POLYGON_2D( extractedSegments, outersAndHoles,
650 stats_n_poly_blocks++;
654 blockX += blockAdvance.x;
655 leftToRight += leftToRight_inc;
658 blockY -= blockAdvance.y;
659 topToBottom += topToBottom_inc;
666 float aBiuTo3dUnitsScale )
668 aOutSegment.resize( aPath.size() );
670 for(
unsigned i = 0; i < aPath.size(); i++ )
672 aOutSegment[i].m_Start =
SFVEC2F(
673 (
float) aPath[i].
X * aBiuTo3dUnitsScale, (
float) -aPath[i].Y * aBiuTo3dUnitsScale );
677 unsigned int j = aOutSegment.size() - 1;
679 for( i = 0; i < aOutSegment.size(); j = i++ )
682 aOutSegment[i].m_inv_JY_minus_IY =
683 1.0f / ( aOutSegment[j].m_Start.y - aOutSegment[i].m_Start.y );
684 aOutSegment[i].m_JX_minus_IX = ( aOutSegment[j].m_Start.x - aOutSegment[i].m_Start.x );
692 ClipperLib::Path aPath;
698 aPath[0] = ClipperLib::IntPoint( -2, -2 );
699 aPath[1] = ClipperLib::IntPoint( 2, -2 );
700 aPath[2] = ClipperLib::IntPoint( 2, 2 );
701 aPath[3] = ClipperLib::IntPoint( -2, 2 );
704 wxASSERT( ClipperLib::Orientation( aPath ) );
708 wxASSERT( aPath.size() == aSegments.size() );
710 wxASSERT( aSegments[0].m_Start ==
SFVEC2F( -2.0f, 2.0f ) );
711 wxASSERT( aSegments[1].m_Start ==
SFVEC2F( 2.0f, 2.0f ) );
712 wxASSERT( aSegments[2].m_Start ==
SFVEC2F( 2.0f, -2.0f ) );
713 wxASSERT( aSegments[3].m_Start ==
SFVEC2F( -2.0f, -2.0f ) );
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
constexpr coord_type GetLeft() const
constexpr coord_type GetRight() const
constexpr coord_type GetTop() const
constexpr coord_type GetBottom() const
void Add(OBJECT_2D *aObject)
A dummy block defined by a 2d box size.
bool Intersect(const RAYSEG2D &aSegRay, float *aOutT, SFVEC2F *aNormalOut) const override
bool IsPointInside(const SFVEC2F &aPoint) const override
bool Intersects(const BBOX_2D &aBBox) const override
a.Intersects(b) ⇔ !a.Disjoint(b) ⇔ !(a ∩ b = ∅)
bool Overlaps(const BBOX_2D &aBBox) const override
Test if the box overlaps the object.
INTERSECTION_RESULT IsBBoxInside(const BBOX_2D &aBBox) const override
Test this object if it's completely outside, intersects, or is completely inside aBBox.
DUMMY_BLOCK_2D(const SFVEC2F &aPbMin, const SFVEC2F &aPbMax, const BOARD_ITEM &aBoardItem)
Represent a sub polygon block.
OUTERS_AND_HOLES m_outers_and_holes
bool Intersects(const BBOX_2D &aBBox) const override
a.Intersects(b) ⇔ !a.Disjoint(b) ⇔ !(a ∩ b = ∅)
INTERSECTION_RESULT IsBBoxInside(const BBOX_2D &aBBox) const override
Test this object if it's completely outside, intersects, or is completely inside aBBox.
bool Intersect(const RAYSEG2D &aSegRay, float *aOutT, SFVEC2F *aNormalOut) const override
bool IsPointInside(const SFVEC2F &aPoint) const override
POLYGON_2D(const SEGMENTS_WIDTH_NORMALS &aOpenSegmentList, const OUTERS_AND_HOLES &aOuterAndHoles, const BOARD_ITEM &aBoardItem)
SEGMENTS_WIDTH_NORMALS m_open_segments
The outer part of the polygon.
bool Overlaps(const BBOX_2D &aBBox) const override
Test if the box overlaps the object.
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.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
Represent a set of closed polygons.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
void BooleanIntersection(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset intersection For aFastMode meaning, see function booleanOp.
int HoleCount(int aOutline) const
Returns the number of holes in a given outline.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
SHAPE_LINE_CHAIN & Hole(int aOutline, int aHole)
Return the reference to aHole-th hole in the aIndex-th outline.
int OutlineCount() const
Return the number of outlines in the set.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
void ConvertPolygonToBlocks(const SHAPE_POLY_SET &aMainPath, CONTAINER_2D_BASE &aDstContainer, float aBiuTo3dUnitsScale, float aDivFactor, const BOARD_ITEM &aBoardItem, int aPolyIndex)
Use a polygon in the format of the ClipperLib::Path and process it and create multiple 2d objects (PO...
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)
std::vector< SFVEC2F > KF_POINTS
static bool polygon_IsPointInside(const SEGMENTS &aSegments, const SFVEC2F &aPoint)
static bool intersect(const SEGMENT_WITH_NORMALS &aSeg, const SFVEC2F &aStart, const SFVEC2F &aEnd)
std::vector< SEGMENT_WITH_NORMALS > SEGMENTS_WIDTH_NORMALS
List used to test ray2d intersections.
std::vector< POLYSEGMENT > SEGMENTS
void Polygon2d_TestModule()
Manage a bounding box defined by two SFVEC2F min max points.
SFVEC2F GetCenter() const
bool Intersects(const BBOX_2D &aBBox) const
Test if a bounding box intersects this box.
SFVEC2F GetExtent() const
void Union(const SFVEC2F &aPoint)
Recalculate the bounding box adding a point.
bool IsInitialized() const
Check if this bounding box is already initialized.
const SFVEC2F & Min() const
bool Inside(const SFVEC2F &aPoint) const
Check is a point is inside this bounding box.
void Reset()
Reset the bounding box to zero and uninitialize it.
const SFVEC2F & Max() const
void Set(const SFVEC2F &aPbMin, const SFVEC2F &aPbMax)
Set bounding box with new parameters.
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
SFVEC2F m_End_minus_start
VECTOR2< int32_t > VECTOR2I