PNS: First pass at updating meander placers for arcs
Fixes https://gitlab.com/kicad/code/kicad/-/issues/6464
This commit is contained in:
parent
8619086cf2
commit
7431d5c985
|
@ -135,6 +135,10 @@ public:
|
|||
|
||||
void Mirror( bool aX = true, bool aY = false, const VECTOR2I& aVector = { 0, 0 } );
|
||||
|
||||
void Reverse();
|
||||
|
||||
SHAPE_ARC Reversed() const;
|
||||
|
||||
double GetRadius() const;
|
||||
|
||||
SEG GetChord() const
|
||||
|
|
|
@ -654,16 +654,15 @@ public:
|
|||
int NearestSegment( const VECTOR2I& aP ) const;
|
||||
|
||||
/**
|
||||
* Function NearestPoint()
|
||||
*
|
||||
* Finds a point on the line chain that is closest to point aP.
|
||||
* @param aP is the point to find
|
||||
* @param aAllowInternalShapePoints if false will not return points internal to an arc (i.e.
|
||||
* only the arc endpoints are possible candidates)
|
||||
* @return the nearest point.
|
||||
*/
|
||||
const VECTOR2I NearestPoint( const VECTOR2I& aP ) const;
|
||||
const VECTOR2I NearestPoint( const VECTOR2I& aP, bool aAllowInternalShapePoints = true ) const;
|
||||
|
||||
/**
|
||||
* Function NearestPoint()
|
||||
*
|
||||
* Finds a point on the line chain that is closest to the line defined by the points of
|
||||
* segment aSeg, also returns the distance.
|
||||
* @param aSeg Segment defining the line.
|
||||
|
|
|
@ -472,3 +472,15 @@ void SHAPE_ARC::Mirror( bool aX, bool aY, const VECTOR2I& aVector )
|
|||
|
||||
update_bbox();
|
||||
}
|
||||
|
||||
|
||||
void SHAPE_ARC::Reverse()
|
||||
{
|
||||
std::swap( m_start, m_end );
|
||||
}
|
||||
|
||||
|
||||
SHAPE_ARC SHAPE_ARC::Reversed() const
|
||||
{
|
||||
return SHAPE_ARC( m_end, m_mid, m_start, m_width );
|
||||
}
|
||||
|
|
|
@ -220,6 +220,8 @@ const SHAPE_LINE_CHAIN SHAPE_LINE_CHAIN::Reverse() const
|
|||
sh = a.m_arcs.size() - sh - 1;
|
||||
}
|
||||
|
||||
for( SHAPE_ARC& arc : a.m_arcs )
|
||||
arc.Reverse();
|
||||
|
||||
a.m_closed = m_closed;
|
||||
|
||||
|
@ -390,6 +392,11 @@ int SHAPE_LINE_CHAIN::Split( const VECTOR2I& aP )
|
|||
|
||||
if( ii >= 0 )
|
||||
{
|
||||
// Are we splitting at the beginning of an arc? If so, let's split right before so that
|
||||
// the shape is preserved
|
||||
if( ii < PointCount() - 1 && m_shapes[ii] >= 0 && m_shapes[ii] == m_shapes[ii + 1] )
|
||||
ii--;
|
||||
|
||||
m_points.insert( m_points.begin() + ii + 1, aP );
|
||||
m_shapes.insert( m_shapes.begin() + ii + 1, ssize_t( SHAPE_IS_PT ) );
|
||||
|
||||
|
@ -528,34 +535,42 @@ const SHAPE_LINE_CHAIN SHAPE_LINE_CHAIN::Slice( int aStartIndex, int aEndIndex )
|
|||
if( aStartIndex < 0 )
|
||||
aStartIndex += PointCount();
|
||||
|
||||
for( int i = aStartIndex; i <= aEndIndex && static_cast<size_t>( i ) < m_points.size(); i++ )
|
||||
#if 0
|
||||
int numPoints = static_cast<int>( m_points.size() );
|
||||
|
||||
for( int i = aStartIndex; i <= aEndIndex && i < numPoints; i++ )
|
||||
{
|
||||
if( m_shapes[i] != SHAPE_IS_PT )
|
||||
{
|
||||
int arcIdx = m_shapes[i];
|
||||
bool wholeArc = true;
|
||||
int arcStart = i;
|
||||
|
||||
// wxASSERT_MSG( i == 0 || ( m_shapes[i - 1] != arcIdx ),
|
||||
// "SHAPE_LINE_CHAIN::Slice in the middle of an arc!" );
|
||||
if( i > 0 && m_shapes[i - 1] >= 0 && m_shapes[i - 1] != arcIdx )
|
||||
wholeArc = false;
|
||||
|
||||
rv.Append( m_arcs[arcIdx] );
|
||||
|
||||
while( m_shapes[i] == arcIdx && static_cast<size_t>( i ) < m_shapes.size() )
|
||||
while( i < numPoints && m_shapes[i] == arcIdx )
|
||||
i++;
|
||||
|
||||
i--;
|
||||
|
||||
// FIXME: PNS currently slices in the middle of arcs all the time (LINE::Walkaround)
|
||||
// wxASSERT_MSG( i <= aEndIndex, "SHAPE_LINE_CHAIN::Slice in the middle of an arc!" );
|
||||
if( i > aEndIndex )
|
||||
wholeArc = false;
|
||||
|
||||
if( wholeArc )
|
||||
{
|
||||
rv.Append( m_arcs[arcIdx] );
|
||||
}
|
||||
else
|
||||
{
|
||||
rv.Append( m_points[arcStart] );
|
||||
i = arcStart;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rv.Append( m_points[i] );
|
||||
}
|
||||
}
|
||||
#else
|
||||
rv.Append( m_points[i] );
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
@ -1036,7 +1051,8 @@ SHAPE_LINE_CHAIN& SHAPE_LINE_CHAIN::Simplify( bool aRemoveColinear )
|
|||
}
|
||||
|
||||
|
||||
const VECTOR2I SHAPE_LINE_CHAIN::NearestPoint( const VECTOR2I& aP ) const
|
||||
const VECTOR2I SHAPE_LINE_CHAIN::NearestPoint( const VECTOR2I& aP,
|
||||
bool aAllowInternalShapePoints ) const
|
||||
{
|
||||
int min_d = INT_MAX;
|
||||
int nearest = 0;
|
||||
|
@ -1045,13 +1061,38 @@ const VECTOR2I SHAPE_LINE_CHAIN::NearestPoint( const VECTOR2I& aP ) const
|
|||
{
|
||||
int d = CSegment( i ).Distance( aP );
|
||||
|
||||
if( d < min_d )
|
||||
bool isInternalShapePoint = false;
|
||||
|
||||
// An internal shape point here is everything after the start of an arc and before the
|
||||
// second-to-last vertex of the arc, because we are looking at segments here!
|
||||
if( i > 0 && i < SegmentCount() - 1 && m_shapes[i] >= 0 &&
|
||||
( ( m_shapes[i - 1] >= 0 && m_shapes[i - 1] == m_shapes[i] ) &&
|
||||
( m_shapes[i + 2] >= 0 && m_shapes[i + 2] == m_shapes[i] ) ) )
|
||||
{
|
||||
isInternalShapePoint = true;
|
||||
}
|
||||
|
||||
if( ( d < min_d ) && ( aAllowInternalShapePoints || !isInternalShapePoint ) )
|
||||
{
|
||||
min_d = d;
|
||||
nearest = i;
|
||||
}
|
||||
}
|
||||
|
||||
// Is this the start of an arc? If so, return it directly
|
||||
if( !aAllowInternalShapePoints &&
|
||||
( ( nearest == 0 && m_shapes[nearest] >= 0 ) ||
|
||||
( m_shapes[nearest] >= 0 && m_shapes[nearest] != m_shapes[nearest - 1] ) ) )
|
||||
{
|
||||
return m_points[nearest];
|
||||
}
|
||||
else if( !aAllowInternalShapePoints && nearest < SegmentCount() &&
|
||||
m_shapes[nearest] >= 0 && m_shapes[nearest + 1] == m_shapes[nearest] )
|
||||
{
|
||||
// If the nearest segment is the last of the arc, just return the arc endpoint
|
||||
return m_points[nearest + 1];
|
||||
}
|
||||
|
||||
return CSegment( nearest ).NearestPoint( aP );
|
||||
}
|
||||
|
||||
|
|
|
@ -71,20 +71,15 @@ NODE* DP_MEANDER_PLACER::CurrentNode( bool aLoopsRemoved ) const
|
|||
|
||||
bool DP_MEANDER_PLACER::Start( const VECTOR2I& aP, ITEM* aStartItem )
|
||||
{
|
||||
VECTOR2I p;
|
||||
|
||||
if( !aStartItem || !aStartItem->OfKind( ITEM::SEGMENT_T ) )
|
||||
if( !aStartItem || !aStartItem->OfKind( ITEM::SEGMENT_T | ITEM::ARC_T ) )
|
||||
{
|
||||
Router()->SetFailureReason( _( "Please select a track whose length you want to tune." ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
m_initialSegment = static_cast<SEGMENT*>( aStartItem );
|
||||
|
||||
p = m_initialSegment->Seg().NearestPoint( aP );
|
||||
|
||||
m_currentNode=NULL;
|
||||
m_currentStart = p;
|
||||
m_initialSegment = static_cast<LINKED_ITEM*>( aStartItem );
|
||||
m_currentNode = nullptr;
|
||||
m_currentStart = getSnappedStartPoint( m_initialSegment, aP );
|
||||
|
||||
m_world = Router()->GetWorld()->Branch();
|
||||
|
||||
|
|
|
@ -145,7 +145,7 @@ private:
|
|||
|
||||
SHAPE_LINE_CHAIN m_finalShapeP, m_finalShapeN;
|
||||
MEANDERED_LINE m_result;
|
||||
SEGMENT* m_initialSegment;
|
||||
LINKED_ITEM* m_initialSegment;
|
||||
|
||||
long long int m_lastLength;
|
||||
int m_padToDieP;
|
||||
|
|
|
@ -59,20 +59,15 @@ NODE* MEANDER_PLACER::CurrentNode( bool aLoopsRemoved ) const
|
|||
|
||||
bool MEANDER_PLACER::Start( const VECTOR2I& aP, ITEM* aStartItem )
|
||||
{
|
||||
VECTOR2I p;
|
||||
|
||||
if( !aStartItem || !aStartItem->OfKind( ITEM::SEGMENT_T ) )
|
||||
if( !aStartItem || !aStartItem->OfKind( ITEM::SEGMENT_T | ITEM::ARC_T ) )
|
||||
{
|
||||
Router()->SetFailureReason( _( "Please select a track whose length you want to tune." ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
m_initialSegment = static_cast<SEGMENT*>( aStartItem );
|
||||
|
||||
p = m_initialSegment->Seg().NearestPoint( aP );
|
||||
|
||||
m_currentNode = NULL;
|
||||
m_currentStart = p;
|
||||
m_initialSegment = static_cast<LINKED_ITEM*>( aStartItem );
|
||||
m_currentNode = nullptr;
|
||||
m_currentStart = getSnappedStartPoint( m_initialSegment, aP );
|
||||
|
||||
m_world = Router()->GetWorld()->Branch();
|
||||
m_originLine = m_world->AssembleLine( m_initialSegment );
|
||||
|
@ -127,8 +122,13 @@ bool MEANDER_PLACER::doMove( const VECTOR2I& aP, ITEM* aEndItem, long long int a
|
|||
m_result.SetWidth( m_originLine.Width() );
|
||||
m_result.SetBaselineOffset( 0 );
|
||||
|
||||
const std::vector<ssize_t>& tunedShapes = tuned.CShapes();
|
||||
|
||||
for( int i = 0; i < tuned.SegmentCount(); i++ )
|
||||
{
|
||||
if( tunedShapes[i] >= 0 )
|
||||
continue;
|
||||
|
||||
const SEG s = tuned.CSegment( i );
|
||||
m_result.AddCorner( s.A );
|
||||
m_result.MeanderSegment( s );
|
||||
|
|
|
@ -116,7 +116,7 @@ protected:
|
|||
|
||||
SHAPE_LINE_CHAIN m_finalShape;
|
||||
MEANDERED_LINE m_result;
|
||||
SEGMENT* m_initialSegment;
|
||||
LINKED_ITEM* m_initialSegment;
|
||||
|
||||
long long int m_lastLength;
|
||||
TUNING_STATUS m_lastStatus;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "pns_meander.h"
|
||||
#include "pns_router.h"
|
||||
#include "pns_solid.h"
|
||||
#include "pns_arc.h"
|
||||
|
||||
namespace PNS {
|
||||
|
||||
|
@ -85,8 +86,8 @@ void MEANDER_PLACER_BASE::cutTunedLine( const SHAPE_LINE_CHAIN& aOrigin, const V
|
|||
}
|
||||
}
|
||||
|
||||
VECTOR2I n = aOrigin.NearestPoint( cp );
|
||||
VECTOR2I m = aOrigin.NearestPoint( aTuneStart );
|
||||
VECTOR2I n = aOrigin.NearestPoint( cp, false );
|
||||
VECTOR2I m = aOrigin.NearestPoint( aTuneStart, false );
|
||||
|
||||
SHAPE_LINE_CHAIN l( aOrigin );
|
||||
l.Split( n );
|
||||
|
@ -235,4 +236,28 @@ int MEANDER_PLACER_BASE::compareWithTolerance(
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
VECTOR2I MEANDER_PLACER_BASE::getSnappedStartPoint( LINKED_ITEM* aStartItem, VECTOR2I aStartPoint )
|
||||
{
|
||||
if( aStartItem->Kind() == ITEM::SEGMENT_T )
|
||||
{
|
||||
return static_cast<SEGMENT*>( aStartItem )->Seg().NearestPoint( aStartPoint );
|
||||
}
|
||||
else
|
||||
{
|
||||
wxASSERT( aStartItem->Kind() == ITEM::ARC_T );
|
||||
ARC* arc = static_cast<ARC*>( aStartItem );
|
||||
|
||||
if( ( VECTOR2I( arc->Anchor( 0 ) - aStartPoint ) ).SquaredEuclideanNorm() <=
|
||||
( VECTOR2I( arc->Anchor( 1 ) - aStartPoint ) ).SquaredEuclideanNorm() )
|
||||
{
|
||||
return arc->Anchor( 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
return arc->Anchor( 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -159,6 +159,8 @@ protected:
|
|||
int compareWithTolerance(
|
||||
long long int aValue, long long int aExpected, long long int aTolerance = 0 ) const;
|
||||
|
||||
VECTOR2I getSnappedStartPoint( LINKED_ITEM* aStartItem, VECTOR2I aStartPoint );
|
||||
|
||||
///> pointer to world to search colliding items
|
||||
NODE* m_world;
|
||||
|
||||
|
|
|
@ -48,20 +48,15 @@ MEANDER_SKEW_PLACER::~MEANDER_SKEW_PLACER( )
|
|||
|
||||
bool MEANDER_SKEW_PLACER::Start( const VECTOR2I& aP, ITEM* aStartItem )
|
||||
{
|
||||
VECTOR2I p;
|
||||
|
||||
if( !aStartItem || !aStartItem->OfKind( ITEM::SEGMENT_T ) )
|
||||
if( !aStartItem || !aStartItem->OfKind( ITEM::SEGMENT_T | ITEM::ARC_T) )
|
||||
{
|
||||
Router()->SetFailureReason( _( "Please select a differential pair trace you want to tune." ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
m_initialSegment = static_cast<SEGMENT*>( aStartItem );
|
||||
|
||||
p = m_initialSegment->Seg().NearestPoint( aP );
|
||||
|
||||
m_currentNode = NULL;
|
||||
m_currentStart = p;
|
||||
m_initialSegment = static_cast<LINKED_ITEM*>( aStartItem );
|
||||
m_currentNode = nullptr;
|
||||
m_currentStart = getSnappedStartPoint( m_initialSegment, aP );
|
||||
|
||||
m_world = Router()->GetWorld( )->Branch();
|
||||
m_originLine = m_world->AssembleLine( m_initialSegment );
|
||||
|
|
Loading…
Reference in New Issue