10C Inc 2: feature tail
119 of the app's 138 symbols now resolve; only the I/O modules and the Inc 4 tail are left. New: GCE2d, GCPnts, BRepFilletAPI, BRepOffsetAPI, ShapeAnalysis, ShapeFix, ShapeUpgrade, BRepCheck, BRepTools, BRepLib, BRepExtrema, BRepClass3d, IntCurvesFace, plus TopTools_HSequenceOfShape. The fillet and chamfer builders derive BRepBuilderAPI_MakeShape, so their history comes from the base bound in Inc 1 — which is what lets the app read a blend's provenance the same way it reads a boolean's. The Inc 2 gate compares that history exactly, alongside the splitter's, which is what sketch-region attribution depends on. Two shapes of deviation, both commented where they are bound: - Trailing enum arguments are left off four constructors (fillet's ChFi3d_FilletShape, MakeThickSolidByJoin's mode/join pair, BRepExtrema's Extrema flags, and Inc 1's GeomAPI_ProjectPointOnSurf). An unregistered enum cannot serve as a default argument — nanobind converts defaults at binding time, so it fails the whole module's import with std::bad_cast. The app never overrides any of them, so OCCT's own defaults apply and behaviour is unchanged. - ShapeAnalysis_FreeBounds.ConnectEdgesToWires reassigns a Handle& out parameter, which the caster cannot honour because it hands C++ a copy of the handle. The lambda splices the result into the sequence the caller passed, so the pass-empty-then-read shape the app uses still works. This is the one place upstream's holder semantics and ours differ observably. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DfriM8XUkn7uYf5Dwe2xo6
This commit is contained in:
@@ -314,6 +314,92 @@ def _constructions() -> dict:
|
||||
}
|
||||
|
||||
|
||||
def _inc2_reference() -> dict:
|
||||
"""Fillet, chamfer, splitter, healing and the query classes.
|
||||
|
||||
The fillet history is the point of this block: a blend's provenance is read
|
||||
exactly like a boolean's, and it is what attributes the new faces back to
|
||||
the feature that made them.
|
||||
"""
|
||||
from OCP.BRepAlgoAPI import BRepAlgoAPI_Splitter
|
||||
from OCP.BRepBuilderAPI import BRepBuilderAPI_MakeEdge
|
||||
from OCP.BRepClass3d import BRepClass3d_SolidClassifier
|
||||
from OCP.BRepExtrema import BRepExtrema_DistShapeShape
|
||||
from OCP.BRepFilletAPI import BRepFilletAPI_MakeChamfer, BRepFilletAPI_MakeFillet
|
||||
from OCP.BRepTools import BRepTools
|
||||
from OCP.ShapeUpgrade import ShapeUpgrade_UnifySameDomain
|
||||
from OCP.TopAbs import TopAbs_EDGE
|
||||
from OCP.TopoDS import TopoDS
|
||||
from OCP.TopTools import TopTools_ListOfShape
|
||||
|
||||
box = _box()
|
||||
edges = _sub_shapes(box, TopAbs_EDGE)
|
||||
|
||||
fillet = BRepFilletAPI_MakeFillet(box)
|
||||
fillet.Add(2.0, TopoDS.Edge_s(edges[0]))
|
||||
fillet.Build()
|
||||
filleted = fillet.Shape()
|
||||
|
||||
# The edge must belong to the very shape the builder was given, not an
|
||||
# equal one built separately — OCCT matches by identity.
|
||||
chamfer_box = _box()
|
||||
chamfer = BRepFilletAPI_MakeChamfer(chamfer_box)
|
||||
chamfer.Add(1.5, TopoDS.Edge_s(_sub_shapes(chamfer_box, TopAbs_EDGE)[0]))
|
||||
chamfer.Build()
|
||||
chamfered = chamfer.Shape()
|
||||
|
||||
# A splitter over an edge, mirroring how sketch regions are cut apart.
|
||||
splitter = BRepAlgoAPI_Splitter()
|
||||
split_box = _box()
|
||||
args, tools = TopTools_ListOfShape(), TopTools_ListOfShape()
|
||||
args.Append(split_box)
|
||||
tools.Append(
|
||||
BRepPrimAPI_MakeBox(gp_Pnt(-5, 5, -5), 20.0, 1.0, 40.0).Shape()
|
||||
)
|
||||
splitter.SetArguments(args)
|
||||
splitter.SetTools(tools)
|
||||
splitter.Build()
|
||||
|
||||
unify = ShapeUpgrade_UnifySameDomain(_fused(), True, True, True)
|
||||
unify.Build()
|
||||
|
||||
dist = BRepExtrema_DistShapeShape(
|
||||
_box(), BRepPrimAPI_MakeBox(gp_Pnt(40, 0, 0), 5.0, 5.0, 5.0).Shape()
|
||||
)
|
||||
|
||||
inside = BRepClass3d_SolidClassifier(box, gp_Pnt(5, 10, 15), 1e-7)
|
||||
outside = BRepClass3d_SolidClassifier(box, gp_Pnt(50, 10, 15), 1e-7)
|
||||
|
||||
face0 = TopoDS.Face_s(_sub_shapes(box, TopAbs_FACE)[0])
|
||||
|
||||
return {
|
||||
"fillet": {
|
||||
"sha256": hashlib.sha256(write_bytes(filleted)).hexdigest(),
|
||||
**_measure(filleted),
|
||||
"history": _history(fillet, box, filleted),
|
||||
},
|
||||
"chamfer": {
|
||||
"sha256": hashlib.sha256(write_bytes(chamfered)).hexdigest(),
|
||||
**_measure(chamfered),
|
||||
},
|
||||
"splitter": {
|
||||
**_measure(splitter.Shape()),
|
||||
"history": _history(splitter, split_box, splitter.Shape()),
|
||||
},
|
||||
"unified": _measure(unify.Shape()),
|
||||
"distance": {
|
||||
"is_done": bool(dist.IsDone()),
|
||||
"value": dist.Value(),
|
||||
"n_solutions": dist.NbSolution(),
|
||||
},
|
||||
"classifier": {"inside": int(inside.State()), "outside": int(outside.State())},
|
||||
"uv_bounds": list(BRepTools.UVBounds_s(face0)),
|
||||
"outer_wire_edges": len(
|
||||
_sub_shapes(BRepTools.OuterWire_s(face0), TopAbs_EDGE)
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def _inc1_reference() -> dict:
|
||||
op, base, _tool = _cut_cylinder_op()
|
||||
return {
|
||||
@@ -359,6 +445,7 @@ def main() -> int:
|
||||
print(f"{name}: {len(data)} bytes, {manifest['shapes'][name]['faces']} faces")
|
||||
|
||||
manifest["inc1"] = _inc1_reference()
|
||||
manifest["inc2"] = _inc2_reference()
|
||||
|
||||
(OUT / "manifest.json").write_text(json.dumps(manifest, indent=2) + "\n")
|
||||
print(f"\nwrote {len(SHAPES)} fixtures + manifest to {OUT}")
|
||||
|
||||
Reference in New Issue
Block a user