agrobot_base/AgroBase/OperationControl/Mapas/Rendering/MapaReferenciaGnssRenderSer...

402 lines
9.5 KiB
C#

using Mapsui;
using Mapsui.Layers;
using Mapsui.Nts;
using Mapsui.Projections;
using Mapsui.Styles;
using NetTopologySuite.Geometries;
using OperationControl.Mapas.Models;
using Brush = Mapsui.Styles.Brush;
using Color = Mapsui.Styles.Color;
using Pen = Mapsui.Styles.Pen;
namespace OperationControl.Mapas.Rendering
{
public sealed class MapaReferenciaGnssRenderService
{
public const string NomeCamada =
"MapaReferenciasGnssNovo";
public MemoryLayer CriarCamada(
MapaEstadoDinamico estado)
{
if (estado == null)
{
throw new ArgumentNullException(
nameof(estado)
);
}
return new MemoryLayer
{
Name = NomeCamada,
Features =
CriarFeatures(
estado
),
Style = null
};
}
public void AtualizarCamada(
MemoryLayer camada,
MapaEstadoDinamico estado)
{
if (camada == null)
{
throw new ArgumentNullException(
nameof(camada)
);
}
if (estado == null)
{
throw new ArgumentNullException(
nameof(estado)
);
}
camada.Features =
CriarFeatures(
estado
);
}
private static List<IFeature>
CriarFeatures(
MapaEstadoDinamico estado)
{
var features =
new List<IFeature>();
foreach (
var entidade
in estado.Entidades)
{
if (
entidade == null ||
!CoordenadaValida(
entidade.Latitude,
entidade.Longitude
) ||
!CoordenadaValida(
entidade.LatitudeBruta,
entidade.LongitudeBruta
)
)
{
continue;
}
/*
* Posição utilizada pelo sistema,
* já considerando a correção aplicada.
*/
var corrigido =
SphericalMercator
.FromLonLat(
entidade.Longitude!.Value,
entidade.Latitude!.Value
);
/*
* Posição GNSS de referência/bruta
* anterior à correção de lever arm.
*/
var bruto =
SphericalMercator
.FromLonLat(
entidade.LongitudeBruta!.Value,
entidade.LatitudeBruta!.Value
);
CriarLinha(
features,
entidade,
bruto.x,
bruto.y,
corrigido.x,
corrigido.y
);
CriarPontoBruto(
features,
entidade,
bruto.x,
bruto.y
);
CriarPontoCorrigido(
features,
entidade,
corrigido.x,
corrigido.y
);
}
return features;
}
private static void CriarLinha(
List<IFeature> features,
MapaEntidadeDinamica entidade,
double rawX,
double rawY,
double corrigidoX,
double corrigidoY)
{
var feature =
new GeometryFeature
{
Geometry =
new LineString(
new[]
{
new Coordinate(
rawX,
rawY
),
new Coordinate(
corrigidoX,
corrigidoY
)
}
)
};
AplicarMetadados(
feature,
entidade,
"LigacaoLeverArm"
);
feature.Styles.Add(
new VectorStyle
{
Line =
new Pen
{
Color =
new Color(
255,
255,
255,
170
),
Width =
1,
PenStyle =
PenStyle.Dash
}
}
);
features.Add(
feature
);
}
private static void CriarPontoBruto(
List<IFeature> features,
MapaEntidadeDinamica entidade,
double x,
double y)
{
var feature =
new PointFeature(
new MPoint(
x,
y
)
);
AplicarMetadados(
feature,
entidade,
"GnssBruto"
);
feature.Styles.Add(
new SymbolStyle
{
SymbolType =
SymbolType.Ellipse,
SymbolScale =
0.55,
Fill =
new Brush(
new Color(
255,
215,
0,
255
)
),
Outline =
new Pen(
new Color(
20,
20,
20,
230
),
1
)
}
);
features.Add(
feature
);
}
private static void CriarPontoCorrigido(
List<IFeature> features,
MapaEntidadeDinamica entidade,
double x,
double y)
{
var feature =
new PointFeature(
new MPoint(
x,
y
)
);
AplicarMetadados(
feature,
entidade,
"GnssCorrigidoLeverArm"
);
feature.Styles.Add(
new SymbolStyle
{
SymbolType =
SymbolType.Ellipse,
SymbolScale =
0.50,
Fill =
new Brush(
Color.White
),
Outline =
new Pen(
new Color(
20,
20,
20,
230
),
1
)
}
);
features.Add(
feature
);
}
private static void AplicarMetadados(
IFeature feature,
MapaEntidadeDinamica entidade,
string referencia)
{
feature["EntidadeId"] =
entidade.Id;
feature["Tipo"] =
"ReferenciaGnss";
feature["Referencia"] =
referencia;
}
private static bool CoordenadaValida(
double? latitude,
double? longitude)
{
if (
!latitude.HasValue ||
!longitude.HasValue
)
{
return false;
}
if (
!double.IsFinite(latitude.Value) ||
!double.IsFinite(longitude.Value)
)
{
return false;
}
if (
latitude.Value < -90.0 ||
latitude.Value > 90.0 ||
longitude.Value < -180.0 ||
longitude.Value > 180.0
)
{
return false;
}
/*
* Mesma proteção que existia no legado:
* não desenhar referência fake em 0,0.
*/
if (
Math.Abs(latitude.Value) <
0.0000001 &&
Math.Abs(longitude.Value) <
0.0000001
)
{
return false;
}
return true;
}
}
}