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); }
/// <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"); } }
/// <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; } }
/// <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; } }