private static AdvancedReshapeRequest CreateReshapeRequest(
            [NotNull] IList <Feature> selectedFeatures,
            [NotNull] Polyline reshapePath,
            [CanBeNull] IList <Feature> adjacentFeatures,
            bool allowOpenJaw, bool multiReshapeAsUnion, bool useNonDefaultSide)
        {
            var request = new AdvancedReshapeRequest();

            ProtobufConversionUtils.ToGdbObjectMsgList(selectedFeatures,
                                                       request.Features,
                                                       request.ClassDefinitions);

            ShapeMsg reshapePathMsg = ProtobufConversionUtils.ToShapeMsg(reshapePath);

            request.ReshapePaths             = reshapePathMsg;
            request.AllowOpenJawReshape      = allowOpenJaw;
            request.UseNonDefaultReshapeSide = useNonDefaultSide;
            request.MultipleSourcesTryUnion  = multiReshapeAsUnion;

            // TODO: from options
            request.MoveOpenJawEndJunction = true;

            if (adjacentFeatures != null)
            {
                ProtobufConversionUtils.ToGdbObjectMsgList(
                    adjacentFeatures, request.PotentiallyConnectedFeatures,
                    request.ClassDefinitions);
            }

            return(request);
        }
        public static ReshapeResult Reshape(
            [NotNull] ReshapeGrpc.ReshapeGrpcClient rpcClient,
            [NotNull] IList <Feature> selectedFeatures,
            [NotNull] Polyline reshapeLine,
            [CanBeNull] IList <Feature> adjacentFeatures,
            bool allowOpenJawReshape,
            bool multiReshapeAsUnion,
            bool tryReshapeNonDefault,
            CancellationToken cancellationToken)
        {
            var allInputFeatures = new Dictionary <GdbObjectReference, Feature>();

            AddInputFeatures(selectedFeatures, allInputFeatures);

            if (adjacentFeatures != null)
            {
                AddInputFeatures(adjacentFeatures, allInputFeatures);
            }

            AdvancedReshapeRequest request = CreateReshapeRequest(
                selectedFeatures, reshapeLine, adjacentFeatures, allowOpenJawReshape,
                multiReshapeAsUnion, tryReshapeNonDefault);

            return(Reshape(rpcClient, request, allInputFeatures, cancellationToken));
        }
        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);
        }
        public override async Task <AdvancedReshapeResponse> AdvancedReshape(
            AdvancedReshapeRequest request, ServerCallContext context)
        {
            Stopwatch watch = _msg.DebugStartTiming();

            Func <ITrackCancel, AdvancedReshapeResponse> func =
                trackCancel => AdvancedReshapeServiceUtils.Reshape(request);

            AdvancedReshapeResponse response =
                await GrpcServerUtils.ExecuteServiceCall(func, context, _staTaskScheduler, true) ??
                new AdvancedReshapeResponse();

            _msg.DebugStopTiming(watch, "Reshaped for peer {0} ({1} source features)",
                                 context.Peer, request.Features.Count);

            return(response);
        }
        private static ReshapeResult Reshape(
            [NotNull] ReshapeGrpc.ReshapeGrpcClient rpcClient,
            [NotNull] AdvancedReshapeRequest request,
            [NotNull] IReadOnlyDictionary <GdbObjectReference, Feature> allInputFeatures,
            CancellationToken cancellationToken)
        {
            request.AllowOpenJawReshape = true;

            const int deadlinePerFeature = 5000;

            AdvancedReshapeResponse reshapeResultMsg = RpcCallUtils.Try(
                o => rpcClient.AdvancedReshape(request, o),
                cancellationToken, deadlinePerFeature * request.Features.Count);

            if (reshapeResultMsg == null)
            {
                return(null);
            }

            var result = new ReshapeResult
            {
                OpenJawReshapeHappened   = reshapeResultMsg.OpenJawReshapeHappened,
                OpenJawIntersectionCount = reshapeResultMsg.OpenJawIntersectionCount,
                FailureMessage           = reshapeResultMsg.WarningMessage
            };

            if (reshapeResultMsg.ResultFeatures.Count == 0)
            {
                return(result);
            }

            foreach (ResultFeatureMsg resultFeatureMsg in reshapeResultMsg.ResultFeatures)
            {
                GdbObjectReference objRef = new GdbObjectReference(
                    resultFeatureMsg.UpdatedFeature.ClassHandle,
                    resultFeatureMsg.UpdatedFeature.ObjectId);

                Feature inputFeature = allInputFeatures[objRef];

                var reshapeResultFeature = new ReshapeResultFeature(inputFeature, resultFeatureMsg);

                result.ResultFeatures.Add(reshapeResultFeature);
            }

            return(result);
        }
        private static IList <IFeature> GetFeaturesToReshape(
            [NotNull] AdvancedReshapeRequest request,
            out GdbTableContainer container)
        {
            container = ProtobufConversionUtils.CreateGdbTableContainer(
                request.ClassDefinitions, null, out _);

            foreach (IDataset dataset in container.GetDatasets(esriDatasetType.esriDTAny))
            {
                if (dataset is IObjectClass objectClass)
                {
                    objectClass.AddField(FieldUtils.CreateOIDField());
                }
            }

            IList <IFeature> featuresToReshape =
                ProtobufConversionUtils.FromGdbObjectMsgList(request.Features, container);

            return(featuresToReshape);
        }
