Closes #17: use svgwrite.

This commit is contained in:
Sergey Vartanov 2020-08-30 10:41:39 +03:00
parent 715ffcacb1
commit f3a9e149b4
6 changed files with 118 additions and 384 deletions

View file

@ -1,2 +1,4 @@
svgwrite
numpy>=1.18.1
PyYAML>=4.2b1
urllib3>=1.25.6

View file

@ -4,22 +4,21 @@ Author: Sergey Vartanov (me@enzet.ru).
import os
import random
import svgwrite
import yaml
from roentgen import extract_icon
from roentgen import svg
from typing import Any, Dict
def draw_icon(
output_file, icon: Dict[str, Any], x: float, y: float,
svg, icon: Dict[str, Any], x: float, y: float,
color: str = "444444"):
output_file.write(
f'<path d="{icon["path"]}" '
f'style="fill:#{color};stroke:none;" '
f'transform="translate({icon["x"] + x},{icon["y"] + y})" />\n')
svg.add(svg.path(
d=icon["path"], fill=f"#{color}", stroke="none",
transform=f'translate({icon["x"] + x},{icon["y"] + y})'))
def draw_grid():
@ -103,16 +102,16 @@ def draw_grid():
height = int(number / (width / step) + 1) * step
output_file = svg.SVG(open(icon_grid_file_name, "w+"))
output_file.begin(width, height)
svg = svgwrite.Drawing(icon_grid_file_name, (width, height))
output_file.rect(0, 0, width, height, color="FFFFFF")
svg.add(svg.rect((0, 0), (width, height), fill="#FFFFFF"))
for icon in icons:
background_color, foreground_color = random.choice(icon_colors)
output_file.rect(x - 2 - 8, y - 2 - 8, 20, 20, color=background_color)
svg.add(svg.rect(
(x - 2 - 8, y - 2 - 8), (20, 20), fill=f"#{background_color}"))
for i in icon["icons"]:
draw_icon(output_file, i, x, y, foreground_color)
draw_icon(svg, i, x, y, foreground_color)
x += step
if x > width - 8:
x = step / 2
@ -121,4 +120,4 @@ def draw_grid():
print(f"Icons: {number}.")
output_file.end()
svg.write(open(icon_grid_file_name, "w"))

View file

