/// <summary> /// Splits a branch at the given node and connect resulting 2 branches to the node. /// All related branch features are moved to the corresponding branch based on their geometry. /// </summary> /// <param name="network"></param> /// <param name="branch"></param> /// <param name="node"></param> public static IBranch SplitBranchAtNode(INetwork network, IBranch branch, INode node) { var originalFirstBranchGeometryLength = branch.Geometry.Length; var lengthIndexedLine = new LengthIndexedLine(branch.Geometry); var firstBranchGeometryLength = lengthIndexedLine.IndexOf(node.Geometry.Coordinates[0]); // compute geometries var firstBranchGeometry = (IGeometry)lengthIndexedLine.ExtractLine(0.0, firstBranchGeometryLength).Clone(); var secondBranchGeometry = (IGeometry)lengthIndexedLine.ExtractLine(firstBranchGeometryLength, originalFirstBranchGeometryLength).Clone(); if (firstBranchGeometry == GeometryCollection.Empty || secondBranchGeometry == GeometryCollection.Empty) { throw new ArgumentException(String.Format("Node {0} not located at line; unable to split branch {1}", node.Id, branch.Id)); } if (!secondBranchGeometry.Coordinates.Any() || !firstBranchGeometry.Coordinates.Any() || firstBranchGeometry.Length == 0.0 || secondBranchGeometry.Length == 0.0) { return(null); // nothing to split } // update existing branch var toNode = branch.Target; branch.Target = node; // create and add second branch var secondBranch = (IBranch)Activator.CreateInstance(branch.GetType()); secondBranch.Name = GetUniqueName(null, branch.Network.Branches, "branch"); secondBranch.Source = node; secondBranch.Target = toNode; secondBranch.Geometry = secondBranchGeometry; secondBranch.IsLengthCustom = branch.IsLengthCustom; secondBranch.OrderNumber = branch.OrderNumber; secondBranch.Attributes = branch.Attributes == null ? null : (IFeatureAttributeCollection)branch.Attributes.Clone(); network.Branches.Add(secondBranch); // FIX the branch geometries..NTS might have introduced NaNs that mess up serialization foreach (var coordinate in firstBranchGeometry.Coordinates.Concat(secondBranch.Geometry.Coordinates)) { coordinate.Z = 0; } if (branch.IsLengthCustom) { // Need to remember the current chainage values because setting the length of a branch with a custom // length causes chainages to be compensated. var originalChainages = branch.BranchFeatures.Concat(secondBranch.BranchFeatures).ToDictionary(f => f, f => f.Chainage); var originalLength = branch.Length; var fraction = firstBranchGeometryLength / originalFirstBranchGeometryLength; branch.Length = originalLength * fraction; secondBranch.Length = originalLength * (1 - fraction); // restore original chainages foreach (var branchFeature in originalChainages.Keys) { branchFeature.Chainage = originalChainages[branchFeature]; } } MoveBranchFeatures(branch, branch.IsLengthCustom ? branch.Length : firstBranchGeometry.Length, secondBranch); // update 1st branch length branch.Geometry = firstBranchGeometry; SplitBranchFeaturesWithLength(branch, secondBranch); return(secondBranch); }
/// <summary> /// /// </summary> /// <param name="branch">The reversed branch, assumed to be not null</param> public BranchReverseAction(IBranch branch) : base("Reverse branch " + branch.GetType().Name.ToLower()) { ReversedBranch = branch; }
/// <summary> /// Splits a branch at the given node and connect resulting 2 branches to the node. /// All related branch features are moved to the corresponding branch based on their geometry. /// </summary> /// <param name="network"></param> /// <param name="branch"></param> /// <param name="node"></param> public static IBranch SplitBranchAtNode(INetwork network, IBranch branch, INode node, bool doBeginEdit = false) { var originalFirstBranchGeometryLength = branch.Geometry.Length; var lengthIndexedLine = new LengthIndexedLine(branch.Geometry); var firstBranchGeometryLength = lengthIndexedLine.IndexOf(node.Geometry.Coordinates[0]); // compute geometries var firstBranchGeometry = (IGeometry)lengthIndexedLine.ExtractLine(0.0, firstBranchGeometryLength).Clone(); if (firstBranchGeometry == GeometryCollection.Empty) { throw new ArgumentException(String.Format("Node {0} not located at line; unable to split branch {1}", node.Id, branch.Id)); } var secondBranchGeometry = (IGeometry)lengthIndexedLine.ExtractLine(firstBranchGeometryLength, originalFirstBranchGeometryLength).Clone(); if (secondBranchGeometry == GeometryCollection.Empty) { throw new ArgumentException(String.Format("Node {0} not located at line; unable to split branch {1}", node.Id, branch.Id)); } if (secondBranchGeometry.Coordinates.Count() == 0 || firstBranchGeometry.Coordinates.Count() == 0 || firstBranchGeometry.Length == 0.0 || secondBranchGeometry.Length == 0.0) { return(null); // nothing to split } // update existing branch var toNode = branch.Target; branch.Target = node; // create and add second branch var fraction = firstBranchGeometryLength / originalFirstBranchGeometryLength; var secondBranch = (IBranch)Activator.CreateInstance(branch.GetType()); secondBranch.Name = GetUniqueName(null, branch.Network.Branches, "branch"); secondBranch.Source = node; secondBranch.Target = toNode; secondBranch.Geometry = secondBranchGeometry; secondBranch.IsLengthCustom = branch.IsLengthCustom; secondBranch.Attributes = branch.Attributes == null ? null : (IFeatureAttributeCollection)branch.Attributes.Clone(); network.Branches.Add(secondBranch); var originalOffsets = branch.BranchFeatures.ToDictionary(bf => bf, bf => bf.Offset); branch.Geometry = firstBranchGeometry; // FIX the branch geometries..NTS might have introduced NaNs that mess up serialization foreach (var coordinate in branch.Geometry.Coordinates.Concat(secondBranch.Geometry.Coordinates)) { coordinate.Z = 0; } // only update length of branch if it is not same as geometry. var originalLength = branch.Length; double newFirstLength, newSecondLength; if (branch.IsLengthCustom) { newFirstLength = originalLength * fraction; newSecondLength = originalLength * (1 - fraction); } else { newFirstLength = branch.Geometry.Length; newSecondLength = secondBranch.Geometry.Length; } // remember all branch features to be moved to the second branch var branchFeatureToMove = branch.BranchFeatures.Where(bf => bf.Offset >= newFirstLength).ToArray(); var newOffsets = new List <double>(); foreach (var branchFeature in branchFeatureToMove) { newOffsets.Add(branchFeature.Offset - newFirstLength); branchFeature.SetBeingMoved(true); branch.BranchFeatures.Remove(branchFeature); } branch.Length = newFirstLength; secondBranch.Length = newSecondLength; // move all features from first branch to the second branch for (var i = 0; i < branchFeatureToMove.Length; i++) { var branchFeature = branchFeatureToMove[i]; branchFeature.Offset = newOffsets[i]; AddBranchFeatureToBranch(branchFeature, secondBranch, branchFeature.Offset); branchFeature.SetBeingMoved(false); } // update offset in first branch to original offset for (int i = 0; i < branch.BranchFeatures.Count; i++) { var branchFeature = branch.BranchFeatures[i]; branchFeature.Offset = originalOffsets[branchFeature]; } return(secondBranch); }
/// <summary> /// Splits a branch at the given node and connect resulting 2 branches to the node. /// All related branch features are moved to the corresponding branch based on their geometry. /// </summary> /// <param name="network"></param> /// <param name="branch"></param> /// <param name="node"></param> public static IBranch SplitBranchAtNode(INetwork network, IBranch branch, INode node) { var originalFirstBranchGeometryLength = branch.Geometry.Length; var lengthIndexedLine = new LengthIndexedLine(branch.Geometry); double firstBranchGeometryLength = lengthIndexedLine.IndexOf(node.Geometry.Coordinates[0]); // compute geometries IGeometry firstBranchGeometry = (IGeometry)lengthIndexedLine.ExtractLine(0.0, firstBranchGeometryLength).Clone(); if (firstBranchGeometry == GeometryCollection.Empty) { throw new ArgumentException(String.Format("Node {0} not located at line; unable to split branch {1}", node.Id, branch.Id)); } IGeometry secondBranchGeometry = (IGeometry)lengthIndexedLine.ExtractLine(firstBranchGeometryLength, originalFirstBranchGeometryLength).Clone(); if (secondBranchGeometry == GeometryCollection.Empty) { throw new ArgumentException(String.Format("Node {0} not located at line; unable to split branch {1}", node.Id, branch.Id)); } if (secondBranchGeometry.Coordinates.Count() == 0 || firstBranchGeometry.Coordinates.Count() == 0 || firstBranchGeometry.Length == 0.0 || secondBranchGeometry.Length == 0.0) { return(null); // nothing to split } // update existing branch var toNode = branch.Target; branch.Target = node; // create and add second branch var fraction = firstBranchGeometryLength / originalFirstBranchGeometryLength; var secondBranch = (IBranch)Activator.CreateInstance(branch.GetType()); secondBranch.Name = GetUniqueName(null, branch.Network.Branches, "branch"); secondBranch.Source = node; secondBranch.Target = toNode; secondBranch.Geometry = secondBranchGeometry; secondBranch.IsLengthCustom = branch.IsLengthCustom; secondBranch.Attributes = branch.Attributes == null ? null : (IFeatureAttributeCollection)branch.Attributes.Clone(); network.Branches.Add(secondBranch); branch.Geometry = firstBranchGeometry; // only update length of branch if it is not same as geometry. var originalLength = branch.Length; if (branch.IsLengthCustom) { branch.Length = originalLength * fraction; secondBranch.Length = originalLength * (1 - fraction); } else { branch.Length = branch.Geometry.Length; secondBranch.Length = secondBranch.Geometry.Length; } // adjust last segment of the first branch (+center, boundary) // SplitBranchSegments(node, firstBranch, secondBranch, originalFirstBranchGeometryLength); // remember all branch features to be moved to the second branch IBranchFeature[] branchFeatureToMove = branch.BranchFeatures.Where(bf => bf.Offset >= firstBranchGeometryLength).ToArray(); // move all features from first branch to the second branch foreach (var branchFeature in branchFeatureToMove) { branch.BranchFeatures.Remove(branchFeature); branchFeature.Offset -= branch.Length; AddBranchFeatureToBranch(secondBranch, branchFeature, branchFeature.Offset); //secondBranch.BranchFeatures.Add(branchFeature); //branchFeature.Offset -= branch.Length; } return(secondBranch); }