Files
qt-migration-legatus/qt6-after/qt6-migrated-legatus/Lts/Proxies/Buildings/BuildingControlUnit/VWM/vwm_building.cpp
T

924 lines
25 KiB
C++
Executable File

#include "vwm_building.h"
#include <utility>
#include "vwm_math.h"
#include <QSet>
#include <QVector>
#include <QLineF>
#include <settings.h>
#include <algorithm>
namespace BuildingControlUnit
{
namespace VWM
{
static NGL::INGLLogger &logger()
{
return BuildingControlUnit::getLogger("VWM.Building");
}
static inline bool isEffectNegligible(double effect)
{
return (effect < Settings::minimumRemainEffectThreshold());
}
static inline bool isEffectNegligible(double RW, double ZF, double TF)
{
return isEffectNegligible(ZF * RW * TF);
}
static inline double calcProtectionOfWallAfterHit(double SG_alt, double RW, double ZF, double TF)
{
const double SG_diff = ZF * RW * TF;
if (isEffectNegligible(SG_diff))
return SG_alt;
return std::max(0.0, SG_alt - SG_diff);
}
void WallExclusionZoneBase::setInitalProtection(double initialProtection, bool bResetProtection)
{
m_initialProtection = initialProtection;
if (bResetProtection)
m_protection = initialProtection;
}
void WallExclusionZoneBase::updateProtection(const double RW, const double ZF, const double TF)
{
const double SG_alt = m_protection;
const double SG_neu = calcProtectionOfWallAfterHit(SG_alt, RW, ZF, TF);
m_protection = SG_neu;
}
void Room::setFortifyFactor(double factorNew, bool bRecalcValues)
{
const double factorOld = m_fortifyFactor;
if (qFuzzyIsNull(factorOld) || qFuzzyIsNull(factorNew))
return;
m_fortifyFactor = factorNew;
if (bRecalcValues)
{
for (OuterWall &wall : m_outerWalls)
{
wall.setProtection(wall.protection() / factorOld * factorNew);
wall.setInitalProtection(wall.initialProtection() / factorOld * factorNew, false);
for (ExclusionZone &exZone : wall.exclusionZones())
{
exZone.setProtection(exZone.protection() / factorOld * factorNew);
exZone.setInitalProtection(exZone.initialProtection() / factorOld * factorNew, false);
}
}
}
}
double Room::damagePercent() const
{
if (m_outerWalls.isEmpty())
return 0;
double currentProtection = 0.0;
double initialProtection = 0.0;
for (const OuterWall &wall : std::as_const(m_outerWalls))
{
currentProtection += wall.protection();
initialProtection += wall.initialProtection();
for (const ExclusionZone &exZone : std::as_const(wall.exclusionZones()))
{
currentProtection += exZone.protection();
initialProtection += exZone.initialProtection();
}
}
if (qFuzzyIsNull(initialProtection))
return 100;
return (1.0 - currentProtection / initialProtection) * 100.0;
}
double Room::calcRemainingEffect(const HitPosition &hitPos, const Charge &ammu) const
{
const double SG_alt = protectionForHitPosition(hitPos);
const double ZF = ammu.destructiveFactor;
const double WF = ammu.penetrationEffect;
const double RW = calcRemainingEffect(SG_alt, ZF, WF);
return RW;
}
void Room::updateProtectionDirectHit(const HitPosition &hitPos, const Charge &ammu)
{
Q_ASSERT(hitPos.state != HitPosition::State::NoHit);
const double SG_alt = protectionForHitPosition(hitPos);
const double ZF = ammu.destructiveFactor;
const double SG_neu = calcProtectionOfWallAfterHit(SG_alt, 1.0, ZF, 1.0);
setProtectionForHitPosition(hitPos, SG_neu);
}
static bool isDirectHitOuterWall(const HitPosition &hitPos, int roomId, int idxOw)
{
if (hitPos.state != HitPosition::State::OuterWall)
return false;
return hitPos.roomId == roomId && hitPos.outerWallIdx == idxOw;
}
static bool isDirectHitExlusionZone(const HitPosition &hitPos, int roomId, int idxOw, int idxEz)
{
if (hitPos.state != HitPosition::State::ExclusionZone)
return false;
return hitPos.roomId == roomId && hitPos.outerWallIdx == idxOw && hitPos.exclusionZoneIdx == idxEz;
}
void Room::updateProtectionIndirectHit(const HitPosition &hitPos, const Charge &ammu, double remainingEffect)
{
updateProtectionNeighbourHit(hitPos, ammu, remainingEffect, 1.0);
}
bool Room::updateProtectionNeighbourHit(const HitPosition &hitPos, const Charge &ammu, double remainingEffect, double transitionFactor)
{
const double ZF = ammu.destructiveFactor;
const double RW = remainingEffect;
const double TF = transitionFactor;
DEBUG_LOG(logger()) << "Effect for room " << m_id
<< " (RW="<< RW << ", ZF=" << ZF << " , TF=" << TF << ") ; effect=" << RW*ZF*TF
<< " -> damagePercent VOR= " << this->damagePercent();
if (isEffectNegligible(RW, ZF, TF))
{
DEBUG_LOG(logger()) << "Effect is Negligible for room " << m_id;
for (int idxOw = 0; idxOw < m_outerWalls.size(); ++idxOw)
{
OuterWall &ow = m_outerWalls[idxOw];
DEBUG_LOG(logger()) << "room " << m_id << "[ow=" << idxOw
<< "] new protection = " << ow.protection()
<< " (" << ow.protectionPercent() << "%)";
}
return false;
}
const char *hitReason = (hitPos.roomId == m_id ? "indirect hit" : "neighbour hit");
for (int idxOw = 0; idxOw < m_outerWalls.size(); ++idxOw)
{
OuterWall &ow = m_outerWalls[idxOw];
if (!isDirectHitOuterWall(hitPos, m_id, idxOw))
{
ow.updateProtection(RW, ZF, TF);
DEBUG_LOG(logger()) << "room " << m_id << "[ow=" << idxOw
<< "] new protection = " << ow.protection()
<< " (" << ow.protectionPercent() << "%) - " << hitReason;
}
for (int idxEz = 0; idxEz < ow.exclusionZones().size(); ++idxEz)
{
if (!isDirectHitExlusionZone(hitPos, m_id, idxOw, idxEz))
{
ExclusionZone &ez = ow.exclusionZones()[idxEz];
ez.updateProtection(RW, ZF, TF);
DEBUG_LOG(logger()) << "room " << m_id << "[ow=" << idxOw
<< "][ez=" << idxEz
<< "] new protection = " << ez.protection()
<< " (" << ez.protectionPercent() << "%) - " << hitReason;
}
}
}
DEBUG_LOG(logger()) << "Effect for room " << m_id << " -> damagePercent NACH = " << this->damagePercent();
return true;
}
double Room::protectionForHitPosition(const HitPosition &hitPos) const
{
const OuterWall &ow = m_outerWalls.at(hitPos.outerWallIdx);
if (hitPos.state == HitPosition::State::OuterWall)
return ow.protection();
return ow.exclusionZones().at(hitPos.exclusionZoneIdx).protection();
}
void Room::setProtectionForHitPosition(const HitPosition &hitPos, double SG_neu)
{
Q_ASSERT(hitPos.state != HitPosition::State::NoHit);
OuterWall &ow = m_outerWalls[hitPos.outerWallIdx];
if (hitPos.state == HitPosition::State::OuterWall)
{
ow.setProtection(SG_neu);
DEBUG_LOG(logger()) << "room " << m_id << "[ow=" << hitPos.outerWallIdx
<< "] new protection = " << ow.protection()
<< " (" << ow.protectionPercent() << "%)"
<< " - direct hit";
}
else
{
ExclusionZone &ez = ow.exclusionZones()[hitPos.exclusionZoneIdx];
ez.setProtection(SG_neu);
DEBUG_LOG(logger()) << "room " << m_id << "[ow=" << hitPos.outerWallIdx
<< "][ez=" << hitPos.exclusionZoneIdx
<< "] new protection = " << ez.protection()
<< " (" << ez.protectionPercent() << "%)"
<< " - direct hit";
}
}
double Room::calcRemainingEffect(double SG_alt, double ZF, double WF)
{
if (SG_alt < 0.0001)
return 1.0;
if (ZF < 0.0001)
return 0;
double D_Wand = 0.0;
if (SG_alt < ZF * 0.95)
D_Wand = ZF * 0.95 - SG_alt;
const double D_Zufall = ZF * WF * 0.05 / SG_alt;
double RW = 100.0 * (D_Wand + D_Zufall) / ZF;
if (RW > 1.0)
RW = 1.0;
return RW;
}
Building::Building()
: m_lastHitPosition(HitPosition())
, m_logger(BuildingControlUnit::getLogger("VWM.Building"))
{}
int Building::checkPolygons()
{
int numberOfDuplicates = 0;
for (const Room &room : std::as_const(m_rooms))
{
for (int owIdx = 0; owIdx < room.outerWalls().size(); ++owIdx)
{
const OuterWall &ow = room.outerWalls().at(owIdx);
for (int elemIdx = 0; elemIdx < ow.elements().size(); ++elemIdx)
{
const WallElement &wallElement = ow.elements().at(elemIdx);
numberOfDuplicates += checkDublicatePointsInPolygon(room.id(), owIdx, elemIdx, "QuterWall", wallElement);
}
}
}
return numberOfDuplicates;
}
int Building::cleanupPolygons()
{
int numberOfRemoved = 0;
for (Room &room : m_rooms)
{
for (int owIdx = 0; owIdx < room.outerWalls().size(); ++owIdx)
{
OuterWall &ow = room.outerWalls()[owIdx];
for (int elemIdx = 0; elemIdx < ow.elements().size(); ++elemIdx)
{
WallElement &wallElement = ow.elements()[elemIdx];
numberOfRemoved += cleanupDublicatePointsInPolygon(room.id(), owIdx, elemIdx, "room", wallElement);
bool bMakePlanarDone = false;
MakePlanar makePlanar(wallElement);
QVector<LtsUtils::QPoint3D> candidate = makePlanar.calculate(&bMakePlanarDone);
cleanupDublicatePointsInPolygon(room.id(), owIdx, elemIdx, "room", candidate);
if (candidate.size() < 4)
{
NOTICE_LOG(m_logger) << "wall was made planar: Building '" << m_name << "' -> "
<< " in room " << room.id() << " OuterWall[" << owIdx
<< "], element[" << elemIdx << "] "
<< " makePlanar and cleanupDublicatePointsInPolygon would generate short polygon, size=" << candidate.size();
for (auto point : std::as_const(candidate))
NOTICE_LOG(m_logger) << " point= " << point;
bMakePlanarDone = false;
} else {
wallElement = candidate;
}
if (bMakePlanarDone)
NOTICE_LOG(m_logger) << "wall was made planar: Building '" << m_name << "' -> "
<< " in room " << room.id() << " OuterWall[" << owIdx
<< "], element[" << elemIdx << "] "
<< " smallestDim=" << (int)makePlanar.getSmallestDim()
<< " smallestRange=" << makePlanar.getSmallestRange();
}
}
}
return numberOfRemoved;
}
int Building::cleanupDublicatePointsInPolygon(int roomId, int idx, int subIdx, const char *type, QVector<LtsUtils::QPoint3D> &points) const
{
QVector<int> idxToRemove;
idxToRemove.reserve(points.size());
for (int i = 0; i < points.size(); ++i)
{
const auto &p1 = points.at(i);
for (int j = i + 1; j < points.size(); ++j)
{
auto p2 = points.at(j);
if (qFuzzyCompare(p1, p2))
{
DEBUG_LOG(m_logger) << "Building '" << m_name << "' -> "
<< "Polygon point " << i << " (" << p1 << ") and " << j << " (" << p2
<< ") in room " << roomId << ", " << type << "[" << idx
<< "], element[" << subIdx << "] are the same! -> REMOVE";
if (!idxToRemove.contains(j))
idxToRemove.push_back(j);
}
}
}
std::sort(idxToRemove.begin(), idxToRemove.end(), std::greater<int>());
int numberOfRemoved = idxToRemove.size();
for (auto idxRemove : idxToRemove)
points.removeAt(idxRemove);
return numberOfRemoved;
}
Room Building::room(int roomId)
{
auto it = m_rooms.find(roomId);
if (it == m_rooms.end())
return {};
return *it;
}
int Building::damagePercent() const
{
double roomDamagePercent = 0.0;
for (const Room &room : m_rooms)
roomDamagePercent += room.damagePercent();
return qRound(roomDamagePercent / m_rooms.size());
}
QVector<HitRoom> Building::roomStates() const
{
QVector<HitRoom> ret;
ret.reserve(m_rooms.size() / 2);
for (const Room &room : m_rooms)
{
const int dmgPercent = qRound(room.damagePercent());
HitRoom hr;
hr.roomId = room.id();
hr.damagePercent = dmgPercent;
hr.remainingEffectPercent = qRound(room.remainingEffect() * 100);
hr.fortifyFactor = room.fortifyFactor();
hr.directHit = room.isDirectHit();
ret += hr;
DEBUG_LOG(m_logger) << "HitRoom " << hr.roomId
<< " damage: " << hr.damagePercent
<< "%, remainEffect: " << hr.remainingEffectPercent << "%"
<< ", remainingEffectChargeTypeId: " << hr.remainingEffectChargeTypeId << "%"
<< ", fortifyFactor: " << hr.fortifyFactor
<< ", isDirectHit:" << room.isDirectHit();
}
return ret;
}
DamageState Building::damageState() const
{
if (Building::damagePercent() >= Settings::killThreshold())
return DamageState::Destroyed;
return DamageState::NoDamage;
}
void Building::init()
{
for (Room &room : m_rooms)
initRoom(room);
}
void Building::destroyAllRooms()
{
for (Room &room : m_rooms)
destroyRoom(room);
}
void Building::setRoomState(DamageState damageState, const QVector<int> &afffectedRooms)
{
for (const int roomId : afffectedRooms)
{
auto it = m_rooms.find(roomId);
if (it == m_rooms.end())
{
WARNING_LOG(m_logger) << "Could not find room with id " << roomId;
continue;
}
if (damageState == DamageState::Destroyed)
destroyRoom(it.value());
else
initRoom(it.value());
}
}
void Building::setFortifyInfo(const QVector<FortifyInfo> &foritfyInfos)
{
for (const FortifyInfo &info : foritfyInfos)
{
auto it = m_rooms.find(info.roomId);
if (it == m_rooms.end())
{
WARNING_LOG(m_logger) << "Could not find room with id " << info.roomId;
continue;
}
Room &room = it.value();
room.setFortifyFactor(info.fortifyFactor);
}
}
void Building::initRoom(Room &room) const
{
const double BGPL = m_buildingProtectionLevel;
const double OWPL = m_outerWallProtectionLevel;
const double EZPL = m_exclusionZoneProtectionLevel;
room.setRemainingEffect(0);
room.setDirectHit(false);
const double fortifyFactor = room.fortifyFactor();
if (room.outerWalls().isEmpty())
{
room.outerWalls() += OuterWall();
}
for (OuterWall &ow : room.outerWalls())
{
if (ow.isDummyWall())
{
ow.setInitalProtection(250 * fortifyFactor, true);
}
else
{
const double OWPF = ow.protectiveFactor();
const double SG_0_Wall = BGPL * OWPL * OWPF * fortifyFactor;
ow.setInitalProtection(SG_0_Wall, true);
for (ExclusionZone &ez : ow.exclusionZones())
{
const double EZPF = ez.protectiveFactor();
const double SG_0_EZ = BGPL * EZPL * EZPF * fortifyFactor;
ez.setInitalProtection(SG_0_EZ, true);
}
}
}
}
void Building::destroyRoom(Room &room)
{
room.setRemainingEffect(1);
for (OuterWall &ow : room.outerWalls())
{
ow.setProtection(0);
for (ExclusionZone &ez : ow.exclusionZones())
ez.setProtection(0);
}
}
bool Building::hit(const LtsUtils::QPoint3D &pos, const LtsUtils::QPoint3D &dir, Charge charge, HitPosition *preCalculatedHitPosition)
{
for (Room &room : m_rooms)
room.setDirectHit(false);
if (preCalculatedHitPosition)
{
m_lastHitPosition = *preCalculatedHitPosition;
} else {
m_lastHitPosition = Math::getHitPosition(pos, dir, m_rooms);
}
const bool bBelowGround = isLastHitPositionBelowGroundHack();
if (bBelowGround)
{
INFO_LOG(m_logger) << " XXXX CES belowGround, reduce charge: " << charge;
charge.destructiveFactor *= 0.25;
charge.penetrationEffect *= 0.25;
INFO_LOG(m_logger) << " XXXX CES belowGround, reduce charge: " << charge;
}
INFO_LOG(m_logger) << "XXXXX HitPosition: state=" << m_lastHitPosition.state
<< ", m_name=" << m_name
<< ", m_modelId=" << m_modelId
<< ", roomId=" << m_lastHitPosition.roomId
<< ", outerWallIndex=" << m_lastHitPosition.outerWallIdx
<< ", exclusionZoneIndex=" << m_lastHitPosition.exclusionZoneIdx
<< ", bBelowGround=" << bBelowGround;
if (m_lastHitPosition.state == HitPosition::State::NoHit)
return false;
Room &hitRoom = m_rooms[m_lastHitPosition.roomId];
if (!hitRoom.isValid())
{
ERROR_LOG(m_logger) << "Internal error in hit calculation - could not find room with id " << m_lastHitPosition.roomId;
return false;
}
hitRoom.setDirectHit(true);
for (Room &room : m_rooms)
room.setRemainingEffect(0);
const double remainingEffect = hitRoom.calcRemainingEffect(m_lastHitPosition, charge);
hitRoom.setRemainingEffect(remainingEffect);
hitRoom.updateProtectionDirectHit(m_lastHitPosition, charge);
hitRoom.updateProtectionIndirectHit(m_lastHitPosition, charge, remainingEffect);
const QMap<int, NeighbourRoom> &neighbours = hitRoom.neighbours();
QMap<int, NeighboursToCheck> neighboursToCheck;
QSet<int> currentGradeNeighbours;
for (const NeighbourRoom &neighbour : neighbours)
{
neighboursToCheck.insert(neighbour.id(), NeighboursToCheck(neighbour, hitRoom.remainingEffect()));
currentGradeNeighbours.insert(neighbour.id());
}
QSet<int> lowerGradeNeighbours;
lowerGradeNeighbours.insert(hitRoom.id());
auto ret = checkHitNeighbours(neighboursToCheck, charge, currentGradeNeighbours, lowerGradeNeighbours);
while (!ret.isEmpty())
{
ret = checkHitNeighbours(ret, charge, currentGradeNeighbours, lowerGradeNeighbours);
}
return true;
}
bool Building::isLastHitPositionBelowGroundHack() const
{
return
(m_name.contains(QStringLiteral("BN_Kanaele"))) ||
(m_name.contains(QStringLiteral("U_Bahn")) && m_lastHitPosition.roomId < 2300)
;
}
QMap<int, Building::NeighboursToCheck> Building::checkHitNeighbours(const QMap<int, NeighboursToCheck> &neighbours,
const Charge &charge,
QSet<int> &currentGradeNeighbours,
QSet<int> &lowerGradeNeighbours)
{
QMap<int, NeighboursToCheck> neighboursToCheck;
QSet<int> newCurrentGradeNeighbours;
for (const NeighboursToCheck &neighbourRoom : neighbours)
{
const int neighbourRoomId = neighbourRoom.room.id();
if (lowerGradeNeighbours.contains(neighbourRoomId))
continue;
auto itRoom = m_rooms.find(neighbourRoomId);
if (itRoom == m_rooms.end())
{
WARNING_LOG(m_logger) << "Could not find room with id " << neighbourRoomId;
continue;
}
Room &neighbour = itRoom.value();
double TF = Settings::transitionMultiplier() * neighbourRoom.room.transitionFactor();
if (TF > 1.0)
TF = 1.0;
if (!neighbour.updateProtectionNeighbourHit(m_lastHitPosition, charge, neighbourRoom.remainEffect, TF))
continue;
const double oldRe = neighbour.remainingEffect();
neighbour.setRemainingEffect(neighbourRoom.remainEffect * TF);
DEBUG_LOG(m_logger) << "room " << neighbourRoomId << " remaining effect old: "
<< oldRe << " -> new: " << neighbour.remainingEffect();
for (const NeighbourRoom &grade2Neighbour : std::as_const(neighbour.neighbours()))
{
if (lowerGradeNeighbours.contains(grade2Neighbour.id()) ||
currentGradeNeighbours.contains(grade2Neighbour.id()))
continue;
auto it = neighboursToCheck.find(grade2Neighbour.id());
if (it == neighboursToCheck.end())
{
neighboursToCheck.insert(grade2Neighbour.id(), NeighboursToCheck(grade2Neighbour, neighbour.remainingEffect()));
} else {
const NeighboursToCheck &curEntry = it.value();
if (neighbour.remainingEffect() > curEntry.remainEffect)
neighboursToCheck.insert(grade2Neighbour.id(), NeighboursToCheck(grade2Neighbour, neighbour.remainingEffect()));
}
newCurrentGradeNeighbours.insert(grade2Neighbour.id());
}
}
lowerGradeNeighbours += currentGradeNeighbours;
currentGradeNeighbours = newCurrentGradeNeighbours;
return neighboursToCheck;
}
QString Building::buildingProperties() const
{
return m_buildingProperties;
}
void Building::setBuildingProperties(const QString &buildingProperties)
{
m_buildingProperties = buildingProperties;
}
QString Building::segmentProperties(const QString &hostname) const
{
return m_segmentProperties.value(hostname);
}
void Building::setSegmentProperties(const QString &hostname, const QString &properties)
{
m_segmentProperties.insert(hostname, properties);
}
int Building::checkDublicatePointsInPolygon(int roomId, int idx, int subIdx, const char *type,
const QVector<LtsUtils::QPoint3D> &points) const
{
int numberOfDuplicates = 0;
for (int i = 0; i < points.size(); ++i)
{
const auto &p1 = points.at(i);
for (int j = i + 1; j < points.size(); ++j)
{
const auto &p2 = points.at(j);
if (qFuzzyCompare(p1, p2))
{
++numberOfDuplicates;
WARNING_LOG(m_logger) << "Building '" << m_name << "' -> "
<< "Polygon point " << i << " (" << p1 << ") and " << j << " (" << p2
<< ") in room " << roomId << ", " << type << "[" << idx
<< "], element[" << subIdx << "] are the same! (size=" << points.size() << ")";
}
}
}
if (numberOfDuplicates > 0)
for (auto point : points)
WARNING_LOG(m_logger) << "Building '" << m_name << "' -> " << "point =" << point << " (same points)";
return numberOfDuplicates;
}
QString Building::toString(const QVector<Building::NeighboursToCheck> &cont)
{
QString str;
for (auto item : cont)
str += QString(QStringLiteral("%1;")).arg(item.room.id());
return str;
}
QString Building::toString(const QMap<int, Building::NeighboursToCheck> &cont)
{
QString str;
for (auto item : cont)
str += QString(QStringLiteral("%1;")).arg(item.room.id());
return str;
}
QString Building::toString(const QSet<int> &cont)
{
QString str;
for (auto item : cont)
str += QString(QStringLiteral("%1;")).arg(item);
return str;
}
MakePlanar::MakePlanar(const QVector<LtsUtils::QPoint3D> &poly)
: m_poly(poly)
{
ranges.resize(3);
}
QVector<LtsUtils::QPoint3D> MakePlanar::calculate(bool *bMakePlanarDone)
{
if (ratioOfSmallestAndBiggestDimension() >= 10.0
&& getRange(m_smallestDim).range() < 0.20
)
{
makePlanar();
if (bMakePlanarDone)
{
*bMakePlanarDone = true;
}
}
return m_poly;
}
double MakePlanar::ratioOfSmallestAndBiggestDimension()
{
if (m_poly.size() < 4)
return -1;
MyRange &rangeX = ranges[static_cast<int>(DIMENSION::X)];
MyRange &rangeY = ranges[static_cast<int>(DIMENSION::Y)];
MyRange &rangeZ = ranges[static_cast<int>(DIMENSION::Z)];
rangeX.min = m_poly.first().x(); rangeX.max = m_poly.first().x();
rangeY.min = m_poly.first().y(); rangeY.max = m_poly.first().y();
rangeZ.min = m_poly.first().z(); rangeZ.max = m_poly.first().z();
for (const LtsUtils::QPoint3D &pnt : std::as_const(m_poly))
{
rangeX.min = std::min(rangeX.min, pnt.x());
rangeX.max = std::max(rangeX.max, pnt.x());
rangeY.min = std::min(rangeY.min, pnt.y());
rangeY.max = std::max(rangeY.max, pnt.y());
rangeZ.min = std::min(rangeZ.min, pnt.z());
rangeZ.max = std::max(rangeZ.max, pnt.z());
}
if (rangeY.range() < rangeX.range())
m_smallestDim = DIMENSION::Y;
if (rangeZ.range() < getRange(m_smallestDim).range())
m_smallestDim = DIMENSION::Z;
if (rangeY.range() > rangeX.range())
m_biggistDim = DIMENSION::Y;
if (rangeZ.range() > getRange(m_biggistDim).range())
m_biggistDim = DIMENSION::Z;
if (!qFuzzyIsNull(getRange(m_smallestDim).range()))
m_ratio = getRange(m_biggistDim).range() / getRange(m_smallestDim).range();
return m_ratio;
}
void MakePlanar::makePlanar()
{
const double newValue = (getRange(m_smallestDim).min + getRange(m_smallestDim).max) / 2.0;
switch (m_smallestDim)
{
case DIMENSION::X:
for (LtsUtils::QPoint3D &pnt_ref : m_poly)
pnt_ref.rx() = newValue;
break;
case DIMENSION::Y:
for (LtsUtils::QPoint3D &pnt_ref : m_poly)
pnt_ref.ry() = newValue;
break;
case DIMENSION::Z:
for (LtsUtils::QPoint3D &pnt_ref : m_poly)
pnt_ref.rz() = newValue;
break;
case DIMENSION::Undefined:
{
}
}
}
void wallElementToBottomLeftTopRight3D(const WallElement &wallElement,
LtsUtils::QPoint3D &bottomLeftOut,
LtsUtils::QPoint3D &topRightOut)
{
const LtsUtils::QPoint3D &frontItem = wallElement.front();
bottomLeftOut = frontItem;
topRightOut = frontItem;
for (auto coord : std::as_const(wallElement))
{
if (coord.x() < bottomLeftOut.x())
bottomLeftOut.setX(coord.x());
if (coord.y() < bottomLeftOut.y())
bottomLeftOut.setY(coord.y());
if (coord.z() < bottomLeftOut.z())
bottomLeftOut.setZ(coord.z());
if (coord.x() > topRightOut.x())
topRightOut.setX(coord.x());
if (coord.y() > topRightOut.y())
topRightOut.setY(coord.y());
if (coord.z() > topRightOut.z())
topRightOut.setZ(coord.z());
}
}
LtsUtils::QPoint3D centerOfWallElement3D(const WallElement &wallElement)
{
LtsUtils::QPoint3D bottomLeftOut, topRightOut;
wallElementToBottomLeftTopRight3D(wallElement, bottomLeftOut, topRightOut);
const LtsUtils::QPoint3D &center = (bottomLeftOut + topRightOut) / 2;
return center;
}
}
}