选择检测
大约 5 分钟
选择检测
本章介绍 WebCAD 中用于选择框相交检测的函数,这些函数用于实现窗口选择(Window)和交叉选择(Cross)功能。
概述
选择检测函数用于判断实体是否与选择框相交或被选择框包含,支持两种选择模式:
- Window(窗口选择):实体必须完全在选择框内才被选中
- Cross(交叉选择):实体与选择框相交或被包含即被选中
import {
findIntersections,
checkPolylineIntersection,
checkHatchIntersection,
checkPatternHatchIntersection,
checkTextBoundsIntersection,
checkGroupIntersection,
check3DBoundingBoxIntersection,
calculateBoundingBoxFromPoints
} from 'vjcad';findIntersections() - 实体间交点计算
计算指定实体与其他实体的所有交点,返回用于捕捉的 SnapPoint 数组。
function findIntersections(
targetEntity: EntityBase,
otherEntities: EntityBase[]
): SnapPoint[]支持的实体类型
- LINE(直线)
- ARC(圆弧)
- CIRCLE(圆)
- RAY(射线)
- XLINE(构造线)
示例
import { findIntersections, LineEnt, CircleEnt, Point2D } from 'vjcad';
const line = new LineEnt(new Point2D(0, 50), new Point2D(100, 50));
const circle = new CircleEnt(new Point2D(50, 50), 30);
const intersections = findIntersections(line, [circle]);
for (const snapPoint of intersections) {
console.log('交点类型:', snapPoint.type); // "Int"
console.log('交点坐标:', snapPoint.point); // DCS 坐标
}特点
- 返回的坐标是设备坐标系(DCS)
- 避免重复计算(通过 ID 比较)
- 支持同一对象的自交检测(ID 为 0 时)
checkPolylineIntersection() - 多段线相交检测
检测多段线是否与选择边界相交。
function checkPolylineIntersection(
polylineEntity: PolylineEnt,
selectionBounds: BoundingBox,
selectionMode: string // "Window" | "Cross"
): boolean示例
import { checkPolylineIntersection, PolylineEnt, BoundingBox, Point2D } from 'vjcad';
const pline = new PolylineEnt();
// ... 设置多段线
const selectionBox = new BoundingBox(
new Point2D(0, 0),
new Point2D(100, 100)
);
// 窗口选择模式
const inWindow = checkPolylineIntersection(pline, selectionBox, 'Window');
// 交叉选择模式
const crosses = checkPolylineIntersection(pline, selectionBox, 'Cross');算法说明
- 遍历多段线的所有几何段(直线和圆弧)
- 收集所有段的边界框
- 合并边界框
- Window 模式:检查合并后的边界框是否完全在选择框内
- Cross 模式:检查每个段是否与选择框边界相交
checkHatchIntersection() - 填充相交检测
检测填充实体是否与选择边界相交。
function checkHatchIntersection(
hatchEntity: HatchEnt,
selectionBounds: BoundingBox,
selectionMode: string,
corner1: Point2D,
corner2: Point2D,
corner3: Point2D,
corner4: Point2D
): boolean参数说明
| 参数 | 说明 |
|---|---|
hatchEntity | 填充实体 |
selectionBounds | 选择边界框 |
selectionMode | "Window" 或 "Cross" |
corner1-4 | 选择框的四个角点(用于精确相交检测) |
示例
import { checkHatchIntersection, HatchEnt, BoundingBox, Point2D } from 'vjcad';
const hatch = new HatchEnt();
// ... 设置填充
const bounds = new BoundingBox(new Point2D(0, 0), new Point2D(100, 100));
const c1 = new Point2D(0, 0);
const c2 = new Point2D(100, 0);
const c3 = new Point2D(100, 100);
const c4 = new Point2D(0, 100);
const isSelected = checkHatchIntersection(
hatch, bounds, 'Cross',
c1, c2, c3, c4
);算法说明
- 获取填充的所有循环(loops)
- 收集每个循环的凸度点
- 转换到设备坐标系(DCS)
- Window 模式:检查所有点是否在选择框内
- Cross 模式:检查循环边是否与选择框边相交
checkPatternHatchIntersection() - 图案填充相交检测
检测图案填充(非实心填充)是否与选择边界相交。
function checkPatternHatchIntersection(
hatchEntity: HatchEnt,
selectionBounds: BoundingBox,
selectionMode: string,
corner1: Point2D,
corner2: Point2D,
corner3: Point2D,
corner4: Point2D
): boolean与 checkHatchIntersection 的区别
- 使用
getPatternEnts()获取图案线段 - 检测每条图案线是否与选择框相交
- 适用于非实心填充(如 ANSI、ISO 图案)
示例
const hatch = new HatchEnt();
hatch.patternName = 'ANSI31'; // 图案填充
const isSelected = checkPatternHatchIntersection(
hatch, bounds, 'Cross',
c1, c2, c3, c4
);checkTextBoundsIntersection() - 文本相交检测
检测文本实体(TextEnt 或 MTextEnt)是否与选择边界相交。
function checkTextBoundsIntersection(
entity: MTextEnt | TextEnt,
selectionBounds: BoundingBox,
selectionMode: string
): boolean示例
import { checkTextBoundsIntersection, TextEnt, BoundingBox, Point2D } from 'vjcad';
const text = new TextEnt();
text.position = new Point2D(50, 50);
text.textString = 'Hello';
const bounds = new BoundingBox(new Point2D(0, 0), new Point2D(100, 100));
const isSelected = checkTextBoundsIntersection(text, bounds, 'Window');算法说明
- 获取文本的内角点(
getInnerCornerPoints()) - 转换到设备坐标系
- 使用四边形与矩形的相交检测
- Window 模式:所有角点都在选择框内
- Cross 模式:任意角点在框内,或框的角点在文本区域内,或边相交
checkGroupIntersection() - 组实体相交检测
检测组实体是否与选择边界相交。
function checkGroupIntersection(
groupEntity: GroupEnt,
selectionBounds: BoundingBox,
selectionMode: string,
corner1: Point2D,
corner2: Point2D,
corner3: Point2D,
corner4: Point2D
): boolean示例
import { checkGroupIntersection, GroupEnt, BoundingBox, Point2D } from 'vjcad';
const group = new GroupEnt();
// ... 添加子实体
const bounds = new BoundingBox(new Point2D(0, 0), new Point2D(100, 100));
const isSelected = checkGroupIntersection(
group, bounds, 'Cross',
c1, c2, c3, c4
);算法说明
- 获取组内所有子实体
- Window 模式:所有子实体都必须在选择框内
- Cross 模式:任一子实体与选择框相交即可
- 支持递归检测嵌套组
支持的子实体类型
- LINE(直线)
- ARC(圆弧)
- CIRCLE(圆)
- PLINE(多段线)
- HATCH(填充)
- TEXT / MTEXT(文本)
- GROUP(嵌套组)
- CUSTOM(自定义实体)
check3DBoundingBoxIntersection() - 3D 边界框相交检测
检测 3D 边界框是否与窗口相交(用于特殊场景)。
function check3DBoundingBoxIntersection(
boundingBoxMin: BoundingBox,
boundingBoxMax: BoundingBox,
corner1: Point2D,
corner2: Point2D,
corner3: Point2D,
corner4: Point2D,
corner5: Point2D,
corner6: Point2D,
corner7: Point2D,
corner8: Point2D
): booleancalculateBoundingBoxFromPoints() - 从点计算边界框
根据点数组计算最小包围边界框。
function calculateBoundingBoxFromPoints(points: Point2D[]): BoundingBox示例
import { calculateBoundingBoxFromPoints, Point2D } from 'vjcad';
const points = [
new Point2D(10, 20),
new Point2D(50, 80),
new Point2D(30, 10),
new Point2D(90, 50)
];
const bbox = calculateBoundingBoxFromPoints(points);
console.log(bbox.minX); // 10
console.log(bbox.maxX); // 90
console.log(bbox.minY); // 10
console.log(bbox.maxY); // 80特殊情况
- 空数组返回原点边界框
(0, 0) - (0, 0) - 单点返回该点的边界框
直线与圆弧交点辅助函数
findLineArcIntersections()
计算直线与圆弧的交点:
function findLineArcIntersections(
lineEntity: EntityBase,
arcEntity: EntityBase
): SnapPoint[]findLineCircleIntersections()
计算直线与圆的交点:
function findLineCircleIntersections(
lineEntity: EntityBase,
circleEntity: EntityBase
): SnapPoint[]使用示例
实现选择命令
import {
checkPolylineIntersection,
checkHatchIntersection,
checkTextBoundsIntersection,
checkGroupIntersection,
BoundingBox,
Point2D,
Engine
} from 'vjcad';
function selectEntitiesInBox(
selectionBox: BoundingBox,
mode: 'Window' | 'Cross'
): EntityBase[] {
const entities = Engine.currentSpace.items;
const selected: EntityBase[] = [];
// 计算选择框角点
const c1 = selectionBox.BL;
const c2 = selectionBox.BR;
const c3 = selectionBox.TR;
const c4 = selectionBox.TL;
for (const entity of entities) {
let isSelected = false;
switch (entity.type) {
case 'PLINE':
case 'LWPOLYLINE':
isSelected = checkPolylineIntersection(entity, selectionBox, mode);
break;
case 'HATCH':
isSelected = checkHatchIntersection(
entity, selectionBox, mode,
c1, c2, c3, c4
);
break;
case 'TEXT':
case 'MTEXT':
isSelected = checkTextBoundsIntersection(entity, selectionBox, mode);
break;
case 'GROUP':
isSelected = checkGroupIntersection(
entity, selectionBox, mode,
c1, c2, c3, c4
);
break;
default:
// 其他实体使用边界框检测
const bbox = entity.boundingBox();
if (mode === 'Window') {
isSelected = boxContains(selectionBox, bbox);
} else {
isSelected = boxesIntersect(selectionBox, bbox);
}
}
if (isSelected) {
selected.push(entity);
}
}
return selected;
}高亮显示交点
import { findIntersections, Engine } from 'vjcad';
function highlightIntersections(entity: EntityBase) {
const allEntities = Engine.currentSpace.items;
const otherEntities = allEntities.filter(e => e !== entity);
const intersections = findIntersections(entity, otherEntities);
for (const snapPoint of intersections) {
// 在交点位置显示标记
drawMarker(snapPoint.point);
}
}坐标系注意事项
选择检测函数通常在设备坐标系(DCS)中工作:
- 将世界坐标转换为设备坐标
- 在设备坐标系中进行相交检测
- 返回的结果也是设备坐标
// WCS 转 DCS
const dcsPoint = Engine.trans.WcsToDcs(wcsPoint);
// DCS 转 WCS
const wcsPoint = Engine.trans.DcsToWcs(dcsPoint);