Beispiel #1
0
        public async Task <CellPassesResponse> ExecuteAsync(CellPassesRequestArgument_ApplicationService arg)
        {
            var result = new CellPassesResponse()
            {
                ReturnCode = CellPassesReturnCode.Error
            };

            if (arg.Filters?.Filters != null && arg.Filters.Filters.Length > 0)
            {
                // Prepare the filters for use in cell passes operations. Failure to prepare any filter results in this request terminating
                if (!arg.Filters.Filters.Select(x => FilterUtilities.PrepareFilterForUse(x, arg.ProjectID)).All(x => x == RequestErrorStatus.OK))
                {
                    return(new CellPassesResponse {
                        ReturnCode = CellPassesReturnCode.FailedToPrepareFilter
                    });
                }
            }

            var siteModel = DIContext.Obtain <ISiteModels>().GetSiteModel(arg.ProjectID);

            if (siteModel == null)
            {
                _log.LogError($"Failed to locate site model {arg.ProjectID}");
                return(result);
            }

            if (!arg.CoordsAreGrid)
            {
                //WGS84 coords need to be converted to NEE
                var pointToConvert = new XYZ(arg.Point.X, arg.Point.Y, 0);
                arg.Point       = DIContext.Obtain <ICoreXWrapper>().LLHToNEE(siteModel.CSIB(), pointToConvert.ToCoreX_XYZ(), CoreX.Types.InputAs.Radians).ToTRex_XYZ();
                result.Northing = arg.Point.Y;
                result.Easting  = arg.Point.X;
            }

            var existenceMap = siteModel.ExistenceMap;

            // Determine the on-the-ground cell
            siteModel.Grid.CalculateIndexOfCellContainingPosition(arg.Point.X,
                                                                  arg.Point.Y,
                                                                  out var otgCellX,
                                                                  out var otgCellY);

            if (!existenceMap[otgCellX >> SubGridTreeConsts.SubGridIndexBitsPerLevel, otgCellY >> SubGridTreeConsts.SubGridIndexBitsPerLevel])
            {
                result.ReturnCode = CellPassesReturnCode.NoDataFound;
                return(result);
            }

            var computeArg      = new CellPassesRequestArgument_ClusterCompute(arg.ProjectID, arg.Point, otgCellX, otgCellY, arg.Filters);
            var requestCompute  = new CellPassesRequest_ClusterCompute();
            var affinityKey     = new SubGridSpatialAffinityKey(SubGridSpatialAffinityKey.DEFAULT_SPATIAL_AFFINITY_VERSION_NUMBER_TICKS, arg.ProjectID, otgCellX, otgCellY);
            var responseCompute = await requestCompute.ExecuteAsync(computeArg, affinityKey);

            result.ReturnCode = responseCompute.ReturnCode;
            result.CellPasses = responseCompute.CellPasses;

            return(result);
        }
