Last active
September 16, 2020 14:15
-
-
Save Jonty/d7e0278315026c551b86c7f845701bd1 to your computer and use it in GitHub Desktop.
An extremely hacky bit of code to split an SVG of joined line paths into individual lines, and merge straight lines made of smaller lines into single lines
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# An extremely hacky bit of code that takes SVG files output by Blender | |
# and splits all the multi-node line paths into single line paths to make | |
# editing easier. Example: A right-angle path is now two lines that meet. | |
# | |
# Blender has a habit of outputting really _weird_ paths that are annoying | |
# to edit on geometric shapes, and also outputs straight lines that are | |
# made up of many smaller straight line nodes. This code also merges those | |
# mini-line lines into single lines to stop you throwing your computer out | |
# of the window when you try and work with the SVG. | |
# | |
# The SVG parsing in this is hilarious and lazy because I only ever needed | |
# to use this once. It will likely not work with SVG output from any other | |
# program, or even different types of SVG from Blender - but just in case | |
# here's the code. I couldn't find anyone else doing this. | |
import sys | |
import re | |
import math | |
with open(sys.argv[1]) as f: | |
for line in f.readlines(): | |
line = line.strip() | |
matches = re.search('(\s*<path d=" M )([^"]+)( ".*)$', line) | |
if matches: | |
tail = matches.group(3) | |
tail = tail.replace('stroke-width="3.0"', 'stroke-width="1.0"') | |
lines = [] | |
# Split into individual lines | |
coords = re.findall('(\d+\.\d+, \d+.\d+)', matches.group(2)) | |
last_coord = coords.pop(0) | |
for coord in coords: | |
lines.append((last_coord, coord)) | |
last_coord = coord | |
# Merge lines that are part of a contiguous line | |
merged_lines = [] | |
last_line = lines.pop(0) | |
last_point = last_line[0] | |
for line in lines: | |
# Last segment | |
x1, y1 = last_line[0].split(", ") | |
x2, y2 = last_line[1].split(", ") | |
last_slope = math.atan2(float(x2) - float(x1), float(y2) - float(y1)) | |
# This segment | |
x1, y1 = line[0].split(", ") | |
x2, y2 = line[1].split(", ") | |
this_slope = math.atan2(float(x2) - float(x1), float(y2) - float(y1)) | |
if abs(last_slope - this_slope) > 0.01: | |
merged_lines.append((last_point, last_line[1])) | |
last_point = line[0] | |
last_line = line | |
merged_lines.append((last_point, last_line[1])) | |
for line in merged_lines: | |
print("%s%s %s%s" % (matches.group(1), line[0], line[1], tail)) | |
else: | |
print(line) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment