예제 #1
0
        List <ICurve> GetCurves(Point point, AxisEdge edge)
        {
            var ellipse = CurveFactory.CreateEllipse(3, 3, point);
            var curves  = new List <ICurve>(Obstacles.Select(o => o as ICurve))
            {
                ellipse,
                new LineSegment(edge.Source.Point, edge.Target.Point
                                )
            };

            if (edge.RightBound < double.PositiveInfinity)
            {
                double rightOffset = edge.RightBound;
                var    del         = DirectionPerp * rightOffset;
                curves.Add(new LineSegment(edge.Source.Point + del, edge.Target.Point + del));
            }
            if (edge.LeftBound > double.NegativeInfinity)
            {
                double leftOffset = edge.LeftBound;
                var    del        = DirectionPerp * leftOffset;
                curves.Add(new LineSegment(edge.Source.Point + del, edge.Target.Point + del));
            }

            curves.AddRange((from e in PathOrders.Keys
                             let a = e.SourcePoint
                                     let b = e.TargetPoint
                                             select new CubicBezierSegment(a, a * 0.8 + b * 0.2, a * 0.2 + b * 0.8, b)).Cast <ICurve>());

            return(curves);
        }
 void BoundAxisEdgeAdjacentToObstaclePort(Port port, AxisEdge axisEdge)
 {
     if (port is WaypointPort || (port.Curve == null && port.PortEntry == null))
     {
         BoundAxisByPoint(port.Location, axisEdge);
     }
     else if (port.PortEntry == null)
     {
         if (port.Curve.BoundingBox.Contains(port.Location))
         {
             BoundAxisEdgeByRect(port.Curve.BoundingBox, axisEdge);
         }
     }
     else
     {
         var portEntry = port.PortEntry as PortEntryOnCurve;
         if (portEntry != null)
         {
             Rectangle rect;
             if (FindPortEntryRectCrossingAxisEdge(portEntry, axisEdge, out rect))
             {
                 BoundAxisEdgeByRect(rect, axisEdge);
             }
         }
     }
 }
예제 #3
0
        void ShowPointAndEdge(Point point, AxisEdge edge)
        {
// ReSharper restore UnusedMember.Local
            List <ICurve> curves = GetCurves(point, edge);

            LayoutAlgorithmSettings.Show(curves.ToArray());
        }
예제 #4
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="x"></param>
 /// <param name="y"></param>
 /// <param name="axisEdge">axisEdge together with the axisEdgeIsReversed parameter define direction of the movement over the paths</param>
 /// <param name="direction"></param>
 /// <returns></returns>
 static int CompareInDirectionStartingFromAxisEdge(PathEdge x, PathEdge y, AxisEdge axisEdge, Directions direction)
 {
     while (true)
     {
         x = GetNextPathEdgeInDirection(x, axisEdge, direction);
         if (x == null)
         {
             return(0);
         }
         y = GetNextPathEdgeInDirection(y, axisEdge, direction);
         if (y == null)
         {
             return(0);
         }
         if (x.AxisEdge == y.AxisEdge)
         {
             direction = FindContinuedDirection(axisEdge, direction, x.AxisEdge);
             axisEdge  = x.AxisEdge;
             int r = GetExistingOrder(x, y);
             if (r == NotOrdered)
             {
                 continue;
             }
             return(direction == axisEdge.Direction ? r : -r);
         }
         //there is a fork
         var forkVertex = direction == axisEdge.Direction ? axisEdge.Target : axisEdge.Source;
         var xFork      = OtherVertex(x.AxisEdge, forkVertex);
         var yFork      = OtherVertex(y.AxisEdge, forkVertex);
         var projection = ProjectionForCompare(axisEdge, direction != axisEdge.Direction);
         return(projection(xFork.Point).CompareTo(projection(yFork.Point)));
     }
 }
예제 #5
0
 void TryToAddRightNeighbor(AxisEdge leftEdge, AxisEdge rightEdge)
 {
     if (ProjectionsOfEdgesOverlap(leftEdge, rightEdge))
     {
         leftEdge.AddRightNeighbor(rightEdge);
     }
 }
예제 #6
0
 static PointProjection ProjectionForCompare(AxisEdge axisEdge, bool isReversed)
 {
     if (axisEdge.Direction == Directions.North)
     {
         return(isReversed ? (p => - p.X) : (PointProjection)(p => p.X));
     }
     return(isReversed ? (p => p.Y) : (PointProjection)(p => - p.Y));
 }
예제 #7
0
 bool ProjectionsOfEdgesOverlap(AxisEdge leftEdge, AxisEdge rightEdge)
 {
     return(SweepPole == Directions.North
                ? !(leftEdge.TargetPoint.Y < rightEdge.SourcePoint.Y - ApproximateComparer.DistanceEpsilon ||
                    rightEdge.TargetPoint.Y < leftEdge.SourcePoint.Y - ApproximateComparer.DistanceEpsilon)
                : !(leftEdge.TargetPoint.X < rightEdge.SourcePoint.X - ApproximateComparer.DistanceEpsilon ||
                    rightEdge.TargetPoint.X < leftEdge.SourcePoint.X - ApproximateComparer.DistanceEpsilon));
 }
예제 #8
0
 void EnqueueEventsForEdge(AxisEdge edge)
 {
     if (EdgeIsParallelToSweepDir(edge))
     {
         EnqueueEvent(EdgeLowPointEvent(edge, edge.Source.Point));
         EnqueueEvent(EdgeHighPointEvent(edge, edge.Target.Point));
     }
 }
예제 #9
0
        void ShowPointAndEdgeWithSweepline(Point point, AxisEdge edge)
        {
// ReSharper restore UnusedMember.Local
            List <ICurve> curves = GetCurves(point, edge);

            curves.Add(new LineSegment(SweepDirection * Z + 10 * DirectionPerp, SweepDirection * Z - 10 * DirectionPerp));

            LayoutAlgorithmSettings.Show(curves.ToArray());
        }
        void RemoveEdge(AxisEdge edge)
        {
            var containerNode = GetAxisEdgesContainerNode(edge.Source.Point);

            containerNode.Item.RemoveAxis(edge);
            if (containerNode.Item.IsEmpty())
            {
                edgeContainersTree.DeleteNodeInternal(containerNode);
            }
        }
예제 #11
0
        void ShowEdge(AxisEdge edge, Point point)
        {
// ReSharper restore SuggestBaseTypeForParameter

            var dd  = GetObstacleBoundaries("black");
            var seg = new DebugCurve(1, "red", new LineSegment(edge.Source.Point, edge.Target.Point));

            LayoutAlgorithmSettings.ShowDebugCurvesEnumeration(dd.Concat(
                                                                   new[] { seg, new DebugCurve("blue", CurveFactory.CreateEllipse(3, 3, point)) }));
        }
예제 #12
0
        static Directions FindContinuedDirection(AxisEdge edge, Directions direction, AxisEdge nextAxisEdge)
        {
            if (edge.Direction == direction)
            {
                return(nextAxisEdge.Source == edge.Target
                         ? nextAxisEdge.Direction
                         : CompassVector.OppositeDir(nextAxisEdge.Direction));
            }

            return(nextAxisEdge.Source == edge.Source
                       ? nextAxisEdge.Direction
                       : CompassVector.OppositeDir(nextAxisEdge.Direction));
        }
