0851
|
Scian.h,
ScianDatasets.h,
ScianDraw.c,
ScianMain.c,
ScianObjFunctions.c,
ScianPreferences.c,
ScianVisContours.c,
ScianVisMesh.c,
ScianVisTraces.c,
ScianVisWindows.c,
|
|
|
/*ScianVisContours.c
June 14, 1991
Eric Pepke
Routines for contour visualization object
The contour object takes a scalar field defined over a data form with
topological dimension 2. The spatial dimension of the dataset may be
either 2 or 3. If the spatial dimension is 2, the Z is assumed to be
zero. The contour visualization object works for regular data forms,
and curvilinear data forms.
*/
#include "Scian.h"
#include "ScianTypes.h"
#include "ScianArrays.h"
#include "ScianWindows.h"
#include "ScianTextBoxes.h"
#include "ScianObjWindows.h"
#include "ScianEvents.h"
#include "ScianIcons.h"
#include "ScianColors.h"
#include "ScianControls.h"
#include "ScianLists.h"
#include "ScianSpaces.h"
#include "ScianSliders.h"
#include "ScianIDs.h"
#include "ScianDatasets.h"
#include "ScianErrors.h"
#include "ScianVisObjects.h"
#include "ScianVisContours.h"
#include "ScianStyle.h"
#include "ScianPictures.h"
#include "ScianTitleBoxes.h"
#include "ScianButtons.h"
#include "ScianMethods.h"
#include "ScianDraw.h"
#include "ScianTemplates.h"
#include "ScianTemplateHelper.h"
ObjPtr contourLineClass; /*Contour line object*/
ObjPtr contoursClass;
typedef struct xyzStruct
{
struct xyzStruct *next; /*Pointer to next in list*/
real x, y, z; /*Coordinates*/
real nx, ny, nz; /*Normals*/
} XYZ;
#ifdef PROTO
static Bool NextContour(ObjPtr, real *);
unsigned char FindQuadJoinings(int initState[2][2]);
void FollowContour(ObjPtr surface, unsigned char *joinings,
long i, long j, long iSize, long jSize,
int startJoin, real contourValue, Bool reverse,
int lineWidth);
XYZ *NewXYZNode(long i, long j, int dir, real contourValue);
#else
static Bool NextContour();
unsigned char FindQuadJoinings();
void FollowContour();
XYZ *NewXYZNode();
#endif
static ObjPtr ContoursInit(object)
ObjPtr object;
/*Initializes a contours object*/
{
ObjPtr minMax;
real bounds[6];
real xySize, zSize;
ObjPtr contourField, mainDataset, colorObj, deformObj;
real min, max, *elements;
double ddiff, majorWidth;
int nTics;
MakeVar(object, MAINDATASET);
SetVar(object, COLOROBJ, colorObj = GetVar(object, MAINDATASET));
if (colorObj)
{
SetVar(object, COLORS, ObjTrue);
}
SetVar(object, DEFORMOBJ, deformObj = GetVar(object, MAINDATASET));
/*Heuristically determine whether to displace Z*/
GetBounds(object, bounds);
xySize = bounds[1] - bounds[0];
xySize = MAX(xySize, bounds[3] - bounds[2]);
xySize = MAX(xySize, bounds[5] - bounds[4]);
if (GetVar(colorObj, DATA))
{
MakeVar(deformObj, MINMAX);
minMax = GetVar(deformObj, MINMAX);
zSize = ((real *) ELEMENTS(minMax))[1] - ((real *) ELEMENTS(minMax))[0];
if (zSize < xySize * 0.5)
{
SetVar(object, DEFORMSWITCH, NewInt(1));
}
else
{
SetVar(object, DEFORMSWITCH, NewInt(0));
}
}
/*Get the contour field*/
contourField = GetObjectVar("ContoursInit", object, MAINDATASET);
if (!contourField) return ObjFalse;
while (mainDataset = GetVar(contourField, MAINDATASET))
{
contourField = mainDataset;
}
/*Find its min and max*/
MakeVar(contourField, MINMAX);
minMax = GetVar(contourField, MINMAX);
if (minMax)
{
elements = ELEMENTS(minMax);
min = elements[0];
max = elements[1];
}
else
{
min = 0.0;
max = 1.0;
}
ddiff = max - min;
CalcGoodSteps(ddiff, 50, 10, &majorWidth, &nTics);
SetVar(object, CONTOURCENTER, NewReal(0.0));
SetVar(object, CONTOURSTEP, NewReal(majorWidth));
SetVar(object, CONTOURMAX, NewReal(PLUSINF));
SetVar(object, CONTOURDIV, NewInt(MAX(1, nTics)));
SetVar(object, CONTOURMIN, NewReal(MINUSINF));
return ObjTrue;
}
static ObjPtr SetContoursMainDataset(visObj, dataSet)
ObjPtr visObj, dataSet;
/*Sets the main data set of visObj to dataSet*/
{
SetVar(visObj, MAINDATASET, dataSet);
return ObjTrue;
}
static ObjPtr MakeContoursColored(visObject)
ObjPtr visObject;
/*Makes the contours colored*/
{
SetVar(visObject, PICCOLORED, ObjTrue);
if (GetPredicate(visObject, COLORS))
{
ObjPtr contourField, contourForm;
ObjPtr colorField, colorForm;
ObjPtr var;
ObjPtr surface;
ObjPtr palette;
/*Get the contour field and its form*/
contourField = GetObjectVar("MakeContoursColored", visObject, MAINDATASET);
if (!contourField) return ObjFalse;
contourForm = GetObjectVar("MakeContoursColored", contourField, DATAFORM);
if (!contourForm) return ObjFalse;
/*Get the color field and its form*/
colorField = GetObjectVar("MakeContoursColored", visObject, COLOROBJ);
if (!colorField) return ObjFalse;
colorForm = GetObjectVar("MakeContoursColored", colorField, DATAFORM);
if (!colorForm) return ObjFalse;
/*Get the color palette*/
MakeVar(colorField, CPALETTE);
palette = GetPaletteVar("MakeContoursColored", colorField, CPALETTE);
if (!palette)
{
return ObjFalse;
}
SetPalette(palette);
/*Get the surface to color*/
surface = GetPictureVar("MakeContoursColored", visObject, SURFACE);
if (!surface) return ObjFalse;
/*Have to make it colored by the object.*/
ColorPictureByObject(surface, colorField, GetPredicate(visObject, INTERPCOLORS));
}
return ObjTrue;
}
#ifdef PROTO
static Bool NextContour(ObjPtr contourList, real *contourValue)
#else
static Bool NextContour(contourList, contourValue)
ObjPtr contourList;
real *contourValue;
#endif
/*Stuffs the next contour ABOVE contourValue in contourList into contourValue
*/
{
ObjPtr var;
real test, closest;
Bool closestSet = false;
ThingListPtr runner;
runner = LISTOF(contourList);
while (runner)
{
var = GetRealVar("NextContour", runner -> thing, STARTVALUE);
if (var)
{
test = GetReal(var);
if (test > *contourValue)
{
if (!closestSet || test < closest)
{
/*Found the next one*/
closestSet = true;
closest = test;
}
}
}
runner = runner -> next;
}
if (closestSet)
{
*contourValue = closest;
}
return closestSet;
}
/*Quadrilateral for contouring is numbered like this
2 3
+-----+
| 2 |
j |3 1|
| 0 |
+-----+
0 1
i
*/
unsigned char fixedJoinings[] =
{
0x00, /* 0000 */
0x30, /* 0001 */
0x10, /* 0010 */
0x70, /* 0011 */
0x0B, /* 0100 */
0x20, /* 0101 */
0x1B, /* 0110 */
0x60, /* 0111 */
0x60, /* 1000 */
0x36, /* 1001 */
0x20, /* 1010 */
0x0B, /* 1011 */
0x70, /* 1100 */
0x10, /* 1101 */
0x30, /* 1110 */
0x00 /* 1111 */
};
unsigned char joinChars[] =
{
' ', /* 0000 */
'\\', /* 0001 */
'/', /* 0010 */
'-', /* 0011 */
'/', /* 0100 */
'|', /* 0101 */
'/', /* 0110 */
'\\', /* 0111 */
'\\', /* 1000 */
'\\', /* 1001 */
'|', /* 1010 */
'/', /* 1011 */
'-', /* 1100 */
'/', /* 1101 */
'\\', /* 1110 */
' ' /* 1111 */
};
#ifdef PROTO
unsigned char FindQuadJoinings(int initState[2][2])
#else
unsigned char FindJoinings(initState)
int initState[2][2];
#endif
/*Finds the joinings for initial state initState*/
{
int index;
index = initState[0][0] +
(initState[1][0] << 1) +
(initState[0][1] << 2) +
(initState[1][1] << 3);
return fixedJoinings[index];
}
#define SELJOIN(j, n) (((n) ? ((j) >> 4) : (j)) & 0xF)
#define WIPEJOIN(j, n) ((n) ? ((j) &= 0xF) : ((j) &= 0xF0))
#define SELEND(j, n) (((n) ? ((j) >> 2) : (j)) & 0x3)
#ifdef PROTO
XYZ *NewXYZNode(long i, long j, int dir, real contourValue)
#else
XYZ *NewXYZNode(i, j, dir, contourValue)
long i, y;
int dir;
real contourValue;
#endif
/*Returns a new XYZ node for dir from i, j assuming contourValue.
Expects dataset in FIELD1 and data form in FIELD2.*/
{
XYZ *node;
long iPlus, jPlus;
real x1, y1, z1, f1, x2, y2, z2, f2, w1, w2;
long curDim[2];
int nComponents;
real c[2][2][3]; /*Corner position*/
real cf[2][2]; /*Corner function*/
real v1[3], v2[3]; /*Vectors*/
real x[3]; /*Cross product*/
/*Make the node*/
node = (XYZ *) Alloc(sizeof(XYZ));
node -> next = NULL;
/*Get the components in the data field*/
nComponents = GetNComponents(FIELD2);
/*Fill the corners*/
for (iPlus = 0; iPlus < 2; ++iPlus)
{
for (jPlus = 0; jPlus < 2; ++jPlus)
{
curDim[0] = i + iPlus;
curDim[1] = j + jPlus;
c[iPlus][jPlus][0] = SelectFieldComponent(FIELD2, 0, curDim);
c[iPlus][jPlus][1] = SelectFieldComponent(FIELD2, 1, curDim);
c[iPlus][jPlus][2] = nComponents >= 3 ?
SelectFieldComponent(FIELD2, 2, curDim) : 0.0;
cf[iPlus][jPlus] = SelectFieldScalar(FIELD1, curDim);
}
}
/*First endpoint*/
switch(dir)
{
case 0:
/*Do 0, 0*/
iPlus = 0;
jPlus = 0;
break;
case 1:
/*Do 1, 0*/
iPlus = 1;
jPlus = 0;
break;
case 2:
/*Do 1, 1*/
iPlus = 1;
jPlus = 1;
break;
case 3:
/*Do 0, 1*/
iPlus = 0;
jPlus = 1;
break;
}
x1 = c[iPlus][jPlus][0];
y1 = c[iPlus][jPlus][1];
z1 = c[iPlus][jPlus][2];
f1 = cf[iPlus][jPlus];
/*Second endpoint*/
switch(dir)
{
case 0:
/*Do 1, 0*/
iPlus = 1;
jPlus = 0;
break;
case 1:
/*Do 1, 1*/
iPlus = 1;
jPlus = 1;
break;
case 2:
/*Do 0, 1*/
iPlus = 0;
jPlus = 1;
break;
case 3:
/*Do 0, 0*/
iPlus = 0;
jPlus = 0;
break;
}
x2 = c[iPlus][jPlus][0];
y2 = c[iPlus][jPlus][1];
z2 = c[iPlus][jPlus][2];
f2 = cf[iPlus][jPlus];
/*Now interpolate*/
if ((f1 <= contourValue) && (contourValue <= f2))
{
real rDiff = 1.0 / (f2 - f1);
w1 = (f2 - contourValue) * rDiff;
w2 = (contourValue - f1) * rDiff;
}
else if ((f2 <= contourValue) && (contourValue <= f1))
{
real rDiff = 1.0 / (f1 - f2);
w2 = (f1 - contourValue) * rDiff;
w1 = (contourValue - f2) * rDiff;
}
else
{
w1 = w2 = 0.0;
fprintf(stderr, "Contour error at (%d %d)\n", i, j);
}
node -> x = x1 * w1 + x2 * w2;
node -> y = y1 * w1 + y2 * w2;
node -> z = z1 * w1 + z2 * w2;
/*Now find the normals*/
v1[0] = c[0][1][0] - c[0][0][0];
v1[1] = c[0][1][1] - c[0][0][1];
v1[2] = c[0][1][2] - c[0][0][2];
v2[0] = c[1][0][0] - c[0][0][0];
v2[1] = c[1][0][1] - c[0][0][1];
v2[2] = c[1][0][2] - c[0][0][2];
CROSS(v1, v2, x);
NORMALIZE(x);
node -> nx = x[0];
node -> ny = x[1];
node -> nz = x[2];
return node;
}
#ifdef PROTO
void FollowContour(ObjPtr surface, unsigned char *joinings,
long i, long j, long iSize, long jSize,
int startJoin,
real contourValue, Bool reverse, int lineWidth)
#else
void FollowContour(surface, joinings, i, j, iSize, jSize, startJoin,
contourValue, reverse, lineWidth)
ObjPtr surface;
unsigned char *joinings;
long i;
long j;
long iSize;
long jSize;
int startJoin;
real contourValue;
Bool reverse;
int lineWidth;
#endif
/*Follows a contour within surface using joinings starting at startJoin at i, j.
startJoin is 0 for LSN and 1 for MSN;
iSize and jSize gives the size of the array. Dataset is assumed to be in
FIELD1 and dataform in FIELD2. This routine runs contours both ways.
Side effects: removes runs from joinings. If reverse is true, reverses the
sense of the normal*/
{
unsigned int joining, a, b, iCur, jCur, aCur, bCur, match, curJoin;
long count, k;
XYZ *first, *last, *runner;
long curDim[2];
VertexPtr vertices;
Bool firstTime;
/*Set joining to the joining to start*/
joining = SELJOIN(joinings[i + j * iSize], startJoin);
/*Set a and b to the two ends of the joining*/
a = SELEND(joining, 1);
b = SELEND(joining, 0);
/*Return if null*/
if (a == b) return;
/*Want to go from a to b. Reverse if neccessary.*/
if ((i == 0 && b == 3) || /*Off left side*/
(i == iSize - 2 && b == 1) || /*Off right side*/
(j == 0 && b == 0) || /*Off bottom side*/
(j == jSize - 2 && b == 2)) /*Off top side*/
{
int t;
t = a;
a = b;
b = t;
}
/*Make the first XYZ in the contour line*/
first = last = NewXYZNode(i, j, a, contourValue);
last -> next = NULL;
iCur = i;
jCur = j;
aCur = a;
bCur = b;
curJoin = startJoin;
/*Now run the contour, from aCur to bCur within iCur, jCur*/
for(;;)
{
/*Emit this joining onto the list*/
last -> next = NewXYZNode(iCur, jCur, bCur, contourValue);
last = last -> next;
/*Delete this joining*/
WIPEJOIN(joinings[iCur + jCur * iSize], curJoin);
/*Find a next place to go*/
switch(bCur)
{
case 0:
--jCur;
match = 2;
break;
case 1:
++iCur;
match = 3;
break;
case 2:
++jCur;
match = 0;
break;
case 3:
--iCur;
match = 1;
break;
}
if (iCur < 0 || jCur < 0 || iCur >= iSize - 1 || jCur >= jSize - 1)
{
/*Fallen off the edge*/
break;
}
/*Get the new joining and see if it matches up. Try 0 first.*/
joining = SELJOIN(joinings[iCur + jCur * iSize], 0);
if (joining)
{
if (SELEND(joining, 1) == match)
{
aCur = SELEND(joining, 1);
bCur = SELEND(joining, 0);
curJoin = 0;
continue;
}
if (SELEND(joining, 0) == match)
{
aCur = SELEND(joining, 0);
bCur = SELEND(joining, 1);
curJoin = 0;
continue;
}
}
/*OK, so now try one*/
joining = SELJOIN(joinings[iCur + jCur * iSize], 1);
if (joining)
{
if (SELEND(joining, 1) == match)
{
aCur = SELEND(joining, 1);
bCur = SELEND(joining, 0);
curJoin = 1;
continue;
}
if (SELEND(joining, 0) == match)
{
aCur = SELEND(joining, 0);
bCur = SELEND(joining, 1);
curJoin = 1;
continue;
}
}
break;
}
/*Follow the contour backward from the beginning, just in case*/
iCur = i;
jCur = j;
bCur = a;
curJoin = startJoin;
firstTime = true;
/*Now run the contour, from aCur to bCur within iCur, jCur*/
for(;;)
{
if (firstTime)
{
firstTime = false;
}
else
{
XYZ *temp;
/*Emit this joining onto the list*/
temp = NewXYZNode(iCur, jCur, bCur, contourValue);
temp -> next = first;
first = temp;
}
/*Delete this joining*/
WIPEJOIN(joinings[iCur + jCur * iSize], curJoin);
/*Find a next place to go*/
switch(bCur)
{
case 0:
--jCur;
match = 2;
break;
case 1:
++iCur;
match = 3;
break;
case 2:
++jCur;
match = 0;
break;
case 3:
--iCur;
match = 1;
break;
}
if (iCur < 0 || jCur < 0 || iCur >= iSize - 1 || jCur >= jSize - 1)
{
/*Fallen off the edge*/
break;
}
/*Get the new joining and see if it matches up. Try 0 first.*/
joining = SELJOIN(joinings[iCur + jCur * iSize], 0);
if (joining)
{
if (SELEND(joining, 1) == match)
{
aCur = SELEND(joining, 1);
bCur = SELEND(joining, 0);
curJoin = 0;
continue;
}
if (SELEND(joining, 0) == match)
{
aCur = SELEND(joining, 0);
bCur = SELEND(joining, 1);
curJoin = 0;
continue;
}
}
/*OK, so now try one*/
joining = SELJOIN(joinings[iCur + jCur * iSize], 1);
if (joining)
{
if (SELEND(joining, 1) == match)
{
aCur = SELEND(joining, 1);
bCur = SELEND(joining, 0);
curJoin = 1;
continue;
}
if (SELEND(joining, 0) == match)
{
aCur = SELEND(joining, 0);
bCur = SELEND(joining, 1);
curJoin = 1;
continue;
}
}
break;
}
/*Count the elements in the list*/
runner = first;
count = 0;
while (runner)
{
++count;
runner = runner -> next;
}
/*Make the vertices*/
vertices = (VertexPtr) Alloc(count * sizeof(Vertex));
if (vertices)
{
/*Run through the list, putting it on the vertices*/
runner = first;
for (k = 0; k < count; ++k)
{
vertices[k] . position[0] = runner -> x;
vertices[k] . position[1] = runner -> y;
vertices[k] . position[2] = runner -> z;
if (reverse)
{
vertices[k] . normal[0] = -runner -> nx;
vertices[k] . normal[1] = -runner -> ny;
vertices[k] . normal[2] = -runner -> nz;
}
else
{
vertices[k] . normal[0] = runner -> nx;
vertices[k] . normal[1] = runner -> ny;
vertices[k] . normal[2] = runner -> nz;
}
vertices[k] . colorIndex = 0;
runner = runner -> next;
}
/*Make a contour line*/
AppendPolylineToPicture(surface, lineWidth, 2, count, vertices);
/*Free the vertices*/
Free(vertices);
}
/*Eliminate the XYZ list*/
while (first)
{
last = first -> next;
Free(first);
first = last;
}
}
static ObjPtr MakeContoursSurface(visObject)
ObjPtr visObject;
/*Makes the surface in a contours object. Also colors it.*/
{
ObjPtr dataset; /*The dataset the vis object represents*/
long datasetFlags; /*Flags of the dataset*/
ObjPtr var; /*Random variable*/
ObjPtr picture; /*The picture to be made*/
dataset = GetObjectVar("MakeContoursSurface", visObject, MAINDATASET);
if (!dataset)
{
return ObjFalse;
}
datasetFlags = GetDatasetInfo(dataset);
if (0 == datasetFlags & DS_HASFORM)
{
ReportError("MakeContoursSurface", "No data form");
return ObjFalse;
}
/*Make the new picture*/
picture = NewPicture();
if (!picture) return ObjFalse;
if (datasetFlags & DS_UNSTRUCTURED)
{
return ObjFalse;
}
else
{
/*It's a structured dataset.*/
int topDim, nComponents;
long curDim[2], iDims[2];
ObjPtr dims;
RectMeshPtr rectMesh;
real temp[3];
int iDim, jDim;
Bool reverse;
/*It must have dimension 2*/
topDim = GetTopDim(dataset);
if (topDim != 2)
{
ReportError("MakeContoursSurface", "Topological dimension must be 2.");
return ObjFalse;
}
/*Get the actual topological dimensions*/
dims = GetDatasetFormDims(dataset);
if (!dims || !IsRealArray(dims) || RANK(dims) != 1 || DIMS(dims)[0] != 2)
{
ReportError("MakeContoursSurface", "No topological dimensions");
return ObjFalse;
}
iDims[0] = ((real *) ELEMENTS(dims))[0];
iDims[1] = ((real *) ELEMENTS(dims))[1];
/*Register the dataset and its dataform*/
if (!SetCurField(FIELD1, dataset))
{
return ObjFalse;
}
if (!SetCurForm(FIELD2, dataset))
{
return ObjFalse;
}
reverse = GetPredicate(visObject, REVERSESENSE) ^
GetPredicate(dataset, ISLEFTHANDED);
if (reverse)
{
iDim = 1;
jDim = 0;
}
else
{
iDim = 0;
jDim = 1;
}
var = GetVar(visObject, CONTOURCENTER);
if (var)
{
/*Create all the contour lines*/
ObjPtr minMax;
real *elements;
ThingListPtr runner;
double min, max, mid;
double curContour;
unsigned char *joinings;
long i, j, k, iPlus, jPlus;
int initState[2][2];
double test;
double center; /*Center of contour*/
double step; /*Plus and minus step*/
int nDivisions; /*Number of divisions*/
double contourMin, contourMax;/*Min and max of contours*/
long contourIndex;
center = GetReal(var);
/*Get the step*/
var = GetRealVar("MakeContoursSurface", visObject, CONTOURSTEP);
if (!var)
{
return ObjFalse;
}
step = GetReal(var);
var = GetIntVar("MakeContoursSurface", visObject, CONTOURDIV);
if (!var)
{
return ObjFalse;
}
nDivisions = GetInt(var);
if (nDivisions > 0)
{
step /= nDivisions;
}
else
{
nDivisions = 1;
}
/*Now the min and max*/
var = GetRealVar("MakeContoursSurface", visObject, CONTOURMAX);
if (!var)
{
return ObjFalse;
}
contourMax = GetReal(var);
var = GetRealVar("MakeContoursSurface", visObject, CONTOURMIN);
if (!var)
{
return ObjFalse;
}
contourMin = GetReal(var);
/*Get the min and max of the dataset*/
MakeVar(dataset, MINMAX);
minMax = GetVar(dataset, MINMAX);
if (minMax)
{
elements = ELEMENTS(minMax);
min = elements[0];
max = elements[1];
}
else
{
min = 0.0;
max = 1.0;
}
mid = (min + max) * 0.5;
/*Make the joinings array*/
joinings = (unsigned char *) Alloc(iDims[0] * iDims[1]);
for (k = 0; k < iDims[0] * iDims[1]; ++k)
{
joinings[k] = 0;
}
/*Clip min and max with contour min and max*/
min = MAX(min, contourMin);
max = MIN(max, contourMax);
/*Find the index of the first contour*/
contourIndex = (min - center) / ABS(step);
curContour = center + contourIndex * ABS(step);
/*Go through the contours, finding joinings*/
while (curContour <= max)
{
/*Generate joinings for this contour*/
for (j = 0; j < iDims[jDim] - 1; ++j)
{
for (i = 0; i < iDims[iDim] - 1; ++i)
{
/*Set up initState*/
for (jPlus = 0; jPlus < 2; ++jPlus)
{
for (iPlus = 0; iPlus < 2; ++iPlus)
{
curDim[iDim] = i + iPlus;
curDim[jDim] = j + jPlus;
test = SelectFieldScalar(FIELD1, curDim);
if (test == missingData)
{
goto cellMissing;
}
initState[(iDim == 0) ? iPlus : jPlus]
[(jDim == 1) ? jPlus : iPlus] =
(curContour > mid) ?
(test <= curContour ? 1 : 0) :
(test <= curContour ? 0 : 1);
}
}
curDim[iDim] = i;
curDim[jDim] = j;
joinings[curDim[1] * iDims[0] + curDim[0]] =
FindQuadJoinings(initState);
cellMissing:;
}
}
/*Follow all the contours*/
for (j = 0; j < iDims[jDim] - 1; ++j)
{
for (i = 0; i < iDims[iDim] - 1; ++i)
{
int joining;
curDim[iDim] = i;
curDim[jDim] = j;
/*Must have a joining involving the bottom edge*/
joining = joinings[curDim[1] * iDims[0] + curDim[0]];
if (joining & 0xF0)
{
FollowContour(picture, joinings, curDim[0], curDim[1], iDims[0], iDims[1], 1, curContour, reverse ? false : true, 0);
}
joining = joinings[curDim[1] * iDims[0] + curDim[0]];
if (joining & 0x0F)
{
FollowContour(picture, joinings, curDim[0], curDim[1], iDims[0], iDims[1], 0, curContour, reverse ? false : true, 0);
}
}
}
/*Next contour*/
++contourIndex;
curContour = center + contourIndex * ABS(step);
}
Free(joinings);
}
}
SetVar(visObject, SURFACE, picture);
SetVar(picture, REPOBJ, visObject);
return ObjTrue;
}
static ObjPtr AddContourControls(contour, panelContents)
ObjPtr contour, panelContents;
/*Adds controls appropriate to a contour object to panelContents*/
{
ObjPtr titleBox, button, radio, var, corral, icon, name, contourField, mainDataset;
ObjPtr textBox, defaultIcon;
int width, left, top, bottom, right, mid;
ObjPtr control;
ObjPtr minMax;
char number[50];
real step, origin, min, max;
int divisions;
width = CWINWIDTH - 2 * CORRALBORDER - CWINCORRALWIDTH;
/*Get the contour field*/
contourField = GetObjectVar("AddContourControls", contour, MAINDATASET);
if (!contourField) return ObjFalse;
while (mainDataset = GetVar(contourField, MAINDATASET))
{
contourField = mainDataset;
}
/*Put in the contour corral at the top left*/
left = MAJORBORDER;
top = MAJORBORDER;
corral = NewIconCorral(NULLOBJ,
left, left + ONECORRALWIDTH,
CWINHEIGHT - MAJORBORDER - ONECORRALHEIGHT,
CWINHEIGHT - MAJORBORDER, 0);
SetVar(corral, SINGLECORRAL, ObjTrue);
SetVar(corral, TOPDOWN, ObjTrue);
SetVar(corral, NAME, NewString("Contour Field"));
SetVar(corral, HELPSTRING,
NewString("This corral shows the dataset that is being used to make \
the contour display. The locations of contours and color cells are calculated \
using this field. The color of color cells is calculated using the Color Field, \
available in the Color control set."));
PrefixList(panelContents, corral);
SetVar(corral, PARENT, panelContents);
SetVar(corral, REPOBJ, contour);
SetMethod(corral, DROPINCONTENTS, DropInMainDatasetCorral);
/*Create the contour source text box*/
textBox = NewTextBox(left, left + ONECORRALWIDTH,
CWINHEIGHT - MAJORBORDER - ONECORRALHEIGHT - TEXTBOXSEP - TEXTBOXHEIGHT,
CWINHEIGHT - MAJORBORDER - ONECORRALHEIGHT - TEXTBOXSEP,
0, "Contour Field Text", "Contour Field");
PrefixList(panelContents, textBox);
SetVar(textBox, PARENT, panelContents);
SetTextAlign(textBox, CENTERALIGN);
top = CWINHEIGHT - 2 * MAJORBORDER - ONECORRALHEIGHT - TEXTBOXSEP - TEXTBOXHEIGHT;
/*Put in an icon that represents the field*/
name = GetVar(contourField, NAME);
defaultIcon = GetVar(contourField, DEFAULTICON);
if (defaultIcon)
{
icon = NewObject(defaultIcon, 0);
SetVar(icon, NAME, name);
}
else
{
icon = NewIcon(0, 0, ICONQUESTION, GetString(name));
}
SetVar(icon, ICONLOC, NULLOBJ);
SetVar(icon, REPOBJ, contourField);
DropIconInCorral(corral, icon);
var = GetRealVar("AddContourControls", contour, CONTOURSTEP);
if (var)
{
step = GetReal(var);
}
else
{
SetVar(contour, CONTOURSTEP, NewReal(1.0));
step = 1.0;
}
var = GetRealVar("AddContourControls", contour, CONTOURCENTER);
if (var)
{
origin = GetReal(var);
}
else
{
SetVar(contour, CONTOURCENTER, NewReal(0.0));
origin = 0.0;
}
var = GetRealVar("AddContourControls", contour, CONTOURMIN);
if (var)
{
min = GetReal(var);
}
else
{
SetVar(contour, CONTOURMIN, NewReal(minusInf));
min = minusInf;
}
var = GetRealVar("AddContourControls", contour, CONTOURMAX);
if (var)
{
max = GetReal(var);
}
else
{
SetVar(contour, CONTOURMAX, NewReal(plusInf));
max = plusInf;
}
var = GetIntVar("AddContourControls", contour, CONTOURDIV);
if (var)
{
divisions = GetInt(var);
}
else
{
SetVar(contour, CONTOURDIV, NewInt(1));
divisions = 1;
}
/*Make the origin*/
textBox = TemplateTextBox(VisContoursTemplate, "Origin Text", 0, "Origin:");
PrefixList(panelContents, textBox);
SetVar(textBox, PARENT, panelContents);
PrintNumber(number, origin);
textBox = TemplateTextBox(VisContoursTemplate, "Origin",
EDITABLE + WITH_PIT + ONE_LINE, number);
SetVar(textBox, PARENT, panelContents);
PrefixList(panelContents, textBox);
SetTextAlign(textBox, RIGHTALIGN);
AssocTextRealControlWithVar(textBox, contour, CONTOURCENTER, minusInf, plusInf, TR_NE_BOTTOM | TR_NE_TOP);
SetVar(textBox, HELPSTRING,
NewString("This number specifies the origin of the contours. \
Contours are calculated starting at the origin, increasing and decreasing by the steps \
specified in the major and minor contours parameters, until the minimum or maximum is reached.\
For most ordinary contours that cover the entire visualization range, this does not \
need to be changed."));
/*Make the minimum*/
textBox = TemplateTextBox(VisContoursTemplate, "Minimum Text",
0, "Minimum:");
PrefixList(panelContents, textBox);
SetVar(textBox, PARENT, panelContents);
PrintNumber(number, min);
textBox = TemplateTextBox(VisContoursTemplate, "Minimum",
EDITABLE + WITH_PIT + ONE_LINE, number);
SetVar(textBox, PARENT, panelContents);
PrefixList(panelContents, textBox);
SetTextAlign(textBox, RIGHTALIGN);
AssocTextRealControlWithVar(textBox, contour, CONTOURMIN, minusInf, plusInf, TR_NE_BOTTOM);
SetVar(textBox, HELPSTRING,
NewString("This number specifies the minimum contour value. \
Contours are calculated starting at the origin, increasing and decreasing by the steps \
specified in the major and minor contours parameters, until the minimum or maximum is reached. \
For most ordinary contours that cover the entire visualization range, this does not \
need to be changed.\n"));
/*Make the maximum*/
textBox = TemplateTextBox(VisContoursTemplate, "Maximum Text", 0, "Maximum:");
PrefixList(panelContents, textBox);
SetVar(textBox, PARENT, panelContents);
PrintNumber(number, max);
textBox = TemplateTextBox(VisContoursTemplate, "Maximum",
EDITABLE + WITH_PIT + ONE_LINE, number);
SetVar(textBox, PARENT, panelContents);
PrefixList(panelContents, textBox);
SetTextAlign(textBox, RIGHTALIGN);
AssocTextRealControlWithVar(textBox, contour, CONTOURMAX, minusInf, plusInf, TR_NE_BOTTOM);
SetVar(textBox, HELPSTRING,
NewString("This number specifies the maximum contour value. \
Contours are calculated starting at the origin, increasing and decreasing by the steps \
specified in the major and minor contours parameters, until the minimum or maximum is reached. \
For most ordinary contours that cover the entire visualization range, this does not \
need to be changed.\n"));
/*Make the major contour controls*/
textBox = TemplateTextBox(VisContoursTemplate, "Step Text",
0, "Major Step:");
PrefixList(panelContents, textBox);
SetVar(textBox, PARENT, panelContents);
PrintNumber(number, step);
textBox = TemplateTextBox(VisContoursTemplate, "Step",
EDITABLE + WITH_PIT + ONE_LINE, number);
SetVar(textBox, PARENT, panelContents);
PrefixList(panelContents, textBox);
SetTextAlign(textBox, RIGHTALIGN);
AssocTextRealControlWithVar(textBox, contour, CONTOURSTEP, 0.0, plusInf, TR_NE_BOTTOM | TR_NE_TOP);
SetVar(textBox, HELPSTRING,
NewString("This number specifies the step size of the major contours. \
It must be a real number greater than 0. \
Contours are calculated starting at the origin, increasing and decreasing by the steps \
specified in the major and minor contours parameters, until the minimum or maximum is reached."));
/*Make the minor contour controls*/
textBox = TemplateTextBox(VisContoursTemplate, "Divisions Text",
0, "Minor Divisions:");
PrefixList(panelContents, textBox);
SetVar(textBox, PARENT, panelContents);
PrintNumber(number, (real) divisions);
textBox = TemplateTextBox(VisContoursTemplate, "Divisions",
EDITABLE + WITH_PIT + ONE_LINE, number);
SetVar(textBox, PARENT, panelContents);
PrefixList(panelContents, textBox);
SetTextAlign(textBox, RIGHTALIGN);
AssocTextIntControlWithVar(textBox, contour, CONTOURDIV, 1.0, plusInf, TR_INT_ONLY | TR_NE_TOP);
SetVar(textBox, HELPSTRING,
NewString("This text box contains a number giving the number of divisions between \
major contours. \
This must be an integer greater than zero. For example, a value of 1 gives no minor divisions \
between major contours. A value of 10 gives one major contour every 10 divisions. \
Contours are calculated starting at the origin, increasing and decreasing by the steps \
specified in the major and minor contours parameters, until the minimum or maximum is reached."));
return ObjTrue;
}
ObjPtr MakeContourLines(contour)
ObjPtr contour;
/*Makes some contour lines*/
{
ObjPtr line, lines;
SetVar(contour, CONTOURLINES, lines = NewList());
return ObjTrue;
}
void InitContours()
/*Initializes the contour objects*/
{
ObjPtr icon, color;
/*Class for a contour line*/
contourLineClass = NewObject(NULLOBJ, 0);
color = NewRealArray(1, 3L);
((real *) ELEMENTS(color))[0] = 1.0;
((real *) ELEMENTS(color))[1] = 1.0;
((real *) ELEMENTS(color))[2] = 1.0;
SetVar(contourLineClass, BASECOLOR, color);
AddToReferenceList(contourLineClass);
/*Class for a contour object*/
contoursClass = NewObject(visDeformed, 0);
AddToReferenceList(contoursClass);
SetVar(contoursClass, NAME, NewString("Contours"));
SetMethod(contoursClass, INITIALIZE, ContoursInit);
SetVar(contoursClass, SHINVAL, NewReal(80.0));
SetVar(contoursClass, SPECVAL, NewReal(0.2));
SetVar(contoursClass, DEFAULTICON, icon = NewObject(visIcon, 0));
SetMethod(contoursClass, CONTOURLINES, MakeContourLines);
SetVar(contoursClass, DRAWSURFACE, ObjFalse);
SetVar(contoursClass, DRAWWIREFRAME, ObjTrue);
SetVar(icon, WHICHICON, NewInt(ICONCONTOURS));
SetVar(icon, NAME, NewString("Contours"));
SetVar(icon, HELPSTRING,
NewString("This icon represents a contour visualization object. \
The contour object shows contours and shaded color surfaces of 2-dimensional \
scalar fields defined over structured or nonstructured grids."));
DeclareIndirectDependency(contoursClass, SURFACE, MAINDATASET, CHANGED);
DeclareDependency(contoursClass, SURFACE, COLORCELLS);
SetMethod(contoursClass, SURFACE, MakeContoursSurface);
DeclareDependency(contoursClass, SURFACE, REVERSESENSE);
DeclareDependency(contoursClass, SURFACE, CONTOURCENTER);
DeclareDependency(contoursClass, SURFACE, CONTOURSTEP);
DeclareDependency(contoursClass, SURFACE, CONTOURMAX);
DeclareDependency(contoursClass, SURFACE, CONTOURDIV);
DeclareDependency(contoursClass, SURFACE, CONTOURMIN);
SetMethod(contoursClass, PICCOLORED, MakeContoursColored);
SetMethod(contoursClass, SETMAINDATASET, SetContoursMainDataset);
SetMethod(contoursClass, ADDCONTROLS, AddContourControls);
icon = NewIcon(0, 0, ICONCONTOURS, "Contours");
SetVar(contoursClass, CONTROLICON, icon);
DefineVisMapping(DS_HASFORM | DS_HASFIELD, 2, 3, 1, contoursClass);
DefineVisMapping(DS_HASFORM | DS_HASFIELD, 2, 2, 1, contoursClass);
DefineVisMapping(DS_HASFORM | DS_HASFIELD | DS_UNSTRUCTURED, 2, 3, 1, contoursClass);
DefineVisMapping(DS_HASFORM | DS_HASFIELD | DS_UNSTRUCTURED, 2, 2, 1, contoursClass);
}
void KillContours()
/*Kills the contours*/
{
DeleteThing(contoursClass);
DeleteThing(contourLineClass);
}
|