More

Leaflet & Esri-Leaflet: JSON objects not drawing correctly when using 'fields' filter


I am working with Leaflet 0.7.3 and esri-leaflet beta.6. Using L.esri.Layers.FeatureLayer works fine until I add the fields filter. At that point, the geojson objects draw sporadically (mostly not at all). I might see one or two shapes on the screen.

Example code at http://codepen.io/BBurnworth/pen/fhBrG/

Lines 32-36:

//The line below works. var parcels = new L.esri.Layers.FeatureLayer(url + '24'); // **The below line works (Checked JSON attributes in firebug) but the parcels flicker and don't display properly** // var parcels = new L.esri.Layers.FeatureLayer(url + '24', { fields: "CITY" });

Is this a bug or am I leaving something out? The JSON (in Firebug) reads correctly, with the geometry data coming in. It just doesn't draw correctly.

I would love for someone to point out something simple that I am missing. I would rather fetch just the bare minimum of data and then use the tasks.IdentifyFeatures to get the attribute data when the user wants it.


a couple things here…

  1. that constructor option expects an array
  2. at a minimum, you have to include the OBJECTID field in that array in order for everything to work on the clientside as it should.

    { fields: ["OBJECTID", "CITY"] }

we should probably be handling that for people. i'll look into it.

http://codepen.io/anon/pen/pjEtD


Esri Technical Support Blog

by Andrew--Johnson

3D data is becoming more ubiquitous nowadays and is especially promoted throughout the ArcGIS Platform. From web scenes, to CityEngine, to ArcGIS Pro, there are many different applications to import, manage, model, and share your 3D data. To get the output you are looking for, it may require numerous steps and tools. To navigate some of these steps and tools, here are some tips and tricks for working with 3D data in ArcGIS.

3D File Coordinate Systems

The majority of 3D formats do not store a coordinate system. GeoVRML and KML are the lone exceptions. KML will use a WGS 1984 coordinate system and meters for the unit of measurement. All other types (DAE, 3DS, OBJ) must be placed properly, otherwise they may import at "0,0" (off the coast of Africa). Trick #1

If you are using CityEngine, you can drag and drop your shape from the Navigator window into the scene (this workflow assumes a scene coordinate system is already set). When you export the shape to a multipatch feature class, the coordinate system is created with the data so you can bring it into another ArcGIS product.Import Overview Trick #2

The same workflow can be accomplished in ArcGIS Pro. Create an empty multipatch feature class, navigate to Editor > Create Features > Select Model, and click the globe to place the model. Trick #3 Use the Replace with Model tool (ArcScene or ArcGlobe) or the Replace with Multipatch tool (ArcGIS Pro).ArcGIS Desktop Replace with ModelArcGIS Pro Replace with Multipatch Trick #4

If you are using ArcScene, ArcGlobe, or ArcGIS Pro, manually place the model during an edit session using the Move, Rotate, or Scale operations.Move, rotate, or scale a feature Note: There is known issue with the Import 3D files tool. The placement points parameter is not honored so as of ArcGIS 10.4.1 or ArcGIS Pro 1.3, this tool is not a viable option. This issue is planned to be fixed in a future release.

To import your 3D file with textures, you must ensure the texture resides next to the 3D file, either as an individual image file or a folder with the images. Note: Both the file and folder must have same name for the software to recognize the texture. Trick #1

Textures are only supported in file or enterprise geodatabases. Shapefile multipatches do not support textures, so make sure to import the multipatch into a geodatabase.

Make sure your 3D data has valid z-values. When sharing a web scene or importing the data into ArcGIS Pro, you want to make sure the elevation values are correct. Trick #1

If your multipatch is not at the correct elevation, you can use this trick. In ArcGIS Pro,set the multipatch data "on the ground" and use the Layer 3D To Feature Class tool. The elevation values are then embedded into the multipatch. Trick #2

If you are using simple feature data (non-multipatch), use the Add Surface Information tool to add z-values to the data. Also, you can add z-values to an attribute table and with the Add Z Information tool, you can verify the values with the tool's output. If the data does not have valid elevation values, see the next tip.

Understand which tools can create 3D data: Layer 3D To Feature Class, Interpolate Shape, or Feature To 3D By Attribute.

Understand your 3D data. Extruded 2D polygons are not true 3D features, so you must export to multipatch to make the polygon a true 3D feature. Simple point, line, and polygon features can be considered 3D data if they have the correct z-values. 2D features can also be symbolized using 3D marker symbology.

Know the difference between a z-enabled feature class and a non-z-enabled feature class with a z field in the attribute table. Feature classes must be z-enabled to display at the correct elevation. You might see a z field in the attribute table, but that does not mean the geometry has the correct z-values. This can be verified by editing the vertices or adding z-values to an attribute table, as described above.

While this blog does not cover every facet of working with 3D data, it is my hope that this will provide some valuable information for working with 3D data on the ArcGIS Platform. Andrew J. – Desktop Support Analyst


Protobuf Tile Server

Working with maps can be amazing, displaying data within maps is one of the trickiest parts when you are developing a platform with geospatial data. A little step to display information in a map is the usage of tiles. In this post we will create a small tile server that will serve protobuf tiles using Node.js, Hapi, Redis and Postgres.

This tutorial was heavily inspired in PostGIS to Protobuf (with vector tiles) please check it out. Keep in mind this tutorial will show a really basic tile server implementation, if you want to find a way more developed and tested implementation you can try TileStache or you may be able to find a lot of great utilities in here. Saying that I hope you enjoy creating your own mini tile server.

