/*
    This file is part of the FElt finite element analysis package.
    Copyright (C) 1993 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:		draw.c
*
* Description:  Contains the routines to draw a FELT structure in two
*		or three dimensions.  DrawStructure is the only one
*		that the user would ever call.  2d and 3d are in separate
*		but really quite similar subroutines simply for clarity,
*		the 3d stuff gets kind of nasty looking.
*
****************************************************************************/

# include <stdio.h>
# include <string.h>
# include <malloc.h>
# include <math.h>
# include <X11/Xlib.h>
# include <X11/Xutil.h>
# include <X11/Intrinsic.h>
# include <X11/StringDefs.h>
# include <X11/Shell.h>
# include <X11/Xaw/Form.h>
# include <X11/Xaw/AsciiText.h>
# include "Drawing.h"
# include "forms.h"
# include "dialog.h"
# include "globals.h"

double atof ();
double strtod ();

# define MaxNodesPerElement	50

void DrawStructure2D (data_file)
   char		*data_file;
{
   Arg		arglist [12];
   Cardinal	n;
   FILE 	*input;
   Point	points [MaxNodesPerElement];
   unsigned	count;
   int		i,j;
   char		buffer [80];
   char		*ptr;
   Figure	dummy;
   float	maxX, minX, maxY, minY, Xscale, Yscale;
   float	x,y;
   XSizeHints	hints;
   Dimension	width, height;
   float	w,h;
   unsigned 	num_pairs;
   struct pair {
      int       npoints;
      float 	x[MaxNodesPerElement], y[MaxNodesPerElement];
   } *element;

   input = fopen (data_file, "r");

   num_pairs = 100;
   element = (struct pair *) malloc (sizeof(struct pair) * num_pairs);

   count = 0;
   i = 0;
   while (fgets (buffer, 80, input) != NULL) {
      if (strcmp (buffer, "\n") != 0) {
         element [count].x[i] = strtod (buffer, &ptr);
         ptr = strchr (buffer, ' ');
         element [count].y[i] = atof (ptr+1);
         i++;
      }
      else { 
         element [count].npoints = i;
         i = 0;
         count++;
         if (count >= num_pairs) {
            num_pairs += 200;
            element = (struct pair *) realloc (element, sizeof(struct pair) * num_pairs);
         }
      }
   }

   fclose (input);

   maxX = minX = element [0].x[0]; 
   maxY = minY = element [0].y[0];
   for (i = 0 ; i < count ; i++) {
      for (j = 0 ; j < element [i].npoints ; j++) {

         x = element [i].x[j];
         y = element [i].y[j];

         if (x > maxX) maxX = x;
         else if (x < minX) minX = x;

         if (y > maxY) maxY = y;
         else if (y < minY) minY = y;
      }
   }

   minX -= 0.05*(maxX - minX); 
   minY -= 0.05*(maxY - minY);
   maxX += 0.05*(maxX - minX);
   maxY += 0.05*(maxY - minY);
   
   XtRealizeWidget (drawingShell);

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

   w = (float) width;
   h = (float) height;

   if ((maxX - minX)/w > (maxY - minY)/h) {
      Xscale = (float) (w / (maxX - minX));
      Yscale = Xscale;
      height = (Dimension) ((maxY - minY)*Yscale);
   }
   else {
      Yscale = (float) (h / (maxY - minY));
      Xscale = Yscale;
      width = (Dimension) ((maxX - minX)*Xscale);
   }

   hints.width = width + 10;
   hints.height = height + 80;

   n = 0;
   XtSetArg (arglist [n], XtNxMin, Float2Arg(minX)); n++; 
   XtSetArg (arglist [n], XtNxMax, Float2Arg(maxX)); n++; 

   XtSetArg (arglist [n], XtNyMin, Float2Arg(minY)); n++; 
   XtSetArg (arglist [n], XtNyMax, Float2Arg(maxY)); n++; 
   XtSetArg (arglist [n], XtNyScale, Float2Arg(Yscale)); n++;
   XtSetArg (arglist [n], XtNxScale, Float2Arg(Xscale)); n++; 
   XtSetArg (arglist [n], XtNheight, height); n++;
   XtSetArg (arglist [n], XtNwidth, width); n++;
   XtSetValues (drawing, arglist, n);

   n = 0;
   XtSetArg (arglist [n], XtNheight, (Dimension) hints.height); n++;
   XtSetArg (arglist [n], XtNwidth, (Dimension) hints.width); n++;
   XtSetValues (drawingShell, arglist, n);

   hints.flags = PSize;

   XSetNormalHints (XtDisplay (drawingShell), 
                    XtWindow (drawingShell), &hints);

   XtPopup (drawingShell, XtGrabNone);
   DW_RemoveAll (drawing);

   for (i = 0 ; i < count ; i++) {
      if (element [i].npoints > 2) {
         for (j = 0 ; j < element [i].npoints ; j++) {
            points [j].x = element [i].x[j];
            points [j].y = element [i].y[j];
         }
         points [element [i].npoints].x = element[i].x[0];
         points [element [i].npoints].y = element[i].y[0];
         dummy = DW_DrawPolygon (drawing, True, points, element [i].npoints+1);
      } else
         dummy = DW_DrawLine (drawing, element[i].x[0], element[i].y[0],
                      element[i].x[1], element[i].y[1]);
   }

   free (element);
} 
