HP Prime for All
English
Русский
Name | Graph3D |
Description | Rudimentary 3D graphing application. Includes rotation and tracing. |
Author | Han Duong (HPSolo) |
Source code formatted by website engine
ICON resource lines were stripped.
begin
if init3D == 0 then
g3D_setdefault();
end;
startview(0, 1);
end;
//----------------------------
// RESET FUNCTION
//----------------------------
View "Reset Plot Settings", RESET()
begin
g3D_setdefault();
end;
//----------------------------
// Symb FUNCTION
//----------------------------
Symb()
begin
startview(0, 1);
end;
//----------------------------
// SymbSetup FUNCTION
//----------------------------
SymbSetup()
begin
msgbox("Use X and Y as the input variables.")
end;
//----------------------------
// PlotSetup FUNCTION
//----------------------------
PlotSetup()
begin
if init3D == 0 then
g3D_setdefault();
end;
g3D_getsettings();
end;
//----------------------------
// Plot FUNCTION
//----------------------------
Plot()
begin
local func;
if init3D == 0 then
g3D_setdefault();
end;
tmode := 0;
if g3D_getfunc() then
iferr func := STRING(V0); then func := ""; end;
V0 := fxy;
g3D_compute();
V0 := func;
end; // if g3D_getfunc
g3D_keys();
end;
//----------------------------
// Numb FUNCTION
//----------------------------
Num()
begin
if init3D == 0 then
g3D_setdefault();
end;
g3D_compute();
editmat(Zvals);
end;
//----------------------------
// NumSetup FUNCTION
//----------------------------
NumSetup()
begin
if init3D == 0 then
g3D_setdefault();
end;
g3D_setgrid();
end;
//----------------------------
// g3D_setdefault
//----------------------------
g3D_setdefault()
begin
xmin3D := -10; xmax3D := 10;
ymin3D := -10; ymax3D := 10;
zmin3D := -10; zmax3D := 10;
zoom3D := 5; grid3D := 15;
rotx := 15; roty := 0; rotz := 10;
xc := 0; yc := 0; zc := 0;
showbox := 1; cmode := 0; tmode := 0;
pmode := 1;
recompute3D := 1;
g3D_getfunc();
init3D := 1;
minD := 30;
xtrace := 1; ytrace := 1;
boxpts := {
[-10, -10, -10],
[-10, -10, 10],
[-10, 10, -10],
[-10, 10, 10],
[10, -10, -10],
[10, -10, 10],
[10, 10, -10],
[10, 10, 10]
};
blines := {0, {1, 2}, {2, 4}, {4, 3}, {3, 1}, {5, 6}, {6, 8}, {8, 7}, {7, 5}, {1, 5}, {2, 6}, {3, 7}, {4, 8}};
g3D_rotmatrix();
winx := -160; winy := -120;
end;
//----------------------------
// g3D_getfunc
//----------------------------
g3D_getfunc()
begin
local i, ftot = 0, fnew, fsel;
if init3D == 0 then fxy := ""; end;
for i from 0 to 9 do
if ISCHECK(i) then
fsel := i; ftot := ftot+1;
end;
end;
if ftot == 0 then
msgbox("Please enter/select a function!");
startview(0, 1);
kill;
end;
if ftot > 1 then
msgbox("Please select only one function!");
startview(0, 1);
kill;
end;
fnew := expr("STRING(V"+left(STRING(fsel), 1) + ")");
if fnew <> fxy then
fxy := fnew;
recompute3D := 1;
end;
return(recompute3D);
end;
//----------------------------
// g3D_getsettings
//----------------------------
view "Plot Settings (all)", g3D_getsettings()
begin
if init3D == 0 then
g3D_setdefault();
end;
g3D_getwin();
g3D_getangles();
end;
//----------------------------
// g3D_getwin
//----------------------------
view "Set Viewing Window", g3D_getwin()
begin
local xmin, xmax, ymin, ymax, zmin, zmax;
local zoom;
if init3D == 0 then
g3D_setdefault();
end;
xmin := xmin3D; xmax := xmax3D;
ymin := ymin3D; ymax := ymax3D;
zmin := zmin3D; zmax := zmax3D;
zoom := zoom3D;
if input(
{xmin, xmax, ymin, ymax, zmin, zmax, zoom},
"Graph 3D View Window",
{
"Xmin = ", "Xmax = ",
"Ymin = ", "Ymax = ",
"Zmin = ", "Zmax = ",
"Zoom = "
},
{
"Enter the value of left side of the viewing box",
"Enter the value of right side of the viewing box",
"Enter the value of front side of the viewing box",
"Enter the value of back side of the viewing box",
"Enter the value of bottom side of the viewing box",
"Enter the value of top side of the viewing box",
"Enter the zoom factor (must be > 0)"
},
{xmin3D, xmax3D, ymin3D, ymax3D, zmin3D, zmax3D, zoom3D})
then
if xmin >= xmax then
msgbox("Warning: Invalid Xmin/Xmax! Setting Xmax := Xmin+1");
xmax := xmin+1;
end;
if ymin >= ymax then
msgbox("Warning: Invalid Ymin/Ymax! Setting Ymax := Ymin+1");
ymax := ymin+1;
end;
if zmin >= zmax then
msgbox("Warning: Invalid Zmin/Zmax! Setting Zmax := Zmin+1");
zmax := zmin+1;
end;
if zoom3D <= 0 then
msgbox("Warning: zoom must be > 0; reset to 15");
zoom := 15;
end;
if (xmin <> xmin3D) or (xmax <> xmax3D) or
(ymin <> ymin3D) or (ymax <> ymax3D)
then
recompute3D := 1;
xmax3D := xmax; xmin3D := xmin;
ymax3D := ymax; ymin3D := ymin;
xc := (xmax3D+xmin3D) / 2;
yc := (ymax3D+ymin3D) / 2;
winx := -160; winy := -120;
end;
if
(zmin <> zmin3D) or (zmax <> zmax3D)
then
cmode := (cmode+1) MOD 2;
zmax3D := zmax; zmin3D := zmin;
zc := (zmax3D+zmin3D) / 2;
if recompute3D == 0 then g3D_recolor(0); end;
end;
zoom3D := zoom;
boxpts := {
[xmin3D-xc, ymin3D-yc, zmin3D-zc],
[xmin3D-xc, ymin3D-yc, zmax3D-zc],
[xmin3D-xc, ymax3D-yc, zmin3D-zc],
[xmin3D-xc, ymax3D-yc, zmax3D-zc],
[xmax3D-xc, ymin3D-yc, zmin3D-zc],
[xmax3D-xc, ymin3D-yc, zmax3D-zc],
[xmax3D-xc, ymax3D-yc, zmin3D-zc],
[xmax3D-xc, ymax3D-yc, zmax3D-zc]
};
end;
end;
//----------------------------
// g3D_setgrid
//----------------------------
view "Set grid size", g3D_setgrid()
begin
local grid;
if init3D == 0 then
g3D_setdefault();
end;
grid := grid3D;
if input(grid, "Graph 3D Grid Size", "Grid Size = ", "Enter N for an NxN grid", grid3D) then
if grid < 2 then
msgbox("Warning: grid size must be > 1; reset to 15");
grid := 15;
end;
end;
if grid <> grid3D then
recompute3D := 1;
end;
grid3D := grid;
end;
//----------------------------
// g3D_getangles
//----------------------------
view "Set Rotation Angles", g3D_getangles()
begin
local rx, ry, rz;
if init3D == 0 then
g3D_setdefault();
end;
rx := rotx; ry := roty; rz := rotz;
if input({rx, ry, rz},
"Graph 3D Rotation Angles",
{ "X-angle = ", "Y-angle = ", "Z-angle = " },
{
"Enter the angle (deg) about the x-axis",
"Enter the angle (deg) about the y-axis",
"Enter the angle (deg) about the z-axis"
},
{rotx, roty, rotz})
then
if (rx <> rotx) or (ry <> roty) or (rz <> rotz) then
rotx := rx; roty := ry; rotz := rz;
g3D_rotmatrix();
end;
end;
end;
//----------------------------
// g3D_rotmatrix
//----------------------------
g3D_rotmatrix()
begin
local a = rotx+90, b = roty, c = rotz;
local Rx, Ry, Rz;
if (AAngle == 1) OR (NOT (AAngle+HAngle)) then
a := a*PI/180; b := b*PI/180; c := c*PI/180;
end;
Rx := [[1, 0, 0], [0, COS(a), -SIN(a)], [0, SIN(a), COS(a)]];
Ry := [[COS(b), 0, -SIN(b)], [0, 1, 0], [SIN(b), 0, COS(b)]];
Rz := [[COS(c), -SIN(c), 0], [SIN(c), COS(c), 0], [0, 0, 1]];
RotM := Rx*Ry*Rz;
RotM(3, 4) := minD;
end;
//----------------------------
// g3D_compute
//----------------------------
g3D_compute()
begin
local minz, maxz;
local c = cmode;
if recompute3D then
dx := (xmax3D-xmin3D) / grid3D;
dy := (ymax3D-ymin3D) / grid3D;
// zColor MUST be defined befor Zvals
cmode := 0;
zColor := makemat(RGB((I-1) / grid3D*255, 1, (J-1) / grid3D*255), grid3D+1, grid3D+1);
Zvals := makemat(g3D_feval(xmin3D + (I-1) * dx, ymin3D + (J-1) * dy, I, J), grid3D+1, grid3D+1);
recompute3D := 0;
minZ := min(Zvals); minz := min(minZ, zmin3D) - zc;
maxZ := max(Zvals); maxz := max(maxZ, zmax3D) - zc;
minD := 10 + (max(abs(minz), abs(maxz))^2 + (xmax3D-xc)^2 + (ymax3D-yc)^2)^(.5);
xtrace := IP(grid3D/2); ytrace := xtrace;
g3D_rotmatrix();
if c then
g3D_recolor(0);
else
ptdef := makelist(g3D_makeptdef((X-1) mod (grid3D+1), IP((X+grid3D) / (grid3D+1))), X, 1, (grid3D+1)^2);
end;
g3D_maketridef();
g3D_makeldef();
end; // if recompute3D
end;
//----------------------------
// g3D_feval
//----------------------------
g3D_feval(x, y, ci, cj)
begin
local z;
iferr
z := V0(x, y);
then
z := MINREAL;
end;
if TYPE(z) == 3 then z := MINREAL; end;
if z == MINREAL then zColor(ci, cj) := 0; end;
return(z);
end;
//----------------------------
// g3D_makeptdef
//----------------------------
g3D_makeptdef(y, x)
begin
return([xmin3D + (x-1) * dx-xc, ymin3D+y*dy-yc, Zvals(x, y+1) - zc, zColor(x, y+1)]);
end;
//----------------------------
// g3D_makeldef
//----------------------------
g3D_makeldef()
begin
local x, y, g1 = grid3D+1;
local m = 1, n = 1, c = 2;
local row = {}, col = {};
rowtrace := {}; coltrace := {};
rowtrace(g1) := 0; coltrace(g1) := 0;
ldef := {#0h};
for y from 1 to g1 do
m := 0; n := 0; row := {}; col := {};
for x from 1 to grid3D do
if (zColor(y, x) and zColor(y, x+1)) then
n := n+1; row(n) := {(y-1) * g1+x, (y-1) * g1+x+1};
end;
if (zColor(x, y) and zColor(x+1, y)) then
m := m+1; col(m) := {(x-1) * g1+y, x*g1+y};
end;
end;
if n then rowtrace(y) := {c, c+n-1}; else rowtrace(y) := {0, 0}; end;
c := c+n;
if m then coltrace(y) := {c, c+m-1}; else coltrace(y) := {0, 0}; end;
c := c+m;
ldef := concat(ldef, row); ldef := concat(ldef, col);
end;
end;
//----------------------------
// g3D_maketridef
//----------------------------
g3D_maketridef()
begin
local x, y, n = 0, g1 = grid3D+1;
local td = {};
td(g1^2) := 0;
for y from 1 to grid3D do
for x from 1 to grid3D do
if (zColor(y, x) and zColor(y, x+1) and zColor(y+1, x) and zColor(y+1, x+1)) then
if transmode then
td(n+1) := {x + (y-1) * g1, x+1 + (y-1) * g1, x+y*g1, -1, 128};
td(n+2) := {x+y*g1, x+1+y*g1, x+1 + (y-1) * g1, -1, 128};
else
td(n+1) := {x + (y-1) * g1, x+1 + (y-1) * g1, x+y*g1};
td(n+2) := {x+y*g1, x+1+y*g1, x+1 + (y-1) * g1};
end;
n := n+2;
end;
end;
end;
tridef := sub(td, 1, n);
end;
//----------------------------
// g3D_triparms
//----------------------------
g3D_triparms()
begin
triparms := {RotM, "N", {winx, winy, minD*zoom3D},
{xmin3D-xc, xmax3D-xc, ymin3D-yc, ymax3D-yc, zmin3D-zc, zmax3D-zc}};
end;
//----------------------------
// g3D_draw
//----------------------------
g3D_draw()
begin
if contour then
g3D_drawcontour();
else
g3D_drawsurface();
end;
end;
//----------------------------
// g3D_drawsurface
//----------------------------
g3D_drawsurface()
begin
local cyan := #FF88h;
local t, l;
g3D_triparms();
dimgrob_p(G1, 320, 240);
zclip := triangle();
if showbox then
t := triangle_p(G1, boxpts, {{1, 3, 5, cmode*cyan, 64}, {3, 5, 7, cmode*cyan, 64}},
triparms, zclip);
end;
if transmode then
t := triangle_p(G1, ptdef, tridef, triparms);
else
zclip := triangle();
t := triangle_p(G1, ptdef, tridef, triparms, zclip);
end;
if (NOT(tmode) AND wiremode) then
l := line_p(G1, t, ldef, triparms, zclip);
end;
if showbox then g3D_drawbox(); end;
blit_p(G0, G1);
end;
//----------------------------
// g3D_drawcontour
//----------------------------
g3D_drawcontour()
begin
local t, i, z, delz;
local minz, maxz;
local cyan := #FF88h;
local ctridef := {0};
if ccolor then
ctridef := concat(ctridef, tridef);
else
ctridef := tridef;
end;
minz := max(minZ, zmin3D);
maxz := min(maxZ, zmax3D);
delz := (maxz-minz) / 8;
g3D_triparms();
dimgrob_p(G1, 320, 240);
zclip := triangle(G1);
if showbox then
t := triangle_p(G1, boxpts, {{1, 3, 5, cmode*cyan, 64}, {3, 5, 7, cmode*cyan, 64}},
triparms, zclip);
end;
for i from 0 to 8 do
if ccolor then ctridef(1) := colors(i+1); end;
z := minz-zc+delz*i;
t := triangle_p(G1, ptdef, ctridef,
{RotM, "N", {winx, winy, minD*zoom3D},
{xmin3D-xc, xmax3D-xc, ymin3D-yc, ymax3D-yc, .95*z, .95*z+delz*.05}});
end;
if showbox then g3D_drawbox(); end;
blit_p(G0, G1);
end;
//----------------------------
// g3D_drawbox
//----------------------------
g3D_drawbox()
begin
local t;
g3D_triparms();
if transmode then
t := line_p(G1, boxpts, blines, triparms);
else
t := line_p(G1, boxpts, blines, triparms, zclip);
end;
end;
//----------------------------
// g3D_keys
//----------------------------
g3D_keys()
begin
local key, run = 1;
g3D_draw();
while run do
key := wait(-1);
case
if TYPE(key) == 6 then
if key(1) == 3 then g3D_buttons(); end;
if tmode then g3D_draw(); g3D_trace(); end;
end;
if key == -1 then run := 0; end;
if key == 9 then g3D_getangles(); g3D_rotmatrix(); g3D_draw(); end;
if key == 27 then g3D_recolor(1); g3D_draw(); end;
if (key == 48 AND contour == 0) then tmode := 1; g3D_draw(); g3D_trace(); end;
// default
repeat
case
if key == 2 then rotx := (rotx-5) MOD 360; end;
if key == 12 then rotx := (rotx+5) MOD 360; end;
if key == 4 then kill; end;
if key == 7 then rotz := (rotz-5) MOD 360; end;
if key == 8 then rotz := (rotz+5) MOD 360; end;
if key == 1 then roty := (roty+5) MOD 360; end;
if key == 3 then roty := (roty-5) MOD 360; end;
if key == 37 then winx := winx+5; end;
if key == 39 then winx := winx-5; end;
if key == 33 then winy := winy+5; end;
if key == 43 then winy := winy-5; end;
if key == 38 then winx := -160; winy := -120; end;
if key == 45 then zoom3D := max(zoom3D/1.05, .01); end;
if key == 50 then zoom3D := zoom3D*1.05; end;
end;
g3D_rotmatrix();
g3D_draw();
until NOT iskeydown(key);
end;
end; // end while
freeze;
end;
//----------------------------
// g3D_trace
//----------------------------
g3D_trace()
begin
local key, run = 1;
g3D_drawtrace();
while run do
key := wait(-1);
case
if TYPE(key) == 6 then
if key(1) == 3 then
g3D_buttons();
if tmode then g3D_drawtrace(); end;
end;
if tmode == 0 then run := 0; end;
end;
if key == -1 then run := 0; end;
if key == 9 then g3D_getangles(); g3D_rotmatrix(); g3D_draw(); g3D_drawtrace(); end;
if key == 27 then g3D_recolor(1); g3D_draw(); g3D_drawtrace(); end;
repeat
case
if key == 4 then tmode := 0; run := 0; end;
if key == 48 then tmode := 0; run := 0; end;
if key == 2 then ytrace := ytrace+1; wait(.1); end;
if key == 12 then ytrace := ytrace-1; wait(.1); end;
if key == 7 then xtrace := xtrace-1; wait(.1); end;
if key == 8 then xtrace := xtrace+1; wait(.1); end;
if key == 37 then winx := winx+5; g3D_draw(); end;
if key == 39 then winx := winx-5; g3D_draw(); end;
if key == 33 then winy := winy+5; g3D_draw(); end;
if key == 43 then winy := winy-5; g3D_draw(); end;
if key == 38 then winx := -160; winy := -120; g3D_draw(); end;
end;
g3D_drawtrace();
until NOT iskeydown(key);
end;
end; // end while
g3D_draw();
end;
//----------------------------
// g3D_drawtrace
//----------------------------
g3D_drawtrace()
begin
local i;
local red = #FF0000h, white = #FFFFFFh;
local tracedef = {white};
local l, t;
if xtrace < 1 then xtrace := grid3D+1; end;
if xtrace > grid3D+1 then xtrace := 1; end;
if ytrace < 1 then ytrace := grid3D+1; end;
if ytrace > grid3D+1 then ytrace := 1; end;
g3D_triparms();
dimgrob_p(G2, 320, 240);
blit_p(G2, G1);
l := rowtrace(xtrace);
if l(1) then
t := sub(ldef, l(1), l(2));
tracedef := concat(tracedef, t);
t := line_p(G2, ptdef, tracedef, triparms);
end;
l := coltrace(ytrace);
if l(1) then
t := sub(ldef, l(1), l(2));
tracedef := concat(tracedef, t);
t := line_p(G2, ptdef, tracedef, triparms);
end;
textout_p("x = " + (xmin3D+dx * (xtrace-1)), G2, 1, 230, 1, red, 106);
textout_p("y = " + (ymin3D+dy * (ytrace-1)), G2, 107, 230, 1, red, 106);
if Zvals(xtrace, ytrace) == MINREAL then
textout_p("z = ", G2, 213, 230, 1, red, 106);
else
textout_p("z = "+Zvals(xtrace, ytrace), G2, 213, 230, 1, red, 106);
end;
blit_p(G0, G2);
end;
//----------------------------
// g3D_recolor
//----------------------------
g3D_recolor(msg)
begin
if msg then
textout_p("Recoloring...", G0, 0, 0, 1, 0);
end;
cmode := (cmode+1) MOD 2;
zColor := makemat(g3D_zcolor(I, J), grid3D+1, grid3D+1);
ptdef := makelist(g3D_makeptdef((X-1) mod (grid3D+1), IP((X+grid3D) / (grid3D+1))), X, 1, (grid3D+1)^2);
// g3D_maketridef();
end;
//----------------------------
// g3D_zcolor
//----------------------------
g3D_zcolor(x, y)
begin
local r;
local minz, maxz;
minz := max(minZ, zmin3D);
maxz := min(maxZ, zmax3D);
case
if cmode == 0 then
r := RGB((x-1) / grid3D*255, 1, (y-1) / grid3D*255);
end;
if cmode == 1 then
r := Zvals(x, y);
if r > maxz then r := .9*maxz; end;
if r < minz then r := .9*minz; end;
r := IP((r-minz) / (maxz-minz+1) * 250) + 1;
r := RGB(r/1.5, r/1.5, r);
end;
end;
if zColor(x, y) then
return(r);
else
return(0);
end;
end;
g3D_buttons()
begin
local i, key, getmouse = 1;
dimgrob_p(G4, 320, 70);
dimgrob_p(G5, 320, 70);
blit_p(G4, G0, 0, 120-35, 320, 120+35);
dimgrob_p(G3, 320, 70, 0);
blit_p(G3, 13, 3, "xyicon");
blit_p(G3, 90, 3, "zicon");
blit_p(G3, 167, 3, "boxicon");
blit_p(G3, 244, 3, "traceicon");
for i from 1 to 35 do
blit_p(G0, 0, 120-i, 320, 120+i, G3);
end;
while getmouse do
key := WAIT(-1);
if TYPE(key) == 6 then
if key(1) == 3 then
if 90 < key(3) AND key(3) < 150 then
case
if 15 < key(2) AND key(2) < 75 then cmode := 1; getmouse := 0; g3D_recolor(1); end;
if 92 < key(2) AND key(2) < 152 then cmode := 0; getmouse := 0; g3D_recolor(1); end;
if 169 < key(2) AND key(2) < 229 then showbox := NOT showbox; getmouse := 0; end;
if 246 < key(2) AND key(2) < 306 then
if (contour == 0) then tmode := NOT tmode; end; getmouse := 0;
end;
end;
else
getmouse := 0;
end;
end;
else
if key == 4 then getmouse := 0; end;
end;
end;
for i from 35 downto 1 do
blit_p(G5, G4);
blit_p(G5, 0, 35-i, 320, 35+i, G3);
blit_p(G0, 0, 120-35, 320, 120+35, G5);
end;
blit_p(G0, 0, 120-35, 320, 120+35, G4);
g3D_draw();
end;
ICON xyicon 89504E470D0A1A0A0000000D49484452000000400000004008030000009DB781EC000002FA504C54450000001111113F3F3F767676B2…
ICON zicon 89504E470D0A1A0A0000000D49484452000000400000004008030000009DB781EC000002FD504C544500000003030337373C7C7C80C5C…
ICON traceicon 89504E470D0A1A0A0000000D49484452000000400000004008030000009DB781EC000002F1504C54450000000606062D2D337A7A7…
ICON boxicon 89504E470D0A1A0A0000000D49484452000000400000004008030000009DB781EC00000201504C54450000000505053636367B7B7BB…