/* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wandadoo.fr * Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, you may find one here: * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * or you may search the http://www.gnu.org website for the version 2 license, * or you may write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ /** * @file class_board_item.h * @brief Classes BOARD_ITEM and BOARD_CONNECTED_ITEM. */ #ifndef BOARD_ITEM_STRUCT_H #define BOARD_ITEM_STRUCT_H #include #include #include #include #include #include #include class BOARD; class BOARD_ITEM_CONTAINER; class SHAPE_POLY_SET; class PCB_BASE_FRAME; class SHAPE; class PCB_GROUP; /** * Enum PCB_SHAPE_TYPE_T * is the set of shapes for PCB graphics and tracks and footprint graphics * in the .m_Shape member */ enum PCB_SHAPE_TYPE_T { S_SEGMENT = 0, ///< usual segment : line with rounded ends S_RECT, ///< segment with non rounded ends S_ARC, ///< Arcs (with rounded ends) S_CIRCLE, ///< ring S_POLYGON, ///< polygon (not yet used for tracks, but could be in microwave apps) S_CURVE, ///< Bezier Curve S_LAST ///< last value for this list }; static inline wxString PCB_SHAPE_TYPE_T_asString( PCB_SHAPE_TYPE_T a ) { switch( a ) { case S_SEGMENT: return "S_SEGMENT"; case S_RECT: return "S_RECT"; case S_ARC: return "S_ARC"; case S_CIRCLE: return "S_CIRCLE"; case S_POLYGON: return "S_POLYGON"; case S_CURVE: return "S_CURVE"; case S_LAST: return "S_LAST"; // Synthetic value, but if we come across it we're // going to want to know. } return wxEmptyString; // Just to quiet GCC. }; /** * BOARD_ITEM * is a base class for any item which can be embedded within the BOARD * container class, and therefore instances of derived classes should only be * found in Pcbnew or other programs that use class BOARD and its contents. * The corresponding class in Eeschema is SCH_ITEM. */ class BOARD_ITEM : public EDA_ITEM { protected: PCB_LAYER_ID m_Layer; PCB_GROUP* m_group; public: BOARD_ITEM( BOARD_ITEM* aParent, KICAD_T idtype ) : EDA_ITEM( aParent, idtype ), m_Layer( F_Cu ), m_group( nullptr ) { } void SetParentGroup( PCB_GROUP* aGroup ) { m_group = aGroup; } PCB_GROUP* GetParentGroup() const { return m_group; } // Do not create a copy constructor & operator=. // The ones generated by the compiler are adequate. int GetX() const { wxPoint p = GetPosition(); return p.x; } int GetY() const { wxPoint p = GetPosition(); return p.y; } /** * Function GetCenter() * * This defaults to the center of the bounding box if not overridden. * * @return centre point of the item */ virtual wxPoint GetCenter() const { return GetBoundingBox().GetCenter(); } void SetX( int aX ) { wxPoint p( aX, GetY() ); SetPosition( p ); } void SetY( int aY ) { wxPoint p( GetX(), aY ); SetPosition( p ); } /** * Function IsConnected() * Returns information if the object is derived from BOARD_CONNECTED_ITEM. * @return True if the object is of BOARD_CONNECTED_ITEM type, false otherwise. */ virtual bool IsConnected() const { return false; } /** * @return true if the object is on any copper layer, false otherwise. */ virtual bool IsOnCopperLayer() const { return IsCopperLayer( GetLayer() ); } /** * A value of wxPoint(0,0) which can be passed to the Draw() functions. */ static wxPoint ZeroOffset; /** * Function GetEffectiveShape * Some pad shapes can be complex (rounded/chamfered rectangle), even without considering * custom shapes. This routine returns a COMPOUND shape (set of simple shapes which make * up the pad fod use with routing, collision determiniation, etc). * * Note that this list can contain a SHAPE_SIMPLE (a simple single-outline non-intersecting * polygon), but should never contain a SHAPE_POLY_SET (a complex polygon consisting of * multiple outlines and/or holes). * * @param aLayer in case of items spanning multiple layers, only the shapes belonging to aLayer * will be returned. Pass UNDEFINED_LAYER to return shapes for all layers. */ virtual std::shared_ptr GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const; BOARD_ITEM_CONTAINER* GetParent() const { return (BOARD_ITEM_CONTAINER*) m_Parent; } /** * Function GetLayer * returns the primary layer this item is on. */ virtual PCB_LAYER_ID GetLayer() const { return m_Layer; } /** * Function GetLayerSet * returns a std::bitset of all layers on which the item physically resides. */ virtual LSET GetLayerSet() const { return LSET( m_Layer ); } virtual void SetLayerSet( LSET aLayers ) { wxFAIL_MSG( "Attempted to SetLayerSet() on a single-layer object." ); // Derived classes which support multiple layers must implement this } /** * Function SetLayer * sets the layer this item is on. * @param aLayer The layer number. * is virtual because some items (in fact: class DIMENSION) * have a slightly different initialization */ virtual void SetLayer( PCB_LAYER_ID aLayer ) { m_Layer = aLayer; } /** * Function Duplicate * creates a copy of a BOARD_ITEM. */ virtual BOARD_ITEM* Duplicate() const { EDA_ITEM* dupe = Clone(); const_cast( dupe->m_Uuid ) = KIID(); return static_cast( dupe ); } /** * Swap data between aItem and aImage. * aItem and aImage should have the same type * Used in undo redo command to swap values between an item and its copy * Only values like layer, size .. which are modified by editing are swapped * @param aImage = the item image which contains data to swap */ virtual void SwapData( BOARD_ITEM* aImage ); /** * Function IsOnLayer * tests to see if this object is on the given layer. Is virtual so * objects like D_PAD, which reside on multiple layers can do their own * form of testing. * @param aLayer The layer to test for. * @return bool - true if on given layer, else false. */ virtual bool IsOnLayer( PCB_LAYER_ID aLayer ) const { return m_Layer == aLayer; } /** * Function IsTrack * tests to see if this object is a track or via (or microvia). * form of testing. * @return bool - true if a track or via, else false. */ bool IsTrack() const { return ( Type() == PCB_TRACE_T ) || ( Type() == PCB_VIA_T ); } /** * Function IsLocked * @return bool - true if the object is locked, else false */ virtual bool IsLocked() const { // only footprints & TRACKs can be locked at this time. return false; } /** * Function SetLocked * modifies 'lock' status for of the item. */ virtual void SetLocked( bool aLocked ) { // only footprints & TRACKs can be locked at this time. } /** * Function DeleteStructure * deletes this object after removing from its parent if it has one. */ void DeleteStructure(); /** * Function ShowShape * converts the enum PCB_SHAPE_TYPE_T integer value to a wxString. */ static wxString ShowShape( PCB_SHAPE_TYPE_T aShape ); // Some geometric transforms, that must be rewritten for derived classes /** * Function Move * move this object. * @param aMoveVector - the move vector for this object. */ virtual void Move( const wxPoint& aMoveVector ) { wxFAIL_MSG( wxString::Format( wxT( "virtual BOARD_ITEM::Move called for %s" ), GetClass() ) ); } void Move( const VECTOR2I& aMoveVector ) { Move( wxPoint( aMoveVector.x, aMoveVector.y ) ); } /** * Function Rotate * Rotate this object. * @param aRotCentre - the rotation point. * @param aAngle - the rotation angle in 0.1 degree. */ virtual void Rotate( const wxPoint& aRotCentre, double aAngle ) { wxMessageBox( wxT( "virtual BOARD_ITEM::Rotate used, should not occur" ), GetClass() ); } void Rotate( const VECTOR2I& aRotCentre, double aAngle ) { Rotate( wxPoint( aRotCentre.x, aRotCentre.y ), aAngle ); } /** * Function Flip * Flip this object, i.e. change the board side for this object * @param aCentre - the rotation point. * @param aFlipLeftRight - mirror across Y axis instead of X (the default) */ virtual void Flip( const wxPoint& aCentre, bool aFlipLeftRight ) { wxMessageBox( wxT( "virtual BOARD_ITEM::Flip used, should not occur" ), GetClass() ); } void Flip( const VECTOR2I& aCentre, bool aFlipLeftRight ) { Flip( wxPoint( aCentre.x, aCentre.y ), aFlipLeftRight ); } /** * Function GetBoard * returns the BOARD in which this BOARD_ITEM resides, or NULL if none. */ virtual BOARD* GetBoard() const; /** * Function GetLayerName * returns the name of the PCB layer on which the item resides. * * @return wxString containing the layer name associated with this item. */ wxString GetLayerName() const; virtual void ViewGetLayers( int aLayers[], int& aCount ) const override; /** * Function TransformShapeWithClearanceToPolygon * Convert the item shape to a closed polygon * Used in filling zones calculations * Circles and arcs are approximated by segments * @param aCornerBuffer = a buffer to store the polygon * @param aClearanceValue = the clearance around the pad * @param aError = the maximum deviation from true circle * @param aErrorLoc = should the approximation error be placed outside or inside the polygon? * @param ignoreLineWidth = used for edge cut items where the line width is only * for visualization */ virtual void TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, PCB_LAYER_ID aLayer, int aClearanceValue, int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth = false ) const; struct ptr_cmp { bool operator() ( const BOARD_ITEM* a, const BOARD_ITEM* b ) const; }; protected: /** * Helper function * Return a string (to be shown to the user) describing a layer mask. * The BOARD is needed because layer names are (somewhat) customizable */ virtual wxString LayerMaskDescribe() const; }; #ifndef SWIG DECLARE_ENUM_TO_WXANY( PCB_LAYER_ID ); #endif /** * A singleton item of this class is returned for a weak reference that no longer exists. * Its sole purpose is to flag the item as having been deleted. */ class DELETED_BOARD_ITEM : public BOARD_ITEM { public: DELETED_BOARD_ITEM() : BOARD_ITEM( nullptr, NOT_USED ) {} wxString GetSelectMenuText( EDA_UNITS aUnits ) const override { return _( "(Deleted Item)" ); } wxString GetClass() const override { return wxT( "DELETED_BOARD_ITEM" ); } // pure virtuals: void SetPosition( const wxPoint& ) override {} wxPoint GetPosition() const override { return wxPoint(0, 0); } static DELETED_BOARD_ITEM* GetInstance() { static DELETED_BOARD_ITEM* item = nullptr; if( !item ) item = new DELETED_BOARD_ITEM(); return item; } #if defined(DEBUG) void Show( int , std::ostream& ) const override {} #endif }; #endif /* BOARD_ITEM_STRUCT_H */