Exemple #7
0
        public void CanAdvancedReshapePolygon()
        {
            var fClass =
                new GdbFeatureClass(123, "TestFC", esriGeometryType.esriGeometryPolygon);

            var sr = SpatialReferenceUtils.CreateSpatialReference(
                WellKnownHorizontalCS.LV95,
                WellKnownVerticalCS.LN02);

            fClass.SpatialReference = sr;

            IPolygon polygon1 = GeometryFactory.CreatePolygon(
                GeometryFactory.CreatePoint(2600000, 1200000, sr),
                GeometryFactory.CreatePoint(2601000, 1201000, sr));

            polygon1.SpatialReference = sr;

            GdbFeature sourceFeature = new GdbFeature(42, fClass)
            {
                Shape = polygon1
            };

            IPath reshapePath = GeometryFactory.CreatePath(
                GeometryFactory.CreatePoint(2600500, 1200000, sr),
                GeometryFactory.CreatePoint(2600500, 1200500, sr),
                GeometryFactory.CreatePoint(2601000, 1200500, sr));

            reshapePath.SpatialReference = sr;

            IPolyline reshapePolyline = GeometryFactory.CreatePolyline(reshapePath);

            var sourceFeatureMsg = ProtobufGdbUtils.ToGdbObjectMsg(sourceFeature);
            var reshapePaths     = ProtobufGeometryUtils.ToShapeMsg(reshapePolyline);

            var objectClassMsg = ProtobufGdbUtils.ToObjectClassMsg(sourceFeature.Class);

            AdvancedReshapeRequest request = new AdvancedReshapeRequest()
            {
                ClassDefinitions =
                {
                    objectClassMsg
                },
                Features =
                {
                    sourceFeatureMsg
                },
                ReshapePaths = reshapePaths
            };

            AdvancedReshapeResponse response = AdvancedReshapeServiceUtils.Reshape(request);

            Assert.AreEqual(1, response.ResultFeatures.Count);

            GdbObjectMsg resultFeatureMsg = response.ResultFeatures[0].UpdatedFeature;

            Assert.AreEqual(sourceFeature.OID, resultFeatureMsg.ObjectId);
            Assert.AreEqual(sourceFeature.Class.ObjectClassID, resultFeatureMsg.ClassHandle);

            var resultPoly = (IPolygon)ProtobufGeometryUtils.FromShapeMsg(resultFeatureMsg.Shape);

            Assert.NotNull(resultPoly);

            double oneQuarter = 1000d * 1000d / 4d;

            Assert.AreEqual(3 * oneQuarter, ((IArea)resultPoly).Area);

            // Non-default side:
            request.UseNonDefaultReshapeSide = true;

            response = AdvancedReshapeServiceUtils.Reshape(request);

            Assert.AreEqual(1, response.ResultFeatures.Count);
            resultFeatureMsg = response.ResultFeatures[0].UpdatedFeature;

            resultPoly = (IPolygon)ProtobufGeometryUtils.FromShapeMsg(resultFeatureMsg.Shape);

            Assert.NotNull(resultPoly);

            Assert.AreEqual(oneQuarter, ((IArea)resultPoly).Area);
        }
