~ubuntu-branches/ubuntu/saucy/lazarus/saucy

« back to all changes in this revision

Viewing changes to components/aggpas/src/agg_trans_perspective.pas

  • Committer: Package Import Robot
  • Author(s): Paul Gevers, Abou Al Montacir, Bart Martens, Paul Gevers
  • Date: 2013-06-08 14:12:17 UTC
  • mfrom: (1.1.9)
  • Revision ID: package-import@ubuntu.com-20130608141217-7k0cy9id8ifcnutc
Tags: 1.0.8+dfsg-1
[ Abou Al Montacir ]
* New upstream major release and multiple maintenace release offering many
  fixes and new features marking a new milestone for the Lazarus development
  and its stability level.
  - The detailed list of changes can be found here:
    http://wiki.lazarus.freepascal.org/Lazarus_1.0_release_notes
    http://wiki.lazarus.freepascal.org/Lazarus_1.0_fixes_branch
* LCL changes:
  - LCL is now a normal package.
      + Platform independent parts of the LCL are now in the package LCLBase
      + LCL is automatically recompiled when switching the target platform,
        unless pre-compiled binaries for this target are already installed.
      + No impact on existing projects.
      + Linker options needed by LCL are no more added to projects that do
        not use the LCL package.
  - Minor changes in LCL basic classes behaviour
      + TCustomForm.Create raises an exception if a form resource is not
        found.
      + TNotebook and TPage: a new implementation of these classes was added.
      + TDBNavigator: It is now possible to have focusable buttons by setting
        Options = [navFocusableButtons] and TabStop = True, useful for
        accessibility and for devices with neither mouse nor touch screen.
      + Names of TControlBorderSpacing.GetSideSpace and GetSpace were swapped
        and are now consistent. GetSideSpace = Around + GetSpace.
      + TForm.WindowState=wsFullscreen was added
      + TCanvas.TextFitInfo was added to calculate how many characters will
        fit into a specified Width. Useful for word-wrapping calculations.
      + TControl.GetColorResolvingParent and
        TControl.GetRGBColorResolvingParent were added, simplifying the work
        to obtain the final color of the control while resolving clDefault
        and the ParentColor.
      + LCLIntf.GetTextExtentExPoint now has a good default implementation
        which works in any platform not providing a specific implementation.
        However, Widgetset specific implementation is better, when available.
      + TTabControl was reorganized. Now it has the correct class hierarchy
        and inherits from TCustomTabControl as it should.
  - New unit in the LCL:
      + lazdialogs.pas: adds non-native versions of various native dialogs,
        for example TLazOpenDialog, TLazSaveDialog, TLazSelectDirectoryDialog.
        It is used by widgetsets which either do not have a native dialog, or
        do not wish to use it because it is limited. These dialogs can also be
        used by user applications directly.
      + lazdeviceapis.pas: offers an interface to more hardware devices such
        as the accelerometer, GPS, etc. See LazDeviceAPIs
      + lazcanvas.pas: provides a TFPImageCanvas descendent implementing
        drawing in a LCL-compatible way, but 100% in Pascal.
      + lazregions.pas. LazRegions is a wholly Pascal implementation of
        regions for canvas clipping, event clipping, finding in which control
        of a region tree one an event should reach, for drawing polygons, etc.
      + customdrawncontrols.pas, customdrawndrawers.pas,
        customdrawn_common.pas, customdrawn_android.pas and
        customdrawn_winxp.pas: are the Lazarus Custom Drawn Controls -controls
        which imitate the standard LCL ones, but with the difference that they
        are non-native and support skinning.
  - New APIs added to the LCL to improve support of accessibility software
    such as screen readers.
* IDE changes:
  - Many improvments.
  - The detailed list of changes can be found here:
    http://wiki.lazarus.freepascal.org/New_IDE_features_since#v1.0_.282012-08-29.29
    http://wiki.lazarus.freepascal.org/Lazarus_1.0_release_notes#IDE_Changes
* Debugger / Editor changes:
  - Added pascal sources and breakpoints to the disassembler
  - Added threads dialog.
