Beispiel #1
0
 internal OrientedHubSegment(ICurve seg, bool reversed, int index, BundleBase bundleBase)
 {
     Segment    = seg;
     Reversed   = reversed;
     Index      = index;
     BundleBase = bundleBase;
 }
Beispiel #2
0
        double GetAssymetryCostForBase(BundleBase bundleBase)
        {
            if (bundleBase.BelongsToRealNode)
            {
                return(0);
            }

            double assymetryWeight = bundleBase.OppositeBase.BelongsToRealNode ? 200 : 500;
            double cost            = 0;

            foreach (var o in bundleBase.OrientedHubSegments)
            {
                int i0 = o.Index;
                int i1 = o.Other.Index;

                var a  = bundleBase.Points[i0];
                var ta = bundleBase.Tangents[i0];

                var oppositeBase = o.Other.BundleBase;
                var b            = oppositeBase.Points[i1];
                var tb           = oppositeBase.Tangents[i1];

                double s = bundleBase.Count + oppositeBase.Count;
                cost += GetAssymetryCostOnData(a, ta, b, tb, assymetryWeight) / s;
            }

            return(cost);
        }
Beispiel #3
0
        double SeparationCostForBundleBase(BundleBase bBase)
        {
            if (bBase.Prev == null)
            {
                return(0);
            }

            return(SeparationCostForAdjacentBundleBases(bBase, bBase.Prev) + SeparationCostForAdjacentBundleBases(bBase, bBase.Next));
        }
Beispiel #4
0
        static Point FindCurveEnd(MetroGraphData metroGraphData, IMetroMapOrderingAlgorithm metroOrdering, Metroline metroline)
        {
            Station u = metroGraphData.PointToStations[metroline.Polyline.EndPoint.Prev.Point];
            Station v = metroGraphData.PointToStations[metroline.Polyline.EndPoint.Point];

            BundleBase bb    = v.BundleBases[u];
            int        index = (!bb.IsParent ? metroOrdering.GetLineIndexInOrder(u, v, metroline) : metroOrdering.GetLineIndexInOrder(v, u, metroline));

            return(bb.Points[index]);
        }
Beispiel #5
0
        bool FanEdgesOfHubSegment(BundleBase bundleHub)
        {
            bool ret = false;

            for (int i = 0; i < bundleHub.Count - 1; i++)
            {
                ret |= FanCouple(bundleHub, i, bundleHub.CurveCenter, bundleHub.Curve.BoundingBox.Diagonal / 2);
            }
            return(ret);
        }
Beispiel #6
0
        void AllocateBundleBases()
        {
            externalBases = new Dictionary <ICurve, List <BundleBase> >();
            internalBases = new Dictionary <ICurve, List <BundleBase> >();
            Bundles       = new List <BundleInfo>();

            foreach (var station in metroGraphData.Stations)
            {
                if (station.BoundaryCurve == null)
                {
                    station.BoundaryCurve = new Ellipse(station.Radius, station.Radius, station.Position);
                }
            }

            foreach (var station in metroGraphData.Stations)
            {
                foreach (Station neighbor in station.Neighbors)
                {
                    if (station < neighbor)
                    {
                        var bb = new BundleBase(metroGraphData.RealEdgeCount(station, neighbor), station.BoundaryCurve, station.Position, station.IsRealNode, neighbor.SerialNumber);
                        station.BundleBases[neighbor] = bb;

                        var bb2 = new BundleBase(metroGraphData.RealEdgeCount(station, neighbor), neighbor.BoundaryCurve, neighbor.Position, neighbor.IsRealNode, station.SerialNumber);
                        neighbor.BundleBases[station] = bb2;

                        if (Curve.PointRelativeToCurveLocation(neighbor.Position, station.BoundaryCurve) != PointLocation.Outside)
                        {
                            bb.IsParent = true;
                            CollectionUtilities.AddToMap(internalBases, station.BoundaryCurve, bb);
                            CollectionUtilities.AddToMap(externalBases, neighbor.BoundaryCurve, bb2);
                        }
                        else if (Curve.PointRelativeToCurveLocation(station.Position, neighbor.BoundaryCurve) != PointLocation.Outside)
                        {
                            bb2.IsParent = true;
                            CollectionUtilities.AddToMap(externalBases, station.BoundaryCurve, bb);
                            CollectionUtilities.AddToMap(internalBases, neighbor.BoundaryCurve, bb2);
                        }
                        else
                        {
                            CollectionUtilities.AddToMap(externalBases, station.BoundaryCurve, bb);
                            CollectionUtilities.AddToMap(externalBases, neighbor.BoundaryCurve, bb2);
                        }

                        Set <Polyline> obstaclesToIgnore = metroGraphData.tightIntersections.ObstaclesToIgnoreForBundle(station, neighbor);
                        var            bundle            = new BundleInfo(bb, bb2, obstaclesToIgnore, bundlingSettings.EdgeSeparation, metroOrdering.GetOrder(station, neighbor).Select(l => l.Width / 2).ToArray());
                        bb.OutgoingBundleInfo = bb2.IncomingBundleInfo = bundle;
                        Bundles.Add(bundle);
                    }
                }
            }

            //neighbors
            SetBundleBaseNeighbors();
        }
Beispiel #7
0
        double SeparationCostForAdjacentBundleBases(BundleBase base0, BundleBase base1)
        {
            Debug.Assert(base0.Curve == base1.Curve);

            ICurve boundaryCurve = base0.Curve;
            double len           = IntervalsOverlapLength(base0.ParRight, base0.ParLeft, base1.ParRight, base1.ParLeft, boundaryCurve);
            double mn            = Math.Min(base0.Span, base1.Span);

            Debug.Assert(ApproximateComparer.LessOrEqual(len, mn));
            Debug.Assert(mn > 0);
            return(Math.Exp(len / mn * 10) - 1);
        }
Beispiel #8
0
        /// <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;*/
        }
Beispiel #9
0
        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;
        }
Beispiel #10
0
        void UpdatePointsOnBundleBase(BundleBase bb)
        {
            int count = bb.Count;

            Point[] pns   = bb.Points;
            var     ls    = new LineSegment(bb.LeftPoint, bb.RightPoint);
            var     scale = 1 / TotalRequiredWidth;
            var     t     = HalfWidthArray[0];

            pns[0] = ls[t * scale];
            for (int i = 1; i < count; i++)
            {
                t     += HalfWidthArray[i - 1] + EdgeSeparation + HalfWidthArray[i];
                pns[i] = ls[t * scale];
            }
        }
Beispiel #11
0
        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);
            var        seg = bundlingSettings.UseCubicBezierSegmentsInsideOfHubs ?
                             StandardBezier(h0.Points[j0], h0.Tangents[j0], h1.Points[j1], h1.Tangents[j1]) :
                             BiArc(h0.Points[j0], h0.Tangents[j0], h1.Points[j1], h1.Tangents[j1]);

            h0.OrientedHubSegments[j0].Segment = seg;
            h1.OrientedHubSegments[j1].Segment = seg;
        }
Beispiel #12
0
        static ICurve SegOnLineVertex(MetroGraphData metroGraphData, IMetroMapOrderingAlgorithm metroOrdering, Metroline line, PolylinePoint i)
        {
            Station    u  = metroGraphData.PointToStations[i.Prev.Point];
            Station    v  = metroGraphData.PointToStations[i.Point];
            BundleBase h0 = v.BundleBases[u];
            int        j0 = metroOrdering.GetLineIndexInOrder(u, v, line);

            if (h0.OrientedHubSegments[j0] == null || h0.OrientedHubSegments[j0].Segment == null)
            {
                var w         = metroGraphData.PointToStations[i.Next.Point];
                var otherBase = v.BundleBases[w];
                var j1        = metroOrdering.GetLineIndexInOrder(w, v, line);
                return(new LineSegment(h0.Points[j0], otherBase.Points[j1]));
            }

            return(h0.OrientedHubSegments[j0].Segment);
        }
        void AllocateBundleBases() {
            externalBases = new Dictionary<ICurve, List<BundleBase>>();
            internalBases = new Dictionary<ICurve, List<BundleBase>>();
            Bundles = new List<BundleInfo>();

            foreach (var station in metroGraphData.Stations) {
                if (station.BoundaryCurve == null)
                    station.BoundaryCurve = new Ellipse(station.Radius, station.Radius, station.Position);
            }

            foreach (var station in metroGraphData.Stations) {
                foreach (Station neighbor in station.Neighbors) {
                    if (station < neighbor) {
                        var bb = new BundleBase(metroGraphData.RealEdgeCount(station, neighbor), station.BoundaryCurve, station.Position, station.IsRealNode, neighbor.SerialNumber);
                        station.BundleBases[neighbor] = bb;

                        var bb2 = new BundleBase(metroGraphData.RealEdgeCount(station, neighbor), neighbor.BoundaryCurve, neighbor.Position, neighbor.IsRealNode, station.SerialNumber);
                        neighbor.BundleBases[station] = bb2;

                        if (Curve.PointRelativeToCurveLocation(neighbor.Position, station.BoundaryCurve) != PointLocation.Outside) {
                            bb.IsParent = true;
                            CollectionUtilities.AddToMap(internalBases, station.BoundaryCurve, bb);
                            CollectionUtilities.AddToMap(externalBases, neighbor.BoundaryCurve, bb2);
                        }
                        else if (Curve.PointRelativeToCurveLocation(station.Position, neighbor.BoundaryCurve) != PointLocation.Outside) {
                            bb2.IsParent = true;
                            CollectionUtilities.AddToMap(externalBases, station.BoundaryCurve, bb);
                            CollectionUtilities.AddToMap(internalBases, neighbor.BoundaryCurve, bb2);
                        }
                        else {
                            CollectionUtilities.AddToMap(externalBases, station.BoundaryCurve, bb);
                            CollectionUtilities.AddToMap(externalBases, neighbor.BoundaryCurve, bb2);
                        }

                        Set<Polyline> obstaclesToIgnore = metroGraphData.tightIntersections.ObstaclesToIgnoreForBundle(station, neighbor);
                        var bundle = new BundleInfo(bb, bb2, obstaclesToIgnore, bundlingSettings.EdgeSeparation, metroOrdering.GetOrder(station, neighbor).Select(l => l.Width / 2).ToArray());
                        bb.OutgoingBundleInfo = bb2.IncomingBundleInfo = bundle;
                        Bundles.Add(bundle);
                    }

                }
            }

            //neighbors
            SetBundleBaseNeighbors();
        }
