point-bounds
本文回答:
Point2D是基础点 / 向量类,可选 z 坐标,支持链式.rotate / .scale / .offset / .move;PointInput联合类型允许Point2D | [x, y] | [x, y, z]三种输入;ObservablePoint2D是带 callback 的响应式版本(实体内部用);BoundingBox是轴对齐包围盒,多框合并mergeBoundingBoxes([...]),从点数组算calculateBoundingBoxFromPoints([...])。
一、Point2D 基础
import { Point2D, toPoint2D } from 'vjcad';
// 创建
const p1 = new Point2D(100, 200);
const p2 = new Point2D(100, 200, 50); // 带 z
const o = Point2D.Origin(); // (0, 0)
// 输入互转
const p3 = toPoint2D([100, 200]);
const p4 = toPoint2D([100, 200, 50]);
// 克隆 / 序列化
const c = p1.clone();
const arr = p1.toDb(); // [100, 200] 或 [100, 200, 50]
const r = Point2D.fromDb([300, 400, 25]);
属性:x / y / z(z 可选)。
MCP 参考:vjcad/doc/geometry/point2d.md。
二、Point2D 向量运算 / 链式变换
const p = new Point2D(100, 0)
.rotate(Math.PI / 4) // 绕原点旋转 45°
.scale(2) // 以原点为中心缩放 ×2
.offset(new Point2D(50, 50)); // 偏移
p.move(new Point2D(0, 0), new Point2D(50, 50)); // 计算位移并应用
p.offsetMinus(new Point2D(50, 30)); // 反向偏移
| 方法 | 参数 | 说明 |
|---|---|---|
clone() |
— | 克隆 |
offset(v) / offsetMinus(v) |
Point2D | 偏移 / 反向偏移 |
move(from, to) |
Point2D, Point2D | 移动 |
rotate(angle, center?) |
rad, Point2D? | 旋转(弧度) |
scale(factor, center?) |
num, Point2D? | 缩放 |
toDb() / fromDb(d) |
— | 序列化 |
所有变换方法都返回
this,支持链式调用——⚠️ 是原地修改后返回 this(p.rotate(π/2)直接改p自身),与 vjmapGeoPoint的 clone 风格相反;要保留原点须先.clone()。⚠️
Point2D是极简类:没有mag / unit / perp / angleTo / distanceTo / dot / lerp——那些是 vjmapGeoPoint的面,混用会undefined is not a function。要算长度/角度用顶层distance/getAngleBetweenPoints/getMidPoint/polarToCartesian。
MCP 参考:vjcad/doc/geometry/point2d.md。
三、PointInput(重要)
type PointInput = Point2D | [number, number] | [number, number, number];
vjcad 大量构造函数 / 几何方法 同时接受这三种形式:
new LineEnt([0, 0], [100, 100]);
new LineEnt(new Point2D(0, 0), new Point2D(100, 100));
new BulgePoint([x, y], bulge);
circle.move([0, 0], [50, 30]);
MCP 参考:vjcad/doc/geometry/point2d.md、vjcad/doc/guide/quick-start.md。
四、ObservablePoint2D(响应式)
实体内部用,坐标变化触发回调(如 setModified())。业务代码很少直接 new,但读 line.startPoint.x = 50 时背后就是它:
const op = new ObservablePoint2D(0, 0, () => console.log('changed'));
op.set(100, 200, 50); // 一次回调
op.copyFrom(other); // 一次回调
op.x = 100; op.y = 200; // 两次回调
MCP 参考:vjcad/doc/geometry/point2d.md。
五、BoundingBox(轴对齐包围盒)
import { BoundingBox, Point2D } from 'vjcad';
const bb = new BoundingBox(new Point2D(0, 0), new Point2D(100, 80));
bb.minX; bb.maxX; bb.minY; bb.maxY;
bb.width; bb.height; bb.center;
bb.BL; bb.BR; bb.TL; bb.TR; // 四个角点
bb.point1; bb.point2; bb.point3; bb.point4;
bb.minPoint; bb.maxPoint;
bb.hasSizeBounds; bb.isSinglePointBounds;
bb.move(new Point2D(0, 0), new Point2D(50, 30)); // 移动
bb.isPointInBox(new Point2D(50, 50)); // true
MCP 参考:vjcad/doc/geometry/bounding-box.md。
六、合并多个 BoundingBox / 从点集算
import { mergeBoundingBoxes, calculateBoundingBoxFromPoints, BoundingBox, Point2D } from 'vjcad';
const merged = mergeBoundingBoxes([bb1, bb2, bb3]);
const points = [new Point2D(10, 20), new Point2D(50, 80), new Point2D(30, 10)];
const bb = calculateBoundingBoxFromPoints(points);
MCP 参考:vjcad/doc/geometry/bounding-box.md、vjcad/example/geometry/15mergebounds.js。
七、典型场景
// 缩放视图到选中实体
function zoomToSelection() {
const ents = Engine.ssGetFirst();
if (!ents.length) return;
// 单实体可直接 e.boundingBox()(运行时全实体可用;EntityBase d.ts 未声明)。
// 多实体聚合边界用引擎级方法:
const merged = Engine.getBoundsByEntities(ents); // 返回 BoundingBox
if (!merged.hasSizeBounds) return;
Engine.zoomToEntities(ents); // 最直接:直接吃实体数组
// 或手动:Engine.zoomExtents(undefined, { wcsBounds: [merged.minPoint.x, merged.minPoint.y, merged.maxPoint.x, merged.maxPoint.y] });
}
// 快速碰撞过滤(先用 bbox 粗判)
function fastIntersect(a, b) {
const ba = Engine.getBoundsByEntities([a]), bb = Engine.getBoundsByEntities([b]);
if (ba.maxPoint.x < bb.minPoint.x || ba.minPoint.x > bb.maxPoint.x) return false;
if (ba.maxPoint.y < bb.minPoint.y || ba.minPoint.y > bb.maxPoint.y) return false;
return true;
}
MCP 参考:vjcad/doc/geometry/bounding-box.md。
反例
Point2D当 mutable 直接修改:业务对象建议先.clone()再改,避免影响实体内部ObservablePoint2D。- 用
Math.atan2自己算角度:vjcad 自带getAngleBetweenPoints(p1, p2)。 - 想 "缩放到一个点":
BoundingBox.isSinglePointBounds=true,zoom*系列遇到该 bbox 行为不可预期,提前expand一定 margin。
参考(官方文档 MCP)
- 文档:
vjcad/doc/geometry/point2d.md、vjcad/doc/geometry/bounding-box.md、vjcad/doc/guide/quick-start.md - 示例:
vjcad/example/geometry/05boundingbox.js、15mergebounds.js