space_time_datasets.py 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389
  1. """!@package grass.temporal
  2. @brief GRASS Python scripting module (temporal GIS functions)
  3. Temporal GIS related functions to be used in Python scripts.
  4. (C) 2008-2011 by the GRASS Development Team
  5. This program is free software under the GNU General Public
  6. License (>=v2). Read the file COPYING that comes with GRASS
  7. for details.
  8. @author Soeren Gebbert
  9. """
  10. import getpass
  11. from ctypes import *
  12. import grass.lib.gis as libgis
  13. import grass.lib.raster as libraster
  14. import grass.lib.vector as libvector
  15. import grass.lib.raster3d as libraster3d
  16. import grass.script as grass
  17. from abstract_map_dataset import *
  18. from abstract_space_time_dataset import *
  19. ###############################################################################
  20. class RasterDataset(AbstractMapDataset):
  21. """!Raster dataset class
  22. This class provides functions to select, update, insert or delete raster
  23. map information and valid time stamps into the SQL temporal database.
  24. Usage:
  25. @code
  26. >>> import grass.script as grass
  27. >>> init()
  28. >>> grass.use_temp_region()
  29. >>> grass.run_command("g.region", n=80.0, s=0.0, e=120.0, w=0.0,
  30. ... t=1.0, b=0.0, res=10.0)
  31. 0
  32. >>> grass.run_command("r.mapcalc", overwrite=True,
  33. ... expression="strds_map_test_case = 1")
  34. 0
  35. >>> grass.run_command("r.timestamp", map="strds_map_test_case",
  36. ... date="15 jan 1999")
  37. 0
  38. >>> mapset = get_current_mapset()
  39. >>> name = "strds_map_test_case"
  40. >>> identifier = "%s@%s" % (name, mapset)
  41. >>> rmap = RasterDataset(identifier)
  42. >>> rmap.map_exists()
  43. True
  44. >>> rmap.read_timestamp_from_grass()
  45. True
  46. >>> rmap.get_temporal_extent_as_tuple()
  47. (datetime.datetime(1999, 1, 15, 0, 0), None)
  48. >>> rmap.load()
  49. >>> rmap.spatial_extent.print_info()
  50. +-------------------- Spatial extent ----------------------------------------+
  51. | North:...................... 80.0
  52. | South:...................... 0.0
  53. | East:.. .................... 120.0
  54. | West:....................... 0.0
  55. | Top:........................ 0.0
  56. | Bottom:..................... 0.0
  57. >>> rmap.absolute_time.print_info()
  58. +-------------------- Absolute time -----------------------------------------+
  59. | Start time:................. 1999-01-15 00:00:00
  60. | End time:................... None
  61. >>> rmap.metadata.print_info()
  62. +-------------------- Metadata information ----------------------------------+
  63. | Datatype:................... CELL
  64. | Number of columns:.......... 8
  65. | Number of rows:............. 12
  66. | Number of cells:............ 96
  67. | North-South resolution:..... 10.0
  68. | East-west resolution:....... 10.0
  69. | Minimum value:.............. 1.0
  70. | Maximum value:.............. 1.0
  71. | STRDS register table ....... None
  72. >>> newmap = rmap.get_new_instance("new@PERMANENT")
  73. >>> isinstance(newmap, RasterDataset)
  74. True
  75. >>> newstrds = rmap.get_new_stds_instance("new@PERMANENT")
  76. >>> isinstance(newstrds, SpaceTimeRasterDataset)
  77. True
  78. >>> rmap.get_type()
  79. 'raster'
  80. >>> rmap.get_stds_register()
  81. >>> rmap.set_absolute_time(start_time=datetime(2001,1,1),
  82. ... end_time=datetime(2012,1,1))
  83. True
  84. >>> rmap.get_absolute_time()
  85. (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2012, 1, 1, 0, 0), None)
  86. >>> rmap.get_temporal_extent_as_tuple()
  87. (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2012, 1, 1, 0, 0))
  88. >>> rmap.get_name()
  89. 'strds_map_test_case'
  90. >>> rmap.get_mapset() == mapset
  91. True
  92. >>> rmap.get_temporal_type()
  93. 'absolute'
  94. >>> rmap.get_spatial_extent_as_tuple()
  95. (80.0, 0.0, 120.0, 0.0, 0.0, 0.0)
  96. >>> rmap.is_time_absolute()
  97. True
  98. >>> rmap.is_time_relative()
  99. False
  100. >>> grass.run_command("g.remove", rast=name)
  101. 0
  102. >>> grass.del_temp_region()
  103. @endcode
  104. """
  105. def __init__(self, ident):
  106. AbstractMapDataset.__init__(self)
  107. self.reset(ident)
  108. def get_type(self):
  109. return 'raster'
  110. def get_new_instance(self, ident):
  111. """!Return a new instance with the type of this class"""
  112. return RasterDataset(ident)
  113. def get_new_stds_instance(self, ident):
  114. """!Return a new space time dataset instance in which maps
  115. are stored with the type of this class"""
  116. return SpaceTimeRasterDataset(ident)
  117. def get_stds_register(self):
  118. """!Return the space time dataset register table name in which stds
  119. are listed in which this map is registered"""
  120. return self.metadata.get_strds_register()
  121. def set_stds_register(self, name):
  122. """!Set the space time dataset register table name in which stds
  123. are listed in which this map is registered"""
  124. self.metadata.set_strds_register(name)
  125. def spatial_overlapping(self, dataset):
  126. """!Return True if the spatial extents 2d overlap"""
  127. return self.spatial_extent.overlapping_2d(dataset.spatial_extent)
  128. def spatial_relation(self, dataset):
  129. """!Return the two dimensional spatial relation"""
  130. return self.spatial_extent.spatial_relation_2d(dataset.spatial_extent)
  131. def spatial_intersection(self, dataset):
  132. """!Return the two dimensional intersection as spatial_extent
  133. object or None in case no intersection was found.
  134. @param dataset The abstract dataset to intersect with
  135. @return The intersection spatial extent or None
  136. """
  137. return self.spatial_extent.intersect_2d(dataset.spatial_extent)
  138. def spatial_union(self, dataset):
  139. """!Return the two dimensional union as spatial_extent
  140. object or None in case the extents does not overlap or meet.
  141. @param dataset The abstract dataset to create a union with
  142. @return The union spatial extent or None
  143. """
  144. return self.spatial_extent.union_2d(dataset.spatial_extent)
  145. def spatial_disjoint_union(self, dataset):
  146. """!Return the two dimensional union as spatial_extent object.
  147. @param dataset The abstract dataset to create a union with
  148. @return The union spatial extent
  149. """
  150. return self.spatial_extent.disjoint_union_2d(dataset.spatial_extent)
  151. def get_np_array(self):
  152. """!Return this raster map as memmap numpy style array to access the raster
  153. values in numpy style without loading the whole map in the RAM.
  154. In case this raster map does exists in the grass spatial database,
  155. the map will be exported using r.out.bin to a temporary location
  156. and assigned to the memmap object that is returned by this function.
  157. In case the raster map does not exists, an empty temporary
  158. binary file will be created and assigned to the memap object.
  159. You need to call the write function to write the memmap
  160. array back into grass.
  161. """
  162. a = garray.array()
  163. if self.map_exists():
  164. a.read(self.get_map_id())
  165. return a
  166. def reset(self, ident):
  167. """!Reset the internal structure and set the identifier"""
  168. self.base = RasterBase(ident=ident)
  169. self.absolute_time = RasterAbsoluteTime(ident=ident)
  170. self.relative_time = RasterRelativeTime(ident=ident)
  171. self.spatial_extent = RasterSpatialExtent(ident=ident)
  172. self.metadata = RasterMetadata(ident=ident)
  173. def has_grass_timestamp(self):
  174. """!Check if a grass file bsased time stamp exists for this map.
  175. """
  176. if libgis.G_has_raster_timestamp(self.get_name(), self.get_mapset()):
  177. return True
  178. else:
  179. return False
  180. def read_timestamp_from_grass(self):
  181. """!Read the timestamp of this map from the map metadata
  182. in the grass file system based spatial database and
  183. set the internal time stamp that should be insert/updated
  184. in the temporal database.
  185. """
  186. if not self.has_grass_timestamp():
  187. return False
  188. ts = libgis.TimeStamp()
  189. check = libgis.G_read_raster_timestamp(self.get_name(), self.get_mapset(),
  190. byref(ts))
  191. if check < 1:
  192. self.msgr.error(_("Unable to read timestamp file "
  193. "for raster map <%s>" % (self.get_map_id())))
  194. return False
  195. return self._set_timestamp_from_grass(ts)
  196. def write_timestamp_to_grass(self):
  197. """!Write the timestamp of this map into the map metadata in
  198. the grass file system based spatial database.
  199. Internally the libgis API functions are used for writing
  200. """
  201. ts = libgis.TimeStamp()
  202. libgis.G_scan_timestamp(byref(ts), self._convert_timestamp())
  203. check = libgis.G_write_raster_timestamp(self.get_name(), byref(ts))
  204. if check == -1:
  205. self.msgr.error(_("Unable to create timestamp file "
  206. "for raster map <%s>" % (self.get_map_id())))
  207. if check == -2:
  208. self.msgr.error(_("Invalid datetime in timestamp for raster map <%s>" %
  209. (self.get_map_id())))
  210. def remove_timestamp_from_grass(self):
  211. """!Remove the timestamp from the grass file system based
  212. spatial database
  213. Internally the libgis API functions are used for removal
  214. """
  215. check = libgis.G_remove_raster_timestamp(self.get_name())
  216. if check == -1:
  217. core.error(_("Unable to remove timestamp for raster map <%s>" %
  218. (self.get_name())))
  219. def map_exists(self):
  220. """!Return True in case the map exists in the grass spatial database
  221. @return True if map exists, False otherwise
  222. """
  223. mapset = libgis.G_find_raster(self.get_name(), self.get_mapset())
  224. if not mapset:
  225. return False
  226. return True
  227. def read_info(self):
  228. """!Read the raster map info from the file system and store the content
  229. into a dictionary
  230. This method uses the ctypes interface to the gis and raster libraries
  231. to read the map metadata information
  232. """
  233. kvp = {}
  234. name = self.get_name()
  235. mapset = self.get_mapset()
  236. if not self.map_exists():
  237. core.fatal(_("Raster map <%s> not found" % name))
  238. # Read the region information
  239. region = libgis.Cell_head()
  240. libraster.Rast_get_cellhd(name, mapset, byref(region))
  241. kvp["north"] = region.north
  242. kvp["south"] = region.south
  243. kvp["east"] = region.east
  244. kvp["west"] = region.west
  245. kvp["nsres"] = region.ns_res
  246. kvp["ewres"] = region.ew_res
  247. kvp["rows"] = region.cols
  248. kvp["cols"] = region.rows
  249. maptype = libraster.Rast_map_type(name, mapset)
  250. if maptype == libraster.DCELL_TYPE:
  251. kvp["datatype"] = "DCELL"
  252. elif maptype == libraster.FCELL_TYPE:
  253. kvp["datatype"] = "FCELL"
  254. elif maptype == libraster.CELL_TYPE:
  255. kvp["datatype"] = "CELL"
  256. # Read range
  257. if libraster.Rast_map_is_fp(name, mapset):
  258. range = libraster.FPRange()
  259. libraster.Rast_init_fp_range(byref(range))
  260. ret = libraster.Rast_read_fp_range(name, mapset, byref(range))
  261. if ret < 0:
  262. core.fatal(_("Unable to read range file"))
  263. if ret == 2:
  264. kvp["min"] = None
  265. kvp["max"] = None
  266. else:
  267. min = libgis.DCELL()
  268. max = libgis.DCELL()
  269. libraster.Rast_get_fp_range_min_max(
  270. byref(range), byref(min), byref(max))
  271. kvp["min"] = min.value
  272. kvp["max"] = max.value
  273. else:
  274. range = libraster.Range()
  275. libraster.Rast_init_range(byref(range))
  276. ret = libraster.Rast_read_range(name, mapset, byref(range))
  277. if ret < 0:
  278. core.fatal(_("Unable to read range file"))
  279. if ret == 2:
  280. kvp["min"] = None
  281. kvp["max"] = None
  282. else:
  283. min = libgis.CELL()
  284. max = libgis.CELL()
  285. libraster.Rast_get_range_min_max(
  286. byref(range), byref(min), byref(max))
  287. kvp["min"] = min.value
  288. kvp["max"] = max.value
  289. return kvp
  290. def load(self):
  291. """!Load all info from an existing raster map into the internal s
  292. tructure"""
  293. # Fill base information
  294. self.base.set_creator(str(getpass.getuser()))
  295. # Get the data from an existing raster map
  296. if get_use_ctypes_map_access() == True:
  297. kvp = self.read_info()
  298. else:
  299. kvp = grass.raster_info(self.get_id())
  300. # Fill spatial extent
  301. self.set_spatial_extent_from_values(north=kvp["north"], south=kvp["south"],
  302. east=kvp["east"], west=kvp["west"])
  303. # Fill metadata
  304. self.metadata.set_nsres(kvp["nsres"])
  305. self.metadata.set_ewres(kvp["ewres"])
  306. self.metadata.set_datatype(kvp["datatype"])
  307. self.metadata.set_min(kvp["min"])
  308. self.metadata.set_max(kvp["max"])
  309. rows = int(kvp["rows"])
  310. cols = int(kvp["cols"])
  311. ncells = cols * rows
  312. self.metadata.set_cols(cols)
  313. self.metadata.set_rows(rows)
  314. self.metadata.set_number_of_cells(ncells)
  315. ###############################################################################
  316. class Raster3DDataset(AbstractMapDataset):
  317. """!Raster3d dataset class
  318. This class provides functions to select, update, insert or delete raster3d
  319. map information and valid time stamps into the SQL temporal database.
  320. Usage:
  321. @code
  322. >>> import grass.script as grass
  323. >>> init()
  324. >>> grass.use_temp_region()
  325. >>> grass.run_command("g.region", n=80.0, s=0.0, e=120.0, w=0.0,
  326. ... t=100.0, b=0.0, res=10.0)
  327. 0
  328. >>> grass.run_command("r3.mapcalc", overwrite=True,
  329. ... expression="str3ds_map_test_case = 1")
  330. 0
  331. >>> grass.run_command("r3.timestamp", map="str3ds_map_test_case",
  332. ... date="15 jan 1999")
  333. 0
  334. >>> mapset = get_current_mapset()
  335. >>> name = "str3ds_map_test_case"
  336. >>> identifier = "%s@%s" % (name, mapset)
  337. >>> r3map = Raster3DDataset(identifier)
  338. >>> r3map.map_exists()
  339. True
  340. >>> r3map.read_timestamp_from_grass()
  341. True
  342. >>> r3map.get_temporal_extent_as_tuple()
  343. (datetime.datetime(1999, 1, 15, 0, 0), None)
  344. >>> r3map.load()
  345. >>> r3map.spatial_extent.print_info()
  346. +-------------------- Spatial extent ----------------------------------------+
  347. | North:...................... 80.0
  348. | South:...................... 0.0
  349. | East:.. .................... 120.0
  350. | West:....................... 0.0
  351. | Top:........................ 100.0
  352. | Bottom:..................... 0.0
  353. >>> r3map.absolute_time.print_info()
  354. +-------------------- Absolute time -----------------------------------------+
  355. | Start time:................. 1999-01-15 00:00:00
  356. | End time:................... None
  357. >>> r3map.metadata.print_info()
  358. +-------------------- Metadata information ----------------------------------+
  359. | Datatype:................... DCELL
  360. | Number of columns:.......... 8
  361. | Number of rows:............. 12
  362. | Number of cells:............ 960
  363. | North-South resolution:..... 10.0
  364. | East-west resolution:....... 10.0
  365. | Minimum value:.............. 1.0
  366. | Maximum value:.............. 1.0
  367. | Number of depths:........... 10
  368. | Top-Bottom resolution:...... 10.0
  369. | STR3DS register table ...... None
  370. >>> newmap = r3map.get_new_instance("new@PERMANENT")
  371. >>> isinstance(newmap, Raster3DDataset)
  372. True
  373. >>> newstr3ds = r3map.get_new_stds_instance("new@PERMANENT")
  374. >>> isinstance(newstr3ds, SpaceTimeRaster3DDataset)
  375. True
  376. >>> r3map.get_type()
  377. 'raster3d'
  378. >>> r3map.get_stds_register()
  379. >>> r3map.set_absolute_time(start_time=datetime(2001,1,1),
  380. ... end_time=datetime(2012,1,1))
  381. True
  382. >>> r3map.get_absolute_time()
  383. (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2012, 1, 1, 0, 0), None)
  384. >>> r3map.get_temporal_extent_as_tuple()
  385. (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2012, 1, 1, 0, 0))
  386. >>> r3map.get_name()
  387. 'str3ds_map_test_case'
  388. >>> r3map.get_mapset() == mapset
  389. True
  390. >>> r3map.get_temporal_type()
  391. 'absolute'
  392. >>> r3map.get_spatial_extent_as_tuple()
  393. (80.0, 0.0, 120.0, 0.0, 100.0, 0.0)
  394. >>> r3map.is_time_absolute()
  395. True
  396. >>> r3map.is_time_relative()
  397. False
  398. >>> grass.run_command("g.remove", rast3d=name)
  399. 0
  400. >>> grass.del_temp_region()
  401. """
  402. def __init__(self, ident):
  403. AbstractMapDataset.__init__(self)
  404. self.reset(ident)
  405. def get_type(self):
  406. return "raster3d"
  407. def get_new_instance(self, ident):
  408. """!Return a new instance with the type of this class"""
  409. return Raster3DDataset(ident)
  410. def get_new_stds_instance(self, ident):
  411. """!Return a new space time dataset instance in which maps
  412. are stored with the type of this class"""
  413. return SpaceTimeRaster3DDataset(ident)
  414. def get_stds_register(self):
  415. """!Return the space time dataset register table name in
  416. which stds are listed in which this map is registered"""
  417. return self.metadata.get_str3ds_register()
  418. def set_stds_register(self, name):
  419. """!Set the space time dataset register table name in
  420. which stds are listed in which this map is registered"""
  421. self.metadata.set_str3ds_register(name)
  422. def spatial_overlapping(self, dataset):
  423. """!Return True if the spatial extents overlap"""
  424. if self.get_type() == dataset.get_type() or dataset.get_type() == "str3ds":
  425. return self.spatial_extent.overlapping(dataset.spatial_extent)
  426. else:
  427. return self.spatial_extent.overlapping_2d(dataset.spatial_extent)
  428. def spatial_relation(self, dataset):
  429. """!Return the two or three dimensional spatial relation"""
  430. if self.get_type() == dataset.get_type() or dataset.get_type() == "str3ds":
  431. return self.spatial_extent.spatial_relation(dataset.spatial_extent)
  432. else:
  433. return self.spatial_extent.spatial_relation_2d(dataset.spatial_extent)
  434. def spatial_intersection(self, dataset):
  435. """!Return the three or two dimensional intersection as spatial_extent
  436. object or None in case no intersection was found.
  437. @param dataset The abstract dataset to intersect with
  438. @return The intersection spatial extent or None
  439. """
  440. if self.get_type() == dataset.get_type() or dataset.get_type() == "str3ds":
  441. return self.spatial_extent.intersect(dataset.spatial_extent)
  442. else:
  443. return self.spatial_extent.intersect_2d(dataset.spatial_extent)
  444. def spatial_union(self, dataset):
  445. """!Return the three or two dimensional union as spatial_extent
  446. object or None in case the extents does not overlap or meet.
  447. @param dataset The abstract dataset to create a union with
  448. @return The union spatial extent or None
  449. """
  450. if self.get_type() == dataset.get_type() or dataset.get_type() == "str3ds":
  451. return self.spatial_extent.union(dataset.spatial_extent)
  452. else:
  453. return self.spatial_extent.union_2d(dataset.spatial_extent)
  454. def spatial_disjoint_union(self, dataset):
  455. """!Return the three or two dimensional union as spatial_extent object.
  456. @param dataset The abstract dataset to create a union with
  457. @return The union spatial extent
  458. """
  459. if self.get_type() == dataset.get_type() or dataset.get_type() == "str3ds":
  460. return self.spatial_extent.disjoint_union(dataset.spatial_extent)
  461. else:
  462. return self.spatial_extent.disjoint_union_2d(dataset.spatial_extent)
  463. def get_np_array(self):
  464. """!Return this 3D raster map as memmap numpy style array to access the 3D raster
  465. values in numpy style without loading the whole map in the RAM.
  466. In case this 3D raster map does exists in the grass spatial database,
  467. the map will be exported using r3.out.bin to a temporary location
  468. and assigned to the memmap object that is returned by this function.
  469. In case the 3D raster map does not exists, an empty temporary
  470. binary file will be created and assigned to the memap object.
  471. You need to call the write function to write the memmap
  472. array back into grass.
  473. """
  474. a = garray.array3d()
  475. if self.map_exists():
  476. a.read(self.get_map_id())
  477. return a
  478. def reset(self, ident):
  479. """!Reset the internal structure and set the identifier"""
  480. self.base = Raster3DBase(ident=ident)
  481. self.absolute_time = Raster3DAbsoluteTime(ident=ident)
  482. self.relative_time = Raster3DRelativeTime(ident=ident)
  483. self.spatial_extent = Raster3DSpatialExtent(ident=ident)
  484. self.metadata = Raster3DMetadata(ident=ident)
  485. def has_grass_timestamp(self):
  486. """!Check if a grass file bsased time stamp exists for this map.
  487. """
  488. if libgis.G_has_raster3d_timestamp(self.get_name(), self.get_mapset()):
  489. return True
  490. else:
  491. return False
  492. def read_timestamp_from_grass(self):
  493. """!Read the timestamp of this map from the map metadata
  494. in the grass file system based spatial database and
  495. set the internal time stamp that should be insert/updated
  496. in the temporal database.
  497. """
  498. if not self.has_grass_timestamp():
  499. return False
  500. ts = libgis.TimeStamp()
  501. check = libgis.G_read_raster3d_timestamp(self.get_name(), self.get_mapset(),
  502. byref(ts))
  503. if check < 1:
  504. self.msgr.error(_("Unable to read timestamp file "
  505. "for 3D raster map <%s>" % (self.get_map_id())))
  506. return False
  507. return self._set_timestamp_from_grass(ts)
  508. def write_timestamp_to_grass(self):
  509. """!Write the timestamp of this map into the map metadata
  510. in the grass file system based spatial database.
  511. Internally the libgis API functions are used for writing
  512. """
  513. ts = libgis.TimeStamp()
  514. libgis.G_scan_timestamp(byref(ts), self._convert_timestamp())
  515. check = libgis.G_write_raster3d_timestamp(self.get_name(), byref(ts))
  516. if check == -1:
  517. self.msgr.error(_("Unable to create timestamp file "
  518. "for raster3d map <%s>" % (self.get_map_id())))
  519. if check == -2:
  520. self.msgr.error(_("Invalid datetime in timestamp "
  521. "for raster3d map <%s>" % (self.get_map_id())))
  522. def remove_timestamp_from_grass(self):
  523. """!Remove the timestamp from the grass file system based spatial database
  524. Internally the libgis API functions are used for removal
  525. """
  526. check = libgis.G_remove_raster3d_timestamp(self.get_name())
  527. if check == -1:
  528. self.msgr.error(_("Unable to remove timestamp for raster3d map <%s>" %
  529. (self.get_name())))
  530. def map_exists(self):
  531. """!Return True in case the map exists in the grass spatial database
  532. @return True if map exists, False otherwise
  533. """
  534. mapset = libgis.G_find_raster3d(self.get_name(), self.get_mapset())
  535. if not mapset:
  536. return False
  537. return True
  538. def read_info(self):
  539. """!Read the raster3d map info from the file system and store the content
  540. into a dictionary
  541. This method uses the ctypes interface to the gis and raster3d libraries
  542. to read the map metadata information
  543. """
  544. kvp = {}
  545. name = self.get_name()
  546. mapset = self.get_mapset()
  547. if not self.map_exists():
  548. core.fatal(_("Raster3d map <%s> not found" % name))
  549. # Read the region information
  550. region = libraster3d.RASTER3D_Region()
  551. libraster3d.Rast3d_read_region_map(name, mapset, byref(region))
  552. kvp["north"] = region.north
  553. kvp["south"] = region.south
  554. kvp["east"] = region.east
  555. kvp["west"] = region.west
  556. kvp["nsres"] = region.ns_res
  557. kvp["ewres"] = region.ew_res
  558. kvp["tbres"] = region.tb_res
  559. kvp["rows"] = region.cols
  560. kvp["cols"] = region.rows
  561. kvp["depths"] = region.depths
  562. kvp["top"] = region.top
  563. kvp["bottom"] = region.bottom
  564. # We need to open the map, this function returns a void pointer
  565. # but we may need the correct type which is RASTER3D_Map, hence
  566. # the casting
  567. g3map = cast(libraster3d.Rast3d_open_cell_old(name, mapset,
  568. libraster3d.RASTER3D_DEFAULT_WINDOW,
  569. libraster3d.RASTER3D_TILE_SAME_AS_FILE,
  570. libraster3d.RASTER3D_NO_CACHE),
  571. POINTER(libraster3d.RASTER3D_Map))
  572. if not g3map:
  573. core.fatal(_("Unable to open 3D raster map <%s>" % (name)))
  574. maptype = libraster3d.Rast3d_file_type_map(g3map)
  575. if maptype == libraster.DCELL_TYPE:
  576. kvp["datatype"] = "DCELL"
  577. elif maptype == libraster.FCELL_TYPE:
  578. kvp["datatype"] = "FCELL"
  579. # Read range
  580. min = libgis.DCELL()
  581. max = libgis.DCELL()
  582. ret = libraster3d.Rast3d_range_load(g3map)
  583. if not ret:
  584. core.fatal(_("Unable to load range of 3D raster map <%s>" %
  585. (name)))
  586. libraster3d.Rast3d_range_min_max(g3map, byref(min), byref(max))
  587. if min.value != min.value:
  588. kvp["min"] = None
  589. else:
  590. kvp["min"] = float(min.value)
  591. if max.value != max.value:
  592. kvp["max"] = None
  593. else:
  594. kvp["max"] = float(max.value)
  595. if not libraster3d.Rast3d_close(g3map):
  596. G_fatal_error(_("Unable to close 3D raster map <%s>" % (name)))
  597. return kvp
  598. def load(self):
  599. """!Load all info from an existing raster3d map into the internal structure"""
  600. # Fill base information
  601. self.base.set_creator(str(getpass.getuser()))
  602. # Fill spatial extent
  603. # Get the data from an existing 3D raster map
  604. if get_use_ctypes_map_access() == True:
  605. kvp = self.read_info()
  606. else:
  607. kvp = grass.raster3d_info(self.get_id())
  608. self.set_spatial_extent_from_values(north=kvp["north"], south=kvp["south"],
  609. east=kvp["east"], west=kvp["west"],
  610. top=kvp["top"], bottom=kvp["bottom"])
  611. # Fill metadata
  612. self.metadata.set_nsres(kvp["nsres"])
  613. self.metadata.set_ewres(kvp["ewres"])
  614. self.metadata.set_tbres(kvp["tbres"])
  615. self.metadata.set_datatype(kvp["datatype"])
  616. self.metadata.set_min(kvp["min"])
  617. self.metadata.set_max(kvp["max"])
  618. rows = int(kvp["rows"])
  619. cols = int(kvp["cols"])
  620. depths = int(kvp["depths"])
  621. ncells = cols * rows * depths
  622. self.metadata.set_cols(cols)
  623. self.metadata.set_rows(rows)
  624. self.metadata.set_depths(depths)
  625. self.metadata.set_number_of_cells(ncells)
  626. ###############################################################################
  627. class VectorDataset(AbstractMapDataset):
  628. """!Vector dataset class
  629. This class provides functions to select, update, insert or delete vector
  630. map information and valid time stamps into the SQL temporal database.
  631. Usage:
  632. @code
  633. >>> import grass.script as grass
  634. >>> init()
  635. >>> grass.use_temp_region()
  636. >>> grass.run_command("g.region", n=80.0, s=0.0, e=120.0, w=0.0,
  637. ... t=1.0, b=0.0, res=10.0)
  638. 0
  639. >>> grass.run_command("v.random", overwrite=True, output="stvds_map_test_case",
  640. ... n=100, zmin=0, zmax=100, flags="z", column="elevation")
  641. 0
  642. >>> grass.run_command("v.timestamp", map="stvds_map_test_case",
  643. ... date="15 jan 1999")
  644. 0
  645. >>> mapset = get_current_mapset()
  646. >>> name = "stvds_map_test_case"
  647. >>> identifier = "%s@%s" % (name, mapset)
  648. >>> vmap = VectorDataset(identifier)
  649. >>> vmap.map_exists()
  650. True
  651. >>> vmap.read_timestamp_from_grass()
  652. True
  653. >>> vmap.get_temporal_extent_as_tuple()
  654. (datetime.datetime(1999, 1, 15, 0, 0), None)
  655. >>> vmap.load()
  656. >>> vmap.absolute_time.print_info()
  657. +-------------------- Absolute time -----------------------------------------+
  658. | Start time:................. 1999-01-15 00:00:00
  659. | End time:................... None
  660. >>> vmap.metadata.print_info()
  661. +-------------------- Metadata information ----------------------------------+
  662. | STVDS register table ....... None
  663. | Is map 3d .................. True
  664. | Number of points ........... 100
  665. | Number of lines ............ 0
  666. | Number of boundaries ....... 0
  667. | Number of centroids ........ 0
  668. | Number of faces ............ 0
  669. | Number of kernels .......... 0
  670. | Number of primitives ....... 100
  671. | Number of nodes ............ 0
  672. | Number of areas ............ 0
  673. | Number of islands .......... 0
  674. | Number of holes ............ 0
  675. | Number of volumes .......... 0
  676. >>> newmap = vmap.get_new_instance("new@PERMANENT")
  677. >>> isinstance(newmap, VectorDataset)
  678. True
  679. >>> newstvds = vmap.get_new_stds_instance("new@PERMANENT")
  680. >>> isinstance(newstvds, SpaceTimeVectorDataset)
  681. True
  682. >>> vmap.get_type()
  683. 'vector'
  684. >>> vmap.get_stds_register()
  685. >>> vmap.set_absolute_time(start_time=datetime(2001,1,1),
  686. ... end_time=datetime(2012,1,1))
  687. True
  688. >>> vmap.get_absolute_time()
  689. (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2012, 1, 1, 0, 0), None)
  690. >>> vmap.get_temporal_extent_as_tuple()
  691. (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2012, 1, 1, 0, 0))
  692. >>> vmap.get_name()
  693. 'stvds_map_test_case'
  694. >>> vmap.get_mapset() == mapset
  695. True
  696. >>> vmap.get_temporal_type()
  697. 'absolute'
  698. >>> vmap.is_time_absolute()
  699. True
  700. >>> vmap.is_time_relative()
  701. False
  702. >>> grass.run_command("g.remove", vect=name)
  703. 0
  704. >>> grass.del_temp_region()
  705. @endcode
  706. """
  707. def __init__(self, ident):
  708. AbstractMapDataset.__init__(self)
  709. self.reset(ident)
  710. def get_type(self):
  711. return "vector"
  712. def get_new_instance(self, ident):
  713. """!Return a new instance with the type of this class"""
  714. return VectorDataset(ident)
  715. def get_new_stds_instance(self, ident):
  716. """!Return a new space time dataset instance in which maps
  717. are stored with the type of this class"""
  718. return SpaceTimeVectorDataset(ident)
  719. def get_stds_register(self):
  720. """!Return the space time dataset register table name in
  721. which stds are listed in which this map is registered"""
  722. return self.metadata.get_stvds_register()
  723. def set_stds_register(self, name):
  724. """!Set the space time dataset register table name in
  725. which stds are listed in which this map is registered"""
  726. self.metadata.set_stvds_register(name)
  727. def get_layer(self):
  728. """!Return the layer"""
  729. return self.base.get_layer()
  730. def spatial_overlapping(self, dataset):
  731. """!Return True if the spatial extents 2d overlap"""
  732. return self.spatial_extent.overlapping_2d(dataset.spatial_extent)
  733. def spatial_relation(self, dataset):
  734. """!Return the two dimensional spatial relation"""
  735. return self.spatial_extent.spatial_relation_2d(dataset.spatial_extent)
  736. def spatial_intersection(self, dataset):
  737. """!Return the two dimensional intersection as spatial_extent
  738. object or None in case no intersection was found.
  739. @param dataset The abstract dataset to intersect with
  740. @return The intersection spatial extent or None
  741. """
  742. return self.spatial_extent.intersect_2d(dataset.spatial_extent)
  743. def spatial_union(self, dataset):
  744. """!Return the two dimensional union as spatial_extent
  745. object or None in case the extents does not overlap or meet.
  746. @param dataset The abstract dataset to create a union with
  747. @return The union spatial extent or None
  748. """
  749. return self.spatial_extent.union_2d(dataset.spatial_extent)
  750. def spatial_disjoint_union(self, dataset):
  751. """!Return the two dimensional union as spatial_extent object.
  752. @param dataset The abstract dataset to create a union with
  753. @return The union spatial extent
  754. """
  755. return self.spatial_extent.disjoint_union_2d(dataset.spatial_extent)
  756. def reset(self, ident):
  757. """!Reset the internal structure and set the identifier"""
  758. self.base = VectorBase(ident=ident)
  759. self.absolute_time = VectorAbsoluteTime(ident=ident)
  760. self.relative_time = VectorRelativeTime(ident=ident)
  761. self.spatial_extent = VectorSpatialExtent(ident=ident)
  762. self.metadata = VectorMetadata(ident=ident)
  763. def has_grass_timestamp(self):
  764. """!Check if a grass file bsased time stamp exists for this map.
  765. """
  766. if libgis.G_has_vector_timestamp(self.get_name(), self.get_layer(),
  767. self.get_mapset()):
  768. return True
  769. else:
  770. return False
  771. def read_timestamp_from_grass(self):
  772. """!Read the timestamp of this map from the map metadata
  773. in the grass file system based spatial database and
  774. set the internal time stamp that should be insert/updated
  775. in the temporal database.
  776. """
  777. if not self.has_grass_timestamp():
  778. return False
  779. ts = libgis.TimeStamp()
  780. check = libgis.G_read_vector_timestamp(self.get_name(),
  781. self.get_layer(),
  782. self.get_mapset(),
  783. byref(ts))
  784. if check < 1:
  785. self.msgr.error(_("Unable to read timestamp file "
  786. "for vector map <%s>" % (self.get_map_id())))
  787. return False
  788. return self._set_timestamp_from_grass(ts)
  789. def write_timestamp_to_grass(self):
  790. """!Write the timestamp of this map into the map metadata in
  791. the grass file system based spatial database.
  792. Internally the libgis API functions are used for writing
  793. """
  794. ts = libgis.TimeStamp()
  795. libgis.G_scan_timestamp(byref(ts), self._convert_timestamp())
  796. check = libgis.G_write_vector_timestamp(
  797. self.get_name(), self.get_layer(), byref(ts))
  798. if check == -1:
  799. self.msgr.error(_("Unable to create timestamp file "
  800. "for vector map <%s>" % (self.get_map_id())))
  801. if check == -2:
  802. self.msgr.error(_("Invalid datetime in timestamp for vector map <%s>" %
  803. (self.get_map_id())))
  804. def remove_timestamp_from_grass(self):
  805. """!Remove the timestamp from the grass file system based spatial
  806. database
  807. Internally the libgis API functions are used for removal
  808. """
  809. check = libgis.G_remove_vector_timestamp(
  810. self.get_name(), self.get_layer())
  811. if check == -1:
  812. self.msgr.error(_("Unable to remove timestamp for vector map <%s>" %
  813. (self.get_name())))
  814. def map_exists(self):
  815. """!Return True in case the map exists in the grass spatial database
  816. @return True if map exists, False otherwise
  817. """
  818. mapset = libgis.G_find_vector(self.get_name(), self.get_mapset())
  819. if not mapset:
  820. return False
  821. return True
  822. def read_info(self):
  823. """!Read the vector map info from the file system and store the content
  824. into a dictionary
  825. This method uses the ctypes interface to the vector libraries
  826. to read the map metadata information
  827. """
  828. kvp = {}
  829. name = self.get_name()
  830. mapset = self.get_mapset()
  831. if not self.map_exists():
  832. core.fatal(_("Vector map <%s> not found" % name))
  833. # The vector map structure
  834. Map = libvector.Map_info()
  835. # We open the maps always in topology mode first
  836. libvector.Vect_set_open_level(2)
  837. with_topo = True
  838. # Code lend from v.info main.c
  839. if libvector.Vect_open_old_head2(byref(Map), name, mapset, "1") < 2:
  840. # force level 1, open fully
  841. # NOTE: number of points, lines, boundaries, centroids,
  842. # faces, kernels is still available
  843. libvector.Vect_set_open_level(1) # no topology
  844. with_topo = False
  845. self.msgr.message(_("Open map without topology support"))
  846. if libvector.Vect_open_old2(byref(Map), name, mapset, "1") < 1:
  847. core.fatal(_("Unable to open vector map <%s>" %
  848. (libvector.Vect_get_full_name(byref(Map)))))
  849. # Release the vector spatial index memory when closed
  850. libvector.Vect_set_release_support(byref(Map))
  851. # Read the extent information
  852. bbox = libvector.bound_box()
  853. libvector.Vect_get_map_box(byref(Map), byref(bbox))
  854. kvp["north"] = bbox.N
  855. kvp["south"] = bbox.S
  856. kvp["east"] = bbox.E
  857. kvp["west"] = bbox.W
  858. kvp["top"] = bbox.T
  859. kvp["bottom"] = bbox.B
  860. kvp["map3d"] = bool(libvector.Vect_is_3d(byref(Map)))
  861. # Read number of features
  862. if with_topo:
  863. kvp["points"] = libvector.Vect_get_num_primitives(
  864. byref(Map), libvector.GV_POINT)
  865. kvp["lines"] = libvector.Vect_get_num_primitives(
  866. byref(Map), libvector.GV_LINE)
  867. kvp["boundaries"] = libvector.Vect_get_num_primitives(
  868. byref(Map), libvector.GV_BOUNDARY)
  869. kvp["centroids"] = libvector.Vect_get_num_primitives(
  870. byref(Map), libvector.GV_CENTROID)
  871. kvp["faces"] = libvector.Vect_get_num_primitives(
  872. byref(Map), libvector.GV_FACE)
  873. kvp["kernels"] = libvector.Vect_get_num_primitives(
  874. byref(Map), libvector.GV_KERNEL)
  875. # Summarize the primitives
  876. kvp["primitives"] = kvp["points"] + kvp["lines"] + \
  877. kvp["boundaries"] + kvp["centroids"]
  878. if kvp["map3d"]:
  879. kvp["primitives"] += kvp["faces"] + kvp["kernels"]
  880. # Read topology information
  881. kvp["nodes"] = libvector.Vect_get_num_nodes(byref(Map))
  882. kvp["areas"] = libvector.Vect_get_num_areas(byref(Map))
  883. kvp["islands"] = libvector.Vect_get_num_islands(byref(Map))
  884. kvp["holes"] = libvector.Vect_get_num_holes(byref(Map))
  885. kvp["volumes"] = libvector.Vect_get_num_primitives(
  886. byref(Map), libvector.GV_VOLUME)
  887. else:
  888. kvp["points"] = None
  889. kvp["lines"] = None
  890. kvp["boundaries"] = None
  891. kvp["centroids"] = None
  892. kvp["faces"] = None
  893. kvp["kernels"] = None
  894. kvp["primitives"] = None
  895. kvp["nodes"] = None
  896. kvp["areas"] = None
  897. kvp["islands"] = None
  898. kvp["holes"] = None
  899. kvp["volumes"] = None
  900. libvector.Vect_close(byref(Map))
  901. return kvp
  902. def load(self):
  903. """!Load all info from an existing vector map into the internal
  904. structure"""
  905. # Fill base information
  906. self.base.set_creator(str(getpass.getuser()))
  907. # Get the data from an existing vector map
  908. if get_use_ctypes_map_access() == True:
  909. kvp = self.read_info()
  910. else:
  911. kvp = grass.vector_info(self.get_map_id())
  912. # Fill spatial extent
  913. self.set_spatial_extent_from_values(north=kvp["north"], south=kvp["south"],
  914. east=kvp["east"], west=kvp["west"],
  915. top=kvp["top"], bottom=kvp["bottom"])
  916. # Fill metadata
  917. self.metadata.set_3d_info(kvp["map3d"])
  918. self.metadata.set_number_of_points(kvp["points"])
  919. self.metadata.set_number_of_lines(kvp["lines"])
  920. self.metadata.set_number_of_boundaries(kvp["boundaries"])
  921. self.metadata.set_number_of_centroids(kvp["centroids"])
  922. self.metadata.set_number_of_faces(kvp["faces"])
  923. self.metadata.set_number_of_kernels(kvp["kernels"])
  924. self.metadata.set_number_of_primitives(kvp["primitives"])
  925. self.metadata.set_number_of_nodes(kvp["nodes"])
  926. self.metadata.set_number_of_areas(kvp["areas"])
  927. self.metadata.set_number_of_islands(kvp["islands"])
  928. self.metadata.set_number_of_holes(kvp["holes"])
  929. self.metadata.set_number_of_volumes(kvp["volumes"])
  930. ###############################################################################
  931. class SpaceTimeRasterDataset(AbstractSpaceTimeDataset):
  932. """!Space time raster dataset class
  933. """
  934. def __init__(self, ident):
  935. AbstractSpaceTimeDataset.__init__(self, ident)
  936. def get_type(self):
  937. return "strds"
  938. def get_new_instance(self, ident):
  939. """!Return a new instance with the type of this class"""
  940. return SpaceTimeRasterDataset(ident)
  941. def get_new_map_instance(self, ident):
  942. """!Return a new instance of a map dataset which is associated "
  943. "with the type of this class"""
  944. return RasterDataset(ident)
  945. def get_map_register(self):
  946. """!Return the name of the map register table"""
  947. return self.metadata.get_raster_register()
  948. def set_map_register(self, name):
  949. """!Set the name of the map register table"""
  950. self.metadata.set_raster_register(name)
  951. def spatial_overlapping(self, dataset):
  952. """!Return True if the spatial extents 2d overlap"""
  953. return self.spatial_extent.overlapping_2d(dataset.spatial_extent)
  954. def spatial_relation(self, dataset):
  955. """!Return the two dimensional spatial relation"""
  956. return self.spatial_extent.spatial_relation_2d(dataset.spatial_extent)
  957. def spatial_intersection(self, dataset):
  958. """!Return the two dimensional intersection as spatial_extent
  959. object or None in case no intersection was found.
  960. @param dataset The abstract dataset to intersect with
  961. @return The intersection spatial extent or None
  962. """
  963. return self.spatial_extent.intersect_2d(dataset.spatial_extent)
  964. def spatial_union(self, dataset):
  965. """!Return the two dimensional union as spatial_extent
  966. object or None in case the extents does not overlap or meet.
  967. @param dataset The abstract dataset to create a union with
  968. @return The union spatial extent or None
  969. """
  970. return self.spatial_extent.union_2d(dataset.spatial_extent)
  971. def spatial_disjoint_union(self, dataset):
  972. """!Return the two dimensional union as spatial_extent object.
  973. @param dataset The abstract dataset to create a union with
  974. @return The union spatial extent
  975. """
  976. return self.spatial_extent.disjoint_union_2d(dataset.spatial_extent)
  977. def reset(self, ident):
  978. """!Reset the internal structure and set the identifier"""
  979. self.base = STRDSBase(ident=ident)
  980. self.base.set_creator(str(getpass.getuser()))
  981. self.absolute_time = STRDSAbsoluteTime(ident=ident)
  982. self.relative_time = STRDSRelativeTime(ident=ident)
  983. self.spatial_extent = STRDSSpatialExtent(ident=ident)
  984. self.metadata = STRDSMetadata(ident=ident)
  985. ###############################################################################
  986. class SpaceTimeRaster3DDataset(AbstractSpaceTimeDataset):
  987. """!Space time raster3d dataset class
  988. """
  989. def __init__(self, ident):
  990. AbstractSpaceTimeDataset.__init__(self, ident)
  991. def get_type(self):
  992. return "str3ds"
  993. def get_new_instance(self, ident):
  994. """!Return a new instance with the type of this class"""
  995. return SpaceTimeRaster3DDataset(ident)
  996. def get_new_map_instance(self, ident):
  997. """!Return a new instance of a map dataset which is associated
  998. with the type of this class"""
  999. return Raster3DDataset(ident)
  1000. def get_map_register(self):
  1001. """!Return the name of the map register table"""
  1002. return self.metadata.get_raster3d_register()
  1003. def set_map_register(self, name):
  1004. """!Set the name of the map register table"""
  1005. self.metadata.set_raster3d_register(name)
  1006. def spatial_overlapping(self, dataset):
  1007. """!Return True if the spatial extents overlap"""
  1008. if self.get_type() == dataset.get_type() or dataset.get_type() == "str3ds":
  1009. return self.spatial_extent.overlapping(dataset.spatial_extent)
  1010. else:
  1011. return self.spatial_extent.overlapping_2d(dataset.spatial_extent)
  1012. def spatial_relation(self, dataset):
  1013. """!Return the two or three dimensional spatial relation"""
  1014. if self.get_type() == dataset.get_type() or \
  1015. dataset.get_type() == "str3ds":
  1016. return self.spatial_extent.spatial_relation(dataset.spatial_extent)
  1017. else:
  1018. return self.spatial_extent.spatial_relation_2d(dataset.spatial_extent)
  1019. def spatial_intersection(self, dataset):
  1020. """!Return the three or two dimensional intersection as spatial_extent
  1021. object or None in case no intersection was found.
  1022. @param dataset The abstract dataset to intersect with
  1023. @return The intersection spatial extent or None
  1024. """
  1025. if self.get_type() == dataset.get_type() or dataset.get_type() == "raster3d":
  1026. return self.spatial_extent.intersect(dataset.spatial_extent)
  1027. else:
  1028. return self.spatial_extent.intersect_2d(dataset.spatial_extent)
  1029. def spatial_union(self, dataset):
  1030. """!Return the three or two dimensional union as spatial_extent
  1031. object or None in case the extents does not overlap or meet.
  1032. @param dataset The abstract dataset to create a union with
  1033. @return The union spatial extent or None
  1034. """
  1035. if self.get_type() == dataset.get_type() or dataset.get_type() == "raster3d":
  1036. return self.spatial_extent.union(dataset.spatial_extent)
  1037. else:
  1038. return self.spatial_extent.union_2d(dataset.spatial_extent)
  1039. def spatial_disjoint_union(self, dataset):
  1040. """!Return the three or two dimensional union as spatial_extent object.
  1041. @param dataset The abstract dataset to create a union with
  1042. @return The union spatial extent
  1043. """
  1044. if self.get_type() == dataset.get_type() or dataset.get_type() == "raster3d":
  1045. return self.spatial_extent.disjoint_union(dataset.spatial_extent)
  1046. else:
  1047. return self.spatial_extent.disjoint_union_2d(dataset.spatial_extent)
  1048. def reset(self, ident):
  1049. """!Reset the internal structure and set the identifier"""
  1050. self.base = STR3DSBase(ident=ident)
  1051. self.base.set_creator(str(getpass.getuser()))
  1052. self.absolute_time = STR3DSAbsoluteTime(ident=ident)
  1053. self.relative_time = STR3DSRelativeTime(ident=ident)
  1054. self.spatial_extent = STR3DSSpatialExtent(ident=ident)
  1055. self.metadata = STR3DSMetadata(ident=ident)
  1056. ###############################################################################
  1057. class SpaceTimeVectorDataset(AbstractSpaceTimeDataset):
  1058. """!Space time vector dataset class
  1059. """
  1060. def __init__(self, ident):
  1061. AbstractSpaceTimeDataset.__init__(self, ident)
  1062. def get_type(self):
  1063. return "stvds"
  1064. def get_new_instance(self, ident):
  1065. """!Return a new instance with the type of this class"""
  1066. return SpaceTimeVectorDataset(ident)
  1067. def get_new_map_instance(self, ident):
  1068. """!Return a new instance of a map dataset which is associated
  1069. with the type of this class"""
  1070. return VectorDataset(ident)
  1071. def get_map_register(self):
  1072. """!Return the name of the map register table"""
  1073. return self.metadata.get_vector_register()
  1074. def set_map_register(self, name):
  1075. """!Set the name of the map register table"""
  1076. self.metadata.set_vector_register(name)
  1077. def spatial_overlapping(self, dataset):
  1078. """!Return True if the spatial extents 2d overlap"""
  1079. return self.spatial_extent.overlapping_2d(dataset.spatial_extent)
  1080. def spatial_relation(self, dataset):
  1081. """!Return the two dimensional spatial relation"""
  1082. return self.spatial_extent.spatial_relation_2d(dataset.spatial_extent)
  1083. def spatial_intersection(self, dataset):
  1084. """!Return the two dimensional intersection as spatial_extent
  1085. object or None in case no intersection was found.
  1086. @param dataset The abstract dataset to intersect with
  1087. @return The intersection spatial extent or None
  1088. """
  1089. return self.spatial_extent.intersect_2d(dataset.spatial_extent)
  1090. def spatial_union(self, dataset):
  1091. """!Return the two dimensional union as spatial_extent
  1092. object or None in case the extents does not overlap or meet.
  1093. @param dataset The abstract dataset to create a union with
  1094. @return The union spatial extent or None
  1095. """
  1096. return self.spatial_extent.union_2d(dataset.spatial_extent)
  1097. def spatial_disjoint_union(self, dataset):
  1098. """!Return the two dimensional union as spatial_extent object.
  1099. @param dataset The abstract dataset to create a union with
  1100. @return The union spatial extent
  1101. """
  1102. return self.spatial_extent.disjoint_union_2d(dataset.spatial_extent)
  1103. def reset(self, ident):
  1104. """!Reset the internal structure and set the identifier"""
  1105. self.base = STVDSBase(ident=ident)
  1106. self.base.set_creator(str(getpass.getuser()))
  1107. self.absolute_time = STVDSAbsoluteTime(ident=ident)
  1108. self.relative_time = STVDSRelativeTime(ident=ident)
  1109. self.spatial_extent = STVDSSpatialExtent(ident=ident)
  1110. self.metadata = STVDSMetadata(ident=ident)
  1111. ###############################################################################
  1112. if __name__ == "__main__":
  1113. import doctest
  1114. doctest.testmod()