Beispiel #2
0
        /// <summary>
        /// Executes the profiler
        /// </summary>
        public async Task <ProfileRequestResponse <T> > ExecuteAsync(ProfileRequestArgument_ApplicationService arg)
        {
            _log.LogInformation("Start execution");

            try
            {
                if (arg.Filters?.Filters != null && arg.Filters.Filters.Length > 0)
                {
                    // Prepare the filters for use in profiling operations. Failure to prepare any filter results in this request terminating
                    if (!arg.Filters.Filters.Select(x => FilterUtilities.PrepareFilterForUse(x, arg.ProjectID)).All(x => x == RequestErrorStatus.OK))
                    {
                        return(new ProfileRequestResponse <T> {
                            ResultStatus = RequestErrorStatus.FailedToPrepareFilter
                        });
                    }
                }

                var arg2 = new ProfileRequestArgument_ClusterCompute
                {
                    ProfileTypeRequired      = arg.ProfileTypeRequired,
                    ProfileStyle             = arg.ProfileStyle,
                    ProjectID                = arg.ProjectID,
                    Filters                  = arg.Filters,
                    ReferenceDesign          = arg.ReferenceDesign,
                    ReturnAllPassesAndLayers = arg.ReturnAllPassesAndLayers,
                    TRexNodeID               = arg.TRexNodeID,
                    VolumeType               = arg.VolumeType,
                    Overrides                = arg.Overrides,
                    LiftParams               = arg.LiftParams
                };

                // Perform coordinate conversion on the argument before broadcasting it:
                if (arg.PositionsAreGrid)
                {
                    arg2.NEECoords = new[] { arg.StartPoint, arg.EndPoint }.Select(x => new XYZ(x.Lon, x.Lat)).ToArray();
                }
                else
                {
                    var siteModel = DIContext.Obtain <ISiteModels>().GetSiteModel(arg.ProjectID);

                    if (siteModel != null)
                    {
                        arg2.NEECoords = DIContext.Obtain <ICoreXWrapper>().WGS84ToCalibration(
                            siteModel.CSIB(),
                            new[] { arg.StartPoint, arg.EndPoint }
                            .ToCoreX_WGS84Point(),
                            CoreX.Types.InputAs.Radians)
                                         .ToTRex_XYZ();
                    }
                }

                var request         = new ProfileRequest_ClusterCompute <T>();
                var profileResponse = await request.ExecuteAsync(arg2);

                profileResponse.GridDistanceBetweenProfilePoints = MathUtilities.Hypot(arg2.NEECoords[1].X - arg2.NEECoords[0].X, arg2.NEECoords[1].Y - arg2.NEECoords[0].Y);

                //... and then sort them to get the final result, as well as removing initial and duplicate null values
                // Remove null cells in the profiles list. Null cells are defined by cells with null CellLastHeight.
                // All duplicate null cells will be replaced by a by single null cell entry
                int firstNonNullIndex = 0;
                var _profileCells     = profileResponse?.ProfileCells?.OrderBy(x => x.Station).ToList();
                if (_profileCells != null)
                {
                    profileResponse.ProfileCells = _profileCells.Where((x, i) =>
                    {
                        // Remove all leading nulls
                        if (_profileCells[i].IsNull() && i == firstNonNullIndex)
                        {
                            firstNonNullIndex++;
                            return(false);
                        }

                        // Collapse all interior nulls to single nulls, unless the null is at the end. Leave any single terminating null
                        return(i == 0 || !_profileCells[i].IsNull() || (_profileCells[i].IsNull() && !_profileCells[i - 1].IsNull()));
                    }).ToList();
                }

                // Return the care package to the caller
                return(profileResponse);
            }
            finally
            {
                _log.LogInformation("End execution");
            }
        }
Beispiel #3
0
        /// <summary>
        /// Builds the pipeline configured per the supplied state ready to execute the request
        /// </summary>
        public bool Build()
        {
            // Todo: This method is left as async as a reminder that the GetExistenveMap workflows could either be async (as they
            // potentially read from the persistent store), and/or they couild be cached in the site model designs/surveyed surfaces contexts
            // See Jira CCSSSCON-1481
            try
            {
                var stopWatch = Stopwatch.StartNew();

                // Ensure the task is initialised with the request descriptor
                Task.RequestDescriptor = RequestDescriptor;

                // Ensure the Task grid data type matches the pipeline processor
                Task.GridDataType = GridDataType;

                // Introduce the task and the pipeline to each other
                Pipeline.PipelineTask = Task;
                Task.PipeLine         = Pipeline;

                (Pipeline as ISubGridPipelineBase <TSubGridsRequestArgument>).CustomArgumentInitializer = CustomArgumentInitializer;

                if ((Filters?.Filters?.Length ?? 0) == 0)
                {
                    _log.LogError($"Filters supplied to pipeline processor is null or empty, replacing with single default filter");
                    Filters = new FilterSet(new CombinedFilter());
                }

                // Construct an aggregated set of excluded surveyed surfaces for the filters used in the query
                foreach (var filter in Filters.Filters)
                {
                    if (filter != null && SurveyedSurfaceExclusionList.Length > 0)
                    {
                        SurveyedSurfaceExclusionList = new Guid[filter.AttributeFilter.SurveyedSurfaceExclusionList.Length];
                        Array.Copy(filter.AttributeFilter.SurveyedSurfaceExclusionList, SurveyedSurfaceExclusionList,
                                   SurveyedSurfaceExclusionList.Length);
                    }
                }

                // Get the SiteModel for the request
                SiteModel = DIContext.Obtain <ISiteModels>().GetSiteModel(DataModelID);
                if (SiteModel == null)
                {
                    Response.ResultStatus = RequestErrorStatus.NoSuchDataModel;
                    return(false);
                }

                SpatialExtents = SiteModel.GetAdjustedDataModelSpatialExtents(SurveyedSurfaceExclusionList);

                if (!SpatialExtents.IsValidPlanExtent)
                {
                    Response.ResultStatus = RequestErrorStatus.FailedToRequestDatamodelStatistics; // Or there was no data in the model
                    return(false);
                }

                // Get the current production data existence map from the site model
                ProdDataExistenceMap = SiteModel.ExistenceMap;

                // Obtain the sub grid existence map for the project
                // Retrieve the existence map for the datamodel
                OverallExistenceMap = new SubGridTreeSubGridExistenceBitMask {
                    CellSize = SubGridTreeConsts.SubGridTreeDimension * SiteModel.CellSize
                };

                if (RequireSurveyedSurfaceInformation)
                {
                    // Obtain local reference to surveyed surfaces (lock free access)
                    var localSurveyedSurfaces = SiteModel.SurveyedSurfaces;

                    if (localSurveyedSurfaces != null)
                    {
                        // Construct two filtered surveyed surface lists to act as a rolling pair used as arguments
                        // to the ProcessSurveyedSurfacesForFilter method
                        var filterSurveyedSurfaces   = DIContext.Obtain <ISurveyedSurfaces>();
                        var filteredSurveyedSurfaces = DIContext.Obtain <ISurveyedSurfaces>();

                        SurveyedSurfacesExcludedViaTimeFiltering = Filters.Filters.Length > 0;

                        foreach (var filter in Filters.Filters)
                        {
                            if (!localSurveyedSurfaces.ProcessSurveyedSurfacesForFilter(DataModelID, filter,
                                                                                        filteredSurveyedSurfaces, filterSurveyedSurfaces, OverallExistenceMap))
                            {
                                Response.ResultStatus = RequestErrorStatus.FailedToRequestSubgridExistenceMap;
                                return(false);
                            }

                            SurveyedSurfacesExcludedViaTimeFiltering &= filterSurveyedSurfaces.Count == 0;
                        }
                    }
                }

                OverallExistenceMap.SetOp_OR(ProdDataExistenceMap);

                foreach (var filter in Filters.Filters)
                {
                    if (filter != null)
                    {
                        if (!DesignFilterUtilities.ProcessDesignElevationsForFilter(SiteModel, filter, OverallExistenceMap))
                        {
                            Response.ResultStatus = RequestErrorStatus.NoDesignProvided;
                            return(false);
                        }

                        Response.ResultStatus = FilterUtilities.PrepareFilterForUse(filter, DataModelID);
                        if (Response.ResultStatus != RequestErrorStatus.OK)
                        {
                            _log.LogInformation($"PrepareFilterForUse failed: Datamodel={DataModelID}");
                            return(false);
                        }
                    }
                }

                // Adjust the extents we have been given to encompass the spatial extent of the supplied filters (if any)
                Filters.ApplyFilterAndSubsetBoundariesToExtents(SpatialExtents);

                // If this request involves a relationship with a design then ensure the existence map
                // for the design is loaded in to memory to allow the request pipeline to confine
                // sub grid requests that overlay the actual design
                if (RequestRequiresAccessToDesignFileExistenceMap)
                {
                    if (CutFillDesign == null || CutFillDesign.DesignID == Guid.Empty)
                    {
                        _log.LogError($"No design provided to cut fill, summary volume or thickness overlay render request for datamodel {DataModelID}");
                        Response.ResultStatus = RequestErrorStatus.NoDesignProvided;
                        return(false);
                    }

                    DesignSubGridOverlayMap = GetExistenceMaps().GetSingleExistenceMap(DataModelID, Consts.EXISTENCE_MAP_DESIGN_DESCRIPTOR, CutFillDesign.DesignID);

                    if (DesignSubGridOverlayMap == null)
                    {
                        _log.LogError($"Failed to request sub grid overlay index for design {CutFillDesign.DesignID} in datamodel {DataModelID}");
                        Response.ResultStatus = RequestErrorStatus.NoDesignProvided;
                        return(false);
                    }

                    DesignSubGridOverlayMap.CellSize = SubGridTreeConsts.SubGridTreeDimension * SiteModel.CellSize;
                }

                // Impose the final restriction on the spatial extents from the client context
                SpatialExtents.Intersect(OverrideSpatialExtents);

                // Introduce the Request analyzer to the pipeline and spatial extents it requires
                RequestAnalyser.Pipeline     = Pipeline;
                RequestAnalyser.WorldExtents = SpatialExtents;

                ConfigurePipeline();

                _log.LogInformation($"Pipeline processor build phase completed in {stopWatch.Elapsed}");

                return(true);
            }
            catch (Exception e)
            {
                _log.LogError(e, "Exception occurred in pipeline builder");
                throw;
            }
        }
