Skip to content

Instantly share code, notes, and snippets.

@helderdarocha
Last active June 28, 2016 18:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save helderdarocha/47fff819307ef8488607007ebb4f8b92 to your computer and use it in GitHub Desktop.
Save helderdarocha/47fff819307ef8488607007ebb4f8b92 to your computer and use it in GitHub Desktop.
Path simplification example with Leaflet
license: cc-by-sa-4.0
height: 550
<!DOCTYPE html>
<html lang="en">
<head>
<style>
#map {
height: 500px;
width: 700px;
}
#slider {
width: 900px;
padding: 10px 20px 0 10px;
}
#info {
width: 200px;
float: left;
padding: 0 20px 0 10px;
}
textarea {
margin-left: 5px;
width: 100%;
height: 120px;
}
button {width: 100%}
input {
width: 50%;
}
</style>
<meta charset="UTF-8">
<title>Track simplification using Leaflet</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/leaflet.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/leaflet.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.2.3/leaflet.draw.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.2.3/leaflet.draw.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
</head>
<body>
<div id="info">
<form>
<h4>Original data</h4>
<p>points: <span id="val_orig_point_count">0</span>
<br/>distance: <span id="val_original_distance">0</span> meters</br>
<p><button type="button" id="btn_load">(Re)load data</button></p>
<h4>Current</h4>
<p>points: <span id="val_current_point_count">0</span>
<br/>distance: <span id="val_current_distance">0</span> meters</br>
<h4>Slider configuration</h4>
<p>Max distance<br><input type="number" id="slider_max" value="100"/> meters</p>
<p>Step<br><input type="number" id="slider_step" value="1"/> meters</p>
</form>
</div>
<div id="map"></div>
<div id="slider">
<form>
Slide to simplify path (max distance to perpendicular line segment of point to remove): <span id="val_tolerance">0</span> meters
<input type="range" id="tolerance"
name="tolerance" value="0"
min="0"
max="100"
step="1">
</form>
</div>
<script>
// SAMPLE DATA - replace this with different data in this format
var trail_data = [{lat:-23.5394387,lng:-46.6788375},{lat:-23.5396059,lng:-46.6785693},{lat:-23.5397239,lng:-46.6783333},{lat:-23.5398813,lng:-46.6781509},{lat:-23.540019,lng:-46.6779792},{lat:-23.5401567,lng:-46.6777647},{lat:-23.5402255,lng:-46.6775823},{lat:-23.5403141,lng:-46.6774642},{lat:-23.5404124,lng:-46.6773248},{lat:-23.5405993,lng:-46.677078},{lat:-23.540737,lng:-46.6769063},{lat:-23.540855,lng:-46.676724},{lat:-23.5409829,lng:-46.6765523},{lat:-23.5410714,lng:-46.6763484},{lat:-23.5411403,lng:-46.6762304},{lat:-23.5411993,lng:-46.6762626},{lat:-23.5412878,lng:-46.6762304},{lat:-23.541455,lng:-46.6762948},{lat:-23.5415632,lng:-46.6763484},{lat:-23.5417698,lng:-46.6764343},{lat:-23.541937,lng:-46.6764343},{lat:-23.5421337,lng:-46.6764772},{lat:-23.542419,lng:-46.6765094},{lat:-23.542714,lng:-46.6765738},{lat:-23.5428419,lng:-46.6766167},{lat:-23.5429599,lng:-46.6766059},{lat:-23.5430681,lng:-46.6766059},{lat:-23.5431665,lng:-46.6766274},{lat:-23.5433632,lng:-46.6766596},{lat:-23.5434812,lng:-46.6767132},{lat:-23.5436681,lng:-46.6766918},{lat:-23.5437665,lng:-46.676681},{lat:-23.5438845,lng:-46.6767025},{lat:-23.544032,lng:-46.6767025},{lat:-23.5442189,lng:-46.6767025},{lat:-23.5444845,lng:-46.6767132},{lat:-23.5446713,lng:-46.6767454},{lat:-23.5449271,lng:-46.6767454},{lat:-23.5451336,lng:-46.6767561},{lat:-23.545586,lng:-46.6768527},{lat:-23.5458713,lng:-46.6768634},{lat:-23.5460582,lng:-46.6768634},{lat:-23.5462549,lng:-46.6768634},{lat:-23.5464417,lng:-46.6768849},{lat:-23.546727,lng:-46.6769493},{lat:-23.547022,lng:-46.6769707},{lat:-23.5472679,lng:-46.6770029},{lat:-23.547504,lng:-46.6770244},{lat:-23.5479072,lng:-46.6770673},{lat:-23.5482711,lng:-46.6771209},{lat:-23.5484973,lng:-46.6771209},{lat:-23.5487826,lng:-46.6772711},{lat:-23.5491268,lng:-46.6773677},{lat:-23.5493235,lng:-46.6775286},{lat:-23.5496382,lng:-46.6774213},{lat:-23.5498349,lng:-46.6774321},{lat:-23.5502185,lng:-46.6774321},{lat:-23.5504349,lng:-46.6774642},{lat:-23.5506513,lng:-46.6774964},{lat:-23.5507791,lng:-46.6775393},{lat:-23.5510348,lng:-46.6776359},{lat:-23.5512611,lng:-46.6777647},{lat:-23.5514184,lng:-46.6778827},{lat:-23.5516348,lng:-46.6780329},{lat:-23.5518118,lng:-46.6782153},{lat:-23.5520479,lng:-46.6783762},{lat:-23.5522839,lng:-46.6785371},{lat:-23.5524019,lng:-46.6786659},{lat:-23.552579,lng:-46.6786981},{lat:-23.5526773,lng:-46.6788268},{lat:-23.5528543,lng:-46.678977},{lat:-23.5530215,lng:-46.6791058},{lat:-23.5531592,lng:-46.6791809},{lat:-23.5532969,lng:-46.6793203},{lat:-23.5534444,lng:-46.6795027},{lat:-23.553592,lng:-46.6796207},{lat:-23.5537985,lng:-46.6797817},{lat:-23.553946,lng:-46.6798997},{lat:-23.5541722,lng:-46.6800714},{lat:-23.5543591,lng:-46.6803288},{lat:-23.5544968,lng:-46.6804576},{lat:-23.554723,lng:-46.6806614},{lat:-23.5549492,lng:-46.6810584},{lat:-23.5551164,lng:-46.6812515},{lat:-23.5552639,lng:-46.681509},{lat:-23.5555098,lng:-46.6818094},{lat:-23.5556081,lng:-46.6819596},{lat:-23.5556966,lng:-46.6821849},{lat:-23.5559523,lng:-46.682539},{lat:-23.55609,lng:-46.6827106},{lat:-23.5562572,lng:-46.6828501},{lat:-23.5564736,lng:-46.682936},{lat:-23.5567686,lng:-46.6829467},{lat:-23.5571128,lng:-46.6828179},{lat:-23.55728,lng:-46.6827321},{lat:-23.5575357,lng:-46.6825604},{lat:-23.5577718,lng:-46.6824532},{lat:-23.5579095,lng:-46.6823244},{lat:-23.5580471,lng:-46.6822064},{lat:-23.5583028,lng:-46.682142},{lat:-23.5584602,lng:-46.6821206},{lat:-23.5587159,lng:-46.6820133},{lat:-23.5589913,lng:-46.6819382},{lat:-23.5591486,lng:-46.6818416},{lat:-23.5593256,lng:-46.6817236},{lat:-23.5595223,lng:-46.6815841},{lat:-23.5597092,lng:-46.681391},{lat:-23.5599747,lng:-46.6811872},{lat:-23.5602107,lng:-46.6810155},{lat:-23.5603779,lng:-46.6809082},{lat:-23.5606631,lng:-46.6807044},{lat:-23.560791,lng:-46.6806078},{lat:-23.5609778,lng:-46.6804683},{lat:-23.5611548,lng:-46.680361},{lat:-23.5613024,lng:-46.6802645},{lat:-23.5614892,lng:-46.680243},{lat:-23.5615089,lng:-46.6803288},{lat:-23.5615974,lng:-46.6802001},{lat:-23.5614991,lng:-46.6801357},{lat:-23.5616564,lng:-46.6800177},{lat:-23.5618826,lng:-46.6798139},{lat:-23.5622661,lng:-46.6795456},{lat:-23.5625513,lng:-46.6793203},{lat:-23.5628365,lng:-46.6791272},{lat:-23.5631119,lng:-46.6789448},{lat:-23.5633086,lng:-46.6787732},{lat:-23.5635348,lng:-46.6786551},{lat:-23.5637216,lng:-46.6785264},{lat:-23.5639871,lng:-46.6783118},{lat:-23.5642035,lng:-46.6781616},{lat:-23.5643412,lng:-46.6780329},{lat:-23.5644592,lng:-46.6779363},{lat:-23.5646854,lng:-46.6777325},{lat:-23.5648624,lng:-46.6775286},{lat:-23.5650394,lng:-46.6773248},{lat:-23.5652066,lng:-46.6770887},{lat:-23.5653541,lng:-46.6769385},{lat:-23.5654721,lng:-46.6767776},{lat:-23.5655704,lng:-46.6766167},{lat:-23.5657769,lng:-46.6763484},{lat:-23.5658851,lng:-46.6761553},{lat:-23.5659933,lng:-46.6759837},{lat:-23.5661408,lng:-46.6758013},{lat:-23.5662391,lng:-46.6756725},{lat:-23.5663572,lng:-46.6755116},{lat:-23.566485,lng:-46.6753614},{lat:-23.566544,lng:-46.6752005},{lat:-23.566603,lng:-46.6750932},{lat:-23.566839,lng:-46.6748464},{lat:-23.566898,lng:-46.6747713},{lat:-23.5671242,lng:-46.6745245},{lat:-23.5672422,lng:-46.6743529},{lat:-23.5673504,lng:-46.6742456},{lat:-23.5676061,lng:-46.6739881},{lat:-23.5677437,lng:-46.6738701},{lat:-23.5679208,lng:-46.6736555},{lat:-23.5680289,lng:-46.6735482},{lat:-23.5682944,lng:-46.67328},{lat:-23.5684223,lng:-46.6731191},{lat:-23.5686386,lng:-46.6729259},{lat:-23.5688156,lng:-46.6727436},{lat:-23.5689336,lng:-46.6726148},{lat:-23.5690713,lng:-46.6724861},{lat:-23.5691795,lng:-46.6723359},{lat:-23.5693467,lng:-46.6721964},{lat:-23.569445,lng:-46.6720891},{lat:-23.5696908,lng:-46.6718102},{lat:-23.5698187,lng:-46.6716385},{lat:-23.5699564,lng:-46.6714776},{lat:-23.5700842,lng:-46.6713595},{lat:-23.5702317,lng:-46.6711879},{lat:-23.5704677,lng:-46.6709304},{lat:-23.5705857,lng:-46.6708231},{lat:-23.5707431,lng:-46.6706622},{lat:-23.5709004,lng:-46.6705227},{lat:-23.5710872,lng:-46.6703403},{lat:-23.5712446,lng:-46.6702116},{lat:-23.5713429,lng:-46.6700399},{lat:-23.5714904,lng:-46.6699004},{lat:-23.5716379,lng:-46.6697824},{lat:-23.5718051,lng:-46.6695786},{lat:-23.5719526,lng:-46.6693854},{lat:-23.5721394,lng:-46.6691816},{lat:-23.5722378,lng:-46.6690528},{lat:-23.5723951,lng:-46.6688919},{lat:-23.5724934,lng:-46.6688168},{lat:-23.5725918,lng:-46.6687202},{lat:-23.5727098,lng:-46.6685808},{lat:-23.5728573,lng:-46.6684735},{lat:-23.5729753,lng:-46.6683555},{lat:-23.573113,lng:-46.6683233},{lat:-23.5732113,lng:-46.6684842},{lat:-23.5733293,lng:-46.668613},{lat:-23.5734178,lng:-46.668731},{lat:-23.573526,lng:-46.6688704},{lat:-23.5736243,lng:-46.6689777},{lat:-23.5736833,lng:-46.6691065},{lat:-23.573762,lng:-46.6692245},{lat:-23.5738406,lng:-46.6693211},{lat:-23.5739488,lng:-46.6694713},{lat:-23.5740275,lng:-46.6696107},{lat:-23.5741258,lng:-46.6697609},{lat:-23.5742045,lng:-46.6698575},{lat:-23.5743028,lng:-46.6698575},{lat:-23.5744601,lng:-46.6698039},{lat:-23.574529,lng:-46.6697073},{lat:-23.5746666,lng:-46.6695678},{lat:-23.5747551,lng:-46.669482},{lat:-23.574883,lng:-46.6695571},{lat:-23.5749518,lng:-46.6697073},{lat:-23.5750895,lng:-46.669879},{lat:-23.5751583,lng:-46.6700506},{lat:-23.5752861,lng:-46.6701686},{lat:-23.5754041,lng:-46.6702652},{lat:-23.5754238,lng:-46.670351},{lat:-23.5755123,lng:-46.6704583},{lat:-23.5756008,lng:-46.6705334},{lat:-23.575709,lng:-46.6704583},{lat:-23.5757876,lng:-46.6703081},{lat:-23.5758958,lng:-46.6701579},{lat:-23.575945,lng:-46.6700721},{lat:-23.5760925,lng:-46.6700721},{lat:-23.5761711,lng:-46.6702116},{lat:-23.57624,lng:-46.6703188},{lat:-23.5763678,lng:-46.6704583},{lat:-23.576476,lng:-46.6705549},{lat:-23.576535,lng:-46.6706836},{lat:-23.5766235,lng:-46.670866},{lat:-23.5767218,lng:-46.6710162},{lat:-23.5768791,lng:-46.6711342},{lat:-23.5770168,lng:-46.6712415},{lat:-23.5771643,lng:-46.6713166},{lat:-23.5773806,lng:-46.6713381},{lat:-23.5776265,lng:-46.6712844},{lat:-23.5778428,lng:-46.6712523},{lat:-23.5779903,lng:-46.6712308},{lat:-23.5780886,lng:-46.6712308},{lat:-23.5782066,lng:-46.6712093},{lat:-23.5785114,lng:-46.6711664},{lat:-23.5786393,lng:-46.671102},{lat:-23.5787671,lng:-46.6710806},{lat:-23.5788949,lng:-46.6710591},{lat:-23.5790523,lng:-46.6710162},{lat:-23.5791703,lng:-46.6709948},{lat:-23.5793079,lng:-46.6709733},{lat:-23.5793964,lng:-46.6709197},{lat:-23.5796127,lng:-46.6709197},{lat:-23.5797307,lng:-46.6708767},{lat:-23.5798586,lng:-46.6708446},{lat:-23.5802126,lng:-46.6708016},{lat:-23.5803699,lng:-46.6707373},{lat:-23.5806255,lng:-46.6706944},{lat:-23.5808714,lng:-46.6706622},{lat:-23.5810385,lng:-46.67063},{lat:-23.5812745,lng:-46.6705978},{lat:-23.5814318,lng:-46.6705871},{lat:-23.5815597,lng:-46.6705656},{lat:-23.5817268,lng:-46.6705441},{lat:-23.5819038,lng:-46.6705227},{lat:-23.5821398,lng:-46.6705334},{lat:-23.5823561,lng:-46.670469},{lat:-23.5825921,lng:-46.670469},{lat:-23.5827494,lng:-46.6704369},{lat:-23.5828871,lng:-46.6704047},{lat:-23.5830543,lng:-46.6703403},{lat:-23.5831919,lng:-46.6703403},{lat:-23.5833787,lng:-46.6703403},{lat:-23.5834869,lng:-46.6705871},{lat:-23.5835754,lng:-46.6708875},{lat:-23.5836344,lng:-46.6710913},{lat:-23.5836934,lng:-46.6713488},{lat:-23.5837819,lng:-46.6716385},{lat:-23.5838016,lng:-46.6718531},{lat:-23.5838605,lng:-46.6720247},{lat:-23.5835754,lng:-46.6721106},{lat:-23.5833492,lng:-46.6721964},{lat:-23.5830936,lng:-46.67225},{lat:-23.5828281,lng:-46.672411},{lat:-23.5826315,lng:-46.6724539},{lat:-23.5824545,lng:-46.672529},{lat:-23.5822775,lng:-46.6725826},{lat:-23.5822086,lng:-46.6724002},{lat:-23.5821693,lng:-46.6721213},{lat:-23.5821005,lng:-46.6719496},{lat:-23.5820218,lng:-46.6716063},{lat:-23.5819727,lng:-46.6714025},{lat:-23.581894,lng:-46.6711879},{lat:-23.5818547,lng:-46.6710269},{lat:-23.5818153,lng:-46.6709089},{lat:-23.581776,lng:-46.6707158},{lat:-23.581776,lng:-46.6704261},{lat:-23.581953,lng:-46.6703939},{lat:-23.5821201,lng:-46.6703725},{lat:-23.5822873,lng:-46.670351},{lat:-23.5824741,lng:-46.6703081},{lat:-23.5826511,lng:-46.6702867},{lat:-23.5828674,lng:-46.6702545},{lat:-23.5829854,lng:-46.6702437},{lat:-23.5831526,lng:-46.6702008},{lat:-23.5833001,lng:-46.6701794},{lat:-23.5834771,lng:-46.6701794},{lat:-23.5836541,lng:-46.6701794},{lat:-23.5838409,lng:-46.6702008},{lat:-23.5839589,lng:-46.6702652},{lat:-23.584185,lng:-46.6702974},{lat:-23.5844013,lng:-46.6703939},{lat:-23.5846078,lng:-46.6704583},{lat:-23.5847357,lng:-46.6705334},{lat:-23.5850208,lng:-46.6706407},{lat:-23.585306,lng:-46.6707158},{lat:-23.5854928,lng:-46.6708231},{lat:-23.5857386,lng:-46.6709411},{lat:-23.5860336,lng:-46.6711128},{lat:-23.586358,lng:-46.6713059},{lat:-23.586535,lng:-46.6713488},{lat:-23.58683,lng:-46.6714454},{lat:-23.5870168,lng:-46.6715312},{lat:-23.5872233,lng:-46.6715634},{lat:-23.5874003,lng:-46.671617},{lat:-23.5875478,lng:-46.6716492},{lat:-23.5877837,lng:-46.6717243},{lat:-23.5880885,lng:-46.6718209},{lat:-23.5882262,lng:-46.6718638},{lat:-23.5883737,lng:-46.671896},{lat:-23.5885998,lng:-46.6719925},{lat:-23.5888063,lng:-46.6720569},{lat:-23.5890226,lng:-46.6721106},{lat:-23.5892389,lng:-46.6721749},{lat:-23.5895437,lng:-46.6722608},{lat:-23.589878,lng:-46.6723359},{lat:-23.5900648,lng:-46.672411},{lat:-23.5904286,lng:-46.6724968},{lat:-23.5906155,lng:-46.672529},{lat:-23.5908514,lng:-46.6725934},{lat:-23.5910972,lng:-46.6726255},{lat:-23.5913234,lng:-46.6727114},{lat:-23.5917265,lng:-46.6727757},{lat:-23.5920411,lng:-46.6728079},{lat:-23.5922181,lng:-46.6728187},{lat:-23.5926802,lng:-46.6729045},{lat:-23.5928473,lng:-46.6729152},{lat:-23.5930538,lng:-46.6729474},{lat:-23.5931816,lng:-46.6729474},{lat:-23.5934274,lng:-46.6729581},{lat:-23.5936241,lng:-46.6729689},{lat:-23.59386,lng:-46.6729796},{lat:-23.5940075,lng:-46.6730332},{lat:-23.594214,lng:-46.673044},{lat:-23.5944303,lng:-46.6730869},{lat:-23.5946269,lng:-46.6731191},{lat:-23.5948334,lng:-46.6731298},{lat:-23.5952168,lng:-46.6731834},{lat:-23.5954331,lng:-46.6732156},{lat:-23.5955413,lng:-46.6732156},{lat:-23.5959149,lng:-46.6733229},{lat:-23.5960329,lng:-46.6733873},{lat:-23.5961902,lng:-46.6734517},{lat:-23.5963967,lng:-46.6735804},{lat:-23.596672,lng:-46.673677},{lat:-23.5968194,lng:-46.6737843},{lat:-23.5969866,lng:-46.6738594},{lat:-23.5972127,lng:-46.6739666},{lat:-23.5974487,lng:-46.6739881},{lat:-23.5976453,lng:-46.6740203},{lat:-23.5978911,lng:-46.6740203},{lat:-23.5984318,lng:-46.6739774},{lat:-23.598658,lng:-46.6739774},{lat:-23.5988153,lng:-46.6739881},{lat:-23.5990119,lng:-46.6739666},{lat:-23.5992478,lng:-46.6739666},{lat:-23.5995035,lng:-46.6739666},{lat:-23.5997591,lng:-46.6739666},{lat:-23.599995,lng:-46.6740096},{lat:-23.6002605,lng:-46.6739881},{lat:-23.6004964,lng:-46.6740417},{lat:-23.6007226,lng:-46.6740203},{lat:-23.6009782,lng:-46.6740417},{lat:-23.601165,lng:-46.6740847},{lat:-23.6013714,lng:-46.6741383},{lat:-23.6016172,lng:-46.6741383},{lat:-23.601745,lng:-46.6741705},{lat:-23.6018925,lng:-46.674192},{lat:-23.6020301,lng:-46.6742563},{lat:-23.6021776,lng:-46.6743207},{lat:-23.6020891,lng:-46.6745353},{lat:-23.6020301,lng:-46.6747713},{lat:-23.6019318,lng:-46.6749001},{lat:-23.6018532,lng:-46.6751039},{lat:-23.6017942,lng:-46.6752756},{lat:-23.6016959,lng:-46.6754901},{lat:-23.6015976,lng:-46.6756296},{lat:-23.6015091,lng:-46.6757476},{lat:-23.6014501,lng:-46.6758657},{lat:-23.6013223,lng:-46.6757476},{lat:-23.6012141,lng:-46.6756833},{lat:-23.601106,lng:-46.6756296},{lat:-23.6009782,lng:-46.6755223},{lat:-23.60087,lng:-46.675458},{lat:-23.6007717,lng:-46.6754258},{lat:-23.6006636,lng:-46.6753507},{lat:-23.6005358,lng:-46.6752756},{lat:-23.6003981,lng:-46.6751897},{lat:-23.6002113,lng:-46.6751254},{lat:-23.6000934,lng:-46.6750717},{lat:-23.5999262,lng:-46.6749644},{lat:-23.5997787,lng:-46.6749215},{lat:-23.5996706,lng:-46.674825},{lat:-23.5994543,lng:-46.6752434},{lat:-23.5993265,lng:-46.6756082},{lat:-23.5992085,lng:-46.6758549},{lat:-23.5990316,lng:-46.6761661},{lat:-23.5989332,lng:-46.6764021},{lat:-23.5988349,lng:-46.6765738},{lat:-23.5986481,lng:-46.6769922},{lat:-23.5985695,lng:-46.6772175},{lat:-23.5984712,lng:-46.6774857},{lat:-23.5981959,lng:-46.6779792},{lat:-23.5980877,lng:-46.6781402},{lat:-23.5979992,lng:-46.6784942},{lat:-23.5979206,lng:-46.6786659},{lat:-23.5977534,lng:-46.6789556},{lat:-23.5976355,lng:-46.679256},{lat:-23.5975273,lng:-46.6794384},{lat:-23.5974782,lng:-46.6795564},{lat:-23.597488,lng:-46.6797173},{lat:-23.5977534,lng:-46.6798246},{lat:-23.5981074,lng:-46.6799963},{lat:-23.5983138,lng:-46.6801357},{lat:-23.598422,lng:-46.6799748},{lat:-23.5985301,lng:-46.679728},{lat:-23.5987858,lng:-46.6792238},{lat:-23.5989627,lng:-46.6788483},{lat:-23.5990119,lng:-46.6786015},{lat:-23.5990905,lng:-46.6784084},{lat:-23.5991594,lng:-46.6782475},{lat:-23.5992872,lng:-46.6780972},{lat:-23.5993265,lng:-46.6779149},{lat:-23.5994248,lng:-46.6777754},{lat:-23.599474,lng:-46.6776145},{lat:-23.599592,lng:-46.6773999},{lat:-23.5996313,lng:-46.677314},{lat:-23.5996706,lng:-46.6772121},{lat:-23.5997198,lng:-46.6771048},{lat:-23.5997738,lng:-46.6770083},{lat:-23.5998132,lng:-46.6768903},{lat:-23.5998771,lng:-46.6767561},{lat:-23.5999016,lng:-46.6766757},{lat:-23.5998082,lng:-46.6766381},{lat:-23.5997247,lng:-46.6766381},{lat:-23.5996313,lng:-46.6766274},{lat:-23.5995625,lng:-46.6765845},{lat:-23.5994986,lng:-46.6765362},{lat:-23.5994936,lng:-46.6763967},{lat:-23.5995428,lng:-46.6763109},{lat:-23.5996214,lng:-46.6762626}];
// PATH SIMPLIFICATION ALGORITHM
// Douglas Peucker path simplification algorithm
// This code is based on https://gist.github.com/adammiller/826148
var Line = function( p1, p2 ) {
this.p1 = p1;
this.p2 = p2;
this.distanceToPoint = function( point ) {
// slope
var m = ( this.p2[0] - this.p1[0] ) / ( this.p2[1] - this.p1[1] ),
// y offset
b = this.p1[0] - ( m * this.p1[1] ),
d = [];
// distance to the linear equation
d.push( Math.abs( point[0] - ( m * point[1] ) - b ) / Math.sqrt( Math.pow( m, 2 ) + 1 ) );
// distance to p1
d.push( Math.sqrt( Math.pow( ( point[1] - this.p1[1] ), 2 ) + Math.pow( ( point[0] - this.p1[0] ), 2 ) ) );
// distance to p2
d.push( Math.sqrt( Math.pow( ( point[1] - this.p2[1] ), 2 ) + Math.pow( ( point[0] - this.p2[0] ), 2 ) ) );
// return the smallest distance
return d.sort( function( a, b ) {
return ( a - b ); //causes an array to be sorted numerically and ascending
} )[0];
};
};
var simplify = function(points, tolerance) {
var douglasPeucker = function( points, tolerance ) {
if ( points.length <= 2 ) {
return [points[0]];
}
var returnPoints = [],
// make line from start to end
line = new Line( points[0], points[points.length - 1] ),
// find the largest distance from intermediate poitns to this line
maxDistance = 0,
maxDistanceIndex = 0,
p;
for( var i = 1; i <= points.length - 2; i++ ) {
var distance = line.distanceToPoint( points[ i ] );
if( distance > maxDistance ) {
maxDistance = distance;
maxDistanceIndex = i;
}
}
// check if the max distance is greater than our tollerance allows
if ( maxDistance >= tolerance ) {
p = points[maxDistanceIndex];
line.distanceToPoint( p, true );
// include this point in the output
returnPoints = returnPoints.concat( douglasPeucker( points.slice( 0, maxDistanceIndex + 1 ), tolerance ) );
// returnPoints.push( points[maxDistanceIndex] );
returnPoints = returnPoints.concat( douglasPeucker( points.slice( maxDistanceIndex, points.length ), tolerance ) );
} else {
// ditching this point
p = points[maxDistanceIndex];
line.distanceToPoint( p, true );
returnPoints = [points[0]];
}
return returnPoints;
};
var result = douglasPeucker( points, tolerance );
// always have to push the very last point on so it doesn't get left off
result.push( points[points.length - 1 ] );
return result;
};
// Polyline distanceTo - calculates an approximate distance
// From http://stackoverflow.com/questions/31221088/how-to-calculate-the-distance-of-a-polyline-in-leaflet-like-geojson-io
L.Polyline = L.Polyline.extend({
getDistance: function() { // in meters
var d = 0;
for (var i = 1; i < this._latlngs.length; i++) {
d += this._latlngs[i].distanceTo(this._latlngs[i - 1]);
}
return d;
}
});
// GLOBAL VARS
// original points (ajax load this from a file or database)
var original = [];
// this will locally store points after editing and simplification
// after editing, the points array changes and can only be restored
// by reloading the data
var points = cloneCoords(original);
// this will locally store points during simplification
// it will allow you to slide in both directions while applying the algorithm
var simplified = cloneCoords(original);
var track; // this will be the L.polyline containing the points
$("#tolerance").prop("disabled", true);
// FUNCTIONS
// makes a deep copy of the array
function cloneCoords(sourceArray) {
var destArray = [];
for(var i = 0; i < sourceArray.length; i++) {
destArray.push([sourceArray[i][0], sourceArray[i][1]]);
}
return destArray;
}
// Converts [{lat,lng},...,{lat,lng}] to [[0][1],...,[0][1]]
function convertToArrayOfArray(sourceArray) {
var destArray = [];
for(var i = 0; i < sourceArray.length; i++) {
destArray.push([sourceArray[i].lat, sourceArray[i].lng]);
}
return destArray;
}
function formatNumber(number) {
return Math.round(number * 100)/100;
}
// These two functions allow you to express the epsilon factor
// (max distance to perpendicular line segment of point to remove)
// in metres.
// About this value see
// https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm
function degreesToMeters(degrees) { // this is approximate (spherical earth, average circumference, not considering altitude, etc.)
var earth = 40075000; // average circumference in metres at sea level
return degrees * earth / 360.0;
}
function metersToDegrees(meters) { // this is approximate (spherical earth, average circumference, not considering altitude, etc.)
var earth = 40075000; // average circumference in metres at sea level
return meters * 360.0 / earth;
}
// Apply simplification algorithm using specified tolerance & redraw shape
// Save points in memory
function simplifyPath() {
var toleranceInDegrees = metersToDegrees($('#tolerance').val()); // value from slider
simplified = simplify(points, toleranceInDegrees);
// change the array for the path & redraw
track.setLatLngs(simplified);
$("#val_tolerance").html(formatNumber(degreesToMeters(toleranceInDegrees)));
$("#val_current_distance").html(formatNumber(track.getDistance()));
$("#val_current_point_count").html(simplified.length);
}
// Load data and revert shape to original points
function loadFromDatabase() {
if(points.length == 0 || confirm("Reset all changes and revert to original path?")) {
// mock data - load your points from database into this variable
original = convertToArrayOfArray(trail_data);
points = cloneCoords(original);
simplified = cloneCoords(original);
if(!track) {
track = L.polyline(points)
.addTo(trailLayer);
} else {
track.setLatLngs(points);
}
$("#tolerance").val(0);
$("#tolerance").prop("disabled", false);
$("#val_tolerance").html("0");
$("#val_original_distance").html(formatNumber(track.getDistance()));
$("#val_current_distance").html(formatNumber(track.getDistance()));
$("#val_orig_point_count").html(original.length);
$("#val_current_point_count").html(points.length);
}
}
function saveToDatabase() {
alert("Save path to database")
// insert here your ajax call to send the data to the server.
}
// MAP
map = new L.Map('map');
var osmUrl = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
var osmAttrib = 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors';
var osm = new L.TileLayer(osmUrl, {
maxZoom: 22,
attribution: osmAttrib
});
map.addLayer(osm);
// original trail for comparison
var trailPath_opti = L.polyline(trail_data, {
color: '#3EA9DE'}).addTo(map);
map.fitBounds(trailPath_opti.getBounds());
// Add the editable layer (renamed mygroup to trailLayer)
var trailLayer = L.featureGroup().addTo(map);
var polyline_options = {
color: '#000'
};
// Initialise the draw control and pass it the FeatureGroup of editable layers
var drawControl = new L.Control.Draw({
draw: false,
edit: {
featureGroup: trailLayer
}
}).addTo(map);
// Editing events
// Using this to disable the slider
map.on('draw:editstart', function (e) {
console.log("started editing")
$("#tolerance").prop("disabled", true);
});
// updates the points aray with the edited array
map.on('draw:edited', function (e) {
console.log("finished editing")
var editedPoints = [];
var coords = track._latlngs;
for (var i = 0; i < coords.length; i++) {
var obj = coords[i];
editedPoints.push([obj.lat, obj.lng]);
}
console.log("edited points length", editedPoints.length)
points = cloneCoords(editedPoints);
$("#val_current_point_count").html(points.length);
$("#val_current_distance").html(formatNumber(track.getDistance()));
$("#tolerance").val(0);
$("#val_tolerance").html("0");
});
// Using this to enable the slider
map.on('draw:editstop', function (e) {
console.log("saved or cancelled")
$("#tolerance").prop("disabled", false);
});
// HTML BINDINGS
$('#tolerance').on("input", simplifyPath);
$('#btn_load').on("click", loadFromDatabase);
$('#btn_save').on("click", saveToDatabase);
$('#slider_max').on("change", function() {
$('#tolerance').prop("max", $(this).val());
});
$('#slider_step').on("change", function() {
$('#tolerance').prop("step", $(this).val());
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment