> **本文回答**：实体智能识别（块参照批量查询 + 模式匹配相似实体）。

## 一、两个能力

1. **批量获取所有块参照**：自动列出图中所有 `AcDbBlockReference`。
2. **相似实体识别**：基于用户选的参考实体，找出图中几何形态相似（含缩放/旋转）的实体。

## 二、获取所有块参照

### 优先从 metadata

```js
const meta = await svc.metadata();
if (meta.blockReferences) {
  const blocks = JSON.parse(meta.blockReferences);
  // blocks = [{ objectId, blockName, layerName, position:[x,y], rotate, scale:[x,y,z], bounds }, ...]
}
```

### 没有则走表达式查询

```js
const q = await svc.exprQueryFeature({
  expr: `return gInFeatureType == 'AcDbBlockReference'`,
  fields: "",           // 空表示所有字段
  geom: false,
  useCache: true,
  limit: 1_000_000
});
const blocks = q.result.map(r => ({
  objectId: r.objectid,
  blockName: r.blockname,
  layerName: r.layername,
  bounds: r.bounds,
  position: r.positon,
  ...r
}));
```

### 可视化

```js
const polygons = blocks.map(b => ({
  points: map.toLngLat(vjmap.GeoBounds.fromString(b.bounds).toPointArray()),
  properties: { blockName: b.blockName, layerName: b.layerName, objectId: b.objectId }
}));
const layer = new vjmap.Polygon({
  data: polygons,
  fillColor: ["case", ["to-boolean", ["feature-state", "hover"]], "#0ff", "#f00"],
  fillOpacity: ["case", ["to-boolean", ["feature-state", "hover"]], 0.1, 0.0],
  fillOutlineColor: ["get", "color"],
  isHoverPointer: true,
  isHoverFeatureState: true
});
layer.addTo(map);
layer.hoverPopup((f, popup) => {
  return `<h3>${f.properties.blockName}</h3>objectId: ${f.properties.objectId}`;
}, { anchor: "bottom" });
```

## 三、相似实体识别

### 配置

```js
const patternConfig = {
  name: "",
  sameColor: true,           // 必须同色
  sameLayer: false,          // 是否必须同图层
  global: {
    match: {
      all: { equalMatchProperty: ["color"] },
      AcDbCircle: { scaleMatchProperty: ["radius"] },
      AcDbArc:    { scaleMatchProperty: ["radius"] },
      AcDbLine:   { scaleMatchProperty: ["length"] },
      AcDbText:   { scaleMatchProperty: ["height"] }
    }
  },
  rules: [{
    tolerance: 1e-5,
    translateTolerance: 0.015,
    transform: {
      scale:    { min: 0.5, max: 2.0 },
      rotation: { min: 0,   max: 360 }
    },
    referenceObjectIds: []       // 用户选的参考实体 feature[]
  }]
};
```

### 选择参考实体 + 识别

```js
// 1) 让用户框选或点选（selectFeatures 是自定义助手函数，非包导出——
//    实现见 interaction/draw-action.md「CAD 实体框选/点选」一节）
const sel = await selectFeatures(map, /* isPointSel */ false);
patternConfig.rules[0].referenceObjectIds = sel.features;

// 2) 执行后端识别
const res = await svc.execCommand("objectDetection", {
  mapid:  svc.currentMapParam().mapid,
  version: svc.currentMapParam().version,
  pattern: JSON.stringify(patternConfig),
  detailedLog: false,
  bounds: undefined
}, "_null", "v1");

// 3) 结果高亮
const geoData = res.result.map(r => {
  const pts = vjmap.GeoBounds.fromString(r.bounds).toPointArray();
  pts.push(pts[0]);
  return { points: map.toLngLat(pts), properties: { color: "#f00" } };
});
vjmap.createAntPathAnimateLineLayer(map, geoData, {
  fillColor1: "#f00", fillColor2: "#0ff", lineWidth: 2, lineOpacity: 0.8
});
```

## 四、保存 / 加载配置

```js
// 保存
await svc.httpPost(svc.serviceUrl("recognizer/add"), patternConfig);

// 获取列表
const list = (await svc.httpGet(svc.serviceUrl("recognizer/list"))).data;   // httpGet 返回 {status,response,data,xhr}，取 .data

// 获取详情
const detail = (await svc.httpGet(svc.serviceUrl(`recognizer/detail?filenames=${filePrefix}`))).data;

// 删除
await svc.httpDel(svc.serviceUrl(`recognizer/delete?filename=${filePrefix}`));
```

## 五、生成缩略图

`getObjectsThumbnail(map, objectIds, bounds, width, height)` 返回 base64 缩略图，可以和 pattern 配合保存。它是官方 `vjmap-vue3/packages/map-manage` 包中的辅助函数（非 vjmap 核心导出；内部用 `svc.createStyle` 按 objectid 过滤 + `wmsTileUrl` 出图 + `cmdDeleteStyle` 清理，可按需复制实现）。

```js
const objectIds = sel.features.map(f => f.properties.objectid);
const bounds = sel.features
  .map(f => vjmap.GeoBounds.fromString(f.properties.bounds))
  .reduce((a, b) => a.updateByBounds(b));
const thumb = await getObjectsThumbnail(map, objectIds, bounds, 120, 80);
patternConfig.thumbnail = thumb;
```

## 六、适用场景

- 块实体统计 / 定位 / 属性查看。
- 重复元素检测 / 设计模式分析。
- 工程标准化检查（查找违规的图例）。

## 七、常见坑

1. **metadata.blockReferences 为空**：是旧版本的图；走表达式查询作为 fallback。
2. **选参考实体数量不足** → 识别不出任何结果；至少 1 个参考对象。
3. **容差过松（translateTolerance 大）** → 误识别太多；过严则漏识别。多次尝试。
4. **识别结果多到爆** → 限制 `bounds` 只在图上某个区域识别。
5. **`objectDetection` 仅支持几何渲染图**：Memory 方式建的图返回 `{error:"geom is false, mapid is not geomrender"}`；且 `mapid`/`version` 必须放参数里、URL 段用 `"_null","v1"`（缺 mapid 报 `param error, mapid is empty`）。
