I'd like to know the local time where my user is sending his request from.
Basically, is there such a thing as a function like this
var localTime = getLocalTime( lat, long );
I'm not sure if a simple division on the lat could work, since most of the countries don't have perfect geometric shapes.
Any help would be great. Any language is accepted. I'd like to avoid calling distant APIs.
The Google Time Zone API seems to be what you're after. It, however does not have any free tier.
The Time Zone API provides time offset data for locations on the surface of the earth. Requesting the time zone information for a specific Latitude/Longitude pair will return the name of that time zone, the time offset from UTC, and the Daylight Savings offset.
The shapefile used to compute the timezone is not maintained anymore.
I just faced the same issue today, and I am not sure how relevant my answer is after all this time, but I basically just wrote a Python function that does what you want. You can find it here.
https://github.com/cstich/gpstotz
Edit:
As mentioned in the comments I should also post code. The code is based on Eric Muller's shapefile of timezones, which you can get here - http://efele.net/maps/tz/world/.
Edit 2:
As it turns out shapefiles have a somewhat archaic definition of exterior and interior rings (basically exterior rings are using the right hand rule, while interior rings are using the left hand rule). In any case fiona seems to take care of that and I updated the code accordingly.
from rtree import index # requires libspatialindex-c3.deb
from shapely.geometry import Polygon
from shapely.geometry import Point
import os
import fiona
''' Read the world timezone shapefile '''
tzshpFN = os.path.join(os.path.dirname(__file__),
'resources/world/tz_world.shp')
''' Build the geo-index '''
idx = index.Index()
with fiona.open(tzshpFN) as shapes:
for i, shape in enumerate(shapes):
assert shape['geometry']['type'] == 'Polygon'
exterior = shape['geometry']['coordinates'][0]
interior = shape['geometry']['coordinates'][1:]
record = shape['properties']['TZID']
poly = Polygon(exterior, interior)
idx.insert(i, poly.bounds, obj=(i, record, poly))
def gpsToTimezone(lat, lon):
'''
For a pair of lat, lon coordiantes returns the appropriate timezone info.
If a point is on a timezone boundary, then this point is not within the
timezone as it is on the boundary. Does not deal with maritime points.
For a discussion of those see here:
http://efele.net/maps/tz/world/
#lat: latitude
#lon: longitude
#return: Timezone info string
'''
query = [n.object for n in idx.intersection((lon, lat, lon, lat),
objects=True)]
queryPoint = Point(lon, lat)
result = [q[1] for q in query
if q[2].contains(queryPoint)]
if len(result) > 0:
return result[0]
else:
return None
if __name__ == "__main__":
''' Tests '''
assert gpsToTimezone(0, 0) is None # In the ocean somewhere
assert gpsToTimezone(51.50, 0.12) == 'Europe/London'
I was searching for the same thing couple of days ago and unfortunately I could not find an API or a simple function that does it. The reason being as you said that countries do not have perfect geometric shapes. You have to create a representation of the area of each time zone and see where your point lies. I think this will be a pain and I have no idea if it can be done at all.
The only one I found is described here: Determine timezone from latitude/longitude without using web services like Geonames.org . Basically you need a database with information about timezones and you are trying to see which one is closest to your point of interest.
However, I was looking for static solutions(without using internet), so if you can use internet connection you can use: http://www.earthtools.org/webservices.htm which provides a webservice to give you the timezone given lat/lon coordinates.
As of 2019, Google API does not have any free tier and the data source of #cstich answer is not maintained anymore.
If you want an API, timezonedb.com offers a free tier rate limited to 1 request/second.
The original maintainer of the data used by #cstich link to this project which retrieve data from OpenStreetMap. The readme contains link to look up libraries in a wide variety of languages.
Couldn't you simply use the user IP to determine which they live in ? And then you use an array of (Countries | Difference with GMT) to get the local time.
Related
I am looking to model a vehicle routing problem with time windows on OctaPy. Specifically, this problem involves traffic enforcement on public roads, so parking wardens need to survey carparks and road segments and visit them more than once during a 24-hour period.
I refer to the answer in the following question as foundation to develop my problem:
Is it possible to create a VRP solution using NetworkX?
I have a few questions regarding the modelling:
How does OctaPy model time-dependency, that is a different edge weight representing travel duration depending on the time of day?
How do I model the demand points if each point needs to be visited X times?
If a demand point is to be visited X times, how can I enforce a time window gap such that the duration between visits is at least a fixed duration (e.g. 1 hour)?
OptaPy models time-dependency the way you model time-dependency. That is, whatever you use to model time-dependency (may it be an edge, a list, a matrix, a class, etc.), OptaPy can use it in its constraints.
If X is known in advance, for each demand point, you create X copies of it and put it in the #problem_fact_collection_property field. If X is not known in advance, consider using real-time planning (https://www.optapy.org/docs/latest/repeated-planning/repeated-planning.html#realTimePlanning).
This depends on how you implement your time dependency. This would be easier when OptaPy supports the new VariableListener API for List Variable (as well as the builtin list shadow variables) that OptaPlanner has. Until then, you need to do the calculation in a function. Make Edge a #planning_entity and give it a inverse relation shadow variable (https://www.optapy.org/docs/latest/shadow-variable/shadow-variable.html#bidirectionalVariable). Add a method get_arrival_time(edge) to Vehicle that get the estimated time of visit for a given Edge in its visited_edges_list.
def less_than_one_hour_between(visit_1: Edge, visit_2: Edge):
visit_1_arrival_time = visit_1.vehicle.get_arrival_time(visit_1)
visit_2_arrival_time = visit_2.vehicle.get_arrival_time(visit_2)
duration = visit_2_arrival_time - visit_1_arrival_time
return timedelta(hours=0) <= duration <= timedelta(hours=1)
def one_hour_between_consecutive_visits(constraint_factory):
return (
constraint_factory.for_each(Edge)
.join(Edge, Joiners.equal(lambda edge: edge.graph_from_node),
Joiners.equal(lambda edge: edge.graph_to_node))
.filter(lambda a, b: a is not b and less_than_one_hour_between(a, b))
.penalize('less than 1 hour between visits', HardSoftScore.ONE_HARD)
The simple equation for user location using inbuilt inertial measurement unit (IMU) which is also called pedestrian dead reckoning (PDR) is given as:
x= x(previous)+step length * sin(heading direction)
y= y(previous)+step length *cos(heading direction )
We can use the motionManager property of CMMotionManager class to access raw values from accelerometer, gyroscope, and magnetometer. Also, we can get attitudes values as roll, pitch, and yaw. The step length can be calculated as the double square root of acceleration. However, I'm confused with the heading direction. Some of the published literature has used a combination of magnetometer and gyroscope data to estimate the heading direction. I can see that CLHeading also gives heading information. There are some online tutorials especially for an android platform like this to estimate user location. However, it does not give any proper mathematical explanation.
I've followed many online resources like this, this,this, and this to make a PDR app. My app can detect the steps and gives the step length properly however its output is full of errors. I think the error is due to the lack of proper heading direction. I've used the following relation to get heading direction from the magnetometer.
magnetometerHeading = atan2(-self.motionManager.magnetometerData.magneticField.y, self.motionManager.magnetometerData.magneticField.x);
Similarly, from gyroscope:
grysocopeHeading +=-self.motionManager.gyroData.rotationRate.z*180/M_PI;
Finally, I give proportional weight to the previous heading driection, gryoscopeheading, and magnetometerHeading as follows:
headingDriection = (2*headingDirection/5)+(magnetometerHeading/5)+(2*gryospoceHeading/5);
I followed this method from a published journal paper. However, I'm getting lots of error in my work. Is my approach wrong? What exactly should I do to get a proper heading direction such that the localization estimation error would be minimum?
Any help would be appreciated.
Thank you.
EDIT
I noticed that while calculating heading direction using gyroscope data, I didn't multiply the rotation rate (which is in radian/sec) with the delta time. For this, I added following code:
CMDeviceMotion *motion = self.motionManager.deviceMotion;
[_motionManager startDeviceMotionUpdates];
if(!previousTime)
previousTime = motion.timestamp;
double deltaTime = motion.timestamp - previousTime;
previousTime = motion.timestamp;
Then I updated the gyroscope heading with :
gyroscopeHeading+= -self.motionManager.gryoData.rotationRate.z*deltaTime*180/M_PI;
The localization result is still not close to the real location. Is my approach correct?
How can I simulate continuous traffic flow from historical data which consists of:
1. Vehicle ID;
2. Speed;
3. Coordinates
without knowing the routes of each vehicle ID.
This is a commonly asked questions but probably hasn't been answered here before. Unfortunately the answer largely depends on the quality of your input data mainly on the frequency / distance of your location updates (it would be also helpful if there is a time stamp to each datum) and how precise the locations fit your street network. In the best case there is a location update on each edge of the route in the street network and you can simply read off the route by mapping the location to the street. This mapping can be done using the python sumolib coming with sumo:
import sumolib
net = sumolib.net.readNet("myNet.net.xml")
route = []
radius = 1
for x, y in coordinates:
minDist, minEdge = min([(dist, edge) for edge, dist in net.getNeighboringEdges(x_coordinate, y_coordinate, radius)])
if len(route) == 0 or route[-1] != minEdge.getID():
route.append(minEdge.getID())
See also http://sumo.dlr.de/wiki/Tools/Sumolib#locate_nearby_edges_based_on_the_geo-coordinate for additional geo conversion.
This will fail when there is an edge in the route which did not get hit by a data point or if you have a mismatch (for instance matching an edge which goes in the "wrong" direction). In the former case you can easily repair the route using sumo's duarouter.
> duarouter -n myNet.net.xml -r myRoutesWithGaps.rou.xml -o myRepairedRoutes.rou.xml --repair
The latter case is considerably harder both to detect and to repair because it largely depends on your definition of a wrong edge. There are almost clear cases like hitting suddenly the opposite direction (which still can happen in real traffic) and a lot of small detours which are hard to decide and deserve a separate answer.
Since you are asking for continuous input you may also be interested in doing this live with TraCI and in this FAQ on constant input flow.
Given a GEO-JSON polygon, such as the below:
[
[15.520376, 38.231155],
[15.160243, 37.444046],
[15.309898, 37.134219],
[15.099988, 36.619987],
[14.335229, 36.996631],
[13.826733, 37.104531],
[12.431004, 37.61295],
[12.570944, 38.126381],
[13.741156, 38.034966],
[14.761249, 38.143874],
[15.520376, 38.231155]
]
How can I check if a GPS location is within the polygon region?
For example, if the user is at Lat 37.387617, Long 14.458008, how would I go about searching the array?
I don't need someone to necessarily write the code for me, I just don't understand the logic of how I can check. If you have any example (any language) please point me.
This task is called point in polygon test.
Gerve has explained the algorithm that is widley used for this task. But this will not help you in implementing it. There are foot traps, like parallel lines.
One of that algorithms is called Crossings Multiply test, which is an optimized variant.
Source code: CrossingsMultiplyTest (last function in the file)
An Overview is given in "Point in Polygon Strategies"
Use longitude for the x coordinate, and latitude for the y coordinate.
I've found an article about the Ray-casting algorithm. It's explained pretty well here, the jist of it is (in pseudo code):
count ← 0
foreach side in polygon:
if ray_intersects_segment(P,side) then
count ← count + 1
if is_odd(count) then
return inside
else
return outside
I need Lat/LON from GIS data
I have data files from
http://www.mngeo.state.mn.us/chouse/land_own_property.html
given in the format of
.dbf, .prj, .sbn, .sbx, .shp, and .shx
in the .dbf I see
PIN, Shape_area, Shape_len
PARC_CODE Parcel Polygon to Parcel Point numeric 2
and PIN Relationship Code
and in the .prj
PROJCS["NAD_1983_UTM_Zone_15N",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",500000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-93.0],PARAMETER["Scale_Factor",0.9996],PARAMETER["Latitude_Of_Origin",0.0],UNIT["Meter",1.0]]
I also know the polygon points for each county
polygons points
Anoka 129139 129138
Carver 38134 38133
Dakota 135925 150294
Hennepin 422976 446623
Ramsey 149169 168233
Scott 55191 55191
Washington 98915 103915
and I know the bounding coordinates
-94.012
-92.732
45.415
44.471
there seems to be tons of software applications for GIS
http://en.wikipedia.org/wiki/List_of_geographic_information_systems_software
but what do I need to do?
I want the lat, lon of every house
Is there a library that will do this for me?
What is the data I need?
I think you need to install one GIS software. You can try open-source Qgis.
Because, firstly your data is not in long/lat (geographic) coordinates. Your .prj part of the shapefile (yes, all .dbf, .prj, .sbn, .sbx, .shp, and .shx files with the same name are one shapefile for GIS) says that the data are in the projected coordinate system NAD 1983 UTM Zone 15N. So, you need to transform your data to geographic system. This you easy can do in GIS, or programmatically by proj.4 library. (In Qgis add the shapefile to the project, then select it in the table of contents, right mouse button and choose "save as...". It will ask you for the target coordinate system.) Note, that you need to decide which geographic coordinates you wish, because your data are in the North American Datum (NAD 1983), but the most common worldwide now is WGS 1984.
Secondly, in GIS you will see your data, are they really points, or maybe polygons. (In case your houses are polygons you will need to get centroids of them, in Qgis menu Vector - Geometry Tools - Polygon Centroids).
Finally, when you really have your houses as points in geographic coordinates, you can get their coordinates, for example using advices from these questions Get list of coordinates for points in a layer and How do I calculate the latitude and longitude of points using QGIS.
Besides, there is a good library to work with GIS vector data, OGR, which can be used by many programming languages.
The file extensions above show, that the files are in ESRI Shape File format. In Java you could use GeoTools libraries, to read that.
The example below shows the first lines, search Internet for a more complete example.
// init shapefile
File shpFile = new File(fileName);
if (!shpFile.exists()) {
LOGGER.fatal(fileName + " does not exist");
}
Map<String, URL> connect = new HashMap<String, URL>();
FeatureCollection collection = null;
FeatureIterator iterator = null;
try {
connect.put("url", shpFile.toURI().toURL());
DataStore dataStore = DataStoreFinder.getDataStore(connect);
String typeName = dataStore.getTypeNames()[0];
"I want the lat, lon of every house" suggests that what you want to do is the process called geocoding. There are services you can use for that, some free (for limited uses) some not. You could start by looking at the List of geocoding systems to get an idea of where to start. I don't think you want to start by learning GIS or shapefiles, other than to extract the addresses you are trying to geocode.
You could estimate the lat/lon of each house by computing the centroid of each parcel. You could more roughly estimate the lat/lon of each house by calculating the centroid of the bounding rectangle of each parcel. Either of those would require extracting the parcel coordinates. If you are doing that for every house in Minnesota you will processing lots of data. A geocoding service would be cheaper. The Census Geocoder might help.