Changeset 170 for trunk/Packages
- Timestamp:
- Nov 23, 2017, 5:02:49 PM (7 years ago)
- Location:
- trunk/Packages/Common
- Files:
-
- 1 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Packages/Common/Common.lpk
r164 r170 17 17 <License Value="GNU/GPL"/> 18 18 <Version Minor="7"/> 19 <Files Count="2 1">19 <Files Count="22"> 20 20 <Item1> 21 21 <Filename Value="StopWatch.pas"/> … … 110 110 <UnitName Value="UGeometry"/> 111 111 </Item21> 112 <Item22> 113 <Filename Value="UGeometryClasses.pas"/> 114 <UnitName Value="UGeometryClasses"/> 115 </Item22> 112 116 </Files> 113 117 <i18n> -
trunk/Packages/Common/Common.pas
r164 r170 11 11 UMemory, UResetableThread, UPool, ULastOpenedList, URegistry, 12 12 UJobProgressView, UXMLUtils, UApplicationInfo, USyncCounter, UListViewSort, 13 UPersistentForm, UFindFile, UScaleDPI, UGeometry, LazarusPackageIntf; 13 UPersistentForm, UFindFile, UScaleDPI, UGeometry, UGeometryClasses, 14 LazarusPackageIntf; 14 15 15 16 implementation -
trunk/Packages/Common/UGeometry.pas
r169 r170 9 9 10 10 type 11 TPointArray = array of TPoint; 12 13 { TLine } 14 15 TLine = record 11 { TGPoint } 12 13 TGPoint<T> = record 14 public 15 X: T; 16 Y: T; 17 constructor Create(const X, Y: T); 18 procedure Rotate(Base: TGPoint<T>; Angle: Double); 19 class operator Add(const A, B: TGPoint<T>): TGPoint<T>; 20 class operator Subtract(const A, B: TGPoint<T>): TGPoint<T>; 21 class operator GreaterThan(const A, B: TGPoint<T>): Boolean; 22 class operator LessThan(const A, B: TGPoint<T>): Boolean; 23 class operator Equal(const A, B: TGPoint<T>): Boolean; 24 function Min(const A, B: TGPoint<T>): TGPoint<T>; 25 function Max(const A, B: TGPoint<T>): TGPoint<T>; 26 end; 27 28 { TGPoint3D } 29 30 TGPoint3D<T> = record 31 public 32 X: T; 33 Y: T; 34 Z: T; 35 constructor Create(const X, Y, Z: T); 36 end; 37 38 { TGRect } 39 40 TGRect<T> = record 41 private 42 function GetEmpty: Boolean; 43 function GetSize: T; 44 procedure SetSize(AValue: T); 45 public 46 P1: T; 47 P2: T; 48 function IsPointInside(const P: T): Boolean; 49 function Center: T; 50 procedure SetEmpty; 51 class operator Equal(const A, B: TGRect<T>): Boolean; 52 constructor Create(const P1, P2: T); 53 constructor CreateBounds(const Origin, Size: T); 54 property Size: T read GetSize write SetSize; 55 property Empty: Boolean read GetEmpty; 56 end; 57 58 { TGLine } 59 60 TGLine<T> = record 16 61 private 17 62 function GetDistance: Double; 18 63 procedure SetDistance(AValue: Double); 19 64 public 20 P1: T Point;21 P2: T Point;22 function Create(const P1, P2: TPoint): TLine;23 function GetMiddle: T Point;65 P1: T; 66 P2: T; 67 constructor Create(const P1, P2: T); 68 function GetMiddle: T; 24 69 function GetAngle: Double; 25 function GetSize: T Point;26 function ToRect: T Rect;70 function GetSize: T; 71 function ToRect: TGRect<T>; 27 72 function DotProduct: Double; 73 class function LineIntersect(const LineA, LineB: TGLine<T>; out Intersection: T): Boolean; static; 28 74 procedure Rotate(const Angle: Double); 29 class operator Equal(const A, B: T Line): Boolean;75 class operator Equal(const A, B: TGLine<T>): Boolean; 30 76 property Distance: Double read GetDistance write SetDistance; 31 77 end; 32 78 33 { T Polygon }34 35 T Polygon= record79 { TGPolygon } 80 81 TGPolygon<T> = record 36 82 private 37 function GetPoint(const Index: Integer): T Point; inline;38 procedure SetPoint(const Index: Integer; const AValue: T Point); inline;83 function GetPoint(const Index: Integer): T; inline; 84 procedure SetPoint(const Index: Integer; const AValue: T); inline; 39 85 public 86 type 87 TPointArray = array of T; 88 var 40 89 Points: TPointArray; 41 function IsPointInside(const P: T Point): Boolean;42 function Create(const Points: TPointArray): TPolygon; overload;43 function Create(const Rect: TRect): TPolygon; overload;44 function GetRect: T Rect;45 procedure AddPoint(const P: T Point);90 function IsPointInside(const P: T): Boolean; 91 constructor Create(const Points: TPointArray); overload; 92 constructor Create(const Rect: TGRect<T>); overload; 93 function GetRect: TGRect<T>; 94 procedure AddPoint(const P: T); 46 95 procedure Clear; 47 procedure CutLine(const Vector: TLine; const PointInside: TPoint); 48 property Items[Index: Integer]: TPoint read GetPoint write SetPoint; default; 49 end; 50 51 function Distance(const P1, P2: TPoint): Integer; 52 function Dot(const P1, P2: TPoint): Double; 53 function AddPoint(const P1, P2: TPoint): TPoint; 54 function SubPoint(const P1, P2: TPoint): TPoint; 55 function PointToLineDistance(const P, V, W: TPoint): Integer; 56 function ComparePoint(const P1, P2: TPoint): Boolean; 57 function RotatePoint(const Center, P: TPoint; Angle: Double): TPoint; 58 function RotatePoints(const Center: TPoint; P: TPointArray; Angle: Double): TPointArray; 59 function LineIntersect(const LineA, LineB: TLine; out Intersection: TPoint): Boolean; 60 function ArcTan2Point(const Point: TPoint): Float; 61 function ArcTanPoint(const Point: TPoint): Float; 62 function RectEquals(const A, B: TRect): Boolean; 63 function RectEnlarge(const Rect: TRect; Value: Integer): TRect; 64 function ShiftRect(const ARect: TRect; Delta: TPoint): TRect; 65 function PointsToRect(const P1, P2: TPoint): TRect; 66 function PointInRect(const P: TPoint; aRect: TRect): Boolean; 67 function HalfDistancePoint(const P1, P2: TPoint): TPoint; 68 function NormalizeAngle(const Angle: Double): Double; 69 function SubAngle(A1, A2: Double): Double; 96 procedure CutLine(const Vector: TGLine<T>; const PointInside: T); 97 property Items[Index: Integer]: T read GetPoint write SetPoint; default; 98 end; 99 100 // Integer 101 TPoint = TGPoint<Integer>; 102 TPoint3D = TGPoint3D<Integer>; 103 TLine = TGLine<TPoint>; 104 TRect = TGRect<TPoint>; 105 TPolygon = TGPolygon<TPoint>; 106 107 // FLoating 108 TPointF = TGPoint<Single>; 109 TPoint3DF = TGPoint3D<Single>; 110 TRectF = TGRect<TPointF>; 111 TLineF = TGLine<TPointF>; 112 TPolygonF = TGPolygon<TPointF>; 113 114 function Divide(Divident, Divisor: Integer): Integer; overload; 115 function Divide(Divident, Divisor: Double): Double; overload; 116 function TypedRound(Value: Double): Integer; overload; 117 function TypedRound(Value: Double): Double; overload; 118 function StdPointToPoint(Value: Classes.TPoint): TPoint; 119 function PointToStdPoint(Value: TPoint): Classes.TPoint; 70 120 71 121 72 122 implementation 73 123 74 function Distance(const P1, P2: TPoint): Integer; 75 begin 76 Result := Trunc(Sqrt(Sqr(P2.X - P1.X) + Sqr(P2.Y - P1.Y))); 77 end; 78 79 function Dot(const P1, P2: TPoint): Double; 80 begin 81 Result := P1.X * P2.X + P1.Y * P2.Y; 82 end; 83 84 function AddPoint(const P1, P2: TPoint): TPoint; 85 begin 86 Result.X := P1.X + P2.X; 87 Result.Y := P1.Y + P2.Y; 88 end; 89 90 function SubPoint(const P1, P2: TPoint): TPoint; 91 begin 92 Result.X := P1.X - P2.X; 93 Result.Y := P1.Y - P2.Y; 94 end; 95 96 function PointToLineDistance(const P, V, W: TPoint): Integer; 97 var 98 l2, t: Double; 99 tt: TPoint; 100 begin 101 // Return minimum distance between line segment vw and point p 102 L2 := Distance(V, W); // i.e. |w-v|^2 - avoid a sqrt 103 L2 := Power(l2, 2); 104 if L2 = 0 then begin 105 Result := Distance(P, V); // v == w case 106 Exit; 107 end; 108 // Consider the line extending the segment, parameterized as v + t (w - v). 109 // We find projection of point p onto the line. 110 // It falls where t = [(p-v) . (w-v)] / |w-v|^2 111 T := Dot(SubPoint(P, V), SubPoint(W, V)) / L2; 112 if T < 0 then begin 113 Result := Distance(P, V); // Beyond the 'v' end of the segment 114 exit; 115 end 116 else if T > 1 then begin 117 Result := Distance(P, W); // Beyond the 'w' end of the segment 118 Exit; 119 end; 120 TT.X := Trunc(V.X + T * (W.X - V.X)); 121 TT.Y := Trunc(V.Y + T * (W.Y - V.Y)); 122 Result := Distance(P, TT); 123 end; 124 125 function ComparePoint(const P1, P2: TPoint): Boolean; 126 begin 127 Result := (P1.X = P2.X) and (P1.Y = P2.Y); 128 end; 129 130 function RotatePoint(const Center, P: TPoint; Angle: Double): TPoint; 131 var 132 D: TPoint; 133 begin 134 D := Point(P.X - Center.X, P.Y - Center.Y); 135 Result := Point(Center.X + Round(D.X * Cos(Angle) - D.Y * Sin(Angle)), 136 Center.Y + Round(D.X * Sin(Angle) + D.Y * Cos(Angle))); 137 end; 138 139 function RotatePoints(const Center: TPoint; P: TPointArray; Angle: Double): TPointArray; 140 var 141 I: Integer; 142 begin 143 SetLength(Result, Length(P)); 144 for I := 0 to High(P) do 145 Result[I] := RotatePoint(Center, P[I], Angle); 146 end; 147 148 function LineIntersect(const LineA, LineB: TLine; out Intersection: TPoint): Boolean; 149 Var 150 LDetLineA, LDetLineB, LDetDivInv: Double; 151 LDiffLA, LDiffLB: TPoint; 152 D: Integer; 153 begin 154 if ComparePoint(LineA.P1, LineA.P2) or ComparePoint(LineB.P1, LineB.P2) then begin 155 Result := False; 156 Exit; 157 end; 158 LDetLineA := LineA.P1.X * LineA.P2.Y - LineA.P1.Y * LineA.P2.X; 159 LDetLineB := LineB.P1.X * LineB.P2.Y - LineB.P1.Y * LineB.P2.X; 160 161 LDiffLA := SubPoint(LineA.P1, LineA.P2); 162 LDiffLB := SubPoint(LineB.P1, LineB.P2); 163 164 D := (LDiffLA.X * LDiffLB.Y) - (LDiffLA.Y * LDiffLB.X); 165 if D = 0 then begin 166 // Parallel lines without intersection 167 Result := False; 168 Exit; 169 end; 170 LDetDivInv := 1 / D; 171 172 Intersection.X := Round(((LDetLineA * LDiffLB.X) - (LDiffLA.X * LDetLineB)) * LDetDivInv); 173 Intersection.Y := Round(((LDetLineA * LDiffLB.Y) - (LDiffLA.Y * LDetLineB)) * LDetDivInv); 174 Result := True; 175 end; 176 177 function ArcTan2Point(const Point: TPoint): Float; 178 begin 179 Result := ArcTan2(Point.Y, Point.X); 180 end; 181 182 function ArcTanPoint(const Point: TPoint): Float; 183 begin 184 if Point.Y = 0 then Result := Infinity 185 else Result := ArcTan(Point.X / Point.Y); 186 end; 187 188 function RectEquals(const A, B: TRect): Boolean; 189 begin 190 Result := (A.Left = B.Left) and (A.Top = B.Top) and 191 (A.Right = B.Right) and (A.Bottom = B.Bottom); 192 end; 193 194 function RectEnlarge(const Rect: TRect; Value: Integer): TRect; 195 begin 196 Result.Left := Rect.Left - Value; 197 Result.Right := Rect.Right + Value; 198 Result.Top := Rect.Top - Value; 199 Result.Bottom := Rect.Bottom + Value; 200 end; 201 202 function ShiftRect(const ARect: TRect; Delta: TPoint): TRect; 203 begin 204 Result := Rect(ARect.Left + Delta.X, ARect.Top + Delta.Y, 205 ARect.Right + Delta.X, ARect.Bottom + Delta.Y); 206 end; 207 208 function PointsToRect(const P1, P2: TPoint): TRect; 209 begin 210 if P1.X < P2.X then Result.Left := P1.X else Result.Left := P2.X; 211 if P1.Y < P2.Y then Result.Top := P1.Y else Result.Top := P2.Y; 212 if P1.X > P2.X then Result.Right := P1.X else Result.Right := P2.X; 213 if P1.Y > P2.Y then Result.Bottom := P1.Y else Result.Bottom := P2.Y; 214 end; 215 216 function PointInRect(const P: TPoint; aRect: TRect): Boolean; 217 begin 218 Result := (P.X >= aRect.Left) and (P.X <= aRect.Right) and 219 (P.Y >= aRect.Top) and (P.Y <= aRect.Bottom); 220 end; 221 222 function HalfDistancePoint(const P1, P2: TPoint): TPoint; 223 begin 224 Result := Point(P1.X + (P2.X - P1.X) div 2, P1.Y + (P2.Y - P1.Y) div 2) 225 end; 226 227 function NormalizeAngle(const Angle: Double): Double; 228 begin 229 if Angle < 0 then Result := Angle + (Trunc(Angle / (2 * Pi)) + 1) * (2 * Pi) 230 else if Angle > 2 * Pi then Result := Angle - Trunc(Angle / (2 * Pi)) * (2 * Pi) 231 else Result := Angle; 232 end; 233 234 function SubAngle(A1, A2: Double): Double; 235 begin 236 A1 := NormalizeAngle(A1); 237 A2 := NormalizeAngle(A2); 238 if A1 < A2 then Result := A1 + 2 * Pi - A2 239 else Result := A1 - A2; 124 function Divide(Divident, Divisor: Integer): Integer; 125 begin 126 Result := Divident div Divisor; 127 end; 128 129 function Divide(Divident, Divisor: Double): Double; 130 begin 131 Result := Divident / Divisor; 132 end; 133 134 function TypedRound(Value: Double): Integer; 135 begin 136 Result := Round(Value); 137 end; 138 139 function TypedRound(Value: Double): Double; 140 begin 141 Result := Value; 142 end; 143 144 function StdPointToPoint(Value: Classes.TPoint): TPoint; 145 begin 146 Result.X := Value.X; 147 Result.Y := Value.Y; 148 end; 149 150 function PointToStdPoint(Value: TPoint): Classes.TPoint; 151 begin 152 Result.X := Value.X; 153 Result.Y := Value.Y; 240 154 end; 241 155 242 156 { TPolygon } 243 157 244 function T Polygon.GetPoint(const Index: Integer): TPoint;158 function TGPolygon<T>.GetPoint(const Index: Integer): T; 245 159 begin 246 160 Result := Points[Index]; 247 161 end; 248 162 249 procedure T Polygon.SetPoint(const Index: Integer; const AValue: TPoint);163 procedure TGPolygon<T>.SetPoint(const Index: Integer; const AValue: T); 250 164 begin 251 165 Points[Index] := AValue; 252 166 end; 253 167 254 function T Polygon.IsPointInside(const P: TPoint): Boolean;168 function TGPolygon<T>.IsPointInside(const P: T): Boolean; 255 169 var 256 170 I, J: Integer; … … 292 206 293 207 294 function TPolygon.Create(const Points: TPointArray): TPolygon;208 constructor TGPolygon<T>.Create(const Points: TPointArray); 295 209 var 296 210 I: Integer; 297 211 begin 298 SetLength( Result.Points, Length(Points));212 SetLength(Self.Points, Length(Points)); 299 213 for I := 0 to Length(Points) - 1 do 300 Result.Points[I] := Points[I];301 end; 302 303 function TPolygon.Create(const Rect: TRect): TPolygon;304 begin 305 SetLength( Result.Points, 4);306 Result.Points[0] := Point(Rect.Left, Rect.Top);307 Result.Points[1] := Point(Rect.Right, Rect.Top);308 Result.Points[2] := Point(Rect.Right, Rect.Bottom);309 Result.Points[3] := Point(Rect.Left, Rect.Bottom);310 end; 311 312 function T Polygon.GetRect: TRect;214 Self.Points[I] := Points[I]; 215 end; 216 217 constructor TGPolygon<T>.Create(const Rect: TGRect<T>); 218 begin 219 SetLength(Self.Points, 4); 220 Self.Points[0] := Rect.P1; 221 Self.Points[1] := T.Create(Rect.P2.X, Rect.P1.Y); 222 Self.Points[2] := Rect.P1; 223 Self.Points[3] := T.Create(Rect.P1.X, Rect.P2.Y); 224 end; 225 226 function TGPolygon<T>.GetRect: TGRect<T>; 313 227 var 314 228 I: Integer; 315 begin 316 Result := Rect(High(Integer), High(Integer), 317 Low(Integer), Low(Integer)); 318 for I := 0 to Length(Points) - 1 do 319 with Points[I] do begin 320 if X > Result.Right then 321 Result.Right := X; 322 if X < Result.Left then 323 Result.Left := X; 324 if Y > Result.Bottom then 325 Result.Bottom := Y; 326 if Y < Result.Top then 327 Result.Top := Y; 328 end; 329 end; 330 331 procedure TPolygon.AddPoint(const P: TPoint); 229 P1: TGPoint<T>; 230 begin 231 if Length(Points) = 0 then 232 Result.Empty 233 else begin 234 Result := TGRect<T>.Create(Points[0], Points[0]); 235 for I := 1 to Length(Points) - 1 do 236 with Points[I] do begin 237 Result.P1 := Points[I].Min(Result.P1, Points[I]); 238 Result.P2 := Points[I].Max(Result.P2, Points[I]); 239 end; 240 end; 241 end; 242 243 procedure TGPolygon<T>.AddPoint(const P: T); 332 244 begin 333 245 SetLength(Points, Length(Points) + 1); … … 335 247 end; 336 248 337 procedure T Polygon.Clear;249 procedure TGPolygon<T>.Clear; 338 250 begin 339 251 SetLength(Points, 0); 340 252 end; 341 253 342 procedure T Polygon.CutLine(const Vector: TLine; const PointInside: TPoint);254 procedure TGPolygon<T>.CutLine(const Vector: TGLine<T>; const PointInside: T); 343 255 var 344 256 I: Integer; 345 257 PointsChecked: Integer; 346 L1, L2: T Line;347 Intersection: T Point;348 NewPoly: T Polygon;258 L1, L2: TGLine<T>; 259 Intersection: T; 260 NewPoly: TGPolygon<T>; 349 261 NewPolygonStarted: Boolean; 350 262 Success: Boolean; … … 359 271 if Length(Points) > 0 then 360 272 while True do begin 361 L2 := T Line.Create(Points[I], Points[(I + 1) mod Length(Points)]);362 if LineIntersect(L1, L2, Intersection) then363 if PointInRect(Intersection, L2.ToRect) then begin273 L2 := TGLine<T>.Create(Points[I], Points[(I + 1) mod Length(Points)]); 274 if TGLine<T>.LineIntersect(L1, L2, Intersection) then 275 if L2.ToRect.IsPointInside(Intersection) then begin 364 276 if not NewPolygonStarted then begin 365 277 // Crossing line, start new polygon … … 391 303 { TLine } 392 304 393 function T Line.GetDistance: Double;305 function TGLine<T>.GetDistance: Double; 394 306 begin 395 307 Result := Sqrt(Sqr(P2.X - P1.X) + Sqr(P2.Y - P1.Y)); 396 308 end; 397 309 398 procedure T Line.SetDistance(AValue: Double);310 procedure TGLine<T>.SetDistance(AValue: Double); 399 311 var 400 312 Angle: Double; 401 313 begin 402 314 Angle := GetAngle; 403 P2 := Point(Round(P1.X + Cos(Angle) * AValue),315 P2 := T.Create(Round(P1.X + Cos(Angle) * AValue), 404 316 Round(P1.Y + Sin(Angle) * AValue)); 405 317 end; 406 318 407 function TLine.Create(const P1, P2: TPoint): TLine; 319 constructor TGLine<T>.Create(const P1, P2: T); 320 begin 321 Self.P1 := P1; 322 Self.P2 := P2; 323 end; 324 325 function TGLine<T>.GetMiddle: T; 326 begin 327 Result := T.Create(P1.X + Divide((P2.X - P1.X), 2), P1.Y + Divide((P2.Y - P1.Y), 2)); 328 end; 329 330 function TGLine<T>.GetAngle: Double; 331 begin 332 Result := ArcTan2(P2.Y - P1.Y, P2.X - P1.X); 333 end; 334 335 function TGLine<T>.GetSize: T; 336 begin 337 Result := P2 - P1; 338 end; 339 340 function TGLine<T>.ToRect: TGRect<T>; 408 341 begin 409 342 Result.P1 := P1; … … 411 344 end; 412 345 413 function TLine.GetMiddle: TPoint; 414 begin 415 Result := Point(P1.X + (P2.X - P1.X) div 2, P1.Y + (P2.Y - P1.Y) div 2); 416 end; 417 418 function TLine.GetAngle: Double; 419 begin 420 Result := ArcTan2(P2.Y - P1.Y, P2.X - P1.X); 421 end; 422 423 function TLine.GetSize: TPoint; 424 begin 425 Result := Point(P2.X - P1.X, P2.Y - P1.Y); 426 end; 427 428 function TLine.ToRect: TRect; 429 begin 430 if P1.X < P2.X then Result.Left := P1.X else Result.Left := P2.X; 431 if P1.Y < P2.Y then Result.Top := P1.Y else Result.Top := P2.Y; 432 if P1.X > P2.X then Result.Right := P1.X else Result.Right := P2.X; 433 if P1.Y > P2.Y then Result.Bottom := P1.Y else Result.Bottom := P2.Y; 434 end; 435 436 function TLine.DotProduct: Double; 346 function TGLine<T>.DotProduct: Double; 437 347 begin 438 348 Result := P1.X * P2.X + P1.Y * P2.Y; 439 349 end; 440 350 441 procedure TLine.Rotate(const Angle: Double); 442 begin 443 P2 := RotatePoint(P1, P2, Angle); 444 end; 445 446 class operator TLine.Equal(const A, B: TLine): Boolean; 447 begin 448 Result := ComparePoint(A.P1, B.P1) and ComparePoint(A.P2, B.P2); 351 procedure TGLine<T>.Rotate(const Angle: Double); 352 begin 353 P2.Rotate(P1, Angle); 354 end; 355 356 class operator TGLine<T>.Equal(const A, B: TGLine<T>): Boolean; 357 begin 358 Result := (A.P1 = B.P1) and (A.P2 = B.P2); 359 end; 360 361 { TGPoint3D } 362 363 constructor TGPoint3D<T>.Create(const X, Y, Z: T); 364 begin 365 Self.X := X; 366 Self.Y := Y; 367 Self.Z := Z; 368 end; 369 370 { TGPoint } 371 372 constructor TGPoint<T>.Create(const X, Y: T); 373 begin 374 Self.X := X; 375 Self.Y := Y; 376 end; 377 378 class operator TGPoint<T>.Equal(const A, B: TGPoint<T>): Boolean; 379 begin 380 Result := (A.X = B.X) and (A.Y = B.Y); 381 end; 382 383 class operator TGPoint<T>.Add(const A, B: TGPoint<T>): TGPoint<T>; 384 begin 385 Result.X := A.X + B.X; 386 Result.Y := A.Y + B.Y; 387 end; 388 389 class operator TGPoint<T>.Subtract(const A, B: TGPoint<T>): TGPoint<T>; 390 begin 391 Result.X := A.X - B.X; 392 Result.Y := A.Y - B.Y; 393 end; 394 395 class operator TGPoint<T>.GreaterThan(const A, B: TGPoint<T>): Boolean; 396 begin 397 Result := (B.X > A.X) and (B.Y > A.Y); 398 end; 399 400 class operator TGPoint<T>.LessThan(const A, B: TGPoint<T>): Boolean; 401 begin 402 Result := (B.X < A.X) and (B.Y < A.Y); 403 end; 404 405 { TGLine } 406 407 class function TGLine<T>.LineIntersect(const LineA, LineB: TGLine<T>; out 408 Intersection: T): Boolean; 409 Var 410 LDetLineA, LDetLineB, LDetDivInv: Double; 411 LDiffLA, LDiffLB: T; 412 D: Double; 413 begin 414 if (LineA.P1 = LineA.P2) or (LineB.P1 = LineB.P2) then begin 415 Result := False; 416 Exit; 417 end; 418 LDetLineA := LineA.P1.X * LineA.P2.Y - LineA.P1.Y * LineA.P2.X; 419 LDetLineB := LineB.P1.X * LineB.P2.Y - LineB.P1.Y * LineB.P2.X; 420 421 LDiffLA := LineA.P1 - LineA.P2; 422 LDiffLB := LineB.P1 - LineB.P2; 423 424 D := (LDiffLA.X * LDiffLB.Y) - (LDiffLA.Y * LDiffLB.X); 425 if D = 0 then begin 426 // Parallel lines without intersection 427 Result := False; 428 Exit; 429 end; 430 LDetDivInv := 1 / D; 431 432 Intersection.X := TypedRound(((LDetLineA * LDiffLB.X) - (LDiffLA.X * LDetLineB)) * LDetDivInv); 433 Intersection.Y := TypedRound(((LDetLineA * LDiffLB.Y) - (LDiffLA.Y * LDetLineB)) * LDetDivInv); 434 Result := True; 435 end; 436 437 procedure TGPoint<T>.Rotate(Base: TGPoint<T>; Angle: Double); 438 var 439 D: TGPoint<T>; 440 begin 441 D := TGPoint<T>.Create(X - Base.X, Y - Base.Y); 442 //X := Base.X + TypedRound(D.X * Cos(Angle) - D.Y * Sin(Angle)); 443 //Y := Base.Y + TypedRound(D.X * Sin(Angle) + D.Y * Cos(Angle)); 444 end; 445 446 function TGPoint<T>.Min(const A, B: TGPoint<T>): TGPoint<T>; 447 begin 448 if A.X < B.X then Result.X := A.X else Result.X := B.X; 449 if A.Y < B.Y then Result.Y := A.Y else Result.Y := B.Y; 450 end; 451 452 function TGPoint<T>.Max(const A, B: TGPoint<T>): TGPoint<T>; 453 begin 454 if A.X > B.X then Result.X := A.X else Result.X := B.X; 455 if A.Y > B.Y then Result.Y := A.Y else Result.Y := B.Y; 456 end; 457 458 { TGRect } 459 460 function TGRect<T>.IsPointInside(const P: T): Boolean; 461 begin 462 Result := (P > P1) and (P < P2); 463 end; 464 465 function TGRect<T>.GetEmpty: Boolean; 466 begin 467 Result := P1 = P2; 468 end; 469 470 procedure TGRect<T>.SetEmpty; 471 begin 472 P2 := P1; 473 end; 474 475 function TGRect<T>.Center: T; 476 begin 477 Result.X := Divide(P2.X - P1.X, 2); 478 Result.Y := Divide(P2.Y - P1.Y, 2); 479 end; 480 481 function TGRect<T>.GetSize: T; 482 begin 483 Result := P2 - P1; 484 end; 485 486 procedure TGRect<T>.SetSize(AValue: T); 487 begin 488 P2 := P1 + AValue; 489 end; 490 491 constructor TGRect<T>.Create(const P1, P2: T); 492 begin 493 Self.P1 := P1; 494 Self.P2 := P2; 495 end; 496 497 constructor TGRect<T>.CreateBounds(const Origin, Size: T); 498 begin 499 Self.P1 := Origin; 500 Self.P2 := Origin + Size; 501 end; 502 503 class operator TGRect<T>.Equal(const A, B: TGRect<T>): Boolean; 504 begin 505 Result := (A.P1 = B.P1) and (A.P2 = B.P2); 449 506 end; 450 507
Note:
See TracChangeset
for help on using the changeset viewer.