public void SearchAllArcsTest() { OFile ofile = OFile.Read(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Data", "rinex", "30900700.11o")); Assert.IsNotNull(ofile, "读取文件失败!"); ofile.DetectAllArcs(); var arcs = ofile.Arcs; foreach (var key in arcs.Keys) { for (int i = 0; i < arcs[key].Count; i++) { Console.WriteLine("{0} 第{1}段 {2,6} {3,6}", key, i + 1, arcs[key][i].StartIndex, arcs[key][i].EndIndex); } Console.WriteLine(""); } }
/// <summary> /// 解算DCB /// </summary> /// <param name="filePathList">用于计算的观测文件列表</param> /// <param name="estimateReceiverDCB">是否估计接收机DCB(默认true)</param> /// <param name="estimateSatelliteDCB">是否估计卫星DCB(默认true)</param> /// <returns></returns> public bool ResolveDCB(int doy, string[] filePathList, DCBOption receiverDCBOpt, DCBOption satelliteDCBOpt, out Dictionary <string, double> receiverDCB, out Dictionary <string, double> satelliteDCB) { receiverDCB = new Dictionary <string, double>(); satelliteDCB = new Dictionary <string, double>(); if (filePathList is null || filePathList.Length <= 0) { return(false); } int year2, year4, month, dom; Time.DOY2MonthDay(doy, out year4, out month, out dom); year2 = Time.GetYear2(year4); PrintWithTime("读取星历文件..."); int beforeDay = DOY.AddDays(doy, -1); int afterDay = DOY.AddDays(doy, 1); Orbit Orb = new Orbit(orbFolder); Orb.Read(orbFolder, beforeDay, afterDay); OFile[] oFiles = new OFile[filePathList.Length]; for (int i = 0; i < filePathList.Length; i++) { PrintWithTime("正在处理文件:" + filePathList[i]); try { OFile of = new OFile(filePathList[i]); of.TryRead(); Orb.GetSatPos(ref of); of.CalAzElIPP(); of.DetectOutlier(); of.DetectAllArcs(); of.DetectCycleSlip(); of.CalSP4(); oFiles[i] = of; } catch (Exception ex) { PrintWithTime(string.Format("处理失败,原因是:{0}", ex.ToString())); continue; } } List <string> stationNames = new List <string>(oFiles.Length * 2); List <LinkedList <int> > prn = new List <LinkedList <int> >(); List <LinkedList <double> > lat = new List <LinkedList <double> >(); List <LinkedList <double> > lon = new List <LinkedList <double> >(); List <LinkedList <double> > sp4 = new List <LinkedList <double> >(); List <LinkedList <double> > ele = new List <LinkedList <double> >(); double b, l; HashSet <string> prnStr = new HashSet <string>(); int prnNum = 0; foreach (var of in oFiles) { stationNames.Add(of.StationName); LinkedList <int> prns = new LinkedList <int>(); LinkedList <double> lats = new LinkedList <double>(); LinkedList <double> lons = new LinkedList <double>(); LinkedList <double> tecs = new LinkedList <double>(); LinkedList <double> eles = new LinkedList <double>(); foreach (var p in of.Arcs.Keys) { prnStr.Add(p); prnNum = int.Parse(p.Substring(1)); var arcs = of.Arcs[p]; foreach (var arc in arcs) { for (int i = 0; i < arc.Length; i++) { if (arc[i]["SP4"] > 0) { Coordinate.SunGeomagnetic(arc[i].IPP[0], arc[i].IPP[1], arc[i].Epoch.Hour, arc[i].Epoch.Minute, arc[i].Epoch.Second, GeoFun.GNSS.Common.GEOMAGNETIC_POLE_LAT, GeoFun.GNSS.Common.GEOMAGENTIC_POLE_LON, out b, out l); prns.AddLast(prnNum); tecs.AddLast(arc[i]["SP4"]); lats.AddLast(b); lons.AddLast(l); eles.AddLast(arc[i].Elevation); } } } } prn.Add(prns); lat.Add(lats); lon.Add(lons); sp4.Add(tecs); ele.Add(eles); } // 从文件中读取dcb if (satelliteDCBOpt.Option == enumDCBOption.ReadFromFile) { if (!File.Exists(satelliteDCBOpt.DCBFilePath)) { throw new FileNotFoundException("卫星DCB文件无法找到", satelliteDCBOpt.DCBFilePath); } DCBFile df = new DCBFile(satelliteDCBOpt.DCBFilePath); if (!df.TryRead()) { throw new IOException(string.Format("卫星DCB文件读取失败:{0}", satelliteDCBOpt.DCBFilePath)); } satelliteDCB = df.DCBDict; // 将dcb单位转换为米 foreach (var p in satelliteDCB.Keys) { satelliteDCB[p] *= GeoFun.GNSS.Common.C0; } } // 忽略卫星dcb else if (satelliteDCBOpt.Option == enumDCBOption.Regardless) { foreach (var p in prnStr) { satelliteDCB.Add(p, 0d); } } PrintWithTime("估计DCB..."); SphericalHarmonicIonoModel spm; if (satelliteDCBOpt.Option == enumDCBOption.Estimation) { bool flag = IonoModel.CalSphericalHarmonicModel(9, 9, stationNames, prn, lat, lon, sp4, ele, out spm, out receiverDCB, out satelliteDCB); spm.SaveAs(@"C:\Users\Administrator\Desktop\data\out\0.spm.txt"); return(flag); } else if (satelliteDCBOpt.Option == enumDCBOption.ReadFromFile || satelliteDCBOpt.Option == enumDCBOption.Regardless) { return(IonoModel.CalSphericalHarmonicModel(9, 9, stationNames, prn, lat, lon, sp4, ele, satelliteDCB, out spm, out receiverDCB)); } else { return(false); } }
/// <summary> /// 读取所有数据,统一进行解算,很耗内存和时间 /// </summary> public void MultiStationMultiDay() { if (!Directory.Exists(obsFolder)) { PrintWithTime("文件夹不存在,结束解算!"); return; } DirectoryInfo obsDir = new DirectoryInfo(obsFolder); PrintWithTime("正在搜索o文件..."); FileInfo[] files = obsDir.GetFiles("*.??o"); PrintWithTime(string.Format("共找到{0}个o文件", files.Length)); Dictionary <int, List <string> > stationsPerDOY = new Dictionary <int, List <string> >(); Dictionary <string, List <int> > doysPerStation = new Dictionary <string, List <int> >(); Dictionary <int, Dictionary <string, FileInfo> > fileDict = new Dictionary <int, Dictionary <string, FileInfo> >(); string stationName; int year, day, doy; foreach (var file in files) { FileName.ParseRinex2(file.Name, out stationName, out day, out year); doy = year * 1000 + day; if (!stationsPerDOY.ContainsKey(doy)) { stationsPerDOY[doy] = new List <string>(); } if (!doysPerStation.ContainsKey(stationName)) { doysPerStation[stationName] = new List <int>(); } if (!fileDict.ContainsKey(doy)) { fileDict[doy] = new Dictionary <string, FileInfo>(); } stationsPerDOY[doy].Add(stationName); doysPerStation[stationName].Add(doy); fileDict[doy].Add(stationName, file); } // 观测值起止时间 int minObsDOY = (from d in stationsPerDOY select d.Key).Min(); int maxObsDOY = (from d in stationsPerDOY select d.Key).Max(); // 轨道起止时间 int minOrbDOY = DOY.AddDays(minObsDOY, -1); int maxOrbDOY = DOY.AddDays(maxObsDOY, 1); // 下载星历,钟差 Download(DOY.AddDays(minObsDOY, -1), DOY.AddDays(maxObsDOY, 1)); // 估计DCB PrintWithTime("估计DCB..."); string[] filePathList = (from p in fileDict[minObsDOY].Values select p.FullName).ToArray(); Dictionary <string, double> recDCB, satDCB; ResolveDCB(minObsDOY, filePathList, DCBOption.Estimate, DCBOption.Estimate, out recDCB, out satDCB); string recDCBName = "0station_dcb.txt"; string satDCBName = "0satellite_dcb.txt"; string recDCBPath = Path.Combine(resFolder, recDCBName); string satDCBPath = Path.Combine(resFolder, satDCBName); string txt = "***\n"; double dcb = 0d; foreach (var rec in recDCB.Keys) { dcb = recDCB[rec] / GeoFun.GNSS.Common.C0 * 1e9; txt += rec + "," + dcb.ToString("#.0000000000") + "\n"; } File.WriteAllText(recDCBPath, txt, Encoding.UTF8); txt = "***\n"; foreach (var sat in satDCB.Keys) { dcb = satDCB[sat] / GeoFun.GNSS.Common.C0 * 1e9; txt += sat + "," + dcb.ToString("#.0000000000") + "\n"; } File.WriteAllText(satDCBPath, txt, Encoding.UTF8); int epoSegNum = 240; foreach (var d in fileDict.Keys) { PrintWithTime(string.Format("正在处理DOY:{0:000}", d)); int beforeDOY = DOY.AddDays(d, -1); int afterDOY = DOY.AddDays(d, 1); Orbit orb = new Orbit(orbFolder); orb.Read(orbFolder, beforeDOY, afterDOY); List <OFile> oFiles = new List <OFile>(); foreach (var s in fileDict[d].Keys) { try { OFile of = new OFile(fileDict[d][s].FullName); PrintWithTime(string.Format("正在处理文件:{0}", of.Path)); if (!of.TryRead()) { continue; } orb.GetSatPos(ref of); of.CalAzElIPP(); of.DetectOutlier(); of.DetectAllArcs(); of.DetectCycleSlip(); of.CalSP4(); oFiles.Add(of); } catch (Exception ex) { continue; } } double b, l; OFile ofile; SphericalHarmonicIonoModel spm; int epoNum = oFiles[0].Epoches.Count; int startIndex = 0, endIndex = epoSegNum; while (startIndex < epoNum) { PrintWithTime(string.Format("电离层二维模型计算 开始历元{0:0000} 结束历元{1:0000}", startIndex, endIndex)); List <string> stationNames = new List <string>(oFiles.Count * 2); List <LinkedList <int> > prn = new List <LinkedList <int> >(); List <LinkedList <double> > lat = new List <LinkedList <double> >(); List <LinkedList <double> > lon = new List <LinkedList <double> >(); List <LinkedList <double> > sp4 = new List <LinkedList <double> >(); List <LinkedList <double> > ele = new List <LinkedList <double> >(); for (int i = 0; i < oFiles.Count; i++) { ofile = oFiles[i]; stationNames.Add(ofile.StationName); LinkedList <int> prns = new LinkedList <int>(); LinkedList <double> lats = new LinkedList <double>(); LinkedList <double> lons = new LinkedList <double>(); LinkedList <double> sp4s = new LinkedList <double>(); LinkedList <double> eles = new LinkedList <double>(); foreach (var p in ofile.Arcs.Keys) { int prnNum = int.Parse(p.Substring(1)); var arcs = ofile.Arcs[p]; foreach (var arc in arcs) { int si = startIndex; int ei = endIndex; if (si > arc.EndIndex) { continue; } if (ei <= arc.StartIndex) { continue; } si = 0; if (startIndex > arc.StartIndex) { si = startIndex - arc.StartIndex; } ei = endIndex - startIndex; if (ei > arc.Length) { ei = arc.Length; } for (int j = si; j < ei; j++) { if (arc[j]["SP4"] <= 0) { continue; } Coordinate.SunGeomagnetic(arc[i].IPP[0], arc[i].IPP[1], arc[i].Epoch.Hour, arc[i].Epoch.Minute, arc[i].Epoch.Second, GeoFun.GNSS.Common.GEOMAGNETIC_POLE_LAT, GeoFun.GNSS.Common.GEOMAGENTIC_POLE_LON, out b, out l); prns.AddLast(prnNum); lats.AddLast(b); lons.AddLast(l); eles.AddLast(arc[j].Elevation); sp4s.AddLast(arc[j]["SP4"]); } } } prn.Add(prns); lat.Add(lats); lon.Add(lons); sp4.Add(sp4s); ele.Add(eles); } IonoModel.CalSphericalHarmonicModel(9, 9, stationNames, prn, lat, lon, sp4, ele, out spm, recDCB, satDCB); string outFileName = string.Format("{0}_{1:0000}.spm.txt", d, startIndex); string outFilePath = Path.Combine(resFolder, outFileName); spm.SaveAs(outFilePath); startIndex = endIndex; endIndex += epoSegNum; if (endIndex > epoNum) { endIndex = epoNum; } } } }
/// <summary> /// 单站单天解 /// </summary> public void ResolveSingleStationSingleDay() { if (string.IsNullOrWhiteSpace(obsFolder)) { FrmIono.MessHelper.Print("\r\n文件夹不存在:" + obsFolder); return; } DirectoryInfo dir = new DirectoryInfo(obsFolder); var files = dir.GetFiles("*.??o"); for (int i = 0; i < files.Length; i++) { FrmIono.MessHelper.Print(string.Format("\r\n{0}:{1}", DateTime.Now, "开始读取文件:" + files[i].Name)); try { OFile of = new OFile(files[i].FullName); if (of.TryRead()) { int year, doy; string stationName; FileName.ParseRinex2(files[i].Name, out stationName, out doy, out year); // 下载星历 Dictionary <string, List <DOY> > doys = new Dictionary <string, List <DOY> >(); doys.Add(stationName, new List <DOY> { new DOY(year, doy) }); if (!Download(doys)) { PrintWithTime("下载星历失败!"); return; } DOY fileDOY = new DOY(year, doy); DOY start = fileDOY.AddDays(-1); DOY end = fileDOY.AddDays(1); // 读取星历 PrintWithTime("正在读取星历..."); Orbit orb = new Orbit(orbFolder); orb.GetAllSp3Files(orbFolder, start, end); orb.Read(orbFolder); // 计算轨道 PrintWithTime("正在计算轨道..."); for (int j = 0; j < of.Epoches.Count; j++) { var epo = of.Epoches[j]; orb.GetSatPos(ref epo); } //探测粗差 PrintWithTime("正在探测粗差..."); of.DetectOutlier(); // 探测弧段 of.DetectAllArcs(); // 探测周跳 PrintWithTime("正在探测周跳..."); of.DetectCycleSlip(); // 计算穿刺点 of.CalIPP(); // 相位平滑伪距 PrintWithTime("正在计算VTEC..."); of.CalSP4(); // 计算VTEC of.CalVTEC(); // 多项式拟合 Print("正在拟合多项式..."); if (FitType == enumFitType.Polynomial) { of.Fit(); } else if (FitType == enumFitType.DoubleDifference) { of.DoubleDifference(); } else if (FitType == enumFitType.Smooth) { of.Smooth(); } // 输出结果 PrintWithTime("正在写入文件..."); of.WriteTEC(resFolder); } else { FrmIono.MessHelper.Print(string.Format("\r\n{0}:{1}", DateTime.Now, "读取文件失败!")); } } catch (Exception e) { FrmIono.MessHelper.Print(string.Format("\r\n{0}:{1}:{2}", DateTime.Now, "解算失败,原因是", e.ToString())); } } }
/// <summary> /// 计算对应o文件的P4,穿刺点 /// </summary> /// <param name="oPath"></param> public static void Calculate(string oPath) { FileInfo info = new FileInfo(oPath); if (info.Name.Length != 12) { throw new ArgumentException("文件名称正确,请检查:" + info.FullName); } // 分解出测站名,doy和年份 string stationName; int doy, year, week, dow; FileName.ParseRinex2(info.Name, out stationName, out doy, out year); Time.DOY2GPS(year, doy, out week, out dow); // 检查是否存在sp3文件 string sp3Path = Path.Combine(info.DirectoryName, string.Format("igs{0}{1}.sp3", week, dow)); if (!File.Exists(sp3Path)) { if (!Downloader.DownloadSp3(week, dow, info.DirectoryName)) { throw new Exception("下载sp3文件失败..."); } } // 读取文件 OFile oFile = new OFile(oPath); SP3File sp3 = new SP3File(sp3Path); oFile.TryRead(); sp3.TryRead(); //Observation.EliminateSatellites(ref oFile.AllEpoch); ObsHelper.CalP4(ref oFile.Epoches); ObsHelper.CalL4(ref oFile.Epoches); ObsHelper.DetectOutlier(ref oFile.Epoches); oFile.DetectAllArcs(); var arcs = oFile.Arcs; foreach (var prn in arcs.Keys) { for (int i = 0; i < arcs[prn].Count; i++) { OArc arc = arcs[prn][i]; Smoother.SmoothP4ByL4(ref arc); } } double[,] ippb = new double[2880, 32]; double[,] ippl = new double[2880, 32]; double[,] sp4 = new double[2880, 32]; if (oFile.Header.approxPos.X == 0d) { throw new Exception("无法获得近似坐标"); } double recX = oFile.Header.approxPos.X; double recY = oFile.Header.approxPos.Y; double recZ = oFile.Header.approxPos.Z; double[] recp = { recX, recY, recZ }; double b, l, h; Coordinate.XYZ2BLH(recX, recY, recZ, out b, out l, out h, Ellipsoid.ELLIP_WGS84); for (int p = 0; p < arcs.Keys.Count; p++) { string prn = arcs.Keys.ElementAt(p); for (int i = 0; i < arcs[prn].Count; i++) { OArc arc = arcs[prn][i]; //多项式拟合 List <double> x = new List <double>(); List <double> y = new List <double>(); for (int j = 0; j < arc.Length; j++) { x.Add(j); y.Add(arc[j]["SP4"]); } PolynomialModel pm = new PolynomialModel(); pm.Order = 3; pm.Fit(x, y); var yy = pm.CalFit(x); for (int j = 0; j < arc.Length; j++) { arc[j]["SP4"] = y[j] - yy[j]; } for (int j = 0; j < arc.Length; j++) { GPST t0 = new GPST(arc[j].Epoch); t0.AddSeconds(-arc[j]["P2"] / GeoFun.GNSS.Common.C0); double[] satp = sp3.GetSatPos(t0, prn); arc[j].SatCoor = satp; double az, el; MathHelper.CalAzEl(recp, satp, out az, out el); double bb, ll; MathHelper.CalIPP(b, l, 63781000, 450000, az, el, out bb, out ll); arc[j].IPP[0] = bb; arc[j].IPP[1] = ll; arc[j].Azimuth = az; arc[j].Elevation = el; ippb[arc.StartIndex + j, p] = bb; ippl[arc.StartIndex + j, p] = ll; double tec = 9.52437 * arc[j]["SP4"]; if (tec > 0.5d || tec < -0.5d) { tec = 0d; } sp4[arc.StartIndex + j, p] = tec; } } } for (int i = 0; i < 24; i++) { StringBuilder sb = new StringBuilder(); for (int j = i * 120; j < i * 120 + 120; j++) { var epoch = oFile.Epoches[j]; foreach (var prn in epoch.AllSat.Keys) { var sat = epoch[prn]; if (sat["SP4"] > 0.5d || sat["SP4"] < -0.5d) { sat["SP4"] = 0d; } if (sat["SP4"] != 0d) { sb.AppendFormat("{0:0#},{1:f10},{2:f10},{3:f3}\r\n", int.Parse(prn.Substring(1)), sat.IPP[1] * Angle.R2D, sat.IPP[0] * Angle.R2D, sat["SP4"] ); } } } File.WriteAllText(string.Format("{0}.{1:0#}-{2:0#}.tec.txt", oPath, i, i + 1), sb.ToString(), Encoding.UTF8); } //// 2个小时一幅图 //for (int i = 0; i < 12; i++) //{ // List<double> lat = new List<double>(); // List<double> lon = new List<double>(); // List<double> tec = new List<double>(); // for (int j = i * 240; j < i * 240 + 240; j++) // { // if (j >= oFile.AllEpoch.Count) // { // break; // } // foreach (var item in oFile.AllEpoch[j].AllSat) // { // var epoch = oFile.AllEpoch[i].Epoch; // var sunL0 = Coordinate.SunLon(epoch.CommonT.Hour, // epoch.CommonT.Minute, (double)epoch.CommonT.second, 8); // var sat = item.Value; // if (sat["SP4"] != 0 && sat["SP4"] > 0) // { // lat.Add(sat.IPP[0]); // lon.Add(sat.IPP[1] - sunL0); // double vtec = Iono.STEC2VTEC(sat["SP4"], sat.Elevation); // tec.Add(vtec); // } // } // } // var shm = SphericalHamonicIonoModel.CalculateModel(5, 5, lat, lon, tec); // for (int j = i * 240; j < i * 240 + 240; j++) // { // if (j - oFile.AllEpoch.Count >= 0) // { // break; // } // foreach (var item in oFile.AllEpoch[j].AllSat) // { // var epoch = oFile.AllEpoch[i].Epoch; // var sunL0 = Coordinate.SunLon(epoch.CommonT.Hour, // epoch.CommonT.Minute, (double)epoch.CommonT.second, 8); // var sat = item.Value; // if (sat["SP4"] != 0) // { // double sp4Est = shm.Calculate(sat.IPP[0], sat.IPP[1] - sunL0); // double sp4Org = sat["SP4"]; // sat["SP4"] -= sp4Est; // } // } // } //} Write(oPath + ".ipp.b.txt", ippb); Write(oPath + ".ipp.l.txt", ippl); Write(oPath + ".meas.p4.txt", sp4); }