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.

616 lines
21 KiB

14 years ago
14 years ago
14 years ago
14 years ago
12 years ago
17 years ago
14 years ago
14 years ago
14 years ago
14 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) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
  5. * Copyright (C) 1992-2015 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. * @brief Classes to handle copper zones
  27. */
  28. #ifndef CLASS_ZONE_H_
  29. #define CLASS_ZONE_H_
  30. #include <vector>
  31. #include <gr_basic.h>
  32. #include <class_board_item.h>
  33. #include <class_board_connected_item.h>
  34. #include <layers_id_colors_and_visibility.h>
  35. #include <PolyLine.h>
  36. #include <class_zone_settings.h>
  37. class EDA_RECT;
  38. class LINE_READER;
  39. class EDA_DRAW_PANEL;
  40. class PCB_EDIT_FRAME;
  41. class BOARD;
  42. class ZONE_CONTAINER;
  43. class MSG_PANEL_ITEM;
  44. /**
  45. * Struct SEGMENT
  46. * is a simple container used when filling areas with segments
  47. */
  48. struct SEGMENT
  49. {
  50. wxPoint m_Start; // starting point of a segment
  51. wxPoint m_End; // ending point of a segment
  52. SEGMENT() {}
  53. SEGMENT( const wxPoint& aStart, const wxPoint& aEnd )
  54. {
  55. m_Start = aStart;
  56. m_End = aEnd;
  57. }
  58. };
  59. /**
  60. * Class ZONE_CONTAINER
  61. * handles a list of polygons defining a copper zone.
  62. * A zone is described by a main polygon, a time stamp, a layer, and a net name.
  63. * Other polygons inside the main polygon are holes in the zone.
  64. */
  65. class ZONE_CONTAINER : public BOARD_CONNECTED_ITEM
  66. {
  67. public:
  68. ZONE_CONTAINER( BOARD* parent );
  69. ZONE_CONTAINER( const ZONE_CONTAINER& aZone );
  70. ZONE_CONTAINER& operator=( const ZONE_CONTAINER &aOther );
  71. ~ZONE_CONTAINER();
  72. /**
  73. * Function GetPosition
  74. * @return a wxPoint, position of the first point of the outline
  75. */
  76. const wxPoint& GetPosition() const; // was overload
  77. void SetPosition( const wxPoint& aPos ) {} // was overload
  78. /**
  79. * Function SetPriority
  80. * @param aPriority = the priority level
  81. */
  82. void SetPriority( unsigned aPriority ) { m_priority = aPriority; }
  83. /**
  84. * Function GetPriority
  85. * @return the priority level of this zone
  86. */
  87. unsigned GetPriority() const { return m_priority; }
  88. void GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList );
  89. /**
  90. * Function Draw
  91. * Draws the zone outline.
  92. * @param panel = current Draw Panel
  93. * @param DC = current Device Context
  94. * @param aDrawMode = GR_OR, GR_XOR, GR_COPY ..
  95. * @param offset = Draw offset (usually wxPoint(0,0))
  96. */
  97. void Draw( EDA_DRAW_PANEL* panel,
  98. wxDC* DC,
  99. GR_DRAWMODE aDrawMode,
  100. const wxPoint& offset = ZeroOffset );
  101. /**
  102. * Function DrawDrawFilledArea
  103. * Draws the filled area for this zone (polygon list .m_FilledPolysList)
  104. * @param panel = current Draw Panel
  105. * @param DC = current Device Context
  106. * @param offset = Draw offset (usually wxPoint(0,0))
  107. * @param aDrawMode = GR_OR, GR_XOR, GR_COPY ..
  108. */
  109. void DrawFilledArea( EDA_DRAW_PANEL* panel,
  110. wxDC* DC,
  111. GR_DRAWMODE aDrawMode,
  112. const wxPoint& offset = ZeroOffset );
  113. /**
  114. * Function DrawWhileCreateOutline
  115. * Draws the zone outline when it is created.
  116. * The moving edges are in XOR graphic mode, old segment in draw_mode graphic mode
  117. * (usually GR_OR). The closing edge has its own shape.
  118. * @param panel = current Draw Panel
  119. * @param DC = current Device Context
  120. * @param draw_mode = draw mode: OR, XOR ..
  121. */
  122. void DrawWhileCreateOutline( EDA_DRAW_PANEL* panel, wxDC* DC,
  123. GR_DRAWMODE draw_mode = GR_OR );
  124. /** Function GetBoundingBox (virtual)
  125. * @return an EDA_RECT that is the bounding box of the zone outline
  126. */
  127. const EDA_RECT GetBoundingBox() const;
  128. int GetClearance( BOARD_CONNECTED_ITEM* aItem = NULL ) const;
  129. /**
  130. * Function TestForCopperIslandAndRemoveInsulatedIslands
  131. * Remove insulated copper islands found in m_FilledPolysList.
  132. * @param aPcb = the board to analyze
  133. */
  134. void TestForCopperIslandAndRemoveInsulatedIslands( BOARD* aPcb );
  135. /**
  136. * Function IsOnCopperLayer
  137. * @return true if this zone is on a copper layer, false if on a technical layer
  138. */
  139. bool IsOnCopperLayer() const
  140. {
  141. return IsCopperLayer( GetLayer() );
  142. }
  143. /// How to fill areas: 0 = use filled polygons, 1 => fill with segments.
  144. void SetFillMode( int aFillMode ) { m_FillMode = aFillMode; }
  145. int GetFillMode() const { return m_FillMode; }
  146. void SetThermalReliefGap( int aThermalReliefGap ) { m_ThermalReliefGap = aThermalReliefGap; }
  147. int GetThermalReliefGap( D_PAD* aPad = NULL ) const;
  148. void SetThermalReliefCopperBridge( int aThermalReliefCopperBridge )
  149. {
  150. m_ThermalReliefCopperBridge = aThermalReliefCopperBridge;
  151. }
  152. int GetThermalReliefCopperBridge( D_PAD* aPad = NULL ) const;
  153. void SetArcSegmentCount( int aArcSegCount ) { m_ArcToSegmentsCount = aArcSegCount; }
  154. int GetArcSegmentCount() const { return m_ArcToSegmentsCount; }
  155. bool IsFilled() const { return m_IsFilled; }
  156. void SetIsFilled( bool isFilled ) { m_IsFilled = isFilled; }
  157. int GetZoneClearance() const { return m_ZoneClearance; }
  158. void SetZoneClearance( int aZoneClearance ) { m_ZoneClearance = aZoneClearance; }
  159. ZoneConnection GetPadConnection( D_PAD* aPad = NULL ) const;
  160. void SetPadConnection( ZoneConnection aPadConnection ) { m_PadConnection = aPadConnection; }
  161. int GetMinThickness() const { return m_ZoneMinThickness; }
  162. void SetMinThickness( int aMinThickness ) { m_ZoneMinThickness = aMinThickness; }
  163. int GetSelectedCorner() const { return m_CornerSelection; }
  164. void SetSelectedCorner( int aCorner ) { m_CornerSelection = aCorner; }
  165. ///
  166. // Like HitTest but selects the current corner to be operated on
  167. void SetSelectedCorner( const wxPoint& aPosition );
  168. int GetLocalFlags() const { return m_localFlgs; }
  169. void SetLocalFlags( int aFlags ) { m_localFlgs = aFlags; }
  170. std::vector <SEGMENT>& FillSegments() { return m_FillSegmList; }
  171. const std::vector <SEGMENT>& FillSegments() const { return m_FillSegmList; }
  172. CPolyLine* Outline() { return m_Poly; }
  173. const CPolyLine* Outline() const { return const_cast< CPolyLine* >( m_Poly ); }
  174. void SetOutline( CPolyLine* aOutline ) { m_Poly = aOutline; }
  175. /**
  176. * Function HitTest
  177. * tests if a point is near an outline edge or a corner of this zone.
  178. * @param aPosition the wxPoint to test
  179. * @return bool - true if a hit, else false
  180. */
  181. virtual bool HitTest( const wxPoint& aPosition ) const;
  182. /**
  183. * Function HitTest
  184. * tests if a point is inside the zone area, i.e. inside the main outline
  185. * and outside holes.
  186. * @param aPosition : the wxPoint to test
  187. * @return bool - true if a hit, else false
  188. */
  189. bool HitTestInsideZone( const wxPoint& aPosition ) const
  190. {
  191. return m_Poly->TestPointInside( aPosition.x, aPosition.y );
  192. }
  193. /**
  194. * Function HitTestFilledArea
  195. * tests if the given wxPoint is within the bounds of a filled area of this zone.
  196. * @param aRefPos A wxPoint to test
  197. * @return bool - true if a hit, else false
  198. */
  199. bool HitTestFilledArea( const wxPoint& aRefPos ) const;
  200. /**
  201. * Function TransformSolidAreasShapesToPolygonSet
  202. * Convert solid areas full shapes to polygon set
  203. * (the full shape is the polygon area with a thick outline)
  204. * Used in 3D view
  205. * Arcs (ends of segments) are approximated by segments
  206. * @param aCornerBuffer = a buffer to store the polygons
  207. * @param aCircleToSegmentsCount = the number of segments to approximate a circle
  208. * @param aCorrectionFactor = the correction to apply to arcs radius to roughly
  209. * keep arc radius when approximated by segments
  210. */
  211. void TransformSolidAreasShapesToPolygonSet( SHAPE_POLY_SET& aCornerBuffer,
  212. int aCircleToSegmentsCount,
  213. double aCorrectionFactor ) const;
  214. /**
  215. * Function BuildFilledSolidAreasPolygons
  216. * Build the filled solid areas data from real outlines (stored in m_Poly)
  217. * The solid areas can be more than one on copper layers, and do not have holes
  218. ( holes are linked by overlapping segments to the main outline)
  219. * in order to have drawable (and plottable) filled polygons
  220. * @return true if OK, false if the solid polygons cannot be built
  221. * @param aPcb: the current board (can be NULL for non copper zones)
  222. * @param aCornerBuffer: A reference to a buffer to store polygon corners, or NULL
  223. * if NULL (default:
  224. * - m_FilledPolysList is used to store solid areas polygons.
  225. * - on copper layers, tracks and other items shapes of other nets are
  226. * removed from solid areas
  227. * if not null:
  228. * Only the zone outline (with holes, if any) is stored in aOutlineBuffer
  229. * with holes linked. Therefore only one polygon is created
  230. *
  231. * When aOutlineBuffer is not null, his function calls
  232. * AddClearanceAreasPolygonsToPolysList() to add holes for pads and tracks
  233. * and other items not in net.
  234. */
  235. bool BuildFilledSolidAreasPolygons( BOARD* aPcb, SHAPE_POLY_SET* aOutlineBuffer = NULL );
  236. /**
  237. * Function AddClearanceAreasPolygonsToPolysList
  238. * Add non copper areas polygons (pads and tracks with clearance)
  239. * to a filled copper area
  240. * used in BuildFilledSolidAreasPolygons when calculating filled areas in a zone
  241. * Non copper areas are pads and track and their clearance area
  242. * The filled copper area must be computed before
  243. * BuildFilledSolidAreasPolygons() call this function just after creating the
  244. * filled copper area polygon (without clearance areas
  245. * @param aPcb: the current board
  246. * _NG version uses SHAPE_POLY_SET instead of Boost.Polygon
  247. */
  248. void AddClearanceAreasPolygonsToPolysList( BOARD* aPcb );
  249. void AddClearanceAreasPolygonsToPolysList_NG( BOARD* aPcb );
  250. /**
  251. * Function TransformOutlinesShapeWithClearanceToPolygon
  252. * Convert the outlines shape to a polygon with no holes
  253. * inflated (optional) by max( aClearanceValue, the zone clearance)
  254. * (holes are linked to external outline by overlapping segments)
  255. * Used in filling zones calculations
  256. * Circles (vias) and arcs (ends of tracks) are approximated by segments
  257. * @param aCornerBuffer = a buffer to store the polygon
  258. * @param aMinClearanceValue = the min clearance around outlines
  259. * @param aUseNetClearance = true to use a clearance which is the max value between
  260. * aMinClearanceValue and the net clearance
  261. * false to use aMinClearanceValue only
  262. * if both aMinClearanceValue = 0 and aUseNetClearance = false: create the zone outline polygon.
  263. */
  264. void TransformOutlinesShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
  265. int aMinClearanceValue,
  266. bool aUseNetClearance );
  267. /**
  268. * Function HitTestForCorner
  269. * tests if the given wxPoint near a corner
  270. * Set m_CornerSelection to -1 if nothing found, or index of corner
  271. * @return true if found
  272. * @param refPos : A wxPoint to test
  273. */
  274. int HitTestForCorner( const wxPoint& refPos ) const;
  275. /**
  276. * Function HitTestForEdge
  277. * tests if the given wxPoint is near a segment defined by 2 corners.
  278. * Set m_CornerSelection to -1 if nothing found, or index of the starting corner of vertice
  279. * @return true if found
  280. * @param refPos : A wxPoint to test
  281. */
  282. int HitTestForEdge( const wxPoint& refPos ) const;
  283. /** @copydoc BOARD_ITEM::HitTest(const EDA_RECT& aRect,
  284. * bool aContained = true, int aAccuracy ) const
  285. */
  286. bool HitTest( const EDA_RECT& aRect, bool aContained = true, int aAccuracy = 0 ) const;
  287. /**
  288. * Function FillZoneAreasWithSegments
  289. * Fill sub areas in a zone with segments with m_ZoneMinThickness width
  290. * A scan is made line per line, on the whole filled areas, with a step of m_ZoneMinThickness.
  291. * all intersecting points with the horizontal infinite line and polygons to fill are calculated
  292. * a list of SEGZONE items is built, line per line
  293. * @return true if success, false on error
  294. */
  295. bool FillZoneAreasWithSegments();
  296. /**
  297. * Function UnFill
  298. * Removes the zone filling
  299. * @return true if a previous filling is removed, false if no change
  300. * (when no filling found)
  301. */
  302. bool UnFill();
  303. /* Geometric transformations: */
  304. /**
  305. * Function Move
  306. * Move the outlines
  307. * @param offset = moving vector
  308. */
  309. void Move( const wxPoint& offset );
  310. /**
  311. * Function MoveEdge
  312. * Move the outline Edge
  313. * @param offset = moving vector
  314. * @param aEdge = start point of the outline edge
  315. */
  316. void MoveEdge( const wxPoint& offset, int aEdge );
  317. /**
  318. * Function Rotate
  319. * Move the outlines
  320. * @param centre = rot centre
  321. * @param angle = in 0.1 degree
  322. */
  323. void Rotate( const wxPoint& centre, double angle );
  324. /**
  325. * Function Flip
  326. * Flip this object, i.e. change the board side for this object
  327. * (like Mirror() but changes layer)
  328. * @param aCentre - the rotation point.
  329. */
  330. virtual void Flip( const wxPoint& aCentre );
  331. /**
  332. * Function Mirror
  333. * Mirror the outlines , relative to a given horizontal axis
  334. * the layer is not changed
  335. * @param mirror_ref = vertical axis position
  336. */
  337. void Mirror( const wxPoint& mirror_ref );
  338. /**
  339. * Function GetClass
  340. * returns the class name.
  341. * @return wxString
  342. */
  343. wxString GetClass() const
  344. {
  345. return wxT( "ZONE_CONTAINER" );
  346. }
  347. /** Access to m_Poly parameters
  348. */
  349. int GetNumCorners( void ) const
  350. {
  351. return m_Poly->GetCornersCount();
  352. }
  353. void RemoveAllContours( void )
  354. {
  355. m_Poly->RemoveAllContours();
  356. }
  357. const wxPoint& GetCornerPosition( int aCornerIndex ) const
  358. {
  359. return m_Poly->GetPos( aCornerIndex );
  360. }
  361. void SetCornerPosition( int aCornerIndex, wxPoint new_pos )
  362. {
  363. m_Poly->SetX( aCornerIndex, new_pos.x );
  364. m_Poly->SetY( aCornerIndex, new_pos.y );
  365. }
  366. void AppendCorner( wxPoint position )
  367. {
  368. m_Poly->AppendCorner( position.x, position.y );
  369. }
  370. int GetHatchStyle() const
  371. {
  372. return m_Poly->GetHatchStyle();
  373. }
  374. void SetHatchStyle( CPolyLine::HATCH_STYLE aStyle )
  375. {
  376. m_Poly->SetHatchStyle( aStyle );
  377. }
  378. /**
  379. * Function IsSame
  380. * tests if 2 zones are equivalent:
  381. * 2 zones are equivalent if they have same parameters and same outlines
  382. * info, filling is not taken into account
  383. * @param aZoneToCompare = zone to compare with "this"
  384. */
  385. bool IsSame( const ZONE_CONTAINER &aZoneToCompare );
  386. /**
  387. * Function ClearFilledPolysList
  388. * clears the list of filled polygons.
  389. */
  390. void ClearFilledPolysList()
  391. {
  392. m_FilledPolysList.RemoveAllContours();
  393. }
  394. /**
  395. * Function GetFilledPolysList
  396. * returns a reference to the list of filled polygons.
  397. * @return Reference to the list of filled polygons.
  398. */
  399. const SHAPE_POLY_SET& GetFilledPolysList() const
  400. {
  401. return m_FilledPolysList;
  402. }
  403. /**
  404. * Function AddFilledPolysList
  405. * sets the list of filled polygons.
  406. */
  407. void AddFilledPolysList( SHAPE_POLY_SET& aPolysList )
  408. {
  409. m_FilledPolysList = aPolysList;
  410. }
  411. /**
  412. * Function GetSmoothedPoly
  413. * returns a pointer to the corner-smoothed version of
  414. * m_Poly if it exists, otherwise it returns m_Poly.
  415. * @return CPolyLine* - pointer to the polygon.
  416. */
  417. CPolyLine* GetSmoothedPoly() const
  418. {
  419. if( m_smoothedPoly )
  420. return m_smoothedPoly;
  421. else
  422. return m_Poly;
  423. };
  424. void SetCornerSmoothingType( int aType ) { m_cornerSmoothingType = aType; };
  425. int GetCornerSmoothingType() const { return m_cornerSmoothingType; };
  426. void SetCornerRadius( unsigned int aRadius );
  427. unsigned int GetCornerRadius() const { return m_cornerRadius; };
  428. void AddPolygon( std::vector< wxPoint >& aPolygon );
  429. void AddFilledPolygon( SHAPE_POLY_SET& aPolygon )
  430. {
  431. m_FilledPolysList.Append( aPolygon );
  432. }
  433. void AddFillSegments( std::vector< SEGMENT >& aSegments )
  434. {
  435. m_FillSegmList.insert( m_FillSegmList.end(), aSegments.begin(), aSegments.end() );
  436. }
  437. virtual wxString GetSelectMenuText() const;
  438. virtual BITMAP_DEF GetMenuImage() const { return add_zone_xpm; }
  439. virtual EDA_ITEM* Clone() const;
  440. /**
  441. * Accessors to parameters used in Keepout zones:
  442. */
  443. bool GetIsKeepout() const { return m_isKeepout; }
  444. bool GetDoNotAllowCopperPour() const { return m_doNotAllowCopperPour; }
  445. bool GetDoNotAllowVias() const { return m_doNotAllowVias; }
  446. bool GetDoNotAllowTracks() const { return m_doNotAllowTracks; }
  447. void SetIsKeepout( bool aEnable ) { m_isKeepout = aEnable; }
  448. void SetDoNotAllowCopperPour( bool aEnable ) { m_doNotAllowCopperPour = aEnable; }
  449. void SetDoNotAllowVias( bool aEnable ) { m_doNotAllowVias = aEnable; }
  450. void SetDoNotAllowTracks( bool aEnable ) { m_doNotAllowTracks = aEnable; }
  451. #if defined(DEBUG)
  452. virtual void Show( int nestLevel, std::ostream& os ) const { ShowDummy( os ); } // override
  453. #endif
  454. private:
  455. void buildFeatureHoleList( BOARD* aPcb, SHAPE_POLY_SET& aFeatures );
  456. CPolyLine* m_Poly; ///< Outline of the zone.
  457. CPolyLine* m_smoothedPoly; // Corner-smoothed version of m_Poly
  458. int m_cornerSmoothingType;
  459. unsigned int m_cornerRadius;
  460. /* Priority: when a zone outline is inside and other zone, if its priority is higher
  461. * the other zone priority, it will be created inside.
  462. * if priorities are equal, a DRC error is set
  463. */
  464. unsigned m_priority;
  465. /* A zone outline can be a keepout zone.
  466. * It will be never filled, and DRC should test for pads, tracks and vias
  467. */
  468. bool m_isKeepout;
  469. /* For keepout zones only:
  470. * what is not allowed inside the keepout ( pads, tracks and vias )
  471. */
  472. bool m_doNotAllowCopperPour;
  473. bool m_doNotAllowVias;
  474. bool m_doNotAllowTracks;
  475. ZoneConnection m_PadConnection;
  476. int m_ZoneClearance; ///< Clearance value in internal units.
  477. int m_ZoneMinThickness; ///< Minimum thickness value in filled areas.
  478. /** The number of segments to convert a circle to a polygon. Valid values are
  479. #ARC_APPROX_SEGMENTS_COUNT_LOW_DEF or #ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF. */
  480. int m_ArcToSegmentsCount;
  481. /** True when a zone was filled, false after deleting the filled areas. */
  482. bool m_IsFilled;
  483. ///< Width of the gap in thermal reliefs.
  484. int m_ThermalReliefGap;
  485. ///< Width of the copper bridge in thermal reliefs.
  486. int m_ThermalReliefCopperBridge;
  487. /// How to fill areas: 0 => use filled polygons, 1 => fill with segments.
  488. int m_FillMode;
  489. /// The index of the corner being moved or -1 if no corner is selected.
  490. int m_CornerSelection;
  491. /// Variable used in polygon calculations.
  492. int m_localFlgs;
  493. /** Segments used to fill the zone (#m_FillMode ==1 ), when fill zone by segment is used.
  494. * In this case the segments have #m_ZoneMinThickness width.
  495. */
  496. std::vector <SEGMENT> m_FillSegmList;
  497. /* set of filled polygons used to draw a zone as a filled area.
  498. * from outlines (m_Poly) but unlike m_Poly these filled polygons have no hole
  499. * (they are all in one piece) In very simple cases m_FilledPolysList is same
  500. * as m_Poly. In less simple cases (when m_Poly has holes) m_FilledPolysList is
  501. * a polygon equivalent to m_Poly, without holes but with extra outline segment
  502. * connecting "holes" with external main outline. In complex cases an outline
  503. * described by m_Poly can have many filled areas
  504. */
  505. SHAPE_POLY_SET m_FilledPolysList;
  506. };
  507. #endif // CLASS_ZONE_H_