123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904 |
- //**********************************************************************************//
- // Copyright (C) 2009-2018 Ovidio Pena <ovidio@bytesfall.com> //
- // Copyright (C) 2013-2018 Konstantin Ladutenko <kostyfisik@gmail.com> //
- // //
- // This file is part of scattnlay //
- // //
- // 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 3 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. //
- // //
- // The only additional remark is that we expect that all publications //
- // describing work using this software, or all commercial products //
- // using it, cite at least one of the following references: //
- // [1] O. Pena and U. Pal, "Scattering of electromagnetic radiation by //
- // a multilayered sphere," Computer Physics Communications, //
- // vol. 180, Nov. 2009, pp. 2348-2354. //
- // [2] K. Ladutenko, U. Pal, A. Rivera, and O. Pena-Rodriguez, "Mie //
- // calculation of electromagnetic near-field for a multilayered //
- // sphere," Computer Physics Communications, vol. 214, May 2017, //
- // pp. 225-230. //
- // //
- // You should have received a copy of the GNU General Public License //
- // along with this program. If not, see <http://www.gnu.org/licenses/>. //
- //**********************************************************************************//
- // @brief Generates points for integration on sphere surface
- #include <cmath>
- #include <complex>
- #include <iostream>
- #include <set>
- #include <stdexcept>
- #include <vector>
- #include "shell-generator.hpp"
- namespace shell_generator {
- template<class T> inline T pow2(const T value) {return value*value;}
- // ********************************************************************** //
- // ********************************************************************** //
- // ********************************************************************** //
- template<typename T, typename A> inline
- T dot(std::vector<T,A> const& a,
- std::vector<T,A> const& b) {
- return a[0]*b[0]+a[1]*b[1]+a[2]*b[2];
- // return std::inner_product(begin(a), end(a), begin(b),
- // static_cast<T>(0.0));
- }
- template<typename T, typename A> inline
- std::vector<T> cross(std::vector<T,A> const& a,
- std::vector<T,A> const& b) {
- std::vector<T> c = {
- a[1]*b[2]-a[2]*b[1],
- a[2]*b[0]-a[0]*b[2],
- a[0]*b[1]-a[1]*b[0]
- };
- return c;
- }
- // template<typename T, typename A> inline
- // std::vector<std::vector<T> > dyadic(std::vector<T,A> const& a,
- // std::vector<T,A> const& b) {
- // std::vector<std::vector<T> > c = {
- // {a[0]*b[0], a[0]*b[1], a[0]*b[2]},
- // {a[1]*b[0], a[1]*b[1], a[1]*b[2]},
- // {a[2]*b[0], a[2]*b[1], a[2]*b[2]}
- // };
- // return c;
- // }
- // template<typename T, typename A> inline
- // std::vector<std::vector<T>,A >
- // operator+(std::vector<std::vector<T>,A > const& a,
- // std::vector<std::vector<T>,A > const& b) {
- // std::vector<std::vector<T>,A > c = {
- // {a[0][0]+b[0][0], a[0][1]+b[0][1], a[0][2]+b[0][2]},
- // {a[1][0]+b[1][0], a[1][1]+b[1][1], a[1][2]+b[1][2]},
- // {a[2][0]+b[2][0], a[2][1]+b[2][1], a[2][2]+b[2][2]}
- // };
- // return c;
- // }
- template<typename T, typename A> inline
- std::vector<T,A >
- operator+(std::vector<T,A > const& a,
- std::vector<T,A > const& b) {
- std::vector<T,A > c = {a[0]+b[0],
- a[1]+b[1],
- a[2]+b[2]};
- return c;
- }
- template<typename T, typename A> inline
- std::vector<T,A >
- operator-(std::vector<T,A > const& a,
- std::vector<T,A > const& b) {
- std::vector<T,A > c = {a[0]-b[0],
- a[1]-b[1],
- a[2]-b[2]};
- return c;
- }
- // template<typename T, typename A> inline
- // std::vector<std::vector<T>,A >
- // operator-(std::vector<std::vector<T>,A > const& a,
- // std::vector<std::vector<T>,A > const& b) {
- // std::vector<std::vector<T>,A > c = {
- // {a[0][0]-b[0][0], a[0][1]-b[0][1], a[0][2]-b[0][2]},
- // {a[1][0]-b[1][0], a[1][1]-b[1][1], a[1][2]-b[1][2]},
- // {a[2][0]-b[2][0], a[2][1]-b[2][1], a[2][2]-b[2][2]}
- // };
- // return c;
- // }
- // template<typename T, typename A> inline
- // std::vector<std::vector<T>,A >
- // real(std::vector<std::vector<T>,A > const& a) {
- // std::vector<std::vector<T>,A > c = {
- // {a[0][0].real(), a[0][1].real(), a[0][2].real()},
- // {a[1][0].real(), a[1][1].real(), a[1][2].real()},
- // {a[2][0].real(), a[2][1].real(), a[2][2].real()}
- // };
- // return c;
- // }
- template<typename T, typename A> inline
- std::vector<T>
- real(std::vector<std::complex<T>,A > const& a) {
- std::vector<T> c = {a[0].real(),
- a[1].real(),
- a[2].real()};
- return c;
- }
- template<typename T, typename A> inline
- T real(std::complex<T> const& a) {
- return a.real();
- }
- template<typename T, typename A>
- std::vector< std::complex<T>,A > vconj(std::vector< std::complex<T>,A > const& a) {
- std::vector< std::complex<T>,A > b = {std::conj(a[0]),
- std::conj(a[1]),
- std::conj(a[2]) };
- // for (auto elem : a)
- // b.push_back(std::conj(elem));
- return b;
- }
- template<typename T1, typename T2, typename A>
- std::vector<T2,A> operator*(T1 const& a, std::vector< T2,A > const& b) {
- std::vector<T2,A > c = {a*b[0],
- a*b[1],
- a*b[2]};
- // for (auto elem : b)
- // c.push_back(a*elem);
- return c;
- }
- template<typename T1, typename T2, typename A>
- std::vector<T2,A> operator/(std::vector< T2,A > const& b, T1 const& a) {
- std::vector<T2,A > c = {b[0]/a,
- b[1]/a,
- b[2]/a};
- // for (auto elem : b)
- // c.push_back(a*elem);
- return c;
- }
-
-
- // ********************************************************************** //
- // ********************************************************************** //
- // ********************************************************************** //
- // ********************************************************************** //
- // ********************************************************************** //
- // ********************************************************************** //
- void ShellGenerator::RotateZ(double angle) {
- for(auto& p : vertices_) {
- double x,y;
- x = std::cos(angle)*p[0]-std::sin(angle)*p[1];
- y = std::sin(angle)*p[0]+std::cos(angle)*p[1];
- p[0] = x;
- p[1] = y;
- }
- }
- // ********************************************************************** //
- // ********************************************************************** //
- // ********************************************************************** //
- void ShellGenerator::RotateY(double angle) {
- for(auto& p : vertices_) {
- double x,z;
- x = std::cos(angle)*p[0]+std::sin(angle)*p[2];
- z = -std::sin(angle)*p[0]+std::cos(angle)*p[2];
- p[0] = x;
- p[2] = z;
- }
- }
- // ********************************************************************** //
- // ********************************************************************** //
- // ********************************************************************** //
- void ShellGenerator::RotateX(double angle) {
- for(auto& p : vertices_) {
- double y,z;
- y = std::cos(angle)*p[1]-std::sin(angle)*p[2];
- z = std::sin(angle)*p[1]+std::cos(angle)*p[2];
- p[1] = y;
- p[2] = z;
- }
- }
- // ********************************************************************** //
- // ********************************************************************** //
- // ********************************************************************** //
- void ShellGenerator::MoveX(double delta) {
- for(auto& p : vertices_) {
- p[0] += delta;
- }
- }
- // ********************************************************************** //
- // ********************************************************************** //
- // ********************************************************************** //
- void ShellGenerator::MoveY(double delta) {
- for(auto& p : vertices_) {
- p[1] += delta;
- }
- }
- // ********************************************************************** //
- // ********************************************************************** //
- // ********************************************************************** //
- void ShellGenerator::MoveZ(double delta) {
- for(auto& p : vertices_) {
- p[2] += delta;
- }
- }
- // ********************************************************************** //
- // ********************************************************************** //
- // ********************************************************************** //
- double ShellGenerator::IntegrateGaussSimple(double charge, double shift) {
- double integral = 0.0;
- // return field at point p from the charge, located at (shift, 0,0)
- auto field = [](double charge, double shift, std::vector<double> p){
- double r = std::sqrt(pow2(p[0]-shift) + pow2(p[1]) + pow2(p[2]) );
- //std::cout << "r: " << r << std::endl;
- const double pi = 3.1415926535897932384626433832795;
- double ampl = charge/(4.0*pi*pow2(r));
- std::vector<double> field = {ampl*(p[0]-shift)/r, ampl*(p[1])/r, ampl*(p[2])/r};
- return field;
- };
- //simple
- // for (auto vert :vertices_) {
- for (long unsigned int i = 0; i<face_centers_.size(); ++i) {
- auto vert = face_centers_[i];
- auto E0 = field(charge, shift, vert);
- // std::cout << "E0: ";
- for (auto component : E0) std::cout << component << " ";
- // std::cout << std::endl;
- // Vector to unit product
- double r = norm(vert);
- std::vector<double> unit = { vert[0]/r, vert[1]/r, vert[2]/r};
- // std::cout << norm(unit) << std::endl;
- for (int j =0; j < 3; ++j)
- integral += per_face_area_[i]*unit[j]*E0[j];
- }
- return integral;
- }
- // ********************************************************************** //
- // ********************************************************************** //
- // ********************************************************************** //
- double ShellGenerator::IntegrateGauss(double charge, double shift) {
- if (faces_.size() == 0)
- throw std::invalid_argument("Error! Faces were not initialized!\nSee IntegrateGaussSimple for using vertices information only.");
- double integral = 0.0;
- // return field at point p from the charge, located at (shift, 0,0)
- auto field = [](double charge, double shift, std::vector<double> p){
- double r = std::sqrt(pow2(p[0]-shift) + pow2(p[1]) + pow2(p[2]) );
- const double pi = 3.1415926535897932384626433832795;
- double ampl = charge/(4.0*pi*pow2(r));
- std::vector<double> field = {ampl*(p[0]-shift)/r, ampl*(p[1])/r, ampl*(p[2])/r};
- return field;
- };
-
- for(const auto face : faces_){
- std::vector<double> mean_vector = {0.0, 0.0, 0.0}, mean_point = {0.0, 0.0, 0.0};
- //Get mean
- for (int vert = 0; vert<3; ++vert) { //vertice
- auto point = vertices_[face[vert]];
- auto E0 = field(charge, shift, point);
- for (int i=0; i<3; ++i) {
- mean_vector[i] += E0[i]/3.0;
- mean_point[i] += point[i]/3.0;
- }
- }
- // Vector to unit product
- double r = norm(mean_point);
- std::vector<double> unit = { mean_point[0]/r, mean_point[1]/r, mean_point[2]/r};
- // std::cout << norm(unit) << std::endl;
- for (int i =0; i < 3; ++i)
- integral += face_area_*
- unit[i]*mean_vector[i];
- }
- return integral;
- }
- // ********************************************************************** //
- // ********************************************************************** //
- // ********************************************************************** //
-
- std::vector<double> ShellGenerator::IntegrateByComp() {
- std::vector<double> integral = {0.0, 0.0, 0.0};
- for (unsigned int i=0; i<E_.size(); ++i) {
- auto E = E_[i];
- auto H = H_[i];
- auto vert = face_centers_[i];
- double r = norm(vert);
- std::vector<double> n = { vert[0]/r, vert[1]/r, vert[2]/r};
- const std::vector< std::vector<double> > d = {{1.0, 0.0, 0.0},
- {0.0, 1.0, 0.0},
- {0.0, 0.0, 1.0}};
-
- std::vector<double> F = {0.0, 0.0, 0.0};
- std::complex<double> S(0.0);
- for (int ii = 0; ii < 3; ++ii)
- S += E[ii]*std::conj(E[ii]) + H[ii]*std::conj(H[ii]);
- std::vector< std::vector<std::complex<double> > >
- T = {{0.0, 0.0, 0.0},
- {0.0, 0.0, 0.0},
- {0.0, 0.0, 0.0}};
- for (int i = 0; i < 3; ++i) {
- for (int j = 0; j < 3; ++j) {
- T[i][j] = E[i]*std::conj(E[j]) + H[i]*std::conj(H[j])
- -1.0/2.0*S*d[i][j];
- F[i] += (1/(2.0/* *4.0*pi */))*real(T[i][j]*n[j]);
- }
- }
- integral = integral + per_face_area_[i]*F;
- }
- return integral;
- }
- // ********************************************************************** //
- // ********************************************************************** //
- // ********************************************************************** //
-
- std::vector<double> ShellGenerator::IntegrateByCompReal() {
- std::vector<double> integral = {0.0, 0.0, 0.0};
- for (unsigned int i=0; i<E_.size(); ++i) {
- auto E = E_[i];
- auto H = H_[i];
- auto vert = face_centers_[i];
- double r = norm(vert);
- std::vector<double> n = { vert[0]/r, vert[1]/r, vert[2]/r};
- const std::vector< std::vector<double> > d = {{1.0, 0.0, 0.0},
- {0.0, 1.0, 0.0},
- {0.0, 0.0, 1.0}};
-
- std::vector<double> F = {0.0, 0.0, 0.0};
- std::complex<double> S(0.0);
- for (int ii = 0; ii < 3; ++ii)
- S += pow2(real(E[ii])) + pow2(real(H[ii]));
- std::vector< std::vector<std::complex<double> > >
- T = {{0.0, 0.0, 0.0},
- {0.0, 0.0, 0.0},
- {0.0, 0.0, 0.0}};
- for (int i = 0; i < 3; ++i) {
- for (int j = 0; j < 3; ++j) {
- T[i][j] = real(E[i])*real(E[j]) + real(H[i])*real(H[j])
- -1.0/2.0*S*d[i][j];
- F[i] += (1/(2.0/* *4.0*pi */))*real(T[i][j]*n[j]);
- }
- }
- integral = integral + per_face_area_[i]*F;
- }
- return integral;
- }
- // ********************************************************************** //
- // ********************************************************************** //
- // ********************************************************************** //
-
- std::vector<double> ShellGenerator::IntegrateByFaces() {
- std::vector<double> integral = {0.0, 0.0, 0.0};
- //simple
- for (long unsigned int i=0; i<E_.size(); ++i) {
- //std::cout << i << " ";
- auto E = E_[i];
- //auto H = 377.0*H_[i];
- auto H = H_[i];
- // auto Es = Es_[i];
- // auto Hs = Hs_[i];
-
- auto vert = face_centers_[i];
- // Vector to unit product
- double r = norm(vert);
- //std::vector<std::complex<double> > unit = { vert[0]/r, vert[1]/r, vert[2]/r};
- // std::cout << norm(unit) << std::endl;
- //const double pi = 3.1415926535897932384626433832795;
- // std::vector<double> P = (1/(2.0))
- // *real(
- // dot(unit,E)*vconj(E) +
- // dot(unit,H)*vconj(H) +
- // (-1.0/2.0)*(dot(E,vconj(E))
- // +dot(H,vconj(H))
- // )*unit
- // );
- // std::vector<double> P = (1/(2.0))
- // *real(
- // Es[0]*vconj(E) +
- // Hs[0]*vconj(H) +
- // (-1.0/2.0)*(dot(E,vconj(E))
- // +dot(H,vconj(H))
- // )*unit
- // );
- // std::vector<double> P = (1/(2.0))
- // *(
- // real(dot(unit,E)*vconj(E)) +
- // real(dot(unit,H)*vconj(H))) +
- // (-1.0/4.0)*(dot(E,vconj(E))*unit
- // +dot(H,vconj(H))*unit
- // )
-
- // );
- // auto
- // std::cout <<"E "<<E[0]<<", "<< E[1] <<", "<<E[2] << std::endl;
- // std::cout <<"H "<<H[0]<<", "<< H[1] <<", "<<H[2] << std::endl;
- // std::cout <<"vert "<<vert[0]<<", "<< vert[1] <<", "<<vert[2] << std::endl<<std::endl;
- //integral = integral + per_face_area_[i]*P;
- // // Test Poynting vector integration in real components -- WRONG
- // std::vector<double> unit = { vert[0]/r, vert[1]/r, vert[2]/r};
- // std::vector<double> P = (1/(2.0))
- // *(cross((real(E)),real(H)));
- // integral[0] = integral[0] + per_face_area_[i]*dot(P,unit);
- // Test Poynting vector integration
- std::vector<double> unit = { vert[0]/r, vert[1]/r, vert[2]/r};
- std::vector<double> P = (1/(2.0))
- *real(cross(E,vconj(H)));
- //integral[0] = integral[0] + per_face_area_[i]*dot(P,unit);
- integral = integral + per_face_area_[i]*P;
- }
- return integral;
- }
-
- // ********************************************************************** //
- // ********************************************************************** //
- // ********************************************************************** //
- std::vector<double> ShellGenerator::Integrate() {
- std::vector<double> integral = {0.0, 0.0, 0.0};
- //simple
- for (unsigned int i=0; i<E_.size(); ++i) {
- auto E = E_[i];
- //auto H = 377.0*H_[i];
- auto H = H_[i];
- auto vert = vertices_[i];
- // Vector to unit product
- double r = norm(vert);
- std::vector<std::complex<double> > unit = { vert[0]/r, vert[1]/r, vert[2]/r};
- // std::cout << norm(unit) << std::endl;
- //const double pi = 3.1415926535897932384626433832795;
- std::vector<double> P = (1/(2.0))
- *real(
- dot(unit,E)*vconj(E) +
- dot(unit,H)*vconj(H) +
- (-1.0/2.0)*(dot(E,vconj(E))
- +dot(H,vconj(H))
- )*unit
- );
- // auto std::cout <<"E "<<E[0]<<", "<< E[1] <<", "<<E[2] << std::endl;
- // std::cout <<"H "<<H[0]<<", "<< H[1] <<", "<<H[2] << std::endl;
- // std::cout <<"vert "<<vert[0]<<", "<< vert[1] <<", "<<vert[2] << std::endl<<std::endl;
- integral = integral + per_vertice_area_*P;
- }
- return integral;
- }
- // ********************************************************************** //
- // ********************************************************************** //
- // ********************************************************************** //
- std::vector< std::vector<double> > ShellGenerator::GetVerticesT() {
- std::vector< std::vector<double> > vertices_t;
- vertices_t.resize(3);
- for(const auto vert : vertices_){
- vertices_t[0].push_back(vert[0]);
- vertices_t[1].push_back(vert[1]);
- vertices_t[2].push_back(vert[2]);
- }
- return vertices_t;
- }
- // ********************************************************************** //
- // ********************************************************************** //
- // ********************************************************************** //
- std::vector< std::vector<double> > ShellGenerator::GetFaceCentersT() {
- EvalFaces();
- std::vector< std::vector<double> > vertices_t;
- vertices_t.resize(3);
- for(const auto vert : face_centers_){
- vertices_t[0].push_back(vert[0]);
- vertices_t[1].push_back(vert[1]);
- vertices_t[2].push_back(vert[2]);
- }
- return vertices_t;
- }
- // ********************************************************************** //
- // ********************************************************************** //
- // ********************************************************************** //
- double ShellGenerator::norm(std::vector<double> a){
- double norm_value = 0;
- for (auto coord:a)
- norm_value += pow2(coord);
- return std::sqrt(norm_value);
- }
- // ********************************************************************** //
- // ********************************************************************** //
- // ********************************************************************** //
- void ShellGenerator::Rescale(double scale) {
- for(auto& vert : vertices_){
- double factor = norm(vert);
- //std::cout<< factor <<std::endl;
- for (auto &coord:vert) {
- coord = coord*scale/factor;
- }
- //std::cout << " " << norm(vert) << " ";
- }
- const double pi = 3.1415926535897932384626433832795;
- double area = 4.0*pi*pow2(scale);
- //face_area_ = area/faces_.size();
- per_vertice_area_ = area/vertices_.size();
- //std::cout << "Per verice area: " << per_vertice_area_ << std::endl;
- }
- // ********************************************************************** //
- // ********************************************************************** //
- // ********************************************************************** //
- void ShellGenerator::PrintVerts() {
- std::cout << "Verts coords:" << std::endl;
- for(auto vert : vertices_){
- std::cout <<"(";
- for (auto coord:vert) std::cout<<coord<<",";
- std::cout <<"),";
- }
- std::cout << std::endl;
- }
- // ********************************************************************** //
- // ********************************************************************** //
- // ********************************************************************** //
- void ShellGenerator::EvalFaces() {
- face_centers_.clear();
- per_face_area_.clear();
- for (auto face : faces_) {
- std::set<long unsigned int> edge_points;
- for (auto edge : face) {
- edge_points.insert(edges_[edge][0]);
- edge_points.insert(edges_[edge][1]);
- }
- std::vector<double> mid_point({0.0, 0.0, 0.0});
- for (auto point : edge_points) {
- mid_point = mid_point + vertices_[point];
- }
- mid_point = mid_point/3.0;
- face_centers_.push_back(mid_point);
- std::vector<long unsigned int> v_edge_points( edge_points.begin(),
- edge_points.end() );
- auto vec_a = vertices_[v_edge_points[1]] - vertices_[v_edge_points[0]];
- auto vec_b = vertices_[v_edge_points[2]] - vertices_[v_edge_points[0]];
- auto area = norm(cross(vec_a, vec_b))/2.0;
- per_face_area_.push_back(area);
- //std::cout << "Area " <<area<<std::endl;
- } // end for face in faces_
- double total_flat_area = 0.0;
- for (auto face:per_face_area_)
- total_flat_area += face;
- auto scale = norm(vertices_[0]);
- const double pi = 3.1415926535897932384626433832795;
- double area = 4.0*pi*pow2(scale);
- face_area_ = area/faces_.size();
- double area_scale = area/total_flat_area;
- for (auto& face:per_face_area_)
- face *= area_scale;
-
-
- for(auto& vert : face_centers_){
- double factor = norm(vert);
- //std::cout<< factor <<std::endl;
- for (auto &coord:vert) {
- coord*=scale/factor;
- }
- //std::cout << " " << norm(vert) << " ";
- }
- // std::cout << "total face centers: " << face_centers_.size()
- // << " scale " << scale
- // << " face_norm " << norm(face_centers_[0])
- // << " area-int " << face_area_
- // << std::endl;
- }
- // ********************************************************************** //
- // ********************************************************************** //
- // ********************************************************************** //
- void ShellGenerator::Refine() {
- for (auto &edge : edges_) {
- auto p0 = vertices_[edge[0]];
- auto p1 = vertices_[edge[1]];
- std::vector<double> new_point = {
- (p0[0]+p1[0])/2.0,
- (p0[1]+p1[1])/2.0,
- (p0[2]+p1[2])/2.0};
- vertices_.push_back(new_point);
- edge.push_back(vertices_.size()-1); // the last index is for the new mid-point
- }
- std::cout << "new verts: " << vertices_.size() <<std::endl;
- // std::cout << "extended edges:" <<std::endl;
- // for (auto edge : edges_) {
- // std::cout<< "\t"<< edge[0]<< "\t"<< edge[1]<< "\t"<< edge[2]<<std::endl;
- // }
- refined_edges_.clear();
- for (auto edge : edges_) {
- // Important! New (refined) point goes the last!
- std::vector<long unsigned int> edge_a = {edge[0],edge[2]};
- std::vector<long unsigned int> edge_b = {edge[1],edge[2]};
- refined_edges_.push_back(edge_a);
- refined_edges_.push_back(edge_b);
- }
- // Now we need to count edges inside old faces.
- refined_faces_.clear();
- for (auto face : faces_) {
- auto point_a = edges_[face[0]][2];
- auto point_b = edges_[face[1]][2];
- auto point_c = edges_[face[2]][2];
- // std::cout << "\tedges_old: " <<face[0]<<" "<<face[1]<<" "<<face[2]<<" "<<std::endl;
- // std::cout << "\tpoints_old_edge0: " <<edges_[face[0]][0]<<" "<<edges_[face[0]][1]<<" "<<edges_[face[0]][2]<<" "<<std::endl;
- // std::cout << "\tpoints_old_edge0: " <<edges_[face[1]][0]<<" "<<edges_[face[1]][1]<<" "<<edges_[face[1]][2]<<" "<<std::endl;
- // std::cout << "\tpoints_old_edge0: " <<edges_[face[2]][0]<<" "<<edges_[face[2]][1]<<" "<<edges_[face[2]][2]<<" "<<std::endl;
- // std::cout<<"\trefined points: "<<point_a<<" "<<point_b<<" "<<point_c<<std::endl;
- std::vector<long unsigned int> edge_c = {point_a, point_b};
- std::vector<long unsigned int> edge_a = {point_b, point_c};
- std::vector<long unsigned int> edge_b = {point_c, point_a};
- refined_edges_.push_back(edge_a);
- auto edge_a_index = refined_edges_.size()-1;
- refined_edges_.push_back(edge_b);
- auto edge_b_index = refined_edges_.size()-1;
- refined_edges_.push_back(edge_c);
- auto edge_c_index = refined_edges_.size()-1;
- /*
- // /\ contrcloсkwise
- // c 1
- // 0 b
- // /__a___\ edge_a
- // /\ /\
- // c \ / 0
- // 1 \ / b
- // edge_0a /__0a__\/__1a__\ edge_1a
- //
- // remember! In edge_0a the refined point is [1], etc.
- */
- auto edge_0a = refined_edges_[2*face[0]];
- auto edge_1a = refined_edges_[2*face[0]+1];
- auto edge_0b = refined_edges_[2*face[1]];
- auto edge_1b = refined_edges_[2*face[1]+1];
- auto edge_0c = refined_edges_[2*face[2]];
- auto edge_1c = refined_edges_[2*face[2]+1];
- auto edge_0a_index = 2*face[0];
- auto edge_1a_index = 2*face[0]+1;
- auto edge_0b_index = 2*face[1];
- auto edge_1b_index = 2*face[1]+1;
- auto edge_0c_index = 2*face[2];
- auto edge_1c_index = 2*face[2]+1;
- // Orient:
- // Try contrcloсkwise:
- bool isClockwise = false, is_b_swapped = false, is_c_swapped=false;
-
- if (edge_0a[0]!=edge_1c[0]) {
- edge_1c.swap(edge_0c);
- is_c_swapped = !is_c_swapped;
- }
- if (edge_1a[0]!=edge_0b[0]) {
- edge_0b.swap(edge_1b);
- is_b_swapped = !is_b_swapped;
- }
- if (edge_1b[0]!=edge_0c[0]) {
- isClockwise = true;
- //Try clockwise:
- if (edge_0a[0]!=edge_1b[0]) {
- edge_1b.swap(edge_0b);
- is_b_swapped = !is_b_swapped;
- }
- if (edge_1a[0]!=edge_0c[0]) {
- edge_0c.swap(edge_1c);
- is_c_swapped = !is_c_swapped;
- }
- if (edge_1c[0]!=edge_0b[0])
- throw std::invalid_argument("Error! Unable to orient edges of refined face!\n");
- }
- if (is_b_swapped) {
- edge_1b_index = 2*face[1];
- edge_0b_index = 2*face[1]+1;
- }
- if (is_c_swapped) {
- edge_1c_index = 2*face[2];
- edge_0c_index = 2*face[2]+1;
- }
- /*
- // /\ clockwise
- // b 1
- // 0 c
- // /__a___\ edge_a
- // /\ /\
- // b \ / 0
- // 1 \ / c
- // edge_0a /__0a__\/__1a__\ edge_1a
- //
- */
- //Build new facets:
- // if isClockwise
- std::vector<long unsigned int> face1({edge_0a_index, edge_1b_index, edge_c_index});
- std::vector<long unsigned int> face2({edge_1a_index, edge_0c_index, edge_b_index});
- std::vector<long unsigned int> face3({edge_0b_index, edge_1c_index, edge_a_index});
- std::vector<long unsigned int> face4({edge_a_index, edge_b_index, edge_c_index});
- if (!isClockwise) {
- face1 = std::vector<long unsigned int>({edge_0a_index, edge_1c_index, edge_b_index});
- face2 = std::vector<long unsigned int>({edge_1a_index, edge_0b_index, edge_c_index});
- face3 = std::vector<long unsigned int>({edge_1b_index, edge_0c_index, edge_a_index});
- face4 = std::vector<long unsigned int>({edge_a_index, edge_b_index, edge_c_index});
- }
- // std::cout<< "\tface1\t"<< face1[0]<< "\t"<< face1[1]<< "\t"<< face1[2]<<std::endl;
- // std::cout<< "\tface2\t"<< face2[0]<< "\t"<< face2[1]<< "\t"<< face2[2]<<std::endl;
- // std::cout<< "\tface3\t"<< face3[0]<< "\t"<< face3[1]<< "\t"<< face3[2]<<std::endl;
- // std::cout<< "\tface4\t"<< face4[0]<< "\t"<< face4[1]<< "\t"<< face4[2]<<std::endl;
- refined_faces_.push_back(face1);
- refined_faces_.push_back(face2);
- refined_faces_.push_back(face3);
- refined_faces_.push_back(face4);
- // std::cout<<"ref edges size: " << refined_edges_.size()<< std::endl;
- // std::cout << "Face1 points: "<< refined_edges_[face1[0]][0]
- // << " " << refined_edges_[face1[0]][1] << " -- "
- // << refined_edges_[face1[1]][0]
- // << " " << refined_edges_[face1[1]][1] << " -- "
- // << refined_edges_[face1[2]][0]
- // << " " << refined_edges_[face1[2]][1] << std::endl;
- } // end for faces_
-
- std::cout << "new edges: " << refined_edges_.size() <<std::endl;
- std::cout << "new faces: " << refined_faces_.size() <<std::endl;
- edges_.clear();
- edges_ = refined_edges_;
- // std::cout << "edges:" <<std::endl;
- // for (auto edge : edges_) {
- // std::cout<< " "<< edge[0]<< "\t"<< edge[1]<<std::endl;
- // }
- faces_.clear();
- faces_ = refined_faces_;
-
- //Rescale(1.0);
- //GenerateEdges();
- // GenerateFaces();
- }
- // ********************************************************************** //
- // ********************************************************************** //
- // ********************************************************************** //
- void ShellGenerator::GenerateFacesInit() {
- faces_.clear();
- for (unsigned int i = 0; i < edges_.size(); ++i) {
- const auto ie = edges_[i];
- for(unsigned int j = i + 1; j < edges_.size(); ++j) {
- const auto je = edges_[j];
- for(unsigned int k = j + 1; k < edges_.size(); ++k) {
- const auto ke = edges_[k];
- std::set<long unsigned int> edges = {ie[0],ie[1],
- je[0],je[1],
- ke[0],ke[1]};
- if (edges.size() != 3) continue;
- std::vector<long unsigned int> face({i,j,k});
- // std::cout << ie[0]<<"-"<<ie[1] << ":"
- // << je[0]<<"-"<<je[1] << ":"
- // << ke[0]<<"-"<<ke[1]
- // << std::endl;
- // std::cout << face[0]<<"-"<<face[1] << "-"<<face[2]<<std::endl;
- faces_.push_back(face);
- }
- }
- }
- std::cout << "Faces: "<< faces_.size() <<std::endl;
- }
- // ********************************************************************** //
- // ********************************************************************** //
- // ********************************************************************** //
- void ShellGenerator::GenerateEdgesInit() {
- std::cout << "Vertices: "<< vertices_.size() <<std::endl;
- edges_.clear();
- EvalEdgeLength();
- for (unsigned int i = 0; i < vertices_.size(); ++i)
- for(unsigned int j = i + 1; j < vertices_.size(); ++j) {
- //std::cout << i<< " " << j<< " == "<< dist(vertices_[i],vertices_[j]) <<std::endl;
- if (dist(vertices_[i],vertices_[j]) > 1.000001*edge_length_) continue;
- std::vector<long unsigned int> edge = {i,j};
- // std::cout << i<< " " << j << " : i=(";
- // for (auto v : vertices_[i]) std::cout << v <<",";
- // std::cout<<") j=(";
- // for (auto v : vertices_[j]) std::cout << v <<",";
- // std::cout<<")"<<std::endl;
- edges_.push_back(edge);
- }
- std::cout << "Edges: "<< edges_.size() <<std::endl;
- }
- // ********************************************************************** //
- // ********************************************************************** //
- // ********************************************************************** //
- void ShellGenerator::EvalEdgeLength() {
- auto p0 = vertices_[0];
- std::vector<double> zero(p0.size(), 0.0);
- double min_dist = 42.0*dist(zero, p0);
- for (auto point : vertices_) {
- if (point == p0) continue;
- double new_dist = dist(p0, point);
- if (new_dist < min_dist) min_dist = new_dist;
- }
- //std::cout << "Edge length = " << min_dist << std::endl;
- edge_length_ = min_dist;
- }
- // ********************************************************************** //
- // ********************************************************************** //
- // ********************************************************************** //
- double ShellGenerator::dist(std::vector<double> a, std::vector<double> b) {
- unsigned int len = a.size();
- if (b.size() != len)
- throw std::invalid_argument("Error! Vector need to be the same size!\n");
- double distance = 0.0;
- for (unsigned int i = 0; i<len; ++i) {
- distance += pow2(a[i]-b[i]);
- }
- return std::sqrt(distance);
- }
- // ********************************************************************** //
- // ********************************************************************** //
- // ********************************************************************** //
- // @brief set up regular icosahedron
- void ShellGenerator::SetInitialVerticesIcosahedron() {
- double a = 0.0;
- double b = 1.0;
- double c = (1+std::sqrt(5.0))/2.0;
- std::vector< std::vector<double> > points = {
- {a, b, c},
- {a, b,-c},
- {a,-b, c},
- {a,-b,-c},
-
- { b, c,a},
- { b,-c,a},
- {-b, c,a},
- {-b,-c,a},
- { c,a, b},
- {-c,a, b},
- { c,a,-b},
- {-c,a,-b}
- };
- vertices_ = std::move(points);
- //Rescale(1.0);
- //std::vector< std::vector<double> > points_debug = {{1,0,0},{-1,0,0}};
- //std::vector< std::vector<double> > points_debug = {{0,1,0},{0,-1,0}};
- //std::vector< std::vector<double> > points_debug = {{1,1,0},{1,-1,0},{-1,-1,0},{-1,1,0}};
- //std::vector< std::vector<double> > points_debug = {{0,1,1},{0,1,-1},{0,-1,-1},{0,-1,1}};
- //std::vector< std::vector<double> > points_debug = {};
- // std::vector< std::vector<double> > points_debug = {{0,0,1},{0,0,-1}};
- //vertices_ = std::move(points_debug);
- // for (auto v : vertices_) {
- // for (auto p : v)
- // std::cout<< p<<std::endl;
- // }
- }
- // ********************************************************************** //
- // ********************************************************************** //
- // ********************************************************************** //
- // @brief set up regular icosahedron
- void ShellGenerator::SetInitialVerticesTetrahedron() {
- double a = 1.0;
- double b = 1.0;
- double c = 1.0;
- std::vector< std::vector<double> > points = {
- {a, b, c},
- {a, -b,-c},
- {-a,-b, c},
- {-a, b,-c}
- };
- vertices_ = std::move(points);
- //Rescale(1.0);
- //vertices_ = std::move(points_debug);
- // for (auto v : vertices_) {
- // for (auto p : v)
- // std::cout<< p<<std::endl;
- // }
- }
- // ********************************************************************** //
- // ********************************************************************** //
- // ********************************************************************** //
- void ShellGenerator::Init() {
- SetInitialVerticesIcosahedron();
- //SetInitialVerticesTetrahedron();
- GenerateEdgesInit();
- GenerateFacesInit();
- }
- } // end of namespace read_spectra
|