Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
+664
@@ -0,0 +1,664 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Interface
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
// Own
|
||||
#include "building_contamination.h"
|
||||
#include <Map/map.h>
|
||||
#include <Map/object_factory.h>
|
||||
#include <MapObjects/cube.h>
|
||||
|
||||
#include <LtsCoordTrans/lts_coord_trans.h>
|
||||
#include <MathUtils/simple_helper.h>
|
||||
|
||||
#include <functional>
|
||||
|
||||
#define USE_BUFFER_APPROACH
|
||||
#ifdef USE_BUFFER_APPROACH
|
||||
# include <arcgis/PolygonBuilder.h>
|
||||
# include <arcgis/GeometryEngine.h>
|
||||
#endif // USE_BUFFER_APPROACH
|
||||
|
||||
namespace SituationMap
|
||||
{
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
class BuildingContamination::Private
|
||||
{
|
||||
public:
|
||||
explicit Private() = default;
|
||||
|
||||
~Private() = default;
|
||||
|
||||
// buildingId, BuildingContamination
|
||||
QMap<int32_t, Buildings::BuildingState> m_buildingStateData;
|
||||
|
||||
Map *m_map = nullptr;
|
||||
|
||||
// MapObjects
|
||||
QMap<QPair<int, int>, UniqueMapId> m_bldgFlr2UniqueMapId;
|
||||
|
||||
bool m_visible = false;
|
||||
int m_drawOrder = 0;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static QPair<int, int> createKey(int buildingId, int floorId)
|
||||
{
|
||||
return {buildingId, floorId};
|
||||
}
|
||||
|
||||
static int buildingIdOfKey(const QPair<int, int> &keyData)
|
||||
{
|
||||
return keyData.first;
|
||||
}
|
||||
|
||||
|
||||
RefPointer<Cube> getCreateCube(int buildingId, int floorId)
|
||||
{
|
||||
const QPair<int, int> &key = createKey(buildingId, floorId);
|
||||
const UniqueMapId uniqueMapId = m_bldgFlr2UniqueMapId.value(key, INVALID_MAP_ID);
|
||||
|
||||
if (!SituationMap::isUniqueMapIdValid(uniqueMapId))
|
||||
{
|
||||
const QString &layernameForCubes = m_map->layerFactory().layernameForCubes();
|
||||
const QString &key_debugInfo = QStringLiteral("bldg_%1-flr%2").arg(buildingId).arg(floorId);
|
||||
|
||||
RefPointer<Cube> cube =
|
||||
m_map->objectFactory().create<Cube>(layernameForCubes, key_debugInfo);
|
||||
|
||||
if (cube.valid())
|
||||
m_bldgFlr2UniqueMapId[key] = cube->uniqueMapId();
|
||||
return cube;
|
||||
}
|
||||
return m_map->objectFactory().get<Cube>(uniqueMapId);
|
||||
}
|
||||
|
||||
void removeCube(int buildingId = -1)
|
||||
{
|
||||
QMutableMapIterator<QPair<int, int>, UniqueMapId> mapIt(m_bldgFlr2UniqueMapId);
|
||||
|
||||
while (mapIt.hasNext())
|
||||
{
|
||||
mapIt.next();
|
||||
|
||||
const QPair<int, int> &key = mapIt.key();
|
||||
int curBuildingId = buildingIdOfKey(key);
|
||||
|
||||
if ((buildingId < 0) ||
|
||||
(buildingId == curBuildingId)
|
||||
)
|
||||
{
|
||||
UniqueMapId uMapId = mapIt.value();
|
||||
SituationMap::AbstractMapObject *mapObj = m_map->objectFactory().idToMapObject(uMapId);
|
||||
if (mapObj)
|
||||
mapObj->removeMySelf();
|
||||
|
||||
// Will remove that pair from map:
|
||||
mapIt.remove();
|
||||
}
|
||||
} // while
|
||||
}
|
||||
|
||||
bool updateVisibility(int buildingId = -1)
|
||||
{
|
||||
bool success = true;
|
||||
QMutableMapIterator<QPair<int, int>, UniqueMapId> mapIt(m_bldgFlr2UniqueMapId);
|
||||
while (mapIt.hasNext())
|
||||
{
|
||||
mapIt.next();
|
||||
|
||||
const QPair<int, int> &key = mapIt.key();
|
||||
int curBuildingId = buildingIdOfKey(key);
|
||||
|
||||
if ((buildingId < 0) ||
|
||||
(buildingId == curBuildingId)
|
||||
)
|
||||
{
|
||||
UniqueMapId uMapId = mapIt.value();
|
||||
SituationMap::AbstractMapObject *mapObj = m_map->objectFactory().idToMapObject(uMapId);
|
||||
if (mapObj)
|
||||
{
|
||||
mapObj->setVisibility(m_visible);
|
||||
if (!mapObj->updateView())
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
} // while
|
||||
return success;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// class BuildingContamination
|
||||
//------------------------------------------------------------------------------
|
||||
BuildingContamination::BuildingContamination(int drawOrder, QObject *parent)
|
||||
: BaseClass(parent)
|
||||
, m_logger(getLogger("BuildingContamination"))
|
||||
, d(new Private())
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
d->m_drawOrder = drawOrder;
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
}
|
||||
|
||||
BuildingContamination::~BuildingContamination()
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
this->stop();
|
||||
// this->removeAllObjects(); // will be done by dtor on Map
|
||||
delete d;
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
}
|
||||
|
||||
bool BuildingContamination::init(Map *map, PluginProvider *pluginProvider)
|
||||
{
|
||||
d->m_map = map;
|
||||
|
||||
if (!d->m_map)
|
||||
return false;
|
||||
|
||||
if (!pluginProvider ||
|
||||
!pluginProvider->cesDtc() ||
|
||||
!pluginProvider->ismDtc())
|
||||
return false;
|
||||
|
||||
m_bldDtc = pluginProvider->bldDtc();
|
||||
m_ismDtc = pluginProvider->ismDtc();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void BuildingContamination::removeAllObjects()
|
||||
{
|
||||
d->removeCube(); // will remove all stored MapObjects/Cubes
|
||||
}
|
||||
|
||||
bool BuildingContamination::run()
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
|
||||
if (!d->m_map)
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " no m_map";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_bldDtc)
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " no m_bldDtc";
|
||||
return false;
|
||||
}
|
||||
|
||||
m_bldDtc->disconnect(this);
|
||||
|
||||
qRegisterMetaType<Buildings::BuildingState>("Buildings::BuildingState");
|
||||
|
||||
connect(m_bldDtc.get(), &Buildings::Interface::Dtc::buildingStateChanged,
|
||||
this, &BuildingContamination::onBuildingStateChanged, Qt::QueuedConnection);
|
||||
|
||||
// get:
|
||||
m_bldDtc->buildingStates([this](const Buildings::BuildingState & data)
|
||||
{
|
||||
onBuildingStateChanged(data, DataModification::eAdded);
|
||||
});
|
||||
|
||||
|
||||
// Trigger manually :
|
||||
if (false)
|
||||
{
|
||||
std::function<void(int, int, int)> fTriggerBuilding = [this](int partyId, int buildingId, int floorId)
|
||||
{
|
||||
// V100.1: Renderingmode::Dynamic -> cube shows height
|
||||
// V100.1: Renderingmode::Static -> cube is flat
|
||||
|
||||
// retrieve geometry:
|
||||
const PositionCont &absPositionsGeo = retrieveBuildingGeometry(buildingId, floorId);
|
||||
|
||||
// retrieve height:
|
||||
QMap<int, double> floorHeights = retrieveBuildingAbsHeight(buildingId);
|
||||
|
||||
// cubes:
|
||||
RefPointer<Cube> cube = d->getCreateCube(buildingId, floorId);
|
||||
if (!cube)
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " no cube created";
|
||||
|
||||
cube->setVisibility(d->m_visible);
|
||||
cube->setDrawOrder(d->m_drawOrder);
|
||||
|
||||
cube->setPartyId(partyId); // means: set partyId of owner
|
||||
cube->setPositions(absPositionsGeo);
|
||||
const double height = floorHeights.value(floorId, 2.5 * floorId);
|
||||
cube->setHeight(height);
|
||||
|
||||
bool success = cube->updateView();
|
||||
INFO_LOG(m_logger) << LOGFUNCTION << " cube->updateView " << success;
|
||||
};
|
||||
|
||||
// partyId, bldId, floorid
|
||||
fTriggerBuilding(24, 5, 1);
|
||||
fTriggerBuilding(-1, 5, 2);
|
||||
fTriggerBuilding(89, 5, 3);
|
||||
|
||||
}
|
||||
// : Trigger manually
|
||||
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
return true;
|
||||
}
|
||||
|
||||
void BuildingContamination::stop()
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
m_bldDtc->disconnect(this);
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
}
|
||||
|
||||
bool BuildingContamination::isVisible() const
|
||||
{
|
||||
return d->m_visible;
|
||||
}
|
||||
bool BuildingContamination::setVisible(bool visible)
|
||||
{
|
||||
d->m_visible = visible;
|
||||
bool succ = d->updateVisibility();
|
||||
return succ;
|
||||
}
|
||||
|
||||
void BuildingContamination::onBuildingStateChanged(const Buildings::BuildingState &data, DataModification modType)
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
|
||||
const int buildingId = data.id();
|
||||
|
||||
switch (modType)
|
||||
{
|
||||
case DataModification::eAdded:
|
||||
case DataModification::eModified:
|
||||
// retrieve geometry from ISM and ownership and finally create cubes
|
||||
updateBuilding(buildingId);
|
||||
break;
|
||||
case DataModification::eRemoved:
|
||||
// reset ownership -> remove cubes:
|
||||
d->removeCube(buildingId);
|
||||
break;
|
||||
|
||||
} // switch
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
}
|
||||
|
||||
void BuildingContamination::onResetBuildingState()
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START";
|
||||
d->removeCube();
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
}
|
||||
|
||||
void BuildingContamination::updateBuilding(int buildingId)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "update Building " << buildingId;
|
||||
// retrieve data for complete building:
|
||||
const Buildings::BuildingState &bos = m_bldDtc->buildingState(buildingId);
|
||||
|
||||
// update own data:
|
||||
d->m_buildingStateData[buildingId] = bos;
|
||||
|
||||
const auto contaminations = bos.contaminationStates();
|
||||
|
||||
DEBUG_LOG(m_logger) << "Statecount " << contaminations.size();
|
||||
|
||||
// accessable by floorId:
|
||||
QSet<int> contaminatedFloors;
|
||||
for (const Buildings::ContaminationState &contaminationState : contaminations)
|
||||
{
|
||||
//we might get multiple contaminations so first make a Set of rooms:
|
||||
QSet<int> rooms;
|
||||
for (const auto &room : contaminationState.rooms())
|
||||
{
|
||||
rooms.insert(room);
|
||||
}
|
||||
//now check for floors
|
||||
DEBUG_LOG(m_logger) << "contaminated rooms " << rooms.size();
|
||||
|
||||
for (int room : rooms)
|
||||
{
|
||||
int floorIdContamination = findFloorIdByRoomId(room);
|
||||
if ( floorIdContamination == -1)
|
||||
continue;
|
||||
contaminatedFloors.insert(floorIdContamination);
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << "contaminated floors " << contaminatedFloors.size();
|
||||
|
||||
// qCritical() << "floor2Party" << floor2Party;
|
||||
|
||||
|
||||
// retrieve height of all floors:
|
||||
QMap<int, double> floorHeights = retrieveBuildingAbsHeight(buildingId);
|
||||
|
||||
|
||||
// create/update one Cube (MapObject) per floor:
|
||||
QMapIterator<int, double> mapIt(floorHeights);
|
||||
int floorCounter = 0;
|
||||
while (mapIt.hasNext())
|
||||
{
|
||||
mapIt.next();
|
||||
|
||||
// a) floorId
|
||||
const int floorId = mapIt.key();
|
||||
|
||||
// b) height
|
||||
const double height = mapIt.value();
|
||||
|
||||
// c) contamination:
|
||||
// set them to "false", if not existing:
|
||||
const bool isContaminaed = contaminatedFloors.contains(floorId);
|
||||
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION
|
||||
<< " floorId=" << floorId
|
||||
<< " height=" << height
|
||||
<< " partyId=" << isContaminaed;
|
||||
|
||||
|
||||
// retrieve geometry:
|
||||
const PositionCont &absPositionsGeo = retrieveBuildingGeometry(buildingId, ++floorCounter);
|
||||
|
||||
// cubes
|
||||
RefPointer<Cube> cube = d->getCreateCube(buildingId, floorId);
|
||||
|
||||
cube->setVisibility(d->m_visible);
|
||||
cube->setDrawOrder(d->m_drawOrder);
|
||||
cube->setPartyId(-1);
|
||||
|
||||
if(isContaminaed)
|
||||
{
|
||||
cube->setPartyId(-2);
|
||||
QColor col(Qt::yellow);
|
||||
cube->setForceMajorColor(col.name());
|
||||
}
|
||||
cube->setPositions(absPositionsGeo);
|
||||
cube->setHeight(height);
|
||||
|
||||
if (!cube->updateView())
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " cube->updateView() failed";
|
||||
|
||||
} // while
|
||||
|
||||
}
|
||||
|
||||
//void BuildingContamination::updateBuildingVisiblity(int buildingId)
|
||||
//{
|
||||
|
||||
//}
|
||||
|
||||
int BuildingContamination::findFloorIdByRoomId(int roomId) noexcept(false)
|
||||
{
|
||||
// get the floor by getting the parent of the room
|
||||
auto roomToFloorCache = m_roomToFloorCache.constFind(roomId); // try to find the floor in the cache first
|
||||
if (roomToFloorCache != m_roomToFloorCache.constEnd())
|
||||
{
|
||||
//qWarning() << ":) cache hit for room" << roomId;
|
||||
return roomToFloorCache.value();
|
||||
}
|
||||
|
||||
//qWarning() << ":( cache miss for room" << roomId;
|
||||
|
||||
InfrastructureManagement::StructureElement roomSe;
|
||||
if (!m_ismDtc->getStructureElementById(roomId, roomSe))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "getStructureElementById roomId=" << roomId << " not found";
|
||||
return -1;
|
||||
}
|
||||
|
||||
const std::vector<int32_t> path = roomSe.path();
|
||||
|
||||
for (const int parentSeId : path)
|
||||
{
|
||||
InfrastructureManagement::StructureElement parentSe;
|
||||
if (!getRoom(parentSeId, parentSe))
|
||||
continue;
|
||||
//qWarning() << "seId" << seId << "type" << structureElement2.structureElementTypeId().underlying();
|
||||
|
||||
if (parentSe.structureElementTypeId().underlying() != InfrastructureManagement::StructureElementType_def::Floor)
|
||||
continue;
|
||||
|
||||
// there can only be one floor per room (duh), so we can break after that and finally know the se id for the floor the participant is in
|
||||
|
||||
m_roomToFloorCache.insert(roomId, parentSeId);
|
||||
return parentSeId;
|
||||
}
|
||||
|
||||
throw QStringLiteral("findFloorId: floor id for room %1 not found").arg(roomSe.id());
|
||||
}
|
||||
|
||||
bool BuildingContamination::getRoom(int roomSeId, InfrastructureManagement::StructureElement &roomSe)
|
||||
{
|
||||
auto it = m_roomStructureElementCache.find(roomSeId);
|
||||
if (it != m_roomStructureElementCache.end())
|
||||
{
|
||||
//qWarning() << "getRoom: cache hit!";
|
||||
roomSe = *it;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m_ismDtc->getStructureElementById(roomSeId, roomSe))
|
||||
{
|
||||
//qWarning() << "getRoom: cache miss - adding to cache";
|
||||
m_roomStructureElementCache.insert(roomSeId, roomSe);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false; // not found :((((
|
||||
}
|
||||
|
||||
|
||||
PositionCont BuildingContamination::retrieveBuildingGeometry(int buildingId, int floorId) const
|
||||
{
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
|
||||
<< " buildingId=" << buildingId
|
||||
<< " floorId=" << floorId;
|
||||
if (!m_ismDtc)
|
||||
{
|
||||
ERROR_LOG(m_logger) << LOGFUNCTION << " no m_ismDtc";
|
||||
return PositionCont();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// retrieve relative points of footprint:
|
||||
//
|
||||
QVector<QPointF> relPositions;
|
||||
{
|
||||
const InfrastructureManagement::MainFootprint &mainFootprint = m_ismDtc->mainFootprint(buildingId);
|
||||
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " START"
|
||||
<< " mainFootprint.elements().size()=" << mainFootprint.elements().size();
|
||||
|
||||
relPositions.reserve(mainFootprint.elements().size());
|
||||
// sorted per definition
|
||||
for (const InfrastructureManagement::FootprintElement &element : mainFootprint.elements())
|
||||
{
|
||||
const auto &relPos = element.relPosition();
|
||||
relPositions += QPointF(relPos.offsetX(), relPos.offsetY());
|
||||
}
|
||||
}
|
||||
// DEBUG_LOG(m_logger) << "footprintOrg = " << relPositions;
|
||||
|
||||
//
|
||||
// expand the polyline depending on the floor:
|
||||
//
|
||||
|
||||
#ifndef USE_BUFFER_APPROACH
|
||||
// calculate the mass/center point of the outline/polygon:
|
||||
{
|
||||
// assume that there will be not more than 100 floors:
|
||||
const double distance = 0.5 + (100 - floorId) * 0.01;
|
||||
|
||||
const QPolygonF &massPoly = relPositions.toVector();
|
||||
const QPointF &massCenterPoint = massPoly.boundingRect().center();
|
||||
|
||||
// increase distance to massCenterPoint (depending on the quadrant)
|
||||
const double massCenterPointX = massCenterPoint.x();
|
||||
const double massCenterPointY = massCenterPoint.y();
|
||||
QMutableListIterator<QPointF> listIt(relPositions);
|
||||
while (listIt.hasNext())
|
||||
{
|
||||
QPointF &relPosition = listIt.next();
|
||||
// X
|
||||
if (relPosition.x() < massCenterPointX)
|
||||
relPosition.rx() -= distance;
|
||||
else
|
||||
relPosition.rx() += distance;
|
||||
|
||||
// Y
|
||||
if (relPosition.y() < massCenterPointY)
|
||||
relPosition.ry() -= distance;
|
||||
else
|
||||
relPosition.ry() += distance;
|
||||
} // for
|
||||
// DEBUG_LOG(m_logger) << "footprintBlown = " << relPositions;
|
||||
}
|
||||
#endif // USE_BUFFER_APPROACH
|
||||
|
||||
|
||||
//
|
||||
// translate to absolute
|
||||
//
|
||||
PositionCont absPositionsGeo;
|
||||
|
||||
const InfrastructureManagement::MainStructureElement &mse = m_ismDtc->mainStructureElement(buildingId);
|
||||
|
||||
const Core::GeoPosition &geoPosition = mse.geoPosition();
|
||||
const QPointF &referencePointGeo = QPointF(geoPosition.lon(), geoPosition.lat());
|
||||
const LtsCoordTrans::UtmCoordinate &referencePointUTM = LtsCoordTrans::UtmCoordinate::fromGeographic(referencePointGeo);
|
||||
const double angleRad = mse.angle() * LtsCoordTrans::deg2rad();
|
||||
|
||||
// add relPos to referencePoint:
|
||||
const QPointF center;
|
||||
absPositionsGeo.reserve(relPositions.size());
|
||||
for (const auto &relPosition : qAsConst(relPositions))
|
||||
{
|
||||
const QPointF &relPositionRotate = MathUtils::rotate(relPosition, center, angleRad); // rotate relPosition by angleRad around 0,0
|
||||
const QPointF &pGeo = referencePointUTM.geographic(relPositionRotate); // add relPosition to referencePointUTM
|
||||
absPositionsGeo.append(Point3D::fromQPointF(pGeo));
|
||||
} // for
|
||||
|
||||
// DEBUG_LOG(m_logger) << "absPositionsGeo = " << absPositionsGeo;
|
||||
|
||||
#ifdef USE_BUFFER_APPROACH
|
||||
{
|
||||
//
|
||||
// This works better for building for building with a shape like a 'H'...
|
||||
//
|
||||
|
||||
// assume that there will be not more than 100 floors:
|
||||
const double distance = (100 - floorId) * 0.01;
|
||||
|
||||
// create EsriGeometry:
|
||||
|
||||
Esri::ArcGISRuntime::PolygonBuilder polygonBuilder(Esri::ArcGISRuntime::SpatialReference::wgs84());
|
||||
constexpr double rad2deg = LtsCoordTrans::rad2deg();
|
||||
for (const Point3D &point : qAsConst(absPositionsGeo))
|
||||
polygonBuilder.addPoint(Esri::ArcGISRuntime::Point(point.x() * rad2deg,
|
||||
point.y() * rad2deg,
|
||||
point.z()));
|
||||
const Esri::ArcGISRuntime::Geometry &esriGeometry = polygonBuilder.toGeometry();
|
||||
|
||||
const Esri::ArcGISRuntime::Polygon &polyline =
|
||||
Esri::ArcGISRuntime::GeometryEngine::bufferGeodetic(esriGeometry,
|
||||
distance,
|
||||
Esri::ArcGISRuntime::LinearUnitId::Meters,
|
||||
0.1,
|
||||
Esri::ArcGISRuntime::GeodeticCurveType::Geodesic);
|
||||
|
||||
if (polyline.parts().isEmpty())
|
||||
return absPositionsGeo;
|
||||
|
||||
const Esri::ArcGISRuntime::ImmutablePart &immutablePart = polyline.parts().part(0);
|
||||
const Esri::ArcGISRuntime::ImmutablePointCollection &pointCollection = immutablePart.points();
|
||||
const int size = pointCollection.size();
|
||||
|
||||
INFO_LOG(m_logger) << " pointCollection.size = " << pointCollection.size()
|
||||
<< " - buildingId = " << buildingId
|
||||
<< ", mse.name = " << mse.name();
|
||||
|
||||
absPositionsGeo.clear();
|
||||
absPositionsGeo.reserve(size);
|
||||
|
||||
for (const Esri::ArcGISRuntime::Point &esriP : pointCollection)
|
||||
{
|
||||
absPositionsGeo.append(Point3D(esriP.x() * LtsCoordTrans::deg2rad(),
|
||||
esriP.y() * LtsCoordTrans::deg2rad(),
|
||||
esriP.z()));
|
||||
} // for;
|
||||
}
|
||||
#endif // USE_BUFFER_APPROACH
|
||||
|
||||
TRACE_LOG(m_logger) << LOGFUNCTION << " END";
|
||||
return absPositionsGeo;
|
||||
}
|
||||
|
||||
QMap<int, double> BuildingContamination::retrieveBuildingAbsHeight(int buildingId) const
|
||||
{
|
||||
QMap<int, double> floorHeights;
|
||||
|
||||
const InfrastructureManagement::MainStructureElement &mse = m_ismDtc->mainStructureElement(buildingId);
|
||||
|
||||
// move from dds to QVector:
|
||||
for (const InfrastructureManagement::StructureElement &element : mse.elements())
|
||||
{
|
||||
if (element.structureElementTypeId() != InfrastructureManagement::StructureElementType::Floor)
|
||||
continue;
|
||||
|
||||
const int floorId = element.id();
|
||||
|
||||
//
|
||||
// Cubes are using the UniqueValueRenderer of layer 'BuildingContamination'.
|
||||
// To reduce the dependency to the elevation source, choose
|
||||
// ExtrusionMode::AbsoluteHeight @ UniqueValueRenderer
|
||||
// Additionally, the top is flat (and not according base surface.)
|
||||
//
|
||||
// If UniqueValueRenderer uses: Esri::ArcGISRuntime::ExtrusionMode::AbsoluteHeight
|
||||
// ExtrusionMode::AbsoluteHeight has a flat top.
|
||||
double height = element.geoPosition().z();
|
||||
|
||||
// If UniqueValueRenderer uses: Esri::ArcGISRuntime::ExtrusionMode::BaseHeight
|
||||
// This is the only extrusion mode that doesn't have a flat top.
|
||||
// The extruded height, we need the relative,
|
||||
// double height = element.relPosition().offsetZ();
|
||||
floorHeights[floorId] = height;
|
||||
}
|
||||
|
||||
// this is the height of the bottom, not the ceiling
|
||||
// therefore we have take value of topwards neighboring floor:
|
||||
{
|
||||
QMutableMapIterator<int, double> mapIt(floorHeights);
|
||||
while (mapIt.hasNext())
|
||||
{
|
||||
QMap<int, double>::iterator curFloor = mapIt.next();
|
||||
if (mapIt.hasNext())
|
||||
{
|
||||
QMap<int, double>::iterator upperFloor = mapIt.peekNext(); // neighboring floor
|
||||
curFloor.value() = upperFloor.value();
|
||||
}
|
||||
else
|
||||
curFloor.value() += 2.0; // add default height of 2 [meter]
|
||||
}
|
||||
}
|
||||
|
||||
return floorHeights;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user