/// <summary>
        /// Evaluates the spatial frequency and temporal frequency resolved reflectance
        /// calculating the Fourier transform of the NURBS curve R(t) at the
        /// required spatial frequency for the specified optical properties.
        /// The computed FT is analitycal or discrete according to the boolean value 'analyticIntegration'.
        /// </summary>
        /// <param name="ops">optical properties</param>
        /// <param name="fxs">spatial frequency</param>
        /// <param name="fts">temporal frequancy</param>
        /// <returns>spatial frequency and temporal frequancy resolved reflectance</returns>
        public override IEnumerable <Complex> ROfFxAndFt(IEnumerable <OpticalProperties> ops, IEnumerable <double> fxs, IEnumerable <double> fts)
        {
            bool    analyticIntegration = false;
            double  fx_ref;
            Complex transformedValue;

            foreach (var op in ops)
            {
                if (analyticIntegration)
                {
                    foreach (var fx in fxs)
                    {
                        fx_ref = fx * _opReference.Musp / op.Musp;
                        double exponentialterm = op.Mua * v * _opReference.Musp / op.Musp;

                        if (fx_ref <= _sfdGenerator.SpaceValues.MaxValue)
                        {
                            foreach (var ft in fts)
                            {
                                transformedValue = _sfdGenerator.EvaluateNurbsCurveFourierTransform(fx_ref, exponentialterm, ft * _opReference.Musp / op.Musp);
                                yield return(Math.PI * transformedValue);
                            }
                        }
                        else
                        {
                            foreach (var ft in fts)
                            {
                                yield return(new Complex(0.0, 0.0));
                            }
                        }
                    }
                }
                else
                {
                    var time   = _sfdGenerator.TimeKnotSpanPolynomialCoefficients.Select(span => span.GetKnotSpanMidTime());
                    var deltaT = _sfdGenerator.TimeKnotSpanPolynomialCoefficients.Select(span => span.GetKnotSpanDeltaT());

                    foreach (var fx in fxs)
                    {
                        fx_ref = fx * op.Musp / _opReference.Musp;
                        if (fx_ref <= _sfdGenerator.SpaceValues.MaxValue)
                        {
                            var ROfT = ROfFxAndTime(op.AsEnumerable(), fx_ref.AsEnumerable(), time);

                            foreach (var ft in fts)
                            {
                                yield return(LinearDiscreteFourierTransform.GetFourierTransform(time.ToArray(), ROfT.ToArray(), deltaT.ToArray(), ft * _opReference.Musp / op.Musp));
                            }
                        }
                        else
                        {
                            foreach (var ft in fts)
                            {
                                yield return(new Complex(0.0, 0.0));
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        ///  Evaluates the temporal frequency and space resolved reflectance at a source
        ///  detector separation rho for a modulation frequency ft,for the specified
        ///  optical properties. It calculates the Fourier transform of the NURBS
        ///  curve R(t) at the required source detector separation.
        ///  The used FT is analitycal or discrete according to the boolean value 'analyticIntegration'.
        /// </summary>
        /// <param name="ops">optical properties</param>
        /// <param name="rhos">source detector separation</param>
        /// <param name="fts">modulation frequency</param>
        /// <returns>reflectance intensity</returns>
        public override IEnumerable <Complex> ROfRhoAndFt(IEnumerable <OpticalProperties> ops, IEnumerable <double> rhos, IEnumerable <double> fts)
        {
            bool   analyticIntegration = false;
            double rho_ref;

            foreach (var op in ops)
            {
                if (analyticIntegration)
                {
                    foreach (var rho in rhos)
                    {
                        double exponentialTerm = op.Mua * v * _opReference.Musp / op.Musp;
                        rho_ref = rho * op.Musp / _opReference.Musp;
                        if (rho_ref <= _rdGenerator.SpaceValues.MaxValue)
                        {
                            foreach (var ft in fts)
                            {
                                yield return(GetScalingFactor(op, 2) * _rdGenerator.EvaluateNurbsCurveFourierTransform(rho_ref, exponentialTerm, ft * _opReference.Musp / op.Musp));
                            }
                        }
                        else
                        {
                            foreach (var ft in fts)
                            {
                                yield return(new Complex(0.0, 0.0));
                            }
                        }
                    }
                }
                else
                {
                    //var time = _rdGenerator.NativeTimes;
                    var time = _rdGenerator.NativeTimes.ToArray();
                    for (int i = 0; i < time.Length; i++)
                    {
                        time[i] = time[i] * _opReference.Musp / op.Musp;
                    }
                    var deltaT = GetDeltaT(time);

                    foreach (var rho in rhos)
                    {
                        if (rho * _opReference.Musp / op.Musp <= _rdGenerator.SpaceValues.MaxValue)
                        {
                            var ROfT = ROfRhoAndTime(op.AsEnumerable(), rho.AsEnumerable(), time);

                            foreach (var ft in fts)
                            {
                                yield return(LinearDiscreteFourierTransform.GetFourierTransform(time.ToArray(), ROfT.ToArray(), deltaT.ToArray(), ft));
                            }
                        }
                        else
                        {
                            foreach (var ft in fts)
                            {
                                yield return(new Complex(0.0, 0.0));
                            }
                        }
                    }
                }
            }
        }