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.

954 lines
33 KiB

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