ImgGPS2KML/ImgGPS2KML/MainWin.cs

238 lines
9.6 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using ExifLib;
using System.Xml;
using Microsoft.WindowsAPICodePack.Dialogs;
using System.IO;
namespace ImgGPS2KML
{
public partial class MainWin : Form
{
public MainWin()
{
InitializeComponent();
}
private void putPlacemark(XmlTextWriter writer,string name, double longitude, double latitude)
{
writer.WriteStartElement("Placemark");
writer.WriteStartElement("name");
writer.WriteString(name);
writer.WriteEndElement();//end of name
writer.WriteStartElement("Style");
writer.WriteStartElement("IconStyle");
writer.WriteStartElement("Icon");
writer.WriteStartElement("href");
writer.WriteString("http://maps.google.com/mapfiles/kml/paddle/blu-blank.png");
writer.WriteEndElement();//end of href
writer.WriteEndElement();//end of Icon
writer.WriteStartElement("color");
writer.WriteString("ffffffff");
writer.WriteEndElement();//end of color
writer.WriteStartElement("scale");
writer.WriteString("1.0");
writer.WriteEndElement();//end of scale
writer.WriteEndElement();//end of IconStyle
writer.WriteEndElement();//end of Style
writer.WriteStartElement("Point");
writer.WriteStartElement("coordinates");
writer.WriteString(String.Format("{0},{1},0", longitude, latitude));
writer.WriteEndElement();//end of coordinates
writer.WriteEndElement();//end of Point
writer.WriteEndElement();//end of Placemark
}
private double toDecimalUnit(double degree, double minute, double second)//把2度2分3秒这样的数据转换成2.3212这样的数据。
{
return degree + minute / 60 + second / 3600;
}
//private double distanceByLongNLat(double long1, double lat1, double long2, double lat2)//计算经纬度两点间距离
//{
// double a, b, R;
// R = 6378137;//地球半径
// lat1 = lat1 * Math.PI / 180.0;
// lat2 = lat2 * Math.PI / 180.0;
// a = lat1 - lat2;
// b = (long1 - long2) * Math.PI / 180.0;
// double d;
// double sa2, sb2;
// sa2 = Math.sin(a / 2.0);
// sb2 = Math.sin(b / 2.0);
// d = 2 * R * Math.asin(Math.sqrt(sa2 * sa2 + Math.cos(lat1) * Math.cos(lat2) * sb2 * sb2));
// return d;
//}
private List<double[]> extractCordinattionFromImg(List<string> imgPaths)//获得所有图片的坐标
{
List<double[]> longitudNLatitude = new List<double[]>();//第一个是经度,第二个是纬度
foreach (string path in imgPaths)
{
try
{
using (ExifReader reader = new ExifReader(path))
{
double[] longitude;//经度
double[] latitude;//纬度
reader.GetTagValue<double[]>(ExifTags.GPSLongitude, out longitude);
reader.GetTagValue<double[]>(ExifTags.GPSLatitude, out latitude);
if (longitude == null || latitude == null)
{
continue;
}
double decimalLongtitude;
decimalLongtitude = toDecimalUnit(longitude[0], longitude[1], longitude[2]);
double decimalLatitude;
decimalLatitude = toDecimalUnit(latitude[0], latitude[1], latitude[2]);
longitudNLatitude.Add(new double[] { decimalLongtitude, decimalLatitude });
}
}
catch
{
}
}
return longitudNLatitude;
}
double[] get_centroid(List<double[]> cluster)
{
double x;
double y;
double z;
x = 0;
y = 0;
z = 0;
int coord_num = cluster.Count;
foreach (double[] coord in cluster)
{
double lon = coord[0] / 180 * Math.PI;
double lat = coord[1] / 180 * Math.PI;
x += Math.Cos(lat) * Math.Cos(lon);
y += Math.Cos(lat) * Math.Sin(lon);
z += Math.Sin(lat);
}
x /= coord_num;
y /= coord_num;
z /= coord_num;
return new double[] { Math.Atan2(y, x) * 180 / Math.PI, Math.Atan2(z, Math.Sqrt(x * x + y * y)) * 180 / Math.PI };
}
private List<string> searchJPG(string sourceDir)
{
string[] allFiles = Directory.GetFiles(sourceDir);
List<string> jpgFiles = new List<string>();
foreach (string file in allFiles)
{
if (Path.GetExtension(file).ToLower() == ".jpg")
{
jpgFiles.Add(file);
}
}
return jpgFiles;
}
private void bt_add_directory(object sender, EventArgs e)
{
this.dvDirectory.Rows.Clear();
CommonOpenFileDialog dialog = new CommonOpenFileDialog();
dialog.Multiselect = true;
dialog.IsFolderPicker = true;
if (dialog.ShowDialog() == CommonFileDialogResult.Ok)
{
foreach (String selectDir in dialog.FileNames)
{
string coordination_col_text;
bool canExport;
canExport = true;
List<string> imgPaths = searchJPG(selectDir);
if (imgPaths.Count > 0)
{
List<double[]> coordinationOfImg;
coordinationOfImg = extractCordinattionFromImg(imgPaths);
if (coordinationOfImg.Count > 0)
{
double[] centroid;
centroid = get_centroid(coordinationOfImg);//计算所有图片坐标的中心
coordination_col_text = string.Format("{0},{1}", centroid[0], centroid[1]);
}
else
{
coordination_col_text = "图片中未找到坐标。";
canExport = false;
}
}
else
{
coordination_col_text="未找到图片。";
canExport = false;
}
this.dvDirectory.Rows.Add(new object[]{selectDir,coordination_col_text,canExport});
}
}
}
private void btExportKML_Click(object sender, EventArgs e)
{
SaveFileDialog dialog = new SaveFileDialog();
dialog.Filter = "kml file (*.kml)|*.kml";
if (dialog.ShowDialog() == DialogResult.OK)
{
using (XmlTextWriter writer = new XmlTextWriter(dialog.FileName, Encoding.UTF8))
{
writer.Formatting = Formatting.Indented;
writer.WriteStartDocument();
writer.WriteStartElement("kml");
writer.WriteStartAttribute("xmlns");
writer.WriteString("http://www.opengis.net/kml/2.2");
writer.WriteEndAttribute();
writer.WriteStartAttribute("xmlns:gx");
writer.WriteString("http://www.google.com/kml/ext/2.2");
writer.WriteEndAttribute();
writer.WriteStartAttribute("xmlns:atom");
writer.WriteString("http://www.w3.org/2005/Atom");
writer.WriteEndAttribute();
writer.WriteStartElement("Document");
writer.WriteStartElement("name");
writer.WriteString("照片导出坐标");
writer.WriteEndElement();//end of name
foreach (DataGridViewRow row in this.dvDirectory.Rows)
{
Int32 canExport;
DataGridViewCheckBoxCell checkBoxColum=row.Cells[2] as DataGridViewCheckBoxCell;
canExport =Convert.ToInt32(checkBoxColum.Value);
if (canExport !=1)
{
continue;
}
double longitude;
double latitude;
string name;
name = Path.GetFileName(Convert.ToString(row.Cells[0].Value));
longitude = Convert.ToDouble(Convert.ToString(row.Cells[1].Value).Split(',')[0]);
latitude = Convert.ToDouble(Convert.ToString(row.Cells[1].Value).Split(',')[1]);
putPlacemark(writer, name, longitude, latitude);
}
writer.WriteEndElement();//end of Document
writer.WriteEndElement();//end of xml
writer.WriteEndDocument();
}
MessageBox.Show("已导出");
}
}
}
}