139 lines
4.2 KiB
Python
139 lines
4.2 KiB
Python
from typing import Union
|
|
from xml.dom import minidom
|
|
import numpy as np
|
|
import matplotlib.pyplot as plt
|
|
|
|
MX = [485.4, 485.4, 486.8]
|
|
MY = [1, 0, 0]
|
|
|
|
|
|
def str_pair_to_float(s: str) -> np.ndarray:
|
|
return np.array([float(el) for el in s.split(",")])
|
|
|
|
|
|
def parse_buffer(s: str) -> Union[float, complex]:
|
|
x, *y = s.split(",")
|
|
if y:
|
|
return float(x) + 1j * float(y[0])
|
|
else:
|
|
return float(x)
|
|
|
|
|
|
def transform_matrix_and_offset(
|
|
x: tuple[float, float, float],
|
|
y: tuple[float, float, float],
|
|
rx: tuple[float, float, float],
|
|
ry: tuple[float, float, float],
|
|
) -> tuple[np.ndarray, np.ndarray]:
|
|
a = -(
|
|
rx[0] * y[1] - rx[0] * y[2] - rx[1] * y[0] + rx[1] * y[2] + rx[2] * y[0] - rx[2] * y[1]
|
|
) / (x[1] * y[0] - x[2] * y[0] - x[0] * y[1] + x[2] * y[1] + x[0] * y[2] - x[1] * y[2])
|
|
b = -(
|
|
rx[0] * x[1] - rx[0] * x[2] - rx[1] * x[0] + rx[1] * x[2] + rx[2] * x[0] - rx[2] * x[1]
|
|
) / (-x[1] * y[0] + x[2] * y[0] + x[0] * y[1] - x[2] * y[1] - x[0] * y[2] + x[1] * y[2])
|
|
c = -(
|
|
ry[0] * y[1] - ry[0] * y[2] - ry[1] * y[0] + ry[1] * y[2] + ry[2] * y[0] - ry[2] * y[1]
|
|
) / (x[1] * y[0] - x[2] * y[0] - x[0] * y[1] + x[2] * y[1] + x[0] * y[2] - x[1] * y[2])
|
|
d = -(
|
|
-ry[0] * x[1] + ry[0] * x[2] + ry[1] * x[0] - ry[1] * x[2] - ry[2] * x[0] + ry[2] * x[1]
|
|
) / (x[1] * y[0] - x[2] * y[0] - x[0] * y[1] + x[2] * y[1] + x[0] * y[2] - x[1] * y[2])
|
|
e = -(
|
|
rx[0] * x[2] * y[1]
|
|
- rx[0] * x[1] * y[2]
|
|
- rx[1] * x[2] * y[0]
|
|
+ rx[1] * x[0] * y[2]
|
|
+ rx[2] * x[1] * y[0]
|
|
- rx[2] * x[0] * y[1]
|
|
) / (-x[1] * y[0] + x[2] * y[0] + x[0] * y[1] - x[2] * y[1] - x[0] * y[2] + x[1] * y[2])
|
|
f = -(
|
|
-ry[0] * x[2] * y[1]
|
|
+ ry[0] * x[1] * y[2]
|
|
+ ry[1] * x[2] * y[0]
|
|
- ry[1] * x[0] * y[2]
|
|
- ry[2] * x[1] * y[0]
|
|
+ ry[2] * x[0] * y[1]
|
|
) / (x[1] * y[0] - x[2] * y[0] - x[0] * y[1] + x[2] * y[1] + x[0] * y[2] - x[1] * y[2])
|
|
return np.array([[a, b], [c, d]]), np.array([e, f])
|
|
|
|
|
|
def parse_path(s: str) -> list[tuple[np.ndarray, np.ndarray]]:
|
|
INSTRUCTIONS = "mMlLhHvV"
|
|
lines: list[list[complex]] = []
|
|
current_line: list[complex] = []
|
|
pos = 0 + 0j
|
|
|
|
def add_line_point(new_pos):
|
|
nonlocal pos
|
|
if not current_line:
|
|
current_line.append(pos)
|
|
pos = new_pos
|
|
current_line.append(pos)
|
|
|
|
s = iter(s + "M")
|
|
instr = next(s)
|
|
buffer = ""
|
|
for char in s:
|
|
if char not in INSTRUCTIONS:
|
|
buffer += char
|
|
continue
|
|
arg = parse_buffer(buffer)
|
|
buffer = ""
|
|
if instr == "m":
|
|
if current_line:
|
|
lines.append(current_line)
|
|
current_line = []
|
|
pos += arg
|
|
elif instr == "M":
|
|
if current_line:
|
|
lines.append(current_line)
|
|
current_line = []
|
|
pos = arg
|
|
elif instr == "l":
|
|
add_line_point(pos + arg)
|
|
elif instr == "L":
|
|
add_line_point(arg)
|
|
elif instr == "v":
|
|
add_line_point(pos + 1j * arg)
|
|
elif instr == "V":
|
|
add_line_point(0 + 1j * arg)
|
|
elif instr == "h":
|
|
add_line_point(pos + arg)
|
|
elif instr == "H":
|
|
add_line_point(arg)
|
|
instr = char
|
|
if current_line:
|
|
lines.append(current_line)
|
|
|
|
lines = np.array(lines)
|
|
return [(line.real, line.imag) for line in lines]
|
|
|
|
|
|
def main():
|
|
with minidom.parse("./data/Balcon2008.svg") as doc:
|
|
rects = [
|
|
(
|
|
float(rect.getAttribute("x")) + float(rect.getAttribute("width")) / 2,
|
|
float(rect.getAttribute("y")) + float(rect.getAttribute("height")) / 2,
|
|
)
|
|
for rect in doc.getElementsByTagName("rect")
|
|
]
|
|
path_strings = [path.getAttribute("d") for path in doc.getElementsByTagName("path")]
|
|
|
|
px, py = parse_path(path_strings[0])[0]
|
|
|
|
M, off = transform_matrix_and_offset(px, py, MX, MY)
|
|
|
|
x, y = (np.array(rects).dot(M.T) + off).T
|
|
s = x.argsort()
|
|
x = x[s]
|
|
y = y[s]
|
|
|
|
np.savetxt("data/Balcon2008.csv", np.c_[x, y], fmt="%.5f")
|
|
|
|
plt.plot(x, y)
|
|
plt.show()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|