lines - open path intersection with paths
-
Hey, i'm trying to create a grid of lines that whenever intersect a font (shape) they get thicker. The rough sketch looks like this:
I haven't found a better way to get intersection points with open paths ( https://github.com/typemytype/drawbot/issues/160 )
and i'm doing everything by hand.bez2 = BezierPath() bez2.text("c", font="Helvetica-Bold", fontSize=500) translate(width()*.3, height()*.3) fill(None) stroke(0) bez3 = BezierPath() bez3.moveTo((0, 50)) bez3.lineTo((300, 50)) bez1 = BezierPath() bez1.moveTo((0, 250)) bez1.lineTo((300, 250)) drawPath(bez1) drawPath(bez2) drawPath(bez3) import pyclipper def split(arr, size): arrs = [] while len(arr) > size: pice = arr[:size] arrs.append(pice) arr = arr[size:] arrs.append(arr) return arrs pc = pyclipper.Pyclipper() pc.AddPath(bez2.points, pyclipper.PT_SUBJECT, True) pc.AddPath(bez1.points, pyclipper.PT_SUBJECT, False) pc.AddPath(bez3.points, pyclipper.PT_SUBJECT, False) solution = pc.Execute2(pyclipper.CT_UNION, pyclipper.PFT_NONZERO, pyclipper.PFT_NONZERO) allSolutionPoints = set(bez1.points) | set(bez2.points) | set(bez3.points) for contour in pyclipper.OpenPathsFromPolyTree(solution): for x, y in contour: allSolutionPoints.add((x, y)) allPoints = set(bez1.points) | set(bez2.points) | set(bez3.points) intersections = allSolutionPoints - allPoints s = 5 coord =[] splitted_coord =[] print(intersections) for x, y in intersections: oval(x-s, y-s, s*2, s*2) coord.append(x) coord.append(y) splitted_coord = split(coord, 4) print(splitted_coord) strokeWidth(5) for elem in splitted_coord : line((elem[0],elem[1]),(elem[2],elem[3])) # check original points for x,y in bez2.points: stroke(None) fill(1,0,0) #oval(x-s, y-s, s*2, s*2)
Is there a better way to do it? If i were to continue like this at a certain point everything will mess up:
In this case the points are in the right positions, but the lines should be horizontal and it's driving me crazy.
-
updates:
newPage(500,500) rect(0, 0, width(), height()) fill(0) word = "a" testo0 = BezierPath() testo0.text(word, font="Helvetica-Bold", fontSize=500) testo1 = BezierPath() testo1.text(word, font="Helvetica-Bold", fontSize=500) testo2 = BezierPath() testo2.text(word, font="Helvetica-Bold", fontSize=500) testo3 = BezierPath() testo3.text(word, font="Helvetica-Bold", fontSize=500) testo4 = BezierPath() testo4.text(word, font="Helvetica-Bold", fontSize=500) testo5 = BezierPath() testo5.text(word, font="Helvetica-Bold", fontSize=500) testo6 = BezierPath() testo6.text(word, font="Helvetica-Bold", fontSize=500) translate(width()/4, height()/4) fill(None) stroke(1) bez0 = BezierPath() bez0.moveTo((0, 5)) bez0.lineTo((300, 5)) bez1 = BezierPath() bez1.moveTo((0, 45)) bez1.lineTo((300, 45)) bez2 = BezierPath() bez2.moveTo((0, 90)) bez2.lineTo((300, 90)) bez3 = BezierPath() bez3.moveTo((0, 135)) bez3.lineTo((300, 135)) bez4 = BezierPath() bez4.moveTo((0, 185)) bez4.lineTo((300, 185)) bez5 = BezierPath() bez5.moveTo((0, 225)) bez5.lineTo((300, 225)) bez6 = BezierPath() bez6.moveTo((0, 270)) bez6.lineTo((300, 270)) #drawPath(testo1) drawPath(bez1) drawPath(bez2) drawPath(bez3) drawPath(bez4) drawPath(bez0) drawPath(bez5) drawPath(bez6) import pyclipper def split(arr, size): arrs = [] while len(arr) > size: pice = arr[:size] arrs.append(pice) arr = arr[size:] arrs.append(arr) return arrs pc0 = pyclipper.Pyclipper() pc0.AddPath(testo0.points, pyclipper.PT_SUBJECT, True) pc0.AddPath(bez0.points, pyclipper.PT_SUBJECT, False) pc = pyclipper.Pyclipper() pc.AddPath(testo1.points, pyclipper.PT_SUBJECT, True) pc.AddPath(bez1.points, pyclipper.PT_SUBJECT, False) pc1 = pyclipper.Pyclipper() pc1.AddPath(testo2.points, pyclipper.PT_SUBJECT, True) pc1.AddPath(bez2.points, pyclipper.PT_SUBJECT, False) pc2 = pyclipper.Pyclipper() pc2.AddPath(testo3.points, pyclipper.PT_SUBJECT, True) pc2.AddPath(bez3.points, pyclipper.PT_SUBJECT, False) pc3 = pyclipper.Pyclipper() pc3.AddPath(testo4.points, pyclipper.PT_SUBJECT, True) pc3.AddPath(bez4.points, pyclipper.PT_SUBJECT, False) pc4 = pyclipper.Pyclipper() pc4.AddPath(testo5.points, pyclipper.PT_SUBJECT, True) pc4.AddPath(bez5.points, pyclipper.PT_SUBJECT, False) pc5 = pyclipper.Pyclipper() pc5.AddPath(testo6.points, pyclipper.PT_SUBJECT, True) pc5.AddPath(bez6.points, pyclipper.PT_SUBJECT, False) solution0 = pc0.Execute2(pyclipper.CT_UNION, pyclipper.PFT_NONZERO, pyclipper.PFT_NONZERO) solution = pc.Execute2(pyclipper.CT_UNION, pyclipper.PFT_NONZERO, pyclipper.PFT_NONZERO) solution1 = pc1.Execute2(pyclipper.CT_UNION, pyclipper.PFT_NONZERO, pyclipper.PFT_NONZERO) solution2 = pc2.Execute2(pyclipper.CT_UNION, pyclipper.PFT_NONZERO, pyclipper.PFT_NONZERO) solution3 = pc3.Execute2(pyclipper.CT_UNION, pyclipper.PFT_NONZERO, pyclipper.PFT_NONZERO) solution4 = pc4.Execute2(pyclipper.CT_UNION, pyclipper.PFT_NONZERO, pyclipper.PFT_NONZERO) solution5 = pc5.Execute2(pyclipper.CT_UNION, pyclipper.PFT_NONZERO, pyclipper.PFT_NONZERO) allSolutionPoints0 = set() allSolutionPoints = set() allSolutionPoints1 = set() allSolutionPoints2 = set() allSolutionPoints3 = set() allSolutionPoints4 = set() allSolutionPoints5 = set() for contour in pyclipper.OpenPathsFromPolyTree(solution0): for x, y in contour: allSolutionPoints0.add((x, y)) for contour in pyclipper.OpenPathsFromPolyTree(solution): for x, y in contour: allSolutionPoints.add((x, y)) for contour in pyclipper.OpenPathsFromPolyTree(solution1): for x, y in contour: allSolutionPoints1.add((x, y)) for contour in pyclipper.OpenPathsFromPolyTree(solution2): for x, y in contour: allSolutionPoints2.add((x, y)) for contour in pyclipper.OpenPathsFromPolyTree(solution3): for x, y in contour: allSolutionPoints3.add((x, y)) for contour in pyclipper.OpenPathsFromPolyTree(solution4): for x, y in contour: allSolutionPoints4.add((x, y)) for contour in pyclipper.OpenPathsFromPolyTree(solution5): for x, y in contour: allSolutionPoints5.add((x, y)) allPoints = set(bez0.points) | set(bez1.points) | set(bez2.points) | set(bez3.points) | set(bez4.points) | set(bez5.points) | set(bez6.points) intersections0 = allSolutionPoints0 - allPoints intersections = allSolutionPoints - allPoints intersections1 = allSolutionPoints1 - allPoints intersections2 = allSolutionPoints2 - allPoints intersections3 = allSolutionPoints3 - allPoints intersections4 = allSolutionPoints4 - allPoints intersections5 = allSolutionPoints5 - allPoints s = 10 coord =[] splitted_coord =[] print("0",intersections0) print("-",intersections) print("1",intersections1) print("2",intersections2) print("3",intersections3) print("4",intersections4) print("5",intersections5) print("") fill(1,1,1) for x, y in intersections0: oval(x-s, y-s, s*2, s*2) coord.append(x) coord.append(y) for x, y in intersections: oval(x-s, y-s, s*2, s*2) coord.append(x) coord.append(y) for x, y in intersections1: oval(x-s, y-s, s*2, s*2) coord.append(x) coord.append(y) for x, y in intersections2: oval(x-s, y-s, s*2, s*2) coord.append(x) coord.append(y) for x, y in intersections3: oval(x-s, y-s, s*2, s*2) coord.append(x) coord.append(y) for x, y in intersections4: oval(x-s, y-s, s*2, s*2) coord.append(x) coord.append(y) for x, y in intersections5: oval(x-s, y-s, s*2, s*2) coord.append(x) coord.append(y) splitted_coord = split(coord, 4) print("split2",split(coord, 2)) print("split4",split(coord, 4)) strokeWidth(20) for elem in splitted_coord : try: print (elem[0],elem[1]),(elem[2],elem[3]) line((elem[0],elem[1]),(elem[2],elem[3])) except: continue stroke(1,0,0) #line((53, 135) ,(158, 135)) # check original points for x,y in testo1.points: stroke(None) fill(1,0,1) #oval(x-s, y-s, s*2, s*2)
It just works with some letters, i don't get the order it follows when i add the elements to the array,
coord.append(x) coord.append(y)
. Sometimes the x points shift and it mess everything again.
-
drawBot includes the
fontPens
library, which containsMarginPen
; you can use it to get the intersections of a line with a shape.here’s an example:
from fontPens.marginPen import MarginPen fill(None) stroke(0) B = BezierPath() B.text("g", font="Helvetica-Bold", fontSize=1000) drawPath(B) for y in range(0, height(), 100): strokeWidth(1) line((0, y), (width(), y)) pen = MarginPen(dict(), y, isHorizontal=True) B.drawToPen(pen) strokeWidth(10) intersections = pen.getAll() for i, x in enumerate(intersections): if not i % 2: xNext = intersections[i+1] line((x, y), (xNext, y))
-
@gferreira Perfect, thanks! silly question: where did you find
fontPens
in the documentation?
-
@sinanatra
MarginPen
used to live inroboFab.pens
. with the retirement ofroboFab
, some pens were moved to a new library called fontPens.