374 lines
16 KiB
JavaScript
374 lines
16 KiB
JavaScript
//public interface Render {
|
|
// /**
|
|
// * drawContour - interface for implementing the user supplied method to
|
|
// * render the countours.
|
|
// *
|
|
// * Draws a line between the start and end coordinates.
|
|
// *
|
|
// * @param startX - start coordinate for X
|
|
// * @param startY - start coordinate for Y
|
|
// * @param endX - end coordinate for X
|
|
// * @param endY - end coordinate for Y
|
|
// * @param contourLevel - Contour level for line.
|
|
// */
|
|
// public void drawContour(double startX, double startY, double endX, double endY, double contourLevel);
|
|
//}
|
|
class Renderer {
|
|
MAGNITUDE = 20;
|
|
drawContour(startX, startY, endX, endY, contourLevel) {
|
|
//strokeWeight((int)contourLevel * 2.057721);
|
|
//if(contourLevel == 1.0) {
|
|
// strokeWeight(5);
|
|
//} else if (contourLevel == 5.0) {
|
|
// strokeWeight(1);
|
|
//}
|
|
//else {
|
|
// strokeWeight(2.5);
|
|
//}
|
|
let from = color(237, 84, 102);
|
|
let to = color(244, 208, 99);
|
|
let c = lerpColor(from, to, startX / (width / this.MAGNITUDE)); //color[] colors = {
|
|
// color(15),
|
|
// color(25),
|
|
// color(35),
|
|
// color(45),
|
|
// color(55),
|
|
// color(65),
|
|
// color(75),
|
|
// color(75),
|
|
// color(95),
|
|
// color(115),
|
|
// color(135),
|
|
// color(155),
|
|
// color(175),
|
|
// color(195),
|
|
// color(205),
|
|
// color(215),
|
|
// color(235),
|
|
// color(255)
|
|
//};
|
|
//color[] colors = {
|
|
// color(255 - 255),
|
|
// color(255 - 235),
|
|
// color(255 - 215),
|
|
// color(255 - 205),
|
|
// color(255 - 195),
|
|
// color(255 - 175),
|
|
// color(255 - 155),
|
|
// color(255 - 135),
|
|
// color(255 - 115),
|
|
// color(255 - 95),
|
|
// color(255 - 75),
|
|
// color(255 - 75),
|
|
// color(255 - 65),
|
|
// color(255 - 55),
|
|
// color(255 - 45),
|
|
// color(255 - 35),
|
|
// color(255 - 25),
|
|
// color(255 - 15),
|
|
//};
|
|
//float i = (float) contourLevel * 2.057721;
|
|
//stroke(127 + 127 * sin((i/10) * 0.05),
|
|
// 127 + 127 * sin((i/20) * 0.003),
|
|
// 127 + 127 * sin((i/10) * 0.009)
|
|
//);
|
|
//stroke(colors[(int)contourLevel]);
|
|
stroke(20); //stroke(c);
|
|
line(
|
|
startX * this.MAGNITUDE,
|
|
startY * this.MAGNITUDE,
|
|
endX * this.MAGNITUDE,
|
|
endY * this.MAGNITUDE
|
|
); //fill(20);
|
|
//line((float)endX * MAGNITUDE, (float)startY * MAGNITUDE, (float)startX * MAGNITUDE, (float)endY * MAGNITUDE);
|
|
//point((float)startX * MAGNITUDE, (float)endY * MAGNITUDE);
|
|
//point((float)endX * MAGNITUDE, (float)startY * MAGNITUDE);
|
|
}
|
|
}
|
|
class Conrec {
|
|
h = new Array(5);
|
|
sh = new Array(5);
|
|
xh = new Array(5);
|
|
yh = new Array(5); // Object that knows how to draw the contour
|
|
renderer = null; /** Creates new Conrec */
|
|
constructor(renderer) {
|
|
this.renderer = renderer;
|
|
}
|
|
/**
|
|
* contour is a contouring subroutine for rectangularily spaced data
|
|
*
|
|
* It emits calls to a line drawing subroutine supplied by the user
|
|
* which draws a contour map corresponding to real*4data on a randomly
|
|
* spaced rectangular grid. The coordinates emitted are in the same
|
|
* units given in the x() and y() arrays.
|
|
*
|
|
* Any number of contour levels may be specified but they must be
|
|
* in order of increasing value.
|
|
*
|
|
*
|
|
* @param d - matrix of data to contour
|
|
* @param ilb,iub,jlb,jub - index bounds of data matrix
|
|
*
|
|
* The following two, one dimensional arrays (x and y) contain the horizontal and
|
|
* vertical coordinates of each sample points.
|
|
* @param x - data matrix column coordinates
|
|
* @param y - data matrix row coordinates
|
|
* @param nc - number of contour levels
|
|
* @param z - contour levels in increasing order.
|
|
*
|
|
*/
|
|
contour(d, ilb, iub, jlb, jub, x, y, nc, z) {
|
|
let m1;
|
|
let m2;
|
|
let m3;
|
|
let case_value;
|
|
let dmin;
|
|
let dmax;
|
|
let x1 = 0.0;
|
|
let x2 = 0.0;
|
|
let y1 = 0.0;
|
|
let y2 = 0.0;
|
|
let i;
|
|
j;
|
|
k;
|
|
m; // The indexing of im and jm should be noted as it has to start from zero
|
|
// unlike the fortran counter part
|
|
let im = [0, 1, 1, 0];
|
|
let jm = [0, 0, 1, 1]; // Note that castab is arranged differently from the FORTRAN code because
|
|
// Fortran and C/C++ arrays are transposed of each other, in this case
|
|
// it is more tricky as castab is in 3 dimension
|
|
let castab = [
|
|
[
|
|
[0, 0, 8],
|
|
[0, 2, 5],
|
|
[7, 6, 9],
|
|
],
|
|
[
|
|
[0, 3, 4],
|
|
[1, 3, 1],
|
|
[4, 3, 0],
|
|
],
|
|
[
|
|
[9, 6, 7],
|
|
[5, 2, 0],
|
|
[8, 0, 0],
|
|
],
|
|
];
|
|
for (j = jub - 1; j >= jlb; j--) {
|
|
for (i = ilb; i <= iub - 1; i++) {
|
|
let temp1;
|
|
temp2;
|
|
temp1 = Math.min(d[i][j], d[i][j + 1]);
|
|
temp2 = Math.min(d[i + 1][j], d[i + 1][j + 1]);
|
|
dmin = Math.min(temp1, temp2);
|
|
temp1 = Math.max(d[i][j], d[i][j + 1]);
|
|
temp2 = Math.max(d[i + 1][j], d[i + 1][j + 1]);
|
|
dmax = Math.max(temp1, temp2);
|
|
if (dmax >= z[0] && dmin <= z[nc - 1]) {
|
|
for (k = 0; k < nc; k++) {
|
|
if (z[k] >= dmin && z[k] <= dmax) {
|
|
for (m = 4; m >= 0; m--) {
|
|
if (m > 0) {
|
|
// The indexing of im and jm should be noted as it has to
|
|
// start from zero
|
|
this.h[m] =
|
|
d[i + im[m - 1]][j + jm[m - 1]] - z[k];
|
|
this.xh[m] = x[i + im[m - 1]];
|
|
this.yh[m] = y[j + jm[m - 1]];
|
|
} else {
|
|
this.h[0] =
|
|
0.25 *
|
|
(this.h[1] +
|
|
this.h[2] +
|
|
this.h[3] +
|
|
this.h[4]);
|
|
this.xh[0] = 0.5 * (x[i] + x[i + 1]);
|
|
this.yh[0] = 0.5 * (y[j] + y[j + 1]);
|
|
}
|
|
if (this.h[m] > 0.0) {
|
|
this.sh[m] = 1;
|
|
} else if (this.h[m] < 0.0) {
|
|
this.sh[m] = -1;
|
|
} else this.sh[m] = 0;
|
|
} //
|
|
// Note: at this stage the relative heights of the corners and the
|
|
// centre are in the h array, and the corresponding coordinates are
|
|
// in the xh and yh arrays. The centre of the box is indexed by 0
|
|
// and the 4 corners by 1 to 4 as shown below.
|
|
// Each triangle is then indexed by the parameter m, and the 3
|
|
// vertices of each triangle are indexed by parameters m1,m2,and
|
|
// m3.
|
|
// It is assumed that the centre of the box is always vertex 2
|
|
// though this is// [processing-p5-convert] important only when all 3 vertices lie exactly on
|
|
// the same contour level, in which case only the side of the box
|
|
// is drawn.
|
|
//
|
|
//
|
|
// vertex 4 +-------------------+ vertex 3
|
|
// | \ / |
|
|
// | \ m-3 / |
|
|
// | \ / |
|
|
// | \ / |
|
|
// | m=2 X m=2 | the centre is vertex 0
|
|
// | / \ |
|
|
// | / \ |
|
|
// | / m=1 \ |
|
|
// | / \ |
|
|
// vertex 1 +-------------------+ vertex 2
|
|
//
|
|
//
|
|
//
|
|
// Scan each triangle in the box
|
|
//
|
|
for (m = 1; m <= 4; m++) {
|
|
m1 = m;
|
|
m2 = 0;
|
|
if (m != 4) {
|
|
m3 = m + 1;
|
|
} else {
|
|
m3 = 1;
|
|
}
|
|
case_value =
|
|
castab[this.sh[m1] + 1][this.sh[m2] + 1][
|
|
this.sh[m3] + 1
|
|
];
|
|
if (case_value != 0) {
|
|
switch (case_value) {
|
|
case 1: // Line between vertices 1 and 2
|
|
x1 = this.xh[m1];
|
|
y1 = this.yh[m1];
|
|
x2 = this.xh[m2];
|
|
y2 = this.yh[m2];
|
|
break;
|
|
case 2: // Line between vertices 2 and 3
|
|
x1 = this.xh[m2];
|
|
y1 = this.yh[m2];
|
|
x2 = this.xh[m3];
|
|
y2 = this.yh[m3];
|
|
break;
|
|
case 3: // Line between vertices 3 and 1
|
|
x1 = this.xh[m3];
|
|
y1 = this.yh[m3];
|
|
x2 = this.xh[m1];
|
|
y2 = this.yh[m1];
|
|
break;
|
|
case 4: // Line between vertex 1 and side 2-3
|
|
x1 = this.xh[m1];
|
|
y1 = this.yh[m1];
|
|
x2 = this.xsect(m2, m3);
|
|
y2 = this.ysect(m2, m3);
|
|
break;
|
|
case 5: // Line between vertex 2 and side 3-1
|
|
x1 = this.xh[m2];
|
|
y1 = this.yh[m2];
|
|
x2 = this.xsect(m3, m1);
|
|
y2 = this.ysect(m3, m1);
|
|
break;
|
|
case 6: // Line between vertex 3 and side 1-2
|
|
x1 = this.xh[m3];
|
|
y1 = this.yh[m3];
|
|
x2 = this.xsect(m1, m2);
|
|
y2 = this.ysect(m1, m2);
|
|
break;
|
|
case 7: // Line between sides 1-2 and 2-3
|
|
x1 = this.xsect(m1, m2);
|
|
y1 = this.ysect(m1, m2);
|
|
x2 = this.xsect(m2, m3);
|
|
y2 = this.ysect(m2, m3);
|
|
break;
|
|
case 8: // Line between sides 2-3 and 3-1
|
|
x1 = this.xsect(m2, m3);
|
|
y1 = this.ysect(m2, m3);
|
|
x2 = this.xsect(m3, m1);
|
|
y2 = this.ysect(m3, m1);
|
|
break;
|
|
case 9: // Line between sides 3-1 and 1-2
|
|
x1 = this.xsect(m3, m1);
|
|
y1 = this.ysect(m3, m1);
|
|
x2 = this.xsect(m1, m2);
|
|
y2 = this.ysect(m1, m2);
|
|
break;
|
|
default:
|
|
break;
|
|
} // Put your processing code here and comment out the printf
|
|
//print("%f %f %f %f %f\n",x1,y1,x2,y2,z[k]);
|
|
this.renderer.drawContour(
|
|
x1,
|
|
y1,
|
|
x2,
|
|
y2,
|
|
z[k]
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
xsect(p1, p2) {
|
|
return (
|
|
(this.h[p2] * this.xh[p1] - this.h[p1] * this.xh[p2]) /
|
|
(this.h[p2] - this.h[p1])
|
|
);
|
|
}
|
|
ysect(p1, p2) {
|
|
return (
|
|
(this.h[p2] * this.yh[p1] - this.h[p1] * this.yh[p2]) /
|
|
(this.h[p2] - this.h[p1])
|
|
);
|
|
}
|
|
}
|
|
let LIMIT = 200;
|
|
let x = new Array(LIMIT);
|
|
let y = new Array(LIMIT);
|
|
let d = Array.from(new Array(LIMIT - 1), () => new Array(LIMIT - 1));
|
|
let renderer = new Renderer();
|
|
let ilb = 0;
|
|
let iub = 100;
|
|
let jlb = 0;
|
|
let jub = 100;
|
|
let nc = 10;
|
|
let z = [
|
|
1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0,
|
|
15.0, 16.0, 17.0,
|
|
];
|
|
let t;
|
|
function setup() {
|
|
//size(6500, 6500);
|
|
createCanvas(1024, 1024);
|
|
for (let i = 0; i < LIMIT; i++) {
|
|
x[i] = i;
|
|
y[i] = i;
|
|
} // frameRate(1);
|
|
}
|
|
function draw() {
|
|
// noFill();
|
|
// background(color(89, 191, 237));
|
|
background(255); // stroke(255);
|
|
for (let i = 0; i < LIMIT - 1; i++) {
|
|
for (let k = 0; k < LIMIT - 1; k++) {
|
|
//float p_noise = noise(t);
|
|
//float p_noise = noise(t) * i * k;
|
|
//float p_noise = noise(t * k) + (10 * cos(k) * i) * (10 * sin(k / 20) * i);
|
|
//float p_noise = noise(t + i) * (10 * cos(k * i)) * (2 * sin(k) * k);
|
|
let p_noise = noise(i * k) * (2 * cos(k * i)) * (5 * sin(t) * k); //float p_noise = (noise(t * k ) / i);
|
|
//float p_noise = noise(t * i * k);
|
|
//float p_noise = noise(t * i) * (k * k);
|
|
d[i][k] = PI * (sin(p_noise / k) + cos(p_noise)); //d[i][k] = (mouseY * sin(p_noise / k) + cos(i / (mouseX + 1)));
|
|
//d[i][k] = (mouseY / 200.0) * (sin(p_noise * (mouseX / 200.0)));
|
|
//d[i][k] = sin(p_noise * PI) * PI + k;
|
|
//print(mouseY);
|
|
//print("/n");
|
|
//d[i][k] = (i * mouseY) * (p_noise / k); // water
|
|
//d[i][k] = (18 - (p_noise + (mouseY / 200.0) )) * mouseX / 200.0;
|
|
//d[i][k] = random(0,10);
|
|
}
|
|
}
|
|
let c = new Conrec(renderer);
|
|
c.contour(d, ilb, iub, jlb, jub, x, y, nc, z); //t = t + 0.005;
|
|
t = second(); //String color_names = from_r + "-" + from_g + "-" + from_b + "--" + to_r + "-"+ to_g + "-"+ to_b;
|
|
//saveFrame("terrain-black-large-outline-2-"+t+"-######.png");
|
|
}
|