Esempio n. 1
0
    def get_inputs(self):
        factor1_s = self.inputs['Factor1'].sv_get()
        factor2_s = self.inputs['Factor2'].sv_get()

        factor1_s = ensure_nesting_level(factor1_s, 2)
        factor2_s = ensure_nesting_level(factor2_s, 2)

        if self.mode == 'TWO':
            curve1_s = self.inputs['Curve1'].sv_get()
            curve2_s = self.inputs['Curve2'].sv_get()
            if isinstance(curve1_s[0], SvCurve):
                curve1_s = [curve1_s]
            if isinstance(curve2_s[0], SvCurve):
                curve2_s = [curve2_s]
            for curve1s, curve2s, factor1s, factor2s in zip_long_repeat(curve1_s, curve2_s, factor1_s, factor2_s):
                for curve1, curve2, factor1, factor2 in zip_long_repeat(curve1s, curve2s, factor1s, factor2s):
                    yield curve1, curve2, factor1, factor2
        else:
            curves_s = self.inputs['Curves'].sv_get()
            if isinstance(curves_s[0], SvCurve):
                curves_s = [curves_s]
            for curves, factor1s, factor2s in zip_long_repeat(curves_s, factor1_s, factor2_s):
                factor1s = repeat_last_for_length(factor1s, len(curves))
                factor2s = repeat_last_for_length(factor2s, len(curves))
                for curve1, curve2, factor1, factor2 in zip(curves, curves[1:], factor1s, factor2s):
                    yield curve1, curve2, factor1, factor2
                if self.cyclic:
                    yield curves[-1], curves[0], factor1s[-1], factor2s[-1]
Esempio n. 2
0
    def generate_surface(self, solid, field, count, min_r, threshold,
                         field_min, field_max, mask, seed):
        counts = self.distribute_faces(solid.Faces, count)
        new_verts = []
        mask = repeat_last_for_length(mask, len(solid.Faces))
        counts = repeat_last_for_length(counts, len(solid.Faces))
        for face, ok, cnt in zip(solid.Faces, mask, counts):
            if not ok:
                continue

            def check(uv, vert):
                point = Base.Vector(vert)
                return face.isInside(point, self.get_tolerance(), True)

            surface = SvSolidFaceSurface(face)

            _, face_verts = populate_surface(surface,
                                             field,
                                             cnt,
                                             threshold,
                                             self.proportional,
                                             field_min,
                                             field_max,
                                             min_r,
                                             seed,
                                             predicate=check)
            new_verts.extend(face_verts)
        return new_verts
Esempio n. 3
0
    def process(self):
        if not any(socket.is_linked for socket in self.outputs):
            return

        surfaces_s = self.inputs['Surface'].sv_get()
        surfaces_s = ensure_nesting_level(surfaces_s, 2, data_types=(SvSurface,))
        src_point_s = self.inputs['UVPoints'].sv_get(default=[[]])
        src_point_s = ensure_nesting_level(src_point_s, 4)
        src_u_s = self.inputs['U'].sv_get()
        src_u_s = ensure_nesting_level(src_u_s, 3)
        src_v_s = self.inputs['V'].sv_get()
        src_v_s = ensure_nesting_level(src_v_s, 3)

        need_values = self.outputs['Curvature1'].is_linked or self.outputs['Curvature2'].is_linked
        need_directions = self.outputs['Dir1'].is_linked or self.outputs['Dir2'].is_linked
        need_gauss = self.outputs['Gauss'].is_linked
        need_mean = self.outputs['Mean'].is_linked
        need_matrix = self.outputs['Matrix'].is_linked

        c1_out = []
        c2_out = []
        dir1_out = []
        dir2_out = []
        mean_out = []
        gauss_out = []
        matrix_out = []
        for surfaces, src_points_i, src_u_i, src_v_i in zip_long_repeat(surfaces_s, src_point_s, src_u_s, src_v_s):
            new_curvatures = []
            for surface, src_points, src_us, src_vs in zip_long_repeat(surfaces, src_points_i, src_u_i, src_v_i):
                if self.input_mode == 'VERTICES':
                    us, vs = self.parse_input(src_points)
                else:
                    maxlen = max(len(src_us), len(src_vs))
                    src_us = repeat_last_for_length(src_us, maxlen)
                    src_vs = repeat_last_for_length(src_vs, maxlen)
                    us, vs = np.array(src_us), np.array(src_vs)
                data = surface.curvature_calculator(us, vs, order=self.order).calc(need_values, need_directions, need_gauss, need_mean, need_matrix)
                if need_values:
                    c1_out.append(data.principal_value_1.tolist())
                    c2_out.append(data.principal_value_2.tolist())
                if need_directions:
                    dir1_out.append(data.principal_direction_1.tolist())
                    dir2_out.append(data.principal_direction_2.tolist())
                if need_mean:
                    mean_out.append(data.mean.tolist())
                if need_gauss:
                    gauss_out.append(data.gauss.tolist())
                if need_matrix:
                    matrix_out.extend(data.matrix)

        self.outputs['Curvature1'].sv_set(c1_out)
        self.outputs['Curvature2'].sv_set(c2_out)
        self.outputs['Dir1'].sv_set(dir1_out)
        self.outputs['Dir2'].sv_set(dir2_out)
        self.outputs['Mean'].sv_set(mean_out)
        self.outputs['Gauss'].sv_set(gauss_out)
        self.outputs['Matrix'].sv_set(matrix_out)
Esempio n. 4
0
        def process(self):
            if not any(socket.is_linked for socket in self.outputs):
                return

            surfaces_s = self.inputs['Surface'].sv_get()
            surfaces_s = ensure_nesting_level(surfaces_s,
                                              2,
                                              data_types=(SvSurface, ))
            src_point_s = self.inputs['Source'].sv_get()
            src_point_s = ensure_nesting_level(src_point_s, 4)
            points_s = self.inputs['Point'].sv_get()
            points_s = ensure_nesting_level(points_s, 4)
            direction_s = self.inputs['Direction'].sv_get()
            direction_s = ensure_nesting_level(direction_s, 4)

            points_out = []
            points_uv_out = []
            for surfaces, src_points_i, points_i, directions_i in zip_long_repeat(
                    surfaces_s, src_point_s, points_s, direction_s):
                for surface, src_points, points, directions in zip_long_repeat(
                        surfaces, src_points_i, points_i, directions_i):
                    u_min = surface.get_u_min()
                    u_max = surface.get_u_max()
                    v_min = surface.get_v_min()
                    v_max = surface.get_v_max()

                    new_uv = []
                    new_u = []
                    new_v = []
                    new_points = []

                    if self.project_mode == 'PARALLEL':
                        directions = repeat_last_for_length(
                            directions, len(points))
                    else:  # CONIC
                        src_points = repeat_last_for_length(
                            src_points, len(points))
                        directions = (np.array(points) -
                                      np.array(src_points)).tolist()

                    result = raycast_surface(
                        surface,
                        points,
                        directions,
                        samples=self.samples,
                        precise=self.precise,
                        calc_points=self.outputs['Point'].is_linked,
                        method=self.method)

                    new_uv = result.uvs
                    new_points = result.points

                    points_out.append(new_points)
                    points_uv_out.append(new_uv)

            self.outputs['Point'].sv_set(points_out)
            self.outputs['UVPoint'].sv_set(points_uv_out)
