internal ObstaclePortEntrance(ObstaclePort oport, Point unpaddedBorderIntersect, Directions outDir, ObstacleTree obstacleTree) { ObstaclePort = oport; UnpaddedBorderIntersect = unpaddedBorderIntersect; OutwardDirection = outDir; // Get the padded intersection. var lineSeg = new LineSegment(UnpaddedBorderIntersect, StaticGraphUtility.RectangleBorderIntersect( oport.Obstacle.VisibilityBoundingBox, UnpaddedBorderIntersect, outDir)); IList<IntersectionInfo> xxs = Curve.GetAllIntersections(lineSeg, oport.Obstacle.VisibilityPolyline, true /*liftIntersections*/); Debug.Assert(1 == xxs.Count, "Expected one intersection"); this.VisibilityBorderIntersect = ApproximateComparer.Round(SpliceUtility.RawIntersection(xxs[0], UnpaddedBorderIntersect)); this.MaxVisibilitySegment = obstacleTree.CreateMaxVisibilitySegment(this.VisibilityBorderIntersect, this.OutwardDirection, out this.pointAndCrossingsList); // Groups are never in a clump (overlapped) but they may still have their port entrance overlapped. if (this.Obstacle.IsOverlapped || (this.Obstacle.IsGroup && !this.Obstacle.IsInConvexHull)) { this.IsOverlapped = obstacleTree.IntersectionIsInsideAnotherObstacle(/*sideObstacle:*/ null, this.Obstacle , this.VisibilityBorderIntersect, ScanDirection.GetInstance(OutwardDirection)); if (!this.Obstacle.IsGroup || this.IsOverlapped || this.InteriorEdgeCrossesObstacle(obstacleTree)) { unpaddedToPaddedBorderWeight = ScanSegment.OverlappedWeight; } } if (this.Obstacle.IsInConvexHull && (unpaddedToPaddedBorderWeight == ScanSegment.NormalWeight)) { SetUnpaddedToPaddedBorderWeightFromHullSiblingOverlaps(obstacleTree); } }
internal static ParallelogramNodeOverICurve CreateParallelogramNodeForCurveSeg(double start, double end, Ellipse seg, double eps){ bool closedSeg = (start == seg.ParStart && end == seg.ParEnd && ApproximateComparer.Close(seg.Start, seg.End)); if(closedSeg) return CreateNodeWithSegmentSplit(start, end, seg, eps); Point s = seg[start]; Point e = seg[end]; Point w = e - s; Point middle = seg[(start + end) / 2]; if (ParallelogramNodeOverICurve.DistToSegm(middle, s, e) <= ApproximateComparer.IntersectionEpsilon && w * w < Curve.LineSegmentThreshold * Curve.LineSegmentThreshold && end - start < Curve.LineSegmentThreshold) { var ls = new LineSegment(s, e); var leaf = ls.ParallelogramNodeOverICurve as ParallelogramLeaf; leaf.Low = start; leaf.High = end; leaf.Seg = seg; leaf.Chord = ls; return leaf; } bool we = WithinEpsilon(seg, start, end, eps); var box = new Parallelogram(); if(we && CreateParallelogramOnSubSeg(start, end, seg, ref box)){ return new ParallelogramLeaf(start, end, box, seg, eps); } else{ return CreateNodeWithSegmentSplit(start, end, seg, eps); } }
protected string LineSegmentString(LineSegment ls) { return("L " + PointToString(ls.End)); }
private void CreateObstaclePortEntrancesFromPoints(ObstaclePort oport) { var graphBox = graphGenerator.ObstacleTree.GraphBox; var curveBox = new Rectangle(ApproximateComparer.Round(oport.PortCurve.BoundingBox.LeftBottom) , ApproximateComparer.Round(oport.PortCurve.BoundingBox.RightTop)); // This Port does not have a PortEntry, so we'll have visibility edges to its location // in the Horizontal and Vertical directions (possibly all 4 directions, if not on boundary). // // First calculate the intersection with the obstacle in all directions. Do nothing in the // horizontal direction for port locations that are on the unpadded vertical extremes, because // this will have a path that moves alongside a rectilinear obstacle side in less than the // padding radius and will thus create the PaddedBorderIntersection on the side rather than top // (and vice-versa for the vertical direction). We'll have an edge in the vertical direction // to the padded extreme boundary ScanSegment, and the Nudger will modify paths as appropriate // to remove unnecessary bends. // Use the unrounded port location to intersect with its curve. Point location = ApproximateComparer.Round(oport.PortLocation); Point xx0, xx1; bool found = false; if (!PointComparer.Equal(location.Y, curveBox.Top) && !PointComparer.Equal(location.Y, curveBox.Bottom)) { found = true; var hSeg = new LineSegment(graphBox.Left, location.Y, graphBox.Right, location.Y); GetBorderIntersections(location, hSeg, oport.PortCurve, out xx0, out xx1); var wBorderIntersect = new Point(Math.Min(xx0.X, xx1.X), location.Y); if (wBorderIntersect.X < curveBox.Left) { // Handle rounding error wBorderIntersect.X = curveBox.Left; } var eBorderIntersect = new Point(Math.Max(xx0.X, xx1.X), location.Y); if (eBorderIntersect.X > curveBox.Right) { eBorderIntersect.X = curveBox.Right; } CreatePortEntrancesAtBorderIntersections(curveBox, oport, location, wBorderIntersect, eBorderIntersect); } // endif horizontal pass is not at vertical extreme if (!PointComparer.Equal(location.X, curveBox.Left) && !PointComparer.Equal(location.X, curveBox.Right)) { found = true; var vSeg = new LineSegment(location.X, graphBox.Bottom, location.X, graphBox.Top); GetBorderIntersections(location, vSeg, oport.PortCurve, out xx0, out xx1); var sBorderIntersect = new Point(location.X, Math.Min(xx0.Y, xx1.Y)); if (sBorderIntersect.Y < graphBox.Bottom) { // Handle rounding error sBorderIntersect.Y = graphBox.Bottom; } var nBorderIntersect = new Point(location.X, Math.Max(xx0.Y, xx1.Y)); if (nBorderIntersect.Y > graphBox.Top) { nBorderIntersect.Y = graphBox.Top; } CreatePortEntrancesAtBorderIntersections(curveBox, oport, location, sBorderIntersect, nBorderIntersect); } // endif vertical pass is not at horizontal extreme if (!found) { // This must be on a corner, else one of the above would have matched. this.CreateEntrancesForCornerPort(curveBox, oport, location); } }
bool IntersectObstacleHierarchy(LineSegment ls) { return HierarchyOfObstacles.GetAllIntersecting(ls.BoundingBox).Any( poly => Curve.CurveCurveIntersectionOne(ls, poly, false) != null); }
private void ShowInputSegments(List<SymmetricTuple<int>> badSegs, Point[] indexToPoints) { #if TEST_MSAGL var l = new List<DebugCurve>(); foreach (var seg in _segments) { var p1 = indexToPoints[seg.A]; var p2 = indexToPoints[seg.B]; var ls = new LineSegment(p1, p2); string color = badSegs.Contains(seg) ? "red" : "black"; double width = badSegs.Contains(seg) ? 3 : 1; l.Add(new DebugCurve(100, width, color, ls)); } //foreach (var p in indexToPoints) //{ // l.Add(new DebugCurve(200, 0.1, "black", CurveFactory.CreateCircle(0.1, p))); //} LayoutAlgorithmSettings.ShowDebugCurves(l.ToArray()); #endif }
static bool LineIntersectsRectangleNode(LineSegment ls, RectangleNode<Polyline> rectNode) { if (!ls.BoundingBox.Intersects(rectNode.Rectangle)) return false; if (rectNode.UserData != null) { // SugiyamaLayoutSettings.Show(ls, rectNode.UserData); return Curve.GetAllIntersections(rectNode.UserData, ls, false).Count > 0; } return LineIntersectsRectangleNode(ls, rectNode.Left) || LineIntersectsRectangleNode(ls, rectNode.Right); }
void GetXCoordinatesOfVirtualNodesOfTheProperLayeredGraphForSkeletonEdge(IntEdge intEdge, LayerArrays layerArrays) { if (intEdge.LayerEdges == null || intEdge.LayerEdges.Count < 2) return; var edgeCurve = intEdge.Edge.Curve; var layerIndex = layerArrays.Y[intEdge.Source] - 1;//it is the layer of the highest virtual node of the edge for (int i = 1; i < intEdge.LayerEdges.Count; i++) { var v = intEdge.LayerEdges[i].Source; var layerY = layerToRecoveredYCoordinates[layerIndex--]; var layerLine = new LineSegment(new Point(originalGraph.Left, layerY), new Point(originalGraph.Right, layerY)); var intersection=Curve.CurveCurveIntersectionOne(edgeCurve, layerLine, false); skeletonVirtualVerticesToX[v] =intersection.IntersectionPoint.X; } }
void ParallelLineSegLineSegMinDist() { LineSegment l0 = curveA as LineSegment; LineSegment l1 = curveB as LineSegment; Point v0 = l0.Start; Point v1 = l0.End; Point v2 = l1.Start; Point v3 = l1.End; Point d0 = v1 - v0; double nd0 = d0.Length; double r0 = 0, r1, r2, r3; if (nd0 > ApproximateComparer.DistanceEpsilon) { //v0 becomes the zero point d0 /= nd0; r1 = d0 * (v1 - v0); r2 = d0 * (v2 - v0); r3 = d0 * (v3 - v0); bool swapped = false; if (r2 > r3) { swapped = true; double t = r2; r2 = r3; r3 = t; } if (r3 < r0) { aSolution = 0; bSolution = swapped ? 0 : 1; } else if (r2 > r1) { aSolution = 1; bSolution = swapped ? 1 : 0; } else { double r = Math.Min(r1, r3); aSolution = r / (r1 - r0); bSolution = (r - r2) / (r3 - r2); if (swapped) { bSolution = 1 - bSolution; } } } else { Point d1 = v3 - v2; double nd1 = d1.Length; if (nd1 > ApproximateComparer.DistanceEpsilon) { //v2 becomes the zero point d1 /= nd1; r0 = 0; //v2 position r1 = d1 * (v3 - v2); //v3 position r2 = d1 * (v0 - v2); //v0 position - here v0 and v1 are indistinguishable if (r2 < r0) { bSolution = 0; aSolution = 1; } else if (r2 > r1) { bSolution = 1; aSolution = 0; } else { double r = Math.Min(r1, r2); bSolution = r / (r1 - r0); aSolution = 0; } } else { aSolution = 0; bSolution = 0; } } aPoint = curveA[aSolution]; bPoint = curveB[bSolution]; }
public static bool SegmentsIntersect(Point p1, Point p2, Point q1, Point q2) { var seg1 = new LineSegment(p1, p2); var seg2 = new LineSegment(q1, q2); var allInt = Curve.GetAllIntersections(seg1, seg2, false); return allInt.Any(); }
internal static ICurve CreateBaseSegmentForDraggingEdgeWithSource(Point delta, GeomEdge edge, EdgeRestoreData edgeRestoreData, Dictionary<GeomEdge, double> offsets) { double offset; ICurve seg; Point a = edgeRestoreData.UnderlyingPolyline.HeadSite.Point + delta; Point b = edgeRestoreData.UnderlyingPolyline.LastSite.Point; if (offsets.TryGetValue(edge, out offset) && offset != 0) { Point ab = b - a; Point abOrtog = ab.Normalize().Rotate(Math.PI/2)*offset; seg = CreateBaseSegOnSourceTargetAndOrth(ref a, ref b, ref abOrtog); // SugiyamaLayoutSettings.Show(seg, edge.Curve, edge.Source.BoundaryCurve); } else seg = new LineSegment(a, b); return seg; }
DebugCurve DebugSweepLine(RealNumberSpan range) { var ls = new LineSegment(Z * SweepDirection + DirectionPerp * range.Min, Z * SweepDirection + DirectionPerp * range.Max); return new DebugCurve(100,0.1,"magenta", ls); }
Rail ContinueReadingRail(LgEdgeInfo topRankedEdgoInfo, int zoomLevel, LgLevel level) { XmlRead(); string pointString; if (TokenIs(GeometryToken.Arrowhead)) { Point arrowheadPosition = TryGetPointAttribute(GeometryToken.ArrowheadPosition); Point attachmentPoint = TryGetPointAttribute(GeometryToken.CurveAttachmentPoint); Arrowhead ah = new Arrowhead { TipPosition = arrowheadPosition, Length = (attachmentPoint - arrowheadPosition).Length }; XmlRead(); ReadEndElement(); var rail = new Rail(ah, attachmentPoint, topRankedEdgoInfo, zoomLevel); var tuple = new SymmetricSegment(arrowheadPosition, attachmentPoint); level._railDictionary[tuple] = rail; return rail; } if (TokenIs(GeometryToken.LineSegment)) { pointString = GetAttribute(GeometryToken.Points); var linePoints = ParsePoints(pointString); Debug.Assert(linePoints.Length == 2); LineSegment ls = new LineSegment(linePoints[0], linePoints[1]); XmlRead(); ReadEndElement(); var rail = new Rail(ls, topRankedEdgoInfo, zoomLevel); var tuple = new SymmetricSegment(ls.Start, ls.End); level._railDictionary[tuple] = rail; level._railTree.Add(ls.BoundingBox, rail); return rail; } if (TokenIs(GeometryToken.CubicBezierSegment)) { pointString = GetAttribute(GeometryToken.Points); var controlPoints = ParsePoints(pointString); Debug.Assert(controlPoints.Length == 4); var bs = new CubicBezierSegment(controlPoints[0], controlPoints[1], controlPoints[2], controlPoints[3]); XmlRead(); ReadEndElement(); var rail = new Rail(bs, topRankedEdgoInfo, zoomLevel); var tuple = new SymmetricSegment(bs.Start, bs.End); level._railDictionary[tuple] = rail; return rail; } throw new Exception(); }
static void AdjustParameters(ParallelogramLeaf l0, LineSegment ls0, ParallelogramLeaf l1, LineSegment ls1, Point x, ref double asol, ref double bsol) { if (ls0 != l0.Seg && l0.Seg is Polyline == false) //l0.Seg is not a LineSegment and not a polyline asol = l0.Seg.ClosestParameter(x); //we need to find the correct parameter else asol = l0.Low + asol*(l0.High - l0.Low); if (ls1 != l1.Seg && l1.Seg is Polyline == false) //l1.Seg is not a LineSegment and not a polyline bsol = l1.Seg.ClosestParameter(x); //we need to find the correct parameter else bsol = l1.Low + bsol*(l1.High - l1.Low); }
static IList<IntersectionInfo> GetAllIntersectionsOfLineAndPolyline(LineSegment lineSeg, Polyline poly) { var ret = new List<IntersectionInfo>(); double offset = 0.0; double par0, par1; Point x; PolylinePoint polyPoint = poly.StartPoint; for (; polyPoint != null && polyPoint.Next != null; polyPoint = polyPoint.Next) { if (CrossTwoLineSegs(lineSeg.Start, lineSeg.End, polyPoint.Point, polyPoint.Next.Point, 0, 1, 0, 1, out par0, out par1, out x)) { AdjustSolution(lineSeg.Start, lineSeg.End, polyPoint.Point, polyPoint.Next.Point, ref par0, ref par1, ref x); if (!OldIntersection(ret, ref x)) ret.Add(new IntersectionInfo(par0, offset + par1, x, lineSeg, poly)); } offset++; } if (poly.Closed) if (CrossTwoLineSegs(lineSeg.Start, lineSeg.End, polyPoint.Point, poly.Start, 0, 1, 0, 1, out par0, out par1, out x)) { AdjustSolution(lineSeg.Start, lineSeg.End, polyPoint.Point, poly.Start, ref par0, ref par1, ref x); if (!OldIntersection(ret, ref x)) ret.Add(new IntersectionInfo(par0, offset + par1, x, lineSeg, poly)); } return ret; }
void WriteLineSeg(LineSegment ls) { WriteStartElement(GeometryToken.LineSegment); WriteAttribute(GeometryToken.Points, PointsToString(ls.Start, ls.End)); WriteEndElement(); }
static void TryToAddPointToLineCircleCrossing(LineSegment lineSeg, Ellipse ellipse, List<IntersectionInfo> ret, Point point, double segLength, Point lineDir) { Point ds = point - lineSeg.Start; Point de = point - lineSeg.End; double t = ds*lineDir; if (t < -ApproximateComparer.DistanceEpsilon) return; t = Math.Max(t, 0); if (t > segLength + ApproximateComparer.DistanceEpsilon) return; t = Math.Min(t, segLength); t /= segLength; double angle = Point.Angle(ellipse.AxisA, point - ellipse.Center); if (ellipse.ParStart - ApproximateComparer.Tolerance <= angle) { angle = Math.Max(angle, ellipse.ParStart); if (angle <= ellipse.ParEnd + ApproximateComparer.Tolerance) { angle = Math.Min(ellipse.ParEnd, angle); ret.Add(new IntersectionInfo(t, angle, point, lineSeg, ellipse)); } } }
public void GetPossibleSides() { for (double angle = 0; angle < 2 * Math.PI; angle += Math.PI / 4) { double lineLength = 10; Point targetPoint = new Point(lineLength * Math.Sin(angle), lineLength * Math.Cos(angle)); LineSegment line = new LineSegment(new Point(0, 0), targetPoint); Point derivative = line.Derivative(0.5); double[] topSides = GetPossibleSides(Label.PlacementSide.Top, derivative).ToArray(); Assert.AreEqual(1, topSides.Length, "Top placement side should have 1 resulting possible side"); Point searchDir = GetSearchDirection(derivative, topSides[0]); Assert.IsTrue(searchDir.Y <= 0, "Top placement side should result in a Y negative search"); double[] bottomSides = GetPossibleSides(Label.PlacementSide.Bottom, derivative).ToArray(); Assert.AreEqual(1, bottomSides.Length, "Bottom placement side should have 1 resulting possible side"); searchDir = GetSearchDirection(derivative, bottomSides[0]); Assert.IsTrue(searchDir.Y >= 0, "Bottom placement side should result in a Y positive search"); double[] leftSides = GetPossibleSides(Label.PlacementSide.Left, derivative).ToArray(); Assert.AreEqual(1, leftSides.Length, "Left placement side should have 1 resulting possible side"); searchDir = GetSearchDirection(derivative, leftSides[0]); Assert.IsTrue(searchDir.X <= 0, "Left placement side should result in a X negative search"); double[] rightSides = GetPossibleSides(Label.PlacementSide.Right, derivative).ToArray(); Assert.AreEqual(1, rightSides.Length, "Right placement side should have 1 resulting possible side"); searchDir = GetSearchDirection(derivative, rightSides[0]); Assert.IsTrue(searchDir.X >= 0, "Right placement side should result in a X positive search"); double[] portSide = GetPossibleSides(Label.PlacementSide.Port, derivative).ToArray(); Assert.AreEqual(1, portSide.Length, "Port placement side should have 1 resulting possible side"); Assert.AreEqual(-1, portSide[0], "Port placement side should be -1"); double[] starboardSide = GetPossibleSides(Label.PlacementSide.Starboard, derivative).ToArray(); Assert.AreEqual(1, starboardSide.Length, "Starboard placement side should have 1 resulting possible side"); Assert.AreEqual(1, starboardSide[0], "Starboard placement side should be 1"); double[] anySide = GetPossibleSides(Label.PlacementSide.Any, derivative).ToArray(); Assert.AreEqual(2, anySide.Length, "Any placement side should have 2 resulting possible sides"); Assert.AreEqual(-1, anySide[0], "Any placement side should start with -1"); Assert.AreEqual(1, anySide[1], "Any placement side should end with 1"); } }
bool LineIntersectsTightObstacles(LineSegment ls) { return LineIntersectsRectangleNode(ls, obstacleCalculator.RootOfTightHierararchy); }
private static bool CurveIntersectsHierarchy(LineSegment lineSeg, ParallelogramNode hierarchy) { if (hierarchy == null) return false; if (!Parallelogram.Intersect(lineSeg.ParallelogramNodeOverICurve.Parallelogram, hierarchy.Parallelogram)) return false; ParallelogramBinaryTreeNode n = hierarchy as ParallelogramBinaryTreeNode; if (n != null) return CurveIntersectsHierarchy(lineSeg, n.LeftSon) || CurveIntersectsHierarchy(lineSeg, n.RightSon); return Curve.GetAllIntersections(lineSeg, ((ParallelogramNodeOverICurve)hierarchy).Seg, false).Count > 0; }
LineSegment TryRouteStraightLine() { var ls = new LineSegment(SourcePoint, TargetPoint); if (obstacleCalculator.ObstaclesIntersectICurve(ls)) return null; return ls; }
static internal bool IntervalsOverlap(LineSegment first, LineSegment second) { return IntervalsOverlap(first.Start, first.End, second.Start, second.End); }
/// <summary> /// ignoring crossing at ls.Start /// </summary> /// <param name="ls"></param> /// <param name="rTree"></param> /// <param name="segsToIgnore"></param> /// <returns></returns> static bool IsCrossing(LineSegment ls, RTree<SegWithIndex> rTree, SegWithIndex[] segsToIgnore) { return rTree.GetAllIntersecting(ls.BoundingBox).Where(seg => !segsToIgnore.Contains(seg)).Any(); }
static internal bool PointIsOnSegmentInterior(LineSegment seg, Point test) { return PointIsOnSegmentInterior(seg.Start, seg.End, test); }
/// <summary> /// Returns a line segment for the given edge. /// </summary> /// <returns>The line segment representing the given edge.</returns> public static LineSegment GetEdgeLine(Edge edge) { ValidateArg.IsNotNull(edge, "edge"); Point sourcePoint; ICurve sourceBox; if (edge.SourcePort == null) { sourcePoint = edge.Source.Center; sourceBox = edge.Source.BoundaryCurve; } else { sourcePoint = edge.SourcePort.Location; sourceBox = edge.SourcePort.Curve; } Point targetPoint; ICurve targetBox; if (edge.TargetPort == null) { targetPoint = edge.Target.Center; targetBox = edge.Target.BoundaryCurve; } else { targetPoint = edge.TargetPort.Location; targetBox = edge.TargetPort.Curve; } LineSegment line = new LineSegment(sourcePoint, targetPoint); IList<IntersectionInfo> intersects = Curve.GetAllIntersections(sourceBox, line, false); if (intersects.Count > 0) { var trimmedLine = (LineSegment)line.Trim(intersects[0].Par1, 1.0); if(trimmedLine != null) { line = trimmedLine; intersects = Curve.GetAllIntersections(targetBox, line, false); if (intersects.Count > 0) { trimmedLine = (LineSegment)line.Trim(0.0, intersects[0].Par1); if(trimmedLine != null) { line = trimmedLine; } } } } return line; }
static internal bool IsVertical(LineSegment seg) { return IsVertical(PointComparer.GetPureDirection(seg.Start, seg.End)); }
private void GetBorderIntersections(Point location, LineSegment lineSeg, ICurve curve , out Point xx0, out Point xx1) { // Important: the LineSegment must be the first arg to GetAllIntersections so RawIntersection works. IList<IntersectionInfo> xxs = Curve.GetAllIntersections(lineSeg, curve, true /*liftIntersections*/); StaticGraphUtility.Assert(2 == xxs.Count, "Expected two intersections", this.ObstacleTree, this.VisGraph); xx0 = SpliceUtility.RawIntersection(xxs[0], location); xx1 = SpliceUtility.RawIntersection(xxs[1], location); }
static internal bool SegmentsIntersect(LineSegment first, LineSegment second, out Point intersect) { return IntervalsIntersect(first.Start, first.End, second.Start, second.End, out intersect); }
string LineSegmentString(LineSegment ls) { return "L " + PointToString(ls.End); }
public Rail CreateRail(Point ep0, Point ep1) { var st = new SymmetricSegment(ep0, ep1); Rail rail; if (RailDictionary.TryGetValue(st, out rail)) { return rail; } var ls = new LineSegment(ep0, ep1); rail = new Rail(ls, ZoomLevel); RailTree.Add(rail.BoundingBox, rail); RailDictionary.Add(st, rail); return rail; }
string LineSegmentString(LineSegment ls, char previousInstruction) { var str= PointToString(ls.End); return previousInstruction == 'L' ? str : "L" + str; }
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 }; }
string LineSegmentString(LineSegment ls) { return "L " + PointToString(ls.End); }
private static void UpdateConnectors(GeometryGraph graph) { foreach (Edge edge in graph.Edges) { BinaryLinkShape linkShape = (BinaryLinkShape)edge.UserData; // need to mark the connector as dirty. this is the easiest way to do this linkShape.ManuallyRouted = !linkShape.ManuallyRouted; linkShape.FixedFrom = VGFixedCode.NotFixed; linkShape.FixedTo = VGFixedCode.NotFixed; // make the labels follow the lines foreach (LineLabelShape lineLabelShape in linkShape.RelativeChildShapes.OfType <LineLabelShape>()) { lineLabelShape.ManuallySized = false; lineLabelShape.ManuallyPlaced = false; } linkShape.EdgePoints.Clear(); // MSAGL deals in line segments; DSL deals in points // with the segments, tne end of one == the beginning of the next, so we can use just the beginning point // of each segment. // But we have to hang on to the end point so that, when we hit the last segment, we can finish off the // set of points if (edge.Curve is LineSegment lineSegment) { // When curve is a single line segment. linkShape.EdgePoints.Add(new EdgePoint(lineSegment.Start.X, lineSegment.Start.Y, VGPointType.Normal)); linkShape.EdgePoints.Add(new EdgePoint(lineSegment.End.X, lineSegment.End.Y, VGPointType.Normal)); } else if (edge.Curve is Curve curve) { //// When curve is a complex segment. EdgePoint lastPoint = null; foreach (ICurve segment in curve.Segments) { switch (segment.GetType().Name) { case "LineSegment": LineSegment line = segment as LineSegment; linkShape.EdgePoints.Add(new EdgePoint(line.Start.X, line.Start.Y, VGPointType.Normal)); lastPoint = new EdgePoint(line.End.X, line.End.Y, VGPointType.Normal); break; case "CubicBezierSegment": CubicBezierSegment bezier = segment as CubicBezierSegment; // there are 4 segments. Store all but the last one linkShape.EdgePoints.Add(new EdgePoint(bezier.B(0).X, bezier.B(0).Y, VGPointType.Normal)); linkShape.EdgePoints.Add(new EdgePoint(bezier.B(1).X, bezier.B(1).Y, VGPointType.Normal)); linkShape.EdgePoints.Add(new EdgePoint(bezier.B(2).X, bezier.B(2).Y, VGPointType.Normal)); lastPoint = new EdgePoint(bezier.B(3).X, bezier.B(3).Y, VGPointType.Normal); break; case "Ellipse": // rather than draw a curved line, we'll bust the curve into 5 parts and draw those as straight lines Ellipse ellipse = segment as Ellipse; double interval = (ellipse.ParEnd - ellipse.ParStart) / 5.0; lastPoint = null; for (double i = ellipse.ParStart; i <= ellipse.ParEnd; i += interval) { Point p = ellipse.Center + (Math.Cos(i) * ellipse.AxisA) + (Math.Sin(i) * ellipse.AxisB); // we'll remember the one we just calculated, but store away the one we calculated last time around // (if there _was_ a last time around). That way, when we're done, we'll have stored all of them except // for the last one if (lastPoint != null) { linkShape.EdgePoints.Add(lastPoint); } lastPoint = new EdgePoint(p.X, p.Y, VGPointType.Normal); } break; } } // finally tuck away the last one. Now we don't have duplicate points in our list if (lastPoint != null) { linkShape.EdgePoints.Add(lastPoint); } } // since we're not changing the nodes this edge connects, this really doesn't do much. // what it DOES do, however, is call ConnectEdgeToNodes, which is an internal method we'd otherwise // be unable to access linkShape.Connect(linkShape.FromShape, linkShape.ToShape); linkShape.ManuallyRouted = false; } }