예제 #13
0
// #if TEST_MSAGL
//         // ReSharper disable UnusedMember.Local
//         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
//         void ShowPointAndEdge(Point point, AxisEdge edge) {
// // ReSharper restore UnusedMember.Local
//             List<ICurve> curves = GetCurves(point, edge);
//
//             LayoutAlgorithmSettings.Show(curves.ToArray());
//         }
//
// // ReSharper disable UnusedMember.Local
//         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
//         void ShowPointAndEdgeWithSweepline(Point point, AxisEdge edge) {
// // ReSharper restore UnusedMember.Local
//             List<ICurve> curves = GetCurves(point, edge);
//
//             curves.Add(new LineSegment(SweepDirection * Z + 10 * DirectionPerp, SweepDirection * Z - 10 * DirectionPerp));
//
//             LayoutAlgorithmSettings.Show(curves.ToArray());
//         }
//
//         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
//         List<ICurve> GetCurves(Point point, AxisEdge edge) {
//             var ellipse = CurveFactory.CreateEllipse(3, 3, point);
//             var curves = new List<ICurve>(Obstacles.Select(o => o as ICurve)){ellipse,
//                                                                             new LineSegment(edge.Source.Point, edge.Target.Point
//                                                                                 )};
//
//             if (edge.RightBound < double.PositiveInfinity) {
//                 double rightOffset = edge.RightBound;
//                 var del = DirectionPerp * rightOffset;
//                 curves.Add(new LineSegment(edge.Source.Point + del, edge.Target.Point + del));
//             }
//             if (edge.LeftBound > double.NegativeInfinity) {
//                 double leftOffset = edge.LeftBound;
//                 var del = DirectionPerp * leftOffset;
//                 curves.Add(new LineSegment(edge.Source.Point + del, edge.Target.Point  + del));
//             }
//
//             curves.AddRange((from e in PathOrders.Keys
//                              let a = e.SourcePoint
//                              let b = e.TargetPoint
//                              select new CubicBezierSegment(a, a*0.8 + b*0.2, a*0.2 + b*0.8, b)).Cast<ICurve>());
//
//             return curves;
//         }
//
//         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
//         List<DebugCurve> GetCurvesTest(Point point){
//             var ellipse = CurveFactory.CreateEllipse(3, 3, point);
//             var curves = new List<DebugCurve>(Obstacles.Select(o => new DebugCurve(100, 1, "black", o)))
//                          {new DebugCurve(100, 1, "red", ellipse)};
//             curves.AddRange(from e in edgeContainersTree
//                              from axisEdge in e
//                              let a = axisEdge.Source.Point
//                              let b = axisEdge.Target.Point
//                              select new DebugCurve(100, 1, "green", new LineSegment(a, b)));
//
//
//             curves.AddRange(RightNeighborsCurvesTest(edgeContainersTree));
//
//             return curves;
//         }
//
//         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
//         static IEnumerable<DebugCurve> RightNeighborsCurvesTest(IEnumerable<AxisEdgesContainer> rbTree) {
//             foreach (var container in rbTree) {
//                 foreach (var edge  in container) {
//                     foreach (var rn in edge.RightNeighbors) {
//                         yield return new DebugCurve(100,1,"brown",new LineSegment(EdgeMidPoint(edge), EdgeMidPoint(rn)));
//                     }
//                 }
//             }
//         }
//
//         static Point EdgeMidPoint(AxisEdge edge) {
//             return 0.5*(edge.SourcePoint + edge.TargetPoint);
//         }
//
//         // ReSharper disable UnusedMember.Local
//         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
//         void ShowAxisEdges() {
//             // ReSharper restore UnusedMember.Local
//             var dd = new List<DebugCurve>(GetObstacleBoundaries("black"));
//             int i = 0;
//             foreach (var axisEdge in AxisEdges) {
//                 var color = DebugCurve.Colors[i];
//                 dd.Add(new DebugCurve(200, 1, color,
//                                        new LineSegment(axisEdge.Source.Point, axisEdge.Target.Point)));
//                 Point perp = axisEdge.Direction == Directions.East ? new Point(0, 1) : new Point(-1, 0);
//                 if (axisEdge.LeftBound != double.NegativeInfinity) {
//                     dd.Add(new DebugCurve(200, 0.5, color,
//                         new LineSegment(axisEdge.Source.Point + axisEdge.LeftBound * perp, axisEdge.Target.Point + axisEdge.LeftBound * perp)));
//                 }
//                 if (axisEdge.RightBound != double.PositiveInfinity) {
//                     dd.Add(new DebugCurve(200, 0.5, color,
//                         new LineSegment(axisEdge.Source.Point - axisEdge.RightBound * perp, axisEdge.Target.Point - axisEdge.RightBound * perp)));
//                 }
//                 i = (i + 1) % DebugCurve.Colors.Length;
//             }
//             DebugCurveCollection.WriteToFile(dd, "c:/tmp/ae");
//             LayoutAlgorithmSettings.ShowDebugCurvesEnumeration(dd);
//         }
//
// // ReSharper disable UnusedMember.Local
//         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
//         void ShowAtPoint(Point point) {
// // ReSharper restore UnusedMember.Local
//             var curves = GetCurvesTest(point);
//             LayoutAlgorithmSettings.ShowDebugCurves(curves.ToArray());
//         }
// #endif
        #endregion
        RBNode <AxisEdgesContainer> GetOrCreateAxisEdgesContainer(AxisEdge edge)
        {
            var source = edge.Source.Point;

            var ret = GetAxisEdgesContainerNode(source);

            if (ret != null)
            {
                return(ret);
            }

            return(edgeContainersTree.Insert(new AxisEdgesContainer(source)));
        }
예제 #14
0
        void OrderPathEdgesSharingEdge(AxisEdge edge)
        {
            var pathOrder = PathOrderOfVisEdge(edge);

            pathOrder.Sort(new Comparison <PathEdge>(CompareTwoPathEdges));
            var i = 0; //fill the index

            foreach (var pathEdge in pathOrder)
            {
                pathEdge.Index = i++;
            }
//            if (pathOrder.PathEdges.Count > 1)
//                Nudger.ShowOrderedPaths(null,pathOrder.PathEdges.Select(e => e.Path), edge.SourcePoint, edge.TargetPoint);
        }
예제 #15
0
 void BoundAxisEdgeAdjacentToObstaclePort(Port port, AxisEdge axisEdge)
 {
     if (port is WaypointPort || (port.Curve == null))
     {
         BoundAxisByPoint(port.Location, axisEdge);
     }
     else
     {
         if (port.Curve.BoundingBox.Contains(port.Location))
         {
             BoundAxisEdgeByRect(port.Curve.BoundingBox, axisEdge);
         }
     }
 }
        static bool FindPortEntryRectCrossingAxisEdge(PortEntryOnCurve portEntry, AxisEdge axisEdge, out Rectangle rect)
        {
            var ar = new Rectangle(axisEdge.SourcePoint, axisEdge.TargetPoint);

            foreach (Rectangle r in portEntry.AllowedRectangles)
            {
                if (r.Intersects(ar))
                {
                    rect = r;
                    return(true);
                }
            }
            rect = Rectangle.CreateAnEmptyBox();
            return(false);
        }
 void BoundAxisEdgeByRect(Rectangle rectangle, AxisEdge axisEdge)
 {
     if (axisEdge != null && axisEdge.Direction == NudgingDirection)
     {
         if (NudgingDirection == Directions.North)
         {
             axisEdge.BoundFromLeft(rectangle.Left);
             axisEdge.BoundFromRight(rectangle.Right);
         }
         else
         {
             axisEdge.BoundFromLeft(-rectangle.Top);
             axisEdge.BoundFromRight(-rectangle.Bottom);
         }
     }
 }
예제 #18
0
        void ConstraintEdgeWithObstaclesAtZFromRight(AxisEdge edge, Point point)
        {
            var node = GetActiveSideFromRight(point);

            if (node == null)
            {
                return;
            }
            if (NotRestricting(edge, ((LeftObstacleSide)node.Item).Polyline))
            {
                return;
            }
            var x = ObstacleSideComparer.IntersectionOfSideAndSweepLine(node.Item);

            edge.BoundFromRight(x * DirectionPerp);
        }
 void BoundAxisByPoint(Point point, AxisEdge axisEdge)
 {
     if (axisEdge != null && axisEdge.Direction == NudgingDirection)
     {
         if (NudgingDirection == Directions.North)
         {
             axisEdge.BoundFromLeft(point.X);
             axisEdge.BoundFromRight(point.X);
         }
         else
         {
             axisEdge.BoundFromLeft(-point.Y);
             axisEdge.BoundFromRight(-point.Y);
         }
     }
 }
