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

nodeop.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.
*/

# include <stdio.h>
# include <string.h>
# include <stdlib.h>
# include <X11/Intrinsic.h>
# include <X11/StringDefs.h>
# include <X11/Xaw/Simple.h>
# include "fe.h"
# include "Constraint.h"
# include "Canvas.h"
# include "Drawing.h"
# include "procedures.h"
# include "problem.h"
# include "globals.h"
# include "vfe.h"
# include "text_entry.h"
# include "objects.h"
# include "error.h"
# include "Node.h"

extern ConstraintDialog constraint_d;
extern NodeDialog node_d;

void EditAddNode ()
{

   if (ConstraintDialogActive (constraint_d) == NULL) {
      error ("No active constraint defined.");
      return;
   }

   SetEditMode ( );
   ChangeStatusLine ("Nodal coordinates:", True);

   XtRemoveAllCallbacks (drawing, XtNbuttonCallback);
   XtAddCallback (drawing, XtNbuttonCallback, AddNodeCB, NULL);

   XtOverrideTranslations (entry, 
           XtParseTranslationTable ("<Key>Return: AddNodeAP()"));
}

void AddNodeCB (w, client_data, call_data)
   Widget   w;
   XtPointer      client_data,
            call_data;
{
   DrawingReport  *report;

   report = (DrawingReport *) call_data;

   if (report -> event -> type != ButtonPress)
      return;

   if (report -> event -> xbutton.button == 1)
      DoAddNode (report -> snapped.x, report -> snapped.y, 0.0);

   if (report -> event -> xbutton.button == 3)
      QuitEdit ( );
}

void AddNodeAP ()
{
   char *status;
   float x,y,z = 0;

   status = GetTextCoordinates (&x, &y, NULL);
   if (status == NULL)
      DoAddNode (x, y, z);
}

void DoAddNode (x, y, z)
   float    x,y,z;
{
   char     message [40];
   Node     node;
   unsigned max;

   node = (Node) TreeMaximum (problem.node_tree);
   max = node != NULL ? node -> number : 0;

   node = CreateNode (max + 1);
   node -> constraint = ConstraintDialogActive (constraint_d);
   node -> x = x;
   node -> y = y;
   node -> z = z;

   DrawNode (node);

   sprintf (message, "Added node %d.  Nodal coordinates:", node -> number);
   ChangeStatusLine (message, True);


   /* The node dialog needs to know that the new node is in
      the tree before it can display it. */

   NodeDialogUpdate (node_d, problem.node_tree, NULL, NULL);
   NodeDialogDisplay (node_d, node);

   changeflag = True;
}


static Node             moved_node;
static Figure           moved_figure;
static Figure           ghost_figure;
static FigureAttributes attr;


static int MoveNode (item)
    Item item;
{
    unsigned i;
    unsigned numnodes;
    Element  element = (Element) item;
    Drawn    drawn;


    numnodes = element -> definition -> shapenodes;

    for (i = 1; i <= numnodes; i ++)
      if (element -> node [i] == moved_node) {
          DW_GetAttributes (drawing, ((Drawn) element -> aux) -> figure,
                        &attr);
          attr.points [i - 1].x = moved_node -> x;
          attr.points [i - 1].y = moved_node -> y;
          if (numnodes > 2 && i == 1) {
            attr.points [numnodes].x = moved_node -> x;
            attr.points [numnodes].y = moved_node -> y;
          }
          drawn = (Drawn) element -> aux;

          DW_SetAttributes (drawing, drawn -> figure, DW_FigurePoints, &attr);

          if (drawn -> label != NULL) {
            ComputeCenter (element, &attr.x, &attr.y);
            DW_SetAttributes (drawing,drawn->label,DW_FigureLocation,&attr);
          }
      }

    return 0;
}


void DoWalkNode (node)
    Node node;
{
    Drawn drawn;


    moved_node = node;
    attr.x = node -> x;
    attr.y = node -> y;
    drawn = (Drawn) node -> aux;

    if (drawn == NULL) {
      DrawNode (node);
      drawn = (Drawn) node -> aux;
    }

    DW_SetAutoRedraw (drawing, False);
    DW_SetAttributes (drawing, drawn -> figure, DW_FigureLocation, &attr);
    DW_SetAttributes (drawing, drawn -> label, DW_FigureLocation, &attr);
    (void) TreeSetIterator (problem.element_tree, MoveNode);
    (void) TreeIterate (problem.element_tree);
    DW_SetAutoRedraw (drawing, True);

    NodeDialogDisplay (node_d, node);
    changeflag = True;
}


