open-axiom repository from github
/*1Copyright (c) 1991-2002, The Numerical Algorithms Group Ltd.2All rights reserved.3Copyright (C) 2007-2010, Gabriel Dos Reis.4All rights reserved.56Redistribution and use in source and binary forms, with or without7modification, are permitted provided that the following conditions are8met:910- Redistributions of source code must retain the above copyright11notice, this list of conditions and the following disclaimer.1213- Redistributions in binary form must reproduce the above copyright14notice, this list of conditions and the following disclaimer in15the documentation and/or other materials provided with the16distribution.1718- Neither the name of The Numerical Algorithms Group Ltd. nor the19names of its contributors may be used to endorse or promote products20derived from this software without specific prior written permission.2122THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS23IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED24TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A25PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER26OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,27EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,28PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR29PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF30LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING31NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS32SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.33*/3435#define _COMPONENT3D_C36#include "openaxiom-c-macros.h"3738#include "header.h"39#include "draw.h"4041#include "Gfun.H1"42#include "util.H1"43#include "XSpadFill.h"4445#include "all_3d.H1"4647#define axisLength 1.0 /* use 100.0, if data is not to be normalized */4849#define samePoint(a,b) ((refPt3D(viewData,a)->x == refPt3D(viewData,b)->x) &&\50(refPt3D(viewData,a)->y == refPt3D(viewData,b)->y) &&\51(refPt3D(viewData,a)->z == refPt3D(viewData,b)->z))52#define MAX_POINT 1000.053#define MIN_POINT -1000.0545556void57scaleComponents (void)58{5960double xRange,yRange,zRange;61int i;62viewTriple *aPoint;6364/* Temporary range limits until the three dimensional clipping65package is fully functional */6667if (viewData.xmin < MIN_POINT) viewData.xmin = MIN_POINT;68if (viewData.xmax > MAX_POINT) viewData.xmax = MAX_POINT;69if (viewData.ymin < MIN_POINT) viewData.ymin = MIN_POINT;70if (viewData.ymax > MAX_POINT) viewData.ymax = MAX_POINT;71if (viewData.zmin < MIN_POINT) viewData.zmin = MIN_POINT;72if (viewData.zmax > MAX_POINT) viewData.zmax = MAX_POINT;7374xRange = viewData.xmax - viewData.xmin;75yRange = viewData.ymax - viewData.ymin;76zRange = viewData.zmax - viewData.zmin;7778/* We scale down, normalize the data, if it is coming from OpenAxiom79(handled by viewman). If the data is coming from a file (handled by80viewAlone) then it should already been scaled down.81*/8283/* Find the coordinate axis with the larges range of data and scale84the others relative to it.85*/86/* compare x and y ranges */87if (xRange > yRange) {88if (xRange > zRange) {89if (absolute(viewData.xmax) >= absolute(viewData.xmin))90viewData.scaleToView = axisLength/(absolute(viewData.xmax));91else92viewData.scaleToView = axisLength/(absolute(viewData.xmin));93} else {94if (absolute(viewData.zmax) >= absolute(viewData.zmin))95viewData.scaleToView = axisLength/(absolute(viewData.zmax));96else97viewData.scaleToView = axisLength/(absolute(viewData.zmin));98}99} else {100if (yRange > zRange) {101if (absolute(viewData.ymax) >= absolute(viewData.ymin))102viewData.scaleToView = axisLength/(absolute(viewData.ymax));103else104viewData.scaleToView = axisLength/(absolute(viewData.ymin));105} else {106if (absolute(viewData.zmax) >= absolute(viewData.zmin))107viewData.scaleToView = axisLength/(absolute(viewData.zmax));108else109viewData.scaleToView = axisLength/(absolute(viewData.zmin));110}111}112113/* We now normalize all the points in this program. The information114needed to link the normalized set of points back to the real object115space scale created in OpenAxiom is held in viewData.scaleToView. */116viewData.xmin *= viewData.scaleToView;117viewData.xmax *= viewData.scaleToView;118viewData.ymin *= viewData.scaleToView;119viewData.ymax *= viewData.scaleToView;120viewData.zmin *= viewData.scaleToView;121viewData.zmax *= viewData.scaleToView;122viewData.clipXmin = viewData.xmin;123viewData.clipXmax = viewData.xmax;124viewData.clipYmin = viewData.ymin;125viewData.clipYmax = viewData.ymax;126viewData.clipZmin = viewData.zmin;127viewData.clipZmax = viewData.zmax;128129for (i=0, aPoint=viewData.points; i<viewData.numOfPoints; i++,aPoint++) {130aPoint->x *= viewData.scaleToView;131aPoint->y *= viewData.scaleToView;132aPoint->z *= viewData.scaleToView;133}134135} /* scaleComponents() */136137138/*139void makeTriangle(a,b,c)140Given three indices to three points, a triangular polygon is created141and inserted into the polygon list of viewData. If two or more of the142points are coincidental, no polygon is created since that would be a143degenerate (collapsed) polygon.144*/145146void147makeTriangle (int a, int b, int c)148{149poly *aPoly;150151if (!(samePoint(a,b) || samePoint(b,c) || samePoint(c,a))) {152/* create triangle only if the three vertex points are distinct */153aPoly = (poly *)saymem("component.c",1,sizeof(poly));154aPoly->num = aPoly->sortNum = viewData.numPolygons++;155aPoly->split = aPoly->moved = no;156aPoly->numpts = 3;157aPoly->primitiveType = polygonComponent;158aPoly->indexPtr = (int *)saymem("component.c",3,sizeof(int));159*(aPoly->indexPtr) = a;160*(aPoly->indexPtr + 1) = b;161*(aPoly->indexPtr + 2) = c;162aPoly->doNotStopDraw = yes;163aPoly->next = viewData.polygons;164viewData.polygons = aPoly;165} /* if all points are unique */166167} /* makeTriangle() */168169170171172/*173void triangulate()174175Only if there is more than one list do we triangulate; a single list176is used for either a space curve or simply a point. Actually, in that177case, we now make "flat" *polygons, flagged by the primitiveType field178(pointComponent, etc. in tube.h). We need to examine two lists at a time179(and if the structure is closed, the last and first as well). For every180three points in the two lists, alternating between one in one and two in181the other, we construct triangles. If one list is shorter, then its last182point becomes the vertex for the remaining pairs of points from the other183list. It turns out that any distribution of points in the two lists184(preserving cyclic order) will produce the same desired polygon.185*/186187void188triangulate (void)189{190191int u,l;192int uBound,lBound;193int i,j,k;194LLPoint *anLLPoint;195LPoint *list1,*list2;196poly *aPoly;197198anLLPoint = viewData.lllp.llp;199for (i=0; i<viewData.lllp.numOfComponents; i++,anLLPoint++) {200if (anLLPoint->numOfLists > 1) {201list2 = anLLPoint->lp;202for (j=1; j<anLLPoint->numOfLists; j++) {203list1 = list2;204list2 = list1 + 1;205u = l = 0;206uBound = u+1 < list1->numOfPoints;207lBound = l+1 < list2->numOfPoints;208while (uBound || lBound) {209if (uBound) {210makeTriangle(*(list1->indices + u + 1),211*(list1->indices + u), *(list2->indices + l));212u++;213uBound = u+1 < list1->numOfPoints;214}215if (lBound) {216makeTriangle(*(list2->indices + l),217*(list2->indices + l + 1), *(list1->indices + u));218l++;219lBound = l+1 < list2->numOfPoints;220}221} /* while (uBound || lBound) */222} /* for j<anLLPoint->numOfLists */223} /* if anLLPoint->numOfLists > 1 */224else {225/* if anLLPoint->numOfLists <= 1...assume this means =1 */226/* Flat polygons are to be drawn when hidden227surface algorithm is used.*/228if (anLLPoint->numOfLists == 1) {229if (anLLPoint->lp->numOfPoints == 1) {230/* this graph is a single point */231aPoly = (poly *)saymem("component.c",1,sizeof(poly));232aPoly->num = aPoly->sortNum = viewData.numPolygons++;233aPoly->split = aPoly->moved = no;234aPoly->primitiveType = pointComponent;235aPoly->numpts = 1;236aPoly->indexPtr = (int *)saymem("component.c",1,intSize);237*(aPoly->indexPtr) = *(anLLPoint->lp->indices);238aPoly->doNotStopDraw = yes;239aPoly->next = viewData.polygons;240viewData.polygons = aPoly;241} else {242/* this graph is a curve */243for (k=0; k<anLLPoint->lp->numOfPoints-1; k++) {244aPoly = (poly *)saymem("component.c",1,sizeof(poly));245aPoly->num = aPoly->sortNum = viewData.numPolygons++;246aPoly->split = aPoly->moved = no;247aPoly->primitiveType = lineComponent; /* curveComponent */248aPoly->numpts = 2;249aPoly->indexPtr =250(int *)saymem("component.c",2,sizeof(int));251*(aPoly->indexPtr) = *(anLLPoint->lp->indices + k);252*(aPoly->indexPtr+1) = *(anLLPoint->lp->indices + k + 1);253aPoly->doNotStopDraw = yes;254aPoly->next = viewData.polygons;255viewData.polygons = aPoly;256} /* for k */257if (anLLPoint->lp->prop.closed) {258aPoly = (poly *)saymem("component.c",1,sizeof(poly));259aPoly->num = aPoly->sortNum = viewData.numPolygons++;260aPoly->split = aPoly->moved = no;261aPoly->primitiveType = lineComponent; /* curveComponent */262aPoly->numpts = 2;263aPoly->indexPtr =264(int *)saymem("component.c",2,sizeof(int));265*(aPoly->indexPtr) = *(anLLPoint->lp->indices + k);266*(aPoly->indexPtr+1) = *(anLLPoint->lp->indices);267aPoly->doNotStopDraw = yes;268aPoly->next = viewData.polygons;269viewData.polygons = aPoly;270} /* if list of points is closed */271} /* else */272} /* point, line, polygon, surface components are taken care of above */273} /* else anLLPoint->numOfLists <= 1 */274} /* for LLPoints in LLLPoints (i) */275276} /* triangulate */277278279280void281readComponentsFromViewman (void)282{283int i,j,k;284LLPoint *anLLPoint;285LPoint *anLPoint;286viewTriple *aPoint;287/* maxLength holds the max(llp,lp) figure regarding how large to288make the array of XPoints, i.e. quadMesh, for use in calling XDraw(). */289int maxLength=0;290291int *anIndex;292293readViewman(&(viewData.numOfPoints),intSize);294aPoint = viewData.points =295(viewTriple *)saymem("component.c",viewData.numOfPoints,296sizeof(viewTriple));297for (i=0; i<viewData.numOfPoints; i++, aPoint++) {298readViewman(&(aPoint->x),floatSize);299readViewman(&(aPoint->y),floatSize);300readViewman(&(aPoint->z),floatSize);301readViewman(&(aPoint->c),floatSize);302#ifdef NANQ_DEBUG303if (!(aPoint->z < 0) && !(aPoint->z > 0) && !(aPoint->z == 0))304fprintf(stderr,"%g\n", aPoint->z);305#endif306}307308readViewman(&(viewData.lllp.numOfComponents),intSize);309anLLPoint = viewData.lllp.llp =310(LLPoint *)saymem("component.c, i",viewData.lllp.numOfComponents,311sizeof(LLPoint));312for (i=0; i<viewData.lllp.numOfComponents; i++,anLLPoint++) {313readViewman(&(anLLPoint->prop.closed),intSize);314readViewman(&(anLLPoint->prop.solid),intSize);315readViewman(&(anLLPoint->numOfLists),intSize);316anLPoint = anLLPoint->lp =317(LPoint *)saymem("component.c, ii",anLLPoint->numOfLists,318sizeof(LPoint));319for (j=0; j<anLLPoint->numOfLists; j++,anLPoint++) {320if (anLLPoint->numOfLists > maxLength)321maxLength = anLLPoint->numOfLists;322readViewman(&(anLPoint->prop.closed),intSize);323readViewman(&(anLPoint->prop.solid),intSize);324readViewman(&(anLPoint->numOfPoints),intSize);325anIndex = anLPoint->indices =326(int *)saymem("component.c, index",anLPoint->numOfPoints,intSize);327if (anLPoint->numOfPoints > maxLength)328maxLength = anLPoint->numOfPoints;329for (k=0; k<anLPoint->numOfPoints; k++,anIndex++) {330readViewman(anIndex,intSize);331/* OpenAxiom arrays are one based, C arrays are zero based */332if (!viewAloned) (*anIndex)--;333}334} /* for LPoints in LLPoints (j) */335} /* for LLPoints in LLLPoints (i) */336337quadMesh = (XPoint *)saymem("component.c",maxLength+2,sizeof(XPoint));338339} /* readComponentsFromViewman() */340341342343/*344void calcNormData() *345Calculates the surface normals for the polygons that make up the tube.346Also finds the fourth coefficient to the plane equation:347Ax + By + Cz + D = 0348A,B, and C are in the normal N[3] and D is the planeConst.349Figures out the color as well (from the average of the points) and350resets the moved flag351*/352353void354calcNormData (void)355{356357poly *aPoly;358int *index;359360for (aPoly = viewData.polygons; aPoly != NIL(poly); aPoly = aPoly->next) {361index = aPoly->indexPtr;362switch (aPoly->primitiveType) {363case pointComponent:364case lineComponent:365aPoly->moved = 0;366aPoly->color = refPt3D(viewData,*index)->c;367break;368default:369/*370The following line takes 3 consecutive points and asks371for the normal vector defined by them. This assumes that372these do not contain co-linear points. For some reason,373co-linear points are allowed, this needs to be changed.374*/375getMeshNormal(refPt3D(viewData,*index)->x,376refPt3D(viewData,*index)->y,377refPt3D(viewData,*index)->z,378refPt3D(viewData,*(index+1))->x,379refPt3D(viewData,*(index+1))->y,380refPt3D(viewData,*(index+1))->z,381refPt3D(viewData,*(index+2))->x,382refPt3D(viewData,*(index+2))->y,383refPt3D(viewData,*(index+2))->z, 0.0, 1.0, aPoly->N);384385/* calculate the constant term, D, for the plane equation */386aPoly->planeConst =387-(aPoly->N[0] * refPt3D(viewData,*index)->x +388aPoly->N[1] * refPt3D(viewData,*index)->y +389aPoly->N[2] * refPt3D(viewData,*index)->z);390aPoly->moved = 0;391aPoly->color = (refPt3D(viewData,*index)->c +392(refPt3D(viewData,*(index+1)))->c +393(refPt3D(viewData,*(index+2)))->c) / 3.0;394break;395} /* switch */396}397398} /* calcNormData() */399400401402/*403viewPoints *make3DComponents()404405Read in all the 3D data from the viewport manager and construct the406model of it. The model is based upon a list of lists of lists of points.407Each top level list makes a component in 3-space. The interpretation408really begins at the level below that, where the list of lists of409points is. For 3D explicit equations of two variables, the closed410boolean for this level is False and the closed boolean for each sublist411is False as well. For 3D parameterized curves of one variable, the412closed boolean for this level is defined by the user from OpenAxiom ,413(which defaults to False) and the closed boolean for each sublist is True.414*/415416viewPoints *417make3DComponents (void)418{419viewPoints *graphData;420421readComponentsFromViewman();422423/* The initial boundaries for the clipping region are set to those424of the boundaries of the data region. */425viewData.clipXmin = viewData.xmin; viewData.clipXmax = viewData.xmax;426viewData.clipYmin = viewData.ymin; viewData.clipYmax = viewData.ymax;427viewData.clipZmin = viewData.zmin; viewData.clipZmax = viewData.zmax;428429/* normalize the data coordinates */430if (viewData.scaleDown) scaleComponents();431viewData.numPolygons = 0;432/* initially the list of polygons is empty */433viewData.polygons = NIL(poly);434/* create the polygons; (sets viewData.polygons and viewData.numPolygons) */435triangulate();436/* calculate the plane equations for all the polygons */437calcNormData();438439graphData = makeViewport();440441imageX = XCreateImage(/* display */ dsply,442/* visual */ DefaultVisual(dsply,scrn),443/* depth */ DefaultDepth(dsply,scrn),444/* format */ ZPixmap,445/* offset */ 0,446/* data */ NULL,447/* width */ vwInfo.width,448/* height */ 1,449/* bitmap_pad */ 32,450/* bytes_per_line */ 0);451imageX->data = NIL(char);452453/* windowing displaying */454writeTitle();455postMakeViewport();456drawViewport(Xoption);457firstTime = yes;458XMapWindow(dsply, graphData->viewWindow);459XMapWindow(dsply, graphData->titleWindow);460XFlush(dsply);461462return(graphData);463464} /* make3DComponents */465466467468469470void471draw3DComponents (int dFlag)472{473474int i, j, k, hue, x1, y1, x2, y2;475LLPoint *anLLPoint;476LPoint *anLPoint;477int *anIndex;478int componentType; /* what the component is to be interpreted as */479int clip_a,clip_i; /* for use in wire mesh mode clipping */480XEvent peekEvent;481viewTriple *aLPt;482XPoint line[2];483RGB col_rgb;484485calcEyePoint();486while ((XPending(dsply) > 0) && (scanline > 0))487XNextEvent(dsply,&peekEvent);488switch (viewData.style) {489490case transparent:491GSetLineAttributes(componentGC,0,LineSolid,CapButt,JoinMiter,dFlag);492if (dFlag==Xoption) {493if (mono || viewport->monoOn)494GSetForeground(componentGC, (float)foregroundColor, dFlag);495else496GSetForeground(componentGC, (float) meshOutline, dFlag);497} else {498GSetForeground(componentGC, psBlack, dFlag);499}500/* no need to check "keep drawing" for ps */501if (dFlag == Xoption) drawMore = keepDrawingViewport();502503/*504This is where we interpret the list of lists of lists of points struct.505We want to extract the following forms of data:506- individual points (drawn as filled points)507- lines (space curves)508- defined polygon primitives509- surfaces510the last one is the one that will replace the function of 2 variables,511tubes as well as 3D parameterized functions of 2 variables.512Since there could be many other ways of constructing L L L Pts - much513more than could be usefully interpreted - any other formats are514currently not allowed. When they are, this comment should be updated515appropriately.516517************************************************************************518519Traverse each component.520We decide here, before we begin traversing the521component what we want to interpret it as.522Here's the convention used to figure that out:523- points: #anLLPoint->numOfLists was 1524#anLPoint->numOfPoints is 1525- lines: #anLLPoint->numOfLists was 1526#anLPoint->numOfPoints > 1527- polygons: #anLLPoint->numOfLists was 2528#anLPoint->numOfPoints is 1529- surface: #anLLPoint->numOfLists was some m>1530#anLPoint->numOfPoints all point lists are the same.531532*/533534anLLPoint = viewData.lllp.llp;535for (i=0; i<viewData.lllp.numOfComponents; i++,anLLPoint++) {536/* initially, component type is unknown */537componentType = stillDontKnow;538if (anLLPoint->numOfLists == 1) {539if (anLLPoint->lp->numOfPoints == 1) componentType = pointComponent;540else componentType = lineComponent;541} else if (anLLPoint->numOfLists == 2) {542if ((anLLPoint->lp->numOfPoints == 1) &&543((anLLPoint->lp+1)->numOfPoints > 2))544componentType = polygonComponent;545}546/* Check for corrupt data and NaN data is made in OpenAxiom . */547if (componentType == stillDontKnow)548componentType = surfaceComponent;549550anLPoint = anLLPoint->lp;551552switch (componentType) {553554case pointComponent:555/* anLLPoint->numOfLists == anLLPoint->lp->numOfPoints == 1 here */556aLPt = refPt3D(viewData,*(anLPoint->indices));557project(aLPt,quadMesh,0);558if (dFlag==Xoption) {559if (mono || viewport->monoOn)560GSetForeground(componentGC, (float)foregroundColor, dFlag);561else {562hue = hueValue(aLPt->c);563GSetForeground(componentGC, (float)XSolidColor(hue,2), dFlag);564}565} else GSetForeground(componentGC, psBlack, dFlag);566GFillArc(componentGC,viewport->viewWindow,quadMesh->x,quadMesh->y,567viewData.pointSize,viewData.pointSize,0,360*64,dFlag);568break;569570case lineComponent:571/* anLLPoint->numOfLists == 1 here */572anIndex = anLPoint->indices;573aLPt = refPt3D(viewData,*anIndex);574project(aLPt,quadMesh,0);575x1 = quadMesh[0].x; y1 = quadMesh[0].y; anIndex++;576for (k=1; k<anLPoint->numOfPoints; k++,anIndex++) {577aLPt = refPt3D(viewData,*anIndex);578project(aLPt,quadMesh,k);579x2 = quadMesh[k].x; y2 = quadMesh[k].y;580if (dFlag==Xoption) {581if (mono || viewport->monoOn)582GSetForeground(componentGC, (float)foregroundColor, dFlag);583else {584hue = hueValue(aLPt->c);585GSetForeground(componentGC, (float)XSolidColor(hue,2), dFlag);586}587if (!eqNANQ(x1) && !eqNANQ(y1) && !eqNANQ(x2) && !eqNANQ(y2))588GDrawLine(componentGC,viewport->viewWindow,x1,y1,x2,y2,dFlag);589} else {590if (dFlag==PSoption && !mono && !viewport->monoOn) {591hue = getHue(aLPt->c);592col_rgb = hlsTOrgb((float)hue,0.5,0.8);593line[0].x = x1; line[0].y = y1;594line[1].x = x2; line[1].y = y2;595PSDrawColor(col_rgb.r,col_rgb.g,col_rgb.b,line,2);596} else {597if (foregroundColor == white)598GSetForeground(componentGC, 0.0, dFlag);599else600GSetForeground(componentGC, psBlack, dFlag);601if (!eqNANQ(x1) && !eqNANQ(y1) && !eqNANQ(x2) && !eqNANQ(y2))602GDrawLine(componentGC,viewport->viewWindow,x1,y1,x2,y2,dFlag);603}604}605x1 = x2; y1 = y2;606} /* for points in LPoints (k) */607if (anLPoint->prop.closed) {608project(refPt3D(viewData,*(anLPoint->indices)),quadMesh,609anLPoint->numOfPoints);610x2 = quadMesh[anLPoint->numOfPoints].x;611y2 = quadMesh[anLPoint->numOfPoints].y;612if (dFlag==Xoption) {613if (mono || viewport->monoOn)614GSetForeground(componentGC, (float)foregroundColor, dFlag);615else {616hue = hueValue(aLPt->c);617GSetForeground(componentGC, (float)XSolidColor(hue,2), dFlag);618}619if (!eqNANQ(x1) && !eqNANQ(y1) && !eqNANQ(x2) && !eqNANQ(y2))620GDrawLine(componentGC,viewport->viewWindow,x1,y1,x2,y2,dFlag);621}622else {623if (dFlag==PSoption && !mono && !viewport->monoOn) {624hue = getHue(aLPt->c);625col_rgb = hlsTOrgb((float)hue,0.5,0.8);626line[0].x = x1; line[0].y = y1;627line[1].x = x2; line[1].y = y2;628PSDrawColor(col_rgb.r,col_rgb.g,col_rgb.b,line,2);629}630else {631if (foregroundColor == white)632GSetForeground(componentGC, 0.0, dFlag);633else634GSetForeground(componentGC, psBlack, dFlag);635if (!eqNANQ(x1) && !eqNANQ(y1) && !eqNANQ(x2) && !eqNANQ(y2))636GDrawLine(componentGC,viewport->viewWindow,x1,y1,x2,y2,dFlag);637}638}639}640break;641642case polygonComponent:643/* first pt of polygon is a single list */644project(refPt3D(viewData,*(anLPoint->indices)),quadMesh,0);645/* remaining points in the 2nd list (always of size 2 or greater) */646x1 = quadMesh[0].x; y1 = quadMesh[0].y;647anLPoint = anLLPoint->lp + 1;648anIndex = anLPoint->indices;649for (k=1; k<=anLPoint->numOfPoints; k++,anIndex++) {650aLPt = refPt3D(viewData,*anIndex);651project(aLPt,quadMesh,k);652x2 = quadMesh[k].x; y2 = quadMesh[k].y;653if (dFlag==Xoption) {654if (mono || viewport->monoOn)655GSetForeground(componentGC, (float)foregroundColor, dFlag);656else {657hue = hueValue(aLPt->c);658GSetForeground(componentGC, (float)XSolidColor(hue,2), dFlag);659}660if (!eqNANQ(x1) && !eqNANQ(y1) && !eqNANQ(x2) && !eqNANQ(y2))661GDrawLine(componentGC,viewport->viewWindow,x1,y1,x2,y2,dFlag);662}663else {664if (dFlag==PSoption && !mono && !viewport->monoOn) {665hue = getHue(aLPt->c);666col_rgb = hlsTOrgb((float)hue,0.5,0.8);667line[0].x = x1; line[0].y = y1;668line[1].x = x2; line[1].y = y2;669PSDrawColor(col_rgb.r,col_rgb.g,col_rgb.b,line,2);670}671else {672if (foregroundColor == white)673GSetForeground(componentGC, 0.0, dFlag);674else675GSetForeground(componentGC, psBlack, dFlag);676if (!eqNANQ(x1) && !eqNANQ(y1) && !eqNANQ(x2) && !eqNANQ(y2))677GDrawLine(componentGC,viewport->viewWindow,x1,y1,x2,y2,dFlag);678}679}680x1 = x2; y1 = y2;681} /* for points in LPoints (k) */682project(refPt3D(viewData,*(anLLPoint->lp->indices)),quadMesh,k);683x2 = quadMesh[k].x; y2 = quadMesh[k].y;684if (dFlag==Xoption) {685if (mono || viewport->monoOn)686GSetForeground(componentGC, (float)foregroundColor, dFlag);687else {688hue = hueValue(refPt3D(viewData,*anIndex)->c);689GSetForeground(componentGC, (float)XSolidColor(hue,2), dFlag);690}691if (!eqNANQ(x1) && !eqNANQ(y1) && !eqNANQ(x2) && !eqNANQ(y2))692GDrawLine(componentGC,viewport->viewWindow,x1,y1,x2,y2,dFlag);693} else {694if (dFlag==PSoption && !mono && !viewport->monoOn) {695hue = getHue(refPt3D(viewData,*anIndex)->c);696col_rgb = hlsTOrgb((float)hue,0.5,0.8);697line[0].x = x1; line[0].y = y1;698line[1].x = x2; line[1].y = y2;699PSDrawColor(col_rgb.r,col_rgb.g,col_rgb.b,line,2);700}701else {702if (foregroundColor == white)703GSetForeground(componentGC, 0.0, dFlag);704else705GSetForeground(componentGC, psBlack, dFlag);706if (!eqNANQ(x1) && !eqNANQ(y1) && !eqNANQ(x2) && !eqNANQ(y2))707GDrawLine(componentGC,viewport->viewWindow,x1,y1,x2,y2,dFlag);708}709}710/* close a polygon */711break;712713case surfaceComponent:714if (dFlag==Xoption) {715if (mono || viewport->monoOn)716GSetForeground(componentGC, (float)foregroundColor, dFlag);717else718GSetForeground(componentGC, (float) meshOutline, dFlag);719}720else {721GSetForeground(componentGC, psBlack, dFlag);722}723724/* traverse down one direction first (all points725in a list at a time) */726for (j=0; drawMore && j<anLLPoint->numOfLists; j++,anLPoint++) {727anIndex = anLPoint->indices;728clip_a = 0;729for (k=0, clip_i=0;730drawMore && k<anLPoint->numOfPoints;731k++, anIndex++, clip_i++) {732aLPt = refPt3D(viewData,*anIndex);733project(aLPt,quadMesh,k);734735if (behindClipPlane(aLPt->pz) ||736(viewData.clipStuff &&737outsideClippedBoundary(aLPt->x, aLPt->y, aLPt->z))) {738if (clip_i - clip_a > 1) {739GDrawLines(componentGC,viewport->viewWindow,(quadMesh+clip_a),740clip_i-clip_a, CoordModeOrigin, dFlag );741}742clip_a = clip_i + 1;743}744745drawMore = keepDrawingViewport();746} /* for points in LPoints (k) */747if (drawMore) {748/* if drawMore is true, then the above loop terminated with749clip_i incremented properly */750if (anLPoint->prop.closed) {751/* If closed, then do the first point again - no need to project752just copy over from the first one */753aLPt = refPt3D(viewData,*(anLPoint->indices));754project(aLPt,quadMesh, anLPoint->numOfPoints);755if (behindClipPlane(aLPt->pz) ||756(viewData.clipStuff &&757outsideClippedBoundary(aLPt->x, aLPt->y, aLPt->z))) {758if (clip_i - clip_a > 1) {759GDrawLines(componentGC, viewport->viewWindow,760(quadMesh+clip_a), clip_i-clip_a,761CoordModeOrigin, dFlag);762}763clip_a = clip_i + 1;764}765clip_i++;766} /* closed */767if (clip_i - clip_a > 1) {768GDrawLines(componentGC, viewport->viewWindow, (quadMesh+clip_a),769clip_i-clip_a, CoordModeOrigin, dFlag);770}771} /* drawMore */772} /* for LPoints in LLPoints (j) */773774/* now traverse down the list in the other direction775(one point from each list at a time) */776for (j=0; drawMore && j<anLLPoint->lp->numOfPoints; j++) {777clip_a = 0;778for (k=0, clip_i=0;779drawMore && k<anLLPoint->numOfLists;780k++, clip_i++) {781aLPt = refPt3D(viewData,*((anLLPoint->lp + k)->indices + j));782project(aLPt, quadMesh,k);783784if (behindClipPlane(aLPt->pz) ||785(viewData.clipStuff &&786outsideClippedBoundary(aLPt->x, aLPt->y, aLPt->z))) {787if (clip_i - clip_a > 1) {788GDrawLines(componentGC,viewport->viewWindow,quadMesh+clip_a,789clip_i-clip_a, CoordModeOrigin, dFlag );790}791clip_a = clip_i + 1;792}793drawMore = keepDrawingViewport();794} /* for points in LPoints (k) */795796if (drawMore) {797/* if drawMore is true, then the above loop terminated with798clip_i incremented properly */799if (anLLPoint->prop.closed) {800/* if closed, do the first point again - no need to project801just copy over from the first one */802aLPt = refPt3D(viewData,*((anLLPoint->lp + 0)->indices + j));803project(aLPt, quadMesh, anLLPoint->numOfLists);804if (behindClipPlane(aLPt->pz) ||805(viewData.clipStuff &&806outsideClippedBoundary(aLPt->x, aLPt->y, aLPt->z))) {807if (clip_i - clip_a > 1) {808GDrawLines(componentGC, viewport->viewWindow,809quadMesh + clip_a, clip_i - clip_a,810CoordModeOrigin, dFlag);811}812clip_a = clip_i + 1;813}814clip_i++;815} /* closed */816if (clip_i - clip_a > 1) {817GDrawLines(componentGC, viewport->viewWindow, quadMesh+clip_a,818clip_i-clip_a, CoordModeOrigin, dFlag);819}820} /* drawMore */821} /* for a point in each LPoint (j) */822break;823} /* switch componentType */824} /* for LLPoints in LLLPoints (i) */825break;826827case opaqueMesh:828if (dFlag==Xoption) {829GSetForeground(globGC, (float)opaqueForeground, dFlag);830GSetForeground(opaqueGC, (float)opaqueOutline, dFlag);831}832else {833GSetForeground(globGC, psBlack, dFlag);834GSetForeground(opaqueGC, psBlack, dFlag);835}836GSetLineAttributes(opaqueGC,0,LineSolid,CapButt,JoinRound,dFlag);837drawPolygons(dFlag);838break;839840case render:841if (viewData.outlineRenderOn) {842GSetLineAttributes(renderGC,0,LineSolid,CapButt,JoinRound,dFlag);843if (dFlag==Xoption) GSetForeground(renderGC,(float)black, dFlag);844else GSetForeground(renderGC,psBlack, dFlag );845}846drawPolygons(dFlag);847break;848849case smooth:850drawPhong(dFlag);851break;852853} /* switch on style */854855} /* draw3DComponents() */856857858859