Pcbnew: Disallow invalid mwwave inductor lengths
Some microwave inductor lengths cause invalid outputs for the calculations, which causes jagged outputs. * If the request length is such that four arcs and no straight segments is too long * If the length is such that an N-turn coil is too short, but an N+1-turn coil is too long. This can happen when the coil count is small. This patch doesn't fix the underlying geometric issue here - fixing the first requires a numerical method, and fixing the second probably needs an iterative approach. Both of these could benefit from a refactor. However, this patch does prevent the tools producing invalid outputs, which can sometimes be quite subtle mistakes if the "jags" are small. Fixes: lp:1792119 * https://bugs.launchpad.net/kicad/+bug/1792119
This commit is contained in:
parent
8b060799eb
commit
d39cdb5565
|
@ -79,6 +79,15 @@ static void gen_arc( std::vector <wxPoint>& aBuffer,
|
|||
}
|
||||
|
||||
|
||||
enum class INDUCTOR_S_SHAPE_RESULT
|
||||
{
|
||||
OK, /// S-shape constructed
|
||||
TOO_LONG, /// Requested length too long
|
||||
TOO_SHORT, /// Requested length too short
|
||||
NO_REPR, /// Requested length can't be represented
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Function BuildCornersList_S_Shape
|
||||
* Create a path like a S-shaped coil
|
||||
|
@ -88,10 +97,8 @@ static void gen_arc( std::vector <wxPoint>& aBuffer,
|
|||
* @param aLength = full length of the path
|
||||
* @param aWidth = segment width
|
||||
*/
|
||||
static int BuildCornersList_S_Shape( std::vector <wxPoint>& aBuffer,
|
||||
const wxPoint& aStartPoint,
|
||||
const wxPoint& aEndPoint,
|
||||
int aLength, int aWidth )
|
||||
static INDUCTOR_S_SHAPE_RESULT BuildCornersList_S_Shape( std::vector<wxPoint>& aBuffer,
|
||||
const wxPoint& aStartPoint, const wxPoint& aEndPoint, int aLength, int aWidth )
|
||||
{
|
||||
/* We must determine:
|
||||
* segm_count = number of segments perpendicular to the direction
|
||||
|
@ -171,7 +178,7 @@ static int BuildCornersList_S_Shape( std::vector <wxPoint>& aBuffer,
|
|||
if( radius < aWidth ) // Radius too small.
|
||||
{
|
||||
// Unable to create line: Requested length value is too large for room
|
||||
return 0;
|
||||
return INDUCTOR_S_SHAPE_RESULT::TOO_LONG;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -192,6 +199,30 @@ static int BuildCornersList_S_Shape( std::vector <wxPoint>& aBuffer,
|
|||
// reduce len of the segm_count segments + 2 half size segments (= 1 full size segment)
|
||||
segm_len -= delta_size / (segm_count + 1);
|
||||
|
||||
// at this point, it could still be that the requested length is too
|
||||
// short (because 4 quarter-circles are too long)
|
||||
// to fix this is a relatively complex numerical problem which probably
|
||||
// needs a refactor in this area. For now, just reject these cases:
|
||||
{
|
||||
const int min_total_length = 2 * stubs_len + 2 * M_PI * ADJUST_SIZE * radius;
|
||||
if( min_total_length > aLength )
|
||||
{
|
||||
// we can't express this inductor with 90-deg arcs of this radius
|
||||
return INDUCTOR_S_SHAPE_RESULT::TOO_SHORT;
|
||||
}
|
||||
}
|
||||
|
||||
if( segm_len - 2 * radius < 0 )
|
||||
{
|
||||
// we can't represent this exact requested length with this number
|
||||
// of segments (using the current algorithm). This stems from when
|
||||
// you add a segment, you also add another half-circle, so there's a
|
||||
// little bit of "dead" space.
|
||||
// It's a bit ugly to just reject the input, as it might be possible
|
||||
// to tweak the radius, but, again, that probably needs a refactor.
|
||||
return INDUCTOR_S_SHAPE_RESULT::NO_REPR;
|
||||
}
|
||||
|
||||
// Generate first line (the first stub) and first arc (90 deg arc)
|
||||
pt = aStartPoint;
|
||||
aBuffer.push_back( pt );
|
||||
|
@ -257,7 +288,7 @@ static int BuildCornersList_S_Shape( std::vector <wxPoint>& aBuffer,
|
|||
// push last point (end point)
|
||||
aBuffer.push_back( aEndPoint );
|
||||
|
||||
return 1;
|
||||
return INDUCTOR_S_SHAPE_RESULT::OK;
|
||||
}
|
||||
|
||||
|
||||
|
@ -298,7 +329,6 @@ MODULE* MWAVE::CreateMicrowaveInductor( INDUCTOR_PATTERN& inductorPattern,
|
|||
*/
|
||||
|
||||
D_PAD* pad;
|
||||
int ll;
|
||||
wxString msg;
|
||||
|
||||
auto pt = inductorPattern.m_End - inductorPattern.m_Start;
|
||||
|
@ -324,14 +354,22 @@ MODULE* MWAVE::CreateMicrowaveInductor( INDUCTOR_PATTERN& inductorPattern,
|
|||
|
||||
// Calculate the elements.
|
||||
std::vector <wxPoint> buffer;
|
||||
ll = BuildCornersList_S_Shape( buffer, inductorPattern.m_Start,
|
||||
inductorPattern.m_End, inductorPattern.m_length,
|
||||
inductorPattern.m_Width );
|
||||
const INDUCTOR_S_SHAPE_RESULT res = BuildCornersList_S_Shape( buffer, inductorPattern.m_Start,
|
||||
inductorPattern.m_End, inductorPattern.m_length, inductorPattern.m_Width );
|
||||
|
||||
if( !ll )
|
||||
switch( res )
|
||||
{
|
||||
case INDUCTOR_S_SHAPE_RESULT::TOO_LONG:
|
||||
aErrorMessage = _( "Requested length too large" );
|
||||
return nullptr;
|
||||
case INDUCTOR_S_SHAPE_RESULT::TOO_SHORT:
|
||||
aErrorMessage = _( "Requested length too small" );
|
||||
return nullptr;
|
||||
case INDUCTOR_S_SHAPE_RESULT::NO_REPR:
|
||||
aErrorMessage = _( "Requested length can't be represented" );
|
||||
return nullptr;
|
||||
case INDUCTOR_S_SHAPE_RESULT::OK:
|
||||
break;
|
||||
}
|
||||
|
||||
// Generate footprint. the value is also used as footprint name.
|
||||
|
|
Loading…
Reference in New Issue