2016 Update
This commit is contained in:
parent
948b86eafa
commit
dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions
|
|
@ -1,3 +1,16 @@
|
|||
Death Star is a task to display a region that consists of a large sphere with part of a smaller sphere removed from it as a result of geometric subtraction. (This will basically produce a shape like a "death star".)
|
||||
{{omit from|AWK|Does not have this functionality in the language}}
|
||||
{{omit from|Lotus 123 Macro Scripting}}
|
||||
{{omit from|ML/I}}
|
||||
{{omit from|Retro}}
|
||||
|
||||
See also: [[Draw a sphere]].
|
||||
[[File:Deathstar-tcl.gif|300px|thumb]]
|
||||
|
||||
;Task:
|
||||
Display a region that consists of a large sphere with part of a smaller sphere removed from it as a result of geometric subtraction.
|
||||
|
||||
(This will basically produce a shape like a "death star".)
|
||||
|
||||
|
||||
;Related task:
|
||||
* [[Draw a sphere]]
|
||||
<br><br>
|
||||
|
|
|
|||
214
Task/Death-Star/Java/death-star.java
Normal file
214
Task/Death-Star/Java/death-star.java
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
import javafx.application.Application;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.geometry.Point3D;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.input.KeyCode;
|
||||
import javafx.scene.input.KeyEvent;
|
||||
import javafx.scene.shape.MeshView;
|
||||
import javafx.scene.shape.TriangleMesh;
|
||||
import javafx.scene.transform.Rotate;
|
||||
import javafx.stage.Stage;
|
||||
public class DeathStar extends Application {
|
||||
|
||||
private static final int DIVISION = 200;// the bigger the higher resolution
|
||||
float radius = 300;// radius of the sphere
|
||||
|
||||
@Override
|
||||
public void start(Stage primaryStage) throws Exception {
|
||||
Point3D otherSphere = new Point3D(-radius, 0, -radius * 1.5);
|
||||
final TriangleMesh triangleMesh = createMesh(DIVISION, radius, otherSphere);
|
||||
MeshView a = new MeshView(triangleMesh);
|
||||
|
||||
a.setTranslateY(radius);
|
||||
a.setTranslateX(radius);
|
||||
a.setRotationAxis(Rotate.Y_AXIS);
|
||||
Scene scene = new Scene(new Group(a));
|
||||
// uncomment if you want to move the other sphere
|
||||
|
||||
// scene.setOnKeyPressed(new EventHandler<KeyEvent>() {
|
||||
// Point3D sphere = otherSphere;
|
||||
//
|
||||
// @Override
|
||||
// public void handle(KeyEvent e) {
|
||||
// KeyCode code = e.getCode();
|
||||
// switch (code) {
|
||||
// case UP:
|
||||
// sphere = sphere.add(0, -10, 0);
|
||||
// break;
|
||||
// case DOWN:
|
||||
// sphere = sphere.add(0, 10, 0);
|
||||
// break;
|
||||
// case LEFT:
|
||||
// sphere = sphere.add(-10, 0, 0);
|
||||
// break;
|
||||
// case RIGHT:
|
||||
// sphere = sphere.add(10, 0, 0);
|
||||
// break;
|
||||
// case W:
|
||||
// sphere = sphere.add(0, 0, 10);
|
||||
// break;
|
||||
// case S:
|
||||
// sphere = sphere.add(0, 0, -10);
|
||||
// break;
|
||||
// default:
|
||||
// return;
|
||||
// }
|
||||
// a.setMesh(createMesh(DIVISION, radius, sphere));
|
||||
//
|
||||
// }
|
||||
// });
|
||||
|
||||
primaryStage.setScene(scene);
|
||||
primaryStage.show();
|
||||
}
|
||||
|
||||
static TriangleMesh createMesh(final int division, final float radius, final Point3D centerOtherSphere) {
|
||||
Rotate rotate = new Rotate(180, centerOtherSphere);
|
||||
final int div2 = division / 2;
|
||||
|
||||
final int nPoints = division * (div2 - 1) + 2;
|
||||
final int nTPoints = (division + 1) * (div2 - 1) + division * 2;
|
||||
final int nFaces = division * (div2 - 2) * 2 + division * 2;
|
||||
|
||||
final float rDiv = 1.f / division;
|
||||
|
||||
float points[] = new float[nPoints * 3];
|
||||
float tPoints[] = new float[nTPoints * 2];
|
||||
int faces[] = new int[nFaces * 6];
|
||||
|
||||
int pPos = 0, tPos = 0;
|
||||
|
||||
for (int y = 0; y < div2 - 1; ++y) {
|
||||
float va = rDiv * (y + 1 - div2 / 2) * 2 * (float) Math.PI;
|
||||
float sin_va = (float) Math.sin(va);
|
||||
float cos_va = (float) Math.cos(va);
|
||||
|
||||
float ty = 0.5f + sin_va * 0.5f;
|
||||
for (int i = 0; i < division; ++i) {
|
||||
double a = rDiv * i * 2 * (float) Math.PI;
|
||||
float hSin = (float) Math.sin(a);
|
||||
float hCos = (float) Math.cos(a);
|
||||
points[pPos + 0] = hSin * cos_va * radius;
|
||||
points[pPos + 2] = hCos * cos_va * radius;
|
||||
points[pPos + 1] = sin_va * radius;
|
||||
|
||||
final Point3D point3D = new Point3D(points[pPos + 0], points[pPos + 1], points[pPos + 2]);
|
||||
double distance = centerOtherSphere.distance(point3D);
|
||||
if (distance <= radius) {
|
||||
Point3D subtract = centerOtherSphere.subtract(point3D);
|
||||
Point3D transform = rotate.transform(subtract);
|
||||
points[pPos + 0] = (float) transform.getX();
|
||||
points[pPos + 1] = (float) transform.getY();
|
||||
points[pPos + 2] = (float) transform.getZ();
|
||||
|
||||
}
|
||||
tPoints[tPos + 0] = 1 - rDiv * i;
|
||||
tPoints[tPos + 1] = ty;
|
||||
pPos += 3;
|
||||
tPos += 2;
|
||||
}
|
||||
tPoints[tPos + 0] = 0;
|
||||
tPoints[tPos + 1] = ty;
|
||||
tPos += 2;
|
||||
}
|
||||
|
||||
points[pPos + 0] = 0;
|
||||
points[pPos + 1] = -radius;
|
||||
points[pPos + 2] = 0;
|
||||
points[pPos + 3] = 0;
|
||||
points[pPos + 4] = radius;
|
||||
points[pPos + 5] = 0;
|
||||
pPos += 6;
|
||||
|
||||
int pS = (div2 - 1) * division;
|
||||
|
||||
float textureDelta = 1.f / 256;
|
||||
for (int i = 0; i < division; ++i) {
|
||||
tPoints[tPos + 0] = rDiv * (0.5f + i);
|
||||
tPoints[tPos + 1] = textureDelta;
|
||||
tPos += 2;
|
||||
}
|
||||
|
||||
for (int i = 0; i < division; ++i) {
|
||||
tPoints[tPos + 0] = rDiv * (0.5f + i);
|
||||
tPoints[tPos + 1] = 1 - textureDelta;
|
||||
tPos += 2;
|
||||
}
|
||||
|
||||
int fIndex = 0;
|
||||
for (int y = 0; y < div2 - 2; ++y) {
|
||||
for (int x = 0; x < division; ++x) {
|
||||
int p0 = y * division + x;
|
||||
int p1 = p0 + 1;
|
||||
int p2 = p0 + division;
|
||||
int p3 = p1 + division;
|
||||
|
||||
int t0 = p0 + y;
|
||||
int t1 = t0 + 1;
|
||||
int t2 = t0 + division + 1;
|
||||
int t3 = t1 + division + 1;
|
||||
|
||||
// add p0, p1, p2
|
||||
faces[fIndex + 0] = p0;
|
||||
faces[fIndex + 1] = t0;
|
||||
faces[fIndex + 2] = p1 % division == 0 ? p1 - division : p1;
|
||||
faces[fIndex + 3] = t1;
|
||||
faces[fIndex + 4] = p2;
|
||||
faces[fIndex + 5] = t2;
|
||||
fIndex += 6;
|
||||
|
||||
// add p3, p2, p1
|
||||
faces[fIndex + 0] = p3 % division == 0 ? p3 - division : p3;
|
||||
faces[fIndex + 1] = t3;
|
||||
faces[fIndex + 2] = p2;
|
||||
faces[fIndex + 3] = t2;
|
||||
faces[fIndex + 4] = p1 % division == 0 ? p1 - division : p1;
|
||||
faces[fIndex + 5] = t1;
|
||||
fIndex += 6;
|
||||
}
|
||||
}
|
||||
|
||||
int p0 = pS;
|
||||
int tB = (div2 - 1) * (division + 1);
|
||||
for (int x = 0; x < division; ++x) {
|
||||
int p2 = x, p1 = x + 1, t0 = tB + x;
|
||||
faces[fIndex + 0] = p0;
|
||||
faces[fIndex + 1] = t0;
|
||||
faces[fIndex + 2] = p1 == division ? 0 : p1;
|
||||
faces[fIndex + 3] = p1;
|
||||
faces[fIndex + 4] = p2;
|
||||
faces[fIndex + 5] = p2;
|
||||
fIndex += 6;
|
||||
}
|
||||
|
||||
p0 = p0 + 1;
|
||||
tB = tB + division;
|
||||
int pB = (div2 - 2) * division;
|
||||
|
||||
for (int x = 0; x < division; ++x) {
|
||||
int p1 = pB + x, p2 = pB + x + 1, t0 = tB + x;
|
||||
int t1 = (div2 - 2) * (division + 1) + x, t2 = t1 + 1;
|
||||
faces[fIndex + 0] = p0;
|
||||
faces[fIndex + 1] = t0;
|
||||
faces[fIndex + 2] = p1;
|
||||
faces[fIndex + 3] = t1;
|
||||
faces[fIndex + 4] = p2 % division == 0 ? p2 - division : p2;
|
||||
faces[fIndex + 5] = t2;
|
||||
fIndex += 6;
|
||||
}
|
||||
|
||||
TriangleMesh m = new TriangleMesh();
|
||||
m.getPoints().setAll(points);
|
||||
m.getTexCoords().setAll(tPoints);
|
||||
m.getFaces().setAll(faces);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
launch(args);
|
||||
}
|
||||
|
||||
}
|
||||
42
Task/Death-Star/Q/death-star-1.q
Normal file
42
Task/Death-Star/Q/death-star-1.q
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/ https://en.wikipedia.org/wiki/BMP_file_format
|
||||
/ BITMAPINFOHEADER / RGB24
|
||||
|
||||
/ generate a header
|
||||
|
||||
genheader:{[w;h]
|
||||
0x424d, "x"$(f2i4[54+4*h*w],0,0,0,0,54,0,0,0,40,0,0,0,
|
||||
f2i4[h],f2i4[w],1,0,24,0,0,0,0,0,
|
||||
f2i4[h*((w*3)+((w*3)mod 4))],
|
||||
19,11,0,0,19,11,0,0,0,0,0,0,0,0,0,0)};
|
||||
|
||||
/ generate a raster line at a vertical position
|
||||
|
||||
genrow:{[w;y;fcn]
|
||||
row:enlist 0i;xx:0i;do[w;row,:fcn[xx;y];xx+:1i];row,:((w mod 4)#0i);1_row};
|
||||
|
||||
/ generate a bitmap
|
||||
|
||||
genbitmap:{[w;h;fcn]
|
||||
ary:enlist 0i;yy:0i;do[h;ary,:genrow[w;yy;fcn];yy+:1i];"x"$1_ary};
|
||||
|
||||
/ deal with endianness
|
||||
/ might need to reverse last line if host computer is not a PC
|
||||
|
||||
f2i4:{[x] r:x;
|
||||
s0:r mod 256;r-:s0; r%:256;
|
||||
s1:r mod 256;r-:s1; r%:256;
|
||||
s2:r mod 256;r-:s2; r%:256;
|
||||
s3:r mod 256;
|
||||
"h"$(s0,s1,s2,s3)}
|
||||
|
||||
/ compose and write a file
|
||||
|
||||
writebmp:{[w;h;fcn;fn]
|
||||
fn 1: (genheader[h;w],genbitmap[w;h;fcn])};
|
||||
|
||||
/ / usage example:
|
||||
/ w:400;
|
||||
/ h:300;
|
||||
/ fcn:{x0:x-w%2;y0:y-h%2;r:175;$[(r*r)>((x0*x0)+(y0*y0));(0;0;255);(0;255;0)]};
|
||||
/ fn:`:demo.bmp;
|
||||
/ writebmp[w;h;fcn;fn];
|
||||
38
Task/Death-Star/Q/death-star-2.q
Normal file
38
Task/Death-Star/Q/death-star-2.q
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
w:400; h:300; r:150; l:-0.5 0.7 0.5
|
||||
sqrt0:{$[x>0;sqrt x;0]};
|
||||
|
||||
/ get x,y,z position of point on sphere given x,y,r
|
||||
|
||||
z:{[x;y;r]sqrt0((r*r)-((x*x)+(y*y)))};
|
||||
|
||||
/ get diffused light at point on sphere
|
||||
|
||||
is:{[x;y;r]
|
||||
z0:z[x;y;r];
|
||||
s:(x;y;z0)%r;
|
||||
$[z0>0;i:0.5*1+(+/)(s*l);i:0];
|
||||
i};
|
||||
|
||||
/ get pixel value at given image position
|
||||
|
||||
fcn:{[xpx;ypx]
|
||||
x:xpx-w%2;
|
||||
y:ypx-h%2;
|
||||
z1:z[x;y;r];
|
||||
x2:x+190;
|
||||
z2:170-z[x2;y;r];
|
||||
$[(r*r)<((x*x)+(y*y));
|
||||
$[y>-50;
|
||||
i:3#0;
|
||||
i:200 100 50];
|
||||
$[z2>z1;
|
||||
i:3#is[x;y;r]*140;
|
||||
i:3#is[(-1*x2);(-1*y);r]*120]
|
||||
];
|
||||
"i"$i};
|
||||
|
||||
/ do it ...
|
||||
|
||||
\l bmp.q
|
||||
fn:`:demo.bmp;
|
||||
writebmp[w;h;fcn;fn];
|
||||
|
|
@ -1,58 +1,55 @@
|
|||
/*REXX pgm draws a sphere with another sphere subtracted where superimposed. */
|
||||
/*REXX program displays a sphere with another sphere subtracted where it's superimposed.*/
|
||||
call deathStar 2, .5, v3('-50 30 50')
|
||||
exit /*stick a fork in it, we're all done. */
|
||||
/*──────────────────────────────────one─liner subroutines────────────────────────────────────────*/
|
||||
dot.: procedure; parse arg x,y; d=dot(x,y); if d<0 then return -d; return 0
|
||||
dot: procedure; parse arg x,y; s=0; do j=1 for words(x); s=s+word(x,j)*word(y,j); end; return s
|
||||
ceil: procedure; parse arg x; _=trunc(x); return _+(x>0)*(x\=_)
|
||||
floor: procedure; parse arg x; _=trunc(x); return _-(x<0)*(x\=_)
|
||||
v3: procedure; parse arg a b c; s=sqrt(a**2+b**2+c**2); return a/s b/s c/s
|
||||
/*──────────────────────────────────DEATHSTAR subroutine──────────────────────*/
|
||||
deathStar: procedure; parse arg k,ambient,sun /* [↓] draw deathstar*/
|
||||
parse var sun s1 s2 s3 /*identify the lightsource coördinates.*/
|
||||
exit /*stick a fork in it, we're all done. */
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
dot.: procedure; parse arg x,y; d=dot(x,y); if d<0 then return -d; return 0
|
||||
dot: #=0; do j=1 for words(x); #=#+word(x,j)*word(y,j); end; return #
|
||||
ceil: procedure; parse arg x; _=trunc(x); return _+(x>0)*(x\=_)
|
||||
floor: procedure; parse arg x; _=trunc(x); return _-(x<0)*(x\=_)
|
||||
v3: procedure; parse arg a b c; #=sqrt(a**2 + b**2 + c**2); return a/# b/# c/#
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
sqrt: procedure; parse arg x; if x=0 then return 0; d=digits(); m.=9; numeric digits
|
||||
numeric form; parse value format(x,2,1,,0) 'E0' with g 'E' _ .; g=g * .5'e'_ % 2
|
||||
h=d+6; do j=0 while h>9; m.j=h; h=h%2+1; end /*j*/
|
||||
do k=j+5 to 0 by -1; numeric digits m.k; g=(g+x/g)*.5; end /*k*/
|
||||
numeric digits d; return (g/1)
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
hitSphere: procedure expose !.; parse arg xx yy zz r,x0,y0; x=x0-xx; y=y0-yy
|
||||
z=r*r-x*x-+y*y; if z<0 then return 0; _=sqrt(z); !.z1=zz-_; !.z2=zz+_; return 1
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
deathStar: procedure; parse arg k,ambient,sun /* [↓] display the deathstar to screen*/
|
||||
parse var sun s1 s2 s3 /*identify the light source coördinates*/
|
||||
if 6=='f6'x then shading= '.:!*oe&#%@' /*shading characters for EBCDIC machine*/
|
||||
else shading= '·:!ºoe@░▒▓' /* " " " ASCII " */
|
||||
shadingL=length(shading)
|
||||
shades.=' '; do i=1 for shadingL; shades.i=substr(shading,i,1); end /*i*/
|
||||
|
||||
if 6=='f6'x then shading= '.:!*oe&#%@' /*shading characters for EBCDIC machine*/
|
||||
else shading= '·:!ºoe@░▒▓' /* " " " ASCII " */
|
||||
ship= 20 20 0 20 ; parse var ship shipX shipY shipZ shipR
|
||||
hole= ' 1 1 -6 20'; parse var hole holeX holeY holeZ .
|
||||
|
||||
shadesLen=length(shading)
|
||||
shades.=' '; do i=1 for shadesLen; shades.i=substr(shading,i,1); end /*i*/
|
||||
do i=floor(shipY-shipR) to ceil(shipY+shipR) +1; y=i+.5; @= /*@ is a single line of the deathstar to be displayed.*/
|
||||
do j=floor(shipX-shipR*2) to ceil(shipX+shipR*2)+1
|
||||
x=.5*(j-shipX)+.5+shipX; !.=0; $bg=0; $pos=0; $neg=0 /*$BG, $POS, and $NEG are boolean values. */
|
||||
?=hitSphere(ship, x, y); b1=!.z1; b2=!.z2 /*? is boolean, "true" indicates ray hits the sphere.*/
|
||||
|
||||
ship= 20 20 0 20 ; parse var ship ship.cx ship.cy ship.cz ship.radius
|
||||
hole=' 1 1 -6 20'; parse var hole hole.cx hole.cy hole.cz hole.radius
|
||||
|
||||
do i=floor(ship.cy-ship.radius) to ceil(ship.cy+ship.radius) +1; y=i+.5; $=
|
||||
do j=trunc(floor(ship.cx-2*ship.radius)) to trunc(ceil(ship.cx+2*ship.radius) +1)
|
||||
x=.5*(j-ship.cx)+.5+ship.cx; !.=0
|
||||
?=hitSphere(ship, x, y); b1=!.z1; b2=!.z2 /*? is boolean, "true" indicates ray hits the sphere.*/
|
||||
|
||||
if \? then !.bg=1 /*ray lands in blank space, so draw the background. */
|
||||
else do; ?=hitSphere(hole, x, y); s1=!.z1; s2=!.z2
|
||||
if \? then !.pos=1 /*ray hits ship but not the hole, so draw ship surface. */
|
||||
else if s1>b1 then !.pos=1 /*ray hits both, but ship front surface is closer. */
|
||||
else if s2>b2 then !.bg=1 /*ship surface is inside hole, so show the background. */
|
||||
else if s2>b1 then !.neg=1 /*hole back surface is inside ship; the only place hole surface will be shown.*/
|
||||
else !.pos=1
|
||||
if \? then $bg=1 /*ray lands in blank space, so draw the background. */
|
||||
else do; ?=hitSphere(hole, x, y); s1=!.z1; s2=!.z2
|
||||
if \? then $pos=1 /*ray hits ship but not the hole, so draw ship surface. */
|
||||
else if s1>b1 then $pos=1 /*ray hits both, but ship front surface is closer. */
|
||||
else if s2>b2 then $bg=1 /*ship surface is inside hole, so show the background. */
|
||||
else if s2>b1 then $neg=1 /*hole back surface is inside ship; the only place a ···*/
|
||||
else $pos=1 /*························· hole surface will be shown.*/
|
||||
end
|
||||
select
|
||||
when !.bg then do; $=$' '; iterate j; end /*append a blank to the line to be displayed.*/
|
||||
when !.pos then vec_=v3(x-ship.cx y-ship.cy b1-ship.cz)
|
||||
when !.neg then vec_=v3(hole.cx-x hole.cy-y hole.cz-s2)
|
||||
when $bg then do; @=@' '; iterate j; end /*append a blank character to the line to be displayed. */
|
||||
when $pos then vec_=v3(x-shipX y-shipY b1-shipZ)
|
||||
when $neg then vec_=v3(holeX-x holeY-y holeZ-s2)
|
||||
end /*select*/
|
||||
|
||||
b=1+min(shadesLen,max(0,trunc((1-(dot.(sun,v3(vec_))**k+ambient))*shadesLen)))
|
||||
$=$ || shades.b /*B is the ray's intensity│brightness*/
|
||||
end /*j*/ /* [↑] build line for showing sphere.*/
|
||||
|
||||
if $\='' then say strip($,'T') /*strip any trailing blanks from line.*/
|
||||
end /*i*/ /* [↑] show all lines for the sphere.*/
|
||||
b=1 +min(shadingL, max(0, trunc((1 - (dot.(sun, v3(vec_))**k + ambient)) * shadingL)))
|
||||
@=@ || shades.b /*B the ray's intensity│brightness*/
|
||||
end /*j*/ /* [↑] build a line for the sphere.*/
|
||||
|
||||
if @\='' then say strip(@,'T') /*strip trailing blanks from line. */
|
||||
end /*i*/ /* [↑] show all lines for sphere. */
|
||||
return
|
||||
/*──────────────────────────────────HITSPHERE subroutine──────────────────────────*/
|
||||
hitSphere: procedure expose !.; parse arg xx yy zz r,x0,y0; x=x0-xx; y=y0-yy
|
||||
z=r**2-(x**2+y**2); if z<0 then return 0; _=sqrt(z); !.z1=zz-_; !.z2=zz+_; return 1
|
||||
/*──────────────────────────────────SQRT subroutine───────────────────────────*/
|
||||
sqrt: procedure; parse arg x; if x=0 then return 0; d=digits(); i=; m.=9
|
||||
numeric digits 9; numeric form; h=d+6; if x<0 then do; x=-x; i='i'; end
|
||||
parse value format(x,2,1,,0) 'E0' with g 'E' _ .; g=g*.5'e'_%2
|
||||
do j=0 while h>9; m.j=h; h=h%2+1; end /*j*/
|
||||
do k=j+5 to 0 by -1; numeric digits m.k; g=(g+x/g)*.5; end /*k*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue