/* This file is part of the OpenLB library
*
* Copyright (C) 2014-2016 Cyril Masquelier, Mathias J. Krause, Benjamin Förster
* E-mail contact: info@openlb.net
* The most recent release of OpenLB can be downloaded at
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef INDICATOR_BASE_F_2D_HH
#define INDICATOR_BASE_F_2D_HH
#include
#include "indicatorBaseF2D.h"
#include "math.h"
namespace olb {
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
template
IndicatorF1D::IndicatorF1D()
: GenericF(1, 1)
{ }
template
Vector& IndicatorF1D::getMin()
{
return _myMin;
}
template
Vector& IndicatorF1D::getMax()
{
return _myMax;
}
template
IndicatorF2D::IndicatorF2D()
: GenericF(1, 2)
{ }
template
Vector& IndicatorF2D::getMin()
{
return _myMin;
}
template
Vector& IndicatorF2D::getMax()
{
return _myMax;
}
template
bool IndicatorF2D::distance(S& distance, const Vector& origin, const Vector& direction, int iC)
{
bool originValue;
(*this)(&originValue, origin.data);
Vector currentPoint(origin);
S precision = .0001;
S pitch = 0.5;
bool currentValue;
(*this)(¤tValue, currentPoint.data);
while (currentValue == originValue && isInsideBox(currentPoint)) {
currentPoint += direction;
(*this)(¤tValue, currentPoint.data);//changed until first point on the other side (inside/outside) is found
}
if (!isInsideBox(currentPoint) && !originValue) {
return false;
}
while (pitch >= precision) {
if (!isInsideBox(currentPoint) && originValue) {
currentPoint -= pitch * direction;
pitch /= 2.;
} else {
(*this)(¤tValue, currentPoint.data);
if (currentValue == originValue) {
currentPoint += pitch * direction;
pitch /= 2.;
} else {
currentPoint-= pitch * direction;
pitch /= 2.;
}
}
}
distance = (currentPoint - origin).norm();
return true;
}
// given origin (inside) and direction first calculate distance to surface
// go -90� to direction using POS as origin and check if inside/outside
// if inside rotate outward, if outside rotate inward
// iterate until close enough to surface, then store point1
// repeat for 90� and store point2
// use point1 and point2 on surface to calculate normal
template
bool IndicatorF2D::normal(Vector& normal, const Vector& origin, const Vector& direction, int iC)
{
//OstreamManager clout(std::cout,"normal");
//clout << "Calculating IndicatorF2D Normal " << endl;
bool originValue;
(*this)(&originValue, origin.data);
Vector currentPoint(origin);
S precision = .0001;
S dist;
distance(dist, origin, direction, iC);
Vector POS(origin + dist*direction*(1/const_cast&> (direction).norm())); //Point on Surface
Vector point1;
Vector point2;
bool currentValue;
for (int n: {
-90,90
}) { //std::range n = {-90, 90};
S rotate(n);
S pitch(rotate/2.);
while (std::abs(pitch) >= precision) {
S theta(rotate*M_PI/180.);
Vector vec(std::cos(theta)*direction[0]+std::sin(theta)*direction[1],-std::sin(theta)*direction[0]+std::cos(theta)*direction[1]);
currentPoint = POS + vec;
(*this)(¤tValue, currentPoint.data);
if (currentValue == originValue) {
rotate -= pitch;
} else {
rotate += pitch;
}
pitch /= 2.;
}
if (n == -90) {
point1 = currentPoint;
} else if (n == 90) {
point2 = currentPoint;
}
}
// Calculate Normal from point1 and point2
normal = Vector((point2[1] - point1[1]), (-1)*(point2[0] - point1[0]));
//S dist;
//Vector dist;
//distance(dist, origin, direction, iC);
//normal = Vector(dist);
return true;
}
template
bool IndicatorF2D::isInsideBox(Vector point)
{
return point >= _myMin && point <= _myMax;
}
template
bool IndicatorF2D::operator() (const S input[])
{
bool output;
this->operator()(&output, input);
return output;
}
template
IndicatorIdentity2D::IndicatorIdentity2D(std::shared_ptr> f)
: _f(f)
{
this->_myMin = _f->getMin();
this->_myMax = _f->getMax();
}
template
bool IndicatorIdentity2D::operator() (bool output[1], const S input[2])
{
return (_f)->operator()(output, input);
}
} // namespace olb
#endif