def construct_spread(self, spread): """ Calculate the Vertex which meets this point and which creates a given spread with this line from both of its lines. """ #pylint: disable-msg=R0914 if self.line.null(): raise NullLineError if spread == 0: par = self.parallel() return Vertex(par, par) a, b, c = self.geometry.form x0, y0 = self.point.form() a1, b1, _ = self.line.form() U = self.line.vector() k = (1 - spread)*U.norm() # set up the parameters to solve # alpha * x^2 + beta * x * y + gamma * y^2 = 0 # if alpha == 0: # => b * x * y + gamma * y * y == 0 # y(b * x + gamma * y) == 0 # x/y == -gamma/beta alpha = (a*b1 - b*a1)*(a*b1 - b*a1) - k*a beta = 2*((a*b1 - b*a1)*(b*b1 - c*a1) - b*k) gamma = (b*b1 - c*a1)*(b*b1 - c*a1) - k*c if alpha == 0: a2 = alpha # = 0; We use alpha like this b2 = alpha + 1 # = 1; to maintain the field a3 = beta b3 = gamma else: det = beta*beta - 4*alpha*gamma a2 = a3 = 2*alpha b2 = beta + det.sqrt() b3 = beta - det.sqrt() c2 = -(a2*x0 + b2*y0) c3 = -(a3*x0 + b3*y0) l2 = Line(a2, b2, c2, self.geometry) l3 = Line(a3, b3, c3, self.geometry) assert PointLine(self.point, l2).on() assert PointLine(self.point, l3).on() assert Vertex(l2, l3).point == self.point or (l2 == l3 and spread == 1) assert Vertex(self.line, l2).spread() == spread or l2.null() assert Vertex(self.line, l3).spread() == spread or l3.null() return Vertex(l2, l3)
class LineSegment(object): """ A linesegment represents a pair of points. """ def __init__(self, point1, point2): """ Create a new line segment from two points. Both points must be of the same geometry or else a GeometryError will be raised. """ self.point1 = point1 self.point2 = point2 if point1.geometry != point2.geometry: raise GeometryError self.geometry = point1.geometry x1, y1 = point1.form() x2, y2 = point2.form() self.line = Line(y1 - y2, x2 - x1, x1*y2 - x2*y1, self.geometry) def __eq__(self, other): return (self.point1 in [other.point1, other.point2] and self.point2 in [other.point1, other.point2] and self.geometry == other.geometry) @check_geometry def midpoint(self): """ Return the midpoint M of the two points of the line segments so that Q(M, point1) == Q(M, point2). """ line0 = self.perp_bisector() # Find where the equidistant line intersects our line return Vertex(self.line, line0).point @check_geometry def perp_bisector(self): """ Return the perpindicular bisector of the two points. """ x1, y1 = self.point1.form() x2, y2 = self.point2.form() a, b, c = self.geometry.form # Calculate the line of equidistant points a0 = 2*(a*(x1 - x2) + b*(y1 - y2)) b0 = 2*(b*(x1 - x2) + c*(y1 - y2)) c0 = -(a*(x1*x1 - x2*x2) + 2*b*(x1*y1 - x2*y2) + c*(y1*y1 - y2*y2)) line0 = Line(a0, b0, c0, self.geometry) if self.line.null(): raise ValueError, \ "The line between %s and %s is null," \ "so the midpoint is not defined" % \ (str(self.point1), str(self.point2)) return line0 @check_geometry def quadrance(self): """ Calculate the quadrance between the two points of the line segment. """ return (self.point1 - self.point2).norm() @check_geometry def quadrola(self, K): x1, y1 = self.point1.form() x2, y2 = self.point2.form() a, b, c = self.geometry.form X02 = self.point1.norm() X12 = self.point2.norm() aa, bb, cc = M(a*(x2 - x1) + b*(y2 - y1), b*(x2 - x1) + c*(y2 - y1)) return Conic(4*(aa - K*a), 4*2*(bb - K*b), 4*(cc - K*c), 4*(X02 - X12)*(a*(x2 - x1) + b*(y2 - y1)) + \ 4*K*(a*(x1 + x2) + b*(y1 + y2)), 4*(X02 - X12)*(b*(x2 - x1) + c*(y2 - y1)) + \ 4*K*(b*(x1 + x2) + c*(y1 + y2)), (K - X02 - X12)*(K - X02 - X12) - 4*X02*X12, self.geometry)