diff --git a/Plugin/SpanningTree.cpp b/Plugin/SpanningTree.cpp
index 4323d6addac2411e147599290e35c9eb8e2a0454..d9b2f09d12ab43b0087f296fafac188760ddc7bf 100644
--- a/Plugin/SpanningTree.cpp
+++ b/Plugin/SpanningTree.cpp
@@ -4,57 +4,71 @@
 // issues on https://gitlab.onelab.info/gmsh/gmsh/issues.
 // Contributed by Nicolas Marsic.
 
+#include <sstream>
+#include <algorithm>
+
 #include "SpanningTree.h"
 #include "GModel.h"
 #include "MLine.h"
 #include "OS.h"
 
+using namespace std;
+
 StringXNumber SpanningTreeOptions_Number[] = {
-  {GMSH_FULLRC, "PhysicalGroup", NULL, -1},
-  {GMSH_FULLRC, "StartingOn", NULL, -1},
   {GMSH_FULLRC, "OutputPhysical", NULL, -1},
 };
 
+StringXString SpanningTreeOptions_String[] = {
+  {GMSH_FULLRC, "PhysicalVolumes",  NULL, ""},
+  {GMSH_FULLRC, "PhysicalSurfaces", NULL, ""},
+  {GMSH_FULLRC, "PhysicalCurves",   NULL, ""},
+};
+
 extern "C" {
-GMSH_Plugin *GMSH_RegisterSpanningTreePlugin(void)
-{
-  return new GMSH_SpanningTreePlugin();
-}
+  GMSH_Plugin *GMSH_RegisterSpanningTreePlugin(void)
+  {
+    return new GMSH_SpanningTreePlugin();
+  }
 }
 
 GMSH_SpanningTreePlugin::GMSH_SpanningTreePlugin(void) {}
 
-std::string GMSH_SpanningTreePlugin::getName(void) const
+string GMSH_SpanningTreePlugin::getName(void) const
 {
   return "SpanningTree";
 }
 
-std::string GMSH_SpanningTreePlugin::getShortHelp(void) const
+string GMSH_SpanningTreePlugin::getShortHelp(void) const
 {
   return "Builds a tree spanning every vertex of a mesh";
 }
 
-std::string GMSH_SpanningTreePlugin::getHelp(void) const
+string GMSH_SpanningTreePlugin::getHelp(void) const
 {
-  return "Plugin(SpanningTree) builds a tree spanning every vertex of a mesh.\n"
-         "Optionally, this tree can be built by starting on a specific part.\n"
-         "The generated tree is stored directly in the model.\n"
+  return "Plugin(SpanningTree) builds a tree spanning every vertex of a mesh "
+         "and stores it directly in the model.\n"
+         "The tree is constructed by starting first on the curves, "
+         "then on the surfaces and finally on the volumes.\n"
          "\n"
          "Parameters\n"
-         "- PhysicalGroup: physical group upon which the tree must be built "
-         "(-1 means the whole mesh).\n"
-         "- StartingOn: physical group used to start the tree construction "
-         "(-1 deactivates this feature).\n"
+         "- PhysicalVolumes: list of the physical volumes "
+         "upon which the tree must be built.\n"
+         "- PhysicalSurfaces: list of the physical surfaces "
+         "upon which the tree must be built.\n"
+         "- PhysicalCurves: list of the physical curves "
+          "upon which the tree must be built.\n"
          "- OutputPhysical: physical tag of the generated tree "
          "(-1 will select a new tag automatically).\n"
          "\n"
+         "Note - Lists must be comma separated integers "
+         "and spaces are ignored.\n"
          "Remark - This plugin does not overwrite a physical group."
          "Therefore, if an existing physical tag is used in OutputPhysical, "
          "the edges of the tree will be /added/ to the specified group.\n"
          "Limitation - Unknown behaviour with curved meshes.";
 }
 
-std::string GMSH_SpanningTreePlugin::getAuthor(void) const
+string GMSH_SpanningTreePlugin::getAuthor(void) const
 {
   return "N. Marsic";
 }
@@ -69,45 +83,66 @@ StringXNumber *GMSH_SpanningTreePlugin::getOption(int iopt)
   return &SpanningTreeOptions_Number[iopt];
 }
 
+int GMSH_SpanningTreePlugin::getNbOptionsStr() const
+{
+  return sizeof(SpanningTreeOptions_String) / sizeof(StringXString);
+}
+
+StringXString *GMSH_SpanningTreePlugin::getOptionStr(int iopt)
+{
+  return &SpanningTreeOptions_String[iopt];
+}
+
 void GMSH_SpanningTreePlugin::run(void)
 {
   // Get data
-  double time = Cpu();
-  int physical = (int)SpanningTreeOptions_Number[0].def;
-  int startOn = (int)SpanningTreeOptions_Number[1].def;
-  int output = (int)SpanningTreeOptions_Number[2].def;
+  double    time = Cpu();
+  int     output = (int)SpanningTreeOptions_Number[0].def;
+  string  volume =      SpanningTreeOptions_String[0].def;
+  string surface =      SpanningTreeOptions_String[1].def;
+  string   curve =      SpanningTreeOptions_String[2].def;
+
+  // Parse physical tags
+  vector<list<int> > physical(3);
+  curve   = parse(curve,   physical[0]);
+  surface = parse(surface, physical[1]);
+  volume  = parse(volume,  physical[2]);
+
+  // Dimensions
+  int dim[3] = {1, 2, 3};
 
   // Get model
   GModel *model = GModel::current();
 
-  // Get all elements in physical
-  ElementSet element;
-  getAllMElement(*model, physical, element);
-
-  // Get all elements in startOn (if defined)
-  ElementSet elementStartOn;
-  if(startOn >= 0) getAllMElement(*model, startOn, elementStartOn);
+  // Get all elements in physicals for each dimension
+  vector<ElementSet> element(3);
+  for(int i = 0; i < 3; i++)
+    for(list<int>::iterator j = physical[i].begin(); j!= physical[i].end(); j++)
+      getAllMElement(*model, *j, dim[i], element[i]);
 
   // Check if we have something
-  if(element.empty() && elementStartOn.empty()) {
-    Msg::Warning("No elements found in physcial %d: abording!", physical);
+  if(element[0].empty() && element[1].empty() && element[2].empty()) {
+    Msg::Warning("No elements found in the given physcials: abording!");
     return;
   }
 
-  // Get all edges from elements
-  EdgeSet edge;
-  getAllMEdge(element, edge);
+  // Display physicals (as [poorly] parsed) //
+  Msg::Info("--> PhysicalVolumes:  %s",  volume.c_str());
+  Msg::Info("--> PhysicalSurfaces: %s", surface.c_str());
+  Msg::Info("--> PhysicalCurves:   %s",   curve.c_str());
+  Msg::Info("--> OutputPhysical:   %d",  output);
 
-  // Get all edges from startOn (if defined)
-  EdgeSet edgeStartOn;
-  if(startOn >= 0) getAllMEdge(elementStartOn, edgeStartOn);
+  // Get all edges from elements for each dimension
+  vector<EdgeSet> edge(3);
+  for(int i = 0; i < 3; i++)
+    getAllMEdge(element[i], edge[i]);
 
-  // Build spanning tree and save into the model (begin with startOn if defined)
+  // Build spanning tree (in ascending dimension order) and save into the model
   DSU vertex(model->getNumMeshVertices());
   Tree tree;
-  if(startOn >= 0) spanningTree(edgeStartOn, vertex, tree);
+  for(int i = 0; i < 3; i++)
+    spanningTree(edge[i], vertex, tree);
 
-  spanningTree(edge, vertex, tree);
   addToModel(*model, tree, output);
 
   // Done
@@ -132,21 +167,48 @@ void GMSH_SpanningTreePlugin::spanningTree(EdgeSet &edge, DSU &vertex,
   }
 }
 
+string GMSH_SpanningTreePlugin::parse(string str, list<int>& physical)
+{
+  // Remove spaces //
+  str.erase(remove(str.begin(), str.end(), ' '), str.end());
+
+  // Replace commas by spaces //
+  replace(str.begin(), str.end(), ',', ' ');
+
+  // Init string stream //
+  stringstream stream;
+  stream << str;
+
+  // Parse stream for integers //
+  int    tag;
+  string tmp;
+  while(!stream.eof()){
+    stream >> tmp; // Take next 'word'
+    if(sscanf(tmp.c_str(), "%d", &tag) > 0)
+      physical.push_back(tag);
+  }
+
+  // Return modified string //
+  return str;
+}
+
 void GMSH_SpanningTreePlugin::getAllMElement(GModel &model, int physical,
-                                             ElementSet &element)
+                                             int dim, ElementSet &element)
 {
-  std::vector<GEntity *> entities;
+  std::map<int, std::vector<GEntity*> >            group;
+  std::map<int, std::vector<GEntity*> >::iterator entity;
 
-  if(physical == -1) { model.getEntities(entities, -1); }
-  else {
-    std::map<int, std::vector<GEntity *> > groups;
-    model.getPhysicalGroups(-1, groups);
-    entities = groups[physical];
-  }
+  // Get groups //
+  model.getPhysicalGroups(dim, group);
+
+  // Get entities, if any //
+  entity = group.find(physical);
+  if(entity == group.end())
+    return;
 
-  for(size_t i = 0; i < entities.size(); i++)
-    for(size_t j = 0; j < entities[i]->getNumMeshElements(); j++)
-      element.insert(entities[i]->getMeshElement(j));
+  for(size_t i = 0; i < entity->second.size(); i++)
+    for(size_t j = 0; j < entity->second[i]->getNumMeshElements(); j++)
+      element.insert(entity->second[i]->getMeshElement(j));
 }
 
 void GMSH_SpanningTreePlugin::getAllMEdge(ElementSet &element, EdgeSet &edge)
