#region License Information
/* HeuristicLab
* Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
*
* This file is part of HeuristicLab.
*
* HeuristicLab is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* HeuristicLab is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with HeuristicLab. If not, see .
*/
#endregion
using GeoAPI.CoordinateSystems;
using GeoAPI.Geometries;
using NetTopologySuite.CoordinateSystems.Transformations;
using NetTopologySuite.Geometries;
using ProjNet.CoordinateSystems;
using ProjNet.CoordinateSystems.Transformations;
using SharpMap.Data;
using SharpMap.Data.Providers;
using SharpMap.Layers;
using SharpMap.Rendering.Thematics;
using SharpMap.Styles;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using ColorBlend = SharpMap.Rendering.Thematics.ColorBlend;
namespace HeuristicLab.BioBoost.Views.MapViews {
public class LazyValueLayerGenerator : ILazyLayerGenerator {
public static ColorBlend DefaultColorBlend = new ColorBlend(new[] {
Color.FromArgb(0, 128, 255),
Color.FromArgb(0, 255, 255),
Color.FromArgb(0, 255, 0),
Color.FromArgb(128, 255, 0),
Color.FromArgb(255, 255, 0),
Color.FromArgb(255, 128, 0),
}, new[] { 0f, 1f / 5, 2f / 5, 3f / 5, 4f / 5, 1f });
private GeometryFeatureProvider geom;
private IEnumerable locationNames;
private IEnumerable values;
private ILayer layer;
public ColorBlend ColorBlend { get; set; }
public double? MinValue { get; set; }
public double? MaxValue { get; set; }
public double ActualMinValue { get; private set; }
public double ActualMaxValue { get; private set; }
public String LayerName { get; set; }
public bool RealtiveToSize { get; set; }
public string Unit { get; set; }
public Dictionary Mapping;
public LazyValueLayerGenerator(GeometryFeatureProvider geom, IEnumerable locationNames, IEnumerable values, String layerName) {
this.geom = geom;
this.locationNames = locationNames;
this.values = values;
this.LayerName = layerName;
this.RealtiveToSize = false;
this.ColorBlend = DefaultColorBlend;
}
public ILayer Layer {
get {
if (layer == null) BuildLayer();
return layer;
}
}
private void BuildLayer() {
string[] locationNames = this.locationNames.ToArray();
double[] values = this.values.ToArray();
this.locationNames = null;
this.values = null;
Mapping = locationNames
.Zip(values, (location, value) => new { location, value })
.ToDictionary(p => p.location, p => p.value);
if (RealtiveToSize) {
foreach (FeatureDataRow row in geom.Features.Rows) {
var nutsId = (string)row["NUTS_ID"];
double value;
if (Mapping.TryGetValue(nutsId, out value)) {
Mapping[nutsId] = value / GetAreaInHa(row.Geometry);
}
}
}
MinValue = MinValue ?? Mapping.Values.Min();
MaxValue = MaxValue ?? Mapping.Values.Max();
ActualMinValue = Math.Min(MinValue.Value, MaxValue.Value);
ActualMaxValue = Math.Max(MinValue.Value, MaxValue.Value);
var range = ActualMaxValue - ActualMinValue;
if (range == 0) range = 1;
layer = new VectorLayer(LayerName, geom) {
SmoothingMode = SmoothingMode.HighQuality,
Theme = new CustomTheme(row => {
var col = Color.LightGray;
double value;
if (row != null && Mapping.TryGetValue((string)row["NUTS_ID"], out value)) {
if (value != 0)
col = ColorBlend.GetColor((float)((value - ActualMinValue) / range));
}
return new VectorStyle {
Fill = new SolidBrush(col),
EnableOutline = true,
Outline = new Pen(Color.Black, 1f),
};
})
};
}
private static readonly CoordinateTransformationFactory transformFactory = new CoordinateTransformationFactory();
private static readonly CoordinateSystemFactory factory = new CoordinateSystemFactory();
private static double GetAreaInHa(IGeometry geom) {
geom = (IGeometry)geom.Clone();
var centroid = geom.Centroid;
var parameters = new List {
new ProjectionParameter("latitude_of_origin", centroid.Y),
new ProjectionParameter("central_meridian", centroid.X),
new ProjectionParameter("standard_parallel_1", 30),
new ProjectionParameter("standard_parallel_2", 75),
new ProjectionParameter("false_easting", 0),
new ProjectionParameter("false_northing", 0)
};
var projection = factory.CreateProjection("Albers", "albers_conic_equal_area", parameters);
var cartesian = factory.CreateProjectedCoordinateSystem(
"local albers",
GeographicCoordinateSystem.WGS84,
projection,
LinearUnit.Metre,
new AxisInfo("East", AxisOrientationEnum.East),
new AxisInfo("North", AxisOrientationEnum.North));
var transform = transformFactory.CreateFromCoordinateSystems(GeographicCoordinateSystem.WGS84, cartesian);
var transformed = GeometryTransform.TransformGeometry(GeometryFactory.Default, geom, transform.MathTransform);
return transformed.Area / 10000;
}
}
}