← Back to team overview

kicad-developers team mailing list archive

[FIX BUG] pcbnew: plot dxf draws 2 lines instead 1 with the right width

 

Hello guys.
Please try my patches that fixes DXF plot bug https://bugs.launchpad.net/kicad/+bug/1643330 .

Current behaviour:
Pcbnew plots drawings to DXF outline mode only.

After patch:
Pcbnew plots drawings to DXF copper/mask/adhes/paste layers in outline mode and other layers (for importing in mechanical) with lines with valid width.
>From 2d38579644eb233f04257bfbad15581a493846c3 Mon Sep 17 00:00:00 2001
From: Eldar Khayrullin <eldar.khayrullin@xxxxxxx>
Date: Sun, 16 Apr 2017 15:02:51 +0300
Subject: [PATCH 3/3] Pcbnew plots to DXF arcs with valid width

---
 common/common_plotDXF_functions.cpp | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/common/common_plotDXF_functions.cpp b/common/common_plotDXF_functions.cpp
index fa58ffbbb..24061a003 100644
--- a/common/common_plotDXF_functions.cpp
+++ b/common/common_plotDXF_functions.cpp
@@ -435,6 +435,8 @@ void DXF_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, i
     if( radius <= 0 )
         return;
 
+    SetCurrentLineWidth( width );
+
     // In DXF, arcs are drawn CCW.
     // In Kicad, arcs are CW or CCW
     // If StAngle > EndAngle, it is CW. So transform it to CCW
@@ -445,13 +447,14 @@ void DXF_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, i
 
     DPOINT centre_dev = userToDeviceCoordinates( centre );
     double radius_dev = userToDeviceSize( radius );
+    double pen_w = userToDeviceSize( GetCurrentLineWidth() );
 
     // Emit a DXF ARC entity
     wxString cname( m_currentColor.ToColour().GetAsString( wxC2S_CSS_SYNTAX ) );
     fprintf( outputFile,
-             "0\nARC\n8\n%s\n10\n%g\n20\n%g\n40\n%g\n50\n%g\n51\n%g\n",
+             "0\nARC\n8\n%s\n10\n%g\n20\n%g\n39\n%g\n40\n%g\n50\n%g\n51\n%g\n",
              TO_UTF8( cname ),
-             centre_dev.x, centre_dev.y, radius_dev,
+             centre_dev.x, centre_dev.y, pen_w, radius_dev,
              StAngle / 10.0, EndAngle / 10.0 );
 }
 
-- 
2.11.0

>From ac7fc0520b6b0efcd105b83948b7568051b00236 Mon Sep 17 00:00:00 2001
From: Eldar Khayrullin <eldar.khayrullin@xxxxxxx>
Date: Sun, 16 Apr 2017 14:50:03 +0300
Subject: [PATCH 2/3] Pcbnew plots to DXF circles with valid width

---
 common/common_plotDXF_functions.cpp | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/common/common_plotDXF_functions.cpp b/common/common_plotDXF_functions.cpp
