1 public static class StandardSubdivisionConvertor 2 { 3 /// <summary> 4 /// 通过图幅号获取四角经纬度坐标 5 /// </summary> 6 /// <param name="subdivCode"></param> 7 /// <returns>返回(经度,纬度)的四角坐标,顺序是西北、东北、东南、西南</returns> 8 public static ((string, string) northWestPoint, (string, string) northEastPoint, (string, string)southEastPoint, (string, string) southWestPoint) GetCoordinatesOfFourCorners(string subdivCode) 9 { 10 ((int degree, int minite, double second) lonDifference, (int degree, int minite, double second) latDifference) = GetLongitudeAndLattitudeDifference(subdivCode); 11 (string longititude, string latitude)southWest = GetCoordinatesOfSouthWestPoint(subdivCode); 12 13 int.TryParse(southWest.longititude.Split('°')[0], out int degreeLonOfSW); 14 int.TryParse(southWest.longititude.Split('°')[1].Split('′')[0], out int miniteLonOfSW); 15 double.TryParse(southWest.longititude.Split('°')[1].Split('′')[1].Split('″')[0], out double secondLonOfSW); 16 17 double sLon = secondLonOfSW + lonDifference.second; 18 double sLon2Second = sLon % 60; 19 int mLon = miniteLonOfSW + (int)sLon / 60 + lonDifference.minite; 20 int mLon2Minite = mLon % 60; 21 int dLon = degreeLonOfSW + lonDifference.degree + mLon / 60; 22 23 string rLon = $"{dLon}°{mLon2Minite}′{sLon2Second}″"; 24 25 26 int.TryParse(southWest.latitude.Split('°')[0], out int degreeLatOfSW); 27 int.TryParse(southWest.latitude.Split('°')[1].Split('′')[0], out int miniteLatOfSW); 28 double.TryParse(southWest.latitude.Split('°')[1].Split('′')[1].Split('″')[0], out double secondLatOfSW); 29 30 double sLat = secondLatOfSW + latDifference.second; 31 double sLat2Second = sLat % 60; 32 int mLat = miniteLatOfSW + (int)sLat / 60 + latDifference.minite; 33 int mLat2Minite = mLat % 60; 34 int dLat = degreeLatOfSW + latDifference.degree + mLat / 60; 35 36 string uLat = $"{dLat}°{mLat2Minite}′{sLat2Second}″"; 37 38 return new ( 39 (southWest.longititude, uLat), 40 (rLon, uLat), 41 (rLon, southWest.latitude), 42 (southWest.longititude,southWest.latitude) 43 ); 44 } 45 /// <summary> 46 /// 根据图幅号计算图幅西南角的坐标。 47 /// </summary> 48 /// <param name="subdivCode"></param> 49 /// <returns>度分秒格式的经纬度坐标</returns> 50 public static (string longititude,string latitude) GetCoordinatesOfSouthWestPoint(string subdivCode) 51 { 52 subdivCode = subdivCode.ToUpper(); 53 //百万行号(纬度带字符码所对应数字码) 54 int latRow = subdivCode[0] switch 55 { 56 'A' => 1, 57 'B' => 2, 58 'C' => 3, 59 'D' => 4, 60 'E' => 5, 61 'F' => 6, 62 'G' => 7, 63 'H' => 8, 64 'I' => 9, 65 'J' => 10, 66 'K' => 11, 67 'L' => 12, 68 'M' => 13, 69 'N' => 14, 70 'O' => 15, 71 'P' => 16, 72 'Q' => 17, 73 'R' => 18, 74 'S' => 19, 75 'T' => 20, 76 'U' => 21, 77 'V' => 22, 78 _ => 0 79 }; 80 if (latRow < 1) throw new ArgumentException("图幅号中百万行号错误!"); 81 //百万列号(经度带数字码) 82 if (!int.TryParse(subdivCode.Substring(1, 2), out int lonCol)||lonCol<1) throw new ArgumentException("图幅号中百万列号错误!"); 83 // 84 if (!int.TryParse(subdivCode.Substring(4, 3), out int row) || row < 1) throw new ArgumentException("图幅号中所在行号错误!"); 85 if (!int.TryParse(subdivCode.Substring(7, 3), out int col) || col < 1) throw new ArgumentException("图幅号中所在列号错误!"); 86 87 //获取经差、纬差 88 ((int, int, double) lonDifference, (int, int, double) latDifference) lonLatDifference = GetLongitudeAndLattitudeDifference(subdivCode); 89 (int, int, double) lonDifference = lonLatDifference.Item1; 90 (int, int, double) latDifference = lonLatDifference.Item2; 91 92 //经度 93 double sLon = (col - 1) * lonDifference.Item3; 94 int sLon2Degree = (int)sLon / 3600; 95 int sLon2Minite = (int)sLon % 3600 / 60; 96 double sLon2Second = sLon % 3600 % 60; 97 98 int mLon = (col - 1) * lonDifference.Item2; 99 int mLon2Degree = (sLon2Minite + mLon) / 60; 100 int mLon2Minite = (sLon2Minite + mLon) % 60; 101 102 string lon = $"{(lonCol - 31) * 6 + lonDifference.Item1 + sLon2Degree + mLon2Degree}°{mLon2Minite}′{sLon2Second}″"; 103 104 //纬度 105 double sLat = row * latDifference.Item3; 106 int sLat2Degree = (int)sLat / 3600; 107 int sLat2Minite = (int)sLat % 3600 / 60; 108 double sLat2Second = (sLat % 3600) % 60; 109 110 int mLat = row * latDifference.Item2; 111 int mLat2Degree = (sLat2Minite + mLat) / 60; 112 int mLat2Minite = (sLat2Minite + mLat) % 60; 113 114 int dLat = row * latDifference.Item1 + sLat2Degree + mLat2Degree; 115 int degreeLat = mLat2Minite > 0 || sLat2Second > 0 ? 4 - dLat - 1 : 4 - dLat; 116 int miniteLat = sLat2Second == 0 && mLat2Minite == 0 ? 0 : sLat2Second > 0 ? 60 - mLat2Minite - 1 : 60 - mLat2Minite; 117 double secondLat = sLat2Second > 0 ? 60 - sLat2Second : 0; 118 119 string lat = $"{(latRow - 1) * 4 + degreeLat}°{miniteLat}′{secondLat}″"; 120 121 return new (lon, lat); 122 } 123 124 /// <summary> 125 /// 根据图幅号返回图幅的经差、纬差 126 /// </summary> 127 /// <param name="scaleCode"></param> 128 /// <returns>对应度分秒的经差和纬差</returns> 129 private static ((int degree, int minite, double second) lonDifference , (int degree, int minite, double second) latDifference) GetLongitudeAndLattitudeDifference(string subdivCode) 130 { 131 //经差 132 (int, int, double) lonDifference = subdivCode[3] switch 133 { 134 'B' => (3, 0, 0), 135 'C' => (1, 30, 0), 136 'D' => (0, 30, 0), 137 'E' => (0, 15, 0), 138 'F' => (0, 7, 30), 139 'G' => (0, 3, 45), 140 'H' => (0, 1, 52.5), 141 'I' => (0, 0, 37.5), 142 'J' => (0, 0, 18.75), 143 'K' => (0, 0, 9.375), 144 _ => (-1, -1, -1) 145 }; 146 if (lonDifference.Item1 < 0) throw new ArgumentException("图幅号中比例尺代码错误!"); 147 //纬差 148 (int,int,double) latDifference = subdivCode[3] switch 149 { 150 'B' => (2, 0, 0), 151 'C' => (1, 0, 0), 152 'D' => (0, 20, 0), 153 'E' => (0, 10, 0), 154 'F' => (0, 5, 0), 155 'G' => (0, 2, 30), 156 'H' => (0, 1, 15), 157 'I' => (0, 0, 25), 158 'J' => (0, 0, 12.5), 159 'K' => (0, 0, 6.25), 160 _ => (-1, -1, -1) 161 }; 162 return new (lonDifference, latDifference); 163 } 164 165 /// <summary> 166 /// 获取本幅八方向邻幅的图幅号 167 /// </summary> 168 /// <param name="subdivCode"></param> 169 /// <returns></returns> 170 public static ((string nw, string n, string ne) northSide, (string sw, string s, string se) southSide, string westSide, string eastSide) GetEightDirectionSubdivCode(string subdivCode) 171 { 172 //百万行号(纬度带字符码所对应数字码) 173 List<char> codeOfMillion = new List<char>() { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V' }; 174 //List<int> rowOfMillion = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 }; 175 176 //本幅比例尺代码 177 char thisScaleCode = subdivCode[3]; 178 //行列数 179 int thisSubdivCount = thisScaleCode switch 180 { 181 'B' => 2, 182 'C' => 4, 183 'D' => 12, 184 'E' => 24, 185 'F' => 48, 186 'G' => 96, 187 'H' => 192, 188 'I' => 576, 189 'J' => 1152, 190 'K' => 2304, 191 _ => -1 192 }; 193 if (thisSubdivCount == -1) throw new ArgumentException("图幅号中比例尺代码错误!"); 194 195 //本幅所在百万行号 196 char thisMRow = subdivCode[0]; 197 if (codeOfMillion.IndexOf(thisMRow) < 0) throw new ArgumentException("图幅号中所在百万行号错误!"); 198 //本幅所在百万列号 199 if (!int.TryParse(subdivCode.Substring(1, 2), out int thisMCol) || thisMCol < 43 || thisMCol > 53) throw new ArgumentException("图幅号中所在百万列号错误!"); 200 //本幅行列号 201 if (!int.TryParse(subdivCode.Substring(4, 3), out int thisRow) || thisRow < 1 || thisRow > thisSubdivCount) throw new ArgumentException("图幅号中所在行号错误!"); 202 if (!int.TryParse(subdivCode.Substring(7, 3), out int thisCol) || thisCol < 1 || thisCol > thisSubdivCount) throw new ArgumentException("图幅号中所在列号错误!"); 203 204 205 // ▁▁▁▁▁N▁▁▁▁▁ 206 // ▏ ▏ ▏ ▏ 207 // ▏ ▏ ▏ ▏ 208 // W━━━━━━━━━━E 209 // ▏ ▏ ▏ ▏ 210 // ▏ ▏ ▏ ▏ 211 // ━━━━━━━━━━━ 212 // ▏ ▏ ▏ ▏ 213 // ▏ ▏ ▏ ▏ 214 // ▔▔▔▔▔S▔▔▔▔▔ 215 //本幅北邻幅行号 216 int rowN; 217 char mRowN; 218 if (thisRow == 1) 219 { 220 rowN = thisSubdivCount; 221 mRowN = codeOfMillion[codeOfMillion.IndexOf(thisMRow) + 1]; 222 } 223 else 224 { 225 rowN = thisRow - 1; 226 mRowN = thisMRow; 227 } 228 //本幅南邻幅行号 229 int rowS; 230 char mRowS; 231 if (thisRow == thisSubdivCount) 232 { 233 rowS = 1; 234 mRowS = codeOfMillion[codeOfMillion.IndexOf(thisMRow) - 1]; 235 } 236 else 237 { 238 rowS = thisRow + 1; 239 mRowS = thisMRow; 240 } 241 //本幅西邻幅列号 242 int colW, mColW; 243 if (thisCol == 1) 244 { 245 colW = thisSubdivCount; 246 mColW = thisMCol - 1; 247 } 248 else 249 { 250 colW = thisCol - 1; 251 mColW = thisMCol; 252 } 253 //本幅东邻幅列号 254 int colE, mColE; 255 if (thisCol == thisSubdivCount) 256 { 257 colE = 1; 258 mColE = thisMCol + 1; 259 } 260 else 261 { 262 colE = thisCol + 1; 263 mColE = thisMCol; 264 } 265 string NW = $"{mRowN}{mColW}{thisScaleCode}{string.Format("{0:d3}", rowN)}{string.Format("{0:d3}", colW)}"; 266 string N = $"{mRowN}{thisMCol}{thisScaleCode}{string.Format("{0:d3}", rowN)}{string.Format("{0:d3}", thisCol)}"; 267 string NE = $"{mRowN}{mColE}{thisScaleCode}{string.Format("{0:d3}", rowN)}{string.Format("{0:d3}", colE)}"; 268 string E = $"{thisMRow}{mColE}{thisScaleCode}{string.Format("{0:d3}", thisRow)}{string.Format("{0:d3}", colE)}"; 269 string SE = $"{mRowS}{mColE}{thisScaleCode}{string.Format("{0:d3}", rowS)}{string.Format("{0:d3}", colE)}"; 270 string S = $"{mRowS}{thisMCol}{thisScaleCode}{string.Format("{0:d3}", rowS)}{string.Format("{0:d3}", thisCol)}"; 271 string SW = $"{mRowS}{mColW}{thisScaleCode}{string.Format("{0:d3}", rowS)}{string.Format("{0:d3}", colW)}"; 272 string W = $"{thisMRow}{mColW}{thisScaleCode}{string.Format("{0:d3}", thisRow)}{string.Format("{0:d3}", colW)}"; 273 return new((NW, N, NE), (SW, S, SE), W, E); 274 } 275 }
标签:13989,Format,C#,double,int,分幅,subdivCode,d3,string From: https://www.cnblogs.com/yzhyingcool/p/17811341.html