```
```python
for i in this.is_python(code):
print("i =", i)
```
```

Which will result in nice looking Python code:

```
for i in this.is_python(code):
print("i =", i)
```

It is strongly advised to use Python 3 syntax.

Images can be included in your post easily, by dragging them onto the edit area. Pasting an image from the clipboard also works.

]]>This gist has all the moving parts: the right folder, the right size. Pretty sure other video apps can be serviced with similar paths.

https://gist.github.com/LettError/9ccc7d7137c0a0b61fd98411fd10655b

]]>sorry for the unclear title, I think showing what I struggle with will make much more sense than describing it. In short, I have created these 'branch' elements that have an initial position and rotation. I am attaching them to the serifs of a type and it looks like this:

The positioning of each branch on each serif I have done by hand here, and you can see it:

So my question is what is good way to align / connect those 'branches' to a set of points (perhaps align with the 2 points that create the serif?) Otherwise, I need to do this for all letters manually, it seems like there is a better solution...

Thank you!

]]>```
'''
Simplest GIF Slideshow
based on "Simplest CSS Slideshow"
http://snook.ca/archives/html_and_css/simplest-css-slideshow
'''
def fadeImgs(img1, img2, seconds, fps=30):
frames = int(seconds * fps)
duration = 1 / fps
w, h = imageSize(img1)
for i in range(frames):
newPage(w, h)
frameDuration(duration)
alpha1 = i * 1.0 / (frames - 1)
alpha2 = 1.0 - alpha1
image(img1, (0, 0), alpha=alpha2)
image(img2, (0, 0), alpha=alpha1)
def makeSlideshow(imgs, static, fade, gifPath, resolution):
w, h = imageSize(imgs[0])
for i, img in enumerate(imgs):
newPage(w, h)
frameDuration(static)
image(img, (0, 0))
nextImg = imgs[(i + 1) % len(imgs)]
fadeImgs(img, nextImg, fade)
saveImage(gifPath, imageResolution=resolution)
imgs = [
"https://farm3.static.flickr.com/2610/4148988872_990b6da667.jpg",
"https://farm3.static.flickr.com/2597/4121218611_040cd7b3f2.jpg",
"https://farm3.static.flickr.com/2531/4121218751_ac8bf49d5d.jpg",
]
makeSlideshow(imgs, 2, 1, '~/Desktop/slideshow-test.gif', 18)
```

]]>Change the

`func_x`

and/or `func_y`

(sin or cos) and/or add some value to the `delta`

to get other curves.Well, actually the curves are just polygons.

```
# ----------------------
# lissajous table
# ----------------------
# settings
cols = 12
rows = 8
cell_s = 80
r_factor = .8 # fraction of the cell size to have a gap between them
func_x = cos # should be `sin` or `cos`
func_y = sin # should be `sin` or `cos`
delta = 0 #pi/3 # some angle in radians
density = 360 # amount of points per cell – higher values make nicer curve approximations
# ----------------------
# calculated settings
radius = (cell_s * r_factor) / 2
step = (2 * pi) / density
pw = cell_s * (cols + 1)
ph = cell_s * (rows + 1)
x_coords = { (col, d) : func_x(step * (col + 1) * d + pi/2 + delta) * radius for col in range(cols) for d in range(density) }
y_coords = { (row, d) : func_y(step * (row + 1) * d + pi/2) * radius for row in range(rows) for d in range(density) }
# ----------------------
# function(s)
def draw_cell(pos, col, row):
cx, cy = pos
points = [(cx + x_coords[(col, f)], cy + y_coords[(row, f)]) for f in range(density)]
polygon(*points)
# ----------------------
# drawings
newPage(pw, ph)
rect(0, 0, pw, ph)
fontSize(12)
translate(0, ph)
fill(1)
text('δ\n{0:.2f}°'.format(degrees(delta)), (cell_s * (1 - r_factor)/2, -20))
for col in range(1, cols+1):
cx = col * cell_s + cell_s * (1 - r_factor)/2
text('{0}\n{1}'.format(func_x.__name__, col), (cx, -20))
for row in range(1, rows + 1):
cy = row * cell_s + cell_s * (1 - r_factor)
text('{0}\n{1}'.format(func_y.__name__, row), (cell_s * (1 - r_factor)/2, -cy))
fill(None)
stroke(.5)
strokeWidth(1)
for col in range(cols):
for row in range(rows):
draw_cell((cell_s * col + cell_s * 1.5, - cell_s * row -cell_s * 1.5), col, row)
```

]]>```
# -------------
# settings
pw = 800
ph = 500
dia = pw * .45
frames = 20
# -------------
# function(s)
def a_page():
newPage(pw, ph)
rect(0, 0, pw, ph)
radialGradient((pw/2, ph/2), (pw/2, ph/2), [(1, 0.8, 0), (0.9, 0.6, 0) ])
oval(pw/2-dia/2, ph/2-dia/2, dia, dia)
def ip(a, b, f): return a + (b-a)*f
# -------------
# drawings
for frame in range(frames):
a_page()
f = frame / frames
x = ip(pw/4, pw/4*3, f)
y = ip(0, ph, f)
fill(0)
if abs(x - pw/2) < .2:
shadow((0, 0), dia/3, (1, 1, 1))
oval(x - dia/2, y - dia/2, dia, dia)
# saveImage('solar_eclipse.gif')
```

]]>Some time ago I got frustrated by the render time so I played a little with multiprocessing. I switched from Drawbot to Processing I wanted to share this code with you guys. Just came across it and figured to share.

Now, don't ask me what does what, since I don't remember `:)`

But I'm sure this will help some people with some long renders. You can render multiple frames a once, so no multiprocessing on one frame.

```
# main.py
import threading
from queue import Queue
import multiprocessing
import datetime
import time
import drawBot
#
import settings as set
def run(args):
frame = args#[0]
print("frame: ", frame)
drawBot.newDrawing() # start from scratch, no multipage
drawBot.newPage(set.canvasWidth, set.canvasHeight)
time = frame / set.frames
# teken een achtergrond
drawBot.fill(1) # wit
drawBot.rect(0, 0, set.canvasWidth, set.canvasHeight)
drawBot.fill(0) # zwart
angle = drawBot.radians(360 * time)
x = set.canvasWidth / 2 + 100 * drawBot.sin(angle)
drawBot.oval(x - 100, 200, 200, 200)
drawBot.saveImage(set.pathExport + set.exportFileName + str(frame) + "." + set.exportFileType)
for i in range(20):
frame = frame * frame
def threader():
while True:
worker = q.get()
run([ worker ])
q.task_done()
q = Queue()
def main_tr():
for x in range(10):
t = threading.Thread(target=threader)
t.daemon = True
t.start()
start = time.time()
for worker in range(100):
q.put(worker)
q.join()
print('total time', time.time() - start)
def main_pool():
multiprocessing.set_start_method('spawn')
p = multiprocessing.Pool( processes = (multiprocessing.cpu_count()-1))
p.map(run, range(set.frames))
p.close
def main_mp():
processes = multiprocessing.cpu_count()
print( 'utilizing %d cores\n' % processes )
ctx = multiprocessing.get_context('spawn')
processes = []
queue = ctx.Queue() # what does this do? :) :)
for frame in range(set.frames):
processes.append(ctx.Process(target=run, args=([ frame ], )))
for p in processes:
p.start()
for p in processes:
p.join()
# for _ in range(times): # I've commented this one out. It works without. But what does it do? :) :)
# assert queue.get(), "One of processes failed."
def main():
for frame in range(set.frames):
run( [ frame ] )
if __name__ == '__main__':
startTime = datetime.datetime.now()
#main_mp() # multiprocessing 1 #10.5
#main_tr() # multithreading
main_pool() #4.55
#main() # default serial # 15.65
print(datetime.datetime.now() - startTime)
print("--End--")
```

```
# settings.py
canvasWidth = 500
canvasHeight = 500
fps = 5
seconds = 10
duration = 1 / fps
frames = seconds * fps
pathExport = '___export/'
exportFileName = "export_"
exportFileType = "gif"
```

Stich it all back together as one gif:

export_gif.py

```
import settings as set
def exportGif():
from drawBot.context.tools.gifTools import generateGif
destinationPath = set.pathExport + "/movie.gif"
images = []
durations = []
for frame in range(set.frames):
path = set.pathExport + set.exportFileName + str(frame) + "." + set.exportFileType
images.append(path)
durations.append(set.duration)
generateGif(images, destinationPath, durations)
if __name__ == '__main__':
exportGif()
```

To end with some shameless self promotion `:)`

You can find a few example on my instagram account @studio.ratata I'll be posting some more stuff soon what I did with DrawBot and Processing.

Have fun with the script!

Tim

`rgba`

colors in sass syntax (or at least I think it was sass)
```
import colorsys
# calculate color bars with interpolated color steps
size(1000,1000)
Variable([
dict(name="steps", ui="Slider", args=dict(value=4, minValue=3, maxValue=15)),
dict(name="hue", ui="Slider", args=dict(value=0.85, minValue=0, maxValue=1)),
dict(name="saturation", ui="Slider", args=dict(value=0.6, minValue=0, maxValue=1)),
dict(name="dark_top", ui="Slider", args=dict(value=.85, minValue=0, maxValue=1)),
dict(name="dark_bottom", ui="Slider", args=dict(value=.15, minValue=0, maxValue=1)),
dict(name="offset", ui="Slider", args=dict(value=.33, minValue=-.5, maxValue=.5)),
], globals())
steps = int(steps)
a = colorsys.hsv_to_rgb(hue%1, saturation, dark_bottom)
b = colorsys.hsv_to_rgb((hue+offset)%1, saturation, dark_top)
def ip(a,b,f):
return a+f*(b-a)
h = height()/(steps+1)
fontSize(min(29, .5*h))
for i in range(steps+1):
f = i/steps
c = (ip(a[0],b[0],f), ip(a[1],b[1],f), ip(a[2],b[2],f))
v = tuple([int(v*255) for v in c])
fill(*c)
rect(0, 0, width(), h)
fill(1,1,1)
t = "$color%d: rgba%s; /*%3.3f%%*/" %(i, str(v), f*100)
text(t, (100, .33*h))
translate(0, h)
print(t)
saveImage("calculateColorScale.png")
```

]]>You cannot draw a circle with Beziers.

When I first read this some time ago I was a bit confused.

Why is this not a circle. It sure looks like one.

After learning a bit more about curve descriptions and calculations I kind of agree but the quote should better say:

You cannot draw a perfect circle with Beziers.

We have a formula to calculate points on a Bezier Curve.

```
x = (1-t)**3*p1[0] + 3*(1-t)**2*t*t1[0] + 3*(1-t)*t**2*t2[0] + t**3*p2[0]
y = (1-t)**3*p1[1] + 3*(1-t)**2*t*t1[1] + 3*(1-t)*t**2*t2[1] + t**3*p2[1]
```

p1 and p2 are the two endpoints and t1 and t2 the two tangent points. t is the factor (0-1) at which we want the point on the curve.

On a bezier curve with the following coördinates:

```
p1 = (1, 0)
p2 = (0, 1)
t1 = (1, tangent_val)
t2 = (tangent_val, 1)
```

we can calculate the tangent_val if we assume that the point at t=0.5 (halfway the curve) is exactly on the circle. Halfway of a quartercircle is 45 degrees so x and y are both at 1/sqrt(2). If we plug these numbers into the formula we can calculate the tangent value:

```
1/sqrt(2) = (1-.5)**3*1 + 3*(1-.5)**2*.5*1 + 3*(1-.5)*.5**2*tangent_val + .5**3*0
...
tangent_val = 4*(sqrt(2)-1)/3 ≈ 0.5522847493
```

With this tangent_val we can calculate other points on the bezier curve. Of which we can calculate the angle in respect to the center point at (0, 0). And with this angle we can use sine and cosine to get the point that would be on a circle.

We can also calculate the distance of the bezier point and see where the offset is the biggest. As we can see the difference is really tiny. With a radius of 1 the biggest off value is 1.0002725295591013 (not even one permille). The difference is hardly visible so I added only the top part of a really long bar chart to make it show.

See the image below:

```
# -------------------
# settings
pw, ph = 595, 842 #A4
margin = 70
tang = 4*(sqrt(2)-1)/3
r = pw - 2 * margin
density = 90 # amount of points
dia_ = 1 # diameter to draw the points
r_plot = 100000 # this is a magnifying factor to make the tiny difference visible.
r_plot_y = margin - r_plot #radius plotting
c_plot_y = ph - 3 * margin - r # circle plotting
# -------------------
# functions
def get_bezier_p(p1, t1, t2, p2, t):
''' get the point on a bezier curve at t (should be between 0 and 1) '''
x = (1 - t)**3 * p1[0] + 3*(1 - t)**2 * t * t1[0] + 3*(1 - t)* t**2 * t2[0] + t**3 * p2[0]
y = (1 - t)**3 * p1[1] + 3*(1 - t)**2 * t * t1[1] + 3*(1 - t)* t**2 * t2[1] + t**3 * p2[1]
return x, y
def get_dist(p1, p2):
''' returns the distance between two points (x, y)'''
return sqrt((p2[0]-p1[0])**2 + (p2[1]-p1[1])**2)
# -------------------
# drawings
newPage(pw, ph)
fill(1)
rect(0, 0, pw, ph)
translate(margin, margin)
# draw the tangent points
rect(r - dia_, c_plot_y + tang*r - dia_, dia_*2, dia_*2)
rect(tang*r -dia_, c_plot_y + r - dia_, dia_*2, dia_*2)
max_off = 1
for i in range(density+1):
# -------
# bezier
# calculate the factor f
f = i/density
fill(0)
if i == 0 or i == (density): dia = dia_ * 4
else: dia = dia_
# get the coordinates for the point at factor f
x_b, y_b = get_bezier_p( (1, 0), (1, tang), (tang, 1), (0, 1), f )
# get the distance of the point from the center at (0, 0)
r_b = get_dist((0, 0), (x_b, y_b))
max_off = max(max_off, r_b)
# get the angle of the point
angle = atan2(y_b, x_b)
# draw the point and a rect for the bar chart
oval(x_b * r - dia/2, c_plot_y + y_b * r - dia/2, dia, dia)
rect((angle/(pi/2)) * r - dia_/2, r_plot_y, dia_, r_plot * r_b)
# -------
# circle
fill(1, 0, 0)
# get the point on a circle
x_c, y_c = cos(angle), sin(angle)
# draw the point and a rect for the bar chart
oval(x_c * r - dia/2, c_plot_y + y_c * r - dia/2, dia, dia)
rect((angle/(pi/2)) * r - dia_/2, r_plot_y, dia_, r_plot)
fill(.3)
if i % 10 == 0:
x_p, y_p = r * f, margin #* 1.5
rect(x_p - .25, y_p, .5, 30)
text('%d°' % (f * 90), (x_p-2, y_p * 1.5))
print (max_off)
text('%.6f' % max_off, (-50, max_off * r_plot - r_plot + margin - 2))
text('%.6f' % 1, (-50, margin - 2))
```

The maybe more interesting peculiarity of bezier curves is the difference between time and distance. We can compare the bezier distance at factor f (0-1) to the circle if we use the same factor to get the appropriate fraction of 90 degrees.

