Line data Source code
1 : /*
2 : * Copyright (c) 2010-2015: G-CSC, Goethe University Frankfurt
3 : * Author: Sebastian Reiter
4 : *
5 : * This file is part of UG4.
6 : *
7 : * UG4 is free software: you can redistribute it and/or modify it under the
8 : * terms of the GNU Lesser General Public License version 3 (as published by the
9 : * Free Software Foundation) with the following additional attribution
10 : * requirements (according to LGPL/GPL v3 §7):
11 : *
12 : * (1) The following notice must be displayed in the Appropriate Legal Notices
13 : * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14 : *
15 : * (2) The following notice must be displayed at a prominent place in the
16 : * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17 : *
18 : * (3) The following bibliography is recommended for citation and must be
19 : * preserved in all covered files:
20 : * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21 : * parallel geometric multigrid solver on hierarchically distributed grids.
22 : * Computing and visualization in science 16, 4 (2013), 151-164"
23 : * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24 : * flexible software system for simulating pde based models on high performance
25 : * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26 : *
27 : * This program is distributed in the hope that it will be useful,
28 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 : * GNU Lesser General Public License for more details.
31 : */
32 :
33 : #include <sstream>
34 : #include <fstream>
35 : #include <boost/archive/text_oarchive.hpp>
36 : #include <boost/archive/text_iarchive.hpp>
37 : #include "common/common.h"
38 : #include "common/util/file_util.h"
39 : #include "file_io_ugx.h"
40 : #include "common/boost_serialization_routines.h"
41 : #include "common/parser/rapidxml/rapidxml_print.hpp"
42 : #include "common/util/archivar.h"
43 : #include "common/util/factory.h"
44 : #include "lib_grid/algorithms/attachment_util.h"
45 : #include "lib_grid/refinement/projectors/projectors.h"
46 :
47 :
48 : using namespace std;
49 : using namespace rapidxml;
50 :
51 : namespace ug
52 : {
53 :
54 : ////////////////////////////////////////////////////////////////////////
55 0 : bool SaveGridToUGX(Grid& grid, ISubsetHandler& sh,
56 : const char* filename)
57 : {
58 0 : if(grid.has_vertex_attachment(aPosition))
59 0 : return SaveGridToUGX(grid, sh, filename, aPosition);
60 0 : else if(grid.has_vertex_attachment(aPosition2))
61 0 : return SaveGridToUGX(grid, sh, filename, aPosition2);
62 0 : else if(grid.has_vertex_attachment(aPosition1))
63 0 : return SaveGridToUGX(grid, sh, filename, aPosition1);
64 :
65 : UG_LOG("ERROR in SaveGridToUGX: no standard attachment found.\n");
66 0 : return false;
67 : }
68 :
69 0 : bool LoadGridFromUGX(Grid& grid, ISubsetHandler& sh,
70 : const char* filename)
71 : {
72 0 : if(grid.has_vertex_attachment(aPosition))
73 0 : return LoadGridFromUGX(grid, sh, filename, aPosition);
74 0 : else if(grid.has_vertex_attachment(aPosition2))
75 0 : return LoadGridFromUGX(grid, sh, filename, aPosition2);
76 0 : else if(grid.has_vertex_attachment(aPosition1))
77 0 : return LoadGridFromUGX(grid, sh, filename, aPosition1);
78 :
79 : // no standard position attachments are available.
80 : // Attach aPosition and use it.
81 : grid.attach_to_vertices(aPosition);
82 0 : return LoadGridFromUGX(grid, sh, filename, aPosition);
83 : }
84 :
85 : ////////////////////////////////////////////////////////////////////////
86 : ////////////////////////////////////////////////////////////////////////
87 : // GridWriterUGX
88 0 : GridWriterUGX::GridWriterUGX()
89 : {
90 0 : xml_node<>* decl = m_doc.allocate_node(node_declaration);
91 0 : decl->append_attribute(m_doc.allocate_attribute("version", "1.0"));
92 0 : decl->append_attribute(m_doc.allocate_attribute("encoding", "utf-8"));
93 0 : m_doc.append_node(decl);
94 0 : }
95 :
96 0 : GridWriterUGX::~GridWriterUGX()
97 : {
98 : // detach aInt from the vertices of the grid
99 0 : for(size_t i = 0; i < m_vEntries.size(); ++i)
100 0 : m_vEntries[i].grid->detach_from_vertices(m_aInt);
101 0 : }
102 :
103 0 : bool GridWriterUGX::
104 : write_to_stream(std::ostream& out)
105 : {
106 0 : out << m_doc;
107 0 : return true;
108 : }
109 :
110 0 : bool GridWriterUGX::
111 : write_to_file(const char* filename)
112 : {
113 0 : ofstream out(filename);
114 0 : if(out){
115 0 : return write_to_stream(out);
116 : }
117 : return false;
118 0 : }
119 :
120 0 : void GridWriterUGX::
121 : add_subset_attributes(rapidxml::xml_node<>* targetNode,
122 : ISubsetHandler& sh, size_t subsetIndex)
123 : {
124 0 : const SubsetInfo& si = sh.subset_info(subsetIndex);
125 : // write name
126 0 : targetNode->append_attribute(m_doc.allocate_attribute("name", si.name.c_str()));
127 :
128 : // write color
129 : {
130 0 : stringstream ss;
131 0 : for(size_t i = 0; i < 4; ++i){
132 0 : ss << si.color[i] << " ";
133 : }
134 :
135 :
136 : // allocate a string and erase last character(' ')
137 0 : char* colorData = m_doc.allocate_string(ss.str().c_str(), ss.str().size() );
138 0 : colorData[ss.str().size() - 1] = 0;
139 0 : targetNode->append_attribute(m_doc.allocate_attribute("color", colorData));
140 0 : }
141 : // write state
142 : {
143 0 : stringstream ss;
144 0 : ss << (size_t)si.subsetState;
145 0 : char* stateData = m_doc.allocate_string(ss.str().c_str(), ss.str().size() + 1);
146 0 : stateData[ss.str().size()] = 0;
147 0 : targetNode->append_attribute(m_doc.allocate_attribute("state", stateData));
148 0 : }
149 0 : }
150 :
151 0 : void GridWriterUGX::
152 : add_subset_handler(ISubsetHandler& sh, const char* name,
153 : size_t refGridIndex)
154 : {
155 : // get the node of the referenced grid
156 0 : if(refGridIndex >= m_vEntries.size()){
157 : UG_LOG("GridWriterUGX::add_subset_handler: bad refGridIndex. Aborting.\n");
158 0 : return;
159 : }
160 :
161 : // add the subset handler to the grid entry
162 0 : m_vEntries[refGridIndex].subsetHandlers.push_back(&sh);
163 :
164 0 : xml_node<>* parentNode = m_vEntries[refGridIndex].node;
165 :
166 : // create the subset-handler node
167 0 : xml_node<>* ndSH = m_doc.allocate_node(node_element, "subset_handler");
168 0 : ndSH->append_attribute(m_doc.allocate_attribute("name", name));
169 :
170 : // add the subset-handler-node to the grid-node.
171 : parentNode->append_node(ndSH);
172 :
173 : // add the subsets
174 0 : for(int i = 0; i < sh.num_subsets(); ++i){
175 0 : xml_node<>* ndSubset = m_doc.allocate_node(node_element, "subset");
176 0 : add_subset_attributes(ndSubset, sh, i);
177 : ndSH->append_node(ndSubset);
178 :
179 : // add elements
180 0 : if(sh.contains_vertices(i))
181 0 : ndSubset->append_node(
182 : create_subset_element_node<Vertex>("vertices", sh, i));
183 0 : if(sh.contains_edges(i))
184 0 : ndSubset->append_node(
185 : create_subset_element_node<Edge>("edges", sh, i));
186 0 : if(sh.contains_faces(i))
187 0 : ndSubset->append_node(
188 : create_subset_element_node<Face>("faces", sh, i));
189 0 : if(sh.contains_volumes(i))
190 0 : ndSubset->append_node(
191 : create_subset_element_node<Volume>("volumes", sh, i));
192 : }
193 : }
194 :
195 : template <class TGeomObj>
196 0 : rapidxml::xml_node<>* GridWriterUGX::
197 : create_subset_element_node(const char* name, const ISubsetHandler& sh,
198 : size_t si)
199 : {
200 :
201 : // the stringstream to which we'll write the data
202 0 : stringstream ss;
203 :
204 0 : if(sh.grid()){
205 : // access the grid
206 0 : Grid& grid = *sh.grid();
207 :
208 : // access the attachment
209 0 : Grid::AttachmentAccessor<TGeomObj, AInt> aaInd(grid, m_aInt);
210 0 : if(aaInd.valid()){
211 0 : GridObjectCollection goc = sh.get_grid_objects_in_subset(si);
212 0 : for(size_t lvl = 0; lvl < goc.num_levels(); ++lvl){
213 : for(typename geometry_traits<TGeomObj>::iterator iter =
214 0 : goc.begin<TGeomObj>(lvl); iter != goc.end<TGeomObj>(lvl); ++iter)
215 : {
216 0 : ss << aaInd[*iter] << " ";
217 : }
218 : }
219 : }
220 : }
221 :
222 0 : if(ss.str().size() > 0){
223 : // allocate a string and erase last character(' ')
224 0 : char* nodeData = m_doc.allocate_string(ss.str().c_str(), ss.str().size());
225 0 : nodeData[ss.str().size()-1] = 0;
226 : // create and return the node
227 0 : return m_doc.allocate_node(node_element, name, nodeData);
228 : }
229 : else{
230 : // return an emtpy node
231 0 : return m_doc.allocate_node(node_element, name);
232 : }
233 0 : }
234 :
235 : template <class TGeomObj>
236 0 : rapidxml::xml_node<>* GridWriterUGX::
237 : create_selector_element_node(const char* name, const ISelector& sel)
238 : {
239 : // the stringstream to which we'll write the data
240 0 : stringstream ss;
241 :
242 0 : if(sel.grid()){
243 : // access the grid
244 : Grid& grid = *sel.grid();
245 :
246 : // access the attachment
247 0 : Grid::AttachmentAccessor<TGeomObj, AInt> aaInd(grid, m_aInt);
248 0 : if(aaInd.valid()){
249 0 : GridObjectCollection goc = sel.get_grid_objects();
250 0 : for(size_t lvl = 0; lvl < goc.num_levels(); ++lvl){
251 : for(typename geometry_traits<TGeomObj>::iterator iter =
252 0 : goc.begin<TGeomObj>(lvl); iter != goc.end<TGeomObj>(lvl); ++iter)
253 : {
254 0 : ss << aaInd[*iter] << " " << (int)sel.get_selection_status(*iter) << " ";
255 : }
256 : }
257 : }
258 : }
259 :
260 0 : if(ss.str().size() > 0){
261 : // allocate a string and erase last character(' ')
262 0 : char* nodeData = m_doc.allocate_string(ss.str().c_str(), ss.str().size());
263 0 : nodeData[ss.str().size()-1] = 0;
264 : // create and return the node
265 0 : return m_doc.allocate_node(node_element, name, nodeData);
266 : }
267 : else{
268 : // return an emtpy node
269 0 : return m_doc.allocate_node(node_element, name);
270 : }
271 0 : }
272 :
273 0 : void GridWriterUGX::
274 : add_selector(ISelector& sel, const char* name, size_t refGridIndex)
275 : {
276 : // get the node of the referenced grid
277 0 : if(refGridIndex >= m_vEntries.size()){
278 : UG_LOG("GridWriterUGX::add_selector: bad refGridIndex. Aborting.\n");
279 0 : return;
280 : }
281 :
282 0 : xml_node<>* parentNode = m_vEntries[refGridIndex].node;
283 :
284 : // create the selector node
285 0 : xml_node<>* ndSel = m_doc.allocate_node(node_element, "selector");
286 0 : ndSel->append_attribute(m_doc.allocate_attribute("name", name));
287 :
288 : // add the selector node to the grid-node.
289 : parentNode->append_node(ndSel);
290 :
291 : // add elements
292 0 : if(sel.contains_vertices())
293 0 : ndSel->append_node(create_selector_element_node<Vertex>("vertices", sel));
294 0 : if(sel.contains_edges())
295 0 : ndSel->append_node(create_selector_element_node<Edge>("edges", sel));
296 0 : if(sel.contains_faces())
297 0 : ndSel->append_node(create_selector_element_node<Face>("faces", sel));
298 0 : if(sel.contains_volumes())
299 0 : ndSel->append_node(create_selector_element_node<Volume>("volumes", sel));
300 : }
301 :
302 0 : xml_node<>* GridWriterUGX::
303 : create_projector_node(RefinementProjector& proj, const char* nodeName)
304 : {
305 0 : static Factory<RefinementProjector, ProjectorTypes> projFac;
306 0 : static Archivar<boost::archive::text_oarchive, RefinementProjector, ProjectorTypes> archivar;
307 :
308 0 : const string& projName = projFac.class_name(proj);
309 :
310 0 : stringstream ss;
311 : boost::archive::text_oarchive ar(ss, boost::archive::no_header);
312 : archivar.archive(ar, proj);
313 :
314 0 : xml_node<>* ndProj = m_doc.allocate_node(node_element, nodeName,
315 0 : m_doc.allocate_string(ss.str().c_str()));
316 :
317 0 : ndProj->append_attribute(m_doc.allocate_attribute("type", projName.c_str()));
318 0 : return ndProj;
319 0 : }
320 :
321 0 : void GridWriterUGX::
322 : add_projection_handler(ProjectionHandler& ph, const char* name, size_t refGridIndex)
323 : {
324 : // get the node of the referenced grid
325 0 : if(refGridIndex >= m_vEntries.size()){
326 : UG_LOG("GridWriterUGX::add_selector: bad refGridIndex. Aborting.\n");
327 0 : return;
328 : }
329 :
330 0 : xml_node<>* parentNode = m_vEntries[refGridIndex].node;
331 :
332 : // create the selector node
333 0 : xml_node<>* ndHandler = m_doc.allocate_node(node_element, "projection_handler");
334 0 : ndHandler->append_attribute(m_doc.allocate_attribute("name", name));
335 :
336 : // find subset handler index in subset handler array
337 : size_t i = 0;
338 : const std::vector<const ISubsetHandler*>& vSH = m_vEntries[refGridIndex].subsetHandlers;
339 : size_t nSH = vSH.size();
340 0 : for (; i < nSH; ++i)
341 0 : if (vSH[i] == ph.subset_handler())
342 : break;
343 :
344 0 : UG_COND_THROW(i == nSH, "ERROR in 'GridWriterUGX::add_projection_handler': "
345 : "No matching SubsetHandler could be found.\n"
346 : "Please make sure to add the associated SubsetHandler before adding a ProjectionHandler");
347 :
348 : // append subset handler index attribute to node
349 0 : ndHandler->append_attribute(m_doc.allocate_attribute("subset_handler",
350 0 : m_doc.allocate_string(mkstr(i).c_str())));
351 :
352 : // add the selector node to the grid-node.
353 : parentNode->append_node(ndHandler);
354 :
355 : // fill the content of the projector-node
356 0 : if(ph.default_projector().valid()){
357 0 : ndHandler->append_node (create_projector_node(
358 0 : *ph.default_projector(), "default"));
359 : }
360 :
361 0 : for(int i = -1; i < (int)ph.num_projectors(); ++i){
362 0 : if(!ph.projector(i).valid())
363 0 : continue;
364 :
365 0 : RefinementProjector& proj= *ph.projector(i);
366 :
367 0 : xml_node<>* ndProj = create_projector_node(proj, "projector");
368 0 : ndProj->append_attribute(m_doc.allocate_attribute("subset",
369 0 : m_doc.allocate_string(mkstr(i).c_str())));
370 : ndHandler->append_node(ndProj);
371 : }
372 : }
373 :
374 :
375 0 : void GridWriterUGX::
376 : init_grid_attachments(Grid& grid)
377 : {
378 : // assign indices to the vertices, edges, faces and volumes
379 0 : grid.attach_to_vertices(m_aInt);
380 : grid.attach_to_edges(m_aInt);
381 : grid.attach_to_faces(m_aInt);
382 : grid.attach_to_volumes(m_aInt);
383 :
384 : // access and initialise indices
385 0 : Grid::VertexAttachmentAccessor<AInt> aaIndVRT(grid, m_aInt);
386 : Grid::EdgeAttachmentAccessor<AInt> aaIndEDGE(grid, m_aInt);
387 : Grid::FaceAttachmentAccessor<AInt> aaIndFACE(grid, m_aInt);
388 : Grid::VolumeAttachmentAccessor<AInt> aaIndVOL(grid, m_aInt);
389 :
390 : int baseInd = 0;
391 : AssignIndices(grid.begin<RegularVertex>(), grid.end<RegularVertex>(), aaIndVRT, baseInd);
392 0 : baseInd += grid.num<RegularVertex>();
393 : AssignIndices(grid.begin<ConstrainedVertex>(), grid.end<ConstrainedVertex>(),
394 : aaIndVRT, baseInd);
395 :
396 : baseInd = 0;
397 : AssignIndices(grid.begin<RegularEdge>(), grid.end<RegularEdge>(), aaIndEDGE, baseInd);
398 0 : baseInd += grid.num<RegularEdge>();
399 : AssignIndices(grid.begin<ConstrainingEdge>(), grid.end<ConstrainingEdge>(),
400 : aaIndEDGE, baseInd);
401 0 : baseInd += grid.num<ConstrainingEdge>();
402 : AssignIndices(grid.begin<ConstrainedEdge>(), grid.end<ConstrainedEdge>(),
403 : aaIndEDGE, baseInd);
404 :
405 : baseInd = 0;
406 : AssignIndices(grid.begin<Triangle>(), grid.end<Triangle>(), aaIndFACE, baseInd);
407 0 : baseInd += grid.num<Triangle>();
408 : AssignIndices(grid.begin<ConstrainingTriangle>(), grid.end<ConstrainingTriangle>(), aaIndFACE, baseInd);
409 0 : baseInd += grid.num<ConstrainingTriangle>();
410 : AssignIndices(grid.begin<ConstrainedTriangle>(), grid.end<ConstrainedTriangle>(), aaIndFACE, baseInd);
411 0 : baseInd += grid.num<ConstrainedTriangle>();
412 :
413 : AssignIndices(grid.begin<Quadrilateral>(), grid.end<Quadrilateral>(), aaIndFACE, baseInd);
414 0 : baseInd += grid.num<Quadrilateral>();
415 : AssignIndices(grid.begin<ConstrainingQuadrilateral>(), grid.end<ConstrainingQuadrilateral>(), aaIndFACE, baseInd);
416 0 : baseInd += grid.num<ConstrainingQuadrilateral>();
417 : AssignIndices(grid.begin<ConstrainedQuadrilateral>(), grid.end<ConstrainedQuadrilateral>(), aaIndFACE, baseInd);
418 : //baseInd += grid.num<ConstrainedQuadrilateral>(); // never used
419 :
420 : AssignIndices(grid.begin<Volume>(), grid.end<Volume>(), aaIndVOL, 0);
421 0 : }
422 :
423 0 : void GridWriterUGX::
424 : add_elements_to_node(rapidxml::xml_node<>* node,
425 : Grid& grid)
426 : {
427 : // access and initialise indices
428 0 : Grid::VertexAttachmentAccessor<AInt> aaIndVRT(grid, m_aInt);
429 : Grid::EdgeAttachmentAccessor<AInt> aaIndEDGE(grid, m_aInt);
430 : Grid::FaceAttachmentAccessor<AInt> aaIndFACE(grid, m_aInt);
431 : Grid::VolumeAttachmentAccessor<AInt> aaIndVOL(grid, m_aInt);
432 :
433 : // write edges
434 0 : if(grid.num<RegularEdge>() > 0)
435 0 : node->append_node(create_edge_node(grid.begin<RegularEdge>(),
436 0 : grid.end<RegularEdge>(), aaIndVRT));
437 :
438 : // write constraining edges
439 0 : if(grid.num<ConstrainingEdge>() > 0)
440 0 : node->append_node(create_constraining_edge_node(
441 0 : grid.begin<ConstrainingEdge>(),
442 0 : grid.end<ConstrainingEdge>(), aaIndVRT));
443 :
444 : // write constrained edges
445 0 : if(grid.num<ConstrainedEdge>() > 0)
446 0 : node->append_node(create_constrained_edge_node(
447 0 : grid.begin<ConstrainedEdge>(),
448 0 : grid.end<ConstrainedEdge>(),
449 : aaIndVRT, aaIndEDGE, aaIndFACE));
450 : // write triangles
451 0 : if(grid.num<Triangle>() > 0)
452 0 : node->append_node(create_triangle_node(grid.begin<Triangle>(),
453 0 : grid.end<Triangle>(), aaIndVRT));
454 :
455 : // write constraining triangles
456 0 : if(grid.num<ConstrainingTriangle>() > 0)
457 0 : node->append_node(create_constraining_triangle_node(
458 0 : grid.begin<ConstrainingTriangle>(),
459 0 : grid.end<ConstrainingTriangle>(),
460 : aaIndVRT));
461 :
462 : // write constrained triangles
463 0 : if(grid.num<ConstrainedTriangle>() > 0)
464 0 : node->append_node(create_constrained_triangle_node(
465 0 : grid.begin<ConstrainedTriangle>(),
466 0 : grid.end<ConstrainedTriangle>(),
467 : aaIndVRT, aaIndFACE));
468 : // write quadrilaterals
469 0 : if(grid.num<Quadrilateral>() > 0)
470 0 : node->append_node(create_quadrilateral_node(grid.begin<Quadrilateral>(),
471 0 : grid.end<Quadrilateral>(), aaIndVRT));
472 :
473 : // write constraining quadrilaterals
474 0 : if(grid.num<ConstrainingQuadrilateral>() > 0)
475 0 : node->append_node(create_constraining_quadrilateral_node(
476 0 : grid.begin<ConstrainingQuadrilateral>(),
477 0 : grid.end<ConstrainingQuadrilateral>(),
478 : aaIndVRT));
479 :
480 : // write constrained quadrilaterals
481 0 : if(grid.num<ConstrainedQuadrilateral>() > 0)
482 0 : node->append_node(create_constrained_quadrilateral_node(
483 0 : grid.begin<ConstrainedQuadrilateral>(),
484 0 : grid.end<ConstrainedQuadrilateral>(),
485 : aaIndVRT, aaIndFACE));
486 :
487 : // write tetrahedrons
488 0 : if(grid.num<Tetrahedron>() > 0)
489 0 : node->append_node(create_tetrahedron_node(grid.begin<Tetrahedron>(),
490 0 : grid.end<Tetrahedron>(), aaIndVRT));
491 :
492 : // write hexahedrons
493 0 : if(grid.num<Hexahedron>() > 0)
494 0 : node->append_node(create_hexahedron_node(grid.begin<Hexahedron>(),
495 0 : grid.end<Hexahedron>(), aaIndVRT));
496 :
497 : // write prisms
498 0 : if(grid.num<Prism>() > 0)
499 0 : node->append_node(create_prism_node(grid.begin<Prism>(),
500 0 : grid.end<Prism>(), aaIndVRT));
501 :
502 : // write pyramids
503 0 : if(grid.num<Pyramid>() > 0)
504 0 : node->append_node(create_pyramid_node(grid.begin<Pyramid>(),
505 0 : grid.end<Pyramid>(), aaIndVRT));
506 :
507 : // write octahedrons
508 0 : if(grid.num<Octahedron>() > 0)
509 0 : node->append_node(create_octahedron_node(grid.begin<Octahedron>(),
510 0 : grid.end<Octahedron>(), aaIndVRT));
511 0 : }
512 :
513 0 : rapidxml::xml_node<>* GridWriterUGX::
514 : create_edge_node(RegularEdgeIterator edgesBegin,
515 : RegularEdgeIterator edgesEnd,
516 : AAVrtIndex aaIndVRT)
517 : {
518 : // write the elements to a temporary stream
519 0 : stringstream ss;
520 0 : for(RegularEdgeIterator iter = edgesBegin; iter != edgesEnd; ++iter)
521 : {
522 0 : ss << aaIndVRT[(*iter)->vertex(0)] << " " << aaIndVRT[(*iter)->vertex(1)] << " ";
523 : }
524 :
525 0 : if(ss.str().size() > 0){
526 : // allocate a string and erase last character(' ')
527 0 : char* nodeData = m_doc.allocate_string(ss.str().c_str(), ss.str().size());
528 0 : nodeData[ss.str().size()-1] = 0;
529 : // create and return the node
530 0 : return m_doc.allocate_node(node_element, "edges", nodeData);
531 : }
532 : else{
533 : // return an emtpy node
534 0 : return m_doc.allocate_node(node_element, "edges");
535 : }
536 0 : }
537 :
538 0 : rapidxml::xml_node<>* GridWriterUGX::
539 : create_constraining_edge_node(ConstrainingEdgeIterator edgesBegin,
540 : ConstrainingEdgeIterator edgesEnd,
541 : AAVrtIndex aaIndVRT)
542 : {
543 : // write the elements to a temporary stream
544 0 : stringstream ss;
545 0 : for(ConstrainingEdgeIterator iter = edgesBegin; iter != edgesEnd; ++iter)
546 : {
547 0 : ss << aaIndVRT[(*iter)->vertex(0)] << " " << aaIndVRT[(*iter)->vertex(1)] << " ";
548 : }
549 :
550 0 : if(ss.str().size() > 0){
551 : // allocate a string and erase last character(' ')
552 0 : char* nodeData = m_doc.allocate_string(ss.str().c_str(), ss.str().size());
553 0 : nodeData[ss.str().size()-1] = 0;
554 : // create and return the node
555 0 : return m_doc.allocate_node(node_element, "constraining_edges", nodeData);
556 : }
557 : else{
558 : // return an emtpy node
559 0 : return m_doc.allocate_node(node_element, "constraining_edges");
560 : }
561 0 : }
562 :
563 0 : rapidxml::xml_node<>* GridWriterUGX::
564 : create_constrained_edge_node(ConstrainedEdgeIterator edgesBegin,
565 : ConstrainedEdgeIterator edgesEnd,
566 : AAVrtIndex aaIndVRT,
567 : AAEdgeIndex aaIndEDGE,
568 : AAFaceIndex aaIndFACE)
569 : {
570 : // write the elements to a temporary stream
571 0 : stringstream ss;
572 0 : for(ConstrainedEdgeIterator iter = edgesBegin; iter != edgesEnd; ++iter)
573 : {
574 : // write endpoint indices
575 0 : ss << aaIndVRT[(*iter)->vertex(0)] << " " << aaIndVRT[(*iter)->vertex(1)] << " ";
576 :
577 : // write index of associated constraining element
578 : // codes: -1: no constraining element
579 : // 0: vertex. index follows
580 : // 1: edge. index follows
581 : // 2: face. index follows
582 : // 3: volume. index follows
583 0 : Edge* ce = dynamic_cast<Edge*>((*iter)->get_constraining_object());
584 0 : Face* cf = dynamic_cast<Face*>((*iter)->get_constraining_object());
585 0 : if(ce)
586 0 : ss << "1 " << aaIndEDGE[ce] << " ";
587 0 : else if(cf)
588 0 : ss << "2 " << aaIndFACE[cf] << " ";
589 : else
590 0 : ss << "-1 ";
591 : }
592 :
593 0 : if(ss.str().size() > 0){
594 : // allocate a string and erase last character(' ')
595 0 : char* nodeData = m_doc.allocate_string(ss.str().c_str(), ss.str().size());
596 0 : nodeData[ss.str().size()-1] = 0;
597 : // create and return the node
598 0 : return m_doc.allocate_node(node_element, "constrained_edges", nodeData);
599 : }
600 : else{
601 : // return an emtpy node
602 0 : return m_doc.allocate_node(node_element, "constrained_edges");
603 : }
604 0 : }
605 :
606 0 : rapidxml::xml_node<>* GridWriterUGX::
607 : create_triangle_node(TriangleIterator trisBegin,
608 : TriangleIterator trisEnd,
609 : AAVrtIndex aaIndVRT)
610 : {
611 : // write the elements to a temporary stream
612 0 : stringstream ss;
613 0 : for(TriangleIterator iter = trisBegin; iter != trisEnd; ++iter)
614 : {
615 0 : ss << aaIndVRT[(*iter)->vertex(0)] << " " << aaIndVRT[(*iter)->vertex(1)]
616 0 : << " " << aaIndVRT[(*iter)->vertex(2)] << " " ;
617 : }
618 :
619 0 : if(ss.str().size() > 0){
620 : // allocate a string and erase last character(' ')
621 0 : char* nodeData = m_doc.allocate_string(ss.str().c_str(), ss.str().size());
622 0 : nodeData[ss.str().size()-1] = 0;
623 : // create and return the node
624 0 : return m_doc.allocate_node(node_element, "triangles", nodeData);
625 : }
626 : else{
627 : // return an emtpy node
628 0 : return m_doc.allocate_node(node_element, "triangles");
629 : }
630 0 : }
631 :
632 0 : rapidxml::xml_node<>* GridWriterUGX::
633 : create_constraining_triangle_node(ConstrainingTriangleIterator trisBegin,
634 : ConstrainingTriangleIterator trisEnd,
635 : AAVrtIndex aaIndVRT)
636 : {
637 : // write the elements to a temporary stream
638 0 : stringstream ss;
639 0 : for(ConstrainingTriangleIterator iter = trisBegin; iter != trisEnd; ++iter)
640 : {
641 0 : ss << aaIndVRT[(*iter)->vertex(0)] << " " << aaIndVRT[(*iter)->vertex(1)]
642 0 : << " " << aaIndVRT[(*iter)->vertex(2)] << " " ;
643 : }
644 :
645 0 : if(ss.str().size() > 0){
646 : // allocate a string and erase last character(' ')
647 0 : char* nodeData = m_doc.allocate_string(ss.str().c_str(), ss.str().size());
648 0 : nodeData[ss.str().size()-1] = 0;
649 : // create and return the node
650 0 : return m_doc.allocate_node(node_element, "constraining_triangles", nodeData);
651 : }
652 : else{
653 : // return an emtpy node
654 0 : return m_doc.allocate_node(node_element, "constraining_triangles");
655 : }
656 0 : }
657 :
658 0 : rapidxml::xml_node<>* GridWriterUGX::
659 : create_constrained_triangle_node(ConstrainedTriangleIterator trisBegin,
660 : ConstrainedTriangleIterator trisEnd,
661 : AAVrtIndex aaIndVRT,
662 : AAFaceIndex aaIndFACE)
663 : {
664 : // write the elements to a temporary stream
665 0 : stringstream ss;
666 0 : for(ConstrainedTriangleIterator iter = trisBegin; iter != trisEnd; ++iter)
667 : {
668 : // write endpoint indices
669 0 : ss << aaIndVRT[(*iter)->vertex(0)] << " " << aaIndVRT[(*iter)->vertex(1)]
670 0 : << " " << aaIndVRT[(*iter)->vertex(2)] << " " ;
671 : // write index of associated constraining element
672 : // codes: -1: no constraining element
673 : // 0: vertex. index follows
674 : // 1: edge. index follows
675 : // 2: face. index follows
676 : // 3: volume. index follows
677 0 : Face* cf = dynamic_cast<Face*>((*iter)->get_constraining_object());
678 0 : if(cf)
679 0 : ss << "2 " << aaIndFACE[cf] << " ";
680 : else
681 0 : ss << "-1 ";
682 : }
683 :
684 0 : if(ss.str().size() > 0){
685 : // allocate a string and erase last character(' ')
686 0 : char* nodeData = m_doc.allocate_string(ss.str().c_str(), ss.str().size());
687 0 : nodeData[ss.str().size()-1] = 0;
688 : // create and return the node
689 0 : return m_doc.allocate_node(node_element, "constrained_triangles", nodeData);
690 : }
691 : else{
692 : // return an emtpy node
693 0 : return m_doc.allocate_node(node_element, "constrained_triangles");
694 : }
695 0 : }
696 :
697 :
698 0 : rapidxml::xml_node<>* GridWriterUGX::
699 : create_quadrilateral_node(QuadrilateralIterator quadsBegin,
700 : QuadrilateralIterator quadsEnd,
701 : AAVrtIndex aaIndVRT)
702 : {
703 : // write the elements to a temporary stream
704 0 : stringstream ss;
705 0 : for(QuadrilateralIterator iter = quadsBegin; iter != quadsEnd; ++iter)
706 : {
707 0 : ss << aaIndVRT[(*iter)->vertex(0)] << " " << aaIndVRT[(*iter)->vertex(1)] << " "
708 0 : << aaIndVRT[(*iter)->vertex(2)] << " " << aaIndVRT[(*iter)->vertex(3)] << " " ;
709 : }
710 :
711 0 : if(ss.str().size() > 0){
712 : // allocate a string and erase last character(' ')
713 0 : char* nodeData = m_doc.allocate_string(ss.str().c_str(), ss.str().size());
714 0 : nodeData[ss.str().size()-1] = 0;
715 : // create and return the node
716 0 : return m_doc.allocate_node(node_element, "quadrilaterals", nodeData);
717 : }
718 : else{
719 : // return an emtpy node
720 0 : return m_doc.allocate_node(node_element, "quadrilaterals");
721 : }
722 0 : }
723 :
724 0 : rapidxml::xml_node<>* GridWriterUGX::
725 : create_constraining_quadrilateral_node(ConstrainingQuadrilateralIterator quadsBegin,
726 : ConstrainingQuadrilateralIterator quadsEnd,
727 : AAVrtIndex aaIndVRT)
728 : {
729 : // write the elements to a temporary stream
730 0 : stringstream ss;
731 0 : for(ConstrainingQuadrilateralIterator iter = quadsBegin; iter != quadsEnd; ++iter)
732 : {
733 0 : ss << aaIndVRT[(*iter)->vertex(0)] << " " << aaIndVRT[(*iter)->vertex(1)] << " "
734 0 : << aaIndVRT[(*iter)->vertex(2)] << " " << aaIndVRT[(*iter)->vertex(3)] << " " ;
735 : }
736 :
737 0 : if(ss.str().size() > 0){
738 : // allocate a string and erase last character(' ')
739 0 : char* nodeData = m_doc.allocate_string(ss.str().c_str(), ss.str().size());
740 0 : nodeData[ss.str().size()-1] = 0;
741 : // create and return the node
742 0 : return m_doc.allocate_node(node_element, "constraining_quadrilaterals", nodeData);
743 : }
744 : else{
745 : // return an emtpy node
746 0 : return m_doc.allocate_node(node_element, "constraining_quadrilaterals");
747 : }
748 0 : }
749 :
750 0 : rapidxml::xml_node<>* GridWriterUGX::
751 : create_constrained_quadrilateral_node(ConstrainedQuadrilateralIterator quadsBegin,
752 : ConstrainedQuadrilateralIterator quadsEnd,
753 : AAVrtIndex aaIndVRT,
754 : AAFaceIndex aaIndFACE)
755 : {
756 : // write the elements to a temporary stream
757 0 : stringstream ss;
758 0 : for(ConstrainedQuadrilateralIterator iter = quadsBegin; iter != quadsEnd; ++iter)
759 : {
760 0 : ss << aaIndVRT[(*iter)->vertex(0)] << " " << aaIndVRT[(*iter)->vertex(1)] << " "
761 0 : << aaIndVRT[(*iter)->vertex(2)] << " " << aaIndVRT[(*iter)->vertex(3)] << " " ;
762 : // write index of associated constraining element
763 : // codes: -1: no constraining element
764 : // 0: vertex. index follows
765 : // 1: edge. index follows
766 : // 2: face. index follows
767 : // 3: volume. index follows
768 0 : Face* cf = dynamic_cast<Face*>((*iter)->get_constraining_object());
769 0 : if(cf)
770 0 : ss << "2 " << aaIndFACE[cf] << " ";
771 : else
772 0 : ss << "-1 ";
773 : }
774 :
775 0 : if(ss.str().size() > 0){
776 : // allocate a string and erase last character(' ')
777 0 : char* nodeData = m_doc.allocate_string(ss.str().c_str(), ss.str().size());
778 0 : nodeData[ss.str().size()-1] = 0;
779 : // create and return the node
780 0 : return m_doc.allocate_node(node_element, "constrained_quadrilaterals", nodeData);
781 : }
782 : else{
783 : // return an emtpy node
784 0 : return m_doc.allocate_node(node_element, "constrained_quadrilaterals");
785 : }
786 0 : }
787 :
788 0 : rapidxml::xml_node<>* GridWriterUGX::
789 : create_tetrahedron_node(TetrahedronIterator tetsBegin,
790 : TetrahedronIterator tetsEnd,
791 : AAVrtIndex aaIndVRT)
792 : {
793 : // write the elements to a temporary stream
794 0 : stringstream ss;
795 0 : for(TetrahedronIterator iter = tetsBegin; iter != tetsEnd; ++iter)
796 : {
797 0 : ss << aaIndVRT[(*iter)->vertex(0)] << " " << aaIndVRT[(*iter)->vertex(1)] << " "
798 0 : << aaIndVRT[(*iter)->vertex(2)] << " " << aaIndVRT[(*iter)->vertex(3)] << " " ;
799 : }
800 :
801 0 : if(ss.str().size() > 0){
802 : // allocate a string and erase last character(' ')
803 0 : char* nodeData = m_doc.allocate_string(ss.str().c_str(), ss.str().size());
804 0 : nodeData[ss.str().size()-1] = 0;
805 : // create and return the node
806 0 : return m_doc.allocate_node(node_element, "tetrahedrons", nodeData);
807 : }
808 : else{
809 : // return an emtpy node
810 0 : return m_doc.allocate_node(node_element, "tetrahedrons");
811 : }
812 0 : }
813 :
814 0 : rapidxml::xml_node<>* GridWriterUGX::
815 : create_hexahedron_node(HexahedronIterator hexasBegin,
816 : HexahedronIterator hexasEnd,
817 : AAVrtIndex aaIndVRT)
818 : {
819 : // write the elements to a temporary stream
820 0 : stringstream ss;
821 0 : for(HexahedronIterator iter = hexasBegin; iter != hexasEnd; ++iter)
822 : {
823 0 : ss << aaIndVRT[(*iter)->vertex(0)] << " " << aaIndVRT[(*iter)->vertex(1)] << " "
824 0 : << aaIndVRT[(*iter)->vertex(2)] << " " << aaIndVRT[(*iter)->vertex(3)] << " "
825 0 : << aaIndVRT[(*iter)->vertex(4)] << " " << aaIndVRT[(*iter)->vertex(5)] << " "
826 0 : << aaIndVRT[(*iter)->vertex(6)] << " " << aaIndVRT[(*iter)->vertex(7)] << " ";
827 : }
828 :
829 0 : if(ss.str().size() > 0){
830 : // allocate a string and erase last character(' ')
831 0 : char* nodeData = m_doc.allocate_string(ss.str().c_str(), ss.str().size());
832 0 : nodeData[ss.str().size()-1] = 0;
833 : // create and return the node
834 0 : return m_doc.allocate_node(node_element, "hexahedrons", nodeData);
835 : }
836 : else{
837 : // return an emtpy node
838 0 : return m_doc.allocate_node(node_element, "hexahedrons");
839 : }
840 0 : }
841 :
842 0 : rapidxml::xml_node<>* GridWriterUGX::
843 : create_prism_node(PrismIterator prismsBegin,
844 : PrismIterator prismsEnd,
845 : AAVrtIndex aaIndVRT)
846 : {
847 : // write the elements to a temporary stream
848 0 : stringstream ss;
849 0 : for(PrismIterator iter = prismsBegin; iter != prismsEnd; ++iter)
850 : {
851 0 : ss << aaIndVRT[(*iter)->vertex(0)] << " " << aaIndVRT[(*iter)->vertex(1)] << " "
852 0 : << aaIndVRT[(*iter)->vertex(2)] << " " << aaIndVRT[(*iter)->vertex(3)] << " "
853 0 : << aaIndVRT[(*iter)->vertex(4)] << " " << aaIndVRT[(*iter)->vertex(5)] << " ";
854 : }
855 :
856 0 : if(ss.str().size() > 0){
857 : // allocate a string and erase last character(' ')
858 0 : char* nodeData = m_doc.allocate_string(ss.str().c_str(), ss.str().size());
859 0 : nodeData[ss.str().size()-1] = 0;
860 : // create and return the node
861 0 : return m_doc.allocate_node(node_element, "prisms", nodeData);
862 : }
863 : else{
864 : // return an emtpy node
865 0 : return m_doc.allocate_node(node_element, "prisms");
866 : }
867 0 : }
868 :
869 0 : rapidxml::xml_node<>* GridWriterUGX::
870 : create_pyramid_node(PyramidIterator pyrasBegin,
871 : PyramidIterator pyrasEnd,
872 : AAVrtIndex aaIndVRT)
873 : {
874 : // write the elements to a temporary stream
875 0 : stringstream ss;
876 0 : for(PyramidIterator iter = pyrasBegin; iter != pyrasEnd; ++iter)
877 : {
878 0 : ss << aaIndVRT[(*iter)->vertex(0)] << " " << aaIndVRT[(*iter)->vertex(1)] << " "
879 0 : << aaIndVRT[(*iter)->vertex(2)] << " " << aaIndVRT[(*iter)->vertex(3)] << " "
880 0 : << aaIndVRT[(*iter)->vertex(4)] << " ";
881 : }
882 :
883 0 : if(ss.str().size() > 0){
884 : // allocate a string and erase last character(' ')
885 0 : char* nodeData = m_doc.allocate_string(ss.str().c_str(), ss.str().size());
886 0 : nodeData[ss.str().size()-1] = 0;
887 : // create and return the node
888 0 : return m_doc.allocate_node(node_element, "pyramids", nodeData);
889 : }
890 : else{
891 : // return an emtpy node
892 0 : return m_doc.allocate_node(node_element, "pyramids");
893 : }
894 0 : }
895 :
896 0 : rapidxml::xml_node<>* GridWriterUGX::
897 : create_octahedron_node(OctahedronIterator octsBegin,
898 : OctahedronIterator octsEnd,
899 : AAVrtIndex aaIndVRT)
900 : {
901 : // write the elements to a temporary stream
902 0 : stringstream ss;
903 0 : for(OctahedronIterator iter = octsBegin; iter != octsEnd; ++iter)
904 : {
905 0 : ss << aaIndVRT[(*iter)->vertex(0)] << " " << aaIndVRT[(*iter)->vertex(1)] << " "
906 0 : << aaIndVRT[(*iter)->vertex(2)] << " " << aaIndVRT[(*iter)->vertex(3)] << " "
907 0 : << aaIndVRT[(*iter)->vertex(4)] << " " << aaIndVRT[(*iter)->vertex(5)] << " ";
908 : }
909 :
910 0 : if(ss.str().size() > 0){
911 : // allocate a string and erase last character(' ')
912 0 : char* nodeData = m_doc.allocate_string(ss.str().c_str(), ss.str().size());
913 0 : nodeData[ss.str().size()-1] = 0;
914 : // create and return the node
915 0 : return m_doc.allocate_node(node_element, "octahedrons", nodeData);
916 : }
917 : else{
918 : // return an emtpy node
919 0 : return m_doc.allocate_node(node_element, "octahedrons");
920 : }
921 0 : }
922 :
923 :
924 : ////////////////////////////////////////////////////////////////////////
925 : ////////////////////////////////////////////////////////////////////////
926 : // implementation of GridReaderUGX
927 0 : GridReaderUGX::GridReaderUGX()
928 : {
929 0 : }
930 :
931 0 : GridReaderUGX::~GridReaderUGX()
932 : {
933 0 : }
934 :
935 0 : const char* GridReaderUGX::
936 : get_grid_name(size_t index) const
937 : {
938 : assert(index < num_grids() && "Bad index!");
939 0 : xml_attribute<>* attrib = m_entries[index].node->first_attribute("name");
940 0 : if(attrib)
941 : return attrib->value();
942 : return "";
943 : }
944 :
945 0 : size_t GridReaderUGX::num_subset_handlers(size_t refGridIndex) const
946 : {
947 : // access the referred grid-entry
948 0 : if(refGridIndex >= m_entries.size()){
949 : UG_LOG("GridReaderUGX::num_subset_handlers: bad refGridIndex. Aborting.\n");
950 0 : return 0;
951 : }
952 :
953 0 : return m_entries[refGridIndex].subsetHandlerEntries.size();
954 : }
955 :
956 0 : const char* GridReaderUGX::
957 : get_subset_handler_name(size_t refGridIndex, size_t subsetHandlerIndex) const
958 : {
959 : assert(refGridIndex < num_grids() && "Bad refGridIndex!");
960 : const GridEntry& ge = m_entries[refGridIndex];
961 : assert(subsetHandlerIndex < ge.subsetHandlerEntries.size() && "Bad subsetHandlerIndex!");
962 :
963 0 : xml_attribute<>* attrib = ge.subsetHandlerEntries[subsetHandlerIndex].node->first_attribute("name");
964 0 : if(attrib)
965 : return attrib->value();
966 : return "";
967 : }
968 :
969 0 : bool GridReaderUGX::
970 : subset_handler(ISubsetHandler& shOut,
971 : size_t subsetHandlerIndex,
972 : size_t refGridIndex)
973 : {
974 : // access the referred grid-entry
975 0 : if(refGridIndex >= m_entries.size()){
976 : UG_LOG("GridReaderUGX::subset_handler: bad refGridIndex. Aborting.\n");
977 0 : return false;
978 : }
979 :
980 : GridEntry& gridEntry = m_entries[refGridIndex];
981 :
982 : // get the referenced subset-handler entry
983 0 : if(subsetHandlerIndex >= gridEntry.subsetHandlerEntries.size()){
984 : UG_LOG("GridReaderUGX::subset_handler: bad subsetHandlerIndex. Aborting.\n");
985 0 : return false;
986 : }
987 :
988 : SubsetHandlerEntry& shEntry = gridEntry.subsetHandlerEntries[subsetHandlerIndex];
989 0 : shEntry.sh = &shOut;
990 :
991 0 : xml_node<>* subsetNode = shEntry.node->first_node("subset");
992 : size_t subsetInd = 0;
993 0 : while(subsetNode)
994 : {
995 : // set subset info
996 : // retrieve an initial subset-info from shOut, so that initialised values are kept.
997 0 : SubsetInfo si = shOut.subset_info(subsetInd);
998 :
999 0 : xml_attribute<>* attrib = subsetNode->first_attribute("name");
1000 0 : if(attrib)
1001 : si.name = attrib->value();
1002 :
1003 0 : attrib = subsetNode->first_attribute("color");
1004 0 : if(attrib){
1005 0 : stringstream ss(attrib->value(), ios_base::in);
1006 0 : for(size_t i = 0; i < 4; ++i)
1007 : ss >> si.color[i];
1008 0 : }
1009 :
1010 0 : attrib = subsetNode->first_attribute("state");
1011 0 : if(attrib){
1012 0 : stringstream ss(attrib->value(), ios_base::in);
1013 : size_t state;
1014 : ss >> state;
1015 0 : si.subsetState = (uint)state;
1016 0 : }
1017 :
1018 0 : shOut.set_subset_info(subsetInd, si);
1019 :
1020 : // read elements of this subset
1021 0 : if(shOut.elements_are_supported(SHE_VERTEX))
1022 0 : read_subset_handler_elements<Vertex>(shOut, "vertices",
1023 : subsetNode, subsetInd,
1024 0 : gridEntry.vertices);
1025 0 : if(shOut.elements_are_supported(SHE_EDGE))
1026 0 : read_subset_handler_elements<Edge>(shOut, "edges",
1027 : subsetNode, subsetInd,
1028 0 : gridEntry.edges);
1029 0 : if(shOut.elements_are_supported(SHE_FACE))
1030 0 : read_subset_handler_elements<Face>(shOut, "faces",
1031 : subsetNode, subsetInd,
1032 0 : gridEntry.faces);
1033 0 : if(shOut.elements_are_supported(SHE_VOLUME))
1034 0 : read_subset_handler_elements<Volume>(shOut, "volumes",
1035 : subsetNode, subsetInd,
1036 0 : gridEntry.volumes);
1037 : // next subset
1038 0 : subsetNode = subsetNode->next_sibling("subset");
1039 0 : ++subsetInd;
1040 : }
1041 :
1042 : return true;
1043 : }
1044 :
1045 : template <class TGeomObj>
1046 0 : bool GridReaderUGX::
1047 : read_subset_handler_elements(ISubsetHandler& shOut,
1048 : const char* elemNodeName,
1049 : rapidxml::xml_node<>* subsetNode,
1050 : int subsetIndex,
1051 : std::vector<TGeomObj*>& vElems)
1052 : {
1053 0 : xml_node<>* elemNode = subsetNode->first_node(elemNodeName);
1054 :
1055 0 : while(elemNode)
1056 : {
1057 : // read the indices
1058 0 : stringstream ss(elemNode->value(), ios_base::in);
1059 :
1060 : size_t index;
1061 0 : while(!ss.eof()){
1062 : ss >> index;
1063 0 : if(ss.fail())
1064 0 : continue;
1065 :
1066 0 : if(index < vElems.size()){
1067 0 : shOut.assign_subset(vElems[index], subsetIndex);
1068 : }
1069 : else{
1070 0 : UG_LOG("Bad element index in subset-node " << elemNodeName <<
1071 : ": " << index << ". Ignoring element.\n");
1072 : return false;
1073 : }
1074 : }
1075 :
1076 : // get next element node
1077 0 : elemNode = elemNode->next_sibling(elemNodeName);
1078 : }
1079 :
1080 : return true;
1081 : }
1082 :
1083 :
1084 : /// returns the number of selectors for the given grid
1085 0 : size_t GridReaderUGX::
1086 : num_selectors(size_t refGridIndex) const
1087 : {
1088 0 : UG_COND_THROW(refGridIndex >= m_entries.size(),
1089 : "Bad refGridIndex: " << refGridIndex);
1090 :
1091 0 : return m_entries[refGridIndex].selectorEntries.size();
1092 : }
1093 :
1094 : /// returns the name of the given selector
1095 0 : const char* GridReaderUGX::
1096 : get_selector_name(size_t refGridIndex, size_t selectorIndex) const
1097 : {
1098 0 : UG_COND_THROW(refGridIndex >= m_entries.size(),
1099 : "Bad refGridIndex: " << refGridIndex);
1100 : const GridEntry& ge = m_entries[refGridIndex];
1101 : assert(selectorIndex < ge.selectorEntries.size() && "Bad selectorIndex!");
1102 :
1103 0 : xml_attribute<>* attrib = ge.selectorEntries[selectorIndex].node->first_attribute("name");
1104 0 : if(attrib)
1105 : return attrib->value();
1106 : return "";
1107 : }
1108 :
1109 : /// fills the given selector
1110 0 : bool GridReaderUGX::
1111 : selector(ISelector& selOut, size_t selectorIndex, size_t refGridIndex)
1112 : {
1113 : // access the referred grid-entry
1114 0 : if(refGridIndex >= m_entries.size()){
1115 : UG_LOG("GridReaderUGX::selector: bad refGridIndex. Aborting.\n");
1116 0 : return false;
1117 : }
1118 :
1119 : GridEntry& gridEntry = m_entries[refGridIndex];
1120 :
1121 : // get the referenced subset-handler entry
1122 0 : if(selectorIndex >= gridEntry.selectorEntries.size()){
1123 : UG_LOG("GridReaderUGX::selector: bad selectorIndex. Aborting.\n");
1124 0 : return false;
1125 : }
1126 :
1127 : SelectorEntry& selEntry = gridEntry.selectorEntries[selectorIndex];
1128 0 : selEntry.sel = &selOut;
1129 :
1130 0 : xml_node<>* selectorNode = selEntry.node;
1131 :
1132 : // read elements of this subset
1133 0 : if(selOut.elements_are_supported(SHE_VERTEX))
1134 0 : read_selector_elements<Vertex>(selOut, "vertices",
1135 : selectorNode,
1136 0 : gridEntry.vertices);
1137 0 : if(selOut.elements_are_supported(SHE_EDGE))
1138 0 : read_selector_elements<Edge>(selOut, "edges",
1139 : selectorNode,
1140 0 : gridEntry.edges);
1141 0 : if(selOut.elements_are_supported(SHE_FACE))
1142 0 : read_selector_elements<Face>(selOut, "faces",
1143 : selectorNode,
1144 0 : gridEntry.faces);
1145 0 : if(selOut.elements_are_supported(SHE_VOLUME))
1146 0 : read_selector_elements<Volume>(selOut, "volumes",
1147 : selectorNode,
1148 0 : gridEntry.volumes);
1149 :
1150 : return true;
1151 : }
1152 :
1153 : template <class TGeomObj>
1154 0 : bool GridReaderUGX::
1155 : read_selector_elements(ISelector& selOut, const char* elemNodeName,
1156 : rapidxml::xml_node<>* selNode,
1157 : std::vector<TGeomObj*>& vElems)
1158 : {
1159 0 : xml_node<>* elemNode = selNode->first_node(elemNodeName);
1160 :
1161 0 : while(elemNode)
1162 : {
1163 : // read the indices
1164 0 : stringstream ss(elemNode->value(), ios_base::in);
1165 :
1166 : size_t index;
1167 : int state;
1168 :
1169 0 : while(!ss.eof()){
1170 : ss >> index;
1171 0 : if(ss.fail())
1172 0 : continue;
1173 :
1174 0 : ss >> state;
1175 0 : if(ss.fail())
1176 0 : continue;
1177 :
1178 0 : if(index < vElems.size()){
1179 0 : selOut.select(vElems[index], state);
1180 : }
1181 : else{
1182 0 : UG_LOG("Bad element index in subset-node " << elemNodeName <<
1183 : ": " << index << ". Ignoring element.\n");
1184 : return false;
1185 : }
1186 : }
1187 :
1188 : // get next element node
1189 0 : elemNode = elemNode->next_sibling(elemNodeName);
1190 : }
1191 : return true;
1192 : }
1193 :
1194 :
1195 0 : size_t GridReaderUGX::
1196 : num_projection_handlers(size_t refGridIndex) const
1197 : {
1198 0 : UG_COND_THROW(refGridIndex >= m_entries.size(),
1199 : "Bad refGridIndex: " << refGridIndex);
1200 :
1201 0 : return m_entries[refGridIndex].projectionHandlerEntries.size();
1202 : }
1203 :
1204 0 : const char* GridReaderUGX::
1205 : get_projection_handler_name(size_t refGridIndex, size_t phIndex) const
1206 : {
1207 0 : UG_COND_THROW(refGridIndex >= m_entries.size(),
1208 : "Bad refGridIndex: " << refGridIndex);
1209 :
1210 : const GridEntry& ge = m_entries[refGridIndex];
1211 0 : UG_COND_THROW(phIndex >= ge.projectionHandlerEntries.size(),
1212 : "Bad projection-handler-index: " << phIndex);
1213 :
1214 0 : xml_attribute<>* attrib = ge.projectionHandlerEntries[phIndex]->first_attribute("name");
1215 0 : if(attrib)
1216 : return attrib->value();
1217 : return "";
1218 : }
1219 :
1220 :
1221 0 : size_t GridReaderUGX::get_projection_handler_subset_handler_index(size_t phIndex, size_t refGridIndex)
1222 : {
1223 0 : UG_COND_THROW(refGridIndex >= m_entries.size(),
1224 : "Bad refGridIndex: " << refGridIndex);
1225 :
1226 : const GridEntry& ge = m_entries[refGridIndex];
1227 0 : UG_COND_THROW(phIndex >= ge.projectionHandlerEntries.size(),
1228 : "Bad projection-handler-index: " << phIndex);
1229 :
1230 0 : xml_node<>* phNode = ge.projectionHandlerEntries[phIndex];
1231 :
1232 : size_t shi = 0;
1233 0 : xml_attribute<>* attribSH = phNode->first_attribute("subset_handler");
1234 0 : if (attribSH) shi = atoi(attribSH->value());
1235 :
1236 0 : return shi;
1237 : }
1238 :
1239 :
1240 0 : SPRefinementProjector GridReaderUGX::
1241 : read_projector(xml_node<>* projNode)
1242 : {
1243 0 : static Factory<RefinementProjector, ProjectorTypes> projFac;
1244 0 : static Archivar<boost::archive::text_iarchive, RefinementProjector, ProjectorTypes> archivar;
1245 :
1246 0 : xml_attribute<>* attribType = projNode->first_attribute("type");
1247 0 : if(attribType){
1248 : try {
1249 0 : SPRefinementProjector proj = projFac.create(attribType->value());
1250 :
1251 0 : string str(projNode->value(), projNode->value_size());
1252 0 : stringstream ss(str, ios_base::in);
1253 : boost::archive::text_iarchive ar(ss, boost::archive::no_header);
1254 : archivar.archive(ar, *proj);
1255 : return proj;
1256 0 : }
1257 0 : catch(boost::archive::archive_exception& e){
1258 0 : UG_LOG("WARNING: Couldn't read projector of type '" <<
1259 : attribType->value() << "'." << std::endl);
1260 0 : }
1261 : }
1262 : return SPRefinementProjector();
1263 : }
1264 :
1265 0 : bool GridReaderUGX::
1266 : projection_handler(ProjectionHandler& phOut, size_t phIndex, size_t refGridIndex)
1267 : {
1268 0 : UG_COND_THROW(refGridIndex >= m_entries.size(),
1269 : "Bad refGridIndex: " << refGridIndex);
1270 :
1271 : const GridEntry& ge = m_entries[refGridIndex];
1272 0 : UG_COND_THROW(phIndex >= ge.projectionHandlerEntries.size(),
1273 : "Bad projection-handler-index: " << phIndex);
1274 :
1275 0 : xml_node<>* phNode = ge.projectionHandlerEntries[phIndex];
1276 :
1277 0 : xml_node<>* defProjNode = phNode->first_node("default");
1278 0 : if(defProjNode){
1279 0 : SPRefinementProjector proj = read_projector(defProjNode);
1280 0 : if(proj.valid()){
1281 0 : phOut.set_default_projector(proj);
1282 : }
1283 : }
1284 :
1285 0 : xml_node<>* projNode = phNode->first_node("projector");
1286 0 : while(projNode){
1287 0 : SPRefinementProjector proj = read_projector(projNode);
1288 0 : if(!proj.valid())
1289 : continue;
1290 :
1291 0 : xml_attribute<>* attribSI = projNode->first_attribute("subset");
1292 0 : if(attribSI){
1293 0 : phOut.set_projector(atoi(attribSI->value()), proj);
1294 : }
1295 :
1296 0 : projNode = projNode->next_sibling("projector");
1297 : }
1298 :
1299 0 : return true;
1300 : }
1301 :
1302 :
1303 0 : bool GridReaderUGX::
1304 : parse_file(const char* filename)
1305 : {
1306 0 : ifstream in(filename, ios::binary);
1307 0 : if(!in)
1308 : return false;
1309 :
1310 : // get the length of the file
1311 0 : streampos posStart = in.tellg();
1312 0 : in.seekg(0, ios_base::end);
1313 0 : streampos posEnd = in.tellg();
1314 : streamsize size = posEnd - posStart;
1315 :
1316 : // go back to the start of the file
1317 0 : in.seekg(posStart);
1318 :
1319 : // read the whole file en-block and terminate it with 0
1320 0 : char* fileContent = m_doc.allocate_string(0, size + 1);
1321 0 : in.read(fileContent, size);
1322 0 : fileContent[size] = 0;
1323 0 : in.close();
1324 :
1325 : // parse the xml-data
1326 0 : m_doc.parse<0>(fileContent);
1327 :
1328 : // notify derived classes that a new document has been parsed.
1329 0 : return new_document_parsed();
1330 0 : }
1331 :
1332 0 : bool GridReaderUGX::
1333 : new_document_parsed()
1334 : {
1335 : // update entries
1336 : m_entries.clear();
1337 :
1338 : // iterate through all grids
1339 0 : xml_node<>* curNode = m_doc.first_node("grid");
1340 0 : while(curNode){
1341 0 : m_entries.push_back(GridEntry(curNode));
1342 : GridEntry& gridEntry = m_entries.back();
1343 :
1344 : // collect associated subset handlers
1345 0 : xml_node<>* curSHNode = curNode->first_node("subset_handler");
1346 0 : while(curSHNode){
1347 0 : gridEntry.subsetHandlerEntries.push_back(SubsetHandlerEntry(curSHNode));
1348 0 : curSHNode = curSHNode->next_sibling("subset_handler");
1349 : }
1350 :
1351 : // collect associated selectors
1352 0 : xml_node<>* curSelNode = curNode->first_node("selector");
1353 0 : while(curSelNode){
1354 0 : gridEntry.selectorEntries.push_back(SelectorEntry(curSelNode));
1355 0 : curSelNode = curSelNode->next_sibling("selector");
1356 : }
1357 :
1358 : // collect associated projectionHandlers
1359 0 : xml_node<>* curPHNode = curNode->first_node("projection_handler");
1360 0 : while(curPHNode){
1361 0 : gridEntry.projectionHandlerEntries.push_back(curPHNode);
1362 0 : curPHNode = curPHNode->next_sibling("projection_handler");
1363 : }
1364 :
1365 0 : curNode = curNode->next_sibling("grid");
1366 : }
1367 :
1368 0 : return true;
1369 : }
1370 :
1371 0 : bool GridReaderUGX::
1372 : create_edges(std::vector<Edge*>& edgesOut,
1373 : Grid& grid, rapidxml::xml_node<>* node,
1374 : std::vector<Vertex*>& vrts)
1375 : {
1376 : // create a buffer with which we can access the data
1377 0 : string str(node->value(), node->value_size());
1378 0 : stringstream ss(str, ios_base::in);
1379 :
1380 : // read the edges
1381 : int i1, i2;
1382 0 : while(!ss.eof()){
1383 : // read the indices
1384 0 : ss >> i1 >> i2;
1385 :
1386 : // make sure that everything went right
1387 0 : if(ss.fail())
1388 : break;
1389 :
1390 : // make sure that the indices are valid
1391 0 : int maxInd = (int)vrts.size() - 1;
1392 0 : if(i1 < 0 || i1 > maxInd ||
1393 0 : i2 < 0 || i2 > maxInd)
1394 : {
1395 0 : UG_LOG(" ERROR in GridReaderUGX::create_edges: invalid vertex index: "
1396 : "(" << i1 << ", " << i2 << ")\n");
1397 : return false;
1398 : }
1399 :
1400 : // create the edge
1401 0 : edgesOut.push_back(*grid.create<RegularEdge>(EdgeDescriptor(vrts[i1], vrts[i2])));
1402 : }
1403 :
1404 : return true;
1405 0 : }
1406 :
1407 0 : bool GridReaderUGX::
1408 : create_constraining_edges(std::vector<Edge*>& edgesOut,
1409 : Grid& grid, rapidxml::xml_node<>* node,
1410 : std::vector<Vertex*>& vrts)
1411 : {
1412 : // create a buffer with which we can access the data
1413 0 : string str(node->value(), node->value_size());
1414 0 : stringstream ss(str, ios_base::in);
1415 :
1416 : // read the edges
1417 : int i1, i2;
1418 0 : while(!ss.eof()){
1419 : // read the indices
1420 0 : ss >> i1 >> i2;
1421 :
1422 : // make sure that everything went right
1423 0 : if(ss.fail())
1424 : break;
1425 :
1426 : // make sure that the indices are valid
1427 0 : int maxInd = (int)vrts.size() - 1;
1428 0 : if(i1 < 0 || i1 > maxInd ||
1429 0 : i2 < 0 || i2 > maxInd)
1430 : {
1431 : UG_LOG(" ERROR in GridReaderUGX::create_constraining_edges: invalid vertex index.\n");
1432 : return false;
1433 : }
1434 :
1435 : // create the edge
1436 0 : edgesOut.push_back(*grid.create<ConstrainingEdge>(EdgeDescriptor(vrts[i1], vrts[i2])));
1437 : }
1438 :
1439 : return true;
1440 0 : }
1441 :
1442 0 : bool GridReaderUGX::
1443 : create_constrained_edges(std::vector<Edge*>& edgesOut,
1444 : std::vector<std::pair<int, int> >& constrainingObjsOut,
1445 : Grid& grid, rapidxml::xml_node<>* node,
1446 : std::vector<Vertex*>& vrts)
1447 : {
1448 : // create a buffer with which we can access the data
1449 0 : string str(node->value(), node->value_size());
1450 0 : stringstream ss(str, ios_base::in);
1451 :
1452 : // read the edges
1453 : int i1, i2;
1454 0 : while(!ss.eof()){
1455 : // read the indices
1456 0 : ss >> i1 >> i2;
1457 :
1458 : // read the type and index of the constraining object
1459 : int conObjType, conObjIndex;
1460 0 : ss >> conObjType;
1461 :
1462 0 : if(conObjType != -1)
1463 0 : ss >> conObjIndex;
1464 :
1465 : // make sure that everything went right
1466 0 : if(ss.fail())
1467 : break;
1468 :
1469 : // make sure that the indices are valid
1470 0 : int maxInd = (int)vrts.size() - 1;
1471 0 : if(i1 < 0 || i1 > maxInd ||
1472 0 : i2 < 0 || i2 > maxInd)
1473 : {
1474 : UG_LOG(" ERROR in GridReaderUGX::create_edges: invalid vertex index.\n");
1475 0 : return false;
1476 : }
1477 :
1478 : // create the edge
1479 0 : ConstrainedEdge* edge = *grid.create<ConstrainedEdge>(EdgeDescriptor(vrts[i1], vrts[i2]));
1480 0 : edgesOut.push_back(edge);
1481 :
1482 : // add conObjType and conObjIndex to their list
1483 0 : constrainingObjsOut.push_back(std::make_pair(conObjType, conObjIndex));
1484 : }
1485 :
1486 : return true;
1487 0 : }
1488 :
1489 0 : bool GridReaderUGX::
1490 : create_triangles(std::vector<Face*>& facesOut,
1491 : Grid& grid, rapidxml::xml_node<>* node,
1492 : std::vector<Vertex*>& vrts)
1493 : {
1494 : // create a buffer with which we can access the data
1495 0 : string str(node->value(), node->value_size());
1496 0 : stringstream ss(str, ios_base::in);
1497 :
1498 : // read the triangles
1499 : int i1, i2, i3;
1500 0 : while(!ss.eof()){
1501 : // read the indices
1502 0 : ss >> i1 >> i2 >> i3;
1503 :
1504 : // make sure that everything went right
1505 0 : if(ss.fail())
1506 : break;
1507 :
1508 : // make sure that the indices are valid
1509 0 : int maxInd = (int)vrts.size() - 1;
1510 0 : if(i1 < 0 || i1 > maxInd ||
1511 0 : i2 < 0 || i2 > maxInd ||
1512 0 : i3 < 0 || i3 > maxInd)
1513 : {
1514 : UG_LOG(" ERROR in GridReaderUGX::create_triangles: invalid vertex index.\n");
1515 : return false;
1516 : }
1517 :
1518 : // create the triangle
1519 : facesOut.push_back(
1520 0 : *grid.create<Triangle>(TriangleDescriptor(vrts[i1], vrts[i2], vrts[i3])));
1521 : }
1522 :
1523 : return true;
1524 0 : }
1525 :
1526 0 : bool GridReaderUGX::
1527 : create_constraining_triangles(std::vector<Face*>& facesOut,
1528 : Grid& grid, rapidxml::xml_node<>* node,
1529 : std::vector<Vertex*>& vrts)
1530 : {
1531 : // create a buffer with which we can access the data
1532 0 : string str(node->value(), node->value_size());
1533 0 : stringstream ss(str, ios_base::in);
1534 :
1535 : // read the triangles
1536 : int i1, i2, i3;
1537 0 : while(!ss.eof()){
1538 : // read the indices
1539 0 : ss >> i1 >> i2 >> i3;
1540 :
1541 : // make sure that everything went right
1542 0 : if(ss.fail())
1543 : break;
1544 :
1545 : // make sure that the indices are valid
1546 0 : int maxInd = (int)vrts.size() - 1;
1547 0 : if(i1 < 0 || i1 > maxInd ||
1548 0 : i2 < 0 || i2 > maxInd ||
1549 0 : i3 < 0 || i3 > maxInd)
1550 : {
1551 : UG_LOG(" ERROR in GridReaderUGX::create_constraining_triangles: invalid vertex index.\n");
1552 : return false;
1553 : }
1554 :
1555 : // create the triangle
1556 : facesOut.push_back(
1557 0 : *grid.create<ConstrainingTriangle>(TriangleDescriptor(vrts[i1], vrts[i2], vrts[i3])));
1558 : }
1559 :
1560 : return true;
1561 0 : }
1562 :
1563 0 : bool GridReaderUGX::
1564 : create_constrained_triangles(std::vector<Face*>& facesOut,
1565 : std::vector<std::pair<int, int> >& constrainingObjsOut,
1566 : Grid& grid, rapidxml::xml_node<>* node,
1567 : std::vector<Vertex*>& vrts)
1568 : {
1569 : // create a buffer with which we can access the data
1570 0 : string str(node->value(), node->value_size());
1571 0 : stringstream ss(str, ios_base::in);
1572 :
1573 : // read the triangles
1574 : int i1, i2, i3;
1575 0 : while(!ss.eof()){
1576 : // read the indices
1577 0 : ss >> i1 >> i2 >> i3;
1578 :
1579 : // read the type and index of the constraining object
1580 : int conObjType, conObjIndex;
1581 0 : ss >> conObjType;
1582 :
1583 0 : if(conObjType != -1)
1584 0 : ss >> conObjIndex;
1585 :
1586 : // make sure that everything went right
1587 0 : if(ss.fail())
1588 : break;
1589 :
1590 : // make sure that the indices are valid
1591 0 : int maxInd = (int)vrts.size() - 1;
1592 0 : if(i1 < 0 || i1 > maxInd ||
1593 0 : i2 < 0 || i2 > maxInd ||
1594 0 : i3 < 0 || i3 > maxInd)
1595 : {
1596 : UG_LOG(" ERROR in GridReaderUGX::create_constraining_triangles: invalid vertex index.\n");
1597 0 : return false;
1598 : }
1599 :
1600 : // create the triangle
1601 : facesOut.push_back(
1602 0 : *grid.create<ConstrainedTriangle>(TriangleDescriptor(vrts[i1], vrts[i2], vrts[i3])));
1603 :
1604 : // add conObjType and conObjIndex to their list
1605 0 : constrainingObjsOut.push_back(std::make_pair(conObjType, conObjIndex));
1606 : }
1607 :
1608 : return true;
1609 0 : }
1610 :
1611 0 : bool GridReaderUGX::
1612 : create_quadrilaterals(std::vector<Face*>& facesOut,
1613 : Grid& grid, rapidxml::xml_node<>* node,
1614 : std::vector<Vertex*>& vrts)
1615 : {
1616 : // create a buffer with which we can access the data
1617 0 : string str(node->value(), node->value_size());
1618 0 : stringstream ss(str, ios_base::in);
1619 :
1620 : // read the quadrilaterals
1621 : int i1, i2, i3, i4;
1622 0 : while(!ss.eof()){
1623 : // read the indices
1624 0 : ss >> i1 >> i2 >> i3 >> i4;
1625 :
1626 : // make sure that everything went right
1627 0 : if(ss.fail())
1628 : break;
1629 :
1630 : // make sure that the indices are valid
1631 0 : int maxInd = (int)vrts.size() - 1;
1632 0 : if(i1 < 0 || i1 > maxInd ||
1633 0 : i2 < 0 || i2 > maxInd ||
1634 0 : i3 < 0 || i3 > maxInd ||
1635 0 : i4 < 0 || i4 > maxInd)
1636 : {
1637 : UG_LOG(" ERROR in GridReaderUGX::create_quadrilaterals: invalid vertex index.\n");
1638 : return false;
1639 : }
1640 :
1641 : // create the quad
1642 : facesOut.push_back(
1643 0 : *grid.create<Quadrilateral>(QuadrilateralDescriptor(vrts[i1], vrts[i2],
1644 0 : vrts[i3], vrts[i4])));
1645 : }
1646 :
1647 : return true;
1648 0 : }
1649 :
1650 0 : bool GridReaderUGX::
1651 : create_constraining_quadrilaterals(std::vector<Face*>& facesOut,
1652 : Grid& grid, rapidxml::xml_node<>* node,
1653 : std::vector<Vertex*>& vrts)
1654 : {
1655 : // create a buffer with which we can access the data
1656 0 : string str(node->value(), node->value_size());
1657 0 : stringstream ss(str, ios_base::in);
1658 :
1659 : // read the quadrilaterals
1660 : int i1, i2, i3, i4;
1661 0 : while(!ss.eof()){
1662 : // read the indices
1663 0 : ss >> i1 >> i2 >> i3 >> i4;
1664 :
1665 : // make sure that everything went right
1666 0 : if(ss.fail())
1667 : break;
1668 :
1669 : // make sure that the indices are valid
1670 0 : int maxInd = (int)vrts.size() - 1;
1671 0 : if(i1 < 0 || i1 > maxInd ||
1672 0 : i2 < 0 || i2 > maxInd ||
1673 0 : i3 < 0 || i3 > maxInd ||
1674 0 : i4 < 0 || i4 > maxInd)
1675 : {
1676 : UG_LOG(" ERROR in GridReaderUGX::create_quadrilaterals: invalid vertex index.\n");
1677 : return false;
1678 : }
1679 :
1680 : // create the quad
1681 : facesOut.push_back(
1682 0 : *grid.create<ConstrainingQuadrilateral>(QuadrilateralDescriptor(
1683 0 : vrts[i1], vrts[i2],
1684 0 : vrts[i3], vrts[i4])));
1685 : }
1686 :
1687 : return true;
1688 0 : }
1689 :
1690 0 : bool GridReaderUGX::
1691 : create_constrained_quadrilaterals(std::vector<Face*>& facesOut,
1692 : std::vector<std::pair<int, int> >& constrainingObjsOut,
1693 : Grid& grid, rapidxml::xml_node<>* node,
1694 : std::vector<Vertex*>& vrts)
1695 : {
1696 : // create a buffer with which we can access the data
1697 0 : string str(node->value(), node->value_size());
1698 0 : stringstream ss(str, ios_base::in);
1699 :
1700 : // read the quadrilaterals
1701 : int i1, i2, i3, i4;
1702 0 : while(!ss.eof()){
1703 : // read the indices
1704 0 : ss >> i1 >> i2 >> i3 >> i4;
1705 :
1706 : // read the type and index of the constraining object
1707 : int conObjType, conObjIndex;
1708 0 : ss >> conObjType;
1709 :
1710 0 : if(conObjType != -1)
1711 0 : ss >> conObjIndex;
1712 :
1713 : // make sure that everything went right
1714 0 : if(ss.fail())
1715 : break;
1716 :
1717 : // make sure that the indices are valid
1718 0 : int maxInd = (int)vrts.size() - 1;
1719 0 : if(i1 < 0 || i1 > maxInd ||
1720 0 : i2 < 0 || i2 > maxInd ||
1721 0 : i3 < 0 || i3 > maxInd ||
1722 0 : i4 < 0 || i4 > maxInd)
1723 : {
1724 : UG_LOG(" ERROR in GridReaderUGX::create_quadrilaterals: invalid vertex index.\n");
1725 0 : return false;
1726 : }
1727 :
1728 : // create the quad
1729 : facesOut.push_back(
1730 0 : *grid.create<ConstrainedQuadrilateral>(QuadrilateralDescriptor(
1731 0 : vrts[i1], vrts[i2],
1732 0 : vrts[i3], vrts[i4])));
1733 :
1734 : // add conObjType and conObjIndex to their list
1735 0 : constrainingObjsOut.push_back(std::make_pair(conObjType, conObjIndex));
1736 : }
1737 :
1738 : return true;
1739 0 : }
1740 :
1741 :
1742 0 : bool GridReaderUGX::
1743 : create_tetrahedrons(std::vector<Volume*>& volsOut,
1744 : Grid& grid, rapidxml::xml_node<>* node,
1745 : std::vector<Vertex*>& vrts)
1746 : {
1747 : // create a buffer with which we can access the data
1748 0 : string str(node->value(), node->value_size());
1749 0 : stringstream ss(str, ios_base::in);
1750 :
1751 : // read the tetrahedrons
1752 : int i1, i2, i3, i4;
1753 0 : while(!ss.eof()){
1754 : // read the indices
1755 0 : ss >> i1 >> i2 >> i3 >> i4;
1756 :
1757 : // make sure that everything went right
1758 0 : if(ss.fail())
1759 : break;
1760 :
1761 : // make sure that the indices are valid
1762 0 : int maxInd = (int)vrts.size() - 1;
1763 0 : if(i1 < 0 || i1 > maxInd ||
1764 0 : i2 < 0 || i2 > maxInd ||
1765 0 : i3 < 0 || i3 > maxInd ||
1766 0 : i4 < 0 || i4 > maxInd)
1767 : {
1768 : UG_LOG(" ERROR in GridReaderUGX::create_tetrahedrons: invalid vertex index.\n");
1769 : return false;
1770 : }
1771 :
1772 : // create the element
1773 : volsOut.push_back(
1774 0 : *grid.create<Tetrahedron>(TetrahedronDescriptor(vrts[i1], vrts[i2],
1775 0 : vrts[i3], vrts[i4])));
1776 : }
1777 :
1778 : return true;
1779 0 : }
1780 :
1781 0 : bool GridReaderUGX::
1782 : create_hexahedrons(std::vector<Volume*>& volsOut,
1783 : Grid& grid, rapidxml::xml_node<>* node,
1784 : std::vector<Vertex*>& vrts)
1785 : {
1786 : // create a buffer with which we can access the data
1787 0 : string str(node->value(), node->value_size());
1788 0 : stringstream ss(str, ios_base::in);
1789 :
1790 : // read the hexahedrons
1791 : int i1, i2, i3, i4, i5, i6, i7, i8;
1792 0 : while(!ss.eof()){
1793 : // read the indices
1794 0 : ss >> i1 >> i2 >> i3 >> i4 >> i5 >> i6 >> i7 >> i8;
1795 :
1796 : // make sure that everything went right
1797 0 : if(ss.fail())
1798 : break;
1799 :
1800 : // make sure that the indices are valid
1801 0 : int maxInd = (int)vrts.size() - 1;
1802 0 : if(i1 < 0 || i1 > maxInd ||
1803 0 : i2 < 0 || i2 > maxInd ||
1804 0 : i3 < 0 || i3 > maxInd ||
1805 0 : i4 < 0 || i4 > maxInd ||
1806 0 : i5 < 0 || i5 > maxInd ||
1807 0 : i6 < 0 || i6 > maxInd ||
1808 0 : i7 < 0 || i7 > maxInd ||
1809 0 : i8 < 0 || i8 > maxInd)
1810 : {
1811 : UG_LOG(" ERROR in GridReaderUGX::create_hexahedrons: invalid vertex index.\n");
1812 : return false;
1813 : }
1814 :
1815 : // create the element
1816 : volsOut.push_back(
1817 0 : *grid.create<Hexahedron>(HexahedronDescriptor(vrts[i1], vrts[i2], vrts[i3], vrts[i4],
1818 0 : vrts[i5], vrts[i6], vrts[i7], vrts[i8])));
1819 : }
1820 :
1821 : return true;
1822 0 : }
1823 :
1824 0 : bool GridReaderUGX::
1825 : create_prisms(std::vector<Volume*>& volsOut,
1826 : Grid& grid, rapidxml::xml_node<>* node,
1827 : std::vector<Vertex*>& vrts)
1828 : {
1829 : // create a buffer with which we can access the data
1830 0 : string str(node->value(), node->value_size());
1831 0 : stringstream ss(str, ios_base::in);
1832 :
1833 : // read the hexahedrons
1834 : int i1, i2, i3, i4, i5, i6;
1835 0 : while(!ss.eof()){
1836 : // read the indices
1837 0 : ss >> i1 >> i2 >> i3 >> i4 >> i5 >> i6;
1838 :
1839 : // make sure that everything went right
1840 0 : if(ss.fail())
1841 : break;
1842 :
1843 : // make sure that the indices are valid
1844 0 : int maxInd = (int)vrts.size() - 1;
1845 0 : if(i1 < 0 || i1 > maxInd ||
1846 0 : i2 < 0 || i2 > maxInd ||
1847 0 : i3 < 0 || i3 > maxInd ||
1848 0 : i4 < 0 || i4 > maxInd ||
1849 0 : i5 < 0 || i5 > maxInd ||
1850 0 : i6 < 0 || i6 > maxInd)
1851 : {
1852 : UG_LOG(" ERROR in GridReaderUGX::create_prisms: invalid vertex index.\n");
1853 : return false;
1854 : }
1855 :
1856 : // create the element
1857 : volsOut.push_back(
1858 0 : *grid.create<Prism>(PrismDescriptor(vrts[i1], vrts[i2], vrts[i3], vrts[i4],
1859 0 : vrts[i5], vrts[i6])));
1860 : }
1861 :
1862 : return true;
1863 0 : }
1864 :
1865 0 : bool GridReaderUGX::
1866 : create_pyramids(std::vector<Volume*>& volsOut,
1867 : Grid& grid, rapidxml::xml_node<>* node,
1868 : std::vector<Vertex*>& vrts)
1869 : {
1870 : // create a buffer with which we can access the data
1871 0 : string str(node->value(), node->value_size());
1872 0 : stringstream ss(str, ios_base::in);
1873 :
1874 : // read the hexahedrons
1875 : int i1, i2, i3, i4, i5;
1876 0 : while(!ss.eof()){
1877 : // read the indices
1878 0 : ss >> i1 >> i2 >> i3 >> i4 >> i5;
1879 :
1880 : // make sure that everything went right
1881 0 : if(ss.fail())
1882 : break;
1883 :
1884 : // make sure that the indices are valid
1885 0 : int maxInd = (int)vrts.size() - 1;
1886 0 : if(i1 < 0 || i1 > maxInd ||
1887 0 : i2 < 0 || i2 > maxInd ||
1888 0 : i3 < 0 || i3 > maxInd ||
1889 0 : i4 < 0 || i4 > maxInd ||
1890 0 : i5 < 0 || i5 > maxInd)
1891 : {
1892 : UG_LOG(" ERROR in GridReaderUGX::create_pyramids: invalid vertex index.\n");
1893 : return false;
1894 : }
1895 :
1896 : // create the element
1897 : volsOut.push_back(
1898 0 : *grid.create<Pyramid>(PyramidDescriptor(vrts[i1], vrts[i2], vrts[i3],
1899 0 : vrts[i4], vrts[i5])));
1900 : }
1901 :
1902 : return true;
1903 0 : }
1904 :
1905 0 : bool GridReaderUGX::
1906 : create_octahedrons(std::vector<Volume*>& volsOut,
1907 : Grid& grid, rapidxml::xml_node<>* node,
1908 : std::vector<Vertex*>& vrts)
1909 : {
1910 : // create a buffer with which we can access the data
1911 0 : string str(node->value(), node->value_size());
1912 0 : stringstream ss(str, ios_base::in);
1913 :
1914 : // read the octahedrons
1915 : int i1, i2, i3, i4, i5, i6;
1916 0 : while(!ss.eof()){
1917 : // read the indices
1918 0 : ss >> i1 >> i2 >> i3 >> i4 >> i5 >> i6;
1919 :
1920 : // make sure that everything went right
1921 0 : if(ss.fail())
1922 : break;
1923 :
1924 : // make sure that the indices are valid
1925 0 : int maxInd = (int)vrts.size() - 1;
1926 0 : if(i1 < 0 || i1 > maxInd ||
1927 0 : i2 < 0 || i2 > maxInd ||
1928 0 : i3 < 0 || i3 > maxInd ||
1929 0 : i4 < 0 || i4 > maxInd ||
1930 0 : i5 < 0 || i5 > maxInd ||
1931 0 : i6 < 0 || i6 > maxInd)
1932 : {
1933 : UG_LOG(" ERROR in GridReaderUGX::create_octahedrons: invalid vertex index.\n");
1934 : return false;
1935 : }
1936 :
1937 : // create the element
1938 : volsOut.push_back(
1939 0 : *grid.create<Octahedron>(OctahedronDescriptor( vrts[i1], vrts[i2], vrts[i3],
1940 0 : vrts[i4], vrts[i5], vrts[i6])));
1941 : }
1942 :
1943 : return true;
1944 0 : }
1945 :
1946 :
1947 0 : UGXFileInfo::UGXFileInfo() :
1948 0 : m_fileParsed(false)
1949 : {
1950 0 : }
1951 :
1952 0 : bool UGXFileInfo::parse_file(const char* filename)
1953 : {
1954 : PROFILE_FUNC_GROUP("UGXFileInfo");
1955 0 : string tfile = FindFileInStandardPaths(filename);
1956 :
1957 0 : ifstream in(tfile.c_str(), ios::binary);
1958 0 : UG_COND_THROW(!in, "UGXFileInfo: couldn't find file '" << filename << "'");
1959 :
1960 : // get the length of the file
1961 0 : streampos posStart = in.tellg();
1962 0 : in.seekg(0, ios_base::end);
1963 0 : streampos posEnd = in.tellg();
1964 : streamsize size = posEnd - posStart;
1965 :
1966 : // go back to the start of the file
1967 0 : in.seekg(posStart);
1968 :
1969 : // read the whole file en-block and terminate it with 0
1970 : rapidxml::xml_document<> doc;
1971 0 : char* fileContent = doc.allocate_string(0, size + 1);
1972 0 : in.read(fileContent, size);
1973 0 : fileContent[size] = 0;
1974 0 : in.close();
1975 :
1976 : // parse the xml-data
1977 0 : doc.parse<0>(fileContent);
1978 :
1979 0 : xml_node<>* curNode = doc.first_node("grid");
1980 0 : while(curNode){
1981 0 : m_grids.push_back(GridInfo());
1982 : GridInfo& gInfo = m_grids.back();
1983 0 : gInfo.m_name = node_name(curNode);
1984 :
1985 : // collect associated subset handlers
1986 0 : xml_node<>* curSHNode = curNode->first_node("subset_handler");
1987 0 : while(curSHNode){
1988 0 : gInfo.m_subsetHandlers.push_back(SubsetHandlerInfo());
1989 : SubsetHandlerInfo& shInfo = gInfo.m_subsetHandlers.back();
1990 0 : shInfo.m_name = node_name(curSHNode);
1991 :
1992 0 : xml_node<>* curSubsetNode = curSHNode->first_node("subset");
1993 :
1994 0 : while(curSubsetNode){
1995 0 : shInfo.m_subsets.push_back(SubsetInfo());
1996 : SubsetInfo& sInfo = shInfo.m_subsets.back();
1997 0 : sInfo.m_name = node_name(curSubsetNode);
1998 0 : curSubsetNode = curSubsetNode->next_sibling("subset");
1999 : }
2000 :
2001 0 : curSHNode = curSHNode->next_sibling("subset_handler");
2002 : }
2003 :
2004 : // loop through vertices to find bounding box of geometry
2005 : AABox<vector3> box(vector3(0, 0, 0), vector3(0, 0, 0));
2006 0 : xml_node<>* vrtNode = curNode->first_node("vertices");
2007 0 : while (vrtNode)
2008 : {
2009 : // create a bounding box around the vertices contained in this xml node
2010 : AABox<vector3> newBox;
2011 0 : bool validBox = calculate_vertex_node_bbox(vrtNode, newBox);
2012 0 : if (validBox)
2013 0 : box = AABox<vector3>(box, newBox);
2014 :
2015 0 : vrtNode = vrtNode->next_sibling("vertices");
2016 : }
2017 :
2018 : // TODO: Do we have to consider ConstrainedVertices here?
2019 :
2020 0 : gInfo.m_extension = box.extension();
2021 :
2022 : // fill m_hasVertices, ...
2023 0 : gInfo.m_hasVertices = curNode->first_node("vertices") != NULL;
2024 0 : gInfo.m_hasVertices |= curNode->first_node("constrained_vertices") != NULL;
2025 :
2026 0 : gInfo.m_hasEdges = curNode->first_node("edges") != NULL;
2027 0 : gInfo.m_hasEdges |= curNode->first_node("constraining_edges") != NULL;
2028 0 : gInfo.m_hasEdges |= curNode->first_node("constrained_edges") != NULL;
2029 :
2030 0 : gInfo.m_hasFaces = curNode->first_node("triangles") != NULL;
2031 0 : gInfo.m_hasFaces |= curNode->first_node("constraining_triangles") != NULL;
2032 0 : gInfo.m_hasFaces |= curNode->first_node("constrained_triangles") != NULL;
2033 0 : gInfo.m_hasFaces |= curNode->first_node("quadrilaterals") != NULL;
2034 0 : gInfo.m_hasFaces |= curNode->first_node("constraining_quadrilaterals") != NULL;
2035 0 : gInfo.m_hasFaces |= curNode->first_node("constrained_quadrilaterals") != NULL;
2036 :
2037 0 : gInfo.m_hasVolumes = curNode->first_node("tetrahedrons") != NULL;
2038 0 : gInfo.m_hasVolumes |= curNode->first_node("hexahedrons") != NULL;
2039 0 : gInfo.m_hasVolumes |= curNode->first_node("prisms") != NULL;
2040 0 : gInfo.m_hasVolumes |= curNode->first_node("pyramids") != NULL;
2041 :
2042 0 : curNode = curNode->next_sibling("grid");
2043 : }
2044 :
2045 0 : m_fileParsed = true;
2046 0 : return true;
2047 0 : }
2048 :
2049 0 : size_t UGXFileInfo::num_grids() const
2050 : {
2051 0 : check_file_parsed();
2052 0 : return m_grids.size();
2053 : }
2054 :
2055 0 : size_t UGXFileInfo::num_subset_handlers(size_t gridInd) const
2056 : {
2057 0 : return grid_info(gridInd).m_subsetHandlers.size();
2058 : }
2059 :
2060 0 : size_t UGXFileInfo::num_subsets(size_t gridInd, size_t shInd) const
2061 : {
2062 0 : return subset_handler_info(gridInd, shInd).m_subsets.size();
2063 : }
2064 :
2065 0 : std::string UGXFileInfo::grid_name(size_t gridInd) const
2066 : {
2067 0 : return grid_info(gridInd).m_name;
2068 : }
2069 :
2070 0 : std::string UGXFileInfo::subset_handler_name(size_t gridInd, size_t shInd) const
2071 : {
2072 0 : return subset_handler_info(gridInd, shInd).m_name;
2073 : }
2074 :
2075 0 : std::string UGXFileInfo::subset_name(size_t gridInd, size_t shInd, size_t subsetInd) const
2076 : {
2077 0 : return subset_info(gridInd, shInd, subsetInd).m_name;
2078 : }
2079 :
2080 0 : bool UGXFileInfo::grid_has_vertices(size_t gridInd) const
2081 : {
2082 0 : return grid_info(gridInd).m_hasVertices;
2083 : }
2084 :
2085 0 : bool UGXFileInfo::grid_has_edges(size_t gridInd) const
2086 : {
2087 0 : return grid_info(gridInd).m_hasEdges;
2088 : }
2089 :
2090 0 : bool UGXFileInfo::grid_has_faces(size_t gridInd) const
2091 : {
2092 0 : return grid_info(gridInd).m_hasFaces;
2093 : }
2094 :
2095 0 : bool UGXFileInfo::grid_has_volumes(size_t gridInd) const
2096 : {
2097 0 : return grid_info(gridInd).m_hasVolumes;
2098 : }
2099 :
2100 0 : size_t UGXFileInfo::physical_grid_dimension(size_t gridInd) const
2101 : {
2102 0 : const GridInfo& gi = grid_info(gridInd);
2103 :
2104 : const vector3& ext = gi.m_extension;
2105 0 : const number relSmall = SMALL * std::max(ext[0], std::max(ext[1], ext[2]));
2106 0 : for (int i = 2; i >= 0; --i)
2107 : {
2108 0 : if (ext[i] > relSmall)
2109 0 : return (size_t) (i + 1);
2110 : }
2111 : return 0;
2112 : }
2113 :
2114 0 : size_t UGXFileInfo::topological_grid_dimension(size_t gridInd) const
2115 : {
2116 0 : const GridInfo& gi = grid_info(gridInd);
2117 :
2118 0 : if(gi.m_hasVolumes)
2119 : return 3;
2120 0 : if(gi.m_hasFaces)
2121 : return 2;
2122 0 : if(gi.m_hasEdges)
2123 0 : return 1;
2124 :
2125 : return 0;
2126 : }
2127 :
2128 0 : size_t UGXFileInfo::grid_world_dimension(size_t gridInd) const
2129 : {
2130 0 : return physical_grid_dimension(gridInd);
2131 : }
2132 :
2133 0 : std::string UGXFileInfo::node_name(rapidxml::xml_node<>* n) const
2134 : {
2135 0 : xml_attribute<>* attrib = n->first_attribute("name");
2136 0 : if(attrib)
2137 0 : return attrib->value();
2138 0 : return "";
2139 : }
2140 :
2141 0 : void UGXFileInfo::check_file_parsed() const
2142 : {
2143 0 : if(!m_fileParsed){
2144 0 : UG_THROW("UGXFileInfo: no file has been parsed!");
2145 : }
2146 0 : }
2147 :
2148 : const UGXFileInfo::GridInfo&
2149 0 : UGXFileInfo::grid_info(size_t index) const
2150 : {
2151 0 : check_file_parsed();
2152 0 : if(index >= m_grids.size()){
2153 0 : UG_THROW("Grid index out of range: " << index
2154 : << ". Num grids available: " << m_grids.size());
2155 : }
2156 :
2157 0 : return m_grids[index];
2158 : }
2159 :
2160 : const UGXFileInfo::SubsetHandlerInfo&
2161 0 : UGXFileInfo::subset_handler_info(size_t gridInd, size_t shInd) const
2162 : {
2163 0 : const GridInfo& gi = grid_info(gridInd);
2164 0 : if(shInd >= gi.m_subsetHandlers.size()){
2165 0 : UG_THROW("SubsetHandler index out of range: " << shInd
2166 : << ". Num subset-handlers available: "
2167 : << gi.m_subsetHandlers.size());
2168 : }
2169 :
2170 0 : return gi.m_subsetHandlers[shInd];
2171 : }
2172 :
2173 : const UGXFileInfo::SubsetInfo&
2174 0 : UGXFileInfo::subset_info(size_t gridInd, size_t shInd, size_t subsetInd) const
2175 : {
2176 0 : const SubsetHandlerInfo& shInfo = subset_handler_info(gridInd, shInd);
2177 0 : if(subsetInd >= shInfo.m_subsets.size()){
2178 0 : UG_THROW("Subset index out of range: " << subsetInd
2179 : << ". Num subset available: "
2180 : << shInfo.m_subsets.size());
2181 : }
2182 :
2183 0 : return shInfo.m_subsets[subsetInd];
2184 : }
2185 :
2186 : bool
2187 0 : UGXFileInfo::calculate_vertex_node_bbox(rapidxml::xml_node<>* vrtNode, AABox<vector3>& bb) const
2188 : {
2189 : size_t numSrcCoords = 0;
2190 0 : rapidxml::xml_attribute<>* attrib = vrtNode->first_attribute("coords");
2191 0 : if (!attrib) return false;
2192 :
2193 0 : numSrcCoords = std::strtoul(attrib->value(), NULL, 10);
2194 : UG_ASSERT(errno != ERANGE, "Coordinate dimension in .ugx file is out of range.");
2195 : UG_ASSERT(numSrcCoords <= 3,
2196 : "Coordinate dimension in .ugx file needs to be in {0,1,2,3}, but is "
2197 : << numSrcCoords << ".");
2198 :
2199 0 : if (numSrcCoords > 3)
2200 : return false;
2201 :
2202 : // create a buffer with which we can access the data
2203 0 : std::string str(vrtNode->value(), vrtNode->value_size());
2204 0 : std::stringstream ss(str, std::ios_base::in);
2205 :
2206 : AABox<vector3> box(vector3(0, 0, 0), vector3(0, 0, 0));
2207 : vector3 min(0, 0, 0);
2208 : vector3 max(0, 0, 0);
2209 : vector3 vrt(0, 0, 0);
2210 : size_t nVrt = 0;
2211 0 : while (!ss.eof())
2212 : {
2213 0 : for (size_t i = 0; i < numSrcCoords; ++i)
2214 : ss >> vrt[i];
2215 :
2216 0 : if (ss.fail())
2217 : break;
2218 :
2219 0 : ++nVrt;
2220 :
2221 0 : for (size_t j = 0; j < numSrcCoords; ++j)
2222 : {
2223 0 : min[j] = std::min(min[j], vrt[j]);
2224 0 : max[j] = std::max(max[j], vrt[j]);
2225 : }
2226 : }
2227 :
2228 : // create bounding box
2229 : bb = AABox<vector3>(min, max);
2230 :
2231 0 : return nVrt > 0;
2232 0 : }
2233 :
2234 : }// end of namespace
|