Logo Search packages:      
Sourcecode: felt version File versions  Download package

vfe.c

/*
    This file is part of the FElt finite element analysis package.
    Copyright (C) 1993-2000 Jason I. Gobat and Darren C. Atkinson

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/************************************************************************
 * File:    vfe.c                                     *
 *                                                    *
 * Description:   This file contains the function definitions for the   *
 *          visualization of the finite element structures.       *
 ************************************************************************/

# include <stdio.h>
# include <string.h>
# include <X11/Intrinsic.h>
# include <X11/StringDefs.h>
# include <X11/Xaw/Viewport.h>
# include "Drawing.h"
# include "Canvas.h"
# include "fe.h"
# include "vfe.h"
# include "error.h"
# include "problem.h"
# include "objects.h"
# include "allocate.h"
# include "globals.h"
# include "procedures.h"

# define Valid(x) (appearance.x != UnspecifiedValue)
# define Present(x)     (appearance.x != NULL)


extern CanvasDialog     canvas_d;
static FigureAttributes attributes;


/************************************************************************
 * Function:      DrawDisplayList                                 *
 *                                                    *
 * Description:   Draws the display list from the appearance structure. *
 ************************************************************************/

static void DrawDisplayList ( )
{
    unsigned  i;
    unsigned  j;
    Figure    figure;
    Point     points [1024];
    FigInfo  *info;


    /* In case no colors are fonts are specified. */

    figure = NULL;

    if (DW_SetForeground (drawing, canvas -> tool_color) == False)
      DW_SetForeground (drawing, "black");

    if (DW_SetFont (drawing, canvas -> tool_font) == False)
      DW_SetFont (drawing, "fixed");

    for (i = 0; i < appearance.num_figures; i ++) {
      info = &appearance.figures [i];

      if (info -> color)
          DW_SetForeground (drawing, info -> color);


      switch (info -> type) {
      case RECTANGLE:
          figure = DW_DrawRectangle (drawing, True, info -> x, info -> y,
                              info -> width, info -> height);
          TreeInsert (figure_tree, figure);
          break;

      case POLYLINE:
          if (info -> num_points == 2) {
            figure = DW_DrawLine (drawing, info -> points [0].x,
                              info -> points [0].y,
                              info -> points [1].x,
                              info -> points [1].y);

          } else if (info -> num_points > 2) {
            for (j = 0; j < info -> num_points; j ++) {
                points [j].x = info -> points [j].x;
                points [j].y = info -> points [j].y;
            }

            figure = DW_DrawPolygon (drawing, True, points,
                              info -> num_points);
          }

          TreeInsert (figure_tree, figure);
          break;

      case TEXT:
          if (info -> font)
              DW_SetFont (drawing, info -> font);

          figure = DW_DrawText (drawing, True, info -> x, info -> y,
                              info -> text);
          TreeInsert (figure_tree, figure);
          break;

      case ARC:
          figure = DW_DrawArc (drawing, True, info -> x, info -> y,
                              info -> width, info -> height,
                              info -> start, info -> length);
          TreeInsert (figure_tree, figure);
          break;
      }
    }
}


/************************************************************************
 * Function:      DrawProblem                               *
 *                                                    *
 * Description: Draw the problem.  We try to present a suitable viewing *
 *          of the problem if the appearance structure is not     *
 *          presence.  If only some of the appearance structure is      *
 *          valid then we try to compromise and keep what         *
 *          information is valid.                           *
 ************************************************************************/

