365 lines
8.7 KiB
C#
365 lines
8.7 KiB
C#
using Mapsui;
|
|
using Mapsui.Layers;
|
|
using Mapsui.Nts;
|
|
using Mapsui.Projections;
|
|
using Mapsui.Providers;
|
|
using Mapsui.Styles;
|
|
using NetTopologySuite.Geometries;
|
|
using OperationControl.Mapas.Editing;
|
|
using Color = Mapsui.Styles.Color;
|
|
using Pen = Mapsui.Styles.Pen;
|
|
|
|
namespace OperationControl.Mapas.Rendering
|
|
{
|
|
public sealed class MapaEdicaoRenderService
|
|
{
|
|
public const string NomeCamada =
|
|
"MapaEdicaoNovo";
|
|
|
|
|
|
private static readonly VectorStyle
|
|
EstiloNormal =
|
|
new()
|
|
{
|
|
Line =
|
|
new Pen(
|
|
new Color(
|
|
46,
|
|
204,
|
|
113,
|
|
210
|
|
),
|
|
2
|
|
)
|
|
};
|
|
|
|
|
|
/*
|
|
* Cor própria da edição.
|
|
*
|
|
* Não confundir com o amarelo usado
|
|
* na seleção operacional da missão.
|
|
*/
|
|
private static readonly VectorStyle
|
|
EstiloSelecionado =
|
|
new()
|
|
{
|
|
Line =
|
|
new Pen(
|
|
new Color(
|
|
255,
|
|
64,
|
|
190,
|
|
255
|
|
),
|
|
5
|
|
)
|
|
};
|
|
|
|
|
|
public MapaRenderResult CriarCamada(
|
|
MapaEstadoEdicao estado)
|
|
{
|
|
if (estado == null)
|
|
{
|
|
throw new ArgumentNullException(
|
|
nameof(estado)
|
|
);
|
|
}
|
|
|
|
|
|
if (
|
|
!estado.EmEdicao ||
|
|
estado.DocumentoTrabalho == null
|
|
)
|
|
{
|
|
throw new InvalidOperationException(
|
|
"Não existe uma sessão de edição ativa."
|
|
);
|
|
}
|
|
|
|
|
|
var featuresPorRuaId =
|
|
new Dictionary<
|
|
string,
|
|
GeometryFeature>(
|
|
StringComparer.OrdinalIgnoreCase
|
|
);
|
|
|
|
|
|
var features =
|
|
new List<IFeature>();
|
|
|
|
|
|
foreach (
|
|
var rua
|
|
in estado.DocumentoTrabalho.Ruas)
|
|
{
|
|
if (
|
|
rua == null ||
|
|
rua.Geometria == null ||
|
|
rua.Geometria.IsEmpty ||
|
|
rua.Geometria.NumPoints < 2
|
|
)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
|
|
/*
|
|
* Documento canônico:
|
|
*
|
|
* EPSG:4326
|
|
* X = longitude
|
|
* Y = latitude
|
|
*
|
|
* Mapsui:
|
|
*
|
|
* desenhamos diretamente em
|
|
* WebMercator EPSG:3857.
|
|
*/
|
|
var coordenadas =
|
|
rua.Geometria
|
|
.Coordinates
|
|
.Select(
|
|
coordenada =>
|
|
{
|
|
var mercator =
|
|
SphericalMercator
|
|
.FromLonLat(
|
|
coordenada.X,
|
|
coordenada.Y
|
|
);
|
|
|
|
|
|
return new Coordinate(
|
|
mercator.x,
|
|
mercator.y
|
|
);
|
|
}
|
|
)
|
|
.ToArray();
|
|
|
|
|
|
if (coordenadas.Length < 2)
|
|
continue;
|
|
|
|
|
|
var feature =
|
|
new GeometryFeature
|
|
{
|
|
Geometry =
|
|
new LineString(
|
|
coordenadas
|
|
)
|
|
};
|
|
|
|
|
|
/*
|
|
* Mantemos os mesmos atributos
|
|
* esperados pelo hit-test atual.
|
|
*/
|
|
feature["RuaId"] =
|
|
rua.Id;
|
|
|
|
feature["Id"] =
|
|
rua.Id;
|
|
|
|
feature["Tipo"] =
|
|
"RuaEdicao";
|
|
|
|
|
|
bool selecionada =
|
|
EstaSelecionada(
|
|
estado,
|
|
rua.Id
|
|
);
|
|
|
|
|
|
feature
|
|
.Styles
|
|
.Add(
|
|
selecionada
|
|
? EstiloSelecionado
|
|
: EstiloNormal
|
|
);
|
|
|
|
|
|
features.Add(
|
|
feature
|
|
);
|
|
|
|
|
|
featuresPorRuaId[
|
|
rua.Id
|
|
] =
|
|
feature;
|
|
}
|
|
|
|
|
|
/*
|
|
* MapaRenderResult trabalha com Layer,
|
|
* portanto seguimos exatamente esse
|
|
* contrato.
|
|
*/
|
|
var provider =
|
|
new MemoryProvider(
|
|
features
|
|
);
|
|
|
|
|
|
var camada =
|
|
new Layer
|
|
{
|
|
Name =
|
|
NomeCamada,
|
|
|
|
DataSource =
|
|
provider,
|
|
|
|
/*
|
|
* Cada feature possui seu
|
|
* próprio estilo.
|
|
*/
|
|
Style =
|
|
null
|
|
};
|
|
|
|
|
|
/*
|
|
* IMPORTANTE:
|
|
*
|
|
* MapaRenderResult NÃO possui
|
|
* construtor vazio.
|
|
*
|
|
* Layer e dicionário entram pelo
|
|
* construtor obrigatório.
|
|
*/
|
|
return new MapaRenderResult(
|
|
camada,
|
|
featuresPorRuaId
|
|
);
|
|
}
|
|
|
|
|
|
public void AtualizarEstiloRua(
|
|
MapaRenderResult render,
|
|
MapaEstadoEdicao estado,
|
|
string ruaId)
|
|
{
|
|
if (
|
|
render == null ||
|
|
estado == null ||
|
|
string.IsNullOrWhiteSpace(
|
|
ruaId
|
|
)
|
|
)
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
* Aproveitamos a API que já existe
|
|
* no próprio MapaRenderResult.
|
|
*/
|
|
var feature =
|
|
render.ObterFeature(
|
|
ruaId
|
|
);
|
|
|
|
|
|
if (feature == null)
|
|
return;
|
|
|
|
|
|
bool selecionada =
|
|
EstaSelecionada(
|
|
estado,
|
|
ruaId
|
|
);
|
|
|
|
|
|
feature
|
|
.Styles
|
|
.Clear();
|
|
|
|
|
|
feature
|
|
.Styles
|
|
.Add(
|
|
selecionada
|
|
? EstiloSelecionado
|
|
: EstiloNormal
|
|
);
|
|
}
|
|
|
|
|
|
public void AplicarSelecao(
|
|
MapaRenderResult render,
|
|
MapaEstadoEdicao estado)
|
|
{
|
|
if (
|
|
render == null ||
|
|
estado == null
|
|
)
|
|
{
|
|
return;
|
|
}
|
|
|
|
|
|
foreach (
|
|
var item
|
|
in render.FeaturesPorRuaId)
|
|
{
|
|
bool selecionada =
|
|
EstaSelecionada(
|
|
estado,
|
|
item.Key
|
|
);
|
|
|
|
|
|
item.Value
|
|
.Styles
|
|
.Clear();
|
|
|
|
|
|
item.Value
|
|
.Styles
|
|
.Add(
|
|
selecionada
|
|
? EstiloSelecionado
|
|
: EstiloNormal
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
private static bool EstaSelecionada(
|
|
MapaEstadoEdicao estado,
|
|
string ruaId)
|
|
{
|
|
if (
|
|
string.IsNullOrWhiteSpace(
|
|
ruaId
|
|
)
|
|
)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
|
|
return estado
|
|
.RuasSelecionadas
|
|
.Any(
|
|
id =>
|
|
string.Equals(
|
|
id,
|
|
ruaId,
|
|
StringComparison
|
|
.OrdinalIgnoreCase
|
|
)
|
|
);
|
|
}
|
|
}
|
|
} |