Best way to find intersection II

Monotype gives me an error upon uploading a font concerning intersections.
Until now I used a script by @GeorgSeifert which always did well.

Now it seems not to find overlaps, instead gives me this error:
Show Metrics Keys plugin:
drawForegroundForLayer_: ‘NoneType’ object is not callable

#MenuTitle: Find Overlaps
# -*- coding: utf-8 -*-
__doc__="""
Find Overlaps.
"""

master = Font.masters[Font.masterIndex]

def findOverlaps(layer):
	AllPaths = []
	for component in layer.components:
		AllPaths.append(component.bezierPath)
	for path in layer.paths:
		AllPaths.append(path.bezierPath)
	
	for path in AllPaths:
		for otherPath in AllPaths:
			if path != otherPath:
				if path.intersectWithPath_(otherPath):
					layer.color = 2
					return

for glyph in Font.glyphs:
	layer = glyph.layers[master.id]
	findOverlaps(layer)

This script will not decompose anything. I just marks all glyphs where it found an overlap.

////

I’d be really great to have a script or plugin that would let me easily find intersections!

Many Thanks!
Georg

The error message has nothing to do with the script. The “Show Metrics Keys plugin” seems to cause this. Disable it for now.

Thank you!

I thought it didn’t work because there were no overlaps found :slight_smile:

No I realized, it’s not overlaps causing the trouble,
it’s very small selfintersecting paths!

Is there a way to find these intersections?

Here is another script that finds self intersections:

from GlyphsApp import GSPathFinder
master = Font.masters[Font.masterIndex]

def findOverlaps(layer):
	segments = []
	#for component in layer.components:
	#	AllPaths.append(component.bezierPath)
	for path in layer.paths:
		segments.extend(path.pathSegments())

	if len(segments) == 0:
		return
	operator = GSPathFinder.new()
	origCount = len(segments)
	operator.addIntersections_(segments)
	resultCount = len(segments)
	if origCount != resultCount:
		print "Intersection", layer.parent.name
		layer.color = 2
		return

for glyph in Font.glyphs:
	layer = glyph.layers[master.id]
	findOverlaps(layer)
1 Like

Thank you Georg!
It’s working great :slight_smile:

Just to explain: I’m working on a Shadow Master.
These intersections happen, when subtracting the frontmost path.

AttributeError: ‘GSPath’ object has no attribute ‘pathSegments’. Did you mean: ‘setSegments_’?

Try path.segments instead.

def findOverlaps(layer):
segmentslist = []
#for component in layer.components:
# AllPaths.append(component.bezierPath)
for path in layer.paths:
segmentslist.append(path.segments())

But:
Traceback (most recent call last):
File “”, line 27
File “”, line 12, in findOverlaps
TypeError: ‘PathSegmentsProxy’ object is not callable

Why are you calling path.segments? The error message states that it is not callable. Remove the function call.

Tanks very much !

from GlyphsApp import GSPathFinder
master = Font.masters[Font.masterIndex]

def findOverlaps(layer):
	segmentslist = []
	#for component in layer.components:
	#	AllPaths.append(component.bezierPath)
	for path in layer.paths:
		segmentslist.extend(path.segments)

	if len(segmentslist) == 0:
		return
	operator = GSPathFinder.new()
	origCount = len(segmentslist)
	operator.addIntersections_(segments)
	resultCount = len(segmentslist)
	if origCount != resultCount:
		print("Intersection", layer.parent.name)
		layer.color = 2
		return

for glyph in Font.glyphs:
	layer = glyph.layers[master.id]
	findOverlaps(layer)

But:

Traceback (most recent call last):
  File "<macro panel>", line 29
  File "<macro panel>", line 20, in findOverlaps
AttributeError: 'GSPathOperator' object has no attribute 'addIntersections_'
from GlyphsApp import GSPathOperator
segments1 = list(Layer.shapes[0].segments)
segments2 = list(Layer.shapes[1].segments)
print(len(segments1))
print(GSPathOperator.addIntersections_otherSegments_(segments1, segments2))
print(len(segments1))

Or more generally:

from GlyphsApp import GSPathOperator

segments = []
for path in layer.paths:
	segments.extend(path.segments)

print(len(segments))
print(GSPathOperator.addIntersections_(segments))
print(len(segments))

If you need more information where the intersections are:

from GlyphsApp import GSPathOperator
intersections = Layer.intersections()
print(intersections)
for p in intersections:
	for path in Layer.paths:
		print(path)
		actualPoint, pathTime = path.nearestPointOnPath_pathTime_(p, None)
		if distance(p, actualPoint) < 0.1:
			print(actualPoint, pathTime)

Tanks very much

Can’t figure this out: Layer.overlaps() doesn’t return overlapping nodes, so here it returns only 1 intersection (and ignores the selected one):

Even stranger in Glyphs2, this intersection doesn’t get detected; it seems like there’s 1.5 threshold?

Is there a way to get all-all layer intersections (in both versions)? Or at least set that threshold to 0 in Glyphs2?

Glyphs 2 uses a completely different, third party library for the overlap removal. I change change that (and will update Glyphs 2 only for very critical fixes).

The new overlap code in Glyphs 3 tries to find all places where it needs to cut a path segment. it doesn’t case about this case here.

1 Like

Got it, thank you!

To work around that, I found that there’s this function for bezierPaths:
GSPath1.bezierPath.allIntersectionsWithPath_(GSPath2.bezierPath)
but it returns
<PyObjCPointer object at 0x7f8e41b2ad10>
Is there a way to convert it into a python list? Chat GPT isn’t being helpful :smiley:

May I ask what you need those intersections for?

I’m trying to get where expanded paths (aka Offset Curve) overlap with the rest of the layer to do some corrections there. But whenever the outline accidentally overlaps some node, it gets ignored.

Or maybe there are other ways to get intersections between two or more paths, not necessarily for the whole layer?