@mlightcad/geometry-engine
Version:
The geometry-engine package provides comprehensive geometric entities, mathematical operations, and transformations for 2D and 3D space. This package mimics AutoCAD ObjectARX's AcGe (Geometry) classes and provides the mathematical foundation for CAD opera
292 lines • 11.2 kB
JavaScript
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
import { AcCmErrors } from '@mlightcad/common';
import { AcGeBox2d, AcGePoint2d, AcGePoint3d } from '../math';
import { AcGeMathUtil, TAU } from '../util';
import { AcGeCurve2d } from './AcGeCurve2d';
/**
* Class representing a 3d ellipse arc defined by center, normal, majorAxis, majorAxisRadius,
* minorAxisRadius, startAngle, and endAngle.
* - The majorAxis vector represents half the major axis of the ellipse (that is, from the center
* point to the start point of the ellipse) and is the zero angle for startAngle and endAngle.
* - Positive angles are counter-clockwise when looking down the normal vector (that is, right-hand
* rule). A startAngle of 0 and endAngle of 2pi will produce a closed Ellipse.
* - If startAngle is equal to 0 and endAngle is equal to 2 * Math.PI, it represents a full 3d ellipse.
*/
var AcGeEllipseArc2d = /** @class */ (function (_super) {
__extends(AcGeEllipseArc2d, _super);
/**
* Construct an instance of the ellipse arc.
* @param center Center point of the ellipse.
* @param majorAxisRadius Major axis radius of the ellipse.
* @param minorAxisRadius Minor axis radius of the ellipse.
* @param startAngle Start angle of the ellipse arc in radians.
* @param endAngle End angle of the ellipse arc in radians.
* @param clockwise The flag Whether the ellipse arc is drawn clockwise. Default is false.
* @param rotation The rotation angle of the ellipse in radians, counterclockwise from the positive X
* axis (optional). Default is 0.
*/
function AcGeEllipseArc2d(center, majorAxisRadius, minorAxisRadius, startAngle, endAngle, clockwise, rotation) {
if (startAngle === void 0) { startAngle = 0; }
if (endAngle === void 0) { endAngle = TAU; }
if (clockwise === void 0) { clockwise = false; }
if (rotation === void 0) { rotation = 0; }
var _this = _super.call(this) || this;
_this.center = center;
_this.majorAxisRadius = majorAxisRadius;
_this.minorAxisRadius = minorAxisRadius;
// Check whether it is a full ellipse
if ((endAngle - startAngle) % TAU == 0) {
_this.startAngle = 0;
_this.endAngle = TAU;
}
else {
_this.startAngle = startAngle;
_this.endAngle = endAngle;
}
_this.clockwise = clockwise;
_this.rotation = rotation;
return _this;
}
Object.defineProperty(AcGeEllipseArc2d.prototype, "center", {
/**
* Center of the ellipse in 3d space
*/
get: function () {
return this._center;
},
set: function (value) {
this._center = new AcGePoint3d(value.x, value.y, value.z || 0);
this._boundingBoxNeedsUpdate = true;
},
enumerable: false,
configurable: true
});
Object.defineProperty(AcGeEllipseArc2d.prototype, "majorAxisRadius", {
/**
* Major axis radius of the ellipse
*/
get: function () {
return this._majorAxisRadius;
},
set: function (value) {
if (value < 0)
throw AcCmErrors.ILLEGAL_PARAMETERS;
this._majorAxisRadius = value;
this._boundingBoxNeedsUpdate = true;
},
enumerable: false,
configurable: true
});
Object.defineProperty(AcGeEllipseArc2d.prototype, "minorAxisRadius", {
/**
* Minor axis radius of the ellipse
*/
get: function () {
return this._minorAxisRadius;
},
set: function (value) {
if (value < 0)
throw AcCmErrors.ILLEGAL_PARAMETERS;
this._minorAxisRadius = value;
this._boundingBoxNeedsUpdate = true;
},
enumerable: false,
configurable: true
});
Object.defineProperty(AcGeEllipseArc2d.prototype, "startAngle", {
/**
* Start angle of the ellipse arc in radians in the range -pi to pi.
*/
get: function () {
return this._startAngle;
},
set: function (value) {
this._startAngle = AcGeMathUtil.normalizeAngle(value);
this._boundingBoxNeedsUpdate = true;
},
enumerable: false,
configurable: true
});
Object.defineProperty(AcGeEllipseArc2d.prototype, "endAngle", {
/**
* End angle of the ellipse arc in radians in the range -pi to pi.
*/
get: function () {
return this._endAngle;
},
set: function (value) {
this._endAngle =
this.startAngle == 0 && value == TAU
? value
: AcGeMathUtil.normalizeAngle(value);
this._boundingBoxNeedsUpdate = true;
},
enumerable: false,
configurable: true
});
Object.defineProperty(AcGeEllipseArc2d.prototype, "clockwise", {
/**
* The flag Whether the ellipse arc is drawn clockwise. Default is false.
*/
get: function () {
return this._clockwise;
},
set: function (value) {
this._clockwise = value;
this._boundingBoxNeedsUpdate = true;
},
enumerable: false,
configurable: true
});
Object.defineProperty(AcGeEllipseArc2d.prototype, "rotation", {
/**
* The rotation angle of the ellipse in radians, counterclockwise from the positive X axis (optional).
* Default is 0.
*/
get: function () {
return this._rotation;
},
set: function (value) {
this._rotation = value;
this._boundingBoxNeedsUpdate = true;
},
enumerable: false,
configurable: true
});
Object.defineProperty(AcGeEllipseArc2d.prototype, "deltaAngle", {
/**
* Return angle between endAngle and startAngle in range 0 to 2*PI
*/
get: function () {
return AcGeMathUtil.normalizeAngle(this.endAngle - this.startAngle);
},
enumerable: false,
configurable: true
});
Object.defineProperty(AcGeEllipseArc2d.prototype, "isLargeArc", {
/**
* Return true if the arc is a large arc whose delta angle value is greater than PI.
*/
get: function () {
return Math.abs(this.deltaAngle) > Math.PI ? 1 : 0;
},
enumerable: false,
configurable: true
});
/**
* Compute the bounding box of the 3D ellipse arc.
* The bounding box is defined by its minimum and maximum x, y, and z coordinates.
* @returns Return bounding box containing the min and max coordinates
*/
AcGeEllipseArc2d.prototype.calculateBoundingBox = function () {
var numPoints = 100;
var minX = Infinity, minY = Infinity;
var maxX = -Infinity, maxY = -Infinity;
for (var i = 0; i <= numPoints; i++) {
var point = this.getPoint(i / numPoints);
minX = Math.min(minX, point.x);
minY = Math.min(minY, point.y);
maxX = Math.max(maxX, point.x);
maxY = Math.max(maxY, point.y);
}
// Return the bounding box defined by min and max coordinates
return new AcGeBox2d({ x: minX, y: minY }, { x: maxX, y: maxY });
};
Object.defineProperty(AcGeEllipseArc2d.prototype, "closed", {
/**
* Return true if its start point is identical to its end point. Otherwise, return false.
*/
get: function () {
return this.deltaAngle == 0;
},
enumerable: false,
configurable: true
});
/**
* Return the point for a given position on the curve according to the arc length.
* @param t Input a position on the curve according to the arc length. Must be in the range [ 0, 1 ].
* @returns Return the point for a given position on the curve according to the arc length.
*/
AcGeEllipseArc2d.prototype.getPoint = function (t) {
var twoPi = Math.PI * 2;
var deltaAngle = this.endAngle - this.startAngle;
var samePoints = Math.abs(deltaAngle) < Number.EPSILON;
// ensures that deltaAngle is 0 .. 2 PI
while (deltaAngle < 0)
deltaAngle += twoPi;
while (deltaAngle > twoPi)
deltaAngle -= twoPi;
if (deltaAngle < Number.EPSILON) {
if (samePoints) {
deltaAngle = 0;
}
else {
deltaAngle = twoPi;
}
}
if (this.clockwise === true && !samePoints) {
if (deltaAngle === twoPi) {
deltaAngle = -twoPi;
}
else {
deltaAngle = deltaAngle - twoPi;
}
}
var angle = this.startAngle + t * deltaAngle;
var x = this.center.x + this.majorAxisRadius * Math.cos(angle);
var y = this.center.y + this.minorAxisRadius * Math.sin(angle);
if (this.rotation !== 0) {
var cos = Math.cos(this.rotation);
var sin = Math.sin(this.rotation);
var tx = x - this.center.x;
var ty = y - this.center.y;
// Rotate the point about the center of the ellipse.
x = tx * cos - ty * sin + this.center.x;
y = tx * sin + ty * cos + this.center.y;
}
return new AcGePoint2d(x, y);
};
/**
* @inheritdoc
*/
AcGeEllipseArc2d.prototype.transform = function (_matrix) {
this._boundingBoxNeedsUpdate = true;
return this;
};
/**
* @inheritdoc
*/
AcGeEllipseArc2d.prototype.copy = function (value) {
this.center = value.center;
this.majorAxisRadius = value.majorAxisRadius;
this.minorAxisRadius = value.minorAxisRadius;
this.startAngle = value.startAngle;
this.endAngle = value.endAngle;
this.clockwise = value.clockwise;
this.rotation = value.rotation;
return this;
};
/**
* @inheritdoc
*/
AcGeEllipseArc2d.prototype.clone = function () {
return new AcGeEllipseArc2d(this.center, this.majorAxisRadius, this.minorAxisRadius, this.startAngle, this.endAngle, this.clockwise, this.rotation);
};
return AcGeEllipseArc2d;
}(AcGeCurve2d));
export { AcGeEllipseArc2d };
//# sourceMappingURL=AcGeEllipseArc2d.js.map