边界检测器
大约 5 分钟
边界检测器
本章介绍 WebCAD 中的 BoundaryDetector 边界检测器,用于从内部点自动检测封闭边界,主要应用于填充(Hatch)命令的边界拾取功能。
概述
BoundaryDetector 基于 ODA GeLoopsBuilder 算法原理实现,使用 WASM 进行高性能边界追踪。它可以从画布上的实体中自动检测包围指定点的最小封闭边界。
import { BoundaryDetector, BoundaryDetectorOptions, BoundaryDetectionResult } from 'vjcad';快速开始
基本使用
import { BoundaryDetector, Point2D } from 'vjcad';
// 创建边界检测器
const detector = new BoundaryDetector();
// 指定内部点
const pickPoint = new Point2D(50, 50);
// 执行检测
const result = detector.detectBoundary(pickPoint);
if (result.success) {
console.log('外边界:', result.outerBoundary);
console.log('孤岛数量:', result.islands.length);
console.log('所有边界:', result.edges);
} else {
console.log('检测失败:', result.errorMessage);
}带配置的使用
const detector = new BoundaryDetector({
gapTolerance: 0.5, // 允许的间隙
detectIslands: true, // 检测孤岛
islandMode: 'normal', // 孤岛模式
maxTraceSteps: 10000, // 最大追踪步数
useViewportClipping: true // 只使用视口内实体
});
const result = detector.detectBoundary(pickPoint);BoundaryDetectorOptions - 检测选项
配置参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
gapTolerance | number | 0.1 | 间隙公差,允许的最大间隙距离 |
detectIslands | boolean | true | 是否检测孤岛(内部孔洞) |
islandMode | string | 'normal' | 孤岛处理模式 |
maxTraceSteps | number | 10000 | 最大追踪步数(防止无限循环) |
useViewportClipping | boolean | true | 是否只使用视口内的实体 |
gapTolerance - 间隙公差
类似 AutoCAD 的 HPGAPTOL 设置,允许边界存在一定的间隙:
// 允许 0.5 单位的间隙
const detector = new BoundaryDetector({
gapTolerance: 0.5
});islandMode - 孤岛模式
| 值 | 说明 |
|---|---|
'normal' | 标准模式,检测所有孤岛 |
'outer' | 只检测外边界,忽略孤岛 |
'ignore' | 忽略孤岛检测 |
// 只检测外边界
const detector = new BoundaryDetector({
islandMode: 'outer'
});
// 忽略孤岛
const detector2 = new BoundaryDetector({
detectIslands: false
});BoundaryDetectionResult - 检测结果
结果结构
interface BoundaryDetectionResult {
success: boolean; // 是否成功
errorMessage?: string; // 错误信息(失败时)
outerBoundary: Edge | null; // 外部边界
islands: Edge[]; // 孤岛边界数组
edges: Edges | null; // 所有边界的 Edges 集合
}使用结果
const result = detector.detectBoundary(pickPoint);
if (!result.success) {
console.error('检测失败:', result.errorMessage);
return;
}
// 外边界
if (result.outerBoundary) {
const outerPoints = result.outerBoundary.bulgePoints;
console.log('外边界点数:', outerPoints.items.length);
}
// 孤岛(内部孔洞)
for (const island of result.islands) {
const islandPoints = island.bulgePoints;
console.log('孤岛点数:', islandPoints.items.length);
}
// 直接用于填充实体
if (result.edges) {
const hatch = new HatchEnt();
hatch.edges = result.edges;
}detectBoundary() - 执行检测
方法签名
detectBoundary(pickPoint: Point2D, entities?: EntityBase[]): BoundaryDetectionResult参数
| 参数 | 类型 | 说明 |
|---|---|---|
pickPoint | Point2D | 拾取点(世界坐标系) |
entities | EntityBase[] | 可选,指定候选实体数组 |
自动获取实体
如果不提供 entities 参数,检测器会自动获取实体:
- 如果
useViewportClipping为 true,使用视口内的实体 - 否则使用当前空间的所有实体
// 自动获取实体
const result = detector.detectBoundary(pickPoint);
// 指定实体范围
const selectedEntities = Engine.getSelectedEntities();
const result2 = detector.detectBoundary(pickPoint, selectedEntities);支持的实体类型
基础几何实体
| 类型 | 说明 |
|---|---|
LINE | 直线 |
ARC | 圆弧 |
CIRCLE | 圆 |
PLINE / LWPOLYLINE | 多段线 |
ELLIPSE | 椭圆 |
SPLINE | 样条曲线 |
BEZIER | 贝塞尔曲线 |
容器实体
检测器会自动展开容器实体中的子实体:
| 类型 | 说明 |
|---|---|
INSERT | 块引用 |
GROUP | 组 |
CUSTOM | 自定义实体 |
// 块引用中的实体也会被检测
const insertEnt = new InsertEnt();
// ...
const result = detector.detectBoundary(pickPoint, [insertEnt]);
// 会自动展开 insertEnt 中的子实体算法原理
核心步骤
- 构建曲线信息 - 将实体转换为曲线信息数组(起点、终点、凸度)
- 计算交点 - 计算所有曲线之间的交点
- 曲线分割 - 在交点处分割曲线
- 构建图结构 - 建立顶点和边的图结构
- 合并顶点 - 合并相近的顶点(间隙容差)
- 移除自由端 - 删除悬挂的边(不形成闭合的边)
- 分割连通分量 - 将图分割为独立的连通区域
- 追踪边界 - 使用极角排序追踪最小闭合边界
- 验证结果 - 验证边界的有效性
WASM 加速
边界检测的核心算法在 WebAssembly 中实现,提供高性能的边界追踪:
// 检测器会自动检测 WASM 是否可用
const detector = new BoundaryDetector();
// WASM 不可用时会显示错误信息
const result = detector.detectBoundary(pickPoint);
if (!result.success && result.errorMessage?.includes('WASM')) {
console.log('请确保 WebCadCore WASM 模块已加载');
}应用示例
填充命令中使用
import { BoundaryDetector, HatchEnt, Point2D, Engine } from 'vjcad';
async function createHatchFromPoint(pickPoint: Point2D) {
// 创建检测器
const detector = new BoundaryDetector({
gapTolerance: 0.1,
detectIslands: true
});
// 检测边界
const result = detector.detectBoundary(pickPoint);
if (!result.success) {
console.error('无法检测到有效边界');
return null;
}
// 创建填充实体
const hatch = new HatchEnt();
hatch.edges = result.edges!;
hatch.patternName = 'SOLID';
hatch.setDefaults();
// 添加到画布
Engine.pcanvas.addEntity(hatch);
return hatch;
}批量边界检测
async function detectMultipleBoundaries(points: Point2D[]): BoundaryDetectionResult[] {
const detector = new BoundaryDetector();
const results: BoundaryDetectionResult[] = [];
for (const point of points) {
const result = detector.detectBoundary(point);
results.push(result);
}
return results;
}自定义实体范围
// 只在特定图层的实体中检测边界
function detectInLayer(pickPoint: Point2D, layerName: string) {
const entities = Engine.currentSpace.items.filter(
e => e.layer === layerName
);
const detector = new BoundaryDetector();
return detector.detectBoundary(pickPoint, entities);
}错误处理
常见错误
| 错误信息 | 原因 | 解决方案 |
|---|---|---|
| "找不到可用的边界实体" | 拾取点附近没有实体 | 检查拾取点位置或实体可见性 |
| "无法生成曲线信息" | 实体类型不支持 | 检查实体类型是否在支持列表中 |
| "WASM模块不可用" | WASM 未加载 | 确保 WebCadCore 已正确初始化 |
| "无外部边界" | 未找到闭合边界 | 增加间隙容差或检查实体是否闭合 |
错误处理示例
const result = detector.detectBoundary(pickPoint);
if (!result.success) {
switch (true) {
case result.errorMessage?.includes('边界实体'):
// 提示用户选择正确位置
break;
case result.errorMessage?.includes('WASM'):
// 提示 WASM 加载问题
break;
case result.errorMessage?.includes('外部边界'):
// 提示边界未闭合
break;
default:
// 其他错误
console.error(result.errorMessage);
}
}性能优化
限制实体范围
// 只使用视口内实体(默认)
const detector = new BoundaryDetector({
useViewportClipping: true
});
// 或手动指定实体
const nearbyEntities = getEntitiesNearPoint(pickPoint, 100);
detector.detectBoundary(pickPoint, nearbyEntities);调整追踪步数
// 对于复杂图形,可能需要增加步数
const detector = new BoundaryDetector({
maxTraceSteps: 50000
});