void DeleteNodeGroup (figures, nfigures)
    Figure  *figures;
    unsigned nfigures;
{
    unsigned         i;
    Figure           fig;
    Drawn            drawn;
    Node             node;
    unsigned         numleft;
    Boolean      firsttime;
    Boolean      newinfo;


    numleft = 0;
    firsttime = True;
    newinfo = False;

    for (i = 0; i < nfigures; i ++) {
      fig = figures [i];
      DW_GetAttributes (drawing, fig, &attr);

      if (attr.user_data == NULL || attr.type == TextFigure)
          continue;

      node = (Node) attr.user_data;
      drawn = (Drawn) node -> aux;
      if (drawn -> type != DrawnNode)
          continue;

      if (drawn -> ref_count) {
          numleft ++;
          continue;
      }

      if (firsttime == True) {
          firsttime = False;
          DW_SetAutoRedraw (drawing, False);
      }

      newinfo = True;
      DW_RemoveFigure (drawing, drawn -> figure);
      DW_RemoveFigure (drawing, drawn -> label);
      (void) TreeDelete (problem.node_tree, node);
      DestroyNode (node);
    }


    if (newinfo) {
        NodeDialogDisplay (node_d, NULL);
      NodeDialogUpdate (node_d, problem.node_tree, NULL, NULL);
    }


    if (firsttime == False) {
      DW_SetAutoRedraw (drawing, True);
      changeflag = True;
    }

    if (numleft)
      error ("Warning: elements still reference %d node%s.", numleft,
                                    numleft > 1 ? "s" : "");

    XtFree ((char *) figures);
}


void DoDeleteNode (node)
    Node node;
{
    static char message [80];
    Drawn drawn = (Drawn) node -> aux;
    Node newnode;


    if (drawn -> ref_count) {
      error ("Node %d is still referenced by %d element%s.", node -> number,
            drawn -> ref_count, drawn -> ref_count > 1 ? "s" : "");
      return;
    }

    if (drawn -> figure != NULL) {
      DW_SetAutoRedraw (drawing, False);
      DW_RemoveFigure (drawing, drawn -> figure);
      if (drawn -> label != NULL)
          DW_RemoveFigure (drawing, drawn -> label);
      DW_SetAutoRedraw (drawing, True);
    }

    sprintf (message, "Node %d deleted.  Select node:", node -> number);

    if (node == NodeDialogActive (node_d)) {
      newnode = (Node) TreePredecessor (problem.node_tree, node);
      if (newnode == NULL)
          newnode = (Node) TreeSuccessor (problem.node_tree, node);

      NodeDialogDisplay (node_d, newnode);
    }

    (void) TreeDelete (problem.node_tree, node);
    NodeDialogUpdate (node_d, problem.node_tree, NULL, NULL);

    DestroyNode (node);
    ChangeStatusLine (message, True);
    changeflag = True;
}


void DeleteNodeCB (w, client_data, call_data)
    Widget    w;
    XtPointer client_data;
    XtPointer call_data;
{
    DrawingReport   *report;
    FigureAttributes attributes;
    Figure           figure;
    Drawn            drawn;
    Node             node;


    report = (DrawingReport *) call_data;

    if (report -> event -> type != ButtonPress)
      return;

    if (report -> event -> xbutton.button == 2) {
      SelectGroup (call_data, DeleteNodeGroup);
      return;
    }

    if (report -> event -> xbutton.button == 3)
      QuitEdit ( );

    if (report -> event -> xbutton.button != 1)
      return;

    figure = DW_FindFigure (w, report -> unsnapped.x, report -> unsnapped.y);

    if (figure == NULL)
      return;

    DW_GetAttributes (w, figure, &attributes);
    if (attributes.user_data == NULL)
      return;

    node = (Node) attributes.user_data;
    drawn = (Drawn) node -> aux;
    if (drawn -> type != DrawnNode)
      return;

    DoDeleteNode (node);
}


