Coder Social home page Coder Social logo

Comments (6)

macdrevx avatar macdrevx commented on May 29, 2024

The prepared geometry capability of GEOS would likely be a good fit for your use case. GEOSwift doesn't expose those APIs yet, but I'll consider this issue a feature request to add them!

from geoswift.

macdrevx avatar macdrevx commented on May 29, 2024

Could you give #264 a try and let me know how it works?

The usage will be something like…

  1. Map the geometry of each of your features to a PreparedGeometry by calling the new makePrepared() method, and store those values somewhere alongside the original features/properties.
  2. At each location update use one of the new contains methods on PreparedGeometry to test for containment.

This is the first time I've tried prepared geometry, and it's a little different than the rest of GEOSwift in that the underly GEOS context escapes the scope of a single method call. I need to do a bit more testing & investigation to make sure that's not going to cause any problems, but in the mean time, please give it a try and let me know if you have any feedback.

from geoswift.

macdrevx avatar macdrevx commented on May 29, 2024

I also wonder whether the STRtree APIs in GEOS might be an even better fit. I will explore that as well (though I'm out of time for today).

from geoswift.

Jessers1 avatar Jessers1 commented on May 29, 2024

Thanks so much! I've implemented your pull request and at this stage (Fingers crossed) with test locations, it seems to work extremely fast and with accuracy however I am yet to test in a live location update sense (During a journey).

Implementation:

`

import Foundation
import MapKit
import GEOSwift
import CoreLocation
import Combine


class SpeedLimitStore: ObservableObject {
    @Published var geoJSON: GeoJSON? = nil
    var preparedGeometries: [PreparedGeometry] = []
    var featureProperties: [[String: Any]] = []

      init() {
          loadSpeedLimits { features in
              self.geoJSON = GeoJSON.featureCollection(FeatureCollection(features: features))
              self.prepareGeometriesAndStoreProperties(features: features)
          }
      }
  
  
  struct SpeedLimit {
      let geometry: Geometry
      let speedLimit: Int
  }

  func loadSpeedLimits(completion: @escaping ([Feature]) -> Void) {
      guard let geoJSONURL = Bundle.main.url(forResource: "speed_limits", withExtension: "geojson") else {
          print("GeoJSON file not found")
          return
      }

      do {
          let data = try Data(contentsOf: geoJSONURL)
          let geoJSON = try JSONDecoder().decode(GeoJSON.self, from: data)
          if case let .featureCollection(featureCollection) = geoJSON {
              print("Loaded \(featureCollection.features.count) speed limit features")
              completion(featureCollection.features)
          } else {
              print("Error: GeoJSON data is not a FeatureCollection")
          }
      } catch {
          print("Error parsing GeoJSON data: \(error.localizedDescription)")
      }
  }
  
  func prepareGeometriesAndStoreProperties(features: [Feature]) {
          for feature in features {
              guard let geometry = feature.geometry,
                    let properties = feature.properties else {
                  continue
              }

              do {
                  let preparedGeometry = try geometry.makePrepared()
                  preparedGeometries.append(preparedGeometry)
                  featureProperties.append(properties)
              } catch {
                  print("Error preparing geometry: \(error)")
              }
          }
      }

}
`

And

`

func findSpeedLimit(location: CLLocationCoordinate2D, preparedGeometries: [PreparedGeometry], featureProperties: [[String: Any]]) -> Int? {

  // Create a Point object from the location coordinates
  let point = Point(x: location.longitude, y: location.latitude)
  
  // Loop through the prepared geometries
  for (index, preparedGeometry) in preparedGeometries.enumerated() {
      do {
          // Check if the prepared geometry contains the point
          if try preparedGeometry.contains(point) {
              // Check if the properties have a speedLimitZoneValue key
              let properties = featureProperties[index]
              if let speedLimit = properties["speedLimitZoneValue"] {
                  let speedLimitString = String(describing: speedLimit)
                  if let number = Int(speedLimitString.components(separatedBy: CharacterSet.decimalDigits.inverted).joined()) {
                      return number
                  }
              } else {
                  print("Feature \(index) has no 'speedLimitZoneValue' property")
              }
          }
      } catch {
          print("Error checking if prepared geometry contains point: \(error)")
      }
  }
  
  return nil

}

`

As I said before at this stage it looks miles quicker for simple test locations however I will need to test it in a live updating context.

from geoswift.

Jessers1 avatar Jessers1 commented on May 29, 2024

I will mention though that the bootup time of the program still is incredibly slow (and was even before the changes). Is this usual with the GeoSwift library. See my current loadspeedlimits function. I do call it in the App.swift file could that be the issue?

`
@main
struct SafeDrivingMapsApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var speedLimitStore = SpeedLimitStore()

      var body: some Scene {
          WindowGroup {
              ContentView()
                  .environmentObject(speedLimitStore)
          }
      }
  }

`

from geoswift.

Jessers1 avatar Jessers1 commented on May 29, 2024

Fixed the bootup time by loading the data asynchronously in the background. At this stage prepared geometry seems to be working perfectly.

from geoswift.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.