def direction_vector(self): """ Vector in the direction of the segment, going from `start` to `end` and with the same length as the segment itself. :return: `Vector` with length equal to segment's length """ return make_vector_between(self.start, self.end)
def contains_point(self, point): """ Tests whether the polygon contains the given point. :param point: `Point` :return: `bool` contains point? """ if point in self.vertices: return True vecs = [make_vector_between(point, vertex) for vertex in self.vertices] paired_vecs = make_round_pairs(vecs) angle_sum = reduce(operator.add, [v1.angle_to(v2) for v1, v2 in paired_vecs]) return are_close_enough(angle_sum, 2 * math.pi)
def intersection_with(self, other): """ Computes the intersection with another line. Returns `None` if the lines don't intersect. :param other: `Line` :return: intersection `Point` or `None` """ if self.is_parallel_to(other): return None d1, d2 = self.direction, other.direction cross_prod = d1.cross(d2) delta = make_vector_between(self.base, other.base) t1 = (delta.u * d2.v - delta.v * d2.u) / cross_prod return self.base.displaced(d1, t1)
def penetration_vector(self, other): """ Assuming this and `other` circles overlap, it computes the vector going from `other`'s center point towards this' center point, and has a length of the maximum penetration between the two. :param other: `Circle` :return: `Vector` """ if not self.overlaps(other): return None direction = make_vector_between(other.center, self.center) centers_dist = self.center.distance_to(other.center) radii_sum = self.radius + other.radius return direction.with_length(radii_sum - centers_dist)
def closest_point_to(self, p: Point): """ Computes the point which belongs to the segment and is closest to a given external point `p`. :param p: `Point` :return: `Point` in segment closest to `p` """ v = make_vector_between(self.start, p) d = self.direction_versor vs = v.projection_over(d) if vs < 0: return self.start if vs > self.length: return self.end return self.start.displaced(d, vs)