| 
									
										
										
										
											2018-04-03 18:51:21 +02:00
										 |  |  | ///////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | // Copyright (C) 2017 F4EXB                                                      //
 | 
					
						
							|  |  |  | // written by Edouard Griffiths                                                  //
 | 
					
						
							|  |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // 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 as version 3 of the License, or                  //
 | 
					
						
							| 
									
										
										
										
											2019-04-11 14:32:15 +02:00
										 |  |  | // (at your option) any later version.                                           //
 | 
					
						
							| 
									
										
										
										
											2018-04-03 18:51:21 +02:00
										 |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // 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 V3 for more details.                               //
 | 
					
						
							|  |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // You should have received a copy of the GNU General Public License             //
 | 
					
						
							|  |  |  | // along with this program. If not, see <http://www.gnu.org/licenses/>.          //
 | 
					
						
							|  |  |  | ///////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-03 13:52:12 +01:00
										 |  |  | #include <cmath>
 | 
					
						
							| 
									
										
										
										
											2018-04-03 18:51:21 +02:00
										 |  |  | #include "projector.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Projector::Projector(ProjectionType projectionType) : | 
					
						
							|  |  |  |     m_projectionType(projectionType), | 
					
						
							|  |  |  |     m_prevArg(0.0f), | 
					
						
							| 
									
										
										
										
											2021-07-15 10:03:09 +02:00
										 |  |  |     m_cache(nullptr), | 
					
						
							| 
									
										
										
										
											2018-04-03 18:51:21 +02:00
										 |  |  |     m_cacheMaster(true) | 
					
						
							| 
									
										
										
										
											2018-04-03 23:33:55 +02:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-04-03 18:51:21 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | Projector::~Projector() | 
					
						
							| 
									
										
										
										
											2018-04-03 23:33:55 +02:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-04-03 18:51:21 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | Real Projector::run(const Sample& s) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Real v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((m_cache) && !m_cacheMaster) { | 
					
						
							|  |  |  |         return m_cache[(int) m_projectionType]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         switch (m_projectionType) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |         case ProjectionImag: | 
					
						
							|  |  |  |             v = s.m_imag / SDR_RX_SCALEF; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case ProjectionMagLin: | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             Real re = s.m_real / SDR_RX_SCALEF; | 
					
						
							|  |  |  |             Real im = s.m_imag / SDR_RX_SCALEF; | 
					
						
							|  |  |  |             Real magsq = re*re + im*im; | 
					
						
							|  |  |  |             v = std::sqrt(magsq); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2018-06-26 00:43:19 +02:00
										 |  |  |         case ProjectionMagSq: | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             Real re = s.m_real / SDR_RX_SCALEF; | 
					
						
							|  |  |  |             Real im = s.m_imag / SDR_RX_SCALEF; | 
					
						
							|  |  |  |             v = re*re + im*im; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2018-04-03 18:51:21 +02:00
										 |  |  |         case ProjectionMagDB: | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             Real re = s.m_real / SDR_RX_SCALEF; | 
					
						
							|  |  |  |             Real im = s.m_imag / SDR_RX_SCALEF; | 
					
						
							|  |  |  |             Real magsq = re*re + im*im; | 
					
						
							|  |  |  |             v = log10f(magsq) * 10.0f; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case ProjectionPhase: | 
					
						
							| 
									
										
										
										
											2019-11-17 23:45:50 +01:00
										 |  |  |             v = std::atan2((float) s.m_imag, (float) s.m_real) / M_PI; // normalize
 | 
					
						
							| 
									
										
										
										
											2018-04-03 18:51:21 +02:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2019-11-15 22:58:18 +01:00
										 |  |  |         case ProjectionDOAP: | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2019-11-17 23:45:50 +01:00
										 |  |  |             // calculate phase. Assume phase difference between two sources at half wavelength distance with sources axis as reference (positive side)
 | 
					
						
							|  |  |  |             // cos(theta) = phi / 2*pi*k
 | 
					
						
							|  |  |  |             Real p = std::atan2((float) s.m_imag, (float) s.m_real); // do not mormalize phi (phi in -pi..+pi)
 | 
					
						
							|  |  |  |             v = acos(p/M_PI) / M_PI; // normalize theta
 | 
					
						
							| 
									
										
										
										
											2019-11-15 22:58:18 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case ProjectionDOAN: | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2019-11-17 23:45:50 +01:00
										 |  |  |             // calculate phase. Assume phase difference between two sources at half wavelength distance with sources axis as reference (negative source)
 | 
					
						
							|  |  |  |             Real p = std::atan2((float) s.m_imag, (float) s.m_real); // do not mormalize phi (phi in -pi..+pi)
 | 
					
						
							|  |  |  |             v = -acos(p/M_PI) / M_PI; // normalize theta
 | 
					
						
							| 
									
										
										
										
											2019-11-15 22:58:18 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2018-04-03 18:51:21 +02:00
										 |  |  |         case ProjectionDPhase: | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             Real curArg = std::atan2((float) s.m_imag, (float) s.m_real); | 
					
						
							|  |  |  |             Real dPhi = (curArg - m_prevArg) / M_PI; | 
					
						
							|  |  |  |             m_prevArg = curArg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (dPhi < -1.0f) { | 
					
						
							|  |  |  |                 dPhi += 2.0f; | 
					
						
							|  |  |  |             } else if (dPhi > 1.0f) { | 
					
						
							|  |  |  |                 dPhi -= 2.0f; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             v = dPhi; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2018-05-22 13:54:01 +02:00
										 |  |  |         case ProjectionBPSK: | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             Real arg = std::atan2((float) s.m_imag, (float) s.m_real); | 
					
						
							|  |  |  |             v = normalizeAngle(2*arg) / (2.0*M_PI); // generic estimation around 0
 | 
					
						
							|  |  |  |             // mapping on 2 symbols
 | 
					
						
							|  |  |  |             if (arg < -M_PI/2) { | 
					
						
							|  |  |  |                 v -= 1.0/2; | 
					
						
							|  |  |  |             } else if (arg < M_PI/2) { | 
					
						
							|  |  |  |                 v += 1.0/2; | 
					
						
							|  |  |  |             } else if (arg < M_PI) { | 
					
						
							|  |  |  |                 v -= 1.0/2; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case ProjectionQPSK: | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             Real arg = std::atan2((float) s.m_imag, (float) s.m_real); | 
					
						
							|  |  |  |             v = normalizeAngle(4*arg) / (4.0*M_PI); // generic estimation around 0
 | 
					
						
							|  |  |  |             // mapping on 4 symbols
 | 
					
						
							|  |  |  |             if (arg < -3*M_PI/4) { | 
					
						
							|  |  |  |                 v -= 3.0/4; | 
					
						
							|  |  |  |             } else if (arg < -M_PI/4) { | 
					
						
							|  |  |  |                 v -= 1.0/4; | 
					
						
							|  |  |  |             } else if (arg < M_PI/4) { | 
					
						
							|  |  |  |                 v += 1.0/4; | 
					
						
							|  |  |  |             } else if (arg < 3*M_PI/4) { | 
					
						
							|  |  |  |                 v += 3.0/4; | 
					
						
							|  |  |  |             } else if (arg < M_PI) { | 
					
						
							|  |  |  |                 v -= 3.0/4; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case Projection8PSK: | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             Real arg = std::atan2((float) s.m_imag, (float) s.m_real); | 
					
						
							|  |  |  |             v = normalizeAngle(8*arg) / (8.0*M_PI); // generic estimation around 0
 | 
					
						
							|  |  |  |             // mapping on 8 symbols
 | 
					
						
							|  |  |  |             if (arg < -7*M_PI/8) { | 
					
						
							|  |  |  |                v -= 7.0/8; | 
					
						
							|  |  |  |             } else if (arg < -5*M_PI/8) { | 
					
						
							|  |  |  |                 v -= 5.0/8; | 
					
						
							|  |  |  |             } else if (arg < -3*M_PI/8) { | 
					
						
							|  |  |  |                 v -= 3.0/8; | 
					
						
							|  |  |  |             } else if (arg < -M_PI/8) { | 
					
						
							|  |  |  |                 v -= 1.0/8; | 
					
						
							|  |  |  |             } else if (arg < M_PI/8) { | 
					
						
							|  |  |  |                 v += 1.0/8; | 
					
						
							|  |  |  |             } else if (arg < 3*M_PI/8) { | 
					
						
							|  |  |  |                 v += 3.0/8; | 
					
						
							|  |  |  |             } else if (arg < 5*M_PI/8) { | 
					
						
							|  |  |  |                 v += 5.0/8; | 
					
						
							|  |  |  |             } else if (arg < 7*M_PI/8) { | 
					
						
							|  |  |  |                 v += 7.0/8; | 
					
						
							|  |  |  |             } else if (arg < M_PI) { | 
					
						
							|  |  |  |                 v -= 7.0/8; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case Projection16PSK: | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             Real arg = std::atan2((float) s.m_imag, (float) s.m_real); | 
					
						
							|  |  |  |             v = normalizeAngle(16*arg) / (16.0*M_PI); // generic estimation around 0
 | 
					
						
							|  |  |  |             // mapping on 16 symbols
 | 
					
						
							|  |  |  |             if (arg < -15*M_PI/16) { | 
					
						
							|  |  |  |                v -= 15.0/16; | 
					
						
							|  |  |  |             } else if (arg < -13*M_PI/16) { | 
					
						
							|  |  |  |                 v -= 13.0/6; | 
					
						
							|  |  |  |             } else if (arg < -11*M_PI/16) { | 
					
						
							|  |  |  |                 v -= 11.0/16; | 
					
						
							|  |  |  |             } else if (arg < -9*M_PI/16) { | 
					
						
							|  |  |  |                 v -= 9.0/16; | 
					
						
							|  |  |  |             } else if (arg < -7*M_PI/16) { | 
					
						
							|  |  |  |                 v -= 7.0/16; | 
					
						
							|  |  |  |             } else if (arg < -5*M_PI/16) { | 
					
						
							|  |  |  |                 v -= 5.0/16; | 
					
						
							|  |  |  |             } else if (arg < -3*M_PI/16) { | 
					
						
							|  |  |  |                 v -= 3.0/16; | 
					
						
							|  |  |  |             } else if (arg < -M_PI/16) { | 
					
						
							|  |  |  |                 v -= 1.0/16; | 
					
						
							|  |  |  |             } else if (arg < M_PI/16) { | 
					
						
							|  |  |  |                 v += 1.0/16; | 
					
						
							|  |  |  |             } else if (arg < 3.0*M_PI/16) { | 
					
						
							|  |  |  |                 v += 3.0/16; | 
					
						
							|  |  |  |             } else if (arg < 5.0*M_PI/16) { | 
					
						
							|  |  |  |                 v += 5.0/16; | 
					
						
							|  |  |  |             } else if (arg < 7.0*M_PI/16) { | 
					
						
							|  |  |  |                 v += 7.0/16; | 
					
						
							|  |  |  |             } else if (arg < 9.0*M_PI/16) { | 
					
						
							|  |  |  |                 v += 9.0/16; | 
					
						
							|  |  |  |             } else if (arg < 11.0*M_PI/16) { | 
					
						
							|  |  |  |                 v += 11.0/16; | 
					
						
							|  |  |  |             } else if (arg < 13.0*M_PI/16) { | 
					
						
							|  |  |  |                 v += 13.0/16; | 
					
						
							|  |  |  |             } else if (arg < 15.0*M_PI/16) { | 
					
						
							|  |  |  |                 v += 15.0/16; | 
					
						
							|  |  |  |             } else if (arg < M_PI) { | 
					
						
							|  |  |  |                 v -= 15.0/16; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2018-04-03 18:51:21 +02:00
										 |  |  |         case ProjectionReal: | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             v = s.m_real / SDR_RX_SCALEF; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (m_cache) { | 
					
						
							|  |  |  |             m_cache[(int) m_projectionType] = v; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return v; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-23 15:53:28 +02:00
										 |  |  | Real Projector::run(const std::complex<float>& s) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Real v; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((m_cache) && !m_cacheMaster) { | 
					
						
							|  |  |  |         return m_cache[(int) m_projectionType]; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         switch (m_projectionType) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |         case ProjectionImag: | 
					
						
							|  |  |  |             v = s.imag(); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case ProjectionMagLin: | 
					
						
							|  |  |  |             v = std::abs(s); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case ProjectionMagSq: | 
					
						
							|  |  |  |             v = std::norm(s); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case ProjectionMagDB: | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             Real magsq = std::norm(s); | 
					
						
							|  |  |  |             v = log10f(magsq) * 10.0f; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case ProjectionPhase: | 
					
						
							|  |  |  |             v = std::arg(s) / M_PI; // normalize
 | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case ProjectionDOAP: | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             // calculate phase. Assume phase difference between two sources at half wavelength distance with sources axis as reference (positive side)
 | 
					
						
							|  |  |  |             // cos(theta) = phi / 2*pi*k
 | 
					
						
							|  |  |  |             Real p = std::arg(s); // do not mormalize phi (phi in -pi..+pi)
 | 
					
						
							|  |  |  |             v = acos(p/M_PI) / M_PI; // normalize theta
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case ProjectionDOAN: | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             // calculate phase. Assume phase difference between two sources at half wavelength distance with sources axis as reference (negative source)
 | 
					
						
							|  |  |  |             Real p = std::arg(s); // do not mormalize phi (phi in -pi..+pi)
 | 
					
						
							|  |  |  |             v = -acos(p/M_PI) / M_PI; // normalize theta
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case ProjectionDPhase: | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             Real curArg = std::arg(s); | 
					
						
							|  |  |  |             Real dPhi = (curArg - m_prevArg) / M_PI; | 
					
						
							|  |  |  |             m_prevArg = curArg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (dPhi < -1.0f) { | 
					
						
							|  |  |  |                 dPhi += 2.0f; | 
					
						
							|  |  |  |             } else if (dPhi > 1.0f) { | 
					
						
							|  |  |  |                 dPhi -= 2.0f; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             v = dPhi; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case ProjectionBPSK: | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             Real arg = std::arg(s); | 
					
						
							|  |  |  |             v = normalizeAngle(2*arg) / (2.0*M_PI); // generic estimation around 0
 | 
					
						
							|  |  |  |             // mapping on 2 symbols
 | 
					
						
							|  |  |  |             if (arg < -M_PI/2) { | 
					
						
							|  |  |  |                 v -= 1.0/2; | 
					
						
							|  |  |  |             } else if (arg < M_PI/2) { | 
					
						
							|  |  |  |                 v += 1.0/2; | 
					
						
							|  |  |  |             } else if (arg < M_PI) { | 
					
						
							|  |  |  |                 v -= 1.0/2; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case ProjectionQPSK: | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             Real arg = std::arg(s); | 
					
						
							|  |  |  |             v = normalizeAngle(4*arg) / (4.0*M_PI); // generic estimation around 0
 | 
					
						
							|  |  |  |             // mapping on 4 symbols
 | 
					
						
							|  |  |  |             if (arg < -3*M_PI/4) { | 
					
						
							|  |  |  |                 v -= 3.0/4; | 
					
						
							|  |  |  |             } else if (arg < -M_PI/4) { | 
					
						
							|  |  |  |                 v -= 1.0/4; | 
					
						
							|  |  |  |             } else if (arg < M_PI/4) { | 
					
						
							|  |  |  |                 v += 1.0/4; | 
					
						
							|  |  |  |             } else if (arg < 3*M_PI/4) { | 
					
						
							|  |  |  |                 v += 3.0/4; | 
					
						
							|  |  |  |             } else if (arg < M_PI) { | 
					
						
							|  |  |  |                 v -= 3.0/4; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case Projection8PSK: | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             Real arg = std::arg(s); | 
					
						
							|  |  |  |             v = normalizeAngle(8*arg) / (8.0*M_PI); // generic estimation around 0
 | 
					
						
							|  |  |  |             // mapping on 8 symbols
 | 
					
						
							|  |  |  |             if (arg < -7*M_PI/8) { | 
					
						
							|  |  |  |                v -= 7.0/8; | 
					
						
							|  |  |  |             } else if (arg < -5*M_PI/8) { | 
					
						
							|  |  |  |                 v -= 5.0/8; | 
					
						
							|  |  |  |             } else if (arg < -3*M_PI/8) { | 
					
						
							|  |  |  |                 v -= 3.0/8; | 
					
						
							|  |  |  |             } else if (arg < -M_PI/8) { | 
					
						
							|  |  |  |                 v -= 1.0/8; | 
					
						
							|  |  |  |             } else if (arg < M_PI/8) { | 
					
						
							|  |  |  |                 v += 1.0/8; | 
					
						
							|  |  |  |             } else if (arg < 3*M_PI/8) { | 
					
						
							|  |  |  |                 v += 3.0/8; | 
					
						
							|  |  |  |             } else if (arg < 5*M_PI/8) { | 
					
						
							|  |  |  |                 v += 5.0/8; | 
					
						
							|  |  |  |             } else if (arg < 7*M_PI/8) { | 
					
						
							|  |  |  |                 v += 7.0/8; | 
					
						
							|  |  |  |             } else if (arg < M_PI) { | 
					
						
							|  |  |  |                 v -= 7.0/8; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case Projection16PSK: | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             Real arg = std::arg(s); | 
					
						
							|  |  |  |             v = normalizeAngle(16*arg) / (16.0*M_PI); // generic estimation around 0
 | 
					
						
							|  |  |  |             // mapping on 16 symbols
 | 
					
						
							|  |  |  |             if (arg < -15*M_PI/16) { | 
					
						
							|  |  |  |                v -= 15.0/16; | 
					
						
							|  |  |  |             } else if (arg < -13*M_PI/16) { | 
					
						
							|  |  |  |                 v -= 13.0/6; | 
					
						
							|  |  |  |             } else if (arg < -11*M_PI/16) { | 
					
						
							|  |  |  |                 v -= 11.0/16; | 
					
						
							|  |  |  |             } else if (arg < -9*M_PI/16) { | 
					
						
							|  |  |  |                 v -= 9.0/16; | 
					
						
							|  |  |  |             } else if (arg < -7*M_PI/16) { | 
					
						
							|  |  |  |                 v -= 7.0/16; | 
					
						
							|  |  |  |             } else if (arg < -5*M_PI/16) { | 
					
						
							|  |  |  |                 v -= 5.0/16; | 
					
						
							|  |  |  |             } else if (arg < -3*M_PI/16) { | 
					
						
							|  |  |  |                 v -= 3.0/16; | 
					
						
							|  |  |  |             } else if (arg < -M_PI/16) { | 
					
						
							|  |  |  |                 v -= 1.0/16; | 
					
						
							|  |  |  |             } else if (arg < M_PI/16) { | 
					
						
							|  |  |  |                 v += 1.0/16; | 
					
						
							|  |  |  |             } else if (arg < 3.0*M_PI/16) { | 
					
						
							|  |  |  |                 v += 3.0/16; | 
					
						
							|  |  |  |             } else if (arg < 5.0*M_PI/16) { | 
					
						
							|  |  |  |                 v += 5.0/16; | 
					
						
							|  |  |  |             } else if (arg < 7.0*M_PI/16) { | 
					
						
							|  |  |  |                 v += 7.0/16; | 
					
						
							|  |  |  |             } else if (arg < 9.0*M_PI/16) { | 
					
						
							|  |  |  |                 v += 9.0/16; | 
					
						
							|  |  |  |             } else if (arg < 11.0*M_PI/16) { | 
					
						
							|  |  |  |                 v += 11.0/16; | 
					
						
							|  |  |  |             } else if (arg < 13.0*M_PI/16) { | 
					
						
							|  |  |  |                 v += 13.0/16; | 
					
						
							|  |  |  |             } else if (arg < 15.0*M_PI/16) { | 
					
						
							|  |  |  |                 v += 15.0/16; | 
					
						
							|  |  |  |             } else if (arg < M_PI) { | 
					
						
							|  |  |  |                 v -= 15.0/16; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         case ProjectionReal: | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             v = s.real(); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (m_cache) { | 
					
						
							|  |  |  |             m_cache[(int) m_projectionType] = v; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return v; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-22 13:54:01 +02:00
										 |  |  | Real Projector::normalizeAngle(Real angle) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     while (angle <= -M_PI) { | 
					
						
							|  |  |  |         angle += 2.0*M_PI; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     while (angle > M_PI) { | 
					
						
							|  |  |  |         angle -= 2.0*M_PI; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return angle; | 
					
						
							|  |  |  | } |