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.

957 lines
33 KiB

8 years ago
5 years ago
5 years ago
5 years ago
8 years ago
8 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2019 Jean-Pierre Charras, jp.charras at wanadoo.fr
  5. * Copyright (C) 1992-2021 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, you may find one here:
  19. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  20. * or you may search the http://www.gnu.org website for the version 2 license,
  21. * or you may write to the Free Software Foundation, Inc.,
  22. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  23. */
  24. #ifndef ZONE_H
  25. #define ZONE_H
  26. #include <mutex>
  27. #include <vector>
  28. #include <gr_basic.h>
  29. #include <board_item.h>
  30. #include <board_connected_item.h>
  31. #include <layer_ids.h>
  32. #include <geometry/shape_poly_set.h>
  33. #include <zone_settings.h>
  34. class EDA_RECT;
  35. class LINE_READER;
  36. class PCB_EDIT_FRAME;
  37. class BOARD;
  38. class ZONE;
  39. class MSG_PANEL_ITEM;
  40. /**
  41. * Handle a list of polygons defining a copper zone.
  42. *
  43. * A zone is described by a main polygon, a time stamp, a layer or a layer set, and a net name.
  44. * Other polygons inside the main polygon are holes in the zone.
  45. *
  46. * a item ZONE is living in a board
  47. * a variant FP_ZONE is living in a footprint
  48. */
  49. class ZONE : public BOARD_CONNECTED_ITEM
  50. {
  51. public:
  52. /**
  53. * The ctor to build ZONE, but compatible with FP_ZONE requirement.
  54. * if aInFP is true, a FP_ZONE is actually built
  55. * (same item, but with a specific type id:
  56. * The type is PCB_ZONE_T for a ZONE
  57. * The type is PCB_FP_ZONE_T for a FP_ZONE
  58. */
  59. ZONE( BOARD_ITEM_CONTAINER* parent, bool aInFP = false );
  60. ZONE( const ZONE& aZone );
  61. ZONE& operator=( const ZONE &aOther );
  62. ~ZONE();
  63. static inline bool ClassOf( const EDA_ITEM* aItem )
  64. {
  65. return aItem && aItem->Type() == PCB_ZONE_T;
  66. }
  67. /**
  68. * Not all ZONEs are *really* BOARD_CONNECTED_ITEMs....
  69. */
  70. bool IsConnected() const override
  71. {
  72. return !GetIsRuleArea();
  73. }
  74. NETCLASS* GetNetClass() const override
  75. {
  76. if( GetIsRuleArea() )
  77. return nullptr;
  78. return BOARD_CONNECTED_ITEM::GetNetClass();
  79. }
  80. wxString GetNetClassName() const override
  81. {
  82. if( GetIsRuleArea() )
  83. return "UNDEFINED";
  84. return BOARD_CONNECTED_ITEM::GetNetClassName();
  85. }
  86. /**
  87. * Copy aZone data to me
  88. */
  89. void InitDataFromSrcInCopyCtor( const ZONE& aZone );
  90. /**
  91. * @return a wxPoint, position of the first point of the outline
  92. */
  93. wxPoint GetPosition() const override;
  94. void SetPosition( const wxPoint& aPos ) override {}
  95. /**
  96. * @param aPriority is the priority level.
  97. */
  98. void SetPriority( unsigned aPriority ) { m_priority = aPriority; }
  99. /**
  100. * @return the priority level of this zone.
  101. */
  102. unsigned GetPriority() const { return m_priority; }
  103. void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
  104. void SetLayerSet( LSET aLayerSet ) override;
  105. virtual LSET GetLayerSet() const override;
  106. wxString GetZoneName() const { return m_zoneName; }
  107. void SetZoneName( const wxString& aName ) { m_zoneName = aName; }
  108. bool Matches( const wxFindReplaceData& aSearchData, void* aAuxData ) const override
  109. {
  110. return BOARD_ITEM::Matches( GetZoneName(), aSearchData );
  111. }
  112. /**
  113. * @return an EDA_RECT that is the bounding box of the zone outline.
  114. */
  115. const EDA_RECT GetBoundingBox() const override;
  116. /**
  117. * ONLY TO BE USED BY CLIENTS WHICH SET UP THE CACHE!
  118. */
  119. const EDA_RECT GetCachedBoundingBox() const { return m_bboxCache; }
  120. void CacheBoundingBox() { m_bboxCache = GetBoundingBox(); }
  121. /**
  122. * Return any local clearances set in the "classic" (ie: pre-rule) system. These are
  123. * things like zone clearance which are NOT an override.
  124. *
  125. * @param aSource [out] optionally reports the source as a user-readable string
  126. * @return the clearance in internal units.
  127. */
  128. int GetLocalClearance( wxString* aSource ) const override;
  129. int GetLocalClearance() const { return GetLocalClearance( nullptr ); }
  130. void SetLocalClearance( int aClearance ) { m_ZoneClearance = aClearance; }
  131. /**
  132. * @return true if this zone is on a copper layer, false if on a technical layer.
  133. */
  134. bool IsOnCopperLayer() const override;
  135. /**
  136. * Test if this zone shares a common layer with the given layer set.
  137. */
  138. bool CommonLayerExists( const LSET aLayerSet ) const;
  139. virtual void SetLayer( PCB_LAYER_ID aLayer ) override;
  140. virtual PCB_LAYER_ID GetLayer() const override;
  141. virtual bool IsOnLayer( PCB_LAYER_ID ) const override;
  142. virtual void ViewGetLayers( int aLayers[], int& aCount ) const override;
  143. double ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const override;
  144. void SetFillMode( ZONE_FILL_MODE aFillMode ) { m_fillMode = aFillMode; }
  145. ZONE_FILL_MODE GetFillMode() const { return m_fillMode; }
  146. void SetThermalReliefGap( int aThermalReliefGap )
  147. {
  148. if( m_thermalReliefGap != aThermalReliefGap )
  149. SetNeedRefill( true );
  150. m_thermalReliefGap = aThermalReliefGap;
  151. }
  152. int GetThermalReliefGap() const { return m_thermalReliefGap; }
  153. int GetThermalReliefGap( PAD* aPad, wxString* aSource = nullptr ) const;
  154. void SetThermalReliefSpokeWidth( int aThermalReliefSpokeWidth )
  155. {
  156. if( m_thermalReliefSpokeWidth != aThermalReliefSpokeWidth )
  157. SetNeedRefill( true );
  158. m_thermalReliefSpokeWidth = aThermalReliefSpokeWidth;
  159. }
  160. int GetThermalReliefSpokeWidth() const { return m_thermalReliefSpokeWidth; }
  161. int GetThermalReliefSpokeWidth( PAD* aPad, wxString* aSource = nullptr ) const;
  162. /**
  163. * Compute the area currently occupied by the zone fill.
  164. *
  165. * @return the currently filled area
  166. */
  167. double CalculateFilledArea();
  168. /**
  169. * This area is cached from the most recent call to CalculateFilledArea().
  170. *
  171. * @return the filled area
  172. */
  173. double GetFilledArea()
  174. {
  175. return m_area;
  176. }
  177. std::mutex& GetLock()
  178. {
  179. return m_lock;
  180. }
  181. int GetFillFlag( PCB_LAYER_ID aLayer )
  182. {
  183. return m_fillFlags.count( aLayer ) ? m_fillFlags[ aLayer ] : false;
  184. }
  185. void SetFillFlag( PCB_LAYER_ID aLayer, bool aFlag ) { m_fillFlags[ aLayer ] = aFlag; }
  186. bool IsFilled() const { return m_isFilled; }
  187. void SetIsFilled( bool isFilled ) { m_isFilled = isFilled; }
  188. bool NeedRefill() const { return m_needRefill; }
  189. void SetNeedRefill( bool aNeedRefill ) { m_needRefill = aNeedRefill; }
  190. ZONE_CONNECTION GetPadConnection( PAD* aPad, wxString* aSource = nullptr ) const;
  191. ZONE_CONNECTION GetPadConnection() const { return m_PadConnection; }
  192. void SetPadConnection( ZONE_CONNECTION aPadConnection ) { m_PadConnection = aPadConnection; }
  193. int GetMinThickness() const { return m_ZoneMinThickness; }
  194. void SetMinThickness( int aMinThickness )
  195. {
  196. if( m_ZoneMinThickness != aMinThickness )
  197. SetNeedRefill( true );
  198. m_ZoneMinThickness = aMinThickness;
  199. }
  200. int GetHatchThickness() const { return m_hatchThickness; }
  201. void SetHatchThickness( int aThickness ) { m_hatchThickness = aThickness; }
  202. int GetHatchGap() const { return m_hatchGap; }
  203. void SetHatchGap( int aStep ) { m_hatchGap = aStep; }
  204. double GetHatchOrientation() const { return m_hatchOrientation; }
  205. void SetHatchOrientation( double aStep ) { m_hatchOrientation = aStep; }
  206. int GetHatchSmoothingLevel() const { return m_hatchSmoothingLevel; }
  207. void SetHatchSmoothingLevel( int aLevel ) { m_hatchSmoothingLevel = aLevel; }
  208. double GetHatchSmoothingValue() const { return m_hatchSmoothingValue; }
  209. void SetHatchSmoothingValue( double aValue ) { m_hatchSmoothingValue = aValue; }
  210. double GetHatchHoleMinArea() const { return m_hatchHoleMinArea; }
  211. void SetHatchHoleMinArea( double aPct ) { m_hatchHoleMinArea = aPct; }
  212. int GetHatchBorderAlgorithm() const { return m_hatchBorderAlgorithm; }
  213. void SetHatchBorderAlgorithm( int aAlgo ) { m_hatchBorderAlgorithm = aAlgo; }
  214. int GetSelectedCorner() const
  215. {
  216. // Transform relative indices to global index
  217. int globalIndex = -1;
  218. if( m_CornerSelection )
  219. m_Poly->GetGlobalIndex( *m_CornerSelection, globalIndex );
  220. return globalIndex;
  221. }
  222. void SetSelectedCorner( int aCorner )
  223. {
  224. SHAPE_POLY_SET::VERTEX_INDEX selectedCorner;
  225. // If the global index of the corner is correct, assign it to m_CornerSelection
  226. if( m_Poly->GetRelativeIndices( aCorner, &selectedCorner ) )
  227. {
  228. if( m_CornerSelection == nullptr )
  229. m_CornerSelection = new SHAPE_POLY_SET::VERTEX_INDEX;
  230. *m_CornerSelection = selectedCorner;
  231. }
  232. else
  233. throw( std::out_of_range( "aCorner-th vertex does not exist" ) );
  234. }
  235. ///
  236. // Like HitTest but selects the current corner to be operated on
  237. void SetSelectedCorner( const wxPoint& aPosition, int aAccuracy );
  238. int GetLocalFlags() const { return m_localFlgs; }
  239. void SetLocalFlags( int aFlags ) { m_localFlgs = aFlags; }
  240. std::vector<SEG>& FillSegments( PCB_LAYER_ID aLayer )
  241. {
  242. wxASSERT( m_FillSegmList.count( aLayer ) );
  243. return m_FillSegmList.at( aLayer );
  244. }
  245. const std::vector<SEG>& FillSegments( PCB_LAYER_ID aLayer ) const
  246. {
  247. wxASSERT( m_FillSegmList.count( aLayer ) );
  248. return m_FillSegmList.at( aLayer );
  249. }
  250. SHAPE_POLY_SET* Outline() { return m_Poly; }
  251. const SHAPE_POLY_SET* Outline() const { return m_Poly; }
  252. void SetOutline( SHAPE_POLY_SET* aOutline ) { m_Poly = aOutline; }
  253. // @copydoc BOARD_ITEM::GetEffectiveShape
  254. virtual std::shared_ptr<SHAPE>
  255. GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const override;
  256. /**
  257. * Test if a point is near an outline edge or a corner of this zone.
  258. *
  259. * @param aPosition the wxPoint to test
  260. * @return true if a hit, else false
  261. */
  262. bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override;
  263. /**
  264. * Test if the given wxPoint is within the bounds of a filled area of this zone.
  265. *
  266. * @param aLayer is the layer to test on
  267. * @param aRefPos A wxPoint to test
  268. * @param aAccuracy Expand the distance by which the areas are expanded for the hittest
  269. * @return true if a hit, else false
  270. */
  271. bool HitTestFilledArea( PCB_LAYER_ID aLayer, const wxPoint &aRefPos, int aAccuracy = 0 ) const;
  272. /**
  273. * Test if the given point is contained within a cutout of the zone.
  274. *
  275. * @param aRefPos is the point to test
  276. * @param aOutlineIdx is the index of the outline containing the cutout
  277. * @param aHoleIdx is the index of the hole
  278. * @return true if aRefPos is inside a zone cutout
  279. */
  280. bool HitTestCutout( const VECTOR2I& aRefPos, int* aOutlineIdx = nullptr,
  281. int* aHoleIdx = nullptr ) const;
  282. bool HitTestCutout( const wxPoint& aRefPos, int* aOutlineIdx = nullptr,
  283. int* aHoleIdx = nullptr ) const
  284. {
  285. return HitTestCutout( VECTOR2I( aRefPos.x, aRefPos.y ), aOutlineIdx, aHoleIdx );
  286. }
  287. /**
  288. * Some intersecting zones, despite being on the same layer with the same net, cannot be
  289. * merged due to other parameters such as fillet radius. The copper pour will end up
  290. * effectively merged though, so we need to do some calculations with them in mind.
  291. */
  292. void GetInteractingZones( PCB_LAYER_ID aLayer, std::vector<ZONE*>* aZones ) const;
  293. /**
  294. * Convert solid areas full shapes to polygon set
  295. * (the full shape is the polygon area with a thick outline)
  296. * Used in 3D view
  297. * Arcs (ends of segments) are approximated by segments
  298. *
  299. * @param aLayer is the layer of the zone to retrieve
  300. * @param aCornerBuffer = a buffer to store the polygons
  301. * @param aError = Maximum error allowed between true arc and polygon approx
  302. */
  303. void TransformSolidAreasShapesToPolygon( PCB_LAYER_ID aLayer, SHAPE_POLY_SET& aCornerBuffer,
  304. int aError = ARC_HIGH_DEF ) const;
  305. /**
  306. * Convert the outlines shape to a polygon with no holes
  307. * inflated (optional) by max( aClearanceValue, the zone clearance)
  308. * (holes are linked to external outline by overlapping segments)
  309. * Used in filling zones calculations
  310. * Circles (vias) and arcs (ends of tracks) are approximated by segments.
  311. *
  312. * @param aCornerBuffer is a buffer to store the polygon
  313. * @param aClearance is the min clearance around outlines
  314. * @param aBoardOutline is the board outline (if a valid one exists; nullptr otherwise)
  315. */
  316. void TransformSmoothedOutlineToPolygon( SHAPE_POLY_SET& aCornerBuffer, int aClearance,
  317. SHAPE_POLY_SET* aBoardOutline ) const;
  318. /**
  319. * Convert the zone shape to a closed polygon
  320. * Used in filling zones calculations
  321. * Circles and arcs are approximated by segments
  322. *
  323. * @param aLayer is the layer of the filled zone to retrieve
  324. * @param aCornerBuffer is a buffer to store the polygon
  325. * @param aClearanceValue is the clearance around the pad
  326. * @param aError is the maximum deviation from true circle
  327. * @param ignoreLineWidth is used for edge cut items where the line width is only
  328. * for visualization
  329. */
  330. void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
  331. PCB_LAYER_ID aLayer, int aClearanceValue,
  332. int aError, ERROR_LOC aErrorLoc,
  333. bool ignoreLineWidth = false ) const override;
  334. /**
  335. * Test if the given wxPoint is near a corner.
  336. *
  337. * @param refPos is the wxPoint to test.
  338. * @param aAccuracy increase the item bounding box by this amount.
  339. * @param aCornerHit [out] is the index of the closest vertex found, useless when return
  340. * value is false.
  341. * @return true if some corner was found to be closer to refPos than aClearance; false
  342. * otherwise.
  343. */
  344. bool HitTestForCorner( const wxPoint& refPos, int aAccuracy,
  345. SHAPE_POLY_SET::VERTEX_INDEX& aCornerHit ) const;
  346. /**
  347. * Test if the given wxPoint is near a corner.
  348. * @param refPos is the wxPoint to test.
  349. * @param aAccuracy increase the item bounding box by this amount.
  350. * @return true if some corner was found to be closer to refPos than aClearance; false
  351. * otherwise.
  352. */
  353. bool HitTestForCorner( const wxPoint& refPos, int aAccuracy ) const;
  354. /**
  355. * Test if the given wxPoint is near a segment defined by 2 corners.
  356. *
  357. * @param refPos is the wxPoint to test.
  358. * @param aAccuracy increase the item bounding box by this amount.
  359. * @param aCornerHit [out] is the index of the closest vertex found, useless when return
  360. * value is false.
  361. * @return true if some edge was found to be closer to refPos than aClearance.
  362. */
  363. bool HitTestForEdge( const wxPoint& refPos, int aAccuracy,
  364. SHAPE_POLY_SET::VERTEX_INDEX& aCornerHit ) const;
  365. /**
  366. * Test if the given wxPoint is near a segment defined by 2 corners.
  367. *
  368. * @param refPos is the wxPoint to test.
  369. * @param aAccuracy increase the item bounding box by this amount.
  370. * @return true if some edge was found to be closer to refPos than aClearance.
  371. */
  372. bool HitTestForEdge( const wxPoint& refPos, int aAccuracy ) const;
  373. /**
  374. * @copydoc BOARD_ITEM::HitTest(const EDA_RECT& aRect,
  375. * bool aContained = true, int aAccuracy) const
  376. */
  377. bool HitTest( const EDA_RECT& aRect, bool aContained = true, int aAccuracy = 0 ) const override;
  378. /**
  379. * Removes the zone filling.
  380. *
  381. * @return true if a previous filling is removed, false if no change (when no filling found).
  382. */
  383. bool UnFill();
  384. /* Geometric transformations: */
  385. /**
  386. * Move the outlines
  387. *
  388. * @param offset is moving vector
  389. */
  390. void Move( const wxPoint& offset ) override;
  391. /**
  392. * Move the outline Edge.
  393. *
  394. * @param offset is moving vector
  395. * @param aEdge is start point of the outline edge
  396. */
  397. void MoveEdge( const wxPoint& offset, int aEdge );
  398. /**
  399. * Move the outlines.
  400. *
  401. * @param aCentre is rot centre
  402. * @param aAngle is in 0.1 degree
  403. */
  404. void Rotate( const wxPoint& aCentre, double aAngle ) override;
  405. /**
  406. * Flip this object, i.e. change the board side for this object
  407. * (like Mirror() but changes layer).
  408. *
  409. * @param aCentre is the rotation point.
  410. */
  411. virtual void Flip( const wxPoint& aCentre, bool aFlipLeftRight ) override;
  412. /**
  413. * Mirror the outlines relative to a given horizontal axis the layer is not changed.
  414. *
  415. * @param aMirrorRef is axis position
  416. * @param aMirrorLeftRight mirror across Y axis (otherwise mirror across X)
  417. */
  418. void Mirror( const wxPoint& aMirrorRef, bool aMirrorLeftRight );
  419. /**
  420. * @return the class name.
  421. */
  422. wxString GetClass() const override
  423. {
  424. return wxT( "ZONE" );
  425. }
  426. /**
  427. * Access to m_Poly parameters
  428. */
  429. int GetNumCorners( void ) const
  430. {
  431. return m_Poly->TotalVertices();
  432. }
  433. /**
  434. * Return an iterator to visit all points of the zone's main outline without holes.
  435. *
  436. * @return an iterator to visit the zone vertices without holes.
  437. */
  438. SHAPE_POLY_SET::ITERATOR Iterate()
  439. {
  440. return m_Poly->Iterate();
  441. }
  442. /**
  443. * Return an iterator to visit all points of the zone's main outline with holes.
  444. *
  445. * @return an iterator to visit the zone vertices with holes.
  446. */
  447. SHAPE_POLY_SET::ITERATOR IterateWithHoles()
  448. {
  449. return m_Poly->IterateWithHoles();
  450. }
  451. /**
  452. * Return an iterator to visit all points of the zone's main outline with holes.
  453. *
  454. * @return an iterator to visit the zone vertices with holes.
  455. */
  456. SHAPE_POLY_SET::CONST_ITERATOR CIterateWithHoles() const
  457. {
  458. return m_Poly->CIterateWithHoles();
  459. }
  460. void RemoveAllContours( void )
  461. {
  462. m_Poly->RemoveAllContours();
  463. }
  464. const VECTOR2I& GetCornerPosition( int aCornerIndex ) const
  465. {
  466. SHAPE_POLY_SET::VERTEX_INDEX index;
  467. // Convert global to relative indices
  468. if( !m_Poly->GetRelativeIndices( aCornerIndex, &index ) )
  469. throw( std::out_of_range( "aCornerIndex-th vertex does not exist" ) );
  470. return m_Poly->CVertex( index );
  471. }
  472. void SetCornerPosition( int aCornerIndex, const wxPoint& new_pos )
  473. {
  474. SHAPE_POLY_SET::VERTEX_INDEX relativeIndices;
  475. // Convert global to relative indices
  476. if( m_Poly->GetRelativeIndices( aCornerIndex, &relativeIndices ) )
  477. {
  478. if( m_Poly->CVertex( relativeIndices ).x != new_pos.x
  479. || m_Poly->CVertex( relativeIndices ).y != new_pos.y )
  480. {
  481. SetNeedRefill( true );
  482. m_Poly->SetVertex( relativeIndices, new_pos );
  483. }
  484. }
  485. else
  486. {
  487. throw( std::out_of_range( "aCornerIndex-th vertex does not exist" ) );
  488. }
  489. }
  490. /**
  491. * Create a new hole on the zone; i.e., a new contour on the zone's outline.
  492. */
  493. void NewHole()
  494. {
  495. m_Poly->NewHole();
  496. }
  497. /**
  498. * Add a new corner to the zone outline (to the main outline or a hole)
  499. *
  500. * @param aPosition is the position of the new corner.
  501. * @param aHoleIdx is the index of the hole (-1 for the main outline, >= 0 for hole).
  502. * @param aAllowDuplication is a flag to indicate whether it is allowed to add this corner
  503. * even if it is duplicated.
  504. * @return true if the corner was added, false if error (aHoleIdx > hole count -1)
  505. */
  506. bool AppendCorner( wxPoint aPosition, int aHoleIdx, bool aAllowDuplication = false );
  507. ZONE_BORDER_DISPLAY_STYLE GetHatchStyle() const { return m_borderStyle; }
  508. void SetHatchStyle( ZONE_BORDER_DISPLAY_STYLE aStyle ) { m_borderStyle = aStyle; }
  509. /**
  510. * Test if 2 zones are equivalent.
  511. *
  512. * Zones are equivalent if they have same parameters and same outline info.
  513. *
  514. * @note Filling is not taken into account.
  515. *
  516. * @param aZoneToCompare is the zone to compare with "this"
  517. */
  518. bool IsSame( const ZONE &aZoneToCompare );
  519. bool HasFilledPolysForLayer( PCB_LAYER_ID aLayer ) const
  520. {
  521. return m_FilledPolysList.count( aLayer ) > 0;
  522. }
  523. /**
  524. * @return a reference to the list of filled polygons.
  525. */
  526. const SHAPE_POLY_SET& GetFilledPolysList( PCB_LAYER_ID aLayer ) const
  527. {
  528. wxASSERT( m_FilledPolysList.count( aLayer ) );
  529. return m_FilledPolysList.at( aLayer );
  530. }
  531. /**
  532. * Create a list of triangles that "fill" the solid areas used for instance to draw
  533. * these solid areas on OpenGL.
  534. */
  535. void CacheTriangulation( PCB_LAYER_ID aLayer = UNDEFINED_LAYER );
  536. /**
  537. * Set the list of filled polygons.
  538. */
  539. void SetFilledPolysList( PCB_LAYER_ID aLayer, const SHAPE_POLY_SET& aPolysList )
  540. {
  541. m_FilledPolysList[aLayer] = aPolysList;
  542. }
  543. /**
  544. * Set the list of filled polygons.
  545. */
  546. void SetRawPolysList( PCB_LAYER_ID aLayer, const SHAPE_POLY_SET& aPolysList )
  547. {
  548. m_RawPolysList[aLayer] = aPolysList;
  549. }
  550. /**
  551. * Check if a given filled polygon is an insulated island.
  552. *
  553. * @param aLayer is the layer to test
  554. * @param aPolyIdx is an index into m_FilledPolysList[aLayer]
  555. * @return true if the given polygon is insulated (i.e. has no net connection)
  556. */
  557. bool IsIsland( PCB_LAYER_ID aLayer, int aPolyIdx ) const;
  558. void SetIsIsland( PCB_LAYER_ID aLayer, int aPolyIdx )
  559. {
  560. m_insulatedIslands[aLayer].insert( aPolyIdx );
  561. }
  562. bool BuildSmoothedPoly( SHAPE_POLY_SET& aSmoothedPoly, PCB_LAYER_ID aLayer,
  563. SHAPE_POLY_SET* aBoardOutline,
  564. SHAPE_POLY_SET* aSmoothedPolyWithApron = nullptr ) const;
  565. void SetCornerSmoothingType( int aType ) { m_cornerSmoothingType = aType; };
  566. int GetCornerSmoothingType() const { return m_cornerSmoothingType; }
  567. void SetCornerRadius( unsigned int aRadius );
  568. unsigned int GetCornerRadius() const { return m_cornerRadius; }
  569. bool GetFilledPolysUseThickness() const { return m_fillVersion == 5; }
  570. bool GetFilledPolysUseThickness( PCB_LAYER_ID aLayer ) const;
  571. int GetFillVersion() const { return m_fillVersion; }
  572. void SetFillVersion( int aVersion ) { m_fillVersion = aVersion; }
  573. /**
  574. * Remove a cutout from the zone.
  575. *
  576. * @param aOutlineIdx is the zone outline the hole belongs to
  577. * @param aHoleIdx is the hole in the outline to remove
  578. */
  579. void RemoveCutout( int aOutlineIdx, int aHoleIdx );
  580. /**
  581. * Add a polygon to the zone outline.
  582. *
  583. * If the zone outline is empty, this is the main outline. Otherwise it is a hole
  584. * inside the main outline.
  585. */
  586. void AddPolygon( std::vector< wxPoint >& aPolygon );
  587. void AddPolygon( const SHAPE_LINE_CHAIN& aPolygon );
  588. void SetFillSegments( PCB_LAYER_ID aLayer, const std::vector<SEG>& aSegments )
  589. {
  590. m_FillSegmList[aLayer] = aSegments;
  591. }
  592. SHAPE_POLY_SET& RawPolysList( PCB_LAYER_ID aLayer )
  593. {
  594. wxASSERT( m_RawPolysList.count( aLayer ) );
  595. return m_RawPolysList.at( aLayer );
  596. }
  597. wxString GetSelectMenuText( EDA_UNITS aUnits ) const override;
  598. BITMAPS GetMenuImage() const override;
  599. EDA_ITEM* Clone() const override;
  600. /**
  601. * Accessors to parameters used in Rule Area zones:
  602. */
  603. bool GetIsRuleArea() const { return m_isRuleArea; }
  604. bool GetDoNotAllowCopperPour() const { return m_doNotAllowCopperPour; }
  605. bool GetDoNotAllowVias() const { return m_doNotAllowVias; }
  606. bool GetDoNotAllowTracks() const { return m_doNotAllowTracks; }
  607. bool GetDoNotAllowPads() const { return m_doNotAllowPads; }
  608. bool GetDoNotAllowFootprints() const { return m_doNotAllowFootprints; }
  609. bool IsKeepout() const;
  610. bool KeepoutAll() const;
  611. void SetIsRuleArea( bool aEnable ) { m_isRuleArea = aEnable; }
  612. void SetDoNotAllowCopperPour( bool aEnable ) { m_doNotAllowCopperPour = aEnable; }
  613. void SetDoNotAllowVias( bool aEnable ) { m_doNotAllowVias = aEnable; }
  614. void SetDoNotAllowTracks( bool aEnable ) { m_doNotAllowTracks = aEnable; }
  615. void SetDoNotAllowPads( bool aEnable ) { m_doNotAllowPads = aEnable; }
  616. void SetDoNotAllowFootprints( bool aEnable ) { m_doNotAllowFootprints = aEnable; }
  617. const ISLAND_REMOVAL_MODE GetIslandRemovalMode() const { return m_islandRemovalMode; }
  618. void SetIslandRemovalMode( ISLAND_REMOVAL_MODE aRemove ) { m_islandRemovalMode = aRemove; }
  619. long long int GetMinIslandArea() const { return m_minIslandArea; }
  620. void SetMinIslandArea( long long int aArea ) { m_minIslandArea = aArea; }
  621. /**
  622. * HatchBorder related methods
  623. */
  624. /**
  625. * @return the zone hatch pitch in iu.
  626. */
  627. int GetBorderHatchPitch() const;
  628. /**
  629. * @return the default hatch pitch in internal units.
  630. */
  631. static int GetDefaultHatchPitch();
  632. /**
  633. * Set all hatch parameters for the zone.
  634. *
  635. * @param aHatchStyle is the style of the hatch, specified as one of HATCH_STYLE possible
  636. * values.
  637. * @param aHatchPitch is the hatch pitch in iu.
  638. * @param aRebuildHatch is a flag to indicate whether to re-hatch after having set the
  639. * previous parameters.
  640. */
  641. void SetBorderDisplayStyle( ZONE_BORDER_DISPLAY_STYLE aHatchStyle, int aHatchPitch,
  642. bool aRebuildHatch );
  643. /**
  644. * Set the hatch pitch parameter for the zone.
  645. *
  646. * @param aPitch is the hatch pitch in iu.
  647. */
  648. void SetHatchPitch( int aPitch );
  649. /**
  650. * Clear the zone's hatch.
  651. */
  652. void UnHatchBorder();
  653. /**
  654. * Compute the hatch lines depending on the hatch parameters and stores it in the zone's
  655. * attribute m_borderHatchLines.
  656. */
  657. void HatchBorder();
  658. const std::vector<SEG>& GetHatchLines() const { return m_borderHatchLines; }
  659. bool GetHV45() const { return m_hv45; }
  660. void SetHV45( bool aConstrain ) { m_hv45 = aConstrain; }
  661. /**
  662. * Build the hash value of m_FilledPolysList, and store it internally in m_filledPolysHash.
  663. * Used in zone filling calculations, to know if m_FilledPolysList is up to date.
  664. */
  665. void BuildHashValue( PCB_LAYER_ID aLayer );
  666. /**
  667. * @return the hash value previously calculated by BuildHashValue().
  668. */
  669. MD5_HASH GetHashValue( PCB_LAYER_ID aLayer );
  670. #if defined(DEBUG)
  671. virtual void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
  672. #endif
  673. virtual void SwapData( BOARD_ITEM* aImage ) override;
  674. protected:
  675. SHAPE_POLY_SET* m_Poly; ///< Outline of the zone.
  676. int m_cornerSmoothingType;
  677. unsigned int m_cornerRadius;
  678. /// An optional unique name for this zone, used for identifying it in DRC checking
  679. wxString m_zoneName;
  680. LSET m_layerSet;
  681. /* Priority: when a zone outline is inside and other zone, if its priority is higher
  682. * the other zone priority, it will be created inside.
  683. * if priorities are equal, a DRC error is set
  684. */
  685. unsigned m_priority;
  686. /* A zone outline can be a keepout zone.
  687. * It will be never filled, and DRC should test for pads, tracks and vias
  688. */
  689. bool m_isRuleArea;
  690. /* For keepout zones only:
  691. * what is not allowed inside the keepout ( pads, tracks and vias )
  692. */
  693. bool m_doNotAllowCopperPour;
  694. bool m_doNotAllowVias;
  695. bool m_doNotAllowTracks;
  696. bool m_doNotAllowPads;
  697. bool m_doNotAllowFootprints;
  698. ZONE_CONNECTION m_PadConnection;
  699. int m_ZoneClearance; // Clearance value in internal units.
  700. int m_ZoneMinThickness; // Minimum thickness value in filled areas.
  701. int m_fillVersion; // See BOARD_DESIGN_SETTINGS for version
  702. // differences.
  703. ISLAND_REMOVAL_MODE m_islandRemovalMode;
  704. /**
  705. * When island removal mode is set to AREA, islands below this area will be removed.
  706. * If this value is negative, all islands will be removed.
  707. */
  708. long long int m_minIslandArea;
  709. /** True when a zone was filled, false after deleting the filled areas. */
  710. bool m_isFilled;
  711. /**
  712. * False when a zone was refilled, true after changes in zone params.
  713. * m_needRefill = false does not imply filled areas are up to date, just
  714. * the zone was refilled after edition, and does not need refilling
  715. */
  716. bool m_needRefill;
  717. int m_thermalReliefGap; // Width of the gap in thermal reliefs.
  718. int m_thermalReliefSpokeWidth; // Width of the copper bridge in thermal reliefs.
  719. /**
  720. * How to fill areas:
  721. *
  722. * ZONE_FILL_MODE::POLYGONS => use solid polygons
  723. * ZONE_FILL_MODE::HATCH_PATTERN => use a grid pattern as shape
  724. */
  725. ZONE_FILL_MODE m_fillMode;
  726. int m_hatchThickness; // thickness of lines (if 0 -> solid shape)
  727. int m_hatchGap; // gap between lines (0 -> solid shape
  728. double m_hatchOrientation; // orientation in degrees of grid lines
  729. int m_hatchSmoothingLevel; // 0 = no smoothing
  730. // 1 = fillet
  731. // 2 = arc low def
  732. // 3 = arc high def
  733. double m_hatchSmoothingValue; // hole chamfer/fillet size (ratio of hole size)
  734. double m_hatchHoleMinArea; // min size before holes are dropped (ratio)
  735. int m_hatchBorderAlgorithm; // 0 = use min zone thickness
  736. // 1 = use hatch thickness
  737. /// The index of the corner being moved or nullptr if no corner is selected.
  738. SHAPE_POLY_SET::VERTEX_INDEX* m_CornerSelection;
  739. int m_localFlgs; // Variable used in polygon calculations.
  740. /**
  741. * Segments used to fill the zone (#m_FillMode ==1 ), when fill zone by segment is used.
  742. * In this case the segments have #m_ZoneMinThickness width.
  743. */
  744. std::map<PCB_LAYER_ID, std::vector<SEG> > m_FillSegmList;
  745. /* set of filled polygons used to draw a zone as a filled area.
  746. * from outlines (m_Poly) but unlike m_Poly these filled polygons have no hole
  747. * (they are all in one piece) In very simple cases m_FilledPolysList is same
  748. * as m_Poly. In less simple cases (when m_Poly has holes) m_FilledPolysList is
  749. * a polygon equivalent to m_Poly, without holes but with extra outline segment
  750. * connecting "holes" with external main outline. In complex cases an outline
  751. * described by m_Poly can have many filled areas
  752. */
  753. std::map<PCB_LAYER_ID, SHAPE_POLY_SET> m_FilledPolysList;
  754. std::map<PCB_LAYER_ID, SHAPE_POLY_SET> m_RawPolysList;
  755. /// Temp variables used while filling
  756. EDA_RECT m_bboxCache;
  757. std::map<PCB_LAYER_ID, bool> m_fillFlags;
  758. /// A hash value used in zone filling calculations to see if the filled areas are up to date
  759. std::map<PCB_LAYER_ID, MD5_HASH> m_filledPolysHash;
  760. ZONE_BORDER_DISPLAY_STYLE m_borderStyle; // border display style, see enum above
  761. int m_borderHatchPitch; // for DIAGONAL_EDGE, distance between 2 lines
  762. std::vector<SEG> m_borderHatchLines; // hatch lines
  763. /// For each layer, a set of insulated islands that were not removed
  764. std::map<PCB_LAYER_ID, std::set<int>> m_insulatedIslands;
  765. bool m_hv45; // constrain edges to horiz, vert or 45º
  766. double m_area; // The filled zone area
  767. /// Lock used for multi-threaded filling on multi-layer zones
  768. std::mutex m_lock;
  769. };
  770. /**
  771. * A specialization of ZONE for use in footprints.
  772. */
  773. class FP_ZONE : public ZONE
  774. {
  775. public:
  776. FP_ZONE( BOARD_ITEM_CONTAINER* aParent );
  777. FP_ZONE( const FP_ZONE& aZone );
  778. FP_ZONE& operator=( const FP_ZONE &aOther );
  779. EDA_ITEM* Clone() const override;
  780. double ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const override;
  781. };
  782. #endif // ZONE_H