void TerrainManagerModuleOrographyModifications::moveGroundPoint(
		point & p,scalar height0, scalar height, const word & addType){

	// prepare:
	const Foam::vector & n_up = moduleBase().cooSys->e(TerrainBlock::UP);

	// add type 'add':
	if(addType.compare("add") == 0){

		if( height != 0 ) p += height * n_up;

	}

	// add type 'max':
	else if(addType.compare("max") == 0){

		const scalar h0 = dot(p,n_up);
		if( height0 + height > h0 ){
			p += (height0 + height - h0) * n_up;
		}
	}

	// add type 'average':
	else if(addType.compare("average") == 0){

		if( height != 0 ){
			const scalar h0 = dot(p,n_up);
			scalar h  = 0.5 * ( 2 * h0 + height0 + height );
			p        += (h - h0) * n_up;
		}

	}

	// add type 'hill':
	else if(addType.compare("hill") == 0){

		if( height != 0.){
			const scalar h0 = dot(p,n_up);
			p        += (height0 + height - h0) * n_up;
		}
	}

}
void TerrainManagerModuleCylinder::reserveStorageCylinder(){

	cylinderBlockNr_ = cylinderRadialBlocks_ * moduleBase().walkBoxMaximum();
	cylinderPointNr_ = cylinderRadialBlocks_ * moduleBase().walkBoxMaximum() * 2;

	if(cylinderSectionNr_ > cylinderBlockNr_){
		Info << "\nTerrainManager: Error: The outer cylinder cannot have that many sections." << endl;
		Info << "   sections       : " << cylinderSectionNr_ <<endl;
		Info << "   at most allowed: " << cylinderBlockNr_ << endl;
		throw;
	}

	moduleBase().resizePoints(moduleBase().points().size() + cylinderPointNr_);
	moduleBase().resizeBlocks(moduleBase().blocks().size() + cylinderBlockNr_);
	moduleBase().resizeEdges(moduleBase().edges().size() + 4 * cylinderBlockNr_);

	cylinderPointAdr_.resize(cylinderPointNr_);
	cylinderBlockAdr_.resize(cylinderBlockNr_);

	Info << "      reserved storage for " << cylinderPointNr_ << " points, " << cylinderBlockNr_
			<< " blocks and " << 4 * cylinderBlockNr_ << " edges" << endl;
}
void TerrainManagerModuleOrographyModifications::makeCyclic(label patchIA, label patchIB,const scalar & depth){

	// prepare:
	label dir_perp = 0;
	label dir_long = 0;
	labelList vListA(2);
	labelList vListB(2);
	if(patchIA == BasicBlock::WEST && patchIB == BasicBlock::EAST){
		dir_perp   = 0;
		dir_long   = 1;
		vListA[0]  = BasicBlock::SWL;
		vListA[1]  = BasicBlock::NWL;
		vListB[0]  = BasicBlock::SEL;
		vListB[1]  = BasicBlock::NEL;
	} else if(patchIA == BasicBlock::EAST && patchIB == BasicBlock::WEST){
		makeCyclic(patchIB,patchIA,depth);
		return;
	} else if(patchIA == BasicBlock::SOUTH && patchIB == BasicBlock::NORTH){
		dir_perp   = 1;
		dir_long   = 0;
		vListA[0]  = BasicBlock::SWL;
		vListA[1]  = BasicBlock::SEL;
		vListB[0]  = BasicBlock::NWL;
		vListB[1]  = BasicBlock::NEL;
	} else if(patchIA == BasicBlock::NORTH && patchIB == BasicBlock::SOUTH){
		makeCyclic(patchIB,patchIA,depth);
		return;
	}
	labelList splPerp(2);
	const Foam::vector & n_perp  = moduleBase().cooSys->e(dir_perp);
	const Foam::vector & n_long  = moduleBase().cooSys->e(dir_long);
	const Foam::vector & n_up    = moduleBase().cooSys->e(2);
	label splineA                = SplineBlock::getSplineLabel(vListA[0],vListA[1]);
	label splineB                = SplineBlock::getSplineLabel(vListB[0],vListB[1]);
	splPerp[0]                   = SplineBlock::getSplineLabel(vListA[0],vListB[0]);
	splPerp[1]                   = SplineBlock::getSplineLabel(vListA[1],vListB[1]);

	// calculate goal mean heights, set boundary values:
	HashTable<scalar> hMean_ilv;
	List<pointField> hMeanSplines_il(moduleBase().blockNrs[dir_long]);
	for(label il = 0; il < moduleBase().blockNrs[dir_long]; il++){

		// point means:
		for(label v = 0; v < 2; v++){

			// v = 1 is only relevant for last block:
			if(v == 1 && il < moduleBase().blockNrs[dir_long] - 1) continue;

			// calc average height:
			word keyA = dir_long == 0 ?
					key(il,0,vListA[v]):
					key(0,il,vListA[v]);
			word keyB = dir_long == 0 ?
					key(il,moduleBase().blockNrs[dir_perp] - 1,vListB[v]):
					key(moduleBase().blockNrs[dir_perp] - 1,il,vListB[v]);
			point & pA = moduleBase().points[moduleBase().pointAdr_ijv[keyA]];
			point & pB = moduleBase().points[moduleBase().pointAdr_ijv[keyB]];
			scalar h_av = 0.5 * (
					dot(pA,n_up) + dot(pB,n_up)
				);

			// store:
			hMean_ilv.set(key(il,v),h_av);

			// set boundary points to average:
			pA += (h_av - dot(pA,n_up)) * n_up;
			pB += (h_av - dot(pB,n_up)) * n_up;

		}
	}


	// mean parallel moduleBase().splines:
	for(label il = 0; il < moduleBase().blockNrs[dir_long]; il++){

		// grab moduleBase().splines:
		word keyA = dir_long == 0 ?
				key(il,0):
				key(0,il);
		word keyB = dir_long == 0 ?
				key(il,moduleBase().blockNrs[dir_perp] - 1):
				key(moduleBase().blockNrs[dir_perp] - 1,il);
		TerrainBlock & blockA = moduleBase().blocks[moduleBase().blockAdr_ij[keyA]];
		TerrainBlock & blockB = moduleBase().blocks[moduleBase().blockAdr_ij[keyB]];
		Spline & splA         = blockA.getSpline(splineA);
		Spline & splB         = blockB.getSpline(splineB);
		label sPoints         = splA.size();

		// correct for possibly inverse point order in moduleBase().splines:
		label signA = 1;
		label signB = 1;
		scalar oA = dot(splA.last() - splA.first(),n_long);
		scalar oB = dot(splB.last() - splB.first(),n_long);
		if(oA < 0) signA = -1;
		if(oB < 0) signB = -1;

		// find average moduleBase().splines and fix them at boundaries:
		pointField hList_av(sPoints);
		forAll(hList_av,hI){

			// get spline points:
			label hIA  = signA > 0 ? hI : sPoints - 1 - hI;
			label hIB  = signB > 0 ? hI : sPoints - 1 - hI;
			point & pA = splA[hIA];
			point & pB = splB[hIB];

			// calc mean:
			hList_av[hI] = 0.5 * ( pA + pB );

			// adjust boundary moduleBase().splines:
			if(hI == 0){
				pA = blockA.getVertex(vListA[0]);
				pB = blockB.getVertex(vListB[0]);
			} else if(hI == sPoints - 1){
				pA = blockA.getVertex(vListA[1]);
				pB = blockB.getVertex(vListB[1]);
			} else {
				pA += dot(hList_av[hI] - pA,n_up) * n_up;
				pB += dot(hList_av[hI] - pB,n_up) * n_up;
			}

		}
		hMeanSplines_il[il] = hList_av;

	}
void TerrainManagerModuleCylinder::initCylinder
(
		const dictionary & dict
){

	// read dictionary:
	cylinderCentre_               = point(dict.lookup("centrePoint"));
	cylinderRadius_               = readScalar(dict.lookup("radius"));
	cylinderRadialBlocks_         = 1;//readLabel(dict.lookup("radialBlocks"));
	cylinderRadialGrading_        = readScalar(dict.lookup("radialGrading"));
	cylinderRadialCells_          = readLabel(dict.lookup("radialBlockCells"));
	cylinderFirstSectionStartDir_ = point(dict.lookup("firstSectionStartDirection"));
	cylinderSectionNr_            = readLabel(dict.lookup("numberOfSections"));

	// check consistency:
	point pCheck = moduleBase().domainBox_.pMin();
	scalar dist  = mag(pCheck - cylinderCentre_);
	if(dist > cylinderRadius_){
		Info << "\nTerrainManager: Error: cylinder radius smaller than distance from box corner SWL to cylinder centre." << endl;
		Info << "   p_SWL            = " << pCheck <<endl;
		Info << "   p_cylinderCentre = " << cylinderCentre_ << endl;
		Info << "   dist             = " << dist << endl;
		Info << "   radius           = " << cylinderRadius_ << endl;
		throw;
	}
	pCheck = moduleBase().domainBox_.pMin()
			+ moduleBase().domainBox_.lengths()[TerrainManager::BASE1] * moduleBase().coordinateSystem().e(TerrainManager::BASE1);
	dist   = mag(pCheck - cylinderCentre_);
	if(dist > cylinderRadius_){
		Info << "\nTerrainManager: Error: cylinder radius smaller than distance from box corner SEL to cylinder centre." << endl;
		Info << "   p_SEL            = " << pCheck <<endl;
		Info << "   p_cylinderCentre = " << cylinderCentre_ << endl;
		Info << "   dist             = " << dist << endl;
		Info << "   radius           = " << cylinderRadius_ << endl;
		throw;
	}
	pCheck = moduleBase().domainBox_.pMin()
			+ moduleBase().domainBox_.lengths()[TerrainManager::BASE2] * moduleBase().coordinateSystem().e(TerrainManager::BASE2);
	dist   = mag(pCheck - cylinderCentre_);
	if(dist > cylinderRadius_){
		Info << "\nTerrainManager: Error: cylinder radius smaller than distance from box corner NWL to cylinder centre." << endl;
		Info << "   p_NWL            = " << pCheck <<endl;
		Info << "   p_cylinderCentre = " << cylinderCentre_ << endl;
		Info << "   dist             = " << dist << endl;
		Info << "   radius           = " << cylinderRadius_ << endl;
		throw;
	}
	pCheck = moduleBase().domainBox_.pMin()
			+ moduleBase().domainBox_.lengths()[TerrainManager::BASE1] * moduleBase().coordinateSystem().e(TerrainManager::BASE1)
			+ moduleBase().domainBox_.lengths()[TerrainManager::BASE2] * moduleBase().coordinateSystem().e(TerrainManager::BASE2);
	dist   = mag(pCheck - cylinderCentre_);
	if(dist > cylinderRadius_){
		Info << "\nTerrainManager: Error: cylinder radius smaller than distance from box corner NEL to cylinder centre." << endl;
		Info << "   p_NEL            = " << pCheck <<endl;
		Info << "   p_cylinderCentre = " << cylinderCentre_ << endl;
		Info << "   dist             = " << dist << endl;
		Info << "   radius           = " << cylinderRadius_ << endl;
		throw;
	}

	// init blending:
	blending_ = ScalarBlendingFunction::New(dict.subDict("blendingFunction"));
}
	forAll(weights[TerrainManager::BASE2],wI){
		blockGrading[TerrainManager::BASE2][wI + 1] =
				moduleBase().domainBox_.lengths()[TerrainManager::BASE2] * weights[TerrainManager::BASE2][wI] / sum[TerrainManager::BASE2];
	}