/// <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); }
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); }
/// <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); }
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; }
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)); }