Esempio n. 5
0
    def process(self):
        if not any(socket.is_linked for socket in self.outputs):
            return

        u_curves_s = self.inputs['CurvesU'].sv_get()
        v_curves_s = self.inputs['CurvesV'].sv_get()
        intersections_s = self.inputs['Intersections'].sv_get()

        if self.explicit_t_values:
            t1_s = self.inputs['T1'].sv_get()
            t2_s = self.inputs['T2'].sv_get()
        else:
            t1_s = [[[]]]
            t2_s = [[[]]]

        u_curves_s = ensure_nesting_level(u_curves_s, 2, data_types=(SvCurve,))
        v_curves_s = ensure_nesting_level(v_curves_s, 2, data_types=(SvCurve,))
        t1_s = ensure_nesting_level(t1_s, 3)
        t2_s = ensure_nesting_level(t2_s, 3)
        intersections_s = ensure_nesting_level(intersections_s, 4)

        surface_out = []
        for u_curves, v_curves, t1s, t2s, intersections in zip_long_repeat(u_curves_s, v_curves_s, t1_s, t2_s, intersections_s):
            u_curves = [SvNurbsCurve.to_nurbs(c) for c in u_curves]
            if any(c is None for c in u_curves):
                raise Exception("Some of U curves are not NURBS!")
            v_curves = [SvNurbsCurve.to_nurbs(c) for c in v_curves]
            if any(c is None for c in v_curves):
                raise Exception("Some of V curves are not NURBS!")

            if self.explicit_t_values:
                if len(t1s) < len(u_curves):
                    t1s = repeat_last_for_length(t1s, len(u_curves))
                elif len(t1s) > len(u_curves):
                    raise Exception(f"Number of items in T1 input {len(t1s)} > number of U-curves {len(u_curves)}")

                if len(t1s[0]) != len(v_curves):
                    raise Exception(f"Length of items in T1 input {len(t1s[0])} != number of V-curves {len(v_curves)}")

                if len(t2s) < len(v_curves):
                    t2s = repeat_last_for_length(t2s, len(v_curves))
                elif len(t2s) > len(v_curves):
                    raise Exception(f"Number of items in T2 input {len(t2s)} > number of V-curves {len(v_curves)}")

                if len(t2s[0]) != len(u_curves):
                    raise Exception(f"Length of items in T2 input {len(t2s[0])} != number of U-curves {len(u_curves)}")

            if self.explicit_t_values:
                kwargs = {'u_knots': np.array(t1s), 'v_knots': np.array(t2s)}
            else:
                kwargs = dict()
            _, _, _, surface = gordon_surface(u_curves, v_curves, intersections, metric=self.metric, knotvector_accuracy = self.knotvector_accuracy, **kwargs)
            surface_out.append(surface)

        self.outputs['Surface'].sv_set(surface_out)
Esempio n. 6
0
    def process(self):
        if not any(socket.is_linked for socket in self.outputs):
            return

        vertices_s = self.inputs['Vertices'].sv_get()
        edges_s = self.inputs['Edges'].sv_get(default=[[]])
        faces_s = self.inputs['Faces'].sv_get(default=[[]])
        masks_s = self.inputs['FaceMask'].sv_get(default=[[1]])
        face_data_s = self.inputs['FaceData'].sv_get(default=[[]])
        offset_s = self.inputs['Offset'].sv_get()

        verts_out = []
        edges_out = []
        faces_out = []
        face_data_out = []

        meshes = zip_long_repeat(vertices_s, edges_s, faces_s, offset_s,
                                 masks_s, face_data_s)
        for vertices, edges, faces, offset, masks, face_data in meshes:
            if isinstance(offset, (list, tuple)):
                offset = offset[0]
            masks = repeat_last_for_length(masks, len(faces))
            if face_data:
                face_data = repeat_last_for_length(face_data, len(faces))

            bm = bmesh_from_pydata(vertices,
                                   edges,
                                   faces,
                                   normal_update=True,
                                   markup_face_data=True)
            bm_faces = [face for mask, face in zip(masks, bm.faces[:]) if mask]

            bmesh.ops.poke(bm,
                           faces=bm_faces,
                           offset=offset,
                           center_mode=self.mode,
                           use_relative_offset=self.offset_relative)

            new_verts, new_edges, new_faces = pydata_from_bmesh(bm)
            if not face_data:
                new_face_data = []
            else:
                new_face_data = face_data_from_bmesh_faces(bm, face_data)
            bm.free()

            verts_out.append(new_verts)
            edges_out.append(new_edges)
            faces_out.append(new_faces)
            face_data_out.append(new_face_data)

        self.outputs['Vertices'].sv_set(verts_out)
        self.outputs['Edges'].sv_set(edges_out)
        self.outputs['Faces'].sv_set(faces_out)
        self.outputs['FaceData'].sv_set(face_data_out)
Esempio n. 7
0
    def get_inputs(self):
        factor1_s = self.inputs['Factor1'].sv_get()
        factor2_s = self.inputs['Factor2'].sv_get()
        params_s = self.inputs['Parameter'].sv_get()

        factor1_s = ensure_nesting_level(factor1_s, 2)
        factor2_s = ensure_nesting_level(factor2_s, 2)
        params_s = ensure_nesting_level(params_s, 2)

        if self.mode == 'TWO':
            curve1_s = self.inputs['Curve1'].sv_get()
            curve2_s = self.inputs['Curve2'].sv_get()
            curve1_s = ensure_nesting_level(curve1_s,
                                            2,
                                            data_types=(SvCurve, ))
            curve2_s = ensure_nesting_level(curve2_s,
                                            2,
                                            data_types=(SvCurve, ))

            results = []
            for inputs in zip_long_repeat(curve1_s, curve2_s, factor1_s,
                                          factor2_s, params_s):
                results.append(zip_long_repeat(*inputs))

            return results

        else:
            curves_s = self.inputs['Curves'].sv_get()
            curves_s = ensure_nesting_level(curves_s,
                                            2,
                                            data_types=(SvCurve, ))

            results = []
            for curves, factor1s, factor2s, params in zip_long_repeat(
                    curves_s, factor1_s, factor2_s, params_s):
                factor1s = repeat_last_for_length(factor1s, len(curves))
                factor2s = repeat_last_for_length(factor2s, len(curves))
                params = repeat_last_for_length(params, len(curves))

                item = list(zip(curves, curves[1:], factor1s, factor2s,
                                params))
                if self.cyclic:
                    item.append((curves[-1], curves[0], factor1s[-1],
                                 factor2s[-1], params[-1]))

                results.append(item)

            return results
Esempio n. 8
0
def get_selected_edges(use_mask, masks, bm_edges):
    if use_mask:
        if isinstance(masks, ndarray):
            mask_matched = numpy_full_list(masks, len(bm_edges)).tolist()
        else:
            mask_matched = repeat_last_for_length(masks, len(bm_edges))
        edge_id = bm_edges.layers.int.get("initial_index")
        return [edge for edge in bm_edges if mask_matched[edge[edge_id]]]

    return bm_edges
Esempio n. 9
0
    def process(self):
        if not any(socket.is_linked for socket in self.outputs):
            return

        vertices_s = self.inputs['Vertices'].sv_get()
        coeffs_s = self.inputs['Coefficient'].sv_get()
        fields_s = self.inputs['Field'].sv_get()
        iterations_s = self.inputs['Iterations'].sv_get()

        vertices_s = ensure_nesting_level(vertices_s, 4)
        coeffs_s = ensure_nesting_level(coeffs_s, 3)
        fields_s = ensure_nesting_level(fields_s,
                                        2,
                                        data_types=(SvVectorField, ))

        verts_out = []
        for fields, vertices_l, coeffs_l, iterations_l in zip_long_repeat(
                fields_s, vertices_s, coeffs_s, iterations_s):
            if not isinstance(iterations_l, (list, tuple)):
                iterations_l = [iterations_l]
            if not isinstance(fields, (list, tuple)):
                fields = [fields]

            for field, vertices, coeffs, iterations in zip_long_repeat(
                    fields, vertices_l, coeffs_l, iterations_l):

                if len(vertices) == 0:
                    new_verts = []
                elif len(vertices) == 1:
                    vertex = vertices[0]
                    coeff = coeffs[0]
                    for i in range(iterations):
                        vector = field.evaluate(*vertex)
                        vertex = (np.array(vertex) + coeff * vector).tolist()
                    new_verts = [vertex]
                else:
                    coeffs = repeat_last_for_length(coeffs, len(vertices))
                    vertices = np.array(vertices)
                    for i in range(iterations):
                        xs = vertices[:, 0]
                        ys = vertices[:, 1]
                        zs = vertices[:, 2]
                        new_xs, new_ys, new_zs = field.evaluate_grid(
                            xs, ys, zs)
                        new_vectors = np.dstack(
                            (new_xs[:], new_ys[:], new_zs[:]))
                        new_vectors = np.array(coeffs)[
                            np.newaxis].T * new_vectors[0]
                        vertices = vertices + new_vectors
                    new_verts = vertices if self.output_numpy else vertices.tolist(
                    )

                verts_out.append(new_verts)

        self.outputs['Vertices'].sv_set(verts_out)
