Add code to drop middle and long, splittable edges

This commit is contained in:
Shaunak Kishore
2015-08-17 11:42:33 -04:00
parent ad4ec0bdbc
commit 7cc924a2cf

View File

@ -3,6 +3,7 @@
Extracts one or more characters from each of the svg fonts in the SVG directory Extracts one or more characters from each of the svg fonts in the SVG directory
and packages them into a 'chars.html' output file. and packages them into a 'chars.html' output file.
''' '''
import collections
import math import math
import os import os
import svg.path import svg.path
@ -147,6 +148,25 @@ def break_path(path):
subpaths[-1].append(element) subpaths[-1].append(element)
return [svg.path.Path(*subpath) for subpath in subpaths] return [svg.path.Path(*subpath) for subpath in subpaths]
def drop_middle_edges(cusps, edges):
# If there is a triple of edges (i, j), (j, k), (k, l) where i and l are
# leaf nodes in the edge graph, drops the edge (j, k). That edge would create
# a stroke that ends in the middle but that should continue along the other
# two edges instead.
adjacency = collections.defaultdict(list)
for (index1, index2) in edges:
adjacency[index1].append(index2)
leaves = set(index for (index, neighbors) in adjacency.iteritems()
if len(neighbors) == 1)
edges_to_remove = set()
for (index1, index2) in edges:
if (any(neighbor != index2 and neighbor in leaves
for neighbor in adjacency[index1]) and
any(neighbor != index1 and neighbor in leaves
for neighbor in adjacency[index2])):
edges_to_remove.add((index1, index2))
return edges.difference(edges_to_remove)
def get_cusps(paths): def get_cusps(paths):
result = {} result = {}
for i, path in enumerate(paths): for i, path in enumerate(paths):
@ -177,11 +197,11 @@ def get_edges(cusps):
for (confidence, index1, index2) in edges: for (confidence, index1, index2) in edges:
other1 = set(b for (a, b) in result if a == index1) other1 = set(b for (a, b) in result if a == index1)
other2 = set(b for (a, b) in result if a == index2) other2 = set(b for (a, b) in result if a == index2)
if other1.intersection(other2): if other1.intersection(other2) or should_split(cusps, index1, index2):
continue continue
result.add((index1, index2)) result.add((index1, index2))
result.add((index2, index1)) result.add((index2, index1))
return result return drop_middle_edges(cusps, result)
def get_svg_path_data(glyph): def get_svg_path_data(glyph):
left = ' d="' left = ' d="'
@ -191,6 +211,18 @@ def get_svg_path_data(glyph):
assert end >= 0, 'Glyph missing d=".*" block:\n{0}'.format(repr(glyph)) assert end >= 0, 'Glyph missing d=".*" block:\n{0}'.format(repr(glyph))
return glyph[start + len(left):end].replace('\n', ' ') return glyph[start + len(left):end].replace('\n', ' ')
def should_split(cusps, index1, index2):
diff = cusps[index2].point - cusps[index1].point
for cusp in cusps.itervalues():
if cusp.index in (index1, index2):
continue
t = ((cusp.point.real - cusps[index1].point.real)*diff.real +
(cusp.point.imag - cusps[index1].point.imag)*diff.imag)/(abs(diff)**2)
distance_to_line = abs(cusps[index1].point + t*diff - cusp.point)
if 0 < t < 1 and distance_to_line < MAX_CUSP_MERGE_DISTANCE:
return True
return False
if __name__ == '__main__': if __name__ == '__main__':
assert len(sys.argv) > 1, 'Usage: ./getchar.py <unicode_codepoint>+' assert len(sys.argv) > 1, 'Usage: ./getchar.py <unicode_codepoint>+'