← Back to team overview

kicad-developers team mailing list archive

[PATCH] SHAPE_CONVEX for the PNS router

 

Hi everybody,


below is a patch to add a SHAPE_CONVEX for the PNS router. The patch was
generated against revision 5484.

What still needs to be done:

- the "hull" around convex shapes (used for keepout when routing traces)
is suboptimal, meaning too large

- I'm not sure all the shape collision cases work correctly

- I don't really understand what the "breakouts" are and are used for,
these are most likely not correct

I do not think I know enough to fix these.

So this patch is not a finished thing but rather a starting point.

BTW, I noticed that unrotated oval pads do not work right in the PNS
router, when in "Highlight collisions" mode and hitting one the pad
itself disappears and only the clearance is drawn.


Enjoy,

MGri


=== modified file 'common/geometry/shape_collisions.cpp'
--- common/geometry/shape_collisions.cpp	2015-03-03 10:50:50 +0000
+++ common/geometry/shape_collisions.cpp	2015-03-08 15:37:58 +0000
@@ -30,6 +30,7 @@
 #include <geometry/shape_circle.h>
 #include <geometry/shape_rect.h>
 #include <geometry/shape_segment.h>
+#include <geometry/shape_convex.h>
 
 typedef VECTOR2I::extended_type ecoord;
 
@@ -168,6 +169,32 @@
 }
 
 
+static inline bool Collide( const SHAPE_CIRCLE& aA, const SHAPE_CONVEX& aB, int aClearance,
+                            bool aNeedMTV, VECTOR2I& aMTV )
+{
+    bool found;
+    const SHAPE_LINE_CHAIN& lc( aB.Vertices() );
+
+    found = lc.Distance( aA.GetCenter() ) <= aClearance + aA.GetRadius();
+
+    if( !aNeedMTV || !found )
+        return found;
+
+    SHAPE_CIRCLE cmoved( aA );
+    VECTOR2I f_total( 0, 0 );
+
+    for( int s = 0; s < lc.SegmentCount(); s++ )
+    {
+        VECTOR2I f = pushoutForce( cmoved, lc.CSegment( s ), aClearance );
+        cmoved.SetCenter( cmoved.GetCenter() + f );
+        f_total += f;
+    }
+
+    aMTV = f_total;
+    return found;
+}
+
+
 static inline bool Collide( const SHAPE_CIRCLE& aA, const SHAPE_SEGMENT& aSeg, int aClearance,
                             bool aNeedMTV, VECTOR2I& aMTV )
 {
@@ -192,6 +219,20 @@
 }
 
 
+static inline bool Collide( const SHAPE_LINE_CHAIN& aA, const SHAPE_CONVEX& aB, int aClearance,
+                            bool aNeedMTV, VECTOR2I& aMTV )
+{
+    return Collide( aA, aB.Vertices(), aClearance, aNeedMTV, aMTV );
+}
+
+
+static inline bool Collide( const SHAPE_CONVEX& aA, const SHAPE_CONVEX& aB, int aClearance,
+                            bool aNeedMTV, VECTOR2I& aMTV )
+{
+    return Collide( aA.Vertices(), aB.Vertices(), aClearance, aNeedMTV, aMTV );
+}
+
+
 static inline bool Collide( const SHAPE_RECT& aA, const SHAPE_LINE_CHAIN& aB, int aClearance,
                             bool aNeedMTV, VECTOR2I& aMTV )
 {
@@ -207,6 +248,13 @@
 }
 
 
+static inline bool Collide( const SHAPE_RECT& aA, const SHAPE_CONVEX& aB, int aClearance,
+                            bool aNeedMTV, VECTOR2I& aMTV )
+{
+    return Collide( aA, aB.Vertices(), aClearance, aNeedMTV, aMTV );
+}
+
+
 static inline bool Collide( const SHAPE_RECT& aA, const SHAPE_SEGMENT& aSeg, int aClearance,
                             bool aNeedMTV, VECTOR2I& aMTV )
 {
@@ -231,6 +279,13 @@
 }
 
 
