Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
esride-ale committed Nov 25, 2024
2 parents 0a337a8 + ab43e87 commit 892ac6c
Show file tree
Hide file tree
Showing 7 changed files with 181 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

#include "AttributeListModel.h"
#include "Feature.h"
#include "Geometry.h"
#include "GeometryEngine.h"

using namespace Esri::ArcGISRuntime;

Expand All @@ -26,6 +28,32 @@ HeatRiskAnalysisGroup::HeatRiskAnalysisGroup(double heatRiskIndex)

}

bool HeatRiskAnalysisGroup::operator==(const HeatRiskAnalysisGroup &other) const
{
if (m_heatRiskIndex != other.m_heatRiskIndex)
{
return false;
}

if (m_heatRiskFeatures.count() != other.m_heatRiskFeatures.count())
{
return false;
}

// Compare features just using the geometry
for (auto index=0; index < m_heatRiskFeatures.count(); index++)
{
auto feature = m_heatRiskFeatures[index];
auto otherFeature = other.m_heatRiskFeatures[index];
if (!feature->geometry().equalsWithTolerance(otherFeature->geometry(), 0.001))
{
return false;
}
}

return true;
}

QString HeatRiskAnalysisGroup::name() const
{
if (m_heatRiskFeatures.empty())
Expand All @@ -47,6 +75,17 @@ void HeatRiskAnalysisGroup::addFeature(Feature *heatRiskFeature)
m_heatRiskFeatures.append(heatRiskFeature);
}

Geometry HeatRiskAnalysisGroup::areaOfInterest()
{
QList<Geometry> geometries;
for (auto heatRiskFeature : m_heatRiskFeatures)
{
geometries.append(heatRiskFeature->geometry());
}

return GeometryEngine::unionOf(geometries);
}


HeatRiskListModel::HeatRiskListModel(QObject *parent)
: QAbstractListModel{parent}
Expand All @@ -64,12 +103,41 @@ void HeatRiskListModel::loadAnalysisGroups(const QList<HeatRiskAnalysisGroup> &a
emit dataChanged(index(0,0), index(rowCount() - 1));
}

int HeatRiskListModel::rowCount(const QModelIndex & parent) const {
void HeatRiskListModel::select(int index)
{
if (m_selectedIndex != index)
{
m_selectedIndex = index;
emit selectedHeatRiskItemChanged();
}
}

HeatRiskAnalysisGroup* HeatRiskListModel::selectedGroup() const
{
if (m_selectedIndex < 0 || m_analysisGroups.count() <= m_selectedIndex)
{
return nullptr;
}

return &const_cast<HeatRiskListModel*>(this)->m_analysisGroups[m_selectedIndex];
}

void HeatRiskListModel::setSelectedGroup(HeatRiskAnalysisGroup *group)
{
auto index_of = m_analysisGroups.indexOf(*group);
if (m_selectedIndex != index_of)
{
m_selectedIndex = index_of;
emit selectedHeatRiskItemChanged();
}
}

int HeatRiskListModel::rowCount(const QModelIndex &parent) const {
Q_UNUSED(parent);
return m_analysisGroups.count();
}

QVariant HeatRiskListModel::data(const QModelIndex & index, int role) const {
QVariant HeatRiskListModel::data(const QModelIndex &index, int role) const {
if (index.row() < 0 || index.row() >= m_analysisGroups.count())
return QVariant();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

namespace Esri::ArcGISRuntime {
class Feature;
class Geometry;
} // namespace Esri::ArcGISRuntime


Expand All @@ -32,6 +33,9 @@ class HeatRiskAnalysisGroup
double heatRiskIndex() const;

void addFeature(Esri::ArcGISRuntime::Feature *heatRiskFeature);
Esri::ArcGISRuntime::Geometry areaOfInterest();

bool operator==(const HeatRiskAnalysisGroup &other) const;

private:
double m_heatRiskIndex;
Expand All @@ -42,6 +46,11 @@ class HeatRiskAnalysisGroup
class HeatRiskListModel : public QAbstractListModel
{
Q_OBJECT

Q_PROPERTY(HeatRiskAnalysisGroup *selectedGroup
READ selectedGroup WRITE setSelectedGroup
NOTIFY selectedHeatRiskItemChanged)

public:
enum HeatRiskRoles {
NameRole = Qt::UserRole + 1,
Expand All @@ -51,15 +60,24 @@ class HeatRiskListModel : public QAbstractListModel
explicit HeatRiskListModel(QObject *parent = nullptr);

void loadAnalysisGroups(const QList<HeatRiskAnalysisGroup> &analysisGroups);
Q_INVOKABLE void select(int index);

int rowCount(const QModelIndex & parent = QModelIndex()) const;
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;

HeatRiskAnalysisGroup *selectedGroup() const;

signals:
void selectedHeatRiskItemChanged();

protected:
QHash<int, QByteArray> roleNames() const;

private:
void setSelectedGroup(HeatRiskAnalysisGroup *group);

QList<HeatRiskAnalysisGroup> m_analysisGroups;
int m_selectedIndex = -1;
};

#endif // HEATRISKLISTMODEL_H
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@
#include "FeatureQueryResult.h"
#include "Geodatabase.h"
#include "GeodatabaseFeatureTable.h"
#include "Graphic.h"
#include "GraphicListModel.h"
#include "GraphicsOverlay.h"
#include "GraphicsOverlayListModel.h"
#include "LayerListModel.h"
#include "MapTypes.h"
#include "OrderBy.h"
Expand All @@ -44,11 +48,15 @@
#include "Scene.h"
#include "SceneQuickView.h"
#include "ServiceFeatureTable.h"
#include "SimpleFillSymbol.h"
#include "SimpleRenderer.h"
#include "SpatialReference.h"
#include "Surface.h"
#include "SymbolTypes.h"
#include "VectorTileCache.h"
#include "Viewpoint.h"

#include <QColor>
#include <QFuture>
#include <QUrl>

Expand All @@ -59,6 +67,7 @@ using namespace Esri::ArcGISRuntime;
UrbanHeatAnalyzer::UrbanHeatAnalyzer(QObject *parent /* = nullptr */)
: QObject(parent)
, m_scene(new Scene(BasemapStyle::OsmStandard, this))
, m_heatRiskOverlay(new GraphicsOverlay(this))
{
// create a new scene layer from OSM Buildings rest service
ArcGISSceneLayer *osmSceneLayer = new ArcGISSceneLayer(
Expand Down Expand Up @@ -110,6 +119,17 @@ UrbanHeatAnalyzer::UrbanHeatAnalyzer(QObject *parent /* = nullptr */)
loadHeatRiskFeatures();
});
m_scene->operationalLayers()->append(tiledLayer);

// define the heat risk overlay rendering
SimpleFillSymbol *heatRiskFillSymbol = new SimpleFillSymbol(
SimpleFillSymbolStyle::Solid,
QColor("cyan"),
this);
SimpleRenderer *heatRiskRenderer = new SimpleRenderer(
heatRiskFillSymbol,
this);
m_heatRiskOverlay->setRenderer(heatRiskRenderer);
m_heatRiskOverlay->setOpacity(0.75f);
}

UrbanHeatAnalyzer::~UrbanHeatAnalyzer() {}
Expand All @@ -130,6 +150,9 @@ void UrbanHeatAnalyzer::setSceneView(SceneQuickView *sceneView)
m_sceneView = sceneView;
m_sceneView->setArcGISScene(m_scene);

// add the graphics overlay
m_sceneView->graphicsOverlays()->append(m_heatRiskOverlay);

emit sceneViewChanged();
}

Expand All @@ -141,6 +164,27 @@ void UrbanHeatAnalyzer::setHeatRiskListModel(HeatRiskListModel *heatRiskListMode
}

m_heatRiskListModel = heatRiskListModel;
connect(m_heatRiskListModel, &HeatRiskListModel::selectedHeatRiskItemChanged, this, [this]()
{
HeatRiskAnalysisGroup *riskGroup = m_heatRiskListModel->selectedGroup();
if (!riskGroup)
{
return;
}

if (m_sceneView)
{
// Zoom to area of interest
Geometry areaOfInterest = riskGroup->areaOfInterest();
Viewpoint newViewpoint = Viewpoint(areaOfInterest);
m_sceneView->setViewpointAsync(newViewpoint, 2.5);

// Add a new graphic visualizing the area of interest
m_heatRiskOverlay->graphics()->clear();
Graphic *heatRiskArea = new Graphic(areaOfInterest, this);
m_heatRiskOverlay->graphics()->append(heatRiskArea);
}
});
}

void UrbanHeatAnalyzer::loadHeatRiskFeatures()
Expand All @@ -154,9 +198,6 @@ void UrbanHeatAnalyzer::loadHeatRiskFeatures()
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;
Expand All @@ -168,7 +209,7 @@ void UrbanHeatAnalyzer::loadHeatRiskFeatures()
{
// Reference raw pointer
auto queryResult = std::unique_ptr<FeatureQueryResult>(rawQueryResult);
if (queryResult && !queryResult->iterator().hasNext())
if (!queryResult && !queryResult->iterator().hasNext())
{
// No results or invalid pointer
return;
Expand Down Expand Up @@ -216,6 +257,16 @@ void UrbanHeatAnalyzer::loadHeatRiskFeatures()
gdb->load();
}

void UrbanHeatAnalyzer::clearOverlay()
{
if (!m_heatRiskOverlay)
{
return;
}

m_heatRiskOverlay->graphics()->clear();
}

void UrbanHeatAnalyzer::printCamera()
{
auto camera = m_sceneView->currentViewpointCamera();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
class HeatRiskListModel;

namespace Esri::ArcGISRuntime {
class GraphicsOverlay;
class Scene;
class SceneQuickView;
} // namespace Esri::ArcGISRuntime
Expand All @@ -49,6 +50,7 @@ class UrbanHeatAnalyzer : public QObject
explicit UrbanHeatAnalyzer(QObject *parent = nullptr);
~UrbanHeatAnalyzer() override;

Q_INVOKABLE void clearOverlay();
Q_INVOKABLE void printCamera();

signals:
Expand All @@ -65,6 +67,8 @@ class UrbanHeatAnalyzer : public QObject
Esri::ArcGISRuntime::Scene *m_scene = nullptr;
Esri::ArcGISRuntime::SceneQuickView *m_sceneView = nullptr;
HeatRiskListModel *m_heatRiskListModel = nullptr;
Esri::ArcGISRuntime::GraphicsOverlay *m_heatRiskOverlay = nullptr;

};

#endif // URBANHEATANALYZER_H
17 changes: 16 additions & 1 deletion native-apps/urban-heat-analyzer/UrbanHeatAnalyzer/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#include "UrbanHeatAnalyzer.h"

#include "ArcGISRuntimeEnvironment.h"
#include "CoreTypes.h"
#include "LicenseResult.h"
#include "SceneQuickView.h"

#include <QDir>
Expand Down Expand Up @@ -61,6 +63,7 @@ int main(int argc, char *argv[])
// 2. API key authentication: Get a long-lived access token that gives your application access to
// ArcGIS location services. Go to the tutorial at https://links.esri.com/create-an-api-key.
// Copy the API Key access token.
#ifdef QT_DEBUG
QString accessToken;
QString apiKeyName = "ARCGIS_API_KEY";
QProcessEnvironment systemEnvironment = QProcessEnvironment::systemEnvironment();
Expand All @@ -79,12 +82,24 @@ int main(int argc, char *argv[])
{
ArcGISRuntimeEnvironment::setApiKey(accessToken);
}
#else
ArcGISRuntimeEnvironment::setApiKey("API KEY");

// Production deployment of applications built with ArcGIS Maps SDK requires you to
// license ArcGIS Maps SDK functionality. For more information see
// https://links.esri.com/arcgis-runtime-license-and-deploy.

// ArcGISRuntimeEnvironment::setLicense("Place license string in here");
LicenseResult licenseResult = ArcGISRuntimeEnvironment::setLicense("Place license string in here");
switch (licenseResult.licenseStatus())
{
case LicenseStatus::Valid:
break;

default:
qWarning()
<< "You need a runtime deployment license!";
}
#endif

// Register the scene view for QML
qmlRegisterType<SceneQuickView>("Esri.UrbanHeatAnalyzer", 1, 0, "SceneView");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ Item {
// Define a property for HeatRiskListModel
property HeatRiskListModel heatRiskListModel: riskModel

function clearOverlay() {
model.clearOverlay();
}

function printCamera() {
model.printCamera();
}
Expand Down
Loading

0 comments on commit 892ac6c

Please sign in to comment.