void DeleteNodeAP ( )
{
    char       *status;
    struct node dummy;
    Item        found;


    if ((status = GetTextNumber (&dummy.number)) != NULL) {
      if (!strcmp (status, "w"))
          SelectGroup (NULL, DeleteNodeGroup);
      return;
    }

    found = TreeSearch (problem.node_tree, (Item) &dummy);
    if (found == NULL) {
      error ("Node %d does not exist.", dummy.number);
      return;
    }

    DoDeleteNode (found);
}


void EditDeleteNode ( )
{
    Arg           arglist [1];

    SetEditMode ( );
    ChangeStatusLine ("Select node:", True);

    XtRemoveAllCallbacks (drawing, XtNbuttonCallback);
    XtAddCallback (drawing, XtNbuttonCallback, DeleteNodeCB, NULL);

    XtSetArg (arglist [0], XtNcursorName, "dotbox");
    XtSetValues (drawing, arglist, 1);

    XtOverrideTranslations (entry,
      XtParseTranslationTable ("<Key>Return: DeleteNodeAP()"));
}


void EditNodeCB (w, client_data, call_data)
    Widget    w;
    XtPointer client_data;
    XtPointer call_data;
{
    DrawingReport   *report;
    FigureAttributes attributes;
    Figure           figure;
    Drawn            drawn;
    Node             node;


    report = (DrawingReport *) call_data;

    if (report -> event -> type != ButtonPress)
      return;

    if (report -> event -> xbutton.button == 3)
      QuitEdit ( );

    if (report -> event -> xbutton.button != 1)
      return;

    figure = DW_FindFigure (w, report -> unsnapped.x, report -> unsnapped.y);

    if (figure == NULL)
      return;

    DW_GetAttributes (w, figure, &attributes);
    if (attributes.user_data == NULL)
      return;

    node = (Node) attributes.user_data;
    drawn = (Drawn) node -> aux;
    if (drawn -> type != DrawnNode)
      return;

    NodeDialogDisplay (node_d, node);
    NodeDialogPopup (node_d);
}


void EditNodeAP ( )
{
    char       *status;
    struct node dummy;
    Item        found;


    if ((status = GetTextNumber (&dummy.number)) != NULL)
      return;

    found = TreeSearch (problem.node_tree, (Item) &dummy);
    if (found == NULL) {
      error ("Node %d does not exist.", dummy.number);
      return;
    }

    NodeDialogDisplay (node_d, found);
    NodeDialogPopup (node_d);
}


void EditNodeNumber ( )
{
    SetEditMode ( );
    ChangeStatusLine ("Select node:", True);

    XtRemoveAllCallbacks (drawing, XtNbuttonCallback);
    XtAddCallback (drawing, XtNbuttonCallback, EditNodeCB, NULL);

    XtOverrideTranslations (entry,
      XtParseTranslationTable ("<Key>Return: EditNodeAP()"));
}


int DrawNode (node)
    Node    node;
{
    Figure        fig;
    Figure        label;
    char          buffer [10];
    FigureAttributes    attr;
    Item          found;
    Drawn               drawn;


    found = TreeInsert (problem.node_tree, (Item) node);
    if (found != (Item) node)
      return 1;

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

    if (node -> force && node -> force -> color) {
        if (DW_SetForeground (drawing, node -> force -> color) == False)
            (void) DW_SetForeground (drawing, "black");
    }
    else if (node -> constraint -> color) {
        if (DW_SetForeground (drawing, node -> constraint -> color) == False)
            (void) DW_SetForeground (drawing, "black");
    }
    else {
        if (DW_SetForeground (drawing, canvas -> node_color) == False)
            (void) DW_SetForeground (drawing, "black");
    }

    if (node -> z == 0) {

      fig = DW_FillArc (drawing, False, node -> x, node -> y,
                        6.0, 6.0, 0.0, 360.0);

      if (canvas -> node_numbers == True) {
          sprintf (buffer, " %d", node -> number);
          label = DW_DrawText (drawing, True, node -> x, node -> y, buffer);
      } else
          label = NULL;

    } else
      fig = label = NULL;

    if (node -> aux == NULL) {
      drawn = (Drawn) XtNew (struct drawn);
      node -> aux = (char *) drawn;
      drawn -> type = DrawnNode;
      drawn -> ref_count = 0;
    } else
      drawn = (Drawn) node -> aux;

    drawn -> figure = fig;
    drawn -> label = label;


    attr.user_data = (char *) node;

    if (fig != NULL)
      DW_SetAttributes (drawing, fig, DW_FigureUserData, &attr);
    if (label != NULL)
        DW_SetAttributes (drawing, label, DW_FigureUserData, &attr);

    return 0;
}


