Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
+880
@@ -0,0 +1,880 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Interface-Implementation of Viewshed
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
// Own
|
||||
#include "viewshed_impl.h"
|
||||
#include "viewshed_analysis.h"
|
||||
#include "viewshed_geo_processing.h"
|
||||
#include "layer_factory_impl.h"
|
||||
|
||||
#include "coord_translation_functor_impl.h"
|
||||
#include <LtsCoordTrans/lts_coord_trans.h>
|
||||
|
||||
#include <Map/object_factory.h>
|
||||
#include <Map/sight_fan.h>
|
||||
|
||||
#include <MathUtils/math_const.h>
|
||||
#include <MathUtils/simple_helper.h>
|
||||
|
||||
#include "Rubberbands/rubberband_factory.h"
|
||||
|
||||
|
||||
// Qt
|
||||
|
||||
|
||||
namespace SituationMap
|
||||
{
|
||||
|
||||
class ViewshedImpl::Private
|
||||
{
|
||||
public:
|
||||
Private() = default;
|
||||
~Private() = default;
|
||||
|
||||
// ESRI data:
|
||||
|
||||
// Own data:
|
||||
SituationMap::MapImpl *m_mapImpl = nullptr;
|
||||
|
||||
QPointer<RB::RubberbandBase> m_rubbandBase = nullptr;
|
||||
|
||||
QString m_url;
|
||||
|
||||
Esri::ArcGISRuntime::GraphicsOverlay *m_graphicsLayer = nullptr; // graphicsLayer used in 2D
|
||||
|
||||
ViewshedParameter m_viewshedParameter;
|
||||
|
||||
using COUNTER_T = long;
|
||||
static COUNTER_T m_viewshedCounter;
|
||||
QMap<COUNTER_T, ViewshedBase* > m_viewshedMap;
|
||||
QMap<COUNTER_T, SightFan*> m_sightFanMap;
|
||||
|
||||
}; // class ViewshedImpl::Private
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ViewshedImpl::Private::COUNTER_T ViewshedImpl::Private::m_viewshedCounter = 0;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// class ViewshedImpl
|
||||
//-----------------------------------------------------------------------------
|
||||
ViewshedImpl::ViewshedImpl(SituationMap::MapImpl *mapImpl)
|
||||
: BaseClass()
|
||||
, m_logger(getLogger("ViewshedImpl"))
|
||||
, d(new Private)
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
d->m_mapImpl = mapImpl;
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
}
|
||||
|
||||
ViewshedImpl::~ViewshedImpl()
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
this->remove();
|
||||
delete d;
|
||||
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
}
|
||||
|
||||
|
||||
void ViewshedImpl::setViewshedUrl(const QString &viewshedServiceUrl)
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START, viewshedServiceUrl='" << viewshedServiceUrl << "'";
|
||||
|
||||
d->m_url = viewshedServiceUrl;
|
||||
|
||||
if (d->m_url.isEmpty())
|
||||
{
|
||||
// only demo!!! 10.2.6!? http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Elevation/ESRI_Elevation_World/GPServer/Viewshed
|
||||
// only demo!!! V100.2 https://sampleserver6.arcgisonline.com/arcgis/rest/services/Elevation/ESRI_Elevation_World/GPServer/Viewshed
|
||||
d->m_url = QLatin1String("https://sampleserver6.arcgisonline.com/arcgis/rest/services/Elevation/ESRI_Elevation_World/GPServer/Viewshed"); // only demo!!!
|
||||
}
|
||||
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END, d->m_url'" << d->m_url << "'";
|
||||
}
|
||||
|
||||
bool ViewshedImpl::isReady()
|
||||
{
|
||||
init();
|
||||
bool isReady = (d->m_graphicsLayer) && d->m_mapImpl->isReady();
|
||||
|
||||
if (!isReady)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION
|
||||
<< " d->m_url.isEmpty() = " << d->m_url.isEmpty()
|
||||
<< " d->m_graphicsLayer = " << d->m_graphicsLayer
|
||||
<< " d->m_mapImpl->isReady() = " << d->m_mapImpl->isReady();
|
||||
}
|
||||
return isReady;
|
||||
}
|
||||
|
||||
bool ViewshedImpl::create()
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
|
||||
if (!isReady())
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " failed, not ready";
|
||||
return false;
|
||||
}
|
||||
|
||||
// remove all former
|
||||
this->remove();
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ViewshedImpl::create(double alpha, double innerRadius, double observerHeight, double targetHeight, double beamAngle)
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
|
||||
if (!isReady())
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " failed, not ready";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (alpha < 0.0) alpha = 0.0;
|
||||
if (alpha > 1.0) alpha = 1.0;
|
||||
|
||||
if (beamAngle < 0.5) beamAngle = 0.5;
|
||||
|
||||
// remove all former
|
||||
this->remove();
|
||||
|
||||
// remove any pending/active rubberbands of our map:
|
||||
RB::Rubberband::deleteAllActiveRubberbands(d->m_mapImpl);
|
||||
|
||||
d->m_viewshedParameter.innerRadius = innerRadius;
|
||||
d->m_viewshedParameter.observerHeight = observerHeight;
|
||||
d->m_viewshedParameter.targetHeight = targetHeight;
|
||||
d->m_viewshedParameter.dAngle = beamAngle*MathConst::pi/180.0; // grad to rad
|
||||
d->m_viewshedParameter.alpha = alpha;
|
||||
|
||||
const Mode mode = d->m_mapImpl->mode();
|
||||
switch (mode) {
|
||||
case Mode::Mode_2D:
|
||||
d->m_rubbandBase = createSightFanRubberband2D();
|
||||
break;
|
||||
case Mode::Mode_3D:
|
||||
d->m_rubbandBase = createSightFanRubberband3D();
|
||||
break;
|
||||
default:
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " mode (" << mode << ")" << " does not support viewshed";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
// d->m_rubbandBase; should be cleared now
|
||||
}
|
||||
|
||||
|
||||
long ViewshedImpl::create(const ViewshedParameter &viewshedParameter)
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
|
||||
<< " viewshedParameter: " << viewshedParameter;
|
||||
|
||||
if (!isReady())
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " failed, not ready";
|
||||
return -1;
|
||||
}
|
||||
|
||||
// store current values:
|
||||
d->m_viewshedParameter = viewshedParameter;
|
||||
|
||||
ViewshedBase *viewshed = nullptr;
|
||||
|
||||
// GPU-based viewshed (viewshedAnalysis) is today supported for 3D only:
|
||||
const Mode mode = d->m_mapImpl->mode();
|
||||
switch (mode) {
|
||||
case Mode::Mode_2D:
|
||||
viewshed = create_viewshedGP(d->m_viewshedParameter);
|
||||
break;
|
||||
case Mode::Mode_3D:
|
||||
viewshed = create_viewshedAnalysis(d->m_viewshedParameter);
|
||||
break;
|
||||
default:
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " mode (" << mode << ")" << " does not support viewshed";
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!viewshed)
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " creation of viewshed failed" << " mode (" << mode << ")";
|
||||
return -1;
|
||||
}
|
||||
|
||||
d->m_viewshedMap[++d->m_viewshedCounter] = viewshed;
|
||||
|
||||
emit viewshedFinished(d->m_viewshedCounter);
|
||||
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
|
||||
return d->m_viewshedCounter;
|
||||
|
||||
} // long ViewshedImpl::create(const ViewshedParameter &viewshedParameter)
|
||||
|
||||
|
||||
bool ViewshedImpl::modify(long viewshedId, double alpha, double innerRadius, double observerHeight, double targetHeight, double beamAngle)
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
|
||||
if (!isReady())
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " failed, not ready";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (alpha < 0.0) alpha = 0.0;
|
||||
if (alpha > 1.0) alpha = 1.0;
|
||||
if (beamAngle < 0.5) beamAngle = 0.5;
|
||||
|
||||
if (viewshedId < 0) viewshedId = d->m_viewshedCounter;
|
||||
|
||||
if (d->m_sightFanMap.contains(viewshedId))
|
||||
{
|
||||
SightFan *sightFan = d->m_sightFanMap[viewshedId];
|
||||
|
||||
d->m_viewshedParameter.innerRadius = innerRadius;
|
||||
d->m_viewshedParameter.observerHeight = observerHeight;
|
||||
d->m_viewshedParameter.targetHeight = targetHeight;
|
||||
d->m_viewshedParameter.dAngle = beamAngle * MathConst::pi / 180.0; // grad to rad
|
||||
d->m_viewshedParameter.noBeams = MathConst::pi_two / d->m_viewshedParameter.dAngle;
|
||||
d->m_viewshedParameter.alpha = alpha;
|
||||
|
||||
sightFan->setAlpha( d->m_viewshedParameter.alpha );
|
||||
sightFan->setInnerRadius( d->m_viewshedParameter.innerRadius );
|
||||
sightFan->setCenterHat( d->m_viewshedParameter.observerHeight );
|
||||
sightFan->setObjectHat( d->m_viewshedParameter.targetHeight );
|
||||
sightFan->setdeltaAngle( d->m_viewshedParameter.dAngle );
|
||||
sightFan->setNoOfFans( d->m_viewshedParameter.noBeams );
|
||||
|
||||
sightFan->show();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} // bool ViewshedImpl::modify(long viewshedId, double alpha, double innerRadius, double observerHeight, double targetHeight, double beamAngle)
|
||||
|
||||
|
||||
ViewshedBase *ViewshedImpl::create_viewshedGP(const ViewshedParameter &viewshedParameter)
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
|
||||
<< " viewshedParameter: " << viewshedParameter;
|
||||
|
||||
if (!d->m_graphicsLayer)
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " no graphicsLayer for viewshed";
|
||||
return nullptr;
|
||||
}
|
||||
if (d->m_url.isEmpty())
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " no url for viewshed";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ViewshedGeoProcessing *viewshed = new ViewshedGeoProcessing(d->m_url, d->m_graphicsLayer, d->m_mapImpl->getEsriSpatialReference());
|
||||
if (!viewshed->init(d->m_mapImpl))
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " init failed";
|
||||
delete viewshed;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// coordTranslation:
|
||||
CoordTranslationFunctor *coordTransFunctor = d->m_mapImpl->coordTranslationFunctor();
|
||||
const QPointF &viewshedPointTranslated = coordTransFunctor ? coordTransFunctor->geographicToMap(viewshedParameter.viewshedOrigin_latLon) : QPointF();
|
||||
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION
|
||||
<< " viewshedParameter= " << viewshedParameter;
|
||||
|
||||
if (!viewshed->execute(viewshedPointTranslated, // Map-Coord
|
||||
viewshedParameter.outerRadius,
|
||||
viewshedParameter.observerHeight))
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " executing GeoProcessing viewshed failed.";
|
||||
delete viewshed;
|
||||
return nullptr;
|
||||
}
|
||||
return viewshed;
|
||||
} // ViewshedBase *ViewshedImpl::create_viewshedGP(const ViewshedParameter &viewshedParameter)
|
||||
|
||||
|
||||
ViewshedBase *ViewshedImpl::create_viewshedAnalysis(const ViewshedParameter &viewshedParameter)
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
|
||||
<< " viewshedParameter: " << viewshedParameter;
|
||||
|
||||
if (!d->m_mapImpl->getEsriSceneGraphicsView())
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " getEsriSceneGraphicsView failed for viewsheds";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ViewshedAnalysis *viewshed = new ViewshedAnalysis(d->m_mapImpl->getEsriSceneGraphicsView());
|
||||
|
||||
// rad to degree
|
||||
const double factor = 180 / MathConst::pi;
|
||||
const QPointF ¢erDegree = viewshedParameter.viewshedOrigin_latLon * factor;
|
||||
|
||||
if (!viewshed->execute(centerDegree, // degree
|
||||
viewshedParameter.outerRadius,
|
||||
viewshedParameter.observerHeight))
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " executing analysis viewshed failed.";
|
||||
delete viewshed;
|
||||
return nullptr;
|
||||
}
|
||||
return viewshed;
|
||||
} // ViewshedBase *ViewshedImpl::create_viewshedAnalysis(const ViewshedParameter &viewshedParameter)
|
||||
|
||||
|
||||
void ViewshedImpl::remove(long viewshedId)
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
|
||||
<< " viewshedId=" << viewshedId;
|
||||
|
||||
//if (viewshedId < 0)
|
||||
{
|
||||
// ok, not special viewshed is adressed --> remove all
|
||||
for (ViewshedBase *viewshed : qAsConst(d->m_viewshedMap))
|
||||
delete viewshed;
|
||||
d->m_viewshedMap.clear();
|
||||
|
||||
for (SightFan *sightFan : qAsConst(d->m_sightFanMap))
|
||||
{
|
||||
if (sightFan)
|
||||
sightFan->removeMySelf();
|
||||
}
|
||||
d->m_sightFanMap.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
if (d->m_viewshedMap.contains(viewshedId))
|
||||
{
|
||||
delete d->m_viewshedMap[viewshedId];
|
||||
d->m_viewshedMap.remove(viewshedId);
|
||||
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
|
||||
<< " viewshedId=" << viewshedId;
|
||||
return;
|
||||
}
|
||||
|
||||
if (d->m_sightFanMap.contains(viewshedId))
|
||||
{
|
||||
d->m_sightFanMap[viewshedId]->removeMySelf();
|
||||
d->m_sightFanMap[viewshedId] = nullptr;
|
||||
d->m_sightFanMap.remove(viewshedId);
|
||||
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
|
||||
<< " viewshedId=" << viewshedId;
|
||||
return;
|
||||
}
|
||||
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " viewShedId not found, id=" << viewshedId;
|
||||
}
|
||||
|
||||
|
||||
ViewshedParameter ViewshedImpl::getViewshedParameter(long viewshedId, bool *ok) const
|
||||
{
|
||||
if (ok)
|
||||
*ok = false;
|
||||
|
||||
if (viewshedId < 0)
|
||||
viewshedId = d->m_viewshedCounter;
|
||||
|
||||
if (d->m_sightFanMap.contains(viewshedId))
|
||||
{
|
||||
const SightFan *sightFan = d->m_sightFanMap[viewshedId];
|
||||
|
||||
if (sightFan)
|
||||
{
|
||||
ViewshedParameter vp;
|
||||
|
||||
vp.viewshedOrigin_latLon = sightFan->center();
|
||||
vp.observerHeight = sightFan->centerHat();
|
||||
vp.targetHeight = sightFan->objectHat();
|
||||
vp.innerRadius = sightFan->innerRadius();
|
||||
vp.outerRadius = sightFan->radius();
|
||||
vp.startAngle = sightFan->startAngle();
|
||||
vp.dAngle = sightFan->dAngle();
|
||||
vp.alpha = sightFan->alpha();
|
||||
vp.noBeams = sightFan->noOfFans();
|
||||
|
||||
if (ok)
|
||||
*ok = true;
|
||||
return vp;
|
||||
}
|
||||
}
|
||||
return d->m_viewshedParameter;
|
||||
} // const ViewshedParameter & ViewshedImpl::getViewshedParameter(long viewshedId = -1, bool *ok = nullptr)
|
||||
|
||||
|
||||
void ViewshedImpl::init()
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
|
||||
if (!d->m_graphicsLayer)
|
||||
{
|
||||
LayerFactoryImpl &layerFactory = d->m_mapImpl->layerFactoryImpl();
|
||||
const QString &toolsLayername = layerFactory.toolLayer();
|
||||
d->m_graphicsLayer = layerFactory.getGraphicsLayer(toolsLayername);
|
||||
}
|
||||
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
}
|
||||
|
||||
RB::RubberbandEllipse *ViewshedImpl::createRubberband2D()
|
||||
{
|
||||
// remove any pending/active rubberbands of our map:
|
||||
RB::Rubberband::deleteAllActiveRubberbands(d->m_mapImpl);
|
||||
|
||||
RB::RubberbandEllipse *rubberband =
|
||||
d->m_mapImpl->rubberbandFactory().create<SituationMap::RB::RubberbandEllipse>(this);
|
||||
|
||||
if (!rubberband || !rubberband->rubberbandIsAlive())
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " create2D failed";
|
||||
return nullptr;
|
||||
}
|
||||
rubberband->setAutoDelete(true);
|
||||
|
||||
rubberband->constrainQuadratic(true);
|
||||
rubberband->constrainOrthogonal(true);
|
||||
// rubberband->minWidth(radiusMin * 2); // Should be 2*radiusMin
|
||||
// rubberband->maxWidth(radiusMax * 2); // Should be 2*radiusMax
|
||||
|
||||
|
||||
connect(rubberband, &SituationMap::RB::Rubberband::abort, this, &ViewshedImpl::onRbAbort, Qt::UniqueConnection);
|
||||
connect(rubberband, &SituationMap::RB::Rubberband::apply, this, &ViewshedImpl::onRb2DApply, Qt::UniqueConnection);
|
||||
|
||||
return rubberband;
|
||||
}
|
||||
|
||||
|
||||
RB::RubberbandEllipse *ViewshedImpl::createSightFanRubberband2D()
|
||||
{
|
||||
// remove any pending/active rubberbands of our map:
|
||||
RB::Rubberband::deleteAllActiveRubberbands(d->m_mapImpl);
|
||||
|
||||
RB::RubberbandEllipse *rubberband =
|
||||
d->m_mapImpl->rubberbandFactory().create<SituationMap::RB::RubberbandEllipse>(this);
|
||||
|
||||
if (!rubberband || !rubberband->rubberbandIsAlive())
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " create2D failed";
|
||||
return nullptr;
|
||||
}
|
||||
rubberband->setAutoDelete(true);
|
||||
|
||||
rubberband->constrainQuadratic(true);
|
||||
rubberband->constrainOrthogonal(true);
|
||||
rubberband->enableSector(false); // set enableSector to true to allow sector sight fans instead of full circles
|
||||
|
||||
rubberband->minWidth(d->m_viewshedParameter.innerRadius * 3); // radius should be larger than innerRadius
|
||||
|
||||
// rubberband->maxWidth(radiusMax * 2); // Should be 2*radiusMax
|
||||
|
||||
|
||||
connect(rubberband, &SituationMap::RB::Rubberband::abort, this, &ViewshedImpl::onRbAbort, Qt::UniqueConnection);
|
||||
connect(rubberband, &SituationMap::RB::Rubberband::apply, this, &ViewshedImpl::onSightFanRb2DApply, Qt::UniqueConnection);
|
||||
|
||||
return rubberband;
|
||||
} // RB::RubberbandEllipse *ViewshedImpl::createSightFanRubberband2D()
|
||||
|
||||
|
||||
RB::RubberbandMultiPointFeature3D *ViewshedImpl::createSightFanRubberband3D()
|
||||
{
|
||||
// remove any pending/active rubberbands of our map:
|
||||
RB::Rubberband::deleteAllActiveRubberbands(d->m_mapImpl);
|
||||
|
||||
RB::RubberbandMultiPointFeature3D *rubberband =
|
||||
d->m_mapImpl->rubberbandFactory().create3D<RB::RubberbandMultiPointFeature3D>(this);
|
||||
|
||||
if (!rubberband || !rubberband->rubberbandIsAlive())
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " create3D failed";
|
||||
return nullptr;
|
||||
}
|
||||
rubberband->setAutoDelete(true);
|
||||
rubberband->enableCircular(true);
|
||||
|
||||
// rubberband->constrainQuadratic(true);
|
||||
// rubberband->constrainOrthogonal(true);
|
||||
|
||||
connect(rubberband, &SituationMap::RB::Rubberband::abort, this, &ViewshedImpl::onRbAbort, Qt::UniqueConnection);
|
||||
connect(rubberband, &SituationMap::RB::Rubberband::apply, this, &ViewshedImpl::onSightFanRb3DApply, Qt::UniqueConnection);
|
||||
|
||||
return rubberband;
|
||||
} // RB::RubberbandMultiPointFeature3D *ViewshedImpl::createSightFanRubberband3D()
|
||||
|
||||
|
||||
RB::RubberbandMultiPointFeature3D *ViewshedImpl::createRubberband3D()
|
||||
{
|
||||
// remove any pending/active rubberbands of our map:
|
||||
RB::Rubberband::deleteAllActiveRubberbands(d->m_mapImpl);
|
||||
|
||||
RB::RubberbandMultiPointFeature3D *rubberband =
|
||||
d->m_mapImpl->rubberbandFactory().create3D<RB::RubberbandMultiPointFeature3D>(this);
|
||||
|
||||
if (!rubberband || !rubberband->rubberbandIsAlive())
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " create3D failed";
|
||||
return nullptr;
|
||||
}
|
||||
rubberband->setAutoDelete(true);
|
||||
rubberband->enableCircular(true);
|
||||
|
||||
// rubberband->constrainQuadratic(true);
|
||||
// rubberband->constrainOrthogonal(true);
|
||||
|
||||
connect(rubberband, &SituationMap::RB::Rubberband::abort, this, &ViewshedImpl::onRbAbort, Qt::UniqueConnection);
|
||||
connect(rubberband, &SituationMap::RB::Rubberband::apply, this, &ViewshedImpl::onSightFanRb3DApply, Qt::UniqueConnection);
|
||||
|
||||
return rubberband;
|
||||
}
|
||||
|
||||
|
||||
void ViewshedImpl::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 ViewshedImpl::onSightFanRb2DApply(RB::RubberbandBase *rbnd)
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
if (!rbnd)
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " no rubberband";
|
||||
return;
|
||||
}
|
||||
|
||||
RB::RubberbandEllipse *ellipse = static_cast<RB::RubberbandEllipse *>(rbnd);
|
||||
const QString &toolLayerName = d->m_mapImpl->layerFactoryImpl().toolLayer();
|
||||
|
||||
double diameter;
|
||||
double dummy;
|
||||
QPointF direction;
|
||||
|
||||
ellipse->rectangleParameter( d->m_viewshedParameter.viewshedOrigin_latLon, diameter, dummy, direction );
|
||||
|
||||
if (diameter > 0.0)
|
||||
{
|
||||
d->m_viewshedParameter.outerRadius = diameter * 0.5;
|
||||
if (ellipse->hasSector())
|
||||
{
|
||||
double startAngle = SituationMap::MathUtils::getMathAngle(ellipse->sectorStart());
|
||||
double endAngle = SituationMap::MathUtils::getMathAngle(ellipse->sectorEnd());
|
||||
|
||||
if (startAngle > endAngle)
|
||||
{
|
||||
startAngle -= MathConst::pi_two;
|
||||
}
|
||||
|
||||
d->m_viewshedParameter.noBeams = ceil( (endAngle - startAngle) / d->m_viewshedParameter.dAngle );
|
||||
d->m_viewshedParameter.startAngle = startAngle;
|
||||
}
|
||||
else
|
||||
{
|
||||
d->m_viewshedParameter.startAngle = 0.0;
|
||||
d->m_viewshedParameter.noBeams = MathConst::pi_two / d->m_viewshedParameter.dAngle;
|
||||
}
|
||||
|
||||
|
||||
ObjectFactory &objFac = d->m_mapImpl->objectFactory();
|
||||
SightFan *sightFan = objFac.create<SituationMap::SightFan>(toolLayerName).take();
|
||||
if (sightFan)
|
||||
{
|
||||
sightFan->initFan( d->m_viewshedParameter.viewshedOrigin_latLon
|
||||
, d->m_viewshedParameter.observerHeight
|
||||
, d->m_viewshedParameter.targetHeight
|
||||
, d->m_viewshedParameter.outerRadius
|
||||
, d->m_viewshedParameter.innerRadius
|
||||
, d->m_viewshedParameter.startAngle
|
||||
, d->m_viewshedParameter.dAngle
|
||||
, d->m_viewshedParameter.noBeams
|
||||
, d->m_viewshedParameter.alpha );
|
||||
|
||||
long sightFanId = ++d->m_viewshedCounter;
|
||||
d->m_sightFanMap[sightFanId] = sightFan;
|
||||
|
||||
emit viewshedFinished(sightFanId);
|
||||
|
||||
// create a RubberbandPointFeature to let the user move around the sight fan
|
||||
|
||||
RB::RubberbandPointFeature *moveRB = d->m_mapImpl->rubberbandFactory().create<RB::RubberbandPointFeature>(this);
|
||||
if (moveRB)
|
||||
{
|
||||
moveRB->setAutoDelete(true);
|
||||
moveRB->enableModificationState();
|
||||
moveRB->setCoordinateVector(QVector<QPointF>() << sightFan->center());
|
||||
|
||||
std::function<bool(SituationMap::RB::RubberbandBase*)> moveSightFan = [this, sightFanId](SituationMap::RB::RubberbandBase* rbBase) -> bool
|
||||
{
|
||||
SituationMap::RB::RubberbandPointFeature *rubberPFeat = dynamic_cast<SituationMap::RB::RubberbandPointFeature*>(rbBase);
|
||||
|
||||
SightFan * sightFan = d->m_sightFanMap[sightFanId];
|
||||
if (nullptr == sightFan)
|
||||
{
|
||||
if (rubberPFeat) rubberPFeat->deleteMySelf();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rubberPFeat)
|
||||
{
|
||||
const QPointF & loc = rubberPFeat->singleCoordinate();
|
||||
sightFan->move(loc);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
moveRB->installExternalUpdate(moveSightFan);
|
||||
}
|
||||
} // if sightFan
|
||||
} // if diameter
|
||||
} // void ViewshedImpl::onSightFanRb2DApply(RB::RubberbandBase *rbnd)
|
||||
|
||||
|
||||
void ViewshedImpl::onSightFanRb3DApply(RB::RubberbandBase *rbnd)
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
if (!rbnd)
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " no rubberband";
|
||||
return;
|
||||
}
|
||||
|
||||
RB::RubberbandMultiPointFeature3D *rubberband = static_cast<RB::RubberbandMultiPointFeature3D *>(rbnd);
|
||||
const QString &toolLayerName = d->m_mapImpl->layerFactoryImpl().toolLayer();
|
||||
const QVector<QPointF> &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 = MathConst::pi / 180.0;
|
||||
const QPointF ¢er = data.at(0) * factor;
|
||||
// viewshedParameter.viewshedOrigin_latLon = center;
|
||||
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
unsigned int noBeams = floor((MathConst::pi_two) / d->m_viewshedParameter.dAngle);
|
||||
|
||||
|
||||
ObjectFactory &objFac = d->m_mapImpl->objectFactory();
|
||||
RefPointer<SightFan> objRef = objFac.create<SituationMap::SightFan>(toolLayerName);
|
||||
SightFan *sightFan = objRef.get();
|
||||
|
||||
if (sightFan)
|
||||
{
|
||||
if (d->m_viewshedParameter.innerRadius*1.5 > viewshedParameter.outerRadius)
|
||||
{
|
||||
viewshedParameter.outerRadius = d->m_viewshedParameter.innerRadius*1.5;
|
||||
}
|
||||
|
||||
sightFan->initFan(center
|
||||
, d->m_viewshedParameter.observerHeight
|
||||
, d->m_viewshedParameter.targetHeight
|
||||
, viewshedParameter.outerRadius
|
||||
, d->m_viewshedParameter.innerRadius
|
||||
, 0.0
|
||||
, d->m_viewshedParameter.dAngle
|
||||
, noBeams
|
||||
, d->m_viewshedParameter.alpha );
|
||||
|
||||
long sightFanId = ++d->m_viewshedCounter;
|
||||
d->m_sightFanMap[sightFanId] = sightFan;
|
||||
|
||||
emit viewshedFinished(sightFanId);
|
||||
|
||||
// create a RubberbandPointFeature3D to let the user move around the sight fan
|
||||
|
||||
RB::RubberbandPointFeature3D *moveRB = d->m_mapImpl->rubberbandFactory().create3D<RB::RubberbandPointFeature3D>(this);
|
||||
if (moveRB)
|
||||
{
|
||||
moveRB->setAutoDelete(true);
|
||||
moveRB->enableModificationState();
|
||||
moveRB->setCoordinateVector(QVector<QPointF>() << sightFan->center());
|
||||
|
||||
std::function<bool(SituationMap::RB::RubberbandBase*)> moveSightFan3D = [this, sightFanId](SituationMap::RB::RubberbandBase* rbBase) -> bool
|
||||
{
|
||||
SituationMap::RB::RubberbandPointFeature3D *rubberPFeat = dynamic_cast<SituationMap::RB::RubberbandPointFeature3D*>(rbBase);
|
||||
|
||||
SightFan * sightFan = d->m_sightFanMap[sightFanId];
|
||||
if (nullptr == sightFan)
|
||||
{
|
||||
if (rubberPFeat) rubberPFeat->deleteMySelf();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rubberPFeat)
|
||||
{
|
||||
const QPointF & loc = rubberPFeat->singleCoordinate();
|
||||
sightFan->move(loc);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
moveRB->installExternalUpdate(moveSightFan3D);
|
||||
}
|
||||
}
|
||||
|
||||
} // void ViewshedImpl::onSightFanRb3DApply(RB::RubberbandBase *rbnd)
|
||||
|
||||
|
||||
void ViewshedImpl::onRb2DApply(RB::RubberbandBase *rbnd)
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
if (!rbnd)
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " no rubberband";
|
||||
return;
|
||||
}
|
||||
|
||||
RB::RubberbandEllipse *ellipse = static_cast<RB::RubberbandEllipse *>(rbnd);
|
||||
|
||||
const QVector<QPointF> &data = ellipse->rectangleVerticies();
|
||||
const LtsCoordTrans::UtmCoordinate p0(LtsCoordTrans::UtmCoordinate::fromGeographic(data.at(0)));
|
||||
const LtsCoordTrans::UtmCoordinate p1(LtsCoordTrans::UtmCoordinate::fromGeographic(data.at(2), p0.zone));
|
||||
|
||||
const QPointF ¢er = ellipse->centerPoint();
|
||||
double radius = fabs((p0.x - p1.x) / 2);
|
||||
|
||||
// 23.03.2018, N. Thoden
|
||||
// LegatusBremen201803151510.gpk contains dem with cell size of ~ 50m
|
||||
// So the inner_radius has to be >= 50m
|
||||
// And of course: outer_radius > inner_radius
|
||||
// So outerRadius > 60
|
||||
|
||||
if (radius < 100.0)
|
||||
radius = 100.0;
|
||||
|
||||
ViewshedParameter viewshedParameter;
|
||||
viewshedParameter.viewshedOrigin_latLon = center;
|
||||
viewshedParameter.outerRadius = radius;
|
||||
|
||||
long id = this->create(viewshedParameter);
|
||||
|
||||
if (id < 0)
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " rubberband failed!?";
|
||||
}
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
}
|
||||
|
||||
void ViewshedImpl::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<RB::RubberbandMultiPointFeature3D *>(rbnd);
|
||||
|
||||
const QVector<QPointF> &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 = MathConst::pi / 180.0;
|
||||
const QPointF ¢er = data.at(0) * factor;
|
||||
viewshedParameter.viewshedOrigin_latLon = center;
|
||||
|
||||
{
|
||||
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
|
||||
Reference in new issue
Block a user