void DrawProblem (z)
    double   z;
{
    unsigned  i;
    Node      n;
    float     xmin, xmax;
    float     ymin, ymax;
    float     scale;
    float     xrange;
    float     yrange;
    Dimension height;
    Dimension width;
    Cardinal  count;
    Boolean   new_limits;
    Arg       arglist [10];


    /* Compute the maximum and minimum values. */

    xmin = 1;
    xmax = -1;
    ymin = 1;
    ymax = -1;

    for (i = 1; i <= problem.num_nodes; i ++) {
      n = problem.nodes [i];

      if (n -> z == z)
          if (xmin > xmax) {
            xmin = xmax = n -> x;
            ymin = ymax = n -> y;
          } else {
            if (n -> x < xmin)
                xmin = n -> x;
            else if (n -> x > xmax)
                xmax = n -> x;
            if (n -> y < ymin)
                ymin = n -> y;
            else if (n -> y > ymax)
                ymax = n -> y;
          }
    }

    if (xmin > xmax && problem.num_nodes)
      error ("No nodes lie within the plane z = %g.", z);


    /* Expand the minimum and maximum a bit. */

    if (xmin >= xmax) {
      xmin -= .1 * (ymax - ymin);
      xmax += .1 * (ymax - ymin);
    }

    if (ymin >= ymax) {
      ymin -= .1 * (xmax - xmin);
      ymax += .1 * (xmax - xmin);
    }


    if (xmax - xmin < ymax - ymin)
      canvas -> snap_size = canvas -> grid_size = (ymax - ymin) / 10;
    else
      canvas -> snap_size = canvas -> grid_size = (xmax - xmin) / 10;

    xrange = xmax - xmin;
    xmin -= .05 * xrange;
    xmax += .05 * xrange;
    xrange = xmax - xmin;

    yrange = ymax - ymin;
    ymin -= .05 * yrange;
    ymax += .05 * yrange;
    yrange = ymax - ymin;

    new_limits = False;


    /* If the x-axis limits are valid, then use them. */

    if (Valid (x_min) && Valid (x_max))
      if (appearance.x_min < appearance.x_max) {
          xmin = appearance.x_min;
          xmax = appearance.x_max;
          new_limits = True;
      }


    /* If the y-axis limits are valid, then use them. */

    if (Valid (y_min) && Valid (y_max))
      if (appearance.y_min < appearance.y_max) {
          ymin = appearance.y_min;
          ymax = appearance.y_max;
          new_limits = True;
      }


    /* Check the grid size and recompute it if necessary. */

    if (Valid (grid_size))
      canvas -> grid_size = appearance.grid_size;
    else if (new_limits) {
      if (xmax - xmin < ymax - ymin)
          canvas -> grid_size = (ymax - ymin) / 10;
      else
          canvas -> grid_size = (xmax - xmin) / 10;
    }


    /* Check the snap size and recompute it if necessary. */

    if (Valid (snap_size))
      canvas -> snap_size = appearance.snap_size;
    else if (new_limits) {
      if (xmax - xmin < ymax - ymin)
          canvas -> snap_size = (ymax - ymin) / 10;
      else
          canvas -> snap_size = (xmax - xmin) / 10;
    }


    count = 0;
    XtSetArg (arglist [count], XtNwidth, &width); count ++;
    XtSetArg (arglist [count], XtNheight, &height); count ++;
    XtGetValues (viewport, arglist, count);


    /* If the width, height, and scale are ALL valid, then use them. */

    if (Valid (width) && Valid (height) && Valid (scale)) {
      scale = appearance.scale;
      width = appearance.width;
      height = appearance.height;
    } else {
      if (xrange / width > yrange / height) {
          scale = width / xrange;
          ymax += (xrange - yrange) / 2;
          ymin -= (xrange - yrange) / 2;
      } else {
          scale = height / yrange;
          xmax += (yrange - xrange) / 2;
          xmin -= (yrange - xrange) / 2;
      }
    }


    /* Set up the canvas dialog. */

    canvas -> xmin = xmin;
    canvas -> xmax = xmax;
    canvas -> ymin = ymin;
    canvas -> ymax = ymax;
    canvas -> scale = scale;

    if (Valid (node_numbers))
      canvas -> node_numbers = appearance.node_numbers;

    if (Valid (element_numbers))
      canvas -> element_numbers = appearance.element_numbers;

    if (Present (node_color))
      canvas -> node_color = strdup (appearance.node_color);

    if (Present (element_color))
      canvas -> element_color = strdup (appearance.element_color);

    if (Present (label_font))
      canvas -> label_font = strdup (appearance.label_font);

    if (Present (tool_color))
      canvas -> tool_color = strdup (appearance.tool_color);

    if (Present (tool_font))
      canvas -> tool_font = strdup (appearance.tool_font);

    CanvasDialogSet (canvas_d);


    if (Valid (grid) && appearance.grid != canvas -> grid)
      ToggleGridStatus ( );

    if (Valid (snap) && appearance.snap != canvas -> snap)
      ToggleSnapStatus ( );


    /* Draw the problem. */

    for (i = 1; i <= problem.num_elements; i ++)
      if (problem.elements [i] != NULL)
          DrawElement (problem.elements [i], i == 1 ? True : False);

    for (i = 1; i <= problem.num_nodes; i ++)
      if (problem.nodes [i] != NULL)
          DrawNode (problem.nodes [i], i == 1 ? True : False);

    DrawDisplayList ( );

    count = 0;
    XtSetArg (arglist [count], XtNwidth, width); count ++;
    XtSetArg (arglist [count], XtNheight, height); count ++;
    XtSetValues (viewport, arglist, count);

    XawViewportSetCoordinates (viewport, -appearance.x_pos, -appearance.y_pos);
    InitAppearance ( );
}


