Last active
January 9, 2024 02:02
-
-
Save ryanbugden/1b1efbbaff35e3a6b572fefb7c9719c4 to your computer and use it in GitHub Desktop.
Looks at selected points, attempts to pair them up, and consolidates each pair into one point (attempts to preserve curve)
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
# menuTitle: Consolidate Selected Point Pairs | |
# shortCut : shift + control + f | |
from fontTools.misc.fixedTools import otRound | |
MAKE_INTO_ONE_POINT = True | |
def average(lst): | |
return sum(lst) / len(lst) | |
def find_point_pairs_from_selection(g): | |
paired_points = [] | |
for c in g.contours: | |
prev_next = None | |
for pt in c.points: | |
# If the point is the same as the second of the last pair, continue on... | |
if pt == prev_next: | |
continue | |
# If the point is in the selection, see if the next point is also, and pair them. | |
if pt in g.selectedPoints: | |
# Get next on-curve point | |
try: | |
next_point = c.points[pt.index + 1] | |
except IndexError: | |
next_point = c.points[0] | |
if next_point.type == 'offcurve': | |
next_point = c.points[pt.index + 3] | |
if next_point in g.selectedPoints: | |
pt_pair = (pt, next_point) | |
paired_points.append(pt_pair) | |
prev_next = next_point | |
return paired_points | |
def find_bpoint_pairs_from_selection(g): | |
paired_bpoints = [] | |
for c in g.contours: | |
prev_next = None | |
for bpt in c.bPoints: | |
# If the point is the same as the second of the last pair, continue on... | |
if bpt == prev_next: | |
continue | |
# If the point is in the selection, see if the next point is also, and pair them. | |
if bpt in g.selectedBPoints: | |
# Get next on-curve point | |
try: | |
next_bpoint = c.bPoints[bpt.index + 1] | |
except IndexError: | |
next_bpoint = c.bPoints[0] | |
if next_bpoint in g.selectedBPoints: | |
bpt_pair = (bpt, next_bpoint) | |
paired_bpoints.append(bpt_pair) | |
prev_next = next_bpoint | |
return paired_bpoints | |
def consolidate_pair(two_pts, two_bpts): | |
point_coords = [(pt.x, pt.y) for pt in two_pts] | |
average_coords = (otRound(average([coord[0] for coord in point_coords])), otRound(average([coord[1] for coord in point_coords]))) | |
# Snap all selected points to the same contour | |
for pt in two_pts: | |
pt.x, pt.y = average_coords | |
# Delete all but one point | |
if MAKE_INTO_ONE_POINT == True: | |
point_amount = len(two_bpts) | |
i = 0 | |
for bpt in two_bpts: | |
i += 1 | |
if i < point_amount: # Currently always going to be 2, but could use this on multiple | |
bpt.contour.removeBPoint(bpt, preserveCurve=True) | |
g = CurrentGlyph() | |
with g.undo("Consolidate selected points"): | |
with g.holdChanges(): | |
paired_points = find_point_pairs_from_selection(g) | |
paired_bpoints = find_bpoint_pairs_from_selection(g) | |
# Put points and bPoints together | |
pts_and_bpts = [] | |
i = 0 | |
for i, pair in enumerate(paired_points): | |
pts_and_bpts.append((pair, paired_bpoints[i])) | |
# Consolidate those pairs into one point each | |
for (pt_pair, bpt_pair) in pts_and_bpts: | |
consolidate_pair(pt_pair, bpt_pair) | |
# Deselect points | |
for pt in g.selectedPoints: | |
pt.selected = False | |
g.changed() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment