Трета задача:
разширеното евклидово
пространство

„ Програмиране с Python“, ФМИ

29.04.2010г.

Класове

class GeometricError(Exception):

    pass

class Vector:

    def __init__(self, x, y):
        self
.x = x
        self
.y = y
               
   
def __repr__(self):
       
return "Vector(%r, %r)" % (self.x , self.y)

class Vector:

    def __eq__(self, other):
       
return isinstance(other, Vector) and \
            self
.x == other.x and self.y == other.y

class Vector:

    def __add__(self, other):
       
if isinstance(other, Vector):
           
return Vector(self.x + other.x, self.y + other.y)
       
else:
           
return NotImplemented
                       
   
def __sub__(self, other):
       
if isinstance(other, Vector):
           
return self + -other
       
else:
           
return NotImplemented

class Vector:

    def __pos__(self):
       
return self.scaled(1)

   
def __neg__(self):
       
return self.scaled(-1)

class Vector:

    def __mul__(self, other):
       
if isinstance(other, Vector):
           
return self.x*other.x + self.y*other.y
       
elif isinstance(other, numbers.Real):
           
return self.scaled(other)
       
else:
           
return NotImplemented

class Vector:

    def __rmul__(self, other):
       
return self * other
               
   
def __truediv__(self, num):
       
if isinstance(other, numbers.Real):
           
return self.scaled(1/other)
       
else:
           
return NotImplemented

class Vector:

    def scaled(self, num):
       
return Vector(self.x*num, self.y*num)

   
def length(self):
       
return (self*self) ** 0.5

   
def normal(self):
       
return Vector(self.y, -self.x) # or (-y, x)

class Vector:

    def normalized(self):
        length
= self.length()
       
if length == 0:
           
raise GeometricError
       
return Vector(self.x / length, self.y / length)

class Vector:

    def iscollinear(self, other):
       
if self.iszero() or other.iszero():
           
return True
        v1
, v2 = self.normalized(), other.normalized()
       
return v1 == v2 or v1 == -v2

   
def isnormal(self, other):
       
if self.iszero() or other.iszero():
           
return True
       
return self.normal().iscollinear(other)

class Vector:

    def isnormalized(self):
       
return self.length() == 1

   
def iszero(self):
       
return self.x == 0 and self.y == 0

class Point:

    def __init__(self, x, y, z=1):
       
if x == y == z == 0:
           
raise GeometricError
       
else:
            self
.x = x
            self
.y = y
            self
.z = z
                       
   
def __repr__(self):
       
return "Point(%r, %r, %r)" % (self.x, self.y, self.z)

class Point:

    def __eq__(self, other):
       
if isinstance(other, Point):
            triplet1
= self.x, self.y, self.z
            triplet2
= other.x, other.y, other.z
           
return homogenous_coord_eq(triplet1, triplet2)
       
else:
           
return False

Помощни функции

def homogenous_coord_eq(triplet1, triplet2):
   
"""
    The homogenous coordinate triplets
    (a1, a2, a3), (b1, b2, b3) are equal iff:

    |a2 a3| = |a3 a1| = |a1 a2| = 0
    |b2 b3|   |b3 b1|   |b1 b2|
    """

    a1
, a2, a3 = triplet1[0], triplet1[1], triplet1[2]
    b1
, b2, b3 = triplet2[0], triplet2[1], triplet2[2]
    D
= determinant
   
return D(a2,a3,b2,b3) == D(a3,a1,b3,b1) == D(a1,a2,b1,b2) == 0

Помощни функции

def determinant(a1, a2, b1, b2):
   
"""
    Returns the value of the determinant:
    |a1 a2|
    |b1 b2|
    """

   
return a1*b2 - a2*b1

class Point:

    def distance(self, other):
       
if isinstance(other, Line):
           
return other.distance(self)
       
elif isinstance(other, Point) and self.z != 0 and other.z != 0:
            diffx
, diffy = self._x()-other._x(), self._y()-other._y()
           
return Vector(diffx, diffy).length()
       
else:
           
raise GeometricError

class Point:

    def _x(self):
       
return self.x / self.z

   
def _y(self):
       
return self.y / self.z

class Line:

    def __init__(self, a, b):
       
if isinstance(a, Point) and isinstance(b, Point):
           
if a.isinfinite() and b.isinfinite():
                self
.__init_infiniteline()
           
elif a.isinfinite():
                self
.__init_pointvector(b, Vector(a.x, a.y))
           
elif b.isinfinite():
                self
.__init_pointvector(a, Vector(b.x, b.y))
           
else:
                self
.__init_pointpoint(a, b)
       
elif isinstance(a, Point) and isinstance(b, Vector):
           
if a.isinfinite():
                self
.__init_infiniteline()
           
else:
                self
.__init_pointvector(a, b)
       
elif isinstance(a, Vector) and isinstance(b, Point):
           
Line.__init__(self, b, a)
       
else:
           
raise GeometricError

class Line:

    def __init_infiniteline(self):
        self
.a = 0
        self
.b = 0
        self
.c = 1
   
   
def __init_pointvector(self, point, vector):
        point_offset
= \
           
Point(point.x + vector.x*point.z, point.y + vector.y*point.z)
        self
.__init_pointpoint(point, point_offset)

class Line:

    def __init_pointpoint(self, point1, point2):
       
assert(not point1.isinfinite() and not point2.isinfinite())
       
if point1 == point2:
           
raise GeometricError
        point1
, point2 = point1.scaled(point2.z), point2.scaled(point1.z)
        self
.a = point2.y - point1.y
        self
.b = point1.x - point2.x
        self
.c = -(self.a*point1.x + self.b*point1.y) / point1.z

class Line:

    def __repr__(self):
       
if self.isinfinite():
           
return "Line(Point(0,1,0), Point(1,0,0))"
       
else:
            vector
= Vector(-self.b, self.a)
            point1
= Point(0, -self.c/self.b) if self.b != 0 else None
            point2
= Point(-self.c/self.a, 0) if self.a != 0 else None
           
return "Line(%r, %r)" % (point1 or point2, vector)

class Line:

    def __eq__(self, other):
       
if isinstance(other, Line):
            triplet1
= self.a, self.b, self.c
            triplet2
= other.a, other.b, other.c
           
return homogenous_coord_eq(triplet1, triplet2)
       
else:
           
return False

class Line:

    def __contains__(self, point):
       
if point.isinfinite():
            point_vector
= Vector(point.x, point.y)
            line_vector
= self.colinear_vector()
           
return line_vector.iscollinear(point_vector)
       
else:
           
return self.distance(point) == 0

class Line:

    def __mul__(self, other):
       
if not isinstance(other, Line):
           
return NotImplemented
       
if self == other:
           
raise GeometricError
        a1
, b1, c1 = self.a, self.b, self.c
        a2
, b2, c2 = other.a, other.b, other.c
        D
= determinant
        x
= D(b1, c1, b2, c2)
        y
= D(c1, a1, c2, a2)
        z
= D(a1, b1, a2, b2)
       
return Point(x, y, z)

class Line:

    def isparallel(self, other):
       
return self == other or (self * other).isinfinite()
   
   
def isinfinite(self):
       
return self.a == 0 and self.b == 0

class Line:

    def distance(self, point):
       
if point.isinfinite():
           
raise GeometricError
       
else:
            line_vector
= Vector(self.a, self.b)
           
return abs(self.a*point._x() + self.b*point._y() + self.c) \
                   
/ line_vector.length()

class Line:

    def colinear_vector(self):
       
return self.normal_vector().normal()

   
def normal_vector(self):
       
return Vector(self.a, self.b)

Още въпроси?