LCOV - code coverage report
Current view: top level - ugbase/lib_grid/file_io - file_io_ug.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 352 0
Test Date: 2025-09-21 23:31:46 Functions: 0.0 % 11 0

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2009-2015:  G-CSC, Goethe University Frankfurt
       3              :  * Authors: Martin Stepniewski, 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 <vector>
      34              : #include <string>
      35              : #include <fstream>
      36              : #include <sstream>
      37              : #include <cstdlib>
      38              : #include <cstring>
      39              : #include <algorithm>
      40              : #include <set>
      41              : #include "file_io_ug.h"
      42              : #include "lib_grid/lg_base.h"
      43              : #include "lib_grid/algorithms/attachment_util.h"
      44              : #include "lib_grid/algorithms/geom_obj_util/geom_obj_util.h"
      45              : #include "lib_grid/algorithms/orientation_util.h"
      46              : #include "lib_grid/algorithms/polychain_util.h"
      47              : #include "lib_grid/callbacks/callbacks.h"
      48              : 
      49              : 
      50              : using namespace std;
      51              : 
      52              : namespace ug
      53              : {
      54              : 
      55              : static  bool CollectLines(Grid& grid, const SubsetHandler& shFace, EdgeSelector& LineSel);
      56              : 
      57              : static  bool CollectInnerVertices(Grid& grid, VertexSelector& InnVrtSel, VertexSelector& SurfVrtSel);
      58              : 
      59              : static  bool CollectSurfaceVertices(Grid& grid, const SubsetHandler& shFace,
      60              :                                                                         VertexSelector& SurfVrtSel);
      61              : 
      62              : static  bool CollectAllVerticesForNG(Grid& grid, VertexSelector& NgVrtSel,
      63              :                                                         VertexSelector& SurfVrtSel, VertexSelector& InnVrtSel);
      64              : 
      65              : static bool WriteLGM(Grid& grid,
      66              :                                           const char* lgmFilename,
      67              :                                           const char* problemName,
      68              :                                           const char* lgmName,
      69              :                                           int convex,
      70              :                                           const SubsetHandler& shFaces,
      71              :                                           const SubsetHandler& shVolumes,
      72              :                                           EdgeSelector& LineSel,
      73              :                                           VertexSelector& SurfVrtSel,
      74              :                                           Grid::EdgeAttachmentAccessor<AInt>& aaLineIndex,
      75              :                                           Grid::VertexAttachmentAccessor<AInt>& aaSurfVrtIndex,
      76              :                                           Grid::VertexAttachmentAccessor<AVector3>& aaPos);
      77              : 
      78              : static  bool GetRightLeftUnitIndex(int& rightIndex, int& leftIndex, Grid& grid, Face* face,
      79              :                                                                    const SubsetHandler& shVolume);
      80              : 
      81              : static bool WriteNG(Grid& grid,
      82              :                                          const SubsetHandler& shFaces,
      83              :                                          const SubsetHandler& shVolumes,
      84              :                                          const char* ngFilename,
      85              :                                          VertexSelector& SurfVrtSel,
      86              :                                          VertexSelector& InnVrtSel,
      87              :                                          VertexSelector& NgVrtSel,
      88              :                                          EdgeSelector& LineSel,
      89              :                                          Grid::EdgeAttachmentAccessor<AInt>& aaLineIndex,
      90              :                                          Grid::VertexAttachmentAccessor<AInt>& aaInnVrtIndex,
      91              :                                          Grid::VertexAttachmentAccessor<AInt>& aaNgVrtIndex,
      92              :                                          Grid::FaceAttachmentAccessor<AInt>& aaFaceIndex,
      93              :                                          Grid::VertexAttachmentAccessor<AVector3>& aaPos);
      94              : 
      95              : //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
      96              : //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
      97              : //      ConvertTETGENToUG
      98              : /// converts tetgen files (*.node, *.face and *.ele) to UG files (*.lgm, *.ng)
      99            0 : bool ExportGridToUG(const Grid& g, const SubsetHandler& shFace, const SubsetHandler& shVolume,
     100              :                                         const char* fileNamePrefix, const char* lgmName,
     101              :                                         const char* problemName, int convex)
     102              : {
     103              : //      the original grid may not be altered
     104            0 :         Grid grid = g;
     105              : 
     106              : //      we need subset-handlers that operate on the local grid
     107            0 :         SubsetHandler shFaces(grid, SHE_FACE);
     108            0 :         SubsetHandler shVolumes(grid, SHE_VOLUME);
     109            0 :         shFaces = shFace;
     110            0 :         shVolumes = shVolume;
     111              : 
     112              : //      fix orientation of faces
     113            0 :         for(int i = 0; i < shFaces.num_subsets(); ++i)
     114            0 :                 FixFaceOrientation(grid, shFaces.begin<Face>(i), shFaces.end<Face>(i));
     115              : 
     116              : //      make sure that all face-subsets are in consecutive order
     117              :         {
     118              :                 bool foundEmpty = false;
     119            0 :                 for(int i = 0; i < shFaces.num_subsets(); ++i){
     120            0 :                         if(shFaces.num<Face>(i) == 0)
     121              :                                 foundEmpty = true;
     122              :                         else{
     123            0 :                                 if(foundEmpty){
     124              :                                 //      there must be no empty face-subsets between filled ones.
     125              :                                         UG_LOG("WARNING in ExportGridToUG: Empty face subset found between filled ones. Aborting...\n");
     126              :                                         return false;
     127              :                                 }
     128              :                         }
     129              :                 }
     130              :         }
     131              : 
     132              : //      make sure that all volume-subsets are in consecutive order
     133              :         {
     134              :                 bool foundEmpty = false;
     135            0 :                 for(int i = 0; i < shVolumes.num_subsets(); ++i){
     136            0 :                         if(shVolumes.num<Volume>(i) == 0)
     137              :                                 foundEmpty = true;
     138              :                         else{
     139            0 :                                 if(foundEmpty){
     140              :                                 //      there must be no empty volume-subsets between filled ones.
     141              :                                         UG_LOG("WARNING in ExportGridToUG: Empty volume subset found between filled ones. Aborting...\n");
     142              :                                         return false;
     143              :                                 }
     144              :                         }
     145              :                 }
     146              :         }
     147              : 
     148              : //      initialization
     149            0 :         EdgeSelector    LineSel(grid);
     150            0 :         VertexSelector  NgVrtSel(grid);
     151            0 :         VertexSelector  SurfVrtSel(grid);
     152            0 :         VertexSelector  InnVrtSel(grid);
     153              : 
     154            0 :         grid.enable_options(FACEOPT_AUTOGENERATE_EDGES);
     155            0 :         grid.enable_options(EDGEOPT_STORE_ASSOCIATED_FACES);
     156              : //      for write ng
     157            0 :         grid.enable_options(FACEOPT_STORE_ASSOCIATED_EDGES);
     158            0 :         grid.enable_options(VRTOPT_STORE_ASSOCIATED_FACES);
     159              : 
     160              :         Grid::VertexAttachmentAccessor<AVector3> aaPos(grid, aPosition);
     161              : 
     162              : //      selection of lines, surface-vertices, inner vertices
     163            0 :         CollectLines(grid, shFaces, LineSel);
     164            0 :         CollectSurfaceVertices(grid, shFaces, SurfVrtSel);
     165            0 :         CollectInnerVertices(grid, InnVrtSel, SurfVrtSel);
     166            0 :         CollectAllVerticesForNG(grid, NgVrtSel, SurfVrtSel, InnVrtSel);
     167              : 
     168              : 
     169              : //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
     170              : //      INDEX ASSIGNMENT SECTION >>>>>>>>>>>>>>>>>>>>>>>>>
     171              : //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
     172              :         //      assign index to every line
     173              :                 AInt aLineIndex;
     174              :                 grid.attach_to_edges(aLineIndex);
     175              :                 Grid::EdgeAttachmentAccessor<AInt> aaLineIndex(grid, aLineIndex);
     176              :                 int counter = 0;
     177            0 :                 for(EdgeIterator EIter = LineSel.begin(); EIter != LineSel.end(); ++EIter, ++counter)
     178            0 :                         aaLineIndex[*EIter] = counter;
     179              : 
     180              :         //      assign index to every face regarding EACH surface
     181              :                 AInt aFaceIndex;
     182              :                 grid.attach_to_faces(aFaceIndex);
     183              :                 Grid::FaceAttachmentAccessor<AInt> aaFaceIndex(grid, aFaceIndex);
     184            0 :                 for(int i = 0; i < shFaces.num_subsets(); ++i)
     185              :                 {
     186              :                         counter = 0;
     187              :                 //      assign triangle indices
     188            0 :                         for(TriangleIterator iter = shFaces.begin<Triangle>(i);
     189            0 :                                 iter != shFaces.end<Triangle>(i); ++iter, ++counter)
     190            0 :                                 aaFaceIndex[*iter] = counter;
     191              : 
     192              :                 //      assign quadrilaterals. Increase index by 2, since 2 triangles are written for each quad
     193            0 :                         for(QuadrilateralIterator iter = shFaces.begin<Quadrilateral>(i);
     194            0 :                                 iter != shFaces.end<Quadrilateral>(i); ++iter, counter += 2)
     195            0 :                                 aaFaceIndex[*iter] = counter;
     196              :                 }
     197              : 
     198              :         //      assign index to every grid-vertex in *.ng file order
     199              :                 AInt aNgVrtIndex;
     200              :                 grid.attach_to_vertices(aNgVrtIndex);
     201              :                 Grid::VertexAttachmentAccessor<AInt> aaNgVrtIndex(grid, aNgVrtIndex);
     202              :                 counter = 0;
     203            0 :                 for(VertexIterator VIter = NgVrtSel.begin(); VIter != NgVrtSel.end(); ++VIter, ++counter)
     204            0 :                         aaNgVrtIndex[*VIter] = counter;
     205              : 
     206              :         //      assign index to every inner-vertex
     207              :                 AInt aInnVrtIndex;
     208              :                 grid.attach_to_vertices(aInnVrtIndex);
     209              :                 Grid::VertexAttachmentAccessor<AInt> aaInnVrtIndex(grid, aInnVrtIndex);
     210              :                 counter = 0;
     211            0 :                 for(VertexIterator VIter = InnVrtSel.begin(); VIter != InnVrtSel.end(); ++VIter, ++counter)
     212            0 :                         aaInnVrtIndex[*VIter] = counter;
     213              : 
     214              :         //      assign index to every surface-vertex
     215              :                 AInt aSurfVrtIndex;
     216              :                 grid.attach_to_vertices(aSurfVrtIndex);
     217              :                 Grid::VertexAttachmentAccessor<AInt> aaSurfVrtIndex(grid, aSurfVrtIndex);
     218              :                 counter = 0;
     219            0 :                 for(VertexIterator SVIter = SurfVrtSel.begin(); SVIter != SurfVrtSel.end(); ++SVIter, ++counter)
     220            0 :                         aaSurfVrtIndex[*SVIter] = counter;
     221              : //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
     222              : //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
     223            0 :         string lgmFilename(fileNamePrefix);
     224            0 :         lgmFilename.append(".lgm");
     225              : //      write *.lgm file
     226            0 :         WriteLGM(grid, lgmFilename.c_str(), problemName, lgmName,
     227              :                          convex, shFaces, shVolumes, LineSel, SurfVrtSel, aaLineIndex, aaSurfVrtIndex, aaPos);
     228              : 
     229            0 :         string ngFilename(fileNamePrefix);
     230            0 :         ngFilename.append(".ng");
     231              : 
     232              : //      write *.ng file
     233            0 :         WriteNG(grid, shFaces, shVolumes, ngFilename.c_str(), SurfVrtSel, InnVrtSel, NgVrtSel, LineSel,
     234              :                         aaLineIndex, aaInnVrtIndex, aaNgVrtIndex, aaFaceIndex, aaPos);
     235              : 
     236              :         return true;
     237            0 : }
     238              : 
     239              : //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     240              : //      CollectLines
     241              : /// collects lines in a selector
     242            0 : static bool CollectLines(Grid& grid, const SubsetHandler& shFace, EdgeSelector& LineSel)
     243              : {
     244              : //      store associated faces in this vector
     245              :         vector<Face*> vFaces;
     246              : 
     247              : //      iterate through all edges in the grid and identify lines by comparing the subset-membership
     248              : //      of the associated faces
     249            0 :         for(EdgeIterator EIter = grid.edges_begin(); EIter != grid.edges_end(); ++EIter)
     250              :         {
     251            0 :                 CollectFaces(vFaces, grid, *EIter);
     252              : 
     253              :                 //if(vFaces.size() > 1)
     254              :                 {
     255              :                         size_t i = 0;
     256              :                         Face* f1 = NULL;
     257              :                 //      find the first face that is assigned to a subset
     258            0 :                         for(; i < vFaces.size(); ++i)
     259              :                         {
     260            0 :                                 if(shFace.get_subset_index(vFaces[i]) != -1){
     261            0 :                                         f1 = vFaces[i];
     262              :                                 //      if the iteration leaves with a break, we have to increase i manually
     263            0 :                                         ++i;
     264            0 :                                         break;
     265              :                                 }
     266              :                         }
     267              :                                                 
     268              :                 //      compare with others. only check the ones that are assigned to a subset.
     269              :                 //      if only one face is in a subset, we'll need a line anyway
     270              :                         bool gotTwoSubsetFaces = false;
     271            0 :                         for(; i < vFaces.size(); ++i)
     272              :                         {
     273            0 :                                 if(shFace.get_subset_index(vFaces[i]) == -1)
     274            0 :                                         continue;
     275              : 
     276              :                                 gotTwoSubsetFaces = true;
     277            0 :                                 if(shFace.get_subset_index(f1) != shFace.get_subset_index(vFaces[i]))
     278              :                                 {
     279            0 :                                         LineSel.select(*EIter);
     280              :                                         break;
     281              :                                 }
     282              :                         }
     283              :                         
     284            0 :                         if((!gotTwoSubsetFaces) && f1){
     285              :                         //      the edge is adjacent to only one subset-face.
     286              :                         //      it thus has to be a line
     287            0 :                                 LineSel.select(*EIter);
     288              :                         }
     289              :                 }
     290              :         }
     291              : 
     292            0 :         return true;
     293            0 : }
     294              : 
     295              : 
     296              : 
     297              : //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     298              : //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     299              : //      CollectInnerVertices
     300              : /// collects inner-vertices in a selector
     301            0 : static bool CollectInnerVertices(Grid& grid, VertexSelector& InnVrtSel, VertexSelector& SurfVrtSel)
     302              : {
     303              : //      iterate through all grid-vertices and select them with VertexSelector InnVrtSel
     304            0 :         for(VertexIterator VIter = grid.vertices_begin(); VIter != grid.vertices_end(); ++VIter)
     305              :         {
     306            0 :                 InnVrtSel.select(*VIter);
     307              :         }
     308              : 
     309              : //      iterate through all surface-vertices and deselect them in VertexSelector InnVrtSel, so that there only remain
     310              : //      the inner vertices
     311            0 :         for(VertexIterator VIter = SurfVrtSel.begin(); VIter != SurfVrtSel.end(); ++VIter)
     312              :         {
     313            0 :                 InnVrtSel.deselect(*VIter);
     314              :         }
     315              : 
     316            0 :         return true;
     317              : }
     318              : 
     319              : 
     320              : 
     321              : //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     322              : //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     323              : //      CollectSurfaceVertices
     324              : /// collects surface-vertices in a selector
     325            0 : static bool CollectSurfaceVertices(Grid& grid, const SubsetHandler& shFace,
     326              :                                                                         VertexSelector& SurfVrtSel)
     327              : {
     328              : //      iterate through all faces that are assigned to a subset and select them
     329            0 :         for(FaceIterator iter = grid.faces_begin(); iter != grid.faces_end(); ++iter)
     330              :         {
     331              :                 Face* f = *iter;
     332            0 :                 if(shFace.get_subset_index(f) != -1)
     333              :                 {
     334            0 :                         for(uint i = 0; i < f->num_vertices(); ++i)
     335            0 :                                 SurfVrtSel.select(f->vertex(i));
     336              :                 }
     337              :         }
     338              : 
     339            0 :         return true;
     340              : }
     341              : 
     342              : 
     343              : 
     344              : //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     345              : //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     346              : //      CollectAllVerticesForNG
     347              : /// collects all vertices in *.ng file order in a selector
     348            0 : static bool CollectAllVerticesForNG(Grid& grid, VertexSelector& NgVrtSel,
     349              :                                                         VertexSelector& SurfVrtSel, VertexSelector& InnVrtSel)
     350              : {
     351              : //      collecting all vertices for an *.ng file requires first to select the surface-vertices and then the inner ones
     352              : 
     353              : //      iterate through all surface-vertices and select them
     354            0 :         for(VertexIterator VIter = SurfVrtSel.begin(); VIter != SurfVrtSel.end(); ++VIter)
     355              :         {
     356            0 :                 NgVrtSel.select(*VIter);
     357              :         }
     358              : 
     359              : //      iterate through all inner vertices and select them
     360            0 :         for(VertexIterator VIter = InnVrtSel.begin(); VIter != InnVrtSel.end(); ++VIter)
     361              :         {
     362            0 :                 NgVrtSel.select(*VIter);
     363              :         }
     364              : 
     365            0 :         return true;
     366              : }
     367              : 
     368              : /**     THIS METHOD USES Grid::mark
     369              :  * This method is required since double-triangles have to be avoided
     370              :  * during triangulation of quadrilaterals which share two edges whith
     371              :  * another quadrilateral (this e.g. occurs in fracture geometries with neumann
     372              :  * boundaries).
     373              :  * Note that only faces in the same subset as q are regarded.
     374              :  */
     375            0 : static int GetFirstRegularVertex(Grid& grid, const SubsetHandler& sh, Face* q)
     376              : {
     377            0 :         grid.begin_marking();
     378              :         vector<Edge*> edges;
     379              :         vector<Face*> faces;
     380            0 :         int si = sh.get_subset_index(q);
     381              : 
     382              : //      check whether a connected face exists, which shares two sides with q.
     383              : //      iterate over all edges, collect associated faces and mark them.
     384              : //      if a face was already marked, then it is shared by at least
     385              : //      two sides. We will then immediately mark all associated vertices of
     386              : //      that face.
     387              :         CollectAssociated(edges, grid, q);
     388            0 :         for(size_t i_edge = 0; i_edge != edges.size(); ++i_edge){
     389            0 :                 CollectAssociated(faces, grid, edges[i_edge]);
     390              :         //      add all faces to nbrs. Check whether it is already contained.
     391            0 :                 for(size_t i_face = 0; i_face < faces.size(); ++i_face){
     392            0 :                         Face* f = faces[i_face];
     393            0 :                         if(sh.get_subset_index(f) != si)
     394            0 :                                 continue;
     395            0 :                         if(f == q)
     396            0 :                                 continue;
     397              : 
     398              :                 //      check whether the face was already encountered
     399            0 :                         if(grid.is_marked(f)){
     400              :                         //      it was already there!
     401              :                         //      mark all of its vertices
     402            0 :                                 for(size_t i_vrt = 0; i_vrt < f->num_vertices(); ++i_vrt)
     403            0 :                                         grid.mark(f->vertex(i_vrt));
     404              :                         }
     405              :                         else{
     406              :                         //      its there for the first time. mark it.
     407              :                                 grid.mark(f);
     408              :                         }
     409              :                 }
     410              :         }
     411              : 
     412              : //      find the first unmarked vertex in q
     413              :         int firstUnmarked = -1;
     414            0 :         for(int i_vrt = 0; i_vrt < (int)q->num_vertices(); ++i_vrt){
     415            0 :                 if(!grid.is_marked(q->vertex(i_vrt))){
     416              :                         firstUnmarked = i_vrt;
     417              :                         break;
     418              :                 }
     419              :         }
     420            0 :         grid.end_marking();
     421            0 :         return firstUnmarked;
     422            0 : }
     423              : //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     424              : //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     425              : //      WriteLGM
     426              : /// writes an *lgm file
     427            0 : static bool WriteLGM(Grid& grid,
     428              :                           const char* lgmFilename,
     429              :                           const char* problemName,
     430              :                           const char* lgmName,
     431              :                           int convex,
     432              :                           const SubsetHandler& shFaces,
     433              :                           const SubsetHandler& shVolumes,
     434              :                           EdgeSelector& LineSel,
     435              :                           VertexSelector& SurfVrtSel,
     436              :                           Grid::EdgeAttachmentAccessor<AInt>& aaLineIndex,
     437              :                           Grid::VertexAttachmentAccessor<AInt>& aaSurfVrtIndex,
     438              :                           Grid::VertexAttachmentAccessor<AVector3>& aaPos)
     439              : {
     440              : //      initialization
     441            0 :         ofstream out(lgmFilename);
     442            0 :         if(!out)
     443              :                 return false;
     444              :         out.setf(ios::scientific);
     445              :         out.precision(24);
     446              : 
     447              : //      write the header
     448              :         out << "#Domain-Info" << endl;
     449            0 :         out << "name = " << lgmName << endl;
     450            0 :         out << "problemname = " << problemName << endl;
     451            0 :         out << "convex = " << convex << endl << endl;
     452              : 
     453              : //      write the units
     454              :         out << "#Unit-Info" << endl;
     455            0 :         for(int i = 0; i < shVolumes.num_subsets(); ++i)
     456              :         {
     457              :         //      if the name is empty then write a standard name
     458              :         //      be cautious with the unit indices:      id = 0 is reserved for outer space ONLY by UG
     459            0 :                 if(shVolumes.subset_info(i).name.size() > 0)
     460            0 :                         out << "unit " << i + 1 << " " << shVolumes.subset_info(i).name << endl;
     461              :                 else {
     462            0 :                         out << "unit " << i + 1 << " " << "unit_" << i + 1 << endl;
     463              :                 }
     464              : 
     465              :         }
     466              :         out << endl;
     467              : 
     468              : //      write the lines
     469              :         out << "#Line-Info" << endl;
     470            0 :         for(EdgeIterator iter = LineSel.begin(); iter != LineSel.end(); ++iter)
     471              :         {
     472              :                 Edge* e = *iter;
     473            0 :                 out << "line " << aaLineIndex[e] << ": points: ";
     474            0 :                 out << aaSurfVrtIndex[e->vertex(0)] << " " << aaSurfVrtIndex[e->vertex(1)] << ";" << endl;
     475              :         }
     476              :         out << endl;
     477              : 
     478              : //      write the surfaces
     479              :         out << "#Surface-Info" << endl;
     480              :         {
     481              :         //      used to find vertices that belong to the i-th subset.
     482            0 :                 VertexSelector tmpSurfVrtSel(grid);
     483            0 :                 for(int i = 0; i < shFaces.num_subsets(); ++i)
     484              :                 {
     485            0 :                         tmpSurfVrtSel.clear();
     486              : 
     487              :                         //      identify left and right unit index of each surface
     488              :                         int tmpLeft, tmpRight;
     489            0 :                         if(!GetRightLeftUnitIndex(tmpRight, tmpLeft, grid, *shFaces.begin<Face>(i), shVolumes))
     490              :                         {
     491              :                                 LOG("- GetRightLeftUnitIndex failed during lgm-write.\n");
     492            0 :                                 LOG("- In surface " << i << " face 0\n");
     493              :                                 LOG("- This can happen due to volume-elements with bad orinentation.\n");
     494              :                                 LOG("- IMPLEMENT a geometrical method for fallback!\n");
     495              :                         }
     496              : 
     497            0 :                         out << "surface " << i << ": left=" << tmpLeft << "; right=" << tmpRight << "; points:";
     498              :                         for(ConstFaceIterator FIter = shFaces.begin<Face>(i);
     499            0 :                                 FIter != shFaces.end<Face>(i); ++FIter)
     500              :                         {
     501              :                                 Face* f = *FIter;
     502            0 :                                 for(uint j = 0; j < f->num_vertices(); ++j)
     503              :                                 {
     504            0 :                                         Vertex* v = f->vertex(j);
     505            0 :                                         if(!tmpSurfVrtSel.is_selected(v))
     506              :                                         {
     507              :                                                 tmpSurfVrtSel.select(v);
     508            0 :                                                 out << " " << aaSurfVrtIndex[v];
     509              :                                         }
     510              :                                 }
     511              :                         }
     512              : 
     513              :                 //      write lines
     514              :                 //      we have to avoid to write lines twice which lie inside a subset.
     515            0 :                         grid.begin_marking();
     516            0 :                         out << "; lines:";
     517              :                         {
     518              :                                 vector<Edge*> vEdges;
     519              :                                 for(ConstFaceIterator FIter = shFaces.begin<Face>(i);
     520            0 :                                         FIter != shFaces.end<Face>(i); ++FIter)
     521              :                                 {
     522            0 :                                         CollectEdges(vEdges, grid, *FIter);
     523            0 :                                         for(vector<Edge*>::iterator EIter = vEdges.begin();
     524            0 :                                                 EIter != vEdges.end(); ++EIter)
     525              :                                         {
     526            0 :                                                 Edge* e = *EIter;
     527            0 :                                                 if(LineSel.is_selected(e) && (!grid.is_marked(e)))
     528              :                                                 {
     529              :                                                         grid.mark(e);
     530            0 :                                                         out << " " << aaLineIndex[e];
     531              :                                                 }
     532              :                                         }
     533              :                                 }
     534            0 :                         }
     535            0 :                         grid.end_marking();
     536              :                         
     537              :                 //      write triangles
     538            0 :                         out << "; triangles:";
     539              :                         {
     540              :                                 vector<Vertex*> vVertices;
     541            0 :                                 for(ConstTriangleIterator TIter = shFaces.begin<Triangle>(i);
     542            0 :                                         TIter != shFaces.end<Triangle>(i); ++TIter)
     543              :                                 {
     544              :                                         Triangle* t = *TIter;
     545            0 :                                         for(uint j = 0; j < t->num_vertices(); ++j)
     546              :                                         {
     547            0 :                                                 out << " " << aaSurfVrtIndex[t->vertex(j)];
     548              :                                         }
     549            0 :                                         out << ";";
     550              :                                 }
     551            0 :                         }
     552              : 
     553              :                 //      write quadrilaterals as triangles
     554              :                 //      special care has to be taken since quadrliaterals can possibly
     555              :                 //      be connected at two sides. If one isn't careful one could thus produce
     556              :                 //      two identical triangles during triangulation.
     557              :                         {
     558              :                         //      we need Grid::mark to check which point is not contained in a neighbour
     559            0 :                                 for(ConstQuadrilateralIterator iter = shFaces.begin<Quadrilateral>(i);
     560            0 :                                         iter != shFaces.end<Quadrilateral>(i); ++iter)
     561              :                                 {
     562              :                                         Quadrilateral* q = *iter;
     563              : 
     564            0 :                                         int firstRegular = GetFirstRegularVertex(grid, shFaces, q);
     565              : 
     566              :                                 //      if we didn't find one, we can't split the face. Schedule a warning.
     567            0 :                                         if(firstRegular == -1){
     568              :                                                 UG_LOG("Can't split quadrilateral due to too many associated degenerated faces.\n");
     569              :                                         }
     570              :                                         else{
     571            0 :                                                 for(int j = firstRegular; j < firstRegular + 3; ++j)
     572            0 :                                                         out << " " << aaSurfVrtIndex[q->vertex(j%4)];
     573              : 
     574            0 :                                                 out << ";";
     575              : 
     576            0 :                                                 for(int j = firstRegular + 2; j < firstRegular + 5; ++j)
     577            0 :                                                         out << " " << aaSurfVrtIndex[q->vertex(j%4)];
     578              : 
     579            0 :                                                 out << ";";
     580              : 
     581              :                                         /*
     582              :                                                 for(uint j = 0; j < 3; ++j)
     583              :                                                         out << " " << aaSurfVrtIndex[q->vertex(j)];
     584              : 
     585              :                                                 out << ";";
     586              : 
     587              :                                                 for(uint j = 2; j < 5; ++j)
     588              :                                                         out << " " << aaSurfVrtIndex[q->vertex(j%4)];
     589              : 
     590              :                                                 out << ";";
     591              :                                         */
     592              :                                         }
     593              :                                 }
     594              :                         }
     595              :                 //      surface written...
     596              :                         out << endl;
     597              :                 }
     598              :         }
     599              : 
     600              : //      write the vertices position data
     601              :         out << endl << "#Point-Info" << endl;
     602            0 :         for(VertexIterator iter = SurfVrtSel.begin(); iter != SurfVrtSel.end(); ++iter)
     603              :         {
     604            0 :                 out << aaPos[*iter].x() << " " << aaPos[*iter].y() << " " << aaPos[*iter].z() << ";" << endl;
     605              :         }
     606              : 
     607              : //      close out file
     608            0 :         out.close();
     609              : 
     610              :         return true;
     611            0 : }
     612              : 
     613              : 
     614              : //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     615              : //      GetRightLeftUnitIndices
     616              : /// identifies the right and left unit index to a given surface
     617            0 : static bool GetRightLeftUnitIndex(int& rightIndex, int& leftIndex, Grid& grid, Face* face,
     618              :                                                                         const SubsetHandler& shVolume)
     619              : {
     620              : //      initialization
     621              :         vector<Volume*> vVolumes;
     622            0 :         FaceDescriptor fd;
     623              : 
     624            0 :         rightIndex = 0;
     625            0 :         leftIndex = 0;
     626              : 
     627              : //      collect all volumes which are adjacent to face into vector<Volume*> vVolumes
     628            0 :         CollectVolumes(vVolumes, grid, face);
     629              : //      iterate through all volumes adjacent to the face and identify left and right unit index
     630            0 :         for(uint j = 0; j < vVolumes.size(); ++j)
     631              :         {
     632            0 :                 Volume* v = vVolumes[j];
     633              : 
     634              :         //      find the face in the volume that matches the face
     635            0 :                 for(uint i = 0; i < v->num_faces(); ++i)
     636              :                 {
     637            0 :                         v->face_desc(i, fd);
     638            0 :                         if(CompareVertices(face, &fd))
     639              :                         {
     640              :                         //      we found a matching face.
     641              :                         //      check whether the orientation is the same as in the face or not
     642            0 :                                 int i0 = GetVertexIndex(face, fd.vertex(0));
     643            0 :                                 int i1 = GetVertexIndex(face, fd.vertex(1));
     644            0 :                                 if(i1 == (i0 + 1) % (int)fd.num_vertices())
     645              :                                 {
     646            0 :                                         if(rightIndex)
     647              :                                                 return false;
     648              :                                 //      the orientation is the same. the volume is on the right.
     649            0 :                                         rightIndex = shVolume.get_subset_index(v) + 1;
     650              :                                 }
     651              :                                 else
     652              :                                 {
     653            0 :                                         if(leftIndex)
     654              :                                                 return false;
     655              :                                 //      the orientation is not the same. the volume is on the left.
     656            0 :                                         leftIndex = shVolume.get_subset_index(v) + 1;
     657              :                                 }
     658              : 
     659              :                                 break;
     660              :                         }
     661              :                 }
     662              : 
     663              :         //      stop iterating through all adjacent volumes, if indices have already been assigned
     664            0 :                 if(leftIndex && rightIndex)
     665              :                         break;
     666              :         }
     667              : 
     668              :         return true;
     669            0 : }
     670              : 
     671              : //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     672              : //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     673              : //      WriteNG
     674              : /// writes an *ng file
     675            0 : static bool WriteNG(Grid& grid,
     676              :                                          const SubsetHandler& shFaces,
     677              :                                          const SubsetHandler& shVolumes,
     678              :                                          const char* ngFilename,
     679              :                                          VertexSelector& SurfVrtSel,
     680              :                                          VertexSelector& InnVrtSel,
     681              :                                          VertexSelector& NgVrtSel,
     682              :                                          EdgeSelector& LineSel,
     683              :                                          Grid::EdgeAttachmentAccessor<AInt>& aaLineIndex,
     684              :                                          Grid::VertexAttachmentAccessor<AInt>& aaInnVrtIndex,
     685              :                                          Grid::VertexAttachmentAccessor<AInt>& aaNgVrtIndex,
     686              :                                          Grid::FaceAttachmentAccessor<AInt>& aaFaceIndex,
     687              :                                          Grid::VertexAttachmentAccessor<AVector3>& aaPos)
     688              : {
     689              : //      initialization
     690              :         vector<Edge*> vEdges;
     691              :         vector<Face*> vFaces;
     692            0 :         vector<bool> faceFlags(shFaces.num_subsets());
     693              : 
     694            0 :         ofstream out(ngFilename);
     695            0 :         if(!out)
     696              :                 return false;
     697              :         out.setf(ios::scientific);
     698              :         out.precision(24);
     699              : //UG_LOG("INFO: WRITING DEBUG INFO TO .ng FILE!\n");//ONLY FOR DEBUG
     700              : //size_t nodeCount = 0;//ONLY FOR DEBUG
     701              : 
     702              : //      write the boundary nodes section
     703              :         out << "# boundary nodes" << endl;
     704            0 :         for(VertexIterator VIter = SurfVrtSel.begin(); VIter != SurfVrtSel.end(); ++VIter)
     705              :         {
     706              :                 Vertex* v = *VIter;
     707              : 
     708            0 :                 for(int i = 0; i < shFaces.num_subsets(); ++i)
     709              :                 {
     710              :                         faceFlags[i] = false;
     711              :                 }
     712              : 
     713              : //out << "# node-id: " << nodeCount << endl;//ONLY FOR DEBUG
     714              : //++nodeCount;//ONLY FOR DEBUG
     715              : 
     716              :         //      write the boundary-vertex position data
     717            0 :                 out << "B " << aaPos[v].x() << " " << aaPos[v].y() << " " << aaPos[v].z() << endl;
     718            0 :                 out << "     ";
     719              : 
     720              :         //      iterate through all lines
     721            0 :                 for(EdgeIterator EIter = LineSel.begin(); EIter != LineSel.end(); ++EIter)
     722              :                 {
     723              :                         Edge* e = *EIter;
     724              : 
     725              :                 //      check if the current boundary-vertex is also a line-vertex
     726            0 :                         if(GetVertexIndex(e, v) != -1)
     727              :                         {
     728              :                         //      write the line-index and line-vertex-index (corresponds to local position)
     729            0 :                                 out << " L " << aaLineIndex[e] << " " << GetVertexIndex(e, v);
     730              :                         }
     731              :                 }
     732              : 
     733              :         //      surface data
     734              :         //      iterate through all associated boundary-faces of vertex v
     735            0 :                 for(Grid::AssociatedFaceIterator FIter = grid.associated_faces_begin(v);
     736            0 :                         FIter != grid.associated_faces_end(v); ++FIter)
     737              :                 {
     738            0 :                         Face* f = *FIter;
     739              : 
     740              :                 //      write the surface section including its index and the triangle index of
     741              :                 //      ONE triangle-representative (per face-subset) associated to vertex v
     742            0 :                         if(shFaces.get_subset_index(f) != -1)
     743              :                         {
     744            0 :                                 if(faceFlags[shFaces.get_subset_index(f)] == false)
     745              :                                 {
     746              :                                 //      write local coordinates of vertex v on the triangle-representative
     747            0 :                                         int faceInd = aaFaceIndex[f];
     748            0 :                                         int vrtInd = GetVertexIndex(f, v);
     749              :                                         vector2 vCoord(0, 0);
     750            0 :                                         if(f->num_vertices() == 4){
     751            0 :                                                 int firstRegular = GetFirstRegularVertex(grid, shFaces, f);
     752            0 :                                                 if(firstRegular == -1){
     753              :                                                         UG_LOG("Can't split quadrilateral due to too many associated degenerated faces.\n");
     754              :                                                         continue;
     755              :                                                 }
     756            0 :                                                 vrtInd = (vrtInd + 4 - firstRegular)%4;
     757              :                                         }
     758              : 
     759            0 :                                         switch(vrtInd)
     760              :                                         {
     761            0 :                                                 case 0: vCoord = vector2(0, 0); break;
     762            0 :                                                 case 1: vCoord = vector2(1.0, 0); break;
     763            0 :                                                 case 2: vCoord = vector2(0, 1.0); break;
     764            0 :                                                 case 3: vCoord = vector2(1.0, 0); faceInd++; break; //index into the second sub-triangle
     765              :                                         }
     766              : 
     767            0 :                                         out << " S " << shFaces.get_subset_index(f) << " " << faceInd;
     768              :                                         out << " " << vCoord.x() << " " << vCoord.y();
     769              : 
     770              :                                         faceFlags[shFaces.get_subset_index(f)] = true;
     771              :                                 }
     772              :                         }
     773              :                 }
     774              : 
     775              :         out << ";" << endl;
     776              :         }
     777              : 
     778              : //      write inner nodes
     779              :         out << endl;
     780              :         out << "# inner nodes" << endl;
     781              : 
     782            0 :         if(InnVrtSel.num() > 0)
     783              :         {
     784              :         //      if there are inner vertices, iterate through all of them
     785            0 :                 for(VertexIterator VIter = InnVrtSel.begin(); VIter != InnVrtSel.end(); ++VIter)
     786              :                 {
     787              :                         Vertex* v = *VIter;
     788              : //out << "# node-id: " << nodeCount << endl;//ONLY FOR DEBUG
     789              : //++nodeCount;//ONLY FOR DEBUG
     790              :                 //      write the position data of the inner vertices
     791            0 :                         out << "I " << aaPos[v].x() << " " << aaPos[v].y() << " " << aaPos[v].z() << ";" << endl;
     792              :                 }
     793              :         }
     794              : 
     795              : //      write elements
     796              :         out << endl;
     797              :         out << "# elements" << endl;
     798              : 
     799            0 :         for(int i = 0; i < shVolumes.num_subsets(); ++i)
     800              :         {
     801              :         //      iterate through all volumes
     802              :                 for(ConstVolumeIterator VIter = shVolumes.begin<Volume>(i);
     803            0 :                         VIter != shVolumes.end<Volume>(i); ++VIter)
     804              :                 {
     805              :                         Volume* v = *VIter;
     806              : 
     807              :                 //      be cautious with the unit indices:      id = 0 is reserved for outer space ONLY by UG
     808            0 :                         out << " E " << i + 1;
     809              : 
     810              :                 //      iterate through all element vertices
     811            0 :                         for(uint j = 0; j < v->num_vertices(); ++j)
     812              :                         {
     813              :                         //      write volume-vertex-index (in *.ng file order)
     814            0 :                                 out << " " << aaNgVrtIndex[v->vertex(j)];
     815              :                         }
     816              : 
     817              :                 //      collect all associated boundary-faces of volume v and write their *.ng file indices
     818              :                         vFaces.clear();
     819            0 :                         CollectFaces(vFaces, grid, v);
     820            0 :                         for(vector<Face*>::iterator iter = vFaces.begin(); iter != vFaces.end(); ++iter)
     821              :                         {
     822            0 :                                 Face* f = *iter;
     823            0 :                                 if(shFaces.get_subset_index(f) != -1)
     824              :                                 {
     825            0 :                                         out << " F " << aaNgVrtIndex[f->vertex(0)];
     826            0 :                                         for(uint j = 1; j < f->num_vertices(); ++j)
     827            0 :                                                 out << " " << aaNgVrtIndex[f->vertex(j)];
     828              :                                 }
     829              :                         }
     830              : 
     831              :                         out << ";" << endl;
     832              :                 }
     833              :         }
     834              : 
     835            0 :         out.close();
     836              :         return true;
     837            0 : }
     838              : 
     839              : 
     840              : ////////////////////////////////////////////////////////////////////////////////////////////////
     841              : ////////////////////////////////////////////////////////////////////////////////////////////////
     842              : //      2D EXPORT
     843              : ////////////////////////////////////////////////////////////////////////////////////////////////
     844              : //      ExportMeshToUG_2D and helper functions
     845            0 : static bool FaceIsOnRightSide(Face* f, Edge* e)
     846              : {
     847              : //  If the vertices in e are in the same order as the vertices in f,
     848              : //  then f is on the left side of e (since vertices are specified counter-clockwise).
     849            0 :     size_t ind1 = GetVertexIndex(f, e->vertex(0));
     850            0 :     size_t ind2 = GetVertexIndex(f, e->vertex(1));
     851              : 
     852            0 :     if(ind2 == (ind1 + 1) % f->num_vertices())
     853            0 :         return false;
     854              : 
     855              :     return true;
     856              : }
     857              : 
     858            0 : bool ExportGridToUG_2D(Grid& grid, const char* fileName, const char* lgmName,
     859              :                                            const char* problemName, int convex,
     860              :                                            SubsetHandler* psh)
     861              : {
     862            0 :         string lgmFileName = fileName;
     863            0 :         lgmFileName.append(".lgm");
     864              : 
     865            0 :         string ngFileName = fileName;
     866            0 :         ngFileName.append(".ng");
     867              : 
     868              : //      open the file
     869            0 :         ofstream out(lgmFileName.c_str());
     870            0 :         if(!out)
     871              :         {
     872              :                 LOG("Failure in ExportGridToUG_2D: couldn't open " << lgmFileName << " for write" << endl);
     873              :                 return false;
     874              :         }
     875              : 
     876              :         out.precision(12);
     877              : 
     878              : //      vectors are used to collect associated elements
     879              :         vector<Face*> vFaces;
     880              :         
     881              : //      Position accessor
     882              :         Grid::VertexAttachmentAccessor<APosition> aaPos(grid, aPosition);
     883              : 
     884              : //      initialise all indices with -1
     885              :         AInt aInt;
     886              :         grid.attach_to_vertices(aInt);
     887              :         Grid::VertexAttachmentAccessor<AInt> aaInt(grid, aInt);
     888              :         SetAttachmentValues(aaInt, grid.vertices_begin(), grid.vertices_end(), -1);
     889              : 
     890              : //      write the header
     891              :         out << "#Domain-Info" << endl;
     892            0 :         out << "name = " << lgmName << endl;
     893            0 :         out << "problemname = " << problemName << endl;
     894            0 :         out << "convex = " << convex << endl << endl;
     895              : 
     896              :         bool bUnitsSupplied;
     897              :         out << "#Unit-Info" << endl;
     898              : 
     899            0 :         if(psh)
     900              :         {
     901              :         //      there are units
     902              :                 bUnitsSupplied = true;
     903              : 
     904              :         //      write the units
     905              :                 bool bGotEmpty = false;// helps us to print a warning if required.
     906            0 :                 for(int i = 0; i < psh->num_subsets(); i++)
     907              :                 {
     908              :                 //      units that do not contain faces are ignored.
     909            0 :                         if(psh->num<Face>(i) == 0){
     910              :                                 bGotEmpty = true;
     911            0 :                                 continue;
     912              :                         }
     913              : 
     914            0 :                         if(bGotEmpty){
     915              :                         //      schedule a warning
     916              :                                 UG_LOG("WARNING in ExportGridToUG_2D: Empty units between filled ones.\n");
     917              :                         }
     918              : 
     919            0 :                         SubsetInfo& sh = psh->subset_info(i);
     920              :                         string unitName = sh.name;
     921            0 :                         size_t k = sh.name.find(".");
     922            0 :                         if(k != string::npos)
     923            0 :                                 unitName.erase(k, unitName.size() - k);
     924            0 :                         if(unitName.size() > 0)
     925            0 :                                 out << "unit " << i+1 << " " << unitName.c_str() << endl;
     926              :                         else
     927            0 :                                 out << "unit " << i+1 << " unit_" << i+1 << endl;
     928              :                 }
     929              :         }
     930              :         else
     931              :         {
     932              :         //      no subsets are attached. This means we'll have to create one unit for all the triangles
     933              :                 bUnitsSupplied = false;
     934              :                 out << "unit 1 unit_1" << endl;
     935              :         }
     936              :         out << endl;
     937              : 
     938              : //      determine the vertices that go into the lgm file and assign indices to them.
     939              : //      This are all vertices wich lie on a border edge or wich are connected to triangles or quads of different subsets.
     940              :         {
     941              :                 int pointIndexCounter = 0;
     942              : 
     943              :                 for(VertexIterator iter = grid.vertices_begin();
     944            0 :                         iter != grid.vertices_end(); iter++)
     945              :                 {
     946            0 :                         if(IsBoundaryVertex2D(grid, *iter))
     947              :                         {
     948            0 :                 aaInt[*iter] = pointIndexCounter++;
     949              :                         }
     950            0 :                         else if(bUnitsSupplied)
     951              :                         {
     952              :                         //      check if the point is connected to triangles and quads of different subsets
     953              :                 int subsetIndex = -1;
     954              :                                 
     955            0 :                                 CollectFaces(vFaces, grid, *iter);
     956              :                                 
     957            0 :                                 if(!vFaces.empty())
     958            0 :                                         subsetIndex = psh->get_subset_index(vFaces[0]);
     959              :                                 
     960            0 :                                 for(size_t i = 1; i < vFaces.size(); ++i){
     961            0 :                                         if(psh->get_subset_index(vFaces[i]) != subsetIndex){
     962            0 :                                                 aaInt[*iter] = pointIndexCounter++;
     963            0 :                                                 break;
     964              :                                         }
     965              :                                 }
     966              :                         }
     967              :                 }
     968              :         }
     969              : 
     970              : //      write the lines
     971              :         out << "#Line-Info" << endl;
     972              : //      we attach an int value to the edges wich describes their line-index. -1 if the edge is not a line
     973              : //      initialise line indices with -1
     974              :         grid.attach_to_edges(aInt);
     975              :         Grid::EdgeAttachmentAccessor<AInt> aaLineInt(grid, aInt);
     976              :         SetAttachmentValues(aaLineInt, grid.edges_begin(), grid.edges_end(), -1);
     977              : 
     978              :         int numLines = 0;
     979              :         vector<vector<Vertex*> > lines;
     980              :         {
     981              :         //      each edge which is connected to two different subsets or which is
     982              :         //      a boundary edge has to be written as a line
     983            0 :                 if(bUnitsSupplied)
     984              :                 {
     985              : 
     986              :                 //      write the edge-subsets as lines
     987            0 :                         for(int i = 0; i < psh->num_subsets(); ++i)
     988              :                         {
     989              :                         //      at this point we assume that lines are oriented
     990            0 :                                 if(!psh->empty<Edge>(i)){
     991              :                                 //      we have to follow the polygonal chain in subset i.
     992              :                                 //      We assume that the chain is regular
     993              :                                 //      create a callback for this subset, since we use it several times
     994            0 :                                         IsInSubset cbIsInSubset(*psh, i);
     995              :                                         std::pair<Vertex*, Edge*> curSec =
     996            0 :                                                 GetFirstSectionOfPolyChain(grid, psh->begin<Edge>(i),
     997            0 :                                                                                                         psh->end<Edge>(i),
     998              :                                                                                                         cbIsInSubset);
     999              : 
    1000            0 :                                         if(curSec.first == NULL)
    1001            0 :                                                 continue;
    1002              : 
    1003              :                                 //      find left and right unit
    1004              :                                 //      curSec.second contains the first edge of the polychain.
    1005            0 :                                         CollectFaces(vFaces, grid, curSec.second);
    1006              : 
    1007            0 :                                         if(vFaces.size() < 1)
    1008            0 :                                                 continue;
    1009              : 
    1010              :                                 //      we now have to check which subset lies on which side of the line
    1011            0 :                                         int subLeft = psh->get_subset_index(vFaces[0]) + 1;
    1012              :                                         int subRight = 0;
    1013            0 :                                         if(vFaces.size() > 1)
    1014            0 :                                                 subRight = psh->get_subset_index(vFaces[1]) + 1;
    1015              :                                         
    1016            0 :                                         if(FaceIsOnRightSide(vFaces[0], curSec.second))
    1017              :                                                 swap(subLeft, subRight);
    1018              : 
    1019              :                                 //      since the edge and the first line segment can be flipped,
    1020              :                                 //      we eventually have to swap again
    1021            0 :                                         if(curSec.first != curSec.second->vertex(0))
    1022              :                                                 swap(subLeft, subRight);
    1023              : 
    1024            0 :                                         out << "line " << numLines << ": left="<< subLeft
    1025            0 :                                                 << "; right=" << subRight << "; points:";
    1026              :                                                         
    1027              :                                         size_t numEdgesInLine = 0;
    1028            0 :                                         lines.push_back(vector<Vertex*>());
    1029              :                                         vector<Vertex*>& curLine = lines.back();
    1030              : 
    1031            0 :                                         while(curSec.first)
    1032              :                                         {
    1033            0 :                                                 Vertex* curVrt = curSec.first;
    1034              :                                                 Edge* curEdge = curSec.second;
    1035              :                                                 
    1036              :                                         //      write the vertex index
    1037            0 :                                                 if(aaInt[curVrt] == -1){
    1038            0 :                                                         throw(UGError("RegularEdge subsets have not been assigned correctly."));
    1039              :                                                 }
    1040              :                                                 
    1041            0 :                                                 if(aaLineInt[curEdge] != -1){
    1042            0 :                                                         throw(UGError("Implementation error: One edge is in different lines."));
    1043              :                                                 }
    1044              :                                                 
    1045            0 :                                                 aaLineInt[curEdge] = numLines;
    1046            0 :                                                 ++numEdgesInLine;
    1047              :                                                 
    1048            0 :                                                 out << " " << aaInt[curVrt];
    1049            0 :                                                 curLine.push_back(curVrt);
    1050              :                                                 
    1051              :                                                 std::pair<Vertex*, Edge*> nextSec =
    1052            0 :                                                         GetNextSectionOfPolyChain(grid, curSec, cbIsInSubset);
    1053              : 
    1054              :                                         //      check whether the next section is still valid.
    1055              :                                         //      if not, write the last vertex and exit.
    1056            0 :                                                 if(!nextSec.first){
    1057            0 :                                                         out << " " << aaInt[GetConnectedVertex(curEdge, curVrt)];
    1058            0 :                                                         curLine.push_back(GetConnectedVertex(curEdge, curVrt));
    1059            0 :                                                         break;
    1060              :                                                 }
    1061            0 :                                                 else if(aaLineInt[nextSec.second] != -1){
    1062              :                                                 //      the edge has already been considered
    1063            0 :                                                         out << " " << aaInt[nextSec.first];
    1064            0 :                                                         curLine.push_back(nextSec.first);
    1065              :                                                         break;
    1066              :                                                 }
    1067              :                                                 
    1068              :                                                 curSec = nextSec;
    1069              :                                         }
    1070              :                                         out << ";" << endl;
    1071            0 :                                         ++numLines;
    1072              :                                         
    1073              :                                 //      make sure that all edges in the subset have been written to the line
    1074            0 :                                         if(numEdgesInLine != psh->num<Edge>(i)){
    1075            0 :                                                 stringstream ss;
    1076              :                                                 ss  << "Couldn't write all edges of subset " << i << " to a line. "
    1077              :                                                         << "This can happen if the subset is not a regular polychain. "
    1078            0 :                                                         << "It is either separated into different parts or irregular (contains junctions).";
    1079              :                                                                           
    1080            0 :                                                 throw(UGError(ss.str().c_str()));
    1081            0 :                                         }
    1082              :                                 }
    1083              :                         }
    1084              : 
    1085              : /*
    1086              :                         for(EdgeIterator iter = grid.edges_begin(); iter != grid.edges_end(); iter++)
    1087              :                         {
    1088              :                                 Edge* e = *iter;
    1089              :                         //      check for adjacent faces of different subset indices
    1090              :                                 CollectFaces(vFaces, grid, e);
    1091              :                                 
    1092              :                                 if(vFaces.size() == 2)
    1093              :                                 {
    1094              :                                         if(psh->get_subset_index(vFaces[0]) != psh->get_subset_index(vFaces[1]))
    1095              :                                         {
    1096              :                                         //      e is a line.
    1097              :                                         //      assign the index
    1098              :                                                 aaLineInt[e] = numLines;
    1099              : 
    1100              :                                         //      write the line
    1101              :                                                 int subLeft = psh->get_subset_index(vFaces[0]) + 1;
    1102              :                                                 int subRight = psh->get_subset_index(vFaces[1]) + 1;
    1103              :                                                 if(!FaceIsOnRightSide(vFaces[0], e))
    1104              :                                                         swap(subLeft, subRight);
    1105              : 
    1106              :                                                 out << "line " << numLines << ": left="<< subLeft
    1107              :                                                         << "; right=" << subRight << "; points: "
    1108              :                                                         << aaInt[e->vertex(0)] << " " << aaInt[e->vertex(1)] << ";" << endl;
    1109              : 
    1110              :                                                 numLines++;
    1111              : 
    1112              :                     //  endvertices of lines have to be marked as boundary-vertices
    1113              :                                                 assert((aaInt[e->vertex(0)] != -1) && "This point should be marked as boundary vertex!");
    1114              :                                                 assert((aaInt[e->vertex(1)] != -1) && "This point should be marked as boundary vertex!");
    1115              :                                         }
    1116              :                                 }
    1117              :                         }
    1118              : */
    1119              :                 }
    1120              :                 else{
    1121              :                 //      check for boundary lines
    1122            0 :                         for(EdgeIterator iter = grid.edges_begin(); iter != grid.edges_end(); iter++)
    1123              :                         {
    1124              :                                 Edge* e = *iter;
    1125            0 :                                 CollectFaces(vFaces, grid, e);
    1126              :                         //      check if it is a boundary edge
    1127            0 :                                 if(vFaces.size() == 1)
    1128              :                                 {
    1129              :                                 //      assign the index
    1130            0 :                                         aaLineInt[e] = numLines;
    1131              : 
    1132              :                                         int unitIndex = 1;
    1133              :                                         if(bUnitsSupplied)
    1134              :                                                 unitIndex = psh->get_subset_index(vFaces[0]) + 1;
    1135              : 
    1136              :                                         int subLeft = 0;
    1137              :                                         int subRight = 0;
    1138            0 :                                         if(FaceIsOnRightSide(vFaces[0], e))
    1139              :                                                 subRight = unitIndex;
    1140              :                                         else
    1141              :                                                 subLeft = unitIndex;
    1142              : 
    1143            0 :                                         out << "line " << numLines << ": left="<< subLeft
    1144            0 :                                                 << "; right=" << subRight << "; points: "
    1145            0 :                                                 << aaInt[e->vertex(0)] << " " << aaInt[e->vertex(1)] << ";" << endl;
    1146              : 
    1147            0 :                                         numLines++;
    1148              : 
    1149              :                                 //  endvertices of lines have to be marked as boundary-vertices
    1150              :                                         assert((aaInt[e->vertex(0)] != -1) && "This point should be marked as boundary vertex!");
    1151              :                                         assert((aaInt[e->vertex(1)] != -1) && "This point should be marked as boundary vertex!");
    1152              :                                 }
    1153              :                         }
    1154              :                 }
    1155              :         }
    1156              : 
    1157              : //      write the vertices position data
    1158              :         {
    1159              :                 out << endl << "#Point-Info" << endl;
    1160            0 :                 for(VertexIterator iter = grid.vertices_begin(); iter != grid.vertices_end(); iter++)
    1161              :                 {
    1162              :                 //      only write the point if it lies on a line
    1163            0 :                         if(aaInt[*iter] != -1)
    1164            0 :                                 out << aaPos[*iter].x() << " " << aaPos[*iter].y() << ";" << endl;
    1165              :                 }
    1166              :         }
    1167              : 
    1168              : //      lgm-write done
    1169            0 :         out.close();
    1170              : 
    1171              : //      now we have to write the ng file
    1172              : //      open the file
    1173            0 :         out.open(ngFileName.c_str());
    1174              : 
    1175              : //      enable scientific number format�
    1176              :         //out.setf(ios::scientific);
    1177              : 
    1178            0 :         if(!out)
    1179              :         {
    1180              :                 LOG("Failure in ExportGridToUG_2D: couldn't open " << ngFileName << " for write" << endl);
    1181              :                 grid.detach_from_vertices(aInt);
    1182              :                 grid.detach_from_edges(aInt);
    1183              :                 return false;
    1184              :         }
    1185              : 
    1186              : //      write the nodes
    1187              :         {
    1188              :                 int numNGVertexs = 0;
    1189              :         //      first we'll write the boundary vertices
    1190              :                 {
    1191            0 :                         for(VertexIterator iter = grid.vertices_begin(); iter != grid.vertices_end(); iter++)
    1192              :                         {
    1193              :                                 Vertex* p = *iter;
    1194              :                         //      check if p is a boundary node
    1195            0 :                                 if(aaInt[p] != -1)
    1196              :                                 {
    1197              :                                 //      it is. write it to the file
    1198            0 :                                         out << "B ";
    1199              :                                 //      position:
    1200            0 :                                         out << aaPos[p].x() << " " << aaPos[p].y();
    1201              :                                 //      connected lines
    1202              :                                 //      make sure that each is only used once
    1203              :                                         set<int> encounteredLines;
    1204            0 :                                         for(Grid::AssociatedEdgeIterator eIter = grid.associated_edges_begin(p);
    1205            0 :                                                 eIter != grid.associated_edges_end(p); ++eIter)
    1206              :                                         {
    1207            0 :                                                 if(aaLineInt[(*eIter)] != -1){
    1208              :                                                 //      get the local coordinate of the vertex on its associated line
    1209            0 :                                                         int lineIndex = aaLineInt[(*eIter)];
    1210            0 :                                                         if(encounteredLines.count(lineIndex) > 0)
    1211            0 :                                                                 continue;// the line was already encountered.
    1212              : 
    1213            0 :                                                         vector<Vertex*>& curLine = lines.at(lineIndex);
    1214              :                                                         assert(curLine.size() > 1 && "A line has to contain at least 2 vertices.");
    1215              :                                                         int localCoord = -1;
    1216            0 :                                                         for(size_t i = 0; i < curLine.size(); ++i){
    1217            0 :                                                                 if(curLine[i] == p)
    1218            0 :                                                                         localCoord = i;
    1219              :                                                         }
    1220            0 :                                                         if(localCoord >= 0){
    1221            0 :                                                                 out << " L " << lineIndex << " " << localCoord;
    1222              :                                                                 encounteredLines.insert(lineIndex);
    1223              :                                                         }
    1224              :                                                         else{
    1225            0 :                                                                 UG_LOG("WARNING in ExportGridToUG_2D: "
    1226              :                                                                                 << "Couldn't find local coordinate of boundary vertex at"
    1227              :                                                                                 << aaPos[p] << endl);
    1228              :                                                         }
    1229              :                                                 }
    1230              :                                         }
    1231              :                                 //      done
    1232              :                                         out << ";" << endl;
    1233            0 :                                         numNGVertexs++;
    1234              :                                 }
    1235              :                         }
    1236              :                 }
    1237              : 
    1238              :         //      write the inner vertices
    1239              :                 {
    1240            0 :                         for(VertexIterator iter = grid.vertices_begin(); iter != grid.vertices_end(); iter++)
    1241              :                         {
    1242              :                                 Vertex* p = *iter;
    1243            0 :                                 if(aaInt[p] == -1)
    1244              :                                 {
    1245              :                                 //      write the point
    1246            0 :                                         out << "I " << aaPos[p].x() << " " << aaPos[p].y() << ";" << endl;
    1247            0 :                                         aaInt[p] = numNGVertexs++;
    1248              :                                 }
    1249              :                         }
    1250              :                 }
    1251              :         }
    1252              : 
    1253              : //      write the elements
    1254              :         {
    1255              :         //      loop through all the triangles
    1256            0 :                 for(FaceIterator iter = grid.faces_begin(); iter != grid.faces_end(); iter++)
    1257              :                 {
    1258              :                         Face* f = *iter;
    1259              : 
    1260              :                         int unitIndex = 1;
    1261            0 :                         if(bUnitsSupplied)
    1262            0 :                                 unitIndex = psh->get_subset_index(f) + 1;
    1263              : 
    1264            0 :                         out << "E " << unitIndex;
    1265            0 :                         for(size_t i = 0; i < f->num_vertices(); ++i)
    1266            0 :                                 out << " " << aaInt[f->vertex(i)];
    1267              : 
    1268              :                 //      check if one of its edges is a line.
    1269            0 :                         for(size_t i = 0; i < f->num_edges(); ++i)
    1270              :                         {
    1271            0 :                                 Edge* e = grid.get_edge(f, i);
    1272            0 :                                 if(aaLineInt[e] != -1)
    1273              :                                 {
    1274            0 :                                         out << " S " << aaInt[e->vertex(0)] << " " << aaInt[e->vertex(1)];
    1275              :                                 }
    1276              :                         }
    1277              :                 //      done
    1278              :                         out << ";" << endl;
    1279              :                 }
    1280              :         }
    1281              : 
    1282              : //      write complete
    1283            0 :         out.close();
    1284              : 
    1285              : //      clean up
    1286              :         grid.detach_from_vertices(aInt);
    1287              :         grid.detach_from_edges(aInt);
    1288              : 
    1289              :         return true;
    1290            0 : }
    1291              : 
    1292              : }//     end of namespace
        

Generated by: LCOV version 2.0-1