@ -3,23 +3,25 @@ Simple OpenStreetMap renderer.
Author: Sergey Vartanov (me@enzet.ru).
"""
import numpy as np
import os
import random
import svgwrite
import sys
import yaml
import numpy as np
from svgwrite.container import Group
from svgwrite.path import Path
from svgwrite.shapes import Circle, Rect
from svgwrite.text import Text
from typing import List
from roentgen import extract_icon
from roentgen import ui
from roentgen import svg
from roentgen.constructor import Constructor, get_path
from roentgen.flinger import GeoFlinger, Geo
from roentgen.osm_reader import OSMReader
from roentgen.osm_getter import get_osm
from roentgen.grid import draw_grid
from typing import List
from roentgen.osm_getter import get_osm
from roentgen.osm_reader import Map, OSMReader
ICONS_FILE_NAME: str = "icons/icons.svg"
TAGS_FILE_NAME: str = "data/tags.yml"
@ -31,7 +33,7 @@ class Painter:
def __init__(
self, show_missing_tags, overlap, draw_nodes, mode, draw_captions,
map_, flinger, output_file, icons, scheme):
map_, flinger, svg: svgwrite.Drawing, icons, scheme):
self.show_missing_tags = show_missing_tags
self.overlap = overlap
@ -41,16 +43,10 @@ class Painter:
self.map_ = map_
self.flinger = flinger
self.output_file = output_file
self.svg: svgwrite.Drawing = svg
self.icons = icons
self.scheme = scheme
def draw_raw_nodes(self):
for node_id in self.map_.node_map:
node = self.map_.node_map[node_id]
flung = self.flinger.fling(node)
self.output_file.circle(flung[0], flung[1], 0.2, color="FFFFFF")
def no_draw(self, key):
if key in self.scheme["tags_to_write"] or \
key in self.scheme["tags_to_skip"]:
@ -125,27 +121,21 @@ class Painter:
#------#
######
"""
text = text.replace("&", "and")
if out_fill_2:
self.output_file.write(
f'<text x="{x}" y="{y}" style="font-size:' +
str(
size) + ";text-anchor:middle;font-family:Roboto;fill:#" +
out_fill_2 + ";stroke-linejoin:round;stroke-width:5;stroke:#" +
out_fill_2 + ";opacity:" + str(
out_opacity_2) + ';">' + text + "</text>")
self.svg.add(Text(
text, (x, y), font_size=size, text_anchor="middle",
font_family="Roboto", fill=f"#{out_fill_2}",
stroke_linejoin="round", stroke_width=5,
stroke=f"#{out_fill_2}", opacity=out_opacity_2))
if out_fill:
self.output_file.write(
f'<text x="{x}" y="{y}" style="font-size:' +
str(
size) + ";text-anchor:middle;font-family:Roboto;fill:#" +
out_fill + ";stroke-linejoin:round;stroke-width:3;stroke:#" +
out_fill + ";opacity:" + str(
out_opacity) + ';">' + text + "</text>")
self.output_file.write(
f'<text x="{x}" y="{y}" style="font-size:' +
str(size) + ";text-anchor:middle;font-family:Roboto;fill:#" +
fill + ';">' + text + "</text>")
self.svg.add(Text(
text, (x, y), font_size=size, text_anchor="middle",
font_family="Roboto", fill=f"#{out_fill}",
stroke_linejoin="round", stroke_width=3,
stroke=f"#{out_fill}", opacity=out_opacity))
self.svg.add(Text(
text, (x, y), font_size=size, text_anchor="middle",
font_family="Roboto", fill=f"#{fill}"))
def wr(self, text, x, y, fill, text_y, size=10):
text = text[:26] + ("..." if len(text) > 26 else "")
@ -268,16 +258,12 @@ class Painter:
node_2 = self.map_.node_map[way.nodes[i + 1]]
flung_1 = self.flinger.fling(Geo(node_1.lat, node_1.lon))
flung_2 = self.flinger.fling(Geo(node_2.lat, node_2.lon))
shifted_1 = np.add(flung_1, shift_1)
shifted_2 = np.add(flung_2, shift_2)
self.output_file.write(
f'<path d="M '
f"{shifted_1[0]},{shifted_1[1]} L "
f"{shifted_1[0]},{shifted_1[1]} "
f"{shifted_2[0]},{shifted_2[1]} "
f'{shifted_2[0]},{shifted_2[1]} Z" '
f'style="fill:#{color};stroke:#{color};'
f'stroke-width:1;" />\n')
self.svg.add(self.svg.path(
d=("M", np.add(flung_1, shift_1), "L",
np.add(flung_2, shift_1), np.add(flung_2, shift_2),
np.add(flung_1, shift_2), "Z"),
fill=f"#{color}", stroke=f"#{color}", stroke_width=1))
elif way.path:
# TODO: implement
pass
@ -289,34 +275,31 @@ class Painter:
if way.kind == "way":
if way.nodes:
path = get_path(way.nodes, [0, 0], self.map_, self.flinger)
self.output_file.write(
f'<path d="{path}" style="' + way.style + '" />\n')
self.svg.add(Path(d=path, style=way.style))
else:
self.output_file.write(
f'<path d="{way.path}" style="' + way.style + '" />\n')
self.svg.add(Path(d=way.path, style=way.style))
# Building shade
self.output_file.write('<g style="opacity:0.1;">\n')
building_shade = Group(opacity=0.1)
for way in ways:
if way.kind == "building":
if way.nodes:
shift = [-5, 5]
if way.levels:
shift = [-5 * way.levels, 5 * way.levels]
for i in range(len(way.nodes) - 1):
node_1 = self.map_.node_map[way.nodes[i]]
node_2 = self.map_.node_map[way.nodes[i + 1]]
flung_1 = self.flinger.fling(Geo(node_1.lat, node_1.lon))
flung_2 = self.flinger.fling(Geo(node_2.lat, node_2.lon))
self.output_file.write(
f'<path d="M '
f'{flung_1[0]},{flung_1[1]} L '
f"{flung_2[0]},{flung_2[1]} "
f"{flung_2[0] + shift[0]},{flung_2[1] + shift[1]} "
f'{flung_1[0] + shift[0]},{flung_1[1] + shift[1]} Z" '
f'style="fill:#000000;stroke:#000000;stroke-width:1;" />\n')
self.output_file.write("</g>\n")
if way.kind != "building" or not way.nodes:
continue
shift = [-5, 5]
if way.levels:
shift = [-5 * way.levels, 5 * way.levels]
for i in range(len(way.nodes) - 1):
node_1 = self.map_.node_map[way.nodes[i]]
node_2 = self.map_.node_map[way.nodes[i + 1]]
flung_1 = self.flinger.fling(Geo(node_1.lat, node_1.lon))
flung_2 = self.flinger.fling(Geo(node_2.lat, node_2.lon))
building_shade.add(Path(
("M", flung_1, "L", flung_2, np.add(flung_2, shift),
np.add(flung_1, shift), "Z"),
fill="#000000", stroke="#000000", stroke_width=1))
self.svg.add(building_shade)
# Building walls
@ -327,18 +310,16 @@ class Painter:
# Building roof
for way in ways:
if way.kind == "building":
if way.nodes:
shift = [0, -3]
if way.levels:
shift = [0 * way.levels, min(-3, -1 * way.levels)]
path = get_path(way.nodes, shift, self.map_, self.flinger)
self.output_file.write(
f'<path d="{path}" style="{way.style};opacity:1;" />\n')
else:
self.output_file.write(
f'<path d="{way.path}" '
f'style="{way.style};opacity:1;" />\n')
if way.kind != "building":
continue
if way.nodes:
shift = [0, -3]
if way.levels:
shift = [0 * way.levels, min(-3, -1 * way.levels)]
path = get_path(way.nodes, shift, self.map_, self.flinger)
self.svg.add(Path(d=path, style=way.style, opacity=1))
else:
self.svg.add(Path(d=way.path, style=way.style, opacity=1))
# Trees
@ -347,11 +328,10 @@ class Painter:
node.tags["natural"] == "tree" and
"diameter_crown" in node.tags):
continue
self.output_file.circle(
float(node.x) + (random.random() - 0.5) * 10,
float(node.y) + (random.random() - 0.5) * 10,
self.svg.add(Circle(
(float(node.x), float(node.y)),
float(node.tags["diameter_crown"]) * 1.2,
color='688C44', fill='688C44', opacity=0.3)
fill="#688C44", stroke="#688C44", opacity=0.3))
# All other nodes
@ -386,20 +366,15 @@ class Painter:
def draw_point(self, shape, x, y, fill, size=16, xx=0, yy=0, tags=None):
x = int(float(x))
y = int(float(y))
self.output_file.write(
'<path d="' + shape + '" style="fill:#' + fill +
';fill-opacity:1" transform="translate(' +
str(x - size / 2.0 - xx * 16) + "," + str(
y - size / 2.0 - yy * 16) +
')">')
if tags:
self.output_file.write("<title>")
self.output_file.write(
"\n".join(map(lambda x: x + ": " + tags[x], tags)))
self.output_file.write("</title>")
self.output_file.write("</path>\n")
path = self.svg.path(
d=shape, fill=f"#{fill}", fill_opacity=1,
transform=f"translate({x - size / 2.0 - xx * 16},"
f"{y - size / 2.0 - yy * 16})")
path.set_desc(title="\n".join(map(lambda x: x + ": " + tags[x], tags)))
self.svg.add(path)
def draw_point_outline(self, shape, x, y, fill, mode="default", size=16, xx=0, yy=0):
def draw_point_outline(
self, shape, x, y, fill, mode="default", size=16, xx=0, yy=0):
x = int(float(x))
y = int(float(y))
opacity = 0.5
@ -413,12 +388,12 @@ class Painter:
if Y > 200:
outline_fill = "000000"
opacity = 0.7
self.output_file.write(
'<path d="' + shape + '" style="fill:#' + outline_fill + ";opacity:" +
str(opacity) + ";" + "stroke:#" + outline_fill +
f';stroke-width:{stroke_width};stroke-linejoin:round;" ' + 'transform="translate(' +
str(x - size / 2.0 - xx * 16) + "," + str(y - size / 2.0 - yy * 16) +
')" />\n')
self.svg.add(self.svg.path(
d=shape, fill=f"#{outline_fill}", opacity=opacity,
stroke=f"#{outline_fill}", stroke_width=stroke_width,
stroke_linejoin="round",
transform=f"translate({x - size / 2.0 - xx * 16},"
f"{y - size / 2.0 - yy * 16})"))
def check_level_number(tags, level):
@ -453,9 +428,9 @@ def main():
if not options:
sys.exit(1)
background_color = "EEEEEE"
background_color = "#EEEEEE"
if options.mode in ["user-coloring", "time"]:
background_color = "111111"
background_color = "#111111"
if options.input_file_name:
input_file_name = options.input_file_name
@ -480,18 +455,18 @@ def main():
print("Fatal: no such file: " + file_name + ".")
sys.exit(1)
map_ = osm_reader.parse_osm_file(
osm_reader.parse_osm_file(
file_name, parse_ways=options.draw_ways,
parse_relations=options.draw_ways, full=full)
output_file = svg.SVG(open(options.output_file_name, "w+"))
map_: Map = osm_reader.map_
w, h = list(map(lambda x: float(x), options.size.split(",")))
output_file.begin(w, h)
output_file.write(
"<title>Rӧntgen</title><style>path:hover {stroke: #FF0000;}</style>\n")
output_file.rect(0, 0, w, h, color=background_color)
svg: svgwrite.Drawing = \
svgwrite.Drawing(options.output_file_name, size=(w, h))
svg.add(Rect((0, 0), (w, h), fill=background_color))
min1 = Geo(boundary_box[1], boundary_box[0])
max1 = Geo(boundary_box[3], boundary_box[2])
@ -537,18 +512,18 @@ def main():
show_missing_tags=options.show_missing_tags, overlap=options.overlap,
draw_nodes=options.draw_nodes, mode=options.mode,
draw_captions=options.draw_captions,
map_=map_, flinger=flinger, output_file=output_file, icons=icons,
map_=map_, flinger=flinger, svg=svg, icons=icons,
scheme=scheme)
painter.draw(constructor.nodes, constructor.ways, points)
if flinger.space[0] == 0:
output_file.rect(0, 0, w, flinger.space[1], color="FFFFFF")
output_file.rect(
0, h - flinger.space[1], w, flinger.space[1], color="FFFFFF")
svg.add(Rect((0, 0), (w, flinger.space[1]), fill="#FFFFFF"))
svg.add(Rect(
(0, h - flinger.space[1]), (w, flinger.space[1]), fill="#FFFFFF"))
if flinger.space[1] == 0:
output_file.rect(0, 0, flinger.space[0], h, color="FFFFFF")
output_file.rect(
w - flinger.space[0], 0, flinger.space[0], h, color="FFFFFF")
svg.add(Rect((0, 0), (flinger.space[0], h), fill="#FFFFFF"))
svg.add(Rect(
(w - flinger.space[0], 0), (flinger.space[0], h), fill="#FFFFFF"))
if options.show_index:
print(min1.lon, max1.lon)
@ -595,12 +570,13 @@ def main():
t2 = flinger.fling(Geo(
min1.lat + (i + 1) * lat_step,
min1.lon + (j + 1) * lon_step))
output_file.text(
((t1 + t2) * 0.5)[0], ((t1 + t2) * 0.5)[1] + 40,
str(int(matrix[i][j])), size=80, color="440000",
opacity=0.1, align="center")
svg.add(Text(
str(int(matrix[i][j])),
(((t1 + t2) * 0.5)[0], ((t1 + t2) * 0.5)[1] + 40),
font_size=80, fill="440000",
opacity=0.1, align="center"))
output_file.end()
svg.write(open(options.output_file_name, "w"))
top_missing_tags = \
sorted(missing_tags.keys(), key=lambda x: -missing_tags[x])

