From e44dfcb5e3ac1e94273898dd5b2efff10af3c12f Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Mon, 25 Feb 2019 23:07:03 -0500 Subject: [PATCH] Add geoVecNormalizedDot --- modules/actions/orthogonalize.js | 23 +++++++++-------------- modules/geo/index.js | 1 + modules/geo/vector.js | 18 ++++++++++++++---- modules/ui/intro/helper.js | 25 +++++++------------------ 4 files changed, 31 insertions(+), 36 deletions(-) diff --git a/modules/actions/orthogonalize.js b/modules/actions/orthogonalize.js index 60300896e..b8410dfa7 100644 --- a/modules/actions/orthogonalize.js +++ b/modules/actions/orthogonalize.js @@ -4,10 +4,10 @@ import _uniq from 'lodash-es/uniq'; import { actionDeleteNode } from './delete_node'; import { geoVecAdd, - geoVecDot, geoVecInterp, geoVecLength, geoVecNormalize, + geoVecNormalizedDot, geoVecScale, geoVecSubtract } from '../geo'; @@ -16,7 +16,7 @@ import { /* * Based on https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/potlatch2/tools/Quadrilateralise.as */ -export function actionOrthogonalize(wayId, projection) { +export function actionOrthogonalize(wayID, projection) { var threshold = 12; // degrees within right or straight to alter var lowerThreshold = Math.cos((90 - threshold) * Math.PI / 180); var upperThreshold = Math.cos(threshold * Math.PI / 180); @@ -26,7 +26,7 @@ export function actionOrthogonalize(wayId, projection) { if (t === null || !isFinite(t)) t = 1; t = Math.min(Math.max(+t, 0), 1); - var way = graph.entity(wayId); + var way = graph.entity(wayID); var nodes = graph.childNodes(way); var points = _uniq(nodes).map(function(n) { return projection(n.loc); }); var corner = {i: 0, dotp: 1}; @@ -103,13 +103,12 @@ export function actionOrthogonalize(wayId, projection) { var c = array[(i + 1) % array.length]; var p = geoVecSubtract(a, b); var q = geoVecSubtract(c, b); - var scale, dotp; - scale = 2 * Math.min(geoVecLength(p), geoVecLength(q)); + var scale = 2 * Math.min(geoVecLength(p), geoVecLength(q)); p = geoVecNormalize(p); q = geoVecNormalize(q); - dotp = filterDotProduct(p[0] * q[0] + p[1] * q[1]); + var dotp = filterDotProduct(p[0] * q[0] + p[1] * q[1]); // nasty hack to deal with almost-straight segments (angle is closer to 180 than to 90/270). if (array.length > 3) { @@ -123,7 +122,6 @@ export function actionOrthogonalize(wayId, projection) { var vec = geoVecNormalize(geoVecAdd(p, q)); return geoVecScale(vec, 0.1 * dotp * scale); - } }; @@ -139,11 +137,9 @@ export function actionOrthogonalize(wayId, projection) { function normalizedDotProduct(i, points) { var a = points[(i - 1 + points.length) % points.length]; - var b = points[i]; - var c = points[(i + 1) % points.length]; - var p = geoVecNormalize(geoVecSubtract(a, b)); - var q = geoVecNormalize(geoVecSubtract(c, b)); - return geoVecDot(p, q); + var origin = points[i]; + var b = points[(i + 1) % points.length]; + return geoVecNormalizedDot(a, b, origin); } @@ -151,13 +147,12 @@ export function actionOrthogonalize(wayId, projection) { if (lowerThreshold > Math.abs(dotp) || Math.abs(dotp) > upperThreshold) { return dotp; } - return 0; } action.disabled = function(graph) { - var way = graph.entity(wayId); + var way = graph.entity(wayID); var nodes = graph.childNodes(way); var points = _uniq(nodes).map(function(n) { return projection(n.loc); }); diff --git a/modules/geo/index.js b/modules/geo/index.js index 04794254c..7023f31e3 100644 --- a/modules/geo/index.js +++ b/modules/geo/index.js @@ -37,5 +37,6 @@ export { geoVecFloor } from './vector.js'; export { geoVecInterp } from './vector.js'; export { geoVecLength } from './vector.js'; export { geoVecNormalize } from './vector.js'; +export { geoVecNormalizedDot } from './vector.js'; export { geoVecSubtract } from './vector.js'; export { geoVecScale } from './vector.js'; diff --git a/modules/geo/vector.js b/modules/geo/vector.js index cbdefab6c..edf6cfa86 100644 --- a/modules/geo/vector.js +++ b/modules/geo/vector.js @@ -61,8 +61,17 @@ export function geoVecAngle(a, b) { // dot product export function geoVecDot(a, b, origin) { origin = origin || [0, 0]; - return (a[0] - origin[0]) * (b[0] - origin[0]) + - (a[1] - origin[1]) * (b[1] - origin[1]); + var p = geoVecSubtract(a, origin); + var q = geoVecSubtract(b, origin); + return (p[0]) * (q[0]) + (p[1]) * (q[1]); +} + +// normalized dot product +export function geoVecNormalizedDot(a, b, origin) { + origin = origin || [0, 0]; + var p = geoVecNormalize(geoVecSubtract(a, origin)); + var q = geoVecNormalize(geoVecSubtract(b, origin)); + return geoVecDot(p, q); } // 2D cross product of OA and OB vectors, returns magnitude of Z vector @@ -70,7 +79,8 @@ export function geoVecDot(a, b, origin) { // negative for clockwise turn, and zero if the points are collinear. export function geoVecCross(a, b, origin) { origin = origin || [0, 0]; - return (a[0] - origin[0]) * (b[1] - origin[1]) - - (a[1] - origin[1]) * (b[0] - origin[0]); + var p = geoVecSubtract(a, origin); + var q = geoVecSubtract(b, origin); + return (p[0]) * (q[1]) - (p[1]) * (q[0]); } diff --git a/modules/ui/intro/helper.js b/modules/ui/intro/helper.js index 14f3f843f..cb40f4932 100644 --- a/modules/ui/intro/helper.js +++ b/modules/ui/intro/helper.js @@ -1,12 +1,7 @@ import { select as d3_select } from 'd3-selection'; import { t } from '../../util/locale'; -import { - geoSphericalDistance, - geoVecDot, - geoVecNormalize, - geoVecSubtract -} from '../../geo'; +import { geoSphericalDistance, geoVecNormalizedDot } from '../../geo'; export function pointBox(loc, context) { @@ -122,26 +117,20 @@ export function isMostlySquare(points) { var threshold = 15; // degrees within right or straight var lowerBound = Math.cos((90 - threshold) * Math.PI / 180); // near right var upperBound = Math.cos(threshold * Math.PI / 180); // near straight - var mag; for (var i = 0; i < points.length; i++) { - mag = Math.abs(normalizedDotProduct(i, points)); + var a = points[(i - 1 + points.length) % points.length]; + var origin = points[i]; + var b = points[(i + 1) % points.length]; + + var dotp = geoVecNormalizedDot(a, b, origin); + var mag = Math.abs(dotp); if (mag > lowerBound && mag < upperBound) { return false; } } return true; - - - function normalizedDotProduct(i, points) { - var a = points[(i - 1 + points.length) % points.length]; - var b = points[i]; - var c = points[(i + 1) % points.length]; - var p = geoVecNormalize(geoVecSubtract(a, b)); - var q = geoVecNormalize(geoVecSubtract(c, b)); - return geoVecDot(p, q); - } }