+static inline bool Collide( const SHAPE_CONVEX& aA, const SHAPE_SEGMENT& aB, int aClearance,
+                            bool aNeedMTV, VECTOR2I& aMTV )
+{
+    return Collide( aA.Vertices(), aB, aClearance, aNeedMTV, aMTV );
+}
+
+
 template<class ShapeAType, class ShapeBType>
 inline bool CollCase( const SHAPE* aA, const SHAPE* aB, int aClearance, bool aNeedMTV, VECTOR2I& aMTV )
 {
@@ -267,6 +322,9 @@
                 case SH_SEGMENT:
                     return CollCase<SHAPE_RECT, SHAPE_SEGMENT>( aA, aB, aClearance, aNeedMTV, aMTV );
 
+                case SH_CONVEX:
+                    return CollCase<SHAPE_RECT, SHAPE_CONVEX>( aA, aB, aClearance, aNeedMTV, aMTV );
+                    
                 default:
                     break;
             }
@@ -286,6 +344,9 @@
                 case SH_SEGMENT:
                     return CollCase<SHAPE_CIRCLE, SHAPE_SEGMENT>( aA, aB, aClearance, aNeedMTV, aMTV );
 
+                case SH_CONVEX:
+                    return CollCase<SHAPE_CIRCLE, SHAPE_CONVEX>( aA, aB, aClearance, aNeedMTV, aMTV );
+                    
                 default:
                     break;
             }
@@ -305,6 +366,9 @@
                 case SH_SEGMENT:
                     return CollCase<SHAPE_LINE_CHAIN, SHAPE_SEGMENT>( aA, aB, aClearance, aNeedMTV, aMTV );
 
+                case SH_CONVEX:
+                    return CollCase<SHAPE_LINE_CHAIN, SHAPE_CONVEX>( aA, aB, aClearance, aNeedMTV, aMTV );
+                    
                 default:
                     break;
             }
@@ -324,10 +388,35 @@
                 case SH_SEGMENT:
                     return CollCase<SHAPE_SEGMENT, SHAPE_SEGMENT>( aA, aB, aClearance, aNeedMTV, aMTV );
 
-                default:
-                    break;
-            }
-
+                case SH_CONVEX:
+                    return CollCase<SHAPE_CONVEX, SHAPE_SEGMENT>( aB, aA, aClearance, aNeedMTV, aMTV );
+                    
+                default:
+                    break;
+            }
+
+        case SH_CONVEX:
+            switch( aB->Type() )
+            {
+                case SH_RECT:
+                    return CollCase<SHAPE_RECT, SHAPE_CONVEX>( aB, aA, aClearance, aNeedMTV, aMTV );
+
+                case SH_CIRCLE:
+                    return CollCase<SHAPE_CIRCLE, SHAPE_CONVEX>( aB, aA, aClearance, aNeedMTV, aMTV );
+
+                case SH_LINE_CHAIN:
+                    return CollCase<SHAPE_LINE_CHAIN, SHAPE_CONVEX>( aB, aA, aClearance, aNeedMTV, aMTV );
+
+                case SH_SEGMENT:
+                    return CollCase<SHAPE_CONVEX, SHAPE_SEGMENT>( aA, aB, aClearance, aNeedMTV, aMTV );
+
+                case SH_CONVEX:
+                    return CollCase<SHAPE_CONVEX, SHAPE_CONVEX>( aA, aB, aClearance, aNeedMTV, aMTV );
+                    
+                default:
+                    break;
+            }
+            
         default:
             break;
     }

=== added file 'include/geometry/shape_convex.h'
--- include/geometry/shape_convex.h	1970-01-01 00:00:00 +0000
+++ include/geometry/shape_convex.h	2015-03-08 15:10:05 +0000
@@ -0,0 +1,223 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2015 Kicad Developers, see change_log.txt for contributors.
+ *
+ * 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
+ */
+
+#ifndef __SHAPE_CONVEX_H
+#define __SHAPE_CONVEX_H
+
+#include <vector>
+
+#include <geometry/shape.h>
+#include <geometry/seg.h>
+#include <geometry/shape_line_chain.h>
+
+/**
+ * Class SHAPE_CONVEX
+ *
+ * Represents a convex polygon consisting of a zero-thickness closed chain of
+ * connected line segments.
+ *
+ * Internally the vertices are held in a SHAPE_LINE_CHAIN, please note that
+ * there is a "virtual" line segment between the last and first vertex.
+ */
+class SHAPE_CONVEX : public SHAPE
+{
+public:
+    /**
+     * Constructor
+     * Creates an empty polygon
+     */
+    SHAPE_CONVEX() :
+        SHAPE( SH_CONVEX )
+    {
+        m_points.SetClosed( true );
+    }
+
+    SHAPE_CONVEX( const SHAPE_CONVEX& aOther ) :
+	    SHAPE( SH_CONVEX ), m_points( aOther.m_points )
+    {}
+
+    SHAPE* Clone() const
+    {
+        return new SHAPE_CONVEX( *this );
+    }
+
+    /**
+     * Function Clear()
+     * Removes all points from the polygon.
+     */
+    void Clear()
+    {
+        m_points.Clear();
+    }
+
+    /// @copydoc SHAPE::BBox()
+    const BOX2I BBox( int aClearance = 0 ) const
+    {
+        return m_points.BBox( aClearance );
+    }
+
+    /**
+     * Function EnclosingCircle()
+     *
+     * Returns the center and radius of a circle enclosing the polygon.
+     * @param reference to an int receiving the radius
+     * @return center of the circle
+     */
+    const VECTOR2I EnclosingCircle( int& radius ) const
+    {
+        int xmin = m_points.CPoint( 0 ).x;
+        int xmax = xmin;
+        int ymin = m_points.CPoint( 0 ).y;
+        int ymax = ymin;
+
+        for( int i = 1; i < m_points.PointCount(); i++ )
+        {
+            const VECTOR2I& v = m_points.CPoint( i );
+
+            if( v.x > xmax )
+                xmax = v.x;
+            if( v.x < xmin )
+                xmin = v.x;
+            if( v.y > ymax )
+                ymax = v.y;
+            if( v.y < ymin )
+                ymin = v.y;
+        }
+
+        VECTOR2I center( xmin + (xmax - xmin) / 2, ymin + (ymax - ymin) / 2 );
+        radius = std::max( xmax - xmin, ymax - ymin ) / 2;
+
+        return center;
+    }
+    
+    /**
+     * Function PointCount()
+     *
+     * Returns the number of points (vertices) in this polygon
+     * @return number of points
+     */
+    int PointCount() const
+    {
+        return m_points.PointCount();
+    }
+
+    /**
+     * Function Point()
+     *
+     * Returns a reference to a given point in the polygon. Negative indices
+     * count from the end of the point list, e.g. -1 means "last point", -2
+     * means "second to last point" and so on.
+     * @param aIndex index of the point
+     * @return reference to the point
+     */
+    VECTOR2I& Point( int aIndex )
+    {
+        return m_points.Point( aIndex );
+    }
+
+    /**
+     * Function CPoint()
+     *
+     * Returns a const reference to a given point in the polygon. Negative
+     * indices count from the end of the point list, e.g. -1 means "last
+     * point", -2 means "second to last point" and so on.
+     * @param aIndex index of the point
+     * @return const reference to the point
+     */
+    const VECTOR2I& CPoint( int aIndex ) const
+    {
+        return m_points.CPoint( aIndex );
+    }
+
+    /**
+     * Function CDPoint()
+     *
+     * Returns a given point as a vector with elements of type double.
+     * 
+     * @param aIndex index of the point
+     * @return the point with elements of type double
+     */
+    const VECTOR2D CDPoint( int aIndex ) const
+    {
+        const VECTOR2I& v = CPoint( aIndex );
+        return VECTOR2D( v.x, v.y );
+    }
+
+    /**
+     * Function Vertices()
+     *
+     * Returns the list of vertices defining this convex polygon.
+     *
+     * @return the list of vertices defining this convex polygon
+     */
+    const SHAPE_LINE_CHAIN& Vertices() const
+    {
+        return m_points;
+    }
+    
+    /**
+     * Function Append()
+     *
+     * Appends a new point at the end of the polygon.
+     * @param aX is X coordinate of the new point
+     * @param aY is Y coordinate of the new point
+     */
+    void Append( int aX, int aY )
+    {
+        VECTOR2I v( aX, aY );
+        Append( v );
+    }
+
+    /**
+     * Function Append()
+     *
+     * Appends a new point at the end of the polygon.
+     * @param aP the new point
+     */
+    void Append( const VECTOR2I& aP )
+    {
+        m_points.Append( aP );
+    }
+
+    /// @copydoc SHAPE::Collide()
+    bool Collide( const SEG& aSeg, int aClearance = 0 ) const
+    {
+        return m_points.Collide( aSeg, aClearance );
+    }
+
+    void Move( const VECTOR2I& aVector )
+    {
+        m_points.Move( aVector );
+    }
+
+    bool IsSolid() const
+    {
+        return true;
+    }
+
+private:
+    // vertices
+    SHAPE_LINE_CHAIN m_points;
+};
+
+#endif // __SHAPE_CONVEX_H

=== modified file 'pcbnew/router/pns_logger.cpp'
--- pcbnew/router/pns_logger.cpp	2015-03-02 16:20:48 +0000
+++ pcbnew/router/pns_logger.cpp	2015-03-08 15:41:53 +0000
@@ -29,6 +29,7 @@
 #include <geometry/shape_line_chain.h>
 #include <geometry/shape_rect.h>
 #include <geometry/shape_circle.h>
+#include <geometry/shape_convex.h>
 
 PNS_LOGGER::PNS_LOGGER( )
 {
@@ -173,6 +174,17 @@
             break;
         }
 
+        case SH_CONVEX:
+        {
+            const SHAPE_CONVEX* c = (const SHAPE_CONVEX*) aSh;
+            m_theLog << "convex " << c->PointCount() << " ";
+
+            for( int i = 0; i < c->PointCount(); i++ )
+                m_theLog << c->CPoint( i ).x << " " << c->CPoint( i ).y << " ";
+
+            break;
+        }
+
         default:
             break;
     }

=== modified file 'pcbnew/router/pns_optimizer.cpp'
--- pcbnew/router/pns_optimizer.cpp	2015-02-18 16:53:46 +0000
+++ pcbnew/router/pns_optimizer.cpp	2015-03-08 15:37:58 +0000
@@ -22,6 +22,7 @@
 
 #include <geometry/shape_line_chain.h>
 #include <geometry/shape_rect.h>
+#include <geometry/shape_convex.h>
 
 #include "pns_line.h"
 #include "pns_diff_pair.h"
@@ -657,6 +658,27 @@
     return breakouts;
 }
 
