KiCad PCB EDA Suite
Loading...
Searching...
No Matches
polygon_2d.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2015-2016 Mario Luzeiro <[email protected]>
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
24
25#include "polygon_2d.h"
26#include "../ray.h"
27#include <wx/debug.h>
28
29
30static bool polygon_IsPointInside( const SEGMENTS& aSegments, const SFVEC2F& aPoint )
31{
32 wxASSERT( aSegments.size() >= 3 );
33
34 unsigned int i;
35 unsigned int j = aSegments.size() - 1;
36 bool oddNodes = false;
37
38 for( i = 0; i < aSegments.size(); j = i++ )
39 {
40 const float polyJY = aSegments[j].m_Start.y;
41 const float polyIY = aSegments[i].m_Start.y;
42
43 if( ( ( polyIY <= aPoint.y ) && ( polyJY >= aPoint.y ) )
44 || ( ( polyJY <= aPoint.y ) && ( polyIY >= aPoint.y ) ) )
45 {
46 const float polyJX = aSegments[j].m_Start.x;
47 const float polyIX = aSegments[i].m_Start.x;
48
49 if( ( polyIX <= aPoint.x ) || ( polyJX <= aPoint.x ) )
50 oddNodes ^= ( ( polyIX + ( ( aPoint.y - polyIY ) * aSegments[i].m_inv_JY_minus_IY )
51 * aSegments[i].m_JX_minus_IX )
52 < aPoint.x );
53 }
54 }
55
56 return oddNodes;
57}
58
59
61 const OUTERS_AND_HOLES& aOuterAndHoles, const BOARD_ITEM& aBoardItem )
62 : OBJECT_2D( OBJECT_2D_TYPE::POLYGON, aBoardItem )
63{
64 m_open_segments.resize( aOpenSegmentList.size() );
65
66 // Copy vectors and structures
67 for( unsigned int i = 0; i < aOpenSegmentList.size(); i++ )
68 m_open_segments[i] = aOpenSegmentList[i];
69
70 m_outers_and_holes = aOuterAndHoles;
71
72 // Compute bounding box with the points of the polygon
73 m_bbox.Reset();
74
75 for( unsigned int i = 0; i < m_outers_and_holes.m_Outers.size(); i++ )
76 {
77 for( unsigned int j = 0; j < m_outers_and_holes.m_Outers[i].size(); j++ )
78 m_bbox.Union( ( (SEGMENTS) m_outers_and_holes.m_Outers[i] )[j].m_Start );
79 }
80
81 m_bbox.ScaleNextUp();
82 m_centroid = m_bbox.GetCenter();
83
84 // Some checks
85 wxASSERT( m_open_segments.size() == aOpenSegmentList.size() );
86 wxASSERT( m_open_segments.size() > 0 );
87
88 wxASSERT( m_outers_and_holes.m_Outers.size() > 0 );
89 wxASSERT( m_outers_and_holes.m_Outers.size() == aOuterAndHoles.m_Outers.size() );
90 wxASSERT( m_outers_and_holes.m_Holes.size() == aOuterAndHoles.m_Holes.size() );
91
92 wxASSERT( m_outers_and_holes.m_Outers[0].size() >= 3 );
93 wxASSERT( m_outers_and_holes.m_Outers[0].size() == aOuterAndHoles.m_Outers[0].size() );
94
95 wxASSERT( m_bbox.IsInitialized() );
96}
97
98
99bool POLYGON_2D::Intersects( const BBOX_2D& aBBox ) const
100{
101 return m_bbox.Intersects( aBBox );
102
103 // !TODO: this is a quick not perfect implementation
104 // in order to make it perfect the box must be checked against all the
105 // polygons in the outers and not inside the holes
106}
107
108
109bool POLYGON_2D::Overlaps( const BBOX_2D& aBBox ) const
110{
111 // NOT IMPLEMENTED, why?
112 return false;
113}
114
115
116bool POLYGON_2D::Intersect( const RAYSEG2D& aSegRay, float* aOutT, SFVEC2F* aNormalOut ) const
117{
118 int hitIndex = -1;
119 float hitU = 0.0f;
120 float tMin = 0.0f;
121
122 for( unsigned int i = 0; i < m_open_segments.size(); i++ )
123 {
124 const SFVEC2F& s = m_open_segments[i].m_Precalc_slope;
125 const SFVEC2F& q = m_open_segments[i].m_Start;
126
127 float rxs = aSegRay.m_End_minus_start.x * s.y - aSegRay.m_End_minus_start.y * s.x;
128
129 if( fabs( rxs ) > FLT_EPSILON )
130 {
131 const float inv_rxs = 1.0f / rxs;
132
133 const SFVEC2F pq = q - aSegRay.m_Start;
134
135 const float t = ( pq.x * s.y - pq.y * s.x ) * inv_rxs;
136
137 if( ( t < 0.0f ) || ( t > 1.0f ) )
138 continue;
139
140 const float u =
141 ( pq.x * aSegRay.m_End_minus_start.y - pq.y * aSegRay.m_End_minus_start.x )
142 * inv_rxs;
143
144 if( ( u < 0.0f ) || ( u > 1.0f ) )
145 continue;
146
147 if( ( hitIndex == -1 ) || ( t <= tMin ) )
148 {
149 tMin = t;
150 hitIndex = i;
151 hitU = u;
152 }
153 }
154 }
155
156 if( hitIndex >= 0 )
157 {
158 wxASSERT( ( tMin >= 0.0f ) && ( tMin <= 1.0f ) );
159
160 if( aOutT )
161 *aOutT = tMin;
162
163 if( aNormalOut )
164 *aNormalOut = glm::normalize( m_open_segments[hitIndex].m_Normals.m_Start * hitU +
165 m_open_segments[hitIndex].m_Normals.m_End *
166 ( 1.0f - hitU ) );
167
168 return true;
169 }
170
171 return false;
172}
173
174
180
181
182bool POLYGON_2D::IsPointInside( const SFVEC2F& aPoint ) const
183{
184 // NOTE: we could add here a test for the bounding box, but because in the
185 // 3d object it already checked for a 3d bbox.
186
187 // First test if point is inside a hole.
188 // If true it can early exit
189 for( unsigned int i = 0; i < m_outers_and_holes.m_Holes.size(); i++ )
190 if( !m_outers_and_holes.m_Holes[i].empty() )
191 if( polygon_IsPointInside( m_outers_and_holes.m_Holes[i], aPoint ) )
192 return false;
193
194 // At this moment, the point is not inside a hole, so check if it is
195 // inside the polygon
196 for( unsigned int i = 0; i < m_outers_and_holes.m_Outers.size(); i++ )
197 if( !m_outers_and_holes.m_Outers[i].empty() )
198 if( polygon_IsPointInside( m_outers_and_holes.m_Outers[i], aPoint ) )
199 return true;
200
201 // Miss the polygon
202 return false;
203}
204
205
206DUMMY_BLOCK_2D::DUMMY_BLOCK_2D( const SFVEC2F& aPbMin, const SFVEC2F& aPbMax,
207 const BOARD_ITEM& aBoardItem )
208 : OBJECT_2D( OBJECT_2D_TYPE::DUMMYBLOCK, aBoardItem )
209{
210 m_bbox.Set( aPbMin, aPbMax );
211 m_bbox.ScaleNextUp();
212 m_centroid = m_bbox.GetCenter();
213}
214
215
216DUMMY_BLOCK_2D::DUMMY_BLOCK_2D( const BBOX_2D& aBBox, const BOARD_ITEM& aBoardItem )
217 : OBJECT_2D( OBJECT_2D_TYPE::DUMMYBLOCK, aBoardItem )
218{
219 m_bbox.Set( aBBox );
220 m_bbox.ScaleNextUp();
221 m_centroid = m_bbox.GetCenter();
222}
223
224
225bool DUMMY_BLOCK_2D::Intersects( const BBOX_2D& aBBox ) const
226{
227 return m_bbox.Intersects( aBBox );
228}
229
230
231bool DUMMY_BLOCK_2D::Overlaps( const BBOX_2D& aBBox ) const
232{
233 // Not implemented
234 return false;
235}
236
237
238bool DUMMY_BLOCK_2D::Intersect( const RAYSEG2D& aSegRay, float* aOutT, SFVEC2F* aNormalOut ) const
239{
240 // The dummy block will be never intersected because it have no edges,
241 // only it have a plan surface of the size of the bounding box
242 return false;
243}
244
245
251
252
253bool DUMMY_BLOCK_2D::IsPointInside( const SFVEC2F& aPoint ) const
254{
255 // The dummy is filled in all his bounding box, so if it hit the bbox
256 // it will hit this dummy
257 if( m_bbox.Inside( aPoint ) )
258 return true;
259
260 return false;
261}
262
263
264typedef std::vector<SFVEC2F> KF_POINTS;
265
266#define MAX_NR_DIVISIONS 96
267
268
269static bool intersect( const SEGMENT_WITH_NORMALS& aSeg, const SFVEC2F& aStart,
270 const SFVEC2F& aEnd )
271{
272 const SFVEC2F r = aEnd - aStart;
273 const SFVEC2F s = aSeg.m_Precalc_slope;
274 const SFVEC2F q = aSeg.m_Start;
275
276 const float rxs = r.x * s.y - r.y * s.x;
277
278 if( fabs( rxs ) > glm::epsilon<float>() )
279 {
280 const float inv_rxs = 1.0f / rxs;
281
282 const SFVEC2F pq = q - aStart;
283
284 const float t = ( pq.x * s.y - pq.y * s.x ) * inv_rxs;
285
286 if( ( t < 0.0f ) || ( t > 1.0f ) )
287 return false;
288
289 const float u = ( pq.x * r.y - pq.y * r.x ) * inv_rxs;
290
291 if( ( u < 0.0f ) || ( u > 1.0f ) )
292 return false;
293
294 return true;
295 }
296
297 return false;
298}
299
300
301static void extractPathsFrom( const SEGMENTS_WIDTH_NORMALS& aSegList, const BBOX_2D& aBBox,
302 SEGMENTS_WIDTH_NORMALS& aOutSegThatIntersect )
303{
304 wxASSERT( aSegList.size() >= 3 );
305
306 unsigned int i;
307 unsigned int j = aSegList.size() - 1;
308
309 const SFVEC2F p1( aBBox.Min().x, aBBox.Min().y );
310 const SFVEC2F p2( aBBox.Max().x, aBBox.Min().y );
311 const SFVEC2F p3( aBBox.Max().x, aBBox.Max().y );
312 const SFVEC2F p4( aBBox.Min().x, aBBox.Max().y );
313
314 aOutSegThatIntersect.clear();
315
316 for( i = 0; i < aSegList.size(); j = i++ )
317 {
318 if( aBBox.Inside( aSegList[i].m_Start ) || aBBox.Inside( aSegList[j].m_Start ) )
319 {
320 // if the segment points are inside the bounding box then this
321 // segment is touching the bbox.
322 aOutSegThatIntersect.push_back( aSegList[i] );
323 }
324 else
325 {
326 // Check if a segment intersects the bounding box
327
328 // Make a bounding box based on the segments start and end
329 BBOX_2D segmentBBox( aSegList[i].m_Start, aSegList[j].m_Start );
330
331 if( aBBox.Intersects( segmentBBox ) )
332 {
333
334 const SEGMENT_WITH_NORMALS& seg = aSegList[i];
335
336 if( intersect( seg, p1, p2 ) || intersect( seg, p2, p3 ) || intersect( seg, p3, p4 )
337 || intersect( seg, p4, p1 ) )
338 {
339 aOutSegThatIntersect.push_back( seg );
340 }
341 }
342 }
343 }
344}
345
346
347static void polygon_Convert( const SHAPE_LINE_CHAIN& aPath, SEGMENTS& aOutSegment,
348 float aBiuTo3dUnitsScale )
349{
350 aOutSegment.resize( aPath.PointCount() );
351
352 for( int j = 0; j < aPath.PointCount(); j++ )
353 {
354 const VECTOR2I& a = aPath.CPoint( j );
355
356 aOutSegment[j].m_Start = SFVEC2F( (float) a.x * aBiuTo3dUnitsScale,
357 (float) -a.y * aBiuTo3dUnitsScale );
358 }
359
360 unsigned int i;
361 unsigned int j = aOutSegment.size() - 1;
362
363 for( i = 0; i < aOutSegment.size(); j = i++ )
364 {
365 // Calculate constants for each segment
366 aOutSegment[i].m_inv_JY_minus_IY = 1.0f /
367 ( aOutSegment[j].m_Start.y - aOutSegment[i].m_Start.y );
368
369 aOutSegment[i].m_JX_minus_IX = ( aOutSegment[j].m_Start.x - aOutSegment[i].m_Start.x );
370 }
371}
372
373
374void ConvertPolygonToBlocks( const SHAPE_POLY_SET& aMainPath, CONTAINER_2D_BASE& aDstContainer,
375 float aBiuTo3dUnitsScale, float aDivFactor,
376 const BOARD_ITEM& aBoardItem, int aPolyIndex )
377{
378 // Get the path
379 wxASSERT( aPolyIndex < aMainPath.OutlineCount() );
380
381 const SHAPE_LINE_CHAIN& path = aMainPath.COutline( aPolyIndex );
382
383 BOX2I pathBounds = path.BBox();
384
385 // Convert the points to segments class
386 BBOX_2D bbox;
387 bbox.Reset();
388
389 // Contains the main list of segments and each segment normal interpolated
390 SEGMENTS_WIDTH_NORMALS segments_and_normals;
391
392 // Contains a closed polygon used to calc if points are inside
393 SEGMENTS segments;
394
395 segments_and_normals.reserve( path.PointCount() );
396 segments.reserve( path.PointCount() );
397
398 SFVEC2F prevPoint;
399
400 for( int i = 0; i < path.PointCount(); i++ )
401 {
402 const VECTOR2I& a = path.CPoint( i );
403
404 const SFVEC2F point( (float) ( a.x ) * aBiuTo3dUnitsScale,
405 (float) ( -a.y ) * aBiuTo3dUnitsScale );
406
407 // Only add points that are not coincident
408 if( ( i == 0 ) || ( fabs( prevPoint.x - point.x ) > FLT_EPSILON )
409 || ( fabs( prevPoint.y - point.y ) > FLT_EPSILON ) )
410 {
411 prevPoint = point;
412
413 bbox.Union( point );
414
416 sn.m_Start = point;
417 segments_and_normals.push_back( sn );
418
419 POLYSEGMENT ps;
420 ps.m_Start = point;
421 segments.push_back( ps );
422 }
423 }
424
425 bbox.ScaleNextUp();
426
427 // Calc the slopes, normals and some statistics about this polygon
428 unsigned int i;
429 unsigned int j = segments_and_normals.size() - 1;
430
431 // Temporary normal to the segment, it will later be used for interpolation
432 std::vector<SFVEC2F> tmpSegmentNormals;
433 tmpSegmentNormals.resize( segments_and_normals.size() );
434
435 float medOfTheSquaresSegmentLength = 0.0f;
436
437#ifdef PRINT_STATISTICS_3D_VIEWER
438 float minLength = FLT_MAX;
439#endif
440
441 for( i = 0; i < segments_and_normals.size(); j = i++ )
442 {
443 const SFVEC2F slope = segments_and_normals[j].m_Start - segments_and_normals[i].m_Start;
444
445 segments_and_normals[i].m_Precalc_slope = slope;
446
447 // Calculate constants for each segment
448 segments[i].m_inv_JY_minus_IY =
449 1.0f / ( segments_and_normals[j].m_Start.y - segments_and_normals[i].m_Start.y );
450
451 segments[i].m_JX_minus_IX =
452 ( segments_and_normals[j].m_Start.x - segments_and_normals[i].m_Start.x );
453
454 // The normal orientation expect a fixed polygon orientation (!TODO: which one?)
455 //tmpSegmentNormals[i] = glm::normalize( SFVEC2F( -slope.y, +slope.x ) );
456 tmpSegmentNormals[i] = glm::normalize( SFVEC2F( slope.y, -slope.x ) );
457
458 const float length = slope.x * slope.x + slope.y * slope.y;
459
460#ifdef PRINT_STATISTICS_3D_VIEWER
461 if( length < minLength )
462 minLength = length;
463#endif
464
465 medOfTheSquaresSegmentLength += length;
466 }
467
468#ifdef PRINT_STATISTICS_3D_VIEWER
469 float minSegmentLength = sqrt( minLength );
470#endif
471
472 // This calc an approximation of medium lengths, that will be used to calc
473 // the size of the division.
474 medOfTheSquaresSegmentLength /= segments_and_normals.size();
475 medOfTheSquaresSegmentLength = sqrt( medOfTheSquaresSegmentLength );
476
477 // Compute the normal interpolation
478 // If calculate the dot between the segments, if they are above/below some
479 // threshold it will not interpolated it (ex: if you are in a edge corner
480 // or in a smooth transaction)
481 j = segments_and_normals.size() - 1;
482
483 for( i = 0; i < segments_and_normals.size(); j = i++ )
484 {
485 const SFVEC2F normalBeforeSeg = tmpSegmentNormals[j];
486 const SFVEC2F normalSeg = tmpSegmentNormals[i];
487 const SFVEC2F normalAfterSeg = tmpSegmentNormals[( i + 1 ) % segments_and_normals.size()];
488
489 const float dotBefore = glm::dot( normalBeforeSeg, normalSeg );
490 const float dotAfter = glm::dot( normalAfterSeg, normalSeg );
491
492 if( dotBefore < 0.7f )
493 segments_and_normals[i].m_Normals.m_Start = normalSeg;
494 else
495 segments_and_normals[i].m_Normals.m_Start =
496 glm::normalize( ( normalBeforeSeg * dotBefore ) + normalSeg );
497
498 if( dotAfter < 0.7f )
499 segments_and_normals[i].m_Normals.m_End = normalSeg;
500 else
501 segments_and_normals[i].m_Normals.m_End =
502 glm::normalize( ( normalAfterSeg * dotAfter ) + normalSeg );
503 }
504
505 SFVEC2UI grid_divisions;
506
507 if( aDivFactor < 0.0f )
508 {
509 grid_divisions = SFVEC2UI( 1 );
510 }
511 else
512 {
513 if( aDivFactor <= FLT_EPSILON )
514 aDivFactor = medOfTheSquaresSegmentLength;
515
516 grid_divisions.x = (unsigned int) ( ( bbox.GetExtent().x / aDivFactor ) );
517 grid_divisions.y = (unsigned int) ( ( bbox.GetExtent().y / aDivFactor ) );
518
519 grid_divisions = glm::clamp(
520 grid_divisions, SFVEC2UI( 1, 1 ), SFVEC2UI( MAX_NR_DIVISIONS, MAX_NR_DIVISIONS ) );
521 }
522
523 // Calculate the steps advance of the grid
524 SFVEC2F blockAdvance;
525
526 blockAdvance.x = bbox.GetExtent().x / (float) grid_divisions.x;
527 blockAdvance.y = bbox.GetExtent().y / (float) grid_divisions.y;
528
529 wxASSERT( blockAdvance.x > 0.0f );
530 wxASSERT( blockAdvance.y > 0.0f );
531
532 const int leftToRight_inc = ( pathBounds.GetRight() - pathBounds.GetLeft() ) / grid_divisions.x;
533
534 const int topToBottom_inc = ( pathBounds.GetBottom() - pathBounds.GetTop() ) / grid_divisions.y;
535
536 // Statistics
537 unsigned int stats_n_empty_blocks = 0;
538 unsigned int stats_n_dummy_blocks = 0;
539 unsigned int stats_n_poly_blocks = 0;
540 unsigned int stats_sum_size_of_polygons = 0;
541
542 // Step by each block of a grid trying to extract segments and create polygon blocks
543 int topToBottom = pathBounds.GetTop();
544 float blockY = bbox.Max().y;
545
546 for( unsigned int iy = 0; iy < grid_divisions.y; iy++ )
547 {
548 int leftToRight = pathBounds.GetLeft();
549 float blockX = bbox.Min().x;
550
551 for( unsigned int ix = 0; ix < grid_divisions.x; ix++ )
552 {
553 BBOX_2D blockBox( SFVEC2F( blockX, blockY - blockAdvance.y ),
554 SFVEC2F( blockX + blockAdvance.x, blockY ) );
555
556 // Make the box large to it will catch (intersect) the edges
557 blockBox.ScaleNextUp();
558 blockBox.ScaleNextUp();
559 blockBox.ScaleNextUp();
560
561 SEGMENTS_WIDTH_NORMALS extractedSegments;
562
563 extractPathsFrom( segments_and_normals, blockBox, extractedSegments );
564
565 if( extractedSegments.empty() )
566 {
567
568 SFVEC2F p1( blockBox.Min().x, blockBox.Min().y );
569 SFVEC2F p2( blockBox.Max().x, blockBox.Min().y );
570 SFVEC2F p3( blockBox.Max().x, blockBox.Max().y );
571 SFVEC2F p4( blockBox.Min().x, blockBox.Max().y );
572
573 if( polygon_IsPointInside( segments, p1 ) || polygon_IsPointInside( segments, p2 )
574 || polygon_IsPointInside( segments, p3 )
575 || polygon_IsPointInside( segments, p4 ) )
576 {
577 // In this case, the segments are not intersecting the
578 // polygon, so it means that if any point is inside it,
579 // then all other are inside the polygon.
580 // This is a full bbox inside, so add a dummy box
581 aDstContainer.Add( new DUMMY_BLOCK_2D( blockBox, aBoardItem ) );
582 stats_n_dummy_blocks++;
583 }
584 else
585 {
586 // Points are outside, so this block completely missed the polygon
587 // In this case, no objects need to be added
588 stats_n_empty_blocks++;
589 }
590 }
591 else
592 {
593 // At this point, the borders of polygon were intersected by the
594 // bounding box, so we must calculate a new polygon that will
595 // close that small block.
596 // This block will be used to calculate if points are inside
597 // the (sub block) polygon.
598
599 SHAPE_POLY_SET subBlockPoly;
600
601 SHAPE_LINE_CHAIN sb = SHAPE_LINE_CHAIN( { VECTOR2I( leftToRight, topToBottom ),
602 VECTOR2I( leftToRight + leftToRight_inc, topToBottom ),
603 VECTOR2I( leftToRight + leftToRight_inc, topToBottom + topToBottom_inc ),
604 VECTOR2I( leftToRight, topToBottom + topToBottom_inc ) } );
605
606 //sb.Append( leftToRight, topToBottom );
607 sb.SetClosed( true );
608
609 subBlockPoly.AddOutline( sb );
610
611 // We need here a simple polygon with outlines and holes
612 SHAPE_POLY_SET solution;
613 solution.BooleanIntersection( aMainPath, subBlockPoly );
614
615 OUTERS_AND_HOLES outersAndHoles;
616
617 outersAndHoles.m_Holes.clear();
618 outersAndHoles.m_Outers.clear();
619
620 for( int idx = 0; idx < solution.OutlineCount(); idx++ )
621 {
622 const SHAPE_LINE_CHAIN& outline = solution.Outline( idx );
623
624 SEGMENTS solutionSegment;
625
626 polygon_Convert( outline, solutionSegment, aBiuTo3dUnitsScale );
627 outersAndHoles.m_Outers.push_back( solutionSegment );
628
629 stats_sum_size_of_polygons += solutionSegment.size();
630
631 for( int holeIdx = 0; holeIdx < solution.HoleCount( idx ); holeIdx++ )
632 {
633 const SHAPE_LINE_CHAIN& hole = solution.Hole( idx, holeIdx );
634
635 polygon_Convert( hole, solutionSegment, aBiuTo3dUnitsScale );
636 outersAndHoles.m_Holes.push_back( solutionSegment );
637 stats_sum_size_of_polygons += solutionSegment.size();
638 }
639 }
640
641 if( !outersAndHoles.m_Outers.empty() )
642 {
643 aDstContainer.Add( new POLYGON_2D( extractedSegments, outersAndHoles,
644 aBoardItem ) );
645 stats_n_poly_blocks++;
646 }
647 }
648
649 blockX += blockAdvance.x;
650 leftToRight += leftToRight_inc;
651 }
652
653 blockY -= blockAdvance.y;
654 topToBottom += topToBottom_inc;
655 }
656}
BOX2< VECTOR2I > BOX2I
Definition box2.h:918
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:81
constexpr coord_type GetLeft() const
Definition box2.h:224
constexpr coord_type GetRight() const
Definition box2.h:213
constexpr coord_type GetTop() const
Definition box2.h:225
constexpr coord_type GetBottom() const
Definition box2.h:218
void Add(OBJECT_2D *aObject)
A dummy block defined by a 2d box size.
Definition polygon_2d.h:123
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)
BBOX_2D m_bbox
Definition object_2d.h:106
SFVEC2F m_centroid
Definition object_2d.h:107
OBJECT_2D(OBJECT_2D_TYPE aObjType, const BOARD_ITEM &aBoardItem)
Definition object_2d.cpp:27
Represent a sub polygon block.
Definition polygon_2d.h:90
OUTERS_AND_HOLES m_outers_and_holes
Definition polygon_2d.h:111
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.
Definition polygon_2d.h:108
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.
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.
void BooleanIntersection(const SHAPE_POLY_SET &b)
Perform boolean polyset intersection.
int OutlineCount() const
Return the number of outlines in the set.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
OBJECT_2D_TYPE
Definition object_2d.h:41
INTERSECTION_RESULT
Definition object_2d.h:33
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...
#define MAX_NR_DIVISIONS
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.
Definition polygon_2d.h:65
std::vector< POLYSEGMENT > SEGMENTS
Definition polygon_2d.h:57
Manage a bounding box defined by two SFVEC2F min max points.
Definition bbox_2d.h:38
bool Intersects(const BBOX_2D &aBBox) const
Test if a bounding box intersects this box.
Definition bbox_2d.cpp:207
SFVEC2F GetExtent() const
Definition bbox_2d.cpp:121
void Union(const SFVEC2F &aPoint)
Recalculate the bounding box adding a point.
Definition bbox_2d.cpp:89
const SFVEC2F & Min() const
Definition bbox_2d.h:171
bool Inside(const SFVEC2F &aPoint) const
Check is a point is inside this bounding box.
Definition bbox_2d.cpp:219
void Reset()
Reset the bounding box to zero and uninitialize it.
Definition bbox_2d.cpp:82
const SFVEC2F & Max() const
Definition bbox_2d.h:176
void ScaleNextUp()
Scale a bounding box to the next float representation making it larger.
Definition bbox_2d.cpp:158
Handle a subset of a polygon.
Definition polygon_2d.h:75
std::vector< SEGMENTS > m_Holes
Definition polygon_2d.h:77
std::vector< SEGMENTS > m_Outers
Definition polygon_2d.h:76
SFVEC2F m_Start
Definition polygon_2d.h:36
SFVEC2F m_End_minus_start
Definition ray.h:105
SFVEC2F m_Start
Definition ray.h:103
std::string path
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683
glm::vec2 SFVEC2F
Definition xv3d_types.h:38
glm::uvec2 SFVEC2UI
Definition xv3d_types.h:34