recognizer
本文回答:实体智能识别(块参照批量查询 + 模式匹配相似实体)。
一、两个能力
- 批量获取所有块参照:自动列出图中所有
AcDbBlockReference。 - 相似实体识别:基于用户选的参考实体,找出图中几何形态相似(含缩放/旋转)的实体。
二、获取所有块参照
优先从 metadata
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 }, ...]
}
没有则走表达式查询
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
}));
可视化
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" });
三、相似实体识别
配置
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[]
}]
};
选择参考实体 + 识别
// 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
});
四、保存 / 加载配置
// 保存
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 清理,可按需复制实现)。
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;
六、适用场景
- 块实体统计 / 定位 / 属性查看。
- 重复元素检测 / 设计模式分析。
- 工程标准化检查(查找违规的图例)。
七、常见坑
- metadata.blockReferences 为空:是旧版本的图;走表达式查询作为 fallback。
- 选参考实体数量不足 → 识别不出任何结果;至少 1 个参考对象。
- 容差过松(translateTolerance 大) → 误识别太多;过严则漏识别。多次尝试。
- 识别结果多到爆 → 限制
bounds只在图上某个区域识别。 objectDetection仅支持几何渲染图:Memory 方式建的图返回{error:"geom is false, mapid is not geomrender"};且mapid/version必须放参数里、URL 段用"_null","v1"(缺 mapid 报param error, mapid is empty)。