1 // This file is part of libigl, a simple c++ geometry processing library.
2 //
3 // Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public License
6 // v. 2.0. If a copy of the MPL was not distributed with this file, You can
7 // obtain one at http://mozilla.org/MPL/2.0/.
8 #include "readNODE.h"
9 #include "matrix_to_list.h"
10 #include <stdio.h>
11
12 template <typename Scalar, typename Index>
readNODE(const std::string node_file_name,std::vector<std::vector<Scalar>> & V,std::vector<std::vector<Index>> & I)13 IGL_INLINE bool igl::readNODE(
14 const std::string node_file_name,
15 std::vector<std::vector<Scalar > > & V,
16 std::vector<std::vector<Index > > & I)
17 {
18 // TODO: should be templated
19 Eigen::MatrixXd mV;
20 Eigen::MatrixXi mI;
21 if(igl::readNODE(node_file_name,mV,mI))
22 {
23 matrix_to_list(mV,V);
24 matrix_to_list(mI,I);
25 return true;
26 }else
27 {
28 return false;
29 }
30 }
31
32 template <typename DerivedV, typename DerivedI>
readNODE(const std::string node_file_name,Eigen::PlainObjectBase<DerivedV> & V,Eigen::PlainObjectBase<DerivedI> & I)33 IGL_INLINE bool igl::readNODE(
34 const std::string node_file_name,
35 Eigen::PlainObjectBase<DerivedV>& V,
36 Eigen::PlainObjectBase<DerivedI>& I)
37 {
38 using namespace std;
39 FILE * node_file = fopen(node_file_name.c_str(),"r");
40 if(NULL==node_file)
41 {
42 fprintf(stderr,"readNODE: IOError: %s could not be opened...\n",
43 node_file_name.c_str());
44 return false;
45 }
46 #ifndef LINE_MAX
47 # define LINE_MAX 2048
48 #endif
49 char line[LINE_MAX];
50 bool still_comments;
51
52 // eat comments at beginning of file
53 still_comments= true;
54 while(still_comments)
55 {
56 fgets(line,LINE_MAX,node_file);
57 still_comments = (line[0] == '#' || line[0] == '\n');
58 }
59
60 // Read header
61 // n number of points
62 // dim dimension
63 // num_attr number of attributes
64 // num_bm number of boundary markers
65 int n,dim,num_attr,num_bm;
66 int head_count = sscanf(line,"%d %d %d %d", &n, &dim, &num_attr, &num_bm);
67 if(head_count!=4)
68 {
69 fprintf(stderr,"readNODE: Error: incorrect header in %s...\n",
70 node_file_name.c_str());
71 fclose(node_file);
72 return false;
73 }
74 if(num_attr)
75 {
76 fprintf(stderr,"readNODE: Error: %d attributes found in %s. "
77 "Attributes are not supported...\n",
78 num_attr,
79 node_file_name.c_str());
80 fclose(node_file);
81 return false;
82 }
83 // Just quietly ignore boundary markers
84 //if(num_bm)
85 //{
86 // fprintf(stderr,"readNODE: Warning: %d boundary markers found in %s. "
87 // "Boundary markers are ignored...\n",
88 // num_bm,
89 // node_file_name.c_str());
90 //}
91
92 // resize output
93 V.resize(n,dim);
94 I.resize(n,1);
95
96 int line_no = 0;
97 int p = 0;
98 while (fgets(line, LINE_MAX, node_file) != NULL)
99 {
100 line_no++;
101 // Skip comments and blank lines
102 if(line[0] == '#' || line[0] == '\n')
103 {
104 continue;
105 }
106 char * l = line;
107 int offset;
108
109 if(sscanf(l,"%d%n",&I(p),&offset) != 1)
110 {
111 fprintf(stderr,"readNODE Error: bad index (%d) in %s...\n",
112 line_no,
113 node_file_name.c_str());
114 fclose(node_file);
115 return false;
116 }
117 // adjust offset
118 l += offset;
119
120 // Read coordinates
121 for(int d = 0;d<dim;d++)
122 {
123 if(sscanf(l,"%lf%n",&V(p,d),&offset) != 1)
124 {
125 fprintf(stderr,"readNODE Error: bad coordinates (%d) in %s...\n",
126 line_no,
127 node_file_name.c_str());
128 fclose(node_file);
129 return false;
130 }
131 // adjust offset
132 l += offset;
133 }
134 // Read boundary markers
135 for(int b = 0;b<num_bm;b++)
136 {
137 int dummy;
138 if(sscanf(l,"%d%n",&dummy,&offset) != 1)
139 {
140 fprintf(stderr,"readNODE Error: bad boundary markers (%d) in %s...\n",
141 line_no,
142 node_file_name.c_str());
143 fclose(node_file);
144 return false;
145 }
146 // adjust offset
147 l += offset;
148 }
149 p++;
150 }
151
152 assert(p == V.rows());
153
154 fclose(node_file);
155 return true;
156 }
157
158 #ifdef IGL_STATIC_LIBRARY
159 // Explicit template instantiation
160 template bool igl::readNODE<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
161 #endif
162