/// <summary>
        /// we need to pass arrowhead length here since the original length mibh
        /// </summary>
        /// <param name="edgeGeometry"></param>
        /// <param name="p"></param>
        /// <returns></returns>
        static bool FindTrimEndForArrowheadAtTarget(EdgeGeometry edgeGeometry, out double p)
        {
            var eps = ApproximateComparer.DistanceEpsilon * ApproximateComparer.DistanceEpsilon;

            //Debug.Assert((edgeGeometry.Curve.End - edgeGeometry.Curve.Start).LengthSquared > eps);
            p = edgeGeometry.Curve.ParEnd;
            if (edgeGeometry.TargetArrowhead == null ||
                edgeGeometry.TargetArrowhead.Length <= ApproximateComparer.DistanceEpsilon)
            {
                return(true);
            }
            var   curve           = edgeGeometry.Curve;
            var   arrowheadLength = edgeGeometry.TargetArrowhead.Length;
            Point newCurveEnd;
            IList <IntersectionInfo> intersections;
            int reps = 10;

            do
            {
                reps--;
                if (reps == 0)
                {
                    return(false);
                }
                intersections    = GetIntersectionsWithArrowheadCircle(curve, arrowheadLength, curve.End);
                p                = intersections.Count != 0 ? intersections.Max(x => x.Par1) : curve.ParEnd;
                newCurveEnd      = edgeGeometry.Curve[p];
                arrowheadLength /= 2;
            } while (((newCurveEnd - curve.Start).LengthSquared < eps || intersections.Count == 0));
            //we would like to have at least something left from the curve
            return(true);
        }
        static bool FindTrimStartForArrowheadAtSource(EdgeGeometry edgeGeometry, out double p)
        {
            p = 0; //does not matter
            if (edgeGeometry.SourceArrowhead == null || edgeGeometry.SourceArrowhead.Length <= ApproximateComparer.DistanceEpsilon)
            {
                return(true);
            }
            var eps = ApproximateComparer.DistanceEpsilon * ApproximateComparer.DistanceEpsilon;

            Debug.Assert((edgeGeometry.Curve.End - edgeGeometry.Curve.Start).LengthSquared > eps);
            var   arrowheadLength = edgeGeometry.SourceArrowhead.Length;
            Point newStart;
            var   curve = edgeGeometry.Curve;
            IList <IntersectionInfo> intersections;
            int reps = 10;

            do
            {
                reps--;
                if (reps == 0)
                {
                    return(false);
                }
                intersections    = GetIntersectionsWithArrowheadCircle(curve, arrowheadLength, curve.Start);
                p                = intersections.Count != 0 ? intersections.Min(x => x.Par1) : curve.ParStart;
                newStart         = curve[p];
                arrowheadLength /= 2;
            } while ((newStart - curve.End).LengthSquared < eps || intersections.Count == 0);
            //we are checkng that something will be left from the curve
            return(true);
        }
 internal PreGraph(EdgeGeometry[] egs, Set<ICurve> nodeBoundaries) {
     edgeGeometries = new List<EdgeGeometry>(egs);
     this.nodeBoundaries = new Set<ICurve>(nodeBoundaries);
     boundingBox = Rectangle.CreateAnEmptyBox();
     foreach (var curve in nodeBoundaries)
         boundingBox.Add(curve.BoundingBox);
 }