Beispiel #14
0
        void AdjustCurrentBundleWidthsOnCurve(List <BundleBase> bases)
        {
            int count = bases.Count;

            if (count <= 1)
            {
                return;
            }

            for (int i = 0; i < count; i++)
            {
                BundleBase rBase = bases[i];
                BundleBase lBase = rBase.Next;

                ShrinkBasesToMakeTwoConsecutiveNeighborsHappy(rBase, lBase);
                Debug.Assert(!rBase.Intersect(lBase));
            }
        }
        internal BundleInfo(BundleBase sourceBase, BundleBase targetBase, Set<Polyline> obstaclesToIgnore, double edgeSeparation, double[] halfWidthArray) {
            SourceBase = sourceBase;
            TargetBase = targetBase;
            this.obstaclesToIgnore = obstaclesToIgnore;
            EdgeSeparation = edgeSeparation;
            HalfWidthArray = halfWidthArray;
            TotalRequiredWidth = EdgeSeparation * HalfWidthArray.Length + HalfWidthArray.Sum() * 2;
            longEnoughSideLength = new Rectangle(sourceBase.Curve.BoundingBox, targetBase.Curve.BoundingBox).Diagonal;

            //sometimes TotalRequiredWidth is too large to fit into the circle, so we evenly scale everything
            double mn = Math.Max(sourceBase.Curve.BoundingBox.Diagonal, targetBase.Curve.BoundingBox.Diagonal);
            if (TotalRequiredWidth > mn) {
                double scale = TotalRequiredWidth / mn;
                for (int i = 0; i < HalfWidthArray.Length; i++)
                    HalfWidthArray[i] /= scale;
                TotalRequiredWidth /= scale;
                EdgeSeparation /= scale;
            }
        }
Beispiel #16
0
        double CenterCost(BundleBase bundleBase)
        {
            if (!bundleBase.BelongsToRealNode)
            {
                return(0);
            }

            double currentMid = bundleBase.ParMid;
            double mn         = Math.Min(bundleBase.InitialMidParameter, currentMid);
            double mx         = Math.Max(bundleBase.InitialMidParameter, currentMid);
            double dist       = Math.Min(mx - mn, mn + bundleBase.ParameterSpan - mx);

            if (bundleBase.CurveCenter == bundleBase.Position || bundleBase.IsParent)
            {
                return(25 * dist * dist);
            }
            else
            {
                return(500 * dist * dist);
            }
        }
