diff --git a/geometry.scad b/geometry.scad
index e0523c0..76d0799 100644
--- a/geometry.scad
+++ b/geometry.scad
@@ -710,6 +710,31 @@ function is_region(x) = is_list(x) && is_path(x.x);
 //   Closes all paths within a given region.
 function close_region(region, eps=EPSILON) = [for (path=region) close_path(path, eps=eps)];
 
+// Function: check_and_fix_path()
+// Usage:
+//   make_path_valid(path, [valid_dim], [closed])
+// Description:
+//   Checks that the input is a path.  If it is a region with one component, converts it to a path.
+//   valid_dim specfies the allowed dimension of the points in the path.
+//   If the path is closed, removed duplicate endpoint if present.
+// Arguments:
+//   path = path to process
+//   valid_dim = list of allowed dimensions for the points in the path, e.g. [2,3] to require 2 or 3 dimensional input.  If left undefined do not perform this check.  Default: undef
+//   closed = set to true if the path is closed, which enables a check for endpoint duplication
+function make_path_valid(path,valid_dim=undef,closed=false) =
+  let( path = is_region(path) ?
+                  assert(len(path)==1,"Region supplied as path does not have exactly one component")
+                  path[0] :
+              assert(is_path(path), "Input is not a path") path,
+       dim = array_dim(path))
+   assert(dim[0]>1,"Path must have at least 2 points")
+   assert(len(dim)==2,"Invalid path: path is either a list of scalars or a list of matrices")
+   assert(is_def(dim[1]), "Invalid path: entries in the path have variable length")
+   let(valid=is_undef(valid_dim) || in_list(dim[1],valid_dim))
+   assert(valid, str("The points on the path have length ",dim[1]," but length must be ",
+                     len(valid_dim)==1? valid_dim[0] : str("one of ",valid_dim)))
+   closed && approx(path[0],select(path,-1)) ? slice(path,0,-2) : path;
+
 
 // Function: cleanup_region()
 // Usage:
