52        if( aOther.m_via->BelongsTo( &aOther ) )
 
   54            m_via = aOther.m_via->Clone();
 
   55            m_via->SetOwner( this );
 
   56            m_via->SetNet( m_net );
 
   64    m_marker = aOther.m_marker;
 
   65    m_rank = aOther.m_rank;
 
   66    m_blockingObstacle = aOther.m_blockingObstacle;
 
 
   97            m_via->SetOwner( 
this );
 
 
  126       m_line = std::move( aOther.m_line );
 
  128       m_net = aOther.m_net;
 
  136           if( aOther.m_via->BelongsTo( &aOther ) )
 
  138               m_via = aOther.m_via->Clone();
 
  139               m_via->SetOwner( 
this );
 
  144               m_via = aOther.m_via;
 
  155       m_links = std::move( aOther.m_links );
 
 
  183        s->Unmark( aMarker );
 
 
  194        marker |= s->Marker();
 
 
  218    for( 
int i = 0; i < 
m_line.SegmentCount() - 1; i++ )
 
  221        const SEG seg2 = 
m_line.CSegment( i + 1 );
 
 
  237    if( x > 0 && x - 1 == y )
 
  240    if( x < max - 1 && x + 1 == y )
 
 
  246#ifdef TOM_EXTRA_DEBUG 
  270    enum VERTEX_TYPE { INSIDE = 0, 
OUTSIDE, ON_EDGE };
 
  283        std::vector<VERTEX*> neighbours;
 
  289        bool visited = 
false;
 
  298    std::vector<VERTEX> vts;
 
  313    if( 
const std::optional<SHAPE_LINE_CHAIN::INTERSECTION> isect = pnew.SelfIntersecting() )
 
  315        if( isect->p != pnew.CLastPoint() )
 
  316            pnew.Split( isect->p );
 
  322        if( pnew.Find( ip.p, 1 ) < 0)
 
  325        if( hnew.
Find( ip.p, 1 ) < 0 )
 
  329    for( 
int i = 0; i < pnew.PointCount(); i++ )
 
  331        const VECTOR2I& p = pnew.CPoint( i );
 
  337        int idx = hnew.
Find( p );
 
  343    #ifdef TOM_EXTRA_DEBUG 
  344    for( 
auto& ip : ips )
 
  346        printf(
"Chk: %d %d\n", pnew.Find( ip.p ), hnew.
Find(ip.p) );
 
  355    vts.reserve( 2 * ( hnew.
PointCount() + pnew.PointCount() ) );
 
  358    for( 
int i = 0; i < pnew.PointCount(); i++ )
 
  364        #ifdef TOM_EXTRA_DEBUG 
  365        printf(
"pnew %d inside %d onedge %d\n", i, !!inside, !!onEdge );
 
  373        v.type = inside && !onEdge ? INSIDE : onEdge ? ON_EDGE : 
OUTSIDE;
 
  377    #ifdef TOM_EXTRA_DEBUG 
  383    for( 
int i = 0; i < pnew.PointCount() - 1; i++ )
 
  385        vts[i].neighbours.push_back( &vts[ i+1 ] );
 
  389    for( 
int i = 1; i < pnew.PointCount() ; i++ )
 
  391        vts[i].neighbours.push_back( &vts[ i-1 ] );
 
  425            vc->neighbours.push_back( vnext );
 
  433    int  lastDst = INT_MAX;
 
  436#ifdef TOM_EXTRA_DEBUG 
  439        if( v.indexh < 0 && v.type == ON_EDGE )
 
  442        printf(
"V %d pos %d %d ip %d ih %d type %d\n", i++, v.pos.x, v.pos.y, v.indexp, v.indexh, v.type );
 
  450    int iterLimit = 1000;
 
  453    while( v->indexp != ( pnew.PointCount() - 1 ) )
 
  468#ifdef TOM_EXTRA_DEBUG 
  469        printf(
"---\nvisit ip %d ih %d type %d outs %d neig %d\n", v->indexp, v->indexh, v->type, out.
PointCount(), v->neighbours.size() );
 
  480            VERTEX* v_next_fallback = 
nullptr;
 
  482            for( 
VERTEX* vn : v->neighbours )
 
  484                if( 
areNeighbours( vn->indexp , v->indexp, pnew.PointCount() )
 
  485                        && vn->type != INSIDE )
 
  492                    else if( vn != v_prev )
 
  494                        v_next_fallback = vn;
 
  500                v_next = v_next_fallback;
 
  505                #ifdef TOM_EXTRA_DEBUG 
  506                printf(
"FAIL VN fallback %p\n", v_next_fallback );
 
  511        else if( v->type == ON_EDGE )
 
  514            for( 
VERTEX* vn : v->neighbours )
 
  516#ifdef TOM_EXTRA_DEBUG 
  517                printf( 
"- OUT scan ip %d ih %d type %d\n", vn->indexp, vn->indexh, vn->type );
 
  520                if( vn->type == 
OUTSIDE && !vn->visited )
 
  530                for( 
VERTEX* vn : v->neighbours )
 
  532                    #ifdef TOM_EXTRA_DEBUG 
  533                    printf(
"- scan ip %d ih %d type %d\n", vn->indexp, vn->indexh, vn->type );
 
  535                    if( vn->type == ON_EDGE && !vn->isHull &&
 
  537                        ( vn->indexh == ( ( v->indexh + 1 ) % hnew.
PointCount() ) ) )
 
  549#ifdef TOM_EXTRA_DEBUG 
  550                printf(
"still no v_next\n");
 
  552                for( 
VERTEX* vn : v->neighbours )
 
  554                    if( vn->type == ON_EDGE )
 
  556                        if( vn->indexh == ( ( v->indexh + 1 ) % hnew.
PointCount() ) )
 
  573#ifdef TOM_EXTRA_DEBUG 
  574                printf(
"v_next %p\n", v_next);
 
  580                if( inLast && v_next )
 
  582                    int d = ( v_next->pos - 
CLastPoint() ).SquaredEuclideanNorm();
 
  610    aPath = std::move( out );
 
 
  628    const int IterationLimit = 5;
 
  632    for( i = 0; i < IterationLimit; i++ )
 
  639            VECTOR2I collisionPoint = obs->m_ipFirst;
 
  661    if( i == IterationLimit )
 
 
  671    std::optional<SHAPE_LINE_CHAIN> picked;
 
  702        for( 
int j = 0; j < 2; j++ )
 
  706            if( paths[j].SegmentCount() < 1 )
 
  709            assert( dirCount < 
int( 
sizeof( dirs ) / 
sizeof( dirs[0] ) ) );
 
  711            dirs[dirCount] = 
DIRECTION_45( paths[j].CSegment( 0 ) );
 
  717            for( 
int j = 0; j < dirCount; j++ )
 
  720                if( endingDir == aPreferredEndingDirection )
 
  730            for( 
int j = 0; j < dirCount; j++ )
 
  732                if( dirs[j] == d_start )
 
  743        for( 
int j = 0; j < dirCount; j++ )
 
  745            if( dirs[j].IsObtuse( d_prev ) )
 
  759        path.Append( *picked );
 
 
  774    int width = 
m_line.Width();
 
  781    else if( aIndex == 
m_line.SegmentCount() )
 
  788        if( 
m_line.IsPtOnArc( 
static_cast<size_t>( aIndex ) + 1 ) )
 
  789            m_line.Insert( aIndex + 1, 
m_line.CPoint( aIndex + 1 ) );
 
  795        path.Append( path_rev );
 
  799    path.SetWidth( width );
 
 
  806    ssize_t idx = 
static_cast<ssize_t
>( aIndex );
 
  807    ssize_t numpts = 
static_cast<ssize_t
>( 
m_line.PointCount() );
 
  810    if( 
m_line.IsPtOnArc( idx ) )
 
  812        if( idx == 0 || ( idx > 0 && !
m_line.IsPtOnArc( idx - 1 ) ) )
 
  816        else if( ( idx == numpts - 1 ) || ( idx < numpts - 1 && !
m_line.IsArcSegment( idx ) ) )
 
  823            wxASSERT_MSG( 
false, wxT( 
"Attempt to dragCornerFree in the middle of an arc!" ) );
 
  827    m_line.SetPoint( idx, aP );
 
 
  833    wxCHECK_RET( aIndex >= 0, wxT( 
"Negative index passed to LINE::DragCorner" ) );
 
 
  860    int s_start = std::max( aIndex - 2, 0 );
 
  861    int s_end = std::min( aIndex + 2, aPath.
SegmentCount() - 1 );
 
  864    int      best_dist = INT_MAX;
 
  870    for( i = s_start; i <= s_end; i++ )
 
  874        for( j = s_start; j < i; j++ )
 
  885                int dist = ( *ip - aP ).EuclideanNorm();
 
 
  904    int          snap_d[2] = { -1, -1 };
 
  930    int      minDist = INT_MAX;
 
  932    for( 
int i = 0; i < 2; i++ )
 
  934        if( snap_d[i] >= 0 && snap_d[i] < minDist && snap_d[i] <= 
m_snapThreshhold )
 
 
  949    wxASSERT( aIndex < 
m_line.PointCount() );
 
  951    SEG guideA[2], guideB[2];
 
  961    if( index == 0 || 
path.IsPtOnArc( index ) )
 
  963        path.Insert( index > 0 ? index + 1 : 0, 
path.CPoint( index ) );
 
  967    if( index == 
path.SegmentCount() - 1 )
 
  969        path.Insert( 
path.PointCount() - 1, 
path.CLastPoint() );
 
  971    else if( 
path.IsPtOnArc( index + 1 ) )
 
  973        path.Insert( index + 1, 
path.CPoint( index + 1 ) );
 
  976    SEG          dragged = 
path.CSegment( index );
 
  979    SEG s_prev = 
path.CSegment( index - 1 );
 
  980    SEG s_next = 
path.CSegment( index + 1 );
 
  985    if( dir_prev == drag_dir )
 
  987        dir_prev = dir_prev.
Left();
 
  988        path.Insert( index, 
path.CPoint( index ) );
 
  993        dir_prev = drag_dir.
Left();
 
  996    if( dir_next == drag_dir )
 
  998        dir_next = dir_next.
Right();
 
  999        path.Insert( index + 1, 
path.CPoint( index + 1 ) );
 
 1003        dir_next = drag_dir.
Right();
 
 1006    s_prev = 
path.CSegment( index - 1 );
 
 1007    s_next = 
path.CSegment( index + 1 );
 
 1008    dragged = 
