~lexaficus/kicad/python-se

« back to all changes in this revision

Viewing changes to gerbview/class_aperture_macro.cpp

  • Committer: jean-pierre charras
  • Date: 2010-10-03 15:40:54 UTC
  • mfrom: (2511.1.3 testing)
  • Revision ID: jp.charras@wanadoo.fr-20101003154054-xugf6sg2dqs3i8pa
finished Draw functions for aperture macros.  Now aperture macros are drawn correctly.  Known bug: aperture macros having parameters are incorrect: parameters are not read correctly. Work still in progress.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************/
 
2
/* class_aperture_macro.cpp */
 
3
/****************************/
 
4
 
 
5
 
 
6
/*
 
7
 * This program source code file is part of KICAD, a free EDA CAD application.
 
8
 *
 
9
 * Copyright (C) 1992-2010 Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
 
10
 * Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
 
11
 * Copyright (C) 1992-2010 Kicad Developers, see change_log.txt for contributors.
 
12
 *
 
13
 * This program is free software; you can redistribute it and/or
 
14
 * modify it under the terms of the GNU General Public License
 
15
 * as published by the Free Software Foundation; either version 2
 
16
 * of the License, or (at your option) any later version.
 
17
 *
 
18
 * This program is distributed in the hope that it will be useful,
 
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
21
 * GNU General Public License for more details.
 
22
 *
 
23
 * You should have received a copy of the GNU General Public License
 
24
 * along with this program; if not, you may find one here:
 
25
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 
26
 * or you may search the http://www.gnu.org website for the version 2 license,
 
27
 * or you may write to the Free Software Foundation, Inc.,
 
28
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 
29
 */
 
30
 
 
31
#include "fctsys.h"
 
32
#include "common.h"
 
33
#include "macros.h"
 
34
#include "trigo.h"
 
35
#include "gerbview.h"
 
36
 
 
37
/** helper Function mapPt
 
38
 * translates a point from the aperture macro coordinate system to our
 
39
 * deci-mils coordinate system.
 
40
 * @return wxPoint - The gerbview coordinate system vector.
 
41
 */
 
42
extern wxPoint mapPt( double x, double y, bool isMetric );  // defined it rs274d.cpp
 
43
 
 
44
/**
 
45
 * Function scale
 
46
 * converts a distance given in floating point to our deci-mils
 
47
 */
 
48
extern int     scale( double aCoord, bool isMetric );       // defined it rs274d.cpp
 
49
 
 
50
 
 
51
/**
 
52
 * Function mapExposure
 
53
 * translates the first parameter from an aperture macro into a current
 
54
 * exposure setting.
 
55
 * @param aParent = a GERBER_DRAW_ITEM that handle:
 
56
 *    ** m_Exposure A dynamic setting which can change throughout the
 
57
 *          reading of the gerber file, and it indicates whether the current tool
 
58
 *          is lit or not.
 
59
 *    ** m_ImageNegative A dynamic setting which can change throughout the reading
 
60
 *          of the gerber file, and it indicates whether the current D codes are to
 
61
 *          be interpreted as erasures or not.
 
62
 * @return true to draw with current color, false to draw with alt color (erase)
 
63
 */
 
64
bool AM_PRIMITIVE::mapExposure( GERBER_DRAW_ITEM* aParent )
 
65
{
 
66
    bool exposure;
 
67
    switch( primitive_id )
 
68
    {
 
69
    case AMP_CIRCLE:
 
70
    case AMP_LINE2:
 
71
    case AMP_LINE20:
 
72
    case AMP_LINE_CENTER:
 
73
    case AMP_LINE_LOWER_LEFT:
 
74
    case AMP_OUTLINE:
 
75
    case AMP_THERMAL:
 
76
    case AMP_POLYGON:
 
77
        // All have an exposure parameter and can return true or false
 
78
        switch( GetExposure() )
 
79
        {
 
80
        case 0:     // exposure always OFF
 
81
            exposure = false;
 
82
            break;
 
83
 
 
84
        default:
 
85
        case 1:     // exposure always OON
 
86
            exposure = true;
 
87
            break;
 
88
 
 
89
        case 2:     // reverse exposure
 
90
            exposure = !aParent->m_LayerNegative;
 
91
        }
 
92
        break;
 
93
 
 
94
    case AMP_MOIRE:
 
95
    case AMP_EOF:
 
96
    case AMP_UNKNOWN:
 
97
    default:
 
98
        return true;    // All have no exposure parameter and must return true (no change for exposure)
 
99
        break;
 
100
    }
 
101
 
 
102
    return exposure ^ aParent->m_ImageNegative;
 
103
}
 
