load("metex.dll", "zegraph.dll", "matrix.dll", "soap.dll"); /*/ Example: metex = new Metex; // metex.setView(900, 800, 360, 44); metex.setView(900, 800, 135, 24); // metex.windfield(2000, 1, 1, 0); metex.trajectory(2001, 1, 1, 0); metex.show(); /*/ class Metex { // confine Julian date julian1 = cal2jul(1990, 1, 10); julian2 = cal2jul(2005, 12, 20); // matrices for SOAP F = matrix("float", 73, 144); U = matrix("double", 73, 144); V = matrix("double", 73, 144); X = matrix("double", 144); X.fill(0, 2.5); Y = matrix("double", 73); Y.fill(90, -2.5); // graphic layout render = zegraph("render"); render.color(0, 0, 0); scene = zegraph("scene"); scene.color(1, 1, 1); render.add(scene); root = zegraph("node"); scene.root(root); light = zegraph("light"); light.position(.5, .5, 1); globe = zegraph("globe"); colorbar = zegraph("colorbar"); colorbar.discrete(false); colorbar.add(.5, .5, 0, 10); colorbar.add(0, .9, 0, 20); colorbar.add(1, 1, 0, 30); colorbar.add(1, .4, 0, 40); cones = zegraph("node"); disable(cones); conesize = 5; speedscale = 2; balls = zegraph("node"); disable(balls); ballsize = 5; red = [1.000, 0.200, 1.000, 0.100, 0.737, 0.737]; green = [1.000, 1.000, 0.500, 0.700, 0.000, 0.000]; blue = [0.200, 0.000, 0.000, 1.000, 0.737, 0.737]; root.add(light, cones, balls, globe); // class variables soap = metex = year = month = day = hour = flag = node = null; array = array(101); function setView(width, height, lon, lat) { [w, h] = render.size(); if (w != width || h != height) { render.size(width, height); scene.viewport(0, 0, width, height); radius = height/2 - 70; if (width < height) radius = width/2 - 70; makeGlobe(radius); globe.color(0, 0, .6); font = zegraph("font"); // font.truetype("c:\\windows\\fonts\\msgothic.ttc"); cones.clear(); cones.translate(radius+50, 20, 0); textnode = zegraph("node"); textnode.closed(true); cones.add(textnode); for (i = 1; i <= 10; i++) { speed = i*2*speedscale; poly = zegraph("polygon"); poly.cone(speed, conesize); [r, g, b] = colorbar.get(speed); poly.color(r, g, b); poly.rotatey(-90); y = i*20; x = 5; poly.translate(0, y, 0); cones.add(poly); text = zegraph("text"); text.font(font, 12); if (speed < 10) { text.string(""+speed+" m/s"); } else { text.string(""+speed+" m/s"); } text.layout(x, y-6, 0, x+1, y-6, 0, x, y-5, 0); textnode.add(text); } balls.clear(); balls.translate(radius+50, 20, 0); textnode = zegraph("node"); textnode.closed(true); balls.add(textnode); for (i = 0; i < 5; i++) { poly = zegraph("polygon"); poly.sphere(ballsize, 2); poly.color(red[i], green[i], blue[i]); y = i*20 + 20; x = 5; poly.translate(0, y, 0); balls.add(poly); text = zegraph("text"); text.font(font, 12); text.string("day-"+(i+1)); text.layout(x, y-6, 0, x+1, y-6, 0, x, y-5, 0); textnode.add(text); } } globe.focus(lon, lat); } function windfield(year, month, day, hour) { if (isnull(soap)) global:soap = soap(); global:flag = "wind"; global:year = year; global:month = month; global:day = day; global:hour = hour; enable(cones); disable(balls); if (!isnull(node)) globe.remove(node); n = size(array); for (i = 0; i < n; i++) globe.remove(array[i]); clear(array); [ptr, n] = soap.request("localhost", "SurfaceU", year, month, day, hour); F.import(ptr); U.clone(F); U *= speedscale; [ptr, n] = soap.request("localhost", "SurfaceV", year, month, day, hour); F.import(ptr); V.clone(F); V *= speedscale; [u, nu] = U.ptr(); [v, nv] = V.ptr(); [x, nx] = X.ptr(); [y, ny] = Y.ptr(); global:node = globe.field(u, v, x, nx, y, ny, conesize, colorbar); } function trajectory(year, month, day, hour) { if (isnull(metex)) global:metex = metex(); global:flag = "traj"; global:year = year; global:month = month; global:day = day; global:hour = hour; if (!isnull(node)) { globe.remove(node); node = null; } enable(balls); disable(cones); n = size(array); for (i = 0; i < n; i++) globe.remove(array[i]); clear(array); count = 0; metex.clear(); metex.utc(year, month, day, hour); [lon, lat] = globe.focus(); metex.add(lon, lat, 500); metex.callback("traj_callback"); metex.start(-1, 120, 1, 24); function traj_callback(cal, pid, yy, mm, dd, hh, x, y, z, zb, zs) { if (count%3 == 0) { line = globe.line(lon, lat, x, y); line.color(0, 1, 0); line.solid(3); array[size(array)] = line; global:lon = x; global:lat = y; } if (count%6 == 0) { poly = globe.sphere(x, y, 5); k = count/24; poly.color(red[k], green[k], blue[k]); array[size(array)] = poly; } count++; } } function makeGlobe(radius, lon, lat) { if (radius < 100) radius = 100; // surface poly = globe.make(radius, 5); poly.color(0, 0, .5); //grid line = globe.grid(20); line.color(.6, .6, .6); // coastlines line = zegraph("line"); globe.add(line); xyz = zegraph("vertex"); line.type("lines"); line.color(1, 1, 1); line.solid(1.5); line.vertex(xyz); D = matrix("double"); D.readgshhs("data/gshhs1.3_c.b", "land"); D.insert(2, 0); [ptr, n] = D.ptr(); xyz.add(ptr, n); xyz.ll2xyz(1.001*radius); nor = xyz.normal(1); line.normal(nor); } function show() { [width, height] = render.size(); window(width, height, "show_callback"); function show_callback(hwnd, msg, wp, hwp, lwp, lp, hlp, llp) { if (msg == "TIMER") { render.towindow(hwnd); hour += 6; jul = cal2jul(year, month, day, hour); if (jul < julian1) jul = julian1; if (jul > julian2) jul = julian1; cal = jul2cal(jul); if (flag == "wind") { windfield(cal.year, cal.month, cal.day, cal.hour); } else { trajectory(cal.year, cal.month, cal.day, cal.hour); } title("Date: " + cal.year + "." + cal.month + "." + cal.day + " " + cal.hour + ":00"); return; } if (msg == "PAINT") { render.towindow(hwnd); return; } if (msg == "CREATE") { timer(2000); } } } }