728x90
gpx 파일을 다운로드 받을 수 있다.
<?xml version="1.0" encoding="UTF-8"?>
<gpx creator="StravaGPX" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"
version="1.1" xmlns="http://www.topografix.com/GPX/1/1">
<metadata>
<time>2013-07-19T11:55:35Z</time>
</metadata>
<trk>
<name>오전 라이딩</name>
<type>1</type>
<trkseg>
<trkpt lat="41.9323470" lon="-87.6441970">
<ele>182.2</ele>
<time>2013-07-19T11:55:35Z</time>
</trkpt>
<trkpt lat="41.9323870" lon="-87.6449280">
<ele>183.2</ele>
<time>2013-07-19T14:42:01Z</time>
</trkpt>
<trkpt lat="41.9322950" lon="-87.6448010">
<ele>183.2</ele>
<time>2013-07-19T14:42:19Z</time>
</trkpt>
<trkpt lat="41.9322280" lon="-87.6446340">
<ele>183.2</ele>
<time>2013-07-19T14:42:45Z</time>
</trkpt>
<trkpt lat="41.9323360" lon="-87.6448060">
<ele>183.2</ele>
<time>2013-07-19T14:43:08Z</time>
</trkpt>
<trkpt lat="41.9326000" lon="-87.6441310">
<ele>181.9</ele>
<time>2013-07-19T14:43:30Z</time>
</trkpt>
<trkpt lat="41.9329520" lon="-87.6444520">
<ele>182.3</ele>
<time>2013-07-19T14:44:22Z</time>
</trkpt>
<trkpt lat="41.9328460" lon="-87.6437660">
....
*.gpx 파일을 열어보면 xml 스키 안에 특정 시간 간격으로 (예:1초) 기본적으로 기록되는 시각, 경도와 위도 그리고 주변기기와 연동하면 케이던스(rpm:1분동안 페달링 한 횟수), 심장박동수, 파워(w:와트) 정보등을 확인할 수 있다.
기록되는 형식은 gpx, kml, Tcx, kmz 등 여러가지 포맷이 있다. 또 자전거 컴퓨터(gps 속도계)의 제조사에 따라 저장되는 파일 형식이 다를 수 있다.
아래 코드는 gpx 파일에서 데이터를 추출하는 파서(Paser)이다.
/// <summary>
/// *.gpx 파일 파싱
/// </summary>
public class GpxPaser
{
List<GpsLogData> listGpxLog = null;
public string FileName { get; set; }
public string TimeType { get; set; }
public GpxPaser(string fileName, string timeType)
{
this.FileName = fileName;
this.TimeType = timeType;
listGpxLog = new List<GpsLogData>();
}
/// <summary>
/// Gpx 데이터 파싱
/// </summary>
/// <param name="listRideDate"></param>
/// <returns></returns>
public List<GpsLogData> Paser(List<RideInfo> listRideDate)
{
DateTimeHelper.DateFormat dateformat = DateTimeHelper.DateFormat.CONVERT_NOMAL;
switch (TimeType)
{
case "UTC":
dateformat = DateTimeHelper.DateFormat.CONVERT_LOCAL_TO_UTC;
break;
case "LOCAL":
dateformat = DateTimeHelper.DateFormat.CONVERT_UTC_TO_LOCAL;
break;
case "NOMAL":
dateformat = DateTimeHelper.DateFormat.CONVERT_NOMAL;
break;
}
XmlDocument xml = new XmlDocument();
xml.Load(FileName);
string utcTime = string.Empty;
string localTime = string.Empty;
string rideDateOrigen = string.Empty;
string overlap = string.Empty;
XmlNodeList metaNodes = xml.GetElementsByTagName("metadata");
if (metaNodes.Count > 0)
{
foreach (XmlNode node in metaNodes)
{
utcTime = node["time"] != null ? node["time"].InnerText.ToString() : string.Empty;
rideDateOrigen = DateTimeHelper.ConvertTimeTotime(dateformat, utcTime, "R", 0);
}
}
else
{
XmlNodeList time = xml.GetElementsByTagName("time");
utcTime = time[0].InnerText;
rideDateOrigen = DateTimeHelper.ConvertTimeTotime(dateformat, utcTime, "R", 0);
}
// 중복체크
foreach (RideInfo day in listRideDate)
{
if (day.RIDE_DATE_ORIGEN == rideDateOrigen)
{
overlap = "Y";
break;
}
}
string name = string.Empty;
XmlNodeList trkNode = xml.GetElementsByTagName("trk");
foreach (XmlNode node in trkNode)
{
name = node["name"] != null ? node["name"].InnerText : string.Empty;
}
var nsmgr = new XmlNamespaceManager(xml.NameTable);
// Path 검색을 위한 NameSpace 설정
nsmgr.AddNamespace("i", "http://www.topografix.com/GPX/1/1");
nsmgr.AddNamespace("gpxtpx", "http://www.garmin.com/xmlschemas/TrackPointExtension/v1");
XmlNodeList nodes = xml.SelectNodes("//i:trkpt", nsmgr);
if (nodes.Count == 0)
nodes = xml.GetElementsByTagName("trkpt");
// log No
int daySeq = 0;
foreach (XmlNode node in nodes)
{
daySeq++;
GpsLogCalculate gpsCalc = new GpsLogCalculate();
GpsLogData log = new GpsLogData();
log.TITLE = name;
log.RIDE_DATE = rideDateOrigen.Substring(0, 10);
log.LAT = Convert.ToDouble(node.Attributes["lat"].Value);
log.LNG = Convert.ToDouble(node.Attributes["lon"].Value);
log.ELE = node["ele"] != null ? Math.Round(Convert.ToDouble(node["ele"].InnerText), 1) : 0;
log.RIDE_DATE_ORIGEN = rideDateOrigen;
utcTime = node["time"] != null ? node["time"].InnerText : string.Empty;
localTime = DateTimeHelper.ConvertTimeTotime(dateformat, utcTime, "L", daySeq);
log.LOG_TIME_ORIGEN = localTime;
log.LOG_TIME = utcTime != string.Empty ? localTime.Substring(0, 19) : localTime;
string gpxtx = "i:extensions/gpxtpx:TrackPointExtension/gpxtpx:{0}";
// 기온 : Xml Path
var atemp = node.SelectSingleNode(string.Format(gpxtx, "atemp"), nsmgr);
log.ATEMP = atemp != null ? Convert.ToDouble(atemp.InnerText) : 0;
// 케이던스 : Xml Path
var cad = node.SelectSingleNode(string.Format(gpxtx, "cad"), nsmgr);
log.CAD = cad != null ? Convert.ToDouble(cad.InnerText) : 0;
// 심박수 : Xml Path
var heart = node.SelectSingleNode(string.Format(gpxtx, "hr"), nsmgr);
log.HEART = heart != null ? Convert.ToDouble(heart.InnerText) : 0;
// 좌표간 거리, 속도 계산
if (listGpxLog.Count >= 1)
{
// row Count
int iCount = listGpxLog.Count - 1;
// 좌표 위경도
double lat = listGpxLog[iCount].LAT;
double lng = listGpxLog[iCount].LNG;
// 좌표간 로그 시작시간과 끝시간
string startDate = listGpxLog[iCount].LOG_TIME;
string endDate = log.LOG_TIME;
// 좌표간 거리계산
double km = gpsCalc.Distance(lat, lng, log.LAT, log.LNG);
// 거리
log.KM = Utils.Common.NaNValue(km);
if (startDate != string.Empty && endDate != string.Empty)
{
// 좌표 A=>B까지 속도(km/h)
log.SPEED_KMH = Math.Round((km > 0 ? GpsLogCalculate.GetKph(km, startDate, endDate) : 0), 1);
// 좌표 A=>B까지 시간
log.DIFF_TIME = DateTimeHelper.GetTimeSpan(startDate, endDate).Seconds;
}
else
{
log.SPEED_KMH = 0;
log.DIFF_TIME = 0;
}
}
log.DAY_SEQ = daySeq.ToString();
log.OVERLAP = overlap; // DB 중복체크
if(log.SPEED_KMH <= 300)
listGpxLog.Add(log);
log = null;
}
// Way Point
XmlNodeList wptNodes = xml.GetElementsByTagName("wpt");
if (wptNodes.Count > 0)
{
int wptSeq = 0;
foreach (XmlNode wpt in wptNodes)
{
GpsLogData wp = new GpsLogData();
wptSeq++;
wp.LAT = Convert.ToDouble(wpt.Attributes["lat"].Value);
wp.LNG = Convert.ToDouble(wpt.Attributes["lon"].Value);
wp.ELE = wpt["ele"] != null ? Convert.ToDouble(wpt["ele"].InnerText) : 0;
wp.TITLE = wpt["name"].InnerText;
wp.RIDE_DATE_ORIGEN = rideDateOrigen;
wp.WAYPOINT = "Y";
wp.DAY_SEQ = wptSeq.ToString();
listGpxLog.Add(wp);
}
}
return listGpxLog;
}
추출하면 위와 같은 형태의 데이터를 얻을 수 있다.
gpx : https://ko.wikipedia.org/wiki/GPX (위키백과)
'.NET C#' 카테고리의 다른 글
자전거 칼로리 공식 (0) | 2023.01.15 |
---|---|
c# 자전거 라이딩 거리 계산 관련 Utils (0) | 2023.01.13 |
c# DateTime (날짜, 시간, 요일 추출) Utils (0) | 2023.01.13 |
코드 블럭 테스트 (c# DB Helper) (0) | 2023.01.12 |
시작일과 종료일 기간 체크 및 날짜 등분 (0) | 2012.05.05 |
시작과 종료일 날짜 간격 구하는 로직 (0) | 2012.05.03 |
Visual Studio 2010 and .NET Framework 4.0 Training Kit - November Preview (0) | 2008.11.30 |
댓글