add result of image.plot layer on geographic map (bing map) - maps

I have a 2D footprint result for an eddy-covariance system on a 1100*1100 square meter, with the domain of
domain = c(-100,1000,-100, 1000)
the cell size of the domain (each grid) is 2 meters with the origin (0,0) accordingly on this location:
Lon = -97.191391 #longtitude
Lat = 36.055935 #latitude
An example data (9.01 Mb) is attached here. FFP.rds
then I can plot a Bing map on my site as this:
library(OpenStreetMap)
library(rgdal)
map <- openmap(c(36.05778,-97.19250), c(36.05444,-97.18861),type='bing')
plot(map)
and I use image.plot() from package "fields" to plot the footprint with these following codes:
library(fields)
str(FFP$fclim_2d)
image.plot(FFP$x_2d[1,],FFP$y_2d[,1],FFP$fclim_2d)
But I am wondering how to scale each grid of my footprint result to Bing map (or google map).
Any suggestions would be greatly appreciated.

Related

How to use extra extra_x_ranges, extra_y_ranges with add_tile in bokeh

I want to use long/lat (EPSG:4326) coordinates in a bokeh plot and have a map in the Background.
I tried with the tile provider maps as suggested in bokeh: Mapping geo data.
But the format is in web mercator coordinates (EPSG:3857) and I don't want to convert my coordinates.
The general question how to do this is unanswered in Is it possible to set figure axis_type in bokeh to geographical (long/lat)?
My idea was to use extra axes:
from bokeh.plotting import figure, show
from bokeh.models import Range1d, LinearAxis
from bokeh.tile_providers import CARTODBPOSITRON, get_provider
tile_provider = get_provider(CARTODBPOSITRON)
p = figure(x_range=(-180, 180), y_range=(-90, 90)) # EPSG:4326
# add extra axis
p.extra_x_ranges = {"EPSG:3857x": Range1d(start=-20026376.39, end=20026376.39)}
p.extra_y_ranges = {"EPSG:3857y": Range1d(start=-20048966.10, end=20048966.10)}
# place extra axis
p.add_layout(LinearAxis(x_range_name="EPSG:3857x"), 'above')
p.add_layout(LinearAxis(y_range_name="EPSG:3857y"), 'right')
p.add_tile(tile_provider, x_range_name="EPSG:3857x", y_range_name="EPSG:3857y")
show(p)
But the map is not visible.
Is there a way to use extra axis for a tile_provider?
If you are just asking about displaying lat/lng visually on the axes, then all you have to do is set the axis type to "mercator"
p = figure(x_range=(-2000000, 6000000), y_range=(-1000000, 7000000),
x_axis_type="mercator", y_axis_type="mercator")
This is demonstrated on the documentation page you linked.
If you are asking about using data that is in lan/lng coordinates to plot on a tile plot, then you will need to convert it to Web Mercator first. The underlying coordinate system for tiles is always Web Mercator.
If you are asking about something else, then your question is not clear (please update to clarify).

Core Data Filter by Distance From Current User Location

I have an NSManagedObject class that's persisted in a SQLite database in Core Data. This object has persistent Latitude and Longitude properties. I'm trying to create an NSFetchedRequestController that fetches all of the instances of that class that are within a certain distance from the user. Having done some research, it seems impossible to do this with Core Data, because Core Data only supports bounding-box style queries, not predicates with blocks.
For example, I have a class of Groups with latitude and longitude properties. Given the latitude and longitude (of, say, a user), fetch all groups that are within a 6 mile radius of the given latitude and longitude.
class Group{
var latitude: Float
var longitude: Float
}
I'd like to take advantage of Core Data's R-Tree Indexing to do a fast bounding-box query on the latitudes and longitudes of instances of my class near my user. Then I'd like to filter the results with a more precise predicate, using my own block of code to see which of the instances are within my users current location. Here's the "Bounding box" query.
let request: NSFetchRequest<Group> = Group.fetchRequest()
let (topLeft,bottomRight) = boundingBox(center: center, radius: searchRadius)
let maxLat = topLeft.latitude
let minLon = topLeft.longitude
let minLat = bottomRight.latitude
let maxLon = bottomRight.longitude
let predicate = NSPredicate(format: "(%f < longitude AND longitude < %f) AND (%f < latitude AND latitude < %f)", minLon, maxLon, minLat, maxLat)
request.predicate = predicate
The problem is that I'd like a fetch that looked like this:
let location: CLLocation = /* Initialize a CLLocation */
let predicate = NSPredicate { (obj, _) -> Bool in
let object = obj as! Group
let objLocation = CLLocation(latitude: Double(object.latitude), longitude: Double(object.longitude))
return location.distance(from: objLocation) < 9656 //6 miles in meters
}
NSFetched results controller doesn't allow predicate with block. There's a significant difference between these two fetches. The first gets all groups in a Bounding Box, (the minLat, minLon, maxLat, and maxLat), the latter gets all groups in a Circle of a given radius.
I want to then use an NSFetchedRequestController to display the results in a table, and take advantage of the nice auto-update features. But of course, Core Data only supports bounding-box style queries, not the two-step filter method I need. Is there a proper solution?
I'm open to using other databases, if Core Data simply won't work with this type of use. I took a look at YapDatabase, and it seems more flexible, and includes R-Tree indexing, but I'm concerned that it's not well supported. Realm doesn't support R-Tree Indexing.