Esempio n. 10
0
def extrude_edges_bmesh(vertices, edges, faces, edge_mask, face_data,
                        matrices):
    if not matrices:
        matrices = [Matrix()]
    if face_data:
        face_data_matched = repeat_last_for_length(face_data, len(faces))

    bm = bmesh_from_pydata(vertices,
                           edges,
                           faces,
                           markup_face_data=True,
                           markup_edge_data=True)
    if edge_mask:
        b_edges = bmesh_edges_from_edge_mask(bm, edge_mask)
    else:
        b_edges = bm.edges

    new_geom = bmesh.ops.extrude_edge_only(bm,
                                           edges=b_edges,
                                           use_select_history=False)['geom']

    extruded_verts = [v for v in new_geom if isinstance(v, bmesh.types.BMVert)]
    if len(matrices) == 1:
        bmesh.ops.transform(bm,
                            verts=extruded_verts,
                            matrix=matrices[0],
                            space=Matrix())
    else:
        for vertex, matrix in zip(
                *match_long_repeat([extruded_verts, matrices])):
            bmesh.ops.transform(bm,
                                verts=[vertex],
                                matrix=matrix,
                                space=Matrix())

    extruded_verts = [tuple(v.co) for v in extruded_verts]

    extruded_edges = [e for e in new_geom if isinstance(e, bmesh.types.BMEdge)]
    extruded_edges = [
        tuple(v.index for v in edge.verts) for edge in extruded_edges
    ]

    extruded_faces = [f for f in new_geom if isinstance(f, bmesh.types.BMFace)]
    extruded_faces = [[v.index for v in edge.verts] for edge in extruded_faces]

    if face_data:
        new_vertices, new_edges, new_faces, new_face_data = pydata_from_bmesh(
            bm, face_data_matched)
    else:
        new_vertices, new_edges, new_faces = pydata_from_bmesh(bm)
        new_face_data = []
    bm.free()
    return (new_vertices, new_edges, new_faces, extruded_verts, extruded_edges,
            extruded_faces, new_face_data)
Esempio n. 11
0
def flip_from_mask(mask, geom, reverse):
    """
    this mode expects a mask list with an element corresponding to each polygon
    """
    verts, edges, faces = geom
    mask_matched = repeat_last_for_length(mask, len(faces))
    b_faces = []
    for m, face in zip(mask_matched, faces):
        mask_val = bool(m) if not reverse else not bool(m)
        b_faces.append(face if mask_val else face[::-1])

    return verts, edges, b_faces
Esempio n. 12
0
def lloyd_relax(vertices, faces, iterations, mask=None, method=NORMAL, skip_boundary=True, use_axes={0,1,2}):
    """
    supported shape preservation methods: NONE, NORMAL, LINEAR, BVH
    """

    def do_iteration(bvh, bm):
        verts_out = []
        face_centers = np.array([face.calc_center_median() for face in bm.faces])
        for bm_vert in bm.verts:
            co = bm_vert.co
            if (skip_boundary and bm_vert.is_boundary) or (mask is not None and not mask[bm_vert.index]):
                new_vert = tuple(co)
            else:    
                normal = bm_vert.normal
                cs = np.array([face_centers[face.index] for face in bm_vert.link_faces])
                
                if method == NONE:
                    new_vert = cs.mean(axis=0)
                elif method == NORMAL:
                    median = mathutils.Vector(cs.mean(axis=0))
                    dv = median - co
                    dv = dv - dv.project(normal)
                    new_vert = co + dv
                elif method == LINEAR:
                    approx = linear_approximation(cs)
                    median = mathutils.Vector(approx.center)
                    plane = approx.most_similar_plane()
                    dist = plane.distance_to_point(bm_vert.co)
                    new_vert = median + plane.normal.normalized() * dist
                elif method == BVH:
                    median = mathutils.Vector(cs.mean(axis=0))
                    new_vert, normal, idx, dist = bvh.find_nearest(median)
                else:
                    raise Exception("Unsupported volume preservation method")
                
                new_vert = tuple(new_vert)
                new_vert = mask_axes(tuple(co), new_vert, use_axes)
                
            verts_out.append(new_vert)

        return verts_out

    if mask is not None:
        mask = repeat_last_for_length(mask, len(vertices))

    bvh = BVHTree.FromPolygons(vertices, faces)
    for i in range(iterations):
        bm = bmesh_from_pydata(vertices, [], faces, normal_update=True)
        vertices = do_iteration(bvh, bm)
        bm.free()

    return vertices
Esempio n. 13
0
    def generate_surface(self, solid, field, count, min_r, radius_field,
                         threshold, field_min, field_max, mask):
        counts = self.distribute_faces(solid.Faces, count)
        new_verts = []
        new_radiuses = []
        mask = repeat_last_for_length(mask, len(solid.Faces))
        counts = repeat_last_for_length(counts, len(solid.Faces))
        done_spheres = []
        for face, ok, cnt in zip(solid.Faces, mask, counts):
            if not ok:
                continue

            def check(uv, vert):
                point = Base.Vector(vert)
                return face.isInside(point, self.get_tolerance(), True)

            surface = SvSolidFaceSurface(face)

            _, face_verts, radiuses = populate_surface(
                surface,
                field,
                cnt,
                threshold,
                self.proportional,
                field_min,
                field_max,
                min_r=min_r,
                min_r_field=radius_field,
                random_radius=self.random_radius,
                avoid_spheres=done_spheres,
                seed=None,
                predicate=check)
            done_spheres.extend(list(zip(face_verts, radiuses)))
            new_verts.extend(face_verts)
            new_radiuses.extend(radiuses)
        return new_verts, new_radiuses
Esempio n. 14
0
    def process(self):

        if not (self.outputs['Vers'].is_linked
                and self.inputs['Vers'].is_linked):
            return

        vertices = Vector_generate(self.inputs['Vers'].sv_get(deepcopy=False))
        faces = self.inputs['Pols'].sv_get(deepcopy=False)
        offset = self.inputs['Offset'].sv_get(deepcopy=False)[0]
        nsides = self.inputs['N sides'].sv_get(deepcopy=False)[0][0]
        radius = self.inputs['Radius'].sv_get(deepcopy=False)[0]

        outv = []
        oute = []
        outo = []
        outn = []

        # for each object
        for verts_obj, faces_obj in zip(vertices, faces):
            offset_m = repeat_last_for_length(offset, len(faces_obj))
            radius_m = repeat_last_for_length(radius, len(faces_obj))
            verlen = set(range(len(verts_obj)))

            bm = bmesh_from_pydata(verts_obj, [],
                                   faces_obj,
                                   normal_update=True)
            result = self.Offset_pols(bm, offset_m, radius_m, nsides, verlen)
            outv.append(result[0])
            oute.append(result[1])
            outo.append(result[2])
            outn.append(result[3])

        self.outputs['Vers'].sv_set(outv)
        self.outputs['Edgs'].sv_set(oute)
        self.outputs['OutPols'].sv_set(outo)
        self.outputs['InPols'].sv_set(outn)
Esempio n. 15
0
    def process(self):
        if not any(socket.is_linked for socket in self.outputs):
            return

        vertices_s = self.inputs['Vertices'].sv_get(deepcopy=False)
        edges_s = self.inputs['Edges'].sv_get(default=[[]], deepcopy=False)
        faces_s = self.inputs['Faces'].sv_get(default=[[]], deepcopy=False)
        masks_s = self.inputs['FaceMask'].sv_get(default=[[1]], deepcopy=False)
        factors_s = self.inputs['Factor'].sv_get(deepcopy=False)
        iterations_s = self.inputs['Iterations'].sv_get(deepcopy=False)

        verts_out = []
        edges_out = []
        faces_out = []

        meshes = match_long_repeat(
            [vertices_s, edges_s, faces_s, masks_s, factors_s, iterations_s])
        for vertices, edges, faces, masks, factor, iterations in zip(*meshes):
            if isinstance(iterations, (list, tuple)):
                iterations = iterations[0]
            if isinstance(factor, (list, tuple)):
                factor = factor[0]

            masks_matched = repeat_last_for_length(masks, len(faces))

            bm = bmesh_from_pydata(vertices, edges, faces, normal_update=True)
            bm_faces = [
                face for mask, face in zip(masks_matched, bm.faces[:]) if mask
            ]

            bmesh.ops.planar_faces(bm,
                                   faces=bm_faces,
                                   iterations=iterations,
                                   factor=factor)

            new_verts, new_edges, new_faces = pydata_from_bmesh(bm)
            bm.free()

            verts_out.append(new_verts)
            edges_out.append(new_edges)
            faces_out.append(new_faces)

        self.outputs['Vertices'].sv_set(verts_out)
        self.outputs['Edges'].sv_set(edges_out)
        self.outputs['Faces'].sv_set(faces_out)
