130 lines
4.6 KiB
Python
130 lines
4.6 KiB
Python
import json
|
|
|
|
import FreeCAD as App
|
|
import Part
|
|
import Sketcher
|
|
|
|
from freecad_mutation_evidence import capture_property_mutation
|
|
|
|
|
|
def version_text():
|
|
return ".".join(str(value) for value in App.Version()[:3])
|
|
|
|
|
|
def square_sketch(body, name, half_size, z=0.0):
|
|
sketch = body.newObject("Sketcher::SketchObject", name)
|
|
points = [(-half_size, -half_size), (half_size, -half_size), (half_size, half_size), (-half_size, half_size)]
|
|
for index, start in enumerate(points):
|
|
end = points[(index + 1) % len(points)]
|
|
sketch.addGeometry(Part.LineSegment(App.Vector(start[0], start[1], 0), App.Vector(end[0], end[1], 0)), False)
|
|
sketch.Placement.Base.z = z
|
|
return sketch
|
|
|
|
|
|
def shape_result(case_id, document, feature):
|
|
document.recompute()
|
|
shape = feature.Shape
|
|
box = shape.BoundBox if not shape.isNull() else None
|
|
return {
|
|
"id": case_id,
|
|
"passed": not shape.isNull() and shape.isValid(),
|
|
"status": feature.getStatusString(),
|
|
"solids": len(shape.Solids) if not shape.isNull() else 0,
|
|
"faces": len(shape.Faces) if not shape.isNull() else 0,
|
|
"volume": float(shape.Volume) if not shape.isNull() else 0.0,
|
|
"bounds": None if box is None else {
|
|
"min": [float(box.XMin), float(box.YMin), float(box.ZMin)],
|
|
"max": [float(box.XMax), float(box.YMax), float(box.ZMax)],
|
|
},
|
|
}
|
|
|
|
|
|
def tapered_pad():
|
|
document = App.newDocument("TaperedPadOracle")
|
|
body = document.addObject("PartDesign::Body", "Body")
|
|
sketch = square_sketch(body, "Sketch", 2.0)
|
|
pad = body.newObject("PartDesign::Pad", "Pad")
|
|
pad.Profile = sketch
|
|
pad.Type = "Length"
|
|
pad.Length = 5.0
|
|
pad.TaperAngle = 5.0
|
|
mutation = capture_property_mutation(document, pad, "Length", 6.0)
|
|
result = shape_result("pad-tapered", document, pad)
|
|
result["mutation"] = mutation
|
|
App.closeDocument(document.Name)
|
|
return result
|
|
|
|
|
|
def base_and_pocket_document(name, half_size=2.0):
|
|
document = App.newDocument(name)
|
|
body = document.addObject("PartDesign::Body", "Body")
|
|
base = body.newObject("PartDesign::Feature", "Base")
|
|
base.Shape = Part.makeBox(10, 10, 10, App.Vector(-5, -5, -5))
|
|
sketch = square_sketch(body, "Sketch", half_size, 5.0)
|
|
pocket = body.newObject("PartDesign::Pocket", "Pocket")
|
|
pocket.Profile = sketch
|
|
if hasattr(pocket, "BaseFeature"):
|
|
pocket.BaseFeature = base
|
|
return document, body, base, sketch, pocket
|
|
|
|
|
|
def tapered_pocket():
|
|
document, _, _, _, pocket = base_and_pocket_document("TaperedPocketOracle")
|
|
pocket.Type = "Length"
|
|
pocket.Length = 10.0
|
|
pocket.TaperAngle = 2.0
|
|
mutation = capture_property_mutation(document, pocket, "Length", 8.0)
|
|
result = shape_result("pocket-tapered", document, pocket)
|
|
result["mutation"] = mutation
|
|
App.closeDocument(document.Name)
|
|
return result
|
|
|
|
|
|
def through_all_pocket():
|
|
document, _, _, _, pocket = base_and_pocket_document("ThroughAllPocketOracle", 1.0)
|
|
pocket.Type = 1
|
|
result = shape_result("pocket-through-all", document, pocket)
|
|
App.closeDocument(document.Name)
|
|
return result
|
|
|
|
|
|
def up_to_face_pocket():
|
|
document, _, base, _, pocket = base_and_pocket_document("UpToFacePocketOracle", 1.0)
|
|
document.recompute()
|
|
top_face = min(range(len(base.Shape.Faces)), key=lambda index: base.Shape.Faces[index].CenterOfMass.z) + 1
|
|
pocket.Type = 3
|
|
pocket.UpToFace = (base, ["Face{}".format(top_face)])
|
|
result = shape_result("pocket-up-to-face", document, pocket)
|
|
result["targetFace"] = top_face
|
|
App.closeDocument(document.Name)
|
|
return result
|
|
|
|
|
|
def midplane_pad():
|
|
document = App.newDocument("MidplanePadOracle")
|
|
body = document.addObject("PartDesign::Body", "Body")
|
|
sketch = square_sketch(body, "Sketch", 2.0)
|
|
pad = body.newObject("PartDesign::Pad", "Pad")
|
|
pad.Profile = sketch
|
|
pad.Type = "Length"
|
|
pad.Length = 6.0
|
|
pad.Midplane = True
|
|
result = shape_result("pad-midplane", document, pad)
|
|
App.closeDocument(document.Name)
|
|
return result
|
|
|
|
|
|
cases = [tapered_pad(), tapered_pocket(), through_all_pocket(), up_to_face_pocket(), midplane_pad()]
|
|
version = App.Version()
|
|
report = {
|
|
"schemaVersion": 1,
|
|
"baselineId": "freecad-1.1.1-partdesign-base-oracle",
|
|
"freecadVersion": version_text(),
|
|
"gitCommit": "0108fd4b4850cc46e625b60e53cea7a7bbe69f8d",
|
|
"status": "pass" if all(case["passed"] for case in cases) else "failed",
|
|
"tolerance": 1e-7,
|
|
"cases": cases,
|
|
"summary": {"cases": len(cases), "passed": sum(1 for case in cases if case["passed"])},
|
|
}
|
|
print("FREECAD_PARTDESIGN_BASE_RESULT=" + json.dumps(report, sort_keys=True, separators=(",", ":")))
|