```
# -------------------
# settings
pw, ph = 595, 842 #A4
margin = 70
tang = 4*(sqrt(2)-1)/3
r = pw - 2 * margin
density = 90 # amount of points
dia_ = 1 # diameter to draw the points
r_plot = 100000 # this is a magnifying factor to make the tiny difference visible.
r_plot_y = margin - r_plot #radius plotting
c_plot_y = ph - 3 * margin - r # circle plotting
# -------------------
# functions
def get_bezier_p(p1, t1, t2, p2, t):
''' get the point on a bezier curve at t (should be between 0 and 1) '''
x = (1 - t)**3 * p1[0] + 3*(1 - t)**2 * t * t1[0] + 3*(1 - t)* t**2 * t2[0] + t**3 * p2[0]
y = (1 - t)**3 * p1[1] + 3*(1 - t)**2 * t * t1[1] + 3*(1 - t)* t**2 * t2[1] + t**3 * p2[1]
return x, y
def get_dist(p1, p2):
''' returns the distance between two points (x, y)'''
return sqrt((p2[0]-p1[0])**2 + (p2[1]-p1[1])**2)
# -------------------
# drawings
newPage(pw, ph)
fill(1)
rect(0, 0, pw, ph)
translate(margin, margin)
# draw the tangent points
rect(r - dia_, c_plot_y + tang*r - dia_, dia_*2, dia_*2)
rect(tang*r -dia_, c_plot_y + r - dia_, dia_*2, dia_*2)
for i in range(density+1):
# -------
# bezier
# calculate the factor f
f = i/density
fill(0)
if i == 0 or i == (density): dia = dia_ * 4
else: dia = dia_
# get the coordinates for the point at factor f
x_b, y_b = get_bezier_p( (1, 0), (1, tang), (tang, 1), (0, 1), f )
# get the distance of the point from the center at (0, 0)
r_b = get_dist((0, 0), (x_b, y_b))
# get the angle of the point
angle = atan2(y_b, x_b)
# draw the point and a rect for the bar chart
oval(x_b * r - dia/2, c_plot_y + y_b * r - dia/2, dia, dia)
rect((angle/(pi/2)) * r - dia_/2, r_plot_y, dia_, r_plot)
# -------
# circle
fill(1, 0, 0)
# get the point on a circle
x_c, y_c = cos( pi/2*f ), sin( pi/2*f )
# draw the point and a rect for the bar chart
oval(x_c * r - dia/2, c_plot_y + y_c * r - dia/2, dia, dia)
rect(f * r - dia_/2, r_plot_y, dia_, r_plot)
fill(.3)
if i % 10 == 0:
x_p, y_p = r * f, margin #* 1.5
rect(x_p - .25, y_p, .5, 30)
text('%d°' % (f * 90), (x_p-2, y_p * 1.5))
```

]]>after this tweet:

https://twitter.com/beesandbombs/status/1021746882362728448

and this processing code:

https://gist.github.com/beesandbombs/6f3e6fb723f50b080916816ae8e561e3

I made a DrawBot/Python translation:

```
import math
n = 720
l = 350
twm = math.pi/20
def mapValue(value, start1, stop1, start2, stop2):
p = 1.0*(value-start1) / (stop1 - start1)
return start2 + p*(stop2 - start2)
def spiral(q, R, nt):
path = BezierPath()
origin = width()*.5, height()*.5
path.moveTo(origin)
for i in range(n):
qq = 1.0*i/(n-1)
r = mapValue(math.cos(2*math.pi*qq), 1, -1, 0, R)*math.sqrt(qq)
th = nt*2*math.pi*qq - 4*2*math.pi*t - q
x = r*math.cos(th)
y = -l*qq + r*math.sin(th)
tw = twm*math.sin(2*math.pi*t - math.pi*qq)
xx = x*math.cos(tw) + y*math.sin(tw)
yy = y*math.cos(tw) - x*math.sin(tw)
path.lineTo((origin[0]+xx, origin[1]+yy))
path.endPath()
drawPath(path)
N = 9
frames = 60
for f in range(frames):
newPage(1000, 1000)
frameDuration(1/30)
fill(1)
rect(0, 0, width(), height())
t = 1.0*f/frames
for i in range(N):
R = 42
m = mapValue(math.sin(2*math.pi*t), -1, 1, 0, 1)
nt = 6+6*m
save()
stroke(.5)
fill(None)
strokeWidth(1)
rotate(360.0*i/N, (width()*.5, height()*.5))
spiral(2*math.pi*i/N, R, nt);
restore()
saveImage('davesCreature.gif')
```

One might find mapValue an interesting function featured natively in processing:

https://processing.org/reference/map_.html

Genootschap voor Reclame annual report, 1970

Study for cover of a book series, Le Saviore Geographique (1971)

Cover of book from series Le Saviore Historique (1973)

The most refined version of Schrofer's design uses a 3 x 3 grid of nodes. Each glyph is a path that uses 8 of the 12 possible node⟷node segments to connect all the nodes in the grid. One other apparent rule, that there be no enclosed counters, is enforced by the other rules and the choice of parameters (8 segments, all nodes).

The code I wrote defines the grid nodes and a list of all unique segments. It then uses combinations() to generate a list of every combination of 8 segments. There are 495 candidate paths meeting this criterion.

Then the code tests each candidate by making a dictionary, keyworded by node, of every segment in the path. It validates the path by checking, first, whether the path does in fact touch every node: if there are no values for any node in the dictionary, then the path fails.

Second, it uses a rudimentary graph-checking function (similar to what map applications use to find and compare routes) against that dictionary to confirm that it's possible to use the segments in the candidate path to connect every node to every other node. If it can't find a path for every pairwise combination of nodes, then the path fails.

There are 192 8-segment paths that meet both criteria, so 192 possible glyphs in the system that Schrofer defined. The code draws each path, in such a way that you can adjust the weight of the strokes as Schrofer did—at their most extreme thickness, almost reversing the positive/negative relationship of the strokes and spaces.

```
from itertools import combinations
# next steps: make the number of nodes and number of nodes that path must touch parametric and extensible, generate a master dictionary of nodes/segments, then generate and test paths from that dictionary
canvas = 720
off = canvas/4 # distance between the nodes of the glyph
nodes = [
(-off, off),
(0, off),
(off, off),
(-off, 0),
(0, 0),
(off, 0),
(-off, -off),
(0, -off),
(off, -off)]
width = off/8 # thickness of the drawn path
numSegs = 8 # how many segments long the path for each glyph must be
segs = [
(0, 1),
(0, 3),
(1, 2),
(1, 4),
(2, 5),
(3, 4),
(3, 6),
(4, 5),
(4, 7),
(5, 8),
(6, 7),
(7, 8)]
paths = []
for subset in combinations(range(0, len(segs)), numSegs):
paths.append(subset)
print(len(paths))
# this function is a placeholder in case future methods could draw paths better
def seg(start, stop):
line(start, stop)
# is_empty function from <pythoncentral.io/how-to-check-if-a-list-tuple-or-dictionary-is-empty-in-python/>
def is_empty(any_structure):
if any_structure:
return False
else:
return True
# find_path function adapted from <python.org/doc/essays/graphs/>
def find_path(graph, start, end, path=[]):
path = path + [start]
if start == end:
return path
for node in graph[start]:
if node not in path:
newpath = find_path(graph, node, end, path)
if newpath: return newpath
return None
def validate_path(path):
# dictionary of all segments in path kw by node
p = {'0': [], '1': [], '2': [], '3': [], '4': [], '5': [], '6': [], '7': [], '8': []}
for n in range(len(path)): # this could use cleaning up
for r in range(2):
if r == 0:
k = str(segs[path[n]][r])
p['%s' %k].append(str(segs[path[n]][r+1]))
else:
k = str(segs[path[n]][r])
p['%s' %k].append(str(segs[path[n]][r-1]))
for key in p:
if is_empty(p[key]) == True: # do path segs include all nodes
return False
for l in range(len(p)):
if find_path(p, key, str(l)) == None: # are all nodes connected by same path
return False
return True
valPaths = []
for m in range(len(paths)):
if validate_path(paths[m]) == True:
valPaths.append(paths[m])
print(len(valPaths))
for n in range(len(valPaths)):
newPage(canvas, canvas)
frameDuration(1/3)
fill(1)
rect(0, 0, canvas, canvas)
translate(canvas/2, canvas/2)
fill(None)
stroke(0)
strokeWidth(width)
lineCap('square')
for s in range(len(valPaths[n])):
g = segs[valPaths[n][s]]
seg(nodes[g[0]], nodes[g[1]])
#saveImage('~/Desktop/schrofer_alpha_test.mp4')
saveImage('~/Desktop/schrofer_alpha_test.gif')
```

Here's the result:

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.