Контейнер с патченым imposm3 и скриптом загрузки
commit
2ecaeee50a
|
@ -0,0 +1,36 @@
|
|||
FROM debian:sid AS build
|
||||
MAINTAINER Vitaliy Filippov <vitalif@mail.ru>
|
||||
|
||||
ADD etc /etc
|
||||
|
||||
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y -q \
|
||||
less wget sudo curl unzip git mc ca-certificates \
|
||||
build-essential golang-go libleveldb-dev libgeos-dev && \
|
||||
apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ADD split-ways.diff /root/
|
||||
|
||||
# Специальный патченый imposm3
|
||||
RUN cd /root && git clone https://github.com/omniscale/imposm3/ go/src/github.com/omniscale/imposm3 && \
|
||||
cd go/src/github.com/omniscale/imposm3 && git checkout c87a9a2b5761787a637e0fa73df9d4331846587d && \
|
||||
patch -p1 < /root/split-ways.diff && make build
|
||||
|
||||
RUN dpkg -l | grep libgeos | awk '{print $2}' >> /root/pkg.lst
|
||||
|
||||
FROM debian:sid AS run
|
||||
MAINTAINER Vitaliy Filippov <vitalif@mail.ru>
|
||||
|
||||
ADD etc /etc
|
||||
|
||||
COPY --from=build /root/pkg.lst /root/
|
||||
|
||||
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y -q \
|
||||
less wget sudo curl unzip git mc \
|
||||
`cat /root/pkg.lst` libleveldb1v5 libdbd-pg-perl && \
|
||||
apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY --from=build /root/go/src/github.com/omniscale/imposm3/imposm /usr/bin/imposm3
|
||||
|
||||
ADD home /home
|
||||
|
||||
CMD /home/osm_loader.pl
|
|
@ -0,0 +1,13 @@
|
|||
## Building
|
||||
|
||||
```
|
||||
docker build -t imposm3 .
|
||||
```
|
||||
|
||||
## Running
|
||||
|
||||
```
|
||||
docker run -it -d --restart always \
|
||||
-v /home/test/russia-latest.osm.pbf:/home/valhalla/data.osm.pbf \
|
||||
--name valhalla -p 8002:8002 valhalla
|
||||
```
|
|
@ -0,0 +1,4 @@
|
|||
APT::Install-Suggests false;
|
||||
APT::Install-Recommends false;
|
||||
Acquire::Retries 5;
|
||||
Binary::apt::APT::Keep-Downloaded-Packages "false";
|
|
@ -0,0 +1,82 @@
|
|||
# Нужно применять с патченым imposm3 (патч тут же, imposm3-split-ways.diff)
|
||||
# Иначе, несмотря на area_tags и linear_tags, здания оказываются в linestring
|
||||
|
||||
areas:
|
||||
area_tags: [building, landuse, leisure, natural, aeroway]
|
||||
linear_tags: [highway, barrier]
|
||||
|
||||
tags:
|
||||
load_all: true
|
||||
exclude:
|
||||
- created_by
|
||||
- source
|
||||
|
||||
tables:
|
||||
point:
|
||||
type: point
|
||||
fields:
|
||||
- name: osm_id
|
||||
type: id
|
||||
- name: geometry
|
||||
type: geometry
|
||||
- name: tags
|
||||
type: hstore_tags
|
||||
mapping:
|
||||
__any__:
|
||||
- __any__
|
||||
linestring:
|
||||
type: linestring
|
||||
fields:
|
||||
- name: osm_id
|
||||
type: id
|
||||
- name: geometry
|
||||
type: geometry
|
||||
- name: tags
|
||||
type: hstore_tags
|
||||
mapping:
|
||||
__any__:
|
||||
- __any__
|
||||
polygon:
|
||||
type: polygon
|
||||
fields:
|
||||
- name: osm_id
|
||||
type: id
|
||||
- name: geometry
|
||||
type: geometry
|
||||
- name: tags
|
||||
type: hstore_tags
|
||||
mapping:
|
||||
__any__:
|
||||
- __any__
|
||||
relation_member:
|
||||
type: relation_member
|
||||
fields:
|
||||
- name: osm_id
|
||||
type: id
|
||||
- name: member
|
||||
type: member_id
|
||||
- name: index
|
||||
type: member_index
|
||||
- name: type
|
||||
type: member_type
|
||||
- name: role
|
||||
type: member_role
|
||||
mapping:
|
||||
__any__:
|
||||
- __any__
|
||||
relation:
|
||||
type: relation
|
||||
fields:
|
||||
- name: osm_id
|
||||
type: id
|
||||
- key: type
|
||||
name: type
|
||||
type: string
|
||||
- key: name
|
||||
name: name
|
||||
type: string
|
||||
- name: tags
|
||||
type: hstore_tags
|
||||
mapping:
|
||||
__any__:
|
||||
- __any__
|
|
@ -0,0 +1,283 @@
|
|||
#!/usr/bin/perl
|
||||
# Configuration in env: OSM_CACHE_DIR, OSM_CARTO_VERSION, URL_LATEST, URL_UPDATES,
|
||||
# plus PG_ENV_OSM_{DB,HOST,PORT,USER,PASSWORD} like in README for the render server itself
|
||||
|
||||
use strict;
|
||||
use DBI;
|
||||
use POSIX;
|
||||
|
||||
my $dbh;
|
||||
my $dir = $ENV{OSM_CACHE_DIR} || '/var/lib/mod_tile/downloads';
|
||||
my $method = $ENV{OSM_METHOD} || 'osm2pgsql-carto';
|
||||
my $url_latest = $ENV{URL_LATEST} || 'http://download.geofabrik.de/russia-latest.osm.pbf';
|
||||
my $url_updates = $ENV{URL_UPDATES} || 'http://download.geofabrik.de/russia-updates';
|
||||
|
||||
if (!$ENV{PG_ENV_OSM_DB})
|
||||
{
|
||||
fatal("OSM database not specified");
|
||||
}
|
||||
|
||||
info("Started OSM update for database: $ENV{PG_ENV_OSM_DB}");
|
||||
|
||||
if ($method ne 'osm2pgsql-carto' && $method ne 'imposm3-all')
|
||||
{
|
||||
fatal("Incorrect OSM update mode: $method");
|
||||
}
|
||||
|
||||
-e $dir || mkdir($dir);
|
||||
chdir $dir or fatal("Failed to chdir $dir");
|
||||
eval { run_update() };
|
||||
if ($@)
|
||||
{
|
||||
fatal("$@");
|
||||
}
|
||||
exit(0);
|
||||
|
||||
sub run_update
|
||||
{
|
||||
my $state = parse_geofabrik_state($url_updates, $dir);
|
||||
my $dbh = DBI->connect(
|
||||
'dbi:Pg:dbname='.$ENV{PG_ENV_OSM_DB}.';host='.$ENV{PG_ENV_OSM_HOST}.';port='.($ENV{PG_ENV_OSM_PORT}||5432),
|
||||
$ENV{PG_ENV_OSM_USER}, $ENV{PG_ENV_OSM_PASSWORD}, {AutoCommit => 0, RaiseError => 1}
|
||||
);
|
||||
my ($version) = eval { $dbh->selectrow_array(
|
||||
'SELECT value FROM replication_state WHERE name=? FOR UPDATE', {}, 'osm_version'
|
||||
) };
|
||||
if (!$version)
|
||||
{
|
||||
if (!$ENV{OSM_INIT})
|
||||
{
|
||||
fatal("Current OSM version missing, run with OSM_INIT=1 environment variable to initialize");
|
||||
}
|
||||
$dbh->rollback; # иначе postgresql пишет "statements until the end ignored"
|
||||
# создаём таблицу и оставляем её заблокированной
|
||||
init_state($dbh, $state);
|
||||
$dbh->do('CREATE EXTENSION IF NOT EXISTS postgis');
|
||||
$dbh->do('CREATE EXTENSION IF NOT EXISTS hstore');
|
||||
# качаем дамп
|
||||
my ($fn) = $url_latest =~ /([^\/]+)$/so;
|
||||
$fn =~ s/^([^\.]+)/$1-$state->{timestamp}/;
|
||||
info("Downloading $url_latest");
|
||||
system("curl -s -C - -f '$url_latest' -o $dir/$fn");
|
||||
if ($? || !-e "$dir/$fn")
|
||||
{
|
||||
fatal("Failed to download $url_latest");
|
||||
}
|
||||
if ($method eq 'osm2pgsql-carto')
|
||||
{
|
||||
init_osm2pgsql($dbh, $state->{timestamp} . ' ' . $state->{sequenceNumber}, "$dir/$fn");
|
||||
}
|
||||
else
|
||||
{
|
||||
init_imposm3($dbh, $state->{timestamp} . ' ' . $state->{sequenceNumber}, "$dir/$fn");
|
||||
}
|
||||
$dbh->commit;
|
||||
info("OSM database initialized with version: ".$state->{timestamp});
|
||||
}
|
||||
else
|
||||
{
|
||||
my $apply = load_geofabrik_deltas($version, $state, $url_updates, $dir);
|
||||
chdir($dir);
|
||||
if ($method eq 'osm2pgsql-carto')
|
||||
{
|
||||
apply_deltas_osm2pgsql($apply);
|
||||
}
|
||||
else
|
||||
{
|
||||
apply_deltas_imposm3($apply);
|
||||
}
|
||||
update_state($dbh, $state);
|
||||
$dbh->commit;
|
||||
info("OSM database updated to version: ".$state->{timestamp});
|
||||
if ($ENV{OSM_EXPIRE})
|
||||
{
|
||||
system("cat $dir/expire.list | render_expired --map=osm_carto --touch-from=11");
|
||||
system("cat $dir/expire.list | render_expired --map=osm_bright --touch-from=11");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub parse_geofabrik_state
|
||||
{
|
||||
my ($url_updates, $dir) = @_;
|
||||
system("curl -s -f '$url_updates/state.txt' -o $dir/state.txt");
|
||||
if (!-r "$dir/state.txt")
|
||||
{
|
||||
fatal("Error downloading $url_updates/state.txt");
|
||||
}
|
||||
else
|
||||
{
|
||||
my $state;
|
||||
if (open FD, "<$dir/state.txt")
|
||||
{
|
||||
local $/ = undef;
|
||||
$state = <FD>;
|
||||
close FD;
|
||||
$state = { map { (split /\s*=\s*/, $_, 2) } grep { !/^\s*(#.*)?$/so && /=/so } split /\n/, $state };
|
||||
if (!$state->{timestamp} || !$state->{sequenceNumber})
|
||||
{
|
||||
fatal("State file incorrect, should have timestamp=<ISO8601 date> and sequenceNumber=<integer>");
|
||||
}
|
||||
$state->{timestamp} =~ s/\\//g;
|
||||
return $state;
|
||||
}
|
||||
}
|
||||
fatal("Error downloading $url_updates/state.txt");
|
||||
}
|
||||
|
||||
sub load_geofabrik_deltas
|
||||
{
|
||||
my ($version, $state, $url_updates, $dir) = @_;
|
||||
my ($timestamp, $i) = split /\s+/, $version;
|
||||
my $apply = [];
|
||||
while ($i <= $state->{sequenceNumber})
|
||||
{
|
||||
my $subdir = sprintf("%03d/%03d", $i / 1000000, ($i / 1000) % 1000);
|
||||
my $fn = sprintf("%03d.osc.gz", $i % 1000);
|
||||
info("Downloading $url_updates/$subdir/$fn");
|
||||
system("mkdir -p $dir/$subdir && curl -C - -s -f '$url_updates/$subdir/$fn' -o $dir/$subdir/$fn");
|
||||
if (-e "$dir/$subdir/$fn")
|
||||
{
|
||||
push @$apply, "$subdir/$fn";
|
||||
}
|
||||
else
|
||||
{
|
||||
fatal("Delta not available: $url_updates/$subdir/$fn\n");
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
return $apply;
|
||||
}
|
||||
|
||||
sub init_state
|
||||
{
|
||||
my ($dbh, $state) = @_;
|
||||
$dbh->do('CREATE TABLE IF NOT EXISTS replication_state (name varchar(1024) not null primary key, value text not null)');
|
||||
$dbh->do(
|
||||
'INSERT INTO replication_state (name, value) VALUES (?, ?)',
|
||||
{}, 'osm_version', $state->{timestamp} . ' ' . $state->{sequenceNumber}
|
||||
);
|
||||
}
|
||||
|
||||
sub update_state
|
||||
{
|
||||
my ($dbh, $state) = @_;
|
||||
$dbh->do(
|
||||
'UPDATE replication_state SET value=? WHERE name=?',
|
||||
{}, $state->{timestamp} . ' ' . $state->{sequenceNumber}, 'osm_version'
|
||||
);
|
||||
}
|
||||
|
||||
sub init_osm2pgsql
|
||||
{
|
||||
my ($dbh, $path) = @_;
|
||||
my $carto_dir = '/usr/share/mapnik/openstreetmap-carto-'.$ENV{OSM_CARTO_VERSION};
|
||||
if (!$ENV{OSM_CARTO_VERSION})
|
||||
{
|
||||
fatal("osm-carto path not specified");
|
||||
}
|
||||
my $cmd =
|
||||
"PGPASSWORD='".$ENV{PG_ENV_OSM_PASSWORD}."' osm2pgsql -I -s -c --hstore".
|
||||
" --style $carto_dir/openstreetmap-carto.style".
|
||||
" --tag-transform-script $carto_dir/openstreetmap-carto.lua".
|
||||
" -C 4000 -G -H '".$ENV{PG_ENV_OSM_HOST}."' -U '".$ENV{PG_ENV_OSM_USER}."' -d '".$ENV{PG_ENV_OSM_DB}."'".
|
||||
" -P ".($ENV{PG_ENV_OSM_PORT} || 5432)." '$path'";
|
||||
system($cmd);
|
||||
if ($?)
|
||||
{
|
||||
fatal("$cmd failed");
|
||||
}
|
||||
local $/ = undef;
|
||||
my $fd;
|
||||
open $fd, "$carto_dir/indexes.sql";
|
||||
for my $index (split /;\s*/, <$fd>)
|
||||
{
|
||||
$dbh->do($index);
|
||||
}
|
||||
close $fd;
|
||||
}
|
||||
|
||||
sub init_imposm3
|
||||
{
|
||||
my ($dbh, $path) = @_;
|
||||
my $cmd =
|
||||
"imposm3 import -connection 'postgis://".$ENV{PG_ENV_OSM_USER}.":".$ENV{PG_ENV_OSM_PASSWORD}.
|
||||
"@".$ENV{PG_ENV_OSM_HOST}.(($ENV{PG_ENV_OSM_PORT}||5432) != 5432 ? ":".$ENV{PG_ENV_OSM_PORT} : "").
|
||||
"/".$ENV{PG_ENV_OSM_DB}."' -cachedir '".$ENV{OSM_CACHE_DIR}."/imposm3-cache' -mapping '/home/imposm3-all.yml' -srid 4326 -diff".
|
||||
" -read '$path' -write";
|
||||
system($cmd);
|
||||
if ($?)
|
||||
{
|
||||
fatal("$cmd failed");
|
||||
}
|
||||
my $indexes = "SET SEARCH_PATH TO import, public;
|
||||
CREATE INDEX IF NOT EXISTS osm_polygon_area ON osm_polygon (st_area(geometry));
|
||||
CREATE INDEX IF NOT EXISTS osm_point_tags ON osm_point USING gin (tags);
|
||||
CREATE INDEX IF NOT EXISTS osm_linestring_tags ON osm_linestring USING gin (tags);
|
||||
CREATE INDEX IF NOT EXISTS osm_polygon_tags ON osm_polygon USING gin (tags);
|
||||
CREATE INDEX IF NOT EXISTS osm_relation_tags ON osm_relation USING gin (tags);
|
||||
CREATE INDEX IF NOT EXISTS osm_point_text ON osm_point USING gin (to_tsvector('russian', tags::text));
|
||||
CREATE INDEX IF NOT EXISTS osm_linestring_text ON osm_linestring USING gin (to_tsvector('russian', tags::text));
|
||||
CREATE INDEX IF NOT EXISTS osm_polygon_text ON osm_polygon USING gin (to_tsvector('russian', tags::text));
|
||||
CREATE INDEX IF NOT EXISTS osm_relation_text ON osm_relation USING gin (to_tsvector('russian', tags::text))";
|
||||
foreach my $index (split /;\n/, $indexes)
|
||||
{
|
||||
$dbh->do($index);
|
||||
}
|
||||
}
|
||||
|
||||
sub apply_deltas_osm2pgsql
|
||||
{
|
||||
my ($apply, $carto_dir) = @_;
|
||||
if (@$apply)
|
||||
{
|
||||
my $cmd =
|
||||
"PGPASSWORD='".$ENV{PG_ENV_OSM_PASSWORD}."' osm2pgsql --append -e15 -o '".$ENV{OSM_CACHE_DIR}."/expire.list' -I -s --hstore".
|
||||
" --style $carto_dir/openstreetmap-carto.style".
|
||||
" --tag-transform-script $carto_dir/openstreetmap-carto.lua".
|
||||
" -C 4000 -G -H '".$ENV{PG_ENV_OSM_HOST}."' -U '".$ENV{PG_ENV_OSM_USER}."' -d '".$ENV{PG_ENV_OSM_DB}."'".
|
||||
" -P ".($ENV{PG_ENV_OSM_PORT} || 5432)." '".join("' '", @$apply)."'";
|
||||
system($cmd);
|
||||
if ($?)
|
||||
{
|
||||
fatal("$cmd failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub apply_deltas_imposm3
|
||||
{
|
||||
my ($apply) = @_;
|
||||
my $carto_dir = '/usr/share/mapnik/openstreetmap-carto-'.$ENV{OSM_CARTO_VERSION};
|
||||
if (!$ENV{OSM_CARTO_VERSION})
|
||||
{
|
||||
fatal("osm-carto path not specified");
|
||||
}
|
||||
if (@$apply)
|
||||
{
|
||||
my $cmd =
|
||||
"imposm3 diff -connection 'postgis://".$ENV{PG_ENV_OSM_USER}.":".$ENV{PG_ENV_OSM_PASSWORD}.
|
||||
"@".$ENV{PG_ENV_OSM_HOST}.(($ENV{PG_ENV_OSM_PORT}||5432) != 5432 ? ":".$ENV{PG_ENV_OSM_PORT} : "").
|
||||
"/".$ENV{PG_ENV_OSM_DB}."' -cachedir '".$ENV{OSM_CACHE_DIR}."/imposm3-cache' -mapping '/home/imposm3-all.yml' -srid 4326".
|
||||
" '".join("' '", @$apply)."'";
|
||||
system($cmd);
|
||||
if ($?)
|
||||
{
|
||||
fatal("$cmd failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub info
|
||||
{
|
||||
my ($msg) = @_;
|
||||
print POSIX::strftime("%Y-%m-%d %H:%M:%S", localtime)." [info] $msg\n";
|
||||
}
|
||||
|
||||
sub fatal
|
||||
{
|
||||
my ($msg) = @_;
|
||||
eval { $dbh->rollback } if $dbh;
|
||||
print POSIX::strftime("%Y-%m-%d %H:%M:%S", localtime)." [error] $msg\n";
|
||||
exit(1);
|
||||
}
|
|
@ -0,0 +1,222 @@
|
|||
commit 8e1da67b3d4221aa16469cba53c8097ddbe78cb8
|
||||
Author: Vitaliy Filippov <vitalif@yourcmc.ru>
|
||||
Date: Sat Sep 29 02:47:19 2018 +0300
|
||||
|
||||
Split ways between linestrings / polygons correctly (so one object cannot be a linestring and a polygon at the same time)
|
||||
|
||||
diff --git a/mapping/mapping.go b/mapping/mapping.go
|
||||
index 4f48658..7e58a93 100644
|
||||
--- a/mapping/mapping.go
|
||||
+++ b/mapping/mapping.go
|
||||
@@ -275,7 +275,7 @@ type elementFilter func(tags element.Tags, key Key, closed bool) bool
|
||||
|
||||
type tableElementFilters map[string][]elementFilter
|
||||
|
||||
-func (m *Mapping) addTypedFilters(tableType TableType, filters tableElementFilters) {
|
||||
+func (m *Mapping) getAreaTags() (map[Key]struct{}, map[Key]struct{}) {
|
||||
var areaTags map[Key]struct{}
|
||||
var linearTags map[Key]struct{}
|
||||
if m.Conf.Areas.AreaTags != nil {
|
||||
@@ -290,42 +290,7 @@ func (m *Mapping) addTypedFilters(tableType TableType, filters tableElementFilte
|
||||
linearTags[Key(tag)] = struct{}{}
|
||||
}
|
||||
}
|
||||
-
|
||||
- for name, t := range m.Conf.Tables {
|
||||
- if TableType(t.Type) != GeometryTable && TableType(t.Type) != tableType {
|
||||
- continue
|
||||
- }
|
||||
- if TableType(t.Type) == LineStringTable && areaTags != nil {
|
||||
- f := func(tags element.Tags, key Key, closed bool) bool {
|
||||
- if closed {
|
||||
- if tags["area"] == "yes" {
|
||||
- return false
|
||||
- }
|
||||
- if tags["area"] != "no" {
|
||||
- if _, ok := areaTags[key]; ok {
|
||||
- return false
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
- return true
|
||||
- }
|
||||
- filters[name] = append(filters[name], f)
|
||||
- }
|
||||
- if TableType(t.Type) == PolygonTable && linearTags != nil {
|
||||
- f := func(tags element.Tags, key Key, closed bool) bool {
|
||||
- if closed && tags["area"] == "no" {
|
||||
- return false
|
||||
- }
|
||||
- if tags["area"] != "yes" {
|
||||
- if _, ok := linearTags[key]; ok {
|
||||
- return false
|
||||
- }
|
||||
- }
|
||||
- return true
|
||||
- }
|
||||
- filters[name] = append(filters[name], f)
|
||||
- }
|
||||
- }
|
||||
+ return areaTags, linearTags
|
||||
}
|
||||
|
||||
func (m *Mapping) addRelationFilters(tableType TableType, filters tableElementFilters) {
|
||||
diff --git a/mapping/matcher.go b/mapping/matcher.go
|
||||
index 2c58446..346782c 100644
|
||||
--- a/mapping/matcher.go
|
||||
+++ b/mapping/matcher.go
|
||||
@@ -10,13 +10,11 @@ func (m *Mapping) pointMatcher() (NodeMatcher, error) {
|
||||
m.mappings(PointTable, mappings)
|
||||
filters := make(tableElementFilters)
|
||||
m.addFilters(filters)
|
||||
- m.addTypedFilters(PointTable, filters)
|
||||
tables, err := m.tables(PointTable)
|
||||
return &tagMatcher{
|
||||
mappings: mappings,
|
||||
filters: filters,
|
||||
tables: tables,
|
||||
- matchAreas: false,
|
||||
}, err
|
||||
}
|
||||
|
||||
@@ -25,12 +23,15 @@ func (m *Mapping) lineStringMatcher() (WayMatcher, error) {
|
||||
m.mappings(LineStringTable, mappings)
|
||||
filters := make(tableElementFilters)
|
||||
m.addFilters(filters)
|
||||
- m.addTypedFilters(LineStringTable, filters)
|
||||
+ areaTags, linearTags := m.getAreaTags()
|
||||
tables, err := m.tables(LineStringTable)
|
||||
return &tagMatcher{
|
||||
mappings: mappings,
|
||||
filters: filters,
|
||||
tables: tables,
|
||||
+ areaTags: areaTags,
|
||||
+ linearTags: linearTags,
|
||||
+ matchLines: true,
|
||||
matchAreas: false,
|
||||
}, err
|
||||
}
|
||||
@@ -40,7 +41,7 @@ func (m *Mapping) polygonMatcher() (RelWayMatcher, error) {
|
||||
m.mappings(PolygonTable, mappings)
|
||||
filters := make(tableElementFilters)
|
||||
m.addFilters(filters)
|
||||
- m.addTypedFilters(PolygonTable, filters)
|
||||
+ areaTags, linearTags := m.getAreaTags()
|
||||
relFilters := make(tableElementFilters)
|
||||
m.addRelationFilters(PolygonTable, relFilters)
|
||||
tables, err := m.tables(PolygonTable)
|
||||
@@ -49,6 +50,9 @@ func (m *Mapping) polygonMatcher() (RelWayMatcher, error) {
|
||||
filters: filters,
|
||||
tables: tables,
|
||||
relFilters: relFilters,
|
||||
+ areaTags: areaTags,
|
||||
+ linearTags: linearTags,
|
||||
+ matchLines: false,
|
||||
matchAreas: true,
|
||||
}, err
|
||||
}
|
||||
@@ -58,8 +62,6 @@ func (m *Mapping) relationMatcher() (RelationMatcher, error) {
|
||||
m.mappings(RelationTable, mappings)
|
||||
filters := make(tableElementFilters)
|
||||
m.addFilters(filters)
|
||||
- m.addTypedFilters(PolygonTable, filters)
|
||||
- m.addTypedFilters(RelationTable, filters)
|
||||
relFilters := make(tableElementFilters)
|
||||
m.addRelationFilters(RelationTable, relFilters)
|
||||
tables, err := m.tables(RelationTable)
|
||||
@@ -68,7 +70,6 @@ func (m *Mapping) relationMatcher() (RelationMatcher, error) {
|
||||
filters: filters,
|
||||
tables: tables,
|
||||
relFilters: relFilters,
|
||||
- matchAreas: true,
|
||||
}, err
|
||||
}
|
||||
|
||||
@@ -77,7 +78,6 @@ func (m *Mapping) relationMemberMatcher() (RelationMatcher, error) {
|
||||
m.mappings(RelationMemberTable, mappings)
|
||||
filters := make(tableElementFilters)
|
||||
m.addFilters(filters)
|
||||
- m.addTypedFilters(RelationMemberTable, filters)
|
||||
relFilters := make(tableElementFilters)
|
||||
m.addRelationFilters(RelationMemberTable, relFilters)
|
||||
tables, err := m.tables(RelationMemberTable)
|
||||
@@ -86,7 +86,6 @@ func (m *Mapping) relationMemberMatcher() (RelationMatcher, error) {
|
||||
filters: filters,
|
||||
tables: tables,
|
||||
relFilters: relFilters,
|
||||
- matchAreas: true,
|
||||
}, err
|
||||
}
|
||||
|
||||
@@ -127,6 +126,9 @@ type tagMatcher struct {
|
||||
tables map[string]*rowBuilder
|
||||
filters tableElementFilters
|
||||
relFilters tableElementFilters
|
||||
+ areaTags map[Key]struct{}
|
||||
+ linearTags map[Key]struct{}
|
||||
+ matchLines bool
|
||||
matchAreas bool
|
||||
}
|
||||
|
||||
@@ -135,23 +137,7 @@ func (tm *tagMatcher) MatchNode(node *element.Node) []Match {
|
||||
}
|
||||
|
||||
func (tm *tagMatcher) MatchWay(way *element.Way) []Match {
|
||||
- if tm.matchAreas { // match way as polygon
|
||||
- if way.IsClosed() {
|
||||
- if way.Tags["area"] == "no" {
|
||||
- return nil
|
||||
- }
|
||||
- return tm.match(way.Tags, true, false)
|
||||
- }
|
||||
- } else { // match way as linestring
|
||||
- if way.IsClosed() {
|
||||
- if way.Tags["area"] == "yes" {
|
||||
- return nil
|
||||
- }
|
||||
- return tm.match(way.Tags, true, false)
|
||||
- }
|
||||
- return tm.match(way.Tags, false, false)
|
||||
- }
|
||||
- return nil
|
||||
+ return tm.match(way.Tags, way.IsClosed(), false)
|
||||
}
|
||||
|
||||
func (tm *tagMatcher) MatchRelation(rel *element.Relation) []Match {
|
||||
@@ -205,7 +191,35 @@ func (tm *tagMatcher) match(tags element.Tags, closed bool, relation bool) []Mat
|
||||
for t, match := range tables {
|
||||
filters, ok := tm.filters[t.Name]
|
||||
filteredOut := false
|
||||
- if ok {
|
||||
+ if !relation && (tm.matchLines || tm.matchAreas) {
|
||||
+ if !closed {
|
||||
+ // open way is always a linestring
|
||||
+ filteredOut = tm.matchLines == false
|
||||
+ } else {
|
||||
+ // allow to include closed ways as linestrings if explicitly marked
|
||||
+ // default -> area
|
||||
+ // area=no or linear tags -> line
|
||||
+ // area=yes or area tags -> area
|
||||
+ filteredOut = tm.matchAreas && tags["area"] == "no" || !tm.matchAreas && tags["area"] != "no"
|
||||
+ for k, _ := range tm.linearTags {
|
||||
+ if _, ok := tags[string(k)]; ok {
|
||||
+ filteredOut = tm.matchAreas
|
||||
+ break
|
||||
+ }
|
||||
+ }
|
||||
+ // but area=yes or area tag means it shouldn't be a linestring
|
||||
+ if tags["area"] == "yes" {
|
||||
+ filteredOut = tm.matchAreas
|
||||
+ }
|
||||
+ for k, _ := range tm.areaTags {
|
||||
+ if _, ok := tags[string(k)]; ok {
|
||||
+ filteredOut = !tm.matchAreas
|
||||
+ break
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ if ok && !filteredOut {
|
||||
for _, filter := range filters {
|
||||
if !filter(tags, Key(match.Key), closed) {
|
||||
filteredOut = true
|
Loading…
Reference in New Issue