X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fgraphlayout%2Fgraphlayout.cpp;h=60cdab8146c6490e07e810a1ca915e8385a0a243;hb=8b9a820756fdf348239872236be2257f854e094a;hp=9828e22fe6f0d3a2dd22946b2f06f4ae5a00016c;hpb=0e39cdf0cc3195b77fa0effca0e2b07355fe1c0b;p=inkscape.git diff --git a/src/graphlayout/graphlayout.cpp b/src/graphlayout/graphlayout.cpp index 9828e22fe..60cdab814 100644 --- a/src/graphlayout/graphlayout.cpp +++ b/src/graphlayout/graphlayout.cpp @@ -3,43 +3,94 @@ */ /* * Authors: -* Tim Dwyer +* Tim Dwyer * * Copyright (C) 2005 Authors * * Released under GNU GPL. Read the file 'COPYING' for more information. */ -#include "graphlayout/graphlayout.h" #include #include +#include +#include +#include +#include +#include +#include -#ifdef HAVE_BOOST_GRAPH_LIB +#include "desktop.h" +#include "inkscape.h" +#include "sp-namedview.h" +#include "util/glib-list-iterators.h" +#include "graphlayout/graphlayout.h" +#include "sp-path.h" #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 -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "libavoid/geomtypes.h" +#include "libcola/cola.h" +#include "libvpsc/generate-constraints.h" +#include "prefs-utils.h" -using namespace boost; -// create a typedef for the Graph type -typedef adjacency_list > Graph; -typedef property_map::type WeightMap; -typedef graph_traits::vertex_descriptor Vertex; -typedef std::vector > PositionVec; -typedef iterator_property_map::type> PositionMap; -#endif // HAVE_BOOST_GRAPH_LIB +using namespace std; +using namespace cola; +using namespace vpsc; +/** + * Returns true if item is a connector + */ +bool isConnector(SPItem const *const i) { + SPPath *path = NULL; + if(SP_IS_PATH(i)) { + path = SP_PATH(i); + } + return path && path->connEndPair.isAutoRoutingConn(); +} + +struct CheckProgress : TestConvergence { + CheckProgress(double d,unsigned i,list& + selected,vector& rs,map& nodelookup) : + TestConvergence(d,i), selected(selected), rs(rs), nodelookup(nodelookup) {} + bool operator()(double new_stress, double* X, double* Y) { + /* This is where, if we wanted to animate the layout, we would need to update + * the positions of all objects and redraw the canvas and maybe sleep a bit + cout << "stress="<namedview->connector_spacing+0.1; - std::map nodelookup; - for (std::list::iterator it(selected.begin()); - it != selected.end(); - ++it) + map nodelookup; + vector rs; + vector es; + for (list::iterator i(selected.begin()); + i != selected.end(); + ++i) { - SPItem *u=*it; - std::cout<<"id:"<id<id,"path",4)) { - nodelookup[u->id]=add_vertex(g); - } + SPItem *u=*i; + boost::optional const item_box(sp_item_bbox_desktop(u)); + if(item_box) { + NR::Point ll(item_box->min()); + NR::Point ur(item_box->max()); + nodelookup[u->id]=rs.size(); + rs.push_back(new Rectangle(ll[0]-spacing,ur[0]+spacing, + ll[1]-spacing,ur[1]+spacing)); + } else { + // I'm not actually sure if it's possible for something with a + // NULL item-box to be attached to a connector in which case we + // should never get to here... but if such a null box can occur it's + // probably pretty safe to simply ignore + //fprintf(stderr,"NULL item_box found in graphlayout, ignoring!\n"); + } } - WeightMap weightmap=get(edge_weight, g); - std::cout<<"Added vertices: Graph has |V|="<::iterator it(selected.begin()); - it != selected.end(); - ++it) + SimpleConstraints scx,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")) { + directed = true; + } + if (overlaps_str && !strcmp(overlaps_str, "true")) { + avoid_overlaps = true; + } + + for (list::iterator i(selected.begin()); + i != selected.end(); + ++i) { - using NR::X; using NR::Y; - SPItem *itu=*it; - Vertex u=nodelookup[itu->id]; - GSList *nlist=itu->avoidRef->getAttachedConnectors(Avoid::ConnRef::runningFrom); - std::list neighbours; - neighbours.insert >(neighbours.end(),nlist,NULL); - std::cout<<" Node "<id<<" has "<::iterator ne(neighbours.begin()); - ne != neighbours.end(); - ++ne) { - - SPItem *itv=*ne; - std::cout<<"neighbour: "<id<id]; - std::cout<<" Neighbour: "<::iterator i=nodelookup.find(iu->id); + if(i==nodelookup.end()) { + continue; + } + unsigned u=i->second; + GSList *nlist=iu->avoidRef->getAttachedConnectors(Avoid::runningFrom); + list connectors; + + connectors.insert >(connectors.end(),nlist,NULL); + for (list::iterator j(connectors.begin()); + j != connectors.end(); + ++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]; + } + + if (iv == NULL) { + // The connector is not attached to anything at the + // other end so we should just ignore it. + continue; + } + + // If iv not in nodelookup we again treat the connector + // as disconnected and continue + map::iterator v_pair=nodelookup.find(iv->id); + if(v_pair!=nodelookup.end()) { + unsigned v=v_pair->second; + //cout << "Edge: (" << u <<","<style->marker[SP_MARKER_LOC_END].set) { + if(directed && strcmp(conn->style->marker[SP_MARKER_LOC_END].value,"none")) { + scy.push_back(new SimpleConstraint(v, u, + (ideal_connector_length * directed_edge_height_modifier))); + } + } + } + } if(nlist) { g_slist_free(nlist); } - NR::Rect const item_box(sp_item_bbox_desktop(*it)); - - NR::Point ll(item_box.min()); - minX=std::min(ll[0],minX); - minY=std::min(ll[1],minY); - NR::Point ur(item_box.max()); - maxX=std::max(ur[0],maxX); - maxY=std::max(ur[1],maxY); } - double width=maxX-minX; - double height=maxY-minY; - std::cout<<"Graph has |V|="<id]].x, - minY+height/2.0+position[nodelookup[u->id]].y); - sp_item_move_rel(u, NR::translate(dest - curr)); + if(!isConnector(u)) { + map::iterator i=nodelookup.find(u->id); + if(i!=nodelookup.end()) { + Rectangle* r=rs[i->second]; + boost::optional item_box(sp_item_bbox_desktop(u)); + if(item_box) { + NR::Point const curr(item_box->midpoint()); + NR::Point const dest(r->getCentreX(),r->getCentreY()); + sp_item_move_rel(u, NR::translate(dest - curr)); + } + } } } -#else - std::cout<<"Connector network layout not available! Install boost graph library and recompile to enable."<