← Back to team overview

kicad-developers team mailing list archive

[PATCH] fix for artifacts in VRML export

 

Attached is a patch which fixes some rendering artifacts in the VRML exporter.

The GLU tesselator implementation on my system appears to have some erratic
behavior when merging contours with vertices near X=0. This patch works
around the suspected bug by performing the origin offset when the coordinates
are written to a file rather than before the invocation of the tesselator.

- Cirilo
=== modified file 'pcbnew/exporters/export_vrml.cpp'
--- pcbnew/exporters/export_vrml.cpp	2014-06-08 10:35:42 +0000
+++ pcbnew/exporters/export_vrml.cpp	2014-06-12 10:16:11 +0000
@@ -88,7 +88,7 @@
 #define MIN_VRML_LINEWIDTH 0.12
 
 // offset for art layers, mm (silk, paste, etc)
-#define  ART_OFFSET 0.02
+#define  ART_OFFSET 0.025
 
 /* helper function:
  * some characters cannot be used in names,
@@ -229,8 +229,17 @@
 
     void SetOffset( double aXoff, double aYoff )
     {
-        tx  = aXoff;
-        ty  = aYoff;
+        tx = aXoff;
+        ty = -aYoff;
+
+        holes.SetVertexOffsets( aXoff, aYoff );
+        board.SetVertexOffsets( aXoff, aYoff );
+        top_copper.SetVertexOffsets( aXoff, aYoff );
+        bot_copper.SetVertexOffsets( aXoff, aYoff );
+        top_silk.SetVertexOffsets( aXoff, aYoff );
+        bot_silk.SetVertexOffsets( aXoff, aYoff );
+        top_tin.SetVertexOffsets( aXoff, aYoff );
+        bot_tin.SetVertexOffsets( aXoff, aYoff );
     }
 
     double GetLayerZ( LAYER_NUM aLayer )
@@ -588,10 +597,10 @@
 {
     LAYER_NUM layer = drawseg->GetLayer();
     double  w   = drawseg->GetWidth() * aModel.scale;
-    double  x   = drawseg->GetStart().x * aModel.scale + aModel.tx;
-    double  y   = drawseg->GetStart().y * aModel.scale + aModel.ty;
-    double  xf  = drawseg->GetEnd().x * aModel.scale + aModel.tx;
-    double  yf  = drawseg->GetEnd().y * aModel.scale + aModel.ty;
+    double  x   = drawseg->GetStart().x * aModel.scale;
+    double  y   = drawseg->GetStart().y * aModel.scale;
+    double  xf  = drawseg->GetEnd().x * aModel.scale;
+    double  yf  = drawseg->GetEnd().y * aModel.scale;
 
     // Items on the edge layer are handled elsewhere; just return
     if( layer == EDGE_N )
@@ -626,12 +635,10 @@
     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( *model_vrml, s_text_layer,
-            x0 * scale + tx, y0 * scale + ty,
-            xf * scale + tx, yf * scale + ty,
+            x0 * scale, y0 * scale,
+            xf * scale, yf * scale,
             s_text_width * scale );
 }
 
@@ -729,8 +736,6 @@
     }
 
     double  scale = aModel.scale;
-    double  dx  = aModel.tx;
-    double  dy  = aModel.ty;
 
     int i = 0;
     int seg;
@@ -756,8 +761,8 @@
             if( bufferPcbOutlines[i].end_contour )
                 break;
 
-            aModel.board.AddVertex( seg, bufferPcbOutlines[i].x * scale + dx,
-                    -(bufferPcbOutlines[i].y * scale + dy) );
+            aModel.board.AddVertex( seg, bufferPcbOutlines[i].x * scale,
+                    -(bufferPcbOutlines[i].y * scale ) );
 
             ++i;
         }
@@ -788,8 +793,8 @@
             if( allLayerHoles[i].end_contour )
                 break;
 
-            aModel.holes.AddVertex( seg, allLayerHoles[i].x * scale + dx,
-                                    -(allLayerHoles[i].y * scale + dy) );
+            aModel.holes.AddVertex( seg, allLayerHoles[i].x * scale,
+                                    -(allLayerHoles[i].y * scale ) );
 
             ++i;
         }
@@ -849,8 +854,8 @@
 
     hole = via->GetDrillValue() * aModel.scale / 2.0;
     r   = via->GetWidth() * aModel.scale / 2.0;
-    x   = via->GetStart().x * aModel.scale + aModel.tx;
-    y   = via->GetStart().y * aModel.scale + aModel.ty;
+    x   = via->GetStart().x * aModel.scale;
+    y   = via->GetStart().y * aModel.scale;
     via->LayerPair( &top_layer, &bottom_layer );
 
     // do not render a buried via
@@ -873,10 +878,10 @@
         else if( track->GetLayer() == FIRST_COPPER_LAYER
                  || track->GetLayer() == LAST_COPPER_LAYER )
             export_vrml_line( aModel, track->GetLayer(),
-                    track->GetStart().x * aModel.scale + aModel.tx,
-                    track->GetStart().y * aModel.scale + aModel.ty,
-                    track->GetEnd().x * aModel.scale + aModel.tx,
-                    track->GetEnd().y * aModel.scale + aModel.ty,
+                    track->GetStart().x * aModel.scale,
+                    track->GetStart().y * aModel.scale,
+                    track->GetEnd().x * aModel.scale,
+                    track->GetEnd().y * aModel.scale,
                     track->GetWidth() * aModel.scale );
     }
 }
@@ -886,9 +891,6 @@
 {
 
     double scale = aModel.scale;
-    double dx = aModel.tx;
-    double dy = aModel.ty;
-
     double x, y;
 
     for( int ii = 0; ii < aPcb->GetAreaCount(); ii++ )
@@ -920,8 +922,8 @@
 
             while( i < nvert )
             {
-                x = poly.GetX(i) * scale + dx;
-                y = -(poly.GetY(i) * scale + dy);
+                x = poly.GetX(i) * scale;
+                y = -(poly.GetY(i) * scale);
 
                 if( poly.IsEndContour(i) )
                     break;
@@ -971,10 +973,10 @@
                                      double aOrientation )
 {
     LAYER_NUM layer = aOutline->GetLayer();
-    double  x   = aOutline->GetStart().x * aModel.scale + aModel.tx;
-    double  y   = aOutline->GetStart().y * aModel.scale + aModel.ty;
-    double  xf  = aOutline->GetEnd().x * aModel.scale + aModel.tx;
-    double  yf  = aOutline->GetEnd().y * aModel.scale + aModel.ty;
+    double  x   = aOutline->GetStart().x * aModel.scale;
+    double  y   = aOutline->GetStart().y * aModel.scale;
+    double  xf  = aOutline->GetEnd().x * aModel.scale;
+    double  yf  = aOutline->GetEnd().y * aModel.scale;
     double  w   = aOutline->GetWidth() * aModel.scale;
 
     switch( aOutline->GetShape() )
@@ -1015,8 +1017,8 @@
                 corner.x += aOutline->GetPosition().x;
                 corner.y += aOutline->GetPosition().y;
 
-                x = corner.x * aModel.scale + aModel.tx;
-                y = - ( corner.y * aModel.scale + aModel.ty );
+                x = corner.x * aModel.scale;
+                y = - ( corner.y * aModel.scale );
 
                 if( !vl->AddVertex( seg, x, y ) )
                     throw( std::runtime_error( vl->GetError() ) );
@@ -1037,8 +1039,8 @@
 {
     // The (maybe offset) pad position
     wxPoint pad_pos = aPad->ShapePos();
-    double  pad_x   = pad_pos.x * aModel.scale + aModel.tx;
-    double  pad_y   = pad_pos.y * aModel.scale + aModel.ty;
+    double  pad_x   = pad_pos.x * aModel.scale;
+    double  pad_y   = pad_pos.y * aModel.scale;
     wxSize  pad_delta = aPad->GetDelta();
 
     double  pad_dx  = pad_delta.x * aModel.scale / 2.0;
@@ -1121,8 +1123,8 @@
     double  hole_drill_w    = (double) aPad->GetDrillSize().x * aModel.scale / 2.0;
     double  hole_drill_h    = (double) aPad->GetDrillSize().y * aModel.scale / 2.0;
     double  hole_drill = std::min( hole_drill_w, hole_drill_h );
-    double  hole_x  = aPad->GetPosition().x * aModel.scale + aModel.tx;
-    double  hole_y  = aPad->GetPosition().y * aModel.scale + aModel.ty;
+    double  hole_x  = aPad->GetPosition().x * aModel.scale;
+    double  hole_y  = aPad->GetPosition().y * aModel.scale;
 
     // Export the hole on the edge layer
     if( hole_drill > 0 )
@@ -1390,7 +1392,7 @@
         EDA_RECT bbbox = pcb->ComputeBoundingBox();
 
         model3d.SetOffset( -model3d.scale * bbbox.Centre().x,
-                           -model3d.scale * bbbox.Centre().y );
+                           model3d.scale * bbbox.Centre().y );
 
         output_file << "  children [\n";
 

=== modified file 'utils/idftools/vrml_layer.cpp'
--- utils/idftools/vrml_layer.cpp	2014-06-08 10:35:42 +0000
+++ utils/idftools/vrml_layer.cpp	2014-06-12 09:44:53 +0000
@@ -152,6 +152,8 @@
     maxArcSeg = 48;
     minSegLength = 0.1;
     maxSegLength = 0.5;
+    offsetX = 0.0;
+    offsetY = 0.0;
 
     fix = false;
     Fault = false;
@@ -902,7 +904,7 @@
         return false;
 
     std::string strx, stry, strz;
-    FormatDoublet( vp->x, vp->y, aPrecision, strx, stry );
+    FormatDoublet( vp->x + offsetX, vp->y + offsetY, aPrecision, strx, stry );
     FormatSinglet( aZcoord, aPrecision, strz );
 
     aOutFile << strx << " " << stry << " " << strz;
@@ -914,7 +916,7 @@
         if( !vp )
             return false;
 
-        FormatDoublet( vp->x, vp->y, aPrecision, strx, stry );
+        FormatDoublet( vp->x + offsetX, vp->y + offsetY, aPrecision, strx, stry );
 
         if( i & 1 )
             aOutFile << ", " << strx << " " << stry << " " << strz;
@@ -954,7 +956,7 @@
         return false;
 
     std::string strx, stry, strz;
-    FormatDoublet( vp->x, vp->y, aPrecision, strx, stry );
+    FormatDoublet( vp->x + offsetX, vp->y + offsetY, aPrecision, strx, stry );
     FormatSinglet( aTopZ, aPrecision, strz );
 
     aOutFile << strx << " " << stry << " " << strz;
@@ -966,7 +968,7 @@
         if( !vp )
             return false;
 
-        FormatDoublet( vp->x, vp->y, aPrecision, strx, stry );
+        FormatDoublet( vp->x + offsetX, vp->y + offsetY, aPrecision, strx, stry );
 
         if( i & 1 )
             aOutFile << ", " << strx << " " << stry << " " << strz;
@@ -976,7 +978,7 @@
 
     // repeat for the bottom layer
     vp = getVertexByIndex( ordmap[0], pholes );
-    FormatDoublet( vp->x, vp->y, aPrecision, strx, stry );
+    FormatDoublet( vp->x + offsetX, vp->y + offsetY, aPrecision, strx, stry );
     FormatSinglet( aBottomZ, aPrecision, strz );
 
     bool endl;
@@ -995,7 +997,7 @@
     for( i = 1, j = ordmap.size(); i < j; ++i )
     {
         vp = getVertexByIndex( ordmap[i], pholes );
-        FormatDoublet( vp->x, vp->y, aPrecision, strx, stry );
+        FormatDoublet( vp->x + offsetX, vp->y + offsetY, aPrecision, strx, stry );
 
         if( endl )
         {
@@ -1564,3 +1566,11 @@
 {
     return error;
 }
+
+
+void VRML_LAYER::SetVertexOffsets( double aXoffset, double aYoffset )
+{
+    offsetX = aXoffset;
+    offsetY = aYoffset;
+    return;
+}

=== modified file 'utils/idftools/vrml_layer.h'
--- utils/idftools/vrml_layer.h	2014-06-08 10:35:42 +0000
+++ utils/idftools/vrml_layer.h	2014-06-12 09:47:53 +0000
@@ -93,6 +93,10 @@
     double minSegLength;                    // min. segment length
     double maxSegLength;                    // max. segment length
 
+    // Vertex offsets to work around a suspected GLU tesselator bug
+    double offsetX;
+    double offsetY;
+
     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)
@@ -429,6 +433,8 @@
      * Returns the error message related to the last failed operation
      */
     const std::string& GetError( void );
+
+    void SetVertexOffsets( double aXoffset, double aYoffset );
 };
 
 #endif    // VRML_LAYER_H