40 m_line( aOther.m_line ),
41 m_width( aOther.m_width ),
42 m_snapThreshhold( aOther.m_snapThreshhold )
136 s->Unmark( aMarker );
147 marker |= s->Marker();
190 if( x > 0 && x - 1 == y )
193 if( x < max - 1 && x + 1 == y )
199#ifdef TOM_EXTRA_DEBUG
236 std::vector<VERTEX*> neighbours;
242 bool visited =
false;
251 std::vector<VERTEX> vts;
266 if(
const std::optional<SHAPE_LINE_CHAIN::INTERSECTION> isect = pnew.SelfIntersecting() )
268 if( isect->p != pnew.CPoint( -1 ) )
269 pnew.Split( isect->p );
275 if( pnew.Find( ip.p, 1 ) < 0)
278 if( hnew.
Find( ip.p, 1 ) < 0 )
282 for(
int i = 0; i < pnew.PointCount(); i++ )
284 const VECTOR2I& p = pnew.CPoint( i );
290 int idx = hnew.
Find( p );
296 #ifdef TOM_EXTRA_DEBUG
297 for(
auto& ip : ips )
299 printf(
"Chk: %d %d\n", pnew.Find( ip.p ), hnew.
Find(ip.p) );
308 vts.reserve( 2 * ( hnew.
PointCount() + pnew.PointCount() ) );
311 for(
int i = 0; i < pnew.PointCount(); i++ )
317 #ifdef TOM_EXTRA_DEBUG
318 printf(
"pnew %d inside %d onedge %d\n", i, !!inside, !!onEdge );
326 v.type = inside && !onEdge ?
INSIDE : onEdge ? ON_EDGE :
OUTSIDE;
330 #ifdef TOM_EXTRA_DEBUG
336 for(
int i = 0; i < pnew.PointCount() - 1; i++ )
338 vts[i].neighbours.push_back( &vts[ i+1 ] );
342 for(
int i = 1; i < pnew.PointCount() ; i++ )
344 vts[i].neighbours.push_back( &vts[ i-1 ] );
378 vc->neighbours.push_back( vnext );
386 int lastDst = INT_MAX;
389#ifdef TOM_EXTRA_DEBUG
392 if( v.indexh < 0 && v.type == ON_EDGE )
395 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 );
403 int iterLimit = 1000;
406 while( v->indexp != ( pnew.PointCount() - 1 ) )
421#ifdef TOM_EXTRA_DEBUG
422 printf(
"---\nvisit ip %d ih %d type %d outs %d neig %d\n", v->indexp, v->indexh, v->type, out.
PointCount(), v->neighbours.size() );
433 VERTEX* v_next_fallback =
nullptr;
435 for(
VERTEX* vn : v->neighbours )
437 if(
areNeighbours( vn->indexp , v->indexp, pnew.PointCount() )
445 else if( vn != v_prev )
447 v_next_fallback = vn;
453 v_next = v_next_fallback;
458 #ifdef TOM_EXTRA_DEBUG
459 printf(
"FAIL VN fallback %p\n", v_next_fallback );
464 else if( v->type == ON_EDGE )
467 for(
VERTEX* vn : v->neighbours )
469#ifdef TOM_EXTRA_DEBUG
470 printf(
"- OUT scan ip %d ih %d type %d\n", vn->indexp, vn->indexh, vn->type );
473 if( vn->type ==
OUTSIDE && !vn->visited )
483 for(
VERTEX* vn : v->neighbours )
485 #ifdef TOM_EXTRA_DEBUG
486 printf(
"- scan ip %d ih %d type %d\n", vn->indexp, vn->indexh, vn->type );
488 if( vn->type == ON_EDGE && !vn->isHull &&
490 ( vn->indexh == ( ( v->indexh + 1 ) % hnew.
PointCount() ) ) )
502#ifdef TOM_EXTRA_DEBUG
503 printf(
"still no v_next\n");
505 for(
VERTEX* vn : v->neighbours )
507 if( vn->type == ON_EDGE )
509 if( vn->indexh == ( ( v->indexh + 1 ) % hnew.
PointCount() ) )
526#ifdef TOM_EXTRA_DEBUG
527 printf(
"v_next %p\n", v_next);
533 if( inLast && v_next )
535 int d = ( v_next->pos -
CPoint( -1 ) ).SquaredEuclideanNorm();
582 const int IterationLimit = 5;
586 for( i = 0; i < IterationLimit; i++ )
593 VECTOR2I collisionPoint = obs->m_ipFirst;
615 if( i == IterationLimit )
625 std::optional<SHAPE_LINE_CHAIN> picked;
656 for(
int j = 0; j < 2; j++ )
660 if( paths[j].SegmentCount() < 1 )
663 assert( dirCount <
int(
sizeof( dirs ) /
sizeof( dirs[0] ) ) );
665 dirs[dirCount] =
DIRECTION_45( paths[j].CSegment( 0 ) );
671 for(
int j = 0; j < dirCount; j++ )
674 if( endingDir == aPreferredEndingDirection )
684 for(
int j = 0; j < dirCount; j++ )
686 if( dirs[j] == d_start )
697 for(
int j = 0; j < dirCount; j++ )
699 if( dirs[j].IsObtuse( d_prev ) )
713 path.Append( *picked );
749 path.Append( path_rev );
753 path.SetWidth( width );
760 ssize_t idx =
static_cast<ssize_t
>( aIndex );
770 else if( ( idx == numpts - 1 ) || ( idx < numpts - 1 && !
m_line.
IsArcSegment( idx ) ) )
777 wxASSERT_MSG(
false, wxT(
"Attempt to dragCornerFree in the middle of an arc!" ) );
787 wxCHECK_RET( aIndex >= 0, wxT(
"Negative index passed to LINE::DragCorner" ) );
814 int s_start = std::max( aIndex - 2, 0 );
815 int s_end = std::min( aIndex + 2, aPath.
SegmentCount() - 1 );
818 int best_dist = INT_MAX;
824 for( i = s_start; i <= s_end; i++ )
828 for( j = s_start; j < i; j++ )
839 int dist = ( *ip - aP ).EuclideanNorm();
858 int snap_d[2] = { -1, -1 };
884 int minDist = INT_MAX;
886 for(
int i = 0; i < 2; i++ )
888 if( snap_d[i] >= 0 && snap_d[i] < minDist && snap_d[i] <=
m_snapThreshhold )
905 SEG guideA[2], guideB[2];
915 if( index == 0 ||
path.IsPtOnArc( index ) )
917 path.Insert( index > 0 ? index + 1 : 0,
path.CPoint( index ) );
921 if( index ==
path.SegmentCount() - 1 )
923 path.Insert(
path.PointCount() - 1,
path.CPoint( -1 ) );
925 else if(
path.IsPtOnArc( index + 1 ) )
927 path.Insert( index + 1,
path.CPoint( index + 1 ) );
930 SEG dragged =
path.CSegment( index );
933 SEG s_prev =
path.CSegment( index - 1 );
934 SEG s_next =
path.CSegment( index + 1 );
939 if( dir_prev == drag_dir )
941 dir_prev = dir_prev.
Left();
942 path.Insert( index,
path.CPoint( index ) );
947 dir_prev = drag_dir.
Left();
950 if( dir_next == drag_dir )
952 dir_next = dir_next.
Right();
953 path.Insert( index + 1,
path.CPoint( index + 1 ) );
957 dir_next = drag_dir.
Right();
960 s_prev =
path.CSegment( index - 1 );
961 s_next =
path.CSegment( index + 1 );
962 dragged =
path.CSegment( index );
971 if( dir_prev.
Angle( drag_dir )
978 guideA[0] = guideA[1] =
SEG( dragged.
A, dragged.
A + dir_prev.
ToVector() );
988 if( dir_next.
Angle( drag_dir )
995 guideB[0] = guideB[1] =
SEG( dragged.
B, dragged.
B + dir_next.
ToVector() );
998 SEG s_current( target, target + drag_dir.
ToVector() );
1000 int best_len = INT_MAX;
1003 for(
int i = 0; i < 2; i++ )
1005 for(
int j = 0; j < 2; j++ )
1015 SEG s1( s_prev.
A, *ip1 );
1016 SEG s2( *ip1, *ip2 );
1017 SEG s3( *ip2, s_next.
B );
1027 else if( ( ip = s3.
Intersect( s_prev ) ) )
1047 if( np.
Length() < best_len )
1057 else if( aIndex == 0 )
1112 s->SetRank( aRank );
1119 int min_rank = INT_MAX;
1124 min_rank = std::min( min_rank, item->Rank() );
1131 int rank = ( min_rank == INT_MAX ) ? -1 : min_rank;
1146 int lastLink = std::max( 0,
static_cast<int>(
m_links.size() ) - 1 );
1154 firstLink = linkIdx;
1156 if( i < 0 || i >= aEnd - 1 || linkIdx >= lastLink )
1165 wxASSERT( lastLink >= firstLink );
1171 wxASSERT(
m_links.size() < INT_MAX );
1172 wxASSERT(
static_cast<int>(
m_links.size() ) >= ( lastLink - firstLink ) );
1181 m_links.resize( lastLink - firstLink + 1 );
1218 bool areaDefined =
false;
1221 int i_end_self = -1, i_end_other = -1;
1231 int n = std::min( np_self, np_other );
1233 for(
int i = 0; i < n; i++ )
1258 for(
int i = 0; i < n; i++ )
1265 i_end_self = np_self - 1 - i;
1266 i_end_other = np_other - 1 - i;
1274 if( i_end_self < 0 )
1275 i_end_self = np_self - 1;
1277 if( i_end_other < 0 )
1278 i_end_other = np_other - 1;
1280 for(
int i = i_start; i <= i_end_self; i++ )
1283 for(
int i = i_start; i <= i_end_other; i++ )
1298 for(
const auto seg :
m_links )
1331 std::stringstream ss;
1343 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.
virtual const std::string Format() const
void SetNet(NET_HANDLE aNet)
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
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)
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
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...
void SetOwner(const ITEM_OWNER *aOwner)
Set the node that owns this item.
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.
bool IsPtOnArc(size_t aPtIndex) const
int Width() const
Get the current width of the segments in the chain.
virtual const VECTOR2I GetPoint(int aIndex) const override
void SetPoint(int aIndex, const VECTOR2I &aPos)
Move a point to a specific location.
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.
void Simplify(int aMaxError=0)
Simplify the line chain by removing colinear adjacent segments and duplicate vertices.
int PointCount() const
Return the number of points (vertices) in this line chain.
void Replace(int aStartIndex, int aEndIndex, const VECTOR2I &aP)
Replace points with indices in range [start_index, end_index] with a single point aP.
bool CompareGeometry(const SHAPE_LINE_CHAIN &aOther) const
void Clear()
Remove all points from the line chain.
const SHAPE_LINE_CHAIN Slice(int aStartIndex, int aEndIndex=-1) const
Return a subset of this line chain containing the [start_index, end_index] range of points.
int NearestSegment(const VECTOR2I &aP) const
Find the segment nearest the given point.
int NextShape(int aPointIndex) const
Return the vertex index of the next shape in the chain, or -1 if aPointIndex is the last shape.
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.
int SegmentCount() const
Return the number of segments in this 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
void Insert(size_t aVertex, const VECTOR2I &aP)
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.
virtual const std::string Format(bool aCplusPlus=true) const override
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.
VECTOR2< int32_t > VECTOR2I