HOW TO BUILD AN MT WITH A CERTAIN SET OF FEATURES

If we have decided that a feature of an MT must be stored in an attribute table, then we must provide a way to compute the values for filling such table.

Attribute values can be computed:

Guidelines

  1. Define a building interface for the feature. This will be a class that uses an attribute building interface for values of the same type as the internal attribute table used for storing the feature.

    Example: for building tile errors (which are stored in a float attribute table) we use a float attribute building interface (class FloatBuildingInterfaceClass).

    This class, that we call WithYYYBuildingInterfaceClass (where YYY is the name of the feature) will provide functions to record the features, and to build an attribute table storing the features.

  2. If attributes are built at the same time as the MT, define a building interface for the MT having the feature. This will be a subclass of MT_BuildingInterfaceClass and of WithYYYBuildingInterfaceClass. It will have all the functions of class MT_BuildingInterfaceClass, plus the additional features to record and to convert the features (inherited from WithYYYBuildingInterfaceClass).

    Then, use such building interface within a program for iterative refinement or coarsening of a tesselation: record the MT history and the attributes, and then convert both history and attributes into an MT and its attribute table, respectively.

  3. If attributes are built after the construction of the MT, use class WithYYYBuildingInterfaceClass directly for recording attributes and then converting them into the attribute table of the existing MT.

Defining a building interface for a feature - An example

We define the building interface for tile errors, called TileErrorBuildingInterfaceClass. This class contains a pointer to an object of the appropriate subclass of MT_AttrBuildingInterfaceClass, in this case an MT_FloatBuildingInterfaceClass.

It defines a number of functions, all implemented through the auxiliary float building interface. These are the functions that, added to an MT building interface, will allow building an MT with tile errors.

typedef class
        TileErrorBuildingInterfaceClass * TileErrorBuildingInterface;

class TileErrorBuildingInterfaceClass : public virtual MT_BuildingBaseClass
{
  protected:

  /* Auxiliary building interface for float attributes */
  MT_FloatBuildingInterface error_build;

  public:

  /*  Constructor and destructor.  */
  TileErrorBuildingInterfaceClass(void)
  {  error_build = new MT_FloatBuildingInterfaceClass();  }
  ~TileErrorBuildingInterfaceClass(void);
  {  if (error_build) delete error_build;  error_build = NULL;  }

  /*  Record the error value for tile t.  */
  void MakeTileError(MT_INDEX t, float err)
  {  error_build->MT_MakeAttrValue(t,err);  }

  /*  Start and end the tracing of tile errors.  */
  void StartTileErrorHistory(void) {  error_build->MT_StartAttrHistory();  }
  void EndTileErrorHistory(void) {  error_build->MT_EndAttrHistory();  }

  /*  Build a tile error table from the recorded errors.  */                     
  int ConvertTileErrors(void)
  {  ConnectTileAttrBuilder(error_build); /* inform that it is for tiles */
     error_build->MT_AttrConvert();
  }


  /*  Set the tile error table to be built.  */                     
  void SetTargetTileErrorTable(WithTileErrorTableClass * m)
  {  error_build->MT_SetTargetAttrTable(m->TheTileErrorTable());  }

  /*  Set and return the textual description used in the tile error file.
      String s is at most MT_DESCR_LEN characters.  */                     
  void SetTileErrorDescription(char * s)  
  {  error_build->MT_SetDescription(s);  }
  void TheTileErrorDescription(char * s)
  {  error_build->MT_TheDescription(s);  }

};

Defining a building interface for an MT with features - An example

Now, we define the building interface for an MT with tile errors. Tile errors are typically computed during the same process of refinement or coarsening that builds the MT. Thus, it is reasonable to record them during MT construction.

The class for our building interface is called FieldWithErrorBuildingInterfaceClass. We maintain the prefix "FieldWithError" for simmetry with the name of class FieldWithErrorClass, even if vertex fields (since not stored) are not built by the interface.

Class FieldWithErrorBuildingInterfaceClass will be a subclass of MT_BuildingInterfaceClass and of TileErrorBuildingInterfaceClass.

Functions of the first superclass will be used to record the history of tesselation refinement/simplification and to build the MT. Functions of the second superclass will be used to record the tile errors during tesselation refinement/simplification and to build the attribute table containing such errors.

