You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649
  1. #include "nds.h"
  2. #include <cassert>
  3. #include <cmath>
  4. #include <algorithm>
  5. #include <bitset>
  6. #include <iostream>
  7. #include <limits>
  8. #include <vector>
  9. using namespace std;
  10. inline bool segmentIntersection(const PointD& p1, const PointD& p2, const PointD& q1,
  11. const PointD& q2)
  12. {
  13. if (max(p1.x, p2.x) < min(q1.x, q2.x) || max(q1.x, q2.x) < min(p1.x, p2.x)
  14. || max(p1.y, p2.y) < min(q1.y, q2.y) || max(q1.y, q2.y) < min(p1.y, p2.y))
  15. return false;
  16. double res1 = (p1.x - p2.x) * (q1.y - p2.y) - (p1.y - p2.y) * (q1.x - p2.x);
  17. double res2 = (p1.x - p2.x) * (q2.y - p2.y) - (p1.y - p2.y) * (q2.x - p2.x);
  18. double res3 = (q1.x - q2.x) * (p1.y - q2.y) - (q1.y - q2.y) * (p1.x - q2.x);
  19. double res4 = (q1.x - q2.x) * (p2.y - q2.y) - (q1.y - q2.y) * (p2.x - q2.x);
  20. return res1 * res2 <= 0 && res3 * res4 <= 0;
  21. }
  22. inline bool segmentIntersection(const PointD& startA, const PointD& endA,
  23. const PointD& startB, const PointD& endB,
  24. PointD& crossPoint)
  25. {
  26. /* // xsub * y + ysub * x + inter = 0 // */
  27. double start1[2] = {startA.x / 100000000.0, startA.y / 100000000.0};
  28. double end1[2] = {endA.x / 100000000.0, endA.y / 100000000.0};
  29. double start2[2] = {startB.x / 100000000.0, startB.y / 100000000.0};
  30. double end2[2] = {endB.x / 100000000.0, endB.y / 100000000.0};
  31. // calculate A、B、C.
  32. double xsub1 = start1[0] - end1[0];
  33. double ysub1 = end1[1] - start1[1];
  34. double xsub2 = start2[0] - end2[0];
  35. double ysub2 = end2[1] - start2[1];
  36. double inter1 = end1[0] * start1[1] - start1[0] * end1[1];
  37. double inter2 = end2[0] * start2[1] - start2[0] * end2[1];
  38. double ans[2];
  39. auto convertCrossPoint = [&ans](PointD& crossPos) {
  40. crossPos.x = ans[0] * 100000000.0;
  41. crossPos.y = ans[1] * 100000000.0;
  42. };
  43. if (xsub1 * ysub2 == xsub2 * ysub1) {
  44. if (inter1 != inter2) {
  45. return false;
  46. }
  47. if ((end1[0] >= start2[0] && start1[0] < start2[0])
  48. || (end1[0] > start2[0] && start1[0] <= start2[0])) {
  49. ans[0] = (double)start2[0];
  50. ans[1] = (double)start2[1];
  51. convertCrossPoint(crossPoint);
  52. return true;
  53. }
  54. if ((end1[0] <= start2[0] && start1[0] > start2[0])
  55. || (end1[0] < start2[0] && start1[0] >= start2[0])) {
  56. ans[0] = end1[0];
  57. ans[1] = end1[1];
  58. convertCrossPoint(crossPoint);
  59. return true;
  60. }
  61. if ((start1[0] == start2[0] && start1[1] == start2[1])
  62. || (start1[0] == end2[0] && start1[1] == end2[1])) {
  63. ans[0] = (double)start1[0];
  64. ans[1] = (double)start1[1];
  65. convertCrossPoint(crossPoint);
  66. return true;
  67. }
  68. if ((start2[0] == end1[0] && start2[1] == end1[1])
  69. || (end1[0] == end2[0] && end1[1] == end2[1])) {
  70. ans[0] = (double)end1[0];
  71. ans[1] = (double)end1[1];
  72. convertCrossPoint(crossPoint);
  73. return true;
  74. }
  75. return false;
  76. }
  77. double x = (double)((inter2 * xsub1 - inter1 * xsub2) / (xsub2 * ysub1 - xsub1 * ysub2));
  78. double y = (double)((inter1 * ysub2 - inter2 * ysub1) / (xsub2 * ysub1 - xsub1 * ysub2));
  79. ans[0] = x;
  80. ans[1] = y;
  81. if (((x <= start1[0] && x >= end1[0]) || (x >= start1[0] && x <= end1[0]))
  82. && ((x <= start2[0] && x >= end2[0]) || (x >= start2[0] && x <= end2[0]))) {
  83. convertCrossPoint(crossPoint);
  84. return true;
  85. }
  86. return false;
  87. }
  88. inline bool segmentIntersectionWithRect(const PointD& p1, const PointD& p2,
  89. const RectD& rct)
  90. {
  91. if (rct.contain(p1) || rct.contain(p2)) return true;
  92. PointD q1(rct.minX, rct.minY);
  93. PointD q2(rct.minX, rct.maxY);
  94. PointD q3(rct.maxX, rct.maxY);
  95. PointD q4(rct.maxX, rct.minY);
  96. return segmentIntersection(p1, p2, q1, q2) || segmentIntersection(p1, p2, q2, q3)
  97. || segmentIntersection(p1, p2, q3, q4) || segmentIntersection(p1, p2, q4, q1);
  98. }
  99. namespace nds {
  100. namespace {
  101. using MortonCode = std::int64_t;
  102. //各个level的grid index mask,获取的时候直接 gridIndexMask[level]
  103. constexpr std::int32_t mashIdMask[] = {0b1,
  104. 0b111,
  105. 0b11111,
  106. 0b1111111,
  107. 0b111111111,
  108. 0b11111111111,
  109. 0b1111111111111,
  110. 0b111111111111111,
  111. 0b11111111111111111,
  112. 0b1111111111111111111,
  113. 0b111111111111111111111,
  114. 0b11111111111111111111111,
  115. 0b1111111111111111111111111,
  116. 0b111111111111111111111111111,
  117. 0b11111111111111111111111111111,
  118. 0b1111111111111111111111111111111};
  119. // nds point各个level的X/Y掩码
  120. constexpr std::int32_t gridXMask[] = {0b1,
  121. 0b11,
  122. 0b111,
  123. 0b1111,
  124. 0b11111,
  125. 0b111111,
  126. 0b1111111,
  127. 0b11111111,
  128. 0b111111111,
  129. 0b1111111111,
  130. 0b11111111111,
  131. 0b111111111111,
  132. 0b1111111111111,
  133. 0b11111111111111,
  134. 0b111111111111111,
  135. 0b1111111111111111};
  136. constexpr std::int32_t gridYMask[] = {0b0,
  137. 0b1,
  138. 0b11,
  139. 0b111,
  140. 0b1111,
  141. 0b11111,
  142. 0b111111,
  143. 0b1111111,
  144. 0b11111111,
  145. 0b111111111,
  146. 0b1111111111,
  147. 0b11111111111,
  148. 0b111111111111,
  149. 0b1111111111111,
  150. 0b11111111111111,
  151. 0b111111111111111};
  152. /// judge (lon, lat) is valid or not
  153. /// \param lon [-180, 180)
  154. /// \param lat [-90, 90)
  155. /// \return
  156. bool isValidLonLat(double lon, double lat)
  157. {
  158. return lon <= MAX_LON && lon >= MIN_LON && lat <= MAX_LAT && lat >= MIN_LAT;
  159. }
  160. bool isValidLevel(uint level)
  161. {
  162. return level >= 0 && level <= 15;
  163. }
  164. LevelId getLevelId(uint level)
  165. {
  166. return LevelId(1 << (16 + level));
  167. }
  168. MortonCode ndsPoint2Mortoncode(const NdsPoint& ndsPoint)
  169. {
  170. // highest bit of X to 2th highest bit of mortoncode
  171. MortonCode mortoncode = (((uint64_t)std::get<0>(ndsPoint) >> 31) & 1) << (31 * 2);
  172. for (int i = 30; i >= 0; i--) {
  173. int64_t xx = ((uint64_t)(std::get<0>(ndsPoint) >> i) & 1) << (i * 2);
  174. int64_t yy = ((uint64_t)(std::get<1>(ndsPoint) >> i) & 1) << (i * 2 + 1);
  175. mortoncode = mortoncode | xx | yy;
  176. }
  177. return mortoncode;
  178. }
  179. NdsPoint mortoncode2NdsPoint(MortonCode mortoncode)
  180. {
  181. int32_t x = 0;
  182. int32_t y = 0;
  183. for (uint i = 0; i < 32; i++) {
  184. x = x | ((mortoncode >> (i * 2)) & 1) << i;
  185. y = y | ((mortoncode >> (i * 2 + 1)) & 1) << i;
  186. }
  187. y = y | ((y >> 30) << 31); // 将y最高位补齐
  188. return std::make_tuple(x, y);
  189. }
  190. MortonCode lonLat2Mortoncode(double lon, double lat)
  191. {
  192. return ndsPoint2Mortoncode(lonLat2NdsPoint(lon, lat));
  193. }
  194. std::tuple<double, double> mortoncode2LonLat(MortonCode mortoncode)
  195. {
  196. return ndsPoint2lonLat(mortoncode2NdsPoint(mortoncode));
  197. }
  198. MeshId mortoncode2MeshId(MortonCode morton, uint level)
  199. {
  200. return MeshId(morton >> (63 - (level * 2 + 1)));
  201. }
  202. uint getGridLevel(NdsGridId gridId)
  203. {
  204. if (gridId == NDS_INVALID_ID) {
  205. return NDS_INVALID_ID;
  206. }
  207. for (uint level = NDS_LEVEL_COUNT - 1; level >= 0; level--) {
  208. LevelId lid = getLevelId(level);
  209. if (gridId & lid)
  210. return level;
  211. }
  212. return NDS_INVALID_ID;
  213. }
  214. // grid 左下角坐标
  215. MortonCode getGridConnerMortoncode(const NdsGridId gridId)
  216. {
  217. std::tuple<MeshId, std::int32_t> ml = gridId2MeshIdAndLevel(gridId);
  218. MeshId meshId = std::get<0>(ml);
  219. uint level = std::get<1>(ml);
  220. // mesh id to morton code
  221. MortonCode morton = (MortonCode)meshId << (63 - (2 * level + 1));
  222. return morton;
  223. }
  224. std::tuple<double, double> getGridConnerPoint(const NdsGridId gridId)
  225. {
  226. return mortoncode2LonLat(getGridConnerMortoncode(gridId));
  227. }
  228. } // namespace
  229. /**
  230. * @brief get the width of the grid at the specified level in latitude and
  231. * longitude coordinate, unit: degree
  232. *
  233. * @param level
  234. * @return grid width in degree
  235. */
  236. double getGridSize(uint level)
  237. {
  238. return ((double)180.0 / (1 << level));
  239. }
  240. NdsPoint lonLat2NdsPoint(double lon, double lat)
  241. {
  242. double x = lon / NDS_PRECISION;
  243. double y = lat / NDS_PRECISION;
  244. return std::make_tuple(int32_t(floor(x)), int32_t(floor(y)));
  245. }
  246. std::tuple<double, double> ndsPoint2lonLat(const NdsPoint& ndsPoint)
  247. {
  248. double x = std::get<0>(ndsPoint) * NDS_PRECISION;
  249. double y = std::get<1>(ndsPoint) * NDS_PRECISION;
  250. return std::make_tuple(x, y);
  251. }
  252. MeshId getMeshId(double lon, double lat, uint level)
  253. {
  254. if (!isValidLevel(level)) {
  255. return NDS_INVALID_ID;
  256. }
  257. MortonCode morton = lonLat2Mortoncode(lon, lat);
  258. return mortoncode2MeshId(morton, level);
  259. }
  260. MeshId getMeshId(const NdsPoint& ndsPoint, uint level)
  261. {
  262. if (!isValidLevel(level)) {
  263. return NDS_INVALID_ID;
  264. }
  265. MortonCode mortoncode = ndsPoint2Mortoncode(ndsPoint);
  266. return mortoncode2MeshId(mortoncode, level);
  267. }
  268. std::vector<MeshId> getSegmentMeshIds(const PointD& p1, const PointD& p2, uint level)
  269. {
  270. std::vector<MeshId> ids;
  271. if (p1 == p2) {
  272. ids.emplace_back(getMeshId(p1.x, p1.y, level));
  273. } else {
  274. MeshId id1 = getMeshId(p1.x, p1.y, level);
  275. MeshId id2 = getMeshId(p2.x, p2.y, level);
  276. if (id1 == id2) {
  277. ids.emplace_back(id1);
  278. } else {
  279. RectD rct(std::min(p1.x, p2.x), std::max(p1.x, p2.x), std::min(p1.y, p2.y),
  280. std::max(p1.y, p2.y));
  281. std::vector<MeshId> tmpIds = getMeshIdInRect(rct, level);
  282. for (auto& id : tmpIds) {
  283. RectD _rct = getMeshRect(id, level);
  284. if (segmentIntersectionWithRect(p1, p2, _rct)) {
  285. ids.emplace_back(id);
  286. }
  287. }
  288. }
  289. }
  290. return ids;
  291. }
  292. NdsGridId getGridId(MeshId meshId, uint level)
  293. {
  294. return (NdsGridId)(getLevelId(level) | meshId);
  295. }
  296. NdsGridId getGridId(double lon, double lat, uint level)
  297. {
  298. if (!isValidLevel(level)) {
  299. return NDS_INVALID_ID;
  300. }
  301. MeshId meshId = getMeshId(lon, lat, level);
  302. return getGridId(meshId, level);
  303. }
  304. NdsGridId getGridId(const NdsPoint& ndsPt, uint level)
  305. {
  306. if (!isValidLevel(level)) {
  307. return NDS_INVALID_ID;
  308. }
  309. MeshId meshId = getMeshId(ndsPt, level);
  310. return getGridId(meshId, level);
  311. }
  312. std::tuple<MeshId, std::int32_t> gridId2MeshIdAndLevel(NdsGridId gridId)
  313. {
  314. uint level = getGridLevel(gridId);
  315. if (level != NDS_INVALID_ID) {
  316. MeshId meshId = gridId & mashIdMask[level];
  317. return std::make_tuple(meshId, level);
  318. }
  319. return std::make_tuple(NDS_INVALID_ID, NDS_INVALID_ID);
  320. }
  321. RectD getMeshRect(MeshId meshId, uint level)
  322. {
  323. NdsGridId gridId = getGridId(meshId, level);
  324. return getGridRect(gridId);
  325. }
  326. PointD getMeshCenter(MeshId meshId, uint level)
  327. {
  328. PointD p;
  329. RectD rct = getMeshRect(meshId, level);
  330. if (!rct.isInvalid()) {
  331. p.x = (rct.maxX + rct.minX) / 2;
  332. p.y = (rct.maxY + rct.minY) / 2;
  333. p.z = (rct.maxZ + rct.minZ) / 2;
  334. }
  335. return p;
  336. }
  337. /// 给定NdsGridId,获取对应网格的l/t/r/b点经纬度
  338. RectD getGridRect(NdsGridId gridId)
  339. {
  340. std::tuple<MeshId, std::int32_t> ml = gridId2MeshIdAndLevel(gridId);
  341. MeshId meshId = std::get<0>(ml);
  342. uint level = std::get<1>(ml);
  343. // 0级别morton code单独处理
  344. if (level == 0) {
  345. if (meshId == 0) { // 东半球
  346. return RectD(0.0, 180.0, -90.0, 90.0);
  347. // return std::make_tuple(0, -90, 180, 90);
  348. } else if (meshId == 1) { // 西半球
  349. return RectD(-180.0, 0.0, -90.0, 90.0);
  350. // return std::make_tuple(-180, -90, 0, 90);
  351. }
  352. }
  353. double w = getGridSize(level);
  354. std::tuple<double, double> lb = getGridConnerPoint(gridId);
  355. return RectD(std::get<0>(lb), std::get<0>(lb) + w, std::get<1>(lb), std::get<1>(lb) + w);
  356. }
  357. RectD getGridsRect(std::vector<NdsGridId> gridIds)
  358. {
  359. double l = std::numeric_limits<double>::max();
  360. double t = -std::numeric_limits<double>::max();
  361. double r = -std::numeric_limits<double>::max();
  362. double b = std::numeric_limits<double>::max();
  363. RectD rct_new; // add by zj
  364. for (auto id : gridIds) {
  365. RectD rct = getGridRect(id);
  366. l = std::min(l, rct.minX);
  367. t = std::max(t, rct.maxY);
  368. r = std::max(r, rct.maxX);
  369. b = std::min(b, rct.minY);
  370. // l = std::min(l, std::get<0>(rct));
  371. // t = std::max(t, std::get<1>(rct));
  372. // r = std::max(r, std::get<2>(rct));
  373. // b = std::min(b, std::get<3>(rct));
  374. }
  375. rct_new.minX = l;
  376. rct_new.maxY = t;
  377. rct_new.maxX = r;
  378. rct_new.minY = b;
  379. return rct_new;
  380. // return {l, t, r, b};
  381. }
  382. RectD getMeshsRect(std::vector<MeshId> meshIds, uint level)
  383. {
  384. std::vector<NdsGridId> gridIds;
  385. for (auto mId : meshIds) {
  386. gridIds.push_back(getGridId(mId, level));
  387. }
  388. return getGridsRect(gridIds);
  389. }
  390. std::vector<MeshId> getMeshIdInRect(const RectD& rct, uint level)
  391. {
  392. std::vector<MeshId> ids;
  393. double l = std::max(MIN_LON, rct.minX);
  394. double b = std::max(MIN_LAT, rct.minY);
  395. double t = std::min(MAX_LAT, rct.maxY);
  396. double r = std::min(MAX_LON, rct.maxX);
  397. if (b > t || l > r) {
  398. return ids;
  399. }
  400. MeshId minMeshId = getMeshId(l, b, level);
  401. MeshId maxMeshId = getMeshId(r, t, level);
  402. // std::cout << "minMeshId=\t" << std::bitset<32>(minMeshId) << std::endl;
  403. // std::cout << "maxMeshId=\t" << std::bitset<32>(maxMeshId) << std::endl;
  404. // 当前level级别的NDS point,直接xy加减就是周边瓦片的nds grid id
  405. NdsPoint minXY = mortoncode2NdsPoint(minMeshId);
  406. NdsPoint maxXY = mortoncode2NdsPoint(maxMeshId);
  407. // std::cout << "minXY:x=\t" << std::bitset<32>(std::get<0>(minXY)) << std::endl;
  408. // std::cout << "minXY:y=\t" << std::bitset<32>(std::get<1>(minXY)) << std::endl;
  409. // std::cout << "maxXY:x=\t" << std::bitset<32>(std::get<0>(maxXY)) << std::endl;
  410. // std::cout << "maxXY:y=\t" << std::bitset<32>(std::get<1>(maxXY)) << std::endl;
  411. int minX = INT_N_2_INT32(std::get<0>(minXY), level + 1); // x的bit个数是level+1
  412. int maxX = INT_N_2_INT32(std::get<0>(maxXY), level + 1);
  413. int minY = INT_N_2_INT32(std::get<1>(minXY), level); // y的bit个数是level
  414. int maxY = INT_N_2_INT32(std::get<1>(maxXY), level);
  415. // std::cout << "minX=\t\t" << std::bitset<32>(minX) << std::endl;
  416. // std::cout << "maxX=\t\t" << std::bitset<32>(maxX) << std::endl;
  417. // std::cout << "minY=\t\t" << std::bitset<32>(minY) << std::endl;
  418. // std::cout << "maxY=\t\t" << std::bitset<32>(maxY) << std::endl;
  419. for (int j = maxY; j >= minY; j--) {
  420. for (int i = minX; i <= maxX; ++i) {
  421. // std::cout << "i=\t\t" << std::bitset<32>(i) << std::endl;
  422. // std::cout << "j=\t\t" << std::bitset<32>(j) << std::endl;
  423. int lon = i & gridXMask[level];
  424. int lat = j & gridYMask[level];
  425. // std::cout << "lon=\t\t" << std::bitset<32>(i) << std::endl;
  426. // std::cout << "lat=\t\t" << std::bitset<32>(j) << std::endl;
  427. MortonCode m = ndsPoint2Mortoncode(std::make_tuple(lon, lat));
  428. // std::cout << "mortonCode=\t" << std::bitset<32>(m) << std::endl;
  429. ids.push_back(static_cast<std::uint32_t>(m));
  430. }
  431. }
  432. return ids;
  433. }
  434. /**
  435. * 获取和指定经纬度相交的gridid
  436. */
  437. std::vector<NdsGridId> getGridIdInRect(const RectD& rct, uint level)
  438. {
  439. std::vector<MeshId> meshIds = getMeshIdInRect(rct, level);
  440. LevelId levelId = getLevelId(level);
  441. std::vector<NdsGridId> ids;
  442. for (auto m : meshIds) {
  443. ids.push_back(NdsGridId(levelId | m));
  444. }
  445. return ids;
  446. }
  447. std::vector<MeshId> getAdjacentMeshIds(MeshId id, uint level, uint32_t n)
  448. {
  449. std::vector<MeshId> meshIds;
  450. if (id != NDS_INVALID_ID && level != 0 && level != 1 && n != 0) {
  451. NdsPoint point = mortoncode2NdsPoint(id);
  452. int32_t x = std::get<0>(point);
  453. int32_t y = std::get<1>(point);
  454. // 只保留对应的有效位
  455. int32_t minX = (x - n) & gridXMask[level];
  456. int32_t maxX = (x + n) & gridXMask[level];
  457. int32_t minY = (y - n) & gridYMask[level];
  458. int32_t maxY = (y + n) & gridYMask[level];
  459. for (int j = maxY; j >= minY; j--) {
  460. for (int i = minX; i <= maxX; ++i) {
  461. MortonCode m = ndsPoint2Mortoncode(std::make_tuple(i, j));
  462. meshIds.push_back(static_cast<std::uint32_t>(m));
  463. }
  464. }
  465. }
  466. return meshIds;
  467. }
  468. std::vector<MeshId> get8AroundMeshId(MeshId meshId, uint level)
  469. {
  470. std::vector<MeshId> aroundMeshIds;
  471. aroundMeshIds.assign(8, NDS_INVALID_ID);
  472. if (meshId != NDS_INVALID_ID && level != 0 && level != 1) {
  473. // mesh id即当前level的前(2*level+1)bit莫顿码
  474. // 拆分出来的NDSPoint也是当前瓦片的在全部瓦片中的(x,y)位置
  475. // x,y 加减即可获取周边瓦片位置
  476. NdsPoint point = mortoncode2NdsPoint(meshId);
  477. int32_t x = std::get<0>(point);
  478. int32_t y = std::get<1>(point);
  479. // cout << "NDS point x:" << x << " Y: " << y << endl;
  480. // 只保留对应的有效位
  481. int32_t lx = (x - 1) & gridXMask[level];
  482. int32_t rx = (x + 1) & gridXMask[level];
  483. int32_t ty = (y + 1) & gridYMask[level];
  484. int32_t by = (y - 1) & gridYMask[level];
  485. // cout << "lx: " << lx << " rx: " << rx << " ty: " << ty << " bx: " << by << endl;
  486. //左右上下组装新的morton code
  487. aroundMeshIds[0] = static_cast<std::uint32_t>(ndsPoint2Mortoncode({lx, ty}));
  488. aroundMeshIds[1] = static_cast<std::uint32_t>(ndsPoint2Mortoncode({x, ty}));
  489. aroundMeshIds[2] = static_cast<std::uint32_t>(ndsPoint2Mortoncode({rx, ty}));
  490. aroundMeshIds[3] = static_cast<std::uint32_t>(ndsPoint2Mortoncode({rx, y}));
  491. aroundMeshIds[4] = static_cast<std::uint32_t>(ndsPoint2Mortoncode({rx, by}));
  492. aroundMeshIds[5] = static_cast<std::uint32_t>(ndsPoint2Mortoncode({x, by}));
  493. aroundMeshIds[6] = static_cast<std::uint32_t>(ndsPoint2Mortoncode({lx, by}));
  494. aroundMeshIds[7] = static_cast<std::uint32_t>(ndsPoint2Mortoncode({lx, y}));
  495. // std::uint32_t std::int64_t
  496. //边界检查,越界的更新为无效值,只对level>=2的层级管用
  497. int32_t signMaskX = 1 << level; // 西半球X最高位为1,东半球为0
  498. int32_t signMaskY = 1 << (level - 1); // 南半球最高位为1,北半球为0
  499. // x最高位为1其余为0为左边界
  500. if (((x & gridXMask[level]) == signMaskX)) {
  501. //[左边界0, 6, 7网格无效]
  502. aroundMeshIds[0] = NDS_INVALID_ID;
  503. aroundMeshIds[6] = NDS_INVALID_ID;
  504. aroundMeshIds[7] = NDS_INVALID_ID;
  505. }
  506. // x最高位为0其余为1为右边界
  507. else if ((x & gridXMask[level]) == (signMaskX - 1)) {
  508. //[右边界2,3,4无效]
  509. aroundMeshIds[2] = NDS_INVALID_ID;
  510. aroundMeshIds[3] = NDS_INVALID_ID;
  511. aroundMeshIds[4] = NDS_INVALID_ID;
  512. }
  513. // Y最高位1其余为0为下边界
  514. if ((y & gridYMask[level]) == signMaskY) {
  515. //[下边界4,5,6无效]
  516. aroundMeshIds[4] = NDS_INVALID_ID;
  517. aroundMeshIds[5] = NDS_INVALID_ID;
  518. aroundMeshIds[6] = NDS_INVALID_ID;
  519. }
  520. // Y最高位为0其余为1为上边界
  521. else if ((y & gridYMask[level]) == (signMaskY - 1)) {
  522. //[上边界0,1,2无效]
  523. aroundMeshIds[0] = NDS_INVALID_ID;
  524. aroundMeshIds[1] = NDS_INVALID_ID;
  525. aroundMeshIds[2] = NDS_INVALID_ID;
  526. }
  527. }
  528. assert(aroundMeshIds.size() == 8);
  529. return aroundMeshIds;
  530. }
  531. /**
  532. * @brief /// 给定gridid,获取其周边的8联通瓦片的id
  533. * note : level=0/1不关心
  534. * id顺序如下:
  535. * 0 1 2
  536. * 7 gridid 3
  537. * 6 5 4
  538. *
  539. * @param gridId
  540. * @return std::vector<NdsGridId>
  541. */
  542. std::vector<NdsGridId> get8AroundGridId(NdsGridId gridId)
  543. {
  544. std::tuple<MeshId, std::int32_t> lm = gridId2MeshIdAndLevel(gridId);
  545. MeshId meshId = std::get<0>(lm);
  546. uint level = std::get<1>(lm);
  547. LevelId levelId = getLevelId(level);
  548. cout << "meshid: " << meshId << " level ID: " << levelId << endl;
  549. std::vector<NdsGridId> aroundGridIds;
  550. aroundGridIds.assign(8, NDS_INVALID_ID);
  551. if (gridId != NDS_INVALID_ID && level != 0 && level != 1) {
  552. std::vector<MeshId> meshIds = get8AroundMeshId(meshId, level);
  553. assert(meshIds.size() == 8);
  554. for (size_t i = 0; i < meshIds.size(); i++) {
  555. if (meshIds[i] != NDS_INVALID_ID) {
  556. aroundGridIds[i] = (levelId | meshIds[i]);
  557. }
  558. }
  559. }
  560. assert(aroundGridIds.size() == 8);
  561. return aroundGridIds;
  562. }
  563. } // namespace nds