802 lines
24 KiB
C++
Executable File
802 lines
24 KiB
C++
Executable File
|
|
/*
|
|
** -----------------------------------------------------------------------------------------------
|
|
**
|
|
** @RDE_HEADER@
|
|
** Implementation of fan of sight
|
|
** $Id$
|
|
** $HeadURL : svn ://192.168.133.21/TDS/branches/product/devel/trunk/Lts/Viewer/SituationMap/Rubberbands/rubberband.cpp $
|
|
** $Author : ehrlicher $
|
|
**
|
|
** -----------------------------------------------------------------------------------------------
|
|
**
|
|
** Hardware - Environment : Intel - PC
|
|
** Software - Environment : Windows 7, Qt 5.x.ArcGISRuntimeQt 100.2
|
|
**
|
|
** Language ........ : C++ 11
|
|
**
|
|
** -----------------------------------------------------------------------------------------------
|
|
**
|
|
** Autor ........... : Nikolaus Hanekamp, SEDG, Tel. 2906
|
|
** Jörg Turla, SPDG, Tel. 3132
|
|
**
|
|
** -----------------------------------------------------------------------------------------------
|
|
**
|
|
** Notices ......... :
|
|
**
|
|
** 01.02.2005, NH : Urversion
|
|
** 15.05.2018, JT : adapting GeISiR source to SituationMap
|
|
**
|
|
** -----------------------------------------------------------------------------------------------
|
|
*/
|
|
|
|
#include "sight_fan_impl.h"
|
|
|
|
#include <GraphicalObjects/graphical_object_path.h>
|
|
|
|
#include <Map/bounding_box.h>
|
|
#include <Map/coord_translation_functor.h>
|
|
|
|
#include <MapImpl/layer_factory_impl.h>
|
|
#include <MapImpl/map_impl.h>
|
|
#include <ElevationMap/elevation_map_manager.h>
|
|
|
|
#include <MathUtils/math_const.h>
|
|
|
|
#include <arcgis/Surface.h>
|
|
|
|
#include <QtCore/QSharedPointer>
|
|
#include <QtCore/QVector>
|
|
#include <QTimer>
|
|
#include <chrono>
|
|
|
|
using namespace std::chrono_literals;
|
|
|
|
|
|
namespace SituationMap
|
|
{
|
|
|
|
// class SightFanImpl::Internal;
|
|
|
|
|
|
enum SightMode { VISIBLE = 0, INVISIBLE, UNDEFINED, START };
|
|
|
|
|
|
class SightEntry
|
|
{
|
|
public:
|
|
|
|
SightEntry() : _dist(0.0), _mode(START) {;}
|
|
SightEntry(double dist, SightMode mode) : _dist(dist), _mode(mode) {;}
|
|
|
|
~SightEntry() = default;
|
|
|
|
double & dist() { return _dist; }
|
|
SightMode & mode() { return _mode; }
|
|
|
|
double dist() const { return _dist; }
|
|
SightMode mode() const { return _mode; }
|
|
|
|
private:
|
|
|
|
double _dist;
|
|
SightMode _mode;
|
|
|
|
}; // SightEntry
|
|
|
|
|
|
|
|
class SightBeam : public Referenced
|
|
{
|
|
public:
|
|
|
|
explicit SightBeam(int beamId, const QPointF &directionB, const QPointF &directionE)
|
|
: _beamId(beamId)
|
|
, _directionBeg(directionB)
|
|
, _directionEnd(directionE)
|
|
, _sightEntryVec()
|
|
, _graphicalQuadVec() {;}
|
|
|
|
SightBeam() = delete;
|
|
~SightBeam() = default;
|
|
|
|
QPointF direction() const
|
|
{
|
|
auto normalize = [](const QPointF &v) -> QPointF
|
|
{
|
|
double l = sqrt(v.x()*v.x() + v.y()*v.y());
|
|
return v / l;
|
|
};
|
|
|
|
return normalize(QPointF((_directionBeg + _directionEnd)*0.5));
|
|
} // QPointF direction()
|
|
|
|
|
|
void add(const SightEntry &sightE)
|
|
{
|
|
_sightEntryVec.push_back(sightE);
|
|
} // void add( const SightEntry &sightE)
|
|
|
|
void clear() { _sightEntryVec.clear(); }
|
|
|
|
// void draw(const QPointF &beamCenter, osg::Matrixd mat, QColor colors[]); // todo: Farbtabelle
|
|
|
|
void updateGraphic( MapImpl *mapImpl, AbstractMapObjectImpl *meMapObj, SightFanImpl::Internal * sightFanInternal );
|
|
|
|
int _beamId;
|
|
|
|
protected:
|
|
|
|
QPointF _directionBeg; // Einheitsvektoren die den Beam begrenzen
|
|
QPointF _directionEnd;
|
|
|
|
using SightEntryVec = QVector<SightEntry>;
|
|
|
|
SightEntryVec _sightEntryVec;
|
|
|
|
QVector<QSharedPointer<GraphicalObjectPath>> _graphicalQuadVec;
|
|
|
|
}; /* SightBeam */
|
|
|
|
|
|
class SightFanImpl::Internal
|
|
{
|
|
public:
|
|
|
|
using SightBeamVec = std::vector<RefPointer<SightBeam>> ;
|
|
|
|
QString m_layerName;
|
|
std::shared_ptr<ElevationMapManager> m_eMapManager;
|
|
QPointF m_center;
|
|
double m_centHat;
|
|
double m_objHat;
|
|
double m_radius;
|
|
double m_innerRadius;
|
|
double m_startAngle;
|
|
double m_dAngle;
|
|
unsigned int m_nrFans;
|
|
|
|
double m_alpha;
|
|
|
|
QRectF m_location; // Lage des SightFans in Kartenkoordinaten
|
|
|
|
SightBeamVec m_sightBeamVec;
|
|
|
|
QColor m_colors[3]; // 0 : visibleCol, 1 : invisibleCol, 2 : undefinedCol
|
|
|
|
QColor m_fanColorVec[2][4];
|
|
|
|
float m_fanMult; // Farbabsenkung jedes 2. Beams < 1.0 !
|
|
|
|
MapImpl *m_mapImpl;
|
|
Esri::ArcGISRuntime::Surface *m_surface;
|
|
|
|
LOGGER_T m_logger; ///< Interface of the Logging-Facility
|
|
|
|
Internal()
|
|
: m_layerName()
|
|
, m_center()
|
|
, m_centHat(1.8)
|
|
, m_objHat(0.5)
|
|
, m_radius(0.0)
|
|
, m_innerRadius(0.0)
|
|
, m_startAngle(0.0)
|
|
, m_dAngle(2.0*MathConst::pi/180)
|
|
, m_nrFans(180)
|
|
, m_alpha(0.8)
|
|
, m_fanMult(0.75)
|
|
, m_mapImpl(nullptr)
|
|
, m_surface(nullptr)
|
|
, m_logger(getLogger("SightFanImpl"))
|
|
{;}
|
|
|
|
|
|
void setFanColorMap( double brightness, double bias, double alpha)
|
|
{
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
double r = (m_colors[i].redF() * brightness) + bias;
|
|
double g = (m_colors[i].greenF() * brightness) + bias;
|
|
double b = (m_colors[i].blueF() * brightness) + bias;
|
|
double a = m_colors[i].alphaF() * alpha;
|
|
|
|
m_fanColorVec[0][i] = QColor::fromRgbF(r,g,b,a);
|
|
m_fanColorVec[1][i] = QColor::fromRgbF(r*m_fanMult,g*m_fanMult,b*m_fanMult,a);
|
|
|
|
}
|
|
m_fanColorVec[0][3] = m_fanColorVec[0][2];
|
|
m_fanColorVec[1][3] = m_fanColorVec[1][2];
|
|
} // void setFanColorMap()
|
|
|
|
|
|
}; // SightFanImpl::Internal
|
|
|
|
|
|
SightFanImpl::SightFanImpl( const QString &debugInfo )
|
|
: SightFan()
|
|
, QObject()
|
|
, AbstractMapObjectImpl(debugInfo)
|
|
, m_internal(new Internal())
|
|
, m_moveDelayTimer(new QTimer(this))
|
|
|
|
{
|
|
initColors();
|
|
m_internal->setFanColorMap(1, 0, 1);
|
|
m_moveDelayTimer->setSingleShot(true);
|
|
m_moveDelayTimer->setInterval(250ms);
|
|
connect(m_moveDelayTimer, &QTimer::timeout, this, &SightFanImpl::delayedMove);
|
|
} // SightFanImpl::SightFanImpl
|
|
|
|
|
|
SightFanImpl::~SightFanImpl()
|
|
{
|
|
delete m_internal;
|
|
} // SightFanImpl::~SightFanImpl()
|
|
|
|
|
|
void SightFanImpl::initColors()
|
|
{
|
|
m_internal->m_fanMult = 0.75;
|
|
m_internal->m_colors[0] = QColor(0, 255, 0, 180);
|
|
m_internal->m_colors[1] = QColor(255, 0, 0, 180);
|
|
m_internal->m_colors[2] = QColor(0, 0, 255, 180);
|
|
} // void SightFanImpl::initColors()
|
|
|
|
|
|
void SightFanImpl::setFanColor( const QColor &visible, const QColor &invisible, const QColor &undefined)
|
|
{
|
|
m_internal->m_colors[0] = visible;
|
|
m_internal->m_colors[1] = invisible;
|
|
m_internal->m_colors[2] = undefined;
|
|
} // void SightFanImpl::setFanColor( const QColor &visible, const QColor &invisible, const QColor &undefined)
|
|
|
|
|
|
void SightFanImpl::setFanColorMark( float colMult)
|
|
{
|
|
if( colMult > 1.0)
|
|
colMult = 1.0;
|
|
if( colMult < 0.0)
|
|
colMult = 0.0;
|
|
|
|
m_internal->m_fanMult = colMult;
|
|
} // void SightFanImpl::setFanColorMark( float colMult)
|
|
|
|
|
|
void SightFanImpl::setCenter(const QPointF ¢er) { m_internal->m_center = center; }
|
|
void SightFanImpl::setCenter(const Point3D ¢er) { m_internal->m_center = center.toPointF();
|
|
m_internal->m_centHat = center.z(); }
|
|
|
|
void SightFanImpl::setCenter(const QPointF ¢er, double centerHat) { m_internal->m_center = center;
|
|
m_internal->m_centHat = centerHat; }
|
|
|
|
void SightFanImpl::setCenterHat(double centerHat) { m_internal->m_centHat = centerHat; }
|
|
void SightFanImpl::setObjectHat(double objHat) { m_internal->m_objHat = objHat; }
|
|
|
|
void SightFanImpl::setRadius(double radius) { m_internal->m_radius = radius; }
|
|
void SightFanImpl::setInnerRadius(double radius) { m_internal->m_innerRadius = radius; }
|
|
void SightFanImpl::setStartAngle(double startAngle) { m_internal->m_startAngle = startAngle; }
|
|
void SightFanImpl::setdeltaAngle(double dAngle) { m_internal->m_dAngle = dAngle; }
|
|
void SightFanImpl::setNoOfFans(double noFans) { m_internal->m_nrFans = noFans; }
|
|
|
|
|
|
void SightFanImpl::setAlpha(double alpha)
|
|
{
|
|
if (alpha < 0.0) alpha = 0.0;
|
|
if (alpha > 1.0) alpha = 1.0;
|
|
|
|
m_internal->m_alpha = alpha;
|
|
} // void SightFanImpl::setAlpha(double alpha)
|
|
|
|
|
|
QPointF SightFanImpl::center() const { return m_internal->m_center; }
|
|
double SightFanImpl::centerHat() const { return m_internal->m_centHat; }
|
|
double SightFanImpl::objectHat() const { return m_internal->m_objHat; }
|
|
double SightFanImpl::innerRadius() const { return m_internal->m_innerRadius; }
|
|
double SightFanImpl::radius() const { return m_internal->m_radius; }
|
|
double SightFanImpl::startAngle() const { return m_internal->m_startAngle; }
|
|
double SightFanImpl::dAngle() const { return m_internal->m_dAngle; }
|
|
double SightFanImpl::alpha() const { return m_internal->m_alpha; }
|
|
unsigned int SightFanImpl::noOfFans() const { return m_internal->m_nrFans; }
|
|
|
|
bool SightFanImpl::init(MapImpl *mapImpl, const QString &logicalLayerName)
|
|
{
|
|
if (mapImpl)
|
|
{
|
|
m_internal->m_mapImpl = mapImpl;
|
|
m_internal->m_layerName = logicalLayerName;
|
|
m_internal->m_eMapManager = mapImpl->getElevationMapManager();
|
|
|
|
if (!m_internal->m_eMapManager)
|
|
{
|
|
ERROR_LOG(m_internal->m_logger) << LOGFUNCTION << " failure, no ElevationMapManager";
|
|
return false;
|
|
}
|
|
if (!AbstractMapObjectImpl::init(mapImpl, logicalLayerName))
|
|
{
|
|
ERROR_LOG(m_internal->m_logger) << LOGFUNCTION << " failure, AbstractMapObjectImpl::init failed";
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
ERROR_LOG(m_internal->m_logger) << LOGFUNCTION << " init SightFanImpl failed";
|
|
return false;
|
|
} // bool SightFanImpl::init(MapImpl *mapImpl, const QString &logicalLayerName)
|
|
|
|
|
|
void SightFanImpl::boundingBox(BoundingBox &bbox) const
|
|
{
|
|
bbox.reset();
|
|
|
|
CoordTranslationFunctor * coordTransFunc = m_internal->m_mapImpl->coordTranslationFunctor();
|
|
|
|
if (coordTransFunc)
|
|
{
|
|
const QPointF ¢erMap = coordTransFunc->geographicToMap(m_internal->m_center);
|
|
double diameter = 2 * m_internal->m_radius;
|
|
|
|
bbox = BoundingBox( BoundingBox::ExtentType::Sim, Point3D::fromQPointF(centerMap), diameter, diameter );
|
|
}
|
|
} // void SightFanImpl::boundingBox(BoundingBox &bbox) const
|
|
|
|
//---------------------------------------------------------------------------------------------------
|
|
|
|
void SightFanImpl::initFan( const Point3D ¢er
|
|
, double objHat
|
|
, double radius
|
|
, double innerRadius
|
|
, double startAngle
|
|
, double dAngle
|
|
, unsigned int nrFans
|
|
, double alpha )
|
|
{
|
|
initFan( center.toPointF(), center.z(), objHat, radius, innerRadius, startAngle, dAngle, nrFans, alpha );
|
|
} // void SightFanImpl::init(...)
|
|
|
|
|
|
void SightFanImpl::initFan( const QPointF ¢er
|
|
, double centHat
|
|
, double objHat
|
|
, double radius
|
|
, double innerRadius
|
|
, double startAngle
|
|
, double dAngle
|
|
, unsigned int nrFans
|
|
, double alpha )
|
|
{
|
|
if (!m_internal->m_mapImpl)
|
|
{
|
|
ERROR_LOG(m_internal->m_logger) << LOGFUNCTION << " no mapImpl";
|
|
return;
|
|
}
|
|
|
|
if (alpha < 0.0) alpha = 0.0;
|
|
if (alpha > 1.0) alpha = 1.0;
|
|
|
|
m_internal->m_center = center;
|
|
m_internal->m_centHat = centHat;
|
|
m_internal->m_objHat = objHat;
|
|
m_internal->m_radius = radius;
|
|
m_internal->m_innerRadius = innerRadius;
|
|
m_internal->m_startAngle = startAngle;
|
|
m_internal->m_dAngle = (dAngle < 0) ? -dAngle : dAngle;
|
|
m_internal->m_nrFans = nrFans;
|
|
m_internal->m_alpha = alpha;
|
|
|
|
QPointF offc(m_internal->m_radius, -m_internal->m_radius);
|
|
m_internal->m_location = QRectF(m_internal->m_center - offc, m_internal->m_center + offc);
|
|
|
|
if ((m_internal->m_nrFans*m_internal->m_dAngle) > (MathConst::pi*2.0))
|
|
{
|
|
m_internal->m_nrFans = floor((MathConst::pi*2.0) / m_internal->m_dAngle + 0.5); // To avoid error with floor; 30.3.2006 JT
|
|
}
|
|
|
|
calculateSightBeamVec();
|
|
|
|
} /* SightFan::SightFan */
|
|
|
|
|
|
void SightFanImpl::calculateSightBeamVec()
|
|
{
|
|
m_internal->m_sightBeamVec.clear();
|
|
|
|
double dAlfa = (m_internal->m_dAngle / 2.0) + 0.00025; // 0.00025 wegen Überlappung, auf antialiazed Systemen nicht nötig
|
|
|
|
for (unsigned int i = 0; i < m_internal->m_nrFans; i++)
|
|
{
|
|
double alfa = m_internal->m_startAngle + m_internal->m_dAngle * i;
|
|
double alfaBeg = alfa - dAlfa;
|
|
double alfaEnd = alfa + dAlfa;
|
|
|
|
RefPointer<SightBeam> sBeam = RefPointer<SightBeam>(new SightBeam(i, QPointF(cos(alfaBeg), sin(alfaBeg)), QPointF(cos(alfaEnd), sin(alfaEnd))));
|
|
calculateSightBeam(*(sBeam.get()));
|
|
m_internal->m_sightBeamVec.push_back(sBeam);
|
|
}
|
|
} // void SightFanImpl::calculateSightBeamVev()
|
|
|
|
|
|
void SightFanImpl::move(const QPointF ¢er, double centHat, double objHat)
|
|
{
|
|
|
|
m_internal->m_centHat = centHat;
|
|
m_internal->m_objHat = objHat;
|
|
move(center);
|
|
} // void SightFanImpl::move(ElevationMap &eMap, QPointF ¢er, double centHat, double objHat)
|
|
|
|
|
|
void SightFanImpl::move(const QPointF & center)
|
|
{
|
|
m_moveDelayedCenter = center;
|
|
m_moveDelayTimer->start();
|
|
|
|
}
|
|
|
|
void SightFanImpl::show()
|
|
{
|
|
move( m_internal->m_center );
|
|
} // void SightFanImpl::show
|
|
|
|
|
|
bool SightFanImpl::updateViewImplPre()
|
|
{
|
|
return true;
|
|
} // bool SightFanImpl::updateViewImplPre()
|
|
|
|
|
|
bool SightFanImpl::updateViewImpl()
|
|
{
|
|
show();
|
|
return true;
|
|
} // bool SightFanImpl::updateViewImpl()
|
|
|
|
|
|
bool SightFanImpl::updateViewImplPost()
|
|
{
|
|
return true;
|
|
} // bool SightFanImpl::updateViewImplPost()
|
|
|
|
|
|
inline QPointF mittelBreitenRechnung(const QPointF &start, const QPointF &direction, double distance)
|
|
{
|
|
// ---------------------------------------------------------------
|
|
// Vec2d mittelBreitenRechnung( Vec2d start, Vec2d direction, double distance )
|
|
|
|
// Berechnet näherungsweise die Koordinate der Endposition eines
|
|
// Beams gemäß der ersten Aufgabe der Besteckrechnung durch das
|
|
// Verfahren der Mittelbreite.
|
|
// Siehe http://astrosail.de/de/static/tutorial/best3.php?cat=42
|
|
|
|
// Start ist die Anfangskoordinate im Bogenmaß, direction der
|
|
// normierte Richtungsvektor, distance die Entfernung in Metern.
|
|
// ---------------------------------------------------------------
|
|
double cosKurs = direction.y();
|
|
double sinKurs = direction.x();
|
|
double distanceBogen = distance / MathConst::EarthRadius;
|
|
double lat = distanceBogen * cosKurs + start.y();
|
|
double mittelbreite = (start.y() + lat) * 0.5;
|
|
double lon = distanceBogen * sinKurs / cos(mittelbreite) + start.x();
|
|
return {lon, lat};
|
|
}
|
|
|
|
inline QPointF endOfBeam( const QPointF &start, const QPointF &direction, double distance )
|
|
{
|
|
return mittelBreitenRechnung(start,direction,distance);
|
|
}
|
|
|
|
|
|
void SightFanImpl::calculateSightBeam(SightBeam &sBeam)
|
|
{
|
|
const QPointF &direction = sBeam.direction();
|
|
const QPointF &end = endOfBeam(m_internal->m_center, direction, m_internal->m_radius);
|
|
|
|
LOSVector losProfile;
|
|
m_internal->m_eMapManager->LOSProfile(m_internal->m_center, end, losProfile);
|
|
calculateSightBeam(losProfile, sBeam);
|
|
sBeam.updateGraphic(m_internal->m_mapImpl, this, m_internal);
|
|
} // void SightFanImpl::calculateSightBeam(ElevationMap &eMap, SightBeam &sBeam)
|
|
|
|
|
|
void SightFanImpl::calculateSightBeam( const LOSVector &losProfile, SightBeam &sBeam )
|
|
{
|
|
sBeam.clear();
|
|
|
|
if (losProfile.empty()) // Startpunkt undefiniert oder ausserhalb der Karte
|
|
{
|
|
sBeam.add( SightEntry(m_internal->m_innerRadius, START) );
|
|
sBeam.add( SightEntry(m_internal->m_radius, UNDEFINED) );
|
|
return;
|
|
}
|
|
|
|
LOSVector::const_iterator itr = losProfile.begin();
|
|
double centerHeight = itr->height() + m_internal->m_centHat;
|
|
|
|
double d1 = 0.0;
|
|
double height1 = itr->height();
|
|
|
|
// überspringen bis _innerRadius erreicht ist !
|
|
while(++itr != losProfile.end())
|
|
{
|
|
double d2 = itr->dist(); // *EarthRadius;
|
|
double height2 = itr->height();
|
|
if (d2 >= m_internal->m_innerRadius)
|
|
{
|
|
height1 = height1 + (m_internal->m_innerRadius - d1) * ( height2 - height1)/(d2 - d1);
|
|
d1 = m_internal->m_innerRadius;
|
|
--itr;
|
|
break;
|
|
}
|
|
d1 = d2;
|
|
height1 = height2;
|
|
}
|
|
|
|
// bool visible = true;
|
|
SightMode mode = START;
|
|
|
|
double curM = (height1 - centerHeight ) / d1; // bestimmende Steigung
|
|
|
|
sBeam.add(SightEntry( d1, START));
|
|
|
|
if (itr != losProfile.end())
|
|
{
|
|
while (++itr != losProfile.end())
|
|
{
|
|
double d2 = itr->dist(); // *EarthRadius;
|
|
double height2 = itr->height();
|
|
|
|
if (std::isnan(height2)) // Undefined
|
|
{
|
|
if (mode != START)
|
|
{
|
|
sBeam.add(SightEntry(d1, mode));
|
|
}
|
|
mode = UNDEFINED;
|
|
break;
|
|
}
|
|
|
|
double hObj = (height2 + m_internal->m_objHat - centerHeight );
|
|
double objM = hObj / d2; // Steigung bezogen auf Objekte( Objekte verdecken nicht !)
|
|
|
|
SightMode newMode = ((objM >= curM)) ? VISIBLE : INVISIBLE;
|
|
|
|
if(newMode != mode)
|
|
{
|
|
if ((mode != START) && (d2 != d1))
|
|
{
|
|
// Korrekturwert für Distanz berechnen, unter Berücksichtigung der Objekthoehe !!
|
|
double localM = (height2 - height1) /(d2 -d1);
|
|
// localM == curM kann nicht auftreten, da newMode != mode
|
|
double dCorr = (hObj - (curM * d2)) / (localM - curM);
|
|
|
|
if (dCorr < 0.0)
|
|
dCorr = 0.0;
|
|
dCorr = d2 - dCorr;
|
|
if (dCorr < d1)
|
|
dCorr = d1;
|
|
|
|
sBeam.add( SightEntry( dCorr, mode) );
|
|
}
|
|
mode = newMode;
|
|
}
|
|
|
|
double terrM = (height2 - centerHeight) / d2; // Steigung bezogen auf Gelaende
|
|
if (terrM >= curM)
|
|
{
|
|
curM = terrM; // neue bestimmende Steigung
|
|
}
|
|
|
|
height1 = height2;
|
|
d1 = d2;
|
|
} /* while */
|
|
}
|
|
sBeam.add( SightEntry(m_internal->m_radius, mode) );
|
|
}
|
|
/*!
|
|
* \brief SightFanImpl::delayedMove
|
|
* \param center
|
|
* \details Delays the move call to prevent crash of map beacause of the heavy load while moving
|
|
*/
|
|
void SightFanImpl::delayedMove()
|
|
{
|
|
m_internal->m_center = m_moveDelayedCenter;
|
|
|
|
m_internal->setFanColorMap(1, 0, 1);
|
|
|
|
QPointF offc(m_internal->m_radius, -m_internal->m_radius);
|
|
m_internal->m_location = QRectF(m_internal->m_center - offc, m_internal->m_center + offc);
|
|
|
|
if (m_internal->m_nrFans == m_internal->m_sightBeamVec.size())
|
|
{
|
|
for (RefPointer<SightBeam> sBeam : qAsConst(m_internal->m_sightBeamVec))
|
|
{
|
|
calculateSightBeam(*sBeam.get());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
calculateSightBeamVec();
|
|
}
|
|
}
|
|
|
|
|
|
void SightBeam::updateGraphic(MapImpl *mapImpl, AbstractMapObjectImpl *meMapObj, SightFanImpl::Internal *sightFanInternal)
|
|
{
|
|
if (!mapImpl || !meMapObj || !sightFanInternal)
|
|
return;
|
|
|
|
if (_sightEntryVec.size() <= 1)
|
|
return;
|
|
|
|
Esri::ArcGISRuntime::GraphicsOverlay *graphicLayer = sightFanInternal->m_mapImpl->getGraphicsLayer(sightFanInternal->m_layerName);
|
|
if (!graphicLayer)
|
|
{
|
|
ERROR_LOG(sightFanInternal->m_logger) << LOGFUNCTION << " Creating graphic overlayer \'" << sightFanInternal->m_layerName << "\' failed. Can't render sight fan";
|
|
return;
|
|
}
|
|
|
|
// _sightEntryVec[0] is SightMode::START
|
|
|
|
// resize _graphicalQuadVec according _sightEntryVec
|
|
// (_sightEntryVec.size() <= 1 is chexck above)
|
|
const int newGraphicalSize = _sightEntryVec.size() - 1;
|
|
_graphicalQuadVec.resize(newGraphicalSize);
|
|
|
|
CoordTranslationFunctor *geoToMap = sightFanInternal->m_mapImpl->coordTranslationFunctor();
|
|
|
|
int quadNo = 0;
|
|
SightEntryVec::iterator itr = _sightEntryVec.begin();
|
|
|
|
const QPointF ¢er = sightFanInternal->m_center;
|
|
QPointF v0 = endOfBeam(center, _directionBeg, itr->dist());
|
|
QPointF v1 = endOfBeam(center, _directionEnd, itr->dist());
|
|
|
|
if (geoToMap)
|
|
{
|
|
v0 = geoToMap->geographicToMap(v0);
|
|
v1 = geoToMap->geographicToMap(v1);
|
|
}
|
|
|
|
PositionCont locationVec;
|
|
|
|
// skip first, we know mode==SightMode::START
|
|
while (++itr != _sightEntryVec.end())
|
|
{
|
|
// GraphicalObjectPath already created :
|
|
QSharedPointer<GraphicalObjectPath> &spGopRef = _graphicalQuadVec[quadNo];
|
|
if (!spGopRef)
|
|
{
|
|
GraphicalObjectPath * grQuad = new GraphicalObjectPath( GraphicalObjectPathType::Polygon
|
|
, mapImpl->getEsriGeoView()
|
|
, graphicLayer
|
|
, QStringLiteral("FanOfSight-Beam-%1").arg(_beamId)
|
|
, meMapObj->uniqueMapId() );
|
|
grQuad->setPickable(false);
|
|
grQuad->rLineStyle().setLinePattern(LinePattern::Null);
|
|
grQuad->rFillStyle().setFillPattern(FillPattern::Solid);
|
|
|
|
// write to _graphicalQuadVec
|
|
spGopRef = QSharedPointer<GraphicalObjectPath>(grQuad);
|
|
}
|
|
// : GraphicalObjectPath already created
|
|
|
|
GraphicalObjectPath * grQuad = _graphicalQuadVec[quadNo].data();
|
|
Q_ASSERT_X(grQuad, "SightBeam", "GraphicalObjectPath invalid");
|
|
|
|
SightMode mode = itr->mode();
|
|
double dist = itr->dist();
|
|
QColor quadColor = sightFanInternal->m_fanColorVec[_beamId % 2][int(mode)];
|
|
|
|
quadColor.setAlphaF( quadColor.alphaF()*sightFanInternal->m_alpha );
|
|
|
|
grQuad->rFillStyle().setFillColor(quadColor);
|
|
|
|
QPointF v2 = endOfBeam(center, _directionBeg, dist);
|
|
QPointF v3 = endOfBeam(center, _directionEnd, dist);
|
|
|
|
if (geoToMap)
|
|
{
|
|
v2 = geoToMap->geographicToMap(v2);
|
|
v3 = geoToMap->geographicToMap(v3);
|
|
}
|
|
|
|
locationVec.clear();
|
|
locationVec << Point3D::fromQPointF(v0);
|
|
locationVec << Point3D::fromQPointF(v1);
|
|
locationVec << Point3D::fromQPointF(v2);
|
|
locationVec << Point3D::fromQPointF(v3);
|
|
|
|
grQuad->setPositions(locationVec);
|
|
|
|
grQuad->updateView();
|
|
|
|
v0 = v3;
|
|
v1 = v2;
|
|
|
|
++quadNo;
|
|
} /* while */
|
|
|
|
} // void SightBeam::updateGraphic(MapImpl *mapImpl, AbstractMapObjectImpl *meMapObj, SightFanImpl::Internal *sightFanInternal)
|
|
|
|
|
|
#ifdef NEVER
|
|
bool SightFan::draw( const AbstractView * const view, osg::Matrixd mat,
|
|
float alpha, float brightness, float bias, MapObject::RenderState rstate ) // todo: Farbtabelle
|
|
{
|
|
if ((rstate & _renderState) == 0) return false;
|
|
|
|
if( !( _location.intersects( view->rectBound()) )) return false; // isCulled
|
|
|
|
|
|
ColorVec colors[2][4];
|
|
for( int i = 0; i < 3; i++)
|
|
{
|
|
colors[0][i] = (_colors[i] * brightness) + bias;
|
|
colors[1][i] = colors[0][i] * _fanMult;
|
|
colors[0][i].alpha = alpha * _colors[i].alpha;
|
|
colors[1][i].alpha = alpha * _colors[i].alpha;
|
|
}
|
|
colors[0][3] = colors[0][2];
|
|
colors[1][3] = colors[1][2];
|
|
|
|
GLint shadeModel;
|
|
|
|
glGetIntegerv( GL_SHADE_MODEL, &shadeModel );
|
|
glShadeModel(GL_FLAT);
|
|
glEnable( GL_BLEND);
|
|
|
|
int n = 0;
|
|
for( SightBeamVec::iterator itr = _sightBeamVec.begin(); itr != _sightBeamVec.end(); ++itr)
|
|
{
|
|
(*itr).get()->draw( _center, mat, colors[(++n)%2]);
|
|
}
|
|
|
|
glDisable( GL_BLEND);
|
|
glShadeModel(shadeModel);
|
|
return true;
|
|
} /* SightFan::draw */
|
|
|
|
|
|
|
|
void SightBeam::draw( Vec2d center, osg::Matrixd mat, ColorVec colors[]) // todo: Farbtabelle !?
|
|
{
|
|
float z = 0;
|
|
|
|
if( _sightEntryVec.size() <= 1) return;
|
|
|
|
SightEntryVec::iterator itr = _sightEntryVec.begin();
|
|
|
|
Vec2d v0 = endOfBeam( center, _directionBeg, (*itr).dist() );
|
|
Vec2d v1 = endOfBeam( center, _directionEnd, (*itr).dist() );
|
|
|
|
osg::Vec3d _v0 = mat.preMult( osg::Vec3d( v0[0], v0[1], 0.0 ));
|
|
osg::Vec3d _v1 = mat.preMult( osg::Vec3d( v1[0], v1[1], 0.0 ));
|
|
|
|
glBegin( GL_QUAD_STRIP);
|
|
{
|
|
glVertex3f( _v0.x(), _v0.y(), z);
|
|
glVertex3f( _v1.x(), _v1.y(), z);
|
|
|
|
|
|
while( ++itr != _sightEntryVec.end() )
|
|
{
|
|
SightMode mode = (*itr).mode();
|
|
glColor4f( colors[mode].red, colors[mode].green, colors[mode].blue, colors[mode].alpha);
|
|
|
|
v0 = endOfBeam( center, _directionBeg, (*itr).dist() );
|
|
v1 = endOfBeam( center, _directionEnd, (*itr).dist() );
|
|
|
|
_v0 = mat.preMult( osg::Vec3d( v0[0], v0[1], 0.0 ));
|
|
_v1 = mat.preMult( osg::Vec3d( v1[0], v1[1], 0.0 ));
|
|
|
|
glVertex3f( _v0.x(), _v0.y(), z);
|
|
glVertex3f( _v1.x(), _v1.y(), z);
|
|
} /* while */
|
|
}
|
|
glEnd();
|
|
} /* SightBeam::draw */
|
|
#endif
|
|
|
|
|
|
|
|
} // SituationMap
|
|
|
|
|