From 86d44bdd00ec1b78f29e0919d01f9b037c185e3b Mon Sep 17 00:00:00 2001 From: mcben Date: Thu, 5 Jun 2014 14:31:56 +0200 Subject: [PATCH 01/10] new plugin: cross links this plugin colors links red if they are crossing a drawnline. any yellow if they are inside a drawn polygon. (requires DrawTools) --- plugins/cross_link.user.js | 188 +++++++++++++++++++++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 plugins/cross_link.user.js diff --git a/plugins/cross_link.user.js b/plugins/cross_link.user.js new file mode 100644 index 00000000..a6b304dd --- /dev/null +++ b/plugins/cross_link.user.js @@ -0,0 +1,188 @@ +// ==UserScript== +// @id iitc-plugin-cross-links@mcben +// @name IITC plugin: cross links +// @category Layer +// @version 1.0.@@DATETIMEVERSION@@ +// @namespace https://github.com/jonatkins/ingress-intel-total-conversion +// @updateURL @@UPDATEURL@@ +// @downloadURL @@DOWNLOADURL@@ +// @description [McBen] requires drawtool! coloring of link collision +// @include https://www.ingress.com/intel* +// @include http://www.ingress.com/intel* +// @match https://www.ingress.com/intel* +// @match http://www.ingress.com/intel* +// @grant none +// ==/UserScript== + +@@PLUGINSTART@@ + +// PLUGIN START //////////////////////////////////////////////////////// + +// use own namespace for plugin +window.plugin.crossLinks = function() {}; + +window.plugin.crossLinks.STYLE_LINECOLLISION = {color: '#f22', weight: 4}; +window.plugin.crossLinks.STYLE_INSIDEPOLY = {color: '#ff2', weight: 4}; + + +function relativeCCW(x1,y1,x2,y2, px, py) { + // code from java.awt + x2 -= x1; + y2 -= y1; + px -= x1; + py -= y1; + + var ccw = px * y2 - py * x2; + + if (ccw == 0.0) { + ccw = px * x2 + py * y2; + + if (ccw > 0.0) { + px -= x2; + py -= y2; + ccw = px * x2 + py * y2; + + if (ccw < 0.0) { + ccw = 0.0; + } + } + } + return (ccw < 0.0) ? -1 : ((ccw > 0.0) ? 1 : 0); + } + +function linesIntersect(x1,y1,x2,y2,x3,y3,x4,y4) { + // code from java.awt + return ( (relativeCCW(x1, y1, x2, y2, x3, y3) * relativeCCW(x1, y1, x2, y2, x4, y4) <= 0) + && (relativeCCW(x3, y3, x4, y4, x1, y1) * relativeCCW(x3, y3, x4, y4, x2, y2) <= 0)); +} + +function isCrossing(p1,p2,q1,q2) { + return linesIntersect( p1.lat,p1.lng,p2.lat,p2.lng, + q1.lat,q1.lng,q2.lat,q2.lng); +} + +window.plugin.crossLinks.testLine = function (drawline, link) { + + var linkline= L.geodesicConvertLines(link._latlngs,0); + + for (var j=0;j point.lng) != (p2.lng>point.lng)) && + (point.lat < (p2.lat - p1.lat)*(point.lng-p1.lng) / (p2.lng-p1.lng) + p1.lat)) + c = !c; + + p2 = p1; + } + return c; +} + +window.plugin.crossLinks.testPolygons = function (polygons, link) { + + var linkline= L.geodesicConvertLines(link._latlngs,0); + + for (var pidx=0;pidx Date: Tue, 10 Jun 2014 17:37:11 +0200 Subject: [PATCH 02/10] cross-links: replaced intersection approximation (inside polygons has to be rewritten) --- plugins/cross_link.user.js | 191 ++++++++++++++++++++++++------------- 1 file changed, 126 insertions(+), 65 deletions(-) diff --git a/plugins/cross_link.user.js b/plugins/cross_link.user.js index a6b304dd..f120dffc 100644 --- a/plugins/cross_link.user.js +++ b/plugins/cross_link.user.js @@ -25,52 +25,113 @@ window.plugin.crossLinks.STYLE_LINECOLLISION = {color: '#f22', weight: 4}; window.plugin.crossLinks.STYLE_INSIDEPOLY = {color: '#ff2', weight: 4}; -function relativeCCW(x1,y1,x2,y2, px, py) { - // code from java.awt - x2 -= x1; - y2 -= y1; - px -= x1; - py -= y1; +// Great Circle Arc Intersection +// http://geospatialmethods.org/spheres/GCAIntersect.html +function intersect(a, b) { + var PI = Math.PI, + radians = PI / 180, + ε = 1e-6; - var ccw = px * y2 - py * x2; + var λ0 = a[0][0], + λ1 = a[1][0], + λ2 = b[0][0], + λ3 = b[1][0], + δλ0 = λ1 - λ0, + δλ1 = λ3 - λ2, + aδλ0 = Math.abs(δλ0), + aδλ1 = Math.abs(δλ1), + sλ0 = aδλ0 > 180, + sλ1 = aδλ1 > 180, + φ0 = a[0][1] * radians, + φ1 = a[1][1] * radians, + φ2 = b[0][1] * radians, + φ3 = b[1][1] * radians, + t; - if (ccw == 0.0) { - ccw = px * x2 + py * y2; + // Ensure λ0 ≤ λ1 and λ2 ≤ λ3. + if (δλ0 < 0) t = λ0, λ0 = λ1, λ1 = t, t = φ0, φ0 = φ1, φ1 = t; + if (δλ1 < 0) t = λ2, λ2 = λ3, λ3 = t, t = φ2, φ2 = φ3, φ3 = t; - if (ccw > 0.0) { - px -= x2; - py -= y2; - ccw = px * x2 + py * y2; + // Check if longitude ranges overlap. + // TODO handle antimeridian crossings. + if (!sλ0 && !sλ1 && (λ0 > λ3 || λ2 > λ1)) return; - if (ccw < 0.0) { - ccw = 0.0; - } - } - } - return (ccw < 0.0) ? -1 : ((ccw > 0.0) ? 1 : 0); - } + // Check for polar endpoints. + if (Math.abs(Math.abs(φ0) - PI / 2) < ε) λ0 = λ1, aδλ0 = δλ0 = 0, sλ0 = false; + if (Math.abs(Math.abs(φ1) - PI / 2) < ε) λ1 = λ0, aδλ0 = δλ0 = 0, sλ0 = false; + if (Math.abs(Math.abs(φ2) - PI / 2) < ε) λ2 = λ3, aδλ1 = δλ1 = 0, sλ1 = false; + if (Math.abs(Math.abs(φ3) - PI / 2) < ε) λ3 = λ2, aδλ1 = δλ1 = 0, sλ1 = false; -function linesIntersect(x1,y1,x2,y2,x3,y3,x4,y4) { - // code from java.awt - return ( (relativeCCW(x1, y1, x2, y2, x3, y3) * relativeCCW(x1, y1, x2, y2, x4, y4) <= 0) - && (relativeCCW(x3, y3, x4, y4, x1, y1) * relativeCCW(x3, y3, x4, y4, x2, y2) <= 0)); + // Check for arcs along meridians. + var m0 = aδλ0 < ε || Math.abs(aδλ0 - 180) < ε, + m1 = aδλ1 < ε || Math.abs(aδλ1 - 180) < ε; + + λ0 *= radians, λ1 *= radians, λ2 *= radians, λ3 *= radians; + + // Intersect two great circles and check the two intersection points against + // the longitude ranges. The intersection points are simply the cross + // product of the great-circle normals ±n1⨯n2. + + // First plane. + var cosφ, + x0 = (cosφ = Math.cos(φ0)) * Math.cos(λ0), + y0 = cosφ * Math.sin(λ0), + z0 = Math.sin(φ0), + x1 = (cosφ = Math.cos(φ1)) * Math.cos(λ1), + y1 = cosφ * Math.sin(λ1), + z1 = Math.sin(φ1), + n0x = y0 * z1 - z0 * y1, + n0y = z0 * x1 - x0 * z1, + n0z = x0 * y1 - y0 * x1, + m = length(n0x, n0y, n0z); + + n0x /= m, n0y /= m, n0z /= m; + + // Second plane. + var x2 = (cosφ = Math.cos(φ2)) * Math.cos(λ2), + y2 = cosφ * Math.sin(λ2), + z2 = Math.sin(φ2), + x3 = (cosφ = Math.cos(φ3)) * Math.cos(λ3), + y3 = cosφ * Math.sin(λ3), + z3 = Math.sin(φ3), + n1x = y2 * z3 - z2 * y3, + n1y = z2 * x3 - x2 * z3, + n1z = x2 * y3 - y2 * x3, + m = length(n1x, n1y, n1z); + + n1x /= m, n1y /= m, n1z /= m; + + var Nx = n0y * n1z - n0z * n1y, + Ny = n0z * n1x - n0x * n1z, + Nz = n0x * n1y - n0y * n1x; + + if (length(Nx, Ny, Nz) < ε) return; + + var λ = Math.atan2(Ny, Nx); + if ((sλ0 ^ (λ0 <= λ && λ <= λ1) || m0 && Math.abs(λ - λ0) < ε) && (sλ1 ^ (λ2 <= λ && λ <= λ3) || m1 && Math.abs(λ - λ2) < ε) || (Nz = -Nz, + (sλ0 ^ (λ0 <= (λ = (λ + 2 * PI) % (2 * PI) - PI) && λ <= λ1) || m0 && Math.abs(λ - λ0) < ε) && (sλ1 ^ (λ2 <= λ && λ <= λ3) || m1 && Math.abs(λ - λ2) < ε))) { + var φ = Math.asin(Nz / length(Nx, Ny, Nz)); + if (m0 || m1) { + if (m1) φ0 = φ2, φ1 = φ3, λ0 = λ2, λ1 = λ3, aδλ0 = aδλ1; + if (aδλ0 > ε) return φ0 + φ1 > 0 ^ φ < (Math.abs(λ - λ0) < ε ? φ0 : φ1) ? [λ / radians, φ / radians] : null; + // Ensure φ0 ≤ φ1. + if (φ1 < φ0) t = φ0, φ0 = φ1, φ1 = t; + return Math.abs(λ - (m0 ? λ0 : λ2)) < ε && φ0 <= φ && φ <= φ1 ? [λ / radians, φ / radians] : null; + } + return [λ / radians, φ / radians]; + } } -function isCrossing(p1,p2,q1,q2) { - return linesIntersect( p1.lat,p1.lng,p2.lat,p2.lng, - q1.lat,q1.lng,q2.lat,q2.lng); +function length(x, y, z) { + return Math.sqrt(x * x + y * y + z * z); } -window.plugin.crossLinks.testLine = function (drawline, link) { +window.plugin.crossLinks.testPolyLine = function (polyline, link) { + var a= [[link[0].lat,link[0].lng],[link[1].lat,link[1].lng]]; + for (var i=0;i Date: Tue, 10 Jun 2014 19:12:16 +0200 Subject: [PATCH 03/10] cross-links: moved to extra layer --- plugins/cross_link.user.js | 56 +++++++++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 13 deletions(-) diff --git a/plugins/cross_link.user.js b/plugins/cross_link.user.js index f120dffc..2a0542aa 100644 --- a/plugins/cross_link.user.js +++ b/plugins/cross_link.user.js @@ -18,13 +18,8 @@ // PLUGIN START //////////////////////////////////////////////////////// -// use own namespace for plugin window.plugin.crossLinks = function() {}; -window.plugin.crossLinks.STYLE_LINECOLLISION = {color: '#f22', weight: 4}; -window.plugin.crossLinks.STYLE_INSIDEPOLY = {color: '#ff2', weight: 4}; - - // Great Circle Arc Intersection // http://geospatialmethods.org/spheres/GCAIntersect.html function intersect(a, b) { @@ -164,6 +159,8 @@ window.plugin.crossLinks.testPolygons = function (polygons, link) { } window.plugin.crossLinks.onLinkAdded = function (data) { + if (window.plugin.crossLinks.disabled) return; + window.plugin.crossLinks.linkLayer.bringToFront(); // FIXME: workaround to keep it on above the link-layer var link = data.link; @@ -172,7 +169,7 @@ window.plugin.crossLinks.onLinkAdded = function (data) { latlngs = layer.getLatLngs(); latlngs.push(latlngs[0]); if (window.plugin.crossLinks.testPolyLine(latlngs, link.getLatLngs())) { - link.setStyle (window.plugin.crossLinks.STYLE_LINECOLLISION); + plugin.crossLinks.showLink(link.getLatLngs()); } // TODO: rework inside-polygons /* @@ -184,31 +181,32 @@ window.plugin.crossLinks.onLinkAdded = function (data) { } else if (layer instanceof L.GeodesicPolyline) { if (window.plugin.crossLinks.testPolyLine(layer.getLatLngs(), link.getLatLngs())) { - link.setStyle (window.plugin.crossLinks.STYLE_LINECOLLISION); + plugin.crossLinks.showLink(link.getLatLngs()); } } }); } window.plugin.crossLinks.checkAllLinks = function() { - console.debug("Cross-Links: checking links"); + console.debug("Cross-Links: checking links"); + if (window.plugin.crossLinks.disabled) return; - // check all links - $.each(window.links, function(guid, link) { + plugin.crossLinks.linkLayer.clearLayers(); - link.setStyle ({color: COLORS[link.options.team], weight: 2}); + // check all links + $.each(window.links, function(guid, link) { window.plugin.drawTools.drawnItems.eachLayer( function(layer) { if (layer instanceof L.GeodesicPolyline) { if (window.plugin.crossLinks.testPolyLine(layer.getLatLngs(), link.getLatLngs())) { - link.setStyle(window.plugin.crossLinks.STYLE_LINECOLLISION); + plugin.crossLinks.showLink(link.getLatLngs()); return false; } } else if (layer instanceof L.GeodesicPolygon) { latlngs = layer.getLatLngs(); latlngs.push(latlngs[0]); if (window.plugin.crossLinks.testPolyLine(latlngs, link.getLatLngs())) { - link.setStyle (window.plugin.crossLinks.STYLE_LINECOLLISION); + plugin.crossLinks.showLink(link.getLatLngs()); } // TODO: rework inside-polygons } @@ -216,6 +214,17 @@ window.plugin.crossLinks.checkAllLinks = function() { }); } +window.plugin.crossLinks.showLink = function(latlngs) { + + var poly = L.geodesicPolyline(latlngs, { + color: '#f11', + opacity: 0.7, + weight: 4, + clickable: false, + }); + + poly.addTo(plugin.crossLinks.linkLayer); +}; window.plugin.crossLinks.drawTools_save = function() { window.plugin.crossLinks.ori_drawTools_save(); @@ -228,6 +237,25 @@ window.plugin.crossLinks.drawTools_load = function() { } +window.plugin.crossLinks.createLayer = function() { + window.plugin.crossLinks.linkLayer = new L.FeatureGroup(); //LayerGroup(); FIXME: need to be a FeatureGroup to bring it to front + window.addLayerGroup('Cross Links', window.plugin.crossLinks.linkLayer, true); + window.plugin.crossLinks.linkLayer.bringToFront(); + + //hide the draw tools when the 'drawn items' layer is off, show it when on + map.on('layeradd', function(obj) { + if(obj.layer === window.plugin.crossLinks.linkLayer) { + window.plugin.crossLinks.disabled = undefined; + window.plugin.crossLinks.checkAllLinks(); + } + }); + map.on('layerremove', function(obj) { + if(obj.layer === window.plugin.crossLinks.linkLayer) { + window.plugin.crossLinks.disabled = true; + } + }); +} + var setup = function() { console.debug("Cross-Links: init"); if (window.plugin.drawTools === undefined) { @@ -235,6 +263,8 @@ var setup = function() { return; } + window.plugin.crossLinks.createLayer(); + // hook 'drawTools' window.plugin.crossLinks.ori_drawTools_save = window.plugin.drawTools.save; window.plugin.drawTools.save = window.plugin.crossLinks.drawTools_save; From f47c9bb234b5bb002858a2a5878ea71dc73734d2 Mon Sep 17 00:00:00 2001 From: McBen Date: Wed, 11 Jun 2014 23:08:01 +0200 Subject: [PATCH 04/10] cross-links: better layer-order --- plugins/cross_link.user.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/plugins/cross_link.user.js b/plugins/cross_link.user.js index 2a0542aa..60347db1 100644 --- a/plugins/cross_link.user.js +++ b/plugins/cross_link.user.js @@ -160,7 +160,6 @@ window.plugin.crossLinks.testPolygons = function (polygons, link) { window.plugin.crossLinks.onLinkAdded = function (data) { if (window.plugin.crossLinks.disabled) return; - window.plugin.crossLinks.linkLayer.bringToFront(); // FIXME: workaround to keep it on above the link-layer var link = data.link; @@ -226,6 +225,13 @@ window.plugin.crossLinks.showLink = function(latlngs) { poly.addTo(plugin.crossLinks.linkLayer); }; +window.plugin.crossLinks.onMapDataRefreshEnd = function () { + if (window.plugin.crossLinks.reorderLinkLayer) { + window.plugin.crossLinks.linkLayer.bringToFront(); + delete window.plugin.crossLinks.reorderLinkLayer; + } +} + window.plugin.crossLinks.drawTools_save = function() { window.plugin.crossLinks.ori_drawTools_save(); window.plugin.crossLinks.checkAllLinks(); @@ -238,11 +244,10 @@ window.plugin.crossLinks.drawTools_load = function() { window.plugin.crossLinks.createLayer = function() { - window.plugin.crossLinks.linkLayer = new L.FeatureGroup(); //LayerGroup(); FIXME: need to be a FeatureGroup to bring it to front + window.plugin.crossLinks.linkLayer = new L.FeatureGroup(); window.addLayerGroup('Cross Links', window.plugin.crossLinks.linkLayer, true); - window.plugin.crossLinks.linkLayer.bringToFront(); + window.plugin.crossLinks.reorderLinkLayer = true; - //hide the draw tools when the 'drawn items' layer is off, show it when on map.on('layeradd', function(obj) { if(obj.layer === window.plugin.crossLinks.linkLayer) { window.plugin.crossLinks.disabled = undefined; @@ -272,6 +277,7 @@ var setup = function() { window.plugin.drawTools.load = window.plugin.crossLinks.drawTools_load; window.addHook('linkAdded', window.plugin.crossLinks.onLinkAdded); + window.addHook('mapDataRefreshEnd', window.plugin.crossLinks.onMapDataRefreshEnd); } // PLUGIN END ////////////////////////////////////////////////////////// From e40249fcd0390b9c54249332f3f36da1ecf1e9f7 Mon Sep 17 00:00:00 2001 From: McBen Date: Wed, 11 Jun 2014 23:12:37 +0200 Subject: [PATCH 05/10] cross-links: refactored collision test --- plugins/cross_link.user.js | 285 +++++++++++++++++-------------------- 1 file changed, 130 insertions(+), 155 deletions(-) diff --git a/plugins/cross_link.user.js b/plugins/cross_link.user.js index 60347db1..4d429a59 100644 --- a/plugins/cross_link.user.js +++ b/plugins/cross_link.user.js @@ -18,204 +18,179 @@ // PLUGIN START //////////////////////////////////////////////////////// + window.plugin.crossLinks = function() {}; -// Great Circle Arc Intersection -// http://geospatialmethods.org/spheres/GCAIntersect.html -function intersect(a, b) { - var PI = Math.PI, - radians = PI / 180, - ε = 1e-6; +/* Great Circle Arc Intersection + Conecpt in short: + - build a plane of each arc (p1,p2,center) + - find intersection line and intersection points on sphere + - check if a point are on both arcs + see: http://geospatialmethods.org/spheres/GCAIntersect.html +*/ +var PI = Math.PI; +var radians = PI / 180; +var near_0 = 1e-6; - var λ0 = a[0][0], - λ1 = a[1][0], - λ2 = b[0][0], - λ3 = b[1][0], - δλ0 = λ1 - λ0, - δλ1 = λ3 - λ2, - aδλ0 = Math.abs(δλ0), - aδλ1 = Math.abs(δλ1), - sλ0 = aδλ0 > 180, - sλ1 = aδλ1 > 180, - φ0 = a[0][1] * radians, - φ1 = a[1][1] * radians, - φ2 = b[0][1] * radians, - φ3 = b[1][1] * radians, - t; +function greatCircleArcIntersect(a0,a1,b0,b1) { - // Ensure λ0 ≤ λ1 and λ2 ≤ λ3. - if (δλ0 < 0) t = λ0, λ0 = λ1, λ1 = t, t = φ0, φ0 = φ1, φ1 = t; - if (δλ1 < 0) t = λ2, λ2 = λ3, λ3 = t, t = φ2, φ2 = φ3, φ3 = t; + // Order points + if (a1.lat < a0.lat) { var t=a1;a1=a0;a0=t;} + if (b1.lat < b0.lat) { var t=b1;b1=b0;b0=t;} - // Check if longitude ranges overlap. - // TODO handle antimeridian crossings. - if (!sλ0 && !sλ1 && (λ0 > λ3 || λ2 > λ1)) return; + var λ0 = a0.lat, + λ1 = a1.lat, + λ2 = b0.lat, + λ3 = b1.lat, + δλ0 = λ1 - λ0, + δλ1 = λ3 - λ2, + sλ0 = δλ0 > 180, + sλ1 = δλ1 > 180, + φ0 = a0.lng * radians, + φ1 = a1.lng * radians, + φ2 = b0.lng * radians, + φ3 = b1.lng * radians, + t; - // Check for polar endpoints. - if (Math.abs(Math.abs(φ0) - PI / 2) < ε) λ0 = λ1, aδλ0 = δλ0 = 0, sλ0 = false; - if (Math.abs(Math.abs(φ1) - PI / 2) < ε) λ1 = λ0, aδλ0 = δλ0 = 0, sλ0 = false; - if (Math.abs(Math.abs(φ2) - PI / 2) < ε) λ2 = λ3, aδλ1 = δλ1 = 0, sλ1 = false; - if (Math.abs(Math.abs(φ3) - PI / 2) < ε) λ3 = λ2, aδλ1 = δλ1 = 0, sλ1 = false; + // Check if longitude ranges overlap. + // TODO handle antimeridian crossings. + if (!sλ0 && !sλ1 && (λ0 > λ3 || λ2 > λ1)) return; - // Check for arcs along meridians. - var m0 = aδλ0 < ε || Math.abs(aδλ0 - 180) < ε, - m1 = aδλ1 < ε || Math.abs(aδλ1 - 180) < ε; + // Check for polar endpoints. + if (Math.abs(Math.abs(φ0) - PI / 2) < near_0) λ0 = λ1, δλ0 = 0, sλ0 = false; + if (Math.abs(Math.abs(φ1) - PI / 2) < near_0) λ1 = λ0, δλ0 = 0, sλ0 = false; + if (Math.abs(Math.abs(φ2) - PI / 2) < near_0) λ2 = λ3, δλ1 = 0, sλ1 = false; + if (Math.abs(Math.abs(φ3) - PI / 2) < near_0) λ3 = λ2, δλ1 = 0, sλ1 = false; - λ0 *= radians, λ1 *= radians, λ2 *= radians, λ3 *= radians; + // Check for arcs along meridians. + var m0 = δλ0 < near_0 || Math.abs(δλ0 - 180) < near_0, + m1 = δλ1 < near_0 || Math.abs(δλ1 - 180) < near_0; - // Intersect two great circles and check the two intersection points against - // the longitude ranges. The intersection points are simply the cross - // product of the great-circle normals ±n1⨯n2. + λ0 *= radians, λ1 *= radians, λ2 *= radians, λ3 *= radians; - // First plane. - var cosφ, - x0 = (cosφ = Math.cos(φ0)) * Math.cos(λ0), - y0 = cosφ * Math.sin(λ0), - z0 = Math.sin(φ0), - x1 = (cosφ = Math.cos(φ1)) * Math.cos(λ1), - y1 = cosφ * Math.sin(λ1), - z1 = Math.sin(φ1), - n0x = y0 * z1 - z0 * y1, - n0y = z0 * x1 - x0 * z1, - n0z = x0 * y1 - y0 * x1, - m = length(n0x, n0y, n0z); + // Intersect two great circles and check the two intersection points against + // the longitude ranges. The intersection points are simply the cross + // product of the great-circle normals ±n1⨯n2. - n0x /= m, n0y /= m, n0z /= m; + // First plane. + var cosφ, + x0 = (cosφ = Math.cos(φ0)) * Math.cos(λ0), + y0 = cosφ * Math.sin(λ0), + z0 = Math.sin(φ0), + x1 = (cosφ = Math.cos(φ1)) * Math.cos(λ1), + y1 = cosφ * Math.sin(λ1), + z1 = Math.sin(φ1), + n0x = y0 * z1 - z0 * y1, + n0y = z0 * x1 - x0 * z1, + n0z = x0 * y1 - y0 * x1, + m = length(n0x, n0y, n0z); - // Second plane. - var x2 = (cosφ = Math.cos(φ2)) * Math.cos(λ2), - y2 = cosφ * Math.sin(λ2), - z2 = Math.sin(φ2), - x3 = (cosφ = Math.cos(φ3)) * Math.cos(λ3), - y3 = cosφ * Math.sin(λ3), - z3 = Math.sin(φ3), - n1x = y2 * z3 - z2 * y3, - n1y = z2 * x3 - x2 * z3, - n1z = x2 * y3 - y2 * x3, - m = length(n1x, n1y, n1z); + n0x /= m, n0y /= m, n0z /= m; - n1x /= m, n1y /= m, n1z /= m; + // Second plane. + var x2 = (cosφ = Math.cos(φ2)) * Math.cos(λ2), + y2 = cosφ * Math.sin(λ2), + z2 = Math.sin(φ2), + x3 = (cosφ = Math.cos(φ3)) * Math.cos(λ3), + y3 = cosφ * Math.sin(λ3), + z3 = Math.sin(φ3), + n1x = y2 * z3 - z2 * y3, + n1y = z2 * x3 - x2 * z3, + n1z = x2 * y3 - y2 * x3, + m = length(n1x, n1y, n1z); - var Nx = n0y * n1z - n0z * n1y, - Ny = n0z * n1x - n0x * n1z, - Nz = n0x * n1y - n0y * n1x; + n1x /= m, n1y /= m, n1z /= m; - if (length(Nx, Ny, Nz) < ε) return; + var Nx = n0y * n1z - n0z * n1y, + Ny = n0z * n1x - n0x * n1z, + Nz = n0x * n1y - n0y * n1x; - var λ = Math.atan2(Ny, Nx); - if ((sλ0 ^ (λ0 <= λ && λ <= λ1) || m0 && Math.abs(λ - λ0) < ε) && (sλ1 ^ (λ2 <= λ && λ <= λ3) || m1 && Math.abs(λ - λ2) < ε) || (Nz = -Nz, - (sλ0 ^ (λ0 <= (λ = (λ + 2 * PI) % (2 * PI) - PI) && λ <= λ1) || m0 && Math.abs(λ - λ0) < ε) && (sλ1 ^ (λ2 <= λ && λ <= λ3) || m1 && Math.abs(λ - λ2) < ε))) { - var φ = Math.asin(Nz / length(Nx, Ny, Nz)); - if (m0 || m1) { - if (m1) φ0 = φ2, φ1 = φ3, λ0 = λ2, λ1 = λ3, aδλ0 = aδλ1; - if (aδλ0 > ε) return φ0 + φ1 > 0 ^ φ < (Math.abs(λ - λ0) < ε ? φ0 : φ1) ? [λ / radians, φ / radians] : null; - // Ensure φ0 ≤ φ1. - if (φ1 < φ0) t = φ0, φ0 = φ1, φ1 = t; - return Math.abs(λ - (m0 ? λ0 : λ2)) < ε && φ0 <= φ && φ <= φ1 ? [λ / radians, φ / radians] : null; + if (length(Nx, Ny, Nz) < near_0) return; + + var λ = Math.atan2(Ny, Nx); + if ( (sλ0 ^ (λ0 <= λ && λ <= λ1) || m0 && Math.abs(λ - λ0) < near_0) && (sλ1 ^ (λ2 <= λ && λ <= λ3) || m1 && Math.abs(λ - λ2) < near_0) || (Nz = -Nz, + (sλ0 ^ (λ0 <= (λ = (λ + 2 * PI) % (2 * PI) - PI) && λ <= λ1) || m0 && Math.abs(λ - λ0) < near_0) && (sλ1 ^ (λ2 <= λ && λ <= λ3) || m1 && Math.abs(λ - λ2) < near_0))) { + + var φ = Math.asin(Nz / length(Nx, Ny, Nz)); + + if (m0 || m1) { + if (m1) φ0 = φ2, φ1 = φ3, λ0 = λ2, λ1 = λ3, δλ0 = δλ1; + + if (δλ0 > near_0) + return (φ0 + φ1 > 0 ^ φ < (Math.abs(λ - λ0) < near_0 ? φ0 : φ1)) ? [λ / radians, φ / radians] : null; + + // Ensure φ0 ≤ φ1. + if (φ1 < φ0) t = φ0, φ0 = φ1, φ1 = t; + return (Math.abs(λ - (m0 ? λ0 : λ2)) < near_0 && φ0 <= φ && φ <= φ1) ? [λ / radians, φ / radians] : null; + } + + return [λ / radians, φ / radians]; } - return [λ / radians, φ / radians]; - } } function length(x, y, z) { return Math.sqrt(x * x + y * y + z * z); } -window.plugin.crossLinks.testPolyLine = function (polyline, link) { - var a= [[link[0].lat,link[0].lng],[link[1].lat,link[1].lng]]; - for (var i=0;i0 = inside ; one >0 = collision +*/ - var b= [[polyline[i].lat,polyline[i].lng],[polyline[i+1].lat,polyline[i+1].lng]]; - if (intersect(a,b)) return true; +window.plugin.crossLinks.testPolyLine = function (polyline, link,closed) { + + var a = link.getLatLngs(); + var b = polyline.getLatLngs(); + + for (var i=0;i point.lng) != (p2.lng>point.lng)) && - (point.lat < (p2.lat - p1.lat)*(point.lng-p1.lng) / (p2.lng-p1.lng) + p1.lat)) - c = !c; - - p2 = p1; - } - return c; -} - -window.plugin.crossLinks.testPolygons = function (polygons, link) { - - var linkline= L.geodesicConvertLines(link._latlngs,0); - - for (var pidx=0;pidx Date: Wed, 11 Jun 2014 23:18:44 +0200 Subject: [PATCH 06/10] cross-links: replaced direct hooks by events --- plugins/cross_link.user.js | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/plugins/cross_link.user.js b/plugins/cross_link.user.js index 4d429a59..13bdeb4e 100644 --- a/plugins/cross_link.user.js +++ b/plugins/cross_link.user.js @@ -207,17 +207,6 @@ window.plugin.crossLinks.onMapDataRefreshEnd = function () { } } -window.plugin.crossLinks.drawTools_save = function() { - window.plugin.crossLinks.ori_drawTools_save(); - window.plugin.crossLinks.checkAllLinks(); - } - -window.plugin.crossLinks.drawTools_load = function() { - window.plugin.crossLinks.ori_drawTools_load(); - window.plugin.crossLinks.checkAllLinks(); - } - - window.plugin.crossLinks.createLayer = function() { window.plugin.crossLinks.linkLayer = new L.FeatureGroup(); window.addLayerGroup('Cross Links', window.plugin.crossLinks.linkLayer, true); @@ -237,22 +226,20 @@ window.plugin.crossLinks.createLayer = function() { } var setup = function() { - console.debug("Cross-Links: init"); - if (window.plugin.drawTools === undefined) { - alert("'Cross-Links' requires 'draw-tools'"); - return; - } + if (window.plugin.drawTools === undefined) { + alert("'Cross-Links' requires 'draw-tools'"); + return; + } - window.plugin.crossLinks.createLayer(); + window.plugin.crossLinks.createLayer(); - // hook 'drawTools' - window.plugin.crossLinks.ori_drawTools_save = window.plugin.drawTools.save; - window.plugin.drawTools.save = window.plugin.crossLinks.drawTools_save; - window.plugin.crossLinks.ori_drawTools_load = window.plugin.drawTools.load; - window.plugin.drawTools.load = window.plugin.crossLinks.drawTools_load; + // events + map.on('draw:created', function(e) {window.plugin.crossLinks.checkAllLinks(); }); + map.on('draw:deleted', function(e) {window.plugin.crossLinks.checkAllLinks(); }); + map.on('draw:edited', function(e) {window.plugin.crossLinks.checkAllLinks();}); - window.addHook('linkAdded', window.plugin.crossLinks.onLinkAdded); - window.addHook('mapDataRefreshEnd', window.plugin.crossLinks.onMapDataRefreshEnd); + window.addHook('linkAdded', window.plugin.crossLinks.onLinkAdded); + window.addHook('mapDataRefreshEnd', window.plugin.crossLinks.onMapDataRefreshEnd); } // PLUGIN END ////////////////////////////////////////////////////////// From 63a0aa69b5ce902291b0e6b7145dca8ccb8a6c6b Mon Sep 17 00:00:00 2001 From: McBen Date: Wed, 11 Jun 2014 23:13:06 +0200 Subject: [PATCH 07/10] cross-links: process collision links only once (and delete if needed) --- plugins/cross_link.user.js | 47 ++++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/plugins/cross_link.user.js b/plugins/cross_link.user.js index 13bdeb4e..d1cfbd91 100644 --- a/plugins/cross_link.user.js +++ b/plugins/cross_link.user.js @@ -167,6 +167,7 @@ window.plugin.crossLinks.checkAllLinks = function() { console.debug("Cross-Links: checking all links"); plugin.crossLinks.linkLayer.clearLayers(); + plugin.crossLinks.linkLayerGuids = {}; $.each(window.links, function(guid, link) { plugin.crossLinks.testLink(link); @@ -174,30 +175,38 @@ window.plugin.crossLinks.checkAllLinks = function() { } window.plugin.crossLinks.testLink = function (link) { - window.plugin.drawTools.drawnItems.eachLayer( function(layer) { + if (plugin.crossLinks.linkLayerGuids[link.options.guid]) return; + + for (var i in plugin.drawTools.drawnItems._layers) { // leaflet don't support breaking out of the loop + var layer = plugin.drawTools.drawnItems._layers[i]; if (layer instanceof L.GeodesicPolygon) { - if (window.plugin.crossLinks.testPolyLine(layer, link,true)) { + if (plugin.crossLinks.testPolyLine(layer, link,true)) { plugin.crossLinks.showLink(link); + break; } } else if (layer instanceof L.GeodesicPolyline) { - if (window.plugin.crossLinks.testPolyLine(layer, link)) { + if (plugin.crossLinks.testPolyLine(layer, link)) { plugin.crossLinks.showLink(link); + break; } } - }); + }; } window.plugin.crossLinks.showLink = function(link) { - var poly = L.geodesicPolyline(link.getLatLngs(), { - color: '#f11', - opacity: 0.7, - weight: 4, - clickable: false, - }); + var poly = L.geodesicPolyline(link.getLatLngs(), { + color: '#f11', + opacity: 0.7, + weight: 4, + clickable: false, - poly.addTo(plugin.crossLinks.linkLayer); + guid: link.options.guid + }); + + poly.addTo(plugin.crossLinks.linkLayer); + plugin.crossLinks.linkLayerGuids[link.options.guid]=poly; } window.plugin.crossLinks.onMapDataRefreshEnd = function () { @@ -205,16 +214,30 @@ window.plugin.crossLinks.onMapDataRefreshEnd = function () { window.plugin.crossLinks.linkLayer.bringToFront(); delete window.plugin.crossLinks.reorderLinkLayer; } + + window.plugin.crossLinks.testForDeletedLinks(); +} + +window.plugin.crossLinks.testForDeletedLinks = function () { + window.plugin.crossLinks.linkLayer.eachLayer( function(layer) { + var guid = layer.options.guid; + if (!this.seenLinksGuid[guid]) { + console.log("link removed"); + plugin.crossLinks.linkLayer.removeLayer(layer); + delete plugin.crossLinks.linkLayerGuids[guid]; + } + }); } window.plugin.crossLinks.createLayer = function() { window.plugin.crossLinks.linkLayer = new L.FeatureGroup(); + window.plugin.crossLinks.linkLayerGuids={}; window.addLayerGroup('Cross Links', window.plugin.crossLinks.linkLayer, true); window.plugin.crossLinks.reorderLinkLayer = true; map.on('layeradd', function(obj) { if(obj.layer === window.plugin.crossLinks.linkLayer) { - window.plugin.crossLinks.disabled = undefined; + delete window.plugin.crossLinks.disabled; window.plugin.crossLinks.checkAllLinks(); } }); From 22ab94ab07f0711607ddb7e9a308ee59309b2239 Mon Sep 17 00:00:00 2001 From: McBen Date: Fri, 13 Jun 2014 22:04:06 +0200 Subject: [PATCH 08/10] cross-link: fixed delete links --- plugins/cross_link.user.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/cross_link.user.js b/plugins/cross_link.user.js index d1cfbd91..1acf6d56 100644 --- a/plugins/cross_link.user.js +++ b/plugins/cross_link.user.js @@ -221,7 +221,7 @@ window.plugin.crossLinks.onMapDataRefreshEnd = function () { window.plugin.crossLinks.testForDeletedLinks = function () { window.plugin.crossLinks.linkLayer.eachLayer( function(layer) { var guid = layer.options.guid; - if (!this.seenLinksGuid[guid]) { + if (!window.mapDataRequest.render.seenLinksGuid[guid]) { console.log("link removed"); plugin.crossLinks.linkLayer.removeLayer(layer); delete plugin.crossLinks.linkLayerGuids[guid]; From 63e7be0cc23329f13690e18a80ec1adb5bd13011 Mon Sep 17 00:00:00 2001 From: McBen Date: Fri, 13 Jun 2014 22:04:25 +0200 Subject: [PATCH 09/10] cross-links: fixed create hook --- plugins/cross_link.user.js | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/plugins/cross_link.user.js b/plugins/cross_link.user.js index 1acf6d56..04192dd9 100644 --- a/plugins/cross_link.user.js +++ b/plugins/cross_link.user.js @@ -218,6 +218,25 @@ window.plugin.crossLinks.onMapDataRefreshEnd = function () { window.plugin.crossLinks.testForDeletedLinks(); } +window.plugin.crossLinks.testAllLinksAgainstLayer = function (layer) { + if (window.plugin.crossLinks.disabled) return; + + $.each(window.links, function(guid, link) { + if (!plugin.crossLinks.linkLayerGuids[link.options.guid]) + { + if (layer instanceof L.GeodesicPolygon) { + if (plugin.crossLinks.testPolyLine(layer, link,true)) { + plugin.crossLinks.showLink(link); + } + } else if (layer instanceof L.GeodesicPolyline) { + if (plugin.crossLinks.testPolyLine(layer, link)) { + plugin.crossLinks.showLink(link); + } + } + } + }); +} + window.plugin.crossLinks.testForDeletedLinks = function () { window.plugin.crossLinks.linkLayer.eachLayer( function(layer) { var guid = layer.options.guid; @@ -257,7 +276,7 @@ var setup = function() { window.plugin.crossLinks.createLayer(); // events - map.on('draw:created', function(e) {window.plugin.crossLinks.checkAllLinks(); }); + map.on('draw:created', function(e) { window.plugin.crossLinks.testAllLinksAgainstLayer(e.layer);}); map.on('draw:deleted', function(e) {window.plugin.crossLinks.checkAllLinks(); }); map.on('draw:edited', function(e) {window.plugin.crossLinks.checkAllLinks();}); From ed46234573bdeefb4ff02268ed3bb90423f9c6fb Mon Sep 17 00:00:00 2001 From: McBen Date: Fri, 13 Jun 2014 22:54:05 +0200 Subject: [PATCH 10/10] cross-links: always bring layer to front --- plugins/cross_link.user.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/plugins/cross_link.user.js b/plugins/cross_link.user.js index 04192dd9..9ad3def8 100644 --- a/plugins/cross_link.user.js +++ b/plugins/cross_link.user.js @@ -210,10 +210,7 @@ window.plugin.crossLinks.showLink = function(link) { } window.plugin.crossLinks.onMapDataRefreshEnd = function () { - if (window.plugin.crossLinks.reorderLinkLayer) { - window.plugin.crossLinks.linkLayer.bringToFront(); - delete window.plugin.crossLinks.reorderLinkLayer; - } + window.plugin.crossLinks.linkLayer.bringToFront(); window.plugin.crossLinks.testForDeletedLinks(); } @@ -252,7 +249,6 @@ window.plugin.crossLinks.createLayer = function() { window.plugin.crossLinks.linkLayer = new L.FeatureGroup(); window.plugin.crossLinks.linkLayerGuids={}; window.addLayerGroup('Cross Links', window.plugin.crossLinks.linkLayer, true); - window.plugin.crossLinks.reorderLinkLayer = true; map.on('layeradd', function(obj) { if(obj.layer === window.plugin.crossLinks.linkLayer) {