How to find the locations (indices whose lat long co-ordinates are stored in geo-json format) within 5 Km radius of a h3 index in h3-js?

I'm creating a hyper local delivery service app . I can only receive order if there is a store within 5 km radius from the user . I stored the store locations in geojson format . Is there a function in h3-js which will take radius , array of stores , h3 index and then give back the list of stores which are within 5 km range from the given h3 index . or how can i implement this using h3-js?
There are a few different parts here:
Pick a resolution: Pick an H3 resolution for lookup. Finer res means more accuracy but more memory usage. Res 8 is roughly a few city blocks in size.
Indexing Data: To use H3 for the radius lookup, you need to index the stores by H3 index. If you want this to be efficient, you'd be better off indexing all the stores ahead of time. How you do this is up to you; one easy way in JS might be to create a map of id arrays:
const lookupIndexes = stores.features.reduce((map, feature) => {
const [lon, lat] = feature.geometry.coordinates;
const h3Index = h3.geoToH3(lat, lon, res);
if (!map[h3Index]) map[h3Index] = [];
map[h3Index].push(feature.id);
return map;
}, {})
Perform the lookup: To search, index your search location and get all the H3 indexes within some radius. You can use the h3.edgeLength function to get the approximate radius of a cell at your current resolution.
const origin = h3.geoToH3(searchLocation.lat, searchLocation.lon, res);
const radius = kmToRadius(searchRadiusKm, res);
// Find all the H3 indexes to search
const lookupIndexes = h3.kRing(origin, radius);
// Find all points of interest in those indexes
const results = lookupIndexes.reduce(
(output, h3Index) => [...output, ...(lookupMap[h3Index] || [])],
[]);
See a working example on Observable
Caveats: This is not a true radius search. The k-ring is a roughly hexagonal shape centered on the origin. This is good enough for many use cases, and much faster than a traditional Haversine radius search, especially if you have many rows to search over. But if you care about the exact distance H3 might not be appropriate (or, in some cases, H3 might be fine, but you might want the indexes inside a "true" circle - one option here is to convert your circle to a close-to-circular polygon, then get the indexes via h3.polyfill).

Openlayers 3 Circle radius in meters

