dxfedit/extract_color_elements.py
puzzlesion c40b3482df 添加Java版本解决方案和问题分析文档
- 创建problem目录存储问题分析和解决方案
- 添加Aspose.CAD Python问题详细报告
- 提供Java版本测试方案和完整代码
- 创建Java版本安装运行指南
- 更新README文档包含Java版本推荐
- 添加颜色元素提取相关脚本
- 提供完整的Maven项目配置
2025-09-05 11:12:34 +08:00

465 lines
18 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
提取特定颜色元素的脚本
功能从DWG文件中提取颜色为(0, 255, 255)的所有元素
作者AI Assistant
日期2024
"""
import os
import sys
import csv
import json
from pathlib import Path
import math
def print_separator(title=""):
"""打印分隔线"""
print("=" * 60)
if title:
print(f" {title} ")
print("=" * 60)
def extract_color_elements(dwg_path, target_color=(0, 255, 255)):
"""提取特定颜色的元素"""
print_separator("提取特定颜色元素")
if not os.path.exists(dwg_path):
print(f"文件不存在: {dwg_path}")
return None
try:
import aspose.cad as cad
from aspose.cad.fileformats.cad import CadImage
from aspose.cad.fileformats.cad.cadobjects import CadLine, CadPolyline, CadCircle, CadArc
from aspose.cad import Color
# 获取文件基本信息
file_size = os.path.getsize(dwg_path)
print(f"文件路径: {dwg_path}")
print(f"文件大小: {file_size:,} 字节 ({file_size/1024/1024:.2f} MB)")
print(f"目标颜色: RGB({target_color[0]}, {target_color[1]}, {target_color[2]})")
# 创建目标颜色对象
target_color_obj = Color.from_argb(255, target_color[0], target_color[1], target_color[2])
print(f"目标颜色对象: {target_color_obj}")
# 加载DWG文件
print("正在加载DWG文件...")
with cad.Image.load(dwg_path) as image:
print(f"成功加载DWG文件")
print(f"图像类型: {type(image).__name__}")
print(f"图像尺寸: {image.width} x {image.height}")
elements_data = []
total_elements = 0
# 方法1尝试使用CadImage.load
print("\n方法1使用CadImage.load")
try:
cad_image = CadImage.load(dwg_path)
print(f"成功使用CadImage.load类型: {type(cad_image).__name__}")
# 检查所有属性
attrs = [attr for attr in dir(cad_image) if not attr.startswith('_')]
print(f"可用属性数量: {len(attrs)}")
# 查找可能包含实体的属性
entity_attrs = [attr for attr in attrs if 'entit' in attr.lower() or 'object' in attr.lower() or 'item' in attr.lower()]
print(f"可能的实体属性: {entity_attrs}")
# 尝试访问这些属性
for attr in entity_attrs:
try:
value = getattr(cad_image, attr)
print(f" {attr}: {type(value).__name__}")
if hasattr(value, '__len__'):
print(f" 长度: {len(value)}")
# 如果长度大于0尝试访问前几个元素
if len(value) > 0:
for i in range(min(5, len(value))):
item = value[i]
print(f" [{i}]: {type(item).__name__}")
# 检查颜色
element_info = check_element_color(item, total_elements, target_color_obj)
if element_info:
elements_data.append(element_info)
total_elements += 1
except Exception as e:
print(f" {attr}: 访问失败 - {e}")
except Exception as e:
print(f"使用CadImage.load失败: {e}")
# 方法2尝试遍历所有可能的属性
print("\n方法2遍历所有可能的属性")
try:
all_attrs = [attr for attr in dir(cad_image) if not attr.startswith('_')]
print(f"cad_image共有 {len(all_attrs)} 个属性")
# 查找可能包含实体的属性
entity_attrs = [attr for attr in all_attrs if 'entit' in attr.lower() or 'object' in attr.lower() or 'item' in attr.lower()]
print(f"可能的实体属性: {entity_attrs}")
for attr_name in entity_attrs:
try:
attr_value = getattr(cad_image, attr_name)
if attr_value and hasattr(attr_value, '__len__') and len(attr_value) > 0:
print(f" 找到属性 {attr_name}: {type(attr_value).__name__} (长度: {len(attr_value)})")
# 尝试遍历这个属性
for i, item in enumerate(attr_value):
item_type = type(item).__name__
print(f" {attr_name}[{i}]: {item_type}")
# 检查颜色
element_info = check_element_color(item, total_elements, target_color_obj)
if element_info:
elements_data.append(element_info)
total_elements += 1
if i >= 9: # 只显示前10个
break
except Exception as e:
print(f" 访问属性 {attr_name} 失败: {e}")
except Exception as e:
print(f"遍历属性失败: {e}")
# 方法3尝试使用不同的API
print("\n方法3尝试使用不同的API")
try:
# 尝试使用Image对象的其他方法
image_methods = [attr for attr in dir(image) if not attr.startswith('_') and callable(getattr(image, attr))]
print(f"Image对象方法: {image_methods}")
# 尝试使用get_strings方法
if 'get_strings' in image_methods:
try:
strings = image.get_strings()
print(f"get_strings(): {type(strings).__name__}")
if hasattr(strings, '__len__'):
print(f" 字符串数量: {len(strings)}")
for i, s in enumerate(strings[:5]):
print(f" [{i}]: {s}")
except Exception as e:
print(f"get_strings()失败: {e}")
except Exception as e:
print(f"尝试不同API失败: {e}")
print(f"\n成功提取 {total_elements} 个目标颜色元素")
return elements_data
except Exception as e:
print(f"提取元素失败: {e}")
import traceback
traceback.print_exc()
return None
def check_element_color(element, element_index, target_color):
"""检查元素颜色是否匹配目标颜色"""
try:
element_type = type(element).__name__
# 尝试获取颜色信息
color_info = None
color_attrs = ['color', 'color_value', 'color_name', 'color_id']
for attr in color_attrs:
if hasattr(element, attr):
try:
color_value = getattr(element, attr)
print(f" 找到颜色属性 {attr}: {color_value} (类型: {type(color_value).__name__})")
# 检查颜色是否匹配
if is_color_match(color_value, target_color):
print(f" ✓ 颜色匹配!")
color_info = str(color_value)
break
except Exception as e:
print(f" 访问颜色属性 {attr} 失败: {e}")
if color_info:
# 提取元素信息
element_info = {
'element_index': element_index,
'element_type': element_type,
'color': color_info,
'layer_name': 'Unknown',
'visible': True,
}
# 尝试获取其他属性
try:
if hasattr(element, 'layer_name'):
element_info['layer_name'] = str(getattr(element, 'layer_name', 'Unknown'))
if hasattr(element, 'visible'):
element_info['visible'] = bool(getattr(element, 'visible', True))
if hasattr(element, 'thickness'):
element_info['thickness'] = float(getattr(element, 'thickness', 0))
if hasattr(element, 'line_type_name'):
element_info['line_type'] = str(getattr(element, 'line_type_name', 'Unknown'))
# 尝试获取坐标信息
if hasattr(element, 'first_point') and hasattr(element, 'second_point'):
first_point = element.first_point
second_point = element.second_point
element_info['start_x'] = float(getattr(first_point, 'x', 0))
element_info['start_y'] = float(getattr(first_point, 'y', 0))
element_info['start_z'] = float(getattr(first_point, 'z', 0))
element_info['end_x'] = float(getattr(second_point, 'x', 0))
element_info['end_y'] = float(getattr(second_point, 'y', 0))
element_info['end_z'] = float(getattr(second_point, 'z', 0))
# 计算长度
dx = element_info['end_x'] - element_info['start_x']
dy = element_info['end_y'] - element_info['start_y']
dz = element_info['end_z'] - element_info['start_z']
length = math.sqrt(dx*dx + dy*dy + dz*dz)
element_info['length'] = round(length, 4)
elif hasattr(element, 'center') and hasattr(element, 'radius'):
center = element.center
element_info['center_x'] = float(getattr(center, 'x', 0))
element_info['center_y'] = float(getattr(center, 'y', 0))
element_info['center_z'] = float(getattr(center, 'z', 0))
element_info['radius'] = float(getattr(element, 'radius', 0))
except Exception as e:
print(f" 获取其他属性失败: {e}")
return element_info
return None
except Exception as e:
print(f"检查元素颜色失败: {e}")
return None
def is_color_match(color_value, target_color):
"""检查颜色是否匹配"""
try:
# 如果是Color对象
if hasattr(color_value, 'r') and hasattr(color_value, 'g') and hasattr(color_value, 'b'):
r = getattr(color_value, 'r', 0)
g = getattr(color_value, 'g', 0)
b = getattr(color_value, 'b', 0)
return (r, g, b) == target_color
# 如果是字符串
if isinstance(color_value, str):
color_str = str(color_value).lower()
if 'cyan' in color_str or 'aqua' in color_str:
return True
# 尝试解析RGB值
if 'rgb' in color_str or ',' in color_str:
# 简单的RGB解析
if '255' in color_str and '0' in color_str:
return True
# 如果是数字
if isinstance(color_value, (int, float)):
# AutoCAD颜色索引
if color_value == 4: # 青色
return True
return False
except Exception as e:
print(f"颜色匹配检查失败: {e}")
return False
def save_elements_to_csv(elements_data, output_path):
"""将元素数据保存为CSV文件"""
if not elements_data:
print("没有元素数据可保存")
return False
try:
with open(output_path, 'w', newline='', encoding='utf-8-sig') as csvfile:
# 获取所有可能的字段名
all_fields = set()
for element in elements_data:
all_fields.update(element.keys())
fieldnames = sorted(list(all_fields))
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
for element in elements_data:
# 确保所有字段都有值
row = {}
for field in fieldnames:
row[field] = element.get(field, '')
writer.writerow(row)
print(f"元素数据已保存到: {output_path}")
return True
except Exception as e:
print(f"保存CSV文件失败: {e}")
return False
def save_elements_to_json(elements_data, output_path):
"""将元素数据保存为JSON文件"""
if not elements_data:
print("没有元素数据可保存")
return False
try:
with open(output_path, 'w', encoding='utf-8') as jsonfile:
json.dump(elements_data, jsonfile, ensure_ascii=False, indent=2)
print(f"元素数据已保存到: {output_path}")
return True
except Exception as e:
print(f"保存JSON文件失败: {e}")
return False
def create_summary_report(elements_data, output_path, target_color):
"""创建元素统计报告"""
if not elements_data:
return False
try:
with open(output_path, 'w', encoding='utf-8') as report:
report.write("DWG文件特定颜色元素提取报告\n")
report.write("=" * 50 + "\n\n")
report.write(f"目标颜色: RGB({target_color[0]}, {target_color[1]}, {target_color[2]})\n")
report.write(f"总元素数量: {len(elements_data)}\n\n")
# 按类型统计
type_count = {}
layer_count = {}
for element in elements_data:
# 类型统计
element_type = element.get('element_type', 'Unknown')
type_count[element_type] = type_count.get(element_type, 0) + 1
# 图层统计
layer = element.get('layer_name', 'Unknown')
layer_count[layer] = layer_count.get(layer, 0) + 1
# 写入统计信息
report.write("按类型统计:\n")
for element_type, count in sorted(type_count.items()):
report.write(f" {element_type}: {count}\n")
report.write("\n按图层统计:\n")
for layer, count in sorted(layer_count.items()):
report.write(f" {layer}: {count}\n")
# 长度统计
lengths = [element.get('length', 0) for element in elements_data if 'length' in element and element['length'] > 0]
if lengths:
report.write(f"\n长度统计:\n")
report.write(f" 最短元素: {min(lengths):.4f}\n")
report.write(f" 最长元素: {max(lengths):.4f}\n")
report.write(f" 平均长度: {sum(lengths)/len(lengths):.4f}\n")
# 详细数据
report.write(f"\n详细元素数据:\n")
for i, element in enumerate(elements_data):
report.write(f"\n元素 {i+1}:\n")
for key, value in element.items():
report.write(f" {key}: {value}\n")
print(f"统计报告已保存到: {output_path}")
return True
except Exception as e:
print(f"创建统计报告失败: {e}")
return False
def main():
"""主函数"""
print_separator("DWG文件特定颜色元素提取工具")
print("提取颜色为(0, 255, 255)的所有元素")
print()
# 目标颜色 (青色)
target_color = (0, 255, 255)
# 查找DWG文件
dwg_files = list(Path('.').glob('*.dwg'))
if not dwg_files:
print("当前目录下未找到DWG文件")
print("请确保DWG文件在当前目录中")
return
print(f"找到 {len(dwg_files)} 个DWG文件:")
for i, dwg_file in enumerate(dwg_files, 1):
print(f" {i}. {dwg_file}")
# 优先使用测试图纸文件
test_file = None
for dwg_file in dwg_files:
if '测试图纸文件' in str(dwg_file):
test_file = str(dwg_file)
break
if not test_file:
test_file = str(dwg_files[0])
print(f"\n使用文件进行提取: {test_file}")
# 提取特定颜色元素
elements_data = extract_color_elements(test_file, target_color)
if elements_data is None:
print("元素提取失败")
return
# 保存数据
base_name = test_file.replace('.dwg', '')
# 保存为CSV
csv_path = f"{base_name}_color_elements.csv"
csv_success = save_elements_to_csv(elements_data, csv_path)
# 保存为JSON
json_path = f"{base_name}_color_elements.json"
json_success = save_elements_to_json(elements_data, json_path)
# 创建统计报告
report_path = f"{base_name}_color_elements_report.txt"
report_success = create_summary_report(elements_data, report_path, target_color)
# 总结
print_separator("提取总结")
print(f"提取的元素数量: {len(elements_data)}")
print(f"CSV文件保存: {'成功' if csv_success else '失败'}")
print(f"JSON文件保存: {'成功' if json_success else '失败'}")
print(f"统计报告生成: {'成功' if report_success else '失败'}")
if csv_success or json_success:
print(f"\n元素提取完成!文件已保存到当前目录")
print(f" - CSV文件: {csv_path}")
print(f" - JSON文件: {json_path}")
print(f" - 统计报告: {report_path}")
else:
print("\n所有保存操作都失败了")
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print("\n\n用户中断了程序执行")
except Exception as e:
print(f"\n\n程序执行出错: {e}")
import traceback
traceback.print_exc()