Docker and Docker-Compose Setup

Docker will let us create containers and run our project anywhere (as long as the machine supports Docker) leaving aside all the issues of package versions or the cumbersome setup of a database for a simple tutorial like this one. The tutorial will use docker-compose 1.11.2 and Docker 17.03.0-ce, in order to check your version run the following commands:

Lets start by creating two Dockerfiles in the root directory. The first Dockerfile will be just to create our package.json and npm-shrinkwrap.json, the second one will be the one in charge of starting the tile server.

The Dockerfile is self-explanatory we are creating an image with the dependencies we need so our tile server can run but there are a few gotchas within these dependencies:

1.- Mapnik, as the official website states mapnik combines pixel-perfect image output with lightning-fast cartographic algorithms, and exposes interfaces in C++, Python, and Node. We will use this library in order to create the tiles in our server.
2.- The missing package.json and npm-shrinkwrap.json, the reason behind these files not being present at the moment is due to the fact that we want to use Docker and docker-compose to create all files.

Now that we have a Dockerfile we will need to create other containers that will allow an easy development, the first service we will declare in our docker-compose.yml file is a node container. We will be using this container to create the package.json and npm-shrinkwrap.json files. Lets create a docker-compose.yml file in our root directory:

With this we can run a container which is able to run node, let’s use this container to create our files. Lets build our node container and run the desired commands:

Now if we look in our root directory we will find our two newly generated files, package.json and npm-shrinkwrap.json. The files may have different a different ownership thus causing writing problems, to fix this we can quickly change the ownership by doing the following:

Lets create a server.js file to test our server container:

Lets add a container for our server in our docker-compose.yml:

In our command option we set npm run start-development , currently our package.json lacks this script, let’s add it into the “scripts” field:
package.json

We are using nodemon to automatically reload our node server and avoid using ctlr + c and running docker-compose up tile-server for each change in our server files. When changing docker-compose.yml we must restart the docker-compose process using ctlr + c and running docker-compose up tile-server . Create a server.js file to quickly test our configuration:
server.js

We can finally test if our setup is working by running docker-compose up tile-server :

Our container works, but the container of server.js is just a console.log. We need a server which will receive http requests, let’s create one with the help of hapijs.

The server

We will be using hapi, to create a simple server. Creating a server with hapi is pretty simple:
server.js

Now we can run our server by running docker-composer run tile-server :

We can test our working server by going to our browser and go to http://0.0.0.0:8081

Amazing, our server works. We will need to connect to a database, in this tutorial we will be using Postgres. Lets create a plugin which will help us connect to a database.

Postgres plugin

In order to connect from our server to a database we will need to add a container into our docker-compose.yml, we will be using an image of postgis:
docker-compose.yml

The tile-server container got new options defined, the links option will link to containers in another service. We need this option so we can communicate with our database, it will also express a dependency between services, which will decide startup order. The depends_on option will start services in dependency order, in our case db will be started before our tile-server. If we run docker-compose up tile-server it will also create and start db.

We now have our server and database, as of now our database is empty. Lets get some example data inserted into our database. In this tutorial we will be using the states from Mexico. The following .sql file will create a schema and a table which will contain all the information we need:

Our database has information and is running correctly, now let’s connect our database to our server by creating a hapi plugin. If you haven’t used hapi plugins please check the docs for more information of how a plugin works.

Create a plugins folder in our root directory and a postgres folder inside it, the postgres plugin will consist of two files a package.json and a index.js. Lets create those files, you should have a structure like the one below:

The index.js file will contain the logic to connect to our database and create a connection which will be available for later use in our handlers.

The plugins array in our server is empty at the moment, we need to include our newly created plugin into the array so hapi will load it.

As soon as we change the plugins array we should see a reload in our server via nodemon:

Lets see if everything works out, let’s add a little route to test the connection to our database:

Go to http://0.0.0.0:8081/postgres-test and check the result, you should see something like this:

Layer plugin

To display a tiled map in a browser usually requires the support of a web mapping framework. This framework handles the retrieval of tiles, display, caching, and user navigation. Popular frameworks for tiled maps include Google Maps API, OpenLayers and Leafet. In this tutorial we will be using leaflet
Most tiled web maps follow certain Google Maps conventions:

  • Tiles are 256x256 pixels
  • At the outer most zoom level, 0, the entire world can be rendered in a single map tile.
  • Each zoom level doubles in both dimensions, so a single tile is replaced by 4 tiles when zooming in. This means that about 22 zoom levels are sufficient for most practical purposes.
  • The Web Mercator projection is used, with latitude limits of around 85 degrees.

The de facto OpenStreetMap standard, known as Slippy Map Tilenames[2] or XYZ,[3] follows these conventions and adds more:

  • An X and Y numbering scheme
  • PNG images for tiles
  • Images are served through a REST API, with a URL like http://. /Z/X/Y.png, where Z is the zoom level, and X and Y identify the tile.

Raster tile layers

Raster tile layers deliver basemaps to your client application as image files (for example, JPG or PNG format) that have been prerendered and stored on the server and are displayed as is by the client. Raster tile layers are most appropriate for basemaps that give your maps geographic context such as imagery (as in the World Imagery basemap) or feature-based maps such as in the Topographic, National Geographic, Oceans, and other basemaps. Raster tile layers can also be composed of static operational layers such as thematic maps of your data.