Exemple #8
0
        public void CanAdvancedReshapePolyline()
        {
            var fClass =
                new GdbFeatureClass(123, "TestFC", esriGeometryType.esriGeometryPolyline);

            var sr = SpatialReferenceUtils.CreateSpatialReference(
                WellKnownHorizontalCS.LV95,
                WellKnownVerticalCS.LN02);

            fClass.SpatialReference = sr;

            IPolyline sourcePolyline = CreatePolyline(
                GeometryFactory.CreatePoint(2600500, 1200000, sr),
                GeometryFactory.CreatePoint(2600500, 1200500, sr),
                GeometryFactory.CreatePoint(2601000, 1200500, sr));

            GdbFeature sourceFeature =
                new GdbFeature(42, fClass)
            {
                Shape = sourcePolyline
            };

            IPolyline sourceAdjacentPolyline = CreatePolyline(
                GeometryFactory.CreatePoint(2601000, 1200500, sr),
                GeometryFactory.CreatePoint(2601500, 1200500, sr),
                GeometryFactory.CreatePoint(2601500, 1200000, sr));

            GdbFeature sourceAdjacentFeature =
                new GdbFeature(43, fClass)
            {
                Shape = sourceAdjacentPolyline
            };

            IPolyline reshapePolyline = CreatePolyline(
                GeometryFactory.CreatePoint(2600500, 1200500, sr),
                GeometryFactory.CreatePoint(2600500, 1201000, sr));

            var sourceFeatureMsg         = ProtobufGdbUtils.ToGdbObjectMsg(sourceFeature);
            var reshapePaths             = ProtobufGeometryUtils.ToShapeMsg(reshapePolyline);
            var sourceAdjacentFeatureMsg = ProtobufGdbUtils.ToGdbObjectMsg(sourceAdjacentFeature);

            var objectClassMsg = ProtobufGdbUtils.ToObjectClassMsg(sourceFeature.Class);

            AdvancedReshapeRequest request = new AdvancedReshapeRequest()
            {
                ClassDefinitions =
                {
                    objectClassMsg
                },
                Features =
                {
                    sourceFeatureMsg
                },
                ReshapePaths                 = reshapePaths,
                AllowOpenJawReshape          = true,
                MoveOpenJawEndJunction       = true,
                PotentiallyConnectedFeatures =
                {
                    sourceAdjacentFeatureMsg
                }
            };

            AdvancedReshapeResponse response = AdvancedReshapeServiceUtils.Reshape(request);

            Assert.AreEqual(2, response.ResultFeatures.Count);

            GdbObjectMsg resultFeatureMsg = response.ResultFeatures[1].UpdatedFeature;

            Assert.AreEqual(sourceFeature.OID, resultFeatureMsg.ObjectId);
            Assert.AreEqual(sourceFeature.Class.ObjectClassID, resultFeatureMsg.ClassHandle);

            var resultPolyline =
                (IPolyline)ProtobufGeometryUtils.FromShapeMsg(resultFeatureMsg.Shape);

            Assert.NotNull(resultPolyline);

            Assert.IsTrue(GeometryUtils.AreEqual(resultPolyline.ToPoint, reshapePolyline.ToPoint));

            GdbObjectMsg resultAdjacentFeatureMsg = response.ResultFeatures[0].UpdatedFeature;
            var          resultAdjacentPolyline   =
                (IPolyline)ProtobufGeometryUtils.FromShapeMsg(resultAdjacentFeatureMsg.Shape);

            Assert.NotNull(resultAdjacentPolyline);
            Assert.IsTrue(
                GeometryUtils.AreEqual(resultAdjacentPolyline.FromPoint, reshapePolyline.ToPoint));

            // Non-default side:
            request.UseNonDefaultReshapeSide = true;

            response = AdvancedReshapeServiceUtils.Reshape(request);

            Assert.AreEqual(1, response.ResultFeatures.Count);
            resultFeatureMsg = response.ResultFeatures[0].UpdatedFeature;

            resultPolyline = (IPolyline)ProtobufGeometryUtils.FromShapeMsg(resultFeatureMsg.Shape);

            Assert.NotNull(resultPolyline);

            Assert.IsTrue(
                GeometryUtils.AreEqual(resultPolyline.FromPoint, reshapePolyline.ToPoint));
        }
        private static GeometryReshaperBase CreateReshaper(
            AdvancedReshapeRequest request, IList <IPath> reshapePaths)
        {
            GeometryReshaperBase result;

            bool allowOpenJaw           = request.AllowOpenJawReshape;
            bool moveOpenJawEndJunction = request.MoveOpenJawEndJunction;

            IList <IFeature> featuresToReshape =
                GetFeaturesToReshape(request, out GdbTableContainer container);

            if (featuresToReshape.Count == 1)
            {
                IFeature firstFeature = featuresToReshape[0];

                var singleGeometryReshaper =
                    new GeometryReshaper(firstFeature)
                {
                    AllowOpenJawReshape = allowOpenJaw
                };

                result = singleGeometryReshaper;
            }
            else
            {
                var stickyIntersections = new StickyIntersections(featuresToReshape);

                foreach (SourceTargetPointPair pair in request.StickyIntersections)
                {
                    stickyIntersections.SourceTargetPairs.Add(
                        new KeyValuePair <IPoint, IPoint>(
                            (IPoint)ProtobufGeometryUtils.FromShapeMsg(
                                pair.SourcePoint),
                            (IPoint)ProtobufGeometryUtils.FromShapeMsg(
                                pair.TargetPoint)));
                }

                result = new MultipleGeometriesReshaper(featuresToReshape)
                {
                    MultipleSourcesTreatIndividually = true,
                    MultipleSourcesTreatAsUnion      =
                        request.MultipleSourcesTryUnion,
                    MaxProlongationLengthFactor = 4,
                    StickyIntersectionPoints    = stickyIntersections
                };

                // Conditions for closed reshape paths being removed:
                // - multiple source geometries, at least two of which polygons
                // - multiple reshape paths (or a single closed path)
                // ... consider checking that the ring-path is completely inside the outermost ring of the source polygon's union
                //     or at least that several polygons are intersected by the sketch geometry
                if ((reshapePaths.Count > 1) || reshapePaths.All(path => path.IsClosed))
                {
                    if (ContainsMultiplePolygonFeatures(featuresToReshape))
                    {
                        result.RemoveClosedReshapePathAreas = true;
                    }
                }
            }

            if (moveOpenJawEndJunction)
            {
                IList <IFeature> targetCandidates = ProtobufConversionUtils.FromGdbObjectMsgList(
                    request.PotentiallyConnectedFeatures, container);

                result.NetworkFeatureFinder =
                    new LinearNetworkGdbFeatureFinder(targetCandidates);

                result.NetworkFeatureUpdater =
                    new LinearNetworkNodeUpdater(result.NetworkFeatureFinder);
            }

            result.MoveLineEndJunction = moveOpenJawEndJunction;

            // TODO: Add to admin-options (i.e. central defaults only, no GUI) together with the threshold
            // _useSimplifiedReshapeSideDeterminationVertexThreshold in ReshapeInfo
            result.AllowSimplifiedReshapeSideDetermination = true;

            return(result);
        }