private INetworkCoverage GetRenderedCoverage(INetworkCoverage networkCoverage) { if (networkCoverage.IsTimeDependent) { if (TimeSelectionStart == null) { SetCurrentTimeSelection(networkCoverage.Time.Values.FirstOrDefault(), null); } //is it already filtered..update the time if (networkCoverage.Filters.Any(f => f.Variable is Variable <DateTime>) || networkCoverage.Parent != null) { var currentTimeFilter = networkCoverage.Filters .OfType <IVariableValueFilter>().FirstOrDefault(f => f.Variable is Variable <DateTime>); //update the time filter and we're done currentTimeFilter.Values[0] = TimeSelectionStart; return(networkCoverage); } //create a filtered version return((INetworkCoverage)networkCoverage.FilterTime(TimeSelectionStart.Value)); } return(networkCoverage); }
private INetworkCoverage GetRenderedCoverage(INetworkCoverage networkCoverage) { if (networkCoverage.IsTimeDependent) { //use current time or some other time. var timeToSet = CurrentTime ?? DateTime.MinValue; //is it already filtered..update the time if (networkCoverage.Filters.Any(f => f.Variable is Variable<DateTime>) || networkCoverage.Parent != null) { var currentTimeFilter = networkCoverage.Filters .OfType<IVariableValueFilter>() .Where(f => f.Variable is Variable<DateTime>) .FirstOrDefault(); //update the time filter and we're done currentTimeFilter.Values[0] = timeToSet; return networkCoverage; } //create a filtered version return (INetworkCoverage)networkCoverage.FilterTime(timeToSet); } return networkCoverage; }
public static void Operate(this INetworkCoverage coverageA, INetworkCoverage coverageB, Func <double, double, double> operation) { var allLocations = GetAllLocations(coverageA, coverageB); if (coverageA.IsTimeDependent && coverageB.IsTimeDependent) { ThrowIfCoverageTimeValuesNotEqual(coverageA, coverageB); foreach (var time in coverageA.Time.Values) { OperateOneTimestep(coverageA.AddTimeFilter(time), coverageB.AddTimeFilter(time), allLocations, operation); } return; } if (coverageA.IsTimeDependent) { foreach (var time in coverageA.Time.Values) { OperateOneTimestep(coverageA.AddTimeFilter(time), coverageB, allLocations, operation); } return; } if (coverageB.IsTimeDependent) { foreach (var time in coverageB.Time.Values) { OperateOneTimestep(coverageA, coverageB.AddTimeFilter(time), allLocations, operation); } return; } OperateOneTimestep(coverageA, coverageB, allLocations, operation); }
private INetworkCoverage GetRenderedCoverage(INetworkCoverage networkCoverage) { if (networkCoverage.IsTimeDependent) { if(TimeSelectionStart == null) { SetCurrentTimeSelection(networkCoverage.Time.Values.FirstOrDefault(), null); } //is it already filtered..update the time if (networkCoverage.Filters.Any(f => f.Variable is Variable<DateTime>) || networkCoverage.Parent != null) { var currentTimeFilter = networkCoverage.Filters .OfType<IVariableValueFilter>().FirstOrDefault(f => f.Variable is Variable<DateTime>); //update the time filter and we're done currentTimeFilter.Values[0] = TimeSelectionStart; return networkCoverage; } //create a filtered version return (INetworkCoverage)networkCoverage.FilterTime(TimeSelectionStart.Value); } return networkCoverage; }
private static INetworkLocation FindNodePoint(INode node, INetworkCoverage coverage) { var incommingBranchPoints = coverage.Locations.Values.Where(l => Math.Abs(l.Chainage - l.Branch.Length) < BranchFeature.Epsilon && node.IncomingBranches.Contains(l.Branch)); var outGoingBranchPoints = coverage.Locations.Values.Where(l => Math.Abs(l.Chainage) < BranchFeature.Epsilon && node.OutgoingBranches.Contains(l.Branch)); return(incommingBranchPoints.Concat(outGoingBranchPoints).FirstOrDefault()); }
private static INetworkLocation FindNodePoint(INode node, INetworkCoverage coverage) { var incommingBranchPoints = coverage.Locations.Values.Where(l => l.Offset == l.Branch.Length && node.IncomingBranches.Contains(l.Branch)); var outGoingBranchPoints = coverage.Locations.Values.Where(l => l.Offset == 0 && node.OutgoingBranches.Contains(l.Branch)); return(incommingBranchPoints.Concat(outGoingBranchPoints).FirstOrDefault()); }
/// <summary> /// Updates the segments for all branches with branchlocation following this scheme: /// b1 /// n1---------------------------------n2 /// /// A----------C---------B----------D-- - network locations /// - segments /// </summary> /// <param name="coverage"></param> /// <param name="fullyCover"></param> /// when set to true the segment of the branch private static void UpdateSegmentsSegmentBetweenLocations(INetworkCoverage coverage, bool fullyCover) { coverage.Segments.Values.Clear(); //var coverageLocations = coverage.Locations.Values.OrderBy(l => l.Offset).OrderBy(l => l.Branch); //sorting is done in coverage locations..don't need to do it here. This supports for reversed segments. var coverageLocations = coverage.Locations.Values; IBranch branch = null; INetworkLocation previous = null; IList<INetworkLocation> branchLocations = new List<INetworkLocation>(); foreach (var location in coverageLocations) { if ((null != previous) && (previous.Branch != location.Branch)) { IEnumerable<INetworkSegment> segments = UpdateSegmentsBranchSegmentBetweenLocations(fullyCover, branch, branchLocations); foreach (var segment in segments) { coverage.Segments.Values.Add(segment); } branchLocations.Clear(); } branchLocations.Add(location); branch = location.Branch; previous = location; } if (branchLocations.Count > 0) { IEnumerable<INetworkSegment> segments = UpdateSegmentsBranchSegmentBetweenLocations(fullyCover, branch, branchLocations); foreach (var segment in segments) { coverage.Segments.Values.Add(segment); } } }
/// <summary> /// Updates the segments for all branches with branchlocation following this scheme: /// b1 /// n1---------------------------------n2 /// /// A----------C---------B----------D-- - network locations /// - segments /// </summary> /// <param name="coverage"></param> /// <param name="fullyCover"></param> /// when set to true the segment of the branch private static void UpdateSegmentsSegmentBetweenLocations(INetworkCoverage coverage, bool fullyCover) { coverage.Segments.Values.Clear(); //var coverageLocations = coverage.Locations.Values.OrderBy(l => l.Offset).OrderBy(l => l.Branch); //sorting is done in coverage locations..don't need to do it here. This supports for reversed segments. var coverageLocations = coverage.Locations.Values; IBranch branch = null; INetworkLocation previous = null; IList <INetworkLocation> branchLocations = new List <INetworkLocation>(); foreach (var location in coverageLocations) { if ((null != previous) && (previous.Branch != location.Branch)) { IEnumerable <INetworkSegment> segments = UpdateSegmentsBranchSegmentBetweenLocations(fullyCover, branch, branchLocations); foreach (var segment in segments) { coverage.Segments.Values.Add(segment); } branchLocations.Clear(); } branchLocations.Add(location); branch = location.Branch; previous = location; } if (branchLocations.Count > 0) { IEnumerable <INetworkSegment> segments = UpdateSegmentsBranchSegmentBetweenLocations(fullyCover, branch, branchLocations); foreach (var segment in segments) { coverage.Segments.Values.Add(segment); } } }
/// <summary> /// Returns the NetworkLocations for segment in the source coverage. If the start and/or end location of the /// segment are not in the source they are added. /// </summary> /// <param name="segment"></param> /// <param name="source"></param> /// <param name="addNewLocations">Should the end and start of the segment be returned?</param> /// <returns></returns> public static IEnumerable<INetworkLocation> GetLocationsForSegment(INetworkSegment segment, INetworkCoverage source, bool addNewLocations) { double min = Math.Min(segment.EndChainage, segment.Chainage); double max = Math.Max(segment.EndChainage, segment.Chainage); IList<INetworkLocation> locations = new List<INetworkLocation>(); if (addNewLocations) { var startChainage = segment.DirectionIsPositive ? segment.Chainage : segment.EndChainage; locations.Add(new NetworkLocation(segment.Branch, startChainage)); } //need a cast here ..but we are sure since we just built it. foreach (var location in source.Locations.Values.Where( nl => nl.Branch == segment.Branch && nl.Chainage >= min && nl.Chainage <= max)) { if (!locations.Contains(location)) { locations.Add(location); } } if (addNewLocations) { var endChainage = segment.DirectionIsPositive ? segment.EndChainage : segment.Chainage; var location = new NetworkLocation(segment.Branch, endChainage); if (!locations.Contains(location)) { locations.Add(location); } } return !segment.DirectionIsPositive ? locations.Reverse() : locations; }
private static void ThrowIfCoverageTimeValuesNotEqual(INetworkCoverage coverage, IEnumerable <INetworkCoverage> otherCoverages) { foreach (var networkCoverage in otherCoverages) { ThrowIfCoverageTimeValuesNotEqual(coverage, networkCoverage); } }
private static DateTime CalculateDateTimeTransition(INetworkCoverage coverage, double referenceValue, INetworkLocation location, DateTime dateTimePrevious, DateTime dateTimeCurrent, InterpolationType timeInterpolation) { var dateTimeIndex = coverage.Time.Values.IndexOf(dateTimeCurrent); if (dateTimeIndex == 0) { return(dateTimeCurrent); } TimeSpan timeSpan; switch (timeInterpolation) { case InterpolationType.None: return(dateTimeCurrent); case InterpolationType.Constant: // Constant interpolation: value changes in the middle of 'dateTime' and 'dateTimePrevious' timeSpan = dateTimeCurrent - dateTimePrevious; return(dateTimePrevious + new TimeSpan(timeSpan.Ticks / 2)); case InterpolationType.Linear: var currentValue = (double)coverage[dateTimeCurrent, location]; var previousValue = (double)coverage[dateTimePrevious, location]; timeSpan = dateTimeCurrent - dateTimePrevious; return(dateTimePrevious + new TimeSpan(Convert.ToInt64(timeSpan.Ticks * Math.Abs(previousValue - referenceValue) / Math.Abs(currentValue - previousValue)))); default: throw new NotImplementedException(String.Format("Interpolation method {0} not supported", coverage.Time.InterpolationType)); } }
/// <summary> /// Snaps the points to the network coverage, given the tolerance. Existing locations/values will be cleared only /// when there are new points mapped to that branch. /// </summary> /// <param name="pointValuePairs"></param> /// <param name="networkCoverage"></param> /// <param name="tolerance"></param> public static void SnapToCoverage(IEnumerable <Tuple <IPoint, double> > pointValuePairs, INetworkCoverage networkCoverage, double tolerance) { var tree = new Quadtree <IBranch>(); networkCoverage.Network.Branches.ForEach(b => tree.Insert(b.Geometry.EnvelopeInternal, b)); // match points to branch buffers var locations = new List <Tuple <INetworkLocation, double> >(); foreach (var pointValue in pointValuePairs) { var envelope = pointValue.Item1.EnvelopeInternal; envelope.ExpandBy(tolerance); var branches = tree.Query(envelope).Cast <IBranch>(); var location = MapPointToClosestBranch(pointValue.Item1, branches, tolerance); if (location != null) { locations.Add(new Tuple <INetworkLocation, double>(location, pointValue.Item2)); } } // remove values for all branches that have new values imported var branchesToClear = locations.Select(l => l.Item1.Branch).Distinct(); branchesToClear.ForEach(b => NetworkHelper.ClearLocations(networkCoverage, b)); // add new values/locations to coverage locations.ForEach(l => networkCoverage[l.Item1] = l.Item2); }
private static void OperateOneTimestep(INetworkCoverage coverageA, INetworkCoverage coverageB, IEnumerable <INetworkLocation> allLocations, Func <double, double, double> operation) { IDictionary <INetworkLocation, double> locationToValueMapping = new Dictionary <INetworkLocation, double>(); foreach (var loc in allLocations) { //in case of different networks the actual location is retrieved using coordinates: var locationInCoverageA = GetLocationInCoverage(coverageA, loc); if (locationInCoverageA != null) { var valueForA = coverageA.Evaluate(locationInCoverageA); var locationInCoverageB = GetLocationInCoverage(coverageB, loc); var valueForB = locationInCoverageB != null?coverageB.Evaluate(locationInCoverageB) : 0.0; var value = operation(valueForA, valueForB); locationToValueMapping.Add(locationInCoverageA, value); } } //apply values in a second loop to prevent evaluation being affected! SetResults(locationToValueMapping, coverageA); }
private static void UpdateSegmentsRouteBetweenLocations(INetworkCoverage coverage) { coverage.Segments.Values.Clear(); var coverageLocations = coverage.Locations.Values; for (var i = 0; i < coverageLocations.Count - 1; i++) { #if MONO var source = (INetworkLocation)((IMultiDimensionalArray)coverageLocations)[i]; var target = (INetworkLocation)((IMultiDimensionalArray)coverageLocations)[i + 1]; #else var source = coverageLocations[i]; var target = coverageLocations[i + 1]; #endif var segments = NetworkHelper.GetShortestPathBetweenBranchFeaturesAsNetworkSegments(coverage.Network, source, target); foreach (var segment in segments) { if (segment.Chainage < 0 || segment.EndChainage < 0) { throw new ArgumentException("EndOffset or segment offset invalid"); } coverage.Segments.Values.Add(segment); } } }
private static void PerformOperation <T>(INetworkCoverage coverage, IEnumerable <INetworkCoverage> otherCoverages, Func <IEnumerable <double>, T> operation, INetworkCoverage outputCoverage = null) { var allLocations = GetAllLocations(coverage, otherCoverages); if (coverage.IsTimeDependent) { ThrowIfCoverageTimeValuesNotEqual(coverage, otherCoverages); foreach (var time in coverage.Time.Values) { foreach (var networkCoverage in otherCoverages) { networkCoverage.AddTimeFilter(time); } if (outputCoverage != null) { OperateOneTimestep(coverage.AddTimeFilter(time), otherCoverages, allLocations, operation, outputCoverage.AddTimeFilter(time)); } else { OperateOneTimestep(coverage.AddTimeFilter(time), otherCoverages, allLocations, operation); } } } else { OperateOneTimestep(coverage, otherCoverages, allLocations, operation, outputCoverage); } }
private static void PerformOperation <T>(INetworkCoverage coverage, double referenceValue, Func <double, double, T> operation, INetworkCoverage outputCoverage = null) { var allLocations = coverage.Locations.Values.Distinct().OrderBy(loc => loc).ToList(); if (coverage.IsTimeDependent) { foreach (var time in coverage.Time.Values) { if (outputCoverage != null) { OperateOneTimeStep(coverage.AddTimeFilter(time), referenceValue, allLocations, operation, outputCoverage.AddTimeFilter(time)); } else { OperateOneTimeStep(coverage.AddTimeFilter(time), referenceValue, allLocations, operation); } } } else { OperateOneTimeStep(coverage, referenceValue, allLocations, operation, outputCoverage); } }
/// <summary> /// Creates a new coverage, based on <paramref name="coverage"/>, with a <see cref="bool"/> value /// defined by <paramref name="operation"/>. /// </summary> /// <param name="coverage">Coverage to perform the operation on.</param> /// <param name="referenceValue">A scalar reference value.</param> /// <param name="operation">A <see cref="Func{T1,T2,TResult}"/> where the first argument are values from <paramref name="coverage"/>, /// the second argument is <paramref name="referenceValue"/> and returns a bool value.</param> /// <returns>Returns a <see cref="INetworkCoverage"/>, with the same time dependency as <paramref name="coverage"/>, /// that has 1 bool component.</returns> public static INetworkCoverage OperateToNewCoverage <T>(this INetworkCoverage coverage, double referenceValue, Func <double, double, T> operation) { var outputCoverage = CreateOutputCoverage <T>(coverage); PerformOperation(coverage, referenceValue, operation, outputCoverage); return(outputCoverage); }
///<summary> ///</summary> ///<param name="networkCoverage"></param> ///<param name="branch"></param> ///<param name="offsets"></param> public static void CreateSegments(INetworkCoverage networkCoverage, IBranch branch, IList <double> offsets) { //ClearSegments(networkCoverage, branch); foreach (var offset in offsets) { networkCoverage[new NetworkLocation(branch, offset)] = 0.0; } }
private static void ThrowIfInputIsInvalid(INetworkCoverage coverageA, INetworkCoverage coverageB) { if (coverageB.Network != coverageA.Network) { throw new InvalidOperationException("Network of coverage {0} does not math network of {1}," + " math operations are not possible"); } }
private static IEnumerable <INetworkLocation> GetAllLocations(INetworkCoverage coverage, IEnumerable <INetworkCoverage> otherCoverages) { if (CheckIfNetworksMismatch(coverage.Network, otherCoverages.Select(c => c.Network))) { return(coverage.Locations.Values.ToList()); } return(coverage.Locations.Values.Concat(otherCoverages.SelectMany(c => c.Locations.Values)).Distinct().OrderBy(loc => loc).ToList()); }
private static IEnumerable <INetworkLocation> GetAllLocations(INetworkCoverage coverageA, INetworkCoverage coverageB) { if (CheckIfNetworksMismatch(coverageA.Network, coverageB.Network)) { return(coverageA.Locations.Values.ToList()); } return(coverageA.Locations.Values.Concat(coverageB.Locations.Values).Distinct().OrderBy(loc => loc).ToList()); }
public static INetworkCoverage OperateToNewCoverage <T>(this INetworkCoverage coverage, IEnumerable <INetworkCoverage> otherCoverages, Func <IEnumerable <double>, T> operation) { var outputCoverage = CreateOutputCoverage <T>(coverage); PerformOperation(coverage, otherCoverages, operation, outputCoverage); return(outputCoverage); }
private static void DrawSegment(VectorLayer segmentsLayer, INetworkCoverage coverage, ITheme theme, int segmentNumber, IList <double> allBranchLocationValues, bool firstSegment, bool lastSegment, Graphics graphics, INetworkSegment segment, VectorStyle defaultStyle, double offset) { var valueAtStart = allBranchLocationValues[segmentNumber * 2]; var value = allBranchLocationValues[segmentNumber * 2 + 1]; var valueAtEnd = allBranchLocationValues[segmentNumber * 2 + 2]; // extract based on valueAtStart and valueAtEnd the colors from the var styleStart = (theme != null) ? (VectorStyle)theme.GetStyle(valueAtStart) : segmentsLayer.Style; var themeStyle = (theme != null) ? (VectorStyle)theme.GetStyle(value) : segmentsLayer.Style; var styleEnd = (theme != null) ? (VectorStyle)theme.GetStyle(valueAtEnd) : segmentsLayer.Style; // check if within limits (preventing GDI+ overflow on 'ultrazoom') var strokes = Transform.TransformToImage((ILineString)segment.Geometry, segmentsLayer.Map); if (strokes.Any(s => !graphics.ClipBounds.Contains(s))) { return; } if (firstSegment && lastSegment) { // 1 segment; render segement based on coverage.Locations.InterpolationType if (coverage.Locations.ExtrapolationType == ExtrapolationType.None) { VectorRenderingHelper.RenderGeometry(graphics, segmentsLayer.Map, segment.Geometry, defaultStyle, null, true); return; } if (coverage.Locations.ExtrapolationType == ExtrapolationType.Linear) { VectorRenderingHelper.RenderGeometry(graphics, segmentsLayer.Map, segment.Geometry, themeStyle, null, true); return; } // todo use proper colors/styles from Theme; now 'via' styles are ignored. var kcolors = new[] { ((SolidBrush)styleStart.Fill).Color, ((SolidBrush)themeStyle.Fill).Color, ((SolidBrush)styleEnd.Fill).Color }; var kpositions = new[] { 0.0F, (float)((offset - segment.Chainage) / segment.Length), 1.0F }; DrawStrokesLinear(graphics, strokes, (int)themeStyle.Line.Width, kcolors, kpositions); return; } var positions = new[] { 0.0F, (float)((offset - segment.Chainage) / segment.Length), (float)((offset - segment.Chainage) / segment.Length), 1.0F }; var colors = CreateBeginEndColors(coverage, firstSegment, lastSegment, GetStyleColor(themeStyle), GetStyleColor(styleStart), GetStyleColor(styleEnd), GetStyleColor(defaultStyle)); // todo use proper colors/styles from Theme; now 'via' styles are ignored. if (!segment.Geometry.IsEmpty) { DrawStrokesLinear(graphics, strokes, (int)themeStyle.Line.Width, colors, positions); } }
public static void ClearLocations(INetworkCoverage networkCoverage, IBranch branch) { var locationsToRemove = networkCoverage.GetLocationsForBranch(branch); if (locationsToRemove.Count != 0) { networkCoverage.Locations.RemoveValues(networkCoverage.Locations.CreateValuesFilter(locationsToRemove)); } }
private static INetworkCoverage CreateOutputCoverage <T>(INetworkCoverage coverage) { var outputCoverage = CopyNetworkCoverage(coverage); outputCoverage.Components.RemoveAt(0); outputCoverage.Components.Add(new Variable <T>()); outputCoverage.Components[0].Unit = new Unit("", ""); return(outputCoverage); }
private static void UpdateSegmentsSegmentPerLocation(INetworkCoverage coverage) { //for performance reasons..get the locations all at once. var allLocations = coverage.Locations.Values; foreach (var branch in coverage.Network.Branches) { UpdateSegments(coverage, branch, allLocations); } }
private static INetworkLocation GetLocationInCoverage(INetworkCoverage coverage, INetworkLocation location) { if (CheckIfNetworksMismatch(coverage.Network, location.Network)) //defined on different network { var coordinate = location.Geometry.Coordinate; var loc = coverage.GetLocationOnBranch(coordinate.X, coordinate.Y); return(loc); } return(location); }
/// <summary> /// Updates the segments for all branches with branch location following this scheme: /// b1 /// n1---------------------------------n2 /// /// A----------C---------B----------D-- - network locations /// - segments /// </summary> /// <param name="coverage"></param> /// <param name="fullyCover"></param> /// when set to true the segment of the branch private static void UpdateSegmentsSegmentBetweenLocations(INetworkCoverage coverage, bool fullyCover) { coverage.Segments.Values.Clear(); //sorting is done in coverage locations..don't need to do it here. This supports for reversed segments. coverage.Segments.SetValues(coverage.Locations.Values.GroupBy(l => l.Branch) .SelectMany( g => UpdateSegmentsBranchSegmentBetweenLocations(fullyCover, g.Key, g))); }
/// <summary> /// Draw a branch with no segments; this will usually be drawn with the style for the default value. /// </summary> /// <param name="map"></param> /// <param name="coverage"></param> /// <param name="g"></param> /// <param name="style"></param> /// <param name="mapExtents"></param> /// <param name="drawnBranches"></param> /// <param name="theme"></param> private static void RenderSegmentFreeBranches(Map map, INetworkCoverage coverage, Graphics g, VectorStyle style, IEnvelope mapExtents, HashSet <IBranch> drawnBranches, ITheme theme) { var visibleBranches = coverage.Network.Branches.Where(b => b.Geometry.EnvelopeInternal.Intersects(mapExtents)).ToList(); visibleBranches.ForEach(vb => { if (!drawnBranches.Contains(vb)) { VectorRenderingHelper.RenderGeometry(g, map, vb.Geometry, style, null, true); } }); }
public static void UpdateSegments(INetworkCoverage coverage, IBranch branch, IMultiDimensionalArray <INetworkLocation> allLocations) { if (coverage.Network == null) { return; } // remove old segments for selected branch foreach (var segment in coverage.Segments.Values.Where(s => s.Branch == branch).ToArray()) { coverage.Segments.Values.Remove(segment); } var branchNetworkLocations = allLocations.Where(l => l.Branch == branch).Cast <INetworkLocation>(); var skipFirst = branchNetworkLocations.FirstOrDefault() == allLocations.FirstOrDefault(); var skipLast = branchNetworkLocations.LastOrDefault() == allLocations.LastOrDefault(); IEnumerable <INetworkSegment> segments; switch (coverage.SegmentGenerationMethod) { case SegmentGenerationMethod.RouteBetweenLocations: segments = NetworkHelper.GenerateSegmentsBetweenLocations(branchNetworkLocations, branch, skipFirst, skipLast); break; case SegmentGenerationMethod.SegmentBetweenLocations: //segments = NetworkHelper.GenerateSegmentsPerLocation(branchNetworkLocations, branch); segments = UpdateSegmentsBranchSegmentBetweenLocations(false, branch, branchNetworkLocations); break; case SegmentGenerationMethod.SegmentPerLocation: segments = NetworkHelper.GenerateSegmentsPerLocation(branchNetworkLocations, branch); break; default: throw new ArgumentException( string.Format("Method {0} not supported", coverage.SegmentGenerationMethod), "coverage"); } foreach (var s in segments) { // todo set branch and offset to NetworkSegmentAttributeAccessor? // assume number of location to be at least number of segments per branch coverage.Segments.Values.Add(s); } }
public static void UpdateSegments(INetworkCoverage coverage) { if (coverage.Network == null) { return; } try { coverage.Segments.Clear(); switch (coverage.SegmentGenerationMethod) { case SegmentGenerationMethod.SegmentPerLocation: UpdateSegmentsSegmentPerLocation(coverage); break; case SegmentGenerationMethod.RouteBetweenLocations: UpdateSegmentsRouteBetweenLocations(coverage); break; case SegmentGenerationMethod.SegmentBetweenLocations: UpdateSegmentsSegmentBetweenLocations(coverage, false); break; case SegmentGenerationMethod.SegmentBetweenLocationsFullyCovered: UpdateSegmentsSegmentBetweenLocations(coverage, true); break; case SegmentGenerationMethod.None: UpdateSegmentsNone(coverage); break; } } //why catch all exceptions here??? there might be something wrong that is WORTH crashing the app //TODO: only catch the exception you know and want to catch catch (Exception exception) { Log.ErrorFormat("Fatal error updating network coverage {0}; reason {1}", coverage.Name, exception.Message); // do not rethrow, it will crash ui } for (int i = 1; i < coverage.Segments.Values.Count + 1; i++) { coverage.Segments.Values[i - 1].SegmentNumber = i; } }
public void ExtractTimeSlice() { var network = GetNetwork(); var networkCoverage = new NetworkCoverage("test", true) { Network = network }; DateTime [] dateTimes = new DateTime[10]; for (int i = 0; i < 10; i++) { dateTimes[i] = new DateTime(2000, 1, 1, 1, /* minute */ i, 0); networkCoverage[dateTimes[i], new NetworkLocation(network.Branches[0], 10.0)] = 10.0 + i; networkCoverage[dateTimes[i], new NetworkLocation(network.Branches[0], 90.0)] = 90.0 + i; networkCoverage[dateTimes[i], new NetworkLocation(network.Branches[1], 10.0)] = 110.0 + i; networkCoverage[dateTimes[i], new NetworkLocation(network.Branches[1], 90.0)] = 190.0 + i; } INetworkCoverage slice = NetworkCoverageHelper.ExtractTimeSlice(networkCoverage, new DateTime(2000, 1, 1, 1, /* minute */ 0, 0)); Assert.AreEqual(false, slice.IsTimeDependent); Assert.AreEqual(10.0 + 0, slice.Evaluate(new NetworkLocation(network.Branches[0], 10.0))); Assert.AreEqual(90.0 + 0, slice.Evaluate(new NetworkLocation(network.Branches[0], 90.0))); Assert.AreEqual(110.0 + 0, slice.Evaluate(new NetworkLocation(network.Branches[1], 10.0))); Assert.AreEqual(190.0 + 0, slice.Evaluate(new NetworkLocation(network.Branches[1], 90.0))); //slice = NetworkCoverageHelper.ExtractTimeSlice(networkCoverage, new DateTime(2000, 1, 1, 1, /* minute */9, 0)); slice = new NetworkCoverage(networkCoverage.Name, false); NetworkCoverageHelper.ExtractTimeSlice(networkCoverage, slice, new DateTime(2000, 1, 1, 1, /* minute */ 9, 0), true); Assert.AreEqual(false, slice.IsTimeDependent); Assert.AreEqual(10.0 + 9, slice.Evaluate(new NetworkLocation(network.Branches[0], 10.0))); Assert.AreEqual(90.0 + 9, slice.Evaluate(new NetworkLocation(network.Branches[0], 90.0))); Assert.AreEqual(110.0 + 9, slice.Evaluate(new NetworkLocation(network.Branches[1], 10.0))); Assert.AreEqual(190.0 + 9, slice.Evaluate(new NetworkLocation(network.Branches[1], 90.0))); // just repeat the previous action; refilling a coverage should also work NetworkCoverageHelper.ExtractTimeSlice(networkCoverage, slice, new DateTime(2000, 1, 1, 1, /* minute */ 9, 0), true); Assert.AreEqual(false, slice.IsTimeDependent); Assert.AreEqual(10.0 + 9, slice.Evaluate(new NetworkLocation(network.Branches[0], 10.0))); Assert.AreEqual(90.0 + 9, slice.Evaluate(new NetworkLocation(network.Branches[0], 90.0))); Assert.AreEqual(110.0 + 9, slice.Evaluate(new NetworkLocation(network.Branches[1], 10.0))); Assert.AreEqual(190.0 + 9, slice.Evaluate(new NetworkLocation(network.Branches[1], 90.0))); }
private static void Operate(INetworkCoverage coverageA, INetworkCoverage coverageB, Func <double, double, double> operation) { ThrowIfInputIsInvalid(coverageA, coverageB); var allLocations = coverageA.Locations.Values.Concat(coverageB.Locations.Values).Distinct().OrderBy(loc => loc).ToList(); var locationToValueMapping = allLocations.ToDictionary(location => location, location => operation(coverageA.Evaluate(location), coverageB.Evaluate(location))); foreach (var location in allLocations) { coverageA[location] = locationToValueMapping[location]; } }
public static void UpdateSegments(INetworkCoverage coverage) { if (coverage.Network == null) { return; } try { coverage.Segments.Clear(); switch (coverage.SegmentGenerationMethod) { case SegmentGenerationMethod.SegmentPerLocation: UpdateSegmentsSegmentPerLocation(coverage); break; case SegmentGenerationMethod.RouteBetweenLocations: UpdateSegmentsRouteBetweenLocations(coverage); break; case SegmentGenerationMethod.SegmentBetweenLocations: UpdateSegmentsSegmentBetweenLocations(coverage, false); break; case SegmentGenerationMethod.SegmentBetweenLocationsFullyCovered: UpdateSegmentsSegmentBetweenLocations(coverage, true); break; case SegmentGenerationMethod.None: UpdateSegmentsNone(coverage); break; } } //why catch all exceptions here??? there might be something wrong that is WORTH crashing the app //TODO: only catch the exception you know and want to catch catch (Exception exception) { Log.ErrorFormat("Fatal error updating network coverage {0}; reason {1}", coverage.Name, exception.Message); // do not rethrow, it will crash ui } for (int i = 1; i < coverage.Segments.Values.Count + 1; i++) { coverage.Segments.Values[i - 1].SegmentNumber = i; } }
/// <summary> /// Extract a time slice for 1 time step out a time dependent network coverage /// </summary> /// <param name="source"></param> /// <param name="dateTime"></param> /// <returns></returns> public static INetworkCoverage ExtractTimeSlice(INetworkCoverage source, DateTime dateTime) { if (!source.Arguments[0].Values.Contains(dateTime)) { throw new ArgumentException("ExtractTimeSlice: invalid time.", "dateTime"); } INetworkCoverage slice = new NetworkCoverage(source.Name, false); //slice.Components[0].NoDataValues = new ArrayList(source.Components[0].NoDataValues); //slice.Locations.Values.AddRange(source.Arguments[1].Values); //var values = source.GetValues(new VariableValueFilter(source.Arguments[0], new [] {dateTime})); //slice.SetValues(values); // extract a time slice from the source and also copy the networklocations. ExtractTimeSlice(source, slice, dateTime, true); return(slice); }
/// <summary> /// Returns all locations in the route. Route cannot contain doubles for now because side view should /// draw structures double etc. Would complicate more then the use-case would justify /// </summary> /// <param name="source"></param> /// <param name="route"></param> /// <returns></returns> public static IList<INetworkLocation> GetLocationsInRoute(INetworkCoverage source, Route route) { IList<INetworkLocation> locations = new List<INetworkLocation>(); foreach (INetworkSegment segment in route.Segments.Values) { var locationsForSegment = GetLocationsForSegment(segment, source, true); foreach (var location in locationsForSegment) { //add location if we didn't just add it..this can happens when segments go like 1-->3 3-->4 4-->5 //don't want the start and endnodes causing doubles so should be like 1-->3-->4-->5 if (!location.Equals(locations.LastOrDefault())) { locations.Add(location); } } } return locations; }
public static void UpdateSegments(INetworkCoverage coverage) { if (coverage.Network == null) { return; } try { coverage.Segments.Clear(); switch (coverage.SegmentGenerationMethod) { case SegmentGenerationMethod.SegmentPerLocation: UpdateSegmentsSegmentPerLocation(coverage); break; case SegmentGenerationMethod.RouteBetweenLocations: UpdateSegmentsRouteBetweenLocations(coverage); break; case SegmentGenerationMethod.SegmentBetweenLocations: UpdateSegmentsSegmentBetweenLocations(coverage, false); break; case SegmentGenerationMethod.SegmentBetweenLocationsFullyCovered: UpdateSegmentsSegmentBetweenLocations(coverage, true); break; case SegmentGenerationMethod.None: UpdateSegmentsNone(coverage); break; } } catch (Exception exception) { Log.ErrorFormat("Fatal error updating network coverage {0}; reason {1}", coverage.Name, exception.Message); // do not rethrow, it will crash ui } }
/// <summary> /// returns the offset of the branchfeature in the route. -1 if branchfeature is not in the route. /// </summary> /// <param name="route"></param> /// <param name="branchFeature"></param> /// <returns></returns> public static double GetRouteOffset(INetworkCoverage route, IBranchFeature branchFeature) { double offset = 0; foreach (var segment in route.Segments.Values) { if (branchFeature.Branch != segment.Branch) { offset += segment.Length; } else { if (segment.DirectionIsPositive) { if (branchFeature.Offset > segment.Offset + segment.Length) { offset += segment.Length; } else { offset += (branchFeature.Offset - segment.Offset); return offset; } } else { if (branchFeature.Offset > segment.Offset)// + segment.Length) { offset += segment.Length; } else { offset += (segment.Offset - branchFeature.Offset); return offset; } } } } return -1; }
public static void ExtractTimeSlice(INetworkCoverage source, INetworkCoverage targetSlice /* bad name */, DateTime dateTime, bool copyLocations) { if (!source.IsTimeDependent) { throw new ArgumentException("ExtractTimeSlice: source network coverage should be time dependent.", "source"); } IMultiDimensionalArray<INetworkLocation> networkLocations = copyLocations ? source.Locations.Values : targetSlice.Locations.Values; IMultiDimensionalArray values; if (copyLocations) { values = source.GetValues(new VariableValueFilter<DateTime>(source.Arguments[0], dateTime)); } else { values = source.GetValues(new VariableValueFilter<DateTime>(source.Arguments[0], dateTime), new VariableValueFilter<INetworkLocation>(source.Arguments[1], networkLocations)); } var clonedValues = new ArrayList(values); var clonedLocations = networkLocations.ToArray(); if (copyLocations) { targetSlice.Clear(); targetSlice.Locations.Values.AddRange(clonedLocations); targetSlice.Components[0].NoDataValues = new ArrayList(source.Components[0].NoDataValues); } targetSlice.SetValues(clonedValues); }
public static void UpdateSegments(INetworkCoverage coverage, IBranch branch, IMultiDimensionalArray<INetworkLocation> allLocations) { if (coverage.Network == null) { return; } // remove old segments for selected branch foreach (var segment in coverage.Segments.Values.Where(s => s.Branch == branch).ToArray()) { coverage.Segments.Values.Remove(segment); } var branchNetworkLocations = allLocations.Where(l => l.Branch == branch).Cast<INetworkLocation>(); var skipFirst = branchNetworkLocations.FirstOrDefault() == allLocations.FirstOrDefault(); var skipLast = branchNetworkLocations.LastOrDefault() == allLocations.LastOrDefault(); IEnumerable<INetworkSegment> segments; switch (coverage.SegmentGenerationMethod) { case SegmentGenerationMethod.RouteBetweenLocations: segments = NetworkHelper.GenerateSegmentsBetweenLocations(branchNetworkLocations, branch, skipFirst, skipLast); break; case SegmentGenerationMethod.SegmentBetweenLocations: //segments = NetworkHelper.GenerateSegmentsPerLocation(branchNetworkLocations, branch); segments = UpdateSegmentsBranchSegmentBetweenLocations(false, branch, branchNetworkLocations); break; case SegmentGenerationMethod.SegmentPerLocation: segments = NetworkHelper.GenerateSegmentsPerLocation(branchNetworkLocations, branch); break; default: throw new ArgumentException( string.Format("Method {0} not supported", coverage.SegmentGenerationMethod), "coverage"); } foreach (var s in segments) { // todo set branch and offset to NetworkSegmentAttributeAccessor? // assume number of location to be at least number of segments per branch coverage.Segments.Values.Add(s); } }
private static void UpdateSegmentsSegmentPerLocation(INetworkCoverage coverage) { //for performance reasons..get the locations all at once. var allLocations = coverage.Locations.Values; foreach (var branch in coverage.Network.Branches) { UpdateSegments(coverage, branch, allLocations); } }
private static void UpdateSegmentsRouteBetweenLocations(INetworkCoverage coverage) { coverage.Segments.Values.Clear(); var coverageLocations = coverage.Locations.Values; for (var i = 0; i < coverageLocations.Count - 1; i++) { #if MONO var source = (INetworkLocation)((IMultiDimensionalArray)coverageLocations)[i]; var target = (INetworkLocation)((IMultiDimensionalArray)coverageLocations)[i + 1]; #else var source = coverageLocations[i]; var target = coverageLocations[i + 1]; #endif var segments = NetworkHelper.GetShortestPathBetweenBranchFeaturesAsNetworkSegments(coverage.Network, source, target); foreach (var segment in segments) { if (segment.Chainage < 0 || segment.EndChainage < 0) { throw new ArgumentException("EndOffset or segment offset invalid"); } coverage.Segments.Values.Add(segment); } } }
private static INetworkLocation FindNodePoint(INode node, INetworkCoverage coverage) { var incommingBranchPoints = coverage.Locations.Values.Where(l => Math.Abs(l.Chainage - l.Branch.Length) < BranchFeature.Epsilon && node.IncomingBranches.Contains(l.Branch)); var outGoingBranchPoints = coverage.Locations.Values.Where(l => Math.Abs(l.Chainage) < BranchFeature.Epsilon && node.OutgoingBranches.Contains(l.Branch)); return incommingBranchPoints.Concat(outGoingBranchPoints).FirstOrDefault(); }
private static void UpdateSegmentsNone(INetworkCoverage coverage) { coverage.Segments.Values.Clear(); }
public static void ExtractTimeSlice(INetworkCoverage source, INetworkCoverage targetSlice /* bad name */, DateTime dateTime, bool copyLocations) { if (!source.IsTimeDependent) { throw new ArgumentException("ExtractTimeSlice: source network coverage should be time dependent.", "source"); } IEnumerable<INetworkLocation> networkLocations = null; if (copyLocations) { networkLocations = source.Arguments[1].GetValues().Cast<INetworkLocation>(); targetSlice.Clear(); targetSlice.Locations.Values.AddRange(networkLocations); } else { networkLocations = targetSlice.Arguments[0].GetValues().Cast<INetworkLocation>(); // networkLocations = new ArrayList(targetSlice.Arguments[0].GetValues()); } targetSlice.Components[0].NoDataValues = new ArrayList(source.Components[0].NoDataValues); IMultiDimensionalArray values; //var values = source.GetValues(new VariableValueFilter(source.Arguments[0], new[] { dateTime })); if (copyLocations) { values = source.GetValues(new VariableValueFilter<DateTime>(source.Arguments[0], dateTime)); } else { values = source.GetValues(new VariableValueFilter<DateTime>(source.Arguments[0], dateTime), new VariableValueFilter<INetworkLocation>(source.Arguments[1], networkLocations)); } targetSlice.SetValues(values); }
public static double GetRouteLength(INetworkCoverage coverage) { return coverage.Segments.Values.Sum(seg => seg.Length); }
public static bool LocationsAreUniqueOnRoute(INetworkCoverage source, Route route) { //find all locations and checks for doubles. var locationsSet = new HashSet<INetworkLocation>(); foreach (var segment in route.Segments.Values) { IEnumerable<INetworkLocation> locations = GetLocationsForSegment(segment, source, false); if (locationsSet.Overlaps(locations)) return false; foreach (var location in locations) { locationsSet.Add(location); } } return true; }
// Evaluate value at start and end of segment and interpolate the colors based on colors from theme. // The 4 dictinctive cases below should be properly handled by coverage.Evaluate //A 0 8 0 // [ ][ ][ ] // interpolate - linear // extrapolate - constant // 0000012334566788877776665555444333322211110000000 //B 0 8 0 // [ ][ ][ ] // interpolate - linear // extrapolate - linear // -10001233456678887777666555544433332221111000-1-1 //C 0 8 0 // [ ][ ][ ] // interpolate - linear // extrapolate - none // ddd00123345667888777766655554443333222111100ddddd where d is default value for coverage //D0 8 0 // [ ][ ][ ] // interpolate - linear // extrapolate - n.a. // 0011233455667888777766565555444433332222111110000 // no interpolation; only locations are visible // 0 8 0 // [ ][ ][ ] // interpolate - constant // 0000000008888888888888888888800000000000000000000 // 0 8 0 // [ ][ ][ ] // interpolate - constant // 0000000088888888888888888888888880000000000000000 private static void RenderBranchSegments(IBranch branch, VectorLayer segmentsLayer, Graphics graphics, INetworkCoverage coverage, Dictionary<INetworkLocation, INetworkSegment> locationsToSegmentDictonary) { var knownBranchLocations = coverage.GetLocationsForBranch(branch); var theme = segmentsLayer.Theme; var defaultStyle = (theme != null) ? (VectorStyle)theme.GetStyle(coverage.DefaultValue) : segmentsLayer.Style; var first = true; var allBranchLocations = new List<double>(); var branchSegments = new List<INetworkSegment>(); foreach (var location in knownBranchLocations) { if (!locationsToSegmentDictonary.Keys.Contains(location)) { continue; } var segment = locationsToSegmentDictonary[location]; branchSegments.Add(segment); if (first) { allBranchLocations.Add(segment.Chainage); } allBranchLocations.Add(location.Chainage); allBranchLocations.Add(segment.Chainage + segment.Length); first = false; } if (allBranchLocations.Any()) { var allBranchLocationValues = coverage.EvaluateWithinBranch(branch, allBranchLocations.OrderBy(o => o), knownBranchLocations); for (var i = 0; i < branchSegments.Count; i++) { var firstSegment = (i == 0); var lastSegment = (i == branchSegments.Count - 1); var segment = branchSegments[i]; var offset = knownBranchLocations[i].Chainage; DrawSegment(segmentsLayer, coverage, theme, i, allBranchLocationValues, firstSegment, lastSegment, graphics, segment, defaultStyle, offset); } } else { // When no locations, we still render because there // might be interpolation across nodes (ordered branches), // otherwise it will be rendered at the default coverage value. var values = new List<double>() { coverage.Evaluate(new NetworkLocation(branch, 0)), coverage.Evaluate(new NetworkLocation(branch, branch.Length/2)), coverage.Evaluate(new NetworkLocation(branch, branch.Length)) }; var segment = new NetworkSegment() { Branch = branch, Chainage = 0.0, Length = branch.Length, Geometry = branch.Geometry }; DrawSegment(segmentsLayer, coverage, theme, 0, values, true, true, graphics, segment, defaultStyle, branch.Length / 2); } }
private static void DrawSegment(VectorLayer segmentsLayer, INetworkCoverage coverage, ITheme theme, int segmentNumber, IList<double> allBranchLocationValues, bool firstSegment, bool lastSegment, Graphics graphics, INetworkSegment segment, VectorStyle defaultStyle, double offset) { var valueAtStart = allBranchLocationValues[segmentNumber * 2]; var value = allBranchLocationValues[segmentNumber * 2 + 1]; var valueAtEnd = allBranchLocationValues[segmentNumber * 2 + 2]; // extract based on valueAtStart and valueAtEnd the colors from the var styleStart = (theme != null) ? (VectorStyle)theme.GetStyle(valueAtStart) : segmentsLayer.Style; var themeStyle = (theme != null) ? (VectorStyle)theme.GetStyle(value) : segmentsLayer.Style; var styleEnd = (theme != null) ? (VectorStyle)theme.GetStyle(valueAtEnd) : segmentsLayer.Style; // check if within limits (preventing GDI+ overflow on 'ultrazoom') var strokes = Transform.TransformToImage((ILineString)segment.Geometry, segmentsLayer.Map); if (strokes.Any(s => !graphics.ClipBounds.Contains(s))) return; if (firstSegment && lastSegment) { // 1 segment; render segement based on coverage.Locations.InterpolationType if (coverage.Locations.ExtrapolationType == ExtrapolationType.None) { VectorRenderingHelper.RenderGeometry(graphics, segmentsLayer.Map, segment.Geometry, defaultStyle, null, true); return; } if (coverage.Locations.ExtrapolationType == ExtrapolationType.Linear) { VectorRenderingHelper.RenderGeometry(graphics, segmentsLayer.Map, segment.Geometry, themeStyle, null, true); return; } // todo use proper colors/styles from Theme; now 'via' styles are ignored. var kcolors = new[] { ((SolidBrush) styleStart.Fill).Color, ((SolidBrush) themeStyle.Fill).Color, ((SolidBrush) styleEnd.Fill).Color }; var kpositions = new[] { 0.0F, (float)((offset - segment.Chainage) / segment.Length), 1.0F }; DrawStrokesLinear(graphics, strokes, (int)themeStyle.Line.Width, kcolors, kpositions); return; } var positions = new[] { 0.0F, (float) ((offset - segment.Chainage)/segment.Length), (float) ((offset - segment.Chainage)/segment.Length), 1.0F }; var colors = CreateBeginEndColors(coverage, firstSegment, lastSegment, GetStyleColor(themeStyle), GetStyleColor(styleStart), GetStyleColor(styleEnd), GetStyleColor(defaultStyle)); // todo use proper colors/styles from Theme; now 'via' styles are ignored. if (!segment.Geometry.IsEmpty) { DrawStrokesLinear(graphics, strokes, (int)themeStyle.Line.Width, colors, positions); } }
private static Color[] CreateBeginEndColors(INetworkCoverage coverage, bool firstSegment, bool lastSegment, Color themeColor, Color startColor, Color endColor, Color defaultColor) { var colors = new Color[4]; var extrapolationType = coverage.Locations.ExtrapolationType; var interpolationType = coverage.Locations.InterpolationType; if (firstSegment) { switch (extrapolationType) { case ExtrapolationType.None: colors[0] = defaultColor; colors[1] = defaultColor; break; case ExtrapolationType.Constant: colors[0] = themeColor; colors[1] = themeColor; break; default: colors[0] = startColor; colors[1] = themeColor; break; } } else { switch (interpolationType) { case InterpolationType.None: colors[0] = defaultColor; colors[1] = defaultColor; break; case InterpolationType.Constant: colors[0] = themeColor; colors[1] = themeColor; break; default: colors[0] = startColor; colors[1] = themeColor; break; } } if (lastSegment) { switch (extrapolationType) { case ExtrapolationType.None: colors[2] = defaultColor; colors[3] = defaultColor; break; case ExtrapolationType.Constant: colors[2] = themeColor; colors[3] = themeColor; break; default: colors[2] = themeColor; colors[3] = endColor; break; } } else { switch (interpolationType) { case InterpolationType.None: colors[2] = defaultColor; colors[3] = defaultColor; break; case InterpolationType.Constant: colors[2] = themeColor; colors[3] = themeColor; break; default: colors[2] = themeColor; colors[3] = endColor; break; } } return colors; }
/// <summary> /// Extract a time slice for 1 time step out a time dependent network coverage /// </summary> /// <param name="source"></param> /// <param name="dateTime"></param> /// <returns></returns> public static INetworkCoverage ExtractTimeSlice(INetworkCoverage source, DateTime dateTime) { if (!source.Arguments[0].Values.Contains(dateTime)) { throw new ArgumentException("ExtractTimeSlice: invalid time.", "dateTime"); } INetworkCoverage slice = new NetworkCoverage(source.Name, false); //slice.Components[0].NoDataValues = new ArrayList(source.Components[0].NoDataValues); //slice.Locations.Values.AddRange(source.Arguments[1].Values); //var values = source.GetValues(new VariableValueFilter(source.Arguments[0], new [] {dateTime})); //slice.SetValues(values); // extract a time slice from the source and also copy the networklocations. ExtractTimeSlice(source, slice, dateTime, true); return slice; }
/// <summary> /// returns the segment where networkLocation is located. /// networkLocation does not have to be a networkLocation in route.Locations. /// </summary> /// <param name="route"></param> /// <param name="networkLocation"></param> /// <returns></returns> public static INetworkSegment GetSegmentForNetworkLocation(INetworkCoverage route, INetworkLocation networkLocation) { var segments = route.Segments.Values.ToArray(); foreach (var segment in segments) { if (segment.Branch != networkLocation.Branch) { continue; } if ((networkLocation.Offset > segment.Offset) && (networkLocation.Offset < segment.EndOffset)) { return segment; } // segment can be reversed in coverage if ((networkLocation.Offset < segment.Offset) && (networkLocation.Offset > segment.EndOffset)) { return segment; } } return null; }
/// <summary> /// Snaps the points to the network coverage, given the tolerance. Existing locations/values will be cleared only /// when there are new points mapped to that branch. /// </summary> /// <param name="pointValuePairs"></param> /// <param name="networkCoverage"></param> /// <param name="tolerance"></param> public static void SnapToCoverage(IEnumerable<Tuple<IPoint, double>> pointValuePairs, INetworkCoverage networkCoverage, double tolerance) { var tree = new Quadtree(); networkCoverage.Network.Branches.ForEach(b => tree.Insert(b.Geometry.EnvelopeInternal, b)); // match points to branch buffers var locations = new List<Tuple<INetworkLocation, double>>(); foreach (var pointValue in pointValuePairs) { var envelope = pointValue.Item1.EnvelopeInternal; envelope.ExpandBy(tolerance); var branches = tree.Query(envelope).Cast<IBranch>(); var location = MapPointToClosestBranch(pointValue.Item1, branches, tolerance); if (location != null) { locations.Add(new Tuple<INetworkLocation, double>(location, pointValue.Item2)); } } // remove values for all branches that have new values imported var branchesToClear = locations.Select(l => l.Item1.Branch).Distinct(); branchesToClear.ForEach(b => NetworkHelper.ClearLocations(networkCoverage, b)); // add new values/locations to coverage locations.ForEach(l => networkCoverage[l.Item1] = l.Item2); }
///<summary> ///</summary> ///<param name="networkCoverage"></param> ///<param name="branch"></param> ///<param name="offsets"></param> public static void CreateSegments(INetworkCoverage networkCoverage, IBranch branch, IList<double> offsets) { //ClearSegments(networkCoverage, branch); foreach (var offset in offsets) { networkCoverage[new NetworkLocation(branch, offset)] = 0.0; } }
/// <summary> /// Updates the segments for all branches with branch location following this scheme: /// b1 /// n1---------------------------------n2 /// /// A----------C---------B----------D-- - network locations /// - segments /// </summary> /// <param name="coverage"></param> /// <param name="fullyCover"></param> /// when set to true the segment of the branch private static void UpdateSegmentsSegmentBetweenLocations(INetworkCoverage coverage, bool fullyCover) { coverage.Segments.Values.Clear(); //sorting is done in coverage locations..don't need to do it here. This supports for reversed segments. coverage.Segments.SetValues(coverage.Locations.Values.GroupBy(l => l.Branch) .SelectMany( g => UpdateSegmentsBranchSegmentBetweenLocations(fullyCover, g.Key, g))); }
/// <summary> /// Draw a branch with no segments; this will usually be drawn with the style for the default value. /// </summary> /// <param name="map"></param> /// <param name="coverage"></param> /// <param name="g"></param> /// <param name="style"></param> /// <param name="mapExtents"></param> /// <param name="drawnBranches"></param> /// <param name="theme"></param> private static void RenderSegmentFreeBranches(IMap map, INetworkCoverage coverage, Graphics g, VectorStyle style, IEnvelope mapExtents, HashSet<IBranch> drawnBranches, ITheme theme) { var visibleBranches = coverage.Network.Branches.Where(b => b.Geometry.EnvelopeInternal.Intersects(mapExtents)).ToList(); visibleBranches.ForEach(vb => { if (!drawnBranches.Contains(vb)) { VectorRenderingHelper.RenderGeometry(g, map, vb.Geometry, style, null, true); } }); }