104
 
 
105
 
 
106
/**
 
107
 * Function GetExposure
 
108
 * returns the first parameter in integer form.  Some but not all primitives
 
109
 * use the first parameter as an exposure control.
 
110
 */
 
111
int AM_PRIMITIVE::GetExposure() const
 
112
{
 
113
    // No D_CODE* for GetValue()
 
114
    wxASSERT( params.size() && params[0].IsImmediate() );
 
115
    return (int) params[0].GetValue( NULL );
 
116
}
 
117
 
 
118
/** function DrawBasicShape
 
119
 * Draw the primitive shape for flashed items.
 
120
 */
 
121
void AM_PRIMITIVE::DrawBasicShape( GERBER_DRAW_ITEM* aParent,
 
122
                                   EDA_Rect* aClipBox,
 
123
                                   wxDC* aDC,
 
124
                                   int aColor, int aAltColor,
 
125
                                   wxPoint aShapePos,
 
126
                                   bool aFilledShape )
 
127
{
 
128
    static std::vector<wxPoint> polybuffer;     // create a static buffer to avoid a lot of memory reallocation
 
129
    polybuffer.clear();
 
130
 
 
131
    wxPoint curPos = aShapePos;
 
132
    D_CODE* tool   = aParent->GetDcodeDescr();
 
133
    bool    gerberMetric = aParent->m_UnitsMetric;
 
134
    int rotation;
 
135
    if( mapExposure( aParent ) == false )
 
136
    {
 
137
        EXCHG(aColor, aAltColor);
 
138
    }
 
139
 
 
140
    switch( primitive_id )
 
141
    {
 
142
    case AMP_CIRCLE:        // Circle, given diameter and position
 
143
    {
 
144
        /* Generated by an aperture macro declaration like:
 
145
         * "1,1,0.3,0.5, 1.0*"
 
146
         * type (1), exposure, diameter, pos.x, pos.y
 
147
         * type is not stored in parameters list, so the first parameter is exposure
 
148
         */
 
149
        curPos += mapPt( params[2].GetValue( tool ), params[3].GetValue( tool ), gerberMetric );
 
150
        int radius = scale( params[1].GetValue( tool ), gerberMetric ) / 2;
 
151
        if( !aFilledShape )
 
152
            GRCircle( aClipBox, aDC, curPos.x, curPos.y, radius, aColor );
 
153
        else
 
154
            GRFilledCircle( aClipBox, aDC, curPos, radius, aColor );
 
155
    }
 
156
    break;
 
157
 
 
158
    case AMP_LINE2:
 
159
    case AMP_LINE20:        // Line with rectangle ends. (Width, start and end pos + rotation)
 
160
    {
 
161
        /* Generated by an aperture macro declaration like:
 
162
         * "2,1,0.3,0,0, 0.5, 1.0,-135*"
 
163
         * type (2), exposure, width, start.x, start.y, end.x, end.y, rotation
 
164
         * type is not stored in parameters list, so the first parameter is exposure
 
165
         */
 
166
        ConvertShapeToPolygon( aParent, polybuffer, gerberMetric );
 
167
 
 
168
        // shape rotation:
 
169
        rotation = wxRound( params[6].GetValue( tool ) * 10.0 );
 
170
        if( rotation )
 
171
        {
 
172
            for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
 
173
                RotatePoint( &polybuffer[ii], rotation );
 
174
        }
 
175
 
 
176
        // Move to current position:
 
177
        for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
 
178
            polybuffer[ii] += curPos;
 
179
 
 
180
        GRClosedPoly( aClipBox, aDC,
 
181
                      polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor );
 
182
    }
 
183
    break;
 
184
 
 
185
    case AMP_LINE_CENTER:
 
186
    {
 
187
        /* Generated by an aperture macro declaration like:
 
188
         * "21,1,0.3,0.03,0,0,-135*"
 
189
         * type (21), exposure, ,width, height, center pos.x, center pos.y, rotation
 
190
         * type is not stored in parameters list, so the first parameter is exposure
 
191
         */
 
192
        ConvertShapeToPolygon( aParent, polybuffer, gerberMetric );
 
193
 
 
194
        // shape rotation:
 
195
        rotation = wxRound( params[5].GetValue( tool ) * 10.0 );
 
196
        if( rotation )
 
197
        {
 
198
            for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
 
199
                RotatePoint( &polybuffer[ii], rotation );
 
200
        }
 
201
 
 
202
        // Move to current position:
 
203
        for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
 
204
            polybuffer[ii] += curPos;
 
205
 
 
206
        GRClosedPoly( aClipBox, aDC,
 
207
                      polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor );
 
208
    }
 
209
    break;
 
210
 
 
211
    case AMP_LINE_LOWER_LEFT:
 
212
    {
 
213
        /* Generated by an aperture macro declaration like:
 
214
         * "22,1,0.3,0.03,0,0,-135*"
 
215
         * type (22), exposure, ,width, height, corner pos.x, corner pos.y, rotation
 
216
         * type is not stored in parameters list, so the first parameter is exposure
 
217
         */
 
218
        ConvertShapeToPolygon( aParent, polybuffer, gerberMetric );
 
219
 
 
220
        // shape rotation:
 
221
        rotation = wxRound( params[5].GetValue( tool ) * 10.0 );
 
222
        if( rotation )
 
223
        {
 
224
            for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
 
225
                RotatePoint( &polybuffer[ii], rotation );
 
226
        }
 
227
 
 
228
        // Move to current position:
 
229
        for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
 
230
            polybuffer[ii] += curPos;
 
231
 
 
232
        GRClosedPoly( aClipBox, aDC,
 
233
                      polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor );
 
234
    }
 
235
    break;
 
236
 
 
237
    case AMP_THERMAL:
 
238
    {
 
239
        /* Generated by an aperture macro declaration like:
 
240
         * "7, 0,0,1.0,0.3,0.01,-13*"
 
241
         * type (7), center.x , center.y, outside diam, inside diam, crosshair thickness, rotation
 
242
         * type is not stored in parameters list, so the first parameter is center.x
 
243
         */
 
244
        curPos += mapPt( params[0].GetValue( tool ), params[1].GetValue( tool ), gerberMetric );
 
245
/*        int outerRadius   = scale( params[2].GetValue( tool ), gerberMetric ) / 2;
 
246
        if( !aFilledShape )
 
247
            GRCircle( aClipBox, aDC, curPos.x, curPos.y, outerRadius, aColor );
 
248
        else
 
249
            GRFilledCircle( aClipBox, aDC, curPos, outerRadius, aColor );
 
250
*/
 
251
        ConvertShapeToPolygon( aParent, polybuffer, gerberMetric );
 
252
 
 
253
        // shape rotation:
 
254
        rotation = wxRound( params[5].GetValue( tool ) * 10.0 );
 
255
 
 
256
        // Because a thermal shape has 4 identical sub-shapes, only one is created in polybuffer.
 
257
        // We must draw 4 sub-shapes rotated by 90 deg
 
258
        std::vector<wxPoint> subshape_poly;
 
259
        for( int ii = 0; ii < 4; ii++ )
 
260
        {
 
261
            subshape_poly = polybuffer;
 
262
            int sub_rotation = rotation + 900 * ii;
 
263
            for( unsigned jj = 0; jj < subshape_poly.size(); jj++ )
 
264
                RotatePoint( &subshape_poly[jj], sub_rotation );
 
265
 
 
266
            // Move to current position:
 
267
            for( unsigned jj = 0; jj < subshape_poly.size(); jj++ )
 
268
                subshape_poly[jj] += curPos;
 
269
 
 
270
            GRClosedPoly( aClipBox, aDC,
 
271
                          subshape_poly.size(), &subshape_poly[0], true, aAltColor,
 
272
                          aAltColor );
 
273
        }
 
274
    }
 
275
    break;
 
276
 
 
277
    case AMP_MOIRE:     // A cross hair with n concentric circles
 
278
    {
 
279
        curPos += mapPt( params[0].GetValue( tool ), params[1].GetValue( tool ),
 
280
                         gerberMetric );
 
281
 
 
282
        /* Generated by an aperture macro declaration like:
 
283
         * "6,0,0,0.125,.01,0.01,3,0.003,0.150,0"
 
284
         * type(6), pos.x, pos.y, diam, penwidth, gap, circlecount, crosshair thickness, crosshaire len, rotation
 
285
         * type is not stored in parameters list, so the first parameter is pos.x
 
286
         */
 
287
        int outerDiam    = scale( params[2].GetValue( tool ), gerberMetric );
 
288
        int penThickness = scale( params[3].GetValue( tool ), gerberMetric );
 
289
        int gap = scale( params[4].GetValue( tool ), gerberMetric );
 
290
        int numCircles = wxRound( params[5].GetValue( tool ) );
 
291
 
 
292
        // adjust outerDiam by this on each nested circle
 
293
        int diamAdjust = (gap + penThickness); //*2;     //Should we use * 2 ?
 
294
        for( int i = 0; i < numCircles; ++i, outerDiam -= diamAdjust )
 
295
        {
 
296
            if( outerDiam <= 0 )
 
297
                break;
 
298
            if( !aFilledShape )
 
299
            {
 
300
                // draw the border of the pen's path using two circles, each as narrow as possible
 
301
                GRCircle( aClipBox, aDC, curPos.x, curPos.y, outerDiam / 2, 0, aColor );
 
302
                GRCircle( aClipBox, aDC, curPos.x, curPos.y,
 
303
                          outerDiam / 2 - penThickness, 0, aColor );
 
304
            }
 
305
            else    // Filled mode
 
306
            {
 
307
                GRCircle( aClipBox, aDC, curPos.x, curPos.y,
 
308
                          (outerDiam - penThickness) / 2, penThickness, aColor );
 
309
            }
 
310
        }
 
311
 
 
312
        // Draw the cross:
 
313
        ConvertShapeToPolygon( aParent, polybuffer, gerberMetric );
 
314
 
 
315
        // shape rotation:
 
316
        rotation = wxRound( params[8].GetValue( tool ) * 10.0 );
 
317
        if( rotation )
 
318
        {
 
319
            for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
 
320
                RotatePoint( &polybuffer[ii], rotation );
 
321
        }
 
322
 
 
323
        // Move to current position:
 
324
        for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
 
325
            polybuffer[ii] += curPos;
 
326
 
 
327
        GRClosedPoly( aClipBox, aDC,
 
328
                      polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor );
 
329
    }
 
330
    break;
 
331
 
 
332
    case AMP_OUTLINE:
 
333
    {
 
334
        /* Generated by an aperture macro declaration like:
 
335
         * "4,1,3,0.0,0.0,0.0,0.5,0.5,0.5,0.5,0.0,-25"
 
336
         * type(4), exposure, corners count, corner1.x, corner.1y, ..., rotation
 
337
         * type is not stored in parameters list, so the first parameter is exposure
 
338
         */
 
339
        int numPoints = (int) params[1].GetValue( tool );
 
340
        rotation  = wxRound( params[numPoints * 2 + 4].GetValue( tool ) * 10.0 );
 
341
        wxPoint pos;
 
342
        // Read points. numPoints does not include the starting point, so add 1.
 
343
        for( int i = 0; i<numPoints + 1; ++i )
 
344
        {
 
345
            int jj = i * 2 + 2;
 
346
            pos.x = scale( params[jj].GetValue( tool ), gerberMetric );
 
347
            pos.y = scale( params[jj + 1].GetValue( tool ), gerberMetric );
 
348
            polybuffer.push_back(pos);
 
349
        }
 
350
        // rotate polygon and move it to the actual position
 
351
        // shape rotation:
 
352
        for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
 
353
        {
 
354
            NEGATE(polybuffer[ii].y);
 
355
            RotatePoint( &polybuffer[ii], rotation );
 
356
       }
 
357
 
 
358
        // Move to current position:
 
359
        for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
 
360
            polybuffer[ii] += curPos;
 
361
 
 
362
        GRClosedPoly( aClipBox, aDC,
 
363
                      polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor );
 
364
    }
 
365
    break;
 
366
 
 
367
    case AMP_POLYGON:   // Is a regular polygon
 
368
        /* Generated by an aperture macro declaration like:
 
369
         * "5,1,0.6,0,0,0.5,25"
 
370
         * type(5), exposure, vertices count, pox.x, pos.y, diameter, rotation
 
371
         * type is not stored in parameters list, so the first parameter is exposure
 
372
         */
 
373
        curPos += mapPt( params[2].GetValue( tool ), params[3].GetValue( tool ),
 
374
                         gerberMetric );
 
375
        // Creates the shape:
 
376
        ConvertShapeToPolygon( aParent, polybuffer, gerberMetric );
 
377
 
 
378
        // rotate polygon and move it to the actual position
 
379
        rotation  = wxRound( params[5].GetValue( tool ) * 10.0 );
 
380
        for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
 
381
        {
 
382
            NEGATE(polybuffer[ii].y);
 
383
            RotatePoint( &polybuffer[ii], rotation );
 
384
            polybuffer[ii] += curPos;
 
385
        }
 
386
        GRClosedPoly( aClipBox, aDC,
 
387
                      polybuffer.size(), &polybuffer[0], aFilledShape, aColor, aColor );
 
388
        break;
 
389
 
 
390
    case AMP_EOF:
 
391
        // not yet supported, waiting for you.
 
392
        break;
 
393
 
 
394
    case AMP_UNKNOWN:
 
395
    default:
 
396
        D( printf( "AM_PRIMITIVE::DrawBasicShape() err: unknown prim id %d\n",primitive_id) );
 
397
        break;
 
398
    }
 
399
}
 
