/** * @RDE_HEADER@ * Declaration/Definition * $Id$ * $HeadURL$ * $Author$ */ #include "Viewshed.h" // Qt #include #include #include #include #include #include // Esri #include #include #include #include #include #include // Uncomment if needed //#include //#include //#include //#include //#include //#include //#define USE_SAMPLE_SERVER EsriRuntimeQt::SpatialReference sr(102100); mainwindow::mainwindow(QWidget *parent) : QMainWindow(parent) { m_map = new EsriRuntimeQt::Map(this); connect(m_map, SIGNAL(mapReady()), this, SLOT(onMapReady())); m_mapGraphicsView = EsriRuntimeQt::MapGraphicsView::create(m_map, this); setCentralWidget(m_mapGraphicsView); m_map->setWrapAroundEnabled(false); // create and add the tiled layer EsriRuntimeQt::ArcGISTiledMapServiceLayer* mapServiceLayer = new EsriRuntimeQt::ArcGISTiledMapServiceLayer(QLatin1String("http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer"), this); m_map->addLayer(mapServiceLayer); QString path = EsriRuntimeQt::ArcGISRuntime::installDirectory(); path.append(QLatin1String("/sdk/samples/data")); QDir dataDir(path); // using QDir to convert to correct file separator QString pathSampleData = dataDir.path() + QDir::separator(); qDebug() << " installDirectory='" << path << "'"; QString tiledBaseMapLayer = pathSampleData + QLatin1String("tpks/Topographic.tpk"); qDebug() << " tiledBaseMapLayer='" << tiledBaseMapLayer << "'"; // m_tiledLayer = new EsriRuntimeQt::ArcGISLocalTiledLayer(tiledBaseMapLayer, this); // m_tiledLayer->setName( QLatin1String("ArcGISLocalTiledLayer") ); // m_map->addLayer(m_tiledLayer); // Create Graphics Layer m_graphicsLayer = new EsriRuntimeQt::GraphicsLayer(this); m_graphicsLayer -> setName(QLatin1String("GraphicsLayer")); m_map->addLayer(m_graphicsLayer); // { // // // // Create red circle at maps origin // // // EsriRuntimeQt::Point nullPoint(0, 0, m_map->spatialReference()); // EsriRuntimeQt::SimpleMarkerSymbol redCircle(Qt::red, 20, EsriRuntimeQt::SimpleMarkerSymbolStyle::Circle); // EsriRuntimeQt::Graphic* graphic1 = new EsriRuntimeQt::Graphic( nullPoint, redCircle); // qint64 gId = m_graphicsLayer->addGraphic(graphic1); // // // // Get access to graphic and hide: -> Works fine :-) // // // EsriRuntimeQt::Graphic* graphicRetrieved = m_graphicsLayer->graphic(gId); // if (graphicRetrieved) // { // graphicRetrieved->setVisible(false); // } else { // qWarning() << LOGFUNCTION << "could NOT retrieve graphic" ; // } // } QString url; #ifdef USE_SAMPLE_SERVER url = QLatin1String("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Elevation/ESRI_Elevation_World/GPServer/Viewshed"); #else url = QLatin1String("http://elevation.arcgis.com/arcgis/rest/services/Tools/Elevation/GPServer/Viewshed"); #endif qDebug() << LOGFUNCTION << " url='" << url << "'"; // create a Geoprocessor that points to the remote geoprocessing service. EsriRuntimeQt::UserCredentials *ucEsri = new EsriRuntimeQt::UserCredentials; ucEsri->setUserAccount("norbert.thoden", "RDEESRI7"); m_geoprocessor = new EsriRuntimeQt::Geoprocessor(url, ucEsri, this); connect(m_geoprocessor, SIGNAL(gpError(const EsriRuntimeQt::ServiceError&)), this, SLOT(onGpError(const EsriRuntimeQt::ServiceError&))); #ifdef USE_SAMPLE_SERVER connect(m_geoprocessor, SIGNAL(gpExecuteComplete(const QList&)), this, SLOT(onGpExecuteComplete(const QList&))); #else connect(m_geoprocessor, SIGNAL(gpSubmitJobComplete(const EsriRuntimeQt::GPJobResource&)), this, SLOT(onGpSubmitJobComplete(const EsriRuntimeQt::GPJobResource&))); // used: connect(m_geoprocessor, SIGNAL(gpJobStatusComplete(const EsriRuntimeQt::GPJobResource&)), this, SLOT(onGpJobStatusComplete(const EsriRuntimeQt::GPJobResource&))); // used: connect(m_geoprocessor, SIGNAL(gpResultComplete(EsriRuntimeQt::GPParameter*)), this, SLOT(onGpResultComplete(EsriRuntimeQt::GPParameter*))); // unused!? connect(m_geoprocessor, SIGNAL(gpServiceInfoComplete(EsriRuntimeQt::GPServiceInfo)), this, SLOT(onGpServiceInfoComplete(EsriRuntimeQt::GPServiceInfo))); // unused!? connect(m_geoprocessor, SIGNAL(gpSubmitJobAndGetResultComplete(const EsriRuntimeQt::GPJobResource&, const QList&)), this, SLOT(onGpSubmitJobAndGetResultComplete(const EsriRuntimeQt::GPJobResource&, const QList&))); // unused!? connect(m_geoprocessor, SIGNAL(statusUpdated(const EsriRuntimeQt::GPJobResource&, const QList&)), this, SLOT(onStatusUpdated(const EsriRuntimeQt::GPJobResource&, const QList&))); // unused!? connect(m_geoprocessor, SIGNAL(gpTaskInfoComplete(EsriRuntimeQt::GPTaskInfo)), this, SLOT(onGpTaskInfoComplete(const EsriRuntimeQt::GPTaskInfo&))); #endif // connect signals connect(m_map, SIGNAL(mapReady()), this, SLOT(onMapReady())); connect(m_map, SIGNAL(mousePressRelease(QMouseEvent&)), this, SLOT(onMousePressRelease(QMouseEvent&))); // // set up progress bar // m_progressDialog = new QProgressDialog(); // m_progressDialog->setBaseSize(280, 20); // m_progressDialog->setRange(0, 0); // m_progressDialog->setValue(0); // m_progressDialog->setCancelButton(0); // connect(m_mapGraphicsView->scene(), SIGNAL(sceneRectChanged(QRectF)), this, SLOT(onResizeProgressBar())); // m_progressDialog->setLabelText(""); // m_progressDialog->setAttribute(Qt::WA_NoBackground); // m_progressDialog->setAutoFillBackground(false); // m_progressDialog->setVisible(false); // WidgetPanel* widget = new WidgetPanel(); // QLabel* instructionsLabel = new QLabel( // QString("Click on the map to set the viewshed point. The viewshed will be computed ") + // QString("from the specified buffer area around the viewshed point. ")); // instructionsLabel->setWordWrap(true); // QFont font; // font.setPixelSize(11); // instructionsLabel->setFont(font); // instructionsLabel->setMargin(5); // instructionsLabel->setObjectName("instructions"); // instructionsLabel->setStyleSheet("QLabel#instructions { background: rgba(0,0,0, 192); color: #ddd; }"); // instructionsLabel->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding)); // // QVBoxLayout* layout = new QVBoxLayout(); // layout->setMargin(0); //// layout->addWidget(instructionsLabel, Qt::AlignLeft); // QHBoxLayout* horizontalBox = new QHBoxLayout(); // horizontalBox->setMargin(1); // QFont font; // font.setPixelSize(12); // QLabel* distanceLabel = new QLabel("Viewshed Buffer (miles):"); // distanceLabel->setFixedSize(180, 25); // distanceLabel->setFont(font); // distanceLabel->setMargin(5); // horizontalBox->addWidget(distanceLabel, Qt::AlignRight); // m_textDistanceLineEdit = new QLineEdit("9"); // m_textDistanceLineEdit->setFixedSize(60, 25); // m_textDistanceLineEdit->setFont(font); // horizontalBox->addWidget(m_textDistanceLineEdit, Qt::AlignLeft); // layout->addLayout(horizontalBox); //// widget->setFixedSize(210, 105); //// widget->setLayout(layout); // QGraphicsProxyWidget *proxy = m_mapGraphicsView->scene()->addWidget(widget); // proxy->setPos(10, 10); // proxy->setAcceptedMouseButtons(Qt::LeftButton); // proxy->setFlag(QGraphicsItem::ItemIsFocusable, true); // proxy->setFlag(QGraphicsItem::ItemIsSelectable, true); // proxy->setFlag(QGraphicsItem::ItemAcceptsInputMethod, true); // proxy->setOpacity(0.85); // m_proxyProgressBar = m_mapGraphicsView->scene()->addWidget(m_progressDialog); // m_proxyProgressBar->setAcceptedMouseButtons(Qt::NoButton); // m_proxyProgressBar->setFlag(QGraphicsItem::ItemIsSelectable, false); // m_viewShed = new // SituationMap::ViewshedBase( // m_geoprocessor->url() // , *m_graphicsLayer, // this); // bool init = m_viewShed->init(); // qDebug() << LOGFUNCTION << " init=" << init; } /* mainwindow::mainwindow */ mainwindow::~mainwindow() { } void mainwindow::onMapReady() { qDebug() << LOGFUNCTION << " ready"; // m_map->setExtent(EsriRuntimeQt::Envelope(-10000, -10000, 10000, 10000, sr)); m_map->setExtent(EsriRuntimeQt::Envelope(-13386516, 4516694, -13236394, 4616827, m_map->spatialReference())); m_srMap = m_map->spatialReference(); } void mainwindow::onMousePressRelease(QMouseEvent &event) { qDebug() << LOGFUNCTION; if (event.button() != Qt::LeftButton) return; if (m_inProgress) return; QPoint scenePosition = event.pos(); // // make sure the mouse didn't move - if so it was a pan so do nothing // QGraphicsItem * graphicsItem = nullptr; // graphicsItem = itemFromQGraphicsScene(m_mapGraphicsView->scene(), scenePosition); // if (graphicsItem) // return; // Clicked item box // remove viewshed from previous computation m_graphicsLayer->removeAll(); int inputValue = 10; // inputValue = m_textDistanceLineEdit->text().toInt(); if (inputValue > 12 || inputValue < 1) { if (m_progressDialog) m_progressDialog->setVisible(false); QMessageBox::warning(this, "Invalid Distance", "Please enter an integer from 1 to 12."); return; } // the click point is the viewshed point EsriRuntimeQt::Point viewshedPoint = m_map->toMapPoint(scenePosition.x(), scenePosition.y()); qDebug() << LOGFUNCTION<< " esriViewshedPoint.x=" << viewshedPoint.x() << " ;y=" << viewshedPoint.y() << " wkid=" << viewshedPoint.spatialReference().wkid() << " m_inProgress=" << m_inProgress ; // make sure it is a point on the map if (!EsriRuntimeQt::GeometryEngine::within(viewshedPoint, m_map->extent())) return; m_inProgress = true; if (m_progressDialog) { m_progressDialog->setLabelText("Computing the viewshed..."); m_progressDialog->setVisible(true); } EsriRuntimeQt::Graphic* viewshedPointGraphic = new EsriRuntimeQt::Graphic(viewshedPoint, EsriRuntimeQt::SimpleMarkerSymbol(QColor("Black"), 14, EsriRuntimeQt::SimpleMarkerSymbolStyle::X)); m_graphicsLayer->addGraphic(viewshedPointGraphic); // initialize the input parameters. refer to help link in the geoprocessing service URL. m_geoprocessor->setProcessSR(m_srMap); m_geoprocessor->setOutSR(m_srMap); QList gpInputParams; #ifdef USE_SAMPLE_SERVER EsriRuntimeQt::GPFeatureRecordSetLayer* gpInputViewshedPoint = new EsriRuntimeQt::GPFeatureRecordSetLayer("Input_Observation_Point", this); #else EsriRuntimeQt::GPFeatureRecordSetLayer* gpInputViewshedPoint = new EsriRuntimeQt::GPFeatureRecordSetLayer("InputPoints", this); #endif gpInputViewshedPoint->setSpatialReference(m_srMap); gpInputViewshedPoint->addGraphic(qobject_cast(viewshedPointGraphic->clone(this))); #ifdef USE_SAMPLE_SERVER EsriRuntimeQt::GPLinearUnit* gpInputViewshedDistance = new EsriRuntimeQt::GPLinearUnit("Viewshed_Distance", this); gpInputViewshedDistance->setUnits("esriMiles"); gpInputViewshedDistance->setDistance(inputValue); gpInputParams.append(gpInputViewshedPoint); gpInputParams.append(gpInputViewshedDistance); #else EsriRuntimeQt::GPDouble* gpInputMaxDistance = new EsriRuntimeQt::GPDouble("MaximumDistance", this); gpInputMaxDistance->setValue(inputValue); EsriRuntimeQt::GPString* gpInputMaxDistanceUnits = new EsriRuntimeQt::GPString("MaximumDistanceUnits", this); gpInputMaxDistanceUnits->setValue(QLatin1String("Miles")); EsriRuntimeQt::GPDouble* gpInputObserverHeight = new EsriRuntimeQt::GPDouble("ObserverHeight", this); gpInputObserverHeight->setValue(3000); // [Meter] EsriRuntimeQt::GPBoolean* gpInputGeneralize = new EsriRuntimeQt::GPBoolean("GeneralizeViewshedPolygons", this); gpInputGeneralize->setValue(false); gpInputParams.append(gpInputViewshedPoint); gpInputParams.append(gpInputMaxDistance); gpInputParams.append(gpInputMaxDistanceUnits); gpInputParams.append(gpInputObserverHeight); // gpInputParams.append(gpInputGeneralize); #endif // execute the geoprocessing request // ------------------------------------------------------------------------------------- // Option 1 - execute sync // Client execution will happen in this thread. It will be blocked on server. // Client side result collection will happen in this thread. It will be blocked on server. // // This is ideal for jobs that take less processing time and whose result size is small. // This will freeze the UI. // ------------------------------------------------------------------------------------- /*QList result = m_geoprocessor->execute(gpInputParams); processResult(result);*/ // ------------------------------------------------------------------------------------- // Option 2 - execute async // Client execution will happen in a new thread. It will be blocked on server. // Client side result collection will happen on that thread. It will be blocked on server. // // This is ideal for jobs that take relatively more processing time than option 1 // and whose result size is small. // ------------------------------------------------------------------------------------- // m_geoprocessor->execute(gpInputParams); m_geoprocessor->setStatusPollingInterval(10); #ifdef USE_SAMPLE_SERVER m_geoprocessor->execute( gpInputParams ); #else m_geoprocessor->submitJob(gpInputParams); #endif } void mainwindow::onGpExecuteComplete(const QList &result) { qDebug() << LOGFUNCTION << " result.size()=" << result.size(); foreach (EsriRuntimeQt::GPParameter* outputParameter, result) { if (!outputParameter) continue; EsriRuntimeQt::GPFeatureRecordSetLayer* gpLayer = qobject_cast(outputParameter); if (gpLayer) { qDebug() << LOGFUNCTION << " gpLayer->graphics().size=" << gpLayer->graphics().size(); // get all the graphics and add them to the graphics layer. foreach (EsriRuntimeQt::Graphic* resultGraphic, gpLayer->graphics()) { EsriRuntimeQt::Graphic* theGraphic = new EsriRuntimeQt::Graphic(resultGraphic->geometry(), EsriRuntimeQt::SimpleFillSymbol(QColor(255, 0, 0, 80), EsriRuntimeQt::SimpleFillSymbolStyle::Solid, EsriRuntimeQt::SimpleLineSymbol(QColor("Red"), 0.5))); // add to the graphics layer m_graphicsLayer->addGraphic(theGraphic); } } outputParameter->deleteLater(); } if (m_progressDialog) m_progressDialog->setVisible(false); m_inProgress = false; } void mainwindow::onGpError(const EsriRuntimeQt::ServiceError &error) { if (m_progressDialog) m_progressDialog->setVisible(false); qWarning() << LOGFUNCTION << QString("Service Error, code: %1, message: %2, details: %3").arg(QString::number(error.code()), error.message(), error.details()); m_inProgress = false; } void mainwindow::onGpSubmitJobComplete(const EsriRuntimeQt::GPJobResource &jobResource) { qWarning() << "\n"; qWarning() << LOGFUNCTION << " isEmpty=" << jobResource.isEmpty(); qWarning() << LOGFUNCTION << " jobId='" << jobResource.jobId() << "'"; qWarning() << LOGFUNCTION << " jobStatus='" << (int)jobResource.jobStatus() << "'"; qWarning() << LOGFUNCTION << " inputParameters().size()='" << (int)jobResource.inputParameters().size() << "'"; qWarning() << LOGFUNCTION << " outputParameters().size()='" << (int)jobResource.outputParameters().size() << "'"; qWarning() << LOGFUNCTION << " messages().size()='" << (int)jobResource.messages().size() << "'"; delete m_timer; m_timer = new QTimer; connect(m_timer, &QTimer::timeout, [=]() { qWarning() << " jobStatus() ..."; m_geoprocessor->jobStatus(); } ); qWarning() << "\n starting timer..."; m_timer->start(1000); } void mainwindow::onGpJobStatusComplete(const EsriRuntimeQt::GPJobResource &jobResource) { qWarning() << "\n"; qWarning() << LOGFUNCTION << " isEmpty=" << jobResource.isEmpty(); qWarning() << LOGFUNCTION << " jobId='" << jobResource.jobId() << "'"; qWarning() << LOGFUNCTION << " jobStatus='" << (int)jobResource.jobStatus() << "'"; qWarning() << LOGFUNCTION << " inputParameters().size()='" << (int)jobResource.inputParameters().size() << "'"; qWarning() << LOGFUNCTION << " outputParameters().size()='" << (int)jobResource.outputParameters().size() << "'"; qWarning() << LOGFUNCTION << " messages().size()='" << (int)jobResource.messages().size() << "'"; if (jobResource.jobStatus() == EsriRuntimeQt::JobStatus::Succeeded) { qWarning() << " Succeeded :-)"; if (m_timer) m_timer->stop(); m_geoprocessor->result(jobResource, QLatin1String("OutputViewshed"), true); // GetAsImageResult } } void mainwindow::onGpResultComplete(EsriRuntimeQt::GPParameter *outputParameter) { qWarning() << "\n"; qWarning() << LOGFUNCTION << " outputParameter=" << outputParameter; if (outputParameter) { EsriRuntimeQt::GPFeatureRecordSetLayer* gpLayer = qobject_cast(outputParameter); if (gpLayer) { qDebug() << LOGFUNCTION << " gpLayer->graphics().size=" << gpLayer->graphics().size(); // get all the graphics and add them to the graphics layer. foreach (EsriRuntimeQt::Graphic* resultGraphic, gpLayer->graphics()) { EsriRuntimeQt::Graphic* theGraphic = new EsriRuntimeQt::Graphic(resultGraphic->geometry(), EsriRuntimeQt::SimpleFillSymbol(QColor(0, 255, 0, 80), EsriRuntimeQt::SimpleFillSymbolStyle::Solid, EsriRuntimeQt::SimpleLineSymbol(QColor("Red"), 0.5))); // add to the graphics layer m_graphicsLayer->addGraphic(theGraphic); } } outputParameter->deleteLater(); } } void mainwindow::onGpServiceInfoComplete(EsriRuntimeQt::GPServiceInfo serviceInfo) { qWarning() << "\n"; qWarning() << LOGFUNCTION ; } void mainwindow::onGpSubmitJobAndGetResultComplete(const EsriRuntimeQt::GPJobResource &, const QList &results) { qWarning() << "\n"; qWarning() << LOGFUNCTION ; } void mainwindow::onStatusUpdated(const EsriRuntimeQt::GPJobResource &jobResource, const QList &msgList) { qWarning() << "\n"; qWarning() << LOGFUNCTION << " isEmpty=" << jobResource.isEmpty(); qWarning() << LOGFUNCTION << " jobId='" << jobResource.jobId() << "'"; qWarning() << LOGFUNCTION << " jobStatus='" << (int)jobResource.jobStatus() << "'"; qWarning() << LOGFUNCTION << " inputParameters().size()='" << (int)jobResource.inputParameters().size() << "'"; qWarning() << LOGFUNCTION << " outputParameters().size()='" << (int)jobResource.outputParameters().size() << "'"; qWarning() << LOGFUNCTION << " messages().size()='" << (int)jobResource.messages().size() << "'"; qWarning() << LOGFUNCTION << " 2 msgList().size()='" << msgList.size() << "'"; m_geoprocessor->jobStatus(); } void mainwindow::onGpTaskInfoComplete(const EsriRuntimeQt::GPTaskInfo &) { qWarning() << "\n"; qWarning() << LOGFUNCTION ; }