/* $Id: plot3d.c,v 1.3 2007/05/08 09:09:37 rice Exp $ 3d plot routines. Copyright (C) 2004 Alan W. Irwin Copyright (C) 2004 Joao Cardoso Copyright (C) 2004 Andrew Ross This file is part of PLplot. PLplot is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. PLplot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with PLplot; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "plplotP.h" /* Internal constants */ #define BINC 50 /* Block size for memory allocation */ static PLINT pl3mode = 0; /* 0 3d solid; 1 mesh plot */ static PLINT pl3upv = 1; /* 1 update view; 0 no update */ static PLINT zbflg = 0, zbcol, zbwidth; static PLFLT zbtck; static PLINT *oldhiview = NULL; static PLINT *oldloview = NULL; static PLINT *newhiview = NULL; static PLINT *newloview = NULL; static PLINT *utmp = NULL; static PLINT *vtmp = NULL; static PLFLT *ctmp = NULL; static PLINT mhi, xxhi, newhisize; static PLINT mlo, xxlo, newlosize; /* Light source for shading */ static PLFLT xlight, ylight, zlight; static PLINT falsecolor=0; static PLFLT fc_minz, fc_maxz; /* Prototypes for static functions */ static void plgrid3 (PLFLT); static void plnxtv (PLINT *, PLINT *, PLFLT*, PLINT, PLINT); static void plside3 (PLFLT *, PLFLT *, PLFLT **, PLINT, PLINT, PLINT); static void plt3zz (PLINT, PLINT, PLINT, PLINT, PLINT, PLINT *, PLFLT *, PLFLT *, PLFLT **, PLINT, PLINT, PLINT *, PLINT *, PLFLT*); static void plnxtvhi (PLINT *, PLINT *, PLFLT*, PLINT, PLINT); static void plnxtvlo (PLINT *, PLINT *, PLFLT*, PLINT, PLINT); static void plnxtvhi_draw(PLINT *u, PLINT *v, PLFLT* c, PLINT n); static void savehipoint (PLINT, PLINT); static void savelopoint (PLINT, PLINT); static void swaphiview (void); static void swaploview (void); static void myexit (const char *); static void myabort (const char *); static void freework (void); static int plabv (PLINT, PLINT, PLINT, PLINT, PLINT, PLINT); static void pl3cut (PLINT, PLINT, PLINT, PLINT, PLINT, PLINT, PLINT, PLINT, PLINT *, PLINT *); static PLFLT plGetAngleToLight(PLFLT* x, PLFLT* y, PLFLT* z); static void plP_draw3d(PLINT x, PLINT y, PLFLT *c, PLINT j, PLINT move); /* pmr: not used ... removed static */ void plxyindexlimits(PLINT instart, PLINT inn, PLINT *inarray_min, PLINT *inarray_max, PLINT *outstart, PLINT *outn, PLINT outnmax, PLINT *outarray_min, PLINT *outarray_max); /* #define MJL_HACK 1 */ #ifdef MJL_HACK #if MJL_HACK static void plP_fill3(PLINT x0, PLINT y0, PLINT x1, PLINT y1, PLINT x2, PLINT y2, PLINT j); static void plP_fill4(PLINT x0, PLINT y0, PLINT x1, PLINT y1, PLINT x2, PLINT y2, PLINT x3, PLINT y3, PLINT j); #endif #endif /*--------------------------------------------------------------------------*\ * void plsetlightsource(x, y, z) * * Sets the position of the light source. \*--------------------------------------------------------------------------*/ void c_pllightsource(PLFLT x, PLFLT y, PLFLT z) { xlight = x; ylight = y; zlight = z; } /*--------------------------------------------------------------------------*\ * void plmesh(x, y, z, nx, ny, opt) * * Plots a mesh representation of the function z[x][y]. The x values * are stored as x[0..nx-1], the y values as y[0..ny-1], and the * z values are in the 2-d array z[][]. The integer "opt" specifies: * see plmeshc() below. \*--------------------------------------------------------------------------*/ void c_plmesh(PLFLT *x, PLFLT *y, PLFLT **z, PLINT nx, PLINT ny, PLINT opt) { c_plot3dc(x, y, z, nx, ny, opt | MESH, NULL, 0); } /*--------------------------------------------------------------------------*\ * void plmeshc(x, y, z, nx, ny, opt, clevel, nlevel) * * Plots a mesh representation of the function z[x][y]. The x values * are stored as x[0..nx-1], the y values as y[0..ny-1], and the * z values are in the 2-d array z[][]. The integer "opt" specifies: * * DRAW_LINEX draw lines parallel to the X axis * DRAW_LINEY draw lines parallel to the Y axis * DRAW_LINEXY draw lines parallel to both the X and Y axis * MAG_COLOR draw the mesh with a color dependent of the magnitude * BASE_CONT draw contour plot at bottom xy plane * TOP_CONT draw contour plot at top xy plane (not yet) * DRAW_SIDES draw sides * * or any bitwise combination, e.g. "MAG_COLOR | DRAW_LINEX" * \*--------------------------------------------------------------------------*/ void c_plmeshc(PLFLT *x, PLFLT *y, PLFLT **z, PLINT nx, PLINT ny, PLINT opt, PLFLT *clevel, PLINT nlevel) { c_plot3dc(x, y, z, nx, ny, opt | MESH, clevel, nlevel); } /* clipping helper for 3d polygons */ int plP_clip_poly(int Ni, PLFLT *Vi[3], int axis, PLFLT dir, PLFLT offset) { int anyout = 0; PLFLT in[PL_MAXPOLY], T[3][PL_MAXPOLY]; int No = 0; int i, j, k; for(i=0; i=0 && in[j]>=0) { for(k=0; k<3; k++) Vi[k][No] = T[k][j]; No++; } else if(in[i]>=0 && in[j]<0) { PLFLT u = in[i] / (in[i] - in[j]); for(k = 0; k<3; k++) Vi[k][No] = T[k][i]*(1-u) + T[k][j]*u; No++; } else if(in[i]<0 && in[j]>=0) { PLFLT u = in[i] / (in[i] - in[j]); for(k = 0; k<3; k++) Vi[k][No] = T[k][i]*(1-u) + T[k][j]*u; No++; for(k=0; k<3; k++) Vi[k][No] = T[k][j]; No++; } } return No; } /* helper for plsurf3d, similar to c_plfill3() */ static void shade_triangle(PLFLT xx0, PLFLT yy0, PLFLT zz0, PLFLT xx1, PLFLT yy1, PLFLT zz1, PLFLT xx2, PLFLT yy2, PLFLT zz2) { int i; /* arrays for interface to core functions */ short u[6], v[6]; PLFLT x[6], y[6], z[6]; int n; PLFLT xmin, xmax, ymin, ymax, zmin, zmax, zscale; PLFLT *V[3]; plP_gdom(&xmin, &xmax, &ymin, &ymax); plP_grange(&zscale, &zmin, &zmax); x[0] = xx0; x[1] = xx1; x[2] = xx2; y[0] = yy0; y[1] = yy1; y[2] = yy2; z[0] = zz0; z[1] = zz1; z[2] = zz2; n = 3; V[0] = x; V[1] = y; V[2] = z; n = plP_clip_poly(n, V, 0, 1, -xmin); n = plP_clip_poly(n, V, 0, -1, xmax); n = plP_clip_poly(n, V, 1, 1, -ymin); n = plP_clip_poly(n, V, 1, -1, ymax); n = plP_clip_poly(n, V, 2, 1, -zmin); n = plP_clip_poly(n, V, 2, -1, zmax); if(n > 0) { if (falsecolor) plcol1(((z[0] + z[1] + z[2]) /3. - fc_minz) / (fc_maxz - fc_minz)); else plcol1(plGetAngleToLight(x, y, z)); for(i=0; i