Beispiel #17
0
        double GetBaseMiddleParamInDirection(BundleBase targetBase, Point sPos, Point neighbPos)
        {
            var curve  = targetBase.Curve;
            var circle = curve as Ellipse;

            if (circle != null && circle.IsArc())
            {
                return(Point.Angle(circle.AxisA, neighbPos - sPos));
            }

            var intersections = Curve.GetAllIntersections(curve, new LineSegment(sPos, neighbPos), true);

            foreach (var intersectionInfo in intersections)
            {
                var xP = intersectionInfo.IntersectionPoint;
                if ((xP - sPos) * (xP - neighbPos) <= 0)
                {
                    return(intersectionInfo.Par0);
                }
            }

            throw new InvalidOperationException();
        }
        internal BundleInfo(BundleBase sourceBase, BundleBase targetBase, Set <Polyline> obstaclesToIgnore, double edgeSeparation, double[] halfWidthArray)
        {
            SourceBase             = sourceBase;
            TargetBase             = targetBase;
            this.obstaclesToIgnore = obstaclesToIgnore;
            EdgeSeparation         = edgeSeparation;
            HalfWidthArray         = halfWidthArray;
            TotalRequiredWidth     = EdgeSeparation * HalfWidthArray.Length + HalfWidthArray.Sum() * 2;
            longEnoughSideLength   = new Rectangle(sourceBase.Curve.BoundingBox, targetBase.Curve.BoundingBox).Diagonal;

            //sometimes TotalRequiredWidth is too large to fit into the circle, so we evenly scale everything
            double mn = Math.Max(sourceBase.Curve.BoundingBox.Diagonal, targetBase.Curve.BoundingBox.Diagonal);

            if (TotalRequiredWidth > mn)
            {
                double scale = TotalRequiredWidth / mn;
                for (int i = 0; i < HalfWidthArray.Length; i++)
                {
                    HalfWidthArray[i] /= scale;
                }
                TotalRequiredWidth /= scale;
                EdgeSeparation     /= scale;
            }
        }
Beispiel #19
0
 internal bool Intersect(BundleBase other)
 {
     return(Intersect(parRight, parLeft, other.parRight, other.parLeft));
 }
        double SeparationCostForAdjacentBundleBases(BundleBase base0, BundleBase base1) {
            Debug.Assert(base0.Curve == base1.Curve);

            ICurve boundaryCurve = base0.Curve;
            double len = IntervalsOverlapLength(base0.ParRight, base0.ParLeft, base1.ParRight, base1.ParLeft, boundaryCurve);
            double mn = Math.Min(base0.Span, base1.Span);
            Debug.Assert(ApproximateComparer.LessOrEqual(len, mn));
            Debug.Assert(mn > 0);
            return Math.Exp(len / mn * 10) - 1;
        }
 bool FanEdgesOfHubSegment(BundleBase bundleHub) {
     bool ret = false;
     for (int i = 0; i < bundleHub.Count - 1; i++)
         ret |= FanCouple(bundleHub, i, bundleHub.CurveCenter, bundleHub.Curve.BoundingBox.Diagonal / 2);
     return ret;
 }
        double GetAssymetryCostForBase(BundleBase bundleBase) {
            if (bundleBase.BelongsToRealNode)
                return 0;

            double assymetryWeight = bundleBase.OppositeBase.BelongsToRealNode ? 200 : 500;
            double cost = 0;
            foreach (var o in bundleBase.OrientedHubSegments) {
                int i0 = o.Index;
                int i1 = o.Other.Index;

                var a = bundleBase.Points[i0];
                var ta = bundleBase.Tangents[i0];

                var oppositeBase = o.Other.BundleBase;
                var b = oppositeBase.Points[i1];
                var tb = oppositeBase.Tangents[i1];

                double s = bundleBase.Count + oppositeBase.Count;
                cost += GetAssymetryCostOnData(a, ta, b, tb, assymetryWeight) / s;
            }

            return cost;
        }
        double SeparationCostForBundleBase(BundleBase bBase) {
            if (bBase.Prev == null)
                return 0;

            return SeparationCostForAdjacentBundleBases(bBase, bBase.Prev) + SeparationCostForAdjacentBundleBases(bBase, bBase.Next);
        }
        double CenterCost(BundleBase bundleBase) {
            if (!bundleBase.BelongsToRealNode)
                return 0;

            double currentMid = bundleBase.ParMid;
            double mn = Math.Min(bundleBase.InitialMidParameter, currentMid);
            double mx = Math.Max(bundleBase.InitialMidParameter, currentMid);
            double dist = Math.Min(mx - mn, mn + bundleBase.ParameterSpan - mx);
            if (bundleBase.CurveCenter == bundleBase.Position || bundleBase.IsParent)
                return 25 * dist * dist;
            else
                return 500 * dist * dist;
        }
        void ShrinkBasesToMakeTwoConsecutiveNeighborsHappy(BundleBase rBase, BundleBase lBase) {
            if (!rBase.Intersect(lBase))
                return;

            //segments are now [l1..r1] and [l2..r2]
            double l1 = rBase.ParRight;
            double r1 = rBase.ParLeft;
            double l2 = lBase.ParRight;
            double r2 = lBase.ParLeft;

            double span = lBase.ParameterSpan;

            //make them regular
            if (l1 > r1)
                l1 -= span;
            if (l2 > r2)
                l2 -= span;

            //make them intersecting
            if (l2 > r1) {
                l2 -= span;
                r2 -= span;
            }

            if (l1 > r2) {
                l1 -= span;
                r1 -= span;
            }

            //they do intersect!
            Debug.Assert(!(l2 >= r1) && !(l1 >= r2));

            double t = RegularCut(l1, r1, l2, r2, rBase.Span, lBase.Span);
            TriangleOrientation to = Point.GetTriangleOrientation(lBase.CurveCenter, lBase.OppositeBase.InitialMidPoint, rBase.OppositeBase.InitialMidPoint);

            if (to == TriangleOrientation.Clockwise) {
                r1 = t;
                l2 = t;
            }
            else if (to == TriangleOrientation.Counterclockwise) {
                r2 = t;
                l1 = t;
            }
            else {
                if (r2 - l1 >= r1 - l2) {
                    r1 = t;
                    l2 = t;
                }
                else {
                    r2 = t;
                    l1 = t;
                }
            }

            Debug.Assert(!rBase.Intersect(l1, r1, l2, r2));

            lBase.ParRight = lBase.AdjustParam(l2);
            lBase.ParLeft = lBase.AdjustParam(r2);
            rBase.ParRight = rBase.AdjustParam(l1);
            rBase.ParLeft = rBase.AdjustParam(r1);
        }
        double GetBaseMiddleParamInDirection(BundleBase targetBase, Point sPos, Point neighbPos) {
            var curve = targetBase.Curve;
            var circle = curve as Ellipse;
            if (circle != null && circle.IsArc())
                return Point.Angle(circle.AxisA, neighbPos - sPos);

            var intersections = Curve.GetAllIntersections(curve, new LineSegment(sPos, neighbPos), true);
            foreach (var intersectionInfo in intersections) {
                var xP = intersectionInfo.IntersectionPoint;
                if ((xP - sPos) * (xP - neighbPos) <= 0) {
                    return intersectionInfo.Par0;
                }
            }

            throw new InvalidOperationException();
        }
