PNS: Fix tuning calculations through locked segments
Fixes https://gitlab.com/kicad/code/kicad/-/issues/9727
This commit is contained in:
parent
2d1ad52212
commit
7de9e48b57
|
@ -95,12 +95,35 @@ public:
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
///< Return true if the joint is a trivial line corner, connecting two
|
||||
///< segments of the same net, on the same layer.
|
||||
bool IsLineCorner() const
|
||||
/**
|
||||
* Checks if a joint connects two segments of the same net, layer, and width.
|
||||
* @param aAllowLockedSegs will consider joints between locked and unlocked segments as trivial
|
||||
* @return true if the joint is a trivial line corner
|
||||
*/
|
||||
bool IsLineCorner( bool aAllowLockedSegs = false ) const
|
||||
{
|
||||
if( m_linkedItems.Size() != 2 || m_linkedItems.Count( SEGMENT_T | ARC_T ) != 2 )
|
||||
return false;
|
||||
{
|
||||
if( !aAllowLockedSegs )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if( m_linkedItems.Size() == 3
|
||||
&& m_linkedItems.Count( SEGMENT_T | ARC_T ) == 2
|
||||
&& m_linkedItems.Count( VIA_T ) == 1 )
|
||||
{
|
||||
assert( static_cast<const ITEM*>( m_linkedItems[2] )->Kind() == VIA_T );
|
||||
|
||||
const VIA* via = static_cast<const VIA*>( m_linkedItems[2] );
|
||||
|
||||
if( !via->IsVirtual() )
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
auto seg1 = static_cast<LINKED_ITEM*>( m_linkedItems[0] );
|
||||
auto seg2 = static_cast<LINKED_ITEM*>( m_linkedItems[1] );
|
||||
|
@ -156,9 +179,9 @@ public:
|
|||
|
||||
///< For trivial joints, return the segment adjacent to (aCurrent). For non-trival ones,
|
||||
///< return NULL, indicating the end of line.
|
||||
LINKED_ITEM* NextSegment( ITEM* aCurrent ) const
|
||||
LINKED_ITEM* NextSegment( ITEM* aCurrent, bool aAllowLockedSegs = false ) const
|
||||
{
|
||||
if( !IsLineCorner() )
|
||||
if( !IsLineCorner( aAllowLockedSegs ) )
|
||||
return nullptr;
|
||||
|
||||
return static_cast<LINKED_ITEM*>( m_linkedItems[m_linkedItems[0] == aCurrent ? 1 : 0] );
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
#include "pns_arc.h"
|
||||
#include "pns_item.h"
|
||||
#include "pns_itemset.h"
|
||||
#include "pns_line.h"
|
||||
#include "pns_node.h"
|
||||
#include "pns_via.h"
|
||||
|
@ -896,7 +897,7 @@ void NODE::Remove( LINE& aLine )
|
|||
|
||||
void NODE::followLine( LINKED_ITEM* aCurrent, bool aScanDirection, int& aPos, int aLimit,
|
||||
VECTOR2I* aCorners, LINKED_ITEM** aSegments, bool* aArcReversed,
|
||||
bool& aGuardHit, bool aStopAtLockedJoints )
|
||||
bool& aGuardHit, bool aStopAtLockedJoints, bool aFollowLockedSegments )
|
||||
{
|
||||
bool prevReversed = false;
|
||||
|
||||
|
@ -904,19 +905,19 @@ void NODE::followLine( LINKED_ITEM* aCurrent, bool aScanDirection, int& aPos, in
|
|||
|
||||
for( int count = 0 ; ; ++count )
|
||||
{
|
||||
const VECTOR2I p = aCurrent->Anchor( aScanDirection ^ prevReversed );
|
||||
const JOINT* jt = FindJoint( p, aCurrent );
|
||||
const VECTOR2I p = aCurrent->Anchor( aScanDirection ^ prevReversed );
|
||||
const JOINT* jt = FindJoint( p, aCurrent );
|
||||
|
||||
assert( jt );
|
||||
|
||||
aCorners[aPos] = jt->Pos();
|
||||
aSegments[aPos] = aCurrent;
|
||||
aCorners[aPos] = jt->Pos();
|
||||
aSegments[aPos] = aCurrent;
|
||||
aArcReversed[aPos] = false;
|
||||
|
||||
if( aCurrent->Kind() == ITEM::ARC_T )
|
||||
{
|
||||
if( ( aScanDirection && jt->Pos() == aCurrent->Anchor( 0 ) ) ||
|
||||
( !aScanDirection && jt->Pos() == aCurrent->Anchor( 1 ) ) )
|
||||
if( ( aScanDirection && jt->Pos() == aCurrent->Anchor( 0 ) )
|
||||
|| ( !aScanDirection && jt->Pos() == aCurrent->Anchor( 1 ) ) )
|
||||
aArcReversed[aPos] = true;
|
||||
}
|
||||
|
||||
|
@ -933,10 +934,10 @@ void NODE::followLine( LINKED_ITEM* aCurrent, bool aScanDirection, int& aPos, in
|
|||
|
||||
bool locked = aStopAtLockedJoints ? jt->IsLocked() : false;
|
||||
|
||||
if( locked || !jt->IsLineCorner() || aPos < 0 || aPos == aLimit )
|
||||
if( locked || !jt->IsLineCorner( aFollowLockedSegments ) || aPos < 0 || aPos == aLimit )
|
||||
break;
|
||||
|
||||
aCurrent = jt->NextSegment( aCurrent );
|
||||
aCurrent = jt->NextSegment( aCurrent, aFollowLockedSegments );
|
||||
|
||||
prevReversed = ( aCurrent && jt->Pos() == aCurrent->Anchor( aScanDirection ) );
|
||||
}
|
||||
|
@ -944,7 +945,7 @@ void NODE::followLine( LINKED_ITEM* aCurrent, bool aScanDirection, int& aPos, in
|
|||
|
||||
|
||||
const LINE NODE::AssembleLine( LINKED_ITEM* aSeg, int* aOriginSegmentIndex,
|
||||
bool aStopAtLockedJoints )
|
||||
bool aStopAtLockedJoints, bool aFollowLockedSegments )
|
||||
{
|
||||
const int MaxVerts = 1024 * 16;
|
||||
|
||||
|
@ -964,12 +965,12 @@ const LINE NODE::AssembleLine( LINKED_ITEM* aSeg, int* aOriginSegmentIndex,
|
|||
pl.SetOwner( this );
|
||||
|
||||
followLine( aSeg, false, i_start, MaxVerts, corners.data(), segs.data(), arcReversed.data(),
|
||||
guardHit, aStopAtLockedJoints );
|
||||
guardHit, aStopAtLockedJoints, aFollowLockedSegments );
|
||||
|
||||
if( !guardHit )
|
||||
{
|
||||
followLine( aSeg, true, i_end, MaxVerts, corners.data(), segs.data(), arcReversed.data(),
|
||||
guardHit, aStopAtLockedJoints );
|
||||
guardHit, aStopAtLockedJoints, aFollowLockedSegments );
|
||||
}
|
||||
|
||||
int n = 0;
|
||||
|
|
|
@ -304,10 +304,14 @@ public:
|
|||
*
|
||||
* @param aSeg the initial segment.
|
||||
* @param aOriginSegmentIndex index of aSeg in the resulting line.
|
||||
* @param aStopAtLockedJoints will terminate the line at the first locked joint encountered
|
||||
* @param aFollowLockedSegments will consider a joint between a locked segment and an unlocked
|
||||
* segment of the same width as a trivial joint.
|
||||
* @return the line
|
||||
*/
|
||||
const LINE AssembleLine( LINKED_ITEM* aSeg, int* aOriginSegmentIndex = nullptr,
|
||||
bool aStopAtLockedJoints = false );
|
||||
bool aStopAtLockedJoints = false,
|
||||
bool aFollowLockedSegments = false );
|
||||
|
||||
///< Print the contents and joints structure.
|
||||
void Dump( bool aLong = false );
|
||||
|
@ -432,7 +436,7 @@ private:
|
|||
///< Scan the joint map, forming a line starting from segment (current).
|
||||
void followLine( LINKED_ITEM* aCurrent, bool aScanDirection, int& aPos, int aLimit,
|
||||
VECTOR2I* aCorners, LINKED_ITEM** aSegments, bool* aArcReversed,
|
||||
bool& aGuardHit, bool aStopAtLockedJoints );
|
||||
bool& aGuardHit, bool aStopAtLockedJoints, bool aFollowLockedSegments );
|
||||
|
||||
private:
|
||||
struct DEFAULT_OBSTACLE_VISITOR;
|
||||
|
|
|
@ -247,7 +247,8 @@ bool TOPOLOGY::followTrivialPath( LINE* aLine, bool aLeft, ITEM_SET& aSet,
|
|||
|
||||
|
||||
const ITEM_SET TOPOLOGY::AssembleTrivialPath( ITEM* aStart,
|
||||
std::pair<JOINT*, JOINT*>* aTerminalJoints )
|
||||
std::pair<JOINT*, JOINT*>* aTerminalJoints,
|
||||
bool aFollowLockedSegments )
|
||||
{
|
||||
ITEM_SET path;
|
||||
std::set<ITEM*> visited;
|
||||
|
@ -278,7 +279,9 @@ const ITEM_SET TOPOLOGY::AssembleTrivialPath( ITEM* aStart,
|
|||
if( !seg )
|
||||
return ITEM_SET();
|
||||
|
||||
LINE l = m_world->AssembleLine( seg );
|
||||
// Assemble a line following through locked segments
|
||||
// TODO: consider if we want to allow tuning lines with different widths in the future
|
||||
LINE l = m_world->AssembleLine( seg, nullptr, false, true );
|
||||
|
||||
path.Add( l );
|
||||
|
||||
|
@ -301,7 +304,7 @@ const ITEM_SET TOPOLOGY::AssembleTrivialPath( ITEM* aStart,
|
|||
const ITEM_SET TOPOLOGY::AssembleTuningPath( ITEM* aStart, SOLID** aStartPad, SOLID** aEndPad )
|
||||
{
|
||||
std::pair<JOINT*, JOINT*> joints;
|
||||
ITEM_SET initialPath = AssembleTrivialPath( aStart, &joints );
|
||||
ITEM_SET initialPath = AssembleTrivialPath( aStart, &joints, true );
|
||||
|
||||
PAD* padA = nullptr;
|
||||
PAD* padB = nullptr;
|
||||
|
|
|
@ -61,10 +61,12 @@ public:
|
|||
*
|
||||
* @param aStart is the item to assemble from.
|
||||
* @param aTerminalJoints will be filled with the start and end points of the assembled path.
|
||||
* @param aFollowLockedSegments if true will assemble a path including locked segments
|
||||
* @return a set of items in the path.
|
||||
*/
|
||||
const ITEM_SET AssembleTrivialPath( ITEM* aStart,
|
||||
std::pair<JOINT*, JOINT*>* aTerminalJoints = nullptr );
|
||||
std::pair<JOINT*, JOINT*>* aTerminalJoints = nullptr,
|
||||
bool aFollowLockedSegments = false );
|
||||
|
||||
/**
|
||||
* Like AssembleTrivialPath, but follows the track length algorithm, which discards segments
|
||||
|
|
Loading…
Reference in New Issue