Files
Web_FreeCAD_Bitbybit/scripts/freecad-partdesign-profile-oracle.py

126 lines
3.7 KiB
Python

import json
import FreeCAD as App
import Part
import Sketcher
LENGTH = 10.0
TOLERANCE = 1e-7
def line(start, end):
return Part.LineSegment(App.Vector(start[0], start[1], 0), App.Vector(end[0], end[1], 0))
def add_loop(sketch, points, closed=True):
segment_count = len(points) if closed else len(points) - 1
sketch.addGeometry([line(points[index], points[(index + 1) % len(points)]) for index in range(segment_count)], False)
def object_status(feature):
try:
status_string = feature.getStatusString()
except Exception:
status_string = ""
return {
"state": [str(value) for value in feature.State],
"statusString": str(status_string),
}
def run_case(case_id, expected, setup):
document = App.newDocument("ProfileOracle_" + case_id.replace("-", "_"))
try:
body = document.addObject("PartDesign::Body", "Body")
sketch = document.addObject("Sketcher::SketchObject", "Sketch")
body.addObject(sketch)
sketch.MapMode = "Deactivated"
setup(sketch)
document.recompute()
pad = document.addObject("PartDesign::Pad", "Pad")
pad.Profile = sketch
pad.Length = LENGTH
body.addObject(pad)
recompute_result = document.recompute()
shape_null = bool(pad.Shape.isNull())
volume = 0.0 if shape_null else float(pad.Shape.Volume)
solids = 0 if shape_null else len(pad.Shape.Solids)
accepted = not shape_null and volume > TOLERANCE and solids >= 1
observed = "accepted" if accepted else "rejected"
return {
"id": case_id,
"expected": expected,
"observed": observed,
"passed": observed == expected,
"recomputeResult": bool(recompute_result),
"shapeNull": shape_null,
"solidCount": int(solids),
"volume": volume,
**object_status(pad),
}
except Exception as error:
return {
"id": case_id,
"expected": expected,
"observed": "rejected",
"passed": expected == "rejected",
"errorType": type(error).__name__,
"error": str(error),
}
finally:
App.closeDocument(document.Name)
OUTER = [(0, 0), (6, 0), (6, 6), (0, 6)]
HOLE = [(2, 2), (2, 4), (4, 4), (4, 2)]
def closed_profile(sketch):
add_loop(sketch, OUTER)
def multi_ring_profile(sketch):
add_loop(sketch, HOLE)
add_loop(sketch, OUTER)
def open_profile(sketch):
add_loop(sketch, OUTER, False)
def self_intersecting_profile(sketch):
add_loop(sketch, [(0, 0), (4, 4), (0, 4), (4, 0)])
def disjoint_profile(sketch):
add_loop(sketch, OUTER)
add_loop(sketch, [(8, 8), (9, 8), (9, 9), (8, 9)])
cases = [
run_case("closed", "accepted", closed_profile),
run_case("multi-ring", "accepted", multi_ring_profile),
run_case("open", "rejected", open_profile),
run_case("self-intersecting", "accepted", self_intersecting_profile),
run_case("invalid-nesting", "accepted", disjoint_profile),
]
report = {
"schemaVersion": 1,
"baselineId": "freecad-1.1.1-partdesign-profile-oracle",
"freecadVersion": ".".join(App.Version()[0:3]),
"gitCommit": "0108fd4b4850cc46e625b60e53cea7a7bbe69f8d",
"length": LENGTH,
"tolerance": TOLERANCE,
"status": "pass" if all(case["passed"] for case in cases) else "failed",
"summary": {
"cases": len(cases),
"passed": sum(1 for case in cases if case["passed"]),
"accepted": sum(1 for case in cases if case["observed"] == "accepted"),
"rejected": sum(1 for case in cases if case["observed"] == "rejected"),
},
"cases": cases,
}
print("FREECAD_PARTDESIGN_PROFILE_ORACLE_RESULT=" + json.dumps(report, sort_keys=True))