Пример #4
0
 private static IEnumerable<ICurve> ArrowHeadCurves(EdgeGeometry edgeGeom)
 {
     var start = edgeGeom.Curve.End;
     var end = edgeGeom.TargetArrowhead.TipPosition;
     var ang = Math.PI / 12;
     var leftTip = end + (start - end).Rotate(ang);
     var rightTip = end + (start - end).Rotate(-ang);
     return new List<ICurve> { new LineSegment(leftTip, end), new LineSegment(rightTip, end) };
 }
 internal static Geometry DefiningTargetArrowHead(EdgeGeometry edgeGeometry, double thickness) {
     if (edgeGeometry.TargetArrowhead == null || edgeGeometry.Curve==null)
         return null;
     var streamGeometry = new StreamGeometry();
     using (StreamGeometryContext context = streamGeometry.Open()) {
         AddArrow(context, edgeGeometry.Curve.End,
                  edgeGeometry.TargetArrowhead.TipPosition, thickness);
         return streamGeometry;
     }
 }
 /// <summary>
 /// Add an EdgeGeometry to route
 /// </summary>
 /// <param name="edgeGeometry"></param>
 public void AddEdgeGeometryToRoute(EdgeGeometry edgeGeometry) {
     ValidateArg.IsNotNull(edgeGeometry, "edgeGeometry");
     // The Port.Location values are not necessarily rounded by the caller.  The values
     // will be rounded upon acquisition in PortManager.cs.  PointComparer.Equal expects
     // all values to be rounded.
     if (!PointComparer.Equal(ApproximateComparer.Round(edgeGeometry.SourcePort.Location)
             , ApproximateComparer.Round(edgeGeometry.TargetPort.Location))) {
         EdgeGeometries.Add(edgeGeometry);
     } else {
         selfEdges.Add(edgeGeometry);
     }
 }
 void CreateCurveLine(Metroline line, EdgeGeometry edge) {
     var c = new Curve();
     Point start = FindCurveStart(metroGraphData, metroOrdering, line);
     Point currentEnd = start;
     var hubSegsOfLine = HubSegsOfLine(metroGraphData, metroOrdering, line);
     foreach (var seg in hubSegsOfLine) {
         if (seg == null) continue;
         c.AddSegment(new LineSegment(currentEnd, seg.Start));
         c.AddSegment(seg);
         currentEnd = seg.End;
     }
     c.AddSegment(new LineSegment(currentEnd, FindCurveEnd(metroGraphData, metroOrdering, line)));
     edge.Curve = c;
     if (CreateUnderlyingPolylines)
         edge.SmoothedPolyline = BuildUnderlyingPolyline(start, currentEnd, hubSegsOfLine);
 }
