126 lines
3.3 KiB
Python
126 lines
3.3 KiB
Python
"""Annotations extracted from technical drawings."""
|
|
|
|
from dataclasses import dataclass
|
|
from enum import Enum
|
|
|
|
|
|
class DimensionDirection(Enum):
|
|
"""Direction of a dimension annotation."""
|
|
|
|
HORIZONTAL = "horizontal"
|
|
VERTICAL = "vertical"
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class DimensionAnnotation:
|
|
"""A dimension measurement from the drawing."""
|
|
|
|
value_mm: float
|
|
direction: DimensionDirection
|
|
dim_line_start: tuple[float, float]
|
|
dim_line_end: tuple[float, float]
|
|
text_bbox: tuple[float, float, float, float]
|
|
|
|
def to_dict(self) -> dict:
|
|
"""Convert to JSON-serializable dict."""
|
|
return {
|
|
"value_mm": self.value_mm,
|
|
"direction": self.direction.value,
|
|
"dim_line_start": list(self.dim_line_start),
|
|
"dim_line_end": list(self.dim_line_end),
|
|
"text_bbox": list(self.text_bbox),
|
|
}
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class MaterialAnnotation:
|
|
"""Material specification for a part."""
|
|
|
|
text: str
|
|
thickness_mm: float | None
|
|
material_type: str # "MDF", "plywood", "HDF", etc.
|
|
finish: str # "white melamine", etc.
|
|
|
|
def to_dict(self) -> dict:
|
|
"""Convert to JSON-serializable dict."""
|
|
return {
|
|
"text": self.text,
|
|
"thickness_mm": self.thickness_mm,
|
|
"material_type": self.material_type,
|
|
"finish": self.finish,
|
|
}
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class EdgebandAnnotation:
|
|
"""Edgebanding specification for an edge."""
|
|
|
|
edge_id: str # "top", "bottom", "left", "right"
|
|
material: str
|
|
thickness_mm: float
|
|
|
|
def to_dict(self) -> dict:
|
|
"""Convert to JSON-serializable dict."""
|
|
return {
|
|
"edge_id": self.edge_id,
|
|
"material": self.material,
|
|
"thickness_mm": self.thickness_mm,
|
|
}
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class HardwareAnnotation:
|
|
"""Hardware specification (hinges, handles, etc.)."""
|
|
|
|
type: str
|
|
model: str
|
|
position_description: str
|
|
|
|
def to_dict(self) -> dict:
|
|
"""Convert to JSON-serializable dict."""
|
|
return {
|
|
"type": self.type,
|
|
"model": self.model,
|
|
"position_description": self.position_description,
|
|
}
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class DrillingAnnotation:
|
|
"""Drilling hole specification."""
|
|
|
|
x_mm: float
|
|
y_mm: float
|
|
diameter_mm: float
|
|
depth_mm: float
|
|
|
|
def to_dict(self) -> dict:
|
|
"""Convert to JSON-serializable dict."""
|
|
return {
|
|
"x_mm": self.x_mm,
|
|
"y_mm": self.y_mm,
|
|
"diameter_mm": self.diameter_mm,
|
|
"depth_mm": self.depth_mm,
|
|
}
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class PartMetadata:
|
|
"""All metadata annotations for a part."""
|
|
|
|
materials: tuple[MaterialAnnotation, ...]
|
|
edgebanding: tuple[EdgebandAnnotation, ...]
|
|
hardware: tuple[HardwareAnnotation, ...]
|
|
drilling: tuple[DrillingAnnotation, ...]
|
|
raw_annotations: tuple[str, ...]
|
|
|
|
def to_dict(self) -> dict:
|
|
"""Convert to JSON-serializable dict."""
|
|
return {
|
|
"materials": [m.to_dict() for m in self.materials],
|
|
"edgebanding": [e.to_dict() for e in self.edgebanding],
|
|
"hardware": [h.to_dict() for h in self.hardware],
|
|
"drilling": [d.to_dict() for d in self.drilling],
|
|
"raw_annotations": list(self.raw_annotations),
|
|
}
|