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