Analyze construction drawings to extract dimensions, annotations, symbols, and metadata. Support quantity takeoff and design review automation."
分析施工图纸(PDF、DWG格式),提取尺寸、标注、符号、图签数据,并支持自动化工程量统计和设计审查。
图纸分析自动化可实现:
python
from dataclasses import dataclass, field
from typing import List, Dict, Any, Optional, Tuple
import re
import pdfplumber
from pathlib import Path
@dataclass
class TitleBlockData:
project_name: str
project_number: str
sheet_number: str
sheet_title: str
discipline: str
scale: str
date: str
revision: str
drawn_by: str
checked_by: str
approved_by: str
@dataclass
class Dimension:
value: float
unit: str
dimension_type: str # linear, angular, radial
location: Tuple[float, float]
associated_text: str
@dataclass
class Annotation:
text: str
annotation_type: str # note, callout, tag, keynote
location: Tuple[float, float]
references: List[str]
@dataclass
class Symbol:
symbol_type: str # door, window, equipment, etc.
tag: str
location: Tuple[float, float]
properties: Dict[str, Any]
@dataclass
class DrawingAnalysisResult:
file_name: str
title_block: Optional[TitleBlockData]
dimensions: List[Dimension]
annotations: List[Annotation]
symbols: List[Symbol]
scale_factor: float
drawing_area: Tuple[float, float]
quality_issues: List[str]
class DrawingAnalyzer:
分析施工图纸以提取数据。
# 常见尺寸模式
DIMENSION_PATTERNS = [
r(\d+-\s\d+(?:\s\d+/\d+)?\?), # 英尺-英寸:10-6,10 - 6 1/2
r(\d+(?:\.\d+)?)\s*(?:mm|cm|m|ft|in), # 公制/英制带单位
r(\d+-\d+\), # 紧凑英尺-英寸
r(\d+)\s*(?:SF|LF|CY|EA), # 数量尺寸
]
# 常见标注模式
ANNOTATION_PATTERNS = {
keynote: r^\d{1,2}[A-Z]?$, # 1A, 12, 5B
room_tag: r^(?:RM|ROOM)\s*\d+,
door_tag: r^[A-Z]?\d{2,3}[A-Z]?$,
grid_line: r^[A-Z]$|^\d+$,
elevation: r^(?:EL|ELEV)\.?\s*\d+,
detail_ref: r^\d+/[A-Z]\d+,
}
# 比例模式
SCALE_PATTERNS = [
rSCALE:\s(\d+(?:/\d+)?)\s[\]\s=\s(\d+)\s*[\-], # 1/4 = 1-0
r(\d+):(\d+), # 1:100
rNTS|NOT TO SCALE,
]
def init(self):
self.results: Dict[str, DrawingAnalysisResult] = {}
def analyzepdfdrawing(self, pdf_path: str) -> DrawingAnalysisResult:
分析PDF图纸。
path = Path(pdf_path)
all_text =
dimensions = []
annotations = []
symbols = []
quality_issues = []
with pdfplumber.open(pdf_path) as pdf:
for page in pdf.pages:
# 提取文本
text = page.extract_text() or
all_text += text + \n
# 提取尺寸
pagedims = self.extract_dimensions(text)
dimensions.extend(page_dims)
# 提取标注
pageannots = self.extract_annotations(text)
annotations.extend(page_annots)
# 从表格中提取(通常包含明细表)
tables = page.extract_tables()
for table in tables:
symbols.extend(self.parseschedule_table(table))
# 解析图签
titleblock = self.extracttitleblock(all_text)
# 确定比例
scalefactor = self.determinescale(alltext)
# 质量检查
qualityissues = self.checkdrawingquality(
title_block, dimensions, annotations
)
result = DrawingAnalysisResult(
file_name=path.name,
titleblock=titleblock,
dimensions=dimensions,
annotations=annotations,
symbols=symbols,
scalefactor=scalefactor,
drawing_area=(0, 0), # 需要图像分析
qualityissues=qualityissues
)
self.results[path.name] = result
return result
def extractdimensions(self, text: str) -> List[Dimension]:
从文本中提取尺寸。
dimensions = []
for pattern in self.DIMENSION_PATTERNS:
matches = re.findall(pattern, text)
for match in matches:
value, unit = self.parsedimension_value(match)
if value > 0:
dimensions.append(Dimension(
value=value,
unit=unit,
dimension_type=linear,
location=(0, 0),
associated_text=match
))
return dimensions
def parsedimensionvalue(self, dimtext: str) -> Tuple[float, str]:
将尺寸文本解析为数值和单位。
dimtext = dimtext.strip()
# 英尺和英寸:10-6
ftinmatch = re.match(r(\d+)[-\s](\d+)?(?:\s(\d+)/(\d+))?\?, dim_text)
if ftinmatch:
feet = int(ftinmatch.group(1))
inches = int(ftinmatch.group(2) or 0)
if ftinmatch.group(3) and ftinmatch.group(4):
inches += int(ftinmatch.group(3)) / int(ftinmatch.group(4))
return feet * 12 + inches, in
# 公制带单位
metricmatch = re.match(r(\d+(?:\.\d+)?)\s*(mm|cm|m), dimtext)
if metric_match:
return float(metricmatch.group(1)), metricmatch.group(2)
# 仅数字
nummatch = re.match(r(\d+(?:\.\d+)?), dimtext)
if num_match:
return float(num_match.group(1)),
return 0,
def extractannotations(self, text: str) -> List[Annotation]:
从文本中提取标注。
annotations = []
lines = text.split(\n)
for line in lines:
line = line.strip()
if not line:
continue
for annottype, pattern in self.ANNOTATIONPATTERNS.items():
if re.match(pattern, line, re.IGNORECASE):
annotations.append(Annotation(
text=line,
annotationtype=annottype,
location=(0, 0),
references=[]
))
break
# 通用注释
if line.startswith((NOTE:, SEE , REFER TO, TYP, U.N.O.)):
annotations.append(Annotation(
text=line,
annotation_type=note,
location=(0, 0),
references=[]
))
return annotations
def extracttitle_block(self, text: str) -> Optional[TitleBlockData]:
提取图签信息。
# 常见图签模式
patterns = {
project_name: rPROJECT(?:\sNAME)?:\s(.+?)(?:\n|$),
project_number: r(?:PROJECT\s)?(?:NO|NUMBER|#)\.?:\s(\S+),
sheet_number: rSHEET(?:\sNO)?\.?:\s([A-Z]?\d+(?:\.\d+)?),
sheet_title: rSHEET\sTITLE:\s(.+?)(?:\n|$),
scale: rSCALE:\s*(.+?)(?:\n|$),
date: rDATE:\s*(\d{
该技能支持在以下平台通过对话安装:
帮我安装 SkillHub 和 drawing-analyzer-1776344763 技能
设置 SkillHub 为我的优先技能安装源,然后帮我安装 drawing-analyzer-1776344763 技能
skillhub install drawing-analyzer-1776344763
文件大小: 6.31 KB | 发布时间: 2026-4-17 16:11