예제 #1
0
 def closest_point(self, p):
     """Return the point on the segment that is closest to p, and the distance to it"""
     a, b = P.solve(self.dir, self.dir.perp(), p - self.p)
     if 0 < a < 1:
         return self.p + self.dir * a, self.dir.norm() * abs(b)
     p_dist, q_dist = p.dist(self.p), p.dist(self.q)
     if p_dist < q_dist:
         return self.p, p_dist
     else:
         return self.q, q_dist
예제 #2
0
    def intersect_with_circle(self, center_point, radius):
        """Intersection of segment object with circle. Returns a segment holding either the two
        points intersecting the circle, the point intersecting and the endpoint contained within
        the circle, or None (if no intersection exists)"""

        # First find the closest point on the line.
        # work in the frame of reference where self.p is zero
        segment_direction = self.dir
        segment_norm = segment_direction.norm()
        perp = segment_direction.perp()

        # solve the equation a*segment_direction+b*perp=center_point-self.p, where a and b are
        # the coefficients of the vectors we are looking for. segment_direction and perp are
        # perpendicular and so represent a basis in which we can define a linear combination of
        # them to get center_point-self.p.
        a, b = P.solve(segment_direction, perp, center_point - self.p)
        height = abs(
            b
        ) * segment_norm  # the height of the triangle created by the intersection
        #  points and the center_point

        if height > radius:
            # no intersections
            return None
        base_size = np.sqrt(radius * radius - height *
                            height) / segment_norm  # base_size is normalized
        # to the size of segment_direction

        # locations of intersections on the vector segment_direction
        left = a - base_size
        right = a + base_size
        if right < 0 or left > 1:
            # entire segment is outside of the circle
            return None

        # Return segment in absolute frame of reference, max and min used for cases where there
        # is only one intersection
        return S(self.p + segment_direction * max(0, left),
                 self.p + segment_direction * min(1, right))
예제 #3
0
 def intersection_params(self, other):
     a, neg_b = P.solve(self.dir, other.dir, other.p - self.p)
     if not a:
         return None, None
     return a, -neg_b