Esempio n. 16
0
    def process(self):
        if not (self.inputs['Vertices'].is_linked and self.inputs['Polygons'].is_linked):
            return
        if not (any(self.outputs[name].is_linked for name in ['Vertices', 'Edges', 'Polygons'])):
            return

        vertices_s = self.inputs['Vertices'].sv_get(default=[[]], deepcopy=False)
        edges_s = self.inputs['Edges'].sv_get(default=[[]], deepcopy=False)
        faces_s = self.inputs['Polygons'].sv_get(default=[[]], deepcopy=False)
        mask_s = self.inputs['Mask'].sv_get(default=[[True]], deepcopy=False)

        result_vertices = []
        result_edges = []
        result_faces = []

        meshes = match_long_repeat([vertices_s, edges_s, faces_s, mask_s])

        for vertices, edges, faces, mask in zip(*meshes):

            bm = bmesh_from_pydata(vertices, edges, faces, normal_update=True)
            mask_matched = repeat_last_for_length(mask, len(faces))

            b_faces = []
            for m, face in zip(mask_matched, bm.faces):
                if m:
                    b_faces.append(face)

            bmesh.ops.recalc_face_normals(bm, faces=b_faces)
            new_vertices, new_edges, new_faces = pydata_from_bmesh(bm)
            bm.free()

            if self.invert:
                new_faces = [list(reversed(face)) for face in new_faces]

            result_vertices.append(new_vertices)
            result_edges.append(new_edges)
            result_faces.append(new_faces)

        if self.outputs['Vertices'].is_linked:
            self.outputs['Vertices'].sv_set(result_vertices)
        if self.outputs['Edges'].is_linked:
            self.outputs['Edges'].sv_set(result_edges)
        if self.outputs['Polygons'].is_linked:
            self.outputs['Polygons'].sv_set(result_faces)
Esempio n. 17
0
    def process(self):
        if not any(socket.is_linked for socket in self.outputs):
            return

        verts_in = self.inputs['Vertices'].sv_get()
        faces_in = self.inputs['Faces'].sv_get()
        add_verts_in = self.inputs['AddVerts'].sv_get()
        if self.mode == 'INDEX':
            face_idxs_in = self.inputs['FaceIndex'].sv_get()
        else:
            face_idxs_in = [[[]]]

        tolerance = 10**(-self.accuracy)

        verts_out = []
        edges_out = []
        faces_out = []
        for verts, faces, add_verts, face_idxs in zip_long_repeat(
                verts_in, faces_in, add_verts_in, face_idxs_in):
            if self.mode == 'INDEX':
                face_idxs = repeat_last_for_length(face_idxs, len(add_verts))
            else:
                face_idxs = find_nearest_idxs(verts, faces, add_verts)

            add_verts_by_face = defaultdict(list)
            for add_vert, idx in zip(add_verts, face_idxs):
                add_verts_by_face[idx].append(add_vert)

            new_verts, new_edges, new_faces = mesh_insert_verts(
                verts,
                faces,
                add_verts_by_face,
                epsilon=tolerance,
                exclude_boundary=self.exclude_boundary,
                preserve_shape=self.preserve_shape,
                recalc_normals=self.recalc_normals)

            verts_out.append(new_verts)
            edges_out.append(new_edges)
            faces_out.append(new_faces)

        self.outputs['Vertices'].sv_set(verts_out)
        self.outputs['Edges'].sv_set(edges_out)
        self.outputs['Faces'].sv_set(faces_out)
Esempio n. 18
0
 def make_solid(self, solid, thickness, mask):
     if not solid.isValid():
         raise Exception("Solid is not valid")
     if self.mask_usage == 'REMOVE':
         mask = [not c for c in mask]
     if all(mask):
         self.info(
             "No faces are selected to be removed; the node will operate as `Offset' operation"
         )
     if not any(mask):
         raise Exception("Invalid faces mask: all faces are to be removed")
     mask = repeat_last_for_length(mask, len(solid.Faces))
     faces = [face for c, face in zip(mask, solid.Faces) if not c]
     try:
         shape = solid.makeThickness(faces, thickness, self.tolerance)
         return shape
     except Part.OCCError as e:
         raise Exception(
             f"FreeCAD API method failed: {e}. Incorrect faces mask?")
Esempio n. 19
0
def subdiv_mesh_to_quads_np(vertices, polygons,
                            iterations, normal_displace,
                            random_f, random_normal, random_seed,
                            smooth_f,
                            vert_data, face_data,
                            output_edges=True,
                            output_vert_map=True):
    np.random.seed(int(random_seed))
    np_verts = vertices if isinstance(vertices, np.ndarray) else np.array(vertices)
    if output_vert_map:
        vert_map = np.zeros(np_verts.shape[0], dtype=int)
    else:
        vert_map = np.array([], dtype=int)

    matched_vert_data = dict()
    if vert_data:
        for key in vert_data:
            matched_vert_data[key] = numpy_full_list(vert_data[key], np_verts.shape[0])

    matched_face_data = dict()
    if face_data:
        for key in face_data:
            data = face_data[key]
            if isinstance(data, np.ndarray):
                matched_face_data[key] = numpy_full_list(data, len(polygons))
            else:
                matched_face_data[key] = repeat_last_for_length(data, len(polygons))


    flat_pols, pol_len, pol_end = np_pols(polygons)
    edges, unique_edges, eds_inverse_idx = pols_to_edges(flat_pols, pol_len, pol_end)
    return subdiv_mesh_to_quads_inner(
        np_verts, polygons,
        pol_len, pol_end,
        edges, unique_edges, eds_inverse_idx,
        iterations, normal_displace,
        random_f, random_normal,
        smooth_f,
        vert_map, matched_vert_data, matched_face_data,
        output_edges=output_edges,
        max_iterations=iterations)
Esempio n. 20
0
def by_sphere(vertices, centers, radius):

    if len(centers) == 1:
        center = centers[0]
        out_verts_mask = np.linalg.norm(
            np.array(vertices) - np.array(center)[np.newaxis, :],
            axis=1) <= radius[0]
    else:
        # build KDTree
        tree = kdtree.KDTree(len(centers))
        for i, v in enumerate(centers):
            tree.insert(v, i)
        tree.balance()

        out_verts_mask = []
        rad = repeat_last_for_length(radius, len(centers))
        for vertex in vertices:
            _, idx, rho = tree.find(vertex)
            mask = rho <= rad[idx]
            out_verts_mask.append(mask)
    return out_verts_mask
Esempio n. 21
0
    def process(self):
        if not any(socket.is_linked for socket in self.outputs):
            return

        size_x_s = self.inputs['Size X'].sv_get()
        size_y_s = self.inputs['Size Y'].sv_get()
        radius_s = self.inputs['Radius'].sv_get()

        size_x_s = ensure_nesting_level(size_x_s, 2)
        size_y_s = ensure_nesting_level(size_y_s, 2)
        radius_nesting = get_data_nesting_level(radius_s)
        if radius_nesting < 2 or radius_nesting > 3:
            raise TypeError(
                f"Radius input can only handle nesting level 2 or 3, got {radius_nesting}"
            )
        radius_per_corner = (radius_nesting == 3)
        #if radius_nesting == 2:
        #radius_s = [[radiuses] for radiuses in radius_s]
        #radius_s = [[[r] for r in radiuses] for radiuses in radius_s]

        curves_out = []
        centers_out = []

        for size_x_i, size_y_i, radius_i in zip_long_repeat(
                size_x_s, size_y_s, radius_s):
            new_curves = []
            new_centers = []
            for size_x, size_y, radiuses in zip_long_repeat(
                    size_x_i, size_y_i, radius_i):
                if not radius_per_corner:
                    radiuses = [radiuses]
                radiuses = repeat_last_for_length(radiuses, 4)
                centers, curve = self.make_curve(size_x, size_y, radiuses)
                new_curves.append(curve)
                new_centers.append([tuple(c) for c in centers])
            curves_out.append(new_curves)
            centers_out.extend(new_centers)

        self.outputs['Curve'].sv_set(curves_out)
        self.outputs['Centers'].sv_set(centers_out)
Esempio n. 22
0
    def process(self):
        if not any(socket.is_linked for socket in self.outputs):
            return

        verts_s = self.inputs['Vertices'].sv_get()
        radius_s = self.inputs['Radius'].sv_get()

        verts_s = ensure_nesting_level(verts_s, 3)
        radius_s = ensure_nesting_level(radius_s, 2)

        curves_out = []
        centers_out = []
        for vertices, radiuses in zip_long_repeat(verts_s, radius_s):
            if len(vertices) < 3:
                raise Exception("At least three vertices are required to make a fillet")
            radiuses = repeat_last_for_length(radiuses, len(vertices))
            curve, centers = self.make_curve(vertices, radiuses)
            curves_out.append(curve)
            centers_out.append(centers)
        
        self.outputs['Curve'].sv_set(curves_out)
        self.outputs['Centers'].sv_set(centers_out)
