spatial_extent.py 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656
  1. """!@package grass.temporal
  2. @brief GRASS Python scripting module (temporal GIS functions)
  3. Temporal GIS related spatial extent functions to be used in Python scripts and tgis packages.
  4. Usage:
  5. @code
  6. >>> import grass.temporal as tgis
  7. >>> tgis.init()
  8. >>> extent = tgis.RasterSpatialExtent(
  9. ... ident="raster@PERMANENT", north=90, south=90, east=180, west=180,
  10. ... top=100, bottom=-20)
  11. >>> extent = tgis.Raster3DSpatialExtent(
  12. ... ident="raster3d@PERMANENT", north=90, south=90, east=180, west=180,
  13. ... top=100, bottom=-20)
  14. >>> extent = tgis.VectorSpatialExtent(
  15. ... ident="vector@PERMANENT", north=90, south=90, east=180, west=180,
  16. ... top=100, bottom=-20)
  17. >>> extent = tgis.STRDSSpatialExtent(
  18. ... ident="strds@PERMANENT", north=90, south=90, east=180, west=180,
  19. ... top=100, bottom=-20)
  20. >>> extent = tgis.STR3DSSpatialExtent(
  21. ... ident="str3ds@PERMANENT", north=90, south=90, east=180, west=180,
  22. ... top=100, bottom=-20)
  23. >>> extent = tgis.STVDSSpatialExtent(
  24. ... ident="stvds@PERMANENT", north=90, south=90, east=180, west=180,
  25. ... top=100, bottom=-20)
  26. @endcode
  27. (C) 2008-2011 by the GRASS Development Team
  28. This program is free software under the GNU General Public
  29. License (>=v2). Read the file COPYING that comes with GRASS
  30. for details.
  31. @author Soeren Gebbert
  32. """
  33. from base import *
  34. class SpatialExtent(SQLDatabaseInterface):
  35. """!This is the spatial extent base class for all maps and space time datasets
  36. This class implements a three dimensional axis aligned bounding box
  37. and functions to compute topological relationships
  38. Usage:
  39. @code
  40. >>> init()
  41. >>> extent = SpatialExtent(table="raster_spatial_extent",
  42. ... ident="soil@PERMANENT", north=90, south=90, east=180, west=180,
  43. ... top=100, bottom=-20)
  44. >>> extent.id
  45. 'soil@PERMANENT'
  46. >>> extent.north
  47. 90.0
  48. >>> extent.south
  49. 90.0
  50. >>> extent.east
  51. 180.0
  52. >>> extent.west
  53. 180.0
  54. >>> extent.top
  55. 100.0
  56. >>> extent.bottom
  57. -20.0
  58. >>> extent.print_info()
  59. +-------------------- Spatial extent ----------------------------------------+
  60. | North:...................... 90.0
  61. | South:...................... 90.0
  62. | East:.. .................... 180.0
  63. | West:....................... 180.0
  64. | Top:........................ 100.0
  65. | Bottom:..................... -20.0
  66. >>> extent.print_shell_info()
  67. north=90.0
  68. south=90.0
  69. east=180.0
  70. west=180.0
  71. top=100.0
  72. bottom=-20.0
  73. @endcode
  74. """
  75. def __init__(self, table=None, ident=None, north=None, south=None,
  76. east=None, west=None, top=None, bottom=None, proj="XY"):
  77. SQLDatabaseInterface.__init__(self, table, ident)
  78. self.set_id(ident)
  79. self.set_spatial_extent(north, south, east, west, top, bottom)
  80. self.set_projection(proj)
  81. def overlapping_2d(self, extent):
  82. """!Return True if this (A) and the provided spatial extent (B) overlaps
  83. in two dimensional space.
  84. Code is lend from wind_overlap.c in lib/gis
  85. Overlapping includes the spatial relations:
  86. - contain
  87. - in
  88. - cover
  89. - covered
  90. - equivalent
  91. @code
  92. >>> A = SpatialExtent(north=80, south=20, east=60, west=10)
  93. >>> B = SpatialExtent(north=80, south=20, east=60, west=10)
  94. >>> A.overlapping_2d(B)
  95. True
  96. @endcode
  97. @param extent The spatial extent to check overlapping with
  98. @return True or False
  99. """
  100. if self.get_projection() != extent.get_projection():
  101. core.error(_("Projections are different. Unable to compute "
  102. "overlapping_2d for spatial extents"))
  103. return False
  104. N = extent.get_north()
  105. S = extent.get_south()
  106. E = extent.get_east()
  107. W = extent.get_west()
  108. # Adjust the east and west in case of LL projection
  109. if self.get_projection() == "LL":
  110. while E < self.get_west():
  111. E += 360.0
  112. W += 360.0
  113. while W > self.get_east():
  114. E -= 360.0
  115. W -= 360.0
  116. if(self.get_north() <= S):
  117. return False
  118. if(self.get_south() >= N):
  119. return False
  120. if self.get_east() <= W:
  121. return False
  122. if self.get_west() >= E:
  123. return False
  124. return True
  125. def overlapping(self, extent):
  126. """!Return True if this (A) and the provided spatial
  127. extent (B) overlaps in three dimensional space.
  128. Overlapping includes the spatial relations:
  129. - contain
  130. - in
  131. - cover
  132. - covered
  133. - equivalent
  134. Usage:
  135. @code
  136. >>> A = SpatialExtent(north=80, south=20, east=60, west=10, bottom=-50, top=50)
  137. >>> B = SpatialExtent(north=80, south=20, east=60, west=10, bottom=-50, top=50)
  138. >>> A.overlapping(B)
  139. True
  140. @endcode
  141. @param extent The spatial extent to check overlapping with
  142. @return True or False
  143. """
  144. if not self.overlapping_2d(extent):
  145. return False
  146. T = extent.get_top()
  147. B = extent.get_bottom()
  148. if self.get_top() <= B:
  149. return False
  150. if self.get_bottom() >= T:
  151. return False
  152. return True
  153. def intersect_2d(self, extent):
  154. """!Return the two dimensional intersection as spatial_extent
  155. object or None in case no intersection was found.
  156. @param extent The spatial extent to intersect with
  157. @return The intersection spatial extent
  158. """
  159. if not self.overlapping_2d(extent):
  160. return None
  161. eN = extent.get_north()
  162. eS = extent.get_south()
  163. eE = extent.get_east()
  164. eW = extent.get_west()
  165. N = self.get_north()
  166. S = self.get_south()
  167. E = self.get_east()
  168. W = self.get_west()
  169. # Adjust the east and west in case of LL projection
  170. if self.get_projection() == "LL":
  171. while eE < W:
  172. eE += 360.0
  173. eW += 360.0
  174. while eW > E:
  175. eE -= 360.0
  176. eW -= 360.0
  177. # Compute the extent
  178. nN = N
  179. nS = S
  180. nE = E
  181. nW = W
  182. if W < eW:
  183. nW = eW
  184. if E > eE:
  185. nE = eE
  186. if N > eN:
  187. nN = eN
  188. if S < eS:
  189. nS = eS
  190. new = SpatialExtent(north=nN, south=nS, east=nE, west=nW,
  191. top=0, bottom=0, proj=self.get_projection())
  192. return new
  193. def intersect(self, extent):
  194. """!Return the three dimensional intersection as spatial_extent
  195. object or None in case no intersection was found.
  196. Usage:
  197. @code
  198. >>> A = SpatialExtent(north=80, south=20, east=60, west=10,
  199. ... bottom=-50, top=50)
  200. >>> B = SpatialExtent(north=80, south=20, east=60, west=10,
  201. ... bottom=-50, top=50)
  202. >>> C = A.intersect(B)
  203. >>> C.print_info()
  204. +-------------------- Spatial extent ----------------------------------------+
  205. | North:...................... 80.0
  206. | South:...................... 20.0
  207. | East:.. .................... 60.0
  208. | West:....................... 10.0
  209. | Top:........................ 50.0
  210. | Bottom:..................... -50.0
  211. >>> B = SpatialExtent(north=40, south=30, east=60, west=10,
  212. ... bottom=-50, top=50)
  213. >>> C = A.intersect(B)
  214. >>> C.print_info()
  215. +-------------------- Spatial extent ----------------------------------------+
  216. | North:...................... 40.0
  217. | South:...................... 30.0
  218. | East:.. .................... 60.0
  219. | West:....................... 10.0
  220. | Top:........................ 50.0
  221. | Bottom:..................... -50.0
  222. >>> B = SpatialExtent(north=40, south=30, east=60, west=30,
  223. ... bottom=-50, top=50)
  224. >>> C = A.intersect(B)
  225. >>> C.print_info()
  226. +-------------------- Spatial extent ----------------------------------------+
  227. | North:...................... 40.0
  228. | South:...................... 30.0
  229. | East:.. .................... 60.0
  230. | West:....................... 30.0
  231. | Top:........................ 50.0
  232. | Bottom:..................... -50.0
  233. >>> B = SpatialExtent(north=40, south=30, east=60, west=30,
  234. ... bottom=-30, top=50)
  235. >>> C = A.intersect(B)
  236. >>> C.print_info()
  237. +-------------------- Spatial extent ----------------------------------------+
  238. | North:...................... 40.0
  239. | South:...................... 30.0
  240. | East:.. .................... 60.0
  241. | West:....................... 30.0
  242. | Top:........................ 50.0
  243. | Bottom:..................... -30.0
  244. >>> B = SpatialExtent(north=40, south=30, east=60, west=30,
  245. ... bottom=-30, top=30)
  246. >>> C = A.intersect(B)
  247. >>> C.print_info()
  248. +-------------------- Spatial extent ----------------------------------------+
  249. | North:...................... 40.0
  250. | South:...................... 30.0
  251. | East:.. .................... 60.0
  252. | West:....................... 30.0
  253. | Top:........................ 30.0
  254. | Bottom:..................... -30.0
  255. @endcode
  256. @param extent The spatial extent to intersect with
  257. @return The intersection spatial extent
  258. """
  259. if not self.overlapping(extent):
  260. return None
  261. new = self.intersect_2d(extent)
  262. eT = extent.get_top()
  263. eB = extent.get_bottom()
  264. T = self.get_top()
  265. B = self.get_bottom()
  266. nT = T
  267. nB = B
  268. if B < eB:
  269. nB = eB
  270. if T > eT:
  271. nT = eT
  272. new.set_top(nT)
  273. new.set_bottom(nB)
  274. return new
  275. def is_in_2d(self, extent):
  276. """!Return True if this extent (A) is located in the provided spatial
  277. extent (B) in two dimensions.
  278. @verbatim
  279. _____
  280. |A _ |
  281. | |_| |
  282. |_____|B
  283. @endverbatim
  284. @param extent The spatial extent
  285. @return True or False
  286. """
  287. if self.get_projection() != extent.get_projection():
  288. core.error(_("Projections are different. Unable to compute "
  289. "is_in_2d for spatial extents"))
  290. return False
  291. eN = extent.get_north()
  292. eS = extent.get_south()
  293. eE = extent.get_east()
  294. eW = extent.get_west()
  295. N = self.get_north()
  296. S = self.get_south()
  297. E = self.get_east()
  298. W = self.get_west()
  299. # Adjust the east and west in case of LL projection
  300. if self.get_projection() == "LL":
  301. while eE < W:
  302. eE += 360.0
  303. eW += 360.0
  304. while eW > E:
  305. eE -= 360.0
  306. eW -= 360.0
  307. if W <= eW:
  308. return False
  309. if E >= eE:
  310. return False
  311. if N >= eN:
  312. return False
  313. if S <= eS:
  314. return False
  315. return True
  316. def is_in(self, extent):
  317. """!Return True if this extent (A) is located in the provided spatial
  318. extent (B) in three dimensions.
  319. Usage:
  320. @code
  321. >>> A = SpatialExtent(north=79, south=21, east=59, west=11,
  322. ... bottom=-49, top=49)
  323. >>> B = SpatialExtent(north=80, south=20, east=60, west=10,
  324. ... bottom=-50, top=50)
  325. >>> A.is_in(B)
  326. True
  327. >>> B.is_in(A)
  328. False
  329. @endcode
  330. @param extent The spatial extent
  331. @return True or False
  332. """
  333. if not self.is_in_2d(extent):
  334. return False
  335. eT = extent.get_top()
  336. eB = extent.get_bottom()
  337. T = self.get_top()
  338. B = self.get_bottom()
  339. if B <= eB:
  340. return False
  341. if T >= eT:
  342. return False
  343. return True
  344. def contain_2d(self, extent):
  345. """!Return True if this extent (A) contains the provided spatial
  346. extent (B) in two dimensions.
  347. Usage:
  348. @code
  349. >>> A = SpatialExtent(north=80, south=20, east=60, west=10)
  350. >>> B = SpatialExtent(north=79, south=21, east=59, west=11)
  351. >>> A.contain_2d(B)
  352. True
  353. >>> B.contain_2d(A)
  354. False
  355. @endcode
  356. @param extent The spatial extent
  357. @return True or False
  358. """
  359. return extent.is_in_2d(self)
  360. def contain(self, extent):
  361. """!Return True if this extent (A) contains the provided spatial
  362. extent (B) in three dimensions.
  363. Usage:
  364. @code
  365. >>> A = SpatialExtent(north=80, south=20, east=60, west=10,
  366. ... bottom=-50, top=50)
  367. >>> B = SpatialExtent(north=79, south=21, east=59, west=11,
  368. ... bottom=-49, top=49)
  369. >>> A.contain(B)
  370. True
  371. >>> B.contain(A)
  372. False
  373. @endcode
  374. @param extent The spatial extent
  375. @return True or False
  376. """
  377. return extent.is_in(self)
  378. def equivalent_2d(self, extent):
  379. """!Return True if this extent (A) is equal to the provided spatial
  380. extent (B) in two dimensions.
  381. Usage:
  382. @code
  383. >>> A = SpatialExtent(north=80, south=20, east=60, west=10)
  384. >>> B = SpatialExtent(north=80, south=20, east=60, west=10)
  385. >>> A.equivalent_2d(B)
  386. True
  387. >>> B.equivalent_2d(A)
  388. True
  389. @endcode
  390. @param extent The spatial extent
  391. @return True or False
  392. """
  393. if self.get_projection() != extent.get_projection():
  394. core.error(_("Projections are different. Unable to compute "
  395. "equivalent_2d for spatial extents"))
  396. return False
  397. eN = extent.get_north()
  398. eS = extent.get_south()
  399. eE = extent.get_east()
  400. eW = extent.get_west()
  401. N = self.get_north()
  402. S = self.get_south()
  403. E = self.get_east()
  404. W = self.get_west()
  405. # Adjust the east and west in case of LL projection
  406. if self.get_projection() == "LL":
  407. while eE < W:
  408. eE += 360.0
  409. eW += 360.0
  410. while eW > E:
  411. eE -= 360.0
  412. eW -= 360.0
  413. if W != eW:
  414. return False
  415. if E != eE:
  416. return False
  417. if N != eN:
  418. return False
  419. if S != eS:
  420. return False
  421. return True
  422. def equivalent(self, extent):
  423. """!Return True if this extent (A) is equal to the provided spatial
  424. extent (B) in three dimensions.
  425. Usage:
  426. @code
  427. >>> A = SpatialExtent(north=80, south=20, east=60, west=10,
  428. ... bottom=-50, top=50)
  429. >>> B = SpatialExtent(north=80, south=20, east=60, west=10,
  430. ... bottom=-50, top=50)
  431. >>> A.equivalent(B)
  432. True
  433. >>> B.equivalent(A)
  434. True
  435. @endcode
  436. @param extent The spatial extent
  437. @return True or False
  438. """
  439. if not self.equivalent_2d(extent):
  440. return False
  441. eT = extent.get_top()
  442. eB = extent.get_bottom()
  443. T = self.get_top()
  444. B = self.get_bottom()
  445. if B != eB:
  446. return False
  447. if T != eT:
  448. return False
  449. return True
  450. def cover_2d(self, extent):
  451. """!Return True if this extent (A) covers the provided spatial
  452. extent (B) in two dimensions.
  453. @verbatim
  454. _____ _____ _____ _____
  455. |A __| |__ A| |A | B| |B | A|
  456. | |B | | B| | | |__| |__| |
  457. |__|__| |__|__| |_____| |_____|
  458. _____ _____ _____ _____
  459. |A|B| | |A __| |A _ | |__ A|
  460. | |_| | | |__|B | |B| | B|__| |
  461. |_____| |_____| |_|_|_| |_____|
  462. _____ _____ _____ _____
  463. |A|B | |_____|A |A|B|A| |_____|A
  464. | | | |B | | | | | |_____|B
  465. |_|___| |_____| |_|_|_| |_____|A
  466. @endverbatim
  467. The following cases are excluded:
  468. - contain
  469. - in
  470. - equivalent
  471. @param extent The spatial extent
  472. @return True or False
  473. """
  474. if self.get_projection() != extent.get_projection():
  475. core.error(_("Projections are different. Unable to compute cover_2d for spatial extents"))
  476. return False
  477. # Exclude equivalent_2d
  478. if self.equivalent_2d(extent):
  479. return False
  480. eN = extent.get_north()
  481. eS = extent.get_south()
  482. eE = extent.get_east()
  483. eW = extent.get_west()
  484. N = self.get_north()
  485. S = self.get_south()
  486. E = self.get_east()
  487. W = self.get_west()
  488. # Adjust the east and west in case of LL projection
  489. if self.get_projection() == "LL":
  490. while eE < W:
  491. eE += 360.0
  492. eW += 360.0
  493. while eW > E:
  494. eE -= 360.0
  495. eW -= 360.0
  496. # Edges of extent located outside of self are not allowed
  497. if E <= eW:
  498. return False
  499. if W >= eE:
  500. return False
  501. if N <= eS:
  502. return False
  503. if S >= eN:
  504. return False
  505. # First we check that at least one edge of extent meets an edge of self
  506. if W != eW and E != eE and N != eN and S != eS:
  507. return False
  508. # We check that at least one edge of extent is located in self
  509. edge_count = 0
  510. if W < eW and E > eW:
  511. edge_count += 1
  512. if E > eE and W < eE:
  513. edge_count += 1
  514. if N > eN and S < eN:
  515. edge_count += 1
  516. if S < eS and N > eS:
  517. edge_count += 1
  518. if edge_count == 0:
  519. return False
  520. return True
  521. def cover(self, extent):
  522. """!Return True if this extent covers the provided spatial
  523. extent in three dimensions.
  524. The following cases are excluded:
  525. - contain
  526. - in
  527. - equivalent
  528. @param extent The spatial extent
  529. @return True or False
  530. """
  531. if self.get_projection() != extent.get_projection():
  532. core.error(_("Projections are different. Unable to compute "
  533. "cover for spatial extents"))
  534. return False
  535. # Exclude equivalent_2d
  536. if self.equivalent_2d(extent):
  537. return False
  538. eN = extent.get_north()
  539. eS = extent.get_south()
  540. eE = extent.get_east()
  541. eW = extent.get_west()
  542. eT = extent.get_top()
  543. eB = extent.get_bottom()
  544. N = self.get_north()
  545. S = self.get_south()
  546. E = self.get_east()
  547. W = self.get_west()
  548. T = self.get_top()
  549. B = self.get_bottom()
  550. # Adjust the east and west in case of LL projection
  551. if self.get_projection() == "LL":
  552. while eE < W:
  553. eE += 360.0
  554. eW += 360.0
  555. while eW > E:
  556. eE -= 360.0
  557. eW -= 360.0
  558. # Edges of extent located outside of self are not allowed
  559. if E <= eW:
  560. return False
  561. if W >= eE:
  562. return False
  563. if N <= eS:
  564. return False
  565. if S >= eN:
  566. return False
  567. if T <= eB:
  568. return False
  569. if B >= eT:
  570. return False
  571. # First we check that at least one edge of extent meets an edge of self
  572. if W != eW and E != eE and N != eN and S != eS and B != eB and T != eT:
  573. return False
  574. # We check that at least one edge of extent is located in self
  575. edge_count = 0
  576. if W < eW and E > eW:
  577. edge_count += 1
  578. if E > eE and W < eE:
  579. edge_count += 1
  580. if N > eN and S < eN:
  581. edge_count += 1
  582. if S < eS and N > eS:
  583. edge_count += 1
  584. if N > eN and S < eN:
  585. edge_count += 1
  586. if S < eS and N > eS:
  587. edge_count += 1
  588. if T > eT and B < eT:
  589. edge_count += 1
  590. if B < eB and T > eB:
  591. edge_count += 1
  592. if edge_count == 0:
  593. return False
  594. return True
  595. def covered_2d(self, extent):
  596. """!Return True if this extent is covered by the provided spatial
  597. extent in two dimensions.
  598. The following cases are excluded:
  599. - contain
  600. - in
  601. - equivalent
  602. @param extent The spatial extent
  603. @return True or False
  604. """
  605. return extent.cover_2d(self)
  606. def covered(self, extent):
  607. """!Return True if this extent is covered by the provided spatial
  608. extent in three dimensions.
  609. The following cases are excluded:
  610. - contain
  611. - in
  612. - equivalent
  613. @param extent The spatial extent
  614. @return True or False
  615. """
  616. return extent.cover(self)
  617. def overlap_2d(self, extent):
  618. """!Return True if this extent (A) overlaps with the provided spatial
  619. extent (B) in two dimensions.
  620. Code is lend from wind_overlap.c in lib/gis
  621. @verbatim
  622. _____
  623. |A __|__
  624. | | | B|
  625. |__|__| |
  626. |_____|
  627. @endverbatim
  628. The following cases are excluded:
  629. - contain
  630. - in
  631. - cover
  632. - covered
  633. - equivalent
  634. @param extent The spatial extent
  635. @return True or False
  636. """
  637. if self.contain_2d(extent):
  638. return False
  639. if self.is_in_2d(extent):
  640. return False
  641. if self.cover_2d(extent):
  642. return False
  643. if self.covered_2d(extent):
  644. return False
  645. if self.equivalent_2d(extent):
  646. return False
  647. N = extent.get_north()
  648. S = extent.get_south()
  649. E = extent.get_east()
  650. W = extent.get_west()
  651. # Adjust the east and west in case of LL projection
  652. if self.get_projection() == "LL":
  653. while E < self.get_west():
  654. E += 360.0
  655. W += 360.0
  656. while W > self.get_east():
  657. E -= 360.0
  658. W -= 360.0
  659. if(self.get_north() <= S):
  660. return False
  661. if(self.get_south() >= N):
  662. return False
  663. if self.get_east() <= W:
  664. return False
  665. if self.get_west() >= E:
  666. return False
  667. return True
  668. def overlap(self, extent):
  669. """!Return True if this extent overlaps with the provided spatial
  670. extent in three dimensions.
  671. The following cases are excluded:
  672. - contain
  673. - in
  674. - cover
  675. - covered
  676. - equivalent
  677. @param extent The spatial extent
  678. @return True or False
  679. """
  680. if self.is_in(extent):
  681. return False
  682. if self.contain(extent):
  683. return False
  684. if self.cover(extent):
  685. return False
  686. if self.covered(extent):
  687. return False
  688. if self.equivalent(extent):
  689. return False
  690. N = extent.get_north()
  691. S = extent.get_south()
  692. E = extent.get_east()
  693. W = extent.get_west()
  694. T = extent.get_top()
  695. B = extent.get_bottom()
  696. # Adjust the east and west in case of LL projection
  697. if self.get_projection() == "LL":
  698. while E < self.get_west():
  699. E += 360.0
  700. W += 360.0
  701. while W > self.get_east():
  702. E -= 360.0
  703. W -= 360.0
  704. if(self.get_north() <= S):
  705. return False
  706. if(self.get_south() >= N):
  707. return False
  708. if self.get_east() <= W:
  709. return False
  710. if self.get_west() >= E:
  711. return False
  712. if self.get_top() <= B:
  713. return False
  714. if self.get_bottom() >= T:
  715. return False
  716. return True
  717. def meet_2d(self, extent):
  718. """!Return True if this extent (A) meets with the provided spatial
  719. extent (B) in two dimensions.
  720. @verbatim
  721. _____ _____
  722. | A | B |
  723. |_____| |
  724. |_____|
  725. _____ _____
  726. | B | A |
  727. | | |
  728. |_____|_____|
  729. ___
  730. | A |
  731. | |
  732. |___|
  733. | B |
  734. | |
  735. |_____|
  736. _____
  737. | B |
  738. | |
  739. |_____|_
  740. | A |
  741. | |
  742. |_____|
  743. @endverbatim
  744. @param extent The spatial extent
  745. @return True or False
  746. """
  747. eN = extent.get_north()
  748. eS = extent.get_south()
  749. eE = extent.get_east()
  750. eW = extent.get_west()
  751. eT = extent.get_top()
  752. eB = extent.get_bottom()
  753. N = self.get_north()
  754. S = self.get_south()
  755. E = self.get_east()
  756. W = self.get_west()
  757. # Adjust the east and west in case of LL projection
  758. if self.get_projection() == "LL":
  759. while eE < W:
  760. eE += 360.0
  761. eW += 360.0
  762. while eW > E:
  763. eE -= 360.0
  764. eW -= 360.0
  765. edge = None
  766. edge_count = 0
  767. if E == eW:
  768. edge = "E"
  769. edge_count += 1
  770. if W == eE:
  771. edge = "W"
  772. edge_count += 1
  773. if N == eS:
  774. edge = "N"
  775. edge_count += 1
  776. if S == eN:
  777. edge = "S"
  778. edge_count += 1
  779. # Meet a a single edge only
  780. if edge_count != 1:
  781. return False
  782. # Check boundaries of the faces
  783. if edge == "E" or edge == "W":
  784. if N < eS or S > eN:
  785. return False
  786. if edge == "N" or edge == "S":
  787. if E < eW or W > eE:
  788. return False
  789. return True
  790. def meet(self, extent):
  791. """!Return True if this extent meets with the provided spatial
  792. extent in three dimensions.
  793. @param extent The spatial extent
  794. @return True or False
  795. """
  796. eN = extent.get_north()
  797. eS = extent.get_south()
  798. eE = extent.get_east()
  799. eW = extent.get_west()
  800. eT = extent.get_top()
  801. eB = extent.get_bottom()
  802. N = self.get_north()
  803. S = self.get_south()
  804. E = self.get_east()
  805. W = self.get_west()
  806. T = self.get_top()
  807. B = self.get_bottom()
  808. # Adjust the east and west in case of LL projection
  809. if self.get_projection() == "LL":
  810. while eE < W:
  811. eE += 360.0
  812. eW += 360.0
  813. while eW > E:
  814. eE -= 360.0
  815. eW -= 360.0
  816. edge = None
  817. edge_count = 0
  818. if E == eW:
  819. edge = "E"
  820. edge_count += 1
  821. if W == eE:
  822. edge = "W"
  823. edge_count += 1
  824. if N == eS:
  825. edge = "N"
  826. edge_count += 1
  827. if S == eN:
  828. edge = "S"
  829. edge_count += 1
  830. if T == eB:
  831. edge = "T"
  832. edge_count += 1
  833. if B == eT:
  834. edge = "B"
  835. edge_count += 1
  836. # Meet a single edge only
  837. if edge_count != 1:
  838. return False
  839. # Check boundaries of the faces
  840. if edge == "E" or edge == "W":
  841. if N < eS or S > eN:
  842. return False
  843. if T < eB or B > eT:
  844. return False
  845. if edge == "N" or edge == "S":
  846. if E < eW or W > eE:
  847. return False
  848. if T < eB or B > eT:
  849. return False
  850. if edge == "T" or edge == "B":
  851. if E < eW or W > eE:
  852. return False
  853. if N < eS or S > eN:
  854. return False
  855. return True
  856. def disjoint_2d(self, extent):
  857. """!Return True if this extent (A) is disjoint with the provided spatial
  858. extent (B) in three dimensions.
  859. @verbatim
  860. _____
  861. | A |
  862. |_____|
  863. _______
  864. | B |
  865. |_______|
  866. @endverbatim
  867. @param extent The spatial extent
  868. @return True or False
  869. """
  870. if self.is_in_2d(extent):
  871. return False
  872. if self.contain_2d(extent):
  873. return False
  874. if self.cover_2d(extent):
  875. return False
  876. if self.covered_2d(extent):
  877. return False
  878. if self.equivalent_2d(extent):
  879. return False
  880. if self.overlapping_2d(extent):
  881. return False
  882. if self.meet_2d(extent):
  883. return False
  884. return True
  885. def disjoint(self, extent):
  886. """!Return True if this extent is disjoint with the provided spatial
  887. extent in three dimensions.
  888. @param extent The spatial extent
  889. @return True or False
  890. """
  891. if self.is_in(extent):
  892. return False
  893. if self.contain(extent):
  894. return False
  895. if self.cover(extent):
  896. return False
  897. if self.covered(extent):
  898. return False
  899. if self.equivalent(extent):
  900. return False
  901. if self.overlapping(extent):
  902. return False
  903. if self.meet(extent):
  904. return False
  905. return True
  906. def spatial_relation_2d(self, extent):
  907. """!Returns the two dimensional spatial relation between this
  908. extent and the provided spatial extent in two dimensions.
  909. Spatial relations are:
  910. - disjoint
  911. - meet
  912. - overlap
  913. - cover
  914. - covered
  915. - in
  916. - contain
  917. - equivalent
  918. Usage: see self.spatial_relation()
  919. """
  920. if self.equivalent_2d(extent):
  921. return "equivalent"
  922. if self.contain_2d(extent):
  923. return "contain"
  924. if self.is_in_2d(extent):
  925. return "in"
  926. if self.cover_2d(extent):
  927. return "cover"
  928. if self.covered_2d(extent):
  929. return "covered"
  930. if self.overlap_2d(extent):
  931. return "overlap"
  932. if self.meet_2d(extent):
  933. return "meet"
  934. if self.disjoint_2d(extent):
  935. return "disjoint"
  936. return "unknown"
  937. def spatial_relation(self, extent):
  938. """!Returns the two dimensional spatial relation between this
  939. extent and the provided spatial extent in three dimensions.
  940. Spatial relations are:
  941. - disjoint
  942. - meet
  943. - overlap
  944. - cover
  945. - covered
  946. - in
  947. - contain
  948. - equivalent
  949. Usage:
  950. @code
  951. >>> A = SpatialExtent(north=80, south=20, east=60, west=10, bottom=-50, top=50)
  952. >>> B = SpatialExtent(north=80, south=20, east=60, west=10, bottom=-50, top=50)
  953. >>> A.spatial_relation(B)
  954. 'equivalent'
  955. >>> B.spatial_relation(A)
  956. 'equivalent'
  957. >>> B = SpatialExtent(north=70, south=20, east=60, west=10, bottom=-50, top=50)
  958. >>> A.spatial_relation_2d(B)
  959. 'cover'
  960. >>> A.spatial_relation(B)
  961. 'cover'
  962. >>> B = SpatialExtent(north=70, south=30, east=60, west=10, bottom=-50, top=50)
  963. >>> A.spatial_relation_2d(B)
  964. 'cover'
  965. >>> A.spatial_relation(B)
  966. 'cover'
  967. >>> B.spatial_relation_2d(A)
  968. 'covered'
  969. >>> B.spatial_relation(A)
  970. 'covered'
  971. >>> B = SpatialExtent(north=70, south=30, east=50, west=10, bottom=-50, top=50)
  972. >>> A.spatial_relation_2d(B)
  973. 'cover'
  974. >>> B.spatial_relation_2d(A)
  975. 'covered'
  976. >>> A.spatial_relation(B)
  977. 'cover'
  978. >>> B = SpatialExtent(north=70, south=30, east=50, west=20, bottom=-50, top=50)
  979. >>> B.spatial_relation(A)
  980. 'covered'
  981. >>> B = SpatialExtent(north=70, south=30, east=50, west=20, bottom=-50, top=50)
  982. >>> A.spatial_relation_2d(B)
  983. 'contain'
  984. >>> A.spatial_relation(B)
  985. 'cover'
  986. >>> B = SpatialExtent(north=70, south=30, east=50, west=20, bottom=-40, top=50)
  987. >>> A.spatial_relation(B)
  988. 'cover'
  989. >>> B = SpatialExtent(north=70, south=30, east=50, west=20, bottom=-40, top=40)
  990. >>> A.spatial_relation(B)
  991. 'contain'
  992. >>> B.spatial_relation(A)
  993. 'in'
  994. >>> B = SpatialExtent(north=90, south=30, east=50, west=20, bottom=-40, top=40)
  995. >>> A.spatial_relation_2d(B)
  996. 'overlap'
  997. >>> A.spatial_relation(B)
  998. 'overlap'
  999. >>> B = SpatialExtent(north=90, south=5, east=70, west=5, bottom=-40, top=40)
  1000. >>> A.spatial_relation_2d(B)
  1001. 'in'
  1002. >>> A.spatial_relation(B)
  1003. 'overlap'
  1004. >>> B = SpatialExtent(north=90, south=5, east=70, west=5, bottom=-40, top=60)
  1005. >>> A.spatial_relation(B)
  1006. 'overlap'
  1007. >>> B = SpatialExtent(north=90, south=5, east=70, west=5, bottom=-60, top=60)
  1008. >>> A.spatial_relation(B)
  1009. 'in'
  1010. >>> A = SpatialExtent(north=80, south=60, east=60, west=10, bottom=-50, top=50)
  1011. >>> B = SpatialExtent(north=60, south=20, east=60, west=10, bottom=-50, top=50)
  1012. >>> A.spatial_relation_2d(B)
  1013. 'meet'
  1014. >>> A.spatial_relation(B)
  1015. 'meet'
  1016. >>> A = SpatialExtent(north=60, south=40, east=60, west=10, bottom=-50, top=50)
  1017. >>> B = SpatialExtent(north=80, south=60, east=60, west=10, bottom=-50, top=50)
  1018. >>> A.spatial_relation_2d(B)
  1019. 'meet'
  1020. >>> A.spatial_relation(B)
  1021. 'meet'
  1022. >>> A = SpatialExtent(north=80, south=40, east=60, west=40, bottom=-50, top=50)
  1023. >>> B = SpatialExtent(north=80, south=40, east=40, west=20, bottom=-50, top=50)
  1024. >>> A.spatial_relation_2d(B)
  1025. 'meet'
  1026. >>> A.spatial_relation(B)
  1027. 'meet'
  1028. >>> A = SpatialExtent(north=80, south=40, east=40, west=20, bottom=-50, top=50)
  1029. >>> B = SpatialExtent(north=90, south=30, east=60, west=40, bottom=-50, top=50)
  1030. >>> A.spatial_relation_2d(B)
  1031. 'meet'
  1032. >>> A.spatial_relation(B)
  1033. 'meet'
  1034. >>> A = SpatialExtent(north=80, south=40, east=40, west=20, bottom=-50, top=50)
  1035. >>> B = SpatialExtent(north=70, south=50, east=60, west=40, bottom=-50, top=50)
  1036. >>> A.spatial_relation_2d(B)
  1037. 'meet'
  1038. >>> A.spatial_relation(B)
  1039. 'meet'
  1040. >>> A = SpatialExtent(north=80, south=40, east=40, west=20, bottom=-50, top=50)
  1041. >>> B = SpatialExtent(north=60, south=20, east=60, west=40, bottom=-50, top=50)
  1042. >>> A.spatial_relation_2d(B)
  1043. 'meet'
  1044. >>> A.spatial_relation(B)
  1045. 'meet'
  1046. >>> A = SpatialExtent(north=80, south=40, east=40, west=20, bottom=-50, top=50)
  1047. >>> B = SpatialExtent(north=40, south=20, east=60, west=40, bottom=-50, top=50)
  1048. >>> A.spatial_relation_2d(B)
  1049. 'disjoint'
  1050. >>> A.spatial_relation(B)
  1051. 'disjoint'
  1052. >>> A = SpatialExtent(north=80, south=40, east=40, west=20, bottom=-50, top=50)
  1053. >>> B = SpatialExtent(north=60, south=20, east=60, west=40, bottom=-60, top=60)
  1054. >>> A.spatial_relation(B)
  1055. 'meet'
  1056. >>> A = SpatialExtent(north=80, south=40, east=40, west=20, bottom=-50, top=50)
  1057. >>> B = SpatialExtent(north=90, south=30, east=60, west=40, bottom=-40, top=40)
  1058. >>> A.spatial_relation(B)
  1059. 'meet'
  1060. >>> A = SpatialExtent(north=80, south=40, east=60, west=20, bottom=0, top=50)
  1061. >>> B = SpatialExtent(north=80, south=40, east=60, west=20, bottom=-50, top=0)
  1062. >>> A.spatial_relation(B)
  1063. 'meet'
  1064. >>> A = SpatialExtent(north=80, south=40, east=60, west=20, bottom=0, top=50)
  1065. >>> B = SpatialExtent(north=80, south=50, east=60, west=30, bottom=-50, top=0)
  1066. >>> A.spatial_relation(B)
  1067. 'meet'
  1068. >>> A = SpatialExtent(north=80, south=40, east=60, west=20, bottom=0, top=50)
  1069. >>> B = SpatialExtent(north=70, south=50, east=50, west=30, bottom=-50, top=0)
  1070. >>> A.spatial_relation(B)
  1071. 'meet'
  1072. >>> A = SpatialExtent(north=80, south=40, east=60, west=20, bottom=0, top=50)
  1073. >>> B = SpatialExtent(north=90, south=30, east=70, west=10, bottom=-50, top=0)
  1074. >>> A.spatial_relation(B)
  1075. 'meet'
  1076. >>> A = SpatialExtent(north=80, south=40, east=60, west=20, bottom=0, top=50)
  1077. >>> B = SpatialExtent(north=70, south=30, east=50, west=10, bottom=-50, top=0)
  1078. >>> A.spatial_relation(B)
  1079. 'meet'
  1080. >>> A = SpatialExtent(north=80, south=40, east=60, west=20, bottom=-50, top=0)
  1081. >>> B = SpatialExtent(north=80, south=40, east=60, west=20, bottom=0, top=50)
  1082. >>> A.spatial_relation(B)
  1083. 'meet'
  1084. >>> A = SpatialExtent(north=80, south=40, east=60, west=20, bottom=-50, top=0)
  1085. >>> B = SpatialExtent(north=80, south=50, east=60, west=30, bottom=0, top=50)
  1086. >>> A.spatial_relation(B)
  1087. 'meet'
  1088. >>> A = SpatialExtent(north=80, south=40, east=60, west=20, bottom=-50, top=0)
  1089. >>> B = SpatialExtent(north=70, south=50, east=50, west=30, bottom=0, top=50)
  1090. >>> A.spatial_relation(B)
  1091. 'meet'
  1092. >>> A = SpatialExtent(north=80, south=40, east=60, west=20, bottom=-50, top=0)
  1093. >>> B = SpatialExtent(north=90, south=30, east=70, west=10, bottom=0, top=50)
  1094. >>> A.spatial_relation(B)
  1095. 'meet'
  1096. >>> A = SpatialExtent(north=80, south=40, east=60, west=20, bottom=-50, top=0)
  1097. >>> B = SpatialExtent(north=70, south=30, east=50, west=10, bottom=0, top=50)
  1098. >>> A.spatial_relation(B)
  1099. 'meet'
  1100. >>> A = SpatialExtent(north=80, south=20, east=60, west=10, bottom=-50, top=50)
  1101. >>> B = SpatialExtent(north=90, south=81, east=60, west=10, bottom=-50, top=50)
  1102. >>> A.spatial_relation(B)
  1103. 'disjoint'
  1104. >>> A = SpatialExtent(north=80, south=20, east=60, west=10, bottom=-50, top=50)
  1105. >>> B = SpatialExtent(north=90, south=80, east=60, west=10, bottom=-50, top=50)
  1106. >>> A.spatial_relation(B)
  1107. 'meet'
  1108. @endcode
  1109. """
  1110. if self.equivalent(extent):
  1111. return "equivalent"
  1112. if self.contain(extent):
  1113. return "contain"
  1114. if self.is_in(extent):
  1115. return "in"
  1116. if self.cover(extent):
  1117. return "cover"
  1118. if self.covered(extent):
  1119. return "covered"
  1120. if self.overlap(extent):
  1121. return "overlap"
  1122. if self.meet(extent):
  1123. return "meet"
  1124. if self.disjoint(extent):
  1125. return "disjoint"
  1126. return "unknown"
  1127. def set_spatial_extent(self, north, south, east, west, top, bottom):
  1128. """!Set the three dimensional spatial extent"""
  1129. self.set_north(north)
  1130. self.set_south(south)
  1131. self.set_east(east)
  1132. self.set_west(west)
  1133. self.set_top(top)
  1134. self.set_bottom(bottom)
  1135. def set_projection(self, proj):
  1136. """!Set the projection of the spatial extent it should be XY or LL.
  1137. As default the projection is XY
  1138. """
  1139. if proj is None or (proj != "XY" and proj != "LL"):
  1140. self.D["proj"] = "XY"
  1141. else:
  1142. self.D["proj"] = proj
  1143. def set_spatial_extent_2d(self, north, south, east, west):
  1144. """!Set the two dimensional spatial extent"""
  1145. self.set_north(north)
  1146. self.set_south(south)
  1147. self.set_east(east)
  1148. self.set_west(west)
  1149. def set_id(self, ident):
  1150. """!Convenient method to set the unique identifier (primary key)"""
  1151. self.ident = ident
  1152. self.D["id"] = ident
  1153. def set_north(self, north):
  1154. """!Set the northern edge of the map"""
  1155. if north is not None:
  1156. self.D["north"] = float(north)
  1157. else:
  1158. self.D["north"] = None
  1159. def set_south(self, south):
  1160. """!Set the southern edge of the map"""
  1161. if south is not None:
  1162. self.D["south"] = float(south)
  1163. else:
  1164. self.D["south"] = None
  1165. def set_west(self, west):
  1166. """!Set the western edge of the map"""
  1167. if west is not None:
  1168. self.D["west"] = float(west)
  1169. else:
  1170. self.D["west"] = None
  1171. def set_east(self, east):
  1172. """!Set the eastern edge of the map"""
  1173. if east is not None:
  1174. self.D["east"] = float(east)
  1175. else:
  1176. self.D["east"] = None
  1177. def set_top(self, top):
  1178. """!Set the top edge of the map"""
  1179. if top is not None:
  1180. self.D["top"] = float(top)
  1181. else:
  1182. self.D["top"] = None
  1183. def set_bottom(self, bottom):
  1184. """!Set the bottom edge of the map"""
  1185. if bottom is not None:
  1186. self.D["bottom"] = float(bottom)
  1187. else:
  1188. self.D["bottom"] = None
  1189. def get_id(self):
  1190. """!Convenient method to get the unique identifier (primary key)
  1191. @return None if not found
  1192. """
  1193. if "id" in self.D:
  1194. return self.D["id"]
  1195. else:
  1196. return None
  1197. def get_projection(self):
  1198. """!Get the projection of the spatial extent"""
  1199. return self.D["proj"]
  1200. def get_volume(self):
  1201. """!Compute the volume of the extent, in case z is zero
  1202. (top == bottom or top - bottom = 1) the area is returned"""
  1203. if self.get_projection() == "LL":
  1204. core.error(_("Volume computation is not supported "
  1205. "for LL projections"))
  1206. area = self.get_area()
  1207. bbox = self.get_spatial_extent()
  1208. z = abs(bbox[4] - bbox[5])
  1209. if z == 0:
  1210. z = 1.0
  1211. return area * z
  1212. def get_area(self):
  1213. """!Compute the area of the extent, extent in z direction is ignored"""
  1214. if self.get_projection() == "LL":
  1215. core.error(_("Area computation is not supported "
  1216. "for LL projections"))
  1217. bbox = self.get_spatial_extent()
  1218. y = abs(bbox[0] - bbox[1])
  1219. x = abs(bbox[2] - bbox[3])
  1220. return x * y
  1221. def get_spatial_extent(self):
  1222. """!Return a tuple (north, south, east, west, top, bottom)
  1223. of the spatial extent"""
  1224. return (
  1225. self.north, self.south, self.east, self.west,
  1226. self.top, self.bottom)
  1227. def get_spatial_extent_2d(self):
  1228. """!Return a tuple (north, south, east, west,) of the 2d spatial extent
  1229. """
  1230. return (self.north, self.south, self.east, self.west)
  1231. def get_north(self):
  1232. """!Get the northern edge of the map
  1233. @return None if not found"""
  1234. if "north" in self.D:
  1235. return self.D["north"]
  1236. else:
  1237. return None
  1238. def get_south(self):
  1239. """!Get the southern edge of the map
  1240. @return None if not found"""
  1241. if "south" in self.D:
  1242. return self.D["south"]
  1243. else:
  1244. return None
  1245. def get_east(self):
  1246. """!Get the eastern edge of the map
  1247. @return None if not found"""
  1248. if "east" in self.D:
  1249. return self.D["east"]
  1250. else:
  1251. return None
  1252. def get_west(self):
  1253. """!Get the western edge of the map
  1254. @return None if not found"""
  1255. if "west" in self.D:
  1256. return self.D["west"]
  1257. else:
  1258. return None
  1259. def get_top(self):
  1260. """!Get the top edge of the map
  1261. @return None if not found"""
  1262. if "top" in self.D:
  1263. return self.D["top"]
  1264. else:
  1265. return None
  1266. def get_bottom(self):
  1267. """!Get the bottom edge of the map
  1268. @return None if not found"""
  1269. if "bottom" in self.D:
  1270. return self.D["bottom"]
  1271. else:
  1272. return None
  1273. id = property(fget=get_id, fset=set_id)
  1274. north = property(fget=get_north, fset=set_north)
  1275. south = property(fget=get_south, fset=set_south)
  1276. east = property(fget=get_east, fset=set_east)
  1277. west = property(fget=get_west, fset=set_west)
  1278. top = property(fget=get_top, fset=set_top)
  1279. bottom= property(fget=get_bottom, fset=set_bottom)
  1280. def print_info(self):
  1281. """!Print information about this class in human readable style"""
  1282. # 0123456789012345678901234567890
  1283. print " +-------------------- Spatial extent ----------------------------------------+"
  1284. print " | North:...................... " + str(self.get_north())
  1285. print " | South:...................... " + str(self.get_south())
  1286. print " | East:.. .................... " + str(self.get_east())
  1287. print " | West:....................... " + str(self.get_west())
  1288. print " | Top:........................ " + str(self.get_top())
  1289. print " | Bottom:..................... " + str(self.get_bottom())
  1290. def print_shell_info(self):
  1291. """Print information about this class in shell style"""
  1292. print "north=" + str(self.get_north())
  1293. print "south=" + str(self.get_south())
  1294. print "east=" + str(self.get_east())
  1295. print "west=" + str(self.get_west())
  1296. print "top=" + str(self.get_top())
  1297. print "bottom=" + str(self.get_bottom())
  1298. ###############################################################################
  1299. class RasterSpatialExtent(SpatialExtent):
  1300. def __init__(self, ident=None, north=None, south=None, east=None,
  1301. west=None, top=None, bottom=None):
  1302. SpatialExtent.__init__(self, "raster_spatial_extent",
  1303. ident, north, south, east, west, top, bottom)
  1304. class Raster3DSpatialExtent(SpatialExtent):
  1305. def __init__(self, ident=None, north=None, south=None, east=None,
  1306. west=None, top=None, bottom=None):
  1307. SpatialExtent.__init__(self, "raster3d_spatial_extent",
  1308. ident, north, south, east, west, top, bottom)
  1309. class VectorSpatialExtent(SpatialExtent):
  1310. def __init__(self, ident=None, north=None, south=None, east=None,
  1311. west=None, top=None, bottom=None):
  1312. SpatialExtent.__init__(self, "vector_spatial_extent",
  1313. ident, north, south, east, west, top, bottom)
  1314. class STRDSSpatialExtent(SpatialExtent):
  1315. def __init__(self, ident=None, north=None, south=None, east=None,
  1316. west=None, top=None, bottom=None):
  1317. SpatialExtent.__init__(self, "strds_spatial_extent",
  1318. ident, north, south, east, west, top, bottom)
  1319. class STR3DSSpatialExtent(SpatialExtent):
  1320. def __init__(self, ident=None, north=None, south=None, east=None,
  1321. west=None, top=None, bottom=None):
  1322. SpatialExtent.__init__(self, "str3ds_spatial_extent",
  1323. ident, north, south, east, west, top, bottom)
  1324. class STVDSSpatialExtent(SpatialExtent):
  1325. def __init__(self, ident=None, north=None, south=None, east=None,
  1326. west=None, top=None, bottom=None):
  1327. SpatialExtent.__init__(self, "stvds_spatial_extent",
  1328. ident, north, south, east, west, top, bottom)
  1329. ###############################################################################
  1330. if __name__ == "__main__":
  1331. import doctest
  1332. doctest.testmod()