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

Gerbview: support for plot lines (currently: not arcs) with a rectangular pen...

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.
parent 1206177c
...@@ -88,8 +88,7 @@ GERBER_DRAW_ITEM::GERBER_DRAW_ITEM( const GERBER_DRAW_ITEM& aSource ) : ...@@ -88,8 +88,7 @@ GERBER_DRAW_ITEM::GERBER_DRAW_ITEM( const GERBER_DRAW_ITEM& aSource ) :
m_mirrorA = aSource.m_mirrorA; m_mirrorA = aSource.m_mirrorA;
m_mirrorB = aSource.m_mirrorB; m_mirrorB = aSource.m_mirrorB;
m_layerOffset = aSource.m_layerOffset; m_layerOffset = aSource.m_layerOffset;
m_drawScale.x = aSource.m_drawScale.x; m_drawScale = aSource.m_drawScale;
m_drawScale.y = aSource.m_drawScale.y;
m_lyrRotation = aSource.m_lyrRotation; m_lyrRotation = aSource.m_lyrRotation;
} }
...@@ -222,7 +221,13 @@ wxString GERBER_DRAW_ITEM::ShowGBRShape() ...@@ -222,7 +221,13 @@ wxString GERBER_DRAW_ITEM::ShowGBRShape()
return wxT( "polygon" ); return wxT( "polygon" );
case GBR_SPOT_MACRO: 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: default:
return wxT( "??" ); return wxT( "??" );
...@@ -363,8 +368,8 @@ void GERBER_DRAW_ITEM::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, int aDrawMode, ...@@ -363,8 +368,8 @@ void GERBER_DRAW_ITEM::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, int aDrawMode,
break; break;
case GBR_CIRCLE: case GBR_CIRCLE:
radius = (int) hypot( (double) ( m_End.x - m_Start.x ), radius = wxRound(hypot( (double) ( m_End.x - m_Start.x ),
(double) ( m_End.y - m_Start.y ) ); (double) ( m_End.y - m_Start.y ) ));
halfPenWidth = m_Size.x >> 1; halfPenWidth = m_Size.x >> 1;
...@@ -384,6 +389,8 @@ void GERBER_DRAW_ITEM::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, int aDrawMode, ...@@ -384,6 +389,8 @@ void GERBER_DRAW_ITEM::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, int aDrawMode,
break; break;
case GBR_ARC: case GBR_ARC:
// Currently, arcs plotted witha rectangular aperture are not supported.
// a round pen only is expected.
#if 0 // for arc debug only #if 0 // for arc debug only
GRLine( &aPanel->m_ClipBox, aDC, GetABPosition( m_Start ), GRLine( &aPanel->m_ClipBox, aDC, GetABPosition( m_Start ),
GetABPosition( m_ArcCentre ), 0, color ); GetABPosition( m_ArcCentre ), 0, color );
...@@ -415,12 +422,30 @@ void GERBER_DRAW_ITEM::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, int aDrawMode, ...@@ -415,12 +422,30 @@ void GERBER_DRAW_ITEM::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, int aDrawMode,
break; break;
case GBR_SEGMENT: case GBR_SEGMENT:
if( !isFilled ) /* Plot a line from m_Start to m_End.
GRCSegm( &aPanel->m_ClipBox, aDC, GetABPosition( m_Start ), * Usually, a round pen is used, but some gerber files use a rectangular pen
GetABPosition( m_End ), m_Size.x, color ); * 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 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 ); GetABPosition( m_End ), m_Size.x, color );
}
else
{
GRFilledSegment( &aPanel->m_ClipBox, aDC, GetABPosition( m_Start ),
GetABPosition( m_End ), m_Size.x, color );
}
}
break; break;
default: default:
...@@ -433,9 +458,71 @@ void GERBER_DRAW_ITEM::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, int aDrawMode, ...@@ -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 /** 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 * Draw filled polygons
*/ */
void GERBER_DRAW_ITEM::DrawGbrPoly( EDA_Rect* aClipBox, void GERBER_DRAW_ITEM::DrawGbrPoly( EDA_Rect* aClipBox,
......
...@@ -194,8 +194,15 @@ public: ...@@ -194,8 +194,15 @@ public:
int aDrawMode, int aDrawMode,
const wxPoint& aOffset = ZeroOffset ); 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 /** 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, void DrawGbrPoly( EDA_Rect* aClipBox,
wxDC* aDC, int aColor, wxDC* aDC, int aColor,
......
*
%FSLAX23Y23*%
%MOIN*%
%ADD10R,0.025X0.025*%
%ADD11R,0.03X0.06*%
%IPPOS*%
%LNtest_rect.gbr*%
%LPD*%
G75*
G54D10*
X04000Y00100D02*
X04400Y00140D01*
G54D11*
X03000Y00100D02*
X02400Y-00340D01*
M02*
...@@ -137,23 +137,23 @@ static void fillFlashedGBRITEM( GERBER_DRAW_ITEM* aGbrItem, ...@@ -137,23 +137,23 @@ static void fillFlashedGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
* @param aGbrItem The GERBER_DRAW_ITEM to fill in. * @param aGbrItem The GERBER_DRAW_ITEM to fill in.
* @param Dcode_index The DCODE value, like D14 * @param Dcode_index The DCODE value, like D14
* @param aLayer The layer index to set into the GBRITEM * @param aLayer The layer index to set into the GBRITEM
* @param aPos The center point of the flash * @param aStart The starting point of the line
* @param aDiameter The diameter of the round flash * @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 aLayerNegative = true if the current layer is negative
* @param aImageNegative = true if the current image is negative
*/ */
static void fillLineGBRITEM( GERBER_DRAW_ITEM* aGbrItem, static void fillLineGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
int Dcode_index, int Dcode_index,
int aLayer, int aLayer,
const wxPoint& aStart, const wxPoint& aStart,
const wxPoint& aEnd, const wxPoint& aEnd,
int aWidth, wxSize aPenSize,
bool aLayerNegative ) bool aLayerNegative )
{ {
aGbrItem->SetLayer( aLayer ); aGbrItem->SetLayer( aLayer );
aGbrItem->m_Flashed = false; aGbrItem->m_Flashed = false;
aGbrItem->m_Size.x = aGbrItem->m_Size.y = aWidth; aGbrItem->m_Size = aPenSize;
aGbrItem->m_Start = aStart; aGbrItem->m_Start = aStart;
aGbrItem->m_End = aEnd; aGbrItem->m_End = aEnd;
...@@ -188,13 +188,12 @@ static void fillLineGBRITEM( GERBER_DRAW_ITEM* aGbrItem, ...@@ -188,13 +188,12 @@ static void fillLineGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
* must be calculated from the previously given constraint: arc only in the * must be calculated from the previously given constraint: arc only in the
* same quadrant. * same quadrant.
* @param aDiameter The diameter of the round flash * @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 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, static void fillArcGBRITEM( GERBER_DRAW_ITEM* aGbrItem, int Dcode_index, int aLayer,
const wxPoint& aStart, const wxPoint& aEnd, const wxPoint& aStart, const wxPoint& aEnd,
const wxPoint& aRelCenter, int aWidth, const wxPoint& aRelCenter, wxSize aPenSize,
bool aClockwise, bool aMultiquadrant, bool aClockwise, bool aMultiquadrant,
bool aLayerNegative ) bool aLayerNegative )
{ {
...@@ -202,7 +201,7 @@ static void fillArcGBRITEM( GERBER_DRAW_ITEM* aGbrItem, int Dcode_index, int aL ...@@ -202,7 +201,7 @@ static void fillArcGBRITEM( GERBER_DRAW_ITEM* aGbrItem, int Dcode_index, int aL
aGbrItem->m_Shape = GBR_ARC; aGbrItem->m_Shape = GBR_ARC;
aGbrItem->SetLayer( aLayer ); aGbrItem->SetLayer( aLayer );
aGbrItem->m_Size.x = aGbrItem->m_Size.y = aWidth; aGbrItem->m_Size = aPenSize;
aGbrItem->m_Flashed = false; aGbrItem->m_Flashed = false;
...@@ -333,7 +332,7 @@ static void fillArcPOLY( BOARD* aPcb, GERBER_DRAW_ITEM* aGbrItem, ...@@ -333,7 +332,7 @@ static void fillArcPOLY( BOARD* aPcb, GERBER_DRAW_ITEM* aGbrItem,
aGbrItem->SetLayerPolarity( aLayerNegative ); aGbrItem->SetLayerPolarity( aLayerNegative );
fillArcGBRITEM( &dummyGbrItem, 0, 0, fillArcGBRITEM( &dummyGbrItem, 0, 0,
aStart, aEnd, rel_center, 0, aStart, aEnd, rel_center, wxSize(0, 0),
clockwise, multiquadrant, aLayerNegative ); clockwise, multiquadrant, aLayerNegative );
wxPoint center; wxPoint center;
...@@ -688,7 +687,7 @@ bool GERBER_IMAGE::Execute_DCODE_Command( char*& text, int D_commande ) ...@@ -688,7 +687,7 @@ bool GERBER_IMAGE::Execute_DCODE_Command( char*& text, int D_commande )
// m_PreviousPos.x, m_PreviousPos.y, // m_PreviousPos.x, m_PreviousPos.y,
// m_CurrentPos.x, m_CurrentPos.y ); ) // m_CurrentPos.x, m_CurrentPos.y ); )
fillLineGBRITEM( gbritem, dcode, activeLayer, m_PreviousPos, fillLineGBRITEM( gbritem, dcode, activeLayer, m_PreviousPos,
m_CurrentPos, size.x, GetLayerParams().m_LayerNegative ); m_CurrentPos, size, GetLayerParams().m_LayerNegative );
StepAndRepeatItem( *gbritem ); StepAndRepeatItem( *gbritem );
break; break;
...@@ -708,7 +707,7 @@ bool GERBER_IMAGE::Execute_DCODE_Command( char*& text, int D_commande ) ...@@ -708,7 +707,7 @@ bool GERBER_IMAGE::Execute_DCODE_Command( char*& text, int D_commande )
// m_CurrentPos.y, m_IJPos.x, // m_CurrentPos.y, m_IJPos.x,
// m_IJPos.y, m_Iterpolation, m_360Arc_enbl ); ) // m_IJPos.y, m_Iterpolation, m_360Arc_enbl ); )
fillArcGBRITEM( gbritem, dcode, activeLayer, m_PreviousPos, fillArcGBRITEM( gbritem, dcode, activeLayer, m_PreviousPos,
m_CurrentPos, m_IJPos, size.x, m_CurrentPos, m_IJPos, size,
( m_Iterpolation == GERB_INTERPOL_ARC_NEG ) ? ( m_Iterpolation == GERB_INTERPOL_ARC_NEG ) ?
false : true, m_360Arc_enbl, GetLayerParams().m_LayerNegative ); false : true, m_360Arc_enbl, GetLayerParams().m_LayerNegative );
StepAndRepeatItem( *gbritem ); StepAndRepeatItem( *gbritem );
......
...@@ -245,9 +245,11 @@ void DRAWSEGMENT::Draw( WinEDA_DrawPanel* panel, wxDC* DC, ...@@ -245,9 +245,11 @@ void DRAWSEGMENT::Draw( WinEDA_DrawPanel* panel, wxDC* DC,
GRSetDrawMode( DC, draw_mode ); GRSetDrawMode( DC, draw_mode );
l_piste = m_Width >> 1; /* half trace width */ l_piste = m_Width >> 1; /* half trace width */
// Line start point or Circle and Arc center
ux0 = m_Start.x; ux0 = m_Start.x;
uy0 = m_Start.y; uy0 = m_Start.y;
// Line end point or circle and arc start point
dx = m_End.x; dx = m_End.x;
dy = m_End.y; dy = m_End.y;
......
...@@ -10,8 +10,8 @@ class DRAWSEGMENT : public BOARD_ITEM ...@@ -10,8 +10,8 @@ class DRAWSEGMENT : public BOARD_ITEM
{ {
public: public:
int m_Width; // thickness of lines ... int m_Width; // thickness of lines ...
wxPoint m_Start; // Line start point wxPoint m_Start; // Line start point or Circle and Arc center
wxPoint m_End; // Line end point wxPoint m_End; // Line end point or circle and arc start point
int m_Shape; // Shape: line, Circle, Arc int m_Shape; // Shape: line, Circle, Arc
int m_Type; // Used in complex associations ( Dimensions.. ) int m_Type; // Used in complex associations ( Dimensions.. )
......
...@@ -421,6 +421,7 @@ int EDGE_MODULE::ReadDescr( char* Line, FILE* File, ...@@ -421,6 +421,7 @@ int EDGE_MODULE::ReadDescr( char* Line, FILE* File,
&m_Start0.x, &m_Start0.y, &m_Start0.x, &m_Start0.y,
&m_End0.x, &m_End0.y, &m_End0.x, &m_End0.y,
&m_Angle, &m_Width, &m_Layer ); &m_Angle, &m_Width, &m_Layer );
NORMALIZE_ANGLE( m_Angle );
break; break;
case S_SEGMENT: case S_SEGMENT:
......
...@@ -818,9 +818,9 @@ void CreateTracksInfoData( FILE* file, BOARD* pcb ) ...@@ -818,9 +818,9 @@ void CreateTracksInfoData( FILE* file, BOARD* pcb )
*/ */
void FootprintWriteShape( FILE* file, MODULE* module ) void FootprintWriteShape( FILE* file, MODULE* module )
{ {
EDGE_MODULE* PtEdge; EDGE_MODULE* edge;
EDA_BaseStruct* PtStruct; EDA_BaseStruct* item;
int Yaxis_sign = -1; // Control Y axis change sign (as normal int y_axis_sign = -1; // Control Y axis change sign (as normal
// module / mirror axis and conventions) // module / mirror axis and conventions)
/* creates header: */ /* creates header: */
...@@ -840,46 +840,53 @@ void FootprintWriteShape( FILE* file, MODULE* module ) ...@@ -840,46 +840,53 @@ void FootprintWriteShape( FILE* file, MODULE* module )
} }
/* creates Drawing */ /* creates Drawing */
PtStruct = module->m_Drawings; item = module->m_Drawings;
for( ; PtStruct != NULL; PtStruct = PtStruct->Next() ) for( ; item != NULL; item = item->Next() )
{ {
switch( PtStruct->Type() ) switch( item->Type() )
{ {
case TYPE_TEXTE_MODULE: case TYPE_TEXTE_MODULE:
break; break;
case TYPE_EDGE_MODULE: case TYPE_EDGE_MODULE:
PtEdge = (EDGE_MODULE*) PtStruct; edge = (EDGE_MODULE*) item;
switch( PtEdge->m_Shape ) switch( edge->m_Shape )
{ {
case S_SEGMENT: case S_SEGMENT:
fprintf( file, "LINE %d %d %d %d\n", fprintf( file, "LINE %d %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,
PtEdge->m_End0.x, Yaxis_sign * PtEdge->m_End0.y ); edge->m_End0.x, y_axis_sign * edge->m_End0.y );
break; break;
case S_CIRCLE: case S_CIRCLE:
{ {
int rayon = (int) hypot( int rayon = (int) hypot(
(double) ( PtEdge->m_End0.x - PtEdge->m_Start0.x ), (double) ( edge->m_End0.x - edge->m_Start0.x ),
(double) ( PtEdge->m_End0.y - PtEdge->m_Start0.y ) ); (double) ( edge->m_End0.y - edge->m_Start0.y ) );
fprintf( file, "CIRCLE %d %d %d\n", 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 ); rayon );
break; break;
} }
case S_ARC: /* print ARC x,y start x,y end x,y center */ case S_ARC: /* print ARC x,y start x,y end x,y center */
{ { // Arcs are defined counter clockwise (positive trigonometric)
int arcendx, arcendy; // from the start point to the end point (0 to 360 degrees)
arcendx = PtEdge->m_Start0.x; wxPoint arcStart, arcEnd;
arcendy = PtEdge->m_Start0.y; // edge->m_Start0 is the arc center relative to the shape position
RotatePoint( &arcendx, &arcendy, PtEdge->m_Angle ); // 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", fprintf( file, "ARC %d %d %d %d %d %d\n",
PtEdge->m_End0.x, Yaxis_sign * PtEdge->m_End0.y, arcStart.x, y_axis_sign * arcStart.y, // Start point
arcendx, Yaxis_sign * arcendy, arcEnd.x, y_axis_sign * arcEnd.y, // End point
PtEdge->m_Start0.x, Yaxis_sign * PtEdge->m_Start0.y ); edge->m_Start0.x, y_axis_sign * edge->m_Start0.y );
break; break;
} }
......
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