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.

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