mirror of
https://github.com/doublecmd/doublecmd.git
synced 2026-06-21 09:58:13 +00:00
197 lines
6.5 KiB
ObjectPascal
197 lines
6.5 KiB
ObjectPascal
unit Img32.Clipper2;
|
|
|
|
(*******************************************************************************
|
|
* Author : Angus Johnson *
|
|
* Version : 4.7 *
|
|
* Date : 6 January 2025 *
|
|
* Website : http://www.angusj.com *
|
|
* Copyright : Angus Johnson 2019-2025 *
|
|
* Purpose : Wrapper module for the Clipper library *
|
|
* License : http://www.boost.org/LICENSE_1_0.txt *
|
|
*******************************************************************************)
|
|
|
|
interface
|
|
|
|
uses
|
|
Img32, Img32.Draw, Img32.Vector, Clipper.Offset;
|
|
|
|
//nb: InflatePath assumes that there's consistent winding where
|
|
//outer paths wind in one direction and inner paths in the other
|
|
type
|
|
TClipperEndType = Clipper.Offset.TEndType;
|
|
|
|
function ClipperEndType(endStyle: TEndStyle): TClipperEndType;
|
|
|
|
function InflatePath(const path: TPathD; delta: Double;
|
|
joinStyle: TJoinStyle = jsAuto; endType: TClipperEndType = etPolygon;
|
|
miterLimit: double = 2.0; arcTolerance: double = 0.0;
|
|
minEdgeLength: double = 0.25): TPathsD;
|
|
|
|
function InflatePaths(const paths: TPathsD; delta: Double;
|
|
joinStyle: TJoinStyle = jsAuto; endType: TClipperEndType = etPolygon;
|
|
miterLimit: double = 2.0; arcTolerance: double = 0.0;
|
|
minEdgeLength: double = 0): TPathsD;
|
|
|
|
//UnionPolygon: removes self-intersections
|
|
function UnionPolygon(const polygon: TPathD;
|
|
fillRule: TFillRule): TPathsD;
|
|
|
|
function UnionPolygons(const polygons: TPathsD;
|
|
fillRule: TFillRule): TPathsD; overload;
|
|
function UnionPolygons(const polygon1, polygon2: TPathD;
|
|
fillRule: TFillRule): TPathsD; overload;
|
|
function UnionPolygons(const polygons1, polygons2: TPathsD;
|
|
fillRule: TFillRule): TPathsD; overload;
|
|
|
|
function IntersectPolygons(const polygons1, polygons2: TPathsD;
|
|
fillRule: TFillRule): TPathsD;
|
|
|
|
function DifferencePolygons(const polygons1, polygons2: TPathsD;
|
|
fillRule: TFillRule): TPathsD;
|
|
|
|
const
|
|
etPolygon = Clipper.Offset.etPolygon;
|
|
etJoined = Clipper.Offset.etJoined;
|
|
etButt = Clipper.Offset.etButt;
|
|
etSquare = Clipper.Offset.etSquare;
|
|
etRound = Clipper.Offset.etRound;
|
|
|
|
implementation
|
|
|
|
uses Clipper, Clipper.Core, Clipper.Engine;
|
|
|
|
//------------------------------------------------------------------------------
|
|
//------------------------------------------------------------------------------
|
|
|
|
function ClipperEndType(endStyle: TEndStyle): TClipperEndType;
|
|
begin
|
|
case endStyle of
|
|
esPolygon: Result := etJoined;
|
|
esButt: Result := etButt;
|
|
esSquare: Result := etSquare;
|
|
else Result := etRound;
|
|
end;
|
|
end;
|
|
//------------------------------------------------------------------------------
|
|
|
|
function InflatePath(const path: Img32.TPathD;
|
|
delta: Double; joinStyle: TJoinStyle; endType: TClipperEndType;
|
|
miterLimit: double; arcTolerance: double; minEdgeLength: double): Img32.TPathsD;
|
|
var
|
|
paths: Img32.TPathsD;
|
|
begin
|
|
setLength(paths, 1);
|
|
paths[0] := path;
|
|
Result := InflatePaths(paths, delta, joinStyle, endType,
|
|
miterLimit, arcTolerance, minEdgeLength);
|
|
end;
|
|
//------------------------------------------------------------------------------
|
|
|
|
function InflatePaths(const paths: Img32.TPathsD;
|
|
delta: Double; joinStyle: TJoinStyle; endType: TClipperEndType;
|
|
miterLimit: double; arcTolerance: double; minEdgeLength: double): Img32.TPathsD;
|
|
var
|
|
jt: Clipper.Offset.TJoinType;
|
|
begin
|
|
case joinStyle of
|
|
jsSquare : jt := jtSquare;
|
|
jsButt : jt := jtBevel;
|
|
jsMiter : jt := jtMiter;
|
|
jsRound : jt := jtRound;
|
|
else if endType = etRound then jt := jtRound
|
|
else jt := jtSquare;
|
|
end;
|
|
Result := Img32.TPathsD(Clipper.InflatePaths(
|
|
Clipper.Core.TPathsD(paths), delta, jt, endType));
|
|
end;
|
|
//------------------------------------------------------------------------------
|
|
|
|
function UnionPolygon(const polygon: Img32.TPathD;
|
|
fillRule: Img32.Vector.TFillRule): Img32.TPathsD;
|
|
begin
|
|
with TClipperD.Create do
|
|
try
|
|
AddSubject(Clipper.Core.TPathD(polygon));
|
|
Execute(ctUnion,
|
|
Clipper.Core.TFillRule(fillRule), Clipper.Core.TPathsD(result));
|
|
finally
|
|
Free;
|
|
end;
|
|
end;
|
|
//------------------------------------------------------------------------------
|
|
|
|
function UnionPolygons(const polygons: Img32.TPathsD;
|
|
fillRule: Img32.Vector.TFillRule): Img32.TPathsD;
|
|
begin
|
|
with TClipperD.Create do
|
|
try
|
|
AddSubject(Clipper.Core.TPathsD(polygons));
|
|
Execute(ctUnion,
|
|
Clipper.Core.TFillRule(fillRule), Clipper.Core.TPathsD(result));
|
|
finally
|
|
Free;
|
|
end;
|
|
end;
|
|
//------------------------------------------------------------------------------
|
|
|
|
function UnionPolygons(const polygon1, polygon2: Img32.TPathD;
|
|
fillRule: Img32.Vector.TFillRule): Img32.TPathsD;
|
|
begin
|
|
with TClipperD.Create do
|
|
try
|
|
AddSubject(Clipper.Core.TPathD(polygon1));
|
|
AddClip(Clipper.Core.TPathD(polygon2));
|
|
Execute(ctUnion,
|
|
Clipper.Core.TFillRule(fillRule), Clipper.Core.TPathsD(result));
|
|
finally
|
|
Free;
|
|
end;
|
|
end;
|
|
//------------------------------------------------------------------------------
|
|
|
|
function UnionPolygons(const polygons1, polygons2: Img32.TPathsD;
|
|
fillRule: Img32.Vector.TFillRule): Img32.TPathsD;
|
|
begin
|
|
with TClipperD.Create do
|
|
try
|
|
AddSubject(Clipper.Core.TPathsD(polygons1));
|
|
AddClip(Clipper.Core.TPathsD(polygons2));
|
|
Execute(ctUnion,
|
|
Clipper.Core.TFillRule(fillRule), Clipper.Core.TPathsD(result));
|
|
finally
|
|
Free;
|
|
end;
|
|
end;
|
|
//------------------------------------------------------------------------------
|
|
|
|
function IntersectPolygons(const polygons1, polygons2: Img32.TPathsD;
|
|
fillRule: Img32.Vector.TFillRule): Img32.TPathsD;
|
|
begin
|
|
with TClipperD.Create do
|
|
try
|
|
AddSubject(Clipper.Core.TPathsD(polygons1));
|
|
AddClip(Clipper.Core.TPathsD(polygons2));
|
|
Execute(ctIntersection,
|
|
Clipper.Core.TFillRule(fillRule), Clipper.Core.TPathsD(result));
|
|
finally
|
|
Free;
|
|
end;
|
|
end;
|
|
//------------------------------------------------------------------------------
|
|
|
|
function DifferencePolygons(const polygons1, polygons2: Img32.TPathsD;
|
|
fillRule: Img32.Vector.TFillRule): Img32.TPathsD;
|
|
begin
|
|
with TClipperD.Create do
|
|
try
|
|
AddSubject(Clipper.Core.TPathsD(polygons1));
|
|
AddClip(Clipper.Core.TPathsD(polygons2));
|
|
Execute(ctDifference,
|
|
Clipper.Core.TFillRule(fillRule), Clipper.Core.TPathsD(result));
|
|
finally
|
|
Free;
|
|
end;
|
|
end;
|
|
//------------------------------------------------------------------------------
|
|
|
|
end.
|