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