1 /* gtkplotsurface - 3d scientific plots widget for gtk+
2 * Copyright 1999-2001 Adrian E. Feiguin <feiguin@ifir.edu.ar>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 */
19
20 /**
21 * SECTION: gtkplotsurface
22 * @short_description:
23 *
24 * FIXME:: need long description
25 */
26
27
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <math.h>
32 #include <gtk/gtk.h>
33 #include "gtkplot.h"
34 #include "gtkplot3d.h"
35 #include "gtkplotdata.h"
36 #include "gtkplotsurface.h"
37 #include "gtkpsfont.h"
38 #include "gtkplotpc.h"
39
40 #define P_(string) string
41
42 static void gtk_plot_surface_class_init (GtkPlotSurfaceClass *klass);
43 static void gtk_plot_surface_init (GtkPlotSurface *data);
44 static void gtk_plot_surface_destroy (GtkObject *object);
45 static void gtk_plot_surface_get_property (GObject *object,
46 guint prop_id,
47 GValue *value,
48 GParamSpec *pspec);
49 static void gtk_plot_surface_set_property (GObject *object,
50 guint prop_id,
51 const GValue *value,
52 GParamSpec *pspec);
53 static void gtk_plot_surface_clone (GtkPlotData *data,
54 GtkPlotData *copy);
55 static void gtk_plot_surface_update_range (GtkPlotData *data);
56 static void gtk_plot_surface_real_build_mesh (GtkPlotSurface *surface);
57 static void gtk_plot_surface_build_polygons (GtkPlotSurface *surface);
58 static void gtk_plot_surface_sort_polygons (GtkPlotSurface *surface);
59 static void update_data (GtkPlotData *data,
60 gboolean new_range);
61 static gboolean gtk_plot_surface_add_to_plot (GtkPlotData *data,
62 GtkPlot *plot);
63 static void gtk_plot_surface_draw_private (GtkPlotData *data);
64 static void gtk_plot_surface_draw_legend (GtkPlotData *data,
65 gint x, gint y);
66 static void gtk_plot_surface_get_legend_size (GtkPlotData *data,
67 gint *width, gint *height);
68 static void gtk_plot_surface_draw_polygons (GtkPlotSurface *surface);
69 static void gtk_plot_surface_lighting (GdkColor *a,
70 GdkColor *b,
71 gdouble normal,
72 gdouble ambient);
73 static void clear_polygons (GtkPlotSurface *surface);
74 extern gint roundint (gdouble x);
75 static void hsv_to_rgb (gdouble h,
76 gdouble s,
77 gdouble v,
78 gdouble *r,
79 gdouble *g,
80 gdouble *b);
81 static void rgb_to_hsv (gdouble r,
82 gdouble g,
83 gdouble b,
84 gdouble *h,
85 gdouble *s,
86 gdouble *v);
87 static gint compare_func (gpointer a, gpointer b);
88
89 enum {
90 ARG_0,
91 ARG_USE_HEIGHT,
92 ARG_USE_AMPLITUD,
93 ARG_LIGHT,
94 ARG_AMBIENT,
95 ARG_NX,
96 ARG_NY,
97 ARG_SHOW_GRID,
98 ARG_SHOW_MESH,
99 ARG_TRANSPARENT,
100 ARG_XSTEP,
101 ARG_YSTEP,
102 ARG_MESH_STYLE,
103 ARG_MESH_WIDTH,
104 ARG_MESH_COLOR,
105 };
106
107 static GtkPlotDataClass *parent_class = NULL;
108
109 /* "stolen" from 3dgpl */
_sqrt(register gulong arg)110 gulong _sqrt(register gulong arg)
111 {
112 register gint i;
113 register gulong nprd,msk=0x8000L,val=0,prd=0;
114
115 for(i=15;i>=0;i--){
116 nprd = prd + (val<<(i+1))+(msk<<i);
117 if(nprd <= arg) { val |= msk; prd = nprd; }
118 msk >>= 1;
119 }
120 return val;
121 }
122
123 GType
gtk_plot_surface_get_type(void)124 gtk_plot_surface_get_type (void)
125 {
126 static GType data_type = 0;
127
128 if (!data_type)
129 {
130 data_type = g_type_register_static_simple (
131 gtk_plot_data_get_type(),
132 "GtkPlotSurface",
133 sizeof (GtkPlotSurfaceClass),
134 (GClassInitFunc) gtk_plot_surface_class_init,
135 sizeof (GtkPlotSurface),
136 (GInstanceInitFunc) gtk_plot_surface_init,
137 0);
138 }
139 return data_type;
140 }
141
142 static void
gtk_plot_surface_class_init(GtkPlotSurfaceClass * klass)143 gtk_plot_surface_class_init (GtkPlotSurfaceClass *klass)
144 {
145 GtkObjectClass *object_class;
146 GtkWidgetClass *widget_class;
147 GtkPlotDataClass *data_class;
148 GtkPlotSurfaceClass *surface_class;
149 GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
150
151 parent_class = g_type_class_ref (gtk_plot_data_get_type ());
152
153 object_class = (GtkObjectClass *) klass;
154 widget_class = (GtkWidgetClass *) klass;
155 data_class = (GtkPlotDataClass *) klass;
156 surface_class = (GtkPlotSurfaceClass *) klass;
157
158 object_class->destroy = gtk_plot_surface_destroy;
159
160 gobject_class->set_property = gtk_plot_surface_set_property;
161 gobject_class->get_property = gtk_plot_surface_get_property;
162
163
164 /**
165 * GtkPlotSurface:use_height:
166 *
167 *
168 **/
169 g_object_class_install_property (gobject_class,
170 ARG_USE_HEIGHT,
171 g_param_spec_boolean ("use_height",
172 P_(""),
173 P_(""),
174 TRUE,
175 G_PARAM_READABLE|G_PARAM_WRITABLE));
176 /**
177 * GtkPlotSurface:use_amplitud:
178 *
179 *
180 **/
181 g_object_class_install_property (gobject_class,
182 ARG_USE_AMPLITUD,
183 g_param_spec_boolean ("use_amplitud",
184 P_(""),
185 P_(""),
186 FALSE,
187 G_PARAM_READABLE|G_PARAM_WRITABLE));
188
189 /**
190 * GtkPlotSurface:vector_light:
191 *
192 *
193 **/
194 g_object_class_install_property (gobject_class,
195 ARG_LIGHT,
196 g_param_spec_pointer ("vector_light",
197 P_(""),
198 P_(""),
199 G_PARAM_READABLE|G_PARAM_WRITABLE));
200
201 /**
202 * GtkPlotSurface:ambient:
203 *
204 *
205 **/
206 g_object_class_install_property (gobject_class,
207 ARG_AMBIENT,
208 g_param_spec_double ("ambient",
209 P_(""),
210 P_(""),
211 0,G_MAXDOUBLE,0.0,
212 G_PARAM_READABLE|G_PARAM_WRITABLE));
213
214 /**
215 * GtkPlotSurface:nx:
216 *
217 *
218 **/
219 g_object_class_install_property (gobject_class,
220 ARG_NX,
221 g_param_spec_int ("nx",
222 P_(""),
223 P_(""),
224 0,G_MAXINT,0,
225 G_PARAM_READABLE|G_PARAM_WRITABLE));
226
227 /**
228 * GtkPlotSurface:ny:
229 *
230 *
231 **/
232 g_object_class_install_property (gobject_class,
233 ARG_NY,
234 g_param_spec_int ("ny",
235 P_(""),
236 P_(""),
237 0,G_MAXINT,0,
238 G_PARAM_READABLE|G_PARAM_WRITABLE));
239
240 /**
241 * GtkPlotSurface:show_grid:
242 *
243 *
244 **/
245 g_object_class_install_property (gobject_class,
246 ARG_SHOW_GRID,
247 g_param_spec_boolean ("show_grid",
248 P_(""),
249 P_(""),
250 FALSE,
251 G_PARAM_READABLE|G_PARAM_WRITABLE));
252
253 /**
254 * GtkPlotSurface:show_mesh:
255 *
256 *
257 **/
258 g_object_class_install_property (gobject_class,
259 ARG_SHOW_MESH,
260 g_param_spec_boolean ("show_mesh",
261 P_(""),
262 P_(""),
263 FALSE,
264 G_PARAM_READABLE|G_PARAM_WRITABLE));
265
266 /**
267 * GtkPlotSurface:transparent:
268 *
269 *
270 **/
271 g_object_class_install_property (gobject_class,
272 ARG_TRANSPARENT,
273 g_param_spec_boolean ("transparent",
274 P_(""),
275 P_(""),
276 FALSE,
277 G_PARAM_READABLE|G_PARAM_WRITABLE));
278
279 /**
280 * GtkPlotSurface:xstep:
281 *
282 *
283 **/
284 g_object_class_install_property (gobject_class,
285 ARG_XSTEP,
286 g_param_spec_double ("xstep",
287 P_(""),
288 P_(""),
289 0,G_MAXDOUBLE,0.0,
290 G_PARAM_READABLE|G_PARAM_WRITABLE));
291
292 /**
293 * GtkPlotSurface:ystep:
294 *
295 *
296 **/
297 g_object_class_install_property (gobject_class,
298 ARG_YSTEP,
299 g_param_spec_double ("ystep",
300 P_(""),
301 P_(""),
302 0,G_MAXDOUBLE,0.0,
303 G_PARAM_READABLE|G_PARAM_WRITABLE));
304
305 /**
306 * GtkPlotSurface:mesh_style:
307 *
308 *
309 **/
310 g_object_class_install_property (gobject_class,
311 ARG_MESH_STYLE,
312 g_param_spec_int ("mesh_style",
313 P_(""),
314 P_(""),
315 0,G_MAXINT,0,
316 G_PARAM_READABLE|G_PARAM_WRITABLE));
317
318 /**
319 * GtkPlotSurface:mesh_width:
320 *
321 *
322 **/
323 g_object_class_install_property (gobject_class,
324 ARG_MESH_WIDTH,
325 g_param_spec_double ("mesh_width",
326 P_(""),
327 P_(""),
328 0,G_MAXDOUBLE,0.0,
329 G_PARAM_READABLE|G_PARAM_WRITABLE));
330
331 /**
332 * GtkPlotSurface:mesh_color:
333 *
334 *
335 **/
336 g_object_class_install_property (gobject_class,
337 ARG_MESH_COLOR,
338 g_param_spec_pointer ("mesh_color",
339 P_(""),
340 P_(""),
341 G_PARAM_READABLE|G_PARAM_WRITABLE));
342
343 data_class->clone = gtk_plot_surface_clone;
344 data_class->update = update_data;
345 data_class->add_to_plot = gtk_plot_surface_add_to_plot;
346 data_class->draw_data = gtk_plot_surface_draw_private;
347 data_class->draw_legend = gtk_plot_surface_draw_legend;
348 data_class->get_legend_size = gtk_plot_surface_get_legend_size;
349 surface_class->draw_polygons = gtk_plot_surface_draw_polygons;
350 surface_class->build_polygons = gtk_plot_surface_build_polygons;
351 surface_class->sort_polygons = gtk_plot_surface_sort_polygons;
352
353 }
354
355 static void
gtk_plot_surface_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)356 gtk_plot_surface_set_property (GObject *object,
357 guint prop_id,
358 const GValue *value,
359 GParamSpec *pspec)
360 {
361 GtkPlotSurface *data;
362
363 data = GTK_PLOT_SURFACE (object);
364
365 switch (prop_id)
366 {
367 case ARG_USE_HEIGHT:
368 data->use_height_gradient = g_value_get_boolean(value);
369 break;
370 case ARG_USE_AMPLITUD:
371 data->use_amplitud = g_value_get_boolean(value);
372 break;
373 case ARG_LIGHT:
374 data->light = *((GtkPlotVector *)g_value_get_pointer(value));
375 break;
376 case ARG_AMBIENT:
377 data->ambient = g_value_get_double(value);
378 break;
379 case ARG_NX:
380 data->nx = g_value_get_int(value);
381 break;
382 case ARG_NY:
383 data->ny = g_value_get_int(value);
384 break;
385 case ARG_SHOW_GRID:
386 data->show_grid = g_value_get_boolean(value);
387 break;
388 case ARG_SHOW_MESH:
389 data->show_mesh = g_value_get_boolean(value);
390 break;
391 case ARG_TRANSPARENT:
392 data->transparent = g_value_get_boolean(value);
393 break;
394 case ARG_XSTEP:
395 data->xstep = g_value_get_double(value);
396 break;
397 case ARG_YSTEP:
398 data->ystep = g_value_get_double(value);
399 break;
400 case ARG_MESH_STYLE:
401 data->mesh_line.line_style = g_value_get_int(value);
402 break;
403 case ARG_MESH_WIDTH:
404 data->mesh_line.line_width = g_value_get_double(value);
405 break;
406 case ARG_MESH_COLOR:
407 data->mesh_line.color = *((GdkColor *)g_value_get_pointer(value));
408 break;
409 }
410 }
411
412 static void
gtk_plot_surface_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)413 gtk_plot_surface_get_property (GObject *object,
414 guint prop_id,
415 GValue *value,
416 GParamSpec *pspec)
417 {
418 GtkPlotSurface *data;
419
420 data = GTK_PLOT_SURFACE (object);
421
422 switch (prop_id)
423 {
424 case ARG_USE_HEIGHT:
425 g_value_set_boolean(value, data->use_height_gradient);
426 break;
427 case ARG_USE_AMPLITUD:
428 g_value_set_boolean(value, data->use_amplitud);
429 break;
430 case ARG_LIGHT:
431 g_value_set_pointer(value, &data->light);
432 break;
433 case ARG_AMBIENT:
434 g_value_set_double(value, data->ambient);
435 break;
436 case ARG_NX:
437 g_value_set_int(value, data->nx);
438 break;
439 case ARG_NY:
440 g_value_set_int(value, data->ny);
441 break;
442 case ARG_SHOW_GRID:
443 g_value_set_boolean(value, data->show_grid);
444 break;
445 case ARG_SHOW_MESH:
446 g_value_set_boolean(value, data->show_mesh);
447 break;
448 case ARG_TRANSPARENT:
449 g_value_set_boolean(value, data->transparent);
450 break;
451 case ARG_XSTEP:
452 g_value_set_double(value, data->xstep);
453 break;
454 case ARG_YSTEP:
455 g_value_set_double(value, data->ystep);
456 break;
457 case ARG_MESH_STYLE:
458 g_value_set_int(value, data->mesh_line.line_style);
459 break;
460 case ARG_MESH_WIDTH:
461 g_value_set_double(value, data->mesh_line.line_width);
462 break;
463 case ARG_MESH_COLOR:
464 g_value_set_pointer(value, &data->mesh_line.color);
465 break;
466 default:
467 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
468 break;
469 }
470 }
471
472 static void
update_data(GtkPlotData * data,gboolean new_range)473 update_data (GtkPlotData *data, gboolean new_range)
474 {
475 if(new_range && data->is_function)
476 GTK_PLOT_SURFACE(data)->recalc_dt = TRUE;
477
478 GTK_PLOT_DATA_CLASS(parent_class)->update(data, new_range);
479 }
480
481 static void
gtk_plot_surface_update_range(GtkPlotData * data)482 gtk_plot_surface_update_range (GtkPlotData *data)
483 {
484 GtkPlotSurface *surface;
485 GtkPlot *plot;
486
487 if(!data->redraw_pending) return;
488
489 surface = GTK_PLOT_SURFACE(data);
490 plot = data->plot;
491
492
493 if(!surface->recalc_dt && data->num_points > 0){
494 gtk_plot_surface_recalc_nodes(surface);
495 data->redraw_pending = FALSE;
496 surface->recalc_dt = FALSE;
497 return;
498 }
499
500 if(!data->is_function && data->num_points > 0){
501 if(surface->recalc_dt)
502 gtk_plot_surface_build_mesh(surface);
503 else
504 gtk_plot_surface_recalc_nodes(surface);
505
506 data->redraw_pending = FALSE;
507 surface->recalc_dt = FALSE;
508 return;
509 }
510
511 if(data->is_function){
512 gdouble xstep, ystep;
513 gdouble xmin, xmax, ymin, ymax;
514 gdouble x, y;
515 gdouble *fx = NULL, *fy = NULL, *fz = NULL;
516 gint nx, ny;
517 gint npoints;
518
519 xmin = GTK_PLOT(plot)->xmin;
520 xmax = GTK_PLOT(plot)->xmax;
521 ymin = GTK_PLOT(plot)->ymin;
522 ymax = GTK_PLOT(plot)->ymax;
523
524 xstep = surface->xstep;
525 surface->nx = roundint((xmax - xmin) / xstep) + 1;
526
527 ystep = surface->ystep;
528 surface->ny = roundint((ymax - ymin) / ystep) + 1;
529
530 npoints = surface->nx * surface->ny;
531 fx = (gdouble *)g_malloc((npoints + 1) * sizeof(gdouble));
532 fy = (gdouble *)g_malloc((npoints + 1) * sizeof(gdouble));
533 fz = (gdouble *)g_malloc((npoints + 1) * sizeof(gdouble));
534
535 npoints = 0;
536 y = ymin;
537 for(ny = 0; ny < surface->ny; ny++)
538 {
539 x = xmin;
540 for(nx = 0; nx < surface->nx; nx++)
541 {
542 gboolean error;
543 fx[npoints] = x;
544 fy[npoints] = y;
545 fz[npoints] = data->function3d(plot, data, x, y, &error);
546
547 x += xstep;
548 npoints++;
549 }
550 y += ystep;
551 }
552
553 gtk_plot_data_set_x(GTK_PLOT_DATA(surface), fx);
554 gtk_plot_data_set_y(GTK_PLOT_DATA(surface), fy);
555 gtk_plot_data_set_z(GTK_PLOT_DATA(surface), fz);
556 gtk_plot_data_set_numpoints(GTK_PLOT_DATA(surface), npoints);
557
558 gtk_plot_surface_build_mesh(surface);
559
560 g_free(fx);
561 g_free(fy);
562 g_free(fz);
563 }
564
565 data->redraw_pending = FALSE;
566 surface->recalc_dt = FALSE;
567 }
568
569 static gboolean
gtk_plot_surface_add_to_plot(GtkPlotData * data,GtkPlot * plot)570 gtk_plot_surface_add_to_plot (GtkPlotData *data, GtkPlot *plot)
571 {
572 if(!data->is_function && data->num_points > 0){
573 gtk_plot_surface_build_mesh(GTK_PLOT_SURFACE(data));
574 }
575
576 data->redraw_pending = TRUE;
577
578 return TRUE;
579 }
580
581 static void
gtk_plot_surface_init(GtkPlotSurface * dataset)582 gtk_plot_surface_init (GtkPlotSurface *dataset)
583 {
584 GtkWidget *widget;
585 GdkColormap *colormap;
586 GdkColor color;
587 GtkPlotArray *dim;
588
589 gtk_widget_set_has_window(GTK_WIDGET(dataset), FALSE);
590
591 widget = GTK_WIDGET(dataset);
592 colormap = gtk_widget_get_colormap(widget);
593
594 gdk_color_parse("black", &color);
595 gdk_color_alloc(colormap, &color);
596 dataset->grid_foreground = color;
597
598 gdk_color_parse("dark green", &color);
599 gdk_color_alloc(colormap, &color);
600 dataset->grid_background = color;
601
602 gdk_color_parse("gray30", &color);
603 gdk_color_alloc(colormap, &color);
604 dataset->shadow = color;
605
606 gdk_color_parse("blue", &color);
607 gdk_color_alloc(colormap, &color);
608 dataset->color = color;
609
610 dataset->light.x = 0.;
611 dataset->light.y = 0.;
612 dataset->light.z = 1.;
613
614 dataset->nx = 0;
615 dataset->ny = 0;
616
617 dataset->show_grid = TRUE;
618 dataset->show_mesh = FALSE;
619 dataset->transparent = FALSE;
620 dataset->use_height_gradient = FALSE;
621 dataset->use_amplitud = FALSE;
622
623 dataset->ambient = 0.3;
624
625 dataset->xstep = 0.05;
626 dataset->ystep = 0.05;
627
628 dataset->mesh_line.color = dataset->grid_foreground;
629 dataset->mesh_line.line_width = 1;
630 dataset->mesh_line.line_style = GTK_PLOT_LINE_SOLID;
631
632 dataset->dt = GTK_PLOT_DT(gtk_plot_dt_new(0));
633 dataset->dt->quadrilateral = FALSE;
634 dataset->recalc_dt = TRUE;
635
636 dataset->polygons = NULL;
637
638 dim = gtk_plot_data_find_dimension(GTK_PLOT_DATA(dataset), "y");
639 gtk_plot_array_set_independent(dim, TRUE);
640 dim = gtk_plot_data_find_dimension(GTK_PLOT_DATA(dataset), "z");
641 gtk_plot_array_set_required(dim, TRUE);
642 }
643
644 GtkWidget*
gtk_plot_surface_new(void)645 gtk_plot_surface_new (void)
646 {
647 GtkPlotData *data;
648
649 data = g_object_new (gtk_plot_surface_get_type (), NULL);
650
651 return GTK_WIDGET (data);
652 }
653
654 /**
655 * gtk_plot_surface_new_function:
656 * @function: (scope async): a #GtkPlotFunc3D
657 *
658 * Return value: (transfer full) the constructed #GtkWidget
659 */
660 GtkWidget*
gtk_plot_surface_new_function(GtkPlotFunc3D function)661 gtk_plot_surface_new_function (GtkPlotFunc3D function)
662 {
663 GtkWidget *dataset;
664
665 dataset = g_object_new (gtk_plot_surface_get_type (), NULL);
666
667 gtk_plot_surface_construct_function(GTK_PLOT_SURFACE(dataset), function);
668
669 return dataset;
670 }
671
672 /**
673 * gtk_plot_surface_construct_function:
674 * @surface:
675 * @function: (scope async): a #GtkPlotFunc3D
676 */
677 void
gtk_plot_surface_construct_function(GtkPlotSurface * surface,GtkPlotFunc3D function)678 gtk_plot_surface_construct_function(GtkPlotSurface *surface,
679 GtkPlotFunc3D function)
680 {
681 GTK_PLOT_DATA(surface)->is_function = TRUE;
682 GTK_PLOT_DATA(surface)->function3d = function;
683 }
684
685 /**
686 * gtk_plot_surface_destroy:
687 * @object:
688 *
689 *
690 */
691 void
gtk_plot_surface_destroy(GtkObject * object)692 gtk_plot_surface_destroy(GtkObject *object)
693 {
694 GtkPlotSurface *surface;
695
696 surface = GTK_PLOT_SURFACE(object);
697
698 if(surface->dt){
699 gtk_object_destroy(GTK_OBJECT(surface->dt));
700 surface->dt = NULL;
701 }
702
703 clear_polygons(surface);
704
705 if ( GTK_OBJECT_CLASS (parent_class)->destroy )
706 (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
707 }
708
709 static void
clear_polygons(GtkPlotSurface * surface)710 clear_polygons(GtkPlotSurface *surface)
711 {
712 if(surface->polygons){
713 GList *list;
714 for (list = surface->polygons; list; list = list->next)
715 if (list->data) g_free(list->data);
716 g_list_free(surface->polygons);
717 surface->polygons= NULL;
718 }
719 }
720
721 static void
gtk_plot_surface_clone(GtkPlotData * real_data,GtkPlotData * copy_data)722 gtk_plot_surface_clone(GtkPlotData *real_data, GtkPlotData *copy_data)
723 {
724 GTK_PLOT_DATA_CLASS(parent_class)->clone(real_data, copy_data);
725
726
727 GTK_PLOT_SURFACE(copy_data)->color = GTK_PLOT_SURFACE(real_data)->color;
728 GTK_PLOT_SURFACE(copy_data)->shadow = GTK_PLOT_SURFACE(real_data)->shadow;
729 GTK_PLOT_SURFACE(copy_data)->grid_foreground = GTK_PLOT_SURFACE(real_data)->grid_foreground;
730 GTK_PLOT_SURFACE(copy_data)->grid_background = GTK_PLOT_SURFACE(real_data)->grid_background;
731
732 GTK_PLOT_SURFACE(copy_data)->use_height_gradient = GTK_PLOT_SURFACE(real_data)->use_height_gradient;
733 GTK_PLOT_SURFACE(copy_data)->use_amplitud = GTK_PLOT_SURFACE(real_data)->use_amplitud;
734
735 GTK_PLOT_SURFACE(copy_data)->light = GTK_PLOT_SURFACE(real_data)->light;
736 GTK_PLOT_SURFACE(copy_data)->ambient = GTK_PLOT_SURFACE(real_data)->ambient;
737
738 GTK_PLOT_SURFACE(copy_data)->nx = GTK_PLOT_SURFACE(real_data)->nx;
739 GTK_PLOT_SURFACE(copy_data)->ny = GTK_PLOT_SURFACE(real_data)->ny;
740
741 GTK_PLOT_SURFACE(copy_data)->show_grid = GTK_PLOT_SURFACE(real_data)->show_grid;
742 GTK_PLOT_SURFACE(copy_data)->show_mesh = GTK_PLOT_SURFACE(real_data)->show_mesh;
743 GTK_PLOT_SURFACE(copy_data)->transparent = GTK_PLOT_SURFACE(real_data)->transparent;
744
745 GTK_PLOT_SURFACE(copy_data)->xstep = GTK_PLOT_SURFACE(real_data)->xstep;
746 GTK_PLOT_SURFACE(copy_data)->ystep = GTK_PLOT_SURFACE(real_data)->ystep;
747
748 GTK_PLOT_SURFACE(copy_data)->mesh_line = GTK_PLOT_SURFACE(real_data)->mesh_line;
749 }
750
751
752 static void
gtk_plot_surface_draw_private(GtkPlotData * data)753 gtk_plot_surface_draw_private (GtkPlotData *data)
754 {
755 GtkPlot *plot;
756 GtkPlotSurface *surface;
757
758 g_return_if_fail(GTK_IS_PLOT_SURFACE(data));
759
760 surface = GTK_PLOT_SURFACE(data);
761 data = GTK_PLOT_DATA(surface);
762
763 g_return_if_fail(GTK_PLOT_DATA(data)->plot != NULL);
764 g_return_if_fail(GTK_IS_PLOT(GTK_PLOT_DATA(data)->plot));
765 if(!gtk_widget_get_visible(GTK_WIDGET(data))) return;
766
767 plot = GTK_PLOT(data->plot);
768
769 g_return_if_fail(GTK_PLOT_DATA(data)->plot != NULL);
770 g_return_if_fail(GTK_IS_PLOT(GTK_PLOT_DATA(data)->plot));
771
772 if(data->redraw_pending) gtk_plot_surface_update_range(data);
773
774 gtk_plot_pc_gsave(plot->pc);
775 GTK_PLOT_SURFACE_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(surface)))->draw_polygons(surface);
776 gtk_plot_pc_grestore(plot->pc);
777 }
778
779 static void
gtk_plot_surface_draw_polygons(GtkPlotSurface * surface)780 gtk_plot_surface_draw_polygons (GtkPlotSurface *surface)
781 {
782 GtkPlot *plot;
783 GtkPlotData *data;
784 GtkPlotPoint t[3];
785 GtkPlotDTtriangle *triangle;
786 GdkDrawable *drawable;
787 gboolean visible = TRUE;
788 GtkPlotVector side1, side2, light, normal;
789 GdkColor color, real_color;
790 GtkPlotVector points[3];
791 gdouble factor, norm;
792 GList *list;
793 gboolean color_set = FALSE;
794 gdouble *array_a;
795 gint n;
796
797 data = GTK_PLOT_DATA(surface);
798 plot = GTK_PLOT(data->plot);
799 drawable = plot->drawable;
800
801 gtk_plot_set_line_attributes(plot, surface->mesh_line);
802 array_a = gtk_plot_data_get_a(GTK_PLOT_DATA(surface), &n);
803
804 list = surface->polygons;
805 while(list){
806 GtkPlotPolygon *poly = (GtkPlotPolygon *)list->data;
807
808 triangle = poly->t;
809 visible = TRUE;
810
811 t[0].x = poly->p[0].x;
812 t[0].y = poly->p[0].y;
813 t[1].x = poly->p[1].x;
814 t[1].y = poly->p[1].y;
815 t[2].x = poly->p[2].x;
816 t[2].y = poly->p[2].y;
817
818 points[0].x = triangle->na->x;
819 points[0].y = triangle->na->y;
820 points[0].z = triangle->na->z;
821 points[1].x = triangle->nb->x;
822 points[1].y = triangle->nb->y;
823 points[1].z = triangle->nb->z;
824 points[2].x = triangle->nc->x;
825 points[2].y = triangle->nc->y;
826 points[2].z = triangle->nc->z;
827
828 if(plot->clip_data){
829 gboolean discard = FALSE;
830 gint i;
831 if(GTK_IS_PLOT3D(plot)){
832 GtkPlot3D *plot3d = GTK_PLOT3D(plot);
833 for(i = 0; i < 3; i++){
834 if(points[i].x < plot3d->ax->ticks.min || points[i].x > plot3d->ax->ticks.max ||
835 points[i].y < plot3d->ay->ticks.min || points[i].y > plot3d->ay->ticks.max ||
836 points[i].z < plot3d->az->ticks.min || points[i].z > plot3d->az->ticks.max)
837 { discard = TRUE; break; }
838 }
839 } else {
840 for(i = 0; i < 3; i++){
841 if(points[i].x < plot->bottom->ticks.min || points[i].x > plot->bottom->ticks.max ||
842 points[i].y < plot->left->ticks.min || points[i].y > plot->left->ticks.max)
843 { discard = TRUE; break; }
844 }
845 }
846 if(discard) { list = list->next; continue; }
847 }
848
849
850 side1.x = -(points[1].x - points[0].x);
851 side1.y = -(points[1].y - points[0].y);
852 side1.z = -(points[1].z - points[0].z);
853 side2.x = -(points[2].x - points[0].x);
854 side2.y = -(points[2].y - points[0].y);
855 side2.z = -(points[2].z - points[0].z);
856
857 if(surface->use_amplitud && array_a){
858 gtk_plot_data_get_gradient_level(GTK_PLOT_DATA(surface),
859 (array_a[triangle->na->id] +
860 array_a[triangle->nb->id] +
861 array_a[triangle->nc->id]) / 3.0,
862 &real_color);
863 } else if(surface->use_height_gradient){
864 gtk_plot_data_get_gradient_level(GTK_PLOT_DATA(surface),
865 (triangle->na->z +
866 triangle->nb->z +
867 triangle->nc->z) / 3.0,
868 &real_color);
869 }else{
870 color = surface->color;
871 light = surface->light;
872 norm = _sqrt(10000*(light.x*light.x + light.y*light.y + light.z*light.z))/100;
873 light.x /= norm;
874 light.y /= norm;
875 light.z /= norm;
876
877 factor = 1.0;
878 if(GTK_IS_PLOT3D(plot)){
879 normal.x = side1.y * side2.z - side1.z * side2.y;
880 normal.y = side1.z * side2.x - side1.x * side2.z;
881 normal.z = side1.x * side2.y - side1.y * side2.x;
882
883 norm = _sqrt(100000000*(normal.x*normal.x + normal.y*normal.y + normal.z*normal.z))/10000.;
884 factor = (normal.x*light.x + normal.y*light.y + normal.z*light.z) / norm;
885 }
886
887 gtk_plot_surface_lighting(&color, &real_color,
888 factor, surface->ambient);
889
890 }
891
892 if(GTK_IS_PLOT3D(plot))
893 if(((t[1].x-t[0].x)*(t[2].y-t[0].y) - (t[1].y-t[0].y)*(t[2].x-t[0].x)) > 0)
894 visible = FALSE;
895
896 if(visible)
897 gtk_plot_pc_set_color(plot->pc, &real_color);
898 else
899 gtk_plot_pc_set_color(plot->pc, &surface->shadow);
900
901 gtk_plot_pc_draw_polygon(plot->pc, !surface->transparent, t, 3);
902
903
904 color_set = FALSE;
905 if(surface->show_mesh){
906 if(visible)
907 gtk_plot_pc_set_color(plot->pc, &surface->grid_foreground);
908 else
909 gtk_plot_pc_set_color(plot->pc, &surface->grid_background);
910 color_set = TRUE;
911 gtk_plot_pc_draw_polygon(plot->pc, FALSE, t, 3);
912 }
913
914 if(!surface->show_mesh && surface->show_grid && surface->dt->quadrilateral){
915 if(!color_set){
916 if(visible)
917 gtk_plot_pc_set_color(plot->pc, &surface->grid_foreground);
918 else
919 gtk_plot_pc_set_color(plot->pc, &surface->grid_background);
920 }
921
922 gtk_plot_pc_draw_line(plot->pc,
923 t[1].x, t[1].y, t[2].x, t[2].y);
924
925 }
926
927 list = list->next;
928 }
929 }
930
931 static void
gtk_plot_surface_get_legend_size(GtkPlotData * data,gint * width,gint * height)932 gtk_plot_surface_get_legend_size(GtkPlotData *data, gint *width, gint *height)
933 {
934 GtkPlotSurface *surface;
935 GtkPlot *plot = NULL;
936 GtkPlotText legend;
937 gint lascent = 0, ldescent = 0, lheight = 0, lwidth = 0;
938 gdouble m;
939
940 surface = GTK_PLOT_SURFACE(data);
941
942 g_return_if_fail(data->plot != NULL);
943 g_return_if_fail(GTK_IS_PLOT(data->plot));
944
945 plot = data->plot;
946
947 m = plot->magnification;
948 legend = plot->legends_attr;
949
950 if(data->legend && strlen(data->legend) > 0)
951 legend.text = data->legend;
952 else
953 legend.text = "X";
954
955 *height = 0;
956 *width = roundint(16*m);
957
958 if(data->show_legend){
959 int lstep = roundint(plot->legends_line_width * m / 10.);
960 double step = (data->gradient->ticks.max - data->gradient->ticks.min) / 10;
961 double level;
962 for(level = data->gradient->ticks.min; level < data->gradient->ticks.max; level += step) *width += lstep;
963
964 gtk_plot_text_get_size(legend.text, legend.angle, legend.font,
965 roundint(legend.height * m),
966 &lwidth, &lheight,
967 &lascent, &ldescent);
968 *height = *height + lascent + ldescent;
969 *width = *width + lwidth;
970 }
971 }
972
973 static void
gtk_plot_surface_draw_legend(GtkPlotData * data,gint x,gint y)974 gtk_plot_surface_draw_legend(GtkPlotData *data, gint x, gint y)
975 {
976 GtkPlotSurface *surface;
977 GtkPlot *plot = NULL;
978 GtkPlotText legend;
979 GdkRectangle area;
980 gint lascent, ldescent, lheight, lwidth;
981 gdouble m;
982 GtkAllocation allocation;
983
984 surface = GTK_PLOT_SURFACE(data);
985
986 g_return_if_fail(data->plot != NULL);
987 g_return_if_fail(GTK_IS_PLOT(data->plot));
988
989 plot = data->plot;
990 gtk_widget_get_allocation(GTK_WIDGET(plot), &allocation);
991 area.x = allocation.x;
992 area.y = allocation.y;
993 area.width = allocation.width;
994 area.height = allocation.height;
995
996 m = plot->magnification;
997 legend = plot->legends_attr;
998
999 if(data->legend && strlen(data->legend) > 0)
1000 legend.text = data->legend;
1001 else
1002 legend.text = "X";
1003
1004 gtk_plot_text_get_size(legend.text, legend.angle, legend.font,
1005 roundint(legend.height * m),
1006 &lwidth, &lheight,
1007 &lascent, &ldescent);
1008
1009
1010 if(data->show_legend){
1011 if(!surface->use_height_gradient && !surface->use_amplitud){
1012 gtk_plot_pc_set_color(plot->pc, &surface->color);
1013
1014 gtk_plot_pc_draw_rectangle(plot->pc, TRUE,
1015 area.x + x, area.y + y,
1016 roundint(plot->legends_line_width * m),
1017 lascent + ldescent);
1018 }else{
1019 gdouble level, step;
1020 gint lx = x, lstep;
1021 step = (data->gradient->ticks.max - data->gradient->ticks.min) / 10;
1022 lstep = roundint(plot->legends_line_width * m / 10.);
1023 for(level = data->gradient->ticks.min; level < data->gradient->ticks.max; level += step){
1024 GdkColor color;
1025 gtk_plot_data_get_gradient_level(data, level, &color);
1026 gtk_plot_pc_set_color(plot->pc, &color);
1027
1028 gtk_plot_pc_draw_rectangle(plot->pc, TRUE,
1029 area.x + lx, area.y + y,
1030 lstep, lascent + ldescent);
1031 lx += lstep;
1032 }
1033 }
1034
1035 legend.x = (gdouble)(area.x + x + roundint((plot->legends_line_width + 4) * m))
1036 / (gdouble)area.width;
1037 legend.y = (gdouble)(area.y + y + lascent) / (gdouble)area.height;
1038
1039 if(data->legend && strlen(data->legend) > 0) gtk_plot_draw_text(plot, legend);
1040
1041 y += 2*lheight;
1042 } else
1043 y += lheight;
1044 }
1045
1046 static void
gtk_plot_surface_lighting(GdkColor * a,GdkColor * b,gdouble normal,gdouble ambient)1047 gtk_plot_surface_lighting (GdkColor *a, GdkColor *b,
1048 gdouble normal, gdouble ambient)
1049 {
1050 gdouble red, green, blue;
1051 gdouble h, s, v;
1052
1053 if(normal == 1.0){
1054 *b = *a;
1055 return;
1056 }
1057
1058 normal = MIN(fabs(normal), 1.0);
1059
1060 red = a->red;
1061 green = a->green;
1062 blue = a->blue;
1063
1064 rgb_to_hsv(red, green, blue, &h, &s, &v);
1065
1066 s *= normal;
1067 v *= normal;
1068
1069 s += ambient;
1070 v += ambient;
1071
1072 hsv_to_rgb(h, MIN(s, 1.0), MIN(v, 1.0), &red, &green, &blue);
1073
1074 b->red = red;
1075 b->green = green;
1076 b->blue = blue;
1077 }
1078
1079
1080 static void
hsv_to_rgb(gdouble h,gdouble s,gdouble v,gdouble * r,gdouble * g,gdouble * b)1081 hsv_to_rgb (gdouble h, gdouble s, gdouble v,
1082 gdouble *r, gdouble *g, gdouble *b)
1083 {
1084 gint i;
1085 gdouble f, w, q, t;
1086
1087 if (s == 0.0)
1088 s = 0.000001;
1089
1090 if (h == -1.0)
1091 {
1092 *r = v;
1093 *g = v;
1094 *b = v;
1095 }
1096 else
1097 {
1098 if (h == 360.0) h = 0.0;
1099 h = h / 60.0;
1100 i = (gint) h;
1101 f = h - i;
1102 w = v * (1.0 - s);
1103 q = v * (1.0 - (s * f));
1104 t = v * (1.0 - (s * (1.0 - f)));
1105
1106 switch (i)
1107 {
1108 case 0:
1109 *r = v;
1110 *g = t;
1111 *b = w;
1112 break;
1113 case 1:
1114 *r = q;
1115 *g = v;
1116 *b = w;
1117 break;
1118 case 2:
1119 *r = w;
1120 *g = v;
1121 *b = t;
1122 break;
1123 case 3:
1124 *r = w;
1125 *g = q;
1126 *b = v;
1127 break;
1128 case 4:
1129 *r = t;
1130 *g = w;
1131 *b = v;
1132 break;
1133 case 5:
1134 *r = v;
1135 *g = w;
1136 *b = q;
1137 break;
1138 }
1139 }
1140
1141 *r *= 65535.;
1142 *g *= 65535.;
1143 *b *= 65535.;
1144 }
1145
1146 static void
rgb_to_hsv(gdouble r,gdouble g,gdouble b,gdouble * h,gdouble * s,gdouble * v)1147 rgb_to_hsv (gdouble r, gdouble g, gdouble b,
1148 gdouble *h, gdouble *s, gdouble *v)
1149 {
1150 double max, min, delta;
1151
1152 r /= 65535.;
1153 g /= 65535.;
1154 b /= 65535.;
1155
1156 max = r;
1157 if (g > max)
1158 max = g;
1159 if (b > max)
1160 max = b;
1161
1162 min = r;
1163 if (g < min)
1164 min = g;
1165 if (b < min)
1166 min = b;
1167
1168 *v = max;
1169 if (max != 0.0)
1170 *s = (max - min) / max;
1171 else
1172 *s = 0.0;
1173
1174 if (*s == 0.0)
1175 *h = -1.0;
1176 else
1177 {
1178 delta = max - min;
1179
1180 if (r == max)
1181 *h = (g - b) / delta;
1182 else if (g == max)
1183 *h = 2.0 + (b - r) / delta;
1184 else if (b == max)
1185 *h = 4.0 + (r - g) / delta;
1186
1187 *h = *h * 60.0;
1188
1189 if (*h < 0.0)
1190 *h = *h + 360;
1191 }
1192 }
1193
1194
1195 /******************************************
1196 * gtk_plot_surface_set_color
1197 * gtk_plot_surface_set_shadow
1198 * gtk_plot_surface_set_grid_foreground
1199 * gtk_plot_surface_set_grid_background
1200 * gtk_plot_surface_set_grid_visible
1201 * gtk_plot_surface_set_mesh_visible
1202 * gtk_plot_surface_get_grid_visible
1203 * gtk_plot_surface_get_mesh_visible
1204 ******************************************/
1205
1206 /**
1207 * gtk_plot_surface_set_color:
1208 * @data:
1209 * @color:
1210 *
1211 *
1212 */
1213 void
gtk_plot_surface_set_color(GtkPlotSurface * data,GdkColor * color)1214 gtk_plot_surface_set_color (GtkPlotSurface *data,
1215 GdkColor *color)
1216 {
1217 data->color = *color;
1218 }
1219
1220 /**
1221 * gtk_plot_surface_set_shadow:
1222 * @data:
1223 * @color:
1224 *
1225 *
1226 */
1227 void
gtk_plot_surface_set_shadow(GtkPlotSurface * data,GdkColor * color)1228 gtk_plot_surface_set_shadow (GtkPlotSurface *data,
1229 GdkColor *color)
1230 {
1231 data->shadow = *color;
1232 }
1233
1234 /**
1235 * gtk_plot_surface_set_grid_foreground:
1236 * @data:
1237 * @foreground:
1238 *
1239 *
1240 */
1241 void
gtk_plot_surface_set_grid_foreground(GtkPlotSurface * data,GdkColor * foreground)1242 gtk_plot_surface_set_grid_foreground (GtkPlotSurface *data,
1243 GdkColor *foreground)
1244 {
1245 data->grid_foreground = *foreground;
1246 }
1247
1248 /**
1249 * gtk_plot_surface_set_grid_background:
1250 * @data:
1251 * @background:
1252 *
1253 *
1254 */
1255 void
gtk_plot_surface_set_grid_background(GtkPlotSurface * data,GdkColor * background)1256 gtk_plot_surface_set_grid_background (GtkPlotSurface *data,
1257 GdkColor *background)
1258 {
1259 data->grid_background = *background;
1260 }
1261
1262 /**
1263 * gtk_plot_surface_set_grid_visible:
1264 * @data:
1265 * @visible:
1266 *
1267 *
1268 */
1269 void
gtk_plot_surface_set_grid_visible(GtkPlotSurface * data,gboolean visible)1270 gtk_plot_surface_set_grid_visible (GtkPlotSurface *data,
1271 gboolean visible)
1272 {
1273 data->show_grid = visible;
1274 }
1275
1276 /**
1277 * gtk_plot_surface_get_grid_visible:
1278 * @data:
1279 *
1280 *
1281 */
1282 gboolean
gtk_plot_surface_get_grid_visible(GtkPlotSurface * data)1283 gtk_plot_surface_get_grid_visible (GtkPlotSurface *data)
1284 {
1285 return (data->show_grid);
1286 }
1287
1288 /**
1289 * gtk_plot_surface_set_mesh_visible:
1290 * @data:
1291 * @visible:
1292 *
1293 *
1294 */
1295 void
gtk_plot_surface_set_mesh_visible(GtkPlotSurface * data,gboolean visible)1296 gtk_plot_surface_set_mesh_visible (GtkPlotSurface *data,
1297 gboolean visible)
1298 {
1299 data->show_mesh = visible;
1300 }
1301
1302 /**
1303 * gtk_plot_surface_get_mesh_visible:
1304 * @data:
1305 *
1306 *
1307 */
1308 gboolean
gtk_plot_surface_get_mesh_visible(GtkPlotSurface * data)1309 gtk_plot_surface_get_mesh_visible (GtkPlotSurface *data)
1310 {
1311 return (data->show_mesh);
1312 }
1313
1314 /**
1315 * gtk_plot_surface_set_light:
1316 * @data:
1317 * @x:
1318 * @y:
1319 * @z:
1320 *
1321 *
1322 */
1323 void
gtk_plot_surface_set_light(GtkPlotSurface * data,gdouble x,gdouble y,gdouble z)1324 gtk_plot_surface_set_light (GtkPlotSurface *data,
1325 gdouble x, gdouble y, gdouble z)
1326 {
1327 data->light.x = x;
1328 data->light.y = y;
1329 data->light.z = z;
1330 }
1331
1332 /**
1333 * gtk_plot_surface_use_height_gradient:
1334 * @data:
1335 * @use_gradient:
1336 *
1337 *
1338 */
1339 void
gtk_plot_surface_use_height_gradient(GtkPlotSurface * data,gboolean use_gradient)1340 gtk_plot_surface_use_height_gradient (GtkPlotSurface *data,
1341 gboolean use_gradient)
1342 {
1343 data->use_height_gradient = use_gradient;
1344 }
1345
1346 /**
1347 * gtk_plot_surface_use_amplitud:
1348 * @data:
1349 * @use_amplitud:
1350 *
1351 *
1352 */
1353 void
gtk_plot_surface_use_amplitud(GtkPlotSurface * data,gboolean use_amplitud)1354 gtk_plot_surface_use_amplitud (GtkPlotSurface *data,
1355 gboolean use_amplitud)
1356 {
1357 data->use_amplitud = use_amplitud;
1358 }
1359
1360 /**
1361 * gtk_plot_surface_set_ambient:
1362 * @data:
1363 * @ambient:
1364 *
1365 *
1366 */
1367 void
gtk_plot_surface_set_ambient(GtkPlotSurface * data,gdouble ambient)1368 gtk_plot_surface_set_ambient (GtkPlotSurface *data,
1369 gdouble ambient)
1370 {
1371 data->ambient = ambient;
1372 }
1373
1374 /**
1375 * gtk_plot_surface_set_transparent:
1376 * @data:
1377 * @transparent:
1378 *
1379 *
1380 */
1381 void
gtk_plot_surface_set_transparent(GtkPlotSurface * data,gboolean transparent)1382 gtk_plot_surface_set_transparent (GtkPlotSurface *data,
1383 gboolean transparent)
1384 {
1385 data->transparent = transparent;
1386 }
1387
1388 /******************************************
1389 * gtk_plot_surface_set_points
1390 * gtk_plot_surface_get_points
1391 * gtk_plot_surface_set_x
1392 * gtk_plot_surface_set_y
1393 * gtk_plot_surface_set_z
1394 * gtk_plot_surface_set_dx
1395 * gtk_plot_surface_set_dy
1396 * gtk_plot_surface_set_dz
1397 * gtk_plot_surface_get_x
1398 * gtk_plot_surface_get_y
1399 * gtk_plot_surface_get_z
1400 * gtk_plot_surface_get_dx
1401 * gtk_plot_surface_get_dy
1402 * gtk_plot_surface_get_dz
1403 * gtk_plot_surface_set_nx
1404 * gtk_plot_surface_set_ny
1405 * gtk_plot_surface_get_nx
1406 * gtk_plot_surface_get_ny
1407 * gtk_plot_surface_set_xstep
1408 * gtk_plot_surface_set_ystep
1409 * gtk_plot_surface_get_xstep
1410 * gtk_plot_surface_get_ystep
1411 ******************************************/
1412
1413 /**
1414 * gtk_plot_surface_set_points:
1415 * @x:
1416 * @y:
1417 * @z:
1418 * @dx:
1419 * @dy:
1420 * @dz:
1421 * @nx:
1422 * @ny:
1423 *
1424 *
1425 */
1426 void
gtk_plot_surface_set_points(GtkPlotSurface * data,gdouble * x,gdouble * y,gdouble * z,gdouble * dx,gdouble * dy,gdouble * dz,gint nx,gint ny)1427 gtk_plot_surface_set_points(GtkPlotSurface *data,
1428 gdouble *x, gdouble *y, gdouble *z,
1429 gdouble *dx, gdouble *dy, gdouble *dz,
1430 gint nx, gint ny)
1431 {
1432 gtk_plot_data_set_x(GTK_PLOT_DATA(data), x);
1433 gtk_plot_data_set_y(GTK_PLOT_DATA(data), y);
1434 gtk_plot_data_set_z(GTK_PLOT_DATA(data), z);
1435 gtk_plot_data_set_dx(GTK_PLOT_DATA(data), dx);
1436 gtk_plot_data_set_dy(GTK_PLOT_DATA(data), dy);
1437 gtk_plot_data_set_dz(GTK_PLOT_DATA(data), dz);
1438 data->nx = nx;
1439 data->ny = ny;
1440 gtk_plot_data_set_numpoints(GTK_PLOT_DATA(data), nx * ny);
1441
1442 gtk_plot_surface_build_mesh(data);
1443 }
1444
1445 /**
1446 * gtk_plot_surface_get_points:
1447 * @x:
1448 * @y:
1449 * @z:
1450 * @dx:
1451 * @dy:
1452 * @dz:
1453 * @nx:
1454 * @ny:
1455 *
1456 *
1457 */
1458 void
gtk_plot_surface_get_points(GtkPlotSurface * data,gdouble ** x,gdouble ** y,gdouble ** z,gdouble ** dx,gdouble ** dy,gdouble ** dz,gint * nx,gint * ny)1459 gtk_plot_surface_get_points(GtkPlotSurface *data,
1460 gdouble **x, gdouble **y, gdouble **z,
1461 gdouble **dx, gdouble **dy, gdouble **dz,
1462 gint *nx, gint *ny)
1463 {
1464 gint n;
1465 *x = gtk_plot_data_get_x(GTK_PLOT_DATA(data), &n);
1466 *y = gtk_plot_data_get_y(GTK_PLOT_DATA(data), &n);
1467 *z = gtk_plot_data_get_z(GTK_PLOT_DATA(data), &n);
1468 *dx = gtk_plot_data_get_dx(GTK_PLOT_DATA(data), &n);
1469 *dy = gtk_plot_data_get_dy(GTK_PLOT_DATA(data), &n);
1470 *dz = gtk_plot_data_get_dz(GTK_PLOT_DATA(data), &n);
1471 *nx = data->nx;
1472 *ny = data->ny;
1473 }
1474
1475 /**
1476 * gtk_plot_surface_set_x:
1477 * @data:
1478 * @x: the value to be set
1479 *
1480 * Return value: (transfer none) the affected #GtkPlotArray
1481 */
1482 GtkPlotArray *
gtk_plot_surface_set_x(GtkPlotSurface * data,gdouble * x)1483 gtk_plot_surface_set_x(GtkPlotSurface *data,
1484 gdouble *x)
1485 {
1486 return gtk_plot_data_set_x(GTK_PLOT_DATA(data), x);
1487 }
1488
1489 /**
1490 * gtk_plot_surface_set_y:
1491 * @data:
1492 * @y: the value to be set
1493 *
1494 * Return value: (transfer none) the affected #GtkPlotArray
1495 */
1496 GtkPlotArray *
gtk_plot_surface_set_y(GtkPlotSurface * data,gdouble * y)1497 gtk_plot_surface_set_y(GtkPlotSurface *data,
1498 gdouble *y)
1499 {
1500 return gtk_plot_data_set_y(GTK_PLOT_DATA(data), y);
1501 }
1502
1503 /**
1504 * gtk_plot_surface_set_z:
1505 * @data:
1506 * @z: the value to be set
1507 *
1508 * Return value: (transfer none) the affected #GtkPlotArray
1509 */
1510 GtkPlotArray *
gtk_plot_surface_set_z(GtkPlotSurface * data,gdouble * z)1511 gtk_plot_surface_set_z(GtkPlotSurface *data,
1512 gdouble *z)
1513 {
1514 return gtk_plot_data_set_z(GTK_PLOT_DATA(data), z);
1515 }
1516
1517 /**
1518 * gtk_plot_surface_set_dx:
1519 * @data:
1520 * @dx: the value to be set
1521 *
1522 * Return value: (transfer none) the affected #GtkPlotArray
1523 */
1524 GtkPlotArray *
gtk_plot_surface_set_dx(GtkPlotSurface * data,gdouble * dx)1525 gtk_plot_surface_set_dx(GtkPlotSurface *data,
1526 gdouble *dx)
1527 {
1528 return gtk_plot_data_set_dx(GTK_PLOT_DATA(data), dx);
1529 }
1530
1531 /**
1532 * gtk_plot_surface_set_dy:
1533 * @data:
1534 * @dy: the value to be set
1535 *
1536 * Return value: (transfer none) the affected #GtkPlotArray
1537 */
1538 GtkPlotArray *
gtk_plot_surface_set_dy(GtkPlotSurface * data,gdouble * dy)1539 gtk_plot_surface_set_dy(GtkPlotSurface *data,
1540 gdouble *dy)
1541 {
1542 return gtk_plot_data_set_dy(GTK_PLOT_DATA(data), dy);
1543 }
1544
1545 /**
1546 * gtk_plot_surface_set_dz:
1547 * @data:
1548 * @dz: the value to be set
1549 *
1550 * Return value: (transfer none) the affected #GtkPlotArray
1551 */
1552 GtkPlotArray *
gtk_plot_surface_set_dz(GtkPlotSurface * data,gdouble * dz)1553 gtk_plot_surface_set_dz(GtkPlotSurface *data,
1554 gdouble *dz)
1555 {
1556 return gtk_plot_data_set_dz(GTK_PLOT_DATA(data), dz);
1557 }
1558
1559 /**
1560 * gtk_plot_surface_get_x:
1561 * @dataset:
1562 * @nx: the value to be set
1563 *
1564 * Return value:
1565 */
1566 gdouble *
gtk_plot_surface_get_x(GtkPlotSurface * dataset,gint * nx)1567 gtk_plot_surface_get_x(GtkPlotSurface *dataset, gint *nx)
1568 {
1569 gint n;
1570 *nx = dataset->nx;
1571 return(gtk_plot_data_get_x(GTK_PLOT_DATA(dataset), &n));
1572 }
1573
1574 /**
1575 * gtk_plot_surface_get_y:
1576 * @dataset:
1577 * @ny:
1578 *
1579 *
1580 *
1581 * Return value:
1582 */
1583 gdouble *
gtk_plot_surface_get_y(GtkPlotSurface * dataset,gint * ny)1584 gtk_plot_surface_get_y(GtkPlotSurface *dataset, gint *ny)
1585 {
1586 gint n;
1587 *ny = dataset->ny;
1588 return(gtk_plot_data_get_y(GTK_PLOT_DATA(dataset), &n));
1589 }
1590
1591 /**
1592 * gtk_plot_surface_get_z:
1593 * @dataset:
1594 * @nx:
1595 * @ny:
1596 *
1597 *
1598 *
1599 * Return value:
1600 */
1601 gdouble *
gtk_plot_surface_get_z(GtkPlotSurface * dataset,gint * nx,gint * ny)1602 gtk_plot_surface_get_z(GtkPlotSurface *dataset, gint *nx, gint *ny)
1603 {
1604 gint n;
1605 *nx = dataset->nx;
1606 *ny = dataset->ny;
1607 return(gtk_plot_data_get_z(GTK_PLOT_DATA(dataset), &n));
1608 }
1609
1610 /**
1611 * gtk_plot_surface_get_dz:
1612 * @dataset:
1613 *
1614 *
1615 *
1616 * Return value:
1617 */
1618 gdouble *
gtk_plot_surface_get_dz(GtkPlotSurface * dataset)1619 gtk_plot_surface_get_dz(GtkPlotSurface *dataset)
1620 {
1621 gint n;
1622 return(gtk_plot_data_get_dz(GTK_PLOT_DATA(dataset), &n));
1623 }
1624
1625 /**
1626 * gtk_plot_surface_get_dx:
1627 * @dataset:
1628 *
1629 *
1630 *
1631 * Return value:
1632 */
1633 gdouble *
gtk_plot_surface_get_dx(GtkPlotSurface * dataset)1634 gtk_plot_surface_get_dx(GtkPlotSurface *dataset)
1635 {
1636 gint n;
1637 return(gtk_plot_data_get_dx(GTK_PLOT_DATA(dataset), &n));
1638 }
1639
1640 /**
1641 * gtk_plot_surface_get_dy:
1642 * @dataset:
1643 *
1644 *
1645 *
1646 * Return value:
1647 */
1648 gdouble *
gtk_plot_surface_get_dy(GtkPlotSurface * dataset)1649 gtk_plot_surface_get_dy(GtkPlotSurface *dataset)
1650 {
1651 gint n;
1652 return(gtk_plot_data_get_dy(GTK_PLOT_DATA(dataset), &n));
1653 }
1654
1655 /**
1656 * gtk_plot_surface_set_nx:
1657 * @dataset:
1658 * @nx:
1659 *
1660 *
1661 */
1662 void
gtk_plot_surface_set_nx(GtkPlotSurface * dataset,gint nx)1663 gtk_plot_surface_set_nx(GtkPlotSurface *dataset, gint nx)
1664 {
1665 dataset->nx = nx;
1666 }
1667
1668 /**
1669 * gtk_plot_surface_set_ny:
1670 * @dataset:
1671 * @ny:
1672 *
1673 *
1674 */
1675 void
gtk_plot_surface_set_ny(GtkPlotSurface * dataset,gint ny)1676 gtk_plot_surface_set_ny(GtkPlotSurface *dataset, gint ny)
1677 {
1678 dataset->ny = ny;
1679 }
1680
1681 /**
1682 * gtk_plot_surface_get_nx:
1683 * @dataset:
1684 *
1685 *
1686 *
1687 * Return value:
1688 */
1689 gint
gtk_plot_surface_get_nx(GtkPlotSurface * dataset)1690 gtk_plot_surface_get_nx(GtkPlotSurface *dataset)
1691 {
1692 return(dataset->nx);
1693 }
1694
1695 /**
1696 * gtk_plot_surface_get_ny:
1697 * @dataset:
1698 *
1699 *
1700 *
1701 * Return value:
1702 */
1703 gint
gtk_plot_surface_get_ny(GtkPlotSurface * dataset)1704 gtk_plot_surface_get_ny(GtkPlotSurface *dataset)
1705 {
1706 return(dataset->ny);
1707 }
1708
1709 /**
1710 * gtk_plot_surface_set_xstep:
1711 * @dataset:
1712 * @xstep:
1713 *
1714 *
1715 */
1716 void
gtk_plot_surface_set_xstep(GtkPlotSurface * dataset,gdouble xstep)1717 gtk_plot_surface_set_xstep(GtkPlotSurface *dataset, gdouble xstep)
1718 {
1719 dataset->xstep = xstep;
1720 }
1721
1722 /**
1723 * gtk_plot_surface_set_ystep:
1724 * @dataset:
1725 * @ystep:
1726 *
1727 *
1728 */
1729 void
gtk_plot_surface_set_ystep(GtkPlotSurface * dataset,gdouble ystep)1730 gtk_plot_surface_set_ystep(GtkPlotSurface *dataset, gdouble ystep)
1731 {
1732 dataset->ystep = ystep;
1733 }
1734
1735 /**
1736 * gtk_plot_surface_get_xstep:
1737 * @dataset:
1738 *
1739 *
1740 *
1741 * Return value:
1742 */
1743 gdouble
gtk_plot_surface_get_xstep(GtkPlotSurface * dataset)1744 gtk_plot_surface_get_xstep(GtkPlotSurface *dataset)
1745 {
1746 return (dataset->xstep);
1747 }
1748
1749 /**
1750 * gtk_plot_surface_get_ystep:
1751 * @dataset:
1752 *
1753 *
1754 *
1755 * Return value:
1756 */
1757 gdouble
gtk_plot_surface_get_ystep(GtkPlotSurface * dataset)1758 gtk_plot_surface_get_ystep(GtkPlotSurface *dataset)
1759 {
1760 return (dataset->ystep);
1761 }
1762
1763 /**
1764 * gtk_plot_surface_build_mesh:
1765 * @surface:
1766 *
1767 *
1768 */
1769 void
gtk_plot_surface_build_mesh(GtkPlotSurface * surface)1770 gtk_plot_surface_build_mesh(GtkPlotSurface *surface)
1771 {
1772 GtkPlotData *data;
1773 GtkPlot *plot;
1774
1775 data = GTK_PLOT_DATA(surface);
1776 if(!data->plot) return;
1777 plot = data->plot;
1778
1779 if(data->is_function){
1780 gdouble xstep, ystep;
1781 gdouble xmin, xmax, ymin, ymax;
1782 gdouble x, y;
1783 gdouble *fx = NULL, *fy = NULL, *fz = NULL;
1784 gint nx, ny;
1785 gint npoints;
1786
1787 xmin = GTK_PLOT(plot)->xmin;
1788 xmax = GTK_PLOT(plot)->xmax;
1789 ymin = GTK_PLOT(plot)->ymin;
1790 ymax = GTK_PLOT(plot)->ymax;
1791
1792 xstep = surface->xstep;
1793 surface->nx = roundint((xmax - xmin) / xstep) + 1;
1794
1795 ystep = surface->ystep;
1796 surface->ny = roundint((ymax - ymin) / ystep) + 1;
1797
1798 npoints = surface->nx * surface->ny;
1799 fx = (gdouble *)g_malloc((npoints + 1) * sizeof(gdouble));
1800 fy = (gdouble *)g_malloc((npoints + 1) * sizeof(gdouble));
1801 fz = (gdouble *)g_malloc((npoints + 1) * sizeof(gdouble));
1802
1803 npoints = 0;
1804 y = ymin;
1805 for(ny = 0; ny < surface->ny; ny++)
1806 {
1807 x = xmin;
1808 for(nx = 0; nx < surface->nx; nx++)
1809 {
1810 gboolean error;
1811 fx[npoints] = x;
1812 fy[npoints] = y;
1813 fz[npoints] = data->function3d(plot, data, x, y, &error);
1814
1815 x += xstep;
1816 npoints++;
1817 }
1818 y += ystep;
1819 }
1820
1821 gtk_plot_data_set_x(data, fx);
1822 gtk_plot_data_set_y(data, fy);
1823 gtk_plot_data_set_z(data, fz);
1824 gtk_plot_data_set_numpoints(data, npoints);
1825 gtk_plot_surface_real_build_mesh(surface);
1826
1827 g_free(fx);
1828 g_free(fy);
1829 g_free(fz);
1830 }
1831 else if(data->is_iterator){
1832 gdouble x, y, z, a, dx, dy, dz, da;
1833 gchar *label;
1834 gdouble *fx = NULL, *fy = NULL, *fz = NULL;
1835 gint iter;
1836
1837 if(data->iterator_mask & GTK_PLOT_DATA_X)
1838 fx = g_new0(gdouble, data->num_points);
1839 if(data->iterator_mask & GTK_PLOT_DATA_Y)
1840 fy = g_new0(gdouble, data->num_points);
1841 if(data->iterator_mask & GTK_PLOT_DATA_Z)
1842 fz = g_new0(gdouble, data->num_points);
1843
1844 for(iter = 0; iter < data->num_points; iter++)
1845 {
1846 gboolean error;
1847 data->iterator (plot, data, iter,
1848 &x, &y, &z, &a, &dx, &dy, &dz, &da, &label, &error);
1849
1850 if(error)
1851 {
1852 break;
1853 }
1854 else
1855 {
1856 if(data->iterator_mask & GTK_PLOT_DATA_X) fx[iter] = x;
1857 if(data->iterator_mask & GTK_PLOT_DATA_Y) fy[iter] = y;
1858 if(data->iterator_mask & GTK_PLOT_DATA_Z) fz[iter] = z;
1859 }
1860 }
1861
1862 gtk_plot_data_set_x(GTK_PLOT_DATA(surface), fx);
1863 gtk_plot_data_set_y(GTK_PLOT_DATA(surface), fy);
1864 gtk_plot_data_set_z(GTK_PLOT_DATA(surface), fz);
1865
1866 gtk_plot_surface_real_build_mesh(surface);
1867
1868 g_free(fx);
1869 g_free(fy);
1870 g_free(fz);
1871 }
1872 else
1873 gtk_plot_surface_real_build_mesh(surface);
1874 }
1875
1876 static void
gtk_plot_surface_real_build_mesh(GtkPlotSurface * surface)1877 gtk_plot_surface_real_build_mesh(GtkPlotSurface *surface)
1878 {
1879 GtkPlotData *data;
1880 gdouble *array_x, *array_y, *array_z;
1881 GtkPlot *plot;
1882 gint i;
1883
1884 data = GTK_PLOT_DATA(surface);
1885 if(!data->plot) return;
1886 plot = data->plot;
1887
1888 if(data->num_points == 0) return;
1889
1890 gtk_plot_dt_clear(surface->dt);
1891
1892 array_x = gtk_plot_data_get_x(GTK_PLOT_DATA(surface), &i);
1893 array_y = gtk_plot_data_get_y(GTK_PLOT_DATA(surface), &i);
1894 array_z = gtk_plot_data_get_z(GTK_PLOT_DATA(surface), &i);
1895
1896 for(i = 0; i < data->num_points; i++){
1897 GtkPlotDTnode node;
1898 node.x = array_x[i];
1899 node.y = array_y[i];
1900 node.z = 0.0;
1901 if(array_z) node.z = array_z[i];
1902 gtk_plot_dt_add_node(surface->dt, node);
1903 }
1904 gtk_plot_dt_triangulate(surface->dt);
1905
1906 GTK_PLOT_SURFACE_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(surface)))->build_polygons(surface);
1907
1908 gtk_plot_surface_recalc_nodes(surface);
1909 surface->recalc_dt = FALSE;
1910 }
1911
1912 static void
gtk_plot_surface_build_polygons(GtkPlotSurface * surface)1913 gtk_plot_surface_build_polygons(GtkPlotSurface *surface)
1914 {
1915 GList *list;
1916
1917 clear_polygons(surface);
1918 list = surface->dt->triangles;
1919 while(list){
1920 GtkPlotPolygon *polygon;
1921 GtkPlotDTtriangle *triangle = (GtkPlotDTtriangle *)list->data;
1922
1923 polygon = g_new0(GtkPlotPolygon, 1);
1924 polygon->t = triangle;
1925 polygon->n = 3;
1926 polygon->cut_level = FALSE;
1927 polygon->xyz[0].x = triangle->na->x;
1928 polygon->xyz[0].y = triangle->na->y;
1929 polygon->xyz[0].z = triangle->na->z;
1930 polygon->xyz[1].x = triangle->nb->x;
1931 polygon->xyz[1].y = triangle->nb->y;
1932 polygon->xyz[1].z = triangle->nb->z;
1933 polygon->xyz[2].x = triangle->nc->x;
1934 polygon->xyz[2].y = triangle->nc->y;
1935 polygon->xyz[2].z = triangle->nc->z;
1936 surface->polygons = g_list_append(surface->polygons, polygon);
1937
1938 list = list->next;
1939 };
1940 }
1941
1942 /**
1943 * gtk_plot_surface_recalc_nodes:
1944 * @surface:
1945 *
1946 *
1947 */
1948 void
gtk_plot_surface_recalc_nodes(GtkPlotSurface * surface)1949 gtk_plot_surface_recalc_nodes(GtkPlotSurface *surface)
1950 {
1951 GtkPlotData *data;
1952 GtkPlot *plot;
1953 GList *list;
1954 gint i;
1955
1956 data = GTK_PLOT_DATA(surface);
1957 if(!data->plot) return;
1958 plot = data->plot;
1959
1960 for(i= surface->dt->node_0; i < surface->dt->node_cnt; i++){
1961 GtkPlotDTnode *node;
1962 node = gtk_plot_dt_get_node(surface->dt,i);
1963 if(GTK_IS_PLOT3D(plot)){
1964 gtk_plot3d_get_pixel(GTK_PLOT3D(plot),
1965 node->x, node->y, node->z,
1966 &node->px, &node->py, &node->pz);
1967 } else {
1968 gtk_plot_get_pixel(plot,
1969 node->x, node->y,
1970 &node->px, &node->py);
1971 node->pz = 0.0;
1972 }
1973 }
1974
1975 list = surface->polygons;
1976 while(list){
1977 GtkPlotPolygon *polygon = (GtkPlotPolygon *)list->data;
1978
1979 for(i = 0; i < polygon->n; i++){
1980 if(GTK_IS_PLOT3D(plot)){
1981 gtk_plot3d_get_pixel(GTK_PLOT3D(plot),
1982 polygon->xyz[i].x, polygon->xyz[i].y, polygon->xyz[i].z,
1983 &polygon->p[i].x, &polygon->p[i].y, &polygon->p[i].z);
1984 } else {
1985 gtk_plot_get_pixel(plot,
1986 polygon->xyz[i].x, polygon->xyz[i].y,
1987 &polygon->p[i].x, &polygon->p[i].y);
1988 polygon->p[i].z = 0.0;
1989 }
1990 }
1991
1992 list = list->next;
1993 };
1994
1995 GTK_PLOT_SURFACE_CLASS(GTK_OBJECT_GET_CLASS(GTK_OBJECT(surface)))->sort_polygons(surface);
1996
1997 }
1998
1999 static void
gtk_plot_surface_sort_polygons(GtkPlotSurface * surface)2000 gtk_plot_surface_sort_polygons(GtkPlotSurface *surface)
2001 {
2002 if(surface->polygons)
2003 surface->polygons = g_list_sort(surface->polygons, (GCompareFunc)compare_func);
2004 }
2005
2006 /* PAINTER'S COMPARISON */
2007 static gint
compare_func(gpointer a,gpointer b)2008 compare_func (gpointer a, gpointer b)
2009 {
2010 GtkPlotPolygon *pa, *pb;
2011 GtkPlotDTtriangle *ta, *tb;
2012 gint i, j;
2013 gint na[3], nb[3];
2014 gint naz[3], nbz[3];
2015 gdouble pax[3], pbx[3];
2016 gdouble pay[3], pby[3];
2017 gdouble paz[3], pbz[3];
2018 gint xg = 0, xl = 0;
2019 gint yg = 0, yl = 0;
2020 gint zg = 0, zl = 0;
2021 GtkPlotDTnode *nda[3], *ndb[3];
2022 gdouble cza = 0, czb = 0;
2023
2024 pa = (GtkPlotPolygon *)a;
2025 pb = (GtkPlotPolygon *)b;
2026
2027 ta = pa->t;
2028 tb = pb->t;
2029
2030 if(ta == tb) {
2031 gdouble z1, z2;
2032 z1 = pa->p[0].z;
2033 z2 = pb->p[0].z;
2034 for(i = 1; i < pa->n; i++) z1 = MIN(z1, pa->p[i].z);
2035 for(i = 1; i < pb->n; i++) z2 = MIN(z2, pb->p[i].z);
2036 if(z1 == z2)
2037 return (pa->level > pb->level ? -1 : (pa->level == pb->level ? 0 : 1));
2038 else
2039 return (z2 > z1 ? -1 : 1);
2040 }
2041
2042 naz[0] = nbz[0] = 0;
2043 naz[1] = nbz[1] = 1;
2044 naz[2] = nbz[2] = 2;
2045
2046 paz[0] = ta->na->pz;
2047 paz[1] = ta->nb->pz;
2048 paz[2] = ta->nc->pz;
2049 pbz[0] = tb->na->pz;
2050 pbz[1] = tb->nb->pz;
2051 pbz[2] = tb->nc->pz;
2052
2053 /*
2054 paz[0] = pa->p[0].z;
2055 paz[1] = pa->p[1].z;
2056 paz[2] = pa->p[2].z;
2057 if(pa->n == 4) paz[0] = pa->p[3].z;
2058 pbz[0] = pb->p[0].z;
2059 pbz[1] = pb->p[1].z;
2060 pbz[2] = pb->p[2].z;
2061 if(pb->n == 4) pbz[0] = pb->p[3].z;
2062 */
2063
2064 zg = zl = 0;
2065 for(i = 0; i < 3; i++){
2066 for(j = 0; j < 3; j++){
2067 if(paz[i] < pbz[j]) zg++;
2068 if(paz[i] > pbz[j]) zl++;
2069 }
2070 }
2071 if(zg == 9) return 1;
2072 if(zl == 9) return -1;
2073
2074 na[0] = nb[0] = 0;
2075 na[1] = nb[1] = 1;
2076 na[2] = nb[2] = 2;
2077
2078 pax[0] = ta->na->px;
2079 pax[1] = ta->nb->px;
2080 pax[2] = ta->nc->px;
2081 pbx[0] = tb->na->px;
2082 pbx[1] = tb->nb->px;
2083 pbx[2] = tb->nc->px;
2084
2085 /*
2086 pax[0] = pa->p[0].x;
2087 pax[1] = pa->p[1].x;
2088 pax[2] = pa->p[2].x;
2089 if(pa->n == 4) pax[0] = pa->p[3].x;
2090 pbx[0] = pb->p[0].x;
2091 pbx[1] = pb->p[1].x;
2092 pbx[2] = pb->p[2].x;
2093 if(pb->n == 4) pbx[0] = pb->p[3].x;
2094 */
2095
2096 xg = xl = 0;
2097 for(i = 0; i < 3; i++){
2098 for(j = 0; j < 3; j++){
2099 if(pax[i] < pbx[j]) xg++;
2100 if(pax[i] > pbx[j]) xl++;
2101 }
2102 }
2103 if(xg == 9 || xl == 9){
2104 cza = (paz[0] + paz[1] + paz[2]);
2105 czb = (pbz[0] + pbz[1] + pbz[2]);
2106 return(czb > cza ? 1 : -1);
2107 }
2108
2109 na[0] = nb[0] = 0;
2110 na[1] = nb[1] = 1;
2111 na[2] = nb[2] = 2;
2112
2113 pay[0] = ta->na->py;
2114 pay[1] = ta->nb->py;
2115 pay[2] = ta->nc->py;
2116 pby[0] = tb->na->py;
2117 pby[1] = tb->nb->py;
2118 pby[2] = tb->nc->py;
2119
2120 /*
2121 pay[0] = pa->p[0].y;
2122 pay[1] = pa->p[1].y;
2123 pay[2] = pa->p[2].y;
2124 if(pa->n == 4) pay[0] = pa->p[3].y;
2125 pby[0] = pb->p[0].y;
2126 pby[1] = pb->p[1].y;
2127 pby[2] = pb->p[2].y;
2128 if(pb->n == 4) pby[0] = pb->p[3].y;
2129 */
2130
2131 yg = yl = 0;
2132 for(i = 0; i < 3; i++){
2133 for(j = 0; j < 3; j++){
2134 if(pay[i] < pby[j]) yg++;
2135 if(pay[i] > pby[j]) yl++;
2136 }
2137 }
2138 if(yg == 9 || yl == 9){
2139 cza = (paz[0] + paz[1] + paz[2]);
2140 czb = (pbz[0] + pbz[1] + pbz[2]);
2141 return(czb > cza ? 1 : -1);
2142 }
2143
2144 nda[0] = ta->na;
2145 nda[1] = ta->nb;
2146 nda[2] = ta->nc;
2147 ndb[0] = tb->na;
2148 ndb[1] = tb->nb;
2149 ndb[2] = tb->nc;
2150
2151 /*
2152 for(i = 0; i < 3; i++){
2153 gdouble n1[3], n2[3];
2154 gdouble t1, t2, det;
2155 gdouble x1, x2;
2156 gdouble y1, y2;
2157 gdouble z1, z2;
2158 gint ia0 = naz[i];
2159 gint ja0 = naz[i == 2 ? 0 : i+1];
2160 n1[0] = pax[ja0]-pax[ia0];
2161 n1[1] = pay[ja0]-pay[ia0];
2162 n1[2] = paz[ja0]-paz[ia0];
2163
2164 for(j = 0; j < 3; j++){
2165 gint ib0 = nbz[j];
2166 gint jb0 = nbz[j == 2 ? 0 : j+1];
2167 gdouble c1, c2;
2168
2169 c1 = (pax[ia0]-pbx[ib0]);
2170 c2 = (pay[ia0]-pby[ib0]);
2171
2172 n2[0] = pbx[jb0]-pbx[ib0];
2173 n2[1] = pby[jb0]-pby[ib0];
2174 n2[2] = pbz[jb0]-pbz[ib0];
2175 det = (-n1[0]*n2[1]+n1[1]*n2[0]);
2176 if(fabs(det) < 1.e-5){
2177 coincide++;
2178 if(coincide == 2) return 0;
2179 }
2180 }
2181 }
2182 */
2183 for(i = 0; i < 3; i++){
2184 gdouble n1[3], n2[3];
2185 gdouble t1, t2, det;
2186 gdouble x1, x2;
2187 gdouble y1, y2;
2188 gdouble z1, z2;
2189 gint ia0 = naz[i];
2190 gint ja0 = naz[i == 2 ? 0 : i+1];
2191 n1[0] = pax[ja0]-pax[ia0];
2192 n1[1] = pay[ja0]-pay[ia0];
2193 n1[2] = paz[ja0]-paz[ia0];
2194
2195 for(j = 0; j < 3; j++){
2196 gint ib0 = nbz[j];
2197 gint jb0 = nbz[j == 2 ? 0 : j+1];
2198 gdouble c1, c2;
2199
2200 if(nda[ia0] == ndb[ib0] || nda[ia0] == ndb[jb0]) continue;
2201 if(nda[ja0] == ndb[ib0] || nda[ja0] == ndb[jb0]) continue;
2202 c1 = (pax[ia0]-pbx[ib0]);
2203 c2 = (pay[ia0]-pby[ib0]);
2204
2205 n2[0] = pbx[jb0]-pbx[ib0];
2206 n2[1] = pby[jb0]-pby[ib0];
2207 n2[2] = pbz[jb0]-pbz[ib0];
2208 det = (-n1[0]*n2[1]+n1[1]*n2[0]);
2209 if(fabs(det) > 1.e-5){
2210 t1 = (c1*n2[1]-c2*n2[0]) / det;
2211 t2 = (-n1[0]*c2+n1[1]*c1) / det;
2212 if(t1 < -0.0001 || t2 < -0.0001) continue;
2213 if(t1 > 1.0001 || t2 > 1.0001) continue;
2214 x1 = pax[ia0] + t1 * n1[0];
2215 y1 = pay[ia0] + t1 * n1[1];
2216 z1 = paz[ia0] + t1 * n1[2];
2217 x2 = pbx[ib0] + t2 * n2[0];
2218 y2 = pby[ib0] + t2 * n2[1];
2219 z2 = pbz[ib0] + t2 * n2[2];
2220 if(z1 < z2) return 1;
2221 if(z2 < z1) return -1;
2222 }
2223 }
2224 }
2225
2226 cza = (paz[0] + paz[1] + paz[2]);
2227 czb = (pbz[0] + pbz[1] + pbz[2]);
2228 return(czb > cza ? 1 : -1);
2229
2230 return 0;
2231 }
2232
2233
2234