/************************************************************************
 * Function:      DestroyProblem                                  *
 *                                                    *
 * Description:   Destroy the current problem invocation.               *
 ************************************************************************/

void DestroyProblem (material_op)
    ItemDestructor material_op;
{
    (void) TreeSetDestructor (problem.node_tree, (ItemDestructor)
            DestroyNode);
    (void) TreeDestroy (problem.node_tree);

    (void) TreeSetDestructor (problem.element_tree, (ItemDestructor)
            DestroyElement);
    (void) TreeDestroy (problem.element_tree);

    (void) TreeSetDestructor (problem.force_tree, (ItemDestructor)
            DestroyForce);
    (void) TreeDestroy (problem.force_tree);

    (void) TreeSetDestructor (problem.material_tree, (ItemDestructor)
            material_op);
    (void) TreeDestroy (problem.material_tree);

    (void) TreeSetDestructor (problem.constraint_tree, (ItemDestructor)
            DestroyConstraint);
    (void) TreeDestroy (problem.constraint_tree);

    (void) TreeSetDestructor (problem.distributed_tree, (ItemDestructor)
            DestroyDistributed);
    (void) TreeDestroy (problem.distributed_tree);
}


/************************************************************************
 * Function:      setnodenum                                *
 *                                                    *
 * Description:   Sets the node numbering for a specified node.         *
 ************************************************************************/

static int setnodenum (item)
    Item item;
{
    static char        number [10];
    FigureAttributes attr;
    Node         node;
    Drawn        drawn;
    float        x;
    float        y;


    node = (Node) item;
    drawn = (Drawn) node -> aux;

    if (drawn -> figure == NULL)
      return 0;

    if (drawn -> label == NULL) {
      x = node -> x;
      y = node -> y;
      sprintf (number, " %d", node -> number);
      drawn -> label = DW_DrawText (drawing, True, x, y, number);
      attr.user_data = (char *) node;
      DW_SetAttributes (drawing, drawn -> label, DW_FigureUserData, &attr);
    }

    DW_SetAttributes (drawing, drawn -> label, DW_FigureVisible, &attributes);
    return 0;
}


/************************************************************************
 * Function:      SetNodeNumbering                          *
 *                                                    *
 * Description:   Set the node numbering status.                        *
 ************************************************************************/

void SetNodeNumbering (value)
    int value;
{
    if (DW_SetForeground (drawing, canvas -> node_color) == False)
      (void) DW_SetForeground (drawing, "black");

    if (DW_SetFont (drawing, canvas -> label_font) == False)
      (void) DW_SetFont (drawing, "fixed");

    attributes.visible = value;
    DW_SetAutoRedraw (drawing, False);
    (void) TreeSetIterator (problem.node_tree, setnodenum);
    (void) TreeIterate (problem.node_tree);
    DW_SetAutoRedraw (drawing, True);
}