void QuitMoveNode ( )
{
    DW_RemoveFigure (drawing, ghost_figure);
    DW_SetInteractive (drawing, False);
    SetNormalMode ( );
}


void WalkNodeCB (w, client_data, call_data)
    Widget    w;
    XtPointer client_data;
    XtPointer call_data;
{
    DrawingReport *report;
    Node           node;


    report = (DrawingReport *) call_data;
    node = (Node) client_data;

    if (report -> event -> type == ButtonPress) {
      if (report -> event -> xbutton.button == 3)
          QuitMoveNode ( );

      if (report -> event -> xbutton.button > 2)
          return;

      node -> x = report -> snapped.x;
      node -> y = report -> snapped.y;
      DW_RemoveFigure (drawing, ghost_figure);
      DW_SetInteractive (drawing, False);
      DoWalkNode (node);
      SetNormalMode ( );

    } else if (report -> event -> type == MotionNotify) {
      attr.x = report -> snapped.x;
      attr.y = report -> snapped.y;
      DW_SetAttributes (drawing, ghost_figure, DW_FigureLocation, &attr);
    }
}


void WalkNodeAP ( )
{
    char *status;
    float x, y;

    status = GetTextCoordinates (&x, &y, NULL);
    if (status != NULL)
      return;

   moved_node -> x = x;
   moved_node -> y = y;
   QuitMoveNode ( );
   DoWalkNode (moved_node);
}


void DoMoveNode (node, motion)
    Node    node;
    Boolean motion;
{
    static char buffer [80];


    SetEditMode ( );
    sprintf (buffer, "Nodal coordinates for node %d:", node -> number);
    ChangeStatusLine (buffer, True);

    AssignQuitAbort (QuitMoveNode, "QuitMoveNode", QuitMoveNode,"QuitMoveNode");

    XtRemoveAllCallbacks (drawing, XtNbuttonCallback);
    XtAddCallback (drawing, XtNbuttonCallback, WalkNodeCB, node);

    if (motion == True) {
      XtRemoveAllCallbacks (drawing, XtNmotionCallback);
      XtAddCallback (drawing, XtNmotionCallback, WalkNodeCB, node);
      DW_SetInteractive (drawing, True);
      ghost_figure = DW_FillArc (drawing, False, node -> x, node -> y,
                              6.0, 6.0, 0.0, 360.0);
    } else {
      moved_figure = NULL;
      ghost_figure = NULL;
    }

    moved_node = node;
    XtOverrideTranslations (entry,
      XtParseTranslationTable ("<Key>Return: WalkNodeAP()"));
}


void MoveNodeCB (w, client_data, call_data)
    Widget    w;
    XtPointer client_data;
    XtPointer call_data;
{
    DrawingReport   *report;
    FigureAttributes attributes;
    Figure       figure;
    Node         node;
    Drawn        drawn;


    report = (DrawingReport *) call_data;

    if (report -> event -> type != ButtonPress)
      return;

    if (report -> event -> xbutton.button == 3)
      QuitEdit ( );

    if (report -> event -> xbutton.button != 1)
      return;

    figure = DW_FindFigure (w, report -> unsnapped.x, report -> unsnapped.y);

    if (figure == NULL)
      return;

    DW_GetAttributes (w, figure, &attributes);
    if (attributes.user_data == NULL)
      return;

    node = (Node) attributes.user_data;
    drawn = (Drawn) node -> aux;
    if (drawn -> type != DrawnNode)
      return;

    moved_figure = figure;
    DoMoveNode (node, False);
}


