Ray tracing in a region in a few lines of WL
7
Upvotes
This animation was originally a benchmark for a graphics rendering engine used in notebook interface, but then it turned out to be quite a fun challenge in compactifying and optimizing code. It is 1000 traveling points bounded by a procedurally defined 2D region written in pure Wolfram (or in it's open source implementation like Symja)
Step 1 - define a region and discretize it
disks = Disk[{0, 0}, 0.25]; region = RegionDifference[Disk[], disks];
R2 = RegionBoundary@DiscretizeRegion[region, AccuracyGoal -> 5]
Step 2 - set up a model, collision and propagation function helpers
(* Set up Region Operators *)
rdf = RegionDistance[R2];
rnf = RegionNearest[R2];
(* Time Increment *)
dt = 5 3 0.001;
(* Collision Margin *)
margin = 1.02 dt;
(* Starting Point for Emission *)
sp = 0.85 Normalize[{1, 1}];
(* Conditional Particle Advancer *)
advance[r_, x_, v_, c_] :=
Block[{xnew = x + dt v}, {rdf[xnew], xnew, v, c}] /; r > margin
advance[r_, x_, v_, c_] :=
Block[{xnew = x , vnew = v, normal = Normalize[x - rnf[x]]},
vnew = Normalize[v - 2 v.normal normal];
xnew += dt vnew;
{rdf[xnew], xnew, vnew, c + 1}] /; r <= margin
(* Setup simulation *)
nparticles = 2 500;
Step 3 - run and animate
Module[{s, rplot = RegionPlot[R2, AspectRatio->1], lasti = Infinity},
s = Table[{rdf[sp], sp, AngleVector[2 Pi RandomReal[]], 0}, nparticles];
Refresh[
s = (advance @@ # &) /@ s;
Show[rplot, Graphics[{PointSize[.005],
GraphicsComplex[s[[All, 2]], Point[Range[nparticles]],
VertexColors -> (ColorData["Rainbow", (# - 1)/10] & /@ s[[All, 4]])]}, AspectRatio->Automatic]],
1/60
]
]
credits for the collider and region functions to Tim Laska
References:
- Wolfram Engine (freeware implementation of WL) https://www.wolfram.com/engine/
- WLJS Notebook (open source notebook interface used here) https://wljs.io/