Tôi mới tham gia vào thế giới GIS hấp dẫn và tôi đã nghiên cứu toàn bộ chủ đề trong vài ngày qua. Mục tiêu của tôi là phục vụ các bản đồ trên toàn hành tinh với dữ liệu OSM trên các máy chủ của riêng tôi.
Ngăn xếp của tôi là:
- Postgres + Postgis - Để lưu trữ, chuyển đổi và xử lý dữ liệu GIS.
- Mapnik - Thư viện kết xuất gạch
- Tilestache - Phục vụ và gạch bộ đệm
- Nginx - Đảo ngược proxy thành Tilestache
- Tờ rơi ( khách hàng bản đồ Slippy )
Để nhập và định kiểu dữ liệu OSM, tôi đang sử dụng
- Tệp PBF (Trích xuất / Hành tinh)
- osm2pgsql
- CartoCSS
- openstreetmap-carto
- Kosmtik - GUI GUI để phát triển / gỡ lỗi
Vì tệp hành tinh đầy đủ là rất lớn, tôi hiện đang sử dụng trích xuất Sao Paulo , đủ tốt / nhỏ để thử nghiệm.
Trước khi tôi gặp phải vấn đề tôi gặp phải, tôi sẽ hướng dẫn các bước tôi đã thực hiện cho đến nay:
Những gì đã làm việc
PostgreSQL và PostGIS được cài đặt đúng. Tôi đang sử dụng 9.6 cho cái trước, 2.3 cho cái sau. Tôi cũng đã thêm postgis_topology
và các hstore
phần mở rộng, sẽ được sử dụng sau.
Tôi đã cài đặt osm2pgsql 0.92.0. Để nhập chiết xuất Sao Paulo, tôi sử dụng
osm2pgsql -G U <user> -d <db> -C 1000 -W --hstore --style openstreetmap-carto.style --tag-transform-script openstreetmap-carto.lua <pbf>
Các hstore
, style
và tag-transform-script
đối số được yêu cầu cho việc sử dụng thích hợp của phong cách OSM, như mô tả ở đây .
Như được mô tả trong quá trình cài đặt openstreetmap-carto, tôi cũng đã thêm các chỉ mục tùy chỉnh và tải xuống các shapefile và phông chữ cần thiết (ngoại trừ các biểu tượng cảm xúc).
Tôi đã xác minh dữ liệu trích xuất được tải chính xác trên cơ sở dữ liệu bằng cách sử dụng QGIS. Tôi đã có thể xem và truy vấn với tất cả các điểm, đa giác, đường và đường. Tất cả đều ở đó.
Các vấn đề
Bước tiếp theo là kết xuất các ô và đó là nơi tôi gặp sự cố. Tôi có mapnik và python-mapnik 3.x, cũng như carto 0.18.2.
Từ project.mml của OSM , tôi đã tạo dự án của riêng mình bằng cách sử dụng carto
. Tôi đã thực hiện các thay đổi sau đây cho kết quả:
- Thêm tên người dùng Postgres (Tham số
user
trên XML của Mapnik ). Thông tin kết nối còn lại được lấy từ ~ / .pgpass . - Thay thế thư mục tương đối
data/<shape>.shp
thành/full/path/data/<shape>.shp
- Thay thế thư mục tương đối
symbols/<symbol>.svg
thành/full/path/symbols/<symbol>.svg
Tôi sắp xếp các đơn vị đã kiểm tra các thay đổi này: các thư mục không chính xác cho shapefiles và các ký hiệu sẽ phát sinh lỗi khi Mapnik cố tải kiểu. Áp dụng tương tự cho thông tin DB không chính xác.
Và đây là vấn đề: mọi ô được Mapnik hiển thị là "trống" (nền màu xanh lam, là nền được xác định cho OSM). Đây là những gì tôi đã cố gắng khắc phục vấn đề này:
Những điều tôi đã thử
Có thể phong cách tạo ra không hợp lệ bằng cách nào đó. Có thể một số đa giác / hình dạng (đại dương?) Đang che phủ một hình khác.
Tôi đã cài đặt Kosmtik và nó hoạt động tốt! Tôi đã có thể duyệt qua trích xuất, kiểm tra dữ liệu, phóng to và thu nhỏ trên tất cả các cấp.
Có lẽ tôi đang tạo gạch ở vị trí sai
Tôi đã thiết lập TileStache với Mapnik là nhà cung cấp. Sau đó, tôi đã thiết lập quy tắc chuyển hướng từ http://[abc].tile.openstreetmap.org
sang http://myserver/<layer>
sử dụng switcheroo, như được mô tả ở đây . Điều này có nghĩa là việc truy cập openstreetmaps.org
sẽ có tất cả các ô hiển thị trên máy chủ của tôi.
Thật thú vị, zoom 1 hoạt động (cái có 4 gạch). Tôi cho rằng nó chỉ sử dụng shapefile hành tinh / thế giới, được tải xuống với phong cách. Tất cả những thứ khác, bất kể thu phóng hay vị trí, đều chuyển thành "trống". Vì vậy, ngay cả khi duyệt tại vị trí của trích xuất, nó sẽ không hiển thị chính xác.
Lưu ý rằng, khi sử dụng Kosmtik, tôi có thể thấy tên của trích xuất từ mức thấp như zoom 4.
Có lẽ tôi đang tạo gạch ở vị trí sai
Dự đoán là khó. Có lẽ có một cái gì đó đang bị "dịch sai" ở đâu đó.
Vì vậy, tôi đã phân tích các yêu cầu mà Kosmtik đang thực hiện (vì chúng đang hoạt động). Nó sử dụng thư viện Modestmaps, dịch sang định dạng Slippy ( <zoom>/<x>/<y>
), cùng định dạng được sử dụng bởi Leaflet, TileStache và openstreetmap.org
.
Chẳng hạn, yêu cầu 17/48561/74357.png
trên Kosmtik hoạt động, nhưng cùng một ô trả về là "trống" trên TileStache. Giả thuyết của tôi là bằng cách nào đó, TileStache đã dịch nó sang tọa độ khác, bên ngoài khu vực giải nén. (Mặc dù TileStache đã sử dụng "Mercator hình cầu" làm hình chiếu).
Vì vậy, tôi đã quyết định sử dụng trực tiếp các ràng buộc trăn của Mapnik. Cho đến nay tôi đã xử lý ba loại hình chiếu khác nhau, đây là những gì tôi biết về chúng. Vui long sửa cho tôi nêu tôi sai:
- EPSG4326 / WGS84 - Phép chiếu lon / lat thông thường, giống như được sử dụng trên GPS. Đơn vị là độ.
- EPSG3857 / {Web, Google, Pseudo} mercator / 900913 - Được sử dụng trên hầu hết các bản đồ web lát gạch. Đơn vị tính bằng mét (không phải "thực", vì nó biến dạng nặng gần các cực).
- "Định dạng Slippy" - Không phải là một hình chiếu, mà là một định dạng khác để dịch.
Vì vậy, Slippy 17/48561/74357
sẽ ở gần -46.632(lon), -23.531(lat)
trên EPSG4326 và gần -5191050.49, -2696361.67
với EPSG3875 / Google mercator.
Sử dụng python, tôi đã tạo các ô tọa độ này trực tiếp tại Mapnik. Kết quả luôn là gạch trống. Tôi tin rằng tôi đang sử dụng các dự đoán chính xác (sẽ nói thêm về điều này sau).
Đầu tiên, một điều cần lưu ý. Rõ ràng vấn đề không nằm ở Mapnik, cũng không phải phong cách. Đối với một, Kosmtik sử dụng Mapnik làm phụ trợ và nó hoạt động tốt. Thứ hai, nếu tôi cố tình tạo ra một ô bên ngoài khu vực trích xuất trên Kostmik, tôi sẽ nhận được một ô trống, như mong đợi.
Điều này khiến tôi tin rằng tôi đang sử dụng phép chiếu sai trong tập lệnh python và TileStache của Mapnik. Trước khi hiển thị mã, một nhận xét về OSM (một lần nữa, vui lòng sửa cho tôi nếu tôi sai):
- Dữ liệu "gốc" của OSM được lưu trữ trong EPSG4326
- osm2pgsql nhập dữ liệu OSM dưới dạng EPSG3857 và đó là phép chiếu trên Postgis.
- Phong cách của Mapnik (XML) có hai hình chiếu, đầu vào và đầu ra, được giải thích tại đây :
- Phép chiếu đầu vào được xác định tại đối tượng Bản đồ và là "hệ tọa độ trong đó bản đồ được hiển thị"
- Phép chiếu đầu ra được xác định tại đối tượng Layer và phải giống với dữ liệu của tôi.
Kết quả XML của Mapnik của tôi có:
<Map srs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over" background-color="#b5d0d0">
#snip#
<Layer name="world" #snip# srs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over">
Vì vậy, theo cách tôi nhìn thấy, cả hai phép chiếu đầu vào và đầu ra đều ở dạng "merc" (3857), và điều đó đúng! Dữ liệu của tôi được lưu trữ với 3857 và bản đồ kết quả dự kiến là 3857.
Cuối cùng, đây là các cuộc gọi Mapnik khác nhau mà tôi đã thử:
Box2d với tọa độ 3857:
map = mapnik.Map(800, 800)
bbox = Box2d(-5191050.49, -2696361.67, -5191059.49, -2696370.70)
mapnik.load_map(map, '/path/to/style.xml')
map.zoom_to_box(bbox)
mapnik.render_to_file(map, 'output.png') # Blank
Box2d với tọa độ 4326 được chuyển thành 3857
merc = mapnik.Projection('+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs +over')
longlat = mapnik.Projection('+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs')
bbox = mapnik.Box2d(-23.53, -46.63, -24.03, -47.03)
transform = mapnik.ProjTransform(longlat, merc)
merc_bbox = transform.forward(bbox)
# load, zoom, render -> Blank
Tôi cũng đã thử với nhiều phong cách khác nhau. Kết quả luôn trống, nhưng điều đó thật bất ngờ vì tôi tin rằng các tọa độ này sẽ nằm trong trích xuất của tôi. Khi cố gắng kết xuất tọa độ bên ngoài trích xuất, nó sẽ hiển thị chính xác dưới dạng trống.
Dù sao, tôi bị lạc và tôi tự hỏi nếu có ai có thể làm sáng tỏ, tôi phải thiếu một cái gì đó. Nhưng cho đến nay, tôi đã chiến đấu với vấn đề này trong hơn 24 giờ và tôi không biết điều gì có thể sai.