Some mathematical help

Hello, please help. ChatGPT is unable to understand my (maybe too amateurish) explanations of what I want to achieve (and has rather annoyingly bad knowledge of the Glyphs API).

I have the following:

As you can see, the curve segment in the foreground has one end which is not orthogonal. In the background, I have manually extended it until it became orthogonal. I want to keep the shape of the current curve segment, but extend it (like with the “open corner” function).

How would this work mathematically? Essentially, I am looking for the “offset” argument in the openCornerAtNode_offset_() function for the resulting curve to become orthogonal at both ends (I am unsure whether this is the correct terminology, please advise).

Thanks!

You can elongate the segments by “dividing” it with a t value bigger than 1, like 1.1 or 1.2. Then you check for extreme points …

Right, I did that. I used tangentAtTime_() and checked whether its angle is orthogonal.

But that’s not very efficient, of course. Any hints where I can dig further? I’m having trouble doing my research, as I simply don’t have the terminology to describe what I need to know.

There is a c-function that can compute the extreme point. That can be used from python like this:

from AppKit import NSBundle
bundle = NSBundle.bundleForClass_(GSFont)
objc.loadBundleFunctions(bundle, globals(), [("GSExtremTimesOfBezier", b'v{CGPoint=dd}{CGPoint=dd}{CGPoint=dd}{CGPoint=dd}o^do^do^do^d')])
s = Layer.shapes[0].segments[0]
print(GSExtremTimesOfBezier(s[0], s[1], s[2], s[3], None, None, None, None))

it returns a tuple of four floats. All values below 1 are valid extreme-t-points.

I added a extremPoints and extremTimes method to GSPathSegment that can be used from python as is.

Amazing! Thank you! I’ll try and get that to work. I need this desperately for a tight project deadline, so any chance the update with the Python functions makes if out soon would be a godsend :slight_smile:

Hello again. I tried the above, but sadly, it looks like it won’t calculate path times greater than 1 (or smaller than 0). I specifically need it to calculate the vertical/horizontal extreme location path time outside of the existing segment. Currently, it will only give maxint if the segment doesn’t have an extreme:

You first need to elongate the segment before finding extremes as described here:

Sure, but that really isn’t efficient at all.

Or am I missing something? I would really dislike elongating the segment in order to then test it. Is there no way of calculating the exact time value by which I need to elongate the segment in order to achieve an extreme?

I don’t think there is a good, efficient solution.

A Bézier segment may never have an extreme point, no matter how much you elongate it. This is why it’s difficult to provide a general solution to what you are asking for.

Alright, thanks. Can you help me figure out how to elongate the segment in order to test it?

Take the four nodes, stick then in the divideCurve() function or use the GSPathSegment methods. You get four new points out and those four points you check for extremes …

Thank you very much, this is extremely handy.

One thing: The spelling is extremePoints and extremeTimes, so it’s currently missing an e in both.

One more request, would it be possible to make these functions available for simple points? So something like a standalone method

extremePoints(P0, P1, P2, P3)
extremeTimes(P0, P1, P2, P3)

That would save the annoying hassle of first initialising a new segment with these points to then use its extremePoints/extremeTimes method.

Edit, yet another bonus:
Add an argument for whether the italic angle should be taken into account for finding vertical extremes. Currently, only turly vertical extremes are given, but it would be immensely useful to be able to get the italic extremes as well.
Or, maybe more adaptable: A function that returns points/times for a given angle.

Those are available but need to be imported as shown above. Check the header of GSGeometrieHelper in the core framework.

Before those get baked into the api and documentation, shouldn’t those typos be fixed to extremePoints and extremeTimes? Note the missing e’s.

I’ll fix it with the next update.

In order to calculate the point at which the curve becomes vertical you need to look at the derivative. If you ever heard about derivatives of functions like f(x) you will surely understand derivatives of Bézier curves. They are surprisingly easy and can be very handy.

1 Like

Thanks Tim. I’m afraid I’m really struggling to catch up on maths (which I hated at school, sadly), but I’ll look into derivatives.

I’m afraid I don’t have the time right this moment to do so and am in desperate need of finding a way to calculate the path time at which a Bézier curve reaches a certain angle (like finding its H/V extremes, just with arbitrary angles). Any chance you would have an idea off the top of your head?

To find a specific angle, rotate the whole segment (use a NSAffineTransform) by that angel and then search for extreme points as explained above.

1 Like

That’s as smart as it is obvious. Thanks!