Gerbview: Aperture Macro: handle overwriting of variables
Gerbview did not handle redefinition of variable like $3 = $3 / 2 This redefinition is sometimes found in Gerber files. This is a long standing issue now fixed. Fixes #7222 https://gitlab.com/kicad/code/kicad/issues/7222
This commit is contained in:
parent
eb240fda9a
commit
54b4f0e673
|
@ -69,7 +69,8 @@ bool AM_PARAM::IsImmediate() const
|
|||
return is_immediate;
|
||||
}
|
||||
|
||||
double AM_PARAM::GetValue( const D_CODE* aDcode ) const
|
||||
|
||||
double AM_PARAM::GetValueFromMacro( APERTURE_MACRO* aApertureMacro ) const
|
||||
{
|
||||
// In macros, actual values are sometimes given by an expression like:
|
||||
// 0-$2/2-$4
|
||||
|
@ -102,22 +103,15 @@ double AM_PARAM::GetValue( const D_CODE* aDcode ) const
|
|||
break;
|
||||
|
||||
case PUSHPARM:
|
||||
// a defered value: get the actual parameter from the aDcode
|
||||
if( aDcode ) // should be always true here
|
||||
// a defered value: get the actual parameter from the aperture macro
|
||||
if( aApertureMacro ) // should be always true here
|
||||
{
|
||||
if( item.GetIndex() <= aDcode->GetParamCount() )
|
||||
{
|
||||
curr_value = aDcode->GetParam( item.GetIndex() );
|
||||
}
|
||||
else // Get parameter from local param definition
|
||||
{
|
||||
const APERTURE_MACRO * am_parent = aDcode->GetMacro();
|
||||
curr_value = am_parent->GetLocalParam( aDcode, item.GetIndex() );
|
||||
}
|
||||
}
|
||||
// Get the actual value
|
||||
curr_value = aApertureMacro->GetLocalParamValue( item.GetIndex() );
|
||||
}
|
||||
else
|
||||
{
|
||||
wxFAIL_MSG( wxT( "AM_PARAM::GetValue(): NULL param aDcode" ) );
|
||||
wxFAIL_MSG( wxT( "AM_PARAM::GetValue(): NULL param aApertureMacro" ) );
|
||||
}
|
||||
|
||||
ops.emplace_back( curr_value );
|
||||
|
@ -129,10 +123,8 @@ double AM_PARAM::GetValue( const D_CODE* aDcode ) const
|
|||
break;
|
||||
|
||||
default:
|
||||
wxFAIL_MSG( wxString::Format( wxT( "AM_PARAM::GetValue(): dcode %d prm %d/%d: "
|
||||
"unexpected type %d" ),
|
||||
aDcode ? aDcode->m_Num_Dcode : -1, ii,
|
||||
m_paramStack.size(), item.GetType() ) );
|
||||
wxFAIL_MSG( wxString::Format( wxT( "AM_PARAM::GetValue(): unexpected prm type %d" ),
|
||||
item.GetType() ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -142,6 +134,7 @@ double AM_PARAM::GetValue( const D_CODE* aDcode ) const
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* add an operator/operand to the current stack
|
||||
* aType = NOP, PUSHVALUE, PUSHPARM, ADD, SUB, MUL, DIV, EQUATE
|
||||
|
|
|
@ -295,7 +295,7 @@ public:
|
|||
void PushOperator( parm_item_type aType, double aValue );
|
||||
void PushOperator( parm_item_type aType, int aValue = 0);
|
||||
|
||||
double GetValue( const D_CODE* aDcode ) const;
|
||||
double GetValueFromMacro( APERTURE_MACRO* aApertureMacro ) const;
|
||||
|
||||
/**
|
||||
* Test if this AM_PARAM holds an immediate parameter or is a pointer into a parameter held
|
||||
|
|
|
@ -55,7 +55,7 @@ static VECTOR2I mapPt( double x, double y, bool isMetric )
|
|||
}
|
||||
|
||||
|
||||
bool AM_PRIMITIVE::IsAMPrimitiveExposureOn( const D_CODE* aDcode ) const
|
||||
bool AM_PRIMITIVE::IsAMPrimitiveExposureOn( APERTURE_MACRO* aApertMacro ) const
|
||||
{
|
||||
/*
|
||||
* Some but not all primitives use the first parameter as an exposure control.
|
||||
|
@ -75,7 +75,7 @@ bool AM_PRIMITIVE::IsAMPrimitiveExposureOn( const D_CODE* aDcode ) const
|
|||
case AMP_OUTLINE:
|
||||
case AMP_POLYGON:
|
||||
// All have an exposure parameter and can return a value (0 or 1)
|
||||
return m_Params[0].GetValue( aDcode ) != 0;
|
||||
return m_Params[0].GetValueFromMacro( aApertMacro ) != 0;
|
||||
break;
|
||||
|
||||
case AMP_THERMAL: // Exposure is always on
|
||||
|
@ -88,11 +88,7 @@ bool AM_PRIMITIVE::IsAMPrimitiveExposureOn( const D_CODE* aDcode ) const
|
|||
}
|
||||
|
||||
|
||||
// TODO(snh): Remove hard coded count
|
||||
const int seg_per_circle = 64; // Number of segments to approximate a circle
|
||||
|
||||
|
||||
void AM_PRIMITIVE::ConvertBasicShapeToPolygon( const D_CODE* aDcode,
|
||||
void AM_PRIMITIVE::ConvertBasicShapeToPolygon( APERTURE_MACRO* aApertMacro,
|
||||
SHAPE_POLY_SET& aShapeBuffer )
|
||||
{
|
||||
// Draw the primitive shape for flashed items.
|
||||
|
@ -100,7 +96,7 @@ void AM_PRIMITIVE::ConvertBasicShapeToPolygon( const D_CODE* aDcode,
|
|||
static std::vector<VECTOR2I> polybuffer;
|
||||
polybuffer.clear();
|
||||
|
||||
const D_CODE* tool = aDcode;
|
||||
aApertMacro->EvalLocalParams( *this );
|
||||
|
||||
switch( m_Primitive_id )
|
||||
{
|
||||
|
@ -112,12 +108,12 @@ void AM_PRIMITIVE::ConvertBasicShapeToPolygon( const D_CODE* aDcode,
|
|||
* <rotation> is a optional parameter: rotation from origin.
|
||||
* type is not stored in parameters list, so the first parameter is exposure
|
||||
*/
|
||||
ConvertShapeToPolygon( tool, polybuffer );
|
||||
ConvertShapeToPolygon( aApertMacro, polybuffer );
|
||||
|
||||
// shape rotation (if any):
|
||||
if( m_Params.size() >= 5 )
|
||||
{
|
||||
EDA_ANGLE rotation( m_Params[4].GetValue( tool ), DEGREES_T );
|
||||
EDA_ANGLE rotation( m_Params[4].GetValueFromMacro( aApertMacro ), DEGREES_T );
|
||||
|
||||
if( !rotation.IsZero() )
|
||||
{
|
||||
|
@ -141,10 +137,10 @@ void AM_PRIMITIVE::ConvertBasicShapeToPolygon( const D_CODE* aDcode,
|
|||
* type (2), exposure, width, start.x, start.y, end.x, end.y, rotation
|
||||
* type is not stored in parameters list, so the first parameter is exposure
|
||||
*/
|
||||
ConvertShapeToPolygon( tool, polybuffer );
|
||||
ConvertShapeToPolygon( aApertMacro, polybuffer );
|
||||
|
||||
// shape rotation:
|
||||
EDA_ANGLE rotation( m_Params[6].GetValue( tool ), DEGREES_T );
|
||||
EDA_ANGLE rotation( m_Params[6].GetValueFromMacro( aApertMacro ), DEGREES_T );
|
||||
|
||||
if( !rotation.IsZero() )
|
||||
{
|
||||
|
@ -165,10 +161,10 @@ void AM_PRIMITIVE::ConvertBasicShapeToPolygon( const D_CODE* aDcode,
|
|||
* type (21), exposure, ,width, height, center pos.x, center pos.y, rotation
|
||||
* type is not stored in parameters list, so the first parameter is exposure
|
||||
*/
|
||||
ConvertShapeToPolygon( tool, polybuffer );
|
||||
ConvertShapeToPolygon( aApertMacro, polybuffer );
|
||||
|
||||
// shape rotation:
|
||||
EDA_ANGLE rotation( m_Params[5].GetValue( tool ), DEGREES_T );
|
||||
EDA_ANGLE rotation( m_Params[5].GetValueFromMacro( aApertMacro ), DEGREES_T );
|
||||
|
||||
if( !rotation.IsZero() )
|
||||
{
|
||||
|
@ -186,10 +182,10 @@ void AM_PRIMITIVE::ConvertBasicShapeToPolygon( const D_CODE* aDcode,
|
|||
* type (22), exposure, ,width, height, corner pos.x, corner pos.y, rotation
|
||||
* type is not stored in parameters list, so the first parameter is exposure
|
||||
*/
|
||||
ConvertShapeToPolygon( tool, polybuffer );
|
||||
ConvertShapeToPolygon( aApertMacro, polybuffer );
|
||||
|
||||
// shape rotation:
|
||||
EDA_ANGLE rotation( m_Params[5].GetValue( tool ), DEGREES_T );
|
||||
EDA_ANGLE rotation( m_Params[5].GetValueFromMacro( aApertMacro ), DEGREES_T );
|
||||
|
||||
if( !rotation.IsZero() )
|
||||
{
|
||||
|
@ -210,12 +206,12 @@ void AM_PRIMITIVE::ConvertBasicShapeToPolygon( const D_CODE* aDcode,
|
|||
* on.
|
||||
*/
|
||||
std::vector<VECTOR2I> subshape_poly;
|
||||
VECTOR2I center( mapPt( m_Params[0].GetValue( tool ),
|
||||
m_Params[1].GetValue( tool ), m_GerbMetric ) );
|
||||
ConvertShapeToPolygon( tool, subshape_poly );
|
||||
VECTOR2I center( mapPt( m_Params[0].GetValueFromMacro( aApertMacro ),
|
||||
m_Params[1].GetValueFromMacro( aApertMacro ), m_GerbMetric ) );
|
||||
ConvertShapeToPolygon( aApertMacro, subshape_poly );
|
||||
|
||||
// shape rotation:
|
||||
EDA_ANGLE rotation( m_Params[5].GetValue( tool ), DEGREES_T );
|
||||
EDA_ANGLE rotation( m_Params[5].GetValueFromMacro( aApertMacro ), DEGREES_T );
|
||||
|
||||
// Because a thermal shape has 4 identical sub-shapes, only one is created in subshape_poly.
|
||||
// We must draw 4 sub-shapes rotated by 90 deg
|
||||
|
@ -256,17 +252,17 @@ void AM_PRIMITIVE::ConvertBasicShapeToPolygon( const D_CODE* aDcode,
|
|||
* crosshair len, rotation. The type is not stored in parameters list, so the first
|
||||
* parameter is pos.x.
|
||||
*/
|
||||
int outerDiam = scaletoIU( m_Params[2].GetValue( tool ), m_GerbMetric );
|
||||
int penThickness = scaletoIU( m_Params[3].GetValue( tool ), m_GerbMetric );
|
||||
int gap = scaletoIU( m_Params[4].GetValue( tool ), m_GerbMetric );
|
||||
int numCircles = KiROUND( m_Params[5].GetValue( tool ) );
|
||||
int outerDiam = scaletoIU( m_Params[2].GetValueFromMacro( aApertMacro ), m_GerbMetric );
|
||||
int penThickness = scaletoIU( m_Params[3].GetValueFromMacro( aApertMacro ), m_GerbMetric );
|
||||
int gap = scaletoIU( m_Params[4].GetValueFromMacro( aApertMacro ), m_GerbMetric );
|
||||
int numCircles = KiROUND( m_Params[5].GetValueFromMacro( aApertMacro ) );
|
||||
|
||||
// Adjust the allowed approx error to convert arcs to segments:
|
||||
int arc_to_seg_error = gerbIUScale.mmToIU( 0.005 ); // Allow 5 microns
|
||||
|
||||
// Draw circles @ position pos.x, pos.y given by the tool:
|
||||
VECTOR2I center( mapPt( m_Params[0].GetValue( tool ), m_Params[1].GetValue( tool ),
|
||||
m_GerbMetric ) );
|
||||
VECTOR2I center( mapPt( m_Params[0].GetValueFromMacro( aApertMacro ),
|
||||
m_Params[1].GetValueFromMacro( aApertMacro ), m_GerbMetric ) );
|
||||
|
||||
// adjust outerDiam by this on each nested circle
|
||||
int diamAdjust = ( gap + penThickness ) * 2;
|
||||
|
@ -292,9 +288,9 @@ void AM_PRIMITIVE::ConvertBasicShapeToPolygon( const D_CODE* aDcode,
|
|||
}
|
||||
|
||||
// Draw the cross:
|
||||
ConvertShapeToPolygon( tool, polybuffer );
|
||||
ConvertShapeToPolygon( aApertMacro, polybuffer );
|
||||
|
||||
EDA_ANGLE rotation( m_Params[8].GetValue( tool ), DEGREES_T );
|
||||
EDA_ANGLE rotation( m_Params[8].GetValueFromMacro( aApertMacro ), DEGREES_T );
|
||||
|
||||
for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
|
||||
{
|
||||
|
@ -325,11 +321,11 @@ void AM_PRIMITIVE::ConvertBasicShapeToPolygon( const D_CODE* aDcode,
|
|||
* type is not stored in parameters list, so the first parameter is exposure
|
||||
*/
|
||||
// m_Params[0] is the exposure and m_Params[1] is the corners count after the first corner
|
||||
int numCorners = (int) m_Params[1].GetValue( tool );
|
||||
int numCorners = (int) m_Params[1].GetValueFromMacro( aApertMacro );
|
||||
|
||||
// the shape rotation is the last param of list, after corners
|
||||
int last_prm = m_Params.size() - 1;
|
||||
EDA_ANGLE rotation( m_Params[last_prm].GetValue( tool ), DEGREES_T );
|
||||
EDA_ANGLE rotation( m_Params[last_prm].GetValueFromMacro( aApertMacro ), DEGREES_T );
|
||||
VECTOR2I pos;
|
||||
|
||||
// Read points.
|
||||
|
@ -340,9 +336,9 @@ void AM_PRIMITIVE::ConvertBasicShapeToPolygon( const D_CODE* aDcode,
|
|||
|
||||
for( int i = 0; i <= numCorners; ++i )
|
||||
{
|
||||
pos.x = scaletoIU( m_Params[prm_idx].GetValue( tool ), m_GerbMetric );
|
||||
pos.x = scaletoIU( m_Params[prm_idx].GetValueFromMacro( aApertMacro ), m_GerbMetric );
|
||||
prm_idx++;
|
||||
pos.y = scaletoIU( m_Params[prm_idx].GetValue( tool ), m_GerbMetric );
|
||||
pos.y = scaletoIU( m_Params[prm_idx].GetValueFromMacro( aApertMacro ), m_GerbMetric );
|
||||
prm_idx++;
|
||||
polybuffer.push_back(pos);
|
||||
|
||||
|
@ -373,13 +369,14 @@ void AM_PRIMITIVE::ConvertBasicShapeToPolygon( const D_CODE* aDcode,
|
|||
* type(5), exposure, vertices count, pox.x, pos.y, diameter, rotation
|
||||
* type is not stored in parameters list, so the first parameter is exposure
|
||||
*/
|
||||
VECTOR2I curPos( mapPt( m_Params[2].GetValue( tool ), m_Params[3].GetValue( tool ), m_GerbMetric ) );
|
||||
VECTOR2I curPos( mapPt( m_Params[2].GetValueFromMacro( aApertMacro ),
|
||||
m_Params[3].GetValueFromMacro( aApertMacro ), m_GerbMetric ) );
|
||||
|
||||
// Creates the shape:
|
||||
ConvertShapeToPolygon( tool, polybuffer );
|
||||
ConvertShapeToPolygon( aApertMacro, polybuffer );
|
||||
|
||||
// rotate polygon
|
||||
EDA_ANGLE rotation( m_Params[5].GetValue( tool ), DEGREES_T );
|
||||
EDA_ANGLE rotation( m_Params[5].GetValueFromMacro( aApertMacro ), DEGREES_T );
|
||||
|
||||
for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
|
||||
{
|
||||
|
@ -408,11 +405,9 @@ void AM_PRIMITIVE::ConvertBasicShapeToPolygon( const D_CODE* aDcode,
|
|||
}
|
||||
|
||||
|
||||
void AM_PRIMITIVE::ConvertShapeToPolygon( const D_CODE* aDcode,
|
||||
void AM_PRIMITIVE::ConvertShapeToPolygon( APERTURE_MACRO* aApertMacro,
|
||||
std::vector<VECTOR2I>& aBuffer )
|
||||
{
|
||||
const D_CODE* tool = aDcode;
|
||||
|
||||
switch( m_Primitive_id )
|
||||
{
|
||||
case AMP_CIRCLE:
|
||||
|
@ -423,17 +418,19 @@ void AM_PRIMITIVE::ConvertShapeToPolygon( const D_CODE* aDcode,
|
|||
* <rotation> is a optional parameter: rotation from origin.
|
||||
* type is not stored in parameters list, so the first parameter is exposure
|
||||
*/
|
||||
int radius = scaletoIU( m_Params[1].GetValue( tool ), m_GerbMetric ) / 2;
|
||||
int radius = scaletoIU( m_Params[1].GetValueFromMacro( aApertMacro ), m_GerbMetric ) / 2;
|
||||
|
||||
// A circle primitive can have a 0 size (for instance when used in roundrect macro),
|
||||
// so skip it
|
||||
if( radius <= 0 )
|
||||
break;
|
||||
|
||||
VECTOR2I center = mapPt( m_Params[2].GetValue( tool ), m_Params[3].GetValue( tool ),
|
||||
VECTOR2I center = mapPt( m_Params[2].GetValueFromMacro( aApertMacro ), m_Params[3].GetValueFromMacro( aApertMacro ),
|
||||
m_GerbMetric );
|
||||
VECTOR2I corner;
|
||||
EDA_ANGLE delta = ANGLE_360 / seg_per_circle; // rot angle in 0.1 degree
|
||||
|
||||
const int seg_per_circle = 64; // Number of segments to approximate a circle
|
||||
EDA_ANGLE delta = ANGLE_360 / seg_per_circle;
|
||||
|
||||
for( EDA_ANGLE angle = ANGLE_0; angle < ANGLE_360; angle += delta )
|
||||
{
|
||||
|
@ -450,11 +447,11 @@ void AM_PRIMITIVE::ConvertShapeToPolygon( const D_CODE* aDcode,
|
|||
case AMP_LINE2:
|
||||
case AMP_LINE20: // Line with rectangle ends. (Width, start and end pos + rotation)
|
||||
{
|
||||
int width = scaletoIU( m_Params[1].GetValue( tool ), m_GerbMetric );
|
||||
int width = scaletoIU( m_Params[1].GetValueFromMacro( aApertMacro ), m_GerbMetric );
|
||||
VECTOR2I start =
|
||||
mapPt( m_Params[2].GetValue( tool ), m_Params[3].GetValue( tool ), m_GerbMetric );
|
||||
mapPt( m_Params[2].GetValueFromMacro( aApertMacro ), m_Params[3].GetValueFromMacro( aApertMacro ), m_GerbMetric );
|
||||
VECTOR2I end =
|
||||
mapPt( m_Params[4].GetValue( tool ), m_Params[5].GetValue( tool ), m_GerbMetric );
|
||||
mapPt( m_Params[4].GetValueFromMacro( aApertMacro ), m_Params[5].GetValueFromMacro( aApertMacro ), m_GerbMetric );
|
||||
VECTOR2I delta = end - start;
|
||||
int len = KiROUND( EuclideanNorm( delta ) );
|
||||
|
||||
|
@ -485,9 +482,9 @@ void AM_PRIMITIVE::ConvertShapeToPolygon( const D_CODE* aDcode,
|
|||
case AMP_LINE_CENTER:
|
||||
{
|
||||
VECTOR2I size =
|
||||
mapPt( m_Params[1].GetValue( tool ), m_Params[2].GetValue( tool ), m_GerbMetric );
|
||||
mapPt( m_Params[1].GetValueFromMacro( aApertMacro ), m_Params[2].GetValueFromMacro( aApertMacro ), m_GerbMetric );
|
||||
VECTOR2I pos =
|
||||
mapPt( m_Params[3].GetValue( tool ), m_Params[4].GetValue( tool ), m_GerbMetric );
|
||||
mapPt( m_Params[3].GetValueFromMacro( aApertMacro ), m_Params[4].GetValueFromMacro( aApertMacro ), m_GerbMetric );
|
||||
|
||||
// Build poly:
|
||||
pos.x -= size.x / 2;
|
||||
|
@ -505,9 +502,9 @@ void AM_PRIMITIVE::ConvertShapeToPolygon( const D_CODE* aDcode,
|
|||
case AMP_LINE_LOWER_LEFT:
|
||||
{
|
||||
VECTOR2I size =
|
||||
mapPt( m_Params[1].GetValue( tool ), m_Params[2].GetValue( tool ), m_GerbMetric );
|
||||
mapPt( m_Params[1].GetValueFromMacro( aApertMacro ), m_Params[2].GetValueFromMacro( aApertMacro ), m_GerbMetric );
|
||||
VECTOR2I lowerLeft =
|
||||
mapPt( m_Params[3].GetValue( tool ), m_Params[4].GetValue( tool ), m_GerbMetric );
|
||||
mapPt( m_Params[3].GetValueFromMacro( aApertMacro ), m_Params[4].GetValueFromMacro( aApertMacro ), m_GerbMetric );
|
||||
|
||||
// Build poly:
|
||||
aBuffer.push_back( lowerLeft );
|
||||
|
@ -526,14 +523,14 @@ void AM_PRIMITIVE::ConvertShapeToPolygon( const D_CODE* aDcode,
|
|||
// this first rotated by 90, 180 and 270 deg.
|
||||
// m_Params = center.x (unused here), center.y (unused here), outside diam, inside diam,
|
||||
// crosshair thickness.
|
||||
int outerRadius = scaletoIU( m_Params[2].GetValue( tool ), m_GerbMetric ) / 2;
|
||||
int innerRadius = scaletoIU( m_Params[3].GetValue( tool ), m_GerbMetric ) / 2;
|
||||
int outerRadius = scaletoIU( m_Params[2].GetValueFromMacro( aApertMacro ), m_GerbMetric ) / 2;
|
||||
int innerRadius = scaletoIU( m_Params[3].GetValueFromMacro( aApertMacro ), m_GerbMetric ) / 2;
|
||||
|
||||
// Safety checks to guarantee no divide-by-zero
|
||||
outerRadius = std::max( 1, outerRadius );
|
||||
innerRadius = std::max( 1, innerRadius );
|
||||
|
||||
int halfthickness = scaletoIU( m_Params[4].GetValue( tool ), m_GerbMetric ) / 2;
|
||||
int halfthickness = scaletoIU( m_Params[4].GetValueFromMacro( aApertMacro ), m_GerbMetric ) / 2;
|
||||
EDA_ANGLE angle_start( asin( (double) halfthickness / innerRadius ), RADIANS_T );
|
||||
|
||||
// Draw shape in the first quadrant (X and Y > 0)
|
||||
|
@ -582,8 +579,8 @@ void AM_PRIMITIVE::ConvertShapeToPolygon( const D_CODE* aDcode,
|
|||
{
|
||||
// A cross hair with n concentric circles. Only the cross is built as
|
||||
// polygon because circles can be drawn easily
|
||||
int crossHairThickness = scaletoIU( m_Params[6].GetValue( tool ), m_GerbMetric );
|
||||
int crossHairLength = scaletoIU( m_Params[7].GetValue( tool ), m_GerbMetric );
|
||||
int crossHairThickness = scaletoIU( m_Params[6].GetValueFromMacro( aApertMacro ), m_GerbMetric );
|
||||
int crossHairLength = scaletoIU( m_Params[7].GetValueFromMacro( aApertMacro ), m_GerbMetric );
|
||||
|
||||
// Create cross. First create 1/4 of the shape.
|
||||
// Others point are the same, rotated by 90, 180 and 270 deg
|
||||
|
@ -616,8 +613,8 @@ void AM_PRIMITIVE::ConvertShapeToPolygon( const D_CODE* aDcode,
|
|||
|
||||
case AMP_POLYGON: // Creates a regular polygon
|
||||
{
|
||||
int vertexcount = KiROUND( m_Params[1].GetValue( tool ) );
|
||||
int radius = scaletoIU( m_Params[4].GetValue( tool ), m_GerbMetric ) / 2;
|
||||
int vertexcount = KiROUND( m_Params[1].GetValueFromMacro( aApertMacro ) );
|
||||
int radius = scaletoIU( m_Params[4].GetValueFromMacro( aApertMacro ), m_GerbMetric ) / 2;
|
||||
|
||||
// rs274x said: vertex count = 3 ... 10, and the first corner is on the X axis
|
||||
if( vertexcount < 3 )
|
||||
|
|
|
@ -117,18 +117,21 @@ public:
|
|||
* In a aperture macro shape, a basic primitive with exposure off is a hole in the shape
|
||||
* it is NOT a negative shape
|
||||
*/
|
||||
bool IsAMPrimitiveExposureOn( const D_CODE* aDcode ) const;
|
||||
bool IsAMPrimitiveExposureOn( APERTURE_MACRO* aApertMacro ) const;
|
||||
|
||||
/**
|
||||
* Generate the polygonal shape of the primitive shape of an aperture
|
||||
* macro instance.
|
||||
*
|
||||
* @param aParent is the parent GERBER_DRAW_ITEM which is actually drawn.
|
||||
* @param aApertMacro is the aperture macro using this primitive.
|
||||
* @param aShapeBuffer is a SHAPE_POLY_SET to put the shape converted to a polygon.
|
||||
* @param aShapePos is the actual shape position.
|
||||
*/
|
||||
#if 0
|
||||
void ConvertBasicShapeToPolygon( const D_CODE* aDcode,
|
||||
SHAPE_POLY_SET& aShapeBuffer );
|
||||
#endif
|
||||
void ConvertBasicShapeToPolygon( APERTURE_MACRO* aApertMacro,
|
||||
SHAPE_POLY_SET& aShapeBuffer );
|
||||
|
||||
private:
|
||||
/**
|
||||
|
@ -141,7 +144,8 @@ private:
|
|||
* converted because circles are very easy to draw (no rotation problem) so convert
|
||||
* them in polygons and draw them as polygons is not a good idea.
|
||||
*/
|
||||
void ConvertShapeToPolygon( const D_CODE* aDcode, std::vector<VECTOR2I>& aBuffer );
|
||||
//void ConvertShapeToPolygon( const D_CODE* aDcode, std::vector<VECTOR2I>& aBuffer );
|
||||
void ConvertShapeToPolygon( APERTURE_MACRO* aApertMacroe, std::vector<VECTOR2I>& aBuffer );
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -32,6 +32,55 @@
|
|||
#include <aperture_macro.h>
|
||||
#include <gerber_draw_item.h>
|
||||
|
||||
void APERTURE_MACRO::InitLocalParams( const D_CODE* aDcode )
|
||||
{
|
||||
// store the initial values coming from aDcode into m_localParamValues
|
||||
// for n parameters, they are local params $1 to $n
|
||||
m_localParamValues.clear();
|
||||
|
||||
// Note: id_param = 1... n, not 0
|
||||
for( unsigned id_param = 1; id_param <= aDcode->GetParamCount(); id_param++ )
|
||||
m_localParamValues[id_param] = aDcode->GetParam( id_param );
|
||||
|
||||
m_paramLevelEval = 0;
|
||||
}
|
||||
|
||||
|
||||
void APERTURE_MACRO::EvalLocalParams( const AM_PRIMITIVE& aPrimitive )
|
||||
{
|
||||
// Evaluate m_localParamValues from current m_paramLevelEval to
|
||||
// aPrimitive.m_LocalParamLevel
|
||||
// if m_paramLevelEval >= m_LocalParamLevel, do nothing: the
|
||||
// m_localParamValues are already up to date
|
||||
|
||||
if( m_paramLevelEval >= aPrimitive.m_LocalParamLevel )
|
||||
return;
|
||||
|
||||
for( ; m_paramLevelEval < aPrimitive.m_LocalParamLevel; m_paramLevelEval++ )
|
||||
{
|
||||
AM_PARAM& am_param = m_localParamStack.at( m_paramLevelEval );
|
||||
int prm_index = am_param.GetIndex();
|
||||
|
||||
double value = am_param.GetValueFromMacro( this );
|
||||
|
||||
// if am_param value is not yet stored in m_localParamValues, add it.
|
||||
// if it is already in m_localParamValues, update its value;
|
||||
m_localParamValues[ prm_index ] = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
double APERTURE_MACRO::GetLocalParamValue( int aIndex )
|
||||
{
|
||||
// return the local param value stored in m_localParamValues
|
||||
// if not existing, returns 0
|
||||
|
||||
if( m_localParamValues.find( aIndex ) != m_localParamValues.end() )
|
||||
return m_localParamValues[ aIndex ];
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
|
||||
void APERTURE_MACRO::AddPrimitiveToList( AM_PRIMITIVE& aPrimitive )
|
||||
{
|
||||
|
@ -52,25 +101,26 @@ AM_PARAM& APERTURE_MACRO::GetLastLocalParamDefFromStack()
|
|||
|
||||
|
||||
SHAPE_POLY_SET* APERTURE_MACRO::GetApertureMacroShape( const GERBER_DRAW_ITEM* aParent,
|
||||
const VECTOR2I& aShapePos )
|
||||
const VECTOR2I& aShapePos )
|
||||
{
|
||||
SHAPE_POLY_SET holeBuffer;
|
||||
|
||||
m_shape.RemoveAllContours();
|
||||
D_CODE * dcode = aParent->GetDcodeDescr();
|
||||
D_CODE* dcode = aParent->GetDcodeDescr();
|
||||
InitLocalParams( dcode );
|
||||
|
||||
for( AM_PRIMITIVE& prim_macro : m_primitivesList )
|
||||
{
|
||||
if( prim_macro.m_Primitive_id == AMP_COMMENT )
|
||||
continue;
|
||||
|
||||
if( prim_macro.IsAMPrimitiveExposureOn( dcode ) )
|
||||
if( prim_macro.IsAMPrimitiveExposureOn( this ) )
|
||||
{
|
||||
prim_macro.ConvertBasicShapeToPolygon( dcode, m_shape );
|
||||
prim_macro.ConvertBasicShapeToPolygon( this, m_shape );
|
||||
}
|
||||
else
|
||||
{
|
||||
prim_macro.ConvertBasicShapeToPolygon( dcode, holeBuffer );
|
||||
prim_macro.ConvertBasicShapeToPolygon( this, holeBuffer );
|
||||
|
||||
if( holeBuffer.OutlineCount() ) // we have a new hole in shape: remove the hole
|
||||
{
|
||||
|
@ -105,27 +155,3 @@ SHAPE_POLY_SET* APERTURE_MACRO::GetApertureMacroShape( const GERBER_DRAW_ITEM* a
|
|||
|
||||
return &m_shape;
|
||||
}
|
||||
|
||||
|
||||
double APERTURE_MACRO::GetLocalParam( const D_CODE* aDcode, unsigned aParamId ) const
|
||||
{
|
||||
// find parameter descr.
|
||||
const AM_PARAM * param = nullptr;
|
||||
|
||||
for( unsigned ii = 0; ii < m_localParamStack.size(); ii ++ )
|
||||
{
|
||||
if( m_localParamStack[ii].GetIndex() == aParamId )
|
||||
{
|
||||
param = &m_localParamStack[ii];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( param == nullptr ) // not found
|
||||
return 0.0;
|
||||
|
||||
// Evaluate parameter
|
||||
double value = param->GetValue( aDcode );
|
||||
|
||||
return value;
|
||||
}
|
||||
|
|
|
@ -68,6 +68,9 @@ class SHAPE_POLY_SET;
|
|||
class APERTURE_MACRO
|
||||
{
|
||||
public:
|
||||
APERTURE_MACRO() :
|
||||
m_paramLevelEval( 0 )
|
||||
{}
|
||||
/**
|
||||
* Usually, parameters are defined inside the aperture primitive using immediate mode or
|
||||
* deferred mode.
|
||||
|
@ -82,17 +85,40 @@ public:
|
|||
*/
|
||||
double GetLocalParam( const D_CODE* aDcode, unsigned aParamId ) const;
|
||||
|
||||
/**
|
||||
* Init m_localParamValues to a initial values coming from aDcode and
|
||||
* clear m_paramLevelEval
|
||||
* must be called once before trying to build the aperture macro shape
|
||||
* corresponding to aDcode
|
||||
*/
|
||||
void InitLocalParams( const D_CODE* aDcode );
|
||||
|
||||
/**
|
||||
* Evaluate m_localParamValues from current m_paramLevelEval to
|
||||
* aPrimitive m_LocalParamLevel
|
||||
* if m_paramLevelEval >= m_LocalParamLevel, do nothing
|
||||
* after call, m_paramLevelEval = m_LocalParamLevel
|
||||
*/
|
||||
void EvalLocalParams( const AM_PRIMITIVE& aPrimitive );
|
||||
|
||||
/**
|
||||
* @return the local param value stored in m_localParamValues
|
||||
* @param aIndex is the param Id (from $n)
|
||||
* if not found, returns 0
|
||||
*/
|
||||
double GetLocalParamValue( int aIndex );
|
||||
|
||||
/**
|
||||
* Calculate the primitive shape for flashed items.
|
||||
*
|
||||
* When an item is flashed, this is the shape of the item.
|
||||
*
|
||||
* @param aParent is the parent #GERBER_DRAW_ITEM which is actually drawn.
|
||||
* @return the shape of the item.
|
||||
* @param aParent is the parent #GERBER_DRAW_ITEM which is actually drawn.
|
||||
* @param aShapePos is the position of the shape to build.
|
||||
*/
|
||||
SHAPE_POLY_SET* GetApertureMacroShape( const GERBER_DRAW_ITEM* aParent,
|
||||
const VECTOR2I& aShapePos );
|
||||
const VECTOR2I& aShapePos );
|
||||
|
||||
/**
|
||||
* The name of the aperture macro as defined like %AMVB_RECTANGLE* (name is VB_RECTANGLE)
|
||||
|
@ -125,6 +151,20 @@ private:
|
|||
*/
|
||||
AM_PARAMS m_localParamStack;
|
||||
|
||||
/**
|
||||
* m_localParamValues is the current value of local parameters after evaluation
|
||||
* the key is the local param id (from $n) and the value is double
|
||||
*/
|
||||
std::map<int, double> m_localParamValues;
|
||||
|
||||
/**
|
||||
* the current level of local param values evaluation
|
||||
* when a primitive is evaluated, if its m_LocalParamLevel is smaller than
|
||||
* m_paramLevelEval, all local params must be evaluated from current m_paramLevelEval
|
||||
* upto m_LocalParamLevel before use in this primitive
|
||||
*/
|
||||
int m_paramLevelEval;
|
||||
|
||||
SHAPE_POLY_SET m_shape; ///< The shape of the item, calculated by GetApertureMacroShape
|
||||
};
|
||||
|
||||
|
|
|
@ -105,6 +105,7 @@ public:
|
|||
* Return a parameter stored in parameter list.
|
||||
*
|
||||
* @param aIdx is the index of parameter.
|
||||
* for n parameters from the Dcode definition, aIdx = 1 .. n, not 0
|
||||
*/
|
||||
double GetParam( unsigned aIdx ) const
|
||||
{
|
||||
|
|
|
@ -320,7 +320,6 @@ const BOX2I GERBER_DRAW_ITEM::GetBoundingBox() const
|
|||
|
||||
case GBR_SPOT_MACRO:
|
||||
case GBR_SPOT_POLY:
|
||||
{
|
||||
if( code )
|
||||
{
|
||||
if( code->m_Polygon.OutlineCount() == 0 )
|
||||
|
@ -331,7 +330,6 @@ const BOX2I GERBER_DRAW_ITEM::GetBoundingBox() const
|
|||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case GBR_SEGMENT:
|
||||
{
|
||||
|
@ -861,12 +859,7 @@ bool GERBER_DRAW_ITEM::HitTest( const VECTOR2I& aRefPos, int aAccuracy ) const
|
|||
}
|
||||
|
||||
case GBR_SPOT_MACRO:
|
||||
{
|
||||
// Aperture macro polygons are already in absolute coordinates
|
||||
SHAPE_POLY_SET* p =
|
||||
GetDcodeDescr()->GetMacro()->GetApertureMacroShape( this, m_Start );
|
||||
return p->Contains( VECTOR2I( aRefPos ), -1, aAccuracy );
|
||||
}
|
||||
return m_AbsolutePolygon.Contains( VECTOR2I( aRefPos ), -1, aAccuracy );
|
||||
|
||||
case GBR_SEGMENT:
|
||||
case GBR_CIRCLE:
|
||||
|
|
|
@ -566,21 +566,26 @@ void GERBVIEW_PAINTER::drawFlashedShape( GERBER_DRAW_ITEM* aItem, bool aFilled )
|
|||
|
||||
void GERBVIEW_PAINTER::drawApertureMacro( GERBER_DRAW_ITEM* aParent, bool aFilled )
|
||||
{
|
||||
D_CODE* code = aParent->GetDcodeDescr();
|
||||
APERTURE_MACRO* macro = code->GetMacro();
|
||||
SHAPE_POLY_SET* macroShape = macro->GetApertureMacroShape( aParent, aParent->m_Start );
|
||||
if( aParent->m_AbsolutePolygon.OutlineCount() == 0 )
|
||||
{
|
||||
D_CODE* code = aParent->GetDcodeDescr();
|
||||
APERTURE_MACRO* macro = code->GetMacro();
|
||||
aParent->m_AbsolutePolygon = *macro->GetApertureMacroShape( aParent, aParent->m_Start );
|
||||
}
|
||||
|
||||
SHAPE_POLY_SET& polyset = aParent->m_AbsolutePolygon;
|
||||
|
||||
if( !gvconfig()->m_Display.m_DisplayPolygonsFill )
|
||||
m_gal->SetLineWidth( m_gerbviewSettings.m_outlineWidth );
|
||||
|
||||
if( !aFilled )
|
||||
{
|
||||
for( int i = 0; i < macroShape->OutlineCount(); i++ )
|
||||
m_gal->DrawPolyline( macroShape->COutline( i ) );
|
||||
for( int i = 0; i < polyset.OutlineCount(); i++ )
|
||||
m_gal->DrawPolyline( polyset.COutline( i ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_gal->DrawPolygon( *macroShape );
|
||||
m_gal->DrawPolygon( polyset );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1132,7 +1132,7 @@ bool GERBER_FILE_IMAGE::ReadApertureMacro( char *aBuff, unsigned int aBuffSize,
|
|||
// in advance, i.e. be immediate.
|
||||
wxASSERT( prim.m_Params[1].IsImmediate() );
|
||||
|
||||
paramCount = (int) prim.m_Params[1].GetValue( nullptr ) * 2 + 1;
|
||||
paramCount = (int) prim.m_Params[1].GetValueFromMacro( nullptr ) * 2 + 1;
|
||||
|
||||
for( int jj = 0; jj < paramCount && *aText != '*'; ++jj )
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue