唯杰地图 logo唯杰地图
VJMAP
EN

line-polyline

vjmapext/references/entity/line-polyline.md 6.6 KB206 行
原文

本文回答:LineEnt 直线和 PolylineEnt 多段线 —— 创建、bulge 弧段、双线 dline、闭合、编辑。

一、LineEnt(直线段)

创建

const line = new vjmapext.LineEnt([x1, y1], [x2, y2]);
line.color = 0xff0000;
line.lineWidth = 2;
mapcadLayer.addEntity(line);

关键属性

属性 类型
startPoint Point2D
endPoint Point2D
midPoint 只读 getter(没有 length/angle 属性,要自己算:startPoint.distanceTo(endPoint) / Math.atan2(dy,dx))

修改

line.startPoint = new Point2D(10, 10);
line.endPoint.x = 200;
line.changed();

场景

  • 网格参考线 / 坐标轴
  • 连接点(配合 PointEnt 显示节点)
  • 配合标注、引线、扉页

二、PolylineEnt(多段线)

创建

// 折线
const poly = new vjmapext.PolylineEnt([
  [0, 0], [100, 0], [100, 100], [200, 100]
]);

// 闭合多边形:最后一个参数 true
const rect = new vjmapext.PolylineEnt([
  [0, 0], [100, 0], [100, 50], [0, 50]
], true);

rect.fillColor = 0x4488ff;
rect.fillOpacity = 0.3;
mapcadLayer.addEntity(rect);

关键属性

属性 说明
bulgePoints BulgePoint[] = {point: Point2D, bulge: number}——顶点和 bulge 都在这,没有独立 points/bulges 数组
isClosed 是否闭合(字段名是 isClosed 不是 closed)
vertices 只读 getter,返回 Point2D[]——数组是新的,但 Point2D 是实体内部引用(改坐标会影响实体,改完仍需 changed())
addVertex(point, bulge?) 追加顶点(内部已调 changed())
fillColor / fillOpacity / borderOpacity 填充(闭合时生效),fillColor=-1 时用 color 填充
lineWidth 默认线宽(继承 EntityBase)

没有 widths 属性——1.0.1 不支持逐段线宽。

bulge 弧段(PLINE 精髓)

bulge = tan(θ/4),θ 为弧段包含角。

bulge 弧形
0 直线
1 半圆(θ = 180°)
0.414 四分之一圆
-1 反向半圆
const arcPoly = new vjmapext.PolylineEnt([
  [0, 0], [100, 0], [100, 100], [0, 100]
], true);

// 第 1、3 段带弧:bulge 写在每个顶点的 bulgePoints[i].bulge 上
[0.5, 0, -0.5, 0].forEach((b, i) => { arcPoly.bulgePoints[i].bulge = b; });
arcPoly.changed();

bulge 弧段顶点

const pl = new vjmapext.PolylineEnt([[0, 0], [100, 50]], true);
pl.bulgePoints = [
  { point: new vjmapext.Point2D(0, 0), bulge: 0.5 },
  { point: new vjmapext.Point2D(100, 50), bulge: 0 }
];
pl.changed();

BulgePoint = { point: Point2D, bulge: number };bulge 为弧凸度(0 = 直线段)。

三、双线(DLINE 命令)

双线没有独立实体类,由 DLINE 命令或工具函数生成一对平行 LineEnt:

mapcadLayer.executeCommand('DLINE');        // 交互式绘制(内部会问宽度)

// 程序化:中心线 + 宽度 → 两侧端点
// 方式一:自己算两侧端点,返回 { startPt1, startPt2, endPt1, endPt2 }
const pts = vjmapext.calculateDoubleLinePoints(
  new vjmapext.Point2D(0, 0), new vjmapext.Point2D(500, 0), 20
);
mapcadLayer.addEntity(new vjmapext.LineEnt(pts.startPt1, pts.endPt1));
mapcadLayer.addEntity(new vjmapext.LineEnt(pts.startPt2, pts.endPt2));

