# -*- coding: utf-8 -*-
# -*- python -*-
#
# PropertyTopomesh
#
# Copyright 2014-2016 INRIA - CIRAD - INRA
#
# File author(s): Guillaume Cerutti <guillaume.cerutti@inria.fr>,
# Hadrien Oliveri <hadrien.oliveri@inria.fr>
#
# File contributor(s): Guillaume Cerutti <guillaume.cerutti@inria.fr>,
# Hadrien Oliveri <hadrien.oliveri@inria.fr>
#
# Distributed under the Cecill-C License.
# See accompanying file LICENSE.txt or copy at
# http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.html
#
# OpenaleaLab Website : http://virtualplants.github.io/
#
###############################################################################
"""
=========================
PropertyTopomesh I/O
=========================
Implementing functions to read and write PropertyTopomesh objects in several standard
mesh file formats, including PLY, OBJ or MSH.
.. autosummary::
:toctree: generated/
save_ply_property_topomesh -- write an ascii PLY file contaning a PropertyTopomesh
read_ply_property_topomesh -- reconstruct a PropertyTopomesh object from a PLY file
"""
from copy import copy
from time import time
import os
import re
import sys
import pickle
import numpy as np
from scipy import ndimage as nd
from cellcomplex.property_topomesh import PropertyTopomesh
from cellcomplex.property_topomesh.utils.matching_tools import kd_tree_match
from cellcomplex.property_topomesh.analysis import compute_topomesh_property
from cellcomplex.utils import array_dict
from sys import path
[docs]def save_property_topomesh(topomesh, path, cells_to_save=None, properties_to_save=dict([(0,['barycenter']),(1,[]),(2,[]),(3,[])]),**kwargs):
if cells_to_save is None:
cells_to_save = np.array(list(topomesh.wisps(3)))
triangles_to_save = np.array(np.unique(np.concatenate([np.array(list(topomesh.borders(3,c))) for c in cells_to_save])),int)
edges_to_save = np.array(np.unique(np.concatenate([np.array(list(topomesh.borders(2,t))) for t in triangles_to_save])),int)
vertices_to_save = np.array(np.unique(np.concatenate([np.array(list(topomesh.borders(1,e))) for e in edges_to_save])),int)
original_pids = kwargs.get('original_pids',False)
original_eids = kwargs.get('original_eids',False)
original_fids = kwargs.get('original_fids',False)
original_cids = kwargs.get('original_cids',True)
sub_topomesh = PropertyTopomesh(3)
vertices_to_pids = {}
for v in vertices_to_save:
if original_pids:
pid = sub_topomesh.add_wisp(0,v)
else:
pid = sub_topomesh.add_wisp(0)
vertices_to_pids[v] = pid
edges_to_eids = {}
for e in edges_to_save:
if original_eids:
eid = sub_topomesh.add_wisp(1,e)
else:
eid = sub_topomesh.add_wisp(1)
edges_to_eids[e] = eid
for v in topomesh.borders(1,e):
sub_topomesh.link(1,eid,vertices_to_pids[v])
triangles_to_fids = {}
for t in triangles_to_save:
if original_fids:
fid = sub_topomesh.add_wisp(2,t)
else:
fid = sub_topomesh.add_wisp(2)
triangles_to_fids[t] = fid
for e in topomesh.borders(2,t):
sub_topomesh.link(2,fid,edges_to_eids[e])
cells_to_cids = {}
for c in cells_to_save:
if original_cids:
cid = sub_topomesh.add_wisp(3,c)
else:
cid = sub_topomesh.add_wisp(3,c)
cells_to_cids[c] = cid
for t in topomesh.borders(3,c):
sub_topomesh.link(3,cid,triangles_to_fids[t])
wisps_to_save = {}
wisps_to_save[0] = vertices_to_save
wisps_to_save[1] = edges_to_save
wisps_to_save[2] = triangles_to_save
wisps_to_save[3] = cells_to_save
wisps_to_wids = {}
wisps_to_wids[0] = vertices_to_pids
wisps_to_wids[1] = edges_to_eids
wisps_to_wids[2] = triangles_to_fids
wisps_to_wids[3] = cells_to_cids
if not 0 in properties_to_save.keys():
properties_to_save[0] = []
if not 'barycenter' in properties_to_save[0]:
properties_to_save[0].append('barycenter')
for degree in properties_to_save.keys():
for property_name in properties_to_save[degree]:
print("Property ",property_name,'(',degree,')')
if topomesh.has_wisp_property(property_name,degree=degree,is_computed=True):
wids_to_save = array_dict(wisps_to_wids[degree]).values(wisps_to_save[degree])
sub_topomesh.update_wisp_property(property_name,degree,array_dict(topomesh.wisp_property(property_name,degree).values(wisps_to_save[degree]),wids_to_save))
pickle.dump(sub_topomesh,open(path,"wb"))
[docs]def save_tissue_property_topomesh(topomesh,tissue_filename='vplants.zip'):
from openalea.celltissue import Tissue, TissueDB, topen, Config, ConfigItem, ConfigFormat
tissue = Tissue()
ptyp = tissue.add_type("point")
etyp = tissue.add_type("edge")
ftyp = tissue.add_type("face")
ctyp = tissue.add_type("cell")
mesh_id = tissue.add_relation("mesh",(ptyp,etyp,ftyp,ctyp))
mesh = tissue.relation(mesh_id)
cells = {}
for c in topomesh.wisps(3):
if len(list(topomesh.borders(3,c)))>0:
cid = tissue.add_element(ctyp)
mesh.add_wisp(3,cid)
cells[c] = cid
faces = {}
for t in topomesh.wisps(2):
fid = tissue.add_element(ftyp)
mesh.add_wisp(2,fid)
faces[t] = fid
edges = {}
for e in topomesh.wisps(1):
eid = tissue.add_element(etyp)
mesh.add_wisp(1,eid)
edges[e] = eid
points = {}
for v in topomesh.wisps(0):
pid = tissue.add_element(ptyp)
mesh.add_wisp(0,pid)
points[v] = pid
for e in topomesh.wisps(1):
for v in topomesh.borders(1,e):
mesh.link(1,edges[e],points[v])
for t in topomesh.wisps(2):
for e in topomesh.borders(2,t):
mesh.link(2,faces[t],edges[e])
for c in topomesh.wisps(3):
if len(list(topomesh.borders(3,c)))>0:
for t in topomesh.borders(3,c):
mesh.link(3,cells[c],faces[t])
positions = {}
for v in topomesh.wisps(0):
positions[points[v]] = tuple(topomesh.wisp_property('barycenter',0)[v])
cfg = ConfigFormat("config")
cfg.add_section("topology")
cfg.add_item(ConfigItem("cell",ctyp) )
cfg.add_item(ConfigItem("face",ftyp) )
cfg.add_item(ConfigItem("edge",etyp) )
cfg.add_item(ConfigItem("point",ptyp) )
cfg.add_item(ConfigItem("mesh_id",mesh_id))
tissue_db = TissueDB()
tissue_db.set_tissue(tissue)
tissue_db.set_property("position",positions)
tissue_db.set_description("position","position of points")
tissue_db.set_config("config",cfg.config())
tissue_db.write(tissue_filename)
[docs]def multidim_data_ply_string(data):
"""Convert a multidimensional data into a PLY-formatted string
Parameters
----------
data : :class:`numpy.ndarray`
Returns
-------
"""
data_string = ""
data = np.array([l for l in data])
for dim in range(data.ndim):
data_string += " "+str(data.shape[dim])
# print data," (",len(data),")"
# data_string = " "+str(len(data))
for d in data.ravel():
data_string += " "+str(d)
# data_string += (" "+str(d)) if data.ndim==1 else multidim_data_ply_string(d)
return data_string
[docs]def save_ply_cellcomplex_topomesh(topomesh,ply_filename,properties_to_save=dict([(0,[]),(1,['length']),(2,['area','epidermis']),(3,[])]),color_faces=False,colormap=None,position_name='barycenter',oriented=True):
"""Implementing the PLY standard defined at Saisnbury Computational Workshop 2015.
Parameters
----------
topomesh
ply_filename
properties_to_save
color_faces
colormap
position_name
oriented
Returns
-------
"""
start_time =time()
print("--> Saving .ply")
ply_file = open(ply_filename,'w+')
if oriented:
compute_topomesh_property(topomesh,'oriented_borders',2)
compute_topomesh_property(topomesh,'oriented_vertices',2)
compute_topomesh_property(topomesh,'oriented_borders',3)
property_types = {}
property_types['bool'] = "int"
property_types['int'] = "int"
property_types['int32'] = "int"
property_types['int64'] = "int"
property_types['float'] = "float"
property_types['float32'] = "float"
property_types['float64'] = "float"
property_types['object'] = "list"
ply_file.write("ply\n")
ply_file.write("format ascii 1.0\n")
ply_file.write("element vertex "+str(topomesh.nb_wisps(0))+"\n")
ply_file.write("property float x\n")
ply_file.write("property float y\n")
ply_file.write("property float z\n")
for property_name in properties_to_save[0]:
if property_name != position_name and topomesh.has_wisp_property(property_name,0,is_computed=True):
property_type = property_types[str(topomesh.wisp_property(property_name,0).values().dtype)]
ply_file.write("property "+property_type+" "+property_name+"\n")
ply_file.write("element face "+str(topomesh.nb_wisps(2))+"\n")
ply_file.write("property list int int vertex_index\n")
if color_faces:
ply_file.write("property uchar red\n")
ply_file.write("property uchar green\n")
ply_file.write("property uchar blue\n")
triangle_data = array_dict(np.array([(list(topomesh.regions(2,t))[0])%256 for t in topomesh.wisps(2)]),list(topomesh.wisps(2)))
for property_name in properties_to_save[2]:
if topomesh.has_wisp_property(property_name,2,is_computed=True):
property_type = property_types[str(topomesh.wisp_property(property_name,2).values().dtype)]
ply_file.write("property "+property_type+" "+property_name+"\n")
ply_file.write("element edge "+str(topomesh.nb_wisps(1))+"\n")
ply_file.write("property int source\n")
ply_file.write("property int target\n")
for property_name in properties_to_save[1]:
if topomesh.has_wisp_property(property_name,1,is_computed=True):
property_type = property_types[str(topomesh.wisp_property(property_name,1).values().dtype)]
ply_file.write("property "+property_type+" "+property_name+"\n")
ply_file.write("element volume "+str(topomesh.nb_wisps(3))+"\n")
ply_file.write("property list int int face_index\n")
ply_file.write("property int label\n")
for property_name in properties_to_save[3]:
if topomesh.has_wisp_property(property_name,3,is_computed=True):
property_type = property_types[str(topomesh.wisp_property(property_name,3).values().dtype)]
ply_file.write("property "+property_type+" "+property_name+"\n")
# ply_file.write("element global 1\n")
# ply_file.write("property list char type\n")
ply_file.write("end_header\n")
vertex_index = {}
for v,pid in enumerate(topomesh.wisps(0)):
ply_file.write(str(topomesh.wisp_property('barycenter',0)[pid][0])+" ")
ply_file.write(str(topomesh.wisp_property('barycenter',0)[pid][1])+" ")
ply_file.write(str(topomesh.wisp_property('barycenter',0)[pid][2])+" ")
for property_name in properties_to_save[0]:
if property_name != position_name and topomesh.has_wisp_property(property_name,0,is_computed=True):
property_type = property_types[str(topomesh.wisp_property(property_name,0).values().dtype)]
if property_type == 'int':
ply_file.write(str(int(topomesh.wisp_property(property_name,0)[pid]))+" ")
else:
ply_file.write(str(topomesh.wisp_property(property_name,0)[pid])+" ")
ply_file.write("\n")
vertex_index[pid] = v
face_index = {}
for t,fid in enumerate(topomesh.wisps(2)):
if oriented:
oriented_face_pids = topomesh.wisp_property('oriented_vertices',2)[fid]
else:
face_pids = np.array(list(topomesh.borders(2,fid,2)))
face_edges = np.array([list(topomesh.borders(1,eid)) for eid in topomesh.borders(2,fid)])
# print fid," : ",face_pids, face_edges
oriented_face_pids = [face_pids[0]]
while len(oriented_face_pids) < len(face_pids):
current_pid = oriented_face_pids[-1]
pid_edges = face_edges[np.where(face_edges==current_pid)[0]]
candidate_pids = set(list(np.unique(pid_edges))).difference({current_pid})
if len(oriented_face_pids)>1:
candidate_pids = candidate_pids.difference({oriented_face_pids[-2]})
if len(list(candidate_pids))==0:
candidate_pids = set(list(face_pids)).difference(list(oriented_face_pids))
oriented_face_pids += [list(candidate_pids)[0]]
# print fid," : ",oriented_face_pids
ply_file.write(str(len(list(topomesh.borders(2,fid,2))))+" ")
for pid in oriented_face_pids:
ply_file.write(str(vertex_index[pid])+" ")
if color_faces:
if colormap is None:
ply_file.write(str(triangle_data[fid])+" ")
ply_file.write(str(triangle_data[fid])+" ")
ply_file.write(str(triangle_data[fid])+" ")
else:
color = colormap._color_points.values()[int(triangle_data[fid])]
ply_file.write(str(int(255*color[0]))+" ")
ply_file.write(str(int(255*color[1]))+" ")
ply_file.write(str(int(255*color[2]))+" ")
for property_name in properties_to_save[2]:
if topomesh.has_wisp_property(property_name,2,is_computed=True):
property_type = property_types[str(topomesh.wisp_property(property_name,2).values().dtype)]
if property_type == 'int':
ply_file.write(str(int(topomesh.wisp_property(property_name,2)[fid]))+" ")
else:
ply_file.write(str(topomesh.wisp_property(property_name,2)[fid])+" ")
ply_file.write("\n")
face_index[fid] = t
edge_index = {}
for e,eid in enumerate(topomesh.wisps(1)):
ply_file.write(str(vertex_index[list(topomesh.borders(1,eid))[0]])+" ")
ply_file.write(str(vertex_index[list(topomesh.borders(1,eid))[1]])+" ")
for property_name in properties_to_save[1]:
if topomesh.has_wisp_property(property_name,1,is_computed=True):
ply_file.write(str(topomesh.wisp_property(property_name,1)[eid])+" ")
ply_file.write("\n")
edge_index[eid] = e
for c, cid in enumerate(topomesh.wisps(3)):
if oriented:
oriented_cell_fids = topomesh.wisp_property('oriented_borders',3)[cid][0]
oriented_cell_fid_orientations = topomesh.wisp_property('oriented_borders',3)[cid][1]
ply_file.write(str(len(oriented_cell_fids))+" ")
for fid,orientation in zip(oriented_cell_fids,oriented_cell_fid_orientations):
ply_file.write(str(orientation*(face_index[fid]+1))+" ")
else:
for fid in topomesh.borders(3,cid):
ply_file.write(str(face_index[fid]+1)+" ")
ply_file.write(str(cid)+" ")
for property_name in properties_to_save[3]:
if topomesh.has_wisp_property(property_name,3,is_computed=True):
ply_file.write(str(topomesh.wisp_property(property_name,3)[cid])+" ")
ply_file.write("\n")
# ply_file.write("12 cell_complex\n")
ply_file.flush()
ply_file.close()
end_time = time()
print("<-- Saving .ply [",end_time-start_time,"s]")
[docs]def save_ply_property_topomesh(topomesh,ply_filename,properties_to_save=dict([(0,[]),(1,['length']),(2,['area','epidermis']),(3,[])]), position_name='barycenter', verbose=True):
"""Write a PropertyTopomesh as a standard PLY file.
Save a PropertyTopomesh object into a ASCII-formatted PLY file with a
subset of element properties written into the file. The written file is
readable by other mesh processing tools, and contains all the necessary
information to reconstruct the PropertyTopomesh including all topological
relationships and element properties.
Parameters
----------
topomesh : :class:`cellcomplex.property_topomesh.PropertyTopomesh`
The PropertyTopomesh instance to save
ply_filename : str
Path to the PLY file to write to
properties_to_save : dict
Dictionary containing ,for each degree, the list of properties to write in the file
position_name : str
Property name used to define the XYZ position of vertices (default : `barycenter`)
verbose : bool
Whether to print information while writing the file
"""
if verbose:
start_time =time()
print("--> Saving .ply")
ply_file = open(ply_filename,'w+')
def get_property_type(dtype):
property_types = {}
property_types['bool'] = "int"
property_types['int'] = "int"
property_types['int16'] = "int"
property_types['int32'] = "int"
property_types['int64'] = "int"
property_types['uint8'] = "int"
property_types['uint16'] = "int"
property_types['float'] = "float"
property_types['float32'] = "float"
property_types['float64'] = "float"
property_types['object'] = "list"
if dtype in property_types:
return property_types[dtype]
elif re.match("[<|][SU][0-9]*", dtype):
return "str"
else:
raise KeyError("Data type not understood :"+str(dtype))
ply_file.write("ply\n")
ply_file.write("format ascii 1.0\n")
ply_file.write("element vertex "+str(topomesh.nb_wisps(0))+"\n")
ply_file.write("property float x\n")
ply_file.write("property float y\n")
ply_file.write("property float z\n")
for property_name in properties_to_save[0]:
if property_name != position_name and topomesh.has_wisp_property(property_name,0,is_computed=True):
property_data = topomesh.wisp_property(property_name,0).values()
if property_data.ndim == 1:
property_type = get_property_type(str(property_data.dtype))
if property_type == "list":
property_type = "list int "+get_property_type(str(np.array(property_data[0]).dtype))
elif property_data.ndim == 2:
property_type = "list int "+get_property_type(str(property_data.dtype))
if get_property_type(str(np.array(property_data).dtype)) == "list":
property_type = "tensor int int "+get_property_type(str(np.array(property_data[0][0]).dtype))
else:
property_type = "tensor "
for i in range(property_data.ndim - 1):
property_type += "int "
property_type += get_property_type(str(property_data.dtype))
ply_file.write("property "+property_type+" "+property_name+"\n")
ply_file.write("element face "+str(topomesh.nb_wisps(2))+"\n")
ply_file.write("property list int int vertex_index\n")
# if color_faces:
# ply_file.write("property uchar red\n")
# ply_file.write("property uchar green\n")
# ply_file.write("property uchar blue\n")
# triangle_data = array_dict(np.array([list(topomesh.regions(2,t))[0]%256 for t in topomesh.wisps(2)]),list(topomesh.wisps(2)))
for property_name in properties_to_save[2]:
if topomesh.has_wisp_property(property_name,2,is_computed=True):
property_data = topomesh.wisp_property(property_name,2).values()
if property_data.ndim == 1:
property_type = get_property_type(str(property_data.dtype))
if property_type == "list":
property_type = "list int "+get_property_type(str(np.array(property_data[0]).dtype))
elif property_data.ndim == 2:
property_type = "list int "+get_property_type(str(property_data.dtype))
if get_property_type(str(np.array(property_data).dtype)) == "list":
property_type = "tensor int int "+get_property_type(str(np.array(property_data[0][0]).dtype))
else:
property_type = "tensor "
for i in range(property_data.ndim - 1):
property_type += "int "
property_type += get_property_type(str(property_data.dtype))
ply_file.write("property "+property_type+" "+property_name+"\n")
ply_file.write("element edge "+str(topomesh.nb_wisps(1))+"\n")
ply_file.write("property int source\n")
ply_file.write("property int target\n")
ply_file.write("property list int int face_index\n")
for property_name in properties_to_save[1]:
if topomesh.has_wisp_property(property_name,1,is_computed=True):
property_data = topomesh.wisp_property(property_name,1).values()
if property_data.ndim == 1:
property_type = get_property_type(str(property_data.dtype))
if property_type == "list":
property_type = "list int "+get_property_type(str(np.array(property_data[0]).dtype))
elif property_data.ndim == 2:
property_type = "list int "+get_property_type(str(property_data.dtype))
if get_property_type(str(np.array(property_data).dtype)) == "list":
property_type = "tensor int int "+get_property_type(str(np.array(property_data[0][0]).dtype))
else:
property_type = "tensor "
for i in range(property_data.ndim - 1):
property_type += "int "
property_type += get_property_type(str(property_data.dtype))
ply_file.write("property "+property_type+" "+property_name+"\n")
ply_file.write("element volume "+str(topomesh.nb_wisps(3))+"\n")
ply_file.write("property list int int face_index\n")
ply_file.write("property int label\n")
for property_name in properties_to_save[3]:
if topomesh.has_wisp_property(property_name,3,is_computed=True):
property_data = topomesh.wisp_property(property_name,3).values()
if property_data.ndim == 1:
property_type = get_property_type(str(property_data.dtype))
if property_type == "list":
property_type = "list int "+get_property_type(str(np.array(property_data[0]).dtype))
elif property_data.ndim == 2:
property_type = "list int "+get_property_type(str(property_data.dtype))
if get_property_type(str(np.array(property_data).dtype)) == "list":
property_type = "tensor int int "+get_property_type(str(np.array(property_data[0][0]).dtype))
else:
property_type = "tensor "
for i in range(property_data.ndim - 1):
property_type += "int "
property_type += get_property_type(str(property_data.dtype))
ply_file.write("property "+property_type+" "+property_name+"\n")
ply_file.write("end_header\n")
vertex_index = {}
for v,pid in enumerate(topomesh.wisps(0)):
ply_file.write(str(topomesh.wisp_property(position_name,0)[pid][0])+" ")
ply_file.write(str(topomesh.wisp_property(position_name,0)[pid][1])+" ")
ply_file.write(str(topomesh.wisp_property(position_name,0)[pid][2]))
for property_name in properties_to_save[0]:
if property_name != position_name and topomesh.has_wisp_property(property_name,0,is_computed=True):
data = np.array(topomesh.wisp_property(property_name,0)[pid])
if data.ndim == 0:
ply_file.write(" "+str(data))
else:
ply_file.write(multidim_data_ply_string(data))
# for property_name in properties_to_save[0] :
# if property_name != position_name and topomesh.has_wisp_property(property_name,0,is_computed=True):
# property_type = property_types[str(topomesh.wisp_property(property_name,0).values().dtype)]
# if topomesh.wisp_property(property_name,0).values().ndim == 1:
# if property_type == 'int':
# ply_file.write(str(int(topomesh.wisp_property(property_name,0)[pid]))+" ")
# else:
# ply_file.write(str(topomesh.wisp_property(property_name,0)[pid])+" ")
# elif topomesh.wisp_property(property_name,0).values().ndim == 2:
# ply_file.write(str(int(len(topomesh.wisp_property(property_name,0)[fid])))+" ")
# for p in topomesh.wisp_property(property_name,0)[fid]:
# if property_type == 'int':
# ply_file.write(str(int(p))+" ")
# else:
# ply_file.write(str(p)+" ")
ply_file.write("\n")
vertex_index[pid] = v
face_index = {}
for t,fid in enumerate(topomesh.wisps(2)):
ply_file.write(str(len(list(topomesh.borders(2,fid,2))))+" ")
if topomesh.has_wisp_property('oriented_vertices',2,is_computed=True):
for i_pid, pid in enumerate(topomesh.wisp_property('oriented_vertices',2)[fid]):
ply_file.write((" " if i_pid>0 else "")+str(vertex_index[pid]))
else:
for i_pid, pid in enumerate(topomesh.borders(2,fid,2)):
ply_file.write((" " if i_pid>0 else "")+str(vertex_index[pid]))
# ply_file.write(str(len(list(topomesh.borders(2,fid))))+" ")
# for eid in topomesh.borders(2,fid):
# ply_file.write(str(edge_index[eid])+" ")
# if color_faces:
# ply_file.write(str(triangle_data[fid])+" ")
# ply_file.write(str(triangle_data[fid])+" ")
# ply_file.write(str(triangle_data[fid])+" ")
# if colormap is None:
# ply_file.write(str(triangle_data[fid])+" ")
# ply_file.write(str(triangle_data[fid])+" ")
# ply_file.write(str(triangle_data[fid])+" ")
# else:
# color = colormap._color_points.values()[int(triangle_data[fid])]
# ply_file.write(str(int(255*color[0]))+" ")
# ply_file.write(str(int(255*color[1]))+" ")
# ply_file.write(str(int(255*color[2]))+" ")
for property_name in properties_to_save[2]:
if topomesh.has_wisp_property(property_name, 2, is_computed=True):
data = np.array(topomesh.wisp_property(property_name, 2)[fid])
if data.ndim == 0:
ply_file.write(" " + str(data))
else:
ply_file.write(multidim_data_ply_string(data))
# for property_name in properties_to_save[2]:
# if topomesh.has_wisp_property(property_name,2,is_computed=True):
# property_type = property_types[str(topomesh.wisp_property(property_name,2).values().dtype)]
# if topomesh.wisp_property(property_name,2).values().ndim == 1:
# if property_type == 'int':
# ply_file.write(str(int(topomesh.wisp_property(property_name,2)[fid]))+" ")
# else:
# ply_file.write(str(topomesh.wisp_property(property_name,2)[fid])+" ")
# elif topomesh.wisp_property(property_name,2).values().ndim == 2:
# ply_file.write(str(int(len(topomesh.wisp_property(property_name,2)[fid])))+" ")
# for p in topomesh.wisp_property(property_name,2)[fid]:
# if property_type == 'int':
# ply_file.write(str(int(p))+" ")
# else:
# ply_file.write(str(p)+" ")
ply_file.write("\n")
face_index[fid] = t
edge_index = {}
for e,eid in enumerate(topomesh.wisps(1)):
ply_file.write(str(vertex_index[list(topomesh.borders(1,eid))[0]])+" ")
ply_file.write(str(vertex_index[list(topomesh.borders(1,eid))[1]])+" ")
ply_file.write(str(len(list(topomesh.regions(1,eid))))+" ")
for i_fid, fid in enumerate(topomesh.regions(1,eid)):
ply_file.write((" " if i_fid>0 else "")+str(face_index[fid]))
for property_name in properties_to_save[1]:
if topomesh.has_wisp_property(property_name, 1, is_computed=True):
data = np.array(topomesh.wisp_property(property_name, 1)[eid])
if data.ndim == 0:
ply_file.write(" " + str(data))
else:
ply_file.write(multidim_data_ply_string(data))
# for property_name in properties_to_save[1]:
# if topomesh.has_wisp_property(property_name,1,is_computed=True):
# property_type = property_types[str(topomesh.wisp_property(property_name,1).values().dtype)]
# if topomesh.wisp_property(property_name,1).values().ndim == 1:
# if property_type == 'int':
# ply_file.write(str(int(topomesh.wisp_property(property_name,1)[eid]))+" ")
# else:
# ply_file.write(str(topomesh.wisp_property(property_name,1)[eid])+" ")
# elif topomesh.wisp_property(property_name,1).values().ndim == 2:
# ply_file.write(str(int(len(topomesh.wisp_property(property_name,1)[eid])))+" ")
# for p in topomesh.wisp_property(property_name,1)[eid]:
# if property_type == 'int':
# ply_file.write(str(int(p))+" ")
# else:
# ply_file.write(str(p)+" ")
ply_file.write("\n")
edge_index[eid] = e
for c, cid in enumerate(topomesh.wisps(3)):
ply_file.write(str(len(list(topomesh.borders(3,cid))))+" ")
for i_fid, fid in enumerate(topomesh.borders(3,cid)):
ply_file.write((" " if i_fid>0 else "")+str(face_index[fid]))
ply_file.write(" "+str(cid))
for property_name in properties_to_save[3]:
if topomesh.has_wisp_property(property_name, 3, is_computed=True):
data = np.array(topomesh.wisp_property(property_name, 3)[cid])
if data.ndim == 0:
ply_file.write(" " + str(data))
else:
ply_file.write(multidim_data_ply_string(data))
# if topomesh.has_wisp_property(property_name,3,is_computed=True):
# property_type = property_types[str(topomesh.wisp_property(property_name,3).values().dtype)]
# if topomesh.wisp_property(property_name,3).values().ndim == 1:
# if property_type == 'int':
# ply_file.write(str(int(topomesh.wisp_property(property_name,3)[cid]))+" ")
# else:
# ply_file.write(str(topomesh.wisp_property(property_name,3)[cid])+" ")
# elif topomesh.wisp_property(property_name,3).values().ndim == 2:
# ply_file.write(str(int(len(topomesh.wisp_property(property_name,3)[cid])))+" ")
# for p in topomesh.wisp_property(property_name,3)[cid]:
# if property_type == 'int':
# ply_file.write(str(int(p))+" ")
# else:
# ply_file.write(str(p)+" ")
ply_file.write("\n")
ply_file.flush()
ply_file.close()
if verbose:
end_time = time()
print("<-- Saving .ply [",end_time-start_time,"s]")
[docs]def read_ply_property_topomesh(ply_filename, verbose=False, fuse_elements=True, fuse_vertices=True):
"""Read a PropertyTopomesh stored as a PLY file.
Read an ASCII-encoded PLY file containing a cell complex. The file can be a
regular mesh file with only `vertex` and `face` elements, but it can also
contain `edge` and `volume` elements that define topological elements of
dimensions 1 and 3 respectively. Associated properties can be of int, float,
string, vector or tensor types.
Parameters
----------
ply_filename : str
Path to the PLY file to read from
verbose : bool
Whether to print all information read from the file
fuse_elements : bool
Whether identical topological elements should be fused in a single wisp
fuse_vertices : bool
Whether vertices at the same position should be fused in a single wisp
Returns
-------
topomesh : :class:`cellcomplex.property_topomesh.PropertyTopomesh`
Cell complex with all the element properties read from the file
"""
if verbose:
start_time =time()
print("--> Reading .ply")
property_types = {}
property_types['int'] = 'int'
property_types['int32'] = 'int'
property_types['int16'] = 'int'
property_types['uint'] = 'int'
property_types['uint8'] = 'int'
property_types['uint16'] = 'int'
property_types['uchar'] = 'int'
property_types['float'] = 'float'
property_types['float32'] = 'float'
property_types['list'] = 'list'
property_types['tensor'] = 'tensor'
property_types['string'] = 'str'
property_types['|S7'] = 'str'
property_types['str'] = 'str'
ply_file = open(ply_filename,'rU')
ply_stream = enumerate(ply_file,1)
assert "ply" in next(ply_stream)[1]
assert "ascii" in next(ply_stream)[1]
n_wisps = {}
properties = {}
properties_types = {}
properties_list_types = {}
properties_tensor_dims = {}
element_name = ""
property_name = ""
elements = []
lineno, line = next(ply_stream)
while not 'end_header' in line:
try:
if re.split(' ',line)[0] == 'element':
element_name = re.split(' ',line)[1]
elements.append(element_name)
n_wisps[element_name] = int(re.split(' ',line)[2])
properties[element_name] = []
properties_types[element_name] = {}
properties_list_types[element_name] = {}
properties_tensor_dims[element_name] = {}
if re.split(' ',line)[0] == 'property':
# print line
property_name = re.split(' ',line)[-1][:-1]
properties[element_name].append(property_name)
properties_types[element_name][property_name] = re.split(' ',line)[1]
if properties_types[element_name][property_name] == 'list':
list_type = re.split(' ',line)[-2]
properties_list_types[element_name][property_name] = list_type
elif properties_types[element_name][property_name] == 'tensor':
properties_tensor_dims[element_name][property_name] = (np.array(re.split(' ',line))[:-2]=='int').sum()
list_type = re.split(' ',line)[-2]
properties_list_types[element_name][property_name] = list_type
except Exception as e:
raise ValueError(ply_filename, lineno, line, e)
lineno, line = next(ply_stream)
if verbose: print(n_wisps)
if verbose: print(properties)
if verbose: print(properties_list_types)
element_properties = {}
for element_name in elements:
element_properties[element_name] = {}
for wid in range(n_wisps[element_name]):
lineno, line = next(ply_stream)
line = line.strip()
line_props = {}
prop_index = 0
try:
for prop in properties[element_name]:
prop_type = properties_types[element_name][prop]
if verbose:
print(element_name," ",wid," - ",prop," (",property_types[prop_type],")")
if property_types[prop_type] == 'float':
line_props[prop] = float(re.split(' ',line)[prop_index])
prop_index += 1
elif property_types[prop_type] == 'int':
line_props[prop] = int(re.split(' ',line)[prop_index])
prop_index += 1
elif property_types[prop_type] == 'str':
line_props[prop] = str(re.split(' ',line)[prop_index])
prop_index += 1
elif property_types[prop_type] == 'list':
list_length = int(re.split(' ',line)[prop_index])
prop_index += 1
list_type = properties_list_types[element_name][prop]
if property_types[list_type] == 'float':
line_props[prop] = [float(p) for p in re.split(' ',line)[prop_index:prop_index+list_length]]
elif property_types[list_type] == 'int':
line_props[prop] = [int(p) for p in re.split(' ',line)[prop_index:prop_index+list_length]]
prop_index += list_length
elif property_types[prop_type] == 'tensor':
n_dims = properties_tensor_dims[element_name][prop]
tensor_dims = tuple(np.array(re.split(' ',line)[prop_index:prop_index+n_dims]).astype(int))
prop_index += n_dims
list_type = properties_list_types[element_name][prop]
line_props[prop] = np.array(re.split(' ',line)[prop_index:prop_index+np.prod(tensor_dims)]).astype(property_types[list_type]).reshape(tensor_dims)
prop_index += np.prod(tensor_dims)
if verbose:
print(element_name," ",wid," - ",prop," : ",line_props[prop])
except Exception as e:
raise ValueError(ply_filename, lineno, line, prop, property_types[prop_type], e)
element_properties[element_name][wid] = line_props
ply_file.close()
if verbose:
print("<-- Parsing .ply [",time()-start_time,"s]")
element_matching = {}
point_positions = {}
for pid in range(n_wisps['vertex']):
point_positions[pid] = np.array([element_properties['vertex'][pid][dim] for dim in ['x','y','z']])
face_vertices = {}
for fid in range(n_wisps['face']):
if 'vertex_index' in element_properties['face'][fid]:
face_vertices[fid] = element_properties['face'][fid]['vertex_index']
elif 'vertex_indices' in element_properties['face'][fid]:
face_vertices[fid] = element_properties['face'][fid]['vertex_indices']
timecheck = verbose
if fuse_elements:
forcetest = False
if timecheck: check_time =time()
if verbose: print(len(point_positions)," Points, ", len(face_vertices), " Faces")
if fuse_vertices:
unique_points = np.unique(np.array(list(point_positions.values())),axis=0)
if not forcetest and len(unique_points) == len(point_positions):
unique_points = np.array(list(point_positions.values()))
point_matching = array_dict(point_positions.keys(),point_positions.keys())
else:
point_matching = array_dict(kd_tree_match(np.array(list(point_positions.values())),unique_points),list(point_positions.keys()))
else:
unique_points = np.array(list(point_positions.values()))
point_matching = array_dict(point_positions.keys(), point_positions.keys())
element_matching['vertex'] = point_matching
if verbose: print(len(unique_points)," Unique Points")
if timecheck: print('point unicity test:',time()-check_time)
if timecheck: check_time =time()
faces = np.array(list(face_vertices.values()))
if len(faces)==0:
if verbose: print("No faces !")
triangular = True
unique_triangles = []
triangle_matching = {}
elif faces.ndim == 2:
if verbose: print("Faces = Triangles !")
triangular = True
triangles = np.sort(point_matching.values(faces))
unique_triangles = np.unique(triangles,axis=0)
if not forcetest and len(unique_triangles) == len(triangles):
unique_triangles = triangles
triangle_matching = array_dict(face_vertices.keys(),face_vertices.keys())
else:
triangle_matching = array_dict(kd_tree_match(triangles,unique_triangles),face_vertices.keys())
else:
triangular = False
if len(faces)>0:
unique_triangles = point_matching.values(faces)
triangle_matching = array_dict(list(face_vertices.keys()),list(face_vertices.keys()))
else:
unique_triangles = np.array([])
triangle_matching = array_dict()
element_matching['face'] = triangle_matching
if verbose: print(len(unique_triangles)," Unique Faces")
if timecheck: print('face unicity test:',time()-check_time)
if timecheck: check_time =time()
if 'edge' in n_wisps:
edge_vertices = {}
edge_faces = {}
for eid in range(n_wisps['edge']):
edge_faces[eid] = []
edge_vertices[eid] = point_matching.values(np.array([element_properties['edge'][eid][dim] for dim in ['source','target']]))
if 'face_index' in element_properties['edge'][eid]:
edge_faces[eid] = element_properties['edge'][eid]['face_index']
#print element_properties['edge']
if not 'face_index' in properties['edge'] and len(faces)>0:
face_edge_vertices = np.sort(np.concatenate([np.transpose([v,list(v[1:])+[v[0]]]) for v in unique_triangles]))
face_edge_faces = np.concatenate([fid*np.ones_like(unique_triangles[fid]) for fid in range(len(unique_triangles))])
face_edge_matching = kd_tree_match(face_edge_vertices,np.sort(list(edge_vertices.values())))
for eid in range(n_wisps['edge']):
edge_faces[eid] = []
for eid, fid in zip(face_edge_matching, face_edge_faces):
if eid is not None:
edge_faces[eid] += [fid]
else:
if triangular:
if len(unique_triangles) == 0:
edge_vertices = {}
edge_faces = {}
else:
edge_vertices = dict(zip(list(range(3*len(unique_triangles))),np.sort(np.concatenate([np.transpose([v,list(v[1:])+[v[0]]]) for v in unique_triangles]))))
edge_faces = dict(zip(list(range(3*len(unique_triangles))),np.concatenate([fid*np.ones_like(unique_triangles[fid]) for fid in range(len(unique_triangles))])))
else:
edge_index = list(range(len(unique_triangles[0])))
for v in unique_triangles[1:]:
edge_index += [edge_index[-1]+1+r for r in range(len(v))]
edge_vertices = dict(list(zip(edge_index,np.sort(np.concatenate([np.transpose([v,list(v[1:])+[v[0]]]) for v in unique_triangles])))))
edge_faces = dict(list(zip(edge_index,np.concatenate([fid*np.ones_like(unique_triangles[fid]) for fid in range(len(unique_triangles))]))))
if verbose: print(len(edge_vertices)," Edges")
if len(edge_vertices)>0:
unique_edges = np.unique(np.sort(list(edge_vertices.values())),axis=0)
if not forcetest and len(unique_edges) == len(edge_vertices.values()):
unique_edges = list(edge_vertices.values())
edge_matching = array_dict(list(edge_vertices.keys()),list(edge_vertices.keys()))
else:
# edge_matching = array_dict(vq(np.sort(edge_vertices.values()),unique_edges)[0],edge_vertices.keys())
edge_matching = array_dict(kd_tree_match(np.sort(list(edge_vertices.values())),unique_edges),list(edge_vertices.keys()))
else:
unique_edges = np.array([])
edge_matching = array_dict()
element_matching['edge'] = edge_matching
if verbose: print(len(unique_edges)," Unique Edges")
if timecheck: print('edge unicity test:',time()-check_time)
if timecheck: check_time =time()
face_cells = {}
for fid in range(len(unique_triangles)):
face_cells[fid] = set()
cell_matching = {}
if 'volume' in n_wisps:
oriented_cells = False
if np.any([np.any([f<0 for f in element_properties['volume'][c]['face_index']]) for c in range(n_wisps['volume'])]):
oriented_cells = True
if 'label' in properties['volume']:
for cid in range(n_wisps['volume']):
cell_matching[cid] = element_properties['volume'][cid]['label']
else:
cell_matching = dict(list(zip(list(range(n_wisps['volume'])),list(range(n_wisps['volume'])))))
if 'face_index' in properties['volume']:
for c in range(n_wisps['volume']):
for f in element_properties['volume'][c]['face_index']:
if oriented_cells:
face_cells[triangle_matching[np.abs(f)-1]] = face_cells[triangle_matching[np.abs(f)-1]].union({cell_matching[c]})
else:
face_cells[triangle_matching[f]] = face_cells[triangle_matching[f]].union({cell_matching[c]})
else:
for f in range(len(unique_triangles)):
face_cells[triangle_matching[f]] = {0}
else:
cell_matching[0] = 0
for f in range(len(unique_triangles)):
face_cells[triangle_matching[f]] = {0}
element_matching['volume'] = cell_matching
if verbose: print(len(cell_matching)," Cells")
if timecheck: print('cell unicity test:',time()-check_time)
else:
unique_points = np.array(list(point_positions.values()))
point_matching = array_dict(list(point_positions.keys()),list(point_positions.keys()))
faces = np.array(face_vertices.values())
if len(faces) == 0:
if verbose: print("No faces !")
triangular = True
unique_triangles = []
triangle_matching = {}
elif faces.ndim == 2:
if verbose: print("Faces = Triangles !")
triangular = True
unique_triangles = np.sort(faces)
triangle_matching = array_dict(list(face_vertices.keys()),list(face_vertices.keys()))
else:
triangular = False
if len(faces)>0:
unique_triangles = point_matching.values(faces)
triangle_matching = array_dict(list(face_vertices.keys()),list(face_vertices.keys()))
else:
unique_triangles = np.array([])
triangle_matching = array_dict()
element_matching['face'] = triangle_matching
if triangular:
if len(unique_triangles) == 0:
edge_vertices = {}
edge_faces = {}
else:
edge_vertices = dict(zip(list(range(3*len(unique_triangles))),np.sort(np.concatenate([np.transpose([v,list(v[1:])+[v[0]]]) for v in unique_triangles]))))
edge_faces = dict(zip(list(range(3*len(unique_triangles))),np.concatenate([fid*np.ones_like(unique_triangles[fid]) for fid in range(len(unique_triangles))])))
else:
edge_index = list(range(len(unique_triangles[0])))
for v in unique_triangles[1:]:
edge_index += [edge_index[-1]+1+r for r in range(len(v))]
edge_vertices = dict(list(zip(edge_index,np.sort(np.concatenate([np.transpose([v,list(v[1:])+[v[0]]]) for v in unique_triangles])))))
edge_faces = dict(list(zip(edge_index,np.concatenate([fid*np.ones_like(unique_triangles[fid]) for fid in range(len(unique_triangles))]))))
unique_edges = edge_vertices.values()
if len(unique_edges) == 0:
edge_matching = array_dict()
else:
edge_matching = array_dict(edge_vertices.keys(),edge_vertices.keys())
element_matching['edge'] = edge_matching
face_cells = {}
for fid in range(len(unique_triangles)):
face_cells[fid] = set()
cell_matching = {}
if 'volume' in n_wisps:
if 'label' in properties['volume']:
for cid in range(n_wisps['volume']):
cell_matching[cid] = element_properties['volume'][cid]['label']
else:
cell_matching = dict(list(zip(list(range(n_wisps['volume'])),list(range(n_wisps['volume'])))))
if 'face_index' in properties['volume']:
for c in range(n_wisps['volume']):
for f in element_properties['volume'][c]['face_index']:
face_cells[triangle_matching[f]] = face_cells[triangle_matching[f]].union({cell_matching[c]})
else:
for f in range(len(unique_triangles)):
face_cells[triangle_matching[f]] = {0}
else:
cell_matching[0] = 0
for f in range(len(unique_triangles)):
face_cells[triangle_matching[f]] = {0}
element_matching['volume'] = cell_matching
if timecheck: check_time =time()
topomesh = PropertyTopomesh(3)
for pid in range(len(unique_points)):
topomesh.add_wisp(0,pid)
for fid in range(len(unique_triangles)):
topomesh.add_wisp(2,fid)
for cid in face_cells[fid]:
if not topomesh.has_wisp(3, cid):
topomesh.add_wisp(3,cid)
topomesh.link(3,cid,fid)
for eid,e in enumerate(unique_edges):
topomesh.add_wisp(1,eid)
for pid in e:
topomesh.link(1,eid,pid)
for e in edge_vertices.keys():
eid = edge_matching[e]
if isinstance(edge_faces[e],list):
for f in edge_faces[e]:
fid = triangle_matching[f]
topomesh.link(2,fid,eid)
else:
fid = edge_faces[e]
topomesh.link(2,fid,eid)
if timecheck: print('topomesh topo creation:',time()-check_time)
topomesh.update_wisp_property('barycenter',0,array_dict(unique_points,np.arange(len(unique_points))))
native_properties = {}
native_properties['vertex'] = ['x','y','z']
native_properties['edge'] = ['source','target','face_index']
native_properties['face'] = ['vertex_index','vertex_indices','red','green','blue']
native_properties['volume'] = ['face_index','label']
for property_degree, element_name in zip([0,1,2,3],['vertex','edge','face','volume']):
if element_name in n_wisps:
for property_name in properties[element_name]:
if property_name not in native_properties[element_name]:
if verbose: print("Adding "+property_name+" "+element_name+" property")
property_dict = {}
for w in element_properties[element_name].keys():
property_dict[element_matching[element_name][w]] = element_properties[element_name][w][property_name]
try:
topomesh.update_wisp_property(property_name,property_degree,array_dict(property_dict))
except ValueError:
property_dict = dict(zip(property_dict.keys(),[list(property_dict[k]) for k in property_dict.keys()]))
topomesh.update_wisp_property(property_name,property_degree,array_dict(property_dict))
if timecheck: print('topomesh creation:',time()-check_time)
if verbose:
end_time = time()
print("<-- Reading .ply [",end_time-start_time,"s]")
return topomesh
[docs]def read_obj_property_topomesh(obj_filename, verbose=True):
"""
"""
import re
# from cellcomplex.property_topomesh.utils.array_tools import array_unique
from cellcomplex.property_topomesh.creation import triangle_topomesh
if verbose:
start_time =time()
print("--> Reading .obj")
obj_file = open(obj_filename,'rU')
if not obj_file:
raise IOError("Unable to open "+obj_filename+"!")
obj_stream = enumerate(obj_file,1)
vertices = []
faces = []
vertex_normals = []
face_normals = []
for lineno, line in obj_stream:
if len(line)>0:
if re.split(' ',line)[0] == 'v':
vertices += [np.array(re.split(' ',line)[1:4]).astype(float)]
if re.split(' ',line)[0] == 'f':
if '//' in line:
faces += [np.array([re.split('//',v)[0] for v in re.split(' ',line)[1:]]).astype(int) - 1]
elif '/' in line:
faces += [np.array([re.split('/',v)[0] for v in re.split(' ',line)[1:]]).astype(int) - 1]
else:
faces += [np.array([v for v in re.split(' ',line)[1:4]]).astype(int) - 1]
vertex_positions = dict(list(zip(list(range(len(vertices))),vertices)))
topomesh = triangle_topomesh(faces,vertex_positions)
return topomesh
[docs]def save_obj_property_topomesh(topomesh, obj_filename, reorient_faces=False, verbose=False):
if reorient_faces:
compute_topomesh_property(topomesh,'normal',2,normal_method='orientation')
start_time =time()
print("--> Saving .obj + .mtl")
mtlfile = open(obj_filename[:-4]+".mtl",'w')
for c in topomesh.wisps(3):
mtlfile.write("newmtl mat"+str(c)+"\n")
col = [np.random.rand(),np.random.rand(),np.random.rand()]
mtlfile.write(" Ka "+str(col[0])+" "+str(col[1])+" "+str(col[2])+"\n")
mtlfile.write(" Kd "+str(col[0])+" "+str(col[1])+" "+str(col[2])+"\n")
mtlfile.write(" Ks 0.0 0.0 0.0\n")
mtlfile.write(" Ns 0.0\n")
mtlfile.write(" d 1.0\n")
mtlfile.write(" Tr 1.0\n")
objfile = open(obj_filename,'w')
objfile.write("#\n")
objfile.write("# Wavefront OBJ file\n")
objfile.write("# TextureMontage Atlas\n")
objfile.write("#\n")
objfile.write("mtllib "+obj_filename[:-4]+".mtl\n")
vertex_index = {}
for i,v in enumerate(list(topomesh.wisps(0))):
pos = topomesh.wisp_property('barycenter',0)[v]
objfile.write("v "+str(pos[0])+" "+str(pos[1])+" "+str(pos[2])+"\n")
vertex_index[v] = i
for c in topomesh.wisps(3):
objfile.write("g object"+str(c)+"\n")
objfile.write("usemtl mat"+str(c)+"\n")
for t in topomesh.borders(3,c):
if reorient_faces:
# tri = list(topomesh.borders(2,t,2))[::topomesh.wisp_property('orientation',2)[t]]
tri = list(topomesh.wisp_property('oriented_vertices',2)[t])[::topomesh.wisp_property('orientation',2)[t]]
else:
tri = list(topomesh.borders(2,t,2))
objfile.write("f "+str(vertex_index[tri[0]]+1)+"/"+str(c)+" "+str(vertex_index[tri[1]]+1)+"/"+str(c)+" "+str(vertex_index[tri[2]]+1)+"/"+str(c)+"\n")
objfile.close()
end_time = time()
print("<-- Saving .obj + .mtl [",end_time-start_time,"s]")
[docs]def read_msh_property_topomesh(msh_filename, preserve_cells=True, verbose=False):
"""
"""
import re
# from cellcomplex.property_topomesh.utils.array_tools import array_unique
from cellcomplex.property_topomesh.creation import triangle_topomesh
if verbose:
start_time =time()
print("--> Reading .msh")
msh_file = open(msh_filename,'rU')
if not msh_file:
raise IOError("Unable to open "+msh_filename+"!")
msh_stream = enumerate(msh_file,1)
vertex_positions = {}
faces = []
face_cells = []
vertex_normals = []
face_normals = []
lineno, line = next(msh_stream)
while not "$MeshFormat" in line:
lineno, line = next(msh_stream)
lineno, line = next(msh_stream)
mesh_format = line
while not "$Nodes" in line:
lineno, line = next(msh_stream)
lineno, line = next(msh_stream)
n_nodes = int(re.split(' ',line)[0])
print(n_nodes," Nodes")
for n in range(n_nodes):
lineno, line = next(msh_stream)
nid = int(re.split(' ',line)[0])
n_pos = np.array(re.split(' ',line)[1:4]).astype(float)
vertex_positions[nid] = n_pos
lineno, line = next(msh_stream)
assert "$EndNodes" in line
while not "$Elements" in line:
lineno, line = next(msh_stream)
lineno, line = next(msh_stream)
n_elements = int(re.split(' ',line)[0])
print(n_elements," Elements")
# 2 : triangular face
# 1 : edge
# 15 : point
element_node_number = dict([(2,3),(1,2),(15,1)])
#element_node_number = dict([(1,2),(15,1)])
for e in range(n_elements):
lineno, line = next(msh_stream)
eid = int(re.split(' ',line)[0])
e_type = int(re.split(' ',line)[1])
n_tags = int(re.split(' ',line)[2])
e_tags = np.array(re.split(' ',line)[3:3+n_tags]).astype(int)
cell = e_tags[-1]
try:
e_nodes = np.array([re.split(' ',line)[3+n_tags+i] for i in range(element_node_number[e_type])]).astype(int)
except KeyError:
raise KeyError("MSH Element type "+str(e_type)+" not handled yet!")
if e_type == 2:
faces += [list(e_nodes)]
face_cells += [cell]
lineno, line = next(msh_stream)
assert "$EndElements" in line
msh_file.close()
topomesh = triangle_topomesh(faces,vertex_positions)
if preserve_cells:
topomesh.remove_wisp(3,0)
for cid in np.sort(np.unique(face_cells)):
topomesh.add_wisp(3,cid)
for fid,cid in enumerate(face_cells):
topomesh.link(3,cid,fid)
return topomesh
[docs]def meshread(filename):
file_formats = ['.ply','.obj','.msh']
# extension = path(filename).ext
extension = os.path.splitext(filename)[1]
try:
assert extension in file_formats
except AssertionError:
raise IOError("The file format "+extension+" is not recognized, only "+str(file_formats)+" mesh files are supported")
else:
if extension == '.ply':
return read_ply_property_topomesh(filename)
elif extension == '.obj':
return read_obj_property_topomesh(filename)
elif extension == '.msh':
return read_msh_property_topomesh(filename)