1242 lines
30 KiB
Perl
1242 lines
30 KiB
Perl
#
|
|
# 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 <http://www.gnu.org/licenses/>
|
|
#
|
|
|
|
|
|
package mwMap ;
|
|
|
|
use strict ;
|
|
use warnings ;
|
|
|
|
use mwConfig ;
|
|
# use mwMisc ;
|
|
# use mwFile ;
|
|
# use mwLabel ;
|
|
|
|
use OSM::osm ;
|
|
|
|
use Geo::Proj4 ;
|
|
|
|
|
|
my $areaNum = 0 ;
|
|
my %areaDef = () ;
|
|
|
|
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
|
|
|
|
require Exporter ;
|
|
|
|
@ISA = qw ( Exporter AutoLoader ) ;
|
|
|
|
@EXPORT = qw ( initGraph
|
|
coordsOut
|
|
drawCircle
|
|
drawSquare
|
|
drawTriangle
|
|
drawDiamond
|
|
drawRect
|
|
drawText
|
|
writeMap
|
|
drawWay
|
|
drawArea
|
|
fitsPaper
|
|
getScale
|
|
createPath
|
|
pathText
|
|
placeIcon
|
|
convert
|
|
gridSquare
|
|
getDimensions
|
|
initOneways
|
|
addOnewayArrows
|
|
addAreaIcon
|
|
createShield
|
|
getMaxShieldSize
|
|
getShieldSizes
|
|
getShieldId
|
|
addToLayer
|
|
createLegendFile
|
|
) ;
|
|
|
|
|
|
my @belowWays = ("background", "base", "area", "multi") ;
|
|
|
|
my @aboveWays = ( "arealabels", "wayLabels", "routes", "routeStops", "shields", "nodes", "icons", "text", "additional", "occupied") ;
|
|
|
|
my @elements = ("scale", "ruler", "legend", "wns", "header", "footer", "rectangles", "title", "gpx") ;
|
|
|
|
my %svgLayer = () ;
|
|
my %wayLayer = () ;
|
|
|
|
my $shieldPathId = 0 ;
|
|
my %createdShields = () ;
|
|
my %shieldXSize = () ;
|
|
my %shieldYSize = () ;
|
|
|
|
my $proj ;
|
|
|
|
my ($bottom, $left, $right, $top) ;
|
|
my ($sizeX, $sizeY) ;
|
|
my ($projLeft, $projBottom, $projRight, $projTop) ;
|
|
my ($projSizeX, $projSizeY) ;
|
|
|
|
sub initGraph {
|
|
|
|
# function initializes the picture and projection
|
|
|
|
my ($x, $l, $b, $r, $t) = @_ ;
|
|
|
|
# my $l0 = int($l) - 1 ;
|
|
my $l0 = int(($r+$l) / 2 ) ;
|
|
|
|
$proj = Geo::Proj4->new(
|
|
proj => cv('projection'),
|
|
ellps => cv('ellipsoid'),
|
|
lon_0 => $l0
|
|
) or die "parameter error: ".Geo::Proj4->error. "\n";
|
|
|
|
|
|
($projLeft, $projBottom) = $proj->forward($b, $l) ; # lat/lon!!!
|
|
($projRight, $projTop) = $proj->forward($t, $r) ; # lat/lon!!!
|
|
|
|
$projSizeX = $projRight - $projLeft ;
|
|
$projSizeY = $projTop - $projBottom ;
|
|
|
|
my $factor = $projSizeY / $projSizeX ;
|
|
|
|
$sizeX = int ($x) ;
|
|
$sizeY = int ($x * $factor) ;
|
|
|
|
$top = $t ;
|
|
$left = $l ;
|
|
$right = $r ;
|
|
$bottom = $b ;
|
|
|
|
if ( ( cv('bgcolor') ne "none" ) and ( cv('bgcolor') ne "" ) ) {
|
|
my $col = cv('bgcolor') ;
|
|
my $svgText = "fill=\"$col\" " ;
|
|
drawRect (0, 0, $sizeX, $sizeY, 0, $svgText, "background") ;
|
|
}
|
|
|
|
if ( cv('ruler') ne "0" ) {
|
|
drawRuler() ;
|
|
}
|
|
|
|
if ( cv('scale') ne "0" ) {
|
|
drawScale() ;
|
|
}
|
|
|
|
if ( cv('grid') != 0) {
|
|
drawGrid() ;
|
|
}
|
|
if ( cv('coords') eq "1") {
|
|
drawCoords() ;
|
|
}
|
|
if ( length cv('foot') > 0 ) {
|
|
drawFoot() ;
|
|
}
|
|
if ( length cv('head') > 0 ) {
|
|
drawHead() ;
|
|
}
|
|
|
|
}
|
|
|
|
sub addToLayer {
|
|
my ($layer, $text) = @_ ;
|
|
|
|
if ( $layer =~ /^[\d\-\.]+$/) {
|
|
push @{$wayLayer{$layer}}, $text ;
|
|
# print "adding NUMERIC: $text\n" ;
|
|
}
|
|
else {
|
|
push @{$svgLayer{$layer}}, $text ;
|
|
# print "adding TEXTUAL: $text\n" ;
|
|
}
|
|
}
|
|
|
|
sub drawWay {
|
|
|
|
# accepts list of nodes (plus convert=1) or list of x,y,x,y (convert=0) and draws way/polygon to layerNr if defined or to layerName
|
|
|
|
my ($nodesRef, $convert, $svgString, $layerName, $layerNumber) = @_ ;
|
|
my @points = () ;
|
|
my $valid = 0 ;
|
|
|
|
# convert? and expand.
|
|
my ($lonRef, $latRef, $tagRef) = mwFile::getNodePointers() ;
|
|
if ($convert) {
|
|
foreach my $node (@$nodesRef) {
|
|
my ($x, $y) = convert ( $$lonRef{$node}, $$latRef{$node}) ;
|
|
push @points, $x, $y ;
|
|
if (! coordsOut ($x, $y)) {
|
|
$valid = 1 ;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
@points = @$nodesRef ;
|
|
foreach my $node (@$nodesRef) {
|
|
my ($x, $y) = ( $$lonRef{$node}, $$latRef{$node}) ;
|
|
if (! coordsOut ($x, $y)) {
|
|
$valid = 1 ;
|
|
}
|
|
}
|
|
}
|
|
|
|
my $refp = simplifyPoints (\@points) ;
|
|
@points = @$refp ;
|
|
|
|
if ($valid) {
|
|
|
|
my $svg = "<polyline points=\"" ;
|
|
for (my$i=0; $i<scalar(@points)-1; $i+=2) {
|
|
$svg = $svg . $points[$i] . "," . $points[$i+1] . " " ;
|
|
}
|
|
|
|
$svg = $svg . "\" $svgString />" ;
|
|
|
|
if (defined $layerNumber) {
|
|
push @{ $wayLayer{ $layerNumber } }, $svg ;
|
|
}
|
|
else {
|
|
push @{ $svgLayer { $layerName } }, $svg ;
|
|
}
|
|
}
|
|
else {
|
|
# if () { print "way not drawn, outside\n" ; }
|
|
}
|
|
}
|
|
|
|
|
|
|
|
sub drawText {
|
|
|
|
my ($x, $y, $convert, $text, $svgString, $layerName) = @_ ;
|
|
|
|
if ($convert) {
|
|
($x, $y) = convert ($x, $y) ;
|
|
}
|
|
|
|
if ( ! coordsOut ($x, $y) ) {
|
|
|
|
my $svg = "<text x=\"$x\" y=\"$y\" $svgString>" . $text . "</text>" ;
|
|
|
|
push @{ $svgLayer { $layerName } }, $svg ;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
sub drawCircle {
|
|
|
|
# draws circle element to svgLayer given; if convertCoords then lon / lat is converted to x / y
|
|
# circleradius either in pixel or in meters (convert=1)
|
|
|
|
my ($x, $y, $convertCoords, $radius, $convertRadius, $format, $layerName) = @_ ;
|
|
|
|
if ($convertCoords) {
|
|
($x, $y) = convert ($x, $y) ;
|
|
}
|
|
if ($convertRadius) {
|
|
$radius = $radius / (1000 * distance ($left, $bottom, $right, $bottom) ) * $sizeX ;
|
|
}
|
|
|
|
if ( ! coordsOut ($x, $y) ) {
|
|
|
|
my $svg = "<circle cx=\"$x\" cy=\"$y\" r=\"$radius\" " ;
|
|
$svg .= $format . " />" ;
|
|
|
|
push @{ $svgLayer { $layerName } }, $svg ;
|
|
}
|
|
}
|
|
|
|
sub drawSquare {
|
|
|
|
# draws square element to svgLayer given; if convertCoords then lon / lat is converted to x / y
|
|
# square size either in pixel or in meters (convert=1)
|
|
|
|
my ($x, $y, $convertCoords, $size, $convertSize, $format, $layerName) = @_ ;
|
|
|
|
if ($convertCoords) {
|
|
($x, $y) = convert ($x, $y) ;
|
|
}
|
|
if ($convertSize) {
|
|
$size = $size / (1000 * distance ($left, $bottom, $right, $bottom) ) * $sizeX ;
|
|
}
|
|
|
|
my $x1 = $x - $size ;
|
|
my $y1 = $y - $size ;
|
|
my $dSize = 2 * $size ;
|
|
|
|
if ( ! coordsOut ($x, $y) ) {
|
|
|
|
my $svg = "<rect x=\"$x1\" y=\"$y1\" width=\"$dSize\" height=\"$dSize\" " ;
|
|
$svg .= $format . " />" ;
|
|
|
|
push @{ $svgLayer { $layerName } }, $svg ;
|
|
}
|
|
}
|
|
|
|
sub drawTriangle {
|
|
|
|
# draws triangle element to svgLayer given; if convertCoords then lon / lat is converted to x / y
|
|
# square size either in pixel or in meters (convert=1)
|
|
|
|
my ($x, $y, $convertCoords, $size, $convertSize, $format, $layerName) = @_ ;
|
|
|
|
if ($convertCoords) {
|
|
($x, $y) = convert ($x, $y) ;
|
|
}
|
|
if ($convertSize) {
|
|
$size = $size / (1000 * distance ($left, $bottom, $right, $bottom) ) * $sizeX ;
|
|
}
|
|
|
|
my $h = int ( sqrt ($size * $size / 2) ) ;
|
|
|
|
my $x1 = $x ;
|
|
# my $y1 = $y - $size ;
|
|
my $y1 = $y - $h ;
|
|
my $x2 = $x - $h ;
|
|
my $y2 = $y + $h ;
|
|
my $x3 = $x + $h ;
|
|
my $y3 = $y + $h ;
|
|
|
|
if ( ! coordsOut ($x1, $y1, $x2, $y2, $x3, $y3) ) {
|
|
|
|
my $svg = "<polyline points=\"$x1,$y1 $x2,$y2 $x3,$y3 $x1,$y1\" " ;
|
|
$svg .= $format . " />" ;
|
|
|
|
push @{ $svgLayer { $layerName } }, $svg ;
|
|
}
|
|
}
|
|
|
|
sub drawDiamond {
|
|
|
|
# draws diamond element to svgLayer given; if convertCoords then lon / lat is converted to x / y
|
|
# square size either in pixel or in meters (convert=1)
|
|
|
|
my ($x, $y, $convertCoords, $size, $convertSize, $format, $layerName) = @_ ;
|
|
|
|
if ($convertCoords) {
|
|
($x, $y) = convert ($x, $y) ;
|
|
}
|
|
if ($convertSize) {
|
|
$size = $size / (1000 * distance ($left, $bottom, $right, $bottom) ) * $sizeX ;
|
|
}
|
|
|
|
my $x1 = $x - $size ; # left
|
|
my $y1 = $y ;
|
|
my $x2 = $x ; # top
|
|
my $y2 = $y - $size ;
|
|
my $x3 = $x + $size ; #right
|
|
my $y3 = $y ;
|
|
my $x4 = $x ; # bottom
|
|
my $y4 = $y + $size ;
|
|
|
|
if ( ! coordsOut ($x1, $y1, $x2, $y2, $x3, $y3, $x4, $y4) ) {
|
|
my $svg = "<polyline points=\"$x1,$y1 $x2,$y2 $x3,$y3 $x4,$y4 $x1,$y1\" " ;
|
|
$svg .= $format . " />" ;
|
|
|
|
push @{ $svgLayer { $layerName } }, $svg ;
|
|
}
|
|
}
|
|
|
|
sub drawRect {
|
|
|
|
# draws square element to svgLayer given; if convertCoords then lon / lat is converted to x / y
|
|
# square size either in pixel or in meters (convert=1)
|
|
|
|
my ($x1, $y1, $x2, $y2, $convertCoords, $format, $layerName) = @_ ;
|
|
|
|
if ($convertCoords) {
|
|
($x1, $y1) = convert ($x1, $y1) ;
|
|
($x2, $y2) = convert ($x2, $y2) ;
|
|
}
|
|
|
|
my $sizeX = $x2 - $x1 ;
|
|
my $sizeY = $y2 - $y1 ;
|
|
|
|
if ( ! coordsOut ($x1, $y1, $x2, $y2) ) {
|
|
my $svg = "<rect x=\"$x1\" y=\"$y1\" width=\"$sizeX\" height=\"$sizeY\" " ;
|
|
$svg .= $format . " />" ;
|
|
|
|
push @{ $svgLayer { $layerName } }, $svg ;
|
|
}
|
|
}
|
|
|
|
|
|
sub createPath {
|
|
#
|
|
# creates path element for later use with textPath
|
|
#
|
|
my ($pathName, $refp, $layer) = @_ ;
|
|
|
|
my $refp2 = simplifyPoints ($refp) ;
|
|
my @points = @$refp2 ;
|
|
|
|
my $svg = "<path id=\"" . $pathName . "\" d=\"M " ;
|
|
my $i ;
|
|
my $first = 1 ;
|
|
for ($i=0; $i<scalar(@points); $i+=2) {
|
|
if ($first) {
|
|
$svg = $svg . $points[$i] . "," . $points[$i+1] . " " ;
|
|
$first = 0 ;
|
|
}
|
|
else {
|
|
$svg = $svg . "L " . $points[$i] . "," . $points[$i+1] . " " ;
|
|
}
|
|
}
|
|
$svg = $svg . "\" />\n" ;
|
|
|
|
push @{ $svgLayer{ $layer } }, $svg ;
|
|
}
|
|
|
|
|
|
sub pathText {
|
|
#
|
|
# draws text to path element; alignment: start, middle, end
|
|
#
|
|
my ($svgText, $text, $pathName, $tSpan, $alignment, $offset, $layer) = @_ ;
|
|
|
|
my $svg = "<text $svgText >\n" ;
|
|
$svg = $svg . "<textPath xlink:href=\"#" . $pathName . "\" text-anchor=\"" . $alignment . "\" startOffset=\"" . $offset . "%\" >\n" ;
|
|
$svg = $svg . "<tspan dy=\"" . $tSpan . "\" >" . $text . " </tspan>\n" ;
|
|
$svg = $svg . "</textPath>\n</text>\n" ;
|
|
|
|
push @{ $svgLayer{ $layer } }, $svg ;
|
|
}
|
|
|
|
|
|
sub placeIcon {
|
|
#
|
|
# create SVG text for icons
|
|
#
|
|
|
|
|
|
my ($x, $y, $icon, $sizeX, $sizeY, $layer) = @_ ;
|
|
|
|
if ( ! coordsOut ($x, $y) ) {
|
|
|
|
my ($out) = "<image x=\"" . $x . "\"" ;
|
|
$out .= " y=\"" . $y . "\"" ;
|
|
if ($sizeX > 0) { $out .= " width=\"" . $sizeX . "\"" ; }
|
|
if ($sizeY > 0) { $out .= " height=\"" . $sizeY . "\"" ; }
|
|
$out .= " xlink:href=\"" . $icon . "\" />" ;
|
|
|
|
push @{ $svgLayer{ $layer } }, $out ;
|
|
}
|
|
}
|
|
|
|
|
|
sub drawArea {
|
|
#
|
|
# draws mp in svg ARRAY of ARRAY of nodes/coordinates
|
|
#
|
|
my ($svgText, $icon, $ref, $convert, $layer) = @_ ;
|
|
my @ways = @$ref ;
|
|
my $i ;
|
|
my $svg = "" ;
|
|
my $valid = 1 ;
|
|
my @newArray = () ;
|
|
|
|
# TODO loop converts original data !!!
|
|
|
|
if ($convert) {
|
|
my ($lonRef, $latRef, $tagRef) = mwFile::getNodePointers () ;
|
|
foreach my $aRef (@ways) {
|
|
my @way = @$aRef ;
|
|
my @newCoords = () ;
|
|
foreach my $n (@way) {
|
|
my ($x, $y) = convert ($$lonRef{$n}, $$latRef{$n}) ;
|
|
push @newCoords, $x, $y ;
|
|
if (coordsOut ($x, $y)) {
|
|
$valid = 0 ;
|
|
}
|
|
}
|
|
push @newArray , [@newCoords] ;
|
|
}
|
|
@ways = @newArray ;
|
|
}
|
|
|
|
if (defined $areaDef{$icon}) {
|
|
$svg = "<path $svgText fill-rule=\"evenodd\" style=\"fill:url(" . $areaDef{$icon} . ")\" d=\"" ;
|
|
}
|
|
else {
|
|
$svg = "<path $svgText fill-rule=\"evenodd\" d=\"" ;
|
|
}
|
|
|
|
foreach my $way (@ways) {
|
|
my @actual = @$way ;
|
|
for ($i=0; $i<scalar(@actual); $i+=2) {
|
|
if ($i == 0) { $svg .= " M " ; } else { $svg .= " L " ; }
|
|
$svg = $svg . $actual[$i] . " " . $actual[$i+1] ;
|
|
}
|
|
$svg .= " z" ;
|
|
}
|
|
|
|
$svg = $svg . "\" />" ;
|
|
|
|
if ($valid) {
|
|
push @{ $svgLayer{ $layer } }, $svg ;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
sub writeMap {
|
|
|
|
my $fileName = cv ('out') ;
|
|
|
|
open (my $file, ">", $fileName) || die "can't open svg output file $fileName\n";
|
|
|
|
print $file "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\n" ;
|
|
print $file "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\" >\n" ;
|
|
|
|
my $w = $sizeX / 300 * 2.54 ; # cm
|
|
my $h = $sizeY / 300 * 2.54 ;
|
|
|
|
my ($svg) = "<svg version=\"1.1\" baseProfile=\"full\" xmlns=\"http://www.w3.org/2000/svg\" " ;
|
|
$svg .= "xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:ev=\"http://www.w3.org/2001/xml-events\" " ;
|
|
$svg .= "width=\"$w" . "cm\" height=\"$h" . "cm\" viewBox=\"0 0 $sizeX $sizeY\">\n" ;
|
|
print $file $svg ;
|
|
|
|
# definitions
|
|
if ( defined @{$svgLayer{'definitions'}} ) {
|
|
print $file "<defs>\n" ;
|
|
foreach ( @{$svgLayer{'definitions'}} ) { print $file $_, "\n" ; }
|
|
print $file "</defs>\n" ;
|
|
}
|
|
|
|
# below ways
|
|
foreach my $layer (@belowWays) {
|
|
if ( defined @{$svgLayer{$layer}} ) {
|
|
print $file "<g id=\"$layer\">\n" ;
|
|
foreach ( @{$svgLayer{$layer}} ) { print $file $_, "\n" ; }
|
|
print $file "</g>\n" ;
|
|
}
|
|
}
|
|
|
|
# ways
|
|
foreach my $layer (sort {$a <=> $b} keys %wayLayer) {
|
|
if ( defined @{$wayLayer{$layer}} ) {
|
|
print $file "<g id=\"way$layer\">\n" ;
|
|
foreach ( @{$wayLayer{$layer}} ) { print $file $_, "\n" ; }
|
|
print $file "</g>\n" ;
|
|
}
|
|
}
|
|
|
|
|
|
# above of ways
|
|
foreach my $layer (@aboveWays) {
|
|
if ( defined @{$svgLayer{$layer}} ) {
|
|
print $file "<g id=\"$layer\">\n" ;
|
|
foreach ( @{$svgLayer{$layer}} ) { print $file $_, "\n" ; }
|
|
print $file "</g>\n" ;
|
|
}
|
|
}
|
|
|
|
|
|
foreach my $layer (@elements) {
|
|
if (defined @{$svgLayer{$layer}}) {
|
|
print $file "<g id=\"$layer\">\n" ;
|
|
foreach ( @{$svgLayer{$layer}} ) { print $file $_, "\n" ; }
|
|
print $file "</g>\n" ;
|
|
}
|
|
}
|
|
|
|
|
|
print $file "</svg>\n" ;
|
|
|
|
close ($file) ;
|
|
|
|
if (cv('pdf') eq "1") {
|
|
my ($pdfName) = $fileName ;
|
|
$pdfName =~ s/\.svg/\.pdf/ ;
|
|
print "creating pdf file $pdfName ...\n" ;
|
|
`inkscape -A $pdfName $fileName` ;
|
|
}
|
|
|
|
if (cv('png') eq "1") {
|
|
my ($pngName) = $fileName ;
|
|
$pngName =~ s/\.svg/\.png/ ;
|
|
my $dpi = cv('pngdpi') ;
|
|
print "creating png file $pngName ($dpi dpi)...\n" ;
|
|
`inkscape --export-dpi=$dpi -e $pngName $fileName` ;
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
# -----------------------------------------------------------------------------------
|
|
|
|
sub drawGrid {
|
|
#
|
|
# draw grid on top of map. receives number of parts in x/lon direction
|
|
#
|
|
|
|
my $number = cv ('grid') ;
|
|
my $color = cv ('gridcolor') ;
|
|
|
|
my $part = $sizeX / $number ;
|
|
my $numY = $sizeY / $part ;
|
|
|
|
my $svgStringLine="stroke=\"$color\" stroke-width=\"5\" stroke-dasharray=\"30,30\"" ;
|
|
|
|
my $svgStringText = mwMisc::createTextSVG ( cv('elementFontFamily'), cv('elementFont'), undef, undef, 60, $color, undef, undef) ;
|
|
|
|
# vertical lines
|
|
for (my $i = 1; $i <= $number; $i++) {
|
|
my @coords = ($i*$part, 0, $i*$part, $sizeY) ;
|
|
drawWay (\@coords, 0, $svgStringLine, "additional", undef) ;
|
|
drawText ( ($i-1)*$part+$part/2, 160, 0, chr($i+64), $svgStringText, "additional") ;
|
|
|
|
}
|
|
|
|
# hor. lines
|
|
for (my $i = 1; $i <= $numY; $i++) {
|
|
my @coords = (0, $i*$part, $sizeX, $i*$part) ;
|
|
drawWay (\@coords, 0, $svgStringLine, "additional", undef) ;
|
|
drawText ( 20, ($i-1)*$part+$part/2, 0, $i, $svgStringText, "additional") ;
|
|
|
|
}
|
|
}
|
|
|
|
sub drawCoords {
|
|
#
|
|
# draws coordinates grid on map
|
|
#
|
|
my $exp = cv('coordsexp') ;
|
|
my $color = cv ('coordscolor');
|
|
my $step = 10 ** $exp ;
|
|
|
|
# vert. lines
|
|
my $start = int ($left / $step) + 1 ;
|
|
my $actual = $start * $step ;
|
|
|
|
my $svgStringLine="stroke=\"$color\" stroke-width=\"3\"" ;
|
|
my $svgStringText = mwMisc::createTextSVG ( cv('elementFontFamily'), cv('elementFont'), undef, undef, 30, $color, undef, undef) ;
|
|
|
|
while ($actual < $right) {
|
|
my ($x1, $y1) = convert ($actual, 0) ;
|
|
|
|
drawText ( $x1+10, $sizeY-50, 0, $actual, $svgStringText, "additional") ;
|
|
|
|
my @coords = ($x1, 0, $x1, $sizeY) ;
|
|
drawWay (\@coords, 0, $svgStringLine, "additional", undef) ;
|
|
|
|
$actual += $step ;
|
|
}
|
|
|
|
# hor lines
|
|
$start = int ($bottom / $step) + 1 ;
|
|
$actual = $start * $step ;
|
|
while ($actual < $top) {
|
|
# print "actualY: $actual\n" ;
|
|
my ($x1, $y1) = convert (0, $actual) ;
|
|
|
|
drawText ( $sizeX-180, $y1+30, 0, $actual, $svgStringText, "additional") ;
|
|
|
|
my @coords = (0, $y1, $sizeX, $y1) ;
|
|
drawWay (\@coords, 0, $svgStringLine, "additional", undef) ;
|
|
|
|
$actual += $step ;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
# -----------------------------------------------------------------------------------
|
|
|
|
sub convert {
|
|
|
|
# converts real world coordinates to system graph pixel coordinates
|
|
|
|
my ($x, $y) = @_ ;
|
|
|
|
my ($x1, $y1) = $proj->forward($y, $x) ; # lat/lon!!!
|
|
|
|
my $x2 = int ( ($x1 - $projLeft) / ($projRight - $projLeft) * $sizeX ) ;
|
|
my $y2 = $sizeY - int ( ($y1 - $projBottom) / ($projTop - $projBottom) * $sizeY ) ;
|
|
|
|
return ($x2, $y2) ;
|
|
}
|
|
|
|
sub simplifyPoints {
|
|
my $ref = shift ;
|
|
my @points = @$ref ;
|
|
my @newPoints ;
|
|
my $maxIndex = $#points ;
|
|
|
|
if (scalar @points > 4) {
|
|
# push first
|
|
push @newPoints, $points[0], $points[1] ;
|
|
|
|
# push other
|
|
for (my $i=2; $i <= $maxIndex; $i+=2) {
|
|
# $simplifyTotal++ ;
|
|
if ( ($points[$i]==$points[$i-2]) and ($points[$i+1]==$points[$i-1]) ) {
|
|
# same
|
|
# $simplified++ ;
|
|
}
|
|
else {
|
|
push @newPoints, $points[$i], $points[$i+1] ;
|
|
}
|
|
}
|
|
return (\@newPoints) ;
|
|
}
|
|
else {
|
|
return ($ref) ;
|
|
}
|
|
|
|
}
|
|
|
|
sub drawRuler {
|
|
#
|
|
# draws ruler
|
|
#
|
|
my $col = cv('rulercolor') ;
|
|
|
|
my $B ; my $B2 ;
|
|
my $L ; my $Lpix ;
|
|
my $x ;
|
|
my $text ;
|
|
|
|
my $lineThickness = 8 ; # at 300dpi
|
|
my $textSize = 40 ; # at 300 dpi
|
|
my $textDist = 60 ; # at 300 dpi
|
|
my $lineLen = 40 ; # at 300 dpi
|
|
|
|
my $xOffset = 2 * $lineThickness ;
|
|
my $yOffset = 2 * $lineThickness ;
|
|
|
|
$B = $right - $left ; # in degrees
|
|
$B2 = $B * cos ($top/360*3.14*2) * 111.1 ; # in km
|
|
$text = "50m" ; $x = 0.05 ; # default length ruler
|
|
|
|
if ($B2 > 0.5) {$text = "100 m" ; $x = 0.1 ; } # enlarge ruler
|
|
if ($B2 > 1) {$text = "500 m" ; $x = 0.5 ; } # enlarge ruler
|
|
if ($B2 > 5) {$text = "1 km" ; $x = 1 ; }
|
|
if ($B2 > 10) {$text = "5 km" ; $x = 5 ; }
|
|
if ($B2 > 50) {$text = "10 km" ; $x = 10 ; }
|
|
$L = $x / (cos ($top/360*3.14*2) * 111.1 ) ; # length ruler in km
|
|
$Lpix = $L / $B * $sizeX ; # length ruler in pixels
|
|
|
|
my $rSizeX = int ($Lpix + 2 * $xOffset) ;
|
|
my $rSizeY = int ($lineLen + $textSize + 3 * $yOffset) ;
|
|
addToLayer ("definitions", "<g id=\"rulerdef\" width=\"$rSizeX\" height=\"$rSizeY\" >") ;
|
|
|
|
if ( cv('rulerbackground') ne "none" ) {
|
|
my $color = cv ('rulerbackground') ;
|
|
my $svgString = "fill=\"$color\"" ;
|
|
drawRect (0, 0, $rSizeX, $rSizeY, 0, $svgString, "definitions") ;
|
|
}
|
|
|
|
my $svgString = "stroke=\"$col\" stroke-width=\"$lineThickness\" stroke-linecap=\"round\" " ;
|
|
|
|
my @coords = ($xOffset, $yOffset, $xOffset+$Lpix, $yOffset) ;
|
|
drawWay (\@coords, 0, $svgString, "definitions", undef) ;
|
|
|
|
@coords = ($xOffset, $yOffset, $xOffset, $yOffset+$lineLen) ;
|
|
drawWay (\@coords, 0, $svgString, "definitions", undef) ;
|
|
|
|
@coords = ($xOffset+$Lpix, $yOffset, $xOffset+$Lpix, $yOffset+$lineLen) ;
|
|
drawWay (\@coords, 0, $svgString, "definitions", undef) ;
|
|
|
|
@coords = ($xOffset+$Lpix/2, $yOffset, $xOffset+$Lpix/2, $yOffset+$lineLen/2) ;
|
|
drawWay (\@coords, 0, $svgString, "definitions", undef) ;
|
|
|
|
|
|
my $scale= getScale() ;
|
|
$text .= "(1:$scale)" ;
|
|
|
|
|
|
$svgString = mwMisc::createTextSVG ( cv('elementFontFamily'), cv('elementFont'), undef, undef, 35, $col, undef, undef) ;
|
|
drawText ($xOffset, $yOffset+$textDist+30, 0, $text, $svgString, "definitions") ;
|
|
|
|
addToLayer ("definitions", "</g>") ;
|
|
|
|
my $posX = 40 ; my $posY = 40 ;
|
|
|
|
if ( cv('ruler') eq "2") {
|
|
$posX = $sizeX - 40 - $rSizeX ;
|
|
$posY = 40 ;
|
|
}
|
|
|
|
if ( cv('ruler') eq "3") {
|
|
$posX = 40 ;
|
|
$posY = $sizeY - 40 - $rSizeY ;
|
|
}
|
|
|
|
if ( cv('ruler') eq "4") {
|
|
$posX = $sizeX - 40 - $rSizeX ;
|
|
$posY = $sizeY - 40 - $rSizeY ;
|
|
}
|
|
|
|
addToLayer ("ruler", "<use x=\"$posX\" y=\"$posY\" xlink:href=\"#rulerdef\" />") ;
|
|
}
|
|
|
|
sub drawScale {
|
|
#
|
|
# draws scale value
|
|
#
|
|
my $col = cv('scalecolor') ;
|
|
|
|
my $xOffset = 20 ;
|
|
my $yOffset = 20 ;
|
|
my $fontSize = 70 ;
|
|
my $borderDist = 60 ;
|
|
|
|
my $rSizeX = int (350 + 2 * $xOffset) ;
|
|
my $rSizeY = int ($fontSize + 2 * $yOffset) ;
|
|
addToLayer ("definitions", "<g id=\"scaledef\" width=\"$rSizeX\" height=\"$rSizeY\" >") ;
|
|
|
|
if ( cv('scalebackground') ne "none" ) {
|
|
my $color = cv ('scalebackground') ;
|
|
my $svgString = "fill=\"$color\"" ;
|
|
drawRect (0, 0, $rSizeX, $rSizeY, 0, $svgString, "definitions") ;
|
|
}
|
|
|
|
my $scale= getScale() ;
|
|
|
|
my $svgString = mwMisc::createTextSVG ( cv('elementFontFamily'), cv('elementFont'), undef, undef, $fontSize, $col, undef, undef) ;
|
|
drawText ($xOffset, $fontSize + $yOffset, 0, "1:$scale", $svgString, "definitions") ;
|
|
|
|
addToLayer ("definitions", "</g>") ;
|
|
|
|
my $posX = $borderDist ; my $posY = $borderDist ;
|
|
|
|
if ( cv('scale') eq "2") {
|
|
$posX = $sizeX - $borderDist - $rSizeX ;
|
|
$posY = $borderDist ;
|
|
}
|
|
|
|
if ( cv('scale') eq "3") {
|
|
$posX = $borderDist ;
|
|
$posY = $sizeY - $borderDist - $rSizeY ;
|
|
}
|
|
|
|
if ( cv('scale') eq "4") {
|
|
$posX = $sizeX - $borderDist - $rSizeX ;
|
|
$posY = $sizeY - $borderDist - $rSizeY ;
|
|
}
|
|
|
|
addToLayer ("scale", "<use x=\"$posX\" y=\"$posY\" xlink:href=\"#scaledef\" />") ;
|
|
}
|
|
|
|
sub drawFoot {
|
|
#
|
|
# draws footer
|
|
#
|
|
my $col = cv('footcolor') ;
|
|
my $text = cv('foot') ;
|
|
my $len = length $text ;
|
|
|
|
my $xOffset = 20 ;
|
|
my $yOffset = 20 ;
|
|
my $fontSize = cv('footsize') ;
|
|
my $borderDistX = 60 ;
|
|
my $borderDistY = $fontSize + 50 ;
|
|
|
|
my $rSizeX = int ($len*cv('ppc')/10*$fontSize + 2 * $xOffset) ;
|
|
my $rSizeY = int ($fontSize + 2 * $yOffset) ;
|
|
addToLayer ("definitions", "<g id=\"footdef\" width=\"$rSizeX\" height=\"$rSizeY\" >") ;
|
|
|
|
if ( cv('footbackground') ne "none" ) {
|
|
my $color = cv ('footbackground') ;
|
|
my $svgString = "fill=\"$color\"" ;
|
|
drawRect (0, 0, $rSizeX, $rSizeY, 0, $svgString, "definitions") ;
|
|
}
|
|
|
|
my $svgString = mwMisc::createTextSVG ( cv('elementFontFamily'), cv('elementFont'), undef, undef, $fontSize, $col, undef, undef) ;
|
|
drawText ($xOffset, $fontSize + $yOffset, 0, $text, $svgString, "definitions") ;
|
|
|
|
addToLayer ("definitions", "</g>") ;
|
|
|
|
my $posX = $borderDistX ; my $posY = $sizeY - $borderDistY ;
|
|
|
|
addToLayer ("footer", "<use x=\"$posX\" y=\"$posY\" xlink:href=\"#footdef\" />") ;
|
|
}
|
|
|
|
sub drawHead {
|
|
#
|
|
# draws header
|
|
#
|
|
my $col = cv('headcolor') ;
|
|
my $text = cv('head') ;
|
|
my $len = length $text ;
|
|
|
|
my $xOffset = 20 ;
|
|
my $yOffset = 20 ;
|
|
my $fontSize = cv('headsize') ;
|
|
my $borderDistX = 60 ;
|
|
my $borderDistY = 60 ;
|
|
|
|
my $rSizeX = int ($len*cv('ppc')/10*$fontSize + 2 * $xOffset) ;
|
|
my $rSizeY = int ($fontSize + 2 * $yOffset) ;
|
|
addToLayer ("definitions", "<g id=\"headdef\" width=\"$rSizeX\" height=\"$rSizeY\" >") ;
|
|
|
|
if ( cv('headbackground') ne "none" ) {
|
|
my $color = cv ('headbackground') ;
|
|
my $svgString = "fill=\"$color\"" ;
|
|
drawRect (0, 0, $rSizeX, $rSizeY, 0, $svgString, "definitions") ;
|
|
}
|
|
|
|
my $svgString = mwMisc::createTextSVG ( cv('elementFontFamily'), cv('elementFont'), undef, undef, $fontSize, $col, undef, undef) ;
|
|
drawText ($xOffset, $fontSize + $yOffset, 0, $text, $svgString, "definitions") ;
|
|
|
|
addToLayer ("definitions", "</g>") ;
|
|
|
|
my $posX = $borderDistX ; my $posY = $borderDistY ;
|
|
|
|
addToLayer ("header", "<use x=\"$posX\" y=\"$posY\" xlink:href=\"#headdef\" />") ;
|
|
}
|
|
|
|
|
|
sub fitsPaper {
|
|
#
|
|
# calculates on what paper size the map will fit. sizes are taken from global variables
|
|
#
|
|
|
|
my $width = $sizeX / 300 * 2.54 ;
|
|
my $height = $sizeY / 300 * 2.54 ;
|
|
my $paper = "" ;
|
|
|
|
my @sizes = () ;
|
|
push @sizes, ["4A0", 168.2, 237.8] ;
|
|
push @sizes, ["2A0", 118.9, 168.2] ;
|
|
push @sizes, ["A0", 84.1, 118.9] ;
|
|
push @sizes, ["A1", 59.4, 84.1] ;
|
|
push @sizes, ["A2", 42, 59.4] ;
|
|
push @sizes, ["A3", 29.7, 42] ;
|
|
push @sizes, ["A4", 21, 29.7] ;
|
|
push @sizes, ["A5", 14.8, 21] ;
|
|
push @sizes, ["A6", 10.5, 14.8] ;
|
|
push @sizes, ["A7", 7.4, 10.5] ;
|
|
push @sizes, ["none", 0, 0] ;
|
|
|
|
foreach my $size (@sizes) {
|
|
if ( ( ($width<=$size->[1]) and ($height<=$size->[2]) ) or ( ($width<=$size->[2]) and ($height<=$size->[1]) ) ) {
|
|
$paper = $size->[0] ;
|
|
}
|
|
}
|
|
|
|
return ($paper, $width, $height) ;
|
|
}
|
|
|
|
sub getScale {
|
|
#
|
|
# calcs scale of map
|
|
#
|
|
my ($dpi) = 300 ;
|
|
|
|
my $dist = distance ($left, $bottom, $right, $bottom) ;
|
|
my $inches = $sizeX / $dpi ;
|
|
my $cm = $inches * 2.54 ;
|
|
my $scale = int ( $dist / ($cm/100/1000) ) ;
|
|
$scale = int ($scale / 100) * 100 ;
|
|
|
|
return ($scale) ;
|
|
}
|
|
|
|
sub gridSquare {
|
|
#
|
|
# returns grid square of given coordinates for directories
|
|
#
|
|
my ($lon, $lat) = @_ ;
|
|
|
|
my $parts = cv('grid') ;
|
|
|
|
my ($x, $y) = convert ($lon, $lat) ;
|
|
my $xi = int ($x / ($sizeX / $parts)) + 1 ;
|
|
my $yi = int ($y / ($sizeX / $parts)) + 1 ;
|
|
if ( ($x >= 0) and ($x <= $sizeX) and ($y >= 0) and ($y <= $sizeY) ) {
|
|
return (chr($xi+64) . $yi) ;
|
|
}
|
|
else {
|
|
return undef ;
|
|
}
|
|
}
|
|
|
|
|
|
sub getDimensions {
|
|
return ($sizeX, $sizeY) ;
|
|
}
|
|
|
|
# ----------------------------------------------------------------------
|
|
|
|
sub initOneways {
|
|
#
|
|
# write marker defs to svg
|
|
#
|
|
my $color = cv('onewaycolor') ;
|
|
|
|
my @svgOutputDef = () ;
|
|
for (my $markerSize = 5; $markerSize <= 40; $markerSize++) {
|
|
push @svgOutputDef, "<marker id=\"Arrow$markerSize\"" ;
|
|
push @svgOutputDef, "viewBox=\"0 0 10 10\" refX=\"5\" refY=\"5\"" ;
|
|
push @svgOutputDef, "markerUnits=\"strokeWidth\"" ;
|
|
push @svgOutputDef, "markerWidth=\"" . $markerSize . "\" markerHeight=\"" . $markerSize . "\"" ;
|
|
push @svgOutputDef, "orient=\"auto\">" ;
|
|
push @svgOutputDef, "<path d=\"M 0 4 L 6 4 L 6 2 L 10 5 L 6 8 L 6 6 L 0 6 Z\" fill=\"" . $color . "\" />" ;
|
|
push @svgOutputDef, "</marker>" ;
|
|
}
|
|
|
|
|
|
foreach my $line (@svgOutputDef) {
|
|
addToLayer ("definitions", $line) ;
|
|
}
|
|
}
|
|
|
|
sub addOnewayArrows {
|
|
#
|
|
# adds oneway arrows to new pathes
|
|
#
|
|
my ($wayNodesRef, $direction, $thickness, $layer) = @_ ;
|
|
my @wayNodes = @$wayNodesRef ;
|
|
my ($lonRef, $latRef) = mwFile::getNodePointers() ;
|
|
|
|
if ($direction == -1) { @wayNodes = reverse @wayNodes ; }
|
|
|
|
my $minDist = cv('onewaysize') * 1.5 ;
|
|
my $markerSize = cv('onewaySize') ;
|
|
|
|
if ( cv('onewayAutoSize') != 0 ) {
|
|
$markerSize = int ( $thickness / 100 * cv('onewayAutoSize') ) ;
|
|
if ( $markerSize < 5 ) { $markerSize = 5 ; }
|
|
if ( $markerSize > 40 ) { $markerSize = 40 ; }
|
|
$minDist = $markerSize * 1.5 ;
|
|
}
|
|
|
|
# create new pathes with new nodes
|
|
for (my $i = 0; $i < scalar( @wayNodes ) - 1; $i++ ) {
|
|
my ($x1, $y1) = convert ($$lonRef{$wayNodes[$i]}, $$latRef{$wayNodes[$i]}) ;
|
|
my ($x2, $y2) = convert ($$lonRef{$wayNodes[$i+1]}, $$latRef{$wayNodes[$i+1]}) ;
|
|
my $xn = ($x2+$x1) / 2 ;
|
|
my $yn = ($y2+$y1) / 2 ;
|
|
if (sqrt (($x2-$x1)**2+($y2-$y1)**2) > $minDist) {
|
|
# create path
|
|
# use path
|
|
my $svg = "<path d=\"M $x1 $y1 L $xn $yn L $x2 $y2\" fill=\"none\" marker-mid=\"url(#Arrow$markerSize)\" />" ;
|
|
|
|
addToLayer ($layer+$thickness/100, $svg) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
# ----------------------------------------------------------------------------
|
|
|
|
sub addAreaIcon {
|
|
#
|
|
# initial collection of area icons
|
|
#
|
|
my $fileNameOriginal = shift ;
|
|
# print "AREA: $fileNameOriginal\n" ;
|
|
my $result = open (my $file, "<", $fileNameOriginal) ;
|
|
close ($file) ;
|
|
if ($result) {
|
|
my ($x, $y) ;
|
|
if (grep /.svg/, $fileNameOriginal) {
|
|
($x, $y) = mwMisc::sizeSVG ($fileNameOriginal) ;
|
|
if ( ($x == 0) or ($y == 0) ) {
|
|
$x = 32 ; $y = 32 ;
|
|
print "WARNING: size of file $fileNameOriginal could not be determined. Set to 32px x 32px\n" ;
|
|
}
|
|
}
|
|
|
|
if (grep /.png/, $fileNameOriginal) {
|
|
($x, $y) = mwMisc::sizePNG ($fileNameOriginal) ;
|
|
}
|
|
|
|
if (!defined $areaDef{$fileNameOriginal}) {
|
|
|
|
my $x1 = $x ; # scale area icons
|
|
my $y1 = $y ;
|
|
my $fx = $x1 / $x ;
|
|
my $fy = $y1 / $y ;
|
|
|
|
# add defs to svg output
|
|
my $defName = "A" . $areaNum ;
|
|
# print "INFO area icon $fileNameOriginal, $defName, $x, $y --- $x1, $y1 --- $fx, $fy --- processed.\n" ;
|
|
$areaNum++ ;
|
|
|
|
my $svgElement = "<pattern id=\"" . $defName . "\" width=\"" . $x . "\" height=\"" . $y . "\" " ;
|
|
$svgElement .= "patternTransform=\"translate(0,0) scale(" . $fx . "," . $fy . ")\" \n" ;
|
|
$svgElement .= "patternUnits=\"userSpaceOnUse\">\n" ;
|
|
$svgElement .= " <image xlink:href=\"" . $fileNameOriginal . "\"/>\n" ;
|
|
$svgElement .= "</pattern>\n" ;
|
|
|
|
addToLayer ("definitions", $svgElement) ;
|
|
|
|
$defName = "#" . $defName ;
|
|
$areaDef{$fileNameOriginal} = $defName ;
|
|
}
|
|
}
|
|
else {
|
|
print "WARNING: area icon $fileNameOriginal not found!\n" ;
|
|
}
|
|
}
|
|
|
|
# ----------------------------------------------------------------------------
|
|
|
|
sub createShield {
|
|
my ($name, $targetSize) = @_ ;
|
|
my @a = split /:/, $name ;
|
|
my $shieldFileName = $a[1] ;
|
|
my $shieldText = $a[2] ;
|
|
|
|
if (! defined $createdShields{$name}) {
|
|
open (my $file, "<", $shieldFileName) or die ("ERROR: shield definition $shieldFileName not found.\n") ;
|
|
my @defText = <$file> ;
|
|
close ($file) ;
|
|
|
|
# get size
|
|
# calc scaling
|
|
my $sizeX = 0 ;
|
|
my $sizeY = 0 ;
|
|
foreach my $line (@defText) {
|
|
if (grep /<svg/, $line) {
|
|
($sizeY) = ( $line =~ /height=\"(\d+)px\"/ ) ;
|
|
($sizeX) = ( $line =~ /width=\"(\d+)px\"/ ) ;
|
|
if ( (!defined $sizeX) or (!defined $sizeY) ) {
|
|
die "ERROR: size of shield in $shieldFileName could not be determined.\n" ;
|
|
}
|
|
}
|
|
}
|
|
if ( ($sizeX == 0) or ($sizeY == 0) ) {
|
|
die "ERROR: initial size of shield $shieldFileName could not be determined.\n" ;
|
|
}
|
|
|
|
my $scaleFactor = $targetSize / $sizeY ;
|
|
|
|
$shieldXSize{ $name } = int ($sizeX * $scaleFactor) ;
|
|
$shieldYSize{ $name } = int ($sizeY * $scaleFactor) ;
|
|
|
|
$shieldPathId++ ;
|
|
my $shieldPathName = "ShieldPath" . $shieldPathId ;
|
|
my $shieldGroupName = "ShieldGroup" . $shieldPathId ;
|
|
|
|
foreach my $line (@defText) {
|
|
$line =~ s/REPLACEID/$shieldGroupName/ ;
|
|
$line =~ s/REPLACESCALE/$scaleFactor/g ;
|
|
$line =~ s/REPLACEPATH/$shieldPathName/ ;
|
|
$line =~ s/REPLACELABEL/$shieldText/ ;
|
|
}
|
|
|
|
foreach my $line (@defText) {
|
|
addToLayer ("definitions", $line) ;
|
|
}
|
|
|
|
$createdShields{$name} = $shieldGroupName ;
|
|
}
|
|
}
|
|
|
|
sub getMaxShieldSize {
|
|
my $name = shift ;
|
|
my $max = $shieldXSize{$name} ;
|
|
if ( $shieldYSize{$name} > $max) { $max = $shieldYSize{$name} ; }
|
|
return $max ;
|
|
}
|
|
|
|
sub getShieldSizes {
|
|
my $name = shift ;
|
|
my $x = $shieldXSize{$name} ;
|
|
my $y = $shieldYSize{$name} ;
|
|
return $x, $y ;
|
|
}
|
|
|
|
sub getShieldId {
|
|
my $name = shift ;
|
|
return $createdShields{$name} ;
|
|
}
|
|
|
|
# --------------------------------------------------------------------
|
|
|
|
sub createLegendFile {
|
|
my ($x, $y, $extension, $group) = @_ ;
|
|
|
|
my $svgName = cv('out') ;
|
|
$svgName =~ s/\.svg/$extension\.svg/i ;
|
|
my $pngName = $svgName ;
|
|
$pngName =~ s/\.svg/\.png/i ;
|
|
my $pdfName = $svgName ;
|
|
$pdfName =~ s/\.svg/\.pdf/i ;
|
|
|
|
|
|
open (my $file, ">", $svgName) || die "can't open legend svg output file $svgName\n";
|
|
|
|
print $file "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\n" ;
|
|
print $file "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\" >\n" ;
|
|
|
|
my $w = $x / 300 * 2.54 ; # cm
|
|
my $h = $y / 300 * 2.54 ;
|
|
|
|
my ($svg) = "<svg version=\"1.1\" baseProfile=\"full\" xmlns=\"http://www.w3.org/2000/svg\" " ;
|
|
$svg .= "xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:ev=\"http://www.w3.org/2001/xml-events\" " ;
|
|
$svg .= "width=\"$w" . "cm\" height=\"$h" . "cm\" viewBox=\"0 0 $x $y\">\n" ;
|
|
print $file $svg ;
|
|
|
|
print $file "<defs>\n" ;
|
|
foreach ( @{$svgLayer{'definitions'}} ) { print $file $_, "\n" ; }
|
|
print $file "</defs>\n" ;
|
|
|
|
print $file "<use x=\"0\" y=\"0\" xlink:href=\"$group\" />\n" ;
|
|
print $file "</svg>\n" ;
|
|
close $file ;
|
|
|
|
if (cv('pdf') eq "1") {
|
|
print "creating pdf file $pdfName ...\n" ;
|
|
`inkscape -A $pdfName $svgName` ;
|
|
}
|
|
|
|
if (cv('png') eq "1") {
|
|
my $dpi = cv('pngdpi') ;
|
|
print "creating png file $pngName ($dpi dpi)...\n" ;
|
|
`inkscape --export-dpi=$dpi -e $pngName $svgName` ;
|
|
}
|
|
}
|
|
|
|
sub coordsOut {
|
|
my @points = @_ ;
|
|
|
|
my $allOut = 0 ;
|
|
|
|
my $outLeft = 1 ;
|
|
my $outRight = 1 ;
|
|
my $outTop = 1 ;
|
|
my $outBottom = 1 ;
|
|
|
|
for (my $i=0; $i < scalar(@points) - 1; $i += 2) {
|
|
my $x = $points[$i] ;
|
|
my $y = $points[$i+1] ;
|
|
if ($x >= 0) { $outLeft = 0 ; }
|
|
if ($x <= $sizeX) { $outRight = 0 ; }
|
|
if ($y >= 0) { $outBottom = 0 ; }
|
|
if ($y <= $sizeY) { $outTop = 0 ; }
|
|
}
|
|
|
|
if ( ($outLeft) or ($outRight) or ($outTop) or ($outBottom) ) { $allOut = 1 ; }
|
|
|
|
return $allOut ;
|
|
}
|
|
|
|
1 ;
|
|
|
|
|