欢迎访问移动开发之家(rcyd.net),关注移动开发教程。移动开发之家  移动开发问答|  每日更新
页面位置 : > > 内容正文

Windows Phone 运动轨迹记录工具,phone轨迹

来源: 开发者 投稿于  被查看 116 次 评论:237

Windows Phone 运动轨迹记录工具,phone轨迹


轨迹记录工具


带有 GPS 记录功能的运动手表价格不菲,于是我自己写了一个简单的运动轨迹记录工具。核心代码如下,只有不到 200 行。

工具记录的数据可以使用 Isolated Storage Explorer Tool 导出,进行进一步的分析、处理和转换。
 

[csharp] 
using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Device.Location; 
using System.IO; 
using System.IO.IsolatedStorage; 
using System.Text; 
using System.Windows; 
using System.Windows.Controls; 
using Microsoft.Phone.Controls; 
using Microsoft.Phone.Shell; 
 
namespace Tracker 

    public partial class MainPage : PhoneApplicationPage 
    { 
        bool tracking; 
        string logName; 
        GeoCoordinateWatcher watcher; 
        List<GeoCoordinate> locations; 
        List<long> timestamps; 
        Object lockObject; 
 
        public MainPage() 
        { 
            tracking = false; 
            lockObject = new Object(); 
            InitializeComponent(); 
            PhoneApplicationService.Current.ApplicationIdleDetectionMode = IdleDetectionMode.Disabled; 
            updateLogName(); 
            status.Text = "GPS Tracker by coolypf"; 
            watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High); 
            watcher.MovementThreshold = 0.0; 
            watcher.PositionChanged += onMove; 
        } 
 
        void onMove(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e) 
        { 
            if (!tracking || watcher.Status != GeoPositionStatus.Ready) 
                return; 
            lock (lockObject) 
            { 
                locations.Add(e.Position.Location); 
                timestamps.Add(e.Position.Timestamp.UtcTicks); 
            } 
        } 
 
        void updateLogName() 
        { 
            IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication(); 
            DateTime now = DateTime.Now; 
            String prefix = now.Year + "-" + now.Month + "-" + now.Day + "-"; 
            String filename; 
            int idx = 1; 
            while (true) 
            { 
                filename = prefix + idx + ".txt"; 
                if (!isf.FileExists(filename)) 
                    break; 
                idx++; 
            } 
            name.Text = filename; 
        } 
 
        void writeLog() 
        { 
            lock (lockObject) 
            { 
                if (locations.Count < 2) 
                    return; 
                IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication(); 
                StreamWriter w = new StreamWriter(isf.OpenFile(logName, FileMode.Create, FileAccess.Write)); 
                for (int i = 0; i < locations.Count; ++i) 
                { 
                    w.Write(timestamps[i]); 
                    w.Write(" "); 
                    GeoCoordinate g = locations[i]; 
                    w.Write(g.Latitude); 
                    w.Write(" "); 
                    w.Write(g.Longitude); 
                    w.Write(" "); 
                    w.Write(g.Altitude); 
                    w.Write(" "); 
                    w.Write(g.Speed); 
                    w.WriteLine(); 
                } 
                w.Close(); 
            } 
        } 
 
        void onControl(object sender, RoutedEventArgs e) 
        { 
            control.IsEnabled = false; 
            if (tracking) 
            { 
                tracking = false; 
                lock (lockObject) 
                { 
                    if (locations.Count > 0) 
                    { 
                        locations.Add(watcher.Position.Location); 
                        timestamps.Add(watcher.Position.Timestamp.UtcTicks); 
                    } 
                } 
                watcher.Stop(); 
                writeLog(); 
                status.Text = getStatus(); 
                locations = null; 
                timestamps = null; 
                control.Content = "Start"; 
                show.IsEnabled = false; 
                updateLogName(); 
                name.IsEnabled = true; 
            } 
            else 
            { 
                name.IsEnabled = false; 
                logName = name.Text; 
                locations = new List<GeoCoordinate>(); 
                timestamps = new List<long>(); 
                tracking = true; 
                watcher.Start(); 
                control.Content = "Stop"; 
                show.IsEnabled = true; 
            } 
            control.IsEnabled = true; 
        } 
 
        String getStatus() 
        { 
            StringBuilder b = new StringBuilder(); 
            lock (lockObject) 
            { 
                b.Append("Tracked positions: "); 
                b.Append(locations.Count); 
                b.AppendLine(); 
                if (locations.Count >= 2) 
                { 
                    double dist = 0.0; 
                    long ticks = timestamps[timestamps.Count - 1] - timestamps[0]; 
                    for (int i = 1; i < locations.Count; ++i) 
                        dist += locations[i - 1].GetDistanceTo(locations[i]); 
                    double speed = dist / (ticks * 1e-7); 
                    b.Append("Total distance:    "); 
                    b.Append(dist); 
                    b.AppendLine(" m"); 
                    b.Append("Total time:        "); 
                    b.Append(new TimeSpan(ticks).ToString()); 
                    b.AppendLine(); 
                    b.Append("Average speed:     "); 
                    b.Append(speed); 
                    b.AppendLine(" m/s"); 
                    b.Append("                   "); 
                    b.Append(speed * 3.6); 
                    b.AppendLine(" km/h"); 
                } 
            } 
            return b.ToString(); 
        } 
 
        void onShow(object sender, RoutedEventArgs e) 
        { 
            if (!tracking) 
                return; 
            status.Text = getStatus() + "GPS status:        " + watcher.Status.ToString(); 
        } 
 
        protected override void OnBackKeyPress(CancelEventArgs e) 
        { 
            if (tracking) 
            { 
                MessageBoxResult result = MessageBox.Show("Tracking is in progress. If you quit, all recorded data will be lost.", "Quit Tracker?", MessageBoxButton.OKCancel); 
                if (result != MessageBoxResult.OK) 
                    e.Cancel = true; 
            } 
            base.OnBackKeyPress(e); 
        } 
    } 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Device.Location;
