From 6c6eebe0f8f5ba0452a1083d99d0dc212fa937dd Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Thu, 27 Nov 2014 18:40:12 +0000
Subject: [PATCH] fix duplicate points + generate to edges

---
 Plugin/MeshSubEntities.cpp         | 86 +++++++++++++++++++++---------
 Plugin/MeshSubEntities.h           |  2 +-
 contrib/mobile/iOS/Onelab/Utils.mm | 16 +++---
 3 files changed, 70 insertions(+), 34 deletions(-)

diff --git a/Plugin/MeshSubEntities.cpp b/Plugin/MeshSubEntities.cpp
index 95c609a1df..52b84bef71 100644
--- a/Plugin/MeshSubEntities.cpp
+++ b/Plugin/MeshSubEntities.cpp
@@ -58,16 +58,12 @@ PView *GMSH_MeshSubEntitiesPlugin::execute(PView *view)
   int outputdim = (int)MeshSubEntitiesOptions_Number[2].def;
   int outphysical = (int)MeshSubEntitiesOptions_Number[3].def;
 
-  if(inputdim < 0 || inputdim > 3 || outputdim > inputdim){
+  if(inputdim < 0 || inputdim > 3 || outputdim < 0 || outputdim > 3 ||
+     outputdim > inputdim){
     Msg::Error("Bad dimensions");
     return view;
   }
 
-  if(outputdim != 0){
-    Msg::Error("Only vertices coded for now");
-    return view;
-  }
-
   GModel *m = GModel::current();
   std::map<int, std::vector<GEntity*> > groups[4];
   m->getPhysicalGroups(groups);
@@ -84,30 +80,70 @@ PView *GMSH_MeshSubEntitiesPlugin::execute(PView *view)
     for(unsigned int j = 0; j < entities[i]->getNumMeshElements(); j++)
       elements.push_back(entities[i]->getMeshElement(j));
 
-  // FIXME: generalize this to outputdim != 0 !
-  std::set<MVertex*> vertices;
-  for(unsigned int i = 0; i < elements.size(); i++){
-    for(int j = 0; j < elements[i]->getNumVertices(); j++){
-      MVertex *v = elements[i]->getVertex(j);
-      vertices.insert(v);
+  if(outputdim == 0){ // create point elements for mesh vertices
+    std::set<MVertex*> vertices;
+    for(unsigned int i = 0; i < elements.size(); i++){
+      for(int j = 0; j < elements[i]->getNumVertices(); j++){
+        MVertex *v = elements[i]->getVertex(j);
+        vertices.insert(v);
+      }
     }
+    for(std::set<MVertex*>::const_iterator it = vertices.begin();
+        it != vertices.end(); ++it){
+      MVertex *v = *it;
+      GVertex *gv = 0;
+      if(v->onWhat() && v->onWhat()->dim() == 0){
+        gv = (GVertex*)v->onWhat();
+      }
+      else{
+        gv = new discreteVertex(m, m->getMaxElementaryNumber(0) + 1);
+        v->setEntity(gv);
+        m->add(gv);
+      }
+      gv->physicals.push_back(outphysical);
+      if(gv->points.empty())
+        gv->points.push_back(new MPoint(v));
+    }
+    m->pruneMeshVertexAssociations();
   }
-  for(std::set<MVertex*>::const_iterator it = vertices.begin(); 
-      it != vertices.end(); ++it){
-    MVertex *v = *it;
-    GVertex *gv = 0;
-    if(v->onWhat() && v->onWhat()->dim() == 0){
-      gv = (GVertex*)v->onWhat();
+  else if(outputdim == 1){ // create line elements for mesh edges
+    std::set<MEdge, Less_Edge> edges;
+    for(unsigned int i = 0; i < elements.size(); i++){
+      for(int j = 0; j < elements[i]->getNumEdges(); j++){
+        MEdge e = elements[i]->getEdge(j);
+        edges.insert(e);
+      }
     }
-    else{
-      gv = new discreteVertex(m, m->getMaxElementaryNumber(0) + 1);
-      v->setEntity(gv);
-      m->add(gv);
+    for(std::set<MEdge, Less_Edge>::const_iterator it = edges.begin();
+        it != edges.end(); ++it){
+      const MEdge &e = *it;
+      GEdge *ge = 0;
+      MVertex *v0 = e.getVertex(0), *v1 = e.getVertex(1);
+      if(v0->onWhat() && v1->onWhat()){
+        if(v0->onWhat()->dim() == 1 &&
+           ((v1->onWhat()->dim() == 1 && v0->onWhat() == v1->onWhat()) ||
+             v1->onWhat()->dim() == 0))
+          ge = (GEdge*)v0->onWhat();
+        else if(v1->onWhat()->dim() == 1 &&
+                ((v0->onWhat()->dim() == 1 && v0->onWhat() == v1->onWhat()) ||
+                  v0->onWhat()->dim() == 0))
+          ge = (GEdge*)v1->onWhat();
+      }
+      if(!ge){
+        ge = new discreteEdge(m, m->getMaxElementaryNumber(1) + 1, 0, 0);
+        v0->setEntity(ge);
+        v1->setEntity(ge);
+        m->add(ge);
+      }
+      ge->physicals.push_back(outphysical);
+      if(ge->lines.empty())
+        ge->lines.push_back(new MLine(v0, v1));
     }
-    gv->physicals.push_back(outphysical);
-    gv->points.push_back(new MPoint(v));
   }
-  m->pruneMeshVertexAssociations();
+  else{
+    Msg::Error("Plugin(MeshSubEntities) not coded yet for output dim %d",
+               outputdim);
+  }
 
   CTX::instance()->mesh.changed = ENT_ALL;
 
diff --git a/Plugin/MeshSubEntities.h b/Plugin/MeshSubEntities.h
index a7484ff865..875eb9f40a 100644
--- a/Plugin/MeshSubEntities.h
+++ b/Plugin/MeshSubEntities.h
@@ -20,7 +20,7 @@ class GMSH_MeshSubEntitiesPlugin : public GMSH_PostPlugin
   std::string getName() const { return "MeshSubEntities"; }
   std::string getShortHelp() const
   {
-    return "Mesh entities generator";
+    return "Mesh subentities generator";
   }
   std::string getHelp() const;
   int getNbOptions() const;
diff --git a/contrib/mobile/iOS/Onelab/Utils.mm b/contrib/mobile/iOS/Onelab/Utils.mm
index c922f6513d..f76a002ff5 100644
--- a/contrib/mobile/iOS/Onelab/Utils.mm
+++ b/contrib/mobile/iOS/Onelab/Utils.mm
@@ -23,20 +23,20 @@
     NSError *error = nil;
     if (![[NSFileManager defaultManager] copyItemAtPath:modelSrc toPath:modelDst error:&error])
       NSLog(@"Error: %@", error);
-	else if(![[NSURL fileURLWithPath:modelDst] setResourceValue: [NSNumber numberWithBool: YES] forKey: NSURLIsExcludedFromBackupKey error: &error])
+    else if(![[NSURL fileURLWithPath:modelDst] setResourceValue: [NSNumber numberWithBool: YES] forKey: NSURLIsExcludedFromBackupKey error: &error])
       NSLog(@"Error %@", error);
   }
 }
 
 + (UIViewController *) traverseResponderChainForUIViewController:(UIView *)v
 {
-	id nextResponder = [v nextResponder];
-	if ([nextResponder isKindOfClass:[UIViewController class]])
-		return nextResponder;
-	else if ([nextResponder isKindOfClass:[UIView class]])
-		return [Utils traverseResponderChainForUIViewController:nextResponder];
-	else
-		return nil;
+  id nextResponder = [v nextResponder];
+  if ([nextResponder isKindOfClass:[UIViewController class]])
+    return nextResponder;
+  else if ([nextResponder isKindOfClass:[UIView class]])
+    return [Utils traverseResponderChainForUIViewController:nextResponder];
+  else
+    return nil;
 }
 
 @end
-- 
GitLab