Files

440 lines
14 KiB
Python

WHITE=(255,255,255)
from mywindow import Window
from mymaths import sign2,mean
from math import sqrt,atan,pi,cos,sin
from cmath import polar
import random
import time
class Figure:
def __init__(self,forms,color=WHITE):
"""Create a figure object."""
self.forms=forms
self.color=color
def show(self,window):
"""Show segments."""
for form in self.forms:
form.show(window)
class Form:
def __init__(self,points,closed=True,fill=False,width=1,color=WHITE):
"""Create the form object using points."""
self.points=points
self.closed=closed
self.fill=fill
self.width=1
self.color=color
def __add__(self,point):
"""Add a point to the form."""
self.points+=point
def __sub__(self,point):
"""Remove a point to the form."""
self.points.remove(point)
def center(self):
"""Return the point of the center."""
mx=mean([p.x for p in self.points])
my=mean([p.y for p in self.points])
return Point(mx,my)
def sides(self):
""""Return the list of the form sides."""
return [Segment(self.points[i%len(self.points)],self.points[(i+1)%len(self.points)],color=self.color,width=self.width) for i in range(len(self.points))]
def show(self,window):
"""Show the form using a window."""
for point in self.points:
point.show(window)
for side in self.sides():
side.show(window)
def __or__(self,other):
"""Return the bool: (2 sides are crossing)."""
for myside in self.sides():
for otherside in other.sides():
if myside|otherside:
return True
return False
def convex(self):
"""Return the bool (the form is convex)."""
center=self.center()
cx,cy=center[0],center[1]
angles=[]
l=len(self.points)
for i in range(l-1):
A=self.points[(i+l-1)%l]
B=self.points[i%l]
C=self.points[(i+1)%l]
u=Vector(A.x-B.x,A.y-B.y)
v=Vector(C.x-B.x,C.y-B.y)
angle=v^u
if angle>pi:
return True
return False
def getSparse(self): #as opposed to makeSparse which keeps the same form and return nothing
"""Return the form with the most sparsed points."""
center=self.center()
cx,cy=center[0],center[1]
list1=[]
for point in self.points:
px,py=point.x,point.y
vector=Vector(px-cx,py-cy)
angle=vector.polar()[1]
list1.append((angle,point))
list1=sorted(list1,key=lambda x:x[0])
points=[element[1] for element in list1]
return Form(points)
def makeSparse(self):
"""Change the form into the one with the most sparsed points."""
self=self.Sparse()
def __contains__(self,point):
"""Return the bool: (the point is in the form)."""
x,y=point[0],point[1]
p1=Point(x,y)
p2=Point(0,0)
line=Line(p1,p2)
line.show(window)
print(line.__dict__)
for segment in self.sides():
if segment|line:
return True
return False
def rotate(self,angle,center=None):
"""Rotate the form by rotating its points from the center of rotation.
Use center of the shape as default center of rotation.""" #Actually not working
if not center:
C=self.center()
for i in range(len(self.points)):
P=self.points[i]
v=Vector(P.x-C.x,P.y-C.y)
v.rotate(angle)
self.points[i]=v(C)
def move(self,*step):
"""Move the object by moving all its points using step."""
x,y=step[0],step[1]
for i in range(len(self.points)):
self.points[i].x+=x
self.points[i].y+=y
def moveTo(self,position):
"""Move the object to an absolute position."""
x,y=position[0],position[1]
cx,cy=self.center()
for i in range(len(self.points)):
vx=self.points[i].x-cx
vy=self.points[i].y-cy
self.points[i].x=vx+x
self.points[i].y=vy+y
def moveUntil(self,position):
"""Move the object to the position until the point is hit."""
pass
def update(self,input):
"""Update the points."""
for point in self.points:
point.update(input)
def __getitem__(self,index):
"""Return the point of index index."""
return self.points[index]
def __setitem__(self,index,value):
"""Change the points of a form."""
self.points[index]=value
def triangleArea(self,form):
"""Return the area of a triangle of type form."""
a,b,c=form.sides()
A=1/4*sqrt(4*a.l**2*b.l**2-(a.l**2+b.l**2-c.l**2)**2)
def __len__(self):
"""Return number of points."""
return len(self.points)
class Polygon:
def __init__(self,points,fill=False,width=1,color=WHITE,showpoints=True):
"""Create the polygon using points, fill, width, color and showpoints."""
self.points=points
self.fill=fill
self.width=1
self.color=color
self.showpoints=showpoints
def show(self,window):
"""Show the polygon using window."""
positions=[[p.x,p.y] for p in self.points]
window.draw.polygon(window.screen,self.color,positions,self.width)
if self.showpoints:
for point in self.points:
point.show(window)
return False
def update(self):
pass
class Point:
def __init__(self,*args,radius=5,fill=False,color=WHITE):
"""Create a point using x, y, radius, fill and color."""
self.x=args[0]
self.y=args[1]
self.n=sqrt(self.x**2+self.y**2)
self.a=atan(self.y/self.x)
self.radius=radius
self.fill=fill
self.color=color
def __contains__(self,other):
"""Return bool if objects is in point."""
ox,oy=other[0],other[1]
if self.radius>=sqrt((ox-self.x)**2+(oy-self.y)**2):
return True
else:
return False
def __getitem__(self,index):
"""Return x or y value using given index."""
if index==0:
return self.x
if index==1:
return self.y
def __setitem__(self,index,value):
"""Change x or y value using given index and value."""
if index==0:
self.x=value
if index==1:
self.y=value
def rotate(self,angle=pi,point=[0,0]):
"""Rotate the point using the angle and the center of rotation.
Uses [0,0] for the center of rotation by default."""
s=Vector(self.x,self.y)
v=Vector(self.x-point[0],self.y-point[1])
sn,sa=s.polar()
vn,va=v.polar()
self.x=s.x+vn*cos(sa+va)
self.y=s.y+vn*sin(sa+va)
print(self.x,self.y)
def move(self,*step):
"""Move the point using given step."""
self.x+=step[0]
self.y+=step[1]
def moveTo(self,position):
"""Move the point to position using given position."""
pass
def show(self,window):
"""Show a point using window."""
window.draw.circle(window.screen,self.color,[int(self.x),int(self.y)],self.radius,not self.fill)
def __add__(self,other):
"""Add two points together by making the sum of their components."""
""" if other.color==self.color:
color=self.color
else:
color=None
if other.width=self.width:
width=self.width
else:
width=None
if"""
return Point(self.x+other[0],self.y+other[1])
def __sub__(self,other):
return Point(self.x-other[0],self.y-other[1])
class Line:
def __init__(self,p1,p2,width=1,color=WHITE):
"""Create the line using 2 points, width and color."""
self.width=width
self.color=color
if p1.x!=p2.x:
self.a=(p2.y-p1.y)/(p2.x-p1.x)
else:
self.a=None
if self.a!=None:
self.b=p1.y-self.a*p1.x
else:
self.b=None
def evaluate(self,x):
"""Evaluate the affine function corresponding to the line using x."""
return self.a*x+self.b
def show(self,window):
"""Show the line using window."""
wcmx,wcmy,wcMx,wcMy=window.coordonnates
my=self.evaluate(wcmx)
My=self.evaluate(wcMx)
window.draw.line(window.screen,self.color,[wcmx,my],[wcMx,My],self.width)
def __or__(self,other):
"""Return bool for (2 lines are crossing)."""
if self.a==other.a:
return None
x=(self.b-other.b)/(other.a-self.a)
y=self.a*x+self.b
return Point(x,y)
class Segment(Line):
def __init__(self,p1,p2,width=1,color=WHITE):
"""Create the segment using 2 points, width and color."""
Line.__init__(self,p1,p2,width,color)
self.p1=p1
self.p2=p2
def center(self):
"""Return the point of the center of the Segment."""
x=(self.p1.x+self.p2.x)/2
y=(self.p1.y+self.p2.y)/2
return Point(x,y,color=self.color)
def show(self,window):
"""Show the segment using window."""
window.draw.line(window.screen,self.color,[self.p1.x,self.p1.y],[self.p2.x,self.p2.y],self.width)
def __len__(self):
"""Return the length of the segment."""
x=p1.x-p2.x
y=p1.y-p2.y
return sqrt(x**2+y**2)
def __or__(self,other):
"""Return bool for (2 segments are crossing)."""
if not self.a or not other.a or not self.b or not other.b:
return None
if self.a==other.a:
return None
x=(self.b-other.b)/(other.a-self.a)
y=self.a*x+self.b
if type(other)==Segment:
mx=max(min(self.p1.x,self.p2.x),min(other.p1.x,other.p2.x))
Mx=min(max(self.p1.x,self.p2.x),max(other.p1.x,other.p2.x))
my=max(min(self.p1.y,self.p2.y),min(other.p1.y,other.p2.y))
My=min(max(self.p1.y,self.p2.y),max(other.p1.y,other.p2.y))
if mx<=x<=Mx and my<=y<=My:
return Point(x,y,color=self.color)
else:
return None
if type(other)==Line:
mx=min(self.p1.x,self.p2.x)
Mx=max(self.p1.x,self.p2.x)
my=min(self.p1.y,self.p2.y)
My=max(self.p1.y,self.p2.y)
if mx<=x<=Mx and my<=y<=My:
return Point(x,y,color=self.color)
else:
return None
else:
return None
class Vector:
def __init__(self,*args,arrow=(3,3),width=1,color=WHITE):
"""Create a vector."""
self.x=args[0]
self.y=args[1]
self.width=width
self.color=color
def show(self,p,window,color=None):
"""Show the vector."""
if not color:
color=self.color
p1=Point(p[0],p[1],color=self.color)
p2=Point(self.x+p[0],self.y+p[1],color=self.color)
s=Segment(p1,p2,width=self.width,color=self.color)
s.show(window)
def __neg__(self):
"""Return the negative vector."""
x=-self.x
y=-self.y
return Vector(x,y,width=self.width,color=self.color)
def polar(self):
"""Return the polar coordonnates for the x and y position of the object."""
return list(polar(complex(self.x,self.y)))
def colinear(self,other):
"""Return if two vectors are colinear."""
return self.x*other.y-self.y*other.x==0
def scalar(self,other):
"""Return the scalar product between two vectors."""
return self.x*other.x+self.y*other.y
def __mul__(self,factor):
"""Multiply a vector by a given factor."""
if type(factor)==Vector:
pass
else:
self.x*=factor
self.y*=factor
def __add__(self,other):
"""Add two vectors together."""
return Vector(self.x+other.x,self.y+other.y,width=self.width,color=self.color)
def rotate(self,angle):
"""Rotate a vector using the angle of rotation."""
n,a=self.polar()
a+=angle
self.x=n*cos(a)
self.y=n*sin(a)
def __getitem__(self,index):
"""Return x or y value using given index."""
if index==0:
return self.x
if index==1:
return self.y
def __setitem__(self,index,value):
"""Change x or y value using given index and value."""
if index==0:
self.x=value
if index==1:
self.y=value
def __call__(self,*points):
"""Return points by applying the vector on those."""
points=[point+self for point in points]
if len(points)==1:
return points[0]
else:
return points
def angle(self):
"""Return the angle of a vector with the [1,0] direction in cartesian coordonnates."""
return self.polar()[1]
def __xor__(self,other):
"""Return the angle between two vectors."""
return self.angle()-other.angle()
class Manager:
def __init__(self,window,forms):
self.window=window
self.forms=forms
def __call__(self):
while self.window.open:
self.window.check()
self.update()
def update(self):
for form in self.forms:
form.update()
class Wrapper:
def __init__(self,form):
self.form=form
def update(self):
pass
if __name__=="__main__":
window=Window()
p1=Point(15,62)
p2=Point(250,400)
p3=Point(800,500)
p4=Point(400,400,color=(0,255,0))
points=[p1,p3,p2,p4]
f=Form([Point(random.randint(1,700),random.randint(1,600)) for i in range(10)],color=(0,0,255))
#f.show(window)
f2=f.getSparse()
p1.show(window)
p2.show(window)
v=Vector(p2[0]-p1[0],p2[1]-p1[1],color=(255,0,0))
center=f2.center()
while window.open:
window.check()
window.clear()
#v.rotate(0.1)
v.show(center,window)
f2.rotate(0.1)
time.sleep(0.1)
f2.show(window)
window.flip()
#Segment(f[0],f[1],color=(255,0,0)).center().show(window)
#print(p4 in f)
#window.clear()
#p4.show(window)
#a=Line(p4,p2,color=(255,0,0))
#b=Segment(p1,p3,color=(255,255,0))
#a.show(window)
#b.show(window)
#p=b|a
#window()
#a=Vector(1,5)