diff --git a/AsbCloudApp/Data/TrajectoryVisualizationFactDto.cs b/AsbCloudApp/Data/TrajectoryCartesianFactDto.cs similarity index 72% rename from AsbCloudApp/Data/TrajectoryVisualizationFactDto.cs rename to AsbCloudApp/Data/TrajectoryCartesianFactDto.cs index be8a2a21..64f3291b 100644 --- a/AsbCloudApp/Data/TrajectoryVisualizationFactDto.cs +++ b/AsbCloudApp/Data/TrajectoryCartesianFactDto.cs @@ -1,9 +1,11 @@ namespace AsbCloudApp.Data { + + /// /// Визуализация траектории 3D /// - public class TrajectoryVisualizationFactDto + public class TrajectoryCartesianDto { /// /// Координаты по оси X, в сторону востока (м) @@ -20,4 +22,9 @@ /// public double Z { get; set; } } + + /// + /// Визуализация фактической траектории 3D + /// + public class TrajectoryCartesianFactDto : TrajectoryCartesianDto { } } diff --git a/AsbCloudApp/Data/TrajectoryVisualizationPlanDto.cs b/AsbCloudApp/Data/TrajectoryCartesianPlanDto.cs similarity index 84% rename from AsbCloudApp/Data/TrajectoryVisualizationPlanDto.cs rename to AsbCloudApp/Data/TrajectoryCartesianPlanDto.cs index 63982b4e..ed7755df 100644 --- a/AsbCloudApp/Data/TrajectoryVisualizationPlanDto.cs +++ b/AsbCloudApp/Data/TrajectoryCartesianPlanDto.cs @@ -3,7 +3,7 @@ /// /// Визуализация траектории 3D для посторения радиуса цели /// - public class TrajectoryVisualizationPlanDto : TrajectoryVisualizationFactDto + public class TrajectoryCartesianPlanDto : TrajectoryCartesianFactDto { /// /// радиус цели diff --git a/AsbCloudApp/Data/TrajectoryFactDto.cs b/AsbCloudApp/Data/TrajectoryFactDto.cs deleted file mode 100644 index 1e01e35c..00000000 --- a/AsbCloudApp/Data/TrajectoryFactDto.cs +++ /dev/null @@ -1,35 +0,0 @@ -namespace AsbCloudApp.Data; - -public class TrajectoryDto -{ - public double WellboreDepth { get; set; } - public double ZenithAngle { get; set; } - public double AzimuthGeo { get; set; } -} - -/// -/// Формирование визуализации траектории 3D -/// -/// Глубина ствола -/// Зенитный угол -/// Азимут географиеский -public class TrajectoryFactDto : TrajectoryDto -{ - -} - - -/// -/// -/// -/// -/// -/// -/// -/// -public class TrajectoryPlanDto : TrajectoryDto -{ - public double? Radius { get; set; } - public string? Comment { get; set; } -} - diff --git a/AsbCloudApp/Data/TrajectoryGeoFactDto.cs b/AsbCloudApp/Data/TrajectoryGeoFactDto.cs new file mode 100644 index 00000000..939a9e7b --- /dev/null +++ b/AsbCloudApp/Data/TrajectoryGeoFactDto.cs @@ -0,0 +1,30 @@ +namespace AsbCloudApp.Data; + +/// +/// Базовая географическая траектория +/// +public abstract class TrajectoryGeoDto +{ + /// + /// Глубина по стволу + /// + public double WellboreDepth { get; set; } + /// + /// Угол зенитный + /// + public double ZenithAngle { get; set; } + + /// + /// Азимут Географ. + /// + public double AzimuthGeo { get; set; } +} + +/// +/// Формирование географической траектории +/// +public class TrajectoryGeoFactDto : TrajectoryGeoDto +{} + + + diff --git a/AsbCloudApp/Data/PlannedTrajectoryDto.cs b/AsbCloudApp/Data/TrajectoryGeoPlanDto.cs similarity index 86% rename from AsbCloudApp/Data/PlannedTrajectoryDto.cs rename to AsbCloudApp/Data/TrajectoryGeoPlanDto.cs index b1e34ba2..526a4ae1 100644 --- a/AsbCloudApp/Data/PlannedTrajectoryDto.cs +++ b/AsbCloudApp/Data/TrajectoryGeoPlanDto.cs @@ -4,7 +4,7 @@ namespace AsbCloudApp.Data /// /// Формирование данных по плановой траектории /// - public class PlannedTrajectoryDto + public class TrajectoryGeoPlanDto: TrajectoryGeoDto { /// /// ИД строки с координатами @@ -15,28 +15,16 @@ namespace AsbCloudApp.Data /// ИД скважины /// public int IdWell { get; set; } + /// /// Дата загрузки /// public DateTime UpdateDate { get; set; } + /// /// ИД пользователя /// public int IdUser { get; set; } - /// - /// Глубина по стволу - /// - public double WellboreDepth { get; set; } - - /// - /// Угол зенитный - /// - public double ZenithAngle { get; set; } - - /// - /// Азимут Географ. - /// - public double AzimuthGeo { get; set; } /// /// Азимут Магнитный @@ -93,6 +81,11 @@ namespace AsbCloudApp.Data /// public double OrificeOffset { get; set; } + /// + /// Радиус цели + /// + public double? Radius { get; set; } + /// /// Комментарии /// diff --git a/AsbCloudApp/Repositories/IActualTrajectoryRepository.cs b/AsbCloudApp/Repositories/IActualTrajectoryRepository.cs deleted file mode 100644 index 5028d2a2..00000000 --- a/AsbCloudApp/Repositories/IActualTrajectoryRepository.cs +++ /dev/null @@ -1,23 +0,0 @@ -using AsbCloudApp.Data; -using AsbCloudApp.Data.WITS; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -namespace AsbCloudApp.Repositories -{ - /// - /// CRUD для работы с фактической траекторией из клиента - /// - /// - public interface IActualTrajectoryRepository : ITrajectoryRepository - { - /// - /// Получение траектории для 3D-визуализации - /// - /// ключ скважины - /// - /// - Task> GetTrajectoryAsync(int idWell, CancellationToken token); - } -} diff --git a/AsbCloudApp/Repositories/ITrajectoryFactRepository.cs b/AsbCloudApp/Repositories/ITrajectoryFactRepository.cs new file mode 100644 index 00000000..95e991f5 --- /dev/null +++ b/AsbCloudApp/Repositories/ITrajectoryFactRepository.cs @@ -0,0 +1,16 @@ +using AsbCloudApp.Data; +using AsbCloudApp.Data.WITS; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudApp.Repositories +{ + /// + /// CRUD для работы с фактической траекторией из клиента + /// + /// + public interface ITrajectoryFactRepository : ITrajectoryRepository + { + } +} diff --git a/AsbCloudApp/Repositories/IPlannedTrajectoryRepository.cs b/AsbCloudApp/Repositories/ITrajectoryPlanRepository.cs similarity index 66% rename from AsbCloudApp/Repositories/IPlannedTrajectoryRepository.cs rename to AsbCloudApp/Repositories/ITrajectoryPlanRepository.cs index 75126124..9e618351 100644 --- a/AsbCloudApp/Repositories/IPlannedTrajectoryRepository.cs +++ b/AsbCloudApp/Repositories/ITrajectoryPlanRepository.cs @@ -9,23 +9,15 @@ namespace AsbCloudApp.Repositories /// CRUD для работы с плановой траекторией из клиента /// /// - public interface IPlannedTrajectoryRepository : ITrajectoryRepository + public interface ITrajectoryPlanRepository : ITrajectoryRepository { - /// - /// Получить все добавленные по скважине координаты плановой траектории - /// - /// - /// - /// - Task> GetAsync(int idWell, CancellationToken token); - /// /// Добавить строки с координатами по одной скважине. Если в коллекции координаты для разных скважин получаем exception. /// /// /// /// количество записанных строк или exception с описанием - Task AddRangeAsync(IEnumerable plannedTrajectoryRows, CancellationToken token); + Task AddRangeAsync(IEnumerable plannedTrajectoryRows, CancellationToken token); /// /// Добавить одну строку с координатами @@ -33,7 +25,7 @@ namespace AsbCloudApp.Repositories /// /// /// - Task AddAsync(PlannedTrajectoryDto plannedTrajectoryRow, CancellationToken token); + Task AddAsync(TrajectoryGeoPlanDto plannedTrajectoryRow, CancellationToken token); /// /// Обновить строку с координатами @@ -41,7 +33,7 @@ namespace AsbCloudApp.Repositories /// /// /// - Task UpdateAsync(PlannedTrajectoryDto row, + Task UpdateAsync(TrajectoryGeoPlanDto row, CancellationToken token); /// @@ -59,13 +51,5 @@ namespace AsbCloudApp.Repositories /// /// Task DeleteByIdWellAsync(int idWell, CancellationToken token); - - /// - /// Получение траектории для 3D-визуализации - /// - /// ключ скважины - /// - /// - Task> GetTrajectoryAsync(int idWell, CancellationToken token); } } diff --git a/AsbCloudApp/Repositories/ITrajectoryRepository.cs b/AsbCloudApp/Repositories/ITrajectoryRepository.cs index 3e3f6263..ab4e5d59 100644 --- a/AsbCloudApp/Repositories/ITrajectoryRepository.cs +++ b/AsbCloudApp/Repositories/ITrajectoryRepository.cs @@ -11,8 +11,15 @@ namespace AsbCloudApp.Repositories /// /// Репозиторий по работе с траекторией /// - public interface ITrajectoryRepository + public interface ITrajectoryRepository + where T : TrajectoryGeoDto { - + /// + /// Получить все добавленные по скважине координаты плановой траектории + /// + /// + /// + /// + Task> GetAsync(int idWell, CancellationToken token); } } diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs index d2c93b3f..1bd60103 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -137,9 +137,7 @@ namespace AsbCloudInfrastructure services.AddTransient(); services.AddTransient(); - services.AddTransient(); - services.AddTransient, TrajectoryVisualizationPlanService>(); - services.AddTransient, TrajectoryVisualizationFactService>(); + services.AddTransient(); services.AddTransient(); @@ -179,8 +177,8 @@ namespace AsbCloudInfrastructure services.AddTransient(); services.AddTransient(); services.AddTransient(); - services.AddTransient(); - services.AddTransient(); + services.AddTransient(); + services.AddTransient(); services.AddTransient(); // Subsystem service diff --git a/AsbCloudInfrastructure/Repository/ActualTrajectoryRepository.cs b/AsbCloudInfrastructure/Repository/TrajectoryFactRepository.cs similarity index 70% rename from AsbCloudInfrastructure/Repository/ActualTrajectoryRepository.cs rename to AsbCloudInfrastructure/Repository/TrajectoryFactRepository.cs index d04a835f..21a1ffff 100644 --- a/AsbCloudInfrastructure/Repository/ActualTrajectoryRepository.cs +++ b/AsbCloudInfrastructure/Repository/TrajectoryFactRepository.cs @@ -11,19 +11,18 @@ using System.Threading.Tasks; namespace AsbCloudInfrastructure.Repository { - internal class ActualTrajectoryRepository : IActualTrajectoryRepository + internal class TrajectoryFactRepository : ITrajectoryFactRepository { private readonly IAsbCloudDbContext db; private readonly IWellService wellService; - public ActualTrajectoryRepository(IAsbCloudDbContext db, IWellService wellService) + public TrajectoryFactRepository(IAsbCloudDbContext db, IWellService wellService) { this.db = db; this.wellService = wellService; } - public async Task> GetTrajectoryAsync(int idWell, CancellationToken token) + public async Task> GetAsync(int idWell, CancellationToken token) { - var well = wellService.GetOrDefault(idWell); if (well is null || well.Timezone is null) throw new ArgumentInvalidException("idWell doesn`t exist", nameof(idWell)); @@ -37,7 +36,12 @@ namespace AsbCloudInfrastructure.Repository .ToArrayAsync(token); var result = entities - .Select(coord => new TrajectoryFactDto(coord.Deptsvym!.Value, coord.Svyinc!.Value, coord.Svyazc!.Value)) + .Select(coord => new TrajectoryGeoFactDto + { + WellboreDepth = coord.Deptsvym!.Value, + ZenithAngle = coord.Svyinc!.Value, + AzimuthGeo = coord.Svyazc!.Value + }) .ToArray(); return result; diff --git a/AsbCloudInfrastructure/Repository/PlannedTrajectoryRepository.cs b/AsbCloudInfrastructure/Repository/TrajectoryPlanRepository.cs similarity index 74% rename from AsbCloudInfrastructure/Repository/PlannedTrajectoryRepository.cs rename to AsbCloudInfrastructure/Repository/TrajectoryPlanRepository.cs index 6c9b46aa..94b66365 100644 --- a/AsbCloudInfrastructure/Repository/PlannedTrajectoryRepository.cs +++ b/AsbCloudInfrastructure/Repository/TrajectoryPlanRepository.cs @@ -14,17 +14,17 @@ using System.Threading.Tasks; namespace AsbCloudInfrastructure.Repository { - public class PlannedTrajectoryRepository : IPlannedTrajectoryRepository + public class TrajectoryPlanRepository : ITrajectoryPlanRepository { private readonly IAsbCloudDbContext db; private readonly IWellService wellService; - public PlannedTrajectoryRepository(IAsbCloudDbContext db, IWellService wellService) + public TrajectoryPlanRepository(IAsbCloudDbContext db, IWellService wellService) { this.db = db; this.wellService = wellService; } /// - public async Task AddRangeAsync(IEnumerable plannedTrajectoryRows, CancellationToken token) + public async Task AddRangeAsync(IEnumerable plannedTrajectoryRows, CancellationToken token) { var idWell = plannedTrajectoryRows.First().IdWell; if (!plannedTrajectoryRows.All(r => r.IdWell == idWell)) @@ -44,7 +44,7 @@ namespace AsbCloudInfrastructure.Repository } /// - public async Task AddAsync(PlannedTrajectoryDto plannedTrajectoryRow, CancellationToken token) + public async Task AddAsync(TrajectoryGeoPlanDto plannedTrajectoryRow, CancellationToken token) { var offsetHours = wellService.GetTimezone(plannedTrajectoryRow.IdWell).Hours; var entity = Convert(plannedTrajectoryRow, offsetHours); @@ -75,7 +75,7 @@ namespace AsbCloudInfrastructure.Repository } /// - public async Task> GetAsync(int idWell, CancellationToken token) + public async Task> GetAsync(int idWell, CancellationToken token) { var well = wellService.GetOrDefault(idWell); if (well is null || well.Timezone is null) @@ -93,7 +93,7 @@ namespace AsbCloudInfrastructure.Repository } /// - public async Task UpdateAsync(PlannedTrajectoryDto row, CancellationToken token) + public async Task UpdateAsync(TrajectoryGeoPlanDto row, CancellationToken token) { var offsetHours = wellService.GetTimezone(row.IdWell).Hours; var entity = Convert(row, offsetHours); @@ -102,35 +102,18 @@ namespace AsbCloudInfrastructure.Repository .ConfigureAwait(false); } - private PlannedTrajectoryDto Convert(PlannedTrajectory entity, double offsetHours) + private TrajectoryGeoPlanDto Convert(PlannedTrajectory entity, double offsetHours) { - var dto = entity.Adapt(); + var dto = entity.Adapt(); dto.UpdateDate = entity.UpdateDate.ToRemoteDateTime(offsetHours); return dto; } - private PlannedTrajectory Convert(PlannedTrajectoryDto dto, double offsetHours) + private PlannedTrajectory Convert(TrajectoryGeoPlanDto dto, double offsetHours) { var entity = dto.Adapt(); entity.UpdateDate = DateTime.Now.ToUtcDateTimeOffset(offsetHours); return entity; } - - public async Task> GetTrajectoryAsync(int idWell, CancellationToken token) - { - var well = wellService.GetOrDefault(idWell); - if (well is null || well.Timezone is null) - throw new ArgumentInvalidException("idWell doesn`t exist", nameof(idWell)); - - var query = db.PlannedTrajectories - .AsNoTracking() - .Where(x => x.IdWell == idWell); - - return await query - .Select(coord => new TrajectoryPlanDto(coord.WellboreDepth, coord.ZenithAngle, coord.AzimuthGeo, coord.RadiusTarget, coord.Comment)) - .ToArrayAsync() - .ConfigureAwait(false); - } } - } diff --git a/AsbCloudInfrastructure/Services/Trajectory/PlannedTrajectoryImportService.cs b/AsbCloudInfrastructure/Services/Trajectory/PlannedTrajectoryImportService.cs index 60a216ad..d319492f 100644 --- a/AsbCloudInfrastructure/Services/Trajectory/PlannedTrajectoryImportService.cs +++ b/AsbCloudInfrastructure/Services/Trajectory/PlannedTrajectoryImportService.cs @@ -19,7 +19,7 @@ namespace AsbCloudInfrastructure.Services.Trajectory */ private readonly IWellService wellService; - private readonly IPlannedTrajectoryRepository plannedTrajectoryService; + private readonly ITrajectoryPlanRepository plannedTrajectoryService; private const string templateFileName = "PlannedTrajectoryTemplate.xlsx"; private const string usingTemplateFile = "AsbCloudInfrastructure.Services.Trajectory"; @@ -41,7 +41,7 @@ namespace AsbCloudInfrastructure.Services.Trajectory private const int ColumnOrificeOffset = 14; private const int ColumnComment = 15; - public PlannedTrajectoryImportService(IWellService wellService, IPlannedTrajectoryRepository plannedTrajectoryService) + public PlannedTrajectoryImportService(IWellService wellService, ITrajectoryPlanRepository plannedTrajectoryService) { this.wellService = wellService; @@ -69,7 +69,7 @@ namespace AsbCloudInfrastructure.Services.Trajectory return MakeExelFileStream(plannedTrajectorys); } - private Stream MakeExelFileStream(IEnumerable plannedTrajectories) + private Stream MakeExelFileStream(IEnumerable plannedTrajectories) { using Stream ecxelTemplateStream = GetTemplateFile(); using var workbook = new XLWorkbook(ecxelTemplateStream, XLEventTracking.Disabled); @@ -80,7 +80,7 @@ namespace AsbCloudInfrastructure.Services.Trajectory return memoryStream; } - private static void AddPlannedTrajecoryToWorkbook(XLWorkbook workbook, IEnumerable plannedTrajectories) + private static void AddPlannedTrajecoryToWorkbook(XLWorkbook workbook, IEnumerable plannedTrajectories) { if (plannedTrajectories.Any()) { @@ -91,7 +91,7 @@ namespace AsbCloudInfrastructure.Services.Trajectory } } - private static void AddPlannedTrajecoryToSheet(IXLWorksheet sheet, IEnumerable plannedTrajectories) + private static void AddPlannedTrajecoryToSheet(IXLWorksheet sheet, IEnumerable plannedTrajectories) { var rowList = plannedTrajectories.ToList(); for (int i = 0; i < rowList.Count; i++) @@ -100,7 +100,7 @@ namespace AsbCloudInfrastructure.Services.Trajectory AddCoordinatesToRow(row, rowList[i]); } } - private static void AddCoordinatesToRow(IXLRow row, PlannedTrajectoryDto trajectory) + private static void AddCoordinatesToRow(IXLRow row, TrajectoryGeoPlanDto trajectory) { row.Cell(ColumnWellboreDepth).Value = trajectory.WellboreDepth; row.Cell(ColumnZenithAngle).Value = trajectory.ZenithAngle; @@ -133,7 +133,7 @@ namespace AsbCloudInfrastructure.Services.Trajectory return rowsCount; } - private async Task SavePlannedTrajectoryAsync(int idWell, IEnumerable newRows, bool deletePrevRow, CancellationToken token) + private async Task SavePlannedTrajectoryAsync(int idWell, IEnumerable newRows, bool deletePrevRow, CancellationToken token) { if (deletePrevRow) await plannedTrajectoryService.DeleteByIdWellAsync(idWell, token); @@ -141,13 +141,13 @@ namespace AsbCloudInfrastructure.Services.Trajectory return rowsCount; } - private IEnumerable ParseFileStream(Stream stream) + private IEnumerable ParseFileStream(Stream stream) { using var workbook = new XLWorkbook(stream, XLEventTracking.Disabled); return ParseWorkbook(workbook); } - private IEnumerable ParseWorkbook(IXLWorkbook workbook) + private IEnumerable ParseWorkbook(IXLWorkbook workbook) { var sheetPlannedTrajectory = workbook.Worksheets.FirstOrDefault(ws => ws.Name == sheetNamePlannedTrajectory); if (sheetPlannedTrajectory is null) @@ -156,7 +156,7 @@ namespace AsbCloudInfrastructure.Services.Trajectory return plannedTrajectoryRows; } - private IEnumerable ParseSheet(IXLWorksheet sheet) + private IEnumerable ParseSheet(IXLWorksheet sheet) { if (sheet.RangeUsed().RangeAddress.LastAddress.ColumnNumber < 15) throw new FileFormatException($"Лист {sheet.Name} содержит меньшее количество столбцов."); @@ -169,7 +169,7 @@ namespace AsbCloudInfrastructure.Services.Trajectory if (count <= 0) throw new FileFormatException($"Лист {sheet.Name} некорректного формата либо пустой"); - var trajectoryRows = new List(count); + var trajectoryRows = new List(count); var parseErrors = new List(); for (int i = 0; i < count; i++) { @@ -187,7 +187,7 @@ namespace AsbCloudInfrastructure.Services.Trajectory return trajectoryRows; } - private PlannedTrajectoryDto ParseRow(IXLRow row) + private TrajectoryGeoPlanDto ParseRow(IXLRow row) { var _wellboreDepth = row.Cell(ColumnWellboreDepth).Value; var _zenithAngle = row.Cell(ColumnZenithAngle).Value; @@ -205,7 +205,7 @@ namespace AsbCloudInfrastructure.Services.Trajectory var _orificeOffset = row.Cell(ColumnOrificeOffset).Value; var _comment = row.Cell(ColumnComment).Value; - var trajectoryRow = new PlannedTrajectoryDto(); + var trajectoryRow = new TrajectoryGeoPlanDto(); static double getDoubleValue(object value, string nameParam, IXLRow row) { diff --git a/AsbCloudInfrastructure/Services/Trajectory/TrajectoryService.cs b/AsbCloudInfrastructure/Services/Trajectory/TrajectoryService.cs new file mode 100644 index 00000000..6f65e1b9 --- /dev/null +++ b/AsbCloudInfrastructure/Services/Trajectory/TrajectoryService.cs @@ -0,0 +1,145 @@ +using AsbCloudApp.Data; +using AsbCloudApp.Repositories; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudInfrastructure.Services.Trajectory; + +abstract class TrajectoryBaseService + where TGeo : TrajectoryGeoDto + where TCartesian : TrajectoryCartesianDto, new() +{ + ITrajectoryRepository repository; + + public TrajectoryBaseService(ITrajectoryRepository repository) + { + this.repository = repository; + } + + protected class Location + { + public double North { get; set; } + public double East { get; set; } + public double Depth { get; set; } + public TrajectoryGeoDto Trajectory { get; set; } = null!; + } + + public async Task?> GetAsync(int idWell, CancellationToken token) + { + var geoCoords = await repository.GetAsync(idWell, token); + var locs = GetTrajectoryVisualisation(geoCoords); + var dtos = locs.Select(l => Convert(l)); + return dtos; + } + + private IEnumerable GetTrajectoryVisualisation(IEnumerable geoCoordinates) + { + var geoCoordinatesLength = geoCoordinates.Count(); + if (geoCoordinatesLength < 2) + return new Location[0]; + + var cartesianCoordinates = new Location[geoCoordinatesLength]; + cartesianCoordinates[0] = new(); + + var geoCoordinatesArray = geoCoordinates.OrderBy(c => c.WellboreDepth).ToArray(); + for (var i = 1; i < geoCoordinatesLength; i++) + { + var preCoordinates = cartesianCoordinates[i - 1]; + var coordinates = Calculate(cartesianCoordinates[i - 1], + geoCoordinatesArray[i - 1], + geoCoordinatesArray[i]); + + cartesianCoordinates[i] = coordinates; + } + + return cartesianCoordinates; + } + + protected Location Calculate(Location prevlocation, TrajectoryGeoDto prev, TrajectoryGeoDto current) + { + var intervalGeoParams = prev; + var deltaWellLength = current.WellboreDepth - intervalGeoParams.WellboreDepth; + var projectionLengthToXYSurface = deltaWellLength * Math.Sin(intervalGeoParams.ZenithAngle * Math.PI / 180); + + var dDepth = deltaWellLength * Math.Cos(intervalGeoParams.ZenithAngle * Math.PI / 180); + var dNorth = projectionLengthToXYSurface * Math.Sin(intervalGeoParams.AzimuthGeo * Math.PI / 180); + var dEast = projectionLengthToXYSurface * Math.Cos(intervalGeoParams.AzimuthGeo * Math.PI / 180); + + return new() + { + North = prevlocation.North + dNorth, + East = prevlocation.East + dEast, + Depth = prevlocation.Depth + dDepth, + Trajectory = current, + }; + } + + protected virtual TCartesian Convert(Location location) + { + var result = new TCartesian() + { + X = location.East, + Y = -location.Depth, + Z = -location.North, + }; + + return result; + } +} + +class TrajectoryPlanService: TrajectoryBaseService +{ + public TrajectoryPlanService(ITrajectoryPlanRepository repository) + :base(repository) + {} + + protected override TrajectoryCartesianPlanDto Convert(Location location) + { + var result = base.Convert(location); + if (location.Trajectory is TrajectoryGeoPlanDto trajectoryPlan) + { + result.Radius = trajectoryPlan.Radius; + result.Comment = trajectoryPlan.Comment; + } + return result; + } +} + +class TrajectoryFactService : TrajectoryBaseService +{ + public TrajectoryFactService(ITrajectoryFactRepository repository) + : base(repository) + { } +} + + +public class TrajectoryService +{ + private TrajectoryPlanService trajectoryPlanService; + private TrajectoryFactService trajectoryFactService; + + public TrajectoryService(ITrajectoryPlanRepository plannedRepository, ITrajectoryFactRepository factRepository) + { + trajectoryPlanService = new TrajectoryPlanService(plannedRepository); + trajectoryFactService = new TrajectoryFactService(factRepository); + } + + /// + /// Получение плановой и фактической траектории по скважине + /// + /// ключ скважины + /// + /// + public async Task, IEnumerable>> GetTrajectoryCartesianAsync(int idWell, CancellationToken token) + { + var result = new PlanFactBase, IEnumerable>(); + + result.Plan = await trajectoryPlanService.GetAsync(idWell, token); + result.Fact = await trajectoryFactService.GetAsync(idWell, token); + + return result; + } +} diff --git a/AsbCloudInfrastructure/Services/Trajectory/TrajectoryVisualizationBaseService.cs b/AsbCloudInfrastructure/Services/Trajectory/TrajectoryVisualizationBaseService.cs deleted file mode 100644 index 54d323eb..00000000 --- a/AsbCloudInfrastructure/Services/Trajectory/TrajectoryVisualizationBaseService.cs +++ /dev/null @@ -1,53 +0,0 @@ -using AsbCloudApp.Data; -using AsbCloudApp.Repositories; -using AsbCloudApp.Services; -using DocumentFormat.OpenXml.Spreadsheet; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace AsbCloudInfrastructure.Services.Trajectory -{ - public class TrajectoryVisualizationBaseService - { - private ITrajectoryVisualizationService planTrajectoryVisualizationService; - private ITrajectoryVisualizationService factTrajectoryVisualizationService; - - public TrajectoryVisualizationBaseService( - ITrajectoryVisualizationService _planTrajectoryVisualizationService, - ITrajectoryVisualizationService _factTrajectoryVisualizationService) - { - this.planTrajectoryVisualizationService = _planTrajectoryVisualizationService; - this.factTrajectoryVisualizationService = _factTrajectoryVisualizationService; - } - - /// - /// Получение плановой и фактической траектории по скважине - /// - /// ключ скважины - /// - /// - public async Task, IEnumerable>> GetTrajectoryAsync(int idWell, CancellationToken token) - { - var result = new PlanFactBase, IEnumerable>(); - - result.Plan = await planTrajectoryVisualizationService.GetVisualizationAsync(idWell, token); - result.Fact = await factTrajectoryVisualizationService.GetVisualizationAsync(idWell, token); - - return result; - } - - - protected void Calculate(TrajectoryDto prev, TrajectoryDto current) { - var intervalGeoParams = prev; - var deltaWellLength = current.WellboreDepth - intervalGeoParams.WellboreDepth; - var projectionLengthToXYSurface = deltaWellLength * Math.Sin(intervalGeoParams.ZenithAngle* Math.PI / 180); - - var dDepth = deltaWellLength * Math.Cos(intervalGeoParams.ZenithAngle * Math.PI / 180); - var dNorth = projectionLengthToXYSurface * Math.Sin(intervalGeoParams.AzimuthGeo * Math.PI / 180); - var dEast = projectionLengthToXYSurface * Math.Cos(intervalGeoParams.AzimuthGeo * Math.PI / 180); - } - } -} diff --git a/AsbCloudInfrastructure/Services/Trajectory/TrajectoryVisualizationFactService.cs b/AsbCloudInfrastructure/Services/Trajectory/TrajectoryVisualizationFactService.cs deleted file mode 100644 index 0a26ddb9..00000000 --- a/AsbCloudInfrastructure/Services/Trajectory/TrajectoryVisualizationFactService.cs +++ /dev/null @@ -1,76 +0,0 @@ -using AsbCloudApp.Data; -using AsbCloudApp.Repositories; -using AsbCloudApp.Services; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace AsbCloudInfrastructure.Services.Trajectory -{ - public class TrajectoryVisualizationFactService : ITrajectoryVisualizationService - { - private readonly IActualTrajectoryRepository actualRepository; - - public TrajectoryVisualizationFactService(IActualTrajectoryRepository actualRepository) - { - this.actualRepository = actualRepository; - } - - /// - /// Визуализация для фактической траектории по скважине - /// - /// ключ скважины - /// - /// - public async Task> GetVisualizationAsync(int idWell, CancellationToken token) - { - var geoFactCoordinates = await actualRepository.GetTrajectoryAsync(idWell, token); - - var visualization = GetTrajectoryVisualisation(geoFactCoordinates); - return visualization; - } - - record struct Location(double North, double East, double Depth); - - - /// - /// Формирует список координат для визуализации трактории 3D - /// - /// - /// - private IEnumerable GetTrajectoryVisualisation(IEnumerable geoCoordinates) - { - var geoCoordinatesLength = geoCoordinates.Count(); - if (geoCoordinatesLength < 2) - return new TrajectoryVisualizationFactDto[0]; - - var cartesianCoordinates = new Location[geoCoordinatesLength]; - cartesianCoordinates[0] = new(); - - var geoCoordinatesArray = geoCoordinates.OrderBy(c => c.WellboreDepth).ToArray(); - for (var i = 1; i < geoCoordinatesLength; i++) - { - var intervalGeoParams = geoCoordinatesArray[i - 1]; - var deltaWellLength = geoCoordinatesArray[i].WellboreDepth - intervalGeoParams.WellboreDepth; - var projectionLengthToXYSurface = deltaWellLength * Math.Sin(intervalGeoParams.ZenithAngle * Math.PI / 180); - - var dDepth = deltaWellLength * Math.Cos(intervalGeoParams.ZenithAngle * Math.PI / 180); - var dNorth = projectionLengthToXYSurface * Math.Sin(intervalGeoParams.AzimuthGeo * Math.PI / 180); - var dEast = projectionLengthToXYSurface * Math.Cos(intervalGeoParams.AzimuthGeo * Math.PI / 180); - - var preCoordinates = cartesianCoordinates[i - 1]; - var coordinates = new Location( - preCoordinates.North + dNorth, - preCoordinates.East + dEast, - preCoordinates.Depth + dDepth); - - cartesianCoordinates[i] = coordinates; - } - - return cartesianCoordinates.Select(location => new TrajectoryVisualizationFactDto { X = location.East, Y = - location.Depth, Z = - location.North}); - } - } - -} diff --git a/AsbCloudInfrastructure/Services/Trajectory/TrajectoryVisualizationPlanService.cs b/AsbCloudInfrastructure/Services/Trajectory/TrajectoryVisualizationPlanService.cs deleted file mode 100644 index 06ff2aef..00000000 --- a/AsbCloudInfrastructure/Services/Trajectory/TrajectoryVisualizationPlanService.cs +++ /dev/null @@ -1,84 +0,0 @@ -using AsbCloudApp.Data; -using AsbCloudApp.Repositories; -using AsbCloudApp.Services; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace AsbCloudInfrastructure.Services.Trajectory -{ - public class TrajectoryVisualizationPlanService : ITrajectoryVisualizationService - { - private readonly IPlannedTrajectoryRepository plannedRepository; - - public TrajectoryVisualizationPlanService(IPlannedTrajectoryRepository plannedRepository) - { - this.plannedRepository = plannedRepository; - } - - /// - /// Визуализация для плановой траектории по скважине - /// - /// ключ скважины - /// - /// - public async Task> GetVisualizationAsync(int idWell, CancellationToken token) - { - var coords = await plannedRepository.GetTrajectoryAsync(idWell, token); - return GetTrajectoryVisualisation(coords); - } - - - - - /// - /// Формирует список координат для визуализации трактории 3D - /// - /// - /// - private IEnumerable GetTrajectoryVisualisation(IEnumerable geoCoordinates) - { - var geoCoordinatesLength = geoCoordinates.Count(); - if (geoCoordinatesLength < 2) - return new TrajectoryVisualizationPlanDto[0]; - - var cartesianCoordinates = new Location[geoCoordinatesLength]; - cartesianCoordinates[0] = new(); - - var geoCoordinatesArray = geoCoordinates.OrderBy(c => c.WellboreDepth).ToArray(); - for (var i = 1; i < geoCoordinatesLength; i++) - { - var intervalGeoParams = geoCoordinatesArray[i - 1]; - var deltaWellLength = geoCoordinatesArray[i].WellboreDepth - intervalGeoParams.WellboreDepth; - var projectionLengthToXYSurface = deltaWellLength * Math.Sin(intervalGeoParams.ZenithAngle * Math.PI / 180); - - var dDepth = deltaWellLength * Math.Cos(intervalGeoParams.ZenithAngle * Math.PI / 180); - var dNorth = projectionLengthToXYSurface * Math.Sin(intervalGeoParams.AzimuthGeo * Math.PI / 180); - var dEast = projectionLengthToXYSurface * Math.Cos(intervalGeoParams.AzimuthGeo * Math.PI / 180); - - var preCoordinates = cartesianCoordinates[i - 1]; - var coordinates = new Location( - preCoordinates.North + dNorth, - preCoordinates.East + dEast, - preCoordinates.Depth + dDepth, - geoCoordinatesArray[i].Radius, - geoCoordinatesArray[i].Comment - ); - - cartesianCoordinates[i] = coordinates; - } - - return cartesianCoordinates.Select(location => new TrajectoryVisualizationPlanDto { - X = location.East, - Y = -location.Depth, - Z = -location.North, - Comment = location.Comment, - Radius = location.Radius - }); - } - - } - -} diff --git a/AsbCloudWebApi.Tests/ServicesTests/TrajectoryVisualizationServiceTest.cs b/AsbCloudWebApi.Tests/ServicesTests/TrajectoryVisualizationServiceTest.cs index 24495f95..58abdf1d 100644 --- a/AsbCloudWebApi.Tests/ServicesTests/TrajectoryVisualizationServiceTest.cs +++ b/AsbCloudWebApi.Tests/ServicesTests/TrajectoryVisualizationServiceTest.cs @@ -13,12 +13,12 @@ namespace AsbCloudWebApi.Tests.ServicesTests { public class TrajectoryVisualizationServiceTest { - private Mock MakeTrajectoryRepositoryMock(IEnumerable dateForGetMethod) - where T : class, ITrajectoryRepository + private Mock MakeTrajectoryRepositoryMock(IEnumerable dateForGetMethod) + where T : class, ITrajectoryPlanRepository { var mock = new Mock(); - mock.Setup(r => r.GetTrajectoryAsync(It.IsAny(), It.IsAny())) + mock.Setup(r => r.GetAsync(It.IsAny(), It.IsAny())) .Returns(Task.FromResult(dateForGetMethod)); return mock; @@ -27,7 +27,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests [Fact] public async Task GetTrajectoryAsync_SameCounts() { - var plannedTrajectory = new TrajectoryFactDto[] + var plannedTrajectory = new TrajectoryGeoFactDto[] { new(0d, 0d, 0d), new(0d, 0d, 10d), @@ -37,17 +37,17 @@ namespace AsbCloudWebApi.Tests.ServicesTests new(0d, 0d, 50d), }; - var actualTrajectory = new TrajectoryFactDto[] + var actualTrajectory = new TrajectoryGeoFactDto[] { new(0, 0, 0), new(30,30,10), new(0, 0, 20), }; - var mockPlan = MakeTrajectoryRepositoryMock(plannedTrajectory); - var mockFact = MakeTrajectoryRepositoryMock(actualTrajectory); - var service = new TrajectoryVisualizationService(mockPlan.Object, mockFact.Object); - var result = await service.GetTrajectoryAsync(1, CancellationToken.None); + var mockPlan = MakeTrajectoryRepositoryMock(plannedTrajectory); + var mockFact = MakeTrajectoryRepositoryMock(actualTrajectory); + var service = new TrajectoryService(mockPlan.Object, mockFact.Object); + var result = await service.GetTrajectoryCartesianAsync(1, CancellationToken.None); Assert.Equal(plannedTrajectory.Length, result.Plan?.Count()); Assert.Equal(actualTrajectory.Length, result.Fact?.Count()); } @@ -55,7 +55,7 @@ namespace AsbCloudWebApi.Tests.ServicesTests [Fact] public async Task GetTrajectoryAsync_StraigthBore() { - var trajectory = new TrajectoryFactDto[] + var trajectory = new TrajectoryGeoFactDto[] { new(0, 0, 0), new(0, 0, 0), @@ -65,10 +65,10 @@ namespace AsbCloudWebApi.Tests.ServicesTests new(50, 0, 0), }; - var mockPlan = MakeTrajectoryRepositoryMock(trajectory); - var mockFact = MakeTrajectoryRepositoryMock(trajectory); - var service = new TrajectoryVisualizationService(mockPlan.Object, mockFact.Object); - var result = await service.GetTrajectoryAsync(1, CancellationToken.None); + var mockPlan = MakeTrajectoryRepositoryMock(trajectory); + var mockFact = MakeTrajectoryRepositoryMock(trajectory); + var service = new TrajectoryService(mockPlan.Object, mockFact.Object); + var result = await service.GetTrajectoryCartesianAsync(1, CancellationToken.None); var lastPointPlan = result.Plan!.Last(); var lastPointFact = result.Fact!.Last(); @@ -84,17 +84,17 @@ namespace AsbCloudWebApi.Tests.ServicesTests [Fact] public async Task GetTrajectoryAsync_Match() { - var trajectory = new TrajectoryFactDto[] + var trajectory = new TrajectoryGeoFactDto[] { new(0, 0, 0), new(10, 30, 30), new(20, 0, 0), }; - var mockPlanned = MakeTrajectoryRepositoryMock(trajectory); - var mockFactual = MakeTrajectoryRepositoryMock(trajectory); - var service = new TrajectoryVisualizationService(mockPlanned.Object, mockFactual.Object); - var result = await service.GetTrajectoryAsync(1, CancellationToken.None); + var mockPlanned = MakeTrajectoryRepositoryMock(trajectory); + var mockFactual = MakeTrajectoryRepositoryMock(trajectory); + var service = new TrajectoryService(mockPlanned.Object, mockFactual.Object); + var result = await service.GetTrajectoryCartesianAsync(1, CancellationToken.None); var lastPointPlan = result.Plan!.Last(); var lastPointFact = result.Fact!.Last(); var tolerancePlan = 0.001d; diff --git a/AsbCloudWebApi/Controllers/PlannedTrajectoryController.cs b/AsbCloudWebApi/Controllers/PlannedTrajectoryController.cs index 86032556..1e8b667d 100644 --- a/AsbCloudWebApi/Controllers/PlannedTrajectoryController.cs +++ b/AsbCloudWebApi/Controllers/PlannedTrajectoryController.cs @@ -23,13 +23,13 @@ namespace AsbCloudWebApi.Controllers { private readonly IWellService wellService; private readonly IPlannedTrajectoryImportService plannedTrajectoryImportService; - private readonly IPlannedTrajectoryRepository plannedTrajectoryRepository; - private readonly TrajectoryVisualizationBaseService trajectoryVisualizationService; + private readonly ITrajectoryPlanRepository plannedTrajectoryRepository; + private readonly TrajectoryService trajectoryVisualizationService; public PlannedTrajectoryController(IWellService wellService, IPlannedTrajectoryImportService plannedTrajectoryImportService, - IPlannedTrajectoryRepository plannedTrajectoryRepository, - TrajectoryVisualizationBaseService trajectoryVisualizationService) + ITrajectoryPlanRepository plannedTrajectoryRepository, + TrajectoryService trajectoryVisualizationService) { this.plannedTrajectoryImportService = plannedTrajectoryImportService; this.wellService = wellService; @@ -119,7 +119,7 @@ namespace AsbCloudWebApi.Controllers /// Список добавленных координат плановой траектории [HttpGet] [Route("getRows")] - [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] + [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)] public async Task GetAsync([FromRoute] int idWell, CancellationToken token = default) { if (!await CanUserAccessToWellAsync(idWell, @@ -139,7 +139,7 @@ namespace AsbCloudWebApi.Controllers [HttpPost] [Route("addRow")] [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task AddAsync(int idWell, [FromBody] PlannedTrajectoryDto row, + public async Task AddAsync(int idWell, [FromBody] TrajectoryGeoPlanDto row, CancellationToken token = default) { if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) @@ -163,7 +163,7 @@ namespace AsbCloudWebApi.Controllers [HttpPost] [Route("addRangeRows")] [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] - public async Task AddRangeAsync(int idWell, [FromBody] IEnumerable rows, + public async Task AddRangeAsync(int idWell, [FromBody] IEnumerable rows, CancellationToken token = default) { if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) @@ -191,7 +191,7 @@ namespace AsbCloudWebApi.Controllers [HttpPut("{idRow}")] [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] public async Task UpdateAsync(int idWell, int idRow, - [FromBody] PlannedTrajectoryDto row, CancellationToken token = default) + [FromBody] TrajectoryGeoPlanDto row, CancellationToken token = default) { if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) return Forbid(); @@ -232,14 +232,14 @@ namespace AsbCloudWebApi.Controllers /// /// [HttpGet] - [ProducesResponseType(typeof(PlanFactBase, IEnumerable>), (int)System.Net.HttpStatusCode.OK)] - public async Task GetPlanFactTrajectoryAsync(int idWell, CancellationToken token) + [ProducesResponseType(typeof(PlanFactBase, IEnumerable>), (int)System.Net.HttpStatusCode.OK)] + public async Task GetTrajectoryCartesianPlanFactAsync(int idWell, CancellationToken token) { if (!await CanUserAccessToWellAsync(idWell, token).ConfigureAwait(false)) return Forbid(); - var result = await trajectoryVisualizationService.GetTrajectoryAsync(idWell, token); + var result = await trajectoryVisualizationService.GetTrajectoryCartesianAsync(idWell, token); return Ok(result); }