예제 #20
0
// #if TEST_MSAGL
// // ReSharper disable UnusedMember.Local
//         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
//         void DebShowEdge(AxisEdge edge, Point point){
// // ReSharper restore UnusedMember.Local
//            // if (InterestingEdge(edge))
//                 ShowEdge(edge,point);
//         }
//
//
// // ReSharper disable SuggestBaseTypeForParameter
//         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
//         void ShowEdge(AxisEdge edge, Point point){
// // ReSharper restore SuggestBaseTypeForParameter
//
//             var dd = GetObstacleBoundaries("black");
//             var seg = new DebugCurve( 1, "red", new LineSegment(edge.Source.Point, edge.Target.Point));
//             LayoutAlgorithmSettings.ShowDebugCurvesEnumeration(dd.Concat(
//                 new[]{seg ,new DebugCurve("blue",CurveFactory.CreateEllipse(3, 3, point))}));
//
//
//         }
//
//         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
//         IEnumerable<DebugCurve> GetObstacleBoundaries(string color){
//             return Obstacles.Select(p => new DebugCurve(1, color, p));
//         }
// #endif


        /// <summary>
        ///
        /// </summary>
        /// <param name="edge"></param>
        /// <param name="point">a point on the edge on Z level</param>
        void ConstraintEdgeWithObstaclesAtZ(AxisEdge edge, Point point)
        {
            Debug.Assert(point == edge.Source.Point || point == edge.Target.Point);
            ConstraintEdgeWithObstaclesAtZFromLeft(edge, point);
            ConstraintEdgeWithObstaclesAtZFromRight(edge, point);
        }
 internal void AddRightNeighbor(AxisEdge edge) {
     RightNeighbors.Insert(edge);
 }
 void BoundAxisEdgeAdjacentToObstaclePort(Port port, AxisEdge axisEdge) {
     if (port is WaypointPort || (port.Curve == null && port.PortEntry == null))
         BoundAxisByPoint(port.Location, axisEdge);
     else if (port.PortEntry == null) {
         if (port.Curve.BoundingBox.Contains(port.Location))
             BoundAxisEdgeByRect(port.Curve.BoundingBox, axisEdge);
     } else {
         var portEntry = port.PortEntry as PortEntryOnCurve;
         if (portEntry != null) {
             Rectangle rect;
             if (FindPortEntryRectCrossingAxisEdge(portEntry, axisEdge, out rect))
                 BoundAxisEdgeByRect(rect, axisEdge);
         }
     }
 }
 internal void RemoveAxis(AxisEdge edge)
 {
     Debug.Assert(edges.Contains(edge));
     edges.Remove(edge);
 }
예제 #24
0
 static SweepEvent EdgeLowPointEvent(AxisEdge edge, Point point)
 {
     return(new AxisEdgeLowPointEvent(edge, point));
 }
 internal List<PathEdge> PathOrderOfVisEdge(AxisEdge axisEdge) {
     return axisEdgesToPathOrders[axisEdge];
 }
 static bool FindPortEntryRectCrossingAxisEdge(PortEntryOnCurve portEntry, AxisEdge axisEdge, out Rectangle rect) {
     var ar = new Rectangle(axisEdge.SourcePoint, axisEdge.TargetPoint);           
     foreach (Rectangle r in portEntry.AllowedRectangles) {
         if(r.Intersects(ar)) {
             rect = r;
             return true;
         }                    
     }
     rect = Rectangle.CreateAnEmptyBox();
     return false;
 }
 void BoundAxisEdgeByRect(Rectangle rectangle, AxisEdge axisEdge) {
     if (axisEdge != null && axisEdge.Direction == NudgingDirection)
         if (NudgingDirection == Directions.North) {
             axisEdge.BoundFromLeft(rectangle.Left);
             axisEdge.BoundFromRight(rectangle.Right);
         } else {
             axisEdge.BoundFromLeft(-rectangle.Top);
             axisEdge.BoundFromRight(-rectangle.Bottom);
         }
 }
 internal PathEdge(AxisEdge edgeForNudging, double width) {
     AxisEdge = edgeForNudging;
     Width = width;
 }
 public AxisEdgeLowPointEvent(AxisEdge  edge, Point point) {
     site = point;
     AxisEdge = edge;
 }
        static Directions FindContinuedDirection(AxisEdge edge, Directions direction, AxisEdge nextAxisEdge) {
            if (edge.Direction == direction)
                return nextAxisEdge.Source == edge.Target
                           ? nextAxisEdge.Direction
                           : CompassVector.OppositeDir(nextAxisEdge.Direction);

            return nextAxisEdge.Source == edge.Source
                       ? nextAxisEdge.Direction
                       : CompassVector.OppositeDir(nextAxisEdge.Direction);
        }
 static PathEdge GetNextPathEdgeInDirection(PathEdge e, AxisEdge axisEdge, Directions direction) {
     Debug.Assert(e.AxisEdge==axisEdge);
     return axisEdge.Direction == direction ? (e.Reversed ? e.Prev : e.Next) : (e.Reversed ? e.Next : e.Prev);
 }
        void OrderPathEdgesSharingEdge(AxisEdge edge) {
            var pathOrder = PathOrderOfVisEdge(edge);
            pathOrder.Sort(new Comparison<PathEdge>(CompareTwoPathEdges));
            var i = 0; //fill the index
            foreach (var pathEdge in pathOrder)
                pathEdge.Index = i++;
//            if (pathOrder.PathEdges.Count > 1)
//                Nudger.ShowOrderedPaths(null,pathOrder.PathEdges.Select(e => e.Path), edge.SourcePoint, edge.TargetPoint);
        }