using System.IO;
using System.IO.IsolatedStorage;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;

namespace Tracker
{
    public partial class MainPage : PhoneApplicationPage
    {
        bool tracking;
        string logName;
        GeoCoordinateWatcher watcher;
        List<GeoCoordinate> locations;
        List<long> timestamps;
        Object lockObject;

        public MainPage()
        {
            tracking = false;
            lockObject = new Object();
            InitializeComponent();
            PhoneApplicationService.Current.ApplicationIdleDetectionMode = IdleDetectionMode.Disabled;
            updateLogName();
            status.Text = "GPS Tracker by coolypf";
            watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High);
            watcher.MovementThreshold = 0.0;
            watcher.PositionChanged += onMove;
        }

        void onMove(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
        {
            if (!tracking || watcher.Status != GeoPositionStatus.Ready)
                return;
            lock (lockObject)
            {
                locations.Add(e.Position.Location);
                timestamps.Add(e.Position.Timestamp.UtcTicks);
            }
        }

        void updateLogName()
        {
            IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication();
            DateTime now = DateTime.Now;
            String prefix = now.Year + "-" + now.Month + "-" + now.Day + "-";
            String filename;
            int idx = 1;
            while (true)
            {
                filename = prefix + idx + ".txt";
                if (!isf.FileExists(filename))
                    break;
                idx++;
            }
            name.Text = filename;
        }

        void writeLog()
        {
            lock (lockObject)
            {
                if (locations.Count < 2)
                    return;
                IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication();
                StreamWriter w = new StreamWriter(isf.OpenFile(logName, FileMode.Create, FileAccess.Write));
                for (int i = 0; i < locations.Count; ++i)
                {
                    w.Write(timestamps[i]);
                    w.Write(" ");
                    GeoCoordinate g = locations[i];
                    w.Write(g.Latitude);
                    w.Write(" ");
                    w.Write(g.Longitude);
                    w.Write(" ");
                    w.Write(g.Altitude);
                    w.Write(" ");
                    w.Write(g.Speed);
                    w.WriteLine();
                }
                w.Close();
            }
        }

        void onControl(object sender, RoutedEventArgs e)
        {
            control.IsEnabled = false;
            if (tracking)
            {
                tracking = false;
                lock (lockObject)
                {
                    if (locations.Count > 0)
                    {
                        locations.Add(watcher.Position.Location);
                        timestamps.Add(watcher.Position.Timestamp.UtcTicks);
                    }
                }
                watcher.Stop();
                writeLog();
                status.Text = getStatus();
                locations = null;
                timestamps = null;
                control.Content = "Start";
                show.IsEnabled = false;
                updateLogName();
                name.IsEnabled = true;
            }
            else
            {
                name.IsEnabled = false;
                logName = name.Text;
                locations = new List<GeoCoordinate>();
                timestamps = new List<long>();
                tracking = true;
                watcher.Start();
                control.Content = "Stop";
                show.IsEnabled = true;
            }
            control.IsEnabled = true;
        }

        String getStatus()
        {
            StringBuilder b = new StringBuilder();
            lock (lockObject)
            {
                b.Append("Tracked positions: ");
                b.Append(locations.Count);
                b.AppendLine();
                if (locations.Count >= 2)
                {
                    double dist = 0.0;
                    long ticks = timestamps[timestamps.Count - 1] - timestamps[0];
                    for (int i = 1; i < locations.Count; ++i)
                        dist += locations[i - 1].GetDistanceTo(locations[i]);
                    double speed = dist / (ticks * 1e-7);
                    b.Append("Total distance:    ");
                    b.Append(dist);
                    b.AppendLine(" m");
                    b.Append("Total time:        ");
                    b.Append(new TimeSpan(ticks).ToString());
                    b.AppendLine();
                    b.Append("Average speed:     ");
                    b.Append(speed);
                    b.AppendLine(" m/s");
                    b.Append("                   ");
                    b.Append(speed * 3.6);
                    b.AppendLine(" km/h");
                }
            }
            return b.ToString();
        }

        void onShow(object sender, RoutedEventArgs e)
        {
            if (!tracking)
                return;
            status.Text = getStatus() + "GPS status:        " + watcher.Status.ToString();
        }

        protected override void OnBackKeyPress(CancelEventArgs e)
        {
            if (tracking)
            {
                MessageBoxResult result = MessageBox.Show("Tracking is in progress. If you quit, all recorded data will be lost.", "Quit Tracker?", MessageBoxButton.OKCancel);
                if (result != MessageBoxResult.OK)
                    e.Cancel = true;
            }
            base.OnBackKeyPress(e);
        }
    }
}轨迹处理工具


下面的程序可以处理轨迹数据,进行简单的分析,并将数据转换成 CSV 和 GPX 格式。前者可以用 Excel 打开,后者可以导入 Google Earth 中,并进一步转换成 KMZ 格式导入到 Google Maps 里面。

[cpp] 
#include <stdio.h>  
#include <string.h>  
#include <math.h>  
#include <vector>  
 
using std::vector; 
 
static double distance(double lat1, double lon1, double lat2, double lon2); 
static void evil_transform(double wg_lat, double wg_lon, double &mg_lat, double &mg_lon); 
static void bd_encrypt(double gg_lat, double gg_lon, double &bd_lat, double &bd_lon); 
static void change_extension(char *name, const char *ext); 
static int date_time(long long ticks, int part); 
 
struct Record 

    long long tick; 
    double lat, lon, alt, speed; 
}; 
 
struct Data 

    long long tick; 
    double lat, lon, alt, speed; 
    double time, dist, acc; 
}; 
 
const double running_threshold = 1.9; 
const double walking_threshold = 0.1; 
 
static inline int hour(long long ticks) 

    return (int)((ticks & 0x3fffffffffffffffll) / 0x861c46800ll % 24ll); 

 
static inline int minute(long long ticks) 

    return (int)((ticks & 0x3fffffffffffffffll) / 0x23c34600ll % 60ll); 

 
static inline int second(long long ticks) 

    return (int)((ticks & 0x3fffffffffffffffll) / 0x989680ll % 60ll); 

 
static inline int millisecond(long long ticks) 

    return (int)((ticks & 0x3fffffffffffffffll) / 10000 % 1000); 

 
