Ejemplo n.º 1
0
def nurbs_taper_sweep(profile,
                      taper,
                      point,
                      direction,
                      scale_base=SvTaperSweepSurface.UNIT):

    axis = LineEquation.from_direction_and_point(direction, point)

    taper_cpts = taper.get_control_points()
    taper_weights = taper.get_weights()

    taper_projections = axis.projection_of_points(taper_cpts)

    control_points = []
    weights = []

    if scale_base == SvTaperSweepSurface.TAPER:
        profile_t_min, profile_t_max = profile.get_u_bounds()
        profile_start = profile.evaluate(profile_t_min)
        profile_start_projection = axis.projection_of_point(profile_start)
        divisor = np.linalg.norm(profile_start - profile_start_projection)
    elif scale_base == SvTaperSweepSurface.PROFILE:
        taper_t_min, taper_t_max = taper.get_u_bounds()
        taper_start = taper.evaluate(taper_t_min)
        taper_start_projection = np.array(
            axis.projection_of_point(taper_start))
        divisor = np.linalg.norm(taper_start_projection - taper_start)
    else:
        divisor = 1.0

    profile_cpts = profile.get_control_points()
    n = len(profile_cpts)
    profile_knotvector = profile.get_knotvector()
    profile_weights = profile.get_weights()

    for taper_control_point, taper_projection, taper_weight in zip(
            taper_cpts, taper_projections, taper_weights):
        radius = np.linalg.norm(taper_control_point - taper_projection)
        if radius < 1e-8:
            parallel_points = np.empty((n, 3))
            parallel_points[:] = taper_projection
        else:
            parallel_points = place_profile(profile_cpts, taper_projection,
                                            radius / divisor)
        parallel_weights = profile_weights * taper_weight

        control_points.append(parallel_points)
        weights.append(parallel_weights)

    control_points = np.array(control_points)
    control_points -= point

    weights = np.array(weights)

    degree_u = taper.get_degree()
    degree_v = profile.get_degree()

    return SvNurbsSurface.build(taper.get_nurbs_implementation(), degree_u,
                                degree_v, taper.get_knotvector(),
                                profile_knotvector, control_points, weights)
Ejemplo n.º 2
0
 def __init__(self, profile, taper, point, direction):
     self.profile = profile
     self.taper = taper
     self.direction = direction
     self.point = point
     self.line = LineEquation.from_direction_and_point(direction, point)
     self.normal_delta = 0.001
    def make_section(self, apex, cone_dir, alpha, cone_gen, count,
                     plane_center, plane_dir, maxd):
        apex = Vector(apex)
        cone_dir = Vector(cone_dir)
        plane_dir = Vector(plane_dir)
        cone_dir2 = cone_dir.orthogonal()

        if self.cone_mode == 'ANGLE':
            cone_vector = rotate_vector_around_vector(cone_dir, cone_dir2,
                                                      alpha)
        else:
            cone_vector = Vector(cone_gen)
        theta = 2 * pi / count
        angle = 0

        plane = PlaneEquation.from_normal_and_point(plane_dir, plane_center)
        cone_ort_plane = PlaneEquation.from_normal_and_point(cone_dir, apex)

        def get_branch(v):
            return cone_ort_plane.side_of_point(v) > 0

        if plane.side_of_point(apex) == 0 or (
                plane_dir.cross(cone_dir)).length < 1e-10:

            def get_side(v):
                return True
        else:
            apex_projection = plane.projection_of_point(apex)
            apex_ort = apex_projection - apex
            cone_sagital_plane = PlaneEquation.from_point_and_two_vectors(
                apex, apex_ort, cone_dir)

            def get_side(v):
                return cone_sagital_plane.side_of_point(v) > 0

        vertices = []
        branch_mask = []
        side_mask = []
        breaks = []
        i = 0
        while angle < 2 * pi:
            cone_line = LineEquation.from_direction_and_point(
                cone_vector, apex)
            vertex = plane.intersect_with_line(cone_line, min_det=1e-10)
            if vertex is not None and (vertex - apex).length <= maxd:
                vertices.append(tuple(vertex))
                branch = get_branch(vertex)
                side = get_side(vertex)
                branch_mask.append(branch)
                side_mask.append(side)
                i += 1
            else:
                breaks.append(i)

            cone_vector = rotate_vector_around_vector(cone_vector, cone_dir,
                                                      theta)
            angle += theta

        return SectionData(vertices, branch_mask, side_mask, get_branch,
                           get_side, breaks)
Ejemplo n.º 4
0
 def evaluate(self, x, y, z):
     v = Vector([x, y, z])
     dv1 = (v - self.v1).length
     dv2 = (v - self.v2).length
     if dv1 > dv2:
         distance_to_nearest = dv2
         nearest_vert = self.v2
         another_vert = self.v1
     else:
         distance_to_nearest = dv1
         nearest_vert = self.v1
         another_vert = self.v2
     edge = another_vert - nearest_vert
     to_nearest = v - nearest_vert
     if to_nearest.length == 0:
         return 0
     angle = edge.angle(to_nearest)
     if angle > pi / 2:
         distance = distance_to_nearest
     else:
         distance = LineEquation.from_two_points(
             self.v1, self.v2).distance_to_point(v)
     if self.falloff is not None:
         value = self.falloff(np.array([distance]))[0]
         return value
     else:
         return distance
Ejemplo n.º 5
0
 def evaluate(self, x, y, z):
     v = Vector([x,y,z])
     dv1 = (v - self.v1).length
     dv2 = (v - self.v2).length
     if dv1 > dv2:
         distance_to_nearest = dv2
         nearest_vert = self.v2
         another_vert = self.v1
     else:
         distance_to_nearest = dv1
         nearest_vert = self.v1
         another_vert = self.v2
     edge = another_vert - nearest_vert
     to_nearest = v - nearest_vert
     if to_nearest.length == 0:
         return 0
     angle = edge.angle(to_nearest)
     if angle > pi/2:
         distance = distance_to_nearest
         vector = - to_nearest
     else:
         vector = LineEquation.from_two_points(self.v1, self.v2).projection_of_points(v)
         distance = vector.length
         vector = np.array(vector)
     if self.falloff is not None:
         return self.falloff(distance) * vector / distance
     else:
         return vector
Ejemplo n.º 6
0
 def evaluate_grid(self, xs, ys, zs):
     n = len(xs)
     vs = np.stack((xs, ys, zs)).T
     v1 = np.array(self.v1)
     v2 = np.array(self.v2)    
     dv1s = np.linalg.norm(vs - v1, axis=1)
     dv2s = np.linalg.norm(vs - v2, axis=1)
     v1_is_nearest = (dv1s < dv2s)
     v2_is_nearest = np.logical_not(v1_is_nearest)
     nearest_verts = np.empty_like(vs)
     other_verts = np.empty_like(vs)
     nearest_verts[v1_is_nearest] = v1
     nearest_verts[v2_is_nearest] = v2
     other_verts[v1_is_nearest] = v2
     other_verts[v2_is_nearest] = v1
     
     to_nearest = vs - nearest_verts
     
     edges = other_verts - nearest_verts
     dot = (to_nearest * edges).sum(axis=1)
     at_edge = (dot > 0)
     at_vertex = np.logical_not(at_edge)
     at_v1 = np.logical_and(at_vertex, v1_is_nearest)
     at_v2 = np.logical_and(at_vertex, v2_is_nearest)
     
     distances = np.empty((n,))
     distances[at_edge] = LineEquation.from_two_points(self.v1, self.v2).distance_to_points(vs[at_edge])
     distances[at_v1] = dv1s[at_v1]
     distances[at_v2] = dv2s[at_v2]
     
     if self.falloff is not None:
         distances = self.falloff(distances)
         return distances
     else:
         return distances
Ejemplo n.º 7
0
    def _faces_by_cylinder(self, topo, center, direction, radius):
        line = LineEquation.from_direction_and_point(direction, center)

        def condition(points):
            distances = line.distance_to_points(points)
            return distances < radius

        return topo.get_faces_by_location_mask(condition, self.include_partial)
Ejemplo n.º 8
0
 def __init__(self, curve, center, direction, radius, coefficient):
     self.curve = curve
     self.center = center
     self.direction = direction
     self.radius = radius
     self.coefficient = coefficient
     self.line = LineEquation.from_direction_and_point(direction, center)
     self.tangent_delta = 0.001
     self.__description__ = "{} casted to Cylinder".format(curve)
Ejemplo n.º 9
0
 def linear_search(segment):
     cpts = segment.get_control_points()
     start, end = cpts[0], cpts[-1]
     line = LineEquation.from_two_points(start, end)
     p = line.projection_of_point(src_point)
     t = locate_linear(start, end, p)
     if 0.0 <= t <= 1.0:
         u1, u2 = segment.get_u_bounds()
         u = (1 - t) * u1 + t * u2
         return u
     else:
         return None
Ejemplo n.º 10
0
 def intersect_line(segment):
     cpts = segment.get_control_points()
     p1, p2 = cpts[0], cpts[-1]
     line = LineEquation.from_two_points(p1, p2)
     p = plane.intersect_with_line(line)
     p = np.array(p)
     u = locate_p(p1, p2, p)
     u1, u2 = segment.get_u_bounds()
     if u >= 0 and u <= 1.0:
         v = (1 - u) * u1 + u * u2
         return v, p
     else:
         return None
Ejemplo n.º 11
0
    def evaluate_grid(self, xs, ys, zs):
        n = len(xs)
        vs = np.stack((xs, ys, zs)).T
        v1 = np.array(self.v1)
        v2 = np.array(self.v2)
        dv1s = np.linalg.norm(vs - v1, axis=1)
        dv2s = np.linalg.norm(vs - v2, axis=1)
        v1_is_nearest = (dv1s < dv2s)
        v2_is_nearest = np.logical_not(v1_is_nearest)
        nearest_verts = np.empty_like(vs)
        other_verts = np.empty_like(vs)
        nearest_verts[v1_is_nearest] = v1
        nearest_verts[v2_is_nearest] = v2
        other_verts[v1_is_nearest] = v2
        other_verts[v2_is_nearest] = v1

        to_nearest = vs - nearest_verts

        edges = other_verts - nearest_verts
        dot = (to_nearest * edges).sum(axis=1)
        at_edge = (dot > 0)
        at_vertex = np.logical_not(at_edge)
        at_v1 = np.logical_and(at_vertex, v1_is_nearest)
        at_v2 = np.logical_and(at_vertex, v2_is_nearest)

        line = LineEquation.from_two_points(self.v1, self.v2)

        vectors = np.empty((n, 3))
        vectors[at_edge] = line.projection_of_points(vs[at_edge]) - vs[at_edge]
        vectors[at_v1] = v1 - vs[at_v1]
        vectors[at_v2] = v2 - vs[at_v2]

        if self.falloff is not None:
            norms = np.linalg.norm(vectors, axis=1, keepdims=True)
            lens = self.falloff(norms)
            nonzero = (norms > 0)[:, 0]
            vectors[nonzero] = vectors[nonzero] / norms[nonzero][:, 0][
                np.newaxis].T
            R = (lens * vectors).T
            return R[0], R[1], R[2]
        else:
            R = vectors.T
            return R[0], R[1], R[2]
Ejemplo n.º 12
0
 def test_intersect_with_line(self):
     plane = PlaneEquation.from_coordinate_plane('XY')
     line = LineEquation.from_direction_and_point((1, 1, 1), (1, 1, 1))
     point = plane.intersect_with_line(line)
     self.assert_sverchok_data_equal(tuple(point), (0, 0, 0))
Ejemplo n.º 13
0
 def test_distance_to_point(self):
     line = LineEquation.from_coordinate_axis('Z')
     point = (0, 2, 0)
     self.assertEquals(line.distance_to_point(point), 2)
