唯杰地图 logo唯杰地图
VJMAP
EN

circle-arc-ellipse

vjmapext/references/entity/circle-arc-ellipse.md 6.2 KB192 行
原文

本文回答:CircleEnt / ArcEnt / EllipseEnt —— 圆、弧、椭圆的参数、角度约定、填充、与 Polyline 互转。

一、圆 (CircleEnt)

创建

const circle = new vjmapext.CircleEnt([cx, cy], radius);
circle.color = 0x4488ff;
circle.fillColor = 0x4488ff;
circle.fillOpacity = 0.3;
mapcadLayer.addEntity(circle);

⚠️ 封闭图形默认带填充:CircleEnt、整椭圆 EllipseEnt、闭合 PolylineEnt/SplineEnt 默认 fillColor = -1(跟随 color)、fillOpacity = 0.2——不设也会有一层 20% 半透明面。只要轮廓就显式 fillOpacity = 0。

属性

属性 类型 说明
center Point2D 圆心
radius number 半径(CAD 单位)

修改

circle.radius = 150;
circle.changed();

查询

// 实体上没有 area()/perimeter()/length() 这类测量方法;自己按几何算:
const area = Math.PI * circle.radius ** 2;        // π r²
const girth = 2 * Math.PI * circle.radius;        // 2 π r
circle.boundingBox();    // 与半径对齐的外接矩形
// CircleEnt 另有静态构造:fromTwoPoints(直径两点) / fromThreePoints(外接圆,共线返 null) / fromCenterDiameter

二、弧 (ArcEnt)

创建

const arc = new vjmapext.ArcEnt(
  [cx, cy],        // 圆心
  radius,          // 半径
  startAngle,      // 起始角,弧度
  endAngle,        // 终止角,弧度
  isCCW            // 可选,默认 true(逆时针);false = 顺时针
);

重要:ArcEnt 用弧度(不是度):

const arc = new vjmapext.ArcEnt([0, 0], 100, 0, Math.PI);   // 上半圆

度 → 弧度:

const deg2rad = d => d * Math.PI / 180;
const quarter = new vjmapext.ArcEnt([0, 0], 100, 0, deg2rad(90));

方向约定

  • isCCW=true(默认)逆时针扫、false 顺时针扫;构造第 5 参控制
  • 0 弧度 = X 正方向
  • π/2 = Y 正方向
  • fromThreePoints 会按三点转向自动判定 isCCW

端点和中点

arc.startPoint;   // 只读 getter,按 startAngle 计算
arc.endPoint;
arc.midPoint;     // 弧中点(按 midAngle)
arc.midAngle;     // 中点角度
// 没有 arc.length();弧长按实际扫掠角算(与渲染同规则,考虑 isCCW 与跨 0 回绕):
let sweep = arc.endAngle - arc.startAngle;
if (arc.isCCW && sweep < 0) sweep += 2 * Math.PI;
if (!arc.isCCW && sweep > 0) sweep -= 2 * Math.PI;
const arcLen = arc.radius * Math.abs(sweep);

用三点构造弧

const arc = vjmapext.ArcEnt.fromThreePoints(
  [0, 0], [50, 80], [100, 0]
);
mapcadLayer.addEntity(arc);

三、椭圆 / 椭圆弧 (EllipseEnt)

创建完整椭圆

// new EllipseEnt(center?, majorRadius?, minorRadius?, rotation?)
// 注意:第三参是短半轴长度(不是比例);起始/终止角是属性不是构造参数
const ell = new vjmapext.EllipseEnt(
  [cx, cy],        // 圆心
  majorRadius,     // 长半轴长度
  minorRadius,     // 短半轴长度(= 长半轴 × ratio)
  rotation         // 旋转(弧度)
);

创建椭圆弧

const ellArc = new vjmapext.EllipseEnt([100, 100], 80, 40, 0);
ellArc.startAngle = 0;          // 弧度(属性)
ellArc.endAngle = Math.PI;
// ellArc.isFullEllipse → false
  • rotation/startAngle/endAngle 单位都是弧度
  • startAngle/endAngle 是参数角 t(相对长轴、旋转前:x = a·cos t, y = b·sin t 再转 rotation),不是从圆心看过去的几何极角——非正圆时两者不等;要从几何角 θ 换算:t = Math.atan2(a * Math.sin(θ), b * Math.cos(θ))(θ 同样相对长轴)
  • 椭圆弧没有 isCCW 标志:endAngle < startAngle 时按顺时针扫;endAngle - startAngle ≈ 0 视为整圆

典型场景

// 横向椭圆,长半轴 100,短半轴 20
const oval = new vjmapext.EllipseEnt([0, 0], 100, 20, 0);
oval.fillColor = 0xffcc00;
oval.fillOpacity = 0.4;
mapcadLayer.addEntity(oval);

四、填充效果组合

const c = new vjmapext.CircleEnt([0, 0], 100);

// 空心
c.fillOpacity = 0;         c.borderOpacity = 1;

// 实心
c.fillOpacity = 1;         c.borderOpacity = 0;   c.fillColor = 0xff4488;

// 半透明 + 粗边框
c.fillColor = 0x4488ff;    c.fillOpacity = 0.3;   c.lineWidth = 3;

五、与 PolylineEnt 互转

圆弧转多段线(近似):

// vjmap.getCirclePolygonCoordinates(center, radius, points?, startAngle?, endAngle?)
// 平面坐标计算(非球面),返回已闭合点串;startAngle/endAngle 单位是【度】
const poly = new vjmapext.PolylineEnt(
  vjmap.getCirclePolygonCoordinates([cx, cy], radius, 64)
, true);

多段线转圆弧(已知三点):

const arc = vjmapext.ArcEnt.fromThreePoints(p1, p2, p3);

六、交互编辑夹点

  • CircleEnt:中心点 + 四向半径点(quad0..3)
  • ArcEnt:圆心(平移)+ start/end 端点夹点(拖动同时改角度和半径)+ mid 中点夹点(只改半径,即曲率)
  • EllipseEnt:中心(平移)+ major 长轴夹点(同时改 majorRadius 和 rotation)+ minor 短轴夹点(改 minorRadius)

可自定义夹点集合,见 drawing/grip。

七、性能建议

量级 推荐
< 1000 个 CircleEnt / ArcEnt / EllipseEnt
1000 ~ 50000 转 GeoJSON 走 primitive/circle-arc
> 10000 点状圆 symbol/circle-symbol

八、常见坑

  1. 角度单位:ArcEnt/EllipseEnt 的 startAngle/endAngle/rotation 和 rotate(center, angle) 全都用弧度(SCALE 命令把用户输入的度 × π/180 才传给 rotate);只有命令交互输入的是度。
  2. EllipseEnt 没有 ratio 字段——构造直接收 minorRadius 长度(内部 Math.abs 取绝对值);minorRadius > majorRadius 不报错,只是长短轴含义对调,语义上保持 minor ≤ major。
  3. Arc 的 start/end 写反:想要半圆上半却画出下半 → 方向是逆时针。
  4. 想要 Arc 填充:Arc 本身不填充;用闭合的 Polyline 或 Ellipse(完整)。
  5. 大量椭圆导致卡顿:考虑用 Symbol 或贴图。