Gerbview: support for plot lines (currently: not arcs) with a rectangular pen (Yes, it exists!). pcbnew: try to fix an issue when exporting arcs in gencad.

This commit is contained in:
jean-pierre charras 2010-10-25 09:43:50 +02:00
parent 1206177ce0
commit f0364c9da6
8 changed files with 165 additions and 46 deletions

View File

@ -88,8 +88,7 @@ GERBER_DRAW_ITEM::GERBER_DRAW_ITEM( const GERBER_DRAW_ITEM& aSource ) :
m_mirrorA = aSource.m_mirrorA;
m_mirrorB = aSource.m_mirrorB;
m_layerOffset = aSource.m_layerOffset;
m_drawScale.x = aSource.m_drawScale.x;
m_drawScale.y = aSource.m_drawScale.y;
m_drawScale = aSource.m_drawScale;
m_lyrRotation = aSource.m_lyrRotation;
}
@ -222,7 +221,13 @@ wxString GERBER_DRAW_ITEM::ShowGBRShape()
return wxT( "polygon" );
case GBR_SPOT_MACRO:
return wxT( "apt_macro" ); // TODO: add aperture macro name
{
wxString name = wxT( "apt_macro" );
D_CODE* dcode = GetDcodeDescr();
if( dcode && dcode->GetMacro() )
name << wxT(" ") << dcode->GetMacro()->name;
return name;
}
default:
return wxT( "??" );
@ -363,8 +368,8 @@ void GERBER_DRAW_ITEM::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, int aDrawMode,
break;
case GBR_CIRCLE:
radius = (int) hypot( (double) ( m_End.x - m_Start.x ),
(double) ( m_End.y - m_Start.y ) );
radius = wxRound(hypot( (double) ( m_End.x - m_Start.x ),
(double) ( m_End.y - m_Start.y ) ));
halfPenWidth = m_Size.x >> 1;
@ -384,6 +389,8 @@ void GERBER_DRAW_ITEM::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, int aDrawMode,
break;
case GBR_ARC:
// Currently, arcs plotted witha rectangular aperture are not supported.
// a round pen only is expected.
#if 0 // for arc debug only
GRLine( &aPanel->m_ClipBox, aDC, GetABPosition( m_Start ),
GetABPosition( m_ArcCentre ), 0, color );
@ -415,12 +422,30 @@ void GERBER_DRAW_ITEM::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, int aDrawMode,
break;
case GBR_SEGMENT:
if( !isFilled )
GRCSegm( &aPanel->m_ClipBox, aDC, GetABPosition( m_Start ),
GetABPosition( m_End ), m_Size.x, color );
/* Plot a line from m_Start to m_End.
* Usually, a round pen is used, but some gerber files use a rectangular pen
* In fact, any aperture can be used to plot a line.
* currently: only a square pen is handled (I believe using a polygon gives a strange plot).
*/
if( d_codeDescr->m_Shape == APT_RECT )
{
if( m_PolyCorners.size() == 0 )
ConvertSegmentToPolygon( );
DrawGbrPoly( &aPanel->m_ClipBox, aDC, color, aOffset, isFilled );
}
else
GRFilledSegment( &aPanel->m_ClipBox, aDC, GetABPosition( m_Start ),
{
if( !isFilled )
{
GRCSegm( &aPanel->m_ClipBox, aDC, GetABPosition( m_Start ),
GetABPosition( m_End ), m_Size.x, color );
}
else
{
GRFilledSegment( &aPanel->m_ClipBox, aDC, GetABPosition( m_Start ),
GetABPosition( m_End ), m_Size.x, color );
}
}
break;
default:
@ -433,9 +458,71 @@ void GERBER_DRAW_ITEM::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, int aDrawMode,
}
}
/** function ConvertSegmentToPolygon
* convert a line to an equivalent polygon.
* Useful when a line is plotted using a rectangular pen.
* In this case, the usual segment plot cannot be used
* The equivalent polygon is the area paint by the rectancular pen
* from m_Start to m_End.
*/
void GERBER_DRAW_ITEM::ConvertSegmentToPolygon( )
{
m_PolyCorners.clear();
m_PolyCorners.reserve(6);
wxPoint start = m_Start;
wxPoint end = m_End;
// make calculations more easy if ensure start.x < end.x
// (only 2 quadrants to consider)
if( start.x > end.x )
EXCHG( start, end );
// calculate values relative to start point:
wxPoint delta = end - start;
// calculate corners for the first quadrant only (delta.x and delta.y > 0 )
// currently, delta.x already is > 0.
// make delta.y > 0
bool change = delta.y < 0;
if( change )
NEGATE( delta.y);
// Now create the full polygon.
// Due to previous chnages, the shape is always something like
// 3 4
// 2 5
// 1 6
wxPoint corner;
corner.x -= m_Size.x/2;
corner.y -= m_Size.y/2;
m_PolyCorners.push_back( corner ); // Lower left corner, start point (1)
corner.y += m_Size.y;
m_PolyCorners.push_back( corner ); // upper left corner, start point (2)
if( delta.x || delta.y)
{
corner += delta;
m_PolyCorners.push_back( corner ); // upper left corner, end point (3)
}
corner.x += m_Size.x;
m_PolyCorners.push_back( corner ); // upper right corner, end point (4)
corner.y -= m_Size.y;
m_PolyCorners.push_back( corner ); // lower right corner, end point (5)
if( delta.x || delta.y )
{
corner -= delta;
m_PolyCorners.push_back( corner ); // lower left corner, start point (6)
}
// Create final polygon:
for( unsigned ii = 0; ii < m_PolyCorners.size(); ii++ )
{
if( change )
NEGATE( m_PolyCorners[ii].y);
m_PolyCorners[ii] += start;
}
}
/** function DrawGbrPoly
* a helper function used id ::Draw to draw the polygon stored ion m_PolyCorners
* a helper function used id ::Draw to draw the polygon stored in m_PolyCorners
* Draw filled polygons
*/
void GERBER_DRAW_ITEM::DrawGbrPoly( EDA_Rect* aClipBox,

View File

@ -194,8 +194,15 @@ public:
int aDrawMode,
const wxPoint& aOffset = ZeroOffset );
/** function ConvertSegmentToPolygon
* convert a line to an equivalent polygon.
* Useful when a line is plotted using a rectangular pen.
* In this case, the usual segment plot function cannot be used
*/
void ConvertSegmentToPolygon( );
/** function DrawGbrPoly
* a helper function used id ::Draw to draw the polygon stored ion m_PolyCorners
* a helper function used id ::Draw to draw the polygon stored in m_PolyCorners
*/
void DrawGbrPoly( EDA_Rect* aClipBox,
wxDC* aDC, int aColor,

View File

@ -0,0 +1,16 @@
*
%FSLAX23Y23*%
%MOIN*%
%ADD10R,0.025X0.025*%
%ADD11R,0.03X0.06*%
%IPPOS*%
%LNtest_rect.gbr*%
%LPD*%
G75*
G54D10*
X04000Y00100D02*
X04400Y00140D01*
G54D11*
X03000Y00100D02*
X02400Y-00340D01*
M02*

View File

@ -137,23 +137,23 @@ static void fillFlashedGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
* @param aGbrItem The GERBER_DRAW_ITEM to fill in.
* @param Dcode_index The DCODE value, like D14
* @param aLayer The layer index to set into the GBRITEM
* @param aPos The center point of the flash
* @param aDiameter The diameter of the round flash
* @param aStart The starting point of the line
* @param aEnd The ending point of the line
* @param aPenSize The size of the flash. Note rectangular shapes are legal.
* @param aLayerNegative = true if the current layer is negative
* @param aImageNegative = true if the current image is negative
*/
static void fillLineGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
int Dcode_index,
int aLayer,
const wxPoint& aStart,
const wxPoint& aEnd,
int aWidth,
wxSize aPenSize,
bool aLayerNegative )
{
aGbrItem->SetLayer( aLayer );
aGbrItem->m_Flashed = false;
aGbrItem->m_Size.x = aGbrItem->m_Size.y = aWidth;
aGbrItem->m_Size = aPenSize;
aGbrItem->m_Start = aStart;
aGbrItem->m_End = aEnd;
@ -188,13 +188,12 @@ static void fillLineGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
* must be calculated from the previously given constraint: arc only in the
* same quadrant.
* @param aDiameter The diameter of the round flash
* @param aWidth is the pen width.
* @param aPenSize The size of the flash. Note rectangular shapes are legal.
* @param aLayerNegative = true if the current layer is negative
* @param aImageNegative = true if the current image is negative
*/
static void fillArcGBRITEM( GERBER_DRAW_ITEM* aGbrItem, int Dcode_index, int aLayer,
const wxPoint& aStart, const wxPoint& aEnd,
const wxPoint& aRelCenter, int aWidth,
const wxPoint& aRelCenter, wxSize aPenSize,
bool aClockwise, bool aMultiquadrant,
bool aLayerNegative )
{
@ -202,7 +201,7 @@ static void fillArcGBRITEM( GERBER_DRAW_ITEM* aGbrItem, int Dcode_index, int aL
aGbrItem->m_Shape = GBR_ARC;
aGbrItem->SetLayer( aLayer );
aGbrItem->m_Size.x = aGbrItem->m_Size.y = aWidth;
aGbrItem->m_Size = aPenSize;
aGbrItem->m_Flashed = false;
@ -333,7 +332,7 @@ static void fillArcPOLY( BOARD* aPcb, GERBER_DRAW_ITEM* aGbrItem,
aGbrItem->SetLayerPolarity( aLayerNegative );
fillArcGBRITEM( &dummyGbrItem, 0, 0,
aStart, aEnd, rel_center, 0,
aStart, aEnd, rel_center, wxSize(0, 0),
clockwise, multiquadrant, aLayerNegative );
wxPoint center;
@ -688,7 +687,7 @@ bool GERBER_IMAGE::Execute_DCODE_Command( char*& text, int D_commande )
// m_PreviousPos.x, m_PreviousPos.y,
// m_CurrentPos.x, m_CurrentPos.y ); )
fillLineGBRITEM( gbritem, dcode, activeLayer, m_PreviousPos,
m_CurrentPos, size.x, GetLayerParams().m_LayerNegative );
m_CurrentPos, size, GetLayerParams().m_LayerNegative );
StepAndRepeatItem( *gbritem );
break;
@ -708,7 +707,7 @@ bool GERBER_IMAGE::Execute_DCODE_Command( char*& text, int D_commande )
// m_CurrentPos.y, m_IJPos.x,
// m_IJPos.y, m_Iterpolation, m_360Arc_enbl ); )
fillArcGBRITEM( gbritem, dcode, activeLayer, m_PreviousPos,
m_CurrentPos, m_IJPos, size.x,
m_CurrentPos, m_IJPos, size,
( m_Iterpolation == GERB_INTERPOL_ARC_NEG ) ?
false : true, m_360Arc_enbl, GetLayerParams().m_LayerNegative );
StepAndRepeatItem( *gbritem );

View File

@ -245,9 +245,11 @@ void DRAWSEGMENT::Draw( WinEDA_DrawPanel* panel, wxDC* DC,
GRSetDrawMode( DC, draw_mode );
l_piste = m_Width >> 1; /* half trace width */
// Line start point or Circle and Arc center
ux0 = m_Start.x;
uy0 = m_Start.y;
// Line end point or circle and arc start point
dx = m_End.x;
dy = m_End.y;

View File

@ -10,8 +10,8 @@ class DRAWSEGMENT : public BOARD_ITEM
{
public:
int m_Width; // thickness of lines ...
wxPoint m_Start; // Line start point
wxPoint m_End; // Line end point
wxPoint m_Start; // Line start point or Circle and Arc center
wxPoint m_End; // Line end point or circle and arc start point
int m_Shape; // Shape: line, Circle, Arc
int m_Type; // Used in complex associations ( Dimensions.. )

View File

@ -421,6 +421,7 @@ int EDGE_MODULE::ReadDescr( char* Line, FILE* File,
&m_Start0.x, &m_Start0.y,
&m_End0.x, &m_End0.y,
&m_Angle, &m_Width, &m_Layer );
NORMALIZE_ANGLE( m_Angle );
break;
case S_SEGMENT:

View File

@ -818,9 +818,9 @@ void CreateTracksInfoData( FILE* file, BOARD* pcb )
*/
void FootprintWriteShape( FILE* file, MODULE* module )
{
EDGE_MODULE* PtEdge;
EDA_BaseStruct* PtStruct;
int Yaxis_sign = -1; // Control Y axis change sign (as normal
EDGE_MODULE* edge;
EDA_BaseStruct* item;
int y_axis_sign = -1; // Control Y axis change sign (as normal
// module / mirror axis and conventions)
/* creates header: */
@ -840,46 +840,53 @@ void FootprintWriteShape( FILE* file, MODULE* module )
}
/* creates Drawing */
PtStruct = module->m_Drawings;
for( ; PtStruct != NULL; PtStruct = PtStruct->Next() )
item = module->m_Drawings;
for( ; item != NULL; item = item->Next() )
{
switch( PtStruct->Type() )
switch( item->Type() )
{
case TYPE_TEXTE_MODULE:
break;
case TYPE_EDGE_MODULE:
PtEdge = (EDGE_MODULE*) PtStruct;
edge = (EDGE_MODULE*) item;
switch( PtEdge->m_Shape )
switch( edge->m_Shape )
{
case S_SEGMENT:
fprintf( file, "LINE %d %d %d %d\n",
PtEdge->m_Start0.x, Yaxis_sign * PtEdge->m_Start0.y,
PtEdge->m_End0.x, Yaxis_sign * PtEdge->m_End0.y );
edge->m_Start0.x, y_axis_sign * edge->m_Start0.y,
edge->m_End0.x, y_axis_sign * edge->m_End0.y );
break;
case S_CIRCLE:
{
int rayon = (int) hypot(
(double) ( PtEdge->m_End0.x - PtEdge->m_Start0.x ),
(double) ( PtEdge->m_End0.y - PtEdge->m_Start0.y ) );
(double) ( edge->m_End0.x - edge->m_Start0.x ),
(double) ( edge->m_End0.y - edge->m_Start0.y ) );
fprintf( file, "CIRCLE %d %d %d\n",
PtEdge->m_Start0.x, Yaxis_sign * PtEdge->m_Start0.y,
edge->m_Start0.x, y_axis_sign * edge->m_Start0.y,
rayon );
break;
}
case S_ARC: /* print ARC x,y start x,y end x,y center */
{
int arcendx, arcendy;
arcendx = PtEdge->m_Start0.x;
arcendy = PtEdge->m_Start0.y;
RotatePoint( &arcendx, &arcendy, PtEdge->m_Angle );
{ // Arcs are defined counter clockwise (positive trigonometric)
// from the start point to the end point (0 to 360 degrees)
wxPoint arcStart, arcEnd;
// edge->m_Start0 is the arc center relative to the shape position
// edge->m_End0 is the arc start point relative to the shape position
arcStart = edge->m_End0;
// calculate arcEnd arc end point relative to the shape position, in pcbnew coordinates
arcEnd = arcStart;
RotatePoint( &arcEnd, edge->m_Start0, -edge->m_Angle );
// due to difference between pcbnew and gencad, swap arc start and arc end
EXCHG(arcEnd, arcStart);
// print arc shape:
fprintf( file, "ARC %d %d %d %d %d %d\n",
PtEdge->m_End0.x, Yaxis_sign * PtEdge->m_End0.y,
arcendx, Yaxis_sign * arcendy,
PtEdge->m_Start0.x, Yaxis_sign * PtEdge->m_Start0.y );
arcStart.x, y_axis_sign * arcStart.y, // Start point
arcEnd.x, y_axis_sign * arcEnd.y, // End point
edge->m_Start0.x, y_axis_sign * edge->m_Start0.y );
break;
}