diff --git a/CMakeLists.txt b/CMakeLists.txt index 898a692..ab61e71 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,6 +81,7 @@ SET(SOURCE src/behave/randfuel.cpp src/behave/randthread.cpp src/behave/safety.cpp + src/behave/safeSeparationDistanceCalculator.cpp src/behave/slopeTool.cpp src/behave/species_master_table.cpp src/behave/spot.cpp @@ -122,6 +123,7 @@ SET(HEADERS src/behave/randfuel.h src/behave/randthread.h src/behave/safety.h + src/behave/safeSeparationDistanceCalculator.h src/behave/slopeTool.h src/behave/species_master_table.h src/behave/spot.h diff --git a/src/behave/safeSeparationDistanceCalculator.cpp b/src/behave/safeSeparationDistanceCalculator.cpp new file mode 100644 index 0000000..f3b6001 --- /dev/null +++ b/src/behave/safeSeparationDistanceCalculator.cpp @@ -0,0 +1,172 @@ +#include "safeSeparationDistanceCalculator.h" + +const std::unordered_map, double, TupleHash> SafeSeparationDistanceCalculator::deltaLookup = { + {{SpeedClass::Light, BurningCondition::Low, SlopeClass::Flat}, 1.0}, + {{SpeedClass::Light, BurningCondition::Low, SlopeClass::Moderate}, 1.0}, + {{SpeedClass::Light, BurningCondition::Low, SlopeClass::Steep}, 2.0}, + + // Moderate Burning Conditions + {{SpeedClass::Light, BurningCondition::Moderate, SlopeClass::Flat}, 1.0}, + {{SpeedClass::Light, BurningCondition::Moderate, SlopeClass::Moderate}, 1.0}, + {{SpeedClass::Light, BurningCondition::Moderate, SlopeClass::Steep}, 2.0}, + + // Extreme Burning Conditions + {{SpeedClass::Light, BurningCondition::Extreme, SlopeClass::Flat}, 1.0}, + {{SpeedClass::Light, BurningCondition::Extreme, SlopeClass::Moderate}, 2.0}, + {{SpeedClass::Light, BurningCondition::Extreme, SlopeClass::Steep}, 3.0}, + + /// Moderate Wind Speed + // Light Burning Conditions + {{SpeedClass::Moderate, BurningCondition::Low, SlopeClass::Flat}, 1.5}, + {{SpeedClass::Moderate, BurningCondition::Low, SlopeClass::Moderate}, 3.0}, + {{SpeedClass::Moderate, BurningCondition::Low, SlopeClass::Steep}, 4.0}, + + // Moderate Burning Conditions + {{SpeedClass::Moderate, BurningCondition::Moderate, SlopeClass::Flat}, 2.0}, + {{SpeedClass::Moderate, BurningCondition::Moderate, SlopeClass::Moderate}, 4.0}, + {{SpeedClass::Moderate, BurningCondition::Moderate, SlopeClass::Steep}, 5.0}, + + // Extreme Burning Conditions + {{SpeedClass::Moderate, BurningCondition::Extreme, SlopeClass::Flat}, 2.5}, + {{SpeedClass::Moderate, BurningCondition::Extreme, SlopeClass::Moderate}, 5.0}, + {{SpeedClass::Moderate, BurningCondition::Extreme, SlopeClass::Steep}, 5.0}, + + /// High Wind Speed + {{SpeedClass::High, BurningCondition::Low, SlopeClass::Flat}, 3.0}, + {{SpeedClass::High, BurningCondition::Low, SlopeClass::Moderate}, 4.0}, + {{SpeedClass::High, BurningCondition::Low, SlopeClass::Steep}, 6.0}, + + // Moderate Burning Conditions + {{SpeedClass::High, BurningCondition::Moderate, SlopeClass::Flat}, 3.0}, + {{SpeedClass::High, BurningCondition::Moderate, SlopeClass::Moderate}, 5.0}, + {{SpeedClass::High, BurningCondition::Moderate, SlopeClass::Steep}, 7.0}, + + // Extreme Burning Conditions + {{SpeedClass::High, BurningCondition::Extreme, SlopeClass::Flat}, 4.0}, + {{SpeedClass::High, BurningCondition::Extreme, SlopeClass::Moderate}, 5.0}, + {{SpeedClass::High, BurningCondition::Extreme, SlopeClass::Steep}, 10.0}, +}; + +SafeSeparationDistanceCalculator::SafeSeparationDistanceCalculator() +{ + burningCondition_ = BurningCondition::Low; + slopeClass_ = SlopeClass::Flat; + speedClass_ = SpeedClass::Light; + vegetationHeight_ = 0.0; + safeSeparationDistance_ = 0.0; + safetyZoneSize_ = 0.0; +} + +SafeSeparationDistanceCalculator::~SafeSeparationDistanceCalculator() { +} + +SafeSeparationDistanceCalculator::SafeSeparationDistanceCalculator(const SafeSeparationDistanceCalculator& rhs) +{ + memberwiseCopyAssignment(rhs); +} + +SafeSeparationDistanceCalculator& SafeSeparationDistanceCalculator::operator=(const SafeSeparationDistanceCalculator& rhs) +{ + if (this != &rhs) + { + memberwiseCopyAssignment(rhs); + } + return *this; +} + +// Calculate + +void SafeSeparationDistanceCalculator::calculate() { + double vegetationHeight = LengthUnits::fromBaseUnits(vegetationHeight_, LengthUnits::Feet); + + double delta = SafeSeparationDistanceCalculator::getValue(speedClass_, burningCondition_, slopeClass_); + + // Perform calculation using delta + double safeSeparationDistance = 8.0 * vegetationHeight * delta; + double safetyZoneSize = M_PI * pow(safeSeparationDistance, 2.0); + + safeSeparationDistance_ = LengthUnits::toBaseUnits(safeSeparationDistance, LengthUnits::Feet); + safetyZoneSize_ = AreaUnits::toBaseUnits(safetyZoneSize, AreaUnits::Acres); +} + +// Getters +BurningCondition::BurningConditionEnum SafeSeparationDistanceCalculator::getBurningCondition() { + return burningCondition_; +} + +SlopeClass::SlopeClassEnum SafeSeparationDistanceCalculator::getSlopeClass() { + return slopeClass_; +} + +SpeedClass::SpeedClassEnum SafeSeparationDistanceCalculator::getSpeedClass() { + return speedClass_; +} + +SafetyCondition::SafetyConditionEnum SafeSeparationDistanceCalculator::getSafetyCondition() { + if (slopeClass_ == SlopeClass::Flat) { + if (speedClass_ == SpeedClass::High) { + return SafetyCondition::Moderate; + } else { + return SafetyCondition::Low; + } + } else if (slopeClass_ == SlopeClass::Moderate) { + if (speedClass_ == SpeedClass::Light) { + return SafetyCondition::Low; + } else if (speedClass_ == SpeedClass::Moderate) { + return SafetyCondition::Moderate; + } else { + return SafetyCondition::Extreme; + } + } else /* Steep Slope */ { + if (speedClass_ == SpeedClass::Light) { + if (burningCondition_ == BurningCondition::Extreme) { + return SafetyCondition::Moderate; + } else { + return SafetyCondition::Low; + } + } else if (speedClass_ == SpeedClass::Moderate) { + return SafetyCondition::Moderate; + } else { + return SafetyCondition::Extreme; + } + } +} + +double SafeSeparationDistanceCalculator::getVegetationHeight(LengthUnits::LengthUnitsEnum lengthUnits) { + return LengthUnits::fromBaseUnits(vegetationHeight_, lengthUnits); +} + +double SafeSeparationDistanceCalculator::getSafeSeparationDistance(LengthUnits::LengthUnitsEnum lengthUnits) { + return LengthUnits::fromBaseUnits(safeSeparationDistance_, lengthUnits); +} + +double SafeSeparationDistanceCalculator::getSafetyZoneSize(AreaUnits::AreaUnitsEnum areaUnits) { + return AreaUnits::fromBaseUnits(safetyZoneSize_, areaUnits); +} + +// Setters +void SafeSeparationDistanceCalculator::setBurningCondition(BurningCondition::BurningConditionEnum condition) { + burningCondition_ = condition; +} + +void SafeSeparationDistanceCalculator::setSlopeClass(SlopeClass::SlopeClassEnum slope) { + slopeClass_ = slope; +} + +void SafeSeparationDistanceCalculator::setSpeedClass(SpeedClass::SpeedClassEnum speed) { + speedClass_ = speed; +} + +void SafeSeparationDistanceCalculator::setVegetationHeight(double vegetationHeight, LengthUnits::LengthUnitsEnum lengthUnits) { + vegetationHeight_ = LengthUnits::toBaseUnits(vegetationHeight, lengthUnits); +} + +void SafeSeparationDistanceCalculator::memberwiseCopyAssignment(const SafeSeparationDistanceCalculator& rhs) +{ + burningCondition_ = rhs.burningCondition_; + slopeClass_ = rhs.slopeClass_; + speedClass_ = rhs.speedClass_; + vegetationHeight_ = rhs.vegetationHeight_; + safeSeparationDistance_ = rhs.safeSeparationDistance_; + safetyZoneSize_ = rhs.safetyZoneSize_; +} diff --git a/src/behave/safeSeparationDistanceCalculator.h b/src/behave/safeSeparationDistanceCalculator.h new file mode 100644 index 0000000..166a6ec --- /dev/null +++ b/src/behave/safeSeparationDistanceCalculator.h @@ -0,0 +1,93 @@ +#pragma once +#include +#include +#include +#include "behaveUnits.h" + +struct BurningCondition { + enum BurningConditionEnum { + Low, + Moderate, + Extreme + }; +}; + +struct SlopeClass { + enum SlopeClassEnum { + Flat, + Moderate, + Steep + }; +}; + +struct SpeedClass { + enum SpeedClassEnum { + Light, + Moderate, + High + }; +}; + +struct SafetyCondition { + enum SafetyConditionEnum { + Low, + Moderate, + Extreme + }; +}; + +struct TupleHash { + template + std::size_t operator()(const std::tuple& t) const { + auto hash1 = std::hash{}(std::get<0>(t)); + auto hash2 = std::hash{}(std::get<1>(t)); + auto hash3 = std::hash{}(std::get<2>(t)); + return hash1 ^ (hash2 << 1) ^ (hash3 << 2); // Combine the hash values + } +}; + +class SafeSeparationDistanceCalculator { +public: + SafeSeparationDistanceCalculator(); + ~SafeSeparationDistanceCalculator(); + SafeSeparationDistanceCalculator(const SafeSeparationDistanceCalculator& rhs); + SafeSeparationDistanceCalculator& operator=(const SafeSeparationDistanceCalculator& rhs); + + // calculate + void calculate(); + + // Getters + BurningCondition::BurningConditionEnum getBurningCondition(); + SlopeClass::SlopeClassEnum getSlopeClass(); + SpeedClass::SpeedClassEnum getSpeedClass(); + SafetyCondition::SafetyConditionEnum getSafetyCondition(); + double getVegetationHeight(LengthUnits::LengthUnitsEnum lengthUnits); + double getSafeSeparationDistance(LengthUnits::LengthUnitsEnum lengthUnits); + double getSafetyZoneSize(AreaUnits::AreaUnitsEnum areaUnits); + + // Setters + void setBurningCondition(BurningCondition::BurningConditionEnum condition); + void setSlopeClass(SlopeClass::SlopeClassEnum slope); + void setSpeedClass(SpeedClass::SpeedClassEnum speed); + void setVegetationHeight(double height, LengthUnits::LengthUnitsEnum lengthUnits); + +protected: + void memberwiseCopyAssignment(const SafeSeparationDistanceCalculator& rhs); + static double getValue(SpeedClass::SpeedClassEnum speed, BurningCondition::BurningConditionEnum burning, SlopeClass::SlopeClassEnum slope) { + auto key = std::make_tuple(speed, burning, slope); + auto it = deltaLookup.find(key); + if (it != deltaLookup.end()) { + return it->second; + } + return 0.0; + } + + BurningCondition::BurningConditionEnum burningCondition_; + SlopeClass::SlopeClassEnum slopeClass_; + SpeedClass::SpeedClassEnum speedClass_; + double vegetationHeight_; + double safeSeparationDistance_; + double safetyZoneSize_; + + static const std::unordered_map, double, TupleHash> deltaLookup; +};