feat: pdf2cad
This commit is contained in:
125
src/pdf2imos/models/annotations.py
Normal file
125
src/pdf2imos/models/annotations.py
Normal file
@@ -0,0 +1,125 @@
|
||||
"""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),
|
||||
}
|
||||
Reference in New Issue
Block a user