1 /*  pdnmesh - a 2D finite element solver
2     Copyright (C) 2001-2005 Sarod Yatawatta <sarod@users.sf.net>
3   This program is free software; you can redistribute it and/or modify
4   it under the terms of the GNU General Public License as published by
5   the Free Software Foundation; either version 2 of the License, or
6   (at your option) any later version.
7 
8   This program is distributed in the hope that it will be useful,
9   but WITHOUT ANY WARRANTY; without even the implied warranty of
10   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11   GNU General Public License for more details.
12 
13   You should have received a copy of the GNU General Public License
14   along with this program; if not, write to the Free Software
15   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16   $Id: dxf.c,v 1.26 2005/04/24 05:32:24 sarod Exp $
17 */
18 
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22 
23 
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <ctype.h>
28 #include <math.h>
29 #include "types.h"
30 
31 extern Mesh M;
32 extern poly_edge *edge_array;
33 extern int nedges;
34 /* array of poins in the DXF file */
35 point * dxf_point_array;
36 /* size will be 3 more than actual no of points
37  * to include outer triangle */
38 int dxf_points;
39 /* current edge closest to cursor */
40 MY_INT current_edge_number;
41 
42 /* array to keep edges of triangles overlapping boundary edges */
43 MY_INT **triangle_edge_array;
44 
45 /* point closest to the mouse cursor in mesh */
46 MY_INT current_point_number;
47 
48 /* polygon list for boundary */
49 boundary_list blist;
50 /* current selected polygon for editing */
51 dxf_polygon *current_polygon;
52 
53 /* filename for output */
54 char *output_cord_filename=0;
55 
56 
57 typedef struct dxfedge_
58 {
59   int p1;			/* fist point */
60   int p2;			/* next point */
61 } edge;
62 /* data for list of edges - used in delaunay triangulation*/
63 typedef struct dxfelist_
64 {
65   edge data;
66   struct dxfelist_ *next;
67 } elist;
68 
69 /* global no for current boundary */
70 unsigned long int boundary_no;
71 
72 /* function to get an edge from list */
73 /* __LOCAL__ */
74 static elist *
E_get(elist * Lhead,edge * tt)75 E_get (elist * Lhead, edge * tt)
76 {
77 
78   elist *temp;
79   if (Lhead == 0)
80     {
81       tt = 0;
82       return (0);
83     }				/* NULL */
84   *tt = Lhead->data;
85   temp = Lhead;
86   Lhead = Lhead->next;
87   free (temp);
88   return (Lhead);
89 }
90 
91 /* function to insert an edge to list -- a queue */
92 static elist *
E_insert(elist * Lhead,edge Ldata)93 E_insert (elist * Lhead, edge Ldata)
94 {
95   elist *temp, *tail;
96 
97   temp = (elist *) malloc (sizeof (elist));
98   temp->data.p1 = Ldata.p1;
99   temp->data.p2 = Ldata.p2;
100   /* first the null case */
101   if (Lhead == NULL)
102     {
103       temp->next = Lhead;
104       Lhead = temp;
105       return (Lhead);
106     }
107 
108   /* list is not null */
109   /* find tha tail of the list */
110   tail = Lhead;
111   while (tail->next)
112     tail = tail->next;
113   /* now we reach the last element */
114   temp->next = NULL;
115   tail->next = temp;
116 
117   return (Lhead);
118 }
119 
120 /* if edge (p0-p1) is on a boundary, return boundary number.
121  * else return -1 */
122 static MY_INT
is_this_edge_on_a_boundary(p0,p1)123 is_this_edge_on_a_boundary(p0,p1)
124 {
125   /* find the ratio using x=(x1+lambda. x2)/(1+lambda) */
126 	/* if x is on (x1-x2), lambda >0 , equal to y */
127 	/* try to do robust computations */
128  int i;
129 	double xp0,xp1,xn0,xn1,yp0,yp1,yn0,yn1;
130 	xp0=Mx(p0,M);
131 	yp0=My(p0,M);
132 	xp1=Mx(p1,M);
133 	yp1=My(p1,M);
134 
135 #ifdef DEBUG
136 	printf("is_this_edge_on_a_boundary:consider points(%d,%d)\n",p0,p1);
137 #endif
138 	for (i=0; i< nedges; i++) {
139     xn0=Mx(edge_array[i].p1,M);
140     yn0=My(edge_array[i].p1,M);
141     xn1=Mx(edge_array[i].p2,M);
142     yn1=My(edge_array[i].p2,M);
143 #ifdef DEBUG
144 	printf("is_this_edge_on_a_boundary: edge %d\n",i);
145 #endif
146 		if ( IS_ZERO((xn0-xp0)*(yp0-yn1)-(yn0-yp0)*(xp0-xn1))
147 			 /* ratio is equal magnitude, check sign */
148 			&& ( ((yn0-yp0)*(yp0-yn1)>0) /* if true, equal and +ve lambda. stop */
149 				|| (IS_ZERO((yn0-yp0)*(yp0-yn1))
150 							&& (xn0-xp0)*(xp0-xn1) >= 0))){
151 					/* if we are here, point p0 is on line */
152 					/* do the same check for point p1 */
153 #ifdef DEBUG
154 	printf("is_this_edge_on_a_boundary: point %d is on line %d\n",p0,i);
155 #endif
156          if ( IS_ZERO((xn0-xp1)*(yp1-yn1)-(yn0-yp1)*(xp1-xn1))
157 			 /* ratio is equal magnitude, check sign */
158 			&& ( ((yn0-yp1)*(yp1-yn1)>0) /* if true, equal and +ve lambda. stop */
159 				|| (IS_ZERO((yn0-yp1)*(yp1-yn1))
160 							&& (xn0-xp1)*(xp1-xn1) >= 0))){
161 					return(i);
162 				}
163 		 }
164 
165   }
166 
167 	return(-1); /* not found */
168 
169 }
170 
171 
172 static int
read_2_lines_at_a_time(FILE * fp,int * line1,char * line2,int line2_length)173 read_2_lines_at_a_time (FILE * fp, int *line1, char *line2, int line2_length)
174 {
175   int flag;
176   int c, count;
177   flag = fscanf (fp, "%d", line1);
178   if (flag == EOF)
179     {
180       return (flag);
181     }
182   /*printf("read_:%d\n",*line1); */
183   /* skip rest of line */
184   do
185     {
186       if ((c = getc (fp)) == EOF)
187 	return (EOF);
188     }
189   while (c != '\n');
190 
191   count = 0;
192   do
193     {
194       if ((c = getc (fp)) == EOF)
195 	{
196 	  return (EOF);
197 	}
198       if (c == '\n')
199 	{
200 	  line2[count] = '\0';
201 	  break;
202 	}
203       if (!isblank((int)c))
204 	{
205 	  line2[count++] = c;
206 	}
207       /*printf("read (%c) ",c); */
208     } while (count<line2_length-1);
209 
210     /* if count > line2_length-1 we have overstepped buffer*/
211     if(count==line2_length-1) {
212 	   line2[count] = '\0';
213      /* read out the rest of the line */
214      do {
215       if ((c=getc(fp))==EOF) {
216          return(EOF);
217       }
218      } while (c!='\n');
219     }
220 #ifdef DEBUG
221   printf(">>>>>>read_:%d and %s\n",*line1,line2);
222 #endif
223   return (count);
224 }
225 
226 /* read DXF file */
227 int
read_dxf_file_and_triangulate(const char * filename)228 read_dxf_file_and_triangulate (const char *filename)
229 {
230   FILE *fp;
231   int line1;
232   char line2[20];
233   int flag;
234   point p0, p1;
235   edge etmp;
236   double xmax, xmin, ymax, ymin;
237   int pn;
238   unsigned int i;
239 		triangle *tg;
240 		DAG_node *current_dag_node, *parent_dag_node;
241 		polygon temp_polygon;
242 		poly_edge e;
243   elist *list = 0;
244 
245   Mesh G={0,0,0,0};
246   p0.z = p1.z = 0;
247   BIT_init(&G, 10);
248 	/* global edges */
249   nedges=0;
250 
251 
252   fp = fopen (filename, "r");
253   if (fp == NULL)
254     {
255       fprintf (stderr, "%s: %d: could not open file %s\n", __FILE__, __LINE__,
256 	       filename);
257       exit (1);
258     }
259   flag = 1;
260 		/* global edge array size */
261   while (flag != EOF)
262     {
263       flag = read_2_lines_at_a_time (fp, &line1, line2,20);
264       if ((flag != EOF) && (line1 == 0) && !strcmp (line2, "LINE"))
265 	{
266 #ifdef DEBUG
267 	  printf("++++++++++++++++++++++++\n");
268 #endif
269 	  /* new line def found */
270 	  do
271 	    {
272 	      flag = read_2_lines_at_a_time (fp, &line1, line2,20);
273 	    }
274 	  while ((flag != EOF) && (line1 != 10));
275 	  if (flag == EOF)
276 	    {
277 	      fprintf (stderr, "%s: %d: could not read file\n", __FILE__,
278 		       __LINE__);
279 	      break;
280 	    }
281 	  p0.x = strtod (line2, 0);
282 
283 #ifdef DEBUG
284 	  printf("x0=%lf from %s\n",p0.x,line2);
285 #endif
286 	  do
287 	    {
288 	      flag = read_2_lines_at_a_time (fp, &line1, line2,20);
289 	    }
290 	  while ((flag != EOF) && (line1 != 20));
291 	  if (flag == EOF)
292 	    {
293 	      fprintf (stderr, "%s: %d: could not read file\n", __FILE__,
294 		       __LINE__);
295 	      break;
296 	    }
297 	  p0.y = strtod (line2, 0);
298 #ifdef DEBUG
299 	  printf("y0=%lf from %s\n",p0.y,line2);
300 #endif
301 	  do
302 	    {
303 	      flag = read_2_lines_at_a_time (fp, &line1, line2,20);
304 	    }
305 	  while ((flag != EOF) && (line1 != 11));
306 	  if (flag == EOF)
307 	    {
308 	      fprintf (stderr, "%s: %d: could not read file\n", __FILE__,
309 		       __LINE__);
310 	      break;
311 	    }
312 	  p1.x = strtod (line2, 0);
313 #ifdef DEBUG
314 	   printf("x1=%lf\n",p1.x);
315 #endif
316 	  do
317 	    {
318 	      flag = read_2_lines_at_a_time (fp, &line1, line2,20);
319 	    }
320 	  while ((flag != EOF) && (line1 != 21));
321 	  if (flag == EOF)
322 	    {
323 	      fprintf (stderr, "%s: %d: could not read file\n", __FILE__,
324 		       __LINE__);
325 	      break;
326 	    }
327 	  p1.y = strtod (line2, 0);
328 #ifdef DEBUG
329 	  printf("y1=%lf\n",p1.y);
330 	  printf ("new line found: (%lf,%lf)--(%lf,%lf)\n", p0.x, p0.y, p1.x,p1.y);
331 #endif
332 	  etmp.p1 = BIT_insert (&G, p0);
333 	  etmp.p2 = BIT_insert (&G, p1);
334 			/* sanity check. if we have an edge with zero length,
335 				* we do not insert it to the edge list. we consider that as a point */
336 			if ( etmp.p1 != etmp.p2 ) {
337 #ifdef DEBUG
338 	  printf ("points inserted (%d)--(%d)\n", etmp.p1, etmp.p2);
339 #endif
340 	  /* insert edge to list */
341 	  list = E_insert (list, etmp);
342 		nedges++;
343 			}
344 	}
345     }
346   if (!fp)
347    fclose (fp);
348   xmax = -1000;
349   xmin = 1000;
350   ymax = -1000;
351   ymin = 1000;
352 
353 
354   for (i = 0; i < G.count; i++)
355     {
356       if (xmin > *((G.Narray[i])->xp))
357 	{
358 	  xmin = *((G.Narray[i])->xp);
359 	}
360       if (xmax < *((G.Narray[i])->xp))
361 	{
362 	  xmax = *((G.Narray[i])->xp);
363 	}
364       if (ymin > (G.Narray[i])->y)
365 	{
366 	  ymin = (G.Narray[i])->y;
367 	}
368       if (ymax < (G.Narray[i])->y)
369 	{
370 	  ymax = (G.Narray[i])->y;
371 	}
372 
373     }
374   g_xoff = -(xmax + xmin) * 0.5;
375   g_yoff = -(ymax + ymin) * 0.5;
376 
377   /* now find the maximum value of coordinates */
378   ymax = ABS (ymax);
379   xmax = ABS (xmax);
380   xmin = ABS (xmin);
381   ymin = ABS (ymin);
382   if (xmax < ymax)
383     xmax = ymax;
384   if (xmax < ymin)
385     xmax = ymin;
386   if (xmax < xmin)
387     xmax = xmin;
388   g_xscale = xmax;
389   g_yscale = xmax;
390 
391 	/* allocate for point array */
392 	dxf_points=G.count+3;
393   if ((dxf_point_array=(point*)malloc((size_t)(dxf_points)*sizeof(point)))==0)
394     {
395       fprintf (stderr, "%s: %d: no free memory", __FILE__, __LINE__);
396       exit (1);
397     }
398 
399   /* boundary points */
400   if ((tg = (triangle *) malloc (sizeof (triangle))) == 0)
401     {
402       fprintf (stderr, "%s: %d: no free memory", __FILE__, __LINE__);
403       exit (1);
404     }
405   p1.x = -3;
406   p1.y = -3;
407   if ((p1.z =
408        (MY_DOUBLE *) malloc ((size_t) (degree_of_freedom) *
409 			     sizeof (MY_DOUBLE))) == 0)
410     {
411       fprintf (stderr, "%s: %d: no free memory\n", __FILE__, __LINE__);
412       exit (1);
413     }
414   p1.z[0] = 0;
415   p1.val = FX;			/* we dont care they are FX or not */
416 #ifdef DEBUG
417   printf ("inserting point %d " MDF "," MDF "\n", 0, p1.x, p1.y);
418 #endif
419   tg->p0 = BIT_insert (&M, p1);
420   p1.x = 3;
421   p1.y = 0;
422   if ((p1.z =
423        (MY_DOUBLE *) malloc ((size_t) (degree_of_freedom) *
424 			     sizeof (MY_DOUBLE))) == 0)
425     {
426       fprintf (stderr, "%s: %d: no free memory\n", __FILE__, __LINE__);
427       exit (1);
428     }
429   p1.z[0] = 0;
430   p1.val = FX;
431 #ifdef DEBUG
432   printf ("inserting point %d " MDF "," MDF "\n", 1, p1.x, p1.y);
433 #endif
434   tg->p1 = BIT_insert (&M, p1);
435   p1.x = 0;
436   p1.y = 3;
437   if ((p1.z =
438        (MY_DOUBLE *) malloc ((size_t) (degree_of_freedom) *
439 			     sizeof (MY_DOUBLE))) == 0)
440     {
441       fprintf (stderr, "%s: %d: no free memory\n", __FILE__, __LINE__);
442       exit (1);
443     }
444   p1.z[0] = 0;
445   p1.val = FX;
446 #ifdef DEBUG
447   printf ("inserting point %d " MDF "," MDF "\n", 2, p1.x, p1.y);
448 #endif
449   tg->p2 = BIT_insert (&M, p1);
450   tg->n = 0;
451   /* triangle is alive */
452   tg->status = LIVE;
453   /* make neighbours -1 */
454   tg->t0 = tg->t1 = tg->t2 = -1;
455   ntriangles = 1;
456 
457   RBT_insert ((void *) tg, &rt);
458   parent_dag_node = dt.root;
459   current_dag_node = DAG_insert (&dt, parent_dag_node, (void *) tg);
460   /* set pointer to dag */
461   tg->dag_p = current_dag_node;
462   /* we have inserted the outer triangle */
463   /* now process the remaining points */
464 
465 
466   for (i = 0; i < G.count; i++)
467     {
468       p1.x = *((G.Narray[i])->xp);
469       p1.y = (G.Narray[i])->y;
470       p1.x += g_xoff;
471       p1.x /= xmax;
472       p1.y += g_yoff;
473       p1.y /= xmax;
474 
475       if ((p1.z =
476 	   (MY_DOUBLE *) malloc ((size_t) (1) * sizeof (MY_DOUBLE))) == 0)
477 	{
478 	  fprintf (stderr, "%s: %d: no free memory\n", __FILE__, __LINE__);
479 	  exit (1);
480 	}
481       p1.z[0] = 0;
482 						p1.val=P_UNKNOWN;
483       /* insert it to mesh */
484       pn = insert_point_to_mesh (p1);
485 			/* insert to point array too */
486 			dxf_point_array[i+3].x=p1.x;
487 			dxf_point_array[i+3].y=p1.y;
488 			dxf_point_array[i+3].z=p1.z;
489 			dxf_point_array[i+3].val=p1.val;
490     }
491 
492 		  /* remove intersections with edges */
493 		  /* create a temporary polygon with all edges */
494 		 init_poly(&temp_polygon);
495 
496 		 /* global edge storage */
497 		 if ((edge_array =(poly_edge *)malloc((size_t)nedges*sizeof(poly_edge)))==0){
498 		fprintf(stderr, "%s: %d: no free memory\n", __FILE__,__LINE__);
499 		exit(1);
500 		}
501   i=0;
502   while (list)
503     {
504       list = E_get (list, &etmp);
505 
506 #ifdef DEBUG
507       printf ("read_dxf: list edge (%d)--(%d)\n", etmp.p1, etmp.p2);
508 #endif
509 						/* increment point number by 3 */
510 						e.p1=etmp.p1+3; e.p2=etmp.p2+3;
511 						e.type=DR; /* arbitrary type */
512 						insert_edge_to_poly(&temp_polygon,&e);
513 						/* also insert this to edge array */
514             edge_array[i].p1=e.p1;
515 						edge_array[i].p2=e.p2;
516 						edge_array[i++].type=E_UNKNOWN;
517     }
518    remove_polygon_mesh_intersections(&temp_polygon);
519 	 destroy_polygon(&temp_polygon);
520 
521   BIT_free (&G);
522 
523 	/* now construct an array, ntriangles by 3
524 	 * type int**. Each row corresponds to a triangle (including hidden).
525 	 * live triangles will have 3 columns each row. (p0-p1),(p1-p2),(p2-p0)
526 	 * edges on any boundary edge, each element of row will
527 	 * give that edge number. if not -1
528 	 */
529 #ifdef DEBUG
530   printf("total triangles=%d\n",ntriangles);
531 #endif
532   if ((triangle_edge_array =(MY_INT**)calloc((size_t)ntriangles,sizeof(MY_INT*)))==0){
533 		fprintf(stderr, "%s: %d: no free memory\n", __FILE__,__LINE__);
534 		exit(1);
535 		}
536 	 DAG_traverse_list_reset(&dt);
537 
538 	 tg=DAG_traverse_prune_list(&dt);
539 	 while(tg) {
540 			if ( tg&&tg->status==LIVE) {
541 #ifdef DEBUG
542 			printf("considering triangle %d for edges\n",tg->n);
543 #endif
544 			/* add record to triangle_edge_array */
545 			if ((triangle_edge_array[tg->n]=(MY_INT*)malloc((size_t)3*sizeof(MY_INT)))==0) {
546       fprintf(stderr, "%s: %d: no free memory\n", __FILE__,__LINE__);
547 		  exit(1);
548 		 }
549 			/* now check each edge of triangle is on a boundary edge */
550 			triangle_edge_array[tg->n][0]=is_this_edge_on_a_boundary(tg->p0,tg->p1);
551 			triangle_edge_array[tg->n][1]=is_this_edge_on_a_boundary(tg->p1,tg->p2);
552 			triangle_edge_array[tg->n][2]=is_this_edge_on_a_boundary(tg->p2,tg->p0);
553 
554 #ifdef DEBUG
555 			printf("edges (%d,%d,%d)\n",triangle_edge_array[tg->n][0],
556          triangle_edge_array[tg->n][1],
557          triangle_edge_array[tg->n][2]);
558 #endif
559 			}
560 		 tg=DAG_traverse_prune_list(&dt);
561 	}
562   current_edge_number=-1;
563 #ifdef DEBUG
564  for (i=0;i<ntriangles;i++) {
565 		if (triangle_edge_array[i]) {
566 			printf("triangle %d/%d: (%d,%d,%d)\n",i,nedges,triangle_edge_array[i][0],
567              triangle_edge_array[i][1],triangle_edge_array[i][2]);
568 		}
569  }
570 #endif
571 
572  /* intialize boundary list */
573  init_boundary_list(&blist);
574   return (0);
575 }
576 
577 /* writing output to output coord file */
578 static void
write_to_output_cord_file(char * outfile)579 write_to_output_cord_file(char *outfile)
580 {
581  FILE *outfd;
582  int i;
583  poly_list *b;
584  dxf_polygon *p;
585  dxf_int *pint;
586 
587  if ( (outfd=fopen(outfile,"w"))==NULL ) {
588 		fprintf(stderr,"%s: %d: could not write to file %s\n",__FILE__,__LINE__,outfile);
589    exit(1);
590  }
591 
592   fprintf(outfd,"# pdnMesh input file %s,\n",outfile);
593   fprintf(outfd,"# Converted from DXF file\n");
594   fprintf(outfd,"# Total no of points\n");
595 	/* points */
596 	fprintf(outfd,"%d\n",dxf_points-3);
597   fprintf(outfd,"# Point data\n");
598   fprintf(outfd,"# Point No, X coord,  Y coord,  Potential,  Fixed(1)/Var(0)\n");
599   for (i=3;i<dxf_points;i++) {
600 		 fprintf(outfd,MIF" "MDF" "MDF" "MDF" ",i-3,Mx(i,M)*g_xscale-g_xoff,My(i,M)*g_yscale-g_yoff,Mz(i,M));
601        if ( Mval(i,M)==DR ) {
602 			fprintf(outfd," 1\n");
603        } else {
604 			 fprintf(outfd," 0\n");
605        }
606   }
607 
608 
609   fprintf(outfd,"# Total Edges\n");
610 	/* edges */
611 	fprintf(outfd,"%d\n",nedges);
612   fprintf(outfd,"# Edge data\n");
613   fprintf(outfd,"# Edge No, Point_1,  Point_2, Type:Dirichlet(1)/Neumann(0)\n");
614 	for ( i=0; i< nedges; i++ ) {
615 		fprintf(outfd,MIF" "MIF" "MIF" ",i,edge_array[i].p1-3,edge_array[i].p2-3);
616 		 if ( edge_array[i].type== DR ) {
617 			fprintf(outfd," 1\n");
618 		 } else {
619 			fprintf(outfd," 0\n");
620 		 }
621 	}
622 
623 	/* boundaries */
624 	b=blist.head;
625   fprintf(outfd,"# Total Boundaries\n");
626 	fprintf(outfd,"%d\n",blist.count);
627   for (i=0;i<blist.count;i++) {
628 	  if ( b ) {
629 			p=b->data;
630 			if ( p ) {
631        fprintf(outfd,"# Boundary data\n");
632        fprintf(outfd,"# Total_Edges,  Not_hollow(1), mu(permeability), epsilon(permittivity), rho(charge/current density) \n");
633 	     fprintf(outfd,"%d %d %s %s %s\n",p->nedges,(p->hollow?1:0),p->mu,p->eps,p->rho);
634 			 pint=p->head;
635        fprintf(outfd,"# Edges\n");
636 			 while(pint) {
637 	       fprintf(outfd,"%d\n",pint->n);
638 				 pint=pint->next;
639 			 }
640 			}
641     }
642 		b=b->next;
643 	}
644 	fclose(outfd);
645 
646 }
647 
648 /********** below is mostly GTK stuff */
649 #ifndef WIN32
650 /* temp globals */
651 MY_DOUBLE temp_scratch_point_z;
652 /* NOTE: we use the following for edge type as well */
653 int temp_scratch_point_type;
654 
655 /* callbacks for point edit */
656 static void
edit_current_point_cb_update(GtkWidget * widget,gpointer data)657 edit_current_point_cb_update(GtkWidget *widget, gpointer data)
658 {
659         /* update the values of current point */
660         Mz(current_point_number,M)=temp_scratch_point_z;
661         Mval(current_point_number,M)=temp_scratch_point_type;
662 				    gtk_widget_destroy(GTK_WIDGET(data));
663 }
664 
665 static void
edit_current_point_cb_cancel(GtkWidget * widget,gpointer data)666 edit_current_point_cb_cancel(GtkWidget *widget, gpointer data)
667 {
668 				    gtk_widget_destroy(GTK_WIDGET(data));
669 }
670 static void
edit_current_point_cb_get_z(GtkWidget * widget,GtkWidget * entry)671 edit_current_point_cb_get_z( GtkWidget *widget,
672                              GtkWidget *entry )
673 {
674 				  const gchar *entry_text;
675 					entry_text = gtk_entry_get_text (GTK_ENTRY (entry));
676           temp_scratch_point_z=(MY_DOUBLE)strtod(entry_text,0);
677 #ifdef DEBUG
678 					printf ("Entry contents: %s="MDF"\n", entry_text,temp_scratch_point_z);
679 #endif
680 }
681 static void
edit_current_point_cb_get_type(GtkWidget * widget,gpointer data)682 edit_current_point_cb_get_type(GtkWidget *widget,gpointer data)
683 {
684   temp_scratch_point_type=GPOINTER_TO_INT(data);
685 }
686 
687 
688 /* utility functions */
689 static GtkWidget *
make_menu_item(gchar * name,GCallback callback,gpointer data)690 make_menu_item(gchar *name, GCallback callback,
691 													gpointer data)
692 {
693 		GtkWidget *item;
694 		item=gtk_menu_item_new_with_label(name);
695 		g_signal_connect(G_OBJECT(item),"activate",
696 		callback,(gpointer)data);
697 		gtk_widget_show(item);
698 	  return(item);
699 }
700 
701 /* edit the properties of the point, given by current_point_number
702  * which is a valid point */
703 static void
edit_current_point_properties(void)704 edit_current_point_properties(void)
705 {
706   GtkWidget *window,*box1,*box2,*label,*button,*entry;
707 	GtkWidget *opt,*menu,*item;
708   static gchar buf[30];
709   /* initialize temp globals */
710   temp_scratch_point_z=Mz(current_point_number,M);
711   temp_scratch_point_type=Mval(current_point_number,M);
712 
713 
714 	window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
715 	g_signal_connect(G_OBJECT(window),"delete_event",
716 								G_CALLBACK(gtk_main_quit),NULL);
717 	gtk_window_set_title(GTK_WINDOW(window),"Edit Point");
718   gtk_window_set_modal(GTK_WINDOW(window),TRUE);
719 
720 	box1=gtk_vbox_new(FALSE,0);
721 	gtk_container_add(GTK_CONTAINER(window),box1);
722 	gtk_widget_show(box1);
723 
724 	box2=gtk_hbox_new(FALSE,10);
725 	gtk_container_set_border_width(GTK_CONTAINER(box2),10);
726 	gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0);
727 	gtk_widget_show(box2);
728 	sprintf(buf,"X["MIF"]=",current_point_number);
729 	label=gtk_label_new(buf);
730 	gtk_box_pack_start(GTK_BOX(box2),label,FALSE,FALSE,0);
731 	gtk_widget_show(label);
732   /* uneditable text */
733 	entry = gtk_entry_new();
734 	gtk_entry_set_max_length (GTK_ENTRY(entry), 50);
735   sprintf(buf,MDF,Mx(current_point_number,M));
736   gtk_entry_set_text (GTK_ENTRY (entry), buf);
737   gtk_editable_set_editable (GTK_EDITABLE(entry), FALSE);
738   gtk_box_pack_start (GTK_BOX(box2), entry, FALSE, FALSE, 0);
739 	gtk_widget_show(entry);
740 
741   box2=gtk_hbox_new(FALSE,10);
742 	gtk_container_set_border_width(GTK_CONTAINER(box2),10);
743 	gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0);
744 	gtk_widget_show(box2);
745   sprintf(buf,"Y["MIF"]=",current_point_number);
746 	label=gtk_label_new(buf);
747 	gtk_box_pack_start(GTK_BOX(box2),label,FALSE,FALSE,0);
748 	gtk_widget_show(label);
749   /* editable text */
750 	entry = gtk_entry_new();
751 	gtk_entry_set_max_length (GTK_ENTRY(entry), 50);
752   sprintf(buf,MDF,My(current_point_number,M));
753   gtk_entry_set_text (GTK_ENTRY (entry), buf);
754   gtk_editable_set_editable (GTK_EDITABLE(entry), FALSE);
755   gtk_box_pack_start (GTK_BOX(box2), entry, FALSE, FALSE, 0);
756 	gtk_widget_show(entry);
757 
758 
759 
760 	/* editable parameters */
761 	box2=gtk_hbox_new(FALSE,10);
762 	gtk_container_set_border_width(GTK_CONTAINER(box2),10);
763 	gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0);
764 	gtk_widget_show(box2);
765   sprintf(buf,"Z["MIF"]=",current_point_number);
766 	label=gtk_label_new(buf);
767 	gtk_box_pack_start(GTK_BOX(box2),label,FALSE,FALSE,0);
768 	gtk_widget_show(label);
769   /* editable text */
770 	/* z value of a point */
771 	entry = gtk_entry_new();
772 	gtk_entry_set_max_length (GTK_ENTRY(entry), 50);
773   sprintf(buf,MDF,Mz(current_point_number,M));
774   gtk_entry_set_text (GTK_ENTRY (entry), buf);
775 	g_signal_connect(G_OBJECT(entry), "changed",
776 									G_CALLBACK(edit_current_point_cb_get_z),
777 									(gpointer)entry);
778   gtk_editable_set_editable (GTK_EDITABLE(entry), TRUE);
779   gtk_box_pack_start (GTK_BOX(box2), entry, FALSE, FALSE, 0);
780 	gtk_widget_show(entry);
781 
782   /* point type */
783 	box2=gtk_hbox_new(FALSE,10);
784 	gtk_container_set_border_width(GTK_CONTAINER(box2),10);
785 	gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0);
786 	gtk_widget_show(box2);
787   label=gtk_label_new("Point Type:");
788 	gtk_box_pack_start(GTK_BOX(box2),label,FALSE,FALSE,0);
789 	gtk_widget_show(label);
790 
791 	 opt=gtk_option_menu_new();
792 	 menu=gtk_menu_new();
793 	 item=make_menu_item("variable",
794 	        G_CALLBACK(edit_current_point_cb_get_type),
795 		      GINT_TO_POINTER(VAR));
796 	gtk_menu_shell_append(GTK_MENU_SHELL(menu),item);
797   item=make_menu_item("fixed",
798 	        G_CALLBACK(edit_current_point_cb_get_type),
799 				  GINT_TO_POINTER(FX));
800 	gtk_menu_shell_append(GTK_MENU_SHELL(menu),item);
801   item=make_menu_item("unknown",
802           G_CALLBACK(edit_current_point_cb_get_type),
803 				  GINT_TO_POINTER(P_UNKNOWN));
804 	gtk_menu_shell_append(GTK_MENU_SHELL(menu),item);
805 
806   gtk_option_menu_set_menu(GTK_OPTION_MENU(opt),menu);
807   if ( Mval(current_point_number,M)==VAR) {
808       gtk_option_menu_set_history(GTK_OPTION_MENU(opt),0);
809   } else if ( Mval(current_point_number,M)==FX) {
810 	    gtk_option_menu_set_history(GTK_OPTION_MENU(opt),1);
811 	} else {
812 	    gtk_option_menu_set_history(GTK_OPTION_MENU(opt),2);
813 	}
814 	gtk_box_pack_start(GTK_BOX(box2),opt,TRUE,TRUE,0);
815 	gtk_widget_show(opt);
816 
817 
818 
819 	/* cancel, update buttons */
820   box2=gtk_hbox_new(FALSE,10);
821 	gtk_container_set_border_width(GTK_CONTAINER(box2),10);
822 	gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0);
823 	gtk_widget_show(box2);
824 
825 
826 	button=gtk_button_new_with_label("OK");
827 	g_signal_connect(G_OBJECT(button),"clicked",
828 									G_CALLBACK(edit_current_point_cb_update),
829 									window);
830 
831 	gtk_box_pack_start(GTK_BOX(box2),button,TRUE,TRUE,0);
832 	GTK_WIDGET_SET_FLAGS(button,GTK_CAN_DEFAULT);
833 	gtk_widget_grab_default(button);
834 	gtk_widget_show(button);
835 
836 	button=gtk_button_new_with_label("Cancel");
837 	g_signal_connect(G_OBJECT(button),"clicked",
838 									G_CALLBACK(edit_current_point_cb_cancel),
839 									window);
840 
841 	gtk_box_pack_start(GTK_BOX(box2),button,TRUE,TRUE,0);
842 	gtk_widget_show(button);
843 
844 
845 	gtk_widget_show(window);
846 }
847 
848 
849 /* callbacks for edge edit */
850 static void
edit_current_edge_cb_update(GtkWidget * widget,gpointer data)851 edit_current_edge_cb_update(GtkWidget *widget, gpointer data)
852 {
853         /* update the values of current point */
854         edge_array[current_edge_number].type=temp_scratch_point_type;
855 				gtk_widget_destroy(GTK_WIDGET(data));
856 }
857 
858 
859 /* edit the properties of the edge, given by current_edge_number
860  * which is a valid edge */
861 static void
edit_current_edge_properties(void)862 edit_current_edge_properties(void)
863 {
864   GtkWidget *window,*box1,*box2,*label,*button;
865   GtkWidget *opt,*menu,*item;
866 
867   /* store default */
868  temp_scratch_point_type=edge_array[current_edge_number].type;
869 
870   window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
871 	g_signal_connect(G_OBJECT(window),"delete_event",
872 								G_CALLBACK(gtk_main_quit),NULL);
873 	gtk_window_set_title(GTK_WINDOW(window),"Edit Edge");
874   gtk_window_set_modal(GTK_WINDOW(window),TRUE);
875 
876 	box1=gtk_vbox_new(FALSE,0);
877 	gtk_container_add(GTK_CONTAINER(window),box1);
878 	gtk_widget_show(box1);
879 
880 	box2=gtk_hbox_new(FALSE,10);
881 	gtk_container_set_border_width(GTK_CONTAINER(box2),10);
882 	gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0);
883 	gtk_widget_show(box2);
884 
885 
886   label=gtk_label_new("Edge Type:");
887 	gtk_box_pack_start(GTK_BOX(box2),label,FALSE,FALSE,0);
888 	gtk_widget_show(label);
889 
890 	 opt=gtk_option_menu_new();
891 	 menu=gtk_menu_new();
892 	 item=make_menu_item("Neumann",
893 	        G_CALLBACK(edit_current_point_cb_get_type),
894 		      GINT_TO_POINTER(VAR));
895 	gtk_menu_shell_append(GTK_MENU_SHELL(menu),item);
896   item=make_menu_item("Dirichlet",
897 	        G_CALLBACK(edit_current_point_cb_get_type),
898 				  GINT_TO_POINTER(FX));
899 	gtk_menu_shell_append(GTK_MENU_SHELL(menu),item);
900   item=make_menu_item("unknown",
901           G_CALLBACK(edit_current_point_cb_get_type),
902 				  GINT_TO_POINTER(P_UNKNOWN));
903 	gtk_menu_shell_append(GTK_MENU_SHELL(menu),item);
904 
905   gtk_option_menu_set_menu(GTK_OPTION_MENU(opt),menu);
906   if ( edge_array[current_edge_number].type==NU) {
907       gtk_option_menu_set_history(GTK_OPTION_MENU(opt),0);
908   } else if ( edge_array[current_edge_number].type==DR) {
909 	    gtk_option_menu_set_history(GTK_OPTION_MENU(opt),1);
910 	} else {
911 	    gtk_option_menu_set_history(GTK_OPTION_MENU(opt),2);
912 	}
913 	gtk_box_pack_start(GTK_BOX(box2),opt,TRUE,TRUE,0);
914 	gtk_widget_show(opt);
915 
916 
917 
918   /* cancel, update buttons */
919   box2=gtk_hbox_new(FALSE,10);
920 	gtk_container_set_border_width(GTK_CONTAINER(box2),10);
921 	gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0);
922 	gtk_widget_show(box2);
923 
924 
925 	button=gtk_button_new_with_label("OK");
926 	g_signal_connect(G_OBJECT(button),"clicked",
927 									G_CALLBACK(edit_current_edge_cb_update),
928 									window);
929 
930 	gtk_box_pack_start(GTK_BOX(box2),button,TRUE,TRUE,0);
931 	GTK_WIDGET_SET_FLAGS(button,GTK_CAN_DEFAULT);
932 	gtk_widget_grab_default(button);
933 	gtk_widget_show(button);
934 
935 	button=gtk_button_new_with_label("Cancel");
936 	g_signal_connect(G_OBJECT(button),"clicked",
937 									G_CALLBACK(edit_current_point_cb_cancel),
938 									window);
939   /* NOTE: we use callback of edit_current_point_properties above */
940 	gtk_box_pack_start(GTK_BOX(box2),button,TRUE,TRUE,0);
941 	gtk_widget_show(button);
942 
943 
944 	gtk_widget_show(window);
945 
946 }
947 
948 static void
949 display_boundary_edit_window(void);
950 
951 static void
boundary_edit_add_boundary(GtkWidget * widget,gpointer data)952 boundary_edit_add_boundary(GtkWidget *widget,gpointer data)
953 {
954   dxf_polygon *p;
955 	if ((p=(dxf_polygon*)malloc(sizeof(dxf_polygon)))==0) {
956    fprintf(stderr,"%s: %d: no free memory",__FILE__,__LINE__);
957 	 exit(1);
958 	}
959 	p->head=0;
960 	p->nedges=0;
961 	/* set default values */
962   /* hollow =1 - keep triangles */
963 	p->hollow=1;
964 	if ((p->rho=(char*)malloc(sizeof(char)*4))==0) {
965    fprintf(stderr,"%s: %d: no free memory",__FILE__,__LINE__);
966 	 exit(1);
967 	}
968 	if ((p->mu=(char*)malloc(sizeof(char)*4))==0) {
969    fprintf(stderr,"%s: %d: no free memory",__FILE__,__LINE__);
970 	 exit(1);
971 	}
972 	if ((p->eps=(char*)malloc(sizeof(char)*4))==0) {
973    fprintf(stderr,"%s: %d: no free memory",__FILE__,__LINE__);
974 	 exit(1);
975 	}
976 
977   strcpy(p->rho,"0.0");
978   strcpy(p->mu,"1.0");
979   strcpy(p->eps,"1.0");
980 	insert_poly_to_boundary(&blist,p);
981 
982 	/* untrack events */
983  mouse_responce_flag=MENU_0;
984 
985 	/* close and reopen the window */
986 	gtk_widget_destroy(GTK_WIDGET(data));
987 	/* reopen */
988 	display_boundary_edit_window();
989 }
990 
991 /* edit current boundary edge list */
992 static void
boundary_edit_edit_boundary(GtkWidget * widget,gpointer data)993 boundary_edit_edit_boundary(GtkWidget *widget,gpointer data)
994 {
995   /* edit current polygon */
996 		/* track closest edges */
997   mouse_responce_flag=MENU_ADD_EDGE;
998 }
999 
1000 
1001 static void
boundary_edit_cancel(GtkWidget * widget,gpointer data)1002 boundary_edit_cancel(GtkWidget *widget,gpointer data)
1003 {
1004   /* untrack events */
1005   mouse_responce_flag=MENU_0;
1006 
1007 	/* sort all polygons of boundaries */
1008 	if ( sort_edges_in_polygons(&blist)== -1 ) {
1009 					generic_dialog("At least One boundary is not closed.\nYou may need to check them again.","Warning!");
1010  }
1011 	/* close the window */
1012 	gtk_widget_destroy(GTK_WIDGET(data));
1013 }
1014 
1015 /* change edit status of texy entry field */
1016 static void
entry_toggle_editable(GtkWidget * button,GtkWidget * entry)1017 entry_toggle_editable( GtkWidget *button,
1018               GtkWidget *entry )
1019 {
1020 				  gtk_editable_set_editable(GTK_EDITABLE (entry),
1021 									GTK_TOGGLE_BUTTON (button)->active);
1022 }
1023 /* change edit status of texy entry field */
1024 static void
check_button_toggle_editable(GtkWidget * toggle_button,GtkWidget * cbutton)1025 check_button_toggle_editable( GtkWidget *toggle_button,
1026               GtkWidget *cbutton)
1027 {
1028 
1029        GtkStyle *style=gtk_widget_get_style(GTK_WIDGET(cbutton));
1030 			if (!GTK_TOGGLE_BUTTON(toggle_button)->active) {
1031       /* disable check button */
1032        gtk_widget_modify_base(cbutton,GTK_STATE_INSENSITIVE,
1033          &style->base[GTK_STATE_NORMAL]);
1034        gtk_widget_modify_text(cbutton,GTK_STATE_INSENSITIVE,
1035          &style->base[GTK_STATE_NORMAL]);
1036       }
1037 }
1038 /* callback to record which button is being toggled */
1039 static void
record_toggle_button(GtkWidget * button,gpointer data)1040 record_toggle_button(GtkWidget *button,
1041 														gpointer data)
1042 {
1043  /* untrack events */
1044  mouse_responce_flag=MENU_0;
1045 
1046 #ifdef debug
1047 			printf("button %d on\n",GPOINTER_TO_INT(data));
1048 #endif
1049 			current_polygon=lookup_poly_from_boundary(&blist,GPOINTER_TO_INT(data));
1050 }
1051 
1052 static void
entry_get_hollow(GtkWidget * widget,GtkWidget * button)1053 entry_get_hollow( GtkWidget *widget,
1054                              GtkWidget *button)
1055 {
1056 			if ( current_polygon ) {
1057           if(GTK_TOGGLE_BUTTON(button)->active) {
1058            current_polygon->hollow=1;
1059           } else {
1060            current_polygon->hollow=0;
1061 					}
1062       }
1063 }
1064 
1065 static void
entry_get_mu(GtkWidget * widget,GtkWidget * entry)1066 entry_get_mu( GtkWidget *widget,
1067                              GtkWidget *entry )
1068 {
1069 				  const gchar *entry_text;
1070 					entry_text = gtk_entry_get_text (GTK_ENTRY (entry));
1071 					if ( current_polygon ) {
1072            if((current_polygon->mu=(char*)realloc((void*)current_polygon->mu,
1073             sizeof(char*)*(size_t)(strlen(entry_text)+1)))==0) {
1074             fprintf(stderr,"%s: %d: No free memory\n",__FILE__,__LINE__);
1075             exit(1);
1076            }
1077           strcpy(current_polygon->mu,entry_text);
1078 					}
1079 #ifdef DEBUG
1080 					printf ("Entry contents: %s=%s\n", entry_text, current_polygon->mu);
1081 #endif
1082 }
1083 
1084 static void
entry_get_eps(GtkWidget * widget,GtkWidget * entry)1085 entry_get_eps( GtkWidget *widget,
1086                              GtkWidget *entry )
1087 {
1088 				  const gchar *entry_text;
1089 					entry_text = gtk_entry_get_text (GTK_ENTRY (entry));
1090 					if ( current_polygon ) {
1091            if((current_polygon->eps=(char*)realloc((void*)current_polygon->eps,
1092             sizeof(char*)*(size_t)(strlen(entry_text)+1)))==0) {
1093             fprintf(stderr,"%s: %d: No free memory\n",__FILE__,__LINE__);
1094             exit(1);
1095            }
1096           strcpy(current_polygon->eps,entry_text);
1097 					}
1098 #ifdef DEBUG
1099 					printf ("Entry contents: %s=%s\n", entry_text, current_polygon->eps);
1100 #endif
1101 }
1102 
1103 
1104 static void
entry_get_rho(GtkWidget * widget,GtkWidget * entry)1105 entry_get_rho( GtkWidget *widget,
1106                              GtkWidget *entry )
1107 {
1108 				  const gchar *entry_text;
1109 					entry_text = gtk_entry_get_text (GTK_ENTRY (entry));
1110 					if ( current_polygon ) {
1111            if((current_polygon->rho=(char*)realloc((void*)current_polygon->rho,
1112             sizeof(char*)*(size_t)(strlen(entry_text)+1)))==0) {
1113             fprintf(stderr,"%s: %d: No free memory\n",__FILE__,__LINE__);
1114             exit(1);
1115            }
1116           strcpy(current_polygon->rho,entry_text);
1117 					}
1118 #ifdef DEBUG
1119 					printf ("Entry contents: %s=%s\n", entry_text, current_polygon->rho);
1120 #endif
1121 }
1122 
1123 /* edit boundaries */
1124 static void
display_boundary_edit_window(void)1125 display_boundary_edit_window(void)
1126 {
1127   GtkWidget *window,*box1,*box2;
1128 	GtkWidget *label,*button,*separator;
1129 	GtkWidget *entry,*cbutton;
1130   GtkStyle *style;
1131 /* array of buttons for the radio buttons */
1132 GtkWidget **buttons=0;
1133 
1134 
1135 	static gchar buf[30];
1136   int i;
1137   poly_list *cp;
1138 
1139   window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
1140 	g_signal_connect(G_OBJECT(window),"delete_event",
1141 								G_CALLBACK(gtk_main_quit),NULL);
1142 	gtk_window_set_title(GTK_WINDOW(window),"Boundary List");
1143   gtk_window_set_modal(GTK_WINDOW(window),FALSE);
1144 
1145 	box1=gtk_vbox_new(FALSE,0);
1146 	gtk_container_add(GTK_CONTAINER(window),box1);
1147 	gtk_widget_show(box1);
1148 
1149 	/* traverse the boundary list */
1150 	cp=blist.head;
1151 
1152 	/* allocate memory for button array */
1153 	if ((buttons=(GtkWidget **)malloc(sizeof(GtkWidget*)*(size_t)blist.count))==0) {
1154       fprintf (stderr, "%s: %d: no free memory", __FILE__, __LINE__);
1155       exit (1);
1156 	}
1157  for (i=0;i<blist.count;i++) {
1158   box2=gtk_hbox_new(FALSE,10);
1159 	 gtk_container_set_border_width(GTK_CONTAINER(box2),10);
1160 	 gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0);
1161 	 gtk_widget_show(box2);
1162 
1163 	 sprintf(buf,"Boundary %d",i);
1164 
1165 
1166 	 /* radio button */
1167 	 if ( !i ) {
1168 	  buttons[i] = gtk_radio_button_new_with_label (NULL, buf);
1169 	  gtk_box_pack_start (GTK_BOX (box2), buttons[i], TRUE, TRUE, 0);
1170    gtk_widget_show (buttons[i]);
1171   } else {
1172 	 buttons[i] = gtk_radio_button_new_with_label_from_widget(
1173 						GTK_RADIO_BUTTON (buttons[0]),
1174 						buf);
1175 	 gtk_box_pack_start (GTK_BOX (box2), buttons[i], TRUE, TRUE, 0);
1176 	 gtk_widget_show (buttons[i]);
1177 	}
1178 
1179 
1180    box2=gtk_hbox_new(FALSE,10);
1181 	 gtk_container_set_border_width(GTK_CONTAINER(box2),10);
1182 	 gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0);
1183 	 gtk_widget_show(box2);
1184 
1185 
1186   cbutton=gtk_check_button_new_with_label("Hollow");
1187   if( cp->data && cp->data->hollow==0) {
1188    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cbutton),TRUE);
1189   } else {
1190    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cbutton),FALSE);
1191   }
1192 	gtk_box_pack_start(GTK_BOX(box2),cbutton,FALSE,FALSE,0);
1193 	/*label=gtk_label_new("not hollow=");
1194 	gtk_box_pack_start(GTK_BOX(box2),label,FALSE,FALSE,0);
1195 	gtk_widget_show(label);
1196   entry = gtk_entry_new();
1197 	gtk_entry_set_max_length(GTK_ENTRY(entry), 1); */
1198   /*if (cp->data&&(cp->data->hollow==1)) {
1199    gtk_entry_set_text (GTK_ENTRY (entry), "1");
1200 	} else  {
1201    gtk_entry_set_text (GTK_ENTRY (entry), "0");
1202 	} */
1203 
1204   style=gtk_widget_get_style(cbutton);
1205   if (i) {
1206    gtk_widget_modify_base(cbutton,GTK_STATE_INSENSITIVE,
1207        &style->base[GTK_STATE_NORMAL]);
1208    gtk_widget_modify_text(cbutton,GTK_STATE_INSENSITIVE,
1209        &style->base[GTK_STATE_NORMAL]);
1210   }
1211 	/* connect signal to radio button */
1212   g_signal_connect (G_OBJECT (buttons[i]), "toggled",
1213 					G_CALLBACK(check_button_toggle_editable), (gpointer) cbutton);
1214   g_signal_connect(G_OBJECT(cbutton), "toggled",
1215 									G_CALLBACK(entry_get_hollow),
1216 									(gpointer)cbutton);
1217 	gtk_widget_show(cbutton);
1218 
1219 	label=gtk_label_new("mu=");
1220 	gtk_box_pack_start(GTK_BOX(box2),label,FALSE,FALSE,0);
1221 	gtk_widget_show(label);
1222 	/* create text entry */
1223   entry = gtk_entry_new();
1224 	gtk_entry_set_max_length(GTK_ENTRY(entry), 10);
1225 
1226   if (cp->data) {
1227    gtk_entry_set_text (GTK_ENTRY (entry), cp->data->mu);
1228 	} else  {
1229    gtk_entry_set_text (GTK_ENTRY (entry), "???");
1230 	}
1231   gtk_box_pack_start (GTK_BOX(box2), entry, FALSE, FALSE, 0);
1232 	/* connect signal to radio button */
1233 	if (!i) {
1234 	g_signal_connect (G_OBJECT (buttons[i]), "toggled",
1235 					G_CALLBACK(entry_toggle_editable), (gpointer) entry);
1236 			gtk_editable_set_editable (GTK_EDITABLE(entry), TRUE);
1237   } else {
1238   g_signal_connect (G_OBJECT (buttons[i]), "toggled",
1239 					G_CALLBACK(entry_toggle_editable), (gpointer) entry);
1240 			gtk_editable_set_editable (GTK_EDITABLE(entry), FALSE);
1241   }
1242   g_signal_connect(G_OBJECT(entry), "changed",
1243 									G_CALLBACK(entry_get_mu),
1244 									(gpointer)entry);
1245 	gtk_widget_show(entry);
1246 
1247   label=gtk_label_new("epsilon=");
1248 	gtk_box_pack_start(GTK_BOX(box2),label,FALSE,FALSE,0);
1249 	gtk_widget_show(label);
1250 	/* create text entry */
1251   entry = gtk_entry_new();
1252 	gtk_entry_set_max_length(GTK_ENTRY(entry), 10);
1253 
1254   if (cp->data) {
1255    gtk_entry_set_text (GTK_ENTRY (entry), cp->data->eps);
1256 	} else  {
1257    gtk_entry_set_text (GTK_ENTRY (entry), "???");
1258 	}
1259   gtk_box_pack_start (GTK_BOX(box2), entry, FALSE, FALSE, 0);
1260 	/* connect signal to radio button */
1261 	if (!i) {
1262 	g_signal_connect (G_OBJECT (buttons[i]), "toggled",
1263 					G_CALLBACK(entry_toggle_editable), (gpointer) entry);
1264 			gtk_editable_set_editable (GTK_EDITABLE(entry), TRUE);
1265   } else {
1266   g_signal_connect (G_OBJECT (buttons[i]), "toggled",
1267 					G_CALLBACK(entry_toggle_editable), (gpointer) entry);
1268 			gtk_editable_set_editable (GTK_EDITABLE(entry), FALSE);
1269   }
1270   g_signal_connect(G_OBJECT(entry), "changed",
1271 									G_CALLBACK(entry_get_eps),
1272 									(gpointer)entry);
1273 	gtk_widget_show(entry);
1274 
1275   label=gtk_label_new("rho=");
1276 	gtk_box_pack_start(GTK_BOX(box2),label,FALSE,FALSE,0);
1277 	gtk_widget_show(label);
1278 	/* create text entry */
1279   entry = gtk_entry_new();
1280 	gtk_entry_set_max_length(GTK_ENTRY(entry), 10);
1281 
1282   if (cp->data) {
1283    gtk_entry_set_text (GTK_ENTRY (entry), cp->data->rho);
1284 	} else  {
1285    gtk_entry_set_text (GTK_ENTRY (entry), "???");
1286 	}
1287   gtk_box_pack_start (GTK_BOX(box2), entry, FALSE, FALSE, 0);
1288 	/* connect signal to radio button */
1289 	if (!i) {
1290 	g_signal_connect (G_OBJECT (buttons[i]), "toggled",
1291 					G_CALLBACK(entry_toggle_editable), (gpointer) entry);
1292 			gtk_editable_set_editable (GTK_EDITABLE(entry), TRUE);
1293   } else {
1294   g_signal_connect (G_OBJECT (buttons[i]), "toggled",
1295 					G_CALLBACK(entry_toggle_editable), (gpointer) entry);
1296 			gtk_editable_set_editable (GTK_EDITABLE(entry), FALSE);
1297   }
1298   g_signal_connect(G_OBJECT(entry), "changed",
1299 									G_CALLBACK(entry_get_rho),
1300 									(gpointer)entry);
1301 	gtk_widget_show(entry);
1302 
1303 
1304  g_signal_connect(G_OBJECT(buttons[i]),"pressed",
1305 													G_CALLBACK(record_toggle_button),GINT_TO_POINTER(i));
1306 
1307 	cp=cp->next;
1308 	}
1309   /* free buttons */
1310 	free(buttons);
1311 	current_polygon=lookup_poly_from_boundary(&blist,0);
1312 
1313 	/* seperator */
1314   separator = gtk_hseparator_new();
1315   gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
1316   gtk_widget_show (separator);
1317 
1318 	/* buttons */
1319   box2=gtk_hbox_new(FALSE,10);
1320 	gtk_container_set_border_width(GTK_CONTAINER(box2),10);
1321 	gtk_box_pack_start(GTK_BOX(box1),box2,TRUE,TRUE,0);
1322 	gtk_widget_show(box2);
1323 
1324 
1325 	button=gtk_button_new_with_label("New Boundary");
1326 	g_signal_connect(G_OBJECT(button),"clicked",
1327 									G_CALLBACK(boundary_edit_add_boundary),
1328 									window);
1329 
1330 	gtk_box_pack_start(GTK_BOX(box2),button,TRUE,TRUE,0);
1331 	GTK_WIDGET_SET_FLAGS(button,GTK_CAN_DEFAULT);
1332 	gtk_widget_grab_default(button);
1333 	gtk_widget_show(button);
1334 
1335 	button=gtk_button_new_with_label("Add Edges");
1336 	g_signal_connect(G_OBJECT(button),"clicked",
1337 									G_CALLBACK(boundary_edit_edit_boundary),
1338 									window);
1339 
1340 	gtk_box_pack_start(GTK_BOX(box2),button,TRUE,TRUE,0);
1341 	GTK_WIDGET_SET_FLAGS(button,GTK_CAN_DEFAULT);
1342 	gtk_widget_grab_default(button);
1343 	gtk_widget_show(button);
1344 
1345 
1346 	button=gtk_button_new_with_label("Done");
1347 	g_signal_connect(G_OBJECT(button),"clicked",
1348 									G_CALLBACK(boundary_edit_cancel),
1349 									window);
1350 
1351 	gtk_box_pack_start(GTK_BOX(box2),button,TRUE,TRUE,0);
1352 	gtk_widget_show(button);
1353 
1354 
1355 	gtk_widget_show(window);
1356 
1357 }
1358 
1359 
1360 
1361 static void
draw_circle(float x,float y,float radius)1362 draw_circle(float x, float y, float radius)
1363 {
1364 						float ang;
1365 						glPushMatrix();
1366 						glTranslatef(x, y, 0);
1367 						glBegin(GL_LINE_LOOP);
1368 						for( ang=0; ang <= 2*M_PI; ang += 0.1)
1369 								 glVertex2f( radius * cos(ang), radius * sin(ang));
1370 						glEnd();
1371 						glPopMatrix();
1372 }
1373 
1374 
1375 static void
realize(GtkWidget * widget,gpointer data)1376 realize (GtkWidget *widget,
1377 								   gpointer   data)
1378 {
1379 	GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
1380 	GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
1381 
1382 	/*** OpenGL BEGIN ***/
1383 	if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
1384 	return;
1385 
1386 	/*** Fill in the details here. ***/
1387 	gdk_gl_drawable_gl_end (gldrawable);
1388   /*** OpenGL END ***/
1389 }
1390 
1391 
1392 static gboolean
configure_event(GtkWidget * widget,GdkEventConfigure * event,gpointer data)1393 configure_event (GtkWidget         *widget,
1394 								     GdkEventConfigure *event,
1395 										      gpointer           data)
1396 {
1397 		GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
1398 		GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
1399 		GLfloat w = widget->allocation.width;
1400 		GLfloat h = widget->allocation.height;
1401 		/*g_print ("%s: \"configure_event\"\n", gtk_widget_get_name (widget)); */
1402 
1403 		/*** OpenGL BEGIN ***/
1404 		if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
1405 		return FALSE;
1406 		/*** Fill in the details here. ***/
1407 		glViewport (0, 0, w, h);
1408 		glMatrixMode(GL_PROJECTION);
1409 		glLoadIdentity();
1410 		gluOrtho2D(-1,1,-1,1);
1411 		glMatrixMode(GL_MODELVIEW);
1412 		gdk_gl_drawable_gl_end (gldrawable);
1413 		/*** OpenGL END ***/
1414 	return TRUE;
1415 }
1416 
1417 
1418 static gboolean
expose_event(GtkWidget * widget,GdkEventExpose * event,gpointer data)1419 expose_event (GtkWidget      *widget,
1420 	      GdkEventExpose *event,
1421 	      gpointer        data)
1422 {
1423 			int i;
1424  dxf_int *hh;
1425 
1426   GdkGLContext *glcontext = gtk_widget_get_gl_context (widget);
1427   GdkGLDrawable *gldrawable = gtk_widget_get_gl_drawable (widget);
1428 
1429 #ifdef DEBUG
1430   g_print ("%s: \"expose_event\"\n", gtk_widget_get_name (widget));
1431 #endif
1432 
1433   /*** OpenGL BEGIN ***/
1434   if (!gdk_gl_drawable_gl_begin (gldrawable, glcontext))
1435     return FALSE;
1436 
1437   glClear (GL_COLOR_BUFFER_BIT);
1438   glLineWidth(1.0);
1439 
1440 /*	 triangle *rec;
1441    glColor3f(0.6f,0.3f,0.1f);
1442 	 DAG_traverse_list_reset(&dt);
1443 
1444 	 rec=DAG_traverse_prune_list(&dt);
1445 	 while(rec) {
1446 			if ( rec&&rec->status==LIVE) {
1447 						glBegin(GL_LINE_LOOP);
1448 						glVertex2f((GLfloat)Mx(rec->p0),(GLfloat)My(rec->p0));
1449 						glVertex2f((GLfloat)Mx(rec->p1),(GLfloat)My(rec->p1));
1450 						glVertex2f((GLfloat)Mx(rec->p2),(GLfloat)My(rec->p2));
1451 						glEnd();
1452 			}
1453 		 rec=DAG_traverse_prune_list(&dt);
1454 	} */
1455 
1456 	/* chosen triangle */
1457 /*	if ( chosen_triangle ) {
1458 		glColor3f(1.0f, 0.3f, 1.0f);
1459 		glLineWidth(1.0);
1460 	  glBegin(GL_LINE_LOOP);
1461 	  glVertex2f( (GLfloat)Mx(chosen_triangle->p0), (GLfloat)My(chosen_triangle->p0));
1462 	  glVertex2f( (GLfloat)Mx(chosen_triangle->p1), (GLfloat)My(chosen_triangle->p1));
1463 	  glVertex2f( (GLfloat)Mx(chosen_triangle->p2), (GLfloat)My(chosen_triangle->p2));
1464 	 glEnd();
1465 	} */
1466   if ( mouse_responce_flag==MENU_EDIT_POINT ) {
1467    /* points in the triangulation */
1468    for (i=3;i<dxf_points;i++) {
1469        if ( Mval(i,M)==DR ) {
1470 		    glColor3f(0.3f, 0.9f, 0.3f);
1471        } else if ( Mval(i,M)==NU ) {
1472 		    glColor3f(0.3f, 0.3f, 0.9f);
1473        } else  {
1474 		    glColor3f(0.9f, 0.3f, 0.9f);
1475        }
1476       draw_circle((float)Mx(i,M),(float)My(i,M),0.02f/current_mat[0]);
1477   }
1478  /* closest point, only from the original point set */
1479 	/* valid numbers are 3,4,...,dxf_points-1 */
1480 	 if ((current_point_number>2) && (current_point_number< dxf_points) ) {
1481 		 glColor3f(1.0f, 1.0f, 1.0f);
1482      glGetDoublev(GL_MODELVIEW_MATRIX,current_mat);
1483      draw_circle((float)Mx(current_point_number,M),(float)My(current_point_number,M),0.03f/current_mat[0]);
1484 	 }
1485   }
1486 
1487 	/* edge array */
1488 	for ( i=0; i< nedges; i++ ) {
1489 		 if ( edge_array[i].type== DR ) {
1490 				 glColor3f(0.9f, 1.0f, 0.4f);
1491 		 } else if (edge_array[i].type== NU ) {
1492          glColor3f(0.4f,0.5f,0.9f);
1493 		 } else {
1494 				glColor3f(1.0f,1.0f,1.0f);
1495 		 }
1496 	  glBegin(GL_LINE_LOOP);
1497 		glVertex2f((GLfloat)Mx(edge_array[i].p1,M),(GLfloat)My(edge_array[i].p1,M));
1498 		glVertex2f((GLfloat)Mx(edge_array[i].p2,M),(GLfloat)My(edge_array[i].p2,M));
1499 		glEnd();
1500 	}
1501 
1502 	/* closest edge */
1503 
1504  if ( mouse_responce_flag==MENU_EDIT_EDGE
1505 							|| mouse_responce_flag==MENU_ADD_EDGE	) {
1506   if ( current_edge_number != -1 ) {
1507    glColor3f(0.1f,1.0f,0.9f);
1508 	glLineWidth(2.0);
1509    glBegin(GL_LINES);
1510    glVertex2f((GLfloat)Mx(edge_array[current_edge_number].p1,M),
1511        (GLfloat)My(edge_array[current_edge_number].p1,M));
1512    glVertex2f((GLfloat)Mx(edge_array[current_edge_number].p2,M),
1513        (GLfloat)My(edge_array[current_edge_number].p2,M));
1514    glEnd();
1515   }
1516  }
1517 
1518  /* draw current polygon while adding edges to it */
1519  if ( mouse_responce_flag==MENU_ADD_EDGE ) {
1520 		if ( current_polygon ) {
1521 			 hh=current_polygon->head;
1522       glColor3f(0.5f,0.3f,0.5f);
1523 	    glLineWidth(2.0);
1524 			 while(hh) {
1525       glBegin(GL_LINES);
1526    glVertex2f((GLfloat)Mx(edge_array[hh->n].p1,M),
1527        (GLfloat)My(edge_array[hh->n].p1,M));
1528    glVertex2f((GLfloat)Mx(edge_array[hh->n].p2,M),
1529        (GLfloat)My(edge_array[hh->n].p2,M));
1530    glEnd();
1531       hh=hh->next;
1532 		 }
1533 		}
1534   }
1535 	/* zoom window */
1536 	/* draw zoom window */
1537 	 if ( mouse_responce_flag == MENU_ZOOM_END ) { /* first point has been selected */
1538 		 glBegin(GL_LINE_STRIP);
1539 			glColor3f(0.0f, 1.0f, 1.0f);
1540 			glVertex2f( (GLfloat)zoom_x1, (GLfloat)zoom_y1 );
1541 			glVertex2f( (GLfloat)zoom_x1, (GLfloat)zoom_y2 );
1542 			glVertex2f( (GLfloat)zoom_x2, (GLfloat)zoom_y2 );
1543 			glVertex2f( (GLfloat)zoom_x2, (GLfloat)zoom_y1 );
1544 			glVertex2f( (GLfloat)zoom_x1, (GLfloat)zoom_y1 );
1545 			glEnd();
1546 		}
1547 
1548 	/*** Fill in the details here. ***/
1549 
1550   /* Swap buffers */
1551   if (gdk_gl_drawable_is_double_buffered (gldrawable))
1552     gdk_gl_drawable_swap_buffers (gldrawable);
1553   else
1554     glFlush ();
1555 
1556   gdk_gl_drawable_gl_end (gldrawable);
1557   /*** OpenGL END ***/
1558 
1559   return TRUE;
1560 }
1561 
1562 
1563 /* find the closet vertex of triangle t to
1564 	* the point (x,y)
1565 	*/
1566 static MY_INT
find_closest_point(triangle * t,MY_DOUBLE x,MY_DOUBLE y)1567 find_closest_point(triangle *t,MY_DOUBLE x,MY_DOUBLE y)
1568 {
1569 	double l0,l1,l2;
1570  if (t) {
1571    l0=LENGTH1(t->p0,x,y,M);
1572    l1=LENGTH1(t->p1,x,y,M);
1573    l2=LENGTH1(t->p2,x,y,M);
1574 			return(((l0<=l1)&&(l0<=l2)?t->p0: (l1<=l2?t->p1:t->p2)));
1575  }
1576 	return(0);
1577 }
1578 
1579 static double
distance_to_line_from_point(MY_DOUBLE x,MY_DOUBLE y,MY_INT p0,MY_INT p1)1580 distance_to_line_from_point(MY_DOUBLE x,MY_DOUBLE y, MY_INT p0, MY_INT p1)
1581 {
1582  double a,b,c;
1583  if ( p0 > M.count || p1>M.count ) {
1584 			printf("error: %d,%d > %d\n",p0,p1,M.count);
1585 		  abort();
1586  }
1587  a=My(p1,M)-My(p0,M);
1588  b=Mx(p0,M)-Mx(p1,M);
1589  c=-a*Mx(p0,M)-b*My(p0,M);
1590 
1591  if ( a==0 && b== 0) return(sqrt((x-Mx(p0,M))*(x-Mx(p0,M))+(y-My(p0,M))*(y-My(p0,M))));
1592 
1593  return(ABS((a*x+b*y+c)/sqrt(a*a+b*b)));
1594 
1595 }
1596 
1597 
1598 /* find the edge on the edge array, lying on an edge of
1599  * the triangle t, closest to point (x,y). point is inside t.
1600  * returns -1 if none found.
1601  */
1602 static MY_INT
find_closest_edge(triangle * t,MY_DOUBLE x,MY_DOUBLE y)1603 find_closest_edge(triangle *t,MY_DOUBLE x,MY_DOUBLE y)
1604 {
1605  double d1,d2,d3;
1606  /* consider each vertex of the triangle */
1607 /* check if they are on any of the edges. get the edge number */
1608  /* finally, two of these edges must have be common
1609 	* for a triangle edge to be on that edge. */
1610  if (!triangle_edge_array[t->n]
1611 		||( triangle_edge_array[t->n][0]==-1
1612 			&& triangle_edge_array[t->n][1]==-1
1613 			&& triangle_edge_array[t->n][2]==-1 )) {
1614 			 return(-1);
1615  }
1616 #ifdef DEBUG
1617  printf("triangle %d, (%d,%d,%d)\n",t->n,t->p0,t->p1,t->p2);
1618 #endif
1619 
1620 /* if we are here, there is at least one boundary edge */
1621     if (triangle_edge_array[t->n][0]==-1) {
1622 					d1=10000; /* large value */
1623      } else {
1624 #ifdef DEBUG
1625  printf("triangle edges %d,%d\n",triangle_edge_array[t->n][0],triangle_edge_array[t->n][0]);
1626 #endif
1627 
1628 			    d1=distance_to_line_from_point(x,y,
1629 						edge_array[triangle_edge_array[t->n][0]].p1,
1630 						edge_array[triangle_edge_array[t->n][0]].p2);
1631 		 }
1632      if (triangle_edge_array[t->n][1]==-1) {
1633 					d2=10000; /* large value */
1634 		 } else {
1635 #ifdef DEBUG
1636  printf("triangle edges %d,%d\n",triangle_edge_array[t->n][1],triangle_edge_array[t->n][1]);
1637 #endif
1638 			    d2=distance_to_line_from_point(x,y,
1639 						edge_array[triangle_edge_array[t->n][1]].p1,
1640 						edge_array[triangle_edge_array[t->n][1]].p2);
1641 
1642 
1643 		 }
1644      if (triangle_edge_array[t->n][2]==-1) {
1645 					d3=10000; /* large value */
1646 		 } else {
1647 #ifdef DEBUG
1648 printf("triangle edges %d,%d\n",triangle_edge_array[t->n][2],triangle_edge_array[t->n][2]);
1649 #endif
1650 			    d3=distance_to_line_from_point(x,y,
1651 						edge_array[triangle_edge_array[t->n][2]].p1,
1652 						edge_array[triangle_edge_array[t->n][2]].p2);
1653 
1654  		 }
1655 	if (d1<d2 && d1<d3) return(triangle_edge_array[t->n][0]);
1656 	if (d2<d3) return(triangle_edge_array[t->n][1]);
1657 	 return(triangle_edge_array[t->n][2]);
1658 }
1659 
1660 /***
1661  *** The "motion_notify_event" signal handler. Any processing required when
1662  *** the OpenGL-capable drawing area is under drag motion should be done here.
1663  ***/
1664 static gboolean
motion_notify_event(GtkWidget * widget,GdkEventMotion * event,gpointer data)1665 motion_notify_event (GtkWidget      *widget,
1666 		     GdkEventMotion *event,
1667 		     gpointer        data)
1668 {
1669 	GLfloat  mx,my;
1670 	point p;
1671 	DAG_node *current_dag_node;
1672   triangle *dxf_chosen_triangle;
1673 #ifdef DEBUG
1674   g_print ("%s: \"motion_notify_event\": button", gtk_widget_get_name (widget));
1675 #endif
1676 
1677 	mx=widget->allocation.width;
1678 	my=widget->allocation.height;
1679 	p.x=2*(double)event->x/(double)mx -1.0;
1680 	p.y=-2*(double)event->y/(double)my +1.0;
1681 	glGetDoublev(GL_MODELVIEW_MATRIX,current_mat);
1682 	p.x=(p.x-current_mat[12])/current_mat[0];
1683 	p.y=(p.y-current_mat[13])/current_mat[5];
1684 	current_dag_node=DAG_find(&dt,(void*)&p,(void*)&M);
1685 	if ( current_dag_node ) {
1686 		 dxf_chosen_triangle=(triangle*)current_dag_node->rec;
1687 
1688 			/* find closest vertex of this triangle */
1689    current_point_number=find_closest_point(dxf_chosen_triangle,p.x,p.y);
1690 	 /* out of the 3 edges of triangle, return the edge number
1691 		* liying on the boundary edges. boundary edge number will be returned */
1692    current_edge_number=find_closest_edge(dxf_chosen_triangle,p.x,p.y);
1693 	  gdk_window_invalidate_rect(widget->window, &widget->allocation ,FALSE);
1694   }
1695 
1696   if ( mouse_responce_flag==MENU_ZOOM_END ) {
1697 						zoom_x2 = (2*( double )event->x/( double ) mx-1.0);
1698 						zoom_y2 = -2*( double )event->y/( double ) my+1.0;
1699 
1700 						/* convert back to world coords */
1701 						glGetDoublev(GL_MODELVIEW_MATRIX,current_mat);
1702 						zoom_x2=(zoom_x2-current_mat[12])/current_mat[0];
1703 						zoom_y2=(zoom_y2-current_mat[13])/current_mat[5];
1704 						gdk_window_invalidate_rect(widget->window, &widget->allocation ,FALSE);
1705 						return(TRUE);
1706    }
1707 
1708 
1709   return FALSE;
1710 }
1711 
1712 
1713 /***
1714  *** The "button_press_event" signal handler. Any processing required when
1715  *** mouse buttons (only left and middle buttons) are pressed on the OpenGL-
1716  *** capable drawing area should be done here.
1717  ***/
1718 static gboolean
button_press_event(GtkWidget * widget,GdkEventButton * event,gpointer data)1719 button_press_event (GtkWidget      *widget,
1720 		    GdkEventButton *event,
1721 		    gpointer        data)
1722 {
1723 	GLfloat  mx,my;
1724  double temp;
1725 
1726 
1727   if (event->button == 1)
1728     {
1729       /*** Fill in the details here. ***/
1730 			if ( mouse_responce_flag==MENU_ZOOM_START) {
1731    	mx=widget->allocation.width;
1732 	   my=widget->allocation.height;
1733 
1734    /* get click point coordinates  */
1735 			zoom_x1 = (2*( double )event->x/( double ) mx-1.0);
1736 			zoom_y1 = -2*( double )event->y/( double ) my+1.0;
1737 
1738 			/* convert back to world coords */
1739 			glGetDoublev(GL_MODELVIEW_MATRIX,current_mat);
1740 			zoom_x1=(zoom_x1-current_mat[12])/current_mat[0];
1741 			zoom_y1=(zoom_y1-current_mat[13])/current_mat[5];
1742 			/* eliminate previous zoom window */
1743 			zoom_x2=zoom_x1; zoom_y2=zoom_y1;
1744 #ifdef DEBUG
1745       g_print (" zoom start %lf %lf",zoom_x1,zoom_y1);
1746 #endif
1747 
1748 			mouse_responce_flag=MENU_ZOOM_END;
1749 			return(TRUE);
1750    } else if (mouse_responce_flag==MENU_ZOOM_END) {
1751 
1752 		  /* get click point coordinates  */
1753 				mx=widget->allocation.width;
1754 				my=widget->allocation.height;
1755 
1756 				zoom_x2 = (2*( double )event->x/( double ) mx-1.0);
1757 				zoom_y2 = -2*( double )event->y/( double ) my+1.0;
1758 
1759 				/* convert back to world coords */
1760 				glGetDoublev(GL_MODELVIEW_MATRIX,current_mat);
1761 				zoom_x2=(zoom_x2-current_mat[12])/current_mat[0];
1762 				zoom_y2=(zoom_y2-current_mat[13])/current_mat[5];
1763 
1764 				if ( zoom_x1 != zoom_x2 ) {
1765 							/* first arrange points in zoom window */
1766 							if ( zoom_x1 > zoom_x2 ) {
1767 							temp=zoom_x1;
1768 							zoom_x1=zoom_x2;
1769 							zoom_x2=temp;
1770 							}
1771 							if ( zoom_y1 < zoom_y2 ) {
1772 							temp=zoom_y1;
1773 							zoom_y1=zoom_y2;
1774 							zoom_y2=temp;
1775 							}
1776     /* now keep same aspect ratio as the figure */
1777 			zoom_y2=-(double)my/(double)mx*(zoom_x2-zoom_x1)+zoom_y1;
1778    glPushMatrix();
1779 			/* first zoom all */
1780 			glLoadIdentity();
1781 			/* then do the real zoom */
1782 			glScalef(-2.0/(zoom_x1-zoom_x2),2.0/(zoom_y1-zoom_y2),1.0);
1783 			glTranslatef(-0.5*(zoom_x1+zoom_x2),-0.5*(zoom_y1+zoom_y2),0);
1784 			/* redisplay */
1785 			gdk_window_invalidate_rect(widget->window, &widget->allocation ,FALSE);
1786 			}
1787 
1788 #ifdef DEBUG
1789       g_print (" zoom end %lf %lf",zoom_x2,zoom_y2);
1790 #endif
1791 
1792 
1793 			mouse_responce_flag=MENU_ZOOM_START;
1794 			return(TRUE);
1795 			} else if (mouse_responce_flag==MENU_EDIT_POINT) {
1796 			/* this is the place where we handle editing point properties */
1797       /* only edit a valid point */
1798 	    if ((current_point_number>2) && (current_point_number< dxf_points) ) {
1799         edit_current_point_properties();
1800 			}
1801       return TRUE;
1802 			} else if (mouse_responce_flag==MENU_EDIT_EDGE) {
1803 			/* this is the place where we handle editing edge properties */
1804        if (current_edge_number!=-1) {
1805          edit_current_edge_properties();
1806        }
1807       return TRUE;
1808       } else if ( mouse_responce_flag==MENU_ADD_EDGE) {
1809 				 if ( current_edge_number!=-1
1810 						&& current_polygon ) {
1811 #ifdef DEBUG
1812       g_print ("adding edge %d to polygon with edges %d\n",current_edge_number,current_polygon->nedges);
1813 #endif
1814 				   insert_remove_from_polygon(current_polygon,current_edge_number);
1815 			   }
1816 			return(TRUE);
1817 		  }
1818 
1819 
1820       return TRUE;
1821     }
1822 
1823   return FALSE;
1824 }
1825 
1826 /* For popup menu. */
1827 static gboolean
button_press_event_popup_menu(GtkWidget * widget,GdkEventButton * event,gpointer data)1828 button_press_event_popup_menu (GtkWidget      *widget,
1829 			       GdkEventButton *event,
1830 			       gpointer        data)
1831 {
1832 
1833   if (event->button == 3)
1834     {
1835 
1836       /* Popup menu. */
1837       gtk_menu_popup (GTK_MENU (widget), NULL, NULL, NULL, NULL,
1838 		      event->button, event->time);
1839       return TRUE;
1840     }
1841 
1842 
1843   return FALSE;
1844 }
1845 
1846 
1847 static void
close_edit_window(GtkWidget * widget,gpointer data)1848 close_edit_window(GtkWidget *widget, gpointer data)
1849 {
1850 		gtk_widget_destroy(GTK_WIDGET(data));
1851 		/*gdk_window_destroy(GDK_WINDOW(widget->window)); */
1852     /* free memory */
1853     destroy_boundary_list(&blist);
1854 }
1855 
1856 static void
switch_to_zoom_start(GtkWidget * widget)1857 switch_to_zoom_start(GtkWidget *widget)
1858 {
1859 			mouse_responce_flag=MENU_ZOOM_START;
1860 }
1861 static void
switch_to_edit_point(GtkWidget * widget)1862 switch_to_edit_point(GtkWidget *widget)
1863 {
1864 			mouse_responce_flag=MENU_EDIT_POINT;
1865 }
1866 static void
switch_to_edit_edge(GtkWidget * widget)1867 switch_to_edit_edge(GtkWidget *widget)
1868 {
1869 			mouse_responce_flag=MENU_EDIT_EDGE;
1870 }
1871 static void
switch_to_edit_bound(GtkWidget * widget)1872 switch_to_edit_bound(GtkWidget *widget)
1873 {
1874 			display_boundary_edit_window();
1875 }
1876 static void
switch_to_zoom_all(GtkWidget * widget)1877 switch_to_zoom_all(GtkWidget *widget)
1878 {
1879 		glLoadIdentity();
1880 		gdk_window_invalidate_rect(widget->window, &widget->allocation ,FALSE);
1881 }
1882 static void
switch_to_zoom_back(GtkWidget * widget)1883 switch_to_zoom_back(GtkWidget *widget)
1884 {
1885 		glPopMatrix();
1886 		gdk_window_invalidate_rect(widget->window, &widget->allocation ,FALSE);
1887 }
1888 
1889 /* save as a coord file */
1890 static void
save_coord_file(GtkWidget * widget,gpointer data)1891 save_coord_file(GtkWidget *widget, gpointer data)
1892 {
1893       GtkWidget *file_selector=(GtkWidget*)data;
1894 			const gchar *tempnm;
1895 			tempnm=gtk_file_selection_get_filename(GTK_FILE_SELECTION(file_selector));
1896 			output_cord_filename=(char*)realloc((void*)output_cord_filename,sizeof(char)*(size_t)(strlen((char*)tempnm)+1));
1897 			if ( output_cord_filename == 0 ) {
1898 			fprintf(stderr,"%s: %d: no free memory",__FILE__,__LINE__);
1899 			exit(1);
1900 			}
1901 			strcpy(output_cord_filename,(char*)tempnm);
1902 #ifdef DEBUG
1903 g_print("menubar_file_open: filename %s\n",output_cord_filename);
1904 #endif
1905 
1906     /* call the true save function */
1907     write_to_output_cord_file(output_cord_filename);
1908 
1909 }
1910 
1911 static void
get_save_coord_filename(GtkWidget * widget)1912 get_save_coord_filename(GtkWidget *widget)
1913 {
1914 
1915 		GtkWidget *file_selector;
1916 		file_selector=gtk_file_selection_new("Please select a file");
1917 		g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(file_selector)->ok_button),
1918 						"clicked",
1919 						G_CALLBACK(save_coord_file),
1920 						(gpointer)file_selector);
1921 	 g_signal_connect_swapped(GTK_OBJECT(GTK_FILE_SELECTION(file_selector)->ok_button),
1922 						"clicked",
1923 						G_CALLBACK(gtk_widget_destroy),
1924 						(gpointer)file_selector);
1925 	 g_signal_connect_swapped(GTK_OBJECT(GTK_FILE_SELECTION(file_selector)->cancel_button),
1926 					"clicked",
1927 					G_CALLBACK(gtk_widget_destroy),
1928 					(gpointer)file_selector);
1929 	 gtk_widget_show(file_selector);
1930 
1931 }
1932 
1933 /***
1934  *** Creates the popup menu to be displayed.
1935  ***/
1936 static GtkWidget *
create_popup_menu(GtkWidget * drawing_area)1937 create_popup_menu (GtkWidget *drawing_area)
1938 {
1939   GtkWidget *menu;
1940   GtkWidget *menu_item;
1941 
1942   menu = gtk_menu_new ();
1943 
1944     /* edit point */
1945 	  menu_item=gtk_menu_item_new_with_label("Edit Points");
1946 		gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
1947 		g_signal_connect_swapped(G_OBJECT(menu_item),"activate",
1948 																	G_CALLBACK(switch_to_edit_point),drawing_area);
1949 		gtk_widget_show(menu_item);
1950     /* edit edge */
1951 	  menu_item=gtk_menu_item_new_with_label("Edit Edges");
1952 		gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
1953 		g_signal_connect_swapped(G_OBJECT(menu_item),"activate",
1954 																	G_CALLBACK(switch_to_edit_edge),drawing_area);
1955 		gtk_widget_show(menu_item);
1956     /* edit boundaries */
1957     menu_item=gtk_menu_item_new_with_label("Edit Boundaries");
1958 		gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
1959 		g_signal_connect_swapped(G_OBJECT(menu_item),"activate",
1960 																	G_CALLBACK(switch_to_edit_bound),drawing_area);
1961 		gtk_widget_show(menu_item);
1962 
1963 
1964 		/* Zooming */
1965 		menu_item=gtk_menu_item_new_with_label("Zoom Window");
1966 		gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
1967 		g_signal_connect_swapped(G_OBJECT(menu_item),"activate",
1968 																	G_CALLBACK(switch_to_zoom_start),drawing_area);
1969 		gtk_widget_show(menu_item);
1970 
1971   menu_item=gtk_menu_item_new_with_label("Zoom Back");
1972 		gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
1973 		g_signal_connect_swapped(G_OBJECT(menu_item),"activate",
1974 																	G_CALLBACK(switch_to_zoom_back),drawing_area);
1975 		gtk_widget_show(menu_item);
1976 
1977 		menu_item=gtk_menu_item_new_with_label("Zoom All");
1978 		gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
1979 		g_signal_connect_swapped(G_OBJECT(menu_item),"activate",
1980 																	G_CALLBACK(switch_to_zoom_all),drawing_area);
1981 		gtk_widget_show(menu_item);
1982 
1983   /* Save as coord file */
1984     menu_item=gtk_menu_item_new_with_label("Save");
1985 		gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
1986 		g_signal_connect_swapped(G_OBJECT(menu_item),"activate",
1987 																	G_CALLBACK(get_save_coord_filename),drawing_area);
1988 		gtk_widget_show(menu_item);
1989 
1990 
1991   /* Quit */
1992   menu_item = gtk_menu_item_new_with_label ("Close");
1993   gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
1994   g_signal_connect (G_OBJECT (menu_item), "activate",
1995 		    G_CALLBACK (close_edit_window), drawing_area->parent->parent);
1996   gtk_widget_show (menu_item);
1997 
1998   return menu;
1999 }
2000 
2001 /***
2002  *** Creates the simple application window with one
2003  *** drawing area that has an OpenGL-capable visual.
2004  ***/
2005 static GtkWidget *
create_edit_window(GdkGLConfig * glconfig,const char * title)2006 create_edit_window (GdkGLConfig *glconfig, const char *title)
2007 {
2008   GtkWidget *window;
2009   GtkWidget *vbox;
2010   GtkWidget *drawing_area;
2011   GtkWidget *menu;
2012 
2013   /*
2014    * Top-level window.
2015    */
2016 
2017   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2018   gtk_window_set_title (GTK_WINDOW (window), title);
2019 
2020   /* Get automatically redrawn if any of their children changed allocation. */
2021   gtk_container_set_reallocate_redraws (GTK_CONTAINER (window), TRUE);
2022 
2023   /* Connect signal handlers to the window */
2024   g_signal_connect (G_OBJECT (window), "delete_event",
2025 		    G_CALLBACK (gtk_main_quit), NULL);
2026 
2027   /*
2028    * VBox.
2029    */
2030 
2031   vbox = gtk_vbox_new (FALSE, 0);
2032   gtk_container_add (GTK_CONTAINER (window), vbox);
2033   gtk_widget_show (vbox);
2034 
2035   /*
2036    * Drawing area to draw OpenGL scene.
2037    */
2038 
2039   drawing_area = gtk_drawing_area_new ();
2040   gtk_widget_set_size_request (drawing_area, DEFAULT_WIDTH, DEFAULT_HEIGHT);
2041 
2042   /* Set OpenGL-capability to the widget */
2043   gtk_widget_set_gl_capability (drawing_area,
2044 				glconfig,
2045 				NULL,
2046 				TRUE,
2047 				GDK_GL_RGBA_TYPE);
2048 
2049   gtk_widget_add_events (drawing_area,
2050 			 GDK_BUTTON1_MOTION_MASK    |
2051 			 GDK_BUTTON2_MOTION_MASK    |
2052 			 GDK_BUTTON_PRESS_MASK      |
2053 			 GDK_POINTER_MOTION_MASK    |  /* any pointer motion */
2054 			 GDK_VISIBILITY_NOTIFY_MASK);
2055 
2056   /* Connect signal handlers to the drawing area */
2057   g_signal_connect_after (G_OBJECT (drawing_area), "realize",
2058                           G_CALLBACK (realize), NULL);
2059   g_signal_connect (G_OBJECT (drawing_area), "configure_event",
2060 		    G_CALLBACK (configure_event), NULL);
2061   g_signal_connect (G_OBJECT (drawing_area), "expose_event",
2062 		    G_CALLBACK (expose_event), NULL);
2063  /* g_signal_connect (G_OBJECT (drawing_area), "unrealize",
2064 		    G_CALLBACK (unrealize), NULL); */
2065 
2066   g_signal_connect (G_OBJECT (drawing_area), "motion_notify_event",
2067 		    G_CALLBACK (motion_notify_event), NULL);
2068   g_signal_connect (G_OBJECT (drawing_area), "button_press_event",
2069 		    G_CALLBACK (button_press_event), NULL);
2070 
2071 
2072   gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
2073 
2074   gtk_widget_show (drawing_area);
2075 
2076   /*
2077    * Popup menu.
2078    */
2079 
2080   menu = create_popup_menu (drawing_area);
2081 
2082   g_signal_connect_swapped (G_OBJECT (drawing_area), "button_press_event",
2083 			    G_CALLBACK (button_press_event_popup_menu), menu);
2084 
2085   return window;
2086 }
2087 
2088 
2089 
2090 /***
2091  *** Configure the OpenGL framebuffer.
2092  ***/
2093 static GdkGLConfig *
configure_edit_window(void)2094 configure_edit_window (void)
2095 {
2096   GdkGLConfig *glconfig;
2097 
2098   /* Try double-buffered visual */
2099   glconfig = gdk_gl_config_new_by_mode (GDK_GL_MODE_RGB    |
2100 					GDK_GL_MODE_DEPTH  |
2101 					GDK_GL_MODE_DOUBLE);
2102   if (glconfig == NULL)
2103     {
2104       g_print ("\n*** Cannot find the double-buffered visual.\n");
2105       g_print ("\n*** Trying single-buffered visual.\n");
2106 
2107       /* Try single-buffered visual */
2108       glconfig = gdk_gl_config_new_by_mode (GDK_GL_MODE_RGB   |
2109 					    GDK_GL_MODE_DEPTH);
2110       if (glconfig == NULL)
2111 	{
2112 	  g_print ("*** No appropriate OpenGL-capable visual found.\n");
2113 	  exit (1);
2114 	}
2115     }
2116 
2117   return glconfig;
2118 }
2119 
2120 
2121 /* display edit window */
2122 void
display_edit_window(const char * title)2123 display_edit_window( const char *title)
2124 {
2125 				    GtkWidget *window;
2126 						GdkGLConfig *glconfig;
2127 
2128 						glconfig=configure_edit_window();
2129 						window=create_edit_window(glconfig,title);
2130 
2131 						gtk_widget_show(window);
2132 
2133 						/* display dialog on to proceed with
2134 						 * defining point/edge proporties */
2135 				generic_dialog("DXF file has been sucessfully read!!.\nNow you must define properties of all Points,\nEdges  and Boundaries in the DXF file.","Next Step");
2136 
2137 }
2138 
2139 
2140 /* generic dialog */
2141 void
generic_dialog(const gchar * msg,const gchar * title)2142 generic_dialog(const gchar *msg,const gchar *title)
2143 {
2144 	GtkWidget *dialog,*label;
2145 	dialog=gtk_dialog_new_with_buttons(title,
2146 						  NULL,
2147 							GTK_DIALOG_MODAL,
2148 							GTK_STOCK_OK,
2149 							GTK_RESPONSE_NONE,
2150 							NULL);
2151    label=gtk_label_new(msg);
2152 	 g_signal_connect_swapped(GTK_OBJECT(dialog),
2153 									 "response",
2154 									 G_CALLBACK(gtk_widget_destroy),
2155 									 GTK_OBJECT(dialog));
2156 	gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox),
2157 										                      label);
2158  gtk_widget_show_all(dialog);
2159 
2160 }
2161 
2162 #endif /*WIN32 */
2163