You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1194 lines
46 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2015-2017 CERN
  5. * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
  6. * @author Alejandro García Montoro <alejandro.garciamontoro@gmail.com>
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version 2
  11. * of the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, you may find one here:
  20. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  21. * or you may search the http://www.gnu.org website for the version 2 license,
  22. * or you may write to the Free Software Foundation, Inc.,
  23. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  24. */
  25. #ifndef __SHAPE_POLY_SET_H
  26. #define __SHAPE_POLY_SET_H
  27. #include <vector>
  28. #include <cstdio>
  29. #include <memory>
  30. #include <geometry/shape.h>
  31. #include <geometry/shape_line_chain.h>
  32. #include "clipper.hpp"
  33. #include <md5_hash.h>
  34. /**
  35. * Class SHAPE_POLY_SET
  36. *
  37. * Represents a set of closed polygons. Polygons may be nonconvex, self-intersecting
  38. * and have holes. Provides boolean operations (using Clipper library as the backend).
  39. *
  40. * Let us define the terms used on this class to clarify methods names and comments:
  41. * - Polygon: each polygon in the set.
  42. * - Outline: first polyline in each polygon; represents its outer contour.
  43. * - Hole: second and following polylines in the polygon.
  44. * - Contour: each polyline of each polygon in the set, whether or not it is an
  45. * outline or a hole.
  46. * - Vertex (or corner): each one of the points that define a contour.
  47. *
  48. * TODO: add convex partitioning & spatial index
  49. */
  50. class SHAPE_POLY_SET : public SHAPE
  51. {
  52. public:
  53. ///> represents a single polygon outline with holes. The first entry is the outline,
  54. ///> the remaining (if any), are the holes
  55. ///> N.B. SWIG only supports typedef, so avoid c++ 'using' keyword
  56. typedef std::vector<SHAPE_LINE_CHAIN> POLYGON;
  57. class TRIANGULATED_POLYGON
  58. {
  59. public:
  60. struct TRI
  61. {
  62. TRI( int _a = 0, int _b = 0, int _c = 0 ) : a( _a ), b( _b ), c( _c )
  63. {
  64. }
  65. int a, b, c;
  66. };
  67. void Clear()
  68. {
  69. m_vertices.clear();
  70. m_triangles.clear();
  71. }
  72. void GetTriangle( int index, VECTOR2I& a, VECTOR2I& b, VECTOR2I& c ) const
  73. {
  74. auto tri = m_triangles[ index ];
  75. a = m_vertices[ tri.a ];
  76. b = m_vertices[ tri.b ];
  77. c = m_vertices[ tri.c ];
  78. }
  79. void AddTriangle( const TRI& aTri )
  80. {
  81. m_triangles.push_back( aTri );
  82. }
  83. void AddTriangle( int a, int b, int c )
  84. {
  85. m_triangles.emplace_back( a, b, c );
  86. }
  87. void AddVertex( const VECTOR2I& aP )
  88. {
  89. m_vertices.push_back( aP );
  90. }
  91. size_t GetTriangleCount() const
  92. {
  93. return m_triangles.size();
  94. }
  95. size_t GetVertexCount() const
  96. {
  97. return m_vertices.size();
  98. }
  99. private:
  100. std::deque<TRI> m_triangles;
  101. std::deque<VECTOR2I> m_vertices;
  102. };
  103. /**
  104. * Struct VERTEX_INDEX
  105. *
  106. * Structure to hold the necessary information in order to index a vertex on a
  107. * SHAPE_POLY_SET object: the polygon index, the contour index relative to the polygon and
  108. * the vertex index relative the contour.
  109. */
  110. typedef struct VERTEX_INDEX
  111. {
  112. int m_polygon; /*!< m_polygon is the index of the polygon. */
  113. int m_contour; /*!< m_contour is the index of the contour relative to the polygon. */
  114. int m_vertex; /*!< m_vertex is the index of the vertex relative to the contour. */
  115. VERTEX_INDEX() : m_polygon(-1), m_contour(-1), m_vertex(-1)
  116. {
  117. }
  118. } VERTEX_INDEX;
  119. /**
  120. * Class ITERATOR_TEMPLATE
  121. *
  122. * Base class for iterating over all vertices in a given SHAPE_POLY_SET.
  123. */
  124. template <class T>
  125. class ITERATOR_TEMPLATE
  126. {
  127. public:
  128. /**
  129. * Function IsEndContour.
  130. * @return bool - true if the current vertex is the last one of the current contour
  131. * (outline or hole); false otherwise.
  132. */
  133. bool IsEndContour() const
  134. {
  135. return m_currentVertex + 1 == m_poly->CPolygon( m_currentPolygon )[m_currentContour].PointCount();
  136. }
  137. /**
  138. * Function IsLastOutline.
  139. * @return bool - true if the current outline is the last one; false otherwise.
  140. */
  141. bool IsLastPolygon() const
  142. {
  143. return m_currentPolygon == m_lastPolygon;
  144. }
  145. operator bool() const
  146. {
  147. return m_currentPolygon <= m_lastPolygon;
  148. }
  149. /**
  150. * Function Advance
  151. * advances the indices of the current vertex/outline/contour, checking whether the
  152. * vertices in the holes have to be iterated through
  153. */
  154. void Advance()
  155. {
  156. // Advance vertex index
  157. m_currentVertex ++;
  158. // Check whether the user wants to iterate through the vertices of the holes
  159. // and behave accordingly
  160. if( m_iterateHoles )
  161. {
  162. // If the last vertex of the contour was reached, advance the contour index
  163. if( m_currentVertex >= m_poly->CPolygon( m_currentPolygon )[m_currentContour].PointCount() )
  164. {
  165. m_currentVertex = 0;
  166. m_currentContour++;
  167. // If the last contour of the current polygon was reached, advance the
  168. // outline index
  169. int totalContours = m_poly->CPolygon( m_currentPolygon ).size();
  170. if( m_currentContour >= totalContours )
  171. {
  172. m_currentContour = 0;
  173. m_currentPolygon++;
  174. }
  175. }
  176. }
  177. else
  178. {
  179. // If the last vertex of the outline was reached, advance to the following polygon
  180. if( m_currentVertex >= m_poly->CPolygon( m_currentPolygon )[0].PointCount() )
  181. {
  182. m_currentVertex = 0;
  183. m_currentPolygon++;
  184. }
  185. }
  186. }
  187. void operator++( int dummy )
  188. {
  189. Advance();
  190. }
  191. void operator++()
  192. {
  193. Advance();
  194. }
  195. T& Get()
  196. {
  197. return m_poly->Polygon( m_currentPolygon )[m_currentContour].Point( m_currentVertex );
  198. }
  199. T& operator*()
  200. {
  201. return Get();
  202. }
  203. T* operator->()
  204. {
  205. return &Get();
  206. }
  207. /**
  208. * Function GetIndex
  209. * @return VERTEX_INDEX - indices of the current polygon, contour and vertex.
  210. */
  211. VERTEX_INDEX GetIndex()
  212. {
  213. VERTEX_INDEX index;
  214. index.m_polygon = m_currentPolygon;
  215. index.m_contour = m_currentContour;
  216. index.m_vertex = m_currentVertex;
  217. return index;
  218. }
  219. private:
  220. friend class SHAPE_POLY_SET;
  221. SHAPE_POLY_SET* m_poly;
  222. int m_currentPolygon;
  223. int m_currentContour;
  224. int m_currentVertex;
  225. int m_lastPolygon;
  226. bool m_iterateHoles;
  227. };
  228. /**
  229. * Class SEGMENT_ITERATOR_TEMPLATE
  230. *
  231. * Base class for iterating over all segments in a given SHAPE_POLY_SET.
  232. */
  233. template <class T>
  234. class SEGMENT_ITERATOR_TEMPLATE
  235. {
  236. public:
  237. /**
  238. * Function IsLastOutline.
  239. * @return bool - true if the current outline is the last one.
  240. */
  241. bool IsLastPolygon() const
  242. {
  243. return m_currentPolygon == m_lastPolygon;
  244. }
  245. operator bool() const
  246. {
  247. return m_currentPolygon <= m_lastPolygon;
  248. }
  249. /**
  250. * Function Advance
  251. * advances the indices of the current vertex/outline/contour, checking whether the
  252. * vertices in the holes have to be iterated through
  253. */
  254. void Advance()
  255. {
  256. // Advance vertex index
  257. m_currentSegment++;
  258. int last;
  259. // Check whether the user wants to iterate through the vertices of the holes
  260. // and behave accordingly
  261. if( m_iterateHoles )
  262. {
  263. last = m_poly->CPolygon( m_currentPolygon )[m_currentContour].SegmentCount();
  264. // If the last vertex of the contour was reached, advance the contour index
  265. if( m_currentSegment >= last )
  266. {
  267. m_currentSegment = 0;
  268. m_currentContour++;
  269. // If the last contour of the current polygon was reached, advance the
  270. // outline index
  271. int totalContours = m_poly->CPolygon( m_currentPolygon ).size();
  272. if( m_currentContour >= totalContours )
  273. {
  274. m_currentContour = 0;
  275. m_currentPolygon++;
  276. }
  277. }
  278. }
  279. else
  280. {
  281. last = m_poly->CPolygon( m_currentPolygon )[0].SegmentCount();
  282. // If the last vertex of the outline was reached, advance to the following
  283. // polygon
  284. if( m_currentSegment >= last )
  285. {
  286. m_currentSegment = 0;
  287. m_currentPolygon++;
  288. }
  289. }
  290. }
  291. void operator++( int dummy )
  292. {
  293. Advance();
  294. }
  295. void operator++()
  296. {
  297. Advance();
  298. }
  299. T Get()
  300. {
  301. return m_poly->Polygon( m_currentPolygon )[m_currentContour].Segment( m_currentSegment );
  302. }
  303. T operator*()
  304. {
  305. return Get();
  306. }
  307. /**
  308. * Function GetIndex
  309. * @return VERTEX_INDEX - indices of the current polygon, contour and vertex.
  310. */
  311. VERTEX_INDEX GetIndex()
  312. {
  313. VERTEX_INDEX index;
  314. index.m_polygon = m_currentPolygon;
  315. index.m_contour = m_currentContour;
  316. index.m_vertex = m_currentSegment;
  317. return index;
  318. }
  319. /**
  320. * Function IsAdjacent
  321. * @param aOther is an iterator pointing to another segment.
  322. * @return bool - true if both iterators point to the same segment of the same
  323. * contour of the same polygon of the same polygon set; false
  324. * otherwise.
  325. */
  326. bool IsAdjacent( SEGMENT_ITERATOR_TEMPLATE<T> aOther )
  327. {
  328. // Check that both iterators point to the same contour of the same polygon of the
  329. // same polygon set
  330. if( m_poly == aOther.m_poly && m_currentPolygon == aOther.m_currentPolygon &&
  331. m_currentContour == aOther.m_currentContour )
  332. {
  333. // Compute the total number of segments
  334. int numSeg;
  335. numSeg = m_poly->CPolygon( m_currentPolygon )[m_currentContour].SegmentCount();
  336. // Compute the difference of the segment indices. If it is exactly one, they
  337. // are adjacent. The only missing case where they also are adjacent is when
  338. // the segments are the first and last one, in which case the difference
  339. // always equals the total number of segments minus one.
  340. int indexDiff = abs( m_currentSegment - aOther.m_currentSegment );
  341. return ( indexDiff == 1 ) || ( indexDiff == (numSeg - 1) );
  342. }
  343. return false;
  344. }
  345. private:
  346. friend class SHAPE_POLY_SET;
  347. SHAPE_POLY_SET* m_poly;
  348. int m_currentPolygon;
  349. int m_currentContour;
  350. int m_currentSegment;
  351. int m_lastPolygon;
  352. bool m_iterateHoles;
  353. };
  354. // Iterator and const iterator types to visit polygon's points.
  355. typedef ITERATOR_TEMPLATE<VECTOR2I> ITERATOR;
  356. typedef ITERATOR_TEMPLATE<const VECTOR2I> CONST_ITERATOR;
  357. // Iterator and const iterator types to visit polygon's edges.
  358. typedef SEGMENT_ITERATOR_TEMPLATE<SEG> SEGMENT_ITERATOR;
  359. typedef SEGMENT_ITERATOR_TEMPLATE<const SEG> CONST_SEGMENT_ITERATOR;
  360. SHAPE_POLY_SET();
  361. /**
  362. * Copy constructor SHAPE_POLY_SET
  363. * Performs a deep copy of \p aOther into \p this.
  364. * @param aOther is the SHAPE_POLY_SET object that will be copied.
  365. * @param aDeepCopy if true, make new copies of the triangulated unique_ptr vector
  366. */
  367. SHAPE_POLY_SET( const SHAPE_POLY_SET& aOther, bool aDeepCopy = false );
  368. ~SHAPE_POLY_SET();
  369. /**
  370. * Function GetRelativeIndices
  371. *
  372. * Converts a global vertex index ---i.e., a number that globally identifies a vertex in a
  373. * concatenated list of all vertices in all contours--- and get the index of the vertex
  374. * relative to the contour relative to the polygon in which it is.
  375. * @param aGlobalIdx is the global index of the corner whose structured index wants to
  376. * be found
  377. * @param aRelativeIndices is a pointer to the set of relative indices to store.
  378. * @return bool - true if the global index is correct and the information in
  379. * aRelativeIndices is valid; false otherwise.
  380. */
  381. bool GetRelativeIndices( int aGlobalIdx, VERTEX_INDEX* aRelativeIndices) const;
  382. /**
  383. * Function GetGlobalIndex
  384. * computes the global index of a vertex from the relative indices of polygon, contour and
  385. * vertex.
  386. * @param aRelativeIndices is the set of relative indices.
  387. * @param aGlobalIdx [out] is the computed global index.
  388. * @return bool - true if the relative indices are correct; false otherwise. The computed
  389. * global index is returned in the \p aGlobalIdx reference.
  390. */
  391. bool GetGlobalIndex( VERTEX_INDEX aRelativeIndices, int& aGlobalIdx );
  392. /// @copydoc SHAPE::Clone()
  393. SHAPE* Clone() const override;
  394. ///> Creates a new empty polygon in the set and returns its index
  395. int NewOutline();
  396. ///> Creates a new hole in a given outline
  397. int NewHole( int aOutline = -1 );
  398. ///> Adds a new outline to the set and returns its index
  399. int AddOutline( const SHAPE_LINE_CHAIN& aOutline );
  400. ///> Adds a new hole to the given outline (default: last) and returns its index
  401. int AddHole( const SHAPE_LINE_CHAIN& aHole, int aOutline = -1 );
  402. ///> Appends a vertex at the end of the given outline/hole (default: the last outline)
  403. /**
  404. * Function Append
  405. * adds a new vertex to the contour indexed by \p aOutline and \p aHole (defaults to the
  406. * outline of the last polygon).
  407. * @param x is the x coordinate of the new vertex.
  408. * @param y is the y coordinate of the new vertex.
  409. * @param aOutline is the index of the polygon.
  410. * @param aHole is the index of the hole (-1 for the main outline),
  411. * @param aAllowDuplication is a flag to indicate whether it is allowed to add this
  412. * corner even if it is duplicated.
  413. * @return int - the number of corners of the selected contour after the addition.
  414. */
  415. int Append( int x, int y, int aOutline = -1, int aHole = -1,
  416. bool aAllowDuplication = false );
  417. ///> Merges polygons from two sets.
  418. void Append( const SHAPE_POLY_SET& aSet );
  419. ///> Appends a vertex at the end of the given outline/hole (default: the last outline)
  420. void Append( const VECTOR2I& aP, int aOutline = -1, int aHole = -1 );
  421. /**
  422. * Function InsertVertex
  423. * Adds a vertex in the globally indexed position aGlobalIndex.
  424. * @param aGlobalIndex is the global index of the position in which teh new vertex will be
  425. * inserted.
  426. * @param aNewVertex is the new inserted vertex.
  427. */
  428. void InsertVertex( int aGlobalIndex, VECTOR2I aNewVertex );
  429. ///> Returns the index-th vertex in a given hole outline within a given outline
  430. VECTOR2I& Vertex( int aIndex, int aOutline, int aHole );
  431. ///> Returns the index-th vertex in a given hole outline within a given outline
  432. const VECTOR2I& CVertex( int aIndex, int aOutline, int aHole ) const;
  433. ///> Returns the aGlobalIndex-th vertex in the poly set
  434. VECTOR2I& Vertex( int aGlobalIndex );
  435. ///> Returns the aGlobalIndex-th vertex in the poly set
  436. const VECTOR2I& CVertex( int aGlobalIndex ) const;
  437. ///> Returns the index-th vertex in a given hole outline within a given outline
  438. VECTOR2I& Vertex( VERTEX_INDEX aIndex );
  439. ///> Returns the index-th vertex in a given hole outline within a given outline
  440. const VECTOR2I& CVertex( VERTEX_INDEX aIndex ) const;
  441. /**
  442. * Returns the global indexes of the previous and the next corner
  443. * of the aGlobalIndex-th corner of a contour in the polygon set.
  444. * they are often aGlobalIndex-1 and aGlobalIndex+1, but not for the first and last
  445. * corner of the contour.
  446. * @param aGlobalIndex is index of the corner, globally indexed between all edges in all
  447. * contours
  448. * @param aPrevious - the globalIndex of the previous corner of the same contour.
  449. * @param aNext - the globalIndex of the next corner of the same contour.
  450. * @return true if OK, false if aGlobalIndex is out of range
  451. */
  452. bool GetNeighbourIndexes( int aGlobalIndex, int* aPrevious, int* aNext );
  453. /**
  454. * Function IsPolygonSelfIntersecting.
  455. * Checks whether the aPolygonIndex-th polygon in the set is self intersecting.
  456. * @param aPolygonIndex index of the polygon that wants to be checked.
  457. * @return bool - true if the aPolygonIndex-th polygon is self intersecting, false
  458. * otherwise.
  459. */
  460. bool IsPolygonSelfIntersecting( int aPolygonIndex );
  461. /**
  462. * Function IsSelfIntersecting
  463. * Checks whether any of the polygons in the set is self intersecting.
  464. * @return bool - true if any of the polygons is self intersecting, false otherwise.
  465. */
  466. bool IsSelfIntersecting();
  467. ///> Returns the number of triangulated polygons
  468. unsigned int TriangulatedPolyCount() const { return m_triangulatedPolys.size(); }
  469. ///> Returns the number of outlines in the set
  470. int OutlineCount() const { return m_polys.size(); }
  471. ///> Returns the number of vertices in a given outline/hole
  472. int VertexCount( int aOutline = -1, int aHole = -1 ) const;
  473. ///> Returns the number of holes in a given outline
  474. int HoleCount( int aOutline ) const
  475. {
  476. if( ( aOutline < 0 ) || (aOutline >= (int)m_polys.size()) || (m_polys[aOutline].size() < 2) )
  477. return 0;
  478. // the first polygon in m_polys[aOutline] is the main contour,
  479. // only others are holes:
  480. return m_polys[aOutline].size() - 1;
  481. }
  482. ///> Returns the reference to aIndex-th outline in the set
  483. SHAPE_LINE_CHAIN& Outline( int aIndex )
  484. {
  485. return m_polys[aIndex][0];
  486. }
  487. /**
  488. * Function Subset
  489. * returns a subset of the polygons in this set, the ones between aFirstPolygon and
  490. * aLastPolygon.
  491. * @param aFirstPolygon is the first polygon to be included in the returned set.
  492. * @param aLastPolygon is the first polygon to be excluded of the returned set.
  493. * @return SHAPE_POLY_SET - a set containing the polygons between aFirstPolygon (included)
  494. * and aLastPolygon (excluded).
  495. */
  496. SHAPE_POLY_SET Subset( int aFirstPolygon, int aLastPolygon );
  497. SHAPE_POLY_SET UnitSet( int aPolygonIndex )
  498. {
  499. return Subset( aPolygonIndex, aPolygonIndex + 1 );
  500. }
  501. ///> Returns the reference to aHole-th hole in the aIndex-th outline
  502. SHAPE_LINE_CHAIN& Hole( int aOutline, int aHole )
  503. {
  504. return m_polys[aOutline][aHole + 1];
  505. }
  506. ///> Returns the aIndex-th subpolygon in the set
  507. POLYGON& Polygon( int aIndex )
  508. {
  509. return m_polys[aIndex];
  510. }
  511. const POLYGON& Polygon( int aIndex ) const
  512. {
  513. return m_polys[aIndex];
  514. }
  515. const TRIANGULATED_POLYGON* TriangulatedPolygon( int aIndex ) const
  516. {
  517. return m_triangulatedPolys[aIndex].get();
  518. }
  519. const SHAPE_LINE_CHAIN& COutline( int aIndex ) const
  520. {
  521. return m_polys[aIndex][0];
  522. }
  523. const SHAPE_LINE_CHAIN& CHole( int aOutline, int aHole ) const
  524. {
  525. return m_polys[aOutline][aHole + 1];
  526. }
  527. const POLYGON& CPolygon( int aIndex ) const
  528. {
  529. return m_polys[aIndex];
  530. }
  531. /**
  532. * Function Iterate
  533. * returns an object to iterate through the points of the polygons between \p aFirst and
  534. * \p aLast.
  535. * @param aFirst is the first polygon whose points will be iterated.
  536. * @param aLast is the last polygon whose points will be iterated.
  537. * @param aIterateHoles is a flag to indicate whether the points of the holes should be
  538. * iterated.
  539. * @return ITERATOR - the iterator object.
  540. */
  541. ITERATOR Iterate( int aFirst, int aLast, bool aIterateHoles = false )
  542. {
  543. ITERATOR iter;
  544. iter.m_poly = this;
  545. iter.m_currentPolygon = aFirst;
  546. iter.m_lastPolygon = aLast < 0 ? OutlineCount() - 1 : aLast;
  547. iter.m_currentContour = 0;
  548. iter.m_currentVertex = 0;
  549. iter.m_iterateHoles = aIterateHoles;
  550. return iter;
  551. }
  552. /**
  553. * Function Iterate
  554. * @param aOutline the index of the polygon to be iterated.
  555. * @return ITERATOR - an iterator object to visit all points in the main outline of the
  556. * aOutline-th polygon, without visiting the points in the holes.
  557. */
  558. ITERATOR Iterate( int aOutline )
  559. {
  560. return Iterate( aOutline, aOutline );
  561. }
  562. /**
  563. * Function IterateWithHoles
  564. * @param aOutline the index of the polygon to be iterated.
  565. * @return ITERATOR - an iterator object to visit all points in the main outline of the
  566. * aOutline-th polygon, visiting also the points in the holes.
  567. */
  568. ITERATOR IterateWithHoles( int aOutline )
  569. {
  570. return Iterate( aOutline, aOutline, true );
  571. }
  572. /**
  573. * Function Iterate
  574. * @return ITERATOR - an iterator object to visit all points in all outlines of the set,
  575. * without visiting the points in the holes.
  576. */
  577. ITERATOR Iterate()
  578. {
  579. return Iterate( 0, OutlineCount() - 1 );
  580. }
  581. /**
  582. * Function IterateWithHoles
  583. * @return ITERATOR - an iterator object to visit all points in all outlines of the set,
  584. * visiting also the points in the holes.
  585. */
  586. ITERATOR IterateWithHoles()
  587. {
  588. return Iterate( 0, OutlineCount() - 1, true );
  589. }
  590. CONST_ITERATOR CIterate( int aFirst, int aLast, bool aIterateHoles = false ) const
  591. {
  592. CONST_ITERATOR iter;
  593. iter.m_poly = const_cast<SHAPE_POLY_SET*>( this );
  594. iter.m_currentPolygon = aFirst;
  595. iter.m_lastPolygon = aLast < 0 ? OutlineCount() - 1 : aLast;
  596. iter.m_currentContour = 0;
  597. iter.m_currentVertex = 0;
  598. iter.m_iterateHoles = aIterateHoles;
  599. return iter;
  600. }
  601. CONST_ITERATOR CIterate( int aOutline ) const
  602. {
  603. return CIterate( aOutline, aOutline );
  604. }
  605. CONST_ITERATOR CIterateWithHoles( int aOutline ) const
  606. {
  607. return CIterate( aOutline, aOutline, true );
  608. }
  609. CONST_ITERATOR CIterate() const
  610. {
  611. return CIterate( 0, OutlineCount() - 1 );
  612. }
  613. CONST_ITERATOR CIterateWithHoles() const
  614. {
  615. return CIterate( 0, OutlineCount() - 1, true );
  616. }
  617. ITERATOR IterateFromVertexWithHoles( int aGlobalIdx )
  618. {
  619. // Build iterator
  620. ITERATOR iter = IterateWithHoles();
  621. // Get the relative indices of the globally indexed vertex
  622. VERTEX_INDEX indices;
  623. if( !GetRelativeIndices( aGlobalIdx, &indices ) )
  624. throw( std::out_of_range( "aGlobalIndex-th vertex does not exist" ) );
  625. // Adjust where the iterator is pointing
  626. iter.m_currentPolygon = indices.m_polygon;
  627. iter.m_currentContour = indices.m_contour;
  628. iter.m_currentVertex = indices.m_vertex;
  629. return iter;
  630. }
  631. ///> Returns an iterator object, for iterating between aFirst and aLast outline, with or
  632. /// without holes (default: without)
  633. SEGMENT_ITERATOR IterateSegments( int aFirst, int aLast, bool aIterateHoles = false )
  634. {
  635. SEGMENT_ITERATOR iter;
  636. iter.m_poly = this;
  637. iter.m_currentPolygon = aFirst;
  638. iter.m_lastPolygon = aLast < 0 ? OutlineCount() - 1 : aLast;
  639. iter.m_currentContour = 0;
  640. iter.m_currentSegment = 0;
  641. iter.m_iterateHoles = aIterateHoles;
  642. return iter;
  643. }
  644. ///> Returns an iterator object, for iterating aPolygonIdx-th polygon edges
  645. SEGMENT_ITERATOR IterateSegments( int aPolygonIdx )
  646. {
  647. return IterateSegments( aPolygonIdx, aPolygonIdx );
  648. }
  649. ///> Returns an iterator object, for all outlines in the set (no holes)
  650. SEGMENT_ITERATOR IterateSegments()
  651. {
  652. return IterateSegments( 0, OutlineCount() - 1 );
  653. }
  654. ///> Returns an iterator object, for all outlines in the set (with holes)
  655. SEGMENT_ITERATOR IterateSegmentsWithHoles()
  656. {
  657. return IterateSegments( 0, OutlineCount() - 1, true );
  658. }
  659. ///> Returns an iterator object, for the aOutline-th outline in the set (with holes)
  660. SEGMENT_ITERATOR IterateSegmentsWithHoles( int aOutline )
  661. {
  662. return IterateSegments( aOutline, aOutline, true );
  663. }
  664. /** operations on polygons use a aFastMode param
  665. * if aFastMode is PM_FAST (true) the result can be a weak polygon
  666. * if aFastMode is PM_STRICTLY_SIMPLE (false) (default) the result is (theorically) a strictly
  667. * simple polygon, but calculations can be really significantly time consuming
  668. * Most of time PM_FAST is preferable.
  669. * PM_STRICTLY_SIMPLE can be used in critical cases (Gerber output for instance)
  670. */
  671. enum POLYGON_MODE
  672. {
  673. PM_FAST = true,
  674. PM_STRICTLY_SIMPLE = false
  675. };
  676. ///> Performs boolean polyset union
  677. ///> For aFastMode meaning, see function booleanOp
  678. void BooleanAdd( const SHAPE_POLY_SET& b, POLYGON_MODE aFastMode );
  679. ///> Performs boolean polyset difference
  680. ///> For aFastMode meaning, see function booleanOp
  681. void BooleanSubtract( const SHAPE_POLY_SET& b, POLYGON_MODE aFastMode );
  682. ///> Performs boolean polyset intersection
  683. ///> For aFastMode meaning, see function booleanOp
  684. void BooleanIntersection( const SHAPE_POLY_SET& b, POLYGON_MODE aFastMode );
  685. ///> Performs boolean polyset union between a and b, store the result in it self
  686. ///> For aFastMode meaning, see function booleanOp
  687. void BooleanAdd( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b,
  688. POLYGON_MODE aFastMode );
  689. ///> Performs boolean polyset difference between a and b, store the result in it self
  690. ///> For aFastMode meaning, see function booleanOp
  691. void BooleanSubtract( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b,
  692. POLYGON_MODE aFastMode );
  693. ///> Performs boolean polyset intersection between a and b, store the result in it self
  694. ///> For aFastMode meaning, see function booleanOp
  695. void BooleanIntersection( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b,
  696. POLYGON_MODE aFastMode );
  697. ///> Performs outline inflation/deflation, using round corners.
  698. void Inflate( int aFactor, int aCircleSegmentsCount );
  699. ///> Converts a set of polygons with holes to a singe outline with "slits"/"fractures" connecting the outer ring
  700. ///> to the inner holes
  701. ///> For aFastMode meaning, see function booleanOp
  702. void Fracture( POLYGON_MODE aFastMode );
  703. ///> Converts a single outline slitted ("fractured") polygon into a set ouf outlines
  704. ///> with holes.
  705. void Unfracture( POLYGON_MODE aFastMode );
  706. ///> Returns true if the polygon set has any holes.
  707. bool HasHoles() const;
  708. ///> Returns true if the polygon set has any holes tha share a vertex.
  709. bool HasTouchingHoles() const;
  710. ///> Simplifies the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
  711. ///> For aFastMode meaning, see function booleanOp
  712. void Simplify( POLYGON_MODE aFastMode );
  713. /**
  714. * Function NormalizeAreaOutlines
  715. * Convert a self-intersecting polygon to one (or more) non self-intersecting polygon(s)
  716. * Removes null segments.
  717. * @return int - the polygon count (always >= 1, because there is at least one polygon)
  718. * There are new polygons only if the polygon count is > 1.
  719. */
  720. int NormalizeAreaOutlines();
  721. /// @copydoc SHAPE::Format()
  722. const std::string Format() const override;
  723. /// @copydoc SHAPE::Parse()
  724. bool Parse( std::stringstream& aStream ) override;
  725. /// @copydoc SHAPE::Move()
  726. void Move( const VECTOR2I& aVector ) override;
  727. /**
  728. * Function Rotate
  729. * rotates all vertices by a given angle
  730. * @param aCenter is the rotation center
  731. * @param aAngle rotation angle in radians
  732. */
  733. void Rotate( double aAngle, const VECTOR2I& aCenter );
  734. /// @copydoc SHAPE::IsSolid()
  735. bool IsSolid() const override
  736. {
  737. return true;
  738. }
  739. const BOX2I BBox( int aClearance = 0 ) const override;
  740. /**
  741. * Function PointOnEdge()
  742. *
  743. * Checks if point aP lies on an edge or vertex of some of the outlines or holes.
  744. * @param aP is the point to check.
  745. * @return bool - true if the point lies on the edge of any polygon.
  746. */
  747. bool PointOnEdge( const VECTOR2I& aP ) const;
  748. /**
  749. * Function Collide
  750. * Checks whether the point aP collides with the inside of the polygon set; if the point
  751. * lies on an edge or on a corner of any of the polygons, there is no collision: the edges
  752. * does not belong to the polygon itself.
  753. * @param aP is the VECTOR2I point whose collision with respect to the poly set
  754. * will be tested.
  755. * @param aClearance is the security distance; if the point lies closer to the polygon
  756. * than aClearance distance, then there is a collision.
  757. * @return bool - true if the point aP collides with the polygon; false in any other case.
  758. */
  759. bool Collide( const VECTOR2I& aP, int aClearance = 0 ) const override;
  760. /**
  761. * Function Collide
  762. * Checks whether the segment aSeg collides with the inside of the polygon set; if the
  763. * segment touches an edge or a corner of any of the polygons, there is no collision:
  764. * the edges do not belong to the polygon itself.
  765. * @param aSeg is the SEG segment whose collision with respect to the poly set
  766. * will be tested.
  767. * @param aClearance is the security distance; if the segment passes closer to the polygon
  768. * than aClearance distance, then there is a collision.
  769. * @return bool - true if the segment aSeg collides with the polygon;
  770. * false in any other case.
  771. */
  772. bool Collide( const SEG& aSeg, int aClearance = 0 ) const override;
  773. /**
  774. * Function CollideVertex
  775. * Checks whether aPoint collides with any vertex of any of the contours of the polygon.
  776. * @param aPoint is the VECTOR2I point whose collision with respect to the polygon
  777. * will be tested.
  778. * @param aClearance is the security distance; if \p aPoint lies closer to a vertex than
  779. * aClearance distance, then there is a collision.
  780. * @param aClosestVertex is the index of the closes vertex to \p aPoint.
  781. * @return bool - true if there is a collision, false in any other case.
  782. */
  783. bool CollideVertex( const VECTOR2I& aPoint, VERTEX_INDEX& aClosestVertex,
  784. int aClearance = 0 );
  785. /**
  786. * Function CollideEdge
  787. * Checks whether aPoint collides with any edge of any of the contours of the polygon.
  788. * @param aPoint is the VECTOR2I point whose collision with respect to the polygon
  789. * will be tested.
  790. * @param aClearance is the security distance; if \p aPoint lies closer to a vertex than
  791. * aClearance distance, then there is a collision.
  792. * @param aClosestVertex is the index of the closes vertex to \p aPoint.
  793. * @return bool - true if there is a collision, false in any other case.
  794. */
  795. bool CollideEdge( const VECTOR2I& aPoint, VERTEX_INDEX& aClosestVertex,
  796. int aClearance = 0 );
  797. /**
  798. * Returns true if a given subpolygon contains the point aP
  799. *
  800. * @param aP is the point to check
  801. * @param aSubpolyIndex is the subpolygon to check, or -1 to check all
  802. * @param aIgnoreHoles controls whether or not internal holes are considered
  803. * @return true if the polygon contains the point
  804. */
  805. bool Contains( const VECTOR2I& aP, int aSubpolyIndex = -1, bool aIgnoreHoles = false ) const;
  806. ///> Returns true if the set is empty (no polygons at all)
  807. bool IsEmpty() const
  808. {
  809. return m_polys.size() == 0;
  810. }
  811. /**
  812. * Function RemoveVertex
  813. * deletes the aGlobalIndex-th vertex.
  814. * @param aGlobalIndex is the global index of the to-be-removed vertex.
  815. */
  816. void RemoveVertex( int aGlobalIndex );
  817. /**
  818. * Function RemoveVertex
  819. * deletes the vertex indexed by aIndex (index of polygon, contour and vertex).
  820. * @param aRelativeIndices is the set of relative indices of the to-be-removed vertex.
  821. */
  822. void RemoveVertex( VERTEX_INDEX aRelativeIndices );
  823. ///> Removes all outlines & holes (clears) the polygon set.
  824. void RemoveAllContours();
  825. /**
  826. * Function RemoveContour
  827. * deletes the aContourIdx-th contour of the aPolygonIdx-th polygon in the set.
  828. * @param aContourIdx is the index of the contour in the aPolygonIdx-th polygon to be
  829. * removed.
  830. * @param aPolygonIdx is the index of the polygon in which the to-be-removed contour is.
  831. * Defaults to the last polygon in the set.
  832. */
  833. void RemoveContour( int aContourIdx, int aPolygonIdx = -1 );
  834. /**
  835. * Function RemoveNullSegments
  836. * looks for null segments; ie, segments whose ends are exactly the same and deletes them.
  837. * @return int - the number of deleted segments.
  838. */
  839. int RemoveNullSegments();
  840. ///> Returns total number of vertices stored in the set.
  841. int TotalVertices() const;
  842. ///> Deletes aIdx-th polygon from the set
  843. void DeletePolygon( int aIdx );
  844. /**
  845. * Function Chamfer
  846. * returns a chamfered version of the aIndex-th polygon.
  847. * @param aDistance is the chamfering distance.
  848. * @param aIndex is the index of the polygon to be chamfered.
  849. * @return POLYGON - A polygon containing the chamfered version of the aIndex-th polygon.
  850. */
  851. POLYGON ChamferPolygon( unsigned int aDistance, int aIndex = 0 );
  852. /**
  853. * Function Fillet
  854. * returns a filleted version of the aIndex-th polygon.
  855. * @param aRadius is the fillet radius.
  856. * @param aErrorMax is the maximum allowable deviation of the polygon from the circle
  857. * @param aIndex is the index of the polygon to be filleted
  858. * @return POLYGON - A polygon containing the filleted version of the aIndex-th polygon.
  859. */
  860. POLYGON FilletPolygon( unsigned int aRadius, int aErrorMax, int aIndex = 0 );
  861. /**
  862. * Function Chamfer
  863. * returns a chamfered version of the polygon set.
  864. * @param aDistance is the chamfering distance.
  865. * @return SHAPE_POLY_SET - A set containing the chamfered version of this set.
  866. */
  867. SHAPE_POLY_SET Chamfer( int aDistance );
  868. /**
  869. * Function Fillet
  870. * returns a filleted version of the polygon set.
  871. * @param aRadius is the fillet radius.
  872. * @param aErrorMax is the maximum allowable deviation of the polygon from the circle
  873. * @return SHAPE_POLY_SET - A set containing the filleted version of this set.
  874. */
  875. SHAPE_POLY_SET Fillet( int aRadius, int aErrorMax );
  876. /**
  877. * Function DistanceToPolygon
  878. * computes the minimum distance between the aIndex-th polygon and aPoint.
  879. * @param aPoint is the point whose distance to the aIndex-th polygon has to be measured.
  880. * @param aIndex is the index of the polygon whose distace to aPoint has to be measured.
  881. * @return int - The minimum distance between aPoint and all the segments of the aIndex-th
  882. * polygon. If the point is contained in the polygon, the distance is zero.
  883. */
  884. int DistanceToPolygon( VECTOR2I aPoint, int aIndex );
  885. /**
  886. * Function DistanceToPolygon
  887. * computes the minimum distance between the aIndex-th polygon and aSegment with a
  888. * possible width.
  889. * @param aSegment is the segment whose distance to the aIndex-th polygon has to be
  890. * measured.
  891. * @param aIndex is the index of the polygon whose distace to aPoint has to be measured.
  892. * @param aSegmentWidth is the width of the segment; defaults to zero.
  893. * @return int - The minimum distance between aSegment and all the segments of the
  894. * aIndex-th polygon. If the point is contained in the polygon, the
  895. * distance is zero.
  896. */
  897. int DistanceToPolygon( SEG aSegment, int aIndex, int aSegmentWidth = 0 );
  898. /**
  899. * Function DistanceToPolygon
  900. * computes the minimum distance between aPoint and all the polygons in the set
  901. * @param aPoint is the point whose distance to the set has to be measured.
  902. * @return int - The minimum distance between aPoint and all the polygons in the set. If
  903. * the point is contained in any of the polygons, the distance is zero.
  904. */
  905. int Distance( VECTOR2I aPoint );
  906. /**
  907. * Function DistanceToPolygon
  908. * computes the minimum distance between aSegment and all the polygons in the set.
  909. * @param aSegment is the segment whose distance to the polygon set has to be measured.
  910. * @param aSegmentWidth is the width of the segment; defaults to zero.
  911. * @return int - The minimum distance between aSegment and all the polygons in the set.
  912. * If the point is contained in the polygon, the distance is zero.
  913. */
  914. int Distance( const SEG& aSegment, int aSegmentWidth = 0 );
  915. /**
  916. * Function IsVertexInHole.
  917. * checks whether the aGlobalIndex-th vertex belongs to a hole.
  918. * @param aGlobalIdx is the index of the vertex.
  919. * @return bool - true if the globally indexed aGlobalIdx-th vertex belongs to a hole.
  920. */
  921. bool IsVertexInHole( int aGlobalIdx );
  922. private:
  923. SHAPE_LINE_CHAIN& getContourForCorner( int aCornerId, int& aIndexWithinContour );
  924. VECTOR2I& vertex( int aCornerId );
  925. const VECTOR2I& cvertex( int aCornerId ) const;
  926. void fractureSingle( POLYGON& paths );
  927. void unfractureSingle ( POLYGON& path );
  928. void importTree( ClipperLib::PolyTree* tree );
  929. /** Function booleanOp
  930. * this is the engine to execute all polygon boolean transforms
  931. * (AND, OR, ... and polygon simplification (merging overlaping polygons)
  932. * @param aType is the transform type ( see ClipperLib::ClipType )
  933. * @param aOtherShape is the SHAPE_LINE_CHAIN to combine with me.
  934. * @param aFastMode is an option to choose if the result can be a weak polygon
  935. * or a stricty simple polygon.
  936. * if aFastMode is PM_FAST the result can be a weak polygon
  937. * if aFastMode is PM_STRICTLY_SIMPLE (default) the result is (theorically) a strictly
  938. * simple polygon, but calculations can be really significantly time consuming
  939. */
  940. void booleanOp( ClipperLib::ClipType aType,
  941. const SHAPE_POLY_SET& aOtherShape, POLYGON_MODE aFastMode );
  942. void booleanOp( ClipperLib::ClipType aType,
  943. const SHAPE_POLY_SET& aShape,
  944. const SHAPE_POLY_SET& aOtherShape, POLYGON_MODE aFastMode );
  945. bool pointInPolygon( const VECTOR2I& aP, const SHAPE_LINE_CHAIN& aPath ) const;
  946. /**
  947. * containsSingle function
  948. * Checks whether the point aP is inside the aSubpolyIndex-th polygon of the polyset. If
  949. * the points lies on an edge, the polygon is considered to contain it.
  950. * @param aP is the VECTOR2I point whose position with respect to the inside of
  951. * the aSubpolyIndex-th polygon will be tested.
  952. * @param aSubpolyIndex is an integer specifying which polygon in the set has to be
  953. * checked.
  954. * @param aIgnoreHoles can be set to true to ignore internal holes in the polygon
  955. * @return bool - true if aP is inside aSubpolyIndex-th polygon; false in any other
  956. * case.
  957. */
  958. bool containsSingle( const VECTOR2I& aP, int aSubpolyIndex, bool aIgnoreHoles = false ) const;
  959. /**
  960. * Operations ChamferPolygon and FilletPolygon are computed under the private chamferFillet
  961. * method; this enum is defined to make the necessary distinction when calling this method
  962. * from the public ChamferPolygon and FilletPolygon methods.
  963. */
  964. enum CORNER_MODE
  965. {
  966. CHAMFERED,
  967. FILLETED
  968. };
  969. /**
  970. * Function chamferFilletPolygon
  971. * Returns the camfered or filleted version of the aIndex-th polygon in the set, depending
  972. * on the aMode selected
  973. * @param aMode represent which action will be taken: CORNER_MODE::CHAMFERED will
  974. * return a chamfered version of the polygon, CORNER_MODE::FILLETED will
  975. * return a filleted version of the polygon.
  976. * @param aDistance is the chamfering distance if aMode = CHAMFERED; if aMode = FILLETED,
  977. * is the filleting radius.
  978. * @param aIndex is the index of the polygon that will be chamfered/filleted.
  979. * @param aErrorMax is the maximum allowable deviation of the polygon from the circle
  980. * if aMode = FILLETED. If aMode = CHAMFERED, it is unused.
  981. * @return POLYGON - the chamfered/filleted version of the polygon.
  982. */
  983. POLYGON chamferFilletPolygon( CORNER_MODE aMode, unsigned int aDistance,
  984. int aIndex, int aErrorMax = -1 );
  985. ///> Returns true if the polygon set has any holes that touch share a vertex.
  986. bool hasTouchingHoles( const POLYGON& aPoly ) const;
  987. typedef std::vector<POLYGON> POLYSET;
  988. POLYSET m_polys;
  989. public:
  990. SHAPE_POLY_SET& operator=( const SHAPE_POLY_SET& );
  991. void CacheTriangulation();
  992. bool IsTriangulationUpToDate() const;
  993. MD5_HASH GetHash() const;
  994. private:
  995. MD5_HASH checksum() const;
  996. std::vector<std::unique_ptr<TRIANGULATED_POLYGON>> m_triangulatedPolys;
  997. bool m_triangulationValid = false;
  998. MD5_HASH m_hash;
  999. };
  1000. #endif