47 const VECTOR2I& aCenter, uint64_t aWidth,
103 case SHAPE_T::RECTANGLE:
105 int stroke_width = aShape.
GetWidth();
131 int soldermask_min_thickness = 0;
136 soldermask_min_thickness = aShape.
GetWidth();
141 if( soldermask_min_thickness == 0 )
156 poly_set.
Deflate( soldermask_min_thickness / 2 - 1,
157 CORNER_STRATEGY::CHAMFER_ALL_CORNERS, maxError );
170 AddContour( poly_set, ii, FILL_T::FILLED_SHAPE );
172 if( strokeWidth != 0 )
174 for(
int jj = 0; jj < poly_set.
COutline( ii ).SegmentCount(); ++jj )
186 for(
int jj = 0; jj < poly_set.
COutline( ii ).SegmentCount(); ++jj )
207 case SHAPE_T::BEZIER:
211 for(
size_t i = 0; i < points.size() - 1; i++ )
219 case SHAPE_T::SEGMENT:
228 wxLogError( wxT(
"Unknown shape when adding ODB++ layer feature" ) );
238 AddFeature<ODB_SURFACE>( aPolygon, aFillType );
263 int mask_clearance = expansion.
x;
274 case PAD_SHAPE::CIRCLE:
283 case PAD_SHAPE::RECTANGLE:
285 if( mask_clearance > 0 )
300 case PAD_SHAPE::OVAL:
306 case PAD_SHAPE::ROUNDRECT:
315 case PAD_SHAPE::CHAMFERED_RECT:
317 int shorterSide = std::min( plotSize.
x, plotSize.
y );
329 case PAD_SHAPE::TRAPEZOID:
349 case PAD_SHAPE::CUSTOM:
358 shape.
Move( center );
363 CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError,
372 default: wxLogError( wxT(
"Unknown pad type" ) );
break;
383 if( iter ==
GetODBPlugin()->GetViaTraceSubnetMap().end() )
385 wxLogError( wxT(
"Failed to get subnet track data" ) );
389 auto subnet = iter->second;
393 PCB_SHAPE shape(
nullptr, SHAPE_T::SEGMENT );
394 shape.
SetStart( track->GetStart() );
395 shape.
SetEnd( track->GetEnd() );
396 shape.
SetWidth( track->GetWidth() );
399 subnet->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::COPPER,
m_layerName,
405 PCB_SHAPE shape(
nullptr, SHAPE_T::ARC );
411 subnet->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::COPPER,
m_layerName,
419 if( aLayer != PCB_LAYER_ID::UNDEFINED_LAYER )
423 subnet->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::COPPER,
m_layerName,
431 ODB_ATTR::GEOMETRY{
"VIA_RoundD"
432 + std::to_string( via->GetWidth( aLayer ) ) } );
442 subnet->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::HOLE,
m_layerName,
453 ODB_ATTR::GEOMETRY{
"VIA_RoundD"
454 + std::to_string( via->GetWidth( aLayer ) ) } );
473 wxLogError( wxT(
"Failed to get subnet plane data" ) );
477 iter->second->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::COPPER,
m_layerName,
490 text_item =
static_cast<EDA_TEXT*
>( tmp_text );
492 text_item =
static_cast<EDA_TEXT*
>( tmp_text );
497 auto plot_text = [&](
const VECTOR2I& aPos,
const wxString& aTextString,
506 if( penWidth == 0 && attributes.
m_Bold )
511 penWidth = -penWidth;
515 std::list<VECTOR2I> pts;
517 auto push_pts = [&]()
527 PCB_SHAPE shape(
nullptr, SHAPE_T::SEGMENT );
529 shape.
SetEnd( pts.back() );
534 ODB_ATTR::STRING{ aTextString.ToStdString() } );
538 for(
auto it = pts.begin(); std::next( it ) != pts.end(); ++it )
540 auto it2 = std::next( it );
541 PCB_SHAPE shape(
nullptr, SHAPE_T::SEGMENT );
548 ODB_ATTR::STRING{ aTextString.ToStdString() } );
562 if( aPt1 == pts.back() )
563 pts.push_back( aPt2 );
564 else if( aPt2 == pts.front() )
565 pts.push_front( aPt1 );
566 else if( aPt1 == pts.front() )
567 pts.push_front( aPt2 );
568 else if( aPt2 == pts.back() )
569 pts.push_back( aPt1 );
573 pts.push_back( aPt1 );
574 pts.push_back( aPt2 );
579 pts.push_back( aPt1 );
580 pts.push_back( aPt2 );
586 if( aPoly.PointCount() < 3 )
594 AddContour( poly_set, ii, FILL_T::FILLED_SHAPE );
599 ODB_ATTR::STRING{ aTextString.ToStdString() } );
603 aFont->Draw( &callback_gal, aTextString, aPos, aAttributes, aFontMetrics );
609 bool isKnockout =
false;
622 wxString defaultFontName;
625 text_item->IsItalic() );
628 wxString shownText( text_item->GetShownText(
true ) );
630 if( shownText.IsEmpty() )
633 VECTOR2I pos = text_item->GetTextPos();
637 attrs.
m_Angle = text_item->GetDrawRotation();
649 for(
int ii = 0; ii < finalpolyset.
OutlineCount(); ++ii )
651 AddContour( finalpolyset, ii, FILL_T::FILLED_SHAPE );
655 ODB_ATTR::STRING{ shownText.ToStdString() } );
658 else if( text_item->IsMultilineAllowed() )
660 std::vector<VECTOR2I> positions;
661 wxArrayString strings_list;
663 positions.reserve( strings_list.Count() );
665 text_item->GetLinePositions( positions, strings_list.Count() );
667 for(
unsigned ii = 0; ii < strings_list.Count(); ii++ )
669 wxString& txt = strings_list.Item( ii );
670 plot_text( positions[ii], txt, attrs, font, fontMetrics );
675 plot_text( pos, shownText, attrs, font, fontMetrics );
683 AddShape( *shape, aLayer );
686 auto add_pad = [&](
PAD*
pad )
688 auto iter = GetODBPlugin()->GetPadSubnetMap().find(
pad );
690 if( iter == GetODBPlugin()->GetPadSubnetMap().end() )
692 wxLogError( wxT(
"Failed to get subnet top data" ) );
700 AddPadShape( *
pad, aLayer );
702 iter->second->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::COPPER, m_layerName,
703 m_featuresList.size() - 1 );
704 if( !m_featuresList.empty() )
707 if( !
pad->HasHole() && !m_featuresList.empty() )
708 AddFeatureAttribute( *m_featuresList.back(), ODB_ATTR::SMD{ true } );
713 if( m_layerName.Contains(
"drill" ) )
719 if(
pad->GetDrillSizeX() ==
pad->GetDrillSizeY() )
728 AddPadShape(
dummy, aLayer );
733 iter->second->AddFeatureID( EDA_DATA::FEATURE_ID::TYPE::HOLE, m_layerName,
734 m_featuresList.size() - 1 );
736 if( !m_featuresList.empty() )
741 if( !m_featuresList.empty() )
752 switch( item->Type() )
760 case PCB_PAD_T: add_pad(
static_cast<PAD*
>( item ) );
break;
772 add_shape( textbox );
819 ost <<
"#\n#Num Features\n#" << std::endl;
825 ost <<
"#\n#Layer features\n#" << std::endl;
829 feat->WriteFeatures( ost );
837 ost <<
"#\n#Num Features\n#" << std::endl;
843 ost <<
"#\n#Feature symbol names\n#" << std::endl;
847 ost <<
"$" << n <<
" " <<
name << std::endl;
852 ost <<
"#\n#Layer features\n#" << std::endl;
856 feat->WriteFeatures( ost );
893 << (
m_direction == ODB_DIRECTION::CW ?
"Y" :
"N" );
921 if( !aPolygon.empty() && aPolygon[0].PointCount() >= 3 )
923 m_surfaces = std::make_unique<ODB_SURFACE_DATA>( aPolygon );
924 if( aFillType != FILL_T::NO_FILL )
948 const std::vector<VECTOR2I>& pts = aPolygon[0].CPoints();
957 m_polygons.at( 0 ).emplace_back( pts.back() );
959 for(
size_t jj = 0; jj < pts.size(); ++jj )
961 m_polygons.at( 0 ).emplace_back( pts.at( jj ) );
969 for(
size_t ii = 1; ii < aPolygon.size(); ++ii )
971 wxCHECK2( aPolygon[ii].PointCount() >= 3,
continue );
973 const std::vector<VECTOR2I>& hole = aPolygon[ii].CPoints();
985 m_polygons.at( ii ).emplace_back( hole.back() );
987 for(
size_t jj = 0; jj < hole.size(); ++jj )
1001 if( contour.empty() )
1004 ost <<
"OB " <<
ODB::AddXY( contour.back().m_end ).first <<
" "
1005 <<
ODB::AddXY( contour.back().m_end ).second <<
" ";
1013 for(
const auto& line : contour )
1016 ost <<
"OS " <<
ODB::AddXY( line.m_end ).first <<
" "
1017 <<
ODB::AddXY( line.m_end ).second << std::endl;
1019 ost <<
"OC " <<
ODB::AddXY( line.m_end ).first <<
" "
1021 <<
" " <<
ODB::AddXY( line.m_center ).second <<
" "
1022 << ( line.m_direction == ODB_DIRECTION::CW ?
"Y" :
"N" ) << std::endl;
1024 ost <<
"OE" << std::endl;
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
void WriteAttributes(std::ostream &ost, const std::string &prefix="") const
void AddFeatureAttribute(Tr &r, Ta v)
void WriteAttributes(std::ostream &ost) const
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
virtual bool IsKnockout() const
FOOTPRINT * GetParentFootprint() const
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
FILL_T GetFillMode() const
int GetRectangleWidth() const
SHAPE_POLY_SET & GetPolyShape()
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
void SetStart(const VECTOR2I &aStart)
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
const std::vector< VECTOR2I > & GetBezierPoints() const
void SetEnd(const VECTOR2I &aEnd)
void SetArcGeometry(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Set the three controlling points for an arc.
int GetRectangleHeight() const
bool IsClockwiseArc() const
void SetWidth(int aWidth)
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
virtual bool IsVisible() const
virtual wxString GetShownText(bool aAllowExtraText, int aDepth=0) const
Return the string actually shown after processing of the base text.
void AddPadShape(const PAD &aPad, PCB_LAYER_ID aLayer)
uint32_t AddRoundRectDonutSymbol(const wxString &aOuterWidth, const wxString &aOuterHeight, const wxString &aLineWidth, const wxString &aRadius)
void AddShape(const PCB_SHAPE &aShape, PCB_LAYER_ID aLayer=UNDEFINED_LAYER)
uint32_t AddRectSymbol(const wxString &aWidth, const wxString &aHeight)
void AddVia(const PCB_VIA *aVia, PCB_LAYER_ID aLayer)
PCB_IO_ODBPP * GetODBPlugin()
void InitFeatureList(PCB_LAYER_ID aLayer, std::vector< BOARD_ITEM * > &aItems)
void AddFeatureLine(const VECTOR2I &aStart, const VECTOR2I &aEnd, uint64_t aWidth)
void AddFeatureArc(const VECTOR2I &aStart, const VECTOR2I &aEnd, const VECTOR2I &aCenter, uint64_t aWidth, ODB_DIRECTION aDirection)
std::map< uint32_t, wxString > m_allSymMap
void GenerateFeatureFile(std::ostream &ost) const
void AddViaDrillHole(const PCB_VIA *aVia, PCB_LAYER_ID aLayer)
void AddPadCircle(const VECTOR2I &aCenter, uint64_t aDiameter, const EDA_ANGLE &aAngle, bool aMirror, double aResize=1.0)
void AddFeatureSurface(const SHAPE_POLY_SET::POLYGON &aPolygon, FILL_T aFillType=FILL_T::FILLED_SHAPE)
uint32_t AddRoundRectSymbol(const wxString &aWidth, const wxString &aHeight, const wxString &aRadius)
uint32_t AddOvalSymbol(const wxString &aWidth, const wxString &aHeight)
void GenerateProfileFeatures(std::ostream &ost) const
std::list< std::unique_ptr< ODB_FEATURE > > m_featuresList
uint32_t AddCircleSymbol(const wxString &aDiameter)
uint32_t AddChamferRectSymbol(const wxString &aWidth, const wxString &aHeight, const wxString &aRadius, int aPositions)
uint32_t AddRoundDonutSymbol(const wxString &aOuterDim, const wxString &aInnerDim)
bool AddContour(const SHAPE_POLY_SET &aPolySet, int aOutline=0, FILL_T aFillType=FILL_T::FILLED_SHAPE)
FONT is an abstract base class for both outline and stroke fonts.
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false, const std::vector< wxString > *aEmbeddedFiles=nullptr, bool aForDrawingSheet=false)
LSET is a set of PCB_LAYER_IDs.
std::pair< wxString, wxString > m_end
std::pair< wxString, wxString > m_start
virtual void WriteRecordContent(std::ostream &ost) override
ODB_DIRECTION m_direction
std::pair< wxString, wxString > m_center
virtual void WriteRecordContent(std::ostream &ost)=0
virtual void WriteFeatures(std::ostream &ost)
virtual FEATURE_TYPE GetFeatureType()=0
virtual void WriteRecordContent(std::ostream &ost) override
std::pair< wxString, wxString > m_start
std::pair< wxString, wxString > m_end
virtual void WriteRecordContent(std::ostream &ost) override
std::pair< wxString, wxString > m_center
void WriteData(std::ostream &ost) const
std::vector< std::vector< SURFACE_LINE > > m_polygons
ODB_SURFACE_DATA(const SHAPE_POLY_SET::POLYGON &aPolygon)
void AddPolygonHoles(const SHAPE_POLY_SET::POLYGON &aPolygon)
std::unique_ptr< ODB_SURFACE_DATA > m_surfaces
virtual void WriteRecordContent(std::ostream &ost) override
ODB_SURFACE(uint32_t aIndex, const SHAPE_POLY_SET::POLYGON &aPolygon, FILL_T aFillType=FILL_T::FILLED_SHAPE)
@ NORMAL
Shape is the same on all layers.
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
void MergePrimitivesAsPolygon(PCB_LAYER_ID aLayer, SHAPE_POLY_SET *aMergedPolygon, ERROR_LOC aErrorLoc=ERROR_INSIDE) const
Merge all basic shapes to a SHAPE_POLY_SET.
int GetRoundRectCornerRadius(PCB_LAYER_ID aLayer) const
PAD_SHAPE GetShape(PCB_LAYER_ID aLayer) const
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc=ERROR_INSIDE, bool ignoreLineWidth=false) const override
Convert the pad shape to a closed polygon.
int GetSolderMaskExpansion(PCB_LAYER_ID aLayer) const
EDA_ANGLE GetOrientation() const
Return the rotation angle of the pad.
int GetChamferPositions(PCB_LAYER_ID aLayer) const
double GetChamferRectRatio(PCB_LAYER_ID aLayer) const
VECTOR2I GetSolderPasteMargin(PCB_LAYER_ID aLayer) const
Usually < 0 (mask shape smaller than pad)because the margin can be dependent on the pad size,...
VECTOR2I ShapePos(PCB_LAYER_ID aLayer) const
const VECTOR2I & GetSize(PCB_LAYER_ID aLayer) const
const VECTOR2I & GetMid() const
std::map< std::pair< PCB_LAYER_ID, ZONE * >, EDA_DATA::SUB_NET_PLANE * > & GetPlaneSubnetMap()
std::map< PCB_TRACK *, EDA_DATA::SUB_NET * > & GetViaTraceSubnetMap()
static std::string m_unitsStr
VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
int GetWidth() const override
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const override
Convert the shape to a closed polygon.
STROKE_PARAMS GetStroke() const override
bool IsBorderEnabled() const
Disables the border, this is done by changing the stroke internally.
const VECTOR2I & GetStart() const
const VECTOR2I & GetEnd() const
virtual int GetWidth() const
bool FlashLayer(int aLayer) const
Check to see whether the via should have a pad on the specific layer.
const PADSTACK & Padstack() const
int GetDrillValue() const
Calculate the drill value for vias (m_drill if > 0, or default drill value for the board).
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
const SEG CSegment(int aIndex) const
Return a constant copy of the aIndex segment in the line chain.
Represent a set of closed polygons.
void Rotate(const EDA_ANGLE &aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Rotate all vertices by a given angle.
void InflateWithLinkedHoles(int aFactor, CORNER_STRATEGY aCornerStrategy, int aMaxError, POLYGON_MODE aFastMode)
Perform outline inflation/deflation, using round corners.
void Fracture(POLYGON_MODE aFastMode)
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
void BooleanAdd(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset union For aFastMode meaning, see function booleanOp.
POLYGON & Polygon(int aIndex)
Return the aIndex-th subpolygon in the set.
std::vector< SHAPE_LINE_CHAIN > POLYGON
represents a single polygon outline with holes.
void Simplify(POLYGON_MODE aFastMode)
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections) For aFastMo...
void Deflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError)
int OutlineCount() const
Return the number of outlines in the set.
void Move(const VECTOR2I &aVector) override
SHAPE_POLY_SET CloneDropTriangulation() const
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
Handle a list of polygons defining a copper zone.
static constexpr EDA_ANGLE ANGLE_0
static constexpr EDA_ANGLE ANGLE_360
int GetPenSizeForBold(int aTextSize)
PCB_LAYER_ID
A quick note on layer IDs:
std::pair< wxString, wxString > AddXY(const VECTOR2I &aVec)
wxString Double2String(double aVal)
wxString SymDouble2String(double aVal)
VECTOR2I GetShapePosition(const PCB_SHAPE &aShape)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
@ PTH
Plated through hole pad.
std::vector< FAB_LAYER_COLOR > dummy
void wxStringSplit(const wxString &aText, wxArrayString &aStrings, wxChar aSplitter)
Split aString to a string list separated at aSplitter.
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
@ PCB_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_DIM_CENTER_T
class PCB_DIM_CENTER, a center point marking (graphic item)
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
@ PCB_ZONE_T
class ZONE, a copper pour area
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
@ PCB_TARGET_T
class PCB_TARGET, a target (graphic item)
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
@ PCB_PAD_T
class PAD, a pad in a footprint
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
@ PCB_DIMENSION_T
class PCB_DIMENSION_BASE: abstract dimension meta-type
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension
VECTOR2< int32_t > VECTOR2I