public static ApplyReshapeLinesResponse ApplyReshapeLines(
            [NotNull] ApplyReshapeLinesRequest request,
            [CanBeNull] ITrackCancel trackCancel)
        {
            var subcurves = new List <CutSubcurve>();

            foreach (ReshapeLineMsg reshapeLineMsg in request.ReshapeLines)
            {
                subcurves.Add(FromReshapeLineMsg(reshapeLineMsg));
            }

            GeometryReshaperBase reshaper = CreateReshaper(request);

            var notifications = new NotificationCollection();

            Dictionary <IGeometry, NotificationCollection> reshapedGeometries =
                reshaper.Reshape(subcurves, notifications, request.UseNonDefaultReshapeSide);

            var response = new ApplyReshapeLinesResponse();

            if (reshapedGeometries.Count > 0)
            {
                // TODO: CacheGeometrySizes...
                IList <IFeature> updatedFeatures = reshaper.Save(reshapedGeometries);

                IList <ResultObjectMsg> ResultObjectMsgs =
                    GetResultFeatureMessages(
                        null, updatedFeatures,
                        f => GetNotifications(reshapedGeometries, f),
                        f => reshaper.NotificationIsWarning);

                response.ResultFeatures.AddRange(ResultObjectMsgs);
            }

            // Calculate new reshape lines based on current source and target states:
            CalculateReshapeLinesRequest calculationRequest = request.CalculationRequest;

            List <IFeature>  newSourceFeatures = reshaper.ReshapeGeometryCloneByFeature.Keys.ToList();
            IList <IFeature> newTargetFeatures =
                GetUpToDateTargets(reshaper, request.CalculationRequest);

            ReshapeAlongCurveUsability curveUsability;

            IList <CutSubcurve> newSubcurves =
                CalculateReshapeLines(newSourceFeatures, newTargetFeatures,
                                      calculationRequest, trackCancel, out curveUsability);

            response.ReshapeLinesUsability = (int)curveUsability;

            foreach (CutSubcurve resultCurve in newSubcurves)
            {
                response.NewReshapeLines.Add(ToReshapeLineMsg(resultCurve));
            }

            return(response);
        }
        public static AdvancedReshapeResponse Reshape(
            [NotNull] AdvancedReshapeRequest request)
        {
            var polyline = (IPolyline)ProtobufGeometryUtils.FromShapeMsg(request.ReshapePaths);

            List <IPath> reshapePaths = GeometryUtils.GetPaths(Assert.NotNull(polyline)).ToList();

            GeometryReshaperBase reshaper = CreateReshaper(request, reshapePaths);

            bool useNonDefaultReshapeSide = request.UseNonDefaultReshapeSide;

            var notifications = new NotificationCollection();

            IDictionary <IGeometry, NotificationCollection> reshapedGeometries =
                reshaper.Reshape(reshapePaths, useNonDefaultReshapeSide, notifications);

            Assert.NotNull(reshapedGeometries, "No reshaped geometries");

            if (reshapedGeometries.Count == 0)
            {
                return(NoReshapeResponse(notifications));
            }

            var response = new AdvancedReshapeResponse();

            if (reshaper.ResultWithinOtherResultButNotInOriginal(
                    reshapedGeometries.Keys, out IPolygon containedPolygon))
            {
                response.OverlapPolygon = ProtobufGeometryUtils.ToShapeMsg(containedPolygon);
            }

            // Messages regarding some of the features that were not reshaped:
            if (notifications.Count > 0 && request.Features.Count > 1)
            {
                string overallMessage = notifications.Concatenate(". ");

                _msg.Info(overallMessage);
                response.WarningMessage = overallMessage;
            }

            // Junction-move, updating of adjacent lines is performed in Save:
            IList <IFeature> storedFeatures = reshaper.Save(reshapedGeometries);

            response.OpenJawReshapeHappened   = reshaper.OpenJawReshapeOcurred;
            response.OpenJawIntersectionCount = reshaper.OpenJawIntersectionPointCount;

            PackReshapeResponseFeatures(response, storedFeatures, reshapedGeometries,
                                        reshaper.OpenJawReshapeOcurred,
                                        reshaper.NotificationIsWarning);

            return(response);
        }