I'm trying to understand the wikitude examples. When I run the example app on my phone, and try one of the POI examples, it loads the poi's into the camera view. However, they always stay relative to me. As I walk around, I can never walk past one, and it appears to always be say 5m away from me. How does one update the wikitide examples so that it shows an absolute geolocation that you can walk around and explore? This seems really simple, but none of the examples online seem relevant to answering this. I have extensively searched the wikitude example docs.
Here is an excerpt from the bottom of the poiatlocation.js file in the architect view -
should I be looking at the js file in the architect world, or in the java code?
locationChanged: function locationChangedFn(lat, lon, alt, acc) {
// request data if not already present
if (!World.initiallyLoadedData) {
var poiData = {
"id": 1,
"longitude": (lon + (Math.random() / 5 - 0.1)),
"latitude": (lat + (Math.random() / 5 - 0.1)),
"altitude": 100.0
};
World.loadPoisFromJsonData(poiData);
World.initiallyLoadedData = true;
}
},
};
/* forward locationChanges to custom function */
AR.context.onLocationChanged = World.locationChanged;
The provided sample implementation creates dummy poi data in the user's vicinity on first location update.
The POIs may be some km away from the user, you can use "lon + 0.001" and "lat + 0.001" to create a closer ones.
Also note, that GPS and Network positioning are usually not very accurate and the sample application uses a very basic "Location Strategy" on Android and the default Location Strategy on iOS - So don't expect in-house movements to cause POI-location changes.
Once you try it outdoors with POIs nearby you will notice the location change effect.
Kind regards
PS.:
In case you want to use a more accurate Location Strategy, please have a look at
http://developer.android.com/guide/topics/location/strategies.html
and overwrite the setLocation implementation of the ARchitectView.
Note: Every architectView.setLocation() in the native environment will also cause a "AR.context.onLocationChanged"-JS-function call.
Related
I'm trying to compare the coordinates from an event in my database to those sent by the user from their client API (after approving) but cannot figure how to properly setup the compare. Right now, the user coordinates are just logging in the terminal:
Here's my script under guestValidate.js:
if(confirm('Compare wants to use your current location to briefly checkin. Do you approve?')) {
navigator.geolocation.getCurrentPosition(function (position) {
console.log(position.coords.latitude)
console.log(position.coords.longitude)
})
} else {
console.log("The Locator was denied.");
}
console.log(eventCoords)
Here's the page where I'm running the ejs:
<% layout('layouts/boilerplate') %>
<h1>Prompt</h1>
<script>
const eventCoords = '<%- event.geometry.coordinates %>'
const eventID = '<%- event.id %>';
</script>
<script src="/javascripts/guestValidate.js"></script>
I attached the output from the terminal below. Both are working I just need to structure them as objects and compare, I think? Could somebody help me compare the two sets of coordinates, please?
If they're equal, I want to send a "true" back to the database route.
One way to do this, if the venue is either relatively small, or not strangely shaped, is to just choose the lat/long in the center of the location and allow a radius that you deem reasonable from that point. You will likely want some amount of room for location inaccuracies, since user location services can be unreliable at times. This is especially common when indoors in concrete buildings.
You could just use the Haversine formula, but since the earth isn't actually a sphere, and you are trying to check in at what I assume to be relatively small locations, haversine's potential errors with a sphere make using it a bad idea. (Error could be up to 0.3%, which doesn't sound bad, but the earth is pretty big, so that means up to 20km of error).
Instead I'd recommend a cool library offered by Chris Veness at https://github.com/chrisveness/geodesy
If you are interested, there's a full explanation of the math behind this library for your usage here: https://www.movable-type.co.uk/scripts/latlong-vincenty.html.
In your case, if you wanted to do this comparison in the browser, the usage would look something like this:
<script src="https://cdn.jsdelivr.net/npm/geodesy#2.2.1/latlon-ellipsoidal-vincenty.js"></script>
<script type="module">
import LatLon from 'https://cdn.jsdelivr.net/npm/geodesy#2.2.1/latlon-ellipsoidal-vincenty.js';
function getDistanceBetweenPoints(user, venue) {
const p1 = new LatLon(user.lat, user.lon);
const p2 = new LatLon(venue.lat, venue.lon);
return p1.distanceTo(p2);
}
let user = { lat: 30.2696082, lon: -97.7521805 };
let venue = { lat: 30.2699360, lon: -97.7485410 };
console.log(`Distance between user and venue is ${getDistanceBetweenPoints(user, venue)} meters`);
</script>
This example using your coordinates provided above results in a distance of roughly 352 meters between the user and the venue. Now, depending on whether the user was considered to actually be at the venue when those coordinates were captured, this might be quite accurate, or show you the user device inaccuracies I mentioned before.
One more thing, users can technically spoof their locations, so I wouldn't recommend using this for anything security related.
function initPano() {
// Set up Street View and initially set it visible. Register the
// custom panorama provider function. Set the StreetView to display
// the custom panorama 'reception' which we check for below.
var panorama = new google.maps.StreetViewPanorama(
document.getElementById('map'), {
pano: 'reception',
visible: true,
panoProvider: getCustomPanorama
});
}
// Return a pano image given the panoID.
function getCustomPanoramaTileUrl(pano, zoom, tileX, tileY) {
// Note: robust custom panorama methods would require tiled pano data.
// Here we're just using a single tile, set to the tile size and equal
// to the pano "world" size.
return 'http://bestofdiscus.gr/portals/0/Discus-Header-WR.jpg';
}
function getCustomPanorama(pano, zoom, tileX, tileY) {
if (pano === 'reception') {
return {
location: {
pano: 'reception',
description: 'Google Sydney - Reception'
},
links: [],
// The text for the copyright control.
copyright: 'Imagery (c) 2010 Google',
// The definition of the tiles for this panorama.
tiles: {
tileSize: new google.maps.Size(1024, 512),
worldSize: new google.maps.Size(1024, 512),
centerHeading: 105,
getTileUrl: getCustomPanoramaTileUrl
}
};
}
}
In this block of code, i don't understand the parameters :pano, zoom, tileX, tileY in the function getCustomPanoramaTileUrl. I understand that, without using these parameter, the function will return an url of image.
my question is:
1/What do these parameters use for and how to use it ?
2/What is a pano ID (i have been searching for it a lot but still can not understand)
What are you talking about?
You may be thinking, "why is my question downvoted?" (PS: I didn't do it!). When asking a question, slapping random code with no context whatsoever will leave anyone trying to help you just as lost as you.
Though the code is useful, your question is missing important information:
What technologies are you using? Any APIs?
What have you tried?
Where is that code from?
Any links to any documentation? What is the context?
Before making a question, always make sure to read the following page https://stackoverflow.com/help/how-to-ask
Your code, where does it come from?
After doing some digging and some research I was able to find that your code is actually a piece of code from the Google Documentation, Custom Street View panoramas.
With this in mind Google has some documentation on the matter that will help you understand what is going on with your code:
https://developers.google.com/maps/documentation/javascript/streetview#TilingPanoramas
I read the documentation, but I still don't get it!
Although Google talks about Custom Panoramas with multiple views, the example provided is too simple to illustrate the full potential of the resources Google provides you.
Now, regarding your specific question...
What are pano, zoom, tileX, tileY used for?
In the code example that you provided, they are used for... nothing. You could literally remove them from getCustomPanoramaTileUrl and the code would still work.
So, what are they used for? Well, according to the References Documentation for StreetView, these parameters have the following objective:
Gets the tile image URL for the specified tile. pano is the panorama
ID of the Street View tile. tileZoom is the zoom level of the tile.
tileX is the x-coordinate of the tile. tileY is the y-coordinate of
the tile. Returns the URL for the tile image.
Now, if this is still, confusing, I will try to explain.
Custom panoramas are sets of images, put together, like in the image bellow:
When using a real panoramic view, you want to pass a set of images, and the StreetView object needs to know which set of images you are referring to (panoId), at which zoom level (zoom) and inside the set, the X and Y positions of the image you are currently seeing (tileX and tileY).
In the example you provided, since it is extremely simple, none of this is used because you always return the same image no matter what. But in a more complex example, that uses a set of images, this information would be crucial to let the StreetView know where you are looking at in order to display the correct image.
Hope it helps!
I'm developing HTML5 web-app for iPad that uses Google Maps API. This API is new for me, I have searched answers for many questions related to it. Markers, info windows, routes, geolocation, street view. The most useful information about that all was found in official documentation:
https://developers.google.com/maps/documentation/javascript/3.exp/reference?hl=ru
However, I still cannot find a solution to one (maybe, simple) problem. For example, I've created a new map instance and one marker (destination), started watching for my position (GEO Location) and drew a route to the location of this marker. How can I check when I will reach the destination? I've looked for appropriate events of DirectionsService, DirectionsRenderer and etc. but with no results. Also, I found the same topic on this website, but it is about Android development, not JS (Android: How to check that whether i reach/near my Destination?).
Being hopeless, I invented my own solution, but it seems not to work properly (I have not fully tested it yet, I'll do it in the next few days). I thought if I would compare lat&lng of my current position with lat&lng of destination - then I could catch the moment when destination is reached:
if (myPosition.lat() == dest.marker.position.lat() && myPosition.lng() == dest.marker.position.lng()) {
alert('You have arrived!');
}
This code executes in successful watch position callback of navigator.geolocation.watchPosition
Do you have any ideas?
LatLng's are values with a high accuracy, you can't expect that the positions of boths markers will match exactly.
Add a tolerance:
//tolerance 50 meters
//requires the geometry-library
if(google.maps.geometry.spherical
.computeDistanceBetween(myPosition,dest.marker.position)<50){
alert('You have arrived!');
}
I don't think it's a good idea to make a home made solution, since maps API can do quit everything.
Using Google Maps API to get travel time data
For Android Studio users:
Get object of currentLocation and destinationLocation
Location currentLocation; // use fusedLocationProviderService
Location destinationLocation = new Location(""); // set Lat and Long
destinationLocation.setLatitude(122.1234123); // like this
if (location.distanceTo(new Location("")) < 30) { // meters
Toast.makeText(MainActivity.this, "Toast you have reached",
Toast.LENGTH_SHORT).show();
}
First: I try to remake a Website called regionalkarten.com
It's a German publisher of Maps. This page uses the Google API v2 to show our custom maps.
My Job is to update the Page to API v3.
Now I found the jQuery GoMap Plugin and I try to use it, but it doesn't seem to support custom maps.
I tried to define a Overly with the custom Map
var ehsTypeBOptions =
{
getTileUrl: function(coord, zoom)
{
var x = coord.x;
var y = coord.y;
return "http://regionalkarten.com/_map/ehs_village_maps/is_maps/z"+zoom+"/"+coord.y+"/"+coord.x+".png";
},
tileSize: new google.maps.Size(256, 256),
};
and load it into the map with:
map.overlayMapTypes.insertAt(0, new google.maps.ImageMapType(ehsTypeBOptions));
That works fine without GoMap. So I tried:
$.goMap.overlayMapTypes.insertAt(0, new google.maps.ImageMapType(ehsTypeBOptions));
and guess what, it didn't work :(
GoMaps Webpage and Google aren't very helpful. Keep in mind that I have to load the custom map into an overlay. I need the real google maps behind the overlay because our maps are not gapless.
I hope you got some ideas or experience with GoMap.
Thank you.
$.goMap does not return the native google.maps.Map-instance, so you can't use the Maps-API-methods there.
The google.maps.Map-instance may be accessed via $.goMap.map .
Beyond that: I would suggest not to use this library, there haven't been any updates since 1 year, and this all can be done without any additional library.
More important: before you continue working with ImageMapType, this is not the right MapType for you, because it appears that the TileServer don't serve tiles for the complete world.
When the user pans or zooms so that a area is in viewport where no tile is available, this area would be shown as a gray space. You better use a Overlay MapType and set the background-image of the overlays to the TileUrl(additionally you may use a condition that checks if a Tile is available at all to reduce unnecessary request to the tile-server)
I need good examples and best practices on program architecture.
I'm trying to build a JS UI for an app that works with Google.Maps. In the 1st draft, user should be able to draw geometric shapes on the map in a way similar to G.M. Then the shapes are sent through AJAX and the response is displayed.
Problem is that the code got complicated just with polygons editing.
Inspired by Joel's "Duct-tape Programmer", I tried to sketch a straightforward code that makes actions and switches event handlers, to avoid big if-else trees. "New poly" button creates an observer for map.onclick, changes event handlers for other buttons or hides them, and hides itself, etc.
The downside of this approach is that data handling code is mixed with interface. A code that creates a div container to display the data on the new polygon stands next to the code that deals w/ G.M or w/ the shape data. If I want to revise the UI, I'll need to process the WHOLE app.
I could review it later and move this UI-generating code elsewhere, but then came my lead programmer. He instead insisted on "messaging" approach: a simple event system where objects subscribe to events and fire them. Interface code can be perfectly isolated from data handling and talking to G.M, but now each listener has to double-check if this message is to it.
For example, clicking on a poly on a map must highlight it and start editing. But not if another poly is being drawn. So, some are-you-talking-to-ME?-code is necessary everywhere.
I'll appreciate good examples of UI architecture approaches.
The event handling idea suggested to you is a good approach.
Here's some more ideas:
Make the shape drawing thing a component
The shape drawing component sends events to other code, to react to stuff like "editing" or "clicked"
This component could also handle the editing part - It sends "clicked" event to controller, controllers tells the component to go into edit mode
While in edit mode the component would not send normal "clicked" events until the editing was closed, avoiding your problem of having to check
In general, it's a good idea to have a "view" layer which simply deals with displaying the data and sending events about user actions on that data (ie. clicks, etc.) to a "controller" layer, which then decides what to do - for example it could decide to change the view into editing mode.
I don't know if this is beside the point. But I use this as a temple for all my javascript projects.
(function () {
var window = this,
$ = jQuery,
controller,
view,
model;
controller = {
addEventForMenu : function () {
// Add event function for menu
}
};
view = {
content : {
doStuff : function () {
}
},
menu : {
openMenuItem : function () {
}
}
};
model = {
data : {
makeJson : function () {
// make json of string
},
doAjax : function () {
},
handleResponse : function () {
}
}
}
$.extend(true, $.view, view);
})();
The good thing here is that it's only the view object that is extended to the DOM, the rest is kept inside the anonymous scope.
Also in bug project i create on of these files for each part ie, map.js, content.js, editor.js
If you just mind the naming of your methods in the view object you can have as many files as you like during development. When the project is set in to a production environment I just make it one file and minify it.
..fredrik
In short publisher-subscriber paradigm works well to make geometric shapes. First make command-line which primitive is base polygon publisher publishes. Canvas object seems obvious here to paint, usual method repaint() for updating the client view (eventdriven programming normally in C you can review eg opengl or glut eventdriven graphics), combined with the so-so gmap API I too use, publisher-subscriber pattern or factory are good design patterns whatever graphics implementation. tricky gmaps specific thing is latitude and longitude switch places in the array between json and persistence layer, there's no serverside reverse geocoding yet, naming is kinda inconsistent, and for multilingua apps names both change relative user human language and are doubled (Paris in Text, Paris in France...),. Look if you like my going implementation, registers geographic names and spatial coordinated relative user with geoip worldwide
function wAdd(response){
map.clearOverlays();
if(!response||response.Status.code!=200){
}
else{
try{
place=response.Placemark[0];
point=new GLatLng(place.Point.coordinates[1],place.Point.coordinates[0]);
marker=new GMarker(point);
map.addOverlay(marker);
marker.openInfoWindowHtml('<a href="/li?lat='+place.Point.coordinates[1]+'&lon='+place.Point.coordinates[0]+'&cc='+place.AddressDetails.Country.CountryNameCode+'">'+place.AddressDetails.Country.AdministrativeArea.Locality.LocalityName+'<span id="wr2"></span> '+ nads( place.Point.coordinates[1],place.Point.coordinates[0] )+' ' +'<img src="http://geoip.wtanaka.com/flag/'+place.AddressDetails.Country.CountryNameCode.toLowerCase()+'.gif">');
}
catch(e){
try{
place=response.Placemark[0];
point=new GLatLng(place.Point.coordinates[1],place.Point.coordinates[0]);
marker=new GMarker(point);
map.addOverlay(marker);
marker.openInfoWindowHtml('<a href="/li?lat='+place.Point.coordinates[1]+'&lon='+place.Point.coordinates[0]+'&cc='+place.AddressDetails.Country.CountryNameCode+'">'+place.AddressDetails.Country.AdministrativeArea.AdministrativeAreaName+'<span id="wr2"></span> '+ nads( place.Point.coordinates[1],place.Point.coordinates[0] )+' ' +'<img src="http://geoip.wtanaka.com/flag/'+place.AddressDetails.Country.CountryNameCode.toLowerCase()+'.gif">');
}
catch(e){
try {
place=response.Placemark[0];
point=new GLatLng(place.Point.coordinates[1],place.Point.coordinates[0]);
marker=new GMarker(point);
map.addOverlay(marker);
marker.openInfoWindowHtml('<a href="/li?lat='+place.Point.coordinates[1]+'&lon='+place.Point.coordinates[0]+'&cc='+place.AddressDetails.Country.CountryNameCode+'">'+place.AddressDetails.Country.CountryName+'<span id="wr2"></span> '+ nads( place.Point.coordinates[1],place.Point.coordinates[0] )+' ' +'<img src="http://geoip.wtanaka.com/flag/'+place.AddressDetails.Country.CountryNameCode.toLowerCase()+'.gif">');
}
catch(e){
place=response.Placemark[0];
marker=new GMarker(point);
map.addOverlay(marker);
marker.openInfoWindowHtml(''+place.address+'');
}
} }
}map.addOverlay(geoXml);
}
i would recommend having few object variables containing the state (0, drawing, editing, ... any other required) - this would help you deciding whether to allow event handling or just bury it if for example drawing is done and clicking on editable polygone happens.
as for the UI - I am not sure if your question is aimed at you - developing the script or at the user as you are mixing two things here.
keep in mind that for a user everything should be as simple as possible: if he is editing, don't allow him to draw. if he is drawing, don't allow him to edit (overlapping of polygons could occur). however - allow user quickly to switch from editing (e.g. right click?) to drawing - or in other words cancel the current state.
The first thing I would do is create a service that wraps over the google API. This is so that later if you need to change mapping services (windows maps or yahoo maps). Then you can put a facade over the google service. Then you might want to put some wrappers over your service and split it up into a view(output) and model(input) and manage this with controllers/presenters. Check into Model View Controller / Model View Presenter / Presenter First / Humble Dialog on Wikipedia. It should discuss the seperation that your looking for. Also Martin Fowler web page goes into presentation patterns. You should check out my old blog ugly-lisp-code. I have references to event driven/event messaging.
If you have a one-to-one pub/sub just store an event-handler(closure/lambda/first-order-function) in the object that is going to fire the event.
If you have a one-to-many pub/sub then you will need a more complex object to store your closures.
LOL! Right now I've been looking at this same exact issue. I'm going to be writing about using a presenter-first in JavaScript on my blog. A bare bones start on presenter and model.
[edit] you might want to check out this stackoverflow question. One of the answer has a link to separating concerns into MVC. The link is on A List Apart.