Menu

documentation

Timo Kähkönen

Clipper 6 Documentation

This is Javascript Clipper 6 documentation. Unfortunately there is no documentation for Javascript Clipper 5. If you need Clipper 5 docs, please download C# Clipper 5 and check the documentation folder.

If you are migrating from Javascript Clipper 5 to 6, please read the migration guide.


Table of Contents


Overview

The Javascript Clipper Library performs clipping and offsetting of both lines and polygons.

A number of features set Clipper apart from other clipping libraries:

  • it accepts all types of polygons including self-intersecting ones
  • it supports multiple polygon filling rules (EvenOdd, NonZero, Positive, Negative)
  • it's very fast relative to other libraries
  • it also performs line and polygon offsetting
  • it's numerically robust
  • it's free to use in both freeware and commercial applications

Current Javascript Clipper version: 6.4.2.2 (C# 6.4.2)

Original C# version's Author & copyright:
Angus Johnson. Copyright © 2010-2017
License, terms and conditions: Boost Software License

Javascript Clipper's Author & copyright:
Timo Kähkönen. Copyright © 2012-2017
License, terms and conditions: Boost Software License

Javascript Clipper uses implementation of Tom Wu's JSBN library, which has BSD license.

Terminology:

  • Clipping: commonly refers to the process of removing (cutting away) from a set of 2-dimensional geometric shapes those parts that are outside a rectangular 'clipping' window. This can be achieved by intersecting subject paths (lines and polygons) with the clipping rectangle. In a more general sense, the clipping window need not be rectangular but can be any type of polygon, even multiple polygons. Also, while clipping typically refers to an intersection operation, in this documentation it will refer to any one of the four boolean operations (intersection, union, difference and exclusive-or).
  • Path: is an ordered sequence of vertices defining a single geometric contour that's either a line (an open path) or a polygon (a closed path).
  • Contour: synonymous with path.
  • Line: or polyline is an open path containing 2 or more vertices.
  • Polygon: in a general sense is a two-dimensional region that's bounded by an outer closed path and containing zero to many 'holes'. However in this documentation polygon refers to a Path that's known to be closed.
  • Hole: is a closed region within a polygon that's not part of the polygon. A polygon that forms the outer boundaries of a hole is called a hole polygon.
  • Polygon Filling Rule: together with a list of paths, the filling rule defines those regions bounded by paths that are inside polygons (ie 'filled' in a graphical display) and those which are outside.

Distribution package contents:

The ZIP package contains the Clipper library's source code as minified and unminified. The library was initially written in Delphi Pascal, but was then made available also in C++, C# and Python. The library's source code in each language is about 5000 lines. Javascript implementation is longer, about 7625 lines due to JSBN library and some helper functions.

Demo applications and examples are not included in the distribution package. They can be accessed here. The sample applications show how Clipper can be used with SVG and Canvas.

Download Link:

SourceForge

References:

Read about references regarding clipping and offsetting algorithms.

See also:
OffsetPaths, ClipType, Path, PolyFillType


Preprocessor defines

Boolean ClipperLib.use_int32
Boolean ClipperLib.use_xyz
Boolean ClipperLib.use_lines
Boolean ClipperLib.use_deprecated

ClipperLib.use_int32:
Not implemented in Javascript.

ClipperLib.use_xyz:
Adds a 'Z' member to IntPoint with only a minor cost to perfomance. For more details see Clipper's Clipper.ZFillFunction property. (Disabled by default)

ClipperLib.use_lines:
Enables open path (line) clipping. If line clipping is disabled, there's generally a very small (ie ~5%) improvement in performance. (Enabled by default)

ClipperLib.use_deprecated:
Enables code developed with versions of Clipper prior to version 6 to compile without changes. This exposes compatibility code that will be removed in a future update. (Enabled by default)

Usage:

ClipperLib.use_xyz = true;
ClipperLib.use_lines = true;
ClipperLib.use_deprecated = true;

See also:
Clipper.ZFillFunction, IntPoint


ClipperBase

ClipperBase is an abstract base class for Clipper. A ClipperBase object should not be instantiated directly.


--- ClipperBase methods ---


ClipperBase.AddPath()

Boolean AddPath(Path pg, PolyType polyType, Boolean closed);

Any number of subject and clip paths can be added to a clipping task, either individually via the AddPath() method, or as groups via the AddPaths() method, or even using both methods.

'Subject' paths may be either open (lines) or closed (polygons) or even a mixture of both, but 'clipping' paths must always be closed. Clipper allows polygons to clip both lines and other polygons, but doesn't allow lines to clip either lines or polygons.

With closed paths, orientation should conform with the filling rule that will be passed via Clipper's Execute method.

Path Coordinate range:
Path coordinates must be between ± 4503599627370495 (sqrt(2^106 -1)/2), otherwise a range error will be thrown when attempting to add the path to the Clipper object. If coordinates can be kept between ± 47453132 (sqrt(2^53 -1)/2), an increase in performance (approx. 40-50%) over the larger range can be achieved by avoiding large integer math.

Return Value:
The function will return false if the path is empty or almost empty. A path is almost empty when:

  • it has less than 2 vertices.
  • it has 2 vertices but is not an open path
  • the vertices are all co-linear and it is not an open path

Usage:

var cpr = new ClipperLib.Clipper();
var path = [{"X":10,"Y":10},{"X":110,"Y":10},{"X":110,"Y":110},{"X":10,"Y":110}];
cpr.AddPath(path, ClipperLib.PolyType.ptSubject, true);

See also:
Example, Clipper.Execute, AddPaths, Orientation, Defines, Path, PolyFillType, PolyType


ClipperBase.AddPaths()

Boolean AddPaths(Paths ppg, PolyType polyType, Boolean closed);

Same functionality as in AddPath(), but the parameter is Paths.

Usage:

var cpr = new ClipperLib.Clipper();
var paths = [[{X:10,Y:10},{X:110,Y:10},{X:110,Y:110},{X:10,Y:110}],
             [{X:20,Y:20},{X:20,Y:100},{X:100,Y:100},{X:100,Y:20}]];;
cpr.AddPaths(paths, ClipperLib.PolyType.ptSubject, true);

See also:
Example, Clipper.Execute, AddPath, Orientation, Defines, Paths, PolyFillType, PolyType


ClipperBase.Clear()

void Clear();

The Clear method removes any existing subject and clip polygons allowing the Clipper object to be reused for clipping operations on different polygon sets.

Usage:

cpr.Clear();


Clipper

The Clipper class encapsulates boolean operations on polygons (intersection, union, difference and XOR), which is also called polygon clipping.

Input polygons, both subject and clip sets, are passed to a Clipper object by its AddPath and AddPaths methods, and the clipping operation is performed by calling its Execute method. Multiple boolean operations can be performed on the same input polygon sets by repeat calls to Execute.

See also:

Overview, ClipType


--- Clipper methods ---


ClipperLib.Clipper()

Clipper Clipper(InitOptions initOptions = 0);

The Clipper constructor creates an instance of the Clipper class. One or more InitOptions may be passed as a parameter to set the corresponding properties. (These properties can still be set or reset after construction.)

Usage:

var cpr = new ClipperLib.Clipper();
// or
var cpr = new ClipperLib.Clipper(ClipperLib.Clipper.ioStrictlySimple | ClipperLib.Clipper.ioPreserveCollinear);
// or
var cpr = new ClipperLib.Clipper(2 | 4);

See also:
PreserveCollinear, ReverseSolution, StrictlySimple, InitOptions


ClipperLib.Clipper.Area()

Number Area(Path poly)

This function returns the area of the supplied polygon. (It's assumed that the path will be closed.) Depending on orientation, this value may be positive or negative. If Orientation is true, then the area will be positive and conversely, if Orientation is false, then the area will be negative.

Usage:

var area = ClipperLib.Clipper.Area(polygon);

See also:
Orientation, Path


ClipperLib.Clipper.CleanPolygon()

Path CleanPolygon(Path path, Number distance)

This function is needed to prevent distortion that is caused by too near vertices and/or micro-self-interserctions.

Removes vertices:

  • that join co-linear edges, or join edges that are almost co-linear (such that if the vertex was moved no more than the specified distance the edges would be co-linear)

  • that are within the specified distance of an adjacent vertex

  • that are within the specified distance of a semi-adjacent vertex together with their out-lying vertices

Vertices are semi-adjacent when they are separated by a single (out-lying) vertex.

The distance parameter's default value is approximately √2 so that a vertex will be removed when adjacent or semi-adjacent vertices having their corresponding X and Y coordinates differing by no more than 1 unit. (If the egdes are semi-adjacent the out-lying vertex will be removed too.)

Timo: According to tests, the most proper distance value to remove artifacts before offsetting is 0.1 * scale.

Usage:

var path = [{"X":10,"Y":10},{"X":11,"Y":11},{"X":110,"Y":10},{"X":110,"Y":110},
{"X":10,"Y":110}]; 
var cleaned_path = ClipperLib.Clipper.CleanPolygon(path, 1.1);
// point {"X":11,"Y":11} is now removed

See also:
CleanPolygons, SimplifyPolygon, Path


ClipperLib.Clipper.CleanPolygons()

Paths CleanPolygons(Paths polys, Number distance)

Same functionality as in CleanPolygon, but the parameter is of type Paths.

According to tests, the most proper distance value to remove artifacts before offsetting is 0.1 * scale

Read more in CleanPolygon.

Usage:

var paths = [[{X:10,Y:10},{X:11,Y:11},{X:110,Y:10},{X:110,Y:110},{X:10,Y:110}],
             [{X:20,Y:20},{X:20,Y:100},{X:100,Y:100},{X:100,Y:20}]];
var cleaned_paths = ClipperLib.Clipper.CleanPolygons(paths, 1.1);
// point {"X":11,"Y":11} is removed

See also:
CleanPolygon, SimplifyPolygons


ClipperLib.Clipper.ClosedPathsFromPolyTree()

Paths ClosedPathsFromPolyTree(PolyTree polytree)

This function filters out open paths from the PolyTree structure and returns only closed paths in a Paths structure.

Usage:

// ... polytree is populated automatically by Execute()
var polygons = ClipperLib.Clipper.ClosedPathsFromPolyTree(polytree);

See also:
PolyTree, Paths


ClipperLib.Clipper.Execute()

Boolean Execute(ClipType clipType,
  Paths solution,
  PolyFillType subjFillType,
  PolyFillType clipFillType);

Boolean Execute(ClipType clipType,
  PolyTree solution,
  PolyFillType subjFillType,
  PolyFillType clipFillType);

Once subject and clip paths have been assigned (via AddPath and/or AddPaths), Execute can then perform the clipping operation (intersection, union, difference or XOR) specified by the clipType parameter.

The solution parameter can be either a Paths or PolyTree structure. The Paths structure is simpler and faster (roughly 10%) than the PolyTree stucture. PolyTree holds information of parent-child relationchips of paths and also whether they are open or closed.

When a PolyTree object is used in a clipping operation on open paths, two ancilliary functions have been provided to quickly separate out open and closed paths from the solution - OpenPathsFromPolyTree and ClosedPathsFromPolyTree. PolyTreeToPaths is also available to convert path data to a Paths structure (irrespective of whether they're open or closed).

There are several things to note about the solution paths returned:

  • they aren't in any specific order
  • they should never overlap or be self-intersecting (but see notes on rounding)
  • holes will be oriented opposite outer polygons
  • the solution fill type can be considered either EvenOdd or NonZero since it will comply with either filling rule
  • polygons may rarely share a common edge (though this is now very rare as of version 6)

The subjFillType and clipFillType parameters define the polygon fill rule to be applied to the polygons (ie closed paths) in the subject and clip paths respectively. (It's usual though obviously not essential that both sets of polygons use the same fill rule.)

Execute can be called multiple times without reassigning subject and clip polygons (ie when different clipping operations are required on the same polygon sets).

Usage:

function DrawPolygons(paths, color)
{/* ... */}

function Main(args)
{
  var subj = [[{X:10,Y:10},{X:110,Y:10},{X:110,Y:110},{X:10,Y:110}],
                  [{X:20,Y:20},{X:20,Y:100},{X:100,Y:100},{X:100,Y:20}]]; 
  var clip = [[{X:50,Y:50},{X:150,Y:50},{X:150,Y:150},{X:50,Y:150}],
                  [{X:60,Y:60},{X:60,Y:140},{X:140,Y:140},{X:140,Y:60}]];   
  DrawPolygons(subj, 0x8033FFFF);
  DrawPolygons(clip, 0x80FFFF33);

  var solution = new ClipperLib.Paths();
  var c = new ClipperLib.Clipper();
  c.AddPaths(subj, ClipperLib.PolyType.ptSubject, true);
  c.AddPaths(clips, ClipperLib.PolyType.ptClip, true);
  c.Execute(ClipperLib.ClipType.ctIntersection, solution);

  DrawPolygons(solution, 0x40808080);
}
Main();

See also:
Rounding, ClipperBase.AddPath, ClipperBase.AddPaths, PolyNode.IsOpen, PolyTree, ClosedPathsFromPolyTree, OpenPathsFromPolyTree, PolyTreeToPaths, ClipType, Path, Paths, PolyFillType


ClipperLib.Clipper.GetBounds()

IntRect GetBounds(Paths paths);

This method returns the axis-aligned bounding rectangle of paths.

Usage:

var paths = [[{"X":10,"Y":10},{"X":110,"Y":10},{"X":110,"Y":110},{"X":10,"Y":110}]];
var bounds = ClipperLib.Clipper.GetBounds(paths);
// bounds is {"left":10,"top":10,"right":110,"bottom":110}

See also:
Example, IntRect


ClipperLib.Clipper.MinkowskiDiff()

Paths MinkowskiDiff(Path poly, Path path, Boolean isClosed)

Minkowski Difference is performed by subtracting each point in a polygon from the set of points in an open or closed path. A key feature of Minkowski Difference is that when it's applied to two polygons, the resulting polygon will contain the coordinate space origin whenever the two polygons touch or overlap. (This function is often used to determine when polygons collide.)

See also:
MinkowskiSum, Path, Paths


ClipperLib.Clipper.MinkowskiSum()

Paths MinkowskiSum(Path pattern, Path path, Boolean pathIsClosed)
Paths MinkowskiSum(Path pattern, Paths paths, PolyFillType pathFillType, Boolean pathIsClosed)

Minkowski Addition is performed by adding each point in a polygon 'pattern' to the set of points in an open or closed path. The resulting polygon (or polygons) defines the region that the 'pattern' would pass over in moving from the beginning to the end of the 'path'.

Usage:

// Star shape ...
var path = [{"X":89.85,"Y":355.85},{"X":131.72,"Y":227.13},{"X":22.1,"Y":147.57},{"X":157.6,"Y":147.57},{"X":199.47,"Y":18.85},{"X":241.34,"Y":147.57},{"X":376.84,"Y":147.57},{"X":267.22,"Y":227.13},{"X":309.09,"Y":355.85},{"X":199.47,"Y":276.29}];
// Diagonal brush shape ...
var shape = [{"X":4,"Y":-6},{"X":6,"Y":-6},{"X":-4,"Y":6},{"X":-6,"Y":6}];
var solution = ClipperLib.Clipper.MinkowskiSum(shape, path, true);

See also:
MinkowskiDiff, Path, Paths


ClipperLib.Clipper.OffsetPaths()

Paths OffsetPaths(Paths polys, Number delta, JoinType jointype = JoinType.jtSquare, EndType endtype = EndType.etClosed, Number limit)

Deprecated. (See ClipperOffset.)

This function offsets the 'polys' parameter by the 'delta' amount. 'polys' may be open or closed paths. With closed paths (polygons), positive delta values 'expand' outer contours and 'shrink' inner 'hole' contours. Negative deltas do the reverse. With open paths (lines), the sign of the delta value is ignored since it's not possible to 'shrink' open paths.

Edge joins may be one of three jointypes - jtMiter, jtSquare or jtRound. (See the image below for examples.)

The meaning and use of the limit parameter depends on jointype:

  • jtMiter: limit sets the maximum distance in multiples of delta that vertices can be offset from their original positions before squaring is applied. The default value is 2 (ie twice delta) which is also the smallest allowed value. If the angle is acute enough to require squaring, then squaring will occur at 1 times delta. If offsetting was allowed without any limits (ie without squaring), then offsetting at very acute angles would produce unacceptably long 'spikes'.

  • jtRound: limit sets the maximum distance that rounded joins can deviate from their true arcs (since it would require an infinite number of vertices to perfectly represent an arc). The default limit is 0.25 units though realistically precision can never be better than 0.5 since arc coordinates will still be rounded to integer values. When offsetting polygons with very large coordinate values (typically as a result of scaling), it's advisable to increase limit to maintain consistent precisions at all joins because the maximum number of vertices allowed in any arc is 222. (This hard coded upper limit has been chosen because the imprecision in a circle constructed with 222 vertices will be only 1/10000th its radius and, not only is creating very large numbers of arc vertices computationally expensive, it can cause out-of-memory problems.)

  • jtSquare: The limit parameter is ignored since squaring will be applied uniformally at 1 times delta.

Self-intersections in closed paths must be removed before the paths are passed to OffsetPaths.

Usage:

var paths = [[{"X":224,"Y":146},{"X":224,"Y":213},{"X":201,"Y":191},{"X":179,"Y":235},{"X":134,"Y":191},{"X":179,"Y":168},{"X":157,"Y":146}]];
var offset_paths = ClipperLib.Clipper.OffsetPaths(paths, 10, ClipperLib.JoinType.jtRound, ClipperLib.EndType.etClosed, 0.25);

See also:
ClipperOffset, ClipperOffset.JoinType, Path


ClipperLib.Clipper.OpenPathsFromPolyTree()

Paths OpenPathsFromPolyTree(PolyTree polytree)

This function filters out closed paths from the PolyTree structure and returns only open paths in a Paths structure.

Usage:

// ... polytree is populated automatically by Execute()
var lines = ClipperLib.Clipper.OpenPathsFromPolyTree(polytree);

See also:
PolyTree, Paths


ClipperLib.Clipper.Orientation()

Boolean Orientation(Path poly)

Returns true, if polygon area is >=0.

Orientation is only important to closed paths. Given that vertices are declared in a specific order, orientation refers to the direction (clockwise or counter-clockwise) that these vertices progress around a closed path.

Orientation is also dependent on axis direction:

  • On Y-axis positive upward displays, Orientation will return true if the polygon's orientation is counter-clockwise.

  • On Y-axis positive downward displays, Orientation will return true if the polygon's orientation is clockwise.

Notes:

Usage:

var orientation = ClipperLib.Clipper.Orientation(polygon);

See also:
Area, Clipper.ReverseSolution, Path


ClipperLib.Clipper.PointInPolygon()

Number PointInPolygon(IntPoint pt, Path poly)

Returns 0 if false, -1 if pt is on poly and +1 if pt is in poly.

Usage:

var poly = [{X:10,Y:10},{X:110,Y:10},{X:110,Y:110},{X:10,Y:110}];
var pt = new ClipperLib.IntPoint(50,50);
var inpoly = ClipperLib.Clipper.PointInPolygon(pt, poly);
// inpoly is 1, which means that pt is in polygon

See also:
IntPoint, Path


ClipperLib.Clipper.PolyTreeToPaths()

Paths PolyTreeToPaths(PolyTree polytree)

This function converts a PolyTree structure into a Paths structure (whether they are open or closed). To differentiate open and closed paths, use OpenPathsFromPolyTree or ClosedPathsFromPolyTree.

Usage:

// ... polytree is populated automatically by Execute()
var paths = ClipperLib.Clipper.PolyTreeToPaths(polytree);

See also:
PolyTree, Paths


ClipperLib.Clipper.ReversePath()

// Call Path.reverse().

Reverses the vertex order (and hence orientation) in a path.

Usage:

var path = [{"X":10,"Y":10},{"X":110,"Y":10},{"X":110,"Y":110},{"X":10,"Y":110}];
path.reverse();
// path is now [[{"X":10,"Y":110},{"X":110,"Y":110},{"X":110,"Y":10},{"X":10,"Y":10}]]

ClipperLib.Clipper.ReversePaths()

void ReversePaths(Paths p)

Reverses the vertex order (and hence orientation) in each contained path.

Usage:

var paths = [[{"X":10,"Y":10},{"X":110,"Y":10},{"X":110,"Y":110},{"X":10,"Y":110}]];
ClipperLib.Clipper.ReversePaths(paths);
// paths is now [[{"X":10,"Y":110},{"X":110,"Y":110},{"X":110,"Y":10},{"X":10,"Y":10}]]


ClipperLib.Clipper.SimplifyPolygon()

Paths SimplifyPolygon(Path poly, PolyFillType fillType = PolyFillType.pftEvenOdd)

Removes self-intersections from the supplied polygon (by performing a boolean union operation using the nominated PolyFillType).

Polygons with non-contiguous duplicate vertices (ie 'touching') will be split into two polygons.

Usage:

// five-pointed star with self-intersections...
var five_pointed_star = [{"X":147,"Y":313},{"X":247,"Y":34},{"X":338,"Y":312},{"X":86,"Y":123},{"X":404,"Y":124}];
var ten_pointed_star = ClipperLib.Clipper.SimplifyPolygon(five_pointed_star, ClipperLib.PolyFillType.pftNonZero);
// ten_pointed_star is a ten-pointed star with no self-intersections
var fifteen_pointed_star = ClipperLib.Clipper.SimplifyPolygon(five_pointed_star, ClipperLib.PolyFillType.pftEvenOdd);
// fifteen_pointed_star is a fifteen-pointed star with no self-intersections

See also:
Clipper.StrictlySimple, CleanPolygon, Path, PolyFillType


ClipperLib.Clipper.SimplifyPolygons()

Paths SimplifyPolygons(Paths polys, PolyFillType fillType = PolyFillType.pftEvenOdd)

The same functionality as in SimplifyPolygon, but the parameter is of type Paths.

Usage:

// five-pointed star with self-intersections...
var five_pointed_star = [[{"X":147,"Y":313},{"X":247,"Y":34},{"X":338,"Y":312},{"X":86,"Y":123},{"X":404,"Y":124}]];
var ten_pointed_star = ClipperLib.Clipper.SimplifyPolygons(five_pointed_star, ClipperLib.PolyFillType.pftNonZero);
// ten_pointed_star is a ten-pointed star with no self-intersections
var fifteen_pointed_star = ClipperLib.Clipper.SimplifyPolygon(five_pointed_star, ClipperLib.PolyFillType.pftEvenOdd);
// fifteen_pointed_star is a fifteen-pointed star with no self-intersections

See also:
Clipper.StrictlySimple, CleanPolygons, PolyFillType


--- Clipper Properties ---

ClipperLib.Clipper.PreserveCollinear

Boolean PreserveCollinear;

By default, when three or more vertices are collinear in input polygons (subject or clip), the Clipper object removes the 'inner' vertices before clipping. When enabled the PreserveCollinear property prevents this default behavior to allow these inner vertices to appear in the solution.

Usage:

var cpr = new ClipperLib.Clipper();
cpr.PreserveCollinear = true;

See also:
ClipperLib.Clipper()


ClipperLib.Clipper.ReverseSolution

Boolean ReverseSolution;

When this property is set to true, polygons returned in the solution parameter of the Execute() method will have orientations opposite to their normal orientations.

Usage:

var cpr = new ClipperLib.Clipper();
cpr.ReverseSolution = true;

See also:
Execute, Orientation


ClipperLib.Clipper.StrictlySimple

Boolean StrictlySimple;

Terminology: * A simple polygon is one that does not self-intersect. * A weakly simple polygon is a simple polygon that contains 'touching' vertices, or 'touching' edges. * A strictly simple polygon is a simple polygon that does not contain 'touching' vertices, or 'touching' edges.

Vertices 'touch' if they share the same coordinates (and are not adjacent). An edge touches another if one of its end vertices touches another edge excluding its adjacent edges, or if they are co-linear and overlapping (including adjacent edges).

Polygons returned by clipping operations (see Clipper.Execute()) should always be simple polygons. When the StrictlySimply property is enabled, polygons returned will be strictly simple, otherwise they may be weakly simple. It's computationally expensive ensuring polygons are strictly simple and so this property is disabled by default.

In the image above, the two examples show weakly simple polygons being broken into two strictly simple polygons. (The outlines with arrows are intended to aid visualizing vertex order.)

See also the article on Simple Polygon on Wikipedia.

Usage:

var cpr = new ClipperLib.Clipper();
cpr.StrictlySimple = true;

See also:
Execute, SimplifyPolygons


ClipperLib.Clipper.ZFillFunction

void ZFillCallback ZFillFunction;

This property is only exposed when the pre-processor directive use_xyz has been defined. If this is the case, a 'Z' member will be included in the IntPoint structure where users can store custom data. While most vertices in a clipping solution will correspond to input (subject and clip) vertices, there will also be new vertices wherever edges intersect. This property assigns a custom callback function to the Clipper object so that custom 'Z' values can be assigned to these intersection vertices. (Note that 'Z' values in the solution at non-intersecting vertices will simply be copied from matching input vertices along with the X and Y values.)

It is up to the library user to assign 'Z' values for new intersection vertices (otherwise these values will remain 0). The four vertices that define the intersecting line segments will be passed to the callback function (together with the new intersection vertex) to aid the user in determining appropriate Z values.

Usage:

var cpr = new ClipperLib.Clipper();
cpr.ZFillFunction = function (bot1, top1, bot2, top2, pt) { /* function body */ };
// or
var ClipCallback = function (bot1, top1, bot2, top2, pt) { /* function body */ };
cpr.ZFillFunction = ClipCallback;

See also:
Defines, IntPoint, ZFillCallback


Types

ClipperLib.ClipType()

Number ClipType {ctIntersection: 0, ctUnion: 1, ctDifference: 2, ctXor: 3};

There are four boolean operations - AND, OR, NOT & XOR.

Given that subject and clip polygon brush 'filling' is defined both by their vertices and their respective filling rules, the four boolean operations can be applied to polygons to define new filling regions:

  • AND (intersection) - create regions where both subject and clip polygons are filled
  • OR (union) - create regions where either subject or clip polygons (or both) are filled
  • NOT (difference) - create regions where subject polygons are filled except where clip * polygons are filled
  • XOR (exclusive or) - create regions where either subject or clip polygons are filled but not where both are filled

All polygon clipping is performed with a Clipper object with the specific boolean operation indicated by the ClipType parameter passed in its Execute method.

With regard to open paths (polylines), clipping rules generally match those of closed paths (polygons).

However, when there are both polyline and polygon subjects, the following clipping rules apply:

  • union operations - polylines will be clipped by any overlapping polygons so that non-overlapped portions will be returned in the solution together with the union-ed polygons
  • intersection, difference and xor operations - polylines will be clipped only by 'clip' polygons and there will be not interaction between polylines and subject polygons.

Example of clipping behaviour when mixing polyline and polygon subjects:

Usage:

var cliptype = ClipperLib.ClipType.ctIntersection;
var cliptype = ClipperLib.ClipType.ctUnion;
var cliptype = ClipperLib.ClipType.ctDifference;
var cliptype = ClipperLib.ClipType.ctXor;

See also:
Clipper, Clipper.Execute, PolyFillType


ClipperLib.EndType

ClipperLib.EndType = {etOpenSquare: 0, etOpenRound: 1, etOpenButt: 2, etClosedLine: 3,  etClosedPolygon: 4 };

The EndType enumerator has 5 values:

  • etOpenSquare: Ends are squared off and extended delta units
  • etOpenRound: Ends are rounded off and extended delta units
  • etOpenButt: Ends are squared off with no extension.
  • etClosedLine: Ends are joined using the JoinType value and the path filled as a polyline
  • etClosedPolygon: Ends are joined using the JoinType value and the path filled as a polygon
    etOpenSingle: Offsets an open path in a single direction. Planned for a future update.

Note: With etClosedPolygon and etClosedLine types, the path closure will be the same regardless of whether or not the first and last vertices in the path match.


Usage:

var endtype = ClipperLib.EndType.etOpenSquare;
var endtype = ClipperLib.EndType.etOpenRound;
var endtype = ClipperLib.EndType.etOpenButt;
var endtype = ClipperLib.EndType.etClosedLine;
var endtype = ClipperLib.EndType.etClosedPolygon;

See also:
ClipperOffset.AddPath, ClipperOffset.AddPaths


ClipperLib.EndType_

if (use_deprecated)
  ClipperLib.EndType_ = {etSquare: 0, etRound: 1, etButt: 2, etClosed: 3};

Deprecated. See ClipperOffset and EndType.

The EndType_ enumerator has 4 values:

  • etSquare: Ends are squared off at exactly delta units
  • etRound: Ends are rounded off at exactly delta units
  • etButt: Ends are squared off abruptly
  • etClosed: Ends are joined using the JoinType value and the path filled as a polygon.

Usage:

var endtype = ClipperLib.EndType_.etSquare;
var endtype = ClipperLib.EndType_.etRound;
var endtype = ClipperLib.EndType_.etButt;
var endtype = ClipperLib.EndType_.etClosed;


ClipperLib.ExPolygon()

ExPolygon ExPolygon();

Creates an instance of ExPolygon object.

This is not anymore in the original Clipper, but in JS version we provide it to ensure backward compatibility.

Usage:

var expolygon = new ClipperLib.ExPolygon();

See also:
PolyTreeToExPolygons, ExPolygonsToPaths


ClipperLib.ExPolygons()

ExPolygons ExPolygons();

Creates an instance of ExPolygons object ie array.

This is not anymore in the original Clipper, but in JS version we provide it to ensure backward compatibility.

Usage:

var expolygons = new ClipperLib.ExPolygons();

See also:
PolyTreeToExPolygons, ExPolygonsToPaths


InitOptions

Number ioReverseSolution = 1;
Number ioStrictlySimple = 2;
Number ioPreserveCollinear = 4;

Usage:

var cpr = new ClipperLib.Clipper(ClipperLib.Clipper.ioStrictlySimple | ClipperLib.Clipper.ioPreserveCollinear);
// or
var cpr = new ClipperLib.Clipper(2 | 4);

See also:
Constructor, Clipper.PreserveCollinear, Clipper.ReverseSolution, Clipper.StrictlySimple


ClipperLib.IntPoint()

IntPoint IntPoint(Number X, Number Y)
IntPoint IntPoint()
IntPoint IntPoint(IntPoint point)

The IntPoint structure is used to represent all vertices in the Clipper Library. An "integer" storage type has been deliberately chosen to preserve numerical robustness. (Early versions of the library used floating point coordinates, but it became apparent that floating point imprecision would always cause occasional errors.)

A sequence of IntPoints are contained within a Path structure to represent a single contour.

As of version 6, IntPoint now has an optional third member 'Z'. This can be enabled by exposing (ie uncommenting) the PreProcessor define 'use_xyz'. When the Z member is used, its values will be copied to corresponding verticies in solutions to clipping operations. However, at points of intersection where there's no corresponding Z value, the value will be assigned zero unless a new value is provided by a user supplied callback function.

Users wishing to clip or offset polygons containing floating point coordinates need to use appropriate scaling when converting these values to and from IntPoints.

See also the notes on rounding.

Usage:

var point = new ClipperLib.IntPoint(10,20); // Creates object {"X":10,"Y":20}
var point2 = new ClipperLib.IntPoint(); // Creates object {"X":0,"Y":0}
var point3 = new ClipperLib.IntPoint(point); // Creates clone of point

See also:
Rounding, Clipper.ZFillFunction, Defines, Path, Paths


ClipperLib.IntRect()

IntRect IntRect(Number left, Number top, Number right, Number bottom);
IntRect IntRect(IntRect intRect);
IntRect IntRect();

Structure returned by Clipper's GetBounds method.

See also:
GetBounds


ClipperLib.JoinType

ClipperLib.JoinType = {jtSquare: 0, jtRound: 1, jtMiter: 2};

When adding paths to a ClipperOffset object via the AddPaths method, the joinType parameter may be one of three types - jtMiter, jtSquare or jtRound.

  • jtMiter: There's a necessary limit to mitered joins since offsetting edges that join at very acute angles will produce excessively long and narrow 'spikes'. To contain these potential spikes, the ClipperOffset object's MiterLimit property specifies a maximum distance that vertices will be offset (in multiples of delta). For any given edge join, when miter offsetting would exceed that maximum distance, 'square' joining is applied.
  • jtRound: While flattened paths can never perfectly trace an arc, they are approximated by a series of arc chords (see ClipperObject's ArcTolerance property).
  • jtSquare: Squaring is applied uniformally at all convex edge joins at 1 × delta.

Usage:

var jointype = ClipperLib.JoinType.jtSquare;
var jointype = ClipperLib.JoinType.jtRound;
var jointype = ClipperLib.JoinType.jtMiter;

See also:
ClipperOffset, AddPaths, ArcTolerance, MiterLimit


ClipperLib.Path()

Path Path()

This structure contains a sequence of IntPoint vertices defining a single contour (see also terminology). Paths may be open and represent line segments bounded by 2 or more vertices, or they may be closed and represent polygons.

Multiple paths can be grouped into a Paths structure.

Usage:

var path = new ClipperLib.Path(); // Creates an empty array []
// or
var path = new Array();
// or
var path = [];

See also:
Overview, Example, ClipperBase.AddPath, PolyTree, Orientation, IntPoint, Paths


ClipperLib.Paths()

Paths Paths()

This structure is fundamental to the Clipper Library. It's an array of one or more Path structures. (The Path structure contains an ordered array of vertices that make a single contour.)

Paths may open (lines), or they may closed (polygons).

Usage:

var paths = new ClipperLib.Paths(); // Creates an empty array []
// or
var paths = new Array();
// or
var paths = [];

See also:
Clipper.Execute, ClipperBase.AddPath, ClipperBase.AddPaths, OffsetPaths, IntPoint, Path


ClipperLib.PolyFillType

ClipperLib.PolyFillType = {pftEvenOdd: 0, pftNonZero: 1, pftPositive: 2, pftNegative: 3};

Filling indicates regions that are inside a polygon (ie 'filled' with a brush color or pattern in a graphical display), and non-filling indicates regions outside polygons. The Clipper Library supports 4 filling rules: Even-Odd, Non-Zero, Positive and Negative.

The simplest filling rule is Even-Odd filling. Given a group of polygons and starting from a point outside, whenever a contour is crossed either filling starts if it had stopped or it stops if it had started. For example, given a single rectangular polygon, when its first (eg left) edge is crossed filling starts and we're inside the polygon. Filling stops again when the next (eg right) edge is crossed.

With the exception of Even-Odd filling, all other filling rules rely on edge direction and winding numbers to determine filling. Edge direction is determined by the order in which vertices are declared when constructing a polygon. Edge direction is used to determine the winding numbers of polygon regions and subregions.

The winding number for any given polygon sub-region can be derived by:

  1. starting with a winding number of zero
  2. from a point (P1) that's outside all polygons, draw an imaginary line to a point that's inside a given sub-region (P2)
  3. while traversing the line from P1 to P2, for each polygon edge that crosses the line from right to left increment the winding number, and for each polygon edge that crosses the line from left to right decrement the winding number.
  4. Once you arrive at the given sub-region you have its winding number.

Even-Odd (Alternate): Odd numbered sub-regions are filled, while even numbered sub-regions are not.
Non-Zero (Winding): All non-zero sub-regions are filled.
Positive: All sub-regions with winding counts > 0 are filled.
Negative: All sub-regions with winding counts < 0 are filled.

By far the most widely used fill rules are Even-Odd (aka Alternate) and Non-Zero (aka Winding). Most graphics rendering libraries (AGG, Android Graphics, Cairo, GDI+, OpenGL, Quartz 2D etc) and vector graphics storage formats (SVG, Postscript, Photoshop etc) support both these rules. However some libraries (eg Java's Graphics2D) only support one fill rule. Android Graphics and OpenGL are the only libraries (that I'm aware of) that support multiple filling rules.

It's useful to note that edge direction has no affect on a winding number's odd-ness or even-ness. (This is why orientation is ignored when the Even-Odd rule is employed.)

The direction of the Y-axis does affect polygon orientation and edge direction. However, changing Y-axis orientation will only change the sign of winding numbers, not their magnitudes, and has no effect on either Even-Odd or Non-Zero filling.

Usage:

var polyfilltype = ClipperLib.PolyFillType.pftEvenOdd;
var polyfilltype = ClipperLib.PolyFillType.pftNonZero;
var polyfilltype = ClipperLib.PolyFillType.pftPositive;
var polyfilltype = ClipperLib.PolyFillType.pftNegative;

See also:
Clipper.Execute, Orientation


ClipperLib.PolyType

Number ClipperLib.PolyType = {ptSubject: 0, ptClip: 1};

Boolean (clipping) operations are mostly applied to two sets of Polygons, represented in this library as subject and clip polygons. Whenever Polygons are added to the Clipper object, they must be assigned to either subject or clip polygons.

UNION operations can be performed on one set or both sets of polygons, but all other boolean operations require both sets of polygons to derive meaningful solutions.

Usage:

var polytype = ClipperLib.PolyType.ptSubject;
var polytype = ClipperLib.PolyType.ptClip;

See also:
ClipperBase.AddPath, ClipperBase.AddPaths, ClipType


ClipperLib.Clipper.ZFillCallback()

void ZFillCallback(IntPoint bot1, IntPoint top1, IntPoint bot2, IntPoint top2, IntPoint pt);

If the use_xyz pre-processor directive is enabled, then the IntPoint class will have an extra 'Z' member and the Clipper class's ZFillFunction property will be exposed so it can be assigned a custom callback function.

This custom callback procedure requires five IntPoint parameters: the first 2 parameters are the vertices that define one line segment involved in the intersection and the next two parameters the other line segment. (Since the Clipper library has been developed in an environment that uses an inverted Y axis display, e1bot and e2bot will always have Y values greater than or equal to their corresponding e1top and e2top Y values.) The last IntPoint parameter contain the actual coordinates at the intersection. This last parameter is passed by reference so that its Z member can be assigned with a custom value.

See also:
Clipper.ZFillFunction


PolyTree

PolyTree is intended as a read-only data structure that should only be used to receive solutions from polygon clipping operations. It's an alternative data structure the Paths structure which can also receive clipping solutions. Its major advantages over the Paths structure is that it properly represents the parent-child relationships of the returned polygons, and that it also differentiates between open and closed paths. However, since a PolyTree is more complex than a Paths structure, and because it's more computationally expensive to process (the Execute method being roughly 5-10% slower), it should only be used when parent-child polygon relationships are needed, or when open paths are being 'clipped'.

An empty PolyTree object can be passed as the solution parameter to a Clipper object's Execute method. Once the clipping operation is completed, this method returns with the PolyTree structure filled with data representing the solution.

A PolyTree object is a container for any number of PolyNode children, with each contained PolyNode representing a single polygon contour (either an outer or hole polygon). PolyTree itself is a specialized PolyNode whose immediate children represent the top-level outer polygons of the solution. (Its own Contour property is always empty.) The contained top-level PolyNodes may contain their own PolyNode children representing hole polygons that may also contain children representing nested outer polygons etc. Children of outers will always be holes, and children of holes will always be outers.

PolyTrees can also contain open paths. Open paths will always be represented by top level PolyNodes. Two functions are provided to quickly separate out open and closed paths from a polytree - ClosedPathsFromPolyTree and OpenPathsFromPolyTree.

    polytree: 
    Contour = ()
    ChildCount = 1
    Childs[0]: 
        Contour = ((10,10),(100,10),(100,100),(10,100))
        IsHole = False
        ChildCount = 1
        Childs[0]: 
            Contour = ((20,20),(20,90),(90,90),(90,20))
            IsHole = True
            ChildCount = 2
            Childs[0]: 
                Contour = ((30,30),(50,30),(50,50),(30,50))
                IsHole = False
                ChildCount = 0
            Childs[1]: 
                Contour = ((60,60),(80,60),(80,80),(60,80))
                IsHole = False
                ChildCount = 0

            

See also:
Overview, Clipper, Clipper.Execute, PolyNode, ClosedPathsFromPolyTree, OpenPathsFromPolyTree, Paths


--- PolyTree methods ---


ClipperLib.PolyTree()

PolyTree PolyTree()

Returns new PolyTree object.

Usage:

var polytree = new ClipperLib.PolyTree(); // creates PolyTree object
// cpr.Execute ...

See also:
Clipper.Execute, PolyNode, ClosedPathsFromPolyTree, OpenPathsFromPolyTree, Paths


ClipperLib.PolyTree.Clear()

void polytree.Clear()

This method clears any PolyNode children contained by PolyTree the object.

Clear does not need to be called explicitly. The Clipper.Execute method that accepts a PolyTree parameter will automatically clear the PolyTree object before propagating it with new PolyNodes. Likewise, PolyTree's destructor will also automatically clear any contained PolyNodes.

See also:
Clipper.Execute


ClipperLib.PolyTree.GetFirst()

PolyNode GetFirst()

This method returns the first outer polygon contour if any, otherwise a null pointer.

This function is almost equivalent to calling Childs[0] except that when a PolyTree object is empty (has no children), calling Childs[0] would raise an out of range exception.

Usage:

var polynode = polytree.GetFirst();

See also:
PolyNode.GetNext, PolyNode.ChildCount, PolyNode.Childs


ClipperLib.PolyTree.Total()

Number Total() // read only

Returns the total number of PolyNodes (polygons) contained within the PolyTree. This value is not to be confused with ChildCount which returns the number of immediate children only (Childs) contained by PolyTree.

var total = polytree.Total();

See also:
PolyNode.ChildCount, PolyNode.Childs


PolyNode

PolyNodes are encapsulated within a PolyTree container, and together provide a data structure representing the parent-child relationships of polygon contours returned by Clipper's Execute method.

A PolyNode object represents a single polygon. Its IsHole property indicates whether it's an outer or a hole. PolyNodes may own any number of PolyNode children (Childs), where children of outer polygons are holes, and children of holes are (nested) outer polygons.

See also:
Overview, Clipper.Execute, PolyTree


--- PolyNode methods ---


ClipperLib.PolyNode()

PolyNode PolyNode() // read only

Creates new PolyNode object.

Usage:

var polynode = new ClipperLib.PolyNode();

See also:
Clipper.Execute, PolyTree


ClipperLib.PolyNode.ChildCount()

Number ChildCount() // read only

Returns the number of PolyNode Childs directly owned by the PolyNode object.

Usage:

var count = polynode.ChildCount();

See also:
Childs


ClipperLib.PolyNode.Childs()

Array < PolyNode > Childs() // read only

Array of PolyNode. Outer PolyNode childs contain hole PolyNodes, and hole PolyNode childs contain nested outer PolyNodes.

Usage:

var childs = polynode.Childs();

See also:
ChildCount


ClipperLib.PolyNode.Contour()

Path Contour() // read only

Returns a path list which contains any number of vertices.

Usage:

var contour = polynode.Contour();


ClipperLib.PolyNode.GetNext()

PolyNode GetNext()

The returned Polynode will be the first child if any, otherwise the next sibling, otherwise the next sibling of the Parent etc.

A PolyTree can be traversed very easily by calling GetFirst() followed by GetNext() in a loop until the returned object is a null pointer ...

Usage:

var polytree = new ClipperLib.PolyTree();
//call to Clipper.Execute method here which fills 'polytree'

var polynode = polytree.GetFirst();
while (polynode)
{
  //do stuff with polynode here

  polynode = polynode.GetNext();
}

See also:
PolyTree.GetFirst


ClipperLib.PolyNode.IsHole()

Boolean IsHole() // read only

Returns true when the PolyNode's polygon (Contour) is a hole.

Children of outer polygons are always holes, and children of holes are always (nested) outer polygons.

The IsHole property of a PolyTree object is undefined but its children are always top-level outer polygons.

Usage:

var ishole = polynode.IsHole();

See also:
Contour, PolyTree


ClipperLib.PolyNode.Parent()

PolyNode Parent(); read only

Returns the parent PolyNode.

The PolyTree object (which is also a PolyNode) does not have a parent and will return a null pointer.

Usage:

var parent = polynode.Parent();


--- PolyNode properties ---


ClipperLib.PolyNode.IsOpen

Boolean IsOpen // read only property

Returns true when the PolyNode's Contour results from a clipping operation on an open contour (path). Only top-level PolyNodes can contain open contours.

Usage:

var isopen = polynode.IsOpen;

See also:
Contour


ClipperOffset

The ClipperOffset class encapsulates the process of offsetting (inflating/deflating) both open and closed paths.

This class replaces the now deprecated OffsetPaths function which is/was less flexible. The Execute method can be called multiple times using different offsets (deltas) without having to reassign paths. Offsetting can now be performed on a mixture of open and closed paths in a single operation. Also, the dual functionality of OffsetPaths' Limit parameter was not only confusing some users, but it also prevented a custom RoundPrecision being assigned when EndType was etRound and JoinType was jtMiter.

When offsetting closed paths (polygons), it's important that:

  1. their orientations are consistent such that outer polygons share the same orientation while holes have the opposite orientation
  2. they do not self-intersect.

--- ClipperOffset methods ---


ClipperLib.ClipperOffset()

ClipperOffset ClipperOffset(Number miterLimit = 2.0, Number roundPrecision = 0.25);

The ClipperOffset constructor takes 2 optional parameters: MiterLimit and ArcTolerance. These two parameters corresponds to properties of the same name. MiterLimit is only relevant when JoinType is jtMiter, and ArcTolerance is only relevant when JoinType is jtRound or when EndType is etOpenRound.

Usage:

var co = new ClipperLib.ClipperOffset(2.0, 0.25);

See also:
ArcTolerance, MiterLimit


ClipperLib.ClipperOffset.AddPath()

void AddPath(Path path, JoinType jointype, EndType endtype);

Adds a path to a ClipperOffset object in preparation for offsetting. This method can be called multiple times.

Usage:

var path = [{X:10,Y:10},{X:110,Y:10},{X:110,Y:110},{X:10,Y:110}];
var co = new ClipperLib.ClipperOffset(2, 0.25);
co.AddPath(path, ClipperLib.JoinType.jtMiter, ClipperLib.EndType.etClosedPolygon);

See also:
JoinType, EndType


ClipperLib.ClipperOffset.AddPaths()

void AddPaths(Paths paths, JoinType jointype, EndType endtype);

Adds paths to a ClipperOffset object in preparation for offsetting. This method can be called multiple times.

Usage:

var paths = [[{X:10,Y:10},{X:110,Y:10},{X:110,Y:110},{X:10,Y:110}],
             [{X:20,Y:20},{X:20,Y:100},{X:100,Y:100},{X:100,Y:20}]]; 
var co = new ClipperLib.ClipperOffset(2, 0.25);
co.AddPaths(paths, ClipperLib.JoinType.jtMiter, ClipperLib.EndType.etClosedPolygon);

See also:
JoinType, EndType


ClipperLib.ClipperOffset.Clear()

void Clear();

This method clears all paths from the ClipperOffset object, allowing new paths to be assigned.

Usage:

var path = [{X:10,Y:10},{X:110,Y:10},{X:110,Y:110},{X:10,Y:110}];
var co = new ClipperLib.ClipperOffset();
co.AddPath(path, ClipperLib.JoinType.jtRound, ClipperLib.EndType.etClosedPolygon);
co.Clear();


ClipperLib.ClipperOffset.Execute()

void Execute(Paths solution, Number delta);
void Execute(PolyTree polytree, Number delta);

This method takes two parameters. The first is the structure (either PolyTree or Paths) that will receive the result of the offset operation. The second parameter is the amount to which the supplied paths will be offset - negative delta values to shrink polygons and positive delta to expand them.

This method can be called multiple times, offsetting the same paths by different amounts (ie using different deltas).

A note about scaling:

Because ClipperOffset uses integer coordinates, you have to scale coordinates to maintain precision and make arcs smooth - also in the case of integer input.

Javascript Clipper provides four functions for this purpose: ScaleUpPath, ScaleUpPaths, ScaleDownPath and ScaleDownPaths.

Scaling is highly recommended if JoinType is jtRound or EndType is etRound.

Usage:

var subj = new ClipperLib.Paths();
var solution = new ClipperLib.Paths();
subj[0] = [{"X":348,"Y":257},{"X":364,"Y":148},{"X":362,"Y":148},{"X":326,"Y":241},{"X":295,"Y":219},{"X":258,"Y":88},{"X":440,"Y":129},{"X":370,"Y":196},{"X":372,"Y":275}];
var scale = 100;
ClipperLib.JS.ScaleUpPaths(subj, scale);
var co = new ClipperLib.ClipperOffset(2, 0.25);
co.AddPaths(subj, ClipperLib.JoinType.jtRound, ClipperLib.EndType.etClosedPolygon);
co.Execute(solution, -7.0);
ClipperLib.JS.ScaleDownPaths(subj, scale);
//draw solution with your own drawing function...
DrawPolygons(solution, 0x4000FF00, 0xFF009900);

See also:
ScaleUpPath, ScaleUpPaths, ScaleDownPath, ScaleDownPaths.


--- ClipperOffset properties ---


ClipperLib.ClipperOffset.ArcTolerance

Number ArcTolerance

Firstly, this field/property is only relevant when JoinType = jtRound and/or EndType = etRound.

Since flattened paths can never perfectly represent arcs, this field/property specifies a maximum acceptable imprecision ('tolerance') when arcs are approximated in an offsetting operation. Smaller values will increase 'smoothness' up to a point though at a cost of performance and in creating more vertices to construct the arc.

The default ArcTolerance is 0.25 units. This means that the maximum distance the flattened path will deviate from the 'true' arc will be no more than 0.25 units (before rounding).

Reducing tolerances below 0.25 will not improve smoothness since vertex coordinates will still be rounded to integer values. The only way to achieve sub-integer precision is through coordinate scaling before and after offsetting (see example below).

It's important to make ArcTolerance a sensible fraction of the offset delta (arc radius). Large tolerances relative to the offset delta will produce poor arc approximations but, just as importantly, very small tolerances will substantially slow offsetting performance while providing unnecessary degrees of precision. This is most likely to be an issue when offsetting polygons whose coordinates have been scaled to preserve floating point precision.

Example: Imagine a set of polygons (defined in floating point coordinates) that is to be offset by 10 units using round joins, and the solution is to retain floating point precision up to at least 6 decimal places.
To preserve this degree of floating point precision, and given that Clipper and ClipperOffset both operate on integer coordinates, the polygon coordinates will be scaled up by 108 (and rounded to integers) prior to offsetting. Both offset delta and ArcTolerance will also need to be scaled by this same factor. If ArcTolerance was left unscaled at the default 0.25 units, every arc in the solution would contain a fraction of 44 THOUSAND vertices while the final arc imprecision would be 0.25 × 10-8 units (ie once scaling was reversed). However, if 0.1 units was an acceptable imprecision in the final unscaled solution, then ArcTolerance should be set to 0.1 × scaling_factor (0.1 × 108 ). Now if scaling is applied equally to both ArcTolerance and to Delta Offset, then in this example the number of vertices (steps) defining each arc would be a fraction of 23.

Usage:

var co = new ClipperLib.ClipperOffset();
co.ArcTolerance = 1.23;


ClipperLib.ClipperOffset.MiterLimit

Number MiterLimit

This property sets the maximum distance in multiples of delta that vertices can be offset from their original positions before squaring is applied. (Squaring truncates a miter by 'cutting it off' at 1 × delta distance from the original vertex.)

The default value for MiterLimit is 2 (ie twice delta). This is also the smallest MiterLimit that's allowed. If mitering was unrestricted (ie without any squaring), then offsets at very acute angles would generate unacceptably long 'spikes'.

An example of an offsetting 'spike' at a narrow angle that's a consequence of using a large MiterLimit (25) ...

Usage:

var co = new ClipperLib.ClipperOffset();
co.MiterLimit = 4.1;

See also:
JoinType


Rounding

By using an integer type for polygon coordinates, the Clipper Library has been able to avoid problems of numerical robustness that can cause havoc with geometric computations. Problems associated with integer rounding and their possible solutions are discussed in the original documentation.


JS

JS is a special object to ensure backward compatibility and make it easier to run frequent tasks.

It is not available in original Clipper.


--- JS methods ---


ClipperLib.JS.AreaOfPolygon()

Number AreaOfPolygon(Path poly, Number scale = 1);

Returns the area of a closed Path. If the path is already scaled up, you can set scale value to force function to return downscaled area.

Usage:

var path = [{X:10,Y:10},{X:110,Y:10},{X:110,Y:110},{X:10,Y:110}];
var area = ClipperLib.JS.AreaOfPolygon (path, 1);
// area is 10000


ClipperLib.JS.AreaOfPolygons()

Number AreaOfPolygons(Paths polys, Number scale = 1);

Returns the area of a closed Paths. If it is already scaled up, you can set scale value to force function to return downscaled area.

Usage:

var paths = [[{X:10,Y:10},{X:110,Y:10},{X:110,Y:110},{X:10,Y:110}],
            [{X:20,Y:20},{X:20,Y:100},{X:100,Y:100},{X:100,Y:20}]];
var area = ClipperLib.JS.AreaOfPolygons (paths, 1);
// area is now 3600


ClipperLib.JS.BoundsOfPath()

IntRect BoundsOfPath(Path path, Number scale = 1);

Returns an IntRect object which describes the bounding box of a Path. If the path is already scaled up, you can set scale value to force function to return downscaled bounds.

Usage:

var path = [{X:10,Y:10},{X:110,Y:10},{X:110,Y:110},{X:10,Y:110}];
var bounds = ClipperLib.JS.BoundsOfPath (path, 1);
// bounds is {"left":10,"top":10,"right":110,"bottom":110}


ClipperLib.JS.BoundsOfPaths()

IntRect BoundsOfPaths(Paths paths, Number scale = 1);

Returns an IntRect object which describes the bounding box of a Paths. If it is already scaled up, you can set scale value to force function to return downscaled bounds.

Usage:

var paths = [[{X:10,Y:10},{X:110,Y:10},{X:110,Y:110},{X:10,Y:110}],
            [{X:20,Y:20},{X:20,Y:100},{X:100,Y:100},{X:100,Y:20}]];
var bounds = ClipperLib.JS.BoundsOfPaths (paths, 1);
// bounds is {"left":10,"top":10,"right":110,"bottom":110}


ClipperLib.JS.Clone()

Path Clone(Path path);
Paths Clone(Paths paths);

Makes a deep copy of Path or Paths so that also IntPoint objects are cloned and not only referenced.

Usage:

var cloned_path = ClipperLib.JS.Clone(path);
// or
var cloned_paths = ClipperLib.JS.Clone(paths);


ClipperLib.JS.Clean()

Path Clean(Path path);
Paths Clean(Paths paths);

Joins vertices that are too near each other and would cause distortion in offsetting without cleaning.

This function differs from CleanPolygon and CleanPolygons, which clean also collinear vertices.

Ideal for situations where you need to prevent distortion and not do anything else.

Usage:

var cleaned_path = ClipperLib.JS.Clean (path, delta);
// or
var cleaned_paths = ClipperLib.JS.Clean (paths, delta);


ClipperLib.JS.Lighten()

Path Lighten(Path path, Number tolerance);
Paths Lighten(Paths paths, Number tolerance);

Removes points that doesn't affect much to the visual appearance. If middle point is at or under certain distance (tolerance) of the line segment between start and end point, the middle point is removed.

Helps to speedup calculations and rendering.

Usage:

var scale = 100;
var lightened_path = ClipperLib.JS.Lighten(path, 0.1 * scale);
// or
var lightened_paths = ClipperLib.JS.Lighten(paths, 0.1 * scale);


ClipperLib.JS.PerimeterOfPath()

Number PerimeterOfPath(Path path, Boolean closed, Number scale = 1);

Returns the perimeter of a Path. If the Path is closed (ie polygon), a clone of the first vertex is added to the end of the Path and removed after calculation to ensure that whole ("polygonal") perimeter is taken into account.

Open paths (ie lines) are measured by taking into account only the existing vertices.

If the path goes back the same way, every line segment is calculated, which means that the returned perimeter is longer than the visual perimeter.

If coordinates are upscaled beforehand by some scaling factor (eg. 100), and scale parameter is provided to the function, the downscaled, real perimeter is returned.

Usage:

var path = [{X:10,Y:10},{X:110,Y:10},{X:110,Y:110},{X:10,Y:110}];
var polygonal_perimeter = ClipperLib.JS.PerimeterOfPath(path, true, 1);
// polygonal_perimeter is 400

// But...
var line_perimeter = ClipperLib.JS.PerimeterOfPath(path, false, 1);
// line_perimeter is 300


ClipperLib.JS.PerimeterOfPaths()

Number PerimeterOfPaths(Paths paths, Boolean closed, Number scale = 1);

Returns the sum of perimeters of individual paths contained in the paths. See also PerimeterOfPath.

Usage:

var paths = [[{X:10,Y:10},{X:110,Y:10},{X:110,Y:110},{X:10,Y:110}],
            [{X:20,Y:20},{X:20,Y:100},{X:100,Y:100},{X:100,Y:20}]];
var polygonal_perimeter = ClipperLib.JS.PerimeterOfPaths (paths, true, 1);
// polygonal_perimeter is 720

var line_perimeter = ClipperLib.JS.PerimeterOfPaths (paths, false, 1);
// line_perimeter is 540


ClipperLib.JS.ScaleDownPath()

void ScaleDownPath(Path path, Number scale = 1);

Divides each coordinate of Path by scale value.

Usage:

var path = [{X:1000,Y:1000},{X:11000,Y:1000},{X:11000,Y:11000},{X:1000,Y:11000}];
ClipperLib.JS.ScaleDownPath (path, 100);
// path is [{X:10,Y:10},{X:110,Y:10},{X:110,Y:110},{X:10,Y:110}];


ClipperLib.JS.ScaleDownPaths()

void ScaleDownPaths(Paths paths, Number scale = 1);

Divides each coordinate of Paths by scale value.

Usage:

var paths = [[{X:1000,Y:1000},{X:11000,Y:1000},{X:11000,Y:11000},{X:1000,Y:11000}],
             [{X:2000,Y:2000},{X:2000,Y:10000},{X:10000,Y:10000},{X:10000,Y:2000}]];
ClipperLib.JS.ScaleDownPaths (path, 100);
// path is [[{X:10,Y:10},{X:110,Y:10},{X:110,Y:110},{X:10,Y:110}],
//          [{X:20,Y:20},{X:20,Y:100},{X:100,Y:100},{X:100,Y:20}]];


ClipperLib.JS.ScaleUpPath()

void ScaleUpPath(Path path, Number scale = 1);

Multiplies each coordinate of a Path by scaling coefficient and rounds to the nearest integer using Math.round().

Usage:

var path = [{X:10,Y:10},{X:110,Y:10},{X:110,Y:110},{X:10,Y:110}];
ClipperLib.JS.ScaleUpPath (path, 100);
// path is now [{X:1000,Y:1000},{X:11000,Y:1000},{X:11000,Y:11000},{X:1000,Y:11000}];


ClipperLib.JS.ScaleUpPaths()

void ScaleUpPaths(Paths paths, Number scale = 1);

Multiplies each coordinate of Paths by scaling coefficient and rounds to the nearest integer using Math.round().

Usage:

var paths = [[{X:10,Y:10},{X:110,Y:10},{X:110,Y:110},{X:10,Y:110}],
            [{X:20,Y:20},{X:20,Y:100},{X:100,Y:100},{X:100,Y:20}]];
ClipperLib.JS.ScaleUpPaths (path, 100);
// path is now [[{X:1000,Y:1000},{X:11000,Y:1000},{X:11000,Y:11000},{X:1000,Y:11000}],
//              [{X:2000,Y:2000},{X:2000,Y:10000},{X:10000,Y:10000},{X:10000,Y:2000}]];


ClipperLib.JS.PolyTreeToExPolygons()

ExPolygons PolyTreeToExPolygons(PolyTree polytree)

Converts PolyTree to ExPolygons.

Usage:

var expolygons = ClipperLib.JS.PolyTreeToExPolygons(polytree);


ClipperLib.JS.ExPolygonsToPaths()

Paths ExPolygonsToPaths(ExPolygons expolygons)

Converts ExPolygons to Paths.

Usage:

var paths = ClipperLib.JS.ExPolygonsToPaths(expolygons);


Texts and images have been copied (with permission) from the original Clipper Documentation, with some modifications to fit the Javascript environment.

Clipper Documentation is copyright 2010-2017 Angus Johnson.

Modifications copyright 2013-2017 Timo.