Select to view content in your preferred language

On land or on water?

885
6
Jump to solution
09-02-2022 01:08 AM
Labels (3)
FatmaAkdemir
Occasional Contributor II

Is there any function in ArcGIS Qt Runtime API deciding whether a given lat lon is on land or on sea? We want to take islands into consideration while performing this check.

0 Kudos
1 Solution

Accepted Solutions
Tanner_Yould
Esri Contributor

Hi Fatma, thank you for your question! There's potentially a couple ways you can do this, but I came up with a quick solution by querying the World Countries feature layer's feature table.

I made a quick app that will tell you if the point you click on the map is either on land or sea. When the user clicks the map, it converts the screen position to map coordinates then queries the world countries feature table to see how many features intersect with the map coordinates. If one or more features intersect the map point, then we've clicked on land, otherwise the point is at sea. You could alternatively use the user's location or any other geometry for this query.

void LandOrSea::setupConnections()
{
  PortalItem* worldCountriesItem = new PortalItem("ac80670eb213440ea5899bbf92a04998", this);
  m_countriesLayer = new FeatureLayer(worldCountriesItem, 0, this);

  connect(m_countriesLayer, &FeatureLayer::loadStatusChanged, this, [this](LoadStatus loadStatus)
  {
    if (loadStatus != LoadStatus::Loaded)
      return;

    m_countriesTable = m_countriesLayer->featureTable();

    connect(m_countriesTable, &FeatureTable::queryFeatureCountCompleted, this, [](QUuid, int count)
    {
      qDebug() << (count > 0 ? "We've run aground" : "We're at sea!");
    });
  });

  m_countriesLayer->load();

  connect(m_mapView, &MapQuickView::mouseClicked, this, &LandOrSea::landOrSeaQuery);
}

void LandOrSea::landOrSeaQuery(QMouseEvent e)
{
  if (!m_countriesTable || m_countriesTable->loadStatus() != LoadStatus::Loaded)
  {
    qDebug() << "Countries table is not loaded and is not ready to query";
    return;
  }

  const Point mouseCoordinates = m_mapView->screenToLocation(e.pos().x(), e.pos().y());

  QueryParameters queryParams;
  queryParams.setGeometry(mouseCoordinates);
  queryParams.setSpatialRelationship(SpatialRelationship::Intersects);

  m_countriesTable->queryFeatureCount(queryParams);
}

 

I hope I've understood your question and I hope this helps. Let me know if there's anything else I can do for you, thank you!

Tanner Yould
Product Engineer
ArcGIS Maps SDK for Native Apps
Esri

View solution in original post

6 Replies
Tanner_Yould
Esri Contributor

Hi Fatma, thank you for your question! There's potentially a couple ways you can do this, but I came up with a quick solution by querying the World Countries feature layer's feature table.

I made a quick app that will tell you if the point you click on the map is either on land or sea. When the user clicks the map, it converts the screen position to map coordinates then queries the world countries feature table to see how many features intersect with the map coordinates. If one or more features intersect the map point, then we've clicked on land, otherwise the point is at sea. You could alternatively use the user's location or any other geometry for this query.

void LandOrSea::setupConnections()
{
  PortalItem* worldCountriesItem = new PortalItem("ac80670eb213440ea5899bbf92a04998", this);
  m_countriesLayer = new FeatureLayer(worldCountriesItem, 0, this);

  connect(m_countriesLayer, &FeatureLayer::loadStatusChanged, this, [this](LoadStatus loadStatus)
  {
    if (loadStatus != LoadStatus::Loaded)
      return;

    m_countriesTable = m_countriesLayer->featureTable();

    connect(m_countriesTable, &FeatureTable::queryFeatureCountCompleted, this, [](QUuid, int count)
    {
      qDebug() << (count > 0 ? "We've run aground" : "We're at sea!");
    });
  });

  m_countriesLayer->load();

  connect(m_mapView, &MapQuickView::mouseClicked, this, &LandOrSea::landOrSeaQuery);
}

void LandOrSea::landOrSeaQuery(QMouseEvent e)
{
  if (!m_countriesTable || m_countriesTable->loadStatus() != LoadStatus::Loaded)
  {
    qDebug() << "Countries table is not loaded and is not ready to query";
    return;
  }

  const Point mouseCoordinates = m_mapView->screenToLocation(e.pos().x(), e.pos().y());

  QueryParameters queryParams;
  queryParams.setGeometry(mouseCoordinates);
  queryParams.setSpatialRelationship(SpatialRelationship::Intersects);

  m_countriesTable->queryFeatureCount(queryParams);
}

 

I hope I've understood your question and I hope this helps. Let me know if there's anything else I can do for you, thank you!

Tanner Yould
Product Engineer
ArcGIS Maps SDK for Native Apps
Esri
FatmaAkdemir
Occasional Contributor II

Hi @Tanner_Yould ,

Thank you very much for this great answer! However our application will be installed on a mountain where there is no internet. Is there any way to download this "World  Countries" feature so that we can make this check offline?

0 Kudos
Tanner_Yould
Esri Contributor

Hey, I'm glad I could be helpful! Depending on the size of the area you need, you may be able to take a specific area offline or download the whole feature service (or something similar) and create a mobile geodatabase to load onto your device. I'll link some sample code that demonstrates how to do that:

These two samples are two of many that we've written to cover most of the Runtime API and demonstrate use cases and best practices for using our API. Hopefully they can point you in the right direction, but don't hesitate to follow up with any additional questions.

Thanks!

Tanner Yould
Product Engineer
ArcGIS Maps SDK for Native Apps
Esri
0 Kudos
FatmaAkdemir
Occasional Contributor II

Hi @Tanner_Yould , I really appreciate your help. I managed to generate the shapefile offline. However since it contains all countries, the land or sea check takes approximately 130 ms. Is there any way to reduce the shapefile or load only certain countries while creating FeatureTable?

0 Kudos
Tanner_Yould
Esri Contributor

There's a few things I'd try here:

  • I haven't tested this, but you may want to try the function void QueryParameters::setMaxFeatures(int maxFeatures) and set it to return just one feature. That way the query would stop after finding a feature and not have to check against any additional features.
  • You could edit the shapefile in ArcGIS Pro to only include the countries in your area of interest.
  • You could run Dissolve Boundaries on the countries layer in Pro and turn all countries into just one feature. That may speed up the query.
Tanner Yould
Product Engineer
ArcGIS Maps SDK for Native Apps
Esri
FatmaAkdemir
Occasional Contributor II

Thank you very much @Tanner_Yould. I clipped the shapefile by using QGis application. After that, query time reduced to 2 ms.

0 Kudos