public void Should_use_default_Design(VolumeCalcType volumeCalcType) { InitRequestHelper(); requestHelper.SetVolumeCalcType(volumeCalcType); var tileRequestResult = requestHelper.CreateTileRequest(DisplayMode.CutFill, 0, 0, null, null); Assert.AreEqual(designDescriptor, tileRequestResult.DesignDescriptor); }
public void Should_set_Filter1_from_topFilter_When_VolCalType_is_valid(VolumeCalcType volumeCalcType) { var topFilter = InitRequestHelper(); requestHelper.SetVolumeCalcType(volumeCalcType); requestHelper.SetTopFilter(topFilter); var tileRequestResult = requestHelper.CreateTileRequest(DisplayMode.CutFill, 0, 0, null, null); Assert.AreEqual(topFilter, tileRequestResult.Filter1); Assert.IsNull(tileRequestResult.Filter2); }
private VolumesType ConvertVolumeCalcType(VolumeCalcType volumesType) { switch (volumesType) { case VolumeCalcType.None: return(VolumesType.None); case VolumeCalcType.GroundToGround: return(VolumesType.Between2Filters); case VolumeCalcType.GroundToDesign: return(VolumesType.BetweenFilterAndDesign); case VolumeCalcType.DesignToGround: return(VolumesType.BetweenDesignAndFilter); default: throw new Exception($"Unknown VolumeCalcType {Convert.ToInt16(volumesType)}"); } }
/// <summary> /// Calculate the elevations for cut-fill or summary volumes cells from the design surface. /// </summary> /// <param name="projectId">Legacy project ID</param> /// <param name="ProjectUid">Project's unique identifier</param> /// <param name="settings">Project settings</param> /// <param name="startLatDegrees">The start latitude of the slicer line in decimal degrees</param> /// <param name="startLonDegrees">The start longitude of the slicer line in decimal degrees</param> /// <param name="endLatDegrees">The end latitude of the slicer line in decimal degrees</param> /// <param name="endLonDegrees">The end longitude of the slicer line in decimal degrees</param> /// <param name="design">The design surface descriptor</param> /// <param name="profileResultHelper">Utility class to do the work</param> /// <param name="slicerProductionDataResult">The slicer profile results containing the production data profiles</param> /// <param name="type">The type of profile, either cut-fill or summary volumes</param> /// <param name="volumeCalcType">Summary volumes calculation type</param> private async Task FindCutFillElevations( long projectId, Guid ProjectUid, CompactionProjectSettings settings, double startLatDegrees, double startLonDegrees, double endLatDegrees, double endLonDegrees, DesignDescriptor design, ICompactionProfileResultHelper profileResultHelper, CompactionProfileResult <CompactionProfileDataResult> slicerProductionDataResult, string type, VolumeCalcType volumeCalcType) { //Get design profile var slicerDesignProfileRequest = requestFactory.Create <DesignProfileRequestHelper>(r => r .ProjectId(projectId) .ProjectUid(ProjectUid) .Headers(this.CustomHeaders) .ProjectSettings(settings) .DesignDescriptor(design)) .CreateDesignProfileRequest(startLatDegrees, startLonDegrees, endLatDegrees, endLonDegrees); slicerDesignProfileRequest.Validate(); var slicerDesignResult = await WithServiceExceptionTryExecuteAsync(() => RequestExecutorContainerFactory .Build <CompactionDesignProfileExecutor>(LoggerFactory, #if RAPTOR RaptorClient, #endif configStore : ConfigStore, trexCompactionDataProxy : TRexCompactionDataProxy, customHeaders : CustomHeaders, userId : GetUserId(), fileImportProxy : FileImportProxy) .ProcessAsync(slicerDesignProfileRequest) ); //Find the cut-fill elevations for the cell stations from the design vertex elevations profileResultHelper.FindCutFillElevations(slicerProductionDataResult, (CompactionProfileResult <CompactionProfileVertex>)slicerDesignResult, type, volumeCalcType); }
/// <summary> /// Find the cut-fill elevations for the cells from the cut-fill design elevations /// </summary> /// <param name="slicerProfileResult">The production data profile result with the cells</param> /// <param name="slicerDesignResult">The design profile result with the vertices</param> /// <param name="type">The type of profile to do, either cut-fill or summary volumes</param> /// <param name="calcType">The type of summary volumes calculation</param> public void FindCutFillElevations(CompactionProfileResult <CompactionProfileDataResult> slicerProfileResult, CompactionProfileResult <CompactionProfileVertex> slicerDesignResult, string type, VolumeCalcType calcType) { log.LogDebug($"FindCutFillElevations: {type}"); if (type != CompactionDataPoint.CUT_FILL && type != CompactionDataPoint.SUMMARY_VOLUMES) { return; } if (calcType == VolumeCalcType.GroundToGround) { return; } var vertices = slicerDesignResult.results; var cells = (from r in slicerProfileResult.results where r.type == type select r).Single().data; if (cells != null && cells.Count > 0 && vertices != null && vertices.Count > 0) { int startIndx = -1; foreach (var cell in cells) { startIndx = FindVertexIndex(vertices, cell.x, startIndx); if (startIndx != -1) { float newy = float.NaN; //Check for no design elevation if (float.IsNaN(vertices[startIndx].elevation) || float.IsNaN(vertices[startIndx + 1].elevation)) { //If the cell station matches (within 3mm) either vertex station //then we can use that vertex elevation directly const double THREE_MM = 0.003; if (Math.Abs(vertices[startIndx].station - cell.x) <= THREE_MM) { newy = vertices[startIndx].elevation; } else if (Math.Abs(vertices[startIndx + 1].station - cell.x) <= THREE_MM) { newy = vertices[startIndx + 1].elevation; } } else { //Calculate elevation by interpolation var proportion = (cell.x - vertices[startIndx].station) / (vertices[startIndx + 1].station - vertices[startIndx].station); newy = (float)(vertices[startIndx].elevation + proportion * (vertices[startIndx + 1].elevation - vertices[startIndx].elevation)); } if (calcType == VolumeCalcType.DesignToGround) { cell.y = newy; } else { cell.y2 = newy; } } } } }
private CompactionProfileResult <CompactionSummaryVolumesProfileCell> ProcessSummaryVolumesProfileCells(List <SummaryVolumeProfileCell> profileCells, double gridDistanceBetweenProfilePoints, VolumeCalcType calcType) { var profile = new CompactionProfileResult <CompactionSummaryVolumesProfileCell>(); profile.results = new List <CompactionSummaryVolumesProfileCell>(); SummaryVolumeProfileCell prevCell = null; foreach (var currCell in profileCells) { var gapExists = ProfilesHelper.CellGapExists(prevCell, currCell, out var prevStationIntercept); if (gapExists) { var gapCell = new CompactionSummaryVolumesProfileCell(SumVolGapCell); gapCell.station = prevStationIntercept; profile.results.Add(gapCell); } var lastPassHeight1 = currCell.LastCellPassElevation1 == VelociraptorConstants.NULL_SINGLE ? float.NaN : currCell.LastCellPassElevation1; var lastPassHeight2 = currCell.LastCellPassElevation2 == VelociraptorConstants.NULL_SINGLE ? float.NaN : currCell.LastCellPassElevation2; var designHeight = currCell.DesignElev == VelociraptorConstants.NULL_SINGLE ? float.NaN : currCell.DesignElev; float cutFill = float.NaN; switch (calcType) { case VolumeCalcType.GroundToGround: cutFill = float.IsNaN(lastPassHeight1) || float.IsNaN(lastPassHeight2) ? float.NaN : lastPassHeight2 - lastPassHeight1; break; case VolumeCalcType.GroundToDesign: cutFill = float.IsNaN(lastPassHeight1) || float.IsNaN(designHeight) ? float.NaN : designHeight - lastPassHeight1; break; case VolumeCalcType.DesignToGround: cutFill = float.IsNaN(designHeight) || float.IsNaN(lastPassHeight2) ? float.NaN : lastPassHeight2 - designHeight; break; } profile.results.Add(new CompactionSummaryVolumesProfileCell { cellType = prevCell == null ? ProfileCellType.MidPoint : ProfileCellType.Edge, station = currCell.Station, lastPassHeight1 = lastPassHeight1, lastPassHeight2 = lastPassHeight2, designHeight = designHeight, cutFill = cutFill }); prevCell = currCell; } //Add a last point at the intercept length of the last cell so profiles are drawn correctly if (prevCell != null && prevCell.InterceptLength > ProfilesHelper.ONE_MM) { var lastCell = new CompactionSummaryVolumesProfileCell(profile.results[profile.results.Count - 1]) { station = prevCell.Station + prevCell.InterceptLength }; profile.results.Add(lastCell); } if (profile.results.Count > 0) { profile.results[profile.results.Count - 1].cellType = ProfileCellType.MidPoint; } profile.gridDistanceBetweenProfilePoints = gridDistanceBetweenProfilePoints; var sb = new StringBuilder(); sb.Append($"After summary volumes profile conversion: {profile.results.Count}"); foreach (var cell in profile.results) { sb.Append($",{cell.cellType}"); } log.LogDebug(sb.ToString()); return(profile); }
/// <summary> /// Convert Raptor data to the data to return from the Web API /// </summary> /// <param name="ms">Memory stream of data from Raptor</param> /// <param name="calcType">Volume calculation type.</param> /// <returns>The profile data</returns> private CompactionProfileResult <CompactionSummaryVolumesProfileCell> ConvertSummaryVolumesProfileResult(MemoryStream ms, VolumeCalcType calcType) { log.LogDebug("Converting summary volumes profile Raptor result"); var pdsiProfile = new PDSSummaryVolumesProfile(); var packager = new TICSummaryVolumesProfileCellListPackager(); packager.CellList = new TICSummaryVolumesProfileCellList(); packager.ReadFromStream(ms); ms.Close(); pdsiProfile.Assign(packager.CellList); pdsiProfile.GridDistanceBetweenProfilePoints = packager.GridDistanceBetweenProfilePoints; var profileCells = pdsiProfile.Cells.Select(c => new SummaryVolumeProfileCell( c.station, c.interceptLength, c.OTGCellX, c.OTGCellY, c.designElevation, c.lastCellPassElevation1, c.lastCellPassElevation2 )).ToList(); return(ProcessSummaryVolumesProfileCells(profileCells, pdsiProfile.GridDistanceBetweenProfilePoints, calcType)); }
/// <summary> /// Convert TRex data to the data to return from the Web API /// </summary> /// <param name="trexResult">Result data from TRex.</param> /// <param name="calcType"></param> /// <returns>The profile data</returns> private CompactionProfileResult <CompactionSummaryVolumesProfileCell> ConvertTRexSummaryVolumesProfileResult(ProfileDataResult <SummaryVolumeProfileCell> trexResult, VolumeCalcType calcType) { log.LogDebug("Converting summary volumes profile TRex result"); return(ProcessSummaryVolumesProfileCells(trexResult.ProfileCells, trexResult.GridDistanceBetweenProfilePoints, calcType));; }
public void Should_set_Design_from_VolumeDescriptor_When_VolCalType_is_valid(VolumeCalcType volumeCalcType) { InitRequestHelper(); requestHelper.SetVolumeCalcType(volumeCalcType); requestHelper.SetVolumeDesign(volumeDescriptor); var tileRequestResult = requestHelper.CreateTileRequest(DisplayMode.CutFill, 0, 0, null, null); Assert.AreEqual(volumeDescriptor, tileRequestResult.DesignDescriptor); }
public void Should_not_set_topFilter_When_VolCalType_is_DesignToGround_or_GroundToDesign(VolumeCalcType volumeCalcType) { var baseFilter = InitRequestHelper(); requestHelper.SetVolumeCalcType(volumeCalcType); requestHelper.SetBaseFilter(baseFilter); var tileRequestResult = requestHelper.CreateTileRequest(DisplayMode.CutFill, 0, 0, null, null); Assert.AreEqual(baseFilter, tileRequestResult.Filter1); Assert.IsNull(tileRequestResult.Filter2); }