/// <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;
 }
Exemple #3
0
        /// <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>
 /// 
 /// </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)
        {
            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);
        }