"""阶段 2:逐图框取证(确定性、串行)。 对每个图框:缩放到该框 → 取结构化数据(实体/文字/标注/块/多段线)→ 截取视口。 结构化数据是权威依据,截图仅作视觉上下文。 """ import time from .. import config from ..mcp_client import result_images, result_json def bbox_to_window(bbox): """[minx,miny,maxx,maxy] -> window 对象。""" return { "min_x": float(bbox[0]), "min_y": float(bbox[1]), "max_x": float(bbox[2]), "max_y": float(bbox[3]), } def collect_frame(ctx, index, frame): """采集单个图框的证据;bbox 无效时返回 None。""" bbox = frame.get("bbox") if not bbox or len(bbox) != 4: return None win = bbox_to_window(bbox) limit = ctx.frame_limit # a. 缩放到图框(给 CAD 留渲染时间) ctx.tools.call("zoom_to_window", dict(win, margin=0.02)) time.sleep(config.RENDER_WAIT) # b. 结构化数据(权威) entities = result_json(ctx.tools.call("query_entities", {"window": win, "limit": limit}), {}) texts = result_json(ctx.tools.call("get_text_content", {"window": win, "limit": limit}), {}) dimensions = result_json(ctx.tools.call("get_dimensions", {"window": win, "limit": limit}), {}) blocks = result_json( ctx.tools.call("get_block_references", {"window": win, "limit": limit}), {} ) polylines = result_json( ctx.tools.call("get_polylines_info", {"window": win, "limit": limit}), {} ) # c. 视口截图(视觉上下文) shot = ctx.tools.call("get_viewport_screenshot", {}) images = result_images(shot) image_b64, image_mime = images[0] if images else (None, None) return { "index": index, "frame": frame, "window": win, "entities": entities, "texts": texts, "dimensions": dimensions, "blocks": blocks, "polylines": polylines, "image_b64": image_b64, "image_mime": image_mime, }