360 lines
8.3 KiB
C++
Executable File
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
|
|
|