void MapPathToItsObstacles(Path path) {
     var startNode = HierarchyOfObstacles.FirstHitNode(path.PathPoints.First(),ObstacleTest);
     var endNode = HierarchyOfObstacles.FirstHitNode(path.PathPoints.Last(), ObstacleTest);
     if ((null != startNode) && (null != endNode)) {
         PathToObstacles[path] = new Tuple<Polyline, Polyline>(startNode.UserData, endNode.UserData);
     }
 }
        void FillTheVisibilityGraphByWalkingPath(Path path){
            var pathEdgesEnum = CreatePathEdgesFromPoints(path.PathPoints, path.Width).GetEnumerator();

            if (pathEdgesEnum.MoveNext())
                path.SetFirstEdge(pathEdgesEnum.Current);
            
            while(pathEdgesEnum.MoveNext())
                path.AddEdge(pathEdgesEnum.Current);
        }
//        bool Correct() {
//            foreach (var kv in verticesToPathOffsets) {
//                Point p = kv.Key;
//                Dictionary<Path, LinkedPoint> pathOffs = kv.Value;
//                foreach (var pathOff in pathOffs) {
//                    var path = pathOff.Key;
//                    var linkedPoint = pathOff.Value;
//                    if (linkedPoint.Point != p)
//                        return false;
//                    if (FindLinkedPointInPath(path, p) == null) {
//                        return false;
//                    }
//                }
//            }
//            return true;
//        }

        void CollapseLoopingPath(Path loopingPath, LinkedPoint departureFromLooping, LinkedPoint arrivalToLooping, Path stemPath, LinkedPoint arrivalToStem){
            var departurePointOnStem = FindLinkedPointInPath(stemPath, departureFromLooping.Point);
            IEnumerable<Point> pointsToInsert = GetPointsInBetween(departurePointOnStem, arrivalToStem);
            if(Before(departureFromLooping, arrivalToLooping)){
                CleanDisappearedPiece(departureFromLooping, arrivalToLooping, loopingPath);
                ReplacePiece(departureFromLooping, arrivalToLooping, pointsToInsert,loopingPath);
            }else{
                CleanDisappearedPiece(arrivalToLooping, departureFromLooping, loopingPath);
                ReplacePiece(arrivalToLooping, departureFromLooping, pointsToInsert.Reverse(),loopingPath);
            }
        }
 bool ProcessPath(Path path) {
     var pts = (Point[])path.PathPoints;
     bool canHaveStaircase;
     if (ProcessPoints(ref pts, out canHaveStaircase)) {
         path.PathPoints = pts;
         return true;
     }
     if (!canHaveStaircase)
         crossedOutPaths.Insert(path);
     return false;
 }
        void ProcessPath(Path path) {
            var departedPaths = new Dictionary<Path, LinkedPoint>();
            Dictionary<Path, LinkedPoint> prevLocationPathOffsets = null;
            for (var linkedPoint = (LinkedPoint) path.PathPoints; linkedPoint != null; linkedPoint = linkedPoint.Next) {
                var pathOffsets = verticesToPathOffsets[linkedPoint.Point];
                if (prevLocationPathOffsets != null) {
                    //handle returning paths
                    if (departedPaths.Count > 0)
                        foreach (var pair in pathOffsets) {
                            LinkedPoint departerLinkedPoint;
                            var path0 = pair.Key;
                            if (departedPaths.TryGetValue(path0, out departerLinkedPoint)) {//returned!
                                CollapseLoopingPath(path0, departerLinkedPoint, pair.Value, path, linkedPoint);
                                departedPaths.Remove(path0);
                            }
                        }

                    //find departed paths
                    foreach (var pair in prevLocationPathOffsets.Where(pair => !pathOffsets.ContainsKey(pair.Key)))
                        departedPaths.Add(pair.Key, pair.Value);
                }
                prevLocationPathOffsets = pathOffsets;
            }
        }
 internal virtual void SpliceVisibilityAndGeneratePath(MsmtRectilinearPath shortestPathRouter, Path edgePath) {
     this.PortManager.AddControlPointsToGraph(edgePath.EdgeGeometry, this.ShapeToObstacleMap);
     this.PortManager.TransUtil.DevTrace_VerifyAllVertices(this.VisibilityGraph);
     this.PortManager.TransUtil.DevTrace_VerifyAllEdgeIntersections(this.VisibilityGraph);
     if (!this.GeneratePath(shortestPathRouter, edgePath)) {
         this.RetryPathsWithAdditionalGroupsEnabled(shortestPathRouter, edgePath);
     }
     this.PortManager.RemoveControlPointsFromGraph();
 }
 internal virtual void GeneratePathThroughVisibilityIntersection(Path edgePath, Point[] intersectPoints) {
     edgePath.PathPoints = intersectPoints;
 }
 static IEnumerable<DebugCurve> PathDebugCurves(Path path, string color) {
     var d = path.PathEdges.Select(e => new DebugCurve(70, 0.5, color, new LineSegment(e.Source, e.Target)));
     return d.Concat(MarkPathVerts(path));
 }
 void CleanDisappearedPiece(LinkedPoint a, LinkedPoint b, Path loopingPath){
     foreach (var point in GetPointsInBetween(a, b)) {
         var pathOffset = verticesToPathOffsets[point];
         Debug.Assert(pathOffset.ContainsKey(loopingPath));
         pathOffset.Remove(loopingPath);
     }
 }
 private static void EnsureNonNullPath(Path edgePath) {
     if (null == edgePath.PathPoints) {
         // Probably a fully-landlocked obstacle such as RectilinearTests.Route_Between_Two_Separately_Landlocked_Obstacles
         // or disconnected subcomponents due to excessive overlaps, such as Rectilinear(File)Tests.*Disconnected*.  In this
         // case, just put the single-bend path in there, even though it most likely cuts across unrelated obstacles.
         if (PointComparer.IsPureDirection(edgePath.EdgeGeometry.SourcePort.Location, edgePath.EdgeGeometry.TargetPort.Location)) {
             edgePath.PathPoints = new[] {
                     edgePath.EdgeGeometry.SourcePort.Location,
                     edgePath.EdgeGeometry.TargetPort.Location
             };
             return;
         }
         edgePath.PathPoints = new[] {
             edgePath.EdgeGeometry.SourcePort.Location,
             new Point(edgePath.EdgeGeometry.SourcePort.Location.X, edgePath.EdgeGeometry.TargetPort.Location.Y),
             edgePath.EdgeGeometry.TargetPort.Location
         };
     }
 }
 private static bool GetSingleStagePath(Path edgePath, MsmtRectilinearPath shortestPathRouter,
             List<VisibilityVertex> sourceVertices, List<VisibilityVertex> targetVertices, bool lastChance) {
     edgePath.PathPoints = shortestPathRouter.GetPath(sourceVertices, targetVertices);
     if (lastChance) {
         EnsureNonNullPath(edgePath);
     }
     return (edgePath.PathPoints != null);
 }
 void CreateLongestNudgedSegmentsForPath(Path path, PointProjection projectionToPerp) {
     //ShowEdgesOfEdgePath(path);
     GoOverPathAndCreateLongSegs(path);
     CalculateIdealPositionsForLongestSegs(path, projectionToPerp);
 }
 void BoundAxisEdgesAdjacentToSourceAndTargetOnEdge(Path path) {
     BoundAxisEdgeAdjacentToObstaclePort(path.EdgeGeometry.SourcePort, path.FirstEdge.AxisEdge);
     BoundAxisEdgeAdjacentToObstaclePort(path.EdgeGeometry.TargetPort, path.LastEdge.AxisEdge);
 }
        static IEnumerable<DebugCurve> GetTestPathAsDebugCurve(double startWidth, double endWidth, string color, Path path) {
            if (path.PathEdges.Count() > 0) {
                int count = path.PathEdges.Count();

                double deltaW = count > 1 ? (endWidth - startWidth)/(count - 1) : 1;
                    //if count ==1 the value of deltaW does not matter
                int i = 0;
                foreach (var e in path.PathEdges)
                    yield return
                        new DebugCurve(150, startWidth + deltaW*(i++), color, new LineSegment(e.Source, e.Target));
            }else {
                int count = path.PathPoints.Count();
                var pts = path.PathPoints.ToArray();

                var deltaW = count > 1 ? (endWidth - startWidth) / (count - 1) : 1;
                //if count ==1 the value of deltaW does not matter
                for (int i = 0; i < count - 1;i++ )
                    yield return new DebugCurve(150, startWidth+deltaW*i, color, new LineSegment(pts[i], pts[i+1]));                    
            }
        }
 void BoundPathByMinCommonAncestors(Path path) {
     foreach (var rect in GetMinCommonAncestors(path.EdgeGeometry).Select(sh => sh.BoundingBox))
         foreach (
             var edge in
                 path.PathEdges.Select(e => e.AxisEdge).Where(
                     axisEdge => axisEdge.Direction == NudgingDirection)
             )
             BoundAxisEdgeByRect(rect, edge);
 }
 static internal IEnumerable<DebugCurve> PathDebugCurvesFromPoint(Path path) {
     var l = new List<Point>(path.PathPoints);
     for (int i = 0; i < l.Count - 1; i++)
         yield return new DebugCurve(4, "red", new LineSegment(l[i], l[i + 1]));
 }
 private static IEnumerable<DebugCurve> MarkPathVerts(Path path) {
     bool first = true;
     var p = new Point();
     foreach (var p0 in path.PathPoints) {
         if (first) {
             yield return new DebugCurve(200, 1, "violet", CurveFactory.CreateDiamond(5, 5, p0));
             first = false;
         } else
             yield return new DebugCurve(100, 0.5, "brown", CurveFactory.CreateEllipse(1.5, 1.5, p0));
         p = p0;
     }
     yield return new DebugCurve(200, 1, "green", CurveFactory.CreateDiamond(3, 3, p));
 }
        private void ShowEdgePath(Path path) {
// ReSharper restore UnusedMember.Local
            List<DebugCurve> dd = Nudger.GetObstacleBoundaries(PaddedObstacles, "black");
            dd.AddRange(Nudger.PathDebugCurvesFromPoint(path));
            dd.AddRange(VisibilityGraph.Edges.Select(e => new DebugCurve(0.5, "blue", new LineSegment(e.SourcePoint, e.TargetPoint))));
            LayoutAlgorithmSettings.ShowDebugCurvesEnumeration(dd);
        }
 internal virtual bool GeneratePath(MsmtRectilinearPath shortestPathRouter, Path edgePath, bool lastChance = false) {
     var sourceVertices = PortManager.FindVertices(edgePath.EdgeGeometry.SourcePort);
     var targetVertices = PortManager.FindVertices(edgePath.EdgeGeometry.TargetPort);
     return edgePath.EdgeGeometry.HasWaypoints 
             ? this.GetMultiStagePath(edgePath, shortestPathRouter, sourceVertices, targetVertices, lastChance) 
             : GetSingleStagePath(edgePath, shortestPathRouter, sourceVertices, targetVertices, lastChance);
 }
 static void CalculateIdealPositionsForLongestSegs(Path path, PointProjection projectionToPerp) {
     LongestNudgedSegment currentLongSeg = null;
     LongestNudgedSegment ret = null;
     double prevOffset = projectionToPerp(path.Start);
     foreach (var edge in path.PathEdges) {
         if (edge.LongestNudgedSegment != null) {
             currentLongSeg = edge.LongestNudgedSegment;
             if (ret != null) {
                 double t;
                 SetIdealPositionForSeg(ret, t = projectionToPerp(ret.Start), prevOffset,
                                        projectionToPerp(currentLongSeg.Start));
                 prevOffset = t;
                 ret = null;
             }
         } else if (currentLongSeg != null) {
             ret = currentLongSeg;
             currentLongSeg = null;
         }
     }
     if (ret != null)
         SetIdealPositionForSeg(ret, projectionToPerp(ret.Start), prevOffset, projectionToPerp(path.End));
     else if (currentLongSeg != null)
         currentLongSeg.IdealPosition = projectionToPerp(currentLongSeg.Start);
 }
        private bool GetMultiStagePath(Path edgePath, MsmtRectilinearPath shortestPathRouter,
                    List<VisibilityVertex> sourceVertices, List<VisibilityVertex> targetVertices, bool lastChance) {
            var waypointVertices = PortManager.FindWaypointVertices(edgePath.EdgeGeometry.Waypoints);
            var paths = shortestPathRouter.GetPath(sourceVertices, waypointVertices, targetVertices);
            if (paths == null) {
                if (!lastChance) {
                    return false;
                }

                // Get each stage individually.  They won't necessarily be ideal but this should be very rare and
                // with at least one stage being "forced" through obstacles, the path is not good anyway.
                foreach (var stagePath in this.edgeGeomsToSplittedEdgePaths[edgePath.EdgeGeometry]) {
                    var stageGeom = stagePath.EdgeGeometry;
                    GetSingleStagePath(stagePath, shortestPathRouter, this.PortManager.FindVertices(stageGeom.SourcePort),
                            this.PortManager.FindVertices(stageGeom.TargetPort), lastChance:true);
                }
                return true;
            }
            
            // Record the path for each state.
            var pathsEnum = paths.GetEnumerator();
            foreach (var stagePath in this.edgeGeomsToSplittedEdgePaths[edgePath.EdgeGeometry]) {
                pathsEnum.MoveNext();
                stagePath.PathPoints = pathsEnum.Current;
            }
            return true;
        }
        void GoOverPathAndCreateLongSegs(Path path) {
            LongestNudgedSegment currentLongestSeg = null;

            var oppositeDir = CompassVector.OppositeDir(NudgingDirection);

            foreach (var edge in path.PathEdges) {
                var edgeDir = edge.Direction;
                if (edgeDir == NudgingDirection || edgeDir == oppositeDir) {
                    if (currentLongestSeg == null)
#if SHARPKIT //https://code.google.com/p/sharpkit/issues/detail?id=368
                    {
                        edge.LongestNudgedSegment = currentLongestSeg = new LongestNudgedSegment(LongestNudgedSegs.Count);
                        LongestNudgedSegs.Add(edge.LongestNudgedSegment);
                    }
#else
                        LongestNudgedSegs.Add(
                            edge.LongestNudgedSegment =
                            currentLongestSeg = new LongestNudgedSegment(LongestNudgedSegs.Count));
#endif
                    else
                        edge.LongestNudgedSegment = currentLongestSeg;

                    if (edge.IsFixed)
                        currentLongestSeg.IsFixed = true;
                } else {
                    //the edge is perpendicular to "direction"
                    edge.LongestNudgedSegment = null;
                    currentLongestSeg = null;
                }
            }
 internal virtual void RetryPathsWithAdditionalGroupsEnabled(MsmtRectilinearPath shortestPathRouter, Path edgePath) {
     // Insert any spatial parent groups that are not in our hierarchical parent tree and retry,
     // if we haven't already done this.
     if (!PortManager.SetAllAncestorsActive(edgePath.EdgeGeometry, ShapeToObstacleMap)
             || !GeneratePath(shortestPathRouter, edgePath)) {
         // Last chance: enable all groups (if we have any).  Only do this on a per-path basis so a single degenerate
         // path won't make the entire graph look bad.
         PortManager.SetAllGroupsActive();
         GeneratePath(shortestPathRouter, edgePath, lastChance:true);
     }
 }
 void InsertPathSegs(Path path) {
     InsertSegs((Point[])path.PathPoints);
 }
 static LinkedPoint FindLinkedPointInPath(Path path, Point point) {
     //this function is supposed to always succeed. it will throw a null reference exception otherwise
     for (var linkedPoint = (LinkedPoint) path.PathPoints;; linkedPoint = linkedPoint.Next)
         if (linkedPoint.Point == point)
             return linkedPoint;
 }
 void ReplacePiece(LinkedPoint a, LinkedPoint b, IEnumerable<Point> points, Path loopingPath){
     var prevPoint = a;
     foreach (var point in points){
         var lp = new LinkedPoint(point);
         prevPoint.Next = lp;
         prevPoint = lp;
         var pathOffset = verticesToPathOffsets[point];
         Debug.Assert(!pathOffset.ContainsKey(loopingPath));
         pathOffset[loopingPath] = prevPoint;
     }
     prevPoint.Next = b;
 }
        static IEnumerable<DebugCurve> PathDebugCurvesFromPoints(Path path, string color) {
            const double startWidth = 0.01;
            const double endWidth = 3;

            var pts = path.PathPoints.ToArray();
            double delta = (endWidth - startWidth) / (pts.Length - 1);
            for (int i = 0; i < pts.Length - 1; i++)
                yield return new DebugCurve(startWidth + delta * i, color, new LineSegment(pts[i], pts[i + 1]));
        }
        static IEnumerable<DebugCurve> GetEdgePathFromPathEdgesAsDebugCurves(double startWidth, double endWidth, string color, Path path) {
            var points = path.PathPoints.ToArray();

            int count = points.Length;

            double deltaW = count > 1 ? (endWidth - startWidth) / (count - 1) : 1; //if count ==1 the value of deltaW does not matter
            for (int i = 0; i < points.Length - 1; i++)
                yield return new DebugCurve(120, startWidth + deltaW * i, color, new LineSegment(points[i], points[i + 1]));
        }
        static LinkedPoint CreateLinkedVertexOfEdgePath(Path path) {
            var pathPoint = new LinkedPoint(path.PathPoints.First());
            var first = pathPoint;
#if SHARPKIT //https://code.google.com/p/sharpkit/issues/detail?id=368
            path.PathPoints.Skip(1).Aggregate(pathPoint, (lp, p) => { lp.Next = new LinkedPoint(p); return lp.Next; });
#else
            path.PathPoints.Skip(1).Aggregate(pathPoint, (lp, p) => lp.Next = new LinkedPoint(p));
#endif
            return first;
        }
 private void AddControlPointsAndGeneratePath(MsmtRectilinearPath shortestPathRouter, Path edgePath) {
     if (!edgePath.EdgeGeometry.HasWaypoints) {
         Point[] intersectPoints = PortManager.GetPortVisibilityIntersection(edgePath.EdgeGeometry);
         if (intersectPoints != null) {
             GeneratePathThroughVisibilityIntersection(edgePath, intersectPoints);
             return;
         }
     }
     this.SpliceVisibilityAndGeneratePath(shortestPathRouter, edgePath);
 }