/************************************************************************
 * Function:      setelementnum                                   *
 *                                                    *
 * Description:   Sets the element numbering for a specified element.   *
 ************************************************************************/

static int setelementnum (item)
    Item item;
{
    static char        number [10];
    FigureAttributes attr;
    Element      element;
    Drawn        drawn;
    float        x;
    float        y;


    element = (Element) item;
    drawn = (Drawn) element -> aux;

    if (drawn -> figure == NULL)
      return 0;

    if (drawn -> label == NULL) {
      ComputeCenter (element, &x, &y);
      sprintf (number, "%d", element -> number);
      drawn -> label = DW_DrawText (drawing, True, x, y, number);
      attr.user_data = (char *) element;
      DW_SetAttributes (drawing, drawn -> label, DW_FigureUserData, &attr);
    }

    DW_SetAttributes (drawing, drawn -> label, DW_FigureVisible, &attributes);
    return 0;
}


/************************************************************************
 * Function:      SetElementNumbering                             *
 *                                                    *
 * Description:   Set the element numbering status.               *
 ************************************************************************/

void SetElementNumbering (value)
    int value;
{
    if (DW_SetForeground (drawing, canvas -> element_color) == False)
      (void) DW_SetForeground (drawing, "black");

    if (DW_SetFont (drawing, canvas -> label_font) == False)
      (void) DW_SetFont (drawing, "fixed");

    attributes.visible = value;
    DW_SetAutoRedraw (drawing, False);
    (void) TreeSetIterator (problem.element_tree, setelementnum);
    (void) TreeIterate (problem.element_tree);
    DW_SetAutoRedraw (drawing, True);
}

static int RecolorNode (item)
   Item           item;
{
   Node                 n;
   FigureAttributes     attrib;
   Drawn          drawn;

   n = (Node) item;
   drawn = (Drawn) n -> aux;

   if (n -> force && n -> force -> color) 
      attrib.color = n -> force -> color; 
   else if (n -> constraint -> color) 
      attrib.color = n -> constraint -> color; 
   else 
      attrib.color = canvas -> node_color;

   if (drawn -> figure)
      DW_SetAttributes (drawing, drawn -> figure, DW_FigureColor, &attrib);
   if (drawn -> label)
      DW_SetAttributes (drawing, drawn -> label, DW_FigureColor, &attrib);

   return 0;
}

static int RecolorElement (item)
   Item           item;
{
   FigureAttributes     attrib;
   Element        e;
   Drawn          drawn;

   e = (Element) item;
   drawn = (Drawn) e -> aux;

   if (e -> numdistributed && e -> distributed[1] -> color) 
      attrib.color = e -> distributed[1] -> color; 
   else if (e -> material -> color) 
      attrib.color = e -> material -> color; 
   else 
      attrib.color = canvas -> element_color;

   if (drawn -> figure)
      DW_SetAttributes (drawing, drawn -> figure, DW_FigureColor, &attrib);
   if (drawn -> label)
      DW_SetAttributes (drawing, drawn -> label, DW_FigureColor, &attrib);

   return 0;
} 

/************************************************************************
 * Function:      RecolorCanvas                                   *
 *                                                    *
 * Description:   Resets the color attribute of all nodes and elements  *
 *          based on possibly new values of object coloring       *
 ************************************************************************/

void RecolorCanvas ( )
{
   DW_SetAutoRedraw (drawing, False);

   TreeSetIterator (problem.node_tree, RecolorNode);
   TreeIterate (problem.node_tree);

   TreeSetIterator (problem.element_tree, RecolorElement);
   TreeIterate (problem.element_tree);

   DW_SetAutoRedraw (drawing, True);

   return;   
}

Generated by  Doxygen 1.6.0   Back to index