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

generate.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:    generate.c
 *
 ***************************************************************************/

# include <X11/Intrinsic.h>
# include <stdlib.h>
# include "allocate.h"
# include "fe.h"
# include "ElementList.h"
# include "Constraint.h"
# include "Material.h"
# include "Trimesh.h"
# include "Grid.h"
# include "Canvas.h"
# include "OutputDialog.h"
# include "Drawing.h"
# include "vfe.h"
# include "procedures.h"
# include "problem.h"
# include "globals.h"
# include "text_entry.h"
# include "error.h"
# include "util.h"

extern ConstraintDialog constraint_d;
extern MaterialDialog   material_d;
extern ElementList      element_l;

static unsigned         op_count;
static TriMesh          trimesh;
static unsigned         maxvc;
static unsigned         curr_vc;
static unsigned         curr_curve;
static Figure           marker [100];
static unsigned         mk_count;

typedef double    dbl_pair [2];

# define LINES    1
# define QUADS    2

static int  grid_type;

static void VelvetCoalesceNodes ( )
{
   unsigned       i;
   unsigned       nn, ne;
   Node                 *new_nodes;
   FigureAttributes     attr;
   unsigned       num_figures;
   Figure         *figure;

   nn = CompactNodeNumbers ( );
   ne = CompactElementNumbers ( );
   if (nn == 0 || ne == 0)
      return;

   for (i = 1 ; i <= nn ; i++) 
      TreeDelete (problem.node_tree, problem.nodes [i]);

   new_nodes = CoalesceNodes (problem.nodes, problem.elements, &nn, ne);

   if (new_nodes == problem.nodes) {
      for (i = 1 ; i <= nn ; i++) 
         TreeInsert (problem.node_tree, problem.nodes [i]);

      return;
   }

   problem.nodes = new_nodes;

   DW_SetAutoRedraw (drawing, False);

   figure = DW_RetrieveAll (drawing, False, &num_figures);
   for (i = 0 ; i < num_figures ; i++) {
      DW_GetAttributes (drawing, figure [i], &attr);
      if (attr.user_data != NULL)
         DW_RemoveFigure (drawing, figure [i]);
   }

   XtFree ((char *) figure); 

   for (i = 1 ; i <= nn ; i++) {
      Deallocate (problem.nodes [i] -> aux);
      problem.nodes [i] -> aux = NULL;

      DrawNode (problem.nodes [i]);
   }

   for (i = 1 ; i <= ne ; i++) {
      TreeDelete (problem.element_tree, problem.elements [i]);

      Deallocate (problem.elements [i] -> aux);
      problem.elements [i] -> aux = NULL;

      DrawElement (problem.elements [i]);
   }

   DW_SetAutoRedraw (drawing, True);

   return;
}

void GenerateElements ( ) 
{ 
   Definition     active_definition;


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

   active_definition = ElementListDefinition (element_l);
   if (active_definition == NULL) {
      error ("No active element type defined.");
      return;
   } 

   op_count = 0;
   if (active_definition -> numnodes == 2) {
      grid_type = LINES;
      SetupGridGeneration ( );
   }
   else if (active_definition -> numnodes == 3)
      SetupTriangleGeneration ( );
   else if (active_definition -> shapenodes == 4) {
      grid_type = QUADS;
      SetupGridGeneration ( );
   }
   else 
      error ("The current type of element cannot be generated."); 
}

