Commit 7176ec25 authored by jean-pierre charras's avatar jean-pierre charras

Gerbview code redesign. See changelog.

parents 3ae0df15 b992af3e
......@@ -4,6 +4,24 @@ KiCad ChangeLog 2010
Please add newer entries at the top, list the date and your name with
email address.
2010-sept-28, UPDATE Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
================================================================================
++gerbview:
Important changes:
graphic functions rewritten.
graphics items are now specific to gerbview (added a GERBER_DRAW_ITEM class)
and do not use tracks from pcbnew.
The way used to draw them is also new.
Apertures are now correctly drawn for round, oval and rectangular shapes
(with or without holes)
Aperture definition type Polygon is not yet handle.
Polygons are correctly drawn.
TODO:
Draw functions for aperture definition type Polygon.
Draw functions for aperture macros.
Work in progress.
2010-Aug-9 UPDATE Dick Hollenbeck <dick@softplc.com>
================================================================================
++CMakeModules:
......@@ -67,7 +85,7 @@ email address.
2010-jul-27, UPDATE Jean-Pierre Charras <jean-pierre.charras@gipsa-lab.inpg.fr>
================================================================================
++all:
Updated boost to version 1.43
Updated boost to version 1.44
Added boost::polygon (experimental)
++pcbnew:
Added experimental zone fill calculations with boost::polygon
......
......@@ -58,6 +58,10 @@ int g_DrawBgColor = WHITE;
void ClipAndDrawFilledPoly( EDA_Rect* ClipBox, wxDC * DC, wxPoint Points[], int n );
#endif
static void GRSCircle( EDA_Rect* ClipBox, wxDC* DC, int x, int y, int r, int width, int Color );
static void GRSFilledCircle( EDA_Rect* ClipBox, wxDC* DC, int x, int y, int r,
int width, int Color, int BgColor );
extern BASE_SCREEN* ActiveScreen;
......@@ -545,8 +549,8 @@ void GRSetColorPen( wxDC* DC, int Color, int width, int style )
}
if( s_DC_lastcolor != Color ||
s_DC_lastwidth != width ||
s_DC_lastpenstyle != style ||
s_DC_lastwidth != width ||
s_DC_lastpenstyle != style ||
s_DC_lastDC != DC )
{
wxPen pen;
......@@ -573,8 +577,8 @@ void GRSetBrush( wxDC* DC, int Color, int fill )
if( ForceBlackPen )
Color = BLACK;
if( s_DC_lastbrushcolor != Color ||
s_DC_lastbrushfill != fill ||
if( s_DC_lastbrushcolor != Color ||
s_DC_lastbrushfill != fill ||
s_DC_lastDC != DC )
{
wxBrush DrawBrush;
......@@ -1333,6 +1337,26 @@ void GRCircle( EDA_Rect* ClipBox, wxDC* DC, int x, int y, int r, int Color )
GRSCircle( ClipBox, DC, cx, cy, radius, 0, Color );
}
/*
* Draw a circle in object space.
*/
void GRCircle( EDA_Rect* ClipBox, wxDC* DC, int x, int y, int r, int width, int Color )
{
r = ZoomValue( r );
width = ZoomValue( width );
GRSCircle( ClipBox, DC, GRMapX( x ), GRMapY( y ), r, width, Color );
}
/*
* Draw a circle in object space.
*/
void GRCircle( EDA_Rect* aClipBox, wxDC* aDC, wxPoint aPos, int aRadius, int aWidth, int aColor )
{
aRadius = ZoomValue( aRadius );
aWidth = ZoomValue( aWidth );
GRSCircle( aClipBox, aDC, GRMapX( aPos.x ), GRMapY( aPos.y ), aRadius, aWidth, aColor );
}
/*
* Draw a filled circle, in object space.
......@@ -1346,6 +1370,14 @@ void GRFilledCircle( EDA_Rect* ClipBox, wxDC* DC, int x, int y, int r,
Color, BgColor );
}
/*
* Draw a filled circle, in object space.
*/
void GRFilledCircle( EDA_Rect* aClipBox, wxDC* aDC, wxPoint aPos, int aRadius, int aColor )
{
aRadius = ZoomValue( aRadius );
GRSFilledCircle( aClipBox, aDC, GRMapX( aPos.x ), GRMapY( aPos.y ), aRadius, 0, aColor, aColor );
}
/*
* Draw a filled circle, in drawing space.
......@@ -1377,22 +1409,6 @@ void GRSFilledCircle( EDA_Rect* ClipBox, wxDC* DC, int x, int y, int r,
}
/*
* Draw a circle in object space.
*/
void GRCircle( EDA_Rect* ClipBox,
wxDC* DC,
int x,
int y,
int r,
int width,
int Color )
{
r = ZoomValue( r );
width = ZoomValue( width );
GRSCircle( ClipBox, DC, GRMapX( x ), GRMapY( y ), r, width, Color );
}
/*
* Draw a circle in drawing space.
......
......@@ -15,6 +15,8 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}
###
set(GERBVIEW_SRCS
block.cpp
class_GERBER.cpp
class_gerber_draw_item.cpp
class_gerbview_layer_widget.cpp
controle.cpp
dcode.cpp
......@@ -32,7 +34,6 @@ set(GERBVIEW_SRCS
gerbview.cpp
hotkeys.cpp
initpcb.cpp
lay2plot.cpp
locate.cpp
menubar.cpp
onrightclick.cpp
......
......@@ -2,6 +2,30 @@
/* Block operations: displacement, rotation, deletion ... */
/**********************************************************/
/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 1992-2010 <Jean-Pierre Charras>
* 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 "gr_basic.h"
......@@ -11,17 +35,18 @@
#include "confirm.h"
#include "gerbview.h"
#include "class_gerber_draw_item.h"
#include "protos.h"
#define BLOCK_COLOR BROWN
static void DrawMovingBlockOutlines( WinEDA_DrawPanel* panel,
wxDC* DC,
bool erase );
static void DrawMovingBlockOutlines( WinEDA_DrawPanel* panel,
wxDC* DC,
bool erase );
static TRACK* IsSegmentInBox( BLOCK_SELECTOR& blocklocate, TRACK* PtSegm );
static bool IsGbrItemInBox( BLOCK_SELECTOR& aBlocklocate, GERBER_DRAW_ITEM* aItem );
/* Return the block command (BLOCK_MOVE, BLOCK_COPY...) corresponding to
......@@ -73,7 +98,7 @@ void WinEDA_GerberFrame::HandleBlockPlace( wxDC* DC )
{
err = TRUE;
DisplayError( this,
wxT( "Error in HandleBlockPLace : ManageCurseur = NULL" ) );
wxT( "Error in HandleBlockPLace : ManageCurseur = NULL" ) );
}
GetScreen()->m_BlockLocate.m_State = STATE_BLOCK_STOP;
......@@ -168,21 +193,10 @@ int WinEDA_GerberFrame::HandleBlockEnd( wxDC* DC )
Block_Delete( DC );
break;
case BLOCK_MIRROR_X: /* Mirror*/
GetScreen()->m_BlockLocate.m_State = STATE_BLOCK_STOP;
DrawPanel->ManageCurseur( DrawPanel, DC, FALSE );
Block_Mirror_X( DC );
break;
case BLOCK_ROTATE: /* Unused */
break;
case BLOCK_FLIP: /* Flip, unused */
break;
case BLOCK_SAVE: /* Save (not used)*/
break;
case BLOCK_MIRROR_X: /* Mirror, unused*/
case BLOCK_ROTATE: /* Unused */
case BLOCK_FLIP: /* Flip, unused */
case BLOCK_SAVE: /* Save (not used)*/
case BLOCK_PASTE:
break;
......@@ -273,28 +287,14 @@ void WinEDA_GerberFrame::Block_Delete( wxDC* DC )
GetScreen()->m_BlockLocate.Normalize();
GetScreen()->SetCurItem( NULL );
TRACK* pt_segm, * NextS;
for( pt_segm = m_Pcb->m_Track; pt_segm != NULL; pt_segm = NextS )
BOARD_ITEM* item = GetBoard()->m_Drawings;
BOARD_ITEM* nextitem;
for( ; item; item = nextitem )
{
NextS = pt_segm->Next();
if( IsSegmentInBox( GetScreen()->m_BlockLocate, pt_segm ) )
{
/* the track here is good to be cleared */
pt_segm->Draw( DrawPanel, DC, GR_XOR );
pt_segm->DeleteStructure();
}
}
/* Erasing areas. */
for( pt_segm = m_Pcb->m_Zone; pt_segm != NULL; pt_segm = NextS )
{
NextS = pt_segm->Next();
if( IsSegmentInBox( GetScreen()->m_BlockLocate, pt_segm ) )
{
/* The track here is good to be cleared. */
pt_segm->Draw( DrawPanel, DC, GR_XOR );
pt_segm->DeleteStructure();
}
nextitem = item->Next();
GERBER_DRAW_ITEM* gerb_item = (GERBER_DRAW_ITEM*) item;
if( IsGbrItemInBox( GetScreen()->m_BlockLocate, gerb_item ) )
gerb_item->DeleteStructure();
}
Refresh();
......@@ -320,106 +320,13 @@ void WinEDA_GerberFrame::Block_Move( wxDC* DC )
/* Calculate displacement vectors. */
delta = GetScreen()->m_BlockLocate.m_MoveVector;
/* Move the Track segments in block */
TRACK* track = m_Pcb->m_Track;
while( track )
/* Move items in block */
BOARD_ITEM* item = GetBoard()->m_Drawings;
for( ; item; item = item->Next() )
{
if( IsSegmentInBox( GetScreen()->m_BlockLocate, track ) )
{
m_Pcb->m_Status_Pcb = 0;
track->Draw( DrawPanel, DC, GR_XOR ); // erase the display
track->m_Start += delta;
track->m_End += delta;
// the two parameters are used in gerbview to store center
// coordinates for arcs. Move this center.
track->m_Param += delta.x;
track->SetSubNet( track->GetSubNet() + delta.y );
track->Draw( DrawPanel, DC, GR_OR ); // redraw the moved track
}
track = track->Next();
}
/* Move the Zone segments in block */
SEGZONE* zsegment = m_Pcb->m_Zone;
while( zsegment )
{
if( IsSegmentInBox( GetScreen()->m_BlockLocate, zsegment ) )
{
zsegment->Draw( DrawPanel, DC, GR_XOR ); // erase the display
zsegment->m_Start += delta;
zsegment->m_End += delta;
// the two parameters are used in gerbview to store center
// coordinates for arcs. Move this center
zsegment->m_Param += delta.x;
zsegment->SetSubNet( zsegment->GetSubNet() + delta.y );
zsegment->Draw( DrawPanel, DC, GR_OR ); // redraw the moved zone
// segment
}
zsegment = zsegment->Next();
}
DrawPanel->Refresh( TRUE );
}
/*
* Function to mirror items in the current selected block
*/
void WinEDA_GerberFrame::Block_Mirror_X( wxDC* DC )
{
int xoffset = 0;
wxPoint oldpos;
oldpos = GetScreen()->m_Curseur;
DrawPanel->ManageCurseur = NULL;
GetScreen()->m_Curseur = oldpos;
DrawPanel->MouseToCursorSchema();
GetScreen()->SetModify();
GetScreen()->m_BlockLocate.Normalize();
/* Calculate offset to mirror track points from block edges */
xoffset = GetScreen()->m_BlockLocate.m_Pos.x
+ GetScreen()->m_BlockLocate.m_Pos.x
+ GetScreen()->m_BlockLocate.m_Size.x;
/* Move the Track segments in block */
for( TRACK* track = m_Pcb->m_Track; track; track = track->Next() )
{
if( IsSegmentInBox( GetScreen()->m_BlockLocate, track ) )
{
m_Pcb->m_Status_Pcb = 0;
track->Draw( DrawPanel, DC, GR_XOR ); // erase the display
track->m_Start.x = xoffset - track->m_Start.x;
track->m_End.x = xoffset - track->m_End.x;
// the two parameters are used in gerbview to store center
// coordinates for arcs. Move this center
track->m_Param = xoffset - track->m_Param;
track->Draw( DrawPanel, DC, GR_OR ); // redraw the moved track
}
}
/* Move the Zone segments in block */
for( SEGZONE* zsegment = m_Pcb->m_Zone;
zsegment;
zsegment = zsegment->Next() )
{
if( IsSegmentInBox( GetScreen()->m_BlockLocate, zsegment ) )
{
zsegment->Draw( DrawPanel, DC, GR_XOR ); // erase the display
zsegment->m_Start.x = xoffset - zsegment->m_Start.x;
zsegment->m_End.x = xoffset - zsegment->m_End.x;
// the two parameters are used in gerbview to store center
// coordinates for arcs. Move this center
zsegment->m_Param = xoffset - zsegment->m_Param;
zsegment->Draw( DrawPanel, DC, GR_OR ); // redraw the moved zone
// segment
}
GERBER_DRAW_ITEM* gerb_item = (GERBER_DRAW_ITEM*) item;
if( IsGbrItemInBox( GetScreen()->m_BlockLocate, gerb_item ) )
gerb_item->Move( delta );
}
DrawPanel->Refresh( TRUE );
......@@ -444,62 +351,34 @@ void WinEDA_GerberFrame::Block_Duplicate( wxDC* DC )
delta = GetScreen()->m_BlockLocate.m_MoveVector;
/* Copy selected track segments and move the new track its new location */
TRACK* track = m_Pcb->m_Track;
while( track )
/* Copy items in block */
BOARD_ITEM* item = GetBoard()->m_Drawings;
for( ; item; item = item->Next() )
{
TRACK* next_track = track->Next();
if( IsSegmentInBox( GetScreen()->m_BlockLocate, track ) )
GERBER_DRAW_ITEM* gerb_item = (GERBER_DRAW_ITEM*) item;
if( IsGbrItemInBox( GetScreen()->m_BlockLocate, gerb_item ) )
{
/* this track segment must be duplicated */
m_Pcb->m_Status_Pcb = 0;
TRACK* new_track = track->Copy();
m_Pcb->Add( new_track );
new_track->m_Start += delta;
new_track->m_End += delta;
new_track->Draw( DrawPanel, DC, GR_OR ); // draw the new created
// segment
/* this item must be duplicated */
BOARD_ITEM* new_item = gerb_item->Copy();
new_item->Move( delta );
GetBoard()->m_Drawings.PushFront( new_item );
}
track = next_track;
}
/* Copy the Zone segments and move the new segment to its new location */
SEGZONE* zsegment = m_Pcb->m_Zone;
while( zsegment )
{
SEGZONE* next_zsegment = zsegment->Next();
if( IsSegmentInBox( GetScreen()->m_BlockLocate, zsegment ) )
{
/* this zone segment must be duplicated */
SEGZONE* new_zsegment = (SEGZONE*) zsegment->Copy();
m_Pcb->Add( new_zsegment );
new_zsegment->m_Start += delta;
new_zsegment->m_End += delta;
new_zsegment->Draw( DrawPanel, DC, GR_OR ); // draw the new created
// segment
}
zsegment = next_zsegment;
}
DrawPanel->Refresh();
}
/* Test if the structure PtStruct is listed in the block selects
* Returns whether PtSegm
* NULL if not
/* Test if the structure PtStruct is inside the block
* Returns true or false
*/
static TRACK* IsSegmentInBox( BLOCK_SELECTOR& blocklocate, TRACK* PtSegm )
bool IsGbrItemInBox( BLOCK_SELECTOR& aBlocklocate, GERBER_DRAW_ITEM* aItem )
{
if( blocklocate.Inside( PtSegm->m_Start.x, PtSegm->m_Start.y ) )
return PtSegm;
if( aBlocklocate.Inside( aItem->m_Start ) )
return true;
if( blocklocate.Inside( PtSegm->m_End.x, PtSegm->m_End.y ) )
return PtSegm;
if( aBlocklocate.Inside( aItem->m_End ) )
return true;
return NULL;
return false;
}
/** @file class_GERBER.cpp
* a GERBER class handle for a given layer info about used D_CODES and how the layer is drawn
*/
/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 1992-2010 <Jean-Pierre Charras>
* 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 "class_drawpanel.h"
#include "confirm.h"
#include "macros.h"
#include "gerbview.h"
/* Format Gerber: NOTES:
* Tools and D_CODES
* tool number (identification of shapes)
* 1 to 999
*
* D_CODES:
* D01 ... D9 = action codes:
* D01 = activating light (lower pen) when di placement
* D02 = light extinction (lift pen) when di placement
* D03 Flash
* D09 = VAPE Flash
* D10 ... = Indentification Tool (Opening)
*
* For tools:
* DCode min = D10
* DCode max = 999
*/
GERBER::GERBER( int aLayer )
{
m_Layer = aLayer; // Layer Number
m_Selected_Tool = FIRST_DCODE;
ResetDefaultValues();
for( unsigned ii = 0; ii < DIM( m_Aperture_List ); ii++ )
m_Aperture_List[ii] = 0;
m_Pcb = 0;
}
GERBER::~GERBER()
{
for( unsigned ii = 0; ii < DIM( m_Aperture_List ); ii++ )
{
delete m_Aperture_List[ii];
// m_Aperture_List[ii] = NULL;
}
delete m_Pcb;
}
D_CODE* GERBER::GetDCODE( int aDCODE, bool create )
{
unsigned ndx = aDCODE - FIRST_DCODE;
if( ndx < (unsigned) DIM( m_Aperture_List ) )
{
// lazily create the D_CODE if it does not exist.
if( create )
{
if( m_Aperture_List[ndx] == NULL )
m_Aperture_List[ndx] = new D_CODE( ndx + FIRST_DCODE );
}
return m_Aperture_List[ndx];
}
return NULL;
}
APERTURE_MACRO* GERBER::FindApertureMacro( const APERTURE_MACRO& aLookup )
{
APERTURE_MACRO_SET::iterator iter = m_aperture_macros.find( aLookup );
if( iter != m_aperture_macros.end() )
{
APERTURE_MACRO* pam = (APERTURE_MACRO*) &(*iter);
return pam;
}
return NULL; // not found
}
void GERBER::ResetDefaultValues()
{
m_FileName.Empty();
m_Name = wxT( "no name" ); // Layer name
m_LayerNegative = FALSE; // TRUE = Negative Layer
m_ImageNegative = FALSE; // TRUE = Negative image
m_GerbMetric = FALSE; // FALSE = Inches, TRUE = metric
m_Relative = FALSE; // FALSE = absolute Coord, RUE =
// relative Coord
m_NoTrailingZeros = FALSE; // True: trailing zeros deleted
m_MirorA = FALSE; // True: miror / axe A (X)
m_MirorB = FALSE; // True: miror / axe B (Y)
m_Has_DCode = FALSE; // TRUE = DCodes in file (FALSE = no
// DCode->
// separate DCode file
m_Offset.x = m_Offset.y = 0; // Coord Offset
m_FmtScale.x = m_FmtScale.y = g_Default_GERBER_Format % 10;
m_FmtLen.x = m_FmtLen.y = m_FmtScale.x + (g_Default_GERBER_Format / 10);
m_LayerScale.x = m_LayerScale.y = 1.0; // scale (X and Y) this
// layer
m_Rotation = 0;
m_Iterpolation = GERB_INTERPOL_LINEAR_1X; // Linear, 90 arc, Circ.
m_360Arc_enbl = FALSE; // 360 deg circular
// interpolation disable
m_Current_Tool = 0; // Current Tool (Dcode)
// number selected
m_CommandState = 0; // gives tate of the
// stacking order analysis
m_CurrentPos.x = m_CurrentPos.y = 0; // current specified coord
// for plot
m_PreviousPos.x = m_PreviousPos.y = 0; // old current specified
// coord for plot
m_IJPos.x = m_IJPos.y = 0; // current centre coord for
// plot arcs & circles
m_Current_File = NULL; // File to read
m_FilesPtr = 0;
m_Transform[0][0] = m_Transform[1][1] = 1;
m_Transform[0][1] = m_Transform[1][0] = 0; // Rotation/mirror = Normal
m_PolygonFillMode = FALSE;
m_PolygonFillModeState = 0;
}
int GERBER::ReturnUsedDcodeNumber()
{
int count = 0;
for( unsigned ii = 0; ii < DIM( m_Aperture_List ); ii++ )
{
if( m_Aperture_List[ii] )
if( m_Aperture_List[ii]->m_InUse || m_Aperture_List[ii]->m_Defined )
++count;
}
return count;
}
void GERBER::InitToolTable()
{
for( int count = 0; count < TOOLS_MAX_COUNT; count++ )
{
if( m_Aperture_List[count] == NULL )
continue;
m_Aperture_List[count]->m_Num_Dcode = count + FIRST_DCODE;
m_Aperture_List[count]->Clear_D_CODE_Data();
}
}
/*************************************
* file class_gerber_draw_item.cpp
*************************************/
/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 1992-2010 <Jean-Pierre Charras>
* 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 "polygons_defs.h"
#include "gr_basic.h"
#include "common.h"
#include "trigo.h"
#include "class_drawpanel.h"
#include "drawtxt.h"
#include "gerbview.h"
#include "class_board_design_settings.h"
#include "colors_selection.h"
#include "class_gerber_draw_item.h"
/**********************************************************/
GERBER_DRAW_ITEM::GERBER_DRAW_ITEM( BOARD_ITEM* aParent ) :
BOARD_ITEM( aParent, TYPE_GERBER_DRAW_ITEM )
/**********************************************************/
{
m_Layer = 0;
m_Shape = GBR_SEGMENT;
m_Flashed = false;
m_DCode = 0;
}
// Copy constructor
GERBER_DRAW_ITEM::GERBER_DRAW_ITEM( const GERBER_DRAW_ITEM& aSource ) :
BOARD_ITEM( aSource )
{
m_Shape = aSource.m_Shape;
m_Flags = aSource.m_Flags;
m_TimeStamp = aSource.m_TimeStamp;
SetStatus( aSource.ReturnStatus() );
m_Start = aSource.m_Start;
m_End = aSource.m_End;
m_Size = aSource.m_Size;
m_Layer = aSource.m_Layer;
m_Shape = aSource.m_Shape;
m_Flashed = aSource.m_Flashed;
m_DCode = aSource.m_DCode;
m_PolyCorners = aSource.m_PolyCorners;
}
GERBER_DRAW_ITEM::~GERBER_DRAW_ITEM()
{
}
GERBER_DRAW_ITEM* GERBER_DRAW_ITEM::Copy() const
{
return new GERBER_DRAW_ITEM( *this );
}
wxString GERBER_DRAW_ITEM::ShowGBRShape()
{
switch( m_Shape )
{
case GBR_SEGMENT:
return _( "Line" );
case GBR_ARC:
return _( "Arc" );
case GBR_CIRCLE:
return _( "Circle" );
case GBR_SPOT_OVAL:
return wxT( "spot_oval" );
case GBR_SPOT_CIRCLE:
return wxT( "spot_circle" );
case GBR_SPOT_RECT:
return wxT( "spot_rect" );
case GBR_POLYGON:
return wxT( "polygon" );
case GBR_MACRO:
return wxT( "apt_macro" ); // TODO: add aperture macro name
default:
return wxT( "??" );
}
}
/**
* Function GetDcodeDescr
* returns the GetDcodeDescr of this object, or NULL.
* @return D_CODE* - a pointer to the DCode description (for flashed items).
*/
D_CODE* GERBER_DRAW_ITEM::GetDcodeDescr()
{
if( (m_DCode < FIRST_DCODE) || (m_DCode > LAST_DCODE) )
return NULL;
GERBER* gerber = g_GERBER_List[m_Layer];
if( gerber == NULL )
return NULL;
D_CODE* d_code = gerber->GetDCODE( m_DCode, false );
return d_code;
}
EDA_Rect GERBER_DRAW_ITEM::GetBoundingBox()
{
// return a rectangle which is (pos,dim) in nature. therefore the +1
EDA_Rect bbox( m_Start, wxSize( 1, 1 ) );
bbox.Inflate( m_Size.x / 2, m_Size.y / 2 );
return bbox;
}
/**
* Function Move
* move this object.
* @param const wxPoint& aMoveVector - the move vector for this object.
*/
void GERBER_DRAW_ITEM::Move( const wxPoint& aMoveVector )
{
m_Start += aMoveVector;
m_End += aMoveVector;
m_ArcCentre += aMoveVector;
for( unsigned ii = 0; ii < m_PolyCorners.size(); ii++ )
m_PolyCorners[ii] += aMoveVector;
}
/** function Save.
* currently: no nothing, but must be defined to meet requirements
* of the basic class
*/
bool GERBER_DRAW_ITEM::Save( FILE* aFile ) const
{
return true;
}
/*********************************************************************/
void GERBER_DRAW_ITEM::Draw( WinEDA_DrawPanel* panel, wxDC* DC, int draw_mode,
const wxPoint& aOffset )
/*********************************************************************/
{
static D_CODE dummyD_CODE( 0 ); // used when a D_CODE is not found. default D_CODE to draw a flashed item
int color;
bool isFilled;
int radius;
int halfPenWidth;
static bool show_err;
BOARD* brd = GetBoard();
D_CODE* d_codeDescr = GetDcodeDescr();
if( d_codeDescr == NULL )
d_codeDescr = &dummyD_CODE;
if( m_Flags & DRAW_ERASED ) // draw in background color ("negative" color)
{
color = g_DrawBgColor;
}
else
{
if( brd->IsLayerVisible( GetLayer() ) == false )
return;
color = brd->GetLayerColor( GetLayer() );
if( draw_mode & GR_SURBRILL )
{
if( draw_mode & GR_AND )
color &= ~HIGHT_LIGHT_FLAG;
else
color |= HIGHT_LIGHT_FLAG;
}
if( color & HIGHT_LIGHT_FLAG )
color = ColorRefs[color & MASKCOLOR].m_LightColor;
}
GRSetDrawMode( DC, draw_mode );
isFilled = DisplayOpt.DisplayPcbTrackFill ? true : false;
switch( m_Shape )
{
case GBR_POLYGON:
isFilled = (g_DisplayPolygonsModeSketch == false);
if( m_Flags & DRAW_ERASED )
isFilled = true;
DrawGbrPoly( &panel->m_ClipBox, DC, color, aOffset, isFilled );
break;
case GBR_CIRCLE:
radius = (int) hypot( (double) ( m_End.x - m_Start.x ),
(double) ( m_End.y - m_Start.y ) );
halfPenWidth = m_Size.x >> 1;
if( isFilled == SKETCH )
{
// draw the border of the pen's path using two circles, each as narrow as possible
#ifdef USE_WX_ZOOM
if( DC->LogicalToDeviceXRel( halfPenWidth ) < L_MIN_DESSIN )
#else
if( panel->GetScreen()->Scale( halfPenWidth ) < L_MIN_DESSIN )
#endif
{
GRCircle( &panel->m_ClipBox, DC, m_Start.x,
m_Start.y, radius, 0, color );
}
else
{
GRCircle( &panel->m_ClipBox, DC, m_Start.x, m_Start.y,
radius - halfPenWidth, 0, color );
GRCircle( &panel->m_ClipBox, DC, m_Start.x, m_Start.y,
radius + halfPenWidth, 0, color );
}
}
else
{
GRCircle( &panel->m_ClipBox, DC, m_Start.x, m_Start.y,
radius, m_Size.x, color );
}
break;
case GBR_ARC:
if( !isFilled )
{
GRArc1( &panel->m_ClipBox, DC, m_Start.x, m_Start.y,
m_End.x, m_End.y,
m_ArcCentre.x, m_ArcCentre.y, 0, color );
}
else
{
GRArc1( &panel->m_ClipBox, DC, m_Start.x, m_Start.y,
m_End.x, m_End.y,
m_ArcCentre.x, m_ArcCentre.y,
m_Size.x, color );
}
break;
case GBR_SPOT_CIRCLE:
case GBR_SPOT_RECT:
case GBR_SPOT_OVAL:
isFilled = DisplayOpt.DisplayPadFill ? true : false;
d_codeDescr->DrawFlashedShape( &panel->m_ClipBox, DC, color,
m_Start, isFilled );
break;
case GBR_SEGMENT:
if( !isFilled )
GRCSegm( &panel->m_ClipBox, DC, m_Start.x, m_Start.y,
m_End.x, m_End.y, m_Size.x, color );
else
GRFillCSegm( &panel->m_ClipBox, DC, m_Start.x,
m_Start.y, m_End.x, m_End.y, m_Size.x, color );
break;
default:
if( !show_err )
{
wxMessageBox( wxT( "Trace_Segment() type error" ) );
show_err = TRUE;
}
break;
}
}
/** function DrawGbrPoly
* a helper function used id ::Draw to draw the polygon stored ion m_PolyCorners
* Draw filled polygons
*/
void GERBER_DRAW_ITEM::DrawGbrPoly( EDA_Rect* aClipBox,
wxDC* aDC,
int aColor,
const wxPoint& aOffset,
bool aFilledShape )
{
std::vector<wxPoint> points;
points = m_PolyCorners;
if( aOffset != wxPoint( 0, 0 ) )
{
for( unsigned ii = 0; ii < points.size(); ii++ )
{
points[ii] += aOffset;
}
}
GRClosedPoly( aClipBox, aDC, points.size(), &points[0], aFilledShape, aColor, aColor );
}
/** Function DisplayInfoBase
* has knowledge about the frame and how and where to put status information
* about this object into the frame's message panel.
* Display info about the track segment only, and does not calculate the full track length
* @param frame A WinEDA_DrawFrame in which to print status information.
*/
void GERBER_DRAW_ITEM::DisplayInfo( WinEDA_DrawFrame* frame )
{
wxString msg;
BOARD* board = ( (WinEDA_BasePcbFrame*) frame )->GetBoard();
frame->ClearMsgPanel();
msg = ShowGBRShape();
frame->AppendMsgPanel( _( "Type" ), msg, DARKCYAN );
/* Display layer */
msg = board->GetLayerName( m_Layer );
frame->AppendMsgPanel( _( "Layer" ), msg, BROWN );
}
/**
* Function HitTest
* tests if the given wxPoint is within the bounds of this object.
* @param ref_pos A wxPoint to test
* @return bool - true if a hit, else false
*/
bool GERBER_DRAW_ITEM::HitTest( const wxPoint& ref_pos )
{
// TODO: a better analyse od the shape (perhaps create a D_CODE::HitTest for flashed items)
int radius = MIN( m_Size.x, m_Size.y) >> 1;
// delta is a vector from m_Start to m_End (an origin of m_Start)
wxPoint delta = m_End - m_Start;
// dist is a vector from m_Start to ref_pos (an origin of m_Start)
wxPoint dist = ref_pos - m_Start;
if( m_Flashed )
{
return (double) dist.x * dist.x + (double) dist.y * dist.y <=
(double) radius * radius;
}
else
{
if( DistanceTest( radius, delta.x, delta.y, dist.x, dist.y ) )
return true;
}
return false;
}
/**
* Function HitTest (overlayed)
* tests if the given EDA_Rect intersect this object.
* For now, an ending point must be inside this rect.
* @param refArea : the given EDA_Rect
* @return bool - true if a hit, else false
*/
bool GERBER_DRAW_ITEM::HitTest( EDA_Rect& refArea )
{
if( refArea.Inside( m_Start ) )
return true;
if( refArea.Inside( m_End ) )
return true;
return false;
}
#if defined(DEBUG)
/**
* Function Show
* is used to output the object tree, currently for debugging only.
* @param nestLevel An aid to prettier tree indenting, and is the level
* of nesting of this object within the overall tree.
* @param os The ostream& to output to.
*/
void GERBER_DRAW_ITEM::Show( int nestLevel, std::ostream& os )
{
NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() <<
" shape=\"" << m_Shape << '"' <<
" addr=\"" << std::hex << this << std::dec << '"' <<
" layer=\"" << m_Layer << '"' <<
" size=\"" << m_Size << '"' <<
" flags=\"" << m_Flags << '"' <<
" status=\"" << GetState( -1 ) << '"' <<
"<start" << m_Start << "/>" <<
"<end" << m_End << "/>";
os << "</" << GetClass().Lower().mb_str() << ">\n";
}
#endif
/*******************************************************************/
/* class_gerber_draw_item.h: definitions relatives to tracks, vias and zones */
/*******************************************************************/
#ifndef CLASS_GERBER_DRAW_ITEM_H
#define CLASS_GERBER_DRAW_ITEM_H
/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 1992-2010 <Jean-Pierre Charras>
* 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 "base_struct.h"
/* Shapes id for basic shapes ( .m_Shape member ) */
enum Gbr_Basic_Shapes {
GBR_SEGMENT = 0, // usual segment : line with rounded ends
GBR_ARC, // Arcs (with rounded ends)
GBR_CIRCLE, // ring
GBR_POLYGON, // polygonal shape
GBR_SPOT_CIRCLE, // flashed shape: round shape (can have hole)
GBR_SPOT_RECT, // flashed shape: rectangular shape can have hole)
GBR_SPOT_OVAL, // flashed shape: oval shape
GBR_MACRO, // complex shape described by a macro
GBR_LAST // last value for this list
};
/***/
class GERBER_DRAW_ITEM : public BOARD_ITEM
{
// make SetNext() and SetBack() private so that they may not be called from anywhere.
// list management is done on GERBER_DRAW_ITEMs using DLIST<GERBER_DRAW_ITEM> only.
private:
void SetNext( EDA_BaseStruct* aNext ) { Pnext = aNext; }
void SetBack( EDA_BaseStruct* aBack ) { Pback = aBack; }
public:
int m_Layer;
int m_Shape; // Shape and type of this gerber item
wxPoint m_Start; // Line or arc start point or position of the shape
// for flashed items
wxPoint m_End; // Line or arc end point
wxPoint m_ArcCentre; // for arcs only: Centre of arc
std::vector <wxPoint> m_PolyCorners; // list of corners for polygons (G36 to G37 coordinates)
// or for complex shapes which are converted to polygon
wxSize m_Size; // Flashed shapes size of the shape
// Lines : m_Size.x = m_Size.y = line width
bool m_Flashed; // True for flashed items
int m_DCode; // DCode used to draw this item.
// 0 for items that do not use DCodes (polygons)
// or when unknown and normal values are 10 to 999
// values 0 to 9 can be used for special purposes
public:
GERBER_DRAW_ITEM( BOARD_ITEM* aParent );
GERBER_DRAW_ITEM( const GERBER_DRAW_ITEM& aSource );
~GERBER_DRAW_ITEM();
/**
* Function Copy
* will copy this object
* the corresponding type.
* @return - GERBER_DRAW_ITEM*
*/
GERBER_DRAW_ITEM* Copy() const;
GERBER_DRAW_ITEM* Next() const { return (GERBER_DRAW_ITEM*) Pnext; }
GERBER_DRAW_ITEM* Back() const { return (GERBER_DRAW_ITEM*) Pback; }
int ReturnMaskLayer()
{
return 1 << m_Layer;
}
/**
* Function Move
* move this object.
* @param const wxPoint& aMoveVector - the move vector for this object.
*/
void Move( const wxPoint& aMoveVector );
/**
* Function GetPosition
* returns the position of this object.
* @return const wxPoint& - The position of this object.
*/
wxPoint& GetPosition()
{
return m_Start; // it had to be start or end.
}
/**
* Function GetDcodeDescr
* returns the GetDcodeDescr of this object, or NULL.
* @return D_CODE* - a pointer to the DCode description (for flashed items).
*/
D_CODE* GetDcodeDescr();
EDA_Rect GetBoundingBox();
/* Display on screen: */
void Draw( WinEDA_DrawPanel* aPanel,
wxDC* aDC,
int aDrawMode,
const wxPoint& aOffset = ZeroOffset );
/** function DrawGbrPoly
* a helper function used id ::Draw to draw the polygon stored ion m_PolyCorners
*/
void DrawGbrPoly( EDA_Rect* aClipBox,
wxDC* aDC, int aColor,
const wxPoint& aOffset, bool aFilledShape );
/* divers */
int Shape() const { return m_Shape; }
/**
* Function DisplayInfo
* has knowledge about the frame and how and where to put status information
* about this object into the frame's message panel.
* Is virtual from EDA_BaseStruct.
* Display info about the track segment and the full track length
* @param frame A WinEDA_DrawFrame in which to print status information.
*/
void DisplayInfo( WinEDA_DrawFrame* frame );
wxString ShowGBRShape();
/**
* Function HitTest
* tests if the given wxPoint is within the bounds of this object.
* @param refPos A wxPoint to test
* @return bool - true if a hit, else false
*/
bool HitTest( const wxPoint& refPos );
/**
* Function HitTest (overlayed)
* tests if the given wxRect intersect this object.
* For now, an ending point must be inside this rect.
* @param refPos A wxPoint to test
* @return bool - true if a hit, else false
*/
bool HitTest( EDA_Rect& refArea );
/**
* Function GetClass
* returns the class name.
* @return wxString
*/
wxString GetClass() const
{
return wxT( "GERBER_DRAW_ITEM" );
}
bool Save( FILE* aFile ) const;
};
#endif /* CLASS_GERBER_DRAW_ITEM_H */
/***************************/
/**** Read GERBER files ****/
/**** class D_CODE ****/
/***************************/
#include "fctsys.h"
......@@ -7,53 +7,16 @@
#include "class_drawpanel.h"
#include "confirm.h"
#include "macros.h"
#include "trigo.h"
#include "gerbview.h"
#include "pcbplot.h"
#include "protos.h"
#include "class_gerber_draw_item.h"
#define DEFAULT_SIZE 100
/* Format Gerber: NOTES:
* Features history:
* Gn =
* G01 linear interpolation (right trace)
* G02, G20, G21 Circular interpolation, meaning trig < 0
* G03, G30, G31 Circular interpolation, meaning trig > 0
* G04 review
* G06 parabolic interpolation
* G07 Cubic Interpolation
* G10 linear interpolation (scale x10)
* G11 linear interpolation (0.1x range)
* G12 linear interpolation (0.01x scale)
* G52 plot symbol reference code by Dnn
* G53 plot symbol reference by Dnn; symbol rotates from -90 degrees
* G54 Selection Tool
* G55 Fashion photo exhibition
* G56 plot symbol reference code for DNN
* G57 displays the symbol link to the console
* G58 plot displays the symbol and link to the console
* G60 linear interpolation (scale x100)
* G70 Units = Inches
* G71 Units = Millimeters
* G74 circular interpolation removes 360 degree, has returned G01
* G75 circular interpolation Active 360 degree
* G90 mode absolute coordinates
* G91 Fashion Related Contacts
*
* Coordinates X, Y
* X and Y are followed by + or - and m + n digits (not separated)
* m = integer part
* n = part after the comma
* conventional formats: m = 2, n = 3 (size 2.3)
* m = 3, n = 4 (size 3.4)
* eg
* G__ X00345Y-06123 * D__
*
* Tools and D_CODES
* tool number (identification of shapes)
* 1 to 99 (Classical)
* 1 to 999
*
* D_CODES:
......@@ -62,145 +25,14 @@
* D02 = light extinction (lift pen) when di placement
* D03 Flash
* D09 = VAPE Flash
* D10 ... = Indentification Tool (Opening)
* D10 ... = Indentification Tool (Shape id)
*
* For tools:
* DCode min = D10
* DCode max = 999
*/
GERBER::GERBER( int aLayer )
{
m_Layer = aLayer; // Layer Number
m_Selected_Tool = FIRST_DCODE;
ResetDefaultValues();
for( unsigned ii = 0; ii < DIM( m_Aperture_List ); ii++ )
m_Aperture_List[ii] = 0;
m_Pcb = 0;
}
GERBER::~GERBER()
{
for( unsigned ii = 0; ii < DIM( m_Aperture_List ); ii++ )
{
delete m_Aperture_List[ii];
// m_Aperture_List[ii] = NULL;
}
delete m_Pcb;
}
D_CODE* GERBER::GetDCODE( int aDCODE, bool create )
{
unsigned ndx = aDCODE - FIRST_DCODE;
if( ndx < (unsigned) DIM( m_Aperture_List ) )
{
// lazily create the D_CODE if it does not exist.
if( create )
{
if( m_Aperture_List[ndx] == NULL )
m_Aperture_List[ndx] = new D_CODE( ndx + FIRST_DCODE );
}
return m_Aperture_List[ndx];
}
return NULL;
}
APERTURE_MACRO* GERBER::FindApertureMacro( const APERTURE_MACRO& aLookup )
{
APERTURE_MACRO_SET::iterator iter = m_aperture_macros.find( aLookup );
if( iter != m_aperture_macros.end() )
{
APERTURE_MACRO* pam = (APERTURE_MACRO*) &(*iter);
return pam;
}
return NULL; // not found
}
void GERBER::ResetDefaultValues()
{
m_FileName.Empty();
m_Name = wxT( "no name" ); // Layer name
m_LayerNegative = FALSE; // TRUE = Negative Layer
m_ImageNegative = FALSE; // TRUE = Negative image
m_GerbMetric = FALSE; // FALSE = Inches, TRUE = metric
m_Relative = FALSE; // FALSE = absolute Coord, RUE =
// relative Coord
m_NoTrailingZeros = FALSE; // True: trailing zeros deleted
m_MirorA = FALSE; // True: miror / axe A (X)
m_MirorB = FALSE; // True: miror / axe B (Y)
m_Has_DCode = FALSE; // TRUE = DCodes in file (FALSE = no
// DCode->
// separate DCode file
m_Offset.x = m_Offset.y = 0; // Coord Offset
m_FmtScale.x = m_FmtScale.y = g_Default_GERBER_Format % 10;
m_FmtLen.x = m_FmtLen.y = m_FmtScale.x + (g_Default_GERBER_Format / 10);
m_LayerScale.x = m_LayerScale.y = 1.0; // scale (X and Y) this
// layer
m_Rotation = 0;
m_Iterpolation = GERB_INTERPOL_LINEAR_1X; // Linear, 90 arc, Circ.
m_360Arc_enbl = FALSE; // 360 deg circular
// interpolation disable
m_Current_Tool = 0; // Current Tool (Dcode)
// number selected
m_CommandState = 0; // gives tate of the
// stacking order analysis
m_CurrentPos.x = m_CurrentPos.y = 0; // current specified coord
// for plot
m_PreviousPos.x = m_PreviousPos.y = 0; // old current specified
// coord for plot
m_IJPos.x = m_IJPos.y = 0; // current centre coord for
// plot arcs & circles
m_Current_File = NULL; // File to read
m_FilesPtr = 0;
m_Transform[0][0] = m_Transform[1][1] = 1;
m_Transform[0][1] = m_Transform[1][0] = 0; // Rotation/mirror = Normal
m_PolygonFillMode = FALSE;
m_PolygonFillModeState = 0;
}
int GERBER::ReturnUsedDcodeNumber()
{
int count = 0;
for( unsigned ii = 0; ii < DIM( m_Aperture_List ); ii++ )
{
if( m_Aperture_List[ii] )
if( m_Aperture_List[ii]->m_InUse || m_Aperture_List[ii]->m_Defined )
++count;
}
return count;
}
void GERBER::InitToolTable()
{
for( int count = 0; count < MAX_TOOLS; count++ )
{
if( m_Aperture_List[count] == NULL )
continue;
m_Aperture_List[count]->m_Num_Dcode = count + FIRST_DCODE;
m_Aperture_List[count]->Clear_D_CODE_Data();
}
}
/***************/
/* Class DCODE */
/***************/
......@@ -228,6 +60,7 @@ void D_CODE::Clear_D_CODE_Data()
m_InUse = FALSE;
m_Defined = FALSE;
m_Macro = 0;
m_Rotation = 0.0;
}
......@@ -370,7 +203,7 @@ int WinEDA_GerberFrame::Read_D_Code_File( const wxString& D_Code_FullFileName )
if( current_Dcode < FIRST_DCODE )
continue;
if( current_Dcode >= MAX_TOOLS )
if( current_Dcode >= TOOLS_MAX_COUNT )
continue;
dcode = gerber->GetDCODE( current_Dcode );
......@@ -393,134 +226,358 @@ void WinEDA_GerberFrame::CopyDCodesSizeToItems()
{
static D_CODE dummy( 999 ); //Used if D_CODE not found in list
for( TRACK* track = GetBoard()->m_Track; track; track = track->Next() )
{
GERBER* gerber = g_GERBER_List[track->GetLayer()];
wxASSERT( gerber );
BOARD_ITEM* item = GetBoard()->m_Drawings;
D_CODE* dcode = gerber->GetDCODE( track->GetNet(), false );
for( ; item; item = item->Next() )
{
GERBER_DRAW_ITEM* gerb_item = (GERBER_DRAW_ITEM*) item;
D_CODE* dcode = gerb_item->GetDcodeDescr();
wxASSERT( dcode );
if( dcode == NULL )
dcode = &dummy;
dcode->m_InUse = TRUE;
if( // Line Item
(track->m_Shape == S_SEGMENT ) /* rectilinear segment */
|| (track->m_Shape == S_RECT ) /* rect segment form (i.e.
* non-rounded ends) */
|| (track->m_Shape == S_ARC ) /* segment arc (rounded tips) */
|| (track->m_Shape == S_CIRCLE ) /* segment in a circle (ring) */
|| (track->m_Shape == S_ARC_RECT ) /* segment arc (stretches)
* (GERBER)*/
gerb_item->m_Size = dcode->m_Size;
if( // Line Item
(gerb_item->m_Shape == GBR_SEGMENT ) /* rectilinear segment */
|| (gerb_item->m_Shape == GBR_ARC ) /* segment arc (rounded tips) */
|| (gerb_item->m_Shape == GBR_CIRCLE ) /* segment in a circle (ring) */
)
{
track->m_Width = dcode->m_Size.x;
}
else // Spots ( Flashed Items )
{
int width, len;
wxSize size = dcode->m_Size;
width = MIN( size.x, size.y );
len = MAX( size.x, size.y ) - width;
track->m_Width = width;
track->m_Start.x = (track->m_Start.x + track->m_End.x) / 2;
track->m_Start.y = (track->m_Start.y + track->m_End.y) / 2;
track->m_End = track->m_Start; // m_Start = m_End = Spot center
switch( dcode->m_Shape )
{
case APT_LINE: // might not appears here, but some broken
// gerber files use it
// gerber files use it
case APT_CIRCLE: /* spot round (for GERBER) */
track->m_Shape = S_SPOT_CIRCLE;
gerb_item->m_Shape = GBR_SPOT_CIRCLE;
break;
case APT_OVAL: /* spot oval (for GERBER)*/
track->m_Shape = S_SPOT_OVALE;
gerb_item->m_Shape = GBR_SPOT_OVAL;
break;
default: /* spot rect (for GERBER)*/
track->m_Shape = S_SPOT_RECT;
gerb_item->m_Shape = GBR_SPOT_RECT;
break;
}
}
}
}
len >>= 1;
if( size.x > size.y )
/** function DrawFlashedShape
* Draw the dcode shape for flashed items.
* When an item is flashed, the DCode shape is the shape of the item
*/
void D_CODE::DrawFlashedShape( EDA_Rect* aClipBox, wxDC* aDC, int aColor,
wxPoint aShapePos, bool aFilledShape )
{
int radius;
switch( m_Shape )
{
case APT_CIRCLE:
radius = m_Size.x >> 1;
if( !aFilledShape )
GRCircle( aClipBox, aDC, aShapePos.x, aShapePos.y, radius, aColor );
else
if( m_DrillShape == 0 )
GRFilledCircle( aClipBox, aDC, aShapePos, radius, aColor );
else if( m_DrillShape == 1 ) // round hole
{
track->m_Start.x -= len;
track->m_End.x += len;
int width = (m_Size.x - m_Drill.x ) / 2;
GRCircle( aClipBox, aDC, aShapePos, radius - (width / 2), width, aColor );
}
else
else // rectangular hole
{
track->m_Start.y -= len;
track->m_End.y += len;
if( m_PolyCorners.size() == 0 )
ConvertShapeToPolygon();
DrawFlashedPolygon( aClipBox, aDC, aColor, aFilledShape, aShapePos );
}
break;
case APT_LINE:
// not used for flashed items
break;
case APT_RECT:
{
wxPoint start;
start.x = aShapePos.x - m_Size.x/2;
start.y = aShapePos.y - m_Size.y/2;
wxPoint end = start + m_Size;
if( !aFilledShape )
{
GRRect( aClipBox, aDC, start.x, start.y, end.x, end.y ,
0, aColor );
}
else if( m_DrillShape == 0 )
{
GRFilledRect( aClipBox, aDC, start.x, start.y, end.x, end.y,
0, aColor, aColor );
}
else
{
if( m_PolyCorners.size() == 0 )
ConvertShapeToPolygon();
DrawFlashedPolygon( aClipBox, aDC, aColor, aFilledShape, aShapePos );
}
}
break;
case APT_OVAL:
{
wxPoint start = aShapePos;
wxPoint end = aShapePos;
if( m_Size.x > m_Size.y ) // horizontal oval
{
int delta = (m_Size.x - m_Size.y) / 2;
start.x -= delta;
end.x += delta;
radius = m_Size.y;
}
else // horizontal oval
{
int delta = (m_Size.y - m_Size.x) / 2;
start.y -= delta;
end.y += delta;
radius = m_Size.x;
}
if( !aFilledShape )
{
GRCSegm( aClipBox, aDC, start.x, start.y,
end.x, end.y, radius, aColor );
}
else if( m_DrillShape == 0 )
{
GRFillCSegm( aClipBox, aDC, start.x,
start.y, end.x, end.y, radius, aColor );
}
else
{
if( m_PolyCorners.size() == 0 )
ConvertShapeToPolygon();
DrawFlashedPolygon( aClipBox, aDC, aColor, aFilledShape, aShapePos );
}
}
break;
case APT_POLYGON:
if( m_PolyCorners.size() == 0 )
ConvertShapeToPolygon();
DrawFlashedPolygon( aClipBox, aDC, aColor, aFilledShape, aShapePos );
break;
case APT_MACRO:
// TODO
break;
}
}
void WinEDA_GerberFrame::Liste_D_Codes( )
/** function DrawFlashedPolygon
* a helper function used id ::Draw to draw the polygon stored ion m_PolyCorners
* Draw some Apertures shapes when they are defined as filled polygons.
* APT_POLYGON is always a polygon, but some complex shapes are also converted to
* polygons (shapes with holes)
*/
void D_CODE::DrawFlashedPolygon( EDA_Rect* aClipBox, wxDC* aDC,
int aColor, bool aFilled,
const wxPoint& aPosition )
{
int ii, jj;
D_CODE* pt_D_code;
wxString Line;
WinEDA_TextFrame* List;
int scale = 10000;
int curr_layer = GetScreen()->m_Active_Layer;
if( m_PolyCorners.size() == 0 )
return;
List = new WinEDA_TextFrame( this, _( "List D codes" ) );
std::vector<wxPoint> points;
points = m_PolyCorners;
for( unsigned ii = 0; ii < points.size(); ii++ )
{
points[ii] += aPosition;
}
for( int layer = 0; layer < 32; layer++ )
GRClosedPoly( aClipBox, aDC, points.size(), &points[0], aFilled, aColor, aColor );
}
/** 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 D_CODE::ConvertShapeToPolygon()
{
#define SEGS_CNT 32 // number of segments to approximate a circle
wxPoint initialpos;
wxPoint currpos;;
m_PolyCorners.clear();
switch( m_Shape )
{
GERBER* gerber = g_GERBER_List[layer];
if( gerber == NULL )
continue;
case APT_CIRCLE: // creates only a circle with rectangular hole
currpos.x = m_Size.x >> 1;
initialpos = currpos;
for( unsigned ii = 0; ii <= SEGS_CNT; ii++ )
{
currpos = initialpos;
RotatePoint( &currpos, ii * 3600 / SEGS_CNT );
m_PolyCorners.push_back( currpos );
}
if( m_DrillShape == 1 )
{
for( unsigned ii = 0 ; ii <= SEGS_CNT; ii++ )
{
currpos.x = m_Drill.x / 2;
currpos.y = 0;
RotatePoint( &currpos, ii * 3600 / SEGS_CNT );
m_PolyCorners.push_back( currpos );
}
m_PolyCorners.push_back( initialpos ); // link to outline
}
if( m_DrillShape == 2 ) // Create rectangular hole
{
currpos.x = m_Drill.x / 2;
currpos.y = m_Drill.y / 2;
m_PolyCorners.push_back( currpos ); // link to hole and begin hole
currpos.x -= m_Drill.x;
m_PolyCorners.push_back( currpos );
currpos.y -= m_Drill.y;
m_PolyCorners.push_back( currpos );
currpos.x += m_Drill.x;
m_PolyCorners.push_back( currpos );
currpos.y += m_Drill.y;
m_PolyCorners.push_back( currpos ); // close hole
m_PolyCorners.push_back( initialpos ); // link to outline
}
break;
if( gerber->ReturnUsedDcodeNumber() == 0 )
continue;
case APT_LINE:
// Not used for flashed shapes
break;
if( layer == curr_layer )
Line.Printf( wxT( "*** Active layer (%2.2d) ***" ), layer + 1 );
else
Line.Printf( wxT( "*** layer %2.2d ***" ), layer + 1 );
List->Append( Line );
case APT_RECT:
currpos.x = m_Size.x / 2;
currpos.y = m_Size.y / 2;
initialpos = currpos;
m_PolyCorners.push_back( currpos );
currpos.x -= m_Size.x;
m_PolyCorners.push_back( currpos );
currpos.y -= m_Size.y;
m_PolyCorners.push_back( currpos );
currpos.x += m_Size.x;
m_PolyCorners.push_back( currpos );
currpos.y += m_Size.y;
m_PolyCorners.push_back( currpos ); // close polygon
if( m_DrillShape == 1 ) // build a round hole
{
for( int ii = 0 ; ii <= SEGS_CNT; ii++ )
{
currpos.x = 0;
currpos.y = m_Drill.x / 2; // m_Drill.x / 2 is the radius of the hole
RotatePoint( &currpos, ii * 3600 / SEGS_CNT );
m_PolyCorners.push_back( currpos );
}
m_PolyCorners.push_back( initialpos ); // link to outline
}
if( m_DrillShape == 2 ) // Create rectangular hole
{
currpos.x = m_Drill.x / 2;
currpos.y = m_Drill.y / 2;
m_PolyCorners.push_back( currpos ); // link to hole and begin hole
currpos.x -= m_Drill.x;
m_PolyCorners.push_back( currpos );
currpos.y -= m_Drill.y;
m_PolyCorners.push_back( currpos );
currpos.x += m_Drill.x;
m_PolyCorners.push_back( currpos );
currpos.y += m_Drill.y;
m_PolyCorners.push_back( currpos ); // close hole
m_PolyCorners.push_back( initialpos ); // link to outline
}
break;
for( ii = 0, jj = 1; ii < MAX_TOOLS; ii++ )
case APT_OVAL:
{
int delta, radius;
// we create an horizontal oval shape. then rotate if needed
if( m_Size.x > m_Size.y ) // horizontal oval
{
pt_D_code = gerber->GetDCODE( ii + FIRST_DCODE, false );
if( pt_D_code == NULL )
continue;
if( !pt_D_code->m_InUse && !pt_D_code->m_Defined )
continue;
Line.Printf( wxT(
"tool %2.2d: D%2.2d V %2.4f H %2.4f %s" ),
jj,
pt_D_code->m_Num_Dcode,
(float) pt_D_code->m_Size.y / scale,
(float) pt_D_code->m_Size.x / scale,
D_CODE::ShowApertureType( pt_D_code->m_Shape )
);
if( !pt_D_code->m_Defined )
Line += wxT( " ?" );
if( !pt_D_code->m_InUse )
Line += wxT( " *" );
List->Append( Line );
jj++;
delta = (m_Size.x - m_Size.y) / 2;
radius = m_Size.y / 2;
}
else // vertical oval
{
delta = (m_Size.y - m_Size.x) / 2;
radius = m_Size.x / 2;
}
currpos.y = radius;
initialpos = currpos;
m_PolyCorners.push_back( currpos );
// build the right arc of the shape
unsigned ii = 0;
for( ; ii <= SEGS_CNT / 2; ii++ )
{
currpos = initialpos;
RotatePoint( &currpos, ii * 3600 / SEGS_CNT );
currpos.x += delta;
m_PolyCorners.push_back( currpos );
}
// build the left arc of the shape
for( ii = SEGS_CNT / 2; ii <= SEGS_CNT; ii++ )
{
currpos = initialpos;
RotatePoint( &currpos, ii * 3600 / SEGS_CNT );
currpos.x -= delta;
m_PolyCorners.push_back( currpos );
}
m_PolyCorners.push_back( initialpos ); // close outline
if( m_Size.y > m_Size.x ) // vertical oval, rotate polygon.
{
for( unsigned jj = 0; jj < m_PolyCorners.size(); jj++ )
RotatePoint( &m_PolyCorners[jj], 900 );
}
if( m_DrillShape == 1 ) // build a round hole
{
for( ii = 0 ; ii <= SEGS_CNT; ii++ )
{
currpos.x = 0;
currpos.y = m_Drill.x / 2; // m_Drill.x / 2 is the radius of the hole
RotatePoint( &currpos, ii * 3600 / SEGS_CNT );
m_PolyCorners.push_back( currpos );
}
m_PolyCorners.push_back( initialpos ); // link to outline
}
if( m_DrillShape == 2 ) // Create rectangular hole
{
currpos.x = m_Drill.x / 2;
currpos.y = m_Drill.y / 2;
m_PolyCorners.push_back( currpos ); // link to hole and begin hole
currpos.x -= m_Drill.x;
m_PolyCorners.push_back( currpos );
currpos.y -= m_Drill.y;
m_PolyCorners.push_back( currpos );
currpos.x += m_Drill.x;
m_PolyCorners.push_back( currpos );
currpos.y += m_Drill.y;
m_PolyCorners.push_back( currpos ); // close hole
m_PolyCorners.push_back( initialpos ); // link to outline
}
}
break;
ii = List->ShowModal();
List->Destroy();
if( ii < 0 )
return;
case APT_POLYGON:
// TODO
break;
case APT_MACRO:
// TODO
break;
}
}
/**************/
/* dcode.h */
/**************/
#ifndef _DCODE_H_
#define _DCODE_H_
#include <vector>
#include <set>
#include "base_struct.h"
/**
* Enum APERTURE_T
* is the set of all gerber aperture types allowed, according to page 16 of
* http://gerbv.sourceforge.net/docs/rs274xrevd_e.pdf
*/
enum APERTURE_T
{
APT_CIRCLE = 'C',
APT_LINE = 'L',
APT_RECT = 'R',
APT_OVAL = '0',
APT_POLYGON = 'P',
APT_MACRO = 'M'
};
#define FIRST_DCODE 10
#define LAST_DCODE 999 // dcodes values are from 10 to 999
#define TOOLS_MAX_COUNT (LAST_DCODE+1)
class D_CODE;
/**
* Class DCODE_PARAM
* holds a parameter for a DCODE or an "aperture macro" as defined within
* standard RS274X. The \a value field can be a constant, i.e. "immediate"
* parameter or it may not be used if this param is going to defer to the
* referencing aperture macro. In that case, the \a index field is an index
* into the aperture macro's parameters.
*/
class DCODE_PARAM
{
public:
DCODE_PARAM() :
index(-1),
value(0.0)
{}
double GetValue( const D_CODE* aDcode ) const;
void SetValue( double aValue )
{
value = aValue;
index = -1;
}
/**
* Function IsImmediate
* tests if this DCODE_PARAM holds an immediate parameter or is a pointer
* into a parameter held by an owning D_CODE.
*/
bool IsImmediate() const { return index == -1; }
unsigned GetIndex() const
{
return (unsigned) index;
}
void SetIndex( int aIndex )
{
index = aIndex;
}
private:
int index; ///< if -1, then \a value field is an immediate value,
// else this is an index into parent's
// D_CODE.m_am_params.
double value; ///< if IsImmediate()==true then use the value, else
// not used.
};
/**
* 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
*/
enum AM_PRIMITIVE_ID
{
AMP_CIRCLE = 1,
AMP_LINE2 = 2,
AMP_LINE20 = 20,
AMP_LINE_CENTER = 21,
AMP_LINE_LOWER_LEFT = 22,
AMP_EOF = 3,
AMP_OUTLINE = 4,
AMP_POLYGON = 5,
AMP_MOIRE = 6,
AMP_THERMAL = 7,
};
typedef std::vector<DCODE_PARAM> DCODE_PARAMS;
/**
* Struct AM_PRIMITIVE
* holds an aperture macro primitive as given in Table 3 of
* http://gerbv.sourceforge.net/docs/rs274xrevd_e.pdf
*/
struct AM_PRIMITIVE
{
AM_PRIMITIVE_ID primitive_id; ///< The primitive type
DCODE_PARAMS params; ///< A sequence of parameters used by
// the 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 );
}
};
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
};
/**
* 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;
/**
* Class D_CODE
* holds a gerber DCODE definition.
*/
class D_CODE
{
friend class DCODE_PARAM;
APERTURE_MACRO* m_Macro; ///< no ownership, points to
// GERBER.m_aperture_macros element
/**
* parameters used only when this D_CODE holds a reference to an aperture
* macro, and these parameters would customize the macro.
*/
DCODE_PARAMS m_am_params;
std::vector <wxPoint> m_PolyCorners; /* Polygon used to draw AMP_POLYGON shape and some other
* complex shapes which are converted to polygon
* (shapes with hole, rotated rectangles ...
*/
public:
wxSize m_Size; /* Horizontal and vertical dimensions. */
APERTURE_T m_Shape; /* shape ( Line, rectangle, circle , oval .. ) */
int m_Num_Dcode; /* D code ( >= 10 ) */
wxSize m_Drill; /* dimension of the hole (if any) */
int m_DrillShape; /* shape of the hole (round = 1, rect = 2) */
double m_Rotation; /* shape rotation in degrees */
bool m_InUse; /* FALSE if not used */
bool m_Defined; /* FALSE if not defined */
wxString m_SpecialDescr;
public:
D_CODE( int num_dcode );
~D_CODE();
void Clear_D_CODE_Data();
void AppendParam( double aValue )
{
DCODE_PARAM param;
param.SetValue( aValue );
m_am_params.push_back( param );
}
void SetMacro( APERTURE_MACRO* aMacro )
{
m_Macro = aMacro;
}
APERTURE_MACRO* GetMacro() { return m_Macro; }
/**
* Function ShowApertureType
* returns a character string telling what type of aperture type \a aType is.
* @param aType The aperture type to show.
*/
static const wxChar* ShowApertureType( APERTURE_T aType );
/** function DrawFlashedShape
* Draw the dcode shape for flashed items.
* When an item is flashed, the DCode shape is the shape of the item
*/
void DrawFlashedShape( EDA_Rect* aClipBox, wxDC* aDC, int aColor,
wxPoint aShapePos, bool aFilledShape );
/** function DrawFlashedPolygon
* a helper function used id ::Draw to draw the polygon stored ion m_PolyCorners
* Draw some Apertures shapes when they are defined as filled polygons.
* APT_POLYGON is always a polygon, but some complex shapes are also converted to
* polygons (shapes with holes, some rotated shapes)
*/
void DrawFlashedPolygon( EDA_Rect* aClipBox, wxDC* aDC, int aColor,
bool aFilled, const wxPoint& aPosition );
/** 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( );
};
inline double DCODE_PARAM::GetValue( const D_CODE* aDcode ) const
{
if( IsImmediate() )
return value;
else
{
// the first one was numbered 1, not zero, as in $1, see page 19 of spec.
unsigned ndx = GetIndex() - 1;
wxASSERT(aDcode);
// get the parameter from the aDcode
if( ndx < aDcode->m_am_params.size() )
return aDcode->m_am_params[ndx].GetValue( NULL );
else
{
wxASSERT( GetIndex()-1 < aDcode->m_am_params.size() );
return 0.0;
}
}
}
#endif // ifndef _DCODE_H_
/*********************************************/
/* Edit Track: Erase Routines */
/* Drop the segment, track, and net area */
/* Edit Track: Erase functions */
/*********************************************/
#include "fctsys.h"
#include "common.h"
#include "class_drawpanel.h"
//#include "class_drawpanel.h"
#include "gerbview.h"
#include "protos.h"
#include "class_gerber_draw_item.h"
void WinEDA_GerberFrame::Delete_DCode_Items( wxDC* DC,
......@@ -18,73 +17,22 @@ void WinEDA_GerberFrame::Delete_DCode_Items( wxDC* DC,
if( dcode_value < FIRST_DCODE ) // No tool selected
return;
TRACK* next;
for( TRACK* track = GetBoard()->m_Track; track; track = next )
BOARD_ITEM* item = GetBoard()->m_Drawings;
BOARD_ITEM * next;
for( ; item; item = next )
{
next = track->Next();
next = item->Next();
GERBER_DRAW_ITEM* gerb_item = (GERBER_DRAW_ITEM*) item;
if( dcode_value != track->GetNet() )
if( dcode_value != gerb_item->m_DCode )
continue;
if( layer_number >= 0 && layer_number != track->GetLayer() )
if( layer_number >= 0 && layer_number != gerb_item->m_Layer )
continue;
Delete_Segment( DC, track );
// TODO: Delete_Item( DC, item );
}
GetScreen()->SetCurItem( NULL );
}
/* Removes 1 segment of track.
*
* If There is evidence of new track: erase segment
* Otherwise: Delete segment under the cursor.
*/
TRACK* WinEDA_GerberFrame::Delete_Segment( wxDC* DC, TRACK* Track )
{
if( Track == NULL )
return NULL;
if( Track->m_Flags & IS_NEW ) // Trace in progress, delete the last
// segment
{
if( g_CurrentTrackList.GetCount() > 0 )
{
// Change track.
delete g_CurrentTrackList.PopBack();
if( g_CurrentTrackList.GetCount()
&& g_CurrentTrackSegment->Type() == TYPE_VIA )
{
delete g_CurrentTrackList.PopBack();
}
UpdateStatusBar();
if( g_CurrentTrackList.GetCount() == 0 )
{
DrawPanel->ManageCurseur = NULL;
DrawPanel->ForceCloseManageCurseur = NULL;
return NULL;
}
else
{
if( DrawPanel->ManageCurseur )
DrawPanel->ManageCurseur( DrawPanel, DC, FALSE );
return g_CurrentTrackSegment;
}
}
return NULL;
}
Trace_Segment( GetBoard(), DrawPanel, DC, Track, GR_XOR );
DLIST<TRACK>* container = (DLIST<TRACK>*)Track->GetList();
wxASSERT( container );
container->Remove( Track );
GetScreen()->SetModify();
return NULL;
}
......@@ -10,7 +10,6 @@
#include "common.h"
#include "pcbnew.h"
TRACK* Marque_Une_Piste( BOARD* aPcb,
TRACK* aStartSegm,
int* aSegmCount,
......@@ -19,3 +18,4 @@ TRACK* Marque_Une_Piste( BOARD* aPcb,
{
return NULL;
}
......@@ -53,12 +53,11 @@ void WinEDA_GerberFrame::OnLeftClick( wxDC* DC, const wxPoint& MousePos )
DrawStruct = GerberGeneralLocateAndDisplay();
if( DrawStruct == NULL )
break;
if( DrawStruct->Type() == TYPE_TRACK )
{
Delete_Segment( DC, (TRACK*) DrawStruct );
GetScreen()->SetCurItem( NULL );
GetScreen()->SetModify();
}
/* TODO:
Delete_Item( DC, (GERBER_DRAW_ITEM*) DrawStruct );
GetScreen()->SetCurItem( NULL );
GetScreen()->SetModify();
*/
break;
default:
......@@ -85,13 +84,9 @@ void WinEDA_GerberFrame::Process_Special_Functions( wxCommandEvent& event )
{
case wxID_CUT:
case wxID_COPY:
case ID_POPUP_MIRROR_X_BLOCK:
case ID_POPUP_DELETE_BLOCK:
case ID_POPUP_PLACE_BLOCK:
case ID_POPUP_ZOOM_BLOCK:
case ID_POPUP_FLIP_BLOCK:
case ID_POPUP_ROTATE_BLOCK:
case ID_POPUP_COPY_BLOCK:
break;
case ID_POPUP_CANCEL_CURRENT_COMMAND:
......@@ -196,13 +191,6 @@ void WinEDA_GerberFrame::Process_Special_Functions( wxCommandEvent& event )
HandleBlockPlace( &dc );
break;
case ID_POPUP_COPY_BLOCK:
GetScreen()->m_BlockLocate.m_Command = BLOCK_COPY;
GetScreen()->m_BlockLocate.SetMessageBlock( this );
DrawPanel->m_AutoPAN_Request = FALSE;
HandleBlockEnd( &dc );
break;
case ID_POPUP_ZOOM_BLOCK:
GetScreen()->m_BlockLocate.m_Command = BLOCK_ZOOM;
GetScreen()->m_BlockLocate.SetMessageBlock( this );
......@@ -216,12 +204,6 @@ void WinEDA_GerberFrame::Process_Special_Functions( wxCommandEvent& event )
HandleBlockEnd( &dc );
break;
case ID_POPUP_MIRROR_X_BLOCK:
GetScreen()->m_BlockLocate.m_Command = BLOCK_MIRROR_X;
GetScreen()->m_BlockLocate.SetMessageBlock( this );
HandleBlockEnd( &dc );
break;
case ID_GERBVIEW_POPUP_DELETE_DCODE_ITEMS:
if( gerber_layer )
Delete_DCode_Items( &dc, gerber_layer->m_Selected_Tool,
......
......@@ -13,6 +13,7 @@
#include "gerbview.h"
#include "class_board_design_settings.h"
#include "class_gerber_draw_item.h"
#include "protos.h"
static int SavePcbFormatAscii( WinEDA_GerberFrame* frame,
......@@ -128,7 +129,6 @@ static int SavePcbFormatAscii( WinEDA_GerberFrame* frame, FILE* aFile,
int* LayerLookUpTable )
{
char line[256];
TRACK* track;
BOARD* gerberPcb = frame->GetBoard();
BOARD* pcb;
......@@ -136,10 +136,11 @@ static int SavePcbFormatAscii( WinEDA_GerberFrame* frame, FILE* aFile,
// create an image of gerber data
pcb = new BOARD( NULL, frame );
for( track = gerberPcb->m_Track; track; track = track->Next() )
BOARD_ITEM* item = gerberPcb->m_Drawings;
for( ; item; item = item->Next() )
{
int layer = track->GetLayer();
GERBER_DRAW_ITEM* gerb_item = (GERBER_DRAW_ITEM*) item;
int layer = gerb_item->m_Layer;
int pcb_layer_number = LayerLookUpTable[layer];
if( pcb_layer_number < 0 || pcb_layer_number > LAST_NO_COPPER_LAYER )
continue;
......@@ -149,17 +150,17 @@ static int SavePcbFormatAscii( WinEDA_GerberFrame* frame, FILE* aFile,
DRAWSEGMENT* drawitem = new DRAWSEGMENT( pcb, TYPE_DRAWSEGMENT );
drawitem->SetLayer( pcb_layer_number );
drawitem->m_Start = track->m_Start;
drawitem->m_End = track->m_End;
drawitem->m_Width = track->m_Width;
drawitem->m_Start = gerb_item->m_Start;
drawitem->m_End = gerb_item->m_End;
drawitem->m_Width = gerb_item->m_Size.x;
if( track->m_Shape == S_ARC )
if( gerb_item->m_Shape == GBR_ARC )
{
double cx = track->m_Param;
double cy = track->GetSubNet();
double a = atan2( track->m_Start.y - cy,
track->m_Start.x - cx );
double b = atan2( track->m_End.y - cy, track->m_End.x - cx );
double cx = gerb_item->m_ArcCentre.x;
double cy = gerb_item->m_ArcCentre.y;
double a = atan2( gerb_item->m_Start.y - cy,
gerb_item->m_Start.x - cx );
double b = atan2( gerb_item->m_End.y - cy, gerb_item->m_End.x - cx );
drawitem->m_Shape = S_ARC;
drawitem->m_Angle = (int) fmod(
......@@ -175,34 +176,28 @@ static int SavePcbFormatAscii( WinEDA_GerberFrame* frame, FILE* aFile,
TRACK* newtrack;
// replace spots with vias when possible
if( track->m_Shape == S_SPOT_CIRCLE
|| track->m_Shape == S_SPOT_RECT
|| track->m_Shape == S_SPOT_OVALE )
if( gerb_item->m_Shape == GBR_SPOT_CIRCLE
|| gerb_item->m_Shape == GBR_SPOT_RECT
|| gerb_item->m_Shape == GBR_SPOT_OVAL )
{
newtrack = new SEGVIA( (const SEGVIA &) * track );
newtrack = new SEGVIA( pcb );
// A spot is found, and can be a via: change it to via, and
// delete other
// spots at same location
newtrack->m_Shape = VIA_THROUGH;
newtrack->SetLayer( 0x0F ); // Layers are 0 to 15 (Cu/Cmp)
newtrack->SetDrillDefault();
// Compute the via position from track position ( Via position
// is the
// position of the middle of the track segment )
newtrack->m_Start.x =
(newtrack->m_Start.x + newtrack->m_End.x) / 2;
newtrack->m_Start.y =
(newtrack->m_Start.y + newtrack->m_End.y) / 2;
newtrack->m_End = newtrack->m_Start;
newtrack->m_Start = newtrack->m_End = gerb_item->m_Start;
newtrack->m_Width = (gerb_item->m_Size.x + gerb_item->m_Size.y) / 2;
}
else // a true TRACK
{
newtrack = track->Copy();
newtrack = new TRACK( pcb );
newtrack->SetLayer( pcb_layer_number );
newtrack->m_Start = gerb_item->m_Start;
newtrack->m_End = gerb_item->m_End;
newtrack->m_Width = gerb_item->m_Size.x;
}
pcb->Add( newtrack );
......@@ -210,7 +205,7 @@ static int SavePcbFormatAscii( WinEDA_GerberFrame* frame, FILE* aFile,
}
// delete redundant vias
for( track = pcb->m_Track; track; track = track->Next() )
for( TRACK * track = pcb->m_Track; track; track = track->Next() )
{
if( track->m_Shape != VIA_THROUGH )
continue;
......
G04 Test flashing of circular apertures*
G04 Four groups of circular apertures are arranged in a square*
G04 Handcoded by Julian Lamb *
%MOIN*%
%FSLAX23Y23*%
%ADD10C,0.050*%
%ADD11C,0.050X0.025*%
%ADD12C,0.050X0.025X0.030*%
G04 No hole, centered at 0,0 *
G54D10*
X0Y0D03*
G04 Round hole, centered at 0.1,0 *
G54D11*
X00100Y0D03*
G04 Square hole, centered at 0,0.1 *
G54D12*
X0Y00100D03*
G04 Two, with round holes, slightly overlapping, centered at 0.1,0.1 *
G54D11*
X00100Y00090D03*
X00100Y00110D03*
M02*
G04 Test flashing of obround apertures*
G04 Four groups of obround apertures are arranged in a square*
G04 Handcoded by Julian Lamb *
%MOIN*%
%FSLAX23Y23*%
%ADD10O,0.050X0.080*%
%ADD11O,0.080X0.050X0.025*%
%ADD12O,0.050X0.025X0.025X0.0150*%
G04 No hole, centered at 0,0 *
G54D10*
X0Y0D03*
G04 Round hole, centered at 0.1,0 *
G54D11*
X00100Y0D03*
G04 Square hole, centered at 0,0.1 *
G54D12*
X0Y00100D03*
G04 Two, with round holes, slightly overlapping, centered at 0.1,0.1 *
G54D11*
X00100Y00090D03*
X00100Y00110D03*
M02*
G04 Test flashing of polygon apertures*
G04 Four groups of polygon apertures are arranged in a square*
G04 Handcoded by Julian Lamb *
%MOIN*%
%FSLAX23Y23*%
%ADD10P,0.050X3*%
%ADD11P,0.050X6X-45X0.035*%
%ADD12P,0.040X10X25X0.025X0.025X0.0150*%
G04 Triangle, centered at 0,0 *
G54D10*
X0Y0D03*
G04 Hexagon with round hole rotate 45 degreed ccwise, centered at 0.1,0 *
G54D11*
X00100Y0D03*
G04 10-sided with square hole rotated 25 degrees, centered at 0,0.1 *
G54D12*
X0Y00100D03*
G04 Two, with round holes, slightly overlapping, centered at 0.1,0.1 *
G54D11*
X00100Y00090D03*
X00100Y00110D03*
M02*
G04 Test flashing of rectangular apertures*
G04 Four groups of rectangular apertures are arranged in a square*
G04 Handcoded by Julian Lamb *
%MOIN*%
%FSLAX23Y23*%
%ADD10R,0.050X0.080*%
%ADD11R,0.080X0.050X0.025*%
%ADD12R,0.050X0.025X0.025X0.0150*%
G04 No hole, centered at 0,0 *
G54D10*
X0Y0D03*
G04 Round hole, centered at 0.1,0 *
G54D11*
X00100Y0D03*
G04 Square hole, centered at 0,0.1 *
G54D12*
X0Y00100D03*
G04 Two, with round holes, slightly overlapping, centered at 0.1,0.1 *
G54D11*
X00100Y00090D03*
X00100Y00110D03*
M02*
......@@ -13,6 +13,7 @@
#include "class_drawpanel.h"
#include "gerbview.h"
#include "class_gerber_draw_item.h"
#include "pcbplot.h"
#include "bitmaps.h"
#include "protos.h"
......@@ -113,6 +114,10 @@ BEGIN_EVENT_TABLE( WinEDA_GerberFrame, WinEDA_BasePcbFrame )
// Option toolbar
EVT_TOOL_RANGE( ID_TB_OPTIONS_START, ID_TB_OPTIONS_END,
WinEDA_GerberFrame::OnSelectOptionToolbar )
EVT_TOOL( ID_TB_OPTIONS_SHOW_FLASHED_ITEMS_SKETCH,
WinEDA_GerberFrame::OnSelectOptionToolbar )
EVT_TOOL( ID_TB_OPTIONS_SHOW_LINES_SKETCH,
WinEDA_GerberFrame::OnSelectOptionToolbar )
EVT_TOOL( ID_TB_OPTIONS_SHOW_LAYERS_MANAGER_VERTICAL_TOOLBAR,
WinEDA_GerberFrame::OnSelectOptionToolbar )
EVT_TOOL( ID_TB_OPTIONS_SHOW_DCODES,
......@@ -236,117 +241,22 @@ void WinEDA_GerberFrame::OnCloseWindow( wxCloseEvent& Event )
}
/** Function SetToolbars()
* Set the tools state for the toolbars, according to display options
*/
void WinEDA_GerberFrame::SetToolbars()
int WinEDA_GerberFrame::BestZoom()
{
PCB_SCREEN* screen = (PCB_SCREEN*) GetScreen();
int layer = screen->m_Active_Layer;
GERBER* gerber = g_GERBER_List[layer];
if( m_HToolBar == NULL )
return;
if( GetScreen()->m_BlockLocate.m_Command == BLOCK_MOVE )
{
m_HToolBar->EnableTool( wxID_CUT, true );
m_HToolBar->EnableTool( wxID_COPY, true );
}
else
{
m_HToolBar->EnableTool( wxID_CUT, false );
m_HToolBar->EnableTool( wxID_COPY, false );
}
if( m_SelLayerBox && (m_SelLayerBox->GetSelection() != screen->m_Active_Layer) )
{
m_SelLayerBox->SetSelection( screen->m_Active_Layer );
}
if( m_SelLayerTool )
{
if( gerber )
{
int sel_index;
m_SelLayerTool->Enable( true );
if( gerber->m_Selected_Tool < FIRST_DCODE ) // No tool selected
sel_index = 0;
else
sel_index = gerber->m_Selected_Tool - FIRST_DCODE + 1;
if( sel_index != m_SelLayerTool->GetSelection() )
{
m_SelLayerTool->SetSelection( sel_index );
}
}
else
{
m_SelLayerTool->SetSelection( 0 );
m_SelLayerTool->Enable( false );
}
}
double x, y;
EDA_Rect bbox;
if( m_OptionsToolBar )
BOARD_ITEM* item = GetBoard()->m_Drawings;
for( ; item; item = item->Next() )
{
m_OptionsToolBar->ToggleTool(
ID_TB_OPTIONS_SELECT_UNIT_MM,
g_UserUnit ==
MILLIMETRES ? true : false );
m_OptionsToolBar->ToggleTool( ID_TB_OPTIONS_SELECT_UNIT_INCH,
g_UserUnit == INCHES ? true : false );
m_OptionsToolBar->ToggleTool( ID_TB_OPTIONS_SHOW_POLAR_COORD,
DisplayOpt.DisplayPolarCood );
m_OptionsToolBar->ToggleTool( ID_TB_OPTIONS_SHOW_GRID,
IsGridVisible() );
m_OptionsToolBar->ToggleTool( ID_TB_OPTIONS_SELECT_CURSOR,
m_CursorShape );
m_OptionsToolBar->ToggleTool( ID_TB_OPTIONS_SHOW_PADS_SKETCH,
!m_DisplayPadFill );
m_OptionsToolBar->ToggleTool( ID_TB_OPTIONS_SHOW_TRACKS_SKETCH,
!m_DisplayPcbTrackFill );
m_OptionsToolBar->ToggleTool( ID_TB_OPTIONS_SHOW_POLYGONS_SKETCH,
g_DisplayPolygonsModeSketch == 0 ? 0 : 1 );
m_OptionsToolBar->ToggleTool( ID_TB_OPTIONS_SHOW_DCODES,
IsElementVisible( DCODES_VISIBLE ) );
m_OptionsToolBar->ToggleTool( ID_TB_OPTIONS_SHOW_LAYERS_MANAGER_VERTICAL_TOOLBAR,
m_show_layer_manager_tools );
if( m_show_layer_manager_tools )
GetMenuBar()->SetLabel( ID_MENU_GERBVIEW_SHOW_HIDE_LAYERS_MANAGER_DIALOG,
_("Hide &Layers Manager" ) );
else
GetMenuBar()->SetLabel( ID_MENU_GERBVIEW_SHOW_HIDE_LAYERS_MANAGER_DIALOG,
_("Show &Layers Manager" ) );
GERBER_DRAW_ITEM* gerb_item = (GERBER_DRAW_ITEM*) item;
bbox.Merge( gerb_item->GetBoundingBox() );
}
DisplayUnitsMsg();
if( m_auimgr.GetManagedWindow() )
m_auimgr.Update();
}
int WinEDA_GerberFrame::BestZoom()
{
double x, y;
wxSize size;
GetBoard()->ComputeBoundaryBox();
size = DrawPanel->GetClientSize();
x = ( (double) GetBoard()->m_BoundaryBox.GetWidth() +
GetScreen()->GetGridSize().x ) / (double) size.x;
y = ( (double) GetBoard()->m_BoundaryBox.GetHeight() +
GetScreen()->GetGridSize().y ) / (double) size.y;
GetScreen()->m_Curseur = GetBoard()->m_BoundaryBox.Centre();
wxSize size = DrawPanel->GetClientSize();
x = ( bbox.GetWidth() + GetScreen()->GetGridSize().x ) / (double) size.x;
y = ( bbox.GetHeight() + GetScreen()->GetGridSize().y ) / (double) size.y;
GetScreen()->m_Curseur = bbox.Centre();
return wxRound( MAX( x, y ) * (double) GetScreen()->m_ZoomScalar );
}
......@@ -506,3 +416,65 @@ void WinEDA_GerberFrame::SetLanguage( wxCommandEvent& event )
ReFillLayerWidget();
}
void WinEDA_GerberFrame::Liste_D_Codes( )
{
int ii, jj;
D_CODE* pt_D_code;
wxString Line;
WinEDA_TextFrame* List;
int scale = 10000;
int curr_layer = GetScreen()->m_Active_Layer;
List = new WinEDA_TextFrame( this, _( "List D codes" ) );
for( int layer = 0; layer < 32; layer++ )
{
GERBER* gerber = g_GERBER_List[layer];
if( gerber == NULL )
continue;
if( gerber->ReturnUsedDcodeNumber() == 0 )
continue;
if( layer == curr_layer )
Line.Printf( wxT( "*** Active layer (%2.2d) ***" ), layer + 1 );
else
Line.Printf( wxT( "*** layer %2.2d ***" ), layer + 1 );
List->Append( Line );
for( ii = 0, jj = 1; ii < TOOLS_MAX_COUNT; ii++ )
{
pt_D_code = gerber->GetDCODE( ii + FIRST_DCODE, false );
if( pt_D_code == NULL )
continue;
if( !pt_D_code->m_InUse && !pt_D_code->m_Defined )
continue;
Line.Printf( wxT(
"tool %2.2d: D%2.2d V %2.4f H %2.4f %s" ),
jj,
pt_D_code->m_Num_Dcode,
(float) pt_D_code->m_Size.y / scale,
(float) pt_D_code->m_Size.x / scale,
D_CODE::ShowApertureType( pt_D_code->m_Shape )
);
if( !pt_D_code->m_Defined )
Line += wxT( " ?" );
if( !pt_D_code->m_InUse )
Line += wxT( " *" );
List->Append( Line );
jj++;
}
}
ii = List->ShowModal();
List->Destroy();
if( ii < 0 )
return;
}
......@@ -8,6 +8,7 @@
#include <vector>
#include <set>
#include "dcode.h"
class WinEDA_GerberFrame;
class BOARD;
......@@ -54,22 +55,6 @@ extern Ki_PageDescr* g_GerberPageSizeList[];
extern const wxString GerbviewShowPageSizeOption;
extern const wxString GerbviewShowDCodes;
/**
* Enum APERTURE_T
* is the set of all gerber aperture types allowed, according to page 16 of
* http://gerbv.sourceforge.net/docs/rs274xrevd_e.pdf
*/
enum APERTURE_T
{
APT_CIRCLE = 'C',
APT_LINE = 'L',
APT_RECT = 'R',
APT_OVAL = '0',
APT_POLYGON = 'P',
APT_MACRO = 'M'
};
// Interpolation type
enum Gerb_Interpolation
{
......@@ -106,9 +91,6 @@ enum Gerb_GCommand
};
#define MAX_TOOLS 2048
#define FIRST_DCODE 10
enum Gerb_Analyse_Cmd
{
CMD_IDLE = 0,
......@@ -119,223 +101,13 @@ enum Gerb_Analyse_Cmd
class D_CODE;
/**
* Class DCODE_PARAM
* holds a parameter for a DCODE or an "aperture macro" as defined within
* standard RS274X. The \a value field can be a constant, i.e. "immediate"
* parameter or it may not be used if this param is going to defer to the
* referencing aperture macro. In that case, the \a index field is an index
* into the aperture macro's parameters.
*/
class DCODE_PARAM
{
public:
DCODE_PARAM() :
index(-1),
value(0.0)
{}
double GetValue( const D_CODE* aDcode ) const;
void SetValue( double aValue )
{
value = aValue;
index = -1;
}
/**
* Function IsImmediate
* tests if this DCODE_PARAM holds an immediate parameter or is a pointer
* into a parameter held by an owning D_CODE.
*/
bool IsImmediate() const { return index == -1; }
unsigned GetIndex() const
{
return (unsigned) index;
}
void SetIndex( int aIndex )
{
index = aIndex;
}
private:
int index; ///< if -1, then \a value field is an immediate value,
// else this is an index into parent's
// D_CODE.m_am_params.
double value; ///< if IsImmediate()==true then use the value, else
// not used.
};
/**
* 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
*/
enum AM_PRIMITIVE_ID
{
AMP_CIRCLE = 1,
AMP_LINE2 = 2,
AMP_LINE20 = 20,
AMP_LINE_CENTER = 21,
AMP_LINE_LOWER_LEFT = 22,
AMP_EOF = 3,
AMP_OUTLINE = 4,
AMP_POLYGON = 5,
AMP_MOIRE = 6,
AMP_THERMAL = 7,
};
typedef std::vector<DCODE_PARAM> DCODE_PARAMS;
/**
* Struct AM_PRIMITIVE
* holds an aperture macro primitive as given in Table 3 of
* http://gerbv.sourceforge.net/docs/rs274xrevd_e.pdf
*/
struct AM_PRIMITIVE
{
AM_PRIMITIVE_ID primitive_id; ///< The primitive type
DCODE_PARAMS params; ///< A sequence of parameters used by
// the 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 );
}
};
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
};
/**
* 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;
/**
* Class D_CODE
* holds a gerber DCODE definition.
*/
class D_CODE
{
friend class DCODE_PARAM;
APERTURE_MACRO* m_Macro; ///< no ownership, points to
// GERBER.m_aperture_macros element
/**
* parameters used only when this D_CODE holds a reference to an aperture
* macro, and these parameters would customize the macro.
*/
DCODE_PARAMS m_am_params;
public:
wxSize m_Size; /* Horizontal and vertical dimensions. */
APERTURE_T m_Shape; /* shape ( Line, rectangle, circle , oval .. ) */
int m_Num_Dcode; /* D code ( >= 10 ) */
wxSize m_Drill; /* dimension of the hole (if any) */
int m_DrillShape; /* shape of the hole (round = 1, rect = 2) */
bool m_InUse; /* FALSE if not used */
bool m_Defined; /* FALSE if not defined */
wxString m_SpecialDescr;
public:
D_CODE( int num_dcode );
~D_CODE();
void Clear_D_CODE_Data();
void AppendParam( double aValue )
{
DCODE_PARAM param;
param.SetValue( aValue );
m_am_params.push_back( param );
}
void SetMacro( APERTURE_MACRO* aMacro )
{
m_Macro = aMacro;
}
APERTURE_MACRO* GetMacro() { return m_Macro; }
/**
* Function ShowApertureType
* returns a character string telling what type of aperture type \a aType is.
* @param aType The aperture type to show.
*/
static const wxChar* ShowApertureType( APERTURE_T aType );
};
inline double DCODE_PARAM::GetValue( const D_CODE* aDcode ) const
{
if( IsImmediate() )
return value;
else
{
// the first one was numbered 1, not zero, as in $1, see page 19 of spec.
unsigned ndx = GetIndex() - 1;
wxASSERT(aDcode);
// get the parameter from the aDcode
if( ndx < aDcode->m_am_params.size() )
return aDcode->m_am_params[ndx].GetValue( NULL );
else
{
wxASSERT( GetIndex()-1 < aDcode->m_am_params.size() );
return 0.0;
}
}
}
/**
* Class GERBER
* holds the data for one gerber file or layer
*/
class GERBER
{
D_CODE* m_Aperture_List[MAX_TOOLS]; ///< Dcode (Aperture) List for this layer
D_CODE* m_Aperture_List[TOOLS_MAX_COUNT]; ///< Dcode (Aperture) List for this layer
bool m_Exposure; ///< whether an aperture macro tool is flashed on or off
BOARD* m_Pcb;
......
......@@ -35,7 +35,7 @@ static PARAM_CFG_WXSTRING DrillExtBufCfg
static PARAM_CFG_INT UnitCfg // Units; 0 inches, 1 mm
(
wxT("Unite"),
wxT("Units"),
(int*)&g_UserUnit,
MILLIMETRES
);
......
......@@ -24,6 +24,8 @@ enum gerbview_ids
ID_GERBVIEW_DISPLAY_OPTIONS_SETUP,
ID_TB_OPTIONS_SHOW_LAYERS_MANAGER_VERTICAL_TOOLBAR,
ID_TB_OPTIONS_SHOW_DCODES,
ID_TB_OPTIONS_SHOW_FLASHED_ITEMS_SKETCH,
ID_TB_OPTIONS_SHOW_LINES_SKETCH,
ID_GERBER_END_LIST
};
......
......@@ -39,7 +39,7 @@ static Ki_HotkeyInfo HkHelp( wxT( "Help: this message" ), HK_HELP, '?' );
static Ki_HotkeyInfo HkSwitchUnits( wxT( "Switch Units" ), HK_SWITCH_UNITS, 'U' );
static Ki_HotkeyInfo HkTrackDisplayMode( wxT(
"Track Display Mode" ),
HK_SWITCH_TRACK_DISPLAY_MODE, 'F' );
HK_SWITCH_GBR_ITEMS_DISPLAY_MODE, 'F' );
static Ki_HotkeyInfo HkSwitch2NextCopperLayer( wxT(
"Switch to Next Layer" ),
......@@ -134,7 +134,7 @@ void WinEDA_GerberFrame::OnHotKey( wxDC* DC, int hotkey,
g_UserUnit = (g_UserUnit == INCHES ) ? MILLIMETRES : INCHES;
break;
case HK_SWITCH_TRACK_DISPLAY_MODE:
case HK_SWITCH_GBR_ITEMS_DISPLAY_MODE:
DisplayOpt.DisplayPcbTrackFill ^= 1; DisplayOpt.DisplayPcbTrackFill &= 1;
DrawPanel->Refresh();
break;
......
......@@ -11,7 +11,7 @@
// for shared hotkeys id
enum hotkey_id_commnand {
HK_SWITCH_UNITS = HK_COMMON_END,
HK_SWITCH_TRACK_DISPLAY_MODE,
HK_SWITCH_GBR_ITEMS_DISPLAY_MODE,
HK_SWITCH_LAYER_TO_NEXT,
HK_SWITCH_LAYER_TO_PREVIOUS
};
......
......@@ -9,7 +9,8 @@
#include "confirm.h"
#include "gerbview.h"
#include "protos.h"
#include "class_gerber_draw_item.h"
//#include "protos.h"
bool WinEDA_GerberFrame::Clear_Pcb( bool query )
......@@ -24,13 +25,8 @@ bool WinEDA_GerberFrame::Clear_Pcb( bool query )
if( !IsOK( this, _( "Current data will be lost?" ) ) )
return FALSE;
}
GetBoard()->m_Drawings.DeleteAll();
GetBoard()->m_Track.DeleteAll();
GetBoard()->m_Zone.DeleteAll();
for( layer = 0; layer < 32; layer++ )
{
if( g_GERBER_List[layer] )
......@@ -60,26 +56,15 @@ void WinEDA_GerberFrame::Erase_Current_Layer( bool query )
if( query && !IsOK( this, msg ) )
return;
/* Delete tracks (spots and lines) */
TRACK* PtNext;
for( TRACK* pt_segm = GetBoard()->m_Track;
pt_segm != NULL;
pt_segm = (TRACK*) PtNext )
{
PtNext = pt_segm->Next();
if( pt_segm->GetLayer() != layer )
continue;
pt_segm->DeleteStructure();
}
/* Delete polygons */
SEGZONE* Nextzone;
for( SEGZONE* zone = GetBoard()->m_Zone; zone != NULL; zone = Nextzone )
BOARD_ITEM* item = GetBoard()->m_Drawings;
BOARD_ITEM * next;
for( ; item; item = next )
{
Nextzone = zone->Next();
if( zone->GetLayer() != layer )
next = item->Next();
GERBER_DRAW_ITEM* gerb_item = (GERBER_DRAW_ITEM*) item;
if( gerb_item->m_Layer != layer )
continue;
zone->DeleteStructure();
gerb_item->DeleteStructure();
}
ScreenPcb->SetModify();
......
/****************/
/* lay2plot.cpp */
/****************/
#include "fctsys.h"
#include "common.h"
#include "class_drawpanel.h"
#include "gerbview.h"
#include "protos.h"
/* Routine to plot the pcb, by selected layers. */
void Print_PcbItems(BOARD * Pcb, wxDC *DC, int drawmode, int printmasklayer)
{
DISPLAY_OPTIONS save_opt;
TRACK * pt_piste;
save_opt = DisplayOpt;
DisplayOpt.DisplayPadFill = FILLED;
DisplayOpt.DisplayViaFill = FILLED;
DisplayOpt.DisplayPadNum = 0;
DisplayOpt.DisplayPadIsol = 0;
DisplayOpt.DisplayPcbTrackFill = FILLED;
DisplayOpt.ShowTrackClearanceMode = DO_NOT_SHOW_CLEARANCE;
DisplayOpt.DisplayDrawItems = FILLED;
DisplayOpt.DisplayZonesMode = 0;
pt_piste = Pcb->m_Track;
for( ; pt_piste != NULL ; pt_piste = pt_piste->Next() )
{
// if( (printmasklayer & ReturnMaskLayer(pt_piste) ) == 0 ) continue;
Trace_Segment(Pcb, NULL, DC, pt_piste, drawmode);
}
DisplayOpt = save_opt;
}
......@@ -12,454 +12,12 @@
#include "protos.h"
int ux0, uy0, dx, dy, spot_cX, spot_cY;
static TRACK* Locate_Zone( TRACK* start_adresse, int layer, int typeloc );
static TRACK* Locate_Zone( TRACK* start_adresse, wxPoint ref, int layer );
static TRACK* Locate_Pistes( TRACK* start_adresse,
int Layer,
int typeloc );
static TRACK* Locate_Pistes( TRACK* start_adresse,
wxPoint ref,
int Layer );
static DRAWSEGMENT* Locate_Segment_Pcb( BOARD* Pcb, int typeloc );
static TEXTE_PCB* Locate_Texte_Pcb( TEXTE_PCB* pt_txt_pcb, int typeloc );
static int distance( int seuil );
/* Macro for calculating the coordinates of the cursor position.
*/
#define SET_REF_POS( ref ) if( typeloc == CURSEUR_ON_GRILLE ) \
{ ref = ActiveScreen->m_Curseur; } \
else { ref = ActiveScreen->m_MousePosition; }
/* Display the character of the localized STRUCTURE and return a pointer
* to it.
*/
BOARD_ITEM* WinEDA_GerberFrame::Locate( int typeloc )
{
TEXTE_PCB* pt_texte_pcb;
TRACK* Track, * TrackLocate;
DRAWSEGMENT* DrawSegm;
int layer;
/* Locate tracks and vias, with priority to vias */
layer = GetScreen()->m_Active_Layer;
Track = Locate_Pistes( GetBoard()->m_Track, -1, typeloc );
if( Track != NULL )
{
TrackLocate = Track;
while( ( TrackLocate = Locate_Pistes( TrackLocate,
layer, typeloc ) ) != NULL )
{
Track = TrackLocate;
if( TrackLocate->Type() == TYPE_VIA )
break;
TrackLocate = TrackLocate->Next();
}
Track->DisplayInfo( this );
return Track;
}
pt_texte_pcb = Locate_Texte_Pcb(
(TEXTE_PCB*) GetBoard()->m_Drawings.GetFirst(), typeloc );
if( pt_texte_pcb )
{
pt_texte_pcb->DisplayInfo( this );
return pt_texte_pcb;
}
if( ( DrawSegm = Locate_Segment_Pcb( GetBoard(), typeloc ) ) != NULL )
{
return DrawSegm;
}
if( ( TrackLocate = Locate_Zone( GetBoard()->m_Zone,
GetScreen()->m_Active_Layer,
typeloc ) ) != NULL )
{
TrackLocate->DisplayInfo( this );
return TrackLocate;
}
MsgPanel->EraseMsgBox();
return NULL;
}
/* Locate of segments of pcb edge or draw as active layer.
* Returns:
* Pointer to START segment if found
* NULL if nothing found
*/
DRAWSEGMENT* Locate_Segment_Pcb( BOARD* Pcb, int typeloc )
{
BOARD_ITEM* PtStruct;
DRAWSEGMENT* pts;
wxPoint ref;
PCB_SCREEN* screen = (PCB_SCREEN*) ActiveScreen;
SET_REF_POS( ref );
PtStruct = Pcb->m_Drawings;
for( ; PtStruct != NULL; PtStruct = PtStruct->Next() )
{
if( PtStruct->Type() != TYPE_DRAWSEGMENT )
continue;
pts = (DRAWSEGMENT*) PtStruct;
ux0 = pts->m_Start.x;
uy0 = pts->m_Start.y;
dx = pts->m_End.x - ux0;
dy = pts->m_End.y - uy0;
spot_cX = ref.x - ux0;
spot_cY = ref.y - uy0;
if( pts->GetLayer() != screen->m_Active_Layer )
continue;
if( ( pts->m_Shape == S_CIRCLE ) || ( pts->m_Shape == S_ARC ) )
{
int rayon, dist, StAngle, EndAngle, MouseAngle;
rayon = (int) hypot( (double) (dx), (double) (dy) );
dist = (int) hypot( (double) (spot_cX), (double) (spot_cY) );
if( abs( rayon - dist ) <= ( pts->m_Width / 2 ) )
{
if( pts->m_Shape == S_CIRCLE )
return pts;
MouseAngle = (int) ArcTangente( spot_cY, spot_cX );
StAngle = (int) ArcTangente( dy, dx );
EndAngle = StAngle + pts->m_Angle;
if( EndAngle > 3600 )
{
StAngle -= 3600; EndAngle -= 3600;
}
if( ( MouseAngle >= StAngle ) && ( MouseAngle <= EndAngle ) )
return pts;
}
}
else
{
if( distance( pts->m_Width / 2 ) )
return pts;
}
}
return NULL;
}
/*
* 1 - Locate segment of track at current cursor position.
* 2 - Locate segment of track point by point.
* Ref_pX, ref_pY.r
*
* The search begins to address start_adresse
*/
TRACK* Locate_Pistes( TRACK* start_adresse, int Layer, int typeloc )
{
wxPoint ref;
SET_REF_POS( ref );
return Locate_Pistes( start_adresse, ref, Layer );
}
TRACK* Locate_Pistes( TRACK* start_adresse, wxPoint ref, int Layer )
{
TRACK* Track;
int l_piste; /* half-width of the track */
for( Track = start_adresse; Track != NULL; Track = Track->Next() )
{
if( Track->GetState( BUSY | DELETED ) )
continue;
/* Calculate coordinates of the test segment. */
l_piste = Track->m_Width >> 1;
ux0 = Track->m_Start.x;
uy0 = Track->m_Start.y;
dx = Track->m_End.x;
dy = Track->m_End.y;
dx -= ux0;
dy -= uy0;
spot_cX = ref.x - ux0;
spot_cY = ref.y - uy0;
if( Track->Type() == TYPE_VIA )
{
if( ( abs( spot_cX ) <= l_piste ) && ( abs( spot_cY ) <=l_piste ) )
{
return Track;
}
continue;
}
if( Layer >= 0 )
if( Track->GetLayer() != Layer )
continue;
if( distance( l_piste ) )
return Track;
}
return NULL;
}
/*
* Locate zone area at the cursor position.
*
* The search begins to address start_adresse
*/
TRACK* Locate_Zone( TRACK* start_adresse, int layer, int typeloc )
{
wxPoint ref;
SET_REF_POS( ref );
return Locate_Zone( start_adresse, ref, layer );
}
/*
* Locate zone area at point.
*
* The search begins to address start_adresse
*/
TRACK* Locate_Zone( TRACK* start_adresse, wxPoint ref, int layer )
{
TRACK* Zone;
int l_segm;
for( Zone = start_adresse; Zone != NULL; Zone = Zone->Next() )
{
l_segm = Zone->m_Width >> 1;
ux0 = Zone->m_Start.x;
uy0 = Zone->m_Start.y;
dx = Zone->m_End.x;
dy = Zone->m_End.y;
dx -= ux0;
dy -= uy0;
spot_cX = ref.x - ux0;
spot_cY = ref.y - uy0;
if( ( layer != -1 ) && ( Zone->GetLayer() != layer ) )
continue;
if( distance( l_segm ) )
return Zone;
}
return NULL;
}
/* Location of text on the PCB:
* INPUT: char pointer to the beginning of the search area
* Return: pointer to the text description located.
*/
TEXTE_PCB* Locate_Texte_Pcb( TEXTE_PCB* pt_txt_pcb, int typeloc )
{
int angle;
EDA_BaseStruct* PtStruct;
wxPoint ref;
SET_REF_POS( ref );
PtStruct = (EDA_BaseStruct*) pt_txt_pcb;
for( ; PtStruct != NULL; PtStruct = PtStruct->Next() )
{
if( PtStruct->Type() != TYPE_TEXTE )
continue;
pt_txt_pcb = (TEXTE_PCB*) PtStruct;
angle = pt_txt_pcb->m_Orient;
ux0 = pt_txt_pcb->m_Pos.x;
uy0 = pt_txt_pcb->m_Pos.y;
dx = ( pt_txt_pcb->m_Size.x * pt_txt_pcb->GetLength() ) / 2;
dy = pt_txt_pcb->m_Size.y / 2;
dx *= 13;
dx /= 9; /* Character for factor 13/9. */
/* Cursor in the rectangle around the center. */
spot_cX = ref.x - ux0;
spot_cY = ref.y - uy0;
RotatePoint( &spot_cX, &spot_cY, -angle );
if( ( abs( spot_cX ) <= abs( dx ) ) && ( abs( spot_cY ) <= abs( dy ) ) )
return pt_txt_pcb;
}
return NULL;
}
/*
* Calculate the distance from the cursor to a line segment:
* (Track, edge, contour module ..
* Returns:
* 0 if distance > threshold
* 1 if distance <= threshold
* Variables used (must be initialized before use, and
* are brought to the mark center on the origin of the segment)
* dx, dy = coord of extremity segment.
* spot_cX, spot_cY = coord of mouse cursor
* Search 4 cases:
* Horizontal segment
* Vertical segment
* Segment 45
* Any segment
*/
int distance( int seuil )
{
int cXrot, cYrot, segX, segY;
int pointX, pointY;
segX = dx;
segY = dy;
pointX = spot_cX;
pointY = spot_cY;
/* Reroute coordinate for the segment in 1st quadrant (coord> = 0). */
if( segX < 0 ) /* Set > 0 if symmetrical about the axis Y. */
{
segX = -segX;
pointX = -pointX;
}
if( segY < 0 ) /* Set > 0 if symmetrical about the axis X. */
{
segY = -segY;
pointY = -pointY;
}
if( segY == 0 ) /* Horizontal track. */
{
if( abs( pointY ) <= seuil )
{
if( ( pointX >= 0 ) && ( pointX <= segX ) )
return 1;
if( ( pointX < 0 ) && ( pointX >= -seuil ) )
{
if( ( ( pointX * pointX ) + ( pointY * pointY ) ) <=
( seuil * seuil ) )
return 1;
}
if( ( pointX > segX ) && ( pointX <= ( segX + seuil ) ) )
{
if( ( ( ( pointX - segX ) * ( pointX - segX ) ) +
( pointY * pointY ) ) <= ( seuil * seuil ) )
return 1;
}
}
}
else if( segX == 0 ) /* Vertical track. */
{
if( abs( pointX ) <= seuil )
{
if( ( pointY >= 0 ) && ( pointY <= segY ) )
return 1;
if( ( pointY < 0 ) && ( pointY >= -seuil ) )
{
if( ( (pointY * pointY ) + ( pointX * pointX ) ) <=
( seuil * seuil ) )
return 1;
}
if( ( pointY > segY ) && ( pointY <= ( segY + seuil ) ) )
{
if( ( ( ( pointY - segY ) * ( pointY - segY ) ) +
( pointX * pointX ) ) <= ( seuil * seuil ) )
return 1;
}
}
}
else if( segX == segY ) /* 45 degree track. */
{
/* You spin axes of 45 degrees. mouse was then
* coord: x1 = x * y * cos45 + sin45
* y1 = y * cos45 - sin45 x *
* And the segment of track is horizontal.
* coord recalculation of the mouse (sin45 = cos45 = .707 = 7 / 10
* Note: sin or cos45 = .707, and when recalculating coord
* dX45 and dy45, lect coeff .707 is neglected, dx and dy are both
* actually .707
* too big. (security hole too small)
* spot_cX *, Y * must be by .707 * .707 = 0.5
*/
cXrot = (pointX + pointY) >> 1;
cYrot = (pointY - pointX) >> 1;
/* Recalculate coordinates of extremity segment, which will be vertical
* following the orientation of axes on the screen: DX45 = pointx
* (or pointy) and 1.414 is actually greater, and dy45 = 0
*
* Threshold should be .707 to reflect the difference in coeff dx, dy
*/
seuil *= 7; seuil /= 10;
if( abs( cYrot ) <= seuil )
{
if( ( cXrot >= 0 ) && ( cXrot <= segX ) )
return 1;
if( ( cXrot < 0 ) && ( cXrot >= -seuil ) )
{
if( ( ( cXrot * cXrot ) + ( cYrot * cYrot ) )
<= ( seuil * seuil ) )
return 1;
}
if( ( cXrot > segX ) && ( cXrot <= ( segX + seuil ) ) )
{
if( ( ( ( cXrot - segX ) * ( cXrot - segX ) ) +
( cYrot * cYrot ) ) <= ( seuil * seuil ) )
return 1;
}
}
}
else /* Any orientation. */
{
/* There is a change of axis (rotation), so that the segment
* track is horizontal in the new reference, */
int angle;
angle = (int) ( atan2( (double) segY, (double) segX ) * 1800 / M_PI);
cXrot = pointX;
cYrot = pointY;
RotatePoint( &cXrot, &cYrot, angle ); /* Rotate test point. */
RotatePoint( &segX, &segY, angle ); /* Rotate segment. */
/* The track is horizontal, following the changes to coordinate
* axis and, therefore segX = length of segment
*/
if( abs( cYrot ) <= seuil )
{
if( ( cXrot >= 0 ) && ( cXrot <= segX ) )
return 1;
if( ( cXrot < 0 ) && ( cXrot >= -seuil ) )
{
if( ( ( cXrot * cXrot ) + ( cYrot * cYrot ) )
<= ( seuil * seuil ) )
return 1;
}
if( ( cXrot > segX ) && ( cXrot <= ( segX + seuil ) ) )
{
if( ( ( ( cXrot - segX ) * ( cXrot - segX ) ) +
( cYrot * cYrot ) ) <= ( seuil * seuil ) )
return 1;
}
}
}
return 0;
}
......@@ -47,17 +47,11 @@ bool WinEDA_GerberFrame::OnRightClick( const wxPoint& MousePos,
{
if( BlockActive )
{
PopMenu->Append( ID_POPUP_CANCEL_CURRENT_COMMAND,
_( "Cancel Block" ) );
PopMenu->Append( ID_POPUP_ZOOM_BLOCK,
_( "Zoom Block (drag middle mouse)" ) );
PopMenu->Append( ID_POPUP_CANCEL_CURRENT_COMMAND, _( "Cancel Block" ) );
PopMenu->AppendSeparator();
PopMenu->Append( ID_POPUP_PLACE_BLOCK, _( "Place Block" ) );
PopMenu->Append( ID_POPUP_COPY_BLOCK,
_( "Copy Block (shift mouse)" ) );
PopMenu->Append( ID_POPUP_DELETE_BLOCK,
_( "Delete Block (ctrl + drag mouse)" ) );
PopMenu->Append( ID_POPUP_MIRROR_X_BLOCK, _( "Mirror Block" ) );
}
else
PopMenu->Append( ID_POPUP_CANCEL_CURRENT_COMMAND,
......@@ -77,19 +71,6 @@ bool WinEDA_GerberFrame::OnRightClick( const wxPoint& MousePos,
GetScreen()->SetCurItem( DrawStruct );
switch( DrawStruct->Type() )
{
case TYPE_TRACK:
break;
default:
msg.Printf( wxT( "WinEDA_GerberFrame::OnRightClick Error: illegal or unknown DrawType %d" ),
DrawStruct->Type() );
DisplayError( this, msg );
break;
}
PopMenu->AppendSeparator();
return true;
}
......@@ -66,7 +66,7 @@ void WinEDA_GerberFrame::OnSelectOptionToolbar( wxCommandEvent& event )
DrawPanel->Refresh( TRUE );
break;
case ID_TB_OPTIONS_SHOW_PADS_SKETCH:
case ID_TB_OPTIONS_SHOW_FLASHED_ITEMS_SKETCH:
if( state )
{
DisplayOpt.DisplayPadFill = m_DisplayPadFill = false;
......@@ -78,19 +78,7 @@ void WinEDA_GerberFrame::OnSelectOptionToolbar( wxCommandEvent& event )
DrawPanel->Refresh( TRUE );
break;
case ID_TB_OPTIONS_SHOW_VIAS_SKETCH:
if( state )
{
DisplayOpt.DisplayViaFill = m_DisplayViaFill = false;
}
else
{
DisplayOpt.DisplayViaFill = m_DisplayViaFill = true;
}
DrawPanel->Refresh( TRUE );
break;
case ID_TB_OPTIONS_SHOW_TRACKS_SKETCH:
case ID_TB_OPTIONS_SHOW_LINES_SKETCH:
if(state )
{
m_DisplayPcbTrackFill = FALSE;
......
/* declarations prototype */
int* InstallDialogLayerPairChoice( WinEDA_GerberFrame* parent );
bool Read_Config();
void Print_PcbItems( BOARD* Pcb, wxDC* DC, int drawmode, int printmasklayer );
void DisplayColorSetupFrame( WinEDA_GerberFrame* parent, const wxPoint& framepos );
void Trace_Segment( BOARD* aBrd, WinEDA_DrawPanel* panel,
wxDC* DC,
TRACK* pt_piste,
int draw_mode );
......@@ -49,7 +49,6 @@
*
* Tools and D_CODES
* Tool number (identification of shapes)
* 1 to 99 (Classical)
* 1 to 999
* D_CODES:
*
......@@ -60,8 +59,7 @@
* D09 = VAPE Flash
* D51 = G54 preceded by -> Select VAPE
*
* D10 ... D255 = Identification Tool (Opening)
* Not in order (see table in PCBPLOT.H)
* D10 ... D999 = Identification Tool (shapes id)
*/
......@@ -83,14 +81,6 @@
* -1 = File not found
* -2 = Error reading file
* Rank D_code max lu (nbr of dCode)
*
* Internal Representation:
*
* Lines are represented as standard TRACKS
* The flash is represented as DRAWSEGMENTS
* - Round or oval: DRAWSEGMENTS
* - Rectangles DRAWSEGMENTS
* Reference to the D-CODE is set in the member Getnet()
*/
......
......@@ -4,6 +4,7 @@
#include "fctsys.h"
#include "polygons_defs.h"
#include "common.h"
#include "confirm.h"
#include "macros.h"
......@@ -11,6 +12,7 @@
#include "pcbplot.h"
#include "trigo.h"
#include "protos.h"
#include "class_gerber_draw_item.h"
#include <math.h>
......@@ -79,18 +81,18 @@ static wxPoint LastPosition;
/* Local Functions (are lower case since they are private to this source file)
**/
**/
/**
* Function fillCircularTRACK
* initializes a given TRACK so that it can draw a circle which is not filled
* Function fillCircularGBRITEM
* initializes a given GBRITEM so that it can draw a circle which is not filled
* and
* has a given pen width (\a aPenWidth ).
*
* @param aTrack The TRACK to fill in.
* @param aGbrItem The GBRITEM to fill in.
* @param Dcode_index The DCODE value, like D14
* @param aLayer The layer index to set into the TRACK
* @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 aPenWidth The width of the pen used to draw the circle's
......@@ -99,171 +101,158 @@ static wxPoint LastPosition;
* color other than the background color, else use the background color
* when drawing so that an erasure happens.
*/
static void fillCircularTRACK( TRACK* aTrack,
int Dcode_index,
int aLayer,
const wxPoint& aPos,
int aDiameter,
int aPenWidth,
bool isDark )
static void fillCircularGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
int Dcode_index,
int aLayer,
const wxPoint& aPos,
int aDiameter,
int aPenWidth,
bool isDark )
{
aTrack->m_Shape = S_CIRCLE;
aTrack->m_Width = aPenWidth;
aGbrItem->m_Shape = GBR_CIRCLE;
aGbrItem->m_Size.x = aGbrItem->m_Size.y = aPenWidth;
aTrack->SetLayer( aLayer );
aTrack->SetNet( Dcode_index );
aGbrItem->SetLayer( aLayer );
aGbrItem->m_DCode = Dcode_index;
// When drawing a TRACK with shape S_CIRCLE, the hypotenuse (i.e. distance)
// When drawing a GBRITEM with shape GBR_CIRCLE, the hypotenuse (i.e. distance)
// between the Start and End points gives the radius of the circle.
aTrack->m_Start = aTrack->m_End = aPos;
aTrack->m_End.x += max( 0, (aDiameter + 1) / 2 );
aGbrItem->m_Start = aGbrItem->m_End = aPos;
aGbrItem->m_End.x += max( 0, (aDiameter + 1) / 2 );
NEGATE( aTrack->m_Start.y );
NEGATE( aTrack->m_End.y );
NEGATE( aGbrItem->m_Start.y );
NEGATE( aGbrItem->m_End.y );
if( !isDark )
{
aTrack->m_Flags |= DRAW_ERASED;
aGbrItem->m_Flags |= DRAW_ERASED;
}
}
/**
* Function fillRoundFlashTRACK
* initializes a given TRACK so that it can draw a circle which is filled and
* Function fillRoundFlashGBRITEM
* initializes a given GBRITEM so that it can draw a circle which is filled and
* has no pen border.
*
* @param aTrack The TRACK to fill in.
* @param aGbrItem The GBRITEM to fill in.
* @param Dcode_index The DCODE value, like D14
* @param aLayer The layer index to set into the TRACK
* @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 isDark True if flash is positive and should use a drawing
* color other than the background color, else use the background color
* when drawing so that an erasure happens.
*/
static void fillRoundFlashTRACK( TRACK* aTrack,
int Dcode_index,
int aLayer,
const wxPoint& aPos,
int aDiameter,
bool isDark )
static void fillRoundFlashGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
int Dcode_index,
int aLayer,
const wxPoint& aPos,
int aDiameter,
bool isDark )
{
aTrack->SetLayer( aLayer );
aTrack->m_Width = aDiameter;
aTrack->m_Start = aTrack->m_End = aPos;
NEGATE( aTrack->m_Start.y );
NEGATE( aTrack->m_End.y );
aTrack->SetNet( Dcode_index );
aTrack->m_Shape = S_SPOT_CIRCLE;
aGbrItem->SetLayer( aLayer );
aGbrItem->m_Size.x = aGbrItem->m_Size.y = aDiameter;
aGbrItem->m_Start = aPos;
NEGATE( aGbrItem->m_Start.y );
aGbrItem->m_End = aGbrItem->m_Start;
aGbrItem->m_DCode = Dcode_index;
aGbrItem->m_Shape = GBR_SPOT_CIRCLE;
aGbrItem->m_Flashed = true;
if( !isDark )
{
aTrack->m_Flags |= DRAW_ERASED;
aGbrItem->m_Flags |= DRAW_ERASED;
}
}
/**
* Function fillOvalOrRectFlashTRACK
* initializes a given TRACK so that it can draw an oval or rectangular
* Function fillOvalOrRectFlashGBRITEM
* initializes a given GBRITEM so that it can draw an oval or rectangular
* filled rectangle.
*
* @param aTrack The TRACK to fill in.
* @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 TRACK
* @param aLayer The layer index to set into the GBRITEM
* @param aPos The center point of the rectangle
* @param aSize The size of the flash
* @param aShape What type of flash, S_SPOT_OVALE or S_SPOT_RECT
* @param aShape What type of flash, GBR_SPOT_OVALE or GBR_SPOT_RECT
* @param isDark True if flash is positive and should use a drawing
* color other than the background color, else use the background color
* when drawing so that an erasure happens.
*/
static void fillOvalOrRectFlashTRACK( TRACK* aTrack,
int Dcode_index,
int aLayer,
const wxPoint& aPos,
const wxSize& aSize,
int aShape,
bool isDark )
static void fillOvalOrRectFlashGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
int Dcode_index,
int aLayer,
const wxPoint& aPos,
const wxSize& aSize,
int aShape,
bool isDark )
{
int width = MIN( aSize.x, aSize.y );
int len = MAX( aSize.x, aSize.y ) - width;
aGbrItem->SetLayer( aLayer );
aGbrItem->m_Flashed = true;
aTrack->SetLayer( aLayer );
aGbrItem->m_Size = aSize;
aTrack->m_Width = width;
aGbrItem->m_Start = aPos;
NEGATE( aGbrItem->m_Start.y );
aGbrItem->m_End = aGbrItem->m_Start;
aTrack->m_Start = aTrack->m_End = aPos;
NEGATE( aTrack->m_Start.y );
NEGATE( aTrack->m_End.y );
aTrack->SetNet( Dcode_index );
aTrack->m_Shape = aShape;
len >>= 1;
if( aSize.x > aSize.y ) // oval or rectangle is horizontal
{
aTrack->m_Start.x -= len;
aTrack->m_End.x += len;
}
else // oval or rectangle is vertical
{
aTrack->m_Start.y -= len;
aTrack->m_End.y += len;
}
aGbrItem->m_DCode = Dcode_index;
aGbrItem->m_Shape = aShape;
if( !isDark )
{
aTrack->m_Flags |= DRAW_ERASED;
aGbrItem->m_Flags |= DRAW_ERASED;
}
}
/**
* Function fillLineTRACK
* initializes a given TRACK so that it can draw a linear D code.
* Function fillLineGBRITEM
* initializes a given GBRITEM so that it can draw a linear D code.
*
* @param aTrack The TRACK to fill in.
* @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 TRACK
* @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 isDark True if flash is positive and should use a drawing
* color other than the background color, else use the background color
* when drawing so that an erasure happens.
*/
static void fillLineTRACK( TRACK* aTrack,
int Dcode_index,
int aLayer,
const wxPoint& aStart,
const wxPoint& aEnd,
int aWidth,
bool isDark )
static void fillLineGBRITEM( GERBER_DRAW_ITEM* aGbrItem,
int Dcode_index,
int aLayer,
const wxPoint& aStart,
const wxPoint& aEnd,
int aWidth,
bool isDark )
{
aTrack->SetLayer( aLayer );
aGbrItem->SetLayer( aLayer );
aGbrItem->m_Flashed = false;
aTrack->m_Width = aWidth;
aGbrItem->m_Size.x = aGbrItem->m_Size.y = aWidth;
aTrack->m_Start = aStart;
NEGATE( aTrack->m_Start.y );
aGbrItem->m_Start = aStart;
NEGATE( aGbrItem->m_Start.y );
aTrack->m_End = aEnd;
NEGATE( aTrack->m_End.y );
aGbrItem->m_End = aEnd;
NEGATE( aGbrItem->m_End.y );
aTrack->SetNet( Dcode_index );
aGbrItem->m_DCode = Dcode_index;
if( !isDark )
{
aTrack->m_Flags |= DRAW_ERASED;
aGbrItem->m_Flags |= DRAW_ERASED;
}
}
/**
* Function fillArcTRACK
* initializes a given TRACK so that it can draw an arc G code.
* Function fillArcGBRITEM
* initializes a given GBRITEM so that it can draw an arc G code.
* <p>
* if multiquadrant == true : arc can be 0 to 360 degrees
* and \a rel_center is the center coordinate relative to start point.
......@@ -276,9 +265,9 @@ static void fillLineTRACK( TRACK* aTrack,
* <li> absolute angle 180 to 270 (quadrant 3) or
* <li> absolute angle 270 to 0 (quadrant 4)
* </ul><p>
* @param aTrack is the TRACK to fill in.
* @param GERBER_DRAW_ITEM is the GBRITEM to fill in.
* @param Dcode_index is the DCODE value, like D14
* @param aLayer is the layer index to set into the TRACK
* @param aLayer is the layer index to set into the GBRITEM
* @param aStart is the starting point
* @param aEnd is the ending point
* @param rel_center is the center coordinate relative to start point,
......@@ -291,16 +280,17 @@ static void fillLineTRACK( TRACK* aTrack,
* color other than the background color, else use the background color
* when drawing so that an erasure happens.
*/
static void fillArcTRACK( TRACK* aTrack, int Dcode_index, int aLayer,
const wxPoint& aStart, const wxPoint& aEnd,
const wxPoint& rel_center, int aWidth,
bool clockwise, bool multiquadrant, bool isDark )
static void fillArcGBRITEM( GERBER_DRAW_ITEM* aGbrItem, int Dcode_index, int aLayer,
const wxPoint& aStart, const wxPoint& aEnd,
const wxPoint& rel_center, int aWidth,
bool clockwise, bool multiquadrant, bool isDark )
{
wxPoint center, delta;
aTrack->m_Shape = S_ARC;
aTrack->SetLayer( aLayer );
aTrack->m_Width = aWidth;
aGbrItem->m_Shape = GBR_ARC;
aGbrItem->SetLayer( aLayer );
aGbrItem->m_Size.x = aGbrItem->m_Size.y = aWidth;
aGbrItem->m_Flashed = false;
if( multiquadrant )
{
......@@ -309,20 +299,19 @@ static void fillArcTRACK( TRACK* aTrack, int Dcode_index, int aLayer,
if( clockwise )
{
aTrack->m_Start = aStart;
aTrack->m_End = aEnd;
aGbrItem->m_Start = aStart;
aGbrItem->m_End = aEnd;
}
else
{
aTrack->m_Start = aEnd;
aTrack->m_End = aStart;
aGbrItem->m_Start = aEnd;
aGbrItem->m_End = aStart;
}
}
else
{
center = rel_center;
delta.x = aEnd.x - aStart.x;
delta.y = aEnd.y - aStart.y;
center = rel_center;
delta = aEnd - aStart;
if( (delta.x >= 0) && (delta.y >= 0) )
{
......@@ -350,28 +339,26 @@ static void fillArcTRACK( TRACK* aTrack, int Dcode_index, int aLayer,
if( clockwise )
{
aTrack->m_Start = aStart;
aTrack->m_End = aEnd;
aGbrItem->m_Start = aStart;
aGbrItem->m_End = aEnd;
}
else
{
aTrack->m_Start = aEnd;
aTrack->m_End = aStart;
aGbrItem->m_Start = aEnd;
aGbrItem->m_End = aStart;
}
}
aTrack->SetNet( Dcode_index );
aTrack->m_Param = center.x;
aTrack->SetSubNet( center.y );
aGbrItem->m_DCode = Dcode_index;
aGbrItem->m_ArcCentre = center;
NEGATE( aTrack->m_Start.y );
NEGATE( aTrack->m_End.y );
aTrack->SetSubNet( -aTrack->GetSubNet() );
NEGATE( aGbrItem->m_Start.y );
NEGATE( aGbrItem->m_End.y );
NEGATE( aGbrItem->m_ArcCentre.y );
if( !isDark )
{
aTrack->m_Flags |= DRAW_ERASED;
aGbrItem->m_Flags |= DRAW_ERASED;
}
}
......@@ -392,7 +379,7 @@ static void fillArcTRACK( TRACK* aTrack, int Dcode_index, int aLayer,
* <li> absolute angle 270 to 0 (quadrant 4)
* </ul><p>
* @param aPcb is the board.
* @param aLayer is the layer index to set into the TRACK
* @param aLayer is the layer index to set into the GBRITEM
* @param aStart is the starting point
* @param aEnd is the ending point
* @param rel_center is the center coordinate relative to start point,
......@@ -404,44 +391,38 @@ static void fillArcTRACK( TRACK* aTrack, int Dcode_index, int aLayer,
* @param isDark True if flash is positive and should use a drawing
* color other than the background color, else use the background color
* when drawing so that an erasure happens.
* @return a pointer to the first segment created
*/
static SEGZONE * fillArcPOLY( BOARD * aPcb, int aLayer,
const wxPoint& aStart, const wxPoint& aEnd,
const wxPoint& rel_center,
bool clockwise, bool multiquadrant, bool isDark )
static void fillArcPOLY( BOARD* aPcb, GERBER_DRAW_ITEM* aGrbrItem,
const wxPoint& aStart, const wxPoint& aEnd,
const wxPoint& rel_center,
bool clockwise, bool multiquadrant, bool isDark )
{
/* in order to calculate arc parameters, we use fillArcTRACK
* so we muse create a dummy track and use its geometric parmeters
/* in order to calculate arc parameters, we use fillArcGBRITEM
* so we muse create a dummy track and use its geometric parameters
*/
static TRACK dummyTrack(NULL);
SEGZONE * firstSegment = NULL;
static GERBER_DRAW_ITEM dummyGbrItem( NULL );
fillArcTRACK( &dummyTrack, 0, aLayer,
aStart, aEnd,
rel_center, 0,
clockwise, multiquadrant, isDark );
fillArcGBRITEM( &dummyGbrItem, 0, 0,
aStart, aEnd, rel_center, 0,
clockwise, multiquadrant, isDark );
// dummyTrack has right geometric parameters, and has its Y coordinates negated (to match the pcbnew Y axis).
// Approximate arc by 36 segments per 360 degree
const int increment_angle = 360/36;
const int increment_angle = 360 / 36;
wxPoint center;
center.x = dummyTrack.m_Param;
center.y = dummyTrack.GetSubNet();
wxPoint center;
center = dummyGbrItem.m_ArcCentre;
// Calculate relative coordinates;
wxPoint start = dummyTrack.m_Start - center;
wxPoint end = dummyTrack.m_End - center;
wxPoint start = dummyGbrItem.m_Start - center;
wxPoint end = dummyGbrItem.m_End - center;
/* Calculate angle arc
* angle is here clockwise because Y axis is reversed
*/
double start_angle =
atan2( (double)start.y, (double)start.x );
double start_angle = atan2( (double) start.y, (double) start.x );
start_angle = 180 * start_angle / M_PI;
double end_angle =
atan2( (double)end.y , (double)end.x );
double end_angle = atan2( (double) end.y, (double) end.x );
end_angle = 180 * end_angle / M_PI;
double angle = start_angle - end_angle;
......@@ -449,19 +430,21 @@ static SEGZONE * fillArcPOLY( BOARD * aPcb, int aLayer,
// start.x, start.y, start_angle, end.x, end.y, end_angle, angle ) );
if( !clockwise )
{
EXCHG(start, end);
D( printf( " >>>> reverse arc\n") );
EXCHG( start, end );
D( printf( " >>>> reverse arc\n" ) );
}
// Normalize angle
while ( angle > 360.0 )
while( angle > 360.0 )
angle -= 360.0;
while ( angle < 0.0 )
while( angle < 0.0 )
angle += 360.0;
int count = (int) (angle / increment_angle );
int count = (int) ( angle / increment_angle );
if( count <= 0 )
count = 1;
// D( printf( " >>>> angle %f, cnt %d sens %d\n", angle, count, clockwise ) );
// calculate segments
......@@ -469,47 +452,33 @@ static SEGZONE * fillArcPOLY( BOARD * aPcb, int aLayer,
for( int ii = 1; ii <= count; ii++ )
{
wxPoint end_arc = start;
int rot = 10 * ii * increment_angle; // rot is in 0.1 deg
int rot = 10 * ii * increment_angle; // rot is in 0.1 deg
if( ii < count )
{
if( clockwise )
RotatePoint(&end_arc, rot);
RotatePoint( &end_arc, rot );
else
RotatePoint(&end_arc, -rot);
RotatePoint( &end_arc, -rot );
}
else
end_arc = end;
SEGZONE * edge_poly = new SEGZONE( aPcb );
if( firstSegment == NULL )
firstSegment = edge_poly;
aPcb->m_Zone.Append( edge_poly );
// D( printf( " >> Add arc %d rot %d, edge poly item %d,%d to %d,%d\n",
// ii, rot, start_arc.x, start_arc.y,end_arc.x, end_arc.y ); )
edge_poly->SetLayer( aLayer );
edge_poly->m_Width = 1;
if( aGrbrItem->m_PolyCorners.size() == 0 )
aGrbrItem->m_PolyCorners.push_back( start_arc + center );
aGrbrItem->m_PolyCorners.push_back( end_arc + center );
edge_poly->m_Start = start_arc + center;
edge_poly->m_End = end_arc + center;
// the first track of each polygon has a netcode of zero,
// otherwise one.
// set netcode to 1. the calling function is responsible
// to set the first point to 0
edge_poly->SetNet( 1 );
if( !isDark )
{
edge_poly->m_Flags |= DRAW_ERASED;
aGrbrItem->m_Flags |= DRAW_ERASED;
}
start_arc = end_arc;
}
return firstSegment;
}
/* These routines read the text string point from Text.
* After use, advanced Text the beginning of the sequence unread
*/
......@@ -574,48 +543,14 @@ wxPoint GERBER::ReadXYCoord( char*& Text )
}
current_coord = atoi( line );
double real_scale = 1.0;
switch( fmt_scale )
{
case 0:
real_scale = 10000.0;
break;
case 1:
real_scale = 1000.0;
break;
case 2:
real_scale = 100.0;
break;
case 3:
real_scale = 10.0;
break;
case 4:
break;
case 5:
real_scale = 0.1;
break;
case 6:
real_scale = 0.01;
break;
case 7:
real_scale = 0.001;
break;
case 8:
real_scale = 0.0001;
break;
case 9:
real_scale = 0.00001;
break;
}
if( fmt_scale < 0 || fmt_scale > 9 )
fmt_scale = 4;
double scale_list[10] =
{ 10000.0, 1000.0, 100.0, 10.0,
1,
0.1, 0.01, 0.001, 0.0001, 0.00001
};
real_scale = scale_list[fmt_scale];
if( m_GerbMetric )
real_scale = real_scale / 25.4;
......@@ -855,8 +790,8 @@ bool GERBER::Execute_G_Command( char*& text, int G_commande )
int D_commande = ReturnDCodeNumber( text );
if( D_commande < FIRST_DCODE )
return false;
if( D_commande > (MAX_TOOLS - 1) )
D_commande = MAX_TOOLS - 1;
if( D_commande > (TOOLS_MAX_COUNT - 1) )
D_commande = TOOLS_MAX_COUNT - 1;
m_Current_Tool = D_commande;
D_CODE* pt_Dcode = GetDCODE( D_commande, false );
if( pt_Dcode )
......@@ -940,7 +875,7 @@ static int scale( double aCoord, bool isMetric )
static wxPoint mapPt( double x, double y, bool isMetric )
{
wxPoint ret( scale( x, isMetric ),
scale( y, isMetric ) );
scale( y, isMetric ) );
return ret;
}
......@@ -985,24 +920,24 @@ static bool mapExposure( int param1, bool curExposure, bool isNegative )
bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame,
char*& text, int D_commande )
{
wxSize size( 15, 15 );
wxSize size( 15, 15 );
APERTURE_T aperture = APT_CIRCLE;
TRACK* track;
BOARD* pcb = frame->GetBoard();
APERTURE_T aperture = APT_CIRCLE;
GERBER_DRAW_ITEM* gbritem;
BOARD* pcb = frame->GetBoard();
int activeLayer = frame->GetScreen()->m_Active_Layer;
int activeLayer = frame->GetScreen()->m_Active_Layer;
int dcode = 0;
D_CODE* tool = NULL;
wxString msg;
int dcode = 0;
D_CODE* tool = NULL;
wxString msg;
D( printf( "%22s: D_CODE<%d>\n", __func__, D_commande ); )
if( D_commande >= FIRST_DCODE ) // This is a "Set tool" command
{
if( D_commande > (MAX_TOOLS - 1) )
D_commande = MAX_TOOLS - 1;
if( D_commande > (TOOLS_MAX_COUNT - 1) )
D_commande = TOOLS_MAX_COUNT - 1;
// remember which tool is selected, nothing is done with it in this
// call
......@@ -1021,44 +956,48 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame,
if( m_PolygonFillMode ) // Enter a polygon description:
{
SEGZONE* edge_poly;
switch( D_commande )
{
case 1: // code D01 Draw line, exposure ON
m_Exposure = true;
if( !m_Exposure )
{
m_Exposure = true;
gbritem = new GERBER_DRAW_ITEM( pcb );
pcb->m_Drawings.Append( gbritem );
gbritem->m_Shape = GBR_POLYGON;
gbritem->SetLayer( activeLayer );
gbritem->m_Flashed = false;
}
switch( m_Iterpolation )
{
case GERB_INTERPOL_ARC_NEG:
case GERB_INTERPOL_ARC_POS:
gbritem = (GERBER_DRAW_ITEM*)( pcb->m_Drawings.GetLast() );
D( printf( "Add arc poly %d,%d to %d,%d fill %d interpol %d 360_enb %d\n",
m_PreviousPos.x, m_PreviousPos.y, m_CurrentPos.x,
m_CurrentPos.y, m_PolygonFillModeState, m_Iterpolation, m_360Arc_enbl ); )
edge_poly = fillArcPOLY( pcb, activeLayer, m_PreviousPos,
m_CurrentPos, m_IJPos,
( m_Iterpolation == GERB_INTERPOL_ARC_NEG ) ?
false : true, m_360Arc_enbl,
!(m_LayerNegative ^ m_ImageNegative) );
edge_poly->SetNet( m_PolygonFillModeState );
m_PreviousPos.x, m_PreviousPos.y, m_CurrentPos.x,
m_CurrentPos.y, m_PolygonFillModeState, m_Iterpolation, m_360Arc_enbl ); )
fillArcPOLY( pcb, gbritem, m_PreviousPos,
m_CurrentPos, m_IJPos,
( m_Iterpolation == GERB_INTERPOL_ARC_NEG ) ?
false : true, m_360Arc_enbl,
!(m_LayerNegative ^ m_ImageNegative) );
break;
default:
edge_poly = new SEGZONE( pcb );
pcb->m_Zone.Append( edge_poly );
gbritem = (GERBER_DRAW_ITEM*)( pcb->m_Drawings.GetLast() );
D( printf( "Add poly edge %d,%d to %d,%d fill %d\n",
m_PreviousPos.x, m_PreviousPos.y,
m_CurrentPos.x, m_CurrentPos.y, m_Iterpolation ); )
m_PreviousPos.x, m_PreviousPos.y,
m_CurrentPos.x, m_CurrentPos.y, m_Iterpolation ); )
edge_poly->SetLayer( activeLayer );
edge_poly->m_Width = 1;
gbritem->m_Start = m_PreviousPos; // m_Start is used as temporary storage
NEGATE( gbritem->m_Start.y );
if( gbritem->m_PolyCorners.size() == 0 )
gbritem->m_PolyCorners.push_back( gbritem->m_Start );
edge_poly->m_Start = m_PreviousPos;
NEGATE( edge_poly->m_Start.y );
edge_poly->m_End = m_CurrentPos;
NEGATE( edge_poly->m_End.y );
edge_poly->SetNet( m_PolygonFillModeState );
gbritem->m_End = m_CurrentPos; // m_End is used as temporary storage
NEGATE( gbritem->m_End.y );
gbritem->m_PolyCorners.push_back( gbritem->m_End );
// the first track of each polygon has a netcode of zero,
// otherwise one. Set the erasure flag in that special track,
......@@ -1066,7 +1005,7 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame,
if( !m_PolygonFillModeState )
{
if( m_LayerNegative ^ m_ImageNegative )
edge_poly->m_Flags |= DRAW_ERASED;
gbritem->m_Flags |= DRAW_ERASED;
D( printf( "\nm_Flags=0x%08X\n", edge_poly->m_Flags ); )
}
break;
......@@ -1104,12 +1043,12 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame,
switch( m_Iterpolation )
{
case GERB_INTERPOL_LINEAR_1X:
track = new TRACK( pcb );
pcb->m_Track.Append( track );
D( printf( "R:%p\n", track ); )
fillLineTRACK( track, dcode, activeLayer, m_PreviousPos,
m_CurrentPos, size.x,
!(m_LayerNegative ^ m_ImageNegative) );
gbritem = new GERBER_DRAW_ITEM( pcb );
pcb->m_Drawings.Append( gbritem );
D( printf( "R:%p\n", gbritem ); )
fillLineGBRITEM( gbritem, dcode, activeLayer, m_PreviousPos,
m_CurrentPos, size.x,
!(m_LayerNegative ^ m_ImageNegative) );
break;
case GERB_INTERPOL_LINEAR_01X:
......@@ -1120,14 +1059,14 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame,
case GERB_INTERPOL_ARC_NEG:
case GERB_INTERPOL_ARC_POS:
track = new TRACK( pcb );
pcb->m_Track.Append( track );
D( printf( "R:%p\n", track ); )
fillArcTRACK( track, dcode, activeLayer, m_PreviousPos,
m_CurrentPos, m_IJPos, size.x,
( m_Iterpolation == GERB_INTERPOL_ARC_NEG ) ?
false : true, m_360Arc_enbl,
!(m_LayerNegative ^ m_ImageNegative) );
gbritem = new GERBER_DRAW_ITEM( pcb );
pcb->m_Drawings.Append( gbritem );
D( printf( "R:%p\n", gbritem ); )
fillArcGBRITEM( gbritem, dcode, activeLayer, m_PreviousPos,
m_CurrentPos, m_IJPos, size.x,
( m_Iterpolation == GERB_INTERPOL_ARC_NEG ) ?
false : true, m_360Arc_enbl,
!(m_LayerNegative ^ m_ImageNegative) );
break;
default:
......@@ -1156,270 +1095,267 @@ bool GERBER::Execute_DCODE_Command( WinEDA_GerberFrame* frame,
switch( aperture )
{
case APT_LINE: // APT_LINE is not in the spec, don't know why it's
// here
case APT_CIRCLE:
track = new TRACK( pcb );
pcb->m_Track.Append( track );
D( printf( "R:%p\n", track ); )
fillRoundFlashTRACK( track, dcode, activeLayer,
m_CurrentPos, size.x,
!(m_LayerNegative ^ m_ImageNegative) );
gbritem = new GERBER_DRAW_ITEM( pcb );
pcb->m_Drawings.Append( gbritem );
D( printf( "R:%p\n", gbritem ); )
fillRoundFlashGBRITEM( gbritem, dcode, activeLayer,
m_CurrentPos, size.x,
!(m_LayerNegative ^ m_ImageNegative) );
break;
case APT_OVAL:
case APT_RECT:
track = new TRACK( pcb );
pcb->m_Track.Append( track );
D( printf( "R:%p\n", track ); )
fillOvalOrRectFlashTRACK( track, dcode, activeLayer,
m_CurrentPos, size,
( aperture == APT_RECT ) ?
S_SPOT_RECT : S_SPOT_OVALE,
!(m_LayerNegative ^ m_ImageNegative) );
gbritem = new GERBER_DRAW_ITEM( pcb );
pcb->m_Drawings.Append( gbritem );
D( printf( "R:%p\n", gbritem ); )
fillOvalOrRectFlashGBRITEM( gbritem, dcode, activeLayer,
m_CurrentPos, size,
( aperture == APT_RECT ) ?
GBR_SPOT_RECT : GBR_SPOT_OVAL,
!(m_LayerNegative ^ m_ImageNegative) );
break;
case APT_MACRO:
{
APERTURE_MACRO* macro = tool->GetMacro();
wxASSERT( macro );
// split the macro primitives up into multiple normal GBRITEM
// elements
for( AM_PRIMITIVES::iterator p = macro->primitives.begin();
p!=macro->primitives.end();
++p )
{
APERTURE_MACRO* macro = tool->GetMacro();
wxASSERT( macro );
// split the macro primitives up into multiple normal TRACK
// elements
for( AM_PRIMITIVES::iterator p = macro->primitives.begin();
p!=macro->primitives.end();
++p )
bool exposure;
wxPoint curPos = m_CurrentPos;
switch( p->primitive_id )
{
case AMP_CIRCLE:
{
bool exposure;
wxPoint curPos = m_CurrentPos;
exposure = mapExposure( p->GetExposure(), m_Exposure,
m_ImageNegative );
curPos += mapPt( p->params[2].GetValue( tool ),
p->params[3].GetValue( tool ),
m_GerbMetric );
int diameter = scale( p->params[1].GetValue( tool ),
m_GerbMetric );
gbritem = new GERBER_DRAW_ITEM( pcb );
pcb->m_Drawings.Append( gbritem );
D( printf( "R:%p\n", gbritem ); )
fillRoundFlashGBRITEM( gbritem, dcode, activeLayer,
curPos, diameter, exposure );
}
break;
switch( p->primitive_id )
case AMP_LINE2:
case AMP_LINE20:
{
exposure = mapExposure(
p->GetExposure(), m_Exposure, m_ImageNegative );
int width = scale( p->params[1].GetValue( tool ),
m_GerbMetric );
wxPoint start = mapPt( p->params[2].GetValue( tool ),
p->params[3].GetValue( tool ),
m_GerbMetric );
wxPoint end = mapPt( p->params[4].GetValue( tool ),
p->params[5].GetValue( tool ),
m_GerbMetric );
if( start.x == end.x )
{
case AMP_CIRCLE:
{
exposure = mapExposure( p->GetExposure(), m_Exposure,
m_ImageNegative );
curPos += mapPt( p->params[2].GetValue( tool ),
p->params[3].GetValue( tool ),
m_GerbMetric );
int diameter = scale( p->params[1].GetValue( tool ),
m_GerbMetric );
track = new TRACK( pcb );
pcb->m_Track.Append( track );
D( printf( "R:%p\n", track ); )
fillRoundFlashTRACK( track, dcode, activeLayer,
curPos, diameter, exposure );
}
break;
size.x = width;
size.y = ABS( end.y - start.y ) + 1;
}
else
{
size.x = ABS( end.x - start.x ) + 1;
size.y = width;
}
case AMP_LINE2:
case AMP_LINE20:
{
exposure = mapExposure(
p->GetExposure(), m_Exposure, m_ImageNegative );
int width = scale( p->params[1].GetValue( tool ),
m_GerbMetric );
wxPoint start = mapPt( p->params[2].GetValue( tool ),
p->params[3].GetValue( tool ),
m_GerbMetric );
wxPoint end = mapPt( p->params[4].GetValue( tool ),
p->params[5].GetValue( tool ),
m_GerbMetric );
if( start.x == end.x )
{
size.x = width;
size.y = ABS( end.y - start.y ) + 1;
}
else
{
size.x = ABS( end.x - start.x ) + 1;
size.y = width;
}
wxPoint midPoint( ( start.x + end.x ) / 2,
( start.y + end.y ) / 2 );
curPos += midPoint;
track = new TRACK( pcb );
pcb->m_Track.Append( track );
D( printf( "R:%p\n", track ); )
fillOvalOrRectFlashTRACK( track, dcode, activeLayer,
curPos, size, S_SPOT_RECT,
exposure );
}
break;
wxPoint midPoint( ( start.x + end.x ) / 2,
( start.y + end.y ) / 2 );
curPos += midPoint;
gbritem = new GERBER_DRAW_ITEM( pcb );
pcb->m_Drawings.Append( gbritem );
D( printf( "R:%p\n", gbritem ); )
fillOvalOrRectFlashGBRITEM( gbritem, dcode, activeLayer,
curPos, size, GBR_SPOT_RECT,
exposure );
}
break;
case AMP_LINE_CENTER:
{
exposure = mapExposure( p->GetExposure(), m_Exposure,
m_ImageNegative );
wxPoint msize = mapPt( p->params[1].GetValue( tool ),
p->params[2].GetValue( tool ),
m_GerbMetric );
size.x = msize.x;
size.y = msize.y;
curPos += mapPt( p->params[3].GetValue( tool ),
p->params[4].GetValue( tool ),
m_GerbMetric );
track = new TRACK( pcb );
pcb->m_Track.Append( track );
D( printf( "R:%p\n", track ); )
fillOvalOrRectFlashTRACK( track, dcode, activeLayer,
curPos, size, S_SPOT_RECT,
exposure );
}
break;
case AMP_LINE_CENTER:
{
exposure = mapExposure( p->GetExposure(), m_Exposure,
m_ImageNegative );
wxPoint msize = mapPt( p->params[1].GetValue( tool ),
p->params[2].GetValue( tool ),
m_GerbMetric );
size.x = msize.x;
size.y = msize.y;
curPos += mapPt( p->params[3].GetValue( tool ),
p->params[4].GetValue( tool ),
m_GerbMetric );
gbritem = new GERBER_DRAW_ITEM( pcb );
pcb->m_Drawings.Append( gbritem );
D( printf( "R:%p\n", gbritem ); )
fillOvalOrRectFlashGBRITEM( gbritem, dcode, activeLayer,
curPos, size, GBR_SPOT_RECT,
exposure );
}
break;
case AMP_LINE_LOWER_LEFT:
{
exposure = mapExposure(
p->GetExposure(), m_Exposure, m_ImageNegative );
wxPoint msize = mapPt( p->params[1].GetValue( tool ),
p->params[2].GetValue( tool ),
m_GerbMetric );
size.x = msize.x;
size.y = msize.y;
wxPoint lowerLeft = mapPt( p->params[3].GetValue( tool ),
p->params[4].GetValue( tool ),
m_GerbMetric );
curPos += lowerLeft;
// need the middle, so adjust from the lower left
curPos.y += size.y / 2;
curPos.x += size.x / 2;
track = new TRACK( pcb );
pcb->m_Track.Append( track );
D( printf( "R:%p\n", track ); )
fillOvalOrRectFlashTRACK( track, dcode, activeLayer,
curPos, size, S_SPOT_RECT,
exposure );
}
break;
case AMP_LINE_LOWER_LEFT:
{
exposure = mapExposure(
p->GetExposure(), m_Exposure, m_ImageNegative );
wxPoint msize = mapPt( p->params[1].GetValue( tool ),
p->params[2].GetValue( tool ),
m_GerbMetric );
size.x = msize.x;
size.y = msize.y;
wxPoint lowerLeft = mapPt( p->params[3].GetValue( tool ),
p->params[4].GetValue( tool ),
m_GerbMetric );
curPos += lowerLeft;
// need the middle, so adjust from the lower left
curPos.y += size.y / 2;
curPos.x += size.x / 2;
gbritem = new GERBER_DRAW_ITEM( pcb );
pcb->m_Drawings.Append( gbritem );
D( printf( "R:%p\n", gbritem ); )
fillOvalOrRectFlashGBRITEM( gbritem, dcode, activeLayer,
curPos, size, GBR_SPOT_RECT,
exposure );
}
break;
case AMP_THERMAL:
{
int outerDiam = scale( p->params[2].GetValue( tool ),
m_GerbMetric );
int innerDiam = scale( p->params[3].GetValue( tool ),
m_GerbMetric );
curPos += mapPt( p->params[0].GetValue( tool ),
p->params[1].GetValue( tool ),
m_GerbMetric );
track = new TRACK( pcb );
pcb->m_Track.Append( track );
D( printf( "R:%p\n", track ); )
fillRoundFlashTRACK( track, dcode, activeLayer,
curPos, outerDiam,
!( m_LayerNegative ^ m_ImageNegative ) );
track = new TRACK( pcb );
pcb->m_Track.Append( track );
D( printf( "R:%p\n", track ); )
fillRoundFlashTRACK( track, dcode, activeLayer, curPos,
innerDiam,
( m_LayerNegative ^ m_ImageNegative ) );
// @todo: draw the cross hairs, see page 23 of rs274
// spec. this might be done with two lines, thickness
// from params[4], and drawing
// darkness "(m_LayerNegative ^ m_ImageNegative)"
}
break;
case AMP_THERMAL:
{
int outerDiam = scale( p->params[2].GetValue( tool ),
m_GerbMetric );
int innerDiam = scale( p->params[3].GetValue( tool ),
m_GerbMetric );
curPos += mapPt( p->params[0].GetValue( tool ),
p->params[1].GetValue( tool ),
m_GerbMetric );
gbritem = new GERBER_DRAW_ITEM( pcb );
pcb->m_Drawings.Append( gbritem );
D( printf( "R:%p\n", gbritem ); )
fillRoundFlashGBRITEM( gbritem, dcode, activeLayer,
curPos, outerDiam,
!( m_LayerNegative ^ m_ImageNegative ) );
gbritem = new GERBER_DRAW_ITEM( pcb );
pcb->m_Drawings.Append( gbritem );
D( printf( "R:%p\n", gbritem ); )
fillRoundFlashGBRITEM( gbritem, dcode, activeLayer, curPos,
innerDiam,
( m_LayerNegative ^ m_ImageNegative ) );
// @todo: draw the cross hairs, see page 23 of rs274
// spec. this might be done with two lines, thickness
// from params[4], and drawing
// darkness "(m_LayerNegative ^ m_ImageNegative)"
}
break;
case AMP_MOIRE:
{
curPos += mapPt( p->params[0].GetValue( tool ),
p->params[1].GetValue( tool ),
m_GerbMetric );
// e.g.: "6,0,0,0.125,.01,0.01,3,0.003,0.150,0"
int outerDiam = scale( p->params[2].GetValue( tool ),
m_GerbMetric );
int penThickness = scale( p->params[3].GetValue( tool ),
m_GerbMetric );
int gap = scale( p->params[4].GetValue( tool ),
m_GerbMetric );
int numCircles = (int) p->params[5].GetValue( tool );
int crossHairThickness =
scale( p->params[6].GetValue( tool ), m_GerbMetric );
int crossHairLength =
scale( p->params[7].GetValue( tool ), m_GerbMetric );
// ignore rotation, not supported
// adjust outerDiam by this on each nested circle
int diamAdjust = 2 * (gap + penThickness);
for( int i = 0;
i < numCircles;
++i, outerDiam -= diamAdjust )
{
track = new TRACK( pcb );
pcb->m_Track.Append( track );
D( printf( "R:%p\n", track ); )
fillCircularTRACK( track, dcode, activeLayer,
curPos, outerDiam,
penThickness,
!( m_LayerNegative ^ m_ImageNegative ) );
}
track = new TRACK( pcb );
pcb->m_Track.Append( track );
D( printf( "R:%p\n", track ); )
fillOvalOrRectFlashTRACK( track, dcode, activeLayer,
curPos,
wxSize( crossHairThickness,
crossHairLength ),
S_SPOT_RECT,
!( m_LayerNegative ^ m_ImageNegative ) );
track = new TRACK( pcb );
pcb->m_Track.Append( track );
D( printf( "R:%p\n", track ); )
// swap x and y in wxSize() for this one
fillOvalOrRectFlashTRACK( track, dcode, activeLayer,
curPos,
wxSize( crossHairLength,
crossHairThickness ),
S_SPOT_RECT,
!( m_LayerNegative ^ m_ImageNegative ) );
}
break;
case AMP_MOIRE:
{
curPos += mapPt( p->params[0].GetValue( tool ),
p->params[1].GetValue( tool ),
m_GerbMetric );
// e.g.: "6,0,0,0.125,.01,0.01,3,0.003,0.150,0"
int outerDiam = scale( p->params[2].GetValue( tool ),
m_GerbMetric );
int penThickness = scale( p->params[3].GetValue( tool ),
m_GerbMetric );
int gap = scale( p->params[4].GetValue( tool ),
m_GerbMetric );
int numCircles = (int) p->params[5].GetValue( tool );
int crossHairThickness =
scale( p->params[6].GetValue( tool ), m_GerbMetric );
int crossHairLength =
scale( p->params[7].GetValue( tool ), m_GerbMetric );
// ignore rotation, not supported
// adjust outerDiam by this on each nested circle
int diamAdjust = 2 * (gap + penThickness);
for( int i = 0; i < numCircles; ++i, outerDiam -= diamAdjust )
{
gbritem = new GERBER_DRAW_ITEM( pcb );
pcb->m_Drawings.Append( gbritem );
D( printf( "R:%p\n", gbritem ); )
fillCircularGBRITEM( gbritem, dcode, activeLayer,
curPos, outerDiam,
penThickness,
!( m_LayerNegative ^ m_ImageNegative ) );
}
gbritem = new GERBER_DRAW_ITEM( pcb );
pcb->m_Drawings.Append( gbritem );
D( printf( "R:%p\n", gbritem ); )
fillOvalOrRectFlashGBRITEM( gbritem, dcode, activeLayer,
curPos,
wxSize( crossHairThickness,
crossHairLength ),
GBR_SPOT_RECT,
!( m_LayerNegative ^ m_ImageNegative ) );
gbritem = new GERBER_DRAW_ITEM( pcb );
pcb->m_Drawings.Append( gbritem );
D( printf( "R:%p\n", gbritem ); )
// swap x and y in wxSize() for this one
fillOvalOrRectFlashGBRITEM( gbritem, dcode, activeLayer,
curPos,
wxSize( crossHairLength,
crossHairThickness ),
GBR_SPOT_RECT,
!( m_LayerNegative ^ m_ImageNegative ) );
}
break;
case AMP_OUTLINE:
case AMP_OUTLINE:
#if defined(DEBUG)
{
int numPoints = (int) p->params[1].GetValue( tool );
printf( "AMP_OUTLINE:\n" );
printf( " exposure: %g\n", p->params[0].GetValue( tool ) );
printf( " # points: %d\n", numPoints );
// numPoints does not include the starting point, so add 1.
for( int i = 0; i<numPoints + 1; ++i )
{
int numPoints = (int) p->params[1].GetValue( tool );
printf( "AMP_OUTLINE:\n" );
printf( " exposure: %g\n", p->params[0].GetValue( tool ) );
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,
p->params[i*2+2+0].GetValue( tool ),
p->params[i*2+2+1].GetValue( tool )
printf( " [%d]: X=%g Y=%g\n", i,
p->params[i * 2 + 2 + 0].GetValue( tool ),
p->params[i * 2 + 2 + 1].GetValue( tool )
);
}
printf( " rotation: %g\n", p->params[numPoints*2+4].GetValue( tool ) );
}
printf( " rotation: %g\n", p->params[numPoints * 2 + 4].GetValue( tool ) );
}
#endif
break;
break;
case AMP_POLYGON:
case AMP_EOF:
default:
case AMP_POLYGON:
case AMP_EOF:
default:
// not yet supported, waiting for you.
break;
}
// not yet supported, waiting for you.
break;
}
}
break;
}
break;
default:
break;
......
......@@ -448,7 +448,7 @@ bool GERBER::ExecuteRS274XCommand( int command,
while( *text == ' ' )
text++;
if( *text == 'Y' )
if( *text == 'X' )
{
text++;
dcode->m_Drill.y =
......
......@@ -107,10 +107,10 @@ void WinEDA_GerberFrame::ReCreateHToolbar( void )
m_HToolBar->AddSeparator();
choices.Clear();
choices.Alloc(MAX_TOOLS+1);
choices.Alloc(TOOLS_MAX_COUNT+1);
choices.Add( _( "No tool" ) );
for( ii = 0; ii < MAX_TOOLS; ii++ )
for( ii = 0; ii < TOOLS_MAX_COUNT; ii++ )
{
wxString msg;
msg = _( "Tool " ); msg << ii + FIRST_DCODE;
......@@ -187,11 +187,11 @@ void WinEDA_GerberFrame::ReCreateOptToolbar( void )
_( "Change cursor shape" ), wxITEM_CHECK );
m_OptionsToolBar->AddSeparator();
m_OptionsToolBar->AddTool( ID_TB_OPTIONS_SHOW_PADS_SKETCH, wxEmptyString,
m_OptionsToolBar->AddTool( ID_TB_OPTIONS_SHOW_FLASHED_ITEMS_SKETCH, wxEmptyString,
wxBitmap( pad_sketch_xpm ),
_( "Show spots in sketch mode" ), wxITEM_CHECK );
m_OptionsToolBar->AddTool( ID_TB_OPTIONS_SHOW_TRACKS_SKETCH, wxEmptyString,
m_OptionsToolBar->AddTool( ID_TB_OPTIONS_SHOW_LINES_SKETCH, wxEmptyString,
wxBitmap( showtrack_xpm ),
_( "Show lines in sketch mode" ), wxITEM_CHECK );
......@@ -215,3 +215,103 @@ void WinEDA_GerberFrame::ReCreateOptToolbar( void )
m_OptionsToolBar->Realize();
}
/** Function SetToolbars()
* Set the tools state for the toolbars, according to display options
*/
void WinEDA_GerberFrame::SetToolbars()
{
PCB_SCREEN* screen = (PCB_SCREEN*) GetScreen();
int layer = screen->m_Active_Layer;
GERBER* gerber = g_GERBER_List[layer];
if( m_HToolBar == NULL )
return;
if( GetScreen()->m_BlockLocate.m_Command == BLOCK_MOVE )
{
m_HToolBar->EnableTool( wxID_CUT, true );
m_HToolBar->EnableTool( wxID_COPY, true );
}
else
{
m_HToolBar->EnableTool( wxID_CUT, false );
m_HToolBar->EnableTool( wxID_COPY, false );
}
if( m_SelLayerBox && (m_SelLayerBox->GetSelection() != screen->m_Active_Layer) )
{
m_SelLayerBox->SetSelection( screen->m_Active_Layer );
}
if( m_SelLayerTool )
{
if( gerber )
{
int sel_index;
m_SelLayerTool->Enable( true );
if( gerber->m_Selected_Tool < FIRST_DCODE ) // No tool selected
sel_index = 0;
else
sel_index = gerber->m_Selected_Tool - FIRST_DCODE + 1;
if( sel_index != m_SelLayerTool->GetSelection() )
{
m_SelLayerTool->SetSelection( sel_index );
}
}
else
{
m_SelLayerTool->SetSelection( 0 );
m_SelLayerTool->Enable( false );
}
}
if( m_OptionsToolBar )
{
m_OptionsToolBar->ToggleTool(
ID_TB_OPTIONS_SELECT_UNIT_MM,
g_UserUnit ==
MILLIMETRES ? true : false );
m_OptionsToolBar->ToggleTool( ID_TB_OPTIONS_SELECT_UNIT_INCH,
g_UserUnit == INCHES ? true : false );
m_OptionsToolBar->ToggleTool( ID_TB_OPTIONS_SHOW_POLAR_COORD,
DisplayOpt.DisplayPolarCood );
m_OptionsToolBar->ToggleTool( ID_TB_OPTIONS_SHOW_GRID,
IsGridVisible() );
m_OptionsToolBar->ToggleTool( ID_TB_OPTIONS_SELECT_CURSOR,
m_CursorShape );
m_OptionsToolBar->ToggleTool( ID_TB_OPTIONS_SHOW_FLASHED_ITEMS_SKETCH,
!m_DisplayPadFill );
m_OptionsToolBar->ToggleTool( ID_TB_OPTIONS_SHOW_LINES_SKETCH,
!m_DisplayPcbTrackFill );
m_OptionsToolBar->ToggleTool( ID_TB_OPTIONS_SHOW_POLYGONS_SKETCH,
g_DisplayPolygonsModeSketch == 0 ? 0 : 1 );
m_OptionsToolBar->ToggleTool( ID_TB_OPTIONS_SHOW_DCODES,
IsElementVisible( DCODES_VISIBLE ) );
m_OptionsToolBar->ToggleTool( ID_TB_OPTIONS_SHOW_LAYERS_MANAGER_VERTICAL_TOOLBAR,
m_show_layer_manager_tools );
if( m_show_layer_manager_tools )
GetMenuBar()->SetLabel( ID_MENU_GERBVIEW_SHOW_HIDE_LAYERS_MANAGER_DIALOG,
_("Hide &Layers Manager" ) );
else
GetMenuBar()->SetLabel( ID_MENU_GERBVIEW_SHOW_HIDE_LAYERS_MANAGER_DIALOG,
_("Show &Layers Manager" ) );
}
DisplayUnitsMsg();
if( m_auimgr.GetManagedWindow() )
m_auimgr.Update();
}
......@@ -7,6 +7,7 @@
*/
#include "fctsys.h"
#include "polygons_defs.h"
#include "gr_basic.h"
#include "common.h"
#include "class_drawpanel.h"
......@@ -17,12 +18,13 @@
#include "protos.h"
#include "class_board_design_settings.h"
#include "colors_selection.h"
#include "class_gerber_draw_item.h"
/***************/
/* tracepcb.cpp */
/***************/
static void Affiche_DCodes_Pistes( WinEDA_DrawPanel* panel, wxDC* DC,
static void Show_Items_DCode_Value( WinEDA_DrawPanel* panel, wxDC* DC,
BOARD* Pcb, int drawmode );
/** virtual Function PrintPage
......@@ -95,8 +97,7 @@ void WinEDA_GerberFrame::RedrawActiveWindow( wxDC* DC, bool EraseBg )
}
/********************************************************************/
void BOARD::Draw( WinEDA_DrawPanel* aPanel, wxDC* DC,
int aDrawMode, const wxPoint& offset )
void BOARD::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, int aDrawMode, const wxPoint& aOffset )
/********************************************************************/
/* Redraw the BOARD items but not cursors, axis or grid */
// @todo: replace WinEDA_GerberFrame::Trace_Gerber() by this function
......@@ -116,315 +117,71 @@ void WinEDA_GerberFrame::Trace_Gerber( wxDC* aDC, int aDraw_mode, int aPrintMask
if( !GetBoard() )
return;
bool erase = false;
int color;
bool filled;
int layer = GetScreen()->m_Active_Layer;
// Draw filled polygons
std::vector<wxPoint> points;
// minimize reallocations of the vector's internal array by starting with a good sized one.
points.reserve(10000);
TRACK* next_track;
for( TRACK* track = GetBoard()->m_Zone; track; track = next_track )
{
next_track = track->Next();
if( !(track->ReturnMaskLayer() & aPrintMasklayer) )
continue;
if( (points.size() == 0) && (track->GetNet() == 0) ) // first point of a new polygon
{
erase = ( track->m_Flags & DRAW_ERASED );
points.push_back( track->m_Start );
}
points.push_back( track->m_End );
if( (next_track == NULL ) || (next_track->GetNet() == 0) ) // EndPoint of the current polygon
{
color = g_ColorsSettings.GetLayerColor( track->GetLayer() );
filled = (g_DisplayPolygonsModeSketch == 0);
if( erase )
{
color = g_DrawBgColor;
filled = true;
}
GRClosedPoly( &DrawPanel->m_ClipBox, aDC, points.size(), &points[0],
filled, color, color );
points.clear();
}
}
// Draw tracks and flashes down here.
// This will probably not be a final solution to drawing order issues
GERBER* gerber = g_GERBER_List[layer];
int dcode_hightlight = 0;
if( gerber )
dcode_hightlight = gerber->m_Selected_Tool;
for( TRACK* track = GetBoard()->m_Track; track; track = track->Next() )
BOARD_ITEM* item = GetBoard()->m_Drawings;
for( ; item; item = item->Next() )
{
if( !(track->ReturnMaskLayer() & aPrintMasklayer) )
GERBER_DRAW_ITEM* gerb_item = (GERBER_DRAW_ITEM*) item;
if( !(gerb_item->ReturnMaskLayer() & aPrintMasklayer) )
continue;
if( dcode_hightlight == track->GetNet() && track->GetLayer()==layer )
Trace_Segment( GetBoard(), DrawPanel, aDC, track, aDraw_mode | GR_SURBRILL );
if( dcode_hightlight == gerb_item->m_DCode && item->GetLayer()==layer )
gerb_item->Draw( DrawPanel, aDC, aDraw_mode | GR_SURBRILL );
else
Trace_Segment( GetBoard(), DrawPanel, aDC, track, aDraw_mode );
gerb_item->Draw( DrawPanel, aDC, aDraw_mode );
}
if( IsElementVisible( DCODES_VISIBLE) )
Affiche_DCodes_Pistes( DrawPanel, aDC, GetBoard(), GR_COPY );
Show_Items_DCode_Value( DrawPanel, aDC, GetBoard(), GR_COPY );
GetScreen()->ClrRefreshReq();
}
#if 1
/***********************************************************************************/
void Trace_Segment( BOARD* aBrd, WinEDA_DrawPanel* panel, wxDC* DC, TRACK* track, int draw_mode )
/***********************************************************************************/
/* Trace 1 segment of track (segment, spot...).
* Parameters :
* Track = a pointer on of the description of the track
* draw_mode = mode ( GR_XOR, GR_OR..)
*/
{
int l_piste;
int color;
int fillopt;
int radius;
int halfPenWidth;
static bool show_err;
if( track->m_Flags & DRAW_ERASED ) // draw in background color, used by classs TRACK in gerbview
{
color = g_DrawBgColor;
}
else
{
if( aBrd->IsLayerVisible( track->GetLayer() ) == false )
return;
color = aBrd->GetLayerColor( track->GetLayer() );
if( draw_mode & GR_SURBRILL )
{
if( draw_mode & GR_AND )
color &= ~HIGHT_LIGHT_FLAG;
else
color |= HIGHT_LIGHT_FLAG;
}
if( color & HIGHT_LIGHT_FLAG )
color = ColorRefs[color & MASKCOLOR].m_LightColor;
}
GRSetDrawMode( DC, draw_mode );
fillopt = DisplayOpt.DisplayPcbTrackFill ? FILLED : SKETCH;
switch( track->m_Shape )
{
case S_CIRCLE:
radius = (int) hypot( (double) (track->m_End.x - track->m_Start.x),
(double) (track->m_End.y - track->m_Start.y) );
halfPenWidth = track->m_Width >> 1;
#ifdef USE_WX_ZOOM
if( DC->LogicalToDeviceXRel( halfPenWidth ) < L_MIN_DESSIN )
#else
if( panel->GetScreen()->Scale( halfPenWidth ) < L_MIN_DESSIN )
#endif
{
GRCircle( &panel->m_ClipBox, DC, track->m_Start.x,
track->m_Start.y, radius, 0, color );
}
if( fillopt == SKETCH )
{
// draw the border of the pen's path using two circles, each as narrow as possible
GRCircle( &panel->m_ClipBox, DC, track->m_Start.x, track->m_Start.y,
radius - halfPenWidth, 0, color );
GRCircle( &panel->m_ClipBox, DC, track->m_Start.x, track->m_Start.y,
radius + halfPenWidth, 0, color );
}
else
{
GRCircle( &panel->m_ClipBox, DC, track->m_Start.x, track->m_Start.y,
radius, track->m_Width, color );
}
break;
case S_ARC:
if( fillopt == SKETCH )
{
GRArc1( &panel->m_ClipBox, DC, track->m_Start.x, track->m_Start.y,
track->m_End.x, track->m_End.y,
track->m_Param, track->GetSubNet(), 0, color );
}
else
{
GRArc1( &panel->m_ClipBox, DC, track->m_Start.x, track->m_Start.y,
track->m_End.x, track->m_End.y,
track->m_Param, track->GetSubNet(),
track->m_Width, color );
}
break;
case S_SPOT_CIRCLE:
radius = track->m_Width >> 1;
fillopt = DisplayOpt.DisplayPadFill ? FILLED : SKETCH;
#ifdef USE_WX_ZOOM
if( DC->LogicalToDeviceXRel( radius ) < L_MIN_DESSIN )
#else
if( panel->GetScreen()->Scale( radius ) < L_MIN_DESSIN )
#endif
{
GRCircle( &panel->m_ClipBox, DC, track->m_Start.x,
track->m_Start.y, radius, 0, color );
}
else if( fillopt == SKETCH )
{
GRCircle( &panel->m_ClipBox, DC, track->m_Start.x,
track->m_Start.y, radius, 0, color );
}
else
{
GRFilledCircle( &panel->m_ClipBox, DC, track->m_Start.x,
track->m_Start.y, radius, 0, color, color );
}
break;
case S_SPOT_RECT:
case S_RECT:
l_piste = track->m_Width >> 1;
fillopt = DisplayOpt.DisplayPadFill ? FILLED : SKETCH;
#ifdef USE_WX_ZOOM
if( DC->LogicalToDeviceXRel( l_piste ) < L_MIN_DESSIN )
#else
if( panel->GetScreen()->Scale( l_piste ) < L_MIN_DESSIN )
#endif
{
GRLine( &panel->m_ClipBox, DC, track->m_Start.x, track->m_Start.y,
track->m_End.x, track->m_End.y, 0, color );
}
else if( fillopt == SKETCH )
{
GRRect( &panel->m_ClipBox, DC,
track->m_Start.x - l_piste,
track->m_Start.y - l_piste,
track->m_End.x + l_piste,
track->m_End.y + l_piste,
0, color );
}
else
{
GRFilledRect( &panel->m_ClipBox, DC,
track->m_Start.x - l_piste,
track->m_Start.y - l_piste,
track->m_End.x + l_piste,
track->m_End.y + l_piste,
0, color, color );
}
break;
case S_SPOT_OVALE:
fillopt = DisplayOpt.DisplayPadFill ? FILLED : SKETCH;
case S_SEGMENT:
l_piste = track->m_Width >> 1;
#ifdef USE_WX_ZOOM
if( DC->LogicalToDeviceXRel( l_piste ) < L_MIN_DESSIN )
#else
if( panel->GetScreen()->Scale( l_piste ) < L_MIN_DESSIN )
#endif
{
GRLine( &panel->m_ClipBox, DC, track->m_Start.x, track->m_Start.y,
track->m_End.x, track->m_End.y, 0, color );
break;
}
if( fillopt == SKETCH )
{
GRCSegm( &panel->m_ClipBox, DC, track->m_Start.x, track->m_Start.y,
track->m_End.x, track->m_End.y, track->m_Width, color );
}
else
{
GRFillCSegm( &panel->m_ClipBox, DC, track->m_Start.x,
track->m_Start.y, track->m_End.x, track->m_End.y,
track->m_Width, color );
}
break;
default:
if( !show_err )
{
wxMessageBox( wxT( "Trace_Segment() type error" ) );
show_err = TRUE;
}
break;
}
}
#endif
/*****************************************************************************************/
void Affiche_DCodes_Pistes( WinEDA_DrawPanel* panel, wxDC* DC, BOARD* Pcb, int drawmode )
void Show_Items_DCode_Value( WinEDA_DrawPanel* aPanel, wxDC* aDC, BOARD* aPcb, int aDrawMode )
/*****************************************************************************************/
{
TRACK* track;
wxPoint pos;
int width, orient;
wxString Line;
GRSetDrawMode( DC, drawmode );
track = Pcb->m_Track;
for( ; track != NULL; track = track->Next() )
GRSetDrawMode( aDC, aDrawMode );
BOARD_ITEM* item = aPcb->m_Drawings;
for( ; item != NULL; item = item->Next() )
{
if( Pcb->IsLayerVisible( track->GetLayer() ) == false )
GERBER_DRAW_ITEM* gerb_item = (GERBER_DRAW_ITEM*) item;
if( aPcb->IsLayerVisible( gerb_item->GetLayer() ) == false )
continue;
if( gerb_item->m_DCode <= 0 )
continue;
if( (track->m_Shape == S_ARC)
|| (track->m_Shape == S_CIRCLE)
|| (track->m_Shape == S_ARC_RECT) )
{
pos.x = track->m_Start.x;
pos.y = track->m_Start.y;
}
if( gerb_item->m_Flashed )
pos = gerb_item->m_Start;
else
{
pos.x = (track->m_Start.x + track->m_End.x) / 2;
pos.y = (track->m_Start.y + track->m_End.y) / 2;
pos.x = (gerb_item->m_Start.x + gerb_item->m_End.x) / 2;
pos.y = (gerb_item->m_Start.y + gerb_item->m_End.y) / 2;
}
Line.Printf( wxT( "D%d" ), track->GetNet() );
Line.Printf( wxT( "D%d" ), gerb_item->m_DCode );
width = track->m_Width;
width = MIN( gerb_item->m_Size.x, gerb_item->m_Size.y );
orient = TEXT_ORIENT_HORIZ;
if( track->m_Shape >= S_SPOT_CIRCLE ) // forme flash
if( gerb_item->m_Flashed )
{
width /= 3;
}
else // lines
{
int dx, dy;
dx = track->m_Start.x - track->m_End.x;
dy = track->m_Start.y - track->m_End.y;
dx = gerb_item->m_Start.x - gerb_item->m_End.x;
dy = gerb_item->m_Start.y - gerb_item->m_End.y;
if( abs( dx ) < abs( dy ) )
orient = TEXT_ORIENT_VERT;
width /= 2;
......@@ -432,7 +189,7 @@ void Affiche_DCodes_Pistes( WinEDA_DrawPanel* panel, wxDC* DC, BOARD* Pcb, int d
int color = g_ColorsSettings.GetItemColor(DCODES_VISIBLE);
DrawGraphicText( panel, DC,
DrawGraphicText( aPanel, aDC,
pos, (EDA_Colors) color, Line,
orient, wxSize( width, width ),
GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER,
......
......@@ -223,8 +223,6 @@ public:
* @param DC A device context to draw on.
*/
void Block_Delete( wxDC* DC );
void Block_Rotate( wxDC* DC );
void Block_Invert( wxDC* DC );
/**
* Function Block_Move
......@@ -237,14 +235,6 @@ public:
*/
void Block_Move( wxDC* DC );
/**
* Function Block_Mirror_X
* mirrors all tracks and segments within the currently selected block
* in the X axis.
*
* @param DC A device context to draw on.
*/
void Block_Mirror_X( wxDC* DC );
/**
* Function Block_Duplicate
* copies-and-moves all tracks and segments within the selected block.
......@@ -339,7 +329,6 @@ public:
bool Clear_Pcb( bool query );
void Erase_Current_Layer( bool query );
void Delete_DCode_Items( wxDC* DC, int dcode_value, int layer_number );
TRACK* Delete_Segment( wxDC* DC, TRACK* Track );
// Conversion function
void ExportDataInPcbnewFormat( wxCommandEvent& event );
......
......@@ -87,6 +87,11 @@ enum KICAD_T {
*/
COMPONENT_FIELD_DRAW_TYPE,
/*
* For Gerbview: items type:
*/
TYPE_GERBER_DRAW_ITEM,
// End value
MAX_STRUCT_TYPE_ID
};
......
......@@ -9,18 +9,15 @@
#include <boost/ptr_container/ptr_vector.hpp>
/* Shapes for segments (graphic segments and tracks) ( .shape member ) */
/* Shapes for segments (graphic segments and tracks) ( .m_Shape member ) */
enum Track_Shapes {
S_SEGMENT = 0, /* usual segment : line with rounded ends */
S_RECT, /* segment with non rounded ends */
S_ARC, /* Arcs (with rounded ends)*/
S_CIRCLE, /* ring*/
S_ARC_RECT, /* Arcs (with non rounded ends) (GERBER)*/
S_SPOT_OVALE, /* Oblong spot (for GERBER)*/
S_SPOT_CIRCLE, /* rounded spot (for GERBER)*/
S_SPOT_RECT, /* Rectangular spott (for GERBER)*/
S_POLYGON, /* polygonal shape */
S_CURVE /* Bezier Curve*/
S_POLYGON, /* polygonal shape (not yet used for tracks, but could be in microwave apps) */
S_CURVE, /* Bezier Curve*/
S_LAST /* last value for this list */
};
......
......@@ -171,12 +171,10 @@ void GRCircle( EDA_Rect* ClipBox, wxDC* aDC, int x, int y, int aRadius,
void GRCircle( EDA_Rect* ClipBox, wxDC* DC, int x, int y, int r, int width,
int Color );
void GRFilledCircle( EDA_Rect* ClipBox, wxDC* DC, int x, int y, int r,
int width, int Color, int BgColor );
void GRSCircle( EDA_Rect* ClipBox, wxDC* DC, int x, int y, int r, int width,
int Color );
void GRSFilledCircle( EDA_Rect* ClipBox, wxDC* DC, int x, int y, int r,
int width, int Color, int BgColor );
void GRFilledCircle( EDA_Rect* ClipBox, wxDC* DC, int x, int y, int r, int width, int Color, int BgColor );
void GRFilledCircle( EDA_Rect* aClipBox, wxDC* aDC, wxPoint aPos, int aRadius, int aColor );
void GRCircle( EDA_Rect* aClipBox, wxDC* aDC, wxPoint aPos, int aRadius, int aWidth, int aColor );
void GRArc( EDA_Rect* ClipBox, wxDC* DC, int x, int y, int StAngle,
int EndAngle, int r, int Color );
void GRArc( EDA_Rect* ClipBox, wxDC* DC, int x, int y, int StAngle,
......
......@@ -25,12 +25,6 @@ wxString BOARD_ITEM::ShowShape( Track_Shapes aShape )
case S_ARC: return _( "Arc" );
case S_CIRCLE: return _( "Circle" );
case S_CURVE: return _( "Bezier Curve" );
// used in Gerbview:
case S_ARC_RECT: return wxT( "arc_rect" );
case S_SPOT_OVALE: return wxT( "spot_oval" );
case S_SPOT_CIRCLE: return wxT( "spot_circle" );
case S_SPOT_RECT: return wxT( "spot_rect" );
case S_POLYGON: return wxT( "polygon" );
default: return wxT( "??" );
}
......
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