Beispiel #4
0
        /// <summary>
        /// Executes the profiler
        /// </summary>
        public async Task <StationOffsetReportRequestResponse_ApplicationService> ExecuteAsync(StationOffsetReportRequestArgument_ApplicationService arg)
        {
            _log.LogInformation($"Start {nameof(ComputeStationOffsetReportExecutor_ApplicationService)}");

            try
            {
                if (arg.Filters?.Filters != null && arg.Filters.Filters.Length > 0)
                {
                    // Prepare the filters for use in stationOffset operations. Failure to prepare any filter results in this request terminating
                    if (!(arg.Filters.Filters.Select(x => FilterUtilities.PrepareFilterForUse(x, arg.ProjectID)).All(x => x == RequestErrorStatus.OK)))
                    {
                        return(new StationOffsetReportRequestResponse_ApplicationService {
                            ResultStatus = RequestErrorStatus.FailedToPrepareFilter
                        });
                    }
                }

                // keep alignment design knowledge here and pass points
                var argClusterCompute = new StationOffsetReportRequestArgument_ClusterCompute
                {
                    ProjectID         = arg.ProjectID,
                    Filters           = arg.Filters,
                    ReferenceDesign   = arg.ReferenceDesign,
                    TRexNodeID        = arg.TRexNodeID,
                    ReportElevation   = arg.ReportElevation,
                    ReportCmv         = arg.ReportCmv,
                    ReportMdp         = arg.ReportMdp,
                    ReportPassCount   = arg.ReportPassCount,
                    ReportTemperature = arg.ReportTemperature,
                    ReportCutFill     = arg.ReportCutFill,
                    Points            = new List <StationOffsetPoint>(),
                    Overrides         = arg.Overrides,
                    LiftParams        = arg.LiftParams
                };

                var siteModel   = DIContext.ObtainRequired <ISiteModels>().GetSiteModel(arg.ProjectID);
                var designFiles = DIContext.ObtainRequired <IDesignFiles>();

                // alignment will convert interval/offsets into northing/eastings for the project
                var alignmentDesign = designFiles.Lock(arg.AlignmentDesignUid, siteModel, siteModel.CellSize, out var loadResult) as SVLAlignmentDesign;

                if (alignmentDesign == null || loadResult != DesignLoadResult.Success)
                {
                    return(new StationOffsetReportRequestResponse_ApplicationService {
                        ReturnCode = ReportReturnCode.NoData, ResultStatus = RequestErrorStatus.NoDesignProvided
                    });
                }

                try
                {
                    argClusterCompute.Points = alignmentDesign.GetOffsetPointsInNEE(arg.CrossSectionInterval, arg.StartStation, arg.EndStation, arg.Offsets, out var calcResult);

                    _log.LogInformation($"{nameof(StationOffsetReportRequestResponse_ApplicationService)}: pointCount: {argClusterCompute.Points.Count}, calcResult: {calcResult}");

                    if (argClusterCompute.Points.Count == 0)
                    {
                        return(new StationOffsetReportRequestResponse_ApplicationService {
                            ReturnCode = ReportReturnCode.NoData, ResultStatus = RequestErrorStatus.NoProductionDataFound
                        });
                    }
                }
                finally
                {
                    designFiles.UnLock(arg.AlignmentDesignUid, alignmentDesign);
                }

                var request = new StationOffsetReportRequest_ClusterCompute();
                var clusterComputeResponse = await request.ExecuteAsync(argClusterCompute);

                // Return the core package to the caller
                var applicationResponse = new StationOffsetReportRequestResponse_ApplicationService
                {
                    ReturnCode   = clusterComputeResponse.ReturnCode,
                    ResultStatus = clusterComputeResponse.ResultStatus
                };
                applicationResponse.LoadStationOffsets(clusterComputeResponse.StationOffsetRows);

                _log.LogInformation($"End {nameof(ComputeStationOffsetReportExecutor_ApplicationService)}: ReturnCode {applicationResponse.ReturnCode}.");
                return(applicationResponse);
            }
            catch (Exception e)
            {
                _log.LogError(e, $"{nameof(StationOffsetReportRequestResponse_ApplicationService)}: Unexpected exception.");
                throw;
            }
        }