1# -*- coding: utf-8 -*- 2""" 3Spatial topology connector class 4 5Usage: 6 7>>> import grass.temporal as tgis 8>>> tmr = tgis.SpatialTopologyDatasetConnector() 9 10(C) 2012-2013 by the GRASS Development Team 11This program is free software under the GNU General Public 12License (>=v2). Read the file COPYING that comes with GRASS 13for details. 14 15:authors: Soeren Gebbert 16""" 17from __future__ import print_function 18import copy 19 20 21class SpatialTopologyDatasetConnector(object): 22 """This class implements a spatial topology access structure to connect 23 spatial related datasets 24 25 This object will be set up by spatial topology creation method provided 26 by the SpatioTemporalTopologyBuilder. 27 28 The following spatial relations with access methods are supported: 29 30 - equivalent 31 - overlap 32 - in 33 - contain 34 - meet 35 - cover 36 - covered 37 38 Usage: 39 40 .. code-block:: python 41 42 >>> import grass.temporal as tgis 43 >>> tgis.init() 44 >>> map = tgis.RasterDataset("a@P") 45 >>> tmr = tgis.SpatialTopologyDatasetConnector() 46 >>> tmr.append_equivalent(map) 47 >>> tmr.append_overlap(map) 48 >>> tmr.append_in(map) 49 >>> tmr.append_contain(map) 50 >>> tmr.append_meet(map) 51 >>> tmr.append_cover(map) 52 >>> tmr.append_covered(map) 53 >>> tmr.print_spatial_topology_info() 54 +-------------------- Spatial Topology --------------------------------------+ 55 | Equivalent: ................ a@P 56 | Cover: ..................... a@P 57 | Covered: ................... a@P 58 | Overlap: ................... a@P 59 | In: ........................ a@P 60 | Contain: ................... a@P 61 | Meet: ...................... a@P 62 >>> tmr.print_spatial_topology_shell_info() 63 equivalent=a@P 64 cover=a@P 65 covered=a@P 66 overlap=a@P 67 in=a@P 68 contain=a@P 69 meet=a@P 70 >>> rlist = tmr.get_spatial_relations() 71 >>> if "COVER" in rlist.keys(): 72 ... print(rlist["COVER"][0].get_id()) 73 a@P 74 75 """ 76 77 def __init__(self): 78 self.reset_spatial_topology() 79 80 def reset_spatial_topology(self): 81 """Reset any information about temporal topology""" 82 self._spatial_topology = {} 83 self._has_spatial_topology = False 84 85 def get_spatial_relations(self): 86 """Return the dictionary of spatial relationships 87 88 Keys are the spatial relationships in upper case, 89 values are abstract map objects. 90 91 :return: The spatial relations dictionary 92 """ 93 return copy.copy(self._spatial_topology) 94 95 def get_number_of_spatial_relations(self): 96 """ Return a dictionary in which the keys are the relation names and the value 97 are the number of relations. 98 99 The following relations are available: 100 101 - equivalent 102 - overlap 103 - in 104 - contain 105 - meet 106 - cover 107 - covered 108 109 To access topological information the spatial topology must be 110 build first using the SpatialTopologyBuilder. 111 112 :return: the dictionary with relations as keys and number as 113 values or None in case the topology wasn't build 114 """ 115 if self._has_spatial_topology is False: 116 return None 117 118 relations = {} 119 try: 120 relations["equivalent"] = len(self._spatial_topology["EQUIVALENT"]) 121 except: 122 relations["equivalent"] = 0 123 try: 124 relations["overlap"] = len(self._spatial_topology["OVERLAP"]) 125 except: 126 relations["overlap"] = 0 127 try: 128 relations["in"] = len(self._spatial_topology["IN"]) 129 except: 130 relations["in"] = 0 131 try: 132 relations["contain"] = len(self._spatial_topology["CONTAIN"]) 133 except: 134 relations["contain"] = 0 135 try: 136 relations["meet"] = len(self._spatial_topology["MEET"]) 137 except: 138 relations["meet"] = 0 139 try: 140 relations["cover"] = len(self._spatial_topology["COVER"]) 141 except: 142 relations["cover"] = 0 143 try: 144 relations["covered"] = len(self._spatial_topology["COVERED"]) 145 except: 146 relations["covered"] = 0 147 148 return relations 149 150 def set_spatial_topology_build_true(self): 151 """Same as name""" 152 self._has_spatial_topology = True 153 154 def set_spatial_topology_build_false(self): 155 """Same as name""" 156 self._has_spatial_topology = False 157 158 def is_spatial_topology_build(self): 159 """Check if the temporal topology was build""" 160 return self._has_spatial_topology 161 162 def append_equivalent(self, map): 163 """Append a map with equivalent spatial extent as this map 164 165 :param map: This object should be of type AbstractMapDataset 166 or derived classes 167 """ 168 if "EQUIVALENT" not in self._spatial_topology: 169 self._spatial_topology["EQUIVALENT"] = [] 170 self._spatial_topology["EQUIVALENT"].append(map) 171 172 def get_equivalent(self): 173 """Return a list of map objects with equivalent spatial extent as this map 174 175 :return: A list of map objects or None 176 """ 177 if "EQUIVALENT" not in self._spatial_topology: 178 return None 179 return self._spatial_topology["EQUIVALENT"] 180 181 def append_overlap(self, map): 182 """Append a map that this spatial overlap with this map 183 184 :param map: This object should be of type AbstractMapDataset 185 or derived classes 186 """ 187 if "OVERLAP" not in self._spatial_topology: 188 self._spatial_topology["OVERLAP"] = [] 189 self._spatial_topology["OVERLAP"].append(map) 190 191 def get_overlap(self): 192 """Return a list of map objects that this map spatial overlap with 193 194 :return: A list of map objects or None 195 """ 196 if "OVERLAP" not in self._spatial_topology: 197 return None 198 return self._spatial_topology["OVERLAP"] 199 200 def append_in(self, map): 201 """Append a map that this is spatial in this map 202 203 :param map: This object should be of type AbstractMapDataset 204 or derived classes 205 """ 206 if "IN" not in self._spatial_topology: 207 self._spatial_topology["IN"] = [] 208 self._spatial_topology["IN"].append(map) 209 210 def get_in(self): 211 """Return a list of map objects that are spatial in this map 212 213 :return: A list of map objects or None 214 """ 215 if "IN" not in self._spatial_topology: 216 return None 217 return self._spatial_topology["IN"] 218 219 def append_contain(self, map): 220 """Append a map that this map spatially contains 221 222 :param map: This object should be of type AbstractMapDataset 223 or derived classes 224 """ 225 if "CONTAIN" not in self._spatial_topology: 226 self._spatial_topology["CONTAIN"] = [] 227 self._spatial_topology["CONTAIN"].append(map) 228 229 def get_contain(self): 230 """Return a list of map objects that this map contains 231 232 :return: A list of map objects or None 233 """ 234 if "CONTAIN" not in self._spatial_topology: 235 return None 236 return self._spatial_topology["CONTAIN"] 237 238 def append_meet(self, map): 239 """Append a map that spatially meet with this map 240 241 :param map: This object should be of type AbstractMapDataset 242 or derived classes 243 """ 244 if "MEET" not in self._spatial_topology: 245 self._spatial_topology["MEET"] = [] 246 self._spatial_topology["MEET"].append(map) 247 248 def get_meet(self): 249 """Return a list of map objects that spatially meet with this map 250 251 :return: A list of map objects or None 252 """ 253 if "MEET" not in self._spatial_topology: 254 return None 255 return self._spatial_topology["MEET"] 256 257 def append_cover(self, map): 258 """Append a map that spatially cover this map 259 260 :param map: This object should be of type AbstractMapDataset 261 or derived classes 262 """ 263 if "COVER" not in self._spatial_topology: 264 self._spatial_topology["COVER"] = [] 265 self._spatial_topology["COVER"].append(map) 266 267 def get_cover(self): 268 """Return a list of map objects that spatially cover this map 269 270 :return: A list of map objects or None 271 """ 272 if "COVER" not in self._spatial_topology: 273 return None 274 return self._spatial_topology["COVER"] 275 276 def append_covered(self, map): 277 """Append a map that is spatially covered by this map 278 279 :param map: This object should be of type AbstractMapDataset 280 or derived classes 281 """ 282 if "COVERED" not in self._spatial_topology: 283 self._spatial_topology["COVERED"] = [] 284 self._spatial_topology["COVERED"].append(map) 285 286 def get_covered(self): 287 """Return a list of map objects that are spatially covered by this map 288 289 :return: A list of map objects or None 290 """ 291 if "COVERED" not in self._spatial_topology: 292 return None 293 return self._spatial_topology["COVERED"] 294 295 def _generate_map_list_string(self, map_list, line_wrap=True): 296 count = 0 297 string = "" 298 for map_ in map_list: 299 if line_wrap and count > 0 and count % 3 == 0: 300 string += "\n | ............................ " 301 count = 0 302 if count == 0: 303 string += map_.get_id() 304 else: 305 string += ",%s" % map_.get_id() 306 count += 1 307 308 return string 309 310 # Set the properties 311 equivalent = property(fget=get_equivalent, fset=append_equivalent) 312 cover = property(fget=get_cover, fset=append_cover) 313 covered = property(fget=get_covered, fset=append_covered) 314 overlap = property(fget=get_overlap, fset=append_overlap) 315 in_ = property(fget=get_in, fset=append_in) 316 contain = property(fget=get_contain, fset=append_contain) 317 meet = property(fget=get_meet, fset=append_meet) 318 319 def print_spatial_topology_info(self): 320 """Print information about this class in human readable style""" 321 322 print(" +-------------------- Spatial Topology --------------------------------------+") 323 # 0123456789012345678901234567890 324 if self.equivalent is not None: 325 print(" | Equivalent: ................ " + 326 self._generate_map_list_string(self.equivalent)) 327 if self.cover is not None: 328 print(" | Cover: ..................... " + 329 self._generate_map_list_string(self.cover)) 330 if self.covered is not None: 331 print(" | Covered: ................... " + 332 self._generate_map_list_string(self.covered)) 333 if self.overlap is not None: 334 print(" | Overlap: ................... " + 335 self._generate_map_list_string(self.overlap)) 336 if self.in_ is not None: 337 print(" | In: ........................ " + 338 self._generate_map_list_string(self.in_)) 339 if self.contain is not None: 340 print(" | Contain: ................... " + 341 self._generate_map_list_string(self.contain)) 342 if self.meet is not None: 343 print(" | Meet: ...................... " + 344 self._generate_map_list_string(self.meet)) 345 346 def print_spatial_topology_shell_info(self): 347 """Print information about this class in shell style""" 348 349 if self.equivalent is not None: 350 print("equivalent=" + self._generate_map_list_string(self.equivalent, 351 False)) 352 if self.cover is not None: 353 print("cover=" + self._generate_map_list_string( 354 self.cover, False)) 355 if self.covered is not None: 356 print("covered=" + 357 self._generate_map_list_string(self.covered, False)) 358 if self.overlap is not None: 359 print("overlap=" + 360 self._generate_map_list_string(self.overlap)) 361 if self.in_ is not None: 362 print("in=" + 363 self._generate_map_list_string(self.in_)) 364 if self.contain is not None: 365 print("contain=" + 366 self._generate_map_list_string(self.contain)) 367 if self.meet is not None: 368 print("meet=" + 369 self._generate_map_list_string(self.meet)) 370 371############################################################################### 372 373if __name__ == "__main__": 374 import doctest 375 doctest.testmod() 376