Area Calculation
Area Calculation
This chapter introduces area calculation features in WebCAD, including polygon area algorithms and related helper classes.
Overview
WebCAD provides polygon area calculation based on the Shoelace formula.
import {
calculatePolygonArea,
AreaCalculationElement,
AreaCalculationCollection,
sortEdgeByArea
} from 'vjcad';calculatePolygonArea() - Polygon Area Calculation
Uses the Shoelace formula to calculate the area of any simple polygon.
function calculatePolygonArea(polygonVertices: Point[]): numberParameters
| Parameter | Type | Description |
|---|---|---|
polygonVertices | Point[] | Polygon vertex array in order |
Return Value
Returns the signed doubled area of the polygon. The actual area is Math.abs(result) / 2.
Basic Example
import { calculatePolygonArea } from 'vjcad';
// Rectangle area (vertices in clockwise or counterclockwise order)
const rectangle = [
{ x: 0, y: 0 },
{ x: 100, y: 0 },
{ x: 100, y: 50 },
{ x: 0, y: 50 }
];
const doubleArea = calculatePolygonArea(rectangle);
const area = Math.abs(doubleArea) / 2; // 5000Triangle Area
const triangle = [
{ x: 0, y: 0 },
{ x: 100, y: 0 },
{ x: 50, y: 80 }
];
const area = Math.abs(calculatePolygonArea(triangle)) / 2; // 4000Complex Polygon
// L-shaped polygon
const lShape = [
{ x: 0, y: 0 },
{ x: 60, y: 0 },
{ x: 60, y: 40 },
{ x: 20, y: 40 },
{ x: 20, y: 100 },
{ x: 0, y: 100 }
];
const area = Math.abs(calculatePolygonArea(lShape)) / 2;Shoelace Formula Principle
The Shoelace formula, also called Gauss's area formula, is a method for calculating the area of a simple polygon.
Mathematical Formula
For a polygon with n vertices ((x_1, y_1), (x_2, y_2), ..., (x_n, y_n)):
[ A = \frac{1}{2} \left| \sum_{i=1}^{n} x_i (y_{i+1} - y_{i-1}) \right| ]
The indices wrap around cyclically: (y_{n+1} = y_1), (y_0 = y_n).
Formula Expansion
Each vertex contributes:
x_i × (y_{i+1} - y_{i-1})That is, the current point's x coordinate multiplied by the next point's y minus the previous point's y.
Why It Is Called the Shoelace Formula
If you draw the diagonal multiplication process of the coordinate pairs, it resembles the crisscross lacing pattern of a shoelace.
AreaCalculationElement
Used to store area-calculation data for a single vertex.
class AreaCalculationElement {
X: number; // Current point X coordinate
Y: number; // Current point Y coordinate
YnA: number; // Next point Y coordinate
YnB: number; // Previous point Y coordinate
get area(): number; // This point's contribution to the area
}Properties
| Property | Description |
|---|---|
X | X coordinate of the current vertex |
Y | Y coordinate of the current vertex |
YnA | Y coordinate of the next vertex |
YnB | Y coordinate of the previous vertex |
area Calculation
get area(): number {
return this.X * (this.YnA - this.YnB);
}Example
import { AreaCalculationElement } from 'vjcad';
// Create one area-calculation element
const element = new AreaCalculationElement();
element.X = 100; // current x
element.Y = 50; // current y (not used in area computation)
element.YnA = 100; // next point y
element.YnB = 0; // previous point y
const contribution = element.area; // 100 * (100 - 0) = 10000AreaCalculationCollection
Manages multiple AreaCalculationElement objects and computes the total area.
class AreaCalculationCollection {
items: AreaCalculationElement[];
get doubleArea(): number; // Signed doubled area
get area(): number; // Actual area (half of doubled area)
}Example
import { AreaCalculationCollection, AreaCalculationElement } from 'vjcad';
// Rectangle: (0,0), (100,0), (100,50), (0,50)
const collection = new AreaCalculationCollection();
// Vertex 1: (0, 0)
const e1 = new AreaCalculationElement();
e1.X = 0;
e1.YnA = 0; // y of next point (100, 0)
e1.YnB = 50; // y of previous point (0, 50)
collection.items.push(e1);
// Vertex 2: (100, 0)
const e2 = new AreaCalculationElement();
e2.X = 100;
e2.YnA = 50; // y of next point (100, 50)
e2.YnB = 0; // y of previous point (0, 0)
collection.items.push(e2);
// Vertex 3: (100, 50)
const e3 = new AreaCalculationElement();
e3.X = 100;
e3.YnA = 50; // y of next point (0, 50)
e3.YnB = 0; // y of previous point (100, 0)
collection.items.push(e3);
// Vertex 4: (0, 50)
const e4 = new AreaCalculationElement();
e4.X = 0;
e4.YnA = 0; // y of next point (0, 0)
e4.YnB = 50; // y of previous point (100, 50)
collection.items.push(e4);
console.log(collection.doubleArea); // 10000 or -10000 depending on vertex order
console.log(collection.area); // 5000sortEdgeByArea() - Sort by Area
Sorts an edge array by area from largest to smallest.
function sortEdgeByArea<T extends { area: number }>(edgeArray: T[]): T[]Example
import { sortEdgeByArea } from 'vjcad';
const edges = [
{ name: 'small', area: 100 },
{ name: 'large', area: 500 },
{ name: 'medium', area: 250 }
];
const sorted = sortEdgeByArea(edges);
// sorted = [{ name: 'large', area: 500 }, { name: 'medium', area: 250 }, { name: 'small', area: 100 }]Use Case
In hatch detection, boundaries often need to be sorted by area so the largest boundary becomes the outer boundary and smaller ones become islands (inner holes):
import { sortEdgeByArea, Edge } from 'vjcad';
// Multiple detected boundaries
const boundaries: Edge[] = detectBoundaries(entities);
// Sort by area
const sorted = sortEdgeByArea(boundaries);
// Largest is the outer boundary
const outerBoundary = sorted[0];
// The rest are islands
const islands = sorted.slice(1);Practical Applications
Calculate Area of Selected Entities
import { calculatePolygonArea, Engine, PolylineEnt } from 'vjcad';
function calculateSelectedArea(): number {
const selected = Engine.getSelectedEntities();
let totalArea = 0;
for (const entity of selected) {
if (entity instanceof PolylineEnt && entity.isClosed) {
// Get polyline vertices
const vertices = entity.bulgePoints.items.map(bp => ({
x: bp.point2d.x,
y: bp.point2d.y
}));
// Calculate area (simplified; arcs are not considered)
const area = Math.abs(calculatePolygonArea(vertices)) / 2;
totalArea += area;
}
}
return totalArea;
}Determine Polygon Orientation
The sign of the Shoelace formula can be used to determine polygon winding:
function isCounterClockwise(vertices: { x: number; y: number }[]): boolean {
const doubleArea = calculatePolygonArea(vertices);
return doubleArea > 0; // Positive means counterclockwise
}Calculate Area of Polygon with Holes
function calculateAreaWithHoles(
outerBoundary: { x: number; y: number }[],
holes: { x: number; y: number }[][]
): number {
// Calculate outer boundary area
const outerArea = Math.abs(calculatePolygonArea(outerBoundary)) / 2;
// Subtract all hole areas
let holeArea = 0;
for (const hole of holes) {
holeArea += Math.abs(calculatePolygonArea(hole)) / 2;
}
return outerArea - holeArea;
}Notes
- Vertex order: vertices must be arranged in order, either clockwise or counterclockwise
- Simple polygons only: applies only to simple polygons whose edges do not intersect
- Doubled area:
calculatePolygonAreareturns doubled area, so divide by2 - Signed result: the result may be negative; use the absolute value for actual area
- Arc handling: for polylines containing arcs, discretize arcs into a point sequence first
Next Steps
- Spline Curves - B-spline curves
- Boundary Detection - using
BoundaryDetector - Selection Detection - selection-rectangle intersection tests