Skip to content

Commit

Permalink
Sample native app for analyzing
Browse files Browse the repository at this point in the history
  • Loading branch information
esride-jts committed Nov 21, 2024
1 parent 7d6edaa commit 6e1b8f3
Show file tree
Hide file tree
Showing 18 changed files with 574 additions and 0 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
124 changes: 124 additions & 0 deletions native-apps/urban-heat-analyzer/UrbanHeatAnalyzer/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
#-------------------------------------------------
# Copyright 2024 ESRI
#
# All rights reserved under the copyright laws of the United States
# and applicable international laws, treaties, and conventions.
#
# You may freely redistribute and use this sample code, with or
# without modification, provided you include the original copyright
# notice and use restrictions.
#
# See the Sample code usage restrictions document for further information.
#-------------------------------------------------
cmake_minimum_required(VERSION 3.5)

project(UrbanHeatAnalyzer LANGUAGES CXX)

set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})

set(CMAKE_INCLUDE_CURRENT_DIR ON)

set(CMAKE_AUTOUIC OFF)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

if(IOS)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_OSX_DEPLOYMENT_TARGET "16.0" CACHE STRING "Minimum iOS deployment version" FORCE)
elseif(APPLE)
set(CMAKE_OSX_DEPLOYMENT_TARGET "13.0" CACHE STRING "Minimum macOS deployment version" FORCE)
endif()

find_package(Qt6 COMPONENTS REQUIRED Core Quick Multimedia Positioning Sensors WebSockets)
if (Qt6Core_VERSION VERSION_LESS 6.5.6)
message(FATAL_ERROR "This version of the ArcGIS Maps SDK for Qt requires at least Qt 6.5.6")
endif()
if(ANDROID OR IOS)
find_package(Qt6 COMPONENTS REQUIRED Bluetooth)
endif()
find_package(ArcGISRuntime 200.5.0 COMPONENTS REQUIRED Cpp)

set(SOURCE_FILES
main.cpp
UrbanHeatAnalyzer.cpp
UrbanHeatAnalyzer.h
qml/qml.qrc
Resources/Resources.qrc
$<$<BOOL:${WIN32}>:Win/Resources.rc>
$<$<BOOL:${APPLE}>:Mac/AppIcon.icns>)

if(ANDROID)
qt_add_executable(${PROJECT_NAME} ${SOURCE_FILES})
else()
qt_add_executable(${PROJECT_NAME} MACOSX_BUNDLE ${SOURCE_FILES})
# IOS uses static Runtimecore Framework
if(IOS)
set_target_properties(${PROJECT_NAME} PROPERTIES INSTALL_RPATH @executable_path/Frameworks
XCODE_EMBED_FRAMEWORKS ${ArcGISRuntime_runtimecore_LIB}
XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY TRUE)
endif()
# On MacOSX add icon to app bundle.
set(MACOSX_BUNDLE_ICON_FILE AppIcon.icns)
set_source_files_properties(Mac/AppIcon.icns
PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")

# Copy required dynamic libraries to the build folder as a post-build step.
if(DEFINED ArcGISRuntime_LIBRARIES)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${ArcGISRuntime_LIBRARIES}
$<TARGET_FILE_DIR:${PROJECT_NAME}>)
endif()
endif()

target_compile_definitions(${PROJECT_NAME}
PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)

target_link_libraries(${PROJECT_NAME} PRIVATE
Qt6::Core
Qt6::Quick
Qt6::Multimedia
Qt6::Positioning
Qt6::Sensors
Qt6::WebSockets
ArcGISRuntime::Cpp)

# To integrate the toolkit, copy the `toolkitcpp` subdirectory from the toolkit
# into your project's directory. Then uncomment the following lines to add it to your project.
# See https://github.com/Esri/arcgis-maps-sdk-toolkit-qt for details
# add_subdirectory(toolkitcpp)
# target_link_libraries(${PROJECT_NAME} PRIVATE libtoolkitcpp)

if(ANDROID OR IOS)
target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Bluetooth)
endif()

if(ANDROID)
target_link_libraries(${PROJECT_NAME} PRIVATE Qt::CorePrivate)

set(PROJECT_DEPLOYABLE_LIBS
${ArcGISRuntime_LIBRARIES})

list(JOIN PROJECT_DEPLOYABLE_LIBS , PROJECT_DEPLOYABLE_LIBS_STRING)

