48bool SegmentsShareEndpoint( 
const SEG& aSegA, 
const SEG& aSegB )
 
   50    return ( aSegA.
A == aSegB.
A || aSegA.
A == aSegB.
B || aSegA.
B == aSegB.
A || aSegA.
B == aSegB.
B );
 
   54std::pair<VECTOR2I*, VECTOR2I*> GetSharedEndpoints( 
SEG& aSegA, 
SEG& aSegB )
 
   56    std::pair<VECTOR2I*, VECTOR2I*> 
result = { 
nullptr, 
nullptr };
 
   58    if( aSegA.
A == aSegB.
A )
 
   62    else if( aSegA.
A == aSegB.
B )
 
   66    else if( aSegA.
B == aSegB.
A )
 
   70    else if( aSegA.
B == aSegB.
B )
 
   82                                                                const std::optional<SEG>& aSeg )
 
   86    const bool removed = !aSeg.has_value() || aSeg->Length() == 0;
 
 
  107    return _( 
"Fillet Lines" );
 
 
  114        return _( 
"Unable to fillet the selected lines." );
 
  116        return _( 
"Some of the lines could not be filleted." );
 
 
  130    auto [a_pt, b_pt] = GetSharedEndpoints( seg_a, seg_b );
 
  144    auto setIfPointOnSeg =
 
  147                VECTOR2I segToVec = aSegment.NearestPoint( aVecToTest ) - aVecToTest;
 
  152                    aPointToSet.
x = aVecToTest.x;
 
  153                    aPointToSet.
y = aVecToTest.y;
 
  161    if( !setIfPointOnSeg( t1newPoint, seg_a, sArc.
GetP0() )
 
  162        && !setIfPointOnSeg( t2newPoint, seg_b, sArc.
GetP0() ) )
 
  168    if( !setIfPointOnSeg( t1newPoint, seg_a, sArc.
GetP1() )
 
  169        && !setIfPointOnSeg( t2newPoint, seg_b, sArc.
GetP1() ) )
 
  180    tArc->SetWidth( aLineA.
GetWidth() );
 
  181    tArc->SetLayer( aLineA.
GetLayer() );
 
  182    tArc->SetLocked( aLineA.
IsLocked() );
 
 
  199    return _( 
"Chamfer Lines" );
 
 
  206        return _( 
"Unable to chamfer the selected lines." );
 
  208        return _( 
"Some of the lines could not be chamfered." );
 
 
  225    if( !SegmentsShareEndpoint( seg_a, seg_b ) )
 
  231    std::optional<CHAMFER_RESULT> chamfer_result =
 
  234    if( !chamfer_result )
 
  242    tSegment->SetStart( chamfer_result->m_chamfer.A );
 
  243    tSegment->SetEnd( chamfer_result->m_chamfer.B );
 
  246    tSegment->SetWidth( aLineA.
GetWidth() );
 
  247    tSegment->SetLayer( aLineA.
GetLayer() );
 
  248    tSegment->SetLocked( aLineA.
IsLocked() );
 
 
  263    return _( 
"Dogbone Corners" );
 
 
  272        msg += 
_( 
"Unable to add dogbone corners to the selected lines." );
 
  274        msg += 
_( 
"Some of the lines could not have dogbone corners added." );
 
  281        msg += 
_( 
"Some of the dogbone corners are too narrow to fit a " 
  282                  "cutter of the specified radius." );
 
  285            msg += 
_( 
" Consider enabling the 'Add Slots' option." );
 
  287            msg += 
_( 
" Slots were added." );
 
 
  301        wxLogTrace( 
"DOGBONE", 
"Skip: zero-length line(s) (A len=%f, B len=%f)",
 
  308        wxLogTrace( 
"DOGBONE", 
"Skip: board outline unavailable" );
 
  315    auto [a_pt, b_pt] = GetSharedEndpoints( seg_a, seg_b );
 
  319        wxLogTrace( 
"DOGBONE", 
"Skip: segments do not share endpoint" );
 
  326        wxLogTrace( 
"DOGBONE", 
"Skip: parallel segments" );
 
  339    const VECTOR2I vecA = ( seg_a.
A == corner ? seg_a.
B - corner : seg_a.
A - corner );
 
  340    const VECTOR2I vecB = ( seg_b.
A == corner ? seg_b.
B - corner : seg_b.
A - corner );
 
  345        wxLogTrace( 
"DOGBONE", 
"Skip: degenerate corner (maxLen==0)" );
 
  350    VECTOR2I bisectorOutward = vecAn + vecBn; 
 
  355        wxLogTrace( 
"DOGBONE", 
"Skip: bisector zero (vectors opposite)" );
 
  361    VECTOR2I sampleDir = ( -bisectorOutward ).Resize( std::min( 1000, 
m_params.DogboneRadiusIU ) );
 
  362    VECTOR2I samplePoint = corner + sampleDir; 
 
  366    if( !oppositeInside )
 
  368        wxLogTrace( 
"DOGBONE", 
"Skip: corner not inward (sample outside polygon)" );
 
  372    std::optional<DOGBONE_RESULT> dogbone_result =
 
  375    if( !dogbone_result )
 
  377        wxLogTrace( 
"DOGBONE", 
"Skip: ComputeDogbone failed (radius=%d slots=%d)",
 
  383    if( dogbone_result->m_small_arc_mouth )
 
  385        wxLogTrace( 
"DOGBONE", 
"Info: small arc mouth (slots %s)",
 
  386                    m_params.AddSlots ? 
"enabled" : 
"disabled" );
 
  395    const auto copyProps = [&]( 
PCB_SHAPE& aShape )
 
  397        aShape.SetWidth( aLineA.
GetWidth() );
 
  398        aShape.SetLayer( aLineA.
GetLayer() );
 
  399        aShape.SetLocked( aLineA.
IsLocked() );
 
  404        if( aSeg.Length() == 0 )
 
  408        tSegment->SetStart( aSeg.A );
 
  409        tSegment->SetEnd( aSeg.B );
 
  411        copyProps( *tSegment );
 
  415    tArc->SetArcGeometry( dogbone_result->m_arc.GetP0(), dogbone_result->m_arc.GetArcMid(),
 
  416                          dogbone_result->m_arc.GetP1() );
 
  421    addSegment( 
SEG{ dogbone_result->m_arc.GetP0(), dogbone_result->m_updated_seg_a->B } );
 
  422    addSegment( 
SEG{ dogbone_result->m_arc.GetP1(), dogbone_result->m_updated_seg_b->B } );
 
  429    wxLogTrace( 
"DOGBONE", 
"Success: dogbone added at (%d,%d)", corner.
x, corner.
y );
 
 
  443        wxLogTrace( 
"DOGBONE", 
"EnsureBoardOutline: board cast failed" );
 
  450        wxLogTrace( 
"DOGBONE", 
"EnsureBoardOutline: GetBoardPolygonOutlines failed" );
 
  455    wxLogTrace( 
"DOGBONE", 
"EnsureBoardOutline: outline %s", ok ? 
"ready" : 
"empty" );
 
 
  462    return _( 
"Extend Lines to Meet" );
 
 
  469        return _( 
"Unable to extend the selected lines to meet." );
 
  471        return _( 
"Some of the lines could not be extended to meet." );
 
 
  502    const auto line_extender = [&]( 
const SEG& aSeg, 
PCB_SHAPE& aLine )
 
  505        if( !aSeg.
Contains( *intersection ) )
 
  507            const int dist_start = ( *intersection - aSeg.
A ).EuclideanNorm();
 
  508            const int dist_end = ( *intersection - aSeg.
B ).EuclideanNorm();
 
  510            const VECTOR2I& furthest_pt = ( dist_start < dist_end ) ? aSeg.
B : aSeg.
A;
 
  513            unsigned int    edge_padding = 
static_cast<unsigned>( 
pcbIUScale.mmToIU( 200 ) );
 
  517            aLine.SetStart( furthest_pt );
 
  518            aLine.SetEnd( new_end );
 
  522    line_extender( seg_a, aLineA );
 
  523    line_extender( seg_b, aLineB );
 
 
  531    std::unique_ptr<SHAPE_POLY_SET> poly;
 
  537        poly = std::make_unique<SHAPE_POLY_SET>( aPcbShape.
GetPolyShape() );
 
  544        poly = std::make_unique<SHAPE_POLY_SET>();
 
  546        const std::vector<VECTOR2I> rect_pts = aPcbShape.
GetRectCorners();
 
  550        for( 
const VECTOR2I& pt : rect_pts )
 
  558        poly = std::make_unique<SHAPE_POLY_SET>();
 
 
  625        std::unique_ptr<PCB_SHAPE> new_poly_shape =
 
  630        new_poly_shape->SetPolyShape( poly_set );
 
  633        new_poly_shape->SetWidth( 
m_width );
 
  634        new_poly_shape->SetLayer( 
m_layer );
 
  637        handler.
AddNewItem( std::move( new_poly_shape ) );
 
 
  644    return _( 
"Merge Polygons" );
 
 
  651        return _( 
"Unable to merge the selected polygons." );
 
  653        return _( 
"Some of the polygons could not be merged." );
 
 
  671    return _( 
"Subtract Polygons" );
 
 
  678        return _( 
"Unable to subtract the selected polygons." );
 
  680        return _( 
"Some of the polygons could not be subtracted." );
 
 
  696    working_polygons = std::move( working_copy );
 
 
  703    return _( 
"Intersect Polygons" );
 
 
  710        return _( 
"Unable to intersect the selected polygons." );
 
  712        return _( 
"Some of the polygons could not be intersected." );
 
 
  736    working_polygons = std::move( working_copy );
 
 
  743    return _( 
"Outset Items" );
 
 
  749        return _( 
"Unable to outset the selected items." );
 
  751        return _( 
"Some of the items could not be outset." );
 
 
  784        if( item_width.has_value() )
 
  794        std::unique_ptr<PCB_SHAPE> new_shape =
 
  797        new_shape->SetPolyShape( new_poly );
 
  798        new_shape->SetLayer( layer );
 
  799        new_shape->SetWidth( width );
 
  810        if( aChain.ArcCount() == 0 )
 
  812            addPolygonalChain( aChain );
 
  816        for( 
size_t si = 0; si < aChain.GetSegmentCount(); ++si )
 
  818            const SEG seg = aChain.GetSegment( si );
 
  823            if( aChain.IsArcSegment( si ) )
 
  826            std::unique_ptr<PCB_SHAPE> new_shape =
 
  828            new_shape->SetStart( seg.
A );
 
  829            new_shape->SetEnd( seg.
B );
 
  830            new_shape->SetLayer( layer );
 
  831            new_shape->SetWidth( width );
 
  836        for( 
size_t ai = 0; ai < aChain.ArcCount(); ++ai )
 
  843            std::unique_ptr<PCB_SHAPE> new_shape =
 
  846            new_shape->SetLayer( layer );
 
  847            new_shape->SetWidth( width );
 
  855        for( 
int oi = 0; oi < aPoly.OutlineCount(); ++oi )
 
  857            addChain( aPoly.Outline( oi ) );
 
  861    const auto addRect = [&]( 
const SHAPE_RECT& aRect )
 
  863        std::unique_ptr<PCB_SHAPE> new_shape =
 
  866        if( !
m_params.gridRounding.has_value() )
 
  868            new_shape->SetPosition( aRect.GetPosition() );
 
  869            new_shape->SetRectangleWidth( aRect.GetWidth() );
 
  870            new_shape->SetRectangleHeight( aRect.GetHeight() );
 
  877            new_shape->SetRectangleWidth( grid_rect.
GetWidth() );
 
  878            new_shape->SetRectangleHeight( grid_rect.
GetHeight() );
 
  881        new_shape->SetLayer( layer );
 
  882        new_shape->SetWidth( width );
 
  887    const auto addCircle = [&]( 
const CIRCLE& aCircle )
 
  889        std::unique_ptr<PCB_SHAPE> new_shape =
 
  891        new_shape->SetCenter( aCircle.Center );
 
  892        new_shape->SetRadius( aCircle.Radius );
 
  893        new_shape->SetLayer( layer );
 
  894        new_shape->SetWidth( width );
 
  899    const auto addCircleOrRect = [&]( 
const CIRCLE& aCircle )
 
  903            addCircle( aCircle );
 
  907            const VECTOR2I   rVec{ aCircle.Radius, aCircle.Radius };
 
  908            const SHAPE_RECT rect{ aCircle.Center - rVec, aCircle.Center + rVec };
 
  913    switch( aItem.
Type() )
 
  917        const PAD& 
pad = 
static_cast<const PAD&
>( aItem );
 
  930            BOX2I box{ 
pad.GetPosition() - pad_size / 2, pad_size };
 
  931            box.Inflate( 
m_params.outsetDistance );
 
  940                radius += std::min( pad_size.
x, pad_size.
y ) / 2;
 
  959            addCircleOrRect( 
circle );
 
  984            box.Inflate( 
m_params.outsetDistance );
 
  992                cornerRadius += 
m_params.outsetDistance;
 
  994            if( 
m_params.gridRounding.has_value() )
 
  997            if( cornerRadius > 0 )
 
 1002                addChain( poly.
Outline( 0 ) );
 
 1016            addCircleOrRect( 
circle );
 
 1036                chain.Append( seg.
A - ext + perp );
 
 1037                chain.Append( seg.
A - ext - perp );
 
 1038                chain.Append( seg.
B + ext - perp );
 
 1039                chain.Append( seg.
B + ext + perp );
 
 1040                chain.SetClosed( 
true );
 
 1062                const SHAPE_ARC inner{ arc.GetCenter(), arc.GetP0() - startNorm,
 
 1063                                       arc.GetCentralAngle(), 0 };
 
 1064                const SHAPE_ARC outer{ arc.GetCenter(), arc.GetP0() + startNorm,
 
 1065                                       arc.GetCentralAngle(), 0 };
 
 1068                chain.Append( outer );
 
 1072                if( inner.GetRadius() > 0 )
 
 1074                    chain.Append( inner.Reversed() );
 
 
constexpr EDA_IU_SCALE pcbIUScale
 
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
 
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
 
bool IsLocked() const override
 
Information pertinent to a Pcbnew printed circuit board.
 
bool GetBoardPolygonOutlines(SHAPE_POLY_SET &aOutlines, OUTLINE_ERROR_HANDLER *aErrorHandler=nullptr, bool aAllowUseArcsInPolygons=false, bool aIncludeNPTHAsOutlines=false)
Extract the board outlines and build a closed polygon from lines, arcs and circle items on edge cut l...
 
Represent basic circle geometry with utility geometry functions.
 
SHAPE_POLY_SET m_boardOutline
Cached board outline polygons.
 
std::optional< wxString > GetStatusMessage(int aSegmentCount) const override
Get a status message to show when the routine is complete.
 
bool EnsureBoardOutline() const
 
wxString GetCommitDescription() const override
 
void ProcessLinePair(PCB_SHAPE &aLineA, PCB_SHAPE &aLineB) override
Perform the action on the pair of lines given.
 
bool m_boardOutlineCached
 
bool IsHorizontal() const
 
KICAD_T Type() const
Returns the type of object.
 
EDA_ANGLE GetArcAngle() 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.
 
std::vector< VECTOR2I > GetRectCorners() const
 
void SetEnd(const VECTOR2I &aEnd)
 
int GetRectangleHeight() const
 
int GetCornerRadius() const
 
virtual void MarkItemModified(BOARD_ITEM &aItem)=0
Report that the tool has modified an item on the board.
 
virtual void DeleteItem(BOARD_ITEM &aItem)=0
Report that the tool has deleted an item on the board.
 
virtual void AddNewItem(std::unique_ptr< BOARD_ITEM > aItem)=0
Report that the tools wants to add a new item to the board.
 
unsigned GetFailures() const
 
void AddFailure()
Mark that one of the actions failed.
 
unsigned GetSuccesses() const
 
void AddSuccess()
Mark that one of the actions succeeded.
 
bool ModifyLineOrDeleteIfZeroLength(PCB_SHAPE &aItem, const std::optional< SEG > &aSeg)
Helper function useful for multiple tools: modify a line or delete it if it has zero length.
 
BOARD_ITEM * GetBoard() const
The BOARD used when creating new shapes.
 
CHANGE_HANDLER & GetHandler()
Access the handler for making changes to the board.
 
std::optional< wxString > GetStatusMessage(int aSegmentCount) const override
Get a status message to show when the routine is complete.
 
wxString GetCommitDescription() const override
 
void ProcessLinePair(PCB_SHAPE &aLineA, PCB_SHAPE &aLineB) override
Perform the action on the pair of lines given.
 
const CHAMFER_PARAMS m_chamferParams
 
wxString GetCommitDescription() const override
 
std::optional< wxString > GetStatusMessage(int aSegmentCount) const override
Get a status message to show when the routine is complete.
 
void ProcessLinePair(PCB_SHAPE &aLineA, PCB_SHAPE &aLineB) override
Perform the action on the pair of lines given.
 
std::optional< wxString > GetStatusMessage(int aSegmentCount) const override
Get a status message to show when the routine is complete.
 
wxString GetCommitDescription() const override
 
void ProcessLinePair(PCB_SHAPE &aLineA, PCB_SHAPE &aLineB) override
Perform the action on the pair of lines given.
 
void ProcessItem(BOARD_ITEM &aItem)
 
const PARAMETERS m_params
 
wxString GetCommitDescription() const override
 
std::optional< wxString > GetStatusMessage() const
 
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
 
VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
 
int GetWidth() const override
 
VECTOR2I GetPosition() const override
 
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
 
SHAPE_POLY_SET m_workingPolygons
This can be disjoint, which will be fixed at the end.
 
void Finalize()
Clear up any outstanding work.
 
SHAPE_POLY_SET & GetWorkingPolygons()
 
void ProcessShape(PCB_SHAPE &aPcbShape)
 
virtual bool ProcessSubsequentPolygon(const SHAPE_POLY_SET &aPolygon)=0
 
std::optional< wxString > GetStatusMessage() const override
Get a status message to show when the routine is complete.
 
wxString GetCommitDescription() const override
 
bool ProcessSubsequentPolygon(const SHAPE_POLY_SET &aPolygon) override
 
bool ProcessSubsequentPolygon(const SHAPE_POLY_SET &aPolygon) override
 
wxString GetCommitDescription() const override
 
std::optional< wxString > GetStatusMessage() const override
Get a status message to show when the routine is complete.
 
wxString GetCommitDescription() const override
 
std::optional< wxString > GetStatusMessage() const override
Get a status message to show when the routine is complete.
 
bool ProcessSubsequentPolygon(const SHAPE_POLY_SET &aPolygon) override
 
A round rectangle shape, based on a rectangle and a radius.
 
void TransformToPolygon(SHAPE_POLY_SET &aBuffer, int aMaxError) const
Get the polygonal representation of the roundrect.
 
bool Intersects(const SEG &aSeg) const
 
int Length() const
Return the length (this).
 
OPT_VECTOR2I IntersectLines(const SEG &aSeg) const
Compute the intersection point of lines passing through ends of (this) and aSeg.
 
bool Contains(const SEG &aSeg) const
 
EDA_ANGLE Angle(const SEG &aOther) const
Determine the smallest angle between two segments.
 
const VECTOR2I & GetArcMid() const
 
const VECTOR2I & GetP1() const
 
const VECTOR2I & GetP0() const
 
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
 
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 BooleanAdd(const SHAPE_POLY_SET &b)
Perform boolean polyset union.
 
void ClearArcs()
Removes all arc references from all the outlines and holes in the polyset.
 
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
 
void BooleanIntersection(const SHAPE_POLY_SET &b)
Perform boolean polyset intersection.
 
int OutlineCount() const
Return the number of outlines in the set.
 
void BooleanSubtract(const SHAPE_POLY_SET &b)
Perform boolean polyset difference.
 
int GetWidth() const override
 
const VECTOR2I & GetPosition() const
 
const VECTOR2I GetSize() const
 
static const int MIN_PRECISION_IU
This is the minimum precision for all the points in a shape.
 
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
 
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
 
This file is part of the common library.
 
std::optional< CHAMFER_RESULT > ComputeChamferPoints(const SEG &aSegA, const SEG &aSegB, const CHAMFER_PARAMS &aChamferParams)
Compute the chamfer points for a given line pair and chamfer parameters.
 
std::optional< DOGBONE_RESULT > ComputeDogbone(const SEG &aSegA, const SEG &aSegB, int aDogboneRadius, bool aAddSlots)
Compute the dogbone geometry for a given line pair and dogbone parameters.
 
static constexpr EDA_ANGLE ANGLE_90
 
static constexpr EDA_ANGLE FULL_CIRCLE
 
static constexpr EDA_ANGLE ANGLE_180
 
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
 
a few functions useful in geometry calculations.
 
VECTOR2< ret_type > GetClampedCoords(const VECTOR2< in_type > &aCoords, pad_type aPadding=1u)
Clamps a vector to values that can be negated, respecting numeric limits of coordinates data type wit...
 
static SHAPE_RECT GetRectRoundedToGridOutwards(const SHAPE_RECT &aRect, int aGridSize)
 
PCB_LAYER_ID
A quick note on layer IDs:
 
SHAPE_LINE_CHAIN ConvertToChain(const SHAPE_SEGMENT &aOval)
 
VECTOR2I RoundNW(const VECTOR2I &aVec, int aGridSize)
Round a vector to the nearest grid point in the NW direction.
 
VECTOR2I RoundSE(const VECTOR2I &aVec, int aGridSize)
Round a vector to the nearest grid point in the SE direction.
 
PAD_SHAPE
The set of pad shapes, used with PAD::{Set,Get}Shape()
 
static bool addSegment(VRML_LAYER &model, IDF_SEGMENT *seg, int icont, int iseg)
 
std::optional< VECTOR2I > OPT_VECTOR2I
 
Utility functions for working with shapes.
 
const SHAPE_LINE_CHAIN chain
 
SHAPE_CIRCLE circle(c.m_circle_center, c.m_circle_radius)
 
wxString result
Test unit parsing edge cases and error handling.
 
VECTOR2I GetRotated(const VECTOR2I &aVector, const EDA_ANGLE &aAngle)
Return a new VECTOR2I that is the result of rotating aVector by aAngle.
 
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
 
@ PCB_PAD_T
class PAD, a pad in a footprint
 
VECTOR2< int32_t > VECTOR2I
 
Supplemental functions for working with vectors and simple objects that interact with vectors.