Coding standards and commenting.

This commit is contained in:
Jeff Young 2021-11-30 14:19:39 +00:00
parent a596a1f2e2
commit 0e65fe5d8d
7 changed files with 151 additions and 185 deletions

View File

@ -57,6 +57,11 @@ class BOARD_ITEM;
class ZONE;
class PROGRESS_REPORTER;
/**
* CN_EDGE represents a point-to-point connection, whether realized or unrealized (ie: tracks etc.
* or a ratsnest line).
*/
class CN_EDGE
{
public:
@ -114,6 +119,7 @@ private:
bool m_visible;
};
class CN_CONNECTIVITY_ALGO
{
public:
@ -274,17 +280,18 @@ private:
void markItemNetAsDirty( const BOARD_ITEM* aItem );
private:
CN_LIST m_itemList;
std::unordered_map<const BOARD_ITEM*, ITEM_MAP_ENTRY> m_itemMap;
CLUSTERS m_connClusters;
CLUSTERS m_ratsnestClusters;
std::vector<bool> m_dirtyNets;
PROGRESS_REPORTER* m_progressReporter = nullptr;
PROGRESS_REPORTER* m_progressReporter = nullptr;
};
class CN_VISITOR
{
public:
@ -299,8 +306,8 @@ protected:
void checkZoneZoneConnection( CN_ZONE_LAYER* aZoneLayerA, CN_ZONE_LAYER* aZoneLayerB );
///< The item we are looking for connections to.
CN_ITEM* m_item;
protected:
CN_ITEM* m_item; ///< The item we are looking for connections to.
};
#endif

View File

@ -118,15 +118,19 @@ void CONNECTIVITY_DATA::Move( const VECTOR2I& aDelta )
void CONNECTIVITY_DATA::updateRatsnest()
{
#ifdef PROFILE
#ifdef PROFILE
PROF_COUNTER rnUpdate( "update-ratsnest" );
#endif
#endif
std::vector<RN_NET*> dirty_nets;
// Start with net 1 as net 0 is reserved for not-connected
// Nets without nodes are also ignored
std::copy_if( m_nets.begin() + 1, m_nets.end(), std::back_inserter( dirty_nets ),
[] ( RN_NET* aNet ) { return aNet->IsDirty() && aNet->GetNodeCount() > 0; } );
[] ( RN_NET* aNet )
{
return aNet->IsDirty() && aNet->GetNodeCount() > 0;
} );
// We don't want to spin up a new thread for fewer than 8 nets (overhead costs)
size_t parallelThreadCount = std::min<size_t>( std::thread::hardware_concurrency() - 1,
@ -135,7 +139,8 @@ void CONNECTIVITY_DATA::updateRatsnest()
std::atomic<size_t> nextNet( 0 );
std::vector<std::future<size_t>> returns( parallelThreadCount );
auto update_lambda = [&nextNet, &dirty_nets]() -> size_t
auto update_lambda =
[&nextNet, &dirty_nets]() -> size_t
{
for( size_t i = nextNet++; i < dirty_nets.size(); i = nextNet++ )
dirty_nets[i]->Update();
@ -144,7 +149,9 @@ void CONNECTIVITY_DATA::updateRatsnest()
};
if( parallelThreadCount == 1 )
{
update_lambda();
}
else
{
for( size_t ii = 0; ii < parallelThreadCount; ++ii )
@ -155,15 +162,15 @@ void CONNECTIVITY_DATA::updateRatsnest()
returns[ii].wait();
}
#ifdef PROFILE
#ifdef PROFILE
rnUpdate.Show();
#endif /* PROFILE */
#endif
}
void CONNECTIVITY_DATA::addRatsnestCluster( const std::shared_ptr<CN_CLUSTER>& aCluster )
{
auto rnNet = m_nets[ aCluster->OriginNet() ];
RN_NET* rnNet = m_nets[ aCluster->OriginNet() ];
rnNet->AddCluster( aCluster );
}
@ -184,7 +191,7 @@ void CONNECTIVITY_DATA::RecalculateRatsnest( BOARD_COMMIT* aCommit )
m_nets[i] = new RN_NET;
}
auto clusters = m_connAlgo->GetClusters();
const std::vector<CN_CLUSTER_PTR>& clusters = m_connAlgo->GetClusters();
int dirtyNets = 0;
@ -197,7 +204,7 @@ void CONNECTIVITY_DATA::RecalculateRatsnest( BOARD_COMMIT* aCommit )
}
}
for( const auto& c : clusters )
for( const CN_CLUSTER_PTR& c : clusters )
{
int net = c->OriginNet();
@ -225,7 +232,7 @@ void CONNECTIVITY_DATA::BlockRatsnestItems( const std::vector<BOARD_ITEM*>& aIte
{
std::vector<BOARD_CONNECTED_ITEM*> citems;
for( auto item : aItems )
for( BOARD_ITEM* item : aItems )
{
if( item->Type() == PCB_FOOTPRINT_T )
{
@ -234,20 +241,20 @@ void CONNECTIVITY_DATA::BlockRatsnestItems( const std::vector<BOARD_ITEM*>& aIte
}
else
{
if( auto citem = dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) )
if( BOARD_CONNECTED_ITEM* citem = dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) )
citems.push_back( citem );
}
}
for( const auto& item : citems )
for( const BOARD_CONNECTED_ITEM* item : citems )
{
if ( m_connAlgo->ItemExists( item ) )
{
auto& entry = m_connAlgo->ItemEntry( item );
CN_CONNECTIVITY_ALGO::ITEM_MAP_ENTRY& entry = m_connAlgo->ItemEntry( item );
for( const auto& cnItem : entry.GetItems() )
for( CN_ITEM* cnItem : entry.GetItems() )
{
for( auto anchor : cnItem->Anchors() )
for( const std::shared_ptr<CN_ANCHOR>& anchor : cnItem->Anchors() )
anchor->SetNoLine( true );
}
}
@ -809,7 +816,7 @@ const std::vector<CN_EDGE> CONNECTIVITY_DATA::GetRatsnestForItems( std::vector<B
}
}
for( const auto& netcode : nets )
for( int netcode : nets )
{
RN_NET* net = GetRatsnestForNet( netcode );

View File

@ -55,6 +55,7 @@ class PAD;
class FOOTPRINT;
class PROGRESS_REPORTER;
struct CN_DISJOINT_NET_ENTRY
{
int net;
@ -62,6 +63,7 @@ struct CN_DISJOINT_NET_ENTRY
VECTOR2I anchorA, anchorB;
};
/**
* A structure used for calculating isolated islands on a given zone across all its layers
*/
@ -76,12 +78,14 @@ struct CN_ZONE_ISOLATED_ISLAND_LIST
std::map<PCB_LAYER_ID, std::vector<int>> m_islands;
};
struct RN_DYNAMIC_LINE
{
int netCode;
VECTOR2I a, b;
};
/**
* Controls how nets are propagated through clusters
*/
@ -91,6 +95,7 @@ enum class PROPAGATE_MODE
RESOLVE_CONFLICTS /// Clusters with conflicting drivers are updated to the most popular net
};
// a wrapper class encompassing the connectivity computation algorithm and the
class CONNECTIVITY_DATA
{
@ -307,30 +312,26 @@ public:
}
private:
void updateRatsnest();
/**
* Updates the item positions without modifying the dirtyNet flag. This is valid only when the
* item list contains all elements in the connectivity database
* @param aItems List of items with new positions
*/
void updateItemPositions( const std::vector<BOARD_ITEM*>& aItems );
void addRatsnestCluster( const std::shared_ptr<CN_CLUSTER>& aCluster );
private:
std::shared_ptr<CN_CONNECTIVITY_ALGO> m_connAlgo;
std::shared_ptr<FROM_TO_CACHE> m_fromToCache;
std::vector<RN_DYNAMIC_LINE> m_dynamicRatsnest;
std::vector<RN_NET*> m_nets;
PROGRESS_REPORTER* m_progressReporter;
/// Used to suppress ratsnest calculations on dynamic ratsnests
bool m_skipRatsnest = false;
KISPINLOCK m_lock;
/// Map of netcode -> netclass the net is a member of; used for ratsnest painting
std::map<int, wxString> m_netclassMap;
PROGRESS_REPORTER* m_progressReporter;
};
#endif

View File

@ -51,6 +51,11 @@
class CN_ITEM;
class CN_CLUSTER;
/**
* CN_ANCHOR represents a physical location that can be connected: a pad or a track/arc/via
* endpoint.
*/
class CN_ANCHOR
{
public:
@ -142,20 +147,12 @@ public:
static const int TAG_UNCONNECTED = -1;
private:
///< Position of the anchor.
VECTOR2I m_pos;
VECTOR2I m_pos; ///< Position of the anchor.
CN_ITEM* m_item = nullptr; ///< Pad or track/arc/via owning the anchor.
int m_tag = -1; ///< Tag for quick connection resolution.
bool m_noline = false; ///< Whether it the node can be a target for ratsnest lines.
///< Item owning the anchor.
CN_ITEM* m_item = nullptr;
///< Tag for quick connection resolution.
int m_tag = -1;
///< Whether it the node can be a target for ratsnest lines.
bool m_noline = false;
///< Cluster to which the anchor belongs.
std::shared_ptr<CN_CLUSTER> m_cluster;
std::shared_ptr<CN_CLUSTER> m_cluster; ///< Cluster to which the anchor belongs.
};
@ -163,7 +160,10 @@ typedef std::shared_ptr<CN_ANCHOR> CN_ANCHOR_PTR;
typedef std::vector<CN_ANCHOR_PTR> CN_ANCHORS;
// basic connectivity item
/**
* CN_ITEM represents a BOARD_CONNETED_ITEM in the connectivity system (ie: a pad, track/arc/via,
* or zone).
*/
class CN_ITEM
{
public:
@ -201,26 +201,17 @@ public:
/**
* Set the layers spanned by the item to aLayers.
*/
void SetLayers( const LAYER_RANGE& aLayers )
{
m_layers = aLayers;
}
void SetLayers( const LAYER_RANGE& aLayers ) { m_layers = aLayers; }
/**
* Set the layers spanned by the item to a single layer aLayer.
*/
void SetLayer( int aLayer )
{
m_layers = LAYER_RANGE( aLayer, aLayer );
}
void SetLayer( int aLayer ) { m_layers = LAYER_RANGE( aLayer, aLayer ); }
/**
* Return the contiguous set of layers spanned by the item.
*/
const LAYER_RANGE& Layers() const
{
return m_layers;
}
const LAYER_RANGE& Layers() const { return m_layers; }
/**
* Return the item's layer, for single-layered items only.
@ -237,13 +228,11 @@ public:
EDA_RECT box = m_parent->GetBoundingBox();
m_bbox = BOX2I( box.GetPosition(), box.GetSize() );
}
return m_bbox;
}
BOARD_CONNECTED_ITEM* Parent() const
{
return m_parent;
}
BOARD_CONNECTED_ITEM* Parent() const { return m_parent; }
const CONNECTED_ITEMS& ConnectedItems() const { return m_connected; }
void ClearConnections() { m_connected.clear(); }
@ -295,8 +284,10 @@ private:
std::mutex m_listLock; ///< mutex protecting this item's connected_items set to
};
typedef std::shared_ptr<CN_ITEM> CN_ITEM_PTR;
class CN_ZONE_LAYER : public CN_ITEM
{
public:
@ -352,6 +343,7 @@ private:
PCB_LAYER_ID m_layer;
};
class CN_LIST
{
protected:
@ -371,7 +363,7 @@ public:
void Clear()
{
for( auto item : m_items )
for( CN_ITEM* item : m_items )
delete item;
m_items.clear();
@ -447,6 +439,7 @@ private:
CN_RTREE<CN_ITEM*> m_index;
};
class CN_CLUSTER
{
private:

View File

@ -2,7 +2,7 @@
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 2013-2017 CERN
* Copyright (C) 2019-2020 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 2019-2021 KiCad Developers, see AUTHORS.txt for contributors.
*
* @author Maciej Suminski <maciej.suminski@cern.ch>
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
@ -106,6 +106,7 @@ private:
std::vector<int> m_depth;
};
void RN_NET::kruskalMST( const std::vector<CN_EDGE> &aEdges )
{
disjoint_set dset( m_nodes.size() );
@ -114,10 +115,10 @@ void RN_NET::kruskalMST( const std::vector<CN_EDGE> &aEdges )
int i = 0;
for( auto& node : m_nodes )
for( const CN_ANCHOR_PTR& node : m_nodes )
node->SetTag( i++ );
for( auto& tmp : aEdges )
for( const CN_EDGE& tmp : aEdges )
{
int u = tmp.GetSourceNode()->GetTag();
int v = tmp.GetTargetNode()->GetTag();
@ -173,18 +174,15 @@ public:
void Triangulate( std::vector<CN_EDGE>& mstEdges)
{
std::vector<double> node_pts;
using ANCHOR_LIST = std::vector<CN_ANCHOR_PTR>;
ANCHOR_LIST anchors;
std::vector<ANCHOR_LIST> anchorChains( m_allNodes.size() );
std::vector<CN_ANCHOR_PTR> anchors;
std::vector< std::vector<CN_ANCHOR_PTR> > anchorChains( m_allNodes.size() );
node_pts.reserve( 2 * m_allNodes.size() );
anchors.reserve( m_allNodes.size() );
CN_ANCHOR_PTR prev = nullptr;
for( const auto& n : m_allNodes )
for( const CN_ANCHOR_PTR& n : m_allNodes )
{
if( !prev || prev->Pos() != n->Pos() )
{
@ -208,8 +206,8 @@ public:
// and chain the nodes together.
for( size_t i = 0; i < anchors.size() - 1; i++ )
{
auto src = anchors[i];
auto dst = anchors[i + 1];
const CN_ANCHOR_PTR& src = anchors[i];
const CN_ANCHOR_PTR& dst = anchors[i + 1];
mstEdges.emplace_back( src, dst, src->Dist( *dst ) );
}
}
@ -220,8 +218,8 @@ public:
for( size_t i = 0; i < triangles.size(); i += 3 )
{
auto src = anchors[triangles[i]];
auto dst = anchors[triangles[i + 1]];
CN_ANCHOR_PTR& src = anchors[triangles[i]];
CN_ANCHOR_PTR& dst = anchors[triangles[i + 1]];
mstEdges.emplace_back( src, dst, src->Dist( *dst ) );
src = anchors[triangles[i + 1]];
@ -238,28 +236,29 @@ public:
if( delaunator.halfedges[i] == delaunator::INVALID_INDEX )
continue;
auto src = anchors[triangles[i]];
auto dst = anchors[triangles[delaunator.halfedges[i]]];
const CN_ANCHOR_PTR& src = anchors[triangles[i]];
const CN_ANCHOR_PTR& dst = anchors[triangles[delaunator.halfedges[i]]];
mstEdges.emplace_back( src, dst, src->Dist( *dst ) );
}
}
for( size_t i = 0; i < anchorChains.size(); i++ )
{
auto& chain = anchorChains[i];
std::vector<CN_ANCHOR_PTR>& chain = anchorChains[i];
if( chain.size() < 2 )
continue;
std::sort( chain.begin(), chain.end(),
[] ( const CN_ANCHOR_PTR& a, const CN_ANCHOR_PTR& b ) {
[] ( const CN_ANCHOR_PTR& a, const CN_ANCHOR_PTR& b )
{
return a->GetCluster().get() < b->GetCluster().get();
} );
for( unsigned int j = 1; j < chain.size(); j++ )
{
const auto& prevNode = chain[j - 1];
const auto& curNode = chain[j];
const CN_ANCHOR_PTR& prevNode = chain[j - 1];
const CN_ANCHOR_PTR& curNode = chain[j];
int weight = prevNode->GetCluster() != curNode->GetCluster() ? 1 : 0;
mstEdges.emplace_back( prevNode, curNode, weight );
}
@ -297,7 +296,7 @@ void RN_NET::compute()
else
{
// Set tags to m_nodes as connected
for( const auto& node : m_nodes )
for( const CN_ANCHOR_PTR& node : m_nodes )
node->SetTag( 0 );
}
@ -307,23 +306,21 @@ void RN_NET::compute()
m_triangulator->Clear();
for( const auto& n : m_nodes )
{
for( const CN_ANCHOR_PTR& n : m_nodes )
m_triangulator->AddNode( n );
}
std::vector<CN_EDGE> triangEdges;
triangEdges.reserve( m_nodes.size() + m_boardEdges.size() );
#ifdef PROFILE
#ifdef PROFILE
PROF_COUNTER cnt("triangulate");
#endif
#endif
m_triangulator->Triangulate( triangEdges );
#ifdef PROFILE
#ifdef PROFILE
cnt.Show();
#endif
#endif
for( const auto& e : m_boardEdges )
for( const CN_EDGE& e : m_boardEdges )
triangEdges.emplace_back( e );
std::sort( triangEdges.begin(), triangEdges.end() );
@ -362,10 +359,10 @@ void RN_NET::AddCluster( CN_CLUSTER_PTR aCluster )
{
CN_ANCHOR_PTR firstAnchor;
for( auto item : *aCluster )
for( CN_ITEM* item : *aCluster )
{
bool isZone = dynamic_cast<CN_ZONE_LAYER*>(item) != nullptr;
auto& anchors = item->Anchors();
bool isZone = dynamic_cast<CN_ZONE_LAYER*>( item );
std::vector<CN_ANCHOR_PTR>& anchors = item->Anchors();
unsigned int nAnchors = isZone ? 1 : anchors.size();
if( nAnchors > anchors.size() )
@ -379,10 +376,8 @@ void RN_NET::AddCluster( CN_CLUSTER_PTR aCluster )
if( firstAnchor )
{
if( firstAnchor != anchors[i] )
{
m_boardEdges.emplace_back( firstAnchor, anchors[i], 0 );
}
}
else
{
firstAnchor = anchors[i];
@ -397,16 +392,19 @@ bool RN_NET::NearestBicoloredPair( const RN_NET& aOtherNet, CN_ANCHOR_PTR& aNode
{
bool rv = false;
VECTOR2I::extended_type distMax = VECTOR2I::ECOORD_MAX;
SEG::ecoord distMax_sq = VECTOR2I::ECOORD_MAX;
auto verify = [&]( auto& aTestNode1, auto& aTestNode2 )
auto verify =
[&]( const std::shared_ptr<CN_ANCHOR>& aTestNode1,
const std::shared_ptr<CN_ANCHOR>& aTestNode2 )
{
auto squaredDist = ( aTestNode1->Pos() - aTestNode2->Pos() ).SquaredEuclideanNorm();
VECTOR2I diff = aTestNode1->Pos() - aTestNode2->Pos();
SEG::ecoord dist_sq = diff.SquaredEuclideanNorm();
if( squaredDist < distMax )
if( dist_sq < distMax_sq )
{
rv = true;
distMax = squaredDist;
distMax_sq = dist_sq;
aNode1 = aTestNode1;
aNode2 = aTestNode2;
}
@ -415,7 +413,7 @@ bool RN_NET::NearestBicoloredPair( const RN_NET& aOtherNet, CN_ANCHOR_PTR& aNode
/// Sweep-line algorithm to cut the number of comparisons to find the closest point
///
/// Step 1: The outer loop needs to be the subset (selected nodes) as it is a linear search
for( const auto& nodeA : aOtherNet.m_nodes )
for( const std::shared_ptr<CN_ANCHOR>& nodeA : aOtherNet.m_nodes )
{
if( nodeA->GetNoLine() )
continue;
@ -433,11 +431,11 @@ bool RN_NET::NearestBicoloredPair( const RN_NET& aOtherNet, CN_ANCHOR_PTR& aNode
if( nodeB->GetNoLine() )
continue;
VECTOR2I::extended_type distX = nodeA->Pos().x - nodeB->Pos().x;
SEG::ecoord distX_sq = SEG::Square( nodeA->Pos().x - nodeB->Pos().x );
/// As soon as the x distance (primary sort) is larger than the smallest distance,
/// stop checking further elements
if( distX * distX > distMax )
if( distX_sq > distMax_sq )
break;
verify( nodeA, nodeB );
@ -451,9 +449,9 @@ bool RN_NET::NearestBicoloredPair( const RN_NET& aOtherNet, CN_ANCHOR_PTR& aNode
if( nodeB->GetNoLine() )
continue;
VECTOR2I::extended_type distX = nodeA->Pos().x - nodeB->Pos().x;
SEG::ecoord distX_sq = SEG::Square( nodeA->Pos().x - nodeB->Pos().x );
if( distX * distX > distMax )
if( distX_sq > distMax_sq )
break;
verify( nodeA, nodeB );
@ -466,6 +464,6 @@ bool RN_NET::NearestBicoloredPair( const RN_NET& aOtherNet, CN_ANCHOR_PTR& aNode
void RN_NET::SetVisible( bool aEnabled )
{
for( auto& edge : m_rnEdges )
for( CN_EDGE& edge : m_rnEdges )
edge.SetVisible( aEnabled );
}

View File

@ -74,10 +74,7 @@ public:
/**
* Mark ratsnest for given net as 'dirty', i.e. requiring recomputation.
*/
void MarkDirty()
{
m_dirty = true;
}
void MarkDirty() { m_dirty = true; }
/**
* Return state of the 'dirty' flag, indicating that ratsnest for a given net is invalid
@ -85,20 +82,12 @@ public:
*
* @return True if ratsnest requires recomputation, false otherwise.
*/
bool IsDirty() const
{
return m_dirty;
}
bool IsDirty() const { return m_dirty; }
/**
* Return pointer to a vector of edges that makes ratsnest for a given net.
*
* @return Pointer to a vector of edges that makes ratsnest for a given net.
*/
const std::vector<CN_EDGE> GetUnconnected() const
{
return m_rnEdges;
}
const std::vector<CN_EDGE> GetUnconnected() const { return m_rnEdges; }
/**
* Recompute ratsnest for a net.
@ -108,38 +97,9 @@ public:
void AddCluster( std::shared_ptr<CN_CLUSTER> aCluster );
unsigned int GetNodeCount() const
{
return m_nodes.size();
}
unsigned int GetNodeCount() const { return m_nodes.size(); }
/**
* Return list of nodes that are associated with a given item.
*
* @param aItem is an item for which the list is generated.
* @return List of associated nodes.
*/
std::list<CN_ANCHOR_PTR> GetNodes( const BOARD_CONNECTED_ITEM* aItem ) const;
const std::vector<CN_EDGE>& GetEdges() const
{
return m_rnEdges;
}
/**
* Add all stored items to a list.
*
* @param aOutput is the list that will have items added.
* @param aTypes determines the type of added items.
*/
void GetAllItems( std::list<BOARD_CONNECTED_ITEM*>& aOutput, const KICAD_T aTypes[] ) const;
/**
* Return a single node that lies in the shortest distance from a specific node.
*
* @param aNode is the node for which the closest node is searched.
*/
const CN_ANCHOR_PTR GetClosestNode( const CN_ANCHOR_PTR& aNode ) const;
const std::vector<CN_EDGE>& GetEdges() const { return m_rnEdges; }
bool NearestBicoloredPair( const RN_NET& aOtherNet, CN_ANCHOR_PTR& aNode1,
CN_ANCHOR_PTR& aNode2 ) const;

View File

@ -121,7 +121,7 @@ void RATSNEST_VIEW_ITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const
gal->SetStrokeColor( color.Brightened( 0.5 ) );
if ( l.a == l.b )
if( l.a == l.b )
{
gal->DrawLine( VECTOR2I( l.a.x - CROSS_SIZE, l.a.y - CROSS_SIZE ),
VECTOR2I( l.b.x + CROSS_SIZE, l.b.y + CROSS_SIZE ) );
@ -168,17 +168,17 @@ void RATSNEST_VIEW_ITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const
// Draw the "static" ratsnest
if( highlightedNets.count( i ) )
gal->SetStrokeColor( color.Brightened(0.8) );
gal->SetStrokeColor( color.Brightened( 0.8 ) );
else
gal->SetStrokeColor( color ); // using the default ratsnest color for not highlighted
for( const auto& edge : net->GetUnconnected() )
for( const CN_EDGE& edge : net->GetUnconnected() )
{
//if ( !edge.IsVisible() )
// continue;
const auto& sourceNode = edge.GetSourceNode();
const auto& targetNode = edge.GetTargetNode();
const CN_ANCHOR_PTR& sourceNode = edge.GetSourceNode();
const CN_ANCHOR_PTR& targetNode = edge.GetTargetNode();
const VECTOR2I source( sourceNode->Pos() );
const VECTOR2I target( targetNode->Pos() );