private static GraphicsPath WarpSubpath(GraphicsPath pathToWarp, SortedList <float, GraphSegment> edges, ref int currentIndex) { //midpoint of figure float minX = float.MaxValue, maxX = float.MinValue; PointF[] pathPoints = pathToWarp.PathPoints; for (int i = 0; i < pathToWarp.PointCount; i++) { minX = Math.Min(minX, pathPoints[i].X); maxX = Math.Max(maxX, pathPoints[i].X); } float ordinateX = (minX + maxX) * 0.5f; //seek pathToWarpTo segment while (true) { if (edges.Keys[currentIndex] <= ordinateX && ((currentIndex == edges.Keys.Count - 1) || ordinateX < edges.Keys[currentIndex + 1])) { break; } if (ordinateX < edges.Keys[currentIndex]) { if (currentIndex == 0) { break; } currentIndex--; } else { if (currentIndex == edges.Count + 1) { break; } currentIndex++; } } GraphSegment s = edges.Values[currentIndex]; float dy = s.DX; float dx = s.DY; PointF[] warpedPathPoints = new PointF[pathToWarp.PointCount]; for (int i = 0; i < pathToWarp.PointCount; i++) { float ptX = pathPoints[i].X; float ptY = pathPoints[i].Y; PointF linePt = s.GetLinePoint(ptX); ptX = -ptY * dx; ptY = ptY * dy; warpedPathPoints[i] = new PointF(linePt.X + ptX, linePt.Y + ptY); } return(new GraphicsPath(warpedPathPoints, pathToWarp.PathTypes, pathToWarp.FillMode)); }
/// <summary> /// for a given node returns all the child nodes /// </summary> /// <param name="nodeValue"></param> /// <param name="parentNodePath"></param> /// <returns></returns> public static List <Tuple <object, GraphPath> > GetChildTraversalNodes(object nodeValue, GraphPath parentNodePath, Func <object, GraphPath, bool> doNotTraverseFilter = null) { List <Tuple <object, GraphPath> > rv = new List <Tuple <object, GraphPath> >(); //if the node is IEnumerable, recurse here if (nodeValue is IEnumerable && (nodeValue is string) == false) { IEnumerable objEnumerable = nodeValue as IEnumerable; int index = 0; foreach (var each in objEnumerable) { //build the path var path = GraphPath.New(parentNodePath); path.AddSegment(EnumeratedItemSegment.New(index)); if (doNotTraverseFilter != null && doNotTraverseFilter(each, path)) { continue; } rv.Add(new Tuple <object, GraphPath>(each, path)); index++; } } else { //recurse the fields var fields = GraphingUtil.GetNestingNotatedFieldInfos(nodeValue.GetType()); foreach (var field in fields) { //get field value var obj = field.Item2.GetValue(nodeValue); var path = GraphPath.New(parentNodePath); path.AddSegment(GraphSegment.New(field.Item1)); if (doNotTraverseFilter != null && doNotTraverseFilter(obj, path)) { continue; } //build the node and recurse rv.Add(new Tuple <object, GraphPath>(obj, path)); } } return(rv); }
/// <summary> /// Calculates the length of all segments in the Path, visible or not /// </summary> /// <param name="path">A flattened <see cref="GraphicsPath"/></param> /// <param name="edges">A <see cref="SortedList{TKey, TValue}"/> containing edges of the path. </param> /// <returns>the length</returns> internal static double GetPathLength(GraphicsPath path, out SortedList <float, GraphSegment> edges) { float length = 0; edges = new SortedList <float, GraphSegment>(path.PointCount - 2); PointF ptLast = new PointF(); PointF ptClose = new PointF(); for (int i = 0; i < path.PointCount; i++) { var ptCurr = path.PathPoints[i]; if (path.PathTypes[i] == (byte)PathPointType.Start) { ptClose = ptCurr; } if (ptCurr.Equals(ptLast)) { continue; } if (!ptLast.IsEmpty) { var gs = new GraphSegment(length, ptLast, ptCurr); edges.Add(length, gs); length += gs.Length; if ((path.PathTypes[i] & (byte)PathPointType.CloseSubpath) == (byte)PathPointType.CloseSubpath) { gs = new GraphSegment(length, ptCurr, ptClose); edges.Add(length, gs); length += gs.Length; ptLast = ptClose; } else { ptLast = ptCurr; } } else { ptLast = ptCurr; } } return(length); }
/// <summary> /// given a parent node and a store of nodes, identifies the children of the parent and wires /// their values to the parent node's value /// </summary> /// <param name="parentNode"></param> /// <param name="nodeStore"></param> private void WireParentToChildren(GraphNode parentNode, IStoreOf <GraphNode> nodeStore) { Condition.Requires(parentNode).IsNotNull(); Condition.Requires(nodeStore).IsNotNull(); List <string> skipFilter = new List <string>() { NullValueManager.ID, DelegateValueManager.ID, PrimitiveValueManager.ID }; if (skipFilter.Contains(parentNode.ValueManagerId)) { return; } var children = nodeStore.GetImmediateChildNodes(parentNode.Path).OrderBy((x) => { return(x.Path.EnumeratedSegmentIndex); }).ToList(); var fields = GraphingUtil.GetNestingNotatedFieldInfos(parentNode.NodeValue.GetType()); //get the manager for this node value var manager = this.ChainOfResponsibility.FindHandlingValueManager(parentNode.NodeValue, this); Condition.Requires(manager).IsNotNull(); var traverseList = manager.GetChildTraversalNodes(parentNode.NodeValue, parentNode.Path); traverseList.WithEach(tuple => { BuildNode(tuple.Item1, tuple.Item2); }); foreach (var each in children) { //add the children if (each.Path.IsEnumeratedSegment) { if (each.NodeValue is IDictionary) { IDictionary dict = parentNode.NodeValue as IDictionary; DictionaryEntry de = (DictionaryEntry)each.NodeValue; dict.Add(de.Key, de.Value); } else if (each.NodeValue is Stack) { Stack stack = parentNode.NodeValue as Stack; stack.Push(each.NodeValue); } else if (each.NodeValue is Queue) { Queue queue = parentNode.NodeValue as Queue; queue.Enqueue(each.NodeValue); } else if (each.NodeValue is IList) { IList list = parentNode.NodeValue as IList; list.Add(each.NodeValue); } } else { //get the matching field GraphSegment gSeg = each.Path.CurrentSegment as GraphSegment; //TODO: refactor implicit contract - that the paths match field names (GraphingUtil.GetNestingNotatedFieldInfos) var matches = fields.Filter((x) => { return(x.Item1 == gSeg.Path); }); Condition.Requires(matches).IsNotNull().HasLength(1); var fi = matches.First(); fi.Item2.SetValue(parentNode.NodeValue, each.NodeValue); } } }
/// <summary> /// Calculates the length of all segments in the Path, visible or not /// </summary> /// <param name="path">A flattened <see cref="GraphicsPath"/></param> /// <param name="edges">A <see cref="SortedList{TKey, TValue}"/> containing edges of the path. </param> /// <returns>the length</returns> internal static double GetPathLength(GraphicsPath path, out SortedList<float, GraphSegment> edges) { float length = 0; edges = new SortedList<float, GraphSegment>(path.PointCount - 2); PointF ptLast = new PointF(); PointF ptClose = new PointF(); for (int i = 0; i < path.PointCount; i++) { var ptCurr = path.PathPoints[i]; if (path.PathTypes[i] == (byte)PathPointType.Start) ptClose = ptCurr; if (ptCurr.Equals(ptLast)) continue; if (!ptLast.IsEmpty) { var gs = new GraphSegment(length, ptLast, ptCurr); edges.Add(length, gs); length += gs.Length; if ((path.PathTypes[i] & (byte)PathPointType.CloseSubpath) == (byte)PathPointType.CloseSubpath) { gs = new GraphSegment(length, ptCurr, ptClose); edges.Add(length, gs); length += gs.Length; ptLast = ptClose; } else { ptLast = ptCurr; } } else { ptLast = ptCurr; } } return length; }