@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
174 lines • 6.28 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 { AcGeBox2d } from '../math';
import { AcGeGeometryUtil, AcGeMathUtil } from '../util';
import { AcGeShape2d } from './AcGeShape2d';
/**
* 2d area defined by one outter loop and multiple inner loops
*/
var AcGeArea2d = /** @class */ (function (_super) {
__extends(AcGeArea2d, _super);
/**
* Create one 2d area defined by one outter loop and multiple inner loops
*/
function AcGeArea2d() {
var _this = _super.call(this) || this;
_this._loops = [];
return _this;
}
/**
* Append one loop to loops of this area. If it is the first loop added, it is the outter loop.
* Otherwise, it is an inner loop.
* @param loop Input the loop to append
*/
AcGeArea2d.prototype.add = function (loop) {
this._loops.push(loop);
this._boundingBoxNeedsUpdate = true;
};
Object.defineProperty(AcGeArea2d.prototype, "loops", {
/**
* The loops of this area
*/
get: function () {
return this._loops;
},
enumerable: false,
configurable: true
});
Object.defineProperty(AcGeArea2d.prototype, "outter", {
/**
* Outter loop of this area
*/
get: function () {
if (this._loops.length > 0) {
return this._loops[0];
}
return undefined;
},
enumerable: false,
configurable: true
});
/**
* @inheritdoc
*/
AcGeArea2d.prototype.calculateBoundingBox = function () {
var outterLoop = this.outter;
if (outterLoop) {
return outterLoop.box;
}
else {
return new AcGeBox2d();
}
};
/**
* @inheritdoc
*/
AcGeArea2d.prototype.transform = function (_matrix) {
// TODO: implement it
this._boundingBoxNeedsUpdate = true;
return this;
};
/**
* Return boundary points of this area
* @param numPoints Input the nubmer of points returned for arc segmentation
* @returns Return points
*/
AcGeArea2d.prototype.getPoints = function (numPoints) {
var pointBoundaries = [];
for (var index = 0; index < this.loops.length; ++index) {
var loop = this.loops[index];
var points = loop.getPoints(numPoints);
pointBoundaries.push(points);
}
return pointBoundaries;
};
AcGeArea2d.prototype.buildHierarchy = function () {
var _a;
var pointBoundaries = this.getPoints(100);
var boundaryBoxes = this.calculateBoundaryBoxes(pointBoundaries);
var areaSortIndex = this.sortBoundaryBoxesByAreas(boundaryBoxes);
var indexNodeMap = new Map(); // index => IndexNode
var count = areaSortIndex.length;
for (var i = 0; i < count; i++) {
indexNodeMap.set(areaSortIndex[i], {
index: areaSortIndex[i],
children: []
});
}
var rootNode = { index: -1, children: [] };
for (var i = 0; i < count; i++) {
var index = areaSortIndex[i];
var boundary = pointBoundaries[index];
var box = boundaryBoxes[index];
var j = i + 1;
for (; j < count; j++) {
var index2 = areaSortIndex[j];
var boundary2 = pointBoundaries[index2];
var box2 = boundaryBoxes[index2];
// Determine whether the boundary is within the boundary2
if (box2.containsBox(box) &&
AcGeGeometryUtil.isPointInPolygon(boundary[AcGeMathUtil.randInt(0, boundary.length - 1)], boundary2)) {
(_a = indexNodeMap
.get(index2)) === null || _a === void 0 ? void 0 : _a.children.push(indexNodeMap.get(index));
break;
}
}
if (j === count) {
rootNode.children.push(indexNodeMap.get(index));
}
}
return rootNode;
};
/**
* Calcuate bounding box of each loop in this area and return an array of their bounding box
* @param pointBoundaries An array of loop consisted by points
* @returns Return an array of bounding box
*/
AcGeArea2d.prototype.calculateBoundaryBoxes = function (pointBoundaries) {
var boundaryBoxes = [];
pointBoundaries.forEach(function (points) {
boundaryBoxes.push(new AcGeBox2d().setFromPoints(points));
});
return boundaryBoxes;
};
/**
* Sort boundary boxes by its area and return the index of boundary boxes array
* @param boundaryBoxes An array of boundary bounding box
* @returns Return an index array of boundary bounding box sorted by its area
*/
AcGeArea2d.prototype.sortBoundaryBoxesByAreas = function (boundaryBoxes) {
var boundaryAreas = [];
boundaryBoxes.forEach(function (box, index) {
var size = box.size;
var area = size.width * size.height;
boundaryAreas.push({
area: area,
index: index
});
});
boundaryAreas.sort(function (a, b) {
return a.area - b.area;
});
var indices = [];
boundaryAreas.forEach(function (a) {
indices.push(a.index);
});
return indices;
};
return AcGeArea2d;
}(AcGeShape2d));
export { AcGeArea2d };
//# sourceMappingURL=AcGeArea2d.js.map