The tile layer format is fast to transmit over the Internet and is easily understood by most common mapping software applications, so these basemaps are compatible not only with ArcGIS and web apps built with the ArcGIS APIs, but also third-party apps that use OGC protocols such as WMS/WMTS. Other benefits of raster tile layers include the following:

  • Work well across a wide range of applications and devices (web, desktop, and mobile), including desktop applications like ArcMap and older versions of web browsers.
  • Provide high-end cartographic capabilities such as advanced label placement and symbology.
  • Support various raster data sources such as imagery and elevation data.
  • Can be printed from web mapping applications.

Vector tile layers

Vector tile layers deliver map data as vector files (for example, PBF format) and include one or more layers that are rendered on the client based on a style delivered with the layer. Vector tiles include similar data to that found in some (but not all) of the available raster tile basemaps, but they store a vector representation of the data that is, geographic features are represented as points, lines, and polygons in a format understood by the client application. Unlike raster tile layers, vector tile layers can adapt to the resolution of their display device and be restyled for multiple uses. Vector tiles have a smaller file size than raster tiles, which translates to faster maps and better performance. The combination of tile access performance and vector drawing allows the tiles to adapt to any resolution of the display, which may vary across devices.

In the map viewer, client-side drawing of vector tiles allows you to customize the style of the vector tile layer and the contents of the map. Other advantages of vector tile layers include the following:

  • Can be used to generate many different map styles using a single set of vector tiles. You can customize vector tile layers—for example, hide their visibility, change symbols and fonts, change languages for labels, and so on—without having to regenerate tiles.
  • Look great on high-resolution displays (for example, retina devices) that offer much better resolution than low-resolution (96 dpi) raster tiles, without the need for generating separate, high-resolution versions. Vector tiles can be displayed at any scale level with clear symbology and labels in desktop applications such as ArcGIS Pro.
  • Can be generated much more quickly, and with fewer hardware resources, than corresponding raster tiles. This reduces the cost to generate the tiles and improves the speed at which data updates can be made available.
  • Vector tiles are much smaller in size than corresponding raster tiles, reducing the cost to store and serve the tiles.
  • Can be projected into various coordinate systems, using desktop applications like ArcGIS Pro, without distortion of labels and other symbols.

You can add vector tile layers as operational layers or basemaps to the map viewer or scene viewer. You can use maps and scenes with vector tile layers in web apps using a configurable app, Web AppBuilder, or ArcGIS API for JavaScript. Vector tile layers have the best performance on machines with newer hardware, and they can be displayed in Internet Explorer 11 and later and most other current versions of desktop browsers, including Chrome, Firefox, and Safari.

Now that we understand a little bit more about vector tiles, let’s understand how we will request the tiles to our server. As mentioned before to display tiled maps we require a web mapping framework, at the moment we will use leaflet to display our vector tiles. As of version 1.0.3 leaflet does not allow to load and display vector tiles by using their API. This could be a problem, but thanks to the great effort of contributors and the leaflet plugins system we will be able to render our vector tiles. We will be using the Leaflet.VectorGrid library.

Lets create a html file which will help us render our map. In order for hapi to serve static assets we will need a plugin, inert will help us with this requirement.

And create an index.html file in our root directory:
index.html

We need a route to serve this html, let’s add this to our server:

By going to http://0.0.0.0:8081/test-vector-tiles we should see our leaflet map. If using Google Chrome you can open the DevTools and go to the Network tab, select the Img filter and you will be able to see the requests to the carto content delivery network:

As you can see a request was made with the // format, let’s try to create a handler that follows this format.

With a working database available, we will proceed to create our layers plugin. In our plugins folder create a layers folder, as our postgres plugin the layers plugin will consist of two files a package.json and a index.js. Lets create those files, you should have a structure like the one below:

At the moment our layers plugin will contain a simple console.log :

And include in our plugins array:

As soon as we change the plugins array we should see a reload in our server via nodemon:

Lets create a layer folder in our plugins/layers/ folder and create a states.js file:

Lets try to find out what is happening in the handler, keep in mind that this handler will run for each tile in the bounding box.

We are importing the sphericalmercator package, which will help us by providing projection math for converting between mercator meters, screen pixels (of 256x256 or configurable-size tiles), and latitude/longitude.

Next we are declaring a query, we will be using two functions. The first function is st_intersects which returns TRUE if the Geometries/Geography “spatially intersect in 2D”. You may be tempted to use ST_CONTAINS or ST_Within but we must get all the polygons that intersect a given polygon.

The second function is ST_MakeEnvelope, this function creates a rectangular Polygon formed from the minima and maxima. Remember that this handler will run for each tile in the bounding box, so the polygon that we will form will be just the tile.

We are basically saying get me the topojson and cve_ent fields from the table estados where the the field geom intersects with the rectangular polygon we provide.

Now let’s get the request params (which will be our xyz values from the tile rendered) and use them to convert to bbox of the form [w, s, e, n]. The bbox method has the following signature bbox(x, y, zoom, tms_style, srs) the first three parameters are from the tiles xyz format, the tms_style will decide whether to compute using tms-style and srs will set the projection for resulting bbox (WGS84|900913).

Now that we have a way to create our polygon via the ST_MakeEnvelope function, let’s run our query. The query resulting mask any has the following signature db.any(query, values) so let’s pass our query and the values as an array from our recently created bbox via the sphericalmercator package and reply with the query result.

