| 1 | #include "outflowchannels.h"
|
|---|
| 2 |
|
|---|
| 3 | #include <mars_util.h>
|
|---|
| 4 | #include <mars_lookup.h>
|
|---|
| 5 | #include <mars_ptr.h>
|
|---|
| 6 |
|
|---|
| 7 | using namespace mars;
|
|---|
| 8 | using namespace geoworld::ofc;
|
|---|
| 9 |
|
|---|
| 10 | namespace geoworld
|
|---|
| 11 | {
|
|---|
| 12 | void OutflowChannelGM::init(SynthesisSession & manager, const IGeoWorldAccessor & accessor, const unsigned short nMaxWidth, const unsigned short nMaxHeight)
|
|---|
| 13 | {
|
|---|
| 14 | using namespace mars;
|
|---|
| 15 |
|
|---|
| 16 | const mars::RangeX< float > mmfDirs(_fGeneralDir - _fSourceSpread / 2.0f, _fGeneralDir + _fSourceSpread / 2.0f);
|
|---|
| 17 |
|
|---|
| 18 | for (unsigned int i = 0; i < _nSourcePoints; ++i)
|
|---|
| 19 | {
|
|---|
| 20 | const float fDir = mmfDirs.next();
|
|---|
| 21 |
|
|---|
| 22 | _chans.addStartPoint(
|
|---|
| 23 | accessor.createCoords(
|
|---|
| 24 | static_cast< GWSurfacePos::Precision > (_mmfSourceDisplacement.next() * cosf(fDir + static_cast< float > (mars::PI))),
|
|---|
| 25 | static_cast< GWSurfacePos::Precision > (_mmfSourceDisplacement.next() * sinf(fDir + static_cast< float > (mars::PI)))
|
|---|
| 26 | ),
|
|---|
| 27 | fDir
|
|---|
| 28 | );
|
|---|
| 29 | }
|
|---|
| 30 |
|
|---|
| 31 | const float
|
|---|
| 32 | nNewHalfWidth = static_cast< float > (nMaxWidth) / 2,
|
|---|
| 33 | nNewHalfHeight = static_cast< float > (nMaxHeight) / 2;
|
|---|
| 34 |
|
|---|
| 35 | _chans.init(
|
|---|
| 36 | new FluiDynQueryBridge (&accessor, _ptStart),
|
|---|
| 37 | _mmnLevels.next(),
|
|---|
| 38 | mars::BBox< float > (
|
|---|
| 39 | -nNewHalfWidth + 1,
|
|---|
| 40 | -nNewHalfHeight + 1,
|
|---|
| 41 | +nNewHalfWidth - 1,
|
|---|
| 42 | +nNewHalfHeight - 1
|
|---|
| 43 | )
|
|---|
| 44 | );
|
|---|
| 45 |
|
|---|
| 46 | const BBox< long > bbox = _chans.getBBox();
|
|---|
| 47 |
|
|---|
| 48 | if (!bbox.empty())
|
|---|
| 49 | _bbox = _chans.getBBox() + _ptStart;
|
|---|
| 50 | else
|
|---|
| 51 | _bbox = BBox< long >();
|
|---|
| 52 | }
|
|---|
| 53 |
|
|---|
| 54 | void OutflowChannelGM::doMorph (LockedGWSection & section) const
|
|---|
| 55 | {
|
|---|
| 56 | mars::BBox< long > bbox = getBBox();
|
|---|
| 57 | LockedGWSection::View * pView = section.createView(bbox.left, bbox.top, bbox.right, bbox.bottom);
|
|---|
| 58 |
|
|---|
| 59 | _chans.run(pView->getHeightMap());
|
|---|
| 60 |
|
|---|
| 61 | section.releaseView(pView);
|
|---|
| 62 | }
|
|---|
| 63 |
|
|---|
| 64 | OutflowChannelGM::~OutflowChannelGM()
|
|---|
| 65 | {
|
|---|
| 66 | }
|
|---|
| 67 |
|
|---|
| 68 | OutflowChannelGM::OutflowChannelGM(
|
|---|
| 69 | const GWSurfacePos & ptStart,
|
|---|
| 70 | const float fGeneralDir,
|
|---|
| 71 | const unsigned int nSourcePoints,
|
|---|
| 72 | const mars::RangeX< float > & mmfSourceDisplacement,
|
|---|
| 73 | const float fSourceSpread,
|
|---|
| 74 | const mars::RangeX< float > & mmfBendZenith,
|
|---|
| 75 | const unsigned int nBendZenithSteps,
|
|---|
| 76 | const unsigned int nCandidateSampleAmt,
|
|---|
| 77 | const mars::RangeX< float > & mmfSplineSeg,
|
|---|
| 78 | const float fGravitySlopeGrace,
|
|---|
| 79 | const float fCarveWeight,
|
|---|
| 80 | const float frSnapToGuide,
|
|---|
| 81 | const mars::RangeX< float > & mmfFlowLineWidth,
|
|---|
| 82 | const mars::RangeX< unsigned int > & mmnLevels,
|
|---|
| 83 | const mars::RangeX< unsigned int > & mmnKidsPerLevel,
|
|---|
| 84 | const float fwStraightness,
|
|---|
| 85 | const float fwElevationInfluence,
|
|---|
| 86 | const float fwDensityInfluence,
|
|---|
| 87 | const float fwChaosInfluence,
|
|---|
| 88 | const unsigned int nSedimentHistorySize
|
|---|
| 89 | ) :
|
|---|
| 90 | _mmfFlowLineWidth(mmfFlowLineWidth),
|
|---|
| 91 | _mmnLevels(mmnLevels),
|
|---|
| 92 | _chans(
|
|---|
| 93 | mmfBendZenith, nBendZenithSteps, nCandidateSampleAmt, mmfSplineSeg,
|
|---|
| 94 | fGravitySlopeGrace, fCarveWeight, frSnapToGuide, mmfFlowLineWidth, mmnKidsPerLevel,
|
|---|
| 95 | fwStraightness, fwElevationInfluence, fwDensityInfluence, fwChaosInfluence,
|
|---|
| 96 | nSedimentHistorySize
|
|---|
| 97 | ),
|
|---|
| 98 | _ptStart(ptStart),
|
|---|
| 99 | _fGeneralDir(fGeneralDir),
|
|---|
| 100 | _nSourcePoints(nSourcePoints),
|
|---|
| 101 | _mmfSourceDisplacement(mmfSourceDisplacement),
|
|---|
| 102 | _fSourceSpread(fSourceSpread)
|
|---|
| 103 | {}
|
|---|
| 104 |
|
|---|
| 105 | OutflowChannelGM::OutflowChannelGM()
|
|---|
| 106 | :
|
|---|
| 107 | _fGeneralDir(0),
|
|---|
| 108 | _nSourcePoints(0),
|
|---|
| 109 | _fSourceSpread(0)
|
|---|
| 110 | {}
|
|---|
| 111 |
|
|---|
| 112 | OutflowChannelGM * OutflowChannelGM::createInstance( mars::ObjectStream & ins )
|
|---|
| 113 | {
|
|---|
| 114 | OutflowChannelGM * pOFCGM = new OutflowChannelGM();
|
|---|
| 115 |
|
|---|
| 116 | ins
|
|---|
| 117 | >> pOFCGM->_mmfFlowLineWidth
|
|---|
| 118 | >> pOFCGM->_mmnLevels
|
|---|
| 119 | >> pOFCGM->_ptStart
|
|---|
| 120 | >> pOFCGM->_fGeneralDir
|
|---|
| 121 | >> pOFCGM->_nSourcePoints
|
|---|
| 122 | >> pOFCGM->_mmfSourceDisplacement
|
|---|
| 123 | >> pOFCGM->_fSourceSpread
|
|---|
| 124 | >> pOFCGM->_bbox;
|
|---|
| 125 |
|
|---|
| 126 | pOFCGM->_chans << ins;
|
|---|
| 127 | return pOFCGM;
|
|---|
| 128 | }
|
|---|
| 129 |
|
|---|
| 130 | mars::ObjectStream & OutflowChannelGM::operator >> ( mars::ObjectStream & outs ) const
|
|---|
| 131 | {
|
|---|
| 132 | outs
|
|---|
| 133 | << _mmfFlowLineWidth
|
|---|
| 134 | << _mmnLevels
|
|---|
| 135 | << _ptStart
|
|---|
| 136 | << _fGeneralDir
|
|---|
| 137 | << _nSourcePoints
|
|---|
| 138 | << _mmfSourceDisplacement
|
|---|
| 139 | << _fSourceSpread
|
|---|
| 140 | << _bbox;
|
|---|
| 141 |
|
|---|
| 142 | _chans >> outs;
|
|---|
| 143 | return outs;
|
|---|
| 144 | }
|
|---|
| 145 |
|
|---|
| 146 | void OutflowChannelGM::MyChannelSet::applyFlowLine( const FlowLineType & fl, OutflowChannelData * pData ) const
|
|---|
| 147 | {
|
|---|
| 148 | unsigned int nSplNum = 0;
|
|---|
| 149 | mars::RingBuffer< HMPrec > & rbSediment = *_prbSediment;
|
|---|
| 150 |
|
|---|
| 151 | for (ChannelFinderType::FlowLineType::Iterator<GeoHeightMap::Precision, EaseInFn, EaseOutFn> it = fl.iterate<GeoHeightMap::Precision, EaseInFn, EaseOutFn>(_fnEaseIn, _fnEaseOut); it; ++it)
|
|---|
| 152 | {
|
|---|
| 153 | const VectorTag< unsigned short > ::V2 pos = *it;
|
|---|
| 154 | // Reset sediment history if wrap-around to new spline
|
|---|
| 155 | if (nSplNum != it.splineNum())
|
|---|
| 156 | {
|
|---|
| 157 | rbSediment.clear();
|
|---|
| 158 | nSplNum = it.splineNum();
|
|---|
| 159 | }
|
|---|
| 160 |
|
|---|
| 161 | // Total width
|
|---|
| 162 | const float fTotalRadius = static_cast <float> (it.crad());
|
|---|
| 163 |
|
|---|
| 164 | // The radius as a ratio to the total width
|
|---|
| 165 | const float frRadius = it.trad();
|
|---|
| 166 |
|
|---|
| 167 | // Perturbation value obtained from map
|
|---|
| 168 | const float per = _perturb->getw(it.radius(), it.index());
|
|---|
| 169 |
|
|---|
| 170 | // Obtain the height at the current spot
|
|---|
| 171 | const GeoHeightMap::Precision s = pData->view(pos.x, pos.y);
|
|---|
| 172 |
|
|---|
| 173 | // Diffused perturbed sediment index based on distance from spline spine
|
|---|
| 174 | const unsigned int ips =
|
|---|
| 175 | std::min(
|
|---|
| 176 | static_cast< unsigned int > (_prbSediment->count - 1),
|
|---|
| 177 | static_cast< unsigned int > (per * _fnBevel.rforce(frRadius) * fTotalRadius)
|
|---|
| 178 | );
|
|---|
| 179 |
|
|---|
| 180 | // If the sediment value at the sediment index is empty/null
|
|---|
| 181 | if (rbSediment[ips] == 0)
|
|---|
| 182 | rbSediment[ips] = s;
|
|---|
| 183 | else
|
|---|
| 184 | rbSediment[ips] = (rbSediment[ips] + s) / 2;
|
|---|
| 185 |
|
|---|
| 186 | //const VectorTag< float > ::V3 T = it.stress();
|
|---|
| 187 |
|
|---|
| 188 | const GeoHeightMap::Precision
|
|---|
| 189 | he = rbSediment[0],
|
|---|
| 190 | h = static_cast <GeoHeightMap::Precision> (
|
|---|
| 191 | (he == 0 ? s : (he + s) / 2)
|
|---|
| 192 | + (_fnBevel.f(frRadius))
|
|---|
| 193 | * getWidthRange().maximum
|
|---|
| 194 | //* std::max(0.0f, T.z / 4.0f) // HACK: Scale down the stress tensor, its scale is unvalidated // HACK: Add the stress tensor to the bevel ratio, scale unvalidated
|
|---|
| 195 | );
|
|---|
| 196 | ++rbSediment;
|
|---|
| 197 |
|
|---|
| 198 | pData->hmbb(pos.x, pos.y) =
|
|---|
| 199 | std::min(
|
|---|
| 200 | pData->view(pos.x, pos.y),
|
|---|
| 201 | std::min(s, h)
|
|---|
| 202 | );
|
|---|
| 203 | }
|
|---|
| 204 | pData->view << pData->hmbb;
|
|---|
| 205 | }
|
|---|
| 206 |
|
|---|
| 207 | void OutflowChannelGM::MyChannelSet::init( const mars::ptr< FluiDynQueryBridge > & pQuery, const unsigned int nLevels, const mars::BBox< float > & bboxSearch )
|
|---|
| 208 | {
|
|---|
| 209 | using namespace mars;
|
|---|
| 210 |
|
|---|
| 211 | OutflowChannelGM::ChannelSetType::init(pQuery, bboxSearch, nLevels);
|
|---|
| 212 |
|
|---|
| 213 | const BBox< long > bbox = getBBox();
|
|---|
| 214 |
|
|---|
| 215 | if (!bbox.empty()) // Sometimes the finder algorithm fails to find any suitable paths, so we ditch this GeoMorph instance
|
|---|
| 216 | {
|
|---|
| 217 | const GWCoords pos3d = GWCoords(-bbox.left, -bbox.top, 0);
|
|---|
| 218 |
|
|---|
| 219 | for (MyChannelSet::GuideList::iterator i = begin(); i != end(); ++i)
|
|---|
| 220 | (*i)->offsetBy(pos3d);
|
|---|
| 221 |
|
|---|
| 222 | _perturb =
|
|---|
| 223 | PerturbMapType::createInstance(
|
|---|
| 224 | static_cast< HMPrec >(getWidthRange().maximum),
|
|---|
| 225 | static_cast< HMPrec >(sqrt(static_cast <float> (SQ(bbox.getWidth()) + SQ(bbox.getHeight())))),
|
|---|
| 226 | mars::Wrap
|
|---|
| 227 | );
|
|---|
| 228 |
|
|---|
| 229 | for (PerturbMapType::EdgeSeedIterator it = _perturb->edgeSeedIterator(); it; ++it)
|
|---|
| 230 | {
|
|---|
| 231 | it = static_cast <short> (RAND(_prbSediment->count));
|
|---|
| 232 | }
|
|---|
| 233 | _perturb->run(0.25f);
|
|---|
| 234 | }
|
|---|
| 235 | }
|
|---|
| 236 |
|
|---|
| 237 | void OutflowChannelGM::MyChannelSet::run( GeoHeightMap::View * pView ) const
|
|---|
| 238 | {
|
|---|
| 239 | OutflowChannelData data(pView);
|
|---|
| 240 | OutflowChannelGM::ChannelSetType::run(&data);
|
|---|
| 241 | }
|
|---|
| 242 |
|
|---|
| 243 | mars::ObjectStream & OutflowChannelGM::MyChannelSet::operator >> (mars::ObjectStream & outs) const
|
|---|
| 244 | {
|
|---|
| 245 | ChannelSetType::operator >> (outs);
|
|---|
| 246 | outs << _fnBevel.getBevelDepth() << (_prbSediment == NULL ? 0 : _prbSediment->count);
|
|---|
| 247 | return outs;
|
|---|
| 248 | }
|
|---|
| 249 | mars::ObjectStream & OutflowChannelGM::MyChannelSet::operator << (mars::ObjectStream & ins)
|
|---|
| 250 | {
|
|---|
| 251 | using namespace mars;
|
|---|
| 252 |
|
|---|
| 253 | ChannelSetType::operator << (ins);
|
|---|
| 254 |
|
|---|
| 255 | float fCarveWeight;
|
|---|
| 256 | unsigned int nSedimentCount;
|
|---|
| 257 |
|
|---|
| 258 | ins >> fCarveWeight >> nSedimentCount;
|
|---|
| 259 | _fnBevel = BevelFn(fCarveWeight);
|
|---|
| 260 | delete _prbSediment;
|
|---|
| 261 | _prbSediment = (nSedimentCount > 0 ? new RingBuffer< HMPrec >(nSedimentCount) : NULL);
|
|---|
| 262 | return ins;
|
|---|
| 263 | }
|
|---|
| 264 |
|
|---|
| 265 | OutflowChannelGM::MyChannelSet::MyChannelSet(
|
|---|
| 266 | const mars::RangeX< float > & mmfBendZenith,
|
|---|
| 267 | const unsigned int nBendZenithSteps,
|
|---|
| 268 | const unsigned int nCandidateSampleAmt,
|
|---|
| 269 | const mars::RangeX< float > & mmfSplineSeg,
|
|---|
| 270 | const float fGravitySlopeGrace,
|
|---|
| 271 | const float fCarveWeight,
|
|---|
| 272 | const float frSnapToGuide,
|
|---|
| 273 | const mars::RangeX< float > & mmfFlowLineWidth,
|
|---|
| 274 | const mars::RangeX< unsigned int > & mmnKidsPerLevel,
|
|---|
| 275 | const float fwStraightness,
|
|---|
| 276 | const float fwElevationInfluence,
|
|---|
| 277 | const float fwDensityInfluence,
|
|---|
| 278 | const float fwChaosInfluence,
|
|---|
| 279 | const unsigned int nSedimentHistorySize
|
|---|
| 280 | )
|
|---|
| 281 | : ChannelSet(
|
|---|
| 282 | mmfBendZenith,
|
|---|
| 283 | nBendZenithSteps,
|
|---|
| 284 | nCandidateSampleAmt,
|
|---|
| 285 | mmfSplineSeg,
|
|---|
| 286 | fGravitySlopeGrace,
|
|---|
| 287 | frSnapToGuide,
|
|---|
| 288 | mmfFlowLineWidth,
|
|---|
| 289 | mmnKidsPerLevel,
|
|---|
| 290 | fwStraightness,
|
|---|
| 291 | fwElevationInfluence,
|
|---|
| 292 | fwDensityInfluence,
|
|---|
| 293 | fwChaosInfluence
|
|---|
| 294 | ),
|
|---|
| 295 | _fnEaseOut(ofc::EASE_IN_FN),
|
|---|
| 296 | _fnEaseIn(ofc::EASE_OUT_FN),
|
|---|
| 297 | _fnBevel(fCarveWeight),
|
|---|
| 298 | _prbSediment(new RingBuffer< HMPrec > (nSedimentHistorySize)),
|
|---|
| 299 | _perturb(NULL)
|
|---|
| 300 | {}
|
|---|
| 301 |
|
|---|
| 302 | OutflowChannelGM::MyChannelSet::MyChannelSet()
|
|---|
| 303 | :
|
|---|
| 304 | _fnEaseOut(ofc::EASE_IN_FN),
|
|---|
| 305 | _fnEaseIn(ofc::EASE_OUT_FN),
|
|---|
| 306 | _fnBevel(0),
|
|---|
| 307 | _prbSediment(NULL),
|
|---|
| 308 | _perturb(NULL)
|
|---|
| 309 | {}
|
|---|
| 310 |
|
|---|
| 311 | OutflowChannelGM::MyChannelSet::~MyChannelSet()
|
|---|
| 312 | {
|
|---|
| 313 | delete _perturb;
|
|---|
| 314 | delete _prbSediment;
|
|---|
| 315 | }
|
|---|
| 316 |
|
|---|
| 317 | GeoMorph * OutflowChannelGMFactory::createRandomInstance( const long x, const long y ) const
|
|---|
| 318 | {
|
|---|
| 319 | return new OutflowChannelGM(
|
|---|
| 320 | GWSurfacePos(x, y),
|
|---|
| 321 | mars::RANDf(static_cast< float > (2 * mars::PI)),
|
|---|
| 322 | _mmnSourcePoints.next(),
|
|---|
| 323 | _mmfSourceDisplacement,
|
|---|
| 324 | _mmfSourceSpread.next(),
|
|---|
| 325 | _mmfBendZenith,
|
|---|
| 326 | _nBendZenithSteps,
|
|---|
| 327 | _nCandidateSampleAmount,
|
|---|
| 328 | _mmfSplineSeg,
|
|---|
| 329 | _fGravitySlopeGrace,
|
|---|
| 330 | _fCarveWeight,
|
|---|
| 331 | _frSnapToGuide,
|
|---|
| 332 | _mmfFlowLineWidth,
|
|---|
| 333 | _mmnLevels,
|
|---|
| 334 | _mmnKidsPerLevel,
|
|---|
| 335 | _fwStraightness,
|
|---|
| 336 | _fwElevationInfluence,
|
|---|
| 337 | _fwDensityInfluence,
|
|---|
| 338 | _fwChaosInfluence,
|
|---|
| 339 | _nSedimentHistorySize
|
|---|
| 340 | );
|
|---|
| 341 | }
|
|---|
| 342 |
|
|---|
| 343 | void OutflowChannelGMFactory::configure( IConfigGMFactory * pFactoryConfig, const IConfigGMFactory::Settings & settings )
|
|---|
| 344 | {
|
|---|
| 345 | geoworld::IConfigSection
|
|---|
| 346 | & section = *pFactoryConfig->getSection(),
|
|---|
| 347 | & sectCandidates = *section.getmap("candidates"),
|
|---|
| 348 | & sectFlowlines = *section.getmap("flowlines"),
|
|---|
| 349 | & sectWeights = *section.getmap("weights");
|
|---|
| 350 |
|
|---|
| 351 | *section["num_sources"] >> _mmnSourcePoints;
|
|---|
| 352 | *section["displacement"] >> _mmfSourceDisplacement;
|
|---|
| 353 | *section["spread"] >> _mmfSourceSpread;
|
|---|
| 354 | *sectCandidates["bend_zenith"] >> _mmfBendZenith;
|
|---|
| 355 | *sectCandidates["zenith_steps"] >> _nBendZenithSteps;
|
|---|
| 356 | *sectCandidates["samples"] >> _nCandidateSampleAmount;
|
|---|
| 357 | *section["segment"] >> _mmfSplineSeg;
|
|---|
| 358 | *section["slope_grace"] >> _fGravitySlopeGrace;
|
|---|
| 359 | *section["carve"] >> _fCarveWeight;
|
|---|
| 360 | *section["guide_snap"] >> _frSnapToGuide;
|
|---|
| 361 | *sectFlowlines["width"] >> _mmfFlowLineWidth;
|
|---|
| 362 | *sectFlowlines["levels"] >> _mmnLevels;
|
|---|
| 363 | *sectFlowlines["children"] >> _mmnKidsPerLevel;
|
|---|
| 364 | *sectWeights["straightness"] >> _fwStraightness;
|
|---|
| 365 | *sectWeights["elevation"] >> _fwElevationInfluence;
|
|---|
| 366 | *sectWeights["density"] >> _fwDensityInfluence;
|
|---|
| 367 | *sectWeights["chaos"] >> _fwChaosInfluence;
|
|---|
| 368 | *section["sediment_memory"] >> _nSedimentHistorySize;
|
|---|
| 369 | }
|
|---|
| 370 |
|
|---|
| 371 | void OutflowChannelGMFactory::save( const GeoMorph * pGM, mars::ObjectStream & outs ) const
|
|---|
| 372 | {
|
|---|
| 373 | const OutflowChannelGM * pOFCGM = dynamic_cast< const OutflowChannelGM * > (pGM);
|
|---|
| 374 |
|
|---|
| 375 | assert(pOFCGM != NULL);
|
|---|
| 376 | *pOFCGM >> outs;
|
|---|
| 377 | }
|
|---|
| 378 |
|
|---|
| 379 | const GeoMorph * OutflowChannelGMFactory::restore( mars::ObjectStream & ins ) const
|
|---|
| 380 | {
|
|---|
| 381 | OutflowChannelGM * pOFCGM;
|
|---|
| 382 |
|
|---|
| 383 | pOFCGM << ins;
|
|---|
| 384 | return pOFCGM;
|
|---|
| 385 | }
|
|---|
| 386 | }
|
|---|