126 lines
3.7 KiB
Python
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))
|