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

360 lines
8.3 KiB
C++
Executable File

/**
* @RDE_HEADER@
* CoordinateTranslation
* $Id$
* $HeadURL$
* $Author$
*/
// Own
#include "coordinate_translation.h"
#include <Map/coord_translation_functor.h>
#include <MapImpl/map_impl.h>
#include <MapImpl/abstract_map_object_impl.h>
#include <MathUtils/simple_helper.h>
// ESRI
#include <arcgis/Point.h>
#include <arcgis/GeometryEngine.h>
// Qt
#include <QMutexLocker>
#include <iostream>
//----------------------------------------------------------------------------
namespace SituationMap
{
void TranslatedBase::setCoordTransFunctor(CoordTranslationFunctor *functor)
{
m_coordTransFunctor = functor;
}
void TranslatedBase::setMapObjectImpl(AbstractMapObjectImpl *mapObjectImpl)
{
m_mapObjectImpl = mapObjectImpl;
}
OriginTranslated::OriginTranslated()
#ifdef WITH_LOGGING
: m_logger(getLogger("OriginTranslated"))
#endif
{}
Point3D OriginTranslated::origin() const
{
return m_origin;
}
bool OriginTranslated::setOrigin(const Point3D &origin)
{
bool changed = m_origin != origin;
if (changed)
{
m_origin = origin;
m_translated = false;
}
return changed;
}
const Point3D &OriginTranslated::originTranslated() const
{
#ifdef WITH_LOGGING
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " m_origin=" << m_origin
;
#endif
if (!m_translated)
{
// m_coordTransFunctor has priority, otherwise use functor of mapImpl:
if (!m_coordTransFunctor)
{
if (m_mapObjectImpl && m_mapObjectImpl->mapImpl())
{
// if useful, a MapObjectType specific functor can be prefered here:
// like: if (m_mapObjectImpl->coordTranslationFunctor()) ctFunctor=m_mapObjectImpl->coordTranslationFunctor();
m_coordTransFunctor = m_mapObjectImpl->mapImpl()->coordTranslationFunctor();
}
}
if (m_coordTransFunctor)
m_originTranslated = m_coordTransFunctor->geographicToMap(m_origin);
else
m_originTranslated = Point3D();
m_translated = true;
}
#ifdef WITH_LOGGING
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " m_originTranslated=" << m_originTranslated
;
#endif
return m_originTranslated;
}
PositionsTranslated::PositionsTranslated()
: m_mutex(QMutex::Recursive)
#ifdef WITH_LOGGING
, m_logger(getLogger("PositionsTranslated"))
#endif
{}
PositionCont PositionsTranslated::positions() const
{
QMutexLocker lock(&m_mutex);
return m_positions + m_singlePositions;
}
bool PositionsTranslated::setPositions(const PositionCont &posCont)
{
QMutexLocker lock(&m_mutex);
bool changed = m_positions != posCont;
if (changed)
{
m_positions = posCont;
m_translated = false;
}
m_singlePositions.clear();
return changed;
}
void PositionsTranslated::addSinglePosition(const Point3D &singlePositions)
{
QMutexLocker lock(&m_mutex);
m_singlePositions.append(singlePositions);
}
bool PositionsTranslated::setPositionsTranslated(const PositionCont &posCont)
{
QMutexLocker lock(&m_mutex);
if ((m_translated) && (m_positionsTranslated == posCont))
return true;
m_positionsTranslated = posCont;
m_positions.clear();
if (!m_coordTransFunctor)
{
if (m_mapObjectImpl && m_mapObjectImpl->mapImpl())
{
// if useful, a MapObjectType specific functor can be prefered here:
// like: if (m_mapObjectImpl->coordTranslationFunctor()) ctFunctor=m_mapObjectImpl->coordTranslationFunctor();
m_coordTransFunctor = m_mapObjectImpl->mapImpl()->coordTranslationFunctor();
}
}
if (m_coordTransFunctor)
{
m_positions.reserve(m_positionsTranslated.size());
for (int i = 0; i < m_positionsTranslated.count(); ++i)
m_positions.push_back(m_coordTransFunctor->mapToGeographic(m_positionsTranslated.at(i))); // for
}
m_singlePositions.clear();
m_translated = true;
return false;
} // PositionsTranslated::setPositionsTranslated( const PositionCont & posCont )
int PositionsTranslated::size() const
{
QMutexLocker lock(&m_mutex);
return m_positions.size() + m_singlePositions.size();
}
bool PositionsTranslated::isEmpty() const
{
QMutexLocker lock(&m_mutex);
return m_positions.isEmpty() && m_singlePositions.isEmpty();
}
void PositionsTranslated::clear()
{
QMutexLocker lock(&m_mutex);
m_positions.clear();
m_positionsTranslated.clear();
m_singlePositions.clear();
m_translated = false;
}
Point3D PositionsTranslated::first()
{
if (isEmpty())
return Point3D();
if (! m_positions.isEmpty())
return m_positions.first();
return m_singlePositions.first();
}
Point3D PositionsTranslated::last()
{
if (isEmpty())
return Point3D();
if (! m_singlePositions.isEmpty())
return m_singlePositions.last();
return m_positions.last();
}
const PositionCont &PositionsTranslated::positionsTranslated() const
{
#ifdef WITH_LOGGING
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
<< " m_positions=" << m_positions;
#endif
QMutexLocker lock(&m_mutex);
// !!! Important: consolidate !!!
consolidate();
if (!m_translated)
{
// translate:
m_positionsTranslated = geographicToMap(m_positions);
m_translated = true;
}
#ifdef WITH_LOGGING
TRACE_LOG(m_logger) << LOGFUNCTION << " END"
<< " m_positionsTranslated=" << m_positionsTranslated;
#endif
return m_positionsTranslated;
}
PositionCont PositionsTranslated::geographicToMap(const PositionCont &positions) const
{
PositionCont ret;
// m_coordTransFunctor has priority, otherwise use functor of mapImpl:
if (!m_coordTransFunctor)
{
if (m_mapObjectImpl && m_mapObjectImpl->mapImpl())
{
// if useful, a MapObjectType specific functor can be prefered here:
// like: if (m_mapObjectImpl->coordTranslationFunctor()) ctFunctor=m_mapObjectImpl->coordTranslationFunctor();
m_coordTransFunctor = m_mapObjectImpl->mapImpl()->coordTranslationFunctor();
}
}
if (!m_coordTransFunctor)
return ret;
ret.reserve(positions.size());
for (int i = 0; i < positions.count(); ++i)
{
const Point3D &p = positions.at(i);
ret.push_back(m_coordTransFunctor->geographicToMap(p));
} // for
return ret;
}
const Point3D &PositionsTranslated::startPointTranslated() const
{
QMutexLocker lock(&m_mutex);
// make sure that positions are translated:
positionsTranslated();
return m_positionsTranslated.first();
}
const Point3D &PositionsTranslated::endPointTranslated() const
{
QMutexLocker lock(&m_mutex);
// make sure that positions are translated:
positionsTranslated();
return m_positionsTranslated.back();
}
double PositionsTranslated::angleOfStartSegment() const
{
QMutexLocker lock(&m_mutex);
positionsTranslated();
const int size = m_positionsTranslated.size();
if (size < 2)
return 0;
// rechtwinkliges Koordinatensystem benutzen
return MathUtils::getAngleDegreeNorth(m_positionsTranslated.at(0).toPointF(), m_positionsTranslated.at(1).toPointF());
}
double PositionsTranslated::angleOfEndSegment() const
{
QMutexLocker lock(&m_mutex);
positionsTranslated();
const int size = m_positionsTranslated.size();
if (size < 2)
return 0;
// rechtwinkliges Koordinatensystem benutzen
return MathUtils::getAngleDegreeNorth(m_positionsTranslated.at(size - 2).toPointF(), m_positionsTranslated.at(size - 1).toPointF());
}
double PositionsTranslated::angleOfClosingSegment() const
{
QMutexLocker lock(&m_mutex);
positionsTranslated();
const int size = m_positionsTranslated.size();
if (size < 2)
return 0;
// rechtwinkliges Koordinatensystem benutzen
return MathUtils::getAngleDegreeNorth(m_positionsTranslated.last().toPointF(), m_positionsTranslated.first().toPointF());
}
void PositionsTranslated::consolidate() const
{
QMutexLocker lock(&m_mutex);
if (m_translated)
{
// ok, m_positions is already translated to m_positionsTranslated
// translate just the remaining m_singlePositions:
// To do so
// 1. add the m_singlePositions to m_positions
m_positions += m_singlePositions;
// 2. translate just the remaining m_singlePositions
// 3. add the now translated singlePositions to
m_positionsTranslated += geographicToMap(m_singlePositions);
// 4. cleanup m_singlePositions:
m_singlePositions.clear();
}
else
{
// move m_singlePositions to m_positions
m_positions += m_singlePositions;
m_singlePositions.clear();
}
}
} // namespace SituationMap