void SetupGridGeneration ()
{
   static GridDialog    grid_d = NULL;
   Element  mxelt;
   Node           mxnode;
   Element  *element;
   Node           *node;
   unsigned mxnode_number,
            mxelt_number;
   unsigned nn, ne;
   unsigned i;
   Grid           grid;

   mxnode = (Node) TreeMaximum (problem.node_tree);
   if (mxnode != NULL)
      mxnode_number = mxnode -> number;
   else
      mxnode_number = 0;

   mxelt = (Element) TreeMaximum (problem.element_tree);
   if (mxelt != NULL)
      mxelt_number = mxelt -> number;
   else
      mxelt_number = 0;

   if (grid_d == NULL)
      grid_d = GridDialogCreate (toplevel, "gridDialog", "Generation Parameters");

   grid = GridDialogPopup (grid_d);
   if (grid == NULL)
      return;

   grid -> definition = ElementListDefinition (element_l);

   if (grid_type == LINES) {
      if (GenerateGrid (grid,&element,&node, 
                        &ne,&nn,mxnode_number,mxelt_number))
         return;
   }
   else if (grid_type == QUADS) {
      if (GenerateQuadGrid (grid,&element,&node, 
                            &ne,&nn,mxnode_number,mxelt_number))
         return;
   }

   for (i = 1 ; i <= ne ; i++) {
      element [i] -> material = MaterialDialogActive (material_d);

      DrawElement (element [i]);
   }

   for (i = 1 ; i <= nn ; i++) {
      node[i] -> constraint = ConstraintDialogActive (constraint_d);

      DrawNode (node [i]);
   }

   VelvetCoalesceNodes ( );

   OutputDialogPrintf (error_dialog,"Generated %d nodes and %d elements",nn,ne);
   CenterOnWidget (OutputDialogShell (error_dialog), toplevel, True);
   WarpToCenter (OutputDialogShell (error_dialog));
   OutputDialogSelect (error_dialog, "Generation status", "okay");

   changeflag = True;
}
   

void SetupTriangleGeneration ( )
{
   static unsigned            flag = 1;
   static TrimeshDialog       trimesh_d;
   unsigned             i;
  
   if (flag) {
      trimesh_d = TrimeshDialogCreate(toplevel,"trimeshDialog",
                                    "Generation Parameters");
      flag = 0;
   }

   trimesh = TrimeshDialogPopup (trimesh_d); 
   if (trimesh == NULL) 
      return;

   trimesh -> curves = Allocate (Curve, trimesh -> numcurves);

   maxvc = 20;

   for (i = 0 ; i < trimesh -> numcurves ; i++) {
      trimesh -> curves [i] = Allocate (struct _curve, 1);
   
      trimesh -> curves [i] -> vcl = Allocate (dbl_pair, maxvc);
      trimesh -> curves [i] -> numvc = 0;
   }

   AssignQuitAbort (FinishCurve, "FinishCurve", AbortTriMesh, "AbortTriMesh");

   XtOverrideTranslations (entry,
      XtParseTranslationTable ("Shift<Key>BackSpace: BackupOnePoint()"));

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

   XtRemoveAllCallbacks (drawing, XtNbuttonCallback);

   XtAddCallback (drawing, XtNbuttonCallback, AddCurvePointCB, NULL);

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

   mk_count = 0;

   op_count = 0;   
   curr_curve = 0;
   curr_vc = 0;
   ChangeStatusLine ("Select first boundary point:", True);
   SetEditMode ();
}

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

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

   DoAddCurvePoint (x,y);
}

void AddCurvePointCB (w, clientData, callData)
   Widget   w;
   XtPointer      clientData;
   XtPointer      callData;
{
   DrawingReport  *report;

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

   if (report -> event -> xbutton.button == 3) {
      FinishCurve ( );
      return;
   } 
   else if (report -> event -> xbutton.button != 1)
      return;

   DoAddCurvePoint (report -> snapped.x, report -> snapped.y);
}

static char *ordinals [ ] = {"", "first", "second", "third", "fourth", "fifth",
                        "sixth", "seventh", "eighth", "ninth", "tenth",
                        "eleventh", "twelfth", "thirteenth", "fourteenth"};

void DoAddCurvePoint (x,y)
   float    x,y;
{
   static char          message [80];

   trimesh -> curves [curr_curve] -> vcl [curr_vc][0] = x;
   trimesh -> curves [curr_curve] -> vcl [curr_vc][1] = y;

   marker [mk_count++] =  DW_FillArc (drawing, False, x, y,6.0,6.0,0.0,360.0);

   curr_vc++;
   if (curr_vc >= maxvc) {
      trimesh -> curves [curr_curve] -> vcl = 
         Reallocate (trimesh -> curves [curr_curve] -> vcl, dbl_pair, 20);

      maxvc += 20;
   }

   sprintf (message, "Select %s %s point:", 
            (curr_vc > 13 ? "next" : ordinals [curr_vc + 1]),
            (curr_curve == 0 ? "boundary" : "hole"));

   ChangeStatusLine (message, True);
}

