import ezdxf from ezdxf.math import Vec3 import json import sys import os import math def get_bounding_box_from_block(block_def): """ Calculates the bounding box of all geometric entities within a block definition and returns its four corner vertices in local coordinates. This version manually handles LINE entities. """ min_x, min_y = math.inf, math.inf max_x, max_y = -math.inf, -math.inf has_geometry = False for entity in block_def: if entity.dxftype() == 'LINE': start, end = entity.dxf.start, entity.dxf.end min_x = min(min_x, start.x, end.x) min_y = min(min_y, start.y, end.y) max_x = max(max_x, start.x, end.x) max_y = max(max_y, start.y, end.y) has_geometry = True elif entity.dxftype() == 'LWPOLYLINE': try: # LWPOLYLINE points are 2D tuples in OCS with entity.points() as points: point_list = list(points) if not point_list: continue x_coords = [p[0] for p in point_list] y_coords = [p[1] for p in point_list] min_x = min(min_x, min(x_coords)) min_y = min(min_y, min(y_coords)) max_x = max(max_x, max(x_coords)) max_y = max(max_y, max(y_coords)) has_geometry = True except (AttributeError, TypeError): continue if not has_geometry: return None # The four corners of the bounding box return [ Vec3(min_x, min_y, 0), Vec3(max_x, min_y, 0), Vec3(max_x, max_y, 0), Vec3(min_x, max_y, 0), ] def main(dxf_file_path: str): """ Finds specified block references in a layout, extracts their corner coordinates based on bounding box, and prints the results as JSON. """ # --- Configuration --- TARGET_LAYOUT = "布局1" TARGET_BLOCK_NAMES = [ "A$C2EB80DB8", "A$C1CC9093B", "A$C6D564680", "新块", "新块1", ] if not os.path.exists(dxf_file_path): print(f"错误: 文件不存在 '{dxf_file_path}'") return try: doc = ezdxf.readfile(dxf_file_path) except IOError: print(f"错误: 无法打开文件 '{dxf_file_path}'") return except ezdxf.DXFStructureError as e: print(f"错误: 无效或损坏的 DXF 文件. {e}") return try: layout = doc.layouts.get(TARGET_LAYOUT) except KeyError: print(f"错误: 找不到布局 '{TARGET_LAYOUT}'。") return found_blocks = {} query_string = 'INSERT' for block_ref in layout.query(query_string): block_name = block_ref.dxf.name if block_name not in TARGET_BLOCK_NAMES: continue block_def = doc.blocks.get(block_name) if not block_def: print(f"警告: 找不到图块 '{block_name}' 的定义。") continue local_vertices = get_bounding_box_from_block(block_def) if not local_vertices: print(f"警告: 在图块 '{block_name}' 中找不到可计算边界的几何体 (LINE, LWPOLYLINE)。") continue # Manually apply the transformation transformed_vertices = [] for v in local_vertices: # Apply scaling scaled_v = Vec3(v.x * block_ref.dxf.xscale, v.y * block_ref.dxf.yscale, v.z * block_ref.dxf.zscale) # Apply rotation and then translation world_vertex = block_ref.dxf.insert + scaled_v.rotate_deg(block_ref.dxf.rotation) transformed_vertices.append(world_vertex) world_vertices = transformed_vertices if block_name not in found_blocks: found_blocks[block_name] = [] found_blocks[block_name].append( { "插入点": f"({block_ref.dxf.insert.x:.3f}, {block_ref.dxf.insert.y:.3f})", "旋转角度": f"{block_ref.dxf.rotation:.3f}", "比例": f"({block_ref.dxf.xscale:.3f}, {block_ref.dxf.yscale:.3f})", "世界坐标": [f"({v.x:.3f}, {v.y:.3f})" for v in world_vertices], } ) if not found_blocks: print(f"在布局 '{TARGET_LAYOUT}' 中没有找到任何目标图块。") else: print( f"在布局 '{TARGET_LAYOUT}' 中找到了 {sum(len(v) for v in found_blocks.values())} 个目标图块的实例。" ) print("--- 结果 ---") print(json.dumps(found_blocks, indent=4, ensure_ascii=False)) if __name__ == "__main__": if len(sys.argv) > 1: file_path = sys.argv[1] main(file_path) else: default_path = r"C:\Users\83500\久翌\CAD编辑同步excel\测试文件区\04_Test_Files\塔器.dxf" print(f"未提供文件路径参数。将使用默认路径: {default_path}") main(default_path)