|
|
|
|
@ -102,6 +102,14 @@ def _point_payload(point):
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _route_length(points):
|
|
|
|
|
total = 0.0
|
|
|
|
|
normalized = [_vector(point) for point in points or []]
|
|
|
|
|
for index in range(len(normalized) - 1):
|
|
|
|
|
total += _distance(normalized[index], normalized[index + 1])
|
|
|
|
|
return total
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _is_finite_point(point):
|
|
|
|
|
try:
|
|
|
|
|
return all(
|
|
|
|
|
@ -514,26 +522,43 @@ def _set_string(obj, name, value, description="Auto-routing property"):
|
|
|
|
|
TerminalObjects.ensure_string_property(obj, name, "QET Routing", description, value)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _route_payload(route_data, collisions):
|
|
|
|
|
def _route_payload(route_data, collisions, wire_style_id=""):
|
|
|
|
|
points = route_data.get("points", [])
|
|
|
|
|
return {
|
|
|
|
|
"algorithm": route_data.get("algorithm", ""),
|
|
|
|
|
"points": [_point_payload(point) for point in route_data.get("points", [])],
|
|
|
|
|
"length_mm": _route_length(points),
|
|
|
|
|
"wire_style_id": str(wire_style_id or "").strip(),
|
|
|
|
|
"points": [_point_payload(point) for point in points],
|
|
|
|
|
"collision_count": len(collisions),
|
|
|
|
|
"collisions": collisions,
|
|
|
|
|
"network": route_data.get("network", {}),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _set_auto_metadata(wire, route_data, collisions):
|
|
|
|
|
def _set_auto_metadata(wire, route_data, collisions, wire_style_id=""):
|
|
|
|
|
length_mm = _route_length(route_data.get("points", []))
|
|
|
|
|
_set_string(
|
|
|
|
|
wire,
|
|
|
|
|
"QetAutoRouteAlgorithm",
|
|
|
|
|
route_data.get("algorithm", ""),
|
|
|
|
|
"Auto-routing algorithm used for this wire",
|
|
|
|
|
)
|
|
|
|
|
_set_string(
|
|
|
|
|
wire,
|
|
|
|
|
"QetAutoRouteLengthMm",
|
|
|
|
|
"{0:.3f}".format(length_mm),
|
|
|
|
|
"Auto route length in millimeters",
|
|
|
|
|
)
|
|
|
|
|
_set_string(
|
|
|
|
|
wire,
|
|
|
|
|
"QetWireStyleId",
|
|
|
|
|
str(wire_style_id or "").strip(),
|
|
|
|
|
"QET wire style ID",
|
|
|
|
|
)
|
|
|
|
|
_set_string(
|
|
|
|
|
wire,
|
|
|
|
|
"QetAutoRouteDiagnosticsJson",
|
|
|
|
|
json.dumps(_route_payload(route_data, collisions), ensure_ascii=False),
|
|
|
|
|
json.dumps(_route_payload(route_data, collisions, wire_style_id=wire_style_id), ensure_ascii=False),
|
|
|
|
|
"Auto-routing diagnostics",
|
|
|
|
|
)
|
|
|
|
|
if route_data.get("network"):
|
|
|
|
|
@ -870,6 +895,7 @@ def route_between_terminals(
|
|
|
|
|
group_uuid="",
|
|
|
|
|
wire_mark="",
|
|
|
|
|
wire_mark_is_manual=False,
|
|
|
|
|
wire_style_id="",
|
|
|
|
|
):
|
|
|
|
|
if doc is None:
|
|
|
|
|
raise AutoRoutingError("No FreeCAD document is available.")
|
|
|
|
|
@ -881,6 +907,7 @@ def route_between_terminals(
|
|
|
|
|
raise AutoRoutingError("Start and end terminal must be different.")
|
|
|
|
|
|
|
|
|
|
opts = _merged_options(options)
|
|
|
|
|
effective_wire_style_id = str(wire_style_id or opts.get("wire_style_id", "") or "").strip()
|
|
|
|
|
start_uuid = (getattr(start_terminal, "QetTerminalUuid", "") or "").strip()
|
|
|
|
|
end_uuid = (getattr(end_terminal, "QetTerminalUuid", "") or "").strip()
|
|
|
|
|
project_uuid = _project_uuid(doc, start_terminal, end_terminal)
|
|
|
|
|
@ -937,7 +964,7 @@ def route_between_terminals(
|
|
|
|
|
wire_mark=wire_mark,
|
|
|
|
|
wire_mark_is_manual=wire_mark_is_manual,
|
|
|
|
|
)
|
|
|
|
|
_set_auto_metadata(wire, route_data, collisions)
|
|
|
|
|
_set_auto_metadata(wire, route_data, collisions, wire_style_id=effective_wire_style_id)
|
|
|
|
|
|
|
|
|
|
routed_group = WiringObjects.ensure_routed_group(doc, project_uuid)
|
|
|
|
|
if wire not in getattr(routed_group, "Group", []):
|
|
|
|
|
@ -1094,6 +1121,7 @@ def route_all_from_payload(doc, payload, options=None):
|
|
|
|
|
group_uuid=_wire_item_value(item, "group_uuid"),
|
|
|
|
|
wire_mark=_wire_item_value(item, "wire_mark"),
|
|
|
|
|
wire_mark_is_manual=bool(item.get("wire_mark_is_manual", False)),
|
|
|
|
|
wire_style_id=_wire_item_value(item, "wire_style_id"),
|
|
|
|
|
)
|
|
|
|
|
except Exception as exc:
|
|
|
|
|
report["errors"].append(str(exc))
|
|
|
|
|
@ -1110,6 +1138,7 @@ def route_all_from_payload(doc, payload, options=None):
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
report["missing_endpoint_uuids"] = sorted(missing_endpoint_uuids)
|
|
|
|
|
_write_auto_route_batch_diagnostic(doc, report)
|
|
|
|
|
return report
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -1126,6 +1155,9 @@ def format_route_all_report(report):
|
|
|
|
|
prepared_layout.get("surface_carriers", 0),
|
|
|
|
|
prepared_layout.get("terminal_access_carriers", 0),
|
|
|
|
|
)
|
|
|
|
|
errors = report.get("errors", []) or []
|
|
|
|
|
if errors:
|
|
|
|
|
message += "\n首个错误:{0}".format(str(errors[0]))
|
|
|
|
|
auto_bound = report.get("auto_bound_terminals", 0)
|
|
|
|
|
auto_created = report.get("auto_created_terminals", 0)
|
|
|
|
|
if auto_bound or auto_created:
|
|
|
|
|
@ -1143,15 +1175,62 @@ def format_route_all_report(report):
|
|
|
|
|
)
|
|
|
|
|
if report.get("local_terminals", 0) > 0:
|
|
|
|
|
message += " 请先从 QET 重新导入/更新工程端子,使端子 UUID 不再是 local:...。"
|
|
|
|
|
sample = (report.get("missing_endpoint_samples") or [None])[0]
|
|
|
|
|
if sample:
|
|
|
|
|
message += "\n缺失示例:{0} -> {1}".format(
|
|
|
|
|
sample.get("start_terminal_uuid", ""),
|
|
|
|
|
sample.get("end_terminal_uuid", ""),
|
|
|
|
|
)
|
|
|
|
|
sample = (report.get("missing_endpoint_samples") or [None])[0]
|
|
|
|
|
if sample:
|
|
|
|
|
message += "\n缺失示例:{0} -> {1}".format(
|
|
|
|
|
sample.get("start_terminal_uuid", ""),
|
|
|
|
|
sample.get("end_terminal_uuid", ""),
|
|
|
|
|
)
|
|
|
|
|
return message
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _clear_auto_route_batch_diagnostics(doc):
|
|
|
|
|
group = WiringObjects.ensure_diagnostic_group(doc, _project_uuid(doc))
|
|
|
|
|
removed = 0
|
|
|
|
|
for obj in list(getattr(group, "Group", []) or []):
|
|
|
|
|
if (getattr(obj, "QetDiagnosticKind", "") or "").strip() != "AutoRouteBatch":
|
|
|
|
|
continue
|
|
|
|
|
try:
|
|
|
|
|
group.removeObject(obj)
|
|
|
|
|
except Exception:
|
|
|
|
|
try:
|
|
|
|
|
group.Group = [
|
|
|
|
|
candidate
|
|
|
|
|
for candidate in list(getattr(group, "Group", []) or [])
|
|
|
|
|
if candidate is not obj
|
|
|
|
|
]
|
|
|
|
|
except Exception:
|
|
|
|
|
pass
|
|
|
|
|
try:
|
|
|
|
|
if doc.getObject(getattr(obj, "Name", "")) is not None:
|
|
|
|
|
doc.removeObject(obj.Name)
|
|
|
|
|
removed += 1
|
|
|
|
|
except Exception:
|
|
|
|
|
pass
|
|
|
|
|
return removed
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _write_auto_route_batch_diagnostic(doc, report):
|
|
|
|
|
if doc is None or not isinstance(report, dict):
|
|
|
|
|
return None
|
|
|
|
|
if not report.get("errors") and not report.get("missing_endpoint_uuids") and report.get("collision_warnings", 0) <= 0:
|
|
|
|
|
return None
|
|
|
|
|
project_uuid = _project_uuid(doc)
|
|
|
|
|
group = WiringObjects.ensure_diagnostic_group(doc, project_uuid)
|
|
|
|
|
_clear_auto_route_batch_diagnostics(doc)
|
|
|
|
|
diagnostic = doc.addObject("App::DocumentObjectGroup", _unique_name(doc, "QETAutoRouteDiagnostic"))
|
|
|
|
|
diagnostic.Label = "QET Auto Route Diagnostic"
|
|
|
|
|
_set_string(diagnostic, "QetDiagnosticKind", "AutoRouteBatch", "QET diagnostic kind")
|
|
|
|
|
_set_string(
|
|
|
|
|
diagnostic,
|
|
|
|
|
"QetDiagnosticJson",
|
|
|
|
|
json.dumps(report, ensure_ascii=False),
|
|
|
|
|
"QET auto-routing batch diagnostic payload",
|
|
|
|
|
)
|
|
|
|
|
group.addObject(diagnostic)
|
|
|
|
|
return diagnostic
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _iter_wire_tasks(doc):
|
|
|
|
|
try:
|
|
|
|
|
task_group = doc.getObject("QETWiring_01_Tasks")
|
|
|
|
|
@ -1175,6 +1254,7 @@ def _wire_tasks_payload(doc):
|
|
|
|
|
"wire_label": (getattr(task, "QetWireLabel", "") or "").strip(),
|
|
|
|
|
"wire_mark": (getattr(task, "QetWireMark", "") or "").strip(),
|
|
|
|
|
"wire_mark_is_manual": bool(getattr(task, "QetWireMarkIsManual", False)),
|
|
|
|
|
"wire_style_id": (getattr(task, "QetWireStyleId", "") or "").strip(),
|
|
|
|
|
"net_uuid": (getattr(task, "QetNetUuid", "") or "").strip(),
|
|
|
|
|
"group_uuid": (getattr(task, "QetGroupUuid", "") or "").strip(),
|
|
|
|
|
"start_element_uuid": (getattr(task, "QetStartElementUuid", "") or "").strip(),
|
|
|
|
|
|