From 488f110d9df9fd1b5c1f6439ac5238ae5f26fdb3 Mon Sep 17 00:00:00 2001 From: Kevin Nowaczyk Date: Thu, 16 May 2024 07:14:00 -0400 Subject: [PATCH] Atan2 (#51) * update function to use atan2 --- src/building.js | 25 ++++----------------- src/extras/BuildingShapeUtils.js | 37 +++++++++++++++++++++++++++----- 2 files changed, 36 insertions(+), 26 deletions(-) diff --git a/src/building.js b/src/building.js index 030bd8c..3031323 100644 --- a/src/building.js +++ b/src/building.js @@ -96,7 +96,7 @@ class Building { } /** - * translate all lat/log values to cartesian and store in an array + * build an array of all the lat/long values of the nodes */ static buildNodeList(fullXmlData) { const nodeElements = fullXmlData.getElementsByTagName('node'); @@ -115,11 +115,12 @@ class Building { } /** - * + * convert all the longitude latitude values + * to meters from the home point. */ repositionNodes() { for (const key in this.nodelist) { - this.nodelist[key] = Building.repositionPoint(this.nodelist[key], this.home); + this.nodelist[key] = BuildingShapeUtils.repositionPoint(this.nodelist[key], this.home); } } @@ -261,24 +262,6 @@ class Building { return true; } - /** - * Rotate lat/lon to reposition the home point onto 0,0. - */ - static repositionPoint(latLon, home) { - const R = 6371 * 1000; // Earth radius in m - const circ = 2 * Math.PI * R; // Circumference - const phi = 90 - latLon[1]; - const theta = latLon[0] - home[0]; - const thetaPrime = home[1] / 180 * Math.PI; - const x = R * Math.sin(theta / 180 * Math.PI) * Math.sin(phi / 180 * Math.PI); - const y = R * Math.cos(phi / 180 * Math.PI); - const z = R * Math.sin(phi / 180 * Math.PI) * Math.cos(theta / 180 * Math.PI); - const abs = Math.sqrt(z**2 + y**2); - const arg = Math.atan(y / z) - thetaPrime; - - return [x, Math.sin(arg) * abs]; - } - /** * Get the extents of the top level building. * diff --git a/src/extras/BuildingShapeUtils.js b/src/extras/BuildingShapeUtils.js index c0f889a..9ffb112 100644 --- a/src/extras/BuildingShapeUtils.js +++ b/src/extras/BuildingShapeUtils.js @@ -243,7 +243,8 @@ class BuildingShapeUtils extends ShapeUtils { } /** - * Calculate the angle of each of a shape's edge + * Calculate the angle of each of a shape's edge. + * the angle will be PI > x >= -PI * * @param {THREE.Shape} shape - the shape * @@ -251,17 +252,21 @@ class BuildingShapeUtils extends ShapeUtils { */ static edgeDirection(shape) { const points = shape.extractPoints().shape; + points.push(points[0]); const angles = []; var p1; var p2; for (let i = 0; i < points.length - 1; i++) { p1 = points[i]; p2 = points[i + 1]; - angles.push(Math.atan((p2.y - p1.y) / (p2.x - p1.x))); + let angle = Math.atan2((p2.y - p1.y), (p2.x - p1.x)); + if (angle >= Math.PI / 2) { + angle -= Math.PI; + } else if (angle < -Math.PI / 2) { + angle += Math.PI; + } + angles.push(angle); } - p1 = points[points.length - 1]; - p2 = points[0]; - angles.push(Math.atan((p2.y - p1.y) / (p2.x - p1.x))); return angles; } @@ -328,5 +333,27 @@ class BuildingShapeUtils extends ShapeUtils { } return angle; } + + /** + * Rotate lat/lon to reposition the home point onto 0,0. + * + * @param {[number, number]} lonLat - The longitute and latitude of a point. + * + * @return {[number, number]} x, y in meters + */ + static repositionPoint(lonLat, home) { + const R = 6371 * 1000; // Earth radius in m + const circ = 2 * Math.PI * R; // Circumference + const phi = 90 - lonLat[1]; + const theta = lonLat[0] - home[0]; + const thetaPrime = home[1] / 180 * Math.PI; + const x = R * Math.sin(theta / 180 * Math.PI) * Math.sin(phi / 180 * Math.PI); + const y = R * Math.cos(phi / 180 * Math.PI); + const z = R * Math.sin(phi / 180 * Math.PI) * Math.cos(theta / 180 * Math.PI); + const abs = Math.sqrt(z**2 + y**2); + const arg = Math.atan(y / z) - thetaPrime; + + return [x, Math.sin(arg) * abs]; + } } export {BuildingShapeUtils};