From 66f7df1dc803e53775efddcd523695727c8c5088 Mon Sep 17 00:00:00 2001 From: Andrew Vardeman Date: Wed, 25 Feb 2026 13:36:48 -0600 Subject: [PATCH 1/6] Add zoom/pan to spatial viewer; fix some null reference exceptions Signed-off-by: Andrew Vardeman --- Visualizer/BoundaryProcessor.cs | 26 +- Visualizer/DrawingUtil.cs | 96 +----- Visualizer/GuidanceExtension.cs | 100 ------ Visualizer/GuidanceProcessor.cs | 125 +++----- Visualizer/Mapping/Map.cs | 61 ++++ Visualizer/Mapping/MapBoundingBox.cs | 75 +++++ Visualizer/Mapping/MapLineString.cs | 21 ++ Visualizer/Mapping/MapObject.cs | 22 ++ Visualizer/Mapping/MapPoint.cs | 21 ++ Visualizer/Mapping/MapPolygon.cs | 20 ++ Visualizer/OperationDataProcessor.cs | 4 +- Visualizer/PrescriptionProcessor.cs | 38 +-- .../{PointExtension.cs => ShapeExtensions.cs} | 59 ++-- Visualizer/SpatialRecordProcessor.cs | 303 +++++++++--------- Visualizer/UI/MainForm.Designer.cs | 194 +++++++---- Visualizer/UI/MainForm.cs | 97 +++--- Visualizer/UI/MainForm.resx | 45 ++- Visualizer/UI/MapControl.Designer.cs | 47 +++ Visualizer/UI/MapControl.cs | 259 +++++++++++++++ Visualizer/UI/MapControl.resx | 120 +++++++ Visualizer/Visualizer.csproj | 1 + VisualizerTests/DrawingUtilTest.cs | 98 ------ VisualizerTests/VisualizerTests.csproj | 1 - 23 files changed, 1136 insertions(+), 697 deletions(-) delete mode 100644 Visualizer/GuidanceExtension.cs create mode 100644 Visualizer/Mapping/Map.cs create mode 100644 Visualizer/Mapping/MapBoundingBox.cs create mode 100644 Visualizer/Mapping/MapLineString.cs create mode 100644 Visualizer/Mapping/MapObject.cs create mode 100644 Visualizer/Mapping/MapPoint.cs create mode 100644 Visualizer/Mapping/MapPolygon.cs rename Visualizer/{PointExtension.cs => ShapeExtensions.cs} (62%) create mode 100644 Visualizer/UI/MapControl.Designer.cs create mode 100644 Visualizer/UI/MapControl.cs create mode 100644 Visualizer/UI/MapControl.resx delete mode 100644 VisualizerTests/DrawingUtilTest.cs diff --git a/Visualizer/BoundaryProcessor.cs b/Visualizer/BoundaryProcessor.cs index d43db71..e7253bd 100644 --- a/Visualizer/BoundaryProcessor.cs +++ b/Visualizer/BoundaryProcessor.cs @@ -13,34 +13,30 @@ using System.Linq; using System.Windows.Forms; using AgGateway.ADAPT.ApplicationDataModel.FieldBoundaries; +using AgGateway.ADAPT.Visualizer.Mapping; +using AgGateway.ADAPT.Visualizer.UI; namespace AgGateway.ADAPT.Visualizer { public class BoundaryProcessor { - private DrawingUtil _drawingUtil; - private readonly TabPage _spatialViewer; + private readonly MapControl _mapControl; - public BoundaryProcessor(TabPage spatialViewer) + public BoundaryProcessor(MapControl mapControl) { - _spatialViewer = spatialViewer; + _mapControl = mapControl; } public void ProcessBoundary(FieldBoundary fieldBoundary) { - using (var graphics = _spatialViewer.CreateGraphics()) - { - _drawingUtil = new DrawingUtil(_spatialViewer.Width, _spatialViewer.Height, graphics); - foreach (var polygon in fieldBoundary.SpatialData.Polygons) - { - var projectedPoints = polygon.ExteriorRing.Points.Select(point => point.ToUtm()).ToList(); - _drawingUtil.SetMinMax(projectedPoints); - - var screenPolygon = projectedPoints.Select(point => point.ToXy(_drawingUtil.MinX, _drawingUtil.MinY, _drawingUtil.GetDelta())).ToArray(); + Map map = new Map(); - graphics.DrawPolygon(DrawingUtil.B_Black, screenPolygon); - } + foreach (var polygon in fieldBoundary.SpatialData.Polygons) + { + map.AddMapObject(new MapPolygon { Polygon = polygon.ToUtm(), Pen = DrawingUtil.B_Black }); } + + _mapControl.Map = map; } } } \ No newline at end of file diff --git a/Visualizer/DrawingUtil.cs b/Visualizer/DrawingUtil.cs index 016648d..2910912 100644 --- a/Visualizer/DrawingUtil.cs +++ b/Visualizer/DrawingUtil.cs @@ -14,100 +14,24 @@ * Andrew Vardeman - Plugged GDI+ memory leaks due to un-disposed pens *******************************************************************************/ -using System.Linq; using Point = AgGateway.ADAPT.ApplicationDataModel.Shapes.Point; namespace AgGateway.ADAPT.Visualizer { public class DrawingUtil { - private readonly int _width; - private readonly int _height; - private bool _isMaxMinSet; - - public DrawingUtil(int width, int height, Graphics graphics) - { - _width = width; - _height = height; - Graphics = graphics; - _isMaxMinSet = false; - } - - public double MinX { get; private set; } - public double MinY { get; private set; } - public double MaxX { get; private set; } - public double MaxY { get; private set; } - public Graphics Graphics { get; private set; } - //Default values - public static Pen B_Black { get; } = new Pen(Color.Black, 2); //WorkingData is not numeric - public static Pen C_DarkMagenta { get; } = new Pen(Color.DarkMagenta, 2); //Non-zero values - public static Pen E_Red { get; } = new Pen(Color.Red, 2); //Zero values or minimum values + public static Pen B_Black { get; } = new Pen(Color.Black, 2) { LineJoin = LineJoin.MiterClipped, MiterLimit = 4 }; //WorkingData is not numeric + public static Pen C_DarkMagenta { get; } = new Pen(Color.DarkMagenta, 2) { LineJoin = LineJoin.MiterClipped, MiterLimit = 4 }; //Non-zero values + public static Pen E_Red { get; } = new Pen(Color.Red, 2) { LineJoin = LineJoin.MiterClipped, MiterLimit = 4 }; //Zero values or minimum values //Range 7 levels - public static Pen F_DarkOrange { get; } = new Pen(Color.DarkOrange, 2); - public static Pen G_Gold { get; } = new Pen(Color.Gold, 2); - public static Pen H_YellowGreen { get; } = new Pen(Color.YellowGreen, 2); - public static Pen I_LawnGreen { get; } = new Pen(Color.LawnGreen, 2); - public static Pen J_LimeGreen { get; } = new Pen(Color.LimeGreen, 2); - public static Pen K_ForestGreen { get; } = new Pen(Color.ForestGreen, 2); - public static Pen L_DarkGreen { get; } = new Pen(Color.DarkGreen, 2); - - - public double GetDelta() - { - double delta; - var lonDistance = (MaxX - MinX); - var latDistance = (MaxY - MinY); - - var width = _width - 50; - var height = _height - 50; - - if (width < height && latDistance > lonDistance) - { - delta = lonDistance / width; - } - else - { - delta = latDistance / height; - } - - return delta; - } - - public void SetMinMax(IList points) - { - if (_isMaxMinSet) - { - var minX = points.Min(point => point.X); - MinX = minX < MinX ? minX : MinX; - - var maxX = points.Max(point => point.X); - MaxX = maxX > MaxX ? maxX : MaxX; - - var minY = points.Min(point => point.Y); - MinY = minY < MinY ? minY : MinY; - - var maxY = points.Max(point => point.Y); - MaxY = maxY > MaxY ? maxY : MaxY; - } - else if (points.Any()) - { - MinX = points.Min(point => point.X); - MaxX = points.Max(point => point.X); - MinY = points.Min(point => point.Y); - MaxY = points.Max(point => point.Y); - _isMaxMinSet = true; - } - SetOriginPoint(GetDelta()); - } - - public void SetOriginPoint(double delta) - { - if (delta == 0.0) - delta = 1.0; - var max = ((MaxY - MinY)/delta + 25) + 20; - Graphics.Transform = new Matrix(1, 0, 0, -1, 0, (float) max); - } + public static Pen F_DarkOrange { get; } = new Pen(Color.DarkOrange, 2) { LineJoin = LineJoin.MiterClipped, MiterLimit = 4 }; + public static Pen G_Gold { get; } = new Pen(Color.Gold, 2) { LineJoin = LineJoin.MiterClipped, MiterLimit = 4 }; + public static Pen H_YellowGreen { get; } = new Pen(Color.YellowGreen, 2) { LineJoin = LineJoin.MiterClipped, MiterLimit = 4 }; + public static Pen I_LawnGreen { get; } = new Pen(Color.LawnGreen, 2) { LineJoin = LineJoin.MiterClipped, MiterLimit = 4 }; + public static Pen J_LimeGreen { get; } = new Pen(Color.LimeGreen, 2) { LineJoin = LineJoin.MiterClipped, MiterLimit = 4 }; + public static Pen K_ForestGreen { get; } = new Pen(Color.ForestGreen, 2) { LineJoin = LineJoin.MiterClipped, MiterLimit = 4 }; + public static Pen L_DarkGreen { get; } = new Pen(Color.DarkGreen, 2) { LineJoin = LineJoin.MiterClipped, MiterLimit = 4 }; } } \ No newline at end of file diff --git a/Visualizer/GuidanceExtension.cs b/Visualizer/GuidanceExtension.cs deleted file mode 100644 index ca49d28..0000000 --- a/Visualizer/GuidanceExtension.cs +++ /dev/null @@ -1,100 +0,0 @@ -/* Copyright (C) 2015-16 AgGateway and ADAPT Contributors - * Copyright (C) 2015-16 Deere and Company - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Tarak Reddy - initial implementation - * Joseph Ross - Made changes to account for mapping multiple guidence patterns with the same context - *******************************************************************************/ - -using System; -using System.Collections.Generic; -using System.Linq; -using AgGateway.ADAPT.ApplicationDataModel.Guidance; -using Point = AgGateway.ADAPT.ApplicationDataModel.Shapes.Point; - -namespace AgGateway.ADAPT.Visualizer -{ - public static class GuidanceExtension - { - public static void SetMinMax(this APlus aPlus, DrawingUtil drawingUtil) - { - var points = new List {aPlus.Point.ToUtm()}; - - SetMinMax(drawingUtil, points); - } - - public static void SetMinMax(this AbLine abLine, DrawingUtil drawingUtil) - { - var points = new List {abLine.A.ToUtm(), abLine.B.ToUtm()}; - - SetMinMax(drawingUtil, points); - } - - public static void SetMinMax(this AbCurve abCurve, DrawingUtil drawingUtil) - { - var points = abCurve.Shape.SelectMany(x => x.Points).Select(x => x.ToUtm()).ToList(); - - SetMinMax(drawingUtil, points); - } - - public static void SetMinMax(this PivotGuidancePattern centerPivot, DrawingUtil drawingUtil) - { - var centerUtm = centerPivot.Center.ToUtm(); - var radius = Math.Abs(centerUtm.X - centerPivot.EndPoint.ToUtm().X); - - var northPoint = new Point - { - X = centerUtm.X, - Y = centerUtm.Y + radius, - }; - var southPoint = new Point - { - X = centerUtm.X, - Y = centerUtm.Y - radius, - }; - var westPoint = new Point - { - X = centerUtm.X - radius, - Y = centerUtm.Y, - }; - var eastPoint = new Point - { - X = centerUtm.X + radius, - Y = centerUtm.Y, - }; - - var points = new List - { - northPoint, - southPoint, - westPoint, - eastPoint - }; - - SetMinMax(drawingUtil, points); - } - - public static void SetMinMax(this MultiAbLine multiAbLine, DrawingUtil drawingUtil) - { - var points = multiAbLine.AbLines.SelectMany(x => new List {x.A.ToUtm(), x.B.ToUtm()}).ToList(); - - SetMinMax(drawingUtil, points); - } - - public static void SetMinMax(this Spiral spiral, DrawingUtil drawingUtil) - { - var points = spiral.Shape.Points.Select(x => x.ToUtm()).ToList(); - - SetMinMax(drawingUtil, points); - } - - private static void SetMinMax(DrawingUtil drawingUtil, List points) - { - drawingUtil.SetMinMax(points); - } - } -} \ No newline at end of file diff --git a/Visualizer/GuidanceProcessor.cs b/Visualizer/GuidanceProcessor.cs index 875660d..1d1c028 100644 --- a/Visualizer/GuidanceProcessor.cs +++ b/Visualizer/GuidanceProcessor.cs @@ -10,39 +10,33 @@ * Joseph Ross - Made changes to account for mapping multiple guidence patterns with the same context *******************************************************************************/ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Windows.Forms; using AgGateway.ADAPT.ApplicationDataModel.Guidance; using AgGateway.ADAPT.ApplicationDataModel.Shapes; +using AgGateway.ADAPT.Visualizer.Mapping; +using AgGateway.ADAPT.Visualizer.UI; using Point = AgGateway.ADAPT.ApplicationDataModel.Shapes.Point; namespace AgGateway.ADAPT.Visualizer { public class GuidanceProcessor { - private DrawingUtil _drawingUtil; - private readonly TabPage _spatialViewer; + private Map? _map; + private readonly MapControl _mapControl; + - public GuidanceProcessor(TabPage spatialViewer) + public GuidanceProcessor(MapControl mapControl) { - _spatialViewer = spatialViewer; + _mapControl = mapControl; } public void ProcessGuidance(GuidanceGroup guidanceGroup, List guidancePatterns) { - using (var graphics = _spatialViewer.CreateGraphics()) + _map = new Map(); + foreach (var id in guidanceGroup.GuidancePatternIds) { - _drawingUtil = new DrawingUtil(_spatialViewer.Width, _spatialViewer.Height, graphics); - - SetMinMax(guidancePatterns, guidanceGroup.GuidancePatternIds); - - foreach (var id in guidanceGroup.GuidancePatternIds) - { - ProcessGuidancePattern(guidancePatterns, id); - } + ProcessGuidancePattern(guidancePatterns, id); } + _mapControl.Map = _map; } private void ProcessGuidancePattern(IEnumerable guidancePatterns, int id) @@ -53,52 +47,11 @@ private void ProcessGuidancePattern(IEnumerable guidancePattern public void ProccessGuidancePattern(GuidancePattern guidancePattern) { - using (var graphics = _spatialViewer.CreateGraphics()) - { - _drawingUtil = new DrawingUtil(_spatialViewer.Width, _spatialViewer.Height, graphics); + _map = new Map(); - SetMinMax(guidancePattern); - - ProcessPattern(guidancePattern); - } - } - - private void SetMinMax(IEnumerable guidancePatterns, List guidancePatternIds) - { - var matchingGuidancePatterns = guidancePatterns.Where(pattern => guidancePatternIds.Contains(pattern.Id.ReferenceId)); + ProcessPattern(guidancePattern); - foreach (var guidancePattern in matchingGuidancePatterns) - { - SetMinMax(guidancePattern); - } - } - - private void SetMinMax(GuidancePattern guidancePattern) - { - if (guidancePattern is APlus) - { - (guidancePattern as APlus).SetMinMax(_drawingUtil); - } - else if (guidancePattern is AbLine) - { - (guidancePattern as AbLine).SetMinMax(_drawingUtil); - } - else if (guidancePattern is AbCurve) - { - (guidancePattern as AbCurve).SetMinMax(_drawingUtil); - } - else if (guidancePattern is PivotGuidancePattern) - { - (guidancePattern as PivotGuidancePattern).SetMinMax(_drawingUtil); - } - else if (guidancePattern is MultiAbLine) - { - (guidancePattern as MultiAbLine).SetMinMax(_drawingUtil); - } - else if (guidancePattern is Spiral) - { - (guidancePattern as Spiral).SetMinMax(_drawingUtil); - } + _mapControl.Map = _map; } private void ProcessPattern(GuidancePattern guidancePattern) @@ -131,27 +84,34 @@ private void ProcessPattern(GuidancePattern guidancePattern) private void ProcessSpiral(Spiral spiral) { - var delta = _drawingUtil.GetDelta(); - - ProcessLineString(spiral.Shape, delta); + ProcessLineString(spiral.Shape.ToUtm()); } private void ProcessMultiAbLine(MultiAbLine multiAbLine) { - var delta = _drawingUtil.GetDelta(); - foreach (var abLine in multiAbLine.AbLines) { - ProcessPoints(new List {abLine.A, abLine.B}, delta); + ProcessPoints(new List {abLine.A.ToUtm(), abLine.B.ToUtm()}); } } private void ProcessCenterPivot(PivotGuidancePattern centerPivot) { - var delta = _drawingUtil.GetDelta(); - var center = centerPivot.Center.ToUtm().ToXy(_drawingUtil.MinX, _drawingUtil.MinY, delta); + var center = centerPivot.Center.ToUtm(); var radius = GetRadius(centerPivot); - _drawingUtil.Graphics.DrawEllipse(DrawingUtil.B_Black, center.X - radius, center.Y - radius, radius + radius, radius + radius); + var points = new List(); + for (int i = 0; i < 36; i++) + { + double angle = Math.PI * i / 18; + double x = center.X + radius * Math.Cos(angle); + double y = center.Y + radius * Math.Sin(angle); + points.Add(new Point { X = x, Y = y }); + } + _map.AddMapObject(new MapPolygon + { + Pen = DrawingUtil.B_Black, + Polygon = new Polygon { ExteriorRing = new LinearRing { Points = points } } + }); } private float GetRadius(PivotGuidancePattern centerPivot) @@ -163,42 +123,37 @@ private float GetRadius(PivotGuidancePattern centerPivot) private void ProcessAbCurve(AbCurve abCurve) { - var delta = _drawingUtil.GetDelta(); - foreach (var lineString in abCurve.Shape) { - ProcessLineString(lineString, delta); + ProcessLineString(lineString.ToUtm()); } } private void ProcessAbLine(AbLine abLine) { - var delta = _drawingUtil.GetDelta(); - - ProcessPoints(new List {abLine.A, abLine.B}, delta); + ProcessPoints(new List {abLine.A.ToUtm(), abLine.B.ToUtm()}); } private void ProcessAPlus(APlus aPlus) { - var delta = _drawingUtil.GetDelta(); var projectedPoint = aPlus.Point; } - private void ProcessLineString(LineString lineString, double delta) + private void ProcessLineString(LineString lineString) { - ProcessPoints(lineString.Points, delta); + ProcessPoints(lineString.Points); } - private void ProcessPoints(IEnumerable points, double delta) + private void ProcessPoints(List points) { if (!points.Any() || points.Count() == 1) return; - if (delta == 0.0) - delta = 1.0; - var screenPoints = points.Select(point => point.ToUtm()).Select(point => point.ToXy(_drawingUtil.MinX, _drawingUtil.MinY, delta)).ToArray(); - - _drawingUtil.Graphics.DrawLines(DrawingUtil.B_Black, screenPoints); + _map.AddMapObject(new MapLineString + { + LineString = new LineString { Points = points }, + Pen = DrawingUtil.B_Black + }); } } } \ No newline at end of file diff --git a/Visualizer/Mapping/Map.cs b/Visualizer/Mapping/Map.cs new file mode 100644 index 0000000..179f3da --- /dev/null +++ b/Visualizer/Mapping/Map.cs @@ -0,0 +1,61 @@ +/* Copyright (C) 2015-16 AgGateway and ADAPT Contributors + * Copyright (C) 2015-16 Deere and Company + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrew Vardeman - Initial Implementation + *******************************************************************************/ + +namespace AgGateway.ADAPT.Visualizer.Mapping +{ + public class Map + { + private readonly List _mapObjects = new(); + private MapBoundingBox? _mapBoundingBox; + private bool _isAllPoints = true; + + public IReadOnlyList MapObjects => _mapObjects; + + public bool IsAllPoints => _isAllPoints; + + public void AddMapObject(MapObject mapObject) + { + _mapObjects.Add(mapObject); + if (!(mapObject is MapPoint)) + { + _isAllPoints = false; + } + _mapBoundingBox = null; + } + + public void Clear() + { + _mapObjects.Clear(); + _mapBoundingBox = null; + _isAllPoints = true; + } + + public MapBoundingBox MapBoundingBox + { + get + { + if (_mapBoundingBox == null) + { + _mapBoundingBox = new(); + foreach (var mapObject in MapObjects) + { + if (mapObject.Shape != null) + { + _mapBoundingBox.Update(mapObject.Shape); + } + } + } + + return _mapBoundingBox; + } + } + } +} diff --git a/Visualizer/Mapping/MapBoundingBox.cs b/Visualizer/Mapping/MapBoundingBox.cs new file mode 100644 index 0000000..0e665a4 --- /dev/null +++ b/Visualizer/Mapping/MapBoundingBox.cs @@ -0,0 +1,75 @@ +/* Copyright (C) 2015-16 AgGateway and ADAPT Contributors + * Copyright (C) 2015-16 Deere and Company + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrew Vardeman - Initial Implementation + *******************************************************************************/ + +using AgGateway.ADAPT.ApplicationDataModel.Shapes; + +namespace AgGateway.ADAPT.Visualizer.Mapping +{ + public class MapBoundingBox + { + public double MinX { get; set; } = double.MaxValue; + public double MinY { get; set; } = double.MaxValue; + public double MaxX { get; set; } = double.MinValue; + public double MaxY { get; set; } = double.MinValue; + public double CenterX => (MinX + MaxX) / 2; + public double CenterY => (MinY + MaxY) / 2; + public double Width => MaxX - MinX; + public double Height => MaxY - MinY; + + public ApplicationDataModel.Shapes.Point Center => + new ApplicationDataModel.Shapes.Point { X = CenterX, Y = CenterY }; + + public MapBoundingBox() { } + + public MapBoundingBox(Shape shape) + { + Update(shape); + } + + public void Update(Shape shape) + { + if (shape is ApplicationDataModel.Shapes.Point point) + { + Update(point); + } + else if (shape is LineString lineString) + { + foreach (var p in lineString.Points) + { + Update(p); + } + } + else if (shape is Polygon polygon) + { + foreach (var p in polygon.ExteriorRing.Points) + { + Update(p); + } + + foreach (var interiorRing in polygon.InteriorRings) + { + foreach (var p in interiorRing.Points) + { + Update(p); + } + } + } + } + + public void Update(ApplicationDataModel.Shapes.Point point) + { + MinX = Math.Min(MinX, point.X); + MinY = Math.Min(MinY, point.Y); + MaxX = Math.Max(MaxX, point.X); + MaxY = Math.Max(MaxY, point.Y); + } + } +} diff --git a/Visualizer/Mapping/MapLineString.cs b/Visualizer/Mapping/MapLineString.cs new file mode 100644 index 0000000..cd26827 --- /dev/null +++ b/Visualizer/Mapping/MapLineString.cs @@ -0,0 +1,21 @@ +/* Copyright (C) 2015-16 AgGateway and ADAPT Contributors + * Copyright (C) 2015-16 Deere and Company + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrew Vardeman - Initial Implementation + *******************************************************************************/ + +using AgGateway.ADAPT.ApplicationDataModel.Shapes; + +namespace AgGateway.ADAPT.Visualizer.Mapping +{ + public class MapLineString : MapObject + { + public LineString? LineString { get; set; } + public override Shape? Shape => LineString; + } +} diff --git a/Visualizer/Mapping/MapObject.cs b/Visualizer/Mapping/MapObject.cs new file mode 100644 index 0000000..ae8f6da --- /dev/null +++ b/Visualizer/Mapping/MapObject.cs @@ -0,0 +1,22 @@ +/* Copyright (C) 2015-16 AgGateway and ADAPT Contributors + * Copyright (C) 2015-16 Deere and Company + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrew Vardeman - Initial Implementation + *******************************************************************************/ + +using AgGateway.ADAPT.ApplicationDataModel.Shapes; + +namespace AgGateway.ADAPT.Visualizer.Mapping +{ + public abstract class MapObject + { + public Pen? Pen { get; set; } + public Brush? Brush { get; set; } + public abstract Shape? Shape { get; } + } +} diff --git a/Visualizer/Mapping/MapPoint.cs b/Visualizer/Mapping/MapPoint.cs new file mode 100644 index 0000000..6aae725 --- /dev/null +++ b/Visualizer/Mapping/MapPoint.cs @@ -0,0 +1,21 @@ +/* Copyright (C) 2015-16 AgGateway and ADAPT Contributors + * Copyright (C) 2015-16 Deere and Company + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrew Vardeman - Initial Implementation + *******************************************************************************/ + +using AgGateway.ADAPT.ApplicationDataModel.Shapes; + +namespace AgGateway.ADAPT.Visualizer.Mapping +{ + public class MapPoint : MapObject + { + public ADAPT.ApplicationDataModel.Shapes.Point? Point { get; set; } + public override Shape? Shape => Point; + } +} diff --git a/Visualizer/Mapping/MapPolygon.cs b/Visualizer/Mapping/MapPolygon.cs new file mode 100644 index 0000000..6bef6bf --- /dev/null +++ b/Visualizer/Mapping/MapPolygon.cs @@ -0,0 +1,20 @@ +/* Copyright (C) 2015-16 AgGateway and ADAPT Contributors + * Copyright (C) 2015-16 Deere and Company + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andrew Vardeman - Initial Implementation + *******************************************************************************/ +using AgGateway.ADAPT.ApplicationDataModel.Shapes; + +namespace AgGateway.ADAPT.Visualizer.Mapping +{ + public class MapPolygon : MapObject + { + public Polygon? Polygon { get; set; } + public override Shape? Shape => Polygon; + } +} diff --git a/Visualizer/OperationDataProcessor.cs b/Visualizer/OperationDataProcessor.cs index e6a2cee..b25a572 100644 --- a/Visualizer/OperationDataProcessor.cs +++ b/Visualizer/OperationDataProcessor.cs @@ -154,7 +154,7 @@ private static void CreateNumericMeterCell(SpatialRecord spatialRecord, WorkingD { var numericRepresentationValue = spatialRecord.GetMeterValue(workingData) as NumericRepresentationValue; var value = numericRepresentationValue != null - ? numericRepresentationValue.Value.Value.ToString(CultureInfo.InvariantCulture) + ? numericRepresentationValue.Value?.Value.ToString(CultureInfo.InvariantCulture) : ""; dataRow[columnIndex] = value; @@ -169,7 +169,7 @@ private void UpdateColumnNamesWithUom(Dictionary> var data1 = data; var workingDataValues = spatialRecords.Select(x => x.GetMeterValue(data1) as NumericRepresentationValue); var numericRepresentationValues = workingDataValues.Where(x => x != null); - var uoms = numericRepresentationValues.Select(x => x.Value.UnitOfMeasure).ToList(); + var uoms = numericRepresentationValues.Select(x => x?.Value?.UnitOfMeasure).ToList(); if (uoms.Any()) _dataTable.Columns[GetColumnName(data, kvp.Key)].ColumnName += "-" + uoms.First()?.Code; diff --git a/Visualizer/PrescriptionProcessor.cs b/Visualizer/PrescriptionProcessor.cs index a0073cd..a57dc80 100644 --- a/Visualizer/PrescriptionProcessor.cs +++ b/Visualizer/PrescriptionProcessor.cs @@ -11,52 +11,38 @@ using AgGateway.ADAPT.ApplicationDataModel.Shapes; using AgGateway.ADAPT.ApplicationDataModel.Prescriptions; - -using Point = AgGateway.ADAPT.ApplicationDataModel.Shapes.Point; +using AgGateway.ADAPT.Visualizer.Mapping; +using AgGateway.ADAPT.Visualizer.UI; namespace AgGateway.ADAPT.Visualizer { public class PrescriptionProcessor { private DrawingUtil _drawingUtil; - private readonly TabPage _spatialViewer; + private readonly MapControl _mapControl; - public PrescriptionProcessor(TabPage spatialViewer) + public PrescriptionProcessor(MapControl mapControl) { - _spatialViewer = spatialViewer; + _mapControl = mapControl; } public void ProcessPrescription(Prescription prescription) { + Map map = new Map(); if (prescription is VectorPrescription) //Only Vector currently supported for the Visualizer map { VectorPrescription vectorPrescription = prescription as VectorPrescription; - using (var graphics = _spatialViewer.CreateGraphics()) + foreach (Polygon polygon in vectorPrescription.RxShapeLookups.SelectMany(x => x.Shape.Polygons)) { - _drawingUtil = new DrawingUtil(_spatialViewer.Width, _spatialViewer.Height, graphics); - - List allPoints = new List(); - List> projectedPointsPerPolygon = new List>(); - foreach (Polygon polygon in vectorPrescription.RxShapeLookups.SelectMany(x => x.Shape.Polygons)) - { - List polygonPoints = new List(); - foreach (Point point in polygon.ExteriorRing.Points) - { - Point projectedPoint = point.ToUtm(); - allPoints.Add(projectedPoint); - polygonPoints.Add(projectedPoint); - } - projectedPointsPerPolygon.Add(polygonPoints); - } - _drawingUtil.SetMinMax(allPoints); - foreach (List polygonPoints in projectedPointsPerPolygon) + map.AddMapObject(new MapPolygon { - var screenPolygon = polygonPoints.Select(point => point.ToXy(_drawingUtil.MinX, _drawingUtil.MinY, _drawingUtil.GetDelta())).ToArray(); - graphics.DrawPolygon(DrawingUtil.B_Black, screenPolygon); - } + Polygon = polygon.ToUtm(), + Pen = DrawingUtil.B_Black + }); } } + _mapControl.Map = map; } } } diff --git a/Visualizer/PointExtension.cs b/Visualizer/ShapeExtensions.cs similarity index 62% rename from Visualizer/PointExtension.cs rename to Visualizer/ShapeExtensions.cs index dc73faf..a036e9f 100644 --- a/Visualizer/PointExtension.cs +++ b/Visualizer/ShapeExtensions.cs @@ -1,19 +1,20 @@ -/* Copyright (C) 2015-16 AgGateway and ADAPT Contributors +/* Copyright (C) 2015-16 AgGateway and ADAPT Contributors * Copyright (C) 2015-16 Deere and Company * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html + * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Tarak Reddy - initial implementation + * Andrew Vardeman - additional ToUtm methods *******************************************************************************/ using AgGateway.ADAPT.ApplicationDataModel.Shapes; namespace AgGateway.ADAPT.Visualizer { - public static class PointExtension + public static class ShapeExtensions { private const double ConstDeg2Rad = 0.0174532925; private const double A = 6378137; @@ -33,34 +34,26 @@ public static ApplicationDataModel.Shapes.Point ToUtm(this ApplicationDataModel. var c = EccPrimeSquared * Math.Cos(latitudeInRadians) * Math.Cos(latitudeInRadians); var a1 = Math.Cos(latitudeInRadians) * (longitudeInRadians - longitudeOriginInRadians); - var m = A*((1 - EccSquared/4 - 3*EccSquared*EccSquared/64 - 5*EccSquared*EccSquared*EccSquared/256)*latitudeInRadians - - (3*EccSquared/8 + 3*EccSquared*EccSquared/32 + 45*EccSquared*EccSquared*EccSquared/1024)*Math.Sin(2*latitudeInRadians) - + (15*EccSquared*EccSquared/256 + 45*EccSquared*EccSquared*EccSquared/1024)*Math.Sin(4*latitudeInRadians) - - (35*EccSquared*EccSquared*EccSquared/3072)*Math.Sin(6*latitudeInRadians)); + var m = A * ((1 - EccSquared / 4 - 3 * EccSquared * EccSquared / 64 - 5 * EccSquared * EccSquared * EccSquared / 256) * latitudeInRadians + - (3 * EccSquared / 8 + 3 * EccSquared * EccSquared / 32 + 45 * EccSquared * EccSquared * EccSquared / 1024) * Math.Sin(2 * latitudeInRadians) + + (15 * EccSquared * EccSquared / 256 + 45 * EccSquared * EccSquared * EccSquared / 1024) * Math.Sin(4 * latitudeInRadians) + - (35 * EccSquared * EccSquared * EccSquared / 3072) * Math.Sin(6 * latitudeInRadians)); - var utmEasting = K0*n*(a1 + (1 - t + c)*a1*a1*a1/6 - + (5 - 18*t + t*t + 72*c - 58*EccPrimeSquared)*a1*a1*a1*a1*a1/120) + var utmEasting = K0 * n * (a1 + (1 - t + c) * a1 * a1 * a1 / 6 + + (5 - 18 * t + t * t + 72 * c - 58 * EccPrimeSquared) * a1 * a1 * a1 * a1 * a1 / 120) + 500000.0; - var utmNorthing = K0*(m + n*Math.Tan(latitudeInRadians)*(a1*a1/2 + (5 - t + 9*c + 4*c*c)*a1*a1*a1*a1/24 + var utmNorthing = K0 * (m + n * Math.Tan(latitudeInRadians) * (a1 * a1 / 2 + (5 - t + 9 * c + 4 * c * c) * a1 * a1 * a1 * a1 / 24 + - (61 - 58*t + t*t + 600*c - 330*EccPrimeSquared)*a1*a1*a1*a1* - a1*a1/720)); + (61 - 58 * t + t * t + 600 * c - 330 * EccPrimeSquared) * a1 * a1 * a1 * a1 * + a1 * a1 / 720)); if (point.Y < 0) { utmNorthing += 10000000.0; } - return new ApplicationDataModel.Shapes.Point {X = utmEasting, Y = utmNorthing}; - } - - public static PointF ToXy(this ApplicationDataModel.Shapes.Point point, double minX, double minY, double delta) - { - var x = (point.X - minX)/delta+25; - var y = (point.Y - minY)/delta+25; - - return new PointF((float)x, (float)y); + return new ApplicationDataModel.Shapes.Point { X = utmEasting, Y = utmNorthing }; } public static ApplicationDataModel.Shapes.Point? FirstPoint(this ApplicationDataModel.Shapes.Shape geometry) @@ -104,9 +97,29 @@ private static double GetLongOrigin(double lon) } else { - longOrigin = (int) (lon/6)*6 + 3*(int) (lon/6)/Math.Abs((int) (lon/6)); + longOrigin = (int)(lon / 6) * 6 + 3 * (int)(lon / 6) / Math.Abs((int)(lon / 6)); } return longOrigin; } + + public static Polygon ToUtm(this Polygon polygon) + { + + return new Polygon + { + ExteriorRing = polygon.ExteriorRing.ToUtm(), + InteriorRings = polygon.InteriorRings?.Select(ring => ring.ToUtm()).ToList() + }; + } + + public static LinearRing ToUtm(this LinearRing linearRing) + { + return new LinearRing { Points = linearRing.Points.Select(p => p.ToUtm()).ToList() }; + } + + public static LineString ToUtm(this LineString lineString) + { + return new LineString { Points = lineString.Points.Select(p => p.ToUtm()).ToList() }; + } } -} \ No newline at end of file +} diff --git a/Visualizer/SpatialRecordProcessor.cs b/Visualizer/SpatialRecordProcessor.cs index e0f86c7..f0bdf7c 100644 --- a/Visualizer/SpatialRecordProcessor.cs +++ b/Visualizer/SpatialRecordProcessor.cs @@ -10,11 +10,13 @@ * Andrew Vardeman - optimized rendering of large datasets *******************************************************************************/ -using System.Drawing.Imaging; using AgGateway.ADAPT.ApplicationDataModel.ADM; using AgGateway.ADAPT.ApplicationDataModel.Equipment; using AgGateway.ADAPT.ApplicationDataModel.LoggedData; using AgGateway.ADAPT.ApplicationDataModel.Representations; +using AgGateway.ADAPT.ApplicationDataModel.Shapes; +using AgGateway.ADAPT.Visualizer.Mapping; +using AgGateway.ADAPT.Visualizer.UI; using Point = AgGateway.ADAPT.ApplicationDataModel.Shapes.Point; namespace AgGateway.ADAPT.Visualizer @@ -22,15 +24,15 @@ namespace AgGateway.ADAPT.Visualizer public class SpatialRecordProcessor { private DrawingUtil _drawingUtil; - private readonly TabPage _spatialViewer; + private readonly MapControl _mapControl; private Dictionary _workingDataDictionary; private OperationData _lastOperationData; private List _spatialRecords; private Bitmap? _bitmap; - public SpatialRecordProcessor(TabPage spatialViewer) + public SpatialRecordProcessor(MapControl mapControl) { - _spatialViewer = spatialViewer; + _mapControl = mapControl; } /// @@ -52,197 +54,192 @@ public void ProcessOperation(OperationData operation, List spatia /// public void ThemeMap(string workingDataKey) { - using (var graphics = _spatialViewer.CreateGraphics()) - { - int width = _spatialViewer.Width; - int height = _spatialViewer.Height; - graphics.Clear(Color.White); - _drawingUtil = new DrawingUtil(width, height, graphics); + Map map = new Map(); - List projectedPoints = new List(); - List doubleValues = null; - foreach (SpatialRecord record in _spatialRecords) + List projectedPoints = new List(); + List doubleValues = null; + foreach (SpatialRecord record in _spatialRecords) + { + Point? point = record.Geometry.FirstPoint(); + if (point is null) { - Point? point = record.Geometry.FirstPoint(); - if (point is null) - { - continue; - } + continue; + } - projectedPoints.Add(point.ToUtm()); + projectedPoints.Add(point.ToUtm()); - if (_workingDataDictionary.ContainsKey(workingDataKey)) + if (_workingDataDictionary.ContainsKey(workingDataKey)) + { + WorkingData workingData = _workingDataDictionary[workingDataKey]; + RepresentationValue repValue = record.GetMeterValue(workingData); + if (repValue is NumericRepresentationValue) { - WorkingData workingData = _workingDataDictionary[workingDataKey]; - RepresentationValue repValue = record.GetMeterValue(workingData); - if (repValue is NumericRepresentationValue) + NumericRepresentationValue numericValue = repValue as NumericRepresentationValue; + if (doubleValues == null) + { + doubleValues = new List(); + } + + if (numericValue != null && numericValue.Value != null) { - NumericRepresentationValue numericValue = repValue as NumericRepresentationValue; - if (doubleValues == null) - { - doubleValues = new List(); - } doubleValues.Add(numericValue.Value.Value); } - else if (repValue is EnumeratedValue) + } + else if (repValue is EnumeratedValue) + { + EnumeratedValue enumValue = repValue as EnumeratedValue; + if (enumValue.Representation.Code == "dtRecordingStatus") { - EnumeratedValue enumValue = repValue as EnumeratedValue; - if (enumValue.Representation.Code == "dtRecordingStatus") + if (doubleValues == null) { - if (doubleValues == null) - { - doubleValues = new List(); - } - doubleValues.Add(enumValue.Value.Value == "On" ? 1d : -1d); + doubleValues = new List(); } + + doubleValues.Add(enumValue.Value.Value == "On" ? 1d : -1d); } } } + } - if (!projectedPoints.Any()) + if (!projectedPoints.Any()) + { + return; + } + + if (projectedPoints.All(p => !double.IsNaN(p.X) && !double.IsNaN(p.Y))) + { + if (doubleValues == null || doubleValues.Count == 0) { - return; + //WorkingData is not numeric + AddMapObject(map, projectedPoints, DrawingUtil.B_Black); } - - _drawingUtil.SetMinMax(projectedPoints); - var screenPolygon = projectedPoints.Select(point => point.ToXy(_drawingUtil.MinX, _drawingUtil.MinY, _drawingUtil.GetDelta())).ToArray(); - - if (screenPolygon.All(p => !double.IsNaN(p.X) && !double.IsNaN(p.Y))) + else { - if (doubleValues == null) + if (doubleValues.Max() == doubleValues.Min()) { - //WorkingData is not numeric - graphics.DrawPolygon(DrawingUtil.B_Black, screenPolygon); + //All values are the same + if (doubleValues.Max() <= 0d) + { + //Zero values + AddMapObject(map, projectedPoints, DrawingUtil.E_Red); + } + else + { + //Non-zero values + AddMapObject(map, projectedPoints, DrawingUtil.C_DarkMagenta); + } } else { - if (doubleValues.Max() == doubleValues.Min()) + double max = doubleValues.Max(); + double min = doubleValues.Min(); + double average = doubleValues.Average(); + List removedZeroValues = doubleValues.Where(dv => dv != 0).ToList(); + double averageWithoutZeroes = removedZeroValues.Average(); + if (average != averageWithoutZeroes) + { + min = removedZeroValues.Min(); + } + + int i = 0; + double range = (max - min) / 7.0; + double e7th = min; + double f7th = e7th + range; + double g7th = f7th + range; + double h7th = g7th + range; + double i7th = h7th + range; + double j7th = i7th + range; + double k7th = j7th + range; + double l7th = max; + + foreach (ADAPT.ApplicationDataModel.Shapes.Point f in projectedPoints) { - //All values are the same - if (doubleValues.Max() <= 0d) + double dbl = i < doubleValues.Count + ? doubleValues[i] + : 0d; //Values will be in same order as points + Pen pen = DrawingUtil.B_Black; + + if (dbl <= e7th) { - //Zero values - graphics.DrawPolygon(DrawingUtil.E_Red, screenPolygon); + pen = DrawingUtil.E_Red; } - else + else if (dbl <= f7th) { - //Non-zero values - graphics.DrawPolygon(DrawingUtil.L_DarkGreen, screenPolygon); + pen = DrawingUtil.F_DarkOrange; } - } - else - { - double max = doubleValues.Max(); - double min = doubleValues.Min(); - double average = doubleValues.Average(); - List removedZeroValues = doubleValues.Where(dv => dv != 0).ToList(); - double averageWithoutZeroes = removedZeroValues.Average(); - if (average != averageWithoutZeroes) + else if (dbl <= g7th) { - min = removedZeroValues.Min(); + pen = DrawingUtil.G_Gold; } - - int i = 0; - double range = (max - min) / 7.0; - double e7th = min; - double f7th = e7th + range; - double g7th = f7th + range; - double h7th = g7th + range; - double i7th = h7th + range; - double j7th = i7th + range; - double k7th = j7th + range; - double l7th = max; - - if (width <= 0 || height <= 0) + else if (dbl <= h7th) { - return; + pen = DrawingUtil.H_YellowGreen; } - - if (_bitmap == null || _bitmap.Width < width || _bitmap.Height < height) + else if (dbl <= i7th) { - int maxWidth = _bitmap == null ? width : Math.Max(width, _bitmap.Width); - int maxHeight = _bitmap == null ? height : Math.Max(height, _bitmap.Height); - _bitmap?.Dispose(); - _bitmap = new Bitmap(maxWidth, maxHeight, PixelFormat.Format32bppArgb); + pen = DrawingUtil.I_LawnGreen; } - - using (Graphics g = Graphics.FromImage(_bitmap)) + else if (dbl <= j7th) { - g.Clear(Color.White); + pen = DrawingUtil.J_LimeGreen; } - - BitmapData bitmapData = _bitmap.LockBits(new Rectangle(0, 0, width, height), - ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); - - - foreach (PointF f in screenPolygon) + else if (dbl <= k7th) { - double dbl = i < doubleValues.Count - ? doubleValues[i] - : 0d; //Values will be in same order as points - Color color = Color.Black; - - if (dbl <= e7th) - { - color = DrawingUtil.E_Red.Color; - } - else if (dbl <= f7th) - { - color = DrawingUtil.F_DarkOrange.Color; - } - else if (dbl <= g7th) - { - color = DrawingUtil.G_Gold.Color; - } - else if (dbl <= h7th) - { - color = DrawingUtil.H_YellowGreen.Color; - } - else if (dbl <= i7th) - { - color = DrawingUtil.I_LawnGreen.Color; - } - else if (dbl <= j7th) - { - color = DrawingUtil.J_LimeGreen.Color; - } - else if (dbl <= k7th) - { - color = DrawingUtil.K_ForestGreen.Color; - } - else if (dbl <= l7th) - { - color = DrawingUtil.L_DarkGreen.Color; - } - - unsafe - { - byte* bytes = (byte*) bitmapData.Scan0; - int cx = (int) f.X; - int cy = (int) f.Y; - for (int x = Math.Max(cx - 2, 0); x <= Math.Min(cx + 1, width - 1); x++) - { - for (int y = Math.Max(cy - 2, 0); y <= Math.Min(cy + 1, height - 1); y++) - { - byte* p = bytes + y * bitmapData.Stride + x * 4; - p[0] = color.B; - p[1] = color.G; - p[2] = color.R; - p[3] = color.A; - } - } - } - - i++; + pen = DrawingUtil.K_ForestGreen; + } + else if (dbl <= l7th) + { + pen = DrawingUtil.L_DarkGreen; } - _bitmap.UnlockBits(bitmapData); - graphics.DrawImage(_bitmap, 0, 0); - } + map.AddMapObject(new MapPoint + { + Point = f, + Pen = pen + }); + i++; + } } + } } + _mapControl.Map = map; + } + + public void AddMapObject(Map map, List points, Pen pen) + { + if (map == null || points == null || points.Count == 0) + { + return; + } + if (points.Count == 1) + { + map.AddMapObject(new MapPoint + { + Point = points[0], + Pen = pen + }); + } + else if (points.Count == 2) + { + map.AddMapObject(new MapLineString + { + LineString = new LineString { Points = points }, + Pen = pen + }); + } + else + { + map.AddMapObject(new MapPolygon + { + Polygon = new Polygon + { + ExteriorRing = new LinearRing { Points = points }, + }, + Pen = pen + }); + } } public List WorkingDataList diff --git a/Visualizer/UI/MainForm.Designer.cs b/Visualizer/UI/MainForm.Designer.cs index 73bf37e..c05f156 100644 --- a/Visualizer/UI/MainForm.Designer.cs +++ b/Visualizer/UI/MainForm.Designer.cs @@ -34,6 +34,11 @@ private void InitializeComponent() _splitContainerMap = new SplitContainer(); _tabControlViewer = new TabControl(); _tabPageSpatial = new TabPage(); + _mapControl = new MapControl(); + _mapToolStrip = new ToolStrip(); + _zoomInToolStripButton = new ToolStripButton(); + _zoomOutToolStripButton = new ToolStripButton(); + _zoomWorldToolStripButton = new ToolStripButton(); _tabPageRawData = new TabPage(); _tableLayoutPanelRawData = new TableLayoutPanel(); _dataGridViewRawData = new DataGridView(); @@ -70,6 +75,8 @@ private void InitializeComponent() _splitContainerMap.Panel2.SuspendLayout(); _splitContainerMap.SuspendLayout(); _tabControlViewer.SuspendLayout(); + _tabPageSpatial.SuspendLayout(); + _mapToolStrip.SuspendLayout(); _tabPageRawData.SuspendLayout(); _tableLayoutPanelRawData.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)_dataGridViewRawData).BeginInit(); @@ -84,8 +91,8 @@ private void InitializeComponent() // _splitContainerViewer // _splitContainerViewer.Dock = DockStyle.Fill; - _splitContainerViewer.Location = new Point(0, 79); - _splitContainerViewer.Margin = new Padding(4, 5, 4, 5); + _splitContainerViewer.Location = new Point(0, 74); + _splitContainerViewer.Margin = new Padding(4); _splitContainerViewer.Name = "_splitContainerViewer"; // // _splitContainerViewer.Panel1 @@ -95,8 +102,8 @@ private void InitializeComponent() // _splitContainerViewer.Panel2 // _splitContainerViewer.Panel2.Controls.Add(_splitContainerMap); - _splitContainerViewer.Size = new Size(887, 682); - _splitContainerViewer.SplitterDistance = 221; + _splitContainerViewer.Size = new Size(776, 497); + _splitContainerViewer.SplitterDistance = 193; _splitContainerViewer.TabIndex = 1; _splitContainerViewer.SplitterMoved += _splitContainerViewer_SplitterMoved; // @@ -104,17 +111,18 @@ private void InitializeComponent() // _treeViewMetadata.Dock = DockStyle.Fill; _treeViewMetadata.Location = new Point(0, 0); - _treeViewMetadata.Margin = new Padding(4, 5, 4, 5); + _treeViewMetadata.Margin = new Padding(4); _treeViewMetadata.Name = "_treeViewMetadata"; - _treeViewMetadata.Size = new Size(221, 682); + _treeViewMetadata.Size = new Size(193, 497); _treeViewMetadata.TabIndex = 0; + _treeViewMetadata.AfterSelect += _treeViewMetadata_AfterSelect; _treeViewMetadata.NodeMouseClick += _treeViewMetadata_NodeMouseClick; // // _splitContainerMap // _splitContainerMap.Dock = DockStyle.Fill; _splitContainerMap.Location = new Point(0, 0); - _splitContainerMap.Margin = new Padding(4, 5, 4, 5); + _splitContainerMap.Margin = new Padding(4); _splitContainerMap.Name = "_splitContainerMap"; _splitContainerMap.Orientation = Orientation.Horizontal; // @@ -127,9 +135,8 @@ private void InitializeComponent() // _splitContainerMap.Panel2.Controls.Add(_dataGridViewTotals); _splitContainerMap.Panel2.Controls.Add(_labelTotals); - _splitContainerMap.Size = new Size(662, 682); - _splitContainerMap.SplitterDistance = 564; - _splitContainerMap.SplitterWidth = 6; + _splitContainerMap.Size = new Size(579, 497); + _splitContainerMap.SplitterDistance = 411; _splitContainerMap.TabIndex = 0; _splitContainerMap.SplitterMoved += _splitContainerMap_SplitterMoved; // @@ -138,32 +145,81 @@ private void InitializeComponent() _tabControlViewer.Controls.Add(_tabPageSpatial); _tabControlViewer.Controls.Add(_tabPageRawData); _tabControlViewer.Dock = DockStyle.Fill; - _tabControlViewer.Location = new Point(0, 44); - _tabControlViewer.Margin = new Padding(4, 5, 4, 5); + _tabControlViewer.Location = new Point(0, 33); + _tabControlViewer.Margin = new Padding(4); _tabControlViewer.Name = "_tabControlViewer"; _tabControlViewer.SelectedIndex = 0; - _tabControlViewer.Size = new Size(662, 520); + _tabControlViewer.Size = new Size(579, 378); _tabControlViewer.TabIndex = 1; + _tabControlViewer.SelectedIndexChanged += _tabControlViewer_SelectedIndexChanged; // // _tabPageSpatial // - _tabPageSpatial.Location = new Point(4, 29); - _tabPageSpatial.Margin = new Padding(4, 5, 4, 5); + _tabPageSpatial.Controls.Add(_mapControl); + _tabPageSpatial.Controls.Add(_mapToolStrip); + _tabPageSpatial.Location = new Point(4, 24); + _tabPageSpatial.Margin = new Padding(4); _tabPageSpatial.Name = "_tabPageSpatial"; - _tabPageSpatial.Padding = new Padding(4, 5, 4, 5); - _tabPageSpatial.Size = new Size(654, 487); + _tabPageSpatial.Padding = new Padding(4); + _tabPageSpatial.Size = new Size(571, 350); _tabPageSpatial.TabIndex = 0; _tabPageSpatial.Text = "Spatial Viewer"; _tabPageSpatial.UseVisualStyleBackColor = true; - _tabPageSpatial.Paint += _tabPageSpatial_Paint; + // + // _mapControl + // + _mapControl.Dock = DockStyle.Fill; + _mapControl.Location = new Point(4, 29); + _mapControl.Name = "_mapControl"; + _mapControl.Size = new Size(563, 317); + _mapControl.TabIndex = 0; + // + // _mapToolStrip + // + _mapToolStrip.Items.AddRange(new ToolStripItem[] { _zoomInToolStripButton, _zoomOutToolStripButton, _zoomWorldToolStripButton }); + _mapToolStrip.Location = new Point(4, 4); + _mapToolStrip.Name = "_mapToolStrip"; + _mapToolStrip.Size = new Size(563, 25); + _mapToolStrip.TabIndex = 1; + _mapToolStrip.Text = "_mapToolStrip"; + // + // _zoomInToolStripButton + // + _zoomInToolStripButton.DisplayStyle = ToolStripItemDisplayStyle.Text; + _zoomInToolStripButton.Image = (Image)resources.GetObject("_zoomInToolStripButton.Image"); + _zoomInToolStripButton.ImageTransparentColor = Color.Magenta; + _zoomInToolStripButton.Name = "_zoomInToolStripButton"; + _zoomInToolStripButton.Size = new Size(56, 22); + _zoomInToolStripButton.Text = "Zoom In"; + _zoomInToolStripButton.Click += _zoomInToolStripButton_Click; + // + // _zoomOutToolStripButton + // + _zoomOutToolStripButton.DisplayStyle = ToolStripItemDisplayStyle.Text; + _zoomOutToolStripButton.Image = (Image)resources.GetObject("_zoomOutToolStripButton.Image"); + _zoomOutToolStripButton.ImageTransparentColor = Color.Magenta; + _zoomOutToolStripButton.Name = "_zoomOutToolStripButton"; + _zoomOutToolStripButton.Size = new Size(66, 22); + _zoomOutToolStripButton.Text = "Zoom Out"; + _zoomOutToolStripButton.Click += _zoomOutToolStripButton_Click; + // + // _zoomWorldToolStripButton + // + _zoomWorldToolStripButton.DisplayStyle = ToolStripItemDisplayStyle.Text; + _zoomWorldToolStripButton.Image = (Image)resources.GetObject("_zoomWorldToolStripButton.Image"); + _zoomWorldToolStripButton.ImageTransparentColor = Color.Magenta; + _zoomWorldToolStripButton.Name = "_zoomWorldToolStripButton"; + _zoomWorldToolStripButton.Size = new Size(78, 22); + _zoomWorldToolStripButton.Text = "Zoom World"; + _zoomWorldToolStripButton.Click += _zoomWorldToolStripButton_Click; // // _tabPageRawData // _tabPageRawData.Controls.Add(_tableLayoutPanelRawData); - _tabPageRawData.Location = new Point(4, 29); - _tabPageRawData.Margin = new Padding(4, 5, 4, 5); + _tabPageRawData.Location = new Point(4, 24); + _tabPageRawData.Margin = new Padding(4); _tabPageRawData.Name = "_tabPageRawData"; - _tabPageRawData.Size = new Size(654, 487); + _tabPageRawData.Size = new Size(571, 350); _tabPageRawData.TabIndex = 1; _tabPageRawData.Text = "Raw data Viewer"; _tabPageRawData.UseVisualStyleBackColor = true; @@ -181,29 +237,28 @@ private void InitializeComponent() _tableLayoutPanelRawData.RowCount = 2; _tableLayoutPanelRawData.RowStyles.Add(new RowStyle(SizeType.Percent, 100F)); _tableLayoutPanelRawData.RowStyles.Add(new RowStyle()); - _tableLayoutPanelRawData.Size = new Size(654, 487); + _tableLayoutPanelRawData.Size = new Size(571, 350); _tableLayoutPanelRawData.TabIndex = 2; // // _dataGridViewRawData // _dataGridViewRawData.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; _dataGridViewRawData.Dock = DockStyle.Fill; - _dataGridViewRawData.Location = new Point(4, 5); - _dataGridViewRawData.Margin = new Padding(4, 5, 4, 5); + _dataGridViewRawData.Location = new Point(4, 4); + _dataGridViewRawData.Margin = new Padding(4); _dataGridViewRawData.Name = "_dataGridViewRawData"; _dataGridViewRawData.RowHeadersWidth = 62; - _dataGridViewRawData.Size = new Size(646, 432); + _dataGridViewRawData.Size = new Size(563, 308); _dataGridViewRawData.TabIndex = 0; _dataGridViewRawData.ColumnAdded += _dataGridViewRawData_ColumnAdded; - _dataGridViewRawData.Paint += _dataGridViewRawData_Paint; // // _buttonExportRawData // _buttonExportRawData.Anchor = AnchorStyles.Bottom | AnchorStyles.Right; - _buttonExportRawData.Location = new Point(531, 447); - _buttonExportRawData.Margin = new Padding(4, 5, 4, 5); + _buttonExportRawData.Location = new Point(463, 320); + _buttonExportRawData.Margin = new Padding(4); _buttonExportRawData.Name = "_buttonExportRawData"; - _buttonExportRawData.Size = new Size(119, 35); + _buttonExportRawData.Size = new Size(104, 26); _buttonExportRawData.TabIndex = 1; _buttonExportRawData.Text = "Export"; _buttonExportRawData.UseVisualStyleBackColor = true; @@ -227,12 +282,11 @@ private void InitializeComponent() _limitDataPanel.Controls.Add(_maxColumnsNumericUpDown, 4, 0); _limitDataPanel.Dock = DockStyle.Top; _limitDataPanel.Location = new Point(0, 0); - _limitDataPanel.Margin = new Padding(3, 4, 3, 4); _limitDataPanel.Name = "_limitDataPanel"; - _limitDataPanel.Padding = new Padding(0, 6, 0, 6); + _limitDataPanel.Padding = new Padding(0, 4, 0, 4); _limitDataPanel.RowCount = 1; _limitDataPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 100F)); - _limitDataPanel.Size = new Size(662, 44); + _limitDataPanel.Size = new Size(579, 33); _limitDataPanel.TabIndex = 0; _limitDataPanel.VisibleChanged += _limitDataPanel_VisibleChanged; // @@ -240,10 +294,9 @@ private void InitializeComponent() // _limitDataCheckBox.Anchor = AnchorStyles.Left; _limitDataCheckBox.AutoSize = true; - _limitDataCheckBox.Location = new Point(3, 10); - _limitDataCheckBox.Margin = new Padding(3, 4, 3, 4); + _limitDataCheckBox.Location = new Point(3, 7); _limitDataCheckBox.Name = "_limitDataCheckBox"; - _limitDataCheckBox.Size = new Size(100, 24); + _limitDataCheckBox.Size = new Size(80, 19); _limitDataCheckBox.TabIndex = 0; _limitDataCheckBox.Text = "Limit Data"; _limitDataCheckBox.UseVisualStyleBackColor = true; @@ -254,10 +307,10 @@ private void InitializeComponent() _maxRowsLabel.Anchor = AnchorStyles.Left; _maxRowsLabel.AutoSize = true; _maxRowsLabel.Enabled = false; - _maxRowsLabel.Location = new Point(112, 12); - _maxRowsLabel.Margin = new Padding(6, 0, 3, 0); + _maxRowsLabel.Location = new Point(91, 9); + _maxRowsLabel.Margin = new Padding(5, 0, 3, 0); _maxRowsLabel.Name = "_maxRowsLabel"; - _maxRowsLabel.Size = new Size(76, 20); + _maxRowsLabel.Size = new Size(60, 15); _maxRowsLabel.TabIndex = 1; _maxRowsLabel.Text = "Max Rows"; // @@ -266,10 +319,10 @@ private void InitializeComponent() _maxColumnsLabel.Anchor = AnchorStyles.Left; _maxColumnsLabel.AutoSize = true; _maxColumnsLabel.Enabled = false; - _maxColumnsLabel.Location = new Point(260, 12); - _maxColumnsLabel.Margin = new Padding(6, 0, 3, 0); + _maxColumnsLabel.Location = new Point(215, 9); + _maxColumnsLabel.Margin = new Padding(5, 0, 3, 0); _maxColumnsLabel.Name = "_maxColumnsLabel"; - _maxColumnsLabel.Size = new Size(98, 20); + _maxColumnsLabel.Size = new Size(80, 15); _maxColumnsLabel.TabIndex = 3; _maxColumnsLabel.Text = "Max Columns"; // @@ -278,11 +331,11 @@ private void InitializeComponent() _maxRowsNumericUpDown.Anchor = AnchorStyles.Left; _maxRowsNumericUpDown.Enabled = false; _maxRowsNumericUpDown.Increment = new decimal(new int[] { 100, 0, 0, 0 }); - _maxRowsNumericUpDown.Location = new Point(194, 8); + _maxRowsNumericUpDown.Location = new Point(157, 5); _maxRowsNumericUpDown.Margin = new Padding(3, 0, 3, 0); _maxRowsNumericUpDown.Maximum = new decimal(new int[] { 100000, 0, 0, 0 }); _maxRowsNumericUpDown.Name = "_maxRowsNumericUpDown"; - _maxRowsNumericUpDown.Size = new Size(57, 27); + _maxRowsNumericUpDown.Size = new Size(50, 23); _maxRowsNumericUpDown.TabIndex = 2; _maxRowsNumericUpDown.Value = new decimal(new int[] { 100, 0, 0, 0 }); _maxRowsNumericUpDown.ValueChanged += _maxRowsNumericUpDown_ValueChanged; @@ -292,12 +345,12 @@ private void InitializeComponent() _maxColumnsNumericUpDown.Anchor = AnchorStyles.Left; _maxColumnsNumericUpDown.Enabled = false; _maxColumnsNumericUpDown.Increment = new decimal(new int[] { 10, 0, 0, 0 }); - _maxColumnsNumericUpDown.Location = new Point(364, 8); + _maxColumnsNumericUpDown.Location = new Point(301, 5); _maxColumnsNumericUpDown.Margin = new Padding(3, 0, 3, 0); _maxColumnsNumericUpDown.Maximum = new decimal(new int[] { 10000, 0, 0, 0 }); _maxColumnsNumericUpDown.Minimum = new decimal(new int[] { 10, 0, 0, 0 }); _maxColumnsNumericUpDown.Name = "_maxColumnsNumericUpDown"; - _maxColumnsNumericUpDown.Size = new Size(57, 27); + _maxColumnsNumericUpDown.Size = new Size(50, 23); _maxColumnsNumericUpDown.TabIndex = 4; _maxColumnsNumericUpDown.Value = new decimal(new int[] { 50, 0, 0, 0 }); _maxColumnsNumericUpDown.ValueChanged += _maxColumnsNumericUpDown_ValueChanged; @@ -307,12 +360,12 @@ private void InitializeComponent() _dataGridViewTotals.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize; _dataGridViewTotals.Columns.AddRange(new DataGridViewColumn[] { _dataGridColumnDescription, _dataGridColumnValue }); _dataGridViewTotals.Dock = DockStyle.Fill; - _dataGridViewTotals.Location = new Point(0, 20); - _dataGridViewTotals.Margin = new Padding(4, 5, 4, 5); + _dataGridViewTotals.Location = new Point(0, 15); + _dataGridViewTotals.Margin = new Padding(4); _dataGridViewTotals.Name = "_dataGridViewTotals"; _dataGridViewTotals.RowHeadersVisible = false; _dataGridViewTotals.RowHeadersWidth = 62; - _dataGridViewTotals.Size = new Size(662, 92); + _dataGridViewTotals.Size = new Size(579, 67); _dataGridViewTotals.TabIndex = 1; // // _dataGridColumnDescription @@ -335,7 +388,7 @@ private void InitializeComponent() _labelTotals.Dock = DockStyle.Top; _labelTotals.Location = new Point(0, 0); _labelTotals.Name = "_labelTotals"; - _labelTotals.Size = new Size(48, 20); + _labelTotals.Size = new Size(38, 15); _labelTotals.TabIndex = 0; _labelTotals.Text = "Totals"; // @@ -346,7 +399,7 @@ private void InitializeComponent() _toolStrip.Items.AddRange(new ToolStripItem[] { _importToolStripButton, _exportToolStripButton, _findToolStripButton, _settingsToolStripButton, _aboutToolStripButton }); _toolStrip.Location = new Point(0, 0); _toolStrip.Name = "_toolStrip"; - _toolStrip.Size = new Size(887, 79); + _toolStrip.Size = new Size(776, 74); _toolStrip.TabIndex = 2; _toolStrip.Text = "toolStrip1"; // @@ -356,7 +409,7 @@ private void InitializeComponent() _importToolStripButton.ImageScaling = ToolStripItemImageScaling.None; _importToolStripButton.ImageTransparentColor = Color.Magenta; _importToolStripButton.Name = "_importToolStripButton"; - _importToolStripButton.Size = new Size(58, 76); + _importToolStripButton.Size = new Size(56, 71); _importToolStripButton.Text = "Import"; _importToolStripButton.TextImageRelation = TextImageRelation.ImageAboveText; _importToolStripButton.ToolTipText = "Import (Ctrl+I)"; @@ -368,7 +421,7 @@ private void InitializeComponent() _exportToolStripButton.ImageScaling = ToolStripItemImageScaling.None; _exportToolStripButton.ImageTransparentColor = Color.Magenta; _exportToolStripButton.Name = "_exportToolStripButton"; - _exportToolStripButton.Size = new Size(56, 76); + _exportToolStripButton.Size = new Size(56, 71); _exportToolStripButton.Text = "Export"; _exportToolStripButton.TextImageRelation = TextImageRelation.ImageAboveText; _exportToolStripButton.ToolTipText = "Export (Ctrl+E)"; @@ -380,7 +433,7 @@ private void InitializeComponent() _findToolStripButton.ImageScaling = ToolStripItemImageScaling.None; _findToolStripButton.ImageTransparentColor = Color.Magenta; _findToolStripButton.Name = "_findToolStripButton"; - _findToolStripButton.Size = new Size(56, 76); + _findToolStripButton.Size = new Size(56, 71); _findToolStripButton.Text = "Find"; _findToolStripButton.TextImageRelation = TextImageRelation.ImageAboveText; _findToolStripButton.ToolTipText = "Find (Ctrl+F)"; @@ -392,7 +445,7 @@ private void InitializeComponent() _settingsToolStripButton.ImageScaling = ToolStripItemImageScaling.None; _settingsToolStripButton.ImageTransparentColor = Color.Magenta; _settingsToolStripButton.Name = "_settingsToolStripButton"; - _settingsToolStripButton.Size = new Size(66, 76); + _settingsToolStripButton.Size = new Size(56, 71); _settingsToolStripButton.Text = "Settings"; _settingsToolStripButton.TextImageRelation = TextImageRelation.ImageAboveText; _settingsToolStripButton.Click += _settingsToolStripButton_Click; @@ -403,7 +456,7 @@ private void InitializeComponent() _aboutToolStripButton.ImageScaling = ToolStripItemImageScaling.None; _aboutToolStripButton.ImageTransparentColor = Color.Magenta; _aboutToolStripButton.Name = "_aboutToolStripButton"; - _aboutToolStripButton.Size = new Size(56, 76); + _aboutToolStripButton.Size = new Size(56, 71); _aboutToolStripButton.Text = "About"; _aboutToolStripButton.TextImageRelation = TextImageRelation.ImageAboveText; _aboutToolStripButton.Click += _aboutToolStripButton_Click; @@ -415,7 +468,7 @@ private void InitializeComponent() _menuStrip.Location = new Point(0, 0); _menuStrip.Name = "_menuStrip"; _menuStrip.Padding = new Padding(4, 2, 0, 2); - _menuStrip.Size = new Size(831, 37); + _menuStrip.Size = new Size(727, 28); _menuStrip.TabIndex = 10; _menuStrip.Text = "menuStrip1"; _menuStrip.Visible = false; @@ -424,14 +477,14 @@ private void InitializeComponent() // _dummyMenuItem.DropDownItems.AddRange(new ToolStripItem[] { _importMenuItem, _exportMenuItem, _findMenuItem, _findNextMenuItem }); _dummyMenuItem.Name = "_dummyMenuItem"; - _dummyMenuItem.Size = new Size(196, 33); + _dummyMenuItem.Size = new Size(162, 24); _dummyMenuItem.Text = "{dummy_for_shorcut_keys}"; // // _importMenuItem // _importMenuItem.Name = "_importMenuItem"; _importMenuItem.ShortcutKeys = Keys.Control | Keys.I; - _importMenuItem.Size = new Size(185, 26); + _importMenuItem.Size = new Size(147, 22); _importMenuItem.Text = "import"; _importMenuItem.Click += _importMenuItem_Click; // @@ -439,7 +492,7 @@ private void InitializeComponent() // _exportMenuItem.Name = "_exportMenuItem"; _exportMenuItem.ShortcutKeys = Keys.Control | Keys.E; - _exportMenuItem.Size = new Size(185, 26); + _exportMenuItem.Size = new Size(147, 22); _exportMenuItem.Text = "export"; _exportMenuItem.Click += _exportMenuItem_Click; // @@ -447,7 +500,7 @@ private void InitializeComponent() // _findMenuItem.Name = "_findMenuItem"; _findMenuItem.ShortcutKeys = Keys.Control | Keys.F; - _findMenuItem.Size = new Size(185, 26); + _findMenuItem.Size = new Size(147, 22); _findMenuItem.Text = "find"; _findMenuItem.Click += _findMenuItem_Click; // @@ -455,7 +508,7 @@ private void InitializeComponent() // _findNextMenuItem.Name = "_findNextMenuItem"; _findNextMenuItem.ShortcutKeys = Keys.F3; - _findNextMenuItem.Size = new Size(185, 26); + _findNextMenuItem.Size = new Size(147, 22); _findNextMenuItem.Text = "find_next"; _findNextMenuItem.Click += _findNextMenuItem_Click; // @@ -463,26 +516,26 @@ private void InitializeComponent() // workingDataComboBox.DropDownStyle = ComboBoxStyle.DropDownList; workingDataComboBox.FormattingEnabled = true; - workingDataComboBox.Location = new Point(352, 17); + workingDataComboBox.Location = new Point(308, 13); workingDataComboBox.Margin = new Padding(2); workingDataComboBox.Name = "workingDataComboBox"; - workingDataComboBox.Size = new Size(474, 28); + workingDataComboBox.Size = new Size(415, 23); workingDataComboBox.TabIndex = 0; workingDataComboBox.Visible = false; workingDataComboBox.SelectedIndexChanged += workingDataComboBox_SelectedIndexChanged; // // MainForm // - AutoScaleDimensions = new SizeF(8F, 20F); + AutoScaleDimensions = new SizeF(7F, 15F); AutoScaleMode = AutoScaleMode.Font; - ClientSize = new Size(887, 761); + ClientSize = new Size(776, 571); Controls.Add(workingDataComboBox); Controls.Add(_splitContainerViewer); Controls.Add(_toolStrip); Controls.Add(_menuStrip); Icon = (Icon)resources.GetObject("$this.Icon"); MainMenuStrip = _menuStrip; - Margin = new Padding(4, 5, 4, 5); + Margin = new Padding(4); Name = "MainForm"; Text = "ADAPT - Visualizer"; WindowState = FormWindowState.Maximized; @@ -501,6 +554,10 @@ private void InitializeComponent() ((System.ComponentModel.ISupportInitialize)_splitContainerMap).EndInit(); _splitContainerMap.ResumeLayout(false); _tabControlViewer.ResumeLayout(false); + _tabPageSpatial.ResumeLayout(false); + _tabPageSpatial.PerformLayout(); + _mapToolStrip.ResumeLayout(false); + _mapToolStrip.PerformLayout(); _tabPageRawData.ResumeLayout(false); _tableLayoutPanelRawData.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)_dataGridViewRawData).EndInit(); @@ -551,6 +608,11 @@ private void InitializeComponent() private NumericUpDown _maxColumnsNumericUpDown; private ToolStripButton _settingsToolStripButton; private TableLayoutPanel _tableLayoutPanelRawData; + private MapControl _mapControl; + private ToolStrip _mapToolStrip; + private ToolStripButton _zoomInToolStripButton; + private ToolStripButton _zoomOutToolStripButton; + private ToolStripButton _zoomWorldToolStripButton; } } diff --git a/Visualizer/UI/MainForm.cs b/Visualizer/UI/MainForm.cs index 33d2d50..afb9792 100644 --- a/Visualizer/UI/MainForm.cs +++ b/Visualizer/UI/MainForm.cs @@ -59,10 +59,10 @@ public MainForm() _model = new Model(UpdateStatus); _operationDataProcessor = new OperationDataProcessor(); - _boundaryProcessor = new BoundaryProcessor(_tabPageSpatial); - _guidanceProcessor = new GuidanceProcessor(_tabPageSpatial); - _spatialRecordProcessor = new SpatialRecordProcessor(_tabPageSpatial); - _prescriptionProcessor = new PrescriptionProcessor(_tabPageSpatial); + _boundaryProcessor = new BoundaryProcessor(_mapControl); + _guidanceProcessor = new GuidanceProcessor(_mapControl); + _spatialRecordProcessor = new SpatialRecordProcessor(_mapControl); + _prescriptionProcessor = new PrescriptionProcessor(_mapControl); _limitDataPanel.Visible = Settings.Default.ShowLimitDataUI; _limitDataCheckBox.Checked = Settings.Default.ShowLimitDataUI && Settings.Default.LimitData; @@ -122,35 +122,7 @@ private void UpdateStatus(Model.State state, string s) private void _treeViewMetadata_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) { - _tabControlViewer.SelectTab(_tabPageSpatial); - workingDataComboBox.Visible = false; - - using (var g = _tabPageSpatial.CreateGraphics()) - { - g.Clear(Color.White); - } - _dataGridViewRawData.DataSource = null; - _dataGridViewTotals.DataSource = null; - - var treeNode = e.Node; - - _tabPageSpatial.Tag = treeNode.Tag == null ? treeNode.Tag : treeNode; - - if (treeNode.Tag == null) - return; - - Cursor.Current = Cursors.WaitCursor; - ProcessData(GetProcessDataRequest(treeNode)); - Cursor.Current = Cursors.Default; - } - private void _tabPageSpatial_Paint(object sender, PaintEventArgs e) - { - if (ProcessedNode == null) - { - return; - } - ProcessData(GetProcessDataRequest(ProcessedNode)); } private void _aboutToolStripButton_Click(object sender, EventArgs e) @@ -246,7 +218,6 @@ private void ProcessData(ProcessDataRequest request) var element = objectWithIndex.Element; ApplicationDataModel.ADM.ApplicationDataModel model = _model.ApplicationDataModels[objectWithIndex.ApplicationDataModelIndex]; - workingDataComboBox.Visible = false; if (element is FieldBoundary) { _boundaryProcessor.ProcessBoundary(element as FieldBoundary); @@ -289,7 +260,6 @@ private void ProcessData(ProcessDataRequest request) _dataGridViewRawData.DataSource = _operationDataProcessor.ProcessOperationData(operation, spatialRecords, request.LimitData, request.MaxColumns); _spatialRecordProcessor.ProcessOperation(operation, spatialRecords, model.Catalog); - workingDataComboBox.Visible = true; if (matchesLastRequest) { DrawSpatialRecords(); @@ -545,11 +515,6 @@ private void DrawSpatialRecords() _spatialRecordProcessor.ThemeMap(workingDataKey); } - private void _dataGridViewRawData_Paint(object sender, PaintEventArgs e) - { - workingDataComboBox.Visible = false; - } - private void _dataGridViewRawData_ColumnAdded(object sender, DataGridViewColumnEventArgs e) { e.Column.FillWeight = 1; @@ -622,5 +587,59 @@ private ProcessDataRequest GetProcessDataRequest(TreeNode node, bool overrideLim (int)_maxColumnsNumericUpDown.Value); } + private void _tabControlViewer_SelectedIndexChanged(object sender, EventArgs e) + { + ShowHideWorkingDataComboBox(_treeViewMetadata.SelectedNode); + } + + private void ShowHideWorkingDataComboBox(TreeNode? treeNode) + { + if (_tabControlViewer.SelectedTab == _tabPageSpatial) + { + var objectWithIndex = (ObjectWithIndex?)treeNode?.Tag; + workingDataComboBox.Visible = objectWithIndex?.Element is OperationData; + } + else + { + workingDataComboBox.Visible = false; + } + } + + private void _treeViewMetadata_AfterSelect(object sender, TreeViewEventArgs e) + { + _mapControl.Map = null; + _tabControlViewer.SelectTab(_tabPageSpatial); + + _dataGridViewRawData.DataSource = null; + _dataGridViewTotals.DataSource = null; + + var treeNode = e.Node; + + _tabPageSpatial.Tag = treeNode.Tag == null ? treeNode.Tag : treeNode; + + ShowHideWorkingDataComboBox(_treeViewMetadata.SelectedNode); + + if (treeNode.Tag == null) + return; + + Cursor.Current = Cursors.WaitCursor; + ProcessData(GetProcessDataRequest(treeNode)); + Cursor.Current = Cursors.Default; + } + + private void _zoomInToolStripButton_Click(object sender, EventArgs e) + { + _mapControl.ZoomIn(); + } + + private void _zoomOutToolStripButton_Click(object sender, EventArgs e) + { + _mapControl.ZoomOut(); + } + + private void _zoomWorldToolStripButton_Click(object sender, EventArgs e) + { + _mapControl.ZoomToMap(); + } } } \ No newline at end of file diff --git a/Visualizer/UI/MainForm.resx b/Visualizer/UI/MainForm.resx index 907b8ec..7e69112 100644 --- a/Visualizer/UI/MainForm.resx +++ b/Visualizer/UI/MainForm.resx @@ -1,7 +1,7 @@  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Visualizer/Visualizer.csproj b/Visualizer/Visualizer.csproj index 34541df..3315488 100644 --- a/Visualizer/Visualizer.csproj +++ b/Visualizer/Visualizer.csproj @@ -8,6 +8,7 @@ enable AgGateway.ADAPT.Visualizer True + true diff --git a/VisualizerTests/DrawingUtilTest.cs b/VisualizerTests/DrawingUtilTest.cs deleted file mode 100644 index 3d0e93f..0000000 --- a/VisualizerTests/DrawingUtilTest.cs +++ /dev/null @@ -1,98 +0,0 @@ -using System.Collections.Generic; -using System.Drawing; -using System.Windows.Forms; -using AgGateway.ADAPT.Visualizer; -using NUnit.Framework; -using Point = AgGateway.ADAPT.ApplicationDataModel.Shapes.Point; - -namespace VisualizerTests -{ - [TestFixture] - public class DrawingUtilTest - { - private DrawingUtil _drawingUtil; - private Graphics _graphics; - private TabPage _tabPage; - - [SetUp] - public void Setup() - { - _tabPage = new TabPage(); - _graphics = _tabPage.CreateGraphics(); - _drawingUtil = new DrawingUtil(1050, 1050, _graphics); - } - - [Test] - public void GivenListOfPointsWhenSetMinAndMaxThenMinIsSet() - { - var points = new List(); - points.Add(new Point { X = 5600, Y = 8900}); - points.Add(new Point { X = 3600, Y = 7200 }); - points.Add(new Point { X = 9900, Y = 1000 }); - points.Add(new Point { X = 7600, Y = 2200 }); - points.Add(new Point { X = 2000, Y = 9000 }); - - _drawingUtil.SetMinMax(points); - Assert.AreEqual(_drawingUtil.MinX, 2000.0); - Assert.AreEqual(_drawingUtil.MinY, 1000.0); - Assert.AreEqual(_drawingUtil.MaxX, 9900.0); - Assert.AreEqual(_drawingUtil.MaxY, 9000.0); - } - - [Test] - public void GivenMinAndMaxesSetAndWidthAndHeightAreEqualWhenGetDeltaThenDeltaIsReturned() - { - var points = new List(); - points.Add(new Point { X = 5600, Y = 8900 }); - points.Add(new Point { X = 3600, Y = 7200 }); - points.Add(new Point { X = 9900, Y = 1000 }); - points.Add(new Point { X = 7600, Y = 2200 }); - points.Add(new Point { X = 2000, Y = 9000 }); - _drawingUtil.SetMinMax(points); - - var delta = _drawingUtil.GetDelta(); - Assert.AreEqual(8, delta); - } - - [Test] - public void GivenMinAndMaxesSetAndHeightAndLatisGreaterWhenGetDeltaThenDeltaIsReturned() - { - _drawingUtil = new DrawingUtil(1050, 1650, _graphics); - - var points = new List(); - points.Add(new Point { X = 5600, Y = 8900 }); - points.Add(new Point { X = 3600, Y = 7200 }); - points.Add(new Point { X = 9000, Y = 1000 }); - points.Add(new Point { X = 7600, Y = 2200 }); - points.Add(new Point { X = 3000, Y = 9000 }); - _drawingUtil.SetMinMax(points); - - var delta = _drawingUtil.GetDelta(); - Assert.AreEqual(6, delta); - } - - [Test] - public void GivenMinAndMaxesSetAndHeightAndLonAreGreaterWhenGetDeltaThenDeltaIsReturned() - { - _drawingUtil = new DrawingUtil(600, 1050, _graphics); - - var points = new List(); - points.Add(new Point { X = 5600, Y = 9000 }); - points.Add(new Point { X = 3600, Y = 7200 }); - points.Add(new Point { X = 9000, Y = 2000 }); - points.Add(new Point { X = 7600, Y = 2700 }); - points.Add(new Point { X = 1000, Y = 8000 }); - _drawingUtil.SetMinMax(points); - - var delta = _drawingUtil.GetDelta(); - Assert.AreEqual(7, delta); - } - - [TearDown] - public void TearDown() - { - _tabPage.Dispose(); - _graphics.Dispose(); - } - } -} diff --git a/VisualizerTests/VisualizerTests.csproj b/VisualizerTests/VisualizerTests.csproj index b686e06..2bf565b 100644 --- a/VisualizerTests/VisualizerTests.csproj +++ b/VisualizerTests/VisualizerTests.csproj @@ -60,7 +60,6 @@ - From 75849487eceed10426dfc603f648067c8c7d21a1 Mon Sep 17 00:00:00 2001 From: Andrew Vardeman Date: Wed, 25 Feb 2026 13:56:05 -0600 Subject: [PATCH 2/6] Remove unused event handler Signed-off-by: Andrew Vardeman --- Visualizer/UI/MainForm.Designer.cs | 1 - Visualizer/UI/MainForm.cs | 5 ----- Visualizer/UI/MainForm.resx | 9 --------- 3 files changed, 15 deletions(-) diff --git a/Visualizer/UI/MainForm.Designer.cs b/Visualizer/UI/MainForm.Designer.cs index c05f156..8828011 100644 --- a/Visualizer/UI/MainForm.Designer.cs +++ b/Visualizer/UI/MainForm.Designer.cs @@ -116,7 +116,6 @@ private void InitializeComponent() _treeViewMetadata.Size = new Size(193, 497); _treeViewMetadata.TabIndex = 0; _treeViewMetadata.AfterSelect += _treeViewMetadata_AfterSelect; - _treeViewMetadata.NodeMouseClick += _treeViewMetadata_NodeMouseClick; // // _splitContainerMap // diff --git a/Visualizer/UI/MainForm.cs b/Visualizer/UI/MainForm.cs index afb9792..667f827 100644 --- a/Visualizer/UI/MainForm.cs +++ b/Visualizer/UI/MainForm.cs @@ -120,11 +120,6 @@ private void UpdateStatus(Model.State state, string s) } } - private void _treeViewMetadata_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) - { - - } - private void _aboutToolStripButton_Click(object sender, EventArgs e) { ShowForm(new AboutForm()); diff --git a/Visualizer/UI/MainForm.resx b/Visualizer/UI/MainForm.resx index 7e69112..8da1dbe 100644 --- a/Visualizer/UI/MainForm.resx +++ b/Visualizer/UI/MainForm.resx @@ -117,15 +117,6 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - True - - - True - - - 266, 10 - 266, 10 From 20e17eb3ede90d52ac3d29e33ff68caacf212464 Mon Sep 17 00:00:00 2001 From: Andrew Vardeman Date: Thu, 26 Feb 2026 08:55:24 -0600 Subject: [PATCH 3/6] Set the app icon to tractor.ico Signed-off-by: Andrew Vardeman --- Visualizer/Visualizer.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/Visualizer/Visualizer.csproj b/Visualizer/Visualizer.csproj index 3315488..8d7c187 100644 --- a/Visualizer/Visualizer.csproj +++ b/Visualizer/Visualizer.csproj @@ -9,6 +9,7 @@ AgGateway.ADAPT.Visualizer True true + Resources\tractor.ico From c42b282d99e39e23a8064c5ef0603ad763ff3e4b Mon Sep 17 00:00:00 2001 From: Andrew Vardeman Date: Thu, 26 Feb 2026 11:17:12 -0600 Subject: [PATCH 4/6] Better null handling in the new code Signed-off-by: Andrew Vardeman --- Visualizer/Mapping/MapBoundingBox.cs | 22 ++++++++++++----- Visualizer/ShapeExtensions.cs | 8 +++--- Visualizer/SpatialRecordProcessor.cs | 13 +--------- Visualizer/UI/MapControl.cs | 37 +++++++++++++++++++--------- 4 files changed, 46 insertions(+), 34 deletions(-) diff --git a/Visualizer/Mapping/MapBoundingBox.cs b/Visualizer/Mapping/MapBoundingBox.cs index 0e665a4..6eaa0c7 100644 --- a/Visualizer/Mapping/MapBoundingBox.cs +++ b/Visualizer/Mapping/MapBoundingBox.cs @@ -40,7 +40,7 @@ public void Update(Shape shape) { Update(point); } - else if (shape is LineString lineString) + else if (shape is LineString lineString && lineString.Points != null) { foreach (var p in lineString.Points) { @@ -49,16 +49,26 @@ public void Update(Shape shape) } else if (shape is Polygon polygon) { - foreach (var p in polygon.ExteriorRing.Points) + if (polygon.ExteriorRing?.Points != null) { - Update(p); + foreach (var p in polygon.ExteriorRing.Points) + { + Update(p); + } } - foreach (var interiorRing in polygon.InteriorRings) + if (polygon.InteriorRings != null) { - foreach (var p in interiorRing.Points) + foreach (var interiorRing in polygon.InteriorRings) { - Update(p); + if (interiorRing?.Points == null) + { + continue; + } + foreach (var p in interiorRing.Points) + { + Update(p); + } } } } diff --git a/Visualizer/ShapeExtensions.cs b/Visualizer/ShapeExtensions.cs index a036e9f..a565bea 100644 --- a/Visualizer/ShapeExtensions.cs +++ b/Visualizer/ShapeExtensions.cs @@ -107,19 +107,19 @@ public static Polygon ToUtm(this Polygon polygon) return new Polygon { - ExteriorRing = polygon.ExteriorRing.ToUtm(), - InteriorRings = polygon.InteriorRings?.Select(ring => ring.ToUtm()).ToList() + ExteriorRing = polygon?.ExteriorRing?.ToUtm(), + InteriorRings = polygon?.InteriorRings?.Select(ring => ring.ToUtm()).ToList() }; } public static LinearRing ToUtm(this LinearRing linearRing) { - return new LinearRing { Points = linearRing.Points.Select(p => p.ToUtm()).ToList() }; + return new LinearRing { Points = linearRing?.Points?.Select(p => p.ToUtm()).ToList() }; } public static LineString ToUtm(this LineString lineString) { - return new LineString { Points = lineString.Points.Select(p => p.ToUtm()).ToList() }; + return new LineString { Points = lineString?.Points?.Select(p => p.ToUtm()).ToList() }; } } } diff --git a/Visualizer/SpatialRecordProcessor.cs b/Visualizer/SpatialRecordProcessor.cs index f0bdf7c..713cc04 100644 --- a/Visualizer/SpatialRecordProcessor.cs +++ b/Visualizer/SpatialRecordProcessor.cs @@ -221,7 +221,7 @@ public void AddMapObject(Map map, List points, Pen pen) Pen = pen }); } - else if (points.Count == 2) + else { map.AddMapObject(new MapLineString { @@ -229,17 +229,6 @@ public void AddMapObject(Map map, List points, Pen pen) Pen = pen }); } - else - { - map.AddMapObject(new MapPolygon - { - Polygon = new Polygon - { - ExteriorRing = new LinearRing { Points = points }, - }, - Pen = pen - }); - } } public List WorkingDataList diff --git a/Visualizer/UI/MapControl.cs b/Visualizer/UI/MapControl.cs index cc0a767..07ad50e 100644 --- a/Visualizer/UI/MapControl.cs +++ b/Visualizer/UI/MapControl.cs @@ -184,24 +184,33 @@ private void DrawMapPolygon(Graphics graphics, MapPolygon mapPolygon) if (mapPolygon.Polygon != null) { PointF[] exteriorPoints = ProjectToControl(mapPolygon.Polygon.ExteriorRing.Points); - if (mapPolygon.Brush != null) + if (exteriorPoints != null && exteriorPoints.Length > 2) { - graphics.FillPolygon(mapPolygon.Brush, exteriorPoints); - } - if (mapPolygon.Pen != null) - { - graphics.DrawPolygon(mapPolygon.Pen, exteriorPoints); - } - foreach (var interiorRing in mapPolygon.Polygon.InteriorRings) - { - PointF[] interiorPoints = ProjectToControl(interiorRing.Points); if (mapPolygon.Brush != null) { - graphics.FillPolygon(mapPolygon.Brush, interiorPoints); + graphics.FillPolygon(mapPolygon.Brush, exteriorPoints); } + if (mapPolygon.Pen != null) { - graphics.DrawPolygon(mapPolygon.Pen, interiorPoints); + graphics.DrawPolygon(mapPolygon.Pen, exteriorPoints); + } + } + + foreach (var interiorRing in mapPolygon.Polygon.InteriorRings) + { + PointF[] interiorPoints = ProjectToControl(interiorRing.Points); + if (interiorPoints != null && interiorPoints.Length > 2) + { + if (mapPolygon.Brush != null) + { + graphics.FillPolygon(mapPolygon.Brush, interiorPoints); + } + + if (mapPolygon.Pen != null) + { + graphics.DrawPolygon(mapPolygon.Pen, interiorPoints); + } } } } @@ -216,6 +225,10 @@ private PointF ProjectToControl(ADAPT.ApplicationDataModel.Shapes.Point point) private PointF[] ProjectToControl(IEnumerable points) { + if (points == null) + { + return Array.Empty(); + } return points.Select(p => ProjectToControl(p)).ToArray(); } From a70a44fc1a3578fd227aaff838055f1411747f16 Mon Sep 17 00:00:00 2001 From: Andrew Vardeman Date: Thu, 26 Feb 2026 11:32:45 -0600 Subject: [PATCH 5/6] Null check in MapControl_MouseMove Signed-off-by: Andrew Vardeman --- Visualizer/UI/MapControl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Visualizer/UI/MapControl.cs b/Visualizer/UI/MapControl.cs index 07ad50e..6334c3a 100644 --- a/Visualizer/UI/MapControl.cs +++ b/Visualizer/UI/MapControl.cs @@ -240,7 +240,7 @@ private void MapControl_MouseDown(object sender, MouseEventArgs e) private void MapControl_MouseMove(object sender, MouseEventArgs e) { - if (e.Button == MouseButtons.Left) + if (e.Button == MouseButtons.Left && _lastMouseDownCenterPoint != null) { float dx = e.X - _lastMouseDownPoint.X; float dy = e.Y - _lastMouseDownPoint.Y; From 1bbf3ca6691c151b53cdeabdf1fb6f763deb0def Mon Sep 17 00:00:00 2001 From: Andrew Vardeman Date: Thu, 26 Feb 2026 11:39:58 -0600 Subject: [PATCH 6/6] More null checks Signed-off-by: Andrew Vardeman --- Visualizer/UI/MapControl.cs | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/Visualizer/UI/MapControl.cs b/Visualizer/UI/MapControl.cs index 6334c3a..dc5e607 100644 --- a/Visualizer/UI/MapControl.cs +++ b/Visualizer/UI/MapControl.cs @@ -183,7 +183,7 @@ private void DrawMapPolygon(Graphics graphics, MapPolygon mapPolygon) { if (mapPolygon.Polygon != null) { - PointF[] exteriorPoints = ProjectToControl(mapPolygon.Polygon.ExteriorRing.Points); + PointF[] exteriorPoints = ProjectToControl(mapPolygon.Polygon.ExteriorRing?.Points); if (exteriorPoints != null && exteriorPoints.Length > 2) { if (mapPolygon.Brush != null) @@ -197,19 +197,22 @@ private void DrawMapPolygon(Graphics graphics, MapPolygon mapPolygon) } } - foreach (var interiorRing in mapPolygon.Polygon.InteriorRings) + if (mapPolygon.Polygon.InteriorRings != null) { - PointF[] interiorPoints = ProjectToControl(interiorRing.Points); - if (interiorPoints != null && interiorPoints.Length > 2) + foreach (var interiorRing in mapPolygon.Polygon.InteriorRings) { - if (mapPolygon.Brush != null) + PointF[] interiorPoints = ProjectToControl(interiorRing.Points); + if (interiorPoints != null && interiorPoints.Length > 2) { - graphics.FillPolygon(mapPolygon.Brush, interiorPoints); - } + if (mapPolygon.Brush != null) + { + graphics.FillPolygon(mapPolygon.Brush, interiorPoints); + } - if (mapPolygon.Pen != null) - { - graphics.DrawPolygon(mapPolygon.Pen, interiorPoints); + if (mapPolygon.Pen != null) + { + graphics.DrawPolygon(mapPolygon.Pen, interiorPoints); + } } } }