/// <summary> /// Get the index of line on the edge (u->v) and node u /// </summary> #if SHARPKIT //http://code.google.com/p/sharpkit/issues/detail?id=203 //SharpKit/Colin - Interface implementations public int GetLineIndexInOrder(Station u, Station v, Metroline Metroline) { #else int IMetroMapOrderingAlgorithm.GetLineIndexInOrder(Station u, Station v, Metroline Metroline) { #endif var edge = new PointPair(u.Position, v.Position); var reversed = u.Position != edge.First; var d = bundles[edge].LineIndexInOrder; return(!reversed ? d[Metroline] : d.Count - 1 - d[Metroline]); } /// <summary> /// Do the main job /// </summary> void BuildOrder() { bundles = new Dictionary <PointPair, PointPairOrder>(); //initialization foreach (var Metroline in Metrolines) { for (var p = Metroline.Polyline.StartPoint; p.Next != null; p = p.Next) { var e = new PointPair(p.Point, p.Next.Point); PointPairOrder li; if (!bundles.TryGetValue(e, out li)) { bundles[e] = li = new PointPairOrder(); } li.Add(Metroline); } } foreach (var edge in bundles) { BuildOrder(edge.Key, edge.Value); } } /// <summary> /// Build order for edge (u->v) /// </summary> void BuildOrder(PointPair pair, PointPairOrder order) { if (order.orderFixed) { return; } order.Metrolines.Sort((line0, line1) => CompareLines(line0, line1, pair.First, pair.Second)); //save order order.orderFixed = true; order.LineIndexInOrder = new Dictionary <Metroline, int>(); for (int i = 0; i < order.Metrolines.Count; i++) { order.LineIndexInOrder[order.Metrolines[i]] = i; } } /// <summary> /// Compare two lines on station u with respect to edge (u->v) /// </summary> int CompareLines(Metroline ml0, Metroline ml1, Point u, Point v) { PolylinePoint polylinePoint0; Func <PolylinePoint, PolylinePoint> next0; Func <PolylinePoint, PolylinePoint> prev0; FindStationOnLine(u, v, ml0, out polylinePoint0, out next0, out prev0); PolylinePoint polylinePoint1; Func <PolylinePoint, PolylinePoint> next1; Func <PolylinePoint, PolylinePoint> prev1; FindStationOnLine(u, v, ml1, out polylinePoint1, out next1, out prev1); //go backward var p0 = polylinePoint0; var p1 = polylinePoint1; PolylinePoint p00, p11 = null; while ((p00 = prev0(p0)) != null && (p11 = prev1(p1)) != null && p00.Point == p11.Point) { var edge = new PointPair(p00.Point, p0.Point); if (bundles[edge].orderFixed) { return(CompareOnFixedOrder(edge, ml0, ml1, p00.Point != edge.First)); } p0 = p00; p1 = p11; } if (p00 != null && p11 != null) //we have a backward fork { var forkBase = p0.Point; return(IsLeft(next0(p0).Point - forkBase, p00.Point - forkBase, p11.Point - forkBase)); } //go forward p0 = polylinePoint0; p1 = polylinePoint1; while ((p00 = next0(p0)) != null && (p11 = next1(p1)) != null && p00.Point == p11.Point) { var edge = new PointPair(p00.Point, p0.Point); if (bundles[edge].orderFixed) { return(CompareOnFixedOrder(edge, ml0, ml1, p0.Point != edge.First)); } p0 = p00; p1 = p11; } if (p00 != null && p11 != null) //compare forward fork { var forkBase = p0.Point; return(-IsLeft(prev0(p0).Point - forkBase, p00.Point - forkBase, p11.Point - forkBase)); } //these are multiple edges return(ml0.Index.CompareTo(ml1.Index)); } int CompareOnFixedOrder(PointPair edge, Metroline ml0, Metroline ml1, bool reverse) { var mlToIndex = bundles[edge].LineIndexInOrder; int r = reverse ? -1 : 1; return(r * mlToIndex[ml0].CompareTo(mlToIndex[ml1])); } /// <summary> /// Reimplement it in more efficient way!!! (cache indexes) /// </summary> void FindStationOnLine(Point u, Point v, Metroline Metroline, out PolylinePoint polyPoint, out Func <PolylinePoint, PolylinePoint> next, out Func <PolylinePoint, PolylinePoint> prev) { for (var p = Metroline.Polyline.StartPoint; p.Next != null; p = p.Next) { if (p.Point == u && p.Next.Point == v) { next = Next; prev = Prev; polyPoint = p; return; } if (p.Point == v && p.Next.Point == u) { prev = Next; next = Prev; polyPoint = p.Next; return; } } throw new InvalidOperationException(); }
/// <summary> /// Get the index of line on the edge (u->v) and node u /// </summary> #if SHARPKIT //http://code.google.com/p/sharpkit/issues/detail?id=203 //SharpKit/Colin - Interface implementations public int GetLineIndexInOrder(Station u, Station v, Metroline Metroline) { #else int IMetroMapOrderingAlgorithm.GetLineIndexInOrder(Station u, Station v, Metroline Metroline) { #endif var edge = new PointPair(u.Position, v.Position); var reversed = u.Position != edge.First; var d = bundles[edge].LineIndexInOrder; return !reversed ? d[Metroline] : d.Count - 1 - d[Metroline]; } /// <summary> /// Do the main job /// </summary> void BuildOrder() { bundles = new Dictionary<PointPair, PointPairOrder>(); //initialization foreach (var Metroline in Metrolines) { for (var p = Metroline.Polyline.StartPoint; p.Next != null; p = p.Next) { var e = new PointPair(p.Point, p.Next.Point); PointPairOrder li; if (!bundles.TryGetValue(e, out li)) bundles[e] = li = new PointPairOrder(); li.Add(Metroline); } } foreach (var edge in bundles) BuildOrder(edge.Key, edge.Value); } /// <summary> /// Build order for edge (u->v) /// </summary> void BuildOrder(PointPair pair, PointPairOrder order) { if (order.orderFixed) return; order.Metrolines.Sort((line0, line1) => CompareLines(line0, line1, pair.First, pair.Second)); //save order order.orderFixed = true; order.LineIndexInOrder = new Dictionary<Metroline, int>(); for (int i = 0; i < order.Metrolines.Count; i++) order.LineIndexInOrder[order.Metrolines[i]] = i; } /// <summary> /// Compare two lines on station u with respect to edge (u->v) /// </summary> int CompareLines(Metroline ml0, Metroline ml1, Point u, Point v) { PolylinePoint polylinePoint0; Func<PolylinePoint, PolylinePoint> next0; Func<PolylinePoint, PolylinePoint> prev0; FindStationOnLine(u, v, ml0, out polylinePoint0, out next0, out prev0); PolylinePoint polylinePoint1; Func<PolylinePoint, PolylinePoint> next1; Func<PolylinePoint, PolylinePoint> prev1; FindStationOnLine(u, v, ml1, out polylinePoint1, out next1, out prev1); //go backward var p0 = polylinePoint0; var p1 = polylinePoint1; PolylinePoint p00, p11 = null; while ((p00 = prev0(p0)) != null && (p11 = prev1(p1)) != null && p00.Point == p11.Point) { var edge = new PointPair(p00.Point, p0.Point); if (bundles[edge].orderFixed) { return CompareOnFixedOrder(edge, ml0, ml1, p00.Point !=edge.First); } p0 = p00; p1 = p11; } if (p00 != null && p11 != null) { //we have a backward fork var forkBase = p0.Point; return IsLeft(next0(p0).Point - forkBase, p00.Point - forkBase, p11.Point - forkBase); } //go forward p0 = polylinePoint0; p1 = polylinePoint1; while ((p00 = next0(p0)) != null && (p11 = next1(p1)) != null && p00.Point == p11.Point) { var edge = new PointPair(p00.Point, p0.Point); if (bundles[edge].orderFixed) return CompareOnFixedOrder(edge, ml0, ml1, p0.Point!=edge.First); p0 = p00; p1 = p11; } if (p00 != null && p11 != null) {//compare forward fork var forkBase = p0.Point; return -IsLeft(prev0(p0).Point - forkBase, p00.Point - forkBase, p11.Point - forkBase); } //these are multiple edges return ml0.Index.CompareTo(ml1.Index); } int CompareOnFixedOrder(PointPair edge, Metroline ml0, Metroline ml1, bool reverse) { var mlToIndex = bundles[edge].LineIndexInOrder; int r = reverse ? -1 : 1; return r * mlToIndex[ml0].CompareTo(mlToIndex[ml1]); } /// <summary> /// Reimplement it in more efficient way!!! (cache indexes) /// </summary> void FindStationOnLine(Point u, Point v, Metroline Metroline, out PolylinePoint polyPoint, out Func<PolylinePoint, PolylinePoint> next, out Func<PolylinePoint, PolylinePoint> prev) { for (var p = Metroline.Polyline.StartPoint; p.Next != null; p = p.Next) { if (p.Point == u && p.Next.Point == v) { next = Next; prev = Prev; polyPoint = p; return; } if (p.Point == v && p.Next.Point == u) { prev = Next; next = Prev; polyPoint = p.Next; return; } } throw new InvalidOperationException(); }