Exemplo n.º 1
0
    def make_brep_geometry(self):
        self.free_shapes = [shp_info for shp_info in self.all_shapes if shp_info.free]
        # sort down from solids to vertices
        self.free_shapes.sort(key=lambda shp: shp.dim(), reverse=True)
        free_shapes = [shp_info.shape for shp_info in self.free_shapes]

        compound = bw.Compound(free_shapes)
        compound.set_free_shapes()
        self.brep_file = os.path.abspath(self.basename + ".brep")
        with open(self.brep_file, 'w') as f:
            bw.write_model(f, compound, bw.Location())

        self.make_gmsh_shape_dict()
Exemplo n.º 2
0
def make_shell_brep(surface_3d):
    # Make surface
    bw_surface = bw.surface_from_bs(surface_3d)

    # make Vertices for the corners
    vertices = [bw.Vertex.on_surface(u, v, bw_surface)
                for u, v in [(0,0), (1,0), (1,1), (0,1)]]
    vertices.append(vertices[0])
    edges = [bw.Edge(vertices[i:i+2]).attach_to_surface(bw_surface) for i in range(4)]
    face = bw.Face([bw.Wire(edges)],bw_surface)
    shell = bw.Shell([face])
    compound = bw.Compound([shell])
    compound.set_free_shapes()
    return compound
Exemplo n.º 3
0
def prism_perturbed():
    # 0, 0; top, bottom
    v1=bw.Vertex((0.0, 0.0, 1.0))
    v2=bw.Vertex((0.0, 0.0, 0.0))

    v3=bw.Vertex((0.0, 1.0, 1.0))
    v4=bw.Vertex((0.0, 1.0, 0.0))

    v5=bw.Vertex((1.0, 0.0, 1.0))
    v6=bw.Vertex((1.0, 0.0, 0.0))

    # face v12 - v34
    # top
    e4=bw.Edge([v1,v3])
    # top
    e6=bw.Edge([v3, v5])
    # top
    e8=bw.Edge([v5, v1])

    # top cup
    f4 = bw.Face([e4, e6, e8])

    # bottom
    e5=bw.Edge([v2,v4])
    # face v34 - v56
    # bottom
    e7=bw.Edge([v4, v6])
    # face v56 - v12
    # bottom
    e9=bw.Edge([v6, v2])

    # bot cup
    w5=bw.Wire([e5, e7, e9])
    f5 = bw.Face([w5.m()])


    # vertical edges
    e1=bw.Edge([v1,v2])
    e2=bw.Edge([v3,v4])
    e3=bw.Edge([v5,v6])

    f1 = bw.Face([e1.m(), e4, e2, e5.m()])
    f2 = bw.Face([e2.m(), e6, e3, e7.m()])
    f3 = bw.Face([e3.m(), e8, e1, e9.m()])

    shell = bw.Shell([ f4, f5.m(), f1, f2, f3 ])
    cube_solid = bw.Solid([ shell ])
    model = bw.Compound([cube_solid])
    return model, composed_location()
Exemplo n.º 4
0
    def test_cube(self):

        shell = self._cube()
        #shell = self._permuted_cube()

        s1=bw.Solid([ shell ])

        c1=bw.Compound([s1])

        loc1=bw.Location([[0,0,1,0],[1,0,0,0],[0,1,0,0]])
        loc2=bw.Location([[0,0,1,0],[1,0,0,0],[0,1,0,0]]) #dej tam tu druhou z prikladu
        cloc=bw.ComposedLocation([(loc1,1),(loc2,1)])

        with open("_out_test_prism.brep", "w") as f:
            bw.write_model(f, c1, cloc)
            #bw.write_model(sys.stdout, c1, cloc)
        print(c1)
Exemplo n.º 5
0
def tetrahedron():
    v0 = bw.Vertex([0,0,0])
    v1 = bw.Vertex([1,0,0])
    v2 = bw.Vertex([0,1,0])
    v3 = bw.Vertex([0,0,1])

    e01 = bw.Edge([v0, v1])
    e02 = bw.Edge([v0, v2])
    e03 = bw.Edge([v0, v3])
    e12 = bw.Edge([v1, v2])
    e23 = bw.Edge([v2, v3])
    e13 = bw.Edge([v1, v3])

    f1 = bw.Face([e01, e12, e02.m()])
    f2 = bw.Face([e02, e23, e03.m()])
    f3 = bw.Face([e03, e13.m(), e01.m()])
    f4 = bw.Face([e12, e23, e13.m()])

    shell = bw.Shell([f1, f2, f3, f4])
    s = bw.Solid([shell])
    return bw.Compound([s]), bw.Identity
