/* 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