query-cases
本文回答:查询 + 处理的典型综合用例:自动分割子图、自动标注、自动提表格、自动提取中心线、工程剖面图。
案例里所有
name='xx'实体类型、字段(s4,n6,n7, ...)含义、conditionQueryFeature完整参数 ⇒ 见 query-features(主查询文档)。本文只描述算法思路 + 关键代码。
这些案例展示了"查询 + 空间算法 + 后续绘制/导出"的思路。完整 demo 可在官方示例 https://vjmap.com/demo/ 搜关键词查看。
一、自动分割子图(queryCase1)
需求:一张"总图"里含多个独立子图,要把每个子图分别取出。
思路:
- 查询所有横竖直线 / 闭合多段线(
name='1'、name='2' and n6=1,类型 ID 与字段含义见 query-features 第三、四节)。 - 按包围关系判断每个子图的轮廓(找最外层未被包含的矩形)。
- 对每个轮廓调用
svc.composeNewMap({ clipbounds }),生成仅含该范围的新图。
关键 SQL:
// 所有"线段"类(直线、二三维多段线)
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
});
组合裁剪:
for (const outline of outlines) {
const composed = await svc.composeNewMap([{
mapid, version,
clipbounds: outline.bounds.toArray()
}]);
// composed.fileid 可用于上传 / 创建新图
}
完整算法(找四线组合矩形、横竖线判断)见原文 https://vjmap.com/guide/queryCase1.html。
二、根据测点编号自动标注位置(queryCase2)
需求:工程图里的"点号 + 坐标"文字 / 测点符号,自动把测点编号关联到真实坐标位置。
两种模式:
A. 文字本身就是 编号 X=xxx Y=yyy 格式 —— 直接正则解析
// 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. 文字只有点号,旁边有图形符号(圆 / 三角填充) —— 用空间临近匹配
// 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 第三节;s4 在文字类实体上 = text,详细对应表见 query-features 第四节。
三、自动识别图纸提取信息(queryCase3)
需求:批量识别图纸里的固定模式对象(如停车场的车位、图纸编号块、圆圈内文字…)。
五种识别方式:
-
属性数据匹配:通过
实体类型+图层+颜色+面积+填充符号+是否同一块等组合一次查出。// 查 "0" 图层、面积 = 12720000 的多段线 await svc.conditionQueryFeature({ condition: `name='2' and layerindex=0 and n5=12720000`, limit: 100000 });name类型 ID 与n5在每种实体上的含义见 query-features 第三、四节。 -
属性 + 业务规则:先查易识别对象(如"圆"),再用空间邻近找关联文字。
-
业务逻辑代码:复杂场景(如自动分割子图,见第一节)。
-
图像相似性:WMS 出图后用 SIFT / 哈希比对(适用于"非块化的重复符号")。
-
AI 深度学习:自定义训练目标检测模型,处理任意对象。
属性块抽取的常用做法:
// 表达式查询:查"图纸编号"块(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。
四、自动提取表格数据(queryCase4)
需求:CAD 图里手工画的表格(线条 + 文字),识别行列并导出 JSON / CSV / Excel。
思路:
- 查所有水平 / 垂直直线(
name='1',详见 query-features);过滤纯横竖(vjmap.isZero(dx) / vjmap.isZero(dy))。 - 查所有文字(
name='12' or name='13' or name='26' or name='27')。 - 线段聚类:水平线按 Y 排序,相邻容差内归同一行;垂直线按 X 排序归同一列。
- 交点 = 单元格顶点,确定每个 cell 的边界。
- 文字插入点 vs 单元格边界,定位归属。
- 合并单元格:相邻 cell 共用边线缺失则视为合并。
后台已封装为命令 extractTable(execCommand 传的命令名;参数:tol 容差、tableEdgeMinPoint 最少点、tableTextMinCount 最少文本、cellEmptyRatio 空值比例…,全部字段见 SDK IExtractTable)。MCP 工具:extractTable(见 ai-features)。
// 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)
需求:墙体 / 道路 / 巷道由一对平行线组成,取它们的中心线(把"具象图形"转"抽象拓扑")。
思路:
- 分页查询所有直线 / 多段线(
name='1' or name='2',分页见 query-features 第六节)。 - 对每条直线找到"平行配对"(角度容差 + 距离对,可同时配多组距离支持不同墙厚)。
- 中点连线 → 中心线。
- 后处理:合并端点、连接断口、过滤短线、合并共线段。
后台命令 extractCenterLines:
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)
需求:给定一条剖面线,抽取穿过的所有实体,按高程排版形成剖面。
思路:
conditionQueryFeature({ bounds: 剖面线点列 })拿到穿越实体。- 每个实体按投影 X 值排序。
- 用 vjmapext 的实体绘制 API 生成新图。
七、查找面积最大子实体(多种查询组合)
在 query-expression 第七节示例里展示了:
- 表达式查询全部块(
name='10' = AcDbBlockReference)。 - 构造
objectid LIKE 'xxx_%'条件查询每个块的子实体。 - 在客户端按块聚合取
area最大值(n5字段,含义见 query-features 第四节)。
八、选择技巧总结
- 几何模式 +
conditionQueryFeature:快,支持空间谓词(相交/包含)。完整接口见 query-features。 - 内存模式 +
exprQueryFeature:不入库,适合"临时查看 + 简单过滤"。 - 几何模式 +
exprQueryFeature:某些复杂逻辑在 SQL 里写不出时的回退方案。 - 全文搜索:在所有图中按文字 / 图层名 / 块名 搜索。
- 后台命令:
extractTable/extractCenterLines/objectDetection等已封装的复杂流程,直接用最省事。
九、常见坑
- 把几何查询当成小数据量 → 大图查 100 万条很慢。分页 + 只要必要字段(见 query-features 第十一节)。
- 自动分割子图时 clipbounds 稍小 → 边界线条缺失。
bounds.scale(1.02)稍放大。 - 表格提取后行列对齐错乱 → 由于 CAD 用户画线不精确,需要做容差聚类(距离 < tol 视为同一行)。
- 中心线不连续 → 平行线有断开,调大
maxGapDistance;或图里有干扰元素,先用图层切换/手动框选缩范围。 - 属性识别失败 → 先
console.log一两条数据看s3..s5/n5..n10的真实值(不同类型字段含义不同,见 query-features 第四节)。
十、相关文档
- 完整查询参考 ⇒ query-features(实体类型表、字段含义、SQL 示例)
- SQL 查询速查 ⇒ query-sql
- 表达式查询(内存模式 / 复杂逻辑)⇒ query-expression
- 全文搜索 ⇒ query-fulltext
- AI / MCP 封装的查询工具 ⇒ ai-features
- 服务端样式 / 高亮 ⇒ svr-style-var