diff --git a/source/addins/ArcMapAddinVisibility/ArcMapAddinVisibility.csproj b/source/addins/ArcMapAddinVisibility/ArcMapAddinVisibility.csproj index 571029a..ab997c4 100644 --- a/source/addins/ArcMapAddinVisibility/ArcMapAddinVisibility.csproj +++ b/source/addins/ArcMapAddinVisibility/ArcMapAddinVisibility.csproj @@ -146,6 +146,9 @@ Config.esriaddinx + + Code + diff --git a/source/addins/ArcMapAddinVisibility/Models/AddInPointObject.cs b/source/addins/ArcMapAddinVisibility/Models/AddInPointObject.cs new file mode 100644 index 0000000..4b05ee4 --- /dev/null +++ b/source/addins/ArcMapAddinVisibility/Models/AddInPointObject.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ArcMapAddinVisibility.Models +{ + public class AddInPointObject + { + private int _id; + + public int ID + { + get { return _id; } + set { _id = value; } + } + private AddInPoint _addInPoint; + + public AddInPoint AddInPoint + { + get { return _addInPoint; } + set { _addInPoint = value; } + } + + } +} diff --git a/source/addins/ArcMapAddinVisibility/ViewModels/LLOSViewModel.cs b/source/addins/ArcMapAddinVisibility/ViewModels/LLOSViewModel.cs index ceb57e5..24456ce 100644 --- a/source/addins/ArcMapAddinVisibility/ViewModels/LLOSViewModel.cs +++ b/source/addins/ArcMapAddinVisibility/ViewModels/LLOSViewModel.cs @@ -36,17 +36,29 @@ public class LLOSViewModel : LOSBaseViewModel { public LLOSViewModel() { - TargetAddInPoints = new ObservableCollection(); - + DisplayProgressBarLLOS = Visibility.Hidden; // commands SubmitCommand = new RelayCommand(OnSubmitCommand); ClearGraphicsVisible = true; + } #region Properties - public ObservableCollection TargetAddInPoints { get; set; } + private Visibility _displayProgressBarLLOS; + public Visibility DisplayProgressBarLLOS + { + get + { + return _displayProgressBarLLOS; + } + set + { + _displayProgressBarLLOS = value; + RaisePropertyChanged(() => DisplayProgressBarLLOS); + } + } #endregion @@ -97,7 +109,11 @@ private void DeleteTargetPoints(List targets) foreach (var obj in targets) { TargetAddInPoints.Remove(obj); + TargetInExtentPoints.Remove(obj); + TargetOutExtentPoints.Remove(obj); } + + ValidateLLOS_LayerSelection(); } internal override void OnDeleteAllPointsCommand(object obj) @@ -111,6 +127,8 @@ internal override void OnDeleteAllPointsCommand(object obj) base.OnDeleteAllPointsCommand(obj); else if (mode == VisibilityLibrary.Properties.Resources.ToolModeTarget) DeleteTargetPoints(TargetAddInPoints.ToList()); + + ValidateLLOS_LayerSelection(); } #endregion @@ -124,16 +142,36 @@ internal override void OnNewMapPointEvent(object obj) var point = obj as IPoint; - if (point == null || !IsValidPoint(point)) - return; - if (ToolMode == MapPointToolMode.Target) + if (point != null && ToolMode == MapPointToolMode.Target) { + if (IsMapClick) + { + if (!(IsValidPoint(point, true))) + { + IsMapClick = false; + return; + } + } + var color = new RgbColorClass() { Red = 255 } as IColor; var guid = AddGraphicToMap(point, color, true, esriSimpleMarkerStyle.esriSMSSquare); var addInPoint = new AddInPoint() { Point = point, GUID = guid }; + bool isValid = IsValidPoint(point, false); + if (!isValid) + { + TargetOutExtentPoints.Insert(0, addInPoint); + } + else + { + TargetInExtentPoints.Insert(0, addInPoint); + } + TargetAddInPoints.Insert(0, addInPoint); + IsMapClick = false; } + + ValidateLLOS_LayerSelection(); } internal override void Reset(bool toolReset) @@ -145,15 +183,17 @@ internal override void Reset(bool toolReset) // reset target points TargetAddInPoints.Clear(); + TargetInExtentPoints.Clear(); + TargetOutExtentPoints.Clear(); } public override bool CanCreateElement { get { - return (!string.IsNullOrWhiteSpace(SelectedSurfaceName) - && ObserverAddInPoints.Any() - && TargetAddInPoints.Any() + return (!string.IsNullOrWhiteSpace(SelectedSurfaceName) + && (ObserverAddInPoints.Any() || LLOS_ObserversInExtent.Any() || LLOS_ObserversOutOfExtent.Any()) + && (TargetAddInPoints.Any() || LLOS_TargetsInExtent.Any() || LLOS_TargetsOutOfExtent.Any()) && TargetOffset.HasValue); } } @@ -173,160 +213,195 @@ internal override void CreateMapElement() IsRunning = true; IPolyline longestLine = new PolylineClass(); + ReadSelectedLayerPoints(); if (!CanCreateElement || ArcMap.Document == null || ArcMap.Document.FocusMap == null || string.IsNullOrWhiteSpace(SelectedSurfaceName)) return; - // take your observer and target points and get lines of sight - var surface = GetSurfaceFromMapByName(ArcMap.Document.FocusMap, SelectedSurfaceName); + if ((LLOS_ObserversInExtent.Any() || ObserverAddInPoints.Any()) + && LLOS_TargetsInExtent.Any() || TargetAddInPoints.Any()) + { + // take your observer and target points and get lines of sight + var observerPoints = new ObservableCollection(LLOS_ObserversInExtent.Select(x => x.AddInPoint).Union(ObserverInExtentPoints)); + var targetPoints = new ObservableCollection(LLOS_TargetsInExtent.Select(x => x.AddInPoint).Union(TargetInExtentPoints)); + var surface = GetSurfaceFromMapByName(ArcMap.Document.FocusMap, SelectedSurfaceName); - if (surface == null) - return; + if (surface == null) + return; - ILayer surfaceLayer = GetLayerFromMapByName(ArcMap.Document.FocusMap, SelectedSurfaceName); + ILayer surfaceLayer = GetLayerFromMapByName(ArcMap.Document.FocusMap, SelectedSurfaceName); - // Issue warning if layer is ImageServerLayer - if (surfaceLayer is IImageServerLayer) - { - MessageBoxResult mbr = MessageBox.Show(VisibilityLibrary.Properties.Resources.MsgLayerIsImageService, - VisibilityLibrary.Properties.Resources.CaptionLayerIsImageService, MessageBoxButton.YesNo); + // Issue warning if layer is ImageServerLayer + if (surfaceLayer is IImageServerLayer) + { + MessageBoxResult mbr = MessageBox.Show(VisibilityLibrary.Properties.Resources.MsgLayerIsImageService, + VisibilityLibrary.Properties.Resources.CaptionLayerIsImageService, MessageBoxButton.YesNo); - if (mbr == MessageBoxResult.No) + if (mbr == MessageBoxResult.No) + { + System.Windows.MessageBox.Show(VisibilityLibrary.Properties.Resources.MsgTryAgain, VisibilityLibrary.Properties.Resources.MsgCalcCancelled); + return; + } + } + + // Determine if selected surface is projected or geographic + var geoDataset = surfaceLayer as IGeoDataset; + if (geoDataset == null) { - System.Windows.MessageBox.Show(VisibilityLibrary.Properties.Resources.MsgTryAgain, VisibilityLibrary.Properties.Resources.MsgCalcCancelled); + System.Windows.MessageBox.Show(VisibilityLibrary.Properties.Resources.MsgTryAgain, VisibilityLibrary.Properties.Resources.CaptionError); return; } - } - - // Determine if selected surface is projected or geographic - var geoDataset = surfaceLayer as IGeoDataset; - if (geoDataset == null) - { - System.Windows.MessageBox.Show(VisibilityLibrary.Properties.Resources.MsgTryAgain, VisibilityLibrary.Properties.Resources.CaptionError); - return; - } - - SelectedSurfaceSpatialRef = geoDataset.SpatialReference; - - if (SelectedSurfaceSpatialRef is IGeographicCoordinateSystem) - { - MessageBox.Show(VisibilityLibrary.Properties.Resources.LLOSUserPrompt, VisibilityLibrary.Properties.Resources.LLOSUserPromptCaption); - return; - } - if (ArcMap.Document.FocusMap.SpatialReference.FactoryCode != geoDataset.SpatialReference.FactoryCode) - { - MessageBox.Show(VisibilityLibrary.Properties.Resources.LOSDataFrameMatch, VisibilityLibrary.Properties.Resources.LOSSpatialReferenceCaption); - return; - } + SelectedSurfaceSpatialRef = geoDataset.SpatialReference; - SelectedSurfaceSpatialRef = geoDataset.SpatialReference; + if (SelectedSurfaceSpatialRef is IGeographicCoordinateSystem) + { + MessageBox.Show(VisibilityLibrary.Properties.Resources.LLOSUserPrompt, VisibilityLibrary.Properties.Resources.LLOSUserPromptCaption); + return; + } - var geoBridge = (IGeoDatabaseBridge2)new GeoDatabaseHelperClass(); + if (ArcMap.Document.FocusMap.SpatialReference.FactoryCode != geoDataset.SpatialReference.FactoryCode) + { + MessageBox.Show(VisibilityLibrary.Properties.Resources.LOSDataFrameMatch, VisibilityLibrary.Properties.Resources.LOSSpatialReferenceCaption); + return; + } - IPoint pointObstruction = null; - IPolyline polyVisible = null; - IPolyline polyInvisible = null; - bool targetIsVisible = false; + SelectedSurfaceSpatialRef = geoDataset.SpatialReference; - double finalObserverOffset = GetOffsetInZUnits(ObserverOffset.Value, surface.ZFactor, OffsetUnitType); - double finalTargetOffset = GetOffsetInZUnits(TargetOffset.Value, surface.ZFactor, OffsetUnitType); + var geoBridge = (IGeoDatabaseBridge2)new GeoDatabaseHelperClass(); - var DictionaryTargetObserverCount = new Dictionary(); + IPoint pointObstruction = null; + IPolyline polyVisible = null; + IPolyline polyInvisible = null; + bool targetIsVisible = false; - foreach (var observerPoint in ObserverAddInPoints) - { - // keep track of visible targets for this observer - var CanSeeAtLeastOneTarget = false; + double finalObserverOffset = GetOffsetInZUnits(ObserverOffset.Value, surface.ZFactor, OffsetUnitType); + double finalTargetOffset = GetOffsetInZUnits(TargetOffset.Value, surface.ZFactor, OffsetUnitType); - var z1 = surface.GetElevation(observerPoint.Point) + finalObserverOffset; + var DictionaryTargetObserverCount = new Dictionary(); - if (double.IsNaN(z1)) + foreach (var observerPoint in observerPoints) { - System.Windows.MessageBox.Show(VisibilityLibrary.Properties.Resources.LLOSPointsOutsideOfSurfaceExtent, VisibilityLibrary.Properties.Resources.MsgCalcCancelled); - return; - } - - foreach (var targetPoint in TargetAddInPoints) - { - var z2 = surface.GetElevation(targetPoint.Point) + finalTargetOffset; + // keep track of visible targets for this observer + var CanSeeAtLeastOneTarget = false; + + var z1 = surface.GetElevation(observerPoint.Point) + finalObserverOffset; - if (double.IsNaN(z2)) + if (double.IsNaN(z1)) { System.Windows.MessageBox.Show(VisibilityLibrary.Properties.Resources.LLOSPointsOutsideOfSurfaceExtent, VisibilityLibrary.Properties.Resources.MsgCalcCancelled); return; } - var fromPoint = new PointClass() { Z = z1, X = observerPoint.Point.X, Y = observerPoint.Point.Y, ZAware = true } as IPoint; - var toPoint = new PointClass() { Z = z2, X = targetPoint.Point.X, Y = targetPoint.Point.Y, ZAware = true } as IPoint; + foreach (var targetPoint in targetPoints) + { + var z2 = surface.GetElevation(targetPoint.Point) + finalTargetOffset; - geoBridge.GetLineOfSight(surface, fromPoint, toPoint, - out pointObstruction, out polyVisible, out polyInvisible, out targetIsVisible, false, false); + if (double.IsNaN(z2)) + { + System.Windows.MessageBox.Show(VisibilityLibrary.Properties.Resources.LLOSPointsOutsideOfSurfaceExtent, VisibilityLibrary.Properties.Resources.MsgCalcCancelled); + return; + } - var pcol = new PolylineClass() as IPointCollection; - pcol.AddPoint(fromPoint); - pcol.AddPoint(toPoint); - IPolyline pcolPolyline = pcol as IPolyline; + var fromPoint = new PointClass() { Z = z1, X = observerPoint.Point.X, Y = observerPoint.Point.Y, ZAware = true } as IPoint; + var toPoint = new PointClass() { Z = z2, X = targetPoint.Point.X, Y = targetPoint.Point.Y, ZAware = true } as IPoint; - longestLine = (longestLine != null && longestLine.Length < pcolPolyline.Length) ? pcolPolyline : longestLine; + geoBridge.GetLineOfSight(surface, fromPoint, toPoint, + out pointObstruction, out polyVisible, out polyInvisible, out targetIsVisible, false, false); - // set the flag if we can see at least one target - if (targetIsVisible) - { - CanSeeAtLeastOneTarget = true; + var pcol = new PolylineClass() as IPointCollection; + pcol.AddPoint(fromPoint); + pcol.AddPoint(toPoint); + IPolyline pcolPolyline = pcol as IPolyline; - // update target observer count - UpdateTargetObserverCount(DictionaryTargetObserverCount, targetPoint.Point); - } + longestLine = (longestLine != null && longestLine.Length < pcolPolyline.Length) ? pcolPolyline : longestLine; - // First Add "SightLine" so it appears behind others - // Black = Not visible -or- White = Visible - if (targetIsVisible) - AddGraphicToMap(pcolPolyline, new RgbColorClass() { RGB = 0xFFFFFF }, false, - size: 6); // white line - else - AddGraphicToMap(pcolPolyline, new RgbColorClass() { RGB = 0x000000 }, false, - size: 6); // black line + // set the flag if we can see at least one target + if (targetIsVisible) + { + CanSeeAtLeastOneTarget = true; - if (polyVisible != null) - { - AddGraphicToMap(polyVisible, new RgbColorClass() { Green = 255 }, size: 5); + // update target observer count + UpdateTargetObserverCount(DictionaryTargetObserverCount, targetPoint.Point); + } + + // First Add "SightLine" so it appears behind others + // Black = Not visible -or- White = Visible + if (targetIsVisible) + AddGraphicToMap(pcolPolyline, new RgbColorClass() { RGB = 0xFFFFFF }, false, + size: 6); // white line + else + AddGraphicToMap(pcolPolyline, new RgbColorClass() { RGB = 0x000000 }, false, + size: 6); // black line + + if (polyVisible != null) + { + AddGraphicToMap(polyVisible, new RgbColorClass() { Green = 255 }, size: 5); + } + + if (polyInvisible != null) + { + AddGraphicToMap(polyInvisible, new RgbColorClass() { Red = 255 }, size: 3); + } + + if (polyVisible == null && polyInvisible == null) + { + if (targetIsVisible) + AddGraphicToMap(pcol as IPolyline, new RgbColorClass() { Green = 255 }, size: 3); + else + AddGraphicToMap(pcol as IPolyline, new RgbColorClass() { Red = 255 }, size: 3); + } } - if (polyInvisible != null) + // visualize observer + + // add blue dot + AddGraphicToMap(observerPoint.Point, new RgbColorClass() { Blue = 255 }, size: 10); + + if (CanSeeAtLeastOneTarget) { - AddGraphicToMap(polyInvisible, new RgbColorClass() { Red = 255 }, size: 3); + // add green dot + AddGraphicToMap(observerPoint.Point, new RgbColorClass() { Green = 255 }); } - - if (polyVisible == null && polyInvisible == null) - { - if (targetIsVisible) - AddGraphicToMap(pcol as IPolyline, new RgbColorClass() { Green = 255 }, size: 3); - else - AddGraphicToMap(pcol as IPolyline, new RgbColorClass() { Red = 255 }, size: 3); + else + { + // add red dot + AddGraphicToMap(observerPoint.Point, new RgbColorClass() { Red = 255 }); } } - // visualize observer + VisualizeTargets(DictionaryTargetObserverCount, targetPoints); + + if ((ObserverInExtentPoints.Any() || LLOS_ObserversInExtent.Any()) + && (TargetInExtentPoints.Any() || LLOS_TargetsInExtent.Any())) + { + ZoomToExtent(longestLine); + } - // add blue dot - AddGraphicToMap(observerPoint.Point, new RgbColorClass() { Blue = 255 }, size: 10); + DisplayOutOfExtentMsg(); - if (CanSeeAtLeastOneTarget) + //display points present out of extent + var colorObserver = new RgbColorClass() { Blue = 255 }; + var colorTarget = new RgbColorClass() { Red = 255 }; + var colorObserverBorder = new RgbColorClass() { Red = 255, Blue = 255, Green = 255 }; + var colorTargetBorder = new RgbColorClass() { Red = 0, Blue = 0, Green = 0 }; + var observerOutOfExtent = new ObservableCollection(LLOS_ObserversOutOfExtent.Select(x => x.AddInPoint).Union(ObserverOutExtentPoints)); + foreach (var point in observerOutOfExtent) { - // add green dot - AddGraphicToMap(observerPoint.Point, new RgbColorClass() { Green = 255 }); + AddGraphicToMap(point.Point, colorObserver, markerStyle: esriSimpleMarkerStyle.esriSMSX, size: 10, borderColor: colorObserverBorder); } - else + var targetOutOfExtent = new ObservableCollection(LLOS_TargetsOutOfExtent.Select(x => x.AddInPoint).Union(TargetOutExtentPoints)); + foreach (var point in targetOutOfExtent) { - // add red dot - AddGraphicToMap(observerPoint.Point, new RgbColorClass() { Red = 255 }); + AddGraphicToMap(point.Point, colorTarget, markerStyle: esriSimpleMarkerStyle.esriSMSX, size: 10, borderColor: colorTargetBorder); } - } - VisualizeTargets(DictionaryTargetObserverCount); - ZoomToExtent(longestLine); + } + else + { + System.Windows.MessageBox.Show(VisibilityLibrary.Properties.Resources.OutOfExtentMsg, VisibilityLibrary.Properties.Resources.OutOfExtentHeader); + } } - catch(Exception ex) + catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.Message); System.Windows.Forms.MessageBox.Show(VisibilityLibrary.Properties.Resources.ExceptionSomethingWentWrong, @@ -335,13 +410,62 @@ internal override void CreateMapElement() finally { IsRunning = false; + ClearLLOSCollections(); + ValidateLLOS_LayerSelection(); + } + } + + private void DisplayOutOfExtentMsg() + { + var observerIDCollection = LLOS_ObserversOutOfExtent.Select(x => x.ID).ToList(); + var targetIDCollection = LLOS_TargetsOutOfExtent.Select(x => x.ID).ToList(); + var observerString = string.Empty; + var targetString = string.Empty; + foreach (var item in observerIDCollection) + { + if (observerString == "") + observerString = item.ToString(); + else + observerString = observerString + "," + item.ToString(); + } + foreach (var item in targetIDCollection) + { + if (targetString == "") + targetString = item.ToString(); + else + targetString = targetString + "," + item.ToString(); + } + if (observerIDCollection.Any() || targetIDCollection.Any()) + { + if ((observerIDCollection.Count + targetIDCollection.Count) <= 10) + { + var msgString = string.Empty; + if (observerIDCollection.Any()) + { + msgString = "Observers lying outside the extent of elevation surface are: " + observerString; + } + if (targetIDCollection.Any()) + { + if (msgString != "") + msgString = msgString + "\n"; + msgString = msgString + "Targets lying outside the extent of elevation surface are: " + targetString; + } + System.Windows.MessageBox.Show(msgString, + "Unable To Process For Few Locations"); + } + else + { + System.Windows.MessageBox.Show(VisibilityLibrary.Properties.Resources.LLOSPointsOutsideOfSurfaceExtent, + VisibilityLibrary.Properties.Resources.MsgCalcCancelled); + } + } } - private void VisualizeTargets(Dictionary dict) + private void VisualizeTargets(Dictionary dict, ObservableCollection targetPoints) { // visualize targets - foreach (var targetPoint in TargetAddInPoints) + foreach (var targetPoint in targetPoints) { if (dict.ContainsKey(targetPoint.Point)) { @@ -373,12 +497,38 @@ private void UpdateTargetObserverCount(Dictionary dict, IPoint targ internal override void OnDisplayCoordinateTypeChanged(object obj) { var list = TargetAddInPoints.ToList(); + var inExtentList = TargetInExtentPoints.ToList(); + var outExtentList = TargetOutExtentPoints.ToList(); + TargetAddInPoints.Clear(); + TargetInExtentPoints.Clear(); + TargetOutExtentPoints.Clear(); + foreach (var item in list) TargetAddInPoints.Add(item); + foreach (var item in inExtentList) + TargetInExtentPoints.Add(item); + + foreach (var item in outExtentList) + TargetOutExtentPoints.Add(item); + // and update observers base.OnDisplayCoordinateTypeChanged(obj); } + + private void ReadSelectedLayerPoints() + { + LLOS_ObserversInExtent.Clear(); + LLOS_ObserversOutOfExtent.Clear(); + LLOS_TargetsInExtent.Clear(); + LLOS_TargetsOutOfExtent.Clear(); + + var observerColor = new RgbColor() { Blue = 255 } as IColor; + ReadSelectedLyrPoints(LLOS_ObserversInExtent, LLOS_ObserversOutOfExtent, SelectedLLOS_ObserverLyrName, observerColor); + + var targetColor = new RgbColor() { Red = 255 } as IColor; + ReadSelectedLyrPoints(LLOS_TargetsInExtent, LLOS_TargetsOutOfExtent, SelectedLLOS_TargetLyrName, observerColor); + } } } diff --git a/source/addins/ArcMapAddinVisibility/ViewModels/LOSBaseViewModel.cs b/source/addins/ArcMapAddinVisibility/ViewModels/LOSBaseViewModel.cs index bd9ab39..9656ed6 100644 --- a/source/addins/ArcMapAddinVisibility/ViewModels/LOSBaseViewModel.cs +++ b/source/addins/ArcMapAddinVisibility/ViewModels/LOSBaseViewModel.cs @@ -1,4 +1,4 @@ -// Copyright 2016 Esri +// Copyright 2016 Esri // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,21 +12,27 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; -using System.Collections.Generic; -using System.Linq; -using System.Collections.ObjectModel; -using System.Collections; +using ArcMapAddinVisibility.Models; +using CoordinateConversionLibrary.Models; +using ESRI.ArcGIS.Analyst3D; using ESRI.ArcGIS.Carto; +using ESRI.ArcGIS.Display; using ESRI.ArcGIS.Geodatabase; -using ESRI.ArcGIS.Analyst3D; using ESRI.ArcGIS.Geometry; -using ESRI.ArcGIS.Display; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Windows; +using System.Windows.Threading; using VisibilityLibrary; using VisibilityLibrary.Helpers; -using VisibilityLibrary.Views; using VisibilityLibrary.ViewModels; -using ArcMapAddinVisibility.Models; +using VisibilityLibrary.Views; namespace ArcMapAddinVisibility.ViewModels { @@ -37,19 +43,40 @@ public LOSBaseViewModel() ObserverOffset = 2.0; TargetOffset = 0.0; OffsetUnitType = DistanceTypes.Meters; + DistanceUnitType = DistanceTypes.Meters; AngularUnitType = AngularTypes.DEGREES; ObserverAddInPoints = new ObservableCollection(); + ObserverInExtentPoints = new ObservableCollection(); + ObserverOutExtentPoints = new ObservableCollection(); + TargetAddInPoints = new ObservableCollection(); + TargetInExtentPoints = new ObservableCollection(); + TargetOutExtentPoints = new ObservableCollection(); + LLOS_ObserversInExtent = new ObservableCollection(); + LLOS_ObserversOutOfExtent = new ObservableCollection(); + LLOS_TargetsInExtent = new ObservableCollection(); + LLOS_TargetsOutOfExtent = new ObservableCollection(); + RLOS_ObserversInExtent = new ObservableCollection(); + RLOS_ObserversOutOfExtent = new ObservableCollection(); + EnterManullyOption = VisibilityLibrary.Properties.Resources.EnterManuallyOption; toolMode = MapPointToolMode.Unknown; SurfaceLayerNames = new ObservableCollection(); + LLOS_ObserverLyrNames = new ObservableCollection(); + LLOS_TargetLyrNames = new ObservableCollection(); + RLOS_ObserverLyrNames = new ObservableCollection(); SelectedSurfaceName = string.Empty; + SelectedLLOS_ObserverLyrName = string.Empty; + SelectedLLOS_TargetLyrName = string.Empty; + SelectedRLOS_ObserverLyrName = string.Empty; Mediator.Register(Constants.MAP_TOC_UPDATED, OnMapTocUpdated); Mediator.Register(Constants.DISPLAY_COORDINATE_TYPE_CHANGED, OnDisplayCoordinateTypeChanged); DeletePointCommand = new RelayCommand(OnDeletePointCommand); DeleteAllPointsCommand = new RelayCommand(OnDeleteAllPointsCommand); + PasteCoordinatesCommand = new RelayCommand(OnPasteCommand); + ImportCSVFileCommand = new RelayCommand(OnImportCSVFileCommand); EditPropertiesDialogCommand = new RelayCommand(OnEditPropertiesDialogCommand); } @@ -101,6 +128,7 @@ public double? ObserverOffset throw new ArgumentException(VisibilityLibrary.Properties.Resources.AEInvalidInput); } } + private double? targetOffset; public double? TargetOffset { @@ -142,12 +170,103 @@ public MapPointToolMode ToolMode } } + private string _selectedLLOS_TargetLyrName; + public string SelectedLLOS_TargetLyrName + { + get + { + return _selectedLLOS_TargetLyrName; + } + set + { + _selectedLLOS_TargetLyrName = value; + ValidateLLOS_LayerSelection(); + RaisePropertyChanged(() => SelectedLLOS_TargetLyrName); + } + } + + private string _selectedLLOS_ObserverLyrName; + public string SelectedLLOS_ObserverLyrName + { + get + { + return _selectedLLOS_ObserverLyrName; + } + set + { + _selectedLLOS_ObserverLyrName = value; + ValidateLLOS_LayerSelection(); + RaisePropertyChanged(() => SelectedLLOS_ObserverLyrName); + } + } + + private string _selectedRLOS_ObserverLyrName; + public string SelectedRLOS_ObserverLyrName + { + get + { + return _selectedRLOS_ObserverLyrName; + } + set + { + _selectedRLOS_ObserverLyrName = value; + ValidateRLOS_LayerSelection(); + RaisePropertyChanged(() => SelectedRLOS_ObserverLyrName); + } + } + + public ObservableCollection LLOS_ObserverLyrNames { get; set; } + public ObservableCollection LLOS_TargetLyrNames { get; set; } + public ObservableCollection RLOS_ObserverLyrNames { get; set; } + + private bool _isLLOSValidSelection { get; set; } + public bool IsLLOSValidSelection + { + get + { + return _isLLOSValidSelection; + } + set + { + _isLLOSValidSelection = value; + RaisePropertyChanged(() => IsLLOSValidSelection); + } + } + + private bool _isRLOSValidSelection { get; set; } + public bool IsRLOSValidSelection + { + get + { + return _isRLOSValidSelection; + } + set + { + _isRLOSValidSelection = value; + RaisePropertyChanged(() => IsRLOSValidSelection); + } + } + + public string EnterManullyOption { get; set; } + public ObservableCollection LLOS_ObserversInExtent { get; set; } + public ObservableCollection LLOS_ObserversOutOfExtent { get; set; } + public ObservableCollection LLOS_TargetsInExtent { get; set; } + public ObservableCollection LLOS_TargetsOutOfExtent { get; set; } + public ObservableCollection RLOS_ObserversInExtent { get; set; } + public ObservableCollection RLOS_ObserversOutOfExtent { get; set; } + public ObservableCollection ObserverAddInPoints { get; set; } + public ObservableCollection ObserverInExtentPoints { get; set; } + public ObservableCollection ObserverOutExtentPoints { get; set; } + public ObservableCollection TargetAddInPoints { get; set; } + public ObservableCollection TargetInExtentPoints { get; set; } + public ObservableCollection TargetOutExtentPoints { get; set; } public ObservableCollection SurfaceLayerNames { get; set; } public string SelectedSurfaceName { get; set; } public DistanceTypes OffsetUnitType { get; set; } + public DistanceTypes DistanceUnitType { get; set; } public AngularTypes AngularUnitType { get; set; } - + #endregion #region Commands @@ -155,6 +274,8 @@ public MapPointToolMode ToolMode public RelayCommand DeletePointCommand { get; set; } public RelayCommand DeleteAllPointsCommand { get; set; } public RelayCommand EditPropertiesDialogCommand { get; set; } + public RelayCommand PasteCoordinatesCommand { get; set; } + public RelayCommand ImportCSVFileCommand { get; set; } /// /// Command method to delete points @@ -189,6 +310,7 @@ private void OnEditPropertiesDialogCommand(object obj) dlg.ShowDialog(); } + private void DeletePoints(List observers) { if (observers == null || !observers.Any()) @@ -201,6 +323,148 @@ private void DeletePoints(List observers) foreach (var point in observers) { ObserverAddInPoints.Remove(point); + ObserverInExtentPoints.Remove(point); + ObserverOutExtentPoints.Remove(point); + } + } + + /// + /// Command method to import points from csv file. + /// + /// + public virtual void OnImportCSVFileCommand(object obj) + { + var mode = obj.ToString(); + CoordinateConversionLibraryConfig.AddInConfig.DisplayAmbiguousCoordsDlg = false; + + var fileDialog = new Microsoft.Win32.OpenFileDialog(); + fileDialog.CheckFileExists = true; + fileDialog.CheckPathExists = true; + fileDialog.Filter = "csv files|*.csv"; + + // attemp to import + var fieldVM = new CoordinateConversionLibrary.ViewModels.SelectCoordinateFieldsViewModel(); + var result = fileDialog.ShowDialog(); + if (result.HasValue && result.Value == true) + { + var dlg = new CoordinateConversionLibrary.Views.SelectCoordinateFieldsView(); + using (Stream s = new FileStream(fileDialog.FileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + { + var headers = CoordinateConversionLibrary.Helpers.ImportCSV.GetHeaders(s); + if (headers != null) + { + foreach (var header in headers) + { + fieldVM.AvailableFields.Add(header); + System.Diagnostics.Debug.WriteLine("header : {0}", header); + } + dlg.DataContext = fieldVM; + } + else + { + System.Windows.Forms.MessageBox.Show(VisibilityLibrary.Properties.Resources.MsgNoDataFound); + return; + } + } + if (dlg.ShowDialog() == true) + { + using (Stream s = new FileStream(fileDialog.FileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + { + var lists = CoordinateConversionLibrary.Helpers.ImportCSV.Import(s, fieldVM.SelectedFields.ToArray()); + + foreach (var item in lists) + { + string outFormattedString = string.Empty; + var sb = new StringBuilder(); + sb.Append(item.lat.Trim()); + if (fieldVM.UseTwoFields) + sb.Append(string.Format(" {0}", item.lon.Trim())); + + string coordinate = sb.ToString(); + CoordinateConversionLibrary.Models.CoordinateType ccType = CoordinateConversionLibrary.Helpers.ConversionUtils.GetCoordinateString(coordinate, out outFormattedString); + if (ccType == CoordinateConversionLibrary.Models.CoordinateType.Unknown) + { + Regex regexMercator = new Regex(@"^(?\-?\d+\.?\d*)[+,;:\s]*(?\-?\d+\.?\d*)"); + var matchMercator = regexMercator.Match(coordinate); + if (matchMercator.Success && matchMercator.Length == coordinate.Length) + { + ccType = CoordinateType.DD; + } + } + IPoint point = (ccType != CoordinateConversionLibrary.Models.CoordinateType.Unknown) ? GetPointFromString(outFormattedString) : null; + if (point != null) + { + if (mode == VisibilityLibrary.Properties.Resources.ToolModeObserver) + { + ToolMode = MapPointToolMode.Observer; + Point1 = point; + if ((ArcMap.Document != null) && (ArcMap.Document.FocusMap != null)) + point.Project(ArcMap.Document.FocusMap.SpatialReference); + OnNewMapPointEvent(Point1); + } + else if (mode == VisibilityLibrary.Properties.Resources.ToolModeTarget) + { + ToolMode = MapPointToolMode.Target; + Point2 = point; + if ((ArcMap.Document != null) && (ArcMap.Document.FocusMap != null)) + point.Project(ArcMap.Document.FocusMap.SpatialReference); + OnNewMapPointEvent(Point2); + } + } + } + } + } + } + } + + /// + /// Command method to paste points from clipboard. + /// + /// + internal virtual void OnPasteCommand(object obj) + { + var mode = obj.ToString(); + + if (string.IsNullOrWhiteSpace(mode)) + return; + + var input = Clipboard.GetText().Trim(); + string[] lines = input.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None); + var coordinates = new List(); + foreach (var item in lines) + { + string outFormattedString = string.Empty; + string coordinate = item.Trim().ToString(); + CoordinateConversionLibrary.Models.CoordinateType ccType = CoordinateConversionLibrary.Helpers.ConversionUtils.GetCoordinateString(coordinate, out outFormattedString); + if (ccType == CoordinateConversionLibrary.Models.CoordinateType.Unknown) + { + Regex regexMercator = new Regex(@"^(?\-?\d+\.?\d*)[+,;:\s]*(?\-?\d+\.?\d*)"); + var matchMercator = regexMercator.Match(coordinate); + if (matchMercator.Success && matchMercator.Length == coordinate.Length) + { + ccType = CoordinateType.DD; + } + } + IPoint point = (ccType != CoordinateConversionLibrary.Models.CoordinateType.Unknown) ? GetPointFromString(outFormattedString) : null; + if (point != null) + { + if (mode == VisibilityLibrary.Properties.Resources.ToolModeObserver) + { + ToolMode = MapPointToolMode.Observer; + Point1 = point; + if ((ArcMap.Document != null) && (ArcMap.Document.FocusMap != null)) + point.Project(ArcMap.Document.FocusMap.SpatialReference); + OnNewMapPointEvent(Point1); + } + else if (mode == VisibilityLibrary.Properties.Resources.ToolModeTarget) + { + ToolMode = MapPointToolMode.Target; + Point2 = point; + if ((ArcMap.Document != null) && (ArcMap.Document.FocusMap != null)) + point.Project(ArcMap.Document.FocusMap.SpatialReference); + OnNewMapPointEvent(Point2); + } + } } } @@ -267,23 +531,41 @@ internal override void OnNewMapPointEvent(object obj) if (!IsActiveTab) return; - var point = obj as IPoint; - - if (point == null || !IsValidPoint(point, true)) - return; + var point = obj as IPoint; // ok, we have a point if (ToolMode == MapPointToolMode.Observer) { + if (IsMapClick) + { + if (!(IsValidPoint(point, true))) + { + IsMapClick = false; + return; + } + } // in tool mode "Observer" we add observer points // otherwise ignore - + var color = new RgbColorClass() { Blue = 255 } as IColor; var guid = AddGraphicToMap(point, color, true); var addInPoint = new AddInPoint() { Point = point, GUID = guid }; + bool isValid = IsValidPoint(point, false); + if (!isValid) + { + + ObserverOutExtentPoints.Insert(0, addInPoint); + } + else + { + ObserverInExtentPoints.Insert(0, addInPoint); + } + ObserverAddInPoints.Insert(0, addInPoint); + IsMapClick = false; } } + internal override void OnMouseMoveEvent(object obj) { if (!IsActiveTab) @@ -294,17 +576,18 @@ internal override void OnMouseMoveEvent(object obj) if (point == null) return; - if(ToolMode == MapPointToolMode.Observer) + if (ToolMode == MapPointToolMode.Observer) { Point1Formatted = string.Empty; Point1 = point; } - else if(ToolMode == MapPointToolMode.Target) + else if (ToolMode == MapPointToolMode.Target) { Point2Formatted = string.Empty; Point2 = point; } } + /// /// Handler for "Enter" key press /// If pressed when input textbox for observer or target is focused @@ -316,13 +599,19 @@ internal override void OnEnterKeyCommand(object obj) { var keyCommandMode = obj as string; - if(keyCommandMode == VisibilityLibrary.Properties.Resources.ToolModeObserver) + if (keyCommandMode == VisibilityLibrary.Properties.Resources.ToolModeObserver) { + if (!IsValidPoint(Point1, true)) + return; + ToolMode = MapPointToolMode.Observer; OnNewMapPointEvent(Point1); } else if (keyCommandMode == VisibilityLibrary.Properties.Resources.ToolModeTarget) { + if (!IsValidPoint(Point2, true)) + return; + ToolMode = MapPointToolMode.Target; OnNewMapPointEvent(Point2); } @@ -332,6 +621,7 @@ internal override void OnEnterKeyCommand(object obj) base.OnEnterKeyCommand(obj); } } + /// /// Method to check to see point is withing the currently selected surface /// returns true if there is no surface selected or point is contained by layer AOI @@ -452,7 +742,7 @@ public ISurface GetSurfaceFromMapByName(IMap map, string name) var mosaicLayer = layer as IMosaicLayer; var rasterLayer = layer as IRasterLayer; - if ((mosaicLayer != null) && (mosaicLayer.PreviewLayer != null) && + if ((mosaicLayer != null) && (mosaicLayer.PreviewLayer != null) && (mosaicLayer.PreviewLayer.Raster != null)) { rasterSurface.PutRaster(mosaicLayer.PreviewLayer.Raster, 0); @@ -520,7 +810,7 @@ public List GetSurfaceNamesFromMap(IMap map, bool IncludeTinLayers = fal var layer = layers.Next(); - while(layer != null) + while (layer != null) { try { @@ -595,12 +885,14 @@ internal override void Reset(bool toolReset) // reset observer points ObserverAddInPoints.Clear(); + ObserverInExtentPoints.Clear(); + ObserverOutExtentPoints.Clear(); ClearTempGraphics(); } /// - /// Method used to reset the currently selected surfacename + /// Method used to reset the currently selected surfacename /// Use when toc items or map changes, on tab selection changed, etc /// /// IMap @@ -621,9 +913,65 @@ internal void ResetSurfaceNames(IMap map) else SelectedSurfaceName = string.Empty; + ResetLayerNames(map); + RaisePropertyChanged(() => SelectedSurfaceName); + RaisePropertyChanged(() => SelectedLLOS_ObserverLyrName); + RaisePropertyChanged(() => SelectedLLOS_TargetLyrName); + RaisePropertyChanged(() => SelectedRLOS_ObserverLyrName); + } + + private void ResetLayerNames(IMap map) + { + var layerNames = new ObservableCollection(); + Dispatcher.CurrentDispatcher.Invoke(() => + { + layerNames = GetLayerNames(map); + }); + + var tempSelectedLLOS_Observer = SelectedLLOS_ObserverLyrName; + var tempSelectedLLOS_Target = SelectedLLOS_TargetLyrName; + var tempSelectedRLOS_Observer = SelectedRLOS_ObserverLyrName; + + + Dispatcher.CurrentDispatcher.Invoke(() => + { + ResetLayerCollectionNames(layerNames); + }); + Dispatcher.CurrentDispatcher.Invoke(() => + { + ResetSelectedLyrName(tempSelectedLLOS_Observer, tempSelectedLLOS_Target, tempSelectedRLOS_Observer); + }); + } + private void ResetSelectedLyrName(string tempSelectedLLOS_Observer, string tempSelectedLLOS_Target, string tempSelectedRLOS_Observer) + { + if (SurfaceLayerNames.Contains(tempSelectedLLOS_Observer)) + SelectedLLOS_ObserverLyrName = tempSelectedLLOS_Observer; + else if (SurfaceLayerNames.Any()) + SelectedLLOS_ObserverLyrName = LLOS_ObserverLyrNames[0]; + else + SelectedLLOS_ObserverLyrName = string.Empty; + + + if (SurfaceLayerNames.Contains(tempSelectedLLOS_Target)) + SelectedLLOS_TargetLyrName = tempSelectedLLOS_Target; + else if (SurfaceLayerNames.Any()) + SelectedLLOS_TargetLyrName = LLOS_TargetLyrNames[0]; + else + SelectedLLOS_TargetLyrName = string.Empty; + + if (SurfaceLayerNames.Contains(tempSelectedRLOS_Observer)) + SelectedRLOS_ObserverLyrName = tempSelectedRLOS_Observer; + else if (SurfaceLayerNames.Any()) + SelectedRLOS_ObserverLyrName = RLOS_ObserverLyrNames[0]; + else + SelectedRLOS_ObserverLyrName = string.Empty; + } + + + /// /// Method to handle the display coordinate type change /// Need to update the list boxes @@ -632,10 +980,175 @@ internal void ResetSurfaceNames(IMap map) internal virtual void OnDisplayCoordinateTypeChanged(object obj) { var list = ObserverAddInPoints.ToList(); + var inExtentList = ObserverInExtentPoints.ToList(); + var outExtentList = ObserverOutExtentPoints.ToList(); + ObserverAddInPoints.Clear(); + ObserverInExtentPoints.Clear(); + ObserverOutExtentPoints.Clear(); + foreach (var item in list) ObserverAddInPoints.Add(item); + + foreach (var item in inExtentList) + ObserverInExtentPoints.Add(item); + + foreach (var item in outExtentList) + ObserverOutExtentPoints.Add(item); RaisePropertyChanged(() => HasMapGraphics); } + + private void ResetLayerCollectionNames(ObservableCollection layerNames) + { + LLOS_ObserverLyrNames.Clear(); + LLOS_TargetLyrNames.Clear(); + RLOS_ObserverLyrNames.Clear(); + + if (!LLOS_ObserverLyrNames.Contains(EnterManullyOption)) + { + LLOS_ObserverLyrNames.Add(EnterManullyOption); + LLOS_TargetLyrNames.Add(EnterManullyOption); + RLOS_ObserverLyrNames.Add(EnterManullyOption); + } + + foreach (var layerName in layerNames) + { + if (!LLOS_ObserverLyrNames.Contains(layerName)) + { + LLOS_ObserverLyrNames.Add(layerName); + LLOS_TargetLyrNames.Add(layerName); + RLOS_ObserverLyrNames.Add(layerName); + } + } + } + + private ObservableCollection GetLayerNames(IMap map) + { + var layerNames = new ObservableCollection(); + + if (map == null) + return layerNames; + + var layers = map.get_Layers(); + + if (layers == null) + return layerNames; + var layer = layers.Next(); + while (layer != null) + { + var lyr = layer as FeatureClass; + if (lyr != null && lyr.Type == esriDatasetType.esriDTFeatureClass) + { + IFeatureLayer FLayer = (IFeatureLayer)lyr; + var geomertyType = FLayer.FeatureClass.ShapeType; + if (geomertyType == esriGeometryType.esriGeometryPoint) + layerNames.Add(layer.Name); + } + layer = layers.Next(); + } + return layerNames; + } + + internal void ValidateLLOS_LayerSelection() + { + if (SelectedLLOS_ObserverLyrName == EnterManullyOption) + { + LLOS_ObserversInExtent.Clear(); + LLOS_ObserversOutOfExtent.Clear(); + } + if (SelectedLLOS_TargetLyrName == EnterManullyOption) + { + LLOS_TargetsInExtent.Clear(); + LLOS_TargetsOutOfExtent.Clear(); + } + + IsLLOSValidSelection = ( + ((SelectedLLOS_ObserverLyrName == EnterManullyOption || string.IsNullOrWhiteSpace(SelectedLLOS_ObserverLyrName)) + && LLOS_ObserversInExtent.Count == 0 && LLOS_ObserversOutOfExtent.Count == 0 && ObserverAddInPoints.Count == 0) + || + ((SelectedLLOS_TargetLyrName == EnterManullyOption || string.IsNullOrWhiteSpace(SelectedLLOS_TargetLyrName)) + && LLOS_TargetsInExtent.Count == 0 && LLOS_TargetsOutOfExtent.Count == 0 && TargetAddInPoints.Count == 0) + ) ? false : true; + } + + internal void ValidateRLOS_LayerSelection() + { + IsRLOSValidSelection = + ((SelectedRLOS_ObserverLyrName == EnterManullyOption || string.IsNullOrWhiteSpace(SelectedRLOS_ObserverLyrName)) + && RLOS_ObserversInExtent.Count == 0 && RLOS_ObserversOutOfExtent.Count == 0) ? false : true; + } + + internal void ReadSelectedLyrPoints(ObservableCollection inExtentPoints, ObservableCollection outOfExtentPoints, string selectedLyrName, IColor color) + { + var map = ArcMap.Document.FocusMap; + if (map == null) + return; + var layers = map.get_Layers(); + if (layers == null) + return; + var layer = layers.Next(); + while (layer != null) + { + if (layer.Name == selectedLyrName) + { + IFeature feature = null; + IFeatureLayer FLayer = (IFeatureLayer)layer; + var cursor = FLayer.FeatureClass.Search(null, false); + var surface = GetSurfaceFromMapByName(ArcMap.Document.FocusMap, SelectedSurfaceName); + double finalObserverOffset = GetOffsetInZUnits(ObserverOffset.Value, surface.ZFactor, OffsetUnitType); + var selectedFeaturesCollections = GetSelectedFeaturesCollections(layer); + while ((feature = cursor.NextFeature()) != null) + { + var value = feature.get_Value(FLayer.FeatureClass.FindField("Shape")); + var point = (IPoint)value; + var guid = AddGraphicToMap(point, color, true, esriSimpleMarkerStyle.esriSMSSquare); + var objectId = FLayer.FeatureClass.FindField("ObjectId"); + var FID = FLayer.FeatureClass.FindField("FID"); + var idIndex = objectId != -1 ? objectId : FID; + var id = Convert.ToInt32(feature.get_Value(idIndex)); + var z1 = surface.GetElevation(point) + finalObserverOffset; + var addInPoint = new AddInPoint() { Point = point, GUID = guid }; + if (selectedFeaturesCollections == null || !selectedFeaturesCollections.Any() || + (selectedFeaturesCollections.Any() && selectedFeaturesCollections.Where(x => x == id).Any())) + { + if (double.IsNaN(z1)) + outOfExtentPoints.Add(new AddInPointObject() { AddInPoint = addInPoint, ID = id }); + else + inExtentPoints.Add(new AddInPointObject() { AddInPoint = addInPoint, ID = id }); + } + } + } + layer = layers.Next(); + } + } + + private static List GetSelectedFeaturesCollections(ILayer layer) + { + var selectedFeatureCollections = new List(); + var selectedFeature = ((IFeatureSelection)layer).SelectionSet; + var enumFeature = ((IEnumIDs)(((ISelectionSet)(selectedFeature)).IDs)); + enumFeature.Reset(); + int selfeature = enumFeature.Next(); + while (selfeature != -1) + { + selectedFeatureCollections.Add(selfeature); + selfeature = enumFeature.Next(); + } + return selectedFeatureCollections; + } + + internal void ClearLLOSCollections() + { + LLOS_TargetsInExtent.Clear(); + LLOS_TargetsOutOfExtent.Clear(); + LLOS_ObserversInExtent.Clear(); + LLOS_ObserversOutOfExtent.Clear(); + } + + internal void ClearRLOSCollections() + { + RLOS_ObserversInExtent.Clear(); + RLOS_ObserversOutOfExtent.Clear(); + } } -} +} \ No newline at end of file diff --git a/source/addins/ArcMapAddinVisibility/ViewModels/RLOSViewModel.cs b/source/addins/ArcMapAddinVisibility/ViewModels/RLOSViewModel.cs index d277fa9..35bbe2e 100644 --- a/source/addins/ArcMapAddinVisibility/ViewModels/RLOSViewModel.cs +++ b/source/addins/ArcMapAddinVisibility/ViewModels/RLOSViewModel.cs @@ -32,6 +32,8 @@ // Solution using VisibilityLibrary.Helpers; using VisibilityLibrary; +using System.Collections.ObjectModel; +using ArcMapAddinVisibility.Models; namespace ArcMapAddinVisibility.ViewModels { @@ -215,11 +217,13 @@ public RLOSViewModel() internal override void OnDeletePointCommand(object obj) { base.OnDeletePointCommand(obj); + ValidateRLOS_LayerSelection(); } internal override void OnDeleteAllPointsCommand(object obj) { base.OnDeleteAllPointsCommand(obj); + ValidateRLOS_LayerSelection(); } public override bool CanCreateElement @@ -227,7 +231,7 @@ public override bool CanCreateElement get { return (!string.IsNullOrWhiteSpace(SelectedSurfaceName) - && ObserverAddInPoints.Any()); + && (ObserverAddInPoints.Any() || RLOS_ObserversInExtent.Any() || RLOS_ObserversOutOfExtent.Any())); } } @@ -344,252 +348,271 @@ internal override void CreateMapElement() try { IsRunning = true; - - if (!CanCreateElement || ArcMap.Document == null || ArcMap.Document.FocusMap == null + var selectedLayer = SelectedRLOS_ObserverLyrName; + ReadSelectedLayerPoints(); + if (!CanCreateElement || ArcMap.Document == null || ArcMap.Document.FocusMap == null || string.IsNullOrWhiteSpace(SelectedSurfaceName)) return; - - var surface = GetSurfaceFromMapByName(ArcMap.Document.FocusMap, SelectedSurfaceName); - if (surface == null) + if (RLOS_ObserversInExtent.Any() || ObserverAddInPoints.Any()) { - System.Windows.MessageBox.Show(VisibilityLibrary.Properties.Resources.MsgTryAgain, VisibilityLibrary.Properties.Resources.CaptionError); - return; - } - bool spatialAnalystAvailable = IsSpatialAnalystAvailable(); - if (!spatialAnalystAvailable) - { - System.Windows.MessageBox.Show(VisibilityLibrary.Properties.Resources.LOSSpatialAnalystLicenseInvalid, VisibilityLibrary.Properties.Resources.MsgCalcCancelled); - return; - } - - ILayer surfaceLayer = GetLayerFromMapByName(ArcMap.Document.FocusMap, SelectedSurfaceName); - // Issue warning if layer is ImageServerLayer - if (surfaceLayer is IImageServerLayer) - { - MessageBoxResult mbr = MessageBox.Show(VisibilityLibrary.Properties.Resources.MsgLayerIsImageService, - VisibilityLibrary.Properties.Resources.CaptionLayerIsImageService, MessageBoxButton.YesNo); - - if (mbr == MessageBoxResult.No) + var observerPoints = RLOS_ObserversInExtent.Select(x => x.AddInPoint).Union(ObserverInExtentPoints); + var surface = GetSurfaceFromMapByName(ArcMap.Document.FocusMap, SelectedSurfaceName); + if (surface == null) { - System.Windows.MessageBox.Show(VisibilityLibrary.Properties.Resources.MsgTryAgain, VisibilityLibrary.Properties.Resources.MsgCalcCancelled); + System.Windows.MessageBox.Show(VisibilityLibrary.Properties.Resources.MsgTryAgain, VisibilityLibrary.Properties.Resources.CaptionError); return; } - } - - // Determine if selected surface is projected or geographic - var geoDataset = surfaceLayer as IGeoDataset; - if (geoDataset == null) - { - System.Windows.MessageBox.Show(VisibilityLibrary.Properties.Resources.MsgTryAgain, VisibilityLibrary.Properties.Resources.CaptionError); - return; - } - SelectedSurfaceSpatialRef = geoDataset.SpatialReference; + bool spatialAnalystAvailable = IsSpatialAnalystAvailable(); + if (!spatialAnalystAvailable) + { + System.Windows.MessageBox.Show(VisibilityLibrary.Properties.Resources.LOSSpatialAnalystLicenseInvalid, VisibilityLibrary.Properties.Resources.MsgCalcCancelled); + return; + } - if (SelectedSurfaceSpatialRef is IGeographicCoordinateSystem) - { - MessageBox.Show(VisibilityLibrary.Properties.Resources.RLOSUserPrompt, VisibilityLibrary.Properties.Resources.RLOSUserPromptCaption); - return; - } + ILayer surfaceLayer = GetLayerFromMapByName(ArcMap.Document.FocusMap, SelectedSurfaceName); + // Issue warning if layer is ImageServerLayer + if (surfaceLayer is IImageServerLayer) + { + MessageBoxResult mbr = MessageBox.Show(VisibilityLibrary.Properties.Resources.MsgLayerIsImageService, + VisibilityLibrary.Properties.Resources.CaptionLayerIsImageService, MessageBoxButton.YesNo); - if (ArcMap.Document.FocusMap.SpatialReference.FactoryCode != geoDataset.SpatialReference.FactoryCode) - { - MessageBox.Show(VisibilityLibrary.Properties.Resources.LOSDataFrameMatch, VisibilityLibrary.Properties.Resources.LOSSpatialReferenceCaption); - return; - } + if (mbr == MessageBoxResult.No) + { + System.Windows.MessageBox.Show(VisibilityLibrary.Properties.Resources.MsgTryAgain, VisibilityLibrary.Properties.Resources.MsgCalcCancelled); + return; + } + } - using (ComReleaser oComReleaser = new ComReleaser()) - { - // Create feature workspace - IFeatureWorkspace workspace = CreateFeatureWorkspace("tempWorkspace"); - if (workspace == null) + // Determine if selected surface is projected or geographic + var geoDataset = surfaceLayer as IGeoDataset; + if (geoDataset == null) { System.Windows.MessageBox.Show(VisibilityLibrary.Properties.Resources.MsgTryAgain, VisibilityLibrary.Properties.Resources.CaptionError); return; } - StartEditOperation((IWorkspace)workspace); + SelectedSurfaceSpatialRef = geoDataset.SpatialReference; - // Create feature class - IFeatureClass pointFc = CreateObserversFeatureClass(workspace, SelectedSurfaceSpatialRef, "Output" + RunCount.ToString()); - if (pointFc == null) + if (SelectedSurfaceSpatialRef is IGeographicCoordinateSystem) { - System.Windows.MessageBox.Show(VisibilityLibrary.Properties.Resources.MsgTryAgain, VisibilityLibrary.Properties.Resources.CaptionError); + MessageBox.Show(VisibilityLibrary.Properties.Resources.RLOSUserPrompt, VisibilityLibrary.Properties.Resources.RLOSUserPromptCaption); return; } - double finalObserverOffset = GetOffsetInZUnits(ObserverOffset.Value, surface.ZFactor, OffsetUnitType); - double finalSurfaceOffset = GetOffsetInZUnits(SurfaceOffset, surface.ZFactor, OffsetUnitType); - - double conversionFactor = GetConversionFactor(SelectedSurfaceSpatialRef); - string unitString = GetUnitString(SelectedSurfaceSpatialRef); - //unit of raster - DistanceTypes srUnit = GetMTUnitFromEsriUnit(unitString); - //get distance in map units - double muMaxDist = GetDistanceFromTo(OffsetUnitType, srUnit, MaxDistance); - double muMinDist = GetDistanceFromTo(OffsetUnitType, srUnit, MinDistance); - //Distance in meters - double convertedMinDistance = MinDistance * conversionFactor; - double convertedMaxDistance = MaxDistance * conversionFactor; - - double finalMinDistance; - double finalMaxDistance; - if (srUnit.ToString() != OffsetUnitType.ToString()) + if (ArcMap.Document.FocusMap.SpatialReference.FactoryCode != geoDataset.SpatialReference.FactoryCode) { - finalMinDistance = GetLinearDistance(ArcMap.Document.FocusMap, convertedMinDistance, OffsetUnitType); - finalMaxDistance = GetLinearDistance(ArcMap.Document.FocusMap, convertedMaxDistance, OffsetUnitType); + MessageBox.Show(VisibilityLibrary.Properties.Resources.LOSDataFrameMatch, VisibilityLibrary.Properties.Resources.LOSSpatialReferenceCaption); + return; } - else + + using (ComReleaser oComReleaser = new ComReleaser()) { - finalMinDistance = GetDistanceFromTo(DistanceTypes.Meters, srUnit, convertedMinDistance); - finalMaxDistance = GetDistanceFromTo(DistanceTypes.Meters, srUnit, convertedMaxDistance); - } + // Create feature workspace + IFeatureWorkspace workspace = CreateFeatureWorkspace("tempWorkspace"); + if (workspace == null) + { + System.Windows.MessageBox.Show(VisibilityLibrary.Properties.Resources.MsgTryAgain, VisibilityLibrary.Properties.Resources.CaptionError); + return; + } - double finalLeftHorizontalFOV = GetAngularDistance(ArcMap.Document.FocusMap, LeftHorizontalFOV, AngularUnitType); - double finalRightHorizontalFOV = GetAngularDistance(ArcMap.Document.FocusMap, RightHorizontalFOV, AngularUnitType); - double finalBottomVerticalFOV = GetAngularDistance(ArcMap.Document.FocusMap, BottomVerticalFOV, AngularUnitType); - double finalTopVerticalFOV = GetAngularDistance(ArcMap.Document.FocusMap, TopVerticalFOV, AngularUnitType); + StartEditOperation((IWorkspace)workspace); - // Output radius geometries - List maxRangeBufferGeomList = new List(); - List rangeFanGeomList = new List(); + // Create feature class + IFeatureClass pointFc = CreateObserversFeatureClass(workspace, SelectedSurfaceSpatialRef, "Output" + RunCount.ToString()); + if (pointFc == null) + { + System.Windows.MessageBox.Show(VisibilityLibrary.Properties.Resources.MsgTryAgain, VisibilityLibrary.Properties.Resources.CaptionError); + return; + } - foreach (var observerPoint in ObserverAddInPoints) - { - if ((observerPoint == null) || (observerPoint.Point == null)) - continue; + double finalObserverOffset = GetOffsetInZUnits(ObserverOffset.Value, surface.ZFactor, OffsetUnitType); + double finalSurfaceOffset = GetOffsetInZUnits(SurfaceOffset, surface.ZFactor, OffsetUnitType); + + double conversionFactor = GetConversionFactor(SelectedSurfaceSpatialRef); + string unitString = GetUnitString(SelectedSurfaceSpatialRef); + //unit of raster + DistanceTypes srUnit = GetMTUnitFromEsriUnit(unitString); + //get distance in map units + double muMaxDist = GetDistanceFromTo(DistanceUnitType, srUnit, MaxDistance); + double muMinDist = GetDistanceFromTo(DistanceUnitType, srUnit, MinDistance); + //Distance in meters + double convertedMinDistance = MinDistance * conversionFactor; + double convertedMaxDistance = MaxDistance * conversionFactor; + + double finalMinDistance; + double finalMaxDistance; + if (srUnit.ToString() != DistanceUnitType.ToString()) + { + finalMinDistance = GetLinearDistance(ArcMap.Document.FocusMap, convertedMinDistance, DistanceUnitType); + finalMaxDistance = GetLinearDistance(ArcMap.Document.FocusMap, convertedMaxDistance, DistanceUnitType); + } + else + { + finalMinDistance = GetDistanceFromTo(DistanceTypes.Meters, srUnit, convertedMinDistance); + finalMaxDistance = GetDistanceFromTo(DistanceTypes.Meters, srUnit, convertedMaxDistance); + } - // Create 2 clipping geometries: - // 1. maxRangeBufferGeomList - is used to clip the viz GP output because 2. doesn't work directly - // 2. rangeFanGeomList - this is the range fan input by the user - ITopologicalOperator topologicalOperator = observerPoint.Point as ITopologicalOperator; - if (topologicalOperator == null) - continue; + double finalLeftHorizontalFOV = GetAngularDistance(ArcMap.Document.FocusMap, LeftHorizontalFOV, AngularUnitType); + double finalRightHorizontalFOV = GetAngularDistance(ArcMap.Document.FocusMap, RightHorizontalFOV, AngularUnitType); + double finalBottomVerticalFOV = GetAngularDistance(ArcMap.Document.FocusMap, BottomVerticalFOV, AngularUnitType); + double finalTopVerticalFOV = GetAngularDistance(ArcMap.Document.FocusMap, TopVerticalFOV, AngularUnitType); - IGeometry geomBuffer = topologicalOperator.Buffer(muMaxDist); + // Output radius geometries + List maxRangeBufferGeomList = new List(); + List rangeFanGeomList = new List(); - maxRangeBufferGeomList.Add(geomBuffer); + foreach (var observerPoint in observerPoints) + { + if ((observerPoint == null) || (observerPoint.Point == null)) + continue; - IGeometry geomRangeFan = ConstructRangeFan(observerPoint.Point, muMinDist, muMaxDist, - finalLeftHorizontalFOV, finalRightHorizontalFOV, SelectedSurfaceSpatialRef); - if (geomRangeFan != null) - rangeFanGeomList.Add(geomRangeFan); + // Create 2 clipping geometries: + // 1. maxRangeBufferGeomList - is used to clip the viz GP output because 2. doesn't work directly + // 2. rangeFanGeomList - this is the range fan input by the user + ITopologicalOperator topologicalOperator = observerPoint.Point as ITopologicalOperator; + if (topologicalOperator == null) + continue; - double z1 = surface.GetElevation(observerPoint.Point) + finalObserverOffset; + IGeometry geomBuffer = topologicalOperator.Buffer(muMaxDist); - //create a new point feature - IFeature ipFeature = pointFc.CreateFeature(); + maxRangeBufferGeomList.Add(geomBuffer); - // Set the field values for the feature - SetFieldValues(finalObserverOffset, finalSurfaceOffset,muMinDist, muMaxDist, finalLeftHorizontalFOV, - finalRightHorizontalFOV, finalBottomVerticalFOV, finalTopVerticalFOV, ipFeature); + IGeometry geomRangeFan = ConstructRangeFan(observerPoint.Point, muMinDist, muMaxDist, + finalLeftHorizontalFOV, finalRightHorizontalFOV, SelectedSurfaceSpatialRef); + if (geomRangeFan != null) + rangeFanGeomList.Add(geomRangeFan); - if (double.IsNaN(z1)) - { - System.Windows.MessageBox.Show(VisibilityLibrary.Properties.Resources.RLOSPointsOutsideOfSurfaceExtent, VisibilityLibrary.Properties.Resources.MsgCalcCancelled); - return; - } + double z1 = surface.GetElevation(observerPoint.Point) + finalObserverOffset; - //Create shape - IPoint point = new PointClass() { Z = z1, X = observerPoint.Point.X, Y = observerPoint.Point.Y, ZAware = true }; - ipFeature.Shape = point; - ipFeature.Store(); - } + //create a new point feature + IFeature ipFeature = pointFc.CreateFeature(); - IFeatureClassDescriptor fd = new FeatureClassDescriptorClass(); - fd.Create(pointFc, null, "OBJECTID"); + // Set the field values for the feature + SetFieldValues(finalObserverOffset, finalSurfaceOffset, muMinDist, muMaxDist, finalLeftHorizontalFOV, + finalRightHorizontalFOV, finalBottomVerticalFOV, finalTopVerticalFOV, ipFeature); - StopEditOperation((IWorkspace)workspace); + if (double.IsNaN(z1)) + { + System.Windows.MessageBox.Show(VisibilityLibrary.Properties.Resources.RLOSPointsOutsideOfSurfaceExtent, VisibilityLibrary.Properties.Resources.MsgCalcCancelled); + return; + } - try - { - ILayer layer = GetLayerFromMapByName(ArcMap.Document.FocusMap, SelectedSurfaceName); - string layerPath = GetLayerPath(layer); + //Create shape + IPoint point = new PointClass() { Z = z1, X = observerPoint.Point.X, Y = observerPoint.Point.Y, ZAware = true }; + ipFeature.Shape = point; + ipFeature.Store(); + } + + IFeatureClassDescriptor fd = new FeatureClassDescriptorClass(); + fd.Create(pointFc, null, "OBJECTID"); - if (string.IsNullOrEmpty(layerPath)) + StopEditOperation((IWorkspace)workspace); + + try { - // if layer path didn't resolve, issue error and stop - System.Windows.MessageBox.Show(VisibilityLibrary.Properties.Resources.MsgSurfaceLayerNotFound, VisibilityLibrary.Properties.Resources.AEInvalidInput); - throw new Exception(VisibilityLibrary.Properties.Resources.MsgSurfaceLayerNotFound); - } + ILayer layer = GetLayerFromMapByName(ArcMap.Document.FocusMap, SelectedSurfaceName); + string layerPath = GetLayerPath(layer); - IFeatureLayer ipFeatureLayer = new FeatureLayerClass(); - ipFeatureLayer.FeatureClass = pointFc; + if (string.IsNullOrEmpty(layerPath)) + { + // if layer path didn't resolve, issue error and stop + System.Windows.MessageBox.Show(VisibilityLibrary.Properties.Resources.MsgSurfaceLayerNotFound, VisibilityLibrary.Properties.Resources.AEInvalidInput); + throw new Exception(VisibilityLibrary.Properties.Resources.MsgSurfaceLayerNotFound); + } - IDataset ipDataset = (IDataset)pointFc; - string outputFcName = ipDataset.BrowseName + "_output"; - string strPath = ipDataset.Workspace.PathName + System.IO.Path.DirectorySeparatorChar + ipDataset.BrowseName; - string outPath = ipDataset.Workspace.PathName + System.IO.Path.DirectorySeparatorChar + outputFcName; + IFeatureLayer ipFeatureLayer = new FeatureLayerClass(); + ipFeatureLayer.FeatureClass = pointFc; - IVariantArray parameters = new VarArrayClass(); - parameters.Add(layerPath); - parameters.Add(strPath); - parameters.Add(outPath); + IDataset ipDataset = (IDataset)pointFc; + string outputFcName = ipDataset.BrowseName + "_output"; + string strPath = ipDataset.Workspace.PathName + System.IO.Path.DirectorySeparatorChar + ipDataset.BrowseName; + string outPath = ipDataset.Workspace.PathName + System.IO.Path.DirectorySeparatorChar + outputFcName; - IGeoProcessor2 gp = new GeoProcessorClass(); + IVariantArray parameters = new VarArrayClass(); + parameters.Add(layerPath); + parameters.Add(strPath); + parameters.Add(outPath); - gp.AddOutputsToMap = false; + IGeoProcessor2 gp = new GeoProcessorClass(); - // Add a mask to buffer the output to selected distance - SetGPMask(workspace, maxRangeBufferGeomList, gp, "radiusMask"); + gp.AddOutputsToMap = false; - object oResult = gp.Execute("Visibility_sa", parameters, null); - IGeoProcessorResult ipResult = (IGeoProcessorResult)oResult; + // Add a mask to buffer the output to selected distance + SetGPMask(workspace, maxRangeBufferGeomList, gp, "radiusMask"); - ComReleaser.ReleaseCOMObject(gp); - gp = null; - GC.Collect(); + object oResult = gp.Execute("Visibility_sa", parameters, null); + IGeoProcessorResult ipResult = (IGeoProcessorResult)oResult; - // Add the range fan geometries to the map - foreach (IGeometry geom in rangeFanGeomList) - { - var color = new RgbColorClass() { Blue = 255 } as IColor; - AddGraphicToMap(geom, color, true); - } + ComReleaser.ReleaseCOMObject(gp); + gp = null; + GC.Collect(); + + // Add the range fan geometries to the map + foreach (IGeometry geom in rangeFanGeomList) + { + var color = new RgbColorClass() { Blue = 255 } as IColor; + AddGraphicToMap(geom, color, true); + } - IRasterLayer outputRasterLayer = new RasterLayerClass(); - outputRasterLayer.CreateFromFilePath(outPath); + IRasterLayer outputRasterLayer = new RasterLayerClass(); + outputRasterLayer.CreateFromFilePath(outPath); - string fcName = IntersectOutput(outputRasterLayer, ipDataset, workspace, rangeFanGeomList); + string fcName = IntersectOutput(outputRasterLayer, ipDataset, workspace, rangeFanGeomList); - IFeatureClass finalFc = workspace.OpenFeatureClass(fcName); + IFeatureClass finalFc = workspace.OpenFeatureClass(fcName); - IFeatureLayer outputFeatureLayer = new FeatureLayerClass(); - outputFeatureLayer.FeatureClass = finalFc; + IFeatureLayer outputFeatureLayer = new FeatureLayerClass(); + outputFeatureLayer.FeatureClass = finalFc; - //Add it to a map if the layer is valid. - if (outputFeatureLayer != null) + //Add it to a map if the layer is valid. + if (outputFeatureLayer != null) + { + // set the renderer + IFeatureRenderer featRend = UniqueValueRenderer(workspace, finalFc); + IGeoFeatureLayer geoLayer = (IGeoFeatureLayer)outputFeatureLayer; + geoLayer.Renderer = featRend; + geoLayer.Name = "RLOS_Visibility_" + RunCount.ToString(); + + // Set the layer transparency + IDisplayFilterManager filterManager = (IDisplayFilterManager)outputFeatureLayer; + ITransparencyDisplayFilter filter = new TransparencyDisplayFilter(); + filter.Transparency = 80; + filterManager.DisplayFilter = filter; + + ESRI.ArcGIS.Carto.IMap map = ArcMap.Document.FocusMap; + map.AddLayer((ILayer)outputFeatureLayer); + + IEnvelope envelope = outputFeatureLayer.AreaOfInterest.Envelope; + ZoomToExtent(envelope); + } + + RunCount += 1; + } + catch (Exception ex) { - // set the renderer - IFeatureRenderer featRend = UniqueValueRenderer(workspace, finalFc); - IGeoFeatureLayer geoLayer = (IGeoFeatureLayer)outputFeatureLayer; - geoLayer.Renderer = featRend; - geoLayer.Name = "RLOS_Visibility_" + RunCount.ToString(); - - // Set the layer transparency - IDisplayFilterManager filterManager = (IDisplayFilterManager)outputFeatureLayer; - ITransparencyDisplayFilter filter = new TransparencyDisplayFilter(); - filter.Transparency = 80; - filterManager.DisplayFilter = filter; - - ESRI.ArcGIS.Carto.IMap map = ArcMap.Document.FocusMap; - map.AddLayer((ILayer)outputFeatureLayer); - - IEnvelope envelope = outputFeatureLayer.AreaOfInterest.Envelope; - ZoomToExtent(envelope); + System.Diagnostics.Debug.WriteLine(ex.Message); + System.Windows.MessageBox.Show(VisibilityLibrary.Properties.Resources.MsgTryAgain, VisibilityLibrary.Properties.Resources.MsgCalcCancelled); } - RunCount += 1; - } - catch (Exception ex) - { - System.Diagnostics.Debug.WriteLine(ex.Message); - System.Windows.MessageBox.Show(VisibilityLibrary.Properties.Resources.MsgTryAgain, VisibilityLibrary.Properties.Resources.MsgCalcCancelled); + DisplayOutOfExtentMsg(selectedLayer); + //display point present out of extent + var colorObserver = new RgbColorClass() { Red = 255 }; + var colorBorder = new RgbColorClass() { Red = 0, Blue = 0, Green = 0 }; + var observerOutOfExtent = new ObservableCollection(RLOS_ObserversOutOfExtent.Select(x => x.AddInPoint).Union(ObserverOutExtentPoints)); + foreach (var point in observerOutOfExtent) + { + AddGraphicToMap(point.Point, colorObserver, markerStyle: esriSimpleMarkerStyle.esriSMSX, size: 10, borderColor: colorBorder); + } } } + else + { + System.Windows.MessageBox.Show(VisibilityLibrary.Properties.Resources.OutOfExtentMsg, VisibilityLibrary.Properties.Resources.OutOfExtentHeader); + } } - catch(Exception ex) + catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.Message); System.Windows.MessageBox.Show(VisibilityLibrary.Properties.Resources.MsgTryAgain, VisibilityLibrary.Properties.Resources.MsgCalcCancelled); @@ -597,6 +620,9 @@ internal override void CreateMapElement() finally { IsRunning = false; + IsRLOSValidSelection = false; + ClearRLOSCollections(); + ValidateRLOS_LayerSelection(); } } @@ -650,29 +676,29 @@ public IFeatureRenderer UniqueValueRenderer(IFeatureWorkspace workspace, IFeatur outlineSymbol.Style = esriSimpleLineStyle.esriSLSSolid; if (ShowNonVisibleData == true) - { + { fillSymbol.Color = new RgbColorClass() { Red = 255 } as IColor; fillSymbol.Outline = outlineSymbol; uvRenderer.AddValue("0", "", fillSymbol as ISymbol); - uvRenderer.set_Label("0", "Non-Visible"); + uvRenderer.set_Label("0", "Non-Visible"); } - fillSymbol2.Color = new RgbColorClass() { Green = 255 } as IColor; - fillSymbol2.Outline = outlineSymbol; - uvRenderer.AddValue("1", "", fillSymbol2 as ISymbol); - uvRenderer.set_Label("1", "Visible by 1 Observer"); + fillSymbol2.Color = new RgbColorClass() { Green = 255 } as IColor; + fillSymbol2.Outline = outlineSymbol; + uvRenderer.AddValue("1", "", fillSymbol2 as ISymbol); + uvRenderer.set_Label("1", "Visible by 1 Observer"); - int field = ipTable.FindField("gridcode"); - uvRenderer.set_Field(0, "gridcode"); + int field = ipTable.FindField("gridcode"); + uvRenderer.set_Field(0, "gridcode"); - for (int i = 2; i < uniqueValues; i++) - { - ISimpleFillSymbol newFillSymbol = new SimpleFillSymbolClass(); - newFillSymbol.Color = colorRamp.get_Color(i); - newFillSymbol.Outline = outlineSymbol; - uvRenderer.AddValue(i.ToString(), "", newFillSymbol as ISymbol); - string label = "Visible by " + i.ToString() + " Observers"; - uvRenderer.set_Label(i.ToString(), label); - } + for (int i = 2; i < uniqueValues; i++) + { + ISimpleFillSymbol newFillSymbol = new SimpleFillSymbolClass(); + newFillSymbol.Color = colorRamp.get_Color(i); + newFillSymbol.Outline = outlineSymbol; + uvRenderer.AddValue(i.ToString(), "", newFillSymbol as ISymbol); + string label = "Visible by " + i.ToString() + " Observers"; + uvRenderer.set_Label(i.ToString(), label); + } return featRenderer; } @@ -716,7 +742,7 @@ public static bool StartEditOperation(IWorkspace ipWorkspace) throw (ex); } } - + return blnWasSuccessful; } @@ -1119,7 +1145,7 @@ private static double GetConversionFactor(ISpatialReference ipSpatialReference) if (ipSpatialReference is IGeographicCoordinateSystem) { IAngularUnit ipAngularUnit = ((IGeographicCoordinateSystem)ipSpatialReference).CoordinateUnit; - String name= ipAngularUnit.Name; + String name = ipAngularUnit.Name; dConversionFactor = ipAngularUnit.ConversionFactor; } else @@ -1138,13 +1164,13 @@ private static String GetUnitString(ISpatialReference ipSpatialReference) { IAngularUnit ipAngularUnit = ((IGeographicCoordinateSystem)ipSpatialReference).CoordinateUnit; name = ipAngularUnit.Name; - + } else { ILinearUnit ipLinearUnit = ((IProjectedCoordinateSystem)ipSpatialReference).CoordinateUnit; name = ipLinearUnit.Name; - + } return name; } @@ -1152,9 +1178,9 @@ private static String GetUnitString(ISpatialReference ipSpatialReference) private static DistanceTypes GetMTUnitFromEsriUnit(String esriUnit) { DistanceTypes outUnit = DistanceTypes.Meters; ; - switch(esriUnit) + switch (esriUnit) { - + case "Foot_US": case "Foot": outUnit = DistanceTypes.Feet; @@ -1279,7 +1305,7 @@ private static string GetLayerPath(ILayer layer) { IImageServerLayer mlayer = layer as IImageServerLayer; return mlayer.Name; - } + } else if (layer is IRasterLayer) { IRasterLayer rlayer = layer as IRasterLayer; @@ -1294,6 +1320,50 @@ private static string GetLayerPath(ILayer layer) return null; } + private void ReadSelectedLayerPoints() + { + + var surface = GetSurfaceFromMapByName(ArcMap.Document.FocusMap, SelectedSurfaceName); + double finalObserverOffset = GetOffsetInZUnits(ObserverOffset.Value, surface.ZFactor, OffsetUnitType); + + var observerColor = new RgbColor() { Blue = 255 } as IColor; + ReadSelectedLyrPoints(RLOS_ObserversInExtent, RLOS_ObserversOutOfExtent, SelectedRLOS_ObserverLyrName, observerColor); + } + + + private void DisplayOutOfExtentMsg(string selectedLayer) + { + var observerIDCollection = RLOS_ObserversOutOfExtent.Select(x => x.ID).ToList(); + var observerString = string.Empty; + var targetString = string.Empty; + foreach (var item in observerIDCollection) + { + if (observerString == "") + observerString = item.ToString(); + else + observerString = observerString + "," + item.ToString(); + } + if (observerIDCollection.Any()) + { + if (observerIDCollection.Count <= 10) + { + var msgString = string.Empty; + if (observerIDCollection.Any()) + { + msgString = "Observers lying outside the extent of elevation surface are: " + observerString; + } + System.Windows.MessageBox.Show(msgString, + "Unable To Process For Few Locations"); + } + else + { + System.Windows.MessageBox.Show(VisibilityLibrary.Properties.Resources.LLOSPointsOutsideOfSurfaceExtent, + VisibilityLibrary.Properties.Resources.MsgCalcCancelled); + } + + } + } + #endregion } } diff --git a/source/addins/ArcMapAddinVisibility/ViewModels/TabBaseViewModel.cs b/source/addins/ArcMapAddinVisibility/ViewModels/TabBaseViewModel.cs index 73a9584..3af72f4 100644 --- a/source/addins/ArcMapAddinVisibility/ViewModels/TabBaseViewModel.cs +++ b/source/addins/ArcMapAddinVisibility/ViewModels/TabBaseViewModel.cs @@ -42,6 +42,7 @@ public TabBaseViewModel() CancelCommand = new RelayCommand(OnCancelCommand); // Mediator + Mediator.Register(Constants.NEW_MAP_POINT, OnMapClickEvent); Mediator.Register(Constants.NEW_MAP_POINT, OnNewMapPointEvent); Mediator.Register(Constants.MOUSE_MOVE_POINT, OnMouseMoveEvent); Mediator.Register(Constants.TAB_ITEM_SELECTED, OnTabItemSelected); @@ -68,7 +69,7 @@ protected virtual void OnActiveToolChanged(object obj) { string currentActiveToolName = obj as string; - if ((currentActiveToolName == ThisAddIn.IDs.MapPointTool)) + if ((currentActiveToolName == ThisAddIn.IDs.MapPointTool)) return; lastActiveToolName = currentActiveToolName; @@ -292,6 +293,7 @@ public virtual bool CanCreateElement public VisibilityLibrary.Helpers.RelayCommand ActivateToolCommand { get; set; } public VisibilityLibrary.Helpers.RelayCommand EnterKeyCommand { get; set; } public VisibilityLibrary.Helpers.RelayCommand CancelCommand { get; set; } + public bool IsMapClick { get; set; } internal void OnCancelCommand(object obj) { @@ -411,7 +413,7 @@ internal void RemoveGraphics(IGraphicsContainer gc, List list) } } elementList.Clear(); - + RaisePropertyChanged(() => HasMapGraphics); } @@ -474,7 +476,13 @@ internal virtual void OnNewMapPointEvent(object obj) // do nothing } + internal virtual void OnMapClickEvent(object obj) + { + IsMapClick = true; + } + #endregion + #region Public Functions /// /// Method used to deactivate tool @@ -502,11 +510,11 @@ public void SetToolActiveInToolBar(string toolName) return; } - if ((ArcMap.Application.CurrentTool != null) && + if ((ArcMap.Application.CurrentTool != null) && (ArcMap.Application.CurrentTool.Name.Equals(toolName))) - // Tricky: Check if tool already active - because setting CurrentTool again will - // cause Activate/Deactive to be called by ArcGIS framework - return; + // Tricky: Check if tool already active - because setting CurrentTool again will + // cause Activate/Deactive to be called by ArcGIS framework + return; ESRI.ArcGIS.Framework.ICommandBars commandBars = ArcMap.Application.Document.CommandBars; ESRI.ArcGIS.esriSystem.UID commandID = new ESRI.ArcGIS.esriSystem.UIDClass(); @@ -530,37 +538,37 @@ private string GetFormattedPoint(IPoint point) try { - var cn = point as IConversionNotation; - if (cn != null) - { - switch (VisibilityConfig.AddInConfig.DisplayCoordinateType) + var cn = point as IConversionNotation; + if (cn != null) { - case CoordinateTypes.DD: - result = cn.GetDDFromCoords(6); - break; - case CoordinateTypes.DDM: - result = cn.GetDDMFromCoords(4); - break; - case CoordinateTypes.DMS: - result = cn.GetDMSFromCoords(2); - break; - //case CoordinateTypes.GARS: - // result = cn.GetGARSFromCoords(); - // break; - case CoordinateTypes.MGRS: - result = cn.CreateMGRS(5, true, esriMGRSModeEnum.esriMGRSMode_Automatic); - break; - case CoordinateTypes.USNG: - result = cn.GetUSNGFromCoords(5, true, true); - break; - case CoordinateTypes.UTM: - result = cn.GetUTMFromCoords(esriUTMConversionOptionsEnum.esriUTMAddSpaces | esriUTMConversionOptionsEnum.esriUTMUseNS); - break; - default: - break; + switch (VisibilityConfig.AddInConfig.DisplayCoordinateType) + { + case CoordinateTypes.DD: + result = cn.GetDDFromCoords(6); + break; + case CoordinateTypes.DDM: + result = cn.GetDDMFromCoords(4); + break; + case CoordinateTypes.DMS: + result = cn.GetDMSFromCoords(2); + break; + //case CoordinateTypes.GARS: + // result = cn.GetGARSFromCoords(); + // break; + case CoordinateTypes.MGRS: + result = cn.CreateMGRS(5, true, esriMGRSModeEnum.esriMGRSMode_Automatic); + break; + case CoordinateTypes.USNG: + result = cn.GetUSNGFromCoords(5, true, true); + break; + case CoordinateTypes.UTM: + result = cn.GetUTMFromCoords(esriUTMConversionOptionsEnum.esriUTMAddSpaces | esriUTMConversionOptionsEnum.esriUTMUseNS); + break; + default: + break; + } } } - } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.Message); @@ -600,6 +608,7 @@ private void OnTabItemSelected(object obj) return; IsActiveTab = (obj == this); + IsMapClick = false; } internal string AddTextToMap(string text, IGeometry geom, IColor color, bool IsTempGraphic = false, int size = 12) @@ -653,9 +662,12 @@ internal string AddTextToMap(string text, IGeometry geom, IColor color, bool IsT /// Adds a graphic element to the map graphics container /// /// IGeometry - internal string AddGraphicToMap(IGeometry geom, IColor color, bool IsTempGraphic = false, - esriSimpleMarkerStyle markerStyle = esriSimpleMarkerStyle.esriSMSCircle, int size = 5) + internal string AddGraphicToMap(IGeometry geom, IColor color, bool IsTempGraphic = false, + esriSimpleMarkerStyle markerStyle = esriSimpleMarkerStyle.esriSMSCircle, int size = 5, IColor borderColor = null) { + if (borderColor == null) + borderColor = color; + if (geom == null || ArcMap.Document == null || ArcMap.Document.FocusMap == null) return string.Empty; @@ -669,7 +681,7 @@ internal string AddGraphicToMap(IGeometry geom, IColor color, bool IsTempGraphic var simpleMarkerSymbol = (ISimpleMarkerSymbol)new SimpleMarkerSymbol(); simpleMarkerSymbol.Color = color; simpleMarkerSymbol.Outline = true; - simpleMarkerSymbol.OutlineColor = color; + simpleMarkerSymbol.OutlineColor = borderColor; simpleMarkerSymbol.Size = size; simpleMarkerSymbol.Style = markerStyle; @@ -695,7 +707,7 @@ internal string AddGraphicToMap(IGeometry geom, IColor color, bool IsTempGraphic IPolygonElement pe = (IPolygonElement)new PolygonElementClass(); element = pe as IElement; IFillShapeElement fe = (IFillShapeElement)pe; - + var fillSymbol = new SimpleFillSymbolClass(); RgbColor selectedColor = new RgbColorClass(); selectedColor.Red = 0; @@ -703,8 +715,8 @@ internal string AddGraphicToMap(IGeometry geom, IColor color, bool IsTempGraphic selectedColor.Blue = 0; selectedColor.Transparency = (byte)0; - fillSymbol.Color = selectedColor; - + fillSymbol.Color = selectedColor; + fe.Symbol = fillSymbol; } @@ -720,7 +732,7 @@ internal string AddGraphicToMap(IGeometry geom, IColor color, bool IsTempGraphic var eprop = (IElementProperties)element; eprop.Name = Guid.NewGuid().ToString(); - GraphicsList.Add(new AMGraphic(eprop.Name, geom, IsTempGraphic)); + GraphicsList.Add(new AMGraphic(eprop.Name, geom, IsTempGraphic)); gc.AddElement(element, 0); @@ -732,7 +744,7 @@ internal string AddGraphicToMap(IGeometry geom, IColor color, bool IsTempGraphic } internal DistanceTypes GetDistanceType(int linearUnitFactoryCode) - { + { DistanceTypes distanceType = DistanceTypes.Meters; switch (linearUnitFactoryCode) { @@ -826,7 +838,7 @@ internal void ZoomToExtent(IGeometry geom) var av = (IActiveView)ArcMap.Document.FocusMap; IEnvelope env = geom.Envelope; - + double extentPercent = (env.XMax - env.XMin) > (env.YMax - env.YMin) ? (env.XMax - env.XMin) * .3 : (env.YMax - env.YMin) * .3; env.XMax = env.XMax + extentPercent; env.XMin = env.XMin - extentPercent; diff --git a/source/addins/ProAppVisibilityModule/Helpers/FeatureClassHelper.cs b/source/addins/ProAppVisibilityModule/Helpers/FeatureClassHelper.cs index 1105b4f..ca9ae27 100644 --- a/source/addins/ProAppVisibilityModule/Helpers/FeatureClassHelper.cs +++ b/source/addins/ProAppVisibilityModule/Helpers/FeatureClassHelper.cs @@ -43,11 +43,11 @@ public class FeatureClassHelper /// POLYLINE /// POLYGON /// - public static async Task CreateLayer(string featureclassName, string featureclassType, bool zEnabled, bool addToMap) + public static async Task CreateLayer(string featureDatasetName, string featureclassName, string featureclassType, bool zEnabled, bool addToMap) { List arguments = new List(); // store the results in the default geodatabase - arguments.Add(CoreModule.CurrentProject.DefaultGeodatabasePath); + arguments.Add(CoreModule.CurrentProject.DefaultGeodatabasePath + System.IO.Path.DirectorySeparatorChar + featureDatasetName); // name of the feature class arguments.Add(featureclassName); // type of geometry @@ -57,7 +57,7 @@ public static async Task CreateLayer(string featureclassName, string featu // m values arguments.Add("DISABLED"); // z values - if(zEnabled) + if (zEnabled) arguments.Add("ENABLED"); else arguments.Add("DISABLED"); @@ -66,9 +66,9 @@ public static async Task CreateLayer(string featureclassName, string featu var environments = Geoprocessing.MakeEnvironmentArray(overwriteoutput: true); - IGPResult result = await Geoprocessing.ExecuteToolAsync("CreateFeatureclass_management", - Geoprocessing.MakeValueArray(arguments.ToArray()), - environments, + IGPResult result = await Geoprocessing.ExecuteToolAsync("CreateFeatureclass_management", + Geoprocessing.MakeValueArray(arguments.ToArray()), + environments, null, null, addToMap ? GPExecuteToolFlags.Default : GPExecuteToolFlags.None); @@ -76,6 +76,29 @@ public static async Task CreateLayer(string featureclassName, string featu return isResultGoodAndReportMessages(result, "CreateFeatureclass_management", arguments); } + public static async Task CreateFeatureDataset(string featureclassName) + { + List arguments = new List(); + // store the results in the default geodatabase + arguments.Add(CoreModule.CurrentProject.DefaultGeodatabasePath); + // name of the feature class + arguments.Add(featureclassName); + + + arguments.Add(MapView.Active.Map.SpatialReference); + + var environments = Geoprocessing.MakeEnvironmentArray(); + + IGPResult result = await Geoprocessing.ExecuteToolAsync("CreateFeatureDataset_management", + Geoprocessing.MakeValueArray(arguments.ToArray()), + environments, + null, + null, + GPExecuteToolFlags.None); + + return isResultGoodAndReportMessages(result, "CreateFeatureDataset_management", arguments); + } + /// /// Add a field to a layer /// @@ -109,7 +132,7 @@ public static async Task AddFieldToLayer(string tableName, string fieldName, str IGPResult result = await Geoprocessing.ExecuteToolAsync("AddField_management", Geoprocessing.MakeValueArray(arguments.ToArray())); } - public static async Task JoinField(string inData, string inField, string joinTable, string joinField, string [] fields) + public static async Task JoinField(string inData, string inField, string joinTable, string joinField, string[] fields) { List arguments = new List(); // in_data @@ -135,10 +158,10 @@ public static async Task JoinField(string inData, string inField, string joinTab /// /// /// - public static async Task CreateSightLines(string observersFeatureLayer, - string targetsFeatureLayer, - string outLineFeatureLayer, - string observerOffsetFieldName, + public static async Task CreateSightLines(string observersFeatureLayer, + string targetsFeatureLayer, + string outLineFeatureLayer, + string observerOffsetFieldName, string targetOffsetFieldName) { List arguments = new List(); @@ -205,8 +228,8 @@ public static async Task AddSurfaceInformation(string featureClass, string /// /// /// - public static async Task CreateLOS(string surfaceName, - string lineFeatureClassName, + public static async Task CreateLOS(string surfaceName, + string lineFeatureClassName, string outLOSFeatureClass) { List arguments = new List(); @@ -276,7 +299,7 @@ public static async Task Delete(string name) /// field from raster /// (Optional)If present, the layer to intersect with the output polygon layer /// success - public static async Task IntersectOutput(string inputRasterLayer, string outputPolygonLayer, + public static async Task IntersectOutput(string inputRasterLayer, string outputPolygonLayer, bool simplify, string rasterField, string intersectMaskFeatureClass = "") { if (string.IsNullOrEmpty(inputRasterLayer) || string.IsNullOrEmpty(outputPolygonLayer)) @@ -306,7 +329,7 @@ public static async Task IntersectOutput(string inputRasterLayer, string o var environments = Geoprocessing.MakeEnvironmentArray(overwriteoutput: true); - IGPResult result = await Geoprocessing.ExecuteToolAsync("RasterToPolygon_conversion", + IGPResult result = await Geoprocessing.ExecuteToolAsync("RasterToPolygon_conversion", Geoprocessing.MakeValueArray(arguments.ToArray()), environments, null, null, addToMap ? GPExecuteToolFlags.Default : GPExecuteToolFlags.None); @@ -325,10 +348,10 @@ public static async Task IntersectOutput(string inputRasterLayer, string o // out_polygon_features argumentsIntersect.Add(outputPolygonLayer); // Don't include FIDs in join (or they will both appear in output) - argumentsIntersect.Add("NO_FID"); + argumentsIntersect.Add("NO_FID"); // if non-empty, intersect with intersectMaskFeatureClass - result = await Geoprocessing.ExecuteToolAsync("Intersect_analysis", + result = await Geoprocessing.ExecuteToolAsync("Intersect_analysis", Geoprocessing.MakeValueArray(argumentsIntersect.ToArray()), environments); return isResultGoodAndReportMessages(result, "Intersect_analysis", arguments); @@ -352,8 +375,8 @@ public static async Task IntersectOutput(string inputRasterLayer, string o /// geoprocessing environments /// add to map or not /// - public static async Task CreateVisibility(string surfaceName, string observerFeatureClassName, string outRLOSFeatureClass, - double observerOffset, double surfaceOffset, + public static async Task CreateVisibility(string surfaceName, string observerFeatureClassName, string outRLOSFeatureClass, + double observerOffset, double surfaceOffset, double minDistance, double maxDistance, double horizontalStartAngle, double horizontalEndAngle, double verticalUpperAngle, double verticalLowerAngle, @@ -462,7 +485,7 @@ await QueuedTask.Run(() => int cnt = 1; foreach (var gc in gridcodeUniqueList) - { + { colors.MoveNext(); List visValues = new List(); @@ -475,7 +498,7 @@ await QueuedTask.Run(() => string label = "Visible by " + cnt.ToString() + observerString; var visClass = new CIMUniqueValueClass() { - Values = visValues.ToArray(), + Values = visValues.ToArray(), Label = label, Visible = true, Editable = true, @@ -527,7 +550,7 @@ await QueuedTask.Run(() => /// AddInPoints collection /// offset in z units /// - public static async Task CreatingFeatures(string featureClassName, ObservableCollection collection, double offsetInZUnits) + public static async Task CreatingFeatures(string featureClassName, ObservableCollection collection, double offsetInZUnits, string rendererConfigFieldName = "") { try { @@ -555,6 +578,10 @@ await QueuedTask.Run(async () => var point = MapPointBuilder.CreateMapPoint(item.Point.X, item.Point.Y, 0.0, item.Point.SpatialReference); rowBuffer[shapeFieldName] = point; + if (rendererConfigFieldName != "") + { + rowBuffer[rendererConfigFieldName] = -1; + } using (var feature = enterpriseFeatureClass.CreateRow(rowBuffer)) { //To Indicate that the attribute table has to be updated @@ -607,7 +634,7 @@ await QueuedTask.Run(async () => using (FeatureClassDefinition fcDefinition = enterpriseFeatureClass.GetDefinition()) { int zFieldIndex = fcDefinition.FindField(zFieldName); - + EditOperation editOperation = new EditOperation(); editOperation.Callback(context => { @@ -626,9 +653,9 @@ await QueuedTask.Run(async () => var z = (Double)feature[zFieldIndex] + offsetInMapZUnits; feature[VisibilityLibrary.Properties.Resources.OffsetWithZFieldName] = z; feature.SetShape(MapPointBuilder.CreateMapPoint(mp.X, mp.Y, z, mp.SpatialReference)); - + feature.Store(); - + context.Invalidate(feature); } } @@ -893,7 +920,7 @@ await QueuedTask.Run(() => var visSymbol = SymbolFactory.Instance.ConstructPointSymbol(); var vis1 = SymbolFactory.Instance.ConstructMarker(CIMColor.CreateRGBColor(0, 255, 0), 5, SimpleMarkerStyle.Circle); var vis2 = SymbolFactory.Instance.ConstructMarker(CIMColor.CreateRGBColor(0, 0, 255), 12, SimpleMarkerStyle.Circle); - + visSymbol.SymbolLayers = new CIMSymbolLayer[2] { vis1, vis2 }; var visTar = new CIMUniqueValueClass() @@ -907,6 +934,26 @@ await QueuedTask.Run(() => classes.Add(visTar); + // out of extent + List outOfExtentValues = new List(); + CIMUniqueValue outOfExtentValue = new CIMUniqueValue(); + outOfExtentValue.FieldValues = new string[] { "-1" }; + outOfExtentValues.Add(outOfExtentValue); + + var outExtentSymbol = SymbolFactory.Instance.ConstructPointSymbol(); + var symbol = SymbolFactory.Instance.ConstructMarker(CIMColor.CreateRGBColor(255, 0, 0), 12, SimpleMarkerStyle.X); + outExtentSymbol.SymbolLayers = new CIMSymbolLayer[1] { symbol }; + + var outOfExtent = new CIMUniqueValueClass() + { + Values = outOfExtentValues.ToArray(), + Label = "Out Of Extent", + Visible = true, + Editable = true, + Symbol = new CIMSymbolReference() { Symbol = outExtentSymbol } + }; + classes.Add(outOfExtent); + CIMUniqueValueGroup groupOne = new CIMUniqueValueGroup(); groupOne.Heading = "Observers"; groupOne.Classes = classes.ToArray(); @@ -914,14 +961,14 @@ await QueuedTask.Run(() => uniqueValueRenderer.Groups = new CIMUniqueValueGroup[] { groupOne }; //Draw the rest with the default symbol - uniqueValueRenderer.UseDefaultSymbol = true; - uniqueValueRenderer.DefaultLabel = "All other values"; + //uniqueValueRenderer.UseDefaultSymbol = true; + //uniqueValueRenderer.DefaultLabel = "All other values"; - var defaultColor = CIMColor.CreateRGBColor(215, 215, 215); - uniqueValueRenderer.DefaultSymbol = new CIMSymbolReference() - { - Symbol = SymbolFactory.Instance.ConstructPointSymbol(defaultColor) - }; + //var defaultColor = CIMColor.CreateRGBColor(215, 215, 215); + //uniqueValueRenderer.DefaultSymbol = new CIMSymbolReference() + //{ + // Symbol = SymbolFactory.Instance.ConstructPointSymbol(defaultColor) + //}; //var renderer = featureLayer.CreateRenderer(uniqueValueRenderer); featureLayer.SetRenderer(uniqueValueRenderer); @@ -958,6 +1005,26 @@ await QueuedTask.Run(() => classes.Add(noVis); + // out of extent + List outOfExtentValues = new List(); + CIMUniqueValue outOfExtentValue = new CIMUniqueValue(); + outOfExtentValue.FieldValues = new string[] { "-1" }; + outOfExtentValues.Add(outOfExtentValue); + + var outExtentSymbol = SymbolFactory.Instance.ConstructPointSymbol(); + var symbol = SymbolFactory.Instance.ConstructMarker(CIMColor.CreateRGBColor(0, 0, 255), 12, SimpleMarkerStyle.X); + outExtentSymbol.SymbolLayers = new CIMSymbolLayer[1] { symbol }; + + var outOfExtent = new CIMUniqueValueClass() + { + Values = outOfExtentValues.ToArray(), + Label = "Out Of Extent", + Visible = true, + Editable = true, + Symbol = new CIMSymbolReference() { Symbol = outExtentSymbol } + }; + classes.Add(outOfExtent); + CIMUniqueValueGroup groupOne = new CIMUniqueValueGroup(); groupOne.Heading = "Targets"; groupOne.Classes = classes.ToArray(); @@ -979,6 +1046,59 @@ await QueuedTask.Run(() => //featureLayer.SetTransparency(50.0); }); } + + internal async static Task CreateRLOSObserversRenderer(FeatureLayer featureLayer) + { + await QueuedTask.Run(() => + { + //Create the Unique Value Renderer + CIMUniqueValueRenderer uniqueValueRenderer = new CIMUniqueValueRenderer(); + + // set the value field + uniqueValueRenderer.Fields = new string[] { VisibilityLibrary.Properties.Resources.IsOutOfExtentFieldName }; + + List classes = new List(); + // out of extent + List outOfExtentValues = new List(); + CIMUniqueValue outOfExtentValue = new CIMUniqueValue(); + outOfExtentValue.FieldValues = new string[] { "-1" }; + outOfExtentValues.Add(outOfExtentValue); + + var outExtentSymbol = SymbolFactory.Instance.ConstructPointSymbol(); + var symbol = SymbolFactory.Instance.ConstructMarker(CIMColor.CreateRGBColor(255, 0, 0), 12, SimpleMarkerStyle.X); + outExtentSymbol.SymbolLayers = new CIMSymbolLayer[1] { symbol }; + + var outOfExtent = new CIMUniqueValueClass() + { + Values = outOfExtentValues.ToArray(), + Label = "Out Of Extent", + Visible = true, + Editable = true, + Symbol = new CIMSymbolReference() { Symbol = outExtentSymbol } + }; + classes.Add(outOfExtent); + + + CIMUniqueValueGroup groupOne = new CIMUniqueValueGroup(); + groupOne.Heading = "Out Of Extent"; + groupOne.Classes = classes.ToArray(); + + uniqueValueRenderer.Groups = new CIMUniqueValueGroup[] { groupOne }; + + //Draw the rest with the default symbol + uniqueValueRenderer.UseDefaultSymbol = true; + uniqueValueRenderer.DefaultLabel = "In side Extent"; + + uniqueValueRenderer.DefaultSymbol = new CIMSymbolReference() + { + Symbol = SymbolFactory.Instance.ConstructPointSymbol(CIMColor.CreateRGBColor(0, 255, 0), 12, SimpleMarkerStyle.Circle) + }; + + //var renderer = featureLayer.CreateRenderer(uniqueValueRenderer); + featureLayer.SetRenderer(uniqueValueRenderer); + }); + } + public static async Task CreateTargetLayerLabels(FeatureLayer featureLayer) { await QueuedTask.Run(() => @@ -996,16 +1116,18 @@ End If lc.SetExpressionEngine(LabelExpressionEngine.VBScript); if (MapView.Active.Map.GetLabelEngine() == LabelEngine.Standard) { - lc.SetStandardLabelPlacementProperties(new CIMStandardLabelPlacementProperties() - { - PointPlacementMethod = StandardPointPlacementMethod.OnTopPoint, FeatureType = LabelFeatureType.Point + lc.SetStandardLabelPlacementProperties(new CIMStandardLabelPlacementProperties() + { + PointPlacementMethod = StandardPointPlacementMethod.OnTopPoint, + FeatureType = LabelFeatureType.Point }); } else { lc.SetMaplexLabelPlacementProperties(new CIMMaplexLabelPlacementProperties() { - PointPlacementMethod = MaplexPointPlacementMethod.CenteredOnPoint, FeatureType = LabelFeatureType.Point + PointPlacementMethod = MaplexPointPlacementMethod.CenteredOnPoint, + FeatureType = LabelFeatureType.Point }); } @@ -1024,7 +1146,7 @@ await QueuedTask.Run(() => return; List layerIds = new List(); - + foreach (Layer layer in layerList) { var layerToAddDef = layer.GetDefinition(); @@ -1046,7 +1168,25 @@ await QueuedTask.Run(() => } mapDef.Layers = maplayerIds.ToArray(); - MapView.Active.Map.SetDefinition(mapDef); + MapView.Active.Map.SetDefinition(mapDef); + }); + } + + public static async Task MoveLayersToGroupLayer(List layerList, string groupLayerName) + { + await QueuedTask.Run(() => + { + GroupLayer groupLayer = LayerFactory.Instance.CreateGroupLayer(MapView.Active.Map, + 0, // add to the top ? + groupLayerName); + for (int i = layerList.Count - 1; i >= 0; i--) + { + groupLayer.MoveLayer(layerList[i], 0); + } + }); + await ArcGIS.Desktop.Framework.FrameworkApplication.Current.Dispatcher.Invoke(async () => + { + await ArcGIS.Desktop.Core.Project.Current.SaveAsync(); }); } @@ -1122,8 +1262,8 @@ await QueuedTask.Run(() => }); } - public static async Task CreateVisCodeRenderer(FeatureLayer featureLayer, string visField, - int visCodeVisible, int visCodeNotVisible, + public static async Task CreateVisCodeRenderer(FeatureLayer featureLayer, string visField, + int visCodeVisible, int visCodeNotVisible, CIMColor visibleColor, CIMColor notVisibleColor, double visibleSize, double notVisibleSize) { diff --git a/source/addins/ProAppVisibilityModule/Models/AddInPointObject.cs b/source/addins/ProAppVisibilityModule/Models/AddInPointObject.cs new file mode 100644 index 0000000..997e622 --- /dev/null +++ b/source/addins/ProAppVisibilityModule/Models/AddInPointObject.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ProAppVisibilityModule.Models +{ + public class AddInPointObject + { + private int _id; + public int ID + { + get { return _id; } + set { _id = value; } + } + private AddInPoint addInPoint; + + public AddInPoint AddInPoint + { + get { return addInPoint; } + set { addInPoint = value; } + } + + } +} diff --git a/source/addins/ProAppVisibilityModule/ProAppVisibilityModule.csproj b/source/addins/ProAppVisibilityModule/ProAppVisibilityModule.csproj index 929e5f9..31b7eda 100644 --- a/source/addins/ProAppVisibilityModule/ProAppVisibilityModule.csproj +++ b/source/addins/ProAppVisibilityModule/ProAppVisibilityModule.csproj @@ -106,6 +106,9 @@ + + Code + @@ -114,6 +117,10 @@ ProEditPropertiesView.xaml + + ProSelectCoordinateFieldsView.xaml + Code + @@ -128,6 +135,10 @@ MSBuild:Compile Designer + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -180,9 +191,10 @@ - + + - + \ No newline at end of file diff --git a/source/addins/ProAppVisibilityModule/ViewModels/ProLLOSViewModel.cs b/source/addins/ProAppVisibilityModule/ViewModels/ProLLOSViewModel.cs index bdacc8e..298ff5e 100644 --- a/source/addins/ProAppVisibilityModule/ViewModels/ProLLOSViewModel.cs +++ b/source/addins/ProAppVisibilityModule/ViewModels/ProLLOSViewModel.cs @@ -32,6 +32,9 @@ using ProAppVisibilityModule.Helpers; using ProAppVisibilityModule.Models; using VisibilityLibrary.Helpers; +using ArcGIS.Core.Data; +using System.Text.RegularExpressions; +using ArcGIS.Core.CIM; namespace ProAppVisibilityModule.ViewModels { @@ -40,16 +43,18 @@ public class ProLLOSViewModel : ProLOSBaseViewModel public ProLLOSViewModel() { TargetAddInPoints = new ObservableCollection(); + TargetInExtentPoints = new ObservableCollection(); + TargetOutExtentPoints = new ObservableCollection(); IsActiveTab = true; - + DisplayProgressBarLLOS = Visibility.Hidden; // commands - SubmitCommand = new RelayCommand(async (obj) => + SubmitCommand = new RelayCommand(async (obj) => { try { await OnSubmitCommand(obj); } - catch(Exception ex) + catch (Exception ex) { Debug.Print(ex.Message); } @@ -59,10 +64,9 @@ public ProLLOSViewModel() #region Properties - public ObservableCollection TargetAddInPoints { get; set; } private int executionCounter = 0; - + private string _ObserversLayerName = VisibilityLibrary.Properties.Resources.LLOSObserversLayerName; public string ObserversLayerName { @@ -119,6 +123,34 @@ public string SightLinesLayerName set { } } + private Visibility _displayProgressBar = Visibility.Collapsed; + public Visibility DisplayProgressBarLLOS + { + get + { + return _displayProgressBar; + } + set + { + _displayProgressBar = value; + RaisePropertyChanged(() => DisplayProgressBarLLOS); + } + } + + private string _FeatureDatasetName = VisibilityLibrary.Properties.Resources.LLOSFeatureDatasetName; + public string FeatureDatasetName + { + get + { + if (executionCounter > 0) + { + _FeatureDatasetName = string.Format("{0}_{1}", VisibilityLibrary.Properties.Resources.LLOSFeatureDatasetName, executionCounter); + } + return _FeatureDatasetName; + } + set { } + } + #endregion #region Commands @@ -139,18 +171,23 @@ await Task.Run(async () => // TODO udpate wait cursor/progressor try { + DisplayProgressBarLLOS = Visibility.Visible; + IsRunning = true; await CreateMapElement(); - //await Reset(true); } - catch(Exception ex) + catch (Exception ex) { Debug.Print(ex.Message); } + finally + { + DisplayProgressBarLLOS = Visibility.Hidden; + } }); } - catch(Exception ex) + catch (Exception ex) { Debug.Print(ex.Message); } @@ -174,6 +211,7 @@ internal override void OnDeletePointCommand(object obj) return; DeleteTargetPoints(targets); + ValidateLLOS_LayerSelection(); } /// @@ -193,6 +231,8 @@ private void DeleteTargetPoints(List targets) foreach (var obj in targets) { TargetAddInPoints.Remove(obj); + TargetInExtentPoints.Remove(obj); + TargetOutExtentPoints.Remove(obj); } } @@ -212,6 +252,8 @@ internal override void OnDeleteAllPointsCommand(object obj) base.OnDeleteAllPointsCommand(obj); else if (mode == VisibilityLibrary.Properties.Resources.ToolModeTarget) DeleteTargetPoints(TargetAddInPoints.ToList()); + + ValidateLLOS_LayerSelection(); } #endregion @@ -230,18 +272,37 @@ internal override async void OnNewMapPointEvent(object obj) var point = obj as MapPoint; - if (point == null || !(await IsValidPoint(point))) - return; - - if (ToolMode == MapPointToolMode.Target) + if (point != null && ToolMode == MapPointToolMode.Target) { + if (IsMapClick) + { + if (!(await IsValidPoint(point, true))) + { + IsMapClick = false; + return; + } + } var guid = await AddGraphicToMap(point, ColorFactory.Instance.RedRGB, true, 5.0, markerStyle: SimpleMarkerStyle.Square, tag: "target"); var addInPoint = new AddInPoint() { Point = point, GUID = guid }; + bool isValid = await IsValidPoint(point, false); Application.Current.Dispatcher.Invoke(() => { + if (!isValid) + { + TargetOutExtentPoints.Insert(0, addInPoint); + } + else + { + TargetInExtentPoints.Insert(0, addInPoint); + } + TargetAddInPoints.Insert(0, addInPoint); }); + IsMapClick = false; } + + ValidateLLOS_LayerSelection(); + } /// @@ -261,9 +322,11 @@ internal override async Task Reset(bool toolReset) { // reset target points TargetAddInPoints.Clear(); + TargetInExtentPoints.Clear(); + TargetOutExtentPoints.Clear(); }); } - catch(Exception ex) + catch (Exception ex) { Debug.Print(ex.Message); } @@ -277,9 +340,9 @@ public override bool CanCreateElement { get { - return (!string.IsNullOrWhiteSpace(SelectedSurfaceName) - && ObserverAddInPoints.Any() - && TargetAddInPoints.Any() + return (!string.IsNullOrWhiteSpace(SelectedSurfaceName) + && (ObserverAddInPoints.Any() || LLOS_ObserversInExtent.Any() || LLOS_ObserversOutOfExtent.Any()) + && (TargetAddInPoints.Any() || LLOS_TargetsInExtent.Any() || LLOS_TargetsOutOfExtent.Any()) && TargetOffset.HasValue && ObserverOffset.HasValue); } @@ -292,18 +355,28 @@ internal override async Task CreateMapElement() { try { - IsRunning = true; + + await ReadSelectedLayers(); if (!CanCreateElement || MapView.Active == null || MapView.Active.Map == null || string.IsNullOrWhiteSpace(SelectedSurfaceName)) return; - bool success = await ExecuteVisibilityLLOS(); - if (!success) - MessageBox.Show("LLOS computations did not complete correctly.\nPlease check your parameters and try again.", - VisibilityLibrary.Properties.Resources.CaptionError); + if ((LLOS_ObserversInExtent.Any() || ObserverAddInPoints.Any()) + && LLOS_TargetsInExtent.Any() || TargetAddInPoints.Any()) + { + bool success = await ExecuteVisibilityLLOS(); + if (!success) + MessageBox.Show("LLOS computations did not complete correctly.\nPlease check your parameters and try again.", + VisibilityLibrary.Properties.Resources.CaptionError); + } + else + { + ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show(VisibilityLibrary.Properties.Resources.OutOfExtentMsg, VisibilityLibrary.Properties.Resources.OutOfExtentHeader); + } DeactivateTool(VisibilityMapTool.ToolId); + OnMapPointToolDeactivated(null); GC.Collect(); GC.WaitForPendingFinalizers(); @@ -311,7 +384,7 @@ internal override async Task CreateMapElement() //await base.CreateMapElement(); } - catch(Exception ex) + catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.Message); ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show(VisibilityLibrary.Properties.Resources.ExceptionSomethingWentWrong, @@ -320,6 +393,7 @@ internal override async Task CreateMapElement() finally { IsRunning = false; + ClearLLOSCollections(); } } @@ -334,19 +408,25 @@ private async Task ExecuteVisibilityLLOS() if (surfaceSR == null || !surfaceSR.IsProjected) { MessageBox.Show(VisibilityLibrary.Properties.Resources.RLOSUserPrompt, VisibilityLibrary.Properties.Resources.RLOSUserPromptCaption); - + Application.Current.Dispatcher.Invoke(() => { TargetAddInPoints.Clear(); ObserverAddInPoints.Clear(); + ObserverInExtentPoints.Clear(); + TargetInExtentPoints.Clear(); + ObserverOutExtentPoints.Clear(); + TargetOutExtentPoints.Clear(); ClearTempGraphics(); }); await Reset(true); - + return false; } + var observerPoints = new ObservableCollection(LLOS_ObserversInExtent.Select(x => x.AddInPoint).Union(ObserverInExtentPoints)); + var targetPoints = new ObservableCollection(LLOS_TargetsInExtent.Select(x => x.AddInPoint).Union(TargetInExtentPoints)); // Warn if Image Service layer Layer surfaceLayer = GetLayerFromMapByName(SelectedSurfaceName); if (surfaceLayer is ImageServiceLayer) @@ -361,7 +441,47 @@ private async Task ExecuteVisibilityLLOS() } } - success = await FeatureClassHelper.CreateLayer(ObserversLayerName, "POINT", true, true); + //Validate Dataframe Spatial reference with surface spatial reference + if (MapView.Active.Map.SpatialReference.Wkid != surfaceSR.Wkid) + { + MessageBox.Show(VisibilityLibrary.Properties.Resources.LOSDataFrameMatch, VisibilityLibrary.Properties.Resources.LOSSpatialReferenceCaption); + return false; + } + + await ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run(() => + { + using (Geodatabase geodatabase = new Geodatabase(new FileGeodatabaseConnectionPath(new Uri(CoreModule.CurrentProject.DefaultGeodatabasePath)))) + { + executionCounter = 0; + int featureDataSetSuffix = 0; + var enterpriseDefinitionNames = geodatabase.GetDefinitions().Where(i => i.GetName().StartsWith(VisibilityLibrary.Properties.Resources.LLOSFeatureDatasetName)).Select(i => i.GetName()).ToList(); + foreach (var defName in enterpriseDefinitionNames) + { + int n; + bool isNumeric = int.TryParse(Regex.Match(defName, @"\d+$").Value, out n); + if (isNumeric) + featureDataSetSuffix = featureDataSetSuffix < n ? n : featureDataSetSuffix; + } + featureDataSetSuffix = enterpriseDefinitionNames.Count > 0 ? featureDataSetSuffix + 1 : 0; + + var observerLyrSuffix = GetLayerSuffix(VisibilityLibrary.Properties.Resources.LLOSObserversLayerName, geodatabase); + var targetLyrSuffix = GetLayerSuffix(VisibilityLibrary.Properties.Resources.LLOSTargetsLayerName, geodatabase); + var sightLinesLyrSuffix = GetLayerSuffix(VisibilityLibrary.Properties.Resources.LLOSSightLinesLayerName, geodatabase); + var outputLyrSuffix = GetLayerSuffix(VisibilityLibrary.Properties.Resources.LLOSOutputLayerName, geodatabase); + + executionCounter = new List { featureDataSetSuffix, observerLyrSuffix, targetLyrSuffix, sightLinesLyrSuffix, outputLyrSuffix }.Max(); + } + }); + + //Create Feature dataset + success = await FeatureClassHelper.CreateFeatureDataset(FeatureDatasetName); + if (!success) + return false; + + success = await FeatureClassHelper.CreateLayer(FeatureDatasetName, ObserversLayerName, "POINT", true, true); + + if (!success) + return false; // add fields for observer offset @@ -369,7 +489,7 @@ private async Task ExecuteVisibilityLLOS() await FeatureClassHelper.AddFieldToLayer(ObserversLayerName, VisibilityLibrary.Properties.Resources.OffsetWithZFieldName, "DOUBLE"); await FeatureClassHelper.AddFieldToLayer(ObserversLayerName, VisibilityLibrary.Properties.Resources.TarIsVisFieldName, "SHORT"); - success = await FeatureClassHelper.CreateLayer(TargetsLayerName, "POINT", true, true); + success = await FeatureClassHelper.CreateLayer(FeatureDatasetName, TargetsLayerName, "POINT", true, true); if (!success) return false; @@ -381,10 +501,10 @@ private async Task ExecuteVisibilityLLOS() await FeatureClassHelper.AddFieldToLayer(TargetsLayerName, VisibilityLibrary.Properties.Resources.NumOfObserversFieldName, "SHORT"); // add observer points to feature layer - await FeatureClassHelper.CreatingFeatures(ObserversLayerName, ObserverAddInPoints, GetAsMapZUnits(surfaceSR, ObserverOffset.Value)); + await FeatureClassHelper.CreatingFeatures(ObserversLayerName, observerPoints, GetAsMapZUnits(surfaceSR, ObserverOffset.Value)); // add target points to feature layer - await FeatureClassHelper.CreatingFeatures(TargetsLayerName, TargetAddInPoints, GetAsMapZUnits(surfaceSR, TargetOffset.Value)); + await FeatureClassHelper.CreatingFeatures(TargetsLayerName, targetPoints, GetAsMapZUnits(surfaceSR, TargetOffset.Value)); // update with surface information success = await FeatureClassHelper.AddSurfaceInformation(ObserversLayerName, SelectedSurfaceName, VisibilityLibrary.Properties.Resources.ZFieldName); @@ -405,8 +525,8 @@ private async Task ExecuteVisibilityLLOS() success = await FeatureClassHelper.CreateSightLines(ObserversLayerName, TargetsLayerName, - CoreModule.CurrentProject.DefaultGeodatabasePath + System.IO.Path.DirectorySeparatorChar + SightLinesLayerName, - VisibilityLibrary.Properties.Resources.OffsetWithZFieldName, + CoreModule.CurrentProject.DefaultGeodatabasePath + System.IO.Path.DirectorySeparatorChar + FeatureDatasetName + System.IO.Path.DirectorySeparatorChar + SightLinesLayerName, + VisibilityLibrary.Properties.Resources.OffsetWithZFieldName, VisibilityLibrary.Properties.Resources.OffsetWithZFieldName); if (!success) @@ -418,8 +538,8 @@ private async Task ExecuteVisibilityLLOS() GC.Collect(); success = await FeatureClassHelper.CreateLOS(SelectedSurfaceName, - CoreModule.CurrentProject.DefaultGeodatabasePath + System.IO.Path.DirectorySeparatorChar + SightLinesLayerName, - CoreModule.CurrentProject.DefaultGeodatabasePath + System.IO.Path.DirectorySeparatorChar + OutputLayerName); + CoreModule.CurrentProject.DefaultGeodatabasePath + System.IO.Path.DirectorySeparatorChar + FeatureDatasetName + System.IO.Path.DirectorySeparatorChar + SightLinesLayerName, + CoreModule.CurrentProject.DefaultGeodatabasePath + System.IO.Path.DirectorySeparatorChar + FeatureDatasetName + System.IO.Path.DirectorySeparatorChar + OutputLayerName); if (!success) return false; @@ -430,9 +550,9 @@ private async Task ExecuteVisibilityLLOS() // join fields with sight lines - await FeatureClassHelper.JoinField(CoreModule.CurrentProject.DefaultGeodatabasePath + System.IO.Path.DirectorySeparatorChar + SightLinesLayerName, + await FeatureClassHelper.JoinField(CoreModule.CurrentProject.DefaultGeodatabasePath + System.IO.Path.DirectorySeparatorChar + FeatureDatasetName + System.IO.Path.DirectorySeparatorChar + SightLinesLayerName, "OID", - CoreModule.CurrentProject.DefaultGeodatabasePath + System.IO.Path.DirectorySeparatorChar + OutputLayerName, + CoreModule.CurrentProject.DefaultGeodatabasePath + System.IO.Path.DirectorySeparatorChar + FeatureDatasetName + System.IO.Path.DirectorySeparatorChar + OutputLayerName, "SourceOID", new string[] { "TarIsVis" }); @@ -441,9 +561,9 @@ await FeatureClassHelper.JoinField(CoreModule.CurrentProject.DefaultGeodatabaseP //if (sourceOIDs.Count > 0) //{ - var visStats = await FeatureClassHelper.GetVisibilityStats(sourceOIDs, SightLinesLayerName); + var visStats = await FeatureClassHelper.GetVisibilityStats(sourceOIDs, SightLinesLayerName); - await FeatureClassHelper.UpdateLayersWithVisibilityStats(visStats, ObserversLayerName, TargetsLayerName); + await FeatureClassHelper.UpdateLayersWithVisibilityStats(visStats, ObserversLayerName, TargetsLayerName); //} @@ -452,6 +572,14 @@ await FeatureClassHelper.JoinField(CoreModule.CurrentProject.DefaultGeodatabaseP var sightLinesLayer = GetLayerFromMapByName(SightLinesLayerName) as FeatureLayer; var outputLayer = GetLayerFromMapByName(OutputLayerName) as FeatureLayer; + var observerOutOfExtent = new ObservableCollection(LLOS_ObserversOutOfExtent.Select(x => x.AddInPoint).Union(ObserverOutExtentPoints)); + // add observer points present out of extent to feature layer + await FeatureClassHelper.CreatingFeatures(ObserversLayerName, observerOutOfExtent, GetAsMapZUnits(surfaceSR, TargetOffset.Value), VisibilityLibrary.Properties.Resources.TarIsVisFieldName); + + var targetOutOfExtent = new ObservableCollection(LLOS_TargetsOutOfExtent.Select(x => x.AddInPoint).Union(TargetOutExtentPoints)); + // add target points present out of extent to feature layer + await FeatureClassHelper.CreatingFeatures(TargetsLayerName, targetOutOfExtent, GetAsMapZUnits(surfaceSR, TargetOffset.Value), VisibilityLibrary.Properties.Resources.NumOfObserversFieldName); + if (observersLayer != null && targetsLayer != null && sightLinesLayer != null && outputLayer != null) { await FeatureClassHelper.CreateObserversRenderer(GetLayerFromMapByName(ObserversLayerName) as FeatureLayer); @@ -487,10 +615,20 @@ await FeatureClassHelper.CreateVisCodeRenderer(GetLayerFromMapByName(OutputLayer // for now we are not resetting after a run of the tool //await Reset(true); + + + List lyrList = new List(); + lyrList.Add(observersLayer); + lyrList.Add(targetsLayer); + lyrList.Add(outputLayer); + lyrList.Add(sightLinesLayer); + + await FeatureClassHelper.MoveLayersToGroupLayer(lyrList, FeatureDatasetName); var envelope = await QueuedTask.Run(() => outputLayer.QueryExtent()); await ZoomToExtent(envelope); - executionCounter++; + var surfaceEnvelope = await GetSurfaceEnvelope(); + await DisplayOutOfExtentMsg(surfaceEnvelope); success = true; } else @@ -498,7 +636,7 @@ await FeatureClassHelper.CreateVisCodeRenderer(GetLayerFromMapByName(OutputLayer success = false; } } - catch(Exception ex) + catch (Exception ex) { success = false; Debug.Print(ex.Message); @@ -507,13 +645,112 @@ await FeatureClassHelper.CreateVisCodeRenderer(GetLayerFromMapByName(OutputLayer return success; } + private int GetLayerSuffix(string layerName, Geodatabase geodatabase) + { + int counter = 0; + var enterpriseFCNames = geodatabase.GetDefinitions().Where(i => i.GetName().StartsWith(layerName)).Select(i => i.GetName()).ToList(); + foreach (var fcName in enterpriseFCNames) + { + int n; + bool isNumeric = int.TryParse(Regex.Match(fcName, @"\d+$").Value, out n); + if (isNumeric) + counter = counter < n ? n : counter; + } + counter = enterpriseFCNames.Count > 0 ? counter + 1 : 0; + return counter; + } + + private async Task DisplayOutOfExtentMsg(Envelope surfaceEnvelope) + { + await QueuedTask.Run(() => + { + var observerIDCollection = LLOS_ObserversOutOfExtent.Select(x => x.ID).ToList(); + var targetIDCollection = LLOS_TargetsOutOfExtent.Select(x => x.ID).ToList(); + var observerString = string.Empty; + var targetString = string.Empty; + foreach (var item in observerIDCollection) + { + if (observerString == "") + observerString = item.ToString(); + else + observerString = observerString + "," + item.ToString(); + } + foreach (var item in targetIDCollection) + { + if (targetString == "") + targetString = item.ToString(); + else + targetString = targetString + "," + item.ToString(); + } + if (observerIDCollection.Any() || targetIDCollection.Any()) + { + if ((observerIDCollection.Count + targetIDCollection.Count) <= 10) + { + var msgString = string.Empty; + if (observerIDCollection.Any()) + { + msgString = "Observers lying outside the extent of elevation surface are: " + observerString; + } + if (targetIDCollection.Any()) + { + if (msgString != "") + msgString = msgString + "\n"; + msgString = msgString + "Targets lying outside the extent of elevation surface are: " + targetString; + } + ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show(msgString, + "Unable To Process For Few Locations"); + } + else + { + ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show(VisibilityLibrary.Properties.Resources.LLOSPointsOutsideOfSurfaceExtent, + VisibilityLibrary.Properties.Resources.MsgCalcCancelled); + } + } + }); + } + + private async Task ReadSelectedLayers() + { + LLOS_ObserversInExtent.Clear(); + LLOS_ObserversOutOfExtent.Clear(); + LLOS_TargetsInExtent.Clear(); + LLOS_TargetsOutOfExtent.Clear(); + + var surfaceEnvelope = await GetSurfaceEnvelope(); + var selectedFeatures = await QueuedTask.Run(() => { return MapView.Active.Map.GetSelection(); }); + await QueuedTask.Run(() => + { + var selectedFeaturesCollections = selectedFeatures.Where(x => x.Key.Name == SelectedLLOS_ObserverLyrName) + .Select(x => x.Value).FirstOrDefault(); + ReadPointFromLayer(surfaceEnvelope, LLOS_ObserversInExtent, LLOS_ObserversOutOfExtent, SelectedLLOS_ObserverLyrName, selectedFeaturesCollections); + }); + await QueuedTask.Run(() => + { + var selectedFeaturesCollections = selectedFeatures.Where(x => x.Key.Name == SelectedLLOS_TargetLyrName) + .Select(x => x.Value).FirstOrDefault(); + ReadPointFromLayer(surfaceEnvelope, LLOS_TargetsInExtent, LLOS_TargetsOutOfExtent, SelectedLLOS_TargetLyrName, selectedFeaturesCollections, "target"); + }); + } + internal override void OnDisplayCoordinateTypeChanged(object obj) { var list = TargetAddInPoints.ToList(); + var inExtentList = TargetInExtentPoints.ToList(); + var outExtentList = TargetOutExtentPoints.ToList(); + TargetAddInPoints.Clear(); + TargetInExtentPoints.Clear(); + TargetOutExtentPoints.Clear(); + foreach (var item in list) TargetAddInPoints.Add(item); + foreach (var item in inExtentList) + TargetInExtentPoints.Add(item); + + foreach (var item in outExtentList) + TargetOutExtentPoints.Add(item); + // and update observers base.OnDisplayCoordinateTypeChanged(obj); } diff --git a/source/addins/ProAppVisibilityModule/ViewModels/ProLOSBaseViewModel.cs b/source/addins/ProAppVisibilityModule/ViewModels/ProLOSBaseViewModel.cs index 0e0adf1..200d4bb 100644 --- a/source/addins/ProAppVisibilityModule/ViewModels/ProLOSBaseViewModel.cs +++ b/source/addins/ProAppVisibilityModule/ViewModels/ProLOSBaseViewModel.cs @@ -1,4 +1,4 @@ -// Copyright 2016 Esri +// Copyright 2016 Esri // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,24 +12,27 @@ // See the License for the specific language governing permissions and // limitations under the License. +using ArcGIS.Core.CIM; +using ArcGIS.Core.Geometry; +using ArcGIS.Desktop.Framework.Threading.Tasks; +using ArcGIS.Desktop.Mapping; +using ArcGIS.Desktop.Mapping.Events; +using ProAppVisibilityModule.Models; using System; +using System.Collections; using System.Collections.Generic; -using System.Linq; using System.Collections.ObjectModel; -using System.Collections; -using System.Windows; -using System.Threading.Tasks; using System.Diagnostics; -using ArcGIS.Core.Geometry; -using ArcGIS.Desktop.Mapping; -using ArcGIS.Desktop.Framework.Threading.Tasks; -using ArcGIS.Desktop.Mapping.Events; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Windows; using VisibilityLibrary; using VisibilityLibrary.Helpers; -using VisibilityLibrary.Views; using VisibilityLibrary.ViewModels; -using ProAppVisibilityModule.Models; -using ArcGIS.Core.CIM; +using VisibilityLibrary.Views; namespace ProAppVisibilityModule.ViewModels { @@ -40,10 +43,23 @@ public ProLOSBaseViewModel() ObserverOffset = 2.0; TargetOffset = 0.0; OffsetUnitType = DistanceTypes.Meters; + DistanceUnitType = DistanceTypes.Meters; AngularUnitType = AngularTypes.DEGREES; + EnterManullyOption = VisibilityLibrary.Properties.Resources.EnterManuallyOption; ObserverAddInPoints = new ObservableCollection(); - + ObserverInExtentPoints = new ObservableCollection(); + ObserverOutExtentPoints = new ObservableCollection(); + LLOS_ObserversInExtent = new ObservableCollection(); + LLOS_ObserversOutOfExtent = new ObservableCollection(); + LLOS_TargetsInExtent = new ObservableCollection(); + LLOS_TargetsOutOfExtent = new ObservableCollection(); + RLOS_ObserversInExtent = new ObservableCollection(); + RLOS_ObserversOutOfExtent = new ObservableCollection(); + LLOS_ObserverLyrNames = new ObservableCollection(); + LLOS_TargetLyrNames = new ObservableCollection(); + RLOS_ObserverLyrNames = new ObservableCollection(); + ToolMode = MapPointToolMode.Unknown; SurfaceLayerNames = new ObservableCollection(); SelectedSurfaceName = string.Empty; @@ -53,6 +69,8 @@ public ProLOSBaseViewModel() DeletePointCommand = new RelayCommand(OnDeletePointCommand); DeleteAllPointsCommand = new RelayCommand(OnDeleteAllPointsCommand); EditPropertiesDialogCommand = new RelayCommand(OnEditPropertiesDialogCommand); + ImportCSVFileCommand = new RelayCommand(OnImportCSVFileCommand); + PasteCoordinatesCommand = new RelayCommand(OnPasteCommand); // subscribe to some mapping events ActiveMapViewChangedEvent.Subscribe(OnActiveMapViewChanged); @@ -125,6 +143,7 @@ public double? ObserverOffset throw new ArgumentException(VisibilityLibrary.Properties.Resources.AEInvalidInput); } } + private double? targetOffset; public double? TargetOffset { @@ -166,11 +185,102 @@ public MapPointToolMode ToolMode } } + public string EnterManullyOption { get; set; } + + public bool _isLLOSValidSelection { get; set; } + public bool IsLLOSValidSelection + { + get + { + return _isLLOSValidSelection; + } + set + { + _isLLOSValidSelection = value; + RaisePropertyChanged(() => IsLLOSValidSelection); + } + } + + private bool _isRLOSValidSelection { get; set; } + public bool IsRLOSValidSelection + { + get + { + return _isRLOSValidSelection; + } + set + { + _isRLOSValidSelection = value; + RaisePropertyChanged(() => IsRLOSValidSelection); + } + } + + private string _selectedLLOS_TargetLyrName; + public string SelectedLLOS_TargetLyrName + { + get + { + return _selectedLLOS_TargetLyrName; + } + set + { + _selectedLLOS_TargetLyrName = value; + ValidateLLOS_LayerSelection(); + RaisePropertyChanged(() => SelectedLLOS_TargetLyrName); + } + } + + private string _selectedLLOS_ObserverLyrName; + public string SelectedLLOS_ObserverLyrName + { + get + { + return _selectedLLOS_ObserverLyrName; + } + set + { + _selectedLLOS_ObserverLyrName = value; + ValidateLLOS_LayerSelection(); + RaisePropertyChanged(() => SelectedLLOS_ObserverLyrName); + } + } + + private string _selectedRLOS_ObserverLyrName; + public string SelectedRLOS_ObserverLyrName + { + get + { + return _selectedRLOS_ObserverLyrName; + } + set + { + _selectedRLOS_ObserverLyrName = value; + ValidateRLOS_LayerSelection(); + RaisePropertyChanged(() => SelectedRLOS_ObserverLyrName); + } + } + + public ObservableCollection LLOS_ObserverLyrNames { get; set; } + public ObservableCollection LLOS_TargetLyrNames { get; set; } + public ObservableCollection RLOS_ObserverLyrNames { get; set; } + public ObservableCollection LLOS_TargetsInExtent { get; set; } + public ObservableCollection LLOS_TargetsOutOfExtent { get; set; } + public ObservableCollection LLOS_ObserversInExtent { get; set; } + public ObservableCollection LLOS_ObserversOutOfExtent { get; set; } + public ObservableCollection RLOS_ObserversInExtent { get; set; } + public ObservableCollection RLOS_ObserversOutOfExtent { get; set; } + public ObservableCollection ObserverAddInPoints { get; set; } + public ObservableCollection ObserverInExtentPoints { get; set; } + public ObservableCollection ObserverOutExtentPoints { get; set; } + public ObservableCollection TargetAddInPoints { get; set; } + public ObservableCollection TargetInExtentPoints { get; set; } + public ObservableCollection TargetOutExtentPoints { get; set; } public ObservableCollection SurfaceLayerNames { get; set; } public string SelectedSurfaceName { get; set; } public DistanceTypes OffsetUnitType { get; set; } - public AngularTypes AngularUnitType { get; set; } + public DistanceTypes DistanceUnitType { get; set; } + public AngularTypes AngularUnitType { get; set; } #endregion @@ -179,6 +289,8 @@ public MapPointToolMode ToolMode public RelayCommand DeletePointCommand { get; set; } public RelayCommand DeleteAllPointsCommand { get; set; } public RelayCommand EditPropertiesDialogCommand { get; set; } + public RelayCommand ImportCSVFileCommand { get; set; } + public RelayCommand PasteCoordinatesCommand { get; set; } /// /// Command method to delete points @@ -214,6 +326,132 @@ private void OnEditPropertiesDialogCommand(object obj) dlg.ShowDialog(); } + public virtual void OnImportCSVFileCommand(object obj) + { + var mode = obj as string; + CoordinateConversionLibrary.Models.CoordinateConversionLibraryConfig.AddInConfig.DisplayAmbiguousCoordsDlg = false; + var fileDialog = new Microsoft.Win32.OpenFileDialog(); + fileDialog.CheckFileExists = true; + fileDialog.CheckPathExists = true; + fileDialog.Filter = "csv files|*.csv"; + + // attemp to import + var fieldVM = new CoordinateConversionLibrary.ViewModels.SelectCoordinateFieldsViewModel(); + var result = fileDialog.ShowDialog(); + if (result.HasValue && result.Value == true) + { + var dlg = new CoordinateConversionLibrary.Views.ProSelectCoordinateFieldsView(); + using (Stream s = new FileStream(fileDialog.FileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + { + var headers = CoordinateConversionLibrary.Helpers.ImportCSV.GetHeaders(s); + if (headers != null) + { + foreach (var header in headers) + { + fieldVM.AvailableFields.Add(header); + System.Diagnostics.Debug.WriteLine("header : {0}", header); + } + dlg.DataContext = fieldVM; + } + else + { + ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show(VisibilityLibrary.Properties.Resources.MsgNoDataFound, + VisibilityLibrary.Properties.Resources.CaptionError); + return; + } + } + if (dlg.ShowDialog() == true) + { + using (Stream s = new FileStream(fileDialog.FileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + { + var lists = CoordinateConversionLibrary.Helpers.ImportCSV.Import(s, fieldVM.SelectedFields.ToArray()); + + foreach (var item in lists) + { + string outFormattedString = string.Empty; + + var sb = new StringBuilder(); + sb.Append(item.lat.Trim()); + if (fieldVM.UseTwoFields) + sb.Append(string.Format(" {0}", item.lon.Trim())); + + string coordinate = sb.ToString(); + CoordinateConversionLibrary.Models.CoordinateType ccType = CoordinateConversionLibrary.Helpers.ConversionUtils.GetCoordinateString(coordinate, out outFormattedString); + if (ccType == CoordinateConversionLibrary.Models.CoordinateType.Unknown) + { + Regex regexMercator = new Regex(@"^(?\-?\d+\.?\d*)[+,;:\s]*(?\-?\d+\.?\d*)"); + var matchMercator = regexMercator.Match(coordinate); + if (matchMercator.Success && matchMercator.Length == coordinate.Length) + { + ccType = CoordinateConversionLibrary.Models.CoordinateType.DD; + } + } + MapPoint point = (ccType != CoordinateConversionLibrary.Models.CoordinateType.Unknown) ? GetMapPointFromString(outFormattedString) : null; + if (point != null) + { + if (mode == VisibilityLibrary.Properties.Resources.ToolModeObserver) + { + ToolMode = MapPointToolMode.Observer; + Point1 = point; + OnNewMapPointEvent(Point1); + } + else if (mode == VisibilityLibrary.Properties.Resources.ToolModeTarget) + { + ToolMode = MapPointToolMode.Target; + Point2 = point; + OnNewMapPointEvent(Point2); + } + } + } + } + } + } + } + + internal virtual void OnPasteCommand(object obj) + { + var mode = obj.ToString(); + + if (string.IsNullOrWhiteSpace(mode)) + return; + + var input = Clipboard.GetText().Trim(); + string[] lines = input.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None); + var coordinates = new List(); + foreach (var item in lines) + { + string outFormattedString = string.Empty; + string coordinate = item.Trim().ToString(); + CoordinateConversionLibrary.Models.CoordinateType ccType = CoordinateConversionLibrary.Helpers.ConversionUtils.GetCoordinateString(coordinate, out outFormattedString); + if (ccType == CoordinateConversionLibrary.Models.CoordinateType.Unknown) + { + Regex regexMercator = new Regex(@"^(?\-?\d+\.?\d*)[+,;:\s]*(?\-?\d+\.?\d*)"); + var matchMercator = regexMercator.Match(coordinate); + if (matchMercator.Success && matchMercator.Length == coordinate.Length) + { + ccType = CoordinateConversionLibrary.Models.CoordinateType.DD; + } + } + MapPoint point = (ccType != CoordinateConversionLibrary.Models.CoordinateType.Unknown) ? GetMapPointFromString(outFormattedString) : null; + if (point != null) + { + if (mode == VisibilityLibrary.Properties.Resources.ToolModeObserver) + { + ToolMode = MapPointToolMode.Observer; + Point1 = point; + OnNewMapPointEvent(Point1); + } + else if (mode == VisibilityLibrary.Properties.Resources.ToolModeTarget) + { + ToolMode = MapPointToolMode.Target; + Point2 = point; + OnNewMapPointEvent(Point2); + } + } + } + } + + /// /// Method used to delete points frome the view's observer listbox /// @@ -231,6 +469,8 @@ private void DeletePoints(List observers) foreach (var point in observers) { ObserverAddInPoints.Remove(point); + ObserverInExtentPoints.Remove(point); + ObserverOutExtentPoints.Remove(point); } } @@ -242,17 +482,23 @@ private void DeletePoints(List observers) /// Override OnKeyKeyCommand to handle manual input /// /// - internal override void OnEnterKeyCommand(object obj) + internal async override void OnEnterKeyCommand(object obj) { var keyCommandMode = obj as string; - if(keyCommandMode == VisibilityLibrary.Properties.Resources.ToolModeObserver) + if (keyCommandMode == VisibilityLibrary.Properties.Resources.ToolModeObserver) { + if (!(await IsValidPoint(Point1, true))) + return; + ToolMode = MapPointToolMode.Observer; OnNewMapPointEvent(Point1); } else if (keyCommandMode == VisibilityLibrary.Properties.Resources.ToolModeTarget) { + if (!(await IsValidPoint(Point2, true))) + return; + ToolMode = MapPointToolMode.Target; OnNewMapPointEvent(Point2); } @@ -300,25 +546,42 @@ internal override async void OnNewMapPointEvent(object obj) return; var point = obj as MapPoint; - - if (point == null || !(await IsValidPoint(point, true))) - return; - + // ok, we have a point - if (ToolMode == MapPointToolMode.Observer) + if (point != null && ToolMode == MapPointToolMode.Observer) { + if (IsMapClick) + { + if (!(await IsValidPoint(point, true))) + { + IsMapClick = false; + return; + } + } // in tool mode "Observer" we add observer points // otherwise ignore var guid = await AddGraphicToMap(point, ColorFactory.Instance.BlueRGB, true, 5.0); var addInPoint = new AddInPoint() { Point = point, GUID = guid }; + bool isValid = await IsValidPoint(point, false); Application.Current.Dispatcher.Invoke(() => { + if (!isValid) + { + ObserverOutExtentPoints.Insert(0, addInPoint); + } + else + { + ObserverInExtentPoints.Insert(0, addInPoint); + } + ObserverAddInPoints.Insert(0, addInPoint); }); + IsMapClick = false; } + } - + /// /// Method to update manual input boxes on mouse movement /// @@ -363,7 +626,7 @@ internal async Task IsValidPoint(MapPoint point, bool showPopup = false) // WORKAROUND/BUG: // QueryExtent() is taking several minutes to return from this call with ImageServiceLayer - // during which MCT can't do anything, so for now just return true, + // during which MCT can't do anything, so for now just return true, // fix this in the future when QueryExtent() or alternate works with ImageServiceLayer if (layer is ImageServiceLayer) { @@ -378,8 +641,7 @@ internal async Task IsValidPoint(MapPoint point, bool showPopup = false) validPoint = await IsPointWithinExtent(point, env); if (validPoint == false && showPopup) - ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show(VisibilityLibrary.Properties.Resources.MsgOutOfAOI, - VisibilityLibrary.Properties.Resources.CaptionError); + ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show(VisibilityLibrary.Properties.Resources.MsgOutOfAOI, VisibilityLibrary.Properties.Resources.CaptionError); } return validPoint; @@ -420,7 +682,7 @@ internal async Task IsPointWithinExtent(MapPoint point, Envelope env) /// /// string name of layer /// Layer - /// + /// internal Layer GetLayerFromMapByName(string name) { var layer = MapView.Active.Map.GetLayersAsFlattenedList().FirstOrDefault(l => l.Name == name); @@ -438,10 +700,10 @@ internal async Task> GetSurfaceNamesFromMap() var elevationSurfaceList = await QueuedTask.Run(() => { var list = new List(); - foreach(var layer in layerList) + foreach (var layer in layerList) { var def = layer.GetDefinition(); - if(def != null && def.LayerType == ArcGIS.Core.CIM.MapLayerType.Operational && + if (def != null && def.LayerType == ArcGIS.Core.CIM.MapLayerType.Operational && (def is CIMRasterLayer || def is CIMTinLayer || def is CIMLASDatasetLayer || def is CIMMosaicLayer)) { list.Add(layer); @@ -499,18 +761,19 @@ internal override async Task Reset(bool toolReset) { // reset observer points ObserverAddInPoints.Clear(); - + ObserverInExtentPoints.Clear(); + ObserverOutExtentPoints.Clear(); ClearTempGraphics(); }); } - catch(Exception ex) + catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.Message); } } /// - /// Method used to reset the currently selected surfacename + /// Method used to reset the currently selected surfacename /// Use when toc items or map changes, on tab selection changed, etc /// internal async Task ResetSurfaceNames() @@ -542,14 +805,89 @@ internal async Task ResetSurfaceNames() else SelectedSurfaceName = string.Empty; + await ResetLayerNames(); RaisePropertyChanged(() => SelectedSurfaceName); } - catch(Exception ex) + catch (Exception ex) { Debug.Print(ex.Message); } } + private async Task ResetLayerNames() + { + var layerNames = await GetLayerNamesFromMap(); + + var tempSelectedLLOS_ObserverLyr = SelectedLLOS_ObserverLyrName; + var tempLLOS_TargetLyrNames = SelectedLLOS_TargetLyrName; + var tempRLOS_ObserverLyrNames = SelectedRLOS_ObserverLyrName; + + ResetLayerNameCollections(layerNames); + + ResetSelectedLyrName(tempSelectedLLOS_ObserverLyr, tempLLOS_TargetLyrNames, tempRLOS_ObserverLyrNames); + } + + private void ResetSelectedLyrName(string tempSelectedLLOS_ObserverLyr, string tempLLOS_TargetLyrNames, string tempRLOS_ObserverLyrNames) + { + if (LLOS_ObserverLyrNames.Contains(tempSelectedLLOS_ObserverLyr)) + SelectedLLOS_ObserverLyrName = tempSelectedLLOS_ObserverLyr; + else if (LLOS_ObserverLyrNames.Any()) + SelectedLLOS_ObserverLyrName = LLOS_ObserverLyrNames[0]; + else + SelectedLLOS_ObserverLyrName = string.Empty; + + if (LLOS_TargetLyrNames.Contains(tempLLOS_TargetLyrNames)) + SelectedLLOS_TargetLyrName = tempLLOS_TargetLyrNames; + else if (LLOS_TargetLyrNames.Any()) + SelectedLLOS_TargetLyrName = LLOS_TargetLyrNames[0]; + else + SelectedLLOS_TargetLyrName = string.Empty; + + if (RLOS_ObserverLyrNames.Contains(tempRLOS_ObserverLyrNames)) + SelectedRLOS_ObserverLyrName = tempRLOS_ObserverLyrNames; + else if (RLOS_ObserverLyrNames.Any()) + SelectedRLOS_ObserverLyrName = RLOS_ObserverLyrNames[0]; + else + SelectedRLOS_ObserverLyrName = string.Empty; + } + + private void ResetLayerNameCollections(List layerNames) + { + Application.Current.Dispatcher.Invoke(() => + { + LLOS_ObserverLyrNames.Clear(); + LLOS_TargetLyrNames.Clear(); + RLOS_ObserverLyrNames.Clear(); + + LLOS_ObserverLyrNames.Add(EnterManullyOption); + LLOS_TargetLyrNames.Add(EnterManullyOption); + RLOS_ObserverLyrNames.Add(EnterManullyOption); + + foreach (var name in layerNames) + { + LLOS_ObserverLyrNames.Add(name); + LLOS_TargetLyrNames.Add(name); + RLOS_ObserverLyrNames.Add(name); + } + }); + } + + private Task> GetLayerNamesFromMap() + { + return QueuedTask.Run(() => + { + var layer = new List(); + try + { + layer = MapView.Active.Map.GetLayersAsFlattenedList().OfType() + .Where(l => l.ShapeType == esriGeometryType.esriGeometryPoint) + .Select(x => x.ToString()).ToList(); + } + catch (Exception) { } + return layer; + }); + } + /// /// Method to handle the display coordinate type change /// Need to update the list boxes @@ -558,9 +896,21 @@ internal async Task ResetSurfaceNames() internal virtual void OnDisplayCoordinateTypeChanged(object obj) { var list = ObserverAddInPoints.ToList(); + var inExtentList = ObserverInExtentPoints.ToList(); + var outExtentList = ObserverOutExtentPoints.ToList(); ObserverAddInPoints.Clear(); + ObserverInExtentPoints.Clear(); + ObserverOutExtentPoints.Clear(); + foreach (var item in list) ObserverAddInPoints.Add(item); + + foreach (var item in inExtentList) + ObserverInExtentPoints.Add(item); + + foreach (var item in outExtentList) + ObserverOutExtentPoints.Add(item); + RaisePropertyChanged(() => HasMapGraphics); } @@ -609,7 +959,7 @@ internal double GetAsMapUnits(SpatialReference sr, double value) if (mapUnit == null) return result; - var offsetLinearUnit = GetLinearUnit(OffsetUnitType); + var offsetLinearUnit = GetLinearUnit(DistanceUnitType); result = offsetLinearUnit.ConvertTo(value, mapUnit); @@ -634,7 +984,6 @@ private async void OnLayersAdded(LayerEventsArgs obj) await ResetSurfaceNames(); } - private async void OnMapPropertyChanged(MapPropertyChangedEventArgs obj) { await ResetSurfaceNames(); @@ -675,5 +1024,100 @@ internal LinearUnit GetLinearUnit(DistanceTypes dtype) return result; } + internal void ValidateLLOS_LayerSelection() + { + IsLLOSValidSelection = ( + ((SelectedLLOS_ObserverLyrName == EnterManullyOption || string.IsNullOrWhiteSpace(SelectedLLOS_ObserverLyrName)) + && ObserverAddInPoints.Count == 0 && LLOS_ObserversInExtent.Count == 0 && LLOS_ObserversOutOfExtent.Count == 0) + || + ((SelectedLLOS_TargetLyrName == EnterManullyOption || string.IsNullOrWhiteSpace(SelectedLLOS_TargetLyrName)) + && TargetAddInPoints.Count == 0 && LLOS_TargetsInExtent.Count == 0 && LLOS_TargetsOutOfExtent.Count == 0) + ) ? false : true; + } + + internal void ValidateRLOS_LayerSelection() + { + IsRLOSValidSelection = + ((SelectedRLOS_ObserverLyrName == EnterManullyOption || string.IsNullOrWhiteSpace(SelectedRLOS_ObserverLyrName)) + && ObserverAddInPoints.Count == 0 && RLOS_ObserversInExtent.Count == 0 && RLOS_ObserversOutOfExtent.Count == 0) ? false : true; + } + + internal async Task GetSurfaceEnvelope() + { + if (!string.IsNullOrWhiteSpace(SelectedSurfaceName) && MapView.Active != null && MapView.Active.Map != null) + { + var selectedSurface = GetLayerFromMapByName(SelectedSurfaceName); + + // WORKAROUND/BUG: + // QueryExtent() is taking several minutes to return from this call with ImageServiceLayer + // during which MCT can't do anything, so for now just return true, + // fix this in the future when QueryExtent() or alternate works with ImageServiceLayer + if (selectedSurface is ImageServiceLayer) + { + return null; + } + + var envelope = await QueuedTask.Run(() => + { + return selectedSurface.QueryExtent(); + }); + return envelope; + } + return null; + } + + internal async void ReadPointFromLayer(Envelope surfaceEnvelope, ObservableCollection inExtentPoints, + ObservableCollection outOfExtentPoints, string selectedLayerName, List selectedFeaturesCollections, string tag = "") + { + if (selectedLayerName != EnterManullyOption && !string.IsNullOrWhiteSpace(selectedLayerName)) + { + var layer = MapView.Active.Map.GetLayersAsFlattenedList().OfType() + .Where(lyr => lyr.Name == selectedLayerName && lyr.ShapeType == esriGeometryType.esriGeometryPoint).FirstOrDefault(); + var cursor = layer.GetFeatureClass().Search(); + + while (cursor.MoveNext()) + { + var point = (MapPoint)cursor.Current["Shape"]; + var addInPoint = new AddInPoint { Point = point, GUID = Guid.NewGuid().ToString() }; + var objectId = -1; + var FID = -1; + try + { + objectId = Convert.ToInt32(cursor.Current["ObjectId"]); + } + catch (Exception) { } + try + { + FID = Convert.ToInt32(cursor.Current["FID"]); + } + catch (Exception) { } + + var ID = objectId != -1 ? objectId : FID; + var isWithinEntent = await IsPointWithinExtent(point, surfaceEnvelope); + if (selectedFeaturesCollections == null || !selectedFeaturesCollections.Any() || + (selectedFeaturesCollections.Any() && selectedFeaturesCollections.Where(x => Convert.ToInt32(x) == ID).Any())) + { + if (isWithinEntent) + inExtentPoints.Add(new AddInPointObject() { ID = ID, AddInPoint = addInPoint }); + else + outOfExtentPoints.Add(new AddInPointObject() { ID = ID, AddInPoint = addInPoint }); + } + } + } + } + + internal void ClearLLOSCollections() + { + LLOS_TargetsInExtent.Clear(); + LLOS_TargetsOutOfExtent.Clear(); + LLOS_ObserversInExtent.Clear(); + LLOS_ObserversOutOfExtent.Clear(); + } + + internal void ClearRLOSCollections() + { + RLOS_ObserversInExtent.Clear(); + RLOS_ObserversOutOfExtent.Clear(); + } } } diff --git a/source/addins/ProAppVisibilityModule/ViewModels/ProRLOSViewModel.cs b/source/addins/ProAppVisibilityModule/ViewModels/ProRLOSViewModel.cs index fd5c0fb..dd70aa9 100644 --- a/source/addins/ProAppVisibilityModule/ViewModels/ProRLOSViewModel.cs +++ b/source/addins/ProAppVisibilityModule/ViewModels/ProRLOSViewModel.cs @@ -28,6 +28,10 @@ using ArcGIS.Core.Data; using ArcGIS.Desktop.Editing; using ArcGIS.Desktop.Framework.Threading.Tasks; +using System.Text.RegularExpressions; +using System.Collections.ObjectModel; +using ProAppVisibilityModule.Models; +using ArcGIS.Core.CIM; namespace ProAppVisibilityModule.ViewModels { @@ -35,27 +39,47 @@ public class ProRLOSViewModel : ProLOSBaseViewModel { #region Properties - private int executionCounter = 1; + private int executionCounter = 0; private string _ObserversLayerName = VisibilityLibrary.Properties.Resources.RLOSObserversLayerName; public string ObserversLayerName { - get + get { - _ObserversLayerName = string.Format("{0}_{1}", VisibilityLibrary.Properties.Resources.RLOSObserversLayerName, executionCounter); + if (executionCounter > 0) + { + _ObserversLayerName = string.Format("{0}_{1}", VisibilityLibrary.Properties.Resources.RLOSObserversLayerName, executionCounter); + } return _ObserversLayerName; } - set {} + set { } + } + + private string _FeatureDatasetName = VisibilityLibrary.Properties.Resources.RLOSFeatureDatasetName; + public string FeatureDatasetName + { + get + { + if (executionCounter > 0) + { + _FeatureDatasetName = string.Format("{0}_{1}", VisibilityLibrary.Properties.Resources.RLOSFeatureDatasetName, executionCounter); + } + return _FeatureDatasetName; + } + set { } } private string _RLOSConvertedPolygonsLayerName = VisibilityLibrary.Properties.Resources.RLOSConvertedPolygonsLayerName; public string RLOSConvertedPolygonsLayerName { - get + get { - _RLOSConvertedPolygonsLayerName = string.Format("{0}_{1}", VisibilityLibrary.Properties.Resources.RLOSConvertedPolygonsLayerName, executionCounter); + if (executionCounter > 0) + { + _RLOSConvertedPolygonsLayerName = string.Format("{0}_{1}", VisibilityLibrary.Properties.Resources.RLOSConvertedPolygonsLayerName, executionCounter); + } return _RLOSConvertedPolygonsLayerName; } - set {} + set { } } private string _RLOSOutputLayerName = VisibilityLibrary.Properties.Resources.RLOSOutputLayerName; @@ -63,7 +87,10 @@ public string RLOSOutputLayerName { get { - _RLOSOutputLayerName = string.Format("{0}_{1}", VisibilityLibrary.Properties.Resources.RLOSOutputLayerName, executionCounter); + if (executionCounter > 0) + { + _RLOSOutputLayerName = string.Format("{0}_{1}", VisibilityLibrary.Properties.Resources.RLOSOutputLayerName, executionCounter); + } return _RLOSOutputLayerName; } set { } @@ -74,19 +101,22 @@ public string RLOSMaskLayerName { get { - _RLOSMaskLayerName = string.Format("{0}_{1}", VisibilityLibrary.Properties.Resources.RLOSMaskLayerName, executionCounter); + if (executionCounter > 0) + { + _RLOSMaskLayerName = string.Format("{0}_{1}", VisibilityLibrary.Properties.Resources.RLOSMaskLayerName, executionCounter); + } return _RLOSMaskLayerName; } set { } } private double _SurfaceOffset = 0.0; - public double SurfaceOffset + public double SurfaceOffset { get { return _SurfaceOffset; } set { - if(value < 0.0) + if (value < 0.0) throw new ArgumentException(VisibilityLibrary.Properties.Resources.AEMustBePositive); _SurfaceOffset = value; @@ -95,15 +125,15 @@ public double SurfaceOffset } private double _MinDistance = 0.0; - public double MinDistance + public double MinDistance { get { return _MinDistance; } set { - if(value < 0.0) + if (value < 0.0) throw new ArgumentException(VisibilityLibrary.Properties.Resources.AEMustBePositive); - if(value > MaxDistance) + if (value > MaxDistance) throw new ArgumentException(VisibilityLibrary.Properties.Resources.AENumMustBeLess); _MinDistance = value; @@ -112,12 +142,12 @@ public double MinDistance } private double _MaxDistance = 1000.0; - public double MaxDistance + public double MaxDistance { get { return _MaxDistance; } set { - if(value < 0.0) + if (value < 0.0) throw new ArgumentException(VisibilityLibrary.Properties.Resources.AEMustBePositive); if (value < MinDistance) @@ -130,7 +160,7 @@ public double MaxDistance private double _LeftHorizontalFOV = 0.0; public double LeftHorizontalFOV - { + { get { return _LeftHorizontalFOV; } set { @@ -144,7 +174,7 @@ public double LeftHorizontalFOV } } private double _RightHorizontalFOV = 360.0; - public double RightHorizontalFOV + public double RightHorizontalFOV { get { return _RightHorizontalFOV; } set @@ -175,7 +205,7 @@ public double BottomVerticalFOV } private double _TopVerticalFOV = 90.0; - public double TopVerticalFOV + public double TopVerticalFOV { get { return _TopVerticalFOV; } set @@ -216,6 +246,7 @@ public Visibility DisplayProgressBar private async void OnSubmitCommand(object obj) { DisplayProgressBar = Visibility.Visible; + IsRLOSValidSelection = false; await CreateMapElement(); DisplayProgressBar = Visibility.Hidden; } @@ -252,11 +283,13 @@ public ProRLOSViewModel() internal override void OnDeletePointCommand(object obj) { base.OnDeletePointCommand(obj); + ValidateRLOS_LayerSelection(); } internal override void OnDeleteAllPointsCommand(object obj) { base.OnDeleteAllPointsCommand(obj); + ValidateRLOS_LayerSelection(); } public override bool CanCreateElement @@ -264,7 +297,9 @@ public override bool CanCreateElement get { return (!string.IsNullOrWhiteSpace(SelectedSurfaceName) - && ObserverAddInPoints.Any()); + && (ObserverAddInPoints.Any() + || RLOS_ObserversInExtent.Any() + || RLOS_ObserversOutOfExtent.Any())); } } @@ -276,17 +311,26 @@ internal override async Task CreateMapElement() try { IsRunning = true; + await ReadSelectedLayers(); if (!CanCreateElement || MapView.Active == null || MapView.Active.Map == null || string.IsNullOrWhiteSpace(SelectedSurfaceName)) return; - bool success = await ExecuteVisibilityRLOS(); + if (RLOS_ObserversInExtent.Any() || ObserverAddInPoints.Any()) + { + bool success = await ExecuteVisibilityRLOS(); - if (!success) - MessageBox.Show("LLOS computations did not complete correctly.\nPlease check your parameters and try again.", - VisibilityLibrary.Properties.Resources.CaptionError); + if (!success) + MessageBox.Show("RLOS computations did not complete correctly.\nPlease check your parameters and try again.", + VisibilityLibrary.Properties.Resources.CaptionError); + } + else + { + ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show(VisibilityLibrary.Properties.Resources.OutOfExtentMsg, VisibilityLibrary.Properties.Resources.OutOfExtentHeader); + } DeactivateTool(VisibilityMapTool.ToolId); + OnMapPointToolDeactivated(null); //await base.CreateMapElement(); } @@ -299,6 +343,13 @@ internal override async Task CreateMapElement() finally { IsRunning = false; + if (ObserverAddInPoints.Count == 0) + IsRLOSValidSelection = false; + else + IsRLOSValidSelection = true; + + ClearRLOSCollections(); + ValidateRLOS_LayerSelection(); } } @@ -314,12 +365,13 @@ private async Task ExecuteVisibilityRLOS() { // Check surface spatial reference var surfaceSR = await GetSpatialReferenceFromLayer(SelectedSurfaceName); - if(surfaceSR == null || !surfaceSR.IsProjected) + if (surfaceSR == null || !surfaceSR.IsProjected) { MessageBox.Show(VisibilityLibrary.Properties.Resources.RLOSUserPrompt, VisibilityLibrary.Properties.Resources.RLOSUserPromptCaption); return false; } + var observerPoints = new ObservableCollection(RLOS_ObserversInExtent.Select(x => x.AddInPoint).Union(ObserverInExtentPoints)); // Warn if Image Service layer Layer surfaceLayer = GetLayerFromMapByName(SelectedSurfaceName); if (surfaceLayer is ImageServiceLayer) @@ -334,7 +386,44 @@ private async Task ExecuteVisibilityRLOS() } } - success = await FeatureClassHelper.CreateLayer(ObserversLayerName, "POINT", true, true); + //Validate Dataframe Spatial reference with surface spatial reference + if (MapView.Active.Map.SpatialReference.Wkid != surfaceSR.Wkid) + { + MessageBox.Show(VisibilityLibrary.Properties.Resources.LOSDataFrameMatch, VisibilityLibrary.Properties.Resources.LOSSpatialReferenceCaption); + return false; + } + + await ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run(() => + { + using (Geodatabase geodatabase = new Geodatabase(new FileGeodatabaseConnectionPath(new Uri(CoreModule.CurrentProject.DefaultGeodatabasePath)))) + { + executionCounter = 0; + int featureDataSetSuffix = 0; + var enterpriseDefinitionNames = geodatabase.GetDefinitions().Where(i => i.GetName().StartsWith(VisibilityLibrary.Properties.Resources.RLOSFeatureDatasetName)).Select(i => i.GetName()).ToList(); + foreach (var defName in enterpriseDefinitionNames) + { + int n; + bool isNumeric = int.TryParse(Regex.Match(defName, @"\d+$").Value, out n); + if (isNumeric) + featureDataSetSuffix = featureDataSetSuffix < n ? n : featureDataSetSuffix; + } + featureDataSetSuffix = enterpriseDefinitionNames.Count > 0 ? featureDataSetSuffix + 1 : 0; + + var observerLyrSuffix = GetLayerSuffix(VisibilityLibrary.Properties.Resources.LLOSObserversLayerName, geodatabase); + var convertedPolygonLyrSuffix = GetLayerSuffix(VisibilityLibrary.Properties.Resources.RLOSConvertedPolygonsLayerName, geodatabase); + var outputLyrSuffix = GetLayerSuffix(VisibilityLibrary.Properties.Resources.RLOSOutputLayerName, geodatabase); + var maskLyrSuffix = GetLayerSuffix(VisibilityLibrary.Properties.Resources.RLOSMaskLayerName, geodatabase); + + executionCounter = new List { featureDataSetSuffix, observerLyrSuffix, convertedPolygonLyrSuffix, outputLyrSuffix, maskLyrSuffix }.Max(); + } + }); + + //Create Feature dataset + success = await FeatureClassHelper.CreateFeatureDataset(FeatureDatasetName); + if (!success) + return false; + + success = await FeatureClassHelper.CreateLayer(FeatureDatasetName, ObserversLayerName, "POINT", true, true); if (!success) return false; @@ -342,77 +431,102 @@ private async Task ExecuteVisibilityRLOS() await FeatureClassHelper.AddFieldToLayer(ObserversLayerName, VisibilityLibrary.Properties.Resources.OffsetFieldName, "DOUBLE"); await FeatureClassHelper.AddFieldToLayer(ObserversLayerName, VisibilityLibrary.Properties.Resources.OffsetWithZFieldName, "DOUBLE"); + await FeatureClassHelper.AddFieldToLayer(ObserversLayerName, VisibilityLibrary.Properties.Resources.IsOutOfExtentFieldName, "SHORT"); // add observer points to feature layer + await FeatureClassHelper.CreatingFeatures(ObserversLayerName, observerPoints, GetAsMapZUnits(surfaceSR, ObserverOffset.Value)); - await FeatureClassHelper.CreatingFeatures(ObserversLayerName, ObserverAddInPoints, GetAsMapZUnits(surfaceSR, ObserverOffset.Value)); + //execute only if points are available in surface extent + if (ObserverInExtentPoints.Any() || RLOS_ObserversInExtent.Any()) + { + // update with surface information + success = await FeatureClassHelper.AddSurfaceInformation(ObserversLayerName, SelectedSurfaceName, VisibilityLibrary.Properties.Resources.ZFieldName); + if (!success) + return false; - // update with surface information + // Visibility - success = await FeatureClassHelper.AddSurfaceInformation(ObserversLayerName, SelectedSurfaceName, VisibilityLibrary.Properties.Resources.ZFieldName); - if (!success) - return false; + var observerOffsetInMapZUnits = GetAsMapZUnits(surfaceSR, ObserverOffset.Value); + var surfaceOffsetInMapZUnits = GetAsMapZUnits(surfaceSR, SurfaceOffset); + var minDistanceInMapUnits = GetAsMapUnits(surfaceSR, MinDistance); + var maxDistanceInMapUnits = GetAsMapUnits(surfaceSR, MaxDistance); + var horizontalStartAngleInDegrees = GetAngularDistanceFromTo(AngularUnitType, AngularTypes.DEGREES, LeftHorizontalFOV); + var horizontalEndAngleInDegrees = GetAngularDistanceFromTo(AngularUnitType, AngularTypes.DEGREES, RightHorizontalFOV); + var verticalUpperAngleInDegrees = GetAngularDistanceFromTo(AngularUnitType, AngularTypes.DEGREES, TopVerticalFOV); + var verticalLowerAngleInDegrees = GetAngularDistanceFromTo(AngularUnitType, AngularTypes.DEGREES, BottomVerticalFOV); - // Visibility + await FeatureClassHelper.UpdateShapeWithZ(ObserversLayerName, VisibilityLibrary.Properties.Resources.ZFieldName, observerOffsetInMapZUnits); - var observerOffsetInMapZUnits = GetAsMapZUnits(surfaceSR, ObserverOffset.Value); - var surfaceOffsetInMapZUnits = GetAsMapZUnits(surfaceSR, SurfaceOffset); - var minDistanceInMapUnits = GetAsMapUnits(surfaceSR, MinDistance); - var maxDistanceInMapUnits = GetAsMapUnits(surfaceSR, MaxDistance); - var horizontalStartAngleInDegrees = GetAngularDistanceFromTo(AngularUnitType, AngularTypes.DEGREES, LeftHorizontalFOV); - var horizontalEndAngleInDegrees = GetAngularDistanceFromTo(AngularUnitType, AngularTypes.DEGREES, RightHorizontalFOV); - var verticalUpperAngleInDegrees = GetAngularDistanceFromTo(AngularUnitType, AngularTypes.DEGREES, TopVerticalFOV); - var verticalLowerAngleInDegrees = GetAngularDistanceFromTo(AngularUnitType, AngularTypes.DEGREES, BottomVerticalFOV); + await CreateMask(RLOSMaskLayerName, minDistanceInMapUnits, maxDistanceInMapUnits, horizontalStartAngleInDegrees, + horizontalEndAngleInDegrees, surfaceSR, observerPoints); - await FeatureClassHelper.UpdateShapeWithZ(ObserversLayerName, VisibilityLibrary.Properties.Resources.ZFieldName, observerOffsetInMapZUnits); + string maxRangeMaskFeatureClassName = CoreModule.CurrentProject.DefaultGeodatabasePath + System.IO.Path.DirectorySeparatorChar + FeatureDatasetName + System.IO.Path.DirectorySeparatorChar + RLOSMaskLayerName; + var environments = Geoprocessing.MakeEnvironmentArray(mask: maxRangeMaskFeatureClassName, overwriteoutput: true); - await CreateMask(RLOSMaskLayerName, minDistanceInMapUnits, maxDistanceInMapUnits, horizontalStartAngleInDegrees, - horizontalEndAngleInDegrees, surfaceSR); + var rlosOutputLayer = CoreModule.CurrentProject.DefaultGeodatabasePath + System.IO.Path.DirectorySeparatorChar + RLOSOutputLayerName; - string maxRangeMaskFeatureClassName = CoreModule.CurrentProject.DefaultGeodatabasePath + System.IO.Path.DirectorySeparatorChar + RLOSMaskLayerName; - var environments = Geoprocessing.MakeEnvironmentArray(mask: maxRangeMaskFeatureClassName, overwriteoutput: true); - var rlosOutputLayer = CoreModule.CurrentProject.DefaultGeodatabasePath + System.IO.Path.DirectorySeparatorChar + RLOSOutputLayerName; + success = await FeatureClassHelper.CreateVisibility(SelectedSurfaceName, ObserversLayerName, + rlosOutputLayer, + observerOffsetInMapZUnits, surfaceOffsetInMapZUnits, + minDistanceInMapUnits, maxDistanceInMapUnits, + horizontalStartAngleInDegrees, horizontalEndAngleInDegrees, + verticalUpperAngleInDegrees, verticalLowerAngleInDegrees, + ShowNonVisibleData, + environments, + false); - success = await FeatureClassHelper.CreateVisibility(SelectedSurfaceName, ObserversLayerName, - rlosOutputLayer, - observerOffsetInMapZUnits, surfaceOffsetInMapZUnits, - minDistanceInMapUnits, maxDistanceInMapUnits, - horizontalStartAngleInDegrees, horizontalEndAngleInDegrees, - verticalUpperAngleInDegrees, verticalLowerAngleInDegrees, - ShowNonVisibleData, - environments, - false); + if (!success) + return false; - if (!success) - return false; + var rlosConvertedPolygonsLayer = CoreModule.CurrentProject.DefaultGeodatabasePath + System.IO.Path.DirectorySeparatorChar + FeatureDatasetName + System.IO.Path.DirectorySeparatorChar + RLOSConvertedPolygonsLayerName; - var rlosConvertedPolygonsLayer = CoreModule.CurrentProject.DefaultGeodatabasePath + System.IO.Path.DirectorySeparatorChar + RLOSConvertedPolygonsLayerName; + string rangeFanMaskFeatureClassName = string.Empty; + if ((MinDistance > 0) || !((horizontalStartAngleInDegrees == 0.0) && (horizontalEndAngleInDegrees == 360.0))) + { + string RLOSRangeFanMaskLayerName = "RangeFan_" + RLOSMaskLayerName; + rangeFanMaskFeatureClassName = CoreModule.CurrentProject.DefaultGeodatabasePath + System.IO.Path.DirectorySeparatorChar + FeatureDatasetName + System.IO.Path.DirectorySeparatorChar + RLOSRangeFanMaskLayerName; - string rangeFanMaskFeatureClassName = string.Empty; - if ((MinDistance > 0) || !((horizontalStartAngleInDegrees == 0.0) && (horizontalEndAngleInDegrees == 360.0))) - { - string RLOSRangeFanMaskLayerName = "RangeFan_" + RLOSMaskLayerName; - rangeFanMaskFeatureClassName = CoreModule.CurrentProject.DefaultGeodatabasePath + System.IO.Path.DirectorySeparatorChar + RLOSRangeFanMaskLayerName; + await CreateMask(RLOSRangeFanMaskLayerName, minDistanceInMapUnits, maxDistanceInMapUnits, horizontalStartAngleInDegrees, + horizontalEndAngleInDegrees, surfaceSR, observerPoints, true); + } - await CreateMask(RLOSRangeFanMaskLayerName, minDistanceInMapUnits, maxDistanceInMapUnits, horizontalStartAngleInDegrees, - horizontalEndAngleInDegrees, surfaceSR, true); + success = await FeatureClassHelper.IntersectOutput(rlosOutputLayer, rlosConvertedPolygonsLayer, false, "Value", rangeFanMaskFeatureClassName); + if (!success) + return false; } - success = await FeatureClassHelper.IntersectOutput(rlosOutputLayer, rlosConvertedPolygonsLayer, false, "Value", rangeFanMaskFeatureClassName); - if (!success) - return false; + // add observer points present out of extent to feature layer + var outOfExtent = new ObservableCollection(RLOS_ObserversOutOfExtent.Select(x => x.AddInPoint).Union(ObserverOutExtentPoints)); + await FeatureClassHelper.CreatingFeatures(ObserversLayerName, outOfExtent, GetAsMapZUnits(surfaceSR, ObserverOffset.Value), VisibilityLibrary.Properties.Resources.IsOutOfExtentFieldName); await FeatureClassHelper.CreateUniqueValueRenderer(GetLayerFromMapByName(RLOSConvertedPolygonsLayerName) as FeatureLayer, ShowNonVisibleData, RLOSConvertedPolygonsLayerName); + var observersLayer = GetLayerFromMapByName(ObserversLayerName) as FeatureLayer; + + if (observersLayer != null) + { + await FeatureClassHelper.CreateRLOSObserversRenderer(observersLayer as FeatureLayer); + } + + await FeatureClassHelper.Delete(RLOSOutputLayerName); + //await FeatureClassHelper.Delete(RLOSMaskLayerName); + // Eventually we will add the new layers to a new group layer for each run // Currently not working in current release of Pro. // From Roshan Herbert - I just spoke with the Dev who wrote the MoveLayer method. Apparently this a known issue. // We have bug to fix this and plan to fix it in the next release. List layerList = new List(); - layerList.Add(GetLayerFromMapByName(ObserversLayerName)); - //layerList.Add(GetLayerFromMapByName(RLOSConvertedPolygonsLayerName)); + var observersLayerFromMap = GetLayerFromMapByName(ObserversLayerName); + var RLOSConvertedPolygonsLayer = GetLayerFromMapByName(RLOSConvertedPolygonsLayerName); + + if (observersLayerFromMap != null) + layerList.Add(observersLayerFromMap); + if (RLOSConvertedPolygonsLayer != null) + layerList.Add(GetLayerFromMapByName(RLOSConvertedPolygonsLayerName)); + await FeatureClassHelper.MoveLayersToGroupLayer(layerList, FeatureDatasetName); + //string groupName = "RLOS Group"; //if (executionCounter > 0) // groupName = string.Format("{0}_{1}", groupName, executionCounter.ToString()); @@ -430,8 +544,8 @@ await CreateMask(RLOSRangeFanMaskLayerName, minDistanceInMapUnits, maxDistanceIn await ZoomToExtent(envelope); } - executionCounter++; - + var surfaceEnvelope = await GetSurfaceEnvelope(); + await DisplayOutOfExtentMsg(); success = true; } catch (Exception ex) @@ -443,6 +557,57 @@ await CreateMask(RLOSRangeFanMaskLayerName, minDistanceInMapUnits, maxDistanceIn return success; } + private int GetLayerSuffix(string layerName, Geodatabase geodatabase) + { + int counter = 0; + var enterpriseFCNames = geodatabase.GetDefinitions().Where(i => i.GetName().StartsWith(layerName)).Select(i => i.GetName()).ToList(); + foreach (var fcName in enterpriseFCNames) + { + int n; + bool isNumeric = int.TryParse(Regex.Match(fcName, @"\d+$").Value, out n); + if (isNumeric) + counter = counter < n ? n : counter; + } + counter = enterpriseFCNames.Count > 0 ? counter + 1 : 0; + return counter; + } + + private async Task DisplayOutOfExtentMsg() + { + await QueuedTask.Run(() => + { + var observerIDCollection = RLOS_ObserversOutOfExtent.Select(x => x.ID).ToList(); + var observerString = string.Empty; + var targetString = string.Empty; + foreach (var item in observerIDCollection) + { + if (observerString == "") + observerString = item.ToString(); + else + observerString = observerString + "," + item.ToString(); + } + if (observerIDCollection.Any()) + { + if (observerIDCollection.Count <= 10) + { + var msgString = string.Empty; + if (observerIDCollection.Any()) + { + msgString = "Observers lying outside the extent of elevation surface are: " + observerString; + } + ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show(msgString, + "Unable To Process For Few Locations"); + } + else + { + ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show(VisibilityLibrary.Properties.Resources.LLOSPointsOutsideOfSurfaceExtent, + VisibilityLibrary.Properties.Resources.MsgCalcCancelled); + } + + } + }); + } + /// /// Method used to create a mask for geoprocessing environment /// Will buffer around each observer at the max distance to create mask @@ -450,13 +615,14 @@ await CreateMask(RLOSRangeFanMaskLayerName, minDistanceInMapUnits, maxDistanceIn /// /// /// Task - private async Task CreateMask(string maskFeatureClassName, - double minDistanceInMapUnits, double maxDistanceInMapUnits, - double horizontalStartAngleInDegrees, double horizontalEndAngleInDegrees, - SpatialReference surfaceSR, bool constructRangeFans = false) + private async Task CreateMask(string maskFeatureClassName, + double minDistanceInMapUnits, double maxDistanceInMapUnits, + double horizontalStartAngleInDegrees, double horizontalEndAngleInDegrees, + SpatialReference surfaceSR, ObservableCollection observerPoints, + bool constructRangeFans = false) { // create new - await FeatureClassHelper.CreateLayer(maskFeatureClassName, "POLYGON", false, false); + await FeatureClassHelper.CreateLayer(FeatureDatasetName, maskFeatureClassName, "POLYGON", false, false); try { @@ -471,42 +637,42 @@ await ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run(async () => EditOperation editOperation = new EditOperation(); editOperation.Callback(context => { - try - { - var shapeFieldName = fcDefinition.GetShapeField(); - - foreach (var observer in ObserverAddInPoints) + try { - using (var rowBuffer = enterpriseFeatureClass.CreateRowBuffer()) - { - // Either the field index or the field name can be used in the indexer. - // project the point here or the buffer tool may use an angular unit and run forever - var point = GeometryEngine.Instance.Project(observer.Point, surfaceSR); - Geometry polygon = null; + var shapeFieldName = fcDefinition.GetShapeField(); - if (constructRangeFans) - { - polygon = GeometryHelper.ConstructRangeFan(point as MapPoint, - minDistanceInMapUnits, maxDistanceInMapUnits, horizontalStartAngleInDegrees, - horizontalEndAngleInDegrees, surfaceSR); - } - else + foreach (var observer in observerPoints) + { + using (var rowBuffer = enterpriseFeatureClass.CreateRowBuffer()) { - polygon = GeometryEngine.Instance.Buffer(point, maxDistanceInMapUnits); - } - - rowBuffer[shapeFieldName] = polygon; - - Feature feature = enterpriseFeatureClass.CreateRow(rowBuffer); - feature.Store(); - context.Invalidate(feature); - } // using - } // for each - } - catch (GeodatabaseException exObj) - { - message = exObj.Message; - } + // Either the field index or the field name can be used in the indexer. + // project the point here or the buffer tool may use an angular unit and run forever + var point = GeometryEngine.Instance.Project(observer.Point, surfaceSR); + Geometry polygon = null; + + if (constructRangeFans) + { + polygon = GeometryHelper.ConstructRangeFan(point as MapPoint, + minDistanceInMapUnits, maxDistanceInMapUnits, horizontalStartAngleInDegrees, + horizontalEndAngleInDegrees, surfaceSR); + } + else + { + polygon = GeometryEngine.Instance.Buffer(point, maxDistanceInMapUnits); + } + + rowBuffer[shapeFieldName] = polygon; + + Feature feature = enterpriseFeatureClass.CreateRow(rowBuffer); + feature.Store(); + context.Invalidate(feature); + } // using + } // for each + } + catch (GeodatabaseException exObj) + { + message = exObj.Message; + } }, enterpriseFeatureClass); creationResult = await editOperation.ExecuteAsync(); @@ -560,6 +726,22 @@ private double GetAngularDistanceFromTo(AngularTypes fromType, AngularTypes toTy return Math.Round(angularDistance, 1); } + private async Task ReadSelectedLayers() + { + var observerPoints = new ObservableCollection(); + RLOS_ObserversInExtent.Clear(); + RLOS_ObserversOutOfExtent.Clear(); + + var surfaceEnvelope = await GetSurfaceEnvelope(); + var selectedFeatures = await QueuedTask.Run(() => { return MapView.Active.Map.GetSelection(); }); + await QueuedTask.Run(() => + { + var selectedFeaturesCollections = selectedFeatures.Where(x => x.Key.Name == SelectedRLOS_ObserverLyrName) + .Select(x => x.Value).FirstOrDefault(); + ReadPointFromLayer(surfaceEnvelope, RLOS_ObserversInExtent, RLOS_ObserversOutOfExtent, SelectedRLOS_ObserverLyrName, selectedFeaturesCollections); + }); + } + #endregion Private } } diff --git a/source/addins/ProAppVisibilityModule/ViewModels/ProTabBaseViewModel.cs b/source/addins/ProAppVisibilityModule/ViewModels/ProTabBaseViewModel.cs index 6909be7..11f7067 100644 --- a/source/addins/ProAppVisibilityModule/ViewModels/ProTabBaseViewModel.cs +++ b/source/addins/ProAppVisibilityModule/ViewModels/ProTabBaseViewModel.cs @@ -50,7 +50,8 @@ public ProTabBaseViewModel() CancelCommand = new VisibilityLibrary.Helpers.RelayCommand(OnCancelCommand); // Mediator - Mediator.Register(VisibilityLibrary.Constants.NEW_MAP_POINT, OnNewMapPointEvent); + Mediator.Register(VisibilityLibrary.Constants.NEW_MAP_POINT, OnMapClickEvent); + Mediator.Register(VisibilityLibrary.Constants.NEW_MAP_POINT, OnNewMapPointEvent); Mediator.Register(VisibilityLibrary.Constants.MOUSE_MOVE_POINT, OnMouseMoveEvent); Mediator.Register(VisibilityLibrary.Constants.TAB_ITEM_SELECTED, OnTabItemSelected); @@ -322,7 +323,7 @@ public bool IsActiveTab { await Reset(true); }); - + isActiveTab = value; RaisePropertyChanged(() => IsActiveTab); } @@ -347,6 +348,7 @@ public virtual bool CanCreateElement public VisibilityLibrary.Helpers.RelayCommand EnterKeyCommand { get; set; } public VisibilityLibrary.Helpers.RelayCommand CancelCommand { get; set; } public VisibilityLibrary.Helpers.RelayCommand ActivateToolCommand { get; set; } + public bool IsMapClick { get; set; } /// /// Clears all the graphics from the maps graphic container @@ -371,7 +373,7 @@ private void OnClearGraphics(object obj) RaisePropertyChanged(() => HasMapGraphics); } - catch(Exception ex) + catch (Exception ex) { Debug.Print(ex.Message); } @@ -436,6 +438,11 @@ internal virtual void OnNewMapPointEvent(object obj) // do nothing } + internal virtual void OnMapClickEvent(object obj) + { + IsMapClick = true; + } + #endregion #region Internal Methods @@ -449,7 +456,7 @@ internal void RemoveGraphics(List guidList) var list = ProGraphicsList.Where(g => guidList.Contains(g.GUID)).ToList(); foreach (var graphic in list) { - if(graphic.Disposable != null) + if (graphic.Disposable != null) graphic.Disposable.Dispose(); ProGraphicsList.Remove(graphic); } @@ -488,7 +495,7 @@ internal void ClearTempGraphics() RaisePropertyChanged(() => HasMapGraphics); } - + /// /// Method used to totally reset the tool /// reset points, feedback @@ -580,7 +587,7 @@ internal MapPoint GetMapPointFromString(string coordinate) var Lon = Double.Parse(matchMercator.Groups["longitude"].Value); point = QueuedTask.Run(() => { - return MapPointBuilder.CreateMapPoint(Lon, Lat); + return MapPointBuilder.CreateMapPoint(Lon, Lat, MapView.Active.Map.SpatialReference); }).Result; return point; } @@ -613,7 +620,7 @@ internal async Task AddGraphicToMap(Geometry geom, CIMColor color, bool await QueuedTask.Run(() => { // TODO add text graphic - //var tg = new CIMTextGraphic() { Placement = Anchor.CenterPoint, Text = text}; + //var tg = new CIMTextGraphic() { Placement = Anchor.CenterPoint, Text = text}; }); } else if (geom.GeometryType == GeometryType.Point) @@ -704,6 +711,7 @@ private void OnTabItemSelected(object obj) return; IsActiveTab = (obj == this); + IsMapClick = false; } /// diff --git a/source/addins/ProAppVisibilityModule/Views/ProSelectCoordinateFieldsView.xaml b/source/addins/ProAppVisibilityModule/Views/ProSelectCoordinateFieldsView.xaml new file mode 100644 index 0000000..552fa5a --- /dev/null +++ b/source/addins/ProAppVisibilityModule/Views/ProSelectCoordinateFieldsView.xaml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - + + + + + + + - - - - - + + + + - - - - - - + + + + + + + +