ClipperOffset


Geometric offsetting refers to the process of creating parallel curves that are offset a specified distance from their primary curves.

The ClipperOffset class manages the process of offsetting (inflating/deflating) both open and closed paths using a number of different join types and end types. The library user will rarely need to access this unit directly since it will generally be easier to use the InflatePaths function when doing polygon offsetting.

Notes:

  1. When offsetting closed paths (polygons), a positive offset delta specifies how much outer polygon contours will expand and how much inner "hole" contours will contract. The converse occurs with negative deltas. (Outer polygons should all have the same winding orientation, and holes should have the opposite orientation.)
  2. You cannot offset open paths (polylines) with negative deltas because it's not possible to contract/shrink open paths.
  3. When offsetting, it's important not to confuse EndType.Polygon with EndType.Joined.
    EndType.Polygon should be used when offsetting polygons (closed paths).
    EndType.Joined should be used with polylines (open paths).

  4. Offsetting should not be performed on self-intersecting closed paths as doing so will almost always produce unexpected results.
      PathsD pp { MakePathD({ 40,40, 360,360, 360,40, 40,360 }) };
      PathsD sol = InflatePaths(pp, 40, JoinType::Square, EndType::Polygon);
      
    
            

    Self-intersections must be removed before offsetting, and this can be achieved through a Union clipping operation.
      PathsD pp { MakePathD({ 40,40, 360,360, 360,40, 40,360 }) };
      pp = Union(pp, FillRule::NonZero);
      PathsD sol = InflatePaths(pp, 40, JoinType::Square, EndType::Polygon);  
    
            

  5. It is, however, quite OK to offset self-intersecting open paths (polylines), though the intersecting (ie overlapping) regions will be flattened in the solution polygon. This is demonstrated in the following example:
      PathsD paths = PathsD{ MakePathD({10,10, 100,200, 10,200, 100,10}) };
      PathsD sol = InflatePaths(paths, 10, JoinType::Round, EndType::Round);
      
    
            

  6. When offsetting closed paths (polygons), the orientation of the solution will match the orientation of paths prior to offsetting (unless applying ReverseSolution).
  7. When offsetting open paths (polylines), the solutions will always have Positive orientation.
  8. Path order following offsetting very likely won't match path order prior to offsetting.
  9. While the ClipperOffset class itself won't accept paths with floating point coordinates, the InflatePaths function that encapsulates the functionality of this class will accept paths with floating point coordinates. (The float-integer conversions will be performed by the InflatePaths function.)
  10. Offset solutions will often contain tiny segments that don't contribute to path shape. These tiny segments can cause problems when offset solutions are themselves offset. The shape of these new solutions will degrade, and offsetting performance will slow. So, after offsetting, tiny segments are best removed (see the SimplifyPaths function).

C++ Example:
#include "clipper2/clipper.h"  
...
using namespace Clipper2Lib;

int main()
{
  Paths64 subject;
  subject.push_back(MakePath({ 3480,2570, 3640,1480, 
    3620,1480, 3260,2410, 2950,2190, 2580,880, 
    4400,1290, 3700,1960, 3720,2750 }));
  Paths64 solution;
  ClipperOffset offsetter;
  offsetter.AddPaths(subject, JoinType::Round, EndType::Polygon);
  offsetter.Execute(-70, solution);
  solution = SimplifyPaths(solution, 2.5);
  
  //draw solution ...
  DrawPolygons(solution, 0x4000FF00, 0xFF009900);
}
      

Reference

Methods Properties
AddPath ArcTolerance
AddPaths MiterLimit
Clear ReverseSolution
Constructor
Execute

See Also

InflatePaths, IsPositive, SimplifyPaths, Union, EndType