52static std::unordered_set<const NODE*> allocNodes;
65 allocNodes.insert(
this );
74 wxLogTrace( wxT(
"PNS" ), wxT(
"attempting to free a node that has kids." ) );
79 if( allocNodes.find(
this ) == allocNodes.end() )
81 wxLogTrace( wxT(
"PNS" ), wxT(
"attempting to free an already-free'd node." ) );
85 allocNodes.erase(
this );
90 std::vector<const ITEM*> toDelete;
96 if( item->BelongsTo(
this ) && item->OfKind(
ITEM::HOLE_T ) )
97 toDelete.push_back( item );
100 for(
const ITEM* item : toDelete )
102 wxLogTrace( wxT(
"PNS" ), wxT(
"del item %p type %s" ), item, item->KindStr().c_str() );
148 JOINT_MAP::iterator j;
158 wxLogTrace( wxT(
"PNS" ), wxT(
"%d items, %d joints, %d overrides" ),
180 m_override( nullptr )
224 if(
m_item == aCandidate )
227 if(
visit( aCandidate ) )
253 assert( allocNodes.find(
this ) != allocNodes.end() );
268 return aObstacles.size();
277 std::vector<SEGMENT> tmpSegs;
282 for(
int i = 0; i < aLine->
CLine().SegmentCount(); i++ )
288 tmpSegs.emplace_back( *aLine, aLine->
CLine().
CSegment( i ) );
295 if( obstacleList.empty() )
319 std::vector<SHAPE_LINE_CHAIN::INTERSECTION> intersectingPts;
320 int layer = aLine->
Layer();
322 for(
const OBSTACLE& obstacle : obstacleList )
330 obstacleHull = obstacle.m_item->Hull( clearance, 0, layer );
334 intersectingPts.clear();
337 for(
const auto& ip : intersectingPts )
341 updateNearest( ip, obstacle );
348 +
via.Diameter() / 2;
350 obstacleHull = obstacle.m_item->Hull( viaClearance, 0, layer );
353 intersectingPts.clear();
357 updateNearest( ip, obstacle );
362 nearest = (*obstacleList.begin());
393 const LINE* line =
static_cast<const LINE*
>( aItemA );
499 aSolid->SetOwner(
this );
534 switch( aItem->
Kind() )
563 for(
size_t i = 0; i < l.
ArcCount(); i++ )
575 auto newarc = std::make_unique< ARC >( aLine, s );
576 aLine.
Link( newarc.get() );
577 Add( std::move( newarc ),
true );
600 std::unique_ptr<SEGMENT> newseg = std::make_unique<SEGMENT>( aLine, s );
601 aLine.
Link( newseg.get() );
602 Add( std::move( newseg ),
true );
620bool NODE::Add( std::unique_ptr< SEGMENT >&& aSegment,
bool aAllowRedundant )
622 if( aSegment->Seg().A == aSegment->Seg().B )
624 wxLogTrace( wxT(
"PNS" ),
625 wxT(
"attempting to add a segment with same end coordinates, ignoring." ) );
649bool NODE::Add( std::unique_ptr< ARC >&& aArc,
bool aAllowRedundant )
674 if( edgeExclusion->Collide( aPos ) )
742 std::vector<ITEM*> links( aJoint->
LinkList() );
744 int net = aItem->
Net();
754 auto range =
m_joints.equal_range( tag );
761 for(
auto f = range.first; f != range.second; ++f )
773 for(
ITEM* link : links )
804 add( aNewItem.release() );
845 switch( aItem->
Kind() )
868 LINE* l =
static_cast<LINE*
>( aItem );
896 std::vector<LINKED_ITEM*>& segRefs = aLine.
Links();
913 bool& aGuardHit,
bool aStopAtLockedJoints,
bool aFollowLockedSegments )
915 bool prevReversed =
false;
919 for(
int count = 0 ; ; ++count )
921 const VECTOR2I p = aCurrent->
Anchor( aScanDirection ^ prevReversed );
926 aCorners[aPos] = jt->
Pos();
927 aSegments[aPos] = aCurrent;
928 aArcReversed[aPos] =
false;
932 if( ( aScanDirection && jt->
Pos() == aCurrent->
Anchor( 0 ) )
933 || ( !aScanDirection && jt->
Pos() == aCurrent->
Anchor( 1 ) ) )
934 aArcReversed[aPos] =
true;
937 aPos += ( aScanDirection ? 1 : -1 );
939 if( count && guard == p )
941 if( aPos >= 0 && aPos < aLimit )
942 aSegments[aPos] =
nullptr;
950 if(
locked || !jt->
IsLineCorner( aFollowLockedSegments ) || aPos < 0 || aPos == aLimit )
953 aCurrent = jt->
NextSegment( aCurrent, aFollowLockedSegments );
955 prevReversed = ( aCurrent && jt->
Pos() == aCurrent->
Anchor( aScanDirection ) );
961 bool aStopAtLockedJoints,
bool aFollowLockedSegments )
963 const int MaxVerts = 1024 * 16;
965 std::array<VECTOR2I, MaxVerts + 1> corners;
966 std::array<LINKED_ITEM*, MaxVerts + 1> segs;
967 std::array<bool, MaxVerts + 1> arcReversed;
970 bool guardHit =
false;
972 int i_start = MaxVerts / 2;
973 int i_end = i_start + 1;
980 followLine( aSeg,
false, i_start, MaxVerts, corners.data(), segs.data(), arcReversed.data(),
981 guardHit, aStopAtLockedJoints, aFollowLockedSegments );
985 followLine( aSeg,
true, i_end, MaxVerts, corners.data(), segs.data(), arcReversed.data(),
986 guardHit, aStopAtLockedJoints, aFollowLockedSegments );
992 bool originSet =
false;
996 for(
int i = i_start + 1; i < i_end; i++ )
1004 if( li && prev_seg != li )
1008 const ARC* arc =
static_cast<const ARC*
>( li );
1013 ssize_t lastShape = nSegs ? line.
ArcIndex(
static_cast<ssize_t
>( nSegs ) - 1 ) : -1;
1021 if( li == aSeg && aOriginSegmentIndex && !originSet )
1025 *aOriginSegmentIndex = line.
PointCount() - 1;
1037 if( aOriginSegmentIndex && *aOriginSegmentIndex >= pl.
SegmentCount() )
1065 JOINT j_start, j_end;
1072 if( id_end < id_start )
1073 std::swap( id_end, id_start );
1075 if( id_start >= 0 && id_end >= 0 )
1078 aLines.push_back( line );
1089 const SEGMENT* locked_seg =
nullptr;
1090 std::vector<VVIA*> vvias;
1094 JOINT joint = jointPair.second;
1099 int n_seg = 0, n_solid = 0, n_vias = 0;
1102 bool is_width_change =
false;
1103 bool is_locked =
false;
1115 else if(
const auto t = dyn_cast<const PNS::SEGMENT*>( item ) )
1119 if( prev_w >= 0 && w != prev_w )
1121 is_width_change =
true;
1124 max_w = std::max( w, max_w );
1127 is_locked = t->IsLocked();
1132 if( ( is_width_change || n_seg >= 3 || is_locked ) && n_solid == 0 && n_vias == 0 )
1143 locked_seg->
Seg().
B :
1144 locked_seg->
Seg().
A;
1151 for(
auto vvia : vvias )
1153 Add( ItemCast<VIA>( std::move( std::unique_ptr<VVIA>( vvia ) ) ) );
1167 if( f == end && !
isRoot() )
1178 if( f->second.Layers().Overlaps( aLayer ) )
1203 JOINT_MAP::iterator f =
m_joints.find( tag );
1205 std::pair<JOINT_MAP::iterator, JOINT_MAP::iterator> range;
1212 for( f = range.first; f != range.second; ++f )
1217 JOINT jt( aPos, aLayers, aNet );
1224 range =
m_joints.equal_range( tag );
1226 if( range.first ==
m_joints.end() )
1229 for( f = range.first; f != range.second; ++f )
1231 if( aLayers.
Overlaps( f->second.Layers() ) )
1233 jt.
Merge( f->second );
1247 wxLogTrace( wxT(
"PNS" ), wxT(
"joint layers %d-%d, net %d, pos %s, links: %d" ),
1276 std::unordered_set<SEGMENT*> all_segs;
1279 for( i = m_items.begin(); i != m_items.end(); i++ )
1282 all_segs.insert(
static_cast<SEGMENT*
>( *i ) );
1287 for( i =
m_root->m_items.begin(); i !=
m_root->m_items.end(); i++ )
1290 all_segs.insert(
static_cast<SEGMENT*
>(*i) );
1294 JOINT_MAP::iterator j;
1300 wxLogTrace( wxT(
"PNS" ), wxT(
"joint : %s, links : %d\n" ),
1301 j->second.GetPos().Format().c_str(), j->second.LinkCount() );
1302 JOINT::LINKED_ITEMS::const_iterator k;
1304 for( k = j->second.GetLinkList().begin(); k != j->second.GetLinkList().end(); ++k )
1306 const ITEM* m_item = *k;
1308 switch( m_item->GetKind() )
1313 wxLogTrace( wxT(
"PNS" ), wxT(
" -> seg %s %s\n" ),
1314 seg->GetSeg().A.
Format().c_str(),
1315 seg->GetSeg().B.
Format().c_str() );
1326 int lines_count = 0;
1328 while( !all_segs.empty() )
1330 SEGMENT* s = *all_segs.begin();
1333 LINE::LinkedSegments* seg_refs = l->GetLinkedSegments();
1337 wxLogTrace( wxT(
"PNS" ), wxT(
"Line: %s, net %d " ),
1338 l->GetLine().
Format().c_str(), l->GetNet() );
1341 for( std::vector<SEGMENT*>::iterator j = seg_refs->begin(); j != seg_refs->end(); ++j )
1343 wxLogTrace( wxT(
"PNS" ), wxT(
"%s " ), (*j)->GetSeg().A.Format().c_str() );
1345 if( j + 1 == seg_refs->end() )
1346 wxLogTrace( wxT(
"PNS" ), wxT(
"%s\n" ), (*j)->GetSeg().B.Format().c_str() );
1348 all_segs.erase( *j );
1354 wxLogTrace( wxT(
"PNS" ), wxT(
"Local joints: %d, lines : %d \n" ),
1372 aRemoved.push_back( item );
1375 aAdded.push_back( item );
1384 for(
NODE* node : kids )
1386 node->releaseChildren();
1397 std::vector<const ITEM*> cacheCheckItems;
1402 if( !item->BelongsTo(
this ) )
1447 for(
ITEM* item : *l_cur )
1449 if( item->OfKind( aKindMask ) && item->IsRoutable() )
1450 aItems.insert( item );
1460 for(
ITEM* item : *l_root )
1462 if( !
Overrides( item ) && item->OfKind( aKindMask ) && item->IsRoutable() )
1463 aItems.insert( item );
1474 item->SetRank( -1 );
1475 item->Mark( item->Marker() & ~aMarkerMask );
1482 std::vector<ITEM*> garbage;
1486 if( item->Marker() & aMarker )
1487 garbage.emplace_back( item );
1490 for(
ITEM* item : garbage )
1513 && ( (
A == a2 &&
B == b2 ) || (
A == b2 &&
B == a2 ) ) )
1542 ARC* seg2 =
static_cast<ARC*
>( item );
1548 && ( (
A == a2 &&
B == b2 ) || (
A == b2 &&
B == a2 ) ) )
1572 for( JOINT_MAP::value_type& j :
m_joints )
1574 if( !j.second.Layers().Overlaps( aLayerMask ) )
1577 if( aBox.
Contains( j.second.Pos() ) && j.second.LinkCount( aKindMask ) )
1579 aJoints.push_back( &j.second );
1589 if( !
Overrides( &j.second ) && j.second.Layers().Overlaps( aLayerMask ) )
1591 if( aBox.
Contains( j.second.Pos() ) && j.second.LinkCount( aKindMask ) )
1593 aJoints.push_back( &j.second );
1612 for(
ITEM* item : *l_cur )
1614 if( item->Parent() == aParent )
1625 std::vector<ITEM*> ret;
1629 if( item->Parent() == aParent )
1630 ret.push_back( item );
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
virtual bool IsConnected() const
Returns information if the object is derived from BOARD_CONNECTED_ITEM.
bool Contains(const Vec &aPoint) const
Represent a contiguous set of PCB layers.
bool IsMultilayer() const
bool Overlaps(const LAYER_RANGE &aOther) const
virtual VECTOR2I Anchor(int n) const override
const SHAPE * Shape() const override
Return the geometrical shape of the item.
ITEM * ParentPadVia() const override
void Remove(ITEM *aItem)
Removes an item from the spatial index.
std::list< ITEM * > NET_ITEMS_LIST
int Size() const
Returns number of items stored in the index.
void Add(ITEM *aItem)
Adds item to the spatial index.
int Query(const ITEM *aItem, int aMinDistance, Visitor &aVisitor) const
Searches items in the index that are in proximity of aItem.
NET_ITEMS_LIST * GetItemsForNet(int aNet)
Returns list of all items in a given net.
void Add(const LINE &aLine)
std::vector< ITEM * > & Items()
const std::vector< ITEM * > & CItems() const
Base class for PNS router board items.
void SetLayers(const LAYER_RANGE &aLayers)
virtual const std::string Format() const
virtual void Unmark(int aMarker=-1) const
PnsKind Kind() const
Return the type (kind) of the item.
virtual void SetRank(int aRank)
virtual int Layer() const
virtual const SHAPE * Shape() const
Return the geometrical shape of the item.
const LAYER_RANGE & Layers() const
bool OfKind(int aKindMask) const
virtual VECTOR2I Anchor(int n) const
bool LayersOverlap(const ITEM *aOther) const
Return true if the set of layers spanned by aOther overlaps our layers.
virtual HOLE * Hole() const
bool Collide(const ITEM *aHead, const NODE *aNode, COLLISION_SEARCH_CONTEXT *aCtx=nullptr) const
Check for a collision (clearance violation) with between us and item aOther.
virtual bool HasHole() const
A 2D point on a given set of layers and belonging to a certain net, that links together a number of b...
const std::vector< ITEM * > & LinkList() const
int LinkCount(int aMask=-1) const
LINKED_ITEM * NextSegment(ITEM *aCurrent, bool aAllowLockedSegs=false) const
bool IsLineCorner(bool aAllowLockedSegs=false) const
Checks if a joint connects two segments of the same net, layer, and width.
void Lock(bool aLock=true)
void Link(ITEM *aItem)
Unlink a given board item from the joint (upon its removal from a NODE)
HASH_TAG m_tag
< hash tag for unordered_multimap
void Merge(const JOINT &aJoint)
bool Unlink(ITEM *aItem)
For trivial joints, return the segment adjacent to (aCurrent).
const VECTOR2I & Pos() const
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
const VECTOR2I & CPoint(int aIdx) const
void ClipVertexRange(int aStart, int aEnd)
Return the number of corners of angles specified by mask aAngles.
const SHAPE_LINE_CHAIN & CLine() const
SHAPE_LINE_CHAIN & Line()
void SetWidth(int aWidth)
Return line width.
int Width() const
Return true if the line is geometrically identical as line aOther.
virtual int Width() const
void Link(LINKED_ITEM *aLink)
Return the list of links from the owning node that constitute this line (or NULL if the line is not l...
bool IsLinked() const
Check if the segment aLink is a part of the line.
virtual void ClearLinks()
Return the number of segments that were assembled together to form this line.
Keep the router "world" - i.e.
NODE * Branch()
Create a lightweight copy (called branch) of self that tracks the changes (added/removed items) wrs t...
void linkJoint(const VECTOR2I &aPos, const LAYER_RANGE &aLayers, int aNet, ITEM *aWhere)
Unlink an item from a joint.
void RemoveByMarker(int aMarker)
NODE * m_root
root node of the whole hierarchy
int FindLinesBetweenJoints(const JOINT &aA, const JOINT &aB, std::vector< LINE > &aLines)
Find the joints corresponding to the ends of line aLine.
std::vector< ITEM * > ITEM_VECTOR
int GetClearance(const ITEM *aA, const ITEM *aB, bool aUseClearanceEpsilon=true) const
Return the pre-set worst case clearance between any pair of items.
void followLine(LINKED_ITEM *aCurrent, bool aScanDirection, int &aPos, int aLimit, VECTOR2I *aCorners, LINKED_ITEM **aSegments, bool *aArcReversed, bool &aGuardHit, bool aStopAtLockedJoints, bool aFollowLockedSegments)
void addSolid(SOLID *aSeg)
bool Overrides(ITEM *aItem) const
void removeSegmentIndex(SEGMENT *aSeg)
void rebuildJoint(const JOINT *aJoint, const ITEM *aItem)
void GetUpdatedItems(ITEM_VECTOR &aRemoved, ITEM_VECTOR &aAdded)
Return the list of items removed and added in this branch with respect to the root branch.
void addSegment(SEGMENT *aSeg)
std::vector< std::unique_ptr< SHAPE > > m_edgeExclusions
JOINT_MAP::value_type TagJointPair
bool QueryEdgeExclusions(const VECTOR2I &aPos) const
void AllItemsInNet(int aNet, std::set< ITEM * > &aItems, int aKindMask=-1)
void doRemove(ITEM *aItem)
OPT_OBSTACLE CheckColliding(const ITEM *aItem, int aKindMask=ITEM::ANY_T)
Check if the item collides with anything else in the world, and if found, returns the obstacle.
void addHole(HOLE *aHole)
std::optional< OBSTACLE > OPT_OBSTACLE
std::unordered_set< ITEM * > m_garbageItems
void Dump(bool aLong=false)
void FindLineEnds(const LINE &aLine, JOINT &aA, JOINT &aB)
Destroy all child nodes. Applicable only to the root node.
RULE_RESOLVER * GetRuleResolver() const
Return the number of joints.
int QueryJoints(const BOX2I &aBox, std::vector< JOINT * > &aJoints, LAYER_RANGE aLayerMask=LAYER_RANGE::All(), int aKindMask=ITEM::ANY_T)
std::set< OBSTACLE > OBSTACLES
INDEX * m_index
Geometric/Net index of the items.
std::vector< ITEM * > FindItemsByZone(const ZONE *aParent)
std::unordered_set< ITEM * > m_override
hash of root's items that have been changed in this node
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 LockJoint(const VECTOR2I &aPos, const ITEM *aItem, bool aLock)
ARC * findRedundantArc(const VECTOR2I &A, const VECTOR2I &B, const LAYER_RANGE &lr, int aNet)
void removeArcIndex(ARC *aVia)
JOINT & touchJoint(const VECTOR2I &aPos, const LAYER_RANGE &aLayers, int aNet)
Touch a joint and links it to an m_item.
void AddEdgeExclusion(std::unique_ptr< SHAPE > aShape)
int QueryColliding(const ITEM *aItem, OBSTACLES &aObstacles, const COLLISION_SEARCH_OPTIONS &aOpts=COLLISION_SEARCH_OPTIONS()) const
Find items colliding (closer than clearance) with the item aItem.
int m_maxClearance
worst case item-item clearance
void unlinkJoint(const VECTOR2I &aPos, const LAYER_RANGE &aLayers, int aNet, ITEM *aWhere)
Helpers for adding/removing items.
void removeViaIndex(VIA *aVia)
void add(ITEM *aItem, bool aAllowRedundant=false)
void removeSolidIndex(SOLID *aSeg)
int m_depth
depth of the node (number of parent nodes in the inheritance chain)
bool Add(std::unique_ptr< SEGMENT > &&aSegment, bool aAllowRedundant=false)
Add an item to the current node.
const JOINT * FindJoint(const VECTOR2I &aPos, int aLayer, int aNet) const
Search for a joint at a given position, layer and belonging to given net.
std::set< NODE * > m_children
list of nodes branched from this one
ITEM * FindItemByParent(const BOARD_ITEM *aParent)
JOINT_MAP m_joints
hash table with the joints, linking the items.
NODE * m_parent
node this node was branched from
void ClearRanks(int aMarkerMask=MK_HEAD|MK_VIOLATION)
void Replace(ITEM *aOldItem, std::unique_ptr< ITEM > &&aNewItem)
Replace an item with another one.
void Remove(ARC *aArc)
Remove an item from this branch.
void Commit(NODE *aNode)
Apply the changes from a given branch (aNode) to the root branch.
RULE_RESOLVER * m_ruleResolver
Design rules resolver.
~NODE()
Return the expected clearance between items a and b.
const LINE AssembleLine(LINKED_ITEM *aSeg, int *aOriginSegmentIndex=nullptr, bool aStopAtLockedJoints=false, bool aFollowLockedSegments=false)
Follow the joint map to assemble a line connecting two non-trivial joints starting from segment aSeg.
SEGMENT * findRedundantSegment(const VECTOR2I &A, const VECTOR2I &B, const LAYER_RANGE &lr, int aNet)
const ITEM_SET HitTest(const VECTOR2I &aPoint) const
Find all items that contain the point aPoint.
OBSTACLE_VISITOR(const ITEM *aItem)
const NODE * m_node
node we are searching in (either root or a branch)
const ITEM * m_item
the item we are looking for collisions with
bool visit(ITEM *aCandidate)
void SetWorld(const NODE *aNode, const NODE *aOverride=nullptr)
const NODE * m_override
node that overrides root entries
void SetOwner(const ITEM_OWNER *aOwner)
Set the node that owns this item.
bool BelongsTo(const ITEM_OWNER *aNode) const
virtual DEBUG_DECORATOR * GetDebugDecorator()=0
ROUTER_IFACE * GetInterface() const
static ROUTER * GetInstance()
virtual void ClearCacheForItems(std::vector< const PNS::ITEM * > &aItems)
virtual int ClearanceEpsilon() const
virtual int Clearance(const ITEM *aA, const ITEM *aB, bool aUseClearanceEpsilon=true)=0
virtual const std::string Format() const override
virtual bool HasHole() const override
virtual HOLE * Hole() const override
const VECTOR2I & Pos() const
const VECTOR2I & Pos() const
virtual HOLE * Hole() const override
virtual bool HasHole() const override
SHAPE_ARC Reversed() 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...
const SHAPE_ARC & Arc(size_t aArc) const
SHAPE_LINE_CHAIN & Simplify(bool aRemoveColinear=true)
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.
ssize_t ArcIndex(size_t aSegment) const
Return the arc index for the given segment index.
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.
int PathLength(const VECTOR2I &aP, int aIndex=-1) const
Compute the walk path length from the beginning of the line chain and the point aP belonging to our l...
const SEG CSegment(int aIndex) const
Return a constant copy of the aIndex segment in the line chain.
bool IsArcSegment(size_t aSegment) const
int Find(const VECTOR2I &aP, int aThreshold=0) const
Search for point aP.
virtual bool Collide(const VECTOR2I &aP, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const
Check if the boundary of shape (this) lies closer to the point aP than aClearance,...
const std::string Format() const
Return the vector formatted as a string.
Handle a list of polygons defining a copper zone.
Push and Shove diff pair dimensions (gap) settings dialog.
void HullIntersection(const SHAPE_LINE_CHAIN &hull, const SHAPE_LINE_CHAIN &line, SHAPE_LINE_CHAIN::INTERSECTIONS &ips)
static std::vector< std::string > split(const std::string &aStr, const std::string &aDelim)
Split the input string into a vector of output strings.
const COLLISION_SEARCH_OPTIONS options
std::set< OBSTACLE > & obstacles
std::set< ITEM * > * m_restrictedSet
bool m_useClearanceEpsilon
bool operator()(ITEM *aItem) override
HIT_VISITOR(ITEM_SET &aTab, const VECTOR2I &aPoint)
< Joints are hashed by their position, layers and net.
bool operator()(ITEM *aCandidate) override
COLLISION_SEARCH_CONTEXT * m_ctx
DEFAULT_OBSTACLE_VISITOR(COLLISION_SEARCH_CONTEXT *aCtx, const ITEM *aItem)
virtual ~DEFAULT_OBSTACLE_VISITOR()
Hold an object colliding with another object, along with some useful data about the collision.
int m_distFirst
... and the distance thereof
int m_maxFanoutWidth
worst case (largest) width of the tracks connected to the item
ITEM * m_head
Line we search collisions against.
VECTOR2I m_ipFirst
First intersection between m_head and m_hull.
ITEM * m_item
Item found to be colliding with m_head.
Represent an intersection between two line segments.
VECTOR2I p
Point of intersection between our and their.
int index_their
index of the intersecting corner/segment in the 'their' (Intersect() method parameter) line.