Commit e0617666 authored by jean-pierre charras's avatar jean-pierre charras

added forgotten files

parent 659299ee
/****************************/
/* class_aperture_macro.cpp */
/****************************/
/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 1992-2010 Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
* Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 1992-2010 Kicad Developers, see change_log.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "fctsys.h"
#include "common.h"
#include "macros.h"
#include "trigo.h"
#include "gerbview.h"
/** helper Function mapPt
* translates a point from the aperture macro coordinate system to our
* deci-mils coordinate system.
* @return wxPoint - The gerbview coordinate system vector.
*/
extern wxPoint mapPt( double x, double y, bool isMetric ); // defined it rs274d.cpp
/**
* Function scale
* converts a distance given in floating point to our deci-mils
*/
extern int scale( double aCoord, bool isMetric ); // defined it rs274d.cpp
/** function DrawBasicShape
* Draw the primitive shape for flashed items.
*/
void AM_PRIMITIVE::DrawBasicShape( GERBER_DRAW_ITEM* aParent,
EDA_Rect* aClipBox,
wxDC* aDC,
int aColor,
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();
bool gerberMetric = aParent->m_UnitsMetric;
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 pos.x
*/
int exposure = params[0].GetValue( tool );
curPos += mapPt( params[2].GetValue( tool ), params[3].GetValue( tool ), gerberMetric );
int radius = scale( params[1].GetValue( tool ), gerberMetric ) / 2;
if( !aFilledShape )
GRCircle( aClipBox, aDC, curPos.x, curPos.y, radius, 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 pos.x
*/
int exposure = params[0].GetValue( tool );
ConvertShapeToPolygon(aParent, polybuffer, gerberMetric);
// shape rotation:
int rotation = wxRound(params[6].GetValue( tool ) * 10.0);
if (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;
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 pos.x
*/
int exposure = params[0].GetValue( tool );
ConvertShapeToPolygon(aParent, polybuffer, gerberMetric);
// shape rotation:
int rotation = wxRound(params[5].GetValue( tool ) * 10.0);
if (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;
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 pos.x
*/
int exposure = params[0].GetValue( tool );
ConvertShapeToPolygon(aParent, polybuffer, gerberMetric);
// shape rotation:
int rotation = wxRound(params[5].GetValue( tool ) * 10.0);
if (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;
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 pos.x
*/
ConvertShapeToPolygon(aParent, polybuffer, gerberMetric);
// shape rotation:
int rotation = wxRound(params[6].GetValue( tool ) * 10.0);
if (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;
GRClosedPoly( aClipBox, aDC, polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor );
printf(" AMP_THERMAL %d\n",polybuffer.size());
}
break;
case AMP_MOIRE: // A cross hair with n concentric circles
{
curPos += mapPt( params[0].GetValue( tool ), params[1].GetValue( tool ),
gerberMetric );
/* 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 = scale( params[2].GetValue( tool ), gerberMetric );
int penThickness = scale( params[3].GetValue( tool ), gerberMetric );
int gap = scale( params[4].GetValue( tool ), gerberMetric );
int numCircles = wxRound(params[5].GetValue( tool ));
// 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, curPos.x, curPos.y, outerDiam/2, 0, aColor );
GRCircle( aClipBox, aDC, curPos.x, curPos.y, outerDiam/2 - penThickness, 0, aColor );
}
else // Filled mode
{
GRCircle( aClipBox, aDC, curPos.x, curPos.y, (outerDiam-penThickness)/2, penThickness, aColor );
}
}
// Draw the cross:
ConvertShapeToPolygon(aParent, polybuffer, gerberMetric);
// shape rotation:
int rotation = wxRound(params[8].GetValue( tool ) * 10.0);
if (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;
GRClosedPoly( aClipBox, aDC, polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor );
}
break;
case AMP_OUTLINE:
#if defined(DEBUG)
{
int exposure = params[0].GetValue( tool );
int numPoints = (int) this->params[1].GetValue( tool );
int rotation = wxRound(params[numPoints * 2 + 4].GetValue( tool ) * 10.0);
printf( "AMP_OUTLINE:\n" );
printf( " exposure: %g\n", exposure );
printf( " # points: %d\n", numPoints );
// numPoints does not include the starting point, so add 1.
for( int i = 0; i<numPoints + 1; ++i )
{
printf( " [%d]: X=%g Y=%g\n", i,
this->params[i * 2 + 2 + 0].GetValue( tool ),
this->params[i * 2 + 2 + 1].GetValue( tool )
);
}
printf( " rotation: %g\n", (float)rotation/10 );
}
#endif
break;
case AMP_UNKNOWN:
case AMP_POLYGON:
case AMP_EOF:
default:
// not yet supported, waiting for you.
break;
}
}
/** function ConvertShapeToPolygon (virtual)
* convert a shape to an equivalent polygon.
* Arcs and circles are approximated by segments
* Useful when a shape is not a graphic primitive (shape with hole,
* rotated shape ... ) and cannot be easily drawn.
* note for some schapes conbining circles and solid lines (rectangles), only rectangles are 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 AM_PRIMITIVE::ConvertShapeToPolygon( GERBER_DRAW_ITEM* aParent, std::vector<wxPoint>& aBuffer, bool aUnitsMetric)
{
D_CODE* tool = aParent->GetDcodeDescr();
switch( primitive_id )
{
case AMP_CIRCLE: // Circle, currently convertion not needed
break;
case AMP_LINE2:
case AMP_LINE20: // Line with rectangle ends. (Width, start and end pos + rotation)
{
int width = scale( this->params[1].GetValue( tool ), aUnitsMetric );
wxPoint start = mapPt( this->params[2].GetValue( tool ),
this->params[3].GetValue( tool ), aUnitsMetric );
wxPoint end = mapPt( this->params[4].GetValue( tool ),
this->params[5].GetValue( tool ), aUnitsMetric );
wxPoint delta = end - start;
int len = wxRound(hypot(delta.x, delta.y));
// To build the polygon, we must create a horizonta polygon starting to "start"
// and rotate it to have it end point to "end"
wxPoint currpt;
currpt.y += width/2; // Upper left
aBuffer.push_back(currpt);
currpt.x = len; // Upper right
aBuffer.push_back(currpt);
currpt.y -= width; // lower right
aBuffer.push_back(currpt);
currpt.x = 0; // Upper left
aBuffer.push_back(currpt);
// Rotate rectangle and move it to the actual start point
int angle = wxRound( atan2(delta.y, delta.x) * 1800.0 / M_PI );
for( unsigned ii = 0; ii < 4; ii++ )
{
RotatePoint(&aBuffer[ii], -angle);
aBuffer[ii] += start;
NEGATE(aBuffer[ii].y);
}
}
break;
case AMP_LINE_CENTER:
{
wxPoint size = mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), aUnitsMetric );
wxPoint pos = mapPt( params[3].GetValue( tool ), params[4].GetValue( tool ), aUnitsMetric );
// Build poly:
pos.x -= size.x/2;
pos.y -= size.y/2; // Lower left
aBuffer.push_back(pos);
pos.y += size.y; // Upper left
aBuffer.push_back(pos);
pos.x += size.x; // Upper right
aBuffer.push_back(pos);
pos.y -= size.y; // lower right
aBuffer.push_back(pos);
}
break;
case AMP_LINE_LOWER_LEFT:
{
wxPoint size = mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), aUnitsMetric );
wxPoint lowerLeft = mapPt( params[3].GetValue( tool ), params[4].GetValue( tool ), aUnitsMetric );
// Build poly:
NEGATE(lowerLeft.y);
aBuffer.push_back(lowerLeft);
lowerLeft.y += size.y; // Upper left
aBuffer.push_back(lowerLeft);
lowerLeft.x += size.x; // Upper right
aBuffer.push_back(lowerLeft);
lowerLeft.y -= size.y; // lower right
aBuffer.push_back(lowerLeft);
// Negate y coordinates:
for( unsigned ii = 0; ii < aBuffer.size(); ii++ )
NEGATE(aBuffer[ii].y);
}
break;
case AMP_THERMAL:
{
int outerDiam = scale( this->params[2].GetValue( tool ), aUnitsMetric );
int innerDiam = scale( this->params[3].GetValue( tool ), aUnitsMetric );
}
break;
case AMP_MOIRE: // A cross hair with n concentric circles. Only the cros is build as polygon
// because circles can be drawn easily
{
int crossHairThickness = scale( this->params[6].GetValue( tool ), aUnitsMetric );
int crossHairLength = scale( this->params[7].GetValue( tool ), aUnitsMetric );
// Create cross. First create 1/4 of the shape.
// Others point are the same, totated by 90, 180 and 270 deg
wxPoint pos(crossHairThickness/2, crossHairLength/2);
aBuffer.push_back(pos);
pos.y = crossHairThickness/2;
aBuffer.push_back(pos);
pos.x = -crossHairLength/2;
aBuffer.push_back(pos);
pos.y = -crossHairThickness/2;
aBuffer.push_back(pos);
// Copy these 4 points, rotated by 90, 180 and 270 deg
for( int jj = 900; jj <= 2700; jj += 900 )
{
for( int ii = 0; ii < 4; ii++ )
{
pos = aBuffer[ii];
RotatePoint(&pos,jj);
aBuffer.push_back(pos);
}
}
}
break;
case AMP_UNKNOWN:
case AMP_OUTLINE:
case AMP_POLYGON:
case AMP_EOF:
break;
}
}
/** function DrawApertureMacroShape
* Draw the primitive shape for flashed items.
* When an item is flashed, this is the shape of the item
*/
void APERTURE_MACRO::DrawApertureMacroShape( GERBER_DRAW_ITEM* aParent,
EDA_Rect* aClipBox,
wxDC* aDC,
int aColor,
wxPoint aShapePos,
bool aFilledShape )
{
for( AM_PRIMITIVES::iterator prim_macro = primitives.begin();
prim_macro != primitives.end(); ++prim_macro )
{
prim_macro->DrawBasicShape( aParent, aClipBox, aDC, aColor, aShapePos, aFilledShape );
}
}
/**************************/
/* class_aperture_macro.h */
/**************************/
#ifndef _APERTURE_MACRO_H_
#define _APERTURE_MACRO_H_
/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 1992-2010 Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
* Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 1992-2010 Kicad Developers, see change_log.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <vector>
#include <set>
#include "base_struct.h"
/**
* Enum AM_PRIMITIVE_ID
* is the set of all "aperture macro primitives" (primitive numbers). See
* Table 3 in http://gerbv.sourceforge.net/docs/rs274xrevd_e.pdf
* aperture macro primitives are basic shapes which can be combined to create a complex shape
* This complex shape is flashed.
*/
enum AM_PRIMITIVE_ID {
AMP_UNKNOWN = 0, // A value for uninitialized AM_PRIMITIVE.
AMP_CIRCLE = 1, // Circle. (diameter and position)
AMP_LINE2 = 2, // Line with rectangle ends. (Width, start and end pos + rotation)
AMP_LINE20 = 20, // Same as AMP_LINE2
AMP_LINE_CENTER = 21, // Rectangle. (height, width and center pos + rotation)
AMP_LINE_LOWER_LEFT = 22, // Rectangle. (height, width and left bottom corner pos + rotation)
AMP_EOF = 3, // End Of File marquer: not really a shape
AMP_OUTLINE = 4, // Free polyline (n corners + rotation)
AMP_POLYGON = 5, // Closed regular polygon(diameter, number of vertices (3 to 10), rotation)
AMP_MOIRE = 6, // A cross hair with n concentric circles + rotation
AMP_THERMAL = 7, // Thermal shape (pos, outer and inner diameter, cross hair thickness + rotation)
};
/**
* Struct AM_PRIMITIVE
* holds an aperture macro primitive as given in Table 3 of
* http://gerbv.sourceforge.net/docs/rs274xrevd_e.pdf
*/
class AM_PRIMITIVE
{
public:
AM_PRIMITIVE_ID primitive_id; ///< The primitive type
DCODE_PARAMS params; ///< A sequence of parameters used by
// the primitive
public:
AM_PRIMITIVE( AM_PRIMITIVE_ID aId = AMP_UNKNOWN )
{
primitive_id = aId;
}
~AM_PRIMITIVE() {}
/**
* Function GetExposure
* returns the first parameter in integer form. Some but not all primitives
* use the first parameter as an exposure control.
*/
int GetExposure() const
{
// No D_CODE* for GetValue()
wxASSERT( params.size() && params[0].IsImmediate() );
return (int) params[0].GetValue( NULL );
}
/* Draw functions: */
/** function DrawBasicShape
* Draw the primitive shape for flashed items.
*/
void DrawBasicShape( GERBER_DRAW_ITEM* aParent, EDA_Rect* aClipBox, wxDC* aDC,
int aColor, wxPoint aShapePos, bool aFilledShape );
private:
/** function ConvertShapeToPolygon
* convert a shape to an equivalent polygon.
* Arcs and circles are approximated by segments
* Useful when a shape is not a graphic primitive (shape with hole,
* rotated shape ... ) and cannot be easily drawn.
*/
void ConvertShapeToPolygon( GERBER_DRAW_ITEM* aParent, std::vector<wxPoint>& aBuffer, bool aUnitsMetric);
};
typedef std::vector<AM_PRIMITIVE> AM_PRIMITIVES;
/**
* Struct APERTURE_MACRO
* helps support the "aperture macro" defined within standard RS274X.
*/
struct APERTURE_MACRO
{
wxString name; ///< The name of the aperture macro
AM_PRIMITIVES primitives; ///< A sequence of AM_PRIMITIVEs
/** function DrawApertureMacroShape
* Draw the primitive shape for flashed items.
* When an item is flashed, this is the shape of the item
*/
void DrawApertureMacroShape( GERBER_DRAW_ITEM* aParent, EDA_Rect* aClipBox, wxDC* aDC,
int aColor, wxPoint aShapePos, bool aFilledShape );
};
/**
* Struct APERTURE_MACRO_less_than
* is used by std:set<APERTURE_MACRO> instantiation which uses
* APERTURE_MACRO.name as its key.
*/
struct APERTURE_MACRO_less_than
{
// a "less than" test on two APERTURE_MACROs (.name wxStrings)
bool operator()( const APERTURE_MACRO& am1, const APERTURE_MACRO& am2 ) const
{
return am1.name.Cmp( am2.name ) < 0; // case specific wxString compare
}
};
/**
* Type APERTURE_MACRO_SET
* is a sorted collection of APERTURE_MACROS whose key is the name field in
* the APERTURE_MACRO.
*/
typedef std::set<APERTURE_MACRO, APERTURE_MACRO_less_than> APERTURE_MACRO_SET;
typedef std::pair<APERTURE_MACRO_SET::iterator, bool> APERTURE_MACRO_SET_PAIR;
#endif // ifndef _APERTURE_MACRO_H_
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment