|
/*ScianVisMesh.c
June 14, 1991
Eric Pepke
Routines for mesh visualization object
The mesh 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 mesh visualization object works for regular data forms,
curvilinear data forms, and nonstructured 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 "ScianVisMesh.h"
#include "ScianStyle.h"
#include "ScianPictures.h"
#include "ScianTitleBoxes.h"
#include "ScianButtons.h"
#include "ScianMethods.h"
#include "ScianDraw.h"
ObjPtr meshClass;
/*Values for color cells. Don't change these values.*/
#define COLORCELLSNONE 0
#define COLORCELLSGRID 1
#define COLORCELLSDATA 2
static ObjPtr MakeMeshColored(visObject)
ObjPtr visObject;
/*Makes the mesh colored*/
{
SetVar(visObject, PICCOLORED, ObjTrue);
MakeVar(visObject, COLORS);
if (GetPredicate(visObject, COLORS))
{
ObjPtr meshField;
ObjPtr colorField;
ObjPtr var;
ObjPtr surface;
ObjPtr palette;
/*Get the mesh field and its form*/
meshField = GetObjectVar("MakeMeshColored", visObject, MAINDATASET);
if (!meshField) return ObjFalse;
/*Get the color field and its form*/
colorField = GetObjectVar("MakeMeshColored", visObject, COLOROBJ);
if (!colorField) return ObjFalse;
/*Get the surface to color*/
MakeVar(visObject, SURFACE);
surface = GetPictureVar("MakeMeshColored", visObject, SURFACE);
if (!surface) return ObjFalse;
/*See if the mesh form is the same as the color form*/
SetCurForm(FORMFIELD, meshField);
SetCurForm(FIELD2, colorField);
MakeVar(colorField, CPALETTE);
palette = GetPaletteVar("MakeMeshColored", colorField, CPALETTE);
if (!palette)
{
return ObjFalse;
}
SetPalette(palette);
if (IdenticalFields(FORMFIELD, FIELD2))
{
/*Yes! It's easy and fast to traverse*/
long info;
info = GetDatasetInfo(colorField);
if (info & DS_UNSTRUCTURED)
{
/*It's an unstructured data form*/
ObjPtr faces; /*Faces of the dataform*/
PolysPtr polys; /*The polygons in the surface*/
PolyPtr polyRunner; /*The runner through the polys*/
ThingListPtr cellRunner; /*The runner through the cells*/
ObjPtr field; /*The field itself*/
SetCurField(FIELD1, colorField);
faces = GetDatasetKEdges(meshField, 2);
if (!faces)
{
return ObjFalse;
}
/*Look in the polys of the picture*/
polys = (PolysPtr) ((PicPtr) surface) -> items;
if (!polys)
{
return ObjTrue;
}
if (polys -> item . type != POLYGONS)
{
ReportError("MakeMeshColored", "Malformed picture");
return ObjFalse;
}
cellRunner = LISTOF(faces);
polyRunner = polys -> polygons;
while (cellRunner)
{
ObjPtr array;
int k, d, i, index;
real *a;
if (!polyRunner)
{
ReportError("MakeMeshColored", "Picture too short");
break;
}
array = cellRunner -> thing;
d = DIMS(array)[0];
a = ArrayMeat(array);
if (d == polyRunner -> nVertices)
{
for (k = 0; k < d; ++k)
{
/*Color the vertices of the polygon*/
long indices[1];
i = *a;
indices[0] = i;
index = GetRealColorIndex(
SelectFieldScalar(FIELD1, indices));
polyRunner -> vertices[k] -> colorIndex = index;
++a;
}
}
else
{
ReportError("MakeMeshColored", "Malformed polygon");
}
cellRunner = cellRunner -> next;
polyRunner = (PolyPtr) polyRunner -> item . next;
}
if (cellRunner)
{
ReportError("MakeMeshColored", "Picture too long");
}
}
else
{
/*Same structured dataset*/
int topDim;
long curDim[2], iDims[2];
RectMeshPtr rectMesh;
real temp[3];
ObjPtr var;
int colorCells;
Bool reverse;
/*It must have dimension 2*/
topDim = CountTraversalDims(FORMFIELD);
if (topDim != 2)
{
ReportError("MakeMeshColored", "Topological dimension must be 2.");
return ObjFalse;
}
/*Get the actual topological dimensions dimension*/
GetTraversalDims(FORMFIELD, iDims);
/*Register the mesh field*/
if (!SetCurField(FIELD1, colorField))
{
return ObjFalse;
}
/*See what kind of color cells it has*/
var = GetIntVar("MakeMeshColored", visObject, COLORCELLS);
if (var)
{
colorCells = GetInt(var);
}
else
{
colorCells = 1;
}
if (colorCells)
{
real sample;
VertexPtr v;
int iDim, jDim;
reverse = (GetPredicate(visObject, REVERSESENSE) ^
GetPredicate(meshField, ISLEFTHANDED));
if (reverse)
{
iDim = 1;
jDim = 0;
}
else
{
iDim = 0;
jDim = 1;
}
/*Get the rectangular mesh*/
rectMesh = (RectMeshPtr) ((PicPtr) surface) -> items;
if (!rectMesh)
{
return ObjFalse;
}
if (colorCells == COLORCELLSGRID)
{
/*Color cells between the grid lines*/
for (curDim[iDim] = 0; curDim[iDim] < iDims[iDim]; ++curDim[iDim])
{
for (curDim[jDim] = 0; curDim[jDim] < iDims[jDim]; ++curDim[jDim])
{
sample = SelectFieldScalar(FIELD1, curDim);
v = RectMeshVertex(rectMesh,
curDim[iDim], curDim[jDim]);
v -> colorIndex = GetRealColorIndex(sample);
}
}
InterpRectCenters(rectMesh);
}
else if (colorCells == COLORCELLSDATA)
{
/*Color cells around the data points*/
for (curDim[iDim] = 0; curDim[iDim] < iDims[iDim]; ++curDim[iDim])
{
for (curDim[jDim] = 0; curDim[jDim] < iDims[jDim]; ++curDim[jDim])
{
sample = SelectFieldScalar(FIELD1, curDim);
v = RectMeshCenter(rectMesh,
curDim[iDim], curDim[jDim]);
v -> colorIndex = GetRealColorIndex(sample);
}
}
InterpRectVertices(rectMesh);
}
}
}
}
else
{
ColorPictureByObject(surface, colorField, GetPredicate(visObject, INTERPCOLORS));
}
}
SetVar(visObject, PICCOLORED, ObjTrue);
return ObjTrue;
}
static ObjPtr MakeMeshSurface(visObject)
ObjPtr visObject;
/*Makes the surface in a mesh object.*/
{
ObjPtr dataset; /*The dataset the vis object represents*/
long datasetFlags; /*Flags of the dataset*/
ObjPtr var; /*Random variable*/
int colorCells; /*What kind of color cells*/
ObjPtr picture; /*The picture to be made*/
dataset = GetObjectVar("MakeMeshSurface", visObject, MAINDATASET);
if (!dataset)
{
return ObjFalse;
}
datasetFlags = GetDatasetInfo(dataset);
if (0 == datasetFlags & DS_HASFORM)
{
ReportError("MakeMeshSurface", "No data form");
return ObjFalse;
}
/*See what kind of color cells it has*/
var = GetIntVar("MakeMeshSurface", visObject, COLORCELLS);
if (var)
{
colorCells = GetInt(var);
}
else
{
colorCells = 1;
}
/*Make the new picture*/
picture = NewPicture();
if (!picture) return ObjFalse;
if (datasetFlags & DS_UNSTRUCTURED)
{
/*It's an unstructured dataset.*/
ObjPtr edges; /*Edges of the dataform*/
ObjPtr faces; /*Faces of the dataform*/
TwoReals *edgesArray; /*Array of edges*/
PolysPtr polys; /*The polygons in the surface*/
ThingListPtr runner; /*The runner through the cells*/
VertexPtr *vertices; /*Temporary holding place for vertices*/
long allocVertices; /*Number of vertices allocated*/
long nVertices; /*Total number of vertices*/
VertexPtr *indVertices; /*Indirect vertices*/
long k; /*Index into form*/
SetCurForm(FORMFIELD, dataset);
/*It must have dimension 2*/
/*Get the actual topological dimensions dimension*/
GetTraversalDims(FORMFIELD, &nVertices);
edges = GetDatasetKEdges(dataset, 1);
if (!edges)
{
return ObjFalse;
}
edgesArray = (TwoReals *) ArrayMeat(edges);
faces = GetDatasetKEdges(dataset, 2);
if (!faces)
{
return ObjFalse;
}
if (colorCells)
{
/*Make the picture and set it up with one polys*/
polys = AppendPolysToPicture(picture);
if (!polys) return ObjFalse;
indVertices = (VertexPtr *) Alloc(nVertices * sizeof(VertexPtr));
for (k = 0; k < nVertices; ++k)
{
indVertices[k] = NewVertex(picture, 0);
indVertices[k] -> position[0] = SelectFieldComponent(FORMFIELD, 0, &k);
indVertices[k] -> position[1] = SelectFieldComponent(FORMFIELD, 1, &k);
indVertices[k] -> position[2] = SelectFieldComponent(FORMFIELD, 2, &k);
}
allocVertices = 20;
vertices = (VertexPtr *) Alloc(20 * sizeof(VertexPtr));
if (!vertices)
{
return ObjFalse;
}
runner = LISTOF(faces);
while (runner)
{
ObjPtr array;
int k, d, i;
real *a;
array = runner -> thing;
d = DIMS(array)[0];
a = ArrayMeat(array);
for (k = 0; k < d; ++k)
{
i = *a;
if (k >= allocVertices)
{
allocVertices += 20;
vertices = (VertexPtr *) Realloc(vertices, allocVertices * sizeof(VertexPtr));
if (!vertices)
{
return ObjFalse;
}
}
vertices[k] = indVertices[i];
++a;
}
/*DIKEO fix to do better vertex allocation*/
AppendSPolyToPolys(polys, d, vertices);
runner = runner -> next;
}
Free(vertices);
Free(indVertices);
}
}
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;
/*Register the dataset and its dataform*/
if (!SetCurField(FIELD1, dataset))
{
return ObjFalse;
}
if (!SetCurForm(FIELD2, dataset))
{
return ObjFalse;
}
/*It must have dimension 2*/
topDim = CountTraversalDims(FIELD2);
if (topDim != 2)
{
ReportError("MakeMeshSurface", "Topological dimension must be 2.");
return ObjFalse;
}
/*Get the actual topological dimensions dimension*/
GetTraversalDims(FIELD2, iDims);
reverse = (GetPredicate(visObject, REVERSESENSE) ^
GetPredicate(dataset, ISLEFTHANDED));
if (reverse)
{
iDim = 1;
jDim = 0;
}
else
{
iDim = 0;
jDim = 1;
}
if (colorCells)
{
/*Create the color cells*/
VertexPtr v;
if (colorCells == COLORCELLSGRID)
{
/*Color cells between the grid lines*/
/*Create a new rectangular mesh*/
rectMesh = AppendRectMeshToPicture(picture, iDims[iDim], iDims[jDim], false);
if (!rectMesh)
{
return ObjFalse;
}
nComponents = GetNComponents(FIELD2);
for (curDim[iDim] = 0; curDim[iDim] < iDims[iDim]; ++curDim[iDim])
{
for (curDim[jDim] = 0; curDim[jDim] < iDims[jDim]; ++curDim[jDim])
{
v = RectMeshVertex(rectMesh, curDim[iDim], curDim[jDim]);
v -> position[0] = SelectFieldComponent(FIELD2, 0, curDim);
v -> position[1] = SelectFieldComponent(FIELD2, 1, curDim);
v -> position[2] = nComponents >= 3 ? SelectFieldComponent(FIELD2, 2, curDim) : 0.0;
}
}
InterpRectCenters(rectMesh);
}
else if (colorCells == COLORCELLSDATA)
{
/*Color cells around the data points*/
/*Create a new rectangular mesh*/
rectMesh = AppendRectMeshToPicture(picture, iDims[iDim] + 1, iDims[jDim] + 1, true);
if (!rectMesh)
{
return ObjFalse;
}
nComponents = GetNComponents(FIELD2);
for (curDim[iDim] = 0; curDim[iDim] < iDims[iDim]; ++curDim[iDim])
{
for (curDim[jDim] = 0; curDim[jDim] < iDims[jDim]; ++curDim[jDim])
{
v = RectMeshCenter(rectMesh, curDim[iDim], curDim[jDim]);
v -> position[0] = SelectFieldComponent(FIELD2, 0, curDim);
v -> position[1] = SelectFieldComponent(FIELD2, 1, curDim);
v -> position[2] = nComponents >= 3 ? SelectFieldComponent(FIELD2, 2, curDim) : 0.0;
}
}
InterpRectVertices(rectMesh);
}
}
}
CalcPictureNormals(picture);
SetVar(visObject, SURFACE, picture);
SetVar(picture, MAINDATASET, dataset);
SetVar(picture, REPOBJ, visObject);
return ObjTrue;
}
static ObjPtr AddMeshControls(mesh, panelContents)
ObjPtr mesh, panelContents;
/*Adds controls appropriate to a mesh object to panelContents*/
{
ObjPtr titleBox, button, radio, var, corral, icon, name, meshField, mainDataset;
ObjPtr textBox, defaultIcon;
int width, left, top, bottom, right;
ObjPtr control;
ObjPtr minMax;
real min, max, *elements;
width = CWINWIDTH - 2 * CORRALBORDER - CWINCORRALWIDTH;
/*Get the mesh field*/
meshField = GetObjectVar("AddMeshControls", mesh, MAINDATASET);
if (!meshField) return ObjFalse;
while (mainDataset = GetVar(meshField, MAINDATASET))
{
meshField = mainDataset;
}
/*Find its min and max*/
MakeVar(meshField, MINMAX);
minMax = GetVar(meshField, MINMAX);
if (minMax)
{
elements = ELEMENTS(minMax);
min = elements[0];
max = elements[1];
}
else
{
min = 0.0;
max = 1.0;
}
/*Create the color cells title box*/
right = width;
left = right - (CCBUTTONLENGTH + 2 * MINORBORDER);
top = CWINHEIGHT - MINORBORDER;
bottom = top - (2 * MINORBORDER + 3 * CHECKBOXHEIGHT + 2 * CHECKBOXSPACING + TITLEBOXTOP);
titleBox = NewTitleBox(left, right, bottom, top, "Color Cells");
PrefixList(panelContents, titleBox);
SetVar(titleBox, PARENT, panelContents);
/*Create the radio button group*/
radio = NewRadioButtonGroup("Color Cells Radio");
PrefixList(panelContents, radio);
SetVar(radio, PARENT, panelContents);
/*Create the buttons*/
left += MINORBORDER;
right -= MINORBORDER;
top -= TITLEBOXTOP + MINORBORDER;
bottom = top - CHECKBOXHEIGHT;
button = NewRadioButton(left, right, bottom, top, "None");
AddRadioButton(radio, button);
top = bottom - CHECKBOXSPACING;
bottom = top - CHECKBOXHEIGHT;
button = NewRadioButton(left, right, bottom, top, "Between Grid Lines");
AddRadioButton(radio, button);
top = bottom - CHECKBOXSPACING;
bottom = top - CHECKBOXHEIGHT;
button = NewRadioButton(left, right, bottom, top, "Around Data Points");
AddRadioButton(radio, button);
/*Set the radio according to COLORCELLS*/
var = GetIntVar("AddMeshControls", mesh, COLORCELLS);
if (!var)
{
SetVar(mesh, COLORCELLS, NewInt(1));
}
AssocDirectControlWithVar(radio, mesh, COLORCELLS);
/*Put in the mesh 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("Mesh Field"));
SetVar(corral, HELPSTRING,
NewString("This corral shows the dataset that is being used to make \
the mesh display. The locations of color cells and meshs 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, mesh);
SetMethod(corral, DROPINCONTENTS, DropInMainDatasetCorral);
/*Create the mesh source text box*/
textBox = NewTextBox(left, left + ONECORRALWIDTH,
CWINHEIGHT - MAJORBORDER - ONECORRALHEIGHT - TEXTBOXSEP - TEXTBOXHEIGHT,
CWINHEIGHT - MAJORBORDER - ONECORRALHEIGHT - TEXTBOXSEP,
0, "Mesh Field Text", "Mesh Field");
PrefixList(panelContents, textBox);
SetVar(textBox, PARENT, panelContents);
SetTextAlign(textBox, CENTERALIGN);
/*Put in an icon that represents the field*/
MakeVar(meshField, NAME);
name = GetVar(meshField, NAME);
MakeVar(meshField, DEFAULTICON);
defaultIcon = GetVar(meshField, 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, meshField);
DropIconInCorral(corral, icon);
return ObjTrue;
}
void InitMeshes()
/*Initializes the mesh object*/
{
ObjPtr icon, color;
#ifdef GRAPHICS
Object o;
float v[3], n[3];
short c[3];
#endif
/*Class for a mesh object*/
meshClass = NewObject(visDeformed, 0);
AddToReferenceList(meshClass);
SetVar(meshClass, NAME, NewString("Mesh"));
SetVar(meshClass, DEFAULTICON, icon = NewObject(visIcon, 0));
#ifdef GRAPHICS
#include "ScianGeoMesh.h"
SetVar(icon, CACHEGRAPHICS, NewInt(o));
#endif
SetVar(icon, WHICHICON, NewInt(ICONMESH));
SetVar(icon, NAME, NewString("Mesh"));
SetVar(icon, HELPSTRING,
NewString("This icon represents a mesh visualization object. \
The mesh object shows shaded mesh surfaces of 2-dimensional \
scalar fields defined over structured or nonstructured grids."));
DeclareIndirectDependency(meshClass, SURFACE, MAINDATASET, CHANGED);
DeclareDependency(meshClass, SURFACE, COLORCELLS);
SetMethod(meshClass, SURFACE, MakeMeshSurface);
DeclareDependency(meshClass, SURFACE, REVERSESENSE);
SetMethod(meshClass, PICCOLORED, MakeMeshColored);
SetVar(meshClass, COLORCELLS, NewInt(1));
DeclareDependency(meshClass, COLORCELLS);
AddSnapVar(meshClass, COLORCELLS);
DefineFixedClass(meshClass, CLASS_MESH, "visMesh");
SetMethod(meshClass, ADDCONTROLS, AddMeshControls);
icon = NewIcon(0, 0, ICONMESH, "Mesh");
SetVar(meshClass, CONTROLICON, icon);
SetVar(icon, PANELHELP, NewString("The Mesh visualization object shows 2-D \
scalar fields as a colored mesh. This panel lets you change parameters that \
control how the mesh is constructed."));
DefineVisMapping(DS_HASFORM | DS_HASFIELD, 2, 3, 1, meshClass);
DefineVisMapping(DS_HASFORM | DS_HASFIELD, 2, 2, 1, meshClass);
DefineVisMapping(DS_HASFORM | DS_HASFIELD | DS_UNSTRUCTURED, 2, 3, 1, meshClass);
DefineVisMapping(DS_HASFORM | DS_HASFIELD | DS_UNSTRUCTURED, 2, 2, 1, meshClass);
}
void KillMeshes()
/*Kills the mesh*/
{
DeleteThing(meshClass);
}
|