// 方式二:createDoubleLineSegment(startPt, endPt, width, prevLine1?, prevLine2?, miterLimit?)
// 返回 { line1, line2, bevelLine? }——传入前一段时拐角在 miterLimit 内用尖角,否则给斜角补边
const seg = vjmapext.createDoubleLineSegment(
  new vjmapext.Point2D(0, 0), new vjmapext.Point2D(500, 0), 20
);
mapcadLayer.addEntity(seg.line1);
mapcadLayer.addEntity(seg.line2);
if (seg.bevelLine) mapcadLayer.addEntity(seg.bevelLine);
// 端头封口:createDoubleButtCap / createDoubleSquareCap / createDoubleRoundCap;闭合用 closeDoubleLineSegment

四、生成常用形状

圆角矩形

function roundRect(x, y, w, h, r) {
  const pts = [
    [x + r, y], [x + w - r, y],
    [x + w, y + r], [x + w, y + h - r],
    [x + w - r, y + h], [x + r, y + h],
    [x, y + h - r], [x, y + r]
  ];
  const poly = new vjmapext.PolylineEnt(pts, true);
  // 每条短边(角)加 0.414 的 bulge(bulge 在 bulgePoints[i].bulge 上)
  const bs = [0, 0.414, 0, 0.414, 0, 0.414, 0, 0.414];
  poly.bulgePoints.forEach((bp, i) => { if (bs[i] != null) bp.bulge = bs[i]; });
  return poly;
}

正多边形

function regularPolygon(cx, cy, radius, sides) {
  const pts = [];
  for (let i = 0; i < sides; i++) {
    const a = (i / sides) * Math.PI * 2 - Math.PI / 2;
    pts.push([cx + radius * Math.cos(a), cy + radius * Math.sin(a)]);
  }
  return new vjmapext.PolylineEnt(pts, true);
}

五、查询几何

poly.boundingBox();       // [minX, minY, maxX, maxY]——BBox 是 4 元素数组,不是 {min,max}

// 总长 / 面积 / 取点等 SDK 未直接提供,用 vertices 自算:
const vs = poly.vertices;
let len = 0;
for (let i = 1; i < vs.length; i++) len += vs[i].distanceTo(vs[i - 1]);

六、交互编辑

默认 editable = true,选中后显示夹点(getGripPoints() / gripEdit()):

  • LineEnt:start/end 端点夹点拖动改端点;mid 中点夹点拖动平移整条线
  • PolylineEnt:顶点夹点(key 为索引 0..n-1)拖动改该顶点;mid_i 段中点夹点拖动平移该段(相邻两顶点一起动)

注意:夹点没有"添加顶点"和"调 bulge"的操作——增顶点用 addVertex()(或属性面板 vertex-list 的插入),调 bulge 直接改 bulgePoints[i].bulge。

禁用:

line.editable = false;

详见 drawing/grip。

七、性能

场景 推荐
< 1000 段的独立线段 LineEnt 数组
连续折线(1 条 N 段) PolylineEnt
几十万级等值线 / 道路网 转 GeoJSON 走 primitive/line
需要弧段 PolylineEnt + bulgePoints

八、常见坑

  1. PLINE 弧段 bulge 数量不对 → bulgePoints 长度 = 顶点数;第 i 项的 bulge 作用于"顶点 i → 顶点 i+1"段(闭合时末顶点段回首顶点)。
  2. 把 bulgePoints 改成新数组/改了成员但没 changed() → 改引用和改值都要 changed()(addVertex() 内部已调,除外)。
  3. 以为不设 fillColor 就不填充 → 默认 -1 的语义是"跟随 color 填充"(默认 fillOpacity=0.2),不是不填充;想要别的填充色须显式设 fillColor。
  4. LineEnt 当多段线用 → 直线只有 2 端点;多点必须 PolylineEnt。
  5. 期望 bulge 是弧度 / 角度 → 它是 tan(θ/4),不是角。