Changeset 521 for GraphicTest/Packages/bgrabitmap/bgratransform.pas
- Timestamp:
- Apr 17, 2019, 12:58:41 AM (5 years ago)
- Location:
- GraphicTest
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
GraphicTest
- Property svn:ignore
-
old new 8 8 GraphicTest.lps 9 9 GraphicTest.dbg 10 heaptrclog.trc
-
- Property svn:ignore
-
GraphicTest/Packages/bgrabitmap/bgratransform.pas
r494 r521 13 13 { Contains an affine matrix, i.e. a matrix to transform linearly and translate TPointF coordinates } 14 14 TAffineMatrix = BGRABitmapTypes.TAffineMatrix; 15 16 { TAffineBox } 17 18 TAffineBox = object 19 private 20 function GetAsPolygon: ArrayOfTPointF; 21 function GetBottomRight: TPointF; 22 function GetIsEmpty: boolean; 23 public 24 TopLeft, TopRight, 25 BottomLeft: TPointF; 26 class function EmptyBox: TAffineBox; 27 class function AffineBox(ATopLeft, ATopRight, ABottomLeft: TPointF): TAffineBox; 28 property BottomRight: TPointF read GetBottomRight; 29 property IsEmpty: boolean read GetIsEmpty; 30 property AsPolygon: ArrayOfTPointF read GetAsPolygon; 31 end; 15 { Contains an affine base and information on the resulting box } 16 TAffineBox = BGRABitmapTypes.TAffineBox; 32 17 33 18 { TBGRAAffineScannerTransform allow to transform any scanner. To use it, … … 87 72 procedure Init(ABitmap: TBGRACustomBitmap; ARepeatImageX: Boolean= false; ARepeatImageY: Boolean= false; AResampleFilter: TResampleFilter = rfLinear; AIncludeEdges: boolean = false); 88 73 public 89 constructor Create(ABitmap: TBGRACustomBitmap; ARepeatImage: Boolean= false; AResampleFilter: TResampleFilter = rfLinear; AIncludeEdges: boolean = false); 90 constructor Create(ABitmap: TBGRACustomBitmap; ARepeatImageX: Boolean; ARepeatImageY: Boolean; AResampleFilter: TResampleFilter = rfLinear; AIncludeEdges: boolean = false); 74 constructor Create(ABitmap: TBGRACustomBitmap; ARepeatImage: Boolean= false; AResampleFilter: TResampleFilter = rfLinear; AIncludeEdges: boolean = false); overload; 75 constructor Create(ABitmap: TBGRACustomBitmap; ARepeatImageX: Boolean; ARepeatImageY: Boolean; AResampleFilter: TResampleFilter = rfLinear; AIncludeEdges: boolean = false); overload; 91 76 destructor Destroy; override; 92 77 function InternalScanCurrentPixel: TBGRAPixel; override; … … 137 122 constructor Create(ASource: IBGRAScanner; 138 123 ASourceMatrix: TAffineMatrix; const APoints: array of TPointF; 139 ATextureInterpolation: boolean = true); 124 ATextureInterpolation: boolean = true); overload; 140 125 constructor Create(ASource: IBGRAScanner; 141 126 const ATexCoords: array of TPointF; const APoints: array of TPointF; 142 ATextureInterpolation: boolean = true); 127 ATextureInterpolation: boolean = true); overload; 143 128 destructor Destroy; override; 144 129 property Culling: TFaceCulling read GetCulling write SetCulling; … … 191 176 {---------------------- Affine matrix functions -------------------} 192 177 //fill a matrix 193 function AffineMatrix(m11,m12,m13,m21,m22,m23: single): TAffineMatrix; 178 function AffineMatrix(m11,m12,m13,m21,m22,m23: single): TAffineMatrix; overload; 179 function AffineMatrix(AU,AV: TPointF; ATranslation: TPointF): TAffineMatrix; overload; 194 180 195 181 //matrix multiplication … … 200 186 operator *(M: TAffineMatrix; V: TPointF): TPointF; 201 187 operator *(M: TAffineMatrix; A: array of TPointF): ArrayOfTPointF; 188 operator *(M: TAffineMatrix; ab: TAffineBox): TAffineBox; 202 189 203 190 //check if matrix is inversible … … 221 208 //define a scaling matrix 222 209 function AffineMatrixScale(sx,sy: single): TAffineMatrix; 210 function AffineMatrixScaledRotation(ASourceVector, ATargetVector: TPointF): TAffineMatrix; 211 function AffineMatrixScaledRotation(ASourcePoint, ATargetPoint, AOrigin: TPointF): TAffineMatrix; 223 212 224 213 function AffineMatrixSkewXDeg(AngleCW: single): TAffineMatrix; … … 228 217 229 218 //define a linear matrix 230 function AffineMatrixLinear(v1,v2: TPointF): TAffineMatrix; 219 function AffineMatrixLinear(v1,v2: TPointF): TAffineMatrix; overload; 220 function AffineMatrixLinear(const AMatrix: TAffineMatrix): TAffineMatrix; overload; 231 221 232 222 //define a rotation matrix (positive radians are counter-clockwise) … … 242 232 243 233 function IsAffineMatrixOrthogonal(M: TAffineMatrix): boolean; 234 function IsAffineMatrixScaledRotation(M: TAffineMatrix): boolean; 244 235 245 236 type … … 278 269 procedure SetIncludeOppositePlane(AValue: boolean); 279 270 public 280 constructor Create(texture: IBGRAScanner; texCoord1,texCoord2: TPointF; const quad: array of TPointF); 281 constructor Create(texture: IBGRAScanner; const texCoordsQuad: array of TPointF; const quad: array of TPointF); 271 constructor Create(texture: IBGRAScanner; texCoord1,texCoord2: TPointF; const quad: array of TPointF); overload; 272 constructor Create(texture: IBGRAScanner; const texCoordsQuad: array of TPointF; const quad: array of TPointF); overload; 282 273 destructor Destroy; override; 283 274 procedure ScanMoveTo(X, Y: Integer); override; … … 298 289 public 299 290 constructor Create; overload; 300 constructor Create(x1,y1,x2,y2: single; const quad: array of TPointF); 301 constructor Create(const quad: array of TPointF; x1,y1,x2,y2: single); 302 constructor Create(const srcQuad,destQuad: array of TPointF); 291 constructor Create(x1,y1,x2,y2: single; const quad: array of TPointF); overload; 292 constructor Create(const quad: array of TPointF; x1,y1,x2,y2: single); overload; 293 constructor Create(const srcQuad,destQuad: array of TPointF); overload; 303 294 function MapQuadToQuad(const srcQuad,destQuad: array of TPointF): boolean; 304 295 function MapRectToQuad(x1,y1,x2,y2: single; const quad: array of TPointF): boolean; … … 386 377 end; 387 378 379 function AffineMatrix(AU, AV: TPointF; ATranslation: TPointF): TAffineMatrix; 380 begin 381 result:= AffineMatrix(AU.x, AV.x, ATranslation.x, 382 AU.y, AV.y, ATranslation.y); 383 end; 384 388 385 operator *(M, N: TAffineMatrix): TAffineMatrix; 389 386 begin … … 427 424 for i := 0 to high(A) do 428 425 result[i] := M*A[i]; 426 end; 427 428 operator*(M: TAffineMatrix; ab: TAffineBox): TAffineBox; 429 begin 430 result.TopLeft := M*ab.TopLeft; 431 result.TopRight := M*ab.TopRight; 432 result.BottomLeft := M*ab.BottomLeft; 429 433 end; 430 434 … … 475 479 end; 476 480 481 function AffineMatrixScaledRotation(ASourceVector, ATargetVector: TPointF): TAffineMatrix; 482 var 483 prevScale, newScale, scale: Single; 484 u1,v1,u2,v2,w: TPointF; 485 begin 486 prevScale := VectLen(ASourceVector); 487 newScale := VectLen(ATargetVector); 488 if (prevScale = 0) or (newScale = 0) then 489 result := AffineMatrixIdentity 490 else 491 begin 492 scale := newScale/prevScale; 493 u1 := ASourceVector*(1/prevScale); 494 v1 := PointF(-u1.y,u1.x); 495 w := ATargetVector*(1/newScale); 496 u2 := PointF(w*u1, w*v1); 497 v2 := PointF(-u2.y,u2.x); 498 result := AffineMatrix(scale*u2,scale*v2,PointF(0,0)); 499 end; 500 end; 501 502 function AffineMatrixScaledRotation(ASourcePoint, ATargetPoint, AOrigin: TPointF): TAffineMatrix; 503 begin 504 result := AffineMatrixTranslation(AOrigin.x,AOrigin.y)* 505 AffineMatrixScaledRotation(ASourcePoint-AOrigin, ATargetPoint-AOrigin)* 506 AffineMatrixTranslation(-AOrigin.x,-AOrigin.y); 507 end; 508 477 509 function AffineMatrixSkewXDeg(AngleCW: single): TAffineMatrix; 478 510 begin … … 506 538 end; 507 539 540 function AffineMatrixLinear(const AMatrix: TAffineMatrix): TAffineMatrix; 541 begin 542 result := AffineMatrix(AMatrix[1,1],AMatrix[1,2],0, 543 AMatrix[2,1],AMatrix[2,2],0); 544 end; 545 508 546 function AffineMatrixRotationRad(AngleCCW: Single): TAffineMatrix; 509 547 begin … … 527 565 begin 528 566 result := PointF(M[1,1],M[2,1])*PointF(M[1,2],M[2,2]) = 0; 567 end; 568 569 function IsAffineMatrixScaledRotation(M: TAffineMatrix): boolean; 570 begin 571 result := IsAffineMatrixOrthogonal(M) and 572 (VectLen(PointF(M[1,1],M[2,1]))=VectLen(PointF(M[1,2],M[2,2]))); 529 573 end; 530 574 … … 608 652 if y > FBounds.Bottom-1 then y := FBounds.Bottom-1; 609 653 result := FSource.ScanAt(X,Y); 610 end;611 612 { TAffineBox }613 614 function TAffineBox.GetAsPolygon: ArrayOfTPointF;615 begin616 result := PointsF([TopLeft,TopRight,BottomRight,BottomLeft]);617 end;618 619 function TAffineBox.GetBottomRight: TPointF;620 begin621 if IsEmpty then622 result := EmptyPointF623 else624 result := TopRight + (BottomLeft-TopLeft);625 end;626 627 function TAffineBox.GetIsEmpty: boolean;628 begin629 result := isEmptyPointF(TopRight) or isEmptyPointF(BottomLeft) or isEmptyPointF(TopLeft);630 end;631 632 class function TAffineBox.EmptyBox: TAffineBox;633 begin634 result.TopLeft := EmptyPointF;635 result.TopRight := EmptyPointF;636 result.BottomLeft := EmptyPointF;637 end;638 639 class function TAffineBox.AffineBox(ATopLeft, ATopRight, ABottomLeft: TPointF): TAffineBox;640 begin641 result.TopLeft := ATopLeft;642 result.TopRight := ATopRight;643 result.BottomLeft := ABottomLeft;644 654 end; 645 655
Note:
See TracChangeset
for help on using the changeset viewer.