Pcbnew: trace length calculations:

fix incorrect calculation when a small segment at the end of the track was inside a pad: it was not taken in account.
Fix also the len die values not always taken in account (references to pads at end of track not always stored)
This is a partial fix of bug 1628585.
This commit is contained in:
jean-pierre charras 2016-10-14 10:35:08 +02:00
parent 9fdcba8229
commit 038f8713ce
3 changed files with 95 additions and 39 deletions

View File

@ -2001,8 +2001,86 @@ TRACK* BOARD::MarkTrace( TRACK* aTrace, int* aCount,
if( firstTrack == NULL ) if( firstTrack == NULL )
return NULL; return NULL;
// First step: calculate the track length and find the pads (when exist)
// at each end of the trace.
double full_len = 0; double full_len = 0;
double lenPadToDie = 0; double lenPadToDie = 0;
// Because we have a track (a set of track segments between 2 nodes),
// only 2 pads (maximum) will be taken in account:
// that are on each end of the track, if any.
// keep trace of them, to know the die length and the track length ibside each pad.
D_PAD* s_pad = NULL; // the pad on one end of the trace
D_PAD* e_pad = NULL; // the pad on the other end of the trace
int dist_fromstart = INT_MAX;
int dist_fromend = INT_MAX;
for( TRACK* track = firstTrack; track; track = track->Next() )
{
if( !track->GetState( BUSY ) )
continue;
layer_set = track->GetLayerSet();
D_PAD * pad_on_start = GetPad( track->GetStart(), layer_set );
D_PAD * pad_on_end = GetPad( track->GetEnd(), layer_set );
// a segment fully inside a pad does not contribute to the track len
// (an other track end inside this pad will contribute to this lenght)
if( pad_on_start && ( pad_on_start == pad_on_end ) )
continue;
full_len += track->GetLength();
if( pad_on_start == NULL && pad_on_end == NULL )
// This most of time the case
continue;
// At this point, we can have one track end on a pad, or the 2 track ends on
// 2 different pads.
// We don't know what pad (s_pad or e_pad) must be used to store the
// start point and the end point of the track, so if a pad is already set,
// use the other
if( pad_on_start )
{
SEG segm( track->GetStart(), pad_on_start->GetPosition() );
int dist = segm.Length();
if( s_pad == NULL )
{
dist_fromstart = dist;
s_pad = pad_on_start;
}
else if( e_pad == NULL )
{
dist_fromend = dist;
e_pad = pad_on_start;
}
else // Should not occur, at least for basic pads
{
// wxLogMessage( "BOARD::MarkTrace: multiple pad_on_start" );
}
}
if( pad_on_end )
{
SEG segm( track->GetEnd(), pad_on_end->GetPosition() );
int dist = segm.Length();
if( s_pad == NULL )
{
dist_fromstart = dist;
s_pad = pad_on_end;
}
else if( e_pad == NULL )
{
dist_fromend = dist;
e_pad = pad_on_end;
}
else // Should not occur, at least for basic pads
{
// wxLogMessage( "BOARD::MarkTrace: multiple pad_on_end" );
}
}
}
if( aReorder ) if( aReorder )
{ {
@ -2025,25 +2103,6 @@ TRACK* BOARD::MarkTrace( TRACK* aTrace, int* aCount,
track->UnLink(); track->UnLink();
list->Insert( track, firstTrack->Next() ); list->Insert( track, firstTrack->Next() );
if( aTraceLength )
full_len += track->GetLength();
if( aPadToDieLength ) // Add now length die.
{
// In fact only 2 pads (maximum) will be taken in account:
// that are on each end of the track, if any
if( track->GetState( BEGIN_ONPAD ) )
{
D_PAD* pad = (D_PAD *) track->start;
lenPadToDie += (double) pad->GetPadToDieLength();
}
if( track->GetState( END_ONPAD ) )
{
D_PAD* pad = (D_PAD *) track->end;
lenPadToDie += (double) pad->GetPadToDieLength();
}
}
} }
} }
} }
@ -2057,28 +2116,24 @@ TRACK* BOARD::MarkTrace( TRACK* aTrace, int* aCount,
{ {
busy_count++; busy_count++;
track->SetState( BUSY, false ); track->SetState( BUSY, false );
full_len += track->GetLength();
// Add now length die.
// In fact only 2 pads (maximum) will be taken in account:
// that are on each end of the track, if any
if( track->GetState( BEGIN_ONPAD ) )
{
D_PAD* pad = (D_PAD *) track->start;
lenPadToDie += (double) pad->GetPadToDieLength();
}
if( track->GetState( END_ONPAD ) )
{
D_PAD* pad = (D_PAD *) track->end;
lenPadToDie += (double) pad->GetPadToDieLength();
}
} }
} }
DBG( printf( "%s: busy_count:%d\n", __func__, busy_count ); ) DBG( printf( "%s: busy_count:%d\n", __func__, busy_count ); )
} }
if( s_pad )
{
full_len += dist_fromstart;
lenPadToDie += (double) s_pad->GetPadToDieLength();
}
if( e_pad )
{
full_len += dist_fromend;
lenPadToDie += (double) e_pad->GetPadToDieLength();
}
if( aTraceLength ) if( aTraceLength )
*aTraceLength = full_len; *aTraceLength = full_len;

