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
This commit is contained in:
ahocevar
2010-12-15 13:38:52 +00:00
parent b61cec71a1
commit e9e2aec77d
4 changed files with 838 additions and 1 deletions

View File

@@ -0,0 +1,86 @@
<!DOCTYPE html>
<html>
<head>
<title>Simplify LineString</title>
<link rel="stylesheet" href="../theme/default/style.css" type="text/css">
<link rel="stylesheet" href="style.css" type="text/css">
<style type="text/css">
#map, #map-simplify {
height: 400px;
width: 400px;
margin: 5px !important;
float: left;
}
#info {
width: 300px;
float: left;
}
</style>
</head>
<body>
<h1 id="title">Simplify a LineString</h1>
<div id="tags">
Douglas-Peucker, Douglas, Peucker, Peuker, tolerance
</div>
<p id="shortdesc">
Shows the usage of the utility method "simplifyLineString" that
implements the Douglas-Peucker algorithm to remove "insignificant"
vertices from LineString geometries.
</p>
<div id="control-simplify">
<input name="tolerance" id="tolerance" type="number" min="0" max="1" step="0.02" value="0.1">
<input type="button" id="simplify" value="Simplify LineString">
<input type="button" id="animation" value="Start animation">
</div>
<div id="map" class="smallmap">
</div>
<div id="map-simplify" class="smallmap">
</div>
<div id="info">
</div>
<div id="docs" style="clear: both;">
<p>
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.
</p>
<p>
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.
</p>
<p>
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.
</p>
<p>
The LineString
represents a part of the coastline of
<a href="http://www.openstreetmap.org/?lat=54.7309684753418&lon=83.1809234619141&zoom=11">this
place in Russia</a> &mdash; found via <a href="http://ryba4.com/python/ramer-douglas-peucker">an
example implementation of the algorithm in python</a>.
</p>
<p>
For a detailled explanation of the algorithm see
<a href="http://en.wikipedia.org/wiki/Douglas-Peucker_algorithm">the
Wikipedia article</a> or the original publication: David Douglas
&amp; 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)
(<a href="http://dx.doi.org/10.3138/FM57-6770-U75U-7727">DOI:
10.3138/FM57-6770-U75U-7727</a>).
</p>
</div>
<script type="text/javascript" src="../lib/OpenLayers.js">
</script>
<script type="text/javascript" src="simplify-linestring.js">
</script>
</body>
</html>

View File

@@ -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 = '<ul><li>Original LineString: <strong>';
infotxt += originalVerticesCnt + ' vertices</strong></li>';
infotxt += ' <li>Simplified geometry: <strong>' + simplifiedVerticesCnt + ' vertices</strong></li>';
infotxt += ' <li>Decreased by <strong>' + (((originalVerticesCnt-simplifiedVerticesCnt)/originalVerticesCnt)*100).toFixed(2) + ' per cent</strong></li></ul>';
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;
})();

View File

@@ -547,6 +547,98 @@ OpenLayers.Geometry.LineString = OpenLayers.Class(OpenLayers.Geometry.Curve, {
} }
return best; 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" CLASS_NAME: "OpenLayers.Geometry.LineString"
}); });

View File

@@ -374,7 +374,67 @@
t.eq(Math.round(got), Math.round(cases[i].exp), "[case " + i + "] length calculated"); 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');
}
</script> </script>
</head> </head>