"""Debug (2026-10-13): build the tapered coping pieces step by step and report validity / boolean results. Run through the app runner: python -c "..." (see tools usage in the session log).""" import json import math import Rhino.Geometry as rg P = json.load(open(PARAMS_PATH, encoding="utf-8")) c = P["coping"] TOL = 0.01 out = {} w, R, L0, z_tip = c["width_y"], c["plan_corner_radius"], c["plan_length"], c["z_tip"] zmin = min(z for _, z in c["profile_xz"]) trap = [(-1250, zmin), (1250, zmin), (L0 / 2, z_tip), (-L0 / 2, z_tip)] prof = rg.PolylineCurve([rg.Point3d(x, -w / 2, z) for x, z in trap + trap[:1]]) srf = rg.Surface.CreateExtrusion(prof, rg.Vector3d(0, w, 0)) low = srf.ToBrep().CapPlanarHoles(TOL) out["lower"] = dict(valid=low.IsValid, solid=low.IsSolid, orient=str(low.SolidOrientation), vol=rg.VolumeMassProperties.Compute(low).Volume if low.IsSolid else None) if low.SolidOrientation == rg.BrepSolidOrientation.Inward: low.Flip() cx, cy = L0 / 2 - R, w / 2 - R blk = rg.Box(rg.BoundingBox(cx, cy, zmin - 100, cx + R + 100, cy + R + 100, z_tip + 100)).ToBrep() cyl = rg.Cylinder(rg.Circle(rg.Plane(rg.Point3d(cx, cy, zmin - 200), rg.Vector3d.ZAxis), R), z_tip - zmin + 400).ToBrep(True, True) waste = rg.Brep.CreateBooleanDifference(blk, cyl, TOL) out["waste"] = dict(n=len(waste) if waste else 0, valid=[b.IsValid for b in waste] if waste else None, solid=[b.IsSolid for b in waste] if waste else None) if waste: d1 = rg.Brep.CreateBooleanDifference(low, waste[0], TOL) out["low_minus_one"] = dict(n=len(d1) if d1 else 0) inter = rg.Brep.CreateBooleanIntersection(low, waste[0], TOL) out["low_and_one"] = dict(n=len(inter) if inter else 0, vol=[rg.VolumeMassProperties.Compute(b).Volume for b in inter] if inter else None) x = rg.Intersect.Intersection.BrepBrep(low, waste[0], TOL) out["brepbrep"] = dict(ok=x[0], curves=len(x[1]), pts=len(x[2])) json.dump(out, open(OUT_PATH, "w"), indent=1, default=str) print(json.dumps(out, default=str))