Ejemplo n.º 14
0
 def test_check_no(self):
     p1 = (1, 1, 1)
     p2 = (3, 3, 3)
     line = LineEquation.from_two_points(p1, p2)
     p3 = (5, 5, 6)
     self.assertFalse(line.check(p3))
Ejemplo n.º 15
0
 def test_from_two_points(self):
     p1 = (1, 1, 1)
     p2 = (3, 3, 3)
     line = LineEquation.from_two_points(p1, p2)
     self.assert_sverchok_data_equal(tuple(line.direction), (2, 2, 2))
     self.assert_sverchok_data_equal(tuple(line.point), p1)
Ejemplo n.º 16
0
 def test_distance_to_point(self):
     line = LineEquation.from_coordinate_axis('Z')
     point = (0, 2, 0)
     self.assertEquals(line.distance_to_point(point), 2)
Ejemplo n.º 17
0
 def test_check_no(self):
     p1 = (1, 1, 1)
     p2 = (3, 3, 3)
     line = LineEquation.from_two_points(p1, p2)
     p3 = (5, 5, 6)
     self.assertFalse(line.check(p3))
Ejemplo n.º 18
0
 def test_from_two_points(self):
     p1 = (1, 1, 1)
     p2 = (3, 3, 3)
     line = LineEquation.from_two_points(p1, p2)
     self.assert_sverchok_data_equal(tuple(line.direction), (2, 2, 2))
     self.assert_sverchok_data_equal(tuple(line.point), p1)
Ejemplo n.º 19
0
 def test_intersect_with_line(self):
     plane = PlaneEquation.from_coordinate_plane('XY')
     line = LineEquation.from_direction_and_point((1, 1, 1), (1, 1, 1))
     point = plane.intersect_with_line(line)
     self.assert_sverchok_data_equal(tuple(point), (0, 0, 0))
Ejemplo n.º 20
0
def intersect_curve_plane_ortho(curve,
                                plane,
                                init_samples=10,
                                ortho_samples=10,
                                tolerance=1e-3,
                                maxiter=50):
    """
    Find intersections of curve and a plane, by combination of orthogonal projections with tangent projections.
    inputs:
        * curve : SvCurve
        * plane : sverchok.utils.geom.PlaneEquation
        * init_samples: number of samples to subdivide the curve to; this defines the maximum possible number
            of solutions the method will return (the solution is searched at each segment).
        * ortho_samples: number of samples for ortho_project_curve method
        * tolerance: target tolerance
        * maxiter: maximum number of iterations
    outputs:
        list of intersection points

    dependencies: scipy
    """
    u_min, u_max = curve.get_u_bounds()
    u_range = np.linspace(u_min, u_max, num=init_samples)
    init_points = curve.evaluate_array(u_range)
    init_signs = plane.side_of_points(init_points)
    good_ranges = []
    for u1, u2, sign1, sign2 in zip(u_range, u_range[1:], init_signs,
                                    init_signs[1:]):
        if sign1 * sign2 < 0:
            good_ranges.append((u1, u2))
    if not good_ranges:
        return []

    solutions = []
    for u1, u2 in good_ranges:
        u0 = u1
        tangent = curve.tangent(u0)
        tangent /= np.linalg.norm(tangent)
        point = curve.evaluate(u0)
        line = LineEquation.from_direction_and_point(tangent, point)

        p = plane.intersect_with_line(line)
        if p is None:
            u0 = u2
            tangent = curve.tangent(u0)
            tangent /= np.linalg.norm(tangent)
            point = curve.evaluate(u0)
            line = LineEquation.from_direction_and_point(tangent, point)
            p = plane.intersect_with_line(line)
            if p is None:
                raise Exception("Can't find initial point for intersection")

        i = 0
        prev_prev_point = None
        prev_point = np.array(p)
        while True:
            i += 1
            if i > maxiter:
                raise Exception(
                    "Maximum number of iterations is exceeded; last step {} - {} = {}"
                    .format(prev_prev_point, point, step))

            ortho = ortho_project_curve(prev_point,
                                        curve,
                                        init_samples=ortho_samples)
            point = ortho.nearest
            step = np.linalg.norm(point - prev_point)
            if step < tolerance:
                debug("After ortho: Point {}, prev {}, iter {}".format(
                    point, prev_point, i))
                break

            prev_point = point
            tangent = curve.tangent(ortho.nearest_u)
            tangent /= np.linalg.norm(tangent)
            point = curve.evaluate(ortho.nearest_u)
            line = LineEquation.from_direction_and_point(tangent, point)
            point = plane.intersect_with_line(line)
            if point is None:
                raise Exception(
                    "Can't intersect a line {} with a plane {}".format(
                        line, point))
            point = np.array(point)
            step = np.linalg.norm(point - prev_point)
            if step < tolerance:
                debug("After raycast: Point {}, prev {}, iter {}".format(
                    point, prev_point, i))
                break

            prev_prev_point = prev_point
            prev_point = point

        solutions.append(point)

    return solutions
Ejemplo n.º 21
0
def intersect_curve_plane(curve,
                          plane,
                          init_samples=10,
                          ortho_samples=10,
                          tolerance=1e-3,
                          maxiter=50):
    u_min, u_max = curve.get_u_bounds()
    u_range = np.linspace(u_min, u_max, num=init_samples)
    init_points = curve.evaluate_array(u_range)
    init_signs = plane.side_of_points(init_points)
    good_ranges = []
    for u1, u2, sign1, sign2 in zip(u_range, u_range[1:], init_signs,
                                    init_signs[1:]):
        if sign1 * sign2 < 0:
            good_ranges.append((u1, u2))
    if not good_ranges:
        return []

    solutions = []
    for u1, u2 in good_ranges:
        u0 = u1
        tangent = curve.tangent(u0)
        tangent /= np.linalg.norm(tangent)
        point = curve.evaluate(u0)
        line = LineEquation.from_direction_and_point(tangent, point)

        p = plane.intersect_with_line(line)
        if p is None:
            u0 = u2
            tangent = curve.tangent(u0)
            tangent /= np.linalg.norm(tangent)
            point = curve.evaluate(u0)
            line = LineEquation.from_direction_and_point(tangent, point)
            p = plane.intersect_with_line(line)
            if p is None:
                raise Exception("Can't find initial point for intersection")

        i = 0
        prev_prev_point = None
        prev_point = np.array(p)
        while True:
            i += 1
            if i > maxiter:
                raise Exception(
                    "Maximum number of iterations is exceeded; last step {} - {} = {}"
                    .format(prev_prev_point, point, step))

            ortho = ortho_project_curve(prev_point,
                                        curve,
                                        init_samples=ortho_samples)
            point = ortho.nearest
            step = np.linalg.norm(point - prev_point)
            if step < tolerance:
                debug("After ortho: Point {}, prev {}, iter {}".format(
                    point, prev_point, i))
                break

            prev_point = point
            tangent = curve.tangent(ortho.nearest_u)
            tangent /= np.linalg.norm(tangent)
            point = curve.evaluate(ortho.nearest_u)
            line = LineEquation.from_direction_and_point(tangent, point)
            point = plane.intersect_with_line(line)
            if point is None:
                raise Exception(
                    "Can't intersect a line {} with a plane {}".format(
                        line, point))
            point = np.array(point)
            step = np.linalg.norm(point - prev_point)
            if step < tolerance:
                debug("After raycast: Point {}, prev {}, iter {}".format(
                    point, prev_point, i))
                break

            prev_prev_point = prev_point
            prev_point = point

        solutions.append(point)

    return solutions
Ejemplo n.º 22
0
 def _verts_by_cylinder(self, topo, center, direction, radius):
     line = LineEquation.from_direction_and_point(direction, center)
     condition = lambda v: line.distance_to_point(v) < radius
     return topo.get_vertices_by_location_mask(condition)