int main(int argc, char **argv) 

    double sampling_threshold = 2.0; 
    if (argc < 2) 
    { 
        fprintf(stderr, "Usage: analyzer tracking_log.txt [sampling_threshold]\nDefault sampling threshold is 2.0 seconds.\n"); 
        return 1; 
    } 
    if (argc >= 3) 
    { 
        double arg = atof(argv[2]); 
        if (arg > 0.0 && arg < 3600.0) 
            sampling_threshold = arg; 
    } 
    if (strlen(argv[1]) > 4000) 
    { 
        fprintf(stderr, "File name too long!\n"); 
        return 1; 
    } 
 
    // Read tracking log records  
    static char buf[4096]; 
    FILE *fp = fopen(argv[1], "r"); 
    if (!fp) 
    { 
        fprintf(stderr, "Can not open %s\n", argv[1]); 
        return 1; 
    } 
    vector<Record> vr; 
    while (1) 
    { 
        if (!fgets(buf, 4096, fp)) 
            break; 
        int len = (int)strlen(buf); 
        if (len < 10 || len > 4000) 
        { 
            fprintf(stderr, "Invalid line: %d\n", (int)vr.size() + 1); 
            return 1; 
        } 
        Record rec; 
        if (sscanf(buf, "%lld%lf%lf%lf%lf", &rec.tick, &rec.lat, &rec.lon, &rec.alt, &rec.speed) != 5) 
        { 
            fprintf(stderr, "Invalid line: %d\n", (int)vr.size() + 1); 
            return 1; 
        } 
        vr.push_back(rec); 
    } 
    fclose(fp); 
 
    // Filter invalid records  
    if (vr.size() < 2) 
    { 
        fprintf(stderr, "No enough data to analyze!\n"); 
        return 1; 
    } 
    vr[0].speed = 0.0; 
    for (size_t i = 1; i < vr.size(); ++i) 
    { 
        double dd = distance(vr[i - 1].lat, vr[i - 1].lon, vr[i].lat, vr[i].lon); 
        long long dt = vr[i].tick - vr[i - 1].tick; 
        if (dt > 0) 
            vr[i].speed = dd * 1e7 / dt; 
        else 
            vr[i].speed = vr[i - 1].speed; 
    } 
    vector<Record> v2; 
    double speed_avg = 0.0, speed_devi = 0.0, speed_limit; 
    for (size_t i = 0; i < vr.size(); ++i) 
        speed_avg += vr[i].speed; 
    speed_avg /= vr.size(); 
    for (size_t i = 0; i < vr.size(); ++i) 
        speed_devi += (vr[i].speed - speed_avg) * (vr[i].speed - speed_avg); 
    speed_devi = sqrt(speed_devi / vr.size()); 
    speed_limit = speed_avg + 3.0 * speed_devi; 
    //  fprintf(stderr, "speed avg, devi, limit: %.2lf, %.2lf, %.2lf\n", speed_avg, speed_devi, speed_limit);  
    for (size_t i = 0; i < vr.size(); ++i) 
        if (vr[i].speed < speed_limit) 
            v2.push_back(vr[i]); 
    vr.swap(v2); 
    v2.clear(); 
 
    // Resample data  
    if (vr.size() < 2) 
    { 
        fprintf(stderr, "No enough data to analyze!\n"); 
        return 1; 
    } 
    vector<Data> vd; 
    { 
        Data dat0; 
        dat0.tick = vr[0].tick; 
        dat0.lat = vr[0].lat; 
        dat0.lon = vr[0].lon; 
        dat0.alt = vr[0].alt; 
        dat0.speed = 0.0; 
        dat0.time = 0.0; 
        dat0.dist = 0.0; 
        dat0.acc = 0.0; 
        vd.push_back(dat0); 
    } 
    long long begin = vr[0].tick; 
    double prev_time = 0.0, dist = 0.0; 
    for (size_t i = 1; i < vr.size(); ++i) 
    { 
        double time = (vr[i].tick - begin) * 1e-7; 
        if (i + 1 < vr.size() && time - prev_time < sampling_threshold) 
            continue; 
        long long dt = vr[i].tick - vd.back().tick; 
        if (dt <= 0) 
            continue; 
        Data dat; 
        double dd = distance(vd.back().lat, vd.back().lon, vr[i].lat, vr[i].lon); 
        dist += dd; 
        dat.tick = vr[i].tick; 
        dat.lat = vr[i].lat; 
        dat.lon = vr[i].lon; 
        dat.alt = vr[i].alt; 
        dat.speed = dd * 1e7 / dt; 
        dat.time = time; 
        dat.dist = dist; 
        vd.push_back(dat); 
        prev_time = time; 
    } 
    vr.clear(); 
 
    // Analyze data  
    if (vd.size() < 2) 
    { 
        fprintf(stderr, "No enough data to analyze!\n"); 
        return 1; 
    } 
    for (size_t i = 1; i + 1 < vd.size(); ++i) 
    { 
        vd[i].acc = (vd[i + 1].speed - vd[i].speed) * 2e7 / (vd[i + 1].tick - vd[i - 1].tick); 
        vd[i].speed = (vd[i].speed * (vd[i + 1].tick - vd[i].tick) + vd[i + 1].speed * (vd[i].tick - vd[i - 1].tick)) / (vd[i + 1].tick - vd[i - 1].tick); 
    } 
    vd.back().speed = 0.0; 
    vd.back().acc = 0.0; 
    double dist_r = 0.0, mx_speed = 0.0; 
    long long time_r = 0, time_w = 0;  
    for (size_t i = 1; i < vd.size(); ++i) 
    { 
        double dd = vd[i].dist - vd[i - 1].dist; 
        long long dt = vd[i].tick - vd[i - 1].tick; 
        if (vd[i].speed > running_threshold) 
        { 
            dist_r += dd; 
            time_r += dt; 
            if (vd[i].speed > mx_speed) 
                mx_speed = vd[i].speed; 
        } 
        else if (vd[i].speed > walking_threshold) 
            time_w += dt; 
    } 
    double dist_a = vd.back().dist, dist_w = dist_a - dist_r; 
    long long time_a = vd.back().tick - vd.front().tick, time_s = time_a - time_r - time_w; 
    printf("%30s: %.3lf km\n", "Total distance", dist_a * 1e-3); 
    printf("%30s: %.3lf km\n", "Running distance", dist_r * 1e-3); 
    printf("%30s: %.3lf km\n", "Walking distance", dist_w * 1e-3); 
    printf("%30s: %d h %d m %d.%03d s\n", "Total time", hour(time_a), minute(time_a), second(time_a), millisecond(time_a)); 
    printf("%30s: %d h %d m %d.%03d s\n", "Running time", hour(time_r), minute(time_r), second(time_r), millisecond(time_r)); 
    printf("%30s: %d h %d m %d.%03d s\n", "Walking time", hour(time_w), minute(time_w), second(time_w), millisecond(time_w)); 
    printf("%30s: %d h %d m %d.%03d s\n", "Stopped time", hour(time_s), minute(time_s), second(time_s), millisecond(time_s)); 
    printf("%30s: %.2lf m/s , %.2lf km/h\n", "Max speed", mx_speed, mx_speed * 3.6); 
    printf("%30s: %.2lf m/s , %.2lf km/h\n", "Average speed", dist_a * 1e7 / time_a, dist_a * 3.6e7 / time_a); 
    printf("%30s: %.2lf m/s , %.2lf km/h\n", "Average running speed", dist_r * 1e7 / time_r, dist_r * 3.6e7 / time_r); 
    printf("%30s: %.2lf m/s , %.2lf km/h\n", "Average walking speed", dist_w * 1e7 / time_w, dist_w * 3.6e7 / time_w); 
 
    // Export data to CSV  
    strcpy(buf, argv[1]); 
    change_extension(buf, ".csv"); 
    fp = fopen(buf, "w"); 
    if (!fp) 
    { 
        fprintf(stderr, "Can not write to %s\n", buf); 
        return 1; 
    } 
    fprintf(fp, "Time(s),Distance(km),Altitude(m),Speed(m/s),Speed(km/h),Acceleration(m/s^2)\n"); 
    for (size_t i = 0; i < vd.size(); ++i) 
        fprintf(fp, "%.2lf,%.3lf,%.1lf,%.2lf,%.2lf,%.2lf\n", vd[i].time, vd[i].dist * 1e-3, vd[i].alt, vd[i].speed, vd[i].speed * 3.6, vd[i].acc); 
    fclose(fp); 
 
    // Export data to GPX  
    const char gpx_head[] = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\n\n" 
                            "<gpx xmlns=\"https://www.topografix.com/GPX/1/1\" version=\"1.1\" creator=\"Analyzer for WP7Tracker\">\n" 
                            "<metadata><name>%s</name><link href=\"https://blog.csdn.net/coolypf/\"><text>coolypf</text></link></metadata>\n" 
                            "<trk><name>%s</name><trkseg>\n"; 
    const char gpx_tail[] = "</trkseg></trk></gpx>\n"; 
 
    strcpy(buf, argv[1]); 
    change_extension(buf, ".wgs-84.gpx"); 
    fp = fopen(buf, "w"); 
    if (!fp) 
    { 
        fprintf(stderr, "Can not write to %s\n", buf); 
        return 1; 
    } 
    fprintf(fp, gpx_head, buf, buf); 
    for (size_t i = 0; i < vd.size(); ++i) 
    { 
        fprintf(fp, "<trkpt lat=\"%.6lf\" lon=\"%.6lf\"><ele>%.1lf</ele>", vd[i].lat, vd[i].lon, vd[i].alt); 
        long long tick = vd[i].tick; 
        fprintf(fp, "<time>%04d-%02d-%02dT%02d:%02d:%02dZ</time></trkpt>\n", 
                date_time(tick, 0), date_time(tick, 2), date_time(tick, 3), 
                hour(tick), minute(tick), second(tick)); 
    } 
    fprintf(fp, gpx_tail); 
    fclose(fp); 
 
    strcpy(buf, argv[1]); 
    change_extension(buf, ".gcj-02.gpx"); 
    fp = fopen(buf, "w"); 
    if (!fp) 
    { 
        fprintf(stderr, "Can not write to %s\n", buf); 
        return 1; 
    } 
    fprintf(fp, gpx_head, buf, buf); 
    for (size_t i = 0; i < vd.size(); ++i) 
    { 
        double lat, lon; 
        evil_transform(vd[i].lat, vd[i].lon, lat, lon); 
        vd[i].lat = lat; 
        vd[i].lon = lon; 
        fprintf(fp, "<trkpt lat=\"%.6lf\" lon=\"%.6lf\"><ele>%.1lf</ele>", vd[i].lat, vd[i].lon, vd[i].alt); 
        long long tick = vd[i].tick; 
        fprintf(fp, "<time>%04d-%02d-%02dT%02d:%02d:%02dZ</time></trkpt>\n", 
                date_time(tick, 0), date_time(tick, 2), date_time(tick, 3), 
                hour(tick), minute(tick), second(tick)); 
    } 
    fprintf(fp, gpx_tail); 
    fclose(fp); 
 
    strcpy(buf, argv[1]); 
    change_extension(buf, ".bd-09.gpx"); 
    fp = fopen(buf, "w"); 
    if (!fp) 
    { 
        fprintf(stderr, "Can not write to %s\n", buf); 
        return 1; 
    } 
    fprintf(fp, gpx_head, buf, buf); 
    for (size_t i = 0; i < vd.size(); ++i) 
    { 
        double lat, lon; 
        bd_encrypt(vd[i].lat, vd[i].lon, lat, lon); 
        vd[i].lat = lat; 
        vd[i].lon = lon; 
        fprintf(fp, "<trkpt lat=\"%.6lf\" lon=\"%.6lf\"><ele>%.1lf</ele>", vd[i].lat, vd[i].lon, vd[i].alt); 
        long long tick = vd[i].tick; 
        fprintf(fp, "<time>%04d-%02d-%02dT%02d:%02d:%02dZ</time></trkpt>\n", 
                date_time(tick, 0), date_time(tick, 2), date_time(tick, 3), 
                hour(tick), minute(tick), second(tick)); 
    } 
    fprintf(fp, gpx_tail); 
    fclose(fp); 
 
    return 0; 

 