Esempio n. 23
0
    def process(self):
        if not any(socket.is_linked for socket in self.outputs):
            return

        vertices_s = self.inputs['Vertices'].sv_get()
        weights_s = self.inputs['Weights'].sv_get(default=[[[None]]])
        degree_s = self.inputs['Degree'].sv_get()
        points_cnt_s = self.inputs['PointsCnt'].sv_get()
        smoothing_s = self.inputs['Smoothing'].sv_get()

        input_level = get_data_nesting_level(vertices_s)
        vertices_s = ensure_nesting_level(vertices_s, 4)
        degree_s = ensure_nesting_level(degree_s, 2)
        points_cnt_s = ensure_nesting_level(points_cnt_s, 2)
        smoothing_s = ensure_nesting_level(smoothing_s, 2)
        has_weights = self.inputs['Weights'].is_linked
        if has_weights:
            weights_s = ensure_nesting_level(weights_s, 3)

        nested_output = input_level > 3

        curves_out = []
        points_out = []
        knots_out = []
        for params in zip_long_repeat(vertices_s, weights_s, degree_s,
                                      points_cnt_s, smoothing_s):
            new_curves = []
            new_points = []
            new_knots = []
            for vertices, weights, degree, points_cnt, smoothing in zip_long_repeat(
                    *params):

                if self.implementation == 'GEOMDL':
                    kwargs = dict(centripetal=self.centripetal)
                    if self.has_points_cnt:
                        kwargs['ctrlpts_size'] = points_cnt

                    curve = fitting.approximate_curve(vertices, degree,
                                                      **kwargs)
                    control_points = curve.ctrlpts
                    knotvector = curve.knotvector
                    curve = SvGeomdlCurve(curve)
                else:  # SCIPY:
                    points = np.array(vertices)
                    if has_weights:
                        weights = repeat_last_for_length(
                            weights, len(vertices))
                    else:
                        weights = None
                    if not self.has_smoothing:
                        smoothing = None

                    if self.is_cyclic:
                        if self.auto_cyclic:
                            dv = np.linalg.norm(points[0] - points[-1])
                            is_cyclic = dv <= self.cyclic_threshold
                            self.info("Dv %s, threshold %s => is_cyclic %s",
                                      dv, self.cyclic_threshold, is_cyclic)
                        else:
                            is_cyclic = True
                    else:
                        is_cyclic = False

                    curve = scipy_nurbs_approximate(
                        points,
                        weights=weights,
                        metric=self.metric,
                        degree=degree,
                        filter_doubles=None
                        if not self.remove_doubles else self.threshold,
                        smoothing=smoothing,
                        is_cyclic=is_cyclic)

                    control_points = curve.get_control_points().tolist()
                    knotvector = curve.get_knotvector().tolist()

                new_curves.append(curve)
                new_points.append(control_points)
                new_knots.append(knotvector)

            if nested_output:
                curves_out.append(new_curves)
                points_out.append(new_points)
                knots_out.append(new_knots)
            else:
                curves_out.extend(new_curves)
                points_out.extend(new_points)
                knots_out.extend(new_knots)

        self.outputs['Curve'].sv_set(curves_out)
        self.outputs['ControlPoints'].sv_set(points_out)
        self.outputs['Knots'].sv_set(knots_out)
Esempio n. 24
0
    def process(self):
        inputs, outputs = self.inputs, self.outputs

        if self.dont_process():
            return

        result_vertices, result_edges, result_faces, result_face_data = [], [], [], []
        r_inner_vertices, r_inner_edges, r_inner_faces = [], [], []
        r_split_vertices, r_split_edges, r_split_faces = [], [], []

        use_mask = inputs['EdgeMask'].is_linked
        show_new = self.show_new and any(s.is_linked for s in outputs[4:7])
        show_old = self.show_old and any(s.is_linked for s in outputs[7:])
        use_face_data = inputs['FaceData'].is_linked and outputs['FaceData'].is_linked
        output_numpy = any(self.out_np)

        meshes = self.get_data()

        for vertices, edges, faces, face_data, masks, cuts, smooth, fractal, along_normal, seed in zip(*meshes):
            if cuts < 1:
                result_vertices.append(vertices)
                result_edges.append(edges)
                result_faces.append(faces)
                result_face_data.append(face_data)
                r_inner_vertices.append(vertices)
                r_inner_edges.append(edges)
                r_inner_faces.append(faces)
                r_split_vertices.append(vertices)
                r_split_edges.append(edges)
                r_split_faces.append(faces)
                continue

            if use_face_data and len(face_data) > 0:
                if isinstance(face_data, ndarray):
                    face_data_matched = numpy_full_list(face_data, len(faces)).tolist()
                else:
                    face_data_matched = repeat_last_for_length(face_data, len(faces))
            else:
                face_data_matched =[]

            bm = bmesh_from_pydata(
                vertices, edges, faces,
                markup_face_data=use_face_data,
                markup_edge_data=use_mask,
                normal_update=True)

            selected_edges = get_selected_edges(use_mask, masks, bm.edges)

            geom = subdivide_edges(
                bm,
                edges=selected_edges,
                smooth=smooth,
                smooth_falloff=self.falloff_type,
                fractal=fractal,
                along_normal=along_normal,
                cuts=cuts,
                seed=seed,
                quad_corner_type=self.corner_type,
                use_grid_fill=self.grid_fill,
                use_single_edge=self.single_edge,
                use_only_quads=self.only_quads,
                use_smooth_even=self.smooth_even)

            if output_numpy:
                new_verts, new_edges, new_faces, new_face_data = numpy_data_from_bmesh(bm, self.out_np, face_data_matched)
            else:
                if use_face_data and len(face_data) > 0:
                    new_verts, new_edges, new_faces, new_face_data = pydata_from_bmesh(bm, face_data_matched)
                else:
                    new_verts, new_edges, new_faces = pydata_from_bmesh(bm)
                    new_face_data = []

            result_vertices.append(new_verts)
            result_edges.append(new_edges)
            result_faces.append(new_faces)
            result_face_data.append(new_face_data)

            if show_new:
                inner_verts, inner_edges, inner_faces = get_partial_result_pydata(geom['geom_inner'])
                r_inner_vertices.append(inner_verts)
                r_inner_edges.append(inner_edges)
                r_inner_faces.append(inner_faces)

            if show_old:
                split_verts, split_edges, split_faces = get_partial_result_pydata(geom['geom_split'])
                r_split_vertices.append(split_verts)
                r_split_edges.append(split_edges)
                r_split_faces.append(split_faces)

            bm.free()


        outputs['Vertices'].sv_set(result_vertices)
        outputs['Edges'].sv_set(result_edges)
        outputs['Faces'].sv_set(result_faces)
        outputs['FaceData'].sv_set(result_face_data)

        outputs['NewVertices'].sv_set(r_inner_vertices)
        outputs['NewEdges'].sv_set(r_inner_edges)
        outputs['NewFaces'].sv_set(r_inner_faces)

        outputs['OldVertices'].sv_set(r_split_vertices)
        outputs['OldEdges'].sv_set(r_split_edges)
        outputs['OldFaces'].sv_set(r_split_faces)
