//
// VisADTriangleStripArray.java
//
/*
VisAD system for interactive analysis and visualization of numerical
data. Copyright (C) 1996 - 2017 Bill Hibbard, Curtis Rueden, Tom
Rink, Dave Glowacki, Steve Emmerson, Tom Whittaker, Don Murray, and
Tommy Jasmin.
This library 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.
This library 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 this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA
*/
package visad;
/**
VisADTriangleStripArray stands in for
j3d.TriangleStripArray and is Serializable.<P>
*/
public class VisADTriangleStripArray extends VisADGeometryArray {
public int[] stripVertexCounts;
public static VisADTriangleStripArray
merge(VisADTriangleStripArray[] arrays)
throws VisADException {
if (arrays == null || arrays.length == 0) return null;
VisADTriangleStripArray array = new VisADTriangleStripArray();
merge(arrays, array);
int n = arrays.length;
int nstrips = 0;
for (int i=0; i<n; i++) {
if (arrays[i] != null) {
nstrips += arrays[i].stripVertexCounts.length;
}
}
if (nstrips <= 0) return null;
int[] stripVertexCounts = new int[nstrips];
nstrips = 0;
for (int i=0; i<n; i++) {
if (arrays[i] != null) {
int incnstrips = arrays[i].stripVertexCounts.length;
for (int j=0; j<incnstrips; j++) {
stripVertexCounts[nstrips + j] = arrays[i].stripVertexCounts[j];
}
nstrips += incnstrips;
}
}
array.stripVertexCounts = stripVertexCounts;
return array;
}
private final static float LIMIT = 1.0f; // constant for TEST = 0
private final static double ALPHA = 0.01; // constant for TEST = 1
public VisADGeometryArray adjustSeam(DataRenderer renderer)
throws VisADException {
CoordinateSystem coord_sys = renderer.getDisplayCoordinateSystem();
// DRM 19 March 2002
//if (coord_sys == null || coord_sys instanceof SphericalCoordinateSystem) {
// return this;
//}
if (coord_sys == null || coord_sys instanceof SphericalCoordinateSystem ||
coordinates == null) {
return this;
}
int len = coordinates.length / 3;
double[][] cs = new double[3][len];
int j = 0;
for (int i=0; i<len; i++) {
cs[0][i] = coordinates[j++];
cs[1][i] = coordinates[j++];
cs[2][i] = coordinates[j++];
}
double[][] rs = coord_sys.fromReference(Set.copyDoubles(cs));
boolean[] test = new boolean[len];
int last_i;
// for TEST 0
double[] lengths = new double[len];
for (int i=0; i<len; i++) lengths[i] = 0.0f;
double mean_length = 0.0;
double var_length = 0.0;
double max_length = 0.0;
int num_length = 0;
boolean any_split = false;
// TEST 1
if (len < 2) return this;
double[][] bs = new double[3][len-1];
double[][] ss = new double[3][len-1];
double ALPHA1 = 1.0 + ALPHA;
double ALPHA1m = 1.0 - ALPHA;
for (int i=0; i<len-1; i++) {
// BS = point ALPHA * opposite direction
bs[0][i] = ALPHA1 * rs[0][i] - ALPHA * rs[0][i+1];
bs[1][i] = ALPHA1 * rs[1][i] - ALPHA * rs[1][i+1];
bs[2][i] = ALPHA1 * rs[2][i] - ALPHA * rs[2][i+1];
// SS = point ALPHA * same direction
ss[0][i] = ALPHA1 * rs[0][i+1] - ALPHA * rs[0][i];
ss[1][i] = ALPHA1 * rs[1][i+1] - ALPHA * rs[1][i];
ss[2][i] = ALPHA1 * rs[2][i+1] - ALPHA * rs[2][i];
}
double[][] ds = coord_sys.toReference(bs);
double[][] es = coord_sys.toReference(ss);
double IALPHA = 1.0 / ALPHA;
last_i = 0; // start i for each vertex strip
for (int i_svc=0; i_svc<stripVertexCounts.length; i_svc++) {
for (int i=last_i; i<last_i+stripVertexCounts[i_svc]-1; i++) {
// A = original line segment
double a0 = cs[0][i+1] - cs[0][i];
double a1 = cs[1][i+1] - cs[1][i];
double a2 = cs[2][i+1] - cs[2][i];
// B = estimate of vector using ALPHA * opposite direction
double b0 = IALPHA * (cs[0][i] - ds[0][i]);
double b1 = IALPHA * (cs[1][i] - ds[1][i]);
double b2 = IALPHA * (cs[2][i] - ds[2][i]);
double aa = (a0 * a0 + a1 * a1 + a2 * a2);
double aminusb =
(b0 - a0) * (b0 - a0) +
(b1 - a1) * (b1 - a1) +
(b2 - a2) * (b2 - a2);
double abratio = aminusb / aa;
// C = estimate of vector using ALPHA * opposite direction
double c0 = IALPHA * (cs[0][i+1] - es[0][i]);
double c1 = IALPHA * (cs[1][i+1] - es[1][i]);
double c2 = IALPHA * (cs[2][i+1] - es[2][i]);
double aminusc =
(c0 + a0) * (c0 + a0) +
(c1 + a1) * (c1 + a1) +
(c2 + a2) * (c2 + a2);
double acratio = aminusc / aa;
// true for bad segment
test[i] = (0.01f < abratio) || (0.01f < acratio);
/*
double bb = (b0 * b0 + b1 * b1 + b2 * b2);
double ab = (b0 * a0 + b1 * a1 + b2 * a2);
// b = A projected onto B, as a signed fraction of B
double b = ab / bb;
// c = (norm(A projected onto B) / norm(A)) ^ 2
double c = (ab * ab) / (aa * bb);
test[i] = !(0.5f < b && b < 2.0f && 0.5f < c);
*/
// TEST 0
double cd = (cs[0][i+1] - cs[0][i]) * (cs[0][i+1] - cs[0][i]) +
(cs[1][i+1] - cs[1][i]) * (cs[1][i+1] - cs[1][i]) +
(cs[2][i+1] - cs[2][i]) * (cs[2][i+1] - cs[2][i]);
if (!test[i]) {
lengths[i] = cd;
num_length++;
mean_length += lengths[i];
var_length += lengths[i] * lengths[i];
if (lengths[i] > max_length) max_length = lengths[i];
}
} // end for (int i=last_i; i<last_i+stripVertexCounts[i_svc]*3; i+=3)
last_i += stripVertexCounts[i_svc];
} // end for (int i_svc=0; i_svc<stripVertexCounts.length; i_svc++)
cs = null;
rs = null;
bs = null;
ss = null;
ds = null;
es = null;
// TEST 0
if (num_length < 2) return this;
mean_length = mean_length / num_length;
var_length = //(float)
Math.sqrt((var_length - mean_length * mean_length) / num_length);
double limit_length = mean_length + LIMIT * var_length;
if (max_length >= limit_length) {
last_i = 0; // start i for each vertex strip
for (int i_svc=0; i_svc<stripVertexCounts.length; i_svc++) {
for (int i=last_i; i<last_i+stripVertexCounts[i_svc]-1; i++) {
// WLH 20 June 2001
// test[i] = test[i] || (lengths[i] > limit_length);
if (test[i]) any_split = true;
} // end for (int i=last_i; i<last_i+stripVertexCounts[i_svc]*3; i+=3)
last_i += stripVertexCounts[i_svc];
} // end for (int i_svc=0; i_svc<stripVertexCounts.length; i_svc++)
}
// System.out.println("any_split = " + any_split);
if (!any_split) {
return this;
}
// most recent point
float[] lastcoord = null;
float[] lastno = null;
byte[] lastcol = null;
float[] lasttex = null;
// point before most recent
float[] earlycoord = null;
float[] earlyno = null;
byte[] earlycol = null;
float[] earlytex = null;
// this point
float[] coord = null;
float[] no = null;
byte[] col = null;
float[] tex = null;
VisADTriangleStripArray array = new VisADTriangleStripArray();
// worst case makes 3 times as many triangles
int worst = 6; // WLH 30 Dec 99 - try new worst
float[] coords = new float[worst * coordinates.length];
float[] nos = null;
if (normals != null) {
nos = new float[worst * normals.length];
}
int color_length = 0;
byte[] cols = null;
if (colors != null) {
color_length = 3;
cols = new byte[worst * colors.length];
if (colors.length != coordinates.length) color_length = 4;
}
float[] texs = null;
if (texCoords != null) {
texs = new float[worst * texCoords.length];
}
// worst case makes as many strips as there were points
int[] svcs = new int[coordinates.length];
int svc_index = 0;
last_i = 0; // start i for each vertex strip
int[] kmr = {0, 0, 0};
int t = 0;
j = 0;
any_split = false;
for (int i_svc=0; i_svc<stripVertexCounts.length; i_svc++) {
boolean this_split = false;
int accum = 0; // strip counter
j = (color_length * last_i / 3) - color_length;
t = (2 * last_i / 3) - 2;
for (int i=last_i; i<last_i+stripVertexCounts[i_svc]*3-3; i+=3) {
j += color_length;
t += 2;
boolean last_split = this_split; // true if last edge was split
if (test[i/3]) {
this_split = true;
any_split = true;
// treat split as a break
if (accum >= 3) {
svcs[svc_index] = accum;
svc_index++;
}
lastcoord = new float[]
{coordinates[i+3], coordinates[i+4], coordinates[i+5]};
if (normals != null) {
lastno = new float[]
{normals[i+3], normals[i+4], normals[i+5]};
}
if (color_length == 3) {
lastcol = new byte[]
{colors[j+3], colors[j+4], colors[j+5]};
}
else if (color_length == 4) {
lastcol = new byte[]
{colors[j+4], colors[j+5], colors[j+6], colors[j+7]};
}
if (texCoords != null) {
lasttex = new float[]
{texCoords[t+2], texCoords[t+3]};
}
accum = 1; // reset strip counter;
continue;
}
else { // no split
this_split = false;
}
if (!this_split) {
if (accum == 0) {
earlycoord = new float[]
{coordinates[i], coordinates[i+1], coordinates[i+2]};
lastcoord = new float[]
{coordinates[i+3], coordinates[i+4], coordinates[i+5]};
if (normals != null) {
earlyno = new float[]
{normals[i], normals[i+1], normals[i+2]};
lastno = new float[]
{normals[i+3], normals[i+4], normals[i+5]};
}
if (color_length == 3) {
earlycol = new byte[]
{colors[j], colors[j+1], colors[j+2]};
lastcol = new byte[]
{colors[j+3], colors[j+4], colors[j+5]};
}
else if (color_length == 4) {
earlycol = new byte[]
{colors[j], colors[j+1], colors[j+2], colors[j+3]};
lastcol = new byte[]
{colors[j+4], colors[j+5], colors[j+6], colors[j+7]};
}
if (texCoords != null) {
earlytex = new float[]
{texCoords[t], texCoords[t+1]};
lasttex = new float[]
{texCoords[t+2], texCoords[t+3]};
}
accum = 2;
continue; // don't make any triangles yet, for accum = 0
} // end if (accum == 0)
else { // (!last_split || lon_axis < 0) && accum > 0 && !this_split
// just add the next point (i+3)
coord = new float[]
{coordinates[i+3], coordinates[i+4], coordinates[i+5]};
if (normals != null) {
no = new float[]
{normals[i+3], normals[i+4], normals[i+5]};
}
if (color_length == 3) {
col = new byte[]
{colors[j+3], colors[j+4], colors[j+5]};
}
else if (color_length == 4) {
col = new byte[]
{colors[j+4], colors[j+5], colors[j+6], colors[j+7]};
}
if (texCoords != null) {
tex = new float[]
{texCoords[t+2], texCoords[t+3]};
}
accum++;
// WLH
if (earlycoord == null) {
earlycoord = new float[3];
if (normals != null) {
earlyno = new float[3];
}
if (color_length > 0) {
earlycol = new byte[color_length];
}
if (texCoords != null) {
earlytex = new float[2];
}
}
nextPoint(accum, color_length, coords, nos, cols, texs,
coord, no, col, tex, lastcoord, lastno, lastcol,
lasttex, earlycoord, earlyno, earlycol, earlytex, kmr);
}
} // end if no split
} // end for (int i=last_i; i<last_i+stripVertexCounts[i_svc]*3-3; i+=3)
if (accum >= 3) {
svcs[svc_index] = accum;
svc_index++;
}
last_i += stripVertexCounts[i_svc] * 3;
} // end for (int i_svc=0; i_svc<stripVertexCounts.length; i_svc++)
if (!any_split) {
return this;
}
else {
array.coordinates = new float[kmr[0]];
System.arraycopy(coords, 0, array.coordinates, 0, kmr[0]);
if (normals != null) {
array.normals = new float[kmr[0]];
System.arraycopy(nos, 0, array.normals, 0, kmr[0]);
}
if (colors != null) {
array.colors = new byte[kmr[1]];
System.arraycopy(cols, 0, array.colors, 0, kmr[1]);
}
if (texCoords != null) {
array.texCoords = new float[kmr[2]];
System.arraycopy(texs, 0, array.texCoords, 0, kmr[2]);
}
array.vertexCount = kmr[0] / 3;
array.stripVertexCounts = new int[svc_index];
System.arraycopy(svcs, 0, array.stripVertexCounts, 0, svc_index);
return array;
}
}
/* */
public VisADGeometryArray adjustLongitude(DataRenderer renderer)
throws VisADException {
float[] lons = getLongitudes(renderer);
if (lons == null) return this;
int[] axis = new int[1];
float[] lon_coords = new float[2];
float[] lon_range = getLongitudeRange(lons, axis, lon_coords);
if (lon_range[0] != lon_range[0] ||
lon_range[1] != lon_range[1]) return this;
float bottom = lon_range[0];
float top = lon_range[1];
float low = bottom + 30.0f;
float hi = top - 30.0f;
int lon_axis = axis[0];
float coord_bottom = lon_coords[0];
float coord_top = lon_coords[1];
// midpoint from this (if this_split)
float[] midcoord_first = null;
float[] midcoord_second = null;
float[] midno = null;
byte[] midcol = null;
float[] midtex = null;
// save midpoint from last (if last_split)
float[] last_midcoord_first = null;
float[] last_midcoord_second = null;
float[] last_midno = null;
byte[] last_midcol = null;
float[] last_midtex = null;
// midpoint between -3 and +3 (if this_split^last_split)
float[] sillymidcoord_first = null;
float[] sillymidcoord_second = null;
float[] sillymidno = null;
byte[] sillymidcol = null;
float[] sillymidtex = null;
// most recent point
float[] lastcoord = null;
float[] lastno = null;
byte[] lastcol = null;
float[] lasttex = null;
// point before most recent
float[] earlycoord = null;
float[] earlyno = null;
byte[] earlycol = null;
float[] earlytex = null;
// this point
float[] coord = null;
float[] no = null;
byte[] col = null;
float[] tex = null;
VisADTriangleStripArray array = new VisADTriangleStripArray();
// worst case makes 3 times as many triangles
int worst = 6; // WLH 30 Dec 99 - try new worst
float[] coords = new float[worst * coordinates.length];
float[] nos = null;
if (normals != null) {
nos = new float[worst * normals.length];
}
int color_length = 0;
byte[] cols = null;
if (colors != null) {
color_length = 3;
cols = new byte[worst * colors.length];
if (colors.length != coordinates.length) color_length = 4;
}
float[] texs = null;
if (texCoords != null) {
texs = new float[worst * texCoords.length];
}
// worst case makes as many strips as there were points
int[] svcs = new int[coordinates.length];
int svc_index = 0;
int last_i = 0; // start i for each vertex strip
int[] kmr = {0, 0, 0};
int t = 0;
int j = 0;
boolean any_split = false;
for (int i_svc=0; i_svc<stripVertexCounts.length; i_svc++) {
boolean this_split = false;
int accum = 0; // strip counter
j = (color_length * last_i / 3) - color_length;
t = (2 * last_i / 3) - 2;
for (int i=last_i; i<last_i+stripVertexCounts[i_svc]*3-3; i+=3) {
j += color_length;
t += 2;
boolean last_split = this_split; // true if last edge was split
if (last_split) {
last_midcoord_first = midcoord_first;
last_midcoord_second = midcoord_second;
last_midno = midno;
last_midcol = midcol;
last_midtex = midtex;
}
int i3 = i / 3;
if ((lons[i3] < low && hi < lons[i3 + 1]) ||
(lons[i3 + 1] < low && hi < lons[i3])) {
/*
System.out.println("any_split " + lons[i3] + " " + lons[i3 + 1] + " " +
low + " " + hi + " " + bottom + " " + top);
*/
this_split = true;
any_split = true;
if (lon_axis < 0) {
// not enough info to interpolate, so treat split as a break
if (accum >= 3) {
svcs[svc_index] = accum;
svc_index++;
}
lastcoord = new float[]
{coordinates[i+3], coordinates[i+4], coordinates[i+5]};
if (normals != null) {
lastno = new float[]
{normals[i+3], normals[i+4], normals[i+5]};
}
if (color_length == 3) {
lastcol = new byte[]
{colors[j+3], colors[j+4], colors[j+5]};
}
else if (color_length == 4) {
lastcol = new byte[]
{colors[j+4], colors[j+5], colors[j+6], colors[j+7]};
}
if (texCoords != null) {
lasttex = new float[]
{texCoords[t+2], texCoords[t+3]};
}
accum = 1; // reset strip counter;
continue;
}
// lon_axis >= 0
// split line by interpolation
float a, b;
float coord_first, coord_second;
if (lons[i3] < low) {
a = lons[i3] - bottom;
b = top - lons[i3 + 1];
coord_first = coord_bottom;
coord_second = coord_top;
}
else {
a = top - lons[i3];
b = lons[i3 + 1] - bottom;
coord_first = coord_top;
coord_second = coord_bottom;
}
float alpha = b / (a + b);
alpha = (alpha != alpha || alpha < 0.0f) ? 0.0f :
((1.0f < alpha) ? 1.0f : alpha);
float beta = 1.0f - alpha;
midcoord_first = new float[]
{alpha * coordinates[i] + beta * coordinates[i+3],
alpha * coordinates[i+1] + beta * coordinates[i+4],
alpha * coordinates[i+2] + beta * coordinates[i+5]};
midcoord_second = new float[]
{midcoord_first[0], midcoord_first[1], midcoord_first[2]};
midcoord_first[lon_axis] = coord_first;
midcoord_second[lon_axis] = coord_second;
if (normals != null) {
midno = new float[]
{alpha * normals[i] + beta * normals[i+3],
alpha * normals[i+1] + beta * normals[i+4],
alpha * normals[i+2] + beta * normals[i+5]};
}
if (color_length == 3) {
midcol = new byte[]
{ShadowType.floatToByte(
alpha * ShadowType.byteToFloat(colors[j]) +
beta * ShadowType.byteToFloat(colors[j+3])),
ShadowType.floatToByte(
alpha * ShadowType.byteToFloat(colors[j+1]) +
beta * ShadowType.byteToFloat(colors[j+4])),
ShadowType.floatToByte(
alpha * ShadowType.byteToFloat(colors[j+2]) +
beta * ShadowType.byteToFloat(colors[j+5]))};
}
else if (color_length == 4) {
midcol = new byte[]
{ShadowType.floatToByte(
alpha * ShadowType.byteToFloat(colors[j]) +
beta * ShadowType.byteToFloat(colors[j+4])),
ShadowType.floatToByte(
alpha * ShadowType.byteToFloat(colors[j+1]) +
beta * ShadowType.byteToFloat(colors[j+5])),
ShadowType.floatToByte(
alpha * ShadowType.byteToFloat(colors[j+2]) +
beta * ShadowType.byteToFloat(colors[j+6])),
ShadowType.floatToByte(
alpha * ShadowType.byteToFloat(colors[j+3]) +
beta * ShadowType.byteToFloat(colors[j+7]))};
}
if (texCoords != null) {
midtex = new float[]
{alpha * texCoords[t] + beta * texCoords[t+2],
alpha * texCoords[t+1] + beta * texCoords[t+3]};
}
}
else { // no split
this_split = false;
}
if (accum > 0 && this_split != last_split && lon_axis >= 0) {
// need to compute mid edge from -3 to +3
// split line by interpolation
float a, b;
float coord_first, coord_second;
if (lons[i3 - 1] < low) {
a = lons[i3 - 1] - bottom;
b = top - lons[i3 + 1];
coord_first = coord_bottom;
coord_second = coord_top;
}
else {
a = top - lons[i3 - 1];
b = lons[i3 + 1] - bottom;
coord_first = coord_top;
coord_second = coord_bottom;
}
float alpha = b / (a + b);
alpha = (alpha != alpha || alpha < 0.0f) ? 0.0f :
((1.0f < alpha) ? 1.0f : alpha);
float beta = 1.0f - alpha;
sillymidcoord_first = new float[]
{alpha * coordinates[i-3] + beta * coordinates[i+3],
alpha * coordinates[i-2] + beta * coordinates[i+4],
alpha * coordinates[i-1] + beta * coordinates[i+5]};
sillymidcoord_second = new float[]
{sillymidcoord_first[0], sillymidcoord_first[1], sillymidcoord_first[2]};
sillymidcoord_first[lon_axis] = coord_first;
sillymidcoord_second[lon_axis] = coord_second;
if (normals != null) {
sillymidno = new float[]
{alpha * normals[i-3] + beta * normals[i+3],
alpha * normals[i-2] + beta * normals[i+4],
alpha * normals[i-1] + beta * normals[i+5]};
}
if (color_length == 3) {
sillymidcol = new byte[]
{ShadowType.floatToByte(
alpha * ShadowType.byteToFloat(colors[j-3]) +
beta * ShadowType.byteToFloat(colors[j+3])),
ShadowType.floatToByte(
alpha * ShadowType.byteToFloat(colors[j-2]) +
beta * ShadowType.byteToFloat(colors[j+4])),
ShadowType.floatToByte(
alpha * ShadowType.byteToFloat(colors[j-1]) +
beta * ShadowType.byteToFloat(colors[j+5]))};
}
else if (color_length == 4) {
sillymidcol = new byte[]
{ShadowType.floatToByte(
alpha * ShadowType.byteToFloat(colors[j-4]) +
beta * ShadowType.byteToFloat(colors[j+4])),
ShadowType.floatToByte(
alpha * ShadowType.byteToFloat(colors[j-3]) +
beta * ShadowType.byteToFloat(colors[j+5])),
ShadowType.floatToByte(
alpha * ShadowType.byteToFloat(colors[j-2]) +
beta * ShadowType.byteToFloat(colors[j+6])),
ShadowType.floatToByte(
alpha * ShadowType.byteToFloat(colors[j-1]) +
beta * ShadowType.byteToFloat(colors[j+7]))};
}
if (texCoords != null) {
sillymidtex = new float[]
{alpha * texCoords[t-2] + beta * texCoords[t+2],
alpha * texCoords[t-1] + beta * texCoords[t+3]};
}
}
if (this_split) {
if (accum == 0) {
earlycoord = new float[]
{midcoord_second[0], midcoord_second[1], midcoord_second[2]};
lastcoord = new float[]
{coordinates[i+3], coordinates[i+4], coordinates[i+5]};
if (normals != null) {
earlyno = new float[]
{midno[0], midno[1], midno[2]};
lastno = new float[]
{normals[i+3], normals[i+4], normals[i+5]};
}
if (color_length == 3) {
earlycol = new byte[]
{midcol[0], midcol[1], midcol[2]};
lastcol = new byte[]
{colors[j+3], colors[j+4], colors[j+5]};
}
else if (color_length == 4) {
earlycol = new byte[]
{midcol[0], midcol[1], midcol[2], midcol[3]};
lastcol = new byte[]
{colors[j+4], colors[j+5], colors[j+6], colors[j+7]};
}
if (texCoords != null) {
earlytex = new float[]
{midtex[0], midtex[1]};
lasttex = new float[]
{texCoords[t+2], texCoords[t+3]};
}
accum = 2;
continue; // don't make any triangles yet, for accum = 0
} // end if (accum == 0)
else if (last_split) { // && this_split
coord = midcoord_first;
no = midno;
col = midcol;
tex = midtex;
accum++;
nextPoint(accum, color_length, coords, nos, cols, texs,
coord, no, col, tex, lastcoord, lastno, lastcol,
lasttex, earlycoord, earlyno, earlycol, earlytex, kmr);
// bind off
svcs[svc_index] = accum;
svc_index++;
// accum = 0, but more to come
// create a 2-triangle strip
// (last_mid_first, i-3, mid_second, i+3)
earlycoord = last_midcoord_first;
earlyno = last_midno;
earlycol = last_midcol;
earlytex = last_midtex;
lastcoord = new float[]
{coordinates[i-3], coordinates[i-2], coordinates[i-1]};
if (normals != null) {
lastno = new float[]
{normals[i-3], normals[i-2], normals[i-1]};
}
if (color_length == 3) {
lastcol = new byte[]
{colors[j-3], colors[j-2], colors[j-1]};
}
else if (color_length == 4) {
lastcol = new byte[]
{colors[j-4], colors[j-3], colors[j-2], colors[j-1]};
}
if (texCoords != null) {
lasttex = new float[]
{texCoords[t-2], texCoords[t-1]};
}
coord = midcoord_second;
no = midno;
col = midcol;
tex = midtex;
accum = 3;
nextPoint(accum, color_length, coords, nos, cols, texs,
coord, no, col, tex, lastcoord, lastno, lastcol,
lasttex, earlycoord, earlyno, earlycol, earlytex, kmr);
coord = new float[]
{coordinates[i+3], coordinates[i+4], coordinates[i+5]};
if (normals != null) {
no = new float[]
{normals[i+3], normals[i+4], normals[i+5]};
}
if (color_length == 3) {
col = new byte[]
{colors[j+3], colors[j+4], colors[j+5]};
}
else if (color_length == 4) {
col = new byte[]
{colors[j+4], colors[j+5], colors[j+6], colors[j+7]};
}
if (texCoords != null) {
tex = new float[]
{texCoords[t+2], texCoords[t+3]};
}
accum++;
nextPoint(accum, color_length, coords, nos, cols, texs,
coord, no, col, tex, lastcoord, lastno, lastcol,
lasttex, earlycoord, earlyno, earlycol, earlytex, kmr);
}
else { // !last_split && accum > 0 && this_split
// add (mid_first, i-3, sillymid_first)
coord = midcoord_first;
no = midno;
col = midcol;
tex = midtex;
accum++;
nextPoint(accum, color_length, coords, nos, cols, texs,
coord, no, col, tex, lastcoord, lastno, lastcol,
lasttex, earlycoord, earlyno, earlycol, earlytex, kmr);
coord = new float[]
{coordinates[i-3], coordinates[i-2], coordinates[i-1]};
if (normals != null) {
no = new float[]
{normals[i-3], normals[i-2], normals[i-1]};
}
if (color_length == 3) {
col = new byte[]
{colors[j-3], colors[j-2], colors[j-1]};
}
else if (color_length == 4) {
col = new byte[]
{colors[j-4], colors[j-3], colors[j-2], colors[j-1]};
}
if (texCoords != null) {
tex = new float[]
{texCoords[t-2], texCoords[t-1]};
}
accum++;
nextPoint(accum, color_length, coords, nos, cols, texs,
coord, no, col, tex, lastcoord, lastno, lastcol,
lasttex, earlycoord, earlyno, earlycol, earlytex, kmr);
coord = sillymidcoord_first;
no = sillymidno;
col = sillymidcol;
tex = sillymidtex;
accum++;
nextPoint(accum, color_length, coords, nos, cols, texs,
coord, no, col, tex, lastcoord, lastno, lastcol,
lasttex, earlycoord, earlyno, earlycol, earlytex, kmr);
// (accum >= 3)
svcs[svc_index] = accum;
svc_index++;
// accum = 0, but more to come
// start a triangle strip
// (sillymid_second, mid_second, i+3)
earlycoord = sillymidcoord_second;
earlyno = sillymidno;
earlycol = sillymidcol;
earlytex = sillymidtex;
lastcoord = midcoord_second;
lastno = midno;
lastcol = midcol;
lasttex = midtex;
coord = new float[]
{coordinates[i+3], coordinates[i+4], coordinates[i+5]};
if (normals != null) {
no = new float[]
{normals[i+3], normals[i+4], normals[i+5]};
}
if (color_length == 3) {
col = new byte[]
{colors[j+3], colors[j+4], colors[j+5]};
}
else if (color_length == 4) {
col = new byte[]
{colors[j+4], colors[j+5], colors[j+6], colors[j+7]};
}
if (texCoords != null) {
tex = new float[]
{texCoords[t+2], texCoords[t+3]};
}
accum = 3;
nextPoint(accum, color_length, coords, nos, cols, texs,
coord, no, col, tex, lastcoord, lastno, lastcol,
lasttex, earlycoord, earlyno, earlycol, earlytex, kmr);
}
}
else { // !this_split
if (accum == 0) {
earlycoord = new float[]
{coordinates[i], coordinates[i+1], coordinates[i+2]};
lastcoord = new float[]
{coordinates[i+3], coordinates[i+4], coordinates[i+5]};
if (normals != null) {
earlyno = new float[]
{normals[i], normals[i+1], normals[i+2]};
lastno = new float[]
{normals[i+3], normals[i+4], normals[i+5]};
}
if (color_length == 3) {
earlycol = new byte[]
{colors[j], colors[j+1], colors[j+2]};
lastcol = new byte[]
{colors[j+3], colors[j+4], colors[j+5]};
}
else if (color_length == 4) {
earlycol = new byte[]
{colors[j], colors[j+1], colors[j+2], colors[j+3]};
lastcol = new byte[]
{colors[j+4], colors[j+5], colors[j+6], colors[j+7]};
}
if (texCoords != null) {
earlytex = new float[]
{texCoords[t], texCoords[t+1]};
lasttex = new float[]
{texCoords[t+2], texCoords[t+3]};
}
accum = 2;
continue; // don't make any triangles yet, for accum = 0
} // end if (accum == 0)
else if (last_split && lon_axis >= 0) { // && !this_split
// first, bind off
if (accum >= 3) {
svcs[svc_index] = accum;
svc_index++;
}
// accum = 0, but more to come
// create a lone triangle (i-3, last_mid_first, sillymid_first)
earlycoord = new float[]
{coordinates[i-3], coordinates[i-2], coordinates[i-1]};
if (normals != null) {
earlyno = new float[]
{normals[i-3], normals[i-2], normals[i-1]};
}
if (color_length == 3) {
earlycol = new byte[]
{colors[j-3], colors[j-2], colors[j-1]};
}
else if (color_length == 4) {
earlycol = new byte[]
{colors[j-4], colors[j-3], colors[j-2], colors[j-1]};
}
if (texCoords != null) {
earlytex = new float[]
{texCoords[t-2], texCoords[t-1]};
}
lastcoord = last_midcoord_first;
lastno = last_midno;
lastcol = last_midcol;
lasttex = last_midtex;
coord = sillymidcoord_first;
no = sillymidno;
col = sillymidcol;
tex = sillymidtex;
accum = 3;
nextPoint(accum, color_length, coords, nos, cols, texs,
coord, no, col, tex, lastcoord, lastno, lastcol,
lasttex, earlycoord, earlyno, earlycol, earlytex, kmr);
// bind off again
svcs[svc_index] = accum;
svc_index++;
// accum = 0, but more to come
// create a 2-triangle strip
// (last_mid_second, sillymid_second, i, i+3)
earlycoord = last_midcoord_second;
earlyno = last_midno;
earlycol = last_midcol;
earlytex = last_midtex;
lastcoord = sillymidcoord_second;
lastno = sillymidno;
lastcol = sillymidcol;
lasttex = sillymidtex;
coord = new float[]
{coordinates[i], coordinates[i+1], coordinates[i+2]};
if (normals != null) {
no = new float[]
{normals[i], normals[i+1], normals[i+2]};
}
if (color_length == 3) {
col = new byte[]
{colors[j], colors[j+1], colors[j+2]};
}
else if (color_length == 4) {
col = new byte[]
{colors[j], colors[j+1], colors[j+2], colors[j+3]};
}
if (texCoords != null) {
tex = new float[]
{texCoords[t], texCoords[t+1]};
}
accum = 3;
nextPoint(accum, color_length, coords, nos, cols, texs,
coord, no, col, tex, lastcoord, lastno, lastcol,
lasttex, earlycoord, earlyno, earlycol, earlytex, kmr);
coord = new float[]
{coordinates[i+3], coordinates[i+4], coordinates[i+5]};
if (normals != null) {
no = new float[]
{normals[i+3], normals[i+4], normals[i+5]};
}
if (color_length == 3) {
col = new byte[]
{colors[j+3], colors[j+4], colors[j+5]};
}
else if (color_length == 4) {
col = new byte[]
{colors[j+4], colors[j+5], colors[j+6], colors[j+7]};
}
if (texCoords != null) {
tex = new float[]
{texCoords[t+2], texCoords[t+3]};
}
accum++;
nextPoint(accum, color_length, coords, nos, cols, texs,
coord, no, col, tex, lastcoord, lastno, lastcol,
lasttex, earlycoord, earlyno, earlycol, earlytex, kmr);
}
else { // (!last_split || lon_axis < 0) && accum > 0 && !this_split
// just add the next point (i+3)
if (earlycoord == null) {
earlycoord = new float[3];
if (normals != null) {
earlyno = new float[3];
}
if (color_length > 0) {
earlycol = new byte[color_length];
}
if (texCoords != null) {
earlytex = new float[2];
}
}
coord = new float[]
{coordinates[i+3], coordinates[i+4], coordinates[i+5]};
if (normals != null) {
no = new float[]
{normals[i+3], normals[i+4], normals[i+5]};
}
if (color_length == 3) {
col = new byte[]
{colors[j+3], colors[j+4], colors[j+5]};
}
else if (color_length == 4) {
col = new byte[]
{colors[j+4], colors[j+5], colors[j+6], colors[j+7]};
}
if (texCoords != null) {
tex = new float[]
{texCoords[t+2], texCoords[t+3]};
}
accum++;
nextPoint(accum, color_length, coords, nos, cols, texs,
coord, no, col, tex, lastcoord, lastno, lastcol,
lasttex, earlycoord, earlyno, earlycol, earlytex, kmr);
}
} // end if no split
} // end for (int i=last_i; i<last_i+stripVertexCounts[i_svc]*3-3; i+=3)
if (accum >= 3) {
svcs[svc_index] = accum;
svc_index++;
}
last_i += stripVertexCounts[i_svc] * 3;
} // end for (int i_svc=0; i_svc<stripVertexCounts.length; i_svc++)
if (!any_split) {
return this;
}
else {
array.coordinates = new float[kmr[0]];
System.arraycopy(coords, 0, array.coordinates, 0, kmr[0]);
if (normals != null) {
array.normals = new float[kmr[0]];
System.arraycopy(nos, 0, array.normals, 0, kmr[0]);
}
if (colors != null) {
array.colors = new byte[kmr[1]];
System.arraycopy(cols, 0, array.colors, 0, kmr[1]);
}
if (texCoords != null) {
array.texCoords = new float[kmr[2]];
System.arraycopy(texs, 0, array.texCoords, 0, kmr[2]);
}
array.vertexCount = kmr[0] / 3;
array.stripVertexCounts = new int[svc_index];
System.arraycopy(svcs, 0, array.stripVertexCounts, 0, svc_index);
return array;
}
}
private void nextPoint(int accum, int color_length, float[] coords,
float[] nos, byte[] cols, float[] texs,
float[] coord, float[] no, byte[] col, float[] tex,
float[] lastcoord, float[] lastno, byte[] lastcol,
float[] lasttex, float[] earlycoord, float[] earlyno,
byte[] earlycol, float[] earlytex, int[] kmr) {
if (accum == 2) {
System.arraycopy(lastcoord, 0, earlycoord, 0, 3);
System.arraycopy(coord, 0, lastcoord, 0, 3);
if (normals != null) {
System.arraycopy(lastno, 0, earlyno, 0, 3);
System.arraycopy(no, 0, lastno, 0, 3);
}
if (colors != null) {
System.arraycopy(lastcol, 0, earlycol, 0, color_length);
System.arraycopy(col, 0, lastcol, 0, color_length);
}
if (texCoords != null) {
/* WLH 9 March 2000
System.arraycopy(lasttex, 0, earlytex, 0, 3);
System.arraycopy(tex, 0, lasttex, 0, 3);
*/
System.arraycopy(lasttex, 0, earlytex, 0, 2);
System.arraycopy(tex, 0, lasttex, 0, 2);
}
return;
}
else if (accum == 3) {
// put early point on new strip
coords[kmr[0]] = earlycoord[0];
coords[kmr[0]+1] = earlycoord[1];
coords[kmr[0]+2] = earlycoord[2];
if (normals != null) {
nos[kmr[0]] = earlyno[0];
nos[kmr[0]+1] = earlyno[1];
nos[kmr[0]+2] = earlyno[2];
}
kmr[0] += 3;
if (colors != null) {
cols[kmr[1]] = earlycol[0];
cols[kmr[1]+1] = earlycol[1];
cols[kmr[1]+2] = earlycol[2];
kmr[1] += 3;
if (color_length == 4) {
cols[kmr[1]++] = earlycol[3];
}
}
if (texCoords != null) {
texs[kmr[2]] = earlytex[0];
texs[kmr[2]+1] = earlytex[1];
kmr[2] += 2;
}
// put last point on new strip
coords[kmr[0]] = lastcoord[0];
coords[kmr[0]+1] = lastcoord[1];
coords[kmr[0]+2] = lastcoord[2];
if (normals != null) {
nos[kmr[0]] = lastno[0];
nos[kmr[0]+1] = lastno[1];
nos[kmr[0]+2] = lastno[2];
}
kmr[0] += 3;
if (colors != null) {
cols[kmr[1]] = lastcol[0];
cols[kmr[1]+1] = lastcol[1];
cols[kmr[1]+2] = lastcol[2];
kmr[1] += 3;
if (color_length == 4) {
cols[kmr[1]++] = lastcol[3];
}
}
if (texCoords != null) {
texs[kmr[2]] = lasttex[0];
texs[kmr[2]+1] = lasttex[1];
kmr[2] += 2;
}
} // end if (accum == 3)
// put this point on new strip
coords[kmr[0]] = coord[0];
coords[kmr[0]+1] = coord[1];
coords[kmr[0]+2] = coord[2];
if (normals != null) {
nos[kmr[0]] = no[0];
nos[kmr[0]+1] = no[1];
nos[kmr[0]+2] = no[2];
}
kmr[0] += 3;
if (colors != null) {
cols[kmr[1]] = col[0];
cols[kmr[1]+1] = col[1];
cols[kmr[1]+2] = col[2];
kmr[1] += 3;
if (color_length == 4) {
cols[kmr[1]++] = col[3];
}
}
if (texCoords != null) {
texs[kmr[2]] = tex[0];
texs[kmr[2]+1] = tex[1];
kmr[2] += 2;
}
}
public VisADGeometryArray removeMissing() {
VisADTriangleStripArray array = new VisADTriangleStripArray();
float[] coords = new float[coordinates.length];
float[] nos = null;
if (normals != null) {
nos = new float[normals.length];
}
int color_length = 3;
byte[] cols = null;
if (colors != null) {
cols = new byte[colors.length];
if (colors.length != coordinates.length) color_length = 4;
}
float[] texs = null;
if (texCoords != null) {
texs = new float[texCoords.length];
}
int[] svcs = new int[coordinates.length / 4];
int svc_index = 0;
int last_i = 0; // start i for each vertex strip
int k = 0;
int m = 0;
int t = 0;
int r = 0;
int j = 0;
boolean any_missing = false;
for (int i_svc=0; i_svc<stripVertexCounts.length; i_svc++) {
int accum = 0; // strip counter
j = color_length * last_i / 3;
t = 2 * last_i / 3;
for (int i=last_i; i<last_i+stripVertexCounts[i_svc]*3; i+=3) {
if (coordinates[i] == coordinates[i] &&
coordinates[i+1] == coordinates[i+1] &&
coordinates[i+2] == coordinates[i+2]) {
accum++;
if (accum >= 3) {
int iml = i;
int jml = j;
int tml = t;
if (accum == 3) {
iml = i - 6;
jml = j - 2 * color_length;
tml = t - 4;
}
int jm = jml;
int tm = tml;
for (int im=iml; im<=i; im+=3) {
coords[k] = coordinates[im];
coords[k+1] = coordinates[im+1];
coords[k+2] = coordinates[im+2];
if (normals != null) {
nos[k] = normals[im];
nos[k+1] = normals[im+1];
nos[k+2] = normals[im+2];
}
if (colors != null) {
cols[m] = colors[jm];
cols[m+1] = colors[jm+1];
cols[m+2] = colors[jm+2];
m += 3;
if (color_length == 4) {
cols[m++] = colors[jm+3];
}
}
if (texCoords != null) {
texs[r] = texCoords[tm];
texs[r+1] = texCoords[tm+1];
r += 2;
}
k += 3;
jm += color_length;
tm += 2;
} // end for (im=iml; im<=i; im+=3)
} // end if (accum >= 3)
}
else { // missing coordinates values
any_missing = true;
if (accum >= 3) {
svcs[svc_index] = accum;
svc_index++;
}
accum = 0; // reset strip counter;
}
j += color_length;
t += 2;
} // end for (int i=last_i; i<last_i+stripVertexCounts[i_svc]*3; i+=3)
if (accum >= 3) {
svcs[svc_index] = accum;
svc_index++;
}
last_i += stripVertexCounts[i_svc] * 3;
} // end for (int i_svc=0; i_svc<stripVertexCounts.length; i_svc++)
if (!any_missing) {
return this;
}
else {
array.coordinates = new float[k];
System.arraycopy(coords, 0, array.coordinates, 0, k);
if (normals != null) {
array.normals = new float[k];
System.arraycopy(nos, 0, array.normals, 0, k);
}
if (colors != null) {
array.colors = new byte[m];
System.arraycopy(cols, 0, array.colors, 0, m);
}
if (texCoords != null) {
array.texCoords = new float[r];
System.arraycopy(texs, 0, array.texCoords, 0, r);
}
array.vertexCount = k / 3;
array.stripVertexCounts = new int[svc_index];
System.arraycopy(svcs, 0, array.stripVertexCounts, 0, svc_index);
return array;
}
}
public String toString() {
/*
String string = "VisADTriangleStripArray\n" + super.toString() +
"\n indexCount = " + indexCount;
*/
String string = "VisADTriangleStripArray ";
string = string + "\n stripVertexCounts = ";
for (int i=0; i<stripVertexCounts.length; i++) {
string = string + stripVertexCounts[i] + " ";
}
return string;
}
public Object clone() {
VisADTriangleStripArray array =
new VisADTriangleStripArray();
copy(array);
if (stripVertexCounts != null) {
array.stripVertexCounts = new int[stripVertexCounts.length];
System.arraycopy(stripVertexCounts, 0, array.stripVertexCounts, 0,
stripVertexCounts.length);
}
return array;
}
}
/*
documentation for VisADTriangleStripArray.adjustLongitude()
and VisADIndexedTriangleStripArray.adjustLongitude()
given a sequence of points (i-1, i, i+1) along a triangle strip:
and the three possible split points (silly = last .xor. this)
i
/\
/ \
/ \
/ \
2nd / \ 1st
last mid / \ mid (this)
1st / \ 2nd
/ \
/ \
/ \
i-1 1st 2nd i+1
silly mid
longitude
split?
l t
a h
s i
t s
1
No No /\
/ \
/ \
/ \
/ \
/ \
/ \
/ \
/ \
/ \
0 2
1
No Yes /\
/ \
/ \
/ \
/ \ 2
/ \
/ \ 6
/ \
/ \
/ \
0, 3 4, 5* 7
1, 7
Yes No /\
/ \
/ \
/ \
0, 5* / \
/ \
3 / \
/ \
/ \
/ \
2* 4, 6 8
1
Yes Yes /\
/ \
/ \
/ \
0 / \ 2
/ \
3* / \ 5
/ \
/ \
/ \
4 6
the numbers are the order of visiting points in the new strip
and n* indicates start a new strip
*/