private bool LoadT2f(string filename, bool showSummary, bool append) { bool loaded_ok = false; IFileSupport fs = null; int Plot2ndCount_old; int WaypointsCountOld; if (append) { Plot2ndCount_old = Plot2ndCount; WaypointsCountOld = WayPointsT2F.Count; } else { Plot2ndCount_old = 0; WaypointsCountOld = 0; } switch (Path.GetExtension(filename).ToLower()) { case ".gcc": fs = new GccSupport(); break; case ".gpx": fs = new GpxSupport(); break; case ".kml": fs = new KmlSupport(); break; default: MessageBox.Show("wrong extension"); return false; } if (fs != null) { mapUtil.clearNav(false); loaded_ok = fs.Load(filename, ref WayPointsT2F, PlotDataSize, ref Plot2ndLat, ref Plot2ndLong, ref Plot2ndZ, ref Plot2ndT, ref Plot2ndD, ref T2fSummary, ref Plot2ndCount, append); graph.scaleCmd = Graph.ScaleCmd.DoAutoscaleNoUndo; } if (loaded_ok) // loaded OK { // If a new track-to-follow loaded (and main track not exist) - need to reset map zoom/shift vars if ((Plot2ndCount + WayPointsT2F.Count != 0) && (PlotCount == 0)) { ResetMapPosition(); } labelFileNameT2F.SetText("Track to Follow: " + Path.GetFileName(filename)); if (Plot2ndCount - Plot2ndCount_old == 0 && WayPointsT2F.Count - WaypointsCountOld > 0) //if no track -> copy WP-data to T2F { if (DialogResult.Yes == MessageBox.Show("Use waypoints as track to navigate?", "File only has Waypoints", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1)) { double OldLong, OldLat; if (Plot2ndCount > 0) { OldLong = Plot2ndLong[Plot2ndCount - 1]; OldLat = Plot2ndLat[Plot2ndCount - 1]; } else { OldLong = WayPointsT2F.lon[WaypointsCountOld]; OldLat = WayPointsT2F.lat[WaypointsCountOld]; } double deltax, deltay; UtmUtil utmUtil2 = new UtmUtil(); //use extra utmUtil utmUtil2.setReferencePoint(OldLat, OldLong); for (int i = WaypointsCountOld; i < WayPointsT2F.Count; i++) { if (Plot2ndCount >= PlotDataSize) // check if we need to decimate arrays { for (int j = 0; j < PlotDataSize / 2; j++) { Plot2ndLat[j] = Plot2ndLat[j * 2]; Plot2ndLong[j] = Plot2ndLong[j * 2]; Plot2ndZ[j] = Plot2ndZ[j * 2]; Plot2ndT[j] = Plot2ndT[j * 2]; Plot2ndD[j] = Plot2ndD[j * 2]; } Plot2ndCount = PlotDataSize / 2; //Decimation *= 2; //use all new data } Plot2ndLong[Plot2ndCount] = WayPointsT2F.lon[i]; Plot2ndLat[Plot2ndCount] = WayPointsT2F.lat[i]; deltax = (Plot2ndLong[Plot2ndCount] - OldLong) * utmUtil2.longit2meter; deltay = (Plot2ndLat[Plot2ndCount] - OldLat) * utmUtil2.lat2meter; T2fSummary.Distance += Math.Sqrt(deltax * deltax + deltay * deltay); OldLong = Plot2ndLong[Plot2ndCount]; OldLat = Plot2ndLat[Plot2ndCount]; Plot2ndD[Plot2ndCount] = (int)T2fSummary.Distance; Plot2ndT[Plot2ndCount] = Plot2ndCount == 0 ? 0 : Plot2ndT[Plot2ndCount - 1] + 1; Plot2ndZ[Plot2ndCount] = 0; Plot2ndCount++; } } } Plot2ndCountUndo = Plot2ndCount; updateNavData(); if (showSummary) loaded_ok = DialogResult.OK == ShowTrackSummary(T2fSummary); } else { labelFileNameT2F.SetText("Track to Follow: " + Path.GetFileName(filename) + " load ERROR"); T2fSummary.desc = "Error loading file"; MessageBox.Show("Error reading file or it does not have track data", "Error loading file", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1); } return loaded_ok; }
public void LoadMaps(string mapsFilesDirectory) { NumMaps = 0; NumBitmaps = 0; string jpg_name = ""; MapsFilesDirectory = mapsFilesDirectory; // dispose of all old maps and reset vars RemoveBitmaps(0); for (int i = 0; i < MaxNumMaps; i++) { Maps[i].zoom_level = 0.0; Maps[i].overlap = 0.0; Maps[i].qfactor = 0.0; } string crFile = mapsFilesDirectory + "\\copyright.txt"; if (File.Exists(crFile)) { StreamReader sr = null; try { sr = new StreamReader(crFile, Encoding.UTF7); mapCopyright = sr.ReadLine(); } catch { mapCopyright = null; } if (sr != null) sr.Close(); } else mapCopyright = null; OsmTilesMode = DetectOsmTiles(); if (!OsmTilesMode && parent.checkDownloadOsm.Checked) { // if want to download - force OsmTilesMode and enable all zoom levels for (int allowed_i = 0; allowed_i < OsmNumZoomLevels; allowed_i++) { OsmZoomAvailable[allowed_i] = true; } OsmFileExtension = ".png"; OsmTilesMode = true; } if (OsmTilesMode) { // all OSM tiles are 256x256 for (int i = 0; i < MaxNumMaps; i++) { Maps[i].sizeX = 256; Maps[i].sizeY = 256; } LoadOsmServer(); return; } // loop over possible map names and load existing map info Cursor.Current = Cursors.WaitCursor; OsmZoom = 1; //otherwise zoom out may be prevented // load jpeg and jpg files string[] jfiles1 = Directory.GetFiles(mapsFilesDirectory, "*.jpg"); string[] jfiles2 = Directory.GetFiles(mapsFilesDirectory, "*.jpeg"); string[] jpg_files = new string[jfiles1.Length + jfiles2.Length]; int tmpi = 0; for (int i = 0; i < jfiles1.Length; i++) { jpg_files[tmpi] = jfiles1[i]; tmpi++; } for (int i = 0; i < jfiles2.Length; i++) { jpg_files[tmpi] = jfiles2[i]; tmpi++; } Array.Sort(jpg_files); // set "." as decimal separator for reading the map info NumberFormatInfo number_info = new NumberFormatInfo(); number_info.NumberDecimalSeparator = "."; for (int i = 0; i < jpg_files.Length; i++) { jpg_name = Path.GetFileName(jpg_files[i]); // kml file name string kml_file = Path.GetFileNameWithoutExtension(jpg_files[i]) + ".kml"; if (mapsFilesDirectory == "\\") { kml_file = "\\" + kml_file; } else { kml_file = mapsFilesDirectory + "\\" + kml_file; } // text file name string txt_file = Path.GetFileNameWithoutExtension(jpg_files[i]) + ".txt"; if (mapsFilesDirectory == "\\") { txt_file = "\\" + txt_file; } else { txt_file = mapsFilesDirectory + "\\" + txt_file; } // gmi file name string gmi_file = Path.GetFileNameWithoutExtension(jpg_files[i]) + ".gmi"; if (mapsFilesDirectory == "\\") { gmi_file = "\\" + gmi_file; } else { gmi_file = mapsFilesDirectory + "\\" + gmi_file; } // check that at least one file exists if ((File.Exists(kml_file) == false) && (File.Exists(txt_file) == false) && (File.Exists(gmi_file) == false)) { continue; } // load maps dimensions if (Utils.GetJpegSize(jpg_files[i], out Maps[NumMaps].sizeX, out Maps[NumMaps].sizeY) != 0) { continue; } // make sure we do not load empty images if ((Maps[NumMaps].sizeX == 0) || (Maps[NumMaps].sizeY == 0)) { continue; } Maps[NumMaps].fname = jpg_files[i]; bool kml_has_problems = false; bool gmi_has_problems = false; try { // load kml file if (File.Exists(kml_file)) { double center_lat = 0.0, center_long = 0.0, center_range = 0.0; FileStream fs = new FileStream(kml_file, FileMode.Open, FileAccess.Read); StreamReader sr = new StreamReader(fs); string line = ""; while ((line = sr.ReadLine()) != null) { line = line.Trim(); if (line == "</kml>") { break; } // replace all "," with "." to read correctly line = line.Replace(",", "."); if (line.StartsWith("<longitude>")) { line = line.Replace("<longitude>", ""); line = line.Replace("</longitude>", ""); center_long = Convert.ToDouble(line.Trim(), number_info); } else if (line.StartsWith("<latitude>")) { line = line.Replace("<latitude>", ""); line = line.Replace("</latitude>", ""); center_lat = Convert.ToDouble(line.Trim(), number_info); } else if (line.StartsWith("<range>")) { line = line.Replace("<range>", ""); line = line.Replace("</range>", ""); center_range = Convert.ToDouble(line.Trim(), number_info); } } sr.Close(); fs.Close(); // compute map lat/long if ((center_lat != 0.0) && (center_long != 0.0) && (center_range != 0.0)) { double sizex = center_range * Math.Tan(30.11 * (Math.PI / 180.0)); double sizey = sizex * Maps[NumMaps].sizeY /Maps[NumMaps].sizeX; double tmp; UtmUtil utmUtil1 = new UtmUtil(); utmUtil1.setReferencePoint(center_lat, center_long); utmUtil1.getLatLong(-sizex, 0.0, out tmp, out Maps[NumMaps].lon1); utmUtil1.getLatLong( sizex, 0.0, out tmp, out Maps[NumMaps].lon2); utmUtil1.getLatLong(0.0,-sizey, out Maps[NumMaps].lat1, out tmp); utmUtil1.getLatLong(0.0, sizey, out Maps[NumMaps].lat2, out tmp); } else { kml_has_problems = true; } } else if (File.Exists(txt_file)) // load text file (if KML does not exist) { FileStream fs = new FileStream(txt_file, FileMode.Open, FileAccess.Read); StreamReader sr = new StreamReader(fs); Maps[NumMaps].lat1 = Convert.ToDouble(sr.ReadLine().Trim().Replace(",", "."), number_info); Maps[NumMaps].lon1 = Convert.ToDouble(sr.ReadLine().Trim().Replace(",", "."), number_info); Maps[NumMaps].lat2 = Convert.ToDouble(sr.ReadLine().Trim().Replace(",", "."), number_info); Maps[NumMaps].lon2 = Convert.ToDouble(sr.ReadLine().Trim().Replace(",", "."), number_info); sr.Close(); fs.Close(); } else // load GMI file (if KML and TXT do not exist) { FileStream fs = new FileStream(gmi_file, FileMode.Open, FileAccess.Read); StreamReader sr = new StreamReader(fs); // check header string header = sr.ReadLine().Trim(); if (header.IndexOf("Map Calibration data file v") != 0) { gmi_has_problems = true; } // read image size and check if the size match if(!gmi_has_problems) { sr.ReadLine().Trim(); // skip image name int image_x = Convert.ToInt32(sr.ReadLine().Trim()); int image_y = Convert.ToInt32(sr.ReadLine().Trim()); if ((image_x != Maps[NumMaps].sizeX) || (image_y != Maps[NumMaps].sizeY)) { gmi_has_problems = true; } } // now read the reference points if (!gmi_has_problems) { // need to extract points with min and max X/Y coordinates (if we have more than 2 ref points) int num_ref_points = 0; RefPointInfo minX, maxX, minY, maxY; minX.i = int.MaxValue; maxX.i = int.MinValue; minX.f = 0; maxX.f = 0; minY.i = int.MaxValue; maxY.i = int.MinValue; minY.f = 0; maxY.f = 0; string line = ""; try { while ((line = sr.ReadLine()) != null) { line = line.Trim(); string[] words = line.Split(';'); if (words.Length != 4) { continue; } // read X and long (0th and 2nd words) int tmp_i = Convert.ToInt32(words[0].Trim()); double tmp_f = Convert.ToDouble(words[2].Trim().Replace(",", "."), number_info); if (tmp_i <= minX.i) { minX.i = tmp_i; minX.f = tmp_f; } if (tmp_i >= maxX.i) { maxX.i = tmp_i; maxX.f = tmp_f; } // read Y and lat (1st and 3rd words). Move the Y origin to the bottom of the picture (from the top) tmp_i = Maps[NumMaps].sizeY - Convert.ToInt32(words[1].Trim()); tmp_f = Convert.ToDouble(words[3].Trim().Replace(",", "."), number_info); if (tmp_i <= minY.i) { minY.i = tmp_i; minY.f = tmp_f; } if (tmp_i >= maxY.i) { maxY.i = tmp_i; maxY.f = tmp_f; } num_ref_points++; } } catch (FormatException /*e*/) { // It's OK. // We ignore the extra info after the ref points. } if ((num_ref_points > 1) && (minX.i != maxX.i) && (minY.i != maxY.i)) { Maps[NumMaps].lat1 = minY.f - minY.i*(maxY.f-minY.f)/(maxY.i-minY.i); Maps[NumMaps].lon1 = minX.f - minX.i*(maxX.f-minX.f)/(maxX.i-minX.i); Maps[NumMaps].lat2 = maxY.f + (Maps[NumMaps].sizeY-maxY.i)*(maxY.f-minY.f)/(maxY.i-minY.i); Maps[NumMaps].lon2 = maxX.f + (Maps[NumMaps].sizeX-maxX.i)*(maxX.f-minX.f)/(maxX.i-minX.i); } else { gmi_has_problems = true; } } sr.Close(); fs.Close(); } } catch (Exception e) { Utils.log.Error (" LoadMaps - Cannot load data for map " + jpg_name + ", map loading cancelled", e); MessageBox.Show("Cannot load data for map " + jpg_name + ", map loading cancelled", "Error reading map info", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1); break; } if (NumMaps >= MaxNumMaps) { MessageBox.Show("Cannot load more than " + MaxNumMaps.ToString() + " maps", "Error reading maps", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1); break; } if (kml_has_problems) { MessageBox.Show("Error reading corresponding KML file: " + kml_file, "Error reading maps", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1); break; } if (gmi_has_problems) { MessageBox.Show("Error reading corresponding GMI file: " + gmi_file, "Error reading maps", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1); break; } // make sure 1 is smaller that 2 if (Maps[NumMaps].lat1 > Maps[NumMaps].lat2) { double tmp = Maps[NumMaps].lat1; Maps[NumMaps].lat1 = Maps[NumMaps].lat2; Maps[NumMaps].lat2 = tmp; } if (Maps[NumMaps].lon1 > Maps[NumMaps].lon2) { double tmp = Maps[NumMaps].lon1; Maps[NumMaps].lon1 = Maps[NumMaps].lon2; Maps[NumMaps].lon2 = tmp; } NumMaps++; } Cursor.Current = Cursors.Default; }
public bool Load(string filename, ref Form1.WayPointInfo WayPoints, int vector_size, ref float[] dataLat, ref float[] dataLong, ref Int16[] dataZ, ref Int32[] dataT, ref Int32[] dataD, ref Form1.TrackSummary ts, ref int data_size, bool append) { bool Status = false; int DecimateCount = 0, Decimation = 1; double OldLat = 0.0, OldLong = 0.0; UtmUtil utmUtil = new UtmUtil(); Int16 ReferenceAlt; if (!append) { data_size = 0; WayPoints.Count = 0; ts.Clear(); } if (data_size == 0) ReferenceAlt = Int16.MaxValue; else ReferenceAlt = dataZ[data_size - 1]; Cursor.Current = Cursors.WaitCursor; try { XmlReaderSettings settings = new XmlReaderSettings(); settings.IgnoreWhitespace = true; StreamReader sr = new StreamReader(filename, System.Text.Encoding.UTF8); //use StreamReader to overwrite encoding ISO-8859-1, which is not supported by .NETCF (no speed drawback) XmlReader reader = XmlReader.Create(sr, settings); ts.filename = filename; //reader.MoveToContent(); //reader.Read(); while (reader.ReadToFollowing("Placemark")) { while (reader.NodeType == XmlNodeType.Element) { if (reader.Name == "Placemark") { bool addLevel = false; string tmpname = ""; string tmpdescription = ""; bool waypoint = false; double lon = 0; double lat = 0; reader.Read(); while (reader.NodeType == XmlNodeType.Element) { if (reader.Name == "name") { tmpname = reader.ReadElementString(); } else if (reader.Name == "description") { tmpdescription = reader.ReadElementString(); } else if (reader.Name == "MultiGeometry") { reader.Read(); addLevel = true; } else if (reader.Name == "LineString") { ts.name = tmpname; ts.desc = tmpdescription; reader.Read(); while (reader.NodeType == XmlNodeType.Element) { if (reader.Name == "coordinates") { reader.ReadStartElement(); while (true) { string line = ""; char[] buf = new char[1]; int count = 1; for (int i = 0; i < 100; i++) //read one line { count = reader.ReadValueChunk(buf, 0, 1); if (buf[0] == '\n' || buf[0] == ' ' || buf[0] == '\r' || buf[0] == '\t' || count == 0) break; line += buf[0]; } if (data_size >= vector_size) // check if we need to decimate arrays { for (int i = 0; i < vector_size / 2; i++) { dataLat[i] = dataLat[i * 2]; dataLong[i] = dataLong[i * 2]; dataZ[i] = dataZ[i * 2]; dataT[i] = dataT[i * 2]; dataD[i] = dataD[i * 2]; } data_size = vector_size / 2; Decimation *= 2; } string[] numbers = line.Split(','); if (numbers.Length >= 2) //read data { lon = Convert.ToDouble(numbers[0], IC); lat = Convert.ToDouble(numbers[1], IC); if (!utmUtil.referenceSet) { utmUtil.setReferencePoint(lat, lon); OldLat = lat; OldLong = lon; } double deltax = (lon - OldLong) * utmUtil.longit2meter; double deltay = (lat - OldLat) * utmUtil.lat2meter; ts.Distance += Math.Sqrt(deltax * deltax + deltay * deltay); OldLong = lon; OldLat = lat; Int16 z_int = Int16.MinValue; //preset invalid Alt in case there is no <ele> field if (numbers.Length >= 3) { z_int = (Int16)Convert.ToDouble(numbers[2], IC); //altitude // compute elevation gain //if (ts.AltitudeStart == Int16.MinValue) // ts.AltitudeStart = z_int; if (z_int > ReferenceAlt) { ts.AltitudeGain += z_int - ReferenceAlt; ReferenceAlt = z_int; } else if (z_int < ReferenceAlt - (short)Form1.AltThreshold) { ReferenceAlt = z_int; } if (z_int > (short)ts.AltitudeMax) ts.AltitudeMax = z_int; if (z_int < (short)ts.AltitudeMin) ts.AltitudeMin = z_int; } if (DecimateCount == 0) //when decimating, add only first sample, ignore rest of decimation { dataLat[data_size] = (float)lat; dataLong[data_size] = (float)lon; dataZ[data_size] = z_int; if (data_size == 0) dataT[data_size] = 0; else dataT[data_size] = dataT[data_size - 1] + Decimation; //every point 1 sec apart dataD[data_size] = (int)ts.Distance; data_size++; } DecimateCount++; if (DecimateCount >= Decimation) DecimateCount = 0; } if (count == 0) break; } reader.Skip(); //advances reader to the next (End) Element reader.ReadEndElement(); //coordinates } else reader.Skip(); } reader.ReadEndElement(); //LineString } else if (reader.Name == "Point") { reader.Read(); while (reader.NodeType == XmlNodeType.Element) { if (reader.Name == "coordinates") { string line = reader.ReadElementString(); string[] numbers = line.Split(','); if (numbers.Length >= 2) { lon = Convert.ToDouble(numbers[0], IC); lat = Convert.ToDouble(numbers[1], IC); waypoint = true; } } else reader.Skip(); } reader.ReadEndElement(); //Point } else reader.Skip(); } if (addLevel) reader.ReadEndElement(); if (waypoint && WayPoints.Count < WayPoints.DataSize) { WayPoints.name[WayPoints.Count] = tmpname; WayPoints.lon[WayPoints.Count] = (float)lon; WayPoints.lat[WayPoints.Count] = (float)lat; WayPoints.Count++; } reader.ReadEndElement(); // Placemark } else reader.Skip(); } } reader.Close(); sr.Close(); Status = true; } catch (Exception e) { Utils.log.Error(" LoadKml ", e); } Cursor.Current = Cursors.Default; return Status; }
public void GetNavigationData(UtmUtil utmUtil, float[] PlotLong2, float[] PlotLat2, int[] PlotD2, int PlotSize2, double CurLong, double CurLat) { //System.Diagnostics.Debug.WriteLine("GetNavigationData"); double x, y; //m (related to CurPos) double dist2, MinDistance2 = double.MaxValue / 16; //m2 int j = 0, k = 0; const int ArSize = 14; int[] indexAr = new int[ArSize]; double[] xAr = new double[ArSize]; //Array in m relative to intersection/MinDistance double[] yAr = new double[ArSize]; int begin = 0, end = PlotSize2-1, increment = 1; //GetNavigationData is only executed if PlotSize2 > 0 if (nav.backward) { begin = end; end = 0; increment = -1; } if (nav.ix >= PlotSize2) //in case trackpoints were removed { nav.ix = PlotSize2 - 1; //set parameters in case point is more than 500m away nav.ixd_intersec = nav.ix; nav.ix_next_drive = nav.ix; nav.LongIntersection = PlotLong2[nav.ix]; nav.LatIntersection = PlotLat2[nav.ix]; } if (nav.ShortSearch == 0) nav.ix = begin; int beginindex = nav.ix; int min_ix = beginindex; int min_ixb = beginindex; double ca2 = 0, cb2 = 0, t2 = 0, min_ca2 = 0, min_t2 = 0; int min_segType = 0; int FBSearch = 1; //1=forward -1=backward other=stop int min_FBSearch = 1; int min_increment = 0; while (FBSearch == 1 || FBSearch == -1) { int increment2 = increment * FBSearch; int i = beginindex; x = (PlotLong2[i] - CurLong) * utmUtil.longit2meter; y = (PlotLat2[i] - CurLat) * utmUtil.lat2meter; ca2 = x * x + y * y; while (i < PlotSize2 && i >= 0) //search segment and point with min distance { int segType = 0; dist2 = ca2; int ib = i + increment2; if (ib < PlotSize2 && ib >= 0) { while (true) { x = (PlotLong2[ib] - PlotLong2[i]) * utmUtil.longit2meter; y = (PlotLat2[ib] - PlotLat2[i]) * utmUtil.lat2meter; t2 = x * x + y * y; if (t2 < 4 && ib + increment2 < PlotSize2 && ib + increment2 >= 0) //next point closer than 2m ib += increment2; else break; } x = (PlotLong2[ib] - CurLong) * utmUtil.longit2meter; y = (PlotLat2[ib] - CurLat) * utmUtil.lat2meter; cb2 = x * x + y * y; if (t2 <= cb2 - ca2) //before i { segType = 0; dist2 = ca2; } else if (t2 <= ca2 - cb2) //after i+1 { segType = 1; dist2 = cb2; } else { //currentPos inbetween track segment segType = 2; dist2 = (2 * (ca2 * cb2 + cb2 * t2 + t2 * ca2) - (ca2 * ca2 + cb2 * cb2 + t2 * t2)) / (4 * t2); //Dreieck-Höhenformel (t2 cannot be 0 here) } } if (dist2 < MinDistance2) { min_ix = i; min_ixb = ib; MinDistance2 = dist2; min_ca2 = ca2; min_t2 = t2; min_segType = segType; min_increment = increment2; min_FBSearch = FBSearch; } if (nav.ShortSearch != 0 && dist2 > MinDistance2 * 4 + 10000) break; i = ib; ca2 = cb2; } if (min_ix == beginindex && FBSearch == 1) FBSearch = -1; //try also backward else FBSearch = 0; } if (MinDistance2 < 500 * 500 || nav.ShortSearch == 0) //use only if within 500m of track zone { nav.ix = min_ix; nav.MinDistance = Math.Sqrt(MinDistance2); nav.Distance2Dest = nav.MinDistance; if (min_segType == 0) { nav.ix_next_drive = min_ix; nav.ixd_intersec = min_ix; nav.LongIntersection = PlotLong2[min_ix]; nav.LatIntersection = PlotLat2[min_ix]; } else if (min_segType == 1) { nav.ix_next_drive = min_ixb; nav.ixd_intersec = min_ixb; nav.LongIntersection = PlotLong2[min_ixb]; nav.LatIntersection = PlotLat2[min_ixb]; } else { double quot; if (min_t2 > 1) quot = Math.Sqrt((min_ca2 - MinDistance2) / min_t2); else quot = 0; if (min_FBSearch == 1) nav.ix_next_drive = min_ixb; else { nav.ix = min_ixb; nav.ix_next_drive = min_ix; } nav.ixd_intersec = min_ix + quot * min_increment; ; nav.LongIntersection = PlotLong2[min_ix] + quot * (PlotLong2[min_ixb] - PlotLong2[min_ix]); nav.LatIntersection = PlotLat2[min_ix] + quot * (PlotLat2[min_ixb] - PlotLat2[min_ix]); } } else { if (nav.MinDistance == -1.0) //not initialized yet { nav.LongIntersection = PlotLong2[nav.ix]; nav.LatIntersection = PlotLat2[nav.ix]; } x = (nav.LongIntersection - CurLong) * utmUtil.longit2meter; y = (nav.LatIntersection - CurLat) * utmUtil.lat2meter; nav.MinDistance = Math.Sqrt(x * x + y * y); nav.Distance2Dest = nav.MinDistance; } nav.ShortSearch = -1; //if (nav.ShortSearch > 0) // nav.ShortSearch--; //else // nav.ShortSearch = 30; //for 30s only shortSearch // ix_next_drive is now first index to drive over #if debugNav //debug intersection point DrawCurrentPoint(parent.BackBufferGraphics, nav.LongIntersection, nav.LatIntersection, 6, Color.Violet); #endif //accumulate Distance2Dest from LongOld (intersection or MinDistance) double accu = 0; //use extra accu because Distance2Dest not always starts from 0 double LongOld = nav.LongIntersection; //point to begin accumulation of Distance2Dest double LatOld = nav.LatIntersection; xAr[0] = 0; yAr[0] = 0; j = 1; indexAr[0] = 0; x = 0; y = 0; for (int i = nav.ix_next_drive; i < PlotSize2 && i >= 0; i += increment) { //accumulate distance to destination double xa = (PlotLong2[i] - LongOld) * utmUtil.longit2meter; double ya = (PlotLat2[i] - LatOld) * utmUtil.lat2meter; double ma = Math.Sqrt(xa * xa + ya * ya); if (i == nav.ix_next_drive) nav.Distance2Dest += ma; //Distance2Dest now: Current - Intersection - ix_next_drive int dist = (int)(accu + ma); while (j < ArSize && j * 20 < dist) //fill array every 20m for corner search [0, 20, 40,.. 260] { double quot = (j * 20 - accu) / ma; xAr[j] = x + xa * quot; // xOld + quot * (x - xOld); yAr[j] = y + ya * quot; //yOld + quot * (y - yOld); indexAr[j] = nav.ix_next_drive; j++; } accu += ma; LongOld = PlotLong2[i]; LatOld = PlotLat2[i]; if (j < ArSize) //only necessary for array fill { x = (LongOld - nav.LongIntersection) * utmUtil.longit2meter; //can get inacurate for long tracks, therefore not used for Distance2Dest y = (LatOld - nav.LatIntersection) * utmUtil.lat2meter; } else break; } nav.Distance2Dest += (PlotD2[end] - PlotD2[nav.ix_next_drive]) * increment; #if debugNav //debug 260m line for (int n = 0; n < j; n++) { DrawCurrentPoint(parent.BackBufferGraphics, (xAr[n] * utmUtil.meter2longit + nav.LongIntersection), (yAr[n] * utmUtil.meter2lat + nav.LatIntersection), 2, Color.White); } #endif //nav.Angle100mAhead = (int)(180.0 / Math.PI * Math.Atan2((PlotLong2[Index100mDistance] - CurLong) * utmUtil.longit2meter, (PlotLat2[Index100mDistance] - CurLat) * utmUtil.lat2meter)); int jdx100 = Math.Min(5, j - 1); nav.Angle100mAhead = (int)(180.0 / Math.PI * Math.Atan2(xAr[jdx100] - (CurLong - nav.LongIntersection) * utmUtil.longit2meter, yAr[jdx100] - (CurLat - nav.LatIntersection) * utmUtil.lat2meter)); if (corner.Type == 0) //search corner { int dir1 = 0, dir2 = 0, angle = 0, angleAbs, angleAbsMax = -1, kc = 0; bool cornerfound = false; if (corner.processedIndex == -1) corner.processedIndex = begin; for (k = 2; k < j - 2; k++) { if (indexAr[k] != PlotSize2 && (corner.processedIndex - indexAr[k]) * increment > 2) //little overlap (reprocess) continue; //already processed - to reduce calc dir1 = (int)(180 / Math.PI * Math.Atan2(xAr[k - 1] - xAr[k - 2], yAr[k - 1] - yAr[k - 2])); dir2 = (int)(180 / Math.PI * Math.Atan2(xAr[k + 2] - xAr[k + 1], yAr[k + 2] - yAr[k + 1])); angle = dir2 - dir1; if (angle > 180) angle -= 360; if (angle <= -180) angle += 360; angleAbs = Math.Abs(angle); corner.processedIndex = indexAr[k]; if (angleAbs > angleAbsMax) { angleAbsMax = angleAbs; corner.IndexT2F = indexAr[k]; corner.dir1 = dir1; corner.dir2 = dir2; corner.angle = angle; kc = k; } if (angleAbsMax >= 35 && angleAbs < angleAbsMax - 10) //run over corner (angle gets smaller) { cornerfound = true; break; } } if (angleAbsMax >= 35 && j < ArSize && kc >= j - 4) //corner at end of T2F cornerfound = true; if (cornerfound) { if (angleAbsMax < 65) corner.Type = 1; //half turn else if (angleAbsMax < 115) corner.Type = 2; //turn else corner.Type = 3; //sharp turn corner.distance = int.MaxValue; //to overcome invalidate algorithm corner.Long = (float)(xAr[kc] * utmUtil.meter2longit + nav.LongIntersection); corner.Lat = (float)(yAr[kc] * utmUtil.meter2lat + nav.LatIntersection); corner.voicePlayed = false; #if debugNav //debug //DrawCurrentPoint(parent.BackBufferGraphics, PlotLong2[indexAr[kc - 2]], PlotLat2[indexAr[kc - 2]], 6, Color.LightBlue); //DrawCurrentPoint(parent.BackBufferGraphics, PlotLong2[indexAr[kc - 1]], PlotLat2[indexAr[kc - 1]], 6, Color.LightBlue); //DrawCurrentPoint(parent.BackBufferGraphics, PlotLong2[indexAr[kc - 0]], PlotLat2[indexAr[kc - 0]], 8, Color.Blue); //DrawCurrentPoint(parent.BackBufferGraphics, PlotLong2[indexAr[kc + 1]], PlotLat2[indexAr[kc + 1]], 6, Color.LightBlue); //DrawCurrentPoint(parent.BackBufferGraphics, PlotLong2[indexAr[kc + 2]], PlotLat2[indexAr[kc + 2]], 6, Color.LightBlue); #endif } else corner.Type = 0; //straight } if (corner.Type != 0) //update volatile corner details { x = (corner.Long - CurLong) * utmUtil.longit2meter; y = (corner.Lat - CurLat) * utmUtil.lat2meter; int cornerdistance = (int)Math.Sqrt(x * x + y * y) / 10 * 10; //rounded to 10m if (cornerdistance > corner.distance || cornerdistance > 300) { invalidateCorner(); } else { corner.distance = cornerdistance; corner.direction = (int)(180.0 / Math.PI * Math.Atan2(x, y)); } } double unit_cff = parent.GetUnitsConversionCff(); string unit_name = parent.GetUnitsName(); int dir = nav.Angle100mAhead; if (parent.Heading != 720) dir -= parent.Heading; while (dir < 0) dir += 360; nav.orient = Orientation.normal; nav.SkyDirection = false; if (nav.MinDistance > (double)parent.numericTrackTolerance.Value) { nav.Symbol = arrow_to; if (parent.Heading == 720) nav.SkyDirection = true; if (dir < 45) nav.orient = Orientation.normal; else if (dir < 135) nav.orient = Orientation.right; else if (dir < 225) nav.orient = Orientation.mirrorY; else if (dir < 315) nav.orient = Orientation.left; //else //nav.orient = Orientation.normal; //if (nav.MinDistance >= 10000) // str += " " + ((int)nav.MinDistance / 1000).ToString() + "km"; //else // str += " " + ((int)nav.MinDistance / 10 * 10).ToString() + "m"; nav.strCmd = (nav.MinDistance * unit_cff).ToString("0.00") + unit_name; } else if (parent.Heading != 720 && dir > 135 && dir < 225 && parent.CurrentSpeed > 4.0) { nav.Symbol = arrow_turn; //wenden nav.strCmd = ""; } else if (corner.Type != 0) //navigation command { switch (corner.Type) { case 1: nav.Symbol = arrow_hr; break; case 2: nav.Symbol = arrow_r; break; case 3: nav.Symbol = arrow_sr; break; default: nav.Symbol = null; break; } if (corner.angle < 0) nav.orient = Orientation.mirrorX; //left //str = corner.angle.ToString() + str; nav.strCmd = corner.distance.ToString() + "m"; } else if (nav.Distance2Dest <= 200) { nav.Symbol = destination; nav.strCmd = (((int)nav.Distance2Dest / 10) * 10).ToString() + "m"; } else nav.Symbol = null; nav.strDistance2Dest = (nav.Distance2Dest * unit_cff).ToString("0.00") + unit_name + " to destin."; return; }
// draw map and 2 lines (main and "to follow"). Shift is the x/y shift of the second line origin. public void DrawMaps(Graphics g, Bitmap BackBuffer, Graphics BackBufferGraphics, UtmUtil utmUtil, bool MouseMoving, bool lifeview, int MapMode, double unit_cff, string unit_name, float[] PlotLong, float[] PlotLat, int PlotSize, Color line_color, int line_width, bool plot_dots, Form1.WayPointInfo WayPointsT, Form1.WayPointInfo WayPointsT2F, int ShowWaypoints, float[] PlotLong2, float[] PlotLat2, int PlotSize2, Color line_color2, int line_width2, bool plot_dots2, double CurrentLong, double CurrentLat, int heading, string clickLatLon, Color mapLabelColor) { ScreenX = BackBuffer.Width; ScreenY = BackBuffer.Height; // if picture is moving - draw existing picture if (MouseMoving && !drawWhileShift) { DrawMovingImage(g, BackBuffer, (int)((LongShift - LongShiftSave) * Long2Pixel), (int)((LatShift - LatShiftSave) * Lat2Pixel)); return; } // set scale from "main" or the "track-to-follow" (if main not exist) float[] CurLongA = { (float)CurrentLong }; float[] CurLatA = { (float)CurrentLat }; if (ShowTrackToFollowMode == ShowTrackToFollow.T2FStart && PlotSize2 > 0) { // Show start position of track to follow SetAutoScale(utmUtil, PlotLong2, PlotLat2, 1, false); } else if (ShowTrackToFollowMode == ShowTrackToFollow.T2FEnd && PlotSize2 > 0) { // Show end position of track to follow float[] Long = { PlotLong2[PlotSize2 - 1] }; float[] Lat = { PlotLat2[PlotSize2 - 1] }; SetAutoScale(utmUtil, Long, Lat, 1, false); } else if (parent.trackEditMode != Form1.TrackEditMode.Off) { SetAutoScale(utmUtil, null, null, 0, false); // in trackEditMode prevent autoscale; only update vars } else if (lifeview) { // Show current GPS position (last position) SetAutoScale(utmUtil, CurLongA, CurLatA, 1, lifeview); } else if (PlotSize > 0) { // Show all points of loaded track SetAutoScale(utmUtil, PlotLong, PlotLat, PlotSize, lifeview); } else if (PlotSize2 > 0 && ShowTrackToFollowMode != ShowTrackToFollow.T2FCurrent) { // Show all points of track to follow SetAutoScale(utmUtil, PlotLong2, PlotLat2, PlotSize2, false); } else { // Show last position SetAutoScale(utmUtil, CurLongA, CurLatA, 1, false); } // need to draw the picture first into back buffer BackBufferGraphics.Clear(Back_Color); if (!hideMap) { // in OSM tile mode, required map array is created based on the current screen coordinates if (OsmTilesMode) { FillOsmTiles(MapMode); NumBitmaps = NumMaps; DrawJpeg(BackBufferGraphics); } else { // Update screen coordinates for all maps for (int i = 0; i < NumMaps; i++) { Maps[i].scrX1_ix = ToScreenX(Maps[i].lon1); Maps[i].scrX2_iz = ToScreenX(Maps[i].lon2); Maps[i].scrY1_iy = ToScreenY(Maps[i].lat1); Maps[i].scrY2 = ToScreenY(Maps[i].lat2); } // select the best map and draw it SelectBestMap(MapMode); RemoveBitmaps(NumBitmaps); // removes unused bitmaps DrawJpeg(BackBufferGraphics); } if (mapCopyright != null) { Font drawFont = new Font("Arial", 8 * parent.df, FontStyle.Bold); SolidBrush drawBrush = new SolidBrush(mapLabelColor); SizeF size = BackBufferGraphics.MeasureString(mapCopyright, drawFont); BackBufferGraphics.DrawString(mapCopyright, drawFont, drawBrush, ScreenX - size.Width - 2, size.Height); } } Pen pen = new Pen(Color.LightGray, 1); // draw the track-to-follow line if (PlotSize2 > 0 && hideT2f == false) { pen.Color = line_color2; pen.Width = line_width2; DrawTrackLine(BackBufferGraphics, pen, PlotLong2, PlotLat2, PlotSize2, plot_dots2, CurrentLong, CurrentLat); DrawCurrentPoint(BackBufferGraphics, PlotLong2[PlotSize2 - 1], PlotLat2[PlotSize2 - 1], line_width2, line_color2); } // draw the main track line if (PlotSize > 0 && hideTrack == false) { pen.Color = line_color; pen.Width = line_width; DrawTrackLine(BackBufferGraphics, pen, PlotLong, PlotLat, PlotSize, plot_dots, 0, 0); // draw last point larger by 5 points DrawCurrentPoint(BackBufferGraphics, PlotLong[PlotSize - 1], PlotLat[PlotSize - 1], line_width + 5, line_color); } if (ShowWaypoints > 0) { // Draw the Waypoints (on top of track2follow and track line) DrawWayPoints(BackBufferGraphics, pen, WayPointsT, Utils.modifyColor(line_color, +100), ShowWaypoints); DrawWayPoints(BackBufferGraphics, pen, WayPointsT2F, Utils.modifyColor(line_color2, +100), ShowWaypoints); } if (lifeview) { Point p0 = new Point(ToScreenX(CurrentLong), ToScreenY(CurrentLat)); Color col = line_color, col2 = line_color2; bool outside0 = false; bool outside1 = false; if (heading == 720) { col = Color.DimGray; col2 = Color.DimGray; } if (PlotSize2 > 0 && (showNav || parent.comboNavCmd.SelectedIndex > 0)) { #if debugNav GetNavigationData(utmUtil, PlotLong2, PlotLat2, parent.Plot2ndD, PlotSize2, CurrentLong, CurrentLat); #endif //DoVoiceCommand(); if (showNav && !hideAllInfos) { // We draw the line between current position and T2F with half of the T2F width and somewhat lighter pen.Width = Math.Max(2, line_width2 / 2); pen.Color = Utils.modifyColor(line_color2, +100); Point p1 = new Point(ToScreenX(nav.LongIntersection), ToScreenY(nav.LatIntersection)); outside0 = ScreenClip(ref p0, p1); outside1 = ScreenClip(ref p1, p0); BackBufferGraphics.DrawLine(pen, p0.X, p0.Y, p1.X, p1.Y); //if (outside0 || outside1) // If the Current Position is outside of the Screen or the nearest point on the track is outside //{ // of the screen, show the min distance to track // DrawDistanceToTrack2Follow(BackBufferGraphics, pen, unit_cff, unit_name); //} if (!outside0) DrawArrow(BackBufferGraphics, p0.X, p0.Y, nav.Angle100mAhead, line_width2 * 3 + 7, line_color2); //navigation arrow pointing at t2f 100m ahead DrawArrow(BackBufferGraphics, ScreenX * 4 / 5, ScreenY / 5, nav.Angle100mAhead - heading, ScreenX / 5, col2); //big navigation arrow in direction of travel Font drawFont = new Font("Arial", 22, FontStyle.Bold); SolidBrush drawBrush = new SolidBrush(line_color2); //if (nav.strCmd.Length > 8) //{ // int blank = nav.strCmd.IndexOf(" ", 5); // if (blank > 1) // { // string navstr2 = nav.strCmd.Remove(0, blank + 1); // nav.strCmd = nav.strCmd.Remove(blank, nav.strCmd.Length - blank); // BackBufferGraphics.DrawString(navstr2, drawFont, drawBrush, ScreenX / 40, ScreenY / 12 + (int)BackBufferGraphics.MeasureString(nav.strCmd, drawFont).Height); // } //} if (nav.Symbol != null) { DrawNavSymbol(BackBufferGraphics, drawBrush, ScreenX / 40, ScreenY / 12, nav.Symbol, nav.orient, nav.SkyDirection, false); BackBufferGraphics.DrawString(nav.strCmd, drawFont, drawBrush, ScreenX * 130 / 480, ScreenY / 14); } if (corner.Type != 0) { //DrawCurrentPoint(BackBufferGraphics, PlotLong2[corner.IndexT2F], PlotLat2[corner.IndexT2F], 6, Color.Fuchsia); DrawCurrentPoint(BackBufferGraphics, corner.Long, corner.Lat, line_width2, Color.Yellow); //DrawCurrentPoint(BackBufferGraphics, PlotLong2[corner.IndexT2F - 2], PlotLat2[corner.IndexT2F - 2], 4, Color.Yellow); //DrawCurrentPoint(BackBufferGraphics, PlotLong2[corner.IndexT2F - 1], PlotLat2[corner.IndexT2F - 1], 4, Color.Yellow); //DrawCurrentPoint(BackBufferGraphics, PlotLong2[corner.IndexT2F + 1], PlotLat2[corner.IndexT2F + 1], 4, Color.Yellow); //DrawCurrentPoint(BackBufferGraphics, PlotLong2[corner.IndexT2F + 2], PlotLat2[corner.IndexT2F + 2], 4, Color.Yellow); } } } if (!outside0) DrawArrow(BackBufferGraphics, p0.X, p0.Y, heading, line_width * 2 + 5, col); //arrow showing direction of movement // draw gps led point //DrawCurrentPoint(BackBufferGraphics, CurLong[0], CurLat[0], line_width, CurrentGpsLedColor); } if (showMapLabel && !hideAllInfos || parent.trackEditMode == Form1.TrackEditMode.T2f) { // draw tick label and map name double screen_width_units = ScreenX / Long2Pixel * unit_cff / utmUtil.meter2longit; // tick distance in "units" (i.e. km or miles) double tick_distance_units = TickMark(screen_width_units, 4); // tick distance in screen pixels int tick_distance_screen = (int)(tick_distance_units * Long2Pixel / unit_cff * utmUtil.meter2longit); pen.Color = mapLabelColor; DrawTickLabel(BackBufferGraphics, pen, tick_distance_screen, tick_distance_units, unit_name, clickLatLon); } if (!hideAllInfos) DrawMapValues(BackBufferGraphics, mapLabelColor); // draw back buffer on screen g.DrawImage(BackBuffer, 0, 0); }
private void SetAutoScale(UtmUtil utmUtil, float[] PlotLong, float[] PlotLat, int PlotSize, bool lifeview) { if (PlotSize > 0) { if (!utmUtil.referenceSet) { utmUtil.setReferencePoint(PlotLat[PlotSize - 1], PlotLong[PlotSize - 1]); utmUtil.referenceSet = false; //better not fix to an old point } if (lifeview || (PlotSize == 1)) // during liveview (logging), set a fixed scale with current point in the middle { double last_x = PlotLong[PlotSize - 1]; double last_y = PlotLat[PlotSize - 1]; double extend_x = 1.0; double extend_y = 1.0; if (!OsmTilesMode) if (ScreenY > ScreenX) extend_y = (double)ScreenY / (double)ScreenX; else extend_x = (double)ScreenX / (double)ScreenY; DataLongMin = last_x - utmUtil.meter2longit * DefaultZoomRadius * extend_x; DataLongMax = last_x + utmUtil.meter2longit * DefaultZoomRadius * extend_x; DataLatMin = last_y - utmUtil.meter2lat * DefaultZoomRadius * extend_y; DataLatMax = last_y + utmUtil.meter2lat * DefaultZoomRadius * extend_y; } else { // compute data limits DataLongMin = 1.0E9; DataLongMax = -1.0E9; DataLatMin = 1.0E9; DataLatMax = -1.0E9; for (int i = 0; i < PlotSize; i++) { if (PlotLong[i] < DataLongMin) { DataLongMin = PlotLong[i]; } if (PlotLong[i] > DataLongMax) { DataLongMax = PlotLong[i]; } if (PlotLat[i] < DataLatMin) { DataLatMin = PlotLat[i]; } if (PlotLat[i] > DataLatMax) { DataLatMax = PlotLat[i]; } } double dx = (DataLongMax - DataLongMin) / 20; //make ca. 10% larger double dy = (DataLatMax - DataLatMin) / 20; if (dx < 0.0001) dx = 0.0001; if (dy < 0.0001) dy = 0.0001; DataLongMin -= dx; DataLongMax += dx; DataLatMin -= dy; DataLatMax += dy; } } double xscale = (double)ScreenX / (DataLongMax - DataLongMin); double yscale = (double)ScreenY / ((OsmLat2YTile(1, DataLatMin) - OsmLat2YTile(1, DataLatMax)) * 360); DataLongMiddle = (DataLongMin + DataLongMax) / 2; DataLatMiddle = (DataLatMin + DataLatMax) / 2; if (OsmTilesMode) { UInt32 xTiles = (UInt32)((yscale > xscale ? xscale : yscale) * 360 / 256); for (OsmN = 1 << 30; OsmN > 1; OsmN >>= 1) if ((xTiles & OsmN) > 0) break; //OsmN is next smaller power of 2 OsmN = (int)(OsmN * ZoomValue); Long2Pixel = OsmN * 32 / 45.0; // OsmN * 256 / 360.0 double yMiddleTile = OsmLat2YTile(OsmN, DataLatMiddle + LatShift); //linearize at middle of display Lat2Pixel = 1 / (OsmYTile2Lat(OsmN, yMiddleTile - 1.0 / 512) - OsmYTile2Lat(OsmN, yMiddleTile + 1.0 / 512)); //linearize with +/- 0.5 pixel } else { Long2Pixel = (yscale > xscale ? xscale : yscale) * ZoomValue; Lat2Pixel = Long2Pixel * utmUtil.meter2longit / utmUtil.meter2lat; } }
public bool Load(string filename, ref Form1.WayPointInfo WayPoints, int vector_size, ref float[] dataLat, ref float[] dataLong, ref Int16[] dataZ, ref Int32[] dataT, ref Int32[] dataD, ref Form1.TrackSummary ts, ref int data_size, bool append) { bool Status = false; TimeSpan tspan; UtmUtil utmUtil = new UtmUtil(); double OldLat = 0.0, OldLong = 0.0; int DecimateCount = 0, Decimation = 1; Int16 ReferenceAlt; if (!append) { data_size = 0; WayPoints.Count = 0; ts.Clear(); } if (data_size == 0) ReferenceAlt = Int16.MaxValue; else ReferenceAlt = dataZ[data_size - 1]; Cursor.Current = Cursors.WaitCursor; try { //XmlParserContext xmlpc = new XmlParserContext(null, null, "", XmlSpace.Default, System.Text.Encoding.UTF8); does not work XmlReaderSettings settings = new XmlReaderSettings(); settings.IgnoreWhitespace = true; StreamReader sr = new StreamReader(filename, System.Text.Encoding.UTF8); //use StreamReader to overwrite encoding ISO-8859-1, which is not supported by .NETCF (no speed drawback) XmlReader reader = XmlReader.Create(sr, settings); ts.filename = filename; //reader.MoveToContent(); reader.ReadToFollowing("gpx"); reader.Read(); while (reader.NodeType == XmlNodeType.Element) { bool isTrack; if ((isTrack = reader.Name == "trk") || reader.Name == "rte") { if (isTrack) reader.Read(); while (reader.NodeType == XmlNodeType.Element) { if (reader.Name == "trkseg" || reader.Name == "rte") { reader.Read(); while (reader.NodeType == XmlNodeType.Element) { if (reader.Name == "trkpt" || reader.Name == "rtept") { trkpt: bool jumptrkpt = false; if (data_size >= vector_size) // check if we need to decimate arrays { for (int i = 0; i < vector_size / 2; i++) { dataLat[i] = dataLat[i * 2]; dataLong[i] = dataLong[i * 2]; dataZ[i] = dataZ[i * 2]; dataT[i] = dataT[i * 2]; dataD[i] = dataD[i * 2]; } data_size = vector_size / 2; Decimation *= 2; } double lat = Convert.ToDouble(reader.GetAttribute("lat"), IC); double lon = Convert.ToDouble(reader.GetAttribute("lon"), IC); if (!utmUtil.referenceSet) { utmUtil.setReferencePoint(lat, lon); OldLat = lat; OldLong = lon; } double deltax = (lon - OldLong) * utmUtil.longit2meter; double deltay = (lat - OldLat) * utmUtil.lat2meter; ts.Distance += Math.Sqrt(deltax * deltax + deltay * deltay); OldLong = lon; OldLat = lat; tspan = TimeSpan.Zero; //clear data in case there is no <time> field Int16 z_int = Int16.MinValue; //preset invalid Alt in case there is no <ele> field reader.Read(); while (reader.NodeType == XmlNodeType.Element) //read subtree { switch (reader.Name) { case "ele": z_int = (Int16)reader.ReadElementContentAsDouble(); // compute elevation gain //if (ts.AltitudeStart == Int16.MinValue) // ts.AltitudeStart = z_int; if (z_int > ReferenceAlt) { ts.AltitudeGain += z_int - ReferenceAlt; ReferenceAlt = z_int; } else if (z_int < ReferenceAlt - (short)Form1.AltThreshold) { ReferenceAlt = z_int; } if (z_int > (short)ts.AltitudeMax) ts.AltitudeMax = z_int; if (z_int < (short)ts.AltitudeMin) ts.AltitudeMin = z_int; break; case "time": if (ts.StartTime == DateTime.MinValue) { ts.StartTime = reader.ReadElementContentAsDateTime(); } else { tspan = reader.ReadElementContentAsDateTime() - ts.StartTime; } break; case "speed": reader.Skip(); break; case "trkpt": //trkpt without EndElement <trkpt lat="47.2615199999997" lon="10.2016400000003"/> case "rtept": jumptrkpt = true; goto savepoint; default: reader.Skip(); break; } } reader.ReadEndElement(); //trkpt savepoint: if (DecimateCount == 0) //when decimating, add only first sample, ignore rest of decimation { dataLat[data_size] = (float)lat; dataLong[data_size] = (float)lon; dataZ[data_size] = z_int; dataT[data_size] = (int)tspan.TotalSeconds; dataD[data_size] = (int)ts.Distance; data_size++; } DecimateCount++; if (DecimateCount >= Decimation) DecimateCount = 0; if (jumptrkpt) goto trkpt; } else reader.Skip(); } if (isTrack) reader.ReadEndElement(); //trkseg } else if (reader.Name == "name") { ts.name = reader.ReadElementString(); } else if (reader.Name == "desc") { ts.desc = reader.ReadElementString(); } else reader.Skip(); } reader.ReadEndElement(); //trk } else if (reader.Name == "wpt") { float lat = (float)Convert.ToDouble(reader.GetAttribute("lat"), IC); float lon = (float)Convert.ToDouble(reader.GetAttribute("lon"), IC); string name = ""; string desc = ""; reader.Read(); while (reader.NodeType == XmlNodeType.Element) { if (reader.Name == "name") { name = reader.ReadElementString(); } else if (reader.Name == "desc") { desc = reader.ReadElementString(); //prepared for later use } else reader.Skip(); } if (WayPoints.Count < WayPoints.DataSize) { WayPoints.lat[WayPoints.Count] = lat; WayPoints.lon[WayPoints.Count] = lon; WayPoints.name[WayPoints.Count] = name; WayPoints.Count++; } reader.ReadEndElement(); } else reader.Skip(); } //reader.ReadEndElement(); reader.Close(); Status = true; } catch (Exception e) { Utils.log.Error(" LoadGpx ", e); } Cursor.Current = Cursors.Default; return Status; }
{ //load as T2F (WayPoints) public bool Load(string filename, ref Form1.WayPointInfo WayPoints, int vector_size, ref float[] dataLat, ref float[] dataLong, ref Int16[] dataZ, ref Int32[] dataT, ref Int32[] dataD, ref Form1.TrackSummary ts, ref int data_size, bool append) { int DecimateCount = 0, Decimation = 1; double OriginShiftX = 0.0; double OriginShiftY = 0.0; bool Status = false; UtmUtil utmUtil = new UtmUtil(); Int16 ReferenceAlt; if (!append) { data_size = 0; WayPoints.Count = 0; ts.Clear(); } if (data_size == 0) ReferenceAlt = Int16.MaxValue; else ReferenceAlt = dataZ[data_size - 1]; Cursor.Current = Cursors.WaitCursor; do { try { ts.filename = filename; FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read); BinaryReader rd = new BinaryReader(fs, System.Text.Encoding.Unicode); // load header "GCC1" (1 is version in binary) if (rd.ReadByte() != 'G') break; if (rd.ReadByte() != 'C') break; if (rd.ReadByte() != 'C') break; if (rd.ReadByte() != 1) break; // read time as 6 bytes: year, month... int tyear = (int)rd.ReadByte(); tyear += 2000; int tmonth = (int)rd.ReadByte(); int tday = (int)rd.ReadByte(); int thour = (int)rd.ReadByte(); int tmin = (int)rd.ReadByte(); int tsec = (int)rd.ReadByte(); ts.StartTime = new DateTime(tyear, tmonth, tday, thour, tmin, tsec); // read lat/long for the starting point double data_lat = rd.ReadDouble(); double data_long = rd.ReadDouble(); utmUtil.setReferencePoint(data_lat, data_long); Int16 x_int = 0; Int16 y_int = 0; Int16 z_int = 0; Int16 s_int = 0; UInt16 t_16 = 0; UInt16 t_16last = 0; Int32 t_high = 0; double out_lat = 0.0, out_long = 0.0; double OldX = 0.0; double OldY = 0.0; UInt64 recordError = 0UL; bool loop = true; while (loop) //break with EndOfStreamException { // get 5 short ints try { x_int = rd.ReadInt16(); y_int = rd.ReadInt16(); z_int = rd.ReadInt16(); s_int = rd.ReadInt16(); t_16 = rd.ReadUInt16(); } catch (EndOfStreamException) { break; } catch (Exception e) { Utils.log.Error(" LoadGcc - get 5 short ints ", e); break; } // check if this is a special record if ((s_int == -1) && (t_16 == 0xFFFF)) { switch (z_int) { case 0: // origin shift: z_int = 0 OriginShiftX += x_int; OriginShiftY += y_int; break; case 1: // battery: z_int = 1 break; case 2: // which GPS options were selected: z_int = 2 break; case 3: // waypoint // read waypoint name, if not blank string name = ""; for (int i = 0; i < x_int; i++) { name += (char)(rd.ReadUInt16()); } // store new waypoint if (WayPoints.Count < WayPoints.DataSize) { WayPoints.name[WayPoints.Count] = name; WayPoints.lat[WayPoints.Count] = (float)out_lat; WayPoints.lon[WayPoints.Count] = (float)out_long; WayPoints.Count++; } break; case 4: // heart rate not supported in T2F break; case 32: // name ts.name = rd.ReadString(); break; case 33: // desc ts.desc = rd.ReadString(); break; default: if ((1UL << z_int & recordError) == 0) { if (MessageBox.Show("unknown special record " + z_int + " at " + data_size + "\ntry to continue load anyway?", "Load Error", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1) == DialogResult.Cancel) loop = false; ; recordError |= 1UL << z_int; } if (loop && z_int >= 32) rd.ReadString(); //read unknown string in order to have correct record bounds break; } } else // "normal" record { // check if we need to decimate arrays if (data_size >= vector_size) { for (int i = 0; i < vector_size / 2; i++) { dataLat[i] = dataLat[i * 2]; dataLong[i] = dataLong[i * 2]; dataZ[i] = dataZ[i * 2]; dataT[i] = dataT[i * 2]; dataD[i] = dataD[i * 2]; } data_size /= 2; Decimation *= 2; } // take into account the origin shift double real_x = OriginShiftX + x_int; double real_y = OriginShiftY + y_int; double deltax = real_x - OldX; double deltay = real_y - OldY; ts.Distance += Math.Sqrt(deltax * deltax + deltay * deltay); OldX = real_x; OldY = real_y; // compute elevation gain if (z_int != Int16.MinValue) //MinValue = invalid { //if (ts.AltitudeStart == Int16.MinValue) // ts.AltitudeStart = z_int; if (z_int > ReferenceAlt) { ts.AltitudeGain += z_int - ReferenceAlt; ReferenceAlt = z_int; } else if (z_int < ReferenceAlt - (short)Form1.AltThreshold) { ReferenceAlt = z_int; } if (z_int > (short)ts.AltitudeMax) ts.AltitudeMax = z_int; if (z_int < (short)ts.AltitudeMin) ts.AltitudeMin = z_int; } if (DecimateCount == 0) //when decimating, add only first sample, ignore rest of decimation { //but calculate distance and elevation from all points utmUtil.getLatLong(real_x, real_y, out out_lat, out out_long); dataLat[data_size] = (float)out_lat; dataLong[data_size] = (float)out_long; dataZ[data_size] = z_int; if (t_16 < t_16last) // handle overflow t_high += 65536; t_16last = t_16; dataT[data_size] = t_high + t_16; dataD[data_size] = (int)ts.Distance; data_size++; } DecimateCount++; if (DecimateCount >= Decimation) DecimateCount = 0; } } rd.Close(); fs.Close(); Status = true; } catch (Exception e) { Utils.log.Error(" LoadGcc ", e); } } while (false); Cursor.Current = Cursors.Default; return Status; }