From a03dd460df8bcc5875870031841d67b629a89fc6 Mon Sep 17 00:00:00 2001 From: Jarl Holta Date: Sun, 28 Jul 2024 01:18:46 +0200 Subject: [PATCH] Add: IsConvexPolygon --- Source/script/imports/simba.import_math.pas | 29 ++++++++++++++++++--- Source/simba.geometry.pas | 25 ++++++++++++++++++ 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/Source/script/imports/simba.import_math.pas b/Source/script/imports/simba.import_math.pas index af31fe233..a33fad7d1 100644 --- a/Source/script/imports/simba.import_math.pas +++ b/Source/script/imports/simba.import_math.pas @@ -203,9 +203,27 @@ procedure _LapePolygonArea(const Params: PParamArray; const Result: Pointer); LA end; (* -PolygonArea +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): 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. *) procedure _LapeTriangulatePolygon(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV begin @@ -213,9 +231,11 @@ procedure _LapeTriangulatePolygon(const Params: PParamArray; const Result: Point end; (* -PolygonArea +LineInPolygon ----------- -> function LineInPolygon(a1, a2: TPoint; const Polygon: TPointArray): Boolean; +> 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 @@ -406,7 +426,8 @@ procedure ImportMath(Compiler: TSimbaScript_Compiler); 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): TTriangleArray', @_LapeTriangulatePolygon); addGlobalFunc('function LineInPolygon(a1, a2: TPoint; const Polygon: TPointArray): Boolean', @_LapeLineInPolygon); diff --git a/Source/simba.geometry.pas b/Source/simba.geometry.pas index aaf10ffd6..66a362380 100644 --- a/Source/simba.geometry.pas +++ b/Source/simba.geometry.pas @@ -11,6 +11,9 @@ - PointInEllipse - AngleBetween - DeltaAngle + - IsConvexPolygon + - LineInPolygon + - TriangulatePolygon } { @@ -43,6 +46,7 @@ TSimbaGeometry = class public class constructor Create; + class function IsConvexPolygon(const Polygon: TPointArray): Boolean; class function LineInPolygon(a1, a2: TPoint; const Polygon: TPointArray): Boolean; class function TriangulatePolygon(Polygon: TPointArray): TTriangleArray; class function PolygonArea(const Polygon: TPointArray): Double; static; inline; @@ -348,6 +352,27 @@ class function TSimbaGeometry.PointInEllipse(const P, Center: TPoint; const YRad Result := (Sqr(X) * Sqr(YRadius)) + (Sqr(Y) * Sqr(XRadius)) <= (Sqr(YRadius) * Sqr(XRadius)); end; +class function TSimbaGeometry.IsConvexPolygon(const Polygon: TPointArray): Boolean; +var + i,d: Int32; + a,b,c: TPoint; +begin + if Length(Polygon) = 0 then Exit(False); + + d := CrossProduct(Polygon[i],Polygon[(i+1) mod Length(Polygon)],Polygon[(i+2) mod Length(Polygon)]); + for i:=0 to High(Polygon) do + begin + A := Polygon[i]; + B := Polygon[(i+1) mod Length(Polygon)]; + C := Polygon[(i+2) mod Length(Polygon)]; + + if CrossProduct(A,B,C)*d <= 0 then + Exit(False); + end; + + Result := True; +end; + class function TSimbaGeometry.LineInPolygon(a1, a2: TPoint; const Polygon: TPointArray): Boolean; var i: Int32;