+// TODO: this is most certainly not correct
+PNS_OPTIMIZER::BREAKOUT_LIST PNS_OPTIMIZER::convexBreakouts( int aWidth,
+        const SHAPE* aShape, bool aPermitDiagonal ) const
+{
+    BREAKOUT_LIST breakouts;
+    const SHAPE_CONVEX* convex = static_cast<const SHAPE_CONVEX*>( aShape );
+    int r;
+    VECTOR2I p0 = convex->EnclosingCircle( r );
+
+    for( int angle = 0; angle < 360; angle += 45 )
+    {
+        SHAPE_LINE_CHAIN l;
+        VECTOR2I v0( r * M_SQRT2, 0 );
+        l.Append( p0 );
+        l.Append( p0 + v0.Rotate( angle * M_PI / 180.0 ) );
+        breakouts.push_back( l );
+    }
+
+    return breakouts;
+}
+
 
 PNS_OPTIMIZER::BREAKOUT_LIST PNS_OPTIMIZER::rectBreakouts( int aWidth,
         const SHAPE* aShape, bool aPermitDiagonal ) const
@@ -742,6 +764,9 @@
         case SH_CIRCLE:
             return circleBreakouts( aWidth, shape, aPermitDiagonal );
 
+        case SH_CONVEX:
+            return convexBreakouts( aWidth, shape, aPermitDiagonal );
+
         default:
             break;
         }

=== modified file 'pcbnew/router/pns_optimizer.h'
--- pcbnew/router/pns_optimizer.h	2015-02-18 16:53:46 +0000
+++ pcbnew/router/pns_optimizer.h	2015-03-08 15:37:58 +0000
@@ -158,6 +158,7 @@
     BREAKOUT_LIST circleBreakouts( int aWidth, const SHAPE* aShape, bool aPermitDiagonal ) const;
     BREAKOUT_LIST rectBreakouts( int aWidth, const SHAPE* aShape, bool aPermitDiagonal ) const;
     BREAKOUT_LIST ovalBreakouts( int aWidth, const SHAPE* aShape, bool aPermitDiagonal ) const;
+    BREAKOUT_LIST convexBreakouts( int aWidth, const SHAPE* aShape, bool aPermitDiagonal ) const;
     BREAKOUT_LIST computeBreakouts( int aWidth, const PNS_ITEM* aItem, bool aPermitDiagonal ) const;
 
     int smartPadsSingle( PNS_LINE* aLine, PNS_ITEM* aPad, bool aEnd, int aEndVertex );

=== modified file 'pcbnew/router/pns_router.cpp'
--- pcbnew/router/pns_router.cpp	2015-03-02 16:21:04 +0000
+++ pcbnew/router/pns_router.cpp	2015-03-08 15:37:58 +0000
@@ -34,6 +34,7 @@
 #include <geometry/shape_line_chain.h>
 #include <geometry/shape_rect.h>
 #include <geometry/shape_circle.h>
+#include <geometry/shape_convex.h>
 
 #include "trace.h"
 #include "pns_node.h"
@@ -201,52 +202,142 @@
     solid->SetPos( c );
 
     double orient = aPad->GetOrientation() / 10.0;
-    bool nonOrtho = false;
 
-    if( orient == 90.0 || orient == 270.0 )
-        sz = VECTOR2I( sz.y, sz.x );
-    else if( orient != 0.0 && orient != 180.0 )
+    if( aPad->GetShape() == PAD_CIRCLE )
     {
-        // rotated pads are replaced by for the moment by circles due to my laziness ;)
-        solid->SetShape( new SHAPE_CIRCLE( c, std::min( sz.x, sz.y ) / 2 ) );
-        nonOrtho = true;
+        solid->SetShape( new SHAPE_CIRCLE( c, sz.x / 2 ) );
     }