400
 
 
401
 
 
402
/** function ConvertShapeToPolygon (virtual)
 
403
 * convert a shape to an equivalent polygon.
 
404
 * Arcs and circles are approximated by segments
 
405
 * Useful when a shape is not a graphic primitive (shape with hole,
 
406
 * rotated shape ... ) and cannot be easily drawn.
 
407
 * note for some schapes conbining circles and solid lines (rectangles), only rectangles are converted
 
408
 * because circles are very easy to draw (no rotation problem) so convert them in polygons,
 
409
 * and draw them as polygons is not a good idea.
 
410
 */
 
411
void AM_PRIMITIVE::ConvertShapeToPolygon( GERBER_DRAW_ITEM*     aParent,
 
412
                                          std::vector<wxPoint>& aBuffer,
 
413
                                          bool                  aUnitsMetric )
 
414
{
 
415
    D_CODE* tool = aParent->GetDcodeDescr();
 
416
 
 
417
    switch( primitive_id )
 
418
    {
 
419
    case AMP_CIRCLE:        // Circle, currently convertion not needed
 
420
        break;
 
421
 
 
422
    case AMP_LINE2:
 
423
    case AMP_LINE20:        // Line with rectangle ends. (Width, start and end pos + rotation)
 
424
    {
 
425
        int     width = scale( params[1].GetValue( tool ), aUnitsMetric );
 
426
        wxPoint start = mapPt( params[2].GetValue( tool ),
 
427
                               params[3].GetValue( tool ), aUnitsMetric );
 
428
        wxPoint end = mapPt( params[4].GetValue( tool ),
 
429
                             params[5].GetValue( tool ), aUnitsMetric );
 
430
        wxPoint delta = end - start;
 
431
        int     len   = wxRound( hypot( delta.x, delta.y ) );
 
432
 
 
433
        // To build the polygon, we must create a horizonta polygon starting to "start"
 
434
        // and rotate it to have it end point to "end"
 
435
        wxPoint currpt;
 
436
        currpt.y += width / 2;          // Upper left
 
437
        aBuffer.push_back( currpt );
 
438
        currpt.x = len;                 // Upper right
 
439
        aBuffer.push_back( currpt );
 
440
        currpt.y -= width;              // lower right
 
441
        aBuffer.push_back( currpt );
 
442
        currpt.x = 0;                   // Upper left
 
443
        aBuffer.push_back( currpt );
 
444
 
 
445
        // Rotate rectangle and move it to the actual start point
 
446
        int angle = wxRound( atan2( delta.y, delta.x ) * 1800.0 / M_PI );
 
447
        for( unsigned ii = 0; ii < 4; ii++ )
 
448
        {
 
449
            RotatePoint( &aBuffer[ii], -angle );
 
450
            aBuffer[ii] += start;
 
451
            NEGATE( aBuffer[ii].y );
 
452
        }
 
453
    }
 
454
    break;
 
455
 
 
456
    case AMP_LINE_CENTER:
 
457
    {
 
458
        wxPoint size = mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), aUnitsMetric );
 
459
        wxPoint pos  = mapPt( params[3].GetValue( tool ), params[4].GetValue( tool ), aUnitsMetric );
 
460
 
 
461
        // Build poly:
 
462
        pos.x -= size.x / 2;
 
463
        pos.y -= size.y / 2;        // Lower left
 
464
        aBuffer.push_back( pos );
 
465
        pos.y += size.y;            // Upper left
 
466
        aBuffer.push_back( pos );
 
467
        pos.x += size.x;            // Upper right
 
468
        aBuffer.push_back( pos );
 
469
        pos.y -= size.y;            // lower right
 
470
        aBuffer.push_back( pos );
 
471
    }
 
