A Polygon Clipping and Offsetting library for LuaJIT (FFI binding to the Clipper2 DLL)
The Clipper2 library performs intersection, union, difference and XOR boolean operations on both simple and complex polygons. It also performs customizable polygon offsetting (inflating or shrinking polygons). This is a major update of the original Clipper library (now "Clipper1"), and while Clipper1 still works very well, Clipper2 is better in just about every way.
Clipper2-Lua provides a high-level LuaJIT FFI wrapper for the official Clipper2 DLL, enabling fast and robust polygon clipping and offsetting in the LuaJIT environment. Key features include an efficient conversion between Lua tables and Clipper paths, a simple, object-oriented API for working with geometric objects, and close mirroring of the Clipper2 C++ interface for intuitive usage.
LuaJIT is a high-performance Just-In-Time Compiler for Lua, widely used for demanding scripting tasks. This wrapper is implemented as a pure LuaJIT module using the FFI (Foreign Function Interface), which allows direct loading and usage of the Clipper2 DLL through intuitive Lua classes.
You can use this library on any platform where both LuaJIT and Clipper2 DLL are available (Windows, Linux, or Mac), as long as the DLL is compiled for your target environment. The DLL file provided in this repository is built for Windows OS and supports both 32-bit and 64-bit architectures.
Download prebuilt DLLs from the official Clipper2 GitHub releases.
Or build the DLL yourself from the Clipper2 C++ source code.
See the Clipper2 HTML documentation for in-depth algorithm explanations and options.
This LuaJIT binding exposes the most-used functions via Lua classes, closely mirroring the C++/C# API.
The main interface for performing polygon operations.
-
Constructor
Clipper:new()
-
Boolean Operations
Clipper:boolean(cliptype, fillrule, subject, clip[,
precision, preserve_collinear, reverse_solution])
Clipper:intersect(subject, clip[, fillrule, precision])
Clipper:union(subject, clip[, fillrule, precision])
Clipper:difference(subject, clip[, fillrule, precision])
Clipper:xor(subject, clip[, fillrule, precision])
-
Path Offsetting
Clipper:inflate_path(path, delta[, jointype, endtype,
precision, miter_limit, arc_tolerance, reverse_solution])
Clipper:inflate_paths(paths, delta[, jointype, endtype,
precision, miter_limit, arc_tolerance, reverse_solution])
-
Rectangle Clipping
Clipper:rect_clip(rect, paths[, precision])
Clipper:rect_clip_lines(rect, paths[, precision])
-
Helpers
Clipper:make_path{ x1, y1, x2, y2, ..., xn, yn }
Clipper:version()
– Get DLL version string.
A collection of polygon paths.
Paths:new()
- Initialize a newPaths
container.Paths:add(path)
– Add aPath
to the collection.Paths:get(index)
– Get the (1-based)Path
atindex
.Paths:clear()
– Remove all paths from the container.Paths:size()
– Number of paths in the collection.tostring(Paths)
– String representation.
A sequence of points (a single polygon or contour).
Path:new()
- Initialize a newPath
container.Path:add(point)
– Add aPoint
to the path.Path:get(index)
– Get the (1-based)Point
atindex
.Path:set(index, point)
– Replace a point at position.Path:clear()
– Remove all points from the container.Path:size()
– Number of points in a collection.tostring(Path)
– String representation.
A rectangle structure for use with rectangle clipping.
Rect:new(left, top, right, bottom)
– Construct a newRect
.tostring(Rect)
– String representation.
A 2D coordinate used to define vertices of paths.
Point:new(x, y)
- Initialize a newPoint
.tostring(Point)
– String representation.
Use these constants to control behavior in operations.
Name | Values |
---|---|
ClipType |
NoClip , Intersection , Union , Difference , Xor |
FillRule |
EvenOdd , NonZero , Positive , Negative |
JoinType |
Square , Bevel , Round , Miter |
EndType |
Polygon , Joined , Butt , Square , Round |
local C = require "ClipperLib"
local FillRule = C.FillRule
local Clipper = C.Clipper
local Paths = C.Paths
local clipper = Clipper()
local subj, clip = Paths(), Paths()
subj:add(clipper:make_path{100,50, 10,79, 65,2, 65,98, 10,21})
clip:add(clipper:make_path{ 98,63, 4,68, 77,8, 52,100, 19,12})
local solution = clipper:intersect(subj, clip, FillRule.NonZero)
print(tostring(solution))
--[[
Path 1: (65,38.7188) (68.3516,39.7969) (67.4141,43.2578) (85.2266,54.7578)
(65,61.2734) (65,64.75) (61.5234,64.9375) (55.9688,85.3594) (43.6719,68.1406)
(40.4453,69.1875) (39.2891,66.1172) (18.3984,67.2266) (30.7109,50)
(28.9297,47.5) (31.5156,45.375) (24.0703,25.5313) (43.6719,31.8516)
(45.5938,29.1641) (48.7578,31.2109) (65,17.8594)
--]]