Simplify Place Geometry

Simplifies geometry of area places

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

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