.. _scriptref-dtm:

Deformable Template Models (DTM)
================================

A DTM is in my view just a relatively simple way of defining a relationship
between several points. Each of these points have a relative offset to each
other, and may different in colour, tolerance, area size and shape.
A DTM generally consists out of one *Main Point*, and several
*Sub Points*.

Finding functions for DTM include the usual parameters. For explanation on
these, see :ref:`scriptref-finding`.

The structure of a DTM looks like this:


.. figure:: ../../Pics/DTM.png
   :scale: 100 %
   :alt: Structure of a DTM

Where each point in a DTM has a colour, tolerance, area size and area shape
entity. The main point's *point* is typically ``(0, 0)``, and all the
*subpoint* points are relative to the main point.

Example of a simple DTM
-----------------------

If one was to create his own DTM, he would first have to think of a useful DTM
structure.

Say:

.. code-block:: pascal

    MainPoint = (123, 456)
    SubPoint_1 = (122, 460)
    SubPoint_2 = (120, 450)

Then we could create the following MDTM structure:

.. code-block:: pascal

	// Give dtm.p a length of three.
	// Mainpoint
	dtm.p[0] = Point(123, 456);

	// Subpoints
	dtm.p[1] = Point(122, 460)
	dtm.p[2] = Point(120, 450)

Note that we do not include other variables, such as colour, tolerance, area
size and area shape; they are of no importance in this example.

However, this code is not very clear about the DTM's points.
Better would be to write:

.. code-block:: pascal

    // Give dtm.p a length of three.
    // Mainpoint
    dtm.p[0] = Point(0, 0);

    // Subpoints
    dtm.p[1] = Point(-1, 4)  // 122 - 123 = -1, 460 - 456 = 4
    dtm.p[2] = Point(-3, -6) // 120 - 123 = -3, 450 - 456 = -6

As you can see it is perfectly valid to use negative points.

Colour and Tolerance
--------------------

The colour value of a point in a DTM is just a RGB integer value.
Black = 0, Red = 255, White = 16777215, et cetera.

The value tolerance decides if a colour is similar enough to the given
colour; if this is the case, we say that the colours *matched*.

With no Area Size and Area Shape specified
we say that a DTM matches if for each
point in the DTM, the colour at the relative point matches the colour in dtm
with the given tolerance.

.. Colour and Tolerance
.. --------------------

.. \forall p \in P, \forall t \in Tol, \forall c \in Col : T(C(p), c) \leq t

..    With C() defining the colour at the given point, and T() defining the tolerance
..    between the two given colours.

Area Size and Shape
-------------------

Area Size and Shape add that nifty extra functionality to DTM's.
*Area Size* defines the area that should all match the colour
with the given tolerance.
*Area Shape* is currently not implemented, mainly because
we haven't found a good use for area shapes.

Loading a DTM from a string
----------------------------

It is also possible to load a DTM from a *zipped* string.
The details of the algorithm will not be explained here. (Have a look at dtm.pas
if you're interested)

MDTM and TDTM
-------------

One may know DTM's as a different type:

.. code-block:: pascal

  TDTMPointDef = record
    x, y, Color, Tolerance, AreaSize, AreaShape: integer;
  end;

  TDTMPointDefArray = Array Of TDTMPointDef;

  TDTM = record
    MainPoint: TDTMPointDef;
    SubPoints: TDTMPointDefArray;
  end;            

The MML provides the two functions *MDTMtoTDTM* and *TDTMtoMDTM* to
directly convert between the two types.

Main Point and AreaSize / Shape
-------------------------------

The main point's area size and shape are not used in the current
implementation. It wouldn't be that hard to add them, however.

DTMFromString
-------------

.. code-block:: pascal

    function DTMFromString(const DTMString: String): Integer;

Load a DTM from a string generated by the DTM Editor.

SetDTMName
----------

.. code-block:: pascal

    procedure SetDTMName(DTM : integer;const name : string);


Assign the DTM a name. Very useful for debugging purposes as it allows the
programmers to find out what DTMs are not being freed.

FreeDTM
-------

.. code-block:: pascal

    procedure FreeDTM(DTM: Integer);

Free a DTM identified by *DTM*.


FindDTM
-------

.. code-block:: pascal

    function FindDTM(DTM: Integer; var x, y: Integer;
    xs, ys, xe, ye: Integer): Boolean;

FindDTM is the most basic DTM finding function. It takes a box to search in,
defined by *x1, y1, x2, y2*; and if the DTM is found, it will set *x* and 
*y* to the coordinate the DTM was found at and it will also return true. 
Else, it returns false. Once a DTM is found, it will stop searching.
In other words; it always returns the first found DTM.

FindDTMs
--------

.. code-block:: pascal

    function FindDTMs(DTM: Integer; var p: TPointArray;
    xs, ys, xe, ye: Integer): Boolean;

FindDTMs is like FindDTM, but it returns an array of
*x* and *y*, as the *TPointArray* type.

FindDTMRotatedSE
----------------

.. code-block:: pascal

    function FindDTMRotatedSE(DTM: Integer; var x, y: Integer;
    xs, ys, xe, ye: Integer; sAngle, eAngle, aStep: Extended;
    var aFound: Extended): Boolean;

FindDTMRotatedSE behaves like FindDTM. Only, it will rotate the DTM between 
sAngle and eAngle by aStep each time. It will also return the angle which the
DTM was found at. Start rotating at StartAngle.

FindDTMRotatedAlternating
-------------------------

.. code-block:: pascal

    function FindDTMRotatedAlternating(DTM: Integer; var x, y: Integer;
    xs, ys, xe, ye: Integer;
    sAngle, eAngle, aStep: Extended; var aFound: Extended): Boolean;

FindDTMRotated behaves like FindDTM. Only, it will rotate the DTM between 
sAngle and eAngle by aStep each time. It will also return the angle which the
DTM was found at. Starts at 0 degrees and alternatives between - and + aStep to search for the DTM.


FindDTMsRotatedSE
-----------------

.. code-block:: pascal

    function FindDTMsRotatedSE(DTM: Integer; var Points: TPointArray; 
    xs, ys, xe, ye: Integer; sAngle, eAngle, aStep: Extended;
    var aFound: T2DExtendedArray) : Boolean;

FindDTMsRotatedSE behaves like FindRotatedDTMSE, but finds all DTM occurances.
Since one point can be found on several angles, aFound is a 2d array.

FindDTMsRotatedAlternating
--------------------------

.. code-block:: pascal

    function FindDTMsRotatedAlternating(DTM: Integer; 
    var Points: TPointArray; xs, ys, xe, ye: Integer; sAngle, eAngle, aStep: 
    Extended; var aFound: T2DExtendedArray) : Boolean;

FindDTMsRotatedAlternating behaves like FindRotatedDTMAlternating,
but finds all DTM occurances.
Since one point can be found on several angles, aFound is a 2d array.

AddMDTM
-------

.. code-block:: pascal

    function AddMDTM(const d: TMDTM): Integer;


AddDTM
------

.. code-block:: pascal

    function AddDTM(const d: TMDTM): Integer;

Load a TMDTM structure as DTM in Simba's system. (After it is loaded you can use
it in FindDTM, etc)


AddSDTM
-------

.. code-block:: pascal

    function AddSDTM(const d: TSDTM): Integer;

Load a TSDTM structure as DTM in Simba's system. (After it is loaded you can use
it in FindDTM, etc)


GetDTM
------

.. code-block:: pascal

    function GetDTM(index: Integer) : TMDTM

Returns the TMDTM of the given DTM index.


SDTMToMDTM
----------

.. code-block:: pascal

    function SDTMToMDTM(Const DTM: TSDTM): TMDTM;

Convert a SDTM to MDTM.

PrintDTM
--------

.. code-block:: pascal

    procedure PrintDTM(const DTM : TMDTM);

Print the DTM contents.

MDTMToSDTM
----------

.. code-block:: pascal

    function MDTMToSDTM(Const DTM: TMDTM): TSDTM;

Convert a MDTM to SDTM.

CreateDTMPoint
--------------

.. code-block:: pascal

    function CreateDTMPoint(x,y,c,t,asz : integer; bp : boolean) : TMDTMPoint;


Create a DTM point.
