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