We have a working handler but we are still missing a route that will execute this handler. Lets go into our index file at our layers plugin folder and register our route:
plugins/layers/index.js

Now if we go to http://0.0.0.0:8081/layers/states/7/28/56.pbf we should get a response like the one below:

So what is happening? We are getting al the polygons that are intersected by the tile polygon. We can say that at the zoom level 7 tile index 28, 56 there are 10 states that intersect the tile polygon. This is a little step to return a vector tile but at the moment we are just returning a json response. We will use mapnik to create our tile:

We are requiring the path and mapnik modules. Mapnik supports a plugin architecture which allows access to a variety of formats, we need to let our mapnik configuration that we’ll be using geojson as a format. Registering geojson.input via registerDatasource will allow us to use GeoJSON as format within the mapnik module. We have just declared our dependencies for the tile creation, now let’s create a function for the creation of our tile:

First we are creating a new vector tile by using the mapnik’s tile generator, which will build a tile according to the Mapbox Vector Tile specification for compressed and simplified tiled vector data. We are requesting topojson data in our query to reduce the data transfer size, the API for the VectorTile object doesn’t won’t accept topoJSON. We will need to transform each topoJSON into a valid GeoJSON, we will use the topojson module to achieve this task. When we have a valid FeatureCollection we may add it to the tile we created by using the addGeoJSON method. Amazing, a tile was created, still we need to compress the data:

The getData method will retrieve the data in the vector tile as a buffer, the signature is the following getData([options], callback) , we can tweak the options a little but the defaults should work smoothly. The second parameter is a callback which allows this task to be done in an asynchronous way. We get the data from our tile as a buffer, we just need to compress it. The zlib deflate will compress the buffer we received from the getData method, the signature for the deflate method is deflate(buf[, options], callback) the first parameter being the buffer and the second one being the callback, so yeah this method is also asynchronous. Since both methods are async we will wrap them in a Promise . Finally we just need to set the headers into our reply interface:

Our states.js file should look like this at the moment:
plugins/layers/layer/state.js

With all this we can simply test with curl if our endpoint works:

The endpoint works and serves vector tiles as protobufs, now we just need to display them in our index.html file:

Lets go to http://0.0.0.0:8081/test-vector-tiles and we should see our tiles working in our maps. Amazing, the styling can be achieved by including properties in your GeoJSON responses by making a join in your query, something like this:

In your parse function you would have to pass the fields you want into the properties object:

And define a function to style the features based in the desired properties:

We have working tiles with the ability of changing styles easily, if we remember correctly at the beginning of the tutorial we mentioned that we were going to use redis. Lets create a redis plugin to reduce the calls to our database.

Redis plugin

Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache and message broker. Redis is not a plain key-value store, it is actually a data structures server, supporting different kinds of values. What this means is that, while in traditional key-value stores you associated string keys to string values, in Redis the value is not limited to a simple string, but can also hold more complex data structures.

One of the complex structures are binary-safe strings, we will use them to avoid unnecessary database calls. In certain use cases the tile information won’t change in a certain period of time and in order to save resources we can store the result of our handlers with redis.

A redis server is not present in our current configuration, let’s add it to our docker-compose.yml
docker-compose.yml

Create a redis folder within our plugins directory and create a index.js and package.json file.

We are using bluebird.promisifyAll in the redis module, which as the documentation explains promisifies the entire object by going through the object’s properties and creating an async equivalent of each function on the object and its prototype chain. The usage of Promises will help us deal with redis in a much cleaner way. We also included a way to clean our cache via http, of course this endpoint should be only exposed in development or protect the endpoint.

Don’t forget to register our plugin into our array of plugins:

Lets use our redis server through our plugin:

We declare a new function which will take care of caching our binary using redis. Now we have to first check if the key exists withitn our cache, getAsync will take care of that. If we find the key in our cache we create a buffer from our stored binary-safe string and use our replyProtoBuf function to return the desired value. In case we didn’t find our key in redis we follow the procedure to create our tile but including the additional setTileInCache function in the promise chain.

The redis usage allows us to reduce quite a bit the response time from our server.


