Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
K
kicad-source-mirror
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
Elphel
kicad-source-mirror
Commits
6418163d
Commit
6418163d
authored
Dec 02, 2011
by
Lorenzo Marcantonio
Committed by
Dick Hollenbeck
Dec 02, 2011
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update to the GENCAD import export
parent
05faa369
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
569 additions
and
425 deletions
+569
-425
class_pad.cpp
pcbnew/class_pad.cpp
+20
-10
export_gencad.cpp
pcbnew/export_gencad.cpp
+549
-415
No files found.
pcbnew/class_pad.cpp
View file @
6418163d
...
...
@@ -854,31 +854,41 @@ int D_PAD::Compare( const D_PAD* padref, const D_PAD* padcmp )
{
int
diff
;
if
(
(
diff
=
padref
->
m_PadShape
-
padcmp
->
m_PadShape
)
)
if
(
diff
=
padref
->
m_PadShape
-
padcmp
->
m_PadShape
)
return
diff
;
if
(
(
diff
=
padref
->
m_Size
.
x
-
padcmp
->
m_Size
.
x
)
)
if
(
diff
=
padref
->
m_DrillShape
-
padcmp
->
m_DrillShape
)
return
diff
;
if
(
(
diff
=
padref
->
m_Size
.
y
-
padcmp
->
m_Size
.
y
)
)
if
(
diff
=
padref
->
m_Drill
.
x
-
padcmp
->
m_Drill
.
x
)
return
diff
;
if
(
(
diff
=
padref
->
m_Offset
.
x
-
padcmp
->
m_Offset
.
x
)
)
if
(
diff
=
padref
->
m_Drill
.
y
-
padcmp
->
m_Drill
.
y
)
return
diff
;
if
(
(
diff
=
padref
->
m_Offset
.
y
-
padcmp
->
m_Offset
.
y
)
)
if
(
diff
=
padref
->
m_Size
.
x
-
padcmp
->
m_Size
.
x
)
return
diff
;
if
(
(
diff
=
padref
->
m_DeltaSize
.
x
-
padcmp
->
m_DeltaSize
.
x
)
)
if
(
diff
=
padref
->
m_Size
.
y
-
padcmp
->
m_Size
.
y
)
return
diff
;
if
(
(
diff
=
padref
->
m_DeltaSize
.
y
-
padcmp
->
m_DeltaSize
.
y
)
)
if
(
diff
=
padref
->
m_Offset
.
x
-
padcmp
->
m_Offset
.
x
)
return
diff
;
if
(
diff
=
padref
->
m_Offset
.
y
-
padcmp
->
m_Offset
.
y
)
return
diff
;
if
(
diff
=
padref
->
m_DeltaSize
.
x
-
padcmp
->
m_DeltaSize
.
x
)
return
diff
;
if
(
diff
=
padref
->
m_DeltaSize
.
y
-
padcmp
->
m_DeltaSize
.
y
)
return
diff
;
// @todo check if export_gencad still works:
// specctra_export needs this, but maybe export_gencad does not. added on
// Jan 24 2008 by Dick.
if
(
(
diff
=
padref
->
m_layerMask
-
padcmp
->
m_layerMask
)
)
// specctra_export needs this, but maybe export_gencad does not.
// Lorenzo: XXX no idea about specctra, but gencad need it to
// implement padstacks!
if
(
diff
=
padref
->
m_layerMask
-
padcmp
->
m_layerMask
)
return
diff
;
return
0
;
...
...
pcbnew/export_gencad.cpp
View file @
6418163d
...
...
@@ -46,55 +46,75 @@
#include "class_edge_mod.h"
bool
CreateHeaderInfoData
(
FILE
*
f
ile
,
PCB_EDIT_FRAME
*
frame
);
static
void
Create
TracksInfoData
(
FILE
*
file
,
BOARD
*
pcb
);
static
void
Create
BoardSection
(
FILE
*
file
,
BOARD
*
p
cb
);
static
void
Create
ComponentsSection
(
FILE
*
file
,
BOARD
*
p
cb
);
static
void
Create
DevicesSection
(
FILE
*
file
,
BOARD
*
p
cb
);
static
void
Create
RoutesSection
(
FILE
*
file
,
BOARD
*
p
cb
);
static
void
Create
SignalsSection
(
FILE
*
file
,
BOARD
*
p
cb
);
static
void
CreateS
hapesSection
(
FILE
*
file
,
BOARD
*
p
cb
);
static
void
Create
PadsShapesSection
(
FILE
*
file
,
BOARD
*
p
cb
);
static
void
CreatePadsS
tacksSection
(
FILE
*
file
,
BOARD
*
p
cb
);
static
bool
CreateHeaderInfoData
(
FILE
*
aF
ile
,
PCB_EDIT_FRAME
*
frame
);
static
void
Create
ArtworksSection
(
FILE
*
aFile
);
static
void
Create
TracksInfoData
(
FILE
*
aFile
,
BOARD
*
aP
cb
);
static
void
Create
BoardSection
(
FILE
*
aFile
,
BOARD
*
aP
cb
);
static
void
Create
ComponentsSection
(
FILE
*
aFile
,
BOARD
*
aP
cb
);
static
void
Create
DevicesSection
(
FILE
*
aFile
,
BOARD
*
aP
cb
);
static
void
Create
RoutesSection
(
FILE
*
aFile
,
BOARD
*
aP
cb
);
static
void
CreateS
ignalsSection
(
FILE
*
aFile
,
BOARD
*
aP
cb
);
static
void
Create
ShapesSection
(
FILE
*
aFile
,
BOARD
*
aP
cb
);
static
void
CreatePadsS
hapesSection
(
FILE
*
aFile
,
BOARD
*
aP
cb
);
static
void
FootprintWriteShape
(
FILE
*
File
,
MODULE
*
module
);
// layer name for Gencad export
static
const
wxString
GenCAD
_Layer_
Name
[
32
]
=
static
const
wxString
GenCAD
Layer
Name
[
32
]
=
{
wxT
(
"BOTTOM"
),
wxT
(
"INNER1"
),
wxT
(
"INNER2"
),
wxT
(
"INNER3"
),
wxT
(
"INNER4"
),
wxT
(
"INNER5"
),
wxT
(
"INNER6"
),
wxT
(
"INNER7"
),
wxT
(
"INNER8"
),
wxT
(
"INNER9"
),
wxT
(
"INNER10"
),
wxT
(
"INNER11"
),
wxT
(
"INNER12"
),
wxT
(
"INNER13"
),
wxT
(
"INNER14"
),
wxT
(
"TOP"
),
wxT
(
"
adhecu"
),
wxT
(
"adhecmp
"
),
wxT
(
"TOP"
),
wxT
(
"
LAYER17"
),
wxT
(
"LAYER18
"
),
wxT
(
"SOLDERPASTE_BOTTOM"
),
wxT
(
"SOLDERPASTE_TOP"
),
wxT
(
"SILKSCREEN_BOTTOM"
),
wxT
(
"SILKSCREEN_TOP"
),
wxT
(
"SOLDERMASK_BOTTOM"
),
wxT
(
"SOLDERMASK_TOP"
),
wxT
(
"
drawings
"
),
wxT
(
"
comments"
),
wxT
(
"eco1"
),
wxT
(
"eco2
"
),
wxT
(
"
edges"
),
wxT
(
"--"
),
wxT
(
"--
"
),
wxT
(
"
--
"
)
wxT
(
"SOLDERMASK_BOTTOM"
),
wxT
(
"SOLDERMASK_TOP"
),
wxT
(
"
LAYER25
"
),
wxT
(
"
LAYER26"
),
wxT
(
"LAYER27"
),
wxT
(
"LAYER28
"
),
wxT
(
"
LAYER29"
),
wxT
(
"LAYER30"
),
wxT
(
"LAYER31
"
),
wxT
(
"
LAYER32
"
)
};
int
offsetX
,
offsetY
;
D_PAD
*
PadList
;
// flipped layer name for Gencad export (to make CAM350 imports correct)
static
const
wxString
GenCADLayerNameFlipped
[
32
]
=
{
wxT
(
"TOP"
),
wxT
(
"INNER14"
),
wxT
(
"INNER13"
),
wxT
(
"INNER12"
),
wxT
(
"INNER11"
),
wxT
(
"INNER10"
),
wxT
(
"INNER9"
),
wxT
(
"INNER8"
),
wxT
(
"INNER7"
),
wxT
(
"INNER6"
),
wxT
(
"INNER5"
),
wxT
(
"INNER4"
),
wxT
(
"INNER3"
),
wxT
(
"INNER2"
),
wxT
(
"INNER1"
),
wxT
(
"BOTTOM"
),
wxT
(
"LAYER17"
),
wxT
(
"LAYER18"
),
wxT
(
"SOLDERPASTE_TOP"
),
wxT
(
"SOLDERPASTE_BOTTOM"
),
wxT
(
"SILKSCREEN_TOP"
),
wxT
(
"SILKSCREEN_BOTTOM"
),
wxT
(
"SOLDERMASK_TOP"
),
wxT
(
"SOLDERMASK_BOTTOM"
),
wxT
(
"LAYER25"
),
wxT
(
"LAYER26"
),
wxT
(
"LAYER27"
),
wxT
(
"LAYER28"
),
wxT
(
"LAYER29"
),
wxT
(
"LAYER30"
),
wxT
(
"LAYER31"
),
wxT
(
"LAYER32"
)
};
// These are the export origin (the auxiliary axis)
static
int
GencadOffsetX
,
GencadOffsetY
;
/* GerbTool chokes on units different than INCH so this is the conversion
factor */
const
static
double
SCALE_FACTOR
=
10000.0
;
/* 2 helper functions to calculate coordinates of modules in gencad values (
* GenCAD Y axis from bottom to top)
/* Two helper functions to calculate coordinates of modules in gencad values
* (GenCAD Y axis from bottom to top)
*/
static
int
mapXto
(
int
x
)
static
double
MapXTo
(
int
aX
)
{
return
x
-
offsetX
;
return
(
aX
-
GencadOffsetX
)
/
SCALE_FACTOR
;
}
static
int
mapYto
(
int
y
)
static
double
MapYTo
(
int
aY
)
{
return
offsetY
-
y
;
return
(
GencadOffsetY
-
aY
)
/
SCALE_FACTOR
;
}
void
PCB_EDIT_FRAME
::
ExportToGenCAD
(
wxCommandEvent
&
e
vent
)
/* Driver function: processing starts here */
void
PCB_EDIT_FRAME
::
ExportToGenCAD
(
wxCommandEvent
&
aE
vent
)
{
wxFileName
fn
=
GetScreen
()
->
GetFileName
();
wxString
msg
,
ext
,
wildcard
;
...
...
@@ -117,11 +137,16 @@ void PCB_EDIT_FRAME::ExportToGenCAD( wxCommandEvent& event )
DisplayError
(
this
,
msg
);
return
;
}
/* Update some board data, to ensure a reliable gencad export: */
SetLocaleTo_C_standard
();
// No pesky decimal separators in gencad
// Update some board data, to ensure a reliable gencad export
GetBoard
()
->
ComputeBoundingBox
();
offsetX
=
m_Auxiliary_Axis_Position
.
x
;
offsetY
=
m_Auxiliary_Axis_Position
.
y
;
// Save the auxiliary origin for the rest of the module
GencadOffsetX
=
m_Auxiliary_Axis_Position
.
x
;
GencadOffsetY
=
m_Auxiliary_Axis_Position
.
y
;
// No idea on *why* this should be needed... maybe to fix net names?
Compile_Ratsnest
(
NULL
,
true
);
/* Temporary modification of footprints that are flipped (i.e. on bottom
...
...
@@ -130,9 +155,10 @@ void PCB_EDIT_FRAME::ExportToGenCAD( wxCommandEvent& event )
* that are given as normal orientation (non flipped, rotation = 0))
* these changes will be undone later
*/
BOARD
*
pcb
=
GetBoard
();
MODULE
*
module
;
for
(
module
=
GetBoard
()
->
m_Modules
;
module
!=
NULL
;
module
=
module
->
Next
()
)
for
(
module
=
pcb
->
m_Modules
;
module
!=
NULL
;
module
=
module
->
Next
()
)
{
module
->
flag
=
0
;
...
...
@@ -143,38 +169,33 @@ void PCB_EDIT_FRAME::ExportToGenCAD( wxCommandEvent& event )
}
}
/
/ Create file header:
CreateHeaderInfoData
(
file
,
this
);
CreateBoardSection
(
file
,
GetBoard
()
);
/
* Gencad has some mandatory and some optional sections: some importer
need the padstack section (which is optional) anyway. Also the
order of the section *is* important */
/* Create TRACKS list
* This is the section $TRACK) (track width sizes) */
CreateTracksInfoData
(
file
,
GetBoard
()
);
CreateHeaderInfoData
(
file
,
this
);
// Gencad header
CreateBoardSection
(
file
,
pcb
);
// Board perimeter
/* Create the shapes list
* (shapes of pads and footprints */
CreatePadsShapesSection
(
file
,
GetBoard
()
);
/* Must be called
* before
* CreatePadsStacksSection
* and
* CreateShapesSection()
*/
CreatePadsStacksSection
(
file
,
GetBoard
()
);
CreateShapesSection
(
file
,
GetBoard
()
);
CreatePadsShapesSection
(
file
,
pcb
);
// Pads and padstacks
CreateArtworksSection
(
file
);
// Empty but mandatory
CreateDevicesSection
(
file
,
GetBoard
()
);
CreateComponentsSection
(
file
,
GetBoard
()
);
/* Gencad splits a component info in shape, component and device.
We don't do any sharing (it would be difficult since each module is
customizable after placement) */
CreateShapesSection
(
file
,
pcb
);
CreateComponentsSection
(
file
,
pcb
);
CreateDevicesSection
(
file
,
pcb
);
/* Create the list of Nets: */
CreateSignalsSection
(
file
,
GetBoard
()
);
// Creates the Routes section (i.e. the list of board tracks)
CreateRoutesSection
(
file
,
GetBoard
()
);
// In a similar way the netlist is split in net, track and route
CreateSignalsSection
(
file
,
pcb
);
CreateTracksInfoData
(
file
,
pcb
);
CreateRoutesSection
(
file
,
pcb
);
fclose
(
file
);
SetLocaleTo_Default
();
// revert to the current locale
/
* Undo the footprints modifications (flipped footprints) */
for
(
module
=
GetBoard
()
->
m_Modules
;
module
!=
NULL
;
module
=
module
->
Next
()
)
/
/ Undo the footprints modifications (flipped footprints)
for
(
module
=
pcb
->
m_Modules
;
module
!=
NULL
;
module
=
module
->
Next
()
)
{
if
(
module
->
flag
)
{
...
...
@@ -184,58 +205,96 @@ void PCB_EDIT_FRAME::ExportToGenCAD( wxCommandEvent& event )
}
}
static
int
Pad
_list_Sort_by_Shapes
(
const
void
*
refptr
,
const
void
*
o
bjptr
)
// Comparator for sorting pads with qsort
static
int
Pad
ListSortByShape
(
const
void
*
aRefptr
,
const
void
*
aO
bjptr
)
{
const
D_PAD
*
padref
=
*
(
D_PAD
**
)
r
efptr
;
const
D_PAD
*
padcmp
=
*
(
D_PAD
**
)
o
bjptr
;
const
D_PAD
*
padref
=
*
(
D_PAD
**
)
aR
efptr
;
const
D_PAD
*
padcmp
=
*
(
D_PAD
**
)
aO
bjptr
;
return
D_PAD
::
Compare
(
padref
,
padcmp
);
}
// Sort vias for uniqueness
static
int
ViaSort
(
const
void
*
aRefptr
,
const
void
*
aObjptr
)
{
TRACK
*
padref
=
*
(
TRACK
**
)
aRefptr
;
TRACK
*
padcmp
=
*
(
TRACK
**
)
aObjptr
;
/* Creates the pads shapes list ( 1 shape per pad )
* Uses .GetSubRatsnest member of class D_PAD, to handle the shape id (value 1
* ..n) for pads shapes PAD1 to PADn
*
* The PADS section is used to describe the shape of all the pads used on the
* printed circuit board. The PADS section must be included, even if only a
* default pad is described and used for all pads.
* The keywords used in the PADS section are:
* $PADS
* PAD <pad_name> <pad_type> <drill_size>
* LINE <line_ref>
* ARC <arc_ref>
* CIRCLE <circle_ref>
* RECTANGLE <rectangle_ref>
* ATTRIBUTE <attrib_ref>
* $ENDPADS
* $PADS and $ENDPADS mark the PADS section of the GenCAD file. Each pad
* description must start with a PAD keyword.
* The layer in which a pad lies is defined in the SHAPE section of the GenCAD
* specification.
* The pad is always placed on a shape at the pad origin, or in a pad stack at
* the pad stack origin.
*/
void
CreatePadsShapesSection
(
FILE
*
file
,
BOARD
*
pcb
)
if
(
padref
->
m_Width
!=
padcmp
->
m_Width
)
return
padref
->
m_Width
-
padcmp
->
m_Width
;
if
(
padref
->
GetDrillValue
()
!=
padcmp
->
GetDrillValue
()
)
return
padref
->
GetDrillValue
()
-
padcmp
->
GetDrillValue
();
if
(
padref
->
ReturnMaskLayer
()
!=
padcmp
->
ReturnMaskLayer
()
)
return
padref
->
ReturnMaskLayer
()
-
padcmp
->
ReturnMaskLayer
();
return
0
;
}
// The ARTWORKS section is empty but (officially) mandatory
static
void
CreateArtworksSection
(
FILE
*
aFile
)
{
/* The artworks section is empty */
fputs
(
"$ARTWORKS
\n
"
,
aFile
);
fputs
(
"$ENDARTWORKS
\n\n
"
,
aFile
);
}
// Emit PADS and PADSTACKS. They are sorted and emitted uniquely.
// Via name is synthesized from their attributes, pads are numbered
static
void
CreatePadsShapesSection
(
FILE
*
aFile
,
BOARD
*
aPcb
)
{
std
::
vector
<
D_PAD
*>
pads
;
std
::
vector
<
D_PAD
*>
padstacks
;
std
::
vector
<
TRACK
*>
vias
;
std
::
vector
<
TRACK
*>
viastacks
;
padstacks
.
resize
(
1
);
// We count pads from 1
const
char
*
pad_type
;
// The master layermask (i.e. the enabled layers) for padstack generation
unsigned
master_layermask
=
aPcb
->
GetBoardDesignSettings
()
->
GetEnabledLayers
();
fputs
(
"$PADS
\n
"
,
f
ile
);
fputs
(
"$PADS
\n
"
,
aF
ile
);
if
(
pcb
->
GetPadsCount
()
>
0
)
// Enumerate and sort the pads
if
(
aPcb
->
GetPadsCount
()
>
0
)
{
pads
.
insert
(
pads
.
end
(),
pcb
->
m_NetInfo
->
m_PadsFullList
.
begin
(),
pcb
->
m_NetInfo
->
m_PadsFullList
.
end
()
);
qsort
(
&
pads
[
0
],
pcb
->
GetPadsCount
(),
sizeof
(
D_PAD
*
),
Pad_list_Sort_by_Shapes
);
aPcb
->
m_NetInfo
->
m_PadsFullList
.
begin
(),
aPcb
->
m_NetInfo
->
m_PadsFullList
.
end
()
);
qsort
(
&
pads
[
0
],
aPcb
->
GetPadsCount
(),
sizeof
(
D_PAD
*
),
PadListSortByShape
);
}
D_PAD
*
old_pad
=
NULL
;
int
pad_name_number
=
0
;
// The same for vias
for
(
TRACK
*
track
=
aPcb
->
m_Track
;
track
!=
NULL
;
track
=
track
->
Next
()
)
{
if
(
track
->
Type
()
==
PCB_VIA_T
)
{
vias
.
push_back
(
track
);
}
}
qsort
(
&
vias
[
0
],
vias
.
size
(),
sizeof
(
TRACK
*
),
ViaSort
);
// Emit vias pads
TRACK
*
old_via
=
0
;
for
(
unsigned
i
=
0
;
i
<
vias
.
size
();
i
++
)
{
TRACK
*
via
=
vias
[
i
];
if
(
old_via
&&
0
==
ViaSort
(
&
old_via
,
&
via
))
continue
;
old_via
=
via
;
viastacks
.
push_back
(
via
);
fprintf
(
aFile
,
"PAD V%d.%d.%X ROUND %g
\n
CIRCLE 0 0 %g
\n
"
,
via
->
m_Width
,
via
->
GetDrillValue
(),
via
->
ReturnMaskLayer
(),
via
->
GetDrillValue
()
/
SCALE_FACTOR
,
via
->
m_Width
/
(
SCALE_FACTOR
*
2
)
);
}
// Emit component pads
D_PAD
*
old_pad
=
0
;
int
pad_name_number
=
0
;
for
(
unsigned
i
=
0
;
i
<
pads
.
size
();
++
i
)
{
D_PAD
*
pad
=
pads
[
i
];
...
...
@@ -250,8 +309,9 @@ void CreatePadsShapesSection( FILE* file, BOARD* pcb )
pad_name_number
++
;
pad
->
SetSubRatsnest
(
pad_name_number
);
fprintf
(
file
,
"PAD PAD
%d"
,
pad
->
GetSubRatsnest
()
);
fprintf
(
aFile
,
"PAD P
%d"
,
pad
->
GetSubRatsnest
()
);
padstacks
.
push_back
(
pad
);
// Will have its own padstack later
int
dx
=
pad
->
m_Size
.
x
/
2
;
int
dy
=
pad
->
m_Size
.
y
/
2
;
...
...
@@ -259,115 +319,169 @@ void CreatePadsShapesSection( FILE* file, BOARD* pcb )
{
default
:
case
PAD_CIRCLE
:
pad_type
=
"ROUND"
;
fprintf
(
file
,
" %s %d
\n
"
,
pad_type
,
pad
->
m_Drill
.
x
);
fprintf
(
file
,
"CIRCLE %d %d %d
\n
"
,
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
,
dx
);
fprintf
(
aFile
,
" ROUND %g
\n
"
,
pad
->
m_Drill
.
x
/
SCALE_FACTOR
);
/* Circle is center, radius */
fprintf
(
aFile
,
"CIRCLE %g %g %g
\n
"
,
pad
->
m_Offset
.
x
/
SCALE_FACTOR
,
-
pad
->
m_Offset
.
y
/
SCALE_FACTOR
,
pad
->
m_Size
.
x
/
(
SCALE_FACTOR
*
2
)
);
break
;
case
PAD_RECT
:
pad_type
=
"RECTANGULAR"
;
fprintf
(
file
,
" %s %d
\n
"
,
pad_type
,
pad
->
m_Drill
.
x
);
fprintf
(
file
,
"RECTANGLE %d %d %d %d
\n
"
,
pad
->
m_Offset
.
x
-
dx
,
-
pad
->
m_Offset
.
y
-
dy
,
pad
->
m_Size
.
x
,
pad
->
m_Size
.
y
);
fprintf
(
aFile
,
" RECTANGULAR %g
\n
"
,
pad
->
m_Drill
.
x
/
SCALE_FACTOR
);
// Rectangle is begin, size *not* begin, end!
fprintf
(
aFile
,
"RECTANGLE %g %g %g %g
\n
"
,
(
-
dx
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
(
-
dy
-
pad
->
m_Offset
.
y
)
/
SCALE_FACTOR
,
dx
/
(
SCALE_FACTOR
/
2
)
,
dy
/
(
SCALE_FACTOR
/
2
)
);
break
;
case
PAD_OVAL
:
/
* Create outline by 2 lines and 2 arcs */
case
PAD_OVAL
:
/
/ Create outline by 2 lines and 2 arcs
{
pad_type
=
"FINGER"
;
fprintf
(
file
,
" %s %d
\n
"
,
pad_type
,
pad
->
m_Drill
.
x
);
// OrCAD Layout call them OVAL or OBLONG - GenCAD call them FINGERs
fprintf
(
aFile
,
" FINGER %g
\n
"
,
pad
->
m_Drill
.
x
/
SCALE_FACTOR
);
int
dr
=
dx
-
dy
;
if
(
dr
>=
0
)
// Horizontal oval
{
int
radius
=
dy
;
fprintf
(
file
,
"LINE %d %d %d %d
\n
"
,
-
dr
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
-
radius
,
dr
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
-
radius
);
fprintf
(
file
,
"ARC %d %d %d %d %d %d
\n
"
,
dr
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
-
radius
,
dr
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
+
radius
,
dr
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
);
fprintf
(
file
,
"LINE %d %d %d %d
\n
"
,
dr
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
+
radius
,
-
dr
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
+
radius
);
fprintf
(
file
,
"ARC %d %d %d %d %d %d
\n
"
,
-
dr
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
+
radius
,
-
dr
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
-
radius
,
-
dr
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
);
fprintf
(
aFile
,
"LINE %g %g %g %g
\n
"
,
(
-
dr
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
(
-
pad
->
m_Offset
.
y
-
radius
)
/
SCALE_FACTOR
,
(
dr
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
(
-
pad
->
m_Offset
.
y
-
radius
)
/
SCALE_FACTOR
);
// GenCAD arcs are (start, end, center)
fprintf
(
aFile
,
"ARC %g %g %g %g %g %g
\n
"
,
(
dr
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
(
-
pad
->
m_Offset
.
y
-
radius
)
/
SCALE_FACTOR
,
(
dr
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
(
-
pad
->
m_Offset
.
y
+
radius
)
/
SCALE_FACTOR
,
(
dr
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
-
pad
->
m_Offset
.
y
/
SCALE_FACTOR
);
fprintf
(
aFile
,
"LINE %g %g %g %g
\n
"
,
(
dr
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
(
-
pad
->
m_Offset
.
y
+
radius
)
/
SCALE_FACTOR
,
(
-
dr
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
(
-
pad
->
m_Offset
.
y
+
radius
)
/
SCALE_FACTOR
);
fprintf
(
aFile
,
"ARC %g %g %g %g %g %g
\n
"
,
(
-
dr
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
(
-
pad
->
m_Offset
.
y
+
radius
)
/
SCALE_FACTOR
,
(
-
dr
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
(
-
pad
->
m_Offset
.
y
-
radius
)
/
SCALE_FACTOR
,
(
-
dr
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
-
pad
->
m_Offset
.
y
/
SCALE_FACTOR
);
}
else
// Vertical oval
{
dr
=
-
dr
;
int
radius
=
dx
;
fprintf
(
file
,
"LINE %d %d %d %d
\n
"
,
-
radius
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
-
dr
,
-
radius
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
+
dr
);
fprintf
(
file
,
"ARC %d %d %d %d %d %d
\n
"
,
-
radius
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
+
dr
,
radius
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
+
dr
,
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
+
dr
);
fprintf
(
file
,
"LINE %d %d %d %d
\n
"
,
radius
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
+
dr
,
radius
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
-
dr
);
fprintf
(
file
,
"ARC %d %d %d %d %d %d
\n
"
,
radius
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
-
dr
,
-
radius
+
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
-
dr
,
pad
->
m_Offset
.
x
,
-
pad
->
m_Offset
.
y
-
dr
);
fprintf
(
aFile
,
"LINE %g %g %g %g
\n
"
,
(
-
radius
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
(
-
pad
->
m_Offset
.
y
-
dr
)
/
SCALE_FACTOR
,
(
-
radius
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
(
-
pad
->
m_Offset
.
y
+
dr
)
/
SCALE_FACTOR
);
fprintf
(
aFile
,
"ARC %g %g %g %g %g %g
\n
"
,
(
-
radius
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
(
-
pad
->
m_Offset
.
y
+
dr
)
/
SCALE_FACTOR
,
(
radius
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
(
-
pad
->
m_Offset
.
y
+
dr
)
/
SCALE_FACTOR
,
pad
->
m_Offset
.
x
/
SCALE_FACTOR
,
(
-
pad
->
m_Offset
.
y
+
dr
)
/
SCALE_FACTOR
);
fprintf
(
aFile
,
"LINE %g %g %g %g
\n
"
,
(
radius
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
(
-
pad
->
m_Offset
.
y
+
dr
)
/
SCALE_FACTOR
,
(
radius
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
(
-
pad
->
m_Offset
.
y
-
dr
)
/
SCALE_FACTOR
);
fprintf
(
aFile
,
"ARC %g %g %g %g %g %g
\n
"
,
(
radius
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
(
-
pad
->
m_Offset
.
y
-
dr
)
/
SCALE_FACTOR
,
(
-
radius
+
pad
->
m_Offset
.
x
)
/
SCALE_FACTOR
,
(
-
pad
->
m_Offset
.
y
-
dr
)
/
SCALE_FACTOR
,
pad
->
m_Offset
.
x
/
SCALE_FACTOR
,
(
-
pad
->
m_Offset
.
y
-
dr
)
/
SCALE_FACTOR
);
}
break
;
}
case
PAD_TRAPEZOID
:
pad_type
=
"POLYGON"
;
fprintf
(
aFile
,
" POLYGON %g
\n
"
,
pad
->
m_Drill
.
x
/
SCALE_FACTOR
);
// XXX TO BE IMPLEMENTED! and I don't know if it could be actually imported by something
break
;
}
}
fputs
(
"
\n
$ENDPADS
\n\n
"
,
aFile
);
fputs
(
"$ENDPADS
\n\n
"
,
file
);
}
// Now emit the padstacks definitions, using the combined layer masks
fputs
(
"$PADSTACKS
\n
"
,
aFile
);
/*The PADSTACKS section is optional, and is used to describe how a group of
* pads are
* arranged. The keywords used in the PADSTACKS section are:
* $PADSTACKS
* PADSTACK <pad_name> <drill_size>
* PAD <pad_name> <layer> <rot> <mirror>
* ATTRIBUTE <attrib_ref>
* $ENDPADSTACKS
* $PADSTACKS and $ENDPADSTACKS mark the PADSTACKS section of the GenCAD file.
*/
void
CreatePadsStacksSection
(
FILE
*
file
,
BOARD
*
pcb
)
// Via padstacks
for
(
unsigned
i
=
0
;
i
<
viastacks
.
size
();
i
++
)
{
TRACK
*
via
=
viastacks
[
i
];
unsigned
mask
=
via
->
ReturnMaskLayer
()
&
master_layermask
;
fprintf
(
aFile
,
"PADSTACK VIA%d.%d.%X %g
\n
"
,
via
->
m_Width
,
via
->
GetDrillValue
(),
mask
,
via
->
GetDrillValue
()
/
SCALE_FACTOR
);
for
(
int
layer
=
0
;
layer
<
32
;
layer
++
)
{
if
(
mask
&
(
1
<<
layer
)
)
{
fprintf
(
aFile
,
"PAD V%d.%d.%X %s 0 0
\n
"
,
via
->
m_Width
,
via
->
GetDrillValue
(),
mask
,
TO_UTF8
(
GenCADLayerName
[
layer
])
);
}
}
}
/* Component padstacks
CAM350 don't apply correctly the FLIP semantics for padstacks, i.e. doesn't
swap the top and bottom layers... so I need to define the shape as MIRRORX
and define a separate 'flipped' padstack... until it appears yet another
noncompliant importer */
for
(
unsigned
i
=
1
;
i
<
padstacks
.
size
();
i
++
)
{
D_PAD
*
pad
=
padstacks
[
i
];
// Straight padstack
fprintf
(
aFile
,
"PADSTACK PAD%d %g
\n
"
,
i
,
pad
->
m_Drill
.
x
/
SCALE_FACTOR
);
for
(
int
layer
=
0
;
layer
<
32
;
layer
++
)
{
if
(
pad
->
m_layerMask
&
(
1
<<
layer
)
&
master_layermask
)
{
fprintf
(
aFile
,
"PAD P%d %s 0 0
\n
"
,
i
,
TO_UTF8
(
GenCADLayerName
[
layer
]
)
);
}
}
// Flipped padstack
fprintf
(
aFile
,
"PADSTACK PAD%dF %g
\n
"
,
i
,
pad
->
m_Drill
.
x
/
SCALE_FACTOR
);
for
(
int
layer
=
0
;
layer
<
32
;
layer
++
)
{
if
(
pad
->
m_layerMask
&
(
1
<<
layer
)
&
master_layermask
)
{
fputs
(
"$PADSTACKS
\n
"
,
file
);
fputs
(
"$ENDPADSTACKS
\n\n
"
,
file
);
fprintf
(
aFile
,
"PAD P%d %s 0 0
\n
"
,
i
,
TO_UTF8
(
GenCADLayerNameFlipped
[
layer
]
)
);
}
}
}
fputs
(
"$ENDPADSTACKS
\n\n
"
,
aFile
);
}
/* Creates the footprint shape list.
* We must use one shape for identical footprint (i.e. come from the same
* footprint in lib)
* But because pads shapes and positions can be easily modified on board,
* a shape is created by footprint found.
* (todo : compare footprints shapes and creates only one shape for all
* footprints found having the same shape)
* The shape is always given in orientation 0, position 0 not flipped
*
* Syntax:
* $SHAPES
* SHAPE <shape_name>
* INSERT <string> here <string> = "TH"
* shape_descr (line, arc ..)
* PIN <pin_name> <pad_name> <x_y_ref> <layer> <rot> <mirror>
*
* SHAPE <shape_name>
* ..
* $ENDSHAPES
* Since module shape is customizable after the placement we cannot share them;
* instead we opt for the one-module-one-shape-one-component-one-device approach
*/
void
CreateShapesSection
(
FILE
*
file
,
BOARD
*
p
cb
)
static
void
CreateShapesSection
(
FILE
*
aFile
,
BOARD
*
aP
cb
)
{
MODULE
*
module
;
D_PAD
*
pad
;
...
...
@@ -376,80 +490,73 @@ void CreateShapesSection( FILE* file, BOARD* pcb )
wxString
pinname
;
const
char
*
mirror
=
"0"
;
fputs
(
"$SHAPES
\n
"
,
f
ile
);
fputs
(
"$SHAPES
\n
"
,
aF
ile
);
for
(
module
=
p
cb
->
m_Modules
;
module
!=
NULL
;
module
=
module
->
Next
()
)
for
(
module
=
aP
cb
->
m_Modules
;
module
!=
NULL
;
module
=
module
->
Next
()
)
{
FootprintWriteShape
(
f
ile
,
module
);
FootprintWriteShape
(
aF
ile
,
module
);
for
(
pad
=
module
->
m_Pads
;
pad
!=
NULL
;
pad
=
pad
->
Next
()
)
{
/* Funny thing: GenCAD requires the pad side even if you use
padstacks (which are theorically optional but gerbtools
*requires* them). Now the trouble thing is that 'BOTTOM'
is interpreted by someone as a padstack flip even
if the spec explicitly says it's not... */
layer
=
"ALL"
;
if
(
(
pad
->
m_layerMask
&
ALL_CU_LAYERS
)
==
LAYER_BACK
)
{
if
(
module
->
GetLayer
()
==
LAYER_N_FRONT
)
layer
=
"BOTTOM"
;
else
layer
=
"TOP"
;
layer
=
(
module
->
flag
)
?
"TOP"
:
"BOTTOM"
;
}
else
if
(
(
pad
->
m_layerMask
&
ALL_CU_LAYERS
)
==
LAYER_FRONT
)
{
if
(
module
->
GetLayer
()
==
LAYER_N_FRONT
)
layer
=
"TOP"
;
else
layer
=
"BOTTOM"
;
layer
=
(
module
->
flag
)
?
"BOTTOM"
:
"TOP"
;
}
pad
->
ReturnStringPadName
(
pinname
);
if
(
pinname
.
IsEmpty
()
)
pinname
=
wxT
(
"non
am
e"
);
pinname
=
wxT
(
"none"
);
orient
=
pad
->
m_Orient
-
module
->
m_Orient
;
NORMALIZE_ANGLE_POS
(
orient
);
fprintf
(
file
,
"PIN %s PAD%d %d %d %s %d %s"
,
TO_UTF8
(
pinname
),
pad
->
GetSubRatsnest
(),
pad
->
m_Pos0
.
x
,
-
pad
->
m_Pos0
.
y
,
layer
,
orient
/
10
,
mirror
);
if
(
orient
%
10
)
fprintf
(
file
,
" .%d"
,
orient
%
10
);
fprintf
(
file
,
"
\n
"
);
// Bottom side modules use the flipped padstack
fprintf
(
aFile
,
(
module
->
flag
)
?
"PIN %s PAD%dF %g %g %s %g %s
\n
"
:
"PIN %s PAD%d %g %g %s %g %s
\n
"
,
TO_UTF8
(
pinname
),
pad
->
GetSubRatsnest
(),
pad
->
m_Pos0
.
x
/
SCALE_FACTOR
,
-
pad
->
m_Pos0
.
y
/
SCALE_FACTOR
,
layer
,
orient
/
10.0
,
mirror
);
}
}
fputs
(
"$ENDSHAPES
\n\n
"
,
f
ile
);
fputs
(
"$ENDSHAPES
\n\n
"
,
aF
ile
);
}
/* Creates the section $COMPONENTS (Footprints placement)
* When a footprint is on bottom side of the board::
* shapes are given with option "FLIP" and "MIRRORX".
* - But shapes remain given like component not mirrored and not flipped
* - orientation is given like if where not mirrored and not flipped.
* Bottom side components are difficult to handle: shapes must be mirrored or
* flipped, silk layers need to be handled correctly and so on. Also it seems
* that *noone* follows the specs...
*/
void
CreateComponentsSection
(
FILE
*
file
,
BOARD
*
p
cb
)
static
void
CreateComponentsSection
(
FILE
*
aFile
,
BOARD
*
aP
cb
)
{
MODULE
*
module
=
pcb
->
m_Modules
;
TEXTE_MODULE
*
PtTexte
;
const
char
*
mirror
;
const
char
*
flip
;
int
ii
;
fputs
(
"$COMPONENTS
\n
"
,
f
ile
);
fputs
(
"$COMPONENTS
\n
"
,
aF
ile
);
for
(
;
module
!=
NULL
;
module
=
module
->
Next
()
)
for
(
MODULE
*
module
=
aPcb
->
m_Modules
;
module
!=
NULL
;
module
=
module
->
Next
()
)
{
TEXTE_MODULE
*
textmod
;
const
char
*
mirror
;
const
char
*
flip
;
int
orient
=
module
->
m_Orient
;
if
(
module
->
flag
)
{
mirror
=
"MIRRORX"
;
// Mirrored relative to X axis
flip
=
"FLIP"
;
// Normal shape description ( gencad
// viewer must show it flipped and
// mirrored)
mirror
=
"0"
;
flip
=
"FLIP"
;
NEGATE_AND_NORMALIZE_ANGLE_POS
(
orient
);
}
else
...
...
@@ -458,61 +565,61 @@ void CreateComponentsSection( FILE* file, BOARD* pcb )
flip
=
"0"
;
}
fprintf
(
file
,
"COMPONENT %s
\n
"
,
TO_UTF8
(
module
->
m_Reference
->
m_Text
)
);
fprintf
(
file
,
"DEVICE %s
\n
"
,
TO_UTF8
(
module
->
m_Reference
->
m_Text
)
);
fprintf
(
file
,
"PLACE %d %d
\n
"
,
mapXto
(
module
->
m_Pos
.
x
),
mapYto
(
module
->
m_Pos
.
y
)
);
fprintf
(
file
,
"LAYER %s
\n
"
,
(
module
->
flag
)
?
"BOTTOM"
:
"TOP"
);
fprintf
(
file
,
"ROTATION %d"
,
orient
/
10
);
if
(
orient
%
10
)
fprintf
(
file
,
".%d"
,
orient
%
10
);
fputs
(
"
\n
"
,
file
);
fprintf
(
file
,
"SHAPE %s %s %s
\n
"
,
TO_UTF8
(
module
->
m_Reference
->
m_Text
),
mirror
,
flip
);
/* creates texts (ref and value) */
PtTexte
=
module
->
m_Reference
;
for
(
ii
=
0
;
ii
<
2
;
ii
++
)
fprintf
(
aFile
,
"
\n
COMPONENT %s
\n
"
,
TO_UTF8
(
module
->
m_Reference
->
m_Text
)
);
fprintf
(
aFile
,
"DEVICE %s_%s
\n
"
,
TO_UTF8
(
module
->
m_Reference
->
m_Text
),
TO_UTF8
(
module
->
m_Value
->
m_Text
)
);
fprintf
(
aFile
,
"PLACE %g %g
\n
"
,
MapXTo
(
module
->
m_Pos
.
x
),
MapYTo
(
module
->
m_Pos
.
y
)
);
fprintf
(
aFile
,
"LAYER %s
\n
"
,
(
module
->
flag
)
?
"BOTTOM"
:
"TOP"
);
fprintf
(
aFile
,
"ROTATION %g
\n
"
,
orient
/
10.0
);
fprintf
(
aFile
,
"SHAPE %s %s %s
\n
"
,
TO_UTF8
(
module
->
m_Reference
->
m_Text
),
mirror
,
flip
);
// Text on silk layer: RefDes and value (are they actually useful?)
textmod
=
module
->
m_Reference
;
for
(
int
ii
=
0
;
ii
<
2
;
ii
++
)
{
int
orient
=
PtTexte
->
m_Orient
;
wxString
layer
=
GenCAD_Layer_Name
[
SILKSCREEN_N_FRONT
];
fprintf
(
file
,
"TEXT %d %d %d %d.%d %s %s
\"
%s
\"
"
,
PtTexte
->
m_Pos0
.
x
,
-
PtTexte
->
m_Pos0
.
y
,
PtTexte
->
m_Size
.
x
,
orient
/
10
,
orient
%
10
,
int
orient
=
textmod
->
m_Orient
;
wxString
layer
=
GenCADLayerName
[(
module
->
flag
)
?
SILKSCREEN_N_BACK
:
SILKSCREEN_N_FRONT
];
fprintf
(
aFile
,
"TEXT %g %g %g %g %s %s
\"
%s
\"
"
,
textmod
->
m_Pos0
.
x
/
SCALE_FACTOR
,
-
textmod
->
m_Pos0
.
y
/
SCALE_FACTOR
,
textmod
->
m_Size
.
x
/
SCALE_FACTOR
,
orient
/
10.0
,
mirror
,
TO_UTF8
(
layer
),
TO_UTF8
(
PtTexte
->
m_Text
)
);
TO_UTF8
(
textmod
->
m_Text
)
);
fprintf
(
file
,
" 0 0 %d %d
\n
"
,
(
int
)
(
PtTexte
->
m_Size
.
x
*
PtTexte
->
m_Text
.
Len
()
),
(
int
)
PtTexte
->
m_Size
.
y
);
// Please note, the width is approx
fprintf
(
aFile
,
" 0 0 %g %g
\n
"
,
(
textmod
->
m_Size
.
x
*
textmod
->
m_Text
.
Len
())
/
SCALE_FACTOR
,
textmod
->
m_Size
.
y
/
SCALE_FACTOR
);
PtTexte
=
module
->
m_Value
;
textmod
=
module
->
m_Value
;
// Dirty trick for the second iteration
}
//
put a comment:
fprintf
(
file
,
"SHEET Part %s %s
\n
"
,
//
The SHEET is a 'generic description' for referencing the component
fprintf
(
aFile
,
"SHEET
\"
RefDes: %s, Value: %s
\"
\n
"
,
TO_UTF8
(
module
->
m_Reference
->
m_Text
),
TO_UTF8
(
module
->
m_Value
->
m_Text
)
);
}
fputs
(
"$ENDCOMPONENTS
\n\n
"
,
f
ile
);
fputs
(
"$ENDCOMPONENTS
\n\n
"
,
aF
ile
);
}
/* Creates the list of Nets:
* $SIGNALS
* SIGNAL <net name>
* NODE <component name> <pin name>
* ...
* NODE <component name> <pin name>
* $ENDSIGNALS
*/
void
CreateSignalsSection
(
FILE
*
file
,
BOARD
*
pcb
)
/* Emit the netlist (which is actually the thing for which GenCAD is used these
* days!); tracks are handled later */
static
void
CreateSignalsSection
(
FILE
*
aFile
,
BOARD
*
aPcb
)
{
wxString
msg
;
NETINFO_ITEM
*
net
;
...
...
@@ -520,11 +627,11 @@ void CreateSignalsSection( FILE* file, BOARD* pcb )
MODULE
*
module
;
int
NbNoConn
=
1
;
fputs
(
"$SIGNALS
\n
"
,
f
ile
);
fputs
(
"$SIGNALS
\n
"
,
aF
ile
);
for
(
unsigned
ii
=
0
;
ii
<
p
cb
->
m_NetInfo
->
GetCount
();
ii
++
)
for
(
unsigned
ii
=
0
;
ii
<
aP
cb
->
m_NetInfo
->
GetCount
();
ii
++
)
{
net
=
p
cb
->
m_NetInfo
->
GetNetItem
(
ii
);
net
=
aP
cb
->
m_NetInfo
->
GetNetItem
(
ii
);
if
(
net
->
GetNetname
()
==
wxEmptyString
)
// dummy netlist (no connection)
{
...
...
@@ -537,10 +644,10 @@ void CreateSignalsSection( FILE* file, BOARD* pcb )
msg
=
wxT
(
"SIGNAL "
)
+
net
->
GetNetname
();
fputs
(
TO_UTF8
(
msg
),
f
ile
);
fputs
(
"
\n
"
,
f
ile
);
fputs
(
TO_UTF8
(
msg
),
aF
ile
);
fputs
(
"
\n
"
,
aF
ile
);
for
(
module
=
p
cb
->
m_Modules
;
module
!=
NULL
;
module
=
module
->
Next
()
)
for
(
module
=
aP
cb
->
m_Modules
;
module
!=
NULL
;
module
=
module
->
Next
()
)
{
for
(
pad
=
module
->
m_Pads
;
pad
!=
NULL
;
pad
=
pad
->
Next
()
)
{
...
...
@@ -550,53 +657,56 @@ void CreateSignalsSection( FILE* file, BOARD* pcb )
continue
;
pad
->
ReturnStringPadName
(
padname
);
msg
.
Printf
(
wxT
(
"NODE %s %
.4
s"
),
msg
.
Printf
(
wxT
(
"NODE %s %s"
),
GetChars
(
module
->
m_Reference
->
m_Text
),
GetChars
(
padname
)
);
fputs
(
TO_UTF8
(
msg
),
f
ile
);
fputs
(
"
\n
"
,
f
ile
);
fputs
(
TO_UTF8
(
msg
),
aF
ile
);
fputs
(
"
\n
"
,
aF
ile
);
}
}
}
fputs
(
"$ENDSIGNALS
\n\n
"
,
f
ile
);
fputs
(
"$ENDSIGNALS
\n\n
"
,
aF
ile
);
}
/* Creates the
section $HEADER ... $ENDHEADER
*/
bool
CreateHeaderInfoData
(
FILE
*
file
,
PCB_EDIT_FRAME
*
f
rame
)
/* Creates the
header section; some of the data come from the frame
*
(actually the screen), not from the pcb *
/
static
bool
CreateHeaderInfoData
(
FILE
*
aFile
,
PCB_EDIT_FRAME
*
aF
rame
)
{
wxString
msg
;
PCB_SCREEN
*
screen
=
(
PCB_SCREEN
*
)
(
frame
->
GetScreen
()
);
fputs
(
"$HEADER
\n
"
,
file
);
fputs
(
"GENCAD 1.4
\n
"
,
file
);
msg
=
wxT
(
"USER "
)
+
wxGetApp
().
GetAppName
()
+
wxT
(
" "
)
+
GetBuildVersion
();
fputs
(
TO_UTF8
(
msg
),
file
);
fputs
(
"
\n
"
,
file
);
msg
=
wxT
(
"DRAWING "
)
+
screen
->
GetFileName
();
fputs
(
TO_UTF8
(
msg
),
file
);
fputs
(
"
\n
"
,
file
);
msg
=
wxT
(
"REVISION "
)
+
screen
->
m_Revision
+
wxT
(
" "
)
+
screen
->
m_Date
;
fputs
(
TO_UTF8
(
msg
),
file
);
fputs
(
"
\n
"
,
file
);
msg
.
Printf
(
wxT
(
"UNITS USER %d"
),
PCB_INTERNAL_UNIT
);
fputs
(
TO_UTF8
(
msg
),
file
);
fputs
(
"
\n
"
,
file
);
msg
.
Printf
(
wxT
(
"ORIGIN %d %d"
),
mapXto
(
frame
->
m_Auxiliary_Axis_Position
.
x
),
mapYto
(
frame
->
m_Auxiliary_Axis_Position
.
y
)
);
fputs
(
TO_UTF8
(
msg
),
file
);
fputs
(
"
\n
"
,
file
);
fputs
(
"INTERTRACK 0
\n
"
,
file
);
fputs
(
"$ENDHEADER
\n\n
"
,
file
);
PCB_SCREEN
*
screen
=
(
PCB_SCREEN
*
)
(
aFrame
->
GetScreen
()
);
fputs
(
"$HEADER
\n
"
,
aFile
);
fputs
(
"GENCAD 1.4
\n
"
,
aFile
);
// Please note: GenCAD syntax requires quoted strings if they can contain spaces
msg
.
Printf
(
wxT
(
"USER
\"
%s %s
\"\n
"
),
GetChars
(
wxGetApp
().
GetAppName
()
),
GetChars
(
GetBuildVersion
()
)
);
fputs
(
TO_UTF8
(
msg
),
aFile
);
msg
=
wxT
(
"DRAWING
\"
"
)
+
screen
->
GetFileName
()
+
wxT
(
"
\"\n
"
);
fputs
(
TO_UTF8
(
msg
),
aFile
);
msg
=
wxT
(
"REVISION
\"
"
)
+
screen
->
m_Revision
+
wxT
(
" "
)
+
screen
->
m_Date
+
wxT
(
"
\"\n
"
);
fputs
(
TO_UTF8
(
msg
),
aFile
);
fputs
(
"UNITS INCH
\n
"
,
aFile
);
msg
.
Printf
(
wxT
(
"ORIGIN %g %g
\n
"
),
MapXTo
(
aFrame
->
m_Auxiliary_Axis_Position
.
x
),
MapYTo
(
aFrame
->
m_Auxiliary_Axis_Position
.
y
)
);
fputs
(
TO_UTF8
(
msg
),
aFile
);
fputs
(
"INTERTRACK 0
\n
"
,
aFile
);
fputs
(
"$ENDHEADER
\n\n
"
,
aFile
);
return
true
;
}
/*
* Sort function used to sort tracks segments:
* items are sorted by netcode, then by width then by layer
*/
static
int
Track
_list_Sort_by_
Netcode
(
const
void
*
refptr
,
const
void
*
objptr
)
static
int
Track
ListSortBy
Netcode
(
const
void
*
refptr
,
const
void
*
objptr
)
{
const
TRACK
*
ref
,
*
cmp
;
int
diff
;
...
...
@@ -626,20 +736,21 @@ static int Track_list_Sort_by_Netcode( const void* refptr, const void* objptr )
* $ENROUTE
* Track segments must be sorted by nets
*/
void
CreateRoutesSection
(
FILE
*
file
,
BOARD
*
p
cb
)
static
void
CreateRoutesSection
(
FILE
*
aFile
,
BOARD
*
aP
cb
)
{
TRACK
*
track
,
**
tracklist
;
int
vianum
=
1
;
int
old_netcode
,
old_width
,
old_layer
;
int
nbitems
,
ii
;
unsigned
master_layermask
=
aPcb
->
GetBoardDesignSettings
()
->
GetEnabledLayers
();
// Count items
nbitems
=
0
;
for
(
track
=
p
cb
->
m_Track
;
track
!=
NULL
;
track
=
track
->
Next
()
)
for
(
track
=
aP
cb
->
m_Track
;
track
!=
NULL
;
track
=
track
->
Next
()
)
nbitems
++
;
for
(
track
=
p
cb
->
m_Zone
;
track
!=
NULL
;
track
=
track
->
Next
()
)
for
(
track
=
aP
cb
->
m_Zone
;
track
!=
NULL
;
track
=
track
->
Next
()
)
{
if
(
track
->
Type
()
==
PCB_ZONE_T
)
nbitems
++
;
...
...
@@ -649,10 +760,10 @@ void CreateRoutesSection( FILE* file, BOARD* pcb )
nbitems
=
0
;
for
(
track
=
p
cb
->
m_Track
;
track
!=
NULL
;
track
=
track
->
Next
()
)
for
(
track
=
aP
cb
->
m_Track
;
track
!=
NULL
;
track
=
track
->
Next
()
)
tracklist
[
nbitems
++
]
=
track
;
for
(
track
=
p
cb
->
m_Zone
;
track
!=
NULL
;
track
=
track
->
Next
()
)
for
(
track
=
aP
cb
->
m_Zone
;
track
!=
NULL
;
track
=
track
->
Next
()
)
{
if
(
track
->
Type
()
==
PCB_ZONE_T
)
tracklist
[
nbitems
++
]
=
track
;
...
...
@@ -660,9 +771,9 @@ void CreateRoutesSection( FILE* file, BOARD* pcb )
tracklist
[
nbitems
]
=
NULL
;
qsort
(
tracklist
,
nbitems
,
sizeof
(
TRACK
*
),
Track
_list_Sort_by_
Netcode
);
qsort
(
tracklist
,
nbitems
,
sizeof
(
TRACK
*
),
Track
ListSortBy
Netcode
);
fputs
(
"$ROUTES
\n
"
,
f
ile
);
fputs
(
"$ROUTES
\n
"
,
aF
ile
);
old_netcode
=
-
1
;
old_width
=
-
1
;
old_layer
=
-
1
;
...
...
@@ -673,7 +784,7 @@ void CreateRoutesSection( FILE* file, BOARD* pcb )
if
(
old_netcode
!=
track
->
GetNet
()
)
{
old_netcode
=
track
->
GetNet
();
NETINFO_ITEM
*
net
=
p
cb
->
FindNet
(
track
->
GetNet
()
);
NETINFO_ITEM
*
net
=
aP
cb
->
FindNet
(
track
->
GetNet
()
);
wxString
netname
;
if
(
net
&&
(
net
->
GetNetname
()
!=
wxEmptyString
)
)
...
...
@@ -681,13 +792,13 @@ void CreateRoutesSection( FILE* file, BOARD* pcb )
else
netname
=
wxT
(
"_noname_"
);
fprintf
(
f
ile
,
"ROUTE %s
\n
"
,
TO_UTF8
(
netname
)
);
fprintf
(
aF
ile
,
"ROUTE %s
\n
"
,
TO_UTF8
(
netname
)
);
}
if
(
old_width
!=
track
->
m_Width
)
{
old_width
=
track
->
m_Width
;
fprintf
(
f
ile
,
"TRACK TRACK%d
\n
"
,
track
->
m_Width
);
fprintf
(
aF
ile
,
"TRACK TRACK%d
\n
"
,
track
->
m_Width
);
}
if
(
(
track
->
Type
()
==
PCB_TRACE_T
)
||
(
track
->
Type
()
==
PCB_ZONE_T
)
)
...
...
@@ -695,24 +806,25 @@ void CreateRoutesSection( FILE* file, BOARD* pcb )
if
(
old_layer
!=
track
->
GetLayer
()
)
{
old_layer
=
track
->
GetLayer
();
fprintf
(
f
ile
,
"LAYER %s
\n
"
,
TO_UTF8
(
GenCAD
_Layer_
Name
[
track
->
GetLayer
()
&
0x1F
]
)
);
fprintf
(
aF
ile
,
"LAYER %s
\n
"
,
TO_UTF8
(
GenCAD
Layer
Name
[
track
->
GetLayer
()
&
0x1F
]
)
);
}
fprintf
(
file
,
"LINE %d %d %d %d
\n
"
,
mapXto
(
track
->
m_Start
.
x
),
mapYt
o
(
track
->
m_Start
.
y
),
mapXto
(
track
->
m_End
.
x
),
mapYt
o
(
track
->
m_End
.
y
)
);
fprintf
(
aFile
,
"LINE %g %g %g %g
\n
"
,
MapXTo
(
track
->
m_Start
.
x
),
MapYT
o
(
track
->
m_Start
.
y
),
MapXTo
(
track
->
m_End
.
x
),
MapYT
o
(
track
->
m_End
.
y
)
);
}
if
(
track
->
Type
()
==
PCB_VIA_T
)
{
fprintf
(
file
,
"VIA viapad%d %d %d ALL %d via%d
\n
"
,
track
->
m_Width
,
mapXto
(
track
->
m_Start
.
x
),
mapYto
(
track
->
m_Start
.
y
),
track
->
GetDrillValue
(),
vianum
++
);
fprintf
(
aFile
,
"VIA VIA%d.%d.%X %g %g ALL %g via%d
\n
"
,
track
->
m_Width
,
track
->
GetDrillValue
(),
track
->
ReturnMaskLayer
()
&
master_layermask
,
MapXTo
(
track
->
m_Start
.
x
),
MapYTo
(
track
->
m_Start
.
y
),
track
->
GetDrillValue
()
/
SCALE_FACTOR
,
vianum
++
);
}
}
fputs
(
"$ENDROUTES
\n\n
"
,
f
ile
);
fputs
(
"$ENDROUTES
\n\n
"
,
aF
ile
);
delete
tracklist
;
}
...
...
@@ -722,64 +834,54 @@ void CreateRoutesSection( FILE* file, BOARD* pcb )
* This is a list of footprints properties
* ( Shapes are in section $SHAPE )
*/
void
CreateDevicesSection
(
FILE
*
file
,
BOARD
*
p
cb
)
static
void
CreateDevicesSection
(
FILE
*
aFile
,
BOARD
*
aP
cb
)
{
MODULE
*
module
;
D_PAD
*
pad
;
fputs
(
"$DEVICES
\n
"
,
f
ile
);
fputs
(
"$DEVICES
\n
"
,
aF
ile
);
for
(
module
=
pcb
->
m_Modules
;
module
!=
NULL
;
module
=
module
->
Next
()
)
{
fprintf
(
file
,
"DEVICE %s
\n
"
,
TO_UTF8
(
module
->
m_Reference
->
m_Text
)
);
fprintf
(
file
,
"PART %s
\n
"
,
TO_UTF8
(
module
->
m_LibRef
)
);
fprintf
(
file
,
"TYPE %s
\n
"
,
"UNKNOWN"
);
for
(
pad
=
module
->
m_Pads
;
pad
!=
NULL
;
pad
=
pad
->
Next
()
)
for
(
module
=
aPcb
->
m_Modules
;
module
!=
NULL
;
module
=
module
->
Next
()
)
{
fprintf
(
file
,
"PINDESCR %.4s"
,
pad
->
m_Padname
);
if
(
pad
->
GetNetname
()
==
wxEmptyString
)
fputs
(
" NoConn
\n
"
,
file
);
else
fprintf
(
file
,
" %.4s
\n
"
,
pad
->
m_Padname
);
}
fprintf
(
file
,
"ATTRIBUTE %s
\n
"
,
TO_UTF8
(
module
->
m_Value
->
m_Text
)
);
fprintf
(
aFile
,
"DEVICE
\"
%s
\"\n
"
,
TO_UTF8
(
module
->
m_Reference
->
m_Text
)
);
fprintf
(
aFile
,
"PART
\"
%s
\"\n
"
,
TO_UTF8
(
module
->
m_Value
->
m_Text
)
);
fprintf
(
aFile
,
"PACKAGE
\"
%s
\"\n
"
,
TO_UTF8
(
module
->
m_LibRef
)
);
// The TYPE attribute is almost freeform
const
char
*
ty
=
"TH"
;
if
(
module
->
m_Attributs
&
MOD_CMS
)
ty
=
"SMD"
;
if
(
module
->
m_Attributs
&
MOD_VIRTUAL
)
ty
=
"VIRTUAL"
;
fprintf
(
aFile
,
"TYPE %s
\n
"
,
ty
);
}
fputs
(
"$ENDDEVICES
\n\n
"
,
f
ile
);
fputs
(
"$ENDDEVICES
\n\n
"
,
aF
ile
);
}
/* Creates the section $BOARD.
* We output here only the board
boundary box
* We output here only the board
perimeter
*/
void
CreateBoardSection
(
FILE
*
file
,
BOARD
*
p
cb
)
static
void
CreateBoardSection
(
FILE
*
aFile
,
BOARD
*
aP
cb
)
{
fputs
(
"$BOARD
\n
"
,
file
);
fprintf
(
file
,
"LINE %d %d %d %d
\n
"
,
mapXto
(
pcb
->
m_BoundaryBox
.
m_Pos
.
x
),
mapYto
(
pcb
->
m_BoundaryBox
.
m_Pos
.
y
),
mapXto
(
pcb
->
m_BoundaryBox
.
GetRight
()
),
mapYto
(
pcb
->
m_BoundaryBox
.
m_Pos
.
y
)
);
fprintf
(
file
,
"LINE %d %d %d %d
\n
"
,
mapXto
(
pcb
->
m_BoundaryBox
.
GetRight
()
),
mapYto
(
pcb
->
m_BoundaryBox
.
m_Pos
.
y
),
mapXto
(
pcb
->
m_BoundaryBox
.
GetRight
()
),
mapYto
(
pcb
->
m_BoundaryBox
.
GetBottom
()
)
);
fprintf
(
file
,
"LINE %d %d %d %d
\n
"
,
mapXto
(
pcb
->
m_BoundaryBox
.
GetRight
()
),
mapYto
(
pcb
->
m_BoundaryBox
.
GetBottom
()
),
mapXto
(
pcb
->
m_BoundaryBox
.
m_Pos
.
x
),
mapYto
(
pcb
->
m_BoundaryBox
.
GetBottom
()
)
);
fprintf
(
file
,
"LINE %d %d %d %d
\n
"
,
mapXto
(
pcb
->
m_BoundaryBox
.
m_Pos
.
x
),
mapYto
(
pcb
->
m_BoundaryBox
.
GetBottom
()
),
mapXto
(
pcb
->
m_BoundaryBox
.
m_Pos
.
x
),
mapYto
(
pcb
->
m_BoundaryBox
.
m_Pos
.
y
)
);
fputs
(
"$ENDBOARD
\n\n
"
,
file
);
fputs
(
"$BOARD
\n
"
,
aFile
);
// Extract the board edges
for
(
EDA_ITEM
*
drawing
=
aPcb
->
m_Drawings
;
drawing
!=
0
;
drawing
=
drawing
->
Next
()
)
{
if
(
drawing
->
Type
()
==
PCB_LINE_T
)
{
DRAWSEGMENT
*
drawseg
=
dynamic_cast
<
DRAWSEGMENT
*>
(
drawing
);
if
(
drawseg
->
GetLayer
()
==
EDGE_N
)
{
// XXX GenCAD supports arc boundaries but I've seen nothing that reads them
fprintf
(
aFile
,
"LINE %g %g %g %g
\n
"
,
MapXTo
(
drawseg
->
m_Start
.
x
),
MapYTo
(
drawseg
->
m_Start
.
y
),
MapXTo
(
drawseg
->
m_End
.
x
),
MapYTo
(
drawseg
->
m_End
.
y
));
}
}
}
fputs
(
"$ENDBOARD
\n\n
"
,
aFile
);
}
...
...
@@ -793,18 +895,19 @@ void CreateBoardSection( FILE* file, BOARD* pcb )
* Each tool name is build like this: "TRACK" + track width.
* For instance for a width = 120 : name = "TRACK120".
*/
void
CreateTracksInfoData
(
FILE
*
file
,
BOARD
*
p
cb
)
static
void
CreateTracksInfoData
(
FILE
*
aFile
,
BOARD
*
aP
cb
)
{
TRACK
*
track
;
int
last_width
=
-
1
;
/* Find thickness used for traces. */
// Find thickness used for traces
// XXX could use the same sorting approach used for pads
std
::
vector
<
int
>
trackinfo
;
unsigned
ii
;
for
(
track
=
p
cb
->
m_Track
;
track
!=
NULL
;
track
=
track
->
Next
()
)
for
(
track
=
aP
cb
->
m_Track
;
track
!=
NULL
;
track
=
track
->
Next
()
)
{
if
(
last_width
!=
track
->
m_Width
)
// Find a thickness already used.
{
...
...
@@ -821,7 +924,7 @@ void CreateTracksInfoData( FILE* file, BOARD* pcb )
}
}
for
(
track
=
p
cb
->
m_Zone
;
track
!=
NULL
;
track
=
track
->
Next
()
)
for
(
track
=
aP
cb
->
m_Zone
;
track
!=
NULL
;
track
=
track
->
Next
()
)
{
if
(
last_width
!=
track
->
m_Width
)
// Find a thickness already used.
{
...
...
@@ -839,116 +942,147 @@ void CreateTracksInfoData( FILE* file, BOARD* pcb )
}
// Write data
fputs
(
"$TRACKS
\n
"
,
f
ile
);
fputs
(
"$TRACKS
\n
"
,
aF
ile
);
for
(
ii
=
0
;
ii
<
trackinfo
.
size
();
ii
++
)
{
fprintf
(
file
,
"TRACK TRACK%d %d
\n
"
,
trackinfo
[
ii
],
trackinfo
[
ii
]
);
fprintf
(
aFile
,
"TRACK TRACK%d %g
\n
"
,
trackinfo
[
ii
],
trackinfo
[
ii
]
/
SCALE_FACTOR
);
}
fputs
(
"$ENDTRACKS
\n\n
"
,
f
ile
);
fputs
(
"$ENDTRACKS
\n\n
"
,
aF
ile
);
}
/* Creates the shape of a footprint (section SHAPE)
* The shape is always given "normal" (Orient 0, not mirrored)
* Syntax:
* SHAPE <shape_name>
* INSERT <string> here <string> = "TH"
* shape_descr (line, arc ..):
* LINE startX startY endX endY
* ARC startX startY endX endY centreX centreY
* PAD_CIRCLE centreX scentreY radius
* It's almost guaranteed that the silk layer will be imported wrong but
* the shape also contains the pads!
*/
void
FootprintWriteShape
(
FILE
*
f
ile
,
MODULE
*
module
)
static
void
FootprintWriteShape
(
FILE
*
aF
ile
,
MODULE
*
module
)
{
EDGE_MODULE
*
edge
;
EDA_ITEM
*
item
;
int
y_axis_sign
=
-
1
;
// Control Y axis change sign (as normal
// module / mirror axis and conventions)
EDGE_MODULE
*
PtEdge
;
EDA_ITEM
*
PtStruct
;
// Control Y axis change sign for flipped modules
int
Yaxis_sign
=
-
1
;
// Flip for bottom side components
if
(
module
->
flag
)
Yaxis_sign
=
1
;
/* creates header: */
fprintf
(
file
,
"SHAPE %s
\n
"
,
TO_UTF8
(
module
->
m_Reference
->
m_Text
)
);
fprintf
(
file
,
"INSERT %s
\n
"
,
(
module
->
m_Attributs
&
MOD_CMS
)
?
"SMD"
:
"TH"
);
fprintf
(
aFile
,
"
\n
SHAPE %s
\n
"
,
TO_UTF8
(
module
->
m_Reference
->
m_Text
)
);
if
(
module
->
m_Attributs
&
MOD_VIRTUAL
)
{
fprintf
(
aFile
,
"INSERT SMD
\n
"
);
}
else
{
if
(
module
->
m_Attributs
&
MOD_CMS
)
{
fprintf
(
aFile
,
"INSERT SMD
\n
"
);
}
else
{
fprintf
(
aFile
,
"INSERT TH
\n
"
);
}
}
#if 0 /* ATTRIBUTE name and value is unspecified and the original exporter
* got the syntax wrong, so CAM350 rejected the whole shape! */
/* creates Attributes */
if( module->m_Attributs != MOD_DEFAULT )
{
fprintf
(
f
ile
,
"ATTRIBUTE"
);
fprintf(
aF
ile, "ATTRIBUTE" );
if( module->m_Attributs & MOD_CMS )
fprintf
(
f
ile
,
" PAD_SMD"
);
fprintf(
aF
ile, " PAD_SMD" );
if( module->m_Attributs & MOD_VIRTUAL )
fprintf
(
f
ile
,
" VIRTUAL"
);
fprintf(
aF
ile, " VIRTUAL" );
fprintf
(
f
ile
,
"
\n
"
);
fprintf(
aF
ile, "\n" );
}
#endif
/* creates Drawing */
item
=
module
->
m_Drawings
;
for
(
;
item
!=
NULL
;
item
=
item
->
Next
()
)
// Silk outline; wildly interpreted by various importers:
// CAM350 read it right but only closed shapes
// ProntoPlace double-flip it (at least the pads are correct)
// GerberTool usually get it right...
for
(
PtStruct
=
module
->
m_Drawings
;
PtStruct
!=
NULL
;
PtStruct
=
PtStruct
->
Next
()
)
{
switch
(
item
->
Type
()
)
switch
(
PtStruct
->
Type
()
)
{
case
PCB_MODULE_TEXT_T
:
// If we wanted to export text, this is not the correct section
break
;
case
PCB_MODULE_EDGE_T
:
edge
=
(
EDGE_MODULE
*
)
item
;
switch
(
edge
->
m_Shape
)
PtEdge
=
(
EDGE_MODULE
*
)
PtStruct
;
if
(
PtEdge
->
GetLayer
()
==
SILKSCREEN_N_FRONT
||
PtEdge
->
GetLayer
()
==
SILKSCREEN_N_BACK
)
{
switch
(
PtEdge
->
m_Shape
)
{
case
S_SEGMENT
:
fprintf
(
file
,
"LINE %d %d %d %d
\n
"
,
edge
->
m_Start0
.
x
,
y_axis_sign
*
edge
->
m_Start0
.
y
,
edge
->
m_End0
.
x
,
y_axis_sign
*
edge
->
m_End0
.
y
);
fprintf
(
aFile
,
"LINE %g %g %g %g
\n
"
,
(
PtEdge
->
m_Start0
.
x
)
/
SCALE_FACTOR
,
(
Yaxis_sign
*
PtEdge
->
m_Start0
.
y
)
/
SCALE_FACTOR
,
(
PtEdge
->
m_End0
.
x
)
/
SCALE_FACTOR
,
(
Yaxis_sign
*
PtEdge
->
m_End0
.
y
)
/
SCALE_FACTOR
);
break
;
case
S_CIRCLE
:
{
int
radius
=
(
int
)
hypot
(
(
double
)
(
edge
->
m_End0
.
x
-
edge
->
m_Start0
.
x
),
(
double
)
(
edge
->
m_End0
.
y
-
edge
->
m_Start0
.
y
)
);
fprintf
(
file
,
"CIRCLE %d %d %d
\n
"
,
edge
->
m_Start0
.
x
,
y_axis_sign
*
edge
->
m_Start0
.
y
,
radius
);
int
radius
=
(
int
)
hypot
(
(
double
)
(
PtEdge
->
m_End0
.
x
-
PtEdge
->
m_Start0
.
x
),
(
double
)
(
PtEdge
->
m_End0
.
y
-
PtEdge
->
m_Start0
.
y
)
);
fprintf
(
aFile
,
"CIRCLE %g %g %g
\n
"
,
PtEdge
->
m_Start0
.
x
/
SCALE_FACTOR
,
Yaxis_sign
*
PtEdge
->
m_Start0
.
y
/
SCALE_FACTOR
,
radius
/
SCALE_FACTOR
);
break
;
}
case
S_ARC
:
/* print ARC x,y start x,y end x,y center */
{
// Arcs are defined counter clockwise (positive trigonometric)
// from the start point to the end point (0 to 360 degrees)
wxPoint
arcStart
,
arcEnd
;
// edge->m_Start0 is the arc center relative to the shape position
// edge->m_End0 is the arc start point relative to the shape position
arcStart
=
edge
->
m_End0
;
// calculate arcEnd arc end point relative to the shape position, in Pcbnew
// coordinates
arcEnd
=
arcStart
;
RotatePoint
(
&
arcEnd
,
edge
->
m_Start0
,
-
edge
->
m_Angle
);
// due to difference between Pcbnew and gencad, swap arc start and arc end
EXCHG
(
arcEnd
,
arcStart
);
// print arc shape:
fprintf
(
file
,
"ARC %d %d %d %d %d %d
\n
"
,
arcStart
.
x
,
y_axis_sign
*
arcStart
.
y
,
// Start point
arcEnd
.
x
,
y_axis_sign
*
arcEnd
.
y
,
// End point
edge
->
m_Start0
.
x
,
y_axis_sign
*
edge
->
m_Start0
.
y
);
case
S_ARC
:
{
int
arcendx
,
arcendy
;
arcendx
=
PtEdge
->
m_End0
.
x
-
PtEdge
->
m_Start0
.
x
;
arcendy
=
PtEdge
->
m_End0
.
y
-
PtEdge
->
m_Start0
.
y
;
RotatePoint
(
&
arcendx
,
&
arcendy
,
-
PtEdge
->
m_Angle
);
arcendx
+=
PtEdge
->
m_Start0
.
x
;
arcendy
+=
PtEdge
->
m_Start0
.
y
;
if
(
Yaxis_sign
==
-
1
)
{
// Flipping Y flips the arc direction too
fprintf
(
aFile
,
"ARC %g %g %g %g %g %g
\n
"
,
(
arcendx
)
/
SCALE_FACTOR
,
(
Yaxis_sign
*
arcendy
)
/
SCALE_FACTOR
,
(
PtEdge
->
m_End0
.
x
)
/
SCALE_FACTOR
,
(
Yaxis_sign
*
PtEdge
->
m_End0
.
y
)
/
SCALE_FACTOR
,
(
PtEdge
->
m_Start0
.
x
)
/
SCALE_FACTOR
,
(
Yaxis_sign
*
PtEdge
->
m_Start0
.
y
)
/
SCALE_FACTOR
);
}
else
{
fprintf
(
aFile
,
"ARC %g %g %g %g %g %g
\n
"
,
(
PtEdge
->
m_End0
.
x
)
/
SCALE_FACTOR
,
(
Yaxis_sign
*
PtEdge
->
m_End0
.
y
)
/
SCALE_FACTOR
,
(
arcendx
)
/
SCALE_FACTOR
,
(
Yaxis_sign
*
arcendy
)
/
SCALE_FACTOR
,
(
PtEdge
->
m_Start0
.
x
)
/
SCALE_FACTOR
,
(
Yaxis_sign
*
PtEdge
->
m_Start0
.
y
)
/
SCALE_FACTOR
);
}
break
;
}
default
:
DisplayError
(
NULL
,
wxT
(
"Type Edge Module invalid."
)
);
break
;
}
/* end switch PtEdge->m_Shape */
}
}
break
;
default
:
break
;
}
/* End switch Items type */
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment