Призма и Esri GetElevationAsync(mapPoint)

Мы создаем приложение для Visual Studio 2017 с использованием wpf, C# и Prism v6.1.0.0. У нас есть трехмерное представление, которое представляет собой среду исполнения Esri.net SceneView. Мы хотели использовать функцию GetElevationAsync(mapPoint) для получения данных высот из данных DTED уровня 0. В автономном приложении, использующем только Esri SceneView, функция GetElevationAsync(mapPoint) работает как для SceneView, так и для MapView, если SceneView активен. Это также использует FileElevationSource и загружает на уровне DTED 0 в FileElevationSource, а затем добавляет его в SceneView.Scene.Surface.

Проблема, с которой мы сталкиваемся, - это когда мы пытаемся вызвать GetElevationAsync(mapPoint), мы получаем исключение System.AccessViolationException. Кто-нибудь еще пытался использовать среду выполнения.net ESRi и Prism для создания приложения SceneView, использующего функцию GetElevationAsync(mapPoint)?

Что есть, это приложение Prism с несколькими представлениями и основной оболочкой. Модуль SceneView имеет службу и использует этот сервер для загрузки данных DTED уровня 0 в SceneView.Scene.Surface. Я перенес всю функциональность в SceneViewView, и мы все еще получаем ту же ошибку доступа. Вызывающий поток является основным потоком приложения. У меня есть сообщение об ошибке и некоторые фрагменты кода. Тот же код, что и у меня в приложении Prism, - это тот же код, что и у меня в простом приложении WPF, в котором используются все те же элементы управления, но не архитектура Prism. Это прекрасно работает, и я могу получить данные повышения, просто активировав Sceneview и без проблем передавая mapoint из Mapview в функцию GetElevationAsync.

  private void OnSceneViewViewLoaded(object sender, RoutedEventArgs e)
  {
     SceneViewService = UnityContainer.Resolve<ISceneViewService>();

     string elevationSourcePath = System.Environment.GetEnvironmentVariable("SHELL") + "\\Resources\\Terrain\\DTED\\Level0\\";
     AddElevationSources(elevationSourcePath);
     mSceneView.MouseMove += OnSceneViewMouseMove;
  }
  private void OnSceneViewMouseMove(object sender, MouseEventArgs e)
  {
     {
        Point screenPoint = e.GetPosition(mSceneView);
        double elevation = 0.0;
        MapPoint point = mSceneView.ScreenToLocation(screenPoint);
        if (point != null)
        {
           MapPoint mapPoint = GeometryEngine.Project(point, SpatialReferences.Wgs84) as MapPoint;

           elevation = GetElevation(mapPoint).Result;

           if (!Double.IsNaN(elevation))
           {
              mElevationStatusBarTextBlock.Text = elevation.ToString();
           }
        }
     }
  }
  public void AddElevationSources(string elevationSourcePath)
  {
     FilenameCollection mFilenameCollection = new FilenameCollection();
     List<String> files = new List<String>();

     try
     {
        files = DirSearch(elevationSourcePath);

        foreach (String file in files)
           mFilenameCollection.Add(file);

        mFileElevationSource.Filenames = mFilenameCollection;
        mFileElevationSource.ID = "Elevation Source";
        mSceneView.Scene.Surface.Add(mFileElevationSource);
        mFileElevationSource.IsEnabled = true;
     }
     catch (Exception excpt)
     {
        Console.WriteLine("AddElevationSources, ElevationSourceService " + excpt.Message);
     }
  }
  public List<String> DirSearch(string sourceDirectory)
  {
     List<String> files = new List<String>();
     try
     {
        foreach (string file in Directory.GetFiles(sourceDirectory, "*.dt0"))
        {
           files.Add(file);
        }
        foreach (string directory in Directory.GetDirectories(sourceDirectory))
        {
           files.AddRange(DirSearch(directory));
        }

     }
     catch (Exception excpt)
     {
        Console.WriteLine("DirSearch, AddElevationSources " + excpt.Message);
     }
     return files;
  }

Передаются данные точки карты "mapPoint = {MapPoint[X=4.54778361440582, Y=27.7940801510867, Z=5.58793544769287E-09, Wkid=4326]}"

  public async Task<double> GetElevation(MapPoint mapPoint)
  {
     double elevation = 0.0;

     try
     {
        if (!Double.IsNaN(mapPoint.X) && !Double.IsNaN(mapPoint.Y))
        {
           elevation = await mFileElevationSource.GetElevationAsync(mapPoint);
           if (Double.IsNaN(elevation))
              elevation = 0;
        }
     }
     catch (Exception excpt)
     {
        Console.WriteLine("Task<double> GetElevation, ElevationSourceModule " + excpt.Message);
     }

     return elevation;
  }
}

Возникла исключительная ситуация System.AccessViolationException HResult=0x80004003 Сообщение = Попытка чтения или записи в защищенную память. Это часто указывает на то, что другая память повреждена. Источник =Esri.ArcGISRuntime StackTrace: в runtimeCoreNet.CoreLocalElevationRaster.LocalElevationLayerPickElevation(IntPtr pNativeElevationLayer, с двойной х, у, Double Double& г) в Esri.ArcGISRuntime.Controls.FileElevationSource.GetElevationAsync(MapPoint точка) в SceneViewModule.Views.SceneViewView.SceneViewView.d__19.MoveNext() в \SceneViewModule\Views\SceneViewView\SceneViewView.xaml.cs: строка 141

1 ответ

Вы упомянули, что используете его в Unity?

API GetElevationAsync работают с ним только при активном рендеринге SceneView. Хотя ошибка не звучит правильно, этот API не будет работать в данный момент отдельно от SceneView (хотя он есть в нашем списке для будущих улучшений). На этом этапе его главная цель - щелкнуть SceneView и получить точное превышение для этой точки. Он не предназначен для одиночества. Я предполагаю, что есть некоторая обработка ошибок, не проверяющая правильно для этого, именно поэтому вы видите сбой. Но если бы это было исправлено, все, что вы получили бы, было бы лучшим сообщением об ошибке.

Другие вопросы по тегам