/* built with Studio Sketchpad:
* https://sketchpad.cc
*
* observe the evolution of this sketch:
* https://studio.sketchpad.cc/sp/pad/view/ro.wMRYtu$32I$/rev.89
*
* authors:
* Masakazu Matsumoto
*
*
*
* license (unless otherwise specified):
* creative commons attribution-share alike 3.0 license.
* https://creativecommons.org/licenses/by-sa/3.0/
*/
// -*- javascript -*-
/* @pjs preload="/static/uploaded_resources/p.7722/gazebo.jpg"; */
/* @pjs preload="/static/uploaded_resources/p.7722/buttonZoom.png"; */
/* @pjs preload="/static/uploaded_resources/p.7722/buttonMap.png"; */
// This sketch builds on a prior work, "hull5", created by Masakazu Matsumoto
// http://studio.sketchpad.cc/sp/pad/view/ro.90J5n40eh-tAf/rev.882
// This sketch builds on a prior work, "hull4", created by Masakazu Matsumoto
// http://studio.sketchpad.cc/sp/pad/view/ro.9We3Kplm-bQ6W/rev.681
// This sketch builds on a prior work, "hull3", created by Masakazu Matsumoto
// http://studio.sketchpad.cc/sp/pad/view/ro.9$Hd6L5iZ4Ot4/rev.123
// This sketch builds on a prior work, "hull2", created by Masakazu Matsumoto
// http://studio.sketchpad.cc/sp/pad/view/ro.9etopzTtVrWvr/rev.735
// This sketch builds on a prior work, "Modified clone of 'hull'", created by Masakazu Matsumoto
// http://studio.sketchpad.cc/sp/pad/view/ro.9LrWM-dHxG6WF/rev.2316
// This sketch builds on a prior work, "hull", created by Masakazu Matsumoto
// http://studio.sketchpad.cc/sp/pad/view/ro.9hhvcmpZ$Xv5K/rev.3095
// Pressing Control-R will render this sketch.
//Convex hull composer.
//The convex hull consists of vertices on a sphere is drawn on an equirectangular map interactively.
////////////////////////////////////////////Convex hull
var norm(var v){
float s = 0.0;
for(int dim=0; dim<3; dim++){
s += v[dim]*v[dim];
}
return sqrt(s);
}
var normalize(var v){
float n = 1./norm(v);
var newv = new Array(3);
for(int dim=0; dim<3; dim++){
newv[dim] = v[dim]*n;
}
return newv;
}
var plain(var vertices, var vs){
//println(["vs",vs]);
var v0 = vertices.get(vs[0]);
var v1 = vertices.get(vs[1]);
var v2 = vertices.get(vs[2]);
var v01 = [];
var v02 = [];
for(int dim=0; dim<3; dim++){
v01.push(v1[dim]-v0[dim]);
v02.push(v2[dim]-v0[dim]);
}
//normal vector
var n = [v02[1]*v01[2] - v02[2]*v01[1],
v02[2]*v01[0] - v02[0]*v01[2],
v02[0]*v01[1] - v02[1]*v01[0],];
n = normalize(n);
//plain: nx(x-a)+ny(y-b)+nz(z-c)=0 ==> ax+by+cz+d=0//
n.push(-n[0]*v0[0]-n[1]*v0[1]-n[2]*v0[2]);
if(n[3]>0.0){
return null;
}
return n;
}
void addVertex(var triangles, HashMap vertices, var newv, var nextv){
var edges = {};
var i=0;
while(i<triangles.length){
var s = 0.0;
for(int dim=0;dim<3;dim++){
s += triangles[i][3][dim]*newv[dim];
}
s += triangles[i][3][3];
if(s > 0.0){
edges[triangles[i][0]*1024+triangles[i][1]] = 1;
edges[triangles[i][1]*1024+triangles[i][2]] = 1;
edges[triangles[i][2]*1024+triangles[i][0]] = 1;
triangles.splice(i,1);
}
else{
i += 1;
}
}
for(edge in edges){
var e0 = edge >> 10;
var e1 = edge % 1024;
var egde = e1*1024+e0;
edges[egde] -= 1;
}
var rim = [];
//remove the overlapped edges
for(var edge in edges){
if(edges[edge]==1){
rim.push(edge);
}
}
//add the vertice
vertices.put(nextv, newv);
var vv = nextv;
//println(["Added",vv]);
nextv += 1;
//add the triangles
for(int i=0;i<rim.length;i++){
var edge = rim[i];
var e0 = edge >> 10;
var e1 = edge % 1024;
var t;
t = [e0,e1,vv];
t.push(plain(vertices,t));
triangles.push(t);
}
return nextv;
}
var triangulation(var rim, var veryfirst, var vertices, var tris){
var first = veryfirst;
while(1){
//first triplet
var second = rim[first];
var third = rim[second];
var t = [first,second,third];
//これが酷い選択の場合がありうる。checkを追加する。
//check
var pl = plain(vertices,t);
while ( pl === null ){
first = second;
second = third;
third = rim[third];
if (first == veryfirst){
//println(["RemovalFailed",vv]);
return 1;//err. removal failed.
}
t = [first,second,third];
pl = plain(vertices,t);
}
t.push(pl);
if(rim[third] == first){ //rim is triangle
tris.push(t);
return 0;
}
//まず最初の候補ができた。
//残りの点がすべて裏にあることを確認する。
var next = rim[third];
var isconvex = 1;
while ( next != first ){
var newv = vertices.get(next);
var s = 0.0;
for(int dim=0;dim<3;dim++){
s += t[3][dim]*newv[dim];
}
s += t[3][3];
if(s > 0.0){
isconvex = 0;
break;
}
next = rim[next];
}
if ( isconvex ){
tris.push(t);
rim[first] = third; //skip the second
//recurse
return triangulation(rim, first, vertices, tris);
}
first = second;
if(first == veryfirst){
return 3;
}
}
}
var removeVertex(var triangles, HashMap vertices, var vv){
if ( vv < 0 ){
return 9;
}
//println(["Remove",vv]);
//for(var i in triangles){
// println([i,triangles[i]]);
//}
var rim = {}; // chain of rim vertices.
//look up the triangles having vv
var trash = [];
var i=0;
var first = 0;
for(var i=0;i<triangles.length;i++){
if(triangles[i][0] == vv){
rim[triangles[i][1]] = triangles[i][2];
first = triangles[i][1];
trash.push(i);
}
else if (triangles[i][1] == vv){
rim[triangles[i][2]] = triangles[i][0];
first = triangles[i][2];
trash.push(i);
}
else if (triangles[i][2] == vv){
rim[triangles[i][0]] = triangles[i][1];
first = triangles[i][0];
trash.push(i);
}
}
//for(var i in rim){
// println(["Rim",i,rim[i]]);
//}
//remove the vertex
//hatch the hole.
var hatches = [];
var err = triangulation(rim, first, vertices, hatches);
if ( err ){
return err;
}
//all succeeded
//remove the triangles
while( trash.length > 0 ){
var tri = trash.pop();
triangles.splice(tri,1);
}
//remove the vertex
vertices.remove(vv);
for(var i=0;i<hatches.length;i++){
//println(["hatches",hatches[i]]);
triangles.push(hatches[i]);
}
return 0;//no error
}
/////////////////////////globals and initialization
//initial tetrahedron
HashMap vertices = new HashMap();; // do not reuse the vertex label
/*
vertices.put(0, normalize([0.,0.,-1.]));
vertices.put(1, normalize([0.,-1.,0.]));
vertices.put(2, normalize([-1.,0.,0.]));
vertices.put(3, normalize([+1.,0.,0.]));
*/
vertices.put(0, normalize([-1.,-1.,-1.]));
vertices.put(1, normalize([+1.,+1.,-1.]));
vertices.put(2, normalize([-1.,+1.,+1.]));
vertices.put(3, normalize([+1.,-1.,+1.]));
var nextv = 4;
var triangles = [];
var t;
t = [0,1,2];
t.push(plain(vertices,t));
triangles.push(t);
t = [0,2,3];
t.push(plain(vertices,t));
triangles.push(t);
t = [0,3,1];
t.push(plain(vertices,t));
triangles.push(t);
t = [3,2,1];
t.push(plain(vertices,t));
triangles.push(t);
/*4..11*/
/*nextv = addVertex(triangles, vertices, normalize([0.,-0.1,+1.]), nextv);
nextv = addVertex(triangles, vertices, normalize([0.,+0.1,+1.]), nextv);
nextv = addVertex(triangles, vertices, normalize([-0.1,0.,+1.]), nextv);
nextv = addVertex(triangles, vertices, normalize([+0.1,0.,+1.]), nextv);
nextv = addVertex(triangles, vertices, normalize([0.,-0.1,-1.]), nextv);
nextv = addVertex(triangles, vertices, normalize([0.,+0.1,-1.]), nextv);
nextv = addVertex(triangles, vertices, normalize([-0.1,0.,-1.]), nextv);
nextv = addVertex(triangles, vertices, normalize([+0.1,0.,-1.]), nextv);
*/
/*nextv = addVertex(triangles, vertices, normalize([0.,0.,-1.]), nextv);
nextv = addVertex(triangles, vertices, normalize([-0.5,0.,-1.]), nextv);
nextv = addVertex(triangles, vertices, normalize([-2.,0.,-1.]), nextv);
*/
//nextv = addVertex(triangles, vertices, normalize([0.,+1.,0.]), nextv);
//nextv = addVertex(triangles, vertices, normalize([0.,0.,+1.]), nextv);
//nextv = addVertex(triangles, vertices, normalize([+1.,-1.,-1.]), nextv);
//nextv = addVertex(triangles, vertices, normalize([+1.,+1.,+1.]), nextv);
//test
//newv = [1.,2.,3.];
//newv = normalize(newv);
//nextv = addVertex(triangles, vertices, newv, nextv);
//for(int i=0;i<triangles.length;i++){
// println([triangles[i][0],triangles[i][1],triangles[i][2]]);
//}
//println(vertices.length);
/////////////////////////utility
var pi = 3.14159265359;
var cartesian2euler(var v){
var r = sqrt(v[0]*v[0]+v[2]*v[2]);
var theta = atan(v[1]/r);
var phi = atan(v[2]/v[0]);
if(v[0]<0){
phi += pi;
}
if(phi > pi){
phi -= 2*pi;
}
return [phi,theta];
}
/////////////////////////setup
PImage online;
//PImage online;
Button buttonZoom;
Button buttonMap;
PImage frontimg = 0;
PImage leftimg = 0;
PImage zenithimg = 0;
PImage backimg = 0;
PImage rightimg = 0;
PImage nadirimg = 0;
//println(test.pixels);
/*
image(f,width/4*3,width/4*2);
image(b,width/4*3-160,width/4*2);
image(l,width/4*3-80,width/4*2);
image(r,width/4*3-240,width/4*2);
image(z,width/4*3,width/4*2-80);
image(n,width/4*3,width/4*2+80);
*/
int winx = screen.width;
int winy = screen.height;
int winx = 1024;
int winy = 768;
//orthographic circle
var orthx = winy/4;
var orthy = winy/4;
var orthr = winy/4;
//rectilinear view
var rectx = winx/2;
var recty = winy/2;
var rectr = winy/2;
//development panel
var devSx = 0;
var devSy = winy/2;
var devSw = winx/2;
var devSh = winy/2;
var devLx = 0;
var devLy = 0;
var devLw = winx;
var devLh = winy;
var devx = devSx;
var devy = devSy;
var devw = devSw;
var devh = devSh;
//
var cube = 1024;
if ( winx < cube ){
cube = winx;
}
void setup() { // this is run once.
//size((int)winx,(int)winy,OPENGL);
size(1024,768,OPENGL);
String url = "/static/uploaded_resources/p.7722/gazebo.jpg";
String urlButtonMap = "/static/uploaded_resources/p.7722/buttonMap.png";
String urlButtonZoom = "/static/uploaded_resources/p.7722/buttonZoom.png";
online = loadImage(url);
buttonZoom = new Button(loadImage(urlButtonZoom), devSx, devSy);
buttonMap = new Button(loadImage(urlButtonMap), devSx+50,devSy);
textureMode(NORMALIZED);
// smooth edges
smooth();
// limit the number of frames per second
frameRate(24);
}
/////////////////////////mouse action
var origin = -1;
var phi = 0; //rotation angle of preview
var cosa = cos(phi);
var sina = sin(phi);
var theta = 0; //rotation angle of preview
var cosb = cos(theta);
var sinb = sin(theta);
var mode = 0; //2==orthographic panel / 3==rectilinear panel
var lastx = 0;
var lasty = 0;
var updated = 1;
var idlejob = [];
var pressedTime = 0;
var pressedX = 0; //initial position
var pressedY = 0;
var mapOrthographic = 0;
var mapDevelop = 0;
//for development
var links;
float com[2];
class Button
{
PImage icon;
var posx,posy;
Button( PImage i, int x, int y )
{
icon = i;
posx = x;
posy = y;
}
void Draw()
{
fill(255);
image(icon,posx,posy);
}
int isPointed()
{
return ( ( posx <= mouseX ) && ( mouseX <= posx+icon.width ) && ( posy <= mouseY ) && ( mouseY <= posy + icon.height ) );
}
};
var addVertexOnOrthographic(){
//add a new point by default
var x = (mouseX - orthx)/orthr;
var y = (mouseY - orthy)/orthr;
var d = x*x+y*y;
if ( d < 1.0 ){
var z = -sqrt(1.0-d);
//var rx = x*cosa + y*sina;
//var ry = -x*sina + y*cosa;
var nx = x; //horiz
var ny = y*cosb - z*sinb; //vert
var nz = y*sinb + z*cosb; //depth
var rx = nx*cosa + nz*sina;//horiz
var ry = ny; //vert
var rz =-nx*sina + nz*cosa;//depth
var newv = [rx,ry,rz];
var euler = cartesian2euler(newv);
var sx = (euler[0]/ (2*pi) + 0.5);
var sy = (euler[1] / pi + 0.5);
newv.push(sx);
newv.push(sy);
//angle = -(sx / width * 2*pi) + pi/2;
var target = nextv;
nextv = addVertex(triangles, vertices, newv, nextv);
return target;
}
return -1;
}
var addVertexOnRectilinear(){
//add a new point by default
var x = (mouseX - rectx)/rectr;
var y = (mouseY - recty)/rectr;
var z = -1.0;
var newv = normalize([x,y,z]);
//var rx = newv[0]*cosa + newv[1]*sina;
//var ry = -newv[0]*sina + newv[1]*cosa;
//var x0 = newv[0]*cosa - newv[1]*sina;//horiz
//var y0 = newv[0]*sina + newv[1]*cosa;//depth
//var z0 = newv[2]; //vert
var nx = newv[0]; //horiz
var ny = newv[1]*cosb - newv[2]*sinb; //vert
var nz = newv[1]*sinb + newv[2]*cosb; //depth
var rx = nx*cosa + nz*sina;//horiz
var ry = ny; //vert
var rz =-nx*sina + nz*cosa;//depth
//rotation around the horizontal axis, i.e.
//var nx = x0; //horiz
//var ny = y0*cosb + z0*sinb; //vert
//var nz =-y0*sinb + z0*cosb; //depth
//newv = [rx,ry,newv[2]];
newv = [rx,ry,rz];
var euler = cartesian2euler(newv);
var sx = (euler[0]/ (2*pi) + 0.5);
var sy = (euler[1] / pi + 0.5);
newv.push(sx);
newv.push(sy);
//angle = -(sx / width * 2*pi) + pi/2;
var target = nextv;
nextv = addVertex(triangles, vertices, newv, nextv);
return target;
}
void mousePressed() {
if ( mode == 5 ){
mode = 0;
devx = devSx;
devy = devSy;
devw = devSw;
devh = devSh;
updated = 1;
return;
}
else if ( mode == 4 ){
return;
}
origin = -1;
pressedX = mouseX;
pressedY = mouseY;
lastx = mouseX;
lasty = mouseY;
pressedTime = frameCount;
var dmx = mouseX - orthx;
var dmy = mouseY - orthy;
if ( dmx*dmx + dmy*dmy < orthr*orthr ){
//orthographic panel
mode = 2;
//no quick response
//look up the existing vertices
var candidate = -1;
var mindist = 20*20;
Iterator i = vertices.entrySet().iterator(); // Get an iterator
while (i.hasNext()) {
Map.Entry me = (Map.Entry)i.next();
var vtx = me.getValue();
if ( vtx[7] == 1 ){ //frontside
var x = vtx[5];
var y = vtx[6];
var dx = x - mouseX;
var dy = y - mouseY;
var dd = dx*dx + dy*dy;
if ( dd < mindist ){
candidate = me.getKey();
mindist = dd;
}
}
}
if ( candidate >= 0 ){
origin = candidate;
//angle = -(mouseX / width * 2*pi) + pi/2;
//println([target,x,y,mouseX,mouseY]);
//updated = 1;
}
}
else if ( buttonMap.isPointed() ){
mapDevelop = ! mapDevelop;
}
else if ( buttonZoom.isPointed() ){
mode = 4;
updated = 1;
}
else{
//rectilinear panel
mode = 3;
//no quick response
//look up the existing vertices
var candidate = -1;
var mindist = 20*20;
Iterator i = vertices.entrySet().iterator(); // Get an iterator
while (i.hasNext()) {
Map.Entry me = (Map.Entry)i.next();
var vtx = me.getValue();
if ( vtx[8] == 1 ){ //frontside
var x = vtx[9];
var y = vtx[10];
var dx = x - mouseX;
var dy = y - mouseY;
var dd = dx*dx + dy*dy;
if ( dd < mindist ){
candidate = me.getKey();
mindist = dd;
}
}
}
if ( candidate >= 0 ){
origin = candidate;
//angle = -(mouseX / width * 2*pi) + pi/2;
//println([target,x,y,mouseX,mouseY]);
//updated = 1;
}
}
}
void delayedAction()
{
if ( mode == 2 ) {
if ( origin < 0 ){
origin = addVertexOnOrthographic();
}
pressedTime = 0;
pressedX = 0;
pressedY = 0;
updated = 1;
}
if ( mode == 3 ) {
if ( origin < 0 ){
origin = addVertexOnRectilinear();
}
pressedTime = 0;
pressedX = 0;
pressedY = 0;
updated = 1;
}
}
void mouseDragged(){
if ( (mode == 2) && (origin < 0) ){
//rotation mode
phi += (mouseX-pmouseX)*0.01;
cosa = cos(phi);
sina = sin(phi);
theta -= (mouseY-pmouseY)*0.01;
cosb = cos(theta);
sinb = sin(theta);
updated = 1;
pressedTime = 0;
return;
}
if ( (mode == 3) && (origin < 0) ){
//rotation mode
phi += (mouseX-pmouseX)*0.01;
cosa = cos(phi);
sina = sin(phi);
theta -= (mouseY-pmouseY)*0.01;
cosb = cos(theta);
sinb = sin(theta);
updated = 1;
pressedTime = 0;
return;
}
if ( (mode == 2) || ( mode == 3 ) ){
if ( abs(mouseX - lastx) + abs(mouseY-lasty) < 15 ){
//動きが小さい場合は、削除→追加の順で処理する。
lastx = mouseX;
lasty = mouseY;
if ( mode == 2 ){
//orthographic panel
//drag mode;
int err = removeVertex(triangles, vertices, origin);
if ( ! err ) {
origin = addVertexOnOrthographic();
}
else{
origin = -1;
}
updated = 1;
pressedTime = 0;
}
if ( mode == 3 ){
//rectilinear panel
//drag mode;
int err = removeVertex(triangles, vertices, origin);
if ( ! err ) {
origin = addVertexOnRectilinear();
}
else{
origin = -1;
}
updated = 1;
pressedTime = 0;
}
}
else{
lastx = mouseX;
lasty = mouseY;
if ( mode == 2 ){
//orthographic panel
//drag mode;
var target = addVertexOnOrthographic();
removeVertex(triangles, vertices, origin);
origin = target;
updated = 1;
}
if ( mode == 3 ){
//rectilinear panel
//drag mode;
var target = addVertexOnRectilinear();
removeVertex(triangles, vertices, origin);
origin = target;
updated = 1;
}
}
}
}
void mouseReleased(){
if ( ( mode == 4 ) || (mode == 5 ) ){
return;
}
var dx = mouseX - pressedX;
var dy = mouseY - pressedY;
if ( dx*dx + dy*dy < 2 ){
//just clicked
//orthographic panel
var x = (mouseX - orthx)/orthr;
var z = (mouseY - orthy)/orthr;
var d = x*x+z*z;
if ( d < 1.0 ){
mapOrthographic = ! mapOrthographic;
}
//develop panel
}
updated = 1;
origin = -1;
mode = 0;
pressedTime = 0;
}
/////////////////////////panels
void orthographic_panel(var vertices, var triangles)
{
var layer = -1;
fill(255,255,255,100);
stroke(0);
strokeWeight(1);
ellipse(orthx,orthy,orthr*2,orthr*2);
//rotate vertices in advance
Iterator i = vertices.entrySet().iterator(); // Get an iterator
while (i.hasNext()) {
Map.Entry me = (Map.Entry)i.next();
vtx = me.getValue();
//rotation around the vertical axis
//var x0 = vtx[0]*cosa - vtx[1]*sina;//horiz
//var y0 = vtx[2]; //vert
//var z0 = vtx[0]*sina + vtx[1]*cosa;//depth
var x0 = vtx[0]*cosa - vtx[2]*sina;//horiz
var y0 = vtx[1]; //vert
var z0 = vtx[0]*sina + vtx[2]*cosa;//depth
//rotation around the horizontal axis, i.e.
var nx = x0; //horiz
var ny = y0*cosb + z0*sinb; //vert
var nz =-y0*sinb + z0*cosb; //depth
vtx[5] = orthr * nx + orthx;
vtx[6] = orthr * ny + orthy;
vtx[7] = 0; //backward
}
for(int i=0; i<triangles.length;i++){
var plane = triangles[i][3];
//rotate normal
var x0 = plane[0]*cosa - plane[2]*sina;//horiz
var y0 = plane[1]; //vert
var z0 = plane[0]*sina + plane[2]*cosa;//depth
//rotation around the horizontal axis, i.e.
var nx = x0; //horiz
var ny = y0*cosb + z0*sinb; //vert
var nz =-y0*sinb + z0*cosb; //depth
if ( nz < 0 ){
fill((int)(255*(-nz)));
beginShape();
for(int j=0;j<3;j++){
var v = vertices.get(triangles[i][j]);
v[7] = 1;
vertex(v[5],v[6],layer);
}
endShape(CLOSE);
}
}
Iterator i = vertices.entrySet().iterator(); // Get an iterator
while (i.hasNext()) {
Map.Entry me = (Map.Entry)i.next();
vtx = me.getValue();
if(vtx[7]==1){
if(me.getKey() == origin){
fill(#ff0000);
}
else{
fill(0);
}
rect(vtx[5]-4,vtx[6]-4,9,9);
}
}
}
void rectilinear_panel(var vertices, var triangles)
{
int layer = -3;
//rotate vertices in advance
Iterator i = vertices.entrySet().iterator(); // Get an iterator
while (i.hasNext()) {
Map.Entry me = (Map.Entry)i.next();
vtx = me.getValue();
vtx.length = 11;
//var ny = vtx[0]*sina + vtx[1]*cosa;
//var nx = vtx[0]*cosa - vtx[1]*sina;
//var nz = vtx[2];
var x0 = vtx[0]*cosa - vtx[1]*sina;//horiz
var y0 = vtx[2]; //vert
var z0 = vtx[0]*sina + vtx[1]*cosa;//depth
var x0 = vtx[0]*cosa - vtx[2]*sina;//horiz
var y0 = vtx[1]; //vert
var z0 = vtx[0]*sina + vtx[2]*cosa;//depth
//rotation around the horizontal axis, i.e.
var nx = x0; //horiz
var ny = y0*cosb + z0*sinb; //vert
var nz =-y0*sinb + z0*cosb; //depth
if ( nz > 0 ){
vtx[8] = 0;
}
else{
vtx[8] = 1;
vtx[9] = -rectr*nx/nz + rectx;
vtx[10] = -rectr*ny/nz + recty;
}
}
stroke(0);
strokeWeight(1);
for(int i=0; i<triangles.length;i++){
var t = triangles[i];
var v0 = vertices.get(t[0]);
var v1 = vertices.get(t[1]);
var v2 = vertices.get(t[2]);
if ( v0[8] && v1[8] ){
beginShape(LINES);
vertex(v0[9],v0[10],layer);
vertex(v1[9],v1[10],layer);
endShape();
}
if ( v2[8] && v1[8] ){
beginShape(LINES);
vertex(v2[9],v2[10],layer);
vertex(v1[9],v1[10],layer);
endShape();
}
if ( v0[8] && v2[8] ){
beginShape(LINES);
vertex(v0[9],v0[10],layer);
vertex(v2[9],v2[10],layer);
endShape();
}
}
Iterator i = vertices.entrySet().iterator(); // Get an iterator
while (i.hasNext()) {
Map.Entry me = (Map.Entry)i.next();
vtx = me.getValue();
if(vtx[8]==1){
if ( (0 < vtx[10]) && ( vtx[10] < winy ) &&
(0 < vtx[9]) && ( vtx[9] < winx ) ){
if(me.getKey() == origin){
fill(#ff0000);
}
else{
fill(0);
}
rect(vtx[9]-4,vtx[10]-4,9,9);
}
}
}
}
/////////////////////////development
void distanceMatrix(var vertices, var triangles)
{
var dm = new Array(triangles.length);
for(int i=0;i<dm.length;i++){
dm[i] = new Array(dm.length);
for(int j=0;j<dm.length;j++){
dm[i][j] = 1.0;
}
}
//まず共有辺の表が必要。
var edges = {};
for(int i=0;i<triangles.length;i++){
edges[[triangles[i][0],triangles[i][1]]] = i;
edges[[triangles[i][1],triangles[i][2]]] = i;
edges[[triangles[i][2],triangles[i][0]]] = i;
}
//println("");
for(int i=0;i<triangles.length;i++){
var va = triangles[i][0];
var vb = triangles[i][1];
var j = edges[[vb,va]];
if (i<j){
var s = 0.0;
for(int dim=0;dim<3;dim++){
s += vertices.get(va)[dim] * vertices.get(vb)[dim];
}
dm[i][j] = [s,va,vb];//innerproduct and labels of shared vertices
dm[j][i] = [s,vb,va];
//println([i,j,s]);
}
va = triangles[i][1];
vb = triangles[i][2];
var j = edges[[vb,va]];
if (i<j){
var s = 0.0;
for(int dim=0;dim<3;dim++){
s += vertices.get(va)[dim] * vertices.get(vb)[dim];
}
dm[i][j] = [s,va,vb];
dm[j][i] = [s,vb,va];
//println([i,j,s]);
}
va = triangles[i][2];
vb = triangles[i][0];
var j = edges[[vb,va]];
if (i<j){
var s = 0.0;
for(int dim=0;dim<3;dim++){
s += vertices.get(va)[dim] * vertices.get(vb)[dim];
}
dm[i][j] = [s,va,vb];
dm[j][i] = [s,vb,va];
//println([i,j,s]);
}
}
return dm;
}
var spanningTree(var dm, var triangles)
{
var links = [];
var undone = [];
for(int i=1;i<dm.length;i++){
undone.push(i);
}
var done = [0,];
fill(#00ff00);
//first node is always 0
while ( undone.length > 0 ){
int imax = 0;
int kmax = 0;
int vmax = 1.;
//println(["done",done]);
//println(["undone",undone]);
for(int ki=0;ki<done.length;ki++){
var i = done[ki];
for(int k=0;k<undone.length;k++){
var j = undone[k];
//println(["test",i,j,dm[i][j]]);
if ( dm[i][j][0] < vmax ){
imax = ki;
kmax = k;
vmax = dm[i][j][0]; // innerproduct
}
}
}
var i = done[imax];
var j = undone[kmax];
links.push([i,j,dm[i][j][1],dm[i][j][2]]);//neighboring faces and shared vertices
//println(["Nearest",i,j,dm[i][j]]);
/*
var v0 = triangles[i][3];//normal vector
vat v1 = triangles[j][3];//normal vector
drawLine(v0,v1);
*/
done.push(j);
undone.splice(kmax,1);
}
return links;
}
var norm2(var v){
float s = 0.0;
for(int dim=0; dim<2; dim++){
s += v[dim]*v[dim];
}
return sqrt(s);
}
//determine the position of the third vertex of the triangle.
//vertices are counter-clockwise
//va and vb are 2D vectors.
void thirdvertex(var va, var vb, var Lbc, var Lac)
{
var vab = [vb[0] - va[0], vb[1] - va[1]];
var Lab = norm2(vab);
var vlong = [vab[0]/Lab, vab[1]/Lab];
var Llong = (Lab*Lab + Lac*Lac - Lbc*Lbc) / (2*Lab);
var vlat = [vlong[1], -vlong[0]];
var Llat = sqrt( Lac*Lac - Llong*Llong );
return [ va[0] + Llong * vlong[0] - Llat * vlat[0],
va[1] + Llong * vlong[1] - Llat * vlat[1] ];
}
//distances between three vertices on the sphere
var edgelength(v0,v1,v2)
{
return [norm([v0[0]-v1[0], v0[1]-v1[1], v0[2]-v1[2]]),
norm([v1[0]-v2[0], v1[1]-v2[1], v1[2]-v2[2]]),
norm([v2[0]-v0[0], v2[1]-v0[1], v2[2]-v0[2]])];
}
var LocatePanels(var vertices, var triangles, var links)
{
//fill(#ff0000);
//textAlign(RIGHT);
//text("Development",width-2,width/2+10);
var wrange = [0.0,0.0];
var hrange = [0.0,0.0];
var tri0 = links[0][0];
var L = edgelength(vertices.get(triangles[tri0][0]),
vertices.get(triangles[tri0][1]),
vertices.get(triangles[tri0][2]));
var v0 = [0.0, 0.0];
var v1 = [0.0, L[0]];
hrange[1] = L[0];
var v2 = thirdvertex(v0,v1,L[1],L[2]);
wrange[0] = min(wrange[0],v2[0]);
wrange[1] = max(wrange[1],v2[0]);
hrange[0] = min(hrange[0],v2[1]);
hrange[1] = max(hrange[1],v2[1]);
triangles[tri0][4] = new HashMap();
triangles[tri0][4].put(triangles[tri0][0],v0);
triangles[tri0][4].put(triangles[tri0][1],v1);
triangles[tri0][4].put(triangles[tri0][2],v2);
for(var i=0;i<links.length;i++){
var tri0 = links[i][0];
var tri1 = links[i][1];
var sv1 = links[i][2];//shared vertices
var sv0 = links[i][3];
var uv2 = triangles[tri1][0] + triangles[tri1][1] + triangles[tri1][2] - sv0 - sv1; // unshaed vertex of tri1
//println(["linkage",tri0,tri1,sv0,sv1,uv2,triangles[tri1][0],triangles[tri1][1],triangles[tri1][2]]);
var L = edgelength(vertices.get(sv0),
vertices.get(sv1),
vertices.get(uv2));
v0 = triangles[tri0][4].get(sv0);
v1 = triangles[tri0][4].get(sv1);
v2 = thirdvertex(v0,v1,L[1],L[2]);
wrange[0] = min(wrange[0],v2[0]);
wrange[1] = max(wrange[1],v2[0]);
hrange[0] = min(hrange[0],v2[1]);
hrange[1] = max(hrange[1],v2[1]);
//println([v0,v1,v2]);
triangles[tri1][4] = new HashMap();
triangles[tri1][4].put(sv0,v0);
triangles[tri1][4].put(sv1,v1);
triangles[tri1][4].put(uv2,v2);
}
return wrange.concat(hrange);
}
var Develop(var vertices, var triangles, var ranges)
{
var layer = -1;
var devzoom = min( devw / (ranges[1]-ranges[0]), devh / (ranges[3]-ranges[2]) );
var devoffsetx = ranges[0];
var devoffsety = ranges[2];
noFill();
stroke(0);
strokeWeight(1);
for(int k=0;k<triangles.length;k++){
beginShape();
Iterator i = triangles[k][4].entrySet().iterator(); // Get an iterator
while (i.hasNext()) {
Map.Entry me = (Map.Entry)i.next();
var vtx = me.getValue();
vertex((vtx[0]-devoffsetx)*devzoom+devx,(vtx[1]-devoffsety)*devzoom+devy,layer);
}
endShape(CLOSE);
}
}
////////make the cube pixel by pixel
//nadir == y > 0
var zenith(var width, PImage eq)
{
var half = width / 2.0;
PImage sq = createImage(width,width,ARGB);
for(int i=0;i<sq.pixels.length;i++){
color c = color(100,100,200,100);
sq.pixels[i] = c;
}
var y = -1.0;
int i=0;
for(int iz=0;iz<sq.width;iz++){
var z = (iz-half)/half;
for(int ix=0;ix<sq.width;ix++){
var x = (ix-half)/half;
var v = normalize([x,y,z]);
var euler = cartesian2euler(v);
int sx = (euler[0]/ (2*pi) + 0.5)*eq.width;
int sy = (euler[1] / pi + 0.5)*eq.width/2;
int j = (int)sy*eq.width+(int)sx;
color c = eq.get((int)sx,(int)sy);
sq.pixels[i] = c;
i++;
}
}
sq.updatePixels();
return sq;
}
var nadir(var width, PImage eq)
{
var half = width / 2.0;
PImage sq = createImage(width,width,ARGB);
for(int i=0;i<sq.pixels.length;i++){
color c = color(100,100,200,100);
sq.pixels[i] = c;
}
var y = 1.0;
int i=0;
for(int iz=0;iz<sq.width;iz++){
var z = (iz-half)/half;
for(int ix=0;ix<sq.width;ix++){
var x = -(ix-half)/half;
var v = normalize([x,y,z]);
var euler = cartesian2euler(v);
int sx = (euler[0]/ (2*pi) + 0.5)*eq.width;
int sy = (euler[1] / pi + 0.5)*eq.width/2;
int j = (int)sy*eq.width+(int)sx;
color c = eq.get((int)sx,(int)sy);
sq.pixels[i] = c;
i++;
}
}
sq.updatePixels();
return sq;
}
var left(var width, PImage eq)
{
var half = width / 2.0;
PImage sq = createImage(width,width,ARGB);
for(int i=0;i<sq.pixels.length;i++){
color c = color(100,100,200,100);
sq.pixels[i] = c;
}
var x = -1.0;
int i=0;
for(int iz=0;iz<sq.width;iz++){
var z = (iz-half)/half;
for(int iy=0;iy<sq.width;iy++){
var y = -(iy-half)/half;
var v = normalize([x,y,z]);
var euler = cartesian2euler(v);
int sx = (euler[0]/ (2*pi) + 0.5)*eq.width;
int sy = (euler[1] / pi + 0.5)*eq.width/2;
int j = (int)sy*eq.width+(int)sx;
color c = eq.get((int)sx,(int)sy);
sq.pixels[i] = c;
i++;
}
}
sq.updatePixels();
return sq;
}
var right(var width, PImage eq)
{
var half = width / 2.0;
PImage sq = createImage(width,width,ARGB);
for(int i=0;i<sq.pixels.length;i++){
color c = color(100,100,200,100);
sq.pixels[i] = c;
}
var x = 1.0;
int i=0;
for(int iz=0;iz<sq.width;iz++){
var z = (iz-half)/half;
for(int iy=0;iy<sq.width;iy++){
var y = (iy-half)/half;
var v = normalize([x,y,z]);
var euler = cartesian2euler(v);
int sx = (euler[0]/ (2*pi) + 0.5)*eq.width;
int sy = (euler[1] / pi + 0.5)*eq.width/2;
int j = (int)sy*eq.width+(int)sx;
color c = eq.get((int)sx,(int)sy);
sq.pixels[i] = c;
i++;
}
}
sq.updatePixels();
return sq;
}
var front(var width, PImage eq)
{
var half = width / 2.0;
PImage sq = createImage(width,width,ARGB);
for(int i=0;i<sq.pixels.length;i++){
color c = color(100,100,200,100);
sq.pixels[i] = c;
}
var z = -1.0;
int i=0;
for(int iy=0;iy<sq.width;iy++){
var y = -(iy-half)/half;
for(int ix=0;ix<sq.width;ix++){
var x = (ix-half)/half;
var v = normalize([x,y,z]);
var euler = cartesian2euler(v);
int sx = (euler[0]/ (2*pi) + 0.5)*eq.width;
int sy = (euler[1] / pi + 0.5)*eq.width/2;
int j = (int)sy*eq.width+(int)sx;
color c = eq.get((int)sx,(int)sy);
sq.pixels[i] = c;
i++;
}
}
sq.updatePixels();
return sq;
}
var back(var width, PImage eq)
{
var half = width / 2.0;
PImage sq = createImage(width,width,ARGB);
for(int i=0;i<sq.pixels.length;i++){
color c = color(100,100,200,100);
sq.pixels[i] = c;
}
var z = 1.0;
int i=0;
for(int iy=0;iy<sq.width;iy++){
var y = (iy-half)/half;
for(int ix=0;ix<sq.width;ix++){
var x = (ix-half)/half;
var v = normalize([x,y,z]);
var euler = cartesian2euler(v);
int sx = (euler[0]/ (2*pi) + 0.5)*eq.width;
int sy = (euler[1] / pi + 0.5)*eq.width/2;
int j = (int)sy*eq.width+(int)sx;
color c = eq.get((int)sx,(int)sy);
sq.pixels[i] = c;
i++;
}
}
sq.updatePixels();
return sq;
}
var mapping(PImage img, var v)
{
var layer = -4;
var div = v.length-1.;
noStroke();
fill(255);
for(int i=0;i<div;i++){
for(int j=0;j<div;j++){
if ( v[i][j][3] && v[i+1][j][3] && v[i][j+1][3] && v[i+1][j+1][3] ){
beginShape(TRIANGLE);
texture(img);
vertex(v[i][j][4],v[i][j][5],layer,i/div,j/div);
vertex(v[i+1][j][4],v[i+1][j][5],layer,(i+1)/div,j/div);
vertex(v[i+1][j+1][4],v[i+1][j+1][5],layer,(i+1)/div,(j+1)/div);
endShape(CLOSE);
beginShape(TRIANGLE);
texture(img);
vertex(v[i][j][4],v[i][j][5],layer,i/div,j/div);
vertex(v[i+1][j+1][4],v[i+1][j+1][5],layer,(i+1)/div,(j+1)/div);
vertex(v[i][j+1][4],v[i][j+1][5],layer,i/div,(j+1)/div);
endShape(CLOSE);
}
}
}
}
var drawFront(PImage img)
{
var div=15;
var divh = div/2.;
var v = new Array(div+1);
for(int i=0;i<div+1;i++){
v[i] = new Array(div+1);
}
for(int i=0;i<div+1;i++){
for(int j=0;j<div+1;j++){
var vtx = normalize([i/divh-1,-j/divh+1,-1]);
var x0 = vtx[0]*cosa - vtx[2]*sina;//horiz
var y0 = vtx[1]; //vert
var z0 = vtx[0]*sina + vtx[2]*cosa;//depth
//rotation around the horizontal axis, i.e.
var nx = x0; //horiz
var ny = y0*cosb + z0*sinb; //vert
var nz =-y0*sinb + z0*cosb; //depth
if ( nz > 0 ){
vtx[3] = 0;
}
else{
vtx[3] = 1;
vtx[4] = -rectr*nx/nz + rectx;
vtx[5] = -rectr*ny/nz + recty;
}
v[i][j] = vtx;
}
}
mapping(img,v);
}
var drawBack(PImage img)
{
var div=15;
var divh = div/2.;
var v = new Array(div+1);
for(int i=0;i<div+1;i++){
v[i] = new Array(div+1);
}
for(int i=0;i<div+1;i++){
for(int j=0;j<div+1;j++){
var vtx = normalize([i/divh-1,j/divh-1,+1]);
var x0 = vtx[0]*cosa - vtx[2]*sina;//horiz
var y0 = vtx[1]; //vert
var z0 = vtx[0]*sina + vtx[2]*cosa;//depth
//rotation around the horizontal axis, i.e.
var nx = x0; //horiz
var ny = y0*cosb + z0*sinb; //vert
var nz =-y0*sinb + z0*cosb; //depth
if ( nz > 0 ){
vtx[3] = 0;
}
else{
vtx[3] = 1;
vtx[4] = -rectr*nx/nz + rectx;
vtx[5] = -rectr*ny/nz + recty;
}
v[i][j] = vtx;
}
}
mapping(img,v);
}
var drawZenith(PImage img)
{
var div=15;
var divh = div/2.;
var v = new Array(div+1);
for(int i=0;i<div+1;i++){
v[i] = new Array(div+1);
}
for(int i=0;i<div+1;i++){
for(int j=0;j<div+1;j++){
var vtx = normalize([i/divh-1,-1,j/divh-1]);
var x0 = vtx[0]*cosa - vtx[2]*sina;//horiz
var y0 = vtx[1]; //vert
var z0 = vtx[0]*sina + vtx[2]*cosa;//depth
//rotation around the horizontal axis, i.e.
var nx = x0; //horiz
var ny = y0*cosb + z0*sinb; //vert
var nz =-y0*sinb + z0*cosb; //depth
if ( nz > 0 ){
vtx[3] = 0;
}
else{
vtx[3] = 1;
vtx[4] = -rectr*nx/nz + rectx;
vtx[5] = -rectr*ny/nz + recty;
}
v[i][j] = vtx;
}
}
mapping(img,v);
}
var drawNadir(PImage img)
{
var div=15;
var divh = div/2.;
var v = new Array(div+1);
for(int i=0;i<div+1;i++){
v[i] = new Array(div+1);
}
for(int i=0;i<div+1;i++){
for(int j=0;j<div+1;j++){
var vtx = normalize([-i/divh+1,+1,j/divh-1]);
var x0 = vtx[0]*cosa - vtx[2]*sina;//horiz
var y0 = vtx[1]; //vert
var z0 = vtx[0]*sina + vtx[2]*cosa;//depth
//rotation around the horizontal axis, i.e.
var nx = x0; //horiz
var ny = y0*cosb + z0*sinb; //vert
var nz =-y0*sinb + z0*cosb; //depth
if ( nz > 0 ){
vtx[3] = 0;
}
else{
vtx[3] = 1;
vtx[4] = -rectr*nx/nz + rectx;
vtx[5] = -rectr*ny/nz + recty;
}
v[i][j] = vtx;
}
}
mapping(img,v);
}
var drawLeft(PImage img)
{
var div=15;
var divh = div/2.;
var v = new Array(div+1);
for(int i=0;i<div+1;i++){
v[i] = new Array(div+1);
}
for(int i=0;i<div+1;i++){
for(int j=0;j<div+1;j++){
var vtx = normalize([-1,-i/divh+1,j/divh-1]);
var x0 = vtx[0]*cosa - vtx[2]*sina;//horiz
var y0 = vtx[1]; //vert
var z0 = vtx[0]*sina + vtx[2]*cosa;//depth
//rotation around the horizontal axis, i.e.
var nx = x0; //horiz
var ny = y0*cosb + z0*sinb; //vert
var nz =-y0*sinb + z0*cosb; //depth
if ( nz > 0 ){
vtx[3] = 0;
}
else{
vtx[3] = 1;
vtx[4] = -rectr*nx/nz + rectx;
vtx[5] = -rectr*ny/nz + recty;
}
v[i][j] = vtx;
}
}
mapping(img,v);
}
var drawRight(PImage img)
{
var div=15;
var divh = div/2.;
var v = new Array(div+1);
for(int i=0;i<div+1;i++){
v[i] = new Array(div+1);
}
for(int i=0;i<div+1;i++){
for(int j=0;j<div+1;j++){
var vtx = normalize([+1,i/divh-1,j/divh-1]);
var x0 = vtx[0]*cosa - vtx[2]*sina;//horiz
var y0 = vtx[1]; //vert
var z0 = vtx[0]*sina + vtx[2]*cosa;//depth
//rotation around the horizontal axis, i.e.
var nx = x0; //horiz
var ny = y0*cosb + z0*sinb; //vert
var nz =-y0*sinb + z0*cosb; //depth
if ( nz > 0 ){
vtx[3] = 0;
}
else{
vtx[3] = 1;
vtx[4] = -rectr*nx/nz + rectx;
vtx[5] = -rectr*ny/nz + recty;
}
v[i][j] = vtx;
}
}
mapping(img,v);
}
//////////////////////////////////subdivision in orthographic panel
var subdivide1(var v0, var v1, var v2, var thres)
{
var layer = -2;
// not always unit vectors
//distance in orthographic panel
var d01 = abs(v0[5]-v1[5])+abs(v0[6]-v1[6]);
var d12 = abs(v1[5]-v2[5])+abs(v1[6]-v2[6]);
var d20 = abs(v2[5]-v0[5])+abs(v2[6]-v0[6]);
if ( min( d01, d12, d20 ) > thres ){
//if ( max( d01, d12, d20 ) > thres ){
//quad division
var v01 = [(v0[0]+v1[0])/2, (v0[1]+v1[1])/2, (v0[2]+v1[2])/2];
var v12 = [(v1[0]+v2[0])/2, (v1[1]+v2[1])/2, (v1[2]+v2[2])/2];
var v20 = [(v2[0]+v0[0])/2, (v2[1]+v0[1])/2, (v2[2]+v0[2])/2];
var euler = cartesian2euler(normalize(v01));
v01[3] = (euler[0]/ (2*pi) + 0.5);
v01[4] = (euler[1] / pi + 0.5);
var euler = cartesian2euler(normalize(v12));
v12[3] = (euler[0]/ (2*pi) + 0.5);
v12[4] = (euler[1] / pi + 0.5);
var euler = cartesian2euler(normalize(v20));
v20[3] = (euler[0]/ (2*pi) + 0.5);
v20[4] = (euler[1] / pi + 0.5);
v01[5] = (v0[5]+v1[5])/2;
v01[6] = (v0[6]+v1[6])/2;
v12[5] = (v1[5]+v2[5])/2;
v12[6] = (v1[6]+v2[6])/2;
v20[5] = (v2[5]+v0[5])/2;
v20[6] = (v2[6]+v0[6])/2;
subdivide1(v0,v01,v20,thres);
subdivide1(v1,v12,v01,thres);
subdivide1(v2,v20,v12,thres);
subdivide1(v01,v12,v20,thres);
}
else if ( d01 == max(d01,d12,d20) && d01 > thres ){
//bidivision
var v01 = [(v0[0]+v1[0])/2, (v0[1]+v1[1])/2, (v0[2]+v1[2])/2];
var euler = cartesian2euler(normalize(v01));
v01[3] = (euler[0]/ (2*pi) + 0.5);
v01[4] = (euler[1] / pi + 0.5);
v01[5] = (v0[5]+v1[5])/2;
v01[6] = (v0[6]+v1[6])/2;
subdivide1(v2,v0,v01,thres);
subdivide1(v01,v1,v2,thres);
}
else if ( d12 == max(d01,d12,d20) && d12 > thres ){
//bidivision
var v12 = [(v1[0]+v2[0])/2, (v1[1]+v2[1])/2, (v1[2]+v2[2])/2];
var euler = cartesian2euler(normalize(v12));
v12[3] = (euler[0]/ (2*pi) + 0.5);
v12[4] = (euler[1] / pi + 0.5);
v12[5] = (v1[5]+v2[5])/2;
v12[6] = (v1[6]+v2[6])/2;
subdivide1(v0,v1,v12,thres);
subdivide1(v12,v2,v0,thres);
}
else if ( d20 == max(d01,d12,d20) && d20 > thres ){
//bidivision
var v20 = [(v2[0]+v0[0])/2, (v2[1]+v0[1])/2, (v2[2]+v0[2])/2];
var euler = cartesian2euler(normalize(v20));
v20[3] = (euler[0]/ (2*pi) + 0.5);
v20[4] = (euler[1] / pi + 0.5);
v20[5] = (v2[5]+v0[5])/2;
v20[6] = (v2[6]+v0[6])/2;
subdivide1(v1,v2,v20,thres);
subdivide1(v20,v0,v1,thres);
}
else{
//boundary treatment required.
var d = abs(v0[3]-v1[3])+abs(v1[3]-v2[3])+abs(v2[3]-v0[3]);
if ( d < 0.5 ){
//orthographic panel
fill(255);
//stroke(0);
noStroke();
beginShape(TRIANGLE);
texture(online);
vertex(v0[5],v0[6], layer, v0[3],v0[4]);
vertex(v1[5],v1[6], layer, v1[3],v1[4]);
vertex(v2[5],v2[6], layer, v2[3],v2[4]);
endShape();
}
else{
if ( thres > 10 ){
subdivide1(v0,v1,v2,thres/2);
}
else{
//seam
fill(0);
noStroke();
beginShape();
vertex(v0[5],v0[6],layer);
vertex(v1[5],v1[6],layer);
vertex(v2[5],v2[6],layer);
endShape(CLOSE);
}
}
}
}
var subdivide_og(var vertices, var triangles, float thres)
{
for(int i=0;i<triangles.length;i++){
var t = triangles[i];
var plane = triangles[i][3];
//rotate normal
//var ny = plane[0]*sina + plane[1]*cosa;
var x0 = plane[0]*cosa - plane[2]*sina;//horiz
var y0 = plane[1]; //vert
var z0 = plane[0]*sina + plane[2]*cosa;//depth
//rotation around the horizontal axis, i.e.
var nx = x0; //horiz
var ny = y0*cosb + z0*sinb; //vert
var nz =-y0*sinb + z0*cosb; //depth
if ( nz < 0 ){
var v0 = vertices.get(t[0]);
var v1 = vertices.get(t[1]);
var v2 = vertices.get(t[2]);
if ( v0[7] && v1[7] && v2[7] ){
//all the vertices are frontside in the orthographic panel
subdivide1(v0,v1,v2, thres);
}
}
}
}
////////////////////////////////////
void subdivide_dev(var vertices, var triangles, var ranges, float thres)
{
var devzoom = min( devw / (ranges[1]-ranges[0]), devh / (ranges[3]-ranges[2]) );
var devoffsetx = ranges[0];
var devoffsety = ranges[2];
fill(255);
for(int k=0;k<triangles.length;k++){
var vs = [];
Iterator i = triangles[k][4].entrySet().iterator(); // Get an iterator
while (i.hasNext()) {
Map.Entry me = (Map.Entry)i.next();
var v = [];
var vtx = me.getKey();
//println(vtx);
vtx = vertices.get(vtx);
var pos = me.getValue();
v[0] = vtx[0];//position on the sphere
v[1] = vtx[1];
v[2] = vtx[2];
v[3] = vtx[3];//position on the equirectangular image
v[4] = vtx[4];
v[5] = (pos[0]-devoffsetx)*devzoom + devx;//position on the screen
v[6] = (pos[1]-devoffsety)*devzoom + devy;
vs.push(v);
}
subdivide1(vs[0],vs[1],vs[2], thres);
}
}
void draw() { // this is run repeatedly.
if ( updated ){
if ( mode == 4 ){
mode = 5;
fill(0);
textSize(winy/20);
text("Developing.... Wait a moment.", devSx, devSy+70);
return;
}
else if ( mode == 5 ){
background(255);
updated = 0;
devx = devLx;
devy = devLy;
devw = devLw;
devh = devLh;
var dm = distanceMatrix(vertices, triangles);
links = spanningTree(dm, triangles);
ranges = LocatePanels(vertices, triangles, links);
subdivide_dev(vertices, triangles, ranges, 8.0);
Develop(vertices, triangles, ranges);
return;
}
background(255);
//fill(200);
//rect(0,width/2,width,height-width/2);
updated = 0;
if ( frontimg == 0 ){
if ( online.width /2 < cube ){
cube = online.width /2 ;
}
frontimg = front(40, online);
var w = 80;
while ( w < cube ){
idlejob.push(["RefreshFront",w]);
idlejob.push(["RefreshBack",w]);
idlejob.push(["RefreshLeft",w]);
idlejob.push(["RefreshRight",w]);
idlejob.push(["RefreshZenith",w]);
idlejob.push(["RefreshNadir",w]);
w += w;
}
}
if ( leftimg == 0 ){
leftimg = left(40, online);
}
if ( zenithimg == 0 ){
zenithimg = zenith(40, online);
}
if ( backimg == 0 ){
backimg = back(40, online);
}
if ( rightimg == 0 ){
rightimg = right(40, online);
}
if ( nadirimg == 0 ){
nadirimg = nadir(40, online);
}
drawFront(frontimg);
drawLeft(leftimg);
drawZenith(zenithimg);
drawBack(backimg);
drawRight(rightimg);
drawNadir(nadirimg);
rectilinear_panel(vertices, triangles);
orthographic_panel(vertices, triangles);
var dm = distanceMatrix(vertices, triangles);
links = spanningTree(dm, triangles);
ranges = LocatePanels(vertices, triangles, links);
Develop(vertices, triangles, ranges);
buttonZoom.Draw();
buttonMap.Draw();
idlejob.unshift(["Redraw",]);
}
else if ( 0 < idlejob.length ){
//do idle job
job = idlejob.shift();
jobname = job[0];
//println(jobname);
if (jobname == "Redraw"){
if ( mapOrthographic )
subdivide_og(vertices, triangles, 20.0);
orthographic_panel(vertices, triangles);
if ( mapDevelop )
subdivide_dev(vertices, triangles, ranges, 20.0);
Develop(vertices, triangles, ranges);
}
else if (jobname == "RefreshFront"){
frontimg = front(job[1], online);
updated = 1;
}
else if (jobname == "RefreshBack"){
backimg = back(job[1], online);
updated = 1;
}
else if (jobname == "RefreshLeft"){
leftimg = left(job[1], online);
updated = 1;
}
else if (jobname == "RefreshRight"){
rightimg = right(job[1], online);
updated = 1;
}
else if (jobname == "RefreshZenith"){
zenithimg = zenith(job[1], online);
updated = 1;
}
else if (jobname == "RefreshNadir"){
nadirimg = nadir(job[1], online);
updated = 1;
}
else{
//unknown job
}
}
if ( ( pressedTime > 0 ) && ( 10 < frameCount - pressedTime ) ){
delayedAction();
}
}
/*
vertices
[0..2] coordinate on the sphere
[3,4] coordinate in equirectangular panel
[5,6] coordinate in orthographic panel
[7] 1 if foreground in the orthographic panel
*/