Gerber, aperture macros: use different apertures primitives in macro defs.
To avoid issues with broken Gerber readers use aperture macros with shapes without rotation when more than one primitive is required. In many gerber readers, rotation of a set of primitives is broken (do not follow Gerber requirements)
This commit is contained in:
parent
728c207105
commit
61f1f7d948
|
@ -40,7 +40,10 @@
|
||||||
// if GBR_USE_MACROS is defined, pads having a shape that is not a Gerber primitive
|
// if GBR_USE_MACROS is defined, pads having a shape that is not a Gerber primitive
|
||||||
// will use a macro when possible
|
// will use a macro when possible
|
||||||
// Old code will be removed only after many tests
|
// Old code will be removed only after many tests
|
||||||
// #define GBR_USE_MACROS
|
#define GBR_USE_MACROS_FOR_ROUNDRECT
|
||||||
|
#define GBR_USE_MACROS_FOR_TRAPEZOID
|
||||||
|
#define GBR_USE_MACROS_FOR_ROTATED_OVAL
|
||||||
|
#define GBR_USE_MACROS_FOR_ROTATED_RECT
|
||||||
|
|
||||||
GERBER_PLOTTER::GERBER_PLOTTER()
|
GERBER_PLOTTER::GERBER_PLOTTER()
|
||||||
{
|
{
|
||||||
|
@ -293,7 +296,7 @@ bool GERBER_PLOTTER::EndPlot()
|
||||||
fputs( APER_MACRO_ROUNDRECT_HEADER, outputFile );
|
fputs( APER_MACRO_ROUNDRECT_HEADER, outputFile );
|
||||||
|
|
||||||
if( m_hasApertureRotOval )
|
if( m_hasApertureRotOval )
|
||||||
fputs( APER_MACRO_HORIZ_OVAL_HEADER, outputFile );
|
fputs( APER_MACRO_SHAPE_OVAL_HEADER, outputFile );
|
||||||
|
|
||||||
if( m_hasApertureRotRect )
|
if( m_hasApertureRotRect )
|
||||||
fputs( APER_MACRO_ROT_RECT_HEADER, outputFile );
|
fputs( APER_MACRO_ROT_RECT_HEADER, outputFile );
|
||||||
|
@ -561,9 +564,34 @@ void GERBER_PLOTTER::writeApertureList()
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case APERTURE::AM_ROUND_RECT: // Aperture macro for round rect pads
|
case APERTURE::AM_ROUND_RECT: // Aperture macro for round rect pads
|
||||||
sprintf( cbuf, "%s,%#fX%#fX%#fX%#f*%%\n", APER_MACRO_ROUNDRECT_NAME,
|
{
|
||||||
tool.m_Size.x * fscale, tool.m_Size.y * fscale,
|
// The aperture macro needs coordinates of the centers of the 4 corners
|
||||||
tool.m_Radius * fscale, tool.m_Rotation );
|
std::vector<VECTOR2I> corners;
|
||||||
|
wxSize half_size( tool.m_Size.x/2-tool.m_Radius, tool.m_Size.y/2-tool.m_Radius );
|
||||||
|
|
||||||
|
corners.emplace_back( -half_size.x, -half_size.y );
|
||||||
|
corners.emplace_back( half_size.x, -half_size.y );
|
||||||
|
corners.emplace_back( half_size.x, half_size.y );
|
||||||
|
corners.emplace_back( -half_size.x, half_size.y );
|
||||||
|
|
||||||
|
// Rotate the corner coordinates:
|
||||||
|
for( int ii = 0; ii < 4; ii++ )
|
||||||
|
RotatePoint( corners[ii], tool.m_Rotation*10.0 );
|
||||||
|
|
||||||
|
sprintf( cbuf, "%s,%#fX", APER_MACRO_ROUNDRECT_NAME,
|
||||||
|
tool.m_Radius * fscale );
|
||||||
|
buffer += cbuf;
|
||||||
|
|
||||||
|
// Add each corner
|
||||||
|
for( int ii = 0; ii < 4; ii++ )
|
||||||
|
{
|
||||||
|
sprintf( cbuf, "%#fX%#fX",
|
||||||
|
corners[ii].x * fscale, corners[ii].y * fscale );
|
||||||
|
buffer += cbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf( cbuf, "0*%%\n" );
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case APERTURE::AM_ROT_RECT: // Aperture macro for rotated rect pads
|
case APERTURE::AM_ROT_RECT: // Aperture macro for rotated rect pads
|
||||||
|
@ -594,10 +622,20 @@ void GERBER_PLOTTER::writeApertureList()
|
||||||
|
|
||||||
case APERTURE::AM_ROTATED_OVAL: // Aperture macro for rotated oval pads
|
case APERTURE::AM_ROTATED_OVAL: // Aperture macro for rotated oval pads
|
||||||
// (not rotated is a primitive)
|
// (not rotated is a primitive)
|
||||||
// m_Size.x = lenght; m_Size.y = width
|
// m_Size.x = lenght; m_Size.y = width, and the macro aperure expects
|
||||||
sprintf( cbuf, "%s,%#fX%#fX%#f*%%\n", APER_MACRO_HORIZ_OVAL_NAME,
|
// the position of ends
|
||||||
tool.m_Size.x * fscale, tool.m_Size.y * fscale,
|
{
|
||||||
tool.m_Rotation );
|
VECTOR2I start( tool.m_Size.x/2, 0 );
|
||||||
|
VECTOR2I end( -tool.m_Size.x/2, 0 );
|
||||||
|
|
||||||
|
RotatePoint( start, tool.m_Rotation*10.0 );
|
||||||
|
RotatePoint( end, tool.m_Rotation*10.0 );
|
||||||
|
|
||||||
|
sprintf( cbuf, "%s,%#fX%#fX%#fX%#fX%#fX0*%%\n", APER_MACRO_SHAPE_OVAL_NAME,
|
||||||
|
tool.m_Size.y * fscale, // width
|
||||||
|
start.x * fscale, -start.y * fscale,
|
||||||
|
end.x * fscale, -end.y * fscale );
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -949,7 +987,7 @@ void GERBER_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, doub
|
||||||
{
|
{
|
||||||
if( trace_mode == FILLED )
|
if( trace_mode == FILLED )
|
||||||
{
|
{
|
||||||
#ifdef GBR_USE_MACROS
|
#ifdef GBR_USE_MACROS_FOR_ROTATED_OVAL
|
||||||
m_hasApertureRotOval = true;
|
m_hasApertureRotOval = true;
|
||||||
// We are using a aperture macro that expect size.y < size.x
|
// We are using a aperture macro that expect size.y < size.x
|
||||||
// i.e draw a horizontal line for rotation = 0.0
|
// i.e draw a horizontal line for rotation = 0.0
|
||||||
|
@ -1041,7 +1079,7 @@ void GERBER_PLOTTER::FlashPadRect( const wxPoint& pos, const wxSize& aSize,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
#ifdef GBR_USE_MACROS
|
#ifdef GBR_USE_MACROS_FOR_ROTATED_RECT
|
||||||
if( trace_mode != SKETCH )
|
if( trace_mode != SKETCH )
|
||||||
{
|
{
|
||||||
m_hasApertureRotRect = true;
|
m_hasApertureRotRect = true;
|
||||||
|
@ -1112,7 +1150,7 @@ void GERBER_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aS
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#ifdef GBR_USE_MACROS
|
#ifdef GBR_USE_MACROS_FOR_ROUNDRECT
|
||||||
m_hasApertureRoundRect = true;
|
m_hasApertureRoundRect = true;
|
||||||
|
|
||||||
DPOINT pos_dev = userToDeviceCoordinates( aPadPos );
|
DPOINT pos_dev = userToDeviceCoordinates( aPadPos );
|
||||||
|
@ -1353,7 +1391,7 @@ void GERBER_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint* aCo
|
||||||
if( aTrace_Mode == SKETCH )
|
if( aTrace_Mode == SKETCH )
|
||||||
PlotPoly( cornerList, NO_FILL, GetCurrentLineWidth(), &metadata );
|
PlotPoly( cornerList, NO_FILL, GetCurrentLineWidth(), &metadata );
|
||||||
else
|
else
|
||||||
#ifdef GBR_USE_MACROS
|
#ifdef GBR_USE_MACROS_FOR_TRAPEZOID
|
||||||
{
|
{
|
||||||
m_hasApertureOutline = true;
|
m_hasApertureOutline = true;
|
||||||
DPOINT pos_dev = userToDeviceCoordinates( aPadPos );
|
DPOINT pos_dev = userToDeviceCoordinates( aPadPos );
|
||||||
|
|
|
@ -26,27 +26,28 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// A aperture macro to define a rounded rect pad shape
|
// A aperture macro to define a rounded rect pad shape
|
||||||
|
// In many gerber readers, the rotation of the full shape is broken
|
||||||
|
// so we are using primitives that does not need a rotation
|
||||||
#define APER_MACRO_ROUNDRECT_NAME "RoundRect"
|
#define APER_MACRO_ROUNDRECT_NAME "RoundRect"
|
||||||
|
|
||||||
#define APER_MACRO_ROUNDRECT_HEADER \
|
#define APER_MACRO_ROUNDRECT_HEADER \
|
||||||
"%AMRoundRect*\n\
|
"%AMRoundRect*\n\
|
||||||
0 Rectangle with rounded corners, with rotation*\n\
|
0 Rectangle with rounded corners*\n\
|
||||||
0 The origin of the aperture is its center*\n\
|
0 $1 Rounding radius*\n\
|
||||||
0 $1 X-size*\n\
|
0 $2 $3 $4 $5 $6 $7 $8 $9 X,Y pos of 4 corners*\n\
|
||||||
0 $2 Y-size*\n\
|
0 Add a 4 corners polygon primitive as box body*\n\
|
||||||
0 $3 Rounding radius*\n\
|
4,1,4,$2,$3,$4,$5,$6,$7,$8,$9,$2,$3,0*\n\
|
||||||
0 $4 Rotation angle, in degrees counterclockwise*\n\
|
|
||||||
0 Add two overlapping rectangle primitives as box body*\n\
|
|
||||||
21,1,$1,$2-$3-$3,0,0,$4*\n\
|
|
||||||
21,1,$1-$3-$3,$2,0,0,$4*\n\
|
|
||||||
0 Add four circle primitives for the rounded corners*\n\
|
0 Add four circle primitives for the rounded corners*\n\
|
||||||
$5=$1/2*\n\
|
1,1,$1+$1,$2,$3,0*\n\
|
||||||
$6=$2/2*\n\
|
1,1,$1+$1,$4,$5,0*\n\
|
||||||
$7=2x$3*\n\
|
1,1,$1+$1,$6,$7,0*\n\
|
||||||
1,1,$7,$5-$3,$6-$3,$4*\n\
|
1,1,$1+$1,$8,$9,0*\n\
|
||||||
1,1,$7,-$5+$3,$6-$3,$4*\n\
|
0 Add four rect primitives between the rounded corners*\n\
|
||||||
1,1,$7,-$5+$3,-$6+$3,$4*\n\
|
20,1,$1+$1,$2,$3,$4,$5,0*\n\
|
||||||
1,1,$7,$5-$3,-$6+$3,$4*%\n"
|
20,1,$1+$1,$4,$5,$6,$7,0*\n\
|
||||||
|
20,1,$1+$1,$6,$7,$8,$9,0*\n\
|
||||||
|
20,1,$1+$1,$8,$9,$2,$3,0*\
|
||||||
|
%\n"
|
||||||
|
|
||||||
// A aperture macro to define a rotated rect pad shape
|
// A aperture macro to define a rotated rect pad shape
|
||||||
#define APER_MACRO_ROT_RECT_NAME "RotRect"
|
#define APER_MACRO_ROT_RECT_NAME "RotRect"
|
||||||
|
@ -63,23 +64,25 @@ $7=2x$3*\n\
|
||||||
|
|
||||||
|
|
||||||
// A aperture macro to define a oval pad shape
|
// A aperture macro to define a oval pad shape
|
||||||
#define APER_MACRO_HORIZ_OVAL_NAME "HorizOval"
|
// In many gerber readers, the rotation of the full shape is broken
|
||||||
|
// so we are using a primitive that does not need a rotation to be
|
||||||
|
// plotted
|
||||||
|
#define APER_MACRO_SHAPE_OVAL_NAME "HorizOval"
|
||||||
|
|
||||||
#define APER_MACRO_HORIZ_OVAL_HEADER \
|
#define APER_MACRO_SHAPE_OVAL_HEADER \
|
||||||
"%AMHorizOval*\n\
|
"%AMHorizOval*\n\
|
||||||
0 Thick line with rounded ends, with rotation*\n\
|
0 Thick line with rounded ends*\n\
|
||||||
0 The origin of the aperture is its center*\n\
|
0 $1 width*\n\
|
||||||
0 $1 length (X dim)*\n\
|
0 $2 $3 position (X,Y) of the first rounded end (center of the circle)*\n\
|
||||||
0 $2 width (Y dim)*\n\
|
0 $4 $5 position (X,Y) of the second rounded end (center of the circle)*\n\
|
||||||
0 $3 Rotation angle, in degrees counterclockwise*\n\
|
0 Add line between two ends*\n\
|
||||||
0 Add horizontal line*\n\
|
20,1,$1,$2,$3,$4,$5,0*\n\
|
||||||
21,1,$1-$2,$2,0,0,$3*\n\
|
0 Add two circle primitives to create the rounded ends*\n\
|
||||||
0 Add two circle primitives for the rounded ends*\n\
|
1,1,$1,$2,$3,0*\n\
|
||||||
$4=($1-$2)/2*\n\
|
1,1,$1,$4,$5,0*%\n"
|
||||||
1,1,$2,$4,0,$3*\n\
|
|
||||||
1,1,$2,-$4,0,$3*%\n"
|
|
||||||
|
|
||||||
// A aperture macro to define a trapezoid (polygon) by 4 corners
|
// A aperture macro to define a trapezoid (polygon) by 4 corners
|
||||||
|
// and a rotation angle
|
||||||
#define APER_MACRO_OUTLINE4P_NAME "Outline4P"
|
#define APER_MACRO_OUTLINE4P_NAME "Outline4P"
|
||||||
|
|
||||||
#define APER_MACRO_OUTLINE4P_HEADER \
|
#define APER_MACRO_OUTLINE4P_HEADER \
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
#include <am_param.h>
|
#include <am_param.h>
|
||||||
#include <am_primitive.h>
|
#include <am_primitive.h>
|
||||||
#include <macros.h>
|
//#include <macros.h>
|
||||||
|
|
||||||
#include <wx/debug.h>
|
#include <wx/debug.h>
|
||||||
|
|
||||||
|
|
|
@ -35,8 +35,6 @@
|
||||||
#include <gerbview.h>
|
#include <gerbview.h>
|
||||||
#include <gerber_file_image.h>
|
#include <gerber_file_image.h>
|
||||||
|
|
||||||
#include <gr_basic.h>
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function scaletoIU
|
* Function scaletoIU
|
||||||
|
@ -281,8 +279,8 @@ void AM_PRIMITIVE::DrawBasicShape( const GERBER_DRAW_ITEM* aParent,
|
||||||
|
|
||||||
case AMP_MOIRE:
|
case AMP_MOIRE:
|
||||||
{
|
{
|
||||||
/* Moir<EFBFBD>, Primitive Code 6
|
/* Moire, Primitive Code 6
|
||||||
* The moir<EFBFBD> primitive is a cross hair centered on concentric rings (annuli).
|
* The moire primitive is a cross hair centered on concentric rings (annuli).
|
||||||
* Exposure is always on.
|
* Exposure is always on.
|
||||||
*/
|
*/
|
||||||
curPos += mapPt( params[0].GetValue( tool ), params[1].GetValue( tool ),
|
curPos += mapPt( params[0].GetValue( tool ), params[1].GetValue( tool ),
|
||||||
|
@ -365,6 +363,7 @@ void AM_PRIMITIVE::DrawBasicShape( const GERBER_DRAW_ITEM* aParent,
|
||||||
// * the polygon is always closed,
|
// * the polygon is always closed,
|
||||||
// * therefore the last XY coordinate is the same as the first
|
// * therefore the last XY coordinate is the same as the first
|
||||||
int prm_idx = 2; // params[2] is the first X coordinate
|
int prm_idx = 2; // params[2] is the first X coordinate
|
||||||
|
|
||||||
for( int i = 0; i <= numCorners; ++i )
|
for( int i = 0; i <= numCorners; ++i )
|
||||||
{
|
{
|
||||||
pos.x = scaletoIU( params[prm_idx].GetValue( tool ), m_GerbMetric );
|
pos.x = scaletoIU( params[prm_idx].GetValue( tool ), m_GerbMetric );
|
||||||
|
|
Loading…
Reference in New Issue