How to get Circle radius in meters
May be this is existing question, but i am not getting proper result. I am trying to create Polygon in postgis with same radius & center getting from openlayers circle.
To get radius in meters I followed this.
Running example link.
var radiusInMeters = circleRadius * ol.proj.METERS_PER_UNIT['m'];
After getting center, radius (in meters) i am trying to generate Polygon(WKT) with postgis (server job) & drawing that feature in map like this.
select st_astext(st_buffer('POINT(79.25887485937808 17.036647682474722 0)'::geography, 365.70644956827164));
But both are not covering same area. Can any body please let me know where i am doing wrong.
Basically my input/output to/from Circle will be in meters only.
ol.geom.Circle might not represent a circle
OpenLayers Circle geometries are defined on the projected plane. This means that they are always circular on the map, but the area covered might not represent an actual circle on earth. The actual shape and size of the area covered by the circle will depend on the projection used.
This could be visualized by Tissot's indicatrix, which shows how circular areas on the globe are transformed when projected onto a plane. Using the projection EPSG:3857, this would look like:
The image is from OpenLayer 3's Tissot example and displays areas that all have a radius of 800 000 meters. If these circles were drawn as ol.geom.Circle with a radius of 800000 (using EPSG:3857), they would all be the same size on the map but the ones closer to the poles would represent a much smaller area of the globe.
This is true for most things with OpenLayers geometries. The radius, length or area of a geometry are all reported in the projected plane.
So if you have an ol.geom.Circle, getting the actual surface radius would depend on the projection and features location. For some projections (such as EPSG:4326), there would not be an accurate answer since the geometry might not even represent a circular area.
However, assuming you are using EPSG:3857 and not drawing extremely big circles or very close to the poles, the Circle will be a good representation of a circular area.
ol.proj.METERS_PER_UNIT
ol.proj.METERS_PER_UNIT is just a conversion table between meters and some other units. ol.proj.METERS_PER_UNIT['m'] will always return 1, since the unit 'm' is meters. EPSG:3857 uses meters as units, but as noted they are distorted towards the poles.
Solution (use after reading and understanding the above)
To get the actual on-the-ground radius of an ol.geom.Circle, you must find the distance between the center of the circle and a point on it's edge. This could be done using ol.Sphere:
var center = geometry.getCenter()
var radius = geometry.getRadius()
var edgeCoordinate = [center[0] + radius, center[1]];
var wgs84Sphere = new ol.Sphere(6378137);
var groundRadius = wgs84Sphere.haversineDistance(
ol.proj.transform(center, 'EPSG:3857', 'EPSG:4326'),
ol.proj.transform(edgeCoordinate, 'EPSG:3857', 'EPSG:4326')
);
More options
If you wish to add a geometry representing a circular area on the globe, you should consider using the method used in the Tissot example above. That is, defining a regular polygon with enough points to appear smooth. That would make it transferable between projections, and appears to be what you are doing server side. OpenLayers 3 enables this by ol.geom.Polygon.circular:
var circularPolygon = ol.geom.Polygon.circular(wgs84Sphere, center, radius, 64);
There is also ol.geom.Polygon.fromCircle, which takes an ol.geom.Circle and transforms it into a Polygon representing the same area.
My answer is a complement of the great answer by Alvin.
Imagine you want to draw a circle of a given radius (in meters) around a point feature. In my particular case, a 200m circle around a moving vehicle.
If this circle has a small diameter (< some kilometers), you can ignore earth roudness. Then, you can use the marker "Circle" in the style function of your point feature.
Here is my style function :
private pointStyle(feature: Feature, resolution: number): Array<Style> {
const viewProjection = map.getView().getProjection();
const coordsInViewProjection = (<Point>(feature.getGeometry())).getCoordinates();
const longLat = toLonLat(coordsInViewProjection, viewProjection);
const latitude_rad = longLat[1] * Math.PI / 180.;
const circle = new Style({
image: new CircleStyle({
stroke: new Stroke({color: '#7c8692'});,
radius: this._circleRadius_m / (resolution / viewProjection.getMetersPerUnit() * Math.cos(latitude_rad)),
}),
});
return [circle];
}
The trick is to scale the radius by the latitude cosine. This will "locally" disable the distortion effect we can observe in the Tissot Example.

Google Maps coordinates in KML

I'm trying to use kml for rendering geo-coordinates in google maps.
Unfortunately, I have some troubles with coordinates: when I insert in KML coordinates from Google maps, and then pass this KML file to google maps service, placemarks points to another place in the Earth.
Maybe I dont guess format of placemark location for KML ?
Sometimes Google Maps will report coordinates in "Degrees, Minutes, Seconds" (DMS) notation, which can look like this: 37°48'21.0"N 122°27'57.6"W.
KML needs coordinates in "Decimal Degrees" (DD) notation, which would look like this: -122.466001, 37.805828. Note that KML also expects the order Longitude, Latitude, which is different from many other places, which show Latitude then Longitude.
So... if you're somehow getting your coordinates in DMS notation, then you'll need to convert to DD notation, and make sure the Lon,Lat order is correct.
in the KML file i have the LatLng was backwards.
KML => -.709448,54.009222,0
gmaps => 54.009222,-.709448
use pandas to read cvs into df
then use simplekml to export it into lml
Note: coords is (lon,lat,height) # lon, lat, optional height
example:
import simplekml
snet_kml='test.kml'
kml = simplekml.Kml()
for name,lat,lon,height in zip(snet[NAMES[0]], snet[NAMES[1]], snet[NAMES[2]], snet[NAMES[3]]):
kml.newpoint(name=name, coords=[(lon,lat,height)]) # lon, lat, optional height
print("*** Created {}".format(snet_kml))
print(kml.kml())
kml.save(snet_kml)

Resources