def cart3d_to_stl(cart3d, stl_filename=None, is_binary=False, log=None, debug=False): """ Converts a Cart3D object to STL format. Parameters ---------- cart3d : Cart3D() a Cart3D object stl_filename : str; default=None path to the output STL file (or None to skip) log : log a logger object (or None) debug : bool; default=False True/False (used if log is not defined) Returns ------- stl : STL() an STL object """ #normals = cart3d.get_normals() stl = STL(log=log, debug=debug) stl.nodes = cart3d.nodes - 1 stl.elements = cart3d.elements - 1 if stl_filename: stl.write_stl(stl_filename, is_binary=is_binary) return stl
def nastran_to_stl(bdf_filename, stl_filename, is_binary=False, log=None): """ Converts a Nastran model to an STL Parameters ---------- bdf_filename : varies str : the path to a BDF input file BDF() : a BDF() model object stl_filename : str the output STL path is_binary : bool; default=False should the output file be binary """ if isinstance(bdf_filename, str): model = read_bdf(bdf_filename, log=None) else: model = bdf_filename #log.info('card_count = %s' % model.card_count) nnodes = len(model.nodes) nodes = zeros((nnodes, 3), dtype='float64') elements = [] i = 0 nodeid_to_i_map = {} for node_id, node in sorted(iteritems(model.nodes)): xyz = node.get_position() nodes[i, :] = xyz nodeid_to_i_map[node_id] = i i += 1 assert len(model.nodes) == i, 'model.nodes=%s i=%s' % (len(model.nodes), i) for eid, element in sorted(iteritems(model.elements)): if element.type in ['CQUADR']: continue elif element.type in ['CBAR', 'CBEAM', 'CONM2', 'RBE2', 'RBE3', 'CBUSH', 'CBUSH1D', 'CBUSH2D', 'CONROD', 'CROD', 'CELAS1', 'CELAS2', 'CELAS3', 'CELAS4', 'CDAMP1', 'CDAMP2', 'CDAMP3', 'CDAMP4',]: continue elif element.type in ['CQUAD4']: n1, n2, n3, n4 = element.node_ids i1, i2, i3, i4 = nodeid_to_i_map[n1], nodeid_to_i_map[n2], nodeid_to_i_map[n3], nodeid_to_i_map[n4] elements.append([i1, i2, i3]) elements.append([i3, i4, i1]) elif element.type in ['CTRIA3', 'CTRIAR']: n1, n2, n3 = element.node_ids i1, i2, i3 = nodeid_to_i_map[n1], nodeid_to_i_map[n2], nodeid_to_i_map[n3] elements.append([i1, i2, i3]) else: print(element.type) elements = array(elements, dtype='int32') stl = STL() stl.nodes = nodes stl.elements = elements stl.write_stl(stl_filename, is_binary=is_binary) return stl
def cart3d_to_stl(cart3d, stl_filename=None, is_binary=False, log=None, debug=False): """ Converts a Cart3D object to STL format. Parameters ---------- cart3d : Cart3D() a Cart3D object stl_filename : str; default=None path to the output STL file (or None to skip) log : log a logger object (or None) debug : bool; default=False True/False (used if log is not defined) Returns ------- stl : STL() an STL object .. todo:: this seems to be broken... """ #normals = cart3d.get_normals() stl = STL(log=log, debug=debug) stl.nodes = cart3d.nodes #- 1 stl.elements = cart3d.elements #- 1 assert stl.elements.min() == 0, stl.elements.min() if stl_filename: stl.write_stl(stl_filename, is_binary=is_binary) return stl
def merge_stl_files(stl_filenames, stl_out_filename=None, remove_bad_elements=False, is_binary=True, float_fmt='%6.12f'): """ Combines multiple STLs into a single file Parameters ---------- stl_filenames : List[str, str, ...] list of stl filenames or a string filename (useful for removing bad elements) remove_bad_elements : bool; default=False should elements with invalid normals be removed? stl_out_filename : str; default=None -> no writing string of stl output filename is_binary : bool; default=True should the output file be binary float_fmt : str; default='%6.12f' the ascii float format Returns ------- stl : STL() the stl object """ if isinstance(stl_filenames, str): stl_filenames = [stl_filenames] assert isinstance(stl_filenames, (list, tuple)), type(stl_filenames) assert len(stl_filenames) > 0, stl_filenames if len(stl_filenames) == 1: model = STL() model.read_stl(stl_filenames[0]) if remove_bad_elements: model.remove_elements_with_bad_normals(model.elements, nodes=model.nodes) if stl_out_filename is not None: model.write_stl(stl_out_filename, is_binary=is_binary) return model nodes = [] elements = [] n0 = 0 for fname in stl_filenames: model = STL() # TODO: you shouldn't need to to reinstantiate the STL model.read_stl(fname) nnodes = model.nodes.shape[0] nodes.append(model.nodes) elements.append(model.elements + n0) n0 += nnodes model.nodes = vstack(nodes) model.elements = vstack(elements) if remove_bad_elements: model.remove_elements_with_bad_normals(model.elements, nodes=model.nodes) if stl_out_filename is not None: model.write_stl(stl_out_filename, is_binary=is_binary, float_fmt=float_fmt) return model
def nastran_to_stl(model, stl_filename, is_binary=False): #log.info('card_count = %s' % model.card_count) nnodes = len(model.nodes) nodes = zeros((nnodes, 3), dtype='float64') elements = [] i = 0 nodeid_to_i_map = {} for node_id, node in sorted(iteritems(model.nodes)): xyz = node.get_position() nodes[i, :] = xyz nodeid_to_i_map[node_id] = i i += 1 assert len(model.nodes) == i, 'model.nodes=%s i=%s' % (len(model.nodes), i) for eid, element in sorted(iteritems(model.elements)): if element.type in ['CQUADR']: continue elif element.type in ['CBAR', 'CBEAM', 'CONM2', 'RBE2', 'RBE3', 'CBUSH', 'CBUSH1D', 'CBUSH2D', 'CONROD', 'CROD', 'CELAS1', 'CELAS2', 'CELAS3', 'CELAS4', 'CDAMP1', 'CDAMP2', 'CDAMP3', 'CDAMP4',]: continue elif element.type in ['CQUAD4']: n1, n2, n3, n4 = element.node_ids i1, i2, i3, i4 = nodeid_to_i_map[n1], nodeid_to_i_map[n2], nodeid_to_i_map[n3], nodeid_to_i_map[n4] elements.append([i1, i2, i3]) elements.append([i3, i4, i1]) elif element.type in ['CTRIA3', 'CTRIAR']: n1, n2, n3 = element.node_ids i1, i2, i3 = nodeid_to_i_map[n1], nodeid_to_i_map[n2], nodeid_to_i_map[n3] elements.append([i1, i2, i3]) else: print(element.type) elements = array(elements, dtype='int32') stl = STL() stl.nodes = nodes stl.elements = elements stl.write_stl(stl_filename, is_binary=is_binary) return stl
def main(): # pragma: no cover import os #base = 'gear' #read_tetgen(base, dimension_flag=2) #return from pyNastran.converters.stl.stl import STL m1 = STL() m1.read_stl('tetgen_test.stl') m1.flip_normals() m1.write_stl('tetgen_test_flipped.stl') del m1 os.system('tetgen.exe -pqcvVqY tetgen_test_flipped.stl') m = Tetgen() base = 'tetgen_test_flipped.1' m.read_tetgen(base + '.node', base + '.smesh', base + '.ele', dimension_flag=3) m.write_nastran(base + '.bdf')
def nastran_to_stl(bdf_filename, stl_filename, is_binary=False, log=None, stop_on_failure=False): """ Converts a Nastran model to an STL Parameters ---------- bdf_filename : varies str : the path to a BDF input file BDF() : a BDF() model object stl_filename : str the output STL path is_binary : bool; default=False should the output file be binary log : Logger() a Python logging object stop_on_failure : bool; default=False should the code stop if an error is encountered """ if isinstance(bdf_filename, str): model = read_bdf(bdf_filename, log=log) else: model = bdf_filename #log.info('card_count = %s' % model.card_count) nnodes = len(model.nodes) nodes = np.zeros((nnodes, 3), dtype='float64') elements = [] i = 0 nodeid_to_i_map = {} offset = False if offset: nid = list(model.nodes.keys())[0] xyz0 = model.nodes[nid].get_position() else: xyz0 = np.zeros(3, dtype='float64') for node_id, node in sorted(model.nodes.items()): xyz = node.get_position() nodes[i, :] = xyz - xyz0 nodeid_to_i_map[node_id] = i i += 1 assert len(model.nodes) == i, 'model.nodes=%s i=%s' % (len(model.nodes), i) for unused_eid, element in sorted(model.elements.items()): if element.type in ['CQUADR']: continue elif element.type in [ 'CBAR', 'CBEAM', 'CONM2', 'RBE2', 'RBE3', 'CBUSH', 'CBUSH1D', 'CBUSH2D', 'CONROD', 'CROD', 'CELAS1', 'CELAS2', 'CELAS3', 'CELAS4', 'CDAMP1', 'CDAMP2', 'CDAMP3', 'CDAMP4', ]: continue elif element.type in ['CQUAD4']: n1, n2, n3, n4 = element.node_ids i1, i2, i3, i4 = (nodeid_to_i_map[n1], nodeid_to_i_map[n2], nodeid_to_i_map[n3], nodeid_to_i_map[n4]) elements.append([i1, i2, i3]) elements.append([i3, i4, i1]) elif element.type in ['CTRIA3', 'CTRIAR']: nids = element.node_ids unids = np.unique(nids) if len(unids) == 2: continue n1, n2, n3 = nids i1, i2, i3 = nodeid_to_i_map[n1], nodeid_to_i_map[ n2], nodeid_to_i_map[n3] elements.append([i1, i2, i3]) else: model.log.warning('skipping %s' % element.type) elements = np.array(elements, dtype='int32') stl = STL(log=model.log) stl.nodes = nodes #stl.nodes -= nodes[0, :] stl.elements = elements stl.write_stl(stl_filename, is_binary=is_binary, stop_on_failure=stop_on_failure) return stl
def nastran_to_stl(bdf_filename, stl_filename, is_binary=False, log=None): """ Converts a Nastran model to an STL Parameters ---------- bdf_filename : varies str : the path to a BDF input file BDF() : a BDF() model object stl_filename : str the output STL path is_binary : bool; default=False should the output file be binary log : Logger() a Python logging object """ if isinstance(bdf_filename, str): model = read_bdf(bdf_filename, log=log) else: model = bdf_filename #log.info('card_count = %s' % model.card_count) nnodes = len(model.nodes) nodes = zeros((nnodes, 3), dtype='float64') elements = [] i = 0 nodeid_to_i_map = {} for node_id, node in sorted(iteritems(model.nodes)): xyz = node.get_position() nodes[i, :] = xyz nodeid_to_i_map[node_id] = i i += 1 assert len(model.nodes) == i, 'model.nodes=%s i=%s' % (len(model.nodes), i) for eid, element in sorted(iteritems(model.elements)): if element.type in ['CQUADR']: continue elif element.type in [ 'CBAR', 'CBEAM', 'CONM2', 'RBE2', 'RBE3', 'CBUSH', 'CBUSH1D', 'CBUSH2D', 'CONROD', 'CROD', 'CELAS1', 'CELAS2', 'CELAS3', 'CELAS4', 'CDAMP1', 'CDAMP2', 'CDAMP3', 'CDAMP4', ]: continue elif element.type in ['CQUAD4']: n1, n2, n3, n4 = element.node_ids i1, i2, i3, i4 = nodeid_to_i_map[n1], nodeid_to_i_map[ n2], nodeid_to_i_map[n3], nodeid_to_i_map[n4] elements.append([i1, i2, i3]) elements.append([i3, i4, i1]) elif element.type in ['CTRIA3', 'CTRIAR']: n1, n2, n3 = element.node_ids i1, i2, i3 = nodeid_to_i_map[n1], nodeid_to_i_map[ n2], nodeid_to_i_map[n3] elements.append([i1, i2, i3]) else: print(element.type) elements = array(elements, dtype='int32') stl = STL(log=model.log) stl.nodes = nodes stl.elements = elements stl.write_stl(stl_filename, is_binary=is_binary) return stl
def stl_reshape(data): if '--xy' not in data: data['--xy'] = False if '--yz' not in data: data['--yz'] = False if '--xz' not in data: data['--xz'] = False if '--scale' not in data: data['--scale'] = None if '--xscale' not in data: data['--xscale'] = None if '--yscale' not in data: data['--yscale'] = None if '--zscale' not in data: data['--zscale'] = None if '<xshift>' not in data: data['<xshift>'] = None if '<yshift>' not in data: data['<yshift>'] = None if '<zshift>' not in data: data['<zshift>'] = None if '--stats' not in data: data['--stats'] = None if '--mirror' not in data: data['--mirror'] = None if '--flip_normals' not in data: data['--flip_normals'] = None in_stl_filename = data['<in_stl_filename>'] out_stl_filename = data['<out_stl_filename>'] assert in_stl_filename != out_stl_filename stl = STL() stl.read_stl(in_stl_filename) if data['<fmt>'] in ['False', False]: is_binary = True fmt = None else: fmt = data['<fmt>'] is_binary = False print('is_binary=%s' % is_binary) if data['--xy'] or data['--yz'] or data['--xz']: scale = 1. if data['--scale'] is not None: scale = float(data['--scale']) if data['--xy']: assert data['--yz'] is False assert data['--xz'] is False axes = 'xy' elif data['--yz']: assert data['--xy'] is False assert data['--xz'] is False axes = 'yz' elif data['--xz']: assert data['--xy'] is False assert data['--yz'] is False axes = 'xz' #print('flip_axes = %r' % axes) #print(data) stl.flip_axes(axes, scale) elif data['--xscale'] or data['--yscale'] or data['--zscale']: xscale = 1. yscale = 1. zscale = 1. if data['--xscale'] is not None: xscale = float(data['--xscale'].strip("'")) if data['--yscale'] is not None: yscale = float(data['--yscale'].strip("'")) if data['--zscale'] is not None: zscale = float(data['--zscale'].strip("'")) x = deepcopy(stl.nodes[:, 0]) y = deepcopy(stl.nodes[:, 1]) z = deepcopy(stl.nodes[:, 2]) stl.nodes[:, 0] = x * xscale stl.nodes[:, 1] = y * yscale stl.nodes[:, 2] = z * zscale elif data['<xshift>'] or data['<yshift>'] or data['<zshift>']: xshift = 1. yshift = 1. zshift = 1. if data['<xshift>'] is not None: if isinstance(xshift, basestring): xshift = float(data['<xshift>'].strip("'")) else: xshift = float(data['<xshift>']) if data['<yshift>'] is not None: if isinstance(xshift, basestring): yshift = float(data['<yshift>'].strip("'")) else: yshift = float(data['<yshift>']) if data['<zshift>'] is not None: if isinstance(xshift, basestring): zshift = float(data['<zshift>'].strip("'")) else: zshift = float(data['<zshift>']) print('delta = (%s, %s, %s)' % (xshift, yshift, zshift)) stl.nodes[:, 0] += xshift stl.nodes[:, 1] += yshift stl.nodes[:, 2] += zshift elif data['--scale']: scale = float(data['--scale']) stl.nodes *= scale elif data['--stats']: xmax, ymax, zmax = stl.nodes.max(axis=0) xmin, ymin, zmin = stl.nodes.min(axis=0) print('xyz_max = (%g, %g, %g)' % (xmax, ymax, zmax)) print('xyz_min = (%g, %g, %g)' % (xmin, ymin, zmin)) return elif data['--mirror']: #plane = data['plane'] #assert plane in ['xy', 'yz', 'xz'], 'plane=%r' % plane xyz = data['<xyz>'] tol = float(data['<tol>']) stl.create_mirror_model(xyz, tol) elif data['--flip_normals']: stl.flip_normals() else: raise RuntimeError('unsupported reshape...data=%s' % data) stl.write_stl(out_stl_filename, is_binary=is_binary, float_fmt=fmt)
def stl_reshape(data): if '--xy' not in data: data['--xy'] = False if '--yz' not in data: data['--yz'] = False if '--xz' not in data: data['--xz'] = False if '--scale' not in data: data['--scale'] = None if '--xscale' not in data: data['--xscale'] = None if '--yscale' not in data: data['--yscale'] = None if '--zscale' not in data: data['--zscale'] = None if '<xshift>' not in data: data['<xshift>'] = None if '<yshift>' not in data: data['<yshift>'] = None if '<zshift>' not in data: data['<zshift>'] = None if '--stats' not in data: data['--stats'] = None if '--mirror' not in data: data['--mirror'] = None if '--flip_normals' not in data: data['--flip_normals'] = None in_stl_filename = data['<in_stl_filename>'] out_stl_filename = data['<out_stl_filename>'] assert in_stl_filename != out_stl_filename stl = STL() stl.read_stl(in_stl_filename) if data['<fmt>'] in ['False', False]: is_binary = True fmt = None else: fmt = data['<fmt>'] is_binary = False print('is_binary=%s' % is_binary) if data['--xy'] or data['--yz'] or data['--xz']: scale = 1. if data['--scale'] is not None: scale = float(data['--scale']) if data['--xy']: assert data['--yz'] is False assert data['--xz'] is False axes = 'xy' elif data['--yz']: assert data['--xy'] is False assert data['--xz'] is False axes = 'yz' elif data['--xz']: assert data['--xy'] is False assert data['--yz'] is False axes = 'xz' #print('flip_axes = %r' % axes) #print(data) stl.flip_axes(axes, scale) elif data['--xscale'] or data['--yscale'] or data['--zscale']: xscale = 1. yscale = 1. zscale = 1. if data['--xscale'] is not None: xscale = float(data['--xscale'].strip("'")) if data['--yscale'] is not None: yscale = float(data['--yscale'].strip("'")) if data['--zscale'] is not None: zscale = float(data['--zscale'].strip("'")) x = deepcopy(stl.nodes[:, 0]) y = deepcopy(stl.nodes[:, 1]) z = deepcopy(stl.nodes[:, 2]) stl.nodes[:, 0] = x * xscale stl.nodes[:, 1] = y * yscale stl.nodes[:, 2] = z * zscale elif data['<xshift>'] or data['<yshift>'] or data['<zshift>']: xshift = 1. yshift = 1. zshift = 1. if data['<xshift>'] is not None: if isinstance(xshift, basestring): xshift = float(data['<xshift>'].strip("'")) else: xshift = float(data['<xshift>']) if data['<yshift>'] is not None: if isinstance(xshift, basestring): yshift = float(data['<yshift>'].strip("'")) else: yshift = float(data['<yshift>']) if data['<zshift>'] is not None: if isinstance(xshift, basestring): zshift = float(data['<zshift>'].strip("'")) else: zshift = float(data['<zshift>']) print('delta = (%s, %s, %s)' % (xshift, yshift, zshift)) stl.nodes[:, 0] += xshift stl.nodes[:, 1] += yshift stl.nodes[:, 2] += zshift elif data['--scale'] : scale = float(data['--scale']) stl.nodes *= scale elif data['--stats'] : xmax, ymax, zmax = stl.nodes.max(axis=0) xmin, ymin, zmin = stl.nodes.min(axis=0) print('xyz_max = (%g, %g, %g)' % (xmax, ymax, zmax)) print('xyz_min = (%g, %g, %g)' % (xmin, ymin, zmin)) return elif data['--mirror']: #plane = data['plane'] #assert plane in ['xy', 'yz', 'xz'], 'plane=%r' % plane xyz = data['<xyz>'] tol = float(data['<tol>']) stl.create_mirror_model(xyz, tol) elif data['--flip_normals']: stl.flip_normals() else: raise RuntimeError('unsupported reshape...data=%s' % data) stl.write_stl(out_stl_filename, is_binary=is_binary, float_fmt=fmt)