From f66edc2949aa865fd8f3ca2b590cf43dad57f1ef Mon Sep 17 00:00:00 2001 From: Mario Voigt Date: Sat, 15 Aug 2020 15:21:42 +0200 Subject: [PATCH] fixed and added barrel distortion --- extensions/fablabchemnitz_distortion.py | 99 +++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 extensions/fablabchemnitz_distortion.py diff --git a/extensions/fablabchemnitz_distortion.py b/extensions/fablabchemnitz_distortion.py new file mode 100644 index 00000000..d62e27d5 --- /dev/null +++ b/extensions/fablabchemnitz_distortion.py @@ -0,0 +1,99 @@ +import math +import re +import inkex +from inkex import bezier +from inkex.paths import Path, CubicSuperPath + +class DistortionExtension(inkex.Effect): + def __init__(self): + inkex.Effect.__init__(self) + self.arg_parser.add_argument("--lambda_coef", type=float, default=-5.0, help="command line help") + + def distort_coordinates(self, x, y): + """Method applies barrel distorsion to given points with distorsion center in center of image, selected to + + Args: + x (float): X coordinate of given point + y (float): Y coordinate of given point + + Returns: + tuple(float, float): Tuple with X,Y distorted coordinates of given point + """ + x_u = (x - self.x_c) / (self.width + self.height) + y_u = (y - self.y_c) / (self.width + self.height) + x_d = x_u / 2 / (self.q * y_u**2 + x_u**2 * self.q) * (1 - math.sqrt(1 - 4 * self.q * y_u**2 - 4 * x_u**2 * self.q)) + y_d = y_u / 2 / (self.q * y_u**2 + x_u**2 * self.q) * (1 - math.sqrt(1 - 4 * self.q * y_u**2 - 4 * x_u**2 * self.q)) + x_d *= self.width + self.height + y_d *= self.width + self.height + x_d += self.x_c + y_d += self.y_c + return x_d, y_d + + + + def split_into_nodes(self, nodes_number=1000): + for id, node in self.svg.selected.items(): + if node.tag == inkex.addNS('path', 'svg'): + p = CubicSuperPath(node.get('d')) + new = [] + for sub in p: + new.append([sub[0][:]]) + i = 1 + while i <= len(sub) - 1: + length = bezier.cspseglength( + new[-1][-1], sub[i]) + + splits = nodes_number + for s in range(int(splits), 1, -1): + new[-1][-1], next, sub[ + i] = bezier.cspbezsplitatlength( + new[-1][-1], sub[i], 1.0 / s) + new[-1].append(next[:]) + new[-1].append(sub[i]) + i += 1 + node.set('d', str(CubicSuperPath(new))) + + def effect(self): + if re.match(r'g\d+', + list(self.svg.selected.items())[0][0]) is not None: + raise SystemExit( + "You are trying to distort group of objects.\n This extension works only with path objects due to Inkscape API restrictions.\n Ungroup your objects and try again." + ) + self.split_into_nodes() + self.q = self.options.lambda_coef + nodes = [] + for id, node in self.svg.selected.items(): + if node.tag == inkex.addNS('path', 'svg'): + path = Path(node.get('d')).to_arrays() + nodes += path + nodes_filtered = [x for x in nodes if x[0] != 'Z'] + x_coordinates = [x[-1][-2] for x in nodes_filtered] + y_coordinates = [y[-1][-1] for y in nodes_filtered] + self.width = max(x_coordinates) - min(x_coordinates) + self.height = max(y_coordinates) - min(y_coordinates) + self.x_c = sum(x_coordinates) / len(x_coordinates) + self.y_c = sum(y_coordinates) / len(y_coordinates) + for id, node in self.svg.selected.items(): + if node.tag == inkex.addNS('path', 'svg'): + path = Path(node.get('d')).to_arrays() + distorted = [] + first = True + for cmd, params in path: + if cmd != 'Z': + if first == True: + x = params[-2] + y = params[-1] + distorted.append( + ['M', + list(self.distort_coordinates(x, y))]) + first = False + else: + x = params[-2] + y = params[-1] + distorted.append( + ['L', self.distort_coordinates(x, y)]) + node.set('d', str(Path(distorted))) + + +if __name__ == '__main__': + DistortionExtension().run() \ No newline at end of file