typedef class FieldWithErrorBuildingInterfaceClass *
                                       FieldWithErrorBuildingInterface;

class FieldWithErrorBuildingInterfaceClass :
                 public virtual MT_BuildingInterfaceClass,
                 public virtual TileErrorBuildingInterfaceClass
{
  public:

  /*  Constructor.  */
  FieldWithErrorBuildingInterfaceClass(void)
  :      MT_BuildingInterfaceClass(),
         TileErrorBuildingInterfaceClass()
  { }

};

Directly Building an MT with Features

We already know how to build a plain MT (no attributes).

Suppose that we want to build an MT with a feature YYY associated with its tiles, and a feature ZZZ associated with its vertices (both stored into attribute tables).

We must use a building interface that belongs to a subclass of MT_BuildingInterfaceClass (providing the functions for building the MT), of YYYBuildingInterfaceClass and of ZZZBuildingInterfaceClass (providing the functions for building the attribute table that stores features YYY and ZZZ, respectively).

Such building interface provides functions MakeYYY (inherited from YYYBuildingInterfaceClass) to record the YYY attribute of a tile, and MakeZZZ (inherited from ZZZBuildingInterfaceClass) to record the ZZZ attribute of a vertex.

Here, we list the additional operations to be performed with respect to the construction of a plain MT.

History recording

  1. After calling MT_StartHistory, call StartYYYHistory and StartZZZHistory in order to start recording YYY and ZZZ attributes as well.
  2. Function MakeYYY, which records the YYY attribute of a tile T, can be called at any point during the process of refinement or simplification, after MT_MakeTile has been called for tile T.
  3. Function MakeZZZ, which records the ZZZ attribute of a vertex V, can be called at any point during the process of refinement or simplification, after MT_UseVertex has already been called on vertex V at least once.
  4. After calling MT_EndHistory, call EndYYYHistory and EndZZZHistory in order to end recording attributes as well.
The attribute value for a vertex or a tile may be recorded more than once. The last value will overwrite the previous ones.

