Feature: Globe Box
Purpose
Printable 3D models of a small Earth globe rendered from the GDEM data on the shared /datasets volume: the globe (100 mm diameter at sea level) is split into two hollow hemisphere halves divided at the equator, and a third piece — a hollow twist-lock cylinder — joins the two halves. Each piece is an STL file that loads into a slicer (OrcaSlicer, PrusaSlicer) and prints on a 3D printer.
Requirements
GLOBE-BOX-R001—scripts/globe-box-build.shmust render the piece set intodataflow.out/box/from the ETOPO 2022 source tiles (/datasets/dataset-etopo-2022/, read-only).GLOBE-BOX-R002— The globe is 100 mm in diameter at sea level: the sea-level sphere has radiusradius_mm = 50; land elevation maps to relief above sea level (relief_mm, default 4), and with--oceans-flat(the standard build) water-covered cells are clamped to sea level.GLOBE-BOX-R003— The piece set is exactly five STL files plus a manifest:globe-north.stl— the northern hemisphere half (lat 0..90).globe-south.stl— the southern hemisphere half (lat -90..0).pellucidar-north.stl— the Pellucidar liner nesting in the northern half.pellucidar-south.stl— the Pellucidar liner nesting in the southern half.twist-lock.stl— the hollow cylinder that joins the halves.
GLOBE-BOX-R004— Each liner must be a thin bowl against its half’s inner surface (outer radius = inner sphere radius minusliner_clearance_mm), wallliner_wall_mm, with Pellucidar’s map on the concave face (relief rising toward the hollow centre) inliner_relief_mm.GLOBE-BOX-R005— Pellucidar’s geography must be the ETOPO elevation INVERTED, with flat seas: our ocean is its land and our land is its sea.GLOBE-BOX-R006— Each liner must be watertight, its rim annulus must be the piece’s lowest face (so it prints flat), and its relief must be faded to zero at the rim (liner_rim_fade_degrees) so the map surface cannot dip below the rim plane.GLOBE-BOX-R007— Each liner must seat on the socket ledge:liner_rim_radius_mmmust exceed the socket bore radius (so the flexing rim catches the ledge) and stay inside the ledge, and the resulting seat must leave the liner clear of the twist-lock ring.GLOBE-BOX-R008— Each liner must have a polar tunnel on its axis, so the hollow interior still vents through the half’s pole hole.GLOBE-BOX-R009— The two liners must sample the same geographic frame as the halves (the south liner mirrors longitude), so they form one continuous world.GLOBE-BOX-R010— Each half is a hollow shell: the outer surface is the globe surface with elevation relief; the inner surface is a sphere of radiusradius_mm - wall_mm(wall_mmdefault 3), except near the rim where it is a cylindrical socket (bore) of radiussocket_radius_mmfor a depthsocket_depth_mm(default 12).GLOBE-BOX-R011— Each half must have a flat rim (annulus) at z = 0 that sits against the printer bed; the STL’s z = 0 is the rim plane.GLOBE-BOX-R012— Each half must be a watertight solid (every edge shared by exactly two triangles), so slicers accept it.GLOBE-BOX-R013— Each half must have a 2 mm vent hole on its pole axis (pole_hole_diameter_mm, default 2.0) bored through the shell into the hollow interior, so air escapes when the halves are pushed together instead of being trapped; the hole must keep the piece watertight. A value of 0 closes the poles again.GLOBE-BOX-R014— The relief must be continuous across the seam: the two halves sample the same elevation grid at the equator, so the rim rings match.GLOBE-BOX-R015— Twist-lock cylinder: a hollow tube whose outer surface mates with the inner surface of the two halves’ sockets (radiussocket_radius_mmminusclearance_mm, default 0.2). It is entirely internal: a plain tube of length 2 xcylinder_socket_length_mmwith no protruding band (band_width_mm, default 0), so the two hemispheres’ rims meet at the equator. A positiveband_width_mminstead gives the ring a knurled band of radiusradius_mm + relief_mm + 2that stays outside at the seam as a grip.GLOBE-BOX-R016— The twist-lock is a bayonet: 3 pins on the cylinder near each end, at 0/120/240 degrees, engage L-shaped grooves cut into the inner surface of each half’s socket. Insert the cylinder into one half with the pins aligned to the groove entrances, slide the other half over the far end, then twist the two hemispheres in OPPOSITE directions bytwist_degrees(default 30) to lock both halves at once; the ring stays put (held by its friction fit), so two hands (one per hemisphere) lock and unlock the globe with a natural motion.GLOBE-BOX-R017— The two halves’ grooves are generated with the same handedness in their own STL frames (both -twist; the south half is assembled rotated 180 degrees about the x axis, which reverses its azimuth), so in the assembled globe the two halves’ grooves turn in OPPOSITE directions. The north half’s groove pattern is offset +2 xtwist_degreesin its STL frame, so the north starts 2 x twist degrees west of the south; the opposite-direction twists bring both halves to the same rotation, so the relief seam is aligned when locked.GLOBE-BOX-R018— The underside of each half may carry an engraved (recessed) label; z = 0 must stay the lowest plane.GLOBE-BOX-R019— Output format: binary STL, millimeters.GLOBE-BOX-R020—scripts/globe-box-build.sh --checkmust validate every generated piece (watertight, flat rim at z = 0, expected bounds, positive signed volume, mating geometry) without rebuilding.GLOBE-BOX-R021— The build must writedataflow.out/box/manifest.json: parameters, piece list with bounds and sizes, and provenance (dataset, script, timestamp, git commit).GLOBE-BOX-R022—scripts/globe-box-assemble.shmust build an assembled web model: the three pieces rebuilt at coarse sampling and merged into one grouped Wavefront OBJ (dataflow.out/box/globe-assembled.obj, groupsglobe-north,globe-south,twist-lock) plusassemble.json. The assembled pose puts the north rim at z = +band_width/2 and the south rim at z = -band_width/2 (the south half rotated 180 degrees about x), with the ring spanning the seam — so with the default band width 0 the rims meet at z = 0 and the ring is entirely inside.GLOBE-BOX-R023— The site must include anassemble.htmlpage with an interactive 3D view of the assembled model (drag to rotate, scroll to zoom), following themodel-render-printframe-page pattern (three.js, grouped OBJ).GLOBE-BOX-R024— Derived output (dataflow.out/box/) is generated and must not be edited by hand.
Behavior
- Running the script recreates the piece set deterministically from the source tiles and the given parameters.
- Re-running the script overwrites existing pieces.
Dependencies
None. This feature depends on no other feature.
External Inputs
- Tool-gated: GDAL 3.8+ and Python 3 with the
osgeoandnumpymodules, plus the ETOPO source tiles under/datasetson the owning host. - Dataset
etopo-2022maintained by themodel-elevation-earthproject.