🥷 High-performance polyline simplification library - port of simplify.js

Overview

SwiftSimplify

High-performance polyline simplification library

SwiftSimplify is a tiny high-performance Swift polyline simplification library ported from Javascript's Simplify.js. Original work come from Leaflet, a JS interactive maps library by Vladimir Agafonkin.

It uses a combination of Douglas-Peucker and Radial Distance algorithms. Works both on browser and server platforms.

Polyline simplification dramatically reduces the number of points in a polyline while retaining its shape, giving a huge performance boost when processing it and also reducing visual noise. For example, it's essential when rendering a 70k-points line chart or a map route in the browser using MapKit.

SwiftSimplify

Requirements

  • iOS 8.0, watchOS 2.0, tvOS 9.0
  • Swift 5.x+

Communication

  • If you found a bug, open an issue.
  • If you have a feature request, open an issue.
  • If you want to contribute, submit a pull request.

Installation

SwiftSimplify is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod "SwiftSimplify"

Usage

Usage is pretty straightforward: in fact you need just call the SwiftSimplify's class method simplify by passing your configuration:

let allPoints: [Point2DRepresentable] = ...
let simplifiedPoints = SwiftSimplify.simplify(allPoints, tolerance: tolerance)

Allowed parameters are:

  • points: An array of points. SwiftSimplify supports Swift's generic so you can pass an array of objects which are conforms to Point2DRepresentable protocol (both CGPoint and CLLocationCoordinate2D objects supports it).
  • tolerance: (1 by default) Affects the amount of simplification (in the same metric as the point coordinates)
  • highQuality: (false by default) Excludes distance-based preprocessing step which leads to highest quality simplification but runs ~10-20 times slower.

❤️ Your Support

Hi fellow developer!
You know, maintaing and developing tools consumes resources and time. While I enjoy making them your support is foundamental to allow me continue its development.

If you are using SwiftSimplify or any other of my creations please consider the following options:

Installation

SwiftSimplify is compatible with Swift 5.x+ under iOS (11+) and macOS platforms.

You can install it via CocoaPods:

use_frameworks!
pod 'SwiftSimplify'

or SPM in your Package.swift:

import PackageDescription

  let package = Package(name: "YourPackage",
    dependencies: [
      .Package(url: "https://github.com/malcommac/SwiftSimplify.git", majorVersion: 0),
    ]
  )

Consider ❤️ support the development of this library!

Contributing

  • If you need help or you'd like to ask a general question, open an issue.
  • If you found a bug, open an issue.
  • If you have a feature request, open an issue.
  • If you want to contribute, submit a pull request.

Copyright & Acknowledgements

SwiftSimplify is currently owned and maintained by Daniele Margutti.
You can follow me on Twitter @danielemargutti.
My web site is https://www.danielemargutti.com

This software is licensed under MIT License.

Follow me on:

