private Node GetOrCreateNode(Port port, Dictionary<ICurve, Node> nodeDictionary) { var curve = GetPortCurve(port); Node node; if (!nodeDictionary.TryGetValue(curve, out node)) nodeDictionary[curve] = node = new Node(curve); return node; }
private ObstaclePort CreateObstaclePort(Obstacle obstacle, Port port) { // This will replace any previous specification for the port (last one wins). Debug.Assert(!obstaclePortMap.ContainsKey(port), "Port is used by more than one obstacle"); if (null == port.Curve) { return null; } var roundedLocation = ApproximateComparer.Round(port.Location); if (PointLocation.Outside == Curve.PointRelativeToCurveLocation(roundedLocation, obstacle.InputShape.BoundaryCurve)) { // Obstacle.Port is outside Obstacle.Shape; handle it as a FreePoint. return null; } if ((obstacle.InputShape.BoundaryCurve != port.Curve) && (PointLocation.Outside == Curve.PointRelativeToCurveLocation(roundedLocation, port.Curve))) { // Obstacle.Port is outside port.Curve; handle it as a FreePoint. return null; } var oport = new ObstaclePort(port, obstacle); obstaclePortMap[port] = oport; return oport; }
private void ConnectOobWaypointToEndpointVisibilityAtGraphBoundary(FreePoint oobWaypoint, Port port) { if ((oobWaypoint == null) || !oobWaypoint.IsOutOfBounds) { return; } // Connect to the graphbox side at points collinear with the vertices. The waypoint may be // OOB in two directions so call once for each axis. var endpointVertices = this.FindVertices(port); var dirFromGraph = oobWaypoint.OutOfBoundsDirectionFromGraph & (Directions.North | Directions.South); ConnectToGraphAtPointsCollinearWithVertices(oobWaypoint, dirFromGraph, endpointVertices); dirFromGraph = oobWaypoint.OutOfBoundsDirectionFromGraph & (Directions.East | Directions.West); ConnectToGraphAtPointsCollinearWithVertices(oobWaypoint, dirFromGraph, endpointVertices); }
private Point FigureOutHookLocationForSimpleOtherPort(Polyline poly, Port otherEdgeEndPort, EdgeGeometry edgeGeom) { Point otherEdgeEnd = otherEdgeEndPort.Location; var shapes = shortestPathRouter.MakeTransparentShapesOfEdgeGeometry(edgeGeom); //SplineRouter.ShowVisGraph(this.VisibilityGraph, this.LooseHierarchy.GetAllLeaves(), // shapes.Select(sh => sh.BoundaryCurve), new[] { new LineSegment(edgeGeom.SourcePort.Location, edgeGeom.TargetPort.Location) }); var s = new SingleSourceMultipleTargetsShortestPathOnVisibilityGraph( VisibilityGraph.FindVertex(otherEdgeEnd), poly.PolylinePoints.Select(p => VisibilityGraph.FindVertex(p.Point)), VisibilityGraph); var path = s.GetPath(); foreach (var sh in shapes) sh.IsTransparent = false; return path.Last().Point; }
void RemoveObstaclePort(Port port) { obstaclePortMap.Remove(port); }
private void WriteRelativePort(Port port, int shapeId) { var relativePort = port as RelativeFloatingPort; var multiPort = port as MultiLocationFloatingPort; Validate.IsNotNull(relativePort, "Unsupported port type for file persistence"); // ReSharper disable PossibleNullReferenceException // The location in the main WritePort line is relevant only for non-multiPort; for multiPorts // the caller sets location via ActiveOffsetIndex. var portTypeString = (null != multiPort) ? RectFileStrings.Multi : RectFileStrings.Relative; this.outputFileWriter.WriteLine(RectFileStrings.WritePort, portTypeString, relativePort.LocationOffset.X, relativePort.LocationOffset.Y, this.portToIdMap[port], shapeId); // ReSharper restore PossibleNullReferenceException if (null != multiPort) { this.outputFileWriter.WriteLine(RectFileStrings.WriteMultiPortOffsets, multiPort.ActiveOffsetIndex); foreach (var offset in multiPort.LocationOffsets) { this.outputFileWriter.WriteLine(RectFileStrings.WritePoint, offset.X, offset.Y); } } }
static void FixPortAtSource(Shape shape, Port port, Edge e) { if (e.SourcePort == null) e.SourcePort = port; else shape.Ports.Insert(e.SourcePort); }
private void AddPortToGraph(Port port, ObstaclePort oport) { if (null != oport) { AddObstaclePortToGraph(oport); return; } // This is a FreePoint, either a Waypoint or a Port not in an Obstacle.Ports list. AddFreePointToGraph(port.Location); }
void DrawEdgeInteractivelyToPort(Port targetPortParameter,Polyline portLoosePolyline) { viewer.DrawRubberEdge(EdgeGeometry = CalculateEdgeInteractively(targetPortParameter,portLoosePolyline)); }
void SetPortForMousePositionInsideOfNode(Point mousePosition, IViewerNode node, ref Port port) { GeometryNode geomNode = GeometryNode(node); double t; if (NeedToCreateBoundaryPort(mousePosition, node, out t)) port = CreateOrUpdateCurvePort(t, geomNode, port); else port = CreateFloatingPort(geomNode, ref mousePosition); }
Set<Shape> AncestorsForPort(Port port) { Shape shape; if (PortToShapes.TryGetValue(port, out shape)) { return AncestorsSets[shape]; } // This is a FreePort or Waypoint; return all spatial parents. return new Set<Shape>(HierarchyOfGroups.AllHitItems(new Rectangle(port.Location, port.Location), null)); }
Port CreateOrUpdateCurvePort(double t, GeometryNode geomNode, Port port) { var cp = port as CurvePort; if (cp == null) return new CurvePort(geomNode.BoundaryCurve, t); cp.Parameter = t; cp.Curve = geomNode.BoundaryCurve; return port; }
void SetPortUnderLoosePolyline(Point mousePosition, Polyline loosePoly, ref IViewerNode node, ref Port port) { double dist = double.PositiveInfinity; double par = 0; foreach (var viewerNode in GetViewerNodesInsideOfLooseObstacle(loosePoly)) { var curve = ((Node)viewerNode.DrawingObject).GeometryNode.BoundaryCurve; if (PointIsInside(mousePosition, curve)) { node = viewerNode; SetPortForMousePositionInsideOfNode(mousePosition, node, ref port); return; } double p = curve.ClosestParameter(mousePosition); double d = (curve[p] - mousePosition).Length; if (d < dist) { par = p; dist = d; node = viewerNode; } } port = CreateOrUpdateCurvePort(par, ((Node)node.DrawingObject).GeometryNode, port); }
IViewerNode SetPortWhenDraggingStraightLine(ref Port port, ref Point mousePosition) { var viewerNode = viewer.ObjectUnderMouseCursor as IViewerNode; if (viewerNode != null){ double t; GeometryNode geomNode = ((Node) viewerNode.DrawingObject).GeometryNode; if (NeedToCreateBoundaryPort(mousePosition, viewerNode, out t)) port = CreateOrUpdateCurvePort(t, geomNode, port); else port = PointIsInside(mousePosition, ((Node) viewerNode.DrawingObject).GeometryNode.BoundaryCurve) ? CreateFloatingPort(geomNode, ref mousePosition) : null; } else port = null; return viewerNode; }
bool TrySetNodePort(MsaglMouseEventArgs e, ref IViewerNode node, ref Port port, out Polyline loosePolyline) { Debug.Assert(InsertingEdge); Point mousePosition = viewer.ScreenToSource(e); loosePolyline = null; if (Graph != null) { if (DraggingStraightLine()) { node= SetPortWhenDraggingStraightLine(ref port, ref mousePosition); } else { if (InteractiveEdgeRouter == null) PrepareForEdgeDragging(); loosePolyline = InteractiveEdgeRouter.GetHitLoosePolyline(viewer.ScreenToSource(e)); if (loosePolyline != null) SetPortUnderLoosePolyline(mousePosition, loosePolyline, ref node, ref port); else { node = null; port = null; } } } return port != null; }
EdgeGeometry CalculateEdgeInteractively(Port targetPortParameter,Polyline portLoosePolyline) { if(InteractiveEdgeRouter.SourcePort == null) InteractiveEdgeRouter.SetSourcePortAndSourceLoosePolyline(SourcePort,sourceLoosePolyline); ICurve curve; SmoothedPolyline smoothedPolyline = null; if(SourceOfInsertedEdge == TargetOfInsertedEdge) { curve = new LineSegment(SourcePort.Location,TargetPort.Location); } else { curve = InteractiveEdgeRouter.RouteEdgeToPort(targetPortParameter,portLoosePolyline,false, out smoothedPolyline); } return new EdgeGeometry { Curve = curve,SmoothedPolyline = smoothedPolyline }; }
internal Set<Shape> FindAncestorsAndObstaclePort(Port port, out ObstaclePort oport) { oport = FindObstaclePort(port); if (0 == AncestorSets.Count) { return null; } if (null != oport) { return AncestorSets[oport.Obstacle.InputShape]; } // This is a free Port (not associated with an obstacle) or a Waypoint; return all spatial parents. return new Set<Shape>(ObstacleTree.Root.AllHitItems(new Rectangle(port.Location, port.Location), shape => shape.IsGroup) .Select(obs => obs.InputShape)); }
Rectangle GetPortRectangle(Port port) { ObstaclePort oport; obstaclePortMap.TryGetValue(port, out oport); if (null != oport) { return (oport.Obstacle.VisibilityBoundingBox); } // FreePoint. return new Rectangle(ApproximateComparer.Round(port.Location)); }
internal ObstaclePort FindObstaclePort(Port port) { ObstaclePort oport; if (obstaclePortMap.TryGetValue(port, out oport)) { // First see if the obstacle's port list has changed without UpdateObstacles() being called. // Unfortunately we don't have a way to update the obstacle's ports until we enter // this block; there is no direct Port->Shape/Obstacle mapping. So UpdateObstacle must still // be called, but at least this check here will remove obsolete ObstaclePorts. Set<Port> addedPorts, removedPorts; if (oport.Obstacle.GetPortChanges(out addedPorts, out removedPorts)) { foreach (var newPort in addedPorts) { CreateObstaclePort(oport.Obstacle, newPort); } foreach (var oldPort in removedPorts) { RemoveObstaclePort(oldPort); } // If it's not still there, it was moved outside the obstacle so we'll just add it as a FreePoint. if (!obstaclePortMap.TryGetValue(port, out oport)) { oport = null; } } } return oport; }
private void WriteIfFreePort(Port port) { // Skip this port if we've already processed it. if (portToIdMap.ContainsKey(port)) { return; } int shapeId = FreePortShapeId; if (port is RelativeFloatingPort) { Shape shape; if ((null == this.freeRelativePortToShapeMap) || !this.freeRelativePortToShapeMap.TryGetValue(port, out shape)) { Validate.Fail("Relative FreePorts must be in FreeRelativePortToShapeMap"); return; } shapeId = shapeToIdMap[shape]; } portToIdMap.Add(port, NextPortId); WritePort(port, shapeId); }
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); } } }
static void CheckPortOfNode(Node node, Port nodePort) { if (node is Cluster) Debug.Assert(nodePort is ClusterBoundaryPort || nodePort is HookUpAnywhereFromInsidePort || nodePort is CurvePort); }
private void WriteObstaclePort(Shape shape, Port port) { Validate.IsFalse(portToIdMap.ContainsKey(port), "Duplicate entries for port in the same or different shape.Ports list(s)"); var relativePort = port as RelativeFloatingPort; if (null != relativePort) { Validate.IsTrue(PointComparer.Equal(shape.BoundingBox.Center, relativePort.CenterDelegate()), "Port CenterDelegate must be Shape.Center for file persistence"); Validate.AreEqual(shape.BoundaryCurve, port.Curve, "Port curve is not the same as that of the Shape in which it is a member"); } portToIdMap.Add(port, NextPortId); WritePort(port, shapeToIdMap[shape]); }
private ICurve GetPortCurve(Port port) { var curve = nodeTree.FirstHitNode(port.Location, (point, c) => Curve.PointRelativeToCurveLocation(point, c) != PointLocation.Outside ? HitTestBehavior.Stop : HitTestBehavior.Continue).UserData; return curve; }
private void WritePort(Port port, int shapeId) { if (typeof(FloatingPort) == port.GetType()) { this.outputFileWriter.WriteLine(RectFileStrings.WritePort, RectFileStrings.Floating, port.Location.X, port.Location.Y, portToIdMap[port], shapeId); } else { WriteRelativePort(port, shapeId); } WritePortEntries(port); }
internal EdgeGeometry(Port sourcePort, Port targetPort) { SourcePort = sourcePort; TargetPort = targetPort; }
private void WritePortEntries(Port port) { if (null == port.PortEntry) { return; } var portEntryOnCurve = port.PortEntry as PortEntryOnCurve; Validate.IsNotNull(portEntryOnCurve, "Unknown IPortEntry implementation"); // ReSharper disable PossibleNullReferenceException this.outputFileWriter.WriteLine(RectFileStrings.PortEntryOnCurve); foreach (var span in portEntryOnCurve.Spans) { this.outputFileWriter.WriteLine(RectFileStrings.WritePoint, span.Item1, span.Item2); } // ReSharper restore PossibleNullReferenceException }
internal List<VisibilityVertex> FindVertices(Port port) { var vertices = new List<VisibilityVertex>(); ObstaclePort oport; if (obstaclePortMap.TryGetValue(port, out oport)) { if (RouteToCenterOfObstacles) { vertices.Add(oport.CenterVertex); return vertices; } // Add all vertices on the obstacle borders. Avoid LINQ for performance. foreach (var entrance in oport.PortEntrances) { VisibilityVertex vertex = this.VisGraph.FindVertex(entrance.UnpaddedBorderIntersect); if (null != vertex) { vertices.Add(vertex); } } return vertices; } vertices.Add(VisGraph.FindVertex(ApproximateComparer.Round(port.Location))); return vertices; }
static void FixPortAtTarget(Shape shape, Port port, Edge e) { if (e.TargetPort == null) e.TargetPort = port; else shape.Ports.Insert(e.TargetPort); }
Point FigureOutHookLocation(Polyline poly, Port otherEdgeEndPort, EdgeGeometry edgeGeom) { var clusterPort = otherEdgeEndPort as ClusterBoundaryPort; if (clusterPort == null) { return FigureOutHookLocationForSimpleOtherPort(poly, otherEdgeEndPort, edgeGeom); } return FigureOutHookLocationForClusterOtherPort(poly, clusterPort, edgeGeom); }