-
-    if( !nonOrtho )
+    else 
     {
-        switch( aPad->GetShape() )
-        {
-        case PAD_CIRCLE:
-            solid->SetShape( new SHAPE_CIRCLE( c, sz.x / 2 ) );
-            break;
-
-        case PAD_OVAL:
-            if( sz.x == sz.y )
-                solid->SetShape( new SHAPE_CIRCLE( c, sz.x / 2 ) );
-            else
-            {
-                VECTOR2I delta;
-
-                if( sz.x > sz.y )
-                    delta = VECTOR2I( ( sz.x - sz.y ) / 2, 0 );
-                else
-                    delta = VECTOR2I( 0, ( sz.y - sz.x ) / 2 );
-
-                SHAPE_SEGMENT* shape = new SHAPE_SEGMENT( c - delta, c + delta,
-                                                          std::min( sz.x, sz.y ) );
-                solid->SetShape( shape );
-            }
-            break;
-
-        case PAD_RECT:
-            solid->SetShape( new SHAPE_RECT( c - sz / 2, sz.x, sz.y ) );
-            break;
-
-        default:
-            TRACEn( 0, "unsupported pad shape" );
-            delete solid;
-
-            return NULL;
+        if( orient == 0.0 || orient == 90.0 || orient == 180.0 || orient == 270.0 )
+        {
+            if( orient == 90.0 || orient == 270.0 )
+                sz = VECTOR2I( sz.y, sz.x );
+            
+            switch( aPad->GetShape() )
+            {
+            // PAD_CIRCLE already handled above
+
+            case PAD_OVAL:
+                if( sz.x == sz.y )
+                    solid->SetShape( new SHAPE_CIRCLE( c, sz.x / 2 ) );
+                else
+                {
+                    VECTOR2I delta;
+
+                    if( sz.x > sz.y )
+                        delta = VECTOR2I( ( sz.x - sz.y ) / 2, 0 );
+                    else
+                        delta = VECTOR2I( 0, ( sz.y - sz.x ) / 2 );
+
+                    SHAPE_SEGMENT* shape = new SHAPE_SEGMENT( c - delta, c + delta,
+                                                              std::min( sz.x, sz.y ) );
+                    solid->SetShape( shape );
+                }
+                break;
+
+            case PAD_RECT:
+                solid->SetShape( new SHAPE_RECT( c - sz / 2, sz.x, sz.y ) );
+                break;
+
+            case PAD_TRAPEZOID:
+            {
+                wxPoint coords[4];
+                aPad->BuildPadPolygon( coords, wxSize( 0, 0 ), aPad->GetOrientation() );
+
+                SHAPE_CONVEX* shape = new SHAPE_CONVEX();
+                for( int ii = 0; ii < 4; ii++ )
+                {
+                    shape->Append( wx_c + coords[ii] );
+                }
+                    
+                solid->SetShape( shape );
+                break;
+            }
+                
+
+            default:
+                TRACEn( 0, "unsupported pad shape" );
+                delete solid;
+
+                return NULL;
+            }
+        }
+        else
+        {
+            switch( aPad->GetShape() )
+            {
+            // PAD_CIRCLE already handled above
+
+            case PAD_OVAL:
+                if( sz.x == sz.y )
+                    solid->SetShape( new SHAPE_CIRCLE( c, sz.x / 2 ) );
+                else
+                {
+                    wxPoint start;
+                    wxPoint end;
+                    wxPoint corner;
+
+                    SHAPE_CONVEX* shape = new SHAPE_CONVEX();
+
+                    int w = aPad->BuildSegmentFromOvalShape( start, end, 0.0, wxSize( 0, 0 ) );
+
+                    if( start.y == 0 )
+                        corner = wxPoint( start.x, -(w / 2) );
+                    else
+                        corner = wxPoint( w / 2, start.y );
+                    RotatePoint( &start, aPad->GetOrientation() );
+                    RotatePoint( &corner, aPad->GetOrientation() );
+                    shape->Append( wx_c + corner );
+
+                    for( int rot = 100; rot <= 1800; rot += 100 )
+                    {
+                        wxPoint p( corner );
+                        RotatePoint( &p, start, rot );
+                        shape->Append( wx_c + p );
+                    }
+                        
+                    if( end.y == 0 )
+                        corner = wxPoint( end.x, w / 2 );
+                    else
+                        corner = wxPoint( -(w / 2), end.y );
+                    RotatePoint( &end, aPad->GetOrientation() );
+                    RotatePoint( &corner, aPad->GetOrientation() );
+                    shape->Append( wx_c + corner );
+
+                    for( int rot = 100; rot <= 1800; rot += 100 )
+                    {
+                        wxPoint p( corner );
+                        RotatePoint( &p, end, rot );
+                        shape->Append( wx_c + p );
+                    }
+
+                    solid->SetShape( shape );
+                }
+                break;
+
+            case PAD_RECT:
+            case PAD_TRAPEZOID:
+            {
+                wxPoint coords[4];
+                aPad->BuildPadPolygon( coords, wxSize( 0, 0 ), aPad->GetOrientation() );
+
+                SHAPE_CONVEX* shape = new SHAPE_CONVEX();
+                for( int ii = 0; ii < 4; ii++ )
+                {
+                    shape->Append( wx_c + coords[ii] );
+                }
+                    
+                solid->SetShape( shape );
+                break;
+            }
+
+            default:
+                TRACEn( 0, "unsupported pad shape" );
+                delete solid;
+
+                return NULL;
+            }
         }
     }
 

=== modified file 'pcbnew/router/pns_solid.cpp'
--- pcbnew/router/pns_solid.cpp	2015-02-18 16:53:46 +0000
+++ pcbnew/router/pns_solid.cpp	2015-03-08 15:37:58 +0000
@@ -24,6 +24,7 @@
 #include <geometry/shape_line_chain.h>
 #include <geometry/shape_rect.h>
 #include <geometry/shape_circle.h>
+#include <geometry/shape_convex.h>
 
 #include "pns_solid.h"
 #include "pns_utils.h"
@@ -54,6 +55,19 @@
         return SegmentHull( *seg, aClearance, aWalkaroundThickness );
     }
 
