Add extreme points, removing them and keeping shape

I’m working on a script that allows me to switch between having vertical extreme points, and points with off curves at a certain angle (useful when working on italics, or other use cases where you want to quickly add non vertical/horizontal points in a consistent way), ex:

For now I’m doing this in a straightforward way: rotate the glyph, add extreme points, rotate back.
Then I need to: remove vertical nodes, remove nodes that were the horizontal extremes before rotating back the glyph.

My main issue with this is: having to delete points that were horizontal extremes which I never needed in the first place results in parts of the glyph with segments drawn differently when they shouldn’t have changed, ex: see top part of /a

My second issue is that sometimes when adding extremes on the rotated glyph, it doesn’t keep the previous extreme point from before rotation, resulting in things like this (bottom of counterform):
Rotated Glyph:

Rotated Glyph with new extreme points:

This doesn’t happen when I add the extreme point manually, only when I do it with addNodesAtExtremes()

And finally, I end up with a lot of curve points with unaligned offcurves, like this:

So my questions are:

  • Is there a way to add extreme points with a condition? For example, only add vertical ones, or only add them on a selection of segments instead of a whole GSPath object?

  • how can I make sure that addNodesAtExtremes() does not remove another point?

  • how can I force off curve points to keep their angle? (when deleting nodes manually, the keep shape feature is providing good results, as much as the original curve can be matched with the new node placement, but the results I have using removeNodeCheckKeepShape_() does not seem to be the same. Am I using the right thing?

Tricky. What I would try is make a new GSLayer object with just the parts you want to manipulate, then stitch it back into the original layer.

1 Like

I was preparing some code but that tool a bit longer. I hope I have something by tomorrow.

Here is some sample code that you can use to write your own “add Extremes” function.

# the next few lines load the bridgesupport file that has info about a lot helper functions. 
from AppKit import NSBundle
bundle = NSBundle.bundleForClass_(GSFont.__class__)

for path in Layer.paths:
	for idx in range(len(path.nodes) -1, -1, -1):
		node = path.nodes[idx]
		if node.type == CURVE:
			p1 = path.nodes[idx - 3].position
			p2 = path.nodes[idx - 2].position
			p3 = path.nodes[idx - 1].position
			p4 = node.position
			# The fuction will return a tuple of four floats (one segment can have four extremes). Most of them will be a very big number, ignore those. Find the one that is between zero and one. 
			allTs = GSExtremTimesOfBezier(p1, p2, p3, p4, None, None, None, None)
			Ts = [x for x in allTs if x < 1]
			if len(Ts) > 0:
				# check if you like that extreme
				pathTime = idx + Ts[0]
1 Like

Thats really helpful Georg, perfect for what I want to do. Thanks! :pray:

how can I make sure that addNodesAtExtremes() does not remove another point?

Does that mean that addNodesAtExtremes() has some sort of cleanup feature and is removing close points to the extremes below a threshold? Because if so, if you look at my screenshots above, it gives inconsistent results.

Obviously, not an issue anymore for what Im trying to do thanks to your sample code, just pointing that out in case there’s a bug somewhere?