• 博客园logo
  • 会员
  • 周边
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

gisoracle

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

AddOverlay和删除

Skip to content

    Product 

Team
Enterprise
Explore
Marketplace
Pricing

Sign in
Sign up
Esri /
arcgis-pro-sdk-community-samples
Public

Code
Issues 2
Pull requests 1
Actions
Projects
Wiki
Security

    Insights

arcgis-pro-sdk-community-samples/Map-Exploration/OverlayGroundSurface/Module1.cs /
@arcgisprosdk
arcgisprosdk ArcGIS Pro SDK 2.7 SDK for .NET
Latest commit 44183d0 on 16 Dec 2020
History
1 contributor
531 lines (474 sloc) 18.8 KB
/*
   Copyright 2020 Esri
   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at
       http://www.apache.org/licenses/LICENSE-2.0
   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   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.Text;
using System.Windows.Input;
using System.Threading.Tasks;
using ArcGIS.Core.CIM;
using ArcGIS.Core.Data;
using ArcGIS.Core.Geometry;
using ArcGIS.Desktop.Catalog;
using ArcGIS.Desktop.Core;
using ArcGIS.Desktop.Editing;
using ArcGIS.Desktop.Extensions;
using ArcGIS.Desktop.Framework;
using ArcGIS.Desktop.Framework.Contracts;
using ArcGIS.Desktop.Framework.Dialogs;
using ArcGIS.Desktop.Framework.Threading.Tasks;
using ArcGIS.Desktop.Mapping;

namespace OverlayGroundSurface
{
  /// <summary>
  /// OverlayGroundSurface illustrates how to draw geometries over a ground surface using AddOverlay.  
  /// </summary>
  /// <remarks>
  /// 1. Download the Community Sample data (see under the 'Resources' section for downloading sample data).  The sample data contains a folder called 'C:\Data\Configurations\Projects' with sample data required for this solution.  Make sure that the Sample data (specifically CommunitySampleData-3D-mm-dd-yyyy.zip) is unzipped into c:\data and c:\data\PolyTest is available.
  /// 1. This solution is using the **Newtonsoft.Json NuGet**.  If needed, you can install the NuGet from the "NuGet Package Manager Console" by using this script: "Install-Package Newtonsoft.Json".
  /// 1. In Visual Studio click the Build menu. Then select Build Solution.
  /// 1. Click Start button to debug ArcGIS Pro.
  /// 1. Open the Pro project file: PolyTest.aprx in the C:\Data\PolyTest\ folder.  Open the 'Graphic Test' tab in ArcGIS Pro.
  /// ![UI](Screenshots/Screen1.png)
  /// 1. Make sure that the 'Scene' is selected as the active map in ArcGIS Pro and then click on the 'Create 3D Polygon Tool'.
  /// 1. Digitize a polygon on the map.  Once a polygon has been digitized the buttons under the 'Polygon 2 Graphic' group are now enabled.  These buttons can be used to 'slice' the digitized polygon into smaller parts.
  /// ![UI](Screenshots/Screen2.png)
  /// 1. Note that the number of slices across the X axis can be controlled with the Resolution pull-down.  The 'Elevation' pull-down can be used add an additional elevation offset to the Z axis when the polygon is rendered in a scene.
  /// 1. Select: Resolution 4 and Elevation 5 on the respective pull-down and click the 'Make Ring MultiPatch' button.
  /// 1. The Add-in now converts the digitized polygon into a multipatch geometry and renders the multipatch in 2D and 3D.
  /// ![UI](Screenshots/Screen3.png)
  /// 1. Select: Resolution 50 and Elevation 20 on the respective pull-down and click the 'Make Ring MultiPatch' button.
  /// 1. The Add-in now converts the digitized polygon into a higher resolution multipatch geometry and renders the multipatch in 3D and 3D.
  /// ![UI](Screenshots/Screen4.png)
  /// </remarks>
  internal class Module1 : Module
  {
    private static Module1 _this = null;

    /// <summary>
    /// Retrieve the singleton instance to this module here
    /// </summary>
    public static Module1 Current
    {
      get
      {
        return _this ?? (_this = (Module1)FrameworkApplication.FindModule("OverlayGroundSurface_Module"));
      }
    }

    internal static MapView CurrentMapView { get; set; }

    #region UI properties and states

    private static List<Geometry> _geometries = new List<Geometry>();
    private static bool _hasImportData = false;

    internal static bool HasImportData
    {
      get { return _hasImportData; }
      set { _hasImportData = value; }
    }

    internal static bool HasGeometries
    {
      get { return HasImportData && _geometries.Count > 0; }
    }

    internal static List<Geometry> Geometries
    {
      get
      {
        return _geometries;
      }
      set
      {
        if (value == null) _geometries = null;
        else
        {
          _geometries.Clear();
          if (value != null)
          {
            foreach (var geom in value)
            {
              _geometries.Add(geom.Clone());
            }
          }
        }
        SetState("has_geometry_state", _geometries != null && _geometries.Count > 0);
      }
    }

    private static Polygon _polygon = null;

    internal static Polygon Polygon
    {
      get
      {
        return _polygon;
      }
      set
      {
        if (value == null) _polygon = null;
        else _polygon = value.Clone() as Polygon;
        SetState("has_polygon_state", _polygon != null);
        foreach (var mv in _graphics.Keys)
        {
          ClearGraphics(mv);
        }
        var mvs = new List<MapView>();
        foreach (var mv in _graphic.Keys)
        {
          if (_graphic[mv] != null) mvs.Add(mv);
        }
        foreach (var mv in mvs)
        {
          _graphic[mv]?.Dispose();
          _graphic[mv] = null;
        }
        HasImportData = false;
      }
    }

    internal static void SetState(string stateName, bool active)
    {
      if (FrameworkApplication.State.Contains(stateName) == active) return;
      // toggle the state
      if (FrameworkApplication.State.Contains(stateName))
      {
        //deactivates the state
        FrameworkApplication.State.Deactivate(stateName);
      }
      else
      {
        //activates the state
        FrameworkApplication.State.Activate(stateName);
      }
    }

    internal static double Resolution { get; set; } = 1.00;

    internal static double Elevation { get; set; } = 1.00;

    #endregion UI properties and states

    #region Overlay Helpers

    private static Dictionary<MapView, IDisposable> _graphic = new Dictionary<MapView, IDisposable>();

    internal static void AddOrUpdateOverlay(Geometry geom, CIMSymbolReference symRef)
    {
      var mapView = Module1.CurrentMapView;
      if (mapView == null) return;
      ClearGraphics(mapView);
      if (!_graphic.ContainsKey(mapView))
      {
        _graphic.Add(mapView, mapView.AddOverlay(geom, symRef));
        return;
      }
      if (_graphic[mapView] == null)
      {
        if (geom is Multipatch)
        {
          var cimMpGraphic = new CIMMultiPatchGraphic
          {
            MultiPatch = geom as Multipatch,
            Symbol = symRef,
            Transparency = 64
          };
          _graphic[mapView] = mapView.AddOverlay(geom, symRef);
        }
        else
          _graphic[mapView] = mapView.AddOverlay(geom, symRef);
      }
      else
        mapView.UpdateOverlay(_graphic[mapView], geom, symRef);
    }

    internal static void ClearGraphic(MapView mapView)
    {
      if (mapView == null) return;
      if (_graphic.ContainsKey(mapView))
      {
        _graphic[mapView]?.Dispose();
        _graphic[mapView] = null;
      }
    }

    private static Dictionary<MapView, List<IDisposable>> _graphics = new Dictionary<MapView, List<IDisposable>>();

    private static void ClearGraphics(MapView mapView)
    {
      if (_graphics.ContainsKey(mapView))
      {
        foreach (var g in _graphics[mapView]) g.Dispose();
        _graphics[mapView].Clear();
      }
    }

    internal static void MultiAddOrUpdateOverlay(bool bFirst, Geometry geom, CIMSymbolReference symRef)
    {
      var mapView = Module1.CurrentMapView;
      if (mapView == null) return;
      if (bFirst)
      {
        ClearGraphic(mapView);
        ClearGraphics(mapView);
      }
      if (!_graphics.ContainsKey(mapView))
      {
        _graphics.Add(mapView, new List<IDisposable>());
      }
      _graphics[mapView].Add(Module1.CurrentMapView?.AddOverlay(geom, symRef));
    }

    #endregion Overlay Helpers

    #region Utility Helpers

    internal static bool Is3D => (Module1.CurrentMapView?.ViewingMode == MapViewingMode.SceneGlobal || Module1.CurrentMapView?.ViewingMode == MapViewingMode.SceneLocal);

    internal static double GetFishnetIntervalDistance(Envelope env)
    {
      return ((env.XMax - env.XMin) + (env.XMax - env.XMin) * 0.01) / Resolution;
    }

    #endregion Utility Helpers

    #region Polygon Helpers

    internal static List<Geometry> MakeFishnetPolygons(Polygon inputPoly)
    {
      List<Geometry> polygons = new List<Geometry>();
      Envelope envPoly = inputPoly.Extent;
      var interval = GetFishnetIntervalDistance(envPoly);
      for (var dX = envPoly.XMin; dX < envPoly.XMax + interval; dX += interval)
      {
        for (var dY = envPoly.YMin; dY < envPoly.YMax + interval; dY += interval)
        {
          var cutEnv = EnvelopeBuilder.CreateEnvelope(dX, dY, dX + interval, dY + interval, envPoly.SpatialReference);
          if (GeometryEngine.Instance.Intersects(cutEnv, inputPoly))
          {
            var addPolygonPart = GeometryEngine.Instance.Clip(inputPoly, cutEnv);
            polygons.Add(addPolygonPart);
          }
        }
      }
      return polygons;
    }

    internal static Geometry MakeFishnetPolygon(Polygon inputPoly)
    {
      Envelope envPoly = inputPoly.Extent;
      var interval = GetFishnetIntervalDistance(envPoly);
      var pb = new PolygonBuilder(inputPoly.SpatialReference)
      {
        HasZ = true
      };
      for (var dX = envPoly.XMin; dX < envPoly.XMax + interval; dX += interval)
      {
        for (var dY = envPoly.YMin; dY < envPoly.YMax + interval; dY += interval)
        {
          var cutEnv = EnvelopeBuilder.CreateEnvelope(dX, dY, dX + interval, dY + interval, envPoly.SpatialReference);
          if (GeometryEngine.Instance.Intersects(cutEnv, inputPoly))
          {
            var addPolygonPart = GeometryEngine.Instance.Clip(inputPoly, cutEnv) as Polygon;
            if (addPolygonPart.Area < 0)
            {
              System.Diagnostics.Debug.WriteLine($@"area: {addPolygonPart.Area}");
            }
            pb.AddPart(addPolygonPart.Points);
          }
        }
      }
      return pb.ToGeometry();
    }

    #endregion Polygon Helpers

    #region MultiPatch Helpers

    internal static async Task<Geometry> MakeFishnetMultiPatchAsync(Polygon inputPoly)
    {
      Envelope envPoly = inputPoly.Extent;
      var interval = GetFishnetIntervalDistance(envPoly);

      var mColor = System.Windows.Media.Colors.LightCyan;
      var materialRed = new BasicMaterial
      {
        Color = mColor,
        EdgeColor = mColor,
        EdgeWidth = 0
      };
      // create the multipatchBuilderEx object
      var mpb = new MultipatchBuilderEx();
      // create a list of patch objects
      var patches = new List<Patch>();
      for (var dX = envPoly.XMin; dX < envPoly.XMax + interval; dX += interval)
      {
        for (var dY = envPoly.YMin; dY < envPoly.YMax + interval; dY += interval)
        {
          var cutEnv = EnvelopeBuilder.CreateEnvelope(dX, dY, dX + interval, dY + interval,
                                                      envPoly.SpatialReference);
          if (GeometryEngine.Instance.Intersects(cutEnv, inputPoly))
          {
            var addPolygonPart = GeometryEngine.Instance.Clip(inputPoly, cutEnv) as Polygon;
            if (addPolygonPart.Area < 0)
            {
              System.Diagnostics.Debug.WriteLine($@"area: {addPolygonPart.Area}");
            }
            var result = await Module1.CurrentMapView.Map.GetZsFromSurfaceAsync(addPolygonPart);
            if (result.Status == SurfaceZsResultStatus.Ok)
            {
              addPolygonPart = GeometryEngine.Instance.Move(result.Geometry, 0, 0, Module1.Elevation) as Polygon;
            }
            var patch = mpb.MakePatch(esriPatchType.TriangleStrip);
            patch.Coords = GetPolygonAsTriangleStrip(addPolygonPart);
            patch.Material = materialRed;
            patches.Add(patch);
          }
        }
      }            // assign the patches to the multipatchBuilder
      mpb.Patches = patches;
      // call ToGeometry to get the multipatch
      return mpb.ToGeometry();
    }

    internal static async Task<Multipatch> MakeFishnetRingMultiPatchAsync(Polygon inputPoly)
    {
      Envelope envPoly = inputPoly.Extent;
      var interval = GetFishnetIntervalDistance(envPoly);

      var mColor = System.Windows.Media.Colors.LightCyan;
      var materialRed = new BasicMaterial
      {
        Color = mColor,
        EdgeColor = mColor,
        EdgeWidth = 0
      };
      // create the multipatchBuilderEx object
      var mpb = new MultipatchBuilderEx();
      // create a list of patch objects
      var patches = new List<Patch>();
      var first = true;
      for (var dX = envPoly.XMin; dX < envPoly.XMax + interval; dX += interval)
      {
        for (var dY = envPoly.YMin; dY < envPoly.YMax + interval; dY += interval)
        {
          var cutEnv = EnvelopeBuilder.CreateEnvelope(dX, dY, dX + interval, dY + interval,
                                                      envPoly.SpatialReference);
          if (GeometryEngine.Instance.Intersects(cutEnv, inputPoly))
          {
            var addPolygonPart = GeometryEngine.Instance.Clip(inputPoly, cutEnv) as Polygon;
            if (addPolygonPart.Area < 0)
            {
              System.Diagnostics.Debug.WriteLine($@"area: {addPolygonPart.Area}");
            }
            var result = await Module1.CurrentMapView.Map.GetZsFromSurfaceAsync(addPolygonPart);
            if (result.Status == SurfaceZsResultStatus.Ok)
            {
              addPolygonPart = GeometryEngine.Instance.Move(result.Geometry, 0, 0, Module1.Elevation) as Polygon;
            }
            var patch = mpb.MakePatch(first ? esriPatchType.FirstRing : esriPatchType.Ring);
            first = false;
            patch.InsertPoints(0, addPolygonPart.Points);
            patch.Material = materialRed;
            patches.Add(patch);
          }
        }
      }            // assign the patches to the multipatchBuilder
      mpb.Patches = patches;
      // call ToGeometry to get the multipatch
      return mpb.ToGeometry() as Multipatch;
    }

    internal static List<Coordinate3D> GetPolygonAsTriangleStrip(Polygon poly)
    {
      if (poly.PointCount < 4)
      {
        throw new Exception($@"Polygon 2 Triangle failed, too few vertices: {poly.PointCount}");
      }
      int maxPoints = poly.PointCount - 1;
      Coordinate3D[] coords = new Coordinate3D[maxPoints];
      int iNext = 0;
      foreach (var coord in poly.Copy3DCoordinatesToList())
      {
        if (iNext < maxPoints) coords[iNext++] = coord;
      }
      var lstCoords = new List<Coordinate3D>();
      int iTop = maxPoints - 1;
      int iBottom = 0;
      lstCoords.Add(DebugCoord(iBottom, coords[iBottom++]));
      lstCoords.Add(DebugCoord(iBottom, coords[iBottom++]));
      lstCoords.Add(DebugCoord(iTop, coords[iTop--]));
      var tick = true;
      for (; iTop >= iBottom; tick = !tick)
      {
        lstCoords.Add(tick ? DebugCoord(iBottom, coords[iBottom++]) : DebugCoord(iTop, coords[iTop--]));
      }
      // get the coordinates in triangle strip order
      return lstCoords;
    }

    internal static Coordinate3D DebugCoord(int idx, Coordinate3D coord)
    {
      // System.Diagnostics.Debug.WriteLine($@"Pnt: {idx} {coord.X} {coord.Y} {coord.Z} ");
      return coord;
    }

    /// <summary>
    /// Call from MCT.
    /// </summary>
    /// <returns></returns>
    internal static CIMSymbolReference GetDefaultMeshSymbol()
    {
      // find a 3d symbol
      var spi = Project.Current.GetItems<StyleProjectItem>().First(s => s.Name == "ArcGIS 3D");
      if (spi == null) return null;
      // create new structural features
      var style_item = spi.SearchSymbols(StyleItemType.MeshSymbol, "").FirstOrDefault(si => si.Name.StartsWith("Gray 40%"));
      var symbol = style_item?.Symbol as CIMMeshSymbol;
      if (symbol == null) return null;
      var meshSymbol = symbol.MakeSymbolReference();
      return meshSymbol;
    }

    #endregion MultiPatch Helpers

    #region Symbol Helpers

    private static CIMSymbolReference _polySymbolRef = null;

    internal static CIMSymbolReference GetPolygonSymbolRef()
    {
      if (_polySymbolRef != null) return _polySymbolRef;
      //Creating a polygon with a red fill and blue outline.
      CIMStroke outline = SymbolFactory.Instance.ConstructStroke(
           ColorFactory.Instance.BlueRGB, 2.0, SimpleLineStyle.Solid);
      _polySymbolRef = SymbolFactory.Instance.ConstructPolygonSymbol(
           ColorFactory.Instance.CreateRGBColor(255, 190, 190),
           SimpleFillStyle.Solid, outline).MakeSymbolReference();
      return _polySymbolRef;
    }

    private static CIMSymbolReference _lineSymbolRef = null;

    /// <summary>
    /// Get a line symbol
    /// Must be called from the MCT.  Use QueuedTask.Run.
    /// </summary>
    /// <returns></returns>
    internal static CIMSymbolReference GetLineSymbolRef()
    {
      if (_lineSymbolRef != null) return _lineSymbolRef;
      _lineSymbolRef = SymbolFactory.Instance.ConstructLineSymbol(
                          ColorFactory.Instance.RedRGB, 4,
                          SimpleLineStyle.Solid).MakeSymbolReference();
      return _lineSymbolRef;
    }

    private static CIMSymbolReference _point3DSymbolRef = null;
    private static CIMSymbolReference _point2DSymbolRef = null;

    internal static CIMSymbolReference GetPointSymbolRef()
    {
      if (Is3D)
      {
        if (_point3DSymbolRef != null) return _point3DSymbolRef;
        var pointSymbol = GetPointSymbol("ArcGIS 3D", @"Pushpin 2");
        CIMPointSymbol pnt3DSym = pointSymbol.Symbol as CIMPointSymbol;
        pnt3DSym.SetSize(200);
        pnt3DSym.SetRealWorldUnits(true);
        _point3DSymbolRef = pnt3DSym.MakeSymbolReference();
        return _point3DSymbolRef;
      }
      if (_point2DSymbolRef != null) return _point2DSymbolRef;
      CIMPointSymbol pntSym = SymbolFactory.Instance.ConstructPointSymbol(ColorFactory.Instance.RedRGB, 8, SimpleMarkerStyle.Circle);
      _point2DSymbolRef = pntSym.MakeSymbolReference();
      return _point2DSymbolRef;
    }

    private static SymbolStyleItem GetPointSymbol(string styleProjectItemName, string symbolStyleName)
    {
      var style3DProjectItem = Project.Current.GetItems<StyleProjectItem>().Where(p => p.Name == styleProjectItemName).FirstOrDefault();
      var symbolStyle = style3DProjectItem.SearchSymbols(StyleItemType.PointSymbol, symbolStyleName).FirstOrDefault();
      return symbolStyle;
    }

    #endregion Symbol Helper

    #region Overrides
    /// <summary>
    /// Called by Framework when ArcGIS Pro is closing
    /// </summary>
    /// <returns>False to prevent Pro from closing, otherwise True</returns>
    protected override bool CanUnload()
    {
      //TODO - add your business logic
      //return false to ~cancel~ Application close
      return true;
    }

    #endregion Overrides

  }
}

    © 2022 GitHub, Inc.

    Terms
    Privacy
    Security
    Status
    Docs
    Contact GitHub
    Pricing
    API
    Training
    Blog
    About

Loading complete

 

posted on 2022-05-13 20:31  gisai  阅读(143)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3