* Components changes:
  - TAChart: many fixes and new features
  - CodeTool: support Delphi style generics and new syntax extensions.
  - AggPas: removed to honor free licencing. (Closes: Bug#708695)
[Bart Martens]
* New debian/watch file fixing issues with upstream RC release.
[Abou Al Montacir]
* Avoid changing files in .pc hidden directory, these are used by quilt for
  internal purpose and could lead to surprises during build.
[Paul Gevers]
* Updated get-orig-source target and it compinion script orig-tar.sh so that they
  repack the source file, allowing bug 708695 to be fixed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//----------------------------------------------------------------------------
2
 
// Anti-Grain Geometry - Version 2.4 (Public License)
3
 
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4
 
//
5
 
// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
6
 
// Pascal Port By: Milan Marusinec alias Milano
7
 
//                 milan@marusinec.sk
8
 
//                 http://www.aggpas.org
9
 
// Copyright (c) 2005-2006
10
 
//
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.
15
 
//
16
 
//----------------------------------------------------------------------------
17
 
// Contact: mcseem@antigrain.com
18
 
//          mcseemagg@yahoo.com
19
 
//          http://www.antigrain.com
20
 
//
21
 
//----------------------------------------------------------------------------
22
 
//
23
 
// Perspective 2D transformations
24
 
//
25
 
// [Pascal Port History] -----------------------------------------------------
26
 
//
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
30
 
//
31
 
{ agg_trans_perspective.pas }
32
 
unit
33
 
 agg_trans_perspective ;
34
 
 
35
 
INTERFACE
36
 
 
37
 
{$I agg_mode.inc }
38
 
 
39
 
uses
40
 
 Math ,
41
 
 agg_basics ,
42
 
 agg_simul_eq ,
43
 
 agg_trans_affine ;
44
 
 
45
 
{ TYPES DEFINITION }
46
 
type
47
 
 iterator_x23 = object
48
 
   den   ,den_step   ,
49
 
   nom_x ,nom_x_step ,
50
 
   nom_y ,nom_y_step : double;
51
 
 
52
 
   x ,y : double;
53
 
 
54
 
   constructor Construct; overload;
55
 
   constructor Construct(tx ,ty ,step : double; m : double_ptr ); overload;
56
 
 
57
 
   procedure inc_operator;
58
 
 
59
 
  end;
60
 
 
61
 
 trans_perspective23_ptr = ^trans_perspective23;
62
 
 trans_perspective23 = object(trans_affine )
63
 
   m_valid : boolean;
64
 
   m_mtx   : array[0..7 ] of double;
65
 
 
66
 
   constructor Construct; overload;
67
 
 
68
 
  // Arbitrary quadrangle transformations
69
 
   constructor Construct(src ,dst : double_ptr ); overload;
70
 
 
71
 
  // Direct transformations
72
 
   constructor Construct(x1 ,y1 ,x2 ,y2 : double; quad : double_ptr ); overload;
73
 
 
74
 
  // Reverse transformations
75
 
   constructor Construct(quad : double_ptr; x1 ,y1 ,x2 ,y2 : double ); overload;
76
 
 
77
 
  // Set the transformations using two arbitrary quadrangles.
78
 
   procedure quad_to_quad(src ,dst : double_ptr );
79
 
 
80
 
  // Set the direct transformations, i.e., rectangle -> quadrangle
81
 
   procedure rect_to_quad(x1 ,y1 ,x2 ,y2 : double; quad : double_ptr );
82
 
 
83
 
  // Set the reverse transformations, i.e., quadrangle -> rectangle
84
 
   procedure quad_to_rect(quad : double_ptr; x1 ,y1 ,x2 ,y2 : double );
85
 
 
86
 
  // Check if the equations were solved successfully
87
 
   function  is_valid : boolean;
88
 
 
89
 
   function  begin_(x ,y ,step : double ) : iterator_x23;
90
 
 
91
 
  end;
92
 
 
93
 
 quadrilateral_ptr = ^quadrilateral;
94
 
 quadrilateral = array[0..8 ] of double;
95
 
 
96
 
 trans_perspective_ptr = ^trans_perspective;
97
 
 
98
 
 iterator_x = object
99
 
   den   ,den_step   ,
100
 
   nom_x ,nom_x_step ,
101
 
   nom_y ,nom_y_step : double;
102
 
 
103
 
   x ,y : double;
104
 
 
105
 
   constructor Construct; overload;
106
 
   constructor Construct(px ,py ,step : double; m : trans_perspective_ptr ); overload;
107
 
 
108
 
   procedure operator_inc;
109
 
 
110
 
  end;
111
 
 
112
 
 trans_perspective = object(trans_affine )
113
 
   sx ,shy ,w0 ,shx ,sy ,w1 ,tx ,ty ,w2 : double;
114
 
 
115
 
   transform_affine : proc_transform;
116
 
 
117
 
  //------------------------------------------------------- Construction
118
 
  // Identity matrix
119
 
   constructor Construct; overload;
120
 
 
121
 
  // Custom matrix
122
 
   constructor Construct(v0 ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 : double ); overload;
123
 
 
124
 
  // Custom matrix from m[9]
125
 
   constructor Construct(m : quadrilateral_ptr ); overload;
126
 
 
127
 
  // From affine
128
 
   constructor Construct_af(a : trans_affine_ptr );
129
 
 
130
 
  // From affine
131
 
   constructor Construct(p : trans_perspective_ptr ); overload;
132
 
 
133
 
  // Rectangle to quadrilateral
134
 
   constructor Construct(x1 ,y1 ,x2 ,y2 : double; quad : quadrilateral_ptr ); overload;
135
 
 
136
 
  // Quadrilateral to rectangle
137
 
   constructor Construct(quad : quadrilateral_ptr; x1 ,y1 ,x2 ,y2 : double ); overload;
138
 
 
139
 
  // Arbitrary quadrilateral transformations
140
 
   constructor Construct(src ,dst : quadrilateral_ptr ); overload;
141
 
 
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;
148
 
 
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;
152
 
 
153
 
  //--------------------------------------------------------- Operations
154
 
  // Reset - load an identity matrix
155
 
   function  reset_ : trans_perspective_ptr;
156
 
 
157
 
  // Invert matrix. Returns false in degenerate case
158
 
   function  invert : boolean;
159
 
 
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;
165
 
 
166
 
  // Multiply the matrix by another one
167
 
   function  multiply(a : trans_perspective_ptr ) : trans_perspective_ptr;
168
 
 
169
 
  // Multiply "m" by "this" and assign the result to "this"
170
 
   function  premultiply(b : trans_perspective_ptr ) : trans_perspective_ptr;
171
 
 
172
 
  // Multiply matrix to inverse of another one
173
 
   function  multiply_inv(m : trans_perspective_ptr ) : trans_perspective_ptr;
174
 
 
175
 
  // Multiply inverse of "m" by "this" and assign the result to "this"
176
 
   function  premultiply_inv(m : trans_perspective_ptr ) : trans_perspective_ptr;
177
 
 
178
 
  // Multiply the matrix by another one
179
 
   function  multiply_af(a : trans_affine_ptr ) : trans_perspective_ptr;
180
 
 
181
 
  // Multiply "m" by "this" and assign the result to "this"
182
 
   function  premultiply_af(b : trans_affine_ptr ) : trans_perspective_ptr;
183
 
 
184
 
  // Multiply the matrix by inverse of another one
185
 
   function  multiply_inv_af(m : trans_affine_ptr ) : trans_perspective_ptr;
186
 
 
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;
189
 
 
190
 
  //--------------------------------------------------------- Load/Store
191
 
   procedure store_to (m : quadrilateral_ptr );
192
 
   function  load_from(m : quadrilateral_ptr ) : trans_perspective_ptr;
193
 
 
194
 
  //---------------------------------------------------------- Auxiliary
195
 
   function  from_affine(a : trans_affine_ptr ) : trans_perspective_ptr;
196
 
 
197
 
   function  determinant : double;
198
 
   function  determinant_reciprocal : double;
199
 
 
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;
203
 
 
204
 
  // Determine the major affine parameters. Use with caution
205
 
  // considering possible degenerate cases.
206
 
   function  scale : double; overload;
207
 
   function  rotation : double;
208
 
 
209
 
   procedure translation(dx ,dy : double_ptr );
210
 
   procedure scaling    (x ,y : double_ptr );
211
 
   procedure scaling_abs(x ,y : double_ptr );
212
 
 
213
 
  // private
214
 
   function  begin_(x ,y ,step : double ) : iterator_x;
215
 
 
216
 
  end;
217
 
 
218
 
{ GLOBAL PROCEDURES }
219
 
 
220
 
 
221
 
IMPLEMENTATION
222
 
{ LOCAL VARIABLES & CONSTANTS }
223
 
{ UNIT IMPLEMENTATION }
224
 
{ CONSTRUCT }
225
 
constructor iterator_x23.Construct;
226
 
begin
227
 
end;
228
 
 
229
 
{ CONSTRUCT }
230
 
constructor iterator_x23.Construct(tx ,ty ,step : double; m : double_ptr );
231
 
begin
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;
234
 
 
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;
237
 
 
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;
240
 
 
241
 
 x:=nom_x / den;
242
 
 y:=nom_y / den;
243
 
 
244
 
end;
245
 
 
246
 
{ INC_OPERATOR }
247
 
procedure iterator_x23.inc_operator;
248
 
var
249
 
 d : double;
250
 
 
251
 
begin
252
 
 den  :=den   + den_step;
253
 
 nom_x:=nom_x + nom_x_step;
254
 
 nom_y:=nom_y + nom_y_step;
255
 
 
256
 
 d:=1.0 / den;
257
 
 x:=nom_x * d;
258
 
 y:=nom_y * d;
259
 
 
260
 
end;
261
 
 
262
 
{ _transform23 }
263
 
procedure _transform23(this : trans_perspective23_ptr; x ,y : double_ptr );
264
 
var
265
 
 tx ,ty ,d : double;
266
 
 
267
 
begin
268
 
 tx:=x^;
269
 
 ty:=y^;
270
 
 d :=1.0 / (this.m_mtx[6 ] * tx + this.m_mtx[7 ] * ty + 1.0 );
271
 
 
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;
274
 
 
275
 
end;
276
 
 
277
 
{ CONSTRUCT }
278
 
constructor trans_perspective23.Construct;
279
 
begin
280
 
 inherited Construct;
281
 
 
282
 
 m_valid:=false;
283
 
 
284
 
 transform:=@_transform23;
285
 
 
286
 
end;
287
 
 
288
 
{ CONSTRUCT }
289
 
constructor trans_perspective23.Construct(src ,dst : double_ptr );
290
 
begin
291
 
 inherited Construct;
292
 
 
293
 
 quad_to_quad(src ,dst );
294
 
 
295
 
 transform:=@_transform23;
296
 
 
297
 
end;
298
 
 
299
 
{ CONSTRUCT }
300
 
constructor trans_perspective23.Construct(x1 ,y1 ,x2 ,y2 : double; quad : double_ptr );
301
 
begin
302
 
 inherited Construct;
303
 
 
304
 
 rect_to_quad(x1 ,y1 ,x2 ,y2 ,quad );
305
 
 
306
 
 transform:=@_transform23;
307
 
 
308
 
end;
309
 
 
310
 
{ CONSTRUCT }
311
 
constructor trans_perspective23.Construct(quad : double_ptr; x1 ,y1 ,x2 ,y2 : double );
312
 
begin
313
 
 inherited Construct;
314
 
 
315
 
 quad_to_rect(quad ,x1 ,y1 ,x2 ,y2 );
316
 
 
317
 
 transform:=@_transform23;
318
 
 
319
 
end;
320
 
 
321
 
{ QUAD_TO_QUAD }
322
 
procedure trans_perspective23.quad_to_quad;
323
 
var
324
 
 left  : double_88;
325
 
 right : double_81;
326
 
 
327
 
 i ,ix ,iy : unsigned;
328
 
 
329
 
begin
330
 
 for i:=0 to 3 do
331
 
  begin
332
 
   ix:=i * 2;
333
 
   iy:=ix + 1;
334
 
 
335
 
   left [ix ][0 ]:=1.0;
336
 
   left [ix ][1 ]:=double_ptr(ptrcomp(src ) + ix * sizeof(double ) )^;
337
 
   left [ix ][2 ]:=double_ptr(ptrcomp(src ) + iy * sizeof(double ) )^;
338
 
   left [ix ][3 ]:=0.0;
339
 
   left [ix ][4 ]:=0.0;
340
 
   left [ix ][5 ]:=0.0;
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 ) )^;
344
 
 
345
 
   left [iy ][0 ]:=0.0;
346
 
   left [iy ][1 ]:=0.0;
347
 
   left [iy ][2 ]:=0.0;
348
 
   left [iy ][3 ]:=1.0;
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 ) )^;
354
 
 
355
 
  end;
356
 
 
357
 
 m_valid:=simul_eq_solve(@left ,@right ,@m_mtx ,8 ,1 );
358
 
 
359
 
end;
360
 
 
361
 
{ RECT_TO_QUAD }
362
 
procedure trans_perspective23.rect_to_quad;
363
 
var
364
 
 src : double_8;
365
 
 
366
 
begin
367
 
 src[0 ]:=x1;
368
 
 src[6 ]:=x1;
369
 
 src[2 ]:=x2;
370
 
 src[4 ]:=x2;
371
 
 src[1 ]:=y1;
372
 
 src[3 ]:=y1;
373
 
 src[5 ]:=y2;
374
 
 src[7 ]:=y2;
375
 
 
376
 
 quad_to_quad(@src ,quad );
377
 
 
378
 
end;
379
 
 
380
 
{ QUAD_TO_RECT }
381
 
procedure trans_perspective23.quad_to_rect;
382
 
var
383
 
 dst : double_8;
384
 
 
385
 
begin
386
 
 dst[0 ]:=x1;
387
 
 dst[6 ]:=x1;
388
 
 dst[2 ]:=x2;
389
 
 dst[4 ]:=x2;
390
 
 dst[1 ]:=y1;
391
 
 dst[3 ]:=y1;
392
 
 dst[5 ]:=y2;
393
 
 dst[7 ]:=y2;
394
 
 
395
 
 quad_to_quad(quad ,@dst );
396
 
 
397
 
end;
398
 
 
399
 
{ IS_VALID }
400
 
function trans_perspective23.is_valid;
401
 
begin
402
 
 result:=m_valid;
403
 
 
404
 
end;
405
 
 
406
 
{ BEGIN_ }
407
 
function trans_perspective23.begin_;
408
 
begin
409
 
 result.Construct(x ,y ,step ,@m_mtx );
410
 
 
411
 
end;
412
 
 
413
 
{ CONSTRUCT }
414
 
constructor iterator_x.Construct;
415
 
begin
416
 
end;
417
 
 
418
 
{ CONSTRUCT }
419
 
constructor iterator_x.Construct(px ,py ,step : double; m : trans_perspective_ptr );
420
 
begin
421
 
 den     :=px * m.w0 + py * m.w1 + m.w2;
422
 
 den_step:=m.w0 * step;
423
 
 
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;
428
 
 
429
 
 x:=nom_x / den;
430
 
 y:=nom_y / den;
431
 
 
432
 
end;
433
 
 
434
 
{ OPERATOR_INC }
435
 
procedure iterator_x.operator_inc;
436
 
var
437
 
 d : double;
438
 
 
439
 
begin
440
 
 den:=den + den_step;
441
 
 
442
 
 nom_x:=nom_x + nom_x_step;
443
 
 nom_y:=nom_y + nom_y_step;
444
 
 
445
 
 d:=1.0 / den;
446
 
 x:=nom_x * d;
447
 
 y:=nom_y * d;
448
 
 
449
 
end;
450
 
 
451
 
{ _transform }
452
 
// Direct transformation of x and y
453
 
procedure _transform(this : trans_perspective_ptr; px ,py : double_ptr );
454
 
var
455
 
 x ,y ,m : double;
456
 
 
457
 
begin
458
 
 x:=px^;
459
 
 y:=py^;
460
 
 
461
 
 try
462
 
  m:=1.0 / (x * this.w0 + y * this.w1 + this.w2 );
463
 
 
464
 
 except
465
 
  m:=0;
466
 
 
467
 
 end;
468
 
 
469
 
 px^:=m * (x * this.sx  + y * this.shx + this.tx );
470
 
 py^:=m * (x * this.shy + y * this.sy  + this.ty );
471
 
 
472
 
end;
473
 
 
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 );
477
 
var
478
 
 tmp : double;
479
 
 
480
 
begin
481
 
 tmp:=x^;
482
 
 
483
 
 x^:=tmp * this.sx  + y^ * this.shx + this.tx;
484
 
 y^:=tmp * this.shy + y^ * this.sy  + this.ty;
485
 
 
486
 
end;
487
 
 
488
 
{ _transform_2x2 }
489
 
// Direct transformation of x and y, 2x2 matrix only, no translation
490
 
procedure _transform_2x2(this : trans_perspective_ptr; x ,y : double_ptr );
491
 
var
492
 
 tmp : double;
493
 
 
494
 
begin
495
 
 tmp:=x^;
496
 
 
497
 
 x^:=tmp * this.sx  + y^ * this.shx;
498
 
 y^:=tmp * this.shy + y^ * this.sy;
499
 
 
500
 
end;
501
 
 
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 );
508
 
var
509
 
 t : trans_perspective;
510
 
 
511
 
begin
512
 
 t.Construct(this );
513
 
 
514
 
 if t.invert then
515
 
  t.transform(@t ,x ,y );
516
 
 
517
 
end;
518
 
 
519
 
{ CONSTRUCT }
520
 
constructor trans_perspective.Construct;
521
 
begin
522
 
 inherited Construct;
523
 
 
524
 
 sx :=1;
525
 
 shy:=0;
526
 
 w0 :=0;
527
 
 shx:=0;
528
 
 sy :=1;
529
 
 w1 :=0;
530
 
 tx :=0;
531
 
 ty :=0;
532
 
 w2 :=1;
533
 
 
534
 
 transform        :=@_transform;
535
 
 transform_2x2    :=@_transform_2x2;
536
 
 inverse_transform:=@_inverse_transform;
537
 
 transform_affine :=@_transform_affine;
538
 
 
539
 
end;
540
 
 
541
 
{ CONSTRUCT }
542
 
constructor trans_perspective.Construct(v0 ,v1 ,v2 ,v3 ,v4 ,v5 ,v6 ,v7 ,v8 : double );
543
 
begin
544
 
 inherited Construct;
545
 
 
546
 
 sx :=v0;
547
 
 shy:=v1;
548
 
 w0 :=v2;
549
 
 shx:=v3;
550
 
 sy :=v4;
551
 
 w1 :=v5;
552
 
 tx :=v6;
553
 
 ty :=v7;
554
 
 w2 :=v8;
555
 
 
556
 
 transform        :=@_transform;
557
 
 transform_2x2    :=@_transform_2x2;
558
 
 inverse_transform:=@_inverse_transform;
559
 
 transform_affine :=@_transform_affine;
560
 
 
561
 
end;
562
 
 
563
 
{ CONSTRUCT }
564
 
constructor trans_perspective.Construct(m : quadrilateral_ptr );
565
 
begin
566
 
 inherited Construct;
567
 
 
568
 
 sx :=m[0 ];
569
 
 shy:=m[1 ];
570
 
 w0 :=m[2 ];
571
 
 shx:=m[3 ];
572
 
 sy :=m[4 ];
573
 
 w1 :=m[5 ];
574
 
 tx :=m[6 ];
575
 
 ty :=m[7 ];
576
 
 w2 :=m[8 ];
577
 
 
578
 
 transform        :=@_transform;
579
 
 transform_2x2    :=@_transform_2x2;
580
 
 inverse_transform:=@_inverse_transform;
581
 
 transform_affine :=@_transform_affine;
582
 
 
583
 
end;
584
 
 
585
 
{ CONSTRUCT }
586
 
constructor trans_perspective.Construct_af(a : trans_affine_ptr );
587
 
begin
588
 
 inherited Construct;
589
 
 
590
 
 sx :=a.m0;
591
 
 shy:=a.m1;
592
 
 w0 :=0;
593
 
 shx:=a.m2;
594
 
 sy :=a.m3;
595
 
 w1 :=0;
596
 
 tx :=a.m4;
597
 
 ty :=a.m5;
598
 
 w2 :=1;
599
 
 
600
 
 transform        :=@_transform;
601
 
 transform_2x2    :=@_transform_2x2;
602
 
 inverse_transform:=@_inverse_transform;
603
 
 transform_affine :=@_transform_affine;
604
 
 
605
 
end;
606
 
 
607
 
{ CONSTRUCT }
608
 
constructor trans_perspective.Construct(p : trans_perspective_ptr );
609
 
begin
610
 
 inherited Construct;
611
 
 
612
 
 sx :=p.sx;
613
 
 shy:=p.shy;
614
 
 w0 :=p.w0;
615
 
 shx:=p.shx;
616
 
 sy :=p.sy;
617
 
 w1 :=p.w1;
618
 
 tx :=p.tx;
619
 
 ty :=p.ty;
620
 
 w2 :=p.w2;
621
 
 
622
 
 transform        :=@_transform;
623
 
 transform_2x2    :=@_transform_2x2;
624
 
 inverse_transform:=@_inverse_transform;
625
 
 transform_affine :=@_transform_affine;
626
 
 
627
 
end;
628
 
 
629
 
{ CONSTRUCT }
630
 
constructor trans_perspective.Construct(x1 ,y1 ,x2 ,y2 : double; quad : quadrilateral_ptr );
631
 
begin
632
 
 inherited Construct;
633
 
 
634
 
 rect_to_quad(x1 ,y1 ,x2 ,y2 ,quad );
635
 
 
636
 
 transform        :=@_transform;
637
 
 transform_2x2    :=@_transform_2x2;
638
 
 inverse_transform:=@_inverse_transform;
639
 
 transform_affine :=@_transform_affine;
640
 
 
641
 
end;
642
 
 
643
 
{ CONSTRUCT }
644
 
constructor trans_perspective.Construct(quad : quadrilateral_ptr; x1 ,y1 ,x2 ,y2 : double );
645
 
begin
646
 
 inherited Construct;
647
 
 
648
 
 quad_to_rect(quad ,x1 ,y1 ,x2 ,y2 );
649
 
 
650
 
 transform        :=@_transform;
651
 
 transform_2x2    :=@_transform_2x2;
652
 
 inverse_transform:=@_inverse_transform;
653
 
 transform_affine :=@_transform_affine;
654
 
 
655
 
end;
656
 
 
657
 
{ CONSTRUCT }
658
 
constructor trans_perspective.Construct(src ,dst : quadrilateral_ptr );
659
 
begin
660
 
 inherited Construct;
661
 
 
662
 
 quad_to_quad(src ,dst );
663
 
 
664
 
 transform        :=@_transform;
665
 
 transform_2x2    :=@_transform_2x2;
666
 
 inverse_transform:=@_inverse_transform;
667
 
 transform_affine :=@_transform_affine;
668
 
 
669
 
end;
670
 
 
671
 
{ QUAD_TO_QUAD }
672
 
function trans_perspective.quad_to_quad(qs ,qd : quadrilateral_ptr ) : boolean;
673
 
var
674
 
 p : trans_perspective;
675
 
 
676
 
begin
677
 
 p.Construct;
678
 
 
679
 
 if not quad_to_square(qs ) then
680
 
  begin
681
 
   result:=false;
682
 
 
683
 
   exit;
684
 
 
685
 
  end;
686
 
 
687
 
 if not p.square_to_quad(qd ) then
688
 
  begin
689
 
   result:=false;
690
 
 
691
 
   exit;
692
 
 
693
 
  end;
694
 
 
695
 
 multiply(@p );
696
 
 
697
 
 result:=true;
698
 
 
699
 
end;
700
 
 
701
 
{ RECT_TO_QUAD }
702
 
function trans_perspective.rect_to_quad(x1 ,y1 ,x2 ,y2 : double; q : quadrilateral_ptr ) : boolean;
703
 
var
704
 
 r : array[0..7 ] of double;
705
 
 
706
 
begin
707
 
 r[0 ]:=x1;
708
 
 r[6 ]:=x1;
709
 
 r[2 ]:=x2;
710
 
 r[4 ]:=x2;
711
 
 r[1 ]:=y1;
712
 
 r[3 ]:=y1;
713
 
 r[5 ]:=y2;
714
 
 r[7 ]:=y2;
715
 
 
716
 
 result:=quad_to_quad(@r[0 ] ,q );
717
 
 
718
 
end;
719
 
 
720
 
{ QUAD_TO_RECT }
721
 
function trans_perspective.quad_to_rect(q : quadrilateral_ptr; x1 ,y1 ,x2 ,y2 : double ) : boolean;
722
 
var
723
 
 r : array[0..7 ] of double;
724
 
 
725
 
begin
726
 
 r[0 ]:=x1;
727
 
 r[6 ]:=x1;
728
 
 r[2 ]:=x2;
729
 
 r[4 ]:=x2;
730
 
 r[1 ]:=y1;
731
 
 r[3 ]:=y1;
732
 
 r[5 ]:=y2;
733
 
 r[7 ]:=y2;
734
 
 
735
 
 result:=quad_to_quad(q ,@r[0 ] );
736
 
 
737
 
end;
738
 
 
739
 
{ SQUARE_TO_QUAD }
740
 
function trans_perspective.square_to_quad(q : quadrilateral_ptr ) : boolean;
741
 
var
742
 
 dx ,dy ,dx1 ,dy1 ,dx2 ,dy2 ,den ,u ,v : double;
743
 
 
744
 
begin
745
 
 dx:=q[0 ] - q[2 ] + q[4 ] - q[6 ];
746
 
 dy:=q[1 ] - q[3 ] + q[5 ] - q[7 ];
747
 
 
748
 
 if (dx = 0.0 ) and
749
 
    (dy = 0.0 ) then
750
 
  begin
751
 
  // Affine case (parallelogram)
752
 
   sx :=q[2 ] - q[0 ];
753
 
   shy:=q[3 ] - q[1 ];
754
 
   w0 :=0.0;
755
 
   shx:=q[4 ] - q[2 ];
756
 
   sy :=q[5 ] - q[3 ];
757
 
   w1 :=0.0;
758
 
   tx :=q[0 ];
759
 
   ty :=q[1 ];
760
 
   w2 :=1.0;
761
 
 
762
 
  end
763
 
 else
764
 
  begin
765
 
   dx1:=q[2 ] - q[4 ];
766
 
   dy1:=q[3 ] - q[5 ];
767
 
   dx2:=q[6 ] - q[4 ];
768
 
   dy2:=q[7 ] - q[5 ];
769
 
   den:=dx1 * dy2 - dx2 * dy1;
770
 
 
771
 
   if den = 0.0 then
772
 
    begin
773
 
    // Singular case
774
 
     sx :=0.0;
775
 
     shy:=0.0;
776
 
     w0 :=0.0;
777
 
     shx:=0.0;
778
 
     sy :=0.0;
779
 
     w1 :=0.0;
780
 
     tx :=0.0;
781
 
     ty :=0.0;
782
 
     w2 :=0.0;
783
 
 
784
 
     result:=false;
785
 
 
786
 
     exit;
787
 
 
788
 
    end;
789
 
 
790
 
  // General case
791
 
   u:=(dx * dy2 - dy * dx2 ) / den;
792
 
   v:=(dy * dx1 - dx * dy1 ) / den;
793
 
 
794
 
   sx :=q[2 ] - q[0 ] + u * q[2 ];
795
 
   shy:=q[3 ] - q[1 ] + u * q[3 ];
796
 
   w0 :=u;
797
 
   shx:=q[6 ] - q[0 ] + v * q[6 ];
798
 
   sy :=q[7 ] - q[1 ] + v * q[7 ];
799
 
   w1 :=v;
800
 
   tx :=q[0 ];
801
 
   ty :=q[1 ];
802
 
   w2 :=1.0;
803
 
 
804
 
  end;
805
 
 
806
 
 result:=true;
807
 
 
808
 
end;
809
 
 
810
 
{ QUAD_TO_SQUARE }
811
 
function trans_perspective.quad_to_square(q : quadrilateral_ptr ) : boolean;
812
 
begin
813
 
 if not square_to_quad(q ) then
814
 
  result:=false
815
 
 else
816
 
  begin
817
 
   invert;
818
 
 
819
 
   result:=true;
820
 
 
821
 
  end;
822
 
 
823
 
end;
824
 
 
825
 
{ RESET_ }
826
 
function trans_perspective.reset_ : trans_perspective_ptr;
827
 
begin
828
 
 sx :=1;
829
 
 shy:=0;
830
 
 w0 :=0;
831
 
 shx:=0;
832
 
 sy :=1;
833
 
 w1 :=0;
834
 
 tx :=0;
835
 
 ty :=0;
836
 
 w2 :=1;
837
 
 
838
 
 result:=@self;
839
 
 
840
 
end;
841
 
 
842
 
{ INVERT }
843
 
function trans_perspective.invert : boolean;
844
 
var
845
 
 d0 ,d1 ,d2 ,d : double;
846
 
 
847
 
 a : trans_perspective;
848
 
 
849
 
begin
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;
854
 
 
855
 
 if d = 0.0 then
856
 
  begin
857
 
   sx :=0.0;
858
 
   shy:=0.0;
859
 
   w0 :=0.0;
860
 
   shx:=0.0;
861
 
   sy :=0.0;
862
 
   w1 :=0.0;
863
 
   tx :=0.0;
864
 
   ty :=0.0;
865
 
   w2 :=0.0;
866
 
 
867
 
   result:=false;
868
 
 
869
 
   exit;
870
 
 
871
 
  end;
872
 
 
873
 
 d:=1.0 / d;
874
 
 
875
 
 a.Construct(trans_perspective_ptr(@self ) );
876
 
 
877
 
 sx :=d * d0;
878
 
 shy:=d * d1;
879
 
 w0 :=d * d2;
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 );
886
 
 
887
 
 result:=true;
888
 
 
889
 
end;
890
 
 
891
 
{ TRANSLATE }
892
 
function trans_perspective.translate(x ,y : double ) : trans_perspective_ptr;
893
 
begin
894
 
 tx:=tx + x;
895
 
 ty:=ty + y;
896
 
 
897
 
 result:=@self;
898
 
 
899
 
end;
900
 
 
901
 
{ ROTATE }
902
 
function trans_perspective.rotate(a : double ) : trans_perspective_ptr;
903
 
var
904
 
 tar : trans_affine_rotation;
905
 
 
906
 
begin
907
 
 tar.Construct(a );
908
 
 
909
 
 multiply_af(@tar );
910
 
 
911
 
 result:=@self;
912
 
 
913
 
end;
914
 
 
915
 
{ SCALE }
916
 
function trans_perspective.scale(s : double ) : trans_perspective_ptr;
917
 
var
918
 
 tas : trans_affine_scaling;
919
 
 
920
 
begin
921
 
 tas.Construct(s );
922
 
 
923
 
 multiply_af(@tas );
924
 
 
925
 
 result:=@self;
926
 
 
927
 
end;
928
 
 
929
 
{ SCALE }
930
 
function trans_perspective.scale(x ,y : double ) : trans_perspective_ptr;
931
 
var
932
 
 tas : trans_affine_scaling;
933
 
 
934
 
begin
935
 
 tas.Construct(x ,y );
936
 
 
937
 
 multiply_af(@tas );
938
 
 
939
 
 result:=@self;
940
 
 
941
 
end;
942
 
 
943
 
{ MULTIPLY }
944
 
function trans_perspective.multiply(a : trans_perspective_ptr ) : trans_perspective_ptr;
945
 
var
946
 
 b : trans_perspective;
947
 
 
948
 
begin
949
 
 b.Construct(trans_perspective_ptr(@self ) );
950
 
 
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;
960
 
 
961
 
 result:=@self;
962
 
 
963
 
end;
964
 
 
965
 
{ PREMULTIPLY }
966
 
function trans_perspective.premultiply(b : trans_perspective_ptr ) : trans_perspective_ptr;
967
 
var
968
 
 a : trans_perspective;
969
 
 
970
 
begin
971
 
 a.Construct(trans_perspective_ptr(@self ) );
972
 
 
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;
982
 
 
983
 
 result:=@self;
984
 
 
985
 
end;
986
 
 
987
 
{ MULTIPLY_INV }
988
 
function trans_perspective.multiply_inv(m : trans_perspective_ptr ) : trans_perspective_ptr;
989
 
var
990
 
 t : trans_perspective;
991
 
 
992
 
begin
993
 
 t.Construct(m );
994
 
 t.invert;
995
 
 
996
 
 result:=multiply(@t )
997
 
 
998
 
end;
999
 
 
1000
 
{ PREMULTIPLY_INV }
1001
 
function trans_perspective.premultiply_inv(m : trans_perspective_ptr ) : trans_perspective_ptr;
1002
 
var
1003
 
 t : trans_perspective;
1004
 
 
1005
 
begin
1006
 
 t.Construct(m );
1007
 
 t.invert;
1008
 
 
1009
 
 t.multiply(@self );
1010
 
 
1011
 
 Construct(trans_perspective_ptr(@self ) );
1012
 
 
1013
 
 result:=@self;
1014
 
 
1015
 
end;
1016
 
 
1017
 
{ MULIPLY_AF }
1018
 
function trans_perspective.multiply_af(a : trans_affine_ptr ) : trans_perspective_ptr;
1019
 
var
1020
 
 b : trans_perspective;
1021
 
 
1022
 
begin
1023
 
 b.Construct(trans_perspective_ptr(@self ) );
1024
 
 
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;
1031
 
 
1032
 
 result:=@self;
1033
 
 
1034
 
end;
1035
 
 
1036
 
{ PREMULTIPLY_AF }
1037
 
function trans_perspective.premultiply_af(b : trans_affine_ptr ) : trans_perspective_ptr;
1038
 
var
1039
 
 a : trans_perspective;
1040
 
 
1041
 
begin
1042
 
 a.Construct(trans_perspective_ptr(@self ) );
1043
 
 
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;
1053
 
 
1054
 
 result:=@self;
1055
 
 
1056
 
end;
1057
 
 
1058
 
{ MULTIPLY_INV_AF }
1059
 
function trans_perspective.multiply_inv_af(m : trans_affine_ptr ) : trans_perspective_ptr;
1060
 
var
1061
 
 t : trans_affine;
1062
 
 
1063
 
begin
1064
 
 t.Construct(m.m0 ,m.m1 ,m.m2 ,m.m3 ,m.m4 ,m.m5 );
1065
 
 t.invert;
1066
 
 
1067
 
 result:=multiply_af(@t );
1068
 
 
1069
 
end;
1070
 
 
1071
 
{ PREMULTIPLY_INV_AF }
1072
 
function trans_perspective.premultiply_inv_af(m : trans_affine_ptr ) : trans_perspective_ptr;
1073
 
var
1074
 
 t : trans_perspective;
1075
 
 
1076
 
begin
1077
 
 t.Construct_af(m );
1078
 
 t.invert;
1079
 
 
1080
 
 t.multiply(@self );
1081
 
 
1082
 
 Construct(trans_perspective_ptr(@t ) );
1083
 
 
1084
 
 result:=@self;
1085
 
 
1086
 
end;
1087
 
 
1088
 
{ STORE_TO }
1089
 
procedure trans_perspective.store_to(m : quadrilateral_ptr );
1090
 
begin
1091
 
 m[0 ]:=sx;
1092
 
 m[1 ]:=shy;
1093
 
 m[2 ]:=w0;
1094
 
 m[3 ]:=shx;
1095
 
 m[4 ]:=sy;
1096
 
 m[5 ]:=w1;
1097
 
 m[6 ]:=tx;
1098
 
 m[7 ]:=ty;
1099
 
 m[8 ]:=w2;
1100
 
 
1101
 
end;
1102
 
 
1103
 
{ LOAD_FROM }
1104
 
function trans_perspective.load_from(m : quadrilateral_ptr ) : trans_perspective_ptr;
1105
 
begin
1106
 
 sx :=m[0 ];
1107
 
 shy:=m[1 ];
1108
 
 w0 :=m[2 ];
1109
 
 shx:=m[3 ];
1110
 
 sy :=m[4 ];
1111
 
 w1 :=m[5 ];
1112
 
 tx :=m[6 ];
1113
 
 ty :=m[7 ];
1114
 
 w2 :=m[8 ];
1115
 
 
1116
 
end;
1117
 
 
1118
 
{ FROM_AFFINE }
1119
 
function trans_perspective.from_affine(a : trans_affine_ptr ) : trans_perspective_ptr;
1120
 
begin
1121
 
 sx :=a.m0;
1122
 
 shy:=a.m1;
1123
 
 w0 :=0;
1124
 
 shx:=a.m2;
1125
 
 sy :=a.m3;
1126
 
 w1 :=0;
1127
 
 tx :=a.m4;
1128
 
 ty :=a.m5;
1129
 
 w2 :=1;
1130
 
 
1131
 
 result:=@self;
1132
 
 
1133
 
end;
1134
 
 
1135
 
{ DETERMINANT }
1136
 
function trans_perspective.determinant : double;
1137
 
begin
1138
 
 result:=
1139
 
  sx  * (sy  * w2 - ty  * w1 ) +
1140
 
  shx * (ty  * w0 - shy * w2 ) +
1141
 
  tx  * (shy * w1 - sy  * w0 );
1142
 
 
1143
 
end;
1144
 
 
1145
 
{ DETERMINANT_RECIPROCAL }
1146
 
function trans_perspective.determinant_reciprocal : double;
1147
 
begin
1148
 
 result:=1.0 / determinant;
1149
 
 
1150
 
end;
1151
 
 
1152
 
{ IS_VALID }
1153
 
function trans_perspective.is_valid(epsilon : double = affine_epsilon ) : boolean;
1154
 
begin
1155
 
 result:=
1156
 
  (Abs(sx ) > epsilon ) and
1157
 
  (Abs(sy ) > epsilon ) and
1158
 
  (Abs(w2 ) > epsilon );
1159
 
 
1160
 
end;
1161
 
 
1162
 
{ IS_IDENTITY }
1163
 
function trans_perspective.is_identity(epsilon : double = affine_epsilon ) : boolean;
1164
 
begin
1165
 
 result:=
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 );
1175
 
 
1176
 
end;
1177
 
 
1178
 
{ IS_EQUAL }
1179
 
function trans_perspective.is_equal(m : trans_perspective_ptr; epsilon : double = affine_epsilon ) : boolean;
1180
 
begin
1181
 
 result:=
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 );
1191
 
 
1192
 
end;
1193
 
 
1194
 
{ SCALE }
1195
 
function trans_perspective.scale : double;
1196
 
var
1197
 
 x ,y : double;
1198
 
 
1199
 
begin
1200
 
 x:=0.707106781 * sx  + 0.707106781 * shx;
1201
 
 y:=0.707106781 * shy + 0.707106781 * sy;
1202
 
 
1203
 
 result:=Sqrt(x * x + y * y );
1204
 
 
1205
 
end;
1206
 
 
1207
 
{ ROTATION }
1208
 
function trans_perspective.rotation : double;
1209
 
var
1210
 
 x1 ,y1 ,x2 ,y2 : double;
1211
 
 
1212
 
begin
1213
 
 x1:=0.0;
1214
 
 y1:=0.0;
1215
 
 x2:=1.0;
1216
 
 y2:=0.0;
1217
 
 
1218
 
 _transform(@self ,@x1 ,@y1 );
1219
 
 _transform(@self ,@x2 ,@y2 );
1220
 
 
1221
 
 result:=ArcTan2(y2 - y1 ,x2 - x1 );
1222
 
 
1223
 
end;
1224
 
 
1225
 
{ TRANSLATION }
1226
 
procedure trans_perspective.translation(dx ,dy : double_ptr );
1227
 
begin
1228
 
 dx^:=tx;
1229
 
 dy^:=ty;
1230
 
 
1231
 
end;
1232
 
 
1233
 
{ SCALING }
1234
 
procedure trans_perspective.scaling(x ,y : double_ptr );
1235
 
var
1236
 
 x1 ,y1 ,x2 ,y2 : double;
1237
 
 
1238
 
 t : trans_perspective;
1239
 
 
1240
 
 tar : trans_affine_rotation;
1241
 
 
1242
 
begin
1243
 
 x1:= 0.0;
1244
 
 y1:= 0.0;
1245
 
 x2:= 1.0;
1246
 
 y2:= 1.0;
1247
 
 
1248
 
 t.Construct  (trans_perspective_ptr(@self ) );
1249
 
 tar.Construct(-rotation );
1250
 
 t.multiply_af(@tar );
1251
 
 
1252
 
 t.transform(@t ,@x1 ,@y1 );
1253
 
 t.transform(@t ,@x2 ,@y2 );
1254
 
 
1255
 
 x^:=x2 - x1;
1256
 
 y^:=y2 - y1;
1257
 
 
1258
 
end;
1259
 
 
1260
 
{ SCALING_ABS }
1261
 
procedure trans_perspective.scaling_abs(x ,y : double_ptr );
1262
 
begin
1263
 
 x^:=Sqrt(sx  * sx  + shx * shx );
1264
 
 y^:=Sqrt(shy * shy + sy  * sy );
1265
 
 
1266
 
end;
1267
 
 
1268
 
{ BEGIN_ }
1269
 
function trans_perspective.begin_(x ,y ,step : double ) : iterator_x;
1270
 
begin
1271
 
 result.Construct(x ,y ,step ,@self );
1272
 
 
1273
 
end;
1274
 
 
1275
 
END.
1276