private void AddAffectedAreaLayer(Map map, Polygon affectedArea) { var geoms = new List <IGeometry>() { affectedArea }; if (!map.MapTransform.IsIdentity) { // affectedArea is aligned with Graphics Canvas (not with north arrow) // The following steps are simply to show this geom in world units var centreX = affectedArea.EnvelopeInternal.Centre.X; var centreY = affectedArea.EnvelopeInternal.Centre.Y; // apply negative rotation about center of polygon var rad = NetTopologySuite.Utilities.Degrees.ToRadians(map.MapTransformRotation); var trans = new AffineTransformation(); trans.Compose(AffineTransformation.TranslationInstance(-centreX, -centreY)); trans.Compose(AffineTransformation.RotationInstance(-rad)); var rotated = trans.Transform(affectedArea.Copy()); // calculate enclosing envelope var minX = rotated.Coordinates.Min(c => c.X); var minY = rotated.Coordinates.Min(c => c.Y); var maxX = rotated.Coordinates.Max(c => c.X); var maxY = rotated.Coordinates.Max(c => c.Y); var coords = new Coordinate[] { new Coordinate(minX, maxY), new Coordinate(maxX, maxY), new Coordinate(maxX, minY), new Coordinate(minX, minY), new Coordinate(minX, maxY), }; // rotate enclosing envelope back to world units trans = new AffineTransformation(); trans.Compose(AffineTransformation.RotationInstance(rad)); trans.Compose(AffineTransformation.TranslationInstance(centreX, centreY)); // construct geom to show on screen var enclosing = trans.Transform(new Polygon(new LinearRing(coords))); geoms.Add(enclosing); } var gp = new GeometryProvider(geoms); var vLayer = new VectorLayer("Affected Area") { DataSource = gp, SRID = map.SRID }; vLayer.Style.Fill = null; vLayer.Style.EnableOutline = true; //vLayer.Enabled = false; map.Layers.Add(vLayer); }
/// <summary> /// Affine transformation defining complete transformation from world coordinate system (WCS) to image coordinates taking into /// account Zoom, Pixel Width/Height, and MapTransformRotation. Additionally, if <paramref name="careAboutTransform"/> = false, /// the viewport rotation will be reverted at the end of the transformation, to be re-applied by Graphics object when rendering. /// </summary> /// <param name="worldCenter">Map center in WCS</param> /// <param name="pixelWidth">Width of pixel in world units</param> /// <param name="pixelHeight">Height of pixel in world units</param> /// <param name="mapTransformRotation">map rotation in degrees</param> /// <param name="imageSize">Map Size when rendered</param> /// <param name="careAboutTransform">True for coordinate calculations, False if Graphics object will apply MapTransform</param> /// <returns>Affine Transformation</returns> public static AffineTransformation WorldToMapMatrix(Coordinate worldCenter, double pixelWidth, double pixelHeight, float mapTransformRotation, Size imageSize, bool careAboutTransform) { var rad = NetTopologySuite.Utilities.Degrees.ToRadians(mapTransformRotation); var trans = new AffineTransformation(); trans.Compose(AffineTransformation.TranslationInstance(-worldCenter.X, -worldCenter.Y)); trans.Compose(AffineTransformation.RotationInstance(-rad)); trans.Compose(AffineTransformation.ScaleInstance(1 / pixelWidth, -1 / pixelHeight)); trans.Compose(AffineTransformation.TranslationInstance(imageSize.Width * 0.5, imageSize.Height * 0.5)); if (!careAboutTransform) { // if we DON'T care about transform (implies that rotation in image space WILL be performed by graphics // object once drawing of ALL objects has been completed) then need to revert rotation (ie MapTransform). trans.Compose(AffineTransformation.RotationInstance(-rad, imageSize.Width * 0.5, imageSize.Height * 0.5)); } return(trans); }