Files
stepanalyser/.venv/lib/python3.12/site-packages/ezdxf/acis/dbg.py
Christian Anetzberger a197de9456 initial
2026-01-22 20:23:51 +01:00

194 lines
6.4 KiB
Python

# Copyright (c) 2022-2024, Manfred Moitzi
# License: MIT License
from __future__ import annotations
from typing import Iterator, Callable, Any
from .entities import (
AcisEntity,
NONE_REF,
Face,
Coedge,
Loop,
Vertex,
)
from . import sab
class AcisDebugger:
def __init__(self, root: AcisEntity = NONE_REF, start_id: int = 1):
self._next_id = start_id - 1
self._root: AcisEntity = root
self.entities: dict[int, AcisEntity] = dict()
if not root.is_none:
self._store_entities(root)
@property
def root(self) -> AcisEntity:
return self._root
def _get_id(self) -> int:
self._next_id += 1
return self._next_id
def _store_entities(self, entity: AcisEntity) -> None:
if not entity.is_none and entity.id == -1:
entity.id = self._get_id()
self.entities[entity.id] = entity
for e in vars(entity).values():
if isinstance(e, AcisEntity) and e.id == -1:
self._store_entities(e)
def set_entities(self, entity: AcisEntity) -> None:
self.entities.clear()
self._root = entity
self._store_entities(entity)
def walk(self, root: AcisEntity = NONE_REF) -> Iterator[AcisEntity]:
def _walk(entity: AcisEntity):
if entity.is_none:
return
yield entity
done.add(entity.id)
for e in vars(entity).values():
if isinstance(e, AcisEntity) and e.id not in done:
yield from _walk(e)
if root.is_none:
root = self._root
done: set[int] = set()
yield from _walk(root)
def filter(
self, func: Callable[[AcisEntity], bool], entity: AcisEntity = NONE_REF
) -> Iterator[Any]:
if entity.is_none:
entity = self._root
yield from filter(func, self.walk(entity))
def filter_type(
self, name: str, entity: AcisEntity = NONE_REF
) -> Iterator[Any]:
if entity.is_none:
entity = self._root
yield from filter(lambda x: x.type == name, self.walk(entity))
@staticmethod
def entity_attributes(entity: AcisEntity, indent: int = 0) -> Iterator[str]:
indent_str = " " * indent
for name, data in vars(entity).items():
if name == "id":
continue
yield f"{indent_str}{name}: {data}"
def face_link_structure(self, face: Face, indent: int = 0) -> Iterator[str]:
indent_str = " " * indent
while not face.is_none:
partner_faces = list(self.partner_faces(face))
error = ""
linked_partner_faces = []
unlinked_partner_faces = []
for pface_id in partner_faces:
pface = self.entities.get(pface_id)
if pface is None:
error += f" face {pface_id} does not exist;"
if isinstance(pface, Face):
reverse_faces = self.partner_faces(pface)
if face.id in reverse_faces:
linked_partner_faces.append(pface_id)
else:
unlinked_partner_faces.append(pface_id)
else:
error += f" entity {pface_id} is not a face;"
if unlinked_partner_faces:
error = f"unlinked partner faces: {unlinked_partner_faces} {error}"
yield f"{indent_str}{str(face)} >> {partner_faces} {error}"
face = face.next_face
@staticmethod
def partner_faces(face: Face) -> Iterator[int]:
coedges: list[Coedge] = []
loop = face.loop
while not loop.is_none:
coedges.extend(co for co in loop.coedges())
loop = loop.next_loop
for coedge in coedges:
for partner_coedge in coedge.partner_coedges():
yield partner_coedge.loop.face.id
@staticmethod
def coedge_structure(face: Face, ident: int = 4) -> list[str]:
lines: list[str] = []
coedges: list[Coedge] = []
loop = face.loop
while not loop.is_none:
coedges.extend(co for co in loop.coedges())
loop = loop.next_loop
for coedge in coedges:
edge1 = coedge.edge
sense1 = coedge.sense
lines.append(f"Coedge={coedge.id} edge={edge1.id} sense={sense1}")
for partner_coedge in coedge.partner_coedges():
edge2 = partner_coedge.edge
sense2 = partner_coedge.sense
lines.append(
f" Partner Coedge={partner_coedge.id} edge={edge2.id} sense={sense2}"
)
ident_str = " " * ident
return [ident_str + line for line in lines]
@staticmethod
def loop_vertices(loop: Loop, indent: int = 0) -> str:
indent_str = " " * indent
return f"{indent_str}{loop} >> {list(AcisDebugger.loop_edges(loop))}"
@staticmethod
def loop_edges(loop: Loop) -> Iterator[list[int]]:
coedge = loop.coedge
first = coedge
while not coedge.is_none:
edge = coedge.edge
sv = edge.start_vertex
ev = edge.end_vertex
if coedge.sense:
yield [ev.id, sv.id]
else:
yield [sv.id, ev.id]
coedge = coedge.next_coedge
if coedge is first:
break
def vertex_to_edge_relation(self) -> Iterator[str]:
for vertex in (
e for e in self.entities.values() if isinstance(e, Vertex)
):
edge = vertex.edge
sv = edge.start_vertex
ev = edge.end_vertex
yield f"{vertex}: parent edge is {edge.id}; {sv.id} => {ev.id}; {edge.curve}"
def is_manifold(self) -> bool:
for coedge in self.filter_type("coedge"):
if len(coedge.partner_coedges()) > 1:
return False
return True
def dump_sab_as_text(data: bytes) -> Iterator[str]:
def entity_data(e):
for tag, value in e:
name = sab.Tags(tag).name
yield f"{name} = {value}"
decoder = sab.Decoder(data)
header = decoder.read_header()
yield from header.dumps()
index = 0
try:
for record in decoder.read_records():
yield f"--------------------- record: {index}"
yield from entity_data(record)
index += 1
except sab.ParsingError as e:
yield str(e)