273 lines
6.5 KiB
C#
273 lines
6.5 KiB
C#
using NetTopologySuite.Geometries;
|
|
using OperationControl.Mapas.Models;
|
|
|
|
namespace OperationControl.Mapas.Services
|
|
{
|
|
public class MapaValidationService
|
|
{
|
|
public MapaResultadoValidacao Validar(
|
|
MapaDocumento? documento)
|
|
{
|
|
var resultado =
|
|
new MapaResultadoValidacao();
|
|
|
|
|
|
if (documento == null)
|
|
{
|
|
resultado.AdicionarErro(
|
|
"O documento de mapa é nulo."
|
|
);
|
|
|
|
return resultado;
|
|
}
|
|
|
|
|
|
if (documento.Ruas == null ||
|
|
documento.Ruas.Count == 0)
|
|
{
|
|
resultado.AdicionarErro(
|
|
"O mapa não possui ruas."
|
|
);
|
|
|
|
return resultado;
|
|
}
|
|
|
|
|
|
var idsUsados =
|
|
new HashSet<string>(
|
|
StringComparer.OrdinalIgnoreCase
|
|
);
|
|
|
|
|
|
for (
|
|
int i = 0;
|
|
i < documento.Ruas.Count;
|
|
i++)
|
|
{
|
|
MapaRua? rua =
|
|
documento.Ruas[i];
|
|
|
|
int numeroRua =
|
|
i + 1;
|
|
|
|
|
|
if (rua == null)
|
|
{
|
|
resultado.AdicionarErro(
|
|
$"A rua na posição {numeroRua} é nula."
|
|
);
|
|
|
|
continue;
|
|
}
|
|
|
|
|
|
ValidarId(
|
|
rua,
|
|
numeroRua,
|
|
idsUsados,
|
|
resultado
|
|
);
|
|
|
|
|
|
ValidarGeometria(
|
|
rua,
|
|
numeroRua,
|
|
resultado
|
|
);
|
|
}
|
|
|
|
|
|
return resultado;
|
|
}
|
|
|
|
|
|
private static void ValidarId(
|
|
MapaRua rua,
|
|
int indice,
|
|
HashSet<string> idsUsados,
|
|
MapaResultadoValidacao resultado)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(rua.Id))
|
|
{
|
|
resultado.AdicionarErro(
|
|
$"A rua na posição {indice} não possui ID."
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
string id =
|
|
rua.Id.Trim();
|
|
|
|
|
|
if (!idsUsados.Add(id))
|
|
{
|
|
resultado.AdicionarErro(
|
|
$"O ID de rua '{id}' está duplicado."
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
private static void ValidarGeometria(
|
|
MapaRua rua,
|
|
int indice,
|
|
MapaResultadoValidacao resultado)
|
|
{
|
|
LineString? geometria =
|
|
rua.Geometria;
|
|
|
|
|
|
if (geometria == null)
|
|
{
|
|
resultado.AdicionarErro(
|
|
$"A rua '{ObterNomeRua(rua, indice)}' " +
|
|
"não possui geometria."
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
if (geometria.IsEmpty)
|
|
{
|
|
resultado.AdicionarErro(
|
|
$"A rua '{ObterNomeRua(rua, indice)}' " +
|
|
"possui geometria vazia."
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
if (geometria.NumPoints < 2)
|
|
{
|
|
resultado.AdicionarErro(
|
|
$"A rua '{ObterNomeRua(rua, indice)}' " +
|
|
"possui menos de dois pontos."
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
Coordinate[] coordenadas =
|
|
geometria.Coordinates;
|
|
|
|
|
|
bool possuiSegmentoReal = false;
|
|
|
|
|
|
for (
|
|
int i = 0;
|
|
i < coordenadas.Length;
|
|
i++)
|
|
{
|
|
Coordinate coordenada =
|
|
coordenadas[i];
|
|
|
|
|
|
double longitude =
|
|
coordenada.X;
|
|
|
|
double latitude =
|
|
coordenada.Y;
|
|
|
|
|
|
bool valida =
|
|
double.IsFinite(longitude) &&
|
|
double.IsFinite(latitude) &&
|
|
longitude >= -180.0 &&
|
|
longitude <= 180.0 &&
|
|
latitude >= -90.0 &&
|
|
latitude <= 90.0;
|
|
|
|
|
|
if (!valida)
|
|
{
|
|
resultado.AdicionarErro(
|
|
$"A rua '{ObterNomeRua(rua, indice)}', " +
|
|
$"ponto {i + 1}, possui coordenada inválida: " +
|
|
$"longitude={longitude}, latitude={latitude}."
|
|
);
|
|
|
|
/*
|
|
* Não precisamos continuar analisando
|
|
* a topologia dessa coordenada.
|
|
*/
|
|
continue;
|
|
}
|
|
|
|
|
|
if (i > 0)
|
|
{
|
|
Coordinate anterior =
|
|
coordenadas[i - 1];
|
|
|
|
|
|
if (
|
|
Math.Abs(
|
|
anterior.X -
|
|
coordenada.X
|
|
) > 1e-12 ||
|
|
Math.Abs(
|
|
anterior.Y -
|
|
coordenada.Y
|
|
) > 1e-12
|
|
)
|
|
{
|
|
possuiSegmentoReal =
|
|
true;
|
|
}
|
|
else
|
|
{
|
|
resultado.AdicionarAviso(
|
|
$"A rua '{ObterNomeRua(rua, indice)}' " +
|
|
$"possui pontos consecutivos repetidos " +
|
|
$"nas posições {i} e {i + 1}."
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (!possuiSegmentoReal)
|
|
{
|
|
resultado.AdicionarErro(
|
|
$"A rua '{ObterNomeRua(rua, indice)}' " +
|
|
"não possui deslocamento geométrico."
|
|
);
|
|
}
|
|
|
|
|
|
if (
|
|
!double.IsFinite(
|
|
rua.ComprimentoMetros
|
|
) ||
|
|
rua.ComprimentoMetros < 0
|
|
)
|
|
{
|
|
resultado.AdicionarErro(
|
|
$"A rua '{ObterNomeRua(rua, indice)}' " +
|
|
"possui comprimento inválido."
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
private static string ObterNomeRua(
|
|
MapaRua rua,
|
|
int indice)
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(
|
|
rua.Id))
|
|
{
|
|
return rua.Id;
|
|
}
|
|
|
|
|
|
return indice.ToString();
|
|
}
|
|
}
|
|
} |