@@ -924,6 +949,18 @@ function _offset_region(
 // Example(2D):
 //   star = star(5, r=100, ir=30);
 //   #stroke(closed=true, star);
+//   stroke(closed=true, offset(star, delta=10, closed=true));
+// Example(2D):
+//   star = star(5, r=100, ir=30);
+//   #stroke(closed=true, star);
+//   stroke(closed=true, offset(star, delta=10, chamfer=true, closed=true));
+// Example(2D):
+//   star = star(5, r=100, ir=30);
+//   #stroke(closed=true, star);
+//   stroke(closed=true, offset(star, r=10, closed=true));
+// Example(2D):
+//   star = star(5, r=100, ir=30);
+//   #stroke(closed=true, star);
 //   stroke(closed=true, offset(star, delta=-10, closed=true));
 // Example(2D):
 //   star = star(5, r=100, ir=30);
@@ -933,46 +970,34 @@ function _offset_region(
 //   star = star(5, r=100, ir=30);
 //   #stroke(closed=true, star);
 //   stroke(closed=true, offset(star, r=-10, closed=true));
-// Example(2D):
-//   star = star(5, r=100, ir=30);
-//   #stroke(closed=true, star);
-//   stroke(closed=true, offset(star, delta=10, closed=true));
-// Example(2D):
-//   star = star(5, r=100, ir=30);
-//   #stroke(closed=true, star);
-//   stroke(closed=true, offset(star, delta=-10, chamfer=true, closed=true));
-// Example(2D):
-//   star = star(5, r=100, ir=30);
-//   #stroke(closed=true, star);
-//   stroke(closed=true, offset(star, r=10, closed=true));
 // Example(2D):  This case needs `quality=2` for success
 //   test = [[0,0],[10,0],[10,7],[0,7], [-1,-3]];
-//   polygon(offset(test,r=1.9, closed=true, quality=2));
-//   //polygon(offset(test,r=1.9, closed=true, quality=1));  // Fails with erroneous 180 deg path error
+//   polygon(offset(test,r=-1.9, closed=true, quality=2));
+//   //polygon(offset(test,r=-1.9, closed=true, quality=1));  // Fails with erroneous 180 deg path error
 //   %down(.1)polygon(test);
 // Example(2D): This case fails if `check_valid=true` when delta is large enough because segments are too close to the opposite side of the curve.  
 //   star = star(5, r=22, ir=13);
-//   stroke(star,width=.1,closed=true);                                                           
+//   stroke(star,width=.2,closed=true);                                                           
 //   color("green")
-//     stroke(offset(star, delta=9, closed=true),width=.1,closed=true); // Works with check_valid=true (the default)
+//     stroke(offset(star, delta=-9, closed=true),width=.2,closed=true); // Works with check_valid=true (the default)
 //   color("red")
-//     stroke(offset(star, delta=10, closed=true, check_valid=false),   // Fails if check_valid=true 
-//            width=.1,closed=true); 
+//     stroke(offset(star, delta=-10, closed=true, check_valid=false),   // Fails if check_valid=true 
+//            width=.2,closed=true); 
 // Example(2D): But if you use rounding with offset then you need `check_valid=true` when `r` is big enough.  It works without the validity check as long as the offset shape retains a some of the straight edges at the star tip, but once the shape shrinks smaller than that, it fails.  There is no simple way to get a correct result for the case with `r=10`, because as in the previous example, it will fail if you turn on validity checks.  
 //   star = star(5, r=22, ir=13);
 //   color("green")
-//     stroke(offset(star, r=8, closed=true,check_valid=false), width=.1, closed=true);
+//     stroke(offset(star, r=-8, closed=true,check_valid=false), width=.1, closed=true);
 //   color("red")
-//     stroke(offset(star, r=10, closed=true,check_valid=false), width=.1, closed=true);
+//     stroke(offset(star, r=-10, closed=true,check_valid=false), width=.1, closed=true);
 // Example(2D): The extra triangles in this example show that the validity check cannot be skipped
-//   ellipse = scale([20,4], p=circle(r=1));
+//   ellipse = scale([20,4], p=circle(r=1,$fn=64));
 //   stroke(ellipse, closed=true, width=0.3);
 //   stroke(offset(ellipse, r=-3, check_valid=false, closed=true), width=0.3, closed=true);
 // Example(2D): The triangles are removed by the validity check
-//   ellipse = scale([20,4], p=circle(r=1));
+//   ellipse = scale([20,4], p=circle(r=1,$fn=64));
 //   stroke(ellipse, closed=true, width=0.3);
 //   stroke(offset(ellipse, r=-3, check_valid=true, closed=true), width=0.3, closed=true);
-// Example(2D):
+// Example(2D): Open path.  The path moves from left to right and the positive offset shifts to the left of the initial red path.
 //   sinpath = 2*[for(theta=[-180:5:180]) [theta/4,45*sin(theta)]];
 //   #stroke(sinpath);
 //   stroke(offset(sinpath, r=17.5));
@@ -1010,7 +1035,8 @@ function offset(
 	let(
 		chamfer = is_def(r) ? false : chamfer,
 		quality = max(0,round(quality)),
-		d = is_def(r)? r : delta,
+                flip_dir = closed && !polygon_clockwise(path) ? -1 : 1,
+		d = flip_dir * (is_def(r) ? r : delta),
 		shiftsegs = [for(i=[0:len(path)-1]) _shift_segment(select(path,i,i+1), d)],
 		// good segments are ones where no point on the segment is less than distance d from any point on the path
 		good = check_valid ? _good_segments(path, abs(d), shiftsegs, closed, quality) : replist(true,len(shiftsegs)),
diff --git a/rounding.scad b/rounding.scad
index d966fbc..008f76c 100644
--- a/rounding.scad
+++ b/rounding.scad
@@ -374,10 +374,10 @@ function bezier_curve(P,N) =
 //   - "steps" - number of vertical steps to use for the roundover.  Default: 16.
 //   - "offset_maxstep" - maxstep distance for offset() calls; controls the horizontal step density.  Default: 1
 //   - "offset" - select "round" (r=) or "delta" (delta=) offset type for offset.  Default: "round"
-//
+//   
 //   You can change the the defaults by passing an argument to the rounded_sweep, which is more convenient if you want
 //   a setting to be the same at both ends.  
-//
+//   
 //   You can use several helper functions to provide the rounding spec.  These use function arguments to set the same parameters listed above, where the
 //   function name indicates the type of rounding and only parameters valid for that rounding type are accepted:
 //   - rs_circle(r,cut,extra,check_valid, quality,steps, offset_maxstep, offset)
@@ -385,11 +385,11 @@ function bezier_curve(P,N) =
 //   - rs_chamfer(height, width, cut, extra,check_valid, quality,steps, offset_maxstep, offset)
 //   - rs_smooth(cut, joint, extra,check_valid, quality,steps, offset_maxstep, offset)
 //   - rs_custom(points, extra,check_valid, quality,steps, offset_maxstep, offset)
-// 
+//   
 //   For example, you could round a path using `rounded_sweep(path, top=rs_teardrop(r=10), bottom=rs_chamfer(height=-10,extra=1))`
 //   Many of the arguments are described as setting "default" values because they establish settings which may be overridden by 
 //   the top and bottom rounding specifications.  
-//
+//   
 // Arguments:
 //   path = 2d path (list of points) to extrude
 //   height = total height (including rounded portions, but not extra sections) of the output
@@ -408,7 +408,7 @@ function bezier_curve(P,N) =
 //   joint = default joint value for smooth roundover.
 //   k = default curvature parameter value for "smooth" roundover
 //   convexity = convexity setting for use with polyhedron.  Default: 10
-//
+//   
 // Example: Rounding a star shaped prism with postive radius values
 //   star = star(5, r=22, ir=13);
 //   rounded_star = round_corners(zip(star, flatten(replist([.5,0],5))), curve="circle", measure="cut", $fn=12);
@@ -441,7 +441,7 @@ function bezier_curve(P,N) =
 //   roundbox = round_corners(smallbox, curve="smooth", measure="cut", size=4, $fn=36);
 //   thickness=4;
 //   height=50;
-//   back_half(y=37, s=200)
+//   back_half(y=25, s=200)
 //     difference(){
 //       rounded_sweep(roundbox, height=height, bottom=["r",10,"type","teardrop"], top=["r",2], steps = 22, check_valid=false);
 //       up(thickness)
@@ -450,6 +450,24 @@ function bezier_curve(P,N) =
 //                       bottom=["r",6],
 //                       top=["type","chamfer","angle",30,"height",-3,"extra",1,"check_valid",false]); 
 //     }
+// Example: A box with multiple sections and rounded dividers
+//   thickness = 2;
+//   box = ([[0,0], [0,50], [255,50], [255,0]]);
+//   cutpoints = [0, 125, 190, 255];
+//   rbox = round_corners(box, curve="smooth", measure="cut", size=4, $fn=36);
+//   back_half(y=25, s=700)
+//     difference(){
+//       rounded_sweep(rbox, height=50, check_valid=false, steps=22, bottom=rs_teardrop(r=2), top=rs_circle(r=1));
+//       up(thickness)
+//         for(i=[0:2]){
+//           ofs = i==1 ? 2 : 0;
+//           hole = round_corners([[cutpoints[i]-ofs,0], [cutpoints[i]-ofs,50], [cutpoints[i+1]+ofs, 50], [cutpoints[i+1]+ofs,0]],
+//                                curve="smooth", measure="cut", size=4, $fn=36);
+//           rounded_sweep(offset(hole, r=-thickness, closed=true,check_valid=false),
+//                         height=48, steps=22, check_valid=false, bottom=rs_circle(r=4), top=rs_circle(r=-1,extra=1));
+//   
+//         }
+//     }
 // Example: Star shaped box
 //   star = star(5, r=22, ir=13);
 //   rounded_star = round_corners(zip(star, flatten(replist([.5,0],5))), curve="circle", measure="cut", $fn=12);
@@ -458,7 +476,7 @@ function bezier_curve(P,N) =
 //   difference(){
 //     rounded_sweep(rounded_star, height=ht, bottom=["r",4], top=["r",1], steps=15);
 //     up(thickness)
-//         rounded_sweep(offset(rounded_star,r=thickness,closed=true),
+//         rounded_sweep(offset(rounded_star,r=-thickness,closed=true),
 //                       height=ht-thickness, check_valid=false,
 //                       bottom=rs_circle(r=7), top=rs_circle(r=-1, extra=1));
 //     }
@@ -488,7 +506,7 @@ function bezier_curve(P,N) =
 //       up(1)
 //         rounded_sweep(offset(rhex,r=1), height=9.5, bottom=rs_circle(r=2), top=rs_teardrop(r=-4));
 //     }
-module rounded_sweep(path, height, top=[], bottom=[], offset="round", r=undef, steps=16, quality=1, check_valid=true, offset_maxstep=1, extra=0, 
+module rounded_sweep(path, height, top=[], bottom=[], offset="round", r=0, steps=16, quality=1, check_valid=true, offset_maxstep=1, extra=0, 
                      cut=undef, width=undef, joint=undef, k=0.75, angle=45, convexity=10)
 {
     // This function does the actual work of repeatedly calling offset() and concatenating the resulting face and vertex lists to produce
@@ -514,13 +532,13 @@ module rounded_sweep(path, height, top=[], bottom=[], offset="round", r=undef, s
 
     // Produce edge profile curve from the edge specification
     // z_dir is the direction multiplier (1 to build up, -1 to build down)
-    function rounding_offsets(edgespec,flipR,z_dir=1) =
+    function rounding_offsets(edgespec,z_dir=1) =
       let( 
         edgetype = struct_val(edgespec, "type"),
         extra = struct_val(edgespec,"extra"),
         N = struct_val(edgespec, "steps"),
-        r = flipR * struct_val(edgespec,"r"),
-        cut = flipR * struct_val(edgespec,"cut"),
+        r = struct_val(edgespec,"r"),
+        cut = struct_val(edgespec,"cut"),
         k = struct_val(edgespec,"k"),
         radius = in_list(edgetype,["circle","teardrop"]) ?
                         first_defined([cut/(sqrt(2)-1),r]) : 
@@ -528,10 +546,10 @@ module rounded_sweep(path, height, top=[], bottom=[], offset="round", r=undef, s
                  undef,
         chamf_angle = struct_val(edgespec, "angle"),
         cheight = struct_val(edgespec, "height"),
-        cwidth = flipR * struct_val(edgespec, "width"),
+        cwidth = struct_val(edgespec, "width"),
         chamf_width = first_defined([cut/cos(chamf_angle), cwidth, cheight*tan(chamf_angle)]),
         chamf_height = first_defined([cut/sin(chamf_angle),cheight, cwidth/tan(chamf_angle)]),
-        joint = first_defined([flipR*struct_val(edgespec,"joint"),
+        joint = first_defined([struct_val(edgespec,"joint"),
                                16*cut/sqrt(2)/(1+4*k)]),
         points = struct_val(edgespec, "points"), 
         argsOK = in_list(edgetype,["circle","teardrop"]) ? is_def(radius) :
@@ -541,7 +559,7 @@ module rounded_sweep(path, height, top=[], bottom=[], offset="round", r=undef, s
                  false)
     assert(argsOK,str("Invalid specification with type ",edgetype))
     let(
-        offsets =  edgetype == "custom" ? scale([-flipR,z_dir], slice(points,1,-1)) :
+        offsets =  edgetype == "custom" ? scale([-1,z_dir], slice(points,1,-1)) :
                    edgetype == "chamfer" ?  width==0 && height==0 ? [] : [[-chamf_width,z_dir*abs(chamf_height)]] :
                    edgetype == "teardrop" ? radius==0 ? [] : concat([for(i=[1:N]) [radius*(cos(i*45/N)-1),z_dir*abs(radius)* sin(i*45/N)]],
                                    [[-2*radius*(1-sqrt(2)/2), z_dir*abs(radius)]]):
@@ -554,8 +572,8 @@ module rounded_sweep(path, height, top=[], bottom=[], offset="round", r=undef, s
       extra > 0 ? concat(offsets, [select(offsets,-1)+[0,z_dir*extra]]) : offsets;
 
   
-  argspec = [["r",0],
-             ["extra",0],
+  argspec = [["r",r],
+             ["extra",extra],
              ["type","circle"],
              ["check_valid",check_valid],
              ["quality",quality],
@@ -570,13 +588,13 @@ module rounded_sweep(path, height, top=[], bottom=[], offset="round", r=undef, s
              ["k", k],
              ["points", []],
             ];
+
+  path = check_and_fix_path(path, [2], closed=true);
+  
   top = struct_set(argspec, top, grow=false);
   bottom = struct_set(argspec, bottom, grow=false);
 
-  struct_echo(top,"top");
-  
   clockwise = polygon_clockwise(path);
-  flipR = clockwise ? 1 : -1;
 
   assert(height>=0, "Height must be nonnegative");
 
@@ -587,11 +605,9 @@ module rounded_sweep(path, height, top=[], bottom=[], offset="round", r=undef, s
   assert(offsetsok,"Offsets must be one of \"round\" or \"delta\"");
   */
   
-  offsets_bot = rounding_offsets(bottom, flipR,-1);
-  offsets_top = rounding_offsets(top, flipR,1);
+  offsets_bot = rounding_offsets(bottom, -1);
+  offsets_top = rounding_offsets(top, 1);
 
-  echo(ofstop = offsets_top);
-  
   // "Extra" height enlarges the result beyond the requested height, so subtract it
   bottom_height = len(offsets_bot)==0 ? 0 : abs(select(offsets_bot,-1)[1]) - struct_val(bottom,"extra");
   top_height = len(offsets_top)==0 ? 0 : abs(select(offsets_top,-1)[1]) - struct_val(top,"extra");
@@ -616,11 +632,6 @@ module rounded_sweep(path, height, top=[], bottom=[], offset="round", r=undef, s
   up(bottom_height)
     polyhedron(concat(vertices_faces_bot[0],vertices_faces_top[0]),
                faces=concat(vertices_faces_bot[1], vertices_faces_top[1], middle_faces),convexity=convexity);
-  echo(botv=vertices_faces_bot[0]);
-  echo(topv=vertices_faces_top[0]);
-  echo(fbot=vertices_faces_bot[1]);
-  echo(ftop=vertices_faces_top[1]);
-  echo(fmid=middle_faces);
 }
 
 function rs_circle(r,cut,extra,check_valid, quality,steps, offset_maxstep, offset) =