472
    break;
 
473
 
 
474
    case AMP_LINE_LOWER_LEFT:
 
475
    {
 
476
        wxPoint size = mapPt( params[1].GetValue( tool ), params[2].GetValue( tool ), aUnitsMetric );
 
477
        wxPoint lowerLeft = mapPt( params[3].GetValue( tool ), params[4].GetValue(
 
478
                                       tool ), aUnitsMetric );
 
479
 
 
480
        // Build poly:
 
481
        NEGATE( lowerLeft.y );
 
482
        aBuffer.push_back( lowerLeft );
 
483
        lowerLeft.y += size.y;          // Upper left
 
484
        aBuffer.push_back( lowerLeft );
 
485
        lowerLeft.x += size.x;          // Upper right
 
486
        aBuffer.push_back( lowerLeft );
 
487
        lowerLeft.y -= size.y;          // lower right
 
488
        aBuffer.push_back( lowerLeft );
 
489
 
 
490
        // Negate y coordinates:
 
491
        for( unsigned ii = 0; ii < aBuffer.size(); ii++ )
 
492
            NEGATE( aBuffer[ii].y );
 
493
    }
 
494
    break;
 
495
 
 
496
    case AMP_THERMAL:
 
497
    {
 
498
        // Only 1/4 of the full shape is built, because the other 3 shapes will be draw from this first
 
499
        // rotated by 90, 180 and 270 deg.
 
500
        // params = center.x (unused here), center.y (unused here), outside diam, inside diam, crosshair thickness
 
501
        int outerRadius   = scale( params[2].GetValue( tool ), aUnitsMetric ) / 2;
 
502
        int innerRadius   = scale( params[3].GetValue( tool ), aUnitsMetric ) / 2;
 
503
        int halfthickness = scale( params[4].GetValue( tool ), aUnitsMetric ) / 2;
 
504
        int angle_start   = wxRound( asin(
 
505
                                         (double) halfthickness / innerRadius ) * 1800 / M_PI );
 
506
 
 
507
        // Draw shape in the first cadrant (X and Y > 0)
 
508
        wxPoint pos, startpos;
 
509
 
 
510
        // Inner arc
 
511
        startpos.x = innerRadius;
 
512
        int angle_end = 900 - angle_start;
 
513
        int angle;
 
514
        for( angle = angle_start; angle < angle_end; angle += 100 )
 
515
        {
 
516
            pos = startpos;
 
517
            RotatePoint( &pos, angle );
 
518
            aBuffer.push_back( pos );
 
519
        }
 
520
 
 
521
        // Last point
 
522
        pos = startpos;
 
523
        RotatePoint( &pos, angle_end );
 
524
        aBuffer.push_back( pos );
 
525
 
 
526
        // outer arc
 
527
        startpos.x  = outerRadius;
 
528
        startpos.y  = 0;
 
529
        angle_start = wxRound( asin( (double) halfthickness / outerRadius ) * 1800 / M_PI );
 
530
        angle_end   = 900 - angle_start;
 
531
 
 
532
        // First point, near Y axis, outer arc
 
533
        for( angle = angle_end; angle > angle_start; angle -= 100 )
 
534
        {
 
535
            pos = startpos;
 
536
            RotatePoint( &pos, angle );
 
537
            aBuffer.push_back( pos );
 
538
        }
 
539
 
 
540
        // last point
 
541
        pos = startpos;
 
542
        RotatePoint( &pos, angle_start );
 
543
        aBuffer.push_back( pos );
 
544
 
 
545
        aBuffer.push_back( aBuffer[0] );  // Close poly
 
546
    }
 
