from __future__ import annotations
import argparse
import sys
from pathlib import Path
from geomcore import Frame, Point, Transform, Vector
from geomcore.surfaces import Cone, Cylinder, Plane, Sphere, Torus
import geomcore_viewer as gv
TYPES = ["Plane", "Cylinder", "Cone", "Sphere", "Torus"]
CELL_STEP = 18.0
def canonical(name: str):
if name == "Plane":
return Plane(Point.origin(), Vector.unit_z())
if name == "Cylinder":
return Cylinder(Point.origin(), Vector.unit_z(), 2.0)
if name == "Cone":
return Cone.from_frame(Frame.world(), 0.4, 2.0)
if name == "Sphere":
return Sphere(Point.origin(), 3.0)
if name == "Torus":
return Torus(Point.origin(), Vector.unit_z(), 4.0, 1.0)
raise KeyError(name)
TILTED_CONE = Cone.from_frame(Frame(Point(0.0, 0.0, 1.0), Vector.unit_z(), Vector.unit_x()), 0.6, 1.0)
WIDE_CONE = Cone.from_frame(Frame.world(), 1.1, 2.0)
RAISED_SPHERE = Sphere(Point(0.0, 0.0, 1.0), 4.0)
WIDE_CYLINDER = Cylinder(Point.origin(), Vector.unit_z(), 4.5)
PAIRS = {
("Plane", "Plane"): (canonical("Plane"), Plane(Point.origin(), Vector.unit_x())),
("Sphere", "Sphere"): (canonical("Sphere"), Sphere(Point(3.0, 0.0, 0.0), 2.0)),
("Cylinder", "Cylinder"): (
canonical("Cylinder"),
Cylinder(Point(3.0, 0.0, 0.0), Vector.unit_z(), 2.0),
),
("Cone", "Cone"): (canonical("Cone"), TILTED_CONE),
("Torus", "Torus"): (
canonical("Torus"),
Torus(Point(0.0, 0.0, 1.5), Vector.unit_z(), 4.0, 1.0),
),
("Torus", "Sphere"): (canonical("Torus"), RAISED_SPHERE),
("Sphere", "Torus"): (RAISED_SPHERE, canonical("Torus")),
("Torus", "Cylinder"): (canonical("Torus"), WIDE_CYLINDER),
("Cylinder", "Torus"): (WIDE_CYLINDER, canonical("Torus")),
("Torus", "Cone"): (canonical("Torus"), WIDE_CONE),
("Cone", "Torus"): (WIDE_CONE, canonical("Torus")),
}
def cell_surfaces(row: str, col: str):
return PAIRS.get((row, col), (canonical(row), canonical(col)))
def main() -> int:
ap = argparse.ArgumentParser(description=__doc__)
ap.add_argument("--out", default=None, help="output scene.json path")
ap.add_argument("--serve", action="store_true", help="also send the scene to the live viewer")
args = ap.parse_args()
view = gv.Viewer("Surface intersection matrix", spawn=args.serve)
with_curve, empty = [], []
for i, row in enumerate(TYPES):
for j, col in enumerate(TYPES):
move = Transform.translation(Vector(j * CELL_STEP, -i * CELL_STEP, 0.0))
s1, s2 = (surface.transformed(move) for surface in cell_surfaces(row, col))
result = s1.intersect(s2)
view.add(result, label=f"{row}×{col}")
if result.curves:
with_curve.append(f"({row},{col})")
else:
empty.append(f"({row},{col})")
out = Path(args.out) if args.out else Path(__file__).with_suffix(".scene.json")
view.save(out)
print(f"saved {out} ({len(view.objects)} objects)")
print(f"cells with intersection curves ({len(with_curve)}): {' '.join(with_curve)}")
print(f"cells with no curve ({len(empty)}): {' '.join(empty)}")
return 0
if __name__ == "__main__":
sys.exit(main())