Esempio n. 25
0
        def process(self):
            if not any(socket.is_linked for socket in self.outputs):
                return

            surfaces_s = self.inputs['Surface'].sv_get()
            surfaces_s = ensure_nesting_level(surfaces_s,
                                              2,
                                              data_types=(SvSurface, ))
            src_point_s = self.inputs['Source'].sv_get()
            src_point_s = ensure_nesting_level(src_point_s, 4)
            points_s = self.inputs['Point'].sv_get()
            points_s = ensure_nesting_level(points_s, 4)
            direction_s = self.inputs['Direction'].sv_get()
            direction_s = ensure_nesting_level(direction_s, 4)

            points_out = []
            points_uv_out = []
            for surfaces, src_points_i, points_i, directions_i in zip_long_repeat(
                    surfaces_s, src_point_s, points_s, direction_s):
                for surface, src_points, points, directions in zip_long_repeat(
                        surfaces, src_points_i, points_i, directions_i):
                    u_min = surface.get_u_min()
                    u_max = surface.get_u_max()
                    v_min = surface.get_v_min()
                    v_max = surface.get_v_max()

                    new_uv = []
                    new_u = []
                    new_v = []
                    new_points = []

                    if self.project_mode == 'PARALLEL':
                        directions = repeat_last_for_length(
                            directions, len(points))
                    else:  # CONIC
                        src_points = repeat_last_for_length(
                            src_points, len(points))
                        directions = (np.array(points) -
                                      np.array(src_points)).tolist()

                    init_us, init_vs, init_ts, init_points = init_guess(
                        surface, points, directions, samples=self.samples)
                    for point, direction, init_u, init_v, init_t, init_point in zip(
                            points, directions, init_us, init_vs, init_ts,
                            init_points):
                        if self.precise:
                            direction = np.array(direction)
                            direction = direction / np.linalg.norm(direction)
                            result = root(goal(surface, np.array(point),
                                               direction),
                                          x0=np.array([init_u, init_v,
                                                       init_t]),
                                          method=self.method)
                            if not result.success:
                                raise Exception(
                                    "Can't find the projection for {}: {}".
                                    format(point, result.message))
                            u0, v0, t0 = result.x
                        else:
                            u0, v0 = init_u, init_v
                            new_points.append(init_point)

                        new_uv.append((u0, v0, 0))
                        new_u.append(u0)
                        new_v.append(v0)

                    if self.precise and self.outputs['Point'].is_linked:
                        new_points = surface.evaluate_array(
                            np.array(new_u), np.array(new_v)).tolist()

                    points_out.append(new_points)
                    points_uv_out.append(new_uv)

            self.outputs['Point'].sv_set(points_out)
            self.outputs['UVPoint'].sv_set(points_uv_out)
Esempio n. 26
0
    def process(self):

        inputs = self.inputs
        outputs = self.outputs

        if not (inputs['Vertices'].is_linked and inputs['Polygons'].is_linked):
            return
        if not any(socket.is_linked for socket in outputs):
            return

        need_mask_out = 'Mask' in outputs and outputs['Mask'].is_linked

        vector_in = self.scale_socket_type

        vertices_s = inputs['Vertices'].sv_get(deepcopy=False)
        edges_s = inputs['Edges'].sv_get(default=[[]], deepcopy=False)
        faces_s = inputs['Polygons'].sv_get(default=[[]], deepcopy=False)
        masks_s = inputs['Mask'].sv_get(default=[[1]], deepcopy=False)
        heights_s = inputs['Height'].sv_get(deepcopy=False)
        scales_s = inputs['Scale'].sv_get(deepcopy=False)
        if 'Matrix' in inputs:
            matrixes_s = inputs['Matrix'].sv_get(default=[[Matrix()]],
                                                 deepcopy=False)
        else:
            matrixes_s = [[Matrix()]]
        if 'FaceData' in inputs:
            face_data_s = self.inputs['FaceData'].sv_get(default=[[]],
                                                         deepcopy=False)
        else:
            face_data_s = [[]]

        if type(matrixes_s[0]) == Matrix:
            matrixes_s = [matrixes_s]

        linked_extruded_polygons = outputs['ExtrudedPolys'].is_linked
        linked_other_polygons = outputs['OtherPolys'].is_linked

        result_vertices = []
        result_edges = []
        result_faces = []
        result_extruded_faces = []
        result_other_faces = []
        result_mask = []
        result_face_data = []

        meshes = match_long_repeat([
            vertices_s, edges_s, faces_s, masks_s, heights_s, scales_s,
            matrixes_s, face_data_s
        ])

        for vertices, edges, faces, masks_, heights_, scales_, matrixes_, face_data in zip(
                *meshes):

            new_extruded_faces = []
            new_extruded_faces_append = new_extruded_faces.append
            heights, scales, matrixes, masks = make_repeaters(
                [heights_, scales_, matrixes_, masks_])
            if face_data:
                face_data_matched = repeat_last_for_length(
                    face_data, len(faces))

            bm = bmesh_from_pydata(vertices,
                                   edges,
                                   faces,
                                   markup_face_data=True,
                                   normal_update=True)
            mask_layer = bm.faces.layers.int.new('mask')
            bm.faces.ensure_lookup_table()
            fill_faces_layer(bm, masks, 'mask', int, OUT)

            if self.mask_mode == 'NOEXTRUDE':
                faces_to_extrude = [
                    face for face, mask in zip(bm.faces, masks) if mask
                ]
            else:
                faces_to_extrude = bm.faces

            extruded_faces = bmesh.ops.extrude_discrete_faces(
                bm, faces=faces_to_extrude)['faces']

            if self.mask_mode == 'NOEXTRUDE':
                extruded_face_items = zip(extruded_faces, heights, scales,
                                          matrixes)
            else:
                extruded_face_items = [
                    (face, height, scale, matrix)
                    for (face, mask, height, scale, matrix) in zip(
                        extruded_faces, masks, heights, scales, matrixes)
                    if mask
                ]

            for face, height, scale, matrix in extruded_face_items:

                vec = scale if vector_in else (scale, scale, scale)

                # preparing matrix
                normal = face.normal
                if normal[0] == 0 and normal[1] == 0:
                    m_r = Matrix() if normal[2] >= 0 else Matrix.Rotation(
                        pi, 4, 'X')
                else:
                    z_axis = normal
                    x_axis = (Vector(
                        (z_axis[1] * -1, z_axis[0], 0))).normalized()
                    y_axis = (z_axis.cross(x_axis)).normalized()
                    m_r = Matrix(list([*zip(x_axis[:], y_axis[:], z_axis[:])
                                       ])).to_4x4()

                dr = face.normal * height
                center = face.calc_center_median()
                translation = Matrix.Translation(center)
                space = (translation @ m_r).inverted()

                if self.extrude_mode == 'NORMAL':
                    # inset, scale and push operations
                    bmesh.ops.scale(bm, vec=vec, space=space, verts=face.verts)
                    bmesh.ops.translate(bm, verts=face.verts, vec=dr)
                else:
                    bmesh.ops.transform(bm,
                                        matrix=matrix,
                                        space=space,
                                        verts=face.verts)

                if linked_extruded_polygons or linked_other_polygons:
                    new_extruded_faces_append([v.index for v in face.verts])

            if face_data:
                new_vertices, new_edges, new_faces, new_face_data = pydata_from_bmesh(
                    bm, face_data_matched)
            else:
                new_vertices, new_edges, new_faces = pydata_from_bmesh(bm)
                new_face_data = []

            new_other_faces = [
                f for f in new_faces if f not in new_extruded_faces
            ] if linked_other_polygons else []
            if need_mask_out:
                new_mask = self.get_out_mask(bm, extruded_faces)
                result_mask.append(new_mask)

            bm.free()

            result_vertices.append(new_vertices)
            result_edges.append(new_edges)
            result_faces.append(new_faces)
            result_extruded_faces.append(new_extruded_faces)
            result_other_faces.append(new_other_faces)
            result_face_data.append(new_face_data)

        outputs['Vertices'].sv_set(result_vertices)
        outputs['Edges'].sv_set(result_edges)
        outputs['Polygons'].sv_set(result_faces)
        outputs['ExtrudedPolys'].sv_set(result_extruded_faces)
        outputs['OtherPolys'].sv_set(result_other_faces)
        if need_mask_out:
            outputs['Mask'].sv_set(result_mask)
        if 'FaceData' in outputs:
            outputs['FaceData'].sv_set(result_face_data)
