source: subversion/applications/rendering/orp/orp-select.pm @ 7201

Last change on this file since 7201 was 7114, checked in by frederik, 12 years ago

little code redesign and area-with-hole support for or/p

File size: 5.5 KB
Line 
1# OR/P - Osmarender in Perl
2# -------------------------
3#
4# Selection Module
5#
6# (See orp.pl for details.)
7#
8# This module contains the implementation for the various styles of
9# object selection supported in <rule> elements.
10
11use strict;
12use warnings;
13
14our $index_way_tags;
15our $index_node_tags;
16our $debug;
17
18sub select_elements_without_tags
19{
20    my ($oldsel, $e) = @_;
21    my $newsel = Set::Object->new();
22    foreach ($oldsel->members())
23    {
24        next if defined($e) and ref($_) != $e;
25        $newsel->insert($_) unless defined($_->{"tags"});
26    }
27    return $newsel;
28}
29
30
31sub select_elements_with_any_tag
32{
33    my ($oldsel, $e) = @_;
34    my $newsel = Set::Object->new();
35
36    foreach ($oldsel->members())
37    {
38        next if defined($e) and ref($_) != $e;
39        $newsel->insert($_) if defined($_->{"tags"});
40    }
41    return $newsel;
42}
43
44sub select_elements_with_given_tag_value
45{
46    my ($oldsel, $e, $v);
47    my $newsel = Set::Object->new();
48    my $seek = {};
49    $seek->{$_} = 1 foreach(split('\|', $v));
50outer:
51    foreach ($oldsel->members())
52    {
53        next if defined($e) and ref($_) ne $e;
54        foreach my $value(values(%{$_->{"tags"}}))
55        {
56            if (defined($seek->{$value}))
57            {
58                $newsel->insert($_);
59                next outer;
60            }
61        }
62    }
63    return $newsel;
64}
65
66sub select_elements_with_given_tag_key
67{
68    my ($oldsel, $e, $k) = @_;
69    my $newsel = Set::Object->new();
70    my @keys_wanted = split('\|', $k);
71
72outer:
73    foreach ($oldsel->members())
74    {
75        next if (defined($e) and ref($_) ne $e);
76        foreach my $key(@keys_wanted)
77        {
78            if (defined($_->{"tags"}->{$key}))
79            {
80                $newsel->insert($_);
81                next outer;
82            }
83        }
84    }
85
86    return $newsel;
87}
88
89sub select_elements_without_given_tag_key
90{
91    my ($oldsel, $e, $k) = @_;
92    my $newsel = Set::Object->new();
93    my @keys_wanted = split('\|', $k);
94
95
96outer:
97    foreach ($oldsel->members())
98    {
99        next if defined($e) and ref($_) ne $e;
100        foreach my $key(@keys_wanted)
101        {
102            next outer if (defined($_->{"tags"}->{$key}));
103        }
104        $newsel->insert($_);
105    }
106
107    return $newsel;
108}
109
110# e=way or node, s not supptd, v must not contain ~
111sub select_elements_with_given_tag_key_and_value_fast
112{
113    my ($oldsel, $e, $k, $v) = @_;
114    my @values_wanted = split('\|', $v);
115    my $newsel = Set::Object->new();
116    my @keys_wanted = split('\|', $k);
117
118    foreach my $key(split('\|', $k))
119    {
120        # retrieve list of objects with this key from index.
121        my @objects = 
122            ($e eq 'way') ? @{$index_way_tags->{$key}||[]} : 
123            ($e eq 'node') ? @{$index_node_tags->{$key}||[]} : 
124            (@{$index_way_tags->{$key}||[]}, @{$index_node_tags->{$key}||[]});
125
126        debug(sprintf('%d objects retrieved from index for e="%s" k="%s"', 
127            scalar(@objects), $e, $k)) if ($debug->{"indexes"});
128
129        # process only those from oldsel that have this key.
130outer:
131        foreach (@objects)
132        {   
133            next unless ($oldsel->contains($_));
134            foreach my $value(@values_wanted)
135            {   
136                if ($_->{"tags"}->{$key} eq $value)
137                {   
138                    $newsel->insert($_);
139                    next outer;
140                }   
141            }   
142        } 
143    }
144    return $newsel;
145}
146
147# e=node, s=way, v must not contain ~
148sub select_nodes_with_given_tag_key_and_value_for_way_fast
149{
150    my ($oldsel, $k, $v) = @_;
151    my @values_wanted = split('\|', $v);
152    my $newsel = Set::Object->new();
153    my @keys_wanted = split('\|', $k);
154
155    foreach my $key(split('\|', $k))
156    {
157        # process only those from oldsel that have this key.
158outer:
159        foreach my $way(@{$index_way_tags->{$key}||[]})
160        {   
161            foreach my $value(@values_wanted)
162            {   
163                if ($way->{"tags"}->{$key} eq $value)
164                {   
165                    foreach (@{$way->{'nodes'}})
166                    {
167                        next unless ($oldsel->contains($_));
168                        $newsel->insert($_);
169                    }   
170                }   
171            }
172        } 
173    }
174    return $newsel;
175}
176
177sub select_elements_with_given_tag_key_and_value_slow
178{
179    my ($oldsel, $e, $k, $v, $s) = @_;
180    my @values_wanted = split('\|', $v);
181    my $newsel = Set::Object->new();
182    my @keys_wanted = split('\|', $k);
183
184outer:
185    foreach ($oldsel->members())
186    {   
187        next if defined($e) and ref($_) ne $e; 
188        # determine whether we're comparing against the tags of the object
189        # itself or the tags selected with the "s" attribute.
190        my $tagsets;
191        if ($s eq "way")
192        {   
193            $tagsets = []; 
194            foreach my $way(@{$_->{"ways"}})
195            {   
196                push(@$tagsets, $way->{"tags"});
197            }   
198        }   
199        else
200        {   
201            $tagsets = [ $_->{"tags"} ];
202        }   
203
204        foreach my $key(@keys_wanted)
205        {   
206            foreach my $value(@values_wanted)
207            {   
208                foreach my $tagset(@$tagsets)
209                {   
210                    my $keyval = $tagset->{$k};
211                    if (($value eq '~' and !defined($keyval)) or
212                        ($value eq $keyval and defined($keyval)))
213                    {   
214                        $newsel->insert($_);
215                        next outer;
216                    }   
217                }   
218            }   
219        }   
220    } 
221   
222    return $newsel;
223}
224
2251;
Note: See TracBrowser for help on using the repository browser.