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