History conversion

  1. Create separately an MT that belongs to a subclass of MT_MultiTesselationClass and of WithYYYTableClass.
  2. Connect such MT to the building interface three times: as the target MT (functions MT_SetTarget, and as the target for construction of the tables containing features YYY and ZZZ, respectively (functions SetTargetYYYTable and SetTargetZZZTable).
  3. After having called function MT_Convert, call YYYConvert and ZZZConvert; this will build the attribute tables for tile feature YYY and vertex feature ZZZ.

An example

We refer to the same example as above, where YYY = tile error, and the building interface is FieldWithErrorBuildingInterfaceClass.

We provide here the template of a program that and builds an MT of class FieldWithErrorClass by using a building interface of class FieldWithErrorBuildingInterfaceClass.

We assume that, given a vertex V of the current tesselation within the user program, the MT_INDEX field associated with V is named V.index; and, given a tile T, the MT_INDEX field associated with T is named T.index.

#include "mt_build.h"
#include "fieldmt.h" /* header of class FieldWithErrorClass
                        and FieldWithErrorBuildingInterfaceClass */
....

FieldWithErrorBuildingInterface bi; /* the building interface */
FieldWithError mt;                  /* the MT to be built */

/* create mt as a 2-dimensional scalar field (graph = triangles in 3D) */
mt = new FieldWithErrorClass(3,2); 

/* create the building interface */
bi = new FieldWithErrorBuildingInterfaceClass(); 

/* start history recording */
bi->MT_StartHistory(3,2, MT_REFINING);

/* start tile error recording */
bi->StartTileErrorHistory();

/* initialize all MT_INDEX fields of vertices and tiles */
for (... every vertex V of the initial tesselation ...)
{  V.index = MT_NULL_INDEX;  }
for (... every tile T of the initial tesselation ...)
{  T.index = MT_NULL_INDEX;  }

/* record the update that creates the initial tesselation */
for (... every tile T of the initial tesselation ...)
{
  V1, V2, V3 =  ... the three vertices of T ...
  V1.index = bi->MT_UseVertex(V1.index, V1.coordinates);
  V2.index = bi->MT_UseVertex(V2.index, V1.coordinates);
  V3.index = bi->MT_UseVertex(V3.index, V1.coordinates);
  T.index = bi->MT_MakeTile();
  /* now, we can record the tile error */
  bi->MakeTileError(T.index, T.error);
}
MT_EndUpdate();

/* main loop */
for (... every update performed on the current tesselation ...)
{
   /* record the current update */
   for (... every tile T deleted in this update ...)
   {  bi->MT_KillTile(T.index);  }
   for (... every new vertex V created in this update ...)
   {  V.index = MT_NULL_INDEX;  }
   for (... every new tile T created in this update ...)
   {
      V1, V2, V3 =  ... the three vertices of T ...
      V1.index = bi->MT_UseVertex(V1.index, V1.coordinates);
      V2.index = bi->MT_UseVertex(V2.index, V1.coordinates);
      V3.index = bi->MT_UseVertex(V3.index, V1.coordinates);
      T.index = bi->MT_MakeTile();
      /* now, we can record the tile error */
      bi->MakeTileError(T.index, T.error);
   }
   MT_EndUpdate();
}

/* record an update deleting the final tesselation */
for (... every new tile T of the current tesselation ...)
{  bi->MT_KillTile(T.index);  }
MT_EndUpdate();

/* end history recording */
bi->MT_EndHistory();

/* end tile error recording */
bi->EndTileErrorHistory();

/* set the description string to be associated with the resulting MT */
bi->MT_SetDescription("A 2-dimensional field");

/* set the description string to be associated with the resulting 
   attribute table */
bi->SetTileErrorDescription("The tile errors of a 2-dimensional field");

/* connect mt to the building interface */
bi->MT_SetTarget(mt);

/* connect the error table of the mt to the error building interface */
bi->SetTargetTileErrorTable(mt);

/* build mt from the history just recorded */
bi->MT_Convert();

/* build the tile error table */
bi->ConvertTileErrors();

Building Features for an Existing MT

Suppose that we know how to compute a certain feature YYY for the tiles (or for the vertices) of an existing MT, and we want to add such information to the MT.

We use the building interface for the feature YYY, i.e., class YYYBuildingInterfaceClass for recording the computed values and converting them into the attribute table of our MT (which must belong to a subclass of WithYYYTableClass).

Feature recording

For every tile (or vertex) or the MT, we compute the feature value and call MakeYYY to record it.

Here, the MT_INDEX passed to function MakeYYY is exactly the MT_INDEX identifying such tile (or vertex) in the MT already built.

Feature conversion

We call function SetTargetYYY on the existing MT, in order to specify that the attribute table to be built is the internal YYY table of such an MT.

Then, we call YYYConvert. As a result, the internal YYY table of our MT will be filled with the recorded values. Now, the YYY building interface can be deleted.

An example

We refer to the usual example, where YYY = tile error, and the related building interface is TileErrorBuildingInterfaceClass.

If tile errors are not computed by the same program that builds the MT by progressively refining or coarsening a tesselation, they can be estimated later with some specialized program. We provide here the template of a program that adds tile errors to an MT of class FieldWithErrorClass.

#include "mt_build.h"
#include "fieldmt.h" /* header of class FieldWithErrorClass */
....

TileErrorBuildingInterface bi;   /* tile error building interface */
FieldWithError mt;               /* MT to which tile errors must be added */

MT_INDEX t;     /* a tile of mt */

/* create mt as a 2-dimensional scalar field (graph = triangles in 3D) */
mt = new FieldWithErrorClass(3,2); 

/* read the MT from some file */
mt->MT_Read(...);

/* create the building interface */
bi = new TileErrorBuildingInterfaceClass(); 

/* start tile error recording */
bi->StartTileErrorHistory();

/* loop on the MT tiles to compute and record their errors */
for ( t=1; t<=mt->MT_TileNum(); t++)
{
  ... compute the approximation error of t ...
  ERR = ... the computed error ...
  bi->MakeTileError(t, ERR);
}

/* end tile error recording */
bi->EndTileErrorHistory();

/* set the description string to be associated with the resulting 
   attribute table */
bi->SetTileErrorDescription("The tile errors of a 2-dimensional field");

/* connect the error table of the mt to the error building interface */
bi->SetTargetTileErrorTable(mt);

/* build the tile error table */
bi->ConvertTileErrors();