Beispiel #1
0
    def round_corners(self, radius=0.5):
        vertices = self.get_vertices()
        arcs = []
        for v1, v2, v3 in adjacent_n_tuples(vertices, 3):
            vect1 = v2 - v1
            vect2 = v3 - v2
            unit_vect1 = normalize(vect1)
            unit_vect2 = normalize(vect2)
            angle = angle_between_vectors(vect1, vect2)
            # Negative radius gives concave curves
            angle *= np.sign(radius)
            # Distance between vertex and start of the arc
            cut_off_length = radius * np.tan(angle / 2)
            # Determines counterclockwise vs. clockwise
            sign = np.sign(np.cross(vect1, vect2)[2])
            arc = ArcBetweenPoints(v2 - unit_vect1 * cut_off_length,
                                   v2 + unit_vect2 * cut_off_length,
                                   angle=sign * angle)
            arcs.append(arc)

        self.clear_points()
        # To ensure that we loop through starting with last
        arcs = [arcs[-1], *arcs[:-1]]
        for arc1, arc2 in adjacent_pairs(arcs):
            self.append_points(arc1.points)
            line = Line(arc1.get_end(), arc2.get_start())
            # Make sure anchors are evenly distributed
            len_ratio = line.get_length() / arc1.get_arc_length()
            line.insert_n_curves(int(arc1.get_num_curves() * len_ratio))
            self.append_points(line.get_points())
        return self
Beispiel #2
0
    def round_corners(self, radius=0.5):
        vertices = self.get_vertices()
        arcs = []
        for v1, v2, v3 in adjacent_n_tuples(vertices, 3):
            vect1 = v2 - v1
            vect2 = v3 - v2
            unit_vect1 = normalize(vect1)
            unit_vect2 = normalize(vect2)
            angle = angle_between_vectors(vect1, vect2)
            # Negative radius gives concave curves
            angle *= np.sign(radius)
            # Distance between vertex and start of the arc
            cut_off_length = radius * np.tan(angle / 2)
            # Determines counterclockwise vs. clockwise
            sign = np.sign(np.cross(vect1, vect2)[2])
            arc = ArcBetweenPoints(
                v2 - unit_vect1 * cut_off_length,
                v2 + unit_vect2 * cut_off_length,
                angle=sign * angle
            )
            arcs.append(arc)

        self.clear_points()
        # To ensure that we loop through starting with last
        arcs = [arcs[-1], *arcs[:-1]]
        for arc1, arc2 in adjacent_pairs(arcs):
            self.append_points(arc1.points)
            line = Line(arc1.get_end(), arc2.get_start())
            # Make sure anchors are evenly distributed
            len_ratio = line.get_length() / arc1.get_arc_length()
            line.insert_n_curves(
                int(arc1.get_num_curves() * len_ratio)
            )
            self.append_points(line.get_points())
        return self
Beispiel #3
0
    def round_corners(self, radius=0.5):
        vertices = self.get_vertices()
        arcs = []
        for v1, v2, v3 in adjacent_n_tuples(vertices, 3):
            vect1 = v2 - v1
            vect2 = v3 - v2
            unit_vect1 = normalize(vect1)
            unit_vect2 = normalize(vect2)
            angle = angle_between_vectors(vect1, vect2)
            # Negative radius gives concave curves
            angle *= np.sign(radius)
            # Distance between vertex and start of the arc
            cut_off_length = radius * np.tan(angle / 2)
            # Determines counterclockwise vs. clockwise
            sign = np.sign(np.cross(vect1, vect2)[2])
            arcs.append(
                ArcBetweenPoints(v2 - unit_vect1 * cut_off_length,
                                 v2 + unit_vect2 * cut_off_length,
                                 angle=sign * angle))

        self.clear_points()
        # To ensure that we loop through starting with last
        arcs = [arcs[-1], *arcs[:-1]]
        for arc1, arc2 in adjacent_pairs(arcs):
            self.append_points(arc1.points)
            self.add_line_to(arc2.get_start())
        return self
Beispiel #4
0
    def viewing_angle_of_point(self, point):
        # as measured from the positive x-axis
        v1 = self.project(RIGHT)
        v2 = self.project(np.array(point) - self.get_source_point())
        absolute_angle = angle_between_vectors(v1, v2)
        # determine the angle's sign depending on their plane's
        # choice of orientation. That choice is set by the camera
        # position, i. e. projection direction

        if np.dot(self.projection_direction(), np.cross(v1, v2)) > 0:
            return absolute_angle
        else:
            return -absolute_angle
Beispiel #5
0
    def viewing_angle_of_point(self, point):
        # as measured from the positive x-axis
        v1 = self.project(RIGHT)
        v2 = self.project(np.array(point) - self.get_source_point())
        absolute_angle = angle_between_vectors(v1, v2)
        # determine the angle's sign depending on their plane's
        # choice of orientation. That choice is set by the camera
        # position, i. e. projection direction

        if np.dot(self.projection_direction(), np.cross(v1, v2)) > 0:
            return absolute_angle
        else:
            return -absolute_angle
Beispiel #6
0
 def subdivide_sharp_curves(self, angle_threshold=30 * DEGREES, recurse=True):
     vmobs = [vm for vm in self.get_family(recurse) if vm.has_points()]
     for vmob in vmobs:
         new_points = []
         for tup in vmob.get_bezier_tuples():
             angle = angle_between_vectors(tup[1] - tup[0], tup[2] - tup[1])
             if angle > angle_threshold:
                 n = int(np.ceil(angle / angle_threshold))
                 alphas = np.linspace(0, 1, n + 1)
                 new_points.extend([
                     partial_quadratic_bezier_points(tup, a1, a2)
                     for a1, a2 in zip(alphas, alphas[1:])
                 ])
             else:
                 new_points.append(tup)
         vmob.set_points(np.vstack(new_points))
     return self
Beispiel #7
0
    def new_sector(self, r, dr, lower_angle, upper_angle):
        alpha = self.max_opacity * self.opacity_function(r)
        annular_sector = AnnularSector(inner_radius=r,
                                       outer_radius=r + dr,
                                       color=self.color,
                                       fill_opacity=alpha,
                                       start_angle=lower_angle,
                                       angle=upper_angle - lower_angle)
        # rotate (not project) it into the viewing plane
        rotation_matrix = z_to_vector(self.projection_direction())
        annular_sector.apply_matrix(rotation_matrix)
        # now rotate it inside that plane
        rotated_RIGHT = np.dot(RIGHT, rotation_matrix.T)
        projected_RIGHT = self.project(RIGHT)
        omega = angle_between_vectors(rotated_RIGHT, projected_RIGHT)
        annular_sector.rotate(omega, axis=self.projection_direction())
        annular_sector.move_arc_center_to(self.get_source_point())

        return annular_sector
Beispiel #8
0
    def new_sector(self, r, dr, lower_angle, upper_angle):
        alpha = self.max_opacity * self.opacity_function(r)
        annular_sector = AnnularSector(
            inner_radius=r,
            outer_radius=r + dr,
            color=self.color,
            fill_opacity=alpha,
            start_angle=lower_angle,
            angle=upper_angle - lower_angle
        )
        # rotate (not project) it into the viewing plane
        rotation_matrix = z_to_vector(self.projection_direction())
        annular_sector.apply_matrix(rotation_matrix)
        # now rotate it inside that plane
        rotated_RIGHT = np.dot(RIGHT, rotation_matrix.T)
        projected_RIGHT = self.project(RIGHT)
        omega = angle_between_vectors(rotated_RIGHT, projected_RIGHT)
        annular_sector.rotate(omega, axis=self.projection_direction())
        annular_sector.move_arc_center_to(self.get_source_point())

        return annular_sector
    def subdivide_sharp_curves(self,
                               angle_threshold=30 * DEGREES,
                               family=True):
        if family:
            vmobs = self.family_members_with_points()
        else:
            vmobs = [self] if self.has_points() else []

        for vmob in vmobs:
            new_points = []
            for tup in vmob.get_bezier_tuples():
                angle = angle_between_vectors(tup[1] - tup[0], tup[2] - tup[1])
                if angle > angle_threshold:
                    n = int(np.ceil(angle / angle_threshold))
                    alphas = np.linspace(0, 1, n + 1)
                    new_points.extend([
                        partial_bezier_points(tup, a1, a2)
                        for a1, a2 in zip(alphas, alphas[1:])
                    ])
                else:
                    new_points.append(tup)
            vmob.points = np.vstack(new_points)
        return self
Beispiel #10
0
 def rotate_to_match_vector(self, vector):
     #rotates a 2D plane such that it's normal matches a 3D vector
     rotation_axis = np.cross(vector, OUT)
     angle = angle_between_vectors(vector, OUT)
     self.rotate_in_place(-angle, axis=rotation_axis)