1 of 31

Maps

And Drupal

2 of 31

Artem Sylchuk

One of the five

3 of 31

A map. What is it?

4 of 31

5 of 31

6 of 31

Mercator projection & Google Web Mercator

7 of 31

Some math and EPSG:3857

Ellipsoid:

x=a×λ

y=a×ln[tan(π/4+φ/2)×((1-e×sinφ)/(1+e×sinφ))^(e/2)]

Sphere:

x=a×λ

y=a×ln[tan(π/4+φ/2)]

λ — lon, rad; φ — lat, rad. a - semimajor axis of the ellipsoid. e - the value of the eccentricity of the ellipsoid (the ratio of the major and minor semi-axes).

8 of 31

9 of 31

http://imgs.xkcd.com/comics/map_projections.png

10 of 31

We need a canvas. Map tiles

11 of 31

x/y/z

Zoom levels are related to each other by powers of four:

  • z0 contains 1 tile.
  • z1 contains 4 tiles.
  • z2 contains 16 tile.

Because of this exponential relationship the amount of detail increases at every zoom level, but so does the amount of bandwidth and storage required to serve up tiles.

For example, a map at z15, about when city building footprints first become visible, requires about 1.1 billion tiles to cover the entire world. At z17, just two zoom levels greater, the world requires 17 billion

12 of 31

http://maps.stamen.com/

13 of 31

Put a point. And one more. And more

14 of 31

Well Known

GEOMETRYCOLLECTION(POINT(4 6),LINESTRING(4 6,7 10))�POINT ZM (1 1 5 60)�POINT M (1 1 80)�POINT EMPTY�MULTIPOLYGON EMPTY�CIRCULARSTRING(1 5, 6 2, 7 3)�COMPOUNDCURVE(CIRCULARSTRING(0 0,1 1,1 0),(1 0,0 1))�CURVEPOLYGON(CIRCULARSTRING(-2 0,-1 -1,0 0,1 -1,2 0,0 2,-2 0),(-1 0,0 0.5,1 0,0 1,-1 0))�MULTICURVE((5 5,3 5,3 3,0 3),CIRCULARSTRING(0 0,2 1,2 2))�TRIANGLE((0 0 0,0 1 0,1 1 0,0 0 0))�TIN (((0 0 0, 0 0 1, 0 1 0, 0 0 0)), ((0 0 0, 0 1 0, 1 1 0, 0 0 0)))�POLYHEDRALSURFACE Z (� ((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0)),� ((0 0 0, 0 1 0, 0 1 1, 0 0 1, 0 0 0)),� ((0 0 0, 1 0 0, 1 0 1, 0 0 1, 0 0 0)),� ((1 1 1, 1 0 1, 0 0 1, 0 1 1, 1 1 1)),� ((1 1 1, 1 0 1, 1 0 0, 1 1 0, 1 1 1)),� ((1 1 1, 1 1 0, 0 1 0, 0 1 1, 1 1 1))� )

15 of 31

GeoJSON

{ "type": "FeatureCollection",� "features": [� { "type": "Feature",� "geometry": {"type": "Point", "coordinates": [102.0, 0.5]},� "properties": {"prop0": "value0"}� },� { "type": "Feature",� "geometry": {� "type": "LineString",� "coordinates": [� [102.0, 0.0], [103.0, 1.0], [104.0, 0.0], [105.0, 1.0]� ]� },� "properties": {� "prop0": "value0",� "prop1": 0.0� }� },� { "type": "Feature",� "geometry": {� "type": "Polygon",� "coordinates": [� [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0],� [100.0, 1.0], [100.0, 0.0] ]� ]� },� "properties": {� "prop0": "value0",� "prop1": {"this": "that"}� }� }� ]� }

16 of 31

Stop. Show me something .

17 of 31

Google. Yandex. Bing.

18 of 31

OpenStreetMap. Data Providers .

19 of 31

20 of 31

OpenLayers, Leaflet

21 of 31

22 of 31

Mapbox .

23 of 31

How to ?

24 of 31

PostGIS

  • Geometry types for Points, LineStrings, Polygons, MultiPoints, MultiLineStrings, MultipPolygons and GeometryCollections.
  • Spatial predicates for determining the interactions of geometries using the 3x3 DE-9IM (provided by the GEOSsoftware library).
  • Spatial operators for determining geospatial measurements like area, distance, length and perimeter.
  • Spatial operators for determining geospatial set operations, like union, difference, symmetric difference and buffers (provided by GEOS).
  • R-tree-over-GiST (Generalized Search Tree) spatial indexes for high speed spatial querying.
  • Index selectivity support, to provide high performance query plans for mixed spatial/non-spatial queries.
  • For raster data, PostGIS WKT Raster (now integrated into PostGIS 2.0+ and renamed PostGIS Raster)

25 of 31

SELECT� neighborhoods.name AS neighborhood_name,� Sum(census.popn_total) AS population,� 100.0 * Sum(census.popn_white) / Sum(census.popn_total) AS white_pct,� 100.0 * Sum(census.popn_black) / Sum(census.popn_total) AS black_pct�FROM nyc_neighborhoods AS neighborhoods�JOIN nyc_census_blocks AS census�ON ST_Intersects(neighborhoods.geom, census.geom)�WHERE neighborhoods.boroname = 'Manhattan'GROUP BY neighborhoods.name�ORDER BY white_pct DESC;

26 of 31

GeoPHP

27 of 31

Solr

<fieldType name="location_rpt" class="solr.SpatialRecursivePrefixTreeFieldType"

spatialContextFactory="org.locationtech.spatial4j.context.jts.JtsSpatialContextFactory"

autoIndex="true"

validationRule="repairBuffer0"

distErrPct="0.025"

maxDistErr="0.001"

distanceUnits="kilometers" />

&q=*:*&sfield=store&pt=45.15,-93.85&facet.query={!frange l=0 u=5}geodist()&facet.query={!frange l=5.001 u=3000}geodist()

28 of 31

29 of 31

30 of 31

31 of 31

This is the end.