1
//----------------------------------------------------------------------------
2
// Anti-Grain Geometry - Version 2.4 (Public License)
3
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
5
// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
6
// Pascal Port By: Milan Marusinec alias Milano
8
// http://www.aggpas.org
9
// Copyright (c) 2005-2006
11
// Permission to copy, use, modify, sell and distribute this software
12
// is granted provided this copyright notice appears in all copies.
13
// This software is provided "as is" without express or implied
14
// warranty, and with no claim as to its suitability for any purpose.
16
//----------------------------------------------------------------------------
17
// Contact: mcseem@antigrain.com
18
// mcseemagg@yahoo.com
19
// http://www.antigrain.com
21
//----------------------------------------------------------------------------
23
// Perspective 2D transformations
25
// [Pascal Port History] -----------------------------------------------------
27
// 13.11.2007-Milano: trans_perspective v 2.4
28
// 23.06.2006-Milano: ptrcomp adjustments
29
// 06.02.2006-Milano: Unit port establishment
31
{ agg_trans_perspective.pas }
33
agg_trans_perspective ;
50
nom_y ,nom_y_step : double;
54
constructor Construct; overload;
55
constructor Construct(tx ,ty ,step : double; m : double_ptr ); overload;
57
procedure inc_operator;
61
trans_perspective23_ptr = ^trans_perspective23;
62
trans_perspective23 = object(trans_affine )
64
m_mtx : array[0..7 ] of double;
66
constructor Construct; overload;
68
// Arbitrary quadrangle transformations
69
constructor Construct(src ,dst : double_ptr ); overload;
71
// Direct transformations
72
constructor Construct(x1 ,y1 ,x2 ,y2 : double; quad : double_ptr ); overload;
74
// Reverse transformations
75
constructor Construct(quad : double_ptr; x1 ,y1 ,x2 ,y2 : double ); overload;
77
// Set the transformations using two arbitrary quadrangles.
78
procedure quad_to_quad(src ,dst : double_ptr );
80
// Set the direct transformations, i.e., rectangle -> quadrangle
81
procedure rect_to_quad(x1 ,y1 ,x2 ,y2 : double; quad : double_ptr );
83
// Set the reverse transformations, i.e., quadrangle -> rectangle
84
procedure quad_to_rect(quad : double_ptr; x1 ,y1 ,x2 ,y2 : double );
86
// Check if the equations were solved successfully
87
function is_valid : boolean;
89
function begin_(x ,y ,step : double ) : iterator_x23;
93
quadrilateral_ptr = ^quadrilateral;
94
quadrilateral = array[0..8 ] of double;
96
trans_perspective_ptr = ^trans_perspective;
101
nom_y ,nom_y_step : double;
105
constructor Construct; overload;
106
constructor Construct(px ,py ,step : double; m : trans_perspective_ptr ); overload;
108
procedure operator_inc;
112
trans_perspective = object(trans_affine )
113
sx ,shy ,w0 ,shx ,sy ,w1 ,tx ,ty ,w2 : double;
115
transform_affine : proc_transform;
117
//------------------------------------------------------- Construction
119
constructor Construct; overload;
122
constructor Construct(v0 ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 : double ); overload;
124
// Custom matrix from m[9]
125
constructor Construct(m : quadrilateral_ptr ); overload;
128
constructor Construct_af(a : trans_affine_ptr );
131
constructor Construct(p : trans_perspective_ptr ); overload;
133
// Rectangle to quadrilateral
134
constructor Construct(x1 ,y1 ,x2 ,y2 : double; quad : quadrilateral_ptr ); overload;
136
// Quadrilateral to rectangle
137
constructor Construct(quad : quadrilateral_ptr; x1 ,y1 ,x2 ,y2 : double ); overload;
139
// Arbitrary quadrilateral transformations
140
constructor Construct(src ,dst : quadrilateral_ptr ); overload;
142
//-------------------------------------- Quadrilateral transformations
143
// The arguments are double[8] that are mapped to quadrilaterals:
144
// x1,y1, x2,y2, x3,y3, x4,y4
145
function quad_to_quad(qs ,qd : quadrilateral_ptr ) : boolean;
146
function rect_to_quad(x1 ,y1 ,x2 ,y2 : double; q : quadrilateral_ptr ) : boolean;
147
function quad_to_rect(q : quadrilateral_ptr; x1 ,y1 ,x2 ,y2 : double ) : boolean;
149
// Map square (0,0,1,1) to the quadrilateral and vice versa
150
function square_to_quad(q : quadrilateral_ptr ) : boolean;
151
function quad_to_square(q : quadrilateral_ptr ) : boolean;
153
//--------------------------------------------------------- Operations
154
// Reset - load an identity matrix
155
function reset_ : trans_perspective_ptr;
157
// Invert matrix. Returns false in degenerate case
158
function invert : boolean;
160
// Direct transformations operations
161
function translate(x ,y : double ) : trans_perspective_ptr;
162
function rotate (a : double ) : trans_perspective_ptr;
163
function scale (s : double ) : trans_perspective_ptr; overload;
164
function scale (x ,y : double ) : trans_perspective_ptr; overload;
166
// Multiply the matrix by another one
167
function multiply(a : trans_perspective_ptr ) : trans_perspective_ptr;
169
// Multiply "m" by "this" and assign the result to "this"
170
function premultiply(b : trans_perspective_ptr ) : trans_perspective_ptr;
172
// Multiply matrix to inverse of another one
173
function multiply_inv(m : trans_perspective_ptr ) : trans_perspective_ptr;
175
// Multiply inverse of "m" by "this" and assign the result to "this"
176
function premultiply_inv(m : trans_perspective_ptr ) : trans_perspective_ptr;
178
// Multiply the matrix by another one
179
function multiply_af(a : trans_affine_ptr ) : trans_perspective_ptr;
181
// Multiply "m" by "this" and assign the result to "this"
182
function premultiply_af(b : trans_affine_ptr ) : trans_perspective_ptr;
184
// Multiply the matrix by inverse of another one
185
function multiply_inv_af(m : trans_affine_ptr ) : trans_perspective_ptr;
187
// Multiply inverse of "m" by "this" and assign the result to "this"
188
function premultiply_inv_af(m : trans_affine_ptr ) : trans_perspective_ptr;
190
//--------------------------------------------------------- Load/Store
191
procedure store_to (m : quadrilateral_ptr );
192
function load_from(m : quadrilateral_ptr ) : trans_perspective_ptr;
194
//---------------------------------------------------------- Auxiliary
195
function from_affine(a : trans_affine_ptr ) : trans_perspective_ptr;
197
function determinant : double;
198
function determinant_reciprocal : double;
200
function is_valid (epsilon : double = affine_epsilon ) : boolean;
201
function is_identity(epsilon : double = affine_epsilon ) : boolean;
202
function is_equal (m : trans_perspective_ptr; epsilon : double = affine_epsilon ) : boolean;
204
// Determine the major affine parameters. Use with caution
205
// considering possible degenerate cases.
206
function scale : double; overload;
207
function rotation : double;
209
procedure translation(dx ,dy : double_ptr );
210
procedure scaling (x ,y : double_ptr );
211
procedure scaling_abs(x ,y : double_ptr );
214
function begin_(x ,y ,step : double ) : iterator_x;
218
{ GLOBAL PROCEDURES }
222
{ LOCAL VARIABLES & CONSTANTS }
223
{ UNIT IMPLEMENTATION }
225
constructor iterator_x23.Construct;
230
constructor iterator_x23.Construct(tx ,ty ,step : double; m : double_ptr );
232
den :=double_ptr(ptrcomp(m ) + 6 * sizeof(double ) )^ * tx + double_ptr(ptrcomp(m ) + 7 * sizeof(double ) )^ * ty + 1.0;
233
den_step:=double_ptr(ptrcomp(m ) + 6 * sizeof(double ) )^ * step;
235
nom_x :=double_ptr(ptrcomp(m ) + 0 * sizeof(double ) )^ + double_ptr(ptrcomp(m ) + 1 * sizeof(double ) )^ * tx + double_ptr(ptrcomp(m ) + 2 * sizeof(double ) )^ * ty;
236
nom_x_step:=double_ptr(ptrcomp(m ) + 1 * sizeof(double ) )^ * step;
238
nom_y :=double_ptr(ptrcomp(m ) + 3 * sizeof(double ) )^ + double_ptr(ptrcomp(m ) + 4 * sizeof(double ) )^ * tx + double_ptr(ptrcomp(m ) + 5 * sizeof(double ) )^ * ty;
239
nom_y_step:=double_ptr(ptrcomp(m ) + 4 * sizeof(double ) )^ * step;
247
procedure iterator_x23.inc_operator;
252
den :=den + den_step;
253
nom_x:=nom_x + nom_x_step;
254
nom_y:=nom_y + nom_y_step;
263
procedure _transform23(this : trans_perspective23_ptr; x ,y : double_ptr );
270
d :=1.0 / (this.m_mtx[6 ] * tx + this.m_mtx[7 ] * ty + 1.0 );
272
x^:=(this.m_mtx[0 ] + this.m_mtx[1 ] * tx + this.m_mtx[2 ] * ty ) * d;
273
y^:=(this.m_mtx[3 ] + this.m_mtx[4 ] * tx + this.m_mtx[5 ] * ty ) * d;
278
constructor trans_perspective23.Construct;
284
transform:=@_transform23;
289
constructor trans_perspective23.Construct(src ,dst : double_ptr );
293
quad_to_quad(src ,dst );
295
transform:=@_transform23;
300
constructor trans_perspective23.Construct(x1 ,y1 ,x2 ,y2 : double; quad : double_ptr );
304
rect_to_quad(x1 ,y1 ,x2 ,y2 ,quad );
306
transform:=@_transform23;
311
constructor trans_perspective23.Construct(quad : double_ptr; x1 ,y1 ,x2 ,y2 : double );
315
quad_to_rect(quad ,x1 ,y1 ,x2 ,y2 );
317
transform:=@_transform23;
322
procedure trans_perspective23.quad_to_quad;
327
i ,ix ,iy : unsigned;
336
left [ix ][1 ]:=double_ptr(ptrcomp(src ) + ix * sizeof(double ) )^;
337
left [ix ][2 ]:=double_ptr(ptrcomp(src ) + iy * sizeof(double ) )^;
341
left [ix ][6 ]:=-double_ptr(ptrcomp(src ) + ix * sizeof(double ) )^ * double_ptr(ptrcomp(dst ) + ix * sizeof(double ) )^;
342
left [ix ][7 ]:=-double_ptr(ptrcomp(src ) + iy * sizeof(double ) )^ * double_ptr(ptrcomp(dst ) + ix * sizeof(double ) )^;
343
right[ix ][0 ]:=double_ptr(ptrcomp(dst ) + ix * sizeof(double ) )^;
349
left [iy ][4 ]:=double_ptr(ptrcomp(src ) + ix * sizeof(double ) )^;
350
left [iy ][5 ]:=double_ptr(ptrcomp(src ) + iy * sizeof(double ) )^;
351
left [iy ][6 ]:=-double_ptr(ptrcomp(src ) + ix * sizeof(double ) )^ * double_ptr(ptrcomp(dst ) + iy * sizeof(double ) )^;
352
left [iy ][7 ]:=-double_ptr(ptrcomp(src ) + iy * sizeof(double ) )^ * double_ptr(ptrcomp(dst ) + iy * sizeof(double ) )^;
353
right[iy ][0 ]:=double_ptr(ptrcomp(dst ) + iy * sizeof(double ) )^;
357
m_valid:=simul_eq_solve(@left ,@right ,@m_mtx ,8 ,1 );
362
procedure trans_perspective23.rect_to_quad;
376
quad_to_quad(@src ,quad );
381
procedure trans_perspective23.quad_to_rect;
395
quad_to_quad(quad ,@dst );
400
function trans_perspective23.is_valid;
407
function trans_perspective23.begin_;
409
result.Construct(x ,y ,step ,@m_mtx );
414
constructor iterator_x.Construct;
419
constructor iterator_x.Construct(px ,py ,step : double; m : trans_perspective_ptr );
421
den :=px * m.w0 + py * m.w1 + m.w2;
422
den_step:=m.w0 * step;
424
nom_x :=px * m.sx + py * m.shx + m.tx;
425
nom_x_step:=step * m.sx;
426
nom_y :=px * m.shy + py * m.sy + m.ty;
427
nom_y_step:=step * m.shy;
435
procedure iterator_x.operator_inc;
442
nom_x:=nom_x + nom_x_step;
443
nom_y:=nom_y + nom_y_step;
452
// Direct transformation of x and y
453
procedure _transform(this : trans_perspective_ptr; px ,py : double_ptr );
462
m:=1.0 / (x * this.w0 + y * this.w1 + this.w2 );
469
px^:=m * (x * this.sx + y * this.shx + this.tx );
470
py^:=m * (x * this.shy + y * this.sy + this.ty );
474
{ _transform_affine }
475
// Direct transformation of x and y, affine part only
476
procedure _transform_affine(this : trans_perspective_ptr; x ,y : double_ptr );
483
x^:=tmp * this.sx + y^ * this.shx + this.tx;
484
y^:=tmp * this.shy + y^ * this.sy + this.ty;
489
// Direct transformation of x and y, 2x2 matrix only, no translation
490
procedure _transform_2x2(this : trans_perspective_ptr; x ,y : double_ptr );
497
x^:=tmp * this.sx + y^ * this.shx;
498
y^:=tmp * this.shy + y^ * this.sy;
502
{ _inverse_transform }
503
// Inverse transformation of x and y. It works slow because
504
// it explicitly inverts the matrix on every call. For massive
505
// operations it's better to invert() the matrix and then use
506
// direct transformations.
507
procedure _inverse_transform(this : trans_perspective_ptr; x ,y : double_ptr );
509
t : trans_perspective;
515
t.transform(@t ,x ,y );
520
constructor trans_perspective.Construct;
534
transform :=@_transform;
535
transform_2x2 :=@_transform_2x2;
536
inverse_transform:=@_inverse_transform;
537
transform_affine :=@_transform_affine;
542
constructor trans_perspective.Construct(v0 ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 : double );
556
transform :=@_transform;
557
transform_2x2 :=@_transform_2x2;
558
inverse_transform:=@_inverse_transform;
559
transform_affine :=@_transform_affine;
564
constructor trans_perspective.Construct(m : quadrilateral_ptr );
578
transform :=@_transform;
579
transform_2x2 :=@_transform_2x2;
580
inverse_transform:=@_inverse_transform;
581
transform_affine :=@_transform_affine;
586
constructor trans_perspective.Construct_af(a : trans_affine_ptr );
600
transform :=@_transform;
601
transform_2x2 :=@_transform_2x2;
602
inverse_transform:=@_inverse_transform;
603
transform_affine :=@_transform_affine;
608
constructor trans_perspective.Construct(p : trans_perspective_ptr );
622
transform :=@_transform;
623
transform_2x2 :=@_transform_2x2;
624
inverse_transform:=@_inverse_transform;
625
transform_affine :=@_transform_affine;
630
constructor trans_perspective.Construct(x1 ,y1 ,x2 ,y2 : double; quad : quadrilateral_ptr );
634
rect_to_quad(x1 ,y1 ,x2 ,y2 ,quad );
636
transform :=@_transform;
637
transform_2x2 :=@_transform_2x2;
638
inverse_transform:=@_inverse_transform;
639
transform_affine :=@_transform_affine;
644
constructor trans_perspective.Construct(quad : quadrilateral_ptr; x1 ,y1 ,x2 ,y2 : double );
648
quad_to_rect(quad ,x1 ,y1 ,x2 ,y2 );
650
transform :=@_transform;
651
transform_2x2 :=@_transform_2x2;
652
inverse_transform:=@_inverse_transform;
653
transform_affine :=@_transform_affine;
658
constructor trans_perspective.Construct(src ,dst : quadrilateral_ptr );
662
quad_to_quad(src ,dst );
664
transform :=@_transform;
665
transform_2x2 :=@_transform_2x2;
666
inverse_transform:=@_inverse_transform;
667
transform_affine :=@_transform_affine;
672
function trans_perspective.quad_to_quad(qs ,qd : quadrilateral_ptr ) : boolean;
674
p : trans_perspective;
679
if not quad_to_square(qs ) then
687
if not p.square_to_quad(qd ) then
702
function trans_perspective.rect_to_quad(x1 ,y1 ,x2 ,y2 : double; q : quadrilateral_ptr ) : boolean;
704
r : array[0..7 ] of double;
716
result:=quad_to_quad(@r[0 ] ,q );
721
function trans_perspective.quad_to_rect(q : quadrilateral_ptr; x1 ,y1 ,x2 ,y2 : double ) : boolean;
723
r : array[0..7 ] of double;
735
result:=quad_to_quad(q ,@r[0 ] );
740
function trans_perspective.square_to_quad(q : quadrilateral_ptr ) : boolean;
742
dx ,dy ,dx1 ,dy1 ,dx2 ,dy2 ,den ,u ,v : double;
745
dx:=q[0 ] - q[2 ] + q[4 ] - q[6 ];
746
dy:=q[1 ] - q[3 ] + q[5 ] - q[7 ];
751
// Affine case (parallelogram)
769
den:=dx1 * dy2 - dx2 * dy1;
791
u:=(dx * dy2 - dy * dx2 ) / den;
792
v:=(dy * dx1 - dx * dy1 ) / den;
794
sx :=q[2 ] - q[0 ] + u * q[2 ];
795
shy:=q[3 ] - q[1 ] + u * q[3 ];
797
shx:=q[6 ] - q[0 ] + v * q[6 ];
798
sy :=q[7 ] - q[1 ] + v * q[7 ];
811
function trans_perspective.quad_to_square(q : quadrilateral_ptr ) : boolean;
813
if not square_to_quad(q ) then
826
function trans_perspective.reset_ : trans_perspective_ptr;
843
function trans_perspective.invert : boolean;
845
d0 ,d1 ,d2 ,d : double;
847
a : trans_perspective;
850
d0:=sy * w2 - w1 * ty;
851
d1:=w0 * ty - shy * w2;
852
d2:=shy * w1 - w0 * sy;
853
d :=sx * d0 + shx * d1 + tx * d2;
875
a.Construct(trans_perspective_ptr(@self ) );
880
shx:=d * (a.w1 * a.tx - a.shx * a.w2 );
881
sy :=d * (a.sx * a.w2 - a.w0 * a.tx );
882
w1 :=d * (a.w0 * a.shx - a.sx * a.w1 );
883
tx :=d * (a.shx * a.ty - a.sy * a.tx );
884
ty :=d * (a.shy * a.tx - a.sx * a.ty );
885
w2 :=d * (a.sx * a.sy - a.shy * a.shx );
892
function trans_perspective.translate(x ,y : double ) : trans_perspective_ptr;
902
function trans_perspective.rotate(a : double ) : trans_perspective_ptr;
904
tar : trans_affine_rotation;
916
function trans_perspective.scale(s : double ) : trans_perspective_ptr;
918
tas : trans_affine_scaling;
930
function trans_perspective.scale(x ,y : double ) : trans_perspective_ptr;
932
tas : trans_affine_scaling;
935
tas.Construct(x ,y );
944
function trans_perspective.multiply(a : trans_perspective_ptr ) : trans_perspective_ptr;
946
b : trans_perspective;
949
b.Construct(trans_perspective_ptr(@self ) );
951
sx :=a.sx * b.sx + a.shx * b.shy + a.tx * b.w0;
952
shx:=a.sx * b.shx + a.shx * b.sy + a.tx * b.w1;
953
tx :=a.sx * b.tx + a.shx * b.ty + a.tx * b.w2;
954
shy:=a.shy * b.sx + a.sy * b.shy + a.ty * b.w0;
955
sy :=a.shy * b.shx + a.sy * b.sy + a.ty * b.w1;
956
ty :=a.shy * b.tx + a.sy * b.ty + a.ty * b.w2;
957
w0 :=a.w0 * b.sx + a.w1 * b.shy + a.w2 * b.w0;
958
w1 :=a.w0 * b.shx + a.w1 * b.sy + a.w2 * b.w1;
959
w2 :=a.w0 * b.tx + a.w1 * b.ty + a.w2 * b.w2;
966
function trans_perspective.premultiply(b : trans_perspective_ptr ) : trans_perspective_ptr;
968
a : trans_perspective;
971
a.Construct(trans_perspective_ptr(@self ) );
973
sx :=a.sx * b.sx + a.shx * b.shy + a.tx * b.w0;
974
shx:=a.sx * b.shx + a.shx * b.sy + a.tx * b.w1;
975
tx :=a.sx * b.tx + a.shx * b.ty + a.tx * b.w2;
976
shy:=a.shy * b.sx + a.sy * b.shy + a.ty * b.w0;
977
sy :=a.shy * b.shx + a.sy * b.sy + a.ty * b.w1;
978
ty :=a.shy * b.tx + a.sy * b.ty + a.ty * b.w2;
979
w0 :=a.w0 * b.sx + a.w1 * b.shy + a.w2 * b.w0;
980
w1 :=a.w0 * b.shx + a.w1 * b.sy + a.w2 * b.w1;
981
w2 :=a.w0 * b.tx + a.w1 * b.ty + a.w2 * b.w2;
988
function trans_perspective.multiply_inv(m : trans_perspective_ptr ) : trans_perspective_ptr;
990
t : trans_perspective;
996
result:=multiply(@t )
1001
function trans_perspective.premultiply_inv(m : trans_perspective_ptr ) : trans_perspective_ptr;
1003
t : trans_perspective;
1011
Construct(trans_perspective_ptr(@self ) );
1018
function trans_perspective.multiply_af(a : trans_affine_ptr ) : trans_perspective_ptr;
1020
b : trans_perspective;
1023
b.Construct(trans_perspective_ptr(@self ) );
1025
sx :=a.m0 * b.sx + a.m2 * b.shy + a.m4 * b.w0;
1026
shx:=a.m0 * b.shx + a.m2 * b.sy + a.m4 * b.w1;
1027
tx :=a.m0 * b.tx + a.m2 * b.ty + a.m4 * b.w2;
1028
shy:=a.m1 * b.sx + a.m3 * b.shy + a.m5 * b.w0;
1029
sy :=a.m1 * b.shx + a.m3 * b.sy + a.m5 * b.w1;
1030
ty :=a.m1 * b.tx + a.m3 * b.ty + a.m5 * b.w2;
1037
function trans_perspective.premultiply_af(b : trans_affine_ptr ) : trans_perspective_ptr;
1039
a : trans_perspective;
1042
a.Construct(trans_perspective_ptr(@self ) );
1044
sx :=a.sx * b.m0 + a.shx * b.m1;
1045
shx:=a.sx * b.m2 + a.shx * b.m3;
1046
tx :=a.sx * b.m4 + a.shx * b.m5 + a.tx;
1047
shy:=a.shy * b.m0 + a.sy * b.m1;
1048
sy :=a.shy * b.m2 + a.sy * b.m3;
1049
ty :=a.shy * b.m4 + a.sy * b.m5 + a.ty;
1050
w0 :=a.w0 * b.m0 + a.w1 * b.m1;
1051
w1 :=a.w0 * b.m2 + a.w1 * b.m3;
1052
w2 :=a.w0 * b.m4 + a.w1 * b.m5 + a.w2;
1059
function trans_perspective.multiply_inv_af(m : trans_affine_ptr ) : trans_perspective_ptr;
1064
t.Construct(m.m0 ,m.m1 ,m.m2 ,m.m3 ,m.m4 ,m.m5 );
1067
result:=multiply_af(@t );
1071
{ PREMULTIPLY_INV_AF }
1072
function trans_perspective.premultiply_inv_af(m : trans_affine_ptr ) : trans_perspective_ptr;
1074
t : trans_perspective;
1082
Construct(trans_perspective_ptr(@t ) );
1089
procedure trans_perspective.store_to(m : quadrilateral_ptr );
1104
function trans_perspective.load_from(m : quadrilateral_ptr ) : trans_perspective_ptr;
1119
function trans_perspective.from_affine(a : trans_affine_ptr ) : trans_perspective_ptr;
1136
function trans_perspective.determinant : double;
1139
sx * (sy * w2 - ty * w1 ) +
1140
shx * (ty * w0 - shy * w2 ) +
1141
tx * (shy * w1 - sy * w0 );
1145
{ DETERMINANT_RECIPROCAL }
1146
function trans_perspective.determinant_reciprocal : double;
1148
result:=1.0 / determinant;
1153
function trans_perspective.is_valid(epsilon : double = affine_epsilon ) : boolean;
1156
(Abs(sx ) > epsilon ) and
1157
(Abs(sy ) > epsilon ) and
1158
(Abs(w2 ) > epsilon );
1163
function trans_perspective.is_identity(epsilon : double = affine_epsilon ) : boolean;
1166
is_equal_eps(sx ,1.0 ,epsilon ) and
1167
is_equal_eps(shy ,0.0 ,epsilon ) and
1168
is_equal_eps(w0 ,0.0 ,epsilon ) and
1169
is_equal_eps(shx ,0.0 ,epsilon ) and
1170
is_equal_eps(sy ,1.0 ,epsilon ) and
1171
is_equal_eps(w1 ,0.0 ,epsilon ) and
1172
is_equal_eps(tx ,0.0 ,epsilon ) and
1173
is_equal_eps(ty ,0.0 ,epsilon ) and
1174
is_equal_eps(w2 ,1.0 ,epsilon );
1179
function trans_perspective.is_equal(m : trans_perspective_ptr; epsilon : double = affine_epsilon ) : boolean;
1182
is_equal_eps(sx ,m.sx ,epsilon ) and
1183
is_equal_eps(shy ,m.shy ,epsilon ) and
1184
is_equal_eps(w0 ,m.w0 ,epsilon ) and
1185
is_equal_eps(shx ,m.shx ,epsilon ) and
1186
is_equal_eps(sy ,m.sy ,epsilon ) and
1187
is_equal_eps(w1 ,m.w1 ,epsilon ) and
1188
is_equal_eps(tx ,m.tx ,epsilon ) and
1189
is_equal_eps(ty ,m.ty ,epsilon ) and
1190
is_equal_eps(w2 ,m.w2 ,epsilon );
1195
function trans_perspective.scale : double;
1200
x:=0.707106781 * sx + 0.707106781 * shx;
1201
y:=0.707106781 * shy + 0.707106781 * sy;
1203
result:=Sqrt(x * x + y * y );
1208
function trans_perspective.rotation : double;
1210
x1 ,y1 ,x2 ,y2 : double;
1218
_transform(@self ,@x1 ,@y1 );
1219
_transform(@self ,@x2 ,@y2 );
1221
result:=ArcTan2(y2 - y1 ,x2 - x1 );
1226
procedure trans_perspective.translation(dx ,dy : double_ptr );
1234
procedure trans_perspective.scaling(x ,y : double_ptr );
1236
x1 ,y1 ,x2 ,y2 : double;
1238
t : trans_perspective;
1240
tar : trans_affine_rotation;
1248
t.Construct (trans_perspective_ptr(@self ) );
1249
tar.Construct(-rotation );
1250
t.multiply_af(@tar );
1252
t.transform(@t ,@x1 ,@y1 );
1253
t.transform(@t ,@x2 ,@y2 );
1261
procedure trans_perspective.scaling_abs(x ,y : double_ptr );
1263
x^:=Sqrt(sx * sx + shx * shx );
1264
y^:=Sqrt(shy * shy + sy * sy );
1269
function trans_perspective.begin_(x ,y ,step : double ) : iterator_x;
1271
result.Construct(x ,y ,step ,@self );