diff --git a/Plugin/SpanningTree.h b/Plugin/SpanningTree.h
index 2c6c1f5232e73cba5f2b86707b1b373982adb0dc..8d0467561d79023b77e118da57b70d6afd709f9b 100644
--- a/Plugin/SpanningTree.h
+++ b/Plugin/SpanningTree.h
@@ -25,10 +25,10 @@ private:
     std::vector<int> rank;
 
   public:
-    DSU(size_t n);
+     DSU(size_t n);
     ~DSU(void);
 
-    int find(int a);
+    int  find(int a);
     void join(int a, int b);
   };
 
@@ -37,9 +37,9 @@ private:
                     const std::pair<int, int> &b) const;
   };
 
-  typedef std::set<const MElement *, MElementPtrLessThan> ElementSet;
-  typedef std::set<std::pair<int, int>, Sort> EdgeSet;
-  typedef std::list<std::pair<int, int> > Tree;
+  typedef  std::set<const MElement *, MElementPtrLessThan> ElementSet;
+  typedef  std::set<std::pair<int, int>, Sort>             EdgeSet;
+  typedef std::list<std::pair<int, int> >                  Tree;
 
 public:
   GMSH_SpanningTreePlugin(void);
@@ -52,12 +52,17 @@ public:
   int getNbOptions(void) const;
   StringXNumber *getOption(int iopt);
 
+  int getNbOptionsStr() const;
+  StringXString *getOptionStr(int iopt);
+
   void run(void);
 
 private:
   static void spanningTree(EdgeSet &edge, DSU &vertex, Tree &tree);
 
-  static void getAllMElement(GModel &model, int physical, ElementSet &element);
+  static std::string parse(std::string str, std::list<int>& physical);
+  static void getAllMElement(GModel &model, int physical,
+                             int dim, ElementSet &element);
   static void getAllMEdge(ElementSet &element, EdgeSet &edge);
   static void addToModel(GModel &model, Tree &tree, int tag);