예제 #33
0
 static PathEdge GetNextPathEdgeInDirection(PathEdge e, AxisEdge axisEdge, Directions direction)
 {
     Debug.Assert(e.AxisEdge == axisEdge);
     return(axisEdge.Direction == direction ? (e.Reversed ? e.Prev : e.Next) : (e.Reversed ? e.Next : e.Prev));
 }
예제 #34
0
        bool NotRestricting(AxisEdge edge, Polyline polyline)
        {
            Polyline p;

            return(AxisEdgesToObstaclesTheyOriginatedFrom.TryGetValue(edge, out p) && p == polyline);
        }
예제 #35
0
 internal List <PathEdge> PathOrderOfVisEdge(AxisEdge axisEdge)
 {
     return(axisEdgesToPathOrders[axisEdge]);
 }
예제 #36
0
 bool EdgeIsParallelToSweepDir(AxisEdge edge)
 {
     return(edge.Direction == SweepPole || edge.Direction == CompassVector.OppositeDir(SweepPole));
 }
 void BoundAxisByPoint(Point point, AxisEdge axisEdge) {
     if (axisEdge != null && axisEdge.Direction == NudgingDirection)
         if (NudgingDirection == Directions.North) {
             axisEdge.BoundFromLeft(point.X);
             axisEdge.BoundFromRight(point.X);
         } else {
             axisEdge.BoundFromLeft(-point.Y);
             axisEdge.BoundFromRight(-point.Y);
         }
 }
 static PointProjection ProjectionForCompare(AxisEdge axisEdge, bool isReversed) {
     if (axisEdge.Direction == Directions.North)
         return isReversed ? (p => -p.X) : (PointProjection)(p => p.X);
     return isReversed ? (p => p.Y) : (PointProjection)(p => -p.Y);
 }
예제 #39
0
        void DebShowEdge(AxisEdge edge, Point point)
        {
// ReSharper restore UnusedMember.Local
            // if (InterestingEdge(edge))
            ShowEdge(edge, point);
        }
예제 #40
0
 static Point EdgeMidPoint(AxisEdge edge)
 {
     return(0.5 * (edge.SourcePoint + edge.TargetPoint));
 }
 internal PathEdge(AxisEdge edgeForNudging, double width)
 {
     AxisEdge = edgeForNudging;
     Width    = width;
 }
예제 #42
0
 internal void AddRightNeighbor(AxisEdge edge)
 {
     RightNeighbors.Insert(edge);
 }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="x"></param>
 /// <param name="y"></param>
 /// <param name="axisEdge">axisEdge together with the axisEdgeIsReversed parameter define direction of the movement over the paths</param>
 /// <param name="direction"></param>
 /// <returns></returns>
 static int CompareInDirectionStartingFromAxisEdge(PathEdge x, PathEdge y, AxisEdge axisEdge, Directions direction){
     while (true) {
         x = GetNextPathEdgeInDirection(x, axisEdge, direction);
         if (x == null)
             return 0;
         y = GetNextPathEdgeInDirection(y, axisEdge, direction);
         if (y == null)
             return 0;
         if (x.AxisEdge == y.AxisEdge) {
             direction = FindContinuedDirection(axisEdge, direction, x.AxisEdge);
             axisEdge = x.AxisEdge;
             int r = GetExistingOrder(x, y);
             if (r == NotOrdered) continue;
             return direction == axisEdge.Direction ? r : -r;
         }
         //there is a fork
         var forkVertex = direction == axisEdge.Direction ? axisEdge.Target : axisEdge.Source;
         var xFork = OtherVertex(x.AxisEdge, forkVertex);
         var yFork = OtherVertex(y.AxisEdge, forkVertex);
         var projection = ProjectionForCompare(axisEdge, direction != axisEdge.Direction);
         return projection(xFork.Point).CompareTo(projection(yFork.Point));
     }
 }