123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868 |
- #include "GraphPreProcessor.h"
- GraphPreProcessor::GraphPreProcessor()
- {
- }
- void GraphPreProcessor::toMaximalPlanar(SubGraph & gInputGraph, EdgeOrderType &oDummyEdges)
- {
- //CHANGE GRAPH FORMAT--------------------------------------------------------------------------------------
- //gInputGraph is a bidirectedS graph, whereas the algorithm to make it maximal planar accepts undirectedS graphs.
- //To map our graph to undirected one, we create a local undirected graph and copy the edges and vertices
- //in our graph to this local graph; and pass this to the algorithm.
- VertexDescriptor descVertexSource, descVertexTarget;
- EdgeIterator itrEdge, itrEdgeEnd;
- EdgeDescriptor descEdge;
- int iVertexSource, iVertexTarget, iNumVertices;
- BoostGraphWrapper graphWrapper;
- iNumVertices = boost::num_vertices(gInputGraph);
- GraphPreProcessor::graph g(iNumVertices); //create a local undirected graph with same no. of vertices
- LayoutUtility layoutUtility;
- // copy each edge one by one
- for(boost::tie(itrEdge, itrEdgeEnd) = edges(gInputGraph); itrEdge != itrEdgeEnd; itrEdge++)
- {
- descEdge = *itrEdge;
- descVertexSource = graphWrapper.getEdgeSource(descEdge, gInputGraph);
- descVertexTarget = graphWrapper.getEdgeTarget(descEdge, gInputGraph);
- iVertexSource = get(vertex_index, gInputGraph, descVertexSource);
- iVertexTarget = get(vertex_index, gInputGraph, descVertexTarget);
- add_edge(iVertexSource, iVertexTarget, g);
- }
- //Initialize the interior edge index
- layoutUtility.reinitializeEdgeIndices(g);
- //Test for planarity; compute the planar embedding as a side-effect
- typedef std::vector< graph_traits<graph>::edge_descriptor > vec_t;
- std::vector<vec_t> embedding(num_vertices(g));
- if (boyer_myrvold_planarity_test(boyer_myrvold_params::graph = g,
- boyer_myrvold_params::embedding = &embedding[0]))
- {
- //std::cout << "Input graph is planar1" << std::endl;
- }
- else
- {
- throw LayoutException("toMaximalPlanar",
- LayoutExceptionEnum::INVALID_GRAPH_TYPE,
- "inputGraph",
- "non-planar");
- //std::cout << "Input graph is not planar1" << std::endl;
- }
- //END------------------------------------------------------------------------------------------------------
- //MAKE MAXIMAL PLANAR--------------------------------------------------------------------------------------
- make_connected(g);
- // Re-initialize the edge index, since we just added a few edges
- layoutUtility.reinitializeEdgeIndices(g);
- //Test for planarity again; compute the planar embedding as a side-effect
- if (boyer_myrvold_planarity_test(boyer_myrvold_params::graph = g,
- boyer_myrvold_params::embedding = &embedding[0]))
- {
- //std::cout << "After calling make_connected, the graph is still planar" << std::endl;
- }
- else
- {
- throw LayoutException("toMaximalPlanar",
- LayoutExceptionEnum::INVALID_GRAPH_TYPE,
- "connectedGraph",
- "non-planar");
- //std::cout << "After calling make_connected, the graph is not planar" << std::endl;
- }
- make_biconnected_planar(g, &embedding[0]);
- // Re-initialize the edge index, since we just added a few edges
- layoutUtility.reinitializeEdgeIndices(g);
- //Test for planarity again; compute the planar embedding as a side-effect
- if (boyer_myrvold_planarity_test(boyer_myrvold_params::graph = g,
- boyer_myrvold_params::embedding = &embedding[0]))
- {
- //std::cout << "After calling make_biconnected, the graph is still planar" << std::endl;
- }
- else
- {
- throw LayoutException("toMaximalPlanar",
- LayoutExceptionEnum::INVALID_GRAPH_TYPE,
- "biconnectedGraph",
- "non-planar");
- //std::cout << "After calling make_biconnected, the graph is not planar" << std::endl;
- }
- make_maximal_planar(g, &embedding[0]);
- // Re-initialize the edge index, since we just added a few edges
- layoutUtility.reinitializeEdgeIndices(g);
- // Test for planarity one final time; compute the planar embedding as a side-effect
- if (boyer_myrvold_planarity_test(boyer_myrvold_params::graph = g,
- boyer_myrvold_params::embedding = &embedding[0]))
- {
- //std::cout << "After calling make_maximal_planar, the final graph is planar." << std::endl;
- }
- else
- {
- throw LayoutException("toMaximalPlanar",
- LayoutExceptionEnum::INVALID_GRAPH_TYPE,
- "maxPlanarGraph",
- "non-planar");
- //std::cout << "is not planar." << std::endl;
- }
- //END------------------------------------------------------------------------------------------------------
- //FIND EXTRA EDGES ADDED--------------------------------------------------------------------------------
- //add them to gInputGraph as well, and remember them as dummy edges
- graph_traits< graph >::edge_iterator itrUndirEdge, itrUndirEdgeEnd;
- graph_traits< graph >::edge_descriptor descUndirEdge;
- graph_traits< graph >::vertex_descriptor descUndirVertSource, descUndirVertTarget;
- bool bIsEdge;
- EdgeBoolPair pairEdgeBoolStoT, pairNewEdge;
- BoostGraphWrapper boostGraphWrapper;
- //for each edge in g:
- for(boost::tie(itrUndirEdge, itrUndirEdgeEnd) = edges(g); itrUndirEdge != itrUndirEdgeEnd; itrUndirEdge++)
- {
- //get edge descriptor for current edge (in g)
- descUndirEdge = *itrUndirEdge;
- //get its source and target vertices (in g)
- descUndirVertSource = source(descUndirEdge, g);
- descUndirVertTarget = target(descUndirEdge, g);
- //get indices of source and target (in g)
- iVertexSource = get(vertex_index, g, descUndirVertSource);
- iVertexTarget = get(vertex_index, g, descUndirVertTarget);
- //get corresponding vertices in gInputGraph
- descVertexSource = vertex(iVertexSource, gInputGraph);
- descVertexTarget = vertex(iVertexTarget, gInputGraph);
- //check if there's corresponding edge between these vertices in gInputGraph
- pairEdgeBoolStoT = lookup_edge(descVertexSource, descVertexTarget, gInputGraph);
- bIsEdge = pairEdgeBoolStoT.second;
- if(!bIsEdge)//if there isn't any edge, current edge is a dummy edge
- {
- //add an edge in gInputGraph
- pairNewEdge = boostGraphWrapper.addEdge(descVertexSource, descVertexTarget, gInputGraph);
- //remember the added edge
- LAYOUT_ASSERT(pairNewEdge.second,
- LayoutException("toMaximalPlanar",
- LayoutExceptionEnum::INVALID_OPERATION,
- "add_edge",
- "toMaximalPlanar"));
- oDummyEdges.push_back(pairNewEdge.first);
- }
- }
- //Initialize the interior edge index in input graph
- layoutUtility.reinitializeEdgeIndices(gInputGraph);
- //END------------------------------------------------------------------------------------------------------
- }
- void GraphPreProcessor::removeDummyEdges(SubGraph & gInputGraph, EdgeOrderType &oDummyEdges)
- {
- LayoutUtility layoutUtility;
- //for each DummyEdge
- for(size_t i = 0; i < oDummyEdges.size(); ++i)
- {
- //find corresponding edge in gInputGraph
- EdgeBoolPair dummyEdgeBool = lookup_edge(source(oDummyEdges[i], gInputGraph),
- target(oDummyEdges[i], gInputGraph),
- gInputGraph);
- //remove it from gInputGraph
- if(dummyEdgeBool.second)
- {
- remove_edge(source(dummyEdgeBool.first, gInputGraph),
- target(dummyEdgeBool.first, gInputGraph),
- gInputGraph);
- }
- else
- {
- throw LayoutException("removeDummyEdges",
- LayoutExceptionEnum::NOT_FOUND_IN_CONTAINER,
- "graph",
- "dummy edge");
- }
- }
- //Initialize the interior edge index in input graph
- layoutUtility.reinitializeEdgeIndices(gInputGraph);
- }
- void GraphPreProcessor::removeParallelEdges(SubGraph &gInputGraph, EdgeOrderType &oParallelEdgeList, std::vector<QString> & oParrallelEdgeIDs)
- {
- //std::vector<QString> oParrallelEdgeIDs;
- LayoutUtility layoutUtility;
- BoostGraphWrapper bGraphWrapper;
- int iNumVertices = boost::num_vertices(gInputGraph);
- GraphPreProcessor::graph gLocalGraph(iNumVertices);
- //for each edge in input graph
- EdgeIterator itrEdge, itrEdgeEnd;
- for(boost::tie(itrEdge, itrEdgeEnd) = edges(gInputGraph); itrEdge != itrEdgeEnd; ++itrEdge)
- {
- //get its endpoints in local graph
- graph_traits<graph>::vertex_descriptor vLocalSource, vLocalTarget;
- vLocalSource = vertex(get(vertex_index,
- gInputGraph,
- source(*itrEdge, gInputGraph)),
- gLocalGraph);
- vLocalTarget = vertex(get(vertex_index,
- gInputGraph,
- target(*itrEdge, gInputGraph)),
- gLocalGraph);
- //check if the edge already exists in local graph
- bool bIsInLocalG = (lookup_edge(vLocalSource, vLocalTarget, gLocalGraph).second
- || lookup_edge(vLocalTarget, vLocalSource, gLocalGraph).second);
- if(!bIsInLocalG) //if doesnot exist in local graph
- {
- //add it to local graph
- LAYOUT_ASSERT(add_edge(vLocalSource, vLocalTarget, gLocalGraph).second,
- LayoutException("removeParallelEdges",
- LayoutExceptionEnum::INVALID_OPERATION,
- "add_edge",
- "removeParallelEdges"));
- //re-initialize edge indices
- layoutUtility.reinitializeEdgeIndices(gLocalGraph);
- }
- else //if already exists in local graph
- {
- //remember it as a parallel edge
- EdgeDescriptor eParallelEdge = *itrEdge;
- oParallelEdgeList.push_back(eParallelEdge);
- QString sEdheID = bGraphWrapper.getEdgeId(eParallelEdge, gInputGraph);
- oParrallelEdgeIDs.push_back(sEdheID);
- }
- }
- //for each parallel edge
- for(size_t iEdgeIndex = 0; iEdgeIndex < oParallelEdgeList.size(); ++iEdgeIndex)
- {
- //remove it
- remove_edge(oParallelEdgeList[iEdgeIndex], gInputGraph);
- }
- //re-initiate edge indices
- layoutUtility.reinitializeEdgeIndices(gInputGraph);
- }
- void GraphPreProcessor::toPlanar(SubGraph & gInputGraph, VertexOrderType &oDummyVertexList,
- std::vector<GraphPreProcessor::EdgePairType> & correspondingCrossingEdgeList)
- {
- int iNumVertices = boost::num_vertices(gInputGraph);
- size_t iNumEdges = boost::num_edges(gInputGraph);
- // XXX unused iNumEdges
- Q_UNUSED(iNumEdges);
- GraphPreProcessor::graph gLocalGraph(iNumVertices);
- std::vector< graph_traits< graph >::edge_descriptor > localCrossingEdgeList;
- //separate out the crossing edges from the graph
- this->findCrossingEdges(gInputGraph, gLocalGraph, localCrossingEdgeList);
- size_t iNumLocalEdges = boost::num_edges(gLocalGraph);
- // XXX unused
- Q_UNUSED(iNumLocalEdges);
- LAYOUT_ASSERT((localCrossingEdgeList.size() + iNumLocalEdges) == iNumEdges,
- LayoutException("toPlanar",
- LayoutExceptionEnum::INCONSISTENT_DATASTRUCTURE,
- "localCrossingEdgeList",
- "gLocalGraph"));
- //replace each crossing by a dummy vertex
- this->replaceCrossingsByDummyVertices(gInputGraph, gLocalGraph, localCrossingEdgeList,
- oDummyVertexList, correspondingCrossingEdgeList);
- LAYOUT_ASSERT(oDummyVertexList.size() == correspondingCrossingEdgeList.size(),
- LayoutException("toPlanar",
- LayoutExceptionEnum::INCONSISTENT_DATASTRUCTURE,
- "DummyVertices",
- "CorrespondingEdges"));
- }
- void GraphPreProcessor::findCrossingEdges(SubGraph & gInputGraph, GraphPreProcessor::graph & gLocalGraph,
- std::vector< graph_traits< graph >::edge_descriptor > & localCrossingEdgeList)
- {
- LayoutUtility layoutUtility;
- //for each edge in input graph
- EdgeIterator itrEdge, itrEdgeEnd;
- for(boost::tie(itrEdge, itrEdgeEnd) = edges(gInputGraph); itrEdge != itrEdgeEnd; ++itrEdge)
- {
- graph_traits<graph>::vertex_descriptor vLocalSource, vLocalTarget;
- vLocalSource = vertex(get(vertex_index, gInputGraph, source(*itrEdge, gInputGraph)),
- gLocalGraph);
- vLocalTarget = vertex(get(vertex_index, gInputGraph, target(*itrEdge, gInputGraph)),
- gLocalGraph);
- //add it to local graph
- add_edge(vLocalSource, vLocalTarget, gLocalGraph);
- //re-initialize edge indices
- layoutUtility.reinitializeEdgeIndices(gLocalGraph);
- //check planarity
- typedef std::vector< graph_traits<graph>::edge_descriptor > vec_t;
- std::vector<vec_t> embedding(num_vertices(gLocalGraph));
- bool bIsPlanar = boyer_myrvold_planarity_test(boyer_myrvold_params::graph = gLocalGraph,
- boyer_myrvold_params::embedding = &embedding[0]);
- if(!bIsPlanar) //if graph looses planarity due to added edge
- {
- LAYOUT_ASSERT(lookup_edge(vLocalSource, vLocalTarget, gLocalGraph).second,
- LayoutException("findCrossingEdges",
- LayoutExceptionEnum::NOT_FOUND_IN_CONTAINER,
- "LocalGraph",
- "crossing edge"));
- //remember it as crossing edge
- graph_traits<graph>::edge_descriptor eLocalCrossingEdge;
- eLocalCrossingEdge = lookup_edge(vLocalSource, vLocalTarget, gLocalGraph).first;
- localCrossingEdgeList.push_back(eLocalCrossingEdge);
- //remove it
- remove_edge(vLocalSource, vLocalTarget, gLocalGraph);
- //re-initialize edge indices
- layoutUtility.reinitializeEdgeIndices(gLocalGraph);
- }
- //else if planar, continue adding edges to local graph
- }
- }
- void GraphPreProcessor::replaceCrossingsByDummyVertices(SubGraph & gInputGraph, GraphPreProcessor::graph & gLocalGraph,
- std::vector< graph_traits< graph >::edge_descriptor > & localCrossingEdgeList,
- VertexOrderType &oDummyVertexList,
- std::vector<GraphPreProcessor::EdgePairType> & correspondingCrossingEdgeList)
- {
- LayoutUtility layoutUtility;
- //for each crossing edge
- for(size_t iCrossingEdgeIndex = 0; iCrossingEdgeIndex < localCrossingEdgeList.size(); ++iCrossingEdgeIndex)
- {
- //get its src and tgt and their indices in local graph
- graph_traits<SubGraph>::vertex_descriptor vSourceOfLocalCrossingEdge, vTargetOfLocalCrossingEdge;
- vSourceOfLocalCrossingEdge = source(localCrossingEdgeList[iCrossingEdgeIndex], gLocalGraph);
- vTargetOfLocalCrossingEdge = target(localCrossingEdgeList[iCrossingEdgeIndex], gLocalGraph);
- int iIndexOfSourceOfCrossingEdge = get(vertex_index, gLocalGraph, vSourceOfLocalCrossingEdge);
- int iIndexOfTargetOfCrossingEdge = get(vertex_index, gLocalGraph, vTargetOfLocalCrossingEdge);
- //get corresponding src and tgt in input graph
- VertexDescriptor vSourceOfCrossingEdge, vTargetOfCrossingEdge;
- vSourceOfCrossingEdge = vertex(iIndexOfSourceOfCrossingEdge, gInputGraph);
- vTargetOfCrossingEdge = vertex(iIndexOfTargetOfCrossingEdge, gInputGraph);
- //find augmented dual graph of local graph------------------------------------------------------------
- GraphPreProcessor::graph gDualGraph;
- UndirEdgeOrderType dualEdge(boost::num_edges(gLocalGraph));
- std::vector< graph_traits<GraphPreProcessor::graph>::vertex_descriptor > oAugmentedVertices(2);
- std::vector< int > oIndicesOfEndsOfCrossingEdge(2);
- oIndicesOfEndsOfCrossingEdge[0] = iIndexOfSourceOfCrossingEdge;
- oIndicesOfEndsOfCrossingEdge[1] = iIndexOfTargetOfCrossingEdge;
- this->createAugmentedDualGraph(gLocalGraph, gDualGraph, dualEdge,
- oIndicesOfEndsOfCrossingEdge,
- oAugmentedVertices);
- graph_traits<GraphPreProcessor::graph>::vertex_descriptor vAugmentedSource, vAugmentedTarget;
- vAugmentedSource = oAugmentedVertices[0];
- vAugmentedTarget = oAugmentedVertices[1];
- //----------------------------------------------------------------------------------------------------
- //find shortest path----------------------------------------------------------------------------------
- GraphPreProcessor::dijkstra_graph gDijkstraGraph(num_vertices(gDualGraph));
- std::vector<GraphPreProcessor::dijkstra_vertex_descriptor> path;
- this->findShortestPath(gDualGraph, gDijkstraGraph, vAugmentedSource, vAugmentedTarget, path);
- //---------------------------------------------------------------------------------------------------
- //Replace edge crossings along the shortest path by dummy vertices-----------------------------------
- graph_traits<graph>::vertex_descriptor vRecentlyAddedLocalVertex = vSourceOfLocalCrossingEdge;
- VertexDescriptor vRecentlyAddedVertex = vSourceOfCrossingEdge;
- LAYOUT_ASSERT(path.size() > 3,
- LayoutException("replaceCrossingsByDummyVertices",
- LayoutExceptionEnum::INCONSISTENT_DATASTRUCTURE,
- "shortest path",
- "in dual graph"));
- //for each dual edge in the shortest path
- for(size_t iPathIndex = 1; iPathIndex <= path.size() - 3; ++iPathIndex)
- {
- //this dual edge ( path[iPathIndex]-path[iPathIndex+1] ) represents a crossing
- //find edge in local graph corresponding to this dual edge (call it 'vertical edge')-------------
- graph_traits<graph>::vertex_descriptor vSourceOfDualEdge, vTargetOfDualEdge;
- //find vertices in (aug)dual draph, corresponding to path[i] and path[i+1] in gDijkstraGraph
- int iSourceIndexOfDualEdgeInPath = get(vertex_index, gDijkstraGraph, path[iPathIndex]);
- vSourceOfDualEdge = vertex(iSourceIndexOfDualEdgeInPath, gDualGraph);
- int iTargetIndexOfDualEdgeInPath = get(vertex_index, gDijkstraGraph, path[iPathIndex + 1]);
- vTargetOfDualEdge = vertex(iTargetIndexOfDualEdgeInPath, gDualGraph);
- //find edge between these vertices in (aug)dual graph
- graph_traits<graph>::edge_descriptor eDualEdge;
- if(lookup_edge(vSourceOfDualEdge, vTargetOfDualEdge, gDualGraph).second)
- eDualEdge = lookup_edge(vSourceOfDualEdge, vTargetOfDualEdge, gDualGraph).first;
- else if(lookup_edge(vTargetOfDualEdge, vSourceOfDualEdge, gDualGraph).second)
- eDualEdge = lookup_edge(vTargetOfDualEdge, vSourceOfDualEdge, gDualGraph).first;
- //find its corresponding edge in local graph
- graph_traits<graph>::edge_descriptor eLocalVerticalEdge;
- size_t iDualEdgeIndex = get(edge_index, gDualGraph, eDualEdge);
- LAYOUT_ASSERT(iDualEdgeIndex < dualEdge.size(),
- LayoutException("replaceCrossingsByDummyVertices",
- LayoutExceptionEnum::INCONSISTENT_DATASTRUCTURE,
- "dualEdge",
- "index out of bound"));
- eLocalVerticalEdge = dualEdge[iDualEdgeIndex];
- //find vertical edge's endpoints in local graph
- graph_traits<graph>::vertex_descriptor vSourceOfLocalVerticalEdge, vTargetOfLocalVerticalEdge;
- vSourceOfLocalVerticalEdge = source(eLocalVerticalEdge, gLocalGraph);
- vTargetOfLocalVerticalEdge = target(eLocalVerticalEdge, gLocalGraph);
- //find vertical edge's endpoints in input graph
- VertexDescriptor vSourceOfVerticalEdge, vTargetOfVerticalEdge;
- int iIndexOfSourceOfLocalVerticalEdge = get(vertex_index, gLocalGraph, vSourceOfLocalVerticalEdge);
- vSourceOfVerticalEdge = vertex(iIndexOfSourceOfLocalVerticalEdge, gInputGraph);
- int iIndexOfTargetOfLocalVerticalEdge = get(vertex_index, gLocalGraph, vTargetOfLocalVerticalEdge);
- vTargetOfVerticalEdge = vertex(iIndexOfTargetOfLocalVerticalEdge, gInputGraph);
- //-----------------------------------------------------------------------------------------------
- //Replace the crossing edges by dummy vertex-----------------------------------------------------
- //IN INPUT GRAPH:
- //add new (dummy) vertex
- VertexDescriptor vNewVertex = add_vertex(gInputGraph);
- oDummyVertexList.push_back(vNewVertex);
- //join new vertex to ends of vertical edge
- add_edge(vSourceOfVerticalEdge, vNewVertex, gInputGraph);
- add_edge(vNewVertex, vTargetOfVerticalEdge, gInputGraph);
- //remove vertical edge
- remove_edge(vSourceOfVerticalEdge, vTargetOfVerticalEdge, gInputGraph);
- remove_edge(vTargetOfVerticalEdge, vSourceOfVerticalEdge, gInputGraph);
- //join recent vertex to new vertex
- add_edge(vRecentlyAddedVertex, vNewVertex, gInputGraph);
- //remember crossing which is being replaced by vertex
- GraphPreProcessor::EdgePairType crossingEdgePair (2, std::vector<VertexDescriptor>(2));
- crossingEdgePair[0][0] = vSourceOfCrossingEdge;
- crossingEdgePair[0][1] = vTargetOfCrossingEdge;
- crossingEdgePair[1][0] = vSourceOfVerticalEdge;
- crossingEdgePair[1][1] = vTargetOfVerticalEdge;
- correspondingCrossingEdgeList.push_back(crossingEdgePair);
- //new vertex becomes recent vertex
- vRecentlyAddedVertex = vNewVertex;
- //IN LOCAL GRAPH:
- //add new vert
- graph_traits<graph>::vertex_descriptor vNewLocalVertex = add_vertex(gLocalGraph);
- //join new vertex to ends of vertical edge
- add_edge(vSourceOfLocalVerticalEdge, vNewLocalVertex, gLocalGraph);
- add_edge(vNewLocalVertex, vTargetOfLocalVerticalEdge, gLocalGraph);
- //remove vertical edge
- remove_edge(vSourceOfLocalVerticalEdge, vTargetOfLocalVerticalEdge, gLocalGraph);
- remove_edge(vTargetOfLocalVerticalEdge, vSourceOfLocalVerticalEdge, gLocalGraph);
- //join recent vertex to new vertex
- add_edge(vRecentlyAddedLocalVertex, vNewLocalVertex, gLocalGraph);
- //new vertex becomes recent vertex
- vRecentlyAddedLocalVertex = vNewLocalVertex;
- //-----------------------------------------------------------------------------------------------
- }
- //connect the last dummy vertex----------------------------------------------------------------------
- //IN INPUT GRAPH:
- //join recent and target of horizontal edge
- add_edge(vRecentlyAddedVertex, vTargetOfCrossingEdge, gInputGraph);
- //remove crossing (horizontal) edge
- remove_edge(vSourceOfCrossingEdge, vTargetOfCrossingEdge, gInputGraph);
- remove_edge(vTargetOfCrossingEdge, vSourceOfCrossingEdge, gInputGraph);
- //re-initiate edge indices
- layoutUtility.reinitializeEdgeIndices(gInputGraph);
- //IN LOCAL GRAPH:
- //join recent and target of horizontal edge
- add_edge(vRecentlyAddedLocalVertex, vTargetOfLocalCrossingEdge, gLocalGraph);
- //re-initialize edge indices
- layoutUtility.reinitializeEdgeIndices(gLocalGraph);
- //---------------------------------------------------------------------------------------------------
- //---------------------------------------------------------------------------------------------------
- }
- }
- void GraphPreProcessor::createAugmentedDualGraph(GraphPreProcessor::graph & gLocalGraph,
- GraphPreProcessor::graph & gDualGraph,
- UndirEdgeOrderType & dualEdge,
- std::vector< int > & oIndicesOfEndsOfCrossingEdge,
- std::vector< graph_traits<GraphPreProcessor::graph>::vertex_descriptor > & oAugmentedVertices)
- {
- LayoutUtility layoutUtility;
- //find dual graph of local graph-------------------------------------------------------------------
- std::vector< UndirVertexOrderType > adjecentFace(boost::num_vertices(gLocalGraph));
- // Compute the planar embedding - we know the input graph is planar,
- // so we're ignoring the return value of the test
- typedef std::vector< graph_traits<graph>::edge_descriptor > vec_t;
- std::vector<vec_t> embedding(num_vertices(gLocalGraph));
- boyer_myrvold_planarity_test(boyer_myrvold_params::graph = gLocalGraph,
- boyer_myrvold_params::embedding = &embedding[0]);
- create_dual_graph(gLocalGraph, gDualGraph, &embedding[0], adjecentFace, dualEdge);
- //-------------------------------------------------------------------------------------------------
- //find augmented dual graph------------------------------------------------------------------------
- //add source and target of the crossing-edge to dual graph
- oAugmentedVertices[0] = add_vertex(gDualGraph);
- oAugmentedVertices[1] = add_vertex(gDualGraph);
- //connect these src and tgt to their adjecent faces
- //for all of source's adjecent faces
- LAYOUT_ASSERT((size_t)oIndicesOfEndsOfCrossingEdge[0] < adjecentFace.size(),
- LayoutException("createAugmentedDualGraph",
- LayoutExceptionEnum::INVALID_ATTRIBUTE_VALUE,
- "adjecentFace",
- "index out of Bound")); //adjecentFace[oIndicesOfEndsOfCrossingEdge[0]] not Null
- LAYOUT_ASSERT(adjecentFace[oIndicesOfEndsOfCrossingEdge[0]].size() > 0,
- LayoutException("createAugmentedDualGraph",
- LayoutExceptionEnum::EMPTY_CONTAINER,
- "adjecentFace[source]",
- "adjecentFace of aug.source")); //adjecentFace[oIndicesOfEndsOfCrossingEdge[0]].size() > 0
- for(size_t iFaceIndex = 0; iFaceIndex < adjecentFace[oIndicesOfEndsOfCrossingEdge[0]].size(); ++iFaceIndex)
- {
- //if src not already connected to adjecent face
- if(!(lookup_edge(oAugmentedVertices[0], adjecentFace[oIndicesOfEndsOfCrossingEdge[0]][iFaceIndex], gDualGraph).second
- || lookup_edge(adjecentFace[oIndicesOfEndsOfCrossingEdge[0]][iFaceIndex], oAugmentedVertices[0], gDualGraph).second))
- {
- //add edge to dual graph
- add_edge(oAugmentedVertices[0], adjecentFace[oIndicesOfEndsOfCrossingEdge[0]][iFaceIndex], gDualGraph);
- }
- //else continue
- }
- //for all of target's adjecent faces
- LAYOUT_ASSERT((size_t)oIndicesOfEndsOfCrossingEdge[1] < adjecentFace.size(),
- LayoutException("createAugmentedDualGraph",
- LayoutExceptionEnum::INVALID_ATTRIBUTE_VALUE,
- "adjecentFace",
- "index out of Bound")); //adjecentFace[oIndicesOfEndsOfCrossingEdge[1]] not Null
- LAYOUT_ASSERT(adjecentFace[oIndicesOfEndsOfCrossingEdge[1]].size() > 0,
- LayoutException("createAugmentedDualGraph",
- LayoutExceptionEnum::EMPTY_CONTAINER,
- "adjecentFace[target]",
- "adjecentFace of aug.target")); //adjecentFace[oIndicesOfEndsOfCrossingEdge[1]].size() > 0
- for(size_t iFaceIndex = 0; iFaceIndex < adjecentFace[oIndicesOfEndsOfCrossingEdge[1]].size(); ++iFaceIndex)
- {
- //if tgt not already connected to adjecent face
- if(!(lookup_edge(oAugmentedVertices[1], adjecentFace[oIndicesOfEndsOfCrossingEdge[1]][iFaceIndex], gDualGraph).second
- || lookup_edge(adjecentFace[oIndicesOfEndsOfCrossingEdge[1]][iFaceIndex], oAugmentedVertices[1], gDualGraph).second))
- {
- //add edge to dual graph
- add_edge(oAugmentedVertices[1], adjecentFace[oIndicesOfEndsOfCrossingEdge[1]][iFaceIndex], gDualGraph);
- }
- //else continue
- }
- //re-initialize edge indices
- layoutUtility.reinitializeEdgeIndices(gDualGraph);
- //---------------------------------------------------------------------------------------------------
- }
- void GraphPreProcessor::findShortestPath(GraphPreProcessor::graph & gDualGraph,
- GraphPreProcessor::dijkstra_graph & gDijkstraGraph,
- graph_traits<GraphPreProcessor::graph>::vertex_descriptor & vAugmentedSource,
- graph_traits<GraphPreProcessor::graph>::vertex_descriptor & vAugmentedTarget,
- std::vector<GraphPreProcessor::dijkstra_vertex_descriptor> & path)
- {
- LayoutUtility layoutUtility;
- //create a copy of the augmented dual graph with edge weights set to '1'------------------------------------
- //for each edge in (augmented)dual graph
- graph_traits< GraphPreProcessor::graph >::edge_iterator itrDualGraphEdge, itrDualGraphEdgeEnd;
- for(boost::tie(itrDualGraphEdge, itrDualGraphEdgeEnd) = edges(gDualGraph); itrDualGraphEdge != itrDualGraphEdgeEnd; ++itrDualGraphEdge)
- {
- //get src and tgt of the edge
- graph_traits< GraphPreProcessor::graph >::vertex_descriptor vSourceOfDualEdge, vTargetOfDualEdge;
- vSourceOfDualEdge = source(*itrDualGraphEdge, gDualGraph);
- vTargetOfDualEdge = target(*itrDualGraphEdge, gDualGraph);
- int iIndexOfSourceOfDualEdge = get(vertex_index, gDualGraph, vSourceOfDualEdge);
- int iIndexOfTargetOfDualEdge = get(vertex_index, gDualGraph, vTargetOfDualEdge);
- //get corresponding src and tgt in dijkstra graph
- graph_traits< GraphPreProcessor::dijkstra_graph >::vertex_descriptor vSourceOfDualEdgeInDijkstra, vTargetOfDualEdgeInDijkstra;
- vSourceOfDualEdgeInDijkstra = vertex(iIndexOfSourceOfDualEdge, gDijkstraGraph);
- vTargetOfDualEdgeInDijkstra = vertex(iIndexOfTargetOfDualEdge, gDijkstraGraph);
- //add edge in dijkstra graph
- add_edge(vSourceOfDualEdgeInDijkstra, vTargetOfDualEdgeInDijkstra, 1, gDijkstraGraph);
- }
- //Initialize the interior edge index
- layoutUtility.reinitializeEdgeIndices(gDijkstraGraph);
- //----------------------------------------------------------------------------------------------------------
- //find vertices in gDijkstraGraph, corresponding to vAugmentedSource and vAugmentedTarget
- GraphPreProcessor::dijkstra_vertex_descriptor vDijkstraSource, vDijkstraTarget;
- int iIndexOfAugmentedSource = get(vertex_index, gDualGraph, vAugmentedSource);
- vDijkstraSource = vertex(iIndexOfAugmentedSource, gDijkstraGraph);
- int iIndexOfAugmentedTarget = get(vertex_index, gDualGraph, vAugmentedTarget);
- vDijkstraTarget = vertex(iIndexOfAugmentedTarget, gDijkstraGraph);
- //call Dijkstra's single source shortest path algorithm-----------------------------------------------------
- //it will calculate distances and preceding vertex of each vertex, in the shortest path from the source
- std::vector<GraphPreProcessor::dijkstra_vertex_descriptor> p(num_vertices(gDijkstraGraph)); //to maintatin parent of each vertex in Dijkstra traversal
- std::vector<int> d(num_vertices(gDijkstraGraph)); //to maintatin distance of each vertex from source in Dijkstra traversal
- dijkstra_shortest_paths(gDijkstraGraph,
- vDijkstraSource,
- predecessor_map(boost::make_iterator_property_map(p.begin(),
- get(boost::vertex_index,
- gDijkstraGraph))).distance_map(boost::make_iterator_property_map(d.begin(),
- get(boost::vertex_index,
- gDijkstraGraph))));
- //find path from src to tgt
- this->findPath(vDijkstraTarget, path, p); //finds path in reverse(target to source) in Dijkstra graph
- std::reverse(path.begin(), path.end());
- LAYOUT_ASSERT(((path[0] == vDijkstraSource) && (path[path.size() - 1] == vDijkstraTarget)),
- LayoutException("findShortestPath",
- LayoutExceptionEnum::NOT_FOUND_IN_CONTAINER,
- "shortest path",
- "aug. source/target")); //path is from source to target
- //----------------------------------------------------------------------------------------------------------
- }
- void GraphPreProcessor::findPath(GraphPreProcessor::dijkstra_vertex_descriptor &vTarget,
- std::vector<GraphPreProcessor::dijkstra_vertex_descriptor> &myPath,
- std::vector<GraphPreProcessor::dijkstra_vertex_descriptor> &parentVertex)
- {
- LAYOUT_ASSERT(vTarget < parentVertex.size(),
- LayoutException("findPath",
- LayoutExceptionEnum::INVALID_ATTRIBUTE_VALUE,
- "parentVertex",
- "index out of bound")); //parentVertex[vTarget] not NULL
- if(parentVertex[vTarget] == vTarget)
- {
- myPath.push_back(vTarget);
- return;
- }
- else
- {
- myPath.push_back(vTarget);
- findPath(parentVertex[vTarget], myPath, parentVertex);
- return;
- }
- }
- void GraphPreProcessor::addParallelEdges(SubGraph &gInputGraph, EdgeOrderType &oParallelEdgeList, std::vector<QString> & oParrallelEdgeIDs)
- {
- BoostGraphWrapper boostGraphWrapper;
- //for each parallel edge, add it to graph
- for(size_t iParallelEdgeIndex = 0; iParallelEdgeIndex < oParallelEdgeList.size(); ++iParallelEdgeIndex)
- {
- VertexDescriptor vSourceOfParallelEdge, vTargetOfParallelEdge;
- vSourceOfParallelEdge = source(oParallelEdgeList[iParallelEdgeIndex], gInputGraph);
- vTargetOfParallelEdge = target(oParallelEdgeList[iParallelEdgeIndex], gInputGraph);
- QString sEdgeID = oParrallelEdgeIDs[iParallelEdgeIndex];
- EdgeBoolPair pEdgeBool = add_edge(vSourceOfParallelEdge, vTargetOfParallelEdge, gInputGraph);
- LAYOUT_ASSERT(pEdgeBool.second,
- LayoutException("addParallelEdges",
- LayoutExceptionEnum::INVALID_OPERATION,
- "add_edge",
- "addParallelEdges"));
- boostGraphWrapper.setEdgeId(pEdgeBool.first, gInputGraph, sEdgeID);
- }
- //reinitialize edge index
- LayoutUtility layoutUtility;
- layoutUtility.reinitializeEdgeIndices(gInputGraph);
- }
- void GraphPreProcessor::removeDummyVertices(SubGraph & gInputGraph, VertexOrderType &oDummyVertices,
- std::vector<GraphPreProcessor::EdgePairType> & correspondingCrossingEdge)
- {
- //for each dummy vertex (in reverse order of insertion)
- // when size_t iDummyVertexIndex >= 0 is always true
- for(int iDummyVertexIndex = oDummyVertices.size() - 1; iDummyVertexIndex >= 0; --iDummyVertexIndex)
- {
- std::vector<EdgeDescriptor> oEdgesToBeRemoved;
- //remove all edges incident on current dummy vertex-----------------------------------------------------
- //for each edge in InputGraph
- EdgeIterator itrEdge, itrEdgeEnd;
- for(boost::tie(itrEdge, itrEdgeEnd)=edges(gInputGraph); itrEdge != itrEdgeEnd; ++itrEdge)
- {
- //if it has dummy vertex as end-point
- if(source(*itrEdge, gInputGraph) == oDummyVertices[iDummyVertexIndex]
- || target(*itrEdge, gInputGraph) == oDummyVertices[iDummyVertexIndex])
- {
- //remember it as ToBeRemoved
- oEdgesToBeRemoved.push_back(*itrEdge);
- }
- //else continue
- }
- //for each edge ToBeRemoved
- for(size_t iEdgeIndex = 0; iEdgeIndex < oEdgesToBeRemoved.size(); ++iEdgeIndex)
- {
- VertexDescriptor vSourceOfEdgeToBeRemoved, vTargetOfEdgeToBeRemoved;
- vSourceOfEdgeToBeRemoved = source(oEdgesToBeRemoved[iEdgeIndex], gInputGraph);
- vTargetOfEdgeToBeRemoved = target(oEdgesToBeRemoved[iEdgeIndex], gInputGraph);
- //remove edge
- remove_edge(vSourceOfEdgeToBeRemoved, vTargetOfEdgeToBeRemoved, gInputGraph);
- remove_edge(vTargetOfEdgeToBeRemoved, vSourceOfEdgeToBeRemoved, gInputGraph);
- }
- //------------------------------------------------------------------------------------------------------
- //add the corresponding crossing edges back-------------------------------------------------------------
- //for each crossing-edge corresponding to current dummy vrtex
- LAYOUT_ASSERT((size_t)iDummyVertexIndex < correspondingCrossingEdge.size(),
- LayoutException("removeDummyVertices",
- LayoutExceptionEnum::INCONSISTENT_DATASTRUCTURE,
- "correspondingCrossingEdge",
- "index out of bound"));
- LAYOUT_ASSERT(correspondingCrossingEdge[iDummyVertexIndex].size() == 2,
- LayoutException("removeDummyVertices",
- LayoutExceptionEnum::INCONSISTENT_DATASTRUCTURE,
- "correspondingCrossingEdges for dummyVertex",
- "index out of bound"));
- for(size_t iCrossingEdgeIndex = 0; iCrossingEdgeIndex < correspondingCrossingEdge[iDummyVertexIndex].size(); ++iCrossingEdgeIndex)
- {
- LAYOUT_ASSERT(correspondingCrossingEdge[iDummyVertexIndex][iCrossingEdgeIndex].size() == 2,
- LayoutException("removeDummyVertices",
- LayoutExceptionEnum::INCONSISTENT_DATASTRUCTURE,
- "endPoints of correspondingCrossingEdge for dummyVertex",
- "index out of bound"));
- //get its src and tgt
- VertexDescriptor vSourceOfCrossingEdge, vTargetOfCrossingEdge;
- vSourceOfCrossingEdge = correspondingCrossingEdge[iDummyVertexIndex][iCrossingEdgeIndex][0];
- vTargetOfCrossingEdge = correspondingCrossingEdge[iDummyVertexIndex][iCrossingEdgeIndex][1];
- //if not already added to InputGraph
- if(!(lookup_edge(vSourceOfCrossingEdge, vTargetOfCrossingEdge, gInputGraph).second
- || lookup_edge(vTargetOfCrossingEdge, vSourceOfCrossingEdge, gInputGraph).second))
- {
- //add edge
- LAYOUT_ASSERT(add_edge(vSourceOfCrossingEdge, vTargetOfCrossingEdge, gInputGraph).second,
- LayoutException("removeDummyVertices",
- LayoutExceptionEnum::INVALID_OPERATION,
- "add_edge",
- "removeDummyVertices"));
- }
- //else continue
- }
- //-----------------------------------------------------------------------------------------------------
- //reinitialize edge index
- LayoutUtility layoutUtility;
- layoutUtility.reinitializeEdgeIndices(gInputGraph);
- //set dummy vertex invisible
- BoostGraphWrapper boostGraphWrapper;
- boostGraphWrapper.setVertexIsInvisible(oDummyVertices[iDummyVertexIndex], gInputGraph, true);
- }
- }
- void GraphPreProcessor::toPlanarAlternate(SubGraph &gInputGraph, EdgeOrderType &oNonPlanarEdges)
- {
- VertexDescriptor descVertexSource;
- VertexDescriptor descVertexTarget;
- VertexDescriptor vNewInputGraphVertex;
- EdgeIterator itrEdge, itrEdgeEnd;
- EdgeDescriptor descEdge;
- int iVertexSource, iVertexTarget, iNumVertices;
- BoostGraphWrapper graphWrapper;
- iNumVertices = boost::num_vertices(gInputGraph);
- GraphPreProcessor::graph gLacalGraph(iNumVertices); //create a local undirected graph with same no. of vertices
- std::vector< graph_traits< graph >::edge_descriptor > nonPlanarUndirEdges;
- graph_traits< graph >::edge_descriptor eCurrentEdge, eTemporaryEdge1, eTemporaryEdge2, eTemporaryEdge3;
- bool bAdded;
- // XXX unused
- Q_UNUSED(vNewInputGraphVertex);
- //PLANARIZATION------------------------------------------------------------------------------------------
- // add each edge from gInputGraph to gLacalGraph one by one, until gLacalGraph is planar
- // if an edge makes gLacalGraph non-planar, remove and store it aside
- property_map<graph, edge_index_t>::type e_index = get(edge_index, gLacalGraph);
- graph_traits<graph>::edges_size_type edge_count;
- graph_traits<graph>::edge_iterator ei, ei_end;
- for(boost::tie(itrEdge, itrEdgeEnd) = edges(gInputGraph); itrEdge != itrEdgeEnd; itrEdge++)
- {
- descEdge = *itrEdge;
- descVertexSource = graphWrapper.getEdgeSource(descEdge, gInputGraph);
- descVertexTarget = graphWrapper.getEdgeTarget(descEdge, gInputGraph);
- iVertexSource = get(vertex_index, gInputGraph, descVertexSource);
- iVertexTarget = get(vertex_index, gInputGraph, descVertexTarget);
- boost::tie(eCurrentEdge, bAdded) = add_edge(iVertexSource, iVertexTarget, gLacalGraph);
- if(bAdded)
- {
- //Initialize the interior edge index
- edge_count = 0;
- for(boost::tie(ei, ei_end) = edges(gLacalGraph); ei != ei_end; ++ei)
- put(e_index, *ei, edge_count++);
- //Test for planarity; compute the planar embedding as a side-effect
- typedef std::vector< graph_traits<graph>::edge_descriptor > vec_t;
- std::vector<vec_t> embedding(num_vertices(gLacalGraph));
- if (boyer_myrvold_planarity_test(boyer_myrvold_params::graph = gLacalGraph,
- boyer_myrvold_params::embedding = &embedding[0]))
- {
- //std::cout << "Input graph is planar3" << std::endl;
- }
- else
- {
- //std::cout << "Input graph is not planar3" << std::endl;
- nonPlanarUndirEdges.push_back(eCurrentEdge);
- remove_edge(eCurrentEdge, gLacalGraph);
- //Re-initialize the interior edge index
- edge_count = 0;
- for(boost::tie(ei, ei_end) = edges(gLacalGraph); ei != ei_end; ++ei)
- put(e_index, *ei, edge_count++);
- }
- }
- }
- //END----------------------------------------------------------------------------------------------------
- //REMOVE NON-PLANAR EDGES FROM INPUT GRAPH---------------------------------------------------------------
- for(size_t iEdgeIndex = 0; iEdgeIndex < nonPlanarUndirEdges.size(); ++iEdgeIndex)
- {
- //find corresponding non-planar edge in gInputGraph
- VertexDescriptor vSourceInInputGraph, vTargetInInputGraph;
- vSourceInInputGraph = vertex(get(vertex_index,
- gInputGraph,
- source(nonPlanarUndirEdges[iEdgeIndex], gLacalGraph)),
- gInputGraph);
- vTargetInInputGraph = vertex(get(vertex_index,
- gInputGraph,
- target(nonPlanarUndirEdges[iEdgeIndex], gLacalGraph)),
- gInputGraph);
- EdgeDescriptor eNonPlanarEdgeInInputGraph;
- if(lookup_edge(vSourceInInputGraph, vTargetInInputGraph, gInputGraph).second)
- eNonPlanarEdgeInInputGraph = lookup_edge(vSourceInInputGraph, vTargetInInputGraph, gInputGraph).first;
- else if(lookup_edge(vTargetInInputGraph, vSourceInInputGraph, gInputGraph).second)
- eNonPlanarEdgeInInputGraph = lookup_edge(vTargetInInputGraph, vSourceInInputGraph, gInputGraph).first;
- else
- std::cout << "Error in finding non-planar edge" << std::endl;
- //remove that edge from gInputGraph and store it
- oNonPlanarEdges.push_back(eNonPlanarEdgeInInputGraph);
- remove_edge(eNonPlanarEdgeInInputGraph, gInputGraph);
- }
- //END----------------------------------------------------------------------------------------------------
- }
- void GraphPreProcessor::addNonPlanarEdges(SubGraph &gInputGraph, EdgeOrderType &oNonPlanarEdges)
- {
- for(size_t i = 0; i < oNonPlanarEdges.size(); ++i)
- {
- add_edge(source(oNonPlanarEdges[i], gInputGraph),
- target(oNonPlanarEdges[i], gInputGraph),
- gInputGraph);
- }
- //Initialize the interior edge index in input graph
- property_map<SubGraph, edge_index_t>::type in_e_index = get(edge_index, gInputGraph);
- graph_traits<SubGraph>::edges_size_type in_edge_count = 0;
- graph_traits<SubGraph>::edge_iterator in_ei, in_ei_end;
- for(boost::tie(in_ei, in_ei_end) = edges(gInputGraph); in_ei != in_ei_end; ++in_ei)
- put(in_e_index, *in_ei, in_edge_count++);
- }
|