Beispiel #27
0
        void ShrinkBasesToMakeTwoConsecutiveNeighborsHappy(BundleBase rBase, BundleBase lBase)
        {
            if (!rBase.Intersect(lBase))
            {
                return;
            }

            //segments are now [l1..r1] and [l2..r2]
            double l1 = rBase.ParRight;
            double r1 = rBase.ParLeft;
            double l2 = lBase.ParRight;
            double r2 = lBase.ParLeft;

            double span = lBase.ParameterSpan;

            //make them regular
            if (l1 > r1)
            {
                l1 -= span;
            }
            if (l2 > r2)
            {
                l2 -= span;
            }

            //make them intersecting
            if (l2 > r1)
            {
                l2 -= span;
                r2 -= span;
            }

            if (l1 > r2)
            {
                l1 -= span;
                r1 -= span;
            }

            //they do intersect!
            Debug.Assert(!(l2 >= r1) && !(l1 >= r2));

            double t = RegularCut(l1, r1, l2, r2, rBase.Span, lBase.Span);
            TriangleOrientation to = Point.GetTriangleOrientation(lBase.CurveCenter, lBase.OppositeBase.InitialMidPoint, rBase.OppositeBase.InitialMidPoint);

            if (to == TriangleOrientation.Clockwise)
            {
                r1 = t;
                l2 = t;
            }
            else if (to == TriangleOrientation.Counterclockwise)
            {
                r2 = t;
                l1 = t;
            }
            else
            {
                if (r2 - l1 >= r1 - l2)
                {
                    r1 = t;
                    l2 = t;
                }
                else
                {
                    r2 = t;
                    l1 = t;
                }
            }

            Debug.Assert(!rBase.Intersect(l1, r1, l2, r2));

            lBase.ParRight = lBase.AdjustParam(l2);
            lBase.ParLeft  = lBase.AdjustParam(r2);
            rBase.ParRight = rBase.AdjustParam(l1);
            rBase.ParLeft  = rBase.AdjustParam(r1);
        }
 internal OrientedHubSegment(ICurve seg, bool reversed, int index, BundleBase bundleBase) {
     Segment = seg;
     Reversed = reversed;
     Index = index;
     BundleBase = bundleBase;
 }
        /// <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;*/
        }
 internal bool Intersect(BundleBase other) {
     return Intersect(parRight, parLeft, other.parRight, other.parLeft);
 }