aimsdata 6.0.0
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>
40#include <cartobase/exception/file.h>
41#include <cartobase/exception/format.h>
42#include <cartobase/stream/fileutil.h>
44#include <aims/rply/rply.h>
45
46#include <aims/mesh/texture.h>
47#include <aims/io/writer.h>
48
49
50namespace aims
51{
52
53 template<long D, typename T>
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>
84 inline int PlyReader<D,T>::ply_vertex_cb(p_ply_argument argument)
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 {
144 AimsVector<uint,D> v;
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,
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
The template class to manage a mesh with time if needed.
Definition surface.h:317
void setHeader(const aims::PythonHeader &hdr)
Set the header.
Definition surface.h:336
const std::vector< Point3df > & normal() const
Get a const reference to the vector of normals of the 0 surface.
Definition surface.h:354
const std::vector< AimsVector< uint, D > > & polygon() const
Get a const reference to the vector of polygons of the 0 surface.
Definition surface.h:366
void updateNormals()
Update/Compute the normals.
Definition surface.h:528
const std::vector< Point3df > & vertex() const
Get a const reference to the vector of verteces of the surface of index 0.
Definition surface.h:348
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
PlyReader(const std::string &name)
Definition plyr.h:57
const T & value() const
static Object value()
Object value(const Object &value)
virtual bool getProperty(const std::string &, Object &) const
virtual bool removeProperty(const std::string &)
virtual void setProperty(const std::string &, Object)
virtual bool hasProperty(const std::string &) const
The class for EcatSino data write operation.
GenesisReader< T > & operator>>(GenesisReader< T > &reader, AimsData< T > &thing)
Definition genesisR.h:70
std::vector< Object > ObjectVector
int ply_get_argument_user_data(p_ply_argument argument, void **pdata, long *idata)
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)
struct t_ply_argument_ * p_ply_argument
Definition rply.h:27
int ply_read_header(p_ply ply)
p_ply ply_open(const char *name, p_ply_error_cb error_cb, long idata, void *pdata)
int ply_get_argument_property(p_ply_argument argument, p_ply_property *property, long *length, long *value_index)
double ply_get_argument_value(p_ply_argument argument)
struct t_ply_ * p_ply
Definition rply.h:24
int ply_read(p_ply ply)
int ply_close(p_ply ply)
unsigned int uint
AimsVector< float, 3 > Point3df