Skip to content

Commit

Permalink
Added selected heat risk graphics
Browse files Browse the repository at this point in the history
  • Loading branch information
esride-jts committed Nov 22, 2024
1 parent 2d21ae6 commit 6ad89e6
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 8 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 @@ -66,7 +105,31 @@ void HeatRiskListModel::loadAnalysisGroups(const QList<HeatRiskAnalysisGroup> &a

void HeatRiskListModel::select(int index)
{
qDebug() << 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 {
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 @@ -56,11 +65,19 @@ class HeatRiskListModel : public QAbstractListModel
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
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
14 changes: 11 additions & 3 deletions native-apps/urban-heat-analyzer/UrbanHeatAnalyzer/qml/main.qml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ ApplicationWindow {
width: 800
height: 600

title: "Urban Heat Analyzer"

Material.theme: Material.Dark
Material.accent: "#C9F2FF"
Material.background: "#0289C3"
Expand Down Expand Up @@ -65,13 +67,13 @@ ApplicationWindow {
Layout.alignment: Qt.AlignLeft
Layout.leftMargin: 10
color: Material.foreground
text: "<b>Name:</b>" + name
text: "<b>Name:</b> " + name
}
Text {
Layout.alignment: Qt.AlignLeft
Layout.leftMargin: 10
color: Material.foreground
text: "<b>Risk:</b>" + risk
text: "<b>Risk:</b> " + risk
}
}

Expand All @@ -80,7 +82,6 @@ ApplicationWindow {
onClicked: {
riskView.currentIndex = index;
mapForm.heatRiskListModel.select(index);
console.log(name);
}
}
}
Expand All @@ -97,6 +98,13 @@ ApplicationWindow {
focus: false
}
}

ToolButton {
text: qsTr("Clear")
onClicked: {
mapForm.clearOverlay();
}
}
}
}

Expand Down

0 comments on commit 6ad89e6

Please sign in to comment.