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

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2009-2015:  G-CSC, Goethe University Frankfurt
       3              :  * Author: Sebastian Reiter
       4              :  * 
       5              :  * This file is part of UG4.
       6              :  * 
       7              :  * UG4 is free software: you can redistribute it and/or modify it under the
       8              :  * terms of the GNU Lesser General Public License version 3 (as published by the
       9              :  * Free Software Foundation) with the following additional attribution
      10              :  * requirements (according to LGPL/GPL v3 §7):
      11              :  * 
      12              :  * (1) The following notice must be displayed in the Appropriate Legal Notices
      13              :  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
      14              :  * 
      15              :  * (2) The following notice must be displayed at a prominent place in the
      16              :  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
      17              :  * 
      18              :  * (3) The following bibliography is recommended for citation and must be
      19              :  * preserved in all covered files:
      20              :  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
      21              :  *   parallel geometric multigrid solver on hierarchically distributed grids.
      22              :  *   Computing and visualization in science 16, 4 (2013), 151-164"
      23              :  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
      24              :  *   flexible software system for simulating pde based models on high performance
      25              :  *   computers. Computing and visualization in science 16, 4 (2013), 165-179"
      26              :  * 
      27              :  * This program is distributed in the hope that it will be useful,
      28              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      29              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      30              :  * GNU Lesser General Public License for more details.
      31              :  */
      32              : 
      33              : #include <vector>
      34              : #include <stack>
      35              : #include <queue>
      36              : #include <map>
      37              : 
      38              : #include "subset_util.h"
      39              : #include "geom_obj_util/geom_obj_util.h"
      40              : #include "polychain_util.h"
      41              : #include "orientation_util.h"
      42              : #include "subset_color_util.h"
      43              : 
      44              : using namespace std;
      45              : 
      46              : namespace ug
      47              : {
      48              : 
      49              : ////////////////////////////////////////////////////////////////////////
      50            0 : int GetFirstFreeSubset(const ISubsetHandler& sh)
      51              : {
      52            0 :         for(int i = 0; i < sh.num_subsets(); ++i){
      53            0 :                 if(!(sh.contains_vertices(i) || sh.contains_edges(i)
      54            0 :                          || sh.contains_faces(i) || sh.contains_volumes(i)))
      55              :                  {
      56            0 :                         return i;
      57              :                  }
      58              :         }
      59              : 
      60              :         return sh.num_subsets();
      61              : }
      62              : 
      63              : 
      64              : ////////////////////////////////////////////////////////////////////////
      65              : //      EraseEmptySubsets
      66              : ///     Erases all subsets which do not contain any geometric objects
      67            0 : void EraseEmptySubsets(ISubsetHandler& sh)
      68              : {
      69              :         int si = 0;
      70            0 :         while(si < sh.num_subsets()){
      71            0 :                 if(!(   sh.contains_vertices(si)
      72            0 :                         ||      sh.contains_edges(si)
      73            0 :                         ||      sh.contains_faces(si)
      74            0 :                         ||      sh.contains_volumes(si)))
      75              :                 {
      76              :                 //      the subset is empty
      77            0 :                         sh.erase_subset(si);
      78              :                 }
      79              :                 else
      80            0 :                         ++si;
      81              :         }
      82            0 : }
      83              : 
      84              : ////////////////////////////////////////////////////////////////////////
      85              : //      AssignGridToSubset
      86            0 : void AssignGridToSubset(Grid& g, ISubsetHandler& sh, int subsetInd)
      87              : {
      88              :         UG_ASSERT(&g == sh.grid(), "Specified subset-handler has to operate on the specified grid!");
      89              : 
      90              :         sh.assign_subset(g.begin<Vertex>(), g.end<Vertex>(), subsetInd);
      91              :         sh.assign_subset(g.begin<Edge>(), g.end<Edge>(), subsetInd);
      92              :         sh.assign_subset(g.begin<Face>(), g.end<Face>(), subsetInd);
      93              :         sh.assign_subset(g.begin<Volume>(), g.end<Volume>(), subsetInd);
      94            0 : }
      95              : 
      96              : ////////////////////////////////////////////////////////////////////////
      97              : //      AssignSelectionToSubset
      98            0 : void AssignSelectionToSubset(ISelector& sel, ISubsetHandler& sh, int subsetInd)
      99              : {
     100              :         UG_ASSERT(sel.grid() == sh.grid(), "Specified selector and subset-handler "
     101              :                                                                            "have to operate on the same grid!");
     102              : 
     103            0 :         GridObjectCollection selGoc = sel.get_grid_objects();
     104              : 
     105            0 :         for(size_t i = 0; i < selGoc.num_levels(); ++i){
     106              :                 sh.assign_subset(selGoc.begin<Vertex>(i),
     107              :                                                  selGoc.end<Vertex>(i), subsetInd);
     108              :                 sh.assign_subset(selGoc.begin<Edge>(i),
     109              :                                                  selGoc.end<Edge>(i), subsetInd);
     110              :                 sh.assign_subset(selGoc.begin<Face>(i),
     111              :                                                  selGoc.end<Face>(i), subsetInd);
     112              :                 sh.assign_subset(selGoc.begin<Volume>(i),
     113              :                                                  selGoc.end<Volume>(i), subsetInd);
     114              :         }
     115            0 : }
     116              : 
     117              : ////////////////////////////////////////////////////////////////////////
     118              : //      AssignInterfaceEdgesToSubsets
     119            0 : void AssignFaceInterfaceEdgesToSubsets(Grid& grid, SubsetHandler& sh)
     120              : {
     121              : //TODO: This algorithm can be improved.
     122              : //      In the moment it runs with arbitrarily O(numSubs^2*averageNumFacesPerSub)
     123              : 
     124              : //      get the first free edge-subset
     125            0 :         int edgeSubsetIndex = GetMaxSubsetIndex<Edge>(sh) + 1;
     126              : 
     127              : //      use this vector to collect adjacent faces
     128              :         vector<Edge*> vEdges;
     129              :         vector<Face*> vFaces;
     130              : 
     131              : //      iterate through all subsets
     132            0 :         for(int j = -1; j < sh.num_subsets(); ++j)
     133              :         {
     134              :         //      find interface-edges to the other subsets.
     135            0 :                 for(int i = j + 1; i < sh.num_subsets(); ++i)
     136              :                 {
     137              :                 //      iterate through all faces of subset i and check
     138              :                 //      whether some edges are adjacent to subset j.
     139              :                         for(FaceIterator iter = sh.begin<Face>(i);
     140            0 :                                 iter != sh.end<Face>(i); ++iter)
     141              :                         {
     142              :                                 Face* f = *iter;
     143            0 :                                 CollectEdges(vEdges, grid, f);
     144            0 :                                 for(uint k = 0; k < vEdges.size(); ++k)
     145              :                                 {
     146            0 :                                         Edge* e = vEdges[k];
     147              : 
     148            0 :                                         if(sh.get_subset_index(e) == -1)
     149              :                                         {
     150            0 :                                                 CollectFaces(vFaces, grid, e);
     151              : 
     152            0 :                                                 if(vFaces.size() == 1)
     153            0 :                                                         sh.assign_subset(e, edgeSubsetIndex);
     154              :                                                 else
     155              :                                                 {
     156            0 :                                                         for(uint l = 0; l < vFaces.size(); ++l)
     157              :                                                         {
     158            0 :                                                                 if(sh.get_subset_index(vFaces[l]) == j)
     159              :                                                                 {
     160            0 :                                                                         sh.assign_subset(e, edgeSubsetIndex);
     161              :                                                                         break;
     162              :                                                                 }
     163              :                                                         }
     164              :                                                 }
     165              :                                         }
     166              :                                 }
     167              :                         }
     168              : 
     169              :                 //      if we assigned edges, we will proceed with the next subset
     170            0 :                         if(edgeSubsetIndex < (int)sh.num_subsets())
     171            0 :                                 if(sh.num_elements<Edge>(edgeSubsetIndex) > 0)
     172            0 :                                         edgeSubsetIndex++;
     173              :                 }
     174              :         }
     175            0 : }
     176              : 
     177              : ////////////////////////////////////////////////////////////////////////
     178              : // AssignVolumeInterfaceFacesToSubsets
     179            0 : void AssignVolumeInterfaceFacesToSubsets(Grid& grid, SubsetHandler& sh)
     180              : {
     181              : //TODO: This algorithm can be improved.
     182              : //      In the moment it runs with arbitrarily O(numSubs^2*averageNumVolumesPerSub)
     183              : 
     184              : //      get the first free face-subset
     185            0 :         int faceSubsetIndex = GetMaxSubsetIndex<Face>(sh) + 1;
     186              : 
     187              : //      use this vector to collect adjacent faces and volumes
     188              :         vector<Face*> vFaces;
     189              :         vector<Volume*> vVolumes;
     190              : 
     191              : //      iterate through all subsets
     192            0 :         for(int j = -1; j < (int)sh.num_subsets(); ++j)
     193              :         {
     194              :         //      find interface-edges to the other subsets.
     195            0 :                 for(int i = j + 1; i < (int)sh.num_subsets(); ++i)
     196              :                 {
     197              :                 //      iterate through all volumes of subset i and check
     198              :                 //      whether some faces are adjacent to subset j.
     199              :                         for(VolumeIterator iter = sh.begin<Volume>(i);
     200            0 :                                 iter != sh.end<Volume>(i); ++iter)
     201              :                         {
     202              :                                 Volume* v = *iter;
     203            0 :                                 CollectFaces(vFaces, grid, v);
     204            0 :                                 for(uint k = 0; k < vFaces.size(); ++k)
     205              :                                 {
     206            0 :                                         Face* f = vFaces[k];
     207              : 
     208            0 :                                         if(sh.get_subset_index(f) == -1)
     209              :                                         {
     210            0 :                                                 CollectVolumes(vVolumes, grid, f);
     211              : 
     212            0 :                                                 if(vVolumes.size() == 1)
     213            0 :                                                         sh.assign_subset(f, faceSubsetIndex);
     214              :                                                 else
     215              :                                                 {
     216            0 :                                                         for(uint l = 0; l < vVolumes.size(); ++l)
     217              :                                                         {
     218            0 :                                                                 if(sh.get_subset_index(vVolumes[l]) == j)
     219              :                                                                 {
     220            0 :                                                                         sh.assign_subset(f, faceSubsetIndex);
     221              :                                                                         break;
     222              :                                                                 }
     223              :                                                         }
     224              :                                                 }
     225              :                                         }
     226              :                                 }
     227              :                         }
     228              : 
     229              :                 //      if we assigned edges, we will proceed with the next subset
     230            0 :                         if(faceSubsetIndex < (int)sh.num_subsets())
     231            0 :                                 if(sh.num_elements<Face>(faceSubsetIndex) > 0)
     232            0 :                                         faceSubsetIndex++;
     233              :                 }
     234              :         }
     235            0 : }
     236              : 
     237              : 
     238              : ////////////////////////////////////////////////////////////////////////
     239              : /**     Helper method that copies subset-indices based on the subset-dimension
     240              :  * property of each element. Subsets are only assigned to previously unassigned elements.*/
     241              : template <class TIterator>
     242            0 : static void CopySubsetFromHigherDimNbr(
     243              :                                 ISubsetHandler& sh,
     244              :                                 TIterator elemsBegin,
     245              :                                 TIterator elemsEnd,
     246              :                                 AChar aDimension)
     247              : {
     248              :         typedef typename PtrToValueType<typename TIterator::value_type>::base_type TElem;
     249              : 
     250            0 :         UG_COND_THROW(!sh.grid(), "The subset-handler has to operate on a grid!");
     251            0 :         Grid& grid = *sh.grid();
     252              :         MultiElementAttachmentAccessor<AChar> aaDim(grid, aDimension, true, true, true, true);
     253              : 
     254              :         Grid::edge_traits::secure_container             edges;
     255              :         Grid::face_traits::secure_container             faces;
     256              :         Grid::volume_traits::secure_container   vols;
     257              : 
     258            0 :         for(TIterator iter = elemsBegin; iter != elemsEnd; ++iter){
     259              :                 TElem* elem = *iter;
     260            0 :                 if(sh.get_subset_index(elem) != -1)
     261            0 :                         continue;
     262              : 
     263            0 :                 const int dim = aaDim[elem];
     264            0 :                 switch(dim){
     265              :                         case 1:{
     266              :                         //      get the edge with dim 1 and with the lowest subset index
     267              :                                 int si = sh.num_subsets();
     268              :                                 grid.associated_elements(edges, elem);
     269            0 :                                 for(size_t i = 0; i < edges.size(); ++i){
     270              :                                         Edge* e = edges[i];
     271              :                                         int esi = sh.get_subset_index(e);
     272            0 :                                         if((aaDim[e] == 1) && (esi < si))
     273              :                                                 si = esi;
     274              :                                 }
     275            0 :                                 sh.assign_subset(elem, si);
     276              :                         }break;
     277              : 
     278              :                         case 2:{
     279              :                         //      get the face with dim 2 and with the lowest subset index
     280              :                                 int si = sh.num_subsets();
     281              :                                 grid.associated_elements(faces, elem);
     282            0 :                                 for(size_t i = 0; i < faces.size(); ++i){
     283              :                                         Face* e = faces[i];
     284              :                                         int esi = sh.get_subset_index(e);
     285            0 :                                         if((aaDim[e] == 2) && (esi < si))
     286              :                                                 si = esi;
     287              :                                 }
     288            0 :                                 sh.assign_subset(elem, si);
     289              :                         }break;
     290              : 
     291              :                         case 3:{
     292              :                         //      get the volume with dim 3 and with the lowest subset index
     293              :                                 int si = sh.num_subsets();
     294              :                                 grid.associated_elements(vols, elem);
     295            0 :                                 for(size_t i = 0; i < vols.size(); ++i){
     296              :                                         Volume* e = vols[i];
     297              :                                         int esi = sh.get_subset_index(e);
     298            0 :                                         if((aaDim[e] == 3) && (esi < si))
     299              :                                                 si = esi;
     300              :                                 }
     301            0 :                                 sh.assign_subset(elem, si);
     302              :                         }break;
     303              :                 }
     304              :         }
     305            0 : }
     306              : 
     307            0 : void CopySubsetIndicesToSides(
     308              :                 ISubsetHandler& sh,
     309              :                 GridObjectCollection goc,
     310              :                 bool toUnassignedOnly)
     311              : {
     312            0 :         UG_COND_THROW(!sh.grid(), "The subset-handler has to operate on a grid!");
     313            0 :         Grid& grid = *sh.grid();
     314              : 
     315            0 :         if(toUnassignedOnly){
     316              :                 AChar aDimension;
     317            0 :                 grid.attach_to_all(aDimension);
     318            0 :                 ComputeLocalSubsetDimensions(sh, aDimension, true);
     319            0 :                 for(int i = 0; i < (int)goc.num_levels(); ++i)
     320            0 :                         CopySubsetFromHigherDimNbr(sh, goc.begin<Vertex>(i), goc.end<Vertex>(i), aDimension);
     321            0 :                 for(int i = 0; i < (int)goc.num_levels(); ++i)
     322            0 :                         CopySubsetFromHigherDimNbr(sh, goc.begin<Edge>(i), goc.end<Edge>(i), aDimension);
     323            0 :                 for(int i = 0; i < (int)goc.num_levels(); ++i)
     324            0 :                         CopySubsetFromHigherDimNbr(sh, goc.begin<Face>(i), goc.end<Face>(i), aDimension);
     325            0 :                 grid.detach_from_all(aDimension);
     326              :         }
     327              :         else{
     328            0 :                 for(int i = 0; i < (int)goc.num_levels(); ++i){
     329            0 :                         CopySubsetIndicesToSides(sh, goc.begin<Volume>(i), goc.end<Volume>(i), false);
     330            0 :                         CopySubsetIndicesToSides(sh, goc.begin<Face>(i), goc.end<Face>(i), false);
     331            0 :                         CopySubsetIndicesToSides(sh, goc.begin<Edge>(i), goc.end<Edge>(i), false);
     332              :                         CopySubsetIndicesToSides(sh, goc.begin<Vertex>(i), goc.end<Vertex>(i), false);
     333              :                 }
     334              :         }
     335            0 : }
     336              : 
     337            0 : void CopySubsetIndicesToSides(ISubsetHandler& sh, ISelector& sel,
     338              :                                                           bool toUnassignedOnly)
     339              : {
     340            0 :         CopySubsetIndicesToSides (sh, sel.get_grid_objects(), toUnassignedOnly);
     341            0 : }
     342              : 
     343              : 
     344              : ////////////////////////////////////////////////////////////////////////
     345            0 : void CopySubsetIndicesToSides(ISubsetHandler& sh, bool toUnassignedOnly)
     346              : {
     347            0 :         UG_COND_THROW(!sh.grid(), "The subset-handler has to operate on a grid!");
     348            0 :         Grid& grid = *sh.grid();
     349            0 :         CopySubsetIndicesToSides(sh, grid.get_grid_objects(), toUnassignedOnly);
     350            0 : }
     351              : 
     352              : 
     353              : ////////////////////////////////////////////////////////////////////////
     354              : // AdjustSubsetsForLgmNg
     355            0 : void AdjustSubsetsForLgmNg(Grid& grid, SubsetHandler& sh,
     356              :                                                         bool keepExistingInterfaceSubsets)
     357              : {
     358            0 :         if(grid.num_volumes() > 0)
     359              :         {
     360              :         //      the 3d case
     361              :                 vector<Volume*> vVolumes;
     362              : 
     363              :         //      first make sure that all volumes are assigned to subsets,
     364              :         //      and that no empty volume-subset is between filled ones.
     365            0 :                 MakeSubsetsConsecutive<Volume>(sh);
     366              : 
     367              :         //      the first index for new subsets.
     368            0 :                 int newVolSubsetIndex = GetMaxSubsetIndex<Volume>(sh) + 1;
     369              :         //      iterate through all volumes and assign each, that is not assigned
     370              :         //      to a subset, to the new one.
     371              :                 for(VolumeIterator iter = grid.volumes_begin();
     372            0 :                         iter != grid.volumes_end(); ++iter)
     373              :                 {
     374            0 :                         if(sh.get_subset_index(*iter) == -1)
     375            0 :                                 sh.assign_subset(*iter, newVolSubsetIndex);
     376              :                 }
     377              : 
     378              :         //      assign all edges to subset -1
     379            0 :                 sh.assign_subset(grid.edges_begin(), grid.edges_end(), -1);
     380              : 
     381            0 :                 if(keepExistingInterfaceSubsets){
     382              :                 //      now we'll assign all faces which are no interface
     383              :                 //      elements, to subset -1.
     384              :                         for(FaceIterator iter = grid.faces_begin();
     385            0 :                                 iter != grid.faces_end(); ++iter)
     386              :                         {
     387              :                                 Face* f = *iter;
     388            0 :                                 if(sh.get_subset_index(f) != -1)
     389              :                                 {
     390            0 :                                         CollectVolumes(vVolumes, grid, f);
     391              : 
     392            0 :                                         if(vVolumes.size() > 1)
     393              :                                         {
     394              :                                         //      check if there are different adjacent volumes.
     395            0 :                                                 int si = sh.get_subset_index(vVolumes[0]);
     396              :                                                 bool gotOne = false;
     397            0 :                                                 for(uint i = 0; i < vVolumes.size(); ++i)
     398              :                                                 {
     399            0 :                                                         if(sh.get_subset_index(vVolumes[i]) != si)
     400              :                                                         {
     401              :                                                                 gotOne = true;
     402              :                                                                 break;
     403              :                                                         }
     404              :                                                 }
     405              : 
     406            0 :                                                 if(!gotOne)
     407              :                                                 {
     408              :                                                 //      no, they are all from the same subset.
     409            0 :                                                         sh.assign_subset(f, -1);
     410              :                                                 }
     411              :                                         }
     412              :                                 }
     413              :                         }
     414              :                 }
     415              :                 else{
     416              :                 //      since we don't have to keep existing interface subsets we
     417              :                 //      can assign all faces to subset -1
     418              :                         sh.assign_subset(grid.faces_begin(), grid.faces_end(), -1);
     419              :                 }
     420              : 
     421              :         //      make sure that there are no empty face-subsets between filled ones.
     422              :         //      since we may not swap subsets (otherwise the volume-sequence would be destroyed)
     423              :         //      we have to copy the elements.
     424            0 :                 for(int i = 0; i < sh.num_subsets(); ++i){
     425            0 :                         if(sh.num<Face>(i) == 0){
     426              :                         //      find the next that has faces
     427              :                                 int next = sh.num_subsets();
     428            0 :                                 for(int j = i+1; j < sh.num_subsets(); ++j){
     429            0 :                                         if(sh.num<Face>(j) > 0){
     430              :                                                 next = j;
     431              :                                                 break;
     432              :                                         }
     433              :                                 }
     434              : 
     435              :                         //      if a filled one has been found, we'll copy the elements
     436            0 :                                 if(next < sh.num_subsets()){
     437              :                                 //      assign all faces in next to subset i
     438              :                                         sh.assign_subset(sh.begin<Face>(next), sh.end<Face>(next), i);
     439              :                                 }
     440              :                                 else{
     441              :                                 //      we're done
     442              :                                         break;
     443              :                                 }
     444              :                         }
     445              :                 }
     446              : 
     447              :         //      now we have to assign the interface faces to subsets.
     448            0 :                 AssignVolumeInterfaceFacesToSubsets(grid, sh);
     449              : 
     450              :         //      we now have to make sure that all face-subsets are regular manifolds.
     451            0 :                 for(int i = 0; i < sh.num_subsets(); ++i){
     452            0 :                         int firstFree = GetMaxSubsetIndex<Face>(sh) + 1;
     453            0 :                         SplitIrregularManifoldSubset(sh, i, firstFree, true);
     454              :                 }
     455              : 
     456              :         //      fix orientation of all face subsets
     457            0 :                 for(int i = 0; i < sh.num_subsets(); ++i){
     458            0 :                         if(sh.num<Face>(i) != 0){
     459            0 :                                 FixFaceOrientation(grid, sh.begin<Face>(i), sh.end<Face>(i));
     460              :                         }
     461              :                 }
     462            0 :         }
     463              :         else
     464              :         {
     465              :         //      the 2d - case.
     466              :                 vector<Face*> vFaces;
     467              : 
     468              :         //      first make sure that all faces are assigned to subsets,
     469              :         //      and that no empty face-subset is between filled ones.
     470            0 :                 MakeSubsetsConsecutive<Face>(sh);
     471              : 
     472              :         //      the first index for new subsets.
     473            0 :                 int newFaceSubsetIndex = GetMaxSubsetIndex<Face>(sh) + 1;
     474              : 
     475              :         //      iterate through all faces and assign each, that is not assigned
     476              :         //      to a subset, to the new one.
     477              :                 for(FaceIterator iter = grid.faces_begin();
     478            0 :                         iter != grid.faces_end(); ++iter)
     479              :                 {
     480            0 :                         if(sh.get_subset_index(*iter) == -1)
     481            0 :                                 sh.assign_subset(*iter, newFaceSubsetIndex);
     482              :                 }
     483              : 
     484              :         //      now we'll assign all edges which are no interface
     485              :         //      elements, to subset -1.
     486            0 :                 if(keepExistingInterfaceSubsets){
     487              :                         for(EdgeIterator iter = grid.edges_begin();
     488            0 :                                 iter != grid.edges_end(); ++iter)
     489              :                         {
     490              :                                 Edge* e = *iter;
     491            0 :                                 if(sh.get_subset_index(e) != -1)
     492              :                                 {
     493            0 :                                         CollectFaces(vFaces, grid, e);
     494              : 
     495            0 :                                         if(vFaces.size() > 1)
     496              :                                         {
     497              :                                         //      check if there are different adjacent volumes.
     498            0 :                                                 int si = sh.get_subset_index(vFaces[0]);
     499              :                                                 bool gotOne = false;
     500            0 :                                                 for(uint i = 0; i < vFaces.size(); ++i)
     501              :                                                 {
     502            0 :                                                         if(sh.get_subset_index(vFaces[i]) != si)
     503              :                                                         {
     504              :                                                                 gotOne = true;
     505              :                                                                 break;
     506              :                                                         }
     507              :                                                 }
     508              : 
     509            0 :                                                 if(!gotOne)
     510              :                                                 {
     511              :                                                 //      no, they are all from the same subset.
     512            0 :                                                         sh.assign_subset(e, -1);
     513              :                                                 }
     514              :                                         }
     515              :                                 }
     516              :                         }
     517              :                 }
     518              :                 else{
     519              :                 //      since we don't have to keep existing interface subsets we can
     520              :                 //      assign all edges to subset -1.
     521            0 :                         sh.assign_subset(grid.edges_begin(), grid.edges_end(), -1);
     522              :                 }
     523              : 
     524              :         //      make sure that there are no empty edge-subsets between filled ones.
     525              :         //      since we may not swap subsets (otherwise the face-sequence would be destroyed)
     526              :         //      we have to copy the elements.
     527            0 :                 for(int i = 0; i < sh.num_subsets(); ++i){
     528            0 :                         if(sh.num<Edge>(i) == 0){
     529              :                         //      find the next that has faces
     530              :                                 int next = sh.num_subsets();
     531            0 :                                 for(int j = i+1; j < sh.num_subsets(); ++j){
     532            0 :                                         if(sh.num<Edge>(j) > 0){
     533              :                                                 next = j;
     534              :                                                 break;
     535              :                                         }
     536              :                                 }
     537              : 
     538              :                         //      if a filled one has been found, we'll copy the elements
     539            0 :                                 if(next < sh.num_subsets()){
     540              :                                 //      assign all edges in next to subset i
     541            0 :                                         sh.assign_subset(sh.begin<Edge>(next), sh.end<Edge>(next), i);
     542              :                                 }
     543              :                                 else{
     544              :                                 //      we're done
     545              :                                         break;
     546              :                                 }
     547              :                         }
     548              :                 }
     549              : 
     550              :         //      now we have to assign the interface edges to subsets.
     551            0 :                 AssignFaceInterfaceEdgesToSubsets(grid, sh);
     552              :                 
     553              :         //      make sure that all edge-subsets are regular poly-chains
     554            0 :                 int firstFree = GetMaxSubsetIndex<Edge>(sh) + 1;
     555            0 :                 for(int i = 0; i < sh.num_subsets(); ++i){
     556            0 :                         if(SplitIrregularPolyChain(sh, i, firstFree))
     557            0 :                                 ++firstFree;
     558              :                 }
     559              : 
     560              :         //      Since ug3 does not support loops, we have to remove those.
     561            0 :                 for(int i = 0; i < sh.num_subsets(); ++i){
     562            0 :                         size_t chainType = GetPolyChainType(grid, sh.begin<Edge>(i),
     563            0 :                                                                                                 sh.end<Edge>(i),
     564            0 :                                                                                                 IsInSubset(sh, i));
     565            0 :                         if(chainType == PCT_CLOSED){
     566              :                         //      since the chain is regular (see loop above) and since it is
     567              :                         //      closed, it is enough to simply move the first edge of the
     568              :                         //      chain to a new subset.
     569            0 :                                 sh.assign_subset(*sh.begin<Edge>(i), firstFree++);
     570              :                         }
     571              :                 }
     572              :                 
     573              :         //      fix orientation
     574            0 :                 for(int i = 0; i < sh.num_subsets(); ++i){
     575            0 :                         if(sh.num<Edge>(i) != 0){
     576            0 :                                 FixEdgeOrientation(grid, sh.begin<Edge>(i), sh.end<Edge>(i));
     577              :                         }
     578              :                 }
     579              : 
     580            0 :         }
     581            0 : }
     582              : 
     583              : ////////////////////////////////////////////////////////////////////////
     584            0 : bool SplitIrregularManifoldSubset(SubsetHandler& sh, int srcIndex,
     585              :                                                                   int targetIndex, bool strictSplitting)
     586              : {
     587              : //      Begin with the first face in the subset-handler and find
     588              : //      associated faces which build a regular manifold.
     589              : //      if the subset is empty, there's nothing to do.
     590            0 :         if(sh.empty<Face>(srcIndex))
     591              :                 return false;
     592              : 
     593              : //      get the grid behind the subset-handler
     594            0 :         if(!sh.grid()){
     595              :                 UG_LOG("ERROR in SplitIrregularManifoldSubset: No Grid associated");
     596              :                 UG_LOG(" with the given SubsetHandler.\n");
     597            0 :                 return false;
     598              :         }
     599              : 
     600            0 :         Grid& grid = *sh.grid();
     601              : 
     602              : //      edges are required
     603            0 :         if(!grid.option_is_enabled(FACEOPT_AUTOGENERATE_EDGES)){
     604              :                 UG_LOG("WARNING in SplitIrregularManifoldSubset: Autoenabling FACEOPT_AUTOGENERATE_EDGES.\n");
     605            0 :                 grid.enable_options(FACEOPT_AUTOGENERATE_EDGES);
     606              :         }
     607              : 
     608              : //      here we'll store some temporary results
     609              :         vector<Edge*> edges;
     610              :         vector<Face*> faces;
     611              : 
     612              : //      the queue is used to keep a list of elements which have to be checked.
     613              : //      begin with the first face.
     614              :         queue<Face*> queFaces;
     615            0 :         queFaces.push(*sh.begin<Face>(srcIndex));
     616              : 
     617              : //      We have to mark all faces which have once been pushed to the stack
     618            0 :         grid.begin_marking();
     619            0 :         grid.mark(queFaces.front());
     620              : 
     621              : //      If we notice that a face would cause a manifold to be irregular,
     622              : //      we'll mark it and push it to this vector.
     623              :         vector<Face*> vIrregFaces;
     624              : 
     625              : //      This counter tells us whether all faces have been processed.
     626              : //      If so, the surface is already a regular manifold.
     627              :         size_t numProcessed = 0;
     628              : 
     629              : //      now while there are unprocessed manifold faces
     630            0 :         while(!queFaces.empty())
     631              :         {
     632            0 :                 Face* curFace = queFaces.front();
     633              :                 queFaces.pop();
     634            0 :                 ++numProcessed;
     635              : 
     636              :         //      collect associated faces of associated edges
     637              :                 CollectAssociated(edges, grid, curFace);
     638            0 :                 for(size_t i_edge = 0; i_edge < edges.size(); ++i_edge)
     639              :                 {
     640              :                 //      collect associated faces
     641            0 :                         CollectAssociated(faces, grid, edges[i_edge]);
     642              : 
     643              :                 //      we only have to continue if we found exactly one face
     644              :                 //      in the same subset other than curFace.
     645              :                 //      (Do not check marks here, since we otherwise may find
     646              :                 //      unwanted neighbors).
     647            0 :                         Face* nbr = NULL;
     648              :                         size_t numFound = 0;
     649            0 :                         for(size_t i_face = 0; i_face < faces.size(); ++i_face){
     650            0 :                                 Face* f = faces[i_face];
     651            0 :                                 if((f != curFace) &&
     652            0 :                                         (       (strictSplitting && (sh.get_subset_index(f) != -1))
     653            0 :                                          || (!strictSplitting && (sh.get_subset_index(f) == srcIndex))))
     654              :                                 {
     655              :                                 //      we found an associated face in the same subset
     656            0 :                                         nbr = f;
     657            0 :                                         numFound++;
     658              :                                 }
     659              :                         }
     660              : 
     661              :                 //      If we found exactly one valid neighbor
     662            0 :                         if(numFound == 1){
     663              :                         //      if the neighbor was not already processed we'll schedule it
     664            0 :                                 if(!grid.is_marked(nbr)){
     665              :                                         grid.mark(nbr);
     666              :                                         queFaces.push(nbr);
     667              :                                 }
     668              :                         }
     669            0 :                         else if(numFound > 1){
     670              :                         //      here we have to make sure that no face which builds an
     671              :                         //      irregular manifold with another face can be identified
     672              :                         //      as a valid neighbor through another element.
     673              :                         //      Thus we'll mark them. Since they wouldn't be added to the
     674              :                         //      subset at targetInd later on (since they are marked) we have
     675              :                         //      to additionally push them into a vector.
     676            0 :                                 for(size_t i_face = 0; i_face < faces.size(); ++i_face){
     677            0 :                                         Face* f = faces[i_face];
     678            0 :                                         if((f != curFace) && (sh.get_subset_index(f) == srcIndex)){
     679            0 :                                                 if(!grid.is_marked(f)){
     680              :                                                         grid.mark(f);
     681            0 :                                                         vIrregFaces.push_back(f);
     682              :                                                 }
     683              :                                         }
     684              :                                 }
     685              :                         }
     686              :                 }
     687              :         }
     688              : 
     689              : //      if all faces of the subset have been processed, then the whole subset is
     690              : //      a regular manifold.
     691            0 :         if(numProcessed == sh.num<Face>(srcIndex)){
     692            0 :                 grid.end_marking();
     693              :                 return false;
     694              :         }
     695              : 
     696              : //      if not, we'll iterate over all faces of the subset and assign unmarked ones
     697              : //      to the subset at targetIndex.
     698              :         for(FaceIterator iter = sh.begin<Face>(srcIndex);
     699            0 :                 iter != sh.end<Face>(srcIndex);)
     700              :         {
     701              :         //      Take care with the iterator, since the element may be assigned
     702              :         //      to another subset.
     703              :                 Face* f = *iter;
     704              :                 ++iter;
     705              : 
     706            0 :                 if(!grid.is_marked(f))
     707            0 :                         sh.assign_subset(f, targetIndex);
     708              :         }
     709              : 
     710              : //      additionally we have to assign all faces in vIrregFaces to the new subset
     711            0 :         for(size_t i = 0; i < vIrregFaces.size(); ++i)
     712            0 :                 sh.assign_subset(vIrregFaces[i], targetIndex);
     713              : 
     714              : //      The subset was split - return true.
     715            0 :         grid.end_marking();
     716              :         return true;
     717            0 : }
     718              : 
     719              : ////////////////////////////////////////////////////////////////////////
     720              : //      SeparateFaceSubsetsByNormal
     721              : //      separates faces by orthogonal axis-aligned normals.
     722            0 : void SeparateFaceSubsetsByNormal(Grid& grid, SubsetHandler& sh,
     723              :                                                                 APosition aPos, ANormal* paNorm,
     724              :                                                                 int applyToSubset)
     725              : {
     726            0 :         vector<vector3> vNormals(6);
     727              :         vNormals[0] = vector3(1, 0, 0);
     728              :         vNormals[1] = vector3(0, 1, 0);
     729              :         vNormals[2] = vector3(0, 0, 1);
     730              :         vNormals[3] = vector3(-1, 0, 0);
     731              :         vNormals[4] = vector3(0, -1, 0);
     732              :         vNormals[5] = vector3(0, 0, -1);
     733              : 
     734            0 :         SeparateFaceSubsetsByNormal(grid, sh, vNormals, aPos, paNorm,
     735              :                                                                 applyToSubset);
     736            0 : }
     737              : 
     738              : ////////////////////////////////////////////////////////////////////////
     739              : //      SeparateFaceSubsetsByNormal
     740              : //      separates subset by the given normals.
     741            0 : void SeparateFaceSubsetsByNormal(Grid& grid, SubsetHandler& sh,
     742              :                                                                 std::vector<vector3> vNormals,
     743              :                                                                 APosition aPos, ANormal* paNorm,
     744              :                                                                 int applyToSubset)
     745              : {
     746              : //      iterate through all existing face-subsets.
     747              : //              iterate through all faces of the subset
     748              : //                      find the normal in vNormals that is the closest to the face-normal.
     749              : //                              add the faces to the matching subset.
     750              : 
     751            0 :         if(!grid.has_vertex_attachment(aPos))
     752            0 :                 return;
     753              : 
     754            0 :         if(vNormals.empty())
     755              :                 return;
     756              : 
     757              : //      the position accessor
     758              :         Grid::VertexAttachmentAccessor<APosition> aaPos(grid, aPos);
     759              : 
     760              : //      the normal accessor
     761              :         vector3 tmpNorm;//      this is only required if paNorm == NULL.
     762              :         Grid::FaceAttachmentAccessor<ANormal> aaNorm;
     763            0 :         if(paNorm)
     764              :         {
     765            0 :                 if(grid.has_face_attachment(*paNorm))
     766              :                         aaNorm.access(grid, *paNorm);
     767              :         }
     768              : 
     769              : //      only separate faces of subsets that already existed at the beginning.
     770            0 :         int numFaceSubsets = GetMaxSubsetIndex<Face>(sh) + 1;
     771              :         int nextFreeSubset = numFaceSubsets;
     772              : 
     773              : //      if a subset was specified, we'll only apply the separation to this subset
     774              :         int i = 0;
     775              :         int iMax = numFaceSubsets - 1;
     776            0 :         if(applyToSubset >= 0){
     777              :                 i = applyToSubset;
     778              :                 iMax = applyToSubset;
     779              :         }
     780              : 
     781            0 :         for(; i <= iMax; ++i)
     782              :         {
     783              :                 bool firstFace = true;
     784              :         //      this vector holds associated subset indices for each normal.
     785            0 :                 vector<int> vSubsetIndices(vNormals.size(), -1);
     786              : 
     787              :         //      iterate through the faces of the active subset
     788              :                 FaceIterator iter = sh.begin<Face>(i);
     789            0 :                 while(iter != sh.end<Face>(i))
     790              :                 {
     791              :                         Face* f = *iter;
     792              :                         iter++;//       increment iterator here, since it would else be invalidated later on.
     793              : 
     794              :                         vector3* pN;//  pointer to the normal of the face.
     795            0 :                         if(aaNorm.valid())
     796              :                                 pN = &aaNorm[f];
     797              :                         else
     798              :                         {
     799              :                         //      calculate normal on the fly
     800            0 :                                 CalculateNormal(tmpNorm, f, aaPos);
     801              :                                 pN = &tmpNorm;
     802              :                         }
     803              : 
     804              :                 //      find the index of the closest normal
     805              :                         int closestInd = -1;
     806              :                         number closestDist = 100;// 4 is the max-distance-square for normized normals.
     807            0 :                         for(uint j = 0; j < (uint)vNormals.size(); ++j)
     808              :                         {
     809            0 :                                 number nDist = VecDistanceSq(*pN, vNormals[j]);
     810            0 :                                 if(nDist < closestDist)
     811              :                                 {
     812              :                                         closestDist = nDist;
     813            0 :                                         closestInd = j;
     814              :                                 }
     815              :                         }
     816              : 
     817              :                 //      get the index of the matching subset.
     818            0 :                         if(vSubsetIndices[closestInd] == -1)
     819              :                         {
     820              :                         //      all faces with the same normal as the first face
     821              :                         //      will stay in the subset
     822            0 :                                 if(firstFace)
     823              :                                 {
     824              :                                         firstFace = false;
     825            0 :                                         vSubsetIndices[closestInd] = i;
     826              :                                 }
     827              :                                 else
     828              :                                 {
     829              :                                 //      choose an empty subset
     830            0 :                                         vSubsetIndices[closestInd] = nextFreeSubset++;
     831              :                                 }
     832              :                         }
     833              : 
     834              :                 //      assign the face
     835            0 :                         if(vSubsetIndices[closestInd] != i)
     836            0 :                                 sh.assign_subset(f, vSubsetIndices[closestInd]);
     837              :                 }
     838            0 :         }
     839              : 
     840              : }
     841              : 
     842              : /*
     843              : void SeparateVolumesByFaceSubsets(Grid& grid, SubsetHandler& sh)
     844              : {
     845              : //      first we'll assign all volumes to subset -1.
     846              :         sh.assign_subset(grid.volumes_begin(), grid.volumes_end(), -1);
     847              : 
     848              : //      we'll keep all unassigned volumes in a selector.
     849              :         Selector sel(grid);
     850              :         sel.select(grid.volumes_begin(), grid.volumes_end());
     851              : 
     852              : //      those vectors will be used to gather element neighbours.
     853              :         vector<Face*> vFaces;
     854              :         vector<Volume*> vVolumes;
     855              : 
     856              : //      this stack contains all volumes that we still have to check for neighbours.
     857              :         stack<Volume*> stkVols;
     858              : 
     859              : //      will be used to store sides of volumes
     860              :         FaceDescriptor fd;
     861              : 
     862              : //      now - while there are unassigned volumes.
     863              :         int subsetIndex = 0;
     864              :         while(!sel.empty())
     865              :         {
     866              :         //      choose the volume with which we want to start
     867              :         //      TODO: if material-points are supplied, this should be the
     868              :         //              the volume that contains the i-th material point.
     869              :                 stkVols.push(*sel.begin<Volume>());
     870              :                 while(!stkVols.empty())
     871              :                 {
     872              :                         Volume* v = stkVols.top();
     873              :                         stkVols.pop();
     874              :                 //      if the volume is unselected it has already been processed.
     875              :                         if(!sel.is_selected(v))
     876              :                                 continue;
     877              :                         sel.deselect(v);
     878              : 
     879              :                 //      assign v to its new subset
     880              :                         sh.assign_subset(v, subsetIndex);
     881              : 
     882              :                 //      check neighbour-volumes, whether they belong to the same subset.
     883              :                 //      iterate through the sides of the volume
     884              :                         for(uint i = 0; i < v->num_faces(); ++i)
     885              :                         {
     886              :                                 v->face(i, fd);
     887              : 
     888              :                         //      get the corresponding face
     889              :                                 Face* f = grid.get_face(fd);
     890              : 
     891              :                                 bool bSeparator = false;
     892              :                         //      if it belongs to a subset other that -1, it is a separator.
     893              :                                 if(f)
     894              :                                         bSeparator = (sh.get_subset_index(f) != -1);
     895              : 
     896              :                         //      if fd is not corresponding to a separator, we'll add all connected volumes
     897              :                                 if(!bSeparator)
     898              :                                 {
     899              :                                         CollectVolumes(vVolumes, grid, fd);
     900              : 
     901              :                                 //      add all volumes that are still selected (v is not selected anymore).
     902              :                                         for(uint j = 0; j < vVolumes.size(); ++j)
     903              :                                         {
     904              :                                                 if(sel.is_selected(vVolumes[j]))
     905              :                                                         stkVols.push(vVolumes[j]);
     906              :                                         }
     907              :                                 }
     908              :                         }
     909              :                 }
     910              :         //      the stack is empty. increase subset index.
     911              :                 subsetIndex++;
     912              :         }
     913              : }
     914              : */
     915            0 : void AssignRegionToSubset(Grid& grid, ISubsetHandler& shVolsOut,
     916              :                                                   const ISubsetHandler& shFaces,
     917              :                                                   Volume* proxyVol, int newSubsetIndex)
     918              : {
     919              : //      we'll utilize a stack to gather all volumes that have to
     920              : //      be examined.
     921              :         stack<Volume*> stkVols;
     922              :         stkVols.push(proxyVol);
     923              : 
     924              : //      this vector will be used to collect neighbours
     925              :         vector<Volume*> vVols;
     926              : 
     927              : //      while there are volumes on the stack we'll go on
     928            0 :         while(!stkVols.empty()){
     929            0 :                 Volume* v = stkVols.top();
     930              :                 stkVols.pop();
     931              : 
     932            0 :                 shVolsOut.assign_subset(v, newSubsetIndex);
     933              : 
     934              :         //      check all neighbours and decide whether they have to be
     935              :         //      pushed to the stack.
     936              :         //      First we'll have to check for each side of v whether we may traverse it
     937            0 :                 for(uint i = 0; i < v->num_faces(); ++i){
     938            0 :                         Face* f = grid.get_face(v, i);
     939            0 :                         if(f){
     940              :                         //      check whether f lies in a subset
     941              :                         //      if so we may not traverse it and we'll continue with the next face.
     942            0 :                                 if(shFaces.get_subset_index(f) != -1)
     943            0 :                                         continue;
     944              : 
     945              :                         //      we may traverse it. get the neighbour-volumes
     946            0 :                                 CollectVolumes(vVols, grid, f);
     947              :                         }
     948              :                         else{
     949              :                         //      no associated face existed. We'll use GetNeighbours to find
     950              :                         //      neighbouring volumes. Since no face can separate them, they
     951              :                         //      belong to the region, too.
     952            0 :                                 GetNeighbours(vVols, grid, v, i);
     953              :                         }
     954              : 
     955              :                 //      add the volumes in vVols to the stack - but only if they don't
     956              :                 //      already belong to the region.
     957            0 :                         for(size_t j = 0; j < vVols.size(); ++j){
     958            0 :                                 if(vVols[j] != v){
     959            0 :                                         if(shVolsOut.get_subset_index(vVols[j]) != newSubsetIndex)
     960              :                                                 stkVols.push(vVols[j]);
     961              :                                 }
     962              :                         }
     963              :                 }
     964              :         }
     965            0 : }
     966              : 
     967              : ////////////////////////////////////////////////////////////////////////
     968            0 : bool SeparateRegions(Grid& grid, ISubsetHandler& shVolsOut,
     969              :                                          const ISubsetHandler& shFaces,
     970              :                                          const MarkerPointManager& mpm,
     971              :                                          int firstSubsetIndex)
     972              : {
     973            0 :         if(!grid.has_vertex_attachment(aPosition))
     974              :                 return false;
     975              : 
     976              :         Grid::VertexAttachmentAccessor<APosition> aaPos(grid, aPosition);
     977              : 
     978            0 :         for(size_t i = 0; i < mpm.num_markers(); ++i)
     979              :         {
     980            0 :                 const vector3& pos = mpm.get_marker(i).pos;
     981              : 
     982              : //TODO: extend to volumes in general. Add a PointIsInsideVolume method.
     983              :         //      find the tetrahedron that contains the marker point
     984              :                 for(TetrahedronIterator iter = grid.begin<Tetrahedron>();
     985            0 :                         iter != grid.end<Tetrahedron>(); ++iter)
     986              :                 {
     987            0 :                         if(PointIsInsideTetrahedron(pos, *iter, aaPos)){
     988              :                         //      assign region to subset
     989            0 :                                 int si = firstSubsetIndex + i;
     990            0 :                                 AssignRegionToSubset(grid, shVolsOut, shFaces,
     991              :                                                                         *iter, si);
     992              :                         //      set subset name
     993            0 :                                 shVolsOut.subset_info(si).name = mpm.get_marker(i).name;
     994              :                         //      we don't have to check other volumes.
     995              :                                 break;
     996              :                         }
     997              :                 }
     998              :         }
     999              : 
    1000              : //      done
    1001              :         return true;
    1002              : }
    1003              : 
    1004            0 : void AssignInnerAndBoundarySubsets(Grid& grid, ISubsetHandler& shOut,
    1005              :                                                                         int inSubset, int bndSubset)
    1006              : {
    1007            0 :         if(grid.num<Volume>() > 0){
    1008              :         //      assign volumes to inSubset
    1009              :                 for(VolumeIterator iter = grid.begin<Volume>();
    1010            0 :                         iter != grid.end<Volume>(); ++iter)
    1011              :                 {
    1012            0 :                         if(shOut.get_subset_index(*iter) == -1)
    1013            0 :                                 shOut.assign_subset(*iter, inSubset);
    1014              :                 }
    1015              : 
    1016              :                 vector<Edge*> vEdges;
    1017              :         //      assign volume-boundary elements to bndSubset
    1018            0 :                 for(FaceIterator iter = grid.begin<Face>(); iter != grid.end<Face>(); ++iter)
    1019              :                 {
    1020              :                         Face* f = *iter;
    1021            0 :                         if(shOut.get_subset_index(f) == -1){
    1022            0 :                                 if(IsVolumeBoundaryFace(grid, f)){
    1023              :                                 //      assign the face to the boundary subset.
    1024            0 :                                         shOut.assign_subset(f, bndSubset);
    1025              : 
    1026              :                                 //      assign associated vertices and edges to the boundary subset, too.
    1027            0 :                                         for(size_t i = 0; i < f->num_vertices(); ++i){
    1028            0 :                                                 if(shOut.get_subset_index(f->vertex(i)) == -1)
    1029            0 :                                                         shOut.assign_subset(f->vertex(i), bndSubset);
    1030              :                                         }
    1031              : 
    1032            0 :                                         CollectEdges(vEdges, grid, f);
    1033            0 :                                         for(size_t i = 0; i < vEdges.size(); ++i){
    1034            0 :                                                 if(shOut.get_subset_index(vEdges[i]) == -1)
    1035            0 :                                                         shOut.assign_subset(vEdges[i], bndSubset);
    1036              :                                         }
    1037              :                                 }
    1038              :                                 else{
    1039              :                                 //      assing the face to the inner subset
    1040            0 :                                         shOut.assign_subset(f, inSubset);
    1041              :                                 }
    1042              :                         }
    1043              :                 }
    1044            0 :         }
    1045              :         else{
    1046              :                 for(FaceIterator iter = grid.begin<Face>();
    1047            0 :                         iter != grid.end<Face>(); ++iter)
    1048              :                 {
    1049            0 :                         if(shOut.get_subset_index(*iter) == -1)
    1050            0 :                                 shOut.assign_subset(*iter, inSubset);
    1051              :                 }
    1052              :         }
    1053              : 
    1054              : //      assign edges and vertices
    1055              :         for(EdgeIterator iter = grid.begin<Edge>();
    1056            0 :                 iter != grid.end<Edge>(); ++iter)
    1057              :         {
    1058              :                 Edge* e = *iter;
    1059            0 :                 if(shOut.get_subset_index(e) == -1){
    1060            0 :                         if(IsBoundaryEdge2D(grid, e))
    1061              :                         {
    1062            0 :                                 shOut.assign_subset(e, bndSubset);
    1063            0 :                                 for(size_t i = 0; i < 2; ++i)
    1064              :                                 {
    1065            0 :                                         if(shOut.get_subset_index(e->vertex(i)) == -1)
    1066            0 :                                                 shOut.assign_subset(e->vertex(i), bndSubset);
    1067              :                                 }
    1068              :                         }
    1069              :                         else
    1070            0 :                                 shOut.assign_subset(e, inSubset);
    1071              :                 }
    1072              :         }
    1073              : 
    1074              : //      assign unassigned vertices
    1075              :         for(VertexIterator iter = grid.begin<Vertex>();
    1076            0 :                 iter != grid.end<Vertex>(); ++iter)
    1077              :         {
    1078            0 :                 if(shOut.get_subset_index(*iter) == -1)
    1079            0 :                         shOut.assign_subset(*iter, inSubset);
    1080              :         }
    1081            0 : }
    1082              : 
    1083              : 
    1084              : ////////////////////////////////////////////////////////////////////////
    1085            0 : vector3 GetColorFromStandardPalette(int index)
    1086              : {
    1087            0 :         return GetColorFromDefaultPalette (index);
    1088              : }
    1089              : 
    1090              : ////////////////////////////////////////////////////////////////////////
    1091            0 : void AssignSubsetColors(ISubsetHandler& sh)
    1092              : {
    1093            0 :         AssignDefaultSubsetColors (sh);
    1094            0 : }
    1095              : 
    1096              : 
    1097              : ////////////////////////////////////////////////////////////////////////
    1098              : template <class TElem>
    1099            0 : void AssignSidesToSubsets(ISubsetHandler& sh, ISelector* psel)
    1100              : {
    1101              :         typedef typename TElem::lower_dim_base_object           Side;
    1102              :         typedef typename geometry_traits<Side>::iterator  SideIter;
    1103              :         typedef std::vector<int> IntString;
    1104              : 
    1105              : //      access the grid on which sh operates.
    1106            0 :         if(!sh.grid())
    1107            0 :                 return;
    1108              : 
    1109            0 :         Grid& grid = *sh.grid();
    1110              : 
    1111              : //      we'll use those marks to check whether a subset has already been
    1112              : //      processed in an iteration. A subset is considered to be marked, if
    1113              : //      marks[subInd] == curMarker.
    1114              : //      Note that curMarker is increased in each iteration.
    1115              : //      Note also, that marks has to be resized whenever a new subset is added.
    1116              :         size_t curMark = 1;
    1117            0 :         vector<size_t> marks(sh.num_subsets(), 0);
    1118              : 
    1119              : //      here we'll check whether a subset already contains elements with
    1120              : //      a given neighborhood subset-constellation.
    1121              : //      Note that the key will be calculated from the subset-constellation.
    1122              : //      we're using double to allow more values
    1123              :         map<IntString, int> subsetMap;
    1124              : 
    1125              : //      this vector will be used to collect all associated subsets of an element.
    1126              : //      we'll use the subset-mark mechanism to avoid duplicate entries.
    1127              :         IntString skey;
    1128              : 
    1129              : //      used to collect neighbors of type TElem
    1130              :         vector<TElem*> elems;
    1131              : 
    1132              : //      Now iterate over all elements of type Side
    1133              :         for(SideIter iterSide = grid.begin<Side>();
    1134            0 :                 iterSide != grid.end<Side>(); ++iterSide)
    1135              :         {
    1136              :                 Side* side = *iterSide;
    1137              : 
    1138            0 :                 if(sh.get_subset_index(side) != -1)
    1139              :                         continue;
    1140              : 
    1141              :         //      check whether we are working on a selected side
    1142              :                 bool isSelected = false;
    1143            0 :                 if(psel && psel->is_selected(side))
    1144              :                         isSelected = true;
    1145              : 
    1146              :         //      increase curMark
    1147            0 :                 ++curMark;
    1148              : 
    1149              :         //      collect all associated elements of side
    1150              :                 CollectAssociated(elems, grid, side);
    1151              : 
    1152              :         //      collect the subsets in which they lie. Note that we won't push the
    1153              :         //      same subset index twice to skey.
    1154              :                 skey.clear();
    1155              : 
    1156              :         //      this subset index shall be used if the key is new
    1157            0 :                 int useSubsetInd = GetFirstFreeSubset(sh);
    1158              : 
    1159            0 :                 for(size_t i_elems = 0; i_elems < elems.size(); ++i_elems){
    1160              :                         bool nbrIsSelected = false;
    1161            0 :                         if(psel && psel->is_selected(elems[i_elems]))
    1162              :                                 nbrIsSelected = true;
    1163              : 
    1164              :                 //      either the element is not selected or it is selected and its neighbor
    1165              :                 //      is selected, too.
    1166            0 :                         if(!isSelected || nbrIsSelected){
    1167            0 :                                 int si = sh.get_subset_index(elems[i_elems]);
    1168              :                         //      check if the subset is marked
    1169            0 :                                 if(marks[si] != curMark){
    1170              :                                 //      no - mark it and add si to subsets
    1171            0 :                                         marks[si] = curMark;
    1172            0 :                                         skey.push_back(si);
    1173              :                                 }
    1174              :                         }
    1175              :                 }
    1176              : 
    1177            0 :                 if(skey.size() == 1){
    1178            0 :                         if(elems.size() > 1){
    1179              :                         //      we've got an inner element. Assign the subset-index
    1180              :                         //      of those inner neighbor elements.
    1181            0 :                                 useSubsetInd = skey[0];
    1182              :                         }
    1183              :                         else{
    1184              :                         //      An outer interface element.
    1185              :                         //      add -2 to skey to make sure that they go into a separate subset
    1186              :                         //      (-1 might occur as a normal subset index)
    1187            0 :                                 skey.push_back(-2);
    1188              :                         }
    1189              :                 }
    1190              : 
    1191              :         //      The subset indices in skey have to be sorted before they can be
    1192              :         //      used as unique key
    1193            0 :                 sort(skey.begin(), skey.end());
    1194              : 
    1195              :         //      get the subset index from the subsetMap, if one exists.
    1196              :                 map<IntString, int>::iterator tMapIter = subsetMap.find(skey);
    1197            0 :                 if(tMapIter != subsetMap.end()){
    1198              :                 //      got one
    1199            0 :                         sh.assign_subset(side, tMapIter->second);
    1200              :                 }
    1201              :                 else{
    1202              :                 //      create a new entry and resize the marks array
    1203            0 :                         subsetMap[skey] = useSubsetInd;
    1204            0 :                         sh.assign_subset(side, useSubsetInd);
    1205            0 :                         if(sh.num_subsets() > (int)marks.size())
    1206            0 :                                 marks.resize(sh.num_subsets(), 0);
    1207              :                 }
    1208              :         }
    1209            0 : }
    1210              : 
    1211              : //      template specialization
    1212              : template void AssignSidesToSubsets<Edge>(ISubsetHandler&, ISelector*);
    1213              : template void AssignSidesToSubsets<Face>(ISubsetHandler&, ISelector*);
    1214              : template void AssignSidesToSubsets<Volume>(ISubsetHandler&, ISelector*);
    1215              : 
    1216              : 
    1217            0 : void AssignSubsetsByElementType(ISubsetHandler& sh)
    1218              : {
    1219            0 :         if(!sh.grid())
    1220              :                 return;
    1221              : 
    1222            0 :         AssignSubsetsByElementType(sh, sh.grid()->get_grid_objects());
    1223              : }
    1224              : 
    1225              : 
    1226            0 : void AssignSubsetsByElementType(ISubsetHandler& sh, GridObjectCollection g)
    1227              : {
    1228              :         int subsetInd = 0;
    1229              : 
    1230            0 :         if(g.num<RegularVertex>() > 0){
    1231              :                 sh.assign_subset(g.begin<RegularVertex>(), g.end<RegularVertex>(), subsetInd);
    1232            0 :                 sh.subset_info(subsetInd++).name = "RegularVertex";
    1233              :         }
    1234              : 
    1235            0 :         if(g.num<ConstrainedVertex>() > 0){
    1236              :                 sh.assign_subset(g.begin<ConstrainedVertex>(), g.end<ConstrainedVertex>(), subsetInd);
    1237            0 :                 sh.subset_info(subsetInd++).name = "HangingVertex";
    1238              :         }
    1239              : 
    1240            0 :         if(g.num<RegularEdge>() > 0){
    1241              :                 sh.assign_subset(g.begin<RegularEdge>(), g.end<RegularEdge>(), subsetInd);
    1242            0 :                 sh.subset_info(subsetInd++).name = "RegularEdge";
    1243              :         }
    1244              : 
    1245            0 :         if(g.num<ConstrainingEdge>() > 0){
    1246              :                 sh.assign_subset(g.begin<ConstrainingEdge>(), g.end<ConstrainingEdge>(), subsetInd);
    1247            0 :                 sh.subset_info(subsetInd++).name = "ConstrainingEdge";
    1248              :         }
    1249              : 
    1250            0 :         if(g.num<ConstrainedEdge>() > 0){
    1251              :                 sh.assign_subset(g.begin<ConstrainedEdge>(), g.end<ConstrainedEdge>(), subsetInd);
    1252            0 :                 sh.subset_info(subsetInd++).name = "ConstrainedEdge";
    1253              :         }
    1254              : 
    1255            0 :         if(g.num<Triangle>() > 0){
    1256              :                 sh.assign_subset(g.begin<Triangle>(), g.end<Triangle>(), subsetInd);
    1257            0 :                 sh.subset_info(subsetInd++).name = "Triangle";
    1258              :         }
    1259              : 
    1260            0 :         if(g.num<ConstrainingTriangle>() > 0){
    1261              :                 sh.assign_subset(g.begin<ConstrainingTriangle>(), g.end<ConstrainingTriangle>(), subsetInd);
    1262            0 :                 sh.subset_info(subsetInd++).name = "ConstrainingTriangle";
    1263              :         }
    1264              : 
    1265            0 :         if(g.num<ConstrainedTriangle>() > 0){
    1266              :                 sh.assign_subset(g.begin<ConstrainedTriangle>(), g.end<ConstrainedTriangle>(), subsetInd);
    1267            0 :                 sh.subset_info(subsetInd++).name = "ConstrainedTriangle";
    1268              :         }
    1269              : 
    1270            0 :         if(g.num<Quadrilateral>() > 0){
    1271              :                 sh.assign_subset(g.begin<Quadrilateral>(), g.end<Quadrilateral>(), subsetInd);
    1272            0 :                 sh.subset_info(subsetInd++).name = "Quadrilateral";
    1273              :         }
    1274              : 
    1275            0 :         if(g.num<ConstrainingQuadrilateral>() > 0){
    1276              :                 sh.assign_subset(g.begin<ConstrainingQuadrilateral>(), g.end<ConstrainingQuadrilateral>(), subsetInd);
    1277            0 :                 sh.subset_info(subsetInd++).name = "ConstrainingQuadrilateral";
    1278              :         }
    1279              : 
    1280            0 :         if(g.num<ConstrainedQuadrilateral>() > 0){
    1281              :                 sh.assign_subset(g.begin<ConstrainedQuadrilateral>(), g.end<ConstrainedQuadrilateral>(), subsetInd);
    1282            0 :                 sh.subset_info(subsetInd++).name = "ConstrainedQuadrilateral";
    1283              :         }
    1284              : 
    1285            0 :         if(g.num<Tetrahedron>() > 0){
    1286              :                 sh.assign_subset(g.begin<Tetrahedron>(), g.end<Tetrahedron>(), subsetInd);
    1287            0 :                 sh.subset_info(subsetInd++).name = "Tetrahedron";
    1288              :         }
    1289              : 
    1290            0 :         if(g.num<Pyramid>() > 0){
    1291              :                 sh.assign_subset(g.begin<Pyramid>(), g.end<Pyramid>(), subsetInd);
    1292            0 :                 sh.subset_info(subsetInd++).name = "Pyramid";
    1293              :         }
    1294              : 
    1295            0 :         if(g.num<Prism>() > 0){
    1296              :                 sh.assign_subset(g.begin<Prism>(), g.end<Prism>(), subsetInd);
    1297            0 :                 sh.subset_info(subsetInd++).name = "Prism";
    1298              :         }
    1299              : 
    1300            0 :         if(g.num<Hexahedron>() > 0){
    1301              :                 sh.assign_subset(g.begin<Hexahedron>(), g.end<Hexahedron>(), subsetInd);
    1302            0 :                 sh.subset_info(subsetInd++).name = "Hexahedron";
    1303              :         }
    1304              : 
    1305            0 :         if(g.num<Octahedron>() > 0){
    1306              :                 sh.assign_subset(g.begin<Octahedron>(), g.end<Octahedron>(), subsetInd);
    1307            0 :                 sh.subset_info(subsetInd++).name = "Octahedron";
    1308              :         }
    1309            0 : }
    1310              : 
    1311              : template <class TElem>
    1312              : static char GetSmallestLocalSubsetDimension(
    1313              :                                 typename Grid::traits<TElem>::secure_container& nbrs,
    1314              :                                 MultiElementAttachmentAccessor<AChar>& aaDim)
    1315              : {
    1316              :         int d = -1;
    1317            0 :         for(size_t i = 0; i < nbrs.size(); ++i){
    1318              :                 TElem* e = nbrs[i];
    1319            0 :                 char ed = aaDim[e];
    1320            0 :                 if((ed != -1 ) && ((d == -1) || (ed < d)))
    1321            0 :                         d = ed;
    1322              :         }
    1323            0 :         return d;
    1324              : }
    1325              : 
    1326              : template <class TElem>
    1327            0 : static bool NbrIsInSubset(
    1328              :                                 ISubsetHandler& sh,
    1329              :                                 typename Grid::traits<TElem>::secure_container& nbrs,
    1330              :                                 int si)
    1331              : {
    1332            0 :         for(size_t i = 0; i < nbrs.size(); ++i){
    1333            0 :                 if(sh.get_subset_index(nbrs[i]) == si)
    1334              :                         return true;
    1335              :         }
    1336              :         return false;
    1337              : }
    1338              : 
    1339            0 : void ComputeLocalSubsetDimensions(
    1340              :                 ISubsetHandler& sh, 
    1341              :                 AChar aDimension,
    1342              :                 bool includeUnassigned)
    1343              : {
    1344            0 :         UG_COND_THROW(!sh.grid(), "The subset-handler has to operate on a grid!");
    1345            0 :         Grid& grid = *sh.grid();
    1346            0 :         grid.attach_to_all(aDimension);
    1347              :         MultiElementAttachmentAccessor<AChar> aaDim(grid, aDimension, true, true, true, true);
    1348              : 
    1349              : 
    1350            0 :         for(VolumeIterator ivol = grid.begin<Volume>(); ivol != grid.end<Volume>(); ++ivol){
    1351            0 :                 if(sh.get_subset_index(*ivol) == -1)
    1352            0 :                         aaDim[*ivol] = -1;
    1353              :                 else
    1354            0 :                         aaDim[*ivol] = 3;
    1355              :         }
    1356              : 
    1357              :         Grid::volume_traits::secure_container vols;
    1358            0 :         for(FaceIterator iface = grid.begin<Face>(); iface != grid.end<Face>(); ++iface){
    1359              :                 Face* f = *iface;
    1360              :                 int si = sh.get_subset_index(f);
    1361            0 :                 if(si == -1){
    1362            0 :                         if(includeUnassigned){
    1363              :                                 grid.associated_elements(vols, f);
    1364            0 :                                 aaDim[f] = GetSmallestLocalSubsetDimension<Volume>(vols, aaDim);
    1365              :                         }
    1366              :                         else
    1367            0 :                                 aaDim[f] = -1;
    1368              :                 }
    1369              :                 else{
    1370            0 :                         aaDim[f] = 2;
    1371              :                         grid.associated_elements(vols, f);
    1372            0 :                         if(NbrIsInSubset<Volume>(sh, vols, si))
    1373            0 :                                 aaDim[f] = 3;
    1374              :                 }
    1375              :         }
    1376              : 
    1377              :         Grid::face_traits::secure_container faces;
    1378            0 :         for(EdgeIterator iedge = grid.begin<Edge>(); iedge != grid.end<Edge>(); ++iedge){
    1379              :                 Edge* e = *iedge;
    1380              :                 int si = sh.get_subset_index(e);
    1381            0 :                 if(si == -1){
    1382            0 :                         if(includeUnassigned){
    1383              :                                 grid.associated_elements(faces, e);
    1384            0 :                                 aaDim[e] = GetSmallestLocalSubsetDimension<Face>(faces, aaDim);
    1385              :                         }
    1386              :                         else
    1387            0 :                                 aaDim[e] = -1;
    1388              :                 }
    1389              :                 else{
    1390            0 :                         aaDim[e] = 1;
    1391              :                         grid.associated_elements(vols, e);
    1392            0 :                         if(NbrIsInSubset<Volume>(sh, vols, si))
    1393            0 :                                 aaDim[e] = 3;
    1394              :                         else{
    1395              :                                 grid.associated_elements(faces, e);
    1396            0 :                                 if(NbrIsInSubset<Face>(sh, faces, si))
    1397            0 :                                         aaDim[e] = 2;
    1398              :                         }
    1399              :                 }
    1400              :         }
    1401              : 
    1402              :         Grid::edge_traits::secure_container edges;
    1403            0 :         for(VertexIterator ivrt = grid.begin<Vertex>(); ivrt != grid.end<Vertex>(); ++ivrt){
    1404              :                 Vertex* v = *ivrt;
    1405              :                 int si = sh.get_subset_index(v);
    1406            0 :                 if(si == -1){
    1407            0 :                         if(includeUnassigned){
    1408              :                                 grid.associated_elements(edges, v);
    1409            0 :                                 aaDim[v] = GetSmallestLocalSubsetDimension<Edge>(edges, aaDim);
    1410              :                         }
    1411              :                         else
    1412            0 :                                 aaDim[v] = -1;
    1413              :                 }
    1414              :                 else{
    1415            0 :                         aaDim[v] = 0;
    1416              :                         grid.associated_elements(vols, v);
    1417            0 :                         if(NbrIsInSubset<Volume>(sh, vols, si))
    1418            0 :                                 aaDim[v] = 3;
    1419              :                         else{
    1420              :                                 grid.associated_elements(faces, v);
    1421            0 :                                 if(NbrIsInSubset<Face>(sh, faces, si))
    1422            0 :                                         aaDim[v] = 2;
    1423              :                                 else{
    1424              :                                         grid.associated_elements(edges, v);
    1425            0 :                                         if(NbrIsInSubset<Edge>(sh, edges, si))
    1426            0 :                                                 aaDim[v] = 1;
    1427              :                                 }
    1428              :                         }
    1429              :                 }
    1430              :         }
    1431            0 : }
    1432              : 
    1433              : }//     end of namespace
    1434              : 
        

Generated by: LCOV version 2.0-1