3232STATIC = Path (__file__ ).parent / "_static"
3333DARK , ACCENT , NEW = "#2c3e6b" , "#21918c" , "#e4572e"
3434BLUE , YELLOW = "#3b528b" , "#fde725"
35+ NPOINTS_3D = 6000
3536plt .rcParams .update (
3637 {
3738 "font.family" : "DejaVu Sans" ,
@@ -171,24 +172,19 @@ def draw(fig, i):
171172
172173
173174def learnerND (target : Path ) -> None :
174- points , values = sampled (
175- adaptive .LearnerND (shell , bounds = [(- 1 , 1 )] * 3 ), npoints_goal = 2500
176- )
177- grow , turn = 45 , 60
178- frames = np .concatenate ([counts (30 , len (points ), grow ), np .full (turn , len (points ))])
179- surfaces = _isosurfaces (points , values , np .unique (frames ))
175+ learner = adaptive .LearnerND (shell , bounds = [(- 1 , 1 )] * 3 )
176+ adaptive .runner .simple (learner , npoints_goal = NPOINTS_3D )
177+ triangles = _isosurface (learner )
178+ centers = triangles .mean (axis = 1 )
179+ inner = np .linalg .norm (centers , axis = 1 ) < 0.75
180+ # Cut an x > 0, y > 0 wedge out of the outer surface to show the inner one.
181+ keep = inner | ~ ((centers [:, 0 ] > 0 ) & (centers [:, 1 ] > 0 ))
182+ triangles , inner = triangles [keep ], inner [keep ]
183+ base = np .array ([to_rgba (BLUE ), to_rgba (YELLOW )])[inner .astype (int )]
184+ nframes = 90
180185
181186 def draw (fig , i ):
182- n = frames [i ]
183- # Rock back and forth, so the cut-away wedge stays in view.
184- azim = 45 + 50 * np .sin (2 * np .pi * max (0 , i - grow ) / turn )
185- triangles = surfaces [n ]
186- centers = triangles .mean (axis = 1 )
187- inner = np .linalg .norm (centers , axis = 1 ) < 0.75
188- # Cut an x > 0, y > 0 wedge out of the outer surface to show the inner one.
189- keep = inner | ~ ((centers [:, 0 ] > 0 ) & (centers [:, 1 ] > 0 ))
190- triangles , inner = triangles [keep ], inner [keep ]
191- base = np .array ([to_rgba (BLUE ), to_rgba (YELLOW )])[inner .astype (int )]
187+ azim = 45 + 55 * np .sin (2 * np .pi * i / nframes ) # keeps the cut in view
192188 colors = base * _lambert (triangles , azim - 30 , 25 + 20 )[:, None ]
193189 colors [:, 3 ] = 1
194190 ax = fig .add_subplot (projection = "3d" )
@@ -201,10 +197,13 @@ def draw(fig, i):
201197 set_lim (- 1 , 1 )
202198 ax .set_box_aspect ((1 , 1 , 1 ), zoom = 1.25 )
203199 ax .set_axis_off ()
204- fig .text (0.5 , 0.04 , f"{ n } points" , ha = "center" , color = "#555555" , fontsize = 12 )
200+ fig .text (
201+ 0.5 , 0.04 , f"LearnerND, { learner .npoints } points" ,
202+ ha = "center" , color = "#555555" , fontsize = 12 ,
203+ ) # fmt: skip
205204 fig .subplots_adjust (left = 0 , right = 1 , top = 1 , bottom = 0 )
206205
207- _render_gif (draw , len ( frames ) , (4.5 , 4.5 ), target , hold = 0 , dpi = 90 )
206+ _render_gif (draw , nframes , (4.5 , 4.5 ), target , hold = 0 , dpi = 90 )
208207
209208
210209def _lambert (triangles : np .ndarray , azim : float , elev : float ) -> np .ndarray :
@@ -220,25 +219,18 @@ def _lambert(triangles: np.ndarray, azim: float, elev: float) -> np.ndarray:
220219 return 0.45 + 0.55 * np .clip (normals @ light , 0 , 1 )
221220
222221
223- def _isosurfaces (points , values , counts_ ) -> dict [int , np .ndarray ]:
224- """Triangles of the f = 0.5 isosurface after the first n points, for each n."""
225- learner = adaptive .LearnerND (shell , bounds = [(- 1 , 1 )] * 3 )
226- surfaces , told = {}, 0
227- for n in counts_ :
228- for point , value in zip (points [told :n ], values [told :n ]):
229- learner .tell (tuple (point ), value )
230- told = n
231- vertices , faces = learner ._get_iso (level = 0.5 )
232- triangles = np .array (vertices )[np .array (faces )]
233- # Wind every triangle with its normal pointing away from the center,
234- # so the shading is consistent.
235- normals = np .cross (
236- triangles [:, 1 ] - triangles [:, 0 ], triangles [:, 2 ] - triangles [:, 0 ]
237- )
238- inward = np .einsum ("ij,ij->i" , normals , triangles .mean (axis = 1 )) < 0
239- triangles [inward ] = triangles [inward ][:, ::- 1 ]
240- surfaces [n ] = triangles
241- return surfaces
222+ def _isosurface (learner : adaptive .LearnerND ) -> np .ndarray :
223+ """Triangles of the learner's f = 0.5 isosurface, with outward normals."""
224+ vertices , faces = learner ._get_iso (level = 0.5 )
225+ triangles = np .array (vertices )[np .array (faces )]
226+ # Wind every triangle with its normal pointing away from the center,
227+ # so the shading is consistent.
228+ normals = np .cross (
229+ triangles [:, 1 ] - triangles [:, 0 ], triangles [:, 2 ] - triangles [:, 0 ]
230+ )
231+ inward = np .einsum ("ij,ij->i" , normals , triangles .mean (axis = 1 )) < 0
232+ triangles [inward ] = triangles [inward ][:, ::- 1 ]
233+ return triangles
242234
243235
244236def _render_gif (draw , nframes , figsize , target , hold = 2.5 , dpi = 100 , fps = 15 ):
0 commit comments