aimsdata  5.0.5
Neuroimaging data handling
plyr.h
Go to the documentation of this file.
1 /* This software and supporting documentation are distributed by
2  * Institut Federatif de Recherche 49
3  * CEA/NeuroSpin, Batiment 145,
4  * 91191 Gif-sur-Yvette cedex
5  * France
6  *
7  * This software is governed by the CeCILL-B license under
8  * French law and abiding by the rules of distribution of free software.
9  * You can use, modify and/or redistribute the software under the
10  * terms of the CeCILL-B license as circulated by CEA, CNRS
11  * and INRIA at the following URL "http://www.cecill.info".
12  *
13  * As a counterpart to the access to the source code and rights to copy,
14  * modify and redistribute granted by the license, users are provided only
15  * with a limited warranty and the software's author, the holder of the
16  * economic rights, and the successive licensors have only limited
17  * liability.
18  *
19  * In this respect, the user's attention is drawn to the risks associated
20  * with loading, using, modifying and/or developing or reproducing the
21  * software by the user in light of its specific status of free software,
22  * that may mean that it is complicated to manipulate, and that also
23  * therefore means that it is reserved for developers and experienced
24  * professionals having in-depth computer knowledge. Users are therefore
25  * encouraged to load and test the software's suitability as regards their
26  * requirements in conditions enabling the security of their systems and/or
27  * data to be ensured and, more generally, to use and operate it in the
28  * same conditions as regards security.
29  *
30  * The fact that you are presently reading this means that you have had
31  * knowledge of the CeCILL-B license and that you accept its terms.
32  */
33 
34 #ifndef AIMS_IO_PLYR_H
35 #define AIMS_IO_PLYR_H
36 
37 #include <aims/data/data.h>
38 #include <aims/io/plyheader.h>
39 #include <aims/io/datatypecode.h>
44 #include <aims/rply/rply.h>
45 
46 #include <aims/mesh/texture.h>
47 #include <aims/io/writer.h>
48 
49 
50 namespace aims
51 {
52 
53  template<long D, typename T>
54  class PlyReader
55  {
56  public:
57  PlyReader( const std::string& name ) : _name( name ) {}
59 
60  void read( AimsTimeSurface<D,T>& thing,
61  const carto::AllocatorContext & context,
62  carto::Object options );
63 
64  private:
65  static int ply_vertex_cb(p_ply_argument argument);
66  static int ply_normal_cb(p_ply_argument argument);
67  static int ply_face_cb(p_ply_argument argument);
68  static int ply_tex_cb(p_ply_argument argument);
69  std::string _name;
70  };
71 
72 
73  template <long D, typename T>
74  inline PlyReader<D,T> &
76  {
77  reader.read( thing, thing.allocator(),
79  return reader;
80  }
81 
82 
83  template <long D, typename T>
85  {
86  long n;
87  void *pdata;
88  if( !ply_get_argument_user_data(argument, &pdata, &n) )
89  return 0;
91  double x = ply_get_argument_value(argument);
92  if( n == 0 )
93  mesh->begin()->second.vertex().push_back( Point3df( (float) x, 0,
94  0 ) );
95  else
96  mesh->begin()->second.vertex().back()[n] = (float) x;
97  return 1;
98  }
99 
100 
101  template <long D, typename T>
102  inline int PlyReader<D,T>::ply_normal_cb(p_ply_argument argument)
103  {
104  long n;
105  void *pdata;
106  if( !ply_get_argument_user_data(argument, &pdata, &n) )
107  return 0;
108  AimsTimeSurface<D,T> *mesh = (AimsTimeSurface<D,T> *) pdata;
109  double x = ply_get_argument_value(argument);
110  if( n == 0 )
111  mesh->begin()->second.normal().push_back( Point3df( (float) x, 0,
112  0 ) );
113  else
114  mesh->begin()->second.normal().back()[n] = (float) x;
115  return 1;
116  }
117 
118 
119  template <long D, typename T>
120  inline int PlyReader<D,T>::ply_tex_cb(p_ply_argument argument)
121  {
122  long n;
123  void *pdata;
124  if( !ply_get_argument_user_data(argument, &pdata, &n) )
125  return 0;
126  TimeTexture<float> *tex = (TimeTexture<float> *) pdata;
127  double x = ply_get_argument_value(argument);
128  (*tex)[n].push_back( (float) x );
129  return 1;
130  }
131 
132 
133  template <long D, typename T>
134  inline int PlyReader<D,T>::ply_face_cb(p_ply_argument argument)
135  {
136  long length, value_index;
137  void *pdata;
138  ply_get_argument_property(argument, NULL, &length, &value_index);
139  if( !ply_get_argument_user_data(argument, &pdata, 0) )
140  return 0;
141  AimsTimeSurface<D,T> *mesh = (AimsTimeSurface<D,T> *) pdata;
142  if( value_index == 0 )
143  {
145  v[0] = (uint) rint( ply_get_argument_value(argument) );
146  mesh->begin()->second.polygon().push_back( v );
147  }
148  else if( value_index > 0 && value_index < D )
149  mesh->begin()->second.polygon().back()[ value_index ]
150  = (uint) rint( ply_get_argument_value(argument) );
151  else if( value_index > 0 )
152  std::cerr << "polygon with too many items: " << value_index << "\n";
153  return 1;
154  }
155 
156 
157  template <long D, typename T>
158  inline
160  const carto::AllocatorContext & /*context*/,
161  carto::Object /*options*/ )
162  {
163  /* std::cout << "PlyReader<" << D << ", " << carto::DataTypeCode<T>::name()
164  << ">\n"; */
165  PlyHeader hdr( _name );
166  hdr.read();
167 
168  long nvertices, ntriangles;
169  p_ply ply = ply_open( _name.c_str(), NULL, 0, 0 );
170  if (!ply)
171  throw carto::wrong_format_error( _name );
172  if (!ply_read_header(ply))
173  throw carto::wrong_format_error( _name );
174 
175  nvertices = ply_set_read_cb(ply, "vertex", "x", ply_vertex_cb, &thing, 0);
176  thing.vertex().reserve( nvertices );
177  thing.normal().reserve( nvertices );
178  ply_set_read_cb(ply, "vertex", "y", ply_vertex_cb, &thing, 1);
179  ply_set_read_cb(ply, "vertex", "z", ply_vertex_cb, &thing, 2);
180  ply_set_read_cb(ply, "vertex", "nx", ply_normal_cb, &thing, 0);
181  ply_set_read_cb(ply, "vertex", "ny", ply_normal_cb, &thing, 1);
182  ply_set_read_cb(ply, "vertex", "nz", ply_normal_cb, &thing, 2);
183 
184  std::vector<std::string> textures;
185  carto::ObjectVector *tex = 0;
186  hdr.getProperty( "texture_names", textures );
187  unsigned ntex = textures.size();
188  if( ntex )
189  {
192  hdr.setProperty( "textures", o );
193  tex = &o->carto::GenericObject::value<carto::ObjectVector>();
194  tex->reserve( ntex );
195  unsigned i;
196 
197  for( i=0; i<ntex; ++i )
198  {
199  tex->push_back( carto::Object::value( TimeTexture<float>() ) );
200  ply_set_read_cb( ply, "vertex", textures[i].c_str(), ply_tex_cb,
201  &(*tex)[i]->carto::GenericObject::value
202  < TimeTexture<float> >(), 0 );
203  }
204  }
205 
206  ntriangles = ply_set_read_cb(ply, "face", "vertex_indices", ply_face_cb,
207  &thing, 0);
208  thing.polygon().reserve( ntriangles );
209  int res = ply_read(ply);
210  ply_close(ply);
211  if( !res )
212  throw carto::invalid_format_error( "PLY reader failed", _name );
213 
214  // verify polygons are all in the vertices range
215  std::vector<AimsVector<uint,D> > & poly = thing.polygon();
216  typename std::vector<AimsVector<uint,D> >::iterator ip;
217  bool broken = false;
218  for ( ip=poly.begin(); ip!=poly.end(); ++ip )
219  {
220  AimsVector<uint,D> & pol = *ip;
221  for ( int j=0; j<D; ++j )
222  if ( pol[j] >= (unsigned) nvertices )
223  {
224  if ( !broken )
225  {
226  broken = true;
227  std::cerr << "Broken mesh: polygon pointing to a "
228  << "vertex out of range" << std::endl;
229  std::cerr << pol[j] << " >= " << nvertices << std::endl;
230  }
231  poly.erase( ip );
232  --ip;
233  break;
234  }
235  }
236  if( thing.normal().size() != thing.vertex().size() )
237  thing.updateNormals();
238 
239  // std::cout << "PLY read OK\n";
240 
241  if( hdr.hasProperty( "filenames" ) )
242  hdr.removeProperty( "filenames" );
243  thing.setHeader( hdr );
244  }
245 
246 }
247 
248 #endif
249 
GenesisReader< T > & operator>>(GenesisReader< T > &reader, AimsData< T > &thing)
Definition: genesisR.h:70
virtual bool getProperty(const std::string &, Object &) const
long ply_set_read_cb(p_ply ply, const char *element_name, const char *property_name, p_ply_read_cb read_cb, void *pdata, long idata)
virtual bool read(uint32_t *offset=0)
Reads the header, and if offset is not null, sets the file offset to the data field.
void read(AimsTimeSurface< D, T > &thing, const carto::AllocatorContext &context, carto::Object options)
Definition: plyr.h:159
struct t_ply_argument_ * p_ply_argument
Definition: rply.h:27
~PlyReader()
Definition: plyr.h:58
The class for EcatSino data write operation.
Definition: border.h:44
virtual bool removeProperty(const std::string &)
int ply_read(p_ply ply)
carto::Object textures
int ply_get_argument_property(p_ply_argument argument, p_ply_property *property, long *length, long *value_index)
The template class to manage a mesh with time if needed.
Definition: surface.h:290
const std::vector< AimsVector< uint, D > > & polygon() const
Get a const reference to the vector of polygons of the 0 surface.
Definition: surface.h:353
const std::vector< Point3df > & normal() const
Get a const reference to the vector of normals of the 0 surface.
Definition: surface.h:341
int ply_read_header(p_ply ply)
std::vector< Object > ObjectVector
struct t_ply_ * p_ply
Definition: rply.h:24
void updateNormals()
Update/Compute the normals.
Definition: surface.h:500
static Object value()
unsigned int uint
const T & value() const
p_ply ply_open(const char *name, p_ply_error_cb error_cb, long idata, void *pdata)
const std::vector< Point3df > & vertex() const
Get a const reference to the vector of verteces of the surface of index 0.
Definition: surface.h:335
virtual void setProperty(const std::string &, Object)
virtual bool hasProperty(const std::string &) const
PlyReader(const std::string &name)
Definition: plyr.h:57
double ply_get_argument_value(p_ply_argument argument)
int ply_close(p_ply ply)
void setHeader(const aims::PythonHeader &hdr)
Set the header.
Definition: surface.h:321
int ply_get_argument_user_data(p_ply_argument argument, void **pdata, long *idata)