simoncozens / beziers.py

Python bezier manipulation library
MIT License
63 stars 15 forks source link

AttributeError: 'MultiPolygon' object has no attribute 'exterior' #6

Open schriftgestalt opened 4 years ago

schriftgestalt commented 4 years ago

I get this error when I run this script inside Glyphs (python 3.8)

from beziers.point import Point
from beziers.path import BezierPath
from beziers.cubicbezier import CubicBezier, Line

def loadPath(gPath):
    bSegs = []
    for gSeg in gPath.segments:
        if gSeg.countOfPoints() == 2:
            p0 = gSeg[0]
            p1 = gSeg[1]
            bSeg = Line(Point(p0.x, p0.y), Point(p1.x, p1.y))
        else:
            p0 = gSeg[0]
            p1 = gSeg[1]
            p2 = gSeg[2]
            p3 = gSeg[3]
            bSeg = CubicBezier(Point(p0.x, p0.y), Point(p1.x, p1.y), Point(p2.x, p2.y), Point(p3.x, p3.y))
        bSegs.append(bSeg)
    bPath = BezierPath.fromSegments(bSegs)
    bPath.closed = gPath.closed
    return bPath

brush = loadPath(Font.glyphs["_brush"].layers[0].shapes[0])
print(brush)
path = loadPath(Layer.shapes[0])
path.closed = False
path.addExtremes()
path.drawWithBrush(brush, 300, 3, 0.12)
print(path.activeRepresentation.segments)
simoncozens commented 4 years ago

I will take a look at this. By the way, you shouldn't need the loadPath function. You should be able to do:

path = BezierPath()
path.activeRepresentation = GSPathRepresentation(path, brush)
simoncozens commented 4 years ago

Could you just try increasing the pathSmoothness and brushSmoothness values in your path.drawWithBrush call? If that fixes it, I will try to make it work out the correct value automatically.

schriftgestalt commented 4 years ago

I doubled all values and it took much longer but produced the same result.

simoncozens commented 4 years ago

OK. Can you give me a test case - simple brush and path that causes it?

schriftgestalt commented 4 years ago

DrawBrushTest.glyphs.zip

from beziers.point import Point
from beziers.path import BezierPath
from beziers.cubicbezier import CubicBezier, Line

def loadPath(gPath):
    bSegs = []
    for gSeg in gPath.segments:
        if gSeg.countOfPoints() == 2:
            p0 = gSeg[0]
            p1 = gSeg[1]
            bSeg = Line(Point(p0.x, p0.y), Point(p1.x, p1.y))
        else:
            p0 = gSeg[0]
            p1 = gSeg[1]
            p2 = gSeg[2]
            p3 = gSeg[3]
            bSeg = CubicBezier(Point(p0.x, p0.y), Point(p1.x, p1.y), Point(p2.x, p2.y), Point(p3.x, p3.y))
        bSegs.append(bSeg)
    bPath = BezierPath.fromSegments(bSegs)
    bPath.closed = gPath.closed
    return bPath

brush = loadPath(Font.glyphs["_brush"].layers[0].shapes[0])
print(brush)
path = loadPath(Layer.shapes[0])
path.closed = False
path.addExtremes()
path.drawWithBrush(brush, 300, 3, 0.12)
print(path.activeRepresentation.segments)
schriftgestalt commented 4 years ago

Open the "A" in and run the script from the macro window.