# # PERL mapweaver module by gary68 # # # # # Copyright (C) 2011, Gerhard Schwanz # # This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 3 of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along with this program; if not, see # package mwRules ; use strict ; use warnings ; use mwConfig ; use mwMap ; use mwMisc ; use vars qw($VERSION @ISA @EXPORT @EXPORT_OK); require Exporter ; @ISA = qw ( Exporter AutoLoader ) ; @EXPORT = qw ( readRules getNodeRule printNodeRules getWayRule printWayRules getAreaRule printAreaRules printValidObjectProperties getRouteColors getRouteRule printRouteRules adaptRuleSizes createLegend ) ; my @validNodeProperties = ( ["keyValue","key and value like [amenity=hospital]"], ["color","color of node i.e. [black]"], ["size","size of node i.e. [50]"], ["shape","shape of node [circle|disc|triangle|diamond|rectangle]"], ["svgString","svg format of shape [valid svg string]"], ["circle","add a circle to the node [yes|no]"], ["circleColor","color of the circle i.e. [blue]"], ["circleRadius","circle radius in meters i.e. [1000]"], ["circleThickness","thickness of the circle i.e. [5]"], ["circleSVGString","format of the circle []"], ["disc","add a disc to the node [yes|no]"], ["discColor","color of the disc i.e. [green]"], ["discOpacity","opacity of the disc [0..100]"], ["discRadius","radius of disc in meters i.e. [5000]"], ["discSVGString","format of the disc []"], ["label","label for the node like [name|ref]"], ["labelColor","color for label text i.e. [white]"], ["labelSize","size of label text i.e. [20]"], ["labelFont","font for label"], ["labelFontFamily","font family for label"], ["labelOffset","distance of label to node i.e. [10]"], ["labelBold","bold font for label"], ["labelItalic","italic font for label"], ["labelHalo","halo for label, width in pixels"], ["labelHaloColor","color for halo"], ["labelTransform","perl code for label name transformation"], ["legend","is this object to be listed in map legend? [yes|no]"], ["legendLabel","label text of object in legend i.e. [city]"], ["icon","icon to use for node, overrides shape i.e. [icondir/icon.svg]"], ["iconSize","size of the icon i.e. [40]"], ["shieldName","NOT YET IMPLEMENTED"], ["shieldSize","NOT YET IMPLEMENTED"], ["shieldLabel","NOT YET IMPLEMENTED"], ["fromScale","rule will only applied if scale is bigger than fromScale i.e. [5000]"], ["toScale","rule will only applied if scale is lower than fromScale i.e. [25000]"], ["direxclude","should these objects be excluded from directory? [yes|no]"] ) ; my @validWayProperties = ( ["keyValue","key and value like [highway=residential]"], ["color","color for the way i.e. [gray]"], ["size","size of the way i.e. [15]"], ["dash","svg dash array for the way i.e. [20,20]; old mapgen values are also possible"], ["dashCap","linecap shape for dashes like [butt|round|square]"], ["borderColor","color of the border of the way i.e. [black]"], ["borderSize","thickness os the border i.e. [2]"], ["label","label to be used i.e. [name|ref]"], ["labelColor","color of label text i.e. [blue]"], ["labelSize","size of the label i.e. [20]"], ["labelFont","font for label"], ["labelFontFamily","font family for label"], ["labelOffset","distance of label to middle of way i.e. [5]"], ["labelBold","bold font for label"], ["labelItalic","italic font for label"], ["labelHalo","halo for label, width in pixels"], ["labelHaloColor","color for halo"], ["labelTransform","perl code for label name transformation"], ["legend","is this object to be listed in map legend? [yes|no]"], ["legendLabel","label text of object in legend i.e. [Highway]"], ["svgStringBottom","format of lower way part (i.e. border) []"], ["svgStringTop","format of upper way part []"], ["bottomBorder","NOT YET IMPLEMENTED"], ["fromScale","rule will only applied if scale is bigger than fromScale i.e. [5000]"], ["toScale","rule will only applied if scale is lower than fromScale i.e. [25000]"], ["direxclude","should these objects be excluded from directory? [yes|no]"] ) ; my @validAreaProperties = ( ["keyValue","key and value of object i.e. [amenity=parking]"], ["color","color of area i.e. [lightgrey]"], ["icon","icon for fill pattern to be used i.e. [icondir/parking.svg]"], ["label", "label text to be rendered i.e. [name]"] , ["labelFont","font for label"], ["labelFontFamily","font family for label"], ["labelColor", "color of label i.e. [green]"] , ["labelSize", "size of label text i.e. [20]"] , ["labelBold","bold font for label"], ["labelItalic","italic font for label"], ["labelHalo","halo for label, width in pixels"], ["labelHaloColor","color for halo"], ["labelTransform","perl code for label name transformation"], ["base","should this object be drawn underneath other objects? (applies for landuse residential i.e.) [yes|no]"], ["svgString","format of area []"], ["legend","is this object to be listed in map legend? [yes|no]"], ["legendLabel","label text of object in legend i.e. [Parking]"], ["fromScale","rule will only applied if scale is bigger than fromScale i.e. [5000]"], ["toScale","rule will only applied if scale is lower than fromScale i.e. [25000]"] ) ; my @validRouteProperties = ( ["type","type of route like [bus|hiking]"], ["color","color of route like [red]"], ["size","size of route i.e. [10]"], ["dash","svg dash array style like [20,20]"], ["linecap","linecap style [butt|round|square]"], ["opacity","opacity of the route [0..100]"], ["label","label to be used like [ref]"], ["labelFont","font for label"], ["labelFontFamily","font family for label"], ["labelSize","size of the label i.e. [15]"], ["nodeSize","size of nodes belonging to route i.e. [20]"], ["fromScale","rule will only applied if scale is bigger than fromScale i.e. [5000]"], ["toScale","rule will only applied if scale is lower than fromScale i.e. [25000]"] ) ; my %nodeRules = () ; my %areaRules = () ; my %wayRules = () ; my %routeRules = () ; my $nodeNr = 0 ; my $areaNr = 0 ; my $wayNr = 0 ; my $routeNr = 0 ; my $line ; my $ruleFile ; # --------------------------------------------------------------------------------------- sub printValidObjectProperties { print "\nValid Object Properties\n" ; print "\nNodes\n-----\n" ; foreach my $p (sort {$a->[0] cmp $b->[0]} @validNodeProperties) { printf "%-20s %s\n", $p->[0], $p->[1] ; } print "\nWays\n----\n" ; foreach my $p (sort {$a->[0] cmp $b->[0]} @validWayProperties) { printf "%-20s %s\n", $p->[0], $p->[1] ; } print "\nAreas\n-----\n" ; foreach my $p (sort {$a->[0] cmp $b->[0]} @validAreaProperties) { printf "%-20s %s\n", $p->[0], $p->[1] ; } print "\nRoutes\n-----\n" ; foreach my $p (sort {$a->[0] cmp $b->[0]} @validRouteProperties) { printf "%-20s %s\n", $p->[0], $p->[1] ; } print "\n" ; } # --------------------------------------------------------------------------------------- sub readRules { my $fileName = cv('style') ; my $nrr = 0 ; my $wrr = 0 ; my $arr = 0 ; my $rrr = 0 ; my $crr = 0 ; print "reading rule file $fileName\n" ; my %vnp = () ; foreach my $p ( @validNodeProperties ) { $vnp{ lc ( $p->[0] ) } = 1 ; } my %vwp = () ; foreach my $p ( @validWayProperties ) { $vwp{ lc ( $p->[0] ) } = 1 ; } my %vap = () ; foreach my $p ( @validAreaProperties ) { $vap{ lc ( $p->[0] ) } = 1 ; } my %vrp = () ; foreach my $p ( @validRouteProperties ) { $vrp{ lc ( $p->[0] ) } = 1 ; } openRuleFile($fileName) ; while (defined $line) { if ( grep /^rule node/i, $line ) { $nodeNr++ ; $nrr++ ; getRuleLine() ; # set defaults first $nodeRules{ $nodeNr }{ 'size' } = cv( 'ruleDefaultNodeSize' ) ; $nodeRules{ $nodeNr }{ 'color' } = cv( 'ruleDefaultNodeColor' ) ; $nodeRules{ $nodeNr }{ 'shape' } = cv( 'ruleDefaultNodeShape' ) ; $nodeRules{ $nodeNr }{ 'label' } = cv( 'ruleDefaultNodeLabel' ) ; $nodeRules{ $nodeNr }{ 'labelfont' } = cv( 'ruleDefaultNodeLabelFont' ) ; $nodeRules{ $nodeNr }{ 'labelfontfamily' } = cv( 'ruleDefaultNodeLabelFontFamily' ) ; $nodeRules{ $nodeNr }{ 'labelsize' } = cv( 'ruleDefaultNodeLabelSize' ) ; $nodeRules{ $nodeNr }{ 'labelitalic' } = "no" ; $nodeRules{ $nodeNr }{ 'labelbold' } = "no" ; $nodeRules{ $nodeNr }{ 'labelhalo' } = 0 ; $nodeRules{ $nodeNr }{ 'labelhalocolor' } = "white" ; $nodeRules{ $nodeNr }{ 'labeltransform' } = "" ; $nodeRules{ $nodeNr }{ 'icon' } = "none" ; $nodeRules{ $nodeNr }{ 'iconsize' } = cv( 'ruleDefaultNodeIconSize' ) ; $nodeRules{ $nodeNr }{ 'legend' } = "no" ; $nodeRules{ $nodeNr }{ 'shieldname' } = "none" ; $nodeRules{ $nodeNr }{ 'svgstring' } = "" ; $nodeRules{ $nodeNr }{ 'legend' } = "no" ; $nodeRules{ $nodeNr }{ 'legendlabel' } = "" ; $nodeRules{ $nodeNr }{ 'circle' } = 'no' ; $nodeRules{ $nodeNr }{ 'circlecolor' } = 'black' ; $nodeRules{ $nodeNr }{ 'circleradius' } = 1000 ; $nodeRules{ $nodeNr }{ 'circlethickness' } = 10 ; $nodeRules{ $nodeNr }{ 'circlesvgstring' } = "" ; $nodeRules{ $nodeNr }{ 'disc' } = 'no' ; $nodeRules{ $nodeNr }{ 'disccolor' } = 'red' ; $nodeRules{ $nodeNr }{ 'discopacity' } = 50 ; $nodeRules{ $nodeNr }{ 'discradius' } = 1000 ; $nodeRules{ $nodeNr }{ 'discradius' } = 1000 ; $nodeRules{ $nodeNr }{ 'discsvgstring' } = '' ; $nodeRules{ $nodeNr }{ 'fromscale' } = cv ('ruledefaultnodefromscale') ; $nodeRules{ $nodeNr }{ 'toscale' } = cv ('ruledefaultnodetoscale') ; $nodeRules{ $nodeNr }{ 'direxclude' } = cv('direxcludedefault') ; while ( ( defined $line) and ( ! grep /^rule/i, $line) ) { my ($k, $v) = ( $line =~ /(.+?)=(.+)/ ) ; if ( ( ! defined $k ) or ( ! defined $v ) ) { print "WARNING: could not parse rule line: $line" ; } else { $k = lc ( $k ) ; $nodeRules{ $nodeNr }{ $k } = $v ; if ( ! defined $vnp{$k} ) { print "WARNING: $k is not a valid node property!\n" ; } } getRuleLine() ; } if ( ! defined $nodeRules{ $nodeNr }{ 'keyvalue' } ) { die "ERROR: rule without keyValue detected!\n" ; } } # node elsif ( grep /^rule way/i, $line ) { $wayNr++ ; $wrr++ ; getRuleLine() ; # set defaults first $wayRules{ $wayNr }{ 'label' } = cv( 'ruleDefaultWayLabel' ) ; $wayRules{ $wayNr }{ 'labelfont' } = cv( 'ruleDefaultWayLabelFont' ) ; $wayRules{ $wayNr }{ 'labelfontfamily' } = cv( 'ruleDefaultWayLabelFontFamily' ) ; $wayRules{ $wayNr }{ 'labelsize' } = cv( 'ruleDefaultWayLabelSize' ) ; $wayRules{ $wayNr }{ 'labelcolor' } = cv( 'ruleDefaultWayLabelColor' ) ; $wayRules{ $wayNr }{ 'labelfont' } = cv( 'ruleDefaultWayLabelFont' ) ; $wayRules{ $wayNr }{ 'labeloffset' } = cv( 'ruleDefaultWayLabelOffset' ) ; $wayRules{ $wayNr }{ 'labelitalic' } = "no" ; $wayRules{ $wayNr }{ 'labelbold' } = "no" ; $wayRules{ $wayNr }{ 'labelhalo' } = 0 ; $wayRules{ $wayNr }{ 'labelhalocolor' } = "white" ; $wayRules{ $wayNr }{ 'labeltransform' } = "" ; $wayRules{ $wayNr }{ 'legend' } = "no" ; $wayRules{ $wayNr }{ 'legendlabel' } = "" ; $wayRules{ $wayNr }{ 'color' } = cv( 'ruleDefaultWayColor' ) ; $wayRules{ $wayNr }{ 'size' } = cv( 'ruleDefaultWaySize' ) ; $wayRules{ $wayNr }{ 'bordercolor' } = cv( 'ruleDefaultWayBorderColor' ) ; $wayRules{ $wayNr }{ 'bordersize' } = cv( 'ruleDefaultWayBorderSize' ) ; $wayRules{ $wayNr }{ 'dash' } = cv( 'ruleDefaultWayDash' ) ; $wayRules{ $wayNr }{ 'dashcap' } = cv( 'ruleDefaultWayDashCap' ) ; $wayRules{ $wayNr }{ 'svgstringtop' } = "" ; $wayRules{ $wayNr }{ 'svgstringbottom' } = "" ; $wayRules{ $wayNr }{ 'fromscale' } = cv ('ruledefaultwayfromscale') ; $wayRules{ $wayNr }{ 'toscale' } = cv ('ruledefaultwaytoscale') ; $wayRules{ $wayNr }{ 'direxclude' } = cv('direxcludedefault') ; while ( ( defined $line) and ( ! grep /^rule/i, $line) ) { my ($k, $v) = ( $line =~ /(.+?)=(.+)/ ) ; if ( ( ! defined $k ) or ( ! defined $v ) ) { print "WARNING: could not parse rule line: $line" ; } else { $k = lc ( $k ) ; $wayRules{ $wayNr }{ $k } = $v ; if ( ! defined $vwp{$k} ) { print "WARNING: $k is not a valid way property!\n" ; } } getRuleLine() ; } if ( ! defined $wayRules{ $wayNr }{ 'keyvalue' } ) { die "ERROR: rule without keyValue detected!\n" ; } } # way elsif ( grep /^rule area/i, $line ) { $areaNr++ ; $arr++ ; getRuleLine() ; # set defaults first $areaRules{ $areaNr }{ 'label' } = "none" ; $areaRules{ $areaNr }{ 'labelfont' } = cv( 'ruleDefaultAreaLabelFont' ) ; $areaRules{ $areaNr }{ 'labelfontfamily' } = cv( 'ruleDefaultAreaLabelFontFamily' ) ; $areaRules{ $areaNr }{ 'labelcolor' } = "black" ; $areaRules{ $areaNr }{ 'labelsize' } = 30 ; $areaRules{ $areaNr }{ 'labelitalic' } = "no" ; $areaRules{ $areaNr }{ 'labelbold' } = "no" ; $areaRules{ $areaNr }{ 'labelhalo' } = 0 ; $areaRules{ $areaNr }{ 'labelhalocolor' } = "white" ; $areaRules{ $areaNr }{ 'labeltransform' } = "" ; $areaRules{ $areaNr }{ 'color' } = cv( 'ruleDefaultAreaColor') ; $areaRules{ $areaNr }{ 'icon' } = "none" ; $areaRules{ $areaNr }{ 'base' } = "no" ; $areaRules{ $areaNr }{ 'svgstring' } = "" ; $areaRules{ $areaNr }{ 'minsize' } = cv ('ruledefaultareaminsize') ; $areaRules{ $areaNr }{ 'legend' } = "no" ; $areaRules{ $areaNr }{ 'legendlabel' } = "" ; $areaRules{ $areaNr }{ 'fromscale' } = cv ('ruledefaultareafromscale') ; $areaRules{ $areaNr }{ 'toscale' } = cv ('ruledefaultareatoscale') ; while ( ( defined $line) and ( ! grep /^rule/i, $line) ) { my ($k, $v) = ( $line =~ /(.+?)=(.+)/ ) ; if ( ( ! defined $k ) or ( ! defined $v ) ) { print "WARNING: could not parse rule line: $line" ; } else { $k = lc ( $k ) ; $areaRules{ $areaNr }{ $k } = $v ; if ( ! defined $vap{$k} ) { print "WARNING: $k is not a valid area property!\n" ; } if ($k eq "icon") { mwMap::addAreaIcon ($v) ; } } getRuleLine() ; } if ( ! defined $areaRules{ $areaNr }{ 'keyvalue' } ) { die "ERROR: rule without keyValue detected!\n" ; } } # area elsif ( grep /^rule route/i, $line ) { $routeNr++ ; $rrr++ ; getRuleLine() ; # set defaults first $routeRules{ $routeNr }{ 'color' } = cv( 'ruleDefaultRouteColor' ) ; $routeRules{ $routeNr }{ 'size' } = cv( 'ruleDefaultRouteSize' ) ; $routeRules{ $routeNr }{ 'dash' } = cv( 'ruleDefaultRouteDash' ) ; $routeRules{ $routeNr }{ 'linecap' } = cv( 'ruleDefaultRouteLinecap' ) ; $routeRules{ $routeNr }{ 'opacity' } = cv( 'ruleDefaultRouteOpacity' ) ; $routeRules{ $routeNr }{ 'label' } = cv( 'ruleDefaultRouteLabel' ) ; # $routeRules{ $routeNr }{ 'labelfont' } = cv( 'ruleDefaultRouteLabelFont' ) ; # $routeRules{ $routeNr }{ 'labelfontfamily' } = cv( 'ruleDefaultRouteLabelFontFamily' ) ; # $routeRules{ $routeNr }{ 'labelsize' } = cv( 'ruleDefaultRouteLabelSize' ) ; $routeRules{ $routeNr }{ 'nodesize' } = cv( 'ruleDefaultRouteNodeSize' ) ; $routeRules{ $routeNr }{ 'fromscale' } = cv( 'ruleDefaultRouteFromScale' ) ; $routeRules{ $routeNr }{ 'toscale' } = cv( 'ruleDefaultRouteToScale' ) ; while ( ( defined $line) and ( ! grep /^rule/i, $line) ) { my ($k, $v) = ( $line =~ /(.+?)=(.+)/ ) ; if ( ( ! defined $k ) or ( ! defined $v ) ) { print "WARNING: could not parse rule line: $line" ; } else { $k = lc ( $k ) ; $routeRules{ $routeNr }{ $k } = $v ; if ( ! defined $vrp{$k} ) { print "WARNING: $k is not a valid route property!\n" ; } } getRuleLine() ; } if ( ! defined $routeRules{ $routeNr }{ 'type' } ) { die "ERROR: route rule without type detected!\n" ; } } # route elsif ( grep /^rule config/i, $line ) { $crr++ ; my ($key, $value) = ( $line =~ /^rule config\s+(.+)=(.+)/i ) ; if ( (defined $key) and (defined $value) ) { setConfigValue ($key, $value) ; if ( cv('debug') eq "1" ) { print "RULES: config changed $key=$value\n" ; } } getRuleLine() ; } # config else { getRuleLine() ; } } close ($ruleFile) ; print "rules read: $nrr nodes, $wrr ways, $arr areas, $rrr routes and $crr configs\n\n" ; } sub getNodeRule { # takes tagref and returns hashref to rule properties my $tagRef = shift ; my $scale = getScale() ; if ( cv('rulescaleset') != 0 ) { $scale = cv('rulescaleset') ; } # print "GNR: scale: $scale\n" ; my $ruleFound ; undef $ruleFound ; # print "\n" ; RUL2: foreach my $rule ( sort { $a <=> $b } keys %nodeRules) { # print "rule $rule\n" ; if ( ( $nodeRules{$rule}{'fromscale'} <= $scale) and ( $nodeRules{$rule}{'toscale'} >= $scale) ) { my @kvs = split /;/, $nodeRules{$rule}{'keyvalue'} ; my $allValid = 1 ; RUL1: foreach my $kv1 ( @kvs ) { # for each needed my ($k, $v) = ( $kv1 =~ /(.+)=(.+)/ ) ; # print " looking for $k=$v\n" ; my $found = 0 ; RUL3: foreach my $tag ( @$tagRef) { # print " actual kvs: $tag->[0]=$tag->[1]\n" ; if ( ( $tag->[0] eq $k) and ( ( $tag->[1] eq $v) or ( $v eq "*") ) ) { $found = 1 ; # print " FOUND\n" ; last RUL3 ; } } # tags if ( ! $found ) { $allValid = 0 ; last RUL1 ; } } # kv1 if ( $allValid ) { # print "ALL VALID\n" ; # return the first rule found $ruleFound = \%{ $nodeRules{ $rule } } ; last RUL2 ; } } # scale } # all rules return ($ruleFound) ; } sub printNodeRules { foreach my $n ( sort { $a <=> $b } keys %nodeRules) { print "node rule $n\n" ; foreach my $v (sort keys %{$nodeRules{$n}}) { print " $v=$nodeRules{$n}{$v}\n" ; } print "\n" ; } } # --------------------------------------------------------------------------------------- sub getWayRule { # takes tagref and returns hashref to rule properties my $tagRef = shift ; my $scale = getScale() ; if ( cv('rulescaleset') != 0 ) { $scale = cv('rulescaleset') ; } my $ruleFound ; undef $ruleFound ; RUL5: foreach my $rule ( sort { $a <=> $b } keys %wayRules) { # print "rule $rule\n" ; if ( ( $wayRules{$rule}{'fromscale'} <= $scale) and ( $wayRules{$rule}{'toscale'} >= $scale) ) { my @kvs = split /;/, $wayRules{$rule}{'keyvalue'} ; my $allValid = 1 ; RUL4: foreach my $kv1 ( @kvs ) { # for each needed my ($k, $v) = ( $kv1 =~ /(.+)=(.+)/ ) ; # print " looking for $k=$v\n" ; my $found = 0 ; RUL6: foreach my $tag ( @$tagRef) { # print " actual kvs: $tag->[0]=$tag->[1]\n" ; if ( ( $tag->[0] eq $k) and ( ( $tag->[1] eq $v) or ( $v eq "*") ) ) { $found = 1 ; # print " FOUND\n" ; last RUL6 ; } } # tags if ( ! $found ) { $allValid = 0 ; last RUL4 ; } } # kv1 if ( $allValid ) { # print "ALL VALID\n" ; # return the first rule found $ruleFound = \%{ $wayRules{ $rule } } ; last RUL5 ; } } # scale } # all rules return ($ruleFound) ; } sub printWayRules { foreach my $n ( sort { $a <=> $b } keys %wayRules) { print "way rule $n\n" ; foreach my $v (sort keys %{$wayRules{$n}}) { print " $v=$wayRules{$n}{$v}\n" ; } print "\n" ; } } # --------------------------------------------------------------------------------------- sub getAreaRule { # takes tagref and returns hashref to rule properties my $tagRef = shift ; my $scale = getScale() ; if ( cv('rulescaleset') != 0 ) { $scale = cv('rulescaleset') ; } my $ruleFound ; undef $ruleFound ; RUL8: foreach my $rule ( sort { $a <=> $b } keys %areaRules) { # print "rule $rule\n" ; if ( ( $areaRules{$rule}{'fromscale'} <= $scale) and ( $areaRules{$rule}{'toscale'} >= $scale) ) { my @kvs = split /;/, $areaRules{$rule}{'keyvalue'} ; my $allValid = 1 ; RUL7: foreach my $kv1 ( @kvs ) { # for each needed my ($k, $v) = ( $kv1 =~ /(.+)=(.+)/ ) ; # print " looking for $k=$v\n" ; my $found = 0 ; RUL9: foreach my $tag ( @$tagRef) { # print " actual kvs: $tag->[0]=$tag->[1]\n" ; if ( ( $tag->[0] eq $k) and ( ( $tag->[1] eq $v) or ( $v eq "*") ) ) { $found = 1 ; # print " FOUND\n" ; last RUL9 ; } } # tags if ( ! $found ) { $allValid = 0 ; last RUL7 ; } } # kv1 if ( $allValid ) { # print "ALL VALID\n" ; # return the first rule found $ruleFound = \%{ $areaRules{ $rule } } ; last RUL8 ; } } # scale } # all rules return ($ruleFound) ; } sub printAreaRules { foreach my $n ( sort { $a <=> $b } keys %areaRules) { print "area rule $n\n" ; foreach my $v (sort keys %{$areaRules{$n}}) { print " $v=$areaRules{$n}{$v}\n" ; } print "\n" ; } } # -------------------------------------------------------------------------------- sub getRouteRule { my $tagRef = shift ; my $scale = getScale() ; if ( cv('rulescaleset') != 0 ) { $scale = cv('rulescaleset') ; } my $ruleFound ; undef $ruleFound ; my $type = getValue ("route", $tagRef) ; if (defined $type) { # print " GRR: $type \n" ; RULA: foreach my $r ( sort { $a <=> $b } keys %routeRules) { # print " GRR: $routeRules{$r}{'type'}\n" ; if ($routeRules{$r}{'type'} eq $type) { if ( ( $routeRules{$r}{'fromscale'} <= $scale) and ( $routeRules{$r}{'toscale'} >= $scale) ) { $ruleFound = \%{ $routeRules{ $r } } ; last RULA ; } } } } return $ruleFound ; } sub getRouteColors { my %routeColors = () ; foreach my $n (keys %routeRules) { my $type = $routeRules{$n}{'type'} ; my $color = $routeRules{$n}{'color'} ; @{$routeColors{$type}} = split ( /;/, $color ) ; } return \%routeColors ; } sub printRouteRules { foreach my $n ( sort { $a <=> $b } keys %routeRules) { print "route rule $n\n" ; foreach my $v (sort keys %{$routeRules{$n}}) { print " $v=$routeRules{$n}{$v}\n" ; } print "\n" ; } } # -------------------------------------------------------------------------------- sub openRuleFile { my $fileName = shift ; open ($ruleFile, "<", $fileName) or die ("ERROR: could not open rule file $fileName\n") ; getRuleLine() ; } sub getRuleLine { $line = <$ruleFile> ; if (defined $line) { $line =~ s/\r//g ; # remove dos/win char at line end } while ( (defined $line) and ( (length $line < 2) or ( grep /^comment/i, $line) or ( grep /^\#/i, $line) ) ) { $line = <$ruleFile> ; } return $line ; } sub adaptRuleSizes { foreach my $r ( keys %nodeRules ) { foreach my $p ( qw (iconSize labelOffset labelSize shieldSize size) ) { if ( defined $nodeRules{ $r }{ $p } ) { if ( grep /:/, $nodeRules{ $r }{ $p } ) { my $old = $nodeRules{ $r }{ $p } ; my $new = scaleSize ($nodeRules{ $r }{ $p }, $nodeRules{ $r }{ 'fromscale' }, $nodeRules{ $r }{ 'toscale' }) ; $nodeRules{ $r }{ $p } = $new ; if ( cv('debug') eq "1" ) { print "RULES/scale/node: $old -> $new\n" ; } } } } } foreach my $r ( keys %wayRules ) { foreach my $p ( qw (bordersize labelsize labeloffset size ) ) { if ( defined $wayRules{ $r }{ $p } ) { if ( grep /:/, $wayRules{ $r }{ $p } ) { my $kv = $wayRules{ $r }{ 'keyvalue' } ; my $old = $wayRules{ $r }{ $p } ; my $new = 0 ; $new = scaleSize ($wayRules{ $r }{ $p }, $wayRules{ $r }{ 'fromscale' }, $wayRules{ $r }{ 'toscale' }) ; $wayRules{ $r }{ $p } = $new ; if ( cv('debug') eq "1" ) { print "RULES/scale/way: $kv $p $old to $new\n" ; } } } } } } sub scaleSize { my ($str, $fromScale, $toScale) = @_ ; my @tmp = split /:/, $str ; my $lower = $tmp[0] ; my $upper = $tmp[1] ; my $newSize = 0 ; my $scale = getScale() ; if ( cv('rulescaleset') ne "0" ) { $scale = cv('rulescaleset') } ; if ( $scale < $fromScale) { $newSize = $upper ; } elsif ( $scale > $toScale ) { $newSize = $lower ; } else { my $percent = ( $scale - $fromScale ) / ($toScale - $fromScale) ; $newSize = $upper - $percent * ($upper - $lower) ; } $newSize = int ( $newSize * 10 ) / 10 ; return $newSize ; } sub createLegend { # TODO Auto size my $nx = 80 ; my $ny = 80 ; my $ey = 1.5 * $ny ; my $sx = 700 ; my $tx = 200 ; my $ty = $ey / 2 ; my $fs = 40 ; my $actualLine = 0 ; my $preCount = 0 ; foreach my $n (keys %nodeRules) { if ( $nodeRules{$n}{"legend"} eq "yes" ) { $preCount++ ; } } foreach my $n (keys %wayRules) { if ( $wayRules{$n}{"legend"} eq "yes" ) { $preCount++ ; } } foreach my $n (keys %areaRules) { if ( $areaRules{$n}{"legend"} eq "yes" ) { $preCount++ ; } } if ( cv('debug') eq "1" ) { print "LEGEND: $preCount elements found\n" ; } my $sy = $preCount * $ey ; addToLayer ("definitions", "") ; my $color = "white" ; my $svgString = "fill=\"$color\"" ; drawRect (0, 0, $sx, $sy, 0, $svgString, "definitions") ; foreach my $n (keys %nodeRules) { if ( $nodeRules{$n}{"legend"} eq "yes" ) { my $x = $nx ; my $y = $actualLine * $ey + $ny ; if ( ($nodeRules{$n}{'size'} > 0) and ($nodeRules{$n}{'icon'} eq "none") ) { my $svgString = "" ; if ( $nodeRules{$n}{'svgstring'} ne "" ) { $svgString = $nodeRules{$n}{'svgstring'} ; } else { $svgString = "fill=\"$nodeRules{$n}{'color'}\"" ; } if ( $nodeRules{$n}{'shape'} eq "circle") { drawCircle ($x, $y, 0, $nodeRules{$n}{'size'}, 0, $svgString, 'definitions') ; } elsif ( $nodeRules{$n}{'shape'} eq "square") { drawSquare ($x, $y, 0, $nodeRules{$n}{'size'}, 0, $svgString, 'definitions') ; } elsif ( $nodeRules{$n}{'shape'} eq "triangle") { drawTriangle ($x, $y, 0, $nodeRules{$n}{'size'}, 0, $svgString, 'definitions') ; } elsif ( $nodeRules{$n}{'shape'} eq "diamond") { drawDiamond ($x, $y, 0, $nodeRules{$n}{'size'}, 0, $svgString, 'definitions') ; } my $textSvgString = createTextSVG ( cv('elementFontFamily'), cv('elementFont'), $fs, "black", undef, undef ) ; drawText ($tx, ($actualLine+0.5) * $ey + $fs/2, 0, $nodeRules{$n}{'legendlabel'}, $textSvgString, "definitions") ; } else { # TODO icon } $actualLine ++ ; } } foreach my $w (keys %wayRules) { if ( $wayRules{$w}{"legend"} eq "yes" ) { my ($x1, $x2) ; $x1 = 0.5 * $nx ; $x2 = 1.5 * $nx ; my $y = $actualLine * $ey + $ny ; my ($svg1, $layer1, $svg2, $layer2) = mwWays::createWayParameters ($wayRules{$w}, 0, 0, 0) ; my @coords = ($x1, $y, $x2, $y) ; if ($svg2 ne "") { drawWay ( \@coords, 0, $svg2, "definitions", undef ) ; } drawWay ( \@coords, 0, $svg1, "definitions", undef ) ; my $textSvgString = createTextSVG ( cv('elementFontFamily'), cv('elementFont'), $fs, "black", undef, undef ) ; drawText ($tx, ($actualLine+0.5)*$ey + $fs/2, 0, $wayRules{$w}{'legendlabel'}, $textSvgString, "definitions") ; $actualLine++ ; } } foreach my $a (keys %areaRules) { if ( $areaRules{$a}{"legend"} eq "yes" ) { my ($x1, $x2) ; my ($y1, $y2) ; $x1 = 0.7 * $nx ; $x2 = 1.3 * $nx ; $y1 = $actualLine * $ey + 0.7 * $ny ; $y2 = $actualLine * $ey + 1.3 * $ny ; my $color = $areaRules{$a}{'color'} ; my $icon = $areaRules{$a}{'icon'} ; my $base = $areaRules{$a}{'base'} ; my $svgString = $areaRules{$a}{'svgstring'} ; if ( ($svgString eq "") and ($icon eq "none") ) { $svgString = "fill=\"$color\" " ; } my @coords = ([$x1, $y1, $x2, $y1, $x2, $y2, $x1, $y2, $x1, $y1]) ; drawArea ($svgString, $icon, \@coords, 0, "definitions") ; my $textSvgString = createTextSVG ( cv('elementFontFamily'), cv('elementFont'), $fs, "black", undef, undef ) ; drawText ($tx, ($actualLine+0.5)*$ey + $fs/2, 0, $areaRules{$a}{'legendlabel'}, $textSvgString, "definitions") ; $actualLine++ ; } } addToLayer ("definitions", "") ; my $posX = 0 ; my $posY = 0 ; my ($sizeX, $sizeY) = getDimensions() ; if ( cv('legend') eq "2") { $posX = $sizeX - $sx ; $posY = 0 ; } if ( cv('legend') eq "3") { $posX = 0 ; $posY = $sizeY - $sy ; } if ( cv('legend') eq "4") { $posX = $sizeX - $sx ; $posY = $sizeY - $sy ; } if ( (cv('legend') >=1) and (cv('legend')<=4) ) { addToLayer ("legend", "") ; } elsif (cv('legend') == 5) { # separate file createLegendFile($sx, $sy, "_legend", "#legenddef") ; } } 1 ;