# # Eidolon is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program (LICENSE.txt). If not, see <http://www.gnu.org/licenses/> from eidolon import vec3, ElemType, PyDataSet, ReprType, MeshSceneObject # construct a dataset with a single triangle by defining 3 vertices, an index matrix with 1 element, and a field assigning a value to each vertex nodes = [vec3(0, 0, 0), vec3(1, 0, 0), vec3(0.5, 0, 0.866)] # 3 vertices of triangle inds = [(0, 1, 2)] # single element in index matrix field = [0.0, 1.0, 2.0] ds = PyDataSet('TriDS', nodes, [('triind', ElemType._Tri1NL, inds)], [('vals', field, 'triind')]) # create the scene object which contains the dataset obj = MeshSceneObject('Tri', ds) mgr.addSceneObject(obj) # create a visual representation of the triangle, "volume" in this value referring to a 3D representation rep = obj.createRepr(ReprType._volume, 0) mgr.addSceneObjectRepr(rep) rep.applyMaterial('Rainbow', field='vals') # adjust the camera to get the triangle in frame mgr.setCameraSeeAll()
inds=[ ('tris',ElemType._Tri1NL,triinds), ('quads',ElemType._Quad1NL,quadinds), ('quadfieldtopo',ElemType._Quad1NL,quadfieldtopo,False) ] fields=[ ('trifield',trifield,'tris'), # per-vertex field for triangles ('trielemfield',trielemfield,'tris'), # per-element field for triangles ('quadfield',quadfield,'quads','quadfieldtopo'), # per-vertex field for quads ('quadelemfield',quadelemfield,'quads'), # per-element field for quads ('nodefield',nodefield) # per-node field for whole mesh ] ds=PyDataSet('MeshTest',nodes,inds,fields) obj=MeshSceneObject('Test',ds) mgr.addSceneObject(obj) # render the triangle field rep=obj.createRepr(ReprType._volume,0) mgr.addSceneObjectRepr(rep) rep.applyMaterial(mat,field='trifield') # render the quad field rep=obj.createRepr(ReprType._volume,10) mgr.addSceneObjectRepr(rep) rep.setPosition(vec3(0,0,-1.1)) rep.applyMaterial(mat,field='quadfield')
inds = listToMatrix( inds, 'LinHex', ElemType._Hex1NL) # convert here as well specifying a matrix type Hex1NL # construct a list of PyDataset objects which contain the node, topology, and field information for each timestep dds = [] for i in xrange(10): n1 = nodes.clone() # clone the nodes n1.mul(vec3(1 + i * 0.1, 1, 1)) # scale the nodes in the X direction field = [n1.getAt(j).lenSq() for j in xrange(n1.n()) ] # generate a field defined as the squared length of each node fieldmat = listToMatrix( field, 'LenSq' ) # convert field, the matrix for each timestep has the same name "LenSq" dds.append(PyDataSet( 'ds%i' % i, n1, [inds], [fieldmat ])) # create the dataset, each shares the matrix `inds' which is safe obj = MeshSceneObject( 'LinBox', dds ) # create the MeshSceneObject, note that this object's "plugin" attribute is None here mgr.addSceneObject( obj ) # add it to the scene, the manager will assign its plugin attribute to be the default mesh plugin rep = obj.createRepr(ReprType._volume, 10, externalOnly=True) mgr.addSceneObjectRepr(rep) mgr.setCameraSeeAll() mgr.controller.setRotation(-0.6, 0.6) mgr.setAxesType(AxesType._cornerTR)
def savePolydataNodes(self, filename, nodes, vecfunc=tuple): return self.saveLegacyFile(filename, PyDataSet('DS', nodes), datasettype=DatasetTypes._POLYDATA, writeFields=False, vecfunc=vecfunc)
def _loadFile(filename, name, task): basename = name or os.path.basename(filename).split('.')[0] name = uniqueStr( basename, [o.getName() for o in self.mgr.enumSceneObjects()]) ds = None tree = ET.parse(filename) root = tree.getroot() unstruc = root.find('UnstructuredGrid') poly = root.find('PolyData') appended = root.find('AppendedData') compressor = _get(root, 'compressor') byteorder = '<' if root.get( 'byte_order') == 'LittleEndian' else '>' #if appended and _get(appended,'encoding').lower()=='base64': # appended=base64.decodestring(root.find('AppendedData').text) if unstruc is not None: pieces = list(unstruc) points = pieces[0].find('Points') cells = pieces[0].find('Cells') celldata = pieces[0].find('CellData') pointdata = pieces[0].find('PointData') nodearray = points.find('DataArray') if celldata is None: celldata = [] if pointdata is None: pointdata = [] nodes = readNodes(nodearray, byteorder, compressor) connectivity = first( i for i in cells if i.get('Name').lower() == 'connectivity') types = first(i for i in cells if i.get('Name').lower() == 'types') offsets = first(i for i in cells if i.get('Name').lower() == 'offsets') indlist = readArray( connectivity, byteorder, compressor).tolist() # faster as Python list? fields = readFields(celldata, pointdata, byteorder, compressor) celltypes = readArray(types, byteorder, compressor) offlist = readArray(offsets, byteorder, compressor) cellofflist = np.vstack((celltypes, offlist)).T.tolist( ) # pair each cell type entry with its width entry assert len(celltypes) == len(offlist) # map cell type IDs to IndexMatrix objects for containing the indices of that type and node ordering list indmats = { i: (IndexMatrix(n + 'Inds', e, 0, len(s)), s) for n, i, e, s in CellTypes } for celltype, off in cellofflist: indmat, _ = indmats.get(celltype, (None, [])) if indmat is not None: # only found for those cell types we understand (ie. not polygon) indmat.append(*indlist[off - indmat.m():off]) inds = [] for ind, order in indmats.values( ): # collect and reorder all non-empty index matrices if ind.n() > 0: ind[:, :] = np.asarray( ind )[:, order] # reorder columns to match CHeart node ordering inds.append(ind) ds = PyDataSet('vtk', nodes, inds, fields) elif poly is not None: pieces = list(poly) #numPoints=int(_get(pieces[0],'NumberOfPoints') points = pieces[0].find('Points') celldata = pieces[0].find('CellData') pointdata = pieces[0].find('PointData') nodearray = points.find('DataArray') nodes = readNodes(nodearray, byteorder, compressor) inds = [] lines = IndexMatrix('lines', ElemType._Line1NL, 0, 2) tris = IndexMatrix('tris', ElemType._Tri1NL, 0, 3) quads = IndexMatrix('quads', ElemType._Quad1NL, 0, 4) for a, b in yieldConnectedOffsets(pieces[0].find('Lines'), byteorder, compressor): lines.append(a, b) for strip in yieldConnectedOffsets(pieces[0].find('Strips'), byteorder, compressor): for a, b, c in eidolon.successive(strip, 3): tris.append(a, b, c) for poly in yieldConnectedOffsets(pieces[0].find('Polys'), byteorder, compressor): if len(poly) == 2: lines.append(*poly) elif len(poly) == 3: tris.append(*poly) elif len(poly) == 4: quads.append(*poly) # TODO: read in arbitrary polygon and triangulate? if len(lines) > 0: inds.append(lines) if len(tris) > 0: inds.append(tris) if len(quads) > 0: quads[:, :] = np.asarray(quads)[:, CellTypes.Quad[-1]] inds.append(quads) fields = readFields(celldata, pointdata, byteorder, compressor) ds = PyDataSet('vtk', nodes, inds, fields) else: raise NotImplementedError('Dataset not understood yet') f.setObject( MeshSceneObject(name, ds, self, filename=filename, isXML=True, descdata=''))
def _loadFile(filename, name, strdata, task): result = self.parseString(strdata or open(filename).read()) basename = name or os.path.basename(filename).split('.')[0] name = uniqueStr( basename, [o.getName() for o in self.mgr.enumSceneObjects()]) version, desc, data = result[:3] pointattrs = [a for a in result[3:] if a[0] == 'POINT_DATA'] cellattrs = [a for a in result[3:] if a[0] == 'CELL_DATA'] ds = None indmats = [] metamap = { VTKProps.desc: desc, VTKProps.version: str(version), VTKProps.datasettype: data[0] } # interpret dataset blocks if data[0] == DatasetTypes._UNSTRUCTURED_GRID: nodes, cells, celltypes = data[1:] # map cell types to the indices of members of `cells' of that type typeindices = {} for i in range(celltypes.n()): typeindices.setdefault(celltypes.getAt(i), []).append(i) for ctype, inds in typeindices.items(): tname, elemtypename, sortinds = first( (n, e, s) for n, i, e, s in CellTypes if i == ctype) or (None, None, None) matname = '' if tname == None else uniqueStr( tname, [i.getName() for i in indmats], '') if tname == CellTypes._Poly: mat = IndexMatrix(matname, elemtypename, 0) polyinds = IndexMatrix(matname + 'Inds', VTKProps._polyinds, 0, 2) mat.meta(VTKProps._polyinds, polyinds.getName()) indmats.append(mat) indmats.append(polyinds) for ind in inds: row = cells.getRow(ind) length = row[0] polyinds.append(mat.n(), mat.n() + length) for r in row[1:length + 1]: mat.append(r) elif tname != None: elemtype = ElemType[elemtypename] mat = IndexMatrix(matname, elemtypename, 0, elemtype.numNodes()) indmats.append(mat) for ind in inds: sortedinds = eidolon.indexList( sortinds, cells.getRow(ind)[1:]) mat.append(*sortedinds) elif data[0] == DatasetTypes._STRUCTURED_GRID: dims, nodes = data[1:] dimx, dimy, dimz = map(int, dims) assert dimx > 1 assert dimy > 1 assert dimz > 1 _, inds = eidolon.generateHexBox(dimx - 2, dimy - 2, dimz - 2) inds = eidolon.listToMatrix(inds, 'hexes') inds.setType(ElemType._Hex1NL) indmats = [inds] metamap[VTKProps._griddims] = repr((dimx, dimy, dimz)) elif data[0] == DatasetTypes._POLYDATA: nodes = data[1] polyelems = data[2:] lines = IndexMatrix('lines', ElemType._Line1NL, 0, 2) tris = IndexMatrix('tris', ElemType._Tri1NL, 0, 3) quads = IndexMatrix('quads', ElemType._Quad1NL, 0, 4) for pname, numelems, numvals, ind in polyelems: n = 0 if pname == 'POLYGONS': while n < ind.n(): polylen = ind.getAt(n) if polylen == 2: lines.append(ind.getAt(n + 1), ind.getAt(n + 2)) elif polylen == 3: tris.append(ind.getAt(n + 1), ind.getAt(n + 2), ind.getAt(n + 3)) elif polylen == 4: quads.append(ind.getAt(n + 1), ind.getAt(n + 2), ind.getAt(n + 4), ind.getAt(n + 3)) n += polylen + 1 if len(tris) > 0: indmats.append(tris) if len(quads) > 0: indmats.append(quads) if len(lines) > 0: indmats.append(lines) else: raise NotImplementedError( 'Dataset type %s not understood yet' % str(data[0])) ds = PyDataSet('vtk', nodes, indmats) for k, v in metamap.items(): ds.meta(k, v) # read attributes into fields for attr in list(pointattrs) + list(cellattrs): for attrtype in attr[2:]: atype = str(attrtype[0]) spatialname = first( ds.indices.keys()) # TODO: choose a better topology if atype == AttrTypes._FIELD: for fname, width, length, dtype, dat in attrtype[3:]: assert (width * length) == dat.n() assert length == nodes.n( ) or length == ds.indices[spatialname].n() dat.setName(fname) dat.setM(width) dat.meta(StdProps._topology, spatialname) dat.meta(StdProps._spatial, spatialname) dat.meta(VTKProps._attrtype, atype) ds.setDataField(dat) else: dat = attrtype[-1] dat.setName(str(attrtype[1])) dat.meta(StdProps._topology, spatialname) dat.meta(StdProps._spatial, spatialname) dat.meta(VTKProps._attrtype, atype) ds.setDataField(dat) if atype in (AttrTypes._NORMALS, AttrTypes._VECTORS): dat.setM(3) elif atype == AttrTypes._LOOKUP_TABLE: dat.setM(4) elif atype == AttrTypes._TENSORS: dat.setM(9) elif atype in (AttrTypes._TEXTURE_COORDINATES, AttrTypes._COLOR_SCALARS): dat.setM(attrtype[2]) elif atype == AttrTypes._SCALARS: if isinstance(attrtype[3], int): dat.setM(attrtype[3]) if attrtype[3] == AttrTypes._LOOKUP_TABLE: dat.meta(AttrTypes._LOOKUP_TABLE, str(attrtype[4])) elif attrtype[4] == AttrTypes._LOOKUP_TABLE: dat.meta(AttrTypes._LOOKUP_TABLE, str(attrtype[5])) try: descdata = eval( desc ) # if desc is a Python object (eg. timestep number) attempt to evaluate it except: descdata = desc # just a normal string f.setObject( MeshSceneObject(name, ds, self, filename=filename, descdata=descdata, result=result))
# # This file is part of Eidolon. # # Eidolon is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Eidolon is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program (LICENSE.txt). If not, see <http://www.gnu.org/licenses/> from eidolon import vec3, PyDataSet, MeshSceneObject, ReprType nodes=[vec3(0,0,0),vec3(2,0,0),vec3(5,0,0),vec3(10,0,0)] field=[0.0,1.0,2.0,3.0] ds=PyDataSet('PtDS',nodes,[],[('vals',field)]) obj=MeshSceneObject('Pts',ds) mgr.addSceneObject(obj) rep=obj.createRepr(ReprType._glyph,glyphname='sphere', sfield= 'vals',glyphscale=(1,1,1)) mgr.addSceneObjectRepr(rep) rep.applyMaterial('Rainbow',field='vals') mgr.setCameraSeeAll()