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.

966 lines
35 KiB

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