/* This file is part of MAUS: http://micewww.pp.rl.ac.uk/projects/maus * * MAUS 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. * * MAUS 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 MAUS. If not, see . */ #include #include #include #include "Utils/Exception.hh" #include "src/common_cpp/FieldTools/SectorField.hh" namespace MAUS { SectorField::SectorField() : BTField(), _polarBBMin(3, 0), _polarBBMax(3, 0) { _polarBBMin[1] = bbMin[1]; _polarBBMax[1] = bbMax[1]; _polarBBMax[0] = bbMax[0]; _polarBBMin[2] = -2.*M_PI; _polarBBMax[2] = 2.*M_PI; } SectorField::~SectorField() {} SectorField::SectorField(double bbMinR, double bbMinY, double bbMinPhi, double bbMaxR, double bbMaxY, double bbMaxPhi) { SetPolarBoundingBox(bbMinR, bbMinY, bbMinPhi, bbMaxR, bbMaxY, bbMaxPhi); } void SectorField::ConvertToPolar(double* position) { double x = ::sqrt(position[0]*position[0]+position[2]*position[2]); double z = ::atan2(position[2], position[0]); position[0] = x; position[2] = z; } void SectorField::ConvertToPolar(const double* position, double* value) { double x = +value[0]*::cos(position[2]) +value[2]*::sin(position[2]); double z = +value[2]*::cos(position[2]) -value[0]*::sin(position[2]); value[0] = x; value[2] = z; } void SectorField::ConvertToCartesian(double* position) { double x = position[0]*::cos(position[2]); // r cos(phi) double z = position[0]*::sin(position[2]); // r sin(phi) position[0] = x; position[2] = z; } void SectorField::ConvertToCartesian(const double* position, double* value) { double x = +value[0]*::cos(position[2]) -value[2]*::sin(position[2]); double z = +value[2]*::cos(position[2]) +value[0]*::sin(position[2]); value[0] = x; value[2] = z; } void SectorField::SetPolarBoundingBox (double bbMinR, double bbMinY, double bbMinPhi, double bbMaxR, double bbMaxY, double bbMaxPhi) { if (bbMinR > bbMaxR) { throw(Exception(Exception::recoverable, "Bounding box minimum radius was greater than maximum radius", "SectorField::SetPolarBoundingBox")); } if (bbMinR < 0.) { throw(Exception(Exception::recoverable, "Bounding box radius must be positive", "SectorField::SetPolarBoundingBox")); } if (bbMinY > bbMaxY) { throw(Exception(Exception::recoverable, "Bounding box minimum y was greater than maximum y", "SectorField::SetPolarBoundingBox")); } if (bbMinY > bbMaxY) { throw(Exception(Exception::recoverable, "Bounding box minimum angle was greater than maximum angle", "SectorField::SetPolarBoundingBox")); } if (bbMinPhi < -2.*M_PI || bbMinPhi > 2.*M_PI || bbMaxPhi < -2.*M_PI || bbMaxPhi > 2.*M_PI) { throw(Exception(Exception::recoverable, "Bounding box angles must be in range -2*M_PI < phi < 2*M_PI", "SectorField::SetPolarBoundingBox")); } _polarBBMin[0] = bbMinR; _polarBBMin[1] = bbMinY; _polarBBMin[2] = bbMinPhi; _polarBBMax[0] = bbMaxR; _polarBBMax[1] = bbMaxY; _polarBBMax[2] = bbMaxPhi; // bounding box from corner coordinates std::vector< std::vector > corner_coords( GetCorners(bbMinR, bbMinPhi, bbMaxR, bbMaxPhi)); BTField::bbMin[0] = *std::min_element(corner_coords[0].begin(), corner_coords[0].end()); BTField::bbMax[0] = *std::max_element(corner_coords[0].begin(), corner_coords[0].end()); BTField::bbMin[1] = bbMinY; BTField::bbMax[1] = bbMaxY; BTField::bbMin[2] = *std::min_element(corner_coords[1].begin(), corner_coords[1].end()); BTField::bbMax[2] = *std::max_element(corner_coords[1].begin(), corner_coords[1].end()); // if the magnet crosses an axis, then the corners are no longer at the max // extent if ( (bbMaxPhi > 0.5*M_PI && bbMinPhi < 0.5*M_PI) || (bbMaxPhi > -1.5*M_PI && bbMinPhi < -1.5*M_PI) ) { BTField::bbMax[2] = bbMaxR; } if ((bbMaxPhi > M_PI && bbMinPhi < M_PI) || (bbMaxPhi > -M_PI && bbMinPhi < -M_PI)) { BTField::bbMin[0] = -bbMaxR; } if ((bbMaxPhi > 1.5*M_PI && bbMinPhi < 1.5*M_PI) || (bbMaxPhi > -0.5*M_PI && bbMinPhi < -0.5*M_PI)) { BTField::bbMin[2] = -bbMaxR; } if ((bbMaxPhi > 0.*M_PI && bbMinPhi < 0.*M_PI)) { BTField::bbMax[0] = bbMaxR; } } std::vector< std::vector > SectorField::GetCorners (double bbMinR, double bbMinPhi, double bbMaxR, double bbMaxPhi) { std::vector< std::vector > corner_coords(2); corner_coords[0] = std::vector(4); corner_coords[1] = std::vector(4); // corners in polar coordinates double corner_0[3] = {bbMinR, 0., bbMinPhi}; double corner_1[3] = {bbMinR, 0., bbMaxPhi}; double corner_2[3] = {bbMaxR, 0., bbMaxPhi}; double corner_3[3] = {bbMaxR, 0., bbMinPhi}; ConvertToCartesian(corner_0); ConvertToCartesian(corner_1); ConvertToCartesian(corner_2); ConvertToCartesian(corner_3); // corners in rectangular coordinates (ignore y) corner_coords[0][0] = corner_0[0]; corner_coords[0][1] = corner_1[0]; corner_coords[0][2] = corner_2[0]; corner_coords[0][3] = corner_3[0]; corner_coords[1][0] = corner_0[2]; corner_coords[1][1] = corner_1[2]; corner_coords[1][2] = corner_2[2]; corner_coords[1][3] = corner_3[2]; return corner_coords; } std::vector SectorField::GetPolarBoundingBoxMin() const { return _polarBBMin; } std::vector SectorField::GetPolarBoundingBoxMax() const { return _polarBBMax; } }