123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410 |
- """!@package grass.temporal
- @brief GRASS Python scripting module (temporal GIS functions)
- Temporal GIS related spatial extent functions to be used in Python scripts and tgis packages.
- Usage:
- @code
- >>> import grass.temporal as tgis
- >>> extent = tgis.RasterSpatialExtent(
- ... ident="raster@PERMANENT", north=90, south=90, east=180, west=180,
- ... top=100, bottom=-20)
- >>> extent = tgis.Raster3DSpatialExtent(
- ... ident="raster3d@PERMANENT", north=90, south=90, east=180, west=180,
- ... top=100, bottom=-20)
- >>> extent = tgis.VectorSpatialExtent(
- ... ident="vector@PERMANENT", north=90, south=90, east=180, west=180,
- ... top=100, bottom=-20)
- >>> extent = tgis.STRDSSpatialExtent(
- ... ident="strds@PERMANENT", north=90, south=90, east=180, west=180,
- ... top=100, bottom=-20)
- >>> extent = tgis.STR3DSSpatialExtent(
- ... ident="str3ds@PERMANENT", north=90, south=90, east=180, west=180,
- ... top=100, bottom=-20)
- >>> extent = tgis.STVDSSpatialExtent(
- ... ident="stvds@PERMANENT", north=90, south=90, east=180, west=180,
- ... top=100, bottom=-20)
- @endcode
- (C) 2008-2011 by the GRASS Development Team
- This program is free software under the GNU General Public
- License (>=v2). Read the file COPYING that comes with GRASS
- for details.
- @author Soeren Gebbert
- """
- from base import *
- class SpatialExtent(SQLDatabaseInterface):
- """!This is the spatial extent base class for all maps and space time datasets
-
- This class implements a three dimensional axis aligned bounding box
- and functions to compute topological relationships
-
- Usage:
-
- @code
-
- >>> extent = SpatialExtent(table="raster_spatial_extent",
- ... ident="soil@PERMANENT", north=90, south=90, east=180, west=180,
- ... top=100, bottom=-20)
- >>> extent.id
- 'soil@PERMANENT'
- >>> extent.north
- 90.0
- >>> extent.south
- 90.0
- >>> extent.east
- 180.0
- >>> extent.west
- 180.0
- >>> extent.top
- 100.0
- >>> extent.bottom
- -20.0
- >>> extent.print_info()
- +-------------------- Spatial extent ----------------------------------------+
- | North:...................... 90.0
- | South:...................... 90.0
- | East:.. .................... 180.0
- | West:....................... 180.0
- | Top:........................ 100.0
- | Bottom:..................... -20.0
- >>> extent.print_shell_info()
- north=90.0
- south=90.0
- east=180.0
- west=180.0
- top=100.0
- bottom=-20.0
-
- @endcode
- """
- def __init__(self, table=None, ident=None, north=None, south=None,
- east=None, west=None, top=None, bottom=None, proj="XY"):
- SQLDatabaseInterface.__init__(self, table, ident)
- self.set_id(ident)
- self.set_spatial_extent(north, south, east, west, top, bottom)
- self.set_projection(proj)
- def overlapping_2d(self, extent):
- """!Return True if the two dimensional extents overlap.
- Code is lend from wind_overlap.c in lib/gis
- Overlapping includes the spatial relations:
- * contain
- * in
- * cover
- * covered
- * equivalent
- """
- if self.get_projection() != extent.get_projection():
- core.error(_("Projections are different. Unable to compute "
- "overlapping_2d for spatial extents"))
- return False
- N = extent.get_north()
- S = extent.get_south()
- E = extent.get_east()
- W = extent.get_west()
- # Adjust the east and west in case of LL projection
- if self.get_projection() == "LL":
- while E < self.get_west():
- E += 360.0
- W += 360.0
- while W > self.get_east():
- E -= 360.0
- W -= 360.0
- if(self.get_north() <= S):
- return False
- if(self.get_south() >= N):
- return False
- if self.get_east() <= W:
- return False
- if self.get_west() >= E:
- return False
- return True
- def overlapping(self, extent):
- """!Return True if the three dimensional extents overlap
- Overlapping includes the spatial relations:
- * contain
- * in
- * cover
- * covered
- * equivalent
-
- Usage:
-
- @code
-
- >>> A = SpatialExtent(north=80, south=20, east=60, west=10, bottom=-50, top=50)
- >>> B = SpatialExtent(north=80, south=20, east=60, west=10, bottom=-50, top=50)
- >>> A.overlapping(B)
- True
-
- @endcode
- """
- if not self.overlapping_2d(extent):
- return False
- T = extent.get_top()
- B = extent.get_bottom()
- if self.get_top() <= B:
- return False
- if self.get_bottom() >= T:
- return False
- return True
- def intersect_2d(self, extent):
- """!Return the two dimensional intersection as spatial_extent
- object or None in case no intersection was found.
- """
- if not self.overlapping_2d(extent):
- return None
- eN = extent.get_north()
- eS = extent.get_south()
- eE = extent.get_east()
- eW = extent.get_west()
- N = self.get_north()
- S = self.get_south()
- E = self.get_east()
- W = self.get_west()
- # Adjust the east and west in case of LL projection
- if self.get_projection() == "LL":
- while eE < W:
- eE += 360.0
- eW += 360.0
- while eW > E:
- eE -= 360.0
- eW -= 360.0
- # Compute the extent
- nN = N
- nS = S
- nE = E
- nW = W
- if W < eW:
- nW = eW
- if E > eE:
- nE = eE
- if N > eN:
- nN = eN
- if S < eS:
- nS = eS
- new = SpatialExtent(north=nN, south=nS, east=nE, west=nW,
- top=0, bottom=0, proj=self.get_projection())
- return new
- def intersect(self, extent):
- """!Return the three dimensional intersection as spatial_extent
- object or None in case no intersection was found.
-
- Usage:
-
- @code
-
- >>> A = SpatialExtent(north=80, south=20, east=60, west=10, bottom=-50, top=50)
- >>> B = SpatialExtent(north=80, south=20, east=60, west=10, bottom=-50, top=50)
- >>> C = A.intersect(B)
- >>> C.print_info()
- +-------------------- Spatial extent ----------------------------------------+
- | North:...................... 80.0
- | South:...................... 20.0
- | East:.. .................... 60.0
- | West:....................... 10.0
- | Top:........................ 50.0
- | Bottom:..................... -50.0
- >>> B = SpatialExtent(north=40, south=30, east=60, west=10, bottom=-50, top=50)
- >>> C = A.intersect(B)
- >>> C.print_info()
- +-------------------- Spatial extent ----------------------------------------+
- | North:...................... 40.0
- | South:...................... 30.0
- | East:.. .................... 60.0
- | West:....................... 10.0
- | Top:........................ 50.0
- | Bottom:..................... -50.0
- >>> B = SpatialExtent(north=40, south=30, east=60, west=30, bottom=-50, top=50)
- >>> C = A.intersect(B)
- >>> C.print_info()
- +-------------------- Spatial extent ----------------------------------------+
- | North:...................... 40.0
- | South:...................... 30.0
- | East:.. .................... 60.0
- | West:....................... 30.0
- | Top:........................ 50.0
- | Bottom:..................... -50.0
- >>> B = SpatialExtent(north=40, south=30, east=60, west=30, bottom=-30, top=50)
- >>> C = A.intersect(B)
- >>> C.print_info()
- +-------------------- Spatial extent ----------------------------------------+
- | North:...................... 40.0
- | South:...................... 30.0
- | East:.. .................... 60.0
- | West:....................... 30.0
- | Top:........................ 50.0
- | Bottom:..................... -30.0
- >>> B = SpatialExtent(north=40, south=30, east=60, west=30, bottom=-30, top=30)
- >>> C = A.intersect(B)
- >>> C.print_info()
- +-------------------- Spatial extent ----------------------------------------+
- | North:...................... 40.0
- | South:...................... 30.0
- | East:.. .................... 60.0
- | West:....................... 30.0
- | Top:........................ 30.0
- | Bottom:..................... -30.0
-
- @endcode
- """
- if not self.overlapping(extent):
- return None
- new = self.intersect_2d(extent)
- eT = extent.get_top()
- eB = extent.get_bottom()
- T = self.get_top()
- B = self.get_bottom()
- nT = T
- nB = B
- if B < eB:
- nB = eB
- if T > eT:
- nT = eT
- new.set_top(nT)
- new.set_bottom(nB)
- return new
- def is_in_2d(self, extent):
- """!Check two dimensional if the self is located in extent
-
- @verbatim
- _____
- |A _ |
- | |_| |
- |_____|B
-
- @endverbatim
- """
- if self.get_projection() != extent.get_projection():
- core.error(_("Projections are different. Unable to compute "
- "is_in_2d for spatial extents"))
- return False
- eN = extent.get_north()
- eS = extent.get_south()
- eE = extent.get_east()
- eW = extent.get_west()
- N = self.get_north()
- S = self.get_south()
- E = self.get_east()
- W = self.get_west()
- # Adjust the east and west in case of LL projection
- if self.get_projection() == "LL":
- while eE < W:
- eE += 360.0
- eW += 360.0
- while eW > E:
- eE -= 360.0
- eW -= 360.0
- if W <= eW:
- return False
- if E >= eE:
- return False
- if N >= eN:
- return False
- if S <= eS:
- return False
- return True
- def is_in(self, extent):
- """!Check three dimensional if the self is located in extent
-
- Usage:
-
- @code
-
- >>> A = SpatialExtent(north=79, south=21, east=59, west=11, bottom=-49, top=49)
- >>> B = SpatialExtent(north=80, south=20, east=60, west=10, bottom=-50, top=50)
- >>> A.is_in(B)
- True
- >>> B.is_in(A)
- False
-
- @endcode
- """
- if not self.is_in_2d(extent):
- return False
- eT = extent.get_top()
- eB = extent.get_bottom()
- T = self.get_top()
- B = self.get_bottom()
- if B <= eB:
- return False
- if T >= eT:
- return False
- return True
- def contain_2d(self, extent):
- """!Check two dimensional if self contains extent """
- return extent.is_in_2d(self)
- def contain(self, extent):
- """!Check three dimensional if self contains extent """
- return extent.is_in(self)
- def equivalent_2d(self, extent):
- """!Check two dimensional if self is equivalent to extent """
- if self.get_projection() != extent.get_projection():
- core.error(_("Projections are different. Unable to compute "
- "equivalent_2d for spatial extents"))
- return False
- eN = extent.get_north()
- eS = extent.get_south()
- eE = extent.get_east()
- eW = extent.get_west()
- N = self.get_north()
- S = self.get_south()
- E = self.get_east()
- W = self.get_west()
- # Adjust the east and west in case of LL projection
- if self.get_projection() == "LL":
- while eE < W:
- eE += 360.0
- eW += 360.0
- while eW > E:
- eE -= 360.0
- eW -= 360.0
- if W != eW:
- return False
- if E != eE:
- return False
- if N != eN:
- return False
- if S != eS:
- return False
- return True
- def equivalent(self, extent):
- """!Check three dimensional if self is equivalent to extent """
- if not self.equivalent_2d(extent):
- return False
- eT = extent.get_top()
- eB = extent.get_bottom()
- T = self.get_top()
- B = self.get_bottom()
- if B != eB:
- return False
- if T != eT:
- return False
- return True
- def cover_2d(self, extent):
- """!Return True if two dimensional self covers extent
-
- @verbatim
- _____ _____ _____ _____
- |A __| |__ A| |A | B| |B | A|
- | |B | | B| | | |__| |__| |
- |__|__| |__|__| |_____| |_____|
- _____ _____ _____ _____
- |A|B| | |A __| |A _ | |__ A|
- | |_| | | |__|B | |B| | B|__| |
- |_____| |_____| |_|_|_| |_____|
- _____ _____ _____ _____
- |A|B | |_____|A |A|B|A| |_____|A
- | | | |B | | | | | |_____|B
- |_|___| |_____| |_|_|_| |_____|A
-
- @endverbatim
- The following cases are excluded:
- * contain
- * in
- * equivalent
- """
- if self.get_projection() != extent.get_projection():
- core.error(_("Projections are different. Unable to compute cover_2d for spatial extents"))
- return False
- # Exclude equivalent_2d
- if self.equivalent_2d(extent):
- return False
- eN = extent.get_north()
- eS = extent.get_south()
- eE = extent.get_east()
- eW = extent.get_west()
- N = self.get_north()
- S = self.get_south()
- E = self.get_east()
- W = self.get_west()
- # Adjust the east and west in case of LL projection
- if self.get_projection() == "LL":
- while eE < W:
- eE += 360.0
- eW += 360.0
- while eW > E:
- eE -= 360.0
- eW -= 360.0
- # Edges of extent located outside of self are not allowed
- if E < eW:
- return False
- if W > eE:
- return False
- if N < eS:
- return False
- if S > eN:
- return False
- # First we check that at least one edge of extent meets an edge of self
- if W != eW and E != eE and N != eN and S != eS:
- return False
- # We check that at least one edge of extent is located in self
- edge_count = 0
- if W < eW and E > eW:
- edge_count += 1
- if E > eE and W < eE:
- edge_count += 1
- if N > eN and S < eN:
- edge_count += 1
- if S < eS and N > eS:
- edge_count += 1
- if edge_count == 0:
- return False
- return True
- def cover(self, extent):
- """!Return True if three dimensional self covers extent
- The following cases are excluded:
- * contain
- * in
- * equivalent
- """
- if self.get_projection() != extent.get_projection():
- core.error(_("Projections are different. Unable to compute cover for spatial extents"))
- return False
- # Exclude equivalent_2d
- if self.equivalent_2d(extent):
- return False
- eN = extent.get_north()
- eS = extent.get_south()
- eE = extent.get_east()
- eW = extent.get_west()
- eT = extent.get_top()
- eB = extent.get_bottom()
- N = self.get_north()
- S = self.get_south()
- E = self.get_east()
- W = self.get_west()
- T = self.get_top()
- B = self.get_bottom()
- # Adjust the east and west in case of LL projection
- if self.get_projection() == "LL":
- while eE < W:
- eE += 360.0
- eW += 360.0
- while eW > E:
- eE -= 360.0
- eW -= 360.0
- # Edges of extent located outside of self are not allowed
- if E <= eW:
- return False
- if W >= eE:
- return False
- if N <= eS:
- return False
- if S >= eN:
- return False
- if T <= eB:
- return False
- if B >= eT:
- return False
- # First we check that at least one edge of extent meets an edge of self
- if W != eW and E != eE and N != eN and S != eS and B != eB and T != eT:
- return False
- # We check that at least one edge of extent is located in self
- edge_count = 0
- if W < eW and E > eW:
- edge_count += 1
- if E > eE and W < eE:
- edge_count += 1
- if N > eN and S < eN:
- edge_count += 1
- if S < eS and N > eS:
- edge_count += 1
- if N > eN and S < eN:
- edge_count += 1
- if S < eS and N > eS:
- edge_count += 1
- if T > eT and B < eT:
- edge_count += 1
- if B < eB and T > eB:
- edge_count += 1
- if edge_count == 0:
- return False
- return True
- def covered_2d(self, extent):
- """!Check two dimensional if self is covered by extent """
- return extent.cover_2d(self)
- def covered(self, extent):
- """!Check three dimensional if self is covered by extent """
- return extent.cover(self)
- def overlap_2d(self, extent):
- """!Return True if the two dimensional extents overlap. Code is
- lend from wind_overlap.c in lib/gis
-
- @verbatim
- _____
- |A __|__
- | | | B|
- |__|__| |
- |_____|
-
- @endverbatim
- The following cases are excluded:
- * contain
- * in
- * cover
- * covered
- * equivalent
- """
- if self.contain_2d(extent):
- return False
- if self.is_in_2d(extent):
- return False
- if self.cover_2d(extent):
- return False
- if self.covered_2d(extent):
- return False
- if self.equivalent_2d(extent):
- return False
- N = extent.get_north()
- S = extent.get_south()
- E = extent.get_east()
- W = extent.get_west()
- # Adjust the east and west in case of LL projection
- if self.get_projection() == "LL":
- while E < self.get_west():
- E += 360.0
- W += 360.0
- while W > self.get_east():
- E -= 360.0
- W -= 360.0
- if(self.get_north() <= S):
- return False
- if(self.get_south() >= N):
- return False
- if self.get_east() <= W:
- return False
- if self.get_west() >= E:
- return False
- return True
- def overlap(self, extent):
- """!Return True if the three dimensional extents overlap
- The following cases are excluded:
- * contain
- * in
- * cover
- * covered
- * equivalent
- """
- if self.is_in(extent):
- return False
- if self.contain(extent):
- return False
- if self.cover(extent):
- return False
- if self.covered(extent):
- return False
- if self.equivalent(extent):
- return False
- N = extent.get_north()
- S = extent.get_south()
- E = extent.get_east()
- W = extent.get_west()
- T = extent.get_top()
- B = extent.get_bottom()
- # Adjust the east and west in case of LL projection
- if self.get_projection() == "LL":
- while E < self.get_west():
- E += 360.0
- W += 360.0
- while W > self.get_east():
- E -= 360.0
- W -= 360.0
- if(self.get_north() <= S):
- return False
- if(self.get_south() >= N):
- return False
- if self.get_east() <= W:
- return False
- if self.get_west() >= E:
- return False
- if self.get_top() <= B:
- return False
- if self.get_bottom() >= T:
- return False
- return True
- def meet_2d(self, extent):
- """!Check if self and extent meet each other in two dimensions
-
- @verbatim
- _____ _____ _____ _____
- | A | B | | B | A |
- |_____| | | | |
- |_____| |_____|_____|
- ___
- | A |
- | |
- |___| _____
- | B | | B |
- | | | |
- |_____| |_____|_
- | A |
- | |
- |_____|
-
- @endverbatim
- """
- eN = extent.get_north()
- eS = extent.get_south()
- eE = extent.get_east()
- eW = extent.get_west()
- eT = extent.get_top()
- eB = extent.get_bottom()
- N = self.get_north()
- S = self.get_south()
- E = self.get_east()
- W = self.get_west()
- # Adjust the east and west in case of LL projection
- if self.get_projection() == "LL":
- while eE < W:
- eE += 360.0
- eW += 360.0
- while eW > E:
- eE -= 360.0
- eW -= 360.0
- edge = None
- edge_count = 0
- if E == eW:
- edge = "E"
- edge_count += 1
- if W == eE:
- edge = "W"
- edge_count += 1
- if N == eS:
- edge = "N"
- edge_count += 1
- if S == eN:
- edge = "S"
- edge_count += 1
- # Meet a a single edge only
- if edge_count != 1:
- return False
- # Check boundaries of the faces
- if edge == "E" or edge == "W":
- if N < eS or S > eN:
- return False
- if edge == "N" or edge == "S":
- if E < eW or W > eE:
- return False
- return True
- def meet(self, extent):
- """!Check if self and extent meet each other in three dimensions"""
- eN = extent.get_north()
- eS = extent.get_south()
- eE = extent.get_east()
- eW = extent.get_west()
- eT = extent.get_top()
- eB = extent.get_bottom()
- N = self.get_north()
- S = self.get_south()
- E = self.get_east()
- W = self.get_west()
- T = self.get_top()
- B = self.get_bottom()
- # Adjust the east and west in case of LL projection
- if self.get_projection() == "LL":
- while eE < W:
- eE += 360.0
- eW += 360.0
- while eW > E:
- eE -= 360.0
- eW -= 360.0
- edge = None
- edge_count = 0
- if E == eW:
- edge = "E"
- edge_count += 1
- if W == eE:
- edge = "W"
- edge_count += 1
- if N == eS:
- edge = "N"
- edge_count += 1
- if S == eN:
- edge = "S"
- edge_count += 1
- if T == eB:
- edge = "T"
- edge_count += 1
- if B == eT:
- edge = "B"
- edge_count += 1
- # Meet a single edge only
- if edge_count != 1:
- return False
- # Check boundaries of the faces
- if edge == "E" or edge == "W":
- if N < eS or S > eN:
- return False
- if T < eB or B > eT:
- return False
- if edge == "N" or edge == "S":
- if E < eW or W > eE:
- return False
- if T < eB or B > eT:
- return False
- if edge == "T" or edge == "B":
- if E < eW or W > eE:
- return False
- if N < eS or S > eN:
- return False
- return True
- def disjoint_2d(self, extent):
- """!Return True if the two dimensional extents are disjoint
- """
- if self.overlapping_2d(extent) or self.meet_2d(extent):
- return False
- return True
- def disjoint(self, extent):
- """!Return True if the three dimensional extents are disjoint
- """
- if self.overlapping(extent) or self.meet(extent):
- return False
- return True
- def spatial_relation_2d(self, extent):
- """!Returns the two dimensional spatial relation between self and extent
- Spatial relations are:
- * disjoint
- * meet
- * overlap
- * cover
- * covered
- * in
- * contain
- * equivalent
-
- Usage: see self.spatial_relation()
- """
- if self.equivalent_2d(extent):
- return "equivalent"
- if self.contain_2d(extent):
- return "contain"
- if self.is_in_2d(extent):
- return "in"
- if self.cover_2d(extent):
- return "cover"
- if self.covered_2d(extent):
- return "covered"
- if self.overlap_2d(extent):
- return "overlap"
- if self.meet_2d(extent):
- return "meet"
- if self.disjoint_2d(extent):
- return "disjoint"
- return "unknown"
- def spatial_relation(self, extent):
- """!Returns the three dimensional spatial relation between self and extent
- Spatial relations are:
- * disjoint
- * meet
- * overlap
- * cover
- * covered
- * in
- * contain
- * equivalent
-
-
- Usage:
-
- @code
-
- >>> A = SpatialExtent(north=80, south=20, east=60, west=10, bottom=-50, top=50)
- >>> B = SpatialExtent(north=80, south=20, east=60, west=10, bottom=-50, top=50)
- >>> A.spatial_relation(B)
- 'equivalent'
- >>> B.spatial_relation(A)
- 'equivalent'
- >>> B = SpatialExtent(north=70, south=20, east=60, west=10, bottom=-50, top=50)
- >>> A.spatial_relation_2d(B)
- 'cover'
- >>> A.spatial_relation(B)
- 'cover'
- >>> B = SpatialExtent(north=70, south=30, east=60, west=10, bottom=-50, top=50)
- >>> A.spatial_relation_2d(B)
- 'cover'
- >>> A.spatial_relation(B)
- 'cover'
- >>> B.spatial_relation_2d(A)
- 'covered'
- >>> B.spatial_relation(A)
- 'covered'
- >>> B = SpatialExtent(north=70, south=30, east=50, west=10, bottom=-50, top=50)
- >>> A.spatial_relation_2d(B)
- 'cover'
- >>> B.spatial_relation_2d(A)
- 'covered'
- >>> A.spatial_relation(B)
- 'cover'
- >>> B = SpatialExtent(north=70, south=30, east=50, west=20, bottom=-50, top=50)
- >>> B.spatial_relation(A)
- 'covered'
- >>> B = SpatialExtent(north=70, south=30, east=50, west=20, bottom=-50, top=50)
- >>> A.spatial_relation_2d(B)
- 'contain'
- >>> A.spatial_relation(B)
- 'cover'
- >>> B = SpatialExtent(north=70, south=30, east=50, west=20, bottom=-40, top=50)
- >>> A.spatial_relation(B)
- 'cover'
- >>> B = SpatialExtent(north=70, south=30, east=50, west=20, bottom=-40, top=40)
- >>> A.spatial_relation(B)
- 'contain'
- >>> B.spatial_relation(A)
- 'in'
- >>> B = SpatialExtent(north=90, south=30, east=50, west=20, bottom=-40, top=40)
- >>> A.spatial_relation_2d(B)
- 'overlap'
- >>> A.spatial_relation(B)
- 'overlap'
- >>> B = SpatialExtent(north=90, south=5, east=70, west=5, bottom=-40, top=40)
- >>> A.spatial_relation_2d(B)
- 'in'
- >>> A.spatial_relation(B)
- 'overlap'
- >>> B = SpatialExtent(north=90, south=5, east=70, west=5, bottom=-40, top=60)
- >>> A.spatial_relation(B)
- 'overlap'
- >>> B = SpatialExtent(north=90, south=5, east=70, west=5, bottom=-60, top=60)
- >>> A.spatial_relation(B)
- 'in'
- >>> A = SpatialExtent(north=80, south=60, east=60, west=10, bottom=-50, top=50)
- >>> B = SpatialExtent(north=60, south=20, east=60, west=10, bottom=-50, top=50)
- >>> A.spatial_relation_2d(B)
- 'meet'
- >>> A.spatial_relation(B)
- 'meet'
- >>> A = SpatialExtent(north=60, south=40, east=60, west=10, bottom=-50, top=50)
- >>> B = SpatialExtent(north=80, south=60, east=60, west=10, bottom=-50, top=50)
- >>> A.spatial_relation_2d(B)
- 'meet'
- >>> A.spatial_relation(B)
- 'meet'
- >>> A = SpatialExtent(north=80, south=40, east=60, west=40, bottom=-50, top=50)
- >>> B = SpatialExtent(north=80, south=40, east=40, west=20, bottom=-50, top=50)
- >>> A.spatial_relation_2d(B)
- 'meet'
- >>> A.spatial_relation(B)
- 'meet'
- >>> A = SpatialExtent(north=80, south=40, east=40, west=20, bottom=-50, top=50)
- >>> B = SpatialExtent(north=90, south=30, east=60, west=40, bottom=-50, top=50)
- >>> A.spatial_relation_2d(B)
- 'meet'
- >>> A.spatial_relation(B)
- 'meet'
- >>> A = SpatialExtent(north=80, south=40, east=40, west=20, bottom=-50, top=50)
- >>> B = SpatialExtent(north=70, south=50, east=60, west=40, bottom=-50, top=50)
- >>> A.spatial_relation_2d(B)
- 'meet'
- >>> A.spatial_relation(B)
- 'meet'
- >>> A = SpatialExtent(north=80, south=40, east=40, west=20, bottom=-50, top=50)
- >>> B = SpatialExtent(north=60, south=20, east=60, west=40, bottom=-50, top=50)
- >>> A.spatial_relation_2d(B)
- 'meet'
- >>> A.spatial_relation(B)
- 'meet'
- >>> A = SpatialExtent(north=80, south=40, east=40, west=20, bottom=-50, top=50)
- >>> B = SpatialExtent(north=40, south=20, east=60, west=40, bottom=-50, top=50)
- >>> A.spatial_relation_2d(B)
- 'disjoint'
- >>> A.spatial_relation(B)
- 'disjoint'
- >>> A = SpatialExtent(north=80, south=40, east=40, west=20, bottom=-50, top=50)
- >>> B = SpatialExtent(north=60, south=20, east=60, west=40, bottom=-60, top=60)
- >>> A.spatial_relation(B)
- 'meet'
- >>> A = SpatialExtent(north=80, south=40, east=40, west=20, bottom=-50, top=50)
- >>> B = SpatialExtent(north=90, south=30, east=60, west=40, bottom=-40, top=40)
- >>> A.spatial_relation(B)
- 'meet'
- >>> A = SpatialExtent(north=80, south=40, east=60, west=20, bottom=0, top=50)
- >>> B = SpatialExtent(north=80, south=40, east=60, west=20, bottom=-50, top=0)
- >>> A.spatial_relation(B)
- 'meet'
- >>> A = SpatialExtent(north=80, south=40, east=60, west=20, bottom=0, top=50)
- >>> B = SpatialExtent(north=80, south=50, east=60, west=30, bottom=-50, top=0)
- >>> A.spatial_relation(B)
- 'meet'
- >>> A = SpatialExtent(north=80, south=40, east=60, west=20, bottom=0, top=50)
- >>> B = SpatialExtent(north=70, south=50, east=50, west=30, bottom=-50, top=0)
- >>> A.spatial_relation(B)
- 'meet'
- >>> A = SpatialExtent(north=80, south=40, east=60, west=20, bottom=0, top=50)
- >>> B = SpatialExtent(north=90, south=30, east=70, west=10, bottom=-50, top=0)
- >>> A.spatial_relation(B)
- 'meet'
- >>> A = SpatialExtent(north=80, south=40, east=60, west=20, bottom=0, top=50)
- >>> B = SpatialExtent(north=70, south=30, east=50, west=10, bottom=-50, top=0)
- >>> A.spatial_relation(B)
- 'meet'
- >>> A = SpatialExtent(north=80, south=40, east=60, west=20, bottom=-50, top=0)
- >>> B = SpatialExtent(north=80, south=40, east=60, west=20, bottom=0, top=50)
- >>> A.spatial_relation(B)
- 'meet'
- >>> A = SpatialExtent(north=80, south=40, east=60, west=20, bottom=-50, top=0)
- >>> B = SpatialExtent(north=80, south=50, east=60, west=30, bottom=0, top=50)
- >>> A.spatial_relation(B)
- 'meet'
- >>> A = SpatialExtent(north=80, south=40, east=60, west=20, bottom=-50, top=0)
- >>> B = SpatialExtent(north=70, south=50, east=50, west=30, bottom=0, top=50)
- >>> A.spatial_relation(B)
- 'meet'
- >>> A = SpatialExtent(north=80, south=40, east=60, west=20, bottom=-50, top=0)
- >>> B = SpatialExtent(north=90, south=30, east=70, west=10, bottom=0, top=50)
- >>> A.spatial_relation(B)
- 'meet'
- >>> A = SpatialExtent(north=80, south=40, east=60, west=20, bottom=-50, top=0)
- >>> B = SpatialExtent(north=70, south=30, east=50, west=10, bottom=0, top=50)
- >>> A.spatial_relation(B)
- 'meet'
-
- @endverbatim
- """
- if self.equivalent(extent):
- return "equivalent"
- if self.contain(extent):
- return "contain"
- if self.is_in(extent):
- return "in"
- if self.cover(extent):
- return "cover"
- if self.covered(extent):
- return "covered"
- if self.overlap(extent):
- return "overlap"
- if self.meet(extent):
- return "meet"
- if self.disjoint(extent):
- return "disjoint"
- return "unknown"
- def set_spatial_extent(self, north, south, east, west, top, bottom):
- """!Set the spatial extent"""
- self.set_north(north)
- self.set_south(south)
- self.set_east(east)
- self.set_west(west)
- self.set_top(top)
- self.set_bottom(bottom)
- def set_projection(self, proj):
- """!Set the projection of the spatial extent it should be XY or LL.
- As default the projection is XY
- """
- if proj is None or (proj != "XY" and proj != "LL"):
- self.D["proj"] = "XY"
- else:
- self.D["proj"] = proj
- def set_spatial_extent_2d(self, north, south, east, west):
- self.set_north(north)
- self.set_south(south)
- self.set_east(east)
- self.set_west(west)
- def set_id(self, ident):
- """!Convenient method to set the unique identifier (primary key)"""
- self.ident = ident
- self.D["id"] = ident
- def set_north(self, north):
- """!Set the northern edge of the map"""
- if north is not None:
- self.D["north"] = float(north)
- else:
- self.D["north"] = None
- def set_south(self, south):
- """!Set the southern edge of the map"""
- if south is not None:
- self.D["south"] = float(south)
- else:
- self.D["south"] = None
- def set_west(self, west):
- """!Set the western edge of the map"""
- if west is not None:
- self.D["west"] = float(west)
- else:
- self.D["west"] = None
- def set_east(self, east):
- """!Set the eastern edge of the map"""
- if east is not None:
- self.D["east"] = float(east)
- else:
- self.D["east"] = None
- def set_top(self, top):
- """!Set the top edge of the map"""
- if top is not None:
- self.D["top"] = float(top)
- else:
- self.D["top"] = None
- def set_bottom(self, bottom):
- """!Set the bottom edge of the map"""
- if bottom is not None:
- self.D["bottom"] = float(bottom)
- else:
- self.D["bottom"] = None
- def get_id(self):
- """!Convenient method to get the unique identifier (primary key)
- @return None if not found
- """
- if "id" in self.D:
- return self.D["id"]
- else:
- return None
- def get_projection(self):
- """!Get the projection of the spatial extent"""
- return self.D["proj"]
- def get_volume(self):
- """!Compute the volume of the extent, in case z is zero
- (top == bottom or top - bottom = 1) the area is returned"""
- if self.get_projection() == "LL":
- core.error(_("Volume computation is not supported "
- "for LL projections"))
- area = self.get_area()
- bbox = self.get_spatial_extent()
- z = abs(bbox[4] - bbox[5])
- if z == 0:
- z = 1.0
- return area * z
- def get_area(self):
- """!Compute the area of the extent, extent in z direction is ignored"""
- if self.get_projection() == "LL":
- core.error(_("Area computation is not supported "
- "for LL projections"))
- bbox = self.get_spatial_extent()
- y = abs(bbox[0] - bbox[1])
- x = abs(bbox[2] - bbox[3])
- return x * y
- def get_spatial_extent(self):
- """!Return a tuple (north, south, east, west, top, bottom)
- of the spatial extent"""
- return (
- self.north, self.south, self.east, self.west,
- self.top, self.bottom)
- def get_spatial_extent_2d(self):
- """!Return a tuple (north, south, east, west,) of the 2d spatial extent
- """
- return (self.north, self.south, self.east, self.west)
- def get_north(self):
- """!Get the northern edge of the map
- @return None if not found"""
- if "north" in self.D:
- return self.D["north"]
- else:
- return None
- def get_south(self):
- """!Get the southern edge of the map
- @return None if not found"""
- if "south" in self.D:
- return self.D["south"]
- else:
- return None
- def get_east(self):
- """!Get the eastern edge of the map
- @return None if not found"""
- if "east" in self.D:
- return self.D["east"]
- else:
- return None
- def get_west(self):
- """!Get the western edge of the map
- @return None if not found"""
- if "west" in self.D:
- return self.D["west"]
- else:
- return None
- def get_top(self):
- """!Get the top edge of the map
- @return None if not found"""
- if "top" in self.D:
- return self.D["top"]
- else:
- return None
- def get_bottom(self):
- """!Get the bottom edge of the map
- @return None if not found"""
- if "bottom" in self.D:
- return self.D["bottom"]
- else:
- return None
-
- id = property(fget=get_id, fset=set_id)
- north = property(fget=get_north, fset=set_north)
- south = property(fget=get_south, fset=set_south)
- east = property(fget=get_east, fset=set_east)
- west = property(fget=get_west, fset=set_west)
- top = property(fget=get_top, fset=set_top)
- bottom= property(fget=get_bottom, fset=set_bottom)
- def print_info(self):
- """!Print information about this class in human readable style"""
- # 0123456789012345678901234567890
- print " +-------------------- Spatial extent ----------------------------------------+"
- print " | North:...................... " + str(self.get_north())
- print " | South:...................... " + str(self.get_south())
- print " | East:.. .................... " + str(self.get_east())
- print " | West:....................... " + str(self.get_west())
- print " | Top:........................ " + str(self.get_top())
- print " | Bottom:..................... " + str(self.get_bottom())
- def print_shell_info(self):
- """Print information about this class in shell style"""
- print "north=" + str(self.get_north())
- print "south=" + str(self.get_south())
- print "east=" + str(self.get_east())
- print "west=" + str(self.get_west())
- print "top=" + str(self.get_top())
- print "bottom=" + str(self.get_bottom())
- ###############################################################################
- class RasterSpatialExtent(SpatialExtent):
- def __init__(self, ident=None, north=None, south=None, east=None,
- west=None, top=None, bottom=None):
- SpatialExtent.__init__(self, "raster_spatial_extent",
- ident, north, south, east, west, top, bottom)
- class Raster3DSpatialExtent(SpatialExtent):
- def __init__(self, ident=None, north=None, south=None, east=None,
- west=None, top=None, bottom=None):
- SpatialExtent.__init__(self, "raster3d_spatial_extent",
- ident, north, south, east, west, top, bottom)
- class VectorSpatialExtent(SpatialExtent):
- def __init__(self, ident=None, north=None, south=None, east=None,
- west=None, top=None, bottom=None):
- SpatialExtent.__init__(self, "vector_spatial_extent",
- ident, north, south, east, west, top, bottom)
- class STRDSSpatialExtent(SpatialExtent):
- def __init__(self, ident=None, north=None, south=None, east=None,
- west=None, top=None, bottom=None):
- SpatialExtent.__init__(self, "strds_spatial_extent",
- ident, north, south, east, west, top, bottom)
- class STR3DSSpatialExtent(SpatialExtent):
- def __init__(self, ident=None, north=None, south=None, east=None,
- west=None, top=None, bottom=None):
- SpatialExtent.__init__(self, "str3ds_spatial_extent",
- ident, north, south, east, west, top, bottom)
- class STVDSSpatialExtent(SpatialExtent):
- def __init__(self, ident=None, north=None, south=None, east=None,
- west=None, top=None, bottom=None):
- SpatialExtent.__init__(self, "stvds_spatial_extent",
- ident, north, south, east, west, top, bottom)
- ###############################################################################
- if __name__ == "__main__":
- import doctest
- doctest.testmod()
|