I need your help to calculate the distance between two markers using distanceTo() method.
I tried to implement that in Angular, but the following error has occurred in the console:
Here's the code:
display() {
let from_select = $('#from_station option:selected').val();
let to_select = $('#to_station option:selected').val();
let filteredStations1 = this.stationsNames.filter( function(currentStation1:any) {
return currentStation1.name == from_select;
})
let filteredStations2 = this.stationsNames.filter( function(currentStation2:any) {
return currentStation2.name == to_select;
})
let from = JSON.parse(filteredStations1[0].loc_stringify);
let to = JSON.parse(filteredStations2[0].loc_stringify);
console.log(from.distanceTo(to));
}
The error:
ERROR TypeError: from.distanceTo is not a function
at AddEditTripComponent.display (main.js:1125)
at AddEditTripComponent_Template_button_click_16_listener (main.js:1174)
at executeListenerWithErrorHandling (vendor.js:58037)
at wrapListenerIn_markDirtyAndPreventDefault (vendor.js:58072)
at HTMLButtonElement.<anonymous> (vendor.js:76806)
at ZoneDelegate.invokeTask (polyfills.js:9646)
at Object.onInvokeTask (vendor.js:71332)
at ZoneDelegate.invokeTask (polyfills.js:9645)
at Zone.runTask (polyfills.js:9414)
at ZoneTask.invokeTask [as invoke] (polyfills.js:9727)
You want to call the function distanceTo of a object that you get from JSON.prase, this object don't have the function distanceTo. You need first to create a Marker or a LatLng Object.
var fromLatLng = L.latLng(from);
var toLatLng = L.latLng(to);
var dis = fromLatLng.distanceTo(to);
console.log(dis);
Here's the answer:
let latlng1 = L.latLng(from.lat, from.lng);
let latlng2 = L.latLng(to.lat, to.lng);
let distance = latlng1.distanceTo(latlng2) / 1000
console.log(distance);
I'm using Firebase with GeoFire 3.0 Cocoapod in my Swift App to populate a map with markers all over the world. Here is the code to perform the circle query to get the markers within the area currently displayed on the map:
dbRef = Database.database().reference()
let geoRef = GeoFire(firebaseRef: dbRef.child("markers"))
let center = CLLocation(latitude: currentLocation.latitude, longitude: currentLocation.longitude)
print("Center: "," Lat: ",currentLocation.latitude," Long: ",currentLocation.longitude )
let circleQuery = geoRef.query(at: center, withRadius: 100)
circleQuery.observe(.keyEntered, with: { key, location in
print("key: ",key,"Location: ",location)
let markerKey = key
let markerLat = location.coordinate.latitude
let markerLong = location.coordinate.longitude
//read "verified" flag from firebase record "key"
self.dbRef.child(markerKey).observeSingleEvent(of: .value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
let verified = value?["verified"] as? Bool
print("key: ",key,"Location: ",location,"verified: ",verified as Any)
...
})
})
When the circle query is expanded by the user zooming out to display the map of the entire world (radius of 8000 Km (4791 MI)), the query aborts with an NSException.
The Xcode debugger shows GeoFire has calculated a latitude of 105.9793939... and longitude of -112.05707936...
Geofire should restrict the latitude at +/- 90 and the longitude at +/- 180 and in that case all GeoFire data should be returned from the Query.
Here is a screenshot of the error in Xcode:
Xcode Error Screenshot
Has anyone else seen this issue and/or found a solution?
Since GeoFire clearly does not limit the latitude and longitude in the way you want it to, you have two options
Report an issue on the GeoFire repo, and possibly propose a PR yourself.
Limit the values to the ranges you want in your own application code.
I'd suggest going with the second approach, since you'll want/need to show that you clipped/restricted the range in the UI anyway.
I am using an API that returns a String that contains coordinate. How do I convert this response:
"route_pins":
"#30.0539983,30.943465#30.0539033,30.9434167#30.05379,30.9434467#30.0536117,30.943865#30.0535133,30.9439867#30.0534633,30.9440967#30.05353,30.94428#30.053675,30.944525#30.0539933,30.9449667#30.0541517,30.9452317#30.0542917,30.9454717#30.054365,30.9455717#30.0544667,30.945725#30.05471,30.9460733#30.0548667,30.94631#30.0550417,30.9465683#30.0553733,30.9471133#30.0557133,30.9476383#30.0558667,30.947905#30.0560083,30.9481767#30.0562517,30.94872#30.0564917,30.9492217#30.0565783,30.9494567#30.056645,30.9496883#30.0566167,30.9501883"
into an Array of CLLocationCoordinate2D to draw a line using MapKit using:
let polyLine = MKPolyline(coordinates: Locations , count: Locations.count)
busMapView.add(polyLine)
You can do it with a combination of components(separatedBy and map
Split the string by character # and drop the first (empty) item.
Map each item to CLLocationCoordinate2D by splitting the string by the comma, convert the strings to CLLocationCoordinate2D and create the coordinate.
let routePins = "#30.0539983,30.943465#30.0539033,30.9434167#30.05379,30.9434467#30.0536117,30.943865#30.0535133,30.9439867#30.0534633,30.9440967#30.05353,30.94428#30.053675,30.944525#30.0539933,30.9449667#30.0541517,30.9452317#30.0542917,30.9454717#30.054365,30.9455717#30.0544667,30.945725#30.05471,30.9460733#30.0548667,30.94631#30.0550417,30.9465683#30.0553733,30.9471133#30.0557133,30.9476383#30.0558667,30.947905#30.0560083,30.9481767#30.0562517,30.94872#30.0564917,30.9492217#30.0565783,30.9494567#30.056645,30.9496883#30.0566167,30.9501883"
let coordinates = routePins.components(separatedBy: "#").dropFirst().map { (pin) -> CLLocationCoordinate2D in
let latLng = pin.components(separatedBy: ",").map{ CLLocationDegrees($0)! }
return CLLocationCoordinate2D(latitude: latLng[0], longitude: latLng[1])
}
The result is [CLLocationCoordinate2D].
let dic:Dictionary<String,Any> = ["route_pins": "#30.0539983,30.943465#30.0539033,30.9434167#30.05379,30.9434467#30.0536117,30.943865#30.0535133,30.9439867#30.0534633,30.9440967#30.05353,30.94428#30.053675,30.944525#30.0539933,30.9449667#30.0541517,30.9452317#30.0542917,30.9454717#30.054365,30.9455717#30.0544667,30.945725#30.05471,30.9460733#30.0548667,30.94631#30.0550417,30.9465683#30.0553733,30.9471133#30.0557133,30.9476383#30.0558667,30.947905#30.0560083,30.9481767#30.0562517,30.94872#30.0564917,30.9492217#30.0565783,30.9494567#30.056645,30.9496883#30.0566167,30.9501883"]
let strLatLng = dic["route_pins"] as! String
let arrayOflatLng = strLatLng.components(separatedBy: "#")
var testcoords = [CLLocationCoordinate2D]()
for latLngStr in arrayOflatLng {
if let strLat = latLngStr.components(separatedBy: ",") as? [String], strLat.count == 2 {
testcoords.append(CLLocationCoordinate2D(latitude: CLLocationDegrees(strLat[0])!, longitude: CLLocationDegrees(strLat[1])!))
}
}
print("testcoords \(testcoords.count)")
let polyLine = MKPolyline(coordinates: testcoords , count: testcoords.count)
busMapView.add(polyLine)
The API string is parsed using 2 levels of parsing ,first we split the API string to locations strings , then using for loop to split each location to its coordinates and save coordinates to CLLocationCoordinate2D and append it to result array
let routePins = "#30.0539983,30.943465#30.0539033,30.9434167#30.05379,30.9434467#30.0536117,30.943865#30.0535133,30.9439867#30.0534633,30.9440967#30.05353,30.94428#30.053675,30.944525#30.0539933,30.9449667#30.0541517,30.9452317#30.0542917,30.9454717#30.054365,30.9455717#30.0544667,30.945725#30.05471,30.9460733#30.0548667,30.94631#30.0550417,30.9465683#30.0553733,30.9471133#30.0557133,30.9476383#30.0558667,30.947905#30.0560083,30.9481767#30.0562517,30.94872#30.0564917,30.9492217#30.0565783,30.9494567#30.056645,30.9496883#30.0566167,30.9501883"
let pins = routePins.components(separatedBy: "#")//first step is splitting the fetched array to pins array
var LocationsArray = [CLLocationCoordinate2D]()//this is the result array
for location in pins {
if(location.contains(",")){//checking that the location is containing lat ,long separtor
let coordinates = location.components(separatedBy: ",")//splitting the location to lat ,long
//safe parsing the string value to double vale for coordinates
let lat = Double(coordinates[0]) ?? 0.0
let long = Double( coordinates[1]) ?? 0.0
LocationsArray.append(CLLocationCoordinate2D(latitude: lat
,longitude: long))// appending new coordinates to locations array
}
}
I have a list of lat&lon, want to show it on map as a path. I could show polyline on the map by using GMSPath(fromEncodePath: polyline).
How could I convert lat&lon list as a polyline or display it on the map?
Much appreciated!
You can create a path from coordinates like this
let path = GMSMutablePath()
path.add(CLLocationCoordinate2DMake(29.520,30.856))
path.add(CLLocationCoordinate2DMake(25.17,40.1235))
let pLine = GMSPolyline.init(path: path)
I am trying to store placemarks in a global array but not sure what I'm actually trying to store. I want to be able to remove the placemark at a later time. Do I just need to store the lat and lng or do I need to store some kind of placemark obj in the array. I've tried to look at the google docs but they are I think written in greek. Could someone point me in the right direction??
Inside a for loop on the global array PASSENGERS we have the following code:
// prepare placemark
var placemark = earth.createPlacemark("");
placemark.setName(PASSENGERS[i].name + " to " + PASSENGERS[i].house);
// prepare icon
var icon = earth.createIcon("");
icon.setHref(url + "/img/" + PASSENGERS[i].username + ".jpg");
// prepare style
var style = earth.createStyle("");
style.getIconStyle().setIcon(icon);
style.getIconStyle().setScale(4.0);
// prepare stylemap
var styleMap = earth.createStyleMap("");
styleMap.setNormalStyle(style);
styleMap.setHighlightStyle(style);
// associate stylemap with placemark
placemark.setStyleSelector(styleMap);
// prepare point
var point = earth.createPoint("");
point.setAltitudeMode(earth.ALTITUDE_RELATIVE_TO_GROUND);
point.setLatitude(building.lat);
point.setLongitude(building.lng);
point.setAltitude(0.0);
// associate placemark with point
placemark.setGeometry(point);
I thought I could print out placemark with:
for (var prop in placemark)
{
console.log(prop + " = " + placemark[prop]);
}
but that doesn't seem to work.
I think you need to take some time and try to understand the docs.
See https://developers.google.com/earth/documentation/placemarks?csw=1
Once you add placemarks to the the plugin they are in memory inside the plugin and there is no need to store them in another array.
You can assign the placemark an id.
// to add
var placemark= ge.createPlacemark('your_id_here');
ge.getFeatures().appendChild(placemark);
// to remove
var myPlacemark= ge.getElementById('your_id_here');
ge.getFeatures().removeChild(myPlacemark);