VRML export rewritten

This commit is contained in:
unknown 2014-06-08 12:35:42 +02:00 committed by jean-pierre charras
parent bd174ebffe
commit 53cd19a69b
9 changed files with 329 additions and 2144 deletions

View File

@ -140,7 +140,6 @@ set( PCBNEW_EXPORTERS
exporters/gen_drill_report_files.cpp
exporters/gen_modules_placefile.cpp
exporters/gendrill_Excellon_writer.cpp
exporters/vrml_board.cpp
)
set( PCBNEW_AUTOROUTER_SRCS

View File

@ -568,7 +568,7 @@ bool Export_IDF3( BOARD* aPcb, const wxString& aFullFileName, bool aUseThou )
ok = false;
}
catch( std::exception& e )
catch( const std::exception& e )
{
wxString msg;
msg << _( "IDF Export Failed:\n" ) << FROM_UTF8( e.what() );

View File

@ -24,6 +24,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/*
* NOTE:
* 1. for improved looks, create a DRILL layer for PTH drills.
@ -42,24 +43,17 @@
*
* 2. How can we suppress fiducials such as those in the corners of the pic-programmer demo?
*
* 3. Export Graphics to Layer objects (see 3d_draw.cpp for clues) to ensure that custom
* tracks/fills/logos are rendered.
* module->TransformGraphicShapesWithClearanceToPolygonSet
*
* For mechanical correctness, we should use the following settings with arcs:
* 1. max. deviation: the number of edges should be determined by the max.
* mechanical deviation and the minimum number of edges shall be 6.
* 2. for very large features we may introduce too many edges in a circle;
* to control this, we should specify a MAX number of edges or a threshold
* radius and a deviation for larger features
*
* For example, many mechanical fits are to within +/-0.05mm, so specifying
* a max. deviation of 0.02mm will yield a hole near the max. material
* condition. Calculating sides for a 10mm radius hole will yield about
* 312 points; such large holes (and arcs) will typically have a specified
* tolerance of +/-0.2mm in which case we can set the MAX edges to 32
* provided none of the important holes requires > 32 edges.
*/
/*
* KNOWN BUGS:
* 1. silk outlines are sometimes mangled; this is somehow due to
* many overlapping segments. This does not happen in 3Dviewer
* so it is worth inspecting that code to see what is different.
*
* These artefacts can be suppressed for exploratory purposes by
* removing the line width parameter from the length calculation in
* export_vrml_line()
*/
#include <fctsys.h>
@ -70,6 +64,9 @@
#include <pgm_base.h>
#include <3d_struct.h>
#include <macros.h>
#include <exception>
#include <fstream>
#include <iomanip>
#include <pcbnew.h>
@ -85,7 +82,13 @@
#include <vector>
#include <cmath>
#include <vrml_board.h>
#include <vrml_layer.h>
// minimum width (mm) of a VRML line
#define MIN_VRML_LINEWIDTH 0.12
// offset for art layers, mm (silk, paste, etc)
#define ART_OFFSET 0.02
/* helper function:
* some characters cannot be used in names,
@ -167,6 +170,9 @@ private:
double layer_z[NB_LAYERS];
VRML_COLOR colors[VRML_COLOR_LAST];
int iMaxSeg; // max. sides to a small circle
double arcMinLen, arcMaxLen; // min and max lengths of an arc chord
public:
VRML_LAYER holes;
@ -179,6 +185,8 @@ public:
VRML_LAYER bot_tin;
double scale; // board internal units to output scaling
double minLineWidth; // minimum width of a VRML line segment
int precision; // precision of output units
double tx; // global translation along X
double ty; // global translation along Y
@ -193,6 +201,8 @@ public:
for( int i = 0; i < NB_LAYERS; ++i )
layer_z[i] = 0;
holes.GetArcParams( iMaxSeg, arcMinLen, arcMaxLen );
// this default only makes sense if the output is in mm
board_thickness = 1.6;
@ -208,6 +218,8 @@ public:
// pad silver
colors[ VRML_COLOR_TIN ] = VRML_COLOR( .749, .756, .761, .749, .756, .761,
0, 0, 0, 0.8, 0, 0.8 );
precision = 5;
}
VRML_COLOR& GetColor( VRML_COLOR_INDEX aIndex )
@ -234,31 +246,51 @@ public:
layer_z[aLayer] = aValue;
}
void SetMaxDev( double dev )
// set the scaling of the VRML world
bool SetScale( double aWorldScale )
{
holes.SetMaxDev( dev );
board.SetMaxDev( dev );
top_copper.SetMaxDev( dev );
bot_copper.SetMaxDev( dev );
top_silk.SetMaxDev( dev );
bot_silk.SetMaxDev( dev );
top_tin.SetMaxDev( dev );
bot_tin.SetMaxDev( dev );
if( aWorldScale < 0.001 || aWorldScale > 10.0 )
throw( std::runtime_error( "WorldScale out of range (valid range is 0.001 to 10.0)" ) );
scale = aWorldScale * MM_PER_IU;
minLineWidth = aWorldScale * MIN_VRML_LINEWIDTH;
// set the precision of the VRML coordinates
if( aWorldScale < 0.01 )
precision = 8;
else if( aWorldScale < 0.1 )
precision = 7;
else if( aWorldScale< 1.0 )
precision = 6;
else if( aWorldScale < 10.0 )
precision = 5;
else
precision = 4;
double smin = arcMinLen * aWorldScale;
double smax = arcMaxLen * aWorldScale;
holes.SetArcParams( iMaxSeg, smin, smax );
board.SetArcParams( iMaxSeg, smin, smax );
top_copper.SetArcParams( iMaxSeg, smin, smax);
bot_copper.SetArcParams( iMaxSeg, smin, smax);
top_silk.SetArcParams( iMaxSeg, smin, smax );
bot_silk.SetArcParams( iMaxSeg, smin, smax );
top_tin.SetArcParams( iMaxSeg, smin, smax );
bot_tin.SetArcParams( iMaxSeg, smin, smax );
return true;
}
};
// static var. for dealing with text
namespace VRMLEXPORT
{
static MODEL_VRML* model_vrml;
bool GetLayer( MODEL_VRML& aModel, LAYER_NUM layer, VRML_LAYER** vlayer );
}
static MODEL_VRML* model_vrml;
// select the VRML layer object to draw on; return true if
// a layer has been selected.
bool VRMLEXPORT::GetLayer( MODEL_VRML& aModel, LAYER_NUM layer, VRML_LAYER** vlayer )
static bool GetLayer( MODEL_VRML& aModel, LAYER_NUM layer, VRML_LAYER** vlayer )
{
switch( layer )
{
@ -286,9 +318,9 @@ bool VRMLEXPORT::GetLayer( MODEL_VRML& aModel, LAYER_NUM layer, VRML_LAYER** vla
}
static void write_triangle_bag( FILE* output_file, VRML_COLOR& color,
static void write_triangle_bag( std::ofstream& output_file, VRML_COLOR& color,
VRML_LAYER* layer, bool plane, bool top,
double top_z, double bottom_z )
double top_z, double bottom_z, int aPrecision )
{
/* A lot of nodes are not required, but blender sometimes chokes
* without them */
@ -328,7 +360,7 @@ static void write_triangle_bag( FILE* output_file, VRML_COLOR& color,
while( marker_found < 4 )
{
if( shape_boiler[lineno] )
fputs( shape_boiler[lineno], output_file );
output_file << shape_boiler[lineno];
else
{
marker_found++;
@ -336,37 +368,34 @@ static void write_triangle_bag( FILE* output_file, VRML_COLOR& color,
switch( marker_found )
{
case 1: // Material marker
fprintf( output_file,
" diffuseColor %g %g %g\n",
color.diffuse_red,
color.diffuse_grn,
color.diffuse_blu );
fprintf( output_file,
" specularColor %g %g %g\n",
color.spec_red,
color.spec_grn,
color.spec_blu );
fprintf( output_file,
" emissiveColor %g %g %g\n",
color.emit_red,
color.emit_grn,
color.emit_blu );
fprintf( output_file,
" ambientIntensity %g\n", color.ambient );
fprintf( output_file,
" transparency %g\n", color.transp );
fprintf( output_file,
" shininess %g\n", color.shiny );
output_file << " diffuseColor " << std::setprecision(3);
output_file << color.diffuse_red << " ";
output_file << color.diffuse_grn << " ";
output_file << color.diffuse_blu << "\n";
output_file << " specularColor ";
output_file << color.spec_red << " ";
output_file << color.spec_grn << " ";
output_file << color.spec_blu << "\n";
output_file << " emissiveColor ";
output_file << color.emit_red << " ";
output_file << color.emit_grn << " ";
output_file << color.emit_blu << "\n";
output_file << " ambientIntensity " << color.ambient << "\n";
output_file << " transparency " << color.transp << "\n";
output_file << " shininess " << color.shiny << "\n";
break;
case 2:
if( plane )
layer->WriteVertices( top_z, output_file );
layer->WriteVertices( top_z, output_file, aPrecision );
else
layer->Write3DVertices( top_z, bottom_z, output_file );
layer->Write3DVertices( top_z, bottom_z, output_file, aPrecision );
fprintf( output_file, "\n" );
output_file << "\n";
break;
case 3:
@ -376,7 +405,7 @@ static void write_triangle_bag( FILE* output_file, VRML_COLOR& color,
else
layer->Write3DIndices( output_file );
fprintf( output_file, "\n" );
output_file << "\n";
break;
default:
@ -389,49 +418,54 @@ static void write_triangle_bag( FILE* output_file, VRML_COLOR& color,
}
static void write_layers( MODEL_VRML& aModel, FILE* output_file, BOARD* aPcb )
static void write_layers( MODEL_VRML& aModel, std::ofstream& output_file, BOARD* aPcb )
{
// VRML_LAYER board;
aModel.board.Tesselate( &aModel.holes );
double brdz = aModel.board_thickness / 2.0 - 40000 * aModel.scale;
double brdz = aModel.board_thickness / 2.0
- ( Millimeter2iu( ART_OFFSET / 2.0 ) ) * aModel.scale;
write_triangle_bag( output_file, aModel.GetColor( VRML_COLOR_PCB ),
&aModel.board, false, false, brdz, -brdz );
&aModel.board, false, false, brdz, -brdz, aModel.precision );
// VRML_LAYER top_copper;
aModel.top_copper.Tesselate( &aModel.holes );
write_triangle_bag( output_file, aModel.GetColor( VRML_COLOR_TRACK ),
&aModel.top_copper, true, true,
aModel.GetLayerZ( LAST_COPPER_LAYER ), 0 );
aModel.GetLayerZ( LAST_COPPER_LAYER ), 0, aModel.precision );
// VRML_LAYER top_tin;
aModel.top_tin.Tesselate( &aModel.holes );
write_triangle_bag( output_file, aModel.GetColor( VRML_COLOR_TIN ),
&aModel.top_tin, true, true,
aModel.GetLayerZ( LAST_COPPER_LAYER ), 0 );
&aModel.top_tin, true, true,
aModel.GetLayerZ( LAST_COPPER_LAYER )
+ Millimeter2iu( ART_OFFSET / 2.0 ) * aModel.scale,
0, aModel.precision );
// VRML_LAYER bot_copper;
aModel.bot_copper.Tesselate( &aModel.holes );
write_triangle_bag( output_file, aModel.GetColor( VRML_COLOR_TRACK ),
&aModel.bot_copper, true, false,
aModel.GetLayerZ( FIRST_COPPER_LAYER ), 0 );
aModel.GetLayerZ( FIRST_COPPER_LAYER ), 0, aModel.precision );
// VRML_LAYER bot_tin;
aModel.bot_tin.Tesselate( &aModel.holes );
write_triangle_bag( output_file, aModel.GetColor( VRML_COLOR_TIN ),
&aModel.bot_tin, true, false,
aModel.GetLayerZ( FIRST_COPPER_LAYER ), 0 );
aModel.GetLayerZ( FIRST_COPPER_LAYER )
- Millimeter2iu( ART_OFFSET / 2.0 ) * aModel.scale,
0, aModel.precision );
// VRML_LAYER top_silk;
aModel.top_silk.Tesselate( &aModel.holes );
write_triangle_bag( output_file, aModel.GetColor( VRML_COLOR_SILK ),
&aModel.top_silk, true, true,
aModel.GetLayerZ( SILKSCREEN_N_FRONT ), 0 );
aModel.GetLayerZ( SILKSCREEN_N_FRONT ), 0, aModel.precision );
// VRML_LAYER bot_silk;
aModel.bot_silk.Tesselate( &aModel.holes );
write_triangle_bag( output_file, aModel.GetColor( VRML_COLOR_SILK ),
&aModel.bot_silk, true, false,
aModel.GetLayerZ( SILKSCREEN_N_BACK ), 0 );
aModel.GetLayerZ( SILKSCREEN_N_BACK ), 0, aModel.precision );
}
@ -454,7 +488,7 @@ static void compute_layer_Zs( MODEL_VRML& aModel, BOARD* pcb )
/* To avoid rounding interference, we apply an epsilon to each
* successive layer */
double epsilon_z = Millimeter2iu( 0.02 ) * aModel.scale;
double epsilon_z = Millimeter2iu( ART_OFFSET ) * aModel.scale;
aModel.SetLayerZ( SOLDERPASTE_N_BACK, -half_thickness - epsilon_z * 4 );
aModel.SetLayerZ( ADHESIVE_N_BACK, -half_thickness - epsilon_z * 3 );
aModel.SetLayerZ( SILKSCREEN_N_BACK, -half_thickness - epsilon_z * 2 );
@ -477,18 +511,22 @@ static void export_vrml_line( MODEL_VRML& aModel, LAYER_NUM layer,
{
VRML_LAYER* vlayer;
if( !VRMLEXPORT::GetLayer( aModel, layer, &vlayer ) )
if( !GetLayer( aModel, layer, &vlayer ) )
return;
if( width < aModel.minLineWidth)
width = aModel.minLineWidth;
starty = -starty;
endy = -endy;
double angle = atan2( endy - starty, endx - startx );
double angle = atan2( endy - starty, endx - startx ) * 180.0 / M_PI;
double length = Distance( startx, starty, endx, endy ) + width;
double cx = ( startx + endx ) / 2.0;
double cy = ( starty + endy ) / 2.0;
vlayer->AddSlot( cx, cy, length, width, angle, 1, false );
if( !vlayer->AddSlot( cx, cy, length, width, angle, false ) )
throw( std::runtime_error( vlayer->GetError() ) );
}
@ -498,9 +536,12 @@ static void export_vrml_circle( MODEL_VRML& aModel, LAYER_NUM layer,
{
VRML_LAYER* vlayer;
if( !VRMLEXPORT::GetLayer( aModel, layer, &vlayer ) )
if( !GetLayer( aModel, layer, &vlayer ) )
return;
if( width < aModel.minLineWidth )
width = aModel.minLineWidth;
starty = -starty;
endy = -endy;
@ -509,11 +550,13 @@ static void export_vrml_circle( MODEL_VRML& aModel, LAYER_NUM layer,
radius = Distance( startx, starty, endx, endy ) + ( width / 2);
hole = radius - width;
vlayer->AddCircle( startx, starty, radius, 1, false );
if( !vlayer->AddCircle( startx, starty, radius, false ) )
throw( std::runtime_error( vlayer->GetError() ) );
if( hole > 0.0001 )
{
vlayer->AddCircle( startx, starty, hole, 1, true );
if( !vlayer->AddCircle( startx, starty, hole, true ) )
throw( std::runtime_error( vlayer->GetError() ) );
}
}
@ -525,16 +568,19 @@ static void export_vrml_arc( MODEL_VRML& aModel, LAYER_NUM layer,
{
VRML_LAYER* vlayer;
if( !VRMLEXPORT::GetLayer( aModel, layer, &vlayer ) )
if( !GetLayer( aModel, layer, &vlayer ) )
return;
if( width < aModel.minLineWidth )
width = aModel.minLineWidth;
centery = -centery;
arc_starty = -arc_starty;
arc_angle *= -M_PI / 180;
if( !vlayer->AddArc( centerx, centery, arc_startx, arc_starty,
width, arc_angle, false ) )
throw( std::runtime_error( vlayer->GetError() ) );
vlayer->AddArc( centerx, centery, arc_startx, arc_starty,
width, arc_angle, 1, false );
}
@ -577,13 +623,13 @@ static void export_vrml_drawsegment( MODEL_VRML& aModel, DRAWSEGMENT* drawseg )
* for coupling the vrml_text_callback with the common parameters */
static void vrml_text_callback( int x0, int y0, int xf, int yf )
{
LAYER_NUM s_text_layer = VRMLEXPORT::model_vrml->s_text_layer;
int s_text_width = VRMLEXPORT::model_vrml->s_text_width;
double scale = VRMLEXPORT::model_vrml->scale;
double tx = VRMLEXPORT::model_vrml->tx;
double ty = VRMLEXPORT::model_vrml->ty;
LAYER_NUM s_text_layer = model_vrml->s_text_layer;
int s_text_width = model_vrml->s_text_width;
double scale = model_vrml->scale;
double tx = model_vrml->tx;
double ty = model_vrml->ty;
export_vrml_line( *VRMLEXPORT::model_vrml, s_text_layer,
export_vrml_line( *model_vrml, s_text_layer,
x0 * scale + tx, y0 * scale + ty,
xf * scale + tx, yf * scale + ty,
s_text_width * scale );
@ -592,8 +638,8 @@ static void vrml_text_callback( int x0, int y0, int xf, int yf )
static void export_vrml_pcbtext( MODEL_VRML& aModel, TEXTE_PCB* text )
{
VRMLEXPORT::model_vrml->s_text_layer = text->GetLayer();
VRMLEXPORT::model_vrml->s_text_width = text->GetThickness();
model_vrml->s_text_layer = text->GetLayer();
model_vrml->s_text_width = text->GetThickness();
wxSize size = text->GetSize();
@ -707,12 +753,12 @@ static void export_vrml_board( MODEL_VRML& aModel, BOARD* pcb )
while( i < nvert )
{
aModel.board.AddVertex( seg, bufferPcbOutlines[i].x * scale + dx,
-(bufferPcbOutlines[i].y * scale + dy) );
if( bufferPcbOutlines[i].end_contour )
break;
aModel.board.AddVertex( seg, bufferPcbOutlines[i].x * scale + dx,
-(bufferPcbOutlines[i].y * scale + dy) );
++i;
}
@ -739,12 +785,12 @@ static void export_vrml_board( MODEL_VRML& aModel, BOARD* pcb )
while( i < nvert )
{
aModel.holes.AddVertex( seg, allLayerHoles[i].x * scale + dx,
-(allLayerHoles[i].y * scale + dy) );
if( allLayerHoles[i].end_contour )
break;
aModel.holes.AddVertex( seg, allLayerHoles[i].x * scale + dx,
-(allLayerHoles[i].y * scale + dy) );
++i;
}
@ -766,31 +812,26 @@ static void export_round_padstack( MODEL_VRML& aModel, BOARD* pcb,
if( top_layer != LAST_COPPER_LAYER || bottom_layer != FIRST_COPPER_LAYER )
thru = false;
if( thru && hole > 0 )
aModel.holes.AddCircle( x, -y, hole, true );
while( 1 )
{
if( layer == FIRST_COPPER_LAYER )
{
aModel.bot_copper.AddCircle( x, -y, r, 1 );
aModel.bot_copper.AddCircle( x, -y, r );
if( hole > 0 && !thru )
aModel.bot_copper.AddCircle( x, -y, hole, true );
if( hole > 0 )
{
if( thru )
aModel.holes.AddCircle( x, -y, hole, 1, true );
else
aModel.bot_copper.AddCircle( x, -y, hole, 1, true );
}
}
else if( layer == LAST_COPPER_LAYER )
{
aModel.top_copper.AddCircle( x, -y, r, 1 );
aModel.top_copper.AddCircle( x, -y, r );
if( hole > 0 && !thru )
aModel.top_copper.AddCircle( x, -y, hole, true );
if( hole > 0 )
{
if( thru )
aModel.holes.AddCircle( x, -y, hole, 1, true );
else
aModel.top_copper.AddCircle( x, -y, hole, 1, true );
}
}
if( layer == bottom_layer )
@ -856,7 +897,7 @@ static void export_vrml_zones( MODEL_VRML& aModel, BOARD* aPcb )
VRML_LAYER* vl;
if( !VRMLEXPORT::GetLayer( aModel, zone->GetLayer(), &vl ) )
if( !GetLayer( aModel, zone->GetLayer(), &vl ) )
continue;
if( !zone->IsFilled() )
@ -881,11 +922,13 @@ static void export_vrml_zones( MODEL_VRML& aModel, BOARD* aPcb )
{
x = poly.GetX(i) * scale + dx;
y = -(poly.GetY(i) * scale + dy);
vl->AddVertex( seg, x, y );
if( poly.IsEndContour(i) )
break;
if( !vl->AddVertex( seg, x, y ) )
throw( std::runtime_error( vl->GetError() ) );
++i;
}
@ -911,8 +954,8 @@ static void export_vrml_text_module( TEXTE_MODULE* module )
if( module->IsMirrored() )
NEGATE( size.x ); // Text is mirrored
VRMLEXPORT::model_vrml->s_text_layer = module->GetLayer();
VRMLEXPORT::model_vrml->s_text_width = module->GetThickness();
model_vrml->s_text_layer = module->GetLayer();
model_vrml->s_text_width = module->GetThickness();
DrawGraphicText( NULL, NULL, module->GetTextPosition(), BLACK,
module->GetText(), module->GetDrawRotation(), size,
@ -952,10 +995,10 @@ static void export_vrml_edge_module( MODEL_VRML& aModel, EDGE_MODULE* aOutline,
{
VRML_LAYER* vl;
if( !VRMLEXPORT::GetLayer( aModel, layer, &vl ) )
if( !GetLayer( aModel, layer, &vl ) )
break;
int nvert = aOutline->GetPolyPoints().size();
int nvert = aOutline->GetPolyPoints().size() - 1;
int i = 0;
if( nvert < 3 ) break;
@ -974,7 +1017,9 @@ static void export_vrml_edge_module( MODEL_VRML& aModel, EDGE_MODULE* aOutline,
x = corner.x * aModel.scale + aModel.tx;
y = - ( corner.y * aModel.scale + aModel.ty );
vl->AddVertex( seg, x, y );
if( !vl->AddVertex( seg, x, y ) )
throw( std::runtime_error( vl->GetError() ) );
++i;
}
@ -988,8 +1033,7 @@ static void export_vrml_edge_module( MODEL_VRML& aModel, EDGE_MODULE* aOutline,
}
static void export_vrml_padshape( MODEL_VRML& aModel, VRML_LAYER* aLayer,
VRML_LAYER* aTinLayer, D_PAD* aPad )
static void export_vrml_padshape( MODEL_VRML& aModel, VRML_LAYER* aTinLayer, D_PAD* aPad )
{
// The (maybe offset) pad position
wxPoint pad_pos = aPad->ShapePos();
@ -1006,15 +1050,18 @@ static void export_vrml_padshape( MODEL_VRML& aModel, VRML_LAYER* aLayer,
switch( aPad->GetShape() )
{
case PAD_CIRCLE:
aLayer->AddCircle( pad_x, -pad_y, pad_w, 1, true );
aTinLayer->AddCircle( pad_x, -pad_y, pad_w, 1, false );
if( !aTinLayer->AddCircle( pad_x, -pad_y, pad_w, false ) )
throw( std::runtime_error( aTinLayer->GetError() ) );
break;
case PAD_OVAL:
aLayer->AddSlot( pad_x, -pad_y, pad_w * 2.0, pad_h * 2.0,
DECIDEG2RAD( aPad->GetOrientation() ), 1, true );
aTinLayer->AddSlot( pad_x, -pad_y, pad_w * 2.0, pad_h * 2.0,
DECIDEG2RAD( aPad->GetOrientation() ), 1, false );
if( !aTinLayer->AddSlot( pad_x, -pad_y, pad_w * 2.0, pad_h * 2.0,
aPad->GetOrientation()/10.0, false ) )
throw( std::runtime_error( aTinLayer->GetError() ) );
break;
case PAD_RECT:
@ -1039,32 +1086,32 @@ static void export_vrml_padshape( MODEL_VRML& aModel, VRML_LAYER* aLayer,
coord[i * 2 + 1] += pad_y;
}
int lines = aLayer->NewContour();
if( lines < 0 )
return;
aLayer->AddVertex( lines, coord[2], -coord[3] );
aLayer->AddVertex( lines, coord[6], -coord[7] );
aLayer->AddVertex( lines, coord[4], -coord[5] );
aLayer->AddVertex( lines, coord[0], -coord[1] );
aLayer->EnsureWinding( lines, true );
int lines;
lines = aTinLayer->NewContour();
if( lines < 0 )
return;
throw( std::runtime_error( aTinLayer->GetError() ) );
aTinLayer->AddVertex( lines, coord[0], -coord[1] );
aTinLayer->AddVertex( lines, coord[4], -coord[5] );
aTinLayer->AddVertex( lines, coord[6], -coord[7] );
aTinLayer->AddVertex( lines, coord[2], -coord[3] );
aTinLayer->EnsureWinding( lines, false );
if( !aTinLayer->AddVertex( lines, coord[0], -coord[1] ) )
throw( std::runtime_error( aTinLayer->GetError() ) );
if( !aTinLayer->AddVertex( lines, coord[4], -coord[5] ) )
throw( std::runtime_error( aTinLayer->GetError() ) );
if( !aTinLayer->AddVertex( lines, coord[6], -coord[7] ) )
throw( std::runtime_error( aTinLayer->GetError() ) );
if( !aTinLayer->AddVertex( lines, coord[2], -coord[3] ) )
throw( std::runtime_error( aTinLayer->GetError() ) );
if( !aTinLayer->EnsureWinding( lines, false ) )
throw( std::runtime_error( aTinLayer->GetError() ) );
}
break;
default:
;
break;
}
}
@ -1084,12 +1131,12 @@ static void export_vrml_pad( MODEL_VRML& aModel, BOARD* pcb, D_PAD* aPad )
{
// Oblong hole (slot)
aModel.holes.AddSlot( hole_x, -hole_y, hole_drill_w * 2.0, hole_drill_h * 2.0,
DECIDEG2RAD( aPad->GetOrientation() ), 1, true );
aPad->GetOrientation()/10.0, true );
}
else
{
// Drill a round hole
aModel.holes.AddCircle( hole_x, -hole_y, hole_drill, 1, true );
aModel.holes.AddCircle( hole_x, -hole_y, hole_drill, true );
}
}
@ -1098,12 +1145,12 @@ static void export_vrml_pad( MODEL_VRML& aModel, BOARD* pcb, D_PAD* aPad )
if( layer_mask & LAYER_BACK )
{
export_vrml_padshape( aModel, &aModel.bot_copper, &aModel.bot_tin, aPad );
export_vrml_padshape( aModel, &aModel.bot_tin, aPad );
}
if( layer_mask & LAYER_FRONT )
{
export_vrml_padshape( aModel, &aModel.top_copper, &aModel.top_tin, aPad );
export_vrml_padshape( aModel, &aModel.top_tin, aPad );
}
}
@ -1150,7 +1197,7 @@ static void compose_quat( double q1[4], double q2[4], double qr[4] )
static void export_vrml_module( MODEL_VRML& aModel, BOARD* aPcb, MODULE* aModule,
FILE* aOutputFile,
std::ofstream& aOutputFile,
double aVRMLModelsToBiu,
bool aExport3DFiles, const wxString& a3D_Subdir )
{
@ -1237,12 +1284,13 @@ static void export_vrml_module( MODEL_VRML& aModel, BOARD* aPcb, MODULE* aModule
compose_quat( q1, q2, q1 );
from_quat( q1, rot );
fprintf( aOutputFile, "Transform {\n" );
aOutputFile << "Transform {\n";
// A null rotation would fail the acos!
if( rot[3] != 0.0 )
{
fprintf( aOutputFile, " rotation %g %g %g %g\n", rot[0], rot[1], rot[2], rot[3] );
aOutputFile << " rotation " << std::setprecision( 3 );
aOutputFile << rot[0] << " " << rot[1] << " " << rot[2] << " " << rot[3] << "\n";
}
// adjust 3D shape local offset position
@ -1258,15 +1306,15 @@ static void export_vrml_module( MODEL_VRML& aModel, BOARD* aPcb, MODULE* aModule
RotatePoint( &offsetx, &offsety, aModule->GetOrientation() );
fprintf( aOutputFile, " translation %g %g %g\n",
(offsetx + aModule->GetPosition().x) * aModel.scale + aModel.tx,
-(offsety + aModule->GetPosition().y) * aModel.scale - aModel.ty,
(offsetz * aModel.scale ) + aModel.GetLayerZ( aModule->GetLayer() ) );
aOutputFile << " translation " << std::setprecision( aModel.precision );
aOutputFile << (( offsetx + aModule->GetPosition().x) * aModel.scale + aModel.tx ) << " ";
aOutputFile << ( -(offsety + aModule->GetPosition().y) * aModel.scale - aModel.ty ) << " ";
aOutputFile << ( (offsetz * aModel.scale ) + aModel.GetLayerZ( aModule->GetLayer() ) ) << "\n";
fprintf( aOutputFile, " scale %g %g %g\n",
vrmlm->m_MatScale.x * aVRMLModelsToBiu,
vrmlm->m_MatScale.y * aVRMLModelsToBiu,
vrmlm->m_MatScale.z * aVRMLModelsToBiu );
aOutputFile << " scale ";
aOutputFile << ( vrmlm->m_MatScale.x * aVRMLModelsToBiu ) << " ";
aOutputFile << ( vrmlm->m_MatScale.y * aVRMLModelsToBiu ) << " ";
aOutputFile << ( vrmlm->m_MatScale.z * aVRMLModelsToBiu ) << "\n";
if( fname.EndsWith( wxT( "x3d" ) ) )
{
@ -1276,18 +1324,25 @@ static void export_vrml_module( MODEL_VRML& aModel, BOARD* aPcb, MODULE* aModule
{
// embed x3d model in vrml format
parser->Load( fname );
fprintf( aOutputFile,
" children [\n %s ]\n", TO_UTF8( parser->VRML_representation() ) );
fprintf( aOutputFile, " }\n" );
delete parser;
try
{
aOutputFile << " children [\n ";
aOutputFile << TO_UTF8( parser->VRML_representation() ) << " ]\n";
aOutputFile << " }\n";
}
catch( const std::exception& e )
{
delete parser;
throw;
}
}
}
else
{
fprintf( aOutputFile,
" children [\n Inline {\n url \"%s\"\n } ]\n",
TO_UTF8( fname ) );
fprintf( aOutputFile, " }\n" );
aOutputFile << " children [\n Inline {\n url \"";
aOutputFile << TO_UTF8( fname ) << "\"\n } ]\n";
aOutputFile << " }\n";
}
}
}
@ -1297,89 +1352,98 @@ bool PCB_EDIT_FRAME::ExportVRML_File( const wxString& aFullFileName,
double aMMtoWRMLunit, bool aExport3DFiles,
const wxString& a3D_Subdir )
{
wxString msg;
FILE* output_file;
BOARD* pcb = GetBoard();
wxString msg;
BOARD* pcb = GetBoard();
bool ok = true;
MODEL_VRML model3d;
VRMLEXPORT::model_vrml = &model3d;
model_vrml = &model3d;
std::ofstream output_file;
output_file = wxFopen( aFullFileName, wxT( "wt" ) );
try
{
output_file.exceptions( std::ofstream::failbit );
output_file.open( TO_UTF8( aFullFileName ), std::ios_base::out );
if( output_file == NULL )
return false;
// Switch the locale to standard C (needed to print floating point numbers like 1.3)
SetLocaleTo_C_standard();
// Switch the locale to standard C (needed to print floating point numbers like 1.3)
SetLocaleTo_C_standard();
// Begin with the usual VRML boilerplate
wxString name = aFullFileName;
// Begin with the usual VRML boilerplate
wxString name = aFullFileName;
name.Replace( wxT( "\\" ), wxT( "/" ) );
ChangeIllegalCharacters( name, false );
name.Replace( wxT( "\\" ), wxT( "/" ) );
ChangeIllegalCharacters( name, false );
fprintf( output_file, "#VRML V2.0 utf8\n"
"WorldInfo {\n"
" title \"%s - Generated by Pcbnew\"\n"
"}\n", TO_UTF8( name ) );
output_file << "#VRML V2.0 utf8\n";
output_file << "WorldInfo {\n";
output_file << " title \"" << TO_UTF8( name ) << " - Generated by Pcbnew\"\n";
output_file << "}\n";
// Global VRML scale to export to a different scale.
model3d.scale = aMMtoWRMLunit / MM_PER_IU;
// Set the VRML world scale factor
model3d.SetScale( aMMtoWRMLunit );
// Set the mechanical deviation limit (in this case 0.02mm)
// XXX - NOTE: the value should be set via the GUI
model3d.SetMaxDev( 20000 * model3d.scale );
output_file << "Transform {\n";
fprintf( output_file, "Transform {\n" );
// compute the offset to center the board on (0, 0, 0)
// XXX - NOTE: we should allow the user a GUI option to specify the offset
EDA_RECT bbbox = pcb->ComputeBoundingBox();
// compute the offset to center the board on (0, 0, 0)
// XXX - NOTE: we should allow the user a GUI option to specify the offset
EDA_RECT bbbox = pcb->ComputeBoundingBox();
model3d.SetOffset( -model3d.scale * bbbox.Centre().x,
-model3d.scale * bbbox.Centre().y );
model3d.SetOffset( -model3d.scale * bbbox.Centre().x, -model3d.scale * bbbox.Centre().y );
output_file << " children [\n";
fprintf( output_file, " children [\n" );
// Preliminary computation: the z value for each layer
compute_layer_Zs( model3d, pcb );
// Preliminary computation: the z value for each layer
compute_layer_Zs( model3d, pcb );
// board edges and cutouts
export_vrml_board( model3d, pcb );
// board edges and cutouts
export_vrml_board( model3d, pcb );
// Drawing and text on the board
export_vrml_drawings( model3d, pcb );
// Drawing and text on the board
export_vrml_drawings( model3d, pcb );
// Export vias and trackage
export_vrml_tracks( model3d, pcb );
// Export vias and trackage
export_vrml_tracks( model3d, pcb );
// Export zone fills
export_vrml_zones( model3d, pcb);
// Export zone fills
export_vrml_zones( model3d, pcb);
/* scaling factor to convert 3D models to board units (decimils)
* Usually we use Wings3D to create thems.
* One can consider the 3D units is 0.1 inch (2.54 mm)
* So the scaling factor from 0.1 inch to board units
* is 2.54 * aMMtoWRMLunit
*/
double wrml_3D_models_scaling_factor = 2.54 * aMMtoWRMLunit;
/* scaling factor to convert 3D models to board units (decimils)
* Usually we use Wings3D to create thems.
* One can consider the 3D units is 0.1 inch (2.54 mm)
* So the scaling factor from 0.1 inch to board units
* is 2.54 * aMMtoWRMLunit
*/
double wrml_3D_models_scaling_factor = 2.54 * aMMtoWRMLunit;
// Export footprints
for( MODULE* module = pcb->m_Modules; module != 0; module = module->Next() )
export_vrml_module( model3d, pcb, module, output_file,
wrml_3D_models_scaling_factor,
aExport3DFiles, a3D_Subdir );
// Export footprints
for( MODULE* module = pcb->m_Modules; module != 0; module = module->Next() )
export_vrml_module( model3d, pcb, module, output_file,
wrml_3D_models_scaling_factor,
aExport3DFiles, a3D_Subdir );
// write out the board and all layers
write_layers( model3d, output_file, pcb );
// write out the board and all layers
write_layers( model3d, output_file, pcb );
// Close the outer 'transform' node
output_file << "]\n}\n";
}
catch( const std::exception& e )
{
wxString msg;
msg << _( "IDF Export Failed:\n" ) << FROM_UTF8( e.what() );
wxMessageBox( msg );
// Close the outer 'transform' node
fputs( "]\n}\n", output_file );
ok = false;
}
// End of work
fclose( output_file );
output_file.exceptions( std::ios_base::goodbit );
output_file.close();
SetLocaleTo_Default(); // revert to the current locale
return true;
return ok;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,379 +0,0 @@
/*
* file: vrml_board.h
*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2013 Cirilo Bernardo
*
* 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
*/
/**
* @file vrml_board.h
*/
/*
* Classes and structures to support the tesselation of a
* PCB for VRML output.
*/
#ifndef VRML_BOARD_H
#define VRML_BOARD_H
#ifdef __WXMAC__
# ifdef __DARWIN__
# include <OpenGL/glu.h>
# else
# include <glu.h>
# endif
#else
# include <GL/glu.h>
#endif
#include <cstdio>
#include <vector>
#include <list>
#include <utility>
#ifndef M_PI2
#define M_PI2 ( M_PI / 2.0 )
#endif
#ifndef M_PI4
#define M_PI4 ( M_PI / 4.0 )
#endif
class GLUtesselator;
struct VERTEX_3D
{
double x;
double y;
int i; // vertex index
int o; // vertex order
};
struct TRIPLET_3D
{
int i1, i2, i3;
TRIPLET_3D( int p1, int p2, int p3 )
{
i1 = p1;
i2 = p2;
i3 = p3;
}
};
class VRML_LAYER
{
private:
bool fix; // when true, no more vertices may be added by the user
int idx; // vertex index (number of contained vertices)
int ord; // vertex order (number of ordered vertices)
std::vector<VERTEX_3D*> vertices; // vertices of all contours
std::vector<std::list<int>*> contours; // lists of vertices for each contour
std::vector< double > areas; // area of the contours (positive if winding is CCW)
std::list<TRIPLET_3D> triplets; // output facet triplet list (triplet of ORDER values)
std::list<std::list<int>*> outline; // indices for outline outputs (index by ORDER values)
std::vector<int> ordmap; // mapping of ORDER to INDEX
std::string error; // error message
double maxdev; // max. deviation from circle when calculating N sides
int hidx; // number of vertices in the holes
int eidx; // index for extra vertices
std::vector<VERTEX_3D*> extra_verts; // extra vertices added for outlines and facets
std::vector<VERTEX_3D*> vlist; // vertex list for the GL command in progress
VRML_LAYER* pholes; // pointer to another layer object used for tesselation;
// this object is normally expected to hold only holes
GLUtesselator* tess; // local instance of the GLU tesselator
GLenum glcmd; // current GL command type ( fan, triangle, tri-strip, loop )
void clearTmp( void ); // clear ephemeral data used by the tesselation routine
// add a triangular facet (triplet) to the output index list
bool addTriplet( VERTEX_3D* p0, VERTEX_3D* p1, VERTEX_3D* p2 );
// retrieve a vertex given its index; the vertex may be contained in the
// vertices vector, extra_verts vector, or foreign VRML_LAYER object
VERTEX_3D* getVertexByIndex( int index, VRML_LAYER* holes );
void processFan( void ); // process a GL_TRIANGLE_FAN list
void processStrip( void ); // process a GL_TRIANGLE_STRIP list
void processTri( void ); // process a GL_TRIANGLES list
void pushVertices( bool holes ); // push the internal vertices
bool pushOutline( VRML_LAYER* holes ); // push the outline vertices
public:
/// set to true when a fault is encountered during tesselation
bool Fault;
VRML_LAYER();
virtual ~VRML_LAYER();
/**
* Function Clear
* erases all data.
*/
void Clear( void );
/**
* Function GetSize
* returns the total number of vertices indexed
*/
int GetSize( void );
/**
* Function SetMaxDev
* sets the maximum deviation from a circle; this parameter is
* used for the automatic calculation of segments within a
* circle or an arc.
*
* @param max is the maximum deviation from a perfect circle or arc;
* minimum value is 0.000002 units
*
* @return bool: true if the value was accepted
*/
bool SetMaxDev( double max );
/**
* Function NewContour
* creates a new list of vertices and returns an index to the list
*
* @return int: index to the list or -1 if the operation failed
*/
int NewContour( void );
/**
* Function AddVertex
* adds a point to the requested contour
*
* @param aContour is an index previously returned by a call to NewContour()
* @param x is the X coordinate of the vertex
* @param y is the Y coordinate of the vertex
*
* @return bool: true if the vertex was added
*/
bool AddVertex( int aContour, double x, double y );
/**
* Function EnsureWinding
* checks the winding of a contour and ensures that it is a hole or
* a solid depending on the value of @param hole
*
* @param aContour is an index to a contour as returned by NewContour()
* @param hole determines if the contour must be a hole
*
* @return bool: true if the operation suceeded
*/
bool EnsureWinding( int aContour, bool hole );
/**
* Function AddCircle
* creates a circular contour and adds it to the internal list
*
* @param x is the X coordinate of the hole center
* @param y is the Y coordinate of the hole center
* @param rad is the radius of the hole
* @param csides is the number of sides (segments) in a circle;
* use a value of 1 to automatically calculate a suitable number.
* @param hole determines if the contour to be created is a cutout
*
* @return bool: true if the new contour was successfully created
*/
bool AddCircle( double x, double y, double rad, int csides, bool hole = false );
/**
* Function AddSlot
* creates and adds a slot feature to the list of contours
*
* @param cx is the X coordinate of the slot
* @param cy is the Y coordinate of the slot
* @param length is the length of the slot along the major axis
* @param width is the width of the slot along the minor axis
* @param angle (radians) is the orientation of the slot
* @param csides is the number of sides to a circle; use 1 to
* take advantage of automatic calculations.
* @param hole determines whether the slot is a hole or a solid
*
* @return bool: true if the slot was successfully created
*/
bool AddSlot( double cx, double cy, double length, double width,
double angle, int csides, bool hole = false );
/**
* Function AddArc
* creates an arc and adds it to the internal list of contours
*
* @param cx is the X coordinate of the arc's center
* @param cy is the Y coordinate of the arc's center
* @param startx is the X coordinate of the starting point
* @param starty is the Y coordinate of the starting point
* @param width is the width of the arc
* @param angle is the included angle
* @param csides is the number of segments in a circle; use 1
* to take advantage of automatic calculations of this number
* @param hole determined whether the arc is to be a hole or a solid
*
* @return bool: true if the feature was successfully created
*/
bool AddArc( double cx, double cy, double startx, double starty,
double width, double angle, int csides, bool hole = false );
/**
* Function Tesselate
* creates a list of outline vertices as well as the
* vertex sets required to render the surface.
*
* @param holes is a pointer to cutouts to be imposed on the
* surface.
*
* @return bool: true if the operation succeeded
*/
bool Tesselate( VRML_LAYER* holes );
/**
* Function WriteVertices
* writes out the list of vertices required to render a
* planar surface.
*
* @param z is the Z coordinate of the plane
* @param fp is the file to write to
*
* @return bool: true if the operation succeeded
*/
bool WriteVertices( double z, FILE* fp );
/**
* Function Write3DVertices
* writes out the list of vertices required to render an extruded solid
*
* @param top is the Z coordinate of the top plane
* @param bottom is the Z coordinate of the bottom plane
* @param fp is the file to write to
*
* @return bool: true if the operation succeeded
*/
bool Write3DVertices( double top, double bottom, FILE* fp );
/**
* Function WriteIndices
* writes out the vertex sets required to render a planar
* surface.
*
* @param top is true if the surface is to be visible from above;
* if false the surface will be visible from below.
* @param fp is the file to write to
*
* @return bool: true if the operation succeeded
*/
bool WriteIndices( bool top, FILE* fp );
/**
* Function Write3DIndices
* writes out the vertex sets required to render an extruded solid
*
* @param fp is the file to write to
*
* @return bool: true if the operation succeeded
*/
bool Write3DIndices( FILE* fp );
/**
* Function AddExtraVertex
* adds an extra vertex as required by the GLU tesselator
*
* @return VERTEX_3D*: is the new vertex or NULL if a vertex
* could not be created.
*/
VERTEX_3D* AddExtraVertex( double x, double y );
/**
* Function glStart
* is invoked by the GLU tesselator callback to notify this object
* of the type of GL command which is applicable to the upcoming
* vertex list.
*
* @param cmd is the GL command
*/
void glStart( GLenum cmd );
/**
* Function glPushVertex
* is invoked by the GLU tesselator callback; the supplied vertex is
* added to the internal list of vertices awaiting processing upon
* execution of glEnd()
*
* @param vertex is a vertex forming part of the GL command as previously
* set by glStart
*/
void glPushVertex( VERTEX_3D* vertex );
/**
* Function glEnd
* is invoked by the GLU tesselator callback to notify this object
* that the vertex list is complete and ready for processing
*/
void glEnd( void );
/**
* Function SetGLError
* sets the error message according to the specified OpenGL error
*/
void SetGLError( GLenum error_id );
/**
* Function Import
* inserts all contours into the given tesselator; this
* results in the renumbering of all vertices from @param start.
* Take care when using this call since tesselators cannot work on
* the internal data concurrently.
*
* @param start is the starting number for vertex indices
* @param tess is a pointer to a GLU Tesselator object
*
* @return int: the number of vertices exported
*/
int Import( int start, GLUtesselator* tess );
/**
* Function GetVertexByIndex
* returns a pointer to the requested vertex or
* NULL if no such vertex exists.
*
* @param ptindex is a vertex index
*
* @return VERTEX_3D*: the requested vertex or NULL
*/
VERTEX_3D* GetVertexByIndex( int ptindex );
/*
* Function GetError
* Returns the error message related to the last failed operation
*/
const std::string& GetError( void );
};
#endif // VRML_BOARD_H

View File

@ -775,7 +775,7 @@ void BOARD_OUTLINE::writeOutline( std::ofstream& aBoardFile, IDF_OUTLINE* aOutli
aBoardFile << aIndex << " " << setiosflags(ios::fixed) << setprecision(5)
<< aOutline->front()->startPoint.x << " "
<< aOutline->front()->startPoint.y << " "
<< setprecision(5) << -aOutline->front()->angle << "\n";
<< setprecision(2) << -aOutline->front()->angle << "\n";
}
}
else
@ -799,7 +799,7 @@ void BOARD_OUTLINE::writeOutline( std::ofstream& aBoardFile, IDF_OUTLINE* aOutli
aBoardFile << aIndex << " " << setiosflags(ios::fixed) << setprecision(1)
<< (aOutline->front()->startPoint.x / IDF_THOU_TO_MM) << " "
<< (aOutline->front()->startPoint.y / IDF_THOU_TO_MM) << " "
<< setprecision(5) << -aOutline->front()->angle << "\n";
<< setprecision(2) << -aOutline->front()->angle << "\n";
}
}
@ -819,7 +819,7 @@ void BOARD_OUTLINE::writeOutline( std::ofstream& aBoardFile, IDF_OUTLINE* aOutli
aBoardFile << aIndex << " " << setiosflags(ios::fixed) << setprecision(5)
<< (*bo)->startPoint.x << " "
<< (*bo)->startPoint.y << " "
<< setprecision(5) << -(*bo)->angle << "\n";
<< setprecision(2) << -(*bo)->angle << "\n";
}
}
else
@ -835,7 +835,7 @@ void BOARD_OUTLINE::writeOutline( std::ofstream& aBoardFile, IDF_OUTLINE* aOutli
aBoardFile << aIndex << " " << setiosflags(ios::fixed) << setprecision(1)
<< ((*bo)->startPoint.x / IDF_THOU_TO_MM) << " "
<< ((*bo)->startPoint.y / IDF_THOU_TO_MM) << " "
<< setprecision(5) << -(*bo)->angle << "\n";
<< setprecision(2) << -(*bo)->angle << "\n";
}
}
@ -869,7 +869,7 @@ void BOARD_OUTLINE::writeOutline( std::ofstream& aBoardFile, IDF_OUTLINE* aOutli
aBoardFile << aIndex << " " << setiosflags(ios::fixed) << setprecision(5)
<< (*bo)->endPoint.x << " "
<< (*bo)->endPoint.y << " "
<< setprecision(5) << (*bo)->angle << "\n";
<< setprecision(2) << (*bo)->angle << "\n";
}
}
else
@ -893,7 +893,7 @@ void BOARD_OUTLINE::writeOutline( std::ofstream& aBoardFile, IDF_OUTLINE* aOutli
aBoardFile << aIndex << " " << setiosflags(ios::fixed) << setprecision(1)
<< ((*bo)->endPoint.x / IDF_THOU_TO_MM) << " "
<< ((*bo)->endPoint.y / IDF_THOU_TO_MM) << " "
<< setprecision(5) << (*bo)->angle << "\n";
<< setprecision(2) << (*bo)->angle << "\n";
}
}
@ -915,7 +915,7 @@ void BOARD_OUTLINE::writeOutline( std::ofstream& aBoardFile, IDF_OUTLINE* aOutli
aBoardFile << aIndex << " " << setiosflags(ios::fixed) << setprecision(5)
<< (*bo)->endPoint.x << " "
<< (*bo)->endPoint.y << " "
<< setprecision(5) << (*bo)->angle << "\n";
<< setprecision(2) << (*bo)->angle << "\n";
}
}
else
@ -931,7 +931,7 @@ void BOARD_OUTLINE::writeOutline( std::ofstream& aBoardFile, IDF_OUTLINE* aOutli
aBoardFile << aIndex << " " << setiosflags(ios::fixed) << setprecision(1)
<< ((*bo)->endPoint.x / IDF_THOU_TO_MM) << " "
<< ((*bo)->endPoint.y / IDF_THOU_TO_MM) << " "
<< setprecision(5) << (*bo)->angle << "\n";
<< setprecision(2) << (*bo)->angle << "\n";
}
}
@ -1281,7 +1281,7 @@ bool BOARD_OUTLINE::addOutline( IDF_OUTLINE* aOutline )
outlines.push_back( aOutline );
}
catch( std::exception& e )
catch( const std::exception& e )
{
errormsg = e.what();

View File

@ -2382,7 +2382,7 @@ void IDF3_BOARD::readBoardFile( const std::string& aFileName, bool aNoSubstitute
}
}
}
catch( std::exception& e )
catch( const std::exception& e )
{
brd.exceptions ( std::ios_base::goodbit );
@ -2689,7 +2689,7 @@ void IDF3_BOARD::readLibFile( const std::string& aFileName )
while( lib.good() ) readLibSection( lib, state, this );
}
catch( std::exception& e )
catch( const std::exception& e )
{
lib.exceptions ( std::ios_base::goodbit );
@ -2773,7 +2773,7 @@ bool IDF3_BOARD::ReadFile( const wxString& aFullFileName, bool aNoSubstituteOutl
// read the board file
readBoardFile( bfname, aNoSubstituteOutlines );
}
catch( std::exception& e )
catch( const std::exception& e )
{
Clear();
errormsg = e.what();
@ -2821,7 +2821,7 @@ bool IDF3_BOARD::writeLibFile( const std::string& aFileName )
}
}
catch( std::exception& e )
catch( const std::exception& e )
{
lib.exceptions( std::ios_base::goodbit );
@ -3065,7 +3065,7 @@ void IDF3_BOARD::writeBoardFile( const std::string& aFileName )
}
}
catch( std::exception& e )
catch( const std::exception& e )
{
brd.exceptions( std::ios_base::goodbit );
@ -3137,7 +3137,7 @@ bool IDF3_BOARD::WriteFile( const wxString& aFullFileName, bool aUnitMM, bool aF
writeBoardFile( bfname );
}
catch( std::exception& e )
catch( const std::exception& e )
{
errormsg = e.what();
@ -3901,7 +3901,7 @@ IDF3_COMP_OUTLINE* IDF3_BOARD::GetComponentOutline( wxString aFullFileName )
}
} // while( true )
}
catch( std::exception& e )
catch( const std::exception& e )
{
delete cp;

View File

@ -230,8 +230,7 @@ void VRML_LAYER::Clear( void )
contours.pop_back();
}
while( !areas.empty() )
areas.pop_back();
areas.clear();
for( i = vertices.size(); i > 0; --i )
{
@ -254,8 +253,7 @@ void VRML_LAYER::clearTmp( void )
ord = 0;
glcmd = 0;
while( !triplets.empty() )
triplets.pop_back();
triplets.clear();
for( i = outline.size(); i > 0; --i )
{
@ -263,8 +261,7 @@ void VRML_LAYER::clearTmp( void )
outline.pop_back();
}
for( i = ordmap.size(); i > 0; --i )
ordmap.pop_back();
ordmap.clear();
for( i = extra_verts.size(); i > 0; --i )
{
@ -274,8 +271,7 @@ void VRML_LAYER::clearTmp( void )
// note: unlike outline and extra_verts,
// vlist is not responsible for memory management
for( i = vlist.size(); i > 0; --i )
vlist.pop_back();
vlist.clear();
// go through the vertex list and reset ephemeral parameters
for( i = 0; i < vertices.size(); ++i )
@ -743,6 +739,7 @@ bool VRML_LAYER::Tesselate( VRML_LAYER* holes )
// open the polygon
gluTessBeginPolygon( tess, this );
// add solid outlines
pushVertices( false );
// close the polygon
@ -751,8 +748,10 @@ bool VRML_LAYER::Tesselate( VRML_LAYER* holes )
if( Fault )
return false;
// push the (solid) outline to the tesselator
if( !pushOutline( holes ) )
// at this point we have a solid outline; add it to the tesselator
gluTessBeginPolygon( tess, this );
if( !pushOutline( NULL ) )
return false;
// add the holes contained by this object
@ -772,14 +771,14 @@ bool VRML_LAYER::Tesselate( VRML_LAYER* holes )
// erase the previous outline data and vertex order
// but preserve the extra vertices
for( int i = outline.size(); i > 0; --i )
while( !outline.empty() )
{
delete outline.back();
outline.pop_back();
}
for( unsigned int i = ordmap.size(); i > 0; --i )
ordmap.pop_back();
ordmap.clear();
ord = 0;
// go through the vertex lists and reset ephemeral parameters
for( unsigned int i = 0; i < vertices.size(); ++i )
@ -792,14 +791,16 @@ bool VRML_LAYER::Tesselate( VRML_LAYER* holes )
extra_verts[i]->o = -1;
}
ord = 0;
// close the polygon; we now have all the data necessary for the tesselation
// close the polygon; this creates the outline points
// and the point ordering list 'ordmap'
gluTessEndPolygon( tess );
// request a tesselated surface
// repeat the last operation but request a tesselated surface
// rather than an outline; this creates the triangles list.
gluTessProperty( tess, GLU_TESS_BOUNDARY_ONLY, GL_FALSE );
gluTessBeginPolygon( tess, this );
if( !pushOutline( holes ) )
return false;
@ -821,8 +822,6 @@ bool VRML_LAYER::pushOutline( VRML_LAYER* holes )
return false;
}
gluTessBeginPolygon( tess, this );
std::list<std::list<int>*>::const_iterator obeg = outline.begin();
std::list<std::list<int>*>::const_iterator oend = outline.end();
@ -851,6 +850,7 @@ bool VRML_LAYER::pushOutline( VRML_LAYER* holes )
if( pi < 0 || (unsigned int) pi > ordmap.size() )
{
gluTessEndContour( tess );
error = "pushOutline():BUG: *outline.begin() is not a valid index to ordmap";
return false;
}
@ -862,6 +862,7 @@ bool VRML_LAYER::pushOutline( VRML_LAYER* holes )
if( !vp )
{
gluTessEndContour( tess );
error = "pushOutline():: BUG: ordmap[n] is not a valid index to vertices[]";
return false;
}
@ -1194,9 +1195,9 @@ bool VRML_LAYER::addTriplet( VERTEX_3D* p0, VERTEX_3D* p1, VERTEX_3D* p2 )
double dy0 = p1->y - p0->y;
double dy1 = p2->y - p0->y;
// this number is chosen because we shall only write 6 decimal places
// on the VRML output
double err = 0.000001;
// this number is chosen because we shall only write 9 decimal places
// at most on the VRML output
double err = 0.000000001;
// test if the triangles are degenerate (parallel sides)

View File

@ -96,6 +96,7 @@ private:
bool fix; // when true, no more vertices may be added by the user
int idx; // vertex index (number of contained vertices)
int ord; // vertex order (number of ordered vertices)
unsigned int idxout; // outline index to first point in 3D outline
std::vector<VERTEX_3D*> vertices; // vertices of all contours
std::vector<std::list<int>*> contours; // lists of vertices for each contour
std::vector< double > areas; // area of the contours (positive if winding is CCW)