606 lines
14 KiB
C#
606 lines
14 KiB
C#
using Mapsui;
|
|
using Mapsui.Layers;
|
|
using Mapsui.Nts;
|
|
using Mapsui.Styles;
|
|
using NetTopologySuite.Geometries;
|
|
using OperationControl.Mapas.Models;
|
|
using Brush = Mapsui.Styles.Brush;
|
|
using Font = Mapsui.Styles.Font;
|
|
using Pen = Mapsui.Styles.Pen;
|
|
|
|
namespace OperationControl.Mapas.Rendering
|
|
{
|
|
/// <summary>
|
|
/// Converte o estado dinâmico de Base/Rovers
|
|
/// em representação visual Mapsui.
|
|
///
|
|
/// Não armazena estado operacional.
|
|
/// </summary>
|
|
public sealed class MapaEntidadeDinamicaRenderService
|
|
{
|
|
public const string NomeCamada =
|
|
"MapaEntidadesDinamicasNovo";
|
|
|
|
|
|
public MemoryLayer CriarCamada(
|
|
MapaEstadoDinamico estado,
|
|
double resolution)
|
|
{
|
|
if (estado == null)
|
|
{
|
|
throw new ArgumentNullException(
|
|
nameof(estado)
|
|
);
|
|
}
|
|
|
|
|
|
return new MemoryLayer
|
|
{
|
|
Name = NomeCamada,
|
|
|
|
Features =
|
|
CriarFeatures(
|
|
estado,
|
|
resolution
|
|
)
|
|
};
|
|
}
|
|
|
|
|
|
public void AtualizarCamada(
|
|
MemoryLayer camada,
|
|
MapaEstadoDinamico estado,
|
|
double resolution)
|
|
{
|
|
if (camada == null)
|
|
{
|
|
throw new ArgumentNullException(
|
|
nameof(camada)
|
|
);
|
|
}
|
|
|
|
if (estado == null)
|
|
{
|
|
throw new ArgumentNullException(
|
|
nameof(estado)
|
|
);
|
|
}
|
|
|
|
|
|
camada.Features =
|
|
CriarFeatures(
|
|
estado,
|
|
resolution
|
|
);
|
|
}
|
|
|
|
|
|
private static IEnumerable<IFeature>
|
|
CriarFeatures(
|
|
MapaEstadoDinamico estado,
|
|
double resolution)
|
|
{
|
|
var features =
|
|
new List<IFeature>();
|
|
|
|
|
|
if (
|
|
!double.IsFinite(resolution) ||
|
|
resolution <= 0
|
|
)
|
|
{
|
|
resolution =
|
|
1.0;
|
|
}
|
|
|
|
|
|
foreach (
|
|
var entidade
|
|
in estado.Entidades)
|
|
{
|
|
if (!entidade.PossuiPosicao)
|
|
continue;
|
|
|
|
|
|
double latitude =
|
|
entidade.Latitude!.Value;
|
|
|
|
double longitude =
|
|
entidade.Longitude!.Value;
|
|
|
|
|
|
var mercator =
|
|
Mapsui.Projections
|
|
.SphericalMercator
|
|
.FromLonLat(
|
|
longitude,
|
|
latitude
|
|
);
|
|
|
|
|
|
var centro =
|
|
new MPoint(
|
|
mercator.x,
|
|
mercator.y
|
|
);
|
|
|
|
|
|
if (
|
|
entidade.Tipo ==
|
|
MapaTipoEntidadeDinamica.Base
|
|
)
|
|
{
|
|
CriarBase(
|
|
entidade,
|
|
centro,
|
|
resolution,
|
|
features
|
|
);
|
|
}
|
|
else
|
|
{
|
|
CriarRover(
|
|
entidade,
|
|
centro,
|
|
resolution,
|
|
features
|
|
);
|
|
}
|
|
|
|
|
|
/*
|
|
* Label e ponto central para futura
|
|
* identificação/hit-test.
|
|
*/
|
|
CriarCentroELabel(
|
|
entidade,
|
|
centro,
|
|
features
|
|
);
|
|
}
|
|
|
|
|
|
return features;
|
|
}
|
|
|
|
|
|
private static void CriarRover(
|
|
MapaEntidadeDinamica entidade,
|
|
MPoint centro,
|
|
double resolution,
|
|
List<IFeature> features)
|
|
{
|
|
/*
|
|
* Aproximadamente 24 px no zoom atual.
|
|
*/
|
|
double comprimento =
|
|
24.0 *
|
|
resolution;
|
|
|
|
double largura =
|
|
comprimento *
|
|
0.75;
|
|
|
|
|
|
double frente =
|
|
comprimento *
|
|
0.55;
|
|
|
|
double traseira =
|
|
comprimento *
|
|
0.45;
|
|
|
|
double meiaLargura =
|
|
largura *
|
|
0.5;
|
|
|
|
|
|
/*
|
|
* Convenção:
|
|
*
|
|
* 0° = Norte
|
|
* 90° = Leste
|
|
* 180° = Sul
|
|
* 270° = Oeste
|
|
*/
|
|
double heading =
|
|
entidade.Heading
|
|
?? 0.0;
|
|
|
|
double rad =
|
|
heading *
|
|
Math.PI /
|
|
180.0;
|
|
|
|
|
|
double ux =
|
|
Math.Sin(rad);
|
|
|
|
double uy =
|
|
Math.Cos(rad);
|
|
|
|
|
|
double px =
|
|
Math.Cos(rad);
|
|
|
|
double py =
|
|
-Math.Sin(rad);
|
|
|
|
|
|
var front =
|
|
new Coordinate(
|
|
centro.X +
|
|
ux * frente,
|
|
|
|
centro.Y +
|
|
uy * frente
|
|
);
|
|
|
|
|
|
var left =
|
|
new Coordinate(
|
|
centro.X -
|
|
ux * traseira +
|
|
px * meiaLargura,
|
|
|
|
centro.Y -
|
|
uy * traseira +
|
|
py * meiaLargura
|
|
);
|
|
|
|
|
|
var right =
|
|
new Coordinate(
|
|
centro.X -
|
|
ux * traseira -
|
|
px * meiaLargura,
|
|
|
|
centro.Y -
|
|
uy * traseira -
|
|
py * meiaLargura
|
|
);
|
|
|
|
|
|
var ring =
|
|
new LinearRing(
|
|
new[]
|
|
{
|
|
front,
|
|
left,
|
|
right,
|
|
front
|
|
}
|
|
);
|
|
|
|
|
|
var feature =
|
|
new GeometryFeature
|
|
{
|
|
Geometry =
|
|
new Polygon(
|
|
ring
|
|
)
|
|
};
|
|
|
|
|
|
feature["EntidadeId"] =
|
|
entidade.Id;
|
|
|
|
feature["Tipo"] =
|
|
"Rover";
|
|
|
|
|
|
var cor =
|
|
new Mapsui.Styles.Color(
|
|
45,
|
|
140,
|
|
220,
|
|
255
|
|
);
|
|
|
|
|
|
feature.Styles.Add(
|
|
new VectorStyle
|
|
{
|
|
Fill =
|
|
new Brush(
|
|
cor
|
|
),
|
|
|
|
Outline =
|
|
new Pen(
|
|
Mapsui.Styles.Color.White,
|
|
entidade.EmFoco
|
|
? 3
|
|
: 2
|
|
)
|
|
}
|
|
);
|
|
|
|
|
|
features.Add(
|
|
feature
|
|
);
|
|
|
|
|
|
/*
|
|
* Halo de foco.
|
|
*/
|
|
if (entidade.EmFoco)
|
|
{
|
|
var foco =
|
|
new PointFeature(
|
|
centro
|
|
);
|
|
|
|
|
|
foco["EntidadeId"] =
|
|
entidade.Id;
|
|
|
|
|
|
foco.Styles.Add(
|
|
new SymbolStyle
|
|
{
|
|
SymbolType =
|
|
SymbolType.Ellipse,
|
|
|
|
SymbolScale =
|
|
1.35,
|
|
|
|
Fill =
|
|
new Brush(
|
|
new Mapsui.Styles.Color(
|
|
cor.R,
|
|
cor.G,
|
|
cor.B,
|
|
40
|
|
)
|
|
),
|
|
|
|
Outline =
|
|
new Pen(
|
|
new Mapsui.Styles.Color(
|
|
cor.R,
|
|
cor.G,
|
|
cor.B,
|
|
180
|
|
),
|
|
2
|
|
)
|
|
}
|
|
);
|
|
|
|
|
|
features.Add(
|
|
foco
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
private static void CriarBase(
|
|
MapaEntidadeDinamica entidade,
|
|
MPoint centro,
|
|
double resolution,
|
|
List<IFeature> features)
|
|
{
|
|
double raio =
|
|
22.0 *
|
|
resolution;
|
|
|
|
|
|
var coords =
|
|
new List<Coordinate>();
|
|
|
|
|
|
/*
|
|
* Hexágono.
|
|
*/
|
|
for (
|
|
int i = 0;
|
|
i < 6;
|
|
i++)
|
|
{
|
|
double ang =
|
|
Math.PI / 6.0 +
|
|
i *
|
|
Math.PI / 3.0;
|
|
|
|
|
|
coords.Add(
|
|
new Coordinate(
|
|
centro.X +
|
|
Math.Cos(ang) *
|
|
raio,
|
|
|
|
centro.Y +
|
|
Math.Sin(ang) *
|
|
raio
|
|
)
|
|
);
|
|
}
|
|
|
|
|
|
coords.Add(
|
|
coords[0]
|
|
);
|
|
|
|
|
|
var feature =
|
|
new GeometryFeature
|
|
{
|
|
Geometry =
|
|
new Polygon(
|
|
new LinearRing(
|
|
coords.ToArray()
|
|
)
|
|
)
|
|
};
|
|
|
|
|
|
feature["EntidadeId"] =
|
|
entidade.Id;
|
|
|
|
feature["Tipo"] =
|
|
"Base";
|
|
|
|
|
|
var cor =
|
|
new Mapsui.Styles.Color(
|
|
220,
|
|
45,
|
|
45,
|
|
255
|
|
);
|
|
|
|
|
|
feature.Styles.Add(
|
|
new VectorStyle
|
|
{
|
|
Fill =
|
|
new Brush(
|
|
cor
|
|
),
|
|
|
|
Outline =
|
|
new Mapsui.Styles.Pen(
|
|
Mapsui.Styles.Color.White,
|
|
entidade.EmFoco
|
|
? 3
|
|
: 2
|
|
)
|
|
}
|
|
);
|
|
|
|
|
|
features.Add(
|
|
feature
|
|
);
|
|
|
|
|
|
/*
|
|
* Centro branco da base.
|
|
*/
|
|
var centroFeature =
|
|
new PointFeature(
|
|
centro
|
|
);
|
|
|
|
|
|
centroFeature["EntidadeId"] =
|
|
entidade.Id;
|
|
|
|
|
|
centroFeature.Styles.Add(
|
|
new SymbolStyle
|
|
{
|
|
SymbolType =
|
|
SymbolType.Ellipse,
|
|
|
|
SymbolScale =
|
|
0.45,
|
|
|
|
Fill =
|
|
new Brush(
|
|
Mapsui.Styles.Color.White
|
|
),
|
|
|
|
Outline =
|
|
null
|
|
}
|
|
);
|
|
|
|
|
|
features.Add(
|
|
centroFeature
|
|
);
|
|
}
|
|
|
|
|
|
private static void CriarCentroELabel(
|
|
MapaEntidadeDinamica entidade,
|
|
MPoint centro,
|
|
List<IFeature> features)
|
|
{
|
|
var ponto =
|
|
new PointFeature(
|
|
centro
|
|
);
|
|
|
|
|
|
/*
|
|
* Isso será muito útil no 7C:
|
|
*
|
|
* feature visual -> EntidadeId
|
|
*/
|
|
ponto["EntidadeId"] =
|
|
entidade.Id;
|
|
|
|
ponto["Tipo"] =
|
|
entidade.Tipo.ToString();
|
|
|
|
|
|
/*
|
|
* Pequeno ponto central.
|
|
*/
|
|
ponto.Styles.Add(
|
|
new SymbolStyle
|
|
{
|
|
SymbolScale =
|
|
0.10,
|
|
|
|
Fill =
|
|
new Brush(
|
|
Mapsui.Styles.Color.White
|
|
),
|
|
|
|
Outline =
|
|
null
|
|
}
|
|
);
|
|
|
|
|
|
ponto.Styles.Add(
|
|
new LabelStyle
|
|
{
|
|
Text =
|
|
entidade.Nome,
|
|
|
|
ForeColor =
|
|
Mapsui.Styles.Color.White,
|
|
|
|
BackColor =
|
|
new Brush(
|
|
new Mapsui.Styles.Color(
|
|
0,
|
|
0,
|
|
0,
|
|
150
|
|
)
|
|
),
|
|
|
|
Offset =
|
|
new Offset(
|
|
0,
|
|
-34
|
|
),
|
|
|
|
Font =
|
|
new Font
|
|
{
|
|
FontFamily =
|
|
"Segoe UI",
|
|
|
|
Size =
|
|
15
|
|
}
|
|
}
|
|
);
|
|
|
|
|
|
features.Add(
|
|
ponto
|
|
);
|
|
}
|
|
}
|
|
} |