Files
qt5-legatus-legacy/Lts/Viewer/SituationMap/MapObjectsImpl/geo_image_impl.cpp
T
2026-08-13 18:33:10 +02:00

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