# Setup openssl by cloning the repo https://github.com/KDAB/android_openssl More info at https://doc.qt.io/qt-6/android-openssl-support.html
# QtCreator can also be used to install openssl https://doc.qt.io/qtcreator/creator-developing-android.html#specifying-android-device-settings
# Uncomment line below and point to your openssl path.

#include(<your_path_to_android_openssl>/CMakeLists.txt)

# QtCreator supports the following variables for Android, which are identical
# to qmake Android variables.
# Check http://doc.qt.io/qt-6/deployment-android.html for more information.
# Setting this property changed at Qt6 see doc below.
# https://doc.qt.io/qt-6/cmake-target-property-qt-android-extra-libs.html

set_property(TARGET ${PROJECT_NAME} PROPERTY QT_ANDROID_EXTRA_LIBS ${PROJECT_DEPLOYABLE_LIBS_STRING} ${ANDROID_EXTRA_LIBS})
get_property(EXTRA_LIBS TARGET ${PROJECT_NAME} PROPERTY QT_ANDROID_EXTRA_LIBS)
if(NOT EXTRA_LIBS MATCHES "libssl" OR NOT EXTRA_LIBS MATCHES "libcrypto")
message(WARNING "openssl libraries are missing, check the project CMakeLists.txt and set up openssl environment")
endif()
endif()
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/Resources">
<file>AppIcon.png</file>
</qresource>
</RCC>
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
// Copyright 2024 ESRI
//
// All rights reserved under the copyright laws of the United States
// and applicable international laws, treaties, and conventions.
//
// You may freely redistribute and use this sample code, with or
// without modification, provided you include the original copyright
// notice and use restrictions.
//
// See the Sample code usage restrictions document for further information.
//
// This "Urban Heat Analyzer" sample app is licensed as
// SPDX-License-Identifier: GPL-3.0-or-later
//
// Additional permission under GNU GPL version 3 section 4 and 5
// If you modify this Program, or any covered work, by linking or combining
// it with ArcGIS Runtime for Qt (or a modified version of that library),
// containing parts covered by the terms of ArcGIS Runtime for Qt,
// the licensors of this Program grant you additional permission to convey the resulting work.
// See <https://developers.arcgis.com/qt/> for further information.
//

#include "UrbanHeatAnalyzer.h"

#include "ArcGISTiledElevationSource.h"
#include "ArcGISVectorTiledLayer.h"
#include "AttributeListModel.h"
#include "CoreTypes.h"
#include "ElevationSourceListModel.h"
#include "Envelope.h"
#include "Feature.h"
#include "FeatureIterator.h"
#include "FeatureQueryResult.h"
#include "Geodatabase.h"
#include "GeodatabaseFeatureTable.h"
#include "LayerListModel.h"
#include "MapTypes.h"
#include "OrderBy.h"
#include "QueryParameters.h"
#include "Scene.h"
#include "SceneQuickView.h"
#include "ServiceFeatureTable.h"
#include "Surface.h"
#include "VectorTileCache.h"
#include "Viewpoint.h"

#include <QFuture>
#include <QUrl>

#include <memory>

using namespace Esri::ArcGISRuntime;

