Skip to content

Commit

Permalink
Longest side (#50)
Browse files Browse the repository at this point in the history
* created tests
* simplified findlongestside function
  • Loading branch information
Beakerboy authored May 15, 2024
1 parent 0ec5931 commit f9c1bcf
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 42 deletions.
60 changes: 25 additions & 35 deletions src/extras/BuildingShapeUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,10 @@ class BuildingShapeUtils extends ShapeUtils {

/**
* Calculate the length of each of a shape's edge
*
* @param {THREE.Shape} shape - the shape
*
* @return {[number, ...]} the esge lwngths.
*/
static edgeLength(shape) {
const points = shape.extractPoints().shape;
Expand Down Expand Up @@ -240,6 +244,10 @@ class BuildingShapeUtils extends ShapeUtils {

/**
* Calculate the angle of each of a shape's edge
*
* @param {THREE.Shape} shape - the shape
*
* @return {[number, ...]} the angles in radians.
*/
static edgeDirection(shape) {
const points = shape.extractPoints().shape;
Expand All @@ -251,6 +259,9 @@ class BuildingShapeUtils extends ShapeUtils {
p2 = points[i + 1];
angles.push(Math.atan((p2.y - p1.y) / (p2.x - p1.x)));
}
p1 = points[points.length - 1];
p2 = points[0];
angles.push(Math.atan((p2.y - p1.y) / (p2.x - p1.x)));
return angles;
}

Expand Down Expand Up @@ -298,45 +309,24 @@ class BuildingShapeUtils extends ShapeUtils {
* @return {number}
*/
static longestSideAngle(shape) {
const newVecs = [];
const newShape = new Shape();
const vecs = shape.extractPoints().shape;
var p0 = vecs[vecs.length - 2];
var p1;
var p2;
for (let i = 0; i < vecs.length - 1; i++) {
p1 = vecs[i];
p2 = vecs[i + 1];
// Calculate angle
const angle = Math.atan2(p2.y - p1.y, p2.x - p1.x) - Math.atan2(p0.y - p1.y, p0.x - p1.x);

// Discard the point if within half a degree of 180.
if (Math.abs(angle - Math.PI) > Math.PI / 360 / 2 ) {
newVecs.push(p1);
const lengths = BuildingShapeUtils.edgeLength(shape);
const directions = BuildingShapeUtils.edgeDirection(shape);
var index;
var maxLength = 0;
for (let i = 0; i < lengths.length; i++) {
if (lengths[i] > maxLength) {
index = i;
maxLength = lengths[i];
}
p0 = p1;
}
if (newVecs.length > 0) {
// convert newVecs into newShape
newShape.setFromPoints(newVecs);
const lengths = BuildingShapeUtils.edgeLength(newShape);
const directions = BuildingShapeUtils.edgeDirection(newShape);
var index;
var maxLength = 0;
for (let i = 0; i < lengths.length; i++) {
if (lengths[i] > maxLength) {
index = i;
maxLength = lengths[i];
}
}
var angle = directions[index];
const extents = BuildingShapeUtils.extents(newShape, Math.PI * 2 - angle);
// If the shape is taller than it is wide after rotation, we are off by 90 degrees.
if ((extents[3] - extents[1]) > (extents[2] - extents[0])) {
angle = angle > Math.PI / 2 ? angle - Math.PI / 2 : angle + Math.PI / 2;
}
return angle;
var angle = directions[index];
const extents = BuildingShapeUtils.extents(shape, -angle);
// If the shape is taller than it is wide after rotation, we are off by 90 degrees.
if ((extents[3] - extents[1]) > (extents[2] - extents[0])) {
angle = angle > 0 ? angle - Math.PI / 2 : angle + Math.PI / 2;
}
return angle;
}
}
export {BuildingShapeUtils};
32 changes: 25 additions & 7 deletions test/utils.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,31 @@ test('Test combining 2 ways', () => {
expect(result[0].outerHTML).toBe(way3);
});

test('Extents no rotation', () => {
const shape = new Shape();
shape.moveTo(1, 1);
shape.lineTo(1, -1);
shape.lineTo(-1, 1);
expect(BuildingShapeUtils.extents(shape)).toStrictEqual([-1, -1, 1, 1]);
const rightTriangle = new Shape();
rightTriangle.moveTo(1, 1);
rightTriangle.lineTo(1, -1);
rightTriangle.lineTo(-1, 1);

test('Extents no Rotation', () => {
expect(BuildingShapeUtils.extents(rightTriangle)).toStrictEqual([-1, -1, 1, 1]);
});

test('Extents Rotation', () => {
const angle = 45 / 360 * 2 * 3.1415926535;
const sqrt2 = Math.sqrt(2);
expect(BuildingShapeUtils.extents(shape, angle)).toBeDeepCloseTo([-sqrt2, 0, sqrt2, sqrt2], 10);
expect(BuildingShapeUtils.extents(rightTriangle, angle)).toBeDeepCloseTo([-sqrt2, 0, sqrt2, sqrt2], 10);
});

test('Edge Lengths', () => {
expect(BuildingShapeUtils.edgeLength(rightTriangle)).toBeDeepCloseTo([2, Math.sqrt(2) * 2, 2]);
});

test('Edge Direction', () => {
expect(BuildingShapeUtils.edgeDirection(rightTriangle)).toBeDeepCloseTo([-Math.PI / 2, -Math.PI / 4, 0]);
});

test('Longest side angle', () => {
// A three.Shape object does not repeat the fist and last nodes.
expect(rightTriangle.extractPoints().shape.length).toBe(3);
expect(BuildingShapeUtils.longestSideAngle(rightTriangle)).toBe(-Math.PI / 4);
});

0 comments on commit f9c1bcf

Please sign in to comment.