Comments
  • Tolerance not working as intended?

    Tolerance not working as intended?

    Hi all I'm currently using SwiftSimplify to reduce the number of coordinates while running, I'm testing runs that go on for about 1 KM but after using Simplify and giving it about 20 points, all it does is return start and end coordinates.

    Simplify is currently like this. SwiftSimplify.simplify(self.activityPolyline!, tolerance: 10, highQuality: false)

    Giving it an array of coordinates like this: [(37.330075379999997, -122.02126848), (37.330058049999998, -122.02100589), (37.33000706, -122.02074717000001), (37.329941720000001, -122.02053031), (37.329871330000003, -122.0202987), (37.329823259999998, -122.02006170999999), (37.329705570000002, -122.01986866), (37.329525689999997, -122.01982409), (37.329339840000003, -122.01980544), (37.329133579999997, -122.0197871), (37.328938319999999, -122.01979684), (37.328738469999998, -122.01980584), (37.328532039999999, -122.0198032), (37.32833935, -122.01980995), (37.32814552, -122.01983108), (37.327952580000002, -122.01982651), (37.327758189999997, -122.01980315), (37.327560220000002, -122.01974095), (37.327370989999999, -122.01972170000001), (37.327185819999997, -122.01971872), (37.326979710000003, -122.01972916)]

    After simplify I get this: [(37.330075379999997, -122.02126848), (37.326979710000003, -122.01972916)]

    What am I doing wrong? The location manager is currently configured as follows: locationManager.activityType = .fitness locationManager.desiredAccuracy = kCLLocationAccuracyKilometer locationManager.distanceFilter = 20

    Appreciate the help.

    opened by sungkim23 4
  • Use generic type conforming Point2DRepresentable for all public interfaces

    Use generic type conforming Point2DRepresentable for all public interfaces

    This PR changes all public interfaces for library to accept parameters with generic types conforming Point2DRepresentable protocol, which makes return type of the function SwiftSimplify.simplify(_:tolerance:highestQuality:) equals the type of the first parameter points.

    enhancement 
    opened by tackgyu 2
  • Support for Swift 5.3

    Support for Swift 5.3

    • Use implicit returns
    • Remove unnecessary explicit references to self
    • Use enum instead of struct for namespacing to restrict initialization
    • Update .gitignore file
    • Add resources to test target in Package.swift
    • fileprivate -> private
    enhancement 
    opened by Coledunsby 1
  • Extensions not public

    Extensions not public

    Referencing instance method 'simplify(tolerance:highestQuality:)' on 'Array' requires the types 'CLLocationCoordinate2D' and 'Point2DRepresentable' be equivalent

    When the lib is added to a project via CocoaPods, the extensions on CLLocationCoordinate2D etc are not visible.

    opened by sobri909 1
  • Pod doesn't work

    Pod doesn't work

    After installing the pod I tried calling it like I would another pod (say like Alamofire) and the methods were not accessible. It did work, however, if I simply added it to my project.

    opened by jasonwiener 1
  • [Enhancement]check count before func simplify

    [Enhancement]check count before func simplify

    In func simplifyRadialDistance, it use force unwrap var prevPoint: T = points.first! and var point: T = points[1]. This would cause crash when input parameter points is just 0 or 1 count. Although I add something like guard line.count > 1 before use SwiftSimplify.simplify to avoid crash, hope this check could add, thank you very much.

    opened by Faydee1220 0
  • Generics support improvement

    Generics support improvement

    Add simple SimplifyValue protocol to add support to simplify any type which supports this protocol. CGPoint and CLLocationCoordinate2D support this protocol already

    opened by OverSwift 0
  • Use projected coordinates when simplifying CLLocationCoordinate2D data

    Use projected coordinates when simplifying CLLocationCoordinate2D data

    If you do calculations based on latitude/longitude, then:

    1. You get different scales on the x/y-axis which leads to weird simplification logic
    2. You can't relate to the tolerance value

    The solution would be to e.g. convert it to MKMapPoints before simplification and if the data points are MKMapPoints you could interpret the tolerance value as meters and it would be both correct (1 above) and use a tolerance that you can relate to (2 above).

    opened by gunnarblom 0
  • Elapsed time calculated in Seconds, but shown as Milliseconds

    Elapsed time calculated in Seconds, but shown as Milliseconds

    You show time in milliseconds /* Returns the current CoreAnimation absolute time. This is the result of

    • calling mach_absolute_time () and converting the units to seconds. */

    @available(iOS 2.0, *) public func CACurrentMediaTime() -> CFTimeInterval

    opened by ansinyutin 0
  • Supports mandatory points to be

    Supports mandatory points to be

    I added the property isMandatory to Point2DRepresentable. This allows to mark certain points as mandatory - so that regardless of the simplification process, they're always included in the result.

    I'm not sure it's the most efficient way of doing this - for our use case it works very well: We're optimisation a large collection of coordinates (x: latitude, y: longitude) and some coordinates must be included in the optimised collection (i.e. isMandatory = true).

    opened by ChristianSteffens 1
  • SPM Target Integrity Warning: range of supported deployment target versions is 9.0 to 14.5.99

    SPM Target Integrity Warning: range of supported deployment target versions is 9.0 to 14.5.99

    SwiftSimplify/Package.swift The iOS Simulator deployment target 'IPHONEOS_DEPLOYMENT_TARGET' is set to 8.0, but the range of supported deployment target versions is 9.0 to 14.5.99.

    Should we an easy fix.

    opened by andreyz 0
  • Returned array with only two values

    Returned array with only two values

    Hi, I'm using the pods and when I try to simplify my [CCLocation2D] consisting in 2125 points the function return my an array with only 2 values.

    I'm doing this:

    let simplifiedCoordinates = SwiftSimplify.simplify(coordinates!, tolerance: 1.75) (I've tried also with 1 tolerance, but nothing change)

    question 
    opened by nicosmazz 3
  • Error or less-than-ideal-naming on distance functions

    Error or less-than-ideal-naming on distance functions

    https://github.com/malcommac/SwiftSimplify/blob/95856a3fce40e4a77f51050d5b6c1f59da072355/Sources/SwiftSimplify/Point2DRepresentable.swift#L54

    These appear to be returning a standard Pythagoras result, but the result is not square rooted. AFAIK this is not meant to be the case but I haven't had time to dig (I only know the DP algorithm at a distance).

    If this is meant to be a linear distance, it looks like it needs to be square rooted. Else it might help to modify the function names to indicate that this is a squared result - otherwise it looks like a straightforward distance calculation function.

    opened by ALTinners 0
  • API for using ArraySlice

    API for using ArraySlice

    For my work I needed to keep array copies at a minimum (dealing with arrays with 100s of 1000s of points) and modified the code here to include an ArraySlice API for dealing with large subsets of the big arrays

    Any interest in a pull request for that API? I wasn't sure how to handle the highestQuality parameter - in my use case I took it out to prevent an array copy but I think the simplifyRadialDistance method could be overloaded to slice the input array even thinner.

    enhancement 
    opened by ALTinners 1
Releases(1.1.1)
Owner
Daniele Margutti
Senior Mobile Engineer/Tech Lead - "Continuous improvement is better than delayed perfection"
Daniele Margutti
LibAuthentication will simplify your code when if you want to use FaceID/TouchID in your tweaks.

LibAuthentication will simplify your code when if you want to use FaceID/TouchID in your tweaks.

Maximehip 6 Oct 3, 2022
A Swift port of some of the original PersistentJXA projects by D00MFist

Persistent-Swift This repo is a Swift port of some of the original PersistentJXA projects by D00MFist (https://github.com/D00MFist/PersistentJXA). I p

Cedric Owens 25 Sep 27, 2022
__.swift is a port of Underscore.js to Swift.

__.swift Now, __.swift is version 0.2.0! With the chain of methods, __.swift became more flexible and extensible. Documentation: http://lotz84.github.

Tatsuya Hirose 86 Jun 29, 2022
Lock a terminal command to the efficiency or performance cores on a big.LITTLE ARM processor

CPU-Lock Lock a terminal command to the efficiency or performance cores on a big.LITTLE ARM processor (Designed for Apple Silicon). Usage Download the

BitesPotatoBacks 0 Aug 11, 2022
Cross-Platform, Protocol-Oriented Programming base library to complement the Swift Standard Library. (Pure Swift, Supports Linux)

SwiftFoundation Cross-Platform, Protocol-Oriented Programming base library to complement the Swift Standard Library. Goals Provide a cross-platform in

null 620 Oct 11, 2022
ZIP Foundation is a library to create, read and modify ZIP archive files.

ZIP Foundation is a library to create, read and modify ZIP archive files. It is written in Swift and based on Apple's libcompression for high performa

Thomas Zoechling 1.9k Dec 27, 2022
macOS system library in Swift

SystemKit A macOS system library in Swift based off of libtop, from Apple's top implementation. For an example usage of this library, see dshb, a macO

null 323 Jan 5, 2023
Swift library to develop custom Alexa Skills

AlexaSkillsKit AlexaSkillsKit is a Swift library that allows you to develop custom skills for Amazon Alexa, the voice service that powers Echo. It tak

Claus Höfele 170 Dec 27, 2022
🏹 Bow is a cross-platform library for Typed Functional Programming in Swift

Bow is a cross-platform library for Typed Functional Programming in Swift. Documentation All documentation and API reference is published in our websi

Bow 613 Dec 20, 2022
Butterfly is a lightweight library for integrating bug-report and feedback features with shake-motion event.

Butterfly is a lightweight library for integrating bug-report and feedback features with shake-motion event. Goals of this project One of th

Zigii Wong 410 Sep 9, 2022
Focus is an Optics library for Swift (where Optics includes Lens, Prisms, and Isos)

Focus Focus is an Optics library for Swift (where Optics includes Lens, Prisms, and Isos) that is inspired by Haskell's Lens library. Introduction Foc

TypeLift 201 Dec 31, 2022
📘A library for isolated developing UI components and automatically taking snapshots of them.

A library for isolated developing UI components and automatically taking snapshots of them. Playbook Playbook is a library that provides a sandbox for

Playbook 969 Dec 27, 2022
A Swift micro library for generating Sunrise and Sunset times.

Solar A Swift helper for generating Sunrise and Sunset times. Solar performs its calculations locally using an algorithm from the United States Naval

Chris Howell 493 Dec 25, 2022
Plugin and runtime library for using protobuf with Swift

Swift Protobuf Welcome to Swift Protobuf! Apple's Swift programming language is a perfect complement to Google's Protocol Buffer ("protobuf") serializ

Apple 4.1k Dec 28, 2022
A Swift package for rapid development using a collection of micro utility extensions for Standard Library, Foundation, and other native frameworks.

ZamzamKit ZamzamKit is a Swift package for rapid development using a collection of micro utility extensions for Standard Library, Foundation, and othe

Zamzam Inc. 261 Dec 15, 2022
ResponderChain is a library that passes events using the responder chain.

ResponderChain ResponderChain is a library that passes events using the responder chain.

GodL 21 Aug 11, 2021
RResultBuilder is DSL library based on Result Builder

RResultBuilder is DSL library based on Result Builder Features Requirements Installation Usage Screenshot Example Contribute Meta Feat

Rakuten, Inc. 24 Sep 28, 2022
noppefoxwolf/notion is a notion.so API library written in swift.

notion noppefoxwolf/notion is a notion.so API library written in swift. Installation Xcode Project > Swift Packages [email protected]:noppefoxwolf/notion

noppefoxwolf 44 Oct 7, 2022
An SSH config parser library with a fancy API

The SshConfig makes it quick and easy to load, parse, and decode/encode the SSH configs. It also helps to resolve the properties by hostname and use them safely in your apps (thanks for Optional and static types in Swift).

Artem Labazin 8 Nov 25, 2022