UrbanHeatAnalyzer::UrbanHeatAnalyzer(QObject *parent /* = nullptr */)
: QObject(parent)
, m_scene(new Scene(BasemapStyle::OsmStandard, this))
{
// create a new elevation source from Terrain3D rest service
ArcGISTiledElevationSource *elevationSource
= new ArcGISTiledElevationSource(QUrl("https://elevation3d.arcgis.com/arcgis/rest/services/"
"WorldElevation3D/Terrain3D/ImageServer"),
this);

// add vector tile cache
VectorTileCache *tileCache = new VectorTileCache(
"/data/Germany/Bonn/heat_risk_index_bonn.vtpk",
this);

// add the vector tile layer
ArcGISVectorTiledLayer *tiledLayer = new ArcGISVectorTiledLayer(
tileCache,
this);
connect(tiledLayer, &ArcGISVectorTiledLayer::doneLoading, this, [tiledLayer, this]()
{
Envelope layerExtent = tiledLayer->fullExtent();
Viewpoint viewpoint = Viewpoint(layerExtent);
m_sceneView->setViewpointAsync(viewpoint, 2.5);
});
m_scene->operationalLayers()->append(tiledLayer);

// add the features
Geodatabase *gdb = new Geodatabase(
"/data/Germany/Bonn/HRI Bonn.geodatabase",
this);
connect(gdb, &Geodatabase::doneLoading, this, [gdb, this]()
{
GeodatabaseFeatureTable *featureTable = gdb->geodatabaseFeatureTable("HRI_Bonn");
connect(featureTable, &GeodatabaseFeatureTable::doneLoading, this, [featureTable, this]()
{
qint64 featureCount = featureTable->numberOfFeatures();
qDebug() << featureCount;

// Execute the analysis
QueryParameters analysisParameters;
QList<OrderBy> orderByFields;
orderByFields.append(OrderBy("HRI", SortOrder::Descending));
analysisParameters.setOrderByFields(orderByFields);
analysisParameters.setWhereClause("HRI > 9");
featureTable->queryFeaturesAsync(analysisParameters, this)
.then(this, [this](FeatureQueryResult *rawQueryResult)
{
// Reference raw pointer
auto queryResult = std::unique_ptr<FeatureQueryResult>(rawQueryResult);
if (queryResult && !queryResult->iterator().hasNext())
{
// No results or invalid pointer
return;
}

QMap<double, QList<Feature*>> analysisGroups;
QList<Feature*> currentGroup;

// iterate over the result object
double lastValue = 9999;
while (queryResult->iterator().hasNext())
{
Feature *feature = queryResult->iterator().next(this);

// add every feature to the results view
double heatRiskIndexValue = round(feature->attributes()->attributeValue("HRI").toDouble());
if (lastValue == heatRiskIndexValue)
{
// add to the last group
currentGroup.append(feature);
}
else if (heatRiskIndexValue < lastValue)
{
// create a new group
analysisGroups.insert(heatRiskIndexValue, QList(currentGroup));
currentGroup.clear();
currentGroup.append(feature);
}
lastValue = heatRiskIndexValue;
}

for (auto groupIt = analysisGroups.keyValueBegin(); groupIt != analysisGroups.keyValueEnd(); ++groupIt)
{
qDebug() << groupIt->first;
qDebug() << groupIt->second.size();
}
});
});
featureTable->load();
});
gdb->load();

// add the elevation source to the scene to display elevation
m_scene->baseSurface()->elevationSources()->append(elevationSource);
}

UrbanHeatAnalyzer::~UrbanHeatAnalyzer() {}

SceneQuickView *UrbanHeatAnalyzer::sceneView() const
{
return m_sceneView;
}

// Set the view (created in QML)
void UrbanHeatAnalyzer::setSceneView(SceneQuickView *sceneView)
{
if (!sceneView || sceneView == m_sceneView) {
return;
}

m_sceneView = sceneView;
m_sceneView->setArcGISScene(m_scene);

emit sceneViewChanged();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright 2024 ESRI
//
// All rights reserved under the copyright laws of the United States
// and applicable international laws, treaties, and conventions.
//
// You may freely redistribute and use this sample code, with or
// without modification, provided you include the original copyright
// notice and use restrictions.
//
// See the Sample code usage restrictions document for further information.
//

#ifndef URBANHEATANALYZER_H
#define URBANHEATANALYZER_H

namespace Esri::ArcGISRuntime {
class Scene;
class SceneQuickView;
} // namespace Esri::ArcGISRuntime

#include <QObject>

Q_MOC_INCLUDE("SceneQuickView.h")

class UrbanHeatAnalyzer : public QObject
{
Q_OBJECT

Q_PROPERTY(Esri::ArcGISRuntime::SceneQuickView *sceneView READ sceneView WRITE setSceneView
NOTIFY sceneViewChanged)

public:
explicit UrbanHeatAnalyzer(QObject *parent = nullptr);
~UrbanHeatAnalyzer() override;

signals:
void sceneViewChanged();

private:
Esri::ArcGISRuntime::SceneQuickView *sceneView() const;
void setSceneView(Esri::ArcGISRuntime::SceneQuickView *sceneView);

Esri::ArcGISRuntime::Scene *m_scene = nullptr;
Esri::ArcGISRuntime::SceneQuickView *m_sceneView = nullptr;
};

#endif // URBANHEATANALYZER_H
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
IDI_ICON1 ICON DISCARDABLE "AppIcon.ico"
Loading

0 comments on commit 6e1b8f3

Please sign in to comment.