We have benchmarked our most recent installed R version (3.0.2) built with the included blas/lapack libraries versus the newest (as of April 2015) release 3.2.0 built with Intel MKL libraries on the HiPerGator1 hardware (AMD Abu Dhabi 2.4GHz CPUs) and the Intel Haswell 2.3GHz CPUs we're testing for possible usage in HiPerGator2. The results are presented in the R Benchmark 2.5 table

  • Q: When I submit a job using 'parallel' package all threads seem to share a single CPU core instead of running on the separate cores I requested.
    • A: On SLURM you need to use --cpus-per-task to specify the number of available cores. E.g.

    will allow mcapply or other function from the 'parallel' package to run on all requested cores


    Osmnx.elevation module¶

    Get node elevations and calculate edge grades.

    osmnx.elevation. add_edge_grades ( G, add_absolute=True, precision=3 ) ¶

    Add grade attribute to each graph edge.

    Vectorized function to calculate the directed grade (ie, rise over run) for each edge in the graph and add it to the edge as an attribute. Nodes must already have elevation attributes to use this function.

    See also the add_node_elevations function.

    • G (networkx.MultiDiGraph) – input graph with elevation node attribute
    • add_absolute (bool) – if True, also add absolute value of grade as grade_abs attribute
    • precision (int) – decimal precision to round grade values

    G – graph with edge grade (and optionally grade_abs ) attributes

    Do not use, deprecated, will be removed in a future release.

    This function and the elevation_provider setting are deprecated.

    • G (networkx.MultiDiGraph) – deprecated, do not use
    • api_key (string) – deprecated, do not use
    • max_locations_per_batch (int) – deprecated, do not use
    • pause_duration (float) – deprecated, do not use
    • precision (int) – deprecated, do not use

    Add elevation (meters) attribute to each node using a web service.

    This uses the Google Maps Elevation API and requires an API key. For a free, local alternative, see the add_node_elevations_raster function. See also the add_edge_grades function.

    • G (networkx.MultiDiGraph) – input graph
    • api_key (string) – a Google Maps Elevation API key
    • max_locations_per_batch (int) – max number of coordinate pairs to submit in each API call (if this is too high, the server will reject the request because its character limit exceeds the max allowed)
    • pause_duration (float) – time to pause between API calls, which can be increased if you get rate limited
    • precision (int) – decimal precision to round elevation values

    G – graph with node elevation attributes

    Add elevation attribute to each node from local raster file(s).

    If filepath is a list of paths, this will generate a virtual raster composed of the files at those paths as an intermediate step.

    • G (networkx.MultiDiGraph) – input graph, in same CRS as raster
    • filepath (stringorpathlib.Pathorlist of strings/Paths) – path (or list of paths) to the raster file(s) to query
    • band (int) – which raster band to query
    • cpus (int) – how many CPU cores to use if None, use all available

    G – graph with node elevation attributes


    Thanks to a contribution from franck34, the DVF now supports the option of placing images on markers or on any Leaflet path-based layer, which can be specified in one of two ways. The simplest way is to provide an imageCircleUrl option as part of the normal L.Path options like so:

    This will place a circle on top of your path shape that is filled with the specified image. The image will be automatically sized to fill the area of the shape. For finer-grained control over the images you add, you can specify a shapeImage option. This lets you control the shape of the overlay – you can provide basic SVG shapes such as a circle, a rect, or an ellipse – and also control the size of the image and pattern. The example below creates a circle with radius of 24 pixels an image is then specified through the image option with a width and height of 48 pixels


    Leaflet Features

    Adding a marker to our map

    At some stage we will most likely want to add a marker to our map to pinpoint something. Leaflet makes the process nice and easy by including a marker function with several options

    In its most simple form the following is the full code to show a map with a marker

    The only difference between this code and the simple map code is the addition of a single line at the bottom of the JavaScript portion

    Here we are declaring a variable with the L.marker method at a point of latitude -41.29042 and longitude 174.78219. Then we simply add that to our map by adding .addTo(map) .

    And here’s our map complete with marker…

    Adding a popup to our marker

    Adding a marker couldn’t be any easier, but it’s also not terribly informative in this context. After all, we have no information on what our marker is pointing to. However we can add this context in the form of a popup which is a small text bubble associated with the marker. To do this the code for our marker should look like this

    Here our additional lines bind a popup to our marker using .bindPopup with the text <b>Te Papa</b><br>Museum of New Zealand. (where the <b> tags will make the text bold and the <br> tag will insert a line break). Then we open the popup with .openPopup() .

    But wait! The coolness doesn’t end there. You can click on the marker and the popup will alternately disappear and return. If you omit the .openPopup() portion the popup won’t be open when your map loads, but if you click on the marker it will open up.

    Marker options

    As well as the standard marker functions shown thus far there are several options that can be utilised when displaying a marker. These are enabled by including an array of the appropriate options and their desired values in a section contained in curly braces after the latitude, longitude declaration. Below there is some sample code for the marker function with three different options demonstrating use for a boolean value (true / false) a string and a number.

    Drag a marker

    The draggable option is a boolean which is set to false by default, but when set to true, the marker can be repositioned by clicking on it with the mouse and moving it.

    The following is a code example

    Add a title to a marker

    The title option is a string which will be displayed in a small rectangle beside the pointer when a users mouse is hovered over the marker.

    The following is a code example

    And this is what it looks like…

    Marker with a title as hover text
    Adjust the markers transparency

    The opacity option will vary the transparency of the marker from 0 (transparent) to 1 (opaque).

    The following is a code example

    And this is what it looks like…

    Semi transparent marker

    . A copy is also in the appendices and a copy of all the files that appear in the book can be downloaded (in a zip file) when you download the book from Leanpub.

    The full code of a live example of a map incorporating a marker with a popup, draggability, a title and opacity are available from bl.ocks.org, GitHub and there is a copy of this file called marker-map-complex.html that can be downloaded (in a zip file) when you download the book from Leanpub. The online version at bl.ocks.org and GitHub both use subresource integrity to support secure CORS CORS (Cross Origin Resource Sharing) requests.

    Adding multiple markers to our map

    At some stage we will most likely want to add multiple markers to our map to pinpoint several things. While we could do this one by one following the previous example, we could also do it programmatically with an array of data.

    The following is the full code to show multiple markers on a map

    The full code of a live example of a map incorporating multiple markers is available online at bl.ocks.org or GitHub. A copy can also be downloaded (in a zip file) when you download the book from Leanpub. It’s called multiple-markers.html.

    There are two differences between this code and the code to add a single marker. Firstly we have declared an array ( planes ) which has a range of values with each row including an identifier (the first column) and latitude and longitude values.

    Secondly we include a for loop that contains our marker adding line.

    In the for loop we go from 0 to the end of the planes array ( planes.length ). For each row in our array, we add a marker where the latitude corresponds to planes[i][1] (in the planes array at row i and column 1 (remembering that the first column is 0)) and the longitude is planes[i][2] . We also add a popup to our marker with the identifier ( planes[i][0] ) before adding each marker to the map ( .addTo(map) ).

    And here’s our map complete with markers…

    Multiple markers on a map

    Adding a line to our map

    Adding a line to our map is a great way to provide an indication of a path or border. Leaflet provides the polyline function to do this

    The following is the full code to show a simple map with a line drawn with 4 lines

    The only difference between this code and the simple map code is the addition of the var polyline = section at the bottom of the JavaScript portion

    Here we are defining a path going from one lat/long point to another. We declare a variable with the L.polyline method and step through our points in the array. Then we simply add that to our map by adding .addTo(map) .

    And here’s our map complete with path…

    Obviously this hasn’t been set to follow any logical route :-).

    Adding options to our polyline

    There are a range of options that can be incorporated into our path and these are added after the array (separated by a comma) and contained in curly braces. The following is an example of the same line but with the colour changed to red, the width (weight) of the line set to 10 pixels, the opacity (transparency) set to 0.7 (on a scale of 0 (transparent) to 1 (opaque)), drawn with dashes of 20 pixels followed by a space of 15 pixels ( dashArray ) and with rounded corners where the lines join.

    And here’s our path with options…

    The full code of a live example of a map incorporating a the polyline and options is available online at bl.ocks.org or GitHub. A copy of the file (polyline-options-map) can be downloaded (in a zip file) when you download the book from Leanpub.

    Using multiple tile layers on your map

    Leaflet has a great feature that allows you to easily switch between tile layers when viewing your map. It’s built right in to leaflet.js and (as usual) it’s simple to implement.

    What we’re going to do is define the locations and appropriate attributions for two different sets of tiles and then tell leaflet to place a control on the map that allows us to switch. These different sets of tiles are referred to as ‘base layers’ and as such only one can be visible at any one time.

    The end result is a small icon in the top right hand corner that looks like this…

    And when we hover over it with our mouse it changes to show the different tile layers that we have defined for use.

    Layers control with mouse over

    There is no change to the HTML part of our code from the simple map example. The full code for this example can be found here on GitHub and a working example is here on bl.ocks.org. A copy of the file (layers-map.html) can be downloaded (in a zip file) when you download the book from Leanpub.

    The only change is in the JavaScript portion. and that looks like the following

    The first block of code sets up the links that we will use for attribution

    This just makes it easier to add later when juggling multiple layers.

    The we declare the URLs for the tiles and the attributions to display

    Again, by declaring these as variables, the process of defining the distinct layers is simplified.

    Which is what we do in the next block of code

    Declaring the layers like this is pretty handy since now we have a single variable for each layer that has all the information associated with it that is required to display the tiles for that layer.

    Now we add the map with the following lines of code

    It looks a lot like our simple map example, but in this case we have added in an option called layers and set that to the osmMap layer. This will be the initial layer that is shown on the map/ I have a note there to say that it’s a good idea to only have one of your base layers in there. That’s because if you put more than two it will load both layers when the map first loads and we don’t need to do that unnecessarily.

    The second last section of the code declares what our base layers are (there are other sorts of layers, but we’ll get to that later) and gives them appropriate text to display in the layers selection box.

    Then the last line adds the control for the baseLayers to the map

    For a fantastic way of finding different tile providers I can recommend heading to the preview page set up here.

    As I mentioned earlier, the full code for this example can be found here on GitHub and a working example is here on bl.ocks.org. A copy of the file (layers-map.html) can be downloaded (in a zip file) when you download the book from Leanpub.

    Overlaying information interactively on your map

    In the previous section we described how to declare and switch between more than one tile layer. Tile layers are described as ‘base layers’ in the sense that only one of them will be visible at a time and they will form the ‘base’ of the map.

    However, it is obvious that a really useful thing to be able to do would be to add information to our map so that different features or areas can be highlighted. These features or areas will exist on top of the base layer so that they have context. In Leaflet these can be set up as ‘overlays’ where an object or group of elements can be added to a map.

    Overlays are treated in much the same way as base layers. In the sense that they are declared and controlled using similar methods but Leaflet is clever enough to recognise that as many overlays as desired can exist on an individual base layer.

    What we aim to do is to add an overlay to one to our previous base layer switching example. The end result will be the same icon in the top right corner of the map

    But this time when we move our mouse over it, it will present an option to select ‘Interesting places’.

    And when selected it will show a series of markers with a connecting line.

    As with the base layer switching example, there is no change to the HTML part of our code from the simple map example. The full code for this example can be found here on GitHub and a working example is here on bl.ocks.org. A copy of the file (layers-map-overlays.html) can be downloaded (in a zip file) when you download the book from Leanpub.

    The only change is in the JavaScript portion. and that looks like the following

    There are only really two differences between this block of script and that for the base layers example.

    The first is where we define what our overlay will be made up of.

    Here we declare a new LayerGroup called coolPlaces ( var coolPlaces = new L.LayerGroup() ). Then we simply define a set of markers and a polyline (see the earlier sections on these two elements for a fuller description) and add them to our coolPlaces layer.

    The second change to our code is right at the end of the block of code.

    Here we declare our overlays (there is only one ( coolPlaces ), but you can add as many as you want) using var overlays = <<put overlays here>>. Then we add overlays to our layers control so that it knows to include the layer in the screen widget.

    And that’s all there is to it!

    As stated earlier, the full code for this example can be found here on GitHub (and there’s a copy in the appendices) an online example is here on bl.ocks.org and copy of the file (layers-map-overlays.html) can be downloaded (in a zip file) when you download the book from Leanpub.


    ImageOverlay

    Used to load and display a single image over specific bounds of the map. Extends Layer .

    Usage example

    Creation

    Factory Description
    L.imageOverlay( imageUrl, bounds, options?) Instantiates an image overlay object given the URL of the image and the geographical bounds it is tied to.

    Options

    Option Type Default Description
    opacity Number 1.0 The opacity of the image overlay.
    alt String '' Text for the alt attribute of the image (useful for accessibility).
    interactive Boolean false If true , the image overlay will emit mouse events when clicked or hovered.
    crossOrigin Boolean false If true, the image will have its crossOrigin attribute set to ''. This is needed if you want to access image pixel data.
    Option Type Default Description
    pane String 'overlayPane' By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
    attribution String null String to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".

    Events

    Event Data Description
    clickMouseEvent Fired when the user clicks (or taps) the layer.
    dblclickMouseEvent Fired when the user double-clicks (or double-taps) the layer.
    mousedownMouseEvent Fired when the user pushes the mouse button on the layer.
    mouseoverMouseEvent Fired when the mouse enters the layer.
    mouseoutMouseEvent Fired when the mouse leaves the layer.
    contextmenuMouseEvent Fired when the user right-clicks on the layer, prevents default browser context menu from showing if there are listeners on this event. Also fired on mobile when the user holds a single touch for a second (also called long press).
    Event Data Description
    addEvent Fired after the layer is added to a map
    removeEvent Fired after the layer is removed from a map
    Event Data Description
    popupopenPopupEvent Fired when a popup bound to this layer is opened
    popupclosePopupEvent Fired when a popup bound to this layer is closed
    Event Data Description
    tooltipopenTooltipEvent Fired when a tooltip bound to this layer is opened.
    tooltipcloseTooltipEvent Fired when a tooltip bound to this layer is closed.

    Methods

    Sets the opacity of the overlay.

    Brings the layer to the top of all overlays.

    Brings the layer to the bottom of all overlays.

    Changes the URL of the image.

    Update the bounds that this ImageOverlay covers

    Get the bounds that this ImageOverlay covers

    Get the img element that represents the ImageOverlay on the map

    Adds the layer to the given map

    Removes the layer from the map it is currently active on.

    Removes the layer from the given map

    Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

    Used by the attribution control , returns the attribution option.

    Binds a popup to the layer with the passed content and sets up the necessary event listeners. If a Function is passed it will receive the layer as the first argument and should return a String or HTMLElement .

    Removes the popup previously bound with bindPopup .

    Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

    Closes the popup bound to this layer if it is open.

    Opens or closes the popup bound to this layer depending on its current state.

    Returns true if the popup bound to this layer is currently open.

    Sets the content of the popup bound to this layer.

    Returns the popup bound to this layer.

    Binds a tooltip to the layer with the passed content and sets up the necessary event listeners. If a Function is passed it will receive the layer as the first argument and should return a String or HTMLElement .

    Removes the tooltip previously bound with bindTooltip .

    Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

    Closes the tooltip bound to this layer if it is open.

    Opens or closes the tooltip bound to this layer depending on its current state.

    Returns true if the tooltip bound to this layer is currently open.

    Sets the content of the tooltip bound to this layer.

    Returns the tooltip bound to this layer.

    Adds a listener function ( fn ) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick' ).

    Adds a set of type/listener pairs, e.g.

    Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on , you must pass the same context to off in order to remove the listener.

    Removes a set of type/listener pairs.

    Removes all listeners to all events on the object.

    Fires an event of the specified type. You can optionally provide an data object — the first argument of the listener function will contain its properties. The event can optionally be propagated to event parents.

    Returns true if a particular event type has any listeners attached to it.

    Behaves as on(…) , except the listener will only get fired once and then removed.

    Adds an event parent - an Evented that will receive propagated events

    Removes an event parent, so it will stop receiving propagated events

    An abstract class that contains options and constants shared between vector overlays (Polygon, Polyline, Circle). Do not use it directly. Extends Layer .

    Options

    Option Type Default Description
    stroke Boolean true Whether to draw stroke along the path. Set it to false to disable borders on polygons or circles.
    color String '#3388ff' Stroke color
    weight Number 3 Stroke width in pixels
    opacity Number 1.0 Stroke opacity
    lineCap String 'round' A string that defines shape to be used at the end of the stroke.
    lineJoin String 'round' A string that defines shape to be used at the corners of the stroke.
    dashArray String null A string that defines the stroke dash pattern. Doesn't work on Canvas -powered layers in some old browsers.
    dashOffset String null A string that defines the distance into the dash pattern to start the dash. Doesn't work on Canvas -powered layers in some old browsers.
    fill Boolean depends Whether to fill the path with color. Set it to false to disable filling on polygons or circles.
    fillColor String * Fill color. Defaults to the value of the color option
    fillOpacity Number 0.2 Fill opacity.
    fillRule String ɾvenodd' A string that defines how the inside of a shape is determined.
    renderer Renderer Use this specific instance of Renderer for this path. Takes precedence over the map's default renderer.
    className String null Custom class name set on an element. Only for SVG renderer.
    Option Type Default Description
    interactive Boolean true If false , the layer will not emit mouse events and will act as a part of the underlying map.
    Option Type Default Description
    pane String 'overlayPane' By default the layer will be added to the map's overlay pane. Overriding this option will cause the layer to be placed on another pane by default.
    attribution String null String to be shown in the attribution control, describes the layer data, e.g. "© Mapbox".

    Events

    Event Data Description
    clickMouseEvent Fired when the user clicks (or taps) the layer.
    dblclickMouseEvent Fired when the user double-clicks (or double-taps) the layer.
    mousedownMouseEvent Fired when the user pushes the mouse button on the layer.
    mouseoverMouseEvent Fired when the mouse enters the layer.
    mouseoutMouseEvent Fired when the mouse leaves the layer.
    contextmenuMouseEvent Fired when the user right-clicks on the layer, prevents default browser context menu from showing if there are listeners on this event. Also fired on mobile when the user holds a single touch for a second (also called long press).
    Event Data Description
    addEvent Fired after the layer is added to a map
    removeEvent Fired after the layer is removed from a map
    Event Data Description
    popupopenPopupEvent Fired when a popup bound to this layer is opened
    popupclosePopupEvent Fired when a popup bound to this layer is closed
    Event Data Description
    tooltipopenTooltipEvent Fired when a tooltip bound to this layer is opened.
    tooltipcloseTooltipEvent Fired when a tooltip bound to this layer is closed.

    Methods

    Redraws the layer. Sometimes useful after you changed the coordinates that the path uses.

    Changes the appearance of a Path based on the options in the Path options object.

    Brings the layer to the top of all path layers.

    Brings the layer to the bottom of all path layers.

    Adds the layer to the given map

    Removes the layer from the map it is currently active on.

    Removes the layer from the given map

    Returns the HTMLElement representing the named pane on the map. If name is omitted, returns the pane for this layer.

    Used by the attribution control , returns the attribution option.

    Binds a popup to the layer with the passed content and sets up the necessary event listeners. If a Function is passed it will receive the layer as the first argument and should return a String or HTMLElement .

    Removes the popup previously bound with bindPopup .

    Opens the bound popup at the specified latlng or at the default popup anchor if no latlng is passed.

    Closes the popup bound to this layer if it is open.

    Opens or closes the popup bound to this layer depending on its current state.

    Returns true if the popup bound to this layer is currently open.

    Sets the content of the popup bound to this layer.

    Returns the popup bound to this layer.

    Binds a tooltip to the layer with the passed content and sets up the necessary event listeners. If a Function is passed it will receive the layer as the first argument and should return a String or HTMLElement .

    Removes the tooltip previously bound with bindTooltip .

    Opens the bound tooltip at the specified latlng or at the default tooltip anchor if no latlng is passed.

    Closes the tooltip bound to this layer if it is open.

    Opens or closes the tooltip bound to this layer depending on its current state.

    Returns true if the tooltip bound to this layer is currently open.

    Sets the content of the tooltip bound to this layer.

    Returns the tooltip bound to this layer.

    Adds a listener function ( fn ) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick' ).

    Adds a set of type/listener pairs, e.g.

    Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on , you must pass the same context to off in order to remove the listener.

    Removes a set of type/listener pairs.

    Removes all listeners to all events on the object.

    Fires an event of the specified type. You can optionally provide an data object — the first argument of the listener function will contain its properties. The event can optionally be propagated to event parents.

    Returns true if a particular event type has any listeners attached to it.

    Behaves as on(…) , except the listener will only get fired once and then removed.

    Adds an event parent - an Evented that will receive propagated events

    Removes an event parent, so it will stop receiving propagated events


    Vector Data file formats list in GIS

    In GIS, we require some data formats to express the geographical features, which mainly are of two types Raster and Vector data formats. These data sources also has multiple file formats in them which are often used to express the geographical features. In this post we are looking forward to see the List of Vector Data file formats in GIS. Vector considers the geographical features as geometrical shape and express them by different types of geometry.


    PosAnimation

    Used internally for panning animations, utilizing CSS3 Transitions for modern browsers and a timer fallback for IE6-9.

    Usage example

    Constructor

    Events

    Event Data Description
    startEvent Fired when the animation starts
    stepEvent Fired continuously during the animation.
    endEvent Fired when the animation ends.

    Methods

    Run an animation of a given element to a new position, optionally setting duration in seconds ( 0.25 by default) and easing linearity factor (3rd argument of the cubic bezier curve, 0.5 by default).

    Stops the animation (if currently running).

    Adds a listener function ( fn ) to a particular event type of the object. You can optionally specify the context of the listener (object the this keyword will point to). You can also pass several space-separated types (e.g. 'click dblclick' ).

    Adds a set of type/listener pairs, e.g.

    Removes a previously added listener function. If no function is specified, it will remove all the listeners of that particular event from the object. Note that if you passed a custom context to on , you must pass the same context to off in order to remove the listener.

    Removes a set of type/listener pairs.

    Removes all listeners to all events on the object.

    Fires an event of the specified type. You can optionally provide an data object — the first argument of the listener function will contain its properties. The event can optionally be propagated to event parents.

    Returns true if a particular event type has any listeners attached to it.

    Behaves as on(…) , except the listener will only get fired once and then removed.