[80a6a52] | 1 | #include "oregen.h"
|
---|
| 2 |
|
---|
| 3 | #include <iterator>
|
---|
| 4 | #include <mars_log.h>
|
---|
| 5 |
|
---|
| 6 | namespace geoworld
|
---|
| 7 | {
|
---|
| 8 | const float DepositSynthesizer::FREQUENCY_MULTIPLIER = 1000;
|
---|
| 9 |
|
---|
| 10 | DepositSynthesizer::DepositSynthesizer(const MineralsDB * pMinDB, const DepositSynthesizerSettings & settings, const WorldUnit nWidth, const WorldUnit nHeight, const WorldUnit nDepth, const unsigned short nDEMLOD)
|
---|
| 11 | : _pMinDB(pMinDB), _nAbsWidth(nWidth), _nAbsHeight(nHeight), _stratum(settings.layers.count, nWidth, nHeight, nDepth, nDEMLOD, mars::Wrap), _settings(settings),
|
---|
| 12 | _otOre(std::max(nWidth, nHeight), 4),
|
---|
| 13 | _factBubbleGum(
|
---|
| 14 | settings.minerals.spherepack.limit,
|
---|
| 15 | settings.minerals.spherepack.minimum,
|
---|
| 16 | settings.minerals.spherepack.maxtier,
|
---|
| 17 | settings.minerals.spherepack.sizeflux,
|
---|
| 18 | settings.minerals.spherepack.kidflux,
|
---|
| 19 | settings.minerals.deposit.vein.detail,
|
---|
| 20 | settings.minerals.deposit.vein.erratic
|
---|
| 21 | ),
|
---|
| 22 | _pbsAbundance(settings.minerals.abundance.curve),
|
---|
| 23 | _pbsDepositSize(settings.minerals.deposit.curve),
|
---|
| 24 | _pbsThickness(settings.layers.count, settings.layers.thickness.curve, settings.layers.thickness.scale)
|
---|
| 25 | {
|
---|
| 26 | assert(((_nAbsWidth - 1) & _nAbsWidth) == 0 && ((_nAbsHeight - 1) & _nAbsHeight) == 0); // Must be a power of 2
|
---|
| 27 | }
|
---|
| 28 |
|
---|
| 29 | DepositSynthesizer::~DepositSynthesizer()
|
---|
| 30 | {
|
---|
| 31 | }
|
---|
| 32 |
|
---|
| 33 | DepositSynthesizerSettings DepositSynthesizer::loadSettings( IDepositSynthConfigReader & cfgreader )
|
---|
| 34 | {
|
---|
| 35 | DepositSynthesizerSettings settings;
|
---|
| 36 | cfgreader.load(settings);
|
---|
| 37 | return settings;
|
---|
| 38 | }
|
---|
| 39 |
|
---|
| 40 | Silica DepositSynthesizer::selectSilica( const float fRatio )
|
---|
| 41 | {
|
---|
| 42 | if (fRatio < 0.16f)
|
---|
| 43 | return Silica_NA;
|
---|
| 44 | else if (fRatio < 0.17f * 2.0f)
|
---|
| 45 | return Silica_UltraMafic;
|
---|
| 46 | else if (fRatio < 0.17f * 3.0f)
|
---|
| 47 | return Silica_Mafic;
|
---|
| 48 | else if (fRatio < 0.17f * 4.0f)
|
---|
| 49 | return Silica_Intermediate;
|
---|
| 50 | else if (fRatio < 0.17f * 5.0f)
|
---|
| 51 | return Silica_InterFelsic;
|
---|
| 52 | else
|
---|
| 53 | return Silica_Felsic;
|
---|
| 54 | }
|
---|
| 55 |
|
---|
| 56 | Origin DepositSynthesizer::selectOrigin( const float fRatio )
|
---|
| 57 | {
|
---|
| 58 | if (fRatio < 0.2f)
|
---|
| 59 | return Origin_NA;
|
---|
| 60 | else if (fRatio < 0.2f * 2.0f)
|
---|
| 61 | return Origin_Plutonic;
|
---|
| 62 | else if (fRatio < 0.2f * 3.0f)
|
---|
| 63 | return Origin_Subvolcanic;
|
---|
| 64 | else if (fRatio < 0.2f * 4.0f)
|
---|
| 65 | return Origin_Volcanic;
|
---|
| 66 | else
|
---|
| 67 | return Origin_Meteoritic;
|
---|
| 68 | }
|
---|
| 69 |
|
---|
| 70 | void DepositSynthesizer::generateStrata()
|
---|
| 71 | {
|
---|
| 72 | using namespace mars;
|
---|
| 73 | typedef std::vector< MineralsDB::ClassesSet::value_type > ClassList;
|
---|
| 74 |
|
---|
| 75 | ClassList lstSilicaClassSelection;
|
---|
| 76 |
|
---|
| 77 | for (unsigned char s = _settings.layers.silica.minimum; s <= _settings.layers.silica.maximum; ++s)
|
---|
| 78 | {
|
---|
| 79 | MineralsDB::ClassesSetFacade facade = _pMinDB->getClassesBySilica(static_cast< Silica > (s));
|
---|
| 80 |
|
---|
| 81 | lstSilicaClassSelection.insert(lstSilicaClassSelection.end(), facade.begin(), facade.end());
|
---|
| 82 | }
|
---|
| 83 |
|
---|
| 84 | ptr< GeoStratumMPDG > pVMPDG =
|
---|
| 85 | GeoStratumMPDG::createInstance(
|
---|
| 86 | static_cast< unsigned short > (_nAbsWidth >> _stratum.lod),
|
---|
| 87 | static_cast< unsigned short > (_nAbsHeight >> _stratum.lod),
|
---|
| 88 | mars::Wrap
|
---|
| 89 | );
|
---|
| 90 |
|
---|
| 91 | for (size_t c = 0; c < _stratum.size(); ++c)
|
---|
| 92 | {
|
---|
| 93 | const size_t nClassCount = _settings.layers.classes.next();
|
---|
| 94 | for (size_t j = 0; j < nClassCount; ++j)
|
---|
| 95 | pVMPDG->reg(lstSilicaClassSelection[mars::RAND(lstSilicaClassSelection.size())]);
|
---|
| 96 |
|
---|
| 97 | pVMPDG->seed(1, _settings.layers.coarseness, static_cast< signed int > (_settings.layers.thickness.base + _pbsThickness[c]));
|
---|
| 98 | pVMPDG->run(_settings.layers.coarseness);
|
---|
| 99 |
|
---|
| 100 | const GeoStratumMPDG::Precision
|
---|
| 101 | min = pVMPDG->range().minimum;
|
---|
| 102 |
|
---|
| 103 | *pVMPDG -= min.altitude - GeoStratumField::ScalarTraits::step().altitude;
|
---|
| 104 |
|
---|
| 105 | _stratum[c] << *pVMPDG;
|
---|
| 106 |
|
---|
| 107 | assert(_stratum[c].range().minimum.altitude >= 0);
|
---|
| 108 |
|
---|
| 109 | pVMPDG->reset();
|
---|
| 110 | pVMPDG->clearRegs();
|
---|
| 111 | }
|
---|
| 112 |
|
---|
| 113 | // TODO: Automate
|
---|
| 114 | _stratum.updateIndexMap();
|
---|
| 115 | }
|
---|
| 116 |
|
---|
| 117 | void DepositSynthesizer::generateMinerals(const unsigned int nPass)
|
---|
| 118 | {
|
---|
| 119 | using namespace mars;
|
---|
| 120 | typedef std::set< ptr< MineralDef > > MineralSet;
|
---|
| 121 | const mars::RangeX< WorldUnit > rngStrata = _stratum.getRange();
|
---|
| 122 |
|
---|
| 123 | const size_t
|
---|
| 124 | nMineralCount = static_cast< size_t > (
|
---|
| 125 | _settings.minerals.frequency *
|
---|
| 126 | static_cast< float > (_nAbsWidth) / FREQUENCY_MULTIPLIER *
|
---|
| 127 | static_cast< float > (_nAbsHeight) / FREQUENCY_MULTIPLIER *
|
---|
| 128 | static_cast< float > (rngStrata.delta) / FREQUENCY_MULTIPLIER
|
---|
| 129 | );
|
---|
| 130 |
|
---|
| 131 | size_t c = 0;
|
---|
| 132 | MineralDepositList lstAssociations, lstProtoliths;
|
---|
| 133 | MineralSet setSelections;
|
---|
| 134 |
|
---|
| 135 | while (c < nMineralCount)
|
---|
| 136 | {
|
---|
| 137 | OctTreeOreInstance::VECTOR ptChosenSpot (RAND(_nAbsWidth), RAND(_nAbsHeight), rngStrata.next());
|
---|
| 138 | const size_t nNestCount = _settings.minerals.deposit.nesting.next();
|
---|
| 139 |
|
---|
| 140 | for (size_t j = 0; j <= nNestCount; ++j, ++c) // j <= x: Nesting value is number of nested hosted minerals not number of minerals total
|
---|
| 141 | {
|
---|
| 142 | const MinClassPtr pEnvironment = _stratum.getDominantElementVN3(ptChosenSpot.x, ptChosenSpot.y, ptChosenSpot.z);
|
---|
| 143 |
|
---|
| 144 | for (
|
---|
| 145 | OctTreeOreInstance::const_EntityRadialIterator
|
---|
| 146 | i = const_cast< const OctTreeOreInstance & > (_otOre).contents(
|
---|
| 147 | OctTreeOreInstance::MyRadialRegion(
|
---|
| 148 | ptChosenSpot,
|
---|
| 149 | _settings.minerals.neighborhood.next()
|
---|
| 150 | )
|
---|
| 151 | );
|
---|
| 152 | i;
|
---|
| 153 | ++i
|
---|
| 154 | )
|
---|
| 155 | {
|
---|
| 156 | if (i->pass < nPass)
|
---|
| 157 | {
|
---|
| 158 | MineralsDB::PetrogenyMineralSetFacade facminIncubated = _pMinDB->getIncubatedMinerals(i->deposit.mineral);
|
---|
| 159 |
|
---|
| 160 | lstProtoliths.push_back(i->deposit);
|
---|
| 161 | for (MineralsDB::PetrogenyMineralSet::const_iterator k = facminIncubated.begin(); k != facminIncubated.end(); ++k)
|
---|
| 162 | setSelections.insert(k->mineral);
|
---|
| 163 | }
|
---|
| 164 | else
|
---|
| 165 | {
|
---|
| 166 | MineralsDB::PetrogenyMineralSetFacade facminAssociated = _pMinDB->getAssociatedMinerals(i->deposit.mineral);
|
---|
| 167 |
|
---|
| 168 | lstAssociations.push_back(i->deposit);
|
---|
| 169 | for (MineralsDB::PetrogenyMineralSet::const_iterator k = facminAssociated.begin(); k != facminAssociated.end(); ++k)
|
---|
| 170 | setSelections.insert(k->mineral);
|
---|
| 171 | }
|
---|
| 172 | }
|
---|
| 173 |
|
---|
| 174 | MineralsDB::PetrogenyClassSetFacade facminEnvironment = _pMinDB->getMineralsByEnvironment(pEnvironment);
|
---|
| 175 |
|
---|
| 176 | for (MineralsDB::PetrogenyClassSet::const_iterator k = facminEnvironment.begin(); k != facminEnvironment.end(); ++k)
|
---|
| 177 | setSelections.insert(k->mineral);
|
---|
| 178 |
|
---|
| 179 | if (!setSelections.empty())
|
---|
| 180 | {
|
---|
| 181 | const size_t nSelection = RAND(setSelections.size());
|
---|
| 182 | MineralSet::const_iterator iMin = setSelections.begin();
|
---|
| 183 | std::vector< MineralDef::GenesisList::const_iterator > lstGeneses;
|
---|
| 184 | MineralDeposit depHost;
|
---|
| 185 |
|
---|
| 186 | std::advance(iMin, nSelection);
|
---|
| 187 | (*iMin)->intersectGeneses(lstGeneses, lstAssociations, lstProtoliths, depHost, pEnvironment);
|
---|
| 188 | if (!lstGeneses.empty())
|
---|
| 189 | {
|
---|
| 190 | const size_t nGenSelection = RAND(lstGeneses.size());
|
---|
| 191 | const PetrogenyDef & petrogeny = *lstGeneses[nGenSelection];
|
---|
| 192 | const std::pair< BubbleGumFactory::PackPtr, DepositDistribution > pairDeposit = depositMineral(petrogeny, ptChosenSpot, *iMin, nPass);
|
---|
| 193 | const BubbleGumFactory::PackPtr & pSpherePack = pairDeposit.first;
|
---|
| 194 | const DepositDistribution & enddDepositDistrib = pairDeposit.second;
|
---|
| 195 | const size_t nSphereCount = pSpherePack->count();
|
---|
| 196 | const size_t nSelectedHostSphere = RAND(nSphereCount);
|
---|
| 197 |
|
---|
| 198 | size_t k = 0;
|
---|
| 199 | for (BubbleGumFactory::PackPtr::Type::const_iterator iPack = pSpherePack->iterate(); iPack; ++iPack, ++k)
|
---|
| 200 | {
|
---|
| 201 | if (k == nSelectedHostSphere)
|
---|
| 202 | {
|
---|
| 203 | ptChosenSpot = iPack->p;
|
---|
| 204 | depHost = MineralDeposit(*iMin, enddDepositDistrib);
|
---|
| 205 | break;
|
---|
| 206 | }
|
---|
| 207 | }
|
---|
| 208 | }
|
---|
| 209 | }
|
---|
| 210 | }
|
---|
| 211 | lstAssociations.clear();
|
---|
| 212 | lstProtoliths.clear();
|
---|
| 213 | setSelections.clear();
|
---|
| 214 | }
|
---|
| 215 | }
|
---|
| 216 |
|
---|
| 217 | std::pair< DepositSynthesizer::BubbleGumFactory::PackPtr, DepositDistribution >
|
---|
| 218 | DepositSynthesizer::depositMineral( const PetrogenyDef & petrogeny, const OctTreeOreInstance::VECTOR & ptChosenSpot, const mars::ptr< MineralDef > & pMin, const size_t nPass )
|
---|
| 219 | {
|
---|
| 220 | using namespace mars;
|
---|
| 221 |
|
---|
| 222 | const PointScale enpsAbundance = _pbsAbundance(RANDf(1.0f));
|
---|
| 223 | const float fDepositSize = _pbsDepositSize[petrogeny.size] * _settings.minerals.deposit.base;
|
---|
| 224 | const size_t nSelDistOff = RAND(petrogeny.distributions.count());
|
---|
| 225 | size_t c = 0;
|
---|
| 226 | for (size_t i = 0; c < petrogeny.distributions.size() && i < nSelDistOff; petrogeny.distributions[c] && ++i, ++c);
|
---|
| 227 | const DepositDistribution enddDistrib = static_cast< DepositDistribution > (c);
|
---|
| 228 |
|
---|
| 229 | BubbleGumFactory::PackPtr pSpherePack;
|
---|
| 230 |
|
---|
| 231 | switch (enddDistrib)
|
---|
| 232 | {
|
---|
| 233 | case Dist_Cluster:
|
---|
| 234 | pSpherePack = _factBubbleGum.createCluster(ptChosenSpot, fDepositSize);
|
---|
| 235 | break;
|
---|
| 236 | case Dist_Vein:
|
---|
| 237 | {
|
---|
| 238 | const OctTreeOreInstance::VECTOR::Precision
|
---|
| 239 | nScale = static_cast< OctTreeOreInstance::VECTOR::Precision > (fDepositSize),
|
---|
| 240 | nHalfScale = nScale / 2;
|
---|
| 241 |
|
---|
| 242 | OctTreeOreInstance::VECTOR off (RAND(nScale) - nHalfScale, RAND(nScale) - nHalfScale, RAND(nScale) - nHalfScale);
|
---|
| 243 |
|
---|
| 244 | off *= nHalfScale;
|
---|
| 245 | off /= MAG(off);
|
---|
| 246 | pSpherePack = _factBubbleGum.createVein(ptChosenSpot - off, ptChosenSpot + off, fDepositSize, _settings.minerals.deposit.vein.deviation.next());
|
---|
| 247 | }
|
---|
| 248 | break;
|
---|
| 249 | case Dist_Dike:
|
---|
| 250 | {
|
---|
| 251 | const OctTreeOreInstance::VECTOR::Precision
|
---|
| 252 | nScale = static_cast< OctTreeOreInstance::VECTOR::Precision > (fDepositSize),
|
---|
| 253 | nHalfScale = nScale / 2;
|
---|
| 254 |
|
---|
| 255 | OctTreeOreInstance::VECTOR off (
|
---|
| 256 | (RAND(nScale) - nHalfScale) / static_cast< OctTreeOreInstance::VECTOR::Precision > (1.0f / (1.0f - _settings.minerals.deposit.dike.orthogonality.next())),
|
---|
| 257 | RAND(nScale) - nHalfScale,
|
---|
| 258 | (RAND(nScale) - nHalfScale) / static_cast< OctTreeOreInstance::VECTOR::Precision > (1.0f / (1.0f - _settings.minerals.deposit.dike.orthogonality.next()))
|
---|
| 259 | );
|
---|
| 260 |
|
---|
| 261 | off *= nHalfScale;
|
---|
| 262 | off /= MAG(off);
|
---|
| 263 | pSpherePack = _factBubbleGum.createVein(ptChosenSpot - off, ptChosenSpot + off, fDepositSize, _settings.minerals.deposit.dike.deviation.next());
|
---|
| 264 | }
|
---|
| 265 | break;
|
---|
| 266 | case Dist_Laccolith:
|
---|
| 267 | pSpherePack = _factBubbleGum.createLaccolith(ptChosenSpot, fDepositSize, _settings.minerals.deposit.laccolith.tail.next());
|
---|
| 268 | break;
|
---|
| 269 | case Dist_Sill:
|
---|
| 270 | case Dist_Layer:
|
---|
| 271 | LOG(mars::Log::Warn) << "Distribution of type sill/layer not implemented, mineral petrogeny dropped";
|
---|
| 272 | break;
|
---|
| 273 | }
|
---|
| 274 |
|
---|
| 275 | if (pSpherePack != NULL)
|
---|
| 276 | pSpherePack->store(_otOre, ptr< OreInstance > (new OreInstance(pMin, nPass, enddDistrib)));
|
---|
| 277 |
|
---|
| 278 | return std::pair< BubbleGumFactory::PackPtr, DepositDistribution > (pSpherePack, enddDistrib);
|
---|
| 279 | }
|
---|
| 280 |
|
---|
| 281 | void DepositSynthesizer::operator>>( FileSource::MineralMap & dest ) const
|
---|
| 282 | {
|
---|
| 283 | for (OctTreeOreInstance::const_EntityAllIterator i = const_cast< const OctTreeOreInstance & > (_otOre).contents(); i; ++i)
|
---|
| 284 | dest.add(i->deposit.mineral, FileSource::MineralMap::QuadTreeSpherePacks::MyCylindricalRegion (i.region()));
|
---|
| 285 | }
|
---|
| 286 | }
|
---|