/******************************************************************** * Functions for 3D plot * * Example: * import plot3d; plot3d(600, 600, 0, 1, .2, 0, 1, .2, 0, 1, .2); line3d([0, 1, .5], [0, 1, 0.5], [0, 0, 1]); show3d(); * ********************************************************************/ load("zegraph.dll"); __render = null; __scene = null; __plot = null; __font = null; __width = 512; __height = 512; __scale = 1.0; __x0 = null; __x1 = null; __y0 = null; __y1 = null; function plot3d(w=512, h=512, x0=-1, x1=1, dx=.5, y0=-1, y1=1, dy=.5, z0=-1, z1=1, dz=.5) { assert(w > 32, h >= 32, dx != 0, dy != 0, dz != 0); global:__x0 = x0; global:__x1 = x1; global:__y0 = y0; global:__y1 = y1; if (w > 800) global:__scale = w/800.0; G = zegraph("render", "scene", "node", "plot", "font", "light"); disable(G.light); node = G.node; G.rotatez = 20; G.rotatex = -60; global:__render = G.render; global:__scene = G.scene; global:__plot = G.plot; global:__font = G.font; global:__width = w; global:__height = h; __render:size(w, h); __render:add(__scene); __scene:viewport(0, 0, w, h); __scene:root(node); node:add(G.light, __plot); __plot:font(__font, 11*__scale); __plot:rotate(G.rotatez, G.rotatex); __plot:scale(0.5, 0.5, 0.5); __plot:xaxis(0, -1, -1); __plot:yaxis(-1, 0, -1); __plot:zaxis(-1, 1, 0); xaxis = __plot:xaxis(); xaxis:range(x0, x1); G.xaxis = xaxis; xaxis:title("X"); xaxis:tickmarks(x0, dx, 1); yaxis = __plot:yaxis(); yaxis:range(y0, y1); G.yaxis = yaxis; yaxis:title("Y"); yaxis:tickmarks(y0, dy, 1); zaxis = __plot:zaxis(); zaxis:range(z0, z1); G.zaxis = zaxis; zaxis:title("Z"); zaxis:tickmarks(z0, dz, 1); return G; } function line3d(x, y, z) { line = zegraph("line"); vert = zegraph("vertex"); line:vertex(vert); line:type("strip"); line:solid(1.5*__scale); __plot:add(line); n = size(x); for (i = 0; i < n; i++) vert:add(x[i], y[i], z[i]); return line; } function point3d(x, y, z) { point = zegraph("point"); vert = zegraph("vertex"); point:vertex(vert); point:size(5*__scale); __plot:add(point); if (isarray(x)) { n = size(x); for (i = 0; i < n; i++) vert:add(x[i], y[i], z[i]); } else { vert:add(x, y, z); } return point; } function text3d(x, y, z, str, halign=0, valign=-1) { text = zegraph("text"); text:font(__font, 10*__scale); text:string(str); size = text:size(); h = -size[0]/2; v = -size[1]/2; if (halign < 0) h = 0; if (halign > 0) h = -size[0]; if (valign < 0) v = 0; if (valign > 0) v = -size[1]; text:layout(h, v, 0, h + 1, v, 0, h, v + 1, 0); __plot:anchor(text, x, y, z); return text; } function image3d(p0, p1, p2, fname) { node = zegraph("node"); texture = zegraph("texture"); polygon = zegraph("polygon"); vertex = zegraph("vertex"); texcoord = zegraph("texcoord"); node:closed(true); node:add(texture, polygon); texture:image(fname, -1, -1, -1); polygon:type("quads"); polygon:color(1, 1, 1); polygon:vertex(vertex); polygon:texcoord(texcoord); vertex:add(p0[0], p0[1], p0[2], p1[0], p1[1], p1[2], p2[0]+p1[0]-p0[0], p2[1]+p1[1]-p0[1], p2[2]+p1[2]-p0[2], p2[0], p2[1], p2[2]); texcoord:add(0, 0, 1, 0, 1, 1, 0, 1); __plot:add(node); } function symbol3d(x, y, z, symbol) { if (isarray(x)) { n = size(x); for (i = 0; i < n; i++) __plot:anchor(symbol, x[i], y[i], z[i]); } else { __plot:anchor(symbol, x, y, 0); } } function show3d() { size = __render:size(); window(size[0], size[1], "callback"); function callback(hwnd, msg, wp, hwp, lwp, lp, hlp, llp) { if (msg == "PAINT") __render:towindow(hwnd); } } function scale3d(xscale=1, yscale=1, zscale=1) { __plot:scale(sx, sy, sz); } function move3d(dx, dy) { __plot:translate(dx, dy, 0); } function rotate3d(rx, rz) { __plot:translate(rz, rx); } function coast3d(gshhs, z=0) { x1 = __x0; x2 = __x1; if (lon1 < 0) { x1 += 180; x2 += 180; } data = matrix("double"); data:readgshhs(gshhs, "land", x1, x2, __y0, __y1); data:insert(2, z); if (lon1 < 0) { v1 = data[null,0]; idx = v1 >= 180; v2 = v1*0; v2[idx] = v1; v2 -= 360; v1[idx] = v2; data[null,0] = v1; } xyz = zegraph("vertex"); p = data:ptr(); xyz:add(p[0], p[1]); coast = zegraph("line"); coast:vertex(xyz); coast:type("lines"); coast:solid(__scale); return coast; }