372 lines
12 KiB
C++
Executable File
372 lines
12 KiB
C++
Executable File
/**
|
|
* @RDE_HEADER@
|
|
* Interface-Implementation of GeoImage
|
|
* $Id$
|
|
* $HeadURL$
|
|
* $Author$
|
|
*/
|
|
|
|
// Own
|
|
#include "geo_image_impl.h"
|
|
#include <MapImpl/map_impl.h>
|
|
#include <GraphicalObjects/graphical_object_picture_marker.h>
|
|
#include <GraphicalObjects/graphical_object_path.h>
|
|
|
|
|
|
// ESRI
|
|
|
|
|
|
// Qt
|
|
#include <QWidget>
|
|
#include <QVBoxLayout>
|
|
#include <QLabel>
|
|
#include <QPushButton>
|
|
#include <GraphicalObjects/graphical_object_picture_marker.h>
|
|
|
|
|
|
namespace SituationMap
|
|
{
|
|
|
|
|
|
class GeoImageImpl::Private
|
|
{
|
|
public:
|
|
Private() = default;
|
|
~Private() = default;
|
|
|
|
// ESRI data:
|
|
|
|
// Own data:
|
|
SimpleValue<GeoImageData> m_geoImageData;
|
|
QSharedPointer<GraphicalObjectPictureMarker> m_gopmPin;
|
|
|
|
|
|
}; // class GeoImageImpl::Private
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// class GeoImageImpl
|
|
//-----------------------------------------------------------------------------
|
|
GeoImageImpl::GeoImageImpl(const QString &debugInfo)
|
|
: GeoImage() // Interface
|
|
, BaseClass(debugInfo) // Implementation
|
|
, d(new Private)
|
|
, m_logger(getLogger("GeoImageImpl"))
|
|
{
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
|
}
|
|
|
|
GeoImageImpl::~GeoImageImpl()
|
|
{
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
|
delete d;
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
|
}
|
|
|
|
|
|
QString GeoImageImpl::toString() const
|
|
{
|
|
QString str;
|
|
str.append(BaseClass::toString());
|
|
str.append(d->m_geoImageData.value().toString());
|
|
return str;
|
|
}
|
|
|
|
GeoImage::GeoImageData GeoImageImpl::geoImageData() const { return d->m_geoImageData.value(); }
|
|
void GeoImageImpl::setGeoImageData(const GeoImageData &geoImageData) { d->m_geoImageData = geoImageData; }
|
|
|
|
MarkerSymbolType GeoImageImpl::proxyMarker() const { return d->m_geoImageData.value().proxyMarker; }
|
|
|
|
void GeoImageImpl::setProxyMarker(const MarkerSymbolType &proxyMarker)
|
|
{
|
|
if (d->m_geoImageData.value().proxyMarker != proxyMarker)
|
|
d->m_geoImageData.refValue().proxyMarker = proxyMarker;
|
|
}
|
|
|
|
int GeoImageImpl::proxyMarkerSize() const { return d->m_geoImageData.value().proxyMarkerSize; }
|
|
void GeoImageImpl::setProxyMarkerSize(int proxyMarkerSize)
|
|
{
|
|
if (d->m_geoImageData.value().proxyMarkerSize != proxyMarkerSize)
|
|
d->m_geoImageData.refValue().proxyMarkerSize = proxyMarkerSize;
|
|
}
|
|
|
|
QColor GeoImageImpl::proxyMarkerColor() const { return d->m_geoImageData.value().proxyMarkerColor; }
|
|
void GeoImageImpl::setProxyMarkerColor(const QColor &proxyMarkerColor)
|
|
{
|
|
if (d->m_geoImageData.value().proxyMarkerColor != proxyMarkerColor)
|
|
d->m_geoImageData.refValue().proxyMarkerColor = proxyMarkerColor;
|
|
}
|
|
|
|
|
|
QImage GeoImageImpl::proxyImage() const { return d->m_geoImageData.value().proxyImage; }
|
|
void GeoImageImpl::setProxyImage(const QImage &proxyImage, const QSize &proxyImageDefaultSize)
|
|
{
|
|
if (d->m_geoImageData.value().proxyImage != proxyImage)
|
|
d->m_geoImageData.refValue().proxyImage = proxyImage;
|
|
|
|
if (d->m_geoImageData.value().proxyImageDefaultSize != proxyImageDefaultSize)
|
|
d->m_geoImageData.refValue().proxyImageDefaultSize = proxyImageDefaultSize;
|
|
}
|
|
QSize GeoImageImpl::proxyImageDefaultSize() const { return d->m_geoImageData.value().proxyImageDefaultSize; }
|
|
|
|
|
|
QImage GeoImageImpl::mainImage() const { return d->m_geoImageData.value().mainImage; }
|
|
|
|
void GeoImageImpl::setMainImage(const QImage &mainImage)
|
|
{
|
|
if (d->m_geoImageData.value().mainImage != mainImage)
|
|
d->m_geoImageData.refValue().mainImage = mainImage;
|
|
}
|
|
|
|
QImage GeoImageImpl::previewImageTypical() const
|
|
{
|
|
if (!d->m_geoImageData.value().proxyImage.isNull())
|
|
return d->m_geoImageData.value().proxyImage;
|
|
if (!d->m_geoImageData.value().mainImage.isNull())
|
|
return d->m_geoImageData.value().mainImage;
|
|
return QImage();
|
|
}
|
|
|
|
QString GeoImageImpl::description() const { return d->m_geoImageData.value().description; }
|
|
|
|
void GeoImageImpl::setDescription(const QString &description)
|
|
{
|
|
if (d->m_geoImageData.value().description != description)
|
|
d->m_geoImageData.refValue().description = description;
|
|
}
|
|
|
|
void GeoImageImpl::setPinEnabled(bool enablePin)
|
|
{
|
|
if (d->m_geoImageData.value().pinEnabled != enablePin)
|
|
d->m_geoImageData.refValue().pinEnabled = enablePin;
|
|
}
|
|
bool GeoImageImpl::isPinEnabled() const { return d->m_geoImageData.value().pinEnabled; }
|
|
|
|
|
|
QWidget *GeoImageImpl::createWidget(QWidget *parent) const
|
|
{
|
|
const GeoImageData &geoImageData = d->m_geoImageData.value();
|
|
|
|
if (geoImageData.mainImage.isNull())
|
|
return nullptr;
|
|
|
|
QWidget *widget = new QWidget(parent);
|
|
widget->setLayout(new QVBoxLayout());
|
|
|
|
QLabel *img = new QLabel();
|
|
img->setPixmap(QPixmap::fromImage(geoImageData.mainImage));
|
|
widget->layout()->addWidget(img);
|
|
|
|
widget->layout()->addWidget(new QLabel(geoImageData.description));
|
|
|
|
|
|
// CloseButton
|
|
QPushButton *pbClose = new QPushButton(QLatin1String("Close"));
|
|
widget->layout()->addWidget(pbClose);
|
|
|
|
pbClose->connect(pbClose, &QPushButton::clicked, widget, [widget]()
|
|
{
|
|
widget->deleteLater();
|
|
});
|
|
|
|
return widget;
|
|
}
|
|
|
|
|
|
bool GeoImageImpl::updateViewImpl()
|
|
{
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
|
|
<< " origin =" << this->origin() //.x() << ", " << this->origin().y()
|
|
<< " visibility=" << m_visibility
|
|
<< " visiTechn=" << m_visibilityTechnical
|
|
<< " visiTact=" << m_visibilityTactical;
|
|
|
|
if (!m_graphicsLayer)
|
|
{
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << " no graphicsLayer";
|
|
return false;
|
|
}
|
|
|
|
if (!m_mainGraphicalObject)
|
|
{
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << " no m_mainGraphicalObject";
|
|
return false;
|
|
}
|
|
|
|
// Marker:
|
|
GraphicalObjectPictureMarker *pMarker = static_cast<GraphicalObjectPictureMarker *>(m_mainGraphicalObject);
|
|
|
|
if (d->m_geoImageData.changed())
|
|
{
|
|
const GeoImageData &geoImageData = d->m_geoImageData.value();
|
|
|
|
if (geoImageData.proxyImage.isNull())
|
|
{
|
|
if (geoImageData.proxyMarker == MarkerSymbolType::Undefined)
|
|
pMarker->setMarkerSymbol(MarkerSymbolType::Diamond, 20, Qt::red);
|
|
else
|
|
pMarker->setMarkerSymbol(geoImageData.proxyMarker,
|
|
geoImageData.proxyMarkerSize,
|
|
geoImageData.proxyMarkerColor);
|
|
}
|
|
else
|
|
pMarker->setImage(geoImageData.proxyImage, geoImageData.proxyImageDefaultSize);
|
|
|
|
// Pin
|
|
if (m_mapImpl->mode() == Mode::Mode_3D)
|
|
{
|
|
if (geoImageData.pinEnabled)
|
|
createPin();
|
|
else
|
|
resetPin();
|
|
}
|
|
}
|
|
|
|
updateIdentifierPosition();
|
|
|
|
pMarker->setOrigin(this->originTranslated());
|
|
|
|
|
|
bool success = BaseClass::updateViewImpl();
|
|
|
|
// reset changed:
|
|
d->m_geoImageData.reset();
|
|
|
|
onMapExtentChanged();
|
|
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
|
|
return success;
|
|
}
|
|
|
|
|
|
|
|
bool GeoImageImpl::init(MapImpl *mapImpl, const QString &logicalLayerName)
|
|
{
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
|
|
|
bool success = BaseClass::init(mapImpl, logicalLayerName);
|
|
|
|
if (success)
|
|
{
|
|
// create underlying object (to save most attributes only there)
|
|
if (!m_mainGraphicalObject)
|
|
m_mainGraphicalObject = new GraphicalObjectPictureMarker(m_mapImpl->getEsriGeoView(),
|
|
m_graphicsLayer,
|
|
m_debugInfo + QLatin1String("#Image"),
|
|
m_uniqueMapId);
|
|
}
|
|
else
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << " init failed";
|
|
|
|
TRACE_LOG(m_logger) << LOGFUNCTION << " END, success=" << success;
|
|
return success;
|
|
}
|
|
|
|
bool GeoImageImpl::onMapExtentChanged()
|
|
{
|
|
TRACE_LOG(m_logger) << " onMapExtentChanged";
|
|
|
|
if (m_graphicalObjectPin && m_mainGraphicalObject) // m_graphicalObjectPin exists only at Mode_3D
|
|
{
|
|
if (!d->m_gopmPin)
|
|
{
|
|
d->m_gopmPin = QSharedPointer<GraphicalObjectPictureMarker>
|
|
(new GraphicalObjectPictureMarker(m_mapImpl->getEsriGeoView()
|
|
, m_graphicsLayer
|
|
, m_debugInfo + QStringLiteral("#PictureMarkerPin")
|
|
, m_uniqueMapId)
|
|
);
|
|
|
|
GraphicalObjectPictureMarker *pMarker = static_cast<GraphicalObjectPictureMarker *>(m_mainGraphicalObject);
|
|
if (pMarker)
|
|
{
|
|
const GeoImageData &geoImageData = d->m_geoImageData.value();
|
|
d->m_gopmPin->setImage(pMarker->image(), geoImageData.proxyImageDefaultSize);
|
|
}
|
|
}
|
|
|
|
d->m_gopmPin->setScale(m_mainGraphicalObject->scale());
|
|
|
|
Point3D originTranslated = this->originTranslated();
|
|
DEBUG_LOG(m_logger) << " XXX originTranslatedORG = " << originTranslated;
|
|
|
|
// GUEZE-2620 3D Sicht SOS Symbole
|
|
// Bisher wurde die Höhe des SOS-Images und -Textes quasi getuned, wobei ja nun
|
|
// unter bestimmten Umständen leider zu einem Höhenwert ausserhalb des
|
|
// Sichtfensters kam.
|
|
// Daher:
|
|
// - Pflicht: SOS-Symbol und Text auf den Boden
|
|
// - Kuer: Zudem versucht die SW, eine zweite Instanz des Images
|
|
// (inkl. Verbindungslinie) zu positionieren.
|
|
// Und zwar grob mittig zw. Erdoberfläche und oberen Kante des Sichtbereichs.
|
|
// Leider funktioniert des dafür genutzte ESRI-Befehl nicht immer zuverlässig.
|
|
// Meist dann, wenn sich der Augenpunkt (ViewPoint) dicht am Objekt befinden...
|
|
// Noch ein bisschen Tuning, aber es verbleiben leider Fehlersituationen.
|
|
|
|
if (m_mapImpl->scale() > 1500)
|
|
{
|
|
const double zVal = m_mapImpl->scale() * m_mapImpl->scale() * 0.0001;
|
|
DEBUG_LOG(m_logger) << " zVal = " << zVal;
|
|
|
|
originTranslated.rz() = zVal;
|
|
|
|
// 1 ... 10000 (qBound ~ std::clamp)
|
|
originTranslated.rz() = qBound(1.0, originTranslated.rz(), 10000.0);
|
|
|
|
// check viewPort:
|
|
// Note: unfortunately its dows not work perfect :-(
|
|
int cnt = 0;
|
|
static int s_counterMax = 10;
|
|
while (m_mapImpl->mapCoordinateToViewPortWindowPoint3D(originTranslated).isNull() && (originTranslated.rz() > 1) && (cnt <= s_counterMax))
|
|
{
|
|
originTranslated.rz() /= 2.0;
|
|
++cnt;
|
|
}
|
|
|
|
if (cnt == s_counterMax)
|
|
originTranslated.rz() = 0;
|
|
else
|
|
originTranslated.rz() *= 0.5; // try to show in the middle between baseSurface and upper edge of window
|
|
|
|
d->m_gopmPin->setVisibility(true);
|
|
|
|
} else {
|
|
// GUEZE-3460 - SOS Meldungen werden nicht korrekt angezeigt
|
|
if (m_mapImpl->scale() < 500)
|
|
originTranslated.rz() = 1.0; // meter
|
|
else if (m_mapImpl->scale() < 1000)
|
|
originTranslated.rz() = 2.5; // meter
|
|
else
|
|
originTranslated.rz() = 10.0; // meter
|
|
|
|
d->m_gopmPin->setVisibility(true);
|
|
}
|
|
|
|
DEBUG_LOG(m_logger) << " originTranslated = " << originTranslated;
|
|
|
|
d->m_gopmPin->setOrigin(originTranslated);
|
|
if (!d->m_gopmPin->updateView())
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << " updateView failed" << m_mainGraphicalObject->debugInfo();
|
|
|
|
// update m_identifierPositionCandidateTranslated ,
|
|
// it will be transfered to m_mainGraphicalObject via BaseClass::onMapExtentChanged()
|
|
// m_identifierPositionCandidateTranslated = originTranslated;
|
|
|
|
Point3D centerEarth = originTranslated;
|
|
centerEarth.rz() = -100; // hopefully lower than lowest level of training area
|
|
m_graphicalObjectPin->setPositions({originTranslated, centerEarth});
|
|
|
|
m_graphicalObjectPin->setVisibility(d->m_gopmPin->visibility());
|
|
|
|
if (!m_graphicalObjectPin->updateView())
|
|
ERROR_LOG(m_logger) << LOGFUNCTION << " updateView failed" << m_graphicalObjectPin->debugInfo();
|
|
|
|
} // if (m_graphicalObjectPin && m_mainGraphicalObject)
|
|
|
|
return BaseClass::onMapExtentChanged();
|
|
}
|
|
|
|
|
|
} // namespace SituationMap
|