// Copyright (c) 2005 INRIA Sophia-Antipolis (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org). // // $URL: https://github.com/CGAL/cgal/blob/v5.1/Stream_lines_2/include/CGAL/Regular_grid_2.h $ // $Id: Regular_grid_2.h 0779373 2020-03-26T13:31:46+01:00 Sébastien Loriot // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // // Author(s) : Abdelkrim Mebarki #ifndef CGAL_REGULAR_GRID_2_H_ #define CGAL_REGULAR_GRID_2_H_ #include #include #include #include #include namespace CGAL { // The class Regular_grid_2 provides a rectangular visualization // domain, with a vector field defined on a regular grid, and also a // bilinear interpolation to extract the vector field values template class Regular_grid_2 { public: typedef Regular_grid_2 Vector_field_2; typedef StreamLinesTraits_2 Geom_traits; typedef typename StreamLinesTraits_2::FT FT; typedef typename StreamLinesTraits_2::Point_2 Point_2; typedef typename StreamLinesTraits_2::Vector_2 Vector_2; protected: boost::shared_ptr< std::vector > vector_field; inline int get_index(int i,int j) const; int number_of_samples_x; int number_of_samples_y; FT domain_size_x; FT domain_size_y; Vector_2 get_vector_field(const Point_2 & p) const; FT get_density_field(const Point_2 & p) const; bool is_in_samples(int i,int j) const; public: Regular_grid_2(int m, int n,const FT & x, const FT & y); // Regular_grid_2(); ~Regular_grid_2() {} inline typename Geom_traits::Iso_rectangle_2 bbox() const; std::pair get_field(const Point_2 & p) const { CGAL_streamlines_precondition(is_in_domain(p)); Vector_2 v = get_vector_field(p); FT density = get_density_field(p); return std::pair(v,density); } inline bool is_in_domain(const Point_2 & p) const; inline FT get_integration_step(const Point_2 &) const; inline FT get_integration_step() const; inline void set_field(int i, int j, const Vector_2 & v); inline Vector_2 get_field(int i, int j) const; inline std::pair get_dimension() { return std::pair(number_of_samples_x, number_of_samples_y); } inline std::pair get_size() { return std::pair(domain_size_x, domain_size_y); } inline FT container_value(int i) const { if (i < 2*number_of_samples_x*number_of_samples_y) return (*vector_field)[i]; else return 0.0; } }; template inline typename Regular_grid_2::Geom_traits::Iso_rectangle_2 Regular_grid_2::bbox() const { return typename Geom_traits::Iso_rectangle_2(0.0, 0.0, domain_size_x, domain_size_y); } template inline int Regular_grid_2::get_index(int i, int j) const { return 2*(number_of_samples_x*j + i); } template Regular_grid_2::Regular_grid_2(int m, int n,const FT & x, const FT & y) { number_of_samples_x = m; number_of_samples_y = n; domain_size_x = x; domain_size_y = y; vector_field = boost::shared_ptr >(new std::vector(number_of_samples_x*number_of_samples_y* 2)); } template inline typename Regular_grid_2::Vector_2 Regular_grid_2::get_field(int i, int j) const { CGAL_streamlines_precondition(is_in_samples(i,j)); int index = get_index(i,j); return Vector_2((*vector_field)[index], (*vector_field)[index+1]); } template inline void Regular_grid_2::set_field(int i, int j, const Vector_2 & v) { CGAL_streamlines_precondition(is_in_samples(i,j)); int index = get_index(i,j); (*vector_field)[index++] = v.x(); (*vector_field)[index] = v.y(); } template inline bool Regular_grid_2::is_in_domain(const Point_2 & p) const { return ((p.x()>=0.0) && (p.x()<=domain_size_x) && (p.y()>=0.0) && (p.y()<=domain_size_y)); } template bool Regular_grid_2::is_in_samples(int i, int j) const { return ((i>=0) && (i<=number_of_samples_x-1) && (j>=0) && (j<=number_of_samples_y-1)); } template typename Regular_grid_2::Vector_2 Regular_grid_2::get_vector_field(const Point_2 & p) const { FT fXv,fYv; FT x = (p.x() / domain_size_x) * (number_of_samples_x-1); FT y = (p.y() / domain_size_y) * (number_of_samples_y-1); int i = (int) x; int j = (int) y; FT xfract = x - (FT) i; FT yfract = y - (FT) j; int iIndex_1 = get_index(i,j); int iIndex_2 = get_index(i+1,j); int iIndex_3 = get_index(i,j+1); int iIndex_4 = get_index(i+1,j+1); FT x00 = container_value(iIndex_1); FT x01 = container_value(iIndex_2); FT x10 = container_value(iIndex_3); FT x11 = container_value(iIndex_4); FT x0 = x00 + xfract * (x01 - x00); FT x1 = x10 + xfract * (x11 - x10); fXv = x0 + yfract * (x1 - x0); iIndex_1++; iIndex_2++; iIndex_3++; iIndex_4++; FT y00 = container_value(iIndex_1); FT y01 = container_value(iIndex_2); FT y10 = container_value(iIndex_3); FT y11 = container_value(iIndex_4); FT y0 = y00 + xfract * (y01 - y00); FT y1 = y10 + xfract * (y11 - y10); fYv = y0 + yfract * (y1 - y0); // normalization step FT normal = sqrt((fXv)*(fXv) + (fYv)*(fYv)); fXv = fXv / normal; fYv = fYv / normal; Vector_2 v = Vector_2(fXv, fYv); return v; } template typename Regular_grid_2::FT Regular_grid_2::get_density_field(const Point_2 & ) const { return 1.0; } template inline typename Regular_grid_2::FT Regular_grid_2::get_integration_step(const Point_2 &) const { return 1.0; } template inline typename Regular_grid_2::FT Regular_grid_2::get_integration_step() const { return 1.0; } } //namespace CGAL #endif