547
    break;
 
548
 
 
549
    case AMP_MOIRE:     // A cross hair with n concentric circles. Only the cros is build as polygon
 
550
                        // because circles can be drawn easily
 
551
    {
 
552
        int crossHairThickness = scale( params[6].GetValue( tool ), aUnitsMetric );
 
553
        int crossHairLength    = scale( params[7].GetValue( tool ), aUnitsMetric );
 
554
 
 
555
        // Create cross. First create 1/4 of the shape.
 
556
        // Others point are the same, totated by 90, 180 and 270 deg
 
557
        wxPoint pos( crossHairThickness / 2, crossHairLength / 2 );
 
558
        aBuffer.push_back( pos );
 
559
        pos.y = crossHairThickness / 2;
 
560
        aBuffer.push_back( pos );
 
561
        pos.x = -crossHairLength / 2;
 
562
        aBuffer.push_back( pos );
 
563
        pos.y = -crossHairThickness / 2;
 
564
        aBuffer.push_back( pos );
 
565
 
 
566
        // Copy the 4 shape, rotated by 90, 180 and 270 deg
 
567
        for( int jj = 900; jj <= 2700; jj += 900 )
 
568
        {
 
569
            for( int ii = 0; ii < 4; ii++ )
 
570
            {
 
571
                pos = aBuffer[ii];
 
572
                RotatePoint( &pos, jj );
 
573
                aBuffer.push_back( pos );
 
574
            }
 
575
        }
 
576
    }
 
