PNS: Fix loop removal, make walkaround less broken for arcs
This commit is contained in:
parent
aebb571dc9
commit
8901e71fc8
|
@ -90,9 +90,20 @@ public:
|
||||||
DIRECTION_45( const SEG& aSeg, bool a90 = false ) :
|
DIRECTION_45( const SEG& aSeg, bool a90 = false ) :
|
||||||
m_90deg( a90 )
|
m_90deg( a90 )
|
||||||
{
|
{
|
||||||
|
|
||||||
construct_( aSeg.B - aSeg.A );
|
construct_( aSeg.B - aSeg.A );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a DIRECTION_45 from the endpoints of a given arc
|
||||||
|
* @param aArc will be translated into the closest DIRECTION_45
|
||||||
|
*/
|
||||||
|
DIRECTION_45( const SHAPE_ARC& aArc, bool a90 = false ) :
|
||||||
|
m_90deg( a90 )
|
||||||
|
{
|
||||||
|
construct_( aArc.GetP1() - aArc.GetP0() );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function Format()
|
* Function Format()
|
||||||
* Formats the direction in a human readable word.
|
* Formats the direction in a human readable word.
|
||||||
|
|
|
@ -232,6 +232,13 @@ public:
|
||||||
return std::max( 0, c );
|
return std::max( 0, c );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of shapes (line segments or arcs) in this line chain.
|
||||||
|
* This is kind of like SegmentCount() but will only count arcs as 1 segment
|
||||||
|
* @return ArcCount() + the number of non-arc segments
|
||||||
|
*/
|
||||||
|
int ShapeCount() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function PointCount()
|
* Function PointCount()
|
||||||
*
|
*
|
||||||
|
@ -283,6 +290,22 @@ public:
|
||||||
const_cast<VECTOR2I&>( m_points[aIndex + 1] ), aIndex );
|
const_cast<VECTOR2I&>( m_points[aIndex + 1] ), aIndex );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the vertex index of the next shape in the chain, or -1 if aPoint is in the last shape
|
||||||
|
* If aPoint is the start of a segment, this will be ( aPoint + 1 ).
|
||||||
|
* If aPoint is part of an arc, this will be the index of the start of the next shape after the
|
||||||
|
* arc, in other words, the last point of the arc.
|
||||||
|
* @param aPointIndex is a vertex in the chain
|
||||||
|
* @param aForwards is true if the next shape is desired, false for previous shape
|
||||||
|
* @return the vertex index of the start of the next shape after aPoint's shape
|
||||||
|
*/
|
||||||
|
int NextShape( int aPointIndex, bool aForwards = true ) const;
|
||||||
|
|
||||||
|
int PrevShape( int aPointIndex ) const
|
||||||
|
{
|
||||||
|
return NextShape( aPointIndex, false );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Accessor Function to move a point to a specific location
|
* Accessor Function to move a point to a specific location
|
||||||
* @param aIndex Index (wrapping) of the point to move
|
* @param aIndex Index (wrapping) of the point to move
|
||||||
|
@ -489,6 +512,14 @@ public:
|
||||||
Remove( aIndex, aIndex );
|
Remove( aIndex, aIndex );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the shape at the given index from the line chain.
|
||||||
|
* If the given index is inside an arc, the entire arc will be removed.
|
||||||
|
* Otherwise this is equivalent to Remove( aPointIndex ).
|
||||||
|
* @param aPointIndex is the index of the point to remove
|
||||||
|
*/
|
||||||
|
void RemoveShape( int aPointIndex );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function Split()
|
* Function Split()
|
||||||
*
|
*
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include <geometry/direction45.h>
|
#include <geometry/direction45.h>
|
||||||
|
|
||||||
|
|
||||||
const SHAPE_LINE_CHAIN DIRECTION_45::BuildInitialTrace( const VECTOR2I& aP0, const VECTOR2I& aP1,
|
const SHAPE_LINE_CHAIN DIRECTION_45::BuildInitialTrace( const VECTOR2I& aP0, const VECTOR2I& aP1,
|
||||||
bool aStartDiagonal, bool aFillet ) const
|
bool aStartDiagonal, bool aFillet ) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -420,6 +420,104 @@ int SHAPE_LINE_CHAIN::FindSegment( const VECTOR2I& aP ) const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int SHAPE_LINE_CHAIN::ShapeCount() const
|
||||||
|
{
|
||||||
|
if( m_points.empty() )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int numPoints = static_cast<int>( m_shapes.size() );
|
||||||
|
int numShapes = 0;
|
||||||
|
int arcIdx = -1;
|
||||||
|
|
||||||
|
for( int i = 0; i < m_points.size() - 1; i++ )
|
||||||
|
{
|
||||||
|
if( m_shapes[i] == SHAPE_IS_PT )
|
||||||
|
{
|
||||||
|
numShapes++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
arcIdx = m_shapes[i];
|
||||||
|
numShapes++;
|
||||||
|
|
||||||
|
// Now skip the rest of the arc
|
||||||
|
while( i < numPoints && m_shapes[i] == arcIdx )
|
||||||
|
i++;
|
||||||
|
|
||||||
|
// Is there another arc right after? Add the "hidden" segment
|
||||||
|
if( i < numPoints &&
|
||||||
|
m_shapes[i] != SHAPE_IS_PT &&
|
||||||
|
m_shapes[i] != arcIdx &&
|
||||||
|
m_points[i] != m_points[i - 1] )
|
||||||
|
{
|
||||||
|
numShapes++;
|
||||||
|
}
|
||||||
|
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return numShapes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int SHAPE_LINE_CHAIN::NextShape( int aPointIndex, bool aForwards ) const
|
||||||
|
{
|
||||||
|
if( aPointIndex < 0 )
|
||||||
|
aPointIndex += PointCount();
|
||||||
|
|
||||||
|
// First or last point?
|
||||||
|
if( ( aForwards && aPointIndex == PointCount() - 1 ) ||
|
||||||
|
( !aForwards && aPointIndex == 0 ) )
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int delta = aForwards ? 1 : -1;
|
||||||
|
|
||||||
|
if( m_shapes[aPointIndex] == SHAPE_IS_PT )
|
||||||
|
return aPointIndex + delta;
|
||||||
|
|
||||||
|
int arcIndex = m_shapes[aPointIndex];
|
||||||
|
int arcStart = aPointIndex;
|
||||||
|
|
||||||
|
while( aPointIndex < static_cast<int>( m_shapes.size() ) && m_shapes[aPointIndex] == arcIndex )
|
||||||
|
aPointIndex += delta;
|
||||||
|
|
||||||
|
// We want the last vertex of the arc if the initial point was the start of one
|
||||||
|
// Well-formed arcs should generate more than one point to travel above
|
||||||
|
if( aPointIndex - arcStart > 1 )
|
||||||
|
aPointIndex -= delta;
|
||||||
|
|
||||||
|
return aPointIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SHAPE_LINE_CHAIN::RemoveShape( int aPointIndex )
|
||||||
|
{
|
||||||
|
if( aPointIndex < 0 )
|
||||||
|
aPointIndex += PointCount();
|
||||||
|
|
||||||
|
if( m_shapes[aPointIndex] == SHAPE_IS_PT )
|
||||||
|
{
|
||||||
|
Remove( aPointIndex );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int start = aPointIndex;
|
||||||
|
int end = aPointIndex;
|
||||||
|
int arcIdx = m_shapes[aPointIndex];
|
||||||
|
|
||||||
|
while( start >= 0 && m_shapes[start] == arcIdx )
|
||||||
|
start--;
|
||||||
|
|
||||||
|
while( end < static_cast<int>( m_shapes.size() ) - 1 && m_shapes[end] == arcIdx )
|
||||||
|
end++;
|
||||||
|
|
||||||
|
Remove( start, end );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const SHAPE_LINE_CHAIN SHAPE_LINE_CHAIN::Slice( int aStartIndex, int aEndIndex ) const
|
const SHAPE_LINE_CHAIN SHAPE_LINE_CHAIN::Slice( int aStartIndex, int aEndIndex ) const
|
||||||
{
|
{
|
||||||
SHAPE_LINE_CHAIN rv;
|
SHAPE_LINE_CHAIN rv;
|
||||||
|
@ -431,7 +529,33 @@ const SHAPE_LINE_CHAIN SHAPE_LINE_CHAIN::Slice( int aStartIndex, int aEndIndex )
|
||||||
aStartIndex += PointCount();
|
aStartIndex += PointCount();
|
||||||
|
|
||||||
for( int i = aStartIndex; i <= aEndIndex && static_cast<size_t>( i ) < m_points.size(); i++ )
|
for( int i = aStartIndex; i <= aEndIndex && static_cast<size_t>( i ) < m_points.size(); i++ )
|
||||||
|
#if 0
|
||||||
|
{
|
||||||
|
if( m_shapes[i] != SHAPE_IS_PT )
|
||||||
|
{
|
||||||
|
int arcIdx = m_shapes[i];
|
||||||
|
|
||||||
|
// wxASSERT_MSG( i == 0 || ( m_shapes[i - 1] != arcIdx ),
|
||||||
|
// "SHAPE_LINE_CHAIN::Slice in the middle of an arc!" );
|
||||||
|
|
||||||
|
rv.Append( m_arcs[arcIdx] );
|
||||||
|
|
||||||
|
while( m_shapes[i] == arcIdx && static_cast<size_t>( i ) < m_shapes.size() )
|
||||||
|
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!" );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
rv.Append( m_points[i] );
|
rv.Append( m_points[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
rv.Append( m_points[i] );
|
||||||
|
#endif
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1331,8 +1331,6 @@ void PNS_KICAD_IFACE_BASE::SetDebugDecorator( PNS::DEBUG_DECORATOR *aDec )
|
||||||
|
|
||||||
void PNS_KICAD_IFACE::DisplayItem( const PNS::ITEM* aItem, int aClearance, bool aEdit )
|
void PNS_KICAD_IFACE::DisplayItem( const PNS::ITEM* aItem, int aClearance, bool aEdit )
|
||||||
{
|
{
|
||||||
wxLogTrace( "PNS", "DisplayItem %p", aItem );
|
|
||||||
|
|
||||||
ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, m_view );
|
ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, m_view );
|
||||||
|
|
||||||
if( aClearance >= 0 )
|
if( aClearance >= 0 )
|
||||||
|
|
|
@ -868,20 +868,67 @@ int LINE::Rank() const
|
||||||
|
|
||||||
void LINE::ClipVertexRange( int aStart, int aEnd )
|
void LINE::ClipVertexRange( int aStart, int aEnd )
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* We need to figure out which joints to keep after the clip operation, because arcs will have
|
||||||
|
* multiple vertices. It is assumed that anything calling this method will have determined the
|
||||||
|
* vertex range to clip based on joints, meaning we will never clip in the middle of an arc.
|
||||||
|
* Clipping in the middle of an arc would break this and various other things...
|
||||||
|
*/
|
||||||
|
int firstLink = 0;
|
||||||
|
int lastLink = std::max( 0, static_cast<int>( m_links.size() ) - 1 );
|
||||||
|
int arcIdx = -1;
|
||||||
|
int linkIdx = 0;
|
||||||
|
|
||||||
|
const std::vector<long>& shapes = m_line.CShapes();
|
||||||
|
int numPoints = static_cast<int>( shapes.size() );
|
||||||
|
|
||||||
|
for( int i = 0; i < m_line.PointCount(); i++ )
|
||||||
|
{
|
||||||
|
if( i <= aStart )
|
||||||
|
firstLink = linkIdx;
|
||||||
|
|
||||||
|
if( shapes[i] >= 0 )
|
||||||
|
{
|
||||||
|
// Account for "hidden segments" between two arcs
|
||||||
|
if( i > aStart && ( shapes[i - 1] >= 0 ) && ( shapes[i - 1] != shapes[i] ) )
|
||||||
|
linkIdx++;
|
||||||
|
|
||||||
|
arcIdx = shapes[i];
|
||||||
|
|
||||||
|
// Skip over the rest of the arc vertices
|
||||||
|
while( i < numPoints && shapes[i] == arcIdx )
|
||||||
|
i++;
|
||||||
|
|
||||||
|
// Back up two vertices to restart at the segment coincident with the end of the arc
|
||||||
|
i -= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( i >= aEnd - 1 || linkIdx >= lastLink )
|
||||||
|
{
|
||||||
|
lastLink = linkIdx;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
linkIdx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxASSERT( lastLink >= firstLink );
|
||||||
|
|
||||||
m_line = m_line.Slice( aStart, aEnd );
|
m_line = m_line.Slice( aStart, aEnd );
|
||||||
|
|
||||||
if( IsLinked() ) {
|
if( IsLinked() )
|
||||||
assert( m_links.size() < INT_MAX );
|
{
|
||||||
assert( (int) m_links.size() >= (aEnd - aStart) );
|
wxASSERT( m_links.size() < INT_MAX );
|
||||||
|
wxASSERT( static_cast<int>( m_links.size() ) >= ( lastLink - firstLink ) );
|
||||||
|
|
||||||
// Note: The range includes aEnd, but we have n-1 segments.
|
// Note: The range includes aEnd, but we have n-1 segments.
|
||||||
std::rotate(
|
std::rotate(
|
||||||
m_links.begin(),
|
m_links.begin(),
|
||||||
m_links.begin() + aStart,
|
m_links.begin() + firstLink,
|
||||||
m_links.begin() + aEnd
|
m_links.begin() + lastLink
|
||||||
);
|
);
|
||||||
|
|
||||||
m_links.resize( aEnd - aStart );
|
m_links.resize( lastLink - firstLink + 1 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -147,6 +147,7 @@ public:
|
||||||
int SegmentCount() const { return m_line.SegmentCount(); }
|
int SegmentCount() const { return m_line.SegmentCount(); }
|
||||||
int PointCount() const { return m_line.PointCount(); }
|
int PointCount() const { return m_line.PointCount(); }
|
||||||
int ArcCount() const { return m_line.ArcCount(); }
|
int ArcCount() const { return m_line.ArcCount(); }
|
||||||
|
int ShapeCount() const { return m_line.ShapeCount(); }
|
||||||
|
|
||||||
///> Returns the aIdx-th point of the line
|
///> Returns the aIdx-th point of the line
|
||||||
const VECTOR2I& CPoint( int aIdx ) const { return m_line.CPoint( aIdx ); }
|
const VECTOR2I& CPoint( int aIdx ) const { return m_line.CPoint( aIdx ); }
|
||||||
|
|
|
@ -189,8 +189,24 @@ bool LINE_PLACER::handlePullback()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIRECTION_45 first_head( head.CSegment( 0 ) );
|
DIRECTION_45 first_head, last_tail;
|
||||||
DIRECTION_45 last_tail( tail.CSegment( -1 ) );
|
|
||||||
|
const std::vector<ssize_t>& headShapes = head.CShapes();
|
||||||
|
const std::vector<ssize_t>& tailShapes = tail.CShapes();
|
||||||
|
|
||||||
|
wxASSERT( tail.PointCount() >= 2 );
|
||||||
|
if( headShapes[0] == -1 )
|
||||||
|
first_head = DIRECTION_45( head.CSegment( 0 ) );
|
||||||
|
else
|
||||||
|
first_head = DIRECTION_45( head.CArcs()[ headShapes[0] ] );
|
||||||
|
|
||||||
|
int lastSegIdx = tail.PointCount() - 2;
|
||||||
|
|
||||||
|
if( tailShapes[lastSegIdx] == -1 )
|
||||||
|
last_tail = DIRECTION_45( tail.CSegment( lastSegIdx ) );
|
||||||
|
else
|
||||||
|
last_tail = DIRECTION_45( tail.CArcs()[tailShapes[lastSegIdx]] );
|
||||||
|
|
||||||
DIRECTION_45::AngleType angle = first_head.Angle( last_tail );
|
DIRECTION_45::AngleType angle = first_head.Angle( last_tail );
|
||||||
|
|
||||||
// case 1: we have a defined routing direction, and the currently computed
|
// case 1: we have a defined routing direction, and the currently computed
|
||||||
|
@ -204,9 +220,20 @@ bool LINE_PLACER::handlePullback()
|
||||||
|
|
||||||
if( pullback_1 || pullback_2 )
|
if( pullback_1 || pullback_2 )
|
||||||
{
|
{
|
||||||
const SEG last = tail.CSegment( -1 );
|
lastSegIdx = tail.PrevShape( -1 );
|
||||||
m_direction = DIRECTION_45( last );
|
|
||||||
m_p_start = last.A;
|
if( tailShapes[lastSegIdx] == -1 )
|
||||||
|
{
|
||||||
|
const SEG& seg = tail.CSegment( lastSegIdx );
|
||||||
|
m_direction = DIRECTION_45( seg );
|
||||||
|
m_p_start = seg.A;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const SHAPE_ARC& arc = tail.CArcs()[tailShapes[lastSegIdx]];
|
||||||
|
m_direction = DIRECTION_45( arc );
|
||||||
|
m_p_start = arc.GetP0();
|
||||||
|
}
|
||||||
|
|
||||||
wxLogTrace( "PNS", "Placer: pullback triggered [%d] [%s %s]",
|
wxLogTrace( "PNS", "Placer: pullback triggered [%d] [%s %s]",
|
||||||
n, last_tail.Format().c_str(), first_head.Format().c_str() );
|
n, last_tail.Format().c_str(), first_head.Format().c_str() );
|
||||||
|
@ -217,7 +244,7 @@ bool LINE_PLACER::handlePullback()
|
||||||
if( n < 2 )
|
if( n < 2 )
|
||||||
tail.Clear(); // don't leave a single-point tail
|
tail.Clear(); // don't leave a single-point tail
|
||||||
else
|
else
|
||||||
tail.Remove( -1, -1 );
|
tail.RemoveShape( -1 );
|
||||||
|
|
||||||
if( !tail.SegmentCount() )
|
if( !tail.SegmentCount() )
|
||||||
m_direction = m_initial_direction;
|
m_direction = m_initial_direction;
|
||||||
|
@ -294,15 +321,6 @@ bool LINE_PLACER::reduceTail( const VECTOR2I& aEnd )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool LINE_PLACER::checkObtusity( const SEG& aA, const SEG& aB ) const
|
|
||||||
{
|
|
||||||
const DIRECTION_45 dir_a( aA );
|
|
||||||
const DIRECTION_45 dir_b( aB );
|
|
||||||
|
|
||||||
return dir_a.IsObtuse( dir_b ) || dir_a == dir_b;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool LINE_PLACER::mergeHead()
|
bool LINE_PLACER::mergeHead()
|
||||||
{
|
{
|
||||||
SHAPE_LINE_CHAIN& head = m_head.Line();
|
SHAPE_LINE_CHAIN& head = m_head.Line();
|
||||||
|
@ -315,8 +333,8 @@ bool LINE_PLACER::mergeHead()
|
||||||
head.Simplify();
|
head.Simplify();
|
||||||
tail.Simplify();
|
tail.Simplify();
|
||||||
|
|
||||||
int n_head = head.SegmentCount();
|
int n_head = head.ShapeCount();
|
||||||
int n_tail = tail.SegmentCount();
|
int n_tail = tail.ShapeCount();
|
||||||
|
|
||||||
if( n_head < 3 )
|
if( n_head < 3 )
|
||||||
{
|
{
|
||||||
|
@ -335,25 +353,41 @@ bool LINE_PLACER::mergeHead()
|
||||||
|
|
||||||
DIRECTION_45 dir_tail, dir_head;
|
DIRECTION_45 dir_tail, dir_head;
|
||||||
|
|
||||||
|
const std::vector<ssize_t>& headShapes = head.CShapes();
|
||||||
|
const std::vector<ssize_t>& tailShapes = tail.CShapes();
|
||||||
|
|
||||||
|
if( headShapes[0] == -1 )
|
||||||
dir_head = DIRECTION_45( head.CSegment( 0 ) );
|
dir_head = DIRECTION_45( head.CSegment( 0 ) );
|
||||||
|
else
|
||||||
|
dir_head = DIRECTION_45( head.CArcs()[ headShapes[0] ] );
|
||||||
|
|
||||||
if( n_tail )
|
if( n_tail )
|
||||||
{
|
{
|
||||||
|
wxASSERT( tail.PointCount() >= 2 );
|
||||||
|
int lastSegIdx = tail.PointCount() - 2;
|
||||||
|
|
||||||
|
if( tailShapes[lastSegIdx] == -1 )
|
||||||
dir_tail = DIRECTION_45( tail.CSegment( -1 ) );
|
dir_tail = DIRECTION_45( tail.CSegment( -1 ) );
|
||||||
|
else
|
||||||
|
dir_tail = DIRECTION_45( tail.CArcs()[ tailShapes[lastSegIdx] ] );
|
||||||
|
|
||||||
if( dir_head.Angle( dir_tail ) & ForbiddenAngles )
|
if( dir_head.Angle( dir_tail ) & ForbiddenAngles )
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
tail.Append( head );
|
tail.Append( head );
|
||||||
tail.Remove( -1 );
|
|
||||||
|
|
||||||
tail.Simplify();
|
tail.Simplify();
|
||||||
|
|
||||||
SEG last = tail.CSegment( -1 );
|
SEG last = tail.CSegment( -1 );
|
||||||
|
|
||||||
m_p_start = last.B;
|
m_p_start = last.B;
|
||||||
m_direction = DIRECTION_45( last ).Right();
|
|
||||||
|
int lastSegIdx = tail.PointCount() - 2;
|
||||||
|
|
||||||
|
if( tailShapes[lastSegIdx] == -1 )
|
||||||
|
m_direction = DIRECTION_45( tail.CSegment( -1 ) );
|
||||||
|
else
|
||||||
|
m_direction = DIRECTION_45( tail.CArcs()[ tailShapes[lastSegIdx] ] );
|
||||||
|
|
||||||
head.Remove( 0, -1 );
|
head.Remove( 0, -1 );
|
||||||
|
|
||||||
|
@ -646,7 +680,7 @@ bool LINE_PLACER::optimizeTailHeadTransition()
|
||||||
|
|
||||||
int threshold = std::min( tail.PointCount(), tailLookbackSegments + 1 );
|
int threshold = std::min( tail.PointCount(), tailLookbackSegments + 1 );
|
||||||
|
|
||||||
if( tail.SegmentCount() < 3 )
|
if( tail.ShapeCount() < 3 )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// assemble TailLookbackSegments tail segments with the current head
|
// assemble TailLookbackSegments tail segments with the current head
|
||||||
|
@ -691,10 +725,10 @@ void LINE_PLACER::routeStep( const VECTOR2I& aP )
|
||||||
|
|
||||||
LINE new_head;
|
LINE new_head;
|
||||||
|
|
||||||
wxLogTrace( "PNS", "INIT-DIR: %s head: %d, tail: %d segs",
|
wxLogTrace( "PNS", "routeStep: direction: %s head: %d, tail: %d shapes",
|
||||||
m_initial_direction.Format().c_str(),
|
m_direction.Format().c_str(),
|
||||||
m_head.SegmentCount(),
|
m_head.ShapeCount(),
|
||||||
m_tail.SegmentCount() );
|
m_tail.ShapeCount() );
|
||||||
|
|
||||||
for( i = 0; i < n_iter; i++ )
|
for( i = 0; i < n_iter; i++ )
|
||||||
{
|
{
|
||||||
|
@ -1064,6 +1098,7 @@ bool LINE_PLACER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinis
|
||||||
if( !fixAll && l.ArcCount() )
|
if( !fixAll && l.ArcCount() )
|
||||||
fixAll = true;
|
fixAll = true;
|
||||||
|
|
||||||
|
// TODO: lastDirSeg will be calculated incorrectly if we end on an arc
|
||||||
SEG lastDirSeg = ( !fixAll && l.SegmentCount() > 1 ) ? l.CSegment( -2 ) : l.CSegment( -1 );
|
SEG lastDirSeg = ( !fixAll && l.SegmentCount() > 1 ) ? l.CSegment( -2 ) : l.CSegment( -1 );
|
||||||
lastDirSeg.A.y = -lastDirSeg.A.y;
|
lastDirSeg.A.y = -lastDirSeg.A.y;
|
||||||
lastDirSeg.B.y = -lastDirSeg.B.y;
|
lastDirSeg.B.y = -lastDirSeg.B.y;
|
||||||
|
@ -1118,9 +1153,7 @@ bool LINE_PLACER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinis
|
||||||
setInitialDirection( d_last );
|
setInitialDirection( d_last );
|
||||||
m_currentStart = ( m_placingVia || fixAll ) ? p_last : p_pre_last;
|
m_currentStart = ( m_placingVia || fixAll ) ? p_last : p_pre_last;
|
||||||
|
|
||||||
NODE* commit = fixAll ? m_lastNode : m_currentNode;
|
m_fixedTail.AddStage( m_p_start, m_currentLayer, m_placingVia, m_direction, m_currentNode );
|
||||||
|
|
||||||
m_fixedTail.AddStage( m_p_start, m_currentLayer, m_placingVia, m_direction, commit );
|
|
||||||
|
|
||||||
m_startItem = NULL;
|
m_startItem = NULL;
|
||||||
m_placingVia = false;
|
m_placingVia = false;
|
||||||
|
@ -1323,6 +1356,9 @@ bool LINE_PLACER::buildInitialLine( const VECTOR2I& aP, LINE& aHead )
|
||||||
SHAPE_LINE_CHAIN l;
|
SHAPE_LINE_CHAIN l;
|
||||||
DIRECTION_45 guessedDir = m_postureSolver.GetPosture( aP );
|
DIRECTION_45 guessedDir = m_postureSolver.GetPosture( aP );
|
||||||
|
|
||||||
|
wxLogTrace( "PNS", "buildInitialLine: m_direction %s, guessedDir %s, tail points %d",
|
||||||
|
m_direction.Format(), guessedDir.Format(), m_tail.PointCount() );
|
||||||
|
|
||||||
// Rounded corners don't make sense when routing orthogonally (single track at a time)
|
// Rounded corners don't make sense when routing orthogonally (single track at a time)
|
||||||
bool fillet = !m_orthoMode && Settings().GetCornerMode() == CORNER_MODE::ROUNDED_45;
|
bool fillet = !m_orthoMode && Settings().GetCornerMode() == CORNER_MODE::ROUNDED_45;
|
||||||
|
|
||||||
|
|
|
@ -328,15 +328,6 @@ private:
|
||||||
*/
|
*/
|
||||||
void simplifyNewLine( NODE* aNode, SEGMENT* aLatest );
|
void simplifyNewLine( NODE* aNode, SEGMENT* aLatest );
|
||||||
|
|
||||||
/**
|
|
||||||
* Function checkObtusity()
|
|
||||||
*
|
|
||||||
* Helper function, checking if segments a and b form an obtuse angle
|
|
||||||
* (in 45-degree regime).
|
|
||||||
* @return true, if angle (aA, aB) is obtuse
|
|
||||||
*/
|
|
||||||
bool checkObtusity( const SEG& aA, const SEG& aB ) const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function handleSelfIntersections()
|
* Function handleSelfIntersections()
|
||||||
*
|
*
|
||||||
|
|
|
@ -48,7 +48,6 @@ static std::unordered_set<NODE*> allocNodes;
|
||||||
|
|
||||||
NODE::NODE()
|
NODE::NODE()
|
||||||
{
|
{
|
||||||
wxLogTrace( "PNS", "NODE::create %p", this );
|
|
||||||
m_depth = 0;
|
m_depth = 0;
|
||||||
m_root = this;
|
m_root = this;
|
||||||
m_parent = NULL;
|
m_parent = NULL;
|
||||||
|
@ -64,8 +63,6 @@ NODE::NODE()
|
||||||
|
|
||||||
NODE::~NODE()
|
NODE::~NODE()
|
||||||
{
|
{
|
||||||
wxLogTrace( "PNS", "NODE::delete %p", this );
|
|
||||||
|
|
||||||
if( !m_children.empty() )
|
if( !m_children.empty() )
|
||||||
{
|
{
|
||||||
wxLogTrace( "PNS", "attempting to free a node that has kids." );
|
wxLogTrace( "PNS", "attempting to free a node that has kids." );
|
||||||
|
@ -127,8 +124,6 @@ NODE* NODE::Branch()
|
||||||
{
|
{
|
||||||
NODE* child = new NODE;
|
NODE* child = new NODE;
|
||||||
|
|
||||||
wxLogTrace( "PNS", "NODE::branch %p (parent %p)", child, this );
|
|
||||||
|
|
||||||
m_children.insert( child );
|
m_children.insert( child );
|
||||||
|
|
||||||
child->m_depth = m_depth + 1;
|
child->m_depth = m_depth + 1;
|
||||||
|
@ -150,10 +145,12 @@ NODE* NODE::Branch()
|
||||||
child->m_override = m_override;
|
child->m_override = m_override;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
wxLogTrace( "PNS", "%d items, %d joints, %d overrides",
|
wxLogTrace( "PNS", "%d items, %d joints, %d overrides",
|
||||||
child->m_index->Size(),
|
child->m_index->Size(),
|
||||||
(int) child->m_joints.size(),
|
(int) child->m_joints.size(),
|
||||||
(int) child->m_override.size() );
|
(int) child->m_override.size() );
|
||||||
|
#endif
|
||||||
|
|
||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
|
@ -932,25 +929,37 @@ const LINE NODE::AssembleLine( LINKED_ITEM* aSeg, int* aOriginSegmentIndex,
|
||||||
for( int i = i_start + 1; i < i_end; i++ )
|
for( int i = i_start + 1; i < i_end; i++ )
|
||||||
{
|
{
|
||||||
const VECTOR2I& p = corners[i];
|
const VECTOR2I& p = corners[i];
|
||||||
|
LINKED_ITEM* li = segs[i];
|
||||||
|
|
||||||
|
if( !li || li->Kind() != ITEM::ARC_T )
|
||||||
pl.Line().Append( p );
|
pl.Line().Append( p );
|
||||||
|
|
||||||
if( segs[i] && prev_seg != segs[i] )
|
if( li && prev_seg != li )
|
||||||
{
|
{
|
||||||
pl.Link( segs[i] );
|
if( li->Kind() == ITEM::ARC_T )
|
||||||
|
{
|
||||||
|
const ARC* arc = static_cast<const ARC*>( li );
|
||||||
|
const SHAPE_ARC* sa = static_cast<const SHAPE_ARC*>( arc->Shape() );
|
||||||
|
pl.Line().Append( *sa );
|
||||||
|
}
|
||||||
|
|
||||||
|
pl.Link( li );
|
||||||
|
|
||||||
// latter condition to avoid loops
|
// latter condition to avoid loops
|
||||||
if( segs[i] == aSeg && aOriginSegmentIndex && !originSet )
|
if( li == aSeg && aOriginSegmentIndex && !originSet )
|
||||||
{
|
{
|
||||||
*aOriginSegmentIndex = n;
|
*aOriginSegmentIndex = n;
|
||||||
originSet = true;
|
originSet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
|
|
||||||
prev_seg = segs[i];
|
prev_seg = li;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pl.Line().Simplify();
|
||||||
|
|
||||||
assert( pl.SegmentCount() != 0 );
|
assert( pl.SegmentCount() != 0 );
|
||||||
|
|
||||||
return pl;
|
return pl;
|
||||||
|
|
|
@ -577,6 +577,7 @@ bool OPTIMIZER::Optimize( LINE* aLine, LINE* aResult )
|
||||||
aResult->ClearLinks();
|
aResult->ClearLinks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hasArcs = aLine->ArcCount();
|
||||||
bool rv = false;
|
bool rv = false;
|
||||||
|
|
||||||
if( m_effortLevel & PRESERVE_VERTEX )
|
if( m_effortLevel & PRESERVE_VERTEX )
|
||||||
|
@ -598,19 +599,23 @@ bool OPTIMIZER::Optimize( LINE* aLine, LINE* aResult )
|
||||||
AddConstraint( c );
|
AddConstraint( c );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( m_effortLevel & MERGE_SEGMENTS )
|
// TODO: Fix for arcs
|
||||||
|
if( !hasArcs && m_effortLevel & MERGE_SEGMENTS )
|
||||||
rv |= mergeFull( aResult );
|
rv |= mergeFull( aResult );
|
||||||
|
|
||||||
if( m_effortLevel & MERGE_OBTUSE )
|
// TODO: Fix for arcs
|
||||||
|
if( !hasArcs && m_effortLevel & MERGE_OBTUSE )
|
||||||
rv |= mergeObtuse( aResult );
|
rv |= mergeObtuse( aResult );
|
||||||
|
|
||||||
if( m_effortLevel & MERGE_COLINEAR )
|
if( m_effortLevel & MERGE_COLINEAR )
|
||||||
rv |= mergeColinear( aResult );
|
rv |= mergeColinear( aResult );
|
||||||
|
|
||||||
if( m_effortLevel & SMART_PADS )
|
// TODO: Fix for arcs
|
||||||
|
if( !hasArcs && m_effortLevel & SMART_PADS )
|
||||||
rv |= runSmartPads( aResult );
|
rv |= runSmartPads( aResult );
|
||||||
|
|
||||||
if( m_effortLevel & FANOUT_CLEANUP )
|
// TODO: Fix for arcs
|
||||||
|
if( !hasArcs && m_effortLevel & FANOUT_CLEANUP )
|
||||||
rv |= fanoutCleanup( aResult );
|
rv |= fanoutCleanup( aResult );
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
|
@ -1023,10 +1028,6 @@ bool OPTIMIZER::Optimize( LINE* aLine, int aEffortLevel, NODE* aWorld, const VEC
|
||||||
if( aEffortLevel & OPTIMIZER::PRESERVE_VERTEX )
|
if( aEffortLevel & OPTIMIZER::PRESERVE_VERTEX )
|
||||||
opt.SetPreserveVertex( aV );
|
opt.SetPreserveVertex( aV );
|
||||||
|
|
||||||
// TODO: fix optimizer for arcs
|
|
||||||
if( aLine->ArcCount() )
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return opt.Optimize( aLine );
|
return opt.Optimize( aLine );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue