Hey there,
I have a GPS module in my car and it saves every 30 seconds my position and then it exports those points of the entire travel. So when I drive about 5 hours, it has about 600 waypoints stored. Now I want to show my trip in google map. One of the soulutions is to generate a .kml file and then draw a polyline inside the map. But because it stores position every 30 seconds, the line is often "off-road". Is there a way google will draw this way exactly on the road? the route() function is useless because of limit of waypoints (i think 8).
Any ideas?
I've been testing the exact same thing today and have come to the conclusion that the frequency of acquiring the co-ordinates should be a function of distance covered rather than being dependent on time. I have kept the threshold distance as 10m and have been able to resolve most of the instances of the lines going off the road.
Er just saw that this question was asked some time ago >_> maybe it will help someone anyway.
If you have enough time you could preprocess the data. Method won't work if you don't have your own server - really rough outline of my thoughts:
var path = [];
var index = 0;
function getRoute() {
thisRoute = getRoute(yourPoints[index], yourPoints[index+=10]);
index+=10;
for(each step in thisRoute)
path.append(step);
if (index < yourPoints.length)
setTimeout(getRoute(), 1000); // or however long it takes for you to be able to get directions again
else
store path in local file which is used later on when you need the full path
}
So to do this you need some way to store the path - I would use my own server and PHP, or there may be other ways that I'm not aware of. When I want to show the path I would retrieve it again using PHP, then draw it with polylines. There are examples around the place for the path.append(step). I'm sure there are better ways to do it (maybe python rather than JS) but this is the general approach I would take.
Related
I'd like to limit the number of markers that appear on the map in the right hand panel to something like 10 at any zoom level.
How can this be achieved?
The library can and examples can be found here:
http://storelocator.googlecode.com/git/index.html
I am following the code example given here:
http://storelocator.googlecode.com/git/examples/panel.html
There is a code reference here:
http://storelocator.googlecode.com/git/reference.html
But it's still not clear to me exactly how I can customise the example I am following so that it only shows a maximum of 10 markers at any one time.
EDIT : Why I want to do this
I sell a product wholesale to many salons. With this map I am trying to show customers which salons they can go to buy the products I supply.
However in the example given by google, the full list of salons appear as markers on the map. This is not good because it is then possible for competitors to glean an entire list of salons that they can market competing products to.
The solution I'd like would be to only show a maximum of 10 markers at a time according whichever is closest to the inputted address.
For me the example( http://storelocator.googlecode.com/git/examples/panel.html ) always show only up to 10 entries in the panel. There is a hardcoded limit of 10 , so it's not possible to achieve it without modifying the store-locator.min.js
But when you wan't to display less than the 10 entries, it would be possible via CSS:
/* limit the displayed entries to 5 */
.store-list li:nth-child(n+6){display:none}
When you want to apply a higher limit(or when it should be compatible with IE<9) edit this part in store-locator.min.js(line 28)
m=e.min(10,c[E]);
(set the 10 to the desired value)
To limit the number of results at all edit this line in MedicareDataSource.prototype.parse_
for (var i = 1, row; row = rows[i]; i++)
and set it to
for (var i = 1, row; row = rows[i],i<XXX; i++)
(where XXX is the limit +1, so e.g. setting XXX to 11 will apply a limit of 10)
There's a few general approaches, and the better solution depends a bit on your total number of stores you have, and how hard you want to make it for someone to scrape.
You could continue to use the static data feed like in this example (which means sending all stores to the browser on load), and then add some logic to only display the closest 10 (such as setting the map to null for all markers that aren't also shown in the panel), but this is not a good solution if:
there are lots of stores (more than a thousand or so) since it will be unnecessarily slow to load them all when only displaying a few.
you don't want someone to look at your code and just grab the full CSV you're sending down the wire with all your data.
Given your scraping concern, a better method is probably to implement the store locator using a dynamic datasource that only returns the closest N records for a given lat/lng so you don't expose the entire thing at once. Using Google services you could use Maps Engine which has an API, and the store locator includes a Google Maps Engine example you could start with. Your security concern here is if these queries are publicly available for anyone to hit directly, the table is also public and then someone could query for the full table. So you'd want to put a proxy inbetween to avoid that type of query hack (although of course someone could just feed you lots of locations to eventually get all your stores if they really wanted).
Other options (again just looking at Google's stack although there are lots of alternatives for this kind of thing, like CartoDB and many more) include AppEngine's Search API which also returns the N closest items (but would require some server side coding which Maps Engine would not), or even put the data into Google spreadsheets and implement a basic Script -> Web Service, where your script takes the lat/lng and do some basic math to find the closest.
Again if you don't love the server side aspect then Maps Engine is probably your best bet for a quick start especially given there's a working sample in the storelocator code.
i would like to know if it's possible to make a navigation function that, before creating the path, check through an array of "indesiderate" points and, if the best way touch one of these, try to find an alternative path.
for example, if i have a busy street (from my database, not using traffic service), i took an array of point along all the street (at any switch of course), and i want to avoid these points (=this street)
i made this sort of list of points, but i cannot find a way to find alternatives in path computing
i saw in the gmaps api documentation that the avoid command alredy exist, but can be used only to avoid tolls or highway, but i cannot find a cord-avoid command
thanks
Not available at present. Vote (star) the enhancement request:
https://code.google.com/p/gmaps-api-issues/issues/detail?id=214
My webpage displays runtime generated FusionTables data on a Google Map.
The problem is: when you create a FusionTable with geometry type column and display it for the first time, Google has to load all related map tiles in its server side cache. This takes a while - sometimes 2-3 sec, sometimes 15 -20 sec.
During caching, the map should display a grey overlay saying "Data may still be loading...". I'd like to avoid this screen, because it's very buggy. Sometimes the overlay is displayed, sometimes not.
I'm looking for a way to detect if all map tiles cached so that i can display the map to the user.
I already tried to refresh the map tiles periodically, but this will give me no feedback when to stop refreshing:
$("img[src*='googleapis']").each(function(){
$(this).attr("src",$(this).attr("src")+"&"+(new Date()).getTime());
});
For this reason I'm looking for other solutions.
Try simplifying your geographic data. The message appears when the server-side process misses a deadline for serving the map tile in a reasonable time. By reducing the complexity of the polygons, you're much more likely to not see the "Data may still be loading...." message tiles.
You can reduce the complexity in two ways: reduce the number of vertices (points) that define the polygons, and reduce the precision of the lat/long locations.
Please also note as an FYI that as the exact same map gets called again and again by different viewers, the process results are cached server-side and the message becomes much less likely to appear, and then usually due to public cacheing.
-Rebecca
Answering my own question: simply there's no way to do it as of now.
As a sidenote: I'd never advise anyone to think about using FusionTables to display dynamically generated geographic data. It's not designed that way. Only use FT if you have a somewhat static dataset that changes rarely.
I am trying to get the distance traveled on a transit route -- particularly San Francisco MUNI, but the standards NextBus, GTFS, and Google Maps API appear to be universal. I'm comfortable using any of these APIs, I'm just not sure how to go about this problem.
The easy way - ask Google Maps (this using webservices, but there is also the javascript API):
http://maps.googleapis.com/maps/api/directions/json?origin=37.7954199,-122.397&destination=37.7873299,-122.44691&sensor=false&mode=transit&departure_time=1348109609&alternatives=true
this JSON includes distance traveled, but there are two issues:
Google does not allow you to use this data unless you're displaying a map, which I don't want to do
I would need to ensure that the distance returned is for the correct route/line, since it can/will give multiple routing options. This is probably doable but would require more logic.
EDIT: using alternatives=true (or provideRouteAlternatives: true using the javascript API) only returns a maximum of 3 routes, which here in SF often doesn't include the route I'm looking for (other transit agencies, multiple lines on the same route, etc). So this isn't such a great option.
NextBus:
example route config:
http://webservices.nextbus.com/service/publicXMLFeed?command=routeConfig&a=sf-muni&r=1
The coordinates for each stop are given, but connecting the dots on those is not the same as the route taken -- it will cut corners, etc, and I need this to be accurate. The actual route taken is given under <path>/<point>, but I don't see any obvious correlation between stop and path coordinates. Plus, NextBus says in their documentation (p.10 near the bottom) that you should NOT connect points between <path> segments, they're only meant for drawing on a map and can overlap.
GTFS:
The GTFS data also separates stop and "shape" coordinates (like NextBus paths). Unfortunately, the coordinates are slightly different for the same stops between NextBus and GTFS (rounding), though the stop ID/tags are the same. Also, the data files are in the megabytes, and I need to use this for a mobile app. I suppose I could put all the data in a database and query that, but that still leaves figuring out how to correlate the stops with the shape. The "shapes_distance_traveled" column in the shapes.txt file is especially promising. MUNI chooses to leave the optional "shapes_distance_traveled" field out of stop_times.txt, though.
Any advice would be appreciated, I understand this seems like an epic task to get a simple value. Maybe I'll just throw a map in to legitimately use the distance :)
Instead of using Google Maps, I would look into the un-encumbered licensing of OpenStreetMap. There are multiple
routing engines that can use OSM data. Personally, I would use routing in PostGIS or SQLite, but depending on your skillset you might choose another.
You've clearly done your research, (+1), and as you said, the easy way is to ask Google. If it is worth for you then you might want to look into purchasing a business licence to use the Google Maps API, and negotiate with them about the requirement of displaying a map. That's the only legal way I can think of with the Google API. Alternatively, you can try building you own routing engine with data from the TIGER data set, which is freely available from the US Census Bureau, but again, as you said, it may seem like an epic task. :-)
I am looking for advice for an application I am developing that uses Google Map.
Summary:
A user has a list of criteria for searching a street segment that fulfills the criteria. The street segments will be colored with 3 colors for showing those below average, average and over average. Then the user clicks on the street segment to see an information window showing the properties of that specific segment hiding those not selected until he/she closes the window and other polyline becomes visible again. This looks quite like the Monopoly City Streets game Hasbro made some month ago the difference being I do not use Flash, I can’t use Open Street Map because it doesn’t list street segment (if it does the IDs won’t be the same anyway) and I do not have to show Google sketch building over.
Information:
I have a database of street segments with IDs, polyline points and centroid.
The database has 6,000,000 street segment records in it. To narrow the generated data a bit we focus on city. The largest city we must show has 250,000 street segments. This means 250,000 line segment polyline to show.
Our longest polyline uses 9600 characters which is stored in two 8000 varchar columns in SQL Server 2008.
We need to use the API v3 because it is faster than the API v2 and the application will be ported to iPhone. For now it's an ASP.NET 3.5 with SQl Server 2008 application.
Performance is a priority.
Problems:
Most of the demo projects that do this are made with API v2. So besides tutorial on the Google API v3 reference page I have nothing to compare performance or technology use to achieve my goal.
There is no available .NET wrapper for the API v3 yet.
Generating a 250,000 line segment polyline creates a heavy file which takes time to transfer and parse. (I have found a demo of one polyline of 390,000 points. I think the encoder would be far less efficient with more polylines with less points since there will be less rounding.)
Since streets segments are shown based on criteria, polylines must be dynamically created and cache can't be used.
Some thoughts:
KML/KMZ:
Pros:
Since it is a standard we can easily load Bing maps, Yahoo! maps, Google maps, Google Earth, with the same KML file. The data generation would be the same.
Cons:
LineString in KML cannot be encoded polyline like the Google map API can handle. So it would probably be bigger and slower to display. Zipping the file at the size it will take more processing time and require the client side to uncompress the data and I am not quite sure with 250,000 data how an iPhone would handle this and how a server would handle 40 users browsing at the same time.
JavaScript file:
Pros:
JavaScript file can have encoded polyline and would significantly reduce the file to transfer.
Cons:
Have to create my own stripped version of API v3 to add overlays, create polyline, etc. It is more complex than just create a KML file and point to the source.
GeoRSS:
This option isn't adapted for my needs I think, but I could be wrong.
MapServer:
I saw some post suggesting using MapServer to generate overlays. Not quite sure for the connection with our database and the performance it would give. Plus it requires a plugin for generating KML. It seems to me that it wouldn't allow me to do better than creating my own KML or JavaScript file. Maintenance would be simpler without.
Monopoly City Streets:
The game is now over, but for those who know what I am talking about Monopoly City Streets was showing at max zoom level only the streets that the centroid was inside the Bounds of the window. Moving the map was sending request to the server for the new streets to show. While I think this was ingenious, I have no idea how to implement something similar. The only thing I thought about was to compare if the long was inside the bound of map area X and same with Y. While this could improve performance significantly at high zoom level, this would give nothing when showing a whole city.
Clustering:
While cluster is awesome for marker, it seems we cannot cluster polylines. I would have liked something like MarkerClusterer for polylines and be able to cluster by my 3 polyline colors. This will probably stay as a “would have been freaking awesome but forget it”.
Arrow:
I will have in a future version to show a direction for the polyline and will have to show an arrow at the centroid. Loading an image or marker will only double my data so creating a custom overlay will probably be my only option. I have found that demo for something similar I would like to achieve. Unfortunately, the demo is very slow, but I only wish to show 1 arrow per polyline and not multiple like the demo. This functionality will depend on the format of data since I don't think KML support custom overlays.
Criteria:
While the application is done with ASP.NET 3.5, the port to the iPhone won't use the web to show the application and be limited in screen size for selecting the criteria. This is why I was more orienting on a service or page generating the file based on criteria passed in parameters. The service would than generate the file I need to display the polylines on the map. I could also create an aspx page that does this. The aspx page is more documented than the service way. There should be a reason.
Questions:
Should I create a web service to returns the street segments file or create an aspx page that return the file?
Should I create a JavaScript file with encoded polyline or a KML with longitude/latitude based on the fact that maximum longitude/latitude polyline have 9600 characters and I have to render maximum 250,000 line segment polyline. Or should I go with a MapServer that generate the overlay?
Will I be able to display simple arrow on the polyline on the next version.
In case of KML generation is it faster to create the file with XDocument, XmlDocument, XmlWriter and this manually or just serialize the street segment in the stream?
This is more a brainstorming Stack Overflow question than an actual code problem. Any answer helping narrow the possibilities is as good as someone having all the knowledge to point me out a better choice.
Large numbers of short GPolylines run massively slower than small numbers of long GPolylines.
The speed difference between Google Maps v2 and Google Maps v3 is not going to be significant, because most of the CPU time will be taken up by the actual graphics system of the browser. Google Maps uses the VML, SVG or Canvas graphics systems, depending on the browser. Of these, VML is by far the slowest, and that gets used whenever the browser is MSIE.
Before embarking on tackling 250,000 line segments, I suggest you take a look at this quick speed test of 200 random polylines. Try zooming and paning that map in MSIE.
Then, also consider the amount of data that needs to be sent from the server to the client to specify 250,000 line segments. The amount of data will vary depending on whether you choose KML or JSON or GeoRSS, but if you end up with 20 bytes per line segment that would take 50 seconds to fetch on a 1 megabit broadband connection. Consider whether your users would be prepared to sit around for 50 seconds.
The only solution that really makes sense is to do what Google do for their traffic overlay, and draw the lines onto tiles in the server, and have those tiles be displayed as a GTileLayerOverlay in the client.
What you need is a spatially aware database, and a server-side graphics library like gd or ImageMagik. The client asks for a tile from the server. If the zoom is above a certain level the server scans the database for line segments that have bounding boxes that overlap the bounding box of the requested tile and use the graphics library to draw them.
The zoom level limit is there to limit the amount of work that your database and server needs to do. You don't want to end up drawing 250,000 line segments onto a single zoomed out tile because that's an awful lot of hard work for the server, and isn't going to mean very much to the user.
Regarding click handling:
The easy thing to do is to listen for clicks on the map, rather than on the objects, and send the click details to a server. The server then uses the click location to search the spatially aware database and returns the details of the clicked object if there is one. The client code does this:
GEvent.addListener(map,"click",function(overlay,point) {
var url="clickserver.php?lat=" + point.lat() + "&lng=" +point.lng();
GDownloadUrl(url, function(html) {
if (html.length) {
map.openInfoWindow(html)
}
});
});
The harder thing to do is to handle the changing of the cursor when the pointer is over the polylines. There's a known technique for doing cursor changes for small markers, which works like this:
Whenever a tile is fetched, the .getTileUrl() also makes a call to a server that returns a list of hotspot boxes for that tile. As the mouse moves, the client constantly calculates which tile the mouse is over, and then scans the corresponding list of hotspot boxes.
Google themselves, in their GLayer() code, add the sophistication of performing a quadtree search to speed up the search for hotspots within a tile, but other people who have implemented this strategy in their own code reckon that's not necessary, and a linear scan of the hotspot list is fast enough.
I've no idea how to extend that to handling cursor over polyline detection.