> **本文回答**：查询 + 处理的典型综合用例：自动分割子图、自动标注、自动提表格、自动提取中心线、工程剖面图。
>
> 案例里所有 `name='xx'` 实体类型、字段（`s4`, `n6`, `n7`, ...）含义、`conditionQueryFeature` 完整参数 ⇒ 见 [query-features](query-features.md)（**主查询文档**）。本文只描述算法思路 + 关键代码。

这些案例展示了"查询 + 空间算法 + 后续绘制/导出"的思路。完整 demo 可在官方示例 [https://vjmap.com/demo/](https://vjmap.com/demo/) 搜关键词查看。

## 一、自动分割子图（queryCase1）

**需求**：一张"总图"里含多个独立子图，要把每个子图分别取出。

思路：

1. 查询所有横竖直线 / 闭合多段线（`name='1'`、`name='2' and n6=1`，类型 ID 与字段含义见 [query-features 第三、四节](query-features.md#三所有实体类型-namexx-完整列表)）。
2. 按包围关系判断每个子图的轮廓（找最外层未被包含的矩形）。
3. 对每个轮廓调用 `svc.composeNewMap({ clipbounds })`，生成仅含该范围的新图。

关键 SQL：

```js
// 所有"线段"类（直线、二三维多段线）
const cond = `name='1' or name='2' or name='3' or name='4'`;
const lines = await svc.conditionQueryFeature({
  condition: cond,
  fields: "objectid,points,envelop",
  limit: 100000
});
```

组合裁剪：

```js
for (const outline of outlines) {
  const composed = await svc.composeNewMap([{
    mapid, version,
    clipbounds: outline.bounds.toArray()
  }]);
  // composed.fileid 可用于上传 / 创建新图
}
```

> 完整算法（找四线组合矩形、横竖线判断）见原文 [https://vjmap.com/guide/queryCase1.html](https://vjmap.com/guide/queryCase1.html)。

## 二、根据测点编号自动标注位置（queryCase2）

**需求**：工程图里的"点号 + 坐标"文字 / 测点符号，自动把测点编号关联到真实坐标位置。

两种模式：

**A. 文字本身就是 `编号 X=xxx Y=yyy` 格式** —— 直接正则解析

```js
// name='13' = AcDbText（单行文本）
const q = await svc.conditionQueryFeature({
  condition: "name='13'",
  fields: "text,location",
  limit: 100000
});
for (const t of q.result) {
  const m = t.text.match(/^(\d+)\s+X=(\S+)\s+Y=(\S+)/);
  if (!m) continue;
  const [, id, x, y] = m;
  new vjmap.Marker({ color: "#3e3" })
    .setLngLat(map.toLngLat([+x, +y]))
    .setPopup(new vjmap.Popup().setHTML(id))
    .addTo(map);
}
```

**B. 文字只有点号，旁边有图形符号（圆 / 三角填充）** —— 用空间临近匹配

```js
// 1) 查所有以 J / DZ 开头的文字，长度 2-12（s4=text）
//    name='12'/'13'/'26'/'27' = 多行/单行/属性注记/块属性 文字类
const texts = await svc.conditionQueryFeature({
  condition: `(name='12' or name='13' or name='26' or name='27')
              and LENGTH(s4) >= 2 and LENGTH(s4) <= 12
              and (s4 like 'J%' or s4 like 'DZ%')`,
  fields: "objectid,text,location",
  limit: 100000
});

// 2) 查所有 hatch（name='11'），按尺寸区分圆 / 三角
const hatches = await svc.conditionQueryFeature({
  condition: `name='11'`,
  includegeom: true,
  limit: 100000
});

// 3) 对每个 hatch 在距离阈值内找最近的文字 → 建立关联
```

字段说明：`name` 类型 ID 见 [query-features 第三节](query-features.md#三所有实体类型-namexx-完整列表)；`s4` 在文字类实体上 = `text`，详细对应表见 [query-features 第四节](query-features.md#四字段含义随类型变化s3s4s5n5n10)。

## 三、自动识别图纸提取信息（queryCase3）

**需求**：批量识别图纸里的固定模式对象（如停车场的车位、图纸编号块、圆圈内文字…）。

五种识别方式：

1. **属性数据匹配**：通过`实体类型`+`图层`+`颜色`+`面积`+`填充符号`+`是否同一块`等组合一次查出。
   ```js
   // 查 "0" 图层、面积 = 12720000 的多段线
   await svc.conditionQueryFeature({
     condition: `name='2' and layerindex=0 and n5=12720000`,
     limit: 100000
   });
   ```
   `name` 类型 ID 与 `n5` 在每种实体上的含义见 [query-features 第三、四节](query-features.md#三所有实体类型-namexx-完整列表)。

2. **属性 + 业务规则**：先查易识别对象（如"圆"），再用空间邻近找关联文字。

3. **业务逻辑代码**：复杂场景（如自动分割子图，见第一节）。

4. **图像相似性**：WMS 出图后用 SIFT / 哈希比对（适用于"非块化的重复符号"）。

5. **AI 深度学习**：自定义训练目标检测模型，处理任意对象。

属性块抽取的常用做法：

```js
// 表达式查询：查"图纸编号"块（gInAttrs5 对应 s5=blockname）
const blockQ = await svc.exprQueryFeature({
  expr: `return gInFeatureType == 'AcDbBlockReference' && gInAttrs5 == '图纸编号'`,
  fields: "objectid,blockname,positon,s4"   // fields 可写属性名或原始列名；块的 s4 列 = attributeDef
});
// 解析每条的 s4 -> KV 对
```

详细方法见原文 [https://vjmap.com/guide/queryCase3.html](https://vjmap.com/guide/queryCase3.html)。

## 四、自动提取表格数据（queryCase4）

**需求**：CAD 图里手工画的表格（线条 + 文字），识别行列并导出 JSON / CSV / Excel。

思路：

1. 查所有水平 / 垂直直线（`name='1'`，详见 [query-features](query-features.md)）；过滤纯横竖（`vjmap.isZero(dx) / vjmap.isZero(dy)`）。
2. 查所有文字（`name='12' or name='13' or name='26' or name='27'`）。
3. **线段聚类**：水平线按 Y 排序，相邻容差内归同一行；垂直线按 X 排序归同一列。
4. **交点 = 单元格顶点**，确定每个 cell 的边界。
5. **文字插入点 vs 单元格边界**，定位归属。
6. **合并单元格**：相邻 cell 共用边线缺失则视为合并。

后台已封装为命令 `extractTable`（`execCommand` 传的命令名；参数：`tol` 容差、`tableEdgeMinPoint` 最少点、`tableTextMinCount` 最少文本、`cellEmptyRatio` 空值比例…，全部字段见 SDK `IExtractTable`）。MCP 工具：`extractTable`（见 [ai-features](ai-features.md)）。

```js
// SDK 封装：内部 execCommand("extractTable", param, "_null", "v1")，mapid/version/layer 缺省取当前图
const r = await svc.cmdExtractTable({
  mapid, version,
  bounds: "x1,y1,x2,y2",   // 空表示全图
  tol: 0,                   // 0=自动求容差
  tableEdgeMinPoint: 12,
  tableTextMinCount: 4,
  findChildMapRects: false  // 同时返回子图范围
});
```

> ⚠️ 这类分析命令（`extractTable`/`extractCenterLines`/`objectDetection`）从**参数里**读 `mapid`/`version`，URL 段固定 `"_null","v1"`；照普通命令把 mapid 放 URL、参数里不带，会报 `param error, mapid is empty`（几何渲染图则静默返回 `{}`）。

## 五、自动提取中心线（queryCase5）

**需求**：墙体 / 道路 / 巷道由一对平行线组成，取它们的中心线（把"具象图形"转"抽象拓扑"）。

思路：

1. 分页查询所有直线 / 多段线（`name='1' or name='2'`，分页见 [query-features 第六节](query-features.md#65-分页查询数据量大时必须)）。
2. 对每条直线找到"平行配对"（**角度容差** + **距离对**，可同时配多组距离支持不同墙厚）。
3. 中点连线 → 中心线。
4. 后处理：合并端点、连接断口、过滤短线、合并共线段。

后台命令 `extractCenterLines`：

```js
await svc.execCommand("extractCenterLines", {
  mapid, version,                // 必须放参数里（见上节 ⚠️）
  bounds: "x1,y1,x2,y2",
  minSpaceDistance: "2.5,3.5",   // 最小距离对（多组）
  maxSpaceDistance: "7.5,8.5",   // 最大距离对
  collinearTolerance: 1.0,        // 共线容差
  duplicateTolerance: 0.2,
  maxGapDistance: 5,              // 允许断开
  paralleSlopeAngleTolerance: 5,  // 平行角度误差（度）
  mergeSlopeAngleTolerance: 3,
  bMergeLine: true,
  bCenterGeoJson: true
}, "_null", "v1");                // 官方路由 /map/cmd/extractCenterLines/_null/v1
```

进阶：用高程注记给中心线插值赋值，再生成 3D 管道。

## 六、工程剖面图（综合 03）

**需求**：给定一条剖面线，抽取穿过的所有实体，按高程排版形成剖面。

思路：

1. `conditionQueryFeature({ bounds: 剖面线点列 })` 拿到穿越实体。
2. 每个实体按投影 X 值排序。
3. 用 vjmapext 的实体绘制 API 生成新图。

## 七、查找面积最大子实体（多种查询组合）

在 [query-expression](query-expression.md) 第七节示例里展示了：

1. 表达式查询全部块（`name='10' = AcDbBlockReference`）。
2. 构造 `objectid LIKE 'xxx_%'` 条件查询每个块的子实体。
3. 在客户端按块聚合取 `area` 最大值（`n5` 字段，含义见 [query-features 第四节](query-features.md#四字段含义随类型变化s3s4s5n5n10)）。

## 八、选择技巧总结

- **几何模式** + `conditionQueryFeature`：快，支持空间谓词（相交/包含）。完整接口见 [query-features](query-features.md)。
- **内存模式** + `exprQueryFeature`：不入库，适合"临时查看 + 简单过滤"。
- **几何模式** + `exprQueryFeature`：某些复杂逻辑在 SQL 里写不出时的回退方案。
- **全文搜索**：在所有图中按文字 / 图层名 / 块名 搜索。
- **后台命令**：`extractTable` / `extractCenterLines` / `objectDetection` 等已封装的复杂流程，直接用最省事。

## 九、常见坑

1. **把几何查询当成小数据量** → 大图查 100 万条很慢。**分页 + 只要必要字段**（见 [query-features 第十一节](query-features.md#十一性能建议)）。
2. **自动分割子图时 clipbounds 稍小** → 边界线条缺失。`bounds.scale(1.02)` 稍放大。
3. **表格提取后行列对齐错乱** → 由于 CAD 用户画线不精确，需要做容差聚类（距离 < tol 视为同一行）。
4. **中心线不连续** → 平行线有断开，调大 `maxGapDistance`；或图里有干扰元素，先用图层切换/手动框选缩范围。
5. **属性识别失败** → 先 `console.log` 一两条数据看 `s3..s5` / `n5..n10` 的真实值（不同类型字段含义不同，见 [query-features 第四节](query-features.md#四字段含义随类型变化s3s4s5n5n10)）。

## 十、相关文档

- **完整查询参考** ⇒ [query-features](query-features.md)（实体类型表、字段含义、SQL 示例）
- SQL 查询速查 ⇒ [query-sql](query-sql.md)
- 表达式查询（内存模式 / 复杂逻辑）⇒ [query-expression](query-expression.md)
- 全文搜索 ⇒ [query-fulltext](query-fulltext.md)
- AI / MCP 封装的查询工具 ⇒ [ai-features](ai-features.md)
- 服务端样式 / 高亮 ⇒ [svr-style-var](svr-style-var.md)
