From e9e2aec77df36ccaa80ae06e7b731e162a5a8203 Mon Sep 17 00:00:00 2001 From: ahocevar Date: Wed, 15 Dec 2010 13:38:52 +0000 Subject: [PATCH] Added Douglas-Peucker linestring simplification to OpenLayers.Geometry.LineString. Thanks chrismayer for this excellent patch. p=chrismayer, r=me (closes #2869) git-svn-id: http://svn.openlayers.org/trunk/openlayers@10969 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf --- examples/simplify-linestring.html | 86 ++++ examples/simplify-linestring.js | 599 ++++++++++++++++++++++++++ lib/OpenLayers/Geometry/LineString.js | 92 ++++ tests/Geometry/LineString.html | 62 ++- 4 files changed, 838 insertions(+), 1 deletion(-) create mode 100644 examples/simplify-linestring.html create mode 100644 examples/simplify-linestring.js diff --git a/examples/simplify-linestring.html b/examples/simplify-linestring.html new file mode 100644 index 0000000000..49cdb21c82 --- /dev/null +++ b/examples/simplify-linestring.html @@ -0,0 +1,86 @@ + + + + Simplify LineString + + + + + +

Simplify a LineString

+
+ Douglas-Peucker, Douglas, Peucker, Peuker, tolerance +
+

+ Shows the usage of the utility method "simplifyLineString" that + implements the Douglas-Peucker algorithm to remove "insignificant" + vertices from LineString geometries. +

+
+ + + +
+
+
+
+
+
+
+
+

+ The method OpenLayers.Util.simplifyLineString can be used to + simplify linestring geometries. Simplification sometimes is + useful to enhance the perfomance of vector rendering or to + reduce complexity of geometries. This might be especially handy + when viewing geometries a small scales. +

+

+ OpenLayers.Util.simplifyLineString is a recursive implementation + of the famous Douglas-Peucker algorithm. It + is controlled by a tolerance factor that defines the threshold + for vertices to be considered "insignificant" for the general + structure of the geometry. +

+

+ The LineString on the left map can be simplified according to + the tolerance value one enters in the form-field above the maps. + Use a value between 0 and 1 for best results. If you navigate + the left map, the right map will show the same location to make + it easier to spot the differeces between the LineStrings. +

+

+ The LineString + represents a part of the coastline of + this + place in Russia — found via an + example implementation of the algorithm in python. +

+

+ For a detailled explanation of the algorithm see + the + Wikipedia article or the original publication: David Douglas + & Thomas Peucker, "Algorithms for the reduction of the + number of points required to represent a digitized line or its + caricature", The Canadian Cartographer 10(2), 112-122 (1973) + (DOI: + 10.3138/FM57-6770-U75U-7727). +

+
+ + + + diff --git a/examples/simplify-linestring.js b/examples/simplify-linestring.js new file mode 100644 index 0000000000..3f4c6f6375 --- /dev/null +++ b/examples/simplify-linestring.js @@ -0,0 +1,599 @@ +// global variables +var map, map2; + +// wrap the instanciation code in an anonymous function that gets executed +// immedeately +(function(){ + // style the vectorlayer + var styleMap = new OpenLayers.StyleMap({ + 'default': new OpenLayers.Style({ + strokeColor: "#333333", + strokeWidth: 1.2, + strokeOpacity: 1 + }) + }); + + // the vectorlayer + var vectorlayer = new OpenLayers.Layer.Vector('Vectorlayer', { + isBaseLayer: true, + styleMap: styleMap + }); + + var original = OpenLayers.Geometry.fromWKT("LINESTRING(" + + "6.247872 11.316756," + + "6.338566 11.316756," + + "6.633323 11.205644," + + "6.724018 11.205644," + + "6.792039 11.205644," + + "7.154817 11.372311," + + "7.313532 11.400089," + + "7.381553 11.344533," + + "7.336206 11.288978," + + "7.200164 11.288978," + + "7.154817 11.261200," + + "7.132143 11.233422," + + "7.154817 11.150089," + + "7.268185 11.177867," + + "7.313532 11.122311," + + "7.404227 11.150089," + + "7.472248 11.094533," + + "7.767005 10.900089," + + "7.758951 10.864989," + + "7.752684 10.837656," + + "7.426900 10.927867," + + "6.519955 10.927867," + + "6.429261 10.900089," + + "6.315893 10.955644," + + "6.270545 10.955644," + + "6.247872 10.927867," + + "6.111830 11.011200," + + "6.066483 11.066756," + + "5.862420 11.038978," + + "5.817073 10.955644," + + "5.771726 10.900089," + + "5.862420 10.761200," + + "5.975788 10.733422," + + "6.157177 10.566756," + + "6.247872 10.511200," + + "6.293219 10.427867," + + "6.315893 10.233422," + + "6.315893 10.177867," + + "6.542629 9.844533," + + "6.587976 9.761200," + + "6.610650 9.288978," + + "6.542629 9.066756," + + "6.565303 8.900089," + + "6.519955 8.816756," + + "6.542629 8.761200," + + "6.565303 8.733422," + + "6.429261 8.427867," + + "6.474608 8.316756," + + "6.724018 8.288978," + + "6.882733 8.538978," + + "6.973428 8.594533," + + "6.996101 8.622311," + + "7.200164 8.650089," + + "7.290859 8.650089," + + "7.426900 8.483422," + + "7.404227 8.455644," + + "7.245511 8.511200," + + "6.996101 8.427867," + + "7.041449 8.372311," + + "7.154817 8.455644," + + "7.200164 8.455644," + + "7.245511 8.455644," + + "7.381553 8.316756," + + "7.381553 8.261200," + + "7.404227 8.233422," + + "7.494921 8.205644," + + "7.767005 8.288978," + + "7.948394 8.233422," + + "8.016415 8.261200," + + "8.197804 8.094533," + + "8.084435 7.816756," + + "8.152456 7.733422," + + "8.175130 7.650089," + + "8.175130 7.511200," + + "8.311172 7.427867," + + "8.311172 7.372311," + + "8.651276 7.372311," + + "8.923360 7.316756," + + "8.900686 7.261200," + + "8.809991 7.261200," + + "8.472735 7.171122," + + "8.333845 7.038978," + + "8.282022 6.981100," + + "8.254778 6.848911," + + "8.265824 6.816756," + + "8.239206 6.711211," + + "8.219743 6.612067," + + "8.130227 6.433044," + + "8.084435 6.316756," + + "8.107109 6.288978," + + "7.948394 6.177867," + + "7.925720 5.983422," + + "7.857699 5.816756," + + "7.835026 5.788978," + + "7.857699 5.511200," + + "7.812352 5.400089," + + "7.812352 5.344533," + + "7.812352 5.177867," + + "8.084435 4.733422," + + "8.107109 4.622311," + + "7.857699 4.344533," + + "7.630963 4.261200," + + "7.540268 4.177867," + + "7.494921 4.150089," + + "7.449574 4.150089," + + "7.404227 4.150089," + + "7.336206 4.094533," + + "7.313532 4.066756," + + "7.041449 4.011200," + + "6.905407 3.955644," + + "6.950754 3.900089," + + "7.200164 3.927867," + + "7.630963 3.872311," + + "7.721657 3.872311," + + "7.948394 3.788978," + + "7.993741 3.705644," + + "7.971067 3.677867," + + "7.925720 3.622311," + + "8.175130 3.705644," + + "8.401866 3.650089," + + "8.492561 3.650089," + + "8.605929 3.538978," + + "8.651276 3.566756," + + "8.855339 3.372311," + + "8.900686 3.316756," + + "8.900686 3.150089," + + "8.787318 2.900089," + + "8.787318 2.844533," + + "8.946033 2.816756," + + "8.991380 2.788978," + + "9.014054 2.705644," + + "8.886928 2.524989," + + "8.832665 2.538978," + + "8.809991 2.455644," + + "8.923360 2.538978," + + "9.014054 2.400089," + + "9.308811 2.288978," + + "9.399506 2.261200," + + "9.512874 2.122311," + + "9.535548 1.983422," + + "9.512874 1.955644," + + "9.467527 1.816756," + + "9.036728 1.816756," + + "8.991380 1.927867," + + "8.946033 1.955644," + + "8.900686 1.983422," + + "8.946033 2.122311," + + "8.968707 2.150089," + + "9.195443 1.927867," + + "9.354158 1.955644," + + "9.376832 2.038978," + + "9.376832 2.094533," + + "9.240790 2.205644," + + "9.195443 2.205644," + + "9.263464 2.150089," + + "9.240790 2.122311," + + "9.195443 2.122311," + + "9.104749 2.122311," + + "8.900686 2.316756," + + "8.787318 2.344533," + + "8.696623 2.372311," + + "8.651276 2.427867," + + "8.719297 2.455644," + + "8.787318 2.650089," + + "8.832665 2.705644," + + "8.605929 2.677867," + + "8.537908 2.788978," + + "8.333845 2.788978," + + "7.925720 2.316756," + + "7.925720 2.261200," + + "7.903046 2.233422," + + "7.857699 2.233422," + + "7.857699 2.177867," + + "7.789678 1.983422," + + "7.812352 1.788978," + + "7.948394 1.538978," + + "7.971067 1.511200," + + "8.129783 1.511200," + + "8.243151 1.594533," + + "8.333845 1.594533," + + "8.424540 1.622311," + + "8.515234 1.566756," + + "8.673950 1.400089," + + "8.771174 1.291756," + + "8.828938 1.119878," + + "8.762504 0.972544," + + "9.238614 0.759633," + + "9.492323 0.627022," + + "9.820891 0.644711," + + "10.376567 0.800622," + + "10.651961 1.085978," + + "10.762173 1.132022," + + "10.943045 1.095989," + + "11.256739 0.999878," + + "11.576074 0.761611," + + "11.768247 0.425211," + + "11.960165 0.074778," + + "11.953907 0.000000," + + "11.629411 0.258767," + + "11.229920 0.582278," + + "11.001633 0.564300," + + "10.868476 0.447478," + + "10.633849 0.541833," + + "10.513370 0.672133," + + "11.188700 0.820078," + + "11.194014 0.859656," + + "11.118212 0.905822," + + "10.874860 0.930311," + + "10.427319 0.716522," + + "10.023620 0.374211," + + "9.434614 0.360144," + + "8.455131 0.859544," + + "8.180481 0.920500," + + "7.902529 1.115078," + + "7.823108 1.269800," + + "7.830482 1.403778," + + "7.791937 1.496744," + + "7.767005 1.538978," + + "7.676310 1.622311," + + "7.653637 1.650089," + + "7.585616 1.955644," + + "7.562942 1.983422," + + "7.562942 2.233422," + + "7.608289 2.400089," + + "7.630963 2.427867," + + "7.608289 2.538978," + + "7.585616 2.566756," + + "7.653637 2.705644," + + "7.630963 2.816756," + + "7.336206 3.011200," + + "7.290859 3.011200," + + "7.245511 3.011200," + + "7.041449 2.955644," + + "6.928081 2.816756," + + "6.928081 2.733422," + + "6.905407 2.622311," + + "6.860060 2.677867," + + "6.814712 2.677867," + + "6.678671 2.677867," + + "6.678671 2.733422," + + "6.769365 2.733422," + + "6.814712 2.733422," + + "6.792039 2.788978," + + "6.293219 3.066756," + + "6.225198 3.122311," + + "6.202525 3.233422," + + "6.134504 3.344533," + + "5.907767 3.261200," + + "5.862420 3.288978," + + "6.043809 3.427867," + + "6.021136 3.483422," + + "5.975788 3.483422," + + "5.930441 3.511200," + + "5.953115 3.566756," + + "5.975788 3.594533," + + "5.749052 3.788978," + + "5.703705 3.788978," + + "5.635684 3.788978," + + "5.703705 3.844533," + + "5.703705 4.011200," + + "5.499642 4.011200," + + "5.862420 4.372311," + + "5.975788 4.427867," + + "6.021136 4.427867," + + "6.089156 4.538978," + + "6.111830 4.566756," + + "6.089156 4.650089," + + "5.998462 4.650089," + + "5.817073 4.788978," + + "5.771726 4.816756," + + "5.681031 4.816756," + + "5.749052 4.927867," + + "5.749052 5.038978," + + "5.839747 5.177867," + + "5.998462 5.233422," + + "6.225198 5.233422," + + "6.270545 5.233422," + + "6.383914 5.288978," + + "6.406587 5.372311," + + "6.429261 5.400089," + + "6.587976 5.483422," + + "6.670626 5.490000," + + "6.700845 5.564100," + + "6.860060 5.927867," + + "6.860060 6.038978," + + "6.950754 6.205644," + + "6.973428 6.316756," + + "7.041449 6.344533," + + "7.064122 6.455644," + + "7.116072 6.541989," + + "7.114313 6.603667," + + "7.025305 6.741422," + + "6.736924 6.701367," + + "6.641658 6.741467," + + "6.500574 6.761389," + + "6.435410 6.733422," + + "6.224291 6.728556," + + "6.191759 6.738989," + + "6.099124 6.755000," + + "6.041805 6.749733," + + "6.001672 6.742967," + + "5.905382 6.718300," + + "5.817073 6.677867," + + "5.611713 6.686622," + + "5.401366 6.864333," + + "5.386274 6.927867," + + "5.356608 6.981811," + + "5.404095 7.111822," + + "5.561958 7.216133," + + "5.660643 7.244722," + + "5.366149 7.489478," + + "5.340927 7.511200," + + "5.114998 7.592867," + + "4.870667 7.692033," + + "4.746560 7.781856," + + "4.708060 7.760867," + + "4.692225 7.802500," + + "4.607090 7.849044," + + "4.481324 7.879711," + + "4.340031 8.093378," + + "4.181171 8.158044," + + "4.116415 8.200800," + + "4.081135 8.195278," + + "4.090912 8.272500," + + "4.032232 8.378311," + + "3.779566 8.791278," + + "3.769654 8.849022," + + "3.598177 8.955178," + + "3.576828 9.059633," + + "3.527037 9.066756," + + "3.498069 9.082022," + + "3.541865 9.174211," + + "3.542409 9.234411," + + "3.576275 9.262711," + + "3.582279 9.287744," + + "3.390995 9.316756," + + "3.209606 9.344533," + + "3.100836 9.367511," + + "2.957466 9.370756," + + "2.870844 9.366222," + + "2.777211 9.285222," + + "2.744851 9.285900," + + "2.775397 9.294867," + + "2.832661 9.341156," + + "2.868114 9.373300," + + "2.869502 9.400089," + + "2.794434 9.420178," + + "2.714423 9.440078," + + "2.641124 9.441944," + + "2.572096 9.428378," + + "2.548379 9.418600," + + "2.573130 9.388211," + + "2.563126 9.333567," + + "2.535855 9.320067," + + "2.517670 9.282778," + + "2.479488 9.260278," + + "2.483125 9.239067," + + "2.464034 9.224278," + + "2.468586 9.180556," + + "2.443129 9.168989," + + "2.439084 9.147456," + + "2.448389 9.129344," + + "2.444897 9.109600," + + "2.450720 9.097256," + + "2.444897 9.080389," + + "2.447808 9.045822," + + "2.424536 9.024011," + + "2.415811 9.000133," + + "2.442457 8.957422," + + "2.429887 8.946567," + + "2.455028 8.894556," + + "2.435936 8.879078," + + "2.413136 8.853411," + + "2.410805 8.836944," + + "2.412202 8.822133," + + "2.387533 8.789544," + + "2.386608 8.776044," + + "2.398706 8.757278," + + "2.373103 8.739511," + + "2.387070 8.769467," + + "2.375434 8.784611," + + "2.358674 8.785922," + + "2.337270 8.793167," + + "2.365195 8.790533," + + "2.399169 8.821478," + + "2.396376 8.837933," + + "2.408946 8.879078," + + "2.432218 8.894878," + + "2.414995 8.963022," + + "2.390961 8.983722," + + "2.340091 8.969389," + + "2.332091 8.946244," + + "2.340091 8.927722," + + "2.332091 8.912289," + + "2.316093 8.904067," + + "2.311730 8.874744," + + "2.288975 8.861244," + + "2.247727 8.856233," + + "2.233180 8.861889," + + "2.209436 8.859233," + + "2.231003 8.871144," + + "2.265911 8.873200," + + "2.277548 8.869600," + + "2.290635 8.873711," + + "2.299360 8.904578," + + "2.268088 8.909622," + + "2.247727 8.925256," + + "2.225734 8.920756," + + "2.208747 8.909622," + + "2.203768 8.921811," + + "2.214352 8.931822," + + "2.197138 8.933811," + + "2.148725 8.907478," + + "2.134577 8.904844," + + "2.113354 8.917222," + + "2.095107 8.918800," + + "2.079961 8.912944," + + "2.060761 8.913356," + + "2.034577 8.902656," + + "1.983589 8.895400," + + "2.033997 8.913356," + + "2.062502 8.918700," + + "2.092758 8.929811," + + "2.148090 8.928756," + + "2.168397 8.937878," + + "2.146421 8.965533," + + "2.182173 8.943933," + + "2.201537 8.951311," + + "2.239138 8.938400," + + "2.267063 8.944989," + + "2.284939 8.925767," + + "2.306887 8.926022," + + "2.311086 8.936356," + + "2.296312 8.952489," + + "2.317254 8.981122," + + "2.334939 9.003844," + + "2.374500 9.014044," + + "2.386136 9.034778," + + "2.401962 9.044656," + + "2.418723 9.044889," + + "2.426287 9.054878," + + "2.411739 9.063522," + + "2.426867 9.099311," + + "2.398362 9.125233," + + "2.373339 9.121944," + + "2.403595 9.134289," + + "2.417680 9.165778," + + "2.425860 9.192778," + + "2.423783 9.231400," + + "2.400330 9.237022," + + "2.419494 9.243567," + + "2.429815 9.246711," + + "2.449495 9.245489," + + "2.457676 9.289856," + + "2.481311 9.298211," + + "2.488585 9.334211," + + "2.520255 9.353822," + + "2.520400 9.369944," + + "2.494960 9.432511," + + "2.463671 9.469200," + + "2.406950 9.500578," + + "2.240907 9.536433," + + "2.129969 9.569467," + + "2.031530 9.607422," + + "1.932328 9.658044," + + "1.835167 9.695656," + + "1.746196 9.760744," + + "1.667446 9.789667," + + "1.575400 9.797622," + + "1.562104 9.828722," + + "1.531422 9.846800," + + "1.415859 9.888744," + + "1.315206 9.942167," + + "1.175573 10.083667," + + "1.147394 10.090267," + + "1.118064 10.086567," + + "0.990883 9.998400," + + "0.778930 9.990856," + + "0.592924 10.033144," + + "0.507490 10.125422," + + "0.419562 10.320811," + + "0.375403 10.344533," + + "0.276464 10.431189," + + "0.220170 10.534911," + + "0.181271 10.571000," + + "0.153745 10.620156," + + "0.114973 10.653889," + + "0.103274 10.707756," + + "0.097914 10.761511," + + "0.076256 10.811522," + + "0.061935 10.867833," + + "0.000000 10.960167)" + ); + vectorlayer.addFeatures([new OpenLayers.Feature.Vector(original)]); + var maxExtent = vectorlayer.getDataExtent(); + // instanciate the map + map = new OpenLayers.Map("map", { + fractionalZoom: true, + maxExtent: maxExtent, + layers: [vectorlayer] + }); + map.zoomToMaxExtent(); + map.events.register('moveend', map, function(){ + map2.setCenter(map.getCenter(), map.getZoom()); + }); + + + var vectorlayer2 = new OpenLayers.Layer.Vector('Vectorlayer simplified', { + isBaseLayer: true, + styleMap: styleMap + }); + + map2 = new OpenLayers.Map("map-simplify", { + fractionalZoom: true, + maxExtent: maxExtent, + controls: [], + layers: [vectorlayer2] + }); + map2.zoomToExtent(maxExtent); + + // Control behaviour + var lastValue = 0.1; + var simplify = function() { + var min = 0; + var max = 1; + var givenVal= parseFloat(document.getElementById('tolerance').value); + var useVal = lastValue; + if (!isNaN(givenVal)) { + if (givenVal >= min && givenVal <= max) { + useVal = givenVal; + } else { + useVal = (givenVal < min) ? min : max; + } + } + document.getElementById('tolerance').value = useVal; + vectorlayer2.removeFeatures(vectorlayer2.features); + var newLineString = original.simplify(useVal); + vectorlayer2.addFeatures([new OpenLayers.Feature.Vector(newLineString)]); + var originalVerticesCnt = original.getVertices().length; + var simplifiedVerticesCnt = newLineString.getVertices().length; + var infotxt = ''; + document.getElementById('info').innerHTML = infotxt; + lastValue = useVal; + }; + document.getElementById('tolerance').value = lastValue; + document.getElementById('simplify').onclick = simplify; + simplify(); + + var animationInterval; + var animationHandler = function(){ + if (this.value === 'Start animation') { + document.getElementById('simplify').disabled = true; + document.getElementById('animation').value = "Stop animation"; + animationInterval = window.setInterval(function(){ + var tolerance = parseFloat(document.getElementById('tolerance').value); + if (tolerance < 1) { + tolerance+=0.02; + } else { + tolerance = 0.02; + } + document.getElementById('tolerance').value = tolerance.toFixed(2); + simplify(); + }, 500); + simplify(); + } else { + if (animationInterval) { + window.clearInterval(animationInterval); + } + document.getElementById('simplify').disabled = false; + document.getElementById('animation').value = "Start animation"; + } + }; + document.getElementById('animation').onclick = animationHandler; +})(); diff --git a/lib/OpenLayers/Geometry/LineString.js b/lib/OpenLayers/Geometry/LineString.js index 02484afae2..4ecf37a3b2 100644 --- a/lib/OpenLayers/Geometry/LineString.js +++ b/lib/OpenLayers/Geometry/LineString.js @@ -547,6 +547,98 @@ OpenLayers.Geometry.LineString = OpenLayers.Class(OpenLayers.Geometry.Curve, { } return best; }, + + /** + * APIMethod: simplify + * This function will return a simplified LineString. + * Simplification is based on the Douglas-Peucker algorithm. + * + * + * Parameters: + * tolerance - {number} threshhold for simplification in map units + * + * Returns: + * {OpenLayers.Geometry.LineString} the simplified LineString + */ + simplify: function(tolerance){ + if (this && this !== null) { + var points = this.getVertices(); + if (points.length < 3) { + return this; + } + + var compareNumbers = function(a, b){ + return (a-b); + }; + + /** + * Private function doing the Douglas-Peucker reduction + */ + var douglasPeuckerReduction = function(points, firstPoint, lastPoint, tolerance){ + var maxDistance = 0; + var indexFarthest = 0; + + for (var index = firstPoint; index < lastPoint; index++) { + distance = perpendicularDistance(points[firstPoint], points[lastPoint], points[index]); + if (distance > maxDistance) { + maxDistance = distance; + indexFarthest = index; + } + } + + if (maxDistance > tolerance && indexFarthest != firstPoint) { + //Add the largest point that exceeds the tolerance + pointIndexsToKeep.push(indexFarthest); + douglasPeuckerReduction(points, firstPoint, indexFarthest, tolerance); + douglasPeuckerReduction(points, indexFarthest, lastPoint, tolerance); + } + }; + + /** + * Private function calculating the perpendicular distance + * TODO: check whether OpenLayers.Geometry.LineString::distanceTo() is faster or slower + */ + var perpendicularDistance = function(point1, point2, point){ + //Area = |(1/2)(x1y2 + x2y3 + x3y1 - x2y1 - x3y2 - x1y3)| *Area of triangle + //Base = v((x1-x2)²+(x1-x2)²) *Base of Triangle* + //Area = .5*Base*H *Solve for height + //Height = Area/.5/Base + + var area = Math.abs(0.5 * (point1.x * point2.y + point2.x * point.y + point.x * point1.y - point2.x * point1.y - point.x * point2.y - point1.x * point.y)); + var bottom = Math.sqrt(Math.pow(point1.x - point2.x, 2) + Math.pow(point1.y - point2.y, 2)); + var height = area / bottom * 2; + + return height; + }; + + var firstPoint = 0; + var lastPoint = points.length - 1; + var pointIndexsToKeep = []; + + //Add the first and last index to the keepers + pointIndexsToKeep.push(firstPoint); + pointIndexsToKeep.push(lastPoint); + + //The first and the last point cannot be the same + while (points[firstPoint].equals(points[lastPoint])) { + lastPoint--; + //Addition: the first point not equal to first point in the LineString is kept as well + pointIndexsToKeep.push(lastPoint); + } + + douglasPeuckerReduction(points, firstPoint, lastPoint, tolerance); + var returnPoints = []; + pointIndexsToKeep.sort(compareNumbers); + for (var index = 0; index < pointIndexsToKeep.length; index++) { + returnPoints.push(points[pointIndexsToKeep[index]]); + } + return new OpenLayers.Geometry.LineString(returnPoints); + + } + else { + return this; + } + }, CLASS_NAME: "OpenLayers.Geometry.LineString" }); diff --git a/tests/Geometry/LineString.html b/tests/Geometry/LineString.html index 535a0547c4..b178620af0 100644 --- a/tests/Geometry/LineString.html +++ b/tests/Geometry/LineString.html @@ -374,7 +374,67 @@ t.eq(Math.round(got), Math.round(cases[i].exp), "[case " + i + "] length calculated"); } - } + } + + function test_LineString_simplify(t){ + t.plan(8); + var ls1 = new OpenLayers.Geometry.LineString([ + new OpenLayers.Geometry.Point(0,0), + new OpenLayers.Geometry.Point(1,2.1), + new OpenLayers.Geometry.Point(1.8,3.8), + new OpenLayers.Geometry.Point(2,4), + new OpenLayers.Geometry.Point(3,4), + new OpenLayers.Geometry.Point(4,4.5), + new OpenLayers.Geometry.Point(5,5) + + ]); + var ls2 = new OpenLayers.Geometry.LineString([ + new OpenLayers.Geometry.Point(0,0), + new OpenLayers.Geometry.Point(1,2.1), + new OpenLayers.Geometry.Point(1.8,3.8), + new OpenLayers.Geometry.Point(2,4), + new OpenLayers.Geometry.Point(3,4), + new OpenLayers.Geometry.Point(4,4.5), + new OpenLayers.Geometry.Point(5,5), + new OpenLayers.Geometry.Point(0,0) + + ]); + var ls3 = new OpenLayers.Geometry.LineString([ + new OpenLayers.Geometry.Point(0,0), + new OpenLayers.Geometry.Point(1,1) + ]); + var ls5 = new OpenLayers.Geometry.LineString([ + new OpenLayers.Geometry.Point(0,0), + new OpenLayers.Geometry.Point(1,1), + new OpenLayers.Geometry.Point(2,2), + new OpenLayers.Geometry.Point(3,3), + new OpenLayers.Geometry.Point(4,4), + new OpenLayers.Geometry.Point(5,5) + + ]); + var ls6 = new OpenLayers.Geometry.LineString([ + new OpenLayers.Geometry.Point(0,0), + new OpenLayers.Geometry.Point(1,1), + new OpenLayers.Geometry.Point(1,1), + new OpenLayers.Geometry.Point(3,2) + ]); + + t.ok(ls1 instanceof OpenLayers.Geometry.LineString, 'LineString is instance of OpenLayers.Geometry.LineString'); + var simplified1 = ls1.simplify(0.5); + t.ok(simplified1 instanceof OpenLayers.Geometry.LineString, 'Simplified LineString is instance of OpenLayers.Geometry.LineString'); + t.ok(simplified1.getVertices().length <= ls1.getVertices().length, 'Simplified LineString has less or equal number of vertices'); + // The simplified version is derived from PostGIS function ST_SIMPLIFY() + t.ok(simplified1.toString() === 'LINESTRING(0 0,1.8 3.8,5 5)', 'LineString 1 was simplified correctly'); + var simplified2 = ls2.simplify(0.5); + // The simplified version is derived from PostGIS function ST_SIMPLIFY() + t.ok(simplified2.toString() === 'LINESTRING(0 0,1.8 3.8,5 5,0 0)', 'LineString 2 was simplified correctly'); + var simplified3 = ls3.simplify(0.5); + t.ok(simplified3.toString() === ls3.toString(), 'LineString with 2 vertices is left untouched'); + var simplified5 = ls5.simplify(0.0); + t.ok(simplified5.toString() === 'LINESTRING(0 0,5 5)', 'A tolerance of 0 returns the optimized version needless vertices'); + var simplified6 = ls6.simplify(0.0); + t.ok(simplified6.toString() === 'LINESTRING(0 0,1 1,3 2)', 'A tolerance of 0 returns the optimized version without doubled vertices'); + }