Google map markers appearing on wrong location on the map - javascript

I have been working on an android application featuring google maps, I am requesting for coordinates to a node js server and the response is then parsed to double type and when passed to an object of Marker the marker appears on an inaccurate location, I have copied the coordinates from the database and when I pass them direct to the Marker's object, the marker appears on the right location, I also have an alert box displaying the value of the markers as I receive them from the serve and it seems to be displaying the right coordinates, what I think is there is some garbage value with in the variables to which I assign the coordinates or it can be an issue in parsing while i get them in the form of JSON from the server and parse them to double
I have done a little search but I couldn't find a solution specifically addressing my issue, if I haven't been thorough I am sorry, thank you all in advance for your help.
Here is the code:
The code when I receive the coordinates and parse them (via socketIO):
public void on(String functionName, IOAcknowledge ioAck, Object... arguments) {
if("points_of_interest".equals(functionName)){
temp=arguments[0].toString();
try {
JSONObject object=new JSONObject(temp);
String idStop=object.getString("route_id");
String longt=object.getString("stop_longg");
String lat=object.getString("stop_lat");
lati=Double.parseDouble(lat);
lngi=Double.parseDouble(longt);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Now here is the function call that creates the markers in the onCreate method:
map=((MapFragment) getFragmentManager().findFragmentById(R.id.allBusMaps)).getMap();
createStops();
Here is the code for createStops() method:
public void createStops(){
map.clear();
// LatLng lhr=new LatLng(31.500794,74.316777);
LatLng lhr=new LatLng(lati,lngi);
Marker lahore = map.addMarker(new MarkerOptions().position(lhr).title("busStop"));
map.moveCamera(CameraUpdateFactory.newLatLngZoom(lhr, 15));
}
In the above mentioned case case when I am passing the value through variables this is the output being generated:
But when I pass the values direct to the Marker's object the marker appears on the right locations:
e.g. LatLng lhr=new LatLng(31.500794,74.316777);

I have found the solution to the above problem i was having on repeated debugging,
the problem i noticed was that lati and lngi objects were not getting their respective values for a specified time interval, until which both of these objects remained to an initial value of 0.0 and 0.0 respectively hence on majority of test attempts the marker was not appearing at the accurate location.
To overcome this problem, i have enforced a wait of 500 milliseconds before i call the createStops method, that gives the lati and lngi objects sufficient time to attain their respective values from the server.
Here is what worked for me:
map=((MapFragment) getFragmentManager().findFragmentById(R.id.allBusMaps)).getMap();
//new pointMarker().execute();
try {
Thread.sleep(500); //a wait of 500 milliseconds
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
createStops(); // this is the method that creates the markers
Thank you everyone for your help.

Related

Why does large eojson not get displayed on Here Map?

I'm trying to parse and display a geojson representation of the UK postcode districts on a Here Map using the JavaScript API within a VueJs application.
The code is relatively simple - districtGeojson is the JSON document. The following function is called after the map has been initialised and displayed:
processGeojson() {
const reader = new H.data.geojson.Reader(districtGeojson, {
disableLegacyMode: true
});
reader.parse();
const layer = reader.getLayer();
this.shapes = layer;
console.log(layer.isValid(7));
try {
this.map.addLayer(layer);
} catch (err) {
console.log('err adding layer', err);
}
}
As you can see, there's a console.log() in there to do some kind of checking on the layer's validity at the default zoom level and it returns true.
All I see is the map flicker briefly and then the plain map is shown. Is there a way to get some feedback from the API on what is going wrong, it seems to just fail silently - addLayer throws no exception?
If necessary, I can share the JSON document but as it's large (5Mb) I wanted to see if there was anything obviously wrong with this code first.
So, it appears there may be an error in the documentation here: https://developer.here.com/documentation/maps/3.1.17.0/api_reference/H.data.geojson.Reader.html#getLayer
which states:
var reader = new H.data.geojson.Reader('/path/to/geojson/file.json');
reader.parse();
// Assumption: map already exists
map.addLayer(reader.getLayer());
Whereas what just worked for me was to call parseData() rather than parse(), passing the source data. I can do:
var reader = new H.data.geojson.Reader('');
reader.parseData(districtGeojson);
// Assumption: map already exists
map.addLayer(reader.getLayer());
But not
var reader = new H.data.geojson.Reader('./Districts.json');
reader.parse();
// Assumption: map already exists
map.addLayer(reader.getLayer());
Which begs the question of why the file path is required in the constructor as I cannot get the reader to parse data that is passed as a path in the constructor.

Leaflet: how to swap coordinates received from an ajax call

I am using Leaflet 1.0.3 and a few plugins including Leaflet.ajax. My L.geo.ajax call is working and returning geojson objects, however, the coordinates are reversed. I created a function to fix this:
var convertLatLng = function (latlng) {
var temp = latlng[y];
latlng[y] = latlng[x];
latlng[x] = temp;
convertedLatLng = latlng;
return convertedLatLng;
console.log('this function is running')
}
But my problem is I don't know where to put it. Do I run it inside my geoJson call? If so, where? Here is a snippet of the ajax call:
var geojson = L.geoJson.ajax('http://www.iotwf.com/deployment_map/json', {
pointToLayer: function (feature, latlng) {
convertLatLng(latlng);
...
},
onEachFeature: function(feature, layer) {
...
}
});
I am also open to other suggestions for what may fix it.
Welcome to SO!
First make sure that your coordinates are indeed reversed.
Note that the GeoJSON format expects [longitude, latitude], whereas Leaflet usually expects [latitude, longitude], EXCEPT in the case of L.geoJSON() factory (and the plugin L.geoJson.ajax()), where it automatically reads the GeoJSON order and builds the layers at the correct coordinates.
If your coordinates are still reversed, the appropriate correction would be obviously to correct the order in your data source directly (or whatever service outputs your data), so that you get actually compliant GeoJSON data. That would solve many future headaches.
If that is not possible, then indeed you could try a workaround within your script.
The most appropriate way to do so would probably be to use the coordsToLatLng option of the L.geoJSON factory.
Changing its default implementation, you would get something like:
L.geoJson.ajax(url, {
coordsToLatLng: function (coords) {
// latitude , longitude, altitude
//return new L.LatLng(coords[1], coords[0], coords[2]); //Normal behavior
return new L.LatLng(coords[0], coords[1], coords[2]);
}
});

How Can I animate Bing map pushpins based on a live GPS feed

I have looked over the bing maps documentation trying to find an answer to my question. I would prefer to do everything using the bing maps api and not have to add a third party library if possible.
Question: How can I animate a pushpin to make a smooth transition from one set of gps coordinate(longitude/latitude) to another in order to simulate smooth movement of a Pushpin on Bing maps?
Question: can deleting an entire object out of the map.entities array waste enough resources to cause performance issues? If so how can I change the pushpin latitude and longitude properties without deleting the entire object?
Sample code of trying to change the pushpins properties without deleting the object out of the array. This code does not work… I am unsure why it is not working?
map.entities.get(theIndexOfThePushPin)._location.latitude = newLat;
map.entities.get(theIndexOfThePushPin)._location.longitude = newLon;
I create a pushpin like so - This works fine
map.entities.push(new Microsoft.Maps.Pushpin(new Microsoft.Maps.Location(lat, lon), {
text: text,
visible: true,
textOffset: new Microsoft.Maps.Point(0, 5)
}));
Pseudo code for my recursive angular $http call
function BusMoveGPSRefresh() {
$http.get(resourceURL)
.then(function (data) {
if ('if pushpins have not been created') {
//create pushpins...
}
} else {
//delete pushpins out of the array and then recreate them
//with updated lon/lat. Or just update existing objects lon/lat properties if possible?
}
}
BusMoveGPSRefresh();//after everything is done then go get more info and start again. recursion...
}, function (reason) {// if fail than do
console.log(reason);
console.log("This Is not Working!!! Dang!!");
});
}
Any insight into the problem would be greatly appreciated! Thanks!
I could not find a simple answer for adding animation. I did find a site that gave a step by step tutorial on a more in-depth answer on how to animate pushpins.
Answer: 1 -- tutorial on how to animate bing map pushpins
https://blogs.bing.com/maps/2014/08/07/bring-your-maps-to-life-creating-animations-with-bing-maps-javascript/
Answer: 2 -- this is how to update the pushpin location without deleting the pushpin object out of the entities array.
Instead of deleting the entire pushpin object find the pushpin index and then use the property "setLocation()" and then add a new location.
//check to make sure that the lat and lon have
//changed if it is still the same location do nothing. else update
if (map.entities.get(indexOfPushpin).getLocation().latitude != lat
|| map.entities.get(indexOfPushpin).getLocation().longitude != lon) {
map.entities.get(indexOfPushpin).setLocation(new Microsoft.Maps.Location(lat, lon));
}

Need to redraw a map with new data (in conjunction with CartoDB.js)

I seem to be having some trouble with reinitializing a Leaflet map object. I am running an init() function that starts by initializing a map, adding a tilelayer and layer with polygons, and then adding sublayers which color the polygons according to a ST_Intersects query. The issue is that this function is tied to an AJAX call that is caused by a click event but does not update the data according to the new parameters sent to the map. I don't think I am explaining this very well, so here is a bit of my code:
success: function(data) {
init(data);
}
function init(data){
// initiate leaflet map
alert("start");
var map = L.map('cartodb-map').setView([40.750028, -73.926768], 11);
alert("map made");
//create sublayers, etc
}
What happens is that the first time init is run, both 'start' and 'map made' alerts work, and the map is made according to the data. Any further calls to init simply alerts with "start" and "map made" is never alerted so I believe the problem is with reinitializing the leaflet map. What should I do to fix this?
Not sure the problem without seeing more of your code, but you could try calling map.remove(); the second time around. So:
if (map) {
map.remove();
// add in new map initialization here
} else {
var map = ...
}

Google Maps ClusterManager on API V3 not working on reload / initial load

I am trying to use the Google Maps V3 API ClusterManager from http://cm.qfox.nl/ to cluster together markers on a map, but I'm hitting the same error in my code as in the original web site - an error when the page is loaded the first time, or reloaded:
Uncaught TypeError: Cannot call method 'fromLatLngToPoint' of undefined ClusterManager_v3.js:586
ClusterManager.latlngToPoint ClusterManager_v3.js:586
ClusterManager._getMarkerBounds ClusterManager_v3.js:645
ClusterManager._cacheMarkerIcon ClusterManager_v3.js:580
ClusterManager.update ClusterManager_v3.js:345
(anonymous function) ClusterManager_v3.js:91
It works fine after the initial load, so I'm fairly sure it's because of a timing issue - e.g., the map or marker isn't initialized before it being used. Unfortunately, I can't figure out a way to wait for everything to initialize because Javascript isn't my first language. Any help or pointers would be most welcome. The source from the web site is the code I'm using almost exactly.
UPDATE:
If found that changing the line:
cm._requestUpdate(50);
to
cm._requestUpdate(250);
Prevented the error. Changing it to 150 resulted in the error occurring 3/10 times. I'm not entirely sure this is a fix, but it maybe so I'm leaving this posted just in case anyone else has a better solution or wants to know mine.
For using Projection methods , it must be initialized. Map will trigger "projection_changed" event, when Projection will be created.Only after that you can use map.getProjection(). So my suggestion is, to add "projection_changed" event's listener, and initialize ClusterManager when it is called:
google.maps.event.addListenerOnce(map, 'projection_changed', function(){
var cm = window.cm = new ClusterManager(
map,
{
objClusterIcon: new google.maps.MarkerImage('markers/cluster.png', false, false, false, new google.maps.Size(20,20)),
objClusterImageSize: new google.maps.Size(20,20)
}
);
// now json contains a list of marker positions. lets add them.
for (var i = 0; i < json.length; ++i) {
.....
}
cm._requestUpdate(50);
});

Categories