path.CSegment( index );
 
 1017        if( dir_prev.
Angle( drag_dir )
 
 1024            guideA[0] = guideA[1] = 
SEG( dragged.
A, dragged.
A + dir_prev.
ToVector() );
 
 1027    if( aIndex == 
m_line.SegmentCount() - 1 )
 
 1034        if( dir_next.
Angle( drag_dir )
 
 1041            guideB[0] = guideB[1] = 
SEG( dragged.
B, dragged.
B + dir_next.
ToVector() );
 
 1044    SEG s_current( target, target + drag_dir.
ToVector() );
 
 1046    int              best_len = INT_MAX;
 
 1049    for( 
int i = 0; i < 2; i++ )
 
 1051        for( 
int j = 0; j < 2; j++ )
 
 1061            SEG s1( s_prev.
A, *ip1 );
 
 1062            SEG s2( *ip1, *ip2 );
 
 1063            SEG s3( *ip2, s_next.
B );
 
 1073            else if( ( ip = s3.
Intersect( s_prev ) ) )
 
 1093            if( np.
Length() < best_len )
 
 1096                best = std::move( np );
 
 1101    if( 
m_line.PointCount() == 1 )
 
 1103    else if( aIndex == 0 )
 
 1104        m_line.Replace( 0, 1, best );
 
 1105    else if( aIndex == 
m_line.SegmentCount() - 1 )
 
 1106        m_line.Replace( -2, -1, best );
 
 1108        m_line.Replace( aIndex, aIndex + 1, best );
 
 
 1136    m_via->SetOwner( 
this );
 
 
 1158        s->SetRank( aRank );
 
 
 1165    int min_rank = INT_MAX;
 
 1170            min_rank = std::min( min_rank, item->Rank() );
 
 1177    int rank = ( min_rank == INT_MAX ) ? -1 : min_rank;
 
 
 1192    int lastLink  = std::max( 0, 
static_cast<int>( 
m_links.size() ) - 1 );
 
 1195    int numPoints = 
static_cast<int>( 
m_line.PointCount() );
 
 1197    for( 
int i = 0; i >= 0 && i < 
m_line.PointCount(); i = 
m_line.NextShape( i ) )
 
 1200            firstLink = linkIdx;
 
 1202        if( i < 0 || i >= aEnd - 1 || linkIdx >= lastLink )
 
 1211    wxASSERT( lastLink >= firstLink );
 
 1217        wxASSERT( 
m_links.size() < INT_MAX );
 
 1218        wxASSERT( 
static_cast<int>( 
m_links.size() ) >= ( lastLink - firstLink ) );
 
 1227        m_links.resize( lastLink - firstLink + 1 );
 
 
 1264    bool areaDefined = 
false;
 
 1267    int i_end_self = -1, i_end_other = -1;
 
 1277    int n = std::min( np_self, np_other );
 
 1279    for( 
int i = 0; i < n; i++ )
 
 1304    for( 
int i = 0; i < n; i++ )
 
 1311            i_end_self = np_self - 1 - i;
 
 1312            i_end_other = np_other - 1 - i;
 
 1320    if( i_end_self < 0 )
 
 1321        i_end_self = np_self - 1;
 
 1323    if( i_end_other < 0 )
 
 1324        i_end_other = np_other - 1;
 
 1326    for( 
int i = i_start; i <= i_end_self; i++ )
 
 1329    for( 
int i = i_start; i <= i_end_other; i++ )
 
 
 1344    for( 
const auto seg : 
m_links )
 
 
 1367        if( 
m_via->BelongsTo( 
this ) )
 
 
 1377    std::stringstream ss;
 
 1379    ss << 
m_seg.Format( 
false );
 
 
 1386    for( 
int i = 0; i < 
m_line.SegmentCount(); i++)
 
 1389        if( s == aSeg->
Seg() )
 
 
std::optional< BOX2I > OPT_BOX2I
 
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
 
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
 
Represent route directions & corner angles in a 45-degree metric.
 
const SHAPE_LINE_CHAIN BuildInitialTrace(const VECTOR2I &aP0, const VECTOR2I &aP1, bool aStartDiagonal=false, CORNER_MODE aMode=CORNER_MODE::MITERED_45) const
Build a 2-segment line chain between points aP0 and aP1 and following 45-degree routing regime.
 
AngleType Angle(const DIRECTION_45 &aOther) const
Return the type of angle between directions (this) and aOther.
 
const DIRECTION_45 Left() const
Return the direction on the left side of this (i.e.
 
const VECTOR2I ToVector() const
 
AngleType
Represent kind of angle formed by vectors heading in two DIRECTION_45s.
 
bool IsDiagonal() const
Returns true if the direction is diagonal (e.g.
 
const DIRECTION_45 Right() const
Return the direction on the right side of this (i.e.
 
BOARD_ITEM * m_sourceItem
 
virtual const std::string Format() const
 
VECTOR2I snapToNeighbourSegments(const SHAPE_LINE_CHAIN &aPath, const VECTOR2I &aP, int aIndex) const
 
void ClipVertexRange(int aStart, int aEnd)
Return the number of corners of angles specified by mask aAngles.
 
int FindSegment(const SEGMENT *aSeg) const
 
const VECTOR2I & CPoint(int aIdx) const
 
OPT_BOX2I ChangedArea(const LINE *aOther) const
 
bool HasLockedSegments() const
 
int Rank() const override
 
void dragCorner45(const VECTOR2I &aP, int aIndex, DIRECTION_45 aPreferredEndingDirection)
 
const LINE ClipToNearestObstacle(NODE *aNode) const
Clip the line to a given range of vertices.
 
virtual void Mark(int aMarker) const override
 
bool CompareGeometry(const LINE &aOther)
Reverse the point/vertex order.
 
ITEM * m_blockingObstacle
For mark obstacle mode.
 
const SHAPE_LINE_CHAIN & CLine() const
 
VECTOR2I snapDraggedCorner(const SHAPE_LINE_CHAIN &aPath, const VECTOR2I &aP, int aIndex) const
 
LINE & operator=(const LINE &aOther)
 
void dragSegment45(const VECTOR2I &aP, int aIndex)
 
const VECTOR2I & CLastPoint() const
 
int CountCorners(int aAngles) const
 
void SetRank(int aRank) override
 
LINE()
Makes an empty line.
 
SHAPE_LINE_CHAIN & Line()
 
void DragCorner(const VECTOR2I &aP, int aIndex, bool aFreeAngle=false, DIRECTION_45 aPreferredEndingDirection=DIRECTION_45())
 
virtual int Marker() const override
 
void AppendVia(const VIA &aVia)
 
virtual void Unmark(int aMarker=-1) const override
 
int m_snapThreshhold
Width to smooth out jagged segments.
 
SHAPE_LINE_CHAIN m_line
The actual shape of the line.
 
void DragSegment(const VECTOR2I &aP, int aIndex, bool aFreeAngle=false)
 
bool Walkaround(SHAPE_LINE_CHAIN aObstacle, SHAPE_LINE_CHAIN &aPre, SHAPE_LINE_CHAIN &aWalk, SHAPE_LINE_CHAIN &aPost, bool aCw) const
Calculate a line tightly wrapping a convex hull of an obstacle object (aObstacle).
 
void Reverse()
Clip the line to the nearest obstacle, traversing from the line's start vertex (0).
 
void dragCornerFree(const VECTOR2I &aP, int aIndex)
 
virtual LINE * Clone() const override
Return a deep copy of the item.
 
int Width() const
Return true if the line is geometrically identical as line aOther.
 
void copyLinks(const LINK_HOLDER *aParent)
< Copy m_links from the line aParent.
 
void Unlink(const LINKED_ITEM *aLink)
Return the list of links from the owning node that constitute this line (or NULL if the line is not l...
 
void Link(LINKED_ITEM *aLink)
 
bool IsLinked() const
Check if the segment aLink is a part of the line.
 
bool ContainsLink(const LINKED_ITEM *aItem) const
 
std::vector< LINKED_ITEM * > m_links
 
LINK_HOLDER(PnsKind aKind)
Add a reference to an item registered in a NODE that is a part of this line.
 
virtual void ClearLinks()
Return the number of segments that were assembled together to form this line.
 
Keep the router "world" - i.e.
 
std::optional< OBSTACLE > OPT_OBSTACLE
 
OPT_OBSTACLE NearestObstacle(const LINE *aLine, const COLLISION_SEARCH_OPTIONS &aOpts=COLLISION_SEARCH_OPTIONS())
Follow the line in search of an obstacle that is nearest to the starting to the line's starting point...
 
const ITEM_OWNER * m_owner
 
bool BelongsTo(const ITEM_OWNER *aNode) const
 
virtual const std::string Format() const override
 
SEGMENT * Clone() const override
Return a deep copy of the item.
 
const SHAPE_LINE_CHAIN Hull(int aClearance, int aWalkaroundThickness, int aLayer=-1) const override
 
const VECTOR2I & Pos() const
 
VIA * Clone() const override
Return a deep copy of the item.
 
int LineDistance(const VECTOR2I &aP, bool aDetermineSide=false) const
Return the closest Euclidean distance between point aP and the line defined by the ends of segment (t...
 
const VECTOR2I NearestPoint(const VECTOR2I &aP) const
Compute a point on the segment (this) that is closest to point aP.
 
OPT_VECTOR2I Intersect(const SEG &aSeg, bool aIgnoreEndpoints=false, bool aLines=false) const
Compute intersection point of segment (this) with segment aSeg.
 
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
 
bool PointOnEdge(const VECTOR2I &aP, int aAccuracy=0) const
Check if point aP lies on an edge or vertex of the line chain.
 
bool PointInside(const VECTOR2I &aPt, int aAccuracy=0, bool aUseBBoxCache=false) const override
Check if point aP lies inside a closed shape.
 
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
 
const SHAPE_LINE_CHAIN Reverse() const
Reverse point order in the line chain.
 
int Split(const VECTOR2I &aP, bool aExact=false)
Insert the point aP belonging to one of the our segments, splitting the adjacent segment in two.
 
int PointCount() const
Return the number of points (vertices) in this line chain.
 
void Clear()
Remove all points from the line chain.
 
void Simplify(int aTolerance=0)
Simplify the line chain by removing colinear adjacent segments and duplicate vertices.
 
int NearestSegment(const VECTOR2I &aP) const
Find the segment nearest the given point.
 
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
 
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
 
const SHAPE_LINE_CHAIN Slice(int aStartIndex, int aEndIndex) const
Return a subset of this line chain containing the [start_index, end_index] range of points.
 
int SegmentCount() const
Return the number of segments in this line chain.
 
const VECTOR2I & CLastPoint() const
Return the last point in the line chain.
 
void Remove(int aStartIndex, int aEndIndex)
Remove the range of points [start_index, end_index] from the line chain.
 
const SEG CSegment(int aIndex) const
Return a constant copy of the aIndex segment in the line chain.
 
bool IsArcSegment(size_t aSegment) const
 
std::vector< INTERSECTION > INTERSECTIONS
 
long long int Length() const
Return length of the line chain in Euclidean metric.
 
int Find(const VECTOR2I &aP, int aThreshold=0) const
Search for point aP.
 
const std::vector< VECTOR2I > & CPoints() const
 
Push and Shove diff pair dimensions (gap) settings dialog.
 
static void extendBox(BOX2I &aBox, bool &aDefined, const VECTOR2I &aP)
 
void HullIntersection(const SHAPE_LINE_CHAIN &hull, const SHAPE_LINE_CHAIN &line, SHAPE_LINE_CHAIN::INTERSECTIONS &ips)
 
static int areNeighbours(int x, int y, int max=0)
 
SHAPE_LINE_CHAIN dragCornerInternal(const SHAPE_LINE_CHAIN &aOrigin, const VECTOR2I &aP, DIRECTION_45 aPreferredEndingDirection=DIRECTION_45())
 
const SHAPE_LINE_CHAIN SegmentHull(const SHAPE_SEGMENT &aSeg, int aClearance, int aWalkaroundThickness)
 
@ OUTSIDE
Text appears outside the dimension line (default)
 
static std::pair< bool, SHAPE_POLY_SET::VERTEX_INDEX > findVertex(SHAPE_POLY_SET &aPolySet, const EDIT_POINT &aPoint)
 
std::optional< VECTOR2I > OPT_VECTOR2I
 
Represent an intersection between two line segments.
 
CADSTAR_ARCHIVE_PARSER::VERTEX_TYPE vt
 
VECTOR2< int32_t > VECTOR2I