diff --git a/AsbCloudApp/Data/TrajectoryDto.cs b/AsbCloudApp/Data/TrajectoryDto.cs
new file mode 100644
index 00000000..80c965f4
--- /dev/null
+++ b/AsbCloudApp/Data/TrajectoryDto.cs
@@ -0,0 +1,13 @@
+namespace AsbCloudApp.Data
+{
+ ///
+ /// Формирование визуализации траектории 3D
+ ///
+ /// Глубина ствола
+ /// Зенитный угол
+ /// Азимут географиеский
+ public record TrajectoryDto(
+ double WellboreDepth,
+ double ZenithAngle,
+ double AzimuthGeo);
+}
diff --git a/AsbCloudApp/Repositories/IActualTrajectoryRepository.cs b/AsbCloudApp/Repositories/IActualTrajectoryRepository.cs
new file mode 100644
index 00000000..76c1648d
--- /dev/null
+++ b/AsbCloudApp/Repositories/IActualTrajectoryRepository.cs
@@ -0,0 +1,17 @@
+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
+ {
+
+ }
+}
diff --git a/AsbCloudApp/Repositories/IPlannedTrajectoryRepository.cs b/AsbCloudApp/Repositories/IPlannedTrajectoryRepository.cs
index 94f19162..85362f9f 100644
--- a/AsbCloudApp/Repositories/IPlannedTrajectoryRepository.cs
+++ b/AsbCloudApp/Repositories/IPlannedTrajectoryRepository.cs
@@ -9,7 +9,7 @@ namespace AsbCloudApp.Repositories
/// CRUD для работы с плановой траекторией из клиента
///
///
- public interface IPlannedTrajectoryRepository
+ public interface IPlannedTrajectoryRepository : ITrajectoryRepository
{
///
/// Получить все добавленные по скважине координаты плановой траектории
diff --git a/AsbCloudApp/Repositories/ITrajectoryRepository.cs b/AsbCloudApp/Repositories/ITrajectoryRepository.cs
new file mode 100644
index 00000000..123f1669
--- /dev/null
+++ b/AsbCloudApp/Repositories/ITrajectoryRepository.cs
@@ -0,0 +1,24 @@
+using AsbCloudApp.Data;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace AsbCloudApp.Repositories
+{
+ ///
+ /// Репозиторий по работе с траекторией
+ ///
+ public interface ITrajectoryRepository
+ {
+ ///
+ /// Получение траектории для 3D-визуализации
+ ///
+ /// ключ скважины
+ ///
+ ///
+ Task> GetTrajectoryAsync(int idWell, CancellationToken token);
+ }
+}
diff --git a/AsbCloudApp/Services/ITrajectoryVisualizationService.cs b/AsbCloudApp/Services/ITrajectoryVisualizationService.cs
index 31d77271..286a81d5 100644
--- a/AsbCloudApp/Services/ITrajectoryVisualizationService.cs
+++ b/AsbCloudApp/Services/ITrajectoryVisualizationService.cs
@@ -11,11 +11,11 @@ namespace AsbCloudApp.Services
public interface ITrajectoryVisualizationService
{
///
- /// Получение траектории по скважине
+ /// Получение плановой и фактической траектории по скважине
///
- ///
+ /// ключ скважины
///
///
- Task> GetTrajectoryAsync(int idWell, CancellationToken token);
+ Task>> GetTrajectoryAsync(int idWell, CancellationToken token);
}
}
diff --git a/AsbCloudDb/Model/WITS/Record7.cs b/AsbCloudDb/Model/WITS/Record7.cs
index d856f8a7..0b768243 100644
--- a/AsbCloudDb/Model/WITS/Record7.cs
+++ b/AsbCloudDb/Model/WITS/Record7.cs
@@ -12,6 +12,7 @@ namespace AsbCloudDb.Model.WITS
{
///
+ ///
/// RecordId = 7,
/// ItemId = 8,
/// LongMnemonic = "DEPTSVYM",
@@ -87,6 +88,7 @@ namespace AsbCloudDb.Model.WITS
public string? Svytype { get; set; }
///
+ ///
/// RecordId = 7,
/// ItemId = 13,
/// LongMnemonic = "SVYINC",
@@ -117,6 +119,7 @@ namespace AsbCloudDb.Model.WITS
public float? Svyazu { get; set; }
///
+ ///
/// RecordId = 7,
/// ItemId = 15,
/// LongMnemonic = "SVYAZC",
diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs
index 7952b1f4..1911d5a8 100644
--- a/AsbCloudInfrastructure/DependencyInjection.cs
+++ b/AsbCloudInfrastructure/DependencyInjection.cs
@@ -180,6 +180,7 @@ namespace AsbCloudInfrastructure
services.AddTransient();
services.AddTransient();
services.AddTransient();
+ services.AddTransient();
services.AddTransient();
// Subsystem service
diff --git a/AsbCloudInfrastructure/Repository/ActualTrajectoryRepository.cs b/AsbCloudInfrastructure/Repository/ActualTrajectoryRepository.cs
new file mode 100644
index 00000000..b89c9cf8
--- /dev/null
+++ b/AsbCloudInfrastructure/Repository/ActualTrajectoryRepository.cs
@@ -0,0 +1,46 @@
+using AsbCloudApp.Data;
+using AsbCloudApp.Exceptions;
+using AsbCloudApp.Repositories;
+using AsbCloudApp.Services;
+using AsbCloudDb.Model;
+using Microsoft.EntityFrameworkCore;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace AsbCloudInfrastructure.Repository
+{
+ internal class ActualTrajectoryRepository : IActualTrajectoryRepository
+ {
+ private readonly IAsbCloudDbContext db;
+ private readonly IWellService wellService;
+ public ActualTrajectoryRepository(IAsbCloudDbContext db, IWellService wellService)
+ {
+ this.db = db;
+ this.wellService = wellService;
+ }
+
+ 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 entities = await db.Record7
+ .AsNoTracking()
+ .Where(x => x.IdTelemetry == well.IdTelemetry)
+ .Where(coord => coord.Deptsvym != null && coord.Svyinc != null && coord.Svyazc != null)
+ .OrderBy(e => e.Deptsvym)
+ .Select(x => new { x.Deptsvym, x.Svyinc, x.Svyazc })
+ .ToArrayAsync(token);
+
+ var result = entities
+ .Select(coord => new TrajectoryDto(coord.Deptsvym!.Value, coord.Svyinc!.Value, coord.Svyazc!.Value))
+ .ToArray();
+
+ return result;
+ }
+ }
+}
diff --git a/AsbCloudInfrastructure/Repository/PlannedTrajectoryRepository.cs b/AsbCloudInfrastructure/Repository/PlannedTrajectoryRepository.cs
index 0db7022d..d09b9690 100644
--- a/AsbCloudInfrastructure/Repository/PlannedTrajectoryRepository.cs
+++ b/AsbCloudInfrastructure/Repository/PlannedTrajectoryRepository.cs
@@ -86,7 +86,7 @@ namespace AsbCloudInfrastructure.Repository
.Where(x => x.IdWell == idWell);
var entities = await query
.OrderBy(e => e.WellboreDepth)
- .ToListAsync(token);
+ .ToArrayAsync(token);
var result = entities
.Select(r => Convert(r, offsetHours));
return result;
@@ -115,6 +115,22 @@ namespace AsbCloudInfrastructure.Repository
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 TrajectoryDto(coord.WellboreDepth, coord.ZenithAngle, coord.AzimuthGeo))
+ .ToArrayAsync()
+ .ConfigureAwait(false);
+ }
}
}
diff --git a/AsbCloudInfrastructure/Services/Trajectory/TrajectoryVisualizationService.cs b/AsbCloudInfrastructure/Services/Trajectory/TrajectoryVisualizationService.cs
index 8eb94b5a..6e298a37 100644
--- a/AsbCloudInfrastructure/Services/Trajectory/TrajectoryVisualizationService.cs
+++ b/AsbCloudInfrastructure/Services/Trajectory/TrajectoryVisualizationService.cs
@@ -12,28 +12,53 @@ namespace AsbCloudInfrastructure.Services.Trajectory
public class TrajectoryVisualizationService : ITrajectoryVisualizationService
{
- private readonly IPlannedTrajectoryRepository repository;
+ private readonly IPlannedTrajectoryRepository plannedRepository;
+ private readonly IActualTrajectoryRepository factualRepository;
- public TrajectoryVisualizationService(IPlannedTrajectoryRepository repository)
+ public TrajectoryVisualizationService(IPlannedTrajectoryRepository plannedRepository, IActualTrajectoryRepository factualRepository)
{
- this.repository = repository;
+ this.plannedRepository = plannedRepository;
+ this.factualRepository = factualRepository;
}
- public async Task> GetTrajectoryAsync(int idWell, CancellationToken token)
+ ///
+ /// Получение плановой и фактической траектории по скважине
+ ///
+ /// ключ скважины
+ ///
+ ///
+ public async Task>> GetTrajectoryAsync(int idWell, CancellationToken token)
{
- var geoCoordinates = (await repository.GetAsync(idWell, token)).ToArray();
+ var result = new PlanFactBase>();
- if (geoCoordinates.Length < 2)
- return Enumerable.Empty();
+ var geoPlanCoordinates = await plannedRepository.GetTrajectoryAsync(idWell, token);
+ var geoFactCoordinates = await factualRepository.GetTrajectoryAsync(idWell, token);
- var cartesianCoordinates = new List(geoCoordinates.Length) {
- new (),
- };
+ result.Plan = GetTrajectoryVisualisation(geoPlanCoordinates);
+ result.Fact = GetTrajectoryVisualisation(geoFactCoordinates);
- for (var i = 1; i < geoCoordinates.Length; i++)
+ return result;
+ }
+
+ ///
+ /// Формирует список координат для визуализации трактории 3D
+ ///
+ ///
+ ///
+ private IEnumerable GetTrajectoryVisualisation(IEnumerable geoCoordinates)
+ {
+ var geoCoordinatesLength = geoCoordinates.Count();
+ if (geoCoordinatesLength < 2)
+ return new TrajectoryVisualizationDto[0];
+
+ var cartesianCoordinates = new TrajectoryVisualizationDto[geoCoordinatesLength];
+ cartesianCoordinates[0] = new();
+
+ var geoCoordinatesArray = geoCoordinates.ToArray();
+ for (var i = 1; i < geoCoordinatesLength; i++)
{
- var intervalGeoParams = geoCoordinates[i - 1];
- var deltaWellLength = geoCoordinates[i].WellboreDepth - intervalGeoParams.WellboreDepth;
+ var intervalGeoParams = geoCoordinatesArray[i - 1];
+ var deltaWellLength = geoCoordinatesArray[i].WellboreDepth - intervalGeoParams.WellboreDepth;
var projectionLengthToXYSurface = deltaWellLength * Math.Sin(intervalGeoParams.ZenithAngle * Math.PI / 180);
var dz = deltaWellLength * Math.Cos(intervalGeoParams.ZenithAngle * Math.PI / 180);
@@ -48,7 +73,7 @@ namespace AsbCloudInfrastructure.Services.Trajectory
Y = preCoordinates.Y + dy,
};
- cartesianCoordinates.Add(coordinates);
+ cartesianCoordinates[i] = coordinates;
}
return cartesianCoordinates;
diff --git a/AsbCloudWebApi.Tests/ServicesTests/TrajectoryVisualizationServiceTest.cs b/AsbCloudWebApi.Tests/ServicesTests/TrajectoryVisualizationServiceTest.cs
index f4532d7c..1a0dab1b 100644
--- a/AsbCloudWebApi.Tests/ServicesTests/TrajectoryVisualizationServiceTest.cs
+++ b/AsbCloudWebApi.Tests/ServicesTests/TrajectoryVisualizationServiceTest.cs
@@ -1,9 +1,8 @@
using AsbCloudApp.Data;
+using AsbCloudApp.Data.WITS;
using AsbCloudApp.Repositories;
-using AsbCloudInfrastructure.Services;
using AsbCloudInfrastructure.Services.Trajectory;
using Moq;
-using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
@@ -14,11 +13,12 @@ namespace AsbCloudWebApi.Tests.ServicesTests
{
public class TrajectoryVisualizationServiceTest
{
- private Mock MakePlannedTrajectoryRepositoryMock(IEnumerable dateForGetMethod)
+ private Mock MakeTrajectoryRepositoryMock(IEnumerable dateForGetMethod)
+ where T : class, ITrajectoryRepository
{
- var mock = new Mock();
+ var mock = new Mock();
- mock.Setup(r => r.GetAsync(It.IsAny(), It.IsAny()))
+ mock.Setup(r => r.GetTrajectoryAsync(It.IsAny(), It.IsAny()))
.Returns(Task.FromResult(dateForGetMethod));
return mock;
@@ -27,65 +27,86 @@ namespace AsbCloudWebApi.Tests.ServicesTests
[Fact]
public async Task GetTrajectoryAsync_SameCounts()
{
- var plannedTrajectory = new PlannedTrajectoryDto[]
+ var plannedTrajectory = new TrajectoryDto[]
{
- new() { AzimuthGeo = 0d, ZenithAngle = 0d, WellboreDepth = 0d},
- new() { AzimuthGeo = 0d, ZenithAngle = 0d, WellboreDepth = 10d},
- new() { AzimuthGeo = 0d, ZenithAngle = 30d, WellboreDepth = 20d},
- new() { AzimuthGeo = 30d, ZenithAngle = 0d, WellboreDepth = 30d},
- new() { AzimuthGeo = 30d, ZenithAngle = 90d, WellboreDepth = 40d},
- new() { AzimuthGeo = 0d, ZenithAngle = 0d, WellboreDepth = 50d},
+ new(0d, 0d, 0d),
+ new(0d, 0d, 10d),
+ new(0d, 30d, 20d),
+ new(30d, 0d, 30d),
+ new(30d, 90d, 40d),
+ new(0d, 0d, 50d),
};
- var mock = MakePlannedTrajectoryRepositoryMock(plannedTrajectory);
- var service = new TrajectoryVisualizationService(mock.Object);
- var result = await service.GetTrajectoryAsync(1, CancellationToken.None);
+ var actualTrajectory = new TrajectoryDto[]
+ {
+ new(0, 0, 0),
+ new(30,30,10),
+ new(0, 0, 20),
+ };
- Assert.Equal(plannedTrajectory.Length, result.Count());
+ var mockPlan = MakeTrajectoryRepositoryMock(plannedTrajectory);
+ var mockFact = MakeTrajectoryRepositoryMock(actualTrajectory);
+ var service = new TrajectoryVisualizationService(mockPlan.Object, mockFact.Object);
+ var result = await service.GetTrajectoryAsync(1, CancellationToken.None);
+ Assert.Equal(plannedTrajectory.Length, result.Plan?.Count());
+ Assert.Equal(actualTrajectory.Length, result.Fact?.Count());
}
[Fact]
public async Task GetTrajectoryAsync_StraigthBore()
{
- var plannedTrajectory = new PlannedTrajectoryDto[]
+ var trajectory = new TrajectoryDto[]
{
- new() { AzimuthGeo = 0d, ZenithAngle = 0d, WellboreDepth = 0d},
- new() { AzimuthGeo = 0d, ZenithAngle = 0d, WellboreDepth = 0d},
- new() { AzimuthGeo = 0d, ZenithAngle = 0d, WellboreDepth = 20d},
- new() { AzimuthGeo = 0d, ZenithAngle = 0d, WellboreDepth = 20d},
- new() { AzimuthGeo = 0d, ZenithAngle = 0d, WellboreDepth = 30d},
- new() { AzimuthGeo = 0d, ZenithAngle = 0d, WellboreDepth = 50d},
+ new(0, 0, 0),
+ new(0, 0, 0),
+ new(20, 0, 0),
+ new(20, 0, 0),
+ new(30, 0, 0),
+ new(50, 0, 0),
};
- var mock = MakePlannedTrajectoryRepositoryMock(plannedTrajectory);
- var service = new TrajectoryVisualizationService(mock.Object);
+ 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 lastPoint = result.Last();
+ var lastPointPlan = result.Plan!.Last();
+ var lastPointFact = result.Fact!.Last();
- Assert.Equal(0d, lastPoint.X, 0.1d);
- Assert.Equal(0d, lastPoint.Y, 0.1d);
- Assert.Equal(50d, lastPoint.Z, 0.1d);
+ Assert.Equal(0d, lastPointPlan.X, 0.1d);
+ Assert.Equal(0d, lastPointPlan.Y, 0.1d);
+ Assert.Equal(50d, lastPointPlan.Z, 0.1d);
+
+ Assert.Equal(0d, lastPointFact.X, 0.1d);
+ Assert.Equal(0d, lastPointFact.Y, 0.1d);
+ Assert.Equal(50d, lastPointFact.Z, 0.1d);
}
[Fact]
public async Task GetTrajectoryAsync_Match()
{
- var plannedTrajectory = new PlannedTrajectoryDto[]
+ var trajectory = new TrajectoryDto[]
{
- new() { AzimuthGeo = 0d, ZenithAngle = 0d, WellboreDepth = 0d},
- new() { AzimuthGeo = 30d, ZenithAngle = 30d, WellboreDepth = 10d},
- new() { AzimuthGeo = 0d, ZenithAngle = 0d, WellboreDepth = 20d},
+ new(0, 0, 0),
+ new(10, 30, 30),
+ new(20, 0, 0),
};
- var mock = MakePlannedTrajectoryRepositoryMock(plannedTrajectory);
- var service = new TrajectoryVisualizationService(mock.Object);
+ 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 lastPoint = result.Last();
- var tolerance = 0.001d;
+ var lastPointPlan = result.Plan!.Last();
+ var lastPointFact = result.Fact!.Last();
+ var tolerancePlan = 0.001d;
+ var toleranceFact = 0.001d;
- Assert.InRange(lastPoint.Z, 10 + tolerance, 20 - tolerance);
- Assert.InRange(lastPoint.Y, 0 + tolerance, 10 - tolerance);
- Assert.InRange(lastPoint.X, 0 + tolerance, 10 - tolerance);
+ Assert.InRange(lastPointPlan.Z, 10 + tolerancePlan, 20 - tolerancePlan);
+ Assert.InRange(lastPointPlan.Y, 0 + tolerancePlan, 10 - tolerancePlan);
+ Assert.InRange(lastPointPlan.X, 0 + tolerancePlan, 10 - tolerancePlan);
+
+ Assert.InRange(lastPointFact.Z, 10 + toleranceFact, 20 - toleranceFact);
+ Assert.InRange(lastPointFact.Y, 0 + toleranceFact, 10 - toleranceFact);
+ Assert.InRange(lastPointFact.X, 0 + toleranceFact, 10 - toleranceFact);
}
}
}
diff --git a/AsbCloudWebApi/Controllers/PlannedTrajectoryController.cs b/AsbCloudWebApi/Controllers/PlannedTrajectoryController.cs
index df564558..5d019e18 100644
--- a/AsbCloudWebApi/Controllers/PlannedTrajectoryController.cs
+++ b/AsbCloudWebApi/Controllers/PlannedTrajectoryController.cs
@@ -225,14 +225,14 @@ namespace AsbCloudWebApi.Controllers
}
///
- /// Получение координат для визуализации траектории
+ /// Получение координат для визуализации траектории (плановой и фактической)
///
///
///
///
[HttpGet]
- [ProducesResponseType(typeof(IEnumerable), (int)System.Net.HttpStatusCode.OK)]
- public async Task GetTrajectoryAsync(int idWell, CancellationToken token)
+ [ProducesResponseType(typeof(PlanFactBase>), (int)System.Net.HttpStatusCode.OK)]
+ public async Task GetPlanFactTrajectoryAsync(int idWell, CancellationToken token)
{
if (!await CanUserAccessToWellAsync(idWell,
token).ConfigureAwait(false))