Пример #8
0
        /// <summary>
        /// calculates new curve ends that are the arrowhead starts
        /// </summary>
        /// <param name="edgeGeometry">The edgeGeometry.Curve is trimmed already by the node boundaries</param>
        /// <returns></returns>
        internal static bool CalculateArrowheads(EdgeGeometry edgeGeometry)
        {
            ValidateArg.IsNotNull(edgeGeometry, "edgeGeometry");

            if (edgeGeometry.SourceArrowhead == null && edgeGeometry.TargetArrowhead == null)
            {
                return(true);
            }

            double parStart, parEnd;

            if (!FindTrimStartForArrowheadAtSource(edgeGeometry, out parStart))
            {
                return(false);
            }

            if (!FindTrimEndForArrowheadAtTarget(edgeGeometry, out parEnd))
            {
                return(false);
            }

            if (parStart > parEnd - ApproximateComparer.IntersectionEpsilon || ApproximateComparer.CloseIntersections(edgeGeometry.Curve[parStart], edgeGeometry.Curve[parEnd]))
            {
                return(false); //after the trim nothing would be left of the curve
            }
            var c = edgeGeometry.Curve.Trim(parStart, parEnd);

            if (c == null)
            {
                return(false);
            }

            if (edgeGeometry.SourceArrowhead != null)
            {
                edgeGeometry.SourceArrowhead.TipPosition = PlaceTip(c.Start, edgeGeometry.Curve.Start, edgeGeometry.SourceArrowhead.Offset);
            }

            if (edgeGeometry.TargetArrowhead != null)
            {
                edgeGeometry.TargetArrowhead.TipPosition = PlaceTip(c.End, edgeGeometry.Curve.End, edgeGeometry.TargetArrowhead.Offset);
            }

            edgeGeometry.Curve = c;

            return(true);
        }
        internal MetroGraphData(EdgeGeometry[] regularEdges,
            RectangleNode<Polyline> looseTree, RectangleNode<Polyline> tightTree,
            BundlingSettings bundlingSettings, Cdt cdt,
            Dictionary<EdgeGeometry, Set<Polyline>> edgeLooseEnterable, Dictionary<EdgeGeometry, Set<Polyline>> edgeTightEnterable, Func<Port, Polyline> loosePolylineOfPort) {
            //Debug.Assert(cdt != null);
            this.regularEdges = regularEdges;
            if (cdt != null)
                Cdt = cdt;
            else
                Cdt = BundleRouter.CreateConstrainedDelaunayTriangulation(looseTree);

            EdgeLooseEnterable = edgeLooseEnterable;
            EdgeTightEnterable = edgeTightEnterable;
            LoosePolylineOfPort = loosePolylineOfPort;

            looseIntersections = new Intersections(this, bundlingSettings, looseTree, station => station.EnterableLoosePolylines);
            tightIntersections = new Intersections(this, bundlingSettings, tightTree, station => station.EnterableTightPolylines);
            cdtIntersections = new CdtIntersections(this, bundlingSettings);

            Initialize(false);
        }
 /// <summary>
 /// calculates new curve ends that are the arrowhead starts
 /// </summary>
 /// <param name="edgeGeometry">The edgeGeometry.Curve is trimmed already by the node boundaries</param>
 /// <returns></returns>
 internal static bool CalculateArrowheads(EdgeGeometry edgeGeometry) {
     ValidateArg.IsNotNull(edgeGeometry, "edgeGeometry");
     if (edgeGeometry.SourceArrowhead == null && edgeGeometry.TargetArrowhead == null)
         return true;
     double parStart, parEnd;
     if (!FindTrimStartForArrowheadAtSource(edgeGeometry, out parStart))
         return false;
     if (!FindTrimEndForArrowheadAtTarget(edgeGeometry, out parEnd))
         return false;
     if (parStart > parEnd - ApproximateComparer.IntersectionEpsilon || ApproximateComparer.CloseIntersections(edgeGeometry.Curve[parStart], edgeGeometry.Curve[parEnd]))
         return false; //after the trim nothing would be left of the curve
     var c = edgeGeometry.Curve.Trim(parStart, parEnd);
     if (c == null)
         return false;
     if (edgeGeometry.SourceArrowhead != null)
         edgeGeometry.SourceArrowhead.TipPosition = PlaceTip(c.Start, edgeGeometry.Curve.Start, edgeGeometry.SourceArrowhead.Offset);
     if (edgeGeometry.TargetArrowhead != null)
         edgeGeometry.TargetArrowhead.TipPosition = PlaceTip(c.End, edgeGeometry.Curve.End, edgeGeometry.TargetArrowhead.Offset);
     edgeGeometry.Curve = c;
     return true;
 }
        void SetEdgeGeometryCurve(EdgeGeometry edgeGeometry) {
            Polyline poly = new Polyline();
            SdVertex curV = EdgesToRouteSources[edgeGeometry];
            poly.AddPoint(curV.Point);
            foreach (var edge in EdgesToRoutes[edgeGeometry]) {
                if (edge.SourcePoint == curV.Point) {
                    poly.AddPoint(edge.TargetPoint);
                    curV = edge.Target;
                }
                else {
                    poly.AddPoint(edge.SourcePoint);
                    curV = edge.Source;
                }
            }

            edgeGeometry.Curve = poly;
            var clusterSourcePort = edgeGeometry.SourcePort as ClusterBoundaryPort;
            if (clusterSourcePort != null)
                ExtendPolylineStartToClusterBoundary(poly, clusterSourcePort.Curve);

            var clusterTargetPort = edgeGeometry.TargetPort as ClusterBoundaryPort;
            if (clusterTargetPort != null)
                ExtendPolylineEndToClusterBoundary(poly, clusterTargetPort.Curve);
        }
 static bool FindTrimStartForArrowheadAtSource(EdgeGeometry edgeGeometry, out double p) {
     p = 0; //does not matter
     if (edgeGeometry.SourceArrowhead == null || edgeGeometry.SourceArrowhead.Length <= ApproximateComparer.DistanceEpsilon)
         return true;
     var eps = ApproximateComparer.DistanceEpsilon * ApproximateComparer.DistanceEpsilon;
     Debug.Assert((edgeGeometry.Curve.End - edgeGeometry.Curve.Start).LengthSquared > eps);
     var arrowheadLength = edgeGeometry.SourceArrowhead.Length;
     Point newStart;
     var curve = edgeGeometry.Curve;
     IList<IntersectionInfo> intersections;
     int reps = 10;
     do
     {
         reps--;
         if (reps == 0)
             return false; 
         intersections = GetIntersectionsWithArrowheadCircle(curve, arrowheadLength, curve.Start);
         p = intersections.Count != 0 ? intersections.Min(x => x.Par1) : curve.ParStart;
         newStart = curve[p];
         arrowheadLength /= 2;
     } while ((newStart - curve.End).LengthSquared < eps || intersections.Count==0);
     //we are checkng that something will be left from the curve
     return true;
 }
 /// <summary>
 /// we need to pass arrowhead length here since the original length mibh
 /// </summary>
 /// <param name="edgeGeometry"></param>
 /// <param name="p"></param>
 /// <returns></returns>
 static bool FindTrimEndForArrowheadAtTarget(EdgeGeometry edgeGeometry, out double p) {
     var eps = ApproximateComparer.DistanceEpsilon*ApproximateComparer.DistanceEpsilon;
     //Debug.Assert((edgeGeometry.Curve.End - edgeGeometry.Curve.Start).LengthSquared > eps);
     p = edgeGeometry.Curve.ParEnd;
     if (edgeGeometry.TargetArrowhead == null ||
         edgeGeometry.TargetArrowhead.Length <= ApproximateComparer.DistanceEpsilon)
         return true;
     var curve = edgeGeometry.Curve;
     var arrowheadLength = edgeGeometry.TargetArrowhead.Length;
     Point newCurveEnd;
     IList<IntersectionInfo> intersections;
     int reps = 10;
     do {
         reps--;
         if (reps == 0)
             return false;
         intersections = GetIntersectionsWithArrowheadCircle(curve, arrowheadLength, curve.End);
         p = intersections.Count != 0 ? intersections.Max(x => x.Par1) : curve.ParEnd;
         newCurveEnd = edgeGeometry.Curve[p];
         arrowheadLength /= 2;
     } while (((newCurveEnd - curve.Start).LengthSquared < eps || intersections.Count == 0));
     //we would like to have at least something left from the curve
     return true;
 }
        // Add path control points - source, target, and any waypoints.
        internal void AddControlPointsToGraph(EdgeGeometry edgeGeom, Dictionary<Shape, Obstacle> shapeToObstacleMap) {
            this.GetPortSpliceLimitRectangle(edgeGeom);
            activeAncestors.Clear();

            ObstaclePort sourceOport, targetOport;
            var ssAncs = FindAncestorsAndObstaclePort(edgeGeom.SourcePort, out sourceOport);
            var ttAncs = FindAncestorsAndObstaclePort(edgeGeom.TargetPort, out targetOport);

            if ((AncestorSets.Count > 0) && (null != sourceOport) && (null != targetOport)) {
                // Make non-common ancestors' boundaries transparent (we don't want to route outside common ancestors).
                var ttAncsOnly = ttAncs - ssAncs;
                var ssAncsOnly = ssAncs - ttAncs;
                ActivateAncestors(ssAncsOnly, ttAncsOnly, shapeToObstacleMap);
            }

            // Now that we've set any active ancestors, splice in the port visibility.
            AddPortToGraph(edgeGeom.SourcePort, sourceOport);
            AddPortToGraph(edgeGeom.TargetPort, targetOport);

            AddWaypointsToGraph(edgeGeom);
        }
 /// <summary>
 /// Remove a routing specification for an EdgeGeometry.
 /// </summary>
 /// <param name="edgeGeometry"></param>
 public void RemoveEdgeGeometryToRoute(EdgeGeometry edgeGeometry) {
     EdgeGeometries.Remove(edgeGeometry);
 }
 private static ICurve GetTargetBoundary(EdgeGeometry edgeGeom) {
     return edgeGeom.TargetPort.Curve;
 }
        void InitNodeEnterableTightPolylines(Metroline metroline, EdgeGeometry regularEdge) {
            //If we have groups, EdgeTightEnterable are precomputed.
            var metrolineEnterable = EdgeTightEnterable != null ? EdgeTightEnterable[regularEdge] : new Set<Polyline>();

            for (var p = metroline.Polyline.StartPoint.Next; p!=null && p.Next != null; p = p.Next) {
                var v = PointToStations[p.Point];
                Set<Polyline> nodeEnterable = v.EnterableTightPolylines;
                if (nodeEnterable != null)
                    v.EnterableTightPolylines = nodeEnterable * metrolineEnterable;
                else
                    v.EnterableTightPolylines = new Set<Polyline>(metrolineEnterable);
            }

            AddTightEnterableForMetrolineStartEndPoints(metroline);
        }
 void AddEdgeGeometryToGraph(EdgeGeometry eg, GeometryGraph graph, Dictionary<ICurve, Node> nodeDictionary) {
     var sourceNode = GetOrCreateNode(eg.SourcePort, nodeDictionary);
     var targetNode = GetOrCreateNode(eg.TargetPort, nodeDictionary);
     var edge = new Edge(sourceNode, targetNode) { EdgeGeometry = eg };
     graph.Edges.Add(edge);
 }
 public Point[] GetPortVisibilityIntersection(EdgeGeometry edgeGeometry) {
     var sourceOport = this.FindObstaclePort(edgeGeometry.SourcePort);
     var targetOport = this.FindObstaclePort(edgeGeometry.TargetPort);
     if ((sourceOport == null) || (targetOport == null)) {
         return null;
     }
     if (sourceOport.Obstacle.IsInConvexHull || targetOport.Obstacle.IsInConvexHull) {
         return null;
     }
     this.CreateObstaclePortEntrancesIfNeeded(sourceOport);
     this.CreateObstaclePortEntrancesIfNeeded(targetOport);
     if (!sourceOport.VisibilityRectangle.Intersects(targetOport.VisibilityRectangle)) {
         return null;
     }
     foreach (var sourceEntrance in sourceOport.PortEntrances) {
         if (!sourceEntrance.WantVisibilityIntersection) {
             continue;
         }
         foreach (var targetEntrance in targetOport.PortEntrances) {
             if (!targetEntrance.WantVisibilityIntersection) {
                 continue;
             }
             var points = (sourceEntrance.IsVertical == targetEntrance.IsVertical)
                         ? GetPathPointsFromOverlappingCollinearVisibility(sourceEntrance, targetEntrance)
                         : GetPathPointsFromIntersectingVisibility(sourceEntrance, targetEntrance);
             if (points != null) {
                 return points;
             }
         }
     }
     return null;
 }
        private static IEnumerable<Path> SplitEdgeGeomWithWaypoints(EdgeGeometry edgeGeom, IEnumerable<Point> waypoints) {
            var ret = new List<Path>();
            IEnumerator<Point> wp0 = waypoints.GetEnumerator();
            wp0.MoveNext();
            ret.Add(new Path(new EdgeGeometry(edgeGeom.SourcePort, new WaypointPort(wp0.Current))));

            IEnumerator<Point> wp1 = waypoints.GetEnumerator();
            wp1.MoveNext();
            while (wp1.MoveNext())
            {
                ret.Add(new Path(new EdgeGeometry(new WaypointPort(wp0.Current), new WaypointPort(wp1.Current))));
                wp0.MoveNext();
            }
            ret.Add(new Path(new EdgeGeometry(new WaypointPort(wp0.Current), edgeGeom.TargetPort)));
            return ret;
        }
        /// <summary>
        /// change the polyline by removing cycles
        /// </summary>
        void SimplifyRegularEdge(EdgeGeometry edge) {
            Polyline polyline = (Polyline)edge.Curve;

            var stack = new Stack<Point>();
            var seen = new Set<Point>();
            for (var p = polyline.EndPoint; p != null; p = p.Prev) {
                var v = p.Point;
                if (seen.Contains(p.Point)) {
                    var pp = p.Next;
                    do {
                        var u = stack.Peek();
                        if (u != v) {
                            seen.Remove(u);
                            stack.Pop();
                            pp = pp.Next;
                        }
                        else
                            break;
                    } while (true);
                    pp.Prev = p.Prev;
                    pp.Prev.Next = pp;
                }
                else {
                    stack.Push(v);
                    seen.Insert(v);
                }
            }
        }
 internal static bool ContainmentLoop(EdgeGeometry eg, double padding) {
     var sourceCurve = eg.SourcePort.Curve;
     var targetCurve = eg.TargetPort.Curve;
     if (sourceCurve == null || targetCurve == null)
         return false;
     Rectangle targetBox = sourceCurve.BoundingBox;
     Rectangle sourceBox = targetCurve.BoundingBox;
     bool targetInSource = targetBox.Contains(sourceBox);
     bool sourceInTarget = (!targetInSource) && sourceBox.Contains(targetBox);
     if (targetInSource || sourceInTarget) {
         eg.Curve = CreateLoop(targetBox, sourceBox, sourceInTarget, padding);
         return true;
     }
     return false;
 }
 public void DrawRubberEdge(EdgeGeometry edgeGeometry) {
     if (_rubberEdgePath == null) {
         _rubberEdgePath = new Path
         {
             Stroke = Brushes.Black,
             StrokeThickness = GetBorderPathThickness()*3
         };
         GraphCanvasChildrenAdd(_rubberEdgePath);
         targetArrowheadPathForRubberEdge = new Path
         {
             Stroke = Brushes.Black,
             StrokeThickness = GetBorderPathThickness()*3
         };
         GraphCanvasChildrenAdd(targetArrowheadPathForRubberEdge);
     }
     _rubberEdgePath.Data = GraphmapsEdge.GetICurveWpfGeometry(edgeGeometry.Curve);
     targetArrowheadPathForRubberEdge.Data = GraphmapsEdge.DefiningTargetArrowHead(edgeGeometry,
         edgeGeometry.LineWidth);
 }