const double pi = 3.14159265358979324; 
const double f = pi / 180.0; 
const double x_pi = f * 3000.0; 
const double a = 6378245.0; 
const double ee = 0.00669342162296594323; 
const double r = 6376500.0; 
 
double distance(double lat1, double lon1, double lat2, double lon2) 

    double rad1 = lat1 * f, rad2 = lat2 * f; 
    double dlat = rad2 - rad1, dlon = (lon2 - lon1) * f; 
    double x = pow(sin(dlat / 2.0), 2.0) + (cos(rad1) * cos(rad2)) * pow(sin(dlon / 2.0), 2.0); 
    return r * 2.0 * atan2(sqrt(x), sqrt(1.0 - x)); 

 
static bool out_of_mars(double lat, double lon) 

    if (lon < 72.004 || lon > 137.8347) 
        return true; 
    if (lat < 0.8293 || lat > 55.8271) 
        return true; 
    return false; 

 
static double transform_lat(double x, double y) 

    double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * sqrt(fabs(x)); 
    ret += (20.0 * sin(6.0 * x * pi) + 20.0 * sin(2.0 * x * pi)) * 2.0 / 3.0; 
    ret += (20.0 * sin(y * pi) + 40.0 * sin(y / 3.0 * pi)) * 2.0 / 3.0; 
    ret += (160.0 * sin(y / 12.0 * pi) + 320 * sin(y * pi / 30.0)) * 2.0 / 3.0; 
    return ret; 

 
static double transform_lon(double x, double y) 

    double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * sqrt(fabs(x)); 
    ret += (20.0 * sin(6.0 * x * pi) + 20.0 * sin(2.0 * x * pi)) * 2.0 / 3.0; 
    ret += (20.0 * sin(x * pi) + 40.0 * sin(x / 3.0 * pi)) * 2.0 / 3.0; 
    ret += (150.0 * sin(x / 12.0 * pi) + 300.0 * sin(x / 30.0 * pi)) * 2.0 / 3.0; 
    return ret; 

 
void evil_transform(double wg_lat, double wg_lon, double &mg_lat, double &mg_lon) 

    if (out_of_mars(wg_lat, wg_lon)) 
    { 
        mg_lat = wg_lat; 
        mg_lon = wg_lon; 
        return; 
    } 
    double d_lat = transform_lat(wg_lon - 105.0, wg_lat - 35.0); 
    double d_lon = transform_lon(wg_lon - 105.0, wg_lat - 35.0); 
    double rad_lat = wg_lat / 180.0 * pi; 
    double magic = sin(rad_lat); 
    magic = 1 - ee * magic * magic; 
    double sqrt_magic = sqrt(magic); 
    d_lat = (d_lat * 180.0) / ((a * (1 - ee)) / (magic * sqrt_magic) * pi); 
    d_lon = (d_lon * 180.0) / (a / sqrt_magic * cos(rad_lat) * pi); 
    mg_lat = wg_lat + d_lat; 
    mg_lon = wg_lon + d_lon; 

 
void bd_encrypt(double gg_lat, double gg_lon, double &bd_lat, double &bd_lon) 

    double x = gg_lon, y = gg_lat; 
    double z = sqrt(x * x + y * y) + 0.00002 * sin(y * x_pi); 
    double theta = atan2(y, x) + 0.000003 * cos(x * x_pi); 
    bd_lon = z * cos(theta) + 0.0065; 
    bd_lat = z * sin(theta) + 0.006; 

 
void change_extension(char *name, const char *ext) 

    int i = (int)strlen(name); 
    while (1) 
    { 
        if (i <= 0 || name[i] == '/' || name[i] =='\\') 
        { 
            i = (int)strlen(name); 
            break; 
        } 
        if (name[i] == '.') 
            break; 
        --i; 
    } 
    strcpy(name + i, ext); 

 
int date_time(long long ticks, int part) 

    const int days_to_month_365[] = { 0, 0x1f, 0x3b, 90, 120, 0x97, 0xb5, 0xd4, 0xf3, 0x111, 0x130, 0x14e, 0x16d }; 
    const int days_to_month_366[] = { 0, 0x1f, 60, 0x5b, 0x79, 0x98, 0xb6, 0xd5, 0xf4, 0x112, 0x131, 0x14f, 0x16e }; 
    ticks &= 0x3fffffffffffffffll; 
    int num2 = (int)(ticks / 0xc92a69c000ll); 
    int num3 = num2 / 0x23ab1; 
    num2 -= num3 * 0x23ab1; 
    int num4 = num2 / 0x8eac; 
    if (num4 == 4) 
        num4 = 3; 
    num2 -= num4 * 0x8eac; 
    int num5 = num2 / 0x5b5; 
    num2 -= num5 * 0x5b5; 
    int num6 = num2 / 0x16d; 
    if (num6 == 4) 
        num6 = 3; 
    if (part == 0) 
        return num3 * 400 + num4 * 100 + num5 * 4 + num6 + 1; 
    num2 -= num6 * 0x16d; 
    if (part == 1) 
        return num2 + 1; 
    const int *num_array = (num6 == 3 && (num5 != 0x18 || num4 == 3)) ? days_to_month_366 : days_to_month_365; 
    int index = num2 >> 6; 
    while (num2 >= num_array[index]) 
        index++; 
    if (part == 2) 
        return index; 
    return num2 - num_array[index - 1] + 1; 

相关频道:

用户评论