Arc Entity (ArcEnt)
About 7 min
Arc Entity (ArcEnt)
ArcEnt represents an arc entity in CAD, defined by a center point, radius, start angle, and end angle.
Overview
An arc is a commonly used curve element in CAD, used for drawing curved outlines, fillets, and more. ArcEnt provides a variety of creation methods and geometric operation functions.
Constructor
import { ArcEnt, Point2D } from 'vjcad';
// Shorthand syntax (recommended)
const arc1 = new ArcEnt([50, 50], 25, 0, Math.PI / 2);
// Point2D syntax
const arc2 = new ArcEnt(new Point2D(50, 50), 25, 0, Math.PI / 2);
// Default constructor (center at origin, radius 1, semicircle from 0 to π)
const arc3 = new ArcEnt();Shorthand Syntax
Both the constructor and the center property support [x, y] array-style coordinates, so you don't have to write new Point2D(...) every time.
Properties
Basic Properties
| Property | Type | Access | Description |
|---|---|---|---|
center | Point2D | Read/Write | Arc center point |
radius | number | Read/Write | Arc radius |
startAng | number | Read/Write | Start angle (radians, 0–2π) |
endAng | number | Read/Write | End angle (radians, 0–2π) |
startAngle | number | Read/Write | Start angle (alias for startAng) |
endAngle | number | Read/Write | End angle (alias for endAng) |
Computed Properties (Read-Only)
| Property | Type | Description |
|---|---|---|
startPoint | Point2D | Start point coordinates of the arc |
endPoint | Point2D | End point coordinates of the arc |
midPoint | Point2D | Midpoint coordinates of the arc |
midAng | number | Mid-angle of the arc |
innerAng | number | Inner angle of the arc (radians) |
totalAngle | number | Total angle (alias for totalAng()) |
isClockwise | boolean | Whether the arc is clockwise |
length | number | Arc length |
bulge | number | Bulge value |
chordLength | number | Chord length |
diameter | number | Diameter |
sagitta | number | Sagitta (arc height) |
import { ArcEnt, Point2D } from 'vjcad';
// Create a 90° arc
const arc = new ArcEnt(new Point2D(0, 0), 50, 0, Math.PI / 2);
// Get geometric properties
console.log('Center:', arc.center); // Point2D(0, 0)
console.log('Radius:', arc.radius); // 50
console.log('Start angle:', arc.startAng); // 0
console.log('End angle:', arc.endAng); // 1.57... (π/2)
console.log('Start point:', arc.startPoint); // Point2D(50, 0)
console.log('End point:', arc.endPoint); // Point2D(0, 50)
console.log('Midpoint:', arc.midPoint); // Point2D(35.35, 35.35)
console.log('Inner angle (radians):', arc.innerAng); // 1.57... (π/2)
console.log('Inner angle (degrees):', arc.innerAng * 180 / Math.PI); // 90
console.log('Arc length:', arc.length); // 78.54...
console.log('Chord length:', arc.chordLength); // 70.71...Creating Arcs
By Center and Angles
import { ArcEnt, Point2D } from 'vjcad';
// Create a semicircle from 0° to 180°
const semicircle = new ArcEnt(
new Point2D(100, 100),
50,
0,
Math.PI
);
// Create an arc from 45° to 135°
const arc45to135 = new ArcEnt(
new Point2D(100, 100),
50,
Math.PI / 4, // 45°
3 * Math.PI / 4 // 135°
);By Three Points
import { ArcEnt, Point2D } from 'vjcad';
const arc = new ArcEnt();
// Initialize arc using three points
const p1 = new Point2D(0, 0); // Start point
const p2 = new Point2D(50, 50); // Point on the arc
const p3 = new Point2D(100, 0); // End point
arc.initBy3Pt(p1, p2, p3);
arc.setDefaults();
console.log('Center:', arc.center);
console.log('Radius:', arc.radius);By Polyline Bulge
import { ArcEnt, Point2D } from 'vjcad';
const arc = new ArcEnt();
// Initialize using start point, end point, and bulge
// bulge = tan(innerAngle / 4)
// bulge > 0: counterclockwise
// bulge < 0: clockwise
// bulge = 1: semicircle
const startPt = new Point2D(0, 0);
const endPt = new Point2D(100, 0);
const bulge = 0.5; // Produces an arc of approximately 53°
arc.initForPlineArc(startPt, endPt, bulge);
arc.setDefaults();Methods
Geometric Transformations
move() - Move
import { ArcEnt, Point2D } from 'vjcad';
const arc = new ArcEnt([0, 0], 50, 0, Math.PI / 2);
// Shorthand syntax (recommended)
arc.move([0, 0], [100, 100]);
console.log('New center:', arc.center); // Point2D(100, 100)
// Radius and angles remain unchangedrotate() - Rotate
import { ArcEnt, Point2D } from 'vjcad';
const arc = new ArcEnt([50, 0], 25, 0, Math.PI / 2);
// Shorthand syntax (recommended)
arc.rotate([0, 0], Math.PI / 2); // Rotate 90° around the origin
console.log('New center:', arc.center); // Point2D(0, 50)
console.log('New start angle:', arc.startAng * 180 / Math.PI); // 90
console.log('New end angle:', arc.endAng * 180 / Math.PI); // 180scale() - Scale
import { ArcEnt, Point2D } from 'vjcad';
const arc = new ArcEnt([50, 50], 25, 0, Math.PI / 2);
// Shorthand syntax (recommended)
arc.scale([0, 0], 2); // Scale up by 2x from the origin
console.log('New center:', arc.center); // Point2D(100, 100)
console.log('New radius:', arc.radius); // 50mirror() - Mirror
import { ArcEnt, Point2D } from 'vjcad';
const arc = new ArcEnt([50, 50], 25, 0, Math.PI / 2);
// Shorthand syntax (recommended)
arc.mirror([0, 0], [100, 0]); // Mirror along the X-axis
// After mirroring, start and end points are swapped, and arc direction is reversedGeometric Calculations
Check if a Point Is Within the Arc Range
import { ArcEnt, Point2D } from 'vjcad';
const arc = new ArcEnt(new Point2D(0, 0), 50, 0, Math.PI / 2);
// Check if a point's angle falls within the arc's angular range
const point = new Point2D(30, 30);
const isInner = arc.pointIsInner(point);
console.log('Point is within arc range:', isInner);
// Check if an angle falls within the range
const angle = Math.PI / 4; // 45°
const angleIsInner = arc.angleIsInner(angle);
console.log('Angle is within range:', angleIsInner); // true (0 < 45° < 90°)Get Nearest Point
import { ArcEnt, Point2D } from 'vjcad';
const arc = new ArcEnt(new Point2D(0, 0), 50, 0, Math.PI / 2);
// Get the nearest point on the arc to a given point
const givenPoint = new Point2D(100, 100);
const nearestPoint = arc.getNearPtByPt(givenPoint);
console.log('Nearest point:', nearestPoint);Get Distance Along the Arc
import { ArcEnt, Point2D } from 'vjcad';
const arc = new ArcEnt(new Point2D(0, 0), 50, 0, Math.PI / 2);
const point = new Point2D(35, 35);
// Calculate distance from the start point
const distFromStart = arc.getDistByPt(point, true);
console.log('Arc length from start:', distFromStart);
// Calculate distance from the end point
const distFromEnd = arc.getDistByPt(point, false);
console.log('Arc length from end:', distFromEnd);Trim Operations
import { ArcEnt, Point2D } from 'vjcad';
const arc = new ArcEnt(new Point2D(0, 0), 50, 0, Math.PI);
console.log('Original arc length:', arc.length);
// Trim 10 units from the start
arc.trimFrontAtDist(10, true);
console.log('Arc length after trimming:', arc.length);
// Trim 10 units from the end
arc.trimBackAtDist(10, true);Grip Editing
import { ArcEnt, Point2D } from 'vjcad';
const arc = new ArcEnt(new Point2D(0, 0), 50, 0, Math.PI / 2);
// Grip types: "start" | "end" | "center" | "mid"
// Move start point (recalculates arc while keeping sagitta unchanged)
arc.gripEdit(new Point2D(-10, 0), "start");
// Move end point
arc.gripEdit(new Point2D(0, 60), "end");
// Move center
arc.gripEdit(new Point2D(10, 10), "center");
// Move midpoint (recalculates arc through three points)
arc.gripEdit(new Point2D(40, 40), "mid");Serialization
import { ArcEnt, Point2D } from 'vjcad';
const arc = new ArcEnt(new Point2D(50, 50), 25, 0, Math.PI / 2);
arc.setDefaults();
// Export
const dbData = arc.toDb();
console.log(dbData);
// {
// type: "ARC",
// layerId: "0",
// center: [50, 50], // Coordinate format: [x, y] or [x, y, z]
// radius: 25,
// startAng: 0,
// endAng: 1.57...
// }
// Import
const newArc = new ArcEnt();
newArc.fromDb(dbData);Complete Examples
Drawing a Sector
import { Engine, ArcEnt, LineEnt, Point2D } from 'vjcad';
function drawSector(center: Point2D, radius: number, startAngle: number, endAngle: number) {
// Create the arc
const arc = new ArcEnt(center, radius, startAngle, endAngle);
arc.setDefaults();
// Create two radius lines
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]);
}
// Draw a 60° sector
drawSector(new Point2D(100, 100), 50, 0, Math.PI / 3);Drawing a Rounded Rectangle
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);
// Four sides
// Top side
entities.push(new LineEnt(
new Point2D(x + r, y + height),
new Point2D(x + width - r, y + height)
));
// Right side
entities.push(new LineEnt(
new Point2D(x + width, y + height - r),
new Point2D(x + width, y + r)
));
// Bottom side
entities.push(new LineEnt(
new Point2D(x + width - r, y),
new Point2D(x + r, y)
));
// Left side
entities.push(new LineEnt(
new Point2D(x, y + r),
new Point2D(x, y + height - r)
));
// Four rounded corners
// Top-right corner
entities.push(new ArcEnt(
new Point2D(x + width - r, y + height - r),
r, 0, Math.PI / 2
));
// Top-left corner
entities.push(new ArcEnt(
new Point2D(x + r, y + height - r),
r, Math.PI / 2, Math.PI
));
// Bottom-left corner
entities.push(new ArcEnt(
new Point2D(x + r, y + r),
r, Math.PI, 3 * Math.PI / 2
));
// Bottom-right corner
entities.push(new ArcEnt(
new Point2D(x + width - r, y + r),
r, 3 * Math.PI / 2, 2 * Math.PI
));
// Set default properties and add to engine
entities.forEach(e => e.setDefaults());
Engine.addEntities(entities);
}
drawRoundedRectangle(50, 50, 200, 100, 20);Interactive Three-Point Arc Drawing
import {
Engine,
ArcEnt,
Point2D,
PointInputOptions,
InputStatusEnum
} from 'vjcad';
async function draw3PointArc() {
// Get the first point (start point)
const opt1 = new PointInputOptions("Specify start point:");
const result1 = await Engine.getPoint(opt1);
if (result1.status !== InputStatusEnum.OK) return;
const p1 = result1.value as Point2D;
// Get the second point (point on the arc)
const opt2 = new PointInputOptions("Specify point on arc:");
opt2.basePoint = p1;
opt2.useBasePoint = true;
const result2 = await Engine.getPoint(opt2);
if (result2.status !== InputStatusEnum.OK) return;
const p2 = result2.value as Point2D;
// Get the third point (end point)
const opt3 = new PointInputOptions("Specify end point:");
opt3.basePoint = p2;
opt3.useBasePoint = true;
const result3 = await Engine.getPoint(opt3);
if (result3.status !== InputStatusEnum.OK) return;
const p3 = result3.value as Point2D;
// Create three-point arc
const arc = new ArcEnt();
arc.initBy3Pt(p1, p2, p3);
arc.setDefaults();
Engine.addEntities(arc);
Engine.writeMessage(`Arc created, radius: ${arc.radius.toFixed(2)}, arc length: ${arc.length.toFixed(2)}`);
}Bulge Explanation
Bulge is an important parameter for representing arc segments in polylines:
bulge = tan(innerAngle / 4)| Bulge Value | Meaning |
|---|---|
| 0 | Straight line segment |
| 1 | Semicircle (counterclockwise) |
| -1 | Semicircle (clockwise) |
| > 0 | Counterclockwise arc |
| < 0 | Clockwise arc |
import { ArcEnt, Point2D } from 'vjcad';
// Create an arc using bulge
const arc = new ArcEnt();
arc.initForPlineArc(
new Point2D(0, 0),
new Point2D(100, 0),
1 // bulge = 1 means semicircle
);
// Get the arc's bulge value
const bulge = arc.bulge;
console.log('Bulge:', bulge);FAQ
Q: How to create an arc with a specific central angle?
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);
}
// Create an arc starting at 30° with a central angle of 60°
const arc = createArcByAngle(new Point2D(100, 100), 50, 30, 60);Q: How to get the area of an arc (sector area)?
import { ArcEnt } from 'vjcad';
function getSectorArea(arc: ArcEnt): number {
// Sector area = (1/2) * r² * θ
return 0.5 * arc.radius * arc.radius * arc.innerAng;
}
function getSegmentArea(arc: ArcEnt): number {
// Segment area = Sector area - Triangle area
const sectorArea = getSectorArea(arc);
const triangleArea = 0.5 * arc.radius * arc.radius * Math.sin(arc.innerAng);
return sectorArea - triangleArea;
}Q: How to check if two arcs intersect?
import { ArcEnt, Point2D } from 'vjcad';
// Simplified version: first check if two circles intersect, then check if intersection points fall within both arc ranges
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)
);
// Check if the two circles intersect
if (d > arc1.radius + arc2.radius || d < Math.abs(arc1.radius - arc2.radius)) {
return false;
}
// Calculate intersection points and check if they fall within the arc ranges
// ... Full implementation requires computing intersection point angles and checking arc.angleIsInner()
return true; // Simplified return
}Next Steps
- Polyline Entity (PolylineEnt) - Polylines containing arc segments
- Ellipse Entity (EllipseEnt) - Ellipses and elliptical arcs
- Spline Entity (SplineEnt) - Free-form curves