17
TSingleCircl2 = record
22
constructor Create(const P1_, P2_, P3_: TSingle2D); overload;
25
TDoubleCircl2 = record
30
constructor Create(const P1_, P2_, P3_: TDouble2D); overload;
33
TSingleCircle = record
38
constructor Create(const P1_, P2_, P3_: TSingle2D); overload;
39
class operator Implicit(const Circl2_: TSingleCircl2): TSingleCircle;
40
class operator Implicit(const Circle_: TSingleCircle): TSingleCircl2;
43
TDoubleCircle = record
48
constructor Create(const P1_, P2_, P3_: TDouble2D); overload;
49
class operator Implicit(const Circl2_: TDoubleCircl2): TDoubleCircle;
50
class operator Implicit(const Circle_: TDoubleCircle): TDoubleCircl2;
64
TSingleTria2D = record
66
function GetNorv: Single;
67
function GetEdge1: TSingle2D;
68
function GetEdge2: TSingle2D;
69
function GetEdge3: TSingle2D;
70
function GetEnor1: TSingle2D;
71
function GetEnor2: TSingle2D;
72
function GetEnor3: TSingle2D;
73
function GetAABB: TSingleArea2D;
78
property Norv: Single read GetNorv;
79
property Edge1: TSingle2D read GetEdge1;
80
property Edge2: TSingle2D read GetEdge2;
81
property Edge3: TSingle2D read GetEdge3;
82
property Enor1: TSingle2D read GetEnor1;
83
property Enor2: TSingle2D read GetEnor2;
84
property Enor3: TSingle2D read GetEnor3;
85
property AABB: TSingleArea2D read GetAABB;
86
function ColliEdge(const Area_: TSingleArea2D): Boolean;
87
function Collision(const Area_: TSingleArea2D): Boolean;
100
TDoubleTria2D = record
102
function GetNorv: Double;
103
function GetEdge1: TDouble2D;
104
function GetEdge2: TDouble2D;
105
function GetEdge3: TDouble2D;
106
function GetEnor1: TDouble2D;
107
function GetEnor2: TDouble2D;
108
function GetEnor3: TDouble2D;
109
function GetAABB: TDoubleArea2D;
114
property Norv: Double read GetNorv;
115
property Edge1: TDouble2D read GetEdge1;
116
property Edge2: TDouble2D read GetEdge2;
117
property Edge3: TDouble2D read GetEdge3;
118
property Enor1: TDouble2D read GetEnor1;
119
property Enor2: TDouble2D read GetEnor2;
120
property Enor3: TDouble2D read GetEnor3;
121
property AABB: TDoubleArea2D read GetAABB;
122
function ColliEdge(const Area_: TDoubleArea2D): Boolean;
123
function Collision(const Area_: TDoubleArea2D): Boolean;
127
// ---------------------------------------------------------------------------
129
function HeronAre2(const L1_, L2_, L3_: Single): Single; overload;
130
function HeronAre2(const L1_, L2_, L3_: Double): Double; overload;
132
function HeronArea(const L1_, L2_, L3_: Single): Single; overload;
133
function HeronArea(const L1_, L2_, L3_: Double): Double; overload;
135
function LineNormal(const P0_, P1_: TSingle2D): TSingle2D; overload;
136
function LineNormal(const P0_, P1_: TDouble2D): TDouble2D; overload;
138
function Barycenter(const P1_, P2_: TSinglePos2D): TSinglePos2D; overload;
139
function Barycenter(const P1_, P2_: TDoublePos2D): TDoublePos2D; overload;
141
function Barycenter(const P1_, P2_, P3_: TSinglePos2D): TSinglePos2D; overload;
142
function Barycenter(const P1_, P2_, P3_: TDoublePos2D): TDoublePos2D; overload;
144
function InnerRadius(const P1_, P2_, P3_: TSinglePos2D): Single; overload;
145
function InnerRadius(const P1_, P2_, P3_: TDoublePos2D): Double; overload;
147
function InnerCenter(const P1_, P2_, P3_: TSinglePos2D): TSinglePos2D; overload;
148
function InnerCenter(const P1_, P2_, P3_: TDoublePos2D): TDoublePos2D; overload;
150
function CircumCenter(const P1_, P2_, P3_: TSingle2D): TSingle2D; overload;
151
function CircumCenter(const P1_, P2_, P3_: TDouble2D): TDouble2D; overload;
153
function CurveLength(const Ps_: array of TSingle2D): Single; overload;
154
function CurveLength(const Ps_: array of TDouble2D): Single; overload;
156
function ClosedCurveLength(const Ps_: array of TSingle2D): Single; overload;
157
function ClosedCurveLength(const Ps_: array of TDouble2D): Single; overload;
159
function BoundingBox(const Ps_: array of TSingle2D): TSingleArea2D; overload;
160
function BoundingBox(const Ps_: array of TDouble2D): TDoubleArea2D; overload;
162
function ShapeMatch(const Vs0_, Vs1_: array of TSingle2D): TSingleM2; overload;
163
function ShapeMatch(const Vs0_, Vs1_: array of TDouble2D): TDoubleM2; overload;
165
function InsideLoop(const P_: TSingle2D; const Ps_: TArray<TSingle2D>)
167
function InsideLoop(const P_: TDouble2D; const Ps_: TArray<TDouble2D>)
170
implementation // -------------------------------------------------------------
172
constructor TSingleCircl2.Create(const P1_, P2_, P3_: TSingle2D);
174
Center := CircumCenter(P1_, P2_, P3_);
175
Radiu2 := (Distanc2(Center, P1_) + Distanc2(Center, P2_) + Distanc2(Center,
179
constructor TDoubleCircl2.Create(const P1_, P2_, P3_: TDouble2D);
181
Center := CircumCenter(P1_, P2_, P3_);
182
Radiu2 := (Distanc2(Center, P1_) + Distanc2(Center, P2_) + Distanc2(Center,
186
constructor TSingleCircle.Create(const P1_, P2_, P3_: TSingle2D);
188
Self := TSingleCircl2.Create(P1_, P2_, P3_);
191
class operator TSingleCircle.Implicit(const Circl2_: TSingleCircl2)
196
Center := Circl2_.Center;
197
Radius := Roo2(Circl2_.Radiu2);
201
class operator TSingleCircle.Implicit(const Circle_: TSingleCircle)
206
Center := Circle_.Center;
207
Radiu2 := Pow2(Circle_.Radius);
211
constructor TDoubleCircle.Create(const P1_, P2_, P3_: TDouble2D);
213
Self := TDoubleCircl2.Create(P1_, P2_, P3_);
216
class operator TDoubleCircle.Implicit(const Circl2_: TDoubleCircl2)
221
Center := Circl2_.Center;
222
Radius := Roo2(Circl2_.Radiu2);
226
class operator TDoubleCircle.Implicit(const Circle_: TDoubleCircle)
231
Center := Circle_.Center;
232
Radiu2 := Pow2(Circle_.Radius);
236
function TSingleTria2D.GetNorv: Single;
238
Result := CrossProduct(Edge2, Edge3);
241
// ------------------------------------------------------------------------------
243
function TSingleTria2D.GetEdge1: TSingle2D;
245
Result := Poin2.VectorTo(Poin3);
248
function TSingleTria2D.GetEdge2: TSingle2D;
250
Result := Poin3.VectorTo(Poin1);
253
function TSingleTria2D.GetEdge3: TSingle2D;
255
Result := Poin1.VectorTo(Poin2);
258
// ------------------------------------------------------------------------------
260
function TSingleTria2D.GetEnor1: TSingle2D;
262
Result := Norv * Edge1.RotL90;
265
function TSingleTria2D.GetEnor2: TSingle2D;
267
Result := Norv * Edge2.RotL90;
270
function TSingleTria2D.GetEnor3: TSingle2D;
272
Result := Norv * Edge3.RotL90;
275
// ------------------------------------------------------------------------------
277
function TSingleTria2D.GetAABB: TSingleArea2D;
281
ProjX := TSingleArea.Create(Poin1.X, Poin2.X, Poin3.X);
282
ProjY := TSingleArea.Create(Poin1.Y, Poin2.Y, Poin3.Y);
286
// ······································
288
function TSingleTria2D.ColliEdge(const Area_: TSingleArea2D): Boolean;
289
(*sub*)function CheckEdge(const N, P: TSingle2D): Boolean;
293
B := Area_.Poin[N.Orthant];
297
Result := DotProduct(N, V) >= 0;
300
// ······································
312
Result := CheckEdge(Enor1, Poin2) and CheckEdge(Enor2, Poin3) and
313
CheckEdge(Enor3, Poin1);
316
function TSingleTria2D.Collision(const Area_: TSingleArea2D): Boolean;
318
Result := AABB.Collision(Area_) and ColliEdge(Area_);
321
function TDoubleTria2D.GetNorv: Double;
323
Result := CrossProduct(Edge2, Edge3);
326
// ------------------------------------------------------------------------------
328
function TDoubleTria2D.GetEdge1: TDouble2D;
330
Result := Poin2.VectorTo(Poin3);
333
function TDoubleTria2D.GetEdge2: TDouble2D;
335
Result := Poin3.VectorTo(Poin1);
338
function TDoubleTria2D.GetEdge3: TDouble2D;
340
Result := Poin1.VectorTo(Poin2);
343
// ------------------------------------------------------------------------------
345
function TDoubleTria2D.GetEnor1: TDouble2D;
347
Result := Norv * Edge1.RotL90;
350
function TDoubleTria2D.GetEnor2: TDouble2D;
352
Result := Norv * Edge2.RotL90;
355
function TDoubleTria2D.GetEnor3: TDouble2D;
357
Result := Norv * Edge3.RotL90;
360
// ------------------------------------------------------------------------------
362
function TDoubleTria2D.GetAABB: TDoubleArea2D;
366
ProjX := TDoubleArea.Create(Poin1.X, Poin2.X, Poin3.X);
367
ProjY := TDoubleArea.Create(Poin1.Y, Poin2.Y, Poin3.Y);
371
// ······································
372
function TDoubleTria2D.ColliEdge(const Area_: TDoubleArea2D): Boolean;
373
(*sub*)function CheckEdge(const N, P: TDouble2D): Boolean;
377
B := Area_.Poin[N.Orthant];
381
Result := DotProduct(N, V) >= 0;
384
// ······································
396
Result := CheckEdge(Enor1, Poin2) and CheckEdge(Enor2, Poin3) and
397
CheckEdge(Enor3, Poin1);
400
function TDoubleTria2D.Collision(const Area_: TDoubleArea2D): Boolean;
402
Result := AABB.Collision(Area_) and ColliEdge(Area_);
405
function HeronAre2(const L1_, L2_, L3_: Single): Single;
409
S := (L1_ + L2_ + L3_) / 2;
411
Result := S * (S - L1_) * (S - L2_) * (S - L3_);
414
function HeronAre2(const L1_, L2_, L3_: Double): Double;
418
S := (L1_ + L2_ + L3_) / 2;
420
Result := S * (S - L1_) * (S - L2_) * (S - L3_);
423
// ------------------------------------------------------------------------------
425
function HeronArea(const L1_, L2_, L3_: Single): Single;
427
Result := Roo2(HeronAre2(L1_, L2_, L3_));
430
function HeronArea(const L1_, L2_, L3_: Double): Double;
432
Result := Roo2(HeronAre2(L1_, L2_, L3_));
435
// ------------------------------------------------------------------------------
437
function LineNormal(const P0_, P1_: TSingle2D): TSingle2D;
439
with P0_.VectorTo(P1_) do
446
function LineNormal(const P0_, P1_: TDouble2D): TDouble2D;
448
with P0_.VectorTo(P1_) do
455
// ------------------------------------------------------------------------------
457
function Barycenter(const P1_, P2_: TSinglePos2D): TSinglePos2D;
459
Result := Ave(P1_, P2_);
462
function Barycenter(const P1_, P2_: TDoublePos2D): TDoublePos2D;
464
Result := Ave(P1_, P2_);
467
function Barycenter(const P1_, P2_, P3_: TSinglePos2D): TSinglePos2D;
469
Result := Ave(P1_, P2_, P3_);
472
function Barycenter(const P1_, P2_, P3_: TDoublePos2D): TDoublePos2D;
474
Result := Ave(P1_, P2_, P3_);
477
// ------------------------------------------------------------------------------
479
function InnerRadius(const P1_, P2_, P3_: TSinglePos2D): Single;
481
L1, L2, L3, S: Single;
483
L1 := Distance(P2_, P3_);
484
L2 := Distance(P3_, P1_);
485
L3 := Distance(P1_, P2_);
487
S := (L1 + L2 + L3) / 2;
489
Result := Roo2((S - L1) * (S - L2) * (S - L3) / S);
492
function InnerRadius(const P1_, P2_, P3_: TDoublePos2D): Double;
494
L1, L2, L3, S: Single;
496
L1 := Distance(P2_, P3_);
497
L2 := Distance(P3_, P1_);
498
L3 := Distance(P1_, P2_);
500
S := (L1 + L2 + L3) / 2;
502
Result := Roo2((S - L1) * (S - L2) * (S - L3) / S);
505
// ------------------------------------------------------------------------------
507
function InnerCenter(const P1_, P2_, P3_: TSinglePos2D): TSinglePos2D;
511
L1 := Distance(P2_, P3_);
512
L2 := Distance(P3_, P1_);
513
L3 := Distance(P1_, P2_);
515
Result := (L1 * P1_ + L2 * P2_ + L3 * P3_) / (L1 + L2 + L3);
518
function InnerCenter(const P1_, P2_, P3_: TDoublePos2D): TDoublePos2D;
522
L1 := Distance(P2_, P3_);
523
L2 := Distance(P3_, P1_);
524
L3 := Distance(P1_, P2_);
526
Result := (L1 * P1_ + L2 * P2_ + L3 * P3_) / (L1 + L2 + L3);
529
// ------------------------------------------------------------------------------
531
function CircumCenter(const P1_, P2_, P3_: TSingle2D): TSingle2D;
533
L1, L2, L3, W: Single;
534
E1, E2, E3: TSingle2D;
543
W := 2 * (P2_.X * P1_.Y - P1_.X * P2_.Y + P3_.X * P2_.Y - P2_.X * P3_.Y +
544
P1_.X * P3_.Y - P3_.X * P1_.Y);
548
X := (L1 * E1.Y + L2 * E2.Y + L3 * E3.Y) / +W;
549
Y := (L1 * E1.X + L2 * E2.X + L3 * E3.X) / -W;
553
function CircumCenter(const P1_, P2_, P3_: TDouble2D): TDouble2D;
555
L1, L2, L3, W: Double;
556
E1, E2, E3: TDouble2D;
565
W := 2 * (P2_.X * P1_.Y - P1_.X * P2_.Y + P3_.X * P2_.Y - P2_.X * P3_.Y +
566
P1_.X * P3_.Y - P3_.X * P1_.Y);
570
X := (L1 * E1.Y + L2 * E2.Y + L3 * E3.Y) / +W;
571
Y := (L1 * E1.X + L2 * E2.X + L3 * E3.X) / -W;
575
// ------------------------------------------------------------------------------
577
function CurveLength(const Ps_: array of TSingle2D): Single;
585
for I := 1 to High(Ps_) do
590
Result := Result + Distance(P0, P1);
594
function CurveLength(const Ps_: array of TDouble2D): Single;
602
for I := 1 to High(Ps_) do
607
Result := Result + Distance(P0, P1);
611
// ------------------------------------------------------------------------------
613
function ClosedCurveLength(const Ps_: array of TSingle2D): Single;
616
P0, P1, P2: TSingle2D;
623
for I := 1 to High(Ps_) do
628
Result := Result + Distance(P0, P1);
631
Result := Result + Distance(P1, P2);
634
function ClosedCurveLength(const Ps_: array of TDouble2D): Single;
637
P0, P1, P2: TDouble2D;
644
for I := 1 to High(Ps_) do
649
Result := Result + Distance(P0, P1);
652
Result := Result + Distance(P1, P2);
655
// ------------------------------------------------------------------------------
657
function BoundingBox(const Ps_: array of TSingle2D): TSingleArea2D;
661
Result := TSingleArea2D.NeInf;
665
if P.X < Result.Min.X then
667
if P.Y < Result.Min.Y then
670
if Result.Max.X < P.X then
672
if Result.Max.Y < P.Y then
677
function BoundingBox(const Ps_: array of TDouble2D): TDoubleArea2D;
681
Result := TDoubleArea2D.NeInf;
685
if P.X < Result.Min.X then
687
if P.Y < Result.Min.Y then
690
if Result.Max.X < P.X then
692
if Result.Max.Y < P.Y then
697
// ------------------------------------------------------------------------------
699
function ShapeMatch(const Vs0_, Vs1_: array of TSingle2D): TSingleM2;
705
Result := TSingleM2.Create(0, 0, 0, 0);
707
for I := 0 to High(Vs0_) do
714
_11 := V1.X * V0.X + V1.Y * V0.Y;
715
_12 := V1.X * V0.Y - V1.Y * V0.X;
716
_21 := V1.Y * V0.X - V1.X * V0.Y;
717
_22 := V1.X * V0.X + V1.Y * V0.Y;
720
Result := Result + M;
723
Result := Result / Roo2(Pow2(Result._11) + Pow2(Result._12));
726
function ShapeMatch(const Vs0_, Vs1_: array of TDouble2D): TDoubleM2;
732
Result := TDoubleM2.Create(0, 0, 0, 0);
734
for I := 0 to High(Vs0_) do
741
_11 := V1.X * V0.X + V1.Y * V0.Y;
742
_12 := V1.X * V0.Y - V1.Y * V0.X;
743
_21 := V1.Y * V0.X - V1.X * V0.Y;
744
_22 := V1.X * V0.X + V1.Y * V0.Y;
747
Result := Result + M;
750
Result := Result / Roo2(Pow2(Result._11) + Pow2(Result._12));
753
// ------------------------------------------------------------------------------
755
function InsideLoop(const P_: TSingle2D; const Ps_: TArray<TSingle2D>): Single;
758
P0, P1, P2, V0, V1: TSingle2D;
765
for I := 1 to High(Ps_) - 1 do
773
A := V0.RotAngleTo(V1);
775
Result := Result + A;
781
A := V0.RotAngleTo(V1);
783
Result := Result + A;
785
Result := Result / Pi2;
788
function InsideLoop(const P_: TDouble2D; const Ps_: TArray<TDouble2D>): Double;
791
P0, P1, P2, V0, V1: TDouble2D;
798
for I := 1 to High(Ps_) - 1 do
806
A := V0.RotAngleTo(V1);
808
Result := Result + A;
814
A := V0.RotAngleTo(V1);
816
Result := Result + A;
818
Result := Result / Pi2;
821
initialization //------------------------------------------------------------