# IBM Visualization Data Explorer Programmer's Reference

[ Bottom of Page | Previous Page | Next Page | Table of Contents | Partial Table of Contents | Index ]

# Chapter 6. Working with Positions

Partial Table-of-Contents

- 6.1 MakeX Module Example--Create New Positions
- 6.2 MakeXEfficient Module Example--Create New Positions

  The following examples illustrate the manipulation of the "positions" component of a data Field. In these examples it is not necessary to access the "data" component: the data value at a particular position has no effect on the output of the module. This example conforms to the general principle, that the only components of a Field that need to be accessed are those required for the module's function.

  ## 6.1 MakeX Module Example--Create New Positions

  The MakeX module places an "x" at every position in an input Field. MakeX differs from the Add module (see 5.1 , "Add Module Example--Add a Number to Every Data Value") in that, instead of simply modifying a component of the input Field, it creates new positions and connections components.

  The MakeX module takes two inputs: the first, `data`, is of type `field` and has no default value; the second, `size`, is of type `float`, and has a default value of 1.

  The MakeX module has one output: `result`, of type `field`.

  (1) Start the Module Builder with the command:

        dx -builder

  The Module Builder dialog box appears. Note that the dialog box carries no information, since no module has been specified. (For a simple example of creating a module with the Module Builder, see 3.3 , "Using the Module Builder: A Quick Walk Through")

  (2) Select `Open` from the `File` pull-down menu. An `Open a Module Builder file...` dialog box appears.

  (3) Read in `/usr/local/dx/samples/program_guide/makex.mb` as follows:

  - Type the full path name in the `Filter` field of the dialog box.
  - Click on (in sequence):
    - the `Filter` button
    - the name of the file in the `Files` field
    - the `OK` button.
    Information describing the inputs and output of the module (extracted from the `makex.mb` file) appears in the Module Builder dialog box.

  (4) Save the .mb file to a writable directory (use `Save As...` in the `File` pull-down menu).

  (5) Select Create All from the `Build` pull-down menu of the dialog box. This option creates three files for the module: `makex.make`, `makex.c`, and `makex.mdf`.

  (6) Implement the MakeX function. As in the example of Add2Invalid (see 5.3 , "Add2Invalid Module Example--Manipulate Invalid Data"), the MakeX module needs access to the input Object at a higher level than that provided by the MakeX_worker routine. Consequently, the addition of new user code includes a modification of the routine doLeaf as well.

  Use an editor to add the following lines (after extracting the positions Array with `DXGetArrayData`):

         . . .
         p_position = (float *)DXGetArrayData(array);
         if (! positions)
            goto error;
       }
      /* New User code starts here */

      /*
       * Make the new positions array for the output. The positions are
       * 3-dimensional.
       */
         positions = DXNewArray(TYPE_FLOAT, CATEGORY_REAL, 1, 3);
         if (! positions)
            goto error;
      /*
       * Check that the input positions are 3-dimensional:
       */
         if (p_dim != 3) {
            DXSetError(ERROR_INVALID_DATA,"input positions must be 3-dimensional");
            goto error;
         }

      /*
       * Allocate space to the new positions array. Four positions are needed
       * for every input position (the four points making up the "x").
       */
         if (! DXAddArrayData(positions, 0, 4*p_knt, NULL))
            goto error;
      /* Get a pointer to the output positions. */
         out_pos_ptr  = (Point *)DXGetArrayData(positions);
      /* Make a connections component for the output. The connections are
       * 2-dimensional (lines).
       */
         connections = DXNewArray(TYPE_INT, CATEGORY_REAL, 1, 2);

      /* Allocate space to the new connections array. There are two lines for
       * each input position.
       */
         if (! DXAddArrayData(connections, 0, 2*p_knt, NULL))
            goto error;
         DXSetAttribute((Object)connections, "element type",
                        (Object)DXNewString("lines"));
      /* Get a pointer to the new connections. */
         conn_ptr = (Line *)DXGetArrayData(connections);
      /* Get the size of the "x" */
         DXExtractFloat(in[1], &size);

      /* Now "draw" the x's */
         for (i=0; i< p_knt; i++) {
             inpoint = DXPt(p_positions[3*i], p_positions[3*i+1], p_positions[3*i+2]);
             out_pos_ptr[4*i]   = DXPt(inpoint.x - size, inpoint.y, inpoint.z);
             out_pos_ptr[4*i+1] = DXPt(inpoint.x + size, inpoint.y, inpoint.z);
             out_pos_ptr[4*i+2] = DXPt(inpoint.x, inpoint.y - size, inpoint.z);
             out_pos_ptr[4*i+3] = DXPt(inpoint.x, inpoint.y + size, inpoint.z);
             conn_ptr[2*i] = DXLn(4*i, 4*i+1);
             conn_ptr[2*i+1] = DXLn(4*i+2, 4*i+3);
         }

      /* Clean up; we're about to significantly modify the positions and connections
       */
         DXChangedComponentStructure((Field)out[0],"positions");
         DXChangedComponentStructure((Field)out[0],"connections");
      /* Now place the new positions and connections in the output field */
         DXSetComponentValue((Field)out[0], "positions", (Object)positions);
         positions = NULL;
         DXSetComponentValue((Field)out[0], "connections", (Object)connections);
         connections = NULL;
      /* Finalize the field */
         DXEndField((Field)out[0]);
      /* return */
         return OK;
      error:
         DXDelete((Object)positions);
         DXDelete((Object)connections);
         return ERROR;

  (7) Remove the call to MakeX_worker: it is not needed. All of the data processing code has been added to doLeaf (Step 5).

  (8) Insert the following declarations after the first block of code in the doLeaf routine:

        /* User added declarations */
        Point *out_pos_ptr, inpoint;
        Array connections=NULL, positions=NULL;
        Line *conn_ptr;
        float size;

  The file `/usr/local/dx/samples/program_guide/makex.c` contains a completed version of this program.

  (9) To create a version of Data Explorer that includes the MakeX module, enter the command:

      make -f makex.make dxexec

  (You have now created an executable that contains the MakeX module.)

  (10) To invoke this version, enter:

      dx  -mdf ./makex.mdf -exec ./dxexec

  This command starts Data Explorer (the `makex.mdf` file tells the graphical user interface about MakeX and its inputs and outputs). The executable dxexec invoked here is the one created in Step 8.

  (11) With this version of Data Explorer you can now run any visual program that uses the MakeX module. One such program is `/usr/local/dx/samples/program_guide/makex.net`

  [ Top of Page | Previous Page | Next Page | Table of Contents | Partial Table of Contents | Index ]
  [Data Explorer Documentation | QuickStart Guide | User's Guide | User's Reference | Programmer's Reference | Installation and Configuration Guide ]

  [Data Explorer Home Page]

  [IBM Home Page | Order | Search | Contact IBM | Legal ]