Skip to content

Commit

Permalink
Merge pull request #9 from raphaelmor/optimisation
Browse files Browse the repository at this point in the history
Optimisation :  fixes #8
  • Loading branch information
raphaelmor committed Jan 17, 2015
2 parents 92bfa52 + c5ba73a commit a6a3e33
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 31 deletions.
27 changes: 27 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Xcode
#
.DS_Store
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate

# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
#
# Pods/
2 changes: 2 additions & 0 deletions Polyline.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_OBJC_BRIDGING_HEADER = "";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
Expand All @@ -349,6 +350,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_OBJC_BRIDGING_HEADER = "";
};
name = Release;
};
Expand Down
85 changes: 54 additions & 31 deletions Polyline/Polyline.swift
Original file line number Diff line number Diff line change
Expand Up @@ -149,43 +149,66 @@ public struct Polyline {

private func decodePolyline(encodedPolyline: String) -> Result<Array<CLLocationCoordinate2D>> {

var remainingPolyline = encodedPolyline.unicodeScalars
var decodedCoordinates = [CLLocationCoordinate2D]()
let data = encodedPolyline.dataUsingEncoding(NSUTF8StringEncoding)!

let byteArray = unsafeBitCast(data.bytes, UnsafePointer<Int8>.self)
let length = Int(data.length)
var position = Int(0)

var decodedCoordinates = [CLLocationCoordinate2D]()

var lat = 0.0
var lon = 0.0

while position < length {

let resultingLat = decodeSingleCoordinate(byteArray, length: length, position: &position)
if resultingLat.failed { return .Failure }
lat += resultingLat.value!

let resultingLon = decodeSingleCoordinate(byteArray, length: length, position: &position)
if resultingLat.failed { return .Failure }
lon += resultingLon.value!

decodedCoordinates.append(CLLocationCoordinate2D(latitude: lat, longitude: lon))
}

return .Success(decodedCoordinates)
}

private func decodeSingleCoordinate(byteArray: UnsafePointer<Int8>, length: Int, inout position: Int ) -> Result<Double> {

var lat = 0.0
var lon = 0.0
if position >= length {
return Result.Failure
}

while countElements(remainingPolyline) > 0 {
let latResult = extractNextChunk(&remainingPolyline)
if latResult.failed {
return .Failure
}
lat += decodeSingleCoordinate(latResult.value!)

let lonResult = extractNextChunk(&remainingPolyline)
if lonResult.failed {
return .Failure
}
lon += decodeSingleCoordinate(lonResult.value!)

decodedCoordinates.append(CLLocationCoordinate2D(latitude: lat, longitude: lon))
}
let bitMask = Int8(0x1F)

return .Success(decodedCoordinates)
}

private func decodeSingleCoordinate(value: String) -> Double {
let scalarArray = [] + value.unicodeScalars
var coordinate : Int32 = 0

var thirtyTwoBitNumber = agregateScalarArray(scalarArray)
// check if number is negative
if (thirtyTwoBitNumber & 0x1) == 0x1 {
thirtyTwoBitNumber = ~(thirtyTwoBitNumber >> 1)
} else {
thirtyTwoBitNumber = thirtyTwoBitNumber >> 1
var currentChar : Int8
var componentCounter : Int32 = 0
var component: Int32 = 0

do {
currentChar = byteArray[position] - 63
component = Int32(currentChar & bitMask)
coordinate |= (component << (5*componentCounter))
position++
componentCounter++
} while ((currentChar & 0x20) == 0x20) && (position < length) && (componentCounter < 6)

if (componentCounter == 6) && ((currentChar & 0x20) == 0x20) {
return Result.Failure
}

return Double(thirtyTwoBitNumber)/1e5
if (coordinate & 0x01) == 0x01 {
coordinate = ~(coordinate >> 1)
} else {
coordinate = coordinate >> 1
}

return Result.Success(Double(coordinate) / 100000.0)
}

// MARK:- Encoding levels
Expand Down
7 changes: 7 additions & 0 deletions PolylineTests/PolylineTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,13 @@ class PolylineTests:XCTestCase {
let sut = Polyline(coordinates: sourceCoordinates)
XCTAssertEqual(sut.encodedPolyline, "_@~@")
}

// Github Issue 8
func testPerformances() {
self.measureBlock {
let sut = Polyline(encodedPolyline:"wamrIo{gnAnG_CVIm@{NEsDFgAHu@^{C`@sC@_As@eWEoBIw@?QDYd@oB@Uv@eDHOViAPwB@_ACUGQIcDYiIsA{a@EcB?iBD]JyBV}C@GJKDOCUMOO@MLy@@}ATI@McEQsLCcC?}@De@BQNe@gDcEgBsCSa@Yy@QiAS{D?gAJ_APmAt@wD`@eDDq@?aCk@uTcBif@KiBSkBa@wBUu@u@yB}CmHo@oAw@kA_@g@y@s@w@i@eJiF}BcB_BwAoCsDaB_DwLsWaBaDyB}Dm@qA_AcDEOIq@Sy@AuBBu@LgAR}@|@kCt@}Ab@s@^g@hAoAb@]jBkAdHqDt@[~@QxABNEHEdA}@TYbAyATQXKdC[n@Sr@c@r@}@|BwE~@eBjAyAvAaAlCaBlCoAjC_A|Cu@lLeBnDcAxBy@xDmBlEkCvDcCrFaEHGxAg@nAYf@Cz@@hCd@zAHj@MTIf@c@T]Zo@b@iBFo@DgA?k@CgAEa@Y_BoBeHo@sC{@iFg@qBk@aDqBeJaBcG}E_P{AsFq@kCk@eCwAmIm@yEk@cFg@eHU{FAiBMaIIiHImDSwF_@gGc@wFq@_G]aCc@yCcAsFiAeFCQ}FgUcEaRmBsJ_C}M_BaK{A{KsC_V_Gil@WqDy@kJk@eHyAeSu@mL]{Ha@kNI_GEkKFcV?mHKeHK}Cg@eKa@cFWmCm@}Ea@uCcCqMm@mCmAoEq@wBuA{DuAmD_BiDeDkG]u@{AwC{BaFiA_Dy@gCiA_Em@cCeAyEo@oDs@yEq@wFm@iHIyA]qIQiJIiBAkBDg@Ru@DOJSFc@Bc@AUIg@M[]aDIsAWyUs@cx@MqJ[wL_@gLg@uLo@oLiAkRo@_Iy@kH_@uCy@}Ey@mDaBcGkDsIgBkDgAaBiDiEkBqB}AkAmCaBaImDkAs@{BeBaBkBmBqCaCoEy@sBw@}Bq@aCoA{EeA_Fg@qCsAaJ_@sC]}CUqC_@qFIuAUkGQeIG}QCsRFuD?_CDgIAoJMyMUaLq@mO[wF}@uMe@oFc@kDu@wF{@{E_BwH[wAmDkL{HaToC}HwA{DiAkD_AuDyA_Ig@}Dg@wCyCiTi@cDy@qGcAeGkHyi@oAcJwBoPwAyJs@yFy@kFoFy_@wBeNkA}HcEuZeBqKOyAs@kEk@qEq@qE[cBWkBoAmHsBeOCQCuD\\{Bd@_Cz@aAbDuC~HuH|BsCjBqCdAgBrAgC~AwDjA{ClA}DrAmFf@_Cz@yE^aCh@_EVaCl@eHPcCp@qNbAuPf@_HtA}Nr@gG|@}GfAmHbB_JrAqG~AoItFkX`@_Cd@uDb@iEb@mFTiEXmJDyDAkDGeD]sIe@oG_A_Ko@gGaA{HwAyJi@eDqAoHiCiMmByH_EmOoCkIaGyR]_A}AcF_AiD}@_DwAiHc@oCa@kDa@gGQaEEwJFoD^}Ib@gF^kCZeCT}@x@oE\\yAtCaOb@iCv@qGV{CXwEJwE\\gh@RaMZsIv@iMX}CXyBnAeIj@qCx@cDrCkJrIeWdAmDp@mC`AsE\\gC~AeJTqBJq@VeDd@yH`@qMZaNx@c\\DaCDiAjAmc@f@iOjDwy@RqC|AcR|@}HtAiK~@oGn@oD|Hoa@vAwJ\\oCl@sGb@cF`@kHF_C`@iKJiH?gJIiDCoBo@yRsBga@[cREsFBeU`@sOTwGFeC~@cWf@wK~@_WbAu[vEmuAfAoXHiLHmTKe]GiCYoHY_Ew@aH}CmSwBkQgBcPw@uKScFCwCHeHZcIx@iOf@cMF}Bn@s^v@k\\n@i[j@aRNwGf@aPNsHb@kP|@yWp@wPLiFLqCbBej@?m@f@sQnAi_@b@mNlAg[VqE\\yELaCLuAdAmKXqB`@{D~BcTn@aGDm@NiATqC@i@F_BCeBOqDK}@e@yCAUDYBQFKn@Er@Bt@Jb@ApBS`CHfFIpEo@lFgB`FwC|@u@vCoCxA}AdEsG`CgFr@kBnAcE`BcHd@uCb@{Dj@kHNsCrAq`@T}ZFSFkAR_BBQDIrBwB|Ca@fGKhADbLfBlD`AhCz@pExBtBpAxCtBt@b@dBr@|@TjBTnBCbAK^IxCeAp@]xC}Bv@u@rCuDxSo\\jBsCfnAgnB|TiZjD}Df@a@bD{BpDsBfIyCvh@yXzB}@pAYnEi@tGArD}@nOsFxJuFjLeIvF}C`GkEtBmA|AUn@AdQP~Fo@zBNtO~B`CV`@@b@I~@o@d@i@|@gB`IeT|C{Ib@aB^iB~DmS`AsD~@eCb@_AXe@lBmCjd@m`@rJcIxKgKbEcDzQmS|CyCfDiCbDmBjBy@tEaBfIqAnQmBbA[|AY|EgBdF_CxH_GtAmAbDsDd@o@|e@mt@vCaEhHqIbL{KvF}DrNmJl@El@c@v@g@\\s@~@o@tG_E\\AbEiCZe@dB}@hGsA^EdCBfC[zNy@`Di@fAM`@Mz@_@~UcIdHcB~CWdACx]nAnFl@pBh@fEvBjRfKrP~IvGlCfB\\rF^n@@~AKpC]fYeH`@EfECrDZ`Ej@xFp@rBFtBErAKnCe@~Ae@lBu@~HcEjF{BpJkDzJaDpCmAtDiC|BqBhEaFbCeCXChBuApBcAb@EJ@RBPEFQh@a@pBq@R@RJL@H?Jd@Xf@TFNATONSDKz@o@XMp@OTMpBUfAQjDoA|BwAv@o@j@]~A_BtIyJtEcGpC_EHKLNNEDKBOC[tDqFtAaBt@u@jAeAfBuALKfA_BjDoEfDiC~@a@BCYyDYsBCQz@aAHIP~@")
}
}

// MARK:- README code samples

Expand Down

0 comments on commit a6a3e33

Please sign in to comment.