diff --git a/src/element.py b/src/element.py index f356c5a..2c3bbd2 100644 --- a/src/element.py +++ b/src/element.py @@ -2,7 +2,7 @@ import math import sys -from point import Point,l_infinity +from point import Point,l_infinity,l_2 from tools import isint_nonzero,sgn,in_interval # parent class of all elements @@ -39,6 +39,7 @@ class Element(): # override in each subclass # move along edge of element + # delta is the impossible move that was asked for def move_along(self,delta,element): return element @@ -47,6 +48,7 @@ class Element(): class Element_square(Element): # check whether an element interacts with square + # TODO: this only works if element is a square! def check_interaction(self,element): # allow for error return l_infinity(element.pos-self.pos)<(self.size+element.size)/2-1e-11 @@ -56,6 +58,7 @@ class Element_square(Element): return l_infinity(self.pos-x)<=1/2 # check whether an element is touching self + # TODO: this only works if element is a square! def check_touch(self,element): # allow for error if in_interval(l_infinity(element.pos-self.pos),(self.size+element.size)/2-1e-11,(self.size+element.size)/2+1e-11): @@ -63,6 +66,7 @@ class Element_square(Element): return False # find position along a line that comes in contact with the line going through element.pos in direction v + # TODO: this only works if element is a square! def move_on_line_to_stick(self,element,v): # compute intersections with four lines making up square if v.x!=0: @@ -106,6 +110,7 @@ class Element_square(Element): return closest-element.pos # move along edge of square + # TODO: this only works if element is a square! def move_along(self,delta,element): rel=element.pos-self.pos # check if the particle is stuck in the x direction @@ -162,3 +167,45 @@ class Element_square(Element): candidate.x=math.floor(rel/((self.size+element.size)/2))*((self.size+element.size)/2)+self.pos.x-element.pos.x return candidate + +# circular elements +# (size is the diameter) +class Element_circle(Element): + + # check whether an element interacts with square + # TODO: this only works if element is a circle! + def check_interaction(self,element): + # allow for error + return l_2(element.pos-self.pos)<(self.size+element.size)/2-1e-11 + + # whether x is in the support of the element + def in_support(self,x): + return l_2(self.pos-x)<=1/2 + + # check whether an element is touching self + # TODO: this only works if element is a circle! + def check_touch(self,element): + # allow for error + if in_interval(l_2(element.pos-self.pos),(self.size+element.size)/2-1e-11,(self.size+element.size)/2+1e-11): + return True + return False + + # find position along a line that comes in contact with the line going through element.pos in direction v + # TODO: this only works if element is a circle! + def move_on_line_to_stick(self,element,v): + # relative position + x=element.pos-self.pos + # radius of collision circle + R=(element.size+self.size)/2 + + # smallest root of t^2 v^2+2x.v t+x^2-R^2 + t=(-v.dot(x)+sqrt(v.dot(x)*v.dot(v)-v.dot(v)*(x.dot(x)-R*R)))/v.dot(v) + + # return difference to pos + return t*v + + # move along edge of circle + # TODO: this only works if element is a circle! + def move_along(self,delta,element): + x=element.pos-self.pos+delta + return x/l_2(x)*(element.size+self.size)/2+self.pos-element.pos diff --git a/src/painter.py b/src/painter.py index ee922ae..f2cc6a5 100644 --- a/src/painter.py +++ b/src/painter.py @@ -213,7 +213,7 @@ class Painter(Widget): touchx=self.coord_topos_x(touch.x) touchy=self.coord_topos_y(touch.y) - # create new cross + # create new particle if touch.button=="right": new=Cross(touchx,touchy) # snap to lattice diff --git a/src/point.py b/src/point.py index b67d4ed..91dca72 100644 --- a/src/point.py +++ b/src/point.py @@ -49,3 +49,7 @@ class Point: # L infinity norm def l_infinity(x): return max(abs(x.x),abs(x.y)) + +# L 2 norm +def l_2(x): + return sqrt(x.x*x.x+x.y*x.y)