importMRDAT.hpp 7.21 KB
Newer Older
Pierre Kraemer's avatar
Pierre Kraemer committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps  *
* version 0.1                                                                  *
* Copyright (C) 2009-2012, IGG Team, LSIIT, University of Strasbourg           *
*                                                                              *
* This library is free software; you can redistribute it and/or modify it      *
* under the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, or (at your     *
* option) any later version.                                                   *
*                                                                              *
* This library 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 Lesser General Public License  *
* for more details.                                                            *
*                                                                              *
* You should have received a copy of the GNU Lesser General Public License     *
* along with this library; if not, write to the Free Software Foundation,      *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.           *
*                                                                              *
* Web site: http://cgogn.unistra.fr/                                           *
* Contact information: cgogn@unistra.fr                                        *
*                                                                              *
*******************************************************************************/

namespace CGoGN
{

namespace Algo
{

31 32 33
namespace Surface
{

Pierre Kraemer's avatar
Pierre Kraemer committed
34 35 36 37 38 39 40 41 42 43 44
namespace Import
{

inline void nextNonEmptyLine(std::ifstream& fp, std::string& line)
{
	do {
		std::getline(fp, line) ;
	} while (line.size() == 0) ;
}

template <typename PFP>
Pierre Kraemer's avatar
Pierre Kraemer committed
45
bool importMRDAT(typename PFP::MAP& map, const std::string& filename, std::vector<std::string>& attrNames, QuadTree& qt)
Pierre Kraemer's avatar
Pierre Kraemer committed
46
{
Pierre Kraemer's avatar
Pierre Kraemer committed
47
	VertexAttribute<typename PFP::VEC3> position = map.template getAttribute<typename PFP::VEC3, VERTEX>("position") ;
Pierre Kraemer's avatar
Pierre Kraemer committed
48
	if (!position.isValid())
Pierre Kraemer's avatar
Pierre Kraemer committed
49
		position = map.template addAttribute<typename PFP::VEC3, VERTEX>("position") ;
Pierre Kraemer's avatar
Pierre Kraemer committed
50 51 52

	attrNames.push_back(position.name()) ;

Pierre Kraemer's avatar
Pierre Kraemer committed
53
	AttributeContainer& container = map.template getAttributeContainer<VERTEX>() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77

	// open file
	std::ifstream fp(filename.c_str(), std::ios::in) ;
	if (!fp.good())
	{
		CGoGNerr << "Unable to open file " << filename << CGoGNendl ;
		return false ;
	}

	std::string line ;

	nextNonEmptyLine(fp, line) ;
	if (line.rfind("Multires data file") == std::string::npos)
	{
		CGoGNerr << "Problem reading MRDAT file" << CGoGNendl ;
		CGoGNerr << line << CGoGNendl ;
		return false ;
	}

	// read the depth
	unsigned int depth ;
	{
		nextNonEmptyLine(fp, line) ;
		std::stringstream oss(line) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
78 79
		std::string s ;
		oss >> s ;
80 81
		oss >> qt.depth ;
		depth = qt.depth;
Pierre Kraemer's avatar
Pierre Kraemer committed
82
	}
Pierre Kraemer's avatar
Pierre Kraemer committed
83 84

	std::cout << "  MR depth -> " << depth << std::endl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
85 86 87 88 89 90 91 92 93 94

	// read vertices
	nextNonEmptyLine(fp, line) ;
	if (line.rfind("Vertices") == std::string::npos)
	{
		CGoGNerr << "Problem reading MRDAT file" << CGoGNendl ;
		CGoGNerr << line << CGoGNendl ;
		return false ;
	}

Pierre Kraemer's avatar
Pierre Kraemer committed
95 96
	std::cout << "  Read vertices.." << std::flush ;

97 98 99
	qt.roots.clear() ;
	qt.darts.clear() ;
	qt.verticesID.clear() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
100 101

	nextNonEmptyLine(fp, line) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
102
	while(line.rfind("Triangles") == std::string::npos)
Pierre Kraemer's avatar
Pierre Kraemer committed
103 104 105 106 107 108 109 110 111 112
	{
		std::stringstream oss(line) ;

		unsigned int level ;
		oss >> level ;

		float x, y, z ;
		oss >> x ;
		oss >> y ;
		oss >> z ;
Pierre Kraemer's avatar
Pierre Kraemer committed
113 114 115 116
		typename PFP::VEC3 pos(x, y, z) ;

		unsigned int id = container.insertLine() ;
		position[id] = pos ;
117
		qt.verticesID.push_back(id) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
118 119 120 121

		nextNonEmptyLine(fp, line) ;
	}

122
	std::cout << "..done (nb vertices -> " << qt.verticesID.size() << ")" << std::endl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
123 124
	std::cout << "  Read triangles (build quadtree).." << std::flush ;

Pierre Kraemer's avatar
Pierre Kraemer committed
125
	QuadTreeNode* current = NULL ;
Pierre Kraemer's avatar
Pierre Kraemer committed
126
	unsigned int currentLevel = -1 ;
Pierre Kraemer's avatar
Pierre Kraemer committed
127 128
	std::vector<unsigned int> lastNum ;
	lastNum.resize(depth + 1) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
129 130

	nextNonEmptyLine(fp, line) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
131
	while(line.rfind("end") == std::string::npos)
Pierre Kraemer's avatar
Pierre Kraemer committed
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
	{
		std::stringstream oss(line) ;

		std::string name ;
		oss >> name ;

		unsigned int num, root, idx0, idx1, idx2 ;
		oss >> num ;
		oss >> root ;
		oss >> idx0 ;
		oss >> idx1 ;
		oss >> idx2 ;

		if(root == 1)
		{
			assert(num == 0) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
148
			QuadTreeNode* n = new QuadTreeNode() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
149 150 151 152 153
			n->indices[0] = idx0 ;
			n->indices[1] = idx1 ;
			n->indices[2] = idx2 ;
			qt.roots.push_back(n) ;
			current = n ;
Pierre Kraemer's avatar
Pierre Kraemer committed
154
			currentLevel = 0 ;
Pierre Kraemer's avatar
Pierre Kraemer committed
155
			lastNum[0] = 0 ;
Pierre Kraemer's avatar
Pierre Kraemer committed
156 157 158
		}
		else
		{
Pierre Kraemer's avatar
Pierre Kraemer committed
159
			if(num == lastNum[currentLevel] + 1) // on lit un autre triangle du même niveau
Pierre Kraemer's avatar
Pierre Kraemer committed
160
			{
Pierre Kraemer's avatar
Pierre Kraemer committed
161
				current = current->parent->children[num] ;
Pierre Kraemer's avatar
Pierre Kraemer committed
162
			}
Pierre Kraemer's avatar
Pierre Kraemer committed
163
			else // on monte ou on descend d'un niveau
Pierre Kraemer's avatar
Pierre Kraemer committed
164
			{
Pierre Kraemer's avatar
Pierre Kraemer committed
165
				if(num == 0) // on subdivise le triangle courant
Pierre Kraemer's avatar
Pierre Kraemer committed
166 167
				{
					current->subdivide() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
168
					current = current->children[0] ;
Pierre Kraemer's avatar
Pierre Kraemer committed
169
					++currentLevel ;
Pierre Kraemer's avatar
Pierre Kraemer committed
170
				}
Pierre Kraemer's avatar
Pierre Kraemer committed
171
				else // on remonte d'un niveau
Pierre Kraemer's avatar
Pierre Kraemer committed
172
				{
Pierre Kraemer's avatar
Pierre Kraemer committed
173 174 175 176 177 178
					assert(lastNum[currentLevel] == 3) ;
					do
					{
						current = current->parent->parent->children[num] ;
						--currentLevel ;
					} while(lastNum[currentLevel] == 3) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
179 180
				}
			}
Pierre Kraemer's avatar
Pierre Kraemer committed
181 182 183
			current->indices[0] = idx0 ;
			current->indices[1] = idx1 ;
			current->indices[2] = idx2 ;
Pierre Kraemer's avatar
Pierre Kraemer committed
184
			lastNum[currentLevel] = num ;
Pierre Kraemer's avatar
Pierre Kraemer committed
185 186 187 188 189
		}

		nextNonEmptyLine(fp, line) ;
	}

Pierre Kraemer's avatar
Pierre Kraemer committed
190 191
	std::cout << "..done" << std::endl ;

Pierre Kraemer's avatar
Pierre Kraemer committed
192 193
	fp.close() ;

Pierre Kraemer's avatar
Pierre Kraemer committed
194 195
	std::cout << "  Create base level mesh.." << std::flush ;

196
	VertexAutoAttribute< NoTypeNameAttribute< std::vector<Dart> > > vecDartsPerVertex(map, "incidents") ;
Pierre Kraemer's avatar
Pierre Kraemer committed
197 198 199 200 201 202 203 204 205 206 207 208
	DartMarkerNoUnmark m(map) ;

	unsigned nbf = qt.roots.size() ;

	// for each root face
	for(unsigned int i = 0; i < nbf; ++i)
	{
		Dart d = map.newFace(3, false) ;
		qt.darts.push_back(d) ;
		for (unsigned int j = 0; j < 3; ++j)
		{
			unsigned int idx = qt.roots[i]->indices[j] ;
209
			unsigned int emb = qt.verticesID[idx] ;
Pierre Kraemer's avatar
Pierre Kraemer committed
210

211
			FunctorSetEmb<typename PFP::MAP, VERTEX> fsetemb(map, emb) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
212
			map.template foreach_dart_of_orbit<PFP::MAP::VERTEX_OF_PARENT>(d, fsetemb) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228

			m.mark(d) ;								// mark on the fly to unmark on second loop
			vecDartsPerVertex[emb].push_back(d) ;	// store incident darts for fast adjacency reconstruction
			d = map.phi1(d) ;
		}
	}

	// reconstruct neighbourhood between root faces
	unsigned int nbBoundaryEdges = 0 ;
	for (Dart d = map.begin(); d != map.end(); map.next(d))
	{
		if (m.isMarked(d))
		{
			// darts incident to end vertex of edge
			std::vector<Dart>& vec = vecDartsPerVertex[map.phi1(d)] ;

Pierre Kraemer's avatar
Pierre Kraemer committed
229
			unsigned int embd = map.template getEmbedding<VERTEX>(d) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
230 231 232
			Dart good_dart = NIL ;
			for (typename std::vector<Dart>::iterator it = vec.begin(); it != vec.end() && good_dart == NIL; ++it)
			{
Pierre Kraemer's avatar
Pierre Kraemer committed
233
				if (map.template getEmbedding<VERTEX>(map.phi1(*it)) == embd)
Pierre Kraemer's avatar
Pierre Kraemer committed
234 235 236 237 238 239
					good_dart = *it ;
			}

			if (good_dart != NIL)
			{
				map.sewFaces(d, good_dart, false) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
240
				m.unmarkOrbit<EDGE>(d) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
241 242 243 244 245 246 247 248 249 250 251 252
			}
			else
			{
				m.unmark(d) ;
				++nbBoundaryEdges ;
			}
		}
	}

	if (nbBoundaryEdges > 0)
	{
//		map.closeMap() ;
Pierre Kraemer's avatar
Pierre Kraemer committed
253
		CGoGNout << "Open mesh.. not managed yet.." << CGoGNendl ;
Pierre Kraemer's avatar
Pierre Kraemer committed
254 255 256
		return false ;
	}

Pierre Kraemer's avatar
Pierre Kraemer committed
257 258
	std::cout << "..done" << std::endl ;

Pierre Kraemer's avatar
Pierre Kraemer committed
259
	return true ;
Pierre Kraemer's avatar
Pierre Kraemer committed
260 261 262 263
}

} // namespace Import

264 265
}

Pierre Kraemer's avatar
Pierre Kraemer committed
266 267 268
} // namespace Algo

} // namespace CGoGN