/// <summary>
        /// Расчет точки положения. Исходя из линейной скорости вычисление местоположения
        /// Расчитывается скорость по x и y, затем прибавляется дельта к
        /// начальной точки A, получаем ответ
        /// </summary>
        /// <returns>
        /// Расчетные координаты фотографии.
        /// </returns>
        ///<param name="DateOfShot">Дата фотографии.</param>
        ///<param name="point_A">Координаты точки A.</param>
        ///<param name="point_B">Координаты точки B.</param>
        private PointGPS PositionCalculation(DateTime DateOfShot, PointGPS point_A, PointGPS point_B)
        {
            double track_y = point_B.latitude - point_A.latitude;
            double track_x = point_B.longitude - point_A.longitude;
            double track_z = point_B.altitude - point_A.altitude;
            //время движения в секундах
            double tracktime_sec = (point_B.time - point_A.time).TotalSeconds;

            //Стояли на месте
            if (tracktime_sec == 0)
            {
                return(point_A);
            }
            double speed_y = track_y / tracktime_sec;
            double speed_x = track_x / tracktime_sec;
            double speed_z = track_z / tracktime_sec;
            //Расчет сколько времени двигались от точки A до времени Фото
            double deltatime_sec = (DateOfShot - point_A.time).TotalSeconds;
            //Расчет дельта по x и y
            double delta_y = speed_y * deltatime_sec;
            double delta_x = speed_x * deltatime_sec;
            double delta_z = speed_z * deltatime_sec;
            //Добавление дельты и получение искомой координаты для новой точки
            PointGPS new_point = point_A;

            new_point.latitude  = new_point.latitude + delta_y;
            new_point.longitude = new_point.longitude + delta_x;
            new_point.altitude  = new_point.altitude + delta_z;
            //
            return(new_point);
        }
 /// <summary>
 /// Поиск двух ближайших точек
 /// </summary>
 ///<param name="DateOfShot">Дата фотографии.</param>
 ///<param name="point_A">Координаты точки A.</param>
 ///<param name="point_B">Координаты точки B.</param>
 private void FindPointsAB(DateTime DateOfShot, ref PointGPS point_A, ref PointGPS point_B)
 {
     //Поиск двух точек внутри Трека
     for (int i = 0; i < this.Track.Count - 1; i++)
     {
         if ((this.Track[i].time < DateOfShot) && (DateOfShot < this.Track[i + 1].time))
         {
             point_A = this.Track[i];
             point_B = this.Track[i + 1];
             //
             return;
         }
         //Если время GPS и время фото совпадает
         if (this.Track[i].time == DateOfShot)
         {
             point_A = point_B = this.Track[i];
             //
             return;
         }
     }
     //Проверка последней точки
     if (this.Track[this.Track.Count - 1].time == DateOfShot)
     {
         point_A = point_B = this.Track[this.Track.Count - 1];
         //
         return;
     }
     //
 }
        /// <summary>
        /// Разбор XML документа с координатами GPS. И формирование из него
        /// списка List. Входной параметр XmlDocument <paramref name="xDoc"/>
        /// XML документ с координатами GPS.
        /// </summary>
        /// <param name="xDoc"> документ с координатами GPS.</param>
        private void parsingKML(XmlDocument xDoc)
        {
            //Выбрка XPath
            //Document/Placemark/Placemark id="tour"/gx:MultiTrack/gx:Track - несколько узлов может быть
            //< when > 2018 - 09 - 14T11: 19:14.406Z </ when >
            //<gx:coord > 20.800204 35.695177 424.20001220703125 </ gx:coord >
            //
            //https://github.com/samcragg/sharpkml
            XmlNodeList nodesMultiTrack = xDoc.GetElementsByTagName("gx:MultiTrack");

            if (nodesMultiTrack.Count < 1)
            {
                //Нет узлов для чтения координат
                throw new Exception("Файл kml не содержит тег gx:MultiTrack для получения координат");
            }
            //Извлечение координат
            var nsManager = new XmlNamespaceManager(new NameTable());

            //register mapping of prefix to namespace uri
            nsManager.AddNamespace("gx", "http://www.google.com/kml/ext/2.2");
            nsManager.AddNamespace("x", "http://www.opengis.net/kml/2.2");
            XmlNodeList nodesTrack = nodesMultiTrack[0].SelectNodes("gx:Track", nsManager);
            //Список полученых координат
            //Каждая Point организует - Track
            //Tracks список всех Track
            List <PointGPS> track_local = new List <PointGPS>();
            PointGPS        pointitem;

            foreach (XmlNode node in nodesTrack)
            {
                XmlNodeList nodeswhen  = node.SelectNodes("x:when", nsManager);
                XmlNodeList nodescoord = node.SelectNodes("gx:coord", nsManager);
                //Сопоставление данных
                int i = 0;
                foreach (XmlNode node2 in nodeswhen)
                {
                    string   strDate = node2.InnerText;
                    string[] values  = nodescoord[i].InnerText.Split(' ');
                    //
                    pointitem           = new PointGPS();
                    pointitem.longitude = Convert.ToDouble(values[0].Replace('.', ','));
                    pointitem.latitude  = Convert.ToDouble(values[1].Replace('.', ','));
                    pointitem.altitude  = Math.Round((Convert.ToDouble(values[2].Replace('.', ','))), 0);
                    pointitem.time      = Convert.ToDateTime(strDate);
                    //
                    track_local.Add(pointitem);
                    //
                    i++;
                }
            }
            //Запись треков
            this.Track = track_local;
            //Collect
            xDoc            = null;
            nodesMultiTrack = null;
            nodesTrack      = null;
            //GC.Collect();
        }
        /// <summary>
        /// Изменение EXIF информации фотограйии для записи
        /// </summary>
        ///<param name="new_point">Координаты фотографии.</param>
        ///<param name="TmpImgEXIF">Ссылка на теги EXIF.</param>
        private void EditEXIF(PointGPS new_point, ref BitmapMetadata TmpImgEXIF)
        {
            //Запись в EXIF
            //широта
            if (new_point.latitude > 0)
            {
                //северная широта
                TmpImgEXIF.SetQuery("/app1/ifd/gps/{ushort=1}", "N");
            }
            else
            {
                //южная широта
                TmpImgEXIF.SetQuery("/app1/ifd/gps/{ushort=1}", "S");
            }
            //долгота
            if (new_point.longitude > 0)
            {
                //Восточная долгота
                TmpImgEXIF.SetQuery("/app1/ifd/gps/{ushort=3}", "E");
            }
            else
            {
                //Западная долгота
                TmpImgEXIF.SetQuery("/app1/ifd/gps/{ushort=3}", "W");
            }
            //Формат версии
            TmpImgEXIF.SetQuery("/app1/ifd/gps/{ushort=0}", "2.2.0.0");
            //Высота ->6
            TmpImgEXIF.SetQuery("/app1/ifd/gps/{ushort=6}", Rational(new_point.altitude));
            //Широта конвертирование в градусы минуты секунды
            double Degree, Minute, Second;

            ConvertToDegreeMinuteSecond(new_point.latitude, out Degree, out Minute, out Second);
            ulong[] t = { Rational(Degree), Rational(Minute), Rational(Second) };
            TmpImgEXIF.SetQuery("/app1/ifd/gps/{ushort=2}", t);
            //Долгота конвертирование в градусы минуты секунды
            ConvertToDegreeMinuteSecond(new_point.longitude, out Degree, out Minute, out Second);
            ulong[] t2 = { Rational(Degree), Rational(Minute), Rational(Second) };
            TmpImgEXIF.SetQuery("/app1/ifd/gps/{ushort=4}", t2);
        }
        /// <summary>
        /// Подпись фотографии координатами GPS.
        /// </summary>
        /// <returns>
        /// Результат операции. ОК или невозможно подписать.
        /// </returns>
        ///<param name="PathImage">Путь на диске к фотографии.</param>
        /// <param name="out_point">Рассчитанные координаты фотографии.</param>
        public string WriteGPSinImage_PresentationCore(string PathImage, out PointGPS out_point)
        {
            out_point = null;
            //На основе https://habr.com/post/134774/
            //Получение EXIF информации фото
            FileStream     Foto       = File.Open(PathImage, FileMode.Open, FileAccess.Read);                                              // открыли файл по адресу s для чтения
            BitmapDecoder  decoder    = JpegBitmapDecoder.Create(Foto, BitmapCreateOptions.IgnoreColorProfile, BitmapCacheOption.Default); //"распаковали" снимок и создали объект decoder
            BitmapMetadata TmpImgEXIF = (BitmapMetadata)decoder.Frames[0].Metadata.Clone();                                                //считали и сохранили метаданные
            //Дата создания снимка
            DateTime DateOfShot = Convert.ToDateTime(TmpImgEXIF.DateTaken);

            //Изменение времени, если было задано пользователем
            if (Params.addOrRemoveTime)
            {
                //add time
                DateOfShot = DateOfShot + Params.addTime;
            }
            else
            {
                //Remove time
                DateOfShot = DateOfShot - Params.addTime;
            }
            //Поиск двух ближайших точек, до создания фото и после создания фото
            //Point pointitem;
            //var time = new TimeSpan(3, 0, 0); //---Убрать потом
            //DateOfShot = DateOfShot - time;//---Убрать потом
            PointGPS point_A = null;
            PointGPS point_B = null;

            //Поиск двух точек A и B
            FindPointsAB(DateOfShot, ref point_A, ref point_B);
            //Если точек A и B нет, то невозможно подписать фото
            if ((point_A == null) || (point_B == null))
            {
                return("Для фотографии отсутствуют точки координат, невозможно подписать.");
            }
            //Расчет новой позиции
            PointGPS new_point = PositionCalculation(DateOfShot, point_A, point_B);

            //Изменение EXIF, добавление GPS
            EditEXIF(new_point, ref TmpImgEXIF);
            //Изменение даты фото, если была включена коррекция даты
            if (DateOfShot != Convert.ToDateTime(TmpImgEXIF.DateTaken))
            {
                TmpImgEXIF.DateTaken = DateOfShot.ToString(DateTimeFormatInfo.InvariantInfo);
            }
            //Запись нового файла с тегами
            JpegBitmapEncoder Encoder = new JpegBitmapEncoder();                                                                                 //создали новый энкодер для Jpeg

            Encoder.QualityLevel = 95;                                                                                                           //95
            Encoder.Frames.Add(BitmapFrame.Create(decoder.Frames[0], decoder.Frames[0].Thumbnail, TmpImgEXIF, decoder.Frames[0].ColorContexts)); //добавили в энкодер новый кадр(он там всего один) с указанными параметрами
            string NewFileName   = new FileInfo(PathImage).Directory + "/" + Path.GetFileNameWithoutExtension(PathImage) + "_.jpg";              //имя исходного файла +GeoTag.jpg
            Stream jpegStreamOut = File.Open(NewFileName, FileMode.Create, FileAccess.ReadWrite);                                                //создали новый файл

            Encoder.Save(jpegStreamOut);                                                                                                         //сохранили новый файл
            //Clear memory
            Encoder = null;
            decoder = null;
            jpegStreamOut.Flush();
            jpegStreamOut.Close();
            jpegStreamOut.Dispose();
            Foto.Close();
            Foto.Dispose();
            GC.Collect();
            //
            //Делаем замену файла
            //Удаляем старый и переименовываем новый
            File.Delete(PathImage);
            File.Move(NewFileName, PathImage);
            //ok
            out_point = new_point;
            return("ok");
        }