15. Examples

This chapter contains example VisTools programs. The source code for all examples resides in devtools/src/vis/exam.

15.1. Example 1, Draw Isosurfaces and Volume Fringes in Hex and Tet

This example is an extension of “A First Program” appearing in the Introduction. The drawing is illustrated using an 8-node, Serendipity connectivity ordered hexahedron and a 20 node, Lagrange connectivity ordered tetrahedron. The drawing functions are implemented using OpenGL from Silicon Graphics. During compilation define the symbol VKI_3DAPI_OPENGL for the OpenGL interface. The extraction of isosurfaces using vis_ThresholdCurv() is placed in a loop to rotate the displayed isosurfaces. Then a TransMap object is instanced to illustrate “volume fringing”. Volume fringing generates a cloud of points whose density and color are mapped to scalar field value. The TransMap object is used to indicate the density of the points. When doing volume fringing it is useful to use a decay factor on the transparency values to accentuate the fringe bands with the lowest transparency. The Size element of the VisContext object is the characteristic length of a volume, (Size cubed), in which a single point will reside at zero transparency.

All of the OpenGL functions and data are encapsulated in a module called GLWin. This module is coded in a style which has the basic characteristics of a standard DevTools module. The files glwin.c and glwin.h are the source and header files for the GLWin module. GLWin is an example of a user written graphics interface module.

This example is implemented using a VglTools interface in file exam1vgl.c.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

#include "glwin.h"

/* coordinates and data for 8 node hex */
static Vfloat xhex[8][3] = {{0., 0., 0.}, {1., 0., 0.}, {1., 1., 0.}, {0., 1., 0.},
                            {0., 0., 1.}, {1., 0., 1.}, {1., 1., 1.}, {0., 1., 1.}};
static Vfloat shex[8] = {0., 1., 1., 0., 1., 2., 2., 1.};
/* coordinates and data (y coordinate) for 20 node tet */
static Vfloat xtet[20][3] = {{0., 0., 0.}, {.5, 0., 0.}, {1., 0., 0.},  {1.5, 0., 0.}, {0., .5, 0.}, {.5, .5, 0.}, {1., .5, 0.},
                             {0., 1., 0.}, {.5, 1., 0.}, {0., 1.5, 0.}, {0., 0., .5},  {.5, 0., .5}, {1., 0., .5}, {0., .5, .5},
                             {.5, .5, .5}, {0., 1., .5}, {0., 0., 1.},  {.5, 0., 1.},  {0., .5, 1.}, {0., 0., 1.5}};
static Vfloat stet[20] = {0., 0., 0., 0., .5, .5, .5, 1., 1., 1.5, 0., 0., 0., .5, .5, 1., 0., 0., .5, 0.};

static Vfloat rgb[7][3] = {{.2f, .2f, .2f}, {1., 0., 0.}, {0., 1., 0.}, {0., 0., 1.}, {0., 1., 1.}, {1., 0., 1.}, {1., 1., 0.}};

/*----------------------------------------------------------------------
                      Draw Isosurfaces and Volume Fringes in Hex and Tet
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun* df;
    vis_VisContext* vc;
    vis_Levels* levels;
    vis_ColorMap* cmap;
    vis_TransMap* tmap;
    vis_Threshold* threshold;
    GLWin* glwin;

    int i;
    Vint nlevels;

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 200, 200, 400, 400);
    GLWinOrtho(glwin, -2., 2., -2., 2., -2., 2.);

    /* create draw function object for GL */
    df = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, df);

    /* vis context and set attributes */
    vc = vis_VisContextBegin();
    vis_VisContextSetIsoValType(vc, VIS_ISOVALSURFACE);

    /* levels, set six evenly spaced levels */
    levels = vis_LevelsBegin();
    nlevels = 6;
    vis_LevelsDef(levels, LEVELS_LINEAR, nlevels);

    /* color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetType(cmap, COLORMAP_TRUECOLOR);
    vis_ColorMapSetRGB(cmap, nlevels + 1, 0, rgb);

    /* create threshold object and set objects */
    threshold = vis_ThresholdBegin();
    vis_ThresholdSetObject(threshold, VGL_DRAWFUN, df);
    vis_ThresholdSetObject(threshold, VIS_VISCONTEXT, vc);
    vis_ThresholdSetObject(threshold, VIS_LEVELS, levels);
    vis_ThresholdSetObject(threshold, VIS_COLORMAP, cmap);

    /* draw threshold surfaces */
    /* 8 node hex */
    vis_LevelsSetMinMax(levels, 0.0, 2.0);
    vis_LevelsGenerate(levels, LEVELS_PADENDS);
    vis_ThresholdSetTopology(threshold, VIS_SHAPEHEX, 2, 0, 0);
    for (i = 0; i < 10; i++) {
        GLWinClear(glwin);
        GLWinXfmPush(glwin);
        GLWinRotate(glwin, i * 12.F, 'x');
        vis_ThresholdCurv(threshold, shex, xhex, VIS_NODATA, NULL);
        GLWinXfmPop(glwin);
        GLWinSwap(glwin);
        sleep(1);
    }
    sleep(2);
    /* 20 node tet */
    vis_LevelsSetMinMax(levels, 0.0, 1.5);
    vis_LevelsGenerate(levels, LEVELS_PADENDS);
    vis_ThresholdSetTopology(threshold, VIS_SHAPETET, 4, 4, 4);
    for (i = 0; i < 10; i++) {
        GLWinClear(glwin);
        GLWinXfmPush(glwin);
        GLWinRotate(glwin, i * 12.F, 'x');
        vis_ThresholdCurv(threshold, stet, xtet, VIS_NODATA, NULL);
        GLWinXfmPop(glwin);
        GLWinSwap(glwin);
        sleep(1);
    }
    sleep(2);

    /* transparency map */
    tmap = vis_TransMapBegin();
    vis_TransMapSetType(tmap, TRANSMAP_FACTOR);
    vis_TransMapRamp(tmap, nlevels + 2, 0, TRANSMAP_UP);
    vis_TransMapSetDecay(tmap, .1f);

    /* set object in threshold */
    vis_ThresholdSetObject(threshold, VIS_TRANSMAP, tmap);

    /* set viscontext for volume fringing */
    vis_VisContextSetIsoValType(vc, VIS_ISOVALFRINGE);
    vis_VisContextSetMapTrans(vc, VIS_ON);
    vis_VisContextSetSize(vc, .05f);

    /* draw threshold volume fringes */
    /* 8 node hex */
    vis_LevelsSetMinMax(levels, 0.0, 2.0);
    vis_LevelsGenerate(levels, LEVELS_PADENDS);
    vis_ThresholdSetTopology(threshold, VIS_SHAPEHEX, 2, 0, 0);
    for (i = 0; i < 10; i++) {
        GLWinClear(glwin);
        GLWinXfmPush(glwin);
        GLWinRotate(glwin, i * 12.F, 'x');
        vis_ThresholdCurv(threshold, shex, xhex, VIS_NODATA, NULL);
        GLWinXfmPop(glwin);
        GLWinSwap(glwin);
        sleep(1);
    }
    sleep(2);
    /* 20 node tet */
    vis_LevelsSetMinMax(levels, 0.0, 1.5);
    vis_LevelsGenerate(levels, LEVELS_PADENDS);
    vis_ThresholdSetTopology(threshold, VIS_SHAPETET, 4, 4, 4);
    for (i = 0; i < 10; i++) {
        GLWinClear(glwin);
        GLWinXfmPush(glwin);
        GLWinRotate(glwin, i * 12.F, 'x');
        vis_ThresholdCurv(threshold, stet, xtet, VIS_NODATA, NULL);
        GLWinXfmPop(glwin);
        GLWinSwap(glwin);
        sleep(1);
    }
    sleep(2);

    /* free all objects */
    vgl_DrawFunEnd(df);
    vis_VisContextEnd(vc);
    vis_LevelsEnd(levels);
    vis_ColorMapEnd(cmap);
    vis_TransMapEnd(tmap);
    vis_ThresholdEnd(threshold);
    GLWinEnd(glwin);
    return 0;
}

15.2. Example 2, Draw Legends

This example illustrates using the Legend module to draw a simple color bar which displays the color and/or transparency mapping which is represented by a set of ColorMap, TransMap and Levels objects. There are two basic layouts for the color bar; vertical and horizontal. Two variations of a vertical color bar are displayed first followed by a horizontal color bar. The sizing is important for legends to display all the components clearly. The sizes used in this example for the two layouts may be used as a guide. The size of stroked fonts used are proportional to the major size for vertical layouts and to the minor size for horizontal layouts.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

#include "glwin.h"

static Vfloat rgb[3][3] = {{0., 0., 0.}, {1., 1., 1.}, {.5, .5, .5}};

static Vfloat xtex[3] = {-3.8f, 1.8f, 0.f};
static Vfloat ctex[3] = {1., 1., 1.};

/*----------------------------------------------------------------------
                      Draw legends
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun* df;
    vis_VisContext* vc;
    vis_ColorMap* cmap;
    vis_TransMap* tmap;
    vis_Levels* levels;
    vis_Legend* legend;
    GLWin* glwin;

    Vfloat x[3];
    Vint nlevels;

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 200, 200, 800, 400);
    GLWinOrtho(glwin, -4., 4., -2., 2., -2., 2.);

    /* create draw function object for GL */
    df = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, df);

    vc = vis_VisContextBegin();
    vis_VisContextSetLineWidth(vc, 2);
    vis_VisContextSetMinorLineStyle(vc, VIS_SOLID);
    vis_VisContextSetMinorLineWidth(vc, 2);
    vis_VisContextSetMinorColor(vc, 14);
    vis_VisContextSetColor(vc, 15);
    vis_VisContextSetTrans(vc, 1);
    vis_VisContextSetFormat(vc, VIS_E2FORMAT);
    vis_VisContextSetFrequency(vc, 0);
    vis_VisContextSetMapTrans(vc, VIS_OFF);
    nlevels = 12;
    /* color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetType(cmap, COLORMAP_TRUECOLOR);
    vis_ColorMapRamp(cmap, nlevels, 1, COLORMAP_ANSYS);
    vis_ColorMapSetRGB(cmap, 3, 13, rgb);

    /* transparency map */
    tmap = vis_TransMapBegin();
    vis_TransMapSetType(tmap, TRANSMAP_FACTOR);
    vis_TransMapRamp(tmap, nlevels, 1, TRANSMAP_UP);

    /* levels, generate evenly spaced levels */
    levels = vis_LevelsBegin();
    vis_LevelsDef(levels, LEVELS_LINEAR, nlevels);
    vis_LevelsSetMinMax(levels, -2., 2.);
    vis_LevelsSetLabel(levels, nlevels - 2, " Yield Stress");

    /* create Legend object and set objects */
    legend = vis_LegendBegin();
    vis_LegendSetObject(legend, VGL_DRAWFUN, df);
    vis_LegendSetObject(legend, VIS_VISCONTEXT, vc);
    vis_LegendSetObject(legend, VIS_COLORMAP, cmap);
    vis_LegendSetObject(legend, VIS_TRANSMAP, tmap);
    vis_LegendSetObject(legend, VIS_LEVELS, levels);

    /* draw vertical layout */
    x[0] = -1.;
    x[1] = -1.5;
    x[2] = 0.;
    vis_VisContextSetSize(vc, .5);
    vis_VisContextSetMinorSize(vc, 3.);
    vis_LegendSetParami(legend, LEGEND_LAYOUT, LEGEND_VERTICAL);

    /* Fringe, Accent, Raster Font */
    vis_VisContextSetFlags(vc, VIS_ISOVALACCENT);
    vis_LegendSetParami(legend, LEGEND_STROKEFONT, VIS_OFF);
    vis_LegendSetParami(legend, LEGEND_SPECTRUM, LEGEND_FRINGE);
    vis_LegendSetParami(legend, LEGEND_PADTOP, VIS_ON);
    vis_LegendSetParami(legend, LEGEND_LABELUSELEVELS, VIS_ON);
    vis_LevelsGenerate(levels, LEVELS_PADTOP);

    GLWinClear(glwin);
    GLWinColor(glwin, ctex);
    GLWinText(glwin, xtex, "Vertical, Fringe, Accent, Raster Font");
    vis_LegendDraw(legend, x);
    GLWinSwap(glwin);
    sleep(5);
    /* Now draw labels on left */
    vis_LegendSetParami(legend, LEGEND_LABELLEFT, VIS_ON);
    GLWinClear(glwin);
    GLWinColor(glwin, ctex);
    GLWinText(glwin, xtex, "Vertical, Fringe, Accent, Raster Font, Left Labels");
    vis_LegendDraw(legend, x);
    GLWinSwap(glwin);
    sleep(5);

    /* Tone, Accent, Stroke Font */
    vis_LegendSetParami(legend, LEGEND_LABELLEFT, VIS_OFF);
    vis_VisContextSetFlags(vc, VIS_OFF);

    vis_LegendSetParami(legend, LEGEND_STROKEFONT, VIS_ON);
    vis_LegendSetParami(legend, LEGEND_SPECTRUM, LEGEND_TONE);
    vis_LegendSetParami(legend, LEGEND_PADTOP, VIS_OFF);
    vis_LegendSetParami(legend, LEGEND_LABELUSELEVELS, VIS_OFF);
    vis_LevelsGenerate(levels, LEVELS_PADNONE);

    GLWinClear(glwin);
    GLWinColor(glwin, ctex);
    GLWinText(glwin, xtex, "Vertical, Tone, Accent, Stroke Font");
    vis_LegendDraw(legend, x);
    GLWinSwap(glwin);
    sleep(5);

    /* draw horizontal layout */
    x[0] = -3.5;
    x[1] = 0.;
    x[2] = 0.;
    vis_VisContextSetSize(vc, 7.);
    vis_VisContextSetMinorSize(vc, .25);
    vis_LegendSetParami(legend, LEGEND_LAYOUT, LEGEND_HORIZONTAL);

    /* Line, Border, Stroked Font */
    vis_VisContextSetFlags(vc, VIS_OFF);
    vis_LegendSetParami(legend, LEGEND_BORDER, VIS_ON);
    vis_LegendSetParami(legend, LEGEND_SPECTRUM, LEGEND_LINE);
    vis_LegendSetParami(legend, LEGEND_PADTOP, VIS_ON);
    vis_LegendSetParami(legend, LEGEND_PADBOTTOM, VIS_ON);
    vis_LevelsGenerate(levels, LEVELS_PADENDS);

    GLWinClear(glwin);
    GLWinColor(glwin, ctex);
    GLWinText(glwin, xtex, "Horizontal, Line, Border, Stroke Font");
    vis_LegendDraw(legend, x);
    GLWinSwap(glwin);
    sleep(5);

    /* free all objects */
    vgl_DrawFunEnd(df);
    vis_VisContextEnd(vc);
    vis_ColorMapEnd(cmap);
    vis_TransMapEnd(tmap);
    vis_LevelsEnd(levels);
    vis_LegendEnd(legend);
    GLWinEnd(glwin);
    return 0;
}
../../_images/vistools-exam2.gif

Figure 14-2, Vertical Legend

15.3. Example 3, Draw Vectors at Vertices of a Hexahedron

This example is an alteration of Example 1 to draw vectors at the vertices of a hexahedron rather than isosurfaces. The vector data used is simply the position vectors of the vertices. Flags are set in the visualization context to draw the vectors with tails and anchor the vectors by the tail. Two different methods of drawing vectors are illustrated. First the vectors are drawn as 3D vectors using the VIS_VECTORCYLINDER vector type. Second the vectors are drawn as view plane projected 2D vectors using the VIS_VECTORLINE vector type. View plane projected vectors are enabled using vis_VisContextSetProject(). Only VIS_VECTORLINE vector types may be view plane projected. The view plane projected vectors require knowledge of the current model view matrix, set using vis_VisContextSetXfmMatrix(). The vectors are constructed so that the vector heads always appear perpendicular to the line of sight.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

#include "glwin.h"

static Vfloat xhex[8][3] = {{0., 0., 0.}, {1., 0., 0.}, {1., 1., 0.}, {0., 1., 0.},
                            {0., 0., 1.}, {1., 0., 1.}, {1., 1., 1.}, {0., 1., 1.}};
static Vfloat rgb[7][3] = {{.2f, .2f, .2f}, {1., .2f, .2f}, {.2f, 1., .2f}, {.2f, .2f, 1.},
                           {0., 1., 1.},    {1., 0., 1.},   {1., 1., 0.}};

/*----------------------------------------------------------------------
                      Generate vectors at vertices of a hexahedron
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun* df;
    vis_VisContext* vc;
    vis_Levels* levels;
    vis_ColorMap* cmap;
    vis_Mark* mark;
    GLWin* glwin;

    int i;
    Vint nlevels;
    Vfloat tm[4][4];

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 200, 200, 400, 400);
    GLWinOrtho(glwin, -2., 2., -2., 2., -2., 2.);

    /* create draw function object for GL */
    df = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, df);

    /* viscontext and set attributes */
    vc = vis_VisContextBegin();
    vis_VisContextSetFlags(vc, VIS_VECTORTAIL | VIS_VECTORTAILREGISTER);
    vis_VisContextSetVectorType(vc, VIS_VECTORCYLINDER);
    vis_VisContextSetSize(vc, .5);

    /* levels, set six evenly spaced levels */
    levels = vis_LevelsBegin();
    nlevels = 6;
    vis_LevelsDef(levels, LEVELS_LINEAR, nlevels);
    vis_LevelsSetMinMax(levels, 0., 2.);
    vis_LevelsGenerate(levels, LEVELS_PADENDS);

    /* color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetType(cmap, COLORMAP_TRUECOLOR);
    vis_ColorMapSetRGB(cmap, nlevels + 1, 0, rgb);

    /* create mark object and set objects */
    mark = vis_MarkBegin();
    vis_MarkSetObject(mark, VGL_DRAWFUN, df);
    vis_MarkSetObject(mark, VIS_VISCONTEXT_VECTOR, vc);
    vis_MarkSetObject(mark, VIS_LEVELS, levels);
    vis_MarkSetObject(mark, VIS_COLORMAP, cmap);

    /* draw vectors */
    for (i = 0; i < 15; i++) {
        GLWinClear(glwin);
        GLWinXfmPush(glwin);
        GLWinRotate(glwin, i * 12.F, 'x');
        vis_MarkVector(mark, 8, xhex, xhex);
        GLWinXfmPop(glwin);
        GLWinSwap(glwin);
        sleep(1);
    }
    sleep(5);

    /* draw viewplane projected vectors */
    vis_VisContextSetProject(vc, VIS_ON);
    vis_VisContextSetVectorType(vc, VIS_VECTORLINE);
    vis_VisContextSetFill(vc, VIS_OFF);
    vis_VisContextSetFlags(vc, VIS_VECTORTAIL | VIS_VECTORTAILREGISTER | VIS_VECTORNOCAP);

    for (i = 0; i < 15; i++) {
        GLWinClear(glwin);
        GLWinXfmPush(glwin);
        GLWinRotate(glwin, i * 12.F, 'x');
        /* get the current modelview matrix */
        GLWinXfmGet(glwin, tm);
        /* set matrix in viscontext */
        vis_VisContextSetXfmMatrix(vc, tm);
        /* draw vectors */
        vis_MarkVector(mark, 8, xhex, xhex);
        GLWinXfmPop(glwin);
        GLWinSwap(glwin);
        sleep(1);
    }
    sleep(5);
    /* free all objects */
    vgl_DrawFunEnd(df);
    vis_VisContextEnd(vc);
    vis_LevelsEnd(levels);
    vis_ColorMapEnd(cmap);
    vis_MarkEnd(mark);
    GLWinEnd(glwin);
    return 0;
}

15.4. Example 3a, Tensor Computations Using Mark

This example illustrates using the Mark object to perform useful tensor computations, specifically computing principal values and maximum shear values. The direction cosine matrix corresponding to the directions of principal stress or maximum shear are computed in addition to the computed values. Both single and double precision versions are available. Note that no attribute objects are required to perform these computations and no graphics primitives are generated.

#include "base/base.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

/* sample tensor */
static Vdouble td[6] = {5.2586293220520020,  0.32901409268379211,   -0.18742503225803375,
                        0.23982234299182892, -0.042775686830282211, 0.76196306943893433};

/*----------------------------------------------------------------------
                      Tensor Computations Using Mark
----------------------------------------------------------------------*/
int
main()
{
    vis_Mark* mark;

    int i, j;
    Vfloat ts[6];
    Vfloat vs[6], tms[3][3];
    Vdouble vd[6], tmd[3][3];

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create mark object */
    mark = vis_MarkBegin();
    /* load double precison tensor into single */
    for (i = 0; i < 6; i++) {
        ts[i] = (Vfloat)td[i];
    }
    /* compute principal values in single, double precision */
    vis_MarkTensorPrincipal(mark, ts, vs, tms);
    printf("Single precision\n");
    printf("Principal values\n");
    for (i = 0; i < 3; i++) {
        printf(" %e\n", vs[i]);
    }
    printf("Principal directions\n");
    for (i = 0; i < 3; i++) {
        for (j = 0; j < 3; j++) {
            printf(" %16.9e", tms[i][j]);
        }
        printf("\n");
    }

    vis_MarkTensorPrincipaldv(mark, td, vd, tmd);
    printf("Double precision\n");
    printf("Principal values\n");
    for (i = 0; i < 3; i++) {
        printf(" %e\n", vd[i]);
    }
    printf("Principal directions\n");
    for (i = 0; i < 3; i++) {
        for (j = 0; j < 3; j++) {
            printf(" %16.9e", tmd[i][j]);
        }
        printf("\n");
    }

    /* compute max shear values in single, double precision */
    vis_MarkTensorMaxShear(mark, ts, vs, tms);
    printf("Single precision\n");
    printf("Max Shear values\n");
    for (i = 0; i < 6; i++) {
        printf(" %e\n", vs[i]);
    }
    printf("Max Shear directions\n");
    for (i = 0; i < 3; i++) {
        for (j = 0; j < 3; j++) {
            printf(" %16.9e", tms[i][j]);
        }
        printf("\n");
    }

    vis_MarkTensorMaxSheardv(mark, td, vd, tmd);
    printf("Double precision\n");
    printf("Max Shear values\n");
    for (i = 0; i < 6; i++) {
        printf(" %e\n", vd[i]);
    }
    printf("Max Shear directions\n");
    for (i = 0; i < 3; i++) {
        for (j = 0; j < 3; j++) {
            printf(" %16.9e", tmd[i][j]);
        }
        printf("\n");
    }

    vis_MarkEnd(mark);
    return 0;
}

15.5. Example 4, Draw Fringes on Threshold Surfaces

This example illustrates the use of the data interpolation facilities in the isovalue modules. In this example, data interpolation is used in a Threshold object to draw fringes of a scalar field on the threshold surfaces generated in Example 2. The basic concept is to place the Threshold object into the data interpolation mode using a DataInt attribute object. The function vis_DataIntSetDataPtr() is used to specify the number of rows in the data array (in this case, 1 row for a scalar field) and a pointer to the start of the data array. Be sure to set the Draw flag in the visualization context for the Threshold object off so that only data primitives are generated. The output from the Threshold object is now directed to a new DrawFun object which calls a Contour object for generating fringes on the threshold surfaces rather than drawing the threshold surfaces directly. The DrawFun object, which previously was set in the Threshold object is now set in the Contour object.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

#include "glwin.h"

static Vfloat xhex[8][3] = {{0., 0., 0.}, {1., 0., 0.}, {1., 1., 0.}, {0., 1., 0.},
                            {0., 0., 1.}, {1., 0., 1.}, {1., 1., 1.}, {0., 1., 1.}};
static Vfloat shex[8] = {0., 1., 1., 0., 1., 2., 2., 1.};
static Vfloat rhex[8] = {0., 0., 1., 1., 0., 0., 1., 1.};
static Vfloat rgb[7][3] = {{.2f, .2f, .2f}, {1., 0., 0.}, {0., 1., 0.}, {0., 0., 1.}, {0., 1., 1.}, {1., 0., 1.}, {1., 1., 0.}};

/*----------------------------------------------------------------------
                      Generate isosurfaces in a hexahedron
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun *dfGL, *dfC;
    vis_VisContext *vc, *vcC;
    vis_Levels *levels, *levelsC;
    vis_ColorMap* cmap;
    vis_Threshold* threshold;
    vis_Contour* contour;
    vis_DataInt* dataint;
    GLWin* glwin;

    int i;
    Vint nlevels, nlevelsC;

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 200, 200, 400, 400);
    GLWinOrtho(glwin, -2., 2., -2., 2., -2., 2.);

    /* create drawing function object for GL */
    dfGL = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, dfGL);

    /* Threshold data interpolation */
    dataint = vis_DataIntBegin();
    vis_DataIntSetDataPtr(dataint, 0, 1, rhex);

    /* Threshold vis context and set attributes */
    vc = vis_VisContextBegin();
    vis_VisContextSetIsoValType(vc, VIS_ISOVALSURFACE);
    vis_VisContextSetDraw(vc, VIS_OFF);
    vis_VisContextSetShade(vc, VIS_NOSHADE);

    /* Threshold levels, set three evenly spaced levels */
    levels = vis_LevelsBegin();
    nlevels = 3;
    vis_LevelsDef(levels, LEVELS_LINEAR, nlevels);
    vis_LevelsSetMinMax(levels, 0., 2.);
    vis_LevelsGenerate(levels, LEVELS_PADENDS);

    /* Contour vis context and set attributes */
    vcC = vis_VisContextBegin();
    vis_VisContextSetIsoValType(vcC, VIS_ISOVALFRINGE);

    /* Contour levels, set six evenly spaced levels */
    levelsC = vis_LevelsBegin();
    nlevelsC = 6;
    vis_LevelsDef(levelsC, LEVELS_LINEAR, nlevelsC);
    vis_LevelsSetMinMax(levelsC, 0., 1.);
    vis_LevelsGenerate(levelsC, LEVELS_PADTOP);

    /* color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetType(cmap, COLORMAP_TRUECOLOR);
    vis_ColorMapSetRGB(cmap, nlevelsC + 1, 0, rgb);

    /* create contour object and set objects */
    contour = vis_ContourBegin();
    vis_ContourSetObject(contour, VGL_DRAWFUN, dfGL);
    vis_ContourSetObject(contour, VIS_VISCONTEXT, vcC);
    vis_ContourSetObject(contour, VIS_LEVELS, levelsC);
    vis_ContourSetObject(contour, VIS_COLORMAP, cmap);

    /* create contouring drawing function object */
    dfC = vgl_DrawFunBegin();
    vgl_DrawFunSetObj(dfC, contour);
    vgl_DrawFunAPI(dfC, DRAWFUN_APIRETURN);
    /* use function provided by Contour module */
    vgl_DrawFunSet(dfC, DRAWFUN_POLYGONDATA, (Vfunc*)vis_ContourPolygonData);

    /* create threshold object and set objects */
    threshold = vis_ThresholdBegin();
    vis_ThresholdSetObject(threshold, VGL_DRAWFUN, dfC);
    vis_ThresholdSetObject(threshold, VIS_VISCONTEXT, vc);
    vis_ThresholdSetObject(threshold, VIS_LEVELS, levels);
    vis_ThresholdSetObject(threshold, VIS_DATAINT, dataint);

    /* draw threshold surfaces */
    for (i = 0; i < 30; i++) {
        GLWinClear(glwin);
        GLWinXfmPush(glwin);
        GLWinRotate(glwin, i * 12.F, 'x');
        vis_ThresholdCurv(threshold, shex, xhex, VIS_NODATA, NULL);
        GLWinXfmPop(glwin);
        GLWinSwap(glwin);
        sleep(1);
    }
    sleep(5);

    /* free all objects */
    vgl_DrawFunEnd(dfGL);
    vgl_DrawFunEnd(dfC);
    vis_VisContextEnd(vc);
    vis_VisContextEnd(vcC);
    vis_LevelsEnd(levels);
    vis_LevelsEnd(levelsC);
    vis_ColorMapEnd(cmap);
    vis_ThresholdEnd(threshold);
    vis_ContourEnd(contour);
    vis_DataIntEnd(dataint);
    GLWinEnd(glwin);
    return 0;
}

15.6. Example 4a, Draw Fringes on Contour Lines

This example illustrates an extended use of the data interpolation facilities in the isovalue modules. In this example, data interpolation is used in a Threshold object followed by data interpolation in a Contour object to draw fringes of a scalar field on a contour line. The contour line represents the intersection of two scalar fields at two constant values. In this case the scalar fields are the x and y global coordinates and the resulting line represents the intersection of the x = .4 and y = .2 planes. A Segment object is used to draw fringes of a scalar data field interpolated along the line.

The basic concept is to place the Threshold and Contour objects into the data interpolation mode using DataInt attribute objects. The Threshold object interpolates the scalar data field and global x coordinate while extracting an isosurface at y = .4 from a scalar field of the y coordinates. The output from the Threshold object is now directed to a new DrawFun object which contains the custom drawing function, TPolygonData, which calls a Contour object for performing the next step in the process. The Contour object interpolates the scalar data field while extracting an isoline at x = .2 from a scalar field of the x coordinates. The output from the Contour object is directed to the vis_SegmentPolyLineData() function which draws fringes of the interpolated scalar data field on the line which forms the intersection of the x = .4 and y = .2 planes.

A custom structure, Tobj, is defined to facilitate passing the Contour object and the associated data pointer together to the TPolygonData function.

In this example the isoline is the intersection of two planes in global coordinates, but in general any two isosurfaces may be used. For example, to fringe a scalar data field on an arbitrarily oriented straight line, fill dthex[i][1] and sthex with coordinates rotated to a coordinate system aligned to the straight line and extract isovalues at the desired constant values in the rotated coordinate system.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

#include "glwin.h"

static Vfloat xhex[8][3] = {{0., 0., 0.}, {1., 0., 0.}, {1., 1., 0.}, {0., 1., 0.},
                            {0., 0., 1.}, {1., 0., 1.}, {1., 1., 1.}, {0., 1., 1.}};
static Vfloat shex[8] = {0., 1., 1., 0., 1., 2., 2., 1.};
static Vfloat rgb[7][3] = {{.2f, .2f, .2f}, {1., 0., 0.}, {0., 1., 0.}, {0., 0., 1.}, {0., 1., 1.}, {1., 0., 1.}, {1., 1., 0.}};

typedef struct Tobj {
    vis_Contour* contour;
    Vfloat* dctri;
} Tobj;

/*----------------------------------------------------------------------
                      Drawing function for output from Threshold
----------------------------------------------------------------------*/
static void
TPolygonData(Vobject* obj, Vint type, Vint npts, Vfloat x[][3], Vint nrws, Vfloat* d, Vint vflag, Vfloat v[])
{
    int i;
    Vfloat sctri[3];
    Tobj* tobj;

    tobj = (Tobj*)obj;
    /* fill dctri with scalar */
    /* fill sctri with x coordinate */
    for (i = 0; i < 3; i++) {
        tobj->dctri[i] = d[nrws * i];
        sctri[i] = d[nrws * i + 1];
    }

    if (npts == 3) {
        vis_ContourSetTopology(tobj->contour, VIS_SHAPETRI, 0, 0);
    }
    else {
        vis_ContourSetTopology(tobj->contour, VIS_SHAPEQUAD, 0, 0);
    }
    vis_ContourCurv(tobj->contour, sctri, x, VIS_NODATA, NULL);
}

/*----------------------------------------------------------------------
                      Generate isolines in a hexahedron
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun *dfGL, *dfT, *dfC;
    vis_DataInt *diT, *diC;
    vis_VisContext *vcT, *vcC, *vc;
    vis_Levels *levelsT, *levelsC, *levels;
    vis_ColorMap* cmap;
    vis_Threshold* threshold;
    vis_Segment* segment;
    GLWin* glwin;

    int i;
    Vint nlevels;
    Vfloat dthex[8][2], sthex[8];
    /* object info for Threshold drawing function */
    Tobj tobj;
    vis_Contour* contour;
    Vfloat dctri[3];

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 200, 200, 400, 400);
    GLWinOrtho(glwin, -2., 2., -2., 2., -2., 2.);

    /* create drawing function object for GL */
    dfGL = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, dfGL);

    /* Threshold levels, set one level at .2 */
    levelsT = vis_LevelsBegin();
    vis_LevelsDef(levelsT, LEVELS_LINEAR, 1);
    vis_LevelsSetValue(levelsT, 1, .2f);

    /* Contour levels, set one level at .4 */
    levelsC = vis_LevelsBegin();
    vis_LevelsDef(levelsC, LEVELS_LINEAR, 1);
    vis_LevelsSetValue(levelsC, 1, .4f);

    /* Segment levels, set six evenly spaced levels */
    levels = vis_LevelsBegin();
    nlevels = 6;
    vis_LevelsDef(levels, LEVELS_LINEAR, nlevels);
    vis_LevelsSetMinMax(levels, 0., 2.);
    vis_LevelsGenerate(levels, LEVELS_PADTOP);

    /* color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetType(cmap, COLORMAP_TRUECOLOR);
    vis_ColorMapSetRGB(cmap, nlevels + 1, 0, rgb);

    /* Segment vis context and set attributes */
    vc = vis_VisContextBegin();
    vis_VisContextSetIsoValType(vc, VIS_ISOVALFRINGE);
    vis_VisContextSetLineWidth(vc, 2);

    /* create segment object and set objects */
    segment = vis_SegmentBegin();
    vis_SegmentSetObject(segment, VGL_DRAWFUN, dfGL);
    vis_SegmentSetObject(segment, VIS_VISCONTEXT, vc);
    vis_SegmentSetObject(segment, VIS_LEVELS, levels);
    vis_SegmentSetObject(segment, VIS_COLORMAP, cmap);

    /* Contour vis context and set attributes */
    vcC = vis_VisContextBegin();
    vis_VisContextSetIsoValType(vcC, VIS_ISOVALLINE);
    vis_VisContextSetDraw(vcC, VIS_OFF);
    vis_VisContextSetShade(vcC, VIS_NOSHADE);
    vis_VisContextSetMapColor(vcC, VIS_OFF);

    /* create drawing function object for Contour output*/
    dfC = vgl_DrawFunBegin();
    vgl_DrawFunSetObj(dfC, segment);
    vgl_DrawFunAPI(dfC, DRAWFUN_APIRETURN);
    /* use function provided by Segment module */
    vgl_DrawFunSet(dfC, DRAWFUN_POLYLINEDATA, (Vfunc*)vis_SegmentPolyLineData);

    /* Contour data interpolation */
    diC = vis_DataIntBegin();
    vis_DataIntSetDataPtr(diC, 0, 1, (Vfloat*)dctri);

    /* create contour object and set objects */
    contour = vis_ContourBegin();
    vis_ContourSetObject(contour, VGL_DRAWFUN, dfC);
    vis_ContourSetObject(contour, VIS_VISCONTEXT, vcC);
    vis_ContourSetObject(contour, VIS_LEVELS, levelsC);
    vis_ContourSetObject(contour, VIS_DATAINT, diC);

    /* Threshold vis context and set attributes */
    vcT = vis_VisContextBegin();
    vis_VisContextSetIsoValType(vcT, VIS_ISOVALSURFACE);
    vis_VisContextSetDraw(vcT, VIS_OFF);
    vis_VisContextSetShade(vcT, VIS_NOSHADE);
    vis_VisContextSetMapColor(vcT, VIS_OFF);

    /* fill object info */
    tobj.contour = contour;
    tobj.dctri = dctri;
    /* create drawing function object for Threshold output*/
    dfT = vgl_DrawFunBegin();
    vgl_DrawFunSetObj(dfT, (Vobject*)&tobj);
    vgl_DrawFunAPI(dfT, DRAWFUN_APIRETURN);
    vgl_DrawFunSet(dfT, DRAWFUN_POLYGONDATA, (Vfunc*)TPolygonData);

    /* Threshold data interpolation */
    diT = vis_DataIntBegin();
    vis_DataIntSetDataPtr(diT, 0, 2, (Vfloat*)dthex);

    /* create threshold object and set objects */
    threshold = vis_ThresholdBegin();
    vis_ThresholdSetObject(threshold, VGL_DRAWFUN, dfT);
    vis_ThresholdSetObject(threshold, VIS_VISCONTEXT, vcT);
    vis_ThresholdSetObject(threshold, VIS_LEVELS, levelsT);
    vis_ThresholdSetObject(threshold, VIS_DATAINT, diT);

    /* fill dthex with scalar and x coordinate */
    /* fill sthex with y coordinate */
    for (i = 0; i < 8; i++) {
        dthex[i][0] = shex[i];
        dthex[i][1] = xhex[i][0];
        sthex[i] = xhex[i][1];
    }

    /* draw segments */
    for (i = 0; i < 30; i++) {
        GLWinClear(glwin);
        GLWinXfmPush(glwin);
        GLWinRotate(glwin, i * 12.F, 'x');
        vis_ThresholdCurv(threshold, sthex, xhex, VIS_NODATA, NULL);
        GLWinXfmPop(glwin);
        GLWinSwap(glwin);
        sleep(1);
    }
    sleep(5);

    /* free all objects */
    vgl_DrawFunEnd(dfGL);
    vgl_DrawFunEnd(dfT);
    vgl_DrawFunEnd(dfC);
    vis_DataIntEnd(diT);
    vis_DataIntEnd(diC);
    vis_VisContextEnd(vcT);
    vis_VisContextEnd(vcC);
    vis_VisContextEnd(vc);
    vis_LevelsEnd(levelsT);
    vis_LevelsEnd(levelsC);
    vis_LevelsEnd(levels);
    vis_ColorMapEnd(cmap);
    vis_ThresholdEnd(threshold);
    vis_ContourEnd(contour);
    vis_SegmentEnd(segment);
    GLWinEnd(glwin);
    return 0;
}

15.7. Example 5, Tangent Curve Generation in a Plane

This example illustrates the use of the Trace module to generate a tangent curve to a vector field in a simple finite element model consisting of 4 planar quadrilateral elements and 9 node points. A Face object is used to draw the outline of each element and a Mark object is used to draw the vector field at each node. As in previous examples, the interface to the graphics subsystem is satisfied with a GLWin object. Notice that three separate VisContext objects are instanced, one each for the Trace, Face and Mark objects. Note that vis_VisContextTouch() must be called to trigger graphics attribute initialization when using a mixture of visualization objects.

A data structure critical to generating tangent curves is the element adjacency array, adj in this example. The adjacency array contains the element numbers adjacent to each element across each element edge. A zero flags a free edge. This information is used to propagate the tangent curve from one element to its neighbor.

This example is implemented using a VglTools interface in file exam5vgl.c.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

#include "glwin.h"

static void
gather(Vfloat x[][3], Vint con[4], Vfloat xe[][3]);

static Vfloat xquad[9][3] = {{0., 0., 0.}, {1., 0., 0.}, {2., 0., 0.}, {0., 1., 0.}, {1., 1., 0.},
                             {2., 1., 0.}, {0., 2., 0.}, {1., 2., 0.}, {2., 2., 0.}};
static Vfloat vquad[9][3] = {{1., 0., 0.}, {1., 0., 0.},  {1., 1., 0.},  {0., 0., 0.}, {0., 0., 0.},
                             {0., 1., 0.}, {-1., 0., 0.}, {-1., 0., 0.}, {-1., 1., 0.}};
static Vint con[4][4] = {{1, 2, 5, 4}, {2, 3, 6, 5}, {4, 5, 8, 7}, {5, 6, 9, 8}};
static Vint adj[4][4] = {{0, 2, 3, 0}, {0, 0, 4, 1}, {1, 4, 0, 0}, {2, 0, 0, 3}};
static Vfloat rgb[7][3] = {{.2f, .2f, .2f}, {1., 0., 0.}, {0., 1., 0.}, {0., 0., 1.}, {0., 1., 1.}, {1., 0., 1.}, {1., 1., 0.}};

/*----------------------------------------------------------------------
                      Generate tangent curve on quadrilateral elements
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun* df;
    vis_VisContext *vcface, *vcmark, *vctrace;
    vis_ColorMap* cmap;
    vis_Face* face;
    vis_Mark* mark;
    vis_Trace* trace;
    GLWin* glwin;

    int i, j;
    Vfloat xe[4][3], ve[4][3], xc[3];
    Vint nn;
    Vfloat t;
    Vint status, edgenumber;
    Vfloat tout;
    Vfloat v[3], w[3], vout[3], wout[3];

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 100, 100, 600, 600);
    GLWinOrtho(glwin, -1., 3., -1., 3., -3., 3.);

    /* create drawing function object for GL */
    df = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, df);

    /* vis context and set attributes */
    vcface = vis_VisContextBegin();
    vis_VisContextSetEdge(vcface, VIS_ON);
    vis_VisContextSetFill(vcface, VIS_OFF);
    vis_VisContextSetColor(vcface, 4);

    vcmark = vis_VisContextBegin();
    vis_VisContextSetFlags(vcmark, VIS_VECTORTAIL | VIS_VECTORTAILREGISTER);
    vis_VisContextSetVectorType(vcmark, VIS_VECTORCYLINDER);
    vis_VisContextSetSize(vcmark, .5);
    vis_VisContextSetMapColor(vcmark, VIS_OFF);
    vis_VisContextSetColor(vcmark, 1);

    vctrace = vis_VisContextBegin();
    vis_VisContextSetLineStyle(vctrace, VIS_CYLINDER);
    vis_VisContextSetSize(vctrace, .25);
    vis_VisContextSetColor(vctrace, 6);

    /* color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetType(cmap, COLORMAP_TRUECOLOR);
    vis_ColorMapSetRGB(cmap, 7, 0, rgb);

    /* create face object and set objects */
    face = vis_FaceBegin();
    vis_FaceSetObject(face, VGL_DRAWFUN, df);
    vis_FaceSetObject(face, VIS_VISCONTEXT, vcface);
    vis_FaceSetObject(face, VIS_COLORMAP, cmap);

    /* create mark object and set objects */
    mark = vis_MarkBegin();
    vis_MarkSetObject(mark, VGL_DRAWFUN, df);
    vis_MarkSetObject(mark, VIS_VISCONTEXT_VECTOR, vcmark);
    vis_MarkSetObject(mark, VIS_COLORMAP, cmap);

    /* create trace object and set objects */
    trace = vis_TraceBegin();
    vis_TraceSetObject(trace, VGL_DRAWFUN, df);
    vis_TraceSetObject(trace, VIS_VISCONTEXT, vctrace);
    vis_TraceSetObject(trace, VIS_COLORMAP, cmap);
    vis_TraceSetContinuous(trace, VIS_ON);

    for (i = 0; i < 10; i++) {
        GLWinClear(glwin);
        GLWinXfmPush(glwin);
        GLWinRotate(glwin, i * 12.F, 'x');
        /* draw face outlines */
        vis_VisContextTouch(vcface);
        for (j = 0; j < 4; j++) {
            gather(xquad, con[j], xe);
            vis_FaceCurv(face, xe, 0, NULL);
        }
        /* draw vectors */
        vis_VisContextTouch(vcmark);
        vis_MarkVector(mark, 9, vquad, xquad);
        /* draw tangent curve */
        vis_VisContextTouch(vctrace);
        t = 0.;
        nn = 0;
        xc[0] = 0.;
        xc[1] = .5;
        xc[2] = 0.;
        v[0] = 0.;
        v[1] = 0.;
        v[2] = 0.;
        w[0] = 0.;
        w[1] = 0.;
        w[2] = 0.;
        for (;;) {
            gather(xquad, con[nn], xe);
            gather(vquad, con[nn], ve);
            vis_TraceSetEnter(trace, SYS_ON, xc, v, w, t);
            vis_TraceCurv(trace, VIS_VECTOR, (Vfloat*)ve, xe);
            vis_TraceGetExit(trace, SYS_ON, &status, &edgenumber, xc, vout, wout, &tout);
            if (adj[nn][edgenumber - 1]) {
                t = tout;
                nn = adj[nn][edgenumber - 1] - 1;
            }
            else {
                break;
            }
        }

        GLWinXfmPop(glwin);
        GLWinSwap(glwin);
        sleep(1);
    }
    sleep(5);

    /* free all objects */
    vgl_DrawFunEnd(df);
    vis_VisContextEnd(vcface);
    vis_VisContextEnd(vcmark);
    vis_VisContextEnd(vctrace);
    vis_ColorMapEnd(cmap);
    vis_FaceEnd(face);
    vis_MarkEnd(mark);
    vis_TraceEnd(trace);
    GLWinEnd(glwin);
    return 0;
}

/*----------------------------------------------------------------------
                      Utility function to gather element vectors
----------------------------------------------------------------------*/
static void
gather(Vfloat x[][3], Vint conArg[4], Vfloat xe[][3])
{
    int i, j;

    for (i = 0; i < 4; i++) {
        for (j = 0; j < 3; j++) {
            xe[i][j] = x[conArg[i] - 1][j];
        }
    }
}

15.8. Example 5a, Stream Ribbon Generation in a Tri-Parabolic Hexahedron

This example illustrates the use of the Stream module to generate a stream ribbon in a vector field which has non zero vorticity. The problem domain is a single 27 nde tri-parabolic solid element. The vector field has a constant component of .5 in the x direction and contains a vortex core parallel to the z axis passing thought the point y = 1. and z = 1. The stream ribbon is initiated at a point on the vortex core, x = 0., y = 1., z = 1.

The stream ribbon consists of a stream line and an adjoining ribbon anchored to the stream line. The twist of the stream ribbon reflects the streamwise curl of the vector field. The initial orientation vector of the stream ribbon is set to (0.,0.,.5). The streamline will propagate in a straight line down the vortex core. The adjoining stream ribbon will twist around the stream line indicating the streamwise vorticity.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"
#include "glwin.h"

static Vfloat xhex[27][3] = {{0., 0., 0.},    {1.f, 0., 0.},  {2.f, 0., 0.},   {0., 1.f, 0.},   {1.f, 1.f, 0.},
                             {2.f, 1.f, 0.},  {0., 2.f, 0.},  {1., 2.f, 0.},   {2.f, 2.f, 0.},

                             {0., 0., 1.f},   {1.f, 0., 1.f}, {2.f, 0., 1.f},  {0., 1.f, 1.f},  {1.f, 1.f, 1.f},
                             {2.f, 1.f, 1.f}, {0., 2.f, 1.f}, {1.f, 2.f, 1.f}, {2.f, 2.f, 1.f},

                             {0., 0., 2.f},   {1.f, 0., 2.f}, {2.f, 0., 2.f},  {0., 1.f, 2.f},  {1.f, 1.f, 2.f},
                             {2.f, 1.f, 2.f}, {0., 2.f, 2.f}, {1.f, 2.f, 2.f}, {2.f, 2.f, 2.f}};
static Vfloat vhex[27][3] = {
{.5f, 1.f, -1.f}, {.5f, 1.f, -1.f}, {.5f, 1.f, -1.f}, {.5f, 1.f, 0.f},  {.5f, 1.f, 0.f},   {.5f, 1.f, 0.f},   {.5f, 1.f, 1.f},
{.5f, 1.f, 1.f},  {.5f, 1.f, 1.f},  {.5f, 0.f, -1.f}, {.5f, 0.f, -1.f}, {.5f, 0.f, -1.f},  {.5f, 0.f, 0.f},   {.5f, 0.f, 0.f},
{.5f, 0.f, 0.f},  {.5f, 0.f, 1.f},  {.5f, 0.f, 1.f},  {.5f, 0.f, 1.f},  {.5f, -1.f, -1.f}, {.5f, -1.f, -1.f}, {.5f, -1.f, -1.f},
{.5f, -1.f, 0.f}, {.5f, -1.f, 0.f}, {.5f, -1.f, 0.f}, {.5f, -1., 1.f},  {.5f, -1.f, 1.f},  {.5f, -1.f, 1.f}};

static Vfloat rgb[4][3] = {{.2f, .2f, .2f}, {1.f, 0.f, 0.f}, {0.f, 1.f, 0.f}, {0.f, 0.f, 1.f}};

/*----------------------------------------------------------------------
                      Generate streamribbon in a 27 node brick element
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun* df;
    vis_VisContext* vc;
    vis_ColorMap* cmap;
    vis_Stream* stream;
    GLWin* glwin;

    int i;
    Vfloat x[3], v[3], w[3];

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 200, 200, 400, 400);
    GLWinOrtho(glwin, -3., 3., -3., 3., -3., 3.);

    /* create draw function object */
    df = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, df);

    /* vis context and set attributes */
    vc = vis_VisContextBegin();
    vis_VisContextSetStreamType(vc, VIS_STREAMRIBBON);
    vis_VisContextSetLineWidth(vc, 3);
    vis_VisContextSetSize(vc, .1f);
    vis_VisContextSetColor(vc, 1);
    vis_VisContextSetMinorColor(vc, 2);
    vis_VisContextSetShade(vc, VIS_VERTEXSHADE);

    /* color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetType(cmap, COLORMAP_TRUECOLOR);
    vis_ColorMapSetRGB(cmap, 4, 0, rgb);

    /* create stream object and set objects */
    stream = vis_StreamBegin();
    vis_StreamSetObject(stream, VGL_DRAWFUN, df);
    vis_StreamSetObject(stream, VIS_VISCONTEXT, vc);
    vis_StreamSetObject(stream, VIS_COLORMAP, cmap);

    /* draw stream */
    vis_StreamSetTopology(stream, VIS_SHAPEHEX, 3, 3, 3);
    /* set initial position */
    x[0] = 0.;
    x[1] = 1.;
    x[2] = 1.;
    /* set initial orientation vector */
    v[0] = 0.;
    v[1] = 0.;
    v[2] = .5;
    w[0] = 0.;
    w[1] = -.5;
    w[2] = 0.;
    for (i = 0; i < 30; i++) {
        GLWinClear(glwin);
        GLWinXfmPush(glwin);
        GLWinRotate(glwin, i * 12.F, 'y');
        vis_StreamSetEnter(stream, SYS_ON, x, v, w, 0.);
        vis_StreamCurv(stream, VIS_VECTOR, (Vfloat*)vhex, xhex);
        GLWinXfmPop(glwin);
        GLWinSwap(glwin);
        sleep(1);
    }
    sleep(5);

    /* free all objects */
    vgl_DrawFunEnd(df);
    vis_VisContextEnd(vc);
    vis_ColorMapEnd(cmap);
    vis_StreamEnd(stream);
    GLWinEnd(glwin);
    return 0;
}

15.9. Example 6, Using Stroked Fonts

This example illustrates the use of the Font module to generate stroked fonts. Three separate displays are generated. The first draws the text string “Hello World” in varying directions and angles. The second display illustrates the expansion, slant, spacing and extrusion attributes. The third display shows each of the built-in fonts which may be loaded.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

#include "glwin.h"

static Vfloat rgb[7][3] = {{.2f, .2f, .2f}, {1., 0., 0.}, {0., 1., 0.}, {0., 0., 1.}, {0., 1., 1.}, {1., 0., 1.}, {1., 1., 0.}};

/*----------------------------------------------------------------------
                      Generate stroked fonts
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun* df;
    vis_VisContext* vc;
    vis_ColorMap* cmap;
    vis_Font* font;
    GLWin* glwin;

    int i;
    Vfloat x[3];

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 100, 100, 800, 400);
    GLWinOrtho(glwin, -2., 6., -2., 2., -2., 2.);

    /* create drawing function object for GL */
    df = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, df);

    /* vis context and set attributes */
    vc = vis_VisContextBegin();
    vis_VisContextSetColor(vc, 4);
    vis_VisContextSetSize(vc, .1f);

    /* color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetType(cmap, COLORMAP_TRUECOLOR);
    vis_ColorMapSetRGB(cmap, 7, 0, rgb);

    /* create font object and set objects */
    font = vis_FontBegin();
    vis_FontSetObject(font, VGL_DRAWFUN, df);
    vis_FontSetObject(font, VIS_VISCONTEXT, vc);
    vis_FontSetObject(font, VIS_COLORMAP, cmap);

    /* draw standard font */
    GLWinClear(glwin);
    x[0] = x[1] = x[2] = 0.;
    vis_FontSetParami(font, FONT_DIRECTION, VIS_RIGHT);
    vis_FontText(font, x, "Hello World");
    vis_FontSetParami(font, FONT_DIRECTION, VIS_BOTTOM);
    vis_FontText(font, x, "Hello World");
    vis_FontSetParami(font, FONT_DIRECTION, VIS_RIGHT);
    x[1] = .5;
    vis_FontText(font, x, "Hello World");
    vis_FontSetParamf(font, FONT_ANGLE, 30.);
    vis_FontText(font, x, "Hello World");
    vis_FontSetParamf(font, FONT_ANGLE, 60.);
    vis_FontText(font, x, "Hello World");
    vis_FontSetParamf(font, FONT_ANGLE, 90.);
    vis_FontText(font, x, "Hello World");
    vis_FontSetParamf(font, FONT_ANGLE, 0.);
    GLWinSwap(glwin);
    sleep(5);
    /* illustrate expansion, spacing, etc. */
    vis_VisContextSetSize(vc, .1f);
    for (i = 0; i < 30; i++) {
        GLWinClear(glwin);
        GLWinXfmPush(glwin);
        GLWinRotate(glwin, i * 12.F, 'x');

        x[0] = -1.8f;
        x[1] = 1.5f;
        vis_FontText(font, x, "1234 ABCD abcd !@#$%^&*()_+");
        x[0] = -1.8f;
        x[1] = 1.0f;
        vis_FontSetParamf(font, FONT_EXPANSION, .5);
        vis_FontText(font, x, "1234 ABCD abcd !@#$%^&*()_+");
        vis_FontSetParamf(font, FONT_EXPANSION, 1.);
        x[0] = -1.8f;
        x[1] = .5f;
        vis_FontSetParamf(font, FONT_SLANT, .2f);
        vis_FontText(font, x, "1234 ABCD abcd !@#$%^&*()_+");
        vis_FontSetParamf(font, FONT_SLANT, 0.);
        x[0] = -1.8f;
        x[1] = 0.;
        vis_FontSetParamf(font, FONT_SPACING, .2f);
        vis_FontText(font, x, "1234 ABCD abcd !@#$%^&*()_+");
        vis_FontSetParamf(font, FONT_SPACING, 0.);
        x[0] = -1.8f;
        x[1] = -.5f;
        vis_FontSetParamf(font, FONT_EXTRUSION, .02f);
        vis_FontText(font, x, "1234 ABCD abcd !@#$%^&*()_+");
        x[0] = -1.8f;
        x[1] = -1.;
        vis_FontSetParamf(font, FONT_EXTRUSION, .05f);
        vis_VisContextSetSize(vc, .2f);
        vis_FontSetParamf(font, FONT_EXPANSION, .5);
        vis_FontText(font, x, "1234 ABCD abcd !@#$%^&*()_+");
        vis_FontSetParamf(font, FONT_EXTRUSION, 0.);
        vis_VisContextSetSize(vc, .1f);
        vis_FontSetParamf(font, FONT_EXPANSION, 1.);

        GLWinXfmPop(glwin);
        GLWinSwap(glwin);
        sleep(1);
    }
    sleep(5);
    /* illustrate available fonts */
    GLWinClear(glwin);
    vis_VisContextSetSize(vc, .15f);
    x[0] = -1.8f;
    x[1] = 1.8f;
    vis_FontLoad(font, FONT_GREEK);
    vis_FontText(font, x, "1234 ABCD abcd !@#$ GREEK");
    x[0] = -1.8f;
    x[1] = 1.4f;
    vis_FontLoad(font, FONT_ITALICS);
    vis_FontText(font, x, "1234 ABCD abcd !@#$ ITALICS");
    x[0] = -1.8f;
    x[1] = 1.0;
    vis_FontLoad(font, FONT_ROMAN1);
    vis_FontText(font, x, "1234 ABCD abcd !@#$ ROMAN1");
    x[0] = -1.8f;
    x[1] = .6f;
    vis_FontLoad(font, FONT_ROMAN2);
    vis_FontText(font, x, "1234 ABCD abcd !@#$ ROMAN2");
    x[0] = -1.8f;
    x[1] = .2f;
    vis_FontLoad(font, FONT_BOLDSCRIPT);
    vis_FontText(font, x, "1234 ABCD abcd !@#$ BOLDSCRIPT");
    /*
       x[0] = -1.8; x[1] = -.2;
       vis_FontLoad (font,FONT_FILLROMAN1);
       vis_FontText (font,x,"1234 ABCD abcd !@#$ FILLROMAN1");
       x[0] = -1.8; x[1] = -.6;
       vis_FontLoad (font,FONT_FILLROMAN2);
       vis_FontText (font,x,"1234 ABCD abcd !@#$ FILLROMAN2");
       x[0] = -1.8; x[1] = -1.0;
       vis_FontLoad (font,FONT_GOTHIC);
       vis_FontText (font,x,"1234 ABCD abcd !@#$ GOTHIC");
    */
    x[0] = -1.8f;
    x[1] = -1.4f;
    vis_FontLoad(font, FONT_SCRIPT);
    vis_FontText(font, x, "1234 ABCD abcd !@#$ SCRIPT");
    x[0] = -1.8f;
    x[1] = -1.8f;
    vis_FontLoad(font, FONT_UNCIAL);
    vis_FontText(font, x, "1234 ABCD abcd !@#$ UNCIAL");
    GLWinSwap(glwin);

    sleep(5);

    /* free all objects */
    vgl_DrawFunEnd(df);
    vis_VisContextEnd(vc);
    vis_ColorMapEnd(cmap);
    vis_FontEnd(font);
    GLWinEnd(glwin);
    return 0;
}

15.10. Example 7, Using Glyphs

This example illustrates the use of the Glyph module to generate 2D and 3D glyphs. Several of the glyphs which are displayed are not documented in the current release of VisTools but will be available in future versions.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"
#include "glwin.h"

static Vfloat rgb[7][3] = {{.2f, .2f, .2f}, {1., 0., 0.}, {0., 1., 0.}, {0., 0., 1.}, {0., 1., 1.}, {1., 0., 1.}, {1., 1., 0.}};

/*----------------------------------------------------------------------
                      Generate periodic table of glyphs
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun* df;
    vis_VisContext* vc;
    vis_ColorMap* cmap;
    vis_Glyph* glyph;
    GLWin* glwin;

    int i;
    Vfloat x[3];

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 200, 200, 400, 400);
    GLWinOrtho(glwin, -2., 2., -2., 2., -2., 2.);

    /* create drawing function object for GL */
    df = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, df);

    /* vis context and set attributes */
    vc = vis_VisContextBegin();
    vis_VisContextSetColor(vc, 4);
    vis_VisContextSetRefinement(vc, 0);
    vis_VisContextSetShade(vc, VIS_VERTEXSHADE);

    /* color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetType(cmap, COLORMAP_TRUECOLOR);
    vis_ColorMapSetRGB(cmap, 7, 0, rgb);

    /* create glyph object and set objects */
    glyph = vis_GlyphBegin();
    vis_GlyphSetObject(glyph, VGL_DRAWFUN, df);
    vis_GlyphSetObject(glyph, VIS_VISCONTEXT, vc);
    vis_GlyphSetObject(glyph, VIS_COLORMAP, cmap);

    /* illustrate glyphs */
    for (i = 0; i < 30; i++) {
        GLWinClear(glwin);
        GLWinXfmPush(glwin);
        GLWinRotate(glwin, i * 12.F, 'x');

        vis_VisContextSetColor(vc, 4);
        x[0] = -1.5f;
        x[1] = 1.5f;
        x[2] = 0.f;
        vis_GlyphArrow2D(glyph, x, .4f, .1f, .1f, 0.f, 1, VIS_ON, VIS_ON, 1, 1);
        x[0] = -1.0f;
        x[1] = 1.5f;
        vis_GlyphArrow3D(glyph, x, .4f, .1f, .1f, 0.f, 1, VIS_ON, 1, 0, 1);
        x[0] = -.5f;
        x[1] = 1.5f;
        vis_GlyphBox(glyph, x, .2f, .3f, .4f, VIS_ON);
        x[0] = .0f;
        x[1] = 1.5f;
        vis_GlyphCircle(glyph, x, .1f, 0.f, VIS_OFF);
        x[0] = .5f;
        x[1] = 1.5f;
        vis_GlyphCylinder(glyph, x, .1f, .4f, 0.f, 1);
        x[0] = 1.0f;
        x[1] = 1.5f;
        vis_GlyphEllipsoid(glyph, x, .2f, .4f, .6f);
        x[0] = 1.5f;
        x[1] = 1.5f;
        vis_GlyphRectangle(glyph, x, .2f, .4f, 0.f, VIS_OFF);

        vis_VisContextSetColor(vc, 5);
        x[0] = -1.5f;
        x[1] = 0.5f;
        vis_GlyphSphere(glyph, x, .2f, 1);
        x[0] = -1.0f;
        x[1] = 0.5f;
        vis_GlyphCone(glyph, x, .2f, .4f, 0.f, 1);
        x[0] = -.5f;
        x[1] = 0.5f;
        vis_GlyphTetrahedron(glyph, x, .2f, 1);
        x[0] = .0f;
        x[1] = 0.5f;
        vis_GlyphPyramid(glyph, x, .2f, .4f, .6f);
        x[0] = .5f;
        x[1] = 0.5f;
        vis_GlyphOctahedron(glyph, x, .2f, .4f, .6f, 1);
        x[0] = 1.0f;
        x[1] = 0.5f;
        vis_GlyphTriaxis(glyph, x, .2f, .4f, .6f, 0.f);
        x[0] = 1.5f;
        x[1] = 0.5f;
        vis_GlyphTriangle(glyph, x, .2f, 1);

        vis_VisContextSetColor(vc, 6);
        x[0] = -1.5f;
        x[1] = -.5f;
        vis_GlyphDiamond(glyph, x, .2f, .15f, 0);
        x[0] = -1.0f;
        x[1] = -.5f;
        vis_GlyphHourglass(glyph, x, .2f);
        x[0] = -.5f;
        x[1] = -.5f;
        vis_GlyphGround(glyph, x, .2f, 0.f, 0.f);
        x[0] = 0.f;
        x[1] = -.5f;
        vis_GlyphLine(glyph, x, .4f, 0.f);

        vis_VisContextSetColor(vc, 1);
        vis_VisContextSetRefinement(vc, 1);
        x[0] = -1.5f;
        x[1] = -1.5f;
        vis_GlyphConicalFrustum(glyph, x, .1f, .2f, .4f, 0.f, 1);
        x[0] = 0.f;
        x[1] = -1.5f;
        vis_GlyphArrow2D3D(glyph, x, 1.f, .15f, .3f, 0.f, 1, VIS_ON, 1, 0, 1);
        x[0] = .5f;
        x[1] = -1.5f;
        vis_GlyphArrow2D3D(glyph, x, 1.f, .1f, .3f, 0.f, 2, VIS_ON, 1, 1, 1);

        vis_VisContextSetColor(vc, 4);
        x[0] = 1.0f;
        x[1] = -1.5f;
        x[2] = 0.f;
        vis_GlyphCircleN(glyph, x, 3);
        x[0] = 1.2f;
        x[1] = -1.5f;
        x[2] = 0.f;
        vis_GlyphCircleN(glyph, x, 5);
        x[0] = 1.4f;
        x[1] = -1.5f;
        x[2] = 0.f;
        vis_GlyphCircleN(glyph, x, 7);
        x[0] = 1.6f;
        x[1] = -1.5f;
        x[2] = 0.f;
        vis_GlyphCircleN(glyph, x, 9);

        GLWinXfmPop(glwin);
        GLWinSwap(glwin);
        sleep(1);
    }
    sleep(5);

    /* free all objects */
    vgl_DrawFunEnd(df);
    vis_VisContextEnd(vc);
    vis_ColorMapEnd(cmap);
    vis_GlyphEnd(glyph);
    GLWinEnd(glwin);
    return 0;
}

15.11. Example 7a, Draw Displacement Restraints Using Glyph

This example illustrates the use of the Glyph module to draw displacement restraints. There are many possible ways to represent structural restraints. The basic strategy is to composite glyphs to achieve a desired representation. This example uses an arrow pointing in the direction of the restraint as the basic visualization entity. A “hatch mark” is added to the arrow to distinguish the arrow from any other arrows which may be used to represent other quantities such as concentrated loads, etc. The arrow representations used in this example for translational and rotational constrains are designed to illustrate increasingly elaborate glyphs with a corresponding increase in graphics complexity.

It is assumed that the length of the restraint arrow is 1.5. This length must, in general, be determined from examining the characteristic length scale of the model with which it is being drawn. The example suggests ratios of the length to be applied to sizes assigned to the arrow head, etc. The arrow tip is located at the point of restraint and the direction is in the direction of restraint. For translational restraints a single headed arrow is used. Two different styles of arrows and hatch mark are used. The first is a planar arrow with a single hatch mark. The second is mixed arrow using a 3D head and a line tail with hatch marks in the x’ and y’ directions. For rotational restraints a double headed arrow is used. A full 3D arrow representation is used with a thin 3D disk used as a hatch mark.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

#include "glwin.h"

/*----------------------------------------------------------------------
                      Draw Displacement Restraints Using Glyph
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun* df;
    vis_VisContext* vc;
    vis_Glyph* glyph;
    GLWin* glwin;

    int i;
    Vfloat c[3], x[3], v[3];
    Vfloat l, r, h, off, hatchoff, hatchh;
    Vint head;
    Vfloat xstg[3] = {-1.5, 1.5, 0.};

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 200, 200, 400, 400);
    GLWinOrtho(glwin, -2., 2., -2., 2., -2., 2.);

    /* create drawing function object for GL */
    df = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, df);

    /* vis context and set attributes */
    vc = vis_VisContextBegin();
    vis_VisContextSetRefinement(vc, 0);
    vis_VisContextSetShade(vc, VIS_VERTEXSHADE);

    /* create glyph object and set objects */
    glyph = vis_GlyphBegin();
    vis_GlyphSetObject(glyph, VGL_DRAWFUN, df);
    vis_GlyphSetObject(glyph, VIS_VISCONTEXT, vc);

    /* draw in light blue */
    c[0] = 0.6f;
    c[1] = 0.6f;
    c[2] = 1.0f;
    vgl_DrawFunColor(df, c);

    /* orient z' direction of arrow along x axis */
    v[0] = 1.f;
    v[1] = 0.;
    v[2] = 0.;
    vis_GlyphSetOrientZ(glyph, v);
    /* arrow tip at 0.,0.,0. */
    x[0] = 0.;
    x[1] = 0.;
    x[2] = 0.;
    /* length of restraint arrow */
    l = 1.5;
    /* make radius of arrow head .125 of length */
    r = .125F * l;
    /* make height of arrow head equal to twice the radius */
    h = 2.F * r;
    /* do not offset arrow head from tip */
    off = 0.;
    /* use 1 headed arrow for displacment restraint */
    head = 1;
    /* set hatch mark offset .75 of arrow length back from tip */
    hatchoff = -.75F * l;

    /* translational restraint using planar (x',z') arrow */
    for (i = 0; i < 19; i++) {
        GLWinClear(glwin);
        vgl_DrawFunText(df, xstg, "Planar head, wireframe tail");
        GLWinXfmPush(glwin);
        GLWinRotate(glwin, -i * 10.F, 'y');
        /* draw 2D arrow with tail, filled, normal style, capped */
        vis_GlyphArrow2D(glyph, x, l, r, h, off, head, VIS_ON, VIS_ON, VIS_OFF, VIS_ON);
        /* add hatch mark in x' direction only */
        vis_GlyphTriaxis(glyph, x, h, 0., 0., hatchoff);

        GLWinXfmPop(glwin);
        GLWinSwap(glwin);
        sleep(1);
    }

    /* translational restraint using mixed arrow */
    for (i = 0; i < 19; i++) {
        GLWinClear(glwin);
        vgl_DrawFunText(df, xstg, "Tetrahedral head, wireframe tail");
        GLWinXfmPush(glwin);
        GLWinRotate(glwin, -i * 10.F, 'y');
        /* draw mixed 2D,3D arrow */
        vis_GlyphArrow2D3D(glyph, x, l, r, h, off, head, VIS_ON, VIS_ON, VIS_OFF, VIS_ON);
        /* add hatch mark in x' and y' directions */
        vis_GlyphTriaxis(glyph, x, h, h, 0., hatchoff);

        GLWinXfmPop(glwin);
        GLWinSwap(glwin);
        sleep(1);
    }

    /* use 2 headed arrow for rotation restraint */
    head = 2;
    /* thin hatch mark disk */
    hatchh = .025F * l;
    /* use higher refinement with circular glyphs */
    vis_VisContextSetRefinement(vc, 2);

    /* illustrate rotational restraint using 3D arrow */
    for (i = 0; i < 19; i++) {
        GLWinClear(glwin);
        vgl_DrawFunText(df, xstg, "Conical head, cylindrical tail");
        GLWinXfmPush(glwin);
        GLWinRotate(glwin, -i * 10.F, 'y');
        /* draw 3D arrow with tail, filled, normal style, capped */
        vis_GlyphArrow3D(glyph, x, l, r, h, off, head, VIS_ON, VIS_ON, VIS_OFF, VIS_ON);
        /* add hatch mark as thin disk */
        vis_GlyphDisk(glyph, x, r, hatchh, hatchoff, VIS_ON);

        GLWinXfmPop(glwin);
        GLWinSwap(glwin);
        sleep(1);
    }
    sleep(2);

    /* free all objects */
    vgl_DrawFunEnd(df);
    vis_VisContextEnd(vc);
    vis_GlyphEnd(glyph);
    GLWinEnd(glwin);
    return 0;
}

15.12. Example 7b, Draw Segmented Glyphs

This example illustrates the use of the Glyph module to draw segmented glyphs using the vis_GlyphSegment(), vis_GlyphSegmentRule() and vis_GlyphSegmentRev() functions. The individual segments can be either a straight line, circular arc or parabolic line. The segments may be drawn as-is in the glyph local x,y plane or ruled (extruded) or revolved about the glyph local z axis.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

#include "glwin.h"

static Vfloat rgb[7][3] = {{.2f, .2f, .2f}, {1., 0., 0.}, {0., 1., 0.}, {0., 0., 1.}, {0., 1., 1.}, {1., 0., 1.}, {1., 1., 0.}};

/*----------------------------------------------------------------------
                      Draw Segmented Glyphs
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun* df;
    vis_VisContext* vc;
    vis_ColorMap* cmap;
    vis_Glyph* glyph;
    GLWin* glwin;

    int i;
    Vfloat x[3], xy[3][2];

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 200, 200, 800, 800);
    GLWinOrtho(glwin, -4., 4., -4., 4., -4., 4.);

    /* create drawing function object for GL */
    df = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, df);

    /* vis context and set attributes */
    vc = vis_VisContextBegin();
    vis_VisContextSetColor(vc, 4);
    vis_VisContextSetRefinement(vc, 0);
    vis_VisContextSetShade(vc, VIS_VERTEXSHADE);

    /* color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetType(cmap, COLORMAP_TRUECOLOR);
    vis_ColorMapSetRGB(cmap, 7, 0, rgb);

    /* create glyph object and set objects */
    glyph = vis_GlyphBegin();
    vis_GlyphSetObject(glyph, VGL_DRAWFUN, df);
    vis_GlyphSetObject(glyph, VIS_VISCONTEXT, vc);
    vis_GlyphSetObject(glyph, VIS_COLORMAP, cmap);

    /* illustrate glyphs */
    for (i = 0; i < 30; i++) {
        GLWinClear(glwin);
        GLWinXfmPush(glwin);
        GLWinRotate(glwin, i * 12.F, 'x');
        GLWinRotate(glwin, 12., 'y');

        vis_VisContextSetColor(vc, 4);
        x[0] = -1.5;
        x[1] = 1.0;
        x[2] = 0.;
        /* line, parabola, arc */
        xy[0][0] = .4f;
        xy[0][1] = .4f;
        xy[1][0] = .4f;
        xy[1][1] = .8f;
        vis_GlyphSegment(glyph, x, GLYPH_SEG_LINE, xy);
        xy[0][0] = .4f;
        xy[0][1] = .8f;
        xy[1][0] = 0.f;
        xy[1][1] = 1.2f;
        xy[2][0] = -.4f;
        xy[2][1] = .8f;
        vis_GlyphSegment(glyph, x, GLYPH_SEG_PARAB, xy);
        xy[0][0] = -.4f;
        xy[0][1] = .8f;
        xy[1][0] = 0.f;
        xy[1][1] = .8f;
        xy[2][0] = 0.f;
        xy[2][1] = .4f;
        vis_GlyphSegment(glyph, x, GLYPH_SEG_ARC, xy);
        /* rule */
        x[0] = 0.0;
        x[1] = 1.0;
        x[2] = 0.;
        vis_VisContextSetColor(vc, 5);
        xy[0][0] = .4f;
        xy[0][1] = .4f;
        xy[1][0] = .4f;
        xy[1][1] = .8f;
        vis_GlyphSegmentRule(glyph, x, .3f, .3f, GLYPH_SEG_LINE, xy);
        vis_VisContextSetColor(vc, 3);
        xy[0][0] = .4f;
        xy[0][1] = .8f;
        xy[1][0] = 0.;
        xy[1][1] = 1.2f;
        xy[2][0] = -.4f;
        xy[2][1] = .8f;
        vis_GlyphSegmentRule(glyph, x, .5, .5, GLYPH_SEG_PARAB, xy);
        vis_VisContextSetColor(vc, 2);
        xy[0][0] = -.4f;
        xy[0][1] = .8f;
        xy[1][0] = 0.;
        xy[1][1] = .8f;
        xy[2][0] = 0.;
        xy[2][1] = .4f;
        vis_GlyphSegmentRule(glyph, x, .4f, .4f, GLYPH_SEG_ARC, xy);

        /* revolve */
        x[0] = 1.0;
        x[1] = 1.0;
        x[2] = 0.;
        vis_VisContextSetColor(vc, 5);
        xy[0][0] = .5f;
        xy[0][1] = .2f;
        xy[1][0] = .7f;
        xy[1][1] = .4f;
        vis_GlyphSegmentRev(glyph, x, 90., GLYPH_SEG_LINE, xy);
        vis_VisContextSetColor(vc, 3);
        xy[0][0] = .7f;
        xy[0][1] = .4f;
        xy[1][0] = .5f;
        xy[1][1] = .6f;
        xy[2][0] = .3f;
        xy[2][1] = .4f;
        vis_GlyphSegmentRev(glyph, x, 90., GLYPH_SEG_PARAB, xy);

        GLWinXfmPop(glwin);
        GLWinSwap(glwin);
        sleep(1);
    }
    sleep(5);

    /* free all objects */
    vgl_DrawFunEnd(df);
    vis_VisContextEnd(vc);
    vis_ColorMapEnd(cmap);
    vis_GlyphEnd(glyph);
    GLWinEnd(glwin);
    return 0;
}

15.13. Example 8, Drawing Axes

This example illustrates the use of the Axis module to generate graph axes in 3D space. A single Axis object is used to draw the axes in the x, y and z directions. As a result, the path, plane and sense must be set to the appropriate values before the axis in each direction is drawn. As an alternative, three separate Axis objects could have been created, one for each direction. The attributes could be set once for each Axis object.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

#include "glwin.h"

static Vfloat rgb[7][3] = {{.8f, .8f, .8f}, {1., 0., 0.}, {0., 1., 0.}, {0., 0., 1.}, {0., 1., 1.}, {1., 0., 1.}, {1., 1., 0.}};

/*----------------------------------------------------------------------
                      Draw Axes
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun* df;
    vis_VisContext* vc;
    vis_Levels* levels;
    vis_ColorMap* cmap;
    vis_Axis* axis;
    GLWin* glwin;

    int i;
    Vfloat x[3], path[3], plane[3];

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 200, 200, 400, 400);
    GLWinOrtho(glwin, -2., 2., -2., 2., -2., 2.);

    /* create drawing function object for GL */
    df = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, df);

    /* vis context and set attributes */
    vc = vis_VisContextBegin();
    vis_VisContextSetColor(vc, 4);
    vis_VisContextSetSize(vc, .025f);
    vis_VisContextSetLineStyle(vc, VIS_CYLINDER);
    vis_VisContextSetXYZColor(vc, 0, 0, 0);
    vis_VisContextSetFill(vc, VIS_OFF);
    vis_VisContextSetMinorColor(vc, 6);
    vis_VisContextSetMinorSize(vc, .08f);
    vis_VisContextSetFormat(vc, VIS_FFORMAT);

    /* Axis levels */
    levels = vis_LevelsBegin();

    /* color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetType(cmap, COLORMAP_TRUECOLOR);
    vis_ColorMapSetRGB(cmap, 7, 0, rgb);

    /* create axis object and set objects */
    axis = vis_AxisBegin();
    vis_AxisSetObject(axis, VGL_DRAWFUN, df);
    vis_AxisSetObject(axis, VIS_VISCONTEXT, vc);
    vis_AxisSetObject(axis, VIS_COLORMAP, cmap);
    vis_AxisSetObject(axis, VIS_LEVELS, levels);

    /* illustrate axes */
    for (i = 0; i < 30; i++) {
        GLWinClear(glwin);
        GLWinXfmPush(glwin);
        GLWinRotate(glwin, i * 1.F, 'X');
        GLWinRotate(glwin, -i * 1.F, 'Y');

        /* draw x axis */
        x[0] = -1.2f;
        x[1] = -1.2f;
        x[2] = 0.;
        vis_LevelsDef(levels, LEVELS_LINEAR, 6);
        vis_LevelsSetMinMax(levels, 0., 100.);
        vis_LevelsGenerate(levels, LEVELS_PADNONE);
        path[0] = 1.;
        path[1] = 0.;
        path[2] = 0.;
        plane[0] = 0.;
        plane[1] = 1.;
        plane[2] = 0.;
        vis_AxisSetPlane(axis, path, plane);
        vis_AxisSetParami(axis, AXIS_SENSE, VIS_OFF);
        vis_AxisPath(axis, x, 3., "X axis", "World Coordinate");
        vis_AxisPlane(axis, x, 3., 2., "", "");
        vis_AxisProjection(axis, x, 3., 2., "", "");

        /* draw y axis */
        vis_LevelsDef(levels, LEVELS_LINEAR, 4);
        vis_LevelsSetMinMax(levels, 0., 60.);
        vis_LevelsGenerate(levels, LEVELS_PADNONE);
        path[0] = 0.;
        path[1] = 1.;
        path[2] = 0.;
        plane[0] = 1.;
        plane[1] = 0.;
        plane[2] = 0.;
        vis_AxisSetPlane(axis, path, plane);
        vis_AxisSetParami(axis, AXIS_SENSE, VIS_ON);
        /* rotate labels by -90. degrees */
        vis_AxisSetParami(axis, AXIS_ROTATELABEL, AXIS_ROTATELABEL_PLUS90);
        vis_AxisPath(axis, x, 2., "Y axis", "");
        vis_AxisSetParami(axis, AXIS_ROTATELABEL, VIS_OFF);

        /* draw z axis */
        vis_LevelsDef(levels, LEVELS_LINEAR, 3);
        vis_LevelsSetMinMax(levels, 0., 1000.);
        vis_LevelsGenerate(levels, LEVELS_PADNONE);
        path[0] = 0.;
        path[1] = 0.;
        path[2] = 1.;
        plane[0] = 0.;
        plane[1] = 1.;
        plane[2] = 0.;
        vis_AxisSetPlane(axis, path, plane);
        vis_AxisSetParami(axis, AXIS_SENSE, VIS_OFF);
        vis_AxisPath(axis, x, 2., "Z axis", "");

        GLWinXfmPop(glwin);
        GLWinSwap(glwin);
        sleep(1);
    }
    sleep(5);

    /* free all objects */
    vgl_DrawFunEnd(df);
    vis_VisContextEnd(vc);
    vis_ColorMapEnd(cmap);
    vis_LevelsEnd(levels);
    vis_AxisEnd(axis);
    GLWinEnd(glwin);
    return 0;
}

15.14. Example 9, Clip Finite Element Faces to Isosurfaces

This example illustrates the use of the IsoClip object for performing isosurface clipping on the faces of finite elements. A 10 by 10 grid of quadrilateral faces is drawn in the x-y plane which is clipped by two isosurfaces. A single IsoClip object can represent several clipping isosurfaces, so only one IsoClip object need be created for the two isosurfaces. The first isosurface, (index = 0), is a constant value of the x coordinate. The second isosurface, (index = 1), is a constant value of the distance from the origin.

The outside loop changes the clipping mode. The first time through the loop, the mode ISOCLIP_ANY will clip away a face, edge or node if it is clipped by any isosurface, the second time through the loop, the mode ISOCLIP_ALL will clip away a face, edge or node only if it is clipped by all isosurfaces. The next loop alters the isosurface values so that they appear to slowly propagate, clipping away successively greater amounts of the faces. The isosurfaces are actually propagated twice. The first time the isosurfaces are defined using scalar data fields to represent the functions of the coordinates. The second time the isosurfaces are defined explicitly using coordinate clipping.

The IsoClip module contains a definition of the active clipping isosurfaces. In the first case, Note that the IsoClip object is given a pointer to a one dimensional array for each clipping isosurface using vis_IsoClipSetDataPtr(). Each of these arrays is to contain the current values of the scalar field corresponding to each isosurface for the face to be drawn with each call to vis_FaceCurv() and the nodes to be drawn with each call to vis_MarkPnt(). In the second case the first isosurface in the x coordinate is defined directly as the global x coordinate of each node, while the second isosurface can be defined as the radial coordinate of each node expressed in a cylindrical coordinate system positioned at the origin. This coordinate system is defined using a CoordSys object. The CoordSys object is set into the IsoClip for index = 1 using vis_IsoClipSetCoordSys().

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

#include "glwin.h"
#define MAG(x) sqrt(((x)[0] * (x)[0] + (x)[1] * (x)[1] + (x)[2] * (x)[2]))

/* anchor location of text string */
static Vfloat xtxt[3] = {-11., 11., 0.};
static Vfloat ctxt[3] = {1., 1., 1.};

/*----------------------------------------------------------------------
                      Clip Finite Element Faces to Isosurfaces
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun* df;
    vis_VisContext* vc;
    vis_ColorMap* cmap;
    vis_Face* face;
    vis_Mark* mark;
    vis_IsoClip* isoclip;
    vis_CoordSys* coordsys;
    GLWin* glwin;

    int i, j, k, n;
    Vfloat c[3];
    Vfloat xf[4][3];
    Vfloat val0, sf0[4], val1, sf1[4];
    Vint mode;

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 200, 200, 400, 400);
    GLWinOrtho(glwin, -12., 12., -12., 12., -12., 12.);

    /* create drawing function object for GL */
    df = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, df);

    /* vis context and set attributes */
    vc = vis_VisContextBegin();
    vis_VisContextSetColor(vc, 1);
    vis_VisContextSetMinorColor(vc, 2);
    vis_VisContextSetEdge(vc, VIS_ON);
    vis_VisContextSetFill(vc, VIS_ON);
    vis_VisContextSetMarkerType(vc, VIS_POINT4);
    vis_VisContextSetMapColor(vc, VIS_MAPCOLOR_NONE);

    /* color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetType(cmap, COLORMAP_TRUECOLOR);
    /* gray */
    c[0] = .5;
    c[1] = .5;
    c[2] = .5;
    vis_ColorMapSetRGB(cmap, 1, 1, (Vfloat(*)[3])c);
    /* white */
    c[0] = 1.0;
    c[1] = 1.0;
    c[2] = 1.0;
    vis_ColorMapSetRGB(cmap, 1, 2, (Vfloat(*)[3])c);
    /* red */
    c[0] = 1.0;
    c[1] = .0;
    c[2] = .0;
    vis_ColorMapSetRGB(cmap, 1, 3, (Vfloat(*)[3])c);

    /* isosurface clipping object */
    isoclip = vis_IsoClipBegin();

    /* create face object and set objects */
    face = vis_FaceBegin();
    vis_FaceSetObject(face, VGL_DRAWFUN, df);
    vis_FaceSetObject(face, VIS_VISCONTEXT, vc);
    vis_FaceSetObject(face, VIS_COLORMAP, cmap);
    vis_FaceSetObject(face, VIS_ISOCLIP, isoclip);

    /* create mark object and set objects */
    mark = vis_MarkBegin();
    vis_MarkSetObject(mark, VGL_DRAWFUN, df);
    vis_MarkSetObject(mark, VIS_VISCONTEXT, vc);
    vis_MarkSetObject(mark, VIS_COLORMAP, cmap);
    vis_MarkSetObject(mark, VIS_ISOCLIP, isoclip);

    /* data based clipping */
    vis_IsoClipSetDataPtr(isoclip, 0, sf0);
    vis_IsoClipSetDataPtr(isoclip, 1, sf1);

    /* first ANY mode and then ALL mode */
    for (n = 0; n < 2; n++) {
        if (n == 0) {
            mode = ISOCLIP_ANY;
        }
        else {
            mode = ISOCLIP_ALL;
        }
        vis_IsoClipSetMode(isoclip, mode);
        /* alter isosurface clipping values 20 times */
        for (i = 0; i < 20; i++) {
            GLWinClear(glwin);
            val0 = 10.F - .3333F * i;
            vis_IsoClipSetType(isoclip, 0, ISOCLIP_DATA, ISOCLIP_HITHER, val0);
            val1 = 12.F - .3333F * i;
            vis_IsoClipSetType(isoclip, 1, ISOCLIP_DATA, ISOCLIP_HITHER, val1);
            /* draw 10 by 10 grid of faces */
            for (j = 0; j < 10; j++) {
                for (k = 0; k < 10; k++) {
                    xf[0][0] = (Vfloat)j;
                    xf[0][1] = (Vfloat)k;
                    xf[0][2] = 0;
                    xf[1][0] = (Vfloat)j + 1;
                    xf[1][1] = (Vfloat)k;
                    xf[1][2] = 0;
                    xf[2][0] = (Vfloat)j + 1;
                    xf[2][1] = (Vfloat)k + 1;
                    xf[2][2] = 0;
                    xf[3][0] = (Vfloat)j;
                    xf[3][1] = (Vfloat)k + 1;
                    xf[3][2] = 0;
                    sf0[0] = xf[0][0];
                    sf0[1] = xf[1][0];
                    sf0[2] = xf[2][0];
                    sf0[3] = xf[3][0];
                    sf1[0] = (Vfloat)(MAG(xf[0]));
                    sf1[1] = (Vfloat)(MAG(xf[1]));
                    sf1[2] = (Vfloat)(MAG(xf[2]));
                    sf1[3] = (Vfloat)(MAG(xf[3]));
                    vis_VisContextSetColor(vc, 1);
                    vis_FaceCurv(face, xf, VIS_NODATA, NULL);
                    vis_VisContextSetColor(vc, 3);
                    vis_MarkPnt(mark, 4, xf);
                }
            }
            GLWinColor(glwin, ctxt);
            if (mode == ISOCLIP_ANY) {
                GLWinText(glwin, xtxt, "Data Clipping, ANY mode");
            }
            else {
                GLWinText(glwin, xtxt, "Data Clipping, ALL mode");
            }
            GLWinSwap(glwin);
            sleep(1);
        }
    }
    /* do the same thing with coordinate based clipping */
    /* create cylindrical system for radial clipping */
    /* default system at origin and aligned to global */
    coordsys = vis_CoordSysBegin();
    vis_CoordSysDef(coordsys, SYS_CYLINDRICAL);
    vis_IsoClipSetCoordSys(isoclip, 1, coordsys);

    for (n = 0; n < 2; n++) {
        if (n == 0) {
            mode = ISOCLIP_ANY;
        }
        else {
            mode = ISOCLIP_ALL;
        }
        vis_IsoClipSetMode(isoclip, mode);
        /* alter isosurface clipping values 20 times */
        for (i = 0; i < 20; i++) {
            GLWinClear(glwin);
            val0 = 10.F - .3333F * i;
            vis_IsoClipSetType(isoclip, 0, ISOCLIP_X, ISOCLIP_HITHER, val0);
            val1 = 12.F - .3333F * i;
            /* the radial coordinate is "X" */
            vis_IsoClipSetType(isoclip, 1, ISOCLIP_X, ISOCLIP_HITHER, val1);
            /* draw 10 by 10 grid of faces */
            for (j = 0; j < 10; j++) {
                for (k = 0; k < 10; k++) {
                    xf[0][0] = (Vfloat)j;
                    xf[0][1] = (Vfloat)k;
                    xf[0][2] = 0;
                    xf[1][0] = (Vfloat)j + 1;
                    xf[1][1] = (Vfloat)k;
                    xf[1][2] = 0;
                    xf[2][0] = (Vfloat)j + 1;
                    xf[2][1] = (Vfloat)k + 1;
                    xf[2][2] = 0;
                    xf[3][0] = (Vfloat)j;
                    xf[3][1] = (Vfloat)k + 1;
                    xf[3][2] = 0;
                    vis_VisContextSetColor(vc, 1);
                    vis_FaceCurv(face, xf, VIS_NODATA, NULL);
                    vis_VisContextSetColor(vc, 3);
                    vis_MarkPnt(mark, 4, xf);
                }
            }
            GLWinColor(glwin, ctxt);
            if (mode == ISOCLIP_ANY) {
                GLWinText(glwin, xtxt, "Coordinate Clipping, ANY mode");
            }
            else {
                GLWinText(glwin, xtxt, "Coordinate Clipping, ALL mode");
            }
            GLWinSwap(glwin);
            sleep(1);
        }
    }

    sleep(5);

    /* free all objects */
    vgl_DrawFunEnd(df);
    vis_VisContextEnd(vc);
    vis_ColorMapEnd(cmap);
    vis_FaceEnd(face);
    vis_MarkEnd(mark);
    vis_IsoClipEnd(isoclip);
    vis_CoordSysEnd(coordsys);
    GLWinEnd(glwin);
    return 0;
}

15.15. Example 9a, Clip Finite Elements to a Volume

This example illustrates the use of the IsoClip, DataInt and Cell objects for clipping hexahedral finite elements to a user defined volume and interpolating a scalar data field to the vertices within the clipped volume. The Cell module is used to perform the actual clipping and data interpolation, the IsoClip and DataInt modules act as attribute objects to the Cell module to define the clipping volume and the data to be interpolated. A VisContext object is also used to enable the VIS_CREATEPOLYHEDRON flag. With this flag enabled the Cell module will output polyhedral geometric primitives spanning the volume of the cell, rather than the default polygon primitives spanning the faces of the cell. Note that the Draw element of the visualization context is disabled so that only the PolygonData drawing function is called. A special user defined drawing function is constructed to capture the polyhedra output by the Cell object. This polyhedral information with interpolated nodal coordinates and data can then be used to perform various types of volume integrals.

A 10 by 10 by 10 grid of hexahedral elements to be clipped is generated. The cylindrical volume is specified by three coordinate surfaces defined in a cylindrical coordinate system represented by a single CoordSys object. The three coordinate surfaces are a radial surface at a radius of 3.5 and two axial surfaces at 2.2 and 7.8. These three surface completely enclose a cylindrical volume and are entered into a IsoClip object.

After all the hexahedral cells are traversed, the Connect object in the user defined object, tobj, will contain all generated polyhedra. The HashTable and Concat objects will contain all the scalar field data interpolated to the nodes of the polyhedra. The function print_info traverses all the polyhedra, computing the volume with the ElemChk module. Finally, an example of printing the nodal coordinates and interpolated data for the first polyhedron is shown.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

static void
print_info(vis_Connect* connect, vsy_HashTable* ht, vsy_Concat* cc);

typedef struct Tobj {
    vis_Connect* connect;
    Vint numnp;
    Vint numel;
    vsy_HashTable* hashtable;
    vsy_Concat* concat;
} Tobj;

static void
TPolygonData(Tobj* t, Vint type, Vint npts, Vfloat x[][3], Vint nrws, Vfloat d[], Vint vflag, Vfloat v[])
{
    Vint i;
    Vint ix[8];
    void* pntr;
    /* set element topology */
    t->numel += 1;
    if (npts == 4) {
        vis_ConnectSetTopology(t->connect, t->numel, VIS_SHAPETET, 0, 0, 0);
    }
    else if (npts == 5) {
        vis_ConnectSetTopology(t->connect, t->numel, VIS_SHAPEPYR, 0, 0, 0);
    }
    else if (npts == 6) {
        vis_ConnectSetTopology(t->connect, t->numel, VIS_SHAPEWED, 0, 0, 0);
    }
    else if (npts == 8) {
        vis_ConnectSetTopology(t->connect, t->numel, VIS_SHAPEHEX, 0, 0, 0);
    }
    /* set node coordinates */
    for (i = 0; i < npts; i++) {
        t->numnp += 1;
        ix[i] = t->numnp;
        vis_ConnectSetCoords(t->connect, t->numnp, x[i]);
    }
    /* set element node connectivity */
    vis_ConnectSetElemNode(t->connect, t->numel, ix);

    /* store data */
    vsy_ConcatAdd(t->concat, nrws * npts * sizeof(Vfloat), d);
    vsy_ConcatRef(t->concat, &pntr);
    vsy_HashTableInsert(t->hashtable, t->numel, pntr);
}

/*----------------------------------------------------------------------
                      Clip Finite Elements to a Volume
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun* df;
    vis_VisContext* vc;
    vis_Cell* cell;
    vis_IsoClip* isoclip;
    vis_DataInt* dataint;
    vis_CoordSys* coordsys;

    Vfloat xc[8][3], d[8];
    Vfloat xo[3], tm[3][3];
    int i, j, k, n;
    Tobj tobj;

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create draw function, with user object tobj */
    df = vgl_DrawFunBegin();
    vgl_DrawFunSetObj(df, (Vobject*)&tobj);
    vgl_DrawFunAPI(df, DRAWFUN_APIRETURN);
    vgl_DrawFunSet(df, DRAWFUN_POLYGONDATA, (Vfunc*)TPolygonData);

    tobj.connect = vis_ConnectBegin();
    tobj.numel = 0;
    tobj.numnp = 0;
    tobj.hashtable = vsy_HashTableBegin();
    tobj.concat = vsy_ConcatBegin();

    /* vis context and set attributes */
    vc = vis_VisContextBegin();
    vis_VisContextSetDraw(vc, VIS_OFF);
    vis_VisContextSetFlags(vc, VIS_CREATEPOLYHEDRON);

    /* define a cylindrical coordinate system */
    coordsys = vis_CoordSysBegin();
    vis_CoordSysDef(coordsys, SYS_CYLINDRICAL);
    xo[0] = 4.;
    xo[1] = 4.;
    xo[2] = 0.;
    tm[0][0] = 1.;
    tm[1][0] = 0.;
    tm[2][0] = 0.;
    tm[0][1] = 0.;
    tm[1][1] = 1.;
    tm[2][1] = 0.;
    tm[0][2] = 0.;
    tm[1][2] = 0.;
    tm[2][2] = 1.;
    vis_CoordSysSetOriginTriad(coordsys, xo, tm);

    /* isosurface clipping object */
    isoclip = vis_IsoClipBegin();
    vis_IsoClipSetCoordSys(isoclip, 0, coordsys);
    vis_IsoClipSetCoordSys(isoclip, 1, coordsys);
    vis_IsoClipSetCoordSys(isoclip, 2, coordsys);
    /* clip to a cylinder, radius=3.5, bottom=2.2, top=7.8 */
    vis_IsoClipSetType(isoclip, 0, ISOCLIP_X, ISOCLIP_HITHER, 3.5f);
    vis_IsoClipSetType(isoclip, 1, ISOCLIP_Z, ISOCLIP_YON, 2.2f);
    vis_IsoClipSetType(isoclip, 2, ISOCLIP_Z, ISOCLIP_HITHER, 7.8f);

    /* data interpolation object for scalar field */
    dataint = vis_DataIntBegin();
    vis_DataIntSetDataPtr(dataint, 0, 1, d);

    /* create cell object and set objects */
    cell = vis_CellBegin();
    vis_CellSetObject(cell, VGL_DRAWFUN, df);
    vis_CellSetObject(cell, VIS_VISCONTEXT, vc);
    vis_CellSetObject(cell, VIS_ISOCLIP, isoclip);
    vis_CellSetObject(cell, VIS_DATAINT, dataint);
    vis_CellSetTopology(cell, VIS_SHAPEHEX, 2, 0, 0);

    /* process cell volumes, 1000 unit cubes */
    for (k = 0; k < 10; k++) {
        for (j = 0; j < 10; j++) {
            for (i = 0; i < 10; i++) {
                xc[0][0] = (Vfloat)i;
                xc[0][1] = (Vfloat)j;
                xc[0][2] = (Vfloat)k;
                xc[1][0] = (Vfloat)i + 1;
                xc[1][1] = (Vfloat)j;
                xc[1][2] = (Vfloat)k;
                xc[2][0] = (Vfloat)i + 1;
                xc[2][1] = (Vfloat)j + 1;
                xc[2][2] = (Vfloat)k;
                xc[3][0] = (Vfloat)i;
                xc[3][1] = (Vfloat)j + 1;
                xc[3][2] = (Vfloat)k;
                xc[4][0] = (Vfloat)i;
                xc[4][1] = (Vfloat)j;
                xc[4][2] = (Vfloat)k + 1;
                xc[5][0] = (Vfloat)i + 1;
                xc[5][1] = (Vfloat)j;
                xc[5][2] = (Vfloat)k + 1;
                xc[6][0] = (Vfloat)i + 1;
                xc[6][1] = (Vfloat)j + 1;
                xc[6][2] = (Vfloat)k + 1;
                xc[7][0] = (Vfloat)i;
                xc[7][1] = (Vfloat)j + 1;
                xc[7][2] = (Vfloat)k + 1;
                /* generate a scalar data field, x + y**2 */
                for (n = 0; n < 8; n++) {
                    d[n] = xc[n][0] + xc[n][1] * xc[n][1];
                }
                vis_CellCurv(cell, xc);
            }
        }
    }
    /* print some information about the resulting polyhedra */
    print_info(tobj.connect, tobj.hashtable, tobj.concat);

    /* clean up tobj */
    vis_ConnectEnd(tobj.connect);
    vsy_HashTableEnd(tobj.hashtable);
    vsy_ConcatEnd(tobj.concat);

    /* free all objects */
    vgl_DrawFunEnd(df);
    vis_VisContextEnd(vc);
    vis_CellEnd(cell);
    vis_IsoClipEnd(isoclip);
    vis_DataIntEnd(dataint);
    vis_CoordSysEnd(coordsys);
    return 0;
}

/*----------------------------------------------------------------------
                      print volume information
----------------------------------------------------------------------*/
static void
print_info(vis_Connect* connect, vsy_HashTable* ht, vsy_Concat* cc)
{
    Vint i;
    Vint index;
    Vint numnp, numel;
    vis_ElemChk* elemchk;
    vis_GridFun* gf;
    Vfloat s[ELEMCHK_MAX];
    Vfloat volume;
    Vint nix, ix[8];
    Vfloat *d, x[8][3];

    /* write NASTRAN bulk data file of polyhedra */
    vis_ConnectWrite(connect, SYS_NASTRAN_BULKDATA, "exam9a.bdf");

    vis_ConnectNumber(connect, SYS_NODE, &numnp);
    vis_ConnectNumber(connect, SYS_ELEM, &numel);
    printf("number of nodes= %d\n", numnp);
    printf("number of elems= %d\n", numel);

    /* compute volume */
    gf = vis_GridFunBegin();
    vis_ConnectGridFun(connect, gf);
    elemchk = vis_ElemChkBegin();
    vis_ElemChkSetObject(elemchk, VIS_GRIDFUN, gf);
    vis_ElemChkSetType(elemchk, ELEMCHK_JACOBIAN_SUM, SYS_ON);
    volume = 0.;
    for (i = 1; i <= numel; i++) {
        vis_ElemChkData(elemchk, i, s);
        volume += s[ELEMCHK_JACOBIAN_SUM];
    }
    printf("volume= %f\n", volume);

    /* delete objects */
    vis_GridFunEnd(gf);
    vis_ElemChkEnd(elemchk);

    /* print data and coordinates of first polyhedron*/
    index = 1;
    vsy_HashTableLookup(ht, index, (Vobject**)&d);
    vis_ConnectElemNode(connect, index, &nix, ix);
    vis_ConnectCoords(connect, nix, ix, x);
    for (i = 0; i < nix; i++) {
        printf(" x= %f, y= %f, z= %f, d= %f\n", x[i][0], x[i][1], x[i][2], d[i]);
    }
}

15.16. Example 9b, Clip Graphics Primitives to Isosurfaces

This example is a modification of Example 9. Instead of clipping the faces of finite elements, this example clips graphics primitives using the PrmClp object. The procedure is similar to clipping faces except that the graphics primitives are sent to the PrmClp object using a drawing function interface.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "glwin.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

/* useful macro for magnitude of a vector */
#define MAG(x) sqrt(((x)[0] * (x)[0] + (x)[1] * (x)[1] + (x)[2] * (x)[2]))

/* anchor location of text string */
static Vfloat xtxt[3] = {-11., 11., 0.};
/* colors for text, polygon, polyline */
static Vfloat ctxt[3] = {1., 1., 1.};
static Vfloat cpgn[3] = {1., 0., 1.};
static Vfloat cpln[3] = {1., 1., 1.};

/*----------------------------------------------------------------------
                      Clip Graphics Primitives to Isosurfaces Using PrmClp
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun* df;
    vgl_DrawFun* dfpc;
    vis_IsoClip* isoclip;
    vis_PrmClp* prmclp;
    vis_CoordSys* coordsys;
    GLWin* glwin;

    int i, j, k;
    Vfloat xf[4][3];
    Vfloat val0, val1;
    Vfloat sf0[4], sf1[4];

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 200, 200, 400, 400);
    GLWinOrtho(glwin, -12., 12., -12., 12., -12., 12.);

    /* create drawing function object for GL */
    df = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, df);

    /* create isosurface clipping object */
    isoclip = vis_IsoClipBegin();
    vis_IsoClipSetMode(isoclip, ISOCLIP_ANY);

    /* create drawing function object for PrmClp */
    dfpc = vgl_DrawFunBegin();
    /* create primitive clipping object */
    prmclp = vis_PrmClpBegin();
    vis_PrmClpDrawFun(prmclp, dfpc);
    /* set isosurface clipping object */
    vis_PrmClpSetObject(prmclp, VIS_ISOCLIP, isoclip);
    /* set output drawing function to GLWin */
    vis_PrmClpSetObject(prmclp, VIS_ISOCLIP, isoclip);
    vis_PrmClpSetObject(prmclp, VGL_DRAWFUN, df);

    /* data based clipping */
    vis_IsoClipSetDataPtr(isoclip, 0, sf0);
    vis_IsoClipSetDataPtr(isoclip, 1, sf1);

    /* alter isosurface clipping values 20 times */
    for (i = 0; i < 20; i++) {
        GLWinClear(glwin);
        val0 = 10.F - .3333F * i;
        vis_IsoClipSetType(isoclip, 0, ISOCLIP_DATA, ISOCLIP_HITHER, val0);
        val1 = 12.F - .3333F * i;
        vis_IsoClipSetType(isoclip, 1, ISOCLIP_DATA, ISOCLIP_HITHER, val1);
        /* draw 10 by 10 grid of faces */
        for (j = 0; j < 10; j++) {
            for (k = 0; k < 10; k++) {
                xf[0][0] = (Vfloat)j;
                xf[0][1] = (Vfloat)k;
                xf[0][2] = 0;
                xf[1][0] = (Vfloat)j + 1;
                xf[1][1] = (Vfloat)k;
                xf[1][2] = 0;
                xf[2][0] = (Vfloat)j + 1;
                xf[2][1] = (Vfloat)k + 1;
                xf[2][2] = 0;
                xf[3][0] = (Vfloat)j;
                xf[3][1] = (Vfloat)k + 1;
                xf[3][2] = 0;
                sf0[0] = xf[0][0];
                sf0[1] = xf[1][0];
                sf0[2] = xf[2][0];
                sf0[3] = xf[3][0];
                sf1[0] = (Vfloat)(MAG(xf[0]));
                sf1[1] = (Vfloat)(MAG(xf[1]));
                sf1[2] = (Vfloat)(MAG(xf[2]));
                sf1[3] = (Vfloat)(MAG(xf[3]));
                GLWinColor(glwin, cpgn);
                vgl_DrawFunPolygon(dfpc, VGL_POLYGON, 4, xf, VGL_NOSHADE, NULL);
                GLWinColor(glwin, cpln);
                vgl_DrawFunPolyLine(dfpc, VGL_LINELOOP, 4, xf);
            }
        }
        GLWinColor(glwin, ctxt);
        GLWinText(glwin, xtxt, "Data Clipping");
        GLWinSwap(glwin);
        sleep(1);
    }
    /* coordinate based clipping */
    /* create cylindrical system for radial clipping */
    /* default system at origin and aligned to global */
    coordsys = vis_CoordSysBegin();
    vis_CoordSysDef(coordsys, SYS_CYLINDRICAL);
    vis_IsoClipSetCoordSys(isoclip, 1, coordsys);

    /* alter isosurface clipping values 20 times */
    for (i = 0; i < 20; i++) {
        GLWinClear(glwin);
        val0 = 10.F - .3333F * i;
        vis_IsoClipSetType(isoclip, 0, ISOCLIP_X, ISOCLIP_HITHER, val0);
        val1 = 12.F - .3333F * i;
        /* the radial coordinate is "X" */
        vis_IsoClipSetType(isoclip, 1, ISOCLIP_X, ISOCLIP_HITHER, val1);
        /* draw 10 by 10 grid of faces */
        for (j = 0; j < 10; j++) {
            for (k = 0; k < 10; k++) {
                xf[0][0] = (Vfloat)j;
                xf[0][1] = (Vfloat)k;
                xf[0][2] = 0;
                xf[1][0] = (Vfloat)j + 1;
                xf[1][1] = (Vfloat)k;
                xf[1][2] = 0;
                xf[2][0] = (Vfloat)j + 1;
                xf[2][1] = (Vfloat)k + 1;
                xf[2][2] = 0;
                xf[3][0] = (Vfloat)j;
                xf[3][1] = (Vfloat)k + 1;
                xf[3][2] = 0;
                GLWinColor(glwin, cpgn);
                vgl_DrawFunPolygon(dfpc, VGL_POLYGON, 4, xf, VGL_NOSHADE, NULL);
                GLWinColor(glwin, cpln);
                vgl_DrawFunPolyLine(dfpc, VGL_LINELOOP, 4, xf);
            }
        }
        GLWinColor(glwin, ctxt);
        GLWinText(glwin, xtxt, "Coordinate Clipping");
        GLWinSwap(glwin);
        sleep(1);
    }

    sleep(5);

    /* free all objects */
    vgl_DrawFunEnd(df);
    vgl_DrawFunEnd(dfpc);
    vis_IsoClipEnd(isoclip);
    vis_PrmClpEnd(prmclp);
    vis_CoordSysEnd(coordsys);
    GLWinEnd(glwin);
    return 0;
}

15.17. Example 10, Draw Contours on Element Faces Using Contour

This example illustrates all of the isovalue types which may be displayed on element faces using the Contour module. It also displays the effect of refinement upon the resolution of the isovalues on the element face. A simple finite element model consisting of a linear quadrilateral and triangle is used. There is a triple nested loop in the example. The outer loop is over the refinements 0,1 and 2, the next loop is over the six varieties of isovalue types, and the inner loop is over the elements. This results in 18 different displays of the isovalues.

The isovalue type VIS_ISOVALTEXTURE relies upon texture mapping to be supported in the graphics subsystem. When this isovalue type is used, the polygons sent to the graphics subsystem contain one dimensional texture coordinates which interpolate a one dimensional texture representing the color mapping to scalar field which has been defined by the ColorMap and Levels objects. The function vis_ColorMapLevelsGetColors() is designed specifically to generate the proper texture map to be used. In this example a banded texture is generated by calling this function with COLORMAP_FRINGE. A continuous tone texture may be generated by using COLORMAP_TONE. Generally it is good practice to make the texture a length of 256. If the texture is smaller, poor results may occur with large polygons. The isovalue type VIS_ISOVALTEXTURE may not yield results identical to the isovalue type VIS_ISOVALFRINGE for non triangular elements.

This example is implemented using a VglTools interface in file exam10vgl.c.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

#include "glwin.h"

void
gatherx(Vfloat x[][3], Vint npts, Vint con[], Vfloat xe[][3]);
void
gathers(Vfloat s[], Vint npts, Vint con[], Vfloat se[]);

/* Finite Element Model */
#define MAX_ELEM 2
#define MAX_NODE 5

static Vfloat x[MAX_NODE][3] = {{0., 0., 0.}, {1., 0., 0.}, {2., 0., 0.}, {0., 1., 0.}, {1., 1., 0.}};

static Vfloat s[MAX_NODE] = {1., 2., 3.5, 4., 3.};

static Vint numconn[MAX_ELEM] = {4, 3};

static Vint conn[MAX_ELEM][4] = {{1, 2, 5, 4}, {2, 3, 5, 0}};

static Vint shap[MAX_ELEM] = {VIS_SHAPEQUAD, VIS_SHAPETRI};

/* Isovalue Types */
static Vint isovaltype[6] = {VIS_ISOVALPOINT,   VIS_ISOVALLINE, VIS_ISOVALFRINGE,
                             VIS_ISOVALTEXTURE, VIS_ISOVALTONE, VIS_ISOVALGOURAUD};

static Vchar* isovalname[6] = {"VIS_ISOVALPOINT",   "VIS_ISOVALLINE", "VIS_ISOVALFRINGE",
                               "VIS_ISOVALTEXTURE", "VIS_ISOVALTONE", "VIS_ISOVALGOURAUD"};

static Vfloat xname[3] = {0., 2., 0.};

static Vfloat cname[3] = {1., 1., 1.};

static Vfloat xref[3] = {0., 2.25, 0.};

/*----------------------------------------------------------------------
                      Draw Contours on Element Faces
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun* df;
    vis_VisContext* vc;
    vis_Levels* levels;
    vis_ColorMap* cmap;
    vis_Contour* contour;
    GLWin* glwin;

    int i, j, k;
    Vint nlevels;
    Vfloat xe[4][3], se[4];
    Vfloat ctexture[256][3];
    Vchar text[33];

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 200, 200, 400, 400);
    GLWinOrtho(glwin, -1., 3., -1., 3., -2., 2.);

    /* create draw function object for GL */
    df = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, df);

    /* vis context and set attributes */
    vc = vis_VisContextBegin();

    /* levels, set twelve evenly spaced levels */
    levels = vis_LevelsBegin();
    nlevels = 12;
    vis_LevelsDef(levels, LEVELS_LINEAR, nlevels);
    vis_LevelsSetMinMax(levels, 1., 4.);
    vis_LevelsGenerate(levels, LEVELS_PADTOP);

    /* color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapRamp(cmap, nlevels, 1, COLORMAP_HUE);
    vis_ColorMapLevelsGetColors(cmap, levels, COLORMAP_FRINGE, 256, ctexture);

    /* create contour object and set objects */
    contour = vis_ContourBegin();
    vis_ContourSetObject(contour, VGL_DRAWFUN, df);
    vis_ContourSetObject(contour, VIS_VISCONTEXT, vc);
    vis_ContourSetObject(contour, VIS_LEVELS, levels);
    vis_ContourSetObject(contour, VIS_COLORMAP, cmap);

    /* loop through refinement levels */
    for (k = 0; k < 3; k++) {
        vis_VisContextSetRefinement(vc, k);
        sprintf(text, "Refinement = %d\n", k);
        /* draw contour types */
        for (i = 0; i < 6; i++) {
            GLWinClear(glwin);
            GLWinColor(glwin, cname);
            GLWinText(glwin, xref, text);
            GLWinText(glwin, xname, isovalname[i]);
            vis_VisContextSetIsoValType(vc, isovaltype[i]);
            if (isovaltype[i] == VIS_ISOVALTEXTURE) {
                GLWinTexture(glwin, 256, 1, ctexture);
            }
            for (j = 0; j < MAX_ELEM; j++) {
                vis_ContourSetTopology(contour, shap[j], 2, 0);
                gatherx(x, numconn[j], conn[j], xe);
                gathers(s, numconn[j], conn[j], se);
                vis_ContourCurv(contour, se, xe, VIS_NODATA, NULL);
            }
            if (isovaltype[i] == VIS_ISOVALTEXTURE) {
                GLWinTexture(glwin, 0, 0, NULL);
            }
            GLWinSwap(glwin);
            sleep(2);
        }
    }
    sleep(5);

    /* free all objects */
    vgl_DrawFunEnd(df);
    vis_VisContextEnd(vc);
    vis_LevelsEnd(levels);
    vis_ColorMapEnd(cmap);
    vis_ContourEnd(contour);
    GLWinEnd(glwin);
    return 0;
}

/*----------------------------------------------------------------------
                      Utility functions to gather element vectors and scalars
----------------------------------------------------------------------*/
void
gatherx(Vfloat xArg[][3], Vint npts, Vint con[], Vfloat xe[][3])
{
    int i, j;

    for (i = 0; i < npts; i++) {
        for (j = 0; j < 3; j++) {
            xe[i][j] = xArg[con[i] - 1][j];
        }
    }
}

void
gathers(Vfloat sArg[], Vint npts, Vint con[], Vfloat se[])
{
    int i;

    for (i = 0; i < npts; i++) {
        se[i] = sArg[con[i] - 1];
    }
}

15.18. Example 10a, Draw Isosurfaces in Elements Using Threshold

This example illustrates using the Threshold to draw isosurfaces in elements. The overall methodology is similar to drawing contours in Example 10, except that the Threshold module is used instead of the Contour module. The isovalue type VIS_ISOVALSURFACE is the most important isovalue type. The isovalue type VIS_ISOVALLINE draws lines around the polygons forming the isosurface.

#include "vis/vis.h"
#include "glwin.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

void
gatherx(Vfloat x[][3], Vint npts, Vint con[], Vfloat xe[][3]);
void
gathers(Vfloat s[], Vint npts, Vint con[], Vfloat se[]);

/* Finite Element Model */
#define MAX_ELEM 2
#define MAX_NODE 10

static Vfloat x[MAX_NODE][3] = {{0., 0., 0.}, {1., 0., 0.}, {2., 0., 0.}, {0., 1., 0.}, {1., 1., 0.},
                                {0., 0., 1.}, {1., 0., 1.}, {2., 0., 1.}, {0., 1., 1.}, {1., 1., 1.}};

static Vfloat s[MAX_NODE] = {1., 2., 3.5f, 4., 3., 1.2f, 2.3f, 3.8f, 4.4f, 3.5f};

static Vint numconn[MAX_ELEM] = {8, 6};

static Vint conn[MAX_ELEM][8] = {{1, 2, 5, 4, 6, 7, 10, 9}, {2, 3, 5, 7, 8, 10, 0, 0}};

static Vint shap[MAX_ELEM] = {VIS_SHAPEHEX, VIS_SHAPEWED};

/* Isovalue Types */
static Vint isovaltype[2] = {VIS_ISOVALSURFACE, VIS_ISOVALLINE};

static Vchar* isovalname[2] = {"VIS_ISOVALSURFACE", "VIS_ISOVALLINE"};

static Vfloat xname[3] = {0., 2., 0.};

static Vfloat cname[3] = {1., 1., 1.};

/*----------------------------------------------------------------------
                      Draw Isosurfaces in Elements
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun* df;
    vis_VisContext* vc;
    vis_Levels* levels;
    vis_ColorMap* cmap;
    vis_Threshold* threshold;
    GLWin* glwin;

    int i, j, k;
    Vint nlevels;
    Vfloat xe[8][3], se[8];

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 200, 200, 400, 400);
    GLWinOrtho(glwin, -1., 3., -1., 3., -2., 2.);

    /* create draw function object for GL */
    df = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, df);

    /* vis context and set attributes */
    vc = vis_VisContextBegin();

    /* levels, set twelve evenly spaced levels */
    levels = vis_LevelsBegin();
    nlevels = 12;
    vis_LevelsDef(levels, LEVELS_LINEAR, nlevels);
    vis_LevelsSetMinMax(levels, 1., 4.);
    vis_LevelsGenerate(levels, LEVELS_PADTOP);

    /* color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapRamp(cmap, nlevels, 1, COLORMAP_HUE);

    /* create threshold object and set objects */
    threshold = vis_ThresholdBegin();
    vis_ThresholdSetObject(threshold, VGL_DRAWFUN, df);
    vis_ThresholdSetObject(threshold, VIS_VISCONTEXT, vc);
    vis_ThresholdSetObject(threshold, VIS_LEVELS, levels);
    vis_ThresholdSetObject(threshold, VIS_COLORMAP, cmap);

    /* draw threshold types */
    for (i = 0; i < 2; i++) {
        vis_VisContextSetIsoValType(vc, isovaltype[i]);
        for (k = 0; k < 10; k++) {
            GLWinClear(glwin);
            GLWinXfmPush(glwin);
            GLWinRotate(glwin, k * 12.F, 'y');
            GLWinColor(glwin, cname);
            GLWinText(glwin, xname, isovalname[i]);
            for (j = 0; j < MAX_ELEM; j++) {
                vis_ThresholdSetTopology(threshold, shap[j], 2, 0, 0);
                gatherx(x, numconn[j], conn[j], xe);
                gathers(s, numconn[j], conn[j], se);
                vis_ThresholdCurv(threshold, se, xe, VIS_NODATA, NULL);
            }
            GLWinXfmPop(glwin);
            GLWinSwap(glwin);
            sleep(1);
        }
    }
    sleep(5);

    /* free all objects */
    vgl_DrawFunEnd(df);
    vis_VisContextEnd(vc);
    vis_LevelsEnd(levels);
    vis_ColorMapEnd(cmap);
    vis_ThresholdEnd(threshold);
    GLWinEnd(glwin);
    return 0;
}

/*----------------------------------------------------------------------
                      Utility functions to gather element vectors and scalars
----------------------------------------------------------------------*/
void
gatherx(Vfloat xArg[][3], Vint npts, Vint con[], Vfloat xe[][3])
{
    int i, j;

    for (i = 0; i < npts; i++) {
        for (j = 0; j < 3; j++) {
            xe[i][j] = xArg[con[i] - 1][j];
        }
    }
}

void
gathers(Vfloat sArg[], Vint npts, Vint con[], Vfloat se[])
{
    int i;

    for (i = 0; i < npts; i++) {
        se[i] = sArg[con[i] - 1];
    }
}

15.19. Example 10b, Draw Mesh Section Using Contour and Threshold

This example illustrates using Contour and Threshold to draw a section cut through a mesh. The Threshold module is used to draw the intersection of the cut with the element volume, the Contour module is used to draw the intersection of the cut with the element faces. The Levels object is used to define a single isovalue which is the coordinate location of the section cut, in this case the value of .5 along the z coordinate. The volume cuts are drawn in white and the face cuts in red.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

#include "glwin.h"

void
gather(Vfloat x[][3], Vint npts, Vint con[], Vfloat xe[][3], Vfloat se[]);

/* Finite Element Model */
#define MAX_ELEM 2
#define MAX_NODE 10

/* node coordinates */
static Vfloat x[MAX_NODE][3] = {{0., 0., 0.}, {1., 0., 0.}, {2., 0., 0.}, {0., 1., 0.}, {1., 1., 0.},
                                {0., 0., 1.}, {1., 0., 1.}, {2., 0., 1.}, {0., 1., 1.}, {1., 1., 1.}};

/* element connectivity */
static Vint numconn[MAX_ELEM] = {8, 6};
static Vint conn[MAX_ELEM][8] = {{1, 2, 5, 4, 6, 7, 10, 9}, {2, 3, 5, 7, 8, 10, 0, 0}};
static Vint shap[MAX_ELEM] = {VIS_SHAPEHEX, VIS_SHAPEWED};

/* face data */
static Vint numface[MAX_ELEM] = {6, 5};
static Vint numconnface[MAX_ELEM][6] = {{4, 4, 4, 4, 4, 4}, {3, 3, 4, 4, 4, 0}};
/* face connectivity relative to parent element */
static Vint indxface[MAX_ELEM][6][4] = {{{1, 4, 3, 2}, {5, 6, 7, 8}, {1, 2, 6, 5}, {4, 8, 7, 3}, {1, 5, 8, 4}, {2, 3, 7, 6}},

                                        {{1, 3, 2, 0}, {4, 5, 6, 0}, {1, 2, 5, 4}, {1, 4, 6, 3}, {2, 3, 6, 5}, {0, 0, 0, 0}}};

/* colors */
static Vfloat rgb[2][3] = {{1., 1., 1.}, {1., 0., 0.}};

/*----------------------------------------------------------------------
                      Draw Mesh Section Using Contour and Threshold
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun* df;
    vis_VisContext* vc;
    vis_Levels* levels;
    vis_ColorMap* cmap;
    vis_Contour* contour;
    vis_Threshold* threshold;
    GLWin* glwin;

    int i, j, k, n;
    Vint nlevels;
    Vint nfc, ifx[4];
    Vfloat xe[8][3], se[8];

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 200, 200, 400, 400);
    GLWinOrtho(glwin, -1., 3., -1., 3., -2., 2.);

    /* create draw function object for GL */
    df = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, df);

    /* vis context and set attributes */
    vc = vis_VisContextBegin();
    vis_VisContextSetMapColor(vc, VIS_MAPCOLOR_NONE);

    /* levels, set twelve evenly spaced levels */
    levels = vis_LevelsBegin();
    nlevels = 1;
    vis_LevelsDef(levels, LEVELS_LINEAR, nlevels);
    vis_LevelsSetValue(levels, 1, .5);

    /* color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetRGB(cmap, 2, 1, rgb);

    /* create contour object and set objects */
    contour = vis_ContourBegin();
    vis_ContourSetObject(contour, VGL_DRAWFUN, df);
    vis_ContourSetObject(contour, VIS_VISCONTEXT, vc);
    vis_ContourSetObject(contour, VIS_LEVELS, levels);
    vis_ContourSetObject(contour, VIS_COLORMAP, cmap);

    /* create threshold object and set objects */
    threshold = vis_ThresholdBegin();
    vis_ThresholdSetObject(threshold, VGL_DRAWFUN, df);
    vis_ThresholdSetObject(threshold, VIS_VISCONTEXT, vc);
    vis_ThresholdSetObject(threshold, VIS_LEVELS, levels);
    vis_ThresholdSetObject(threshold, VIS_COLORMAP, cmap);

    /* draw mesh section */
    for (k = 0; k < 10; k++) {
        GLWinClear(glwin);
        GLWinXfmPush(glwin);
        GLWinRotate(glwin, k * 12.F, 'y');
        for (j = 0; j < MAX_ELEM; j++) {
            /* use threshold to draw cut through element in white */
            vis_VisContextSetIsoValType(vc, VIS_ISOVALSURFACE);
            vis_VisContextSetColor(vc, 1);
            vis_ThresholdSetTopology(threshold, shap[j], 2, 0, 0);
            gather(x, numconn[j], conn[j], xe, se);
            vis_ThresholdCurv(threshold, se, xe, VIS_NODATA, NULL);
            /* use contour to draw cut through element faces in red */
            vis_VisContextSetIsoValType(vc, VIS_ISOVALLINE);
            vis_VisContextSetColor(vc, 2);
            vis_VisContextSetLineWidth(vc, 2);
            /* loop through faces and get face nodes */
            for (i = 0; i < numface[j]; i++) {
                nfc = numconnface[j][i];
                for (n = 0; n < nfc; n++) {
                    ifx[n] = conn[j][indxface[j][i][n] - 1];
                }
                if (nfc == 3) {
                    vis_ContourSetTopology(contour, SYS_SHAPETRI, 2, 0);
                }
                else {
                    vis_ContourSetTopology(contour, SYS_SHAPEQUAD, 2, 0);
                }
                gather(x, nfc, ifx, xe, se);
                vis_ContourCurv(contour, se, xe, VIS_NODATA, NULL);
            }
        }
        GLWinXfmPop(glwin);
        GLWinSwap(glwin);
        sleep(1);
    }
    sleep(5);

    /* free all objects */
    vgl_DrawFunEnd(df);
    vis_VisContextEnd(vc);
    vis_LevelsEnd(levels);
    vis_ColorMapEnd(cmap);
    vis_ContourEnd(contour);
    vis_ThresholdEnd(threshold);
    GLWinEnd(glwin);
    return 0;
}

/*----------------------------------------------------------------------
                      Utility function to gather element data
----------------------------------------------------------------------*/
void
gather(Vfloat xArg[][3], Vint npts, Vint con[], Vfloat xe[][3], Vfloat se[])
{
    int i, j;

    for (i = 0; i < npts; i++) {
        for (j = 0; j < 3; j++) {
            xe[i][j] = xArg[con[i] - 1][j];
        }
        /* return z coordinate as scalar */
        se[i] = xArg[con[i] - 1][2];
    }
}

15.20. Example 10c, Draw Contour Line Labels Using IsoLabel

This example illustrates using IsoLabel in conjunction with Contour to draw labels on contour lines. The IsoLabel object is designed to capture contour line segment information from the Contour object and use it to generate appropriate contour line labelling using various user-specified options.

The Contour object is configured for normal contour line generation with the addition of a call to vis_ContourSetParami() to specify that contour line segment information is meant to be set in the IsoLabel object which has been installed in Contour using vis_ContourSetObject().

Contours are generated on square grid in function generate_contour. The drawing function output is to a VglTools DList object and IsoLabel will accumulate all the contour line segment data and geometry information. The function vis_IsoLabelReset() is called to clear any previous contour line segments cached in IsoLabel.

When the contour lines are rendered in function draw_scene, the DList is traversed to draw the contour lines and the function vis_IsoLabelDraw() is called to generate contour line labels. The drawing function output from vis_IsoLabel should, in general, be immediately drawn if any graphics view dependent labeling is performed.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

static Vfloat rgb[12][3] = {{0., 0., 1.},     {0., 0.2f, 0.8f}, {0., 0.4f, 0.6f}, {0., 0.6f, 0.4f},
                            {0., 0.8f, 0.2f}, {0., 1.f, 0.},    {0.2f, 0.8f, 0.}, {0.4f, 0.6f, 0.},
                            {0.6f, 0.4f, 0.}, {0.8f, 0.2f, 0.}, {1., 0., 0.},     {1., 1., 1.}};
static Vint nlevels = 10;
static Vint ndiv = 10;
static Vfloat white[3] = {1., 1., 1.};

static void
draw_scene(vgl_DrawFun* df, vgl_DList* dlist, vis_IsoLabel* isolabel, vis_VisContext* vc, vgl_RasFont* rasfont, Vint sizetype,
           Vfloat size, Vint textplane, Vint mapcolor, Vchar title[])
{
    Vint parami[4];
    Vfloat paramf[16], xtitle[3];

    /* draw title with default screen oriented font */
    vgl_DrawFunRasFontSelect(df, 0);
    xtitle[0] = -2.9f;
    xtitle[1] = 2.7f;
    xtitle[2] = 0.;
    vgl_DrawFunColor(df, white);
    vgl_DrawFunText(df, xtitle, title);

    /* draw contour lines */
    vgl_DListCall(dlist);

    /* pass screen parameters to VisContext */
    vgl_DrawFunGetFloat(df, VGL_PROJECTIONMATRIX, paramf);
    vis_VisContextSetProjMatrix(vc, (Vfloat(*)[4])paramf);
    vgl_DrawFunGetFloat(df, VGL_MODELVIEWMATRIX, paramf);
    vis_VisContextSetXfmMatrix(vc, (Vfloat(*)[4])paramf);
    vgl_DrawFunGetInteger(df, VGL_VIEWPORT, parami);
    vis_VisContextSetViewport(vc, parami[0], parami[1], parami[2], parami[3]);

    /* set IsoLabel paramters */
    /* turn on user labels when doing world sizing */
    vis_VisContextSetSizeType(vc, sizetype);
    if (sizetype == VIS_SIZEDEVICE) {
        vis_VisContextSetDeviceSize(vc, (Vint)size);
    }
    else {
        vis_VisContextSetSize(vc, size);
        vis_IsoLabelSetParami(isolabel, ISOLABEL_LABELUSELEVELS, SYS_ON);
    }
    /* set color mapping mode */
    vis_VisContextSetMapColor(vc, mapcolor);

    /* set RasFont text plane mode */
    vgl_RasFontSetParami(rasfont, RASFONT_TEXTPLANE, textplane);
    /* OpenGLDev must reconfigure changed RasFont */
    vgl_DrawFunRasFontDefine(df, 1, rasfont);
    vgl_DrawFunRasFontSelect(df, 1);
    vis_IsoLabelSetParami(isolabel, ISOLABEL_TEXTPLANE, textplane);

    /* draw labels */
    vis_IsoLabelDraw(isolabel);
}

static void
generate_contour(vis_Contour* contour)
{
    Vint i, j, n;
    Vfloat x[4][3], s[4];

    /* set all Z coordinates to zero */
    x[0][2] = x[1][2] = x[2][2] = x[3][2] = 0.;
    /* use ContourCurv to draw lines */
    vis_ContourSetTopology(contour, SYS_SHAPEQUAD, 0, 0);
    for (i = 0; i < ndiv; ++i) {
        /* set x coordinates */
        x[0][0] = -1.8F + i * 3.6F / ndiv;
        x[1][0] = -1.8F + (i + 1) * 3.6F / ndiv;
        x[2][0] = x[1][0];
        x[3][0] = x[0][0];
        for (j = 0; j < ndiv; ++j) {
            /* set y coordinates */
            x[0][1] = -1.8F + j * 3.6F / ndiv;
            x[1][1] = x[0][1];
            x[2][1] = -1.8F + (j + 1) * 3.6F / ndiv;
            x[3][1] = x[2][1];

            /* compute distance from center as field to display */
            for (n = 0; n < 4; ++n) {
                s[n] = (Vfloat)sqrt(x[n][0] * x[n][0] + x[n][1] * x[n][1]);
            }
            vis_ContourCurv(contour, s, x, VIS_NODATA, NULL);
        }
    }
}

/*----------------------------------------------------------------------
                      Draw Contour Line Labels Using IsoLabel
----------------------------------------------------------------------*/
int
main()
{
#ifdef VKI_WIND_X11
    Display* display;
    int screen;
#endif
    Vint i;
    Vfloat sizepix;
    Vchar label[16];
    vgl_DrawFun *dfGL, *dfDL;
    vis_VisContext* vc;
    vis_ColorMap* cmap;
    vis_IsoLabel* isolabel;
    vis_Contour* contour;
    vis_Levels* levels;
    vgl_OpenGLDev* ogldev;
    vgl_RasFont* rasfont;
    vgl_DList* dlist;

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

#ifdef VKI_WIND_X11
    /* open X display */
    display = XOpenDisplay(0);
    screen = DefaultScreen(display);
    vgl_OpenGLDevConnectX(display, screen);
#endif
#ifdef VKI_WIND_WIN32
    vgl_OpenGLDevConnectWIN();
#endif
    /* create GL device */
    ogldev = vgl_OpenGLDevBegin();

    /* create draw function object for GL */
    dfGL = vgl_DrawFunBegin();
    vgl_OpenGLDevDrawFun(ogldev, dfGL);

    vgl_DrawFunPositionWindow(dfGL, 200, 200, 800, 800);
    vgl_DrawFunOpenWindow(dfGL, "Example 10cvgl");
    vgl_DrawFunProjOrtho(dfGL, -3., 3., -3., 3., -1., 1.);
    /*
     * IsoLabel always uses VGL_BOTTOM, but it must
     * know what the VGL_TEXTANCHORMODE has been set to
     * so it can compensate for it
     */
    vgl_DrawFunSetMode(dfGL, VGL_TEXTANCHORMODE, VGL_BOTTOMLEFT);

    /* create draw function object for DList */
    dlist = vgl_DListBegin();
    dfDL = vgl_DrawFunBegin();
    vgl_DListDrawFun(dlist, dfDL);
    vgl_DListSetObject(dlist, VGL_DRAWFUN, (Vobject*)dfGL);

    /* create objects */
    vc = vis_VisContextBegin();
    cmap = vis_ColorMapBegin();
    levels = vis_LevelsBegin();
    isolabel = vis_IsoLabelBegin();
    contour = vis_ContourBegin();
    rasfont = vgl_RasFontBegin();

    /* configure ColorMap */
    vis_ColorMapSetType(cmap, COLORMAP_TRUECOLOR);
    vis_ColorMapSetRGB(cmap, 12, 0, rgb);

    /* configure Levels */
    vis_LevelsDef(levels, LEVELS_LINEAR, nlevels);
    vis_LevelsSetMinMax(levels, 0., 3.);
    vis_LevelsGenerate(levels, LEVELS_PADENDS);
    /* user defined labels at levels */
    for (i = 1; i <= nlevels; i++) {
        sprintf(label, "level %d", i);
        vis_LevelsSetLabel(levels, i, label);
    }
    /* configure Contour */
    vis_ContourSetObject(contour, VGL_DRAWFUN, dfDL);
    vis_ContourSetObject(contour, VIS_ISOLABEL, isolabel);
    vis_ContourSetObject(contour, VIS_VISCONTEXT, vc);
    vis_ContourSetObject(contour, VIS_COLORMAP, cmap);
    vis_ContourSetObject(contour, VIS_LEVELS, levels);
    /* tell Contour to generate data for IsoLabel */
    vis_ContourSetParami(contour, CONTOUR_ISOVALDATA, SYS_ON);

    /* configure IsoLabel */
    vis_IsoLabelSetObject(isolabel, VIS_VISCONTEXT, vc);
    vis_IsoLabelSetObject(isolabel, VIS_COLORMAP, cmap);
    vis_IsoLabelSetObject(isolabel, VIS_LEVELS, levels);
    vis_IsoLabelSetObject(isolabel, VGL_DRAWFUN, dfGL);

    vis_IsoLabelSetParami(isolabel, ISOLABEL_TEXTPLANE, SYS_ON);

    /* add labels to every other level */
    vis_IsoLabelSetParami(isolabel, ISOLABEL_LINEFREQUENCY, 2);

    /* use numeric values, not pre-defined string labels */
    vis_IsoLabelSetParami(isolabel, ISOLABEL_LABELUSELEVELS, SYS_OFF);

    /* tolerance to merge lines from Contour */
    vis_VisContextSetDistTol(vc, 0.01f);

    /* segment curvature tolerance to skip labeling */
    vis_IsoLabelSetParamf(isolabel, ISOLABEL_CURVFRAC, 0.05f);

    /* flag to not allow overlap of labels */
    vis_IsoLabelSetParami(isolabel, ISOLABEL_OVERLAP, SYS_OFF);

    /* configure RasFont */
    vgl_RasFontLoad(rasfont, RASFONT_QUALITY9X13);
    vgl_RasFontSetParami(rasfont, RASFONT_DEVICESIZE, SYS_ON);
    vgl_DrawFunRasFontDefine(dfGL, 1, rasfont);
    vgl_DrawFunRasFontSelect(dfGL, 1);

    /* configure VisContext */
    /* white constant color */
    vis_VisContextSetColor(vc, 11);
    /* draw dot where label is positioned */
    vis_VisContextSetSpot(vc, SYS_ON);
    vis_VisContextSetPointSize(vc, 4);

    /* set TEXTANCHORMODE as used by DrawFun */
    vis_VisContextSetPosition(vc, VGL_BOTTOMLEFT);

    /* specify floating point format for label */
    vis_VisContextSetFormat(vc, VIS_FMFORMAT);

    /* space labels based on device (pixels) distance */
    vis_VisContextSetSizeType(vc, VIS_SIZEDEVICE);

    /* space labels at approximately 200 pixels on lines */
    vis_VisContextSetDeviceSize(vc, 200);

    /* offset label 3 pixels away from lines */
    vis_VisContextSetDeviceOffset(vc, 0, 3);

    /* always orient labels so they read left to right */
    vis_VisContextSetFlags(vc, VIS_BACKPLANEFLIP);

    /* specify raster font character sizes */
    vis_VisContextSetTextBox(vc, 9, 13);

    /* for Contour object, generate lines */
    vis_VisContextSetIsoValType(vc, VIS_ISOVALLINE);
    vis_VisContextSetMapColor(vc, VIS_MAPCOLOR_SMOOTH);

    /* generate contour */
    vis_IsoLabelReset(isolabel);
    generate_contour(contour);

    /* draw */
    /* vary the device size */
    for (i = 1; i <= 5; i++) {
        vgl_DrawFunClear(dfGL);
        sizepix = i * 20.F;
        draw_scene(dfGL, dlist, isolabel, vc, rasfont, VIS_SIZEDEVICE, sizepix, SYS_ON, VIS_MAPCOLOR_SMOOTH,
                   "SIZE=DEVICE, TEXTPLANE=SYS_ON, MAPCOLOR=SMOOTH");
        vgl_DrawFunSwap(dfGL);
        vgl_DrawFunDelay(dfGL, 2.);
    }
    /* do not output oriented labels */
    vgl_DrawFunClear(dfGL);
    draw_scene(dfGL, dlist, isolabel, vc, rasfont, VIS_SIZEDEVICE, 200., SYS_OFF, VIS_MAPCOLOR_SMOOTH,
               "SIZE=DEVICE, TEXTPLANE=SYS_OFF, MAPCOLOR=SMOOTH");
    vgl_DrawFunSwap(dfGL);
    vgl_DrawFunDelay(dfGL, 5.);
    /* constant color, white, labels */
    vgl_DrawFunClear(dfGL);
    draw_scene(dfGL, dlist, isolabel, vc, rasfont, VIS_SIZEDEVICE, 200., SYS_OFF, VIS_MAPCOLOR_NONE,
               "SIZE=DEVICE, TEXTPLANE=SYS_OFF, MAPCOLOR=NONE");
    vgl_DrawFunSwap(dfGL);
    vgl_DrawFunDelay(dfGL, 5.);
    /* world coordinate spacing of oriented labels */
    vgl_DrawFunClear(dfGL);
    draw_scene(dfGL, dlist, isolabel, vc, rasfont, VIS_SIZEWORLD, 0.5, SYS_ON, VIS_MAPCOLOR_SMOOTH,
               "SIZE=WORLD, TEXTPLANE=SYS_ON, MAPCOLOR=SMOOTH");
    vgl_DrawFunSwap(dfGL);
    vgl_DrawFunDelay(dfGL, 5.);

    /* close window */
    vgl_DrawFunCloseWindow(dfGL);
    /* disconnect */
    vgl_OpenGLDevDisconnect();
#ifdef VKI_WIND_X11
    XCloseDisplay(display);
#endif
    /* free all objects */
    vgl_RasFontEnd(rasfont);
    vis_ContourEnd(contour);
    vis_IsoLabelEnd(isolabel);
    vis_LevelsEnd(levels);
    vis_ColorMapEnd(cmap);
    vis_VisContextEnd(vc);
    vgl_DrawFunEnd(dfGL);
    vgl_DrawFunEnd(dfDL);
    vgl_DListEnd(dlist);
    vgl_OpenGLDevEnd(ogldev);
    return 0;
}

15.21. Example 11, Display Scalar, Vector and Tensor Markers

This example illustrates using the Mark module to draw scalar, vector and tensor markers. Three samples of each marker type are drawn together and slowly rotated to display their three dimensional character. A single Mark object is instanced to perform the drawing. Three VisContext objects are instanced, each represents the visualization context for the scalar, vector and tensor marker types respectively. The Mark object accepts independent VisContext objects as attributes to control the drawing of scalar, vector and tensor marker types separately. For each marker type, three variations of the marker type are drawn simultaneously, side by side. The variations are meant to illustrate a reduction in marker complexity from left to right on the screen.

The scalar marker types display variations in marker type and color mapping using the scalar VisContext object. The vector markers display variations in vector type, color mapping and size mapping. Component vectors are drawn first, then resultants. Tensor markers are a composite of vectors and a tensorbox type. Therefore the display of tensor markers can be changed by altering both the vector and tensor VisContext attribute objects.

Note that the vis_MarkTensorCompute() function is used to annotate the ends of the vectors in the tensor marker with component or principal values. Component tensors are drawn first then the same tensors are drawn in their principal directions and maximum shear directions.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

#include "glwin.h"

static Vfloat xpt[3][3] = {{-1., 0., 0.}, {0., 0., 0.}, {1., 0., 0.}};
static Vfloat sca = {-.6f};
static Vfloat vec[3] = {.3f, -.6f, 1.};
static Vfloat ten[6] = {.3f, -.6f, 1., .6f, .2f, -.4f};
static Vfloat xtex[3] = {-1., 1.5f, 0.};
static Vfloat ctex[3] = {1., 1., 1.};

static Vfloat rgb[7][3] = {{.5f, .5f, .5f}, {1., 0., 0.}, {0., 1., 0.}, {0., 0., 1.}, {0., 1., 1.}, {1., 0., 1.}, {1., 1., 0.}};

/*----------------------------------------------------------------------
                      Display a Scalar, Vector and Tensor in 3 Ways
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun* df;
    vis_VisContext *vcsca, *vcvec, *vcten;
    vis_Levels* levels;
    vis_ColorMap* cmap;
    vis_Mark* mark;
    GLWin* glwin;

    int i, j, k;
    Vint nlevels;
    Vfloat van[6], xan[6][2][3];
    Vchar stg[16];

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 200, 200, 400, 400);
    GLWinOrtho(glwin, -2., 2., -2., 2., -2., 2.);

    /* create draw function object for GL */
    df = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, df);

    /* scalar viscontext and set attributes */
    vcsca = vis_VisContextBegin();
    vis_VisContextSetColor(vcsca, 4);
    vis_VisContextSetRefinement(vcsca, 2);

    /* vector viscontext and set attributes */
    vcvec = vis_VisContextBegin();
    vis_VisContextSetFlags(vcvec, VIS_VECTORTAIL | VIS_VECTORTAILREGISTER);
    vis_VisContextSetMapSize(vcvec, VIS_ON);
    vis_VisContextSetXYZColor(vcvec, 4, 5, 6);

    /* tensor viscontext and set attributes */
    vcten = vis_VisContextBegin();
    vis_VisContextSetFlags(vcten, VIS_TENSORBOX | VIS_TENSORDIRECT | VIS_TENSORSHEAR);
    vis_VisContextSetMapSize(vcten, VIS_ON);
    vis_VisContextSetXYZColor(vcten, 4, 5, 6);
    vis_VisContextSetRefinement(vcten, 1);

    /* levels, set three evenly spaced levels */
    levels = vis_LevelsBegin();
    nlevels = 6;
    vis_LevelsDef(levels, LEVELS_LINEAR, nlevels);
    vis_LevelsSetMinMax(levels, -1., 1.);
    vis_LevelsGenerate(levels, LEVELS_PADNONE);

    /* color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetType(cmap, COLORMAP_TRUECOLOR);
    vis_ColorMapSetRGB(cmap, 7, 0, rgb);

    /* create mark object and set objects */
    mark = vis_MarkBegin();
    vis_MarkSetObject(mark, VGL_DRAWFUN, df);
    vis_MarkSetObject(mark, VIS_VISCONTEXT_SCALAR, vcsca);
    vis_MarkSetObject(mark, VIS_VISCONTEXT_VECTOR, vcvec);
    vis_MarkSetObject(mark, VIS_VISCONTEXT_TENSOR, vcten);
    vis_MarkSetObject(mark, VIS_LEVELS, levels);
    vis_MarkSetObject(mark, VIS_COLORMAP, cmap);

    /* draw scalars */
    for (i = 0; i < 8; i++) {
        GLWinClear(glwin);
        GLWinColor(glwin, ctex);
        GLWinText(glwin, xtex, "Scalar");
        GLWinXfmPush(glwin);
        GLWinRotate(glwin, i * 8.F, 'x');
        GLWinRotate(glwin, i * 4.F, 'y');

        /* 3D spherical type scalar, mapped to color */
        vis_VisContextSetMarkerType(vcsca, VIS_SPHERE);
        vis_VisContextSetMapColor(vcsca, VIS_ON);
        vis_MarkScalar(mark, 1, &sca, (Vfloat(*)[3])xpt[0]);

        /* 2D line type scalar, not mapped to color */
        vis_VisContextSetMarkerType(vcsca, VIS_HOURGLASS);
        vis_VisContextSetMapColor(vcsca, VIS_OFF);
        vis_MarkScalar(mark, 1, &sca, (Vfloat(*)[3])xpt[1]);

        /* 2D point type scalar, mapped to color */
        vis_VisContextSetMarkerType(vcsca, VIS_POINT4);
        vis_VisContextSetMapColor(vcsca, VIS_ON);
        vis_MarkScalar(mark, 1, &sca, (Vfloat(*)[3])xpt[2]);

        GLWinXfmPop(glwin);
        GLWinSwap(glwin);
        sleep(1);
    }
    sleep(2);

    /* draw vectors */
    for (j = 0; j < 2; j++) {
        for (i = 0; i < 8; i++) {
            GLWinClear(glwin);
            GLWinColor(glwin, ctex);
            if (j) {
                vis_VisContextSetComponent(vcvec, VIS_COMPONENT_PRINCIPAL);
                GLWinText(glwin, xtex, "Vector Resultants");
            }
            else {
                vis_VisContextSetComponent(vcvec, VIS_COMPONENT_BASIC);
                GLWinText(glwin, xtex, "Vector Components");
            }
            GLWinXfmPush(glwin);
            GLWinRotate(glwin, i * 8.F, 'x');
            GLWinRotate(glwin, i * 4.F, 'y');

            /* 3D cylindrical type vector, mapped to color */
            vis_VisContextSetVectorType(vcvec, VIS_VECTORCYLINDER);
            vis_VisContextSetMapColor(vcvec, VIS_ON);
            vis_MarkVector(mark, 1, (Vfloat(*)[3])vec, (Vfloat(*)[3])xpt[0]);

            /* 2D line type vector, not mapped to color */
            vis_VisContextSetVectorType(vcvec, VIS_VECTORLINE);
            vis_VisContextSetMapColor(vcvec, VIS_OFF);
            vis_MarkVector(mark, 1, (Vfloat(*)[3])vec, (Vfloat(*)[3])xpt[1]);

            /* 3D polygon head, 2D line tail vector, mapped to color */
            vis_VisContextSetVectorType(vcvec, VIS_VECTORUMBRELLA);
            vis_VisContextSetMapSize(vcvec, VIS_OFF);
            vis_VisContextSetSize(vcvec, .6f);
            vis_VisContextSetMapColor(vcvec, VIS_ON);
            vis_MarkVector(mark, 1, (Vfloat(*)[3])vec, (Vfloat(*)[3])xpt[2]);
            vis_VisContextSetMapSize(vcvec, VIS_ON);
            vis_VisContextSetSize(vcvec, 1.);

            GLWinXfmPop(glwin);
            GLWinSwap(glwin);
            sleep(1);
        }
        sleep(1);
    }
    sleep(2);

    /* draw tensors */
    for (j = 0; j < 3; j++) {
        for (i = 0; i < 8; i++) {
            GLWinClear(glwin);
            GLWinColor(glwin, ctex);
            if (j == 2) {
                vis_VisContextSetComponent(vcten, VIS_COMPONENT_MAXSHEAR);
                GLWinText(glwin, xtex, "Tensor Max Shear");
            }
            else if (j == 1) {
                vis_VisContextSetComponent(vcten, VIS_COMPONENT_PRINCIPAL);
                GLWinText(glwin, xtex, "Tensor Principals");
            }
            else {
                vis_VisContextSetComponent(vcten, VIS_COMPONENT_BASIC);
                GLWinText(glwin, xtex, "Tensor Components");
            }
            GLWinXfmPush(glwin);
            GLWinRotate(glwin, i * 8.F, 'x');
            GLWinRotate(glwin, i * 4.F, 'y');

            /* 3D ellipsoidal tensor, mapped to color */
            vis_VisContextSetVectorType(vcvec, VIS_VECTORCYLINDER);
            vis_VisContextSetTensorType(vcten, VIS_TENSORELLIPSOID);
            vis_VisContextSetMapColor(vcten, VIS_ON);
            vis_MarkTensor(mark, 1, (Vfloat(*)[6])ten, (Vfloat(*)[3])xpt[0]);

            /* 3D cube tensor, not mapped to color */
            vis_VisContextSetVectorType(vcvec, VIS_VECTORLINE);
            vis_VisContextSetTensorType(vcten, VIS_TENSORCUBE);
            vis_VisContextSetMapColor(vcten, VIS_OFF);
            vis_VisContextSetSize(vcten, .6f);
            vis_VisContextSetXYZColor(vcten, 0, 0, 0);
            vis_MarkTensor(mark, 1, (Vfloat(*)[6])ten, (Vfloat(*)[3])xpt[1]);
            vis_VisContextSetMapSize(vcten, VIS_ON);
            vis_VisContextSetSize(vcten, 1.);
            vis_VisContextSetXYZColor(vcten, 4, 5, 6);

            /* 2D crows feet tensor, mapped to color */
            vis_VisContextSetVectorType(vcvec, VIS_VECTORUMBRELLA);
            vis_VisContextSetTensorType(vcten, VIS_TENSORCROWSFEET);
            vis_VisContextSetMapColor(vcten, VIS_ON);
            vis_VisContextSetMapSize(vcvec, VIS_OFF);
            vis_VisContextSetSize(vcvec, .6f);
            vis_MarkTensor(mark, 1, (Vfloat(*)[6])ten, (Vfloat(*)[3])xpt[2]);
            vis_MarkTensorCompute(mark, ten, xpt[2], van, xan);
            vis_VisContextSetMapSize(vcvec, VIS_ON);
            vis_VisContextSetSize(vcvec, 1.);
            /* annotate */
            GLWinColor(glwin, ctex);
            for (k = 0; k < 6; k++) {
                if (van[k] != 0.) {
                    sprintf(stg, "%g", van[k]);
                    GLWinText(glwin, xan[k][0], stg);
                }
            }

            GLWinXfmPop(glwin);
            GLWinSwap(glwin);
            sleep(1);
        }
        sleep(1);
    }
    sleep(2);

    /* free all objects */
    vgl_DrawFunEnd(df);
    vis_VisContextEnd(vcsca);
    vis_VisContextEnd(vcvec);
    vis_VisContextEnd(vcten);
    vis_LevelsEnd(levels);
    vis_ColorMapEnd(cmap);
    vis_MarkEnd(mark);
    GLWinEnd(glwin);
    return 0;
}
../../_images/vistools-exam1.gif

Figure 14-11, Scalar, Vector and Tensor Component Markers

15.22. Example 11a, Draw Distributed Loads

This example illustrates using the Mark, Contour, Edge and Face modules to draw distributed loadings. There are many ways in which distributed loadings may be visualized. The strategy used in this example is to composite discrete vector markers representing the magnitude and direction of a load with a “load surface” which represents the distributed nature of the load. In this example two distributed load types are drawn. The first is a distributed pressure over a face, the second is a distributed moment along an edge. If load surfaces are to be drawn together with load markers, the load surfaces must be coincident in space to the marker feature. The function vis_MarkVectorCompute() is used to return the annotation location of the marker. This location in turn is used to position the load surfaces.

The distributed pressure load is drawn with vectors pointing in the direction of the pressure load at the face nodes and a contoured surface showing the magnitude and distribution of the pressure. It is important that the vis_VisContextSetSize() function be used to indicate the size of the markers at their maximum magnitude as set in the Levels object. The function vis_FaceComputeDist() is used to compute the equivalent nodal loads for the distributed pressure. The equivalent nodal load vectors are drawn. The face is a parabolic Serendipity topology, note that the equivalent nodal loads are somewhat counter intuitive. The function vis_FaceConvertDist() is then called to convert the equivalent nodal loads to a distributed traction. The recovered tractions are drawn and are identical to the original distributed pressure vectors.

The distributed moment load is drawn with round vectors pointing in the direction of the moment load at the edge nodes and a constant colored surface showing the magnitude and distribution of the moment. The load surface is decomposed into 12 strips, each of which is drawn as a 3 by 2 point face.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

static Vfloat xquad[8][3] = {{-1., -1., 0.},  {1., -1., 0.},  {1., 1., 0.}, {-1., 1., 0.},
                             {0., -1.1f, 0.}, {1., 0., 0.1f}, {0., 1., 0.}, {-1., 0., 0.2f}};

static Vfloat xline[3][3] = {{-1., -1., 0.}, {0., -1.1f, 0.}, {1., -1., 0.}};

static Vfloat xtitle[3] = {-1.5f, 1.5f, 0.};

/* Red,Green,Blue components of entity Colormap */
static Vfloat gray[3] = {.6f, .6f, .6f};
static Vfloat white[3] = {1., 1., 1.};
static Vfloat lightblue[3] = {.5, .5, 1.};

/* scalar element node face pressures */
static Vfloat pres[8] = {1., 2., 7., 4., 1.5f, 3.5f, 5.5f, 2.5f};
/* scalar element node line moments */
static Vfloat moment[3] = {1., 3., 2.5};

/*----------------------------------------------------------------------
                      Draw Distributed Loads
----------------------------------------------------------------------*/
int
main()
{
#ifdef VKI_WIND_X11
    Display* display;
    int screen;
#endif
    vis_Face* face;
    vis_Edge* edge;
    vis_Contour* contour;
    vis_Mark* mark;
    vis_VisContext *vc, *vccontour, *vcmark;
    vis_Levels* levels;
    vis_ColorMap *cmapiso, *cmap;
    vis_TransMap* tmap;
    vgl_DrawFun* df;
    vgl_OpenGLDev* ogldev;
    vgl_Xfm* xfm;

    Vint i, j, k, n;
    Vfloat tm[4][4], cl[3], xl[3];
    Vfloat vec[8][3], norm[8][3], xo[8][3], sc, tang[3][3];
    Vfloat enl[8][3], vcl[8][3];
    Vfloat rx[3][3], ry[3][3], d[3], ang, xv[3], xe[6][3], ve[6][3];
    Vfloat trans;
    Vint flag;
    Vint nlevels;

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* connect to window system */
#ifdef VKI_WIND_X11
    if (vgl_OpenGLDevTestX(&flag), flag == 0) {
        printf("OpenGL not enabled, exiting\n");
        return 1;
    }
    display = XOpenDisplay(0);
    screen = DefaultScreen(display);
    vgl_OpenGLDevConnectX(display, screen);
#endif
#ifdef VKI_WIND_WIN32
    if (vgl_OpenGLDevTestWIN(&flag), flag == 0) {
        printf("OpenGL not enabled, exiting\n");
        return 1;
    }
    vgl_OpenGLDevConnectWIN();
#endif

    /* create OpenGL device */
    ogldev = vgl_OpenGLDevBegin();
    df = vgl_DrawFunBegin();
    vgl_OpenGLDevDrawFun(ogldev, df);
    vgl_DrawFunPositionWindow(df, 200, 200, 600, 600);
    vgl_DrawFunOpenWindow(df, "Example 11avgl");
    vgl_DrawFunProjOrtho(df, -2.0, 2.0, -2.0, 2.0, -10., 10.);
    vgl_DrawFunSetMode(df, VGL_ZBUFFERMODE, VGL_ON);
    vgl_DrawFunSetMode(df, VGL_LIGHTMODE, VGL_ON);
    cl[0] = .7f;
    cl[1] = .7f;
    cl[2] = .7f;
    xl[0] = 0.;
    xl[1] = 0.;
    xl[2] = 0.;
    vgl_DrawFunLight(df, 0, VGL_LIGHT_AMBIENT, cl, xl);
    cl[0] = .5f;
    cl[1] = .5f;
    cl[2] = .5f;
    xl[0] = 1.f;
    xl[1] = 1.;
    xl[2] = 1.;
    vgl_DrawFunLight(df, 1, VGL_LIGHT_DISTANT, cl, xl);

    /* create transformation object */
    xfm = vgl_XfmBegin();

    /* edge/face vis context */
    vc = vis_VisContextBegin();
    vis_VisContextSetRefinement(vc, 2);
    vis_VisContextSetShade(vc, VIS_VERTEXSHADE);

    /* edge/face color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetType(cmap, COLORMAP_TRUECOLOR);
    vis_ColorMapSetRGB(cmap, 1, 1, &gray);
    vis_ColorMapSetRGB(cmap, 1, 2, &white);
    vis_ColorMapSetRGB(cmap, 1, 3, &lightblue);

    /* transparency map */
    trans = .5;
    tmap = vis_TransMapBegin();
    vis_TransMapSetType(tmap, TRANSMAP_FACTOR);
    vis_TransMapSetTrans(tmap, 1, 1, &trans);

    /* create face object and set objects */
    face = vis_FaceBegin();
    vis_FaceSetObject(face, VGL_DRAWFUN, df);
    vis_FaceSetObject(face, VIS_VISCONTEXT, vc);
    vis_FaceSetObject(face, VIS_COLORMAP, cmap);
    vis_FaceSetObject(face, VIS_TRANSMAP, tmap);

    /* create edge object and set objects */
    edge = vis_EdgeBegin();
    vis_EdgeSetObject(edge, VGL_DRAWFUN, df);
    vis_EdgeSetObject(edge, VIS_VISCONTEXT, vc);
    vis_EdgeSetObject(edge, VIS_COLORMAP, cmap);

    /* define levels */
    nlevels = 12;
    levels = vis_LevelsBegin();
    vis_LevelsDef(levels, LEVELS_LINEAR, nlevels);

    /* generate load color maps */
    cmapiso = vis_ColorMapBegin();
    vis_ColorMapSetType(cmapiso, COLORMAP_TRUECOLOR);
    vis_ColorMapRamp(cmapiso, nlevels, 1, COLORMAP_HUE);

    /* mark vis context */
    vcmark = vis_VisContextBegin();
    vis_VisContextSetMapSize(vcmark, SYS_ON);
    vis_VisContextSetSize(vcmark, 1.);
    vis_VisContextSetMapColor(vcmark, VIS_MAPCOLOR_SMOOTH);

    /* distributed load vectors */
    mark = vis_MarkBegin();
    vis_MarkSetObject(mark, VGL_DRAWFUN, df);
    vis_MarkSetObject(mark, VIS_VISCONTEXT, vcmark);
    vis_MarkSetObject(mark, VIS_LEVELS, levels);
    vis_MarkSetObject(mark, VIS_COLORMAP, cmapiso);

    /* setup contour object */
    vccontour = vis_VisContextBegin();
    vis_VisContextSetIsoValType(vccontour, VIS_ISOVALFRINGE);
    vis_VisContextSetRefinement(vccontour, 2);
    vis_VisContextSetShade(vccontour, VIS_VERTEXSHADE);
    vis_VisContextSetTrans(vccontour, 1);

    contour = vis_ContourBegin();
    vis_ContourSetObject(contour, VGL_DRAWFUN, df);
    vis_ContourSetObject(contour, VIS_VISCONTEXT, vccontour);
    vis_ContourSetObject(contour, VIS_LEVELS, levels);
    vis_ContourSetObject(contour, VIS_COLORMAP, cmapiso);
    vis_ContourSetObject(contour, VIS_TRANSMAP, tmap);

    /* draw pressure */
    vis_LevelsSetMinMax(levels, 0., 7.);
    vis_LevelsGenerate(levels, LEVELS_PADTOP);
    for (i = 1; i <= 20; i++) {
        vgl_DrawFunClear(df);
        vgl_DrawFunColor(df, white);
        vgl_DrawFunText(df, xtitle, "Distributed pressure surface");

        vgl_DrawFunXfmPush(df);
        vgl_XfmRotate(xfm, -(i - 1) * 8.F * 3.14F / 180.F, XFM_YAXIS);
        vgl_XfmGetMatrix(xfm, tm);
        vgl_DrawFunXfmLoad(df, tm);

        /* draw element face - gray, opaque */
        vis_VisContextSetColor(vc, 1);
        vis_VisContextSetTrans(vc, 0);
        vis_FaceSetTopology(face, SYS_SHAPEQUAD, 3, 0);
        vis_FaceCurv(face, xquad, VIS_NODATA, NULL);

        /* compute pressure sized normal to surface */
        vis_FaceComputeNorm(face, xquad, norm);
        for (n = 0; n < 8; n++) {
            vec[n][0] = -pres[n] * norm[n][0];
            vec[n][1] = -pres[n] * norm[n][1];
            vec[n][2] = -pres[n] * norm[n][2];
        }
        /* draw vectors at face nodes */
        vis_VisContextSetRefinement(vcmark, 1);
        vis_VisContextSetVectorType(vcmark, VIS_VECTORUMBRELLA);
        vis_VisContextSetFlags(vcmark, VIS_VECTORTAIL);
        vis_MarkVector(mark, 8, vec, xquad);

        /* draw pressure colored offset face */
        /* compute locations of vector tails for pressure face */
        for (n = 0; n < 8; n++) {
            vis_MarkVectorCompute(mark, vec[n], xquad[n], &sc, &xo[n]);
        }
        vis_VisContextTouch(vccontour);
        vis_ContourSetTopology(contour, SYS_SHAPEQUAD, 3, 0);
        vis_ContourCurv(contour, pres, xo, VIS_VERTEXDATA, norm);

        vgl_DrawFunSwap(df);
        vgl_DrawFunDelay(df, 1.);

        /* show equivalent nodal loads on eighth frame */
        if (i == 8) {
            vgl_DrawFunClear(df);
            vgl_DrawFunColor(df, white);
            vgl_DrawFunText(df, xtitle, "Equivalent nodal loads");

            vis_VisContextTouch(vc);
            vis_FaceCurv(face, xquad, VIS_NODATA, NULL);
            vis_FaceComputeDist(face, xquad, 3, (Vfloat*)vec, (Vfloat*)enl);
            vis_MarkVector(mark, 8, enl, xquad);

            vgl_DrawFunSwap(df);
            vgl_DrawFunDelay(df, 2.);
        }

        /* show and recover original tractions on eighth frame */
        if (i == 8) {
            vgl_DrawFunClear(df);
            vgl_DrawFunColor(df, white);
            vgl_DrawFunText(df, xtitle, "Recover original tractions");

            vis_VisContextTouch(vc);
            vis_FaceCurv(face, xquad, VIS_NODATA, NULL);
            vis_FaceConvertDist(face, xquad, 3, (Vfloat*)enl, (Vfloat*)vcl);
            vis_MarkVector(mark, 8, vcl, xquad);

            vgl_DrawFunSwap(df);
            vgl_DrawFunDelay(df, 2.);
        }

        vgl_DrawFunXfmPop(df);
    }

    /* draw edge moment */
    vis_LevelsSetMinMax(levels, 0., 3.);
    vis_LevelsGenerate(levels, LEVELS_PADTOP);
    for (i = 0; i < 20; i++) {
        vgl_DrawFunClear(df);
        vgl_DrawFunColor(df, white);
        vgl_DrawFunText(df, xtitle, "Distributed edge moment");

        vgl_DrawFunXfmPush(df);
        vgl_XfmRotate(xfm, -i * 8.F * 3.14F / 180.F, XFM_YAXIS);
        vgl_XfmGetMatrix(xfm, tm);
        vgl_DrawFunXfmLoad(df, tm);

        /* draw face */
        vis_VisContextSetColor(vc, 1);
        vis_VisContextSetTrans(vc, 0);
        vis_FaceSetTopology(face, SYS_SHAPEQUAD, 3, 0);
        vis_FaceCurv(face, xquad, VIS_NODATA, NULL);

        /* draw edge */
        vis_VisContextSetColor(vc, 2);
        vis_VisContextSetLineWidth(vc, 2);
        vis_EdgeSetTopology(edge, SYS_SHAPELINE, 3);
        vis_EdgeCurv(edge, xline);
        /* compute tangent to edge and scale vector by moment */
        vis_EdgeComputeTang(edge, xline, tang);
        for (n = 0; n < 3; n++) {
            vec[n][0] = tang[n][0] * moment[n];
            vec[n][1] = tang[n][1] * moment[n];
            vec[n][2] = tang[n][2] * moment[n];
        }
        /* draw round moment vectors along edge */
        vis_VisContextSetRefinement(vcmark, 2);
        vis_VisContextSetVectorType(vcmark, VIS_VECTORCYLINDER);
        vis_VisContextSetFlags(vcmark, VIS_VECTORTAIL | VIS_VECTORROUND);
        vis_MarkVector(mark, 3, vec, xline);

        /* connect moment arrows with transparent surface */
        /* compute local x', y' directions perpendicular to edge
           and marker radius */
        for (n = 0; n < 3; n++) {
            vis_MarkVectorCompute(mark, vec[n], xline[n], &sc, &xo[n]);
            rx[n][0] = xo[n][0] - xline[n][0];
            rx[n][1] = xo[n][1] - xline[n][1];
            rx[n][2] = xo[n][2] - xline[n][2];

            ry[n][0] = tang[n][1] * rx[n][2] - tang[n][2] * rx[n][1];
            ry[n][1] = tang[n][2] * rx[n][0] - tang[n][0] * rx[n][2];
            ry[n][2] = tang[n][0] * rx[n][1] - tang[n][1] * rx[n][0];

            d[n] = (Vfloat)sqrt(rx[n][0] * rx[n][0] + rx[n][1] * rx[n][1] + rx[n][2] * rx[n][2]);
        }
        /* draw surface - lightblue, transparent */
        vis_VisContextSetColor(vc, 3);
        vis_VisContextSetTrans(vc, 1);
        for (j = 0; j < 12; j++) {
            for (k = 0; k < 2; k++) {
                ang = 2.F * (j + k) / 12.F * 3.14159F;
                xv[0] = (Vfloat)cos(ang);
                xv[1] = (Vfloat)sin(ang);
                xv[2] = 0.;
                /* compute coordinates and normals of a 3 by 2 strip */
                for (n = 0; n < 3; n++) {
                    xe[n + 3 * k][0] = xline[n][0] + xv[0] * rx[n][0] + xv[1] * ry[n][0];
                    xe[n + 3 * k][1] = xline[n][1] + xv[0] * rx[n][1] + xv[1] * ry[n][1];
                    xe[n + 3 * k][2] = xline[n][2] + xv[0] * rx[n][2] + xv[1] * ry[n][2];
                    ve[n + 3 * k][0] = (xe[n + 3 * k][0] - xline[n][0]) / d[n];
                    ve[n + 3 * k][1] = (xe[n + 3 * k][1] - xline[n][1]) / d[n];
                    ve[n + 3 * k][2] = (xe[n + 3 * k][2] - xline[n][2]) / d[n];
                }
            }
            /* draw strip with face object */
            vis_FaceSetTopology(face, SYS_SHAPEQUAD, 3, 2);
            vis_FaceCurv(face, xe, VIS_VERTEXDATA, ve);
        }

        vgl_DrawFunXfmPop(df);
        vgl_DrawFunSwap(df);
        vgl_DrawFunDelay(df, 1.);
    }
    vgl_DrawFunDelay(df, 5.);

    /* free all objects */
    vgl_DrawFunEnd(df);
    vgl_OpenGLDevEnd(ogldev);
    vgl_XfmEnd(xfm);
    vis_VisContextEnd(vc);
    vis_ColorMapEnd(cmap);
    vis_TransMapEnd(tmap);
    vis_FaceEnd(face);
    vis_EdgeEnd(edge);
    vis_LevelsEnd(levels);
    vis_ColorMapEnd(cmapiso);
    vis_MarkEnd(mark);
    vis_VisContextEnd(vcmark);
    vis_VisContextEnd(vccontour);
    vis_ContourEnd(contour);

    /* disconnect from window system */
    vgl_OpenGLDevDisconnect();
#ifdef VKI_WIND_X11
    XCloseDisplay(display);
#endif
    return 0;
}

15.23. Example 12, Draw Triads

This example illustrates using the Triad module to draw representations of Cartesian, cylindrical and spherical coordinate systems. There are many colors and drawing styles to choose from. These variations are specified with a combination of settings in the VisContext object and parameter settings in the Triad object. Two major styles of triads are drawn in this example. The first style is the basic triad which consists of three orthogonal vectors draw along the orientation axes which are labeled with X,Y,Z, R,T,Z or R,T,P depending upon whether the coordinate system is Cartesian, cylindrical or spherical. The second style is the detailed triad in which the radius and angle conventions of cylindrical and spherical systems are displayed.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

#include "glwin.h"

static Vfloat rgb[8][3] = {{.8f, .8f, .8f}, {1., 0., 0.}, {0., 1., 0.}, {0., 0., 1.},
                           {0., 1., 1.},    {1., 0., 1.}, {1., 1., 0.}, {1., 1., 1.}};

static Vfloat xtex[3] = {-.5, 3.5, 0.};
static Vfloat ctex[3] = {1., 1., 1.};

/*----------------------------------------------------------------------
                      Draw triads
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun* df;
    vis_VisContext* vc;
    vis_ColorMap* cmap;
    vis_Triad* triad;
    GLWin* glwin;

    int i;
    Vfloat x[3], tm[3][3];

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 200, 200, 700, 500);
    GLWinOrtho(glwin, -1., 6., -1., 4., -4., 4.);

    /* create draw function object for GL */
    df = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, df);

    vc = vis_VisContextBegin();
    vis_VisContextSetLineWidth(vc, 2);
    vis_VisContextSetMinorColor(vc, 0);
    vis_VisContextSetSize(vc, 1.);
    vis_VisContextSetMinorSize(vc, .5);
    vis_VisContextSetColor(vc, 7);
    vis_VisContextSetXYZColor(vc, 1, 2, 3);
    vis_VisContextSetABCColor(vc, 7, 7, 7);
    vis_VisContextSetTrans(vc, 1);

    /* color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetType(cmap, COLORMAP_TRUECOLOR);
    vis_ColorMapSetRGB(cmap, 8, 0, rgb);

    /* create triad object and set objects */
    triad = vis_TriadBegin();
    vis_TriadSetObject(triad, VGL_DRAWFUN, df);
    vis_TriadSetObject(triad, VIS_VISCONTEXT, vc);
    vis_TriadSetObject(triad, VIS_COLORMAP, cmap);

    /* set triad orientation to the global system */
    tm[0][0] = 1.;
    tm[0][1] = 0.;
    tm[0][2] = 0.;
    tm[1][0] = 0.;
    tm[1][1] = 1.;
    tm[1][2] = 0.;
    tm[2][0] = 0.;
    tm[2][1] = 0.;
    tm[2][2] = 1.;

    /* use line vectors and no detail */
    vis_VisContextSetVectorType(vc, VIS_VECTORLINE);
    vis_TriadSetParami(triad, TRIAD_DETAIL, VIS_OFF);

    /* draw basic triads */
    for (i = 0; i < 8; i++) {
        GLWinClear(glwin);
        GLWinColor(glwin, ctex);
        GLWinText(glwin, xtex, "Basic Triads");
        GLWinXfmPush(glwin);
        GLWinRotate(glwin, i * 8.F, 'x');
        GLWinRotate(glwin, i * 4.F, 'y');

        x[0] = 0.;
        x[1] = 0.;
        x[2] = 0.;
        vis_TriadDraw(triad, SYS_CARTESIAN, x, tm);
        x[0] = 2.;
        x[1] = 0.;
        x[2] = 0.;
        vis_TriadDraw(triad, SYS_CYLINDRICAL, x, tm);
        x[0] = 4.;
        x[1] = 0.;
        x[2] = 0.;
        vis_TriadDraw(triad, SYS_CYLINDRICAL_ALT, x, tm);
        x[0] = 0.;
        x[1] = 2.;
        x[2] = 0.;
        vis_TriadDraw(triad, SYS_SPHERICAL, x, tm);
        x[0] = 2.;
        x[1] = 2.;
        x[2] = 0.;
        vis_TriadDraw(triad, SYS_SPHERICAL_ALT, x, tm);
        x[0] = 4.;
        x[1] = 2.;
        x[2] = 0.;
        vis_TriadDraw(triad, SYS_TOROIDAL, x, tm);

        GLWinXfmPop(glwin);
        GLWinSwap(glwin);
        sleep(1);
    }
    sleep(2);

    /* use umbrella vectors, detail and shape */
    vis_VisContextSetVectorType(vc, VIS_VECTORUMBRELLA);
    vis_TriadSetParami(triad, TRIAD_DETAIL, VIS_ON);
    vis_TriadSetParami(triad, TRIAD_SHAPE, VIS_ON);

    /* draw detailed triads */
    for (i = 0; i < 8; i++) {
        GLWinClear(glwin);
        GLWinColor(glwin, ctex);
        GLWinText(glwin, xtex, "Detailed Triads");
        GLWinXfmPush(glwin);
        GLWinRotate(glwin, i * 8.F, 'x');
        GLWinRotate(glwin, i * 4.F, 'y');

        x[0] = 0.;
        x[1] = 0.;
        x[2] = 0.;
        vis_TriadDraw(triad, SYS_CARTESIAN, x, tm);
        x[0] = 2.;
        x[1] = 0.;
        x[2] = 0.;
        vis_TriadDraw(triad, SYS_CYLINDRICAL, x, tm);
        x[0] = 4.;
        x[1] = 0.;
        x[2] = 0.;
        vis_TriadDraw(triad, SYS_CYLINDRICAL_ALT, x, tm);
        x[0] = 0.;
        x[1] = 2.;
        x[2] = 0.;
        vis_TriadDraw(triad, SYS_SPHERICAL, x, tm);
        x[0] = 2.;
        x[1] = 2.;
        x[2] = 0.;
        vis_TriadDraw(triad, SYS_SPHERICAL_ALT, x, tm);
        x[0] = 4.;
        x[1] = 2.;
        x[2] = 0.;
        vis_TriadDraw(triad, SYS_TOROIDAL, x, tm);

        GLWinXfmPop(glwin);
        GLWinSwap(glwin);
        sleep(1);
    }
    sleep(4);

    /* free all objects */
    vgl_DrawFunEnd(df);
    vis_VisContextEnd(vc);
    vis_ColorMapEnd(cmap);
    vis_TriadEnd(triad);
    GLWinEnd(glwin);
    return 0;
}
../../_images/vistools-exam12.gif

Figure 14-12, Basic Triads

15.24. Example 13, Compute and Draw a TEE Beam Section

This example illustrates using the BeamSect module to compute and draw a parameterized TEE beam section. The BeamSect module supports a set of built-in parameterized sections in which the user need only supply the dimensions of a small set of section dimensions and the BeamSect module will compute and display the section properties. In this example, the width is 3., height is 2., the thickness of the flange and web are .1 and .3 and the radius of the fillet is .2 . After the section dimensions are defined by calling vis_BeamSectSetDimensions(), the section properties are computed by calling vis_BeamSectProps(). The computed properties are returned by calling vis_BeamSectGetProps() and are printed. The section is drawn by calling vis_BeamSectDraw(). The appropriate display parameters have been enabled using vis_BeamSectSetParami() to include icons for the locations of the shear center and centroid and orientations of the section reference axes and principal axes.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

#include "glwin.h"

static Vfloat rgb[9][3] = {{.5f, .5f, .5f}, {1., 0., 0.}, {0., 1., 0.},    {0., 0., 1.}, {0., 1., 1.},
                           {1., 0., 1.},    {1., 1., 0.}, {.2f, .2f, .2f}, {1., 1., 1.}};

static Vfloat xtex[3] = {-1.8f, 1.8f, 0.};
static Vfloat ctex[3] = {1., 1., 1.};

/*----------------------------------------------------------------------
                      Compute and Draw TEE Beam Section
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun* df;
    vis_VisContext* vc;
    vis_ColorMap* cmap;
    vis_Levels* levels;
    vis_BeamSect* beamsect;
    GLWin* glwin;

    Vfloat dimes[5];
    Vfloat x[3], tm[3][3];
    Vfloat props[BEAMSECT_MAXPROPS];
    Vfloat dmat[21];

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 200, 200, 400, 400);
    GLWinOrtho(glwin, -2., 2., -2., 2., -2., 2.);

    /* create draw function object for GL */
    df = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, df);

    vc = vis_VisContextBegin();
    vis_VisContextSetColor(vc, 0);
    vis_VisContextSetXYZColor(vc, 1, 2, 3);
    vis_VisContextSetABCColor(vc, 8, 7, 6);
    vis_VisContextSetEdge(vc, VIS_ON);
    vis_VisContextSetFill(vc, VIS_ON);
    vis_VisContextSetSize(vc, .5);
    vis_VisContextSetMinorSize(vc, .2f);
    vis_VisContextSetMapColor(vc, VIS_ON);

    /* levels for beam section */
    levels = vis_LevelsBegin();
    vis_LevelsDef(levels, LEVELS_LINEAR, 7);

    /* color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetType(cmap, COLORMAP_TRUECOLOR);
    vis_ColorMapSetRGB(cmap, 9, 0, rgb);

    /* create beamsect object and set objects */
    beamsect = vis_BeamSectBegin();
    vis_BeamSectSetObject(beamsect, VGL_DRAWFUN, df);
    vis_BeamSectSetObject(beamsect, VIS_VISCONTEXT, vc);
    vis_BeamSectSetObject(beamsect, VIS_COLORMAP, cmap);
    vis_BeamSectSetObject(beamsect, VIS_LEVELS, levels);

    /* set display parameters */
    vis_BeamSectSetParami(beamsect, BEAMSECT_AXESBASIC, VIS_ON);
    vis_BeamSectSetParami(beamsect, BEAMSECT_AXESPRINCIPAL, VIS_ON);
    vis_BeamSectSetParami(beamsect, BEAMSECT_CENTROID, BEAMSECT_CENTROID_CIRCLE);
    vis_BeamSectSetParami(beamsect, BEAMSECT_SHEARCENTER, VIS_ON);

    /* define TEE section */
    vis_BeamSectDef(beamsect, BEAMSECT_TEE);
    dimes[0] = 3.;
    dimes[1] = 2.;
    dimes[2] = .1f;
    dimes[3] = .3f;
    dimes[4] = .2f;
    vis_BeamSectSetDimensions(beamsect, dimes);

    /* compute and get section properties */
    vis_BeamSectProps(beamsect);
    vis_BeamSectGetProps(beamsect, props, dmat);

    /* print section properties */
    printf("\n");
    printf("A   = %f\n", props[0]);
    printf("Iyy = %f\n", props[1]);
    printf("Izz = %f\n", props[2]);
    printf("Iyz = %f\n", props[3]);
    printf("Ang = %f\n", props[4]);
    printf("J   = %f\n", props[5]);
    printf("Asy = %f\n", props[6]);
    printf("Asz = %f\n", props[7]);
    printf("Ey  = %f\n", props[9]);
    printf("Ez  = %f\n", props[10]);
    printf("Dsy = %f\n", props[11]);
    printf("Dsz = %f\n", props[12]);
    printf("Cw  = %f\n", props[13]);
    printf("Ny  = %f\n", props[14]);
    printf("Nz  = %f\n", props[15]);

    /* draw */
    GLWinClear(glwin);
    GLWinColor(glwin, ctex);
    GLWinText(glwin, xtex, "TEE Beam Section");
    /* set position */
    x[0] = 0.;
    x[1] = 0.;
    x[2] = 0.;
    /* set orientation - x' out, y' right, z' up */
    tm[0][0] = 0.;
    tm[0][1] = 0.;
    tm[0][2] = 1.;
    tm[1][0] = 1.;
    tm[1][1] = 0.;
    tm[1][2] = 0.;
    tm[2][0] = 0.;
    tm[2][1] = 1.;
    tm[2][2] = 0.;
    vis_BeamSectDraw(beamsect, x, tm, VIS_OFF);
    GLWinSwap(glwin);
    sleep(5);

    /* free all objects */
    vgl_DrawFunEnd(df);
    vis_VisContextEnd(vc);
    vis_ColorMapEnd(cmap);
    vis_LevelsEnd(levels);
    vis_BeamSectEnd(beamsect);
    GLWinEnd(glwin);
    return 0;
}
../../_images/vistools-exam13.gif

Figure 14-13, TEE Beam Section

15.25. Example 13a, Compute and Draw a User Defined Beam Section

This example illustrates using the BeamSect module to compute and draw a user defined beam section. User defined sections are input as a series of straight line segments defining loops. Generally there is a single external loop and any number of interior loops defining holes in the section. The geometry of the loops is defined by specifying the locations of a set of points on a plane using vis_BeamSectSetPoint(), then the loops are defined by specifying the point connectivity using vis_BeamSectSetLoop(). Note that the identifiers of all points and loops must be greater than or equal to one. In this example a beam section with a triangular outline is defined with a triangular cutout. This requires six points and two loops to be defined. Once the geometry is defined then the section properties are computed, accessed and drawn is a manner identical to the previous example.

For illustration, the location of point 2 is repeatedly moved by increments of .01 along the positive x axis and the section is recalculated and drawn.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

#include "glwin.h"

static Vfloat rgb[9][3] = {{.5f, .5f, .5f}, {1., 0., 0.}, {0., 1., 0.},    {0., 0., 1.}, {0., 1., 1.},
                           {1., 0., 1.},    {1., 1., 0.}, {.2f, .2f, .2f}, {1., 1., 1.}};

static Vfloat xtex[3] = {-1.8f, 1.8f, 0.};
static Vfloat ctex[3] = {1., 1., 1.};

/*----------------------------------------------------------------------
                      Compute and Draw User Defined Beam Section
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun* df;
    vis_VisContext* vc;
    vis_ColorMap* cmap;
    vis_Levels* levels;
    vis_BeamSect* beamsect;
    GLWin* glwin;

    int i, n;
    Vfloat xp[6][2] = {{.2f, .2f}, {2., .2f}, {.2f, 1.5f}, {.4f, .4f}, {1., .4f}, {.4f, 1.}};
    Vint ix[2][3] = {{1, 2, 3}, {4, 5, 6}};
    Vfloat x[3], tm[3][3];
    Vfloat props[BEAMSECT_MAXPROPS];
    Vfloat dmat[21];

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 200, 200, 400, 400);
    GLWinOrtho(glwin, -2., 2., -2., 2., -2., 2.);

    /* create draw function object for GL */
    df = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, df);

    vc = vis_VisContextBegin();
    vis_VisContextSetColor(vc, 0);
    vis_VisContextSetXYZColor(vc, 1, 2, 3);
    vis_VisContextSetABCColor(vc, 8, 7, 6);
    vis_VisContextSetEdge(vc, VIS_ON);
    vis_VisContextSetFill(vc, VIS_ON);
    vis_VisContextSetSize(vc, .5);
    vis_VisContextSetMinorSize(vc, .2f);
    vis_VisContextSetMapColor(vc, VIS_ON);

    /* levels for beam section */
    levels = vis_LevelsBegin();
    vis_LevelsDef(levels, LEVELS_LINEAR, 7);

    /* color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetType(cmap, COLORMAP_TRUECOLOR);
    vis_ColorMapSetRGB(cmap, 9, 0, rgb);

    /* create beamsect object and set objects */
    beamsect = vis_BeamSectBegin();
    vis_BeamSectSetObject(beamsect, VGL_DRAWFUN, df);
    vis_BeamSectSetObject(beamsect, VIS_VISCONTEXT, vc);
    vis_BeamSectSetObject(beamsect, VIS_COLORMAP, cmap);
    vis_BeamSectSetObject(beamsect, VIS_LEVELS, levels);

    /* set display parameters */
    vis_BeamSectSetParami(beamsect, BEAMSECT_AXESBASIC, VIS_ON);
    vis_BeamSectSetParami(beamsect, BEAMSECT_AXESPRINCIPAL, VIS_ON);
    vis_BeamSectSetParami(beamsect, BEAMSECT_CENTROID, BEAMSECT_CENTROID_CIRCLE);
    vis_BeamSectSetParami(beamsect, BEAMSECT_SHEARCENTER, VIS_ON);

    /* define user defined section */
    vis_BeamSectDef(beamsect, BEAMSECT_GEOMETRY);
    for (i = 1; i <= 6; i++) {
        vis_BeamSectSetPoint(beamsect, i, xp[i - 1]);
    }
    vis_BeamSectSetLoop(beamsect, 1, 1, 3, ix[0]);
    vis_BeamSectSetLoop(beamsect, 2, 0, 3, ix[1]);

    /* loop, changing point 2 */
    for (n = 0; n < 100; n++) {
        /* compute and get section properties */
        vis_BeamSectProps(beamsect);
        vis_BeamSectGetProps(beamsect, props, dmat);

        /* print section properties */
        printf("\n");
        printf("A   = %f\n", props[0]);
        printf("Iyy = %f\n", props[1]);
        printf("Izz = %f\n", props[2]);
        printf("Iyz = %f\n", props[3]);
        printf("Ang = %f\n", props[4]);
        printf("J   = %f\n", props[5]);
        printf("Asy = %f\n", props[6]);
        printf("Asz = %f\n", props[7]);
        printf("Asyz= %f\n", props[8]);
        printf("Ey  = %f\n", props[9]);
        printf("Ez  = %f\n", props[10]);
        printf("Dsy = %f\n", props[11]);
        printf("Dsz = %f\n", props[12]);
        printf("Cw  = %f\n", props[13]);
        /* draw */
        GLWinClear(glwin);
        GLWinColor(glwin, ctex);
        GLWinText(glwin, xtex, "User Defined Beam Section");
        /* set position */
        x[0] = -1.;
        x[1] = -1.;
        x[2] = 0.;
        /* set orientation - x' out, y' right, z' up */
        tm[0][0] = 0.;
        tm[0][1] = 0.;
        tm[0][2] = 1.;
        tm[1][0] = 1.;
        tm[1][1] = 0.;
        tm[1][2] = 0.;
        tm[2][0] = 0.;
        tm[2][1] = 1.;
        tm[2][2] = 0.;
        vis_BeamSectDraw(beamsect, x, tm, VIS_OFF);
        GLWinSwap(glwin);

        /* increment point 2 */
        xp[1][0] += .01f;
        vis_BeamSectSetPoint(beamsect, 2, xp[1]);
    }
    sleep(5);

    /* free all objects */
    vgl_DrawFunEnd(df);
    vis_VisContextEnd(vc);
    vis_ColorMapEnd(cmap);
    vis_LevelsEnd(levels);
    vis_BeamSectEnd(beamsect);
    GLWinEnd(glwin);
    return 0;
}
../../_images/vistools-exam13a.gif

Figure 14-13, User Defined Beam Section

15.26. Example 13b, Draw a TEE, GEOMETRY and SEGMENTS Beam Element

This example extends Example 13 using the BeamSect and BeamElem modules to draw a complete beam element with a TEE beam section, a general GEOMETRY beam section and a connected SEGMENTS beam section. The BeamSect object defining the beam section properties is installed as an attribute object to a BeamElem object. The beam element is a three node, parabolic beam with a tapered cross section. The three node topology is set using vis_BeamElemSetTopology(). A call to vis_BeamElemSetEndFactors() defines the overall section scale factors at the beam end points. The section scaling is performed linearly between the beam element end points. The end flags are set to draw the section at both end points when the ElemRep element in the VisContext object is set to draw a solid representation. The beam element is drawn in five sequences illustrating different combinations of the ElemRep and ElemLoc visualization contexts.

The fifth sequence renders the beam using the so-called “polyline” representation of the beam section. The polyline representation of the general GEOMETRY section must be defined using vis_BeamSectSetPolyLine() or else the polyline representation will not be drawn. The polyline representation is more economical than drawing the full surface of the beam section in detail. Note that color mapping should be explicitly disabled so that the individual polylines representing the beam section are not drawn in different colors.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

#include "glwin.h"

static Vfloat rgb[9][3] = {{.5f, .5f, .5f}, {1., 0., 0.}, {0., 1., 0.},    {0., 0., 1.}, {0., 1., 1.},
                           {1., 0., 1.},    {1., 1., 0.}, {.2f, .2f, .2f}, {1., 1., 1.}};

static Vfloat xtex[3] = {-1.8f, 1.8f, 0.};
static Vfloat ctex[3] = {1., 1., 1.};

/* beam element node point locations */
static Vfloat xbeam[3][3] = {{-1.5f, .3f, 0.}, {0., 0., 0.}, {1.5f, .3f, 0.}};

/* dimensions of TEE */
static Vfloat dimes[5] = {3., 2., .1f, .3f, .2f};
/* general GEOMETRY */
static Vfloat xp[6][2] = {{.2f, .2f}, {2.f, .2f}, {.2f, 1.5f}, {.4f, .4f}, {1.f, .4f}, {.4f, 1.f}};
static Vint ix[2][3] = {{1, 2, 3}, {4, 5, 6}};
/* connected SEGMENTS */
static Vfloat xs[6][2] = {{.2f, .2f}, {.2f, 1.}, {.5f, 1.}, {.5f, .2f}, {.9f, .2f}, {.9f, 1.}};
static Vfloat ts[6] = {.05f, .1f, .05f, .1f, .05f};

/*----------------------------------------------------------------------
                      Draw TEE and GEOMETRY Beam Element
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun* df;
    vis_VisContext* vc;
    vis_ColorMap* cmap;
    vis_Levels* levels;
    vis_BeamSect* beamsect;
    vis_BeamElem* beamelem;
    GLWin* glwin;

    int i, j, k;
    Vfloat factors[2];
    Vchar text[65];

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 200, 200, 400, 400);
    GLWinOrtho(glwin, -2., 2., -2., 2., -3., 3.);

    /* create draw function object for GL */
    df = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, df);

    vc = vis_VisContextBegin();
    vis_VisContextSetColor(vc, 0);
    vis_VisContextSetXYZColor(vc, 1, 2, 3);
    vis_VisContextSetABCColor(vc, 8, 7, 6);
    vis_VisContextSetEdge(vc, VIS_ON);
    vis_VisContextSetFill(vc, VIS_ON);
    vis_VisContextSetSize(vc, .5);
    vis_VisContextSetMinorSize(vc, .2f);
    vis_VisContextSetMapColor(vc, VIS_ON);
    vis_VisContextSetRefinement(vc, 2);
    vis_VisContextSetShade(vc, VIS_VERTEXSHADE);
    vis_VisContextSetMarkerType(vc, VIS_BOX);

    /* levels for beam section */
    levels = vis_LevelsBegin();
    vis_LevelsDef(levels, LEVELS_LINEAR, 7);

    /* color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetType(cmap, COLORMAP_TRUECOLOR);
    vis_ColorMapSetRGB(cmap, 9, 0, rgb);

    /* create beamsect object and set objects */
    beamsect = vis_BeamSectBegin();
    vis_BeamSectSetObject(beamsect, VGL_DRAWFUN, df);
    vis_BeamSectSetObject(beamsect, VIS_VISCONTEXT, vc);
    vis_BeamSectSetObject(beamsect, VIS_COLORMAP, cmap);
    vis_BeamSectSetObject(beamsect, VIS_LEVELS, levels);

    /* set display parameters */
    vis_BeamSectSetParami(beamsect, BEAMSECT_CENTROID, BEAMSECT_CENTROID_SPHERE);
    vis_BeamSectSetParami(beamsect, BEAMSECT_SHEARCENTER, VIS_ON);
    vis_BeamSectSetParami(beamsect, BEAMSECT_AXESBASIC, VIS_ON);
    vis_BeamSectSetParami(beamsect, BEAMSECT_AXESPRINCIPAL, VIS_ON);

    /* create beam element object and set objects */
    beamelem = vis_BeamElemBegin();
    vis_BeamElemSetObject(beamelem, VGL_DRAWFUN, df);
    vis_BeamElemSetObject(beamelem, VIS_VISCONTEXT, vc);
    vis_BeamElemSetObject(beamelem, VIS_COLORMAP, cmap);
    vis_BeamElemSetObject(beamelem, VIS_BEAMSECT, beamsect);
    vis_BeamElemSetParami(beamelem, BEAMELEM_SECT, VIS_ON);

    vis_BeamElemSetTopology(beamelem, VIS_SHAPELINE, 3);
    factors[0] = 1.;
    factors[1] = .5;
    vis_BeamElemSetEndFactors(beamelem, factors);

    /* draw */
    /* three beam types */
    for (k = 0; k < 3; k++) {
        /* define TEE section */
        if (k == 0) {
            strcpy(text, "TEE Beam Element");
            vis_BeamSectDef(beamsect, BEAMSECT_TEE);
            vis_BeamSectSetDimensions(beamsect, dimes);
            /* define general GEOMETRY section */
        }
        else if (k == 1) {
            strcpy(text, "GEOMETRY Beam Element");
            vis_BeamSectDef(beamsect, BEAMSECT_GEOMETRY);
            for (i = 1; i <= 6; i++) {
                vis_BeamSectSetPoint(beamsect, i, xp[i - 1]);
            }
            vis_BeamSectSetLoop(beamsect, 1, 1, 3, ix[0]);
            vis_BeamSectSetLoop(beamsect, 2, 0, 3, ix[1]);
            /* use outer loop as closed loop polyline */
            vis_BeamSectSetPolyLine(beamsect, 1, VIS_ON, 3, ix[0]);
            /* define connected SEGMENTS section */
        }
        else if (k == 2) {
            strcpy(text, "SEGMENTS Beam Element");
            vis_BeamSectDef(beamsect, BEAMSECT_SEGMENTS);
            vis_BeamSectSetSegments(beamsect, 5, ts, xs);
        }

        vis_VisContextSetMapColor(vc, VIS_ON);
        vis_BeamSectSetParami(beamsect, BEAMSECT_POLYLINE, VIS_OFF);
        /* 5 beam drawing styles */
        for (j = 0; j < 5; j++) {
            if (j == 0) {
                vis_VisContextSetElemLoc(vc, VIS_ELEMLOC_CENTROID);
                vis_VisContextSetElemRep(vc, VIS_ELEMREP_SEMI);
            }
            else if (j == 1) {
                vis_VisContextSetElemLoc(vc, VIS_ELEMLOC_CORNERS);
                vis_VisContextSetElemRep(vc, VIS_ELEMREP_SEMI);
            }
            else if (j == 2) {
                vis_VisContextSetElemLoc(vc, VIS_ELEMLOC_NODES);
                vis_VisContextSetElemRep(vc, VIS_ELEMREP_SEMI);
            }
            else if (j == 3) {
                vis_VisContextSetElemRep(vc, VIS_ELEMREP_SOLID);
            }
            else if (j == 4) {
                vis_VisContextSetElemRep(vc, VIS_ELEMREP_SOLID);
                vis_VisContextSetMapColor(vc, VIS_OFF);
                vis_BeamSectSetParami(beamsect, BEAMSECT_POLYLINE, VIS_ON);
            }
            /* rotate 10 times */
            for (i = 0; i < 10; i++) {
                GLWinClear(glwin);
                GLWinColor(glwin, ctex);
                GLWinText(glwin, xtex, text);
                GLWinXfmPush(glwin);
                GLWinRotate(glwin, i * 4.F, 'x');
                GLWinRotate(glwin, i * 12.F, 'y');
                vis_BeamElemCurv(beamelem, xbeam, VIS_NODATA, NULL, VIS_NODATA, NULL);
                GLWinXfmPop(glwin);
                GLWinSwap(glwin);
                sleep(1);
            }
        }
    }
    sleep(5);

    /* free all objects */
    vgl_DrawFunEnd(df);
    vis_VisContextEnd(vc);
    vis_ColorMapEnd(cmap);
    vis_LevelsEnd(levels);
    vis_BeamSectEnd(beamsect);
    vis_BeamElemEnd(beamelem);
    GLWinEnd(glwin);
    return 0;
}
../../_images/vistools-exam13b1.gif

Figure 14-13b1, TEE Beam Element, End Point Sections and Reference Axis

../../_images/vistools-exam13b2.gif

Figure 14-13b2, TEE Beam Element, End Point Sections and Element Exterior

15.27. Example 13c, Compute and Plot Strain on a TEE Beam Section

This example extends Example 13 to illustrate stress and strain recovery across a beam section given the centroidal strains, curvatures and twist. A component of the computed strain is contour plotted across the section. The nodes (quality points) and elements (quality parabolic Lagrange triangles) of the internal finite element mesh are used for the stress and strain recovery and contouring process. Note that adaptive error refinement has been enabled. Once the beam section properties have been computed using vis_BeamSectProps() the number of quality points and elements is returned using vis_BeamSectGetNum(). The stress and strain is computed for each quality point using vis_BeamSectStrsStrn() and the ezx component of strain is stored for each point. Then the quality triangles are traversed and the ezx strain is contoured for each triangle.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

#include "glwin.h"

static Vfloat rgb[9][3] = {{.5f, .5f, .5f}, {1., 0., 0.}, {0., 1., 0.},    {0., 0., 1.}, {0., 1., 1.},
                           {1., 0., 1.},    {1., 1., 0.}, {.2f, .2f, .2f}, {1., 1., 1.}};

static Vfloat xtex[3] = {-1.8f, 1.8f, 0.};
static Vfloat ctex[3] = {1., 1., 1.};

/*----------------------------------------------------------------------
                      Compute and Plot Strain on a TEE Beam Section
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun* df;
    vis_VisContext* vc;
    vis_ColorMap* cmap;
    vis_Levels* levels;
    vis_BeamSect* beamsect;
    vis_Contour* contour;
    GLWin* glwin;

    Vint i, j;
    Vfloat dimes[5];
    Vfloat x[3], tm[3][3];
    Vfloat elas[2];
    Vint npoints, nloops, nlines, ntris, nqualpnts, nqualtris;
    Vfloat eks[6], strs[6], strn[6];
    Vfloat st[6], xt[6][3];
    Vfloat *stptr, stmin = 0, stmax = 0;
    Vint ix[6], mid;
    Vfloat props[BEAMSECT_MAXPROPS], dmat[21];
    Vdouble err;

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 200, 200, 600, 600);
    GLWinOrtho(glwin, -2., 2., -2., 2., -2., 2.);

    /* create draw function object for GL */
    df = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, df);

    vc = vis_VisContextBegin();
    vis_VisContextSetColor(vc, 0);
    vis_VisContextSetXYZColor(vc, 1, 2, 3);
    vis_VisContextSetABCColor(vc, 8, 7, 6);
    vis_VisContextSetEdge(vc, VIS_ON);
    vis_VisContextSetFill(vc, VIS_OFF);
    vis_VisContextSetSize(vc, .5);
    vis_VisContextSetMinorSize(vc, .2f);
    vis_VisContextSetMapColor(vc, VIS_ON);
    vis_VisContextSetIsoValType(vc, VIS_ISOVALTONE);

    /* levels for beam section */
    levels = vis_LevelsBegin();
    vis_LevelsDef(levels, LEVELS_LINEAR, 7);

    /* color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetType(cmap, COLORMAP_TRUECOLOR);
    vis_ColorMapSetRGB(cmap, 9, 0, rgb);

    /* create contour object and set objects */
    contour = vis_ContourBegin();
    vis_ContourSetObject(contour, VGL_DRAWFUN, df);
    vis_ContourSetObject(contour, VIS_VISCONTEXT, vc);
    vis_ContourSetObject(contour, VIS_COLORMAP, cmap);
    vis_ContourSetObject(contour, VIS_LEVELS, levels);

    /* create beamsect object and set objects */
    beamsect = vis_BeamSectBegin();
    vis_BeamSectSetObject(beamsect, VGL_DRAWFUN, df);
    vis_BeamSectSetObject(beamsect, VIS_VISCONTEXT, vc);
    vis_BeamSectSetObject(beamsect, VIS_COLORMAP, cmap);
    vis_BeamSectSetObject(beamsect, VIS_LEVELS, levels);

    /* define TEE section */
    vis_BeamSectDef(beamsect, BEAMSECT_TEE);
    dimes[0] = 3.;
    dimes[1] = 2.;
    dimes[2] = .1f;
    dimes[3] = .3f;
    dimes[4] = .2f;
    vis_BeamSectSetDimensions(beamsect, dimes);

    /* set elastic properties */
    elas[0] = 10000000.;
    elas[1] = .3f;
    mid = 1;
    vis_BeamSectSetElasProp(beamsect, mid, SYS_MAT_ISOTROPIC, elas);
    /* option to draw quality grid edges */
    vis_BeamSectSetParami(beamsect, BEAMSECT_QUALITYGRID, SYS_ON);
    /* option to enable adaptive error refinement,
       set to .5 percent */
    vis_BeamSectSetParami(beamsect, BEAMSECT_REFINE, SYS_ON);
    vis_BeamSectSetParamd(beamsect, BEAMSECT_ERRORTOL, .005);

    /* compute section properties */
    vis_BeamSectProps(beamsect);
    vis_BeamSectGetProps(beamsect, props, dmat);
    /* print section properties */
    printf("\n");
    printf("A   = %f\n", props[0]);
    printf("Iyy = %f\n", props[1]);
    printf("Izz = %f\n", props[2]);
    printf("Iyz = %f\n", props[3]);
    printf("Ang = %f\n", props[4]);
    printf("J   = %f\n", props[5]);
    printf("Asy = %f\n", props[6]);
    printf("Asz = %f\n", props[7]);
    printf("Asyz= %f\n", props[8]);
    printf("Ey  = %f\n", props[9]);
    printf("Ez  = %f\n", props[10]);
    printf("Dsy = %f\n", props[11]);
    printf("Dsz = %f\n", props[12]);
    printf("Cw  = %f\n", props[13]);
    printf("Ny  = %f\n", props[14]);
    printf("Nz  = %f\n", props[15]);

    /* retrieve error */
    vis_BeamSectGetDouble(beamsect, BEAMSECT_ERROR, &err);
    printf("error= %e\n", err);

    /* draw */
    GLWinClear(glwin);
    GLWinColor(glwin, ctex);
    GLWinText(glwin, xtex, "TEE Beam Section");
    /* set position */
    x[0] = 0.;
    x[1] = 0.;
    x[2] = 0.;
    /* set orientation - x' out, y' right, z' up */
    tm[0][0] = 0.;
    tm[0][1] = 0.;
    tm[0][2] = 1.;
    tm[1][0] = 1.;
    tm[1][1] = 0.;
    tm[1][2] = 0.;
    tm[2][0] = 0.;
    tm[2][1] = 1.;
    tm[2][2] = 0.;

    /* set centroidal strain, curvature, twist */
    eks[0] = .001f;
    eks[1] = .002f;
    eks[2] = .003f;
    eks[3] = .004f;
    eks[4] = .005f;
    eks[5] = .006f;
    /* determine number of quality points and triangles */
    vis_BeamSectGetNum(beamsect, &npoints, &nloops, &nlines, &ntris, &nqualpnts, &nqualtris);

    /* allocate memory */
    stptr = (Vfloat*)malloc(sizeof(Vfloat) * nqualpnts);

    /* evaluate stress and strain at each quality point */
    for (i = 1; i <= nqualpnts; i++) {
        vis_BeamSectStrsStrn(beamsect, i, eks, strs, strn);
        /* plot ezx strain */
        stptr[i - 1] = strn[5];
        if (i == 1) {
            stmin = stptr[i - 1];
            stmax = stptr[i - 1];
        }
        else {
            if (stptr[i - 1] < stmin)
                stmin = stptr[i - 1];
            if (stptr[i - 1] > stmax)
                stmax = stptr[i - 1];
        }
    }
    /* set minimum and maximum in Levels for contouring */
    vis_LevelsSetMinMax(levels, stmin, stmax);
    vis_LevelsGenerate(levels, LEVELS_PADNONE);

    vis_ContourSetTopology(contour, VIS_SHAPETRI, 3, 0);

    /* loop through triangles */
    for (i = 1; i <= nqualtris; i++) {
        vis_BeamSectGetQualTri(beamsect, i, ix, &mid);
        for (j = 0; j < 6; j++) {
            vis_BeamSectGetPoint(beamsect, ix[j], xt[j]);
            xt[j][2] = 0.;
            st[j] = stptr[ix[j] - 1];
        }
        vis_ContourCurv(contour, st, xt, VIS_NODATA, NULL);
    }
    vis_BeamSectDraw(beamsect, x, tm, VIS_OFF);

    GLWinSwap(glwin);
    sleep(10);
    /* free memory */
    free(stptr);
    /* free all objects */
    vgl_DrawFunEnd(df);
    vis_VisContextEnd(vc);
    vis_ColorMapEnd(cmap);
    vis_LevelsEnd(levels);
    vis_BeamSectEnd(beamsect);
    vis_ContourEnd(contour);
    GLWinEnd(glwin);
    return 0;
}
../../_images/vistools-exam13c.gif

Figure 14-13c, TEE Beam Section, Contour Plot of ezx

15.28. Example 13d, Contour Stress on a TEE Beam Element

This example extends Example 13 to illustrate contouring a scalar quantity, in this case axial stress, on a TEE section beam element. Contouring is performed on two representations of the beam element; 1) the complete outer surface including the end sections and 2) the polyline representation of the beam element. Contouring on any beam element may be decomposed into drawing any number of straight segments along the beam in which the forces and moments are known. Depending upon the beam theory used the axial stress (and other quantities) may be computed at a section point using the associated forces and moments and the section coordinate of the point. The strategy is to first compute the axial stress at each point defining the section at each end of the beam segment. The function vis_BeamSectGetPoint() is used to query the section point coordinates to be used in the calculation. This example uses a simple formula for axial stress for illustration purposes only.

The axial stress is first contoured over the complete surface of the beam by processing all the loops which define the beam section. Beam element endpoint coordinates are computed and stress is gathered into two data arrays which are then contoured using vis_ContourCurv() for each loop. Care is taken to ensure that the normal to the surface is outward. Stress is contoured on the endpoint sections by looping through the section triangulation and contouring each triangle individually. It may be desirable to enable back face culling in the underlying graphics system when rendering beam elements contoured in this manner.

The axial stress is then contoured on the “polyline” representation of the beam element by looping through the individual polylines and contouring each in a manner similar to processing loops above.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

#include "glwin.h"

static Vfloat rgb[9][3] = {{.5, .5, .5}, {1., 0., 0.}, {0., 1., 0.},    {0., 0., 1.}, {0., 1., 1.},
                           {1., 0., 1.}, {1., 1., 0.}, {.2f, .2f, .2f}, {1., 1., 1.}};

static Vfloat xtex[3] = {-1.8f, 1.8f, 0.};
static Vfloat ctex[3] = {1., 1., 1.};

static Vfloat xbeam[2][3] = {{0., 0., 0.}, {1.5f, .3f, 0.}};

/*----------------------------------------------------------------------
                      Contour Stress on a TEE Beam Element
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun* df;
    vis_VisContext* vc;
    vis_ColorMap* cmap;
    vis_Levels* levels;
    vis_BeamSect* beamsect;
    vis_BeamElem* beamelem;
    vis_Contour* contour;
    GLWin* glwin;

    int i, j, n, nn;
    Vfloat dimes[5];
    Vint npoints, nloops, nlines, ntris, nqualpnts, nqualtris;
    Vfloat xs[2], xb[2][3];
    Vint type, npts, *ix;
    Vint reflectflag;
    Vfloat(*xl)[3], *sl, *s1, *s2;
    Vfloat props[BEAMSECT_MAXPROPS];
    Vfloat dmat[21];
    Vfloat area, iyy, izz;
    Vfloat nx1, my1, mz1;
    Vfloat nx2, my2, mz2;
    Vfloat smin, smax;
    Vfloat st1[3], xt1[3][3];
    Vfloat st2[3], xt2[3][3];

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 200, 200, 400, 400);
    GLWinOrtho(glwin, -2., 2., -2., 2., -2., 2.);

    /* create draw function object for GL */
    df = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, df);

    vc = vis_VisContextBegin();
    vis_VisContextSetShade(vc, VIS_VERTEXSHADE);
    vis_VisContextSetIsoValType(vc, VIS_ISOVALFRINGE);

    /* levels for contouring */
    levels = vis_LevelsBegin();
    vis_LevelsDef(levels, LEVELS_LINEAR, 7);

    /* color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetType(cmap, COLORMAP_TRUECOLOR);
    vis_ColorMapSetRGB(cmap, 9, 0, rgb);

    /* create contour object and set objects */
    contour = vis_ContourBegin();
    vis_ContourSetObject(contour, VGL_DRAWFUN, df);
    vis_ContourSetObject(contour, VIS_VISCONTEXT, vc);
    vis_ContourSetObject(contour, VIS_COLORMAP, cmap);
    vis_ContourSetObject(contour, VIS_LEVELS, levels);

    /* create beamsect object */
    beamsect = vis_BeamSectBegin();

    /* define TEE section */
    vis_BeamSectDef(beamsect, BEAMSECT_TEE);
    dimes[0] = 3.;
    dimes[1] = 2.;
    dimes[2] = .1f;
    dimes[3] = .3f;
    dimes[4] = .2f;
    vis_BeamSectSetDimensions(beamsect, dimes);

    /* compute and retrieve section properties */
    vis_BeamSectProps(beamsect);
    vis_BeamSectGetProps(beamsect, props, dmat);
    area = props[0];
    iyy = props[1];
    izz = props[2];

    /* create beam element object and set objects */
    beamelem = vis_BeamElemBegin();
    vis_BeamElemSetObject(beamelem, VIS_BEAMSECT, beamsect);

    /* straight beam segment */
    vis_BeamElemSetTopology(beamelem, VIS_SHAPELINE, 2);

    /* get number of points and loops */
    vis_BeamSectGetNum(beamsect, &npoints, &nloops, &nlines, &ntris, &nqualpnts, &nqualtris);

    /* allocate memory for possibly all point ids */
    ix = (Vint*)malloc(sizeof(Vint) * npoints);

    /* allocate memory for point stress data at each end */
    s1 = (Vfloat*)malloc(sizeof(Vfloat) * npoints);
    s2 = (Vfloat*)malloc(sizeof(Vfloat) * npoints);

    /* assume some end forces and moments */
    nx1 = 100.;
    my1 = 3.;
    mz1 = 20.;
    nx2 = 100.;
    my2 = 6.;
    mz2 = 40.;
    /* compute stresses */
    smin = smax = 0.;
    for (n = 1; n <= npoints; n++) {
        vis_BeamSectGetPoint(beamsect, n, xs);
        /* first end */
        s1[n - 1] = nx1 / area + my1 * xs[0] / iyy + mz1 * xs[1] / izz;
        if (s1[n - 1] < smin)
            smin = s1[n - 1];
        if (s1[n - 1] > smax)
            smax = s1[n - 1];

        /* second end */
        s2[n - 1] = nx2 / area + my2 * xs[0] / iyy + mz2 * xs[1] / izz;
        if (s2[n - 1] < smin)
            smin = s2[n - 1];
        if (s2[n - 1] > smax)
            smax = s2[n - 1];
    }
    /* generate contour levels */
    vis_LevelsSetMinMax(levels, smin, smax);
    vis_LevelsGenerate(levels, LEVELS_PADNONE);

    /* allocate memory for local stress and coordinate arrays */
    sl = (Vfloat*)malloc(sizeof(Vfloat) * 2 * (npoints + 1));
    xl = (Vfloat(*)[3])malloc(3 * sizeof(Vfloat) * 2 * (npoints + 1));

    /* rotate display 30 times */
    /* contour the complete surface of the beam */
    for (i = 0; i < 30; i++) {
        GLWinClear(glwin);
        GLWinColor(glwin, ctex);
        GLWinText(glwin, xtex, "TEE Beam Complete Loop Surface Contour");
        GLWinXfmPush(glwin);
        GLWinRotate(glwin, i * 4.F, 'x');
        GLWinRotate(glwin, i * 12.F, 'y');
        GLWinRotate(glwin, i * 6.F, 'z');

        /* loop over loops, the first loop is the outer loop */
        for (j = 1; j <= nloops; j++) {
            vis_BeamSectGetLoop(beamsect, j, &type, &npts, ix);
            vis_ContourSetTopology(contour, VIS_SHAPEQUAD, 2, npts + 1);
            reflectflag = (j == 1);
            for (n = 0; n <= npts; n++) {
                nn = n % npts;

                /* compute coordinates */
                vis_BeamElemCoords(beamelem, ix[nn], reflectflag, xbeam, VIS_NODATA, NULL, VIS_NODATA, NULL, &xl[2 * n]);

                /* gather stress */
                if (reflectflag) {
                    sl[2 * n + 1] = s1[ix[nn] - 1];
                    sl[2 * n] = s2[ix[nn] - 1];
                }
                else {
                    sl[2 * n] = s1[ix[nn] - 1];
                    sl[2 * n + 1] = s2[ix[nn] - 1];
                }
            }
            vis_ContourCurv(contour, sl, xl, VIS_NODATA, NULL);
        }

        /* cap ends, loop over tris */
        vis_ContourSetTopology(contour, VIS_SHAPETRI, 2, 0);
        for (j = 1; j <= ntris; j++) {
            vis_BeamSectGetTri(beamsect, j, ix);
            for (n = 0; n < 3; n++) {
                vis_BeamElemCoords(beamelem, ix[n], 0, xbeam, VIS_NODATA, NULL, VIS_NODATA, NULL, xb);
                /* invert first end to point outward */
                xt1[2 - n][0] = xb[0][0];
                xt1[2 - n][1] = xb[0][1];
                xt1[2 - n][2] = xb[0][2];
                st1[2 - n] = s1[ix[n] - 1];
                /* second end is already pointed outward */
                xt2[n][0] = xb[1][0];
                xt2[n][1] = xb[1][1];
                xt2[n][2] = xb[1][2];
                st2[n] = s2[ix[n] - 1];
            }
            vis_ContourCurv(contour, st1, xt1, VIS_NODATA, NULL);
            vis_ContourCurv(contour, st2, xt2, VIS_NODATA, NULL);
        }

        GLWinXfmPop(glwin);
        GLWinSwap(glwin);
        sleep(1);
    }
    sleep(5);
    /* rotate display 30 times */
    /* contour the polyline representation of the beam */
    for (i = 0; i < 30; i++) {
        GLWinClear(glwin);
        GLWinColor(glwin, ctex);
        GLWinText(glwin, xtex, "TEE Beam PolyLine Surface Contour");
        GLWinXfmPush(glwin);
        GLWinRotate(glwin, i * 4.F, 'x');
        GLWinRotate(glwin, i * 12.F, 'y');
        GLWinRotate(glwin, i * 6.F, 'z');

        /* loop over polylines */
        for (j = 1; j <= nlines; j++) {
            vis_BeamSectGetPolyLine(beamsect, j, &type, &npts, ix);
            for (n = 0; n < npts; n++) {
                /* compute coordinates */
                vis_BeamElemCoords(beamelem, ix[n], 0, xbeam, VIS_NODATA, NULL, VIS_NODATA, NULL, &xl[2 * n]);

                /* gather stress */
                sl[2 * n] = s1[ix[n] - 1];
                sl[2 * n + 1] = s2[ix[n] - 1];
            }
            /* close polyline if necessary */
            if (type == VIS_ON) {
                vis_ContourSetTopology(contour, VIS_SHAPEQUAD, 2, npts + 1);
                vis_BeamElemCoords(beamelem, ix[0], 0, xbeam, VIS_NODATA, NULL, VIS_NODATA, NULL, &xl[2 * npts]);
                sl[2 * npts] = s1[ix[0] - 1];
                sl[2 * npts + 1] = s2[ix[0] - 1];
            }
            else {
                vis_ContourSetTopology(contour, VIS_SHAPEQUAD, 2, npts);
            }
            vis_ContourCurv(contour, sl, xl, VIS_NODATA, NULL);
        }

        GLWinXfmPop(glwin);
        GLWinSwap(glwin);
        sleep(1);
    }
    sleep(5);
    /* free allocated memory */
    free(ix);
    free(s1);
    free(s2);
    free(sl);
    free(xl);
    /* free all objects */
    vgl_DrawFunEnd(df);
    vis_VisContextEnd(vc);
    vis_ColorMapEnd(cmap);
    vis_LevelsEnd(levels);
    vis_BeamSectEnd(beamsect);
    vis_BeamElemEnd(beamelem);
    vis_ContourEnd(contour);
    GLWinEnd(glwin);
    return 0;
}

15.29. Example 13e, Draw TEE Beam Element Bending Moment Diagram

This example extends Example 13 to draw a contoured diagram of a scalar field, such as a bending moment diagram, on a beam element. The diagram is drawn along the beam element local y’ axis using vis_BeamElemDiagram(). It is superimposed on a beam element drawn using vis_BeamElemCurv().

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

#include "glwin.h"

static Vfloat rgb[9][3] = {{.5, .5, .5}, {1., 0., 0.}, {0., 1., 0.},    {0., 0., 1.}, {0., 1., 1.},
                           {1., 0., 1.}, {1., 1., 0.}, {.2f, .2f, .2f}, {1., 1., 1.}};

static Vfloat xtex[3] = {-1.8f, 1.8f, 0.};
static Vfloat ctex[3] = {1., 1., 1.};

static Vfloat xbeam[3][3] = {{-1.5f, .3f, 0.}, {0., 0., 0.}, {1.5f, .3f, 0.}};
static Vfloat sbeam[3] = {5., 3., 8.};

/*----------------------------------------------------------------------
                      Draw TEE Beam Element Bending Moment Diagram
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun* df;
    vis_VisContext* vc;
    vis_ColorMap* cmap;
    vis_Levels* levels;
    vis_BeamSect* beamsect;
    vis_BeamElem* beamelem;
    GLWin* glwin;

    int i, j;
    Vfloat dimes[5];
    Vfloat factors[2];

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 200, 200, 400, 400);
    GLWinOrtho(glwin, -2., 2., -2., 2., -2., 2.);

    /* create draw function object for GL */
    df = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, df);

    vc = vis_VisContextBegin();
    vis_VisContextSetColor(vc, 0);
    vis_VisContextSetMinorColor(vc, 8);
    vis_VisContextSetXYZColor(vc, 1, 2, 3);
    vis_VisContextSetABCColor(vc, 8, 7, 6);
    vis_VisContextSetEdge(vc, VIS_ON);
    vis_VisContextSetFill(vc, VIS_ON);
    vis_VisContextSetSize(vc, 1.);
    vis_VisContextSetMinorSize(vc, .2f);
    vis_VisContextSetMapColor(vc, VIS_ON);
    vis_VisContextSetMapSize(vc, VIS_ON);
    vis_VisContextSetRefinement(vc, 2);
    vis_VisContextSetShade(vc, VIS_VERTEXSHADE);
    vis_VisContextSetMarkerType(vc, VIS_BOX);
    vis_VisContextSetIsoValType(vc, VIS_ISOVALFRINGE);

    /* levels for beam section */
    levels = vis_LevelsBegin();
    vis_LevelsDef(levels, LEVELS_LINEAR, 7);
    vis_LevelsSetMinMax(levels, 2., 8.);
    vis_LevelsGenerate(levels, LEVELS_PADNONE);

    /* color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetType(cmap, COLORMAP_TRUECOLOR);
    vis_ColorMapSetRGB(cmap, 9, 0, rgb);

    /* create beamsect object and set objects */
    beamsect = vis_BeamSectBegin();
    vis_BeamSectSetObject(beamsect, VGL_DRAWFUN, df);
    vis_BeamSectSetObject(beamsect, VIS_VISCONTEXT, vc);
    vis_BeamSectSetObject(beamsect, VIS_COLORMAP, cmap);
    vis_BeamSectSetObject(beamsect, VIS_LEVELS, levels);

    /* set display parameters */
    vis_BeamSectSetParami(beamsect, BEAMSECT_CENTROID, BEAMSECT_CENTROID_SPHERE);
    vis_BeamSectSetParami(beamsect, BEAMSECT_SHEARCENTER, VIS_ON);
    vis_BeamSectSetParami(beamsect, BEAMSECT_AXESBASIC, VIS_ON);
    vis_BeamSectSetParami(beamsect, BEAMSECT_AXESPRINCIPAL, VIS_ON);

    /* define TEE section */
    vis_BeamSectDef(beamsect, BEAMSECT_TEE);
    dimes[0] = 3.;
    dimes[1] = 2.;
    dimes[2] = .1f;
    dimes[3] = .3f;
    dimes[4] = .2f;
    vis_BeamSectSetDimensions(beamsect, dimes);

    /* create beam element object and set objects */
    beamelem = vis_BeamElemBegin();
    vis_BeamElemSetObject(beamelem, VGL_DRAWFUN, df);
    vis_BeamElemSetObject(beamelem, VIS_VISCONTEXT, vc);
    vis_BeamElemSetObject(beamelem, VIS_COLORMAP, cmap);
    vis_BeamElemSetObject(beamelem, VIS_BEAMSECT, beamsect);
    vis_BeamElemSetObject(beamelem, VIS_LEVELS, levels);
    vis_BeamElemSetParami(beamelem, BEAMELEM_SECT, VIS_ON);

    vis_BeamElemSetTopology(beamelem, VIS_SHAPELINE, 3);
    factors[0] = 1.;
    factors[1] = .5;
    vis_BeamElemSetEndFactors(beamelem, factors);

    /* draw */
    for (j = 0; j < 5; j++) {
        if (j == 0) {
            vis_VisContextSetElemLoc(vc, VIS_ELEMLOC_CENTROID);
            vis_VisContextSetElemRep(vc, VIS_ELEMREP_SEMI);
        }
        else if (j == 1) {
            vis_VisContextSetElemLoc(vc, VIS_ELEMLOC_CORNERS);
            vis_VisContextSetElemRep(vc, VIS_ELEMREP_SEMI);
        }
        else if (j == 2) {
            vis_VisContextSetElemLoc(vc, VIS_ELEMLOC_NODES);
            vis_VisContextSetElemRep(vc, VIS_ELEMREP_SEMI);
        }
        else if (j == 3) {
            vis_VisContextSetElemRep(vc, VIS_ELEMREP_SOLID);
        }
        else if (j == 4) {
            vis_VisContextSetElemRep(vc, VIS_ELEMREP_SOLID);
            vis_VisContextSetMapColor(vc, VIS_OFF);
            vis_BeamSectSetParami(beamsect, BEAMSECT_POLYLINE, VIS_ON);
        }

        for (i = 0; i < 10; i++) {
            GLWinClear(glwin);
            GLWinColor(glwin, ctex);
            GLWinText(glwin, xtex, "TEE Beam Element");
            GLWinXfmPush(glwin);
            GLWinRotate(glwin, i * 4.F, 'x');
            GLWinRotate(glwin, i * 12.F, 'y');
            /* draw diagram along y' axis */
            vis_BeamElemDiagram(beamelem, sbeam, SYS_YAXIS, xbeam, VIS_NODATA, NULL, VIS_NODATA, NULL);
            /* draw beam */
            vis_BeamElemCurv(beamelem, xbeam, VIS_NODATA, NULL, VIS_NODATA, NULL);
            GLWinXfmPop(glwin);
            GLWinSwap(glwin);
            sleep(1);
        }
    }
    sleep(5);

    /* free all objects */
    vgl_DrawFunEnd(df);
    vis_VisContextEnd(vc);
    vis_ColorMapEnd(cmap);
    vis_LevelsEnd(levels);
    vis_BeamSectEnd(beamsect);
    vis_BeamElemEnd(beamelem);
    GLWinEnd(glwin);
    return 0;
}

15.30. Example 13f, Compute Cross-section Properties for Composite Beam

This example generates a L-shaped composite beam cross-section made of 3 different material properties. The different material properties are displayed in Figure 13-13f below.

Because of the discontinuity in material properties, stress and strain recovery is done on an element-by-element basis. The results are printed and saved to a SDRC Universal file for further visualization.

../../_images/vistools-exam13f.gif

Figure 14-13f, TEE Beam Section, Contour Plot of ezx

#include <stdio.h>
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

static Vdouble vy[3] = {0., 1., 0.};
static Vdouble vz[3] = {0., 0., 1.};
static Vdouble origin[3] = {0., 0., 0.};

static Vint loop[3][4] = {{1, 2, 5, 8}, {2, 3, 4, 5}, {5, 6, 7, 8}};
static Vdouble elast[3][2] = {{1.e+7, 0.1}, {2.e+6, 0.2}, {3.e+7, 0.3}};
static Vdouble x[8][3] = {{0., 0., 0.}, {1., 0., 0.}, {5., 0., 0.}, {5., 2., 0.},
                          {1., 2., 0.}, {1., 4., 0.}, {0., 4., 0.}, {0., 2., 0.}};

/*----------------------------------------------------------------------
                      Compute Composite Beam Section Properties
----------------------------------------------------------------------*/
int
main()
{
    vis_BeamSect* beamsect;
    vis_Connect* connect;
    vis_State *states, *statee;
    vis_RProp *rprops, *rprope;
    vis_GridFun* gridfun;
    Vdouble eks[6], strs[36], strn[36];
    Vint i, j, n;
    Vdouble props[BEAMSECT_MAXPROPS], dmat[21], xp[3];
    Vint ix[6], mid;
    Vint npoints, nloops, nlines, ntris, nqualpnts, nqualtris;

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* instance BeamSect for comparison */
    beamsect = vis_BeamSectBegin();

    /* generate data in arbitrary coordinates */
    vis_BeamSectDef(beamsect, BEAMSECT_GEOMETRY);
    for (n = 1; n <= 8; n++) {
        vis_BeamSectSetPointdv(beamsect, n, x[n - 1]);
    }
    for (n = 1; n <= 3; n++) {
        mid = n;
        vis_BeamSectSetLoop(beamsect, n, mid, 4, loop[n - 1]);
        vis_BeamSectSetElasPropdv(beamsect, mid, SYS_MAT_ISOTROPIC, elast[n - 1]);
    }
    vis_BeamSectSetParami(beamsect, BEAMSECT_VABS, SYS_ON);
    vis_BeamSectProps(beamsect);
    vis_BeamSectGetPropsdv(beamsect, props, dmat);

    /* print Timoshenko stiffness matrix */
    for (n = 0, i = 0; i < 6; i++) {
        for (j = 0; j <= i; j++, n++) {
            printf("%11.4e ", dmat[n]);
        }
        printf("\n");
    }
    /* determine number of quality points and triangles */
    vis_BeamSectGetNum(beamsect, &npoints, &nloops, &nlines, &ntris, &nqualpnts, &nqualtris);

    /* save model to IDEAS Universal file */
    connect = vis_ConnectBegin();
    vis_ConnectDef(connect, nqualpnts, nqualtris);
    for (n = 1; n <= nqualpnts; n++) {
        vis_BeamSectCoordsdv(beamsect, n, origin, vy, vz, xp);
        vis_ConnectSetCoordsdv(connect, n, xp);
    }
    for (n = 1; n <= nqualtris; n++) {
        vis_BeamSectGetQualTri(beamsect, n, ix, &mid);
        vis_ConnectSetTopology(connect, n, SYS_SHAPETRI, 3, 0, 0);
        vis_ConnectSetElemNode(connect, n, ix);
        vis_ConnectSetElemAssoc(connect, VIS_MATLID, n, mid);
    }
    vis_ConnectWrite(connect, SYS_SDRC_UNIVERSAL, "exam13f.unv");

    /* set stress and strain states */
    gridfun = vis_GridFunBegin();
    vis_ConnectGridFun(connect, gridfun);

    statee = vis_StateBegin();
    vis_StateSetObject(statee, VIS_GRIDFUN, (Vobject*)gridfun);
    vis_StateDef(statee, nqualtris, SYS_ELEM, SYS_NODE, SYS_TENSOR);
    rprope = vis_RPropBegin();
    vis_RPropSetType(rprope, SYS_RES_E);
    vis_RPropSetIds(rprope, 1, 0, 0);

    states = vis_StateBegin();
    vis_StateSetObject(states, VIS_GRIDFUN, (Vobject*)gridfun);
    vis_StateDef(states, nqualtris, SYS_ELEM, SYS_NODE, SYS_TENSOR);
    rprops = vis_RPropBegin();
    vis_RPropSetType(rprops, SYS_RES_S);
    vis_RPropSetIds(rprops, 1, 0, 0);

    /* set centroidal strain, curvature, twist */
    eks[0] = .001;
    eks[1] = .002;
    eks[2] = .003;
    eks[3] = .004;
    eks[4] = .005;
    eks[5] = .006;
    /* evaluate stress and strain at each quality element */
    for (n = 1; n <= nqualtris; n++) {
        vis_BeamSectGetQualTri(beamsect, n, ix, &mid);
        vis_BeamSectElemStrsStrndv(beamsect, n, eks, strs, strn);
        printf("element= %d, mid= %d\n", n, mid);
        for (i = 0; i < 6; ++i) {
            printf("   node= %d\n", i + 1);
            printf("      strain= %11.4e %11.4e %11.4e %11.4e %11.4e %11.4e\n", strn[6 * i], strn[6 * i + 1], strn[6 * i + 2],
                   strn[6 * i + 3], strn[6 * i + 4], strn[6 * i + 5]);
            printf("      stress= %11.4e %11.4e %11.4e %11.4e %11.4e %11.4e\n", strs[6 * i], strs[6 * i + 1], strs[6 * i + 2],
                   strs[6 * i + 3], strs[6 * i + 4], strs[6 * i + 5]);
            vis_StateSetDatadv(statee, n, strn);
            vis_StateSetDatadv(states, n, strs);
        }
    }
    vis_StateWrite(statee, rprope, SYS_SDRC_UNIVERSAL, "exam13f.unv");
    vis_StateWrite(states, rprops, SYS_SDRC_UNIVERSAL, "exam13f.unv");

    /* clean up*/
    vis_StateEnd(statee);
    vis_StateEnd(states);
    vis_RPropEnd(rprope);
    vis_RPropEnd(rprops);
    vis_GridFunEnd(gridfun);
    vis_ConnectEnd(connect);
    vis_BeamSectEnd(beamsect);
    return 0;
}

15.31. Example 13g, Draw TEE Beam Element with Local Axis Orientations

This example illustrates the various options for orienting beam element cross sections. There are two basic methods for orienting beam cross sections. For prismatic beams with the plane of the cross sections perpendicular to the axis of the beam, define an element local system using vis_BeamElemSetLocalSystem(). For twisted beams or beams with the plane of the cross sections not perpendicular to the beam axis, use the cross section orientation vectors in the call to vis_BeamElemCurv(). If the optional cross section orientation vectors in vis_BeamElemCurv() are used, the local element system defined using vis_BeamElemSetLocalSystem() is ignored.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

#include "glwin.h"

static Vfloat rgb[9][3] = {{.5, .5, .5}, {1., 0., 0.}, {0., 1., 0.},    {0., 0., 1.}, {0., 1., 1.},
                           {1., 0., 1.}, {1., 1., 0.}, {.2f, .2f, .2f}, {1., 1., 1.}};

static Vfloat xtex[3] = {-1.8f, 1.8f, 0.};
static Vfloat ctex[3] = {1., 1., 1.};

/* beam element node point locations */
static Vfloat xbeam[2][3] = {{-1.0, .3f, 0.}, {1.0f, .3f, 0.}};

/* dimensions of TEE */
static Vfloat dimes[5] = {3., 2., .1f, .3f, .2f};

/* dimensions of geometry */
static Vfloat xp[6][2] = {{0.2f, 0.2f}, {0.4f, 0.2f}, {0.6f, 0.2f}, {0.6f, 0.4f}, {0.4f, 0.4f}, {0.2f, 0.4f}};
static Vint ix[6] = {1, 2, 3, 4, 5, 6};
/* 3 orientations of beam element axis */
static Vfloat mbeam[3][2][3] = {
{{-1.0, .3f, 0.}, {1.0, .3f, 0}}, {{0.3f, 1., 0.}, {0.3f, -1., 0}}, {{1.0, .3f, 1.}, {1.0, .3f, -1.}}};

/*----------------------------------------------------------------------
                      Draw TEE Beam Element with Local Axis Orientations
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun* df;
    vis_VisContext* vc;
    vis_ColorMap* cmap;
    vis_Levels* levels;
    vis_BeamSect* beamsect;
    vis_BeamElem* beamelem;
    GLWin* glwin;

    int i, k;
    Vfloat vec[3];
    Vfloat v1[2][3], v2[2][3];
    Vchar text[65];

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 200, 200, 400, 400);
    GLWinOrtho(glwin, -2., 2., -2., 2., -3., 3.);

    /* create draw function object for GL */
    df = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, df);

    vc = vis_VisContextBegin();
    vis_VisContextSetColor(vc, 0);
    vis_VisContextSetXYZColor(vc, 1, 2, 3);
    vis_VisContextSetABCColor(vc, 8, 7, 6);
    vis_VisContextSetEdge(vc, VIS_ON);
    vis_VisContextSetFill(vc, VIS_ON);
    vis_VisContextSetSize(vc, .6f);
    vis_VisContextSetMapColor(vc, VIS_ON);
    vis_VisContextSetRefinement(vc, 2);
    vis_VisContextSetShade(vc, VIS_VERTEXSHADE);
    vis_VisContextSetMarkerType(vc, VIS_BOX);
    vis_VisContextSetElemRep(vc, VIS_ELEMREP_SOLID);
    vis_VisContextSetLineWidth(vc, 2);

    /* levels for beam section */
    levels = vis_LevelsBegin();
    vis_LevelsDef(levels, LEVELS_LINEAR, 7);

    /* color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetType(cmap, COLORMAP_TRUECOLOR);
    vis_ColorMapSetRGB(cmap, 9, 0, rgb);

    /* create beamsect object and set objects */
    beamsect = vis_BeamSectBegin();
    vis_BeamSectSetObject(beamsect, VGL_DRAWFUN, df);
    vis_BeamSectSetObject(beamsect, VIS_VISCONTEXT, vc);
    vis_BeamSectSetObject(beamsect, VIS_COLORMAP, cmap);
    vis_BeamSectSetObject(beamsect, VIS_LEVELS, levels);

    /* set display parameters */
    vis_BeamSectSetParami(beamsect, BEAMSECT_AXESBASIC, VIS_ON);

    /* create beam element object and set objects */
    beamelem = vis_BeamElemBegin();
    vis_BeamElemSetObject(beamelem, VGL_DRAWFUN, df);
    vis_BeamElemSetObject(beamelem, VIS_VISCONTEXT, vc);
    vis_BeamElemSetObject(beamelem, VIS_COLORMAP, cmap);
    vis_BeamElemSetObject(beamelem, VIS_BEAMSECT, beamsect);
    vis_BeamElemSetParami(beamelem, BEAMELEM_SECT, VIS_ON);
    vis_BeamElemSetTopology(beamelem, VIS_SHAPELINE, 2);

    vis_BeamSectDef(beamsect, BEAMSECT_TEE);
    vis_BeamSectSetDimensions(beamsect, dimes);

    /* orient beam element local y' axis */
    for (k = 0; k < 3; k++) {
        /* orient along global z axis */
        if (k == 0) {
            vec[0] = 0.;
            vec[1] = 0.;
            vec[2] = 1.;
            vis_BeamElemSetLocalSystem(beamelem, SYS_ELEMSYS_VECTOR, vec, 0.);
            strcpy(text, "Global Z Axis");
            /* orient 30. degrees from global z axis */
        }
        else if (k == 1) {
            vec[0] = 0.;
            vec[1] = 0.;
            vec[2] = 1.;
            vis_BeamElemSetLocalSystem(beamelem, SYS_ELEMSYS_VECTOR, vec, 30.);
            strcpy(text, "30. Degrees from Global Z Axis");
            /* orient along global y axis */
        }
        else if (k == 2) {
            vec[0] = 0.;
            vec[1] = 1.;
            vec[2] = 0.;
            vis_BeamElemSetLocalSystem(beamelem, SYS_ELEMSYS_VECTOR, vec, 0.);
            strcpy(text, "Global Y Axis");
        }
        /* rotate 10 times */
        for (i = 0; i < 10; i++) {
            GLWinClear(glwin);
            GLWinColor(glwin, ctex);
            GLWinText(glwin, xtex, text);
            GLWinXfmPush(glwin);
            GLWinRotate(glwin, i * 4.F, 'x');
            GLWinRotate(glwin, i * 12.F, 'y');
            vis_BeamElemCurv(beamelem, xbeam, VIS_NODATA, NULL, VIS_NODATA, NULL);
            GLWinXfmPop(glwin);
            GLWinSwap(glwin);
            sleep(1);
        }
    }
    /* orient beam element local y' and z' axes */
    for (k = 0; k < 2; k++) {
        /* rotate 15 times */
        for (i = 0; i < 15; i++) {
            GLWinClear(glwin);
            GLWinColor(glwin, ctex);
            GLWinXfmPush(glwin);
            if (k == 0) {
                v1[0][0] = 0.;
                v1[0][1] = 1.;
                v1[0][2] = 0.;
                v1[1][0] = 0.;
                v1[1][1] = 1.;
                v1[1][2] = 1.;
                strcpy(text, "Twisted Beam");
            }
            else if (k == 1) {
                v1[0][0] = 0.;
                v1[0][1] = 1.;
                v1[0][2] = 0.;
                v1[1][0] = 0.;
                v1[1][1] = 1.;
                v1[1][2] = 0.;
                v2[0][0] = -1.;
                v2[0][1] = 0.;
                v2[0][2] = 1.;
                v2[1][0] = +1.;
                v2[1][1] = 0.;
                v2[1][2] = 1.;
                strcpy(text, "Tilted Beam");
            }
            GLWinText(glwin, xtex, text);
            GLWinRotate(glwin, i * 4.F, 'x');
            GLWinRotate(glwin, i * 12.F, 'y');
            /* twisted beam */
            if (k == 0) {
                vis_BeamElemCurv(beamelem, xbeam, VIS_VERTEXDATA, v1, VIS_NODATA, NULL);
                /* tilted beam*/
            }
            else if (k == 1) {
                vis_BeamElemCurv(beamelem, xbeam, VIS_VERTEXDATA, v1, VIS_VERTEXDATA, v2);
            }
            GLWinXfmPop(glwin);
            GLWinSwap(glwin);
            sleep(1);
        }
    }
    /* user defined geometry */
    vis_BeamSectDef(beamsect, BEAMSECT_GEOMETRY);
    for (i = 1; i <= 6; i++) {
        vis_BeamSectSetPoint(beamsect, i, xp[i - 1]);
    }
    vis_BeamSectSetLoop(beamsect, 1, 1, 6, ix);
    /* orient beam element x' axis along global x, y and z */
    for (k = 0; k < 3; k++) {
        /* local x' along global x, local y' along global z */
        if (k == 0) {
            vec[0] = 0.;
            vec[1] = 0.;
            vec[2] = 1.;
            vis_BeamElemSetLocalSystem(beamelem, SYS_ELEMSYS_VECTOR, vec, 0.);
            strcpy(text, "X' along Global X, Y' along Global Z");
            /* local x' along global y, local y' along global x */
        }
        else if (k == 1) {
            vec[0] = 1.;
            vec[1] = 0.;
            vec[2] = 0.;
            vis_BeamElemSetLocalSystem(beamelem, SYS_ELEMSYS_VECTOR, vec, 0.);
            strcpy(text, "X' along Global Y, Y' along Global X");
            /* local x' along global z, local y' along global y */
        }
        else if (k == 2) {
            vec[0] = 0.;
            vec[1] = 1.;
            vec[2] = 0.;
            vis_BeamElemSetLocalSystem(beamelem, SYS_ELEMSYS_VECTOR, vec, 0.);
            strcpy(text, "X' along Global Z, Y' along Global Y");
        }
        /* rotate 10 times */
        for (i = 0; i < 10; i++) {
            GLWinClear(glwin);
            GLWinColor(glwin, ctex);
            GLWinText(glwin, xtex, text);
            GLWinXfmPush(glwin);
            GLWinRotate(glwin, i * 4.F, 'x');
            GLWinRotate(glwin, i * 12.F, 'y');
            vis_BeamElemCurv(beamelem, mbeam[k], VIS_NODATA, NULL, VIS_NODATA, NULL);
            GLWinXfmPop(glwin);
            GLWinSwap(glwin);
            sleep(1);
        }
    }
    sleep(5);

    /* free all objects */
    vgl_DrawFunEnd(df);
    vis_VisContextEnd(vc);
    vis_ColorMapEnd(cmap);
    vis_LevelsEnd(levels);
    vis_BeamSectEnd(beamsect);
    vis_BeamElemEnd(beamelem);
    GLWinEnd(glwin);
    return 0;
}

15.32. Example 14, Compute and Draw a Three Layer Shell Wall

This example illustrates using the ShellWall module to compute and draw a three layer shell laminate. The ShellWall module supports multiple layer laminates in which the user supplies the thickness, material angle and material properties of each layer. The ShellWall module will compute and display the shell wall properties. The geometry of the layers is defined by specifying the locations of a set of points along a line (local shell z axis) using vis_ShellWallSetPoint(). These points should be at the bottom and top surface of the laminate and at the interfaces between the layers. The layers are defined by specifying the point connectivity using vis_ShellWallSetLayer(). Note that the identifiers of all points and layers must be greater than or equal to one. In this example a three layer laminate is defined with four points and a single orthotropic material.

The laminate properties are computed by calling vis_ShellWallProps(). The shell wall is drawn by calling vis_ShellWallDraw(). The appropriate flags have been enabled in the VisContext attribute object to draw a colored line for each layer. The orientation of the local material coordinate system for each layer is drawn by default, the drawing of the basic local coordinate system axes is enabled by calling vis_ShellWallSetParami().

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

#include "glwin.h"

static Vfloat rgb[9][3] = {{.5, .5, .5}, {1., 0., 0.}, {0., 1., 0.},    {0., 0., 1.}, {0., 1., 1.},
                           {1., 0., 1.}, {1., 1., 0.}, {.2f, .2f, .2f}, {1., 1., 1.}};

static Vfloat xtex[3] = {-.8f, .8f, 0.};
static Vfloat ctex[3] = {1., 1., 1.};

/*----------------------------------------------------------------------
                      Compute and Draw 3-Layer Shell Wall
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun* df;
    vis_VisContext* vc;
    vis_ColorMap* cmap;
    vis_Levels* levels;
    vis_ShellWall* shellwall;
    GLWin* glwin;

    Vint i;
    Vfloat x[3], tm[3][3];
    Vint nlayers = 3;
    Vfloat zp[4] = {0., .2f, .6f, .8f};
    Vint ix[2];
    Vfloat phi[3] = {-45., 0., -45.};
    Vfloat mprop[6];

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 200, 200, 400, 400);
    GLWinOrtho(glwin, -1., 1., -1., 1., -1., 1.);

    /* create draw function object for GL */
    df = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, df);

    vc = vis_VisContextBegin();
    vis_VisContextSetABCColor(vc, 0, 0, 0);
    vis_VisContextSetXYZColor(vc, 4, 5, 6);
    vis_VisContextSetLineWidth(vc, 2);
    vis_VisContextSetMinorLineWidth(vc, 2);
    vis_VisContextSetSize(vc, .4f);
    vis_VisContextSetMapColor(vc, VIS_ON);

    /* levels for shell wall */
    levels = vis_LevelsBegin();
    vis_LevelsDef(levels, LEVELS_LINEAR, 7);

    /* color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetType(cmap, COLORMAP_TRUECOLOR);
    vis_ColorMapSetRGB(cmap, 9, 0, rgb);

    /* create shellwall object and set objects */
    shellwall = vis_ShellWallBegin();
    vis_ShellWallSetObject(shellwall, VGL_DRAWFUN, df);
    vis_ShellWallSetObject(shellwall, VIS_VISCONTEXT, vc);
    vis_ShellWallSetObject(shellwall, VIS_COLORMAP, cmap);
    vis_ShellWallSetObject(shellwall, VIS_LEVELS, levels);
    vis_ShellWallSetParami(shellwall, SHELLWALL_AXESBASIC, SYS_ON);

    /* define 3 layer laminate */
    vis_ShellWallDef(shellwall, SHELLWALL_GEOMETRY);
    for (i = 1; i <= nlayers + 1; i++) {
        vis_ShellWallSetPoint(shellwall, i, zp[i - 1]);
    }
    for (i = 1; i <= nlayers; i++) {
        ix[0] = i;
        ix[1] = i + 1;
        vis_ShellWallSetLayer(shellwall, i, ix, phi[i - 1], 1);
    }
    /* define lamina material id 1 */
    mprop[0] = 1000000.;
    mprop[1] = 2000000.;
    mprop[2] = .1f;
    mprop[3] = 500000.;
    mprop[4] = 500000.;
    mprop[5] = 500000.;
    vis_ShellWallSetElasProp(shellwall, 1, VIS_MAT_LAMINA, mprop);

    /* compute wall properties */
    vis_ShellWallProps(shellwall);

    /* set position */
    x[0] = 0.;
    x[1] = 0.;
    x[2] = 0.;
    /* set orientation - x' out, y' right, z' up */
    tm[0][0] = 0.;
    tm[0][1] = 0.;
    tm[0][2] = 1.;
    tm[1][0] = 1.;
    tm[1][1] = 0.;
    tm[1][2] = 0.;
    tm[2][0] = 0.;
    tm[2][1] = 1.;
    tm[2][2] = 0.;

    /* draw */
    GLWinClear(glwin);
    GLWinColor(glwin, ctex);
    GLWinText(glwin, xtex, "3 Layer Shell Wall");
    GLWinRotate(glwin, 20., 'x');
    GLWinRotate(glwin, 60., 'y');
    vis_ShellWallDraw(shellwall, x, tm);
    GLWinSwap(glwin);
    sleep(5);

    /* free all objects */
    vgl_DrawFunEnd(df);
    vis_VisContextEnd(vc);
    vis_ColorMapEnd(cmap);
    vis_LevelsEnd(levels);
    vis_ShellWallEnd(shellwall);
    GLWinEnd(glwin);
    return 0;
}
../../_images/vistools-exam14.gif

Figure 14-14, Three Layer Shell Laminate

15.33. Example 14a, Draw a Three Layer Parabolic Triangular Shell Element

This example extends Example 14 using the ShellWall and ShellElem modules to draw a complete shell element with three layers. The ShellWall object defining the shell wall properties is installed as an attribute object to a ShellElem object. The shell element is a 6 node, parabolic triangular tapered shell.

The six node topology is set using vis_ShellElemSetTopology(). A call to vis_ShellElemSetCornerFactors() defines the overall laminate scale factors at the shell corner points. The laminate scaling is performed linearly between the shell element corner points. The shell element is drawn in five sequences illustrating various combinations of the ElemRep and ElemLoc visualization contexts and enabling the SHELLELEM_WALL parameter.

When drawing assemblies of curved shells it is essential to supply the exact shell node normals to the call to vis_ShellElemCurv(). This ensures that the reconstructed top and bottom surfaces of adjacent shells are conformal. It is also highly recommended to avoid drawing the edges of shell elements which are mated to an adjacent shell and will be obscured by the top and bottom surfaces of the shells. Only the visible edges of shells need be drawn. Use vis_ShellElemSetEdgeFlag() to flag only those edges to be drawn.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

#include "glwin.h"

static Vfloat rgb[9][3] = {{.5, .5, .5}, {1., 0., 0.}, {0., 1., 0.},    {0., 0., 1.}, {0., 1., 1.},
                           {1., 0., 1.}, {1., 1., 0.}, {.2f, .2f, .2f}, {1., 1., 1.}};

static Vfloat xtex[3] = {-.8f, 2.8f, 0.};
static Vfloat ctex[3] = {1., 1., 1.};
/* cylindrical shell midsurface coordinates */
static Vfloat xshell[6][3] = {{0., 0., 0.}, {2., 0., 0.},          {0., 1., 1.},
                              {1., 0., 0.}, {1.f, .7071f, .2928f}, {0.f, .7071f, .2928f}};
/* shell midsurface normals */
static Vfloat vshell[6][3] = {{0., 0., 1.}, {0., 0., 1.},          {0., -1., 0.},
                              {0., 0., 1.}, {0., -.7071f, .7071f}, {0., -.7071f, .7071f}};

/*----------------------------------------------------------------------
                      Draw 3-Layer Parabolic Triangular Shell Element
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun* df;
    vis_VisContext* vc;
    vis_ColorMap* cmap;
    vis_Levels* levels;
    vis_ShellElem* shellelem;
    vis_ShellWall* shellwall;
    GLWin* glwin;

    Vint i, j;
    Vfloat factors[3];
    Vint nlayers = 3;
    Vfloat zp[4] = {0., .02f, .06f, .08f};
    Vint ix[2];
    Vfloat phi[3] = {-45., 0., -45.};
    Vfloat mprop[6];

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 200, 200, 600, 600);
    GLWinOrtho(glwin, -.5, 2.5, -.5, 2.5, -10., 10.);

    /* create draw function object for GL */
    df = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, df);

    vc = vis_VisContextBegin();
    /* surfaces gray */
    vis_VisContextSetColor(vc, 0);
    vis_VisContextSetMinorColor(vc, 0);
    vis_VisContextSetABCColor(vc, 0, 0, 0);

    vis_VisContextSetXYZColor(vc, 1, 2, 3);
    vis_VisContextSetFill(vc, VIS_ON);
    vis_VisContextSetEdge(vc, VIS_OFF);
    vis_VisContextSetSize(vc, .4f);
    vis_VisContextSetMapColor(vc, VIS_ON);
    vis_VisContextSetRefinement(vc, 2);
    vis_VisContextSetScale(vc, 2.);
    vis_VisContextSetShade(vc, VIS_VERTEXSHADE);
    vis_VisContextSetElemRep(vc, VIS_ELEMREP_SOLID);

    /* levels for shell wall */
    levels = vis_LevelsBegin();
    vis_LevelsDef(levels, LEVELS_LINEAR, 7);

    /* color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetType(cmap, COLORMAP_TRUECOLOR);
    vis_ColorMapSetRGB(cmap, 9, 0, rgb);

    /* create shellwall object and set objects */
    shellwall = vis_ShellWallBegin();
    vis_ShellWallSetObject(shellwall, VGL_DRAWFUN, df);
    vis_ShellWallSetObject(shellwall, VIS_VISCONTEXT, vc);
    vis_ShellWallSetObject(shellwall, VIS_COLORMAP, cmap);
    vis_ShellWallSetObject(shellwall, VIS_LEVELS, levels);
    vis_ShellWallSetParami(shellwall, SHELLWALL_AXESBASIC, SYS_ON);

    /* define 3 layer laminate */
    vis_ShellWallDef(shellwall, SHELLWALL_GEOMETRY);
    for (i = 1; i <= nlayers + 1; i++) {
        vis_ShellWallSetPoint(shellwall, i, zp[i - 1]);
    }
    for (i = 1; i <= nlayers; i++) {
        ix[0] = i;
        ix[1] = i + 1;
        vis_ShellWallSetLayer(shellwall, i, ix, phi[i - 1], 1);
    }
    /* define lamina material id 1 */
    mprop[0] = 1000000.;
    mprop[1] = 2000000.;
    mprop[2] = .1f;
    mprop[3] = 500000.;
    mprop[4] = 500000.;
    mprop[5] = 500000.;
    vis_ShellWallSetElasProp(shellwall, 1, VIS_MAT_LAMINA, mprop);

    /* compute wall properties */
    vis_ShellWallProps(shellwall);

    /* create shell object and set objects */
    shellelem = vis_ShellElemBegin();
    vis_ShellElemSetObject(shellelem, VGL_DRAWFUN, df);
    vis_ShellElemSetObject(shellelem, VIS_VISCONTEXT, vc);
    vis_ShellElemSetObject(shellelem, VIS_COLORMAP, cmap);
    vis_ShellElemSetObject(shellelem, VIS_SHELLWALL, shellwall);
    vis_ShellElemSetParami(shellelem, SHELLELEM_WALL, VIS_ON);

    vis_ShellElemSetTopology(shellelem, VIS_SHAPETRI, 3, 0);
    factors[0] = 1.;
    factors[1] = 1.5;
    factors[2] = 1.75;
    vis_ShellElemSetCornerFactors(shellelem, factors);

    /* draw */
    for (j = 0; j < 5; j++) {
        if (j == 0) {
            vis_VisContextSetElemLoc(vc, VIS_ELEMLOC_CENTROID);
            vis_VisContextSetElemRep(vc, VIS_ELEMREP_SEMI);
        }
        else if (j == 1) {
            vis_VisContextSetElemLoc(vc, VIS_ELEMLOC_CORNERS);
            vis_VisContextSetElemRep(vc, VIS_ELEMREP_SEMI);
        }
        else if (j == 2) {
            vis_VisContextSetElemLoc(vc, VIS_ELEMLOC_NODES);
            vis_VisContextSetElemRep(vc, VIS_ELEMREP_SEMI);
            /* bottom surface green, top surface red */
        }
        else if (j == 3) {
            vis_VisContextSetColor(vc, 1);
            vis_VisContextSetMinorColor(vc, 2);
            vis_VisContextSetElemRep(vc, VIS_ELEMREP_SOLID);
            vis_ShellElemSetParami(shellelem, SHELLELEM_WALL, VIS_OFF);
        }
        else if (j == 4) {
            vis_VisContextSetColor(vc, 0);
            vis_VisContextSetMinorColor(vc, 0);
            vis_VisContextSetElemRep(vc, VIS_ELEMREP_SOLID);
            vis_ShellElemSetParami(shellelem, SHELLELEM_WALL, VIS_ON);
        }

        for (i = 0; i < 10; i++) {
            GLWinClear(glwin);
            GLWinColor(glwin, ctex);
            GLWinText(glwin, xtex, "3 Layer Shell Element");
            GLWinXfmPush(glwin);
            GLWinRotate(glwin, i * 4.F, 'x');
            GLWinRotate(glwin, i * 11.F, 'y');
            /* draw shell using exact normals */
            vis_ShellElemCurv(shellelem, xshell, VIS_VERTEXDATA, vshell);
            GLWinXfmPop(glwin);
            GLWinSwap(glwin);
            sleep(1);
        }
    }
    sleep(5);

    /* free all objects */
    vgl_DrawFunEnd(df);
    vis_VisContextEnd(vc);
    vis_ColorMapEnd(cmap);
    vis_LevelsEnd(levels);
    vis_ShellWallEnd(shellwall);
    vis_ShellElemEnd(shellelem);
    GLWinEnd(glwin);
    return 0;
}
../../_images/vistools-exam14a1.gif

Figure 14-14a1, Shell Element, Corner Shell Wall and Reference Surface

../../_images/vistools-exam14a2.gif

Figure 14-14a2, Shell Element, Edge Laminate and Top and Bottom Surfaces

15.34. Example 14b, Contour Plot and Cutting Plane 3D Monocoque Shell Elements

This example illustrates contour plotting a scalar field over the bottom and top surfaces and free edges of an assemblage of two shell elements using the Contour object. The shell elements are 6 node, parabolic triangular shells. The second part of the example illustrates generating a cutting plane through the 3D volume of the shells using the Threshold and Contour objects.

The Connect object is used to generate an element edge group of the free faces of the two connected shell elements. This group will be used to avoid contouring any interior edges of the shell model. The basic geometry of the shell is represented by the shell midsurface coordinates and a shell thickness. The shell bottom and top surface coordinates are computed and the scalar field to be contoured is simply the x coordinate for the bottom surface and the x coordinate plus .5 for the top surface. Notice that when contouring the bottom surface the VisContext reflect flag is enabled so that the generated graphics primitives have their normals pointing out of the shell. The edges of the shells are contoured as quadrilateral faces which are parabolic in one direction and linear in the thickness direction. The vis_ConnectElemCnn() function is useful for returning the locations of the shell edge data from the shell element arrays so that the correct values can be gathered for the bottom and top surfaces of the edge.

The cutting plane is generated in the usual way using the DataInt object to supply the Threshold object with the pointer to the data to be contoured. The dfC drawing function is registered in Threshold so that the graphics primitives with scalar data interpolated to their verices are sent to the appropriate contouring function. The topology used by Threshold in this case is a wedge with the data at the bottom surface nodes first followed by the data at the top surface nodes. Note that the Levels object associated with the cutting plane has a single level whose value is the y coordinate of the cutting plane. The scalar values input to vis_ThresholdCurv() in this case are the y coordinates of the vertices of the wedge reconstruction of the 3D triangular shell element.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

#include "glwin.h"

static Vfloat rgb[9][3] = {{.5, .5, .5}, {1., 0., 0.}, {0., 1., 0.},    {0., 0., 1.}, {0., 1., 1.},
                           {1., 0., 1.}, {1., 1., 0.}, {.2f, .2f, .2f}, {1., 1., 1.}};

/*       two 6 node triangular shell elements

           7---8---9
           | \     |
           4---5---6
           |     \ |
           1---2---3
*/
/* midsurface node coordinates */
static Vfloat xmid[9][3] = {{0., 0., 0.}, {1., 0., 0.}, {2., 0., 0.}, {0., 1., 0.}, {1., 1., 0.},
                            {2., 1., 0.}, {0., 2., 0.}, {1., 2., 0.}, {2., 2., 0.}};
/* midsurface normals, all in z direction */
static Vfloat vmid[9][3] = {{0., 0., 1.}, {0., 0., 1.}, {0., 0., 1.}, {0., 0., 1.}, {0., 0., 1.},
                            {0., 0., 1.}, {0., 0., 1.}, {0., 0., 1.}, {0., 0., 1.}};
/* shell element connectivity */
static Vint scon[2][6] = {{1, 3, 7, 2, 5, 4}, {3, 9, 7, 6, 8, 5}};

/*----------------------------------------------------------------------
                      Contour Plot and Cutting Plane 3D Monocoque Shell Elements
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun *df, *dfC;
    vis_VisContext* vc;
    vis_ColorMap* cmap;
    vis_Levels* levels;
    vis_Contour* contour;
    vis_VisContext* vct;
    vis_Levels* levelst;
    vis_Threshold* threshold;
    vis_DataInt* dataint;
    GLWin* glwin;
    vis_Connect* connect;
    vis_Group* group;

    Vint i, j, k, m, n;
    Vfloat xbt[2][6][3], sbt[2][6];
    Vfloat xedge[6][3], sedge[6];
    Vfloat sth[2][6];
    Vint numelem, numnode;
    Vint flag, nix, in[3], nn;
    Vfloat thick = .25;

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 200, 200, 400, 400);
    GLWinOrtho(glwin, -3., 3., -3., 3., -10., 10.);

    /* create draw function object for GL */
    df = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, df);
    /* load shell model into Connect object */
    numnode = 9;
    numelem = 2;
    connect = vis_ConnectBegin();
    vis_ConnectDef(connect, numnode, numelem);
    /* load nodes */
    for (i = 1; i <= numnode; i++) {
        vis_ConnectSetCoords(connect, i, xmid[i - 1]);
    }
    /* load element connectivity */
    for (i = 1; i <= numelem; i++) {
        vis_ConnectSetTopology(connect, i, VIS_SHAPETRI, 3, 0, 0);
        vis_ConnectSetElemNode(connect, i, scon[i - 1]);
    }
    /* form kernel for adjacency related queries */
    vis_ConnectKernel(connect, 0);
    /* generate element edge group of free edges */
    group = vis_GroupBegin();
    vis_GroupDef(group, numelem, SYS_ELEM, SYS_EDGE);
    vis_ConnectEdgeGroup(connect, CONNECT_FREE, NULL, group);

    vc = vis_VisContextBegin();
    vis_VisContextSetIsoValType(vc, VIS_ISOVALFRINGE);
    vis_VisContextSetMapColor(vc, VIS_ON);
    vis_VisContextSetShade(vc, VIS_VERTEXSHADE);

    /* color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetType(cmap, COLORMAP_TRUECOLOR);
    vis_ColorMapSetRGB(cmap, 9, 0, rgb);

    /* levels object for contouring, 6 levels*/
    levels = vis_LevelsBegin();
    vis_LevelsDef(levels, LEVELS_LINEAR, 6);
    vis_LevelsSetMinMax(levels, 0., 2.5);
    vis_LevelsGenerate(levels, LEVELS_PADTOP);

    /* contour object */
    contour = vis_ContourBegin();
    vis_ContourSetObject(contour, VGL_DRAWFUN, df);
    vis_ContourSetObject(contour, VIS_VISCONTEXT, vc);
    vis_ContourSetObject(contour, VIS_COLORMAP, cmap);
    vis_ContourSetObject(contour, VIS_LEVELS, levels);

    /* rotate 30 times */
    for (k = 0; k < 15; k++) {
        GLWinClear(glwin);
        GLWinXfmPush(glwin);
        GLWinRotate(glwin, -k * 4.F, 'x');
        GLWinRotate(glwin, -k * 10.F, 'y');
        /* loop through elements */
        for (i = 1; i <= numelem; i++) {
            /* bottom and top surfaces */
            vis_ContourSetTopology(contour, VIS_SHAPETRI, 3, 0);
            for (j = 0; j < 6; j++) {
                nn = scon[i - 1][j];
                xbt[0][j][0] = xmid[nn - 1][0] - vmid[nn - 1][0] * .5F * thick;
                xbt[0][j][1] = xmid[nn - 1][1] - vmid[nn - 1][1] * .5F * thick;
                xbt[0][j][2] = xmid[nn - 1][2] - vmid[nn - 1][2] * .5F * thick;
                sbt[0][j] = xbt[0][j][0];
                xbt[1][j][0] = xmid[nn - 1][0] + vmid[nn - 1][0] * .5F * thick;
                xbt[1][j][1] = xmid[nn - 1][1] + vmid[nn - 1][1] * .5F * thick;
                xbt[1][j][2] = xmid[nn - 1][2] + vmid[nn - 1][2] * .5F * thick;
                sbt[1][j] = xbt[1][j][0] + .5F;
            }
            /* turn on reflect for bottom */
            vis_VisContextSetReflect(vc, VIS_ON);
            vis_ContourCurv(contour, sbt[0], xbt[0], VIS_NODATA, NULL);
            /* turn off reflect for top */
            vis_VisContextSetReflect(vc, VIS_OFF);
            vis_ContourCurv(contour, sbt[1], xbt[1], VIS_NODATA, NULL);
            /* now loop through 3 edges */
            /* the edge is a quad face
               parabolic in one direction and linear in the other */
            vis_ContourSetTopology(contour, VIS_SHAPEQUAD, 3, 2);
            for (m = 1; m <= 3; m++) {
                /* test to only draw free edges */
                flag = vis_GroupElemEnt(group, i, m);
                if (flag == 0)
                    continue;
                /* get locations of edge data in element arrays */
                vis_ConnectElemCnn(connect, SYS_EDGE, i, m, &nix, in);
                /* set bottom data first and then top data */
                for (n = 0; n < 3; n++) {
                    xedge[n][0] = xbt[0][in[n] - 1][0];
                    xedge[n][1] = xbt[0][in[n] - 1][1];
                    xedge[n][2] = xbt[0][in[n] - 1][2];
                    sedge[n] = sbt[0][in[n] - 1];
                    xedge[3 + n][0] = xbt[1][in[n] - 1][0];
                    xedge[3 + n][1] = xbt[1][in[n] - 1][1];
                    xedge[3 + n][2] = xbt[1][in[n] - 1][2];
                    sedge[3 + n] = sbt[1][in[n] - 1];
                }
                vis_ContourCurv(contour, sedge, xedge, VIS_NODATA, NULL);
            }
        }
        GLWinXfmPop(glwin);
        GLWinSwap(glwin);
        GLWinDelay(glwin, 1.);
    }

    /* viscontext for threshold */
    vct = vis_VisContextBegin();
    vis_VisContextSetIsoValType(vct, VIS_ISOVALSURFACE);
    vis_VisContextSetShade(vc, VIS_VERTEXSHADE);

    /* levels object for threshold 1 level*/
    /* the cutting plane is at y = .75 */
    levelst = vis_LevelsBegin();
    vis_LevelsDef(levelst, LEVELS_LINEAR, 1);
    vis_LevelsSetValue(levelst, 1, .75);

    /* data interpolation object for scalar field */
    dataint = vis_DataIntBegin();
    vis_DataIntSetDataPtr(dataint, 0, 1, (Vfloat*)sbt);

    /* create contouring drawing function object */
    dfC = vgl_DrawFunBegin();
    vgl_DrawFunSetObj(dfC, contour);
    vgl_DrawFunAPI(dfC, DRAWFUN_APIRETURN);
    /* use function provided by Contour module */
    vgl_DrawFunSet(dfC, DRAWFUN_POLYGONDATA, (Vfunc*)vis_ContourPolygonData);

    /* threshold object */
    threshold = vis_ThresholdBegin();
    vis_ThresholdSetObject(threshold, VGL_DRAWFUN, dfC);
    vis_ThresholdSetObject(threshold, VIS_VISCONTEXT, vct);
    vis_ThresholdSetObject(threshold, VIS_COLORMAP, cmap);
    vis_ThresholdSetObject(threshold, VIS_LEVELS, levelst);
    vis_ThresholdSetObject(threshold, VIS_DATAINT, dataint);

    /* rotate 30 times */
    for (k = 0; k < 15; k++) {
        GLWinClear(glwin);
        GLWinXfmPush(glwin);
        GLWinRotate(glwin, -k * 4.F, 'x');
        GLWinRotate(glwin, -k * 10.F, 'y');
        /* the 3D shell is respresented as a wedge */
        vis_ThresholdSetTopology(threshold, VIS_SHAPEWED, 3, 0, 2);
        /* loop through elements */
        for (i = 1; i <= numelem; i++) {
            /* bottom and top surfaces */
            /* sth array holds y coordinates */
            for (j = 0; j < 6; j++) {
                nn = scon[i - 1][j];
                xbt[0][j][0] = xmid[nn - 1][0] - vmid[nn - 1][0] * .5F * thick;
                xbt[0][j][1] = xmid[nn - 1][1] - vmid[nn - 1][1] * .5F * thick;
                xbt[0][j][2] = xmid[nn - 1][2] - vmid[nn - 1][2] * .5F * thick;
                sbt[0][j] = xbt[0][j][0];
                sth[0][j] = xbt[0][j][1];
                xbt[1][j][0] = xmid[nn - 1][0] + vmid[nn - 1][0] * .5F * thick;
                xbt[1][j][1] = xmid[nn - 1][1] + vmid[nn - 1][1] * .5F * thick;
                xbt[1][j][2] = xmid[nn - 1][2] + vmid[nn - 1][2] * .5F * thick;
                sbt[1][j] = xbt[1][j][0] + .5F;
                sth[1][j] = xbt[1][j][1];
            }
            vis_ThresholdCurv(threshold, (Vfloat*)sth, (Vfloat(*)[3])xbt, VIS_NODATA, NULL);
        }
        GLWinXfmPop(glwin);
        GLWinSwap(glwin);
        GLWinDelay(glwin, 1.);
    }
    /* free all objects */
    vgl_DrawFunEnd(df);
    vis_VisContextEnd(vc);
    vis_ColorMapEnd(cmap);
    vis_LevelsEnd(levels);
    vis_ContourEnd(contour);
    vgl_DrawFunEnd(dfC);
    vis_VisContextEnd(vct);
    vis_LevelsEnd(levelst);
    vis_ThresholdEnd(threshold);
    vis_ConnectEnd(connect);
    vis_GroupEnd(group);
    GLWinEnd(glwin);
    return 0;
}

15.35. Example 15, Draw a Simple Billboard

This example illustrates using the Billboard module to draw quantitative information about an entity. Information is formatted in a billboard as items. Items can consist of text, lines, polygons, points, beveled rules, titles, etc. In this case two billboards are drawn. The first billboard contains a title, a beveled rule and a dashed line rule and some text items which list element stress and strain. All current attributes such as color, line style, etc. which affect items are set using vis_BillboardSetItemParami() or vis_BillboardSetItemParamfv(). Note that newlines are conveniently specified using the ‘n’ character in the text items.

The second billboard illustrates drawing wide character strings with the vis_BillboardTextItemtv() function. The underlying graphics system must accept wide character strings. In this case VisTools and VglTools must be compiled with VKI_WIDECHAR defined. A window system raster font is used which supports wide characters.

The ColorMap module function vis_ColorMapRamp() is used with COLORMAP_SET to provide a useful set of named colors for coloring and shading the billboard.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

/*----------------------------------------------------------------------
                      Draw a Simple Billboard
----------------------------------------------------------------------*/
int
main()
{
#ifdef VKI_WIND_X11
    Display* display;
    int screen;
#else
    HFONT hfont;
#endif

    vgl_DrawFun* df;
    vis_VisContext* vc;
    vis_ColorMap* cmap;
    vis_Billboard* billboard;
    vgl_OpenGLDev* ogldev;
    vgl_RasFont* rasfont;
#ifdef VKI_WIDECHAR
    static Vtchar euro[] = {L'U', L'n', L'i', L'c', L'o', L'd', L'e', L' ', L'E', L'u', L'r', L'o', L'=', L' ', 0x20ac, L'\0'};
#else
    static Vtchar euro[] = "Unicode Euro= euro";
#endif

    Vfloat x[3];

#ifdef VKI_WIND_X11
    display = XOpenDisplay(0);
    screen = DefaultScreen(display);
    vgl_OpenGLDevConnectX(display, screen);
#endif

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

#ifdef VKI_WIND_WIN32
    vgl_OpenGLDevConnectWIN();
#endif
    /* create GL device */
    ogldev = vgl_OpenGLDevBegin();

    /* create draw function object for GL */
    df = vgl_DrawFunBegin();
    vgl_OpenGLDevDrawFun(ogldev, df);

    vgl_DrawFunPositionWindow(df, 200, 200, 400, 400);
    vgl_DrawFunOpenWindow(df, "Example 15vgl");
    vgl_DrawFunProjOrtho(df, -2., 2., -2., 2., -2., 2.);
    vgl_DrawFunSetMode(df, VGL_ZBUFFERMODE, VGL_ON);

    rasfont = vgl_RasFontBegin();
#ifdef VKI_WIND_X11
    vgl_RasFontLoadXFont(rasfont, display, "-adobe-courier-bold-o-normal--14-100-100-100-m-90-iso10646-1");
#else
    hfont = CreateFont(15, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, FIXED_PITCH | FF_DONTCARE, TEXT("Arial"));
    vgl_RasFontLoadWINFont(rasfont, hfont);
#endif
    vgl_DrawFunRasFontDefine(df, 1, rasfont);

    /* color map, standard set of 29 colors */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetType(cmap, COLORMAP_TRUECOLOR);
    vis_ColorMapRamp(cmap, 29, 0, COLORMAP_SET);

    /* vis context and set attributes */
    vc = vis_VisContextBegin();
    vis_VisContextSetMapColor(vc, VIS_OFF);
    vis_VisContextSetColor(vc, COLORMAP_SET_GRAY40);
    vis_VisContextSetABCColor(vc, COLORMAP_SET_RED, COLORMAP_SET_REDDARK, COLORMAP_SET_REDLITE);

    /* create billboard object */
    billboard = vis_BillboardBegin();
    vis_BillboardSetObject(billboard, VGL_DRAWFUN, df);
    vis_BillboardSetObject(billboard, VIS_COLORMAP, cmap);
    vis_BillboardSetObject(billboard, VIS_VISCONTEXT, vc);

    /* enter contents of billboard */
    vis_BillboardSetItemParami(billboard, BILLBOARD_COLOR, COLORMAP_SET_BLUE);
    /* title automatically generate a new line */
    vis_BillboardTitleItem(billboard, "Analysis Results");
    vis_BillboardSetItemParami(billboard, BILLBOARD_COLOR, COLORMAP_SET_WHITE);
    vis_BillboardSetItemParami(billboard, BILLBOARD_SHADOW_COLOR, COLORMAP_SET_GRAY20);
    vis_BillboardSetItemParami(billboard, BILLBOARD_RULE_BEVEL, VIS_ON);
    /* rule automatically generate a new line */
    vis_BillboardRuleItem(billboard);

    vis_BillboardSetItemParami(billboard, BILLBOARD_COLOR, COLORMAP_SET_CYAN);
    vis_BillboardTextItem(billboard, "stress_xx = 10230.\n");
    vis_BillboardTextItem(billboard, "stress_yy = 15328.\n");
    vis_BillboardTextItem(billboard, "stress_zz =   556.\n");

    vis_BillboardSetItemParami(billboard, BILLBOARD_COLOR, COLORMAP_SET_BLACK);
    vis_BillboardSetItemParami(billboard, BILLBOARD_RULE_BEVEL, VIS_OFF);
    vis_BillboardSetItemParami(billboard, BILLBOARD_LINE_STYLE, VIS_DASHDASH);
    vis_BillboardRuleItem(billboard);

    vis_BillboardSetItemParami(billboard, BILLBOARD_COLOR, COLORMAP_SET_YELLOW);
    vis_BillboardTextItem(billboard, "strain_xx = .00121\n");
    vis_BillboardTextItem(billboard, "strain_yy = .00153\n");
    /* do not want newline after last item */
    vis_BillboardTextItem(billboard, "strain_zz = .00012");

    /* define anchor point */
    x[0] = -0.5;
    x[1] = -0.5;
    x[2] = 0.0;
    /* draw billboard */
    vgl_DrawFunClear(df);
    vis_BillboardDraw(billboard, x);
    vgl_DrawFunSwap(df);
    vgl_DrawFunDelay(df, 5.);

    /* draw billboard with wide character string */
    vis_BillboardErase(billboard);
    vis_BillboardSetItemParami(billboard, BILLBOARD_COLOR, COLORMAP_SET_BLUE);
    vis_BillboardTitleItem(billboard, "Product Cost");
    vis_BillboardRuleItem(billboard);
    vis_BillboardTextItemtv(billboard, euro);

    vgl_DrawFunRasFontSelect(df, 1);
    vgl_DrawFunClear(df);
    vis_BillboardDraw(billboard, x);
    vgl_DrawFunSwap(df);
    vgl_DrawFunDelay(df, 5.);

    /* close window */
    vgl_DrawFunCloseWindow(df);

    /* free all objects */
    vgl_DrawFunEnd(df);
    vgl_RasFontEnd(rasfont);
    vis_VisContextEnd(vc);
    vis_ColorMapEnd(cmap);
    vgl_OpenGLDevEnd(ogldev);
    vis_BillboardEnd(billboard);

    /* disconnect */
    vgl_OpenGLDevDisconnect();
#ifdef VKI_WIND_X11
    XCloseDisplay(display);
#endif
    return 0;
}
../../_images/vistools-exam15.gif

Figure 14-15, Simple Billboard

15.36. Example 15a, Draw a Fancy Billboard

This example illustrates a more advanced use of the Billboard module than the previous example. A billboard is created with two title lines and a series of colored and outlined rectangles labeled with text. The resulting billboard could be used for a custom color legend. Note that vis_BillboardSpace() is used to backspace to overstrike the filled rectangle with a black outline.

A Cell module is used to draw the wireframe of a hexahedron in yellow. The billboard is anchored to the fifth node of the hexahedron. A device offset is defined in the visualization context so that the billboard is offset up and to the right from the anchor point. A parameter is set using vis_BillboardSetParami() to display an offset vector from the anchor point to the attachment position on the billboard - in this case the bottom left of the billboard. As the entire scene is rotated the billboard is transformed by the anchor point but remains the same size and oriented perpendicular to the viewer. Note that lighting is disabled immediately before the billboard is drawn using vis_BillboardDraw(). Since billboards are essentially 2D annotation objects it is desirable to ensure that their base colors are not modified by lighting calculations. Lighting is re-enabled after the billboard is drawn.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

static Vfloat xhex[8][3] = {{-.5, -.5, -.5}, {.5, -.5, -.5}, {.5, .5, -.5}, {-.5, .5, -.5},
                            {-.5, -.5, .5},  {.5, -.5, .5},  {.5, .5, .5},  {-.5, .5, .5}};

/*----------------------------------------------------------------------
                      Draw a Fancy Billboard
----------------------------------------------------------------------*/
int
main()
{
#ifdef VKI_WIND_X11
    Display* display;
    int screen;
#endif

    vgl_DrawFun* df;
    vis_VisContext *vc, *vccell;
    vis_ColorMap* cmap;
    vis_Billboard* billboard;
    vis_Cell* cell;
    vgl_OpenGLDev* ogldev;
    vgl_Xfm* xfm;

    int i;
    Vfloat offset[2];
    Vchar str[80];
    Vfloat width, height;
    Vfloat c[3], x[3], tm[4][4];

#ifdef VKI_WIND_X11
    display = XOpenDisplay(0);
    screen = DefaultScreen(display);
    vgl_OpenGLDevConnectX(display, screen);
#endif

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

#ifdef VKI_WIND_WIN32
    vgl_OpenGLDevConnectWIN();
#endif

    /* create GL device */
    ogldev = vgl_OpenGLDevBegin();

    /* create draw function object for GL */
    df = vgl_DrawFunBegin();
    vgl_OpenGLDevDrawFun(ogldev, df);

    vgl_DrawFunPositionWindow(df, 100, 100, 800, 800);
    vgl_DrawFunOpenWindow(df, "Example 15avgl");
    vgl_DrawFunProjOrtho(df, -1., 2., -1., 2., -1., 2.);
    vgl_DrawFunSetMode(df, VGL_ZBUFFERMODE, VGL_ON);
    vgl_DrawFunSetMode(df, VGL_LIGHTMODE, VGL_ON);
    c[0] = .4f;
    c[1] = .4f;
    c[2] = .4f;
    x[0] = 0.;
    x[1] = 0.;
    x[2] = 0.;
    vgl_DrawFunLight(df, 0, VGL_LIGHT_AMBIENT, c, x);
    c[0] = .6f;
    c[1] = .6f;
    c[2] = .6f;
    x[0] = 1.;
    x[1] = 1.;
    x[2] = 1.;
    vgl_DrawFunLight(df, 1, VGL_LIGHT_DISTANT, c, x);
    x[0] = -1.;
    x[1] = -1.;
    x[2] = -1.;
    vgl_DrawFunLight(df, 2, VGL_LIGHT_DISTANT, c, x);

    /* create transformation object */
    xfm = vgl_XfmBegin();

    /* color map, standard set of 29 colors */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetType(cmap, COLORMAP_TRUECOLOR);
    vis_ColorMapRamp(cmap, 29, 0, COLORMAP_SET);

    /* vis context and set attributes */
    vccell = vis_VisContextBegin();
    vis_VisContextSetMapColor(vccell, VIS_OFF);
    vis_VisContextSetColor(vccell, COLORMAP_SET_YELLOW);
    vis_VisContextSetFill(vccell, VIS_OFF);
    vis_VisContextSetEdge(vccell, VIS_ON);
    vis_VisContextSetLineStyle(vccell, VIS_CYLINDER);
    vis_VisContextSetSize(vccell, .025f);

    /* create cell object */
    cell = vis_CellBegin();
    vis_CellSetObject(cell, VGL_DRAWFUN, df);
    vis_CellSetObject(cell, VIS_COLORMAP, cmap);
    vis_CellSetObject(cell, VIS_VISCONTEXT, vccell);

    /* vis context and set attributes */
    vc = vis_VisContextBegin();
    vis_VisContextSetMapColor(vc, VIS_OFF);
    vis_VisContextSetColor(vc, COLORMAP_SET_GRAY40);
    vis_VisContextSetMinorColor(vc, COLORMAP_SET_WHITE);
    vis_VisContextSetABCColor(vc, COLORMAP_SET_GRAY50, COLORMAP_SET_GRAY30, COLORMAP_SET_GRAY70);
    vis_VisContextSetDeviceOffset(vc, 40, 10);

    /* create billboard object */
    billboard = vis_BillboardBegin();
    vis_BillboardSetObject(billboard, VGL_DRAWFUN, df);
    vis_BillboardSetObject(billboard, VIS_COLORMAP, cmap);
    vis_BillboardSetObject(billboard, VIS_VISCONTEXT, vc);

    /* enter contents of billboard */
    vis_BillboardSetItemParami(billboard, BILLBOARD_COLOR, COLORMAP_SET_BLUE);
    vis_BillboardTitleItem(billboard, "Custom");
    vis_BillboardTitleItem(billboard, "Color Legend");
    vis_BillboardSetItemParami(billboard, BILLBOARD_COLOR, COLORMAP_SET_GRAY70);
    vis_BillboardSetItemParami(billboard, BILLBOARD_SHADOW_COLOR, COLORMAP_SET_GRAY30);
    vis_BillboardRuleItem(billboard);
    vis_BillboardNewLine(billboard, 2.0);
    width = 4.0;
    height = 2.5;

    /* add a series of colored boxes for a legend */
    for (i = 0; i < 6; i++) {
        sprintf(str, "value %d", i + 1);
        vis_BillboardSetItemParami(billboard, BILLBOARD_COLOR, COLORMAP_SET_RED + i);
        vis_BillboardRectangleItem(billboard, width, height, 1);

        /* backspace to outline in black */
        vis_BillboardSpace(billboard, -width);
        vis_BillboardSetItemParami(billboard, BILLBOARD_COLOR, COLORMAP_SET_BLACK);
        vis_BillboardRectangleItem(billboard, width, height, 0);

        /* offset to draw text after rectangle */
        offset[0] = 2.0;
        offset[1] = 1.0;
        vis_BillboardSetItemParamfv(billboard, BILLBOARD_OFFSET, offset);
        vis_BillboardSetItemParami(billboard, BILLBOARD_COLOR, COLORMAP_SET_RED + i);
        vis_BillboardTextItem(billboard, str);
        offset[0] = 0.0;
        offset[1] = 0.0;
        vis_BillboardSetItemParamfv(billboard, BILLBOARD_OFFSET, offset);

        if (i != 5) {
            vis_BillboardNewLine(billboard, height);
        }
    }
    /* turn on drawing of offset vector */
    vis_BillboardSetParami(billboard, BILLBOARD_OFFSET_VECTOR, VIS_ON);

    /* draw billboard and wireframe cell */
    for (i = 0; i < 340; i++) {
        vgl_DrawFunClear(df);
        vgl_DrawFunXfmPush(df);
        vgl_XfmRotate(xfm, i * .03F, XFM_YAXIS);
        vgl_XfmGetMatrix(xfm, tm);
        vgl_DrawFunXfmLoad(df, tm);
        vgl_XfmRotate(xfm, i * .01F, XFM_XAXIS);
        vgl_XfmGetMatrix(xfm, tm);
        vgl_DrawFunXfmMult(df, tm);
        vis_VisContextTouch(vccell);
        vis_CellCurv(cell, xhex);
        vis_VisContextTouch(vc);
        vgl_DrawFunSetMode(df, VGL_LIGHTMODE, VGL_OFF);
        vis_BillboardDraw(billboard, xhex[4]);
        vgl_DrawFunSetMode(df, VGL_LIGHTMODE, VGL_ON);
        vgl_DrawFunXfmPop(df);
        vgl_DrawFunSwap(df);
        vgl_DrawFunDelay(df, .05f);
    }

    vgl_DrawFunDelay(df, 5.);

    /* close window */
    vgl_DrawFunCloseWindow(df);

    /* free all objects */
    vgl_DrawFunEnd(df);
    vis_VisContextEnd(vc);
    vis_VisContextEnd(vccell);
    vis_ColorMapEnd(cmap);
    vgl_OpenGLDevEnd(ogldev);
    vgl_XfmEnd(xfm);
    vis_BillboardEnd(billboard);
    vis_CellEnd(cell);

    /* disconnect */
    vgl_OpenGLDevDisconnect();
#ifdef VKI_WIND_X11
    XCloseDisplay(display);
#endif
    return 0;
}
../../_images/vistools-exam15a.gif

Figure 14-15a, Fancy Billboard

15.37. Example 16, Draw Dimensioning Annotation

This example illustrates using the Dimension module to draw dimensioning and annotation text and graphics for a 3D polygonal model. The model is constructed by extruding a planar face consisting of five straight edges and one circular edge in the z direction. A dimension plane is defined using vis_DimensionSetPlane() with a right vector of (1.0, 0.0, 0.0) and an up vector of (0.0, 1.0, 0.0). The lengths of three straight edges of the model are annotated using linear dimensions. The three linear dimensions illustrate three varieties of alignment: horizontal, vertical and “aligned”.

The center of the circular edge with its radius is annotated using a radius leader. The circular edge is also annotated on its back side with an angular dimension. The right side of the model is annotated as a contact surface using a leader line. The dimensioning module backplane flip option is enabled so that as the model rotates about the y-axis the dimensioning labels are always readable.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "glwin.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

#define MAX_PTS 50

static Vfloat rgb[7][3] = {{.2f, .2f, .2f}, {1., 0., 0.}, {0., 1., 0.}, {0., 0., 1.}, {0., 1., 1.}, {1., 0., 1.}, {1., 1., 0.}};

static Vfloat frnt_norm[3] = {0.0, 0.0, 1.0};
static Vfloat back_norm[3] = {0.0, 0.0, -1.0};

void
create_outline(Vint* p_n, Vfloat outline[][2]);
void
draw_solid(vgl_DrawFun* df, Vint n, Vfloat outline[][2], Vfloat zf, Vfloat zb);

/*----------------------------------------------------------------------
                      Generate dimension annotation for a solid
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun* df;
    vis_VisContext* vc;
    vis_ColorMap* cmap;
    GLWin* glwin;

    Vint i, n;
    Vfloat outline[MAX_PTS][2];
    Vfloat view_mat[4][4];
    Vfloat zf, zb;
    vis_Dimension* dimension;
    Vfloat up[3], right[3];
    Vfloat x[3], xl[3], xlabel[3], xcenter[3];

    Vfloat text_size = 0.35f;
    Vfloat arrow_size = 1.5f;

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 200, 200, 600, 600);
    GLWinOrtho(glwin, -14., 14., -14., 14., -14., 14.);

    /* create draw function object for GL */
    df = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, df);

    /* vis context and set attributes */
    vc = vis_VisContextBegin();

    /* color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetType(cmap, COLORMAP_TRUECOLOR);
    vis_ColorMapSetRGB(cmap, 16, 0, rgb);
    vis_ColorMapValueDrawFun(cmap, df, 1);

    /* create solid outline */
    create_outline(&n, outline);
    zf = 2.5;
    zb = -2.5;
    /* dimension */
    dimension = vis_DimensionBegin();
    vis_DimensionSetObject(dimension, VGL_DRAWFUN, df);
    vis_DimensionSetObject(dimension, VIS_COLORMAP, cmap);
    vis_DimensionSetObject(dimension, VIS_VISCONTEXT, vc);

    right[0] = 1.0;
    right[1] = 0.0;
    right[2] = 0.0;
    up[0] = 0.0;
    up[1] = 1.0;
    up[2] = 0.0;
    vis_DimensionSetPlane(dimension, right, up);

    vis_VisContextSetColor(vc, 2);
    vis_VisContextSetSize(vc, text_size);
    vis_VisContextSetMinorSize(vc, arrow_size);
    vis_VisContextSetMinorColor(vc, 4);
    vis_VisContextSetFlags(vc, VIS_BACKPLANEFLIP);

    /* draw solid with dimensions */
    for (i = 0; i < 36; i++) {
        GLWinClear(glwin);
        GLWinXfmPush(glwin);
        GLWinRotate(glwin, i * 10.F, 'y');
        GLWinXfmGet(glwin, view_mat);
        vis_VisContextSetXfmMatrix(vc, view_mat);
        vis_ColorMapValueDrawFun(cmap, df, 1);
        draw_solid(df, n, outline, zf, zb);

        vis_VisContextSetVectorType(vc, VIS_VECTORLINE);
        vis_VisContextSetMinorColor(vc, 4);
        vis_VisContextSetLineWidth(vc, 1);

        /* linear vertical dimension */
        x[0] = -5.0;
        x[1] = -5.0;
        x[2] = zf;
        xl[0] = -5.0;
        xl[1] = 0.0;
        xl[2] = zf;
        xlabel[0] = -7.0;
        xlabel[1] = 0.0;
        xlabel[2] = zf;
        vis_DimensionSetParami(dimension, DIMENSION_LABEL_ALIGN, DIMENSION_HORIZONTAL);
        vis_DimensionSetParami(dimension, DIMENSION_LINEAR_ALIGN, DIMENSION_VERTICAL);
        vis_DimensionLinear(dimension, x, xl, xlabel, "5");

        /* linear horizontal dimension */
        x[0] = 0.0;
        x[1] = 5.0;
        x[2] = zf;
        xl[0] = 5.0;
        xl[1] = 5.0;
        xl[2] = zf;
        xlabel[0] = 4.0;
        xlabel[1] = 7.0;
        xlabel[2] = zf;
        vis_DimensionSetParami(dimension, DIMENSION_LINEAR_ALIGN, DIMENSION_HORIZONTAL);
        vis_DimensionLinear(dimension, x, xl, xlabel, "5.0");

        /* linear aligned dimension */
        x[0] = -5.0;
        x[1] = 0.0;
        x[2] = zf;
        xl[0] = 0.0;
        xl[1] = 5.0;
        xl[2] = zf;
        xlabel[0] = -5.0;
        xlabel[1] = 5.0;
        xlabel[2] = zf;
        vis_DimensionSetParami(dimension, DIMENSION_LABEL_ALIGN, DIMENSION_ALIGNED);
        vis_DimensionSetParami(dimension, DIMENSION_LINEAR_ALIGN, DIMENSION_ALIGNED);
        vis_DimensionLinear(dimension, x, xl, xlabel, "7.071");

        /* radius leader dimension */
        x[0] = 1.465f;
        x[1] = -1.465f;
        x[2] = zf;
        xcenter[0] = 5.0;
        xcenter[1] = -5.0;
        xcenter[2] = zf;
        xlabel[0] = 8.0;
        xlabel[1] = -6.0;
        xlabel[2] = zf;
        vis_DimensionRadius(dimension, x, xcenter, xlabel, "5.0");

        /* angular dimension */
        x[0] = 5.0;
        x[1] = 0.0;
        x[2] = zb;
        xl[0] = 0.0;
        xl[1] = -5.0;
        xl[2] = zb;
        xcenter[0] = 5.0;
        xcenter[1] = -5.0;
        xcenter[2] = zb;
        xlabel[0] = 3.0;
        xlabel[1] = -3.0;
        xlabel[2] = zb;
        vis_DimensionSetParami(dimension, DIMENSION_LABEL_ALIGN, DIMENSION_ORTHOGONAL);
        vis_VisContextSetMinorLineStyle(vc, VIS_DASHDASH);
        vis_DimensionAngular(dimension, x, xl, xcenter, xlabel, "90 deg");
        vis_VisContextSetMinorLineStyle(vc, VIS_SOLID);

        /* leader dimension */
        vis_VisContextSetVectorType(vc, VIS_VECTORUMBRELLA);
        vis_VisContextSetMinorColor(vc, 6);
        vis_VisContextSetLineWidth(vc, 2);
        x[0] = 5.0;
        x[1] = 2.5;
        x[2] = 0.;
        xlabel[0] = 7.0;
        xlabel[1] = 4.0;
        xlabel[2] = 0.;
        vis_DimensionLeader(dimension, x, xlabel, "Contact Surface");

        GLWinXfmPop(glwin);
        GLWinSwap(glwin);
        sleep(1);
    }

    sleep(2);

    /* free all objects */
    vgl_DrawFunEnd(df);
    vis_VisContextEnd(vc);
    vis_ColorMapEnd(cmap);
    vis_DimensionEnd(dimension);
    GLWinEnd(glwin);
    return 0;
}

void
create_outline(Vint* p_n, Vfloat outline[][2])
{
    Vint n, i, num_div;
    Vfloat r, begin_a, end_a, pi;
    Vfloat t, dt, cx, cy;

    /* Create an outline of a solid */
    n = 0;
    outline[n][0] = -5.0;
    outline[n++][1] = -5.0;
    outline[n][0] = -5.0;
    outline[n++][1] = 0.0;
    outline[n][0] = 0.0;
    outline[n++][1] = 5.0;
    outline[n][0] = 5.0;
    outline[n++][1] = 5.0;
    outline[n][0] = 5.0;
    outline[n++][1] = 0.0;

    r = 5.0;
    num_div = 30;
    pi = 4.0F * (Vfloat)atan(1.0);
    begin_a = pi / 2.0F;
    end_a = pi;
    cx = 5.0;
    cy = -5.0;
    dt = (end_a - begin_a) / (Vfloat)num_div;
    t = begin_a + dt;

    for (i = 0; i < num_div; i++) {
        outline[n][0] = cx + r * (Vfloat)cos(t);
        outline[n++][1] = cy + r * (Vfloat)sin(t);
        t += dt;
    }

    *p_n = n;
}

void
draw_solid(vgl_DrawFun* df, Vint n, Vfloat outline[][2], Vfloat zf, Vfloat zb)
{
    Vint j, k, p, q;
    Vfloat pts[4][3];
    Vfloat nx, ny, nz, norm[3], mag;

    /* Draw a solid extruded from an outline */
    for (j = 0; j < n; j++) {
        k = j + 1;
        if (k >= n) {
            k = 0;
        }

        pts[0][0] = outline[j][0];
        pts[0][1] = outline[j][1];
        pts[0][2] = zf;
        pts[1][0] = outline[k][0];
        pts[1][1] = outline[k][1];
        pts[1][2] = zf;
        pts[2][0] = 0.0;
        pts[2][1] = 0.0;
        pts[2][2] = zf;
        vgl_DrawFunPolygon(df, VGL_POLYGON, 3, pts, VGL_FLATSHADE, frnt_norm);

        pts[0][2] = zb;
        pts[1][2] = zb;
        pts[2][2] = zb;
        vgl_DrawFunPolygon(df, VGL_POLYGON, 3, pts, VGL_FLATSHADE, back_norm);

        pts[0][2] = zf;
        pts[1][2] = zf;
        pts[2][0] = outline[k][0];
        pts[2][1] = outline[k][1];
        pts[2][2] = zb;
        pts[3][0] = outline[j][0];
        pts[3][1] = outline[j][1];
        pts[3][2] = zb;
        nx = ny = nz = 0.0;

        for (p = 0; p < 4; p++) {
            if (p == 3) {
                q = 0;
            }
            else {
                q = p + 1;
            }

            nx += pts[q][1] * pts[p][2] - pts[q][2] * pts[p][1];
            ny += pts[q][2] * pts[p][0] - pts[q][0] * pts[p][2];
            nz += pts[q][0] * pts[p][1] - pts[q][1] * pts[p][0];
        }

        mag = (Vfloat)sqrt(nx * nx + ny * ny + nz * nz);
        norm[0] = nx / mag;
        norm[1] = ny / mag;
        norm[2] = nz / mag;
        vgl_DrawFunPolygon(df, VGL_POLYGON, 4, pts, VGL_FLATSHADE, norm);
    }
}
../../_images/vistools-exam16.gif

Figure 14-16, Dimensioning

15.38. Example 17, Using Coordinate Systems - CoordSys

This example illustrates using the CoordSys module to define local coordinate systems and perform operations with them. A CoordSys object to represent a cylindrical system is created using vis_CoordSysBegin() and vis_CoordSysDef(). The origin and orientation are specified using vis_CoordSysSetOriginTriad(). The origin is at 10.,10.,0. in the global coordinate system. The orientation is x’ along z, y’ along x and z’ along y. A point, xp, is defined at global coordinate location 20.,20.,10. and the local Cartesian direction cosine matrix at that point is computed using vis_CoordSysDirCos(). The equivalent rotation angle vector at the point is computed using vis_CoordSysRotAng(). The rotation angle vector is a compact representation of the direction cosine matrix. The cylindrical coordinates of x are computed using vis_CoordSysConvertCoord(). The functions vis_CoordSysConvertVector() and vis_CoordSysComputeVector() are used to convert a vector at point xp to the local Cartesian system at point xp and back again to the global Cartesian system.

A new Cartesian system is defined using the computed rotation angle vector as the system orientation using the function vis_CoordSysSetOriginRotAng(). The function vis_CoordSysOriginTriad() is used to query the system orientation returning a direction cosine matrix. Note that this returned direction cosine matrix is identical to that returned by the previous call to vis_CoordSysDirCos(), illustrating the equivalence of the rotation angle vector to the direction cosine matrix.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "glwin.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

/*----------------------------------------------------------------------
                      Using Coordinate Systems
----------------------------------------------------------------------*/
int
main()
{
    vis_CoordSys* coordsys;
    vis_CoordSys* coordsysang;
    Vfloat x[3], tm[3][3];
    Vfloat xp[3], tmp[3][3], xpl[3], rap[3];
    Vfloat xa[3], tma[3][3];
    Vfloat vp[3], vlc[3], vpc[3];

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create Cylindrical CoordSys */
    coordsys = vis_CoordSysBegin();
    vis_CoordSysDef(coordsys, SYS_CYLINDRICAL);

    /* set origin at 10.,10.,0. */
    x[0] = 10.;
    x[1] = 10.;
    x[2] = 0.;
    /* set orientation, x' along z, y' along x, z' along y */
    tm[0][0] = 0.;
    tm[0][1] = 0.;
    tm[0][2] = 1.;
    tm[1][0] = 1.;
    tm[1][1] = 0.;
    tm[1][2] = 0.;
    tm[2][0] = 0.;
    tm[2][1] = 1.;
    tm[2][2] = 0.;
    vis_CoordSysSetOriginTriad(coordsys, x, tm);

    /* compute local direction cosines at point 20.,20.,10. */
    xp[0] = 20.;
    xp[1] = 20.;
    xp[2] = 10.;
    vis_CoordSysDirCos(coordsys, xp, tmp);
    printf("x''= %f %f %f\n", tmp[0][0], tmp[0][1], tmp[0][2]);
    printf("y''= %f %f %f\n", tmp[1][0], tmp[1][1], tmp[1][2]);
    printf("z''= %f %f %f\n", tmp[2][0], tmp[2][1], tmp[2][2]);

    /* compute equivalent rotation angles of same system */
    vis_CoordSysRotAng(coordsys, xp, rap);
    printf("\n");
    printf("rx''= %f\n", rap[0]);
    printf("ry''= %f\n", rap[1]);
    printf("rz''= %f\n", rap[2]);

    /* define a new system using the computed rotation angles */
    coordsysang = vis_CoordSysBegin();
    vis_CoordSysDef(coordsysang, SYS_CARTESIAN);
    vis_CoordSysSetOriginRotAng(coordsysang, x, rap);

    /* query should match direction cosines */
    vis_CoordSysOriginTriad(coordsysang, xa, tma);
    printf("\n");
    printf("x''= %f %f %f\n", tma[0][0], tma[0][1], tma[0][2]);
    printf("y''= %f %f %f\n", tma[1][0], tma[1][1], tma[1][2]);
    printf("z''= %f %f %f\n", tma[2][0], tma[2][1], tma[2][2]);
    vis_CoordSysEnd(coordsysang);

    /* convert global coordinate to cylindrical coordinates */
    vis_CoordSysConvertCoord(coordsys, xp, xpl);
    printf("\n");
    printf("r    = %f\n", xpl[0]);
    printf("theta= %f\n", xpl[1]);
    printf("z'   = %f\n", xpl[2]);

    /* convert vector vp at xp to local Cartesian system */
    vp[0] = 2.;
    vp[1] = 0.;
    vp[2] = 0.;
    vis_CoordSysConvertVector(coordsys, xp, vp, vlc);
    printf("\n");
    printf("vlc= %f %f %f\n", vlc[0], vlc[1], vlc[2]);

    /* perform inverse. vpc should be same as original vp */
    vis_CoordSysComputeVector(coordsys, xp, vlc, vpc);
    printf("\n");
    printf("vpc= %f %f %f\n", vpc[0], vpc[1], vpc[2]);

    /* free object */
    vis_CoordSysEnd(coordsys);
    return 0;
}

15.39. Example 18, Draw Rigid Elements - RigidElem

This example illustrates using the RigidElem module to draw rigid elements. There are several special types of rigid elements which have different properties, topologies, etc. The iconic representation is dependent upon the special type. Detailed element properties may be added to the basic icon if an EProp object is registered with RigidElem and detailed element property drawing is enabled using vis_RigidElemSetParami(). The detailed rigid element properties consist of independent and dependent freedoms at each node with optional weights in some cases.

The first type drawn is a distributing coupling (eg. NASTRAN RBE3). The special type is set using vis_RigidElemSetSpec() with value SYS_RIGID_DIST. Typically all translations and rotations of the first node are dependent and all translations of subsequent nodes are independent. The topology should be SYS_SHAPEPOINT. For all point topologies, the icons are drawn as spokes radiating from the first node to the subsequent nodes. The spokes are Gouraud shaded from the Color at the first node to the MinorColor at the subsequent nodes. Note that weight sizing only requires the weight element properties in the EProp object.

The next type drawn is a kinematic coupling (eg. NASTRAN RBE2). The special type is set using vis_RigidElemSetSpec() with value SYS_RIGID_KINE. All translations and rotations of the first node are independent and all translations of subsequent nodes are dependent. The topology should be SYS_SHAPEPOINT.

The next type drawn is a rigid link (eg. NASTRAN RROD). The special type is set using vis_RigidElemSetSpec() with value SYS_RIGID_LINK. The topology should be SYS_SHAPELINE.

The next type drawn is a rigid triangular plate (eg. NASTRAN RTRPLT). The special type is set using vis_RigidElemSetSpec() with value SYS_RIGID_KINE. The topology should be SYS_SHAPETRI.

The final type drawn is a multi-point constraint. The special type is set using vis_RigidElemSetSpec() with value SYS_RIGID_MPC. The topology should be SYS_SHAPEPOINT. The first node is the dependent node and all subsequent nodes should be dependent. The weights are the coefficients of the constraint equation.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

#include "glwin.h"

static Vfloat rgb[8][3] = {{.5, .5, .5}, {1., 0., 0.}, {0., 1., 0.}, {0., 0., 1.},
                           {0., 1., 1.}, {1., 0., 1.}, {1., 1., 0.}, {1., 1., 1.}};

static Vfloat xtex[3] = {-1.8f, 1.5f, 0.};
static Vfloat ctex[3] = {1., 1., 1.};

void
draw_elem(vgl_DrawFun* df, vis_RigidElem* rigidelem, Vfloat x[][3], Vchar* text);
void
rotate_elem(vgl_DrawFun* df, vis_RigidElem* rigidelem, Vfloat x[][3], Vchar* text);

/*----------------------------------------------------------------------
                      Draw rigid elements
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun* df;
    vis_VisContext* vc;
    vis_ColorMap* cmap;
    vis_RigidElem* rigidelem;
    vis_EProp* eprop;
    GLWin* glwin;

    Vfloat x[4][3];
    Vint dofflagind[4], dofflagdep[4];
    Vfloat wgts[4];

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 200, 200, 400, 400);
    GLWinOrtho(glwin, -2., 2., -2., 2., -2., 2.);

    /* create draw function object for GL */
    df = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, df);

    vc = vis_VisContextBegin();
    vis_VisContextSetColor(vc, 1);
    vis_VisContextSetMinorColor(vc, 7);
    vis_VisContextSetSize(vc, .5);
    vis_VisContextSetShade(vc, VIS_VERTEXSHADE);
    vis_VisContextSetRefinement(vc, 2);
    vis_VisContextSetABCColor(vc, 3, 7, 7);

    /* color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetRGB(cmap, 8, 0, rgb);

    /* create eprop object to control display */
    eprop = vis_EPropBegin();
    vis_EPropDef(eprop, SYS_ELEM_RIGID);

    /* create rigidelem object and set objects */
    rigidelem = vis_RigidElemBegin();
    vis_RigidElemSetObject(rigidelem, VGL_DRAWFUN, df);
    vis_RigidElemSetObject(rigidelem, VIS_VISCONTEXT, vc);
    vis_RigidElemSetObject(rigidelem, VIS_COLORMAP, cmap);
    vis_RigidElemSetObject(rigidelem, VIS_EPROP, eprop);

    vis_VisContextSetElemRep(vc, VIS_ELEMREP_SOLID);
    vis_RigidElemSetParami(rigidelem, RIGIDELEM_PROP, VIS_ON);

    x[0][0] = 0.;
    x[0][1] = 0.;
    x[0][2] = 0.;
    x[1][0] = 1.;
    x[1][1] = 1.;
    x[1][2] = 1.;
    x[2][0] = 1.;
    x[2][1] = .5;
    x[2][2] = 0.;
    x[3][0] = 0.;
    x[3][1] = 1.;
    x[3][2] = 1.;

    /* draw distributing coupling, RBE3 */
    vis_VisContextSetFlags(vc, VIS_DOFBACK);
    vis_EPropSetValuei(eprop, EPROP_DOFFLAG_NUM, 4);
    dofflagdep[0] = 63;
    dofflagdep[1] = 0;
    dofflagdep[2] = 0;
    dofflagdep[3] = 0;
    dofflagind[0] = 0;
    dofflagind[1] = 7;
    dofflagind[2] = 7;
    dofflagind[3] = 7;
    vis_EPropSetValueiv(eprop, EPROP_DOFFLAG_IND, dofflagind);
    vis_EPropSetValueiv(eprop, EPROP_DOFFLAG_DEP, dofflagdep);
    wgts[0] = 1.;
    wgts[1] = 1.;
    wgts[2] = .5;
    wgts[3] = .25;
    vis_RigidElemSetParami(rigidelem, RIGIDELEM_WGTSIZEFLAG, VIS_ON);
    vis_RigidElemSetParamf(rigidelem, RIGIDELEM_WGTSIZE, .1f);
    vis_EPropSetValuefv(eprop, EPROP_DOFFLAG_WGTS, wgts);
    vis_RigidElemSetSpec(rigidelem, SYS_RIGID_DIST);
    /* 4 nodes; 1 dependent, 3 independent */
    vis_RigidElemSetTopology(rigidelem, SYS_SHAPEPOINT, 4);
    /* with properties */
    rotate_elem(df, rigidelem, x, "Distributing Coupling with Properties");
    vgl_DrawFunDelay(df, 2.);
    /* without properties */
    vis_RigidElemSetParami(rigidelem, RIGIDELEM_PROP, VIS_OFF);
    vis_RigidElemSetParami(rigidelem, RIGIDELEM_WGTSIZEFLAG, VIS_OFF);
    rotate_elem(df, rigidelem, x, "Distributing Coupling without Properties");
    vgl_DrawFunDelay(df, 2.);

    /* draw kinematic coupling, RBE2 */
    vis_RigidElemSetParami(rigidelem, RIGIDELEM_PROP, VIS_ON);
    vis_EPropSetValuei(eprop, EPROP_DOFFLAG_NUM, 2);
    dofflagdep[0] = 0;
    dofflagdep[1] = 7;
    dofflagind[0] = 63;
    dofflagind[1] = 0;
    vis_EPropSetValueiv(eprop, EPROP_DOFFLAG_IND, dofflagind);
    vis_EPropSetValueiv(eprop, EPROP_DOFFLAG_DEP, dofflagdep);
    vis_RigidElemSetSpec(rigidelem, SYS_RIGID_DIST);
    rotate_elem(df, rigidelem, x, "Kinematic Coupling");
    vgl_DrawFunDelay(df, 2.);

    /* rigid link, RROD */
    vis_RigidElemSetSpec(rigidelem, SYS_RIGID_LINK);
    vis_EPropSetValuei(eprop, EPROP_DOFFLAG_NUM, 2);
    dofflagdep[0] = 2;
    dofflagdep[1] = 0;
    dofflagind[0] = 5;
    dofflagind[1] = 7;
    vis_EPropSetValueiv(eprop, EPROP_DOFFLAG_IND, dofflagind);
    vis_EPropSetValueiv(eprop, EPROP_DOFFLAG_DEP, dofflagdep);
    vis_RigidElemSetTopology(rigidelem, SYS_SHAPELINE, 2);
    rotate_elem(df, rigidelem, x, "Rigid Link");
    vgl_DrawFunDelay(df, 2.);

    /* rigid triangular plate, RTRPLT */
    vis_RigidElemSetSpec(rigidelem, SYS_RIGID_KINE);
    vis_RigidElemSetTopology(rigidelem, SYS_SHAPETRI, 2);
    vis_RigidElemSetParami(rigidelem, RIGIDELEM_PROP, VIS_OFF);
    rotate_elem(df, rigidelem, x, "Rigid Triangular Plate");
    vgl_DrawFunDelay(df, 2.);

    /* multi-point constraint */
    vis_RigidElemSetSpec(rigidelem, SYS_RIGID_MPC);
    vis_EPropSetValuei(eprop, EPROP_DOFFLAG_NUM, 4);
    dofflagdep[0] = 2;
    dofflagdep[1] = 0;
    dofflagdep[2] = 0;
    dofflagdep[3] = 0;
    dofflagind[0] = 0;
    dofflagind[1] = 2;
    dofflagind[2] = 4;
    dofflagind[3] = 2;
    vis_EPropSetValueiv(eprop, EPROP_DOFFLAG_IND, dofflagind);
    vis_EPropSetValueiv(eprop, EPROP_DOFFLAG_DEP, dofflagdep);
    wgts[0] = 1.;
    wgts[1] = .5;
    wgts[2] = 1.51265f;
    wgts[3] = .5;
    vis_EPropSetValuefv(eprop, EPROP_DOFFLAG_WGTS, wgts);
    vis_RigidElemSetParami(rigidelem, RIGIDELEM_PROP, VIS_ON);
    vis_RigidElemSetTopology(rigidelem, SYS_SHAPEPOINT, 4);
    rotate_elem(df, rigidelem, x, "Multi-Point Constraint");
    vgl_DrawFunDelay(df, 2.);

    /* free all objects */
    vgl_DrawFunEnd(df);
    vis_VisContextEnd(vc);
    vis_ColorMapEnd(cmap);
    vis_RigidElemEnd(rigidelem);
    vis_EPropEnd(eprop);
    GLWinEnd(glwin);
    return 0;
}

/*----------------------------------------------------------------------
                      draw element
----------------------------------------------------------------------*/
void
draw_elem(vgl_DrawFun* df, vis_RigidElem* rigidelem, Vfloat x[][3], Vchar* text)
{
    vgl_DrawFunClear(df);
    vgl_DrawFunColor(df, ctex);
    vgl_DrawFunText(df, xtex, text);
    vis_RigidElemCurv(rigidelem, x);
    vgl_DrawFunSwap(df);
}

void
rotate_elem(vgl_DrawFun* df, vis_RigidElem* rigidelem, Vfloat x[][3], Vchar* text)
{
    Vint i;
    vgl_Xfm* xfm;
    Vfloat tm[4][4];

    xfm = vgl_XfmBegin();
    for (i = 0; i < 8; i++) {
        vgl_DrawFunClear(df);
        vgl_DrawFunColor(df, ctex);
        vgl_DrawFunText(df, xtex, text);
        vgl_DrawFunXfmPush(df);
        vgl_XfmRotate(xfm, -i * 8.F * 3.14F / 180.F, XFM_YAXIS);
        vgl_XfmGetMatrix(xfm, tm);
        vgl_DrawFunXfmLoad(df, tm);
        vis_RigidElemCurv(rigidelem, x);
        vgl_DrawFunSwap(df);
        vgl_DrawFunXfmPop(df);
        vgl_DrawFunDelay(df, 1.);
    }
    vgl_XfmEnd(xfm);
}

15.40. Example 18a, Draw Mass Elements - MassElem

This example illustrates using the MassElem module to draw mass elements. Like rigid elements, there are several special types of mass elements which have different properties, topologies, etc. The iconic representation is dependent upon the special type. Detailed element properties may be added to the basic icon if an EProp object is registered with MassElem and detailed element property drawing is enabled using vis_MassElemSetParami(). The detailed mass element properties consist of mass, rotary inertia, offset and connected degrees of freedom.

The first type drawn is a scalar mass (eg. NASTRAN CMASS1). The special type is set using vis_MassElemSetSpec() with value SYS_MASS_SCALAR. The topology should be SYS_SHAPELINE for a node to node mass. The scalar mass connects a y translation at the first node to a z translation at the second node. The topology is then changed to SYS_SHAPEPOINT for a single node. This will draw a node to ground scalar mass.

The next type drawn is a lumped mass with rotary inertia (eg. NASTRAN CONM2). The special type is set using vis_MassElemSetSpec() with value SYS_MASS_LUMP. The topology should be SYS_SHAPEPOINT. A local system is defined to orient the rotary inertia icons. The offset is drawn as a dashed line.

The final type drawn is a mass matrix (eg. NASTRAN CONM1). The special type is set using vis_MassElemSetSpec() with value SYS_MASS_MATRIX. The topology should be SYS_SHAPEPOINT. A local system is defined to orient the matrix icon. The mass matrix is also drawn as a bitmap by calling vis_VisContextSetElemRep() with value VIS_ELEMREP_BITMAP. The bitmap size is gradually increased.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

#include "glwin.h"

static Vfloat rgb[8][3] = {{.5f, .5f, .5f}, {1., 0., 0.}, {0., 1., 0.}, {0., 0., 1.},
                           {0., 1., 1.},    {1., 0., 1.}, {1., 1., 0.}, {1., 1., 1.}};

static Vfloat xtex[3] = {-1.8f, 1.5f, 0.};
static Vfloat ctex[3] = {1., 1., 1.};

void
draw_elem(vgl_DrawFun* df, vis_MassElem* masselem, Vfloat x[][3], Vchar* text);
void
rotate_elem(vgl_DrawFun* df, vis_MassElem* masselem, Vfloat x[][3], Vchar* text);

/*----------------------------------------------------------------------
                      Draw mass elements
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun* df;
    vis_VisContext* vc;
    vis_ColorMap* cmap;
    vis_MassElem* masselem;
    vis_EProp* eprop;
    vis_CoordSys* coordsys;
    GLWin* glwin;

    Vint i;
    Vfloat x[2][3];
    Vfloat xyzoff[3], inertia[6];
    Vfloat xo[3], v1[3], v2[3], vec[3];

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 200, 200, 400, 400);
    GLWinOrtho(glwin, -2., 2., -2., 2., -2., 2.);
    /* create drawing function object for GLWin */
    df = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, df);

    vc = vis_VisContextBegin();
    vis_VisContextSetColor(vc, 7);
    vis_VisContextSetMinorColor(vc, 1);
    vis_VisContextSetSize(vc, .5);
    vis_VisContextSetShade(vc, VIS_VERTEXSHADE);
    vis_VisContextSetRefinement(vc, 2);

    vis_VisContextSetXYZColor(vc, 4, 5, 6);
    vis_VisContextSetABCColor(vc, 3, 7, 7);
    /* color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetRGB(cmap, 8, 0, rgb);

    /* create eprop object to control display */
    eprop = vis_EPropBegin();
    vis_EPropDef(eprop, SYS_ELEM_MASS);

    /* create coordsys object to define local system */
    coordsys = vis_CoordSysBegin();
    vis_CoordSysDef(coordsys, SYS_CARTESIAN);

    /* create masselem object and set objects */
    masselem = vis_MassElemBegin();
    vis_MassElemSetObject(masselem, VGL_DRAWFUN, df);
    vis_MassElemSetObject(masselem, VIS_VISCONTEXT, vc);
    vis_MassElemSetObject(masselem, VIS_COLORMAP, cmap);
    vis_MassElemSetObject(masselem, VIS_EPROP, eprop);

    vis_VisContextSetElemRep(vc, VIS_ELEMREP_SOLID);
    vis_MassElemSetParami(masselem, MASSELEM_PROP, VIS_ON);

    x[0][0] = 0.;
    x[0][1] = 0.;
    x[0][2] = 0.;
    x[1][0] = 1.;
    x[1][1] = 1.;
    x[1][2] = 1.;

    /* draw scalar mass */
    vis_VisContextSetFlags(vc, VIS_DOFBACK);
    vis_EPropSetValuef(eprop, EPROP_MASS, 1.);
    vis_EPropSetValuei(eprop, EPROP_DOF1, 2);
    vis_EPropSetValuei(eprop, EPROP_DOF2, 4);
    vis_MassElemSetSpec(masselem, SYS_MASS_SCALAR);
    vis_MassElemSetTopology(masselem, SYS_SHAPELINE, 2);
    rotate_elem(df, masselem, x, "Node to Node Scalar Mass");
    vgl_DrawFunDelay(df, 2.);

    /* draw node to ground scalar mass */
    vis_MassElemSetTopology(masselem, SYS_SHAPEPOINT, 1);
    draw_elem(df, masselem, x, "Node to Ground Scalar Mass");
    vgl_DrawFunDelay(df, 2.);

    /* lumped mass with rotary inertia and offset */
    vis_MassElemSetSpec(masselem, SYS_MASS_LUMP);
    vis_VisContextSetMinorLineStyle(vc, VIS_DASHDASH);
    /* magnitudes of mass, inertia do not affect icon size */
    inertia[0] = 1.;
    inertia[1] = 2.;
    inertia[2] = 3.;
    inertia[3] = 1.;
    inertia[4] = 2.;
    inertia[5] = 3.;
    vis_EPropSetValuefv(eprop, EPROP_INERTIA, inertia);
    /* offset is represented physically */
    xyzoff[0] = .5;
    xyzoff[1] = .3f;
    xyzoff[2] = .1f;
    vis_EPropSetValuefv(eprop, EPROP_OFFSETVEC, xyzoff);
    /* set and draw local system orientation */
    vis_VisContextSetElemAxes(vc, VIS_ON);
    xo[0] = 0.;
    xo[1] = 0.;
    xo[2] = 0.;
    v1[0] = 1.;
    v1[1] = 1.;
    v1[2] = 0.;
    v2[0] = 0.;
    v2[1] = 1.;
    v2[2] = 0.;
    vis_CoordSysSetOriginVectors(coordsys, xo, v1, v2);
    vis_CoordSysRotAng(coordsys, x[0], vec);
    vis_MassElemSetLocalSystem(masselem, SYS_ELEMSYS_ROTANG, vec, 0.);
    rotate_elem(df, masselem, x, "Lumped Mass with Rotary Inertia");
    vgl_DrawFunDelay(df, 2.);

    /* mass matrix */
    vis_MassElemSetSpec(masselem, SYS_MASS_MATRIX);
    /* open box representation */
    rotate_elem(df, masselem, x, "Mass Matrix");
    vgl_DrawFunDelay(df, 2.);
    /* checker box representation */
    vis_MassElemSetParami(masselem, MASSELEM_CHECKER, VIS_ON);
    rotate_elem(df, masselem, x, "Mass Matrix");
    vgl_DrawFunDelay(df, 2.);

    /* mass matrix bitmap representation */
    vis_VisContextSetElemRep(vc, VIS_ELEMREP_BITMAP);
    vis_MassElemSetSpec(masselem, SYS_MASS_MATRIX);
    for (i = 1; i < 8; i++) {
        vis_VisContextSetBitmapSize(vc, i);
        draw_elem(df, masselem, x, "Mass Matrix");
        vgl_DrawFunDelay(df, 1.);
    }
    vgl_DrawFunDelay(df, 2.);

    /* free all objects */
    vgl_DrawFunEnd(df);
    vis_VisContextEnd(vc);
    vis_ColorMapEnd(cmap);
    vis_MassElemEnd(masselem);
    vis_EPropEnd(eprop);
    vis_CoordSysEnd(coordsys);
    GLWinEnd(glwin);

    return 0;
}

/*----------------------------------------------------------------------
                      draw element
----------------------------------------------------------------------*/
void
draw_elem(vgl_DrawFun* df, vis_MassElem* masselem, Vfloat x[][3], Vchar* text)
{
    vgl_DrawFunClear(df);
    vgl_DrawFunColor(df, ctex);
    vgl_DrawFunText(df, xtex, text);
    vis_MassElemCurv(masselem, x);
    vgl_DrawFunSwap(df);
}

void
rotate_elem(vgl_DrawFun* df, vis_MassElem* masselem, Vfloat x[][3], Vchar* text)
{
    Vint i;
    vgl_Xfm* xfm;
    Vfloat tm[4][4];

    xfm = vgl_XfmBegin();
    for (i = 0; i < 8; i++) {
        vgl_DrawFunClear(df);
        vgl_DrawFunColor(df, ctex);
        vgl_DrawFunText(df, xtex, text);
        vgl_DrawFunXfmPush(df);
        vgl_XfmRotate(xfm, -i * 8.F * 3.14F / 180.F, XFM_YAXIS);
        vgl_XfmGetMatrix(xfm, tm);
        vgl_DrawFunXfmLoad(df, tm);
        vis_MassElemCurv(masselem, x);
        vgl_DrawFunSwap(df);
        vgl_DrawFunXfmPop(df);
        vgl_DrawFunDelay(df, 1.);
    }
    vgl_XfmEnd(xfm);
}

15.41. Example 18b, Draw Spring and Dashpot Elements - DiscElem

This example illustrates using the DiscElem module to draw spring and dashpot elements. Like rigid and mass elements, there are several special types of spring and dashpot elements which have different properties, topologies, etc. The iconic representation is dependent upon the special type. Detailed element properties may be added to the basic icon if an EProp object is registered with DiscElem and detailed element property drawing is enabled using vis_DiscElemSetParami(). The detailed element properties consist of spring stiffness, dashpot damping and connected degrees of freedom.

The first type drawn is a scalar spring (eg. NASTRAN CELAS1). The special type is set using vis_DiscElemSetSpec() with value SYS_SPRINGDASHPOT_SCALAR. The topology should be SYS_SHAPELINE for a node to node spring. The element damping property is set to zero to suppress the drawing of the dashpot icon. The scalar spring connects a y translation at the first node to a z translation at the second node.

The next type drawn is a link spring and dashpot (eg. ANSYS COMBIN14). The special type is set using vis_DiscElemSetSpec() with value SYS_SPRINGDASHPOT_LINK. Element properties are set for both stiffness and damping to activate drawing the spring and dashpot icons. The topology should be SYS_SHAPELINE. The topology is then changed to SYS_SHAPEPOINT for a single node. This will draw a node to ground spring and dashpot. Then the stiffness and damping properties are successively set to zero to disable the spring and then the dashpot. The representation is then set to line by calling vis_VisContextSetElemRep() with value VIS_ELEMREP_LINE. Then the representation is set to bitmap and the bitmap size is gradually increased.

The next type drawn is a bush spring (eg. NASTRAN CBUSH). The special type is set using vis_DiscElemSetSpec() with value SYS_SPRINGDASHPOT_BUSH. The bush spring icon displays both translational and rotational spring stiffness icons. The topology should be SYS_SHAPELINE.

The final type drawn is a weld spring (eg. NASTRAN CWELD). The special type is set using vis_DiscElemSetSpec() with value SYS_SPRINGDASHPOT_WELD. The weld icon is assumed to have two physical endpoints. It is defined by a spot weld location and diameter and the nature of the connections at its two endpoints. A spot weld connection is assumed to be smeared over an adjacent element. The function vis_DiscElemSetEndTopo() is used to specify the topologies of the elements connected to each endpoint. In this case a 4 node quadrilateral for the first endpoint and a 3 node triangle for the second endpoint. The endpoint locations are specified using the function vis_DiscElemSetEndCon(). These endpoint locations are projected onto the elements connected to each endpoint. The topology of the element is SYS_SHAPEPOINT and maxi should be set to the total number of points in the adjacent connected elements.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

#include "glwin.h"

static Vfloat rgb[8][3] = {{.5, .5, .5}, {1., 0., 0.}, {0., 1., 0.}, {0., 0., 1.},
                           {0., 1., 1.}, {1., 0., 1.}, {1., 1., 0.}, {1., 1., 1.}};

static Vfloat xtex[3] = {-1.8f, 1.5f, 0.};
static Vfloat ctex[3] = {1., 1., 1.};

void
draw_elem(vgl_DrawFun* df, vis_DiscElem* discelem, Vfloat x[][3], Vchar* text);
void
rotate_elem(vgl_DrawFun* df, vis_DiscElem* discelem, Vfloat x[][3], Vchar* text);

/*----------------------------------------------------------------------
                      Draw discrete elements
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun* df;
    vis_VisContext* vc;
    vis_ColorMap* cmap;
    vis_DiscElem* discelem;
    vis_EProp* eprop;
    GLWin* glwin;

    int i;
    Vfloat x[7][3];
    Vfloat xend[3];

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 200, 200, 400, 400);
    GLWinOrtho(glwin, -2., 2., -2., 2., -2., 2.);

    /* create draw function object for GL */
    df = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, df);

    vc = vis_VisContextBegin();
    vis_VisContextSetColor(vc, 1);
    vis_VisContextSetMinorColor(vc, 7);
    vis_VisContextSetSize(vc, .5);
    vis_VisContextSetShade(vc, VIS_VERTEXSHADE);
    vis_VisContextSetRefinement(vc, 2);
    vis_VisContextSetABCColor(vc, 3, 7, 7);

    /* color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetRGB(cmap, 8, 0, rgb);

    /* create eprop object to control display */
    eprop = vis_EPropBegin();
    vis_EPropDef(eprop, SYS_ELEM_SPRINGDASHPOT);

    /* create discelem object and set objects */
    discelem = vis_DiscElemBegin();
    vis_DiscElemSetObject(discelem, VGL_DRAWFUN, df);
    vis_DiscElemSetObject(discelem, VIS_VISCONTEXT, vc);
    vis_DiscElemSetObject(discelem, VIS_COLORMAP, cmap);
    vis_DiscElemSetObject(discelem, VIS_EPROP, eprop);

    vis_VisContextSetElemRep(vc, VIS_ELEMREP_SOLID);

    vis_DiscElemSetParami(discelem, DISCELEM_WINDINGS, 2);
    vis_DiscElemSetParami(discelem, DISCELEM_PROP, VIS_ON);

    x[0][0] = 0.;
    x[0][1] = 0.;
    x[0][2] = 0.;
    x[1][0] = 1.;
    x[1][1] = 1.;
    x[1][2] = 1.;

    /* draw scalar spring */
    vis_VisContextSetFlags(vc, VIS_DOFBACK);
    vis_EPropSetValuei(eprop, EPROP_DOF1, 2);
    vis_EPropSetValuei(eprop, EPROP_DOF2, 4);
    vis_EPropSetValuef(eprop, EPROP_STIFF, 1.);
    vis_EPropSetValuef(eprop, EPROP_DAMP, 0.);
    vis_DiscElemSetSpec(discelem, SYS_SPRINGDASHPOT_SCALAR);
    vis_DiscElemSetTopology(discelem, SYS_SHAPELINE, 2);
    rotate_elem(df, discelem, x, "Node to Node Scalar Spring");
    vgl_DrawFunDelay(df, 2.);

    /* draw link spring and dashpot */
    vis_EPropSetValuef(eprop, EPROP_STIFF, 1.);
    vis_EPropSetValuef(eprop, EPROP_DAMP, 1.);
    vis_DiscElemSetSpec(discelem, SYS_SPRINGDASHPOT_LINK);
    vis_DiscElemSetTopology(discelem, SYS_SHAPELINE, 2);
    rotate_elem(df, discelem, x, "Node to Node Link Spring and Dashpot");
    vgl_DrawFunDelay(df, 2.);

    /* draw node to ground spring and dashpot */
    vis_DiscElemSetTopology(discelem, SYS_SHAPEPOINT, 1);
    draw_elem(df, discelem, x, "Node to Ground Spring and Dashpot");
    vgl_DrawFunDelay(df, 2.);

    /* draw node to ground dashpot only */
    vis_EPropSetValuef(eprop, EPROP_STIFF, 0.);
    draw_elem(df, discelem, x, "Node to Ground Link Dashpot");
    vgl_DrawFunDelay(df, 2.);

    /* draw node to ground spring only */
    vis_EPropSetValuef(eprop, EPROP_STIFF, 1.);
    vis_EPropSetValuef(eprop, EPROP_DAMP, 0.);
    draw_elem(df, discelem, x, "Node to Ground Link Spring");
    vgl_DrawFunDelay(df, 2.);

    /* draw node to ground spring only, line representation */
    vis_VisContextSetElemRep(vc, VIS_ELEMREP_LINE);
    draw_elem(df, discelem, x, "Node to Ground Link Spring");
    vgl_DrawFunDelay(df, 2.);

    /* draw node to ground spring only, bitmap representation */
    vis_VisContextSetElemRep(vc, VIS_ELEMREP_BITMAP);
    for (i = 1; i < 8; i++) {
        vis_VisContextSetBitmapSize(vc, i);
        draw_elem(df, discelem, x, "Node to Ground Link Spring");
        vgl_DrawFunDelay(df, 1.);
    }
    vgl_DrawFunDelay(df, 2.);
    vis_VisContextSetBitmapSize(vc, 1);

    /* draw bush with translation and rotation springs */
    vis_VisContextSetElemRep(vc, VIS_ELEMREP_SOLID);
    vis_EPropSetValuef(eprop, EPROP_STIFFTRA, 1.);
    vis_EPropSetValuef(eprop, EPROP_STIFFROT, 1.);
    vis_DiscElemSetSpec(discelem, SYS_SPRINGDASHPOT_BUSH);
    vis_DiscElemSetTopology(discelem, SYS_SHAPELINE, 2);
    rotate_elem(df, discelem, x, "Node to Node Bush");
    vgl_DrawFunDelay(df, 2.);

    /* draw weld with topological end connections */
    /* end A quad */
    x[0][0] = 0.;
    x[0][1] = 0.;
    x[0][2] = 0.;
    x[1][0] = 1.;
    x[1][1] = 0.;
    x[1][2] = 0.;
    x[2][0] = 1.;
    x[2][1] = 1.;
    x[2][2] = 0.;
    x[3][0] = 0.;
    x[3][1] = 1.;
    x[3][2] = 0.;
    /* end B tri */
    x[4][0] = 0.;
    x[4][1] = 0.;
    x[4][2] = 1.;
    x[5][0] = 1.;
    x[5][1] = 0.;
    x[5][2] = 1.;
    x[6][0] = 1.;
    x[6][1] = 1.;
    x[6][2] = 1.;

    /* set diameter of weld */
    vis_EPropSetValuef(eprop, EPROP_DOUT, .2f);
    vis_DiscElemSetSpec(discelem, SYS_SPRINGDASHPOT_WELD);
    /* set topologies of end points */
    vis_DiscElemSetEndTopo(discelem, SYS_TOPO_QUAD4SER, SYS_TOPO_TRI3);
    /* location of spot weld */
    xend[0] = .4f;
    xend[1] = .2f;
    xend[2] = .5;
    vis_DiscElemSetEndCon(discelem, SYS_ELEMEND_POSITION, xend, SYS_ELEMEND_POSITION, xend);
    vis_DiscElemSetTopology(discelem, SYS_SHAPEPOINT, 7);
    rotate_elem(df, discelem, x, "Elem to Elem Weld");
    vgl_DrawFunDelay(df, 2.);

    /* free all objects */
    vgl_DrawFunEnd(df);
    vis_VisContextEnd(vc);
    vis_ColorMapEnd(cmap);
    vis_DiscElemEnd(discelem);
    vis_EPropEnd(eprop);
    GLWinEnd(glwin);
    return 0;
}

/*----------------------------------------------------------------------
                      draw element
----------------------------------------------------------------------*/
void
draw_elem(vgl_DrawFun* df, vis_DiscElem* discelem, Vfloat x[][3], Vchar* text)
{
    vgl_DrawFunClear(df);
    vgl_DrawFunColor(df, ctex);
    vgl_DrawFunText(df, xtex, text);
    vis_DiscElemCurv(discelem, x);
    vgl_DrawFunSwap(df);
}

void
rotate_elem(vgl_DrawFun* df, vis_DiscElem* discelem, Vfloat x[][3], Vchar* text)
{
    Vint i;
    vgl_Xfm* xfm;
    Vfloat tm[4][4];

    xfm = vgl_XfmBegin();
    for (i = 0; i < 8; i++) {
        vgl_DrawFunClear(df);
        vgl_DrawFunColor(df, ctex);
        vgl_DrawFunText(df, xtex, text);
        vgl_DrawFunXfmPush(df);
        vgl_XfmRotate(xfm, -i * 8.F * 3.14F / 180.F, XFM_YAXIS);
        vgl_XfmGetMatrix(xfm, tm);
        vgl_DrawFunXfmLoad(df, tm);
        vis_DiscElemCurv(discelem, x);
        vgl_DrawFunSwap(df);
        vgl_DrawFunXfmPop(df);
        vgl_DrawFunDelay(df, 1.);
    }
    vgl_XfmEnd(xfm);
}

15.42. Example 18c, Draw Gap Elements - GapElem

This example illustrates using the GapElem module to draw gap elements. Detailed element properties may be added to the basic icon if an EProp object is registered with GapElem and detailed element property drawing is enabled using vis_GapElemSetParami(). The detailed element properties consist of initial gap.

The first type drawn is a node to node gap (eg. NASTRAN CGAP). The topology should be SYS_SHAPELINE. The gap element initial gap is set to .05. The node points are non coincident so that the gap local coordinate system, by default, will be constructed with the x’ direction oriented from the first to the second node. The initial gap will be accurately represented in the distance between the gap icons. Then the gap is drawn again with the two coincident nodes. In this case no x’ axis can be computed and an explicit element system should be specified using vis_GapElemSetLocalSystem(). The local system is displayed by enabling vis_VisContextSetElemAxes().

Finally the topology is set to a single point, the detailed element properties are disabled and a grounded gap is drawn.

#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

#include "glwin.h"

static Vfloat rgb[8][3] = {{.5, .5, .5}, {1., 0., 0.}, {0., 1., 0.}, {0., 0., 1.},
                           {0., 1., 1.}, {1., 0., 1.}, {1., 1., 0.}, {1., 1., 1.}};

static Vfloat xtex[3] = {-1.8f, 1.5f, 0.};
static Vfloat ctex[3] = {1., 1., 1.};

void
draw_elem(vgl_DrawFun* df, vis_GapElem* gapelem, Vfloat x[][3], Vchar* text);
void
rotate_elem(vgl_DrawFun* df, vis_GapElem* gapelem, Vfloat x[][3], Vchar* text);

/*----------------------------------------------------------------------
                      Draw gap elements
----------------------------------------------------------------------*/
int
main()
{
    vgl_DrawFun* df;
    vis_VisContext* vc;
    vis_ColorMap* cmap;
    vis_GapElem* gapelem;
    vis_EProp* eprop;
    vis_CoordSys* coordsys;
    GLWin* glwin;

    Vfloat x[2][3];
    Vfloat xo[3], v1[3], v2[3], vec[3];

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 200, 200, 400, 400);
    GLWinOrtho(glwin, -2., 2., -2., 2., -2., 2.);

    /* create draw function object for GL */
    df = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, df);

    vc = vis_VisContextBegin();
    vis_VisContextSetColor(vc, 1);
    vis_VisContextSetMinorColor(vc, 7);
    vis_VisContextSetSize(vc, .5);
    vis_VisContextSetShade(vc, VIS_VERTEXSHADE);
    vis_VisContextSetRefinement(vc, 2);
    vis_VisContextSetABCColor(vc, 3, 7, 7);
    vis_VisContextSetXYZColor(vc, 4, 5, 6);

    /* color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetRGB(cmap, 8, 0, rgb);

    /* create eprop object to control display */
    eprop = vis_EPropBegin();
    vis_EPropDef(eprop, SYS_ELEM_GAP);

    /* create coordsys object to define local system */
    coordsys = vis_CoordSysBegin();
    vis_CoordSysDef(coordsys, SYS_CARTESIAN);

    /* create gapelem object and set objects */
    gapelem = vis_GapElemBegin();
    vis_GapElemSetObject(gapelem, VGL_DRAWFUN, df);
    vis_GapElemSetObject(gapelem, VIS_VISCONTEXT, vc);
    vis_GapElemSetObject(gapelem, VIS_COLORMAP, cmap);
    vis_GapElemSetObject(gapelem, VIS_EPROP, eprop);

    vis_VisContextSetElemRep(vc, VIS_ELEMREP_SOLID);

    vis_GapElemSetParami(gapelem, DISCELEM_PROP, VIS_ON);

    x[0][0] = 0.;
    x[0][1] = 0.;
    x[0][2] = 0.;
    x[1][0] = 1.;
    x[1][1] = 0.;
    x[1][2] = 0.;

    /* draw node to node gap */
    vis_GapElemSetTopology(gapelem, SYS_SHAPELINE, 2);
    vis_EPropSetValuef(eprop, EPROP_UZERO, .05f);
    /* non coincident nodes */
    rotate_elem(df, gapelem, x, "Node to Node Gap Non Coincident");
    vgl_DrawFunDelay(df, 2.);
    /* coincident nodes, need local system for orientation */
    x[1][0] = 0.;
    x[1][1] = 0.;
    x[1][2] = 0.;
    vis_VisContextSetElemAxes(vc, VIS_ON);
    xo[0] = 0.;
    xo[1] = 0.;
    xo[2] = 0.;
    v1[0] = 1.;
    v1[1] = 1.;
    v1[2] = 0.;
    v2[0] = 0.;
    v2[1] = 1.;
    v2[2] = 0.;
    vis_CoordSysSetOriginVectors(coordsys, xo, v1, v2);
    vis_CoordSysRotAng(coordsys, x[0], vec);
    vis_GapElemSetLocalSystem(gapelem, SYS_ELEMSYS_ROTANG, vec, 0.);
    rotate_elem(df, gapelem, x, "Node to Node Gap Coincident");
    vgl_DrawFunDelay(df, 2.);

    /* draw node to ground gap */
    vis_GapElemSetParami(gapelem, DISCELEM_PROP, VIS_OFF);
    vis_GapElemSetTopology(gapelem, SYS_SHAPEPOINT, 1);
    rotate_elem(df, gapelem, x, "Node to Ground Gap");
    vgl_DrawFunDelay(df, 2.);

    /* free all objects */
    vgl_DrawFunEnd(df);
    vis_VisContextEnd(vc);
    vis_ColorMapEnd(cmap);
    vis_GapElemEnd(gapelem);
    vis_EPropEnd(eprop);
    vis_CoordSysEnd(coordsys);
    GLWinEnd(glwin);
    return 0;
}

/*----------------------------------------------------------------------
                      draw element
----------------------------------------------------------------------*/
void
draw_elem(vgl_DrawFun* df, vis_GapElem* gapelem, Vfloat x[][3], Vchar* text)
{
    vgl_DrawFunClear(df);
    vgl_DrawFunColor(df, ctex);
    vgl_DrawFunText(df, xtex, text);
    vis_GapElemCurv(gapelem, x);
    vgl_DrawFunSwap(df);
}

void
rotate_elem(vgl_DrawFun* df, vis_GapElem* gapelem, Vfloat x[][3], Vchar* text)
{
    Vint i;
    vgl_Xfm* xfm;
    Vfloat tm[4][4];

    xfm = vgl_XfmBegin();
    for (i = 0; i < 8; i++) {
        vgl_DrawFunClear(df);
        vgl_DrawFunColor(df, ctex);
        vgl_DrawFunText(df, xtex, text);
        vgl_DrawFunXfmPush(df);
        vgl_XfmRotate(xfm, -i * 8.F * 3.14F / 180.F, XFM_YAXIS);
        vgl_XfmGetMatrix(xfm, tm);
        vgl_DrawFunXfmLoad(df, tm);
        vis_GapElemCurv(gapelem, x);
        vgl_DrawFunSwap(df);
        vgl_DrawFunXfmPop(df);
        vgl_DrawFunDelay(df, 1.);
    }
    vgl_XfmEnd(xfm);
}

15.43. Example 19, Draw a 2D Polygon - Tess

This example illustrates using the Tess module to tesselate polygons bound by line segments and circular arcs. The line segments and arc may be overlapping. In this example there are three closed loops. The first two coincident along an edge, the third represents a hole. The sense of the line segments indicates material or void. As you move along the line segment in the plane material is to the left and void is to the right. The resulting polygon is drawn four times. The first time the arcs are tesselated to lines .1 world coordinate units long. The second and subsequent tesselations are controlled by device (pixel) size. Device sizing only affects the drawing of arcs. This is useful for retaining adapting the resolution of the tesselation to the size of the polygon on the graphics screen.

#include "base/base.h"
#include "vis/vis.h"
#include "vgl/vgl.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

static Vfloat rgb[7][3] = {{.2f, .2f, .2f}, {1., 0., 0.}, {0., 1., 0.}, {0., 0., 1.}, {0., 1., 1.}, {1., 0., 1.}, {1., 1., 0.}};

#define NPOINTS 13
#define NLINES  12

static Vfloat pts[NPOINTS][3] = {{-0.4f, -0.5f, 0.}, {0.4f, -0.5f, 0.}, {0.4f, 0.0, 0.},   {-0.4f, 0.0, 0.}, {-0.8f, 0.0, 0.},
                                 {0.8f, 0.0, 0.},    {0.8f, 0.8f, 0.},  {-0.8f, 0.8f, 0.}, {0.0, 0.5f, 0.},  {-0.2f, 0.2f, 0.},
                                 {-0.2f, 0.4f, 0.},  {0.2f, 0.4f, 0.},  {0.2f, 0.2f, 0.}};

static Vint lines[NLINES][3] = {
/* bottom polygon */
{1, 2, 0},
{2, 3, 0},
{3, 4, 0},
{4, 1, 0},
/* top polygon */
{5, 6, 0},
{6, 7, 0},
{7, 9, 8}, /* this is an arc */
{8, 5, 0},
/* hole in top polygon */
{10, 11, 0},
{11, 12, 0},
{12, 13, 0},
{13, 10, 0}};

/* text drawing */
static Vfloat xtxt[3] = {-0.8f, 0.9f, 0.};
static Vfloat white[3] = {1., 1., 1.};

/* device pixel sizes */
static Vint isize[3] = {5, 10, 50};

/*----------------------------------------------------------------------
                      Draw a 2D Polygon
----------------------------------------------------------------------*/
int
main()
{
#ifdef VKI_WIND_X11
    Display* display;
    int screen;
#endif
    vis_Tess* tess;
    vis_VisContext* vc;
    vis_ColorMap* cm;
    vgl_DrawFun* df;
    vgl_OpenGLDev* ogldev;
    Vint n;
    Vint devicesize;
    Vint parami[4];
    Vchar buffer[80];
    Vfloat paramf[16];

#ifdef VKI_WIND_X11
    /* open X display */
    display = XOpenDisplay(0);
    screen = DefaultScreen(display);
    vgl_OpenGLDevConnectX(display, screen);
#endif

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

#ifdef VKI_WIND_WIN32
    vgl_OpenGLDevConnectWIN();
#endif
    /* create GL device */
    ogldev = vgl_OpenGLDevBegin();

    /* create drawing functions */
    df = vgl_DrawFunBegin();
    vgl_OpenGLDevDrawFun(ogldev, df);
    vgl_DrawFunPositionWindow(df, 100, 400, 400, 400);
    vgl_DrawFunOpenWindow(df, "Example 19 vgl");
    vgl_DrawFunProjOrtho(df, -1., 1., -1., 1., -1., 1.);

    /* vis context and set attributes */
    vc = vis_VisContextBegin();
    vis_VisContextSetColor(vc, 3);
    vis_VisContextSetMinorColor(vc, 5);
    vis_VisContextSetLineWidth(vc, 2);
    vis_VisContextSetLineStyle(vc, VGL_LINESTYLE_DASH);
    vis_VisContextSetFill(vc, 1);
    vis_VisContextSetEdge(vc, 1);
    vis_VisContextSetPrimType(vc, VIS_PRIM_STRIP);

    /* color map */
    cm = vis_ColorMapBegin();
    vis_ColorMapSetType(cm, COLORMAP_TRUECOLOR);
    vis_ColorMapSetRGB(cm, 7, 0, rgb);

    /* tess object setup */
    tess = vis_TessBegin();
    vis_TessSetObject(tess, VIS_VISCONTEXT, vc);
    vis_TessSetObject(tess, VIS_COLORMAP, cm);
    vis_TessSetObject(tess, VGL_DRAWFUN, df);
    vis_TessSetParami(tess, TESS_EDGE, TESS_EDGE_OUTLINE);

    vis_TessDef(tess, NPOINTS, NLINES);
    for (n = 1; n <= NPOINTS; n++) {
        vis_TessSetPoint(tess, n, pts[n - 1]);
    }
    for (n = 1; n <= NLINES; n++) {
        if (lines[n - 1][2] == 0) {
            vis_TessSetLine(tess, n, lines[n - 1]);
        }
        else {
            vis_TessSetArc(tess, n, lines[n - 1]);
        }
    }
    /* illustrate world sizing and 3 device sizes */
    for (n = 1; n <= 4; n++) {
        vgl_DrawFunClear(df);
        vgl_DrawFunColor(df, white);
        /* world sizing */
        if (n == 1) {
            vgl_DrawFunText(df, xtxt, "World size= 0.1");
            vis_VisContextSetSizeType(vc, VIS_SIZEWORLD);
            vis_VisContextSetSize(vc, 0.1f);
            /* 3 device sizes, 5, 10 and 50 pixels */
            /* note that Size scales DeviceSize */
        }
        else {
            devicesize = isize[n - 2];
            sprintf(buffer, "Device size= %d", devicesize);
            vgl_DrawFunText(df, xtxt, buffer);
            vis_VisContextSetSizeType(vc, VIS_SIZEDEVICE);
            vis_VisContextSetSize(vc, 1.);
            vis_VisContextSetDeviceSize(vc, devicesize);
            vgl_DrawFunGetFloat(df, VGL_PROJECTIONMATRIX, paramf);
            vis_VisContextSetProjMatrix(vc, (Vfloat(*)[4])paramf);
            vgl_DrawFunGetFloat(df, VGL_MODELVIEWMATRIX, paramf);
            vis_VisContextSetXfmMatrix(vc, (Vfloat(*)[4])paramf);
            vgl_DrawFunGetInteger(df, VGL_VIEWPORT, parami);
            vis_VisContextSetViewport(vc, parami[0], parami[1], parami[2], parami[3]);
        }
        vis_TessDraw(tess);
        vgl_DrawFunSwap(df);
        vgl_DrawFunDelay(df, 5.);
    }

    /* close windows */
    vgl_DrawFunCloseWindow(df);

    /* free objects */
    vis_TessEnd(tess);
    vis_ColorMapEnd(cm);
    vis_VisContextEnd(vc);
    vgl_DrawFunEnd(df);
    vgl_OpenGLDevEnd(ogldev);

    /* close X display */
#ifdef VKI_WIND_X11
    XCloseDisplay(display);
#endif
    return 0;
}

15.44. Example 19a, Triangulate a Planar Slice of a Bounded Tesselation

This example illustrates using the Tess module to tesselate a planar slice through a solid represented by a closed boundary tesselation. A surface tesselation may be read from an input file in STL format or loaded from static arrays. The static arrays contain a simple unit cube. The cutting plane is normal to the z-axis and placed at the center of the z-coordinate extent of the input geometry.

The function outlinesurface loops through all triangles and extracts a line which is the intersection of the cutting plane with the triangle. A possible performance optimization would be to select only those triangles which lie on the cutting plane using a geometric search tree. The line end points and line connectivity are entered into a Connect object for convenience. The line connectivity is oriented so that the cross product of the direction of the line with the normal to the cutting plane points out of the body of the geometry.

The intersection lines and points are passed to the Tess object for tesselation. The Tess object will merge all coincident points.

#include <stdio.h>
#include "base/base.h"
#include "vgl/vgl.h"
#include "vis/vis.h"
#include "vis/exam/glwin.h"
#include "base/license.h"
#include "CEETRON_SAM_license.h"

static Vfloat rgb[7][3] = {{.2f, .2f, .2f}, {1., 0., 0.}, {0., 1., 0.}, {0., 0., 1.}, {0., 1., 1.}, {1., 0., 1.}, {1., 1., 0.}};

/* a simple hollow cube */
static Vdouble coords[16][3] = {{-10., -10., -10.}, {10., -10., -10.}, {-10., 10., -10.}, {10., 10., -10.},
                                {-10., -10., 10.},  {10., -10., 10.},  {-10., 10., 10.},  {10., 10., 10.},
                                {-11., -11., -11.}, {11., -11., -11.}, {-11., 11., -11.}, {11., 11., -11.},
                                {-11., -11., 11.},  {11., -11., 11.},  {-11., 11., 11.},  {11., 11., 11.}};

static Vint tris[24][3] = {{3, 5, 1},    {7, 5, 3},    {2, 6, 4},    {4, 6, 8},    {5, 2, 1},    {6, 2, 5},
                           {3, 4, 7},    {7, 4, 8},    {2, 4, 1},    {3, 1, 4},    {7, 8, 5},    {8, 6, 5},
                           {9, 13, 11},  {11, 13, 15}, {12, 14, 10}, {16, 14, 12}, {9, 10, 13},  {13, 10, 14},
                           {15, 12, 11}, {16, 12, 15}, {9, 12, 10},  {12, 9, 11},  {13, 16, 15}, {13, 14, 16}};

void
loadsurface(vis_Connect* connectsrf);
void
readsurface(vis_Connect* connectsrf, Vchar* path);
void
outlinesurface(vis_Connect* connectsrf, Vdouble xn[3], Vdouble vn[3], vis_Tess* tess);

/*----------------------------------------------------------------------
         Cross product between two vectors
----------------------------------------------------------------------*/
static void
cross(Vdouble a[3], Vdouble b[3], Vdouble c[3])
{
    c[0] = a[1] * b[2] - a[2] * b[1];
    c[1] = a[2] * b[0] - a[0] * b[2];
    c[2] = a[0] * b[1] - a[1] * b[0];
}

/*----------------------------------------------------------------------
         Difference between two vectors
----------------------------------------------------------------------*/
static void
diff(Vdouble a[3], Vdouble b[3], Vdouble c[3])
{
    c[0] = a[0] - b[0];
    c[1] = a[1] - b[1];
    c[2] = a[2] - b[2];
}

/*----------------------------------------------------------------------
                      Triangulate a Planar Slice of a Bounded Tesselation
----------------------------------------------------------------------*/
int
main(int argc, char** argv)
{
    vis_Connect* connectsrf;
    vis_Tess* tess;
    vis_VisContext* vc;
    vis_ColorMap* cmap;
    GLWin* glwin;
    vgl_DrawFun* df;

    Vdouble bbox[2][3], d[3], blen, xn[3], vn[3];
    Vfloat xmin, xmax, ymin, ymax;
    Vfloat dx, dy, xc, yc, sca;
    Vint numunrec, numdrawtri;

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* create connect object of surface */
    connectsrf = vis_ConnectBegin();
    /* load surface from static arrays */
    if (argc < 2) {
        loadsurface(connectsrf);
        /* read surface from STL file */
    }
    else {
        readsurface(connectsrf, argv[1]);
    }
    /* compute extent */
    vis_ConnectExtentdv(connectsrf, NULL, bbox);
    diff(bbox[1], bbox[0], d);
    blen = sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);

    /* cutting plane normal to z axis */
    xn[0] = 0.;
    xn[1] = 0.;
    xn[2] = .5 * (bbox[0][2] + bbox[1][2]);

    vn[0] = 0.;
    vn[1] = 0.;
    vn[2] = 1.;

    xmin = (Vfloat)bbox[0][0];
    xmax = (Vfloat)bbox[1][0];
    ymin = (Vfloat)bbox[0][1];
    ymax = (Vfloat)bbox[1][1];
    /* determine orthographic limits to fit view */
    /* assuming a square viewport */
    dx = xmax - xmin;
    xc = .5F * (xmax + xmin);
    dy = ymax - ymin;
    yc = .5F * (ymax + ymin);
    if (dx > dy) {
        sca = dx / dy;
        ymin = yc - .5F * sca * dy;
        ymax = yc + .5F * sca * dy;
    }
    else {
        sca = dy / dx;
        xmin = xc - .5F * sca * dx;
        xmax = xc + .5F * sca * dx;
    }
    /* add a bit of margin */
    xmin = xmin - .05F * (xmax - xmin);
    xmax = xmax + .05F * (xmax - xmin);
    ymin = ymin - .05F * (ymax - ymin);
    ymax = ymax + .05F * (ymax - ymin);
    /* create GL device */
    glwin = GLWinBegin();
    GLWinCreateWindow(glwin, 200, 200, 400, 400);
    /* create draw function object for GL */
    df = vgl_DrawFunBegin();
    GLWinDrawFun(glwin, df);
    GLWinOrtho(glwin, xmin, xmax, ymin, ymax, -10000., 10000);

    tess = vis_TessBegin();
    vis_TessDef(tess, 0, 0);
    /* create outline mesh on surface triangles */
    /* create tess object */
    outlinesurface(connectsrf, xn, vn, tess);

    /* visualization context */
    vc = vis_VisContextBegin();
    vis_VisContextSetColor(vc, 4);
    vis_VisContextSetMinorColor(vc, 5);
    vis_VisContextSetShade(vc, VIS_VERTEXSHADE);
    vis_VisContextSetPrimType(vc, VIS_PRIM_STRIP);
    vis_VisContextSetEdge(vc, VIS_ON);

    /* color map */
    cmap = vis_ColorMapBegin();
    vis_ColorMapSetType(cmap, COLORMAP_TRUECOLOR);
    vis_ColorMapSetRGB(cmap, 7, 0, rgb);

    /* normal to cutting plane */
    vis_TessSetNormaldv(tess, vn);
    /* set objects for drawing */
    vis_TessSetObject(tess, VIS_VISCONTEXT, vc);
    vis_TessSetObject(tess, VIS_COLORMAP, cmap);
    vis_TessSetObject(tess, VGL_DRAWFUN, df);
    vis_TessSetParamd(tess, TESS_INTERTOL, .00001 * blen);

    /* draw */
    GLWinClear(glwin);
    vis_TessDraw(tess);
    vis_TessGetInteger(tess, TESS_NUMUNREC, &numunrec);
    vis_TessGetInteger(tess, TESS_NUMDRAWTRI, &numdrawtri);
    if (numunrec || numdrawtri == 0) {
        printf("numunrec=   %d\n", numunrec);
        printf("numdrawtri= %d\n", numdrawtri);
    }
    GLWinSwap(glwin);
    sleep(10);
    /* end Tess */
    vis_ConnectEnd(connectsrf);
    vis_TessEnd(tess);
    vis_ColorMapEnd(cmap);
    vis_VisContextEnd(vc);
    GLWinEnd(glwin);
    vgl_DrawFunEnd(df);
    return 0;
}

void
loadsurface(vis_Connect* connectsrf)
{
    Vint i;

    printf("load surface from static arrays\n");
    vis_ConnectDef(connectsrf, 0, 0);
    /* set nodes */
    for (i = 0; i < 16; i++) {
        vis_ConnectSetCoordsdv(connectsrf, i + 1, coords[i]);
    }
    /* set triangles */
    for (i = 0; i < 24; i++) {
        vis_ConnectSetTopology(connectsrf, i + 1, VIS_SHAPETRI, 2, 0, 0);
        vis_ConnectSetElemNode(connectsrf, i + 1, tris[i]);
    }
}

void
readsurface(vis_Connect* connectsrf, Vchar* path)
{
    vis_Connect* connect;

    connect = vis_ConnectBegin();
    if (strstr(path, ".stl") != NULL) {
        printf("read surface from stl file: %s\n", path);
        vis_ConnectRead(connect, SYS_FILE_STL, path);
    }
    else if (strstr(path, ".STL") != NULL) {
        printf("read surface from binary stl file: %s\n", path);
        vis_ConnectRead(connect, SYS_FILE_STLBIN, path);
    }
    /* copy it */
    vis_ConnectCopy(connectsrf, connect);
    vis_ConnectEnd(connect);
}

void
outlinesurface(vis_Connect* connectsrf, Vdouble xn[3], Vdouble vn[3], vis_Tess* tess)
{
    Vint k, m;
    Vdouble x[3][3];
    Vint ntris;
    Vint nplus, nminus;
    Vint np, lp[2], lix[2], npnts, nlins;
    Vint nix, ix[3];
    Vdouble d[3], dt[3], dx[3];
    Vint s[3];
    Vdouble xl[2][3], xd[3], xc[3], dot, f;
    Vdouble vt[3][3];

    vis_ConnectNumber(connectsrf, SYS_ELEM, &ntris);
    npnts = 0;
    nlins = 0;
    /* determine intersection line of plane and triangle */
    for (m = 1; m <= ntris; m++) {
        vis_ConnectElemNode(connectsrf, m, &nix, ix);
        vis_ConnectCoordsdv(connectsrf, nix, ix, x);
        nplus = nminus = 0;
        for (k = 0; k < 3; k++) {
            diff(x[k], xn, d);
            dt[k] = vn[0] * d[0] + vn[1] * d[1] + vn[2] * d[2];
            if (dt[k] >= 0.) {
                s[k] = 1;
                nplus += 1;
            }
            else if (dt[k] < 0.) {
                s[k] = -1;
                nminus += 1;
            }
        }
        if (nplus == 0 || nminus == 0)
            continue;
        /* compute exact intersection points */
        np = 0;
        for (k = 0; k < 3; k++) {
            if (s[k] == 0)
                continue;
            if (s[(k + 1) % 3] * s[k] == 1)
                continue;
            diff(x[(k + 1) % 3], x[k], dx);
            f = dt[k] / (dt[k] - dt[(k + 1) % 3]);
            xl[np][0] = x[k][0] + f * dx[0];
            xl[np][1] = x[k][1] + f * dx[1];
            xl[np][2] = x[k][2] + f * dx[2];
            lp[np] = ++npnts;
            vis_TessSetPointdv(tess, lp[np], xl[np]);
            np += 1;
        }
        vis_ConnectElemNormdv(connectsrf, m, 1, vt);
        diff(xl[1], xl[0], xd);
        cross(xd, vn, xc);
        dot = xc[0] * vt[0][0] + xc[1] * vt[0][1] + xc[2] * vt[0][2];
        if (dot >= 0.) {
            lix[0] = lp[0];
            lix[1] = lp[1];
        }
        else {
            lix[1] = lp[0];
            lix[0] = lp[1];
        }
        nlins += 1;
        vis_TessSetLine(tess, nlins, lix);
    }
}