LAYOUTEVENT CGraphLeeLayoutImpl::pulse(const GraphTypes::RectF & extent) { size_t verticy_count = m_meta.GetVisibleUnpinnedVertexCount(m_graph, m_canvas); if (verticy_count > 1) { GraphTypes::PointF vp; LeeRoutePlanner* plannerLee; // GraphTypes::SizeF gridSize; //gridSize.Width=32.0; //gridSize.Height=32.0; plannerLee=LeeRoutePlanner::Create(); //gridSize); assert(plannerLee); plannerLee->BeginAddPoints(); for(StlLinked<IVertexIterator> itr = m_graph->GetUserVertexIterator(new MetaStateSkipper(m_meta, m_canvas, TRISTATE_TRUE, TRISTATE_FALSE)); itr->IsValidItem(); itr->NextItem()) { CComPtr<IGraphVertex> vertex = itr->Get(); CComPtr<IRenderer> ir=m_canvas->GetRenderer(vertex); ir->GetPosition(vp); plannerLee->AddPoint(vp, &vp); ir->SetPosition(vp); } plannerLee->EndAddPoints(); IGraphEdgeVector edges; m_graph->GetEdges(edges); for (IGraphEdgeVector::iterator itr = edges.begin(); itr != edges.end(); ++itr) { IGraphEdge * edge = *itr; IGraphVertex * from = edge->GetSource(); IGraphVertex * to = edge->GetTarget(); GraphTypes::PointF start, end; GraphTypes::PointFVector path; CComPtr<IRenderer> irf=m_canvas->GetRenderer(from); CComPtr<IRenderer> irt=m_canvas->GetRenderer(to); CComQIPtr<IEdgeRenderer> ire=m_canvas->GetRenderer(edge); irf->GetPosition(start); irt->GetPosition(end); if ( plannerLee->GetShortestPath( start, end, path ) ) { ire->SetPoints(path); } } plannerLee->Dispose(); } return LAYOUTEVENT_FINISHED; }
//relaxEdges is more like tense edges up. All edges pull nodes closes together; void CGraphTouchgraphLayoutImpl::relaxEdges() { std::map<unsigned,IGraphVertex*> dupes; for (CComPtr<IEdgeIterator> itr = m_graph->GetEdgeIterator(); itr->IsValidItem() == true && !m_halt; itr->NextItem()) { IGraphEdge * edge = itr->Get(); if (m_meta.IsVisible(edge)) { IGraphVertex* s = edge->GetSource(); IGraphVertex* t = edge->GetTarget(); //TODO Identical to this edge pruning algo is used also in neato.cpp. Isolate into the //method when changing headers will be less painful CComPtr<IGraphSubgraph> ss=s->GetParent(); CComPtr<IGraphSubgraph> st=t->GetParent(); ATLASSERT(ss && st); bool addedge=true; bool sinsg=false, tinsg=false; unsigned shash, thash; if(ss->GetID()!=ROOT_ID) // edge for vertex that is not in the root graph { sinsg=true; // see if the other side is in the map if(dupes.find(t->GetID().GetHash())==dupes.end()) { dupes[t->GetID().GetHash()]=t; shash=ss->GetID().GetHash(); } else addedge=false; } else shash=s->GetID().GetHash(); if(addedge && st->GetID()!=ROOT_ID) // edge for vertex that is not in the root graph { tinsg=true; // see if the other side is in the map if(dupes.find(s->GetID().GetHash())==dupes.end()) { dupes[s->GetID().GetHash()]=s; thash=st->GetID().GetHash(); } else addedge=false; } else thash=t->GetID().GetHash(); if(sinsg && tinsg) // skip edges connecting vertices inside subgraph addedge=false; if(!addedge) continue; PointF posTo; IRenderer * ir = m_canvas->GetRenderer(t); if(ir) { ir->GetPosition(posTo); } PointF posFrom; ir = m_canvas->GetRenderer(s); if(ir) { ir->GetPosition(posFrom); } PointF vP(posTo.x - posFrom.x, posTo.y - posFrom.y); float len = sqrt(vP.x * vP.x + vP.y * vP.y); //PointF float dx = vP.x * rigidity; //rigidity makes edges tighter float dy = vP.y * rigidity; dx /= 150.0f * 100; dy /= 150.0f * 100; // Edges pull directly in proportion to the distance between the nodes. This is good, // because we want the edges to be stretchy. The edges are ideal rubberbands. They // They don't become springs when they are too short. That only causes the graph to // oscillate. // ATLASSERT(dx < 1 && dy < 1); //if (m_justMadeLocal[to->GetID()] || !m_justMadeLocal[from->GetID()]) //{ // m_dv[to->GetID()].x -= dx * len; // m_dv[to->GetID()].y -= dy * len; //} //else { m_dv[t->GetID()].x -= dx * len / 10; m_dv[t->GetID()].y -= dy * len / 10; } //if (m_justMadeLocal[from->GetID()] || !m_justMadeLocal[to->GetID()]) //{ // m_dv[from->GetID()].x += dx * len; // m_dv[from->GetID()].y += dy * len; //} //else { m_dv[s->GetID()].x += dx * len / 10; m_dv[s->GetID()].y += dy * len / 10; } } } }