private async Task <bool> ExecuteVisibilityLLOS() { bool success = false; try { // Check surface spatial reference var surfaceSR = await GetSpatialReferenceFromLayer(SelectedSurfaceName); 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); } if (string.IsNullOrEmpty(SelectedSurfaceName)) { MessageBox.Show(VisibilityLibrary.Properties.Resources.MsgSurfaceLayerNotFound, VisibilityLibrary.Properties.Resources.CaptionError, MessageBoxButton.OK); return(true); } //Validate Dataframe Spatial reference with surface spatial reference IsElevationSurfaceValid = ValidateElevationSurface(MapView.Active.Map, SelectedSurfaceName); if (!await IsElevationSurfaceValid) { ArcGIS.Desktop.Framework.Dialogs.MessageBox.Show(VisibilityLibrary.Properties.Resources.LOSDataFrameMatch, VisibilityLibrary.Properties.Resources.LOSSpatialReferenceCaption); SetErrorTemplate(false); return(true); } else { SetErrorTemplate(true); } var observerPoints = new ObservableCollection <AddInPoint>(LLOS_ObserversInExtent.Select(x => x.AddInPoint).Union(ObserverInExtentPoints)); var targetPoints = new ObservableCollection <AddInPoint>(LLOS_TargetsInExtent.Select(x => x.AddInPoint).Union(TargetInExtentPoints)); // Warn if Image Service layer Layer surfaceLayer = GetLayerFromMapByName(SelectedSurfaceName); if (surfaceLayer is ImageServiceLayer) { MessageBoxResult mbr = MessageBox.Show(VisibilityLibrary.Properties.Resources.MsgLayerIsImageService, VisibilityLibrary.Properties.Resources.CaptionLayerIsImageService, MessageBoxButton.YesNo); if (mbr == MessageBoxResult.No) { System.Windows.MessageBox.Show(VisibilityLibrary.Properties.Resources.MsgTryAgain, VisibilityLibrary.Properties.Resources.MsgCalcCancelled); 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 <FeatureDatasetDefinition>().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 <int> { 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 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.TarIsVisFieldName, "SHORT"); success = await FeatureClassHelper.CreateLayer(FeatureDatasetName, TargetsLayerName, "POINT", true, true); if (!success) { return(false); } // add fields for target offset await FeatureClassHelper.AddFieldToLayer(TargetsLayerName, VisibilityLibrary.Properties.Resources.OffsetFieldName, "DOUBLE"); await FeatureClassHelper.AddFieldToLayer(TargetsLayerName, VisibilityLibrary.Properties.Resources.OffsetWithZFieldName, "DOUBLE"); await FeatureClassHelper.AddFieldToLayer(TargetsLayerName, VisibilityLibrary.Properties.Resources.NumOfObserversFieldName, "SHORT"); // add observer points to feature layer await FeatureClassHelper.CreatingFeatures(ObserversLayerName, observerPoints, GetAsMapZUnits(surfaceSR, ObserverOffset.Value)); // add target points to feature layer await FeatureClassHelper.CreatingFeatures(TargetsLayerName, targetPoints, GetAsMapZUnits(surfaceSR, TargetOffset.Value)); // update with surface information success = await FeatureClassHelper.AddSurfaceInformation(ObserversLayerName, SelectedSurfaceName, VisibilityLibrary.Properties.Resources.ZFieldName); if (!success) { return(false); } success = await FeatureClassHelper.AddSurfaceInformation(TargetsLayerName, SelectedSurfaceName, VisibilityLibrary.Properties.Resources.ZFieldName); if (!success) { return(false); } await FeatureClassHelper.UpdateShapeWithZ(ObserversLayerName, VisibilityLibrary.Properties.Resources.ZFieldName, GetAsMapZUnits(surfaceSR, ObserverOffset.Value)); await FeatureClassHelper.UpdateShapeWithZ(TargetsLayerName, VisibilityLibrary.Properties.Resources.ZFieldName, GetAsMapZUnits(surfaceSR, TargetOffset.Value)); // create sight lines GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); success = await FeatureClassHelper.CreateSightLines(ObserversLayerName, TargetsLayerName, CoreModule.CurrentProject.DefaultGeodatabasePath + System.IO.Path.DirectorySeparatorChar + FeatureDatasetName + System.IO.Path.DirectorySeparatorChar + SightLinesLayerName, VisibilityLibrary.Properties.Resources.OffsetWithZFieldName, VisibilityLibrary.Properties.Resources.OffsetWithZFieldName); if (!success) { return(false); } // LOS GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); success = await FeatureClassHelper.CreateLOS(SelectedSurfaceName, 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); } GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); // join fields with sight lines await FeatureClassHelper.JoinField(CoreModule.CurrentProject.DefaultGeodatabasePath + System.IO.Path.DirectorySeparatorChar + FeatureDatasetName + System.IO.Path.DirectorySeparatorChar + SightLinesLayerName, "OID", CoreModule.CurrentProject.DefaultGeodatabasePath + System.IO.Path.DirectorySeparatorChar + FeatureDatasetName + System.IO.Path.DirectorySeparatorChar + OutputLayerName, "SourceOID", new string[] { "TarIsVis" }); // gather results for updating observer and target layers var sourceOIDs = await FeatureClassHelper.GetSourceOIDs(OutputLayerName); //if (sourceOIDs.Count > 0) //{ var visStats = await FeatureClassHelper.GetVisibilityStats(sourceOIDs, SightLinesLayerName); await FeatureClassHelper.UpdateLayersWithVisibilityStats(visStats, ObserversLayerName, TargetsLayerName); //} var observersLayer = GetLayerFromMapByName(ObserversLayerName) as FeatureLayer; var targetsLayer = GetLayerFromMapByName(TargetsLayerName) as FeatureLayer; var sightLinesLayer = GetLayerFromMapByName(SightLinesLayerName) as FeatureLayer; var outputLayer = GetLayerFromMapByName(OutputLayerName) as FeatureLayer; var observerOutOfExtent = new ObservableCollection <AddInPoint>(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 <AddInPoint>(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); await FeatureClassHelper.CreateTargetsRenderer(GetLayerFromMapByName(TargetsLayerName) as FeatureLayer); await FeatureClassHelper.CreateTargetLayerLabels(GetLayerFromMapByName(TargetsLayerName) as FeatureLayer); await FeatureClassHelper.CreateVisCodeRenderer(GetLayerFromMapByName(SightLinesLayerName) as FeatureLayer, VisibilityLibrary.Properties.Resources.TarIsVisFieldName, 1, 0, ColorFactory.Instance.WhiteRGB, ColorFactory.Instance.BlackRGB, 6.0, 6.0); await FeatureClassHelper.CreateVisCodeRenderer(GetLayerFromMapByName(OutputLayerName) as FeatureLayer, VisibilityLibrary.Properties.Resources.VisCodeFieldName, 1, 2, ColorFactory.Instance.GreenRGB, ColorFactory.Instance.RedRGB, 5.0, 3.0); //await Reset(true); //string groupName = "LLOS Group"; //if (executionCounter > 0) // groupName = string.Format("{0}_{1}", groupName, executionCounter.ToString()); //await FeatureClassHelper.CreateGroupLayer(layerList, groupName); // for now we are not resetting after a run of the tool //await Reset(true); List <Layer> lyrList = new List <Layer>(); 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); var surfaceEnvelope = await GetSurfaceEnvelope(); await DisplayOutOfExtentMsg(surfaceEnvelope); success = true; } else { success = false; } } catch (Exception ex) { success = false; Debug.Print(ex.Message); } return(success); }
/// <summary> /// Here we need to create the lines of sight and determine is a target can be seen or not /// Visualize the visible targets with GREEN circles /// Visualize the non visible targets with RED circles /// Visualize the number of observers that can see a target with a label # /// Visualize an observer that can see no targets with a RED circle on top of a BLUE circle /// Visualize an observer that can see at least one target with a GREEN circle on top of a BLUE circle /// </summary> internal override void CreateMapElement() { try { IsRunning = true; IPolyline longestLine = new PolylineClass(); ReadSelectedLayerPoints(); if (!CanCreateElement || ArcMap.Document == null || ArcMap.Document.FocusMap == null || string.IsNullOrWhiteSpace(SelectedSurfaceName)) { return; } 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 <AddInPoint>(LLOS_ObserversInExtent.Select(x => x.AddInPoint).Union(ObserverInExtentPoints)); var targetPoints = new ObservableCollection <AddInPoint>(LLOS_TargetsInExtent.Select(x => x.AddInPoint).Union(TargetInExtentPoints)); var surface = GetSurfaceFromMapByName(ArcMap.Document.FocusMap, SelectedSurfaceName); if (surface == null) { 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) { 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.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; var geoBridge = (IGeoDatabaseBridge2) new GeoDatabaseHelperClass(); IPoint pointObstruction = null; IPolyline polyVisible = null; IPolyline polyInvisible = null; bool targetIsVisible = false; double finalObserverOffset = GetOffsetInZUnits(ObserverOffset.Value, surface.ZFactor, OffsetUnitType); double finalTargetOffset = GetOffsetInZUnits(TargetOffset.Value, surface.ZFactor, OffsetUnitType); var DictionaryTargetObserverCount = new Dictionary <IPoint, int>(); foreach (var observerPoint in observerPoints) { // keep track of visible targets for this observer var CanSeeAtLeastOneTarget = false; var z1 = surface.GetElevation(observerPoint.Point) + finalObserverOffset; if (double.IsNaN(z1)) { System.Windows.MessageBox.Show(VisibilityLibrary.Properties.Resources.LLOSPointsOutsideOfSurfaceExtent, VisibilityLibrary.Properties.Resources.MsgCalcCancelled); return; } foreach (var targetPoint in targetPoints) { var z2 = surface.GetElevation(targetPoint.Point) + finalTargetOffset; if (double.IsNaN(z2)) { 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; geoBridge.GetLineOfSight(surface, fromPoint, toPoint, out pointObstruction, out polyVisible, out polyInvisible, out targetIsVisible, false, false); var pcol = new PolylineClass() as IPointCollection; pcol.AddPoint(fromPoint); pcol.AddPoint(toPoint); IPolyline pcolPolyline = pcol as IPolyline; longestLine = (longestLine != null && longestLine.Length < pcolPolyline.Length) ? pcolPolyline : longestLine; // set the flag if we can see at least one target if (targetIsVisible) { CanSeeAtLeastOneTarget = true; // 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); } } } // visualize observer // add blue dot AddGraphicToMap(observerPoint.Point, new RgbColorClass() { Blue = 255 }, size: 10); if (CanSeeAtLeastOneTarget) { // add green dot AddGraphicToMap(observerPoint.Point, new RgbColorClass() { Green = 255 }); } else { // add red dot AddGraphicToMap(observerPoint.Point, new RgbColorClass() { Red = 255 }); } } VisualizeTargets(DictionaryTargetObserverCount, targetPoints); if ((ObserverInExtentPoints.Any() || LLOS_ObserversInExtent.Any()) && (TargetInExtentPoints.Any() || LLOS_TargetsInExtent.Any())) { ZoomToExtent(longestLine); } DisplayOutOfExtentMsg(); //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 <AddInPoint>(LLOS_ObserversOutOfExtent.Select(x => x.AddInPoint).Union(ObserverOutExtentPoints)); foreach (var point in observerOutOfExtent) { AddGraphicToMap(point.Point, colorObserver, markerStyle: esriSimpleMarkerStyle.esriSMSX, size: 10, borderColor: colorObserverBorder); } var targetOutOfExtent = new ObservableCollection <AddInPoint>(LLOS_TargetsOutOfExtent.Select(x => x.AddInPoint).Union(TargetOutExtentPoints)); foreach (var point in targetOutOfExtent) { AddGraphicToMap(point.Point, colorTarget, markerStyle: esriSimpleMarkerStyle.esriSMSX, size: 10, borderColor: colorTargetBorder); } } else { System.Windows.MessageBox.Show(VisibilityLibrary.Properties.Resources.OutOfExtentMsg, VisibilityLibrary.Properties.Resources.OutOfExtentHeader); } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.Message); System.Windows.Forms.MessageBox.Show(VisibilityLibrary.Properties.Resources.ExceptionSomethingWentWrong, VisibilityLibrary.Properties.Resources.CaptionError); } finally { IsRunning = false; ClearLLOSCollections(); ValidateLLOS_LayerSelection(); } }