WME Simplify Place Geometry

Simplifies geometry of area places in WME

当前为 2015-02-23 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name WME Simplify Place Geometry
  3. // @description Simplifies geometry of area places in WME
  4. // @version 0.9
  5. // @author SAR85
  6. // @grant none
  7. // @include https://www.waze.com/editor/*
  8. // @include https://www.waze.com/*/editor/*
  9. // @include https://editor-beta.waze.com/*
  10. // @namespace https://greasyfork.org/users/9321
  11. // ==/UserScript==
  12.  
  13. function simpBootstrap() {
  14. var bGreasemonkeyServiceDefined = false;
  15. try
  16. {
  17. if ("object" === typeof Components.interfaces.gmIGreasemonkeyService)
  18. {
  19. bGreasemonkeyServiceDefined = true;
  20. }
  21. }
  22. catch (err)
  23. {
  24. // Ignore.
  25. }
  26. if ( "undefined" === typeof unsafeWindow || ! bGreasemonkeyServiceDefined)
  27. {
  28. unsafeWindow = ( function ()
  29. {
  30. var dummyElem = document.createElement('p');
  31. dummyElem.setAttribute ('onclick', 'return window;');
  32. return dummyElem.onclick ();
  33. } ) ();
  34. }
  35. /* begin running the code! */
  36. window.setTimeout(simpInit, 2000);
  37. /*doesn't work in FF: $(document).ready(simpInit); */
  38. }
  39.  
  40. function addSimplifyFunc() {
  41. /*
  42. (c) 2013, Vladimir Agafonkin
  43. Simplify.js, a high-performance JS polyline simplification library
  44. mourner.github.io/simplify-js
  45. */
  46. (function () { 'use strict';
  47.  
  48. // to suit your point format, run search/replace for '.x' and '.y';
  49. // for 3D version, see 3d branch (configurability would draw significant performance overhead)
  50.  
  51. // square distance between 2 points
  52. function getSqDist(p1, p2) {
  53.  
  54. var dx = p1.x - p2.x,
  55. dy = p1.y - p2.y;
  56.  
  57. return dx * dx + dy * dy;
  58. }
  59.  
  60. // square distance from a point to a segment
  61. function getSqSegDist(p, p1, p2) {
  62.  
  63. var x = p1.x,
  64. y = p1.y,
  65. dx = p2.x - x,
  66. dy = p2.y - y;
  67.  
  68. if (dx !== 0 || dy !== 0) {
  69.  
  70. var t = ((p.x - x) * dx + (p.y - y) * dy) / (dx * dx + dy * dy);
  71.  
  72. if (t > 1) {
  73. x = p2.x;
  74. y = p2.y;
  75.  
  76. } else if (t > 0) {
  77. x += dx * t;
  78. y += dy * t;
  79. }
  80. }
  81.  
  82. dx = p.x - x;
  83. dy = p.y - y;
  84.  
  85. return dx * dx + dy * dy;
  86. }
  87. // rest of the code doesn't care about point format
  88.  
  89. // basic distance-based simplification
  90. function simplifyRadialDist(points, sqTolerance) {
  91.  
  92. var prevPoint = points[0],
  93. newPoints = [prevPoint],
  94. point;
  95.  
  96. for (var i = 1, len = points.length; i < len; i++) {
  97. point = points[i];
  98.  
  99. if (getSqDist(point, prevPoint) > sqTolerance) {
  100. newPoints.push(point);
  101. prevPoint = point;
  102. }
  103. }
  104.  
  105. if (prevPoint !== point) newPoints.push(point);
  106.  
  107. return newPoints;
  108. }
  109.  
  110. // simplification using optimized Douglas-Peucker algorithm with recursion elimination
  111. function simplifyDouglasPeucker(points, sqTolerance) {
  112.  
  113. var len = points.length,
  114. MarkerArray = typeof Uint8Array !== 'undefined' ? Uint8Array : Array,
  115. markers = new MarkerArray(len),
  116. first = 0,
  117. last = len - 1,
  118. stack = [],
  119. newPoints = [],
  120. i, maxSqDist, sqDist, index;
  121.  
  122. markers[first] = markers[last] = 1;
  123.  
  124. while (last) {
  125.  
  126. maxSqDist = 0;
  127.  
  128. for (i = first + 1; i < last; i++) {
  129. sqDist = getSqSegDist(points[i], points[first], points[last]);
  130.  
  131. if (sqDist > maxSqDist) {
  132. index = i;
  133. maxSqDist = sqDist;
  134. }
  135. }
  136.  
  137. if (maxSqDist > sqTolerance) {
  138. markers[index] = 1;
  139. stack.push(first, index, index, last);
  140. }
  141.  
  142. last = stack.pop();
  143. first = stack.pop();
  144. }
  145.  
  146. for (i = 0; i < len; i++) {
  147. if (markers[i]) newPoints.push(points[i]);
  148. }
  149.  
  150. return newPoints;
  151. }
  152.  
  153. // both algorithms combined for awesome performance
  154. function simplify(points, tolerance, highestQuality) {
  155.  
  156. if (points.length <= 1) return points;
  157.  
  158. var sqTolerance = tolerance !== undefined ? tolerance * tolerance : 1;
  159.  
  160. points = highestQuality ? points : simplifyRadialDist(points, sqTolerance);
  161. points = simplifyDouglasPeucker(points, sqTolerance);
  162.  
  163. return points;
  164. }
  165.  
  166. // export as AMD module / Node module / browser or worker variable
  167. if (typeof define === 'function' && define.amd) define(function() { return simplify; });
  168. else if (typeof module !== 'undefined') module.exports = simplify;
  169. else if (typeof self !== 'undefined') self.simplify = simplify;
  170. else window.simplify = simplify;
  171.  
  172. })();
  173. }
  174.  
  175. function simpInit() {
  176. /* HTML */
  177. var tab = '<li><a href="#sidepanel-simplifyarea" data-toggle="tab" id="simplifytab">Simplify Area</a></li>';
  178. var content = '<div class="tab-pane" id="sidepanel-simplifyarea"><h1 style="display: block; position:relative; margin-top: -10px; margin-bottom: 10px">Simplify Area Place Geometry</h1><hr><p>Simplification factor:</p><p>0<input type="range" id="simpE" step="1" min="1" max="100" defaultValue="50"></input>100</p><p>Press "j" to simplify the geometry of a selected area place.</p></div>';
  179. /* Initialize simplification library */
  180. addSimplifyFunc();
  181. /* Add HTML to page */
  182. $('h2 + ul.nav-tabs').append(tab);
  183. $('h2 + ul.nav-tabs + .tab-content').append(content);
  184. /* Shortcut key = j */
  185. $(document).keypress(function(e) {
  186. if (e.charCode == 106) simplifyFeatureGeometry($('#simpE').val());
  187. });
  188. console.log("WME Simplify Area Geometry Initialized");
  189. }
  190.  
  191. function simplifyFeatureGeometry(e) {
  192. if (!W.selectionManager.hasSelectedItems() || W.selectionManager.selectedItems[0].model.type !== "venue") return;
  193. var UpdateFeatureGeometry = require("Waze/Action/UpdateFeatureGeometry");
  194. var place = W.selectionManager.selectedItems[0];
  195. var placegeo = place.geometry.clone();
  196. var newgeo = placegeo.clone();
  197. newgeo.components[0].components = simplify(placegeo.components[0].components, e, false);
  198. if (newgeo.components[0].components.length < placegeo.components[0].components.length) {
  199. W.model.actionManager.add(new UpdateFeatureGeometry(place.model,W.model.venues,placegeo,newgeo));
  200. console.log("WME Simplify Area Geometry: " + place.model.attributes.name + " simplified from " + placegeo.components[0].components.length + " to " + newgeo.components[0].components.length + " geo nodes using factor " + e + ".");
  201. } else {
  202. console.log("Geo nodes cannot be simplified from " + placegeo.components[0].components.length + " to " + newgeo.components[0].components.length + ".");
  203. }
  204. }
  205.  
  206. simpBootstrap();