--- d:/_xxx/Comp/intern/opensg/Source/System/GraphOp/OSGDotFileGeneratorGraphOp.cpp	2013-10-08 14:45:02.358968200 +0200
+++ h:/Content/Work/CADdy++/graphicengine/2013_10_13/opensg/Source/System/GraphOp/OSGDotFileGeneratorGraphOp.cpp	2013-10-12 13:06:18.947255400 +0200
@@ -39,7 +39,8 @@
 #include <sstream>
 #include <boost/foreach.hpp>
 
-#include <OSGNameAttachment.h>
+#include "OSGNameAttachment.h"
+#include "OSGContainerCollection.h"
 #include "OSGDotFileGeneratorGraphOp.h"
 #include "OSGGraphOpFactory.h"
 #include "OSGGroup.h"
@@ -173,7 +174,8 @@
     _usedColors(),
     _suppressed(),
     _suppressed_derived(),
-    _dotted_edges()
+    _dotted_edges(),
+    _set_obj_ids()
 {
     // nothing to do
 }
@@ -605,6 +607,8 @@
 
             CloseGroup();
         }
+
+        traverse(subTreeRoot);
     }
 }
 
@@ -789,16 +793,32 @@
 
                 if(att != NULL)
                 {
-//                    FieldContainerType& attType = att->getType();
-
                     if (_no_name_attachments && 
                         Name::getClassType().getGroupId() == att->getGroupId())
                     {
                         continue;
                     }
 
+                    if (ContainerCollection::getClassType().getGroupId() == att->getGroupId())
+                    {
+                        ContainerCollectionUnrecPtr collection = dynamic_pointer_cast<ContainerCollection>(att);
+                        if (collection) 
+                        {
+                            const MFUnrecFieldContainerPtr* fieldCont = collection->getMFContainers();
+                            MFUnrecFieldContainerPtr::const_iterator iter = fieldCont->begin();
+                            MFUnrecFieldContainerPtr::const_iterator end  = fieldCont->end();
+                            for (; iter != end; ++iter)
+                            {
+                                // ToDo: Currently only Nodes are handled!
+                                // Note: Endless loop might be possible?
+                                Node* node = dynamic_cast<Node*>(*iter);
+                                if (node)
+                                    traverse(node);
+                            }
+                        }
+                    }
+
                     flag = true;
-                    break;
                 }
             }
 
@@ -815,8 +835,6 @@
                 AttachmentUnrecPtr att = mapIt->second;
                 if(att != NULL)
                 {
-//                    FieldContainerType& attType = att->getType();
-
                     if(_no_name_attachments && 
                        Name::getClassType().getGroupId() == att->getGroupId())
                     {
@@ -827,6 +845,27 @@
 
                     DefineAttachment(attachment_info);
                     DefineAttachmentEdge(info, attachment_info);
+
+                    if (ContainerCollection::getClassType().getGroupId() == att->getGroupId())
+                    {
+                        ContainerCollectionUnrecPtr collection = dynamic_pointer_cast<ContainerCollection>(att);
+                        if (collection) 
+                        {
+                            const MFUnrecFieldContainerPtr* fieldCont = collection->getMFContainers();
+                            MFUnrecFieldContainerPtr::const_iterator iter = fieldCont->begin();
+                            MFUnrecFieldContainerPtr::const_iterator end  = fieldCont->end();
+                            for (; iter != end; ++iter)
+                            {
+                                // ToDo: Currently only Nodes are handled!
+                                // Note: Endless loop might be possible?
+                                Node* node = dynamic_cast<Node*>(*iter);
+                                if (node) {
+                                    const Info &node_info = NodeInfo(node);
+                                    DefineHoldingEdge(attachment_info, node_info);
+                                }
+                            }
+                        }
+                    }
                 }
             }
 
@@ -869,6 +908,7 @@
         info.name    = name.str();
         info.label   = label.str();
         info.id      = node->getTypeName();
+        info.obj_id  = node;
         
         return _mapInfo.insert(
             MapInfoT::value_type(node, info)).first->second;
@@ -904,6 +944,7 @@
         info.name    = name.str();
         info.label   = label.str();
         info.id      = core_name;
+        info.obj_id  = core;
         
         Light *light = dynamic_cast<Light*>(core);
 
@@ -945,6 +986,7 @@
         info.name    = name.str();
         info.label   = label.str();
         info.id      = attachment_name;
+        info.obj_id  = att;
         
         return _mapInfo.insert(
             MapInfoT::value_type(att, info)).first->second;
