def generate_falsecolour_bar(minval, maxval, unit_str, bar_length, description_str = None, bar_pos = (0,0,0), inverse = False): """ This function constructs a falsecolour diagram. Parameters ---------- minval : float The minimum value of the falsecolour bar. maxval : float The maximum value of the falsecolour bar. unit_str : str The string of the unit to be displayed on the bar. bar_length : float The length of the falsecolour bar. description_str : str, optional Description for the falsecolour bar, Default = None. bar_pos : tuple of floats, optional The position of the bar, Default = (0,0,0). inverse : bool False for red being max, True for blue being maximum. Returns ------- falsecolour bar : list of OCCfaces The falsecolor bar which is a list of OCCfaces. bar colour : list of tuple of floats Each tuple is a r,g,b that is specifying the colour of the bar. geometries of text: OCCcompound The geometries of the text. str_colour_list : list of tuple of floats Each tuple is a r,g,b that is specifying the colour of the string. value of each falsecolour : list of floats The value of each falsecolour. """ import numpy interval = 10.0 xdim = bar_length/interval ydim = bar_length rectangle = construct.make_rectangle(xdim, ydim) rec_mid_pt = calculate.face_midpt(rectangle) moved_rectangle = fetch.topo2topotype(modify.move(rec_mid_pt, bar_pos, rectangle)) grid_srfs = construct.grid_face(moved_rectangle, xdim, xdim) #generate uniform results between max and min inc1 = (maxval-minval)/(interval) value_range = list(numpy.arange(minval, maxval+0.1, inc1)) inc2 = inc1/2.0 value_range_midpts = list(numpy.arange(minval+inc2, maxval, inc1)) bar_colour = falsecolour(value_range_midpts, minval, maxval, inverse=inverse) grid_srfs2 = [] moved_str_face_list = [] srf_cnt = 0 for srf in grid_srfs: reversed_srf = modify.reverse_face(srf) grid_srfs2.append(reversed_srf) res_label = round(value_range[srf_cnt],2) brep_str = fetch.topo2topotype(construct.make_brep_text(str(res_label), xdim/2)) orig_pt = calculate.get_centre_bbox(brep_str) loc_pt = calculate.face_midpt(srf) loc_pt = modify.move_pt(loc_pt, (1,-0.3,0), xdim*1.2) moved_str = modify.move(orig_pt, loc_pt, brep_str) moved_str_face_list.append(moved_str) if srf_cnt == len(grid_srfs)-1: res_label = round(value_range[srf_cnt+1],2) brep_str = fetch.topo2topotype(construct.make_brep_text(str(res_label), xdim/2)) orig_pt = calculate.get_centre_bbox(brep_str) loc_pt3 = modify.move_pt(loc_pt, (0,1,0), xdim) moved_str = modify.move(orig_pt, loc_pt3, brep_str) moved_str_face_list.append(moved_str) brep_str_unit = construct.make_brep_text(str(unit_str), xdim) orig_pt2 = calculate.get_centre_bbox(brep_str_unit) loc_pt2 = modify.move_pt(loc_pt, (0,1,0), xdim*2) moved_str = modify.move(orig_pt2, loc_pt2, brep_str_unit) moved_str_face_list.append(moved_str) if description_str !=None: if srf_cnt == 0: d_str = fetch.topo2topotype(construct.make_brep_text(description_str, xdim/2)) orig_pt2 = calculate.get_centre_bbox(d_str) loc_pt2 = modify.move_pt(loc_pt, (0,-1,0), xdim*5) moved_str = modify.move(orig_pt2, loc_pt2, d_str) moved_str_face_list.append(moved_str) srf_cnt+=1 cmpd = construct.make_compound(moved_str_face_list) face_list = fetch.topo_explorer(cmpd, "face") meshed_list = [] for face in face_list: meshed_face_list = construct.simple_mesh(face) mface = construct.make_shell(meshed_face_list) face_mid_pt = calculate.face_midpt(face) str_mid_pt = calculate.get_centre_bbox(mface) moved_mface = modify.move(str_mid_pt,face_mid_pt,mface) meshed_list.append(moved_mface) meshed_str_cmpd =construct.make_compound(meshed_list) str_colour_list = [(0,0,0)] return grid_srfs2, bar_colour, meshed_str_cmpd, str_colour_list, value_range_midpts
def write_2_stl2(occtopology, stl_filepath, is_meshed = True, linear_deflection = 0.8, angle_deflection = 0.5): """ This function writes a 3D model into STL format. This is different from write2stl as it uses the numpy-stl library. Parameters ---------- occtopology : OCCtopology Geometries to be written into STL. OCCtopology includes: OCCshape, OCCcompound, OCCcompsolid, OCCsolid, OCCshell, OCCface, OCCwire, OCCedge, OCCvertex stl_filepath : str The file path of the STL file. mesh_incremental_float : float, optional Default = 0.8. Returns ------- None : None The geometries are written to a STL file. """ import numpy as np from stl import mesh if is_meshed == False: tri_faces = construct.simple_mesh(occtopology, linear_deflection = linear_deflection, angle_deflection = angle_deflection) occtopology = construct.make_compound(tri_faces) face_list = fetch.topo_explorer(occtopology, "face") vlist = fetch.topo_explorer(occtopology, "vertex") occptlist = modify.occvertex_list_2_occpt_list(vlist) pyptlist = modify.occpt_list_2_pyptlist(occptlist) pyptlist = modify.rmv_duplicated_pts(pyptlist) vertices = np.array(pyptlist) face_index_2dlsit = [] for face in face_list: f_pyptlist = fetch.points_frm_occface(face) f_pyptlist.reverse() if len(f_pyptlist) == 3: index_list = [] for fp in f_pyptlist: p_index = pyptlist.index(fp) index_list.append(p_index) face_index_2dlsit.append(index_list) elif len(f_pyptlist) > 3: print "THE FACE HAS THE WRONG NUMBER OF VERTICES, IT HAS:", len(f_pyptlist), "VERTICES" tri_faces = construct.simple_mesh(face) for tri_face in tri_faces: tps = fetch.points_frm_occface(tri_face) index_list = [] for tp in tps: p_index = pyptlist.index(tp) index_list.append(p_index) face_index_2dlsit.append(index_list) # else: # print "THE FACE HAS THE WRONG NUMBER OF VERTICES, IT HAS:", len(f_pyptlist), "VERTICES" faces = np.array(face_index_2dlsit) shape_mesh = mesh.Mesh(np.zeros(faces.shape[0], dtype = mesh.Mesh.dtype)) for i, f in enumerate(faces): for j in range(3): shape_mesh.vectors[i][j] = vertices[f[j],:] shape_mesh.save(stl_filepath)
def generate_falsecolour_bar(minval, maxval, unit_str, bar_length, description_str=None, bar_pos=(0, 0, 0), inverse=False): """ This function constructs a falsecolour diagram. Parameters ---------- minval : float The minimum value of the falsecolour bar. maxval : float The maximum value of the falsecolour bar. unit_str : str The string of the unit to be displayed on the bar. bar_length : float The length of the falsecolour bar. description_str : str, optional Description for the falsecolour bar, Default = None. bar_pos : tuple of floats, optional The position of the bar, Default = (0,0,0). inverse : bool False for red being max, True for blue being maximum. Returns ------- falsecolour bar : list of OCCfaces The falsecolor bar which is a list of OCCfaces. bar colour : list of tuple of floats Each tuple is a r,g,b that is specifying the colour of the bar. geometries of text: OCCcompound The geometries of the text. str_colour_list : list of tuple of floats Each tuple is a r,g,b that is specifying the colour of the string. value of each falsecolour : list of floats The value of each falsecolour. """ import numpy interval = 10.0 xdim = bar_length / interval ydim = bar_length rectangle = construct.make_rectangle(xdim, ydim) rec_mid_pt = calculate.face_midpt(rectangle) moved_rectangle = fetch.topo2topotype( modify.move(rec_mid_pt, bar_pos, rectangle)) grid_srfs = construct.grid_face(moved_rectangle, xdim, xdim) #generate uniform results between max and min inc1 = (maxval - minval) / (interval) value_range = list(numpy.arange(minval, maxval + 0.1, inc1)) inc2 = inc1 / 2.0 value_range_midpts = list(numpy.arange(minval + inc2, maxval, inc1)) bar_colour = falsecolour(value_range_midpts, minval, maxval, inverse=inverse) grid_srfs2 = [] moved_str_face_list = [] srf_cnt = 0 for srf in grid_srfs: reversed_srf = modify.reverse_face(srf) grid_srfs2.append(reversed_srf) res_label = round(value_range[srf_cnt], 2) brep_str = fetch.topo2topotype( construct.make_brep_text(str(res_label), xdim / 2)) orig_pt = calculate.get_centre_bbox(brep_str) loc_pt = calculate.face_midpt(srf) loc_pt = modify.move_pt(loc_pt, (1, -0.3, 0), xdim * 1.2) moved_str = modify.move(orig_pt, loc_pt, brep_str) moved_str_face_list.append(moved_str) if srf_cnt == len(grid_srfs) - 1: res_label = round(value_range[srf_cnt + 1], 2) brep_str = fetch.topo2topotype( construct.make_brep_text(str(res_label), xdim / 2)) orig_pt = calculate.get_centre_bbox(brep_str) loc_pt3 = modify.move_pt(loc_pt, (0, 1, 0), xdim) moved_str = modify.move(orig_pt, loc_pt3, brep_str) moved_str_face_list.append(moved_str) brep_str_unit = construct.make_brep_text(str(unit_str), xdim) orig_pt2 = calculate.get_centre_bbox(brep_str_unit) loc_pt2 = modify.move_pt(loc_pt, (0, 1, 0), xdim * 2) moved_str = modify.move(orig_pt2, loc_pt2, brep_str_unit) moved_str_face_list.append(moved_str) if description_str != None: if srf_cnt == 0: d_str = fetch.topo2topotype( construct.make_brep_text(description_str, xdim / 2)) orig_pt2 = calculate.get_centre_bbox(d_str) loc_pt2 = modify.move_pt(loc_pt, (0, -1, 0), xdim * 5) moved_str = modify.move(orig_pt2, loc_pt2, d_str) moved_str_face_list.append(moved_str) srf_cnt += 1 cmpd = construct.make_compound(moved_str_face_list) face_list = fetch.topo_explorer(cmpd, "face") meshed_list = [] for face in face_list: meshed_face_list = construct.simple_mesh(face) mface = construct.make_shell(meshed_face_list) face_mid_pt = calculate.face_midpt(face) str_mid_pt = calculate.get_centre_bbox(mface) moved_mface = modify.move(str_mid_pt, face_mid_pt, mface) meshed_list.append(moved_mface) meshed_str_cmpd = construct.make_compound(meshed_list) str_colour_list = [(0, 0, 0)] return grid_srfs2, bar_colour, meshed_str_cmpd, str_colour_list, value_range_midpts
def write_2_stl2(occtopology, stl_filepath, is_meshed=True, linear_deflection=0.8, angle_deflection=0.5): """ This function writes a 3D model into STL format. This is different from write2stl as it uses the numpy-stl library. Parameters ---------- occtopology : OCCtopology Geometries to be written into STL. OCCtopology includes: OCCshape, OCCcompound, OCCcompsolid, OCCsolid, OCCshell, OCCface, OCCwire, OCCedge, OCCvertex stl_filepath : str The file path of the STL file. mesh_incremental_float : float, optional Default = 0.8. Returns ------- None : None The geometries are written to a STL file. """ import numpy as np from stl import mesh if is_meshed == False: tri_faces = construct.simple_mesh(occtopology, linear_deflection=linear_deflection, angle_deflection=angle_deflection) occtopology = construct.make_compound(tri_faces) face_list = fetch.topo_explorer(occtopology, "face") vlist = fetch.topo_explorer(occtopology, "vertex") occptlist = modify.occvertex_list_2_occpt_list(vlist) pyptlist = modify.occpt_list_2_pyptlist(occptlist) pyptlist = modify.rmv_duplicated_pts(pyptlist) vertices = np.array(pyptlist) face_index_2dlsit = [] for face in face_list: f_pyptlist = fetch.points_frm_occface(face) f_pyptlist.reverse() if len(f_pyptlist) == 3: index_list = [] for fp in f_pyptlist: p_index = pyptlist.index(fp) index_list.append(p_index) face_index_2dlsit.append(index_list) elif len(f_pyptlist) > 3: print "THE FACE HAS THE WRONG NUMBER OF VERTICES, IT HAS:", len( f_pyptlist), "VERTICES" tri_faces = construct.simple_mesh(face) for tri_face in tri_faces: tps = fetch.points_frm_occface(tri_face) index_list = [] for tp in tps: p_index = pyptlist.index(tp) index_list.append(p_index) face_index_2dlsit.append(index_list) # else: # print "THE FACE HAS THE WRONG NUMBER OF VERTICES, IT HAS:", len(f_pyptlist), "VERTICES" faces = np.array(face_index_2dlsit) shape_mesh = mesh.Mesh(np.zeros(faces.shape[0], dtype=mesh.Mesh.dtype)) for i, f in enumerate(faces): for j in range(3): shape_mesh.vectors[i][j] = vertices[f[j], :] shape_mesh.save(stl_filepath)
def occtopo_2_collada(dae_filepath, occface_list=None, face_rgb_colour_list=None, occedge_list=None): """ This function converts OCCtopologies into a pycollada Collada class. The units are in meter. Parameters ---------- occface_list : list of OCCfaces The geometries to be visualised with the results. The list of geometries must correspond to the list of results. Other OCCtopologies are also accepted, but the OCCtopology must contain OCCfaces. OCCtopology includes: OCCshape, OCCcompound, OCCcompsolid, OCCsolid, OCCshell, OCCface. dae_filepath : str The file path of the DAE (Collada) file. face_rgb_colour_list : list of tuple of floats, optional Each tuple is a r,g,b that is specifying the colour of the face. The number of colours must correspond to the number of OCCfaces. occedge_list : list of OCCedges, optional OCCedges to be visualised together, Default = None. Returns ------- mesh : pycollada Collada class object The collada object from pycollada library. """ import collada from collada import asset, material, source, geometry, scene import numpy mesh = collada.Collada() mesh.assetInfo.upaxis = asset.UP_AXIS.Z_UP mesh.assetInfo.unitmeter = 1.0 mesh.assetInfo.unitname = "meter" if face_rgb_colour_list != None: mat_list = [] colour_cnt = 0 for rgb_colour in face_rgb_colour_list: effect = material.Effect("effect" + str(colour_cnt), [], "phong", diffuse=rgb_colour, specular=rgb_colour, double_sided=True) mat = material.Material("material" + str(colour_cnt), "mymaterial" + str(colour_cnt), effect) mesh.effects.append(effect) mesh.materials.append(mat) mat_list.append(mat) colour_cnt += 1 else: effect = material.Effect("effect0", [], "phong", diffuse=(1, 1, 1), specular=(1, 1, 1)) mat = material.Material("material0", "mymaterial", effect) mesh.effects.append(effect) mesh.materials.append(mat) edgeeffect = material.Effect("edgeeffect0", [], "phong", diffuse=(1, 1, 1), specular=(1, 1, 1), double_sided=True) edgemat = material.Material("edgematerial0", "myedgematerial", effect) mesh.effects.append(edgeeffect) mesh.materials.append(edgemat) geomnode_list = [] shell_cnt = 0 if occface_list: for occshell in occface_list: vert_floats = [] normal_floats = [] vcnt = [] indices = [] face_list = fetch.topo_explorer(occshell, "face") vert_cnt = 0 for face in face_list: wire_list = fetch.topo_explorer(face, "wire") nwire = len(wire_list) if nwire == 1: pyptlist = fetch.points_frm_occface(face) vcnt.append(len(pyptlist)) face_nrml = calculate.face_normal(face) pyptlist.reverse() for pypt in pyptlist: vert_floats.append(pypt[0]) vert_floats.append(pypt[1]) vert_floats.append(pypt[2]) normal_floats.append(face_nrml[0]) normal_floats.append(face_nrml[1]) normal_floats.append(face_nrml[2]) indices.append(vert_cnt) vert_cnt += 1 if nwire > 1: tri_face_list = construct.simple_mesh(face) for tface in tri_face_list: pyptlist = fetch.points_frm_occface(tface) vcnt.append(len(pyptlist)) face_nrml = calculate.face_normal(tface) pyptlist.reverse() for pypt in pyptlist: vert_floats.append(pypt[0]) vert_floats.append(pypt[1]) vert_floats.append(pypt[2]) normal_floats.append(face_nrml[0]) normal_floats.append(face_nrml[1]) normal_floats.append(face_nrml[2]) indices.append(vert_cnt) vert_cnt += 1 vert_id = "ID" + str(shell_cnt) + "1" vert_src = source.FloatSource(vert_id, numpy.array(vert_floats), ('X', 'Y', 'Z')) normal_id = "ID" + str(shell_cnt) + "2" normal_src = source.FloatSource(normal_id, numpy.array(normal_floats), ('X', 'Y', 'Z')) geom = geometry.Geometry(mesh, "geometry" + str(shell_cnt), "geometry" + str(shell_cnt), [vert_src, normal_src]) input_list = source.InputList() input_list.addInput(0, 'VERTEX', "#" + vert_id) #input_list.addInput(1, 'NORMAL', "#"+normal_id) vcnt = numpy.array(vcnt) indices = numpy.array(indices) if face_rgb_colour_list != None: mat_name = "materialref" + str(shell_cnt) polylist = geom.createPolylist(indices, vcnt, input_list, mat_name) geom.primitives.append(polylist) mesh.geometries.append(geom) matnode = scene.MaterialNode(mat_name, mat_list[shell_cnt], inputs=[]) geomnode = scene.GeometryNode(geom, [matnode]) geomnode_list.append(geomnode) else: mat_name = "materialref" polylist = geom.createPolylist(indices, vcnt, input_list, mat_name) geom.primitives.append(polylist) mesh.geometries.append(geom) matnode = scene.MaterialNode(mat_name, mat, inputs=[]) geomnode = scene.GeometryNode(geom, [matnode]) geomnode_list.append(geomnode) shell_cnt += 1 if occedge_list: edge_cnt = 0 for occedge in occedge_list: vert_floats = [] indices = [] pypt_list = fetch.points_frm_edge(occedge) if len(pypt_list) == 2: vert_cnt = 0 for pypt in pypt_list: vert_floats.append(pypt[0]) vert_floats.append(pypt[1]) vert_floats.append(pypt[2]) indices.append(vert_cnt) vert_cnt += 1 vert_id = "ID" + str(edge_cnt + shell_cnt) + "1" vert_src = source.FloatSource(vert_id, numpy.array(vert_floats), ('X', 'Y', 'Z')) geom = geometry.Geometry( mesh, "geometry" + str(edge_cnt + shell_cnt), "geometry" + str(edge_cnt + shell_cnt), [vert_src]) input_list = source.InputList() input_list.addInput(0, 'VERTEX', "#" + vert_id) indices = numpy.array(indices) mat_name = "edgematerialref" linelist = geom.createLineSet(indices, input_list, mat_name) geom.primitives.append(linelist) mesh.geometries.append(geom) matnode = scene.MaterialNode(mat_name, edgemat, inputs=[]) geomnode = scene.GeometryNode(geom, [matnode]) geomnode_list.append(geomnode) edge_cnt += 1 vis_node = scene.Node("node0", children=geomnode_list) myscene = scene.Scene("myscene", [vis_node]) mesh.scenes.append(myscene) mesh.scene = myscene return mesh
def write_2_collada(dae_filepath, occface_list=None, face_rgb_colour_list=None, occedge_list=None, text_string=None): """ This function writes a 3D model into a Collada file. Parameters ---------- dae_filepath : str The file path of the DAE (Collada) file. occface_list : list of OCCfaces, optional The geometries to be visualised with the results. The list of geometries must correspond to the list of results. Other OCCtopologies are also accepted, but the OCCtopology must contain OCCfaces. OCCtopology includes: OCCshape, OCCcompound, OCCcompsolid, OCCsolid, OCCshell, OCCface. face_rgb_colour_list : list of tuple of floats, optional Each tuple is a r,g,b that is specifying the colour of the face,Default = None. The number of colours must correspond to the number of OCCfaces. occedge_list : list of OCCedges, optional OCCedges to be visualised together, Default = None. text_string : str, optional Description for the 3D model, Default = None. Returns ------- None : None The geometries are written to a DAE file. """ if text_string != None: if occface_list != None: overall_cmpd = construct.make_compound(occface_list) else: overall_cmpd = construct.make_compound(occedge_list) occface_list = [] xmin, ymin, zmin, xmax, ymax, zmax = calculate.get_bounding_box( overall_cmpd) xdim = xmax - xmin d_str = fetch.topo2topotype( construct.make_brep_text(text_string, xdim / 10)) xmin1, ymin1, zmin1, xmax1, ymax1, zmax1 = calculate.get_bounding_box( d_str) corner_pt = (xmin1, ymax1, zmin1) corner_pt2 = (xmin, ymin, zmin) moved_str = modify.move(corner_pt, corner_pt2, d_str) face_list = fetch.topo_explorer(moved_str, "face") meshed_list = [] for face in face_list: meshed_face_list = construct.simple_mesh(face) mface = construct.make_shell(meshed_face_list) face_mid_pt = calculate.face_midpt(face) str_mid_pt = calculate.get_centre_bbox(mface) moved_mface = modify.move(str_mid_pt, face_mid_pt, mface) meshed_list.append(moved_mface) meshed_str_cmpd = construct.make_compound(meshed_list) occface_list.append(meshed_str_cmpd) if face_rgb_colour_list != None: face_rgb_colour_list.append((0, 0, 0)) mesh = occtopo_2_collada(dae_filepath, occface_list=occface_list, face_rgb_colour_list=face_rgb_colour_list, occedge_list=occedge_list) mesh.write(dae_filepath)
def flatten_shell_z_value(occshell, z=0): """ This function flatten the OCCshell to the Z-value specified. Parameters ---------- occshell : OCCshell The OCCshell to be flattened. z : float, optional The Z-value to flatten to. Default = 0. Returns ------- flatten shell : OCCshell The flatten OCCshell. """ face_list = fetch.faces_frm_solid(occshell) xmin, ymin, zmin, xmax, ymax, zmax = calculate.get_bounding_box(occshell) boundary_pyptlist = [[xmin, ymin, zmin], [xmax, ymin, zmin], [xmax, ymax, zmin], [xmin, ymax, zmin]] boundary_face = construct.make_polygon(boundary_pyptlist) b_mid_pt = calculate.face_midpt(boundary_face) #flatten_shell = fetch.topo2topotype(uniform_scale(occshell, 1, 1, 0, b_mid_pt)) face_list = construct.simple_mesh(occshell) f_face_list = [] for occface in face_list: f_face = flatten_face_z_value(occface, z=zmin) f_face_list.append(f_face) face_list = f_face_list flatten_shell = construct.make_compound(face_list) nfaces = len(face_list) merged_faces = construct.merge_faces(face_list) dest_pt = [b_mid_pt[0], b_mid_pt[1], z] #depending on how complicated is the shell we decide which is the best way to flatten it #1.) if it is an open shell and when everything is flatten it fits nicely as a flat surface if len(merged_faces) == 1: m_area = calculate.face_area(merged_faces[0]) if m_area > 1e-06: flatten_face = fetch.topo2topotype( move(b_mid_pt, dest_pt, merged_faces[0])) return flatten_face #2.) if it is a complex shell with less than 500 faces we fused and create a single surface if nfaces < 50: try: fused_shape = None fcnt = 0 for face in face_list: face_area = calculate.face_area(face) if not face_area < 0.001: if fcnt == 0: fused_shape = face else: #construct.visualise([[fused_shape], [face]], ['WHITE', 'RED']) fused_shape = construct.boolean_fuse(fused_shape, face) fcnt += 1 if fused_shape != None: fused_face_list = fetch.topo_explorer(fused_shape, "face") merged_faces = construct.merge_faces(fused_face_list) if len(merged_faces) == 1: flatten_face = fetch.topo2topotype( move(b_mid_pt, dest_pt, merged_faces[0])) return flatten_face else: flatten_vertex = fetch.topo_explorer( flatten_shell, "vertex") flatten_pts = modify.occvertex_list_2_occpt_list( flatten_vertex) flatten_pypts = modify.occpt_list_2_pyptlist(flatten_pts) dface_list = construct.delaunay3d(flatten_pypts) merged_faces = construct.merge_faces(dface_list) if len(merged_faces) == 1: flatten_face = fetch.topo2topotype( move(b_mid_pt, dest_pt, merged_faces[0])) return flatten_face else: #construct.visualise([[occshell]],["WHITE"]) return None except RuntimeError: flatten_vertex = fetch.topo_explorer(flatten_shell, "vertex") flatten_pts = modify.occvertex_list_2_occpt_list(flatten_vertex) flatten_pypts = modify.occpt_list_2_pyptlist(flatten_pts) dface_list = construct.delaunay3d(flatten_pypts) merged_faces = construct.merge_faces(dface_list) if len(merged_faces) == 1: flatten_face = fetch.topo2topotype( move(b_mid_pt, dest_pt, merged_faces[0])) return flatten_face else: #construct.visualise([[occshell]],["WHITE"]) return None #3.) if it is a complex shell with more than 500 faces we get the vertexes and create a triangulated srf with delaunay #and merge all the faces to make a single surface if nfaces >= 50: flatten_vertex = fetch.topo_explorer(flatten_shell, "vertex") flatten_pts = modify.occvertex_list_2_occpt_list(flatten_vertex) flatten_pypts = modify.occpt_list_2_pyptlist(flatten_pts) #flatten_pypts = rmv_duplicated_pts_by_distance(flatten_pypts, tolerance = 1e-04) dface_list = construct.delaunay3d(flatten_pypts) merged_faces = construct.merge_faces(dface_list) if len(merged_faces) == 1: flatten_face = fetch.topo2topotype( move(b_mid_pt, dest_pt, merged_faces[0])) return flatten_face else: #construct.visualise([[occshell]],["WHITE"]) return None
def flatten_shell_z_value(occshell, z=0): #face_list = fetch.faces_frm_solid(occshell) xmin, ymin, zmin, xmax, ymax, zmax = calculate.get_bounding_box(occshell) boundary_pyptlist = [[xmin, ymin, zmin], [xmax, ymin, zmin], [xmax, ymax, zmin], [xmin, ymax, zmin]] boundary_face = construct.make_polygon(boundary_pyptlist) b_mid_pt = calculate.face_midpt(boundary_face) flatten_shell = fetch.shape2shapetype( uniform_scale(occshell, 1, 1, 0, b_mid_pt)) face_list = construct.simple_mesh(flatten_shell) #face_list = fetch.geom_explorer(flatten_shell,"face") nfaces = len(face_list) merged_faces = construct.merge_faces(face_list) dest_pt = [b_mid_pt[0], b_mid_pt[1], z] #depending on how complicated is the shell we decide which is the best way to flatten it #1.) if it is an open shell and when everything is flatten it fits nicely as a flat surface if len(merged_faces) == 1: flatten_face = fetch.shape2shapetype( move(b_mid_pt, dest_pt, merged_faces[0])) return flatten_face #2.) if it is a complex shell with less than 500 faces we fused and create a single surface if nfaces < 50: try: fused_shape = None fcnt = 0 for face in face_list: face_area = calculate.face_area(face) if not face_area < 0.001: if fcnt == 0: fused_shape = face else: #construct.visualise([[fused_shape], [face]], ['WHITE', 'RED']) fused_shape = construct.boolean_fuse(fused_shape, face) fcnt += 1 if fused_shape != None: fused_face_list = fetch.geom_explorer(fused_shape, "face") merged_faces = construct.merge_faces(fused_face_list) if len(merged_faces) == 1: flatten_face = fetch.shape2shapetype( move(b_mid_pt, dest_pt, merged_faces[0])) return flatten_face else: flatten_vertex = fetch.geom_explorer( flatten_shell, "vertex") flatten_pts = fetch.vertex_list_2_point_list( flatten_vertex) flatten_pypts = fetch.occptlist2pyptlist(flatten_pts) dface_list = construct.delaunay3d(flatten_pypts) merged_faces = construct.merge_faces(dface_list) if len(merged_faces) == 1: flatten_face = fetch.shape2shapetype( move(b_mid_pt, dest_pt, merged_faces[0])) return flatten_face else: #construct.visualise([[occshell]],["WHITE"]) return None except RuntimeError: flatten_vertex = fetch.geom_explorer(flatten_shell, "vertex") flatten_pts = fetch.vertex_list_2_point_list(flatten_vertex) flatten_pypts = fetch.occptlist2pyptlist(flatten_pts) dface_list = construct.delaunay3d(flatten_pypts) merged_faces = construct.merge_faces(dface_list) if len(merged_faces) == 1: flatten_face = fetch.shape2shapetype( move(b_mid_pt, dest_pt, merged_faces[0])) return flatten_face else: #construct.visualise([[occshell]],["WHITE"]) return None #3.) if it is a complex shell with more than 500 faces we get the vertexes and create a triangulated srf with delaunay #and merge all the faces to make a single surface if nfaces >= 50: flatten_vertex = fetch.geom_explorer(flatten_shell, "vertex") flatten_pts = fetch.vertex_list_2_point_list(flatten_vertex) flatten_pypts = fetch.occptlist2pyptlist(flatten_pts) #flatten_pypts = rmv_duplicated_pts_by_distance(flatten_pypts, tolerance = 1e-04) dface_list = construct.delaunay3d(flatten_pypts) merged_faces = construct.merge_faces(dface_list) if len(merged_faces) == 1: flatten_face = fetch.shape2shapetype( move(b_mid_pt, dest_pt, merged_faces[0])) return flatten_face else: #construct.visualise([[occshell]],["WHITE"]) return None
def flatten_shell_z_value(occshell, z=0): """ This function flatten the OCCshell to the Z-value specified. Parameters ---------- occshell : OCCshell The OCCshell to be flattened. z : float, optional The Z-value to flatten to. Default = 0. Returns ------- flatten shell : OCCshell The flatten OCCshell. """ face_list = fetch.faces_frm_solid(occshell) xmin,ymin,zmin,xmax,ymax,zmax = calculate.get_bounding_box(occshell) boundary_pyptlist = [[xmin,ymin,zmin], [xmax,ymin,zmin], [xmax,ymax,zmin], [xmin,ymax,zmin]] boundary_face = construct.make_polygon(boundary_pyptlist) b_mid_pt = calculate.face_midpt(boundary_face) #flatten_shell = fetch.topo2topotype(uniform_scale(occshell, 1, 1, 0, b_mid_pt)) face_list = construct.simple_mesh(occshell) f_face_list = [] for occface in face_list: f_face = flatten_face_z_value(occface, z=zmin) f_face_list.append(f_face) face_list = f_face_list flatten_shell = construct.make_compound(face_list) nfaces = len(face_list) merged_faces = construct.merge_faces(face_list) dest_pt = [b_mid_pt[0], b_mid_pt[1], z] #depending on how complicated is the shell we decide which is the best way to flatten it #1.) if it is an open shell and when everything is flatten it fits nicely as a flat surface if len(merged_faces) == 1: m_area = calculate.face_area(merged_faces[0]) if m_area > 1e-06: flatten_face = fetch.topo2topotype(move(b_mid_pt, dest_pt,merged_faces[0])) return flatten_face #2.) if it is a complex shell with less than 500 faces we fused and create a single surface if nfaces < 50: try: fused_shape = None fcnt = 0 for face in face_list: face_area = calculate.face_area(face) if not face_area < 0.001: if fcnt == 0: fused_shape = face else: #construct.visualise([[fused_shape], [face]], ['WHITE', 'RED']) fused_shape = construct.boolean_fuse(fused_shape, face) fcnt+=1 if fused_shape!=None: fused_face_list = fetch.topo_explorer(fused_shape, "face") merged_faces = construct.merge_faces(fused_face_list) if len(merged_faces) == 1: flatten_face = fetch.topo2topotype(move(b_mid_pt, dest_pt,merged_faces[0])) return flatten_face else: flatten_vertex = fetch.topo_explorer(flatten_shell,"vertex") flatten_pts = modify.occvertex_list_2_occpt_list(flatten_vertex) flatten_pypts = modify.occpt_list_2_pyptlist(flatten_pts) dface_list = construct.delaunay3d(flatten_pypts) merged_faces = construct.merge_faces(dface_list) if len(merged_faces) == 1: flatten_face = fetch.topo2topotype(move(b_mid_pt, dest_pt,merged_faces[0])) return flatten_face else: #construct.visualise([[occshell]],["WHITE"]) return None except RuntimeError: flatten_vertex = fetch.topo_explorer(flatten_shell,"vertex") flatten_pts = modify.occvertex_list_2_occpt_list(flatten_vertex) flatten_pypts = modify.occpt_list_2_pyptlist(flatten_pts) dface_list = construct.delaunay3d(flatten_pypts) merged_faces = construct.merge_faces(dface_list) if len(merged_faces) == 1: flatten_face = fetch.topo2topotype(move(b_mid_pt, dest_pt,merged_faces[0])) return flatten_face else: #construct.visualise([[occshell]],["WHITE"]) return None #3.) if it is a complex shell with more than 500 faces we get the vertexes and create a triangulated srf with delaunay #and merge all the faces to make a single surface if nfaces >=50: flatten_vertex = fetch.topo_explorer(flatten_shell,"vertex") flatten_pts = modify.occvertex_list_2_occpt_list(flatten_vertex) flatten_pypts = modify.occpt_list_2_pyptlist(flatten_pts) #flatten_pypts = rmv_duplicated_pts_by_distance(flatten_pypts, tolerance = 1e-04) dface_list = construct.delaunay3d(flatten_pypts) merged_faces = construct.merge_faces(dface_list) if len(merged_faces) == 1: flatten_face = fetch.topo2topotype(move(b_mid_pt, dest_pt,merged_faces[0])) return flatten_face else: #construct.visualise([[occshell]],["WHITE"]) return None