Example #1
0
//*************************************************************
// call for PlanarizationLayoutUML
void SimDrawCaller::callPlanarizationLayout()
{
	m_SD->addAttribute(GraphAttributes::nodeGraphics);
	m_SD->addAttribute(GraphAttributes::edgeGraphics);

	// nodes get default size
	node v;
	forall_nodes(v, *m_G)
		m_GA->height(v) = m_GA->width(v) = 5.0;


	// actual call on PlanarizationLayout
	PlanarizationLayout PL;
	PL.callSimDraw(*m_GA);

} // end callPlanarizationLayout
Example #2
0
int main()
{
	Graph G;
	GraphAttributes GA(G,
		GraphAttributes::nodeGraphics |
		GraphAttributes::edgeGraphics |
		GraphAttributes::nodeLabel |
		GraphAttributes::edgeStyle |
		GraphAttributes::nodeStyle |
		GraphAttributes::nodeTemplate);
	GraphIO::readGML(GA, G, "ERDiagram.gml");

	PlanarizationLayout pl;

	SubgraphPlanarizer *crossMin = new SubgraphPlanarizer;

	FastPlanarSubgraph *ps = new FastPlanarSubgraph;
	ps->runs(100);
	VariableEmbeddingInserter *ves = new VariableEmbeddingInserter;
	ves->removeReinsert(rrAll);

	crossMin->setSubgraph(ps);
	crossMin->setInserter(ves);

	EmbedderMinDepthMaxFaceLayers *emb = new EmbedderMinDepthMaxFaceLayers;
	pl.setEmbedder(emb);

	OrthoLayout *ol = new OrthoLayout;
	ol->separation(20.0);
	ol->cOverhang(0.4);
	pl.setPlanarLayouter(ol);

	pl.call(GA);

	GraphIO::writeGML(GA, "ERDiagram-layout.gml");

	return 0;
}
Example #3
0
CRevisionGraphWnd::CRevisionGraphWnd()
	: CWnd()
	, m_SelectedEntry1(nullptr)
	, m_SelectedEntry2(nullptr)
	, m_HeadNode(nullptr)
	, m_pDlgTip(nullptr)
	, m_nFontSize(12)
	, m_bTweakTrunkColors(true)
	, m_bTweakTagsColors(true)
	, m_fZoomFactor(DEFAULT_ZOOM)
	, m_ptRubberEnd(0,0)
	, m_ptMoveCanvas(0,0)
	, m_bShowOverview(false)
	, m_parent(nullptr)
	, m_hoverIndex(nullptr)
	, m_hoverGlyphs (0)
	, m_tooltipIndex(nullptr)
	, m_showHoverGlyphs (false)
	, m_bIsCanvasMove(false)
	, m_previewWidth(0)
	, m_previewHeight(0)
	, m_previewZoom(1)
	, m_ullTicks(0)
	, m_logEntries(&m_LogCache)
	, m_bCurrentBranch(false)
	, m_bLocalBranches(FALSE)
{
	memset(&m_lfBaseFont, 0, sizeof(LOGFONT));
	std::fill_n(m_apFonts, MAXFONTS, nullptr);

	WNDCLASS wndcls;
	HINSTANCE hInst = AfxGetInstanceHandle();
#define REVGRAPH_CLASSNAME _T("Revgraph_windowclass")
	if (!(::GetClassInfo(hInst, REVGRAPH_CLASSNAME, &wndcls)))
	{
		// otherwise we need to register a new class
		wndcls.style			= CS_DBLCLKS | CS_OWNDC;
		wndcls.lpfnWndProc	  = ::DefWindowProc;
		wndcls.cbClsExtra	   = wndcls.cbWndExtra = 0;
		wndcls.hInstance		= hInst;
		wndcls.hIcon			= nullptr;
		wndcls.hCursor		  = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
		wndcls.hbrBackground	= (HBRUSH) (COLOR_WINDOW + 1);
		wndcls.lpszMenuName	 = nullptr;
		wndcls.lpszClassName	= REVGRAPH_CLASSNAME;

		RegisterClass(&wndcls);
	}

	m_bTweakTrunkColors = CRegDWORD(_T("Software\\TortoiseGit\\RevisionGraph\\TweakTrunkColors"), TRUE) != FALSE;
	m_bTweakTagsColors = CRegDWORD(_T("Software\\TortoiseGit\\RevisionGraph\\TweakTagsColors"), TRUE) != FALSE;
	m_szTip[0]  = 0;
	m_wszTip[0] = 0;

	m_GraphAttr.init(this->m_Graph, ogdf::GraphAttributes::nodeGraphics | ogdf::GraphAttributes::edgeGraphics |
		ogdf:: GraphAttributes::nodeLabel | ogdf::GraphAttributes::nodeColor |
		ogdf::GraphAttributes::edgeColor | ogdf::GraphAttributes::edgeStyle |
		ogdf::GraphAttributes::nodeStyle | ogdf::GraphAttributes::nodeTemplate);

	m_SugiyamLayout.setRanking(::new ogdf::OptimalRanking());
	m_SugiyamLayout.setCrossMin(::new ogdf::MedianHeuristic());

	double pi = 3.1415926;
	m_ArrowCos = cos(pi/8);
	m_ArrowSin = sin(pi/8);
	this->m_ArrowSize = 8;
#if 0
	ogdf::node one = this->m_Graph.newNode();
	ogdf::node two = this->m_Graph.newNode();
	ogdf::node three = this->m_Graph.newNode();
	ogdf::node four = this->m_Graph.newNode();


	m_GraphAttr.width(one)=100;
	m_GraphAttr.height(one)=200;
	m_GraphAttr.width(two)=100;
	m_GraphAttr.height(two)=100;
	m_GraphAttr.width(three)=100;
	m_GraphAttr.height(three)=20;
	m_GraphAttr.width(four)=100;
	m_GraphAttr.height(four)=20;

	m_GraphAttr.labelNode(one)="One";
	m_GraphAttr.labelNode(two)="Two";
	m_GraphAttr.labelNode(three)="three";

	this->m_Graph.newEdge(one, two);
	this->m_Graph.newEdge(one, three);
	this->m_Graph.newEdge(two, four);
	this->m_Graph.newEdge(three, four);

#endif
	FastHierarchyLayout *pOHL = ::new FastHierarchyLayout;
	//It will auto delte when m_SugiyamLayout destory

	pOHL->layerDistance(30.0);
	pOHL->nodeDistance(25.0);

	m_SugiyamLayout.setLayout(pOHL);

#if 0
	//this->m_OHL.layerDistance(30.0);
	//this->m_OHL.nodeDistance(25.0);
	//this->m_OHL.weightBalancing(0.8);
	m_SugiyamLayout.setLayout(&m_OHL);
	m_SugiyamLayout.call(m_GraphAttr);
#endif
#if 0
	PlanarizationLayout pl;

	FastPlanarSubgraph *ps = ::new FastPlanarSubgraph;
	ps->runs(100);
	VariableEmbeddingInserter *ves = ::new VariableEmbeddingInserter;
	ves->removeReinsert(EdgeInsertionModule::rrAll);
	pl.setSubgraph(ps);
	pl.setInserter(ves);

	EmbedderMinDepthMaxFaceLayers *emb = ::new EmbedderMinDepthMaxFaceLayers;
	pl.setEmbedder(emb);

	OrthoLayout *ol =::new OrthoLayout;
	ol->separation(20.0);
	ol->cOverhang(0.4);
	ol->setOptions(2+4);
	ol->preferedDir(OrthoDir::odEast);
	pl.setPlanarLayouter(ol);

	pl.call(m_GraphAttr);

	node v;
	forall_nodes(v,m_Graph) {

		TRACE(_T("node  x %f y %f %f %f\n"),/* m_GraphAttr.idNode(v), */
			m_GraphAttr.x(v),
			m_GraphAttr.y(v),
			m_GraphAttr.width(v),
			m_GraphAttr.height(v)
		);
	}
void ComponentLayouter::orthoGraphLayout(const SparseMatrix& veIncidenceMat, 
										const VectorXf& rVec, 
										MatrixXf& finalPos2D, 
										float& finalRadius , 
										QList<MatrixXf>& edgeList )
{
	typedef ogdf::Graph Graph;
	typedef ogdf::GraphAttributes GraphAttributes;

	int nVtx = rVec.size();
	int nEdge= veIncidenceMat.cols();

	Graph G;
	GraphAttributes GA(G,
		GraphAttributes::nodeGraphics | GraphAttributes::edgeGraphics );

	std::vector<node> nodeArray;
	std::vector<edge> edgeArray;
	for (int i = 0; i < nVtx; ++i)
	{
		nodeArray.push_back(G.newNode());
		GA.width(nodeArray.back()) = rVec[i]*2.f;
		GA.height(nodeArray.back())= rVec[i]*2.f;
	}

	for (int i = 0; i < nEdge; ++i)
	{
		int src, tar;
		GraphUtility::getVtxFromEdge(veIncidenceMat, i, src, tar);
		edgeArray.push_back(G.newEdge(nodeArray[src], nodeArray[tar]));
	}

	PlanarizationLayout pl;

// 	FastPlanarSubgraph *ps = new FastPlanarSubgraph;
// 	ps->runs(100);
// 	VariableEmbeddingInserter *ves = new VariableEmbeddingInserter;
// 	ves->removeReinsert(EdgeInsertionModule::rrAll);
// 
// 	pl.setSubgraph(ps);
// 	pl.setInserter(ves);
// 
// 	EmbedderMinDepthMaxFaceLayers *emb = new EmbedderMinDepthMaxFaceLayers;
// 	pl.setEmbedder(emb);
// 
// 	OrthoLayout *ol = new OrthoLayout;
// 	ol->separation(20.0);
// 	ol->cOverhang(0.4);
// 	ol->setOptions(2+4);

	//pl.setPlanarLayouter(ol);

	pl.call(GA);

	MatrixXd pos2D(nVtx, 2);
	for (int v = 0; v < nodeArray.size(); ++v)
	{
		double x = GA.x(nodeArray[v]);
		double y = GA.y(nodeArray[v]);
		pos2D(v, 0) = x;
		pos2D(v, 1) = y;
		//		cout << v << "th vtx: " << x << " " << y << endl;
	}
	VectorXd halfSize,offset;
	GeometryUtility::moveToOrigin(pos2D, rVec.cast<double>(), halfSize, &offset);
	finalPos2D  = pos2D.cast<float>();
	finalRadius = halfSize.norm();//(size[0] > size[1] ? size[0] : size[1]) * 0.5f;


	for(int e = 0; e < edgeArray.size(); ++e)
	{
		DPolyline& p = GA.bends(edgeArray[e]);
		int nPnts    = p.size();
		MatrixXf pntMat(nPnts,2);
		int ithPnt   = 0;
		for (DPolyline::iterator pLine = p.begin(); pLine != p.end(); ++pLine, ++ithPnt)
		{
			pntMat(ithPnt, 0) = (*pLine).m_x + offset[0];
			pntMat(ithPnt, 1) = (*pLine).m_y + offset[1];
		}
	}

}
Example #5
0
bool ClassLayouter::computeNormally()
{
    FuzzyDependAttr::Ptr fuzzyAttr = m_parent->getAttr<FuzzyDependAttr>();
    if (!fuzzyAttr)
        return false;

    Graph G;
    GraphAttributes GA(G,
                       GraphAttributes::nodeGraphics | GraphAttributes::edgeGraphics |
                       GraphAttributes::nodeLabel    | GraphAttributes::nodeTemplate |
                       GraphAttributes::edgeDoubleWeight);

    SparseMatrix& veMat = fuzzyAttr->vtxEdgeMatrix();
    VectorXd	  edgeWeight	= fuzzyAttr->edgeWeightVector();
    if (edgeWeight.size() != veMat.cols())
    {
        m_status |= WARNING_USE_DEFAULT_EDGE_WEIGHT;
        edgeWeight.setOnes(veMat.cols());
    }
    const int nNodes = veMat.rows();
    const int nEdges = veMat.cols();
    if (nNodes <= 0 || nNodes != m_childList.size() || nEdges < 1)
    {
        m_status |= WARNING_NO_EDGE;
        return false;
    }

    bool isUseOrthoLayout = nEdges < 50;

    vector<node> nodeArray;
    vector<edge> edgeArray;
    NodeArray<float> nodeSize(G);
    EdgeArray<double> edgeLength(G);
    for (int i = 0; i < nNodes; ++i)
    {
        nodeArray.push_back(G.newNode());
        float r = m_nodeRadius[i];
        GA.width(nodeArray.back()) = r*2;
        GA.height(nodeArray.back()) = r*2;
        nodeSize[nodeArray.back()] = r * 2;
    }

    float maxEdgeWeight = edgeWeight.maxCoeff();
    float minEdgeWeight = edgeWeight.minCoeff();
    for (int ithEdge = 0; ithEdge < nEdges; ++ithEdge)
    {
        int src, dst;
        GraphUtility::getVtxFromEdge(veMat, ithEdge, src, dst);
        edgeArray.push_back(G.newEdge(nodeArray[src], nodeArray[dst]));
        //GA.doubleWeight(edgeArray.back()) = edgeWeight[ithEdge];
        edgeLength[edgeArray.back()] = 1;//log(edgeWeight[ithEdge] + 1);
    }


    // add dummy vertices and edges in order to merge parallel edge segments attached to the same node
    VectorXi compVec;
    int nComp = 1;
    const float dummyNodeRadius = 0.01;
    if(m_isMergeEdgeEnd && isUseOrthoLayout && GraphUtility::findConnectedComponentsVE(	veMat, compVec, nComp ))
    {
        bool* isCompSet = new bool[nComp];
        for (int i = 0; i < nComp; ++i)
            isCompSet[i] = false;

        // add a dummy node and edge for each connect component
        for (int ithVtx = 0; ithVtx < compVec.size(); ++ithVtx)
        {
            int ithCmp = compVec[ithVtx];
            if (isCompSet[ithCmp] == false)
            {
                // add dummy node and set its radius
                nodeArray.push_back(G.newNode());
                GA.width(nodeArray.back()) = dummyNodeRadius;
                GA.height(nodeArray.back()) = dummyNodeRadius;
                // add dummy edge
                edgeArray.push_back(G.newEdge(nodeArray[ithVtx], nodeArray.back()));
                isCompSet[ithCmp] = true;
            }
        }
        delete[] isCompSet;
    }


    MatrixXd pos;
    pos.resize(nNodes, 2);
    try
    {
        if (isUseOrthoLayout)
        {
            PlanarizationLayout layouter;
            OrthoLayout *ol = new OrthoLayout;
            float sep = max(m_nodeRadius.sum() / nNodes, LayoutSetting::s_baseRadius * 12);
            ol->separation(sep);
            ol->cOverhang(0.1);
            ol->setOptions(1+4);
            layouter.setPlanarLayouter(ol);
            layouter.call(GA);
            for (int v = 0; v < nNodes; ++v)
            {
                double x = GA.x(nodeArray[v]);
                double y = GA.y(nodeArray[v]);
                pos(v,0) = x;
                pos(v,1) = y;
            }
        }
        else
        {
            FMMMLayout layouter;
            //CircularLayout layouter;
            float avgRadius = m_nodeRadius.sum();
            layouter.unitEdgeLength(avgRadius * 4);
            //layouter.call(GA, edgeLength);
            layouter.call(GA);
            // 	layouter.resizeDrawing(true);
            // 	layouter.resizingScalar(3);

            for (int v = 0; v < nNodes; ++v)
            {
                double x = GA.x(nodeArray[v]);
                double y = GA.y(nodeArray[v]);
                pos(v,0) = x;
                pos(v,1) = y;
            }

            MDSPostProcesser m_postProcessor(5000, 1, 1.0, 1.0, LayoutSetting::s_baseRadius * 2);
            m_postProcessor.set2DPos(pos, m_nodeRadius.cast<double>());
            m_postProcessor.compute();
            m_postProcessor.getFinalPos(pos);
        }
    }
    catch(...)//AlgorithmFailureException e
    {
        return false;
    }

    VectorXd halfSize,offset;
    GeometryUtility::moveToOrigin(pos, m_nodeRadius.cast<double>(), halfSize, &offset);
    m_nodePos = pos.cast<float>();

    // postprocessing, and set edges
    float edgeBound[2] = {halfSize[0], halfSize[1]};
    if (isUseOrthoLayout)
    {
        for(int ithEdge = 0; ithEdge < nEdges; ++ithEdge)
        {
            DPolyline& p = GA.bends(edgeArray[ithEdge]);
            int nPoints = p.size();

            BSpline splineBuilder(5, BSpline::BSPLINE_OPEN_UNIFORM, true);
            int ithPnt = 0;
            for (DPolyline::iterator pLine = p.begin(); pLine != p.end(); ++pLine, ++ithPnt)
            {
                float px = (*pLine).m_x + offset[0];
                float py = (*pLine).m_y + offset[1];
                splineBuilder.addPoint(px,py);
                splineBuilder.addPoint(px,py);
            }
            splineBuilder.computeLine((nPoints) * 5);
            const QList<QPointF>& curve = splineBuilder.getCurvePnts();

            m_edgeParam.push_back(EdgeParam());
            EdgeParam& ep = m_edgeParam.back();
            ep.m_points.resize(curve.size(),2);
            for (int i = 0; i < curve.size(); ++i)
            {
                ep.m_points(i, 0) = curve[i].x();
                ep.m_points(i, 1) = curve[i].y();

                edgeBound[0] = qMax(edgeBound[0], (float)qAbs(curve[i].x()));
                edgeBound[1] = qMax(edgeBound[1], (float)qAbs(curve[i].y()));
            }
            ep.m_weight = edgeWeight[ithEdge];
        }
    }
    else
    {
        DelaunayCore::DelaunayRouter router;
        router.setLaneWidthRatio(2);
        router.setSmoothParam(0.5,2);
        router.setEndPointNormalRatio(0.8);
        computeEdgeRoute(router);
    }

    m_totalRadius = qSqrt(edgeBound[0]*edgeBound[0] + edgeBound[1]*edgeBound[1]);
    return true;
}