@@ -980,6 +1022,7 @@
         info.name    = name.str();
         info.label   = label.str();
         info.id      = material_name;
+        info.obj_id  = material;
         
         return _mapInfo.insert(
             MapInfoT::value_type(material, info)).first->second;
@@ -1011,6 +1054,7 @@
         info.name    = name.str();
         info.label   = label.str();
         info.id      = "Matrix";
+        info.obj_id  = handler;
     
         return _mapInfo.insert(
             MapInfoT::value_type(handler, info)).first->second;
@@ -1032,6 +1076,7 @@
     info.name    = name.str();
     info.label   = label.str();
     info.id      = "Etcetera";
+    info.obj_id  = 0;
     
     return info;
 }
@@ -1062,6 +1107,7 @@
         info.name    = name.str();
         info.label   = label.str();
         info.id      = "Image";
+        info.obj_id  = image;
         
         return _mapInfo.insert(
             MapInfoT::value_type(image, info)).first->second;
@@ -1097,6 +1143,7 @@
         info.name    = name.str();
         info.label   = label.str();
         info.id      = chunk_name;
+        info.obj_id  = chunk;
         
         return _mapInfo.insert(
             MapInfoT::value_type(chunk, info)).first->second;
@@ -1132,6 +1179,7 @@
         info.name    = name.str();
         info.label   = label.str();
         info.id      = property_name+context;
+        info.obj_id  = property;
         
         return _mapInfo.insert(
             MapInfoT::value_type(property, info)).first->second;
@@ -1167,6 +1215,7 @@
         info.name    = name.str();
         info.label   = label.str();
         info.id      = property_name+context;
+        info.obj_id  = property;
         
         return _mapInfo.insert(
             MapInfoT::value_type(property, info)).first->second;
@@ -1180,6 +1229,18 @@
     return iter != _mapInfo.end();
 }
 
+bool DotFileGeneratorGraphOp::hasEdge(const Info& src, const Info& dst)
+{
+    PairObjIdsT p = std::make_pair(src.obj_id, dst.obj_id);
+
+    if (_set_obj_ids.find(p) == _set_obj_ids.end()) 
+    {
+        _set_obj_ids.insert(p);
+        return false;
+    } else
+        return true;
+}
+
 std::ofstream &DotFileGeneratorGraphOp::initialize()
 {
     if(!_spStream) 
@@ -1473,6 +1534,8 @@
 void DotFileGeneratorGraphOp::DefineNodeEdge(const Info &parent_info, 
                                              const Info &node_info  )
 {
+    if (hasEdge(parent_info, node_info)) return;
+
     std::ofstream &stream = initialize();
     
     stream << space()
@@ -1490,6 +1553,8 @@
 void DotFileGeneratorGraphOp::DefineCoreEdge(const Info &node_info, 
                                              const Info &core_info)
 {
+    if (hasEdge(node_info, core_info)) return;
+
     std::ofstream &stream = initialize();
     
     stream << space()
@@ -1504,15 +1569,36 @@
            << std::endl;
 }
 
+void DotFileGeneratorGraphOp::DefineHoldingEdge(const Info &src_info, 
+                                                const Info &dst_info)
+{
+    if (hasEdge(src_info, dst_info)) return;
+
+    std::ofstream &stream = initialize();
+    
+    stream << space()
+           << src_info.name << " "
+           << "->" << " "
+           << dst_info.name << " "
+           << "["
+           << "dir=both" << ","
+           << "arrowtail=diamond" << ","
+           << "weight=2"
+           << "];"
+           << std::endl;
+}
+
 void DotFileGeneratorGraphOp::DefineAttachmentEdge(const Info &node_info, 
-                                                   const Info &core_info)
+                                                   const Info &att_info)
 {
+    if (hasEdge(node_info, att_info)) return;
+
     std::ofstream &stream = initialize();
     
     stream << space()
            << node_info.name << " "
            << "->" << " "
-           << core_info.name << " "
+           << att_info.name << " "
            << "["
            << "style=dotted" << ","
            << "arrowhead=vee" << ","
@@ -1527,6 +1613,8 @@
           bool         constraint, 
           std::string  attribute )
 {
+    if (hasEdge(src_info, dst_info)) return;
+
     std::ofstream &stream = initialize();
     
     stream << space()
@@ -1553,6 +1641,8 @@
           bool         constraint, 
           std::string  attribute )
 {
+    if (hasEdge(src_info, dst_info)) return;
+
     std::ofstream &stream = initialize();
     
     stream << space()