index fe1ce3b25..fa58ffbbb 100644
--- a/common/common_plotDXF_functions.cpp
+++ b/common/common_plotDXF_functions.cpp
@@ -313,6 +313,7 @@ void DXF_PLOTTER::Circle( const wxPoint& centre, int diameter, FILL_T fill, int
 {
     wxASSERT( outputFile );
     double radius = userToDeviceSize( diameter / 2 );
+    SetCurrentLineWidth( width );
     DPOINT centre_dev = userToDeviceCoordinates( centre );
     if( radius > 0 )
     {
@@ -320,9 +321,10 @@ void DXF_PLOTTER::Circle( const wxPoint& centre, int diameter, FILL_T fill, int
 
         if( !fill )
         {
-            fprintf( outputFile, "0\nCIRCLE\n8\n%s\n10\n%g\n20\n%g\n40\n%g\n",
+            double pen_w = userToDeviceSize( GetCurrentLineWidth() );
+            fprintf( outputFile, "0\nCIRCLE\n8\n%s\n10\n%g\n20\n%g\n39\n%g\n40\n%g\n",
                     TO_UTF8( cname ),
-                    centre_dev.x, centre_dev.y, radius );
+                    centre_dev.x, centre_dev.y, pen_w, radius );
         }
 
         if( fill == FILLED_SHAPE )
-- 
2.11.0

>From c156d30e5cedff26cf00c2ec4d62799c3b83fe32 Mon Sep 17 00:00:00 2001
From: Eldar Khayrullin <eldar.khayrullin@xxxxxxx>
Date: Sun, 16 Apr 2017 14:34:28 +0300
Subject: [PATCH 1/3] Pcbnew plots segments to DXF copper/mask/adhes/paste
 layers in outline mode and other layers with lines with width

---
 common/common_plotDXF_functions.cpp | 113 ++++++++----------------------------
 include/plot_common.h               |   5 +-
 pcbnew/plot_board_layers.cpp        |  15 +----
 3 files changed, 27 insertions(+), 106 deletions(-)

diff --git a/common/common_plotDXF_functions.cpp b/common/common_plotDXF_functions.cpp
index 088da297d..fe1ce3b25 100644
--- a/common/common_plotDXF_functions.cpp
+++ b/common/common_plotDXF_functions.cpp
@@ -44,7 +44,7 @@ static const double DXF_OBLIQUE_ANGLE = 15;
 
 /**
  * Set the scale/position for the DXF plot
- * The DXF engine doesn't support line widths and mirroring. The output
+ * The DXF engine doesn't support mirroring. The output
  * coordinate system is in the first quadrant (in mm)
  */
 void DXF_PLOTTER::SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
@@ -67,7 +67,7 @@ void DXF_PLOTTER::SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
     iuPerDeviceUnit = 1.0 / aIusPerDecimil; // Gives a DXF in decimils
     iuPerDeviceUnit *= 0.00254;             // ... now in mm
 
-    SetDefaultLineWidth( 0 );               // No line width on DXF
+    SetDefaultLineWidth( 0 );
     m_plotMirror = false;                     // No mirroring on DXF
     m_currentColor = COLOR4D::BLACK;
 }
@@ -355,99 +355,22 @@ void DXF_PLOTTER::PlotPoly( const std::vector<wxPoint>& aCornerList,
     if( aCornerList.size() <= 1 )
         return;
 
-    unsigned last = aCornerList.size() - 1;
-
-    // Plot outlines with lines (thickness = 0) to define the polygon
-    if( aWidth <= 0  )
-    {
-        MoveTo( aCornerList[0] );
-
-        for( unsigned ii = 1; ii < aCornerList.size(); ii++ )
-            LineTo( aCornerList[ii] );
-
-        // Close polygon if 'fill' requested
-        if( aFill )
-        {
-            if( aCornerList[last] != aCornerList[0] )
-                LineTo( aCornerList[0] );
-        }
-
-        PenFinish();
+    SetCurrentLineWidth( aWidth );
 
-        return;
-    }
-
-
-    // if the polygon outline has thickness, and is not filled
-    // (i.e. is a polyline) plot outlines with thick segments
-    if( aWidth > 0 && !aFill )
-    {
-        MoveTo( aCornerList[0] );
-
-        for( unsigned ii = 1; ii < aCornerList.size(); ii++ )
-            ThickSegment( aCornerList[ii-1], aCornerList[ii],
-                          aWidth, FILLED, NULL );
-
-        return;
-    }
-
-    // The polygon outline has thickness, and is filled
-    // Build and plot the polygon which contains the initial
-    // polygon and its thick outline
-    SHAPE_POLY_SET  bufferOutline;
-    SHAPE_POLY_SET  bufferPolybase;
-    const int circleToSegmentsCount = 16;
+    unsigned last = aCornerList.size() - 1;
 
-    bufferPolybase.NewOutline();
+    MoveTo( aCornerList[0] );
 
-    // enter outline as polygon:
     for( unsigned ii = 1; ii < aCornerList.size(); ii++ )
-    {
-        TransformRoundedEndsSegmentToPolygon( bufferOutline,
-            aCornerList[ii-1], aCornerList[ii], circleToSegmentsCount, aWidth );
-    }
+	    LineTo( aCornerList[ii] );
 
-    // enter the initial polygon:
-    for( unsigned ii = 0; ii < aCornerList.size(); ii++ )
+    // Close polygon if 'fill' requested
+    if( aFill )
     {
-        bufferPolybase.Append( aCornerList[ii] );
+	    if( aCornerList[last] != aCornerList[0] )
+		    LineTo( aCornerList[0] );
     }
 
-    // Merge polygons to build the polygon which contains the initial
-    // polygon and its thick outline
-
-    // create the outline which contains thick outline:
-    bufferPolybase.BooleanAdd( bufferOutline, SHAPE_POLY_SET::PM_FAST );
-    bufferPolybase.Fracture( SHAPE_POLY_SET::PM_FAST );
-
-    if( bufferPolybase.OutlineCount() < 1 )      // should not happen
-        return;
-
-    const SHAPE_LINE_CHAIN& path = bufferPolybase.COutline( 0 );
-
-    if( path.PointCount() < 2 )           // should not happen
-        return;
-
-    // Now, output the final polygon to DXF file:
-    last = path.PointCount() - 1;
-	  VECTOR2I point = path.CPoint( 0 );
-
-    wxPoint startPoint( point.x, point.y );
-    MoveTo( startPoint );
-
-    for( int ii = 1; ii < path.PointCount(); ii++ )
-    {
-        point = path.CPoint( ii );
-        LineTo( wxPoint( point.x, point.y ) );
-    }
-
-    // Close polygon, if needed
-    point = path.CPoint( last );
-    wxPoint endPoint( point.x, point.y );
-
-    if( endPoint != startPoint )
-        LineTo( startPoint );
-
     PenFinish();
 }
 
@@ -464,11 +387,12 @@ void DXF_PLOTTER::PenTo( const wxPoint& pos, char plume )
 
     if( penLastpos != pos && plume == 'D' )
     {
+        double pen_w = userToDeviceSize( GetCurrentLineWidth() );
         // DXF LINE
         wxString cname( m_currentColor.ToColour().GetAsString( wxC2S_CSS_SYNTAX ) );
-        fprintf( outputFile, "0\nLINE\n8\n%s\n10\n%g\n20\n%g\n11\n%g\n21\n%g\n",
+        fprintf( outputFile, "0\nLINE\n8\n%s\n10\n%g\n20\n%g\n11\n%g\n21\n%g\n39\n%g\n",
                  TO_UTF8( cname ),
-                 pen_lastpos_dev.x, pen_lastpos_dev.y, pos_dev.x, pos_dev.y );
+                 pen_lastpos_dev.x, pen_lastpos_dev.y, pos_dev.x, pos_dev.y, pen_w );
     }
     penLastpos = pos;
 }
@@ -482,11 +406,20 @@ void DXF_PLOTTER::SetDash( bool dashed )
     // NOP for now
 }
 
+void DXF_PLOTTER::SetCurrentLineWidth( int aWidth, void* aData )
+{
+    if( aWidth >= 0 )
+        currentPenWidth = aWidth;
+    else
+        currentPenWidth = defaultPenWidth;
+}
 
 void DXF_PLOTTER::ThickSegment( const wxPoint& aStart, const wxPoint& aEnd, int aWidth,
                                 EDA_DRAW_MODE_T aPlotMode, void* aData )
 {
-    segmentAsOval( aStart, aEnd, aWidth, aPlotMode );
+    SetCurrentLineWidth( aWidth );
+    MoveTo( aStart );
+    FinishTo( aEnd );
 }
 
 /* Plot an arc in DXF format
diff --git a/include/plot_common.h b/include/plot_common.h
index 4fc54a537..8478b773d 100644
--- a/include/plot_common.h
+++ b/include/plot_common.h
@@ -1235,10 +1235,7 @@ public:
     virtual bool EndPlot() override;
 
     // For now we don't use 'thick' primitives, so no line width
-    virtual void SetCurrentLineWidth( int width, void* aData = NULL ) override
-    {
-        currentPenWidth = 0;
-    }
+    virtual void SetCurrentLineWidth( int width, void* aData = NULL ) override;
 
     virtual void SetDefaultLineWidth( int width ) override
     {
diff --git a/pcbnew/plot_board_layers.cpp b/pcbnew/plot_board_layers.cpp
index 57137c168..7cbfa2912 100644
--- a/pcbnew/plot_board_layers.cpp
+++ b/pcbnew/plot_board_layers.cpp
@@ -223,10 +223,7 @@ void PlotOneBoardLayer( BOARD *aBoard, PLOTTER* aPlotter, PCB_LAYER_ID aLayer,
 
         case F_SilkS:
         case B_SilkS:
-            if( plotOpt.GetFormat() == PLOT_FORMAT_DXF )
-                PlotLayerOutlines( aBoard, aPlotter, layer_mask, plotOpt );
-            else
-                PlotSilkScreen( aBoard, aPlotter, layer_mask, plotOpt );
+            PlotSilkScreen( aBoard, aPlotter, layer_mask, plotOpt );
 
             // Gerber: Subtract soldermask from silkscreen if enabled
             if( aPlotter->GetPlotterType() == PLOT_FORMAT_GERBER
@@ -264,20 +261,14 @@ void PlotOneBoardLayer( BOARD *aBoard, PLOTTER* aPlotter, PCB_LAYER_ID aLayer,
             plotOpt.SetSkipPlotNPTH_Pads( false );
             plotOpt.SetDrillMarksType( PCB_PLOT_PARAMS::NO_DRILL_SHAPE );
 
-            if( plotOpt.GetFormat() == PLOT_FORMAT_DXF )
-                PlotLayerOutlines( aBoard, aPlotter, layer_mask, plotOpt );
-            else
-                PlotSilkScreen( aBoard, aPlotter, layer_mask, plotOpt );
+            PlotSilkScreen( aBoard, aPlotter, layer_mask, plotOpt );
             break;
 
         default:
             plotOpt.SetSkipPlotNPTH_Pads( false );
             plotOpt.SetDrillMarksType( PCB_PLOT_PARAMS::NO_DRILL_SHAPE );
 
-            if( plotOpt.GetFormat() == PLOT_FORMAT_DXF )
-                PlotLayerOutlines( aBoard, aPlotter, layer_mask, plotOpt );
-            else
-                PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
+            PlotStandardLayer( aBoard, aPlotter, layer_mask, plotOpt );
             break;
         }
     }
-- 
2.11.0