/** * @RDE_HEADER@ * Interface-Implementation of TerrainProfile * $Id$ * $HeadURL$ * $Author$ */ // Own #include "terrain_profile_impl.h" #include "terrain_profile_processor.h" #include "layer_factory_impl.h" #include "coord_translation_functor_impl.h" #include #include #include "Rubberbands/rubberband_factory.h" //ESRI #include // Qt #include #include #include #include namespace SituationMap { class TerrainProfileImpl::Private { public: Private() = default; ~Private() = default; // ESRI data: // Own data: SituationMap::MapImpl *m_mapImpl = nullptr; Esri::ArcGISRuntime::Surface *m_surface = nullptr; TerrainProfileParameter m_terrainProfileParameter; QPointer m_rubbandBase = nullptr; using COUNTER_T = long; static COUNTER_T m_terrainProfileCounter; QMap> m_terrainProfileMap; std::function< bool(long id, const QVector> &)> m_finishedCallback; }; // class TerrainProfileImpl::Private //----------------------------------------------------------------------------- TerrainProfileImpl::Private::COUNTER_T TerrainProfileImpl::Private::m_terrainProfileCounter = 0; //----------------------------------------------------------------------------- // class TerrainProfileImpl //----------------------------------------------------------------------------- TerrainProfileImpl::TerrainProfileImpl(SituationMap::MapImpl *mapImpl) : BaseClass() , QObject() , m_logger(getLogger("TerrainProfileImpl")) , d(new Private) { TRACE_LOG(m_logger) << LOGFUNCTION << " START"; d->m_mapImpl = mapImpl; TRACE_LOG(m_logger) << LOGFUNCTION << " END"; } TerrainProfileImpl::~TerrainProfileImpl() { TRACE_LOG(m_logger) << LOGFUNCTION << " START"; this->remove(); delete d; TRACE_LOG(m_logger) << LOGFUNCTION << " END"; } bool TerrainProfileImpl::isReady() { init(); bool isReady = d->m_surface && d->m_surface->loadStatus() == Esri::ArcGISRuntime::LoadStatus::Loaded && d->m_mapImpl->isReady(); if (!isReady) { Esri::ArcGISRuntime::LoadStatus ls = Esri::ArcGISRuntime::LoadStatus::Unknown; if (d->m_surface) ls = d->m_surface->loadStatus(); DEBUG_LOG(m_logger) << LOGFUNCTION << " d->m_surface = " << d->m_surface << " d->m_surface->loadStatus = " << ls << " d->m_mapImpl->isReady() = " << d->m_mapImpl->isReady(); } return isReady; } void TerrainProfileImpl::setFinishedCallback(const std::function< bool(long id, const QVector > &)> &finishedCallback) { d->m_finishedCallback = finishedCallback; } void TerrainProfileImpl::setTerrainProfileDialog(long id, QPointer &terrainProfileDialog) { if (!d->m_terrainProfileMap.contains(id)) { ERROR_LOG(m_logger) << LOGFUNCTION << " no proc found for id = " << id; return; } QPointer proc = d->m_terrainProfileMap[id]; if (!proc) return; proc->setTerrainProfileDialog(terrainProfileDialog); } bool TerrainProfileImpl::create() { TRACE_LOG(m_logger) << LOGFUNCTION << " START"; if (!isReady()) { ERROR_LOG(m_logger) << LOGFUNCTION << " failed, not ready"; return false; } // remove any pending/active rubberbands of our map: RB::Rubberband::deleteAllActiveRubberbands(d->m_mapImpl); // d->m_rubbandBase; should be cleared now const Mode mode = d->m_mapImpl->mode(); switch (mode) { case Mode::Mode_2D: d->m_rubbandBase = createRubberband2D(); break; case Mode::Mode_3D: // d->m_rubbandBase = createRubberband3D(); break; default: ERROR_LOG(m_logger) << LOGFUNCTION << " mode (" << mode << ")" << " does not support viewshed"; return false; break; } return true; } long TerrainProfileImpl::create(const TerrainProfileParameter &terrainProfileParameter) { DEBUG_LOG(m_logger) << LOGFUNCTION << " START" << " terrainProfileParameter: " << terrainProfileParameter; if (!isReady()) { ERROR_LOG(m_logger) << LOGFUNCTION << " failed, not ready"; return -1; } // remove all former this->remove(); // store current values: d->m_terrainProfileParameter = terrainProfileParameter; TerrainProfileProcessor *proc = new TerrainProfileProcessor(); if (!proc->init(d->m_mapImpl, d->m_terrainProfileCounter)) { ERROR_LOG(m_logger) << LOGFUNCTION << " init of TerrainProfileProcessor failed"; delete proc; return -1; } d->m_terrainProfileMap[d->m_terrainProfileCounter++] = proc; connect(proc, &TerrainProfileProcessor::locationsToElevationsCompleted, this, &TerrainProfileImpl::onLocationsToElevationsCompleted, Qt::UniqueConnection); // GlobalWaitDialog LtsWidgets::LtsGlobalWaitDialog::getInstance()->wait(); proc->start(d->m_terrainProfileParameter); TRACE_LOG(m_logger) << LOGFUNCTION << " END"; return d->m_terrainProfileCounter; } void TerrainProfileImpl::remove(long terrainProfileId) { TRACE_LOG(m_logger) << LOGFUNCTION << " START" << " terrainProfileId=" << terrainProfileId; if (terrainProfileId < 0) { for (const QPointer &proc : qAsConst(d->m_terrainProfileMap)) delete proc; d->m_terrainProfileMap.clear(); return; } if (d->m_terrainProfileMap.contains(terrainProfileId)) { QPointer proc = d->m_terrainProfileMap[terrainProfileId]; if (proc) delete d->m_terrainProfileMap[terrainProfileId]; d->m_terrainProfileMap.remove(terrainProfileId); } else ERROR_LOG(m_logger) << LOGFUNCTION << " terrainProfileId not found, id=" << terrainProfileId; TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " terrainProfileId=" << terrainProfileId; } void TerrainProfileImpl::init() { TRACE_LOG(m_logger) << LOGFUNCTION << " START"; if (!d->m_mapImpl) { ERROR_LOG(m_logger) << LOGFUNCTION << " no mapImpl"; return; } const LayerFactoryImpl &layerFactoryImpl = d->m_mapImpl->layerFactoryImpl(); if (!d->m_surface) d->m_surface = layerFactoryImpl.baseSurface(); TRACE_LOG(m_logger) << LOGFUNCTION << " END"; } RB::RubberbandMultiPointFeature *TerrainProfileImpl::createRubberband2D() { // remove any pending/active rubberbands of our map: RB::Rubberband::deleteAllActiveRubberbands(d->m_mapImpl); RB::RubberbandMultiPointFeature *rubberband = d->m_mapImpl->rubberbandFactory().create(this); if (!rubberband || !rubberband->rubberbandIsAlive()) { ERROR_LOG(m_logger) << LOGFUNCTION << " create2D failed"; return nullptr; } rubberband->setAutoDelete(true); connect(rubberband, &SituationMap::RB::Rubberband::abort, this, &TerrainProfileImpl::onRbAbort, Qt::UniqueConnection); connect(rubberband, &SituationMap::RB::Rubberband::apply, this, &TerrainProfileImpl::onRb2DApply, Qt::UniqueConnection); return rubberband; } /* RB::RubberbandMultiPointFeature3D *TerrainProfileImpl::createRubberband3D() { // remove any pending/active rubberbands of our map: RB::Rubberband::deleteAllActiveRubberbands(d->m_mapImpl); RB::RubberbandMultiPointFeature3D *rubberband = d->m_mapImpl->rubberbandFactory().create3D(this); if (!rubberband || !rubberband->rubberbandIsAlive()) { ERROR_LOG(m_logger) << LOGFUNCTION << " create3D failed"; return nullptr; } rubberband->setAutoDelete(true); // rubberband->constrainQuadratic(true); // rubberband->constrainOrthogonal(true); connect(rubberband, &SituationMap::RB::Rubberband::abort, this, &TerrainProfileImpl::onRbAbort, Qt::UniqueConnection); connect(rubberband, &SituationMap::RB::Rubberband::apply, this, &TerrainProfileImpl::onRb3DApply, Qt::UniqueConnection); return rubberband; } */ void TerrainProfileImpl::onRbAbort(RB::RubberbandBase *rbnd) { TRACE_LOG(m_logger) << LOGFUNCTION << " START"; if (!rbnd) return; DEBUG_LOG(m_logger) << LOGFUNCTION << " rb abort"; TRACE_LOG(m_logger) << LOGFUNCTION << " END"; } void TerrainProfileImpl::onRb2DApply(RB::RubberbandBase *rbnd) { TRACE_LOG(m_logger) << LOGFUNCTION << " START"; if (!rbnd) { ERROR_LOG(m_logger) << LOGFUNCTION << " no rubberband"; return; } RB::RubberbandMultiPointFeature *polyline = static_cast(rbnd); TerrainProfileParameter para; para.m_coordinates = convert2D3D(polyline->coordinateVector(RB::CoordinateSystem::Geo)); long id = this->create(para); if (id < 0) ERROR_LOG(m_logger) << LOGFUNCTION << " rubberband failed!?"; TRACE_LOG(m_logger) << LOGFUNCTION << " END" << " para.m_coordinates.size()= " << para.m_coordinates.size(); } void TerrainProfileImpl::onLocationsToElevationsCompleted(long id) { TRACE_LOG(m_logger) << LOGFUNCTION << " START" << ", id=" << id; // GlobalWaitDialog LtsWidgets::LtsGlobalWaitDialog::getInstance()->done(); const auto it = d->m_terrainProfileMap.find(id); // if (it == d->m_terrainProfileMap.constEnd()) // { // ERROR_LOG(m_logger) << LOGFUNCTION << " rubberband failed!?"; // return; // } QPointer proc = it.value(); if (!proc) return; const QVector> &resultList = proc->results(); INFO_LOG(m_logger) << LOGFUNCTION << " START" << " id =" << id << " m_locationToElevationBulk.resultList().size()=" << resultList.size(); if (d->m_finishedCallback) d->m_finishedCallback(id, resultList); else WARNING_LOG(m_logger) << LOGFUNCTION << " NO exe CallBack!?"; TRACE_LOG(m_logger) << LOGFUNCTION << " END" << ", id=" << id; } /* void TerrainProfileImpl::onRb3DApply(RB::RubberbandBase *rbnd) { TRACE_LOG(m_logger) << LOGFUNCTION << " START"; if (!rbnd) { ERROR_LOG(m_logger) << LOGFUNCTION << " no rubberband"; return; } RB::RubberbandMultiPointFeature3D *rubberband = static_cast(rbnd); const QVector &data = rubberband->coordinateVector(RB::CoordinateSystem::Map); // 3D -> RB::CoordinateSystem::Map -> degree if (data.isEmpty()) { ERROR_LOG(m_logger) << LOGFUNCTION << " rubberband failed!?"; return; } if (data.size() < 2) { ERROR_LOG(m_logger) << LOGFUNCTION << " insufficiant number of coords"; return; } ViewshedParameter viewshedParameter; // degree to rad const double factor = M_PI / 180.0; const QPointF ¢er = data.at(0) * factor; viewshedParameter.viewshedOrigin_latLon = center; if (data.size() >= 2) { static Esri::ArcGISRuntime::GeometryEngine *gEngine = Esri::ArcGISRuntime::GeometryEngine::instance(); const Esri::ArcGISRuntime::SpatialReference &sr = d->m_mapImpl->getEsriSpatialReference(); QPointF coord = data.at(0); Esri::ArcGISRuntime::Point geom1(coord.x(), coord.y(), sr); coord = data.at(1); Esri::ArcGISRuntime::Point geom2(coord.x(), coord.y(), sr); Esri::ArcGISRuntime::GeodeticDistanceResult geodeticDistanceResult = gEngine->distanceGeodetic(geom1, geom2, Esri::ArcGISRuntime::LinearUnitId::Meters, Esri::ArcGISRuntime::AngularUnitId::Degrees, Esri::ArcGISRuntime::GeodeticCurveType::Geodesic); viewshedParameter.outerRadius = geodeticDistanceResult.distance(); } long id = this->create(viewshedParameter); if (id < 0) { ERROR_LOG(m_logger) << LOGFUNCTION << " rubberband failed!?"; } TRACE_LOG(m_logger) << LOGFUNCTION << " END"; } */ } // namespace SituationMap