void AM_PRIMITIVE::DrawBasicShape( const GERBER_DRAW_ITEM* aParent, SHAPE_POLY_SET& aShapeBuffer, wxPoint aShapePos ) { #define TO_POLY_SHAPE { aShapeBuffer.NewOutline(); \ for( unsigned jj = 0; jj < polybuffer.size(); jj++ )\ aShapeBuffer.Append( polybuffer[jj].x, polybuffer[jj].y );\ aShapeBuffer.Append( polybuffer[0].x, polybuffer[0].y );} // Draw the primitive shape for flashed items. static std::vector<wxPoint> polybuffer; // create a static buffer to avoid a lot of memory reallocation polybuffer.clear(); wxPoint curPos = aShapePos; D_CODE* tool = aParent->GetDcodeDescr(); double rotation; switch( primitive_id ) { case AMP_CIRCLE: // Circle, given diameter and position { /* Generated by an aperture macro declaration like: * "1,1,0.3,0.5, 1.0*" * type (1), exposure, diameter, pos.x, pos.y, <rotation> * <rotation> is a optional parameter: rotation from origin. * type is not stored in parameters list, so the first parameter is exposure */ ConvertShapeToPolygon( aParent, polybuffer ); // shape rotation (if any): if( params.size() >= 5 ) { rotation = params[4].GetValue( tool ) * 10.0; if( rotation != 0) { for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) RotatePoint( &polybuffer[ii], -rotation ); } } // Move to current position: for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) { polybuffer[ii] += curPos; polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); } TO_POLY_SHAPE; } break; case AMP_LINE2: case AMP_LINE20: // Line with rectangle ends. (Width, start and end pos + rotation) { /* Vector Line, Primitive Code 20. * A vector line is a rectangle defined by its line width, start and end points. * The line ends are rectangular. */ /* Generated by an aperture macro declaration like: * "2,1,0.3,0,0, 0.5, 1.0,-135*" * 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( aParent, polybuffer ); // shape rotation: rotation = params[6].GetValue( tool ) * 10.0; if( rotation != 0) { for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) RotatePoint( &polybuffer[ii], -rotation ); } // Move to current position: for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) { polybuffer[ii] += curPos; polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); } TO_POLY_SHAPE; } break; case AMP_LINE_CENTER: { /* Center Line, Primitive Code 21 * A center line primitive is a rectangle defined by its width, height, and center point */ /* Generated by an aperture macro declaration like: * "21,1,0.3,0.03,0,0,-135*" * 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( aParent, polybuffer ); // shape rotation: rotation = params[5].GetValue( tool ) * 10.0; if( rotation != 0 ) { for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) RotatePoint( &polybuffer[ii], -rotation ); } // Move to current position: for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) { polybuffer[ii] += curPos; polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); } TO_POLY_SHAPE; } break; case AMP_LINE_LOWER_LEFT: { /* Generated by an aperture macro declaration like: * "22,1,0.3,0.03,0,0,-135*" * 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( aParent, polybuffer ); // shape rotation: rotation = params[5].GetValue( tool ) * 10.0; if( rotation != 0) { for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) RotatePoint( &polybuffer[ii], -rotation ); } // Move to current position: for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) { polybuffer[ii] += curPos; polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); } TO_POLY_SHAPE; } break; case AMP_THERMAL: { /* Generated by an aperture macro declaration like: * "7, 0,0,1.0,0.3,0.01,-13*" * type (7), center.x , center.y, outside diam, inside diam, crosshair thickness, rotation * type is not stored in parameters list, so the first parameter is center.x * * The thermal primitive is a ring (annulus) interrupted by four gaps. Exposure is always on. */ std::vector<wxPoint> subshape_poly; curPos += mapPt( params[0].GetValue( tool ), params[1].GetValue( tool ), m_GerbMetric ); ConvertShapeToPolygon( aParent, subshape_poly ); // shape rotation: rotation = params[5].GetValue( tool ) * 10.0; // 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 for( int ii = 0; ii < 4; ii++ ) { polybuffer = subshape_poly; double sub_rotation = rotation + 900 * ii; for( unsigned jj = 0; jj < polybuffer.size(); jj++ ) RotatePoint( &polybuffer[jj], -sub_rotation ); // Move to current position: for( unsigned jj = 0; jj < polybuffer.size(); jj++ ) { polybuffer[jj] += curPos; polybuffer[jj] = aParent->GetABPosition( polybuffer[jj] ); } TO_POLY_SHAPE; } } break; case AMP_MOIRE: { /* Moir�, Primitive Code 6 * The moir� primitive is a cross hair centered on concentric rings (annuli). * Exposure is always on. */ curPos += mapPt( params[0].GetValue( tool ), params[1].GetValue( tool ), m_GerbMetric ); /* Generated by an aperture macro declaration like: * "6,0,0,0.125,.01,0.01,3,0.003,0.150,0" * type(6), pos.x, pos.y, diam, penwidth, gap, circlecount, crosshair thickness, crosshaire len, rotation * type is not stored in parameters list, so the first parameter is pos.x */ int outerDiam = scaletoIU( params[2].GetValue( tool ), m_GerbMetric ); int penThickness = scaletoIU( params[3].GetValue( tool ), m_GerbMetric ); int gap = scaletoIU( params[4].GetValue( tool ), m_GerbMetric ); int numCircles = KiROUND( params[5].GetValue( tool ) ); // Draw circles: wxPoint center = aParent->GetABPosition( curPos ); // adjust outerDiam by this on each nested circle int diamAdjust = (gap + penThickness) * 2; for( int i = 0; i < numCircles; ++i, outerDiam -= diamAdjust ) { if( outerDiam <= 0 ) break; // Note: outerDiam is the outer diameter of the ring. // the ring graphic diameter is (outerDiam - penThickness) if( outerDiam <= penThickness ) { // No room to draw a ring (no room for the hole): // draw a circle instead (with no hole), with the right diameter TransformCircleToPolygon( aShapeBuffer, center, outerDiam / 2, seg_per_circle ); } else TransformRingToPolygon( aShapeBuffer, center, (outerDiam - penThickness) / 2, seg_per_circle, penThickness ); } // Draw the cross: ConvertShapeToPolygon( aParent, polybuffer ); rotation = params[8].GetValue( tool ) * 10.0; for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) { // shape rotation: RotatePoint( &polybuffer[ii], -rotation ); // Move to current position: polybuffer[ii] += curPos; polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); } TO_POLY_SHAPE; } break; case AMP_OUTLINE: { /* Outline, Primitive Code 4 * An outline primitive is an area enclosed by an n-point polygon defined by its start point and n * subsequent points. The outline must be closed, i.e. the last point must be equal to the start * point. There must be at least one subsequent point (to close the outline). * The outline of the primitive is actually the contour (see 2.6) that consists of linear segments * only, so it must conform to all the requirements described for contours. * Warning: Make no mistake: n is the number of subsequent points, being the number of * vertices of the outline or one less than the number of coordinate pairs. */ /* Generated by an aperture macro declaration like: * "4,1,3,0.0,0.0,0.0,0.5,0.5,0.5,0.5,0.0,-25" * type(4), exposure, corners count, corner1.x, corner.1y, ..., corner1.x, corner.1y, rotation * type is not stored in parameters list, so the first parameter is exposure */ // params[0] is the exposure and params[1] is the corners count after the first corner int numCorners = (int) params[1].GetValue( tool ); // the shape rotation is the last param of list, after corners int last_prm = params.size() - 1; rotation = params[last_prm].GetValue( tool ) * 10.0; wxPoint pos; // Read points. // Note: numCorners is the polygon corner count, following the first corner // * the polygon is always closed, // * therefore the last XY coordinate is the same as the first int prm_idx = 2; // params[2] is the first X coordinate for( int i = 0; i <= numCorners; ++i ) { pos.x = scaletoIU( params[prm_idx].GetValue( tool ), m_GerbMetric ); prm_idx++; pos.y = scaletoIU( params[prm_idx].GetValue( tool ), m_GerbMetric ); prm_idx++; polybuffer.push_back(pos); // Guard: ensure prm_idx < last_prm // I saw malformed gerber files with numCorners = number // of coordinates instead of number of coordinates following the first point if( prm_idx >= last_prm ) break; } // rotate polygon and move it to the actual position // shape rotation: for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) { RotatePoint( &polybuffer[ii], -rotation ); } // Move to current position: for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) { polybuffer[ii] += curPos; polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); } TO_POLY_SHAPE; } break; case AMP_POLYGON: /* Polygon, Primitive Code 5 * A polygon primitive is a regular polygon defined by the number of vertices n, the center point * and the diameter of the circumscribed circle */ /* Generated by an aperture macro declaration like: * "5,1,0.6,0,0,0.5,25" * type(5), exposure, vertices count, pox.x, pos.y, diameter, rotation * type is not stored in parameters list, so the first parameter is exposure */ curPos += mapPt( params[2].GetValue( tool ), params[3].GetValue( tool ), m_GerbMetric ); // Creates the shape: ConvertShapeToPolygon( aParent, polybuffer ); // rotate polygon and move it to the actual position rotation = params[5].GetValue( tool ) * 10.0; for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) { RotatePoint( &polybuffer[ii], -rotation ); polybuffer[ii] += curPos; polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); } TO_POLY_SHAPE; break; case AMP_EOF: // not yet supported, waiting for you. break; case AMP_UNKNOWN: default: DBG( printf( "AM_PRIMITIVE::DrawBasicShape() err: unknown prim id %d\n",primitive_id) ); break; } }
void D_CODE::DrawFlashedShape( GERBER_DRAW_ITEM* aParent, EDA_RECT* aClipBox, wxDC* aDC, COLOR4D aColor, wxPoint aShapePos, bool aFilledShape ) { int radius; switch( m_Shape ) { case APT_MACRO: GetMacro()->DrawApertureMacroShape( aParent, aClipBox, aDC, aColor, aShapePos, aFilledShape); break; case APT_CIRCLE: radius = m_Size.x >> 1; if( !aFilledShape ) GRCircle( aClipBox, aDC, aParent->GetABPosition(aShapePos), radius, 0, aColor ); else if( m_DrillShape == APT_DEF_NO_HOLE ) { GRFilledCircle( aClipBox, aDC, aParent->GetABPosition(aShapePos), radius, aColor ); } else if( m_DrillShape == APT_DEF_ROUND_HOLE ) // round hole in shape { int width = (m_Size.x - m_Drill.x ) / 2; GRCircle( aClipBox, aDC, aParent->GetABPosition(aShapePos), radius - (width / 2), width, aColor ); } else // rectangular hole { if( m_Polygon.OutlineCount() == 0 ) ConvertShapeToPolygon(); DrawFlashedPolygon( aParent, aClipBox, aDC, aColor, aFilledShape, aShapePos ); } break; case APT_RECT: { wxPoint start; start.x = aShapePos.x - m_Size.x / 2; start.y = aShapePos.y - m_Size.y / 2; wxPoint end = start + m_Size; start = aParent->GetABPosition( start ); end = aParent->GetABPosition( end ); if( !aFilledShape ) { GRRect( aClipBox, aDC, start.x, start.y, end.x, end.y, 0, aColor ); } else if( m_DrillShape == APT_DEF_NO_HOLE ) { GRFilledRect( aClipBox, aDC, start.x, start.y, end.x, end.y, 0, aColor, aColor ); } else { if( m_Polygon.OutlineCount() == 0 ) ConvertShapeToPolygon(); DrawFlashedPolygon( aParent, aClipBox, aDC, aColor, aFilledShape, aShapePos ); } } break; case APT_OVAL: { wxPoint start = aShapePos; wxPoint end = aShapePos; if( m_Size.x > m_Size.y ) // horizontal oval { int delta = (m_Size.x - m_Size.y) / 2; start.x -= delta; end.x += delta; radius = m_Size.y; } else // horizontal oval { int delta = (m_Size.y - m_Size.x) / 2; start.y -= delta; end.y += delta; radius = m_Size.x; } start = aParent->GetABPosition( start ); end = aParent->GetABPosition( end ); if( !aFilledShape ) { GRCSegm( aClipBox, aDC, start.x, start.y, end.x, end.y, radius, aColor ); } else if( m_DrillShape == APT_DEF_NO_HOLE ) { GRFillCSegm( aClipBox, aDC, start.x, start.y, end.x, end.y, radius, aColor ); } else { if( m_Polygon.OutlineCount() == 0 ) ConvertShapeToPolygon(); DrawFlashedPolygon( aParent, aClipBox, aDC, aColor, aFilledShape, aShapePos ); } } break; case APT_POLYGON: if( m_Polygon.OutlineCount() == 0 ) ConvertShapeToPolygon(); DrawFlashedPolygon( aParent, aClipBox, aDC, aColor, aFilledShape, aShapePos ); break; } }
/** * Function DrawBasicShape * Draw the primitive shape for flashed items. */ void AM_PRIMITIVE::DrawBasicShape( GERBER_DRAW_ITEM* aParent, EDA_RECT* aClipBox, wxDC* aDC, EDA_COLOR_T aColor, EDA_COLOR_T aAltColor, wxPoint aShapePos, bool aFilledShape ) { static std::vector<wxPoint> polybuffer; // create a static buffer to avoid a lot of memory reallocation polybuffer.clear(); wxPoint curPos = aShapePos; D_CODE* tool = aParent->GetDcodeDescr(); double rotation; if( mapExposure( aParent ) == false ) { EXCHG(aColor, aAltColor); } switch( primitive_id ) { case AMP_CIRCLE: // Circle, given diameter and position { /* Generated by an aperture macro declaration like: * "1,1,0.3,0.5, 1.0*" * type (1), exposure, diameter, pos.x, pos.y * type is not stored in parameters list, so the first parameter is exposure */ curPos += mapPt( params[2].GetValue( tool ), params[3].GetValue( tool ), m_GerbMetric ); curPos = aParent->GetABPosition( curPos ); int radius = scaletoIU( params[1].GetValue( tool ), m_GerbMetric ) / 2; if( !aFilledShape ) GRCircle( aClipBox, aDC, curPos, radius, 0, aColor ); else GRFilledCircle( aClipBox, aDC, curPos, radius, aColor ); } break; case AMP_LINE2: case AMP_LINE20: // Line with rectangle ends. (Width, start and end pos + rotation) { /* Generated by an aperture macro declaration like: * "2,1,0.3,0,0, 0.5, 1.0,-135*" * 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( aParent, polybuffer ); // shape rotation: rotation = params[6].GetValue( tool ) * 10.0; if( rotation != 0) { for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) RotatePoint( &polybuffer[ii], -rotation ); } // Move to current position: for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) { polybuffer[ii] += curPos; polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); } GRClosedPoly( aClipBox, aDC, polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor ); } break; case AMP_LINE_CENTER: { /* Generated by an aperture macro declaration like: * "21,1,0.3,0.03,0,0,-135*" * 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( aParent, polybuffer ); // shape rotation: rotation = params[5].GetValue( tool ) * 10.0; if( rotation != 0 ) { for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) RotatePoint( &polybuffer[ii], -rotation ); } // Move to current position: for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) { polybuffer[ii] += curPos; polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); } GRClosedPoly( aClipBox, aDC, polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor ); } break; case AMP_LINE_LOWER_LEFT: { /* Generated by an aperture macro declaration like: * "22,1,0.3,0.03,0,0,-135*" * 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( aParent, polybuffer ); // shape rotation: rotation = params[5].GetValue( tool ) * 10.0; if( rotation != 0) { for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) RotatePoint( &polybuffer[ii], -rotation ); } // Move to current position: for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) { polybuffer[ii] += curPos; polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); } GRClosedPoly( aClipBox, aDC, polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor ); } break; case AMP_THERMAL: { /* Generated by an aperture macro declaration like: * "7, 0,0,1.0,0.3,0.01,-13*" * type (7), center.x , center.y, outside diam, inside diam, crosshair thickness, rotation * type is not stored in parameters list, so the first parameter is center.x */ curPos += mapPt( params[0].GetValue( tool ), params[1].GetValue( tool ), m_GerbMetric ); ConvertShapeToPolygon( aParent, polybuffer ); // shape rotation: rotation = params[5].GetValue( tool ) * 10.0; // Because a thermal shape has 4 identical sub-shapes, only one is created in polybuffer. // We must draw 4 sub-shapes rotated by 90 deg std::vector<wxPoint> subshape_poly; for( int ii = 0; ii < 4; ii++ ) { subshape_poly = polybuffer; double sub_rotation = rotation + 900 * ii; for( unsigned jj = 0; jj < subshape_poly.size(); jj++ ) RotatePoint( &subshape_poly[jj], -sub_rotation ); // Move to current position: for( unsigned jj = 0; jj < subshape_poly.size(); jj++ ) { subshape_poly[jj] += curPos; subshape_poly[jj] = aParent->GetABPosition( subshape_poly[jj] ); } GRClosedPoly( aClipBox, aDC, subshape_poly.size(), &subshape_poly[0], true, aAltColor, aAltColor ); } } break; case AMP_MOIRE: // A cross hair with n concentric circles { curPos += mapPt( params[0].GetValue( tool ), params[1].GetValue( tool ), m_GerbMetric ); /* Generated by an aperture macro declaration like: * "6,0,0,0.125,.01,0.01,3,0.003,0.150,0" * type(6), pos.x, pos.y, diam, penwidth, gap, circlecount, crosshair thickness, crosshaire len, rotation * type is not stored in parameters list, so the first parameter is pos.x */ int outerDiam = scaletoIU( params[2].GetValue( tool ), m_GerbMetric ); int penThickness = scaletoIU( params[3].GetValue( tool ), m_GerbMetric ); int gap = scaletoIU( params[4].GetValue( tool ), m_GerbMetric ); int numCircles = KiROUND( params[5].GetValue( tool ) ); // Draw circles: wxPoint center = aParent->GetABPosition( curPos ); // adjust outerDiam by this on each nested circle int diamAdjust = (gap + penThickness); //*2; //Should we use * 2 ? for( int i = 0; i < numCircles; ++i, outerDiam -= diamAdjust ) { if( outerDiam <= 0 ) break; if( !aFilledShape ) { // draw the border of the pen's path using two circles, each as narrow as possible GRCircle( aClipBox, aDC, center, outerDiam / 2, 0, aColor ); GRCircle( aClipBox, aDC, center, outerDiam / 2 - penThickness, 0, aColor ); } else // Filled mode { GRCircle( aClipBox, aDC, center, (outerDiam - penThickness) / 2, penThickness, aColor ); } } // Draw the cross: ConvertShapeToPolygon( aParent, polybuffer ); rotation = params[8].GetValue( tool ) * 10.0; for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) { // shape rotation: RotatePoint( &polybuffer[ii], -rotation ); // Move to current position: polybuffer[ii] += curPos; polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); } GRClosedPoly( aClipBox, aDC, polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor ); } break; case AMP_OUTLINE: { /* Generated by an aperture macro declaration like: * "4,1,3,0.0,0.0,0.0,0.5,0.5,0.5,0.5,0.0,-25" * type(4), exposure, corners count, corner1.x, corner.1y, ..., rotation * type is not stored in parameters list, so the first parameter is exposure */ int numPoints = (int) params[1].GetValue( tool ); rotation = params[numPoints * 2 + 4].GetValue( tool ) * 10.0; wxPoint pos; // Read points. numPoints does not include the starting point, so add 1. for( int i = 0; i<numPoints + 1; ++i ) { int jj = i * 2 + 2; pos.x = scaletoIU( params[jj].GetValue( tool ), m_GerbMetric ); pos.y = scaletoIU( params[jj + 1].GetValue( tool ), m_GerbMetric ); polybuffer.push_back(pos); } // rotate polygon and move it to the actual position // shape rotation: for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) { RotatePoint( &polybuffer[ii], -rotation ); } // Move to current position: for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) { polybuffer[ii] += curPos; polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); } GRClosedPoly( aClipBox, aDC, polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor ); } break; case AMP_POLYGON: // Is a regular polygon /* Generated by an aperture macro declaration like: * "5,1,0.6,0,0,0.5,25" * type(5), exposure, vertices count, pox.x, pos.y, diameter, rotation * type is not stored in parameters list, so the first parameter is exposure */ curPos += mapPt( params[2].GetValue( tool ), params[3].GetValue( tool ), m_GerbMetric ); // Creates the shape: ConvertShapeToPolygon( aParent, polybuffer ); // rotate polygon and move it to the actual position rotation = params[5].GetValue( tool ) * 10.0; for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) { RotatePoint( &polybuffer[ii], -rotation ); polybuffer[ii] += curPos; polybuffer[ii] = aParent->GetABPosition( polybuffer[ii] ); } GRClosedPoly( aClipBox, aDC, polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor ); break; case AMP_EOF: // not yet supported, waiting for you. break; case AMP_UNKNOWN: default: DBG( printf( "AM_PRIMITIVE::DrawBasicShape() err: unknown prim id %d\n",primitive_id) ); break; } }