public BesselianElementsTableItem(int index, PolynomialBesselianElements pbe)
        {
            Index = index.ToString();
            X     = pbe.X[index].ToString("N6", CultureInfo.InvariantCulture);
            Y     = pbe.Y[index].ToString("N6", CultureInfo.InvariantCulture);

            if (index <= 2)
            {
                D  = pbe.D[index].ToString("N6", CultureInfo.InvariantCulture);
                L1 = pbe.L1[index].ToString("N6", CultureInfo.InvariantCulture);
                L2 = pbe.L2[index].ToString("N6", CultureInfo.InvariantCulture);
            }

            if (index <= 1)
            {
                Mu = Angle.To360(pbe.Mu[index]).ToString("N6", CultureInfo.InvariantCulture);
            }
        }
 /// <inheritdoc/>
 public ICollection <SolarEclipseLocalCircumstances> FindLocalCircumstancesForCities(PolynomialBesselianElements be, ICollection <CrdsGeographical> cities, CancellationToken?cancelToken = null, IProgress <double> progress = null)
 {
     return(cities
            .Distinct()
            .Select(c => SolarEclipses.LocalCircumstances(be, c))
            .ToArray());
 }
        /// <inheritdoc/>
        public ICollection <SolarEclipseLocalCircumstances> FindCitiesOnCentralLine(PolynomialBesselianElements be, ICollection <CrdsGeographical> centralLine, CancellationToken?cancelToken = null, IProgress <double> progress = null)
        {
            var cities = new List <CrdsGeographical>();

            for (int i = 0; i < centralLine.Count - 1; i++)
            {
                // Report progess
                progress?.Report((double)(i + 1) / centralLine.Count * 100);

                // Exit loop if cancel requested
                if (cancelToken?.IsCancellationRequested == true)
                {
                    return(new SolarEclipseLocalCircumstances[0]);
                }

                // 2 successive points create a central line segment
                var g0 = centralLine.ElementAt(i);
                var g1 = centralLine.ElementAt(i + 1);

                // Segment length, distance between 2 points on central line, in kilometers
                var length = g0.DistanceTo(g1);

                // Local circumstances at point "g0"
                var local = SolarEclipses.LocalCircumstances(be, g0);

                // Lunar umbra radius, in kilometers
                float r  = (float)(local.PathWidth / 2);
                float r0 = r;
                if (r < 10)
                {
                    r = 10;
                }

                if (r > 0)
                {
                    // Count of parts the segment should be splitted
                    int parts = (int)Math.Round(length / r);

                    // If the segment should be splitted
                    if (parts > 1)
                    {
                        // Find intermediate points and add closest cities
                        for (int j = 0; j < parts; j++)
                        {
                            // Exit loop if cancel requested
                            if (cancelToken?.IsCancellationRequested == true)
                            {
                                return(new SolarEclipseLocalCircumstances[0]);
                            }

                            var g         = Angle.Intermediate(g0, g1, (float)j / parts);
                            var locations = locationsManager.Search(g, r);
                            cities.AddRange(locations.Where(loc => loc.DistanceTo(g) <= r0));
                        }
                    }
                    // The segment should not be splitted, add closest cities to the first point
                    else
                    {
                        var locations = locationsManager.Search(g0, r);
                        cities.AddRange(locations.Where(loc => loc.DistanceTo(g0) <= r0));
                    }
                }
            }

            return(FindLocalCircumstancesForCities(be, cities, cancelToken, progress));
        }