Skip to content

Instantly share code, notes, and snippets.

@ColonelThirtyTwo
Last active January 2, 2016 00:59
Show Gist options
  • Save ColonelThirtyTwo/8227727 to your computer and use it in GitHub Desktop.
Save ColonelThirtyTwo/8227727 to your computer and use it in GitHub Desktop.
Updated C/LuaJIT bindings for Clipper
#include "clipper.cpp"
using namespace ClipperLib;
#ifdef __MINGW32__
#define export extern "C" __declspec (dllexport)
#else
#define export extern "C"
#endif
// clipper_path class
export Path* clipper_path_create(int n) {
try {
return new Path(n);
} catch(...) {
return 0;
}
}
export void clipper_path_free(Path* poly) {
delete poly;
}
export int clipper_path_size(Path* poly) {
return poly->size();
}
export IntPoint* clipper_path_get(Path* poly, int i) {
return &((*poly)[i]);
}
export void clipper_path_set(Path* poly, int i, cInt x, cInt y)
{
(*poly)[i] = IntPoint(x,y);
}
export int clipper_path_add(Path* poly, cInt x, cInt y) {
try {
poly->push_back(IntPoint(x, y));
return 0;
} catch(...) {
return 1;
}
}
export Paths* clipper_path_simplify(Path* poly, PolyFillType fill_type) {
try {
Paths* in = new Paths();
in->push_back(*poly);
Paths* out = new Paths();
SimplifyPolygons(*in, *out, PolyFillType(fill_type));
return out;
} catch(...) {
return 0;
}
}
export Path* clipper_path_clean(Path* poly, double distance) {
try {
Path* out = new Path();
CleanPolygon(*poly, *out, distance);
return out;
} catch(...) {
return 0;
}
}
export void clipper_path_reverse(Path* poly) {
ReversePath(*poly);
}
export int clipper_path_orientation(Path* poly) {
return Orientation(*poly);
}
export double clipper_path_area(Path* poly) {
return Area(*poly);
}
// clipper_paths class
export Paths* clipper_paths_create(int n) {
try {
return new Paths(n);
} catch(...) {
return 0;
}
}
export void clipper_paths_free(Paths* poly) {
delete poly;
}
export int clipper_paths_size(Paths* poly) {
return poly->size();
}
export Path* clipper_paths_get(Paths* poly, int i) {
return &((*poly)[i]);
}
export void clipper_paths_set(Paths* poly, int i, Path* e) {
(*poly)[i] = *e;
}
export int clipper_paths_add(Paths* poly, Path* e) {
try {
poly->push_back(*e);
return 0;
} catch(...) {
return 1;
}
}
export Paths* clipper_paths_simplify(Paths* poly, PolyFillType fill_type) {
try {
Paths* out = new Paths();
SimplifyPolygons(*poly, *out, PolyFillType(fill_type));
return out;
} catch(...) {
return 0;
}
}
export Paths* clipper_paths_clean(Paths* poly, double distance) {
try {
Paths* out = new Paths(poly->size());
CleanPolygons(*poly, *out, distance);
return out;
} catch(...) {
return 0;
}
}
export void clipper_paths_reverse(Paths* poly) {
ReversePaths(*poly);
}
/*
export Paths* clipper_paths_offset(Paths* poly, double delta, JoinType jointype, double miter_limit) {
try {
Paths* out = new Paths();
OffsetPaths(*poly, *out, delta, JoinType(jointype), miter_limit, false);
return out;
} catch(...) {
return 0;
}
}
*/
// clipper class
export Clipper* clipper_create() {
try {
return new Clipper();
} catch(...) {
return 0;
}
}
export void clipper_free(Clipper* clipper) {
delete clipper;
}
export int clipper_add_path(Clipper* clipper, Path* poly, PolyType poly_type) {
clipper->AddPath(*poly, PolyType(poly_type), true);
return 0;
}
export int clipper_add_paths(Clipper* clipper, Paths* poly, PolyType poly_type) {
clipper->AddPaths(*poly, PolyType(poly_type), true);
return 0;
}
export void clipper_get_bounds(Clipper* clipper, IntRect* out) {
*out = clipper->GetBounds();
}
export Paths* clipper_execute(Clipper* clipper, ClipType clipType,
PolyFillType subjFillType,
PolyFillType clipFillType) {
try {
Paths* solution = new Paths();
clipper->Execute(ClipType(clipType), *solution,
PolyFillType(subjFillType),
PolyFillType(clipFillType));
return solution;
} catch(...) {
return 0;
}
}
export void clipper_clear(Clipper* clipper) {
clipper->Clear();
}
export int clipper_get_reverse_solution(Clipper* clipper) {
return clipper->ReverseSolution();
}
export void clipper_set_reverse_solution(Clipper* clipper, int reverse) {
clipper->ReverseSolution(reverse);
}
local ffi = require'ffi'
local C = ffi.load'clipper-c'
ffi.cdef[[
typedef signed long long cInt;
typedef unsigned long long cUInt;
typedef struct clipper_point_st { cInt x, y; } clipper_point;
typedef struct clipper_rect_st { cInt x1, y1, x2, y2; } clipper_rect;
typedef enum {
clipper_ctIntersection,
clipper_ctUnion,
clipper_ctDifference,
clipper_ctXor
} clipper_ClipType;
typedef enum {
clipper_ptSubject,
clipper_ptClip
} clipper_PolyType;
typedef enum {
clipper_pftEvenOdd,
clipper_pftNonZero,
clipper_pftPositive,
clipper_pftNegative
} clipper_PolyFillType;
typedef enum {
clipper_jtSquare,
clipper_jtRound,
clipper_jtMiter
} clipper_JoinType;
typedef struct clipper_Path clipper_path;
typedef struct clipper_Paths clipper_paths;
typedef struct clipper_Clipper clipper;
clipper_path* clipper_path_create(int);
void clipper_path_free (clipper_path*);
int clipper_path_size (clipper_path*);
clipper_point* clipper_path_get (clipper_path*, int);
int clipper_path_set (clipper_path*, int, cInt x, cInt y);
int clipper_path_add (clipper_path*, cInt x, cInt y);
clipper_paths* clipper_path_simplify (clipper_path*, clipper_PolyFillType);
clipper_path* clipper_path_clean (clipper_path*, double);
void clipper_path_reverse (clipper_path*);
int clipper_path_orientation (clipper_path*);
double clipper_path_area (clipper_path*);
clipper_paths* clipper_paths_create(int n);
void clipper_paths_free (clipper_paths*);
int clipper_paths_size (clipper_paths*);
clipper_path* clipper_paths_get (clipper_paths*, int);
void clipper_paths_set (clipper_paths*, int, clipper_path*);
int clipper_paths_add (clipper_paths*, clipper_path*);
clipper_paths* clipper_paths_simplify (clipper_paths*, clipper_PolyFillType);
clipper_paths* clipper_paths_clean (clipper_paths*, double);
void clipper_paths_reverse (clipper_paths*);
clipper_paths* clipper_paths_offset (clipper_paths*, double, clipper_JoinType, double);
clipper* clipper_create();
void clipper_free (clipper*);
int clipper_add_path (clipper*, clipper_path*, clipper_PolyType);
int clipper_add_paths (clipper*, clipper_paths*, clipper_PolyType);
void clipper_get_bounds (clipper*, clipper_rect*);
clipper_paths* clipper_execute (clipper*, clipper_ClipType,
clipper_PolyFillType,
clipper_PolyFillType);
void clipper_clear (clipper*);
int clipper_get_reverse_solution (clipper*);
void clipper_set_reverse_solution (clipper*, int);
]]
local fill_types = {
even_odd = C.clipper_pftEvenOdd,
non_zero = C.clipper_pftNonZero,
positive = C.clipper_pftPositive,
negative = C.clipper_pftNegative,
}
local join_types = {
square = C.clipper_jtSquare,
round = C.clipper_jtRound,
miter = C.clipper_jtMiter,
}
local clip_types = {
intersection = C.clipper_ctIntersection,
union = C.clipper_ctUnion,
difference = C.clipper_ctDifference,
xor = C.clipper_ctXor
}
local clipper_type = ffi.typeof 'clipper'
local path_type = ffi.typeof'clipper_path'
local paths_type = ffi.typeof 'clipper_paths'
local function is_path(poly)
return ffi.istype(path_type, poly)
end
local Path = {} --path methods
Path.__index = Path
function Path:__new(n)
return C.clipper_path_create(n or 0)
end
Path.__gc = C.clipper_path_free
function Path:free()
C.clipper_path_free(self)
ffi.gc(self, nil)
end
function Path:size()
-- Lua passes two arguments to __len: self and nil, which causes an error when directly using the C function
return C.clipper_path_size(self)
end
Path.__len = Path.size
function Path:get(i)
return C.clipper_path_get(self, i-1)
end
function Path:set(i, x, y)
C.clipper_path_set(self, i, x, y)
end
function Path:add(x, y)
assert(C.clipper_path_add(self, x, y) == 0, 'out of memory')
end
function Path:simplify(fill_type)
local out = C.clipper_path_simplify(self, fill_types[fill_type or 'even_odd'])
return ffi.gc(out, C.clipper_paths_free)
end
function Path:clean(d)
local out = C.clipper_path_clean(self, d or 1.415)
return ffi.gc(out, C.clipper_path_free)
end
Path.reverse = C.clipper_path_reverse
function Path:orientation()
return C.clipper_path_orientation(self) == 1
end
Path.area = C.clipper_path_area
local Paths = {} --paths methods
Paths.__index = Paths
function Paths:__new(...)
if is_path(...) then
local n = select('#',...)
local out = C.clipper_paths_create(n)
for i=1,n do
out:set(i, select(i,...))
end
return out
else
return C.clipper_paths_create(... or 0)
end
end
Paths.__gc = C.clipper_paths_free
function Paths:free()
C.clipper_paths_free(self)
ffi.gc(self, nil)
end
Paths.size = C.clipper_paths_size
function Paths:get(i)
return C.clipper_paths_get(self, i-1)
end
function Paths:set(i, poly)
return C.clipper_paths_set(self, i-1, poly)
end
function Paths:add(poly)
assert(C.clipper_paths_add(self, poly) == 0, 'out of memory')
end
function Paths:simplify(fill_type)
local out = C.clipper_paths_simplify(self, fill_types[fill_type or 'even_odd'])
return ffi.gc(out, C.clipper_paths_free)
end
function Paths:clean(d)
local out = C.clipper_paths_clean(self, d or 1.415)
return ffi.gc(out, C.clipper_paths_free)
end
Paths.reverse = C.clipper_paths_reverse
function Paths:offset(delta, join_type, limit)
local out = C.clipper_paths_offset(self, delta, join_types[join_type or 'square'], limit or 0)
return ffi.gc(out, C.clipper_paths_free)
end
local Clipper = {} --clipper methods
Clipper.__index = Clipper
function Clipper:__new()
return C.clipper_create()
end
Clipper.__gc = C.clipper_free
function Clipper:free()
C.clipper_free(self)
ffi.gc(self, nil)
end
local function Clipper_add(self, poly, where_flag)
if is_path(poly) then
C.clipper_add_path(self, poly, where_flag)
else
C.clipper_add_paths(self, poly, where_flag)
end
end
function Clipper:add_subject(poly) clipper_add(self, poly, C.clipper_ptSubject) end
function Clipper:add_clip(poly) clipper_add(self, poly, C.clipper_ptClip) end
function Clipper:get_bounds(r)
local r = r or ffi.new'clipper_rect'
C.clipper_get_bounds(self, r)
return r.x1, r.y1, r.x2, r.y2
end
function Clipper:execute(clip_type, subj_fill_type, clip_fill_type, reverse)
C.clipper_set_reverse_solution(self, reverse and 1 or 0)
local out = C.clipper_execute(self,
clip_types[clip_type],
fill_types[subj_fill_type or 'even_odd'],
fill_types[clip_fill_type or 'even_odd'])
return ffi.gc(out, C.clipper_paths_free)
end
Clipper.clear = C.clipper_clear
ffi.metatype(clipper_type, Clipper)
ffi.metatype(path_type, Path)
ffi.metatype(paths_type, Paths)
return {
Clipper = clipper_type,
Path = path_type,
Paths = paths_type,
lib = C,
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment