public void Test_RequestorUtilities_CreateIntermediaries_SingleDefaultFilter_WithSurveyedSurfaces() { var ru = new RequestorUtilities(); Guid ssGuid = Guid.NewGuid(); ISurveyedSurfaces surveyedSurfaces = DIContext.Obtain <ISurveyedSurfaces>(); surveyedSurfaces.AddSurveyedSurfaceDetails(ssGuid, DesignDescriptor.Null(), TRex.Common.Consts.MIN_DATETIME_AS_UTC, BoundingWorldExtent3D.Null()); var mockGrid = new Mock <IServerSubGridTree>(); mockGrid.Setup(x => x.CellSize).Returns(SubGridTreeConsts.DefaultCellSize); var mockSiteModel = new Mock <ISiteModel>(); mockSiteModel.Setup(x => x.SurveyedSurfacesLoaded).Returns(true); mockSiteModel.Setup(x => x.SurveyedSurfaces).Returns(surveyedSurfaces); mockSiteModel.Setup(x => x.Grid).Returns(mockGrid.Object); ICombinedFilter filter = new CombinedFilter(); IFilterSet filters = new FilterSet(filter); var intermediaries = ru.ConstructRequestorIntermediaries(mockSiteModel.Object, filters, true, GridDataType.Height); intermediaries.Length.Should().Be(1); intermediaries[0].Filter.Should().Be(filter); intermediaries[0].FilteredSurveyedSurfaces.Should().Equal(surveyedSurfaces); intermediaries[0].CacheContexts[0].Should().Be(_fixture.TRexSpatialMemoryCacheContext); intermediaries[0].surfaceElevationPatchRequest.Should().Be(_fixture.SurfaceElevationPatchRequest); }
/// <summary> /// Add a new surveyed surface to a site model via direct manipulation of the information in the grid /// </summary> /// <param name="SiteModelID"></param> /// <param name="designDescriptor"></param> /// <param name="asAtDate"></param> /// <param name="extents"></param> /// <param name="SuveyedSurfaceID"></param> public void AddDirect(Guid SiteModelID, DesignDescriptor designDescriptor, DateTime asAtDate, BoundingWorldExtent3D extents, out Guid SurveyedSurfaceID) { // This should be done under a lock on the cache key. For now, we will live with the race condition... INonSpatialAffinityKey cacheKey = CacheKey(SiteModelID); SurveyedSurfaceID = Guid.NewGuid(); // Get the surveyed surfaces, creating it if it does not exist ISurveyedSurfaces ssList = DIContext.Obtain <ISurveyedSurfaces>(); try { ssList.FromBytes(mutableNonSpatialCache.Get(cacheKey)); } catch (KeyNotFoundException) { // Swallow exception, the list will be empty } // Add the new surveyed surface, generating a random ID from a GUID ssList.AddSurveyedSurfaceDetails(SurveyedSurfaceID, designDescriptor, asAtDate, extents); // Put the list back into the cache with the new entry mutableNonSpatialCache.Put(cacheKey, ssList.ToBytes()); }
public void Test_RequestorUtilities_CreateIntermediaries_MultipleDefaultFilters_WithSurveyedSurfaces(int filterCount) { var ru = new RequestorUtilities(); Guid ssGuid = Guid.NewGuid(); ISurveyedSurfaces surveyedSurfaces = DIContext.Obtain <ISurveyedSurfaces>(); surveyedSurfaces.AddSurveyedSurfaceDetails(ssGuid, DesignDescriptor.Null(), Consts.MIN_DATETIME_AS_UTC, BoundingWorldExtent3D.Null()); var mockGrid = new Mock <IServerSubGridTree>(); mockGrid.Setup(x => x.CellSize).Returns(SubGridTreeConsts.DefaultCellSize); var mockSiteModel = new Mock <ISiteModel>(); mockSiteModel.Setup(x => x.SurveyedSurfacesLoaded).Returns(true); mockSiteModel.Setup(x => x.SurveyedSurfaces).Returns(surveyedSurfaces); mockSiteModel.Setup(x => x.Grid).Returns(mockGrid.Object); ICombinedFilter[] filters = Enumerable.Range(1, filterCount).Select(x => new CombinedFilter()).ToArray(); IFilterSet filterSet = new FilterSet(filters); var intermediaries = ru.ConstructRequestorIntermediaries(mockSiteModel.Object, filterSet, true, GridDataType.Height); intermediaries.Length.Should().Be(filters.Length); for (int i = 0; i < intermediaries.Length; i++) { intermediaries[i].Filter.Should().Be(filters[i]); intermediaries[i].FilteredSurveyedSurfaces.Should().Equal(surveyedSurfaces); intermediaries[i].CacheContexts[0].Should().NotBeNull(); intermediaries[i].surfaceElevationPatchRequest.Should().Be(_fixture.SurfaceElevationPatchRequest); } }
public void Test_RequestorUtilities_CreateRequestors_DefaultFilters(int filterCount) { var ru = new RequestorUtilities(); ISurveyedSurfaces surveyedSurfaces = DIContext.Obtain <ISurveyedSurfaces>(); // Create two surveyed surfaces that bracket current time by one day either side and set the filter end time to be current time // which will cause only one surveyed surface to be filtered Guid ssGuid1 = Guid.NewGuid(); var ss1 = surveyedSurfaces.AddSurveyedSurfaceDetails(ssGuid1, DesignDescriptor.Null(), Consts.MIN_DATETIME_AS_UTC, BoundingWorldExtent3D.Null()); var mockGrid = new Mock <IServerSubGridTree>(); mockGrid.Setup(x => x.CellSize).Returns(SubGridTreeConsts.DefaultCellSize); var mockSiteModel = new Mock <ISiteModel>(); mockSiteModel.Setup(x => x.SurveyedSurfacesLoaded).Returns(true); mockSiteModel.Setup(x => x.SurveyedSurfaces).Returns(surveyedSurfaces); mockSiteModel.Setup(x => x.Grid).Returns(mockGrid.Object); ICombinedFilter[] filters = Enumerable.Range(1, filterCount).Select(x => new CombinedFilter()).ToArray(); IFilterSet filterSet = new FilterSet(filters); var intermediaries = ru.ConstructRequestorIntermediaries(mockSiteModel.Object, filterSet, true, GridDataType.Height); var requestors = ru.ConstructRequestors(new SubGridsRequestArgument(), mockSiteModel.Object, new OverrideParameters(), new LiftParameters(), intermediaries, AreaControlSet.CreateAreaControlSet(), null); requestors.Length.Should().Be(filters.Length); for (var i = 0; i < requestors.Length; i++) { requestors[i].CellOverrideMask.Should().NotBe(null); } }
/// <summary> /// Remove a given surveyed surface from a site model /// </summary> /// <param name="SiteModelID"></param> /// <param name="SurveySurfaceID"></param> /// <returns></returns> public bool RemoveDirect(Guid SiteModelID, Guid SurveySurfaceID) { // TODO: This should be done under a lock on the cache key. For now, we will live with the race condition try { INonSpatialAffinityKey cacheKey = CacheKey(SiteModelID); // Get the surveyed surfaces, creating it if it does not exist ISurveyedSurfaces ssList = DIContext.Obtain <ISurveyedSurfaces>(); ssList.FromBytes(mutableNonSpatialCache.Get(cacheKey)); // Add the new surveyed surface, generating a random ID from a GUID bool result = ssList.RemoveSurveyedSurface(SurveySurfaceID); // Put the list back into the cache with the new entry if (result) { mutableNonSpatialCache.Put(cacheKey, ssList.ToBytes()); } return(result); } catch (KeyNotFoundException) { return(false); } }
public void Assign(ISurveyedSurfaces source) { Clear(); foreach (var ss in source) { Add(ss); // formerly Add(ss.Clone()); } }
public void Test_RequestorUtilities_CreateIntermediaries_MultipleFilters_WithOneOfTwoSurveyedSurfacesFilteredByTime_NoSurveyedSurfaceExclusions(int filterCount) { var ru = new RequestorUtilities(); ISurveyedSurfaces surveyedSurfaces = DIContext.Obtain <ISurveyedSurfaces>(); // Create two surveyed surfaces that bracket current time by one day either side and set the filter end time to be current time // which will cause only one surveyed surface to be filtered Guid ssGuid1 = Guid.NewGuid(); var ss1 = surveyedSurfaces.AddSurveyedSurfaceDetails(ssGuid1, DesignDescriptor.Null(), DateTime.UtcNow.AddDays(-1), BoundingWorldExtent3D.Null()); Guid ssGuid2 = Guid.NewGuid(); var ss2 = surveyedSurfaces.AddSurveyedSurfaceDetails(ssGuid2, DesignDescriptor.Null(), DateTime.UtcNow.AddDays(+1), BoundingWorldExtent3D.Null()); var mockGrid = new Mock <IServerSubGridTree>(); mockGrid.Setup(x => x.CellSize).Returns(SubGridTreeConsts.DefaultCellSize); var mockSiteModel = new Mock <ISiteModel>(); mockSiteModel.Setup(x => x.SurveyedSurfacesLoaded).Returns(true); mockSiteModel.Setup(x => x.SurveyedSurfaces).Returns(surveyedSurfaces); mockSiteModel.Setup(x => x.Grid).Returns(mockGrid.Object); ICombinedFilter[] filters = Enumerable.Range(1, filterCount).Select(x => { var filter = new CombinedFilter { AttributeFilter = { HasTimeFilter = true, StartTime = Consts.MIN_DATETIME_AS_UTC, EndTime = DateTime.UtcNow } }; return(filter); }).ToArray(); IFilterSet filterSet = new FilterSet(filters); var intermediaries = ru.ConstructRequestorIntermediaries(mockSiteModel.Object, filterSet, true, GridDataType.Height); intermediaries.Length.Should().Be(filters.Length); for (int i = 0; i < intermediaries.Length; i++) { intermediaries[i].Filter.Should().Be(filters[i]); intermediaries[i].FilteredSurveyedSurfaces.Should().Equal(new List <ISurveyedSurface> { ss1 }); intermediaries[i].CacheContexts[0].Should().NotBeNull(); intermediaries[i].surfaceElevationPatchRequest.Should().Be(_fixture.SurfaceElevationPatchRequest); } }
ITRexSpatialMemoryCacheContext[] CacheContexts) GetIntermediary(ICombinedFilter filter) { // Construct the appropriate list of surveyed surfaces // Obtain local reference to surveyed surface list. If it is replaced while processing the // list then the local reference will still be valid allowing lock free read access to the list. ISurveyedSurfaces filteredSurveyedSurfaces = null; var surveyedSurfaceList = siteModel.SurveyedSurfaces; if (includeSurveyedSurfaceInformation && surveyedSurfaceList?.Count > 0) { filteredSurveyedSurfaces = DIContext.Obtain <ISurveyedSurfaces>(); // Filter out any surveyed surfaces which don't match current filter (if any) - realistically, this is time filters we're thinking of here surveyedSurfaceList.FilterSurveyedSurfaceDetails(filter.AttributeFilter.HasTimeFilter, filter.AttributeFilter.StartTime, filter.AttributeFilter.EndTime, filter.AttributeFilter.ExcludeSurveyedSurfaces(), filteredSurveyedSurfaces, filter.AttributeFilter.SurveyedSurfaceExclusionList); // Ensure that the filtered surveyed surfaces are in a known ordered state filteredSurveyedSurfaces.SortChronologically(filter.AttributeFilter.ReturnEarliestFilteredCellPass); } var filteredSurveyedSurfacesAsArray = filteredSurveyedSurfaces?.Count > 0 ? filteredSurveyedSurfaces.Select(s => s.ID).ToArray() : new Guid[0]; // Get a caching context for the sub grids returned by this requester, but only if the requested grid data type supports it ITRexSpatialMemoryCacheContext[] subGridCacheContexts = null; if (_enableGeneralSubGridResultCaching && ClientLeafSubGrid.SupportsAssignationFromCachedPreProcessedClientSubGrid[(int)gridDataType]) { filter.AttributeFilter.SiteModel = siteModel; var contextType1 = Utilities.IntermediaryICGridDataTypeForDataType(gridDataType, true); var contextType2 = Utilities.IntermediaryICGridDataTypeForDataType(gridDataType, false); var context1 = SubGridCache?.LocateOrCreateContext(siteModel.ID, contextType1, SpatialCacheFingerprint.ConstructFingerprint(siteModel.ID, contextType1, filter, filteredSurveyedSurfacesAsArray)); var context2 = SubGridCache?.LocateOrCreateContext(siteModel.ID, contextType2, SpatialCacheFingerprint.ConstructFingerprint(siteModel.ID, contextType2, filter, filteredSurveyedSurfacesAsArray)); subGridCacheContexts = new[] { context1, context2 }.Where(x => x != null).ToArray(); } return(gridDataType, filter, filteredSurveyedSurfaces, _surfaceElevationPatchRequestFactory(SubGridCache, SubGridCache?.LocateOrCreateContext(siteModel.ID, GridDataType.SurveyedSurfaceHeightAndTime, SpatialCacheFingerprint.ConstructFingerprint(siteModel.ID, GridDataType.SurveyedSurfaceHeightAndTime, null, filteredSurveyedSurfaces?.Select(x => x.ID).ToArray() ?? new Guid[0]))), subGridCacheContexts); }
/// <summary> /// Stores the list of surveyed surfaces for a site model /// </summary> private void Store(Guid siteModelUid, ISurveyedSurfaces surveyedSurfaces) { using var stream = surveyedSurfaces.ToStream(); if (_writeStorageProxy.WriteStreamToPersistentStore(siteModelUid, SURVEYED_SURFACE_STREAM_NAME, FileSystemStreamType.SurveyedSurfaces, stream, this) == FileSystemErrorStatus.OK) { _writeStorageProxy.Commit(); } // Notify the grid listeners that attributes of this site model have changed. var sender = DIContext.Obtain <ISiteModelAttributesChangedEventSender>(); sender.ModelAttributesChanged(SiteModelNotificationEventGridMutability.NotifyAll, siteModelUid, surveyedSurfacesChanged: true); }
public virtual void Initialise() { // Todo: Only first filter in filter set is currently used for surface & alignment mask designs or surveyed surface restriction driven by date range var PassFilter = FilterSet.Filters[0].AttributeFilter; var CellFilter = FilterSet.Filters[0].SpatialFilter; if (CellFilter.SurfaceDesignMaskDesignUid != Guid.Empty) { SurfaceDesignMaskDesign = SiteModel.Designs.Locate(CellFilter.SurfaceDesignMaskDesignUid); if (SurfaceDesignMaskDesign == null) { throw new ArgumentException($"Design {CellFilter.SurfaceDesignMaskDesignUid} not found in project {SiteModel.ID}"); } } if (SiteModel.SurveyedSurfaces?.Count > 0) { // Filter out any surveyed surfaces which don't match current filter (if any) // - realistically, this is time filters we're thinking of here FilteredSurveyedSurfaces = DIContext.Obtain <ISurveyedSurfaces>(); SiteModel.SurveyedSurfaces?.FilterSurveyedSurfaceDetails(PassFilter.HasTimeFilter, PassFilter.StartTime, PassFilter.EndTime, PassFilter.ExcludeSurveyedSurfaces(), FilteredSurveyedSurfaces, PassFilter.SurveyedSurfaceExclusionList); if (FilteredSurveyedSurfaces?.Count == 0) { FilteredSurveyedSurfaces = null; } } // Instantiate a single instance of the argument object for the surface elevation patch requests to obtain composite // elevation sub grids and populate it with the common elements for this set of sub grids being requested. SurfaceElevationPatchArg = new SurfaceElevationPatchArgument (siteModelID: SiteModel.ID, oTGCellBottomLeftX: int.MaxValue, oTGCellBottomLeftY: int.MaxValue, cellSize: SiteModel.CellSize, includedSurveyedSurfaces: FilteredSurveyedSurfaces, surveyedSurfacePatchType: SurveyedSurfacePatchType.CompositeElevations, processingMap: new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Filled)); var _cache = DIContext.Obtain <ITRexSpatialMemoryCache>(); var _context = _cache?.LocateOrCreateContext(SiteModel.ID, GridDataType.SurveyedSurfaceHeightAndTime, SurfaceElevationPatchArg.CacheFingerprint()); SurfaceElevationPatchRequest = SurfaceElevationPatchRequestFactory(_cache, _context); }
/// <summary> /// List the surveyed surfaces for a site model /// </summary> public ISurveyedSurfaces List(Guid SiteModelID) { INonSpatialAffinityKey cacheKey = CacheKey(SiteModelID); Log.LogInformation($"Listing surveyed surfaces from {cacheKey}"); try { ISurveyedSurfaces ss = DIContext.Obtain <ISurveyedSurfaces>(); ss.FromBytes(mutableNonSpatialCache.Get(cacheKey)); return(ss); } catch (KeyNotFoundException) { return(null); } }
/// <summary> /// Determine if the surveyed surfaces in this list are the same as the surveyed surfaces in the other list, based on ID comparison /// </summary> public bool IsSameAs(ISurveyedSurfaces other) { if (Count != other.Count) { return(false); } for (var I = 0; I < Count; I++) { if (this[I].ID != other[I].ID) { return(false); } } return(true); }
public bool Process(IMutableCacheEntry <INonSpatialAffinityKey, byte[]> entry, Guid arg) { ISurveyedSurfaces ss = DIContext.Obtain <ISurveyedSurfaces>(); if (entry.Exists) { ss.FromBytes(entry.Value); } if (ss.RemoveSurveyedSurface(arg)) { entry.Value = ss.ToBytes(); return(true); } return(false); }
/// <summary> /// Constructor taking the full state of the surface patch computation operation /// </summary> public SurfaceElevationPatchArgument(Guid siteModelID, int oTGCellBottomLeftX, int oTGCellBottomLeftY, double cellSize, SurveyedSurfacePatchType surveyedSurfacePatchType, SubGridTreeBitmapSubGridBits processingMap, ISurveyedSurfaces includedSurveyedSurfaces) { SiteModelID = siteModelID; OTGCellBottomLeftX = oTGCellBottomLeftX; OTGCellBottomLeftY = oTGCellBottomLeftY; CellSize = cellSize; SurveyedSurfacePatchType = surveyedSurfacePatchType; ProcessingMap = processingMap == null ? new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Unfilled) : new SubGridTreeBitmapSubGridBits(processingMap); // Prepare the list of surveyed surfaces for use by all invocations using this argument includedSurveyedSurfaces?.SortChronologically(surveyedSurfacePatchType == SurveyedSurfacePatchType.LatestSingleElevation); IncludedSurveyedSurfaces = includedSurveyedSurfaces?.Select(x => x.ID).ToArray() ?? new Guid[0]; }
/// <summary> /// Perform filtering on a set of surveyed surfaces according to the supplied time constraints. /// Note: The list of filtered surveyed surfaces is assumed to be empty at the point it is passed to this method /// </summary> public void FilterSurveyedSurfaceDetails(bool hasTimeFilter, DateTime startTime, DateTime endTime, bool excludeSurveyedSurfaces, ISurveyedSurfaces filteredSurveyedSurfaceDetails, Guid[] exclusionList) { if (excludeSurveyedSurfaces) { return; } if (startTime.Kind != DateTimeKind.Utc || endTime.Kind != DateTimeKind.Utc) { throw new ArgumentException("StartTime and EndTime must be UTC date times"); } if (!hasTimeFilter && (exclusionList?.Length ?? 0) == 0) { filteredSurveyedSurfaceDetails.Assign(this); return; } filteredSurveyedSurfaceDetails.Clear(); foreach (var ss in this) { if (!hasTimeFilter) { if (exclusionList == null || !exclusionList.Any(x => x == ss.ID)) // if SS not excluded from project { filteredSurveyedSurfaceDetails.Add(ss); // Formerly ss.Clone } } else { if (ss.AsAtDate >= startTime && ss.AsAtDate <= endTime && (exclusionList == null || !exclusionList.Any(x => x == ss.ID))) // if SS not excluded from project { filteredSurveyedSurfaceDetails.Add(ss); // Formerly ss.Clone } } } }
public bool Process(IMutableCacheEntry <INonSpatialAffinityKey, byte[]> entry, ISurveyedSurface arg) { try { ISurveyedSurfaces ss = DIContext.Obtain <ISurveyedSurfaces>(); if (entry.Exists) { ss.FromBytes(entry.Value); } ss.AddSurveyedSurfaceDetails(arg.ID, arg.Get_DesignDescriptor(), arg.AsAtDate, arg.Extents); entry.Value = ss.ToBytes(); return(true); } catch { throw; // return false; } }
private void btnListSurveyedSurfacesClick(object sender, EventArgs e) { try { if (GetSiteModelID(out Guid SiteModelID)) { ISurveyedSurfaces ss = surveyedSurfaceManager.List(SiteModelID); if (ss == null || ss.Count == 0) { MessageBox.Show(@"No surveyed surfaces"); } else { MessageBox.Show("Surveyed Surfaces:\n" + ss.Select(x => x.ToString() + "\n").Aggregate((s1, s2) => s1 + s2)); } } } catch (Exception E) { MessageBox.Show($@"Exception: {E}"); } }
/// <summary> /// Given a filter compute which of the surfaces in the list match any given time aspect /// of the filter, and the overall existence map of the surveyed surfaces that match the filter. /// ComparisonList denotes a possibly pre-filtered set of surfaces for another filter; if this is the same as the /// filtered set of surfaces then the overall existence map for those surfaces will not be computed as it is /// assumed to be the same. /// </summary> public bool ProcessSurveyedSurfacesForFilter(Guid siteModelId, ICombinedFilter filter, ISurveyedSurfaces comparisonList, ISurveyedSurfaces filteredSurveyedSurfaces, ISubGridTreeBitMask overallExistenceMap) { // Filter out any surveyed surfaces which don't match current filter (if any) - realistically, this is time filters we're thinking of here FilterSurveyedSurfaceDetails(filter.AttributeFilter.HasTimeFilter, filter.AttributeFilter.StartTime, filter.AttributeFilter.EndTime, filter.AttributeFilter.ExcludeSurveyedSurfaces(), filteredSurveyedSurfaces, filter.AttributeFilter.SurveyedSurfaceExclusionList); if (filteredSurveyedSurfaces != null) { if (filteredSurveyedSurfaces.IsSameAs(comparisonList)) { return(true); } if (filteredSurveyedSurfaces.Count > 0) { var surveyedSurfaceExistenceMap = GetExistenceMaps().GetCombinedExistenceMap(siteModelId, filteredSurveyedSurfaces.Select(x => new Tuple <long, Guid>(Consts.EXISTENCE_SURVEYED_SURFACE_DESCRIPTOR, x.ID)).ToArray()); if (overallExistenceMap == null) { return(false); } overallExistenceMap.SetOp_OR(surveyedSurfaceExistenceMap); } } return(true); }
/// <summary> /// Constructor that accepts the common parameters around a set of sub grids the requester will be asked to process /// and initializes the requester state ready to start processing individual sub grid requests. /// </summary> public void Initialize(ISubGridsRequestArgument subGridsRequestArgument, ISiteModel siteModel, GridDataType gridDataType, IStorageProxy storageProxy, ICombinedFilter filter, bool hasOverrideSpatialCellRestriction, BoundingIntegerExtent2D overrideSpatialCellRestriction, int maxNumberOfPassesToReturn, AreaControlSet areaControlSet, IFilteredValuePopulationControl populationControl, ISubGridTreeBitMask pdExistenceMap, ITRexSpatialMemoryCache subGridCache, ITRexSpatialMemoryCacheContext[] subGridCacheContexts, ISurveyedSurfaces filteredSurveyedSurfaces, ISurfaceElevationPatchRequest surfaceElevationPatchRequest, IOverrideParameters overrides, ILiftParameters liftParams) { _siteModel = siteModel; _gridDataType = gridDataType; _filter = filter; _hasOverrideSpatialCellRestriction = hasOverrideSpatialCellRestriction; _overrideSpatialCellRestriction = overrideSpatialCellRestriction; _retriever = DIContext.Obtain <ISubGridRetrieverFactory>().Instance(subGridsRequestArgument, siteModel, gridDataType, storageProxy, filter, _filterAnnex, hasOverrideSpatialCellRestriction, overrideSpatialCellRestriction, maxNumberOfPassesToReturn, areaControlSet, populationControl, pdExistenceMap, subGridCacheContexts, overrides, liftParams); _returnEarliestFilteredCellPass = _filter.AttributeFilter.ReturnEarliestFilteredCellPass; _processingMap = new SubGridTreeBitmapSubGridBits(SubGridBitsCreationOptions.Unfilled); _surfaceElevationPatchRequest = surfaceElevationPatchRequest; _subGridCache = subGridCache; _subGridCacheContexts = subGridCacheContexts; _surveyedSurfacePatchType = _filter.AttributeFilter.ReturnEarliestFilteredCellPass ? SurveyedSurfacePatchType.EarliestSingleElevation : SurveyedSurfacePatchType.LatestSingleElevation; _filteredSurveyedSurfaces = filteredSurveyedSurfaces; _filteredSurveyedSurfaces?.SortChronologically(_surveyedSurfacePatchType == SurveyedSurfacePatchType.LatestSingleElevation); _filteredSurveyedSurfacesAsGuidArray = _filteredSurveyedSurfaces?.Select(x => x.ID).ToArray() ?? new Guid[0]; var elevRangeDesignFilter = _filter.AttributeFilter.ElevationRangeDesign; if (elevRangeDesignFilter.DesignID != Guid.Empty) { var design = _siteModel.Designs.Locate(elevRangeDesignFilter.DesignID); if (design == null) { _log.LogError($"ElevationRangeDesign {elevRangeDesignFilter.DesignID} is unknown in project {siteModel.ID}"); } else { _elevationRangeDesign = new DesignWrapper(elevRangeDesignFilter, design); } } if (_filter.SpatialFilter.IsDesignMask) { _surfaceDesignMaskDesign = _siteModel.Designs.Locate(_filter.SpatialFilter.SurfaceDesignMaskDesignUid); } _filter.AttributeFilter.SiteModel = _siteModel; }
/// <summary> /// Performs the donkey work of the elevation patch calculation /// </summary> public IClientLeafSubGrid Execute(ISiteModel siteModel, int otgCellBottomLeftX, int otgCellBottomLeftY, double cellSize, SurveyedSurfacePatchType patchType, Guid[] includedSurveyedSurfaces, IDesignFiles designs, ISurveyedSurfaces surveyedSurfaces, SubGridTreeBitmapSubGridBits processingMap) { var calcResult = DesignProfilerRequestResult.UnknownError; try { if (!Enum.IsDefined(typeof(SurveyedSurfacePatchType), patchType)) { _log.LogError($"Unknown SurveyedSurfacePatchType: {patchType}, returning null"); return(null); } if (includedSurveyedSurfaces == null) { _log.LogError("Included surveyed surfaces list is null, returning null"); return(null); } if (processingMap == null) { _log.LogError("Supplied processing map is null, returning null"); return(null); } var patch = _clientLeafSubGridFactory.GetSubGridEx( patchType == SurveyedSurfacePatchType.CompositeElevations ? GridDataType.CompositeHeights : GridDataType.HeightAndTime, cellSize, SubGridTreeConsts.SubGridTreeLevels, otgCellBottomLeftX, otgCellBottomLeftY); // Assign var patchSingle = patchType != SurveyedSurfacePatchType.CompositeElevations ? patch as ClientHeightAndTimeLeafSubGrid : null; var patchComposite = patchType == SurveyedSurfacePatchType.CompositeElevations ? patch as ClientCompositeHeightsLeafSubgrid : null; patch.CalculateWorldOrigin(out var originX, out var originY); var halfCellSize = cellSize / 2; var originXPlusHalfCellSize = originX + halfCellSize; var originYPlusHalfCellSize = originY + halfCellSize; // Work down through the list of surfaces in the time ordering provided by the caller foreach (var surveyedSurfaceUid in includedSurveyedSurfaces) { if (processingMap.IsEmpty()) { break; } var thisSurveyedSurface = surveyedSurfaces.Locate(surveyedSurfaceUid); if (thisSurveyedSurface == null) { _log.LogError($"Surveyed surface {surveyedSurfaceUid} not found in site model, returning null"); calcResult = DesignProfilerRequestResult.FailedToLoadDesignFile; return(null); } // Lock & load the design var design = designs.Lock(thisSurveyedSurface.DesignDescriptor.DesignID, siteModel, cellSize, out _); if (design == null) { _log.LogError($"Failed to lock design file {thisSurveyedSurface.DesignDescriptor} in {nameof(CalculateSurfaceElevationPatch)}"); calcResult = DesignProfilerRequestResult.FailedToLoadDesignFile; return(null); } try { if (!design.HasElevationDataForSubGridPatch( otgCellBottomLeftX >> SubGridTreeConsts.SubGridIndexBitsPerLevel, otgCellBottomLeftY >> SubGridTreeConsts.SubGridIndexBitsPerLevel)) { continue; } var asAtDate = thisSurveyedSurface.AsAtDate.Ticks; var hint = -1; // Walk across the sub grid checking for a design elevation for each appropriate cell // based on the processing bit mask passed in processingMap.ForEachSetBit((x, y) => { // If we can interpolate a height for the requested cell, then update the cell height // and decrement the bit count so that we know when we've handled all the requested cells if (design.InterpolateHeight(ref hint, originXPlusHalfCellSize + cellSize * x, originYPlusHalfCellSize + cellSize * y, 0, out var z)) { // Check for composite elevation processing if (patchType == SurveyedSurfacePatchType.CompositeElevations) { // Set the first elevation if not already set if (patchComposite.Cells[x, y].FirstHeightTime == 0) { patchComposite.Cells[x, y].FirstHeightTime = asAtDate; patchComposite.Cells[x, y].FirstHeight = (float)z; } // Always set the latest elevation (surfaces ordered by increasing date) patchComposite.Cells[x, y].LastHeightTime = asAtDate; patchComposite.Cells[x, y].LastHeight = (float)z; // Update the lowest height if (patchComposite.Cells[x, y].LowestHeightTime == 0 || patchComposite.Cells[x, y].LowestHeight > z) { patchComposite.Cells[x, y].LowestHeightTime = asAtDate; patchComposite.Cells[x, y].LowestHeight = (float)z; } // Update the highest height if (patchComposite.Cells[x, y].HighestHeightTime == 0 || patchComposite.Cells[x, y].HighestHeight > z) { patchComposite.Cells[x, y].HighestHeightTime = asAtDate; patchComposite.Cells[x, y].HighestHeight = (float)z; } } else // earliest/latest singular value processing { patchSingle.Times[x, y] = asAtDate; patchSingle.Cells[x, y] = (float)z; } } // Only clear the processing bit if earliest or latest information is wanted from the surveyed surfaces if (patchType != SurveyedSurfacePatchType.CompositeElevations) { processingMap.ClearBit(x, y); } return(true); }); } finally { designs.UnLock(thisSurveyedSurface.DesignDescriptor.DesignID, design); } } calcResult = DesignProfilerRequestResult.OK; return(patch); } catch (Exception e) { _log.LogError(e, $"Exception occurred calculating surveyed surface patch, calcResult = {calcResult}"); return(null); } }