void MoveNodeAP ( )
{
    char       *status;
    struct node dummy;
    Item        found;


    if ((status = GetTextNumber (&dummy.number)) != NULL)
      return;

    found = TreeSearch (problem.node_tree, &dummy);
    if (found == NULL) {
      error ("Node %d does not exist.", dummy.number);
      return;
    }

    DoMoveNode (found, False);
}


void MoveNodeNumber ( )
{
    SetEditMode ( );
    ChangeStatusLine ("Select node: ", True);

    XtRemoveAllCallbacks (drawing, XtNbuttonCallback);
    XtAddCallback (drawing, XtNbuttonCallback, MoveNodeCB, NULL);

    XtOverrideTranslations (entry,
      XtParseTranslationTable ("<Key>Return: MoveNodeAP()"));
}

static double mass_value = 0.0;

void AssignMassGroup (figures, nfigures)
    Figure  *figures;
    unsigned nfigures;
{
    unsigned         i;
    Figure           fig;
    Drawn            drawn;
    Node             node;


    for (i = 0; i < nfigures; i ++) {
      fig = figures [i];
      DW_GetAttributes (drawing, fig, &attr);

      if (attr.user_data == NULL || attr.type == TextFigure)
          continue;

      node = (Node) attr.user_data;
      drawn = (Drawn) node -> aux;
      if (drawn -> type != DrawnNode)
          continue;

        node -> m = mass_value;
    }


    changeflag = True;

    return;
}


void DoAssignMass (node)
    Node node;
{
    char    message [80];

    node -> m = mass_value;

    if (node == NodeDialogActive (node_d))
       NodeDialogDisplay (node_d, node);

    sprintf (message, "Mass assigned to node %d.  Select node:", node -> number);

    ChangeStatusLine (message, True);
    changeflag = True;
}


void AssignMassCB (w, client_data, call_data)
    Widget    w;
    XtPointer client_data;
    XtPointer call_data;
{
    DrawingReport   *report;
    FigureAttributes attributes;
    Figure           figure;
    Drawn            drawn;
    Node             node;


    report = (DrawingReport *) call_data;

    if (report -> event -> type != ButtonPress)
      return;

    if (report -> event -> xbutton.button == 2) {
      SelectGroup (call_data, AssignMassGroup);
      return;
    }

    if (report -> event -> xbutton.button == 3)
      QuitEdit ( );

    if (report -> event -> xbutton.button != 1)
      return;

    figure = DW_FindFigure (w, report -> unsnapped.x, report -> unsnapped.y);

    if (figure == NULL)
      return;

    DW_GetAttributes (w, figure, &attributes);
    if (attributes.user_data == NULL)
      return;

    node = (Node) attributes.user_data;
    drawn = (Drawn) node -> aux;
    if (drawn -> type != DrawnNode)
      return;

    DoAssignMass (node);
}


void AssignMassAP ( )
{
    char       *status;
    struct node dummy;
    Item        found;


    if ((status = GetTextNumber (&dummy.number)) != NULL) {
      if (!strcmp (status, "w"))
          SelectGroup (NULL, AssignMassGroup);
      return;
    }

    found = TreeSearch (problem.node_tree, (Item) &dummy);
    if (found == NULL) {
      error ("Node %d does not exist.", dummy.number);
      return;
    }

    DoAssignMass (found);
}

void SetMassAP ( )
{
    Arg           args [1];
    char    *status;
    float   m;

    status = GetTextCoordinates (&m, NULL, NULL);
    if (status == NULL)
       mass_value = m;
    else
       return; 

    ChangeStatusLine ("Select node:", True);

    XtSetArg (args [0], XtNcursorName, "dotbox");
    XtSetValues (drawing, args, 1);

    XtAddCallback (drawing, XtNbuttonCallback, AssignMassCB, NULL);
    XtOverrideTranslations (entry,
      XtParseTranslationTable ("<Key>Return: AssignMassAP()"));
}

void EditNodalMass ( )
{
    SetEditMode ( );
    ChangeStatusLine ("Enter mass value:", True);

    XtRemoveAllCallbacks (drawing, XtNbuttonCallback);

    XtOverrideTranslations (entry,
      XtParseTranslationTable ("<Key>Return: SetMassAP()"));
}

Generated by  Doxygen 1.6.0   Back to index