Esempio n. 27
0
    def process(self):
        # inputs
        if not self.inputs['Vertices'].is_linked:
            return

        vertices_s = self.inputs['Vertices'].sv_get(deepcopy=False)
        edges_s = self.inputs['Edges'].sv_get(default=[[]], deepcopy=False)
        faces_s = self.inputs['Polygons'].sv_get(default=[[]], deepcopy=False)
        masks_s = self.inputs['Mask'].sv_get(default=[[1]], deepcopy=False)
        if self.transform_mode == "Matrix":
            matrices_s = [
                self.inputs['Matrices'].sv_get(default=[Matrix()],
                                               deepcopy=False)
            ]
            heights_s = [0.0]
            scales_s = [1.0]
        else:
            matrices_s = [[]]
            heights_s = self.inputs['Height'].sv_get(deepcopy=False)
            scales_s = self.inputs['Scale'].sv_get(deepcopy=False)
        if 'FaceData' in self.inputs:
            face_data_s = self.inputs['FaceData'].sv_get(default=[[]],
                                                         deepcopy=False)
        else:
            face_data_s = [[]]

        need_mask_out = 'Mask' in self.outputs and self.outputs[
            'Mask'].is_linked

        result_vertices = []
        result_edges = []
        result_faces = []
        result_ext_vertices = []
        result_ext_edges = []
        result_ext_faces = []
        result_face_data = []
        result_mask = []

        meshes = match_long_repeat([
            vertices_s, edges_s, faces_s, masks_s, matrices_s, heights_s,
            scales_s, face_data_s
        ])

        for vertices, edges, faces, masks, matrix_per_iteration, height_per_iteration, scale_per_iteration, face_data in zip(
                *meshes):
            if self.transform_mode == "Matrix":
                if not matrix_per_iteration:
                    matrix_per_iteration = [Matrix()]

            if self.multiple:
                if self.transform_mode == "Matrix":
                    n_iterations = len(matrix_per_iteration)
                else:
                    n_iterations = max(len(height_per_iteration),
                                       len(scale_per_iteration))
                    height_per_iteration_matched = repeat_last_for_length(
                        height_per_iteration, n_iterations)
                    scale_per_iteration_matched = repeat_last_for_length(
                        scale_per_iteration, n_iterations)
            else:
                n_iterations = 1
                matrix_per_iteration = [matrix_per_iteration]

            mask_matched = repeat_last_for_length(masks, len(faces))
            if face_data:
                face_data_matched = repeat_last_for_length(
                    face_data, len(faces))

            bm = bmesh_from_pydata(vertices,
                                   edges,
                                   faces,
                                   normal_update=True,
                                   markup_face_data=True)
            mask_layer = bm.faces.layers.int.new('mask')
            bm.faces.ensure_lookup_table()
            #fill_faces_layer(bm, masks, 'mask', int, MASK, invert_mask=True)

            b_faces = []
            b_edges = set()
            b_verts = set()
            for mask, face in zip(mask_matched, bm.faces):
                if mask:
                    b_faces.append(face)
                    for edge in face.edges:
                        b_edges.add(edge)
                    for vert in face.verts:
                        b_verts.add(vert)

            extrude_geom = b_faces + list(b_edges) + list(b_verts)

            extruded_verts_last = []
            extruded_bm_verts_all = set()
            extruded_edges_last = []
            extruded_faces_last = []
            extruded_bm_faces_last = []

            matrix_spaces = [Matrix()]

            for idx in range(n_iterations):

                for item in extrude_geom:
                    if isinstance(item, bmesh.types.BMFace):
                        item[mask_layer] = OUT

                if is_290:
                    kwargs = {
                        'use_dissolve_ortho_edges': self.dissolve_ortho_edges
                    }
                else:
                    kwargs = {}

                new_geom = bmesh.ops.extrude_face_region(
                    bm,
                    geom=extrude_geom,
                    edges_exclude=set(),
                    use_keep_orig=self.keep_original,
                    **kwargs)['geom']

                extruded_verts = [
                    v for v in new_geom if isinstance(v, bmesh.types.BMVert)
                ]
                extruded_faces = [
                    f for f in new_geom if isinstance(f, bmesh.types.BMFace)
                ]

                if self.transform_mode == "Matrix":
                    matrices = matrix_per_iteration[idx]
                    if isinstance(matrices, Matrix):
                        matrices = [matrices]
                    matrix_spaces_matched = repeat_last_for_length(
                        matrix_spaces, len(extruded_verts))
                    for vertex_idx, (vertex, matrix) in enumerate(
                            zip(*match_long_repeat([extruded_verts, matrices
                                                    ]))):
                        bmesh.ops.transform(
                            bm,
                            verts=[vertex],
                            matrix=matrix,
                            space=matrix_spaces_matched[vertex_idx])
                        matrix_spaces_matched[vertex_idx] = matrix.inverted(
                        ) @ matrix_spaces_matched[vertex_idx]
                else:
                    height = height_per_iteration_matched[idx]
                    scale = scale_per_iteration_matched[idx]

                    normal = get_avg_normal(extruded_faces)
                    dr = normal * height
                    center = get_faces_center(extruded_faces)
                    translation = Matrix.Translation(center)
                    rotation = normal.rotation_difference(
                        (0, 0, 1)).to_matrix().to_4x4()
                    m = translation @ rotation
                    bmesh.ops.scale(bm,
                                    vec=(scale, scale, scale),
                                    space=m.inverted(),
                                    verts=extruded_verts)
                    bmesh.ops.translate(bm, verts=extruded_verts, vec=dr)

                extruded_bm_verts_all.update(extruded_verts)
                extruded_verts_last = [tuple(v.co) for v in extruded_verts]

                extruded_edges = [
                    e for e in new_geom if isinstance(e, bmesh.types.BMEdge)
                ]
                extruded_edges_last = [
                    tuple(v.index for v in edge.verts)
                    for edge in extruded_edges
                ]

                extruded_bm_faces_last = extruded_faces
                extruded_faces_last = [[v.index for v in face.verts]
                                       for face in extruded_faces]

                extrude_geom = new_geom

            if face_data:
                new_vertices, new_edges, new_faces, new_face_data = pydata_from_bmesh(
                    bm, face_data_matched)
            else:
                new_vertices, new_edges, new_faces = pydata_from_bmesh(bm)
                new_face_data = []

            if need_mask_out:
                new_mask = self.get_out_mask(bm, extruded_bm_faces_last,
                                             extruded_bm_verts_all)
                result_mask.append(new_mask)

            bm.free()

            result_vertices.append(new_vertices)
            result_edges.append(new_edges)
            result_faces.append(new_faces)
            result_ext_vertices.append(extruded_verts_last)
            result_ext_edges.append(extruded_edges_last)
            result_ext_faces.append(extruded_faces_last)
            result_face_data.append(new_face_data)

        self.outputs['Vertices'].sv_set(result_vertices)
        self.outputs['Edges'].sv_set(result_edges)
        self.outputs['Polygons'].sv_set(result_faces)
        self.outputs['NewVertices'].sv_set(result_ext_vertices)
        self.outputs['NewEdges'].sv_set(result_ext_edges)
        self.outputs['NewFaces'].sv_set(result_ext_faces)
        if 'Mask' in self.outputs:
            self.outputs['Mask'].sv_set(result_mask)
        if 'FaceData' in self.outputs:
            self.outputs['FaceData'].sv_set(result_face_data)
Esempio n. 28
0
    def process(self):
        if not (self.inputs['Vertices'].is_linked
                and self.inputs['Polygons'].is_linked):
            return
        if not (any(
                self.outputs[name].is_linked for name in
            ['Vertices', 'Edges', 'Polygons', 'NewEdges', 'NewPolys'])):
            return

        vertices_s = self.inputs['Vertices'].sv_get(default=[[]],
                                                    deepcopy=False)
        edges_s = self.inputs['Edges'].sv_get(default=[[]], deepcopy=False)
        faces_s = self.inputs['Polygons'].sv_get(default=[[]], deepcopy=False)
        if 'FaceData' in self.inputs:
            face_data_s = self.inputs['FaceData'].sv_get(default=[[]],
                                                         deepcopy=False)
        else:
            face_data_s = [[]]
        mask_s = self.inputs['Mask'].sv_get(default=[[True]], deepcopy=False)

        result_vertices = []
        result_edges = []
        result_faces = []
        result_face_data = []
        result_new_edges = []
        result_new_faces = []

        meshes = match_long_repeat(
            [vertices_s, edges_s, faces_s, face_data_s, mask_s])

        for vertices, edges, faces, face_data, mask in zip(*meshes):
            if face_data:
                face_data_matched = repeat_last_for_length(
                    face_data, len(faces))

            bm = bmesh_from_pydata(vertices,
                                   edges,
                                   faces,
                                   markup_face_data=True)
            mask_matched = repeat_last_for_length(mask, len(faces))

            b_faces = []
            for m, face in zip(mask_matched, bm.faces):
                if m:
                    b_faces.append(face)

            res = bmesh.ops.triangulate(bm,
                                        faces=b_faces,
                                        quad_method=self.quad_mode,
                                        ngon_method=self.ngon_mode)

            b_new_edges = [
                tuple(v.index for v in edge.verts) for edge in res['edges']
            ]
            b_new_faces = [[v.index for v in face.verts]
                           for face in res['faces']]

            if face_data:
                new_vertices, new_edges, new_faces, new_face_data = pydata_from_bmesh(
                    bm, face_data_matched)
            else:
                new_vertices, new_edges, new_faces = pydata_from_bmesh(bm)
                new_face_data = []
            bm.free()

            result_vertices.append(new_vertices)
            result_edges.append(new_edges)
            result_faces.append(new_faces)
            result_face_data.append(new_face_data)
            result_new_edges.append(b_new_edges)
            result_new_faces.append(b_new_faces)

        self.outputs['Vertices'].sv_set(result_vertices)
        self.outputs['Edges'].sv_set(result_edges)
        self.outputs['Polygons'].sv_set(result_faces)
        if 'FaceData' in self.outputs:
            self.outputs['FaceData'].sv_set(result_face_data)
        self.outputs['NewEdges'].sv_set(result_new_edges)
        self.outputs['NewPolys'].sv_set(result_new_faces)
