#!/usr/bin/env python
# coding: utf-8
# # Things that are nice to look at and how to draw them
#
#
#
# We're going to be drawing things. So first, let's choose how we're going to represent points, lines and figures.
#
# #### Representing Points in Python
#
# We choose to represent a point in the plane as a list `[x, y]` containing the x and y coordinates of the point. For example the point A = (3, 4) in the plane will be represented by the list `[3,4]` in python.
#
# #### Representing Lines in Python
#
# We choose to represent a line as a list of two points `[p, q]` containing the endpoints of the line. So for example the segment AB between points A = (0,0) and B = (1,1) would be represented in python as the list `[[0,0], [1,1]]`.
#
#
#
#
# In the following exercice, you'll be asked to return a list of lines.
# ## Dragon Curve
#
# The dragon curve is a figure that appeared on the chapter covers of Jurassic Parc. It looks like this :
#
#
# |
#
#
# The 0-dragon curve between two points P and Q is a simple line between the points:
#
#
#
#
# The 1-dragon curve between two points P and Q looks like this :
#
#
#
#
# #### Recursive definition of the dragon curve
#
# To build the n-dragon curve between points P and Q, you need to define an intermediary point R. Here is how you get R.
# You build a circle with diameter PQ. If you pick any point A on that circle, the triangle PAQ will be a right triangle.
# There are two points on that circle that will not only give you a right triangle, but also an isoscele triangle. Pick one of those points call it R and write a function `gimmeR(P, Q)` that returns the point R. Look at the figure below to better understand.
#
#
# In[ ]:
def gimmeR(P, Q):
pass
gimmeR([0,0], [1, 1]) # should return [1, 0]
gimmeR([0,0], [0,1]) # should return [0.5, 0.5]
# The n-dragon curve between the points P and Q is defined as the concatenation of the (n-1)-dragon curve between P and R and the (n-1)-dragon curve between Q and R. Using `gimmeR`, write a recusive function `dragon(n, P, Q)` that returns the list of segments in the n-dragon curve between P and Q.
# In[ ]:
def dragon(n, P, Q):
pass
# The function `draw(L)` takes a list of lines and draws it. Check that your function works by calling it.
# In[62]:
import matplotlib.pyplot as plt
from matplotlib.patches import Circle, Polygon
from matplotlib.collections import PatchCollection, LineCollection
def draw(L):
plt.style.use('ggplot')
f, ax = plt.subplots()
lc = LineCollection(L)
ax.add_collection(lc)
ax.autoscale()
ax.set_aspect('equal')
plt.axis('off')
plt.show()
# Dragon curves start looking nice and pretty after 10. Here is what a 13-dragon curve looks like :
#
#
# ## Sierpinsky triangles
#
#
#
# #### Representing Triangles in Python
#
# We choose to represent a triangle as a list of three points `[p, q, r]`. The following exercice asks you to return a list of triangles, you should return a list containing lists of three points.
#
# #### Exercice
#
# Here are examples of the Sierpinsky triangles :
#
#
# The triangles are equilateral. Write a recursive function `sierpinsky(p, q, r, n)` that takes three points `p, q, r` (the endpoints of an equilateral triangle), an integer `n` and returns the list of triangles that make up the n-th sierpinsky triangle.
#
# In[ ]:
import numpy as np
import matplotlib.pyplot as plt
def sierpin(p, q, r, n):
pass
### p, q and r below are the endpoints of an equilateral triangle, use them to test your code
p = np.array([0,0])
q = np.array([2,0])
r = np.array([1, 3**0.5])
L = sierpin(p, q, r, 4)
def drawTriangles(L):
triangles = []
for a, b, c in L:
triangles += [Polygon([a, b, c], True)]
f, ax = plt.subplots()
ax.add_collection(PatchCollection(triangles))
ax.autoscale()
ax.set_aspect('equal')
plt.axis('off')
plt.show()
drawTriangles(L)
# ## The Ethiopian-Orthodox Cross (Hard)
#
#
#
#
# The Ethiopian-Orthodox cross can be approximated by a fractal. We're going to try drawing this :
#
#
#
#
# The base figure for the cross looks like this :
#
#
#
# You are provided with a function that gives the set of lines that make up this figure. `base_figure(scale)` returns the base figure centered at the origin (0,0) and scaled by a factor of `scale`.
# #### The recursive definition :
#
#
# The n-cross is composed of 8 (n-1)-crosses. Look at the figures below and try finding how you should combine the 8 crosses :
#
#
#
# 0-cross |
# 1-cross |
# 2-cross |
#
#
#
# You are provided with the functions :
#
# - `rotfigure(figure, angle)` that rotates a given figure
# - `shiftfigure(figure, angle, dist)` that shifts a given figure by a value of `dist` in the direction given by `angle`
# - `rescale(figure, factor)` that rescales a figure
#
** The angles are in radians **
# Use these function to draw the ethiopian cross. (Use trial and error to figure out scaling and shifting parameters)
#
# In[64]:
import numpy as np
import matplotlib.pyplot as plt
def rot(angle, x):
O = np.array([[np.cos(angle), -1*np.sin(angle)], [np.sin(angle), np.cos(angle)]])
return np.dot(O, x)
def shift(angle, dist, x):
vect = dist * np.array([np.cos(angle), np.sin(angle)])
return np.array(x) + vect
def rotfigure(figure, angle):
return [[rot(angle, p[0]), rot(angle, p[1])] for p in figure]
def shiftfigure(figure, angle, dist):
return [[shift(angle, dist, p[0]), shift(angle, dist, p[1])] for p in figure]
def rescale(figure, factor):
return [[factor*np.array(p[0]), factor*np.array(p[1])] for p in figure]
def base_figure(scale):
origin = np.array([0,0])
pi = np.pi
r = 4
v_id = np.array([1,1])
up = np.array([0,1])
right = np.array([1,0])
lst = []
lst.append([origin, origin+scale*v_id])
lst.append([origin+scale*v_id, origin+scale*v_id + r*scale*right])
lst.append([origin+scale*v_id + r*scale*right, origin+scale*v_id + r*scale*right + scale*rot(-pi/2, v_id)])
lst.append([origin+scale*v_id + r*scale*right, origin+scale*v_id + r*scale*right + r*scale*up])
lst.append([origin+scale*v_id + r*scale*right + r*scale*up, origin+scale*v_id + r*scale*right + r*scale*up + scale*v_id])
lst.append([origin+scale*v_id , origin+scale*v_id + r*scale*up])
lst.append([origin+scale*v_id + r*scale*up, origin+scale*v_id + r*scale*up + r*scale*right])
lst.append([origin+scale*v_id + r*scale*up, origin+scale*v_id + r*scale*up + scale*rot(pi/2, v_id)])
#center
center = scale*(1+r/2)*np.array([1,1])
lst = [ [p[0] - center , p[1] - center ] for p in lst ]
return [[rot(pi/4, p[0]), rot(pi/4, p[1])] for p in lst]
def ethiodraw(L):
for pair in L:
a, b = pair
line = plt.Line2D([a[0], b[0]], [a[1], b[1]], lw=2.5, color='k')
plt.gca().add_line(line)
plt.axis('scaled')
plt.axis('off')
#plt.savefig('et0.png', format='png', dpi=300)
plt.show()
# In[ ]:
### Write your function here
def cross(scale, n):
pass
# In[ ]: