| <!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 © <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