Files
Web_FreeCAD_Bitbybit/scripts/freecad-attachment-mode-oracle.py
wangdequan f97eae4153
Some checks failed
real-verification / chrome (push) Has been cancelled
real-verification / freecad-oracle (push) Has been cancelled
real-verification / wasm (push) Has been cancelled
feat: add candidate FreeCAD naming SDK and attachment oracles
Build and verify the candidate-only FreeCAD naming bridge and OCCT worker path, including three-stage StringHasher restoration. Add Datum, ShapeBinder, attachment-mode, and PartDesign structure oracles plus offline SDK build plans and CI boundary checks.
2026-08-13 17:16:07 -04:00

183 lines
6.5 KiB
Python

import json
import os
import tempfile
import FreeCAD as App
def version_text():
return ".".join(str(value) for value in App.Version()[:3])
def placement_json(placement):
axis = placement.Rotation.Axis
base = placement.Base
return {
"position": [float(base.x), float(base.y), float(base.z)],
"axis": [float(axis.x), float(axis.y), float(axis.z)],
"angleDegrees": float(placement.Rotation.Angle * 180.0 / 3.141592653589793),
}
def support_json(value):
result = []
for obj, sub_elements in value:
subs = [sub_elements] if isinstance(sub_elements, str) else list(sub_elements)
result.append({
"document": obj.Document.Name,
"object": obj.Name,
"subElements": [str(sub) for sub in subs if str(sub)],
})
return result
def engine_json(obj):
attacher = obj.Attacher
implemented = list(attacher.ImplementedModes)
return {
"typeId": obj.TypeId,
"attacherType": attacher.AttacherType,
"completeModeList": list(attacher.CompleteModeList),
"implementedModes": implemented,
"modeInfo": {
mode: {
"modeIndex": int(attacher.getModeInfo(mode)["ModeIndex"]),
"referenceCombinations": attacher.getModeInfo(mode)["ReferenceCombinations"],
}
for mode in implemented
},
}
def object_state(obj):
suggestion = obj.Attacher.suggestModes()
return {
"typeId": obj.TypeId,
"mapMode": str(obj.MapMode),
"support": support_json(obj.AttachmentSupport),
"placement": placement_json(obj.Placement),
"state": [str(value) for value in obj.State],
"status": str(obj.getStatusString()),
"positionBySupport": bool(obj.positionBySupport()),
"suggestion": {
"message": suggestion["message"],
"bestFitMode": suggestion["bestFitMode"],
"allApplicableModes": suggestion["allApplicableModes"],
"referenceTypes": suggestion["references_Types"],
},
}
document = App.newDocument("AttachmentModeOracle")
source_body = document.addObject("PartDesign::Body", "SourceBody")
source_box = source_body.newObject("PartDesign::AdditiveBox", "SourceBox")
source_box.Length = 4
source_box.Width = 5
source_box.Height = 6
document.recompute()
plane_body = document.addObject("PartDesign::Body", "PlaneBody")
datum_plane = plane_body.newObject("PartDesign::Plane", "DatumPlane")
datum_plane.AttachmentSupport = [(source_box, "Face1")]
datum_plane.MapMode = "FlatFace"
line_body = document.addObject("PartDesign::Body", "LineBody")
datum_line = line_body.newObject("PartDesign::Line", "DatumLine")
datum_line.AttachmentSupport = [(source_box, ("Vertex1", "Vertex2"))]
datum_line.MapMode = "TwoPointLine"
point_body = document.addObject("PartDesign::Body", "PointBody")
datum_point = point_body.newObject("PartDesign::Point", "DatumPoint")
datum_point.AttachmentSupport = [(source_box, "Vertex1")]
datum_point.MapMode = "Vertex"
sketch_body = document.addObject("PartDesign::Body", "SketchBody")
sketch = sketch_body.newObject("Sketcher::SketchObject", "Sketch")
sketch.AttachmentSupport = [(source_box, "Face1")]
sketch.MapMode = "FlatFace"
invalid_plane_body = document.addObject("PartDesign::Body", "InvalidPlaneBody")
invalid_plane = invalid_plane_body.newObject("PartDesign::Plane", "InvalidPlane")
invalid_plane.AttachmentSupport = [(source_box, "Vertex1")]
invalid_plane.MapMode = "Vertex"
invalid_line_body = document.addObject("PartDesign::Body", "InvalidLineBody")
invalid_line = invalid_line_body.newObject("PartDesign::Line", "InvalidLine")
invalid_line.AttachmentSupport = [(source_box, "Face1")]
invalid_line.MapMode = "FlatFace"
invalid_point_body = document.addObject("PartDesign::Body", "InvalidPointBody")
invalid_point = invalid_point_body.newObject("PartDesign::Point", "InvalidPoint")
invalid_point.AttachmentSupport = [(source_box, "Face1")]
invalid_point.MapMode = "FlatFace"
document.recompute()
engine_objects = {
"plane": datum_plane,
"line": datum_line,
"point": datum_point,
"sketch": sketch,
}
engines = {name: engine_json(obj) for name, obj in engine_objects.items()}
success_initial = {name: object_state(obj) for name, obj in engine_objects.items()}
failures = {
obj.Name: {
"typeId": obj.TypeId,
"mapMode": str(obj.MapMode),
"support": support_json(obj.AttachmentSupport),
"state": [str(value) for value in obj.State],
"status": str(obj.getStatusString()),
}
for obj in [invalid_plane, invalid_line, invalid_point]
}
source_box.Height = 9
document.recompute()
success_edited = {name: object_state(obj) for name, obj in engine_objects.items()}
with tempfile.TemporaryDirectory(prefix="freecad-attachment-mode-") as temp_dir:
path = os.path.join(temp_dir, "AttachmentModeOracle.FCStd")
document.saveAs(path)
App.closeDocument(document.Name)
reopened = App.openDocument(path)
reopened.recompute()
roundtrip = {
name: object_state(reopened.getObject(object_name))
for name, object_name in {
"plane": "DatumPlane",
"line": "DatumLine",
"point": "DatumPoint",
"sketch": "Sketch",
}.items()
}
roundtrip_failures = {
object_name: {
"mapMode": str(reopened.getObject(object_name).MapMode),
"state": [str(value) for value in reopened.getObject(object_name).State],
"status": str(reopened.getObject(object_name).getStatusString()),
}
for object_name in ["InvalidPlane", "InvalidLine", "InvalidPoint"]
}
App.closeDocument(reopened.Name)
all_modes = engines["plane"]["completeModeList"]
implemented_union = sorted({mode for engine in engines.values() for mode in engine["implementedModes"]})
report = {
"schemaVersion": 1,
"baselineId": "freecad-1.1.1-attachment-mode-oracle",
"freecadVersion": version_text(),
"gitCommit": "0108fd4b4850cc46e625b60e53cea7a7bbe69f8d",
"status": "pass",
"tolerance": 1e-7,
"registry": {
"modeCount": len(all_modes),
"modes": all_modes,
"implementedUnionCount": len(implemented_union),
"unimplementedModes": [mode for mode in all_modes if mode not in implemented_union],
},
"engines": engines,
"success": {"initial": success_initial, "edited": success_edited, "roundtrip": roundtrip},
"failures": {"initial": failures, "roundtrip": roundtrip_failures},
}
print("FREECAD_ATTACHMENT_MODE_RESULT=" + json.dumps(report, sort_keys=True, separators=(",", ":")))