1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wandadoo.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 #ifndef BOARD_ITEM_STRUCT_H
26 #define BOARD_ITEM_STRUCT_H
27 
28 
29 #include <eda_item.h>
30 #include <eda_units.h>
31 #include <convert_to_biu.h>
32 #include <gr_basic.h>
33 #include <layer_ids.h>
34 #include <geometry/geometry_utils.h>
35 
36 class BOARD;
37 class BOARD_ITEM_CONTAINER;
38 class SHAPE_POLY_SET;
39 class PCB_BASE_FRAME;
40 class SHAPE;
41 class PCB_GROUP;
42 
43 
44 /**
45  * A base class for any item which can be embedded within the #BOARD container class, and
46  * therefore instances of derived classes should only be found in Pcbnew or other programs
47  * that use class #BOARD and its contents.
48  */
49 class BOARD_ITEM : public EDA_ITEM
50 {
51 public:
BOARD_ITEM(BOARD_ITEM * aParent,KICAD_T idtype)52     BOARD_ITEM( BOARD_ITEM* aParent, KICAD_T idtype ) :
53             EDA_ITEM( aParent, idtype ),
54             m_layer( F_Cu ),
55             m_group( nullptr )
56     {
57     }
58 
SetParentGroup(PCB_GROUP * aGroup)59     void SetParentGroup( PCB_GROUP* aGroup ) { m_group = aGroup; }
GetParentGroup()60     PCB_GROUP* GetParentGroup() const { return m_group; }
61 
62     // Do not create a copy constructor & operator=.
63     // The ones generated by the compiler are adequate.
GetX()64     int GetX() const
65     {
66         wxPoint p = GetPosition();
67         return p.x;
68     }
69 
GetY()70     int GetY() const
71     {
72         wxPoint p = GetPosition();
73         return p.y;
74     }
75 
76     /**
77      * This defaults to the center of the bounding box if not overridden.
78      *
79      * @return center point of the item
80      */
GetCenter()81     virtual wxPoint GetCenter() const
82     {
83         return GetBoundingBox().GetCenter();
84     }
85 
SetX(int aX)86     void SetX( int aX )
87     {
88         wxPoint p( aX, GetY() );
89         SetPosition( p );
90     }
91 
SetY(int aY)92     void SetY( int aY )
93     {
94         wxPoint p( GetX(), aY );
95         SetPosition( p );
96     }
97 
98     /**
99      * Returns information if the object is derived from BOARD_CONNECTED_ITEM.
100      *
101      * @return True if the object is of BOARD_CONNECTED_ITEM type, false otherwise.
102      */
IsConnected()103     virtual bool IsConnected() const
104     {
105         return false;
106     }
107 
108     /**
109      * @return true if the object is on any copper layer, false otherwise.
110      */
IsOnCopperLayer()111     virtual bool IsOnCopperLayer() const
112     {
113         return IsCopperLayer( GetLayer() );
114     }
115 
116     /**
117      * A value of wxPoint(0,0) which can be passed to the Draw() functions.
118      */
119     static wxPoint ZeroOffset;
120 
121     /**
122      * Some pad shapes can be complex (rounded/chamfered rectangle), even without considering
123      * custom shapes.  This routine returns a COMPOUND shape (set of simple shapes which make
124      * up the pad for use with routing, collision determination, etc).
125      *
126      * @note This list can contain a SHAPE_SIMPLE (a simple single-outline non-intersecting
127      * polygon), but should never contain a SHAPE_POLY_SET (a complex polygon consisting of
128      * multiple outlines and/or holes).
129      *
130      * @param aLayer in case of items spanning multiple layers, only the shapes belonging to aLayer
131      *               will be returned. Pass UNDEFINED_LAYER to return shapes for all layers.
132      */
133     virtual std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const;
134 
GetParent()135     BOARD_ITEM_CONTAINER* GetParent() const { return (BOARD_ITEM_CONTAINER*) m_parent; }
136 
137     BOARD_ITEM_CONTAINER* GetParentFootprint() const;
138 
139     /**
140      * Return the primary layer this item is on.
141      */
GetLayer()142     virtual PCB_LAYER_ID GetLayer() const { return m_layer; }
143 
144     /**
145      * Return a std::bitset of all layers on which the item physically resides.
146      */
GetLayerSet()147     virtual LSET GetLayerSet() const { return LSET( m_layer ); }
SetLayerSet(LSET aLayers)148     virtual void SetLayerSet( LSET aLayers )
149     {
150         wxFAIL_MSG( "Attempted to SetLayerSet() on a single-layer object." );
151 
152         // Derived classes which support multiple layers must implement this
153     }
154 
155     /**
156      * Set the layer this item is on.
157      *
158      * This method is virtual because some items (in fact: class DIMENSION)
159      * have a slightly different initialization.
160      *
161      * @param aLayer The layer number.
162      */
SetLayer(PCB_LAYER_ID aLayer)163     virtual void SetLayer( PCB_LAYER_ID aLayer )
164     {
165         m_layer = aLayer;
166     }
167 
168     /**
169      * Create a copy of this #BOARD_ITEM.
170      */
Duplicate()171     virtual BOARD_ITEM* Duplicate() const
172     {
173         EDA_ITEM* dupe = Clone();
174         const_cast<KIID&>( dupe->m_Uuid ) = KIID();
175 
176         return static_cast<BOARD_ITEM*>( dupe );
177     }
178 
179     /**
180      * Swap data between \a aItem and \a aImage.
181      *
182      * \a aItem and \a aImage should have the same type.
183      *
184      * Used in undo and redo commands to swap values between an item and its copy.
185      * Only values like layer, size .. which are modified by editing are swapped.
186      *
187      * @param aImage the item image which contains data to swap.
188      */
189     virtual void SwapData( BOARD_ITEM* aImage );
190 
191     /**
192      * Test to see if this object is on the given layer.
193      *
194      * Virtual so objects like #PAD, which reside on multiple layers can do their own form
195      * of testing.
196      *
197      * @param aLayer The layer to test for.
198      * @return true if on given layer, else false.
199      */
IsOnLayer(PCB_LAYER_ID aLayer)200     virtual bool IsOnLayer( PCB_LAYER_ID aLayer ) const
201     {
202         return m_layer == aLayer;
203     }
204 
205     /**
206      * Test to see if this object is a track or via (or microvia).
207      *
208      * @return true if a track or via, else false.
209      */
IsTrack()210     bool IsTrack() const
211     {
212         return ( Type() == PCB_TRACE_T ) || ( Type() == PCB_VIA_T );
213     }
214 
215     /**
216      * @return true if the object is locked, else false.
217      */
218     virtual bool IsLocked() const;
219 
220     /**
221      * Modify the 'lock' status for of the item.
222      */
SetLocked(bool aLocked)223     virtual void SetLocked( bool aLocked )
224     {
225         SetState( LOCKED, aLocked );
226     }
227 
228     /**
229      * Delete this object after removing from its parent if it has one.
230      */
231     void DeleteStructure();
232 
233     /**
234      * Move this object.
235      *
236      * @param aMoveVector the move vector for this object.
237      */
Move(const wxPoint & aMoveVector)238     virtual void Move( const wxPoint& aMoveVector )
239     {
240         wxFAIL_MSG( "virtual BOARD_ITEM::Move called for " + GetClass() );
241     }
242 
Move(const VECTOR2I & aMoveVector)243     void Move( const VECTOR2I& aMoveVector )
244     {
245         Move( wxPoint( aMoveVector.x, aMoveVector.y ) );
246     }
247 
248     /**
249      * Rotate this object.
250      *
251      * @param aRotCentre the rotation point.
252      * @param aAngle the rotation angle in 0.1 degree.
253      */
254     virtual void Rotate( const wxPoint& aRotCentre, double aAngle );
255 
Rotate(const VECTOR2I & aRotCentre,double aAngle)256     void Rotate( const VECTOR2I& aRotCentre, double aAngle )
257     {
258         Rotate( wxPoint( aRotCentre.x, aRotCentre.y ), aAngle );
259     }
260 
261     /**
262      * Flip this object, i.e. change the board side for this object.
263      *
264      * @param aCentre the rotation point.
265      * @param aFlipLeftRight mirror across Y axis instead of X (the default).
266      */
267     virtual void Flip( const wxPoint& aCentre, bool aFlipLeftRight );
268 
Flip(const VECTOR2I & aCentre,bool aFlipLeftRight)269     void Flip( const VECTOR2I& aCentre, bool aFlipLeftRight )
270     {
271         Flip( wxPoint( aCentre.x, aCentre.y ), aFlipLeftRight );
272     }
273 
274     /**
275      * Return the #BOARD in which this #BOARD_ITEM resides, or NULL if none.
276      */
277     virtual const BOARD* GetBoard() const;
278     virtual BOARD* GetBoard();
279 
280     /**
281      * Return the name of the PCB layer on which the item resides.
282      *
283      * @return the layer name associated with this item.
284      */
285     wxString GetLayerName() const;
286 
287     virtual void ViewGetLayers( int aLayers[], int& aCount ) const override;
288 
289     /**
290      * Convert the item shape to a closed polygon.
291      *
292      * Used in filling zones calculations.  Circles and arcs are approximated by segments.
293      *
294      * @param aCornerBuffer a buffer to store the polygon.
295      * @param aClearanceValue the clearance around the pad.
296      * @param aError the maximum deviation from true circle.
297      * @param aErrorLoc should the approximation error be placed outside or inside the polygon?
298      * @param ignoreLineWidth used for edge cut items where the line width is only
299      *                        for visualization.
300      */
301     virtual void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer,
302                                                        PCB_LAYER_ID aLayer, int aClearanceValue,
303                                                        int aError, ERROR_LOC aErrorLoc,
304                                                        bool ignoreLineWidth = false ) const;
305 
306     struct ptr_cmp
307     {
308         bool operator() ( const BOARD_ITEM* a, const BOARD_ITEM* b ) const;
309     };
310 
311 protected:
312     /**
313      * Return a string (to be shown to the user) describing a layer mask. The BOARD is needed
314      * because layer names are customizable.
315      */
316     virtual wxString layerMaskDescribe() const;
317 
318     PCB_LAYER_ID    m_layer;
319     PCB_GROUP*      m_group;
320 };
321 
322 #ifndef SWIG
323 DECLARE_ENUM_TO_WXANY( PCB_LAYER_ID );
324 #endif
325 
326 
327 /**
328  * A singleton item of this class is returned for a weak reference that no longer exists.
329  *
330  * Its sole purpose is to flag the item as having been deleted.
331  */
332 class DELETED_BOARD_ITEM : public BOARD_ITEM
333 {
334 public:
DELETED_BOARD_ITEM()335     DELETED_BOARD_ITEM() :
336         BOARD_ITEM( nullptr, NOT_USED )
337     {}
338 
GetSelectMenuText(EDA_UNITS aUnits)339     wxString GetSelectMenuText( EDA_UNITS aUnits ) const override
340     {
341         return _( "(Deleted Item)" );
342     }
343 
GetClass()344     wxString GetClass() const override
345     {
346         return wxT( "DELETED_BOARD_ITEM" );
347     }
348 
349     // pure virtuals:
SetPosition(const wxPoint &)350     void SetPosition( const wxPoint& ) override {}
GetPosition()351     wxPoint GetPosition() const override { return wxPoint(0, 0); }
352 
GetInstance()353     static DELETED_BOARD_ITEM* GetInstance()
354     {
355         static DELETED_BOARD_ITEM* item = nullptr;
356 
357         if( !item )
358             item = new DELETED_BOARD_ITEM();
359 
360         return item;
361     }
362 
363 #if defined(DEBUG)
Show(int,std::ostream &)364     void Show( int , std::ostream& ) const override {}
365 #endif
366 };
367 
368 
369 #endif /* BOARD_ITEM_STRUCT_H */
370