DD.WellWorkover.Cloud/AsbCloudInfrastructure/Services/Trajectory/TrajectoryService.cs
2023-05-30 11:21:07 +05:00

146 lines
4.9 KiB
C#

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<TGeo, TCartesian>
where TGeo : TrajectoryGeoDto
where TCartesian : TrajectoryCartesianDto, new()
{
ITrajectoryRepository<TGeo> repository;
public TrajectoryBaseService(ITrajectoryRepository<TGeo> 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<IEnumerable<TCartesian>?> 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<Location> GetTrajectoryVisualisation(IEnumerable<TrajectoryGeoDto> 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<TrajectoryGeoPlanDto, TrajectoryCartesianPlanDto>
{
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<TrajectoryGeoFactDto, TrajectoryCartesianFactDto>
{
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);
}
/// <summary>
/// Получение плановой и фактической траектории по скважине
/// </summary>
/// <param name="idWell">ключ скважины</param>
/// <param name="token"></param>
/// <returns></returns>
public async Task<PlanFactBase<IEnumerable<TrajectoryCartesianPlanDto>, IEnumerable<TrajectoryCartesianFactDto>>> GetTrajectoryCartesianAsync(int idWell, CancellationToken token)
{
var result = new PlanFactBase<IEnumerable<TrajectoryCartesianPlanDto>, IEnumerable<TrajectoryCartesianFactDto>>();
result.Plan = await trajectoryPlanService.GetAsync(idWell, token);
result.Fact = await trajectoryFactService.GetAsync(idWell, token);
return result;
}
}