kicad/pcbnew/pcb_track.h

615 lines
19 KiB
C
Raw Normal View History

/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
* Copyright (C) 1992-2023 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
*/
/**
2021-06-11 21:07:02 +00:00
* @brief A single base class (PCB_TRACK) represents both tracks and vias, with subclasses
* for curved tracks (PCB_ARC) and vias (PCB_VIA). All told there are three KICAD_Ts:
* PCB_TRACK_T, PCB_ARC_T, and PCB_VIA_T.
*
* For vias there is a further VIATYPE which indicates THROUGH, BLIND_BURIED, or
* MICROVIA, which are supported by the synthetic KICAD_Ts PCB_LOCATE_STDVIA_T,
* PCB_LOCATE_BBVIA_T, and PCB_LOCATE_UVIA_T.
*/
#ifndef CLASS_TRACK_H
#define CLASS_TRACK_H
2023-01-15 17:18:56 +00:00
#include <mutex>
#include <array>
2018-02-02 20:57:12 +00:00
#include <board_connected_item.h>
#include <base_units.h>
#include <geometry/shape_segment.h>
#include <core/minoptmax.h>
#include <core/arraydim.h>
2021-06-11 21:07:02 +00:00
class PCB_TRACK;
class PCB_VIA;
2020-11-12 22:30:02 +00:00
class PAD;
class MSG_PANEL_ITEM;
class SHAPE_POLY_SET;
2021-06-06 12:59:05 +00:00
class SHAPE_ARC;
// Flag used in locate routines (from which endpoint work)
enum ENDPOINT_T : int
{
ENDPOINT_START = 0,
ENDPOINT_END = 1
};
// Note that this enum must be synchronized to GAL_LAYER_ID
enum class VIATYPE : int
{
2019-12-28 00:55:11 +00:00
THROUGH = 3, /* Always a through hole via */
BLIND_BURIED = 2, /* this via can be on internal layers */
MICROVIA = 1, /* this via which connect from an external layer
* to the near neighbor internal layer */
2019-12-28 00:55:11 +00:00
NOT_DEFINED = 0 /* not yet used */
};
#define UNDEFINED_DRILL_DIAMETER -1 //< Undefined via drill diameter.
// Used for tracks and vias for algorithmic safety, not to enforce constraints
2022-09-17 00:45:14 +00:00
#define GEOMETRY_MIN_SIZE (int) ( 0.001 * pcbIUScale.IU_PER_MM )
2021-06-11 21:07:02 +00:00
class PCB_TRACK : public BOARD_CONNECTED_ITEM
{
public:
static inline bool ClassOf( const EDA_ITEM* aItem )
{
return aItem && PCB_TRACE_T == aItem->Type();
}
2021-06-11 21:07:02 +00:00
PCB_TRACK( BOARD_ITEM* aParent, KICAD_T idtype = PCB_TRACE_T );
2007-09-01 12:00:30 +00:00
// Do not create a copy constructor. The one generated by the compiler is adequate.
2007-08-08 20:51:08 +00:00
void Move( const VECTOR2I& aMoveVector ) override
2009-08-01 19:26:05 +00:00
{
m_Start += aMoveVector;
2011-12-01 22:50:41 +00:00
m_End += aMoveVector;
2009-08-01 19:26:05 +00:00
}
void Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle ) override;
2009-08-01 19:26:05 +00:00
virtual void Mirror( const VECTOR2I& aCentre, bool aMirrorAroundXAxis );
void Flip( const VECTOR2I& aCentre, bool aFlipLeftRight ) override;
2009-08-01 19:26:05 +00:00
void SetPosition( const VECTOR2I& aPos ) override { m_Start = aPos; }
VECTOR2I GetPosition() const override { return m_Start; }
const VECTOR2I GetFocusPosition() const override { return ( m_Start + m_End ) / 2; }
2011-12-14 04:29:25 +00:00
void SetWidth( int aWidth ) { m_Width = aWidth; }
int GetWidth() const { return m_Width; }
2011-11-30 07:43:46 +00:00
void SetEnd( const VECTOR2I& aEnd ) { m_End = aEnd; }
const VECTOR2I& GetEnd() const { return m_End; }
void SetStart( const VECTOR2I& aStart ) { m_Start = aStart; }
const VECTOR2I& GetStart() const { return m_Start; }
2011-11-30 07:43:46 +00:00
void SetEndX( int aX ) { m_End.x = aX; }
void SetEndY( int aY ) { m_End.y = aY; }
int GetEndX() const { return m_End.x; }
2021-01-31 20:43:12 +00:00
int GetEndY() const { return m_End.y; }
/// Return the selected endpoint (start or end)
const VECTOR2I& GetEndPoint( ENDPOINT_T aEndPoint ) const
{
if( aEndPoint == ENDPOINT_START )
return m_Start;
else
return m_End;
}
// Virtual function
2022-08-31 09:15:42 +00:00
const BOX2I GetBoundingBox() const override;
2008-03-05 22:39:33 +00:00
2007-10-13 06:18:44 +00:00
/**
* Get the length of the track using the hypotenuse calculation.
*
* @return the length of the track.
2007-10-13 06:18:44 +00:00
*/
2021-06-06 12:59:05 +00:00
virtual double GetLength() const;
2010-11-12 15:17:10 +00:00
/**
* Convert the track shape to a closed polygon.
*
* Circles (vias) and arcs (ends of tracks) are approximated by segments.
*
* @param aBuffer is a buffer to store the polygon
* @param aClearance is the clearance around the pad
* @param aError is the maximum deviation from true circle
* @param ignoreLineWidth is used for edge cut items where the line width is only for
* visualization
*/
void TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, int aClearance,
int aError, ERROR_LOC aErrorLoc,
bool ignoreLineWidth = false ) const override;
// @copydoc BOARD_ITEM::GetEffectiveShape
std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER,
FLASHING aFlash = FLASHING::DEFAULT ) const override;
/**
* Return STARTPOINT if point if near (dist = min_dist) start point, ENDPOINT if
* point if near (dist = min_dist) end point,STARTPOINT|ENDPOINT if point if near
* (dist = min_dist) both ends, or 0 if none of the above.
*
* If min_dist < 0: min_dist = track_width/2
*/
EDA_ITEM_FLAGS IsPointOnEnds( const VECTOR2I& point, int min_dist = 0 ) const;
/**
* Return true if segment length is zero.
*/
2019-05-31 02:30:28 +00:00
bool IsNull() const
{
return ( Type() == PCB_VIA_T ) || ( m_Start == m_End );
}
2007-08-08 20:51:08 +00:00
void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
2022-12-22 22:44:40 +00:00
wxString GetFriendlyName() const override;
INSPECT_RESULT Visit( INSPECTOR inspector, void* testData,
const std::vector<KICAD_T>& aScanTypes ) override;
bool HitTest( const VECTOR2I& aPosition, int aAccuracy = 0 ) const override;
2022-08-31 09:33:46 +00:00
bool HitTest( const BOX2I& aRect, bool aContained, int aAccuracy = 0 ) const override;
2021-06-11 21:07:02 +00:00
bool ApproxCollinear( const PCB_TRACK& aTrack );
2016-09-24 18:53:15 +00:00
wxString GetClass() const override
2007-08-08 20:51:08 +00:00
{
2021-06-11 21:07:02 +00:00
return wxT( "PCB_TRACK" );
2007-08-08 20:51:08 +00:00
}
/**
* Return any local clearance overrides set in the "classic" (ie: pre-rule) system.
*
* @param aSource [out] optionally reports the source as a user-readable string
* @return int - the clearance in internal units.
*/
int GetLocalClearance( wxString* aSource ) const override;
MINOPTMAX<int> GetWidthConstraint( wxString* aSource = nullptr ) const;
wxString GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const override;
BITMAPS GetMenuImage() const override;
2016-09-24 18:53:15 +00:00
virtual EDA_ITEM* Clone() const override;
2016-09-24 18:53:15 +00:00
virtual void ViewGetLayers( int aLayers[], int& aCount ) const override;
2013-07-08 07:57:23 +00:00
double ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const override;
2013-07-08 07:57:23 +00:00
const BOX2I ViewBBox() const override;
/**
* @return true because a track or a via is always on a copper layer.
*/
bool IsOnCopperLayer() const override
{
return true;
}
/**
* Get last used LOD for the track net name.
*
* @return LOD from ViewGetLOD()
*/
double GetCachedLOD()
{
return m_CachedLOD;
}
/**
* Set the cached LOD.
*
* @param aLOD value from ViewGetLOD() or 0.0 to always display.
*/
void SetCachedLOD( double aLOD )
{
m_CachedLOD = aLOD;
}
/**
* Get last used zoom scale for the track net name.
*
* @return scale from GetScale()
*/
double GetCachedScale()
{
return m_CachedScale;
}
/**
* Set the cached scale.
*
* @param aScale value from GetScale()
*/
void SetCachedScale( double aScale )
{
m_CachedScale = aScale;
}
struct cmp_tracks
{
2021-06-11 21:07:02 +00:00
bool operator()( const PCB_TRACK* aFirst, const PCB_TRACK* aSecond ) const;
};
#if defined (DEBUG)
2016-09-24 18:53:15 +00:00
virtual void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
#endif
protected:
virtual void swapData( BOARD_ITEM* aImage ) override;
void GetMsgPanelInfoBase_Common( EDA_DRAW_FRAME* aFrame,
std::vector<MSG_PANEL_ITEM>& aList ) const;
protected:
int m_Width; ///< Thickness of track, or via diameter
VECTOR2I m_Start; ///< Line start point
VECTOR2I m_End; ///< Line end point
double m_CachedLOD; ///< Last LOD used to draw this track's net
double m_CachedScale; ///< Last zoom scale used to draw this track's net.
};
2007-09-01 12:00:30 +00:00
2021-06-11 21:07:02 +00:00
class PCB_ARC : public PCB_TRACK
{
public:
2021-06-11 21:07:02 +00:00
PCB_ARC( BOARD_ITEM* aParent ) :
PCB_TRACK( aParent, PCB_ARC_T )
{
};
2021-06-11 21:07:02 +00:00
PCB_ARC( BOARD_ITEM* aParent, const SHAPE_ARC* aArc );
static inline bool ClassOf( const EDA_ITEM *aItem )
{
return aItem && PCB_ARC_T == aItem->Type();
}
virtual void Move( const VECTOR2I& aMoveVector ) override
{
m_Start += aMoveVector;
m_Mid += aMoveVector;
m_End += aMoveVector;
}
void Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle ) override;
void Mirror( const VECTOR2I& aCentre, bool aMirrorAroundXAxis ) override;
void Flip( const VECTOR2I& aCentre, bool aFlipLeftRight ) override;
void SetMid( const VECTOR2I& aMid ) { m_Mid = aMid; }
const VECTOR2I& GetMid() const { return m_Mid; }
void SetPosition( const VECTOR2I& aPos ) override
{
m_Start = aPos;
}
virtual VECTOR2I GetPosition() const override;
virtual VECTOR2I GetCenter() const override { return GetPosition(); }
double GetRadius() const;
2022-01-14 15:34:41 +00:00
EDA_ANGLE GetAngle() const;
EDA_ANGLE GetArcAngleStart() const;
EDA_ANGLE GetArcAngleEnd() const;
virtual bool HitTest( const VECTOR2I& aPosition, int aAccuracy = 0 ) const override;
virtual bool HitTest( const BOX2I& aRect, bool aContained = true,
int aAccuracy = 0 ) const override;
bool IsCCW() const;
wxString GetClass() const override
{
2021-06-11 21:07:02 +00:00
return wxT( "PCB_ARC" );
}
2020-08-13 10:08:16 +00:00
// @copydoc BOARD_ITEM::GetEffectiveShape
std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER,
FLASHING aFlash = FLASHING::DEFAULT ) const override;
2020-08-13 10:08:16 +00:00
/**
* Return the length of the arc track.
*
* @return double - the length of the track
*/
virtual double GetLength() const override
{
2022-01-14 15:34:41 +00:00
return GetRadius() * std::abs( GetAngle().AsRadians() );
}
EDA_ITEM* Clone() const override;
/**
* @return true if the arc is too small to allow a safe calculation
* of center position and arc angles i.e if distance between m_Mid and each arc end
* is only a few internal units.
* @param aThreshold is the minimal dist in internal units. Default id 5 IU
*/
bool IsDegenerated( int aThreshold = 5 ) const;
protected:
virtual void swapData( BOARD_ITEM* aImage ) override;
private:
VECTOR2I m_Mid; ///< Arc mid point, halfway between start and end
};
2021-06-11 21:07:02 +00:00
class PCB_VIA : public PCB_TRACK
{
public:
2021-06-11 21:07:02 +00:00
PCB_VIA( BOARD_ITEM* aParent );
2007-09-01 12:00:30 +00:00
static inline bool ClassOf( const EDA_ITEM *aItem )
{
return aItem && PCB_VIA_T == aItem->Type();
}
PCB_VIA( const PCB_VIA& aOther );
PCB_VIA& operator=( const PCB_VIA &aOther );
bool IsType( const std::vector<KICAD_T>& aScanTypes ) const override
{
if( BOARD_CONNECTED_ITEM::IsType( aScanTypes ) )
return true;
for( KICAD_T scanType : aScanTypes )
{
if( scanType == PCB_LOCATE_STDVIA_T && m_viaType == VIATYPE::THROUGH )
return true;
else if( scanType == PCB_LOCATE_UVIA_T && m_viaType == VIATYPE::MICROVIA )
return true;
else if( scanType == PCB_LOCATE_BBVIA_T && m_viaType == VIATYPE::BLIND_BURIED )
return true;
}
return false;
}
2020-11-14 14:29:11 +00:00
VIATYPE GetViaType() const { return m_viaType; }
void SetViaType( VIATYPE aViaType ) { m_viaType = aViaType; }
bool HasHole() const override
{
return true;
}
std::shared_ptr<SHAPE_SEGMENT> GetEffectiveHoleShape() const override;
bool IsTented() const override;
int GetSolderMaskExpansion() const;
bool IsOnLayer( PCB_LAYER_ID aLayer ) const override;
2016-09-24 18:53:15 +00:00
virtual LSET GetLayerSet() const override;
/**
* Note SetLayerSet() initialize the first and last copper layers connected by the via.
* So currently SetLayerSet ignore non copper layers
*/
virtual void SetLayerSet( LSET aLayers ) override;
/**
* For a via m_layer contains the top layer, the other layer is in m_bottomLayer/
*
* @param aTopLayer is the first layer connected by the via.
* @param aBottomLayer is last layer connected by the via.
*/
void SetLayerPair( PCB_LAYER_ID aTopLayer, PCB_LAYER_ID aBottomLayer );
void SetBottomLayer( PCB_LAYER_ID aLayer );
void SetTopLayer( PCB_LAYER_ID aLayer );
/**
* Return the 2 layers used by the via (the via actually uses all layers between these
* 2 layers)
*
* @param[out] top_layer is storage for the first layer of the via (can be null).
* @param[out] bottom_layer is storage for the last layer of the via(can be null).
*/
void LayerPair( PCB_LAYER_ID* top_layer, PCB_LAYER_ID* bottom_layer ) const;
PCB_LAYER_ID TopLayer() const;
PCB_LAYER_ID BottomLayer() const;
/**
* Check so that the layers are correct depending on the type of via, and
* so that the top actually is on top.
*/
void SanitizeLayers();
VECTOR2I GetPosition() const override { return m_Start; }
void SetPosition( const VECTOR2I& aPoint ) override { m_Start = aPoint; m_End = aPoint; }
void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
bool HitTest( const VECTOR2I& aPosition, int aAccuracy = 0 ) const override;
2022-08-31 09:33:46 +00:00
bool HitTest( const BOX2I& aRect, bool aContained, int aAccuracy = 0 ) const override;
2014-05-01 06:50:11 +00:00
2016-09-24 18:53:15 +00:00
wxString GetClass() const override
2007-08-08 20:51:08 +00:00
{
2021-06-11 21:07:02 +00:00
return wxT( "PCB_VIA" );
2007-08-08 20:51:08 +00:00
}
wxString GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const override;
BITMAPS GetMenuImage() const override;
2016-09-24 18:53:15 +00:00
EDA_ITEM* Clone() const override;
void ViewGetLayers( int aLayers[], int& aCount ) const override;
Introduction of Graphics Abstraction Layer based rendering for pcbnew. New classes: - VIEW - represents view that is seen by user, takes care of layer ordering & visibility and how it is displayed (which location, how much zoomed, etc.) - VIEW_ITEM - Base class for every item that can be displayed on VIEW (the biggest change is that now it may be necessary to override ViewBBox & ViewGetLayers method for derived classes). - EDA_DRAW_PANEL_GAL - Inherits after EDA_DRAW_PANEL, displays VIEW output, right now it is not editable (in opposite to usual EDA_DRAW_PANEL). - GAL/OPENGL_GAL/CAIRO_GAL - Base Graphics Abstraction Layer class + two different flavours (Cairo is not fully supported yet), that offers methods to draw primitives using different libraries. - WX_VIEW_CONTROLS - Controller for VIEW, handles user events, allows zooming, panning, etc. - PAINTER/PCB_PAINTER - Classes that uses GAL interface to draw items (as you may have already guessed - PCB_PAINTER is a class for drawing PCB specific object, PAINTER is an abstract class). Its methods are invoked by VIEW, when an item has to be drawn. To display a new type of item - you need to implement draw(ITEM_TYPE*) method that draws it using GAL methods. - STROKE_FONT - Implements stroke font drawing using GAL methods. Most important changes to Kicad original code: * EDA_ITEM now inherits from VIEW_ITEM, which is a base class for all drawable objects. * EDA_DRAW_FRAME contains both usual EDA_DRAW_PANEL and new EDA_DRAW_PANEL_GAL, that can be switched anytime. * There are some new layers for displaying multilayer pads, vias & pads holes (these are not shown yet on the right sidebar in pcbnew) * Display order of layers is different than in previous versions (if you are curious - you may check m_galLayerOrder@pcbnew/basepcbframe.cpp). Preserving usual order would result in not very natural display, such as showing silkscreen texts on the bottom. * Introduced new hotkey (Alt+F12) and new menu option (View->Switch canvas) for switching canvas during runtime. * Some of classes (mostly derived from BOARD_ITEM) now includes ViewBBox & ViewGetLayers methods. * Removed tools/class_painter.h, as now it is extended and included in source code. Build changes: * GAL-based rendering option is turned on by a new compilation CMake option KICAD_GAL. * When compiling with CMake option KICAD_GAL=ON, GLEW and Cairo libraries are required. * GAL-related code is compiled into a static library (common/libgal). * Build with KICAD_GAL=OFF should not need any new libraries and should come out as a standard version of Kicad Currently most of items in pcbnew can be displayed using OpenGL (to be done are DIMENSIONS and MARKERS). More details about GAL can be found in: http://www.ohwr.org/attachments/1884/view-spec.pdf
2013-04-02 06:54:03 +00:00
double ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const override;
void Flip( const VECTOR2I& aCentre, bool aFlipLeftRight ) override;
#if defined (DEBUG)
void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
#endif
int GetMinAnnulus( PCB_LAYER_ID aLayer, wxString* aSource ) const;
/**
* Sets the unconnected removal property. If true, the copper is removed on zone fill
* or when specifically requested when the via is not connected on a layer.
*/
2020-11-14 14:29:11 +00:00
void SetRemoveUnconnected( bool aSet ) { m_removeUnconnectedLayer = aSet; }
bool GetRemoveUnconnected() const { return m_removeUnconnectedLayer; }
/**
* Sets whether we keep the start and end annular rings even if they are not connected
*/
void SetKeepStartEnd( bool aSet ) { m_keepStartEndLayer = aSet; }
bool GetKeepStartEnd() const { return m_keepStartEndLayer; }
bool ConditionallyFlashed( PCB_LAYER_ID aLayer ) const
{
if( !m_removeUnconnectedLayer )
return false;
if( m_keepStartEndLayer && ( aLayer == m_layer || aLayer == m_bottomLayer ) )
return false;
return true;
}
/**
* Check to see whether the via should have a pad on the specific layer.
*
* @param aLayer Layer to check for connectivity
* @return true if connected by pad or track (or optionally zone)
*/
bool FlashLayer( int aLayer ) const;
/**
* Check to see if the via is present on any of the layers in the set.
*
* @param aLayers is the set of layers to check the via against.
* @return true if connected by pad or track (or optionally zone) on any of the associated
* layers.
*/
bool FlashLayer( LSET aLayers ) const;
/**
* Set the drill value for vias.
*
* @param aDrill is the new drill diameter
*/
2020-11-14 14:29:11 +00:00
void SetDrill( int aDrill ) { m_drill = aDrill; }
/**
* Return the local drill setting for this PCB_VIA.
*
* @note Use GetDrillValue() to get the calculated value.
*/
2020-11-14 14:29:11 +00:00
int GetDrill() const { return m_drill; }
/**
* Calculate the drill value for vias (m-Drill if > 0, or default drill value for the board.
*
* @return the calculated drill value.
*/
int GetDrillValue() const;
/**
* Set the drill value for vias to the default value #UNDEFINED_DRILL_DIAMETER.
*/
2020-11-14 14:29:11 +00:00
void SetDrillDefault() { m_drill = UNDEFINED_DRILL_DIAMETER; }
/**
* Check if the via is a free via (as opposed to one created on a track by the router).
*
* Free vias don't have their nets automatically updated by the connectivity algorithm.
*
* @return true if the via is a free via
*/
bool GetIsFree() const { return m_isFree; }
void SetIsFree( bool aFree = true ) { m_isFree = aFree; }
/**
* @return true if the drill value is default value (-1)
*/
2020-11-14 14:29:11 +00:00
bool IsDrillDefault() const { return m_drill <= 0; }
2020-08-13 10:08:16 +00:00
// @copydoc BOARD_ITEM::GetEffectiveShape
std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER,
FLASHING aFlash = FLASHING::DEFAULT ) const override;
2020-08-13 10:08:16 +00:00
void ClearZoneLayerOverrides()
{
m_zoneLayerOverrides.fill( ZLO_NONE );
}
const ZONE_LAYER_OVERRIDE& GetZoneLayerOverride( PCB_LAYER_ID aLayer ) const
{
return m_zoneLayerOverrides.at( aLayer );
}
void SetZoneLayerOverride( PCB_LAYER_ID aLayer, ZONE_LAYER_OVERRIDE aOverride )
{
std::unique_lock<std::mutex> cacheLock( m_zoneLayerOverridesMutex );
m_zoneLayerOverrides.at( aLayer ) = aOverride;
}
protected:
void swapData( BOARD_ITEM* aImage ) override;
2020-11-16 11:16:44 +00:00
wxString layerMaskDescribe() const override;
private:
2020-11-14 14:29:11 +00:00
/// The bottom layer of the via (the top layer is in m_layer)
PCB_LAYER_ID m_bottomLayer;
2020-11-14 14:29:11 +00:00
VIATYPE m_viaType; ///< through, blind/buried or micro
2020-11-14 14:29:11 +00:00
int m_drill; ///< for vias: via drill (- 1 for default value)
bool m_removeUnconnectedLayer; ///< Remove annular rings on unconnected layers
bool m_keepStartEndLayer; ///< Keep the start and end annular rings
bool m_isFree; ///< "Free" vias don't get their nets auto-updated
std::mutex m_zoneLayerOverridesMutex;
std::array<ZONE_LAYER_OVERRIDE, MAX_CU_LAYERS> m_zoneLayerOverrides;
};
#endif // CLASS_TRACK_H