唯杰地图 logo唯杰地图
VJMAP
EN

point-bounds

vjcad/references/geometry/point-bounds.md 5.9 KB153 行
原文

本文回答: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 自身),与 vjmap GeoPoint 的 clone 风格相反;要保留原点须先 .clone()。

⚠️ Point2D 是极简类:没有 mag / unit / perp / angleTo / distanceTo / dot / lerp——那些是 vjmap GeoPoint 的面,混用会 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