bool FitLonger(OrientedHubSegment longerOrientedSeg, Point del0, Point del1, Point midPointOfShorter, double minDelLength, double maxDel, Point center, double radius) { CubicBezierSegment seg = (CubicBezierSegment)longerOrientedSeg.Segment; Point start = seg.Start; Point end = seg.End; // LayoutAlgorithmSettings.ShowDebugCurves(new DebugCurve("green", shorterDebugOnly), new DebugCurve("red", seg)); int steps = 0; const int maxSteps = 10; Point lowP1 = (1 - SqueezeBound) * seg.Start + SqueezeBound * seg.B(1); Point lowP2 = (1 - SqueezeBound) * seg.End + SqueezeBound * seg.B(2); Point highP1 = 2 * seg.B(1) - seg.Start; //originally the tangents were 0.25 of the length of seg[1]-seg[0] - so were are safe to lengthen two times Point highP2 = 2 * seg.B(2) - seg.End; PullControlPointToTheCircle(seg.Start, ref highP1, center, radius); int r = NicelyAligned(seg, del0, del1, midPointOfShorter, minDelLength, maxDel); do { if (r == -1) { //pull the control points lower Point p1 = (seg.B(1) + lowP1) / 2; Point p2 = (seg.B(2) + lowP2) / 2; highP1 = seg.B(1); highP2 = seg.B(2); seg = new CubicBezierSegment(start, p1, p2, end); } else { Debug.Assert(r == 1); //pull the control points higher Point p1 = (seg.B(1) + highP1) / 2; Point p2 = (seg.B(2) + highP2) / 2; lowP1 = seg.B(1); lowP2 = seg.B(2); seg = new CubicBezierSegment(start, p1, p2, end); } if ((r = NicelyAligned(seg, del0, del1, midPointOfShorter, minDelLength, maxDel)) == 0) { longerOrientedSeg.Other.Segment = longerOrientedSeg.Segment = seg; return(true); } if (steps++ > maxSteps) { return(false); //cannot fix it } } while (true); }
/// <summary> /// fans the couple i,i+1 /// </summary> bool FanCouple(BundleBase bundleHub, int i, Point center, double radius) { OrientedHubSegment lSeg = bundleHub.OrientedHubSegments[i]; OrientedHubSegment rSeg = bundleHub.OrientedHubSegments[i + 1]; if (lSeg == null) { return(false); } Point x; if (LineSegment.Intersect(lSeg.Segment.Start, lSeg.Segment.End, rSeg.Segment.Start, rSeg.Segment.End, out x)) { return(false); //it doesn not make sense to push these segs apart } if (Point.GetTriangleOrientation(lSeg[0], lSeg[0.5], lSeg[1]) != Point.GetTriangleOrientation(rSeg[0], rSeg[0.5], rSeg[1])) { return(false); } double ll = BaseLength(lSeg); double rl = BaseLength(rSeg); if (Math.Abs(ll - rl) < ApproximateComparer.IntersectionEpsilon) { return(false); } if (ll > rl) { return(AdjustLongerSeg(lSeg, rSeg, center, radius)); } return(AdjustLongerSeg(rSeg, lSeg, center, radius)); /* * var del0 = lSeg.Start - rSeg.Start; * var del1 = lSeg.End - rSeg.End; * var desiredDelta = Math.Min(del0, del1); * var leftMiddle = lSeg[0.5]; * var rightMiddle = rSeg[0.5]; * if ((leftMiddle - rightMiddle).Length >= desiredDelta - ApproximateComparer.DistanceEpsilon) * return false; * var leftMiddleToCenter = (leftMiddle - BundleHub.Vertex).Length; * var rightMiddleToCenter = (rightMiddle - BundleHub.Vertex).Length; * if (leftMiddleToCenter > rightMiddleToCenter) { * if (MoveSegToDesiredDistance(rightMiddle, lSeg, desiredDelta)) * return true; * } else if (MoveSegToDesiredDistance(leftMiddle, rSeg, desiredDelta)) * return true; * * return false;*/ }
void CreateOrientedSegsOnLineVertex(Metroline line, PolylinePoint polyPoint) { Station u = metroGraphData.PointToStations[polyPoint.Prev.Point]; Station v = metroGraphData.PointToStations[polyPoint.Point]; Station w = metroGraphData.PointToStations[polyPoint.Next.Point]; BundleBase h0 = v.BundleBases[u]; BundleBase h1 = v.BundleBases[w]; int j0 = metroOrdering.GetLineIndexInOrder(u, v, line); int j1 = metroOrdering.GetLineIndexInOrder(w, v, line); OrientedHubSegment or0 = h0.OrientedHubSegments[j0] = new OrientedHubSegment(null, false, j0, h0); OrientedHubSegment or1 = h1.OrientedHubSegments[j1] = new OrientedHubSegment(null, true, j1, h1); or1.Other = or0; or0.Other = or1; }
bool AdjustLongerSeg(OrientedHubSegment longerSeg, OrientedHubSegment shorterSeg, Point center, double radius) { Point del0 = longerSeg[0] - shorterSeg[0]; Point del1 = longerSeg[1] - shorterSeg[1]; double minDelLength = Math.Min(del0.Length, del1.Length); Point midPointOfShorter = shorterSeg[0.5]; double maxDelLen = Math.Max(del0.Length, del1.Length); if (NicelyAligned((CubicBezierSegment)longerSeg.Segment, del0, del1, midPointOfShorter, minDelLength, maxDelLen) == 0) { return(false); } return(FitLonger(longerSeg, del0, del1, midPointOfShorter, minDelLength, maxDelLen, center, radius)); }
double BaseLength(OrientedHubSegment seg) { return (seg[0] - seg[1]).LengthSquared; }
bool FitLonger(OrientedHubSegment longerOrientedSeg, Point del0, Point del1, Point midPointOfShorter, double minDelLength, double maxDel, Point center, double radius) { CubicBezierSegment seg = (CubicBezierSegment)longerOrientedSeg.Segment; Point start = seg.Start; Point end = seg.End; // LayoutAlgorithmSettings.ShowDebugCurves(new DebugCurve("green", shorterDebugOnly), new DebugCurve("red", seg)); int steps = 0; const int maxSteps = 10; Point lowP1 = (1 - SqueezeBound) * seg.Start + SqueezeBound * seg.B(1); Point lowP2 = (1 - SqueezeBound) * seg.End + SqueezeBound * seg.B(2); Point highP1 = 2 * seg.B(1) - seg.Start; //originally the tangents were 0.25 of the length of seg[1]-seg[0] - so were are safe to lengthen two times Point highP2 = 2 * seg.B(2) - seg.End; PullControlPointToTheCircle(seg.Start, ref highP1, center, radius); int r = NicelyAligned(seg, del0, del1, midPointOfShorter, minDelLength, maxDel); do { if (r == -1) { //pull the control points lower Point p1 = (seg.B(1) + lowP1) / 2; Point p2 = (seg.B(2) + lowP2) / 2; highP1 = seg.B(1); highP2 = seg.B(2); seg = new CubicBezierSegment(start, p1, p2, end); } else { Debug.Assert(r == 1); //pull the control points higher Point p1 = (seg.B(1) + highP1) / 2; Point p2 = (seg.B(2) + highP2) / 2; lowP1 = seg.B(1); lowP2 = seg.B(2); seg = new CubicBezierSegment(start, p1, p2, end); } if ((r = NicelyAligned(seg, del0, del1, midPointOfShorter, minDelLength, maxDel)) == 0) { longerOrientedSeg.Other.Segment = longerOrientedSeg.Segment = seg; return true; } if (steps++ > maxSteps) return false; //cannot fix it } while (true); }
bool AdjustLongerSeg(OrientedHubSegment longerSeg, OrientedHubSegment shorterSeg, Point center, double radius) { Point del0 = longerSeg[0] - shorterSeg[0]; Point del1 = longerSeg[1] - shorterSeg[1]; double minDelLength = Math.Min(del0.Length, del1.Length); Point midPointOfShorter = shorterSeg[0.5]; double maxDelLen = Math.Max(del0.Length, del1.Length); if (NicelyAligned((CubicBezierSegment)longerSeg.Segment, del0, del1, midPointOfShorter, minDelLength, maxDelLen) == 0) return false; return FitLonger(longerSeg, del0, del1, midPointOfShorter, minDelLength, maxDelLen, center, radius); }
double BaseLength(OrientedHubSegment seg) { return((seg[0] - seg[1]).LengthSquared); }