Exemplo n.º 6
0
def gen(gallery_mesh_file, out_brep_file, mesh_cut_tool_param, inv_par,
        project_conf):
    el_char_len = 1.0
    other_char_len = 10.0

    if inv_par.meshFrom == MeshFrom.GALLERY_CLOUD:
        offset = np.array([
            project_conf.point_cloud_origin_x,
            project_conf.point_cloud_origin_y,
            project_conf.point_cloud_origin_z
        ])
    else:
        offset = np.array([
            project_conf.gallery_mesh_origin_x,
            project_conf.gallery_mesh_origin_y,
            project_conf.gallery_mesh_origin_z
        ])

    gallery_mesh = GmshIO(gallery_mesh_file)

    #gallery_origin = np.array(gallery_origin)

    for id, node in gallery_mesh.nodes.items():
        gallery_mesh.nodes[id] = gallery_mesh.nodes[
            id]  #+ np.array([-622000.0, -1128000.0, 0.0])

    base_point, gen_vecs = cut_tool_to_gen_vecs(mesh_cut_tool_param)

    opposite_pont = base_point + gen_vecs[0] + gen_vecs[1] + gen_vecs[2]
    planes = [(base_point, gen_vecs[0], gen_vecs[1]),
              (base_point, gen_vecs[1], gen_vecs[2]),
              (base_point, gen_vecs[2], gen_vecs[0]),
              (opposite_pont, gen_vecs[0], -gen_vecs[1]),
              (opposite_pont, gen_vecs[1], -gen_vecs[2]),
              (opposite_pont, gen_vecs[2], -gen_vecs[0])]

    b = inv_tr(gen_vecs)

    class VertInfo:
        def __init__(self, node):
            self.plane_pos = [0] * 6
            self.cut = [False] * 6

            for i in range(6):
                pv = np.cross(planes[i][1], planes[i][2])
                w = np.array(node) - planes[i][0]
                self.plane_pos[i] = np.sign(np.dot(pv, w))  # sign zbytecny

    #v1 = bw.Vertex(base_point + gen_vecs[0])
    bw_vertices = {}
    vertices_tr = {}
    vert_info = {}
    for id, node in gallery_mesh.nodes.items():
        node += offset
        #bw_vertices[id] = bw.Vertex(node + np.array([- 622000, - 1128000, 0]), tolerance=1e-3)
        bw_vertices[id] = bw.Vertex(node, tolerance=1e-3)
        vert_info[id] = VertInfo(node)
        vertices_tr[id] = b @ (np.array(node) - base_point)

    bw_edges = {}

    def get_edge(id0, id1):
        k = (id0, id1)
        if k in bw_edges:
            return bw_edges[k]
        elif (id1, id0) in bw_edges:
            return bw_edges[(id1, id0)].m()
        else:
            e = bw.Edge([bw_vertices[k[0]], bw_vertices[k[1]]])
            bw_edges[k] = e
            return e

    bw_faces = []
    vids_to_move = [[], [], [], [], [], []]
    plane_edges = [[], [], [], [], [], []]
    cut_triangles = [[], [], [], [], [], []]
    tri_map = {}

    def process_triangle(id0, id1, id2):
        for i in range(6):
            if vert_info[id0].plane_pos[i] <= 0 or vert_info[id1].plane_pos[
                    i] <= 0 or vert_info[id2].plane_pos[i] <= 0:
                id_out = set()
                for j in range(6):
                    if j == i:
                        continue
                    # todo: zbytecne resi protilehlou stranu
                    for k in [id0, id1, id2]:
                        if vert_info[k].plane_pos[j] <= 0:
                            id_out.add(k)
                if len(id_out) >= 3:
                    return
                id_inside = []
                for j in [id0, id1, id2]:
                    if vert_info[j].plane_pos[i] > 0:
                        vids_to_move[i].append(j)
                        id_inside.append(j)
                if len(id_inside) == 2:
                    edge = (id_inside[0], id_inside[1])
                    if edge in plane_edges[i]:
                        plane_edges[i].remove(edge)
                    elif (edge[1], edge[0]) in plane_edges[i]:
                        plane_edges[i].remove((edge[1], edge[0]))
                    else:
                        plane_edges[i].append(edge)
                if len(id_inside) >= 1:
                    cut_triangles[i].append((id0, id1, id2))
                return

        e1 = get_edge(id0, id1)
        e2 = get_edge(id1, id2)
        e3 = get_edge(id2, id0)
        f = bw.Face([e1, e2, e3])
        bw_faces.append(f)
        tri_map[(id0, id1, id2)] = f

    for id, data in gallery_mesh.elements.items():
        el_type, tags, nodes = data
        if el_type != 2:
            continue
        process_triangle(*nodes)

    # remove duplicit vertices id
    vids_to_move_set = [set() for _ in range(6)]
    for i in range(6):
        vids_to_move_set[i] = set(vids_to_move[i])
        vids_to_move[i] = list(vids_to_move_set[i])

    # check if every border vertex belongs to only one plane
    for i in range(6):
        for j in range(6):
            if i == j:
                continue
            if not vids_to_move_set[i].isdisjoint(vids_to_move_set[j]):
                print("ERROR: Edge of cut body is to close to gallery mesh.")
                return False

    # remove triangles laying on plane
    for i in range(6):
        two_side = []
        for id, data in gallery_mesh.elements.items():
            el_type, tags, nodes = data
            if el_type != 2:
                continue
            count = 0
            for n in nodes:
                if n in vids_to_move_set[i]:
                    count += 1
            if count == 3:
                two_side.append((*nodes, ))

                if (nodes[0], nodes[1]) in plane_edges[i]:
                    plane_edges[i].remove((nodes[0], nodes[1]))
                elif (nodes[1], nodes[0]) in plane_edges[i]:
                    plane_edges[i].remove((nodes[1], nodes[0]))
                else:
                    plane_edges[i].append((nodes[0], nodes[1]))

                if (nodes[1], nodes[2]) in plane_edges[i]:
                    plane_edges[i].remove((nodes[1], nodes[2]))
                elif (nodes[2], nodes[1]) in plane_edges[i]:
                    plane_edges[i].remove((nodes[2], nodes[1]))
                else:
                    plane_edges[i].append((nodes[1], nodes[2]))

                if (nodes[2], nodes[0]) in plane_edges[i]:
                    plane_edges[i].remove((nodes[2], nodes[0]))
                elif (nodes[0], nodes[2]) in plane_edges[i]:
                    plane_edges[i].remove((nodes[0], nodes[2]))
                else:
                    plane_edges[i].append((nodes[2], nodes[0]))

                bw_faces.remove(tri_map[(*nodes, )])

    # move border vertices
    ax_pos = [
        (2, 0.0),
        (0, 0.0),
        (1, 0.0),
        (2, 1.0),
        (0, 1.0),
        (1, 1.0),
    ]
    for i in range(6):
        for vid in vids_to_move[i]:
            shift = ax_pos[i][1] - vertices_tr[vid][ax_pos[i][0]]
            vertices_tr[vid][ax_pos[i][0]] = ax_pos[i][1]
            bw_vertices[vid].point += shift * gen_vecs[ax_pos[i][0]]

    face_edges = [[], [], [], [], [], []]

    # todo: doresit dotekajici se wiry
    for i in range(6):
        if not plane_edges[i]:
            continue
        first_edge = last_edge = plane_edges[i].pop()
        first_vertex = last_edge[0]
        last_vertex = last_edge[1]
        wire = [first_edge]
        while plane_edges[i]:
            find = False
            cont_edges = []
            for edge in list(plane_edges[i]):
                if last_vertex in edge:
                    cont_edges.append(edge)
            if cont_edges:
                # find appropriate edge
                edge = cont_edges[0]
                wire.append(edge)
                plane_edges[i].remove(edge)
                if first_vertex in edge:
                    # we have closed wire
                    face_edges[i].append(wire)
                    #print(wire)
                    if not plane_edges[i]:
                        break
                    first_edge = last_edge = plane_edges[i].pop()
                    first_vertex = last_edge[0]
                    last_vertex = last_edge[1]
                    wire = [first_edge]
                else:
                    last_edge = edge
                    last_vertex = edge[1] if last_vertex != edge[1] else edge[0]
            else:
                # not find closed wire
                if not plane_edges[i]:
                    break
                first_edge = last_edge = plane_edges[i].pop()
                first_vertex = last_edge[0]
                last_vertex = last_edge[1]
                wire = [first_edge]

    v1 = bw.Vertex(base_point + gen_vecs[0])
    v2 = bw.Vertex(base_point + gen_vecs[2] + gen_vecs[0])
    v3 = bw.Vertex(base_point + gen_vecs[2] + gen_vecs[1] + gen_vecs[0])
    v4 = bw.Vertex(base_point + gen_vecs[1] + gen_vecs[0])

    v5 = bw.Vertex(base_point)
    v6 = bw.Vertex(base_point + gen_vecs[2])
    v7 = bw.Vertex(base_point + gen_vecs[2] + gen_vecs[1])
    v8 = bw.Vertex(base_point + gen_vecs[1])

    e1 = bw.Edge([v1, v2])
    e2 = bw.Edge([v2, v3])
    e3 = bw.Edge([v3, v4])
    e4 = bw.Edge([v4, v1])

    faces = []
    for i in [4]:  #range(6):
        #surf, vtxs_uv = bw.Approx.plane([planes[i][0], planes[i][0] + planes[i][1], planes[i][0] + planes[i][2]])
        surf, vtxs_uv = bw.Approx.plane(
            [v1.point, v1.point + gen_vecs[1], v1.point + gen_vecs[2]])
        assert vtxs_uv == [(0, 0), (1, 0), (0, 1)]

        e1.attach_to_surface(surf, (0, 0), (0, 1))
        e2.attach_to_surface(surf, (0, 1), (1, 1))
        e3.attach_to_surface(surf, (1, 1), (1, 0))
        e4.attach_to_surface(surf, (1, 0), (0, 0))

        for j in range(len(face_edges[i])):
            for e in face_edges[i][j]:
                try:
                    bw_edges[e].attach_to_surface(surf, vertices_tr[e[0]][1:],
                                                  vertices_tr[e[1]][1:])
                except KeyError:
                    bw_edges[(e[1],
                              e[0])].attach_to_surface(surf,
                                                       vertices_tr[e[1]][1:],
                                                       vertices_tr[e[0]][1:])

        wire_list = []
        for j in range(len(face_edges[i])):
            edge_list = []
            for e in face_edges[i][j]:
                if e in bw_edges:
                    edge_list.append(bw_edges[e])
                else:
                    edge_list.append(bw_edges[(e[1], e[0])])
            wire_list.append(edge_list)
        # todo: face v dire nefunguje
        faces.append(
            bw.Face([
                bw.Wire([e1, e2, e3, e4]),
                *[bw.Wire(edge_list) for edge_list in wire_list]
            ],
                    surface=surf))

    #f1 = bw.Face([bw.Wire([e1, e2, e3]), bw.Wire([e1x, e2x, e3x])], surface=surf)

    e5 = bw.Edge([v5, v6])
    e6 = bw.Edge([v6, v7])
    e7 = bw.Edge([v7, v8])
    e8 = bw.Edge([v8, v5])

    f2 = bw.Face([e5, e6, e7, e8])

    e9 = bw.Edge([v1, v5])
    e10 = bw.Edge([v2, v6])
    e11 = bw.Edge([v3, v7])
    e12 = bw.Edge([v4, v8])

    # f3 = bw.Face([e1, e10, e5.m(), e9.m()])
    # f4 = bw.Face([e2, e11, e6.m(), e10.m()])
    # f5 = bw.Face([e3, e12, e7.m(), e11.m()])
    # f6 = bw.Face([e4, e9, e8.m(), e12.m()])

    for i in [2]:  #range(6):
        surf, vtxs_uv = bw.Approx.plane(
            [v5.point, v5.point + gen_vecs[0], v5.point + gen_vecs[2]])
        assert vtxs_uv == [(0, 0), (1, 0), (0, 1)]

        e1.attach_to_surface(surf, (1, 0), (1, 1))
        e10.attach_to_surface(surf, (1, 1), (0, 1))
        e5.attach_to_surface(surf, (0, 0), (0, 1))
        e9.attach_to_surface(surf, (1, 0), (0, 0))

        for j in range(len(face_edges[i])):
            for e in face_edges[i][j]:
                try:
                    bw_edges[e].attach_to_surface(surf,
                                                  vertices_tr[e[0]][0:3:2],
                                                  vertices_tr[e[1]][0:3:2])
                except KeyError:
                    bw_edges[(e[1], e[0])].attach_to_surface(
                        surf, vertices_tr[e[1]][0:3:2],
                        vertices_tr[e[0]][0:3:2])

        wire_list = []
        for j in range(len(face_edges[i])):
            edge_list = []
            for e in face_edges[i][j]:
                if e in bw_edges:
                    edge_list.append(bw_edges[e])
                else:
                    edge_list.append(bw_edges[(e[1], e[0])])
            wire_list.append(edge_list)
        faces.append(
            bw.Face([
                bw.Wire([e1, e10, e5, e9]),
                *[bw.Wire(edge_list) for edge_list in wire_list]
            ],
                    surface=surf))

    for i in [5]:  #range(6):
        surf, vtxs_uv = bw.Approx.plane(
            [v8.point, v8.point + gen_vecs[0], v8.point + gen_vecs[2]])
        #print(vtxs_uv)

        e3.attach_to_surface(surf, (1, 1), (1, 0))
        e12.attach_to_surface(surf, (1, 0), (0, 0))
        e7.attach_to_surface(surf, (0, 1), (0, 0))
        e11.attach_to_surface(surf, (1, 1), (0, 1))

        for j in range(len(face_edges[i])):
            for e in face_edges[i][j]:
                try:
                    bw_edges[e].attach_to_surface(surf,
                                                  vertices_tr[e[0]][0:3:2],
                                                  vertices_tr[e[1]][0:3:2])
                except KeyError:
                    bw_edges[(e[1], e[0])].attach_to_surface(
                        surf, vertices_tr[e[1]][0:3:2],
                        vertices_tr[e[0]][0:3:2])

        wire_list = []
        for j in range(len(face_edges[i])):
            edge_list = []
            for e in face_edges[i][j]:
                if e in bw_edges:
                    edge_list.append(bw_edges[e])
                else:
                    edge_list.append(bw_edges[(e[1], e[0])])
            wire_list.append(edge_list)

        #wire_list2 = [wire_list[4]]
        #wire_list.remove(wire_list[4])

        faces.append(
            bw.Face([
                bw.Wire([e3, e12, e7, e11]),
                *[bw.Wire(edge_list) for edge_list in wire_list]
            ],
                    surface=surf))
        #faces.append(bw.Face([bw.Wire(edge_list)], surface=surf))
        #faces.append(bw.Face([*[bw.Wire(edge_list) for edge_list in wire_list2]], surface=surf))

    for i in [1]:  #range(6):
        surf, vtxs_uv = bw.Approx.plane(
            [v5.point, v5.point + gen_vecs[1], v5.point + gen_vecs[2]])
        #print(vtxs_uv)

        e5.attach_to_surface(surf, (0, 0), (0, 1))
        e6.attach_to_surface(surf, (0, 1), (1, 1))
        e7.attach_to_surface(surf, (1, 1), (1, 0))
        e8.attach_to_surface(surf, (1, 0), (0, 0))

        for j in range(len(face_edges[i])):
            for e in face_edges[i][j]:
                try:
                    bw_edges[e].attach_to_surface(surf, vertices_tr[e[0]][1:],
                                                  vertices_tr[e[1]][1:])
                except KeyError:
                    bw_edges[(e[1],
                              e[0])].attach_to_surface(surf,
                                                       vertices_tr[e[1]][1:],
                                                       vertices_tr[e[0]][1:])

        wire_list = []
        for j in range(len(face_edges[i])):
            edge_list = []
            for e in face_edges[i][j]:
                if e in bw_edges:
                    edge_list.append(bw_edges[e])
                else:
                    edge_list.append(bw_edges[(e[1], e[0])])
            wire_list.append(edge_list)
        faces.append(
            bw.Face([
                bw.Wire([e5, e6, e7, e8]),
                *[bw.Wire(edge_list) for edge_list in wire_list]
            ],
                    surface=surf))

    for i in [3]:  #range(6):
        surf, vtxs_uv = bw.Approx.plane(
            [v6.point, v6.point + gen_vecs[0], v6.point + gen_vecs[1]])

        e2.attach_to_surface(surf, (1, 0), (1, 1))
        e11.attach_to_surface(surf, (1, 1), (0, 1))
        e6.attach_to_surface(surf, (0, 0), (0, 1))
        e10.attach_to_surface(surf, (1, 0), (0, 0))

        for j in range(len(face_edges[i])):
            for e in face_edges[i][j]:
                try:
                    bw_edges[e].attach_to_surface(surf, vertices_tr[e[0]][:2],
                                                  vertices_tr[e[1]][:2])
                except KeyError:
                    bw_edges[(e[1],
                              e[0])].attach_to_surface(surf,
                                                       vertices_tr[e[1]][:2],
                                                       vertices_tr[e[0]][:2])

        wire_list = []
        for j in range(len(face_edges[i])):
            edge_list = []
            for e in face_edges[i][j]:
                if e in bw_edges:
                    edge_list.append(bw_edges[e])
                else:
                    edge_list.append(bw_edges[(e[1], e[0])])
            wire_list.append(edge_list)
        faces.append(
            bw.Face([
                bw.Wire([e2, e11, e6, e10]),
                *[bw.Wire(edge_list) for edge_list in wire_list]
            ],
                    surface=surf))

    for i in [0]:  #range(6):
        surf, vtxs_uv = bw.Approx.plane(
            [v5.point, v5.point + gen_vecs[0], v5.point + gen_vecs[1]])

        e4.attach_to_surface(surf, (1, 1), (1, 0))
        e9.attach_to_surface(surf, (1, 0), (0, 0))
        e8.attach_to_surface(surf, (0, 1), (0, 0))
        e12.attach_to_surface(surf, (1, 1), (0, 1))

        for j in range(len(face_edges[i])):
            for e in face_edges[i][j]:
                try:
                    bw_edges[e].attach_to_surface(surf, vertices_tr[e[0]][:2],
                                                  vertices_tr[e[1]][:2])
                except KeyError:
                    bw_edges[(e[1],
                              e[0])].attach_to_surface(surf,
                                                       vertices_tr[e[1]][:2],
                                                       vertices_tr[e[0]][:2])

        wire_list = []
        for j in range(len(face_edges[i])):
            edge_list = []
            for e in face_edges[i][j]:
                if e in bw_edges:
                    edge_list.append(bw_edges[e])
                else:
                    edge_list.append(bw_edges[(e[1], e[0])])
            wire_list.append(edge_list)
        faces.append(
            bw.Face([
                bw.Wire([e4, e9, e8, e12]),
                *[bw.Wire(edge_list) for edge_list in wire_list]
            ],
                    surface=surf))

    shell = bw.Shell(bw_faces + faces)
    #shell = bw.Shell(faces)

    s1 = bw.Solid([shell])

    c1 = bw.Compound([s1])

    with open(out_brep_file, "w") as f:
        bw.write_model(f, c1)

    return True
Exemplo n.º 7
0
def gen(cloud_file, out_brep_file, mesh_cut_tool_param):
    surf_approx = bs_approx.SurfaceApprox.approx_from_file(cloud_file)

    quad = surf_approx.compute_default_quad()
    nuv = surf_approx.compute_default_nuv()
    nuv = nuv / 5
    surface = surf_approx.compute_approximation()
    #surface = surf_approx.compute_approximation(quad=quad, nuv=nuv)
    surface_3d = surface.make_full_surface()
    bw_surface = bw.surface_from_bs(surface_3d)

    a = bw_surface._bs_surface.eval(0, 0)
    b = bw_surface._bs_surface.eval(1, 0)
    c = bw_surface._bs_surface.eval(0, 1)

    base_point, gen_vecs = cut_tool_to_gen_vecs(mesh_cut_tool_param)

    a[2] = 0
    b[2] = 0
    c[2] = 0

    ab = b - a
    ac = c - a
    tr = np.array([ab, ac, [0, 0, 1]]).T
    inv_tr = np.linalg.inv(tr)

    v1 = bw.Vertex(base_point + gen_vecs[0])
    v2 = bw.Vertex(base_point + gen_vecs[2] + gen_vecs[0])
    v3 = bw.Vertex(base_point + gen_vecs[2] + gen_vecs[1] + gen_vecs[0])
    v4 = bw.Vertex(base_point + gen_vecs[1] + gen_vecs[0])

    v5 = bw.Vertex(base_point)
    v6 = bw.Vertex(base_point + gen_vecs[2])
    v7 = bw.Vertex(base_point + gen_vecs[2] + gen_vecs[1])
    v8 = bw.Vertex(base_point + gen_vecs[1])

    v2l = inv_tr @ (v2.point - a)
    v3l = inv_tr @ (v3.point - a)
    v6l = inv_tr @ (v6.point - a)
    v7l = inv_tr @ (v7.point - a)

    try:
        v2s = bw_surface._bs_surface.eval(v2l[0], v2l[1])
        v3s = bw_surface._bs_surface.eval(v3l[0], v3l[1])
        v6s = bw_surface._bs_surface.eval(v6l[0], v6l[1])
        v7s = bw_surface._bs_surface.eval(v7l[0], v7l[1])
    except IndexError:
        print("Error: Mesh cut area must be inside surface point cloud.")
        return False, bw_surface

    v2h = v2s[2] - base_point[2]
    v3h = v3s[2] - base_point[2]
    v6h = v6s[2] - base_point[2]
    v7h = v7s[2] - base_point[2]

    v2.point[2] = v2s[2]
    v3.point[2] = v3s[2]
    v6.point[2] = v6s[2]
    v7.point[2] = v7s[2]

    e1 = bw.Edge([v1, v2])
    e2 = bw.Edge([v2, v3])
    e3 = bw.Edge([v3, v4])
    e4 = bw.Edge([v4, v1])

    e5 = bw.Edge([v5, v6])
    e6 = bw.Edge([v6, v7])
    e7 = bw.Edge([v7, v8])
    e8 = bw.Edge([v8, v5])

    e9 = bw.Edge([v1, v5])
    e10 = bw.Edge([v2, v6])
    e11 = bw.Edge([v3, v7])
    e12 = bw.Edge([v4, v8])

    faces = []

    # top
    e2.attach_to_surface(bw_surface, (v2l[0], v2l[1]), (v3l[0], v3l[1]))
    e11.attach_to_surface(bw_surface, (v3l[0], v3l[1]), (v7l[0], v7l[1]))
    e6.attach_to_surface(bw_surface, (v6l[0], v6l[1]), (v7l[0], v7l[1]))
    e10.attach_to_surface(bw_surface, (v2l[0], v2l[1]), (v6l[0], v6l[1]))

    faces.append(bw.Face([bw.Wire([e2, e11, e6, e10])], surface=bw_surface))

    # bottom
    surf, vtxs_uv = bw.Approx.plane(
        [v5.point, v5.point + gen_vecs[0], v5.point + gen_vecs[1]])

    e4.attach_to_surface(surf, (1, 1), (1, 0))
    e9.attach_to_surface(surf, (1, 0), (0, 0))
    e8.attach_to_surface(surf, (0, 1), (0, 0))
    e12.attach_to_surface(surf, (1, 1), (0, 1))

    faces.append(bw.Face([bw.Wire([e4, e9, e8, e12])], surface=surf))

    def get_curves(v0, v1):
        n_points = 100
        u_points = np.linspace(v0[0], v1[0], n_points)
        v_points = np.linspace(v0[1], v1[1], n_points)
        uv_points = np.stack((u_points, v_points), axis=1)
        xyz_points = bw_surface._bs_surface.eval_array(uv_points)
        curve_xyz = bs_approx.curve_from_grid(xyz_points)

        poles_z = curve_xyz.poles[:, 2].copy()
        x_diff, y_diff, z_diff = np.abs(xyz_points[-1] - xyz_points[0])
        if x_diff > y_diff:
            axis = 0
        else:
            axis = 1
        poles_t = curve_xyz.poles[:, axis].copy()
        poles_t -= xyz_points[0][axis]
        poles_t /= (xyz_points[-1][axis] - xyz_points[0][axis])
        poles_z -= base_point[2]
        poles_tz = np.stack((poles_t, poles_z), axis=1)
        curve_tz = bs.Curve(curve_xyz.basis, poles_tz)

        return bw.curve_from_bs(curve_tz), bw.curve_from_bs(curve_xyz)

    surf, vtxs_uv = bw.Approx.plane(
        [v1.point, v1.point + gen_vecs[1], v1.point + [0, 0, 1]])
    assert vtxs_uv == [(0, 0), (1, 0), (0, 1)]

    e1.attach_to_surface(surf, (0, 0), (0, v2h))
    curve_tz, curve_xyz = get_curves(v2l, v3l)
    e2.attach_to_2d_curve((0.0, 1.0), curve_tz, surf)
    e2.attach_to_3d_curve((0.0, 1.0), curve_xyz)
    e3.attach_to_surface(surf, (1, v3h), (1, 0))
    e4.attach_to_surface(surf, (1, 0), (0, 0))

    faces.append(bw.Face([bw.Wire([e1, e2, e3, e4])], surface=surf))

    surf, vtxs_uv = bw.Approx.plane(
        [v5.point + gen_vecs[0], v5.point, v5.point + gen_vecs[0] + [0, 0, 1]])
    assert vtxs_uv == [(0, 0), (1, 0), (0, 1)]

    e1.attach_to_surface(surf, (0, 0), (0, v2h))
    curve_tz, curve_xyz = get_curves(v2l, v6l)
    e10.attach_to_2d_curve((0.0, 1.0), curve_tz, surf)
    e10.attach_to_3d_curve((0.0, 1.0), curve_xyz)
    e5.attach_to_surface(surf, (1, 0), (1, v6h))
    e9.attach_to_surface(surf, (0, 0), (1, 0))

    faces.append(bw.Face([bw.Wire([e1, e10, e5, e9])], surface=surf))

    surf, vtxs_uv = bw.Approx.plane(
        [v8.point + gen_vecs[0], v8.point, v8.point + gen_vecs[0] + [0, 0, 1]])
    assert vtxs_uv == [(0, 0), (1, 0), (0, 1)]

    e3.attach_to_surface(surf, (0, v3h), (0, 0))
    e12.attach_to_surface(surf, (0, 0), (1, 0))
    e7.attach_to_surface(surf, (1, v7h), (1, 0))
    curve_tz, curve_xyz = get_curves(v3l, v7l)
    e11.attach_to_2d_curve((0.0, 1.0), curve_tz, surf)
    e11.attach_to_3d_curve((0.0, 1.0), curve_xyz)

    faces.append(bw.Face([bw.Wire([e3, e12, e7, e11])], surface=surf))

    surf, vtxs_uv = bw.Approx.plane(
        [v5.point, v5.point + gen_vecs[1], v5.point + [0, 0, 1]])
    assert vtxs_uv == [(0, 0), (1, 0), (0, 1)]

    e5.attach_to_surface(surf, (0, 0), (0, v6h))
    curve_tz, curve_xyz = get_curves(v6l, v7l)
    e6.attach_to_2d_curve((0.0, 1.0), curve_tz, surf)
    e6.attach_to_3d_curve((0.0, 1.0), curve_xyz)
    e7.attach_to_surface(surf, (1, v7h), (1, 0))
    e8.attach_to_surface(surf, (1, 0), (0, 0))

    faces.append(bw.Face([bw.Wire([e5, e6, e7, e8])], surface=surf))

    shell = bw.Shell(faces)

    s1 = bw.Solid([shell])

    c1 = bw.Compound([s1])

    with open(out_brep_file, "w") as f:
        bw.write_model(f, c1)

    return True, bw_surface