diff --git a/paths.scad b/paths.scad
index eaf40d2..db2c279 100644
--- a/paths.scad
+++ b/paths.scad
@@ -210,36 +210,31 @@ function path_length_fractions(path, closed=false) =
 ///   for (isect=isects) translate(isect[0]) color("blue") sphere(d=10);
 function _path_self_intersections(path, closed=true, eps=EPSILON) =
     let(
-        path = cleanup_path(path, eps=eps),
+        path = closed ? close_path(path,eps=eps) : path,
         plen = len(path)
     )
-    [
-        for (i = [0:1:plen-(closed?2:3)])
-            let(
-                a1 = path[i],
-                a2 = path[(i+1)%plen],
-                maxax = max(a1.x,a2.x),
-                minax = min(a1.x,a2.x),
-                maxay = max(a1.y,a2.y),
-                minay = min(a1.y,a2.y)
-            )
-            for(j=[i+2:1:plen-(closed?1:2)])
+    [ for (i = [0:1:plen-3]) let(
+          a1 = path[i],
+          a2 = path[i+1],
+                // The sign of signals is positive if the segment is one one side of
+                // the line defined by [a1,a2] and negative on the other side.  
+          seg_normal = unit([-(a2-a1).y, (a2-a1).x]),
+          signals = [for(j=[i+2:1:plen-(i==0 && closed? 2: 1)]) path[j]-a1 ]*seg_normal 
+        )
+        for(j=[i+2:1:plen-(i==0 && closed? 3: 2)])
+            // The signals test requires the two signals to have different signs,
+            // otherwise b1 and b2 are on the same side of the line defined by [a1,a2]
+            // and hence intersection is impossible
+            if( signals[j-i-2]*signals[j-i-1] <= 0 )
                 let(
                     b1 = path[j],
-                    b2 = path[(j+1)%plen],
-                    isect =
-                            maxax < b1.x && maxax < b2.x  ||
-                            minax > b1.x && minax > b2.x  ||
-                            maxay < b1.y && maxay < b2.y  ||
-                            minay > b1.y && minay > b2.y
-                          ? undef
-                          : _general_line_intersection([a1,a2],[b1,b2])
+                    b2 = path[j+1]
                 )
-                if ((!closed || i!=0 || j!=plen-1)
-                        && isect != undef
-                        && isect[1]>=-eps && isect[1]<=1+eps 
-                        && isect[2]>=-eps && isect[2]<=1+eps)
-                    [isect[0], i, isect[1], j, isect[2]]
+                // This test checks that a1 and a2 are on opposite sides of the
+                // line defined by [b1,b2].  
+                if( cross(b2-b1, a1-b1)*cross(b2-b1, a2-b1) <= 0 )
+                    let(isect =  _general_line_intersection([a1,a2],[b1,b2],eps=eps))
+                    if (isect) [isect[0], i, isect[1], j, isect[2]]
     ];
 
 
@@ -266,7 +261,7 @@ function _sum_preserving_round(data, index=0) =
 
 // Function: subdivide_path()
 // Usage:
-//   newpath = subdivide_path(path, [N|refine], method);
+//   newpath = subdivide_path(path, [N|refine], method, [closed], [exact]);
 // Description:
 //   Takes a path as input (closed or open) and subdivides the path to produce a more
 //   finely sampled path.  The new points can be distributed proportional to length
diff --git a/vnf.scad b/vnf.scad
index db9ca92..5db8f27 100644
--- a/vnf.scad
+++ b/vnf.scad
@@ -486,33 +486,34 @@ module vnf_polyhedron(vnf, convexity=2, extent=true, cp=[0,0,0], anchor="origin"
 // Usage:
 //   vnf_wireframe(vnf, <r|d>);
 // Description:
-//   Given a VNF, creates a wire frame ball-and-stick model of the polyhedron with a cylinder for each edge and a sphere at each vertex.
+//   Given a VNF, creates a wire frame ball-and-stick model of the polyhedron with a cylinder for
+//   each edge and a sphere at each vertex.  The width parameter specifies the width of the sticks
+//   that form the wire frame. 
 // Arguments:
 //   vnf = A vnf structure
-//   r|d = radius or diameter of the cylinders forming the wire frame.  Default: r=1
+//   width = width of the cylinders forming the wire frame.  Default: 1
 // Example:
 //   $fn=32;
 //   ball = sphere(r=20, $fn=6);
-//   vnf_wireframe(ball,d=1);
+//   vnf_wireframe(ball,width=1);
 // Example:
-//  include<BOSL2/polyhedra.scad>
-//  $fn=32;
-//  cube_oct = regular_polyhedron_info("vnf", name="cuboctahedron", or=20);
-//  vnf_wireframe(cube_oct);
+//   include <BOSL2/polyhedra.scad>
+//   $fn=32;
+//   cube_oct = regular_polyhedron_info("vnf", name="cuboctahedron", or=20);
+//   vnf_wireframe(cube_oct);
 // Example: The spheres at the vertex are imperfect at aligning with the cylinders, so especially at low $fn things look prety ugly.  This is normal.
-//  include<BOSL2/polyhedra.scad>
-//  $fn=8;
-//  octahedron = regular_polyhedron_info("vnf", name="octahedron", or=20);
-//  vnf_wireframe(octahedron,r=5);
-module vnf_wireframe(vnf, r, d)
+//   include <BOSL2/polyhedra.scad>
+//   $fn=8;
+//   octahedron = regular_polyhedron_info("vnf", name="octahedron", or=20);
+//   vnf_wireframe(octahedron,width=5);
+module vnf_wireframe(vnf, width=1)
 {
-  r = get_radius(r=r,d=d,dflt=1);
   vertex = vnf[0];
   edges = unique([for (face=vnf[1], i=idx(face))
                     sort([face[i], select(face,i+1)])
                  ]);
-  for (e=edges) extrude_from_to(vertex[e[0]],vertex[e[1]]) circle(r=r);
-  move_copies(vertex) sphere(r=r);
+  for (e=edges) extrude_from_to(vertex[e[0]],vertex[e[1]]) circle(d=width);
+  move_copies(vertex) sphere(d=width);
 }
 
 
@@ -931,9 +932,9 @@ function _split_polygons_at_each_y(polys, ys, _i=0) =
 // Section: Debugging Polyhedrons
 
 
-// Module: debug_vertices()
+// Module: _show_vertices()
 // Usage:
-//   debug_vertices(vertices, [size], [disabled=]);
+//   _show_vertices(vertices, [size], [disabled=]);
 // Description:
 //   Draws all the vertices in an array, at their 3D position, numbered by their
 //   position in the vertex array.  Also draws any children of this module with
@@ -946,87 +947,75 @@ function _split_polygons_at_each_y(polys, ys, _i=0) =
 // Example:
 //   verts = [for (z=[-10,10], y=[-10,10], x=[-10,10]) [x,y,z]];
 //   faces = [[0,1,2], [1,3,2], [0,4,5], [0,5,1], [1,5,7], [1,7,3], [3,7,6], [3,6,2], [2,6,4], [2,4,0], [4,6,7], [4,7,5]];
-//   debug_vertices(vertices=verts, size=2) {
+//   _show_vertices(vertices=verts, size=2) {
 //       polyhedron(points=verts, faces=faces);
 //   }
-module debug_vertices(vertices, size=1, disabled=false) {
-    if (!disabled) {
-        color("blue") {
-            dups = vector_search(vertices, EPSILON, vertices);
-            for (ind = dups){
-                numstr = str_join([for(i=ind) str(i)],",");
-                v = vertices[ind[0]];
-                translate(v) {
-                    up(size/8) zrot($vpr[2]) xrot(90) {
-                        linear_extrude(height=size/10, center=true, convexity=10) {
-                            text(text=numstr, size=size, halign="center");
-                        }
-                    }
-                    sphere(size/10);
+module _show_vertices(vertices, size=1) {
+    color("blue") {
+        dups = vector_search(vertices, EPSILON, vertices);
+        for (ind = dups){
+            numstr = str_join([for(i=ind) str(i)],",");
+            v = vertices[ind[0]];
+            translate(v) {
+                rot($vpr) back(size/8){
+                   linear_extrude(height=size/10, center=true, convexity=10) {
+                      text(text=numstr, size=size, halign="center");
+                   }
                 }
+                sphere(size/10);
             }
         }
     }
-    if ($children > 0) {
-        if (!disabled) {
-            color([0.2, 1.0, 0, 0.5]) children();
-        } else {
-            children();
-        }
-    }
 }
 
 
-
-// Module: debug_faces()
-// Usage:
-//   debug_faces(vertices, faces, [size=], [disabled=]);
-// Description:
-//   Draws all the vertices at their 3D position, numbered in blue by their
-//   position in the vertex array.  Each face will have their face number drawn
-//   in red, aligned with the center of face.  All children of this module are drawn
-//   with transparency.
-// Arguments:
-//   vertices = Array of point vertices.
-//   faces = Array of faces by vertex numbers.
-//   ---
-//   size = The size of the text used to label the faces and vertices.  Default: 1
-//   disabled = If true, don't draw numbers, and draw children without transparency.  Default: false.
-// Example(EdgesMed):
-//   verts = [for (z=[-10,10], y=[-10,10], x=[-10,10]) [x,y,z]];
-//   faces = [[0,1,2], [1,3,2], [0,4,5], [0,5,1], [1,5,7], [1,7,3], [3,7,6], [3,6,2], [2,6,4], [2,4,0], [4,6,7], [4,7,5]];
-//   debug_faces(vertices=verts, faces=faces, size=2) {
-//       polyhedron(points=verts, faces=faces);
-//   }
-module debug_faces(vertices, faces, size=1, disabled=false) {
-    if (!disabled) {
-        vlen = len(vertices);
-        color("red") {
-            for (i = [0:1:len(faces)-1]) {
-                face = faces[i];
-                if (face[0] < 0 || face[1] < 0 || face[2] < 0 || face[0] >= vlen || face[1] >= vlen || face[2] >= vlen) {
-                    echo("BAD FACE: ", vlen=vlen, face=face);
-                } else {
-                    verts = select(vertices,face);
-                    c = mean(verts);
-                    v0 = verts[0];
-                    v1 = verts[1];
-                    v2 = verts[2];
-                    dv0 = unit(v1 - v0);
-                    dv1 = unit(v2 - v0);
-                    nrm0 = cross(dv0, dv1);
-                    nrm1 = UP;
-                    axis = vector_axis(nrm0, nrm1);
-                    ang = vector_angle(nrm0, nrm1);
-                    theta = atan2(nrm0[1], nrm0[0]);
-                    translate(c) {
-                        rotate(a=180-ang, v=axis) {
-                            zrot(theta-90)
-                            linear_extrude(height=size/10, center=true, convexity=10) {
-                                union() {
-                                    text(text=str(i), size=size, halign="center");
-                                    text(text=str("_"), size=size, halign="center");
-                                }
+/// Module: _show_faces()
+/// Usage:
+///   _show_faces(vertices, faces, [size=], [disabled=]);
+/// Description:
+///   Draws all the vertices at their 3D position, numbered in blue by their
+///   position in the vertex array.  Each face will have their face number drawn
+///   in red, aligned with the center of face.  All children of this module are drawn
+///   with transparency.
+/// Arguments:
+///   vertices = Array of point vertices.
+///   faces = Array of faces by vertex numbers.
+///   ---
+///   size = The size of the text used to label the faces and vertices.  Default: 1
+///   disabled = If true, don't draw numbers, and draw children without transparency.  Default: false.
+/// Example(EdgesMed):
+///   verts = [for (z=[-10,10], y=[-10,10], x=[-10,10]) [x,y,z]];
+///   faces = [[0,1,2], [1,3,2], [0,4,5], [0,5,1], [1,5,7], [1,7,3], [3,7,6], [3,6,2], [2,6,4], [2,4,0], [4,6,7], [4,7,5]];
+///   _show_faces(vertices=verts, faces=faces, size=2) {
+///       polyhedron(points=verts, faces=faces);
+///   }
+module _show_faces(vertices, faces, size=1) {
+    vlen = len(vertices);
+    color("red") {
+        for (i = [0:1:len(faces)-1]) {
+            face = faces[i];
+            if (face[0] < 0 || face[1] < 0 || face[2] < 0 || face[0] >= vlen || face[1] >= vlen || face[2] >= vlen) {
+                echo("BAD FACE: ", vlen=vlen, face=face);
+            } else {
+                verts = select(vertices,face);
+                c = mean(verts);
+                v0 = verts[0];
+                v1 = verts[1];
+                v2 = verts[2];
+                dv0 = unit(v1 - v0);
+                dv1 = unit(v2 - v0);
+                nrm0 = cross(dv0, dv1);
+                nrm1 = UP;
+                axis = vector_axis(nrm0, nrm1);
+                ang = vector_angle(nrm0, nrm1);
+                theta = atan2(nrm0[1], nrm0[0]);
+                translate(c) {
+                    rotate(a=180-ang, v=axis) {
+                        zrot(theta-90)
+                        linear_extrude(height=size/10, center=true, convexity=10) {
+                            union() {
+                                text(text=str(i), size=size, halign="center");
+                                text(text=str("_"), size=size, halign="center");
                             }
                         }
                     }
@@ -1034,44 +1023,49 @@ module debug_faces(vertices, faces, size=1, disabled=false) {
             }
         }
     }
-    debug_vertices(vertices, size=size, disabled=disabled) {
-        children();
-    }
-    if (!disabled) {
-        echo(faces=faces);
-    }
 }
 
 
 
-// Module: debug_vnf()
+// Module: vnf_debug()
 // Usage:
-//   debug_vnf(vnfs, [convexity=], [txtsize=], [disabled=]);
+//   vnf_debug(vnfs, [faces=], [vertices=], [convexity=], [txtsize=]);
 // Description:
-//   A drop-in module to replace `vnf_polyhedron()` and help debug vertices and faces.
+//   A drop-in module to replace `vnf_polyhedron()` to help debug vertices and faces.
 //   Draws all the vertices at their 3D position, numbered in blue by their
 //   position in the vertex array.  Each face will have its face number drawn
 //   in red, aligned with the center of face.  All given faces are drawn with
 //   transparency. All children of this module are drawn with transparency.
 //   Works best with Thrown-Together preview mode, to see reversed faces.
+//   You can set opacity to 0 if you want to disable the display of the polyhedron faces.  
+//   .
+//   The vertex numbers are shown rotated to face you.  As you rotate your polyhedron you
+//   can rerun the preview to display them oriented for viewing from a different viewpoint.
+// Topics: Polyhedra, Debugging
 // Arguments:
 //   vnf = vnf to display
 //   ---
+//   faces = if true display face numbers.  Default: true
+//   vertices = if true display vertex numbers.  Default: true
+//   opacity = Opacity of the polyhedron faces.  Default: 0.5
 //   convexity = The max number of walls a ray can pass through the given polygon paths.
-//   txtsize = The size of the text used to label the faces and vertices.
+//   size = The size of the text used to label the faces and vertices.  Default: 1
 //   disabled = If true, act exactly like `polyhedron()`.  Default = false.
 // Example(EdgesMed):
 //   verts = [for (z=[-10,10], a=[0:120:359.9]) [10*cos(a),10*sin(a),z]];
 //   faces = [[0,1,2], [5,4,3], [0,3,4], [0,4,1], [1,4,5], [1,5,2], [2,5,3], [2,3,0]];
-//   debug_vnf([verts,faces], txtsize=2);
-module debug_vnf(vnf, convexity=6, txtsize=1, disabled=false) {
-    debug_faces(vertices=vnf[0], faces=vnf[1], size=txtsize, disabled=disabled) {
-        vnf_polyhedron(vnf, convexity=convexity);
-    }
+//   vnf_debug([verts,faces], txtsize=2);
+module vnf_debug(vnf, convexity=6, size=1, faces=true, vertices=true, opacity=0.5) {
+    no_children($children);
+    if (faces)
+      _show_faces(vertices=vnf[0], faces=vnf[1], size=size);
+    if (vertices)
+      _show_vertices(vertices=vnf[0], size=size);
+    color([0.2, 1.0, 0, opacity])
+       vnf_polyhedron(vnf,convexity=convexity);
 }
 
 
-
 // Function&Module: vnf_validate()
 // Usage: As Function
 //   fails = vnf_validate(vnf);