mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-04-21 23:23:47 +00:00
Optimize optimizeZoneToZoneAnchors.
Only do tests between 3 polygon pairs with closest bbox centers. Only do tests between 5 parts of line chain pairs with closest bbox centers. Gets OptimizeRNEdges down to 350 ms See https://gitlab.com/kicad/code/kicad/-/issues/18148
This commit is contained in:
parent
e9ece8266b
commit
8532e1f9ec
libs/kimath
pcbnew/ratsnest
@ -180,6 +180,16 @@ public:
|
||||
*/
|
||||
const VECTOR2I NearestPoint( const SEG &aSeg ) const;
|
||||
|
||||
/**
|
||||
* Compute closest points between this segment and \a aSeg.
|
||||
*
|
||||
* @param aPtA point on this segment (output)
|
||||
* @param aPtB point on the other segment (output)
|
||||
* @param aDistSq squared distance between points (output)
|
||||
* @return true if the operation was successful
|
||||
*/
|
||||
bool NearestPoints( const SEG& aSeg, VECTOR2I& aPtA, VECTOR2I& aPtB, int64_t& aDistSq ) const;
|
||||
|
||||
/**
|
||||
* Reflect a point using this segment as axis.
|
||||
*
|
||||
|
@ -81,11 +81,10 @@ struct CLIPPER_Z_VALUE
|
||||
*/
|
||||
class SHAPE_LINE_CHAIN : public SHAPE_LINE_CHAIN_BASE
|
||||
{
|
||||
private:
|
||||
public:
|
||||
typedef std::vector<VECTOR2I>::iterator point_iter;
|
||||
typedef std::vector<VECTOR2I>::const_iterator point_citer;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Represent an intersection between two line segments
|
||||
*/
|
||||
@ -218,6 +217,40 @@ public:
|
||||
virtual bool Collide( const SEG& aSeg, int aClearance = 0, int* aActual = nullptr,
|
||||
VECTOR2I* aLocation = nullptr ) const override;
|
||||
|
||||
/**
|
||||
* Finds closest points between this and the other line chain. Doesn't test segments or arcs.
|
||||
*
|
||||
* @param aOther the line chain to test against.
|
||||
* @param aPt0 closest point on this line chain (output).
|
||||
* @param aPt1 closest point on the other line chain (output).
|
||||
* @param aDistance distance between points (output).
|
||||
* @return true, if the operation was successful.
|
||||
*/
|
||||
bool ClosestPoints( const SHAPE_LINE_CHAIN& aOther, VECTOR2I& aPt0, VECTOR2I& aPt1 ) const;
|
||||
|
||||
static bool ClosestPoints( const point_citer& aMyStart, const point_citer& aMyEnd,
|
||||
const point_citer& aOtherStart, const point_citer& aOtherEnd,
|
||||
VECTOR2I& aPt0, VECTOR2I& aPt1, int64_t& aDistSq );
|
||||
|
||||
static bool ClosestSegments( const VECTOR2I& aMyPrevPt, const point_citer& aMyStart,
|
||||
const point_citer& aMyEnd, const VECTOR2I& aOtherPrevPt,
|
||||
const point_citer& aOtherStart, const point_citer& aOtherEnd,
|
||||
VECTOR2I& aPt0, VECTOR2I& aPt1, int64_t& aDistSq );
|
||||
|
||||
/**
|
||||
* Finds closest points between segments of this and the other line chain. Doesn't guarantee
|
||||
* that the points are the absolute closest (use ClosestSegments for that) as there might
|
||||
* be edge cases, but it is much faster.
|
||||
*
|
||||
* @param aOther the line chain to test against.
|
||||
* @param aPt0 closest point on this line chain (output).
|
||||
* @param aPt1 closest point on the other line chain (output).
|
||||
* @param aDistance distance between points (output).
|
||||
* @return true, if the operation was successful.
|
||||
*/
|
||||
bool ClosestSegmentsFast( const SHAPE_LINE_CHAIN& aOther, VECTOR2I& aPt0,
|
||||
VECTOR2I& aPt1 ) const;
|
||||
|
||||
SHAPE_LINE_CHAIN& operator=( const SHAPE_LINE_CHAIN& ) = default;
|
||||
|
||||
SHAPE* Clone() const override;
|
||||
|
@ -42,6 +42,10 @@ struct BOX2I_MINMAX
|
||||
{
|
||||
}
|
||||
|
||||
BOX2I_MINMAX( const VECTOR2I& aPt ) : BOX2I_MINMAX( aPt.x, aPt.y ) {}
|
||||
|
||||
BOX2I_MINMAX( int aX, int aY ) : m_Left( aX ), m_Top( aY ), m_Right( aX ), m_Bottom( aY ) {}
|
||||
|
||||
BOX2I_MINMAX( const BOX2I& aBox ) :
|
||||
m_Left( aBox.GetLeft() ), m_Top( aBox.GetTop() ), m_Right( aBox.GetRight() ),
|
||||
m_Bottom( aBox.GetBottom() )
|
||||
@ -81,6 +85,31 @@ struct BOX2I_MINMAX
|
||||
return left <= right && top <= bottom;
|
||||
}
|
||||
|
||||
void Merge( const VECTOR2I& aPt )
|
||||
{
|
||||
m_Left = std::min( m_Left, aPt.x );
|
||||
m_Right = std::max( m_Right, aPt.x );
|
||||
m_Top = std::min( m_Top, aPt.y );
|
||||
m_Bottom = std::max( m_Bottom, aPt.y );
|
||||
}
|
||||
|
||||
VECTOR2I GetCenter() const
|
||||
{
|
||||
int cx = ( (int64_t) m_Left + m_Right ) / 2;
|
||||
int cy = ( (int64_t) m_Top + m_Bottom ) / 2;
|
||||
|
||||
return VECTOR2I( cx, cy );
|
||||
}
|
||||
|
||||
double GetDiameter() const
|
||||
{
|
||||
VECTOR2L start( m_Left, m_Top );
|
||||
VECTOR2L end( m_Right, m_Bottom );
|
||||
VECTOR2L d = end - start;
|
||||
|
||||
return std::hypot( d.x, d.y );
|
||||
}
|
||||
|
||||
int m_Left;
|
||||
int m_Top;
|
||||
int m_Right;
|
||||
|
@ -147,6 +147,64 @@ const VECTOR2I SEG::NearestPoint( const SEG& aSeg ) const
|
||||
}
|
||||
|
||||
|
||||
bool SEG::NearestPoints( const SEG& aSeg, VECTOR2I& aPtA, VECTOR2I& aPtB, int64_t& aDistSq ) const
|
||||
{
|
||||
if( OPT_VECTOR2I p = Intersect( aSeg ) )
|
||||
{
|
||||
aPtA = aPtB = *p;
|
||||
aDistSq = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const VECTOR2I pts_origin[4] =
|
||||
{
|
||||
aSeg.NearestPoint( A ),
|
||||
aSeg.NearestPoint( B ),
|
||||
NearestPoint( aSeg.A ),
|
||||
NearestPoint( aSeg.B )
|
||||
};
|
||||
|
||||
const VECTOR2I* pts_a_out[4] =
|
||||
{
|
||||
&A,
|
||||
&B,
|
||||
&pts_origin[2],
|
||||
&pts_origin[3]
|
||||
};
|
||||
|
||||
const VECTOR2I* pts_b_out[4] =
|
||||
{
|
||||
&pts_origin[0],
|
||||
&pts_origin[1],
|
||||
&aSeg.A,
|
||||
&aSeg.B
|
||||
};
|
||||
|
||||
const ecoord pts_dist[4] =
|
||||
{
|
||||
( pts_origin[0] - A ).SquaredEuclideanNorm(),
|
||||
( pts_origin[1] - B ).SquaredEuclideanNorm(),
|
||||
( pts_origin[2] - aSeg.A ).SquaredEuclideanNorm(),
|
||||
( pts_origin[3] - aSeg.B ).SquaredEuclideanNorm()
|
||||
};
|
||||
|
||||
int min_i = 0;
|
||||
|
||||
for( int i = 0; i < 4; i++ )
|
||||
{
|
||||
if( pts_dist[i] < pts_dist[min_i] )
|
||||
min_i = i;
|
||||
}
|
||||
|
||||
aPtA = *pts_a_out[min_i];
|
||||
aPtB = *pts_b_out[min_i];
|
||||
aDistSq = pts_dist[min_i];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SEG::intersects( const SEG& aSeg, bool aIgnoreEndpoints, bool aLines, VECTOR2I* aPt ) const
|
||||
{
|
||||
const VECTOR2<ecoord> e = VECTOR2<ecoord>( B ) - A;
|
||||
|
@ -549,6 +549,262 @@ void SHAPE_LINE_CHAIN::Rotate( const EDA_ANGLE& aAngle, const VECTOR2I& aCenter
|
||||
}
|
||||
|
||||
|
||||
bool SHAPE_LINE_CHAIN::ClosestSegmentsFast( const SHAPE_LINE_CHAIN& aOther, VECTOR2I& aPt0,
|
||||
VECTOR2I& aPt1 ) const
|
||||
{
|
||||
const std::vector<VECTOR2I>& myPts = m_points;
|
||||
const std::vector<VECTOR2I>& otherPts = aOther.m_points;
|
||||
|
||||
const int c_maxBoxes = 100;
|
||||
const int c_minPtsPerBox = 20;
|
||||
|
||||
int myPointsPerBox = std::max( c_minPtsPerBox, int( myPts.size() / c_maxBoxes ) + 1 );
|
||||
int otherPointsPerBox = std::max( c_minPtsPerBox, int( otherPts.size() / c_maxBoxes ) + 1 );
|
||||
|
||||
int myNumBoxes = ( myPts.size() + myPointsPerBox - 1 ) / myPointsPerBox;
|
||||
int otherNumBoxes = ( otherPts.size() + otherPointsPerBox - 1 ) / otherPointsPerBox;
|
||||
|
||||
struct BOX
|
||||
{
|
||||
BOX2I_MINMAX bbox;
|
||||
VECTOR2I center;
|
||||
int radius;
|
||||
bool valid = false;
|
||||
};
|
||||
|
||||
std::vector<BOX> myBoxes( myNumBoxes );
|
||||
std::vector<BOX> otherBoxes( otherNumBoxes );
|
||||
|
||||
// Calculate bounding boxes
|
||||
for( size_t i = 0; i < myPts.size(); i++ )
|
||||
{
|
||||
const VECTOR2I pt = myPts[i];
|
||||
BOX& box = myBoxes[i / myPointsPerBox];
|
||||
|
||||
if( box.valid )
|
||||
{
|
||||
box.bbox.Merge( pt );
|
||||
}
|
||||
else
|
||||
{
|
||||
box.bbox = BOX2I_MINMAX( pt );
|
||||
box.valid = true;
|
||||
}
|
||||
}
|
||||
|
||||
for( size_t i = 0; i < otherPts.size(); i++ )
|
||||
{
|
||||
const VECTOR2I pt = otherPts[i];
|
||||
BOX& box = otherBoxes[i / otherPointsPerBox];
|
||||
|
||||
if( box.valid )
|
||||
{
|
||||
box.bbox.Merge( pt );
|
||||
}
|
||||
else
|
||||
{
|
||||
box.bbox = BOX2I_MINMAX( pt );
|
||||
box.valid = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Store centers and radiuses
|
||||
for( BOX& box : myBoxes )
|
||||
{
|
||||
box.center = box.bbox.GetCenter();
|
||||
box.radius = int( box.bbox.GetDiameter() / 2 );
|
||||
}
|
||||
|
||||
for( BOX& box : otherBoxes )
|
||||
{
|
||||
box.center = box.bbox.GetCenter();
|
||||
box.radius = int( box.bbox.GetDiameter() / 2 );
|
||||
}
|
||||
|
||||
// Find closest pairs
|
||||
struct DIST_PAIR
|
||||
{
|
||||
DIST_PAIR( int64_t aDistSq, size_t aIdA, size_t aIdB ) :
|
||||
dist( aDistSq ), idA( aIdA ), idB( aIdB )
|
||||
{
|
||||
}
|
||||
|
||||
int64_t dist;
|
||||
size_t idA;
|
||||
size_t idB;
|
||||
};
|
||||
|
||||
std::vector<DIST_PAIR> pairsToTest;
|
||||
|
||||
for( size_t ia = 0; ia < myBoxes.size(); ia++ )
|
||||
{
|
||||
for( size_t ib = 0; ib < otherBoxes.size(); ib++ )
|
||||
{
|
||||
const BOX& ca = myBoxes[ia];
|
||||
const BOX& cb = otherBoxes[ib];
|
||||
|
||||
if( !ca.valid || !cb.valid )
|
||||
continue;
|
||||
|
||||
VECTOR2L pA( ca.center );
|
||||
VECTOR2L pB( cb.center );
|
||||
|
||||
int64_t dist = ( pB - pA ).EuclideanNorm();
|
||||
|
||||
dist -= ca.radius;
|
||||
dist -= cb.radius;
|
||||
|
||||
pairsToTest.emplace_back( dist, ia, ib );
|
||||
}
|
||||
}
|
||||
|
||||
std::sort( pairsToTest.begin(), pairsToTest.end(),
|
||||
[]( const DIST_PAIR& a, const DIST_PAIR& b )
|
||||
{
|
||||
return a.dist < b.dist;
|
||||
} );
|
||||
|
||||
const int c_polyPairsLimit = 5;
|
||||
|
||||
// Find closest segments in tested pairs
|
||||
int64_t total_closest_dist_sq = VECTOR2I::ECOORD_MAX;
|
||||
|
||||
for( size_t pairId = 0; pairId < pairsToTest.size() && pairId < c_polyPairsLimit; pairId++ )
|
||||
{
|
||||
const DIST_PAIR& pair = pairsToTest[pairId];
|
||||
|
||||
VECTOR2I ptA;
|
||||
VECTOR2I ptB;
|
||||
int64_t dist_sq;
|
||||
|
||||
size_t myStartId = pair.idA * myPointsPerBox;
|
||||
size_t myEndId = myStartId + myPointsPerBox;
|
||||
|
||||
if( myEndId > myPts.size() )
|
||||
myEndId = myPts.size();
|
||||
|
||||
VECTOR2I myPrevPt = myPts[myStartId == 0 ? myPts.size() - 1 : myStartId - 1];
|
||||
|
||||
size_t otherStartId = pair.idB * otherPointsPerBox;
|
||||
size_t otherEndId = otherStartId + otherPointsPerBox;
|
||||
|
||||
if( otherEndId > otherPts.size() )
|
||||
otherEndId = otherPts.size();
|
||||
|
||||
VECTOR2I otherPrevPt = otherPts[otherStartId == 0 ? otherPts.size() - 1 : otherStartId - 1];
|
||||
|
||||
if( ClosestSegments( myPrevPt, myPts.begin() + myStartId, myPts.begin() + myEndId,
|
||||
otherPrevPt, otherPts.begin() + otherStartId,
|
||||
otherPts.begin() + otherEndId, ptA, ptB, dist_sq ) )
|
||||
{
|
||||
if( dist_sq < total_closest_dist_sq )
|
||||
{
|
||||
total_closest_dist_sq = dist_sq;
|
||||
aPt0 = ptA;
|
||||
aPt1 = ptB;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return total_closest_dist_sq != VECTOR2I::ECOORD_MAX;
|
||||
}
|
||||
|
||||
|
||||
bool SHAPE_LINE_CHAIN::ClosestSegments( const VECTOR2I& aMyPrevPt, const point_citer& aMyStart,
|
||||
const point_citer& aMyEnd, const VECTOR2I& aOtherPrevPt,
|
||||
const point_citer& aOtherStart,
|
||||
const point_citer& aOtherEnd, VECTOR2I& aPt0,
|
||||
VECTOR2I& aPt1, int64_t& aDistSq )
|
||||
{
|
||||
if( aMyStart == aMyEnd )
|
||||
return false;
|
||||
|
||||
if( aOtherStart == aOtherEnd )
|
||||
return false;
|
||||
|
||||
int64_t closest_dist_sq = VECTOR2I::ECOORD_MAX;
|
||||
VECTOR2I lastPtA = aMyPrevPt;
|
||||
|
||||
for( point_citer itA = aMyStart; itA != aMyEnd; itA++ )
|
||||
{
|
||||
const VECTOR2I& ptA = *itA;
|
||||
VECTOR2I lastPtB = aOtherPrevPt;
|
||||
|
||||
for( point_citer itB = aOtherStart; itB != aOtherEnd; itB++ )
|
||||
{
|
||||
const VECTOR2I& ptB = *itB;
|
||||
|
||||
SEG segA( lastPtA, ptA );
|
||||
SEG segB( lastPtB, ptB );
|
||||
|
||||
VECTOR2I nearestA, nearestB;
|
||||
|
||||
int64_t dist_sq;
|
||||
|
||||
if( segA.NearestPoints( segB, nearestA, nearestB, dist_sq ) )
|
||||
{
|
||||
if( dist_sq < closest_dist_sq )
|
||||
{
|
||||
closest_dist_sq = dist_sq;
|
||||
aPt0 = nearestA;
|
||||
aPt1 = nearestB;
|
||||
}
|
||||
}
|
||||
|
||||
lastPtB = ptB;
|
||||
}
|
||||
|
||||
lastPtA = ptA;
|
||||
}
|
||||
|
||||
aDistSq = closest_dist_sq;
|
||||
return closest_dist_sq != VECTOR2I::ECOORD_MAX;
|
||||
}
|
||||
|
||||
|
||||
bool SHAPE_LINE_CHAIN::ClosestPoints( const point_citer& aMyStart, const point_citer& aMyEnd,
|
||||
const point_citer& aOtherStart, const point_citer& aOtherEnd,
|
||||
VECTOR2I& aPt0, VECTOR2I& aPt1, int64_t& aDistSq )
|
||||
{
|
||||
int64_t closest_dist_sq = VECTOR2I::ECOORD_MAX;
|
||||
|
||||
for( point_citer itA = aMyStart; itA != aMyEnd; itA++ )
|
||||
{
|
||||
const VECTOR2I& ptA = *itA;
|
||||
|
||||
for( point_citer itB = aOtherStart; itB != aOtherEnd; itB++ )
|
||||
{
|
||||
const VECTOR2I& ptB = *itB;
|
||||
|
||||
ecoord dx = (ecoord) ptB.x - ptA.x;
|
||||
ecoord dy = (ecoord) ptB.y - ptA.y;
|
||||
|
||||
SEG::ecoord dist_sq = dx * dx + dy * dy;
|
||||
|
||||
if( dist_sq < closest_dist_sq )
|
||||
{
|
||||
closest_dist_sq = dist_sq;
|
||||
aPt0 = ptA;
|
||||
aPt1 = ptB;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aDistSq = closest_dist_sq;
|
||||
return closest_dist_sq != VECTOR2I::ECOORD_MAX;
|
||||
}
|
||||
|
||||
|
||||
bool SHAPE_LINE_CHAIN::ClosestPoints( const SHAPE_LINE_CHAIN& aOther, VECTOR2I& aPt0,
|
||||
VECTOR2I& aPt1 ) const
|
||||
{
|
||||
ecoord dist_sq;
|
||||
|
||||
return ClosestPoints( m_points.cbegin(), m_points.cend(), aOther.m_points.cbegin(),
|
||||
aOther.m_points.cend(), aPt0, aPt1, dist_sq );
|
||||
}
|
||||
|
||||
|
||||
bool SHAPE_LINE_CHAIN_BASE::Collide( const SEG& aSeg, int aClearance, int* aActual,
|
||||
VECTOR2I* aLocation ) const
|
||||
{
|
||||
|
@ -374,47 +374,111 @@ void RN_NET::OptimizeRNEdges()
|
||||
auto optimizeZoneToZoneAnchors =
|
||||
[&]( const std::shared_ptr<const CN_ANCHOR>& a,
|
||||
const std::shared_ptr<const CN_ANCHOR>& b,
|
||||
const std::function<void(const std::shared_ptr<const CN_ANCHOR>&)>& setOptimizedATo,
|
||||
const std::function<void(const std::shared_ptr<const CN_ANCHOR>&)>& setOptimizedBTo )
|
||||
const std::function<void( const std::shared_ptr<const CN_ANCHOR>& )>&
|
||||
setOptimizedATo,
|
||||
const std::function<void( const std::shared_ptr<const CN_ANCHOR>& )>&
|
||||
setOptimizedBTo )
|
||||
{
|
||||
struct CENTER
|
||||
{
|
||||
VECTOR2I pt;
|
||||
bool valid = false;
|
||||
};
|
||||
|
||||
struct DIST_PAIR
|
||||
{
|
||||
DIST_PAIR( int64_t aDistSq, size_t aIdA, size_t aIdB )
|
||||
: dist_sq( aDistSq ), idA( aIdA ), idB( aIdB )
|
||||
{}
|
||||
|
||||
int64_t dist_sq;
|
||||
size_t idA;
|
||||
size_t idB;
|
||||
};
|
||||
|
||||
const std::vector<CN_ITEM*>& connectedItemsA = a->Item()->ConnectedItems();
|
||||
const std::vector<CN_ITEM*>& connectedItemsB = b->Item()->ConnectedItems();
|
||||
|
||||
std::vector<CENTER> centersA( connectedItemsA.size() );
|
||||
std::vector<CENTER> centersB( connectedItemsB.size() );
|
||||
|
||||
for( size_t i = 0; i < connectedItemsA.size(); i++ )
|
||||
{
|
||||
CN_ITEM* itemA = connectedItemsA[i];
|
||||
CN_ZONE_LAYER* zoneLayerA = dynamic_cast<CN_ZONE_LAYER*>( itemA );
|
||||
|
||||
if( !zoneLayerA )
|
||||
continue;
|
||||
|
||||
const SHAPE_LINE_CHAIN& shapeA = zoneLayerA->GetOutline();
|
||||
centersA[i].pt = shapeA.BBox().GetCenter();
|
||||
centersA[i].valid = true;
|
||||
}
|
||||
|
||||
for( size_t i = 0; i < connectedItemsB.size(); i++ )
|
||||
{
|
||||
CN_ITEM* itemB = connectedItemsB[i];
|
||||
CN_ZONE_LAYER* zoneLayerB = dynamic_cast<CN_ZONE_LAYER*>( itemB );
|
||||
|
||||
if( !zoneLayerB )
|
||||
continue;
|
||||
|
||||
const SHAPE_LINE_CHAIN& shapeB = zoneLayerB->GetOutline();
|
||||
centersB[i].pt = shapeB.BBox().GetCenter();
|
||||
centersB[i].valid = true;
|
||||
}
|
||||
|
||||
std::vector<DIST_PAIR> pairsToTest;
|
||||
|
||||
for( size_t ia = 0; ia < centersA.size(); ia++ )
|
||||
{
|
||||
for( size_t ib = 0; ib < centersB.size(); ib++ )
|
||||
{
|
||||
for( CN_ITEM* itemA : a->Item()->ConnectedItems() )
|
||||
{
|
||||
CN_ZONE_LAYER* zoneLayerA = dynamic_cast<CN_ZONE_LAYER*>( itemA );
|
||||
const CENTER& ca = centersA[ia];
|
||||
const CENTER& cb = centersB[ib];
|
||||
|
||||
if( !zoneLayerA )
|
||||
continue;
|
||||
if( !ca.valid || !cb.valid )
|
||||
continue;
|
||||
|
||||
for( CN_ITEM* itemB : b->Item()->ConnectedItems() )
|
||||
{
|
||||
CN_ZONE_LAYER* zoneLayerB = dynamic_cast<CN_ZONE_LAYER*>( itemB );
|
||||
VECTOR2L pA( ca.pt );
|
||||
VECTOR2L pB( cb.pt );
|
||||
|
||||
if( !zoneLayerB || zoneLayerB == zoneLayerA )
|
||||
continue;
|
||||
int64_t dist_sq = ( pB - pA ).SquaredEuclideanNorm();
|
||||
pairsToTest.emplace_back( dist_sq, ia, ib );
|
||||
}
|
||||
}
|
||||
|
||||
if( zoneLayerB->Layer() == zoneLayerA->Layer() )
|
||||
{
|
||||
// Process the first matching layer. We don't really care if it's
|
||||
// the "best" layer or not, as anything will be better than the
|
||||
// original anchors (which are connected to the zone and so certainly
|
||||
// don't look like they should have ratsnest lines coming off them).
|
||||
std::sort( pairsToTest.begin(), pairsToTest.end(),
|
||||
[]( const DIST_PAIR& a, const DIST_PAIR& b )
|
||||
{
|
||||
return a.dist_sq < b.dist_sq;
|
||||
} );
|
||||
|
||||
VECTOR2I startA = zoneLayerA->GetOutline().GetPoint( 0 );
|
||||
VECTOR2I startB = zoneLayerB->GetOutline().GetPoint( 0 );
|
||||
const SHAPE* shapeA = &zoneLayerA->GetOutline();
|
||||
const SHAPE* shapeB = &zoneLayerB->GetOutline();
|
||||
int startDist = ( startA - startB ).EuclideanNorm();
|
||||
const int c_polyPairsLimit = 3;
|
||||
|
||||
VECTOR2I ptA;
|
||||
shapeA->Collide( shapeB, startDist + 10, nullptr, &ptA );
|
||||
setOptimizedATo( std::make_shared<CN_ANCHOR>( ptA, zoneLayerA ) );
|
||||
for( size_t i = 0; i < pairsToTest.size() && i < c_polyPairsLimit; i++ )
|
||||
{
|
||||
const DIST_PAIR& pair = pairsToTest[i];
|
||||
|
||||
VECTOR2I ptB;
|
||||
shapeB->Collide( shapeA, startDist + 10, nullptr, &ptB );
|
||||
setOptimizedBTo( std::make_shared<CN_ANCHOR>( ptB, zoneLayerB ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
CN_ZONE_LAYER* zoneLayerA = static_cast<CN_ZONE_LAYER*>( connectedItemsA[pair.idA] );
|
||||
CN_ZONE_LAYER* zoneLayerB = static_cast<CN_ZONE_LAYER*>( connectedItemsB[pair.idB] );
|
||||
|
||||
if( zoneLayerA == zoneLayerB )
|
||||
continue;
|
||||
|
||||
const SHAPE_LINE_CHAIN& shapeA = zoneLayerA->GetOutline();
|
||||
const SHAPE_LINE_CHAIN& shapeB = zoneLayerB->GetOutline();
|
||||
|
||||
VECTOR2I ptA;
|
||||
VECTOR2I ptB;
|
||||
|
||||
if( shapeA.ClosestSegmentsFast( shapeB, ptA, ptB ) )
|
||||
{
|
||||
setOptimizedATo( std::make_shared<CN_ANCHOR>( ptA, zoneLayerA ) );
|
||||
setOptimizedBTo( std::make_shared<CN_ANCHOR>( ptB, zoneLayerB ) );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for( CN_EDGE& edge : m_rnEdges )
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user