Code

- Connectors with end-markers now constrained to point downwards in graph layout
[inkscape.git] / src / graphlayout / graphlayout.cpp
index ac2d5429f4ae1518e50d73706d01567b37f12a88..432f3c942c58518f9452c50c4fb7f5048af170f1 100644 (file)
@@ -22,6 +22,7 @@
 #include "sp-item.h"
 #include "sp-item-transform.h"
 #include "sp-conn-end-pair.h"
+#include "style.h"
 #include "conn-avoid-ref.h"
 #include "libavoid/connector.h"
 #include "libavoid/geomtypes.h"
@@ -31,6 +32,7 @@
 
 using namespace std;
 using namespace cola;
+using namespace vpsc;
 
 /**
  * Returns true if item is a connector
@@ -90,9 +92,28 @@ void graphlayout(GSList const *const items) {
                minX=min(ll[0],minX); minY=min(ll[1],minY);
                maxX=max(ur[0],maxX); maxY=max(ur[1],maxY);
                nodelookup[u->id]=rs.size();
+               cout << "Node " << rs.size() << endl;
                rs.push_back(new Rectangle(ll[0],ur[0],ll[1],ur[1]));
        }
 
+       SimpleConstraints scy;
+       double ideal_connector_length = prefs_get_double_attribute("tools.connector","length",100);
+       double directed_edge_height_modifier = 1.0;
+       gchar const *directed_str = NULL, *overlaps_str = NULL;
+       directed_str = prefs_get_string_attribute("tools.connector",
+                       "directedlayout");
+       overlaps_str = prefs_get_string_attribute("tools.connector",
+                       "avoidoverlaplayout");
+       bool avoid_overlaps = false;
+       bool directed = false;
+        if (directed_str && !strcmp(directed_str, "true")) {
+            cout << "Directed layout requested.\n";
+           directed = true;
+       }
+        if (overlaps_str && !strcmp(overlaps_str, "true")) {
+            cout << "Avoid overlaps requested.\n";
+           avoid_overlaps = true;
+       }
 
        for (list<SPItem *>::iterator i(selected.begin());
                i != selected.end();
@@ -100,17 +121,38 @@ void graphlayout(GSList const *const items) {
        {
                SPItem *iu=*i;
                unsigned u=nodelookup[iu->id];
-               GSList *nlist=iu->avoidRef->getAttachedShapes(Avoid::runningFrom);
-               list<SPItem *> neighbours;
-               neighbours.insert<GSListConstIterator<SPItem *> >(neighbours.end(),nlist,NULL);
-               for (list<SPItem *>::iterator j(neighbours.begin());
-                               j != neighbours.end();
+               GSList *nlist=iu->avoidRef->getAttachedConnectors(Avoid::runningFrom);
+               list<SPItem *> connectors;
+               
+               connectors.insert<GSListConstIterator<SPItem *> >(connectors.end(),nlist,NULL);
+               for (list<SPItem *>::iterator j(connectors.begin());
+                               j != connectors.end();
                                ++j) {
-                       
-                       SPItem *iv=*j;
+                       SPItem *conn=*j;
+                       SPItem *iv;
+                       SPItem *items[2];
+                       assert(isConnector(conn));
+                       SP_PATH(conn)->connEndPair.getAttachedItems(items);
+                       if(items[0]==iu) {
+                               iv=items[1];
+                       } else {
+                               iv=items[0];
+                       }
+               
                        // What do we do if iv not in nodelookup?!?!
-                       unsigned v=nodelookup[iv->id];
-                       es.push_back(make_pair(u,v));
+                       map<string,unsigned>::iterator v_pair=nodelookup.find(iv->id);
+                       if(v_pair!=nodelookup.end()) {
+                               unsigned v=v_pair->second;
+                               cout << "Edge: (" << u <<","<<v<<")"<<endl;
+                               es.push_back(make_pair(u,v));
+                               if(conn->style->marker[SP_MARKER_LOC_END].set) {
+                                       if(directed && strcmp(conn->style->marker[SP_MARKER_LOC_END].value,"none")) {
+                                               cout << conn->style->marker[SP_MARKER_LOC_END].value << endl;
+                                               scy.push_back(new SimpleConstraint(v, u, 
+                                    (ideal_connector_length * directed_edge_height_modifier)));
+                                       }
+                               }
+                       }
                }
                if(nlist) {
                        g_slist_free(nlist);
@@ -122,24 +164,9 @@ void graphlayout(GSList const *const items) {
        double eweights[E];
        fill(eweights,eweights+E,1);
 
-       ConstrainedMajorizationLayout alg(rs,es,eweights,
-               prefs_get_double_attribute("tools.connector","length",100));
-       gchar const *directed = NULL, *overlaps = NULL;
-       directed = prefs_get_string_attribute("tools.connector",
-                       "directedlayout");
-       overlaps = prefs_get_string_attribute("tools.connector",
-                       "avoidoverlaplayout");
-       bool avoid_overlaps = false;
-        if (directed && !strcmp(directed, "true")) {
-            cout << "Directed layout requested, but not yet implemented\n";
-            cout << "  because we haven't coded cyclic removal alg...\n";
-       }
-        if (overlaps && !strcmp(overlaps, "true")) {
-            cout << "Avoid overlaps requested.\n";
-           avoid_overlaps = true;
-       }
+       ConstrainedMajorizationLayout alg(rs,es,eweights,ideal_connector_length);
        alg.setupConstraints(NULL,NULL,avoid_overlaps,
-                       NULL,NULL,NULL,NULL,NULL,NULL);
+                       NULL,NULL,NULL,&scy,NULL,NULL);
        alg.run();
        
        for (list<SPItem *>::iterator it(selected.begin());
@@ -156,3 +183,5 @@ void graphlayout(GSList const *const items) {
                }
        }
 }
+// vim: set cindent 
+// vim: ts=4 sw=4 et tw=0 wm=0