圆弧实体 (ArcEnt)
大约 8 分钟
圆弧实体 (ArcEnt)
ArcEnt 表示 CAD 中的圆弧实体,由圆心、半径、起始角度和结束角度确定。
概述
圆弧是 CAD 中常用的曲线元素,用于绘制曲线轮廓、圆角等。ArcEnt 提供了丰富的创建方式和几何操作方法。
构造函数
import { ArcEnt, Point2D } from 'vjcad';
// 简化写法(推荐)
const arc1 = new ArcEnt([50, 50], 25, 0, Math.PI / 2);
// Point2D 写法
const arc2 = new ArcEnt(new Point2D(50, 50), 25, 0, Math.PI / 2);
// 默认构造(圆心原点,半径1,0到π的半圆)
const arc3 = new ArcEnt();简化写法
构造函数和 center 属性都支持 [x, y] 数组形式的坐标,避免每次都写 new Point2D(...)。
属性
基本属性
| 属性 | 类型 | 读写 | 说明 |
|---|---|---|---|
center | Point2D | 读写 | 圆弧圆心 |
radius | number | 读写 | 圆弧半径 |
startAng | number | 读写 | 起始角度(弧度,0-2π) |
endAng | number | 读写 | 结束角度(弧度,0-2π) |
计算属性(只读)
| 属性 | 类型 | 说明 |
|---|---|---|
startPoint | Point2D | 圆弧起点坐标 |
endPoint | Point2D | 圆弧终点坐标 |
midPoint | Point2D | 圆弧中点坐标 |
midAng | number | 圆弧中间角度 |
innerAng | number | 圆弧内角(弧度) |
length | number | 圆弧长度 |
bulge | number | 凸度值 |
chordLength | number | 弦长 |
diameter | number | 直径 |
sagitta | number | 矢高(弓形高度) |
import { ArcEnt, Point2D } from 'vjcad';
// 创建 90° 圆弧
const arc = new ArcEnt(new Point2D(0, 0), 50, 0, Math.PI / 2);
// 获取几何属性
console.log('圆心:', arc.center); // Point2D(0, 0)
console.log('半径:', arc.radius); // 50
console.log('起始角度:', arc.startAng); // 0
console.log('结束角度:', arc.endAng); // 1.57... (π/2)
console.log('起点:', arc.startPoint); // Point2D(50, 0)
console.log('终点:', arc.endPoint); // Point2D(0, 50)
console.log('中点:', arc.midPoint); // Point2D(35.35, 35.35)
console.log('内角(弧度):', arc.innerAng); // 1.57... (π/2)
console.log('内角(度):', arc.innerAng * 180 / Math.PI); // 90
console.log('弧长:', arc.length); // 78.54...
console.log('弦长:', arc.chordLength); // 70.71...创建圆弧
通过圆心和角度
import { ArcEnt, Point2D } from 'vjcad';
// 创建从 0° 到 180° 的半圆
const semicircle = new ArcEnt(
new Point2D(100, 100),
50,
0,
Math.PI
);
// 创建从 45° 到 135° 的圆弧
const arc45to135 = new ArcEnt(
new Point2D(100, 100),
50,
Math.PI / 4, // 45°
3 * Math.PI / 4 // 135°
);通过三点创建
import { ArcEnt, Point2D } from 'vjcad';
const arc = new ArcEnt();
// 使用三点初始化圆弧
const p1 = new Point2D(0, 0); // 起点
const p2 = new Point2D(50, 50); // 中间点(弧上的点)
const p3 = new Point2D(100, 0); // 终点
arc.initBy3Pt(p1, p2, p3);
arc.setDefaults();
console.log('圆心:', arc.center);
console.log('半径:', arc.radius);通过多段线凸度创建
import { ArcEnt, Point2D } from 'vjcad';
const arc = new ArcEnt();
// 使用起点、终点和凸度初始化
// 凸度(bulge) = tan(内角/4)
// bulge > 0: 逆时针
// bulge < 0: 顺时针
// bulge = 1: 半圆
const startPt = new Point2D(0, 0);
const endPt = new Point2D(100, 0);
const bulge = 0.5; // 产生约 53° 的圆弧
arc.initForPlineArc(startPt, endPt, bulge);
arc.setDefaults();方法
几何变换
move() - 移动
import { ArcEnt, Point2D } from 'vjcad';
const arc = new ArcEnt([0, 0], 50, 0, Math.PI / 2);
// 简化写法(推荐)
arc.move([0, 0], [100, 100]);
console.log('新圆心:', arc.center); // Point2D(100, 100)
// 半径和角度不变rotate() - 旋转
import { ArcEnt, Point2D } from 'vjcad';
const arc = new ArcEnt([50, 0], 25, 0, Math.PI / 2);
// 简化写法(推荐)
arc.rotate([0, 0], Math.PI / 2); // 绕原点旋转 90°
console.log('新圆心:', arc.center); // Point2D(0, 50)
console.log('新起始角:', arc.startAng * 180 / Math.PI); // 90
console.log('新结束角:', arc.endAng * 180 / Math.PI); // 180scale() - 缩放
import { ArcEnt, Point2D } from 'vjcad';
const arc = new ArcEnt([50, 50], 25, 0, Math.PI / 2);
// 简化写法(推荐)
arc.scale([0, 0], 2); // 以原点为中心放大 2 倍
console.log('新圆心:', arc.center); // Point2D(100, 100)
console.log('新半径:', arc.radius); // 50mirror() - 镜像
import { ArcEnt, Point2D } from 'vjcad';
const arc = new ArcEnt([50, 50], 25, 0, Math.PI / 2);
// 简化写法(推荐)
arc.mirror([0, 0], [100, 0]); // 沿 X 轴镜像
// 镜像后起点和终点交换,圆弧方向反转几何计算
判断点是否在圆弧范围内
import { ArcEnt, Point2D } from 'vjcad';
const arc = new ArcEnt(new Point2D(0, 0), 50, 0, Math.PI / 2);
// 判断点的角度是否在圆弧角度范围内
const point = new Point2D(30, 30);
const isInner = arc.pointIsInner(point);
console.log('点在圆弧范围内:', isInner);
// 判断角度是否在范围内
const angle = Math.PI / 4; // 45°
const angleIsInner = arc.angleIsInner(angle);
console.log('角度在范围内:', angleIsInner); // true (0 < 45° < 90°)获取最近点
import { ArcEnt, Point2D } from 'vjcad';
const arc = new ArcEnt(new Point2D(0, 0), 50, 0, Math.PI / 2);
// 获取给定点到圆弧上最近的点
const givenPoint = new Point2D(100, 100);
const nearestPoint = arc.getNearPtByPt(givenPoint);
console.log('最近点:', nearestPoint);获取沿弧长的距离
import { ArcEnt, Point2D } from 'vjcad';
const arc = new ArcEnt(new Point2D(0, 0), 50, 0, Math.PI / 2);
const point = new Point2D(35, 35);
// 从起点计算距离
const distFromStart = arc.getDistByPt(point, true);
console.log('从起点的弧长:', distFromStart);
// 从终点计算距离
const distFromEnd = arc.getDistByPt(point, false);
console.log('从终点的弧长:', distFromEnd);修剪操作
import { ArcEnt, Point2D } from 'vjcad';
const arc = new ArcEnt(new Point2D(0, 0), 50, 0, Math.PI);
console.log('原始弧长:', arc.length);
// 从起点修剪 10 个单位长度
arc.trimFrontAtDist(10, true);
console.log('修剪后弧长:', arc.length);
// 从终点修剪 10 个单位长度
arc.trimBackAtDist(10, true);夹点编辑
import { ArcEnt, Point2D } from 'vjcad';
const arc = new ArcEnt(new Point2D(0, 0), 50, 0, Math.PI / 2);
// 夹点类型: "start" | "end" | "center" | "mid"
// 移动起点(保持矢高不变重新计算圆弧)
arc.gripEdit(new Point2D(-10, 0), "start");
// 移动终点
arc.gripEdit(new Point2D(0, 60), "end");
// 移动圆心
arc.gripEdit(new Point2D(10, 10), "center");
// 移动中点(重新计算圆弧通过三点)
arc.gripEdit(new Point2D(40, 40), "mid");序列化
import { ArcEnt, Point2D } from 'vjcad';
const arc = new ArcEnt(new Point2D(50, 50), 25, 0, Math.PI / 2);
arc.setDefaults();
// 导出
const dbData = arc.toDb();
console.log(dbData);
// {
// type: "ARC",
// layerId: "0",
// center: [50, 50], // 坐标格式: [x, y] 或 [x, y, z]
// radius: 25,
// startAng: 0,
// endAng: 1.57...
// }
// 导入
const newArc = new ArcEnt();
newArc.fromDb(dbData);完整示例
绘制扇形
import { Engine, ArcEnt, LineEnt, Point2D } from 'vjcad';
function drawSector(center: Point2D, radius: number, startAngle: number, endAngle: number) {
// 创建圆弧
const arc = new ArcEnt(center, radius, startAngle, endAngle);
arc.setDefaults();
// 创建两条半径线
const line1 = new LineEnt(center.clone(), arc.startPoint);
const line2 = new LineEnt(center.clone(), arc.endPoint);
line1.setDefaults();
line2.setDefaults();
Engine.addEntities([arc, line1, line2]);
}
// 绘制 60° 扇形
drawSector(new Point2D(100, 100), 50, 0, Math.PI / 3);绘制圆角矩形
import { Engine, ArcEnt, LineEnt, Point2D } from 'vjcad';
function drawRoundedRectangle(
x: number, y: number,
width: number, height: number,
cornerRadius: number
) {
const entities = [];
const r = Math.min(cornerRadius, width / 2, height / 2);
// 四条边
// 上边
entities.push(new LineEnt(
new Point2D(x + r, y + height),
new Point2D(x + width - r, y + height)
));
// 右边
entities.push(new LineEnt(
new Point2D(x + width, y + height - r),
new Point2D(x + width, y + r)
));
// 下边
entities.push(new LineEnt(
new Point2D(x + width - r, y),
new Point2D(x + r, y)
));
// 左边
entities.push(new LineEnt(
new Point2D(x, y + r),
new Point2D(x, y + height - r)
));
// 四个圆角
// 右上角
entities.push(new ArcEnt(
new Point2D(x + width - r, y + height - r),
r, 0, Math.PI / 2
));
// 左上角
entities.push(new ArcEnt(
new Point2D(x + r, y + height - r),
r, Math.PI / 2, Math.PI
));
// 左下角
entities.push(new ArcEnt(
new Point2D(x + r, y + r),
r, Math.PI, 3 * Math.PI / 2
));
// 右下角
entities.push(new ArcEnt(
new Point2D(x + width - r, y + r),
r, 3 * Math.PI / 2, 2 * Math.PI
));
// 设置默认属性并添加
entities.forEach(e => e.setDefaults());
Engine.addEntities(entities);
}
drawRoundedRectangle(50, 50, 200, 100, 20);交互式绘制三点圆弧
import {
Engine,
ArcEnt,
Point2D,
PointInputOptions,
InputStatusEnum
} from 'vjcad';
async function draw3PointArc() {
// 获取第一个点(起点)
const opt1 = new PointInputOptions("指定起点:");
const result1 = await Engine.getPoint(opt1);
if (result1.status !== InputStatusEnum.OK) return;
const p1 = result1.value as Point2D;
// 获取第二个点(弧上的点)
const opt2 = new PointInputOptions("指定弧上的点:");
opt2.basePoint = p1;
opt2.useBasePoint = true;
const result2 = await Engine.getPoint(opt2);
if (result2.status !== InputStatusEnum.OK) return;
const p2 = result2.value as Point2D;
// 获取第三个点(终点)
const opt3 = new PointInputOptions("指定终点:");
opt3.basePoint = p2;
opt3.useBasePoint = true;
const result3 = await Engine.getPoint(opt3);
if (result3.status !== InputStatusEnum.OK) return;
const p3 = result3.value as Point2D;
// 创建三点圆弧
const arc = new ArcEnt();
arc.initBy3Pt(p1, p2, p3);
arc.setDefaults();
Engine.addEntities(arc);
Engine.writeMessage(`圆弧已创建,半径: ${arc.radius.toFixed(2)}, 弧长: ${arc.length.toFixed(2)}`);
}凸度 (Bulge) 说明
凸度是多段线中表示弧段的重要参数:
bulge = tan(内角 / 4)| bulge 值 | 含义 |
|---|---|
| 0 | 直线段 |
| 1 | 半圆(逆时针) |
| -1 | 半圆(顺时针) |
| > 0 | 逆时针圆弧 |
| < 0 | 顺时针圆弧 |
import { ArcEnt, Point2D } from 'vjcad';
// 通过凸度创建圆弧
const arc = new ArcEnt();
arc.initForPlineArc(
new Point2D(0, 0),
new Point2D(100, 0),
1 // bulge = 1 表示半圆
);
// 获取圆弧的凸度
const bulge = arc.bulge;
console.log('凸度:', bulge);常见问题
Q: 如何创建指定圆心角的圆弧?
import { ArcEnt, Point2D } from 'vjcad';
function createArcByAngle(
center: Point2D,
radius: number,
startAngleDeg: number,
angleDeg: number
) {
const startAngleRad = startAngleDeg * Math.PI / 180;
const endAngleRad = (startAngleDeg + angleDeg) * Math.PI / 180;
return new ArcEnt(center, radius, startAngleRad, endAngleRad);
}
// 创建从 30° 开始,圆心角为 60° 的圆弧
const arc = createArcByAngle(new Point2D(100, 100), 50, 30, 60);Q: 如何获取圆弧的面积(扇形面积)?
import { ArcEnt } from 'vjcad';
function getSectorArea(arc: ArcEnt): number {
// 扇形面积 = (1/2) * r² * θ
return 0.5 * arc.radius * arc.radius * arc.innerAng;
}
function getSegmentArea(arc: ArcEnt): number {
// 弓形面积 = 扇形面积 - 三角形面积
const sectorArea = getSectorArea(arc);
const triangleArea = 0.5 * arc.radius * arc.radius * Math.sin(arc.innerAng);
return sectorArea - triangleArea;
}Q: 如何判断两个圆弧是否相交?
import { ArcEnt, Point2D } from 'vjcad';
// 简化版本:先检查两圆是否相交,再检查交点是否在两个圆弧范围内
function arcsIntersect(arc1: ArcEnt, arc2: ArcEnt): boolean {
const d = Math.sqrt(
Math.pow(arc2.center.x - arc1.center.x, 2) +
Math.pow(arc2.center.y - arc1.center.y, 2)
);
// 检查两圆是否相交
if (d > arc1.radius + arc2.radius || d < Math.abs(arc1.radius - arc2.radius)) {
return false;
}
// 计算交点并检查是否在圆弧范围内
// ... 详细实现需要计算交点角度并检查 arc.angleIsInner()
return true; // 简化返回
}下一步
- 多段线实体 (PolylineEnt) - 包含弧段的多段线
- 椭圆实体 (EllipseEnt) - 椭圆和椭圆弧
- 样条曲线 (SplineEnt) - 自由曲线