This is plnxtv.c in view mode; [Download] [Up]
/* Draws the next view of a 3-d plot. The physical coordinates of */
/* the points for the next view are placed in the n points of arrays */
/* u and v. The silhouette found so far is stored in the heap as a */
/* set of m peak points. */
#include "plplot.h"
#include <stdio.h>
#if defined(PLSTDC) && defined(STDLIB)
#include <stdlib.h>
#else
extern char *malloc();
extern char *realloc();
extern void free();
#endif
/* This routine now dynamically allocates the memory it needs for hidden */
/* line removal. Memory is allocated in blocks of 2*BINC*sizeof(int) */
/* bytes. Large values of BINC give better performance but also */
/* allocate more memory than is needed. If your 3D plots are very */
/* "spiky" or you are working with very large matrices then you will */
/* probably want to increase BINC. */
#define BINC 50
static int *oldhiview;
static int *oldloview;
static int *newhiview;
static int *newloview;
static int mhi, xxhi, newhisize;
static int mlo, xxlo, newlosize;
void goldhivw(ohivw)
int **ohivw;
{
*ohivw = oldhiview;
}
void goldlovw(olovw)
int **olovw;
{
*olovw = oldloview;
}
static int pl3mode=0; /* 0 3d solid; 1 mesh plot */
static int pl3upv=1; /* 1 update view; 0 no update */
void set3mode(mod)
int mod;
{
pl3mode = mod;
}
void set3upd(updm)
int updm;
{
pl3upv = updm;
}
void plnxtv(u, v, n, init)
int *u, *v, n, init;
{
void plnxtvhi(), plnxtvlo();
plnxtvhi(u,v,n,init);
if(pl3mode)
plnxtvlo(u,v,n,init);
}
static void plnxtvhi(u,v,n,init)
int *u, *v, n, init;
{
int i, j, first;
int sx1, sx2, sy1, sy2;
int su1, su2, sv1, sv2;
int cx, cy, px, py;
int seg, ptold, lstold, pthi, pnewhi, newhi, change, ochange;
void savehipoint(), swaphiview();
sy2 = sy1 = sx2 = sx1 = 0;
ochange = lstold = 0;
first = 1;
pnewhi = 0;
/* For the initial set of points, just display them and store them as */
/* the peak points. */
if (init == 1) {
/* heap not yet allocated so ... */
if(!( oldhiview = (int *)malloc(2*n*sizeof(int))))
plexit("Out of memory.");
movphy(u[0],v[0]);
oldhiview[0] = u[0];
oldhiview[1] = v[0];
for (i=1; i<n; i++){
draphy(u[i],v[i]);
oldhiview[2*i] = u[i];
oldhiview[2*i+1] = v[i];
}
mhi = n;
return;
}
/* Otherwise, we need to consider hidden-line removal problem. We scan */
/* over the points in both the old (i.e. oldhiview[]) and */
/* new (i.e. u[] and v[]) arrays in order of increasing x coordinate. */
/* At each stage, we find the line segment in the other array (if one */
/* exists) that straddles the x coordinate of the point. We */
/* have to determine if the point lies above or below the line segment, */
/* and to check if the below/above status has changed since the last */
/* point. */
/* If pl3upv = 0 we do not update the view, this is useful for drawing */
/* lines on the graph after we are done plotting points. Hidden line */
/* removal is still done, but the view is not updated. */
xxhi = 0;
i = 0;
j = 0;
if(pl3upv != 0) {
newhisize = 2*(mhi+BINC);
if(!( newhiview = (int *)malloc(newhisize*sizeof(int)))) {
free((VOID *)oldhiview);
plexit("Out of memory.");
}
}
/* (oldhiview[2*i], oldhiview[2*i]) is the i'th point in the old array */
/* (u[j], v[j]) is the j'th point in the new array */
while (i < mhi || j < n) {
/* The coordinates of the point under consideration are (px,py). */
/* The line segment joins (sx1,sy1) to (sx2,sy2). */
/* "ptold" is true if the point lies in the old array. We set it */
/* by comparing the x coordinates of the i'th old point */
/* and the j'th new point, being careful if we have fallen past */
/* the edges. Having found the point, load up the point and */
/* segment coordinates appropriately. */
ptold = ((oldhiview[2*i] < u[j] && i<mhi) || j>= n);
if (ptold) {
px = oldhiview[2*i];
py = oldhiview[2*i+1];
seg = j>0 && j<n;
if (seg) {
sx1 = u[j-1];
sy1 = v[j-1];
sx2 = u[j];
sy2 = v[j];
}
}
else {
px = u[j];
py = v[j];
seg = i>0 && i<mhi;
if (seg) {
sx1 = oldhiview[2*(i-1)];
sy1 = oldhiview[2*(i-1)+1];
sx2 = oldhiview[2*i];
sy2 = oldhiview[2*i+1];
}
}
/* Now determine if the point is higher than the segment, using the */
/* logical function "above". We also need to know if it is */
/* the old view or the new view that is higher. "newhi" is set true */
/* if the new view is higher than the old */
if(seg)
pthi = plabv(px,py,sx1,sy1,sx2,sy2);
else
pthi = 1;
newhi = (ptold && !pthi) || (!ptold && pthi);
change = (newhi && !pnewhi) || (!newhi && pnewhi);
/* There is a new intersection point to put in the peak array if the */
/* state of "newhi" changes */
if (first) {
movphy(px,py);
first = 0;
lstold = ptold;
savehipoint(px,py);
pthi = 0;
ochange = 0;
}
else if (change) {
/* Take care of special cases at end of arrays. If pl3upv */
/* is 0 the endpoints are not connected to the old view. */
if (pl3upv==0 && ((!ptold && j==0)||(ptold && i==0))) {
movphy(px,py);
lstold = ptold;
pthi = 0;
ochange = 0;
}
else if (pl3upv==0 && ((!ptold && i>=mhi)||(ptold && j>=n))) {
movphy(px,py);
lstold = ptold;
pthi = 0;
ochange = 0;
}
/* If pl3upv is not 0 then we do want to connect the current line */
/* with the previous view at the endpoints. */
/* Also find intersection point with old view. */
else {
if (i == 0) {
sx1 = oldhiview[0];
sy1 = -1;
sx2 = oldhiview[0];
sy2 = oldhiview[1];
}
else if (i >= mhi) {
sx1 = oldhiview[2*(mhi-1)];
sy1 = oldhiview[2*(mhi-1)+1];
sx2 = oldhiview[2*(mhi-1)];
sy2 = -1;
}
else {
sx1 = oldhiview[2*(i-1)];
sy1 = oldhiview[2*(i-1)+1];
sx2 = oldhiview[2*i];
sy2 = oldhiview[2*i+1];
}
if (j == 0) {
su1 = u[0];
sv1 = -1;
su2 = u[0];
sv2 = v[0];
}
else if (j >= n) {
su1 = u[n-1];
sv1 = v[n-1];
su2 = u[n];
sv2 = -1;
}
else {
su1 = u[j-1];
sv1 = v[j-1];
su2 = u[j];
sv2 = v[j];
}
/* Determine the intersection */
pl3cut(sx1,sy1,sx2,sy2,su1,sv1,su2,sv2,&cx,&cy);
if (cx == px && cy == py) {
if (lstold && !ochange)
movphy(px,py);
else
draphy(px,py);
savehipoint(px,py);
lstold = 1;
pthi = 0;
}
else {
if (lstold && !ochange)
movphy(cx,cy);
else
draphy(cx,cy);
lstold = 1;
savehipoint(cx,cy);
}
ochange =1;
}
}
/* If point is high then draw plot to point and update view. */
if (pthi) {
if (lstold && ptold)
movphy(px,py);
else
draphy(px,py);
savehipoint(px,py);
lstold = ptold;
ochange = 0;
}
pnewhi = newhi;
if (ptold)
i = i+1;
else
j = j+1;
}
/* Set oldhiview */
swaphiview();
}
static void savehipoint(px, py)
int px, py;
{
int *temp;
if(pl3upv == 0)
return;
if( xxhi >= newhisize ) {
/* allocate additional space */
newhisize += 2*BINC;
if(!(temp = (int *)realloc((VOID *)newhiview,newhisize*sizeof(int)))) {
free((VOID *)oldhiview);
free((VOID *)newhiview);
plexit("Out of memory.");
}
newhiview = temp;
}
newhiview[xxhi] = px;
xxhi++;
newhiview[xxhi] = py;
xxhi++;
}
static void swaphiview()
{
if(pl3upv != 0) {
mhi = xxhi/2;
free((VOID *)oldhiview);
oldhiview = newhiview;
}
}
static void plnxtvlo(u,v,n,init)
int *u, *v, n, init;
{
int i, j, first;
int sx1, sx2, sy1, sy2;
int su1, su2, sv1, sv2;
int cx, cy, px, py;
int seg, ptold, lstold, ptlo, pnewlo, newlo, change, ochange;
void savelopoint(), swaploview();
sy2 = sy1 = sx2 = sx1 = 0;
ochange = lstold = 0;
first = 1;
pnewlo = 0;
/* For the initial set of points, just display them and store them as */
/* the peak points. */
if (init == 1) {
/* heap not yet allocated so ... */
if(!( oldloview = (int *)malloc(2*n*sizeof(int))))
plexit("Out of memory.");
movphy(u[0],v[0]);
oldloview[0] = u[0];
oldloview[1] = v[0];
for (i=1; i<n; i++){
draphy(u[i],v[i]);
oldloview[2*i] = u[i];
oldloview[2*i+1] = v[i];
}
mlo = n;
return;
}
/* Otherwise, we need to consider hidden-line removal problem. We scan */
/* over the points in both the old (i.e. oldloview[]) and */
/* new (i.e. u[] and v[]) arrays in order of increasing x coordinate. */
/* At each stage, we find the line segment in the other array (if one */
/* exists) that straddles the x coordinate of the point. We */
/* have to determine if the point lies above or below the line segment, */
/* and to check if the below/above status has changed since the last */
/* point. */
/* If pl3upv = 0 we do not update the view, this is useful for drawing */
/* lines on the graph after we are done plotting points. Hidden line */
/* removal is still done, but the view is not updated. */
xxlo = 0;
i = 0;
j = 0;
if(pl3upv != 0) {
newlosize = 2*(mlo+BINC);
if(!( newloview = (int *)malloc(newlosize*sizeof(int)))) {
free((VOID *)oldloview);
plexit("Out of memory.");
}
}
/* (oldloview[2*i], oldloview[2*i]) is the i'th point in the old array */
/* (u[j], v[j]) is the j'th point in the new array */
while (i < mlo || j < n) {
/* The coordinates of the point under consideration are (px,py). */
/* The line segment joins (sx1,sy1) to (sx2,sy2). */
/* "ptold" is true if the point lies in the old array. We set it */
/* by comparing the x coordinates of the i'th old point */
/* and the j'th new point, being careful if we have fallen past */
/* the edges. Having found the point, load up the point and */
/* segment coordinates appropriately. */
ptold = ((oldloview[2*i] < u[j] && i<mlo) || j>= n);
if (ptold) {
px = oldloview[2*i];
py = oldloview[2*i+1];
seg = j>0 && j<n;
if (seg) {
sx1 = u[j-1];
sy1 = v[j-1];
sx2 = u[j];
sy2 = v[j];
}
}
else {
px = u[j];
py = v[j];
seg = i>0 && i<mlo;
if (seg) {
sx1 = oldloview[2*(i-1)];
sy1 = oldloview[2*(i-1)+1];
sx2 = oldloview[2*i];
sy2 = oldloview[2*i+1];
}
}
/* Now determine if the point is lower than the segment, using the */
/* logical function "above". We also need to know if it is */
/* the old view or the new view that is lower. "newlo" is set true */
/* if the new view is lower than the old */
if(seg)
ptlo = !plabv(px,py,sx1,sy1,sx2,sy2);
else
ptlo = 1;
newlo = (ptold && !ptlo) || (!ptold && ptlo);
change = (newlo && !pnewlo) || (!newlo && pnewlo);
/* There is a new intersection point to put in the peak array if the */
/* state of "newlo" changes */
if (first) {
movphy(px,py);
first = 0;
lstold = ptold;
savelopoint(px,py);
ptlo = 0;
ochange = 0;
}
else if (change) {
/* Take care of special cases at end of arrays. If pl3upv */
/* is 0 the endpoints are not connected to the old view. */
if (pl3upv==0 && ((!ptold && j==0)||(ptold && i==0))) {
movphy(px,py);
lstold = ptold;
ptlo = 0;
ochange = 0;
}
else if (pl3upv==0 && ((!ptold && i>=mlo)||(ptold && j>=n))) {
movphy(px,py);
lstold = ptold;
ptlo = 0;
ochange = 0;
}
/* If pl3upv is not 0 then we do want to connect the current line */
/* with the previous view at the endpoints. */
/* Also find intersection point with old view. */
else {
if (i == 0) {
sx1 = oldloview[0];
sy1 = 100000;
sx2 = oldloview[0];
sy2 = oldloview[1];
}
else if (i >= mlo) {
sx1 = oldloview[2*(mlo-1)];
sy1 = oldloview[2*(mlo-1)+1];
sx2 = oldloview[2*(mlo-1)];
sy2 = 100000;
}
else {
sx1 = oldloview[2*(i-1)];
sy1 = oldloview[2*(i-1)+1];
sx2 = oldloview[2*i];
sy2 = oldloview[2*i+1];
}
if (j == 0) {
su1 = u[0];
sv1 = 100000;
su2 = u[0];
sv2 = v[0];
}
else if (j >= n) {
su1 = u[n-1];
sv1 = v[n-1];
su2 = u[n];
sv2 = 100000;
}
else {
su1 = u[j-1];
sv1 = v[j-1];
su2 = u[j];
sv2 = v[j];
}
/* Determine the intersection */
pl3cut(sx1,sy1,sx2,sy2,su1,sv1,su2,sv2,&cx,&cy);
if (cx == px && cy == py) {
if (lstold && !ochange)
movphy(px,py);
else
draphy(px,py);
savelopoint(px,py);
lstold = 1;
ptlo = 0;
}
else {
if (lstold && !ochange)
movphy(cx,cy);
else
draphy(cx,cy);
lstold = 1;
savelopoint(cx,cy);
}
ochange =1;
}
}
/* If point is low then draw plot to point and update view. */
if (ptlo) {
if (lstold && ptold)
movphy(px,py);
else
draphy(px,py);
savelopoint(px,py);
lstold = ptold;
ochange = 0;
}
pnewlo = newlo;
if (ptold)
i = i+1;
else
j = j+1;
}
/* Set oldloview */
swaploview();
}
static void savelopoint(px, py)
int px, py;
{
int *temp;
if(pl3upv == 0)
return;
if( xxlo >= newlosize ) {
/* allocate additional space */
newlosize += 2*BINC;
if(!(temp = (int *)realloc((VOID *)newloview,newlosize*sizeof(int)))) {
free((VOID *)oldloview);
free((VOID *)newloview);
plexit("Out of memory.");
}
newloview = temp;
}
newloview[xxlo] = px;
xxlo++;
newloview[xxlo] = py;
xxlo++;
}
static void swaploview()
{
if(pl3upv != 0) {
mlo = xxlo/2;
free((VOID *)oldloview);
oldloview = newloview;
}
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.