Merge pull request #14 from EmbroidePy/tatarize-patch-1

matrix testing, split off embmatrix file
pull/15/head
tatarize 2018-09-21 22:06:39 -07:00 zatwierdzone przez GitHub
commit 0f90ce91b4
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
5 zmienionych plików z 283 dodań i 97 usunięć

Wyświetl plik

@ -11,7 +11,8 @@ def read(f, out, settings=None):
if len(row) == 0:
continue
if "*" in row[0]:
command = command_dict[row[2]]
split = row[2].split(' ')
command = command_dict[split[0]]
if len(row) == 3:
out.add_command(command)
else:

Wyświetl plik

@ -1,6 +1,7 @@
import math
from .EmbConstant import *
from .EmbMatrix import EmbMatrix
class Transcoder:
@ -38,34 +39,28 @@ class Transcoder:
self.long_stitch_contingency = \
settings.get("long_stitch_contingency", CONTINGENCY_LONG_STITCH_JUMP_NEEDLE)
self.matrix = get_identity()
self.matrix = EmbMatrix()
translate = settings.get("translate", None)
if translate is not None:
try:
m = get_translate(translate[0], translate[1])
self.matrix = matrix_multiply(self.matrix, m)
self.matrix.post_translate(translate[0], translate[1])
except IndexError:
try:
m = get_translate(translate.x, translate.y)
self.matrix = matrix_multiply(self.matrix, m)
self.matrix.post_translate(translate.x, translate.y)
except AttributeError:
pass
scale = settings.get("scale", None)
if scale is not None:
try:
m = get_scale(scale[0], scale[1])
self.matrix = matrix_multiply(self.matrix, m)
self.matrix.post_scale(scale[0], scale[1])
except (IndexError, TypeError):
try:
m = get_scale(scale.x, scale.y)
self.matrix = matrix_multiply(self.matrix, m)
self.matrix.post_scale(scale.x, scale.y)
except AttributeError:
m = get_scale(scale, scale)
self.matrix = matrix_multiply(self.matrix, m)
self.matrix.post_scale(scale, scale)
rotate = settings.get("rotate", None)
if rotate is not None:
m = get_rotate(rotate)
self.matrix = matrix_multiply(self.matrix, m)
self.matrix.post_rotate(rotate)
self.source_pattern = None
self.destination_pattern = None
self.position = 0
@ -178,7 +173,7 @@ class Transcoder:
flags = NO_COMMAND
for self.position, self.stitch in enumerate(source):
p = point_in_matrix_space(self.matrix, self.stitch)
p = self.matrix.point_in_matrix_space(self.stitch)
x = p[0]
y = p[1]
flags = self.stitch[2] & COMMAND_MASK
@ -305,30 +300,20 @@ class Transcoder:
elif flags == CONTINGENCY_SEQUIN_UTILIZE:
self.sequin_contingency = CONTINGENCY_SEQUIN_UTILIZE
elif flags == MATRIX_TRANSLATE:
m = get_translate(self.stitch[0], self.stitch[1])
self.matrix = matrix_multiply(self.matrix, m)
self.matrix.post_translate(self.stitch[0], self.stitch[1])
elif flags == MATRIX_SCALE_ORIGIN:
m = get_scale(self.stitch[0], self.stitch[1])
self.matrix = matrix_multiply(self.matrix, m)
self.matrix.post_scale(self.stitch[0], self.stitch[1])
elif flags == MATRIX_ROTATE_ORIGIN:
m = get_rotate(self.stitch[0])
self.matrix = matrix_multiply(self.matrix, m)
self.matrix.post_rotate(self.stitch[0])
elif flags == MATRIX_SCALE:
pos = point_in_matrix_space(self.matrix, (self.needle_x, self.needle_y))
m0 = get_translate(-pos[0], -pos[1])
m1 = get_scale(self.stitch[0], self.stitch[1])
m2 = get_translate(pos[0], pos[1])
m = post_matrix_cat((m0, m1, m2))
self.matrix = matrix_multiply(self.matrix, m)
p = self.matrix.point_in_matrix_space(self.needle_x, self.needle_y)
self.matrix.post_scale(self.stitch[0], self.stitch[1], p[0], p[1])
elif flags == MATRIX_ROTATE:
pos = point_in_matrix_space(self.matrix, (self.needle_x, self.needle_y))
m0 = get_translate(-pos[0], -pos[1])
m1 = get_rotate(self.stitch[0])
m2 = get_translate(pos[0], pos[1])
m = post_matrix_cat((m0, m1, m2))
self.matrix = matrix_multiply(self.matrix, m)
# p = self.matrix.point_in_matrix_space(self.needle_x, self.needle_y)
# self.matrix.post_rotate(self.stitch[0], p[0], p[1])
self.matrix.post_rotate(self.stitch[0], self.needle_x, self.needle_y)
elif flags == MATRIX_RESET:
self.matrix = get_identity()
self.matrix.reset()
if flags != END:
self.end_here()
@ -404,9 +389,8 @@ class Transcoder:
def tie_off(self):
if self.tie_off_contingency == CONTINGENCY_TIE_OFF_THREE_SMALL:
try:
b = point_in_matrix_space(
self.matrix,
self.source_pattern.stitches[self.position - 1],
b = self.matrix.point_in_matrix_space(
self.source_pattern.stitches[self.position - 1]
)
flags = b[2]
if flags == STITCH or flags == NEEDLE_AT or \
@ -419,8 +403,7 @@ class Transcoder:
def tie_on(self):
if self.tie_on_contingency == CONTINGENCY_TIE_ON_THREE_SMALL:
try:
b = point_in_matrix_space(
self.matrix,
b = self.matrix.point_in_matrix_space(
self.source_pattern.stitches[self.position + 1]
)
flags = b[2]
@ -567,9 +550,7 @@ class Transcoder:
if length is None:
length = self.max_stitch
if new_x is None or new_y is None:
p = point_in_matrix_space(self.matrix,
self.stitch[0],
self.stitch[1])
p = self.matrix.point_in_matrix_space(self.stitch[0], self.stitch[1])
new_x = p[0]
new_y = p[1]
distance_x = new_x - self.needle_x
@ -694,23 +675,23 @@ def get_rotate(theta):
def post_matrix_cat(matrix_list):
m = get_identity()
for mx in matrix_list:
m = matrix_list[0]
for mx in matrix_list[1:]:
m = matrix_multiply(m, mx)
return m
def matrix_multiply(a, b):
def matrix_multiply(m0, m1):
return [
a[0] * b[0] + a[1] * b[3] + a[2] * b[6],
a[0] * b[1] + a[1] * b[4] + a[2] * b[7],
a[0] * b[2] + a[1] * b[5] + a[2] * b[8],
a[3] * b[0] + a[4] * b[3] + a[5] * b[6],
a[3] * b[1] + a[4] * b[4] + a[5] * b[7],
a[3] * b[2] + a[4] * b[5] + a[5] * b[8],
a[6] * b[0] + a[7] * b[3] + a[8] * b[6],
a[6] * b[1] + a[7] * b[4] + a[8] * b[7],
a[6] * b[2] + a[7] * b[5] + a[8] * b[8]]
m1[0] * m0[0] + m1[1] * m0[3] + m1[2] * m0[6],
m1[0] * m0[1] + m1[1] * m0[4] + m1[2] * m0[7],
m1[0] * m0[2] + m1[1] * m0[5] + m1[2] * m0[8],
m1[3] * m0[0] + m1[4] * m0[3] + m1[5] * m0[6],
m1[3] * m0[1] + m1[4] * m0[4] + m1[5] * m0[7],
m1[3] * m0[2] + m1[4] * m0[5] + m1[5] * m0[8],
m1[6] * m0[0] + m1[7] * m0[3] + m1[8] * m0[6],
m1[6] * m0[1] + m1[7] * m0[4] + m1[8] * m0[7],
m1[6] * m0[2] + m1[7] * m0[5] + m1[8] * m0[8]]
def point_in_matrix_space(matrix, v0, v1=None):

Wyświetl plik

@ -0,0 +1,138 @@
import math
class EmbMatrix:
def __init__(self):
self.m = self.get_identity()
def get_matrix(self):
return self.m
def reset(self):
self.m = self.get_identity()
def inverse(self):
m = self.m
m48s75 = m[4] * m[8] - m[7] * m[5]
m38s56 = m[5] * m[6] - m[3] * m[8]
m37s46 = m[3] * m[7] - m[4] * m[6]
det = m[0] * m48s75 + m[1] * m38s56 + m[2] * m37s46
inverse_det = 1.0 / float(det)
self.m = [
m48s75 * inverse_det,
(m[2] * m[7] - m[1] * m[8]) * inverse_det,
(m[1] * m[5] - m[2] * m[4]) * inverse_det,
m38s56 * inverse_det,
(m[0] * m[8] - m[2] * m[6]) * inverse_det,
(m[3] * m[2] - m[0] * m[5]) * inverse_det,
m37s46 * inverse_det,
(m[6] * m[1] - m[0] * m[7]) * inverse_det,
(m[0] * m[4] - m[3] * m[1]) * inverse_det,
]
def post_scale(self, sx=1, sy=None, x=0, y=0):
if sy is None:
sy = sx
if x == 0 and y == 0:
self.m = self.matrix_multiply(self.m, self.get_scale(sx, sy))
else:
self.post_translate(x, y)
self.post_scale(sx, sy)
self.post_translate(-x, -y)
def post_translate(self, tx, ty):
self.m = self.matrix_multiply(self.m, self.get_translate(tx, ty))
def post_rotate(self, theta, x=0, y=0):
if x == 0 and y == 0:
self.m = self.matrix_multiply(self.m, self.get_rotate(theta))
else:
self.post_translate(x, y)
self.post_rotate(theta)
self.post_translate(-x, -y)
def post_cat(self, matrix_list):
for mx in matrix_list:
self.m = self.matrix_multiply(self.m, mx)
def pre_scale(self, sx=1, sy=None):
if sy is None:
sy = sx
self.m = self.matrix_multiply(self.get_scale(sx, sy), self.m)
def pre_translate(self, tx, ty):
self.m = self.matrix_multiply(self.get_translate(tx, ty), self.m)
def pre_rotate(self, theta):
self.m = self.matrix_multiply(self.get_rotate(theta), self.m)
def pre_cat(self, matrix_list):
for mx in matrix_list:
self.m = self.matrix_multiply(mx, self.m)
def point_in_matrix_space(self, v0, v1=None):
m = self.m
if v1 is None:
try:
return [
v0[0] * m[0] + v0[1] * m[3] + 1 * m[6],
v0[0] * m[1] + v0[1] * m[4] + 1 * m[7],
v0[2]
]
except IndexError:
return [
v0[0] * m[0] + v0[1] * m[3] + 1 * m[6],
v0[0] * m[1] + v0[1] * m[4] + 1 * m[7]
# Must not have had a 3rd element.
]
return [
v0 * m[0] + v1 * m[3] + 1 * m[6],
v0 * m[1] + v1 * m[4] + 1 * m[7]
]
@staticmethod
def get_identity():
return \
1, 0, 0, \
0, 1, 0, \
0, 0, 1 # identity
@staticmethod
def get_scale(sx, sy=None):
if sy is None:
sy = sx
return \
sx, 0, 0, \
0, sy, 0, \
0, 0, 1
@staticmethod
def get_translate(tx, ty):
return \
1, 0, 0, \
0, 1, 0, \
tx, ty, 1
@staticmethod
def get_rotate(theta):
tau = math.pi * 2
theta *= tau / 360
ct = math.cos(theta)
st = math.sin(theta)
return \
ct, st, 0, \
-st, ct, 0, \
0, 0, 1
@staticmethod
def matrix_multiply(m0, m1):
return [
m1[0] * m0[0] + m1[1] * m0[3] + m1[2] * m0[6],
m1[0] * m0[1] + m1[1] * m0[4] + m1[2] * m0[7],
m1[0] * m0[2] + m1[1] * m0[5] + m1[2] * m0[8],
m1[3] * m0[0] + m1[4] * m0[3] + m1[5] * m0[6],
m1[3] * m0[1] + m1[4] * m0[4] + m1[5] * m0[7],
m1[3] * m0[2] + m1[4] * m0[5] + m1[5] * m0[8],
m1[6] * m0[0] + m1[7] * m0[3] + m1[8] * m0[6],
m1[6] * m0[1] + m1[7] * m0[4] + m1[8] * m0[7],
m1[6] * m0[2] + m1[7] * m0[5] + m1[8] * m0[8]]

Wyświetl plik

@ -4,6 +4,7 @@ name = "pyembroidery"
from .PyEmbroidery import *
from .EmbConstant import *
from .EmbPattern import EmbPattern
from .EmbMatrix import EmbMatrix
# items available in a sub-heirarchy (e.g. pyembroidery.PecGraphics.get_graphic_as_string)
from .PecGraphics import get_graphic_as_string

Wyświetl plik

@ -6,97 +6,162 @@ from pyembroidery import *
class TestEmbpattern(unittest.TestCase):
def position_equals(self, stitches, j, k):
self.assertEqual(stitches[j][:1], stitches[k][:1])
def test_write(self):
pattern = EmbPattern()
pattern.stitch_abs(0, 0)
pattern.stitch_abs(0, 100)
pattern.add_command(MATRIX_ROTATE, 30)
pattern.stitch_abs(100, 100)
pattern.stitch_abs(100, 0)
pattern.stitch_abs(0, 0)
stitches = pattern.stitches
assert (stitches[-1][0] == 0)
assert (stitches[-1][1] == 0)
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "red")
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "blue")
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "green")
write_dst(pattern, "file.dst")
dst_pattern = read_dst("file.dst")
self.assertIsNotNone(dst_pattern)
self.assertEqual(dst_pattern.count_stitch_commands(STITCH), 5)
self.assertNotEqual(dst_pattern.stitches[-1][0], 0)
self.assertNotEqual(dst_pattern.stitches[-1][1], 0)
self.assertEqual(dst_pattern.count_stitch_commands(STITCH), 15)
self.position_equals(dst_pattern.stitches, 0, -1)
print("dst: ", dst_pattern.stitches)
write_exp(pattern, "file.exp")
exp_pattern = read_exp("file.exp")
self.assertIsNotNone(exp_pattern)
self.assertEqual(exp_pattern.count_stitch_commands(STITCH), 5)
self.assertNotEqual(exp_pattern.stitches[-1][0], 0)
self.assertNotEqual(exp_pattern.stitches[-1][1], 0)
self.assertEqual(exp_pattern.count_stitch_commands(STITCH), 15)
self.position_equals(exp_pattern.stitches, 0, -1)
print("exp: ", exp_pattern.stitches)
write_vp3(pattern, "file.vp3")
vp3_pattern = read_vp3("file.vp3")
self.assertIsNotNone(vp3_pattern)
self.assertEqual(vp3_pattern.count_stitch_commands(STITCH), 5)
self.assertNotEqual(vp3_pattern.stitches[-1][0], 0)
self.assertNotEqual(vp3_pattern.stitches[-1][1], 0)
self.assertEqual(vp3_pattern.count_stitch_commands(STITCH), 15)
self.position_equals(vp3_pattern.stitches, 0, -1)
print("vp3: ", vp3_pattern.stitches)
write_jef(pattern, "file.jef")
jef_pattern = read_jef("file.jef")
self.assertIsNotNone(jef_pattern)
self.assertEqual(jef_pattern.count_stitch_commands(STITCH), 5)
self.assertNotEqual(jef_pattern.stitches[-1][0], 0)
self.assertNotEqual(jef_pattern.stitches[-1][1], 0)
self.assertEqual(jef_pattern.count_stitch_commands(STITCH), 15)
self.position_equals(jef_pattern.stitches, 0, -1)
print("jef: ", jef_pattern.stitches)
write_pec(pattern, "file.pec")
pec_pattern = read_pec("file.pec")
self.assertIsNotNone(pec_pattern)
self.assertEqual(pec_pattern.count_stitch_commands(STITCH), 6)
self.assertNotEqual(pec_pattern.stitches[-1][0], 0)
self.assertNotEqual(pec_pattern.stitches[-1][1], 0)
self.assertEqual(pec_pattern.count_stitch_commands(STITCH), 16) # 5
self.position_equals(pec_pattern.stitches, 0, -1)
print("pec: ", pec_pattern.stitches)
write_pes(pattern, "file.pes")
pes_pattern = read_pes("file.pes")
self.assertIsNotNone(pes_pattern)
self.assertEqual(pes_pattern.count_stitch_commands(STITCH), 6)
self.assertNotEqual(pes_pattern.stitches[-1][0], 0)
self.assertNotEqual(pes_pattern.stitches[-1][1], 0)
self.assertEqual(pes_pattern.count_stitch_commands(STITCH), 16) # 5
self.position_equals(pes_pattern.stitches, 0, -1)
print("pes: ", pes_pattern.stitches)
write_u01(pattern, "file.u01")
u01_pattern = read_u01("file.u01")
self.assertIsNotNone(u01_pattern)
self.assertEqual(u01_pattern.count_stitch_commands(STITCH), 5)
self.assertNotEqual(u01_pattern.stitches[-1][0], 0)
self.assertNotEqual(u01_pattern.stitches[-1][1], 0)
self.assertEqual(u01_pattern.count_stitch_commands(STITCH), 15)
self.position_equals(u01_pattern.stitches, 0, -1)
print("u01: ", u01_pattern.stitches)
write_csv(pattern, "file.csv")
csv_pattern = read_csv("file.csv")
self.assertIsNotNone(csv_pattern)
self.assertEqual(csv_pattern.count_stitch_commands(STITCH), 5)
self.assertNotEqual(csv_pattern.stitches[-1][0], 0)
self.assertNotEqual(csv_pattern.stitches[-1][1], 0)
self.assertEqual(csv_pattern.count_stitch_commands(STITCH), 15)
self.position_equals(csv_pattern.stitches, 0, -1)
print("csv: ", csv_pattern.stitches)
def position_equals(self, stitches, j, k):
self.assertEqual(stitches[j][0], stitches[k][0])
self.assertEqual(stitches[j][1], stitches[k][1])
def test_matrix(self):
matrix = EmbMatrix()
matrix.post_rotate(90, 100, 100)
p = matrix.point_in_matrix_space(50, 50)
self.assertAlmostEqual(p[0], 150)
self.assertAlmostEqual(p[1], 50)
matrix.reset()
matrix.post_scale(2, 2, 50, 50)
p = matrix.point_in_matrix_space(50, 50)
self.assertAlmostEqual(p[0], 50)
self.assertAlmostEqual(p[1], 50)
p = matrix.point_in_matrix_space(25, 25)
self.assertAlmostEqual(p[0], 0)
self.assertAlmostEqual(p[1], 0)
matrix.post_rotate(45, 50, 50)
p = matrix.point_in_matrix_space(25, 25)
self.assertAlmostEqual(p[0], 50)
matrix.reset()
matrix.post_scale(0.5, 0.5)
p = matrix.point_in_matrix_space(100, 100)
self.assertAlmostEqual(p[0], 50)
self.assertAlmostEqual(p[1], 50)
matrix.reset()
matrix.post_scale(2, 2, 100, 100)
p = matrix.point_in_matrix_space(50, 50)
self.assertAlmostEqual(p[0], 0)
self.assertAlmostEqual(p[1], 0)
def test_matrix_commands(self):
pattern = EmbPattern()
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "red")
pattern.add_block([(10, 10), (10, 110), (110, 110), (110, 10), (10, 10)], "red")
pattern.add_command(MATRIX_ROTATE, 45)
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "blue")
pattern.add_block([(10, 10), (10, 110), (110, 110), (110, 10), (10, 10)], "blue")
pattern.add_command(MATRIX_ROTATE, 45)
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "aqua")
pattern.add_block([(10, 10), (10, 110), (110, 110), (110, 10), (10, 10)], "aqua")
pattern = pattern.get_normalized_pattern()
self.position_equals(pattern.stitches, 5, 6)
self.position_equals(pattern.stitches, 10, 11)
print(pattern.stitches)
print("rotate:", pattern.stitches)
self.assertAlmostEqual(pattern.stitches[4][0], pattern.stitches[6][0])
self.assertAlmostEqual(pattern.stitches[4][1], pattern.stitches[6][1])
self.assertAlmostEqual(pattern.stitches[10][0], pattern.stitches[12][0])
self.assertAlmostEqual(pattern.stitches[10][1], pattern.stitches[12][1])
self.assertAlmostEqual(pattern.stitches[4][0], pattern.stitches[12][0])
self.assertAlmostEqual(pattern.stitches[4][1], pattern.stitches[12][1])
write_svg(pattern, "file.svg")
pattern = EmbPattern()
pattern.add_block([(10, 10), (10, 110), (110, 110), (110, 10), (10, 10)], "red")
pattern.add_command(MATRIX_TRANSLATE, 20, 40)
pattern.add_block([(10, 10), (10, 110), (110, 110), (110, 10), (10, 10)], "blue")
pattern.add_command(MATRIX_TRANSLATE, -20, -40)
pattern.add_block([(10, 10), (10, 110), (110, 110), (110, 10), (10, 10)], "aqua")
pattern = pattern.get_normalized_pattern()
print("translate:", pattern.stitches)
self.assertIsNotNone(pattern.stitches)
self.assertEqual(pattern.count_stitch_commands(MATRIX_TRANSLATE), 0)
self.assertAlmostEqual(pattern.stitches[4][0], pattern.stitches[12][0])
self.assertAlmostEqual(pattern.stitches[4][1], pattern.stitches[12][1])
write_svg(pattern, "file2.svg")
pattern = EmbPattern()
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "red")
pattern.add_command(MATRIX_TRANSLATE, 20, 40)
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "blue")
pattern.add_command(MATRIX_ROTATE, -90)
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "aqua")
pattern = pattern.get_normalized_pattern()
print("transrot:", pattern.stitches)
self.assertIsNotNone(pattern.stitches)
self.assertEqual(pattern.count_stitch_commands(MATRIX_TRANSLATE), 0)
self.assertEqual(pattern.count_stitch_commands(MATRIX_ROTATE), 0)
# self.assertAlmostEqual(pattern.stitches[12][0], pattern.stitches[6][0])
# self.assertAlmostEqual(pattern.stitches[12][1], pattern.stitches[6][1])
write_svg(pattern, "file3.svg")
pattern = EmbPattern()
pattern.add_block([(10, 10), (10, 110), (110, 110), (110, 10), (10, 10)], "red")
pattern.add_command(MATRIX_TRANSLATE, 20, 40)
pattern.add_block([(10, 10), (10, 110), (110, 110), (110, 10), (10, 10)], "blue")
pattern.add_command(MATRIX_SCALE, 2, 2)
pattern.add_block([(10, 10), (10, 110), (110, 110), (110, 10), (10, 10)], "aqua")
pattern = pattern.get_normalized_pattern()
print("transcale:", pattern.stitches)
self.assertIsNotNone(pattern.stitches)
self.assertEqual(pattern.count_stitch_commands(MATRIX_TRANSLATE), 0)
self.assertEqual(pattern.count_stitch_commands(MATRIX_SCALE), 0)
# self.assertAlmostEqual(pattern.stitches[12][0], pattern.stitches[6][0])
# self.assertAlmostEqual(pattern.stitches[12][1], pattern.stitches[6][1])
write_svg(pattern, "file4.svg")