diff --git a/AsbCloudApp/Data/TrajectoryVisualizationDataDto.cs b/AsbCloudApp/Data/TrajectoryVisualizationDataDto.cs
new file mode 100644
index 00000000..7fbce489
--- /dev/null
+++ b/AsbCloudApp/Data/TrajectoryVisualizationDataDto.cs
@@ -0,0 +1,41 @@
+namespace AsbCloudDb.Model
+{
+#nullable enable
+ ///
+ /// Данные для визуализации траектории
+ ///
+ public class TrajectoryVisualizationDataDto
+ {
+
+ ///
+ /// Глубина по стволу
+ ///
+ public double WellboreDepth { get; set; }
+
+ ///
+ /// Зенит
+ ///
+ public double Zenith { get; set; }
+
+ ///
+ /// Азимут
+ ///
+ public double Azimuth { get; set; }
+
+ ///
+ /// Координаты по оси X
+ ///
+ public double X { get; set; }
+
+ ///
+ /// Координаты по оси Y
+ ///
+ public double Y { get; set; }
+
+ ///
+ /// Координаты по оси Z
+ ///
+ public double Z { get; set; }
+ }
+#nullable disable
+}
diff --git a/AsbCloudApp/Data/TrajectoryVisualizationDto.cs b/AsbCloudApp/Data/TrajectoryVisualizationDto.cs
new file mode 100644
index 00000000..3d8cbe8c
--- /dev/null
+++ b/AsbCloudApp/Data/TrajectoryVisualizationDto.cs
@@ -0,0 +1,32 @@
+namespace AsbCloudApp.Data
+{
+ ///
+ /// Визуализация траектории 3D
+ ///
+ public class TrajectoryVisualizationDto : IWellRelated
+ {
+
+ ///
+ public int IdWell { get; set; }
+
+ ///
+ /// Плоскость
+ ///
+ public double Flat { get; set; }
+
+ ///
+ /// Координаты по оси X
+ ///
+ public double X { get; set; }
+
+ ///
+ /// Координаты по оси Y
+ ///
+ public double Y { get; set; }
+
+ ///
+ /// Координаты по оси Z
+ ///
+ public double Z { get; set; }
+ }
+}
diff --git a/AsbCloudApp/Repositories/ITrajectoryVisualizationRepository.cs b/AsbCloudApp/Repositories/ITrajectoryVisualizationRepository.cs
new file mode 100644
index 00000000..24cb646b
--- /dev/null
+++ b/AsbCloudApp/Repositories/ITrajectoryVisualizationRepository.cs
@@ -0,0 +1,23 @@
+using AsbCloudDb.Model;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace AsbCloudApp.Repositories
+{
+#nullable enable
+ ///
+ /// Визуализация траектории 3D
+ ///
+ public interface ITrajectoryVisualizationRepository
+ {
+ ///
+ /// Получение данных для расчета
+ ///
+ ///
+ ///
+ ///
+ Task> GetAllAsync(int idWell, CancellationToken token);
+ }
+#nullable disable
+}
diff --git a/AsbCloudApp/Services/ITrajectoryVisualizationService.cs b/AsbCloudApp/Services/ITrajectoryVisualizationService.cs
new file mode 100644
index 00000000..a387e501
--- /dev/null
+++ b/AsbCloudApp/Services/ITrajectoryVisualizationService.cs
@@ -0,0 +1,23 @@
+using AsbCloudApp.Data;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace AsbCloudApp.Services
+{
+#nullable enable
+ ///
+ /// Сервис "Визуализация траектории 3D"
+ ///
+ public interface ITrajectoryVisualizationService
+ {
+ ///
+ /// Получение траектории по скважине
+ ///
+ ///
+ ///
+ ///
+ Task> GetTrajectoryAsync(int idWell, CancellationToken token);
+ }
+#nullable disable
+}
diff --git a/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj b/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj
index 1a8e2432..3e674968 100644
--- a/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj
+++ b/AsbCloudInfrastructure/AsbCloudInfrastructure.csproj
@@ -72,4 +72,8 @@
+
+
+
+
diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs
index dcc2eb70..32a6f490 100644
--- a/AsbCloudInfrastructure/DependencyInjection.cs
+++ b/AsbCloudInfrastructure/DependencyInjection.cs
@@ -140,6 +140,7 @@ namespace AsbCloudInfrastructure
services.AddTransient();
services.AddTransient();
services.AddTransient();
+ services.AddTransient();
// admin crud services:
services.AddTransient, CrudCacheRepositoryBase>(s =>
@@ -177,6 +178,7 @@ namespace AsbCloudInfrastructure
services.AddTransient();
services.AddTransient();
services.AddTransient();
+ services.AddTransient();
// Subsystem service
services.AddTransient, CrudCacheRepositoryBase>();
diff --git a/AsbCloudInfrastructure/Repository/TrajectoryVisualizationRepository.cs b/AsbCloudInfrastructure/Repository/TrajectoryVisualizationRepository.cs
new file mode 100644
index 00000000..76b11e7a
--- /dev/null
+++ b/AsbCloudInfrastructure/Repository/TrajectoryVisualizationRepository.cs
@@ -0,0 +1,44 @@
+using AsbCloudApp.Repositories;
+using AsbCloudDb.Model;
+using Microsoft.EntityFrameworkCore;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace AsbCloudInfrastructure.Repository
+{
+#nullable enable
+ public class TrajectoryVisualizationRepository : ITrajectoryVisualizationRepository
+ {
+ private readonly IAsbCloudDbContext context;
+
+ public TrajectoryVisualizationRepository(IAsbCloudDbContext context)
+ {
+ this.context = context;
+ }
+
+ ///
+ public async Task> GetAllAsync(int idWell, CancellationToken token)
+ {
+ var dtos = await context.PlannedTrajectories
+ .Where(t => t.IdWell == idWell)
+ .OrderBy(x => x.UpdateDate)
+ .Select(x => Convert(x))
+ .ToListAsync(token)
+ .ConfigureAwait(false);
+
+ return dtos;
+ }
+
+ private static TrajectoryVisualizationDataDto Convert(PlannedTrajectory dto)
+ {
+ return new TrajectoryVisualizationDataDto {
+ WellboreDepth = dto.WellboreDepth,
+ Azimuth = dto.AzimuthGeo,
+ Zenith = dto.ZenithAngle
+ };
+ }
+ }
+#nullable disable
+}
diff --git a/AsbCloudInfrastructure/Services/TrajectoryVisualizationService.cs b/AsbCloudInfrastructure/Services/TrajectoryVisualizationService.cs
new file mode 100644
index 00000000..97aae641
--- /dev/null
+++ b/AsbCloudInfrastructure/Services/TrajectoryVisualizationService.cs
@@ -0,0 +1,63 @@
+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
+{
+ public class TrajectoryVisualizationService : ITrajectoryVisualizationService
+ {
+ private readonly ITrajectoryVisualizationRepository repository;
+
+ public TrajectoryVisualizationService(ITrajectoryVisualizationRepository repository)
+ {
+ this.repository = repository;
+ }
+
+ public async Task> GetTrajectoryAsync(int idWell, CancellationToken token)
+ {
+ var result = new List();
+ var dto = (await repository.GetAllAsync(idWell, token)).ToArray();
+
+ var prevData = dto[0];
+ for (var i = 1; i < dto.Length; i++)
+ {
+ var data = dto[i];
+ var flat = GetFlat(data.WellboreDepth, prevData.WellboreDepth, data.Zenith);
+ var x = data.X = GetX(data.Azimuth, flat, prevData.X);
+ var y = data.Y = GetY(data.Azimuth, flat, prevData.Y);
+ var z = data.Z = GetZ(data.WellboreDepth, prevData.WellboreDepth, data.Zenith, prevData.Z);
+ prevData = data;
+
+ var coordinates = new TrajectoryVisualizationDto
+ {
+ IdWell = idWell,
+ Flat = flat,
+ X = x,
+ Y = y,
+ Z = z
+ };
+
+ result.Add(coordinates);
+ }
+
+ return result;
+ }
+
+ private double GetFlat(double depthEnd, double depthStart, double zenit) =>
+ (depthEnd - depthStart) * Math.Sin(zenit * Math.PI / 180);
+
+ private double GetX(double azimuth, double flat, double prev) =>
+ (prev + flat) * Math.Sin(azimuth * Math.PI / 180);
+
+ private double GetY(double azimuth, double flat, double prev) =>
+ prev + flat * Math.Cos(azimuth * Math.PI / 180);
+
+ private double GetZ(double depthEnd, double depthStart, double zenit, double prev) =>
+ prev - (depthEnd - depthStart) * Math.Cos(zenit * Math.PI / 180);
+ }
+}
diff --git a/AsbCloudWebApi/Controllers/TrajectoryVisualizationController.cs b/AsbCloudWebApi/Controllers/TrajectoryVisualizationController.cs
new file mode 100644
index 00000000..1ba99178
--- /dev/null
+++ b/AsbCloudWebApi/Controllers/TrajectoryVisualizationController.cs
@@ -0,0 +1,34 @@
+using AsbCloudApp.Data;
+using AsbCloudApp.Services;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using System.Threading.Tasks;
+using System.Threading;
+using System.Collections.Generic;
+
+namespace AsbCloudWebApi.Controllers
+{
+ ///
+ /// Визуализация траектории 3D
+ ///
+ [Route("api/[controller]")]
+ [ApiController]
+ [Authorize]
+ public class TrajectoryVisualizationController : ControllerBase
+ {
+ private readonly ITrajectoryVisualizationService service;
+
+ public TrajectoryVisualizationController(ITrajectoryVisualizationService service)
+ {
+ this.service = service;
+ }
+
+ [HttpGet]
+ [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)]
+ public async Task GetTrajectoryAsync(int idWell, CancellationToken token)
+ {
+ var result = await service.GetTrajectoryAsync(idWell, token);
+ return Ok(result);
+ }
+ }
+}