I've been working with MapServer for about 2 hours now , but it seems alittle bit complicated to get started with.
So here's my question
Is there any way to get mapserver to show a simple map of whole world in which I can move the map to see different parts of the world ?
( from what I've learnt so far , it just shows you the Map you've passed the mapserv cgi , and the map is static and cannot be moved ! )
EDIT :
I'm still wondering if I can have a simple map for the whole world or a country or whatever ! Should I be Writing .Map Files for everything On my own ??
Okay , so after looking it up and struggling alittle , I found some JS libraries to do this, One of the was Open Layers. You just have to reference it at the beginning of your html page like :
<script src="http://openlayers.org/api/OpenLayers.js"></script>
and then you can have zoom and move options for your map by binding MapServer data as follows to the OpenLayers init function.
Var map, layer;
function init(){
map = new OpenLayers.Map( 'map' );
layer = new OpenLayers.Layer.MapServer( "NAME",
"http://localhost/cgi-bin/mapserv", {map: 'PATH_TO_.MAP'} );
map.addLayer(layer);
map.zoomToMaxExtent();
}
And lots of cool tutorials can be found in spatialhorizons.com.
Hope this helps someone :)
MapServer is just that, a MAP SERVER. It sounds like you are currently using a cgi script to display a hosted map. WMS providers like MapServer host data that can be viewed using a WMS client application. There are many such applications. You will need a more sophisticated client application to connect to the MapServer in order to perform more complicated map manipulations.
check out GoogleEarth
or NASA WorldWind
or I haven't used this yet but it looks like it might be the easiest, if least dependable.
First MapServer is the GIS server side technology. The zoom in/ pan is the client side behavior in my opinion.
When we look at the moment that user pan/zoom at one web application, what really happened is the front end application get the pan/zoom event and make calls to mapserver to get the new map to return to the client side.
So it is more likely your leaflet, Google map API, Openlayers, etc. are handling the detection of the client movement and parse it into new getmap request and send the request to mapserver to get the response.
What you saw from the MapServer using get request is static and it is suppose to be so. The dynamic part is happened in the client side to make dynamic calls from the front end application to make these static calls. That is interactive when client side dynamically sending out request and refresh the map from the response.
Related
I'm rewording a question I asked earlier in hopes that it will get me some feedback.
I need to generate a static map from Mapbox that shows two end points and the polyline route between them. The method outlined below is what I'm using. It sometimes works and sometimes doesn't--and that is what's driving me crazy.
First, I use the two GPS end points to make an API request that generates the polyline. Then I use a second API request with the two end points and the polyline to generate the static map. The first part always seems to work. I get an encoded polyline that I can run through an online decoding tool and it shows the various points along the path just fine, but the second step to generate the map from Mapbox sometimes gives me the expected map and sometimes gives me an error code. The code is usually {"message":"Not Found"}, but sometimes I get a {"message":"Not Authorized - No Token"} error code.
I use this API with the two end points to get a JSON file that has a polyline:
https://api.mapbox.com/directions/v5/mapbox/driving/POINT1;POINT2?access_token=TOKEN
Then, once I have the polyline, I am using this API to generate the map:
https://api.mapbox.com/styles/v1/mapbox/streets-v11/static/pin-s-a+9ed4bd(POINT1),pin-s-b+000(POINT2),path-5+f44-0.5(POLYLINE)/auto/500x300?access_token=TOKEN
This works fine...
Point 1 = -87.321536,36.584454
Point 2 = -104.793676,38.749513
Polyline = }kh~Ez{}sO|HUuHmj#uhHbOyAla#kisAdelC|aMf~w#egO|uaAahfBr{|#w_#sAozkCcwFsp#v]__w#hjFjf#bdCkaJhmzAiyXtzb#fJ|{#{p[|~yErtBdacE{x^vkvHrZfuKo[tpBfxSrcuBocGpi_AqhCvjb#wgAvfsDhyc#fkrD~mD~bkDayD~ywCsui#vjmEoyBpk|AiOhHrvEdueApda#huoA|v[zuhFsySvwaAvbDwqHxXpwDYj#riJULheEfXh^tdAj~I^gIhAkEY~#kHseBlGyC^kA
Map API request = https://api.mapbox.com/styles/v1/mapbox/streets-v11/static/pin-s-a+9ed4bd(-87.321536,36.584454),pin-s-b+000(-104.793676,38.749513),path-5+f44-0.5(}kh~Ez{}sO|HUuHmj#uhHbOyAla#kisAdelC|aMf~w#egO|uaAahfBr{|#w_#sAozkCcwFsp#v]__w#`hjFjf#bdCkaJhmzAiyXtzb#fJ|{#{p[|~yErtBdacE{x^vkvHrZfuKo[tpBfxSrcuBocGpi_AqhCvjb#wgAvfsDhyc#fkrD~mD~bkDayD~ywCsui#vjmEoyBpk|AiOhHrvEdueApda#huoA|v[zuhFsySvwaAvbD`wqHxXpwDYj#riJULheEfXh^tdAj~I`^gI`hAkEY~#kHseBlGyC^kA)/auto/500x300?access_token=TOKEN
Map (yay!)
This does not work...
Point 1 = -87.321536,36.584454
Point 2 = -85.855218,37.690038
Polyline = }kh~Ez{}sO|HUtCurC}xCkhC}~BqvIuc_#o~l#oaI}aUrs#kkL}~Iso\qHoyGsiKaTpQcRdlGusK_DEiz#w^cwOakJurAizT{hCugF_bBenSsOclZkdCw]mgEwyDogLgfBatEubCmkGxa#icLe_Do_Spf#cw]}sEgOaDgT{[zFyIk~Bts#
Map API request = https://api.mapbox.com/styles/v1/mapbox/streets-v11/static/pin-s-a+9ed4bd(-87.321536,36.584454),pin-s-b+000(-85.855218,37.690038),path-5+f44-0.5(}kh~Ez{}sO|HUtCurC}xCkhC}~BqvIuc_#o~l#oaI}aUrs#kkL}~Iso\qHoyGsiKa`TpQcRdlGusK_DEiz#w^cwOakJurAizT{hCugF_bBenSs`OclZkdCw]mgEwyDogLgfBatEubCmkGxa#icLe_Do_Spf#cw]}sEgOaDgT{[zFyIk~Bts#)/auto/500x300?access_token=TOKEN
No Map :-(
This is a small part of a much bigger project where I am automating the process for generating project reports, but the problem isn't with my jQuery/AJAX code. It's a problem with my APIs and/or Mapbox. If there is a better/faster/easier way to get these maps, then I am absolutely open to suggestions, because this does not seem like the most efficient way to do it. I will be generating these reports from a computer. I am not worried about bandwidth or scaling down for a phone application. The file can be as cumbersome as it wants to be as long as I can consistently generate a map every time.
Steve's comment hints at the right solution, but just to make it absolutely clear - this is happening because you are not properly encoding the path polyline in your request. Polylines in particular have a nasty habit of including reserved characters that will break URIs unless properly encoded at the time of the request.
When I encode the polyline portion of your path overlay with a simple tool like url encode decode, I'm able to make your request work as expected:
https://api.mapbox.com/styles/v1/mapbox/streets-v11/static/pin-s-a+9ed4bd(-87.321536,36.584454),pin-s-b+000(-85.855218,37.690038),path-5+f44-0.5(%7Dkh~Ez%7B%7DsO%7CHUtCurC%7DxCkhC%7D~BqvIuc_%40o~l%40oaI%7DaUrs%40kkL%7D~Iso%2FqHoyGsiKa%60TpQcRdlGusK_DEiz%40w%5EcwOakJurAizT%7BhCugF_bBenSs%60OclZkdCw%5DmgEwyDogLgfBatEubCmkGxa%40icLe_Do_Spf%40cw%5D%7DsEgOaDgT%7B%5BzFyIk~Bts%40)/auto/500x300?access_token=MAPBOX_ACCESS_TOKEN
⚠️ disclaimer: I currently work at Mapbox ⚠️
hi
I want to build a control panel for a web art application that needs to run in fullscreen, so all this panel, that controls stuff like colors and speed values, have to be located at a different window.
My idea is to have a database storing all these values and when I make a change in the control panel window the corresponding variable in the application window gets updated too. So, it's basically a real-time update that I could do with AJAX setting a interval to keep checking for changes BUT my problem is: I can't wait 30 seconds or so for the update to happen and I guess a every-1-second AJAX request would be impossible.
Final question: is there a way to create a sort of a listener to changes in the database and fire the update event in the main application only immediately after I change some value in the control panel? Does Angular or another framework have this capability?
(Sorry for the long explanation, but I hope my question is clearer by offering the context [: )
A web socket powered application would have this benefit. This carries a bit more complexity on the back end, but has the benefit of making your application as close to real-time as can be reasonably expected.
The Mozilla Development Network has some good documentation on websockets.
On the front end, the WebSocket object should work for you on most modern browsers.
I'm not sure what your back end is written in, but Socket.IO for Node.js and Tornado for Python will make your applications web-socket capable
If one window is opening the other windows via JavaScript, you can keep the reference to the opened window and use otherWindow.postMessage to pass messages across
"Parent" window looks like
// set up to receive messages
window.addEventListener('message', function (e) {
if (e.origin !== 'http://my.url')
return; // ignore unknown source
console.log(e.message);
});
// set up to send messages
var otherWindow = window.open('/foo', '_blank');
otherWindow.postMessage('hello world', 'http://my.url');
"Child" windows look similar
// same setup to recieve
// ...
// set up to send
var otherWindow = window.opener;
// ... same as before
For the realtime I would recommend using a library like socket.io or using a database like firebase.
For the fullscreen I would recommend using a library like angular-screenfull
i use https://pushjs.io/, had exactly the same problem and this is a really simple solution for your problem. It is capable of sending and listening to events without any database interference.
I am a PHP dev looking to port my API over to the Parse platform.
Am I right in thinking that you only need cloud code for complex operations? For example, consider the following methods:
// Simple function to fetch a user by id
function getUser($userid) {
return (SELECT * FROM users WHERE userid=$userid LIMIT 1)
}
// another simple function, fetches all of a user's allergies (by their user id)
function getAllergies($userid) {
return (SELECT * FROM allergies WHERE userid=$userid)
}
// Creates a script (story?) about the user using their user id
// Uses their name and allergies to create the story
function getScript($userid) {
$user = getUser($userid)
$allergies = getAllergies($userid).
return "My name is {$user->getName()}. I am allergic to {$allergies}"
}
Would I need to implement getUser()/getAllergies() endpoints in Cloud Code? Or can I simply use Parse.Query("User")... thus leaving me with only the getScript() endpoint to implement in cloud code?
Cloud code is for computation heavy operations that should not be performed on the client, i.e. handling a large dataset.
It is also for performing beforeSave/afterSave and similar hooks.
In your example, providing you have set up a reasonable data model, none of the operations require cloud code.
Your approach sounds reasonable. I tend to put simply queries that will most likely not change on the client side, but it all depends on your scenario. When developing mobile apps I tend to put a lot of code in cloud code. I've found that it speeds up my development cycle. For example, if someone finds a bug and it's in cloud code, make the fix, run parse deploy, done! The change is available to all mobile environments instantly!!! If that same code is in my mobile app, it really sucks, cause now I have to fix the bug, rebuild, push it to the app store/google play, wait x number of days for it to be approved, have the users download it... you see where I'm going here.
Take for example your
SELECT * FROM allergies WHERE userid=$userid query.
Even though this is a simple query, what if you want to sort it? maybe add some additional filtering?
These are the kinds of things I think of when deciding where to put the code. Hope this helps!
As a side note, I have also found cloud code very handy when needing to add extra security to my apps.
I have a Backbone application, which has a collection called Links. Links maps to a REST API URI of /api/links.
The API will give the user the latest links. However, I have a system in place that will add a job to the message queue when the user hits this API, requesting that the links in the database are updated.
When this job is finished, I would to push the new links to the Backbone collection.
How should I do this? In my mind I have two options:
From the Backbone collection, long poll the API for new links
Setup WebSockets to send a "message" to the collection when the job is done, sending the new data with it
Scrap the REST API for my application and just use WebSockets for everything, as I am likely to have more realtime needs later down the line
WebSockets with the REST API
If I use WebSockets, I'm not sure of the best way to integrate this into my Backbone collection so that it works alongside the REST API.
At the moment my Backbone collection looks like this:
var Links = Backbone.Collection.extend({
url: '/api/links'
});
I'm not sure how to enable the Backbone collection to handle AJAX and WebSockets. Do I continue to use the default Backbone.sync for the CRUD Ajax operations, and then deal with the single WebSocket connection manually? In my mind:
var Links = Backbone.Collection.extend({
url: '/api/links',
initialize: function () {
var socket = io.connect('http://localhost');
socket.on('newLinks', addLinks)
},
addLinks: function (data) {
// Prepend `data` to the collection
};
})
Questions
How should I implement my realtime needs, from the options above or any other ideas you have? Please provide examples of code to give some context.
No worries! Backbone.WS got you covered.
You can init a WebSocket connection like:
var ws = new Bakcbone.WS('ws://exmaple.com/');
And bind a Model to it like:
var model = new Backbone.Model();
ws.bind(model);
Then this model will listen to messages events with the type ws:message and you can call model.send(data) to send data via that connection.
Of course the same goes for Collections.
Backbone.WS also gives some tools for mapping a custom REST-like API to your Models/Collections.
My company has a fully Socket.io based solution using backbone, primarily because we want our app to "update" the gui when changes are made on another users screen in real time.
In a nutshell, it's a can of worms. Socket.IO works well, but it also opens a lot of doors you may not be interested in seeing behind. Backbone events get quite out of whack because they are so tightly tied to the ajax transactions...you're effectively overriding that default behavior. One of our better hiccups has been deletes, because our socket response isn't the model that changed, but the entire collection, for example. Our solution does go a bit further than most, because transactions are via a DDL that is specifically setup to be universal across the many devices we need to be able to communicate with, now and in the future.
If you do go the ioBind path, beware that you'll be using different methods for change events compared to your non-socket traffic (if you mix and match) That's the big drawback of that method, standard things like "change" becomes "update" for example to avoid collisions. It can get really confusing in late-night debug or when you have a new developer join the team. For that reason, I prefer either going sockets, or not, not a combination. Sockets have been good so far, and scary fast.
We use a base function that does the heavy lifting, and have several others that extend this base to give us the transaction functionality we need.
This article gives a great starter for the method we used.
In my winrt app, I am trying to update the live tile based on polled URIs. There is currently no update happening and I can't figure out how to troubleshoot. There are numerous scenarios that could be breaking things but i can't seem to find anyway to get insight into potential errors.
The TileUpdateManager seems to be a bit of a black hole that absorbs information but never lets it out.
Does anyone know of how to view errors from the TileUpdateManager?
If it interests anyone, here is my update code:
TileUpdateManager.CreateTileUpdaterForApplication().EnableNotificationQueue(true);
PeriodicUpdateRecurrence recurrence = PeriodicUpdateRecurrence.HalfHour;
List<Uri> urisToPoll = new List<Uri>();
urisToPoll.Add(new Uri(#"http://livetileservice2012.azurewebsites.net/api/liveupdate/1"));
urisToPoll.Add(new Uri(#"http://livetileservice2012.azurewebsites.net/api/liveupdate/2"));
TileUpdateManager.CreateTileUpdaterForApplication().StartPeriodicUpdateBatch(urisToPoll, recurrence);
To expand on Nathan's comment, here are two steps you can take to troubleshoot:
Enter your URI straight into a browser to see the results that are returned, and inspect them for being proper XML. As Nathan points out, your URIs are returning JSON which will be ignored by the tile update manager. As a working example (that I use in Chapter 13 of my HTML/JS book), try http://programmingwin8-js-ch13-hellotiles.azurewebsites.net/Default.cshtml.
If you feel that your URI is returning proper XML, try it in the Push and Periodic Notifications Sample (Scenarios 4 and 5 for tiles and badges). If this works, then the error would be in your app code and not in the service.
Do note that StartPeriodicUpdate[Batch] will send a request to the service right away, rather than waiting for the first interval to pass.
Also, if you think that you might have a problem with the service, it's possible to step through its code using Visual Studio Express for Web running on the localhost, when the app is also running inside Visual Studio Express for Win8 (where localhost is enabled).
.Kraig