2009-11-09 14:00:22 +00:00
|
|
|
|
/***************************/
|
2010-09-28 14:42:05 +00:00
|
|
|
|
/**** class D_CODE ****/
|
2009-11-09 14:00:22 +00:00
|
|
|
|
/***************************/
|
2007-06-05 12:10:51 +00:00
|
|
|
|
|
|
|
|
|
#include "fctsys.h"
|
|
|
|
|
#include "common.h"
|
2009-02-04 15:25:03 +00:00
|
|
|
|
#include "class_drawpanel.h"
|
|
|
|
|
#include "confirm.h"
|
2009-04-05 20:49:15 +00:00
|
|
|
|
#include "macros.h"
|
2010-09-28 14:42:05 +00:00
|
|
|
|
#include "trigo.h"
|
2009-02-04 15:25:03 +00:00
|
|
|
|
|
2007-06-05 12:10:51 +00:00
|
|
|
|
#include "gerbview.h"
|
2010-09-28 14:42:05 +00:00
|
|
|
|
#include "class_gerber_draw_item.h"
|
2010-10-06 17:28:07 +00:00
|
|
|
|
#include "class_GERBER.h"
|
2007-06-05 12:10:51 +00:00
|
|
|
|
|
|
|
|
|
#define DEFAULT_SIZE 100
|
|
|
|
|
|
2009-11-09 14:00:22 +00:00
|
|
|
|
/* Format Gerber: NOTES:
|
|
|
|
|
* Tools and D_CODES
|
|
|
|
|
* tool number (identification of shapes)
|
|
|
|
|
* 1 to 999
|
|
|
|
|
*
|
|
|
|
|
* D_CODES:
|
2010-09-29 19:00:35 +00:00
|
|
|
|
* D01 ... D9 = command codes:
|
|
|
|
|
* D01 = activating light (pen down) while moving
|
|
|
|
|
* D02 = light extinction (pen up) while moving
|
|
|
|
|
* D03 = Flash
|
|
|
|
|
* D04 to D09 = non used
|
|
|
|
|
* D10 ... D999 = Indentification Tool (Shape id)
|
2010-09-28 14:42:05 +00:00
|
|
|
|
*
|
2010-09-29 19:00:35 +00:00
|
|
|
|
* For tools defining a shape):
|
2010-09-28 14:42:05 +00:00
|
|
|
|
* DCode min = D10
|
|
|
|
|
* DCode max = 999
|
2009-11-09 14:00:22 +00:00
|
|
|
|
*/
|
|
|
|
|
|
2007-06-05 12:10:51 +00:00
|
|
|
|
|
2009-11-09 14:00:22 +00:00
|
|
|
|
/***************/
|
|
|
|
|
/* Class DCODE */
|
|
|
|
|
/***************/
|
2007-06-05 12:10:51 +00:00
|
|
|
|
|
|
|
|
|
|
2008-04-17 16:25:29 +00:00
|
|
|
|
D_CODE::D_CODE( int num_dcode )
|
2007-06-05 12:10:51 +00:00
|
|
|
|
{
|
2008-04-17 16:25:29 +00:00
|
|
|
|
m_Num_Dcode = num_dcode;
|
|
|
|
|
Clear_D_CODE_Data();
|
2007-06-05 12:10:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-04-17 16:25:29 +00:00
|
|
|
|
|
2007-09-13 11:55:46 +00:00
|
|
|
|
D_CODE::~D_CODE()
|
2007-06-05 12:10:51 +00:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2008-04-17 16:25:29 +00:00
|
|
|
|
|
2007-09-13 11:55:46 +00:00
|
|
|
|
void D_CODE::Clear_D_CODE_Data()
|
2007-06-05 12:10:51 +00:00
|
|
|
|
{
|
2008-04-17 16:25:29 +00:00
|
|
|
|
m_Size.x = DEFAULT_SIZE;
|
|
|
|
|
m_Size.y = DEFAULT_SIZE;
|
2008-11-08 06:44:07 +00:00
|
|
|
|
m_Shape = APT_CIRCLE;
|
2008-04-17 16:25:29 +00:00
|
|
|
|
m_Drill.x = m_Drill.y = 0;
|
2010-09-28 19:34:16 +00:00
|
|
|
|
m_DrillShape = APT_DEF_NO_HOLE;
|
2009-11-09 14:00:22 +00:00
|
|
|
|
m_InUse = FALSE;
|
|
|
|
|
m_Defined = FALSE;
|
2010-09-28 19:34:16 +00:00
|
|
|
|
m_Macro = NULL;
|
2010-09-28 14:42:05 +00:00
|
|
|
|
m_Rotation = 0.0;
|
2010-09-28 19:34:16 +00:00
|
|
|
|
m_EdgesCount = 0;
|
2010-10-05 11:44:34 +00:00
|
|
|
|
m_PolyCorners.clear();
|
2008-11-09 02:57:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
2009-11-09 14:00:22 +00:00
|
|
|
|
|
2008-11-09 02:57:42 +00:00
|
|
|
|
const wxChar* D_CODE::ShowApertureType( APERTURE_T aType )
|
|
|
|
|
{
|
|
|
|
|
const wxChar* ret;
|
|
|
|
|
|
|
|
|
|
switch( aType )
|
|
|
|
|
{
|
2009-11-09 14:00:22 +00:00
|
|
|
|
case APT_CIRCLE:
|
|
|
|
|
ret = wxT( "Round" ); break;
|
|
|
|
|
|
|
|
|
|
case APT_RECT:
|
|
|
|
|
ret = wxT( "Rect" ); break;
|
|
|
|
|
|
|
|
|
|
case APT_OVAL:
|
|
|
|
|
ret = wxT( "Oval" ); break;
|
|
|
|
|
|
|
|
|
|
case APT_POLYGON:
|
|
|
|
|
ret = wxT( "Poly" ); break;
|
|
|
|
|
|
|
|
|
|
case APT_MACRO:
|
|
|
|
|
ret = wxT( "Macro" ); break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
ret = wxT( "???" ); break;
|
2008-11-09 02:57:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
2007-06-05 12:10:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-10-23 18:12:11 +00:00
|
|
|
|
/** GetShapeDim
|
|
|
|
|
* Calculate a value that can be used to evaluate the size of text
|
|
|
|
|
* when displaying the D-Code of an item
|
|
|
|
|
* due to the complexity of some shapes,
|
|
|
|
|
* one cannot calculate the "size" of a shape (only a bounding box)
|
|
|
|
|
* but here, the "dimension" of the shape is the diameter of the primitive
|
|
|
|
|
* or for lines the width of the line if the shape is a line
|
|
|
|
|
* @param aParent = the parent GERBER_DRAW_ITEM which is actually drawn
|
|
|
|
|
* @return a dimension, or -1 if no dim to calculate
|
|
|
|
|
*/
|
|
|
|
|
int D_CODE::GetShapeDim( GERBER_DRAW_ITEM* aParent )
|
|
|
|
|
{
|
|
|
|
|
int dim = -1;
|
|
|
|
|
switch( m_Shape )
|
|
|
|
|
{
|
|
|
|
|
case APT_CIRCLE:
|
|
|
|
|
dim = m_Size.x;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case APT_RECT:
|
|
|
|
|
case APT_OVAL:
|
|
|
|
|
dim = MIN( m_Size.x, m_Size.y );
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case APT_POLYGON:
|
|
|
|
|
dim = MIN( m_Size.x, m_Size.y );
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case APT_MACRO:
|
|
|
|
|
if( m_Macro )
|
|
|
|
|
dim = m_Macro->GetShapeDim( aParent );
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return dim;
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-01 19:11:30 +00:00
|
|
|
|
|
2010-09-30 06:25:33 +00:00
|
|
|
|
/** Function Read_D_Code_File
|
|
|
|
|
* Can be useful only with old RS274D Gerber file format.
|
|
|
|
|
* Is not needed with RS274X files format.
|
2010-10-01 19:11:30 +00:00
|
|
|
|
* These files need an auxiliary DCode file description. There is no defined file format for this.
|
2010-09-30 06:25:33 +00:00
|
|
|
|
* This function read a file format I needed a long time ago.
|
|
|
|
|
* reads in a dcode file assuming ALSPCB file format with ';' indicating comments.
|
|
|
|
|
* Format is like CSV but with optional ';' delineated comments:
|
|
|
|
|
* tool, Horiz, Vert, drill, vitesse, acc. ,Type ; [DCODE (commentaire)]
|
|
|
|
|
* ex: 1, 12, 12, 0, 0, 0, 3 ; D10
|
|
|
|
|
*/
|
2008-04-17 16:25:29 +00:00
|
|
|
|
int WinEDA_GerberFrame::Read_D_Code_File( const wxString& D_Code_FullFileName )
|
2007-06-05 12:10:51 +00:00
|
|
|
|
{
|
2008-04-17 16:25:29 +00:00
|
|
|
|
int current_Dcode, ii, dcode_scale;
|
|
|
|
|
char* ptcar;
|
2008-11-08 06:44:07 +00:00
|
|
|
|
int dimH, dimV, drill, dummy;
|
2008-04-17 16:25:29 +00:00
|
|
|
|
float fdimH, fdimV, fdrill;
|
|
|
|
|
char c_type_outil[256];
|
2008-11-08 06:44:07 +00:00
|
|
|
|
char line[GERBER_BUFZ];
|
2008-04-17 16:25:29 +00:00
|
|
|
|
wxString msg;
|
2008-11-09 02:57:42 +00:00
|
|
|
|
D_CODE* dcode;
|
2008-04-17 16:25:29 +00:00
|
|
|
|
FILE* dest;
|
|
|
|
|
int layer = GetScreen()->m_Active_Layer;
|
2008-11-08 06:44:07 +00:00
|
|
|
|
int type_outil;
|
2008-04-17 16:25:29 +00:00
|
|
|
|
|
2008-11-08 06:44:07 +00:00
|
|
|
|
if( g_GERBER_List[layer] == NULL )
|
2010-10-16 14:51:22 +00:00
|
|
|
|
g_GERBER_List[layer] = new GERBER_IMAGE( this, layer );
|
2008-04-17 16:25:29 +00:00
|
|
|
|
|
2010-10-16 14:51:22 +00:00
|
|
|
|
GERBER_IMAGE* gerber = g_GERBER_List[layer];
|
2008-11-09 02:57:42 +00:00
|
|
|
|
|
|
|
|
|
|
2009-11-09 14:00:22 +00:00
|
|
|
|
/* Updating gerber scale: */
|
|
|
|
|
dcode_scale = 10; /* By uniting dCode = mil, internal unit = 0.1 mil
|
|
|
|
|
* -> 1 unite dcode = 10 unit PCB */
|
2008-04-17 16:25:29 +00:00
|
|
|
|
current_Dcode = 0;
|
|
|
|
|
|
|
|
|
|
if( D_Code_FullFileName.IsEmpty() )
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
dest = wxFopen( D_Code_FullFileName, wxT( "rt" ) );
|
|
|
|
|
if( dest == 0 )
|
|
|
|
|
{
|
|
|
|
|
msg = _( "File " ) + D_Code_FullFileName + _( " not found" );
|
|
|
|
|
DisplayError( this, msg, 10 );
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-09 02:57:42 +00:00
|
|
|
|
gerber->InitToolTable();
|
2008-04-17 16:25:29 +00:00
|
|
|
|
|
2008-11-08 06:44:07 +00:00
|
|
|
|
while( fgets( line, sizeof(line) - 1, dest ) != NULL )
|
2008-04-17 16:25:29 +00:00
|
|
|
|
{
|
2008-11-08 06:44:07 +00:00
|
|
|
|
if( *line == ';' )
|
2009-11-09 14:00:22 +00:00
|
|
|
|
continue;
|
2008-11-09 02:57:42 +00:00
|
|
|
|
|
2008-11-08 06:44:07 +00:00
|
|
|
|
if( strlen( line ) < 10 )
|
2009-11-09 14:00:22 +00:00
|
|
|
|
continue; /* Skip blank line. */
|
2008-04-17 16:25:29 +00:00
|
|
|
|
|
2008-11-09 02:57:42 +00:00
|
|
|
|
dcode = NULL;
|
|
|
|
|
current_Dcode = 0;
|
2008-11-08 06:44:07 +00:00
|
|
|
|
|
2009-11-09 14:00:22 +00:00
|
|
|
|
/* Determine of the type of file from D_Code. */
|
2008-11-08 06:44:07 +00:00
|
|
|
|
ptcar = line;
|
2009-11-09 14:00:22 +00:00
|
|
|
|
ii = 0;
|
2008-04-17 16:25:29 +00:00
|
|
|
|
while( *ptcar )
|
|
|
|
|
if( *(ptcar++) == ',' )
|
|
|
|
|
ii++;
|
|
|
|
|
|
|
|
|
|
if( ii >= 6 ) /* valeurs en mils */
|
|
|
|
|
{
|
2008-11-08 06:44:07 +00:00
|
|
|
|
sscanf( line, "%d,%d,%d,%d,%d,%d,%d", &ii,
|
2010-10-01 19:11:30 +00:00
|
|
|
|
&dimH, &dimV, &drill, &dummy, &dummy, &type_outil );
|
2008-11-08 06:44:07 +00:00
|
|
|
|
|
2010-09-30 06:25:33 +00:00
|
|
|
|
dimH = wxRound( dimH * dcode_scale );
|
|
|
|
|
dimV = wxRound( dimV * dcode_scale );
|
|
|
|
|
drill = wxRound( drill * dcode_scale );
|
2008-04-17 16:25:29 +00:00
|
|
|
|
if( ii < 1 )
|
|
|
|
|
ii = 1;
|
|
|
|
|
current_Dcode = ii - 1 + FIRST_DCODE;
|
|
|
|
|
}
|
2009-11-09 14:00:22 +00:00
|
|
|
|
else /* Values in inches are converted to mils. */
|
2008-04-17 16:25:29 +00:00
|
|
|
|
{
|
2008-11-09 02:57:42 +00:00
|
|
|
|
fdrill = 0;
|
|
|
|
|
current_Dcode = 0;
|
|
|
|
|
|
2008-11-08 06:44:07 +00:00
|
|
|
|
sscanf( line, "%f,%f,%1s", &fdimV, &fdimH, c_type_outil );
|
|
|
|
|
ptcar = line;
|
2008-04-17 16:25:29 +00:00
|
|
|
|
while( *ptcar )
|
|
|
|
|
{
|
|
|
|
|
if( *ptcar == 'D' )
|
|
|
|
|
{
|
2008-11-08 06:44:07 +00:00
|
|
|
|
sscanf( ptcar + 1, "%d,%f", ¤t_Dcode, &fdrill );
|
|
|
|
|
break;
|
2008-04-17 16:25:29 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
ptcar++;
|
|
|
|
|
}
|
|
|
|
|
|
2010-09-30 06:25:33 +00:00
|
|
|
|
dimH = wxRound( fdimH * dcode_scale * 1000 );
|
|
|
|
|
dimV = wxRound( fdimV * dcode_scale * 1000 );
|
|
|
|
|
drill = wxRound( fdrill * dcode_scale * 1000 );
|
2008-11-08 06:44:07 +00:00
|
|
|
|
|
|
|
|
|
if( strchr( "CLROP", c_type_outil[0] ) )
|
|
|
|
|
type_outil = (APERTURE_T) c_type_outil[0];
|
|
|
|
|
else
|
2008-04-17 16:25:29 +00:00
|
|
|
|
{
|
2008-11-08 06:44:07 +00:00
|
|
|
|
fclose( dest );
|
|
|
|
|
return -2;
|
2008-04-17 16:25:29 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2008-11-08 06:44:07 +00:00
|
|
|
|
|
2009-11-09 14:00:22 +00:00
|
|
|
|
/* Update the list of d_codes if consistant. */
|
2008-04-17 16:25:29 +00:00
|
|
|
|
if( current_Dcode < FIRST_DCODE )
|
|
|
|
|
continue;
|
2008-11-08 06:44:07 +00:00
|
|
|
|
|
2010-09-28 14:42:05 +00:00
|
|
|
|
if( current_Dcode >= TOOLS_MAX_COUNT )
|
2008-04-17 16:25:29 +00:00
|
|
|
|
continue;
|
2008-11-08 06:44:07 +00:00
|
|
|
|
|
2008-11-09 02:57:42 +00:00
|
|
|
|
dcode = gerber->GetDCODE( current_Dcode );
|
|
|
|
|
dcode->m_Size.x = dimH;
|
|
|
|
|
dcode->m_Size.y = dimV;
|
|
|
|
|
dcode->m_Shape = (APERTURE_T) type_outil;
|
|
|
|
|
dcode->m_Drill.x = dcode->m_Drill.y = drill;
|
|
|
|
|
dcode->m_Defined = TRUE;
|
2008-04-17 16:25:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fclose( dest );
|
|
|
|
|
|
|
|
|
|
return 1;
|
2007-06-05 12:10:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Set Size Items (Lines, Flashes) from DCodes List
|
2008-04-17 16:25:29 +00:00
|
|
|
|
*/
|
2009-11-09 14:00:22 +00:00
|
|
|
|
void WinEDA_GerberFrame::CopyDCodesSizeToItems()
|
2007-06-05 12:10:51 +00:00
|
|
|
|
{
|
2009-11-09 14:00:22 +00:00
|
|
|
|
static D_CODE dummy( 999 ); //Used if D_CODE not found in list
|
2008-12-17 14:51:39 +00:00
|
|
|
|
|
2010-09-28 14:42:05 +00:00
|
|
|
|
BOARD_ITEM* item = GetBoard()->m_Drawings;
|
2008-11-09 02:57:42 +00:00
|
|
|
|
|
2010-09-28 14:42:05 +00:00
|
|
|
|
for( ; item; item = item->Next() )
|
|
|
|
|
{
|
|
|
|
|
GERBER_DRAW_ITEM* gerb_item = (GERBER_DRAW_ITEM*) item;
|
|
|
|
|
D_CODE* dcode = gerb_item->GetDcodeDescr();
|
2008-11-09 02:57:42 +00:00
|
|
|
|
wxASSERT( dcode );
|
2009-11-09 14:00:22 +00:00
|
|
|
|
if( dcode == NULL )
|
2008-12-17 14:51:39 +00:00
|
|
|
|
dcode = &dummy;
|
2008-11-09 02:57:42 +00:00
|
|
|
|
|
|
|
|
|
dcode->m_InUse = TRUE;
|
2008-04-17 16:25:29 +00:00
|
|
|
|
|
2010-09-28 14:42:05 +00:00
|
|
|
|
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) */
|
2008-04-17 16:25:29 +00:00
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
else // Spots ( Flashed Items )
|
|
|
|
|
{
|
2008-11-09 02:57:42 +00:00
|
|
|
|
switch( dcode->m_Shape )
|
2008-04-17 16:25:29 +00:00
|
|
|
|
{
|
2010-09-28 19:34:16 +00:00
|
|
|
|
case APT_CIRCLE: /* spot round */
|
2010-09-28 14:42:05 +00:00
|
|
|
|
gerb_item->m_Shape = GBR_SPOT_CIRCLE;
|
2008-04-17 16:25:29 +00:00
|
|
|
|
break;
|
|
|
|
|
|
2010-09-28 19:34:16 +00:00
|
|
|
|
case APT_OVAL: /* spot oval*/
|
2010-09-28 14:42:05 +00:00
|
|
|
|
gerb_item->m_Shape = GBR_SPOT_OVAL;
|
2008-04-17 16:25:29 +00:00
|
|
|
|
break;
|
|
|
|
|
|
2010-09-28 19:34:16 +00:00
|
|
|
|
case APT_RECT: /* spot rect*/
|
2010-09-28 14:42:05 +00:00
|
|
|
|
gerb_item->m_Shape = GBR_SPOT_RECT;
|
2008-04-17 16:25:29 +00:00
|
|
|
|
break;
|
2010-09-28 19:34:16 +00:00
|
|
|
|
|
|
|
|
|
case APT_POLYGON: /* spot regular polyg 3 to 1<> edges */
|
|
|
|
|
gerb_item->m_Shape = GBR_SPOT_POLY;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case APT_MACRO: /* spot defined by a macro */
|
|
|
|
|
gerb_item->m_Shape = GBR_SPOT_MACRO;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
2010-10-01 19:11:30 +00:00
|
|
|
|
wxMessageBox( wxT( "WinEDA_GerberFrame::CopyDCodesSizeToItems() error" ) );
|
2010-09-28 19:34:16 +00:00
|
|
|
|
break;
|
2008-04-17 16:25:29 +00:00
|
|
|
|
}
|
2010-09-28 14:42:05 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-04-17 16:25:29 +00:00
|
|
|
|
|
2010-09-28 14:42:05 +00:00
|
|
|
|
/** function DrawFlashedShape
|
|
|
|
|
* Draw the dcode shape for flashed items.
|
|
|
|
|
* When an item is flashed, the DCode shape is the shape of the item
|
|
|
|
|
*/
|
2010-10-01 19:11:30 +00:00
|
|
|
|
void D_CODE::DrawFlashedShape( GERBER_DRAW_ITEM* aParent,
|
2010-10-03 15:39:06 +00:00
|
|
|
|
EDA_Rect* aClipBox, wxDC* aDC, int aColor, int aAltColor,
|
2010-10-01 19:11:30 +00:00
|
|
|
|
wxPoint aShapePos, bool aFilledShape )
|
2010-09-28 14:42:05 +00:00
|
|
|
|
{
|
|
|
|
|
int radius;
|
|
|
|
|
|
|
|
|
|
switch( m_Shape )
|
|
|
|
|
{
|
2010-10-01 19:11:30 +00:00
|
|
|
|
case APT_MACRO:
|
2010-10-03 15:39:06 +00:00
|
|
|
|
GetMacro()->DrawApertureMacroShape( aParent, aClipBox, aDC, aColor, aAltColor,
|
|
|
|
|
aShapePos, aFilledShape);
|
2010-10-01 19:11:30 +00:00
|
|
|
|
break;
|
2010-09-28 19:34:16 +00:00
|
|
|
|
|
2010-09-28 14:42:05 +00:00
|
|
|
|
case APT_CIRCLE:
|
|
|
|
|
radius = m_Size.x >> 1;
|
|
|
|
|
if( !aFilledShape )
|
2010-10-10 17:57:54 +00:00
|
|
|
|
GRCircle( aClipBox, aDC, aParent->GetABPosition(aShapePos),
|
|
|
|
|
radius, 0, aColor );
|
2010-09-28 14:42:05 +00:00
|
|
|
|
else
|
2010-09-28 19:34:16 +00:00
|
|
|
|
if( m_DrillShape == APT_DEF_NO_HOLE )
|
2010-10-10 17:57:54 +00:00
|
|
|
|
GRFilledCircle( aClipBox, aDC, aParent->GetABPosition(aShapePos),
|
|
|
|
|
radius, aColor );
|
2010-09-28 19:34:16 +00:00
|
|
|
|
else if( APT_DEF_ROUND_HOLE == 1 ) // round hole in shape
|
2008-04-17 16:25:29 +00:00
|
|
|
|
{
|
2010-09-28 14:42:05 +00:00
|
|
|
|
int width = (m_Size.x - m_Drill.x ) / 2;
|
2010-10-10 17:57:54 +00:00
|
|
|
|
GRCircle( aClipBox, aDC, aParent->GetABPosition(aShapePos),
|
|
|
|
|
radius - (width / 2), width, aColor );
|
2008-04-17 16:25:29 +00:00
|
|
|
|
}
|
2010-09-28 14:42:05 +00:00
|
|
|
|
else // rectangular hole
|
2008-04-17 16:25:29 +00:00
|
|
|
|
{
|
2010-09-28 14:42:05 +00:00
|
|
|
|
if( m_PolyCorners.size() == 0 )
|
|
|
|
|
ConvertShapeToPolygon();
|
2010-10-10 17:57:54 +00:00
|
|
|
|
DrawFlashedPolygon( aParent, aClipBox, aDC, aColor, aFilledShape, aShapePos );
|
2008-04-17 16:25:29 +00:00
|
|
|
|
}
|
2010-09-28 14:42:05 +00:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case APT_RECT:
|
|
|
|
|
{
|
|
|
|
|
wxPoint start;
|
2010-09-28 19:34:16 +00:00
|
|
|
|
start.x = aShapePos.x - m_Size.x / 2;
|
|
|
|
|
start.y = aShapePos.y - m_Size.y / 2;
|
2010-09-28 14:42:05 +00:00
|
|
|
|
wxPoint end = start + m_Size;
|
2010-10-10 17:57:54 +00:00
|
|
|
|
start = aParent->GetABPosition( start );
|
|
|
|
|
end = aParent->GetABPosition( end );
|
2010-09-28 14:42:05 +00:00
|
|
|
|
if( !aFilledShape )
|
|
|
|
|
{
|
2010-09-28 19:34:16 +00:00
|
|
|
|
GRRect( aClipBox, aDC, start.x, start.y, end.x, end.y,
|
2010-09-28 14:42:05 +00:00
|
|
|
|
0, aColor );
|
|
|
|
|
}
|
2010-09-28 19:34:16 +00:00
|
|
|
|
else if( m_DrillShape == APT_DEF_NO_HOLE )
|
2010-09-28 14:42:05 +00:00
|
|
|
|
{
|
|
|
|
|
GRFilledRect( aClipBox, aDC, start.x, start.y, end.x, end.y,
|
|
|
|
|
0, aColor, aColor );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if( m_PolyCorners.size() == 0 )
|
|
|
|
|
ConvertShapeToPolygon();
|
2010-10-10 17:57:54 +00:00
|
|
|
|
DrawFlashedPolygon( aParent, aClipBox, aDC, aColor, aFilledShape, aShapePos );
|
2008-04-17 16:25:29 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2010-09-28 19:34:16 +00:00
|
|
|
|
break;
|
2010-09-28 14:42:05 +00:00
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
2010-10-10 17:57:54 +00:00
|
|
|
|
start = aParent->GetABPosition( start );
|
|
|
|
|
end = aParent->GetABPosition( end );
|
2010-09-28 14:42:05 +00:00
|
|
|
|
if( !aFilledShape )
|
|
|
|
|
{
|
|
|
|
|
GRCSegm( aClipBox, aDC, start.x, start.y,
|
|
|
|
|
end.x, end.y, radius, aColor );
|
|
|
|
|
}
|
2010-09-28 19:34:16 +00:00
|
|
|
|
else if( m_DrillShape == APT_DEF_NO_HOLE )
|
2010-09-28 14:42:05 +00:00
|
|
|
|
{
|
|
|
|
|
GRFillCSegm( aClipBox, aDC, start.x,
|
|
|
|
|
start.y, end.x, end.y, radius, aColor );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if( m_PolyCorners.size() == 0 )
|
|
|
|
|
ConvertShapeToPolygon();
|
2010-10-10 17:57:54 +00:00
|
|
|
|
DrawFlashedPolygon( aParent, aClipBox, aDC, aColor, aFilledShape, aShapePos );
|
2010-09-28 14:42:05 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case APT_POLYGON:
|
|
|
|
|
if( m_PolyCorners.size() == 0 )
|
|
|
|
|
ConvertShapeToPolygon();
|
2010-10-10 17:57:54 +00:00
|
|
|
|
DrawFlashedPolygon( aParent, aClipBox, aDC, aColor, aFilledShape, aShapePos );
|
2010-09-28 14:42:05 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
2007-06-05 12:10:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-09-28 14:42:05 +00:00
|
|
|
|
/** 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)
|
|
|
|
|
*/
|
2010-10-10 17:57:54 +00:00
|
|
|
|
void D_CODE::DrawFlashedPolygon( GERBER_DRAW_ITEM* aParent,
|
|
|
|
|
EDA_Rect* aClipBox, wxDC* aDC,
|
2010-09-28 14:42:05 +00:00
|
|
|
|
int aColor, bool aFilled,
|
|
|
|
|
const wxPoint& aPosition )
|
2007-06-05 12:10:51 +00:00
|
|
|
|
{
|
2010-09-28 14:42:05 +00:00
|
|
|
|
if( m_PolyCorners.size() == 0 )
|
|
|
|
|
return;
|
2009-11-09 14:00:22 +00:00
|
|
|
|
|
2010-09-28 14:42:05 +00:00
|
|
|
|
std::vector<wxPoint> points;
|
|
|
|
|
points = m_PolyCorners;
|
|
|
|
|
for( unsigned ii = 0; ii < points.size(); ii++ )
|
|
|
|
|
{
|
|
|
|
|
points[ii] += aPosition;
|
2010-10-10 17:57:54 +00:00
|
|
|
|
points[ii] = aParent->GetABPosition( points[ii] );
|
2010-09-28 14:42:05 +00:00
|
|
|
|
}
|
2008-04-17 16:25:29 +00:00
|
|
|
|
|
2010-09-28 14:42:05 +00:00
|
|
|
|
GRClosedPoly( aClipBox, aDC, points.size(), &points[0], aFilled, aColor, aColor );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-09-28 19:34:16 +00:00
|
|
|
|
#define SEGS_CNT 32 // number of segments to approximate a circle
|
|
|
|
|
|
|
|
|
|
// A helper function for D_CODE::ConvertShapeToPolygon().
|
|
|
|
|
// Add a hole to a polygon
|
|
|
|
|
static void addHoleToPolygon( std::vector<wxPoint>& aBuffer,
|
|
|
|
|
APERTURE_DEF_HOLETYPE aHoleShape,
|
|
|
|
|
wxSize aSize,
|
2010-10-01 19:11:30 +00:00
|
|
|
|
wxPoint aAnchorPos );
|
2010-09-28 19:34:16 +00:00
|
|
|
|
|
2010-09-28 14:42:05 +00:00
|
|
|
|
/** 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()
|
|
|
|
|
{
|
|
|
|
|
wxPoint initialpos;
|
|
|
|
|
wxPoint currpos;;
|
2010-10-01 19:11:30 +00:00
|
|
|
|
|
2010-09-28 14:42:05 +00:00
|
|
|
|
m_PolyCorners.clear();
|
|
|
|
|
|
|
|
|
|
switch( m_Shape )
|
2008-04-17 16:25:29 +00:00
|
|
|
|
{
|
2010-09-28 14:42:05 +00:00
|
|
|
|
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 );
|
|
|
|
|
}
|
2010-09-28 19:34:16 +00:00
|
|
|
|
|
|
|
|
|
addHoleToPolygon( m_PolyCorners, m_DrillShape, m_Drill, initialpos );
|
2010-09-28 14:42:05 +00:00
|
|
|
|
break;
|
2008-11-08 06:44:07 +00:00
|
|
|
|
|
2010-09-28 14:42:05 +00:00
|
|
|
|
case APT_RECT:
|
2010-09-28 19:34:16 +00:00
|
|
|
|
currpos.x = m_Size.x / 2;
|
|
|
|
|
currpos.y = m_Size.y / 2;
|
2010-09-28 14:42:05 +00:00
|
|
|
|
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;
|
2010-09-28 19:34:16 +00:00
|
|
|
|
m_PolyCorners.push_back( currpos ); // close polygon
|
|
|
|
|
|
|
|
|
|
addHoleToPolygon( m_PolyCorners, m_DrillShape, m_Drill, initialpos );
|
2010-09-28 14:42:05 +00:00
|
|
|
|
break;
|
2008-04-17 16:25:29 +00:00
|
|
|
|
|
2010-09-28 14:42:05 +00:00
|
|
|
|
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
|
2008-04-17 16:25:29 +00:00
|
|
|
|
{
|
2010-09-28 19:34:16 +00:00
|
|
|
|
delta = (m_Size.x - m_Size.y) / 2;
|
2010-09-28 14:42:05 +00:00
|
|
|
|
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 );
|
|
|
|
|
}
|
2010-09-28 19:34:16 +00:00
|
|
|
|
|
2010-09-28 14:42:05 +00:00
|
|
|
|
m_PolyCorners.push_back( initialpos ); // close outline
|
2010-09-28 19:34:16 +00:00
|
|
|
|
if( m_Size.y > m_Size.x ) // vertical oval, rotate polygon.
|
2010-09-28 14:42:05 +00:00
|
|
|
|
{
|
|
|
|
|
for( unsigned jj = 0; jj < m_PolyCorners.size(); jj++ )
|
|
|
|
|
RotatePoint( &m_PolyCorners[jj], 900 );
|
|
|
|
|
}
|
2010-09-28 19:34:16 +00:00
|
|
|
|
|
|
|
|
|
addHoleToPolygon( m_PolyCorners, m_DrillShape, m_Drill, initialpos );
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case APT_POLYGON:
|
|
|
|
|
currpos.x = m_Size.x >> 1; // first point is on X axis
|
|
|
|
|
initialpos = currpos;
|
2010-10-01 19:11:30 +00:00
|
|
|
|
|
2010-09-28 19:34:16 +00:00
|
|
|
|
// rs274x said: m_EdgesCount = 3 ... 12
|
|
|
|
|
if( m_EdgesCount < 3 )
|
|
|
|
|
m_EdgesCount = 3;
|
|
|
|
|
if( m_EdgesCount > 12 )
|
|
|
|
|
m_EdgesCount = 12;
|
|
|
|
|
for( int ii = 0; ii <= m_EdgesCount; ii++ )
|
2010-09-28 14:42:05 +00:00
|
|
|
|
{
|
2010-09-28 19:34:16 +00:00
|
|
|
|
currpos = initialpos;
|
|
|
|
|
RotatePoint( &currpos, ii * 3600 / m_EdgesCount );
|
|
|
|
|
m_PolyCorners.push_back( currpos );
|
2010-09-28 14:42:05 +00:00
|
|
|
|
}
|
2010-10-01 19:11:30 +00:00
|
|
|
|
|
2010-09-28 19:34:16 +00:00
|
|
|
|
addHoleToPolygon( m_PolyCorners, m_DrillShape, m_Drill, initialpos );
|
|
|
|
|
if( m_Rotation ) // vertical oval, rotate polygon.
|
2010-09-28 14:42:05 +00:00
|
|
|
|
{
|
2010-10-01 19:11:30 +00:00
|
|
|
|
int angle = wxRound( m_Rotation * 10 );
|
2010-09-28 19:34:16 +00:00
|
|
|
|
for( unsigned jj = 0; jj < m_PolyCorners.size(); jj++ )
|
|
|
|
|
{
|
|
|
|
|
RotatePoint( &m_PolyCorners[jj], -angle );
|
|
|
|
|
}
|
2008-04-17 16:25:29 +00:00
|
|
|
|
}
|
2010-09-28 14:42:05 +00:00
|
|
|
|
break;
|
2008-04-17 16:25:29 +00:00
|
|
|
|
|
2010-09-28 14:42:05 +00:00
|
|
|
|
case APT_MACRO:
|
2010-09-28 19:34:16 +00:00
|
|
|
|
|
2010-09-28 14:42:05 +00:00
|
|
|
|
// TODO
|
|
|
|
|
break;
|
|
|
|
|
}
|
2007-06-05 12:10:51 +00:00
|
|
|
|
}
|
2010-09-28 19:34:16 +00:00
|
|
|
|
|
2010-10-01 19:11:30 +00:00
|
|
|
|
|
2010-09-28 19:34:16 +00:00
|
|
|
|
// The helper function for D_CODE::ConvertShapeToPolygon().
|
|
|
|
|
// Add a hole to a polygon
|
|
|
|
|
static void addHoleToPolygon( std::vector<wxPoint>& aBuffer,
|
|
|
|
|
APERTURE_DEF_HOLETYPE aHoleShape,
|
|
|
|
|
wxSize aSize,
|
|
|
|
|
wxPoint aAnchorPos )
|
|
|
|
|
{
|
|
|
|
|
wxPoint currpos;
|
2010-10-01 19:11:30 +00:00
|
|
|
|
|
2010-09-28 19:34:16 +00:00
|
|
|
|
if( aHoleShape == APT_DEF_ROUND_HOLE ) // build a round hole
|
|
|
|
|
{
|
|
|
|
|
for( int ii = 0; ii <= SEGS_CNT; ii++ )
|
|
|
|
|
{
|
|
|
|
|
currpos.x = 0;
|
|
|
|
|
currpos.y = aSize.x / 2; // aSize.x / 2 is the radius of the hole
|
|
|
|
|
RotatePoint( &currpos, ii * 3600 / SEGS_CNT );
|
|
|
|
|
aBuffer.push_back( currpos );
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-01 19:11:30 +00:00
|
|
|
|
aBuffer.push_back( aAnchorPos ); // link to outline
|
2010-09-28 19:34:16 +00:00
|
|
|
|
}
|
2010-10-01 19:11:30 +00:00
|
|
|
|
if( aHoleShape == APT_DEF_RECT_HOLE ) // Create rectangular hole
|
2010-09-28 19:34:16 +00:00
|
|
|
|
{
|
|
|
|
|
currpos.x = aSize.x / 2;
|
|
|
|
|
currpos.y = aSize.y / 2;
|
|
|
|
|
aBuffer.push_back( currpos ); // link to hole and begin hole
|
|
|
|
|
currpos.x -= aSize.x;
|
|
|
|
|
aBuffer.push_back( currpos );
|
|
|
|
|
currpos.y -= aSize.y;
|
|
|
|
|
aBuffer.push_back( currpos );
|
|
|
|
|
currpos.x += aSize.x;
|
|
|
|
|
aBuffer.push_back( currpos );
|
|
|
|
|
currpos.y += aSize.y;
|
2010-10-01 19:11:30 +00:00
|
|
|
|
aBuffer.push_back( currpos ); // close hole
|
|
|
|
|
aBuffer.push_back( aAnchorPos ); // link to outline
|
2010-09-28 19:34:16 +00:00
|
|
|
|
}
|
|
|
|
|
}
|