mightyscape-1.2/extensions/fablabchemnitz/table_support/base_transform.py

266 lines
9.1 KiB
Python

#!/usr/bin/env python3
"""
base_transform.py
Base matemathical operations for SVG 3x3 matrices
Copyright (C) 2011 Cosmin Popescu, cosminadrianpopescu@gmail.com
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 2 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.
"""
import re
import inkex
import os
from math import *
class BaseTransform(inkex.Effect):
unitMatrix = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
def isset(self, v, i = None):
try:
if (i is None):
v
else:
v[i]
return True
except:
return False
def __init__(self):
inkex.Effect.__init__(self)
def sizeToPx(self, s, dim = "y"):
root = self.document.getroot()
try:
factor = float(root.attrib[inkex.addNS('export-' + dim + 'dpi', 'inkscape')])
except:
factor = 90
unit = ''
pattern = '[\\-\\d\\.]+([a-zA-Z][a-zA-Z])'
if (re.search(pattern, s)):
res = re.search(pattern, s)
unit = res.group(1)
pattern = '^([\\-\\d\\.]*)'
res = re.search(pattern, s)
n = float(res.group(1))
if unit == 'cm':
return (n / 2.54) * factor
elif unit == 'ft':
return n * 12 * factor
elif unit == 'in':
return n * factor
elif unit == 'm':
return ((n * 10) / 2.54) * factor
elif unit == 'mm':
return ((n / 10) / 2.54) * factor
elif unit == 'pc':
return ((n * 2.36228956229) / 2.54) * factor
elif unit == 'pt':
return (((n / 2.83464646465) / 10) / 2.54) * factor
elif unit == 'px' or unit == '':
return n
return 0
def transform(self, el):
result = self.unitMatrix
if (el.tag == inkex.addNS('svg', 'svg')):
return result
if (not self.isset(el.attrib, 'transform')):
return self.multiply(self.transform(el.getparent()), result)
pattern = '(matrix|translate|scale|rotate|skewX|skewY)[\\s|,]*\\(([^\\)]*)\\)'
transforms = re.findall(pattern, el.attrib['transform'])
for transform in transforms:
values = re.split('[\\s|,]+', transform[1])
for i in range(len(values)):
values[i] = float(values[i])
function = transform[0]
if (function == 'matrix'):
a = [[values[0], values[2], values[4]],
[values[1], values[3], values[5]],
[0, 0, 1]]
result = self.multiply(result, a)
elif (function == 'translate'):
a = [[1, 0, values[0]],
[0, 1, values[1]],
[0, 0, 1]]
result = self.multiply(result, a)
elif (function == 'scale'):
a = [[values[0], 0, 0],
[0, values[1], 0],
[0, 0, 1]]
result = self.multiply(result, a)
elif (function == 'rotate'):
if (len(values) == 1):
a = [[math.cos(values[0]), -math.sin(values[0]), 0],
[math.sin(values[0]), math.cos(values[0]), 0],
[0, 0, 1]]
result = self.multiply(result, a)
else:
a = [[1, 0, values[2]],
[0, 1, values[2]],
[0, 0, 1]]
result = self.multiply(result, a)
a = [[math.cos(values[0]), -math.sin(values[0]), 0],
[math.sin(values[0]), math.cos(values[0]), 0],
[0, 0, 1]]
result = self.multiply(result, a)
a = [[1, 0, -values[2]],
[0, 1, -values[2]],
[0, 0, 1]]
result = self.multiply(result, a)
elif (function == 'skewX'):
a = [[1, math.tan(values[0]), 0],
[0, 1, 0],
[0, 0, 1]]
result = self.multiply(result, a)
elif (function == 'skewY'):
a = [[1, 0, 0],
[math.tan(values[0]), 1, 0],
[0, 0, 1]]
result = self.multiply(result, a)
return self.multiply(self.transform(el.getparent()), result)
def getPosition(self, el):
if not self.isset(el.attrib, 'x'):
return False
x = self.sizeToPx(el.attrib['x'], 'x')
y = self.sizeToPx(el.attrib['y'], 'y')
v = [x, y, 1]
t = self.transform(el)
v = self.multiply(t, v)
return {'coordinates': v, 'matrix': t}
def setPosition(self, el, position):
c = position['coordinates']
a = position['matrix']
if (not self.isUnitMatrix(a)):
c = self.multiply(self.inverse(a), c)
el.set('x', str(c[0]))
el.set('y', str(c[1]))
def determinant(self, a):
if len(a) != 3:
return False
if (len(a[0]) != 3):
return False
det = a[0][0] * (a[1][1] * a[2][2] - a[2][1] * a[1][2]) - a[0][1] * (a[1][0] * a[2][2] - a[2][0] * a[1][2]) + a[0][2] * (a[1][0] * a[2][1] - a[2][0] * a[1][1])
if (det == 0):
det = 0.00001
return det
def minors(self, a):
if len(a) != 3:
return False
if (len(a[0]) != 3):
return False
return [[a[1][1] * a[2][2] - a[2][1] * a[1][2], a[1][0] * a[2][2] - a[2][0] * a[1][2], a[1][0] * a[2][1] - a[2][0] * a[1][1]],
[a[0][1] * a[2][2] - a[2][1] * a[0][2], a[0][0] * a[2][2] - a[0][2] * a[2][0], a[0][0] * a[2][1] - a[2][0] * a[0][1]],
[a[0][1] * a[1][2] - a[1][1] * a[0][2], a[0][0] * a[1][2] - a[0][1] * a[0][2], a[0][0] * a[1][1] - a[1][0] * a[0][1]]
]
def cofactors(self, a):
if len(a) != 3:
return False
if (len(a[0]) != 3):
return False
return [[a[0][0], -a[0][1], a[0][2]],
[-a[1][0], a[1][1], -a[1][2]],
[a[2][0], -a[2][1], a[2][2]]
]
def adjoint(self, a):
if len(a) != 3:
return False
if (len(a[0]) != 3):
return False
return [[a[0][0], a[1][0], a[2][0]],
[a[0][1], a[1][1], a[2][1]],
[a[0][2], a[1][2], a[2][2]]
]
def inverse(self, a):
if len(a) != 3:
return False
if (len(a[0]) != 3):
return False
det = self.determinant(a)
m = self.minors(a)
c = self.cofactors(m)
adj = self.adjoint(c)
return [[adj[0][0] / det, adj[0][1] / det, adj[0][2] / det],
[adj[1][0] / det, adj[1][1] / det, adj[1][2] / det],
[adj[2][0] / det, adj[2][1] / det, adj[2][2] / det]
]
def multiply(self, a, v):
if len(a) != 3:
return False
if (len(a[0]) != 3):
return False
if (len(v) != 3):
return False
if (not self.isset(v[0], 0)):
return [a[0][0] * v[0] + a[0][1] * v[1] + a[0][2] * v[2],
a[1][0] * v[0] + a[1][1] * v[1] + a[1][2] * v[2],
a[2][0] * v[0] + a[2][1] * v[1] + a[2][2] * v[2]
]
else:
return [[a[0][0] * v[0][0] + a[0][1] * v[1][0] + a[0][2] * v[2][0], a[0][0] * v[0][1] + a[0][1] * v[1][1] + a[0][2] * v[2][1], a[0][0] * v[0][2] + a[0][1] * v[1][2] + a[0][2] * v[2][2]],
[a[1][0] * v[0][0] + a[1][1] * v[1][0] + a[1][2] * v[2][0], a[1][0] * v[0][1] + a[1][1] * v[1][1] + a[1][2] * v[2][1], a[1][0] * v[0][2] + a[1][1] * v[1][2] + a[1][2] * v[2][2]],
[a[2][0] * v[0][0] + a[2][1] * v[1][0] + a[2][2] * v[2][0], a[2][0] * v[0][1] + a[2][1] * v[1][1] + a[2][2] * v[2][1], a[2][0] * v[0][2] + a[2][1] * v[1][2] + a[2][2] * v[2][2]]
]
def isUnitMatrix(self, a):
if (len(a) != 3):
return False
if (len(a[0]) != 3):
return False
for i in range(3):
for j in range(3):
if (a[i][j] != self.unitMatrix[i][j]):
return False
return True
def reParse(self):
if os.name == 'nt':
path = os.environ['USERPROFILE']
else:
path = os.path.expanduser("~")
text = inkex.etree.tostring(self.document.getroot())
f = open(path + '/tmp.svg', 'w')
f.write(text)
f.close()
self.parse(path + '/tmp.svg')
os.remove(path + '/tmp.svg')
def matrix2string(self, a):
return 'matrix(' + str(a[0][0]) + ',' + str(a[1][0]) + ',' + str(a[0][1]) + ',' + str(a[1][1]) + ',' + str(a[0][2]) + ',' + str(a[1][2]) + ')'