View file

@ -3,7 +3,7 @@ Reading OpenStreetMap data from XML file.
Author: Sergey Vartanov
"""
from typing import Any, Dict, List, Optional
from typing import Dict, List, Optional
from roentgen import ui

View file

@ -1,245 +0,0 @@
"""
Very simple SVG library.
Author: Sergey Vartanov (me@enzet.ru)
"""
import math
class SVG:
def __init__(self, file_):
self.file = file_
self.index = 0
def begin(self, width, height):
self.file.write(
'<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n\n')
self.file.write(
f'''<svg version="1.1" baseProfile="full"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:ev="http://www.w3.org/2001/xml-events"
bgcolor="#e5e9e6" width="{width}" height="{height}">\n''')
def end(self):
self.file.write('</svg>\n')
def path(
self, path: str, color: str = "black", width: float = 1,
fill: str = "none", end: str = "butt", id: str = None,
color2: str = None, gx1: float = 0, gy1: float = 0, gx2: float = 0,
gy2: float = 0, dash: str = None, dashoffset: str = None,
opacity: float = 1, transform: str = None):
if color2:
self.index += 1
self.file.write(
f'<defs><linearGradient id="grad{str(self.index)}" '
f'x1="{str(gx1)}" y1="{str(gy1)}" '
f'x2="{str(gx2)}" y2="{str(gy2)}" '
f'gradientUnits="userSpaceOnUse">'
f'<stop style="stop-color:{self.get_color(color)};'
f'stop-opacity:1;" offset="0" />'
f'<stop style="stop-color:{self.get_color(color2)};'
f'stop-opacity:1;" offset="1" /></linearGradient></defs>\n')
self.file.write(' <path d = "' + path + '" ')
if id:
self.file.write(f'id="{id}" ')
if transform:
self.file.write('transform="' + transform + '" ')
self.file.write('style = "')
if not color2:
self.file.write('stroke:' + self.get_color(color) + '; ')
else:
self.file.write('stroke:url(#grad' + str(self.index) + '); ')
self.file.write('stroke-width:' + str(width) + '; ')
self.file.write('fill:' + self.get_color(fill) + '; ')
self.file.write('stroke-linecap:' + end + '; ')
if opacity != 1:
self.file.write('opacity:' + str(opacity) + '; ')
if dash:
self.file.write('stroke-dasharray:' + dash + '; ')
if dashoffset:
self.file.write('stroke-dashoffset:' + str(dashoffset) + '; ')
self.file.write('" />\n')
def line(
self, x1, y1, x2, y2, width=1, color='black', end='butt', id_=None,
color2=None, gx1=None, gy1=None, gx2=None, gy2=None, dash=None,
dashoffset=None, opacity=None):
if color2:
if not gx1:
gx1 = x1
if not gy1:
gy1 = y1
if not gx2:
gx2 = x2
if not gy2:
gy2 = y2
self.index += 1
self.file.write(
f'<defs><linearGradient id="grad{str(self.index)}" '
f'x1="{str(gx1)}" y1="{str(gy1)}" x2="{str(gx2)}" '
f'y2="{str(gy2)}" gradientUnits="userSpaceOnUse">\n'
f'<stop style="stop-color:#{str(color)};stop-opacity:1;" '
f'offset="0" />'
f'<stop style=\"stop-color:#{str(color2)};stop-opacity:1;" '
f'offset="1" />'
f'</linearGradient></defs>\n')
self.file.write(
f' <path d = "M {str(x1)},{str(y1)} {str(x2)},{str(y2)}" ')
if id_:
self.file.write(f'id="{id_}" ')
self.file.write('style="')
if not color2:
self.file.write(f'stroke:{self.get_color(color)}; ')
else:
self.file.write(f'stroke:url(#grad{self.index}); ')
self.file.write(f'stroke-width:{width}; ')
self.file.write(f'stroke-linecap:{end}; ')
if dash:
self.file.write('stroke-dasharray:' + dash + '; ')
if dashoffset:
self.file.write('stroke-dashoffset:' + str(dashoffset) + '; ')
if opacity:
self.file.write('opacity: ' + str(opacity) + '; ')
self.file.write('" />\n')
def rect(
self, x, y, width, height, color='black', id=None, rx=0, ry=0,
opacity=1.0, stroke_color='none', stroke_width=1.0):
self.file.write(' <rect x = "' + str(x) + '" y = "' + str(y) + '" rx = "' + str(rx) + '" ry = "' + str(ry) +
'" ')
self.file.write(' width = "' + str(width) + '" height = "' + str(height) + '" ')
if id:
self.file.write('id = "' + id + '" ')
self.file.write('style = "')
if opacity != 1:
self.file.write('opacity:' + str(opacity) + '; ')
self.file.write('fill:' + self.get_color(color) + '; ')
self.file.write('stroke:' + self.get_color(stroke_color) + '; ')
self.file.write('stroke-width:' + str(stroke_width) + '; ')
self.file.write('" />\n')
def curve(self, x1, y1, x2, y2, x3, y3, x4, y4, id=None, width=1, color='black'):
self.file.write(' <path d = "M ' + str(x1) + ',' + str(y1) + ' C ' + str(x2) + ',' + str(y2) + ' ')
self.file.write(str(x3) + ',' + str(y3) + ' ' + str(x4) + ',' + str(y4) + '" ')
self.file.write('style = "')
self.file.write('stroke:' + self.get_color(color) + '; ')
self.file.write('stroke-width:' + str(width) + '; ')
self.file.write('fill: none; ')
self.file.write('" />\n')
def rhombus(self, x, y, width, height, color='black', id=None):
self.file.write(''' <path d = "M %5.1f %5.1f L %5.1f %5.1f L %5.1f %5.1f
L %5.1f %5.1f L %5.1f %5.1f" ''' % (x, y - height, x + width, y, x, y + height, x - width, y, x,
y - height))
if id:
self.file.write('id = "' + id + '" ')
self.file.write('style = "')
self.file.write('fill:' + self.get_color(color) + '; ')
self.file.write('" />\n')
def circle(self, x, y, d, color='black', color2='white', fill='none',
opacity=None, width=1, id_=None, gx=0, gy=0, gr=0, fx=0, fy=0):
is_grad = gx != 0 or gy != 0 or gr != 0
if is_grad:
self.index += 1
self.file.write(
f'<defs><radialGradient id="grad{str(self.index)}" '
f'cx="{gx}%" cy="{gy}%" r="{gr}%" fx="{fx}%" fy="{fy}%">'
f'<stop offset="0%" style="stop-color:rgb(255,255,255);'
f'stop-opacity:0" /><stop offset="100%" '
f'style="stop-color:{self.get_color(color)};stop-opacity:1" />'
f'</radialGradient></defs>\n')
c = 0.577
self.file.write(
f' <path d = "'
f'M {x:5.1f} {y + d:5.1f} '
f'C {x - d * c:5.1f} {y + d:5.1f} {x - d:5.1f} {y + d * c:5.1f} '
f'{x - d:5.1f} {y:5.1f} '
f'C {x - d:5.1f} {y - d * c:5.1f} {x - d * c:5.1f} {y - d:5.1f} '
f'{x:5.1f} {y - d:5.1f} '
f'C {x + d * c:5.1f} {y - d:5.1f} {x + d:5.1f} {y - d * c:5.1f} '
f'{x + d:5.1f} {y:5.1f} '
f'C {x + d:5.1f} {y + d * c:5.1f} {x + d * c:5.1f} {y + d:5.1f} '
f'{x:5.1f} {y + d:5.1f}" ')
if id_:
self.file.write('id = "' + id_ + '" ')
self.file.write('style = "')
if is_grad:
self.file.write('fill:url(#grad' + str(self.index) + '); ')
else:
self.file.write('fill:' + self.get_color(fill) + '; ')
self.file.write('stroke-width:' + str(width) + '; ')
self.file.write('stroke:' + self.get_color(color) + '; ')
if opacity:
self.file.write('opacity:' + str(opacity) + '; ')
self.file.write('" />\n')
def text(self, x, y, text, font='Myriad Pro', size='10', align='left',
color='black', id=None, weight=None, letter_spacing=None, angle=None,
opacity=None):
"""
Drawing SVG <text> element.
"""
if angle is None:
self.file.write(f' <text x="{str(x)}" y="{str(y)}" ')
else:
self.file.write(' <text x="0" y="0" ')
self.file.write('font-size = "' + str(size) + '" ')
if id:
self.file.write('id = "' + id + '" ')
if not (angle is None) and angle <= 0:
align = 'end'
if align == 'right':
align = 'end'
if align == 'center':
align = 'middle'
self.file.write('style = "')
self.file.write('text-anchor:' + align + '; ')
if opacity:
self.file.write('opacity:' + str(opacity) + '; ')
self.file.write('font-family: ' + font + '; ')
self.file.write('fill: ' + self.get_color(color) + '; ')
if weight == 'bold':
self.file.write('font-weight:bold; ')
if letter_spacing:
self.file.write('letter-spacing:' + str(letter_spacing) + '; ')
self.file.write('"')
if not (angle is None):
if math.sin(angle) > 0:
trans = 'transform = "matrix(' + str(math.sin(angle)) + ',' + str(math.cos(angle)) + ',' + \
str(-math.cos(angle)) + ',' + str(math.sin(angle)) + ',' + str(x) + ',' + str(y) + ')"'
else:
trans = 'transform = "matrix(' + str(math.sin(angle + math.pi)) + ',' + str(math.cos(angle + math.pi)) + ',' + \
str(-math.cos(angle + math.pi)) + ',' + str(math.sin(angle + math.pi)) + ',' + str(x) + ',' + str(y) + ')"'
self.file.write(' ' + trans)
self.file.write('>')
self.file.write(text)
self.file.write('</text>\n')
@staticmethod
def get_color(color):
if color == 'none':
return 'none'
if color == 'black':
return 'black'
return '#' + str(color)
def begin_layer(self, name):
self.file.write(f'<g id="{name}" label="{name}" ')
self.file.write('inkscape:groupmode="layer">\n')
def end_layer(self):
self.file.write('</g>\n')
def write(self, raw_code):
self.file.write(raw_code)

View file

@ -8,7 +8,9 @@ from typing import Optional
def parse_options(args):
"""
Parse Röntgen command-line options.
"""
parser = argparse.ArgumentParser()
parser.add_argument(
@ -56,9 +58,9 @@ def parse_options(args):
"--show-index", dest="show_index", action="store_true")
parser.add_argument(
"--no-show-index", dest="show_index", action="store_false")
parser.add_argument("--mode", dest="mode", default="normal")
parser.add_argument("--seed", dest="seed", default="")
parser.add_argument("--level", dest="level", default=None)
parser.add_argument("--mode", default="normal")
parser.add_argument("--seed", default="")
parser.add_argument("--level", default=None)
arguments = parser.parse_args(args[1:])