Пример #24
0
 public void DrawRubberEdge(EdgeGeometry edgeGeometry)
 {
     if (RubberEdgePath != null)
         MainCanvas.Children.Remove(RubberEdgePath);
     RubberEdgePath = new Path() { Stroke = BlackBrush, StrokeThickness = 2.0 };
     PathFigure figure = Draw.CreateGraphicsPath(edgeGeometry.Curve);
     PathGeometry geometry = new PathGeometry();
     geometry.Figures.Add(figure);
     RubberEdgePath.Data = geometry;
     RubberEdgePath.SetValue(Canvas.LeftProperty, edgeGeometry.BoundingBox.Left);
     RubberEdgePath.SetValue(Canvas.TopProperty, edgeGeometry.BoundingBox.Bottom);
     geometry.Transform = new MatrixTransform() { Matrix = new Matrix(1.0, 0.0, 0.0, 1.0, -edgeGeometry.BoundingBox.Left, -edgeGeometry.BoundingBox.Bottom) };
     MainCanvas.Children.Add(RubberEdgePath);
 }
 void InitEdgeData(EdgeGeometry geomEdge, int index) {
     var metroEdge = new Metroline((Polyline)geomEdge.Curve, geomEdge.LineWidth, EdgeSourceAndTargetFunc(geomEdge), index);
     metrolines.Add(metroEdge);
     PointToStations[metroEdge.Polyline.Start].BoundaryCurve = geomEdge.SourcePort.Curve;
     PointToStations[metroEdge.Polyline.End].BoundaryCurve = geomEdge.TargetPort.Curve;
 }
        private void AddWaypointsToGraph(EdgeGeometry edgeGeom) {
            if (null == edgeGeom.Waypoints) {
                return;
            }

            // Waypoints form part of a composite path and therefore we want more than just a single entry to out-of-bounds
            // waypoints, so we can go out from graph, through waypoint, and back to the graph without backtracking along the
            // same edge. If two waypoints are out of bounds to the same side, make sure there is a single-bend (or 0-bend
            // if collinear) path between them.
            FreePoint lastOobWaypoint = null;
            FreePoint firstWaypoint = null;
            foreach (var point in edgeGeom.Waypoints) {
                var freePoint = this.AddFreePointToGraph(point);
                if (firstWaypoint == null) {
                    firstWaypoint = freePoint;
                }
                if (!freePoint.IsOutOfBounds) {
                    lastOobWaypoint = null;
                    continue;
                }

                if (null != lastOobWaypoint) {
                    if (!this.ObstacleTree.GraphBox.Intersects(new Rectangle(lastOobWaypoint.Point, freePoint.Point))) {
                        // They are oob to the same side.
                        var dirs = PointComparer.GetDirections(lastOobWaypoint.Point, freePoint.Point);
                        if (CompassVector.IsPureDirection(dirs)) {
                            this.TransUtil.ConnectVertexToTargetVertex(lastOobWaypoint.Vertex, freePoint.Vertex, dirs, ScanSegment.NormalWeight);
                        } else {
                            this.TransUtil.ConnectVertexToTargetVertex(lastOobWaypoint.Vertex, freePoint.Vertex, 
                                dirs & (Directions.North | Directions.South), ScanSegment.NormalWeight);
                            this.TransUtil.ConnectVertexToTargetVertex(lastOobWaypoint.Vertex, freePoint.Vertex,
                                dirs & (Directions.East | Directions.West), ScanSegment.NormalWeight);
                        }
                    } else {
                        // They are both out of bounds but not to the same side, so create a single turn around the corner.
                        // Nudger doesn't seem to always remove the staircase if we don't.  Don't bother if they are at 
                        // opposite sides of the graph, including diagonal corners.
                        if (PointComparer.IsPureDirection(freePoint.OutOfBoundsDirectionFromGraph)
                                && PointComparer.IsPureDirection(lastOobWaypoint.OutOfBoundsDirectionFromGraph)
                                && (lastOobWaypoint.OutOfBoundsDirectionFromGraph != CompassVector.OppositeDir(freePoint.OutOfBoundsDirectionFromGraph))) {
                            this.TransUtil.ConnectVertexToTargetVertex(freePoint.Vertex, lastOobWaypoint.Vertex, 
                                CompassVector.OppositeDir(freePoint.OutOfBoundsDirectionFromGraph), ScanSegment.NormalWeight);
                        }
                    }
                }
                lastOobWaypoint = freePoint;
            }

            ConnectOobWaypointToEndpointVisibilityAtGraphBoundary(firstWaypoint, edgeGeom.SourcePort);
            ConnectOobWaypointToEndpointVisibilityAtGraphBoundary(lastOobWaypoint, edgeGeom.TargetPort);
        }
        internal bool SetAllAncestorsActive(EdgeGeometry edgeGeom, Dictionary<Shape, Obstacle> shapeToObstacleMap) {
            if (0 == AncestorSets.Count) {
                return false;
            }
            ObstacleTree.AdjustSpatialAncestors();

            ClearActiveAncestors();

            ObstaclePort sourceOport, targetOport;
            var ssAncs = FindAncestorsAndObstaclePort(edgeGeom.SourcePort, out sourceOport);
            var ttAncs = FindAncestorsAndObstaclePort(edgeGeom.TargetPort, out targetOport);

            if ((AncestorSets.Count > 0) && (null != ssAncs) && (null != ttAncs)) {
                // Make all ancestors boundaries transparent; in this case we've already tried with only
                // non-common and found no path, so perhaps an obstacle is outside its parent group's bounds.
                ActivateAncestors(ssAncs, ttAncs, shapeToObstacleMap);
                return true;
            }
            return false;
        }
        /// <summary>
        /// trim the edge curve with the node boundaries
        /// </summary>
        /// <param name="edgeGeometry"></param>
        /// <param name="targetBoundary"></param>
        /// <param name="spline"></param>
        /// <param name="narrowestInterval"></param>
        /// <param name="sourceBoundary"></param>
        /// <param name="keepOriginalSpline"></param>
        /// <returns></returns>
        public static bool TrimSplineAndCalculateArrowheads(EdgeGeometry edgeGeometry,
                                                            ICurve sourceBoundary,
                                                            ICurve targetBoundary,
                                                            ICurve spline,
                                                            bool narrowestInterval,
                                                            bool keepOriginalSpline)
        {
            ValidateArg.IsNotNull(spline, "spline");
            ValidateArg.IsNotNull(edgeGeometry, "edgeGeometry");


            edgeGeometry.Curve = Curve.TrimEdgeSplineWithNodeBoundaries(sourceBoundary, targetBoundary, spline,
                                                                        narrowestInterval);
            if (edgeGeometry.Curve == null)
            {
                return(false);
            }

            if ((edgeGeometry.SourceArrowhead == null ||
                 edgeGeometry.SourceArrowhead.Length < ApproximateComparer.DistanceEpsilon) &&
                (edgeGeometry.TargetArrowhead == null ||
                 edgeGeometry.TargetArrowhead.Length < ApproximateComparer.DistanceEpsilon))
            {
                return(true); //there are no arrowheads
            }
            bool   success = false;
            double sourceArrowheadSavedLength = edgeGeometry.SourceArrowhead != null
                                                    ? edgeGeometry.SourceArrowhead.Length
                                                    : 0;
            double targetArrowheadSavedLength = edgeGeometry.TargetArrowhead != null
                                                    ? edgeGeometry.TargetArrowhead.Length
                                                    : 0;
            var len = (edgeGeometry.Curve.End - edgeGeometry.Curve.Start).Length;

            if (edgeGeometry.SourceArrowhead != null)
            {
                edgeGeometry.SourceArrowhead.Length = Math.Min(len, sourceArrowheadSavedLength);
            }
            if (edgeGeometry.TargetArrowhead != null)
            {
                edgeGeometry.TargetArrowhead.Length = Math.Min(len, targetArrowheadSavedLength);
            }
            int count = 10;

            while (
                (
                    edgeGeometry.SourceArrowhead != null &&
                    edgeGeometry.SourceArrowhead.Length > ApproximateComparer.IntersectionEpsilon
                    ||
                    edgeGeometry.TargetArrowhead != null &&
                    edgeGeometry.TargetArrowhead.Length > ApproximateComparer.IntersectionEpsilon) && !success)
            {
                success = Arrowheads.CalculateArrowheads(edgeGeometry);
                if (!success)
                {
                    if (edgeGeometry.SourceArrowhead != null)
                    {
                        edgeGeometry.SourceArrowhead.Length *= 0.5;
                    }
                    if (edgeGeometry.TargetArrowhead != null)
                    {
                        edgeGeometry.TargetArrowhead.Length *= 0.5;
                    }
                }
                count--;
                if (count == 0)
                {
                    break;
                }
            }

            if (!success)
            {
                //to avoid drawing the arrowhead to (0,0)
                if (edgeGeometry.SourceArrowhead != null)
                {
                    edgeGeometry.SourceArrowhead.TipPosition = spline.Start;
                }
                if (edgeGeometry.TargetArrowhead != null)
                {
                    edgeGeometry.TargetArrowhead.TipPosition = spline.End;
                }
            }

            if (edgeGeometry.SourceArrowhead != null)
            {
                edgeGeometry.SourceArrowhead.Length = sourceArrowheadSavedLength;
            }
            if (edgeGeometry.TargetArrowhead != null)
            {
                edgeGeometry.TargetArrowhead.Length = targetArrowheadSavedLength;
            }

            return(success);
        }
        private void GetPortSpliceLimitRectangle(EdgeGeometry edgeGeom) {
            if (!this.LimitPortVisibilitySpliceToEndpointBoundingBox) {
                this.portSpliceLimitRectangle = graphGenerator.ObstacleTree.GraphBox;
                return;
            }

            // Return the endpoint-containing rectangle marking the limits of edge-chain extension for a single path.
            this.portSpliceLimitRectangle = GetPortRectangle(edgeGeom.SourcePort);
            this.portSpliceLimitRectangle.Add(GetPortRectangle(edgeGeom.TargetPort));
            if (null != edgeGeom.Waypoints) {
                foreach (Point waypoint in edgeGeom.Waypoints) {
                    AddToLimitRectangle(waypoint);
                }
            }
        }
        private PreGraph CreatePregraphFromSetOfEdgeGeometries(EdgeGeometry[] egs) {
            var nodeBoundaries = new Set<ICurve>();
            var eg = egs[0];
            var c = GetPortCurve(eg.SourcePort);
            var rect = c.BoundingBox;
            nodeBoundaries.Insert(c);
            nodeBoundaries.Insert(eg.TargetPort.Curve);
            rect.Add(eg.TargetPort.Curve.BoundingBox);
            var overlapped = nodeTree.GetNodeItemsIntersectingRectangle(rect);
            foreach (var nodeBoundary in overlapped)
                nodeBoundaries.Insert(nodeBoundary);

            return new PreGraph(egs, nodeBoundaries);
        }
 private static void CalculateArrowheads(EdgeGeometry edgeGeom)
 {
     Arrowheads.TrimSplineAndCalculateArrowheads(edgeGeom, edgeGeom.SourcePort.Curve, edgeGeom.TargetPort.Curve, edgeGeom.Curve, true, false);
 }
 private static ICurve GetSourceBoundary(EdgeGeometry edgeGeom){
     return edgeGeom.SourcePort.Curve;            
 }
Пример #33
0
 public void DrawRubberEdge(EdgeGeometry edgeGeometry)
 {
     throw new NotImplementedException();
 }
 internal Func<Tuple<Polyline, Polyline>> EdgeSourceAndTargetFunc(EdgeGeometry geomEdge) {
     return
         () =>
         new Tuple<Polyline, Polyline>(LoosePolylineOfPort(geomEdge.SourcePort),
                                        LoosePolylineOfPort(geomEdge.TargetPort));
 }