I have a big problem. I am using leaflet javascript library to display openstreetmap. I would like to display a default size of 15, but its always end up showing zoom size 11. Basically, if I use map.locate function then it just displays the whole city with 30km diameter and my aim is display just 2km diameter. Interestingly, there is a way to increase the diameter(zoom size) from 12 to 10 or 8 but there is no way reducing zoom size :(
I am using map.locate to auto-locate user location on map but the zoom size is default 11 or it can be even bigger like 10,9, etc but its not possible to decrease zoom(diamter) size.
Here is my code:
function initMap() {
map = L.map('map').setView(startingLocation, 15);
map.on("locationfound", onLocationFound);
map.on("locationerror", onLocationError);
L.tileLayer('http://{s}.tile.cloudmade.com/BC9A493B41014CAABB98F0471D759707/997/256/{z}/{x}/{y}.png', {
maxZoom: 18,
attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery © CloudMade'
}).addTo(map);
}
map.locate({
setView: true,
maxZoom: 16,
enableHighAccuracy: true,
timeout: 10000
});
function onLocationFound(position) {
marker.setLatLng(position.latlng);
updateLocationWithRevGeocoding([{name: 'lat', value: position.latlng.lat}, {name: 'lon', value: position.latlng.lng}]);
}
And I am using p:remoteCommand(javascript call) for function updateLocationWithRevGeocoding to call updateLocationWithReverseGeocoding action from the backend bean.
public void updateLocationWithReverseGeocoding() throws URISyntaxException, IOException {
Map<String, String> params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
this.latitude = params.get("lat");
this.longitude = params.get("lon");
this.locationName = performReverseGeocoding(this.latitude, this.longitude);
RequestContext.getCurrentInstance().execute("updateMarkerPopup(\"" + this.locationName + "\")");
}
I see code below with zoom level 16, No matter how much i change this level, it stays the same. I just can increase diameter from 30km(Zoom size 11 to 10, 8 etc) but I am not able to decrease(diameter) zoom size :(
private String performReverseGeocoding(String lat, String lon) throws URISyntaxException, ParseException, IOException {
URIBuilder uriBuilder = new URIBuilder("http://nominatim.openstreetmap.org/reverse.php?format=json&zoom=16"); //I just removed original URL because of company proprietary.
uriBuilder.setParameter("accept-language", "de"); // TODO externalize or parametrize
uriBuilder.setParameter("lat", lat);
uriBuilder.setParameter("lon", lon);
//uriBuilder.setParameter("key", appKey);
URI uri = uriBuilder.build();
HttpGet request = new HttpGet(uri);
HttpResponse httpResponse = this.httpClient.execute(request);
Map<String, Object> jsonResponse = jsonMapper.readValue(EntityUtils.toString(httpResponse.getEntity(), "UTF-8"), Map.class);
return jsonResponse.get("display_name").toString(); // TODO find something shorter and more informative
}
I already debugged the javascript from firefox. Map zoom size automatically increases before the control enters into OnLocationFound call. I have an obligation to use map.locate, otherwise the map does not locate user to his location.
Related
I have been struggling with this piece of javascript for some time now. I have read different, and similar, posts on the subject but I can't find anything that seems to lead me in the right direction of solving my problem.
I need to call the value of the variables from the watchPosition (and getCurrentPosition) method , set them as global and then call them inside of the function initMap().
The code is working but watchPosition reloads the Google map (this appears to happen when i change the browser/switch between tabs). I can't get the global variables to catch the value from the methods below (inside updateMarker).
How do I set the values from:
mon_lat = +position.coords.latitude;
mon_long = +position.coords.longitude;
to become global?
My main question is, more or less: how can i load the script without updating function initMap()? I would like it so that the navigator.geolocation.watchPosition() method updates automatically.
$(document).ready(function() {
updateMarker();
});
var mon_lat = null;
var mon_long = null;
var start_lat = null;
var start_long = null;
function updateMarker() {
// Get positions
if (navigator.geolocation) {
// Get current position
navigator.geolocation.watchPosition(
function (position) {
mon_lat = +position.coords.latitude;
mon_long = +position.coords.longitude;
initMap(mon_lat, mon_long);
}
);
// Get starting position
navigator.geolocation.getCurrentPosition(
function (position) {
start_lat = +position.coords.latitude;
start_long = +position.coords.longitude;
initMap(start_lat, start_long);
}
);
}
}
function initMap() {
// Display the map
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: mon_lat, lng: mon_long},
zoom: 10,
mapTypeControl:false
});
}
I am loading features into Vector source utilizing the Tile strategy. I'd like implement kind of progress bar, similar to http://openlayers.org/en/master/examples/tile-load-events.html.
However, unlike VectorTile source, the Vector source doesn't trigger tile loading events which could be used for calculating desired ratio 100*(tilesLoaded/tilesToLoad).
So far I can retrieve the total count of tiles to load, but I am unable to count already loaded tiles. The most promising is a custom loader, but it is not clear to me how to modify it without touching the original OL source code.
var vectorSource = new ol.source.Vector({
loader: ol.featureloader.xhrX(url, format),
strategy: ol.loadingstrategy.tile(tileGrid)
});
// forked method, but the inner 'loadFeaturesXhr' method seems to be private and cannot be used
ol.featureloader.xhrX = function(url, format) {
/*
return ol.featureloader.loadFeaturesXhr(url, format,
function(features, dataProjection) {
this.addFeatures(features);
// when tile loading succeeds
tilesLoaded++;
},
function() {
// when tile loading fails
tilesLoaded++;
});
*/
// just returning the original loader
return ol.featureloader.xhr(url, format);
}
var url = function(extent, resolution) {
tilesToLoad++; // when a new tile is needed, this counter is incremented
var tileCoord = tileGrid.getTileCoordForCoordAndResolution(ol.extent.getCenter(extent), resolution);
return 'tiles/' +
tileCoord[0] + '/' +
tileCoord[1] + '/' +
(Math.pow(2, tileCoord[0]) + tileCoord[2]) + '.json';
}
var format = new ol.format.GeoJSON({
defaultDataProjection: 'EPSG:3857'
});
Any idea how to call loadFeaturesXhr() method from my source?
Instead of forking default OL3 loader I created a custom one. It was not as hard as expected. Now I can freely add counters to proper places (in the code below I actually update the progress component itself):
var vectorSource = new ol.source.Vector({
loader: function(extent, resolution, projection) {
var getUrl = function(extent, resolution) {
progress.addLoading();
...
};
var xhr = new XMLHttpRequest();
xhr.open('GET', getUrl(extent, resolution), true);
xhr.onload = function(event) {
...
progress.addLoaded();
}.bind(this);
xhr.onerror = function(event) {
progress.addLoaded();
}
xhr.send();
},
strategy: ol.loadingstrategy.tile(tileGrid)
});
The Setup
Currently building my phone gap iOS app which includes geolocation in addition to sending the results to a database and getting back nearby locations. Because I am using jQuery Mobile and Phonegap, I was testing on a browser to perfection, geolocation was success and everything returned was as well. On the iOS device, not so much. When sending a set latitude and longitude, everything returned successfully, but when using the google maps geolocation, and eventually the cordova plugin for geolocation, both failed as unable to find my location, even though they are the exact same code, minus the phone gap initializer on the website.
The Code
jQuery
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
$(document).ready(function () {
//Load Google Map & Geolocate
$(document).on("pagecreate", "#game", function () {
// keep as separate function call to allow for DOM to update after a tag
loadGoogleMap();
});
function loadGoogleMap() {
var defaultLatLng = new google.maps.LatLng(34.0983425, -118.3267434); //default location is Hollywood, CA
if (navigator.geolocation) {
function success(pos) {
//set fields for current user latitude and longitude
$("#lat_in").val(pos.coords.latitude);
$("#lon_in").val(pos.coords.longitude);
//location found
drawMap(new google.maps.LatLng(pos.coords.latitude, pos.coords.longitude));
}
function fail(error) {
//try cordova geolocation plugin
function onSuccess(position) {
alert("CDV position success");
//alert(position.coords.latitude);
//alert(position.coords.longitude);
}
function onError(error) {
alert("CDV position error");
//alert("code: " + error.code + "\n" + "message: " + error.message);
}
navigator.geolocation.getCurrentPosition(onSuccess, onError);
alert("CDV position fail. Google geolocate fail"); //WHERE THE ERROR IS THROWN. THIS IS ALWAYS THE OUTCOME
//drawMap(defaultLatLng); //Failed to find location. Show default location
}
//Geolocate. Cache location for 5 mins. Timeout after 6 seconds
navigator.geolocation.getCurrentPosition(success, fail, {
maximumAge: 500000,
enableHighAccuracy: true,
timeout: 6000
});
} else {
drawMap(defaultLatLng); //No geolocation support, show default map
}
function drawMap(latlng) {
//Collect Data to Send
var uname = $("#unm_in").val();
var lat = $("#lat_in").val();
var lon = $("#lon_in").val();
var myOptions = {
zoom: 16,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map-canvas"), myOptions);
//update latitude and longitude on DB for logged in user && get nearby users
$.post("PHP_ON_SERVER", {
uname: uname,
lat: lat,
lon: lon
}, function (data) {
$.each(data, function (key, value) {
//Define variables
var allUsrLoc = new google.maps.LatLng(value.lat, value.lon);
var contentString = value.uname;
var mkrImg = "inUsrIcon.png"; //icon for logged in user
var inUserName = value.fname + " " + value.lname;
//if info belongs to current user
if (contentString === uname) {
var marker = new google.maps.Marker({
position: allUsrLoc,
map: map,
title: "Player",
icon: mkrImg
});
//change header to name and points
$("#inUserInfo").text("Hi " + inUserName + " || You have " + value.points + " points");
//disable tag button if not it
if (value.isit === "notit") {
$("#tagBtn").addClass("ui-state-disabled");
}
}
//if not current user and is not it
else if (contentString != uname && value.isit != "it") {
var marker = new google.maps.Marker({
position: allUsrLoc,
map: map,
title: "Player"
});
google.maps.event.addListener(marker, 'click', function () {
//Change selected player hidden field to match marker
$("#unm_sel").val(contentString);
$("#lat_sel").val(value.lat);
$("#lon_sel").val(value.lon);
$("#isit_sel").val(value.isit);
//Change tag button to selected player's username
$("#tagBtn").text("Tag " + contentString);
});
}
//no condition for if not current user and is it. TBD if anything will come
});
}, "json");
} //end drawMap
} // end loadGoogleMap
}
HTML
<div data-role="content" role="main" id="map-canvas">
<!-- Map loads here -->
</div>
Some More to Know
I have been reading up on other related questions, but none of the others do work. Either they say use the plugin, which I am to no avail, or set <access origin="*" /> which I am doing already. In addition, most of the other questions revolve around pre-3.0.0 versions of phone gap, which was its own monster. Also, the map loads, just no markers display. On the DB, the user who's location is being updated is set to (0,0). Lastly, when using geolocation in any other app, the iOS device I test on is successfully finding my location. In addition, I am testing on the same WiFi network as the browser which worked, so anything relating to internally being unable to locate due to network or hardware is ruled out.
If you want to see the working example, just ask.
As a part of my final year project in university I'm analysing Twitter data using graph entropy. To briefly outline the purposes:
I want to collect all tweet from a certain area (London) containing keywords "cold", "flu" etc. This part is done using Streaming API.
Then I want to access each of the user's (who tweeted about being ill, collected in previous section) list of followers and following to be able to build a graph for further analysis. And here I'm stuck.
I assume for the second part I should be using Search API, but I keep getting error 88 even for a single user.
Below is the code I use for the first part:
final TwitterStream twitterStream = new TwitterStreamFactory(cb.build())
.getInstance();
StatusListener listener = new StatusListener() {
public void onStatus(Status status) {
User user = status.getUser();
long userid = user.getId();
String username = status.getUser().getScreenName();
String content = status.getText();
GeoLocation geolocation = status.getGeoLocation();
Date date = status.getCreatedAt();
if (filterText(content)) {
System.out.println(username+"\t"+userid);
System.out.println(content);
System.out.println(geolocation);
System.out.println(date);
try {
getConnections(userid);
} catch (TwitterException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//OTHER LISTENER METHODS
};
twitterStream.addListener(listener);
// London
double lat3 = 51.23;
double lat4 = 51.72;
double lon3 = -0.56;
double lon4 = 0.25;
double[][] bb = { { lon3, lat3 }, { lon4, lat4 } };
FilterQuery fq = new FilterQuery();
fq.locations(bb);
twitterStream.filter(fq);
private static boolean filterText(String tweet) {
return tweet.contains("flu")
|| tweet.contains("cold")
|| tweet.contains("cough")
|| tweet.contains("virus");
}
And this is what I'm trying to complete the second part with:
private static void getConnections(long id) throws TwitterException {
Twitter twitter = new TwitterFactory().getInstance();
long lCursor = -1;
IDs friendsIDs = twitter.getFriendsIDs(id, lCursor);
System.out.println(twitter.showUser(id).getName());
System.out.println("==========================");
do
{
for (long i : friendsIDs.getIDs())
{
System.out.println("follower ID #" + i);
System.out.println(twitter.showUser(i).getName());
}
}while(friendsIDs.hasNext());
}
Any suggestions?
When you receive error 88, that's Twitter telling you that you're being rate limited:
The request limit for this resource has been reached for the current rate limit window.
The search call is limited to either 180 or 450 calls in a 15 minute period. You can see the rate limits here and this documentation explains the rate limiting in detail.
As for how to get around it, you may have to throttle your search calls to the API. Twitter4J provides ways to inspect current limits/exhaustion which may help - see Twitter#getRateLimitStatus().
I would appreciate any help concerning pan and zoom for a jquery mobile web app. I have an image of a building floorplan with an image map on top that I would like the user to be able to view from his mobile phone, zoom in and out and pan the area of interest into view.
This should do the trick. http://www.photoswipe.com/
I solved my problem with OpenLayers, image now pans and zooms http://dev.openlayers.org/releases/OpenLayers-2.11/examples/image-layer.html
have to figure out how to combine it with imagemapster now.. (http://www.outsharked.com/imagemapster/)
I have been working on the same problem where an office's floor map of desks should be shown in different colors based on desk's status (Empty, Allocated, Hot seated and etc).
Adding to to this if user clicks on desk, the details of allocated associates/employees should be shown.
The above requirements had been implemented using image mapster jquery plug-in.
And also zooming and panning should be provided.For zooming and panning I have found gzoom plug-in which best suits my requirement. But it is not working as expected when used with image mapster plug-in.
I appreciate your help regarding this.
I figured it out, got everything I needed from the OpenLayers examples
<script type="text/javascript">
var map;
function init(){
map = new OpenLayers.Map('map');
var options = {numZoomLevels: 3}
var floorplan = new OpenLayers.Layer.Image(
'Floorplan Map',
'../../temp_photos/sample-floor-plan.jpg',
new OpenLayers.Bounds(-180, -90, 180, 90),
new OpenLayers.Size(275, 190),
options
);
map.addLayer(floorplan);
//Create a Format object
var vector_format = new OpenLayers.Format.GeoJSON({});
//Create a Protocol object using the format object just created
var vector_protocol = new OpenLayers.Protocol.HTTP({
url: '../../controller?action=GET_FLOOR_FEATURES',
format: vector_format
});
//Create an array of strategy objects
var vector_strategies = [new OpenLayers.Strategy.Fixed()];
//Create a vector layer that contains a Format, Protocol, and Strategy class
var vector_layer = new OpenLayers.Layer.Vector('More Advanced Vector Layer',{
protocol: vector_protocol,
strategies: vector_strategies
});
map.addLayer(vector_layer);
//Create and add selectFeature control
var select_feature_control = new OpenLayers.Control.SelectFeature(
vector_layer,
{
multiple: false,
toggle: true,
toggleKey: 'ctrlKey',
multipleKey: 'shiftKey'
}
);
map.addControl(select_feature_control);
//Activate the control
select_feature_control.activate();
//Finally, let's add some events so we can do stuff when the user
// interacts with the features
function selected_feature(event){
//clear out the log's contents
document.getElementById('map_feature_log').innerHTML = '';
//Show the current selected feature (passed in from the event object)
var display_text = 'Clicked on: '
+ '<strong>' + event.feature.attributes.location + '</strong>'
+ ': ' + event.feature.attributes.description + '<hr />';
document.getElementById('map_feature_log').innerHTML = display_text;
//Show all the selected features
document.getElementById('map_feature_log').innerHTML += 'All selected features: ';
//Now, loop through the selected feature array
for(var i=0; i<vector_layer.selectedFeatures.length; i++){
document.getElementById('map_feature_log').innerHTML +=
vector_layer.selectedFeatures[i].attributes.location + ' | ';
}
}
function unselected_feature(event){
var display_text = event.feature.attributes.location + ' unselected!' + '<hr />';
document.getElementById('map_feature_log').innerHTML = display_text;
//Show all the selected features
document.getElementById('map_feature_log').innerHTML += 'All selected features: ';
//Now, loop through the selected feature array
for(var i=0; i<vector_layer.selectedFeatures.length; i++){
document.getElementById('map_feature_log').innerHTML +=
vector_layer.selectedFeatures[i].attributes.location + ' | ';
}
}
//Register the event
vector_layer.events.register('featureselected', this, selected_feature);
vector_layer.events.register('featureunselected', this, unselected_feature);
if(!map.getCenter()){
map.setCenter(new OpenLayers.LonLat(0, 0),1);
}
}
</script>
Markup:
Image Layer Example
<p id="shortdesc">
This is a floor plan for the first floor of the Science Building
</p>
<div id="map" class="smallmap"></div>
<div id="docs"><div id='map_feature_log'></div>
<p class="caption">
This test shows how to display an image of a floorplan as a
base layer and then draw vectors on top of that, on a new layerage
</p>
<p>
When vector is added popup appears with that vector's information
</p>
</div>
</body>
I get my features from the server:
package actions;
import control_layer.Action;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
*
* #author christina
*/
public class GetFloorFeatures implements Action {
private static final int MAX_INACTIVE_INTERVAL = 900; // 15 minutes
private String view;
#Override
public boolean execute(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
HttpSession session = req.getSession(true);
System.out.println("------------ In GetFloorFeatures");
session.setMaxInactiveInterval(MAX_INACTIVE_INTERVAL);
view = "pages/maps/displayFloorFeatures.jsp";
return true;
}
#Override
public String getView() {
return view;
}
#Override
public Object getModel() {
return null;
}
}
The data is hardcoded in the jsp file but it will eventually be generated by a database query:
<%#page contentType="application/json" pageEncoding="UTF-8"%>
<% response.setContentType("application/json");
//harcoded now, later will call database query to retrieve features for this floor
String floorFeatureVectors = "{\"type\": \"FeatureCollection\",\"features\": [{\"type\":\"Feature\", \"id\":\"OpenLayers.Feature.Vector_84\", \"properties\":{\"location\": \"Telecom Lab\",\"description\": \"Stand back, I'm going to try science!\"}, \"geometry\":{\"type\":\"Polygon\", \"coordinates\":[[[9, -52.342105263158], [9.4736842105263, -79.815789473684], [40.263157894737, -78.868421052632], [43.105263157895, -78.394736842105], [44.526315789474, -51.394736842105], [9, -52.342105263158]]]}, \"crs\":{\"type\":\"OGC\", \"properties\":{\"urn\":\"urn:ogc:def:crs:OGC:1.3:CRS84\"}}},"
+ "{\"type\":\"Feature\", \"id\":\"OpenLayers.Feature.Vector_85\", \"properties\":{\"location\": \"MUSIC lab\",\"description\": \"Laboratory of Distributed Multimedia Information Systems and Applications \"}, \"geometry\":{\"type\":\"Polygon\", \"coordinates\":[[[-113.21052631579, 4.9736842105263], [-113.68421052632, -11.605263157895], [-76.263157894737, -13.026315789474], [-76.263157894737, -1.1842105263158], [-93.315789473684, -0.71052631578947], [-93.789473684211, 4.0263157894737], [-113.21052631579, 4.9736842105263]]]}, \"crs\":{\"type\":\"OGC\", \"properties\":{\"urn\":\"urn:ogc:def:crs:OGC:1.3:CRS84\"}}},"
+ "{\"type\":\"Feature\", \"id\":\"OpenLayers.Feature.Vector_86\", \"properties\":{\"location\": \"Main Entrance Science Building\",\"description\": \"Caffeteria \"}, \"geometry\":{\"type\":\"Point\", \"coordinates\":[-8.0526315789474, 36.710526315789]}, \"crs\":{\"type\":\"OGC\", \"properties\":{\"urn\":\"urn:ogc:def:crs:OGC:1.3:CRS84\"}}}"
+ "]}";%><%=floorFeatureVectors%>