Esempio n. 29
0
    def process(self):
        vertices_s = self.inputs['ControlPoints'].sv_get()
        has_weights = self.inputs['Weights'].is_linked
        weights_s = self.inputs['Weights'].sv_get(default=[[1.0]])
        u_size_s = self.inputs['USize'].sv_get()
        knots_u_s = self.inputs['KnotsU'].sv_get(default=[[]])
        knots_v_s = self.inputs['KnotsV'].sv_get(default=[[]])
        degree_u_s = self.inputs['DegreeU'].sv_get()
        degree_v_s = self.inputs['DegreeV'].sv_get()

        if self.input_mode == '1D':
            vertices_s = ensure_nesting_level(vertices_s, 3)
        else:
            vertices_s = ensure_nesting_level(vertices_s, 4)

        surfaces_out = []
        inputs = zip_long_repeat(vertices_s, weights_s, knots_u_s, knots_v_s,
                                 degree_u_s, degree_v_s, u_size_s)
        for vertices, weights, knots_u, knots_v, degree_u, degree_v, u_size in inputs:
            if isinstance(degree_u, (tuple, list)):
                degree_u = degree_u[0]
            if isinstance(degree_v, (tuple, list)):
                degree_v = degree_v[0]
            if isinstance(u_size, (list, tuple)):
                u_size = u_size[0]

            if self.surface_mode != 'NURBS':
                weights = None

            if self.surface_mode == 'NURBS':
                if self.input_mode == '1D':
                    weights = repeat_last_for_length(weights,
                                                     len(vertices),
                                                     deepcopy=True)
                else:
                    if isinstance(weights[0], (int, float)):
                        weights = [weights]
                    weights = repeat_last_for_length(weights,
                                                     len(vertices),
                                                     deepcopy=True)
                    for verts_u, weights_u in zip(vertices, weights):
                        fullList_deep_copy(weights_u, len(verts_u))

            if self.input_mode == '1D':
                n_v = u_size
                n_u = len(vertices) // n_v

                vertices = split_by_count(vertices, n_u)
                if self.surface_mode == 'NURBS':
                    weights = split_by_count(weights, n_u)

            if self.knot_mode == 'AUTO':
                if self.is_cyclic_v:
                    for row_idx in range(len(vertices)):
                        vertices[row_idx].extend(vertices[row_idx][:degree_v +
                                                                   1])
                        if self.surface_mode == 'NURBS':
                            weights[row_idx].extend(
                                weights[row_idx][:degree_v + 1])
                if self.is_cyclic_u:
                    vertices.extend(vertices[:degree_u + 1])
                    if self.surface_mode == 'NURBS':
                        weights.extend(weights[:degree_u + 1])
                self.debug("UxV: %s x %s", len(vertices), len(vertices[0]))

            n_u_total = len(vertices)
            n_v_total = len(vertices[0])

            if self.knot_mode == 'AUTO':
                if self.is_cyclic_u:
                    knots_u = list(range(n_u_total + degree_u + 1))
                else:
                    knots_u = sv_knotvector.generate(degree_u, n_u_total)
                self.debug("Auto knots U: %s", knots_u)
                surf_knotvector_u = knots_u

                if self.is_cyclic_v:
                    knots_v = list(range(n_v_total + degree_v + 1))
                else:
                    knots_v = sv_knotvector.generate(degree_v, n_v_total)
                self.debug("Auto knots V: %s", knots_v)
                surf_knotvector_v = knots_v
            else:
                surf_knotvector_u = knots_u
                surf_knotvector_v = knots_v

            new_surf = SvNurbsSurface.build(self.implementation, degree_u,
                                            degree_v, surf_knotvector_u,
                                            surf_knotvector_v, vertices,
                                            weights, self.normalize_knots)
            surf_knotvector_u = new_surf.get_knotvector_u().tolist()
            surf_knotvector_v = new_surf.get_knotvector_v().tolist()
            if self.is_cyclic_u:
                u_min = surf_knotvector_u[degree_u]
                u_max = surf_knotvector_u[-degree_u - 2]
                new_surf.u_bounds = u_min, u_max
                #print("U:",new_surf.u_bounds)
            else:
                u_min = min(surf_knotvector_u)
                u_max = max(surf_knotvector_u)
                new_surf.u_bounds = u_min, u_max
            if self.is_cyclic_v:
                v_min = surf_knotvector_v[degree_v]
                v_max = surf_knotvector_v[-degree_v - 2]
                new_surf.v_bounds = v_min, v_max
                #print("V:",new_surf.v_bounds)
            else:
                v_min = min(surf_knotvector_v)
                v_max = max(surf_knotvector_v)
                new_surf.v_bounds = v_min, v_max
            surfaces_out.append(new_surf)

        self.outputs['Surface'].sv_set(surfaces_out)
Esempio n. 30
0
    def process(self):
        if not any(socket.is_linked for socket in self.outputs):
            return

        surfaces_s = self.inputs['Surface'].sv_get()
        surface_level = get_data_nesting_level(surfaces_s,
                                               data_types=(SvSurface, ))
        surfaces_s = ensure_nesting_level(surfaces_s,
                                          2,
                                          data_types=(SvSurface, ))
        src_point_s = self.inputs['UVPoints'].sv_get(default=[[]])
        src_point_s = ensure_nesting_level(src_point_s, 4)

        src_u_s = self.inputs['U'].sv_get()
        src_u_s = ensure_nesting_level(src_u_s, 3)
        src_v_s = self.inputs['V'].sv_get()
        src_v_s = ensure_nesting_level(src_v_s, 3)

        normal_out = []
        tangent_u_out = []
        tangent_v_out = []
        matrix_out = []
        area_out = []
        du_out = []
        dv_out = []

        for surfaces, src_points_i, src_u_i, src_v_i in zip_long_repeat(
                surfaces_s, src_point_s, src_u_s, src_v_s):
            new_normals = []
            new_tangent_u = []
            new_tangent_v = []
            new_area = []
            new_du = []
            new_dv = []
            for surface, src_points, src_us, src_vs in zip_long_repeat(
                    surfaces, src_points_i, src_u_i, src_v_i):
                if self.input_mode == 'VERTICES':
                    us, vs = self.parse_input(src_points)
                else:
                    maxlen = max(len(src_us), len(src_vs))
                    src_us = repeat_last_for_length(src_us, maxlen)
                    src_vs = repeat_last_for_length(src_vs, maxlen)
                    us, vs = np.array(src_us), np.array(src_vs)

                data = surface.derivatives_data_array(us, vs)

                new_normals.append(data.unit_normals().tolist())
                du, dv = data.unit_tangents()
                new_tangent_u.append(du.tolist())
                new_tangent_v.append(dv.tolist())

                normals_len = [n[0] for n in data.normals_len().tolist()]
                new_area.append(normals_len)

                du_len, dv_len = data.tangent_lens()
                du_len = [n[0] for n in du_len.tolist()]
                dv_len = [n[0] for n in dv_len.tolist()]
                new_du.append(du_len)
                new_dv.append(dv_len)

                matrix_out.extend(data.matrices(as_mathutils=True))

            normal_out.append(new_normals)
            tangent_u_out.append(new_tangent_u)
            tangent_v_out.append(new_tangent_v)
            area_out.append(new_area)
            if surface_level == 2:
                du_out.append(new_du)
                dv_out.append(new_dv)
            else:
                du_out.extend(new_du)
                dv_out.extend(new_dv)

        self.outputs['Normal'].sv_set(normal_out)
        self.outputs['TangentU'].sv_set(tangent_u_out)
        self.outputs['TangentV'].sv_set(tangent_v_out)
        self.outputs['Matrix'].sv_set(matrix_out)
        self.outputs['AreaStretch'].sv_set(area_out)
        self.outputs['StretchU'].sv_set(du_out)
        self.outputs['StretchV'].sv_set(dv_out)