Files
Web_FreeCAD_Bitbybit/scripts/freecad-golden-driver.py

108 lines
4.3 KiB
Python

import json
import os
import FreeCAD as App
import Part
def make_feature_shape(type_id, properties):
document = App.newDocument("GoldenPrimitive")
try:
feature = document.addObject(type_id, "Primitive")
for name, value in properties.items():
setattr(feature, name, value)
document.recompute()
return feature.Shape.copy()
finally:
App.closeDocument(document.Name)
def make_shape(operation):
kind = operation["type"]
if kind == "box":
shape = Part.makeBox(operation["length"], operation["width"], operation["height"])
elif kind == "cylinder":
shape = Part.makeCylinder(operation["radius"], operation["height"], App.Vector(0, 0, 0), App.Vector(0, 0, 1), operation["angle"])
elif kind == "sphere":
shape = Part.makeSphere(operation["radius"])
elif kind == "cone":
shape = Part.makeCone(operation["radius1"], operation["radius2"], operation["height"], App.Vector(0, 0, 0), App.Vector(0, 0, 1), operation["angle"])
elif kind == "ellipsoid":
shape = make_feature_shape("Part::Ellipsoid", {
"Radius1": operation["radius1"], "Radius2": operation["radius2"], "Radius3": operation["radius3"],
"Angle1": operation["angle1"], "Angle2": operation["angle2"], "Angle3": operation["angle3"],
})
elif kind == "torus":
shape = make_feature_shape("Part::Torus", {
"Radius1": operation["radius1"], "Radius2": operation["radius2"],
"Angle1": operation["angle1"], "Angle2": operation["angle2"], "Angle3": operation["angle3"],
})
elif kind == "prism":
shape = make_feature_shape("Part::Prism", {
"Polygon": operation["polygon"], "Circumradius": operation["circumradius"], "Height": operation["height"],
"FirstAngle": operation["firstAngle"], "SecondAngle": operation["secondAngle"],
})
elif kind == "wedge":
shape = make_feature_shape("Part::Wedge", {
"Xmin": operation["xmin"], "Ymin": operation["ymin"], "Zmin": operation["zmin"],
"Z2min": operation["z2min"], "X2min": operation["x2min"], "Xmax": operation["xmax"],
"Ymax": operation["ymax"], "Zmax": operation["zmax"], "Z2max": operation["z2max"], "X2max": operation["x2max"],
})
elif kind == "helix":
shape = make_feature_shape("Part::Helix", {
"Pitch": operation["pitch"], "Height": operation["height"], "Radius": operation["radius"],
"Angle": operation["angle"], "SegmentLength": operation["segmentLength"],
})
elif kind in ("cut", "fuse", "common"):
base = make_shape(operation["base"])
tool = make_shape(operation["tool"])
shape = base.cut(tool) if kind == "cut" else base.fuse(tool) if kind == "fuse" else base.common(tool)
else:
raise ValueError("Unsupported golden operation: " + kind)
placement_value = operation.get("placement")
if placement_value:
placement = App.Placement()
placement.Base = App.Vector(*(placement_value.get("translation") or [0, 0, 0]))
rotation = placement_value.get("rotation")
if rotation:
placement.Rotation = App.Rotation(App.Vector(*rotation["axis"]), rotation["angle"])
shape = shape.copy()
shape.Placement = placement
return shape
def vector(x, y, z):
return [float(x), float(y), float(z)]
scenario_path = os.environ.get("FREECAD_GOLDEN_SCENARIO")
if not scenario_path:
raise RuntimeError("FREECAD_GOLDEN_SCENARIO is required")
with open(scenario_path, "r", encoding="utf-8") as scenario_file:
scenario = json.load(scenario_file)
shape = make_shape(scenario["operation"])
box = shape.BoundBox
version = App.Version()
result = {
"schemaVersion": 1,
"fixtureId": scenario["id"],
"freecadVersion": ".".join(str(value) for value in version[:3]),
"shapeType": shape.ShapeType,
"isNull": shape.isNull(),
"isValid": shape.isValid(),
"solids": len(shape.Solids),
"faces": len(shape.Faces),
"edges": len(shape.Edges),
"vertices": len(shape.Vertexes),
"volume": float(shape.Volume),
"area": float(shape.Area),
"boundingBox": {
"min": vector(box.XMin, box.YMin, box.ZMin),
"max": vector(box.XMax, box.YMax, box.ZMax),
},
}
print("FREECAD_GOLDEN_RESULT=" + json.dumps(result, sort_keys=True, separators=(",", ":")))