Skip to content

Commit

Permalink
Add polygon type
Browse files Browse the repository at this point in the history
  • Loading branch information
ollydev committed Jan 6, 2025
1 parent b46dbb5 commit 26b195f
Show file tree
Hide file tree
Showing 15 changed files with 568 additions and 387 deletions.
87 changes: 0 additions & 87 deletions Source/script/imports/simba.import_math.pas
Original file line number Diff line number Diff line change
Expand Up @@ -214,86 +214,6 @@ procedure _LapeDeltaAngle(const Params: PParamArray; const Result: Pointer); LAP
PDouble(Result)^ := TSimbaGeometry.DeltaAngle(PDouble(Params^[0])^, PDouble(Params^[1])^, PDouble(Params^[2])^);
end;

(*
ExpandPolygon
-------------
```
function ExpandPolygon(const Polygon: TPointArray; Amount: Integer): TPointArray;
```
*)
procedure _LapeExpandPolygon(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV
begin
PPointArray(Result)^ := TSimbaGeometry.ExpandPolygon(PPointArray(Params^[0])^, PInteger(Params^[1])^);
end;

(*
PolygonArea
-----------
```
function PolygonArea(const Polygon: TPointArray): Double;
```
*)
procedure _LapePolygonArea(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV
begin
PDouble(Result)^ := TSimbaGeometry.PolygonArea(PPointArray(Params^[0])^);
end;

(*
IsConvexPolygon
-----------
> function IsConvexPolygon(Polygon: TPointArray): Boolean;
Returns if the polygon is convex, order does not matter. A concave polygon will return False.
*)
procedure _LapeIsConvexPolygon(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV
begin
PBoolean(Result)^ := TSimbaGeometry.IsConvexPolygon(PPointArray(Params^[0])^);
end;

(*
TriangulatePolygon
-----------
> function TriangulatePolygon(Polygon: TPointArray; MinArea: Double=0; MaxDepth: Int32=0): TTriangleArray;
Break the polygon into triangles, the smallest possible polygon. The order of the
input does matter, if it fails, try to reverse the Poly with Poly.Reversed()
This is a custom algorithm by slacky, based around the concept of trimming "ears",
if you dont like the output, you may have more luck with rolling the Polygon before calling.
Two default params exists as well, `MinArea` and `MaxDepth`, they work in tandom,
`MinArea` parameter is for setting a minimum size of triangles added to result, and as this method
works iteratively, removing triangles in a circle around the shape over and over, `MaxDepth` refers
to the max number of rounds it has moved around the shape before it ignores `MinArea` paramater.
*)
procedure _LapeTriangulatePolygon(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV
begin
PTriangleArray(Result)^ := TSimbaGeometry.TriangulatePolygon(PPointArray(Params^[0])^, PSingle(Params^[1])^, PInt32(Params^[2])^);
end;

(*
LineInPolygon
-----------
> function LineInPolygon(p,q: TPoint; const Polygon: TPointArray): Boolean;
Returns True if the line fits within the bounds of the polygon.
*)
procedure _LapeLineInPolygon(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV
begin
PBoolean(Result)^ := TSimbaGeometry.LineInPolygon(PPoint(Params^[0])^, PPoint(Params^[1])^, PPointArray(Params^[2])^);
end;

(*
FurthestPointsPolygon
-----------
> procedure FurthestPointsPolygon(const Polygon: TPointArray; out A,B: TPoint);
Returns the two points that are furthest away from eachother in a polygon.
*)
procedure _LapeFurthestPointsPolygon(const Params: PParamArray); LAPE_WRAPPER_CALLING_CONV
begin
TSimbaGeometry.FurthestPointsPolygon(PPointArray(Params^[0])^, PPoint(Params^[1])^, PPoint(Params^[2])^);
end;

(*
CrossProduct
Expand Down Expand Up @@ -507,15 +427,8 @@ procedure ImportMath(Script: TSimbaScript);

addGlobalFunc('function Modulo(const X, Y: Integer): Integer; overload', @_LapeModulo);
addGlobalFunc('function Modulo(const X, Y: Double): Double; overload', @_LapeModuloF);

addGlobalFunc('function IsConvexPolygon(const Polygon: TPointArray): Boolean', @_LapeIsConvexPolygon);
addGlobalFunc('function TriangulatePolygon(const Polygon: TPointArray; MinArea: Single=0; MaxDepth: Int32=0): TTriangleArray', @_LapeTriangulatePolygon);
addGlobalFunc('function LineInPolygon(a1, a2: TPoint; const Polygon: TPointArray): Boolean', @_LapeLineInPolygon);
addGlobalFunc('procedure FurthestPointsPolygon(const Polygon: TPointArray; out A,B: TPoint)', @_LapeFurthestPointsPolygon);

addGlobalFunc('function DeltaAngle(const DegreesA, DegreesB: Double; R: Double = 360): Double', @_LapeDeltaAngle);
addGlobalFunc('function PolygonArea(const Polygon: TPointArray): Double', @_LapePolygonArea);
addGlobalFunc('function ExpandPolygon(const Polygon: TPointArray; Amount: Integer): TPointArray', @_LapeExpandPolygon);

addGlobalFunc('function CrossProduct(const r, p, q: TPoint): Int64; overload', @_LapeCrossProduct1);
addGlobalFunc('function CrossProduct(const rx,ry, px,py, qx,qy: Double): Double; overload', @_LapeCrossProduct2);
Expand Down
22 changes: 13 additions & 9 deletions Source/script/imports/simba.import_point.pas
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,17 @@ procedure ImportPoint(Script: TSimbaScript);
implementation

uses
simba.vartype_point, simba.vartype_pointarray,
simba.vartype_point, simba.vartype_pointarray, simba.vartype_polygon,
lptypes;

type
PPolygon = ^TPolygon;
PPolygonArray = ^TPolygonArray;

(*
TPoint
======
The TPoint type is a record which defines a X,Y coordinate.
The TPoint type is a record which defines a X,Y integer coordinate.
*)

(*
Expand Down Expand Up @@ -935,12 +939,12 @@ procedure _LapeTPAEdges(const Params: PParamArray; const Result: Pointer); LAPE_
TPointArray.ConvexHull
----------------------
```
function TPointArray.ConvexHull: TPointArray;
function TPointArray.ConvexHull: TPolygon;
```
*)
procedure _LapeTPAConvexHull(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV
begin
PPointArray(Result)^ := PPointArray(Params^[0])^.ConvexHull();
PPolygon(Result)^ := PPointArray(Params^[0])^.ConvexHull();
end;

(*
Expand Down Expand Up @@ -1165,24 +1169,24 @@ procedure _LapeTPADouglasPeucker(const Params: PParamArray; const Result: Pointe
TPointArray.ConcaveHull
-----------------------
```
function TPointArray.ConcaveHull(Epsilon:Double=2.5; kCount:Int32=5): TPointArray;
function TPointArray.ConcaveHull(Epsilon:Double=2.5; kCount:Int32=5): TPolygon;
```
*)
procedure _LapeTPAConcaveHull(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV
begin
PPointArray(Result)^ := PPointArray(Params^[0])^.ConcaveHull(PDouble(Params^[1])^, PInteger(Params^[2])^);
PPolygon(Result)^ := PPointArray(Params^[0])^.ConcaveHull(PDouble(Params^[1])^, PInteger(Params^[2])^);
end;

(*
TPointArray.ConcaveHullEx
-------------------------
```
function TPointArray.ConcaveHullEx(MaxLeap: Double=-1; Epsilon:Double=2): T2DPointArray;
function TPointArray.ConcaveHullEx(MaxLeap: Double=-1; Epsilon:Double=2): TPolygonArray;
```
*)
procedure _LapeTPAConcaveHullEx(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV
begin
P2DPointArray(Result)^ := PPointArray(Params^[0])^.ConcaveHullEx(PDouble(Params^[1])^, PDouble(Params^[2])^);
PPolygonArray(Result)^ := PPointArray(Params^[0])^.ConcaveHullEx(PDouble(Params^[1])^, PDouble(Params^[2])^);
end;

(*
Expand Down Expand Up @@ -1652,7 +1656,7 @@ procedure ImportPoint(Script: TSimbaScript);
addGlobalFunc('function TPointArray.Skeleton(FMin: Integer = 2; FMax: Integer = 6): TPointArray;', @_LapeTPASkeleton);
addGlobalFunc('function TPointArray.Border: TPointArray;', @_LapeTPABorder);
addGlobalFunc('function TPointArray.Edges: TPointArray;', @_LapeTPAEdges);
addGlobalFunc('function TPointArray.ConvexHull: TPointArray;', @_LapeTPAConvexHull);
addGlobalFunc('function TPointArray.ConvexHull: TPolygon;', @_LapeTPAConvexHull);

addGlobalFunc('function TPointArray.Erode(Iterations: Integer): TPointArray;', @_LapeTPAErode);
addGlobalFunc('function TPointArray.Grow(Iterations: Integer): TPointArray;', @_LapeTPAGrow);
Expand Down
145 changes: 145 additions & 0 deletions Source/script/imports/simba.import_polygon.pas
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
{
Author: Raymond van Venetië and Merlijn Wajer
Project: Simba (https://github.com/MerlijnWajer/Simba)
License: GNU General Public License (https://www.gnu.org/licenses/gpl-3.0)
}
unit simba.import_polygon;

{$i simba.inc}

interface

uses
Classes, SysUtils,
simba.base, simba.script;

procedure ImportPolygon(Script: TSimbaScript);

implementation

uses
lptypes,
simba.vartype_polygon;

type
PPolygon = ^TPolygon;

(*
Polygon
=======
Polygon type
*)

procedure _LapePolygon_Area(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV
begin
PDouble(Result)^ := PPolygon(Params^[0])^.Area;
end;

(*
TPolygon.IsConvex
-----------------
```
function TPolygon.IsConvex(Polygon: TPointArray): Boolean;
```
Returns if the polygon is convex, order does not matter. A concave polygon will return False.
*)
procedure _LapePolygon_IsConvex(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV
begin
PBoolean(Result)^ := PPolygon(Params^[0])^.IsConvex;
end;

procedure _LapePolygon_Contains(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV
begin
PBoolean(Result)^ := PPolygon(Params^[0])^.Contains(PPoint(Params^[1])^);
end;


(*
TPolygon.ContainsLine
---------------------
```
function TPolygon.ContainsLine(p,q: TPoint): Boolean;
```
Returns True if the line fits within the bounds of the polygon.
*)
procedure _LapePolygon_ContainsLine(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV
begin
PBoolean(Result)^ := PPolygon(Params^[0])^.ContainsLine(PPoint(Params^[1])^, PPoint(Params^[2])^);
end;

procedure _LapePolygon_NearestEdge(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV
begin
PPoint(Result)^ := PPolygon(Params^[0])^.NearestEdge(PPoint(Params^[1])^);
end;

procedure _LapePolygon_Expand(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV
begin
PPolygon(Result)^ := PPolygon(Params^[0])^.Expand(PInteger(Params^[1])^);
end;

(*
TPolygon.Triangulate
--------------------
```
function TPolygon.Triangulate(MinArea: Double = 0; MaxDepth: Int32 = 0): TTriangleArray;
```
Break the polygon into triangles, the smallest possible polygon. The order of the
input does matter, if it fails, try to reverse the Poly with Poly.Reversed()
This is a custom algorithm by slacky, based around the concept of trimming "ears",
if you dont like the output, you may have more luck with rolling the Polygon before calling.
Two default params exists as well, `MinArea` and `MaxDepth`, they work in tandom,
`MinArea` parameter is for setting a minimum size of triangles added to result, and as this method
works iteratively, removing triangles in a circle around the shape over and over, `MaxDepth` refers
to the max number of rounds it has moved around the shape before it ignores `MinArea` paramater.
*)
procedure _LapePolygon_Triangulate(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV
begin
PTriangleArray(Result)^ := PPolygon(Params^[0])^.Triangulate(PInteger(Params^[1])^, PInteger(Params^[2])^);
end;

(*
TPolygon.FurthestPoints
-----------------------
> procedure TPolygon.FurthestPoints(out A,B: TPoint);
Returns the two points that are furthest away from eachother in a polygon.
*)
procedure _LapePolygon_FurthestPoints(const Params: PParamArray); LAPE_WRAPPER_CALLING_CONV
begin
PPolygon(Params^[0])^.FurthestPoints(PPoint(Params^[1])^, PPoint(Params^[2])^);
end;

procedure _LapePoint_IN_Polygon(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV
begin
PBoolean(Result)^ := PPoint(Params^[0])^ in PPolygon(Params^[1])^;
end;

procedure ImportPolygon(Script: TSimbaScript);
begin
with Script.Compiler do
begin
DumpSection := 'TPolygon';

addGlobalType('array of TPoint', 'TPolygon');
addGlobalType('array of TPolygon', 'TPolygonArray');

addGlobalFunc('function TPolygon.Area: Double', @_LapePolygon_Area);
addGlobalFunc('function TPolygon.IsConvex: Boolean', @_LapePolygon_IsConvex);
addGlobalFunc('function TPolygon.Contains(p: TPoint): Boolean', @_LapePolygon_Contains);
addGlobalFunc('function TPolygon.ContainsLine(a1, a2: TPoint): Boolean', @_LapePolygon_ContainsLine);
addGlobalFunc('function TPolygon.NearestEdge(P: TPoint): TPoint', @_LapePolygon_NearestEdge);
addGlobalFunc('function TPolygon.Expand(Amount: Integer): TPolygon', @_LapePolygon_Expand);
addGlobalFunc('function TPolygon.Triangulate(MinArea: Single; MaxDepth: Int32): TTriangleArray;', @_LapePolygon_Triangulate);
addGlobalFunc('procedure TPolygon.FurthestPoints(out A, B: TPoint);', @_LapePolygon_FurthestPoints);

addGlobalFunc('operator in(Left: TPoint; Right: TPolygon): Boolean;', @_LapePoint_IN_Polygon);

DumpSection := '';
end;
end;

end.

5 changes: 3 additions & 2 deletions Source/script/simba.script_imports.pas
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ implementation
simba.import_async,

// Simba shapes
simba.import_quad, simba.import_triangle, simba.import_box, simba.import_point, simba.import_circle,
simba.import_quad, simba.import_triangle, simba.import_box, simba.import_point, simba.import_circle, simba.import_polygon,


// Simba classes
Expand Down Expand Up @@ -68,7 +68,8 @@ procedure AddSimbaImports(Script: TSimbaScript);
ImportColorMath(Script);
ImportMatrix(Script);
ImportWindowHandle(Script);


ImportPolygon(Script);
ImportQuad(Script);
ImportCircle(Script);
ImportBox(Script);
Expand Down
10 changes: 10 additions & 0 deletions Source/simba.base.pas
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,7 @@ procedure Swap(var A, B: Single); inline; overload;
procedure Swap(var A, B: Double); inline; overload;
procedure Swap(var A, B: TColorBGRA); inline; overload;
procedure Swap(var A, B: Pointer); inline; overload;
procedure Swap(var A, B: TPoint); inline; overload;

function IfThen(const Val: Boolean; const IfTrue, IfFalse: String): String; inline; overload;
function IfThen(const Val: Boolean; const IfTrue, IfFalse: Int64): Int64; inline; overload;
Expand Down Expand Up @@ -606,6 +607,15 @@ procedure Swap(var A, B: Pointer);
B := Temp;
end;

procedure Swap(var A, B: TPoint);
var
Temp: TPoint;
begin
Temp := A;
A := B;
B := Temp;
end;

function IfThen(const Val: Boolean; const IfTrue, IfFalse: String): String;
begin
Result := specialize IfThen<String>(Val, IfTrue, IfFalse);
Expand Down
4 changes: 2 additions & 2 deletions Source/simba.component_shapebox.pas
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ implementation

uses
LCLType, simba.geometry, simba.vartype_pointarray,
simba.vartype_box, simba.vartype_string, simba.vartype_point;
simba.vartype_box, simba.vartype_string, simba.vartype_point, simba.vartype_polygon;

const
CLOSE_DISTANCE = 4;
Expand Down Expand Up @@ -504,7 +504,7 @@ procedure TSimbaShapeBoxShape_Path.Paint(Sender: TSimbaShapeBox; ACanvas: TSimba

procedure TSimbaShapeBoxShape_Poly.BuildContainsCache;
begin
FContainsCache := TSimbaGeometry.ExpandPolygon(FPoly.ConvexHull(), CLOSE_DISTANCE);
FContainsCache := FPoly.ConvexHull().Expand(CLOSE_DISTANCE);
end;

procedure TSimbaShapeBoxShape_Poly.SelectingMouseDown(Sender: TSimbaShapeBox; Button: TMouseButton; Shift: TShiftState; MousePoint: TPoint);
Expand Down
Loading

0 comments on commit 26b195f

Please sign in to comment.