+    case SH_CONVEX:
+    {
+        SHAPE_CONVEX* convex = static_cast<SHAPE_CONVEX*>( m_shape );
+
+        int r;
+        VECTOR2I center = convex->EnclosingCircle( r );
+
+        // TODO: this is highly suboptimal, the segments of the octagon
+        // should be maximally close to the polygon
+        return OctagonalHull( center - VECTOR2I( r, r ), VECTOR2I( 2 * r, 2 * r ),
+                              cl + 1, 0.52 * ( r + cl ) );
+    }
+
     default:
         break;
     }

=== modified file 'pcbnew/router/router_preview_item.cpp'
--- pcbnew/router/router_preview_item.cpp	2015-03-03 10:50:50 +0000
+++ pcbnew/router/router_preview_item.cpp	2015-03-08 15:37:58 +0000
@@ -18,9 +18,12 @@
  * with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <deque>
+
 #include <gal/color4d.h>
 
 #include <geometry/shape_rect.h>
+#include <geometry/shape_convex.h>
 
 #include "class_track.h"
 #include <pcb_painter.h>
@@ -227,6 +230,28 @@
             }
 
         case SH_CONVEX:
+        {
+            const SHAPE_CONVEX* c = (const SHAPE_CONVEX*) m_shape;
+            std::deque<VECTOR2D> polygon = std::deque<VECTOR2D>();
+            for( int i = 0; i < c->PointCount(); i++ )
+            {
+                polygon.push_back( c->CDPoint( i ) );
+            }
+            aGal->DrawPolygon( polygon );
+
+            if( m_clearance > 0 )
+            {
+                aGal->SetLayerDepth( ClearanceOverlayDepth );
+                aGal->SetStrokeColor( COLOR4D( DARKDARKGRAY ) );
+                aGal->SetIsStroke( true );
+                aGal->SetLineWidth( 2 * m_clearance );
+                // need the implicit last segment to be explicit for DrawPolyline
+                polygon.push_back( c->CDPoint( 0 ) );                
+                aGal->DrawPolyline( polygon );
+            }
+            break;
+        }
+	    
         case SH_POLYGON:
         case SH_COMPOUND:
             break;          // Not yet in use



Follow ups