"use strict"
const geoRegPolyModule = require('./geo-reg-poly');
const reinforcementModule = require('./reinforcement');
/**
* Finds the central point (avg.) between the given points
* @param {number[]} points
* @memberof calcs.geometry.points
* @returns central point (avg.) between the given points
*/
const ptCentroid = (points, mode = '3d') => {
const min = [Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER]
const max = [Number.MIN_SAFE_INTEGER, Number.MIN_SAFE_INTEGER, Number.MIN_SAFE_INTEGER]
points.forEach(pt => {
min[0] = Math.min(min[0], pt[0])
min[1] = Math.min(min[1], pt[1])
max[0] = Math.max(max[0], pt[0])
max[1] = Math.max(max[1], pt[1])
if (mode === '3d') {
min[2] = Math.min(min[2], pt[2])
max[2] = Math.max(max[2], pt[2])
}
})
let output = [
(max[0] + min[0]) / 2,
(max[1] + min[1]) / 2,
]
if (mode === '3d') {
output = [...output, (max[2] + min[2]) / 2]
}
return output;
}
/**
* Geometry
* @memberof calcs
* @namespace geometry
*/
const geometryInit = ({ jscad, swcadJs }) => {
const { math } = swcadJs.calcs;
const { constants } = swcadJs.data;
/**
* ...
* @memberof calcs.geometry
* @param {*} startPt
* @param {*} endPt
* @param {*} mode
* @returns ...
*/
const angleOfTwoPtLine = (startPt, endPt, mode = 'rad') => {
const diffY = endPt[1] - startPt[1]
const diffX = endPt[0] - startPt[0]
const angleRad = Math.atan2(diffY, diffX)
const angleDeg = angleRad * (180 / Math.PI)
return mode == 'deg' ? angleDeg : angleRad
}
/**
* ...
* @memberof calcs.geometry
* @param {*} angleRad
* @param {*} dist
* @returns ...
*/
const pointFromAngleAndDist = (angleRad, dist) => {
const x = dist * Math.cos(angleRad)
const y = dist * Math.sin(angleRad)
return [x, y]
}
/**
* Gets line data from outline points
* @param {*} outlinePts
* @returns array of line details
* @memberof calcs.geometry
* @private
*/
const getLineDataFromOutlinePoints = (outlinePts) => {
const lineData = []
for (let ptIdx = 0; ptIdx < outlinePts.length - 1; ptIdx++) {
const startPt = outlinePts[ptIdx];
const endPt = outlinePts[ptIdx + 1];
const coordDiffs = [
endPt[0] - startPt[0],
endPt[1] - startPt[1],
]
const midPt = [
startPt[0] + (coordDiffs[0] / 2),
startPt[1] + (coordDiffs[1] / 2),
]
const lineLength = Math.hypot(coordDiffs[0], coordDiffs[1])
const lineAngle = angleOfTwoPtLine(startPt, endPt)
lineData.push({
start: startPt,
end: endPt,
mid: midPt,
length: lineLength,
angle: lineAngle,
})
}
return lineData
}
/**
* Gets triangular points in area
* @memberof calcs.geometry
* @param {*} x
* @param {*} y
* @param {*} distance
* @param {*} centrePoints
* @returns ...
*/
const getTriangularPtsInArea = (x, y, distance, centrePoints = true) => {
const halfDist = distance / 2;
const allPoints = [];
const allYCoords = [];
let yCoordCtr = 0;
do {
allYCoords.push(yCoordCtr);
yCoordCtr = distance * constants.EQUI_TRIANGLE_HEIGHT_FACTOR + yCoordCtr;
} while (yCoordCtr < y);
const hasOffsetCollision = false
let yIdxCtr = 0;
do {
let xCtr = 0;
do {
if (math.isEven(yIdxCtr)) {
allPoints.push({ x: xCtr, y: allYCoords[yIdxCtr] });
} else {
if (halfDist + xCtr <= x) {
allPoints.push({ x: halfDist + xCtr, y: allYCoords[yIdxCtr] });
}
}
xCtr = xCtr + distance;
} while (xCtr < x);
yIdxCtr = yIdxCtr + 1;
} while (yIdxCtr < allYCoords.length);
if (!centrePoints) {
return allPoints
}
const simplePts = allPoints.map(pt => [pt.x, pt.y])
const pointCentroid = ptCentroid(simplePts, '2d');
return allPoints.map(pt => {
return {
x: pt.x - pointCentroid[0],
y: pt.y - pointCentroid[1],
}
});
}
/**
* Gets square points in area
* @memberof calcs.geometry
* @param {*} x
* @param {*} y
* @param {*} distance
* @param {*} centrePoints
* @returns ...
*/
const getSquarePtsInArea = (x, y, distance, centrePoints = true) => {
const halfDist = distance / 2;
const allXCoords = [];
let xCtr = 0;
do {
allXCoords.push(xCtr);
xCtr = xCtr + distance;
} while (xCtr <= x);
const allYCoords = [];
let yCtr = 0;
do {
allYCoords.push(yCtr);
yCtr = yCtr + distance;
} while (yCtr <= y);
const allPoints = math.arrayCartesianProduct(allXCoords, allYCoords);
const outPts = allPoints.map(pt => { return { x: pt[0], y: pt[1] } });
if (!centrePoints) {
return outPts
}
const simplePts = outPts.map(pt => [pt.x, pt.y])
const pointCentroid = ptCentroid(simplePts, '2d');
return outPts.map(pt => {
return {
x: pt.x - pointCentroid[0],
y: pt.y - pointCentroid[1],
}
});
}
/**
* Functions related to sets of Cartesian points
* @memberof calcs.geometry
* @namespace points
*/
const points = {
centroid: ptCentroid,
}
const regPoly = geoRegPolyModule.init({ jscad, swcadJs })
const reinforcement = reinforcementModule.init({ jscad, swcadJs })
return {
angleOfTwoPtLine,
pointFromAngleAndDist,
getLineDataFromOutlinePoints,
getTriangularPtsInArea,
getSquarePtsInArea,
points,
regPoly,
reinforcement,
}
}
module.exports = { init: geometryInit };