View File

@ -1289,12 +1289,12 @@ public:
* *
* @param aTrace The segment within a list of trace segments to test. * @param aTrace The segment within a list of trace segments to test.
* @param aCount A pointer to an integer where to return the number of * @param aCount A pointer to an integer where to return the number of
* marked segments. * marked segments (can be NULL).
* @param aTraceLength A pointer to an double where to return the length of the * @param aTraceLength A pointer to an double where to return the length of the
* trace. * trace (can be NULL).
* @param aInPackageLength A pointer to an double where to return the extra lengths inside * @param aInPackageLength A pointer to an double where to return the extra lengths inside
* integrated circuits from the pads connected to this track to the * integrated circuits from the pads connected to this track to the
* die (if any). * die (if any) (can be NULL).
* @param aReorder true for reorder the interesting segments (useful for * @param aReorder true for reorder the interesting segments (useful for
* track edition/deletion) in this case the flag BUSY is * track edition/deletion) in this case the flag BUSY is
* set (the user is responsible of flag clearing). False * set (the user is responsible of flag clearing). False
@ -1378,7 +1378,7 @@ public:
* segment start position if the return value is not NULL. * segment start position if the return value is not NULL.
* @param aSegment The trace segment to create the lock point on. * @param aSegment The trace segment to create the lock point on.
* @param aList The pick list to add the created items to. * @param aList The pick list to add the created items to.
* @return NULL if no new point was created or a pointer to a TRACK ojbect of the * @return NULL if no new point was created or a pointer to a TRACK object of the
* created segment. If \a aSegment points to a via the exact value of \a * created segment. If \a aSegment points to a via the exact value of \a
* aPosition and a pointer to the via are returned. * aPosition and a pointer to the via are returned.
*/ */

View File

@ -44,6 +44,7 @@
// Polygon calculations can use fast mode or force strickly simple polygons after calculations // Polygon calculations can use fast mode or force strickly simple polygons after calculations
// Forcing strickly simple polygons is time consuming, and we have not see issues in fast mode // Forcing strickly simple polygons is time consuming, and we have not see issues in fast mode
// so we use fast mode // so we use fast mode
// (choice is SHAPE_POLY_SET::PM_STRICTLY_SIMPLE or SHAPE_POLY_SET::PM_FAST)
#define POLY_CALC_MODE SHAPE_POLY_SET::PM_FAST #define POLY_CALC_MODE SHAPE_POLY_SET::PM_FAST
#include <cmath> #include <cmath>