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

added forgotten files

parent 659299ee
Loading
Loading
Loading
Loading
+408 −0
Original line number Diff line number Diff line
/****************************/
/* 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 );
    }
}
+159 −0
Original line number Diff line number Diff line
/**************************/
/* 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_