From 63a956785862c4c9bb48139caafc14b907b55c03 Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Wed, 26 Dec 2012 18:25:04 +0100 Subject: [PATCH 1/9] Format: Added EncodedPolyline class This class is able to convert an encoded polyline string into a LineString embedded in a Vector Feature. See https://developers.google.com/maps/documentation/utilities/polylinealgorithm for more information. --- lib/OpenLayers.js | 1 + lib/OpenLayers/Format/EncodedPolyline.js | 85 ++++++++++++++++++++++++ tests/Format/EncodedPolyline.html | 41 ++++++++++++ tests/list-tests.html | 1 + 4 files changed, 128 insertions(+) create mode 100644 lib/OpenLayers/Format/EncodedPolyline.js create mode 100644 tests/Format/EncodedPolyline.html diff --git a/lib/OpenLayers.js b/lib/OpenLayers.js index 4df00ddf62..b6d5b397ff 100644 --- a/lib/OpenLayers.js +++ b/lib/OpenLayers.js @@ -306,6 +306,7 @@ "OpenLayers/Format/GML/v2.js", "OpenLayers/Format/GML/v3.js", "OpenLayers/Format/Atom.js", + "OpenLayers/Format/EncodedPolyline.js", "OpenLayers/Format/KML.js", "OpenLayers/Format/GeoRSS.js", "OpenLayers/Format/WFS.js", diff --git a/lib/OpenLayers/Format/EncodedPolyline.js b/lib/OpenLayers/Format/EncodedPolyline.js new file mode 100644 index 0000000000..237782b7f7 --- /dev/null +++ b/lib/OpenLayers/Format/EncodedPolyline.js @@ -0,0 +1,85 @@ +/* Copyright (c) 2006-2012 by OpenLayers Contributors (see authors.txt for + * full list of contributors). Published under the 2-clause BSD license. + * See license.txt in the OpenLayers distribution or repository for the + * full text of the license. */ + +/** + * @requires OpenLayers/Format.js + * @requires OpenLayers/Feature/Vector.js + */ + +/** + * Class: OpenLayers.Format.EncodedPolyline + * Class for reading and writing encoded polylines. Create a new instance + * with the constructor. + * + * Inherits from: + * - + */ +OpenLayers.Format.EncodedPolyline = OpenLayers.Class(OpenLayers.Format, { + + /** + * Constructor: OpenLayers.Format.EncodedPolyline + * Create a new parser for encoded polylines + * + * Parameters: + * options - {Object} An optional object whose properties will be set on + * this instance + * + * Returns: + * {} A new encoded polylines parser. + */ + initialize: function(options) { + OpenLayers.Format.prototype.initialize.apply(this, [options]); + }, + + /** + * Method: read + * Deserialize an encoded polyline string and return a vector feature. + * + * Parameters: + * encoded - {String} An encoded polyline string + * + * Returns: + * {} A vector feature with a linestring. + */ + read: function(encoded) { + var points = new Array(); + + var lat = 0; + var lon = 0; + + for (var i = 0; i < encoded.length;) { + var b; + var result = 0; + var shift = 0; + + do { + b = encoded.charCodeAt(i++) - 63; + result |= (b & 0x1f) << shift; + shift += 5; + } while (b >= 0x20); + + lat += ((result & 1) ? ~(result >> 1) : (result >> 1)); + + result = 0; + shift = 0; + + do { + b = encoded.charCodeAt(i++) - 63; + result |= (b & 0x1f) << shift; + shift += 5; + } while (b >= 0x20); + + lon += ((result & 1) ? ~(result >> 1) : (result >> 1)); + + points.push(new OpenLayers.Geometry.Point(lon * 1e-5, lat * 1e-5)); + } + + return new OpenLayers.Feature.Vector( + new OpenLayers.Geometry.LineString(points) + ); + }, + + CLASS_NAME: "OpenLayers.Format.EncodedPolyline" +}); diff --git a/tests/Format/EncodedPolyline.html b/tests/Format/EncodedPolyline.html new file mode 100644 index 0000000000..29e0a65709 --- /dev/null +++ b/tests/Format/EncodedPolyline.html @@ -0,0 +1,41 @@ + + + + + + + + diff --git a/tests/list-tests.html b/tests/list-tests.html index 8c37464b84..dfcaa2f4a0 100644 --- a/tests/list-tests.html +++ b/tests/list-tests.html @@ -66,6 +66,7 @@
  • Format/XML/VersionedOGC.html
  • Format/ArcXML/Features.html
  • Format/CQL.html
  • +
  • Format/EncodedPolyline.html
  • Format/GeoJSON.html
  • Format/GeoRSS.html
  • Format/GML.html
  • From 88a3091a908177507938f644e42edb8a3ff8d36c Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Thu, 27 Dec 2012 19:49:49 +0100 Subject: [PATCH 2/9] examples: Added example for the EncodedPolyline Format class --- examples/encoded-polyline.html | 47 ++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 examples/encoded-polyline.html diff --git a/examples/encoded-polyline.html b/examples/encoded-polyline.html new file mode 100644 index 0000000000..d084d13148 --- /dev/null +++ b/examples/encoded-polyline.html @@ -0,0 +1,47 @@ + + + + + + + + + + + + +

    Encoded Polyline Example

    + +
    + Encoded Polyline, Google +
    + +

    + Demonstrate the use of the Encoded Polyline format. +

    +
    +
    +

    This example uses the Encoded Polyline format.

    +
    + + From aedafc03362a2dcb3de1900c481ebdd47cab8621 Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Thu, 27 Dec 2012 21:36:30 +0100 Subject: [PATCH 3/9] EncodedPolyline: Added geometryType attribute This makes it possible to read polygons or multipoints too. Since the encoded format is just a list of points the reader needs to be told what Feature to create from the encoded list. The example code is edited to reflect that API extension. --- examples/encoded-polyline.html | 2 +- lib/OpenLayers/Format/EncodedPolyline.js | 26 ++++++++++++++- tests/Format/EncodedPolyline.html | 41 ++++++++++++++++++++---- 3 files changed, 61 insertions(+), 8 deletions(-) diff --git a/examples/encoded-polyline.html b/examples/encoded-polyline.html index d084d13148..c40a243201 100644 --- a/examples/encoded-polyline.html +++ b/examples/encoded-polyline.html @@ -22,7 +22,7 @@ map.setCenter(new OpenLayers.LonLat(lon, lat), zoom); var encoded = "m}e`IqvbgAkJqyAoI}w@wTupA}Myb@{CmFsDcEuEgCgFa@oFj@mNzFsFpEiLpQmDxIkMxa@cGpVqE`XqC~Y_Bfw@b@jdAyAzHyCeBRmGlDIp@zHcDpBi@kG`D{@hArHuCtDqBiEhCsCxBfGiBzGcE@{@yF|GtBg@xIsDrB{BcEbAoFnDt@t@|I{BxGiDgABqG`DkAzBbG_A`IoDd@q@cGrD}AhBvGcC~FgDeBbAwF~DjBPrIqDjC}B}DlBmF|DvARbJeDlEuCqCfAiFdExAh@fIwCbEuCgCf@mG~CqBdDvDE|IgDzCsBaE~AgFvD|BV|IsCvG{Et@qCgERaHnCyElEBtCrFMrI_D|DqCyCz@_GlQ~ApEcBdq@es@vx@srApC_Fjc@}y@fCoEfCkCtCvArAvHf@tJCbJeBnHqDrD_E\\qDuC{AeHTaHvBsDbD?lEvPbD~C~Jb@`DaCvDjAStJmEnCwDmAEsGxDoA}B|S}AuEdC}DfEfDNbJmDjCsB}Dj@wG~CyDvJaE~HkHxMwOjMiMjMoK~KeGfEmDdHaMvLka@tNc]pLeSzMcQ|I_UjEcOnCaOh@oG~@iPc@gGqBwEuCmDuCuCeDyA{DHoP|FyIpG{BtF}@lIRzUcAbI_Np\\uHrKsGpOgMtm@o\\bdA_Qvo@uHb_@{Gl^_Df^iB`JyCvHgEnCuCyCzEkCt@rKiC|FyD^sBsD|@cEhDRtBtF_FpNeD}Ag@kFpAgE|Co@pCjECjJkDlEmDqCIqG`C{CvDdBpAfI_BhIgEpCwG_InAmEhDe@~CvDt@hIsAnIsDjEcEWwAqFz@qGfDgChD|DsF|L_AeFdCqBxC|FoAdIoEn@cB{E|A{DlDrC\\rIiCrG_E`@yA}DpAoEbDI|BbFF|IkCrGaEp@eC{CYmF|AkD`DDrCzEHvIkCdGkEEyA{ExAkElDF|BbGm@hJaErDyD_B{@gGzAqElDRlBzGk@pJuDtEaEeAq@wGlBgEnDQ|CbFmAhTqEvAaFcLf@kGpCqMvBaUvA_FvCcD`E`BxAtIaHlK{BgEn@uGjDqApDhE`AxJiA|IkDpCsDuAcBoF~D}K~CiBzIwBtWoJlRoI`VsLzPmKrv@_r@`e@m`@jKcK|IuKpYeWbDmBrDhCNnIyC`EkD}Aa@yFtAyD|CJdBxHiB|GoDEgBuEk@oFf@{ErD]fBvGqG`LuCmBAmF`DgAtCbGHnIoBpG{DnA}BcDt@uFxD]tCbGNnIwCnI{DB_BmEz@sF`EBrB|Ga@xI}BnFsDR{BoDm@oF]wNwDy]gEap@eFu^YmOu@yFmB_FwCuD{DaC}q@oT_Y{Eo_@{E{Oq@}DHoYtCiEtCkBbI~@xIhDnClBoDoAoF}DCeCxFHbJpBzGnDj@hA{E}BsD}DdDo@tJtBnGjDSeA}LuDdCa@lJfC~FrDbA~CeCx@qGoC}DiDvDBbJnDrCpCyCUyFsDYqBfH`AdIlDtBdC}CC{FgCiCqDfDm@rJdAvIbD~EfE[nB{EqAeFgEL{DpEuAfJ~@lJnDtEfEDjCyDNmGsBcEcEr@eCbIf@nKvDtErDiAv@_GsB}DwDr@wIdMcO~OcE~CoEpA{EUaDqDR_GrDl@T`JsDzCwC_Dh@uFzDIvChFFpJ_DzFkEAmBmFIyGnDmB`ChGgAbIaEGYeGxD[nAnHoChF_DkC\\cGlDcAzCdEt@tIcBrHyDdAuBgEn@kG`DyAbDfDp@tI}BlGaE\\qBqE`@mGlDmB`DpDBrIcDbEcEEgCaE]aHxBqEtErA`CpHO~J_CnIyD`CuCeDEsHfC}E`EDlCfGLdK}BvHgE`BsDaCcAqGlA}F`D{AfDvBbB~H]lJyCxFkERkCkE]cHxAoFpDyA~DIvDq@tUiKhFuAnNv@vNCxZoBpE@rd@pEpRRhLi@rPuBvj@sLbNwE|I{@tD~A~CbEzBjHjCpTnCjm@tAnv@u@vv@}DtnAyA`T}Jpd@wNxa@_Srd@iAbHBvIrAbIhDlC`CeDo@gGiDgAwCfEu@dIf@zHlB`H~CpD`CaCaAoFwDRkAhIdBbH|CY?uF_DmByCbENrIhDhD`CkCoAeFyDj@gBfHdA~HhDhBfBiDkAgFaERmBjHz@rIdD|BdAkKsDk@}BbGl@hIbD|BvBeD{@yFoDm@wBnG|@xHlDtA~A_E{AcFwDP_B`HnAlHjDbAxAqE{A{EqDXeBvGxAtHtDLn@yFaCgDcDtBk@zH`CxFpDa@f@cGaCuDgDfAkAhHhAjHdDnBfCmCOkG{ByDkN_PsIwL{^}o@}M}PqZw[_f@gk@sb@o_@wJkFie@yRwSmEuE[qEnA{E\\wCqCDuFxCy@dBtG}BhGmDsAOaFxCoAzC`EHtIeDzDuCoC^iFbDSlBfGkAlIsDdBuBeDz@mEpDdA|@jIwBlGuDBgTqo@kLcm@cEwNqT}y@eIib@kLqc@yLuZcNgb@kOua@gOgYuMwa@}B{EoInDmB`JWfK~AtHpDd@tAqEwBsDwDlCBlIhG_BmCgD}CfEt@fI`EJ^mGeDiB{CzEf@|IjDtA|AyFmBsEsDtAjAlQxCsBu@gGcEj@yAzHvBrG~CqASuGcEOcBtHvBpG`DyAK{GgDsBwCtFfAhIrDDn@eGkCsD}CpEx@~IhDFGaG_EUwAjIzBbGpC_BSwGkb@c`A_CgHsb@scB}S_eAkHa\\gYunAgKy\\qVa`AaHy_@aUcbA}Nwt@{BuHeHmLaC{FyAuGd@mGhDs@pChGg@lJmDhCuC_C_@{EvBgCrDjCpAnI{ApIsDdAmB_DXmFtCwBnDzB~@`JeCbHsDf@gE{Hw@{MiBuLmAmG_XwpAaRoiAyQux@_Ho_@gPkn@o@uHp@gIpDqCpCbGiBfGwDiA]qGjCkD|DvB\\nIqCfEyCqBz@yFjE~@\\vIcD`CmBkEhA{GfEApA~HcC`FwDkAcByFiFoWaHyUcByMiGcYmSoq@uSs_@uh@yx@{O}XyIyPsNy_@yU}g@wb@ss@ui@qw@eJ{JgU}Oko@ko@gEoDeLaFaCuEp@iGtDg@`B`IiCvF{CmBLcGtCkCxDlC`@pJeCxH}DnCaEe@kC}DeBgFoCyCcEl@cBnHvCtEjCaE{AoF}Df@iCvGHtJhDzErD}Aj@mGqBuF{CwBcIcB{HwD_SyRoa@gh@mt@mfAyn@st@sS_X{^qo@}Vii@y\\_h@mM_UgE{L|@uFnEf@lCtHYjJ{CfFwDf@aMiIeDw@sCiBoB}CsDkMgOmw@_Nox@SwG^eHlDyBzBzFwAjG}DS{AoFlB{EzC|DeA`HcDu@R}FpDR^|HeDzAm@kFhDyA~A|GeCtE}BeD~AcFhDrCShIiD|@]oGlDiA~@tH_DnDcBmEfCeDfC~F_BnHeDiAp@iGjDxAH~IkDvBsAkFnCyC|BjGiBlHsD_@NcGrDp@BnIsDdCqBaE|BwD|CnEcAzHsDLg@gG|CiBjCdFSbJsDbBsAoFpCqC`CpF_BpGcDoARgGlDSbBhHyApHyDp@g@oFjDSZjJiClGiD[f@_GvDbBBvJkC~EaCeDrBoEdDzDw@pHiDq@`@iG|DDnAfH}CrDsBqE`CiDdCvFcB`HmDmAj@sGfEp@p@nIiDnCcBqEbCwDfD|NiDnAmAqFZyHy@aH}B{EmVuYqJkNmI_SuNco@eEgBsBrGfCpG`EwDyAqEkChFzB`HrDiBu@mFmD~Bn@jIbELt@sG}CcBcBxGtCdFfDqCg@mGsDb@q@hIrDdElCaEgAuFmD`AYbIrDjD~CkD]kHqBuGwc@}kAyd@stAkHyUa[}dA}Tsq@kGgPkSuc@oa@ubAsP{^{EiNkM{h@uS_qAqEi`@kEmb@_D}b@iXqlDuEib@wHoj@aJ{cA_K{z@cJqo@iGkm@cIqm@aW{eBqEc`@cNqfAwOqfA}DaT_Du_@aFsNsDeAwDxAyCzFYdJjCjFhD{@u@qLoDvBu@|IpB~GpGyEiAeFiDHgBrRfDnDdDsBDaHmCoCmDnCq@fJfC~F|Dq@bAyFyA}DiDOiDfEu@rItA`I|D~BnCiDg@_HgEeAwDvGn@fLvEvBnC_FiAcGkEj@_B`JtC|GlDgCg@wGkEGsBnHzAlIfEHn@qGyH~CjA`JpE^rAiGeCgEcEfBk@fJhD`FvFiKiDqOuBsS_JiuAsCcl@gFap@cGsl@qIog@aMigAqPk|@]yGjCgBvBtFyAdHeEYoBeFz@eFjDxB]tHiD\\q@kFdCeDbDb@dAdHkCjFiD_A{BqOqBaFuHyIaPuJ{CqCmAyE`CuDjCzE{ArG_DuApAeFnA`NeDeAv@yF`E~@p@vIuChEkC{CjA_FrDtBd@tI}C`EkD{BmDiOkJ}q@wHi\\yFkZgDmXKcHpCqDlDbDl@vI}AjIyDvAoA{EnC_DjDfCf@dI{C~EoCgCbFiCCvImDxAgAaFpCsCnCtE_AtHoDIQgGbD}@lBlGiBdGiD{@RoGtDy@~BrF}AhGeDqAHwG~De@hCrHmApHuDIq@iGtC{DtDrCPxIcDrDyC{BRsGzDuA`CrQgDhBuAaFrBeF`ExA~@vIoC|E{CsBRmG|DeA`DtFYfJiD`CuCuCdDkKpDbEHxJiD|DyC_Db@aHnEIxAhTqDbAeB_FxAiGfE]tC`H[bJkD~AkCsEaEwPoMkb@oDkQc^omBmVsyAeA_F}CkAoDjE}ApJHzKbId^xFfa@}BbtAlBxGhE|CdC|GDnIaCzE_Dg@kCkCiBcEuCiByDfAcDjEyAbI`Fj_@iB|UoArIoHb[u\\hpAp@fT_@tJcBlJuChI_Zna@}AzGSfJiB|IcExFwSzMoDbDaElOBlJeA|IkG~QcBfJaHzk@uR|rCaA~H{BvGeBbJwAzYiBnu@_BxGcDx@cB}DwDi_AvAoFdDzBm@bIiDWJcGpDBfAhIqCdFoCkC~@wFxDPzB~Fk@bIyDz@aAsFfCeDhD`CCtIiDzDgEJ}DyAcBsEzBsDfClEoAfHiEp@eCoDxAgEbDhDq@tHgDYd@iFxDdAdAdIqBpGkCeHvDx@l@tI_B~VIlWlBbv@Eta@TrLhDrbBHtgAPjHnBfE|CgBiF{HeCnF]zHZnRxFfnArB`r@v@pJxCbE~CqASgG}DH}B|G^fIfDnAdAmFaCqE{DlA{@lH`CrDvBeDoAiGuDnAShIlCnBrAeFiB{EmDdAaAbIHnUaBtp@mClq@]fm@qDrpB{Ctr@CzJhCdFvCoCkAyFmEz@u@xIfCpEtBaDgBqEaE|BBhIdDtAn@qFcDuBaC`GnArGdDg@I}GkDcBoCfF~@nHtDCZoGiDaBiCxFnAxHfDDJuFyD_AgCjG^tIjB~HhQpg@~EnQnDt@`AwGqCyCuCxEdAhIxDa@ZgHyC{B}BjFzAdHlDaA?_HeDm@kB~FxA~GzD_AGeHaDw@aB|FbBnGlDqAMoHeDw@_BnGlBfGhD}A@gHaD_AyApGvB~FrD}Bg@eHqDOuAfGxAxGrDZbByFiB_FgDxAeBfG{BjPeCrDcEa@yDj@kCtETjIpD~BtAsFyCuFqE^aA|HzCnDpBuFwBsFwDjC`@xHvDl@XkHmDmBoBhGxBlFjCcD{AkFiD`Cl@pHnDBPiHsDqAmBlGxBzEjCcDuAuFyDhBDdInDbAf@qG_D_BgCnGiBfe@u@d]yDjkBiDt`AmFv{A{AjZmG~p@o@lLd@vr@dBfIbDbGzB`Ir@nJ_@nX_DfWuBvIuC|DoDBqBoErA{EbDdCM~HeDz@cAiFdCwBrBtEkA|G_DSM_GxCu@rBrF_@pHyC~B{B{DrA}EbDjAtAzHyCfg@I~HbBdSZvJS|KmBlYiDhZiFzp@gGhf@gJzbAsD`u@cGhmCeDlc@HnJlBnIrDjChBgEmBaEuDlDCvIzCjCfBkEuAeF}DjA{@rIfCrFzCeA]cG_EDuBnH|AdHlDe@@eGsDq@cCdGdAfIrDDT_GsDeAkCrGEhKl@xUtCnj@pDrtAfF|vAnKdwDvFl|AmAtIsDz@{@uFhDeAz@nH{ClE{CkCp@sFnD~@t@bIkCpFmDuANiG`E[pBtGaCvGaE]g@cGbDeCzChD]hIaEjA_BeFlBsE|D`CYrIgElCiCuDlAoFxD|@p@pIcDhEmCaDfA_FpDrBp@jJoJh`@uAtLcNjeBcEdgA{C`d@a@fj@f@~fAMvf@zBhHbE`AhCwEWeHeD}BiDtCe@hIhChG|D]|@mG}ByDiDjCSrIdDrElDkCIsGoDoAiC|F~@tIfEbBdC{Eq@gH{D_BeDxDa@|IdCjHfELbByFoAqGcEm@gDhE}DvPqJtl@sBlIkc@dtA}Yrq@{I`MsSpSoKlO{s@jsAgLxRac@xt@yPfVqRxRyCfHaAjWdDhF~CmB{@}FiEz@o@xIrDxCzBaFgBmFsEbBeA|IlCzGfEc@xAkG}@yGmDkCmE\\mDtDwBhHiLbj@kOpm@_FxVmJf]cNzu@{O`w@me@zsBaPji@mBrIsDlDgCcF|@_IbD}ErPwQdDcFjHgMjZoi@vFyMjK}`@|P{t@tUwiAvDi\\Dg^f@}GbB_FlJ_BvBcDrFyVbNu\\bE{IzCHlAvIyCpGyDDoAwE`C}C`CrFaBjHkDWWyFhDc@`AtHgCfGaEb@uD_B}CuCg@}FjCkC~BhFoAnIeEjC{CyCl@mGlDHxAdHwBlGcDcBp@}FhD~@HdIoDnCqBaE`BsEtCvCy@|HuD?[cGhCkEjRuP~k@if@tZyUxI_JvDX`@lImDtCvBqJrB|GxChDvDg@~DmDvd@el@vOwTtK}RrDbAAnIkE~@{@oFnC}AxBpGaClGwC{BdAuE`DhCc@tIwDR?cGjExAIjJsDzB_AoFxCq@nAlHqCtE{BsDhByDnCfEkAzHsDu@RqFhDh@b@vI}DzC_B{EzF|AkAlI}DCSwGbDk@nBvGkA|H}DGc@yF~Cs@z@dIcD~EgCuCnAgEzCdDHjJsDzCgBkErCmErJlGzDlBfh@hXdg@v]lNfHnjBrbA`iAxq@~a@`Ub\\jOjRpMhMdF|`@tHvLnAb[hAja@lE|SHlJYbb@aFlLl@t\\hFbEnBpVzTd_@lUf`@|OvLxCbRpCfYfJfDfBdAnHsCbGoDmA_AmGrA_E~CxBMdJyDbB_BkE~AiDxCtCSnI{DxAgAaF`CqChJdDzE`@ll@v@p\\u@zDs@f@eFqD]uAbJxC~F`CkDeCyCqC|GrBfIlDsAeA_FwDpDLjKrDzBf@yF{D]eAxIxCzE`CoDwBkEoD|DpAtJzD[@cGoDs@gB~HxC~FtCgCaAwFaEdA{@nJtCvGbDoA{@aGaErAItJvDzCa@iLyChObDlD`E]pc@}LdUmDxi@}InLgCzLg@xRdA|DMpAmEaCcD}DrDeA`Jz@~HjCxDxC]pBqCf@kEcAsFAeFnBwBlDY`EuAzY{NrVgJtd@aUhb@}ZhW{O`SwJhDpBrC~FjDdAnCwBrGkJvIiIb`@qTxKqA`Pu@nKsBbQ}FvPmDvTmJ~CIvG|LlDBpC{BhGkIfXyWhJ{Ev[yMdTmQ|NcJrBoCg@aFyDHmBrIhBhIrDj@pB_DoAkEeE~A_BvI|ApHpCgAm@mF}Dz@cA|IjCxFbDw@NaF_D}AgE~CiBdI`AzIvDtCxD@vZaDrV{@du@e@|q@vB`H{CnDW|D`@zBxFq@nI_DlGqEfDkEIwDsDiEGqBjHpBtGtCwByAyFaElCBjJhD`ATiGyDkAoCxGnAlIrDDHcGiEaAiCdI|AlIrDS?iG}Dy@eClIbBlIzDSHqGsDmBgDlG`@vJrD`CbB}EaCqEcExD@zJrD|BbBwEcCcEeEnDKzJhDbEdDcCm@sFoEl@oAzIjCdFhCaCiAcFcE~@wAhIdCzErBoDgCiDaE`DYzIbDtC~AkE{B}DyDdCq@bJzCxDvBeDyBaEgEfD]hJtCdE~CuBlBkFnDeCfEHdD`EIhIyDvBgBmEtB}CdDdAxAnHkCvGoDsAXyFzCwBh]{FnTiC`k@eL|Eq@brAcP`VyFle@}E`RcDvm@gJdUiFjOsBtg@gL~^{JnKgE|g@gT`J{ArYI~RnAnZnDvXnA|PMlEz@dDzE~@lI{BzG_Dq@`@oFbD|@HjJqDbDoA}DnCwBzBhGgBzHyC_BbAmE~I[bDm@v[_NfRaFrMuEtx@a^dP{EtYkDrOH~LdB`}@~GnMdDlEExAmGMwIoVgjDsHebBgKqxBaG_wAgEgkAoBkf@y@yIc@gI??EI"; - var format = new OpenLayers.Format.EncodedPolyline(); + var format = new OpenLayers.Format.EncodedPolyline({geometryType:"polygon"}); var vector_layer = new OpenLayers.Layer.Vector(); map.addLayer(vector_layer); vector_layer.addFeatures(format.read(encoded)); diff --git a/lib/OpenLayers/Format/EncodedPolyline.js b/lib/OpenLayers/Format/EncodedPolyline.js index 237782b7f7..b09bd2b39e 100644 --- a/lib/OpenLayers/Format/EncodedPolyline.js +++ b/lib/OpenLayers/Format/EncodedPolyline.js @@ -18,6 +18,13 @@ */ OpenLayers.Format.EncodedPolyline = OpenLayers.Class(OpenLayers.Format, { + /** + * APIProperty: geometryType + * {String} Geometry type to output. One of: linestring (default), + * linearring, multipoint or polygon + */ + geometryType: "linestring", + /** * Constructor: OpenLayers.Format.EncodedPolyline * Create a new parser for encoded polylines @@ -44,6 +51,16 @@ OpenLayers.Format.EncodedPolyline = OpenLayers.Class(OpenLayers.Format, { * {} A vector feature with a linestring. */ read: function(encoded) { + var geomType; + if (this.geometryType == "linestring") + geomType = OpenLayers.Geometry.LineString; + else if (this.geometryType == "linearring") + geomType = OpenLayers.Geometry.LinearRing; + else if (this.geometryType == "multipoint") + geomType = OpenLayers.Geometry.MultiPoint; + else if (this.geometryType != "polygon") + return null; + var points = new Array(); var lat = 0; @@ -76,8 +93,15 @@ OpenLayers.Format.EncodedPolyline = OpenLayers.Class(OpenLayers.Format, { points.push(new OpenLayers.Geometry.Point(lon * 1e-5, lat * 1e-5)); } + if (this.geometryType == "polygon") + return new OpenLayers.Feature.Vector( + new OpenLayers.Geometry.Polygon([ + new OpenLayers.Geometry.LinearRing(points) + ]) + ); + return new OpenLayers.Feature.Vector( - new OpenLayers.Geometry.LineString(points) + new geomType(points) ); }, diff --git a/tests/Format/EncodedPolyline.html b/tests/Format/EncodedPolyline.html index 29e0a65709..10f2487347 100644 --- a/tests/Format/EncodedPolyline.html +++ b/tests/Format/EncodedPolyline.html @@ -3,11 +3,27 @@ From 2c5d4c75d43da3c00c112b3ab3a8ec97ba7ff021 Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Thu, 27 Dec 2012 22:10:51 +0100 Subject: [PATCH 4/9] EncodedPolyline: Merged duplicate code in read() method This patch also prepares the code for making it possible to read encoded strings with multi-dimensional points. --- lib/OpenLayers/Format/EncodedPolyline.js | 38 +++++++++--------------- 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/lib/OpenLayers/Format/EncodedPolyline.js b/lib/OpenLayers/Format/EncodedPolyline.js index b09bd2b39e..a71b0a449b 100644 --- a/lib/OpenLayers/Format/EncodedPolyline.js +++ b/lib/OpenLayers/Format/EncodedPolyline.js @@ -62,35 +62,25 @@ OpenLayers.Format.EncodedPolyline = OpenLayers.Class(OpenLayers.Format, { return null; var points = new Array(); - - var lat = 0; - var lon = 0; + var point = new Array(0, 0); for (var i = 0; i < encoded.length;) { - var b; - var result = 0; - var shift = 0; + for (var dim = 0; dim < 2; ++dim) { + var result = 0; + var shift = 0; - do { - b = encoded.charCodeAt(i++) - 63; - result |= (b & 0x1f) << shift; - shift += 5; - } while (b >= 0x20); + var b; + do { + b = encoded.charCodeAt(i++) - 63; + result |= (b & 0x1f) << shift; + shift += 5; + } while (b >= 0x20); - lat += ((result & 1) ? ~(result >> 1) : (result >> 1)); + point[dim] += ((result & 1) ? ~(result >> 1) : (result >> 1)); + } - result = 0; - shift = 0; - - do { - b = encoded.charCodeAt(i++) - 63; - result |= (b & 0x1f) << shift; - shift += 5; - } while (b >= 0x20); - - lon += ((result & 1) ? ~(result >> 1) : (result >> 1)); - - points.push(new OpenLayers.Geometry.Point(lon * 1e-5, lat * 1e-5)); + points.push(new OpenLayers.Geometry.Point(point[1] * 1e-5, + point[0] * 1e-5)); } if (this.geometryType == "polygon") From c118d9884da0f52279adcddf347378615865d822 Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Thu, 27 Dec 2012 23:07:31 +0100 Subject: [PATCH 5/9] EncodedPolyline: Extracted universal decode(encoded, dims) method --- lib/OpenLayers/Format/EncodedPolyline.js | 57 ++++++++++++++++++------ tests/Format/EncodedPolyline.html | 30 +++++++++++-- 2 files changed, 70 insertions(+), 17 deletions(-) diff --git a/lib/OpenLayers/Format/EncodedPolyline.js b/lib/OpenLayers/Format/EncodedPolyline.js index a71b0a449b..5c7b68c221 100644 --- a/lib/OpenLayers/Format/EncodedPolyline.js +++ b/lib/OpenLayers/Format/EncodedPolyline.js @@ -61,11 +61,50 @@ OpenLayers.Format.EncodedPolyline = OpenLayers.Class(OpenLayers.Format, { else if (this.geometryType != "polygon") return null; + var points = this.decode(encoded, 2); + var pointGeometries = new Array(); + for (i in points) { + var point = points[i]; + pointGeometries.push( + new OpenLayers.Geometry.Point(point[1] * 1e-5, point[0] * 1e-5) + ); + } + + if (this.geometryType == "polygon") + return new OpenLayers.Feature.Vector( + new OpenLayers.Geometry.Polygon([ + new OpenLayers.Geometry.LinearRing(pointGeometries) + ]) + ); + + return new OpenLayers.Feature.Vector( + new geomType(pointGeometries) + ); + }, + + /** + * Method: decode + * Deserialize an encoded string and return an array of n-dimensional + * points. + * + * Parameters: + * encoded - {String} An encoded string + * dims - {int} The dimension of the points that are returned + * + * Returns: + * {Array(Array(int))} An array containing n-dimensional arrays of + * coordinates. + */ + decode: function(encoded, dims) { var points = new Array(); - var point = new Array(0, 0); + var point = new Array(dims); + + // Reset the point array + for (var i = 0; i < point.length; ++i) + point[i] = 0; for (var i = 0; i < encoded.length;) { - for (var dim = 0; dim < 2; ++dim) { + for (var dim = 0; dim < dims; ++dim) { var result = 0; var shift = 0; @@ -79,20 +118,10 @@ OpenLayers.Format.EncodedPolyline = OpenLayers.Class(OpenLayers.Format, { point[dim] += ((result & 1) ? ~(result >> 1) : (result >> 1)); } - points.push(new OpenLayers.Geometry.Point(point[1] * 1e-5, - point[0] * 1e-5)); + points.push(point.slice(0)); } - if (this.geometryType == "polygon") - return new OpenLayers.Feature.Vector( - new OpenLayers.Geometry.Polygon([ - new OpenLayers.Geometry.LinearRing(points) - ]) - ); - - return new OpenLayers.Feature.Vector( - new geomType(points) - ); + return points; }, CLASS_NAME: "OpenLayers.Format.EncodedPolyline" diff --git a/tests/Format/EncodedPolyline.html b/tests/Format/EncodedPolyline.html index 10f2487347..9ad7dbd726 100644 --- a/tests/Format/EncodedPolyline.html +++ b/tests/Format/EncodedPolyline.html @@ -3,10 +3,19 @@ From 8651e05e75468db6f36a3810da23ef2ef18951e1 Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Thu, 27 Dec 2012 23:19:44 +0100 Subject: [PATCH 6/9] EncodedPolyline: Allow setting geometryType to "point --- lib/OpenLayers/Format/EncodedPolyline.js | 10 ++++++++-- tests/Format/EncodedPolyline.html | 6 +++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/lib/OpenLayers/Format/EncodedPolyline.js b/lib/OpenLayers/Format/EncodedPolyline.js index 5c7b68c221..289c2aa8ef 100644 --- a/lib/OpenLayers/Format/EncodedPolyline.js +++ b/lib/OpenLayers/Format/EncodedPolyline.js @@ -21,7 +21,8 @@ OpenLayers.Format.EncodedPolyline = OpenLayers.Class(OpenLayers.Format, { /** * APIProperty: geometryType * {String} Geometry type to output. One of: linestring (default), - * linearring, multipoint or polygon + * linearring, point, multipoint or polygon. If the geometryType is + * point, only the first point of the string is returned. */ geometryType: "linestring", @@ -58,7 +59,7 @@ OpenLayers.Format.EncodedPolyline = OpenLayers.Class(OpenLayers.Format, { geomType = OpenLayers.Geometry.LinearRing; else if (this.geometryType == "multipoint") geomType = OpenLayers.Geometry.MultiPoint; - else if (this.geometryType != "polygon") + else if (this.geometryType != "point" && this.geometryType != "polygon") return null; var points = this.decode(encoded, 2); @@ -70,6 +71,11 @@ OpenLayers.Format.EncodedPolyline = OpenLayers.Class(OpenLayers.Format, { ); } + if (this.geometryType == "point") + return new OpenLayers.Feature.Vector( + pointGeometries[0] + ); + if (this.geometryType == "polygon") return new OpenLayers.Feature.Vector( new OpenLayers.Geometry.Polygon([ diff --git a/tests/Format/EncodedPolyline.html b/tests/Format/EncodedPolyline.html index 9ad7dbd726..b1692ba848 100644 --- a/tests/Format/EncodedPolyline.html +++ b/tests/Format/EncodedPolyline.html @@ -51,7 +51,7 @@ } function test_Format_EncodedPolyline_read(t) { - t.plan(4); + t.plan(5); var format = new OpenLayers.Format.EncodedPolyline(); @@ -71,6 +71,10 @@ format.geometryType = "polygon"; t.ok(polygon.geometry.equals(format.read(encoded).geometry), "format correctly reads encoded polygon"); + + format.geometryType = "point"; + t.ok(points[0].equals(format.read(encoded).geometry), + "format correctly reads encoded point"); } function test_Format_EncodedPolyline_decode(t) { From 510d42b12ffd567791fa7d66c6e62ebf250fd151 Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Fri, 28 Dec 2012 01:31:24 +0100 Subject: [PATCH 7/9] EncodedPolyline: Added encode() method The write() method will follow in the next commit. --- lib/OpenLayers/Format/EncodedPolyline.js | 75 ++++++++++++++++++++++++ tests/Format/EncodedPolyline.html | 8 +++ 2 files changed, 83 insertions(+) diff --git a/lib/OpenLayers/Format/EncodedPolyline.js b/lib/OpenLayers/Format/EncodedPolyline.js index 289c2aa8ef..c901d7c796 100644 --- a/lib/OpenLayers/Format/EncodedPolyline.js +++ b/lib/OpenLayers/Format/EncodedPolyline.js @@ -130,5 +130,80 @@ OpenLayers.Format.EncodedPolyline = OpenLayers.Class(OpenLayers.Format, { return points; }, + /** + * Method: encode + * Serialize an array of n-dimensional points and return an encoded string + * + * Parameters: + * points - {Array(Array(int))} An array containing n-dimensional + * arrays of coordinates + * dims - {int} The dimension of the points that should be read + * + * Returns: + * {String} An encoded string + */ + encode: function (points, dims) { + var encoded_points = ""; + + var lastPoint = new Array(dims); + for (var i = 0; i < lastPoint.length; ++i) + lastPoint[i] = 0; + + for (var i = 0; i < points.length; i++) { + var point = points[i]; + + for (var dim = 0; dim < lastPoint.length; ++dim) { + var delta = point[dim] - lastPoint[dim]; + encoded_points += this.encodeSignedNumber(delta); + } + + lastPoint = point; + } + return encoded_points; + }, + + /** + * Method: encodeSignedNumber + * Encode one single signed integer and return an encoded string + * + * Parameters: + * num - {int} A signed integer that should be encoded + * + * Returns: + * {String} An encoded string + */ + encodeSignedNumber: function (num) { + var sgn_num = num << 1; + if (num < 0) + sgn_num = ~(sgn_num); + + return this.encodeNumber(sgn_num); + }, + + /** + * Method: encodeNumber + * Encode one single unsigned integer and return an encoded string + * + * encodeSignedNumber should be used instead of using this method directly! + * + * Parameters: + * num - {int} An unsigned integer that should be encoded + * + * Returns: + * {String} An encoded string + */ + encodeNumber: function (num) { + var encodeString = ""; + var value; + while (num >= 0x20) { + value = (0x20 | (num & 0x1f)) + 63; + encodeString += (String.fromCharCode(value)); + num >>= 5; + } + value = num + 63; + encodeString += (String.fromCharCode(value)); + return encodeString; + }, + CLASS_NAME: "OpenLayers.Format.EncodedPolyline" }); diff --git a/tests/Format/EncodedPolyline.html b/tests/Format/EncodedPolyline.html index b1692ba848..785b56df41 100644 --- a/tests/Format/EncodedPolyline.html +++ b/tests/Format/EncodedPolyline.html @@ -91,6 +91,14 @@ } } + function test_Format_EncodedPolyline_encode(t) { + t.plan(1); + + var format = new OpenLayers.Format.EncodedPolyline(); + + t.eq(format.encode(basePoints, 2), encoded); + } + From 06409da72e1c453a100d05ce188e44f3547ae820 Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Fri, 28 Dec 2012 19:14:30 +0100 Subject: [PATCH 8/9] EncodedPolyline: Added APIMethod keywords to documentation --- lib/OpenLayers/Format/EncodedPolyline.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/OpenLayers/Format/EncodedPolyline.js b/lib/OpenLayers/Format/EncodedPolyline.js index c901d7c796..53050f294e 100644 --- a/lib/OpenLayers/Format/EncodedPolyline.js +++ b/lib/OpenLayers/Format/EncodedPolyline.js @@ -42,7 +42,7 @@ OpenLayers.Format.EncodedPolyline = OpenLayers.Class(OpenLayers.Format, { }, /** - * Method: read + * APIMethod: read * Deserialize an encoded polyline string and return a vector feature. * * Parameters: @@ -89,7 +89,7 @@ OpenLayers.Format.EncodedPolyline = OpenLayers.Class(OpenLayers.Format, { }, /** - * Method: decode + * APIMethod: decode * Deserialize an encoded string and return an array of n-dimensional * points. * @@ -131,7 +131,7 @@ OpenLayers.Format.EncodedPolyline = OpenLayers.Class(OpenLayers.Format, { }, /** - * Method: encode + * APIMethod: encode * Serialize an array of n-dimensional points and return an encoded string * * Parameters: From 06bd07ff8de423b1d6f33ca67038ce3b4fc61b3a Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Fri, 28 Dec 2012 20:24:57 +0100 Subject: [PATCH 9/9] EncodedPolyline: Added write() method --- lib/OpenLayers/Format/EncodedPolyline.js | 45 ++++++++++++++++++++++++ tests/Format/EncodedPolyline.html | 27 ++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/lib/OpenLayers/Format/EncodedPolyline.js b/lib/OpenLayers/Format/EncodedPolyline.js index 53050f294e..1255eb1c91 100644 --- a/lib/OpenLayers/Format/EncodedPolyline.js +++ b/lib/OpenLayers/Format/EncodedPolyline.js @@ -130,6 +130,51 @@ OpenLayers.Format.EncodedPolyline = OpenLayers.Class(OpenLayers.Format, { return points; }, + /** + * APIMethod: write + * Serialize a feature or array of features into a WKT string. + * + * Parameters: + * features - {|Array} A feature or array of + * features + * + * Returns: + * {String} The WKT string representation of the input geometries + */ + write: function(features) { + var feature; + if (features.constructor == Array) + feature = features[0]; + else + feature = features; + + var geometry = feature.geometry; + var type = geometry.CLASS_NAME.split('.')[2].toLowerCase(); + + var pointGeometries; + if (type == "point") + pointGeometries = new Array(geometry); + else if (type == "linestring" || + type == "linearring" || + type == "multipoint") + pointGeometries = geometry.components; + else if (type == "polygon") + pointGeometries = geometry.components[0].components; + else + return null; + + var points = new Array(); + for (var i in pointGeometries) { + var pointGeometry = pointGeometries[i]; + var point = [Math.round(pointGeometry.y * 1e5), + Math.round(pointGeometry.x * 1e5)]; + points.push(point); + } + + var result = this.encode(points, 2); + return result; + }, + /** * APIMethod: encode * Serialize an array of n-dimensional points and return an encoded string diff --git a/tests/Format/EncodedPolyline.html b/tests/Format/EncodedPolyline.html index 785b56df41..1a93a41afa 100644 --- a/tests/Format/EncodedPolyline.html +++ b/tests/Format/EncodedPolyline.html @@ -18,6 +18,8 @@ basePoints[2][0] * 1e-5) ]; + var singlePoint = new OpenLayers.Feature.Vector(points[0]); + var linestring = new OpenLayers.Feature.Vector( new OpenLayers.Geometry.LineString(points) ); @@ -91,6 +93,31 @@ } } + function test_Format_EncodedPolyline_write(t) { + t.plan(5); + + var format = new OpenLayers.Format.EncodedPolyline(); + + t.eq(format.write(linestring), encoded, + "format correctly writes encoded polyline"); + + t.eq(format.write(multipoint), encoded, + "format correctly writes encoded multipoint"); + + // Different output than encoded, + // because polygon closing point is included + t.eq(format.write(linearring), + "_p~iF~ps|U_ulLnnqC_mqNvxq`@~b_\\ghde@", + "format correctly writes encoded linearring"); + + t.eq(format.write(polygon), + "_p~iF~ps|U_ulLnnqC_mqNvxq`@~b_\\ghde@", + "format correctly writes encoded polygon"); + + t.eq(format.write(singlePoint), "_p~iF~ps|U", + "format correctly writes encoded point"); + } + function test_Format_EncodedPolyline_encode(t) { t.plan(1);