private void DetermineFinalPositions(ITreeNode tn, int iLayer, double pxFromTop, double pxParentFromLeft) { double pxRowHeight = _lstLayerHeight[iLayer]; LayeredTreeInfo lti = Info(tn); double pxBottom; DPoint dptOrigin; lti.pxFromTop = pxFromTop + CalcJustify(tn.TreeHeight, pxRowHeight); pxBottom = lti.pxFromTop + tn.TreeHeight; if (pxBottom > PxOverallHeight) { PxOverallHeight = pxBottom; } lti.pxFromLeft = lti.pxLeftPosRelativeToParent + pxParentFromLeft; dptOrigin = new DPoint(lti.pxFromLeft + tn.TreeWidth / 2, lti.pxFromTop + tn.TreeHeight); iLayer++; foreach (ITreeNode tnCur in GetChildren(tn)) { List <DPoint> lstcpt = new List <DPoint>(); LayeredTreeInfo ltiCur = Info(tnCur); lstcpt.Add(dptOrigin); DetermineFinalPositions(tnCur, iLayer, pxFromTop + pxRowHeight + _pxBufferVertical, lti.pxFromLeft); lstcpt.Add(new DPoint(ltiCur.pxFromLeft + tnCur.TreeWidth / 2, ltiCur.pxFromTop)); _lsttcn.Add(new TreeConnection(tn, tnCur, lstcpt)); } }
private void CalculateBoundaryLists(ITreeNode tnRoot) { LayeredTreeInfo lti = Info(tnRoot); lti.lstPosLeftBoundaryRelativeToRoot.Add(0.0); lti.lstPosRightBoundaryRelativeToRoot.Add(tnRoot.TreeWidth); DetermineBoundary(tnRoot.TreeChildren, true /* fLeft */, lti.lstPosLeftBoundaryRelativeToRoot); DetermineBoundary(tnRoot.TreeChildren.Reverse(), false /* fLeft */, lti.lstPosRightBoundaryRelativeToRoot); }
private static void LayoutLeafNode(ITreeNode tnRoot) { double width = tnRoot.TreeWidth; LayeredTreeInfo lti = new LayeredTreeInfo(width, tnRoot); lti.lstPosLeftBoundaryRelativeToRoot.Add(0); lti.lstPosRightBoundaryRelativeToRoot.Add(width); tnRoot.PrivateNodeInfo = lti; }
private void DetermineParentRelativePositionsOfChildren(ITreeNode tnRoot) { LayeredTreeInfo ltiRoot = Info(tnRoot); foreach (ITreeNode tn in GetChildren(tnRoot)) { LayeredTreeInfo ltiCur = Info(tn); ltiCur.pxLeftPosRelativeToParent = ltiCur.pxLeftPosRelativeToBoundingBox - ltiRoot.pxLeftPosRelativeToBoundingBox; } }
private void DetermineFinalPositions(ITreeNode tn, int iLayer, double pxFromTop, double pxParentFromLeft) { double pxRowHeight = _lstLayerHeight[iLayer]; LayeredTreeInfo lti = Info(tn); double pxBottom; DPoint dptOrigin; lti.pxFromTop = pxFromTop + CalcJustify(tn.TreeHeight, pxRowHeight); pxBottom = lti.pxFromTop + tn.TreeHeight; if (pxBottom > PxOverallHeight) { PxOverallHeight = pxBottom; } lti.pxFromLeft = lti.pxLeftPosRelativeToParent + pxParentFromLeft; dptOrigin = new DPoint(lti.pxFromLeft + tn.TreeWidth / 2, lti.pxFromTop + tn.TreeHeight); iLayer++; TreeNodeGroup tng = GetChildren(tn); foreach (ITreeNode tnCur in tng) { //斜线连接 //List<DPoint> lstcpt = new List<DPoint>(); //LayeredTreeInfo ltiCur = Info(tnCur); //lstcpt.Add(dptOrigin); //DetermineFinalPositions(tnCur, iLayer, pxFromTop + pxRowHeight + _pxBufferVertical, lti.pxFromLeft); //lstcpt.Add(new DPoint(ltiCur.pxFromLeft + tnCur.TreeWidth / 2, ltiCur.pxFromTop)); //_lsttcn.Add(new TreeConnection(tn, tnCur, lstcpt)); //横竖线连接 List <DPoint> lstcpt = new List <DPoint>(); LayeredTreeInfo ltiCur = Info(tnCur); lstcpt.Add(dptOrigin); DetermineFinalPositions(tnCur, iLayer, pxFromTop + pxRowHeight + _pxBufferVertical, lti.pxFromLeft); //If parent node has only one child then no changes here, just a normal TreeConnection if (tng.Count == 1) { lstcpt.Add(new DPoint(ltiCur.pxFromLeft + tnCur.TreeWidth / 2, ltiCur.pxFromTop)); _lsttcn.Add(new TreeConnection(tn, tnCur, lstcpt)); } else { //If parent node has more than one child then add the extra connection points double halfHeight = (ltiCur.pxFromTop - dptOrigin.Y) / 2; DPoint p2 = new DPoint(dptOrigin.X, dptOrigin.Y + halfHeight); lstcpt.Add(p2); DPoint p3 = new DPoint(ltiCur.pxFromLeft + tnCur.TreeWidth / 2, dptOrigin.Y + halfHeight); lstcpt.Add(p3); DPoint p4 = new DPoint(ltiCur.pxFromLeft + tnCur.TreeWidth / 2, ltiCur.pxFromTop + 5); lstcpt.Add(p4); _lsttcn.Add(new TreeConnection(tn, tnCur, lstcpt)); } } }
private void RepositionSubtree( int itn, TreeNodeGroup tngSiblings, List <double> lstLeftToBB, List <int> lsttnResponsible) { int itnResponsible; ITreeNode tn = tngSiblings[itn]; LayeredTreeInfo lti = Info(tn); if (itn == 0) { // No shifting but we still have to prepare the initial version of the // left hand skeleton list foreach (double pxRelativeToRoot in lti.lstPosRightBoundaryRelativeToRoot) { lstLeftToBB.Add(pxRelativeToRoot + lti.pxLeftPosRelativeToBoundingBox); lsttnResponsible.Add(0); } return; } ITreeNode tnLeft = tngSiblings[itn - 1]; //LayeredTreeInfo ltiLeft = Info(tnLeft); int iLayer; double pxHorizontalBuffer = _pxBufferHorizontal; double pxNewPosFromBB = PxCalculateNewPos(lti, lstLeftToBB, lsttnResponsible, out itnResponsible, out iLayer); if (iLayer != 0) { pxHorizontalBuffer = _pxBufferHorizontalSubtree; } lti.pxToLeftSibling = pxNewPosFromBB - lstLeftToBB.First() + tnLeft.TreeWidth + pxHorizontalBuffer; int cLevels = Math.Min(lti.lstPosRightBoundaryRelativeToRoot.Count, lstLeftToBB.Count); for (int i = 0; i < cLevels; i++) { lstLeftToBB[i] = lti.lstPosRightBoundaryRelativeToRoot[i] + pxNewPosFromBB + pxHorizontalBuffer; lsttnResponsible[i] = itn; } for (int i = lstLeftToBB.Count; i < lti.lstPosRightBoundaryRelativeToRoot.Count; i++) { lstLeftToBB.Add(lti.lstPosRightBoundaryRelativeToRoot[i] + pxNewPosFromBB + pxHorizontalBuffer); lsttnResponsible.Add(itn); } ApportionSlop(itn, itnResponsible, tngSiblings); }
private void ApportionSlop(int itn, int itnResponsible, TreeNodeGroup tngSiblings) { LayeredTreeInfo lti = Info(tngSiblings[itn]); ITreeNode tnLeft = tngSiblings[itn - 1]; double pxSlop = lti.pxToLeftSibling - tnLeft.TreeWidth - _pxBufferHorizontal; if (pxSlop > 0) { for (int i = itnResponsible + 1; i < itn; i++) { Info(tngSiblings[i]).pxToLeftSibling += pxSlop * (i - itnResponsible) / (itn - itnResponsible); } lti.pxToLeftSibling -= (itn - itnResponsible - 1) * pxSlop / (itn - itnResponsible); } }
private double PxCalculateNewPos( LayeredTreeInfo lti, List <double> lstLeftToBB, List <int> lstitnResponsible, out int itnResponsible, out int iLayerRet) { //double pxOffsetToBB = lstLeftToBB[0]; int cLayers = Math.Min(lti.lstPosLeftBoundaryRelativeToRoot.Count, lstLeftToBB.Count); double pxRootPosRightmost = 0.0; iLayerRet = 0; using (IEnumerator <double> enRight = lti.lstPosLeftBoundaryRelativeToRoot.GetEnumerator(), enLeft = lstLeftToBB.GetEnumerator()) using (IEnumerator <int> enResponsible = lstitnResponsible.GetEnumerator()) { itnResponsible = -1; enRight.MoveNext(); enLeft.MoveNext(); enResponsible.MoveNext(); for (int iLayer = 0; iLayer < cLayers; iLayer++) { double pxLeftBorderFromBB = enLeft.Current; double pxRightBorderFromRoot = enRight.Current; double pxRightRootBasedOnThisLevel; int itnResponsibleCur = enResponsible.Current; enLeft.MoveNext(); enRight.MoveNext(); enResponsible.MoveNext(); pxRightRootBasedOnThisLevel = pxLeftBorderFromBB - pxRightBorderFromRoot; if (pxRightRootBasedOnThisLevel > pxRootPosRightmost) { iLayerRet = iLayer; pxRootPosRightmost = pxRightRootBasedOnThisLevel; itnResponsible = itnResponsibleCur; } } } return(pxRootPosRightmost); }
private void LayoutInteriorNode(ITreeNode tnRoot, int iLayer) { ITreeNode tnLast = null; TreeNodeGroup tng = GetChildren(tnRoot); LayeredTreeInfo ltiThis; LayoutAllOurChildren(iLayer, tnLast, tng); // This width doesn't account for the parent node's width... ltiThis = new LayeredTreeInfo(CalculateWidthFromInterChildDistances(tnRoot), tnRoot); tnRoot.PrivateNodeInfo = ltiThis; // ...so that this centering may place the parent node negatively while the "width" is the width of // all the child nodes. CenterOverChildren(tnRoot, ltiThis); DetermineParentRelativePositionsOfChildren(tnRoot); CalculateBoundaryLists(tnRoot); }
private static void CenterOverChildren(ITreeNode tnRoot, LayeredTreeInfo ltiThis) { // We should be centered between the connection points of our children... ITreeNode tnLeftMost = tnRoot.TreeChildren.LeftMost(); double pxLeftChild = Info(tnLeftMost).pxLeftPosRelativeToBoundingBox + tnLeftMost.TreeWidth / 2; ITreeNode tnRightMost = tnRoot.TreeChildren.RightMost(); double pxRightChild = Info(tnRightMost).pxLeftPosRelativeToBoundingBox + tnRightMost.TreeWidth / 2; ltiThis.pxLeftPosRelativeToBoundingBox = (pxLeftChild + pxRightChild - tnRoot.TreeWidth) / 2; // If the m_RootNode node was wider than the subtree, then we'll have a negative position for it. We need // to readjust things so that the left of the m_RootNode node represents the left of the bounding box and // the child distances to the Bounding box need to be adjusted accordingly. if (ltiThis.pxLeftPosRelativeToBoundingBox < 0) { foreach (ITreeNode tnChildCur in tnRoot.TreeChildren) { Info(tnChildCur).pxLeftPosRelativeToBoundingBox -= ltiThis.pxLeftPosRelativeToBoundingBox; } ltiThis.pxLeftPosRelativeToBoundingBox = 0; } }
private void DetermineBoundary(IEnumerable <ITreeNode> entn, bool fLeft, List <double> lstPos) { int cLayersDeep = 1; List <double> lstPosCur; foreach (ITreeNode tnChild in entn) { LayeredTreeInfo ltiChild = Info(tnChild); if (fLeft) { lstPosCur = ltiChild.lstPosLeftBoundaryRelativeToRoot; } else { lstPosCur = ltiChild.lstPosRightBoundaryRelativeToRoot; } if (lstPosCur.Count >= lstPos.Count) { using (IEnumerator <double> enPosCur = lstPosCur.GetEnumerator()) { for (int i = 0; i < cLayersDeep - 1; i++) { enPosCur.MoveNext(); } while (enPosCur.MoveNext()) { lstPos.Add(enPosCur.Current + ltiChild.pxLeftPosRelativeToParent); cLayersDeep++; } } } } }