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); } } } }
void ShowPointAndEdge(Point point, AxisEdge edge) { // ReSharper restore UnusedMember.Local List <ICurve> curves = GetCurves(point, edge); LayoutAlgorithmSettings.Show(curves.ToArray()); }
/// <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))); } }
void TryToAddRightNeighbor(AxisEdge leftEdge, AxisEdge rightEdge) { if (ProjectionsOfEdgesOverlap(leftEdge, rightEdge)) { leftEdge.AddRightNeighbor(rightEdge); } }
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)); }
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)); }
void EnqueueEventsForEdge(AxisEdge edge) { if (EdgeIsParallelToSweepDir(edge)) { EnqueueEvent(EdgeLowPointEvent(edge, edge.Source.Point)); EnqueueEvent(EdgeHighPointEvent(edge, edge.Target.Point)); } }
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); } }
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)) })); }
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)); }
// #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))); }
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); }
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); } } }
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); } } }
// #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); }
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); }
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)); }
bool NotRestricting(AxisEdge edge, Polyline polyline) { Polyline p; return(AxisEdgesToObstaclesTheyOriginatedFrom.TryGetValue(edge, out p) && p == polyline); }
internal List <PathEdge> PathOrderOfVisEdge(AxisEdge axisEdge) { return(axisEdgesToPathOrders[axisEdge]); }
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); }
void DebShowEdge(AxisEdge edge, Point point) { // ReSharper restore UnusedMember.Local // if (InterestingEdge(edge)) ShowEdge(edge, point); }
static Point EdgeMidPoint(AxisEdge edge) { return(0.5 * (edge.SourcePoint + edge.TargetPoint)); }
internal PathEdge(AxisEdge edgeForNudging, double width) { AxisEdge = edgeForNudging; Width = width; }
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)); } }