577
    break;
 
578
 
 
579
    case AMP_OUTLINE:
 
580
        // already is a polygon. Do nothing
 
581
        break;
 
582
 
 
583
    case AMP_POLYGON:   // Creates a regular polygon
 
584
    {
 
585
        int vertexcount = wxRound( params[1].GetValue( tool ) );
 
586
        int radius    = scale( params[4].GetValue( tool ), aUnitsMetric ) / 2;
 
587
        // rs274x said: vertex count = 3 ... 10, and the first corner is on the X axis
 
588
        if( vertexcount < 3 )
 
589
            vertexcount = 3;
 
590
        if( vertexcount > 10 )
 
591
            vertexcount = 10;
 
592
        for( int ii = 0; ii <= vertexcount; ii++ )
 
593
        {
 
594
            wxPoint pos( radius, 0);
 
595
            RotatePoint( &pos, ii * 3600 / vertexcount );
 
596
            aBuffer.push_back( pos );
 
597
        }
 
598
    }
 
599
        break;
 
600
 
 
601
    case AMP_UNKNOWN:
 
602
    case AMP_EOF:
 
603
        break;
 
604
    }
 
605
}
 
606
 
 
607
 
 
608
/** function DrawApertureMacroShape
 
609
 * Draw the primitive shape for flashed items.
 
610
 * When an item is flashed, this is the shape of the item
 
611
 */
 
612
void APERTURE_MACRO::DrawApertureMacroShape( GERBER_DRAW_ITEM* aParent,
 
613
                                             EDA_Rect* aClipBox, wxDC* aDC,
 
614
                                             int aColor, int aAltColor,
 
615
                                             wxPoint aShapePos, bool aFilledShape )
 
616
{
 
617
    for( AM_PRIMITIVES::iterator prim_macro = primitives.begin();
 
618
         prim_macro != primitives.end(); ++prim_macro )
 
619
    {
 
620
        prim_macro->DrawBasicShape( aParent, aClipBox, aDC,
 
621
                                    aColor, aAltColor,
 
622
                                    aShapePos,
 
623
                                    aFilledShape );
 
624
    }
 
625
}