void DoTriMeshGeneration ()
{
   Element  *element;
   Node           *node;
   unsigned ne,nn;
   Element  mxelt;
   Node           mxnode;
   unsigned maxnode;
   unsigned maxelt;
   unsigned i;

  
   mxnode = (Node) TreeMaximum (problem.node_tree);
   if (mxnode != NULL)
      maxnode = mxnode -> number;
   else
      maxnode = 0;

   mxelt = (Element) TreeMaximum (problem.element_tree);
   if (mxelt != NULL)
      maxelt = mxelt -> number; 
   else
      maxelt = 0;
 
   DW_SetAutoRedraw (drawing, False);
    
   for (i = 0 ; i < mk_count ; i++)
      DW_RemoveFigure (drawing, marker [i]);
 
   DW_SetAutoRedraw (drawing, True);

   trimesh -> definition = ElementListDefinition (element_l);
      
   if (GenerateTriMesh (trimesh,&element,&node,&ne,&nn,maxnode,maxelt)) {
      for (i = 0 ; i < trimesh -> numcurves ; i++) {
         Deallocate (trimesh -> curves [i] -> vcl);
         Deallocate (trimesh -> curves [i]);
      }
      Deallocate (trimesh -> curves);

      return;
   }

   for (i = 1 ; i <= ne ; i++) {
      element [i] -> material = MaterialDialogActive (material_d);

      DrawElement (element [i]);
   }     
 
   for (i = 1 ; i <= nn ; i++) {
      node[i] -> constraint = ConstraintDialogActive (constraint_d);

      DrawNode (node [i]);
   }
  
   for (i = 0 ; i < trimesh -> numcurves ; i++) {
      Deallocate (trimesh -> curves [i] -> vcl);
      Deallocate (trimesh -> curves [i]);
   }

   Deallocate (trimesh -> curves);

   VelvetCoalesceNodes ( );

   OutputDialogPrintf (error_dialog,"Generated %d nodes and %d elements",nn,ne);
   CenterOnWidget (OutputDialogShell (error_dialog), toplevel, True);
   WarpToCenter (OutputDialogShell (error_dialog));
   OutputDialogSelect (error_dialog, "Generation status", "okay");

   changeflag = True;
}

void FinishCurve ()
{
   trimesh -> curves [curr_curve] -> numvc = curr_vc;
   maxvc = 20;
   curr_vc = 0;
   curr_curve++; 

   if (curr_curve >= trimesh -> numcurves) {
      DoTriMeshGeneration ();
      XtOverrideTranslations (entry,
         XtParseTranslationTable ("Shift<Key>BackSpace: no-op()"));

      SetNormalMode ();
   }
   else 
      ChangeStatusLine ("Select first hole point:", True);
}

void AbortTriMesh ()
{
   unsigned i;

   for (i = 0 ; i < trimesh -> numcurves ; i++) {
      Deallocate (trimesh -> curves [i] -> vcl);
      Deallocate (trimesh -> curves [i]);
   }

   Deallocate (trimesh -> curves);  

   DW_SetAutoRedraw (drawing, False);

   for (i = 0 ; i < mk_count ; i++)
      DW_RemoveFigure (drawing, marker [i]);

   DW_SetAutoRedraw (drawing, True);

   XtOverrideTranslations (entry,
      XtParseTranslationTable ("Shift<Key>BackSpace: no-op()"));

   SetNormalMode ();
}

void BackupOnePoint ()
{
   char           message [80];

   if (curr_vc == 0)
      return;

   curr_vc--;
   sprintf (message,"Deleted. Select %s %s point:",
      (curr_vc > 13 ? "next" : ordinals [curr_vc + 1]),
      (curr_curve == 0 ? "boundary" : "hole"));

   ChangeStatusLine (message, True);

   mk_count --;
   DW_RemoveFigure (drawing, marker [mk_count]);
}


Generated by  Doxygen 1.6.0   Back to index