[GRASS-SVN] r51142 - grass/trunk/lib/python/temporal
svn_grass at osgeo.org
svn_grass at osgeo.org
Thu Mar 22 08:21:11 EDT 2012
Author: huhabla
Date: 2012-03-22 05:21:11 -0700 (Thu, 22 Mar 2012)
New Revision: 51142
Modified:
grass/trunk/lib/python/temporal/Makefile
grass/trunk/lib/python/temporal/__init__.py
grass/trunk/lib/python/temporal/abstract_dataset.py
grass/trunk/lib/python/temporal/abstract_space_time_dataset.py
grass/trunk/lib/python/temporal/space_time_datasets.py
grass/trunk/lib/python/temporal/space_time_datasets_tools.py
grass/trunk/lib/python/temporal/spatial_extent.py
grass/trunk/lib/python/temporal/temporal_extent.py
grass/trunk/lib/python/temporal/temporal_granularity.py
grass/trunk/lib/python/temporal/unit_tests.py
Log:
New spatial relationship computationi. Now spatio-temporal transition relations can be computed.
Implemented spatio-temporal sampling. Support for multiple input for spatio-temporal sampling.
Modified: grass/trunk/lib/python/temporal/Makefile
===================================================================
--- grass/trunk/lib/python/temporal/Makefile 2012-03-22 10:28:16 UTC (rev 51141)
+++ grass/trunk/lib/python/temporal/Makefile 2012-03-22 12:21:11 UTC (rev 51142)
@@ -8,7 +8,7 @@
GDIR = $(PYDIR)/grass
DSTDIR = $(GDIR)/temporal
-MODULES = base core abstract_dataset abstract_map_dataset abstract_space_time_dataset space_time_datasets space_time_datasets_tools metadata spatial_extent temporal_extent datetime_math temporal_granularity unit_tests aggregation
+MODULES = base core abstract_dataset abstract_map_dataset abstract_space_time_dataset space_time_datasets space_time_datasets_tools metadata spatial_extent temporal_extent datetime_math temporal_granularity temporal_relationships unit_tests aggregation
PYFILES := $(patsubst %,$(DSTDIR)/%.py,$(MODULES) __init__)
PYCFILES := $(patsubst %,$(DSTDIR)/%.pyc,$(MODULES) __init__)
Modified: grass/trunk/lib/python/temporal/__init__.py
===================================================================
--- grass/trunk/lib/python/temporal/__init__.py 2012-03-22 10:28:16 UTC (rev 51141)
+++ grass/trunk/lib/python/temporal/__init__.py 2012-03-22 12:21:11 UTC (rev 51142)
@@ -10,5 +10,6 @@
from space_time_datasets_tools import *
from datetime_math import *
from temporal_granularity import *
+from temporal_relationships import *
from unit_tests import *
from aggregation import *
Modified: grass/trunk/lib/python/temporal/abstract_dataset.py
===================================================================
--- grass/trunk/lib/python/temporal/abstract_dataset.py 2012-03-22 10:28:16 UTC (rev 51141)
+++ grass/trunk/lib/python/temporal/abstract_dataset.py 2012-03-22 12:21:11 UTC (rev 51142)
@@ -47,6 +47,11 @@
"""
raise IOError("This method must be implemented in the subclasses")
+ def spatial_overlapping(self, dataset):
+ """Return True if the spatial extents are overlapping"""
+
+ raise IOError("This method must be implemented in the subclasses")
+
def print_info(self):
"""Print information about this class in human readable style"""
raise IOError("This method must be implemented in the subclasses")
@@ -172,11 +177,6 @@
return (north, south, east, west, top, bottom)
- def spatial_overlap(self, dataset):
- """Return True if the spatial extents overlap"""
-
- north = self.spatial_extent.overlap(dataset.spatial_extent)
-
def select(self, dbif=None):
"""Select temporal dataset entry from database and fill up the internal structure"""
Modified: grass/trunk/lib/python/temporal/abstract_space_time_dataset.py
===================================================================
--- grass/trunk/lib/python/temporal/abstract_space_time_dataset.py 2012-03-22 10:28:16 UTC (rev 51141)
+++ grass/trunk/lib/python/temporal/abstract_space_time_dataset.py 2012-03-22 12:21:11 UTC (rev 51142)
@@ -22,6 +22,7 @@
"""
from abstract_dataset import *
from temporal_granularity import *
+from temporal_relationships import *
###############################################################################
@@ -194,67 +195,7 @@
return map_time
- def print_temporal_relation_matrix(self, maps):
- """Print the temporal relation matrix of all registered maps to stdout
-
- The temporal relation matrix includes the temporal relations between
- all registered maps. The relations are strings stored in a list of lists.
-
- @param dbif: The database interface to be used
- """
-
- for i in range(len(maps)):
- reltations = ""
- count = 0
- for j in range(i + 1, len(maps)):
- relation = maps[j].temporal_relation(maps[i])
-
- # print maps[j].base.get_name(), maps[i].base.get_name(), relation
- if count == 0:
- relations = relation
- else:
- relations += "," + str(relation)
- count += 1
- # Break if the the next map follows
- if relation == "follows":
- break
- # Break if the the next map is after
- if relation == "after":
- break
- if i < len(maps) - 1:
- print maps[i].base.get_name(), relations
- else:
- print maps[i].base.get_name()
-
- def get_temporal_relation_matrix(self, maps):
- """Return the temporal relation matrix of all registered maps as list of lists
-
- The map list must be ordered by start time
-
- The temporal relation matrix includes the temporal relations between
- all registered maps. The relations are strings stored in a list of lists.
-
- @param maps: a ordered by start_time list of map objects
- """
-
- matrix = []
-
- # Create the temporal relation matrix
- # Add the map names first
- row = []
- for map in maps:
- row.append(map.get_id())
- matrix.append(row)
-
- for mapA in maps:
- row = []
- for mapB in maps:
- row.append(mapA.temporal_relation(mapB))
- matrix.append(row)
-
- return matrix
-
- def count_temporal_types(self, maps):
+ def count_temporal_types(self, maps=None, dbif=None):
"""Return the temporal type of the registered maps as dictionary
The map list must be ordered by start time
@@ -265,8 +206,12 @@
* invalid -> No valid time point or interval found
@param maps: A sorted (start_time) list of abstract_dataset objects
+ @param dbif: The database interface to be used
"""
+ if maps == None:
+ maps = get_registered_maps_as_objects(where=None, order="start_time", dbif=dbif)
+
time_invalid = 0
time_point = 0
time_interval = 0
@@ -292,13 +237,17 @@
return tcount
- def count_gaps(self, maps):
+ def count_gaps(self, maps=None, dbif=None):
"""Count the number of gaps between temporal neighbors
@param maps: A sorted (start_time) list of abstract_dataset objects
+ @param dbif: The database interface to be used
@return The numbers of gaps between temporal neighbors
"""
+ if maps == None:
+ maps = get_registered_maps_as_objects(where=None, order="start_time", dbif=dbif)
+
gaps = 0
# Check for gaps
@@ -309,36 +258,54 @@
gaps += 1
return gaps
+
+ def print_temporal_relation_matrix(self, maps=None, dbif=None):
+ """Print the temporal relation matrix of all registered maps to stdout
- def count_temporal_relations(self, maps):
- """Count the temporal relations between the registered maps.
+ The temporal relation matrix includes the temporal relations between
+ all registered maps. The relations are strings stored in a list of lists.
+
+ @param maps: a ordered by start_time list of map objects
+ @param dbif: The database interface to be used
+ """
+
+ if maps == None:
+ maps = get_registered_maps_as_objects(where=None, order="start_time", dbif=dbif)
+
+ print_temporal_relations(maps, maps)
+ def get_temporal_relation_matrix(self, maps=None, dbif=None):
+ """Return the temporal relation matrix of all registered maps as list of lists
+
The map list must be ordered by start time
- @param maps: A sorted (start_time) list of abstract_dataset objects
- @return A dictionary with counted temporal relationships
+ The temporal relation matrix includes the temporal relations between
+ all registered maps. The relations are strings stored in a list of lists.
+
+ @param maps: a ordered by start_time list of map objects
+ @param dbif: The database interface to be used
"""
+ if maps == None:
+ maps = get_registered_maps_as_objects(where=None, order="start_time", dbif=dbif)
- tcount = {}
- for i in range(len(maps)):
- # Check for point and interval data
- for j in range(i + 1, len(maps)):
- relation = maps[j].temporal_relation(maps[i])
+ return get_temporal_relation_matrix(maps, maps)
- if tcount.has_key(relation):
- tcount[relation] = tcount[relation] + 1
- else:
- tcount[relation] = 1
+ def count_temporal_relations(self, maps=None, dbif=None):
+ """Count the temporal relations between the registered maps.
- # Break if the the next map follows
- if relation == "follows":
- break
- # Break if the the next map is after
- if relation == "after":
- break
+ The map list must be ordered by start time. Temporal relations are counted
+ by analysing the sparse upper right side temporal relationships matrix.
- return tcount
+ @param maps: A sorted (start_time) list of abstract_dataset objects
+ @param dbif: The database interface to be used
+ @return A dictionary with counted temporal relationships
+ """
+
+ if maps == None:
+ maps = get_registered_maps_as_objects(where=None, order="start_time", dbif=dbif)
+ return count_temporal_relations(maps, maps)
+
def check_temporal_topology(self, maps=None, dbif=None):
"""Check the temporal topology
@@ -401,10 +368,13 @@
return True
- def sample_by_dataset_topology(self, stds, method=None, dbif=None):
+ def sample_by_dataset(self, stds, method=None, spatial=False, dbif=None):
"""Sample this space time dataset with the temporal topology of a second space time dataset
The sample dataset must have "interval" as temporal map type, so all sample maps have valid interval time.
+
+ In case spatial is True, the spatial overlap between temporal related maps is performed. Only
+ temporal related and spatial overlapping maps are returned.
Return all registered maps as ordered (by start_time) object list with
"gap" map objects (id==None). Each list entry is a list of map objects
@@ -413,7 +383,7 @@
Each entry in the object list is a dict. The actual sampler map and its temporal extent (the actual granule) and
the list of samples are stored:
- list = self.sample_by_dataset_topology(stds=sampler, method=["during","overlap","contain","equal"])
+ list = self.sample_by_dataset(stds=sampler, method=["during","overlap","contain","equal"])
for entry in list:
granule = entry["granule"]
maplist = entry["samples"]
@@ -462,6 +432,8 @@
granule: s-----------e
All these methods can be combined. Method must be of type tuple including the identification strings.
+ @param spatial: If set True additional the spatial overlapping is used for selection -> spatio-temporal relation.
+ The returned map objects will have temporal and spatial extents
@param dbif: The database interface to be used
In case nothing found None is returned
@@ -519,31 +491,35 @@
sample_maps = stds.get_registered_maps_as_objects_with_gaps(where=None, dbif=dbif)
for granule in sample_maps:
+ # Read the spatial extent
+ if spatial == True:
+ granule.spatial_extent.select(dbif)
start, end = granule.get_valid_time()
where = create_temporal_relation_sql_where_statement(start, end, use_start, \
use_during, use_overlap, use_contain, use_equal)
- rows = self.get_registered_maps("id", where, "start_time", dbif)
+ maps = self.get_registered_maps_as_objects(where, "start_time", dbif)
result = {}
result["granule"] = granule
- maplist = None
+ num_samples = 0
+ maplist = []
- if rows:
- maplist = []
- for row in rows:
- map = self.get_new_map_instance(row["id"])
+ if maps:
+ for map in maps:
+ # Read the spatial extent
+ if spatial == True:
+ map.spatial_extent.select(dbif)
+ # Ignore spatial disjoint maps
+ if not granule.spatial_overlapping(map):
+ continue
- if self.is_time_absolute():
- map.set_absolute_time(start, end)
- elif self.is_time_relative():
- map.set_relative_time(start, end, self.get_relative_time_unit())
-
+ num_samples += 1
maplist.append(copy.copy(map))
- result["samples"] = maplist
- else:
- maplist = []
+
+ # Fill with empty map in case no spatio-temporal relations found
+ if not maps or num_samples == 0:
map = self.get_new_map_instance(None)
if self.is_time_absolute():
@@ -552,8 +528,9 @@
map.set_relative_time(start, end, self.get_relative_time_unit())
maplist.append(copy.copy(map))
- result["samples"] = maplist
+ result["samples"] = maplist
+
obj_list.append(copy.copy(result))
if connect == True:
Modified: grass/trunk/lib/python/temporal/space_time_datasets.py
===================================================================
--- grass/trunk/lib/python/temporal/space_time_datasets.py 2012-03-22 10:28:16 UTC (rev 51141)
+++ grass/trunk/lib/python/temporal/space_time_datasets.py 2012-03-22 12:21:11 UTC (rev 51142)
@@ -64,6 +64,11 @@
"""Return the name of the C-module to set the time stamp in the file system"""
return "r.timestamp"
+ def spatial_overlapping(self, dataset):
+ """Return True if the spatial extents 2d overlap"""
+
+ return self.spatial_extent.overlap_2d(dataset.spatial_extent)
+
def reset(self, ident):
"""Reset the internal structure and set the identifier"""
self.ident = ident
@@ -142,6 +147,14 @@
"""Return the name of the C-module to set the time stamp in the file system"""
return "r3.timestamp"
+ def spatial_overlapping(self, dataset):
+ """Return True if the spatial extents overlap"""
+
+ if self.get_type() == dataset.get_type() or dataset.get_type() == "str3ds":
+ return self.spatial_extent.overlap(dataset.spatial_extent)
+ else:
+ return self.spatial_extent.overlap_2d(dataset.spatial_extent)
+
def reset(self, ident):
"""Reset the internal structure and set the identifier"""
self.ident = ident
@@ -228,6 +241,11 @@
"""Return the layer"""
return self.base.get_layer()
+ def spatial_overlapping(self, dataset):
+ """Return True if the spatial extents 2d overlap"""
+
+ return self.spatial_extent.overlap_2d(dataset.spatial_extent)
+
def reset(self, ident):
"""Reset the internal structure and set the identifier"""
self.ident = ident
@@ -288,6 +306,11 @@
"""Set the name of the map register table"""
self.metadata.set_raster_register(name)
+ def spatial_overlapping(self, dataset):
+ """Return True if the spatial extents 2d overlap"""
+
+ return self.spatial_extent.overlap_2d(dataset.spatial_extent)
+
def reset(self, ident):
"""Reset the internal structure and set the identifier"""
@@ -332,6 +355,14 @@
"""Set the name of the map register table"""
self.metadata.set_raster3d_register(name)
+ def spatial_overlapping(self, dataset):
+ """Return True if the spatial extents overlap"""
+
+ if self.get_type() == dataset.get_type() or dataset.get_type() == "rast3d":
+ return self.spatial_extent.overlap(dataset.spatial_extent)
+ else:
+ return self.spatial_extent.overlap_2d(dataset.spatial_extent)
+
def reset(self, ident):
"""Reset the internal structure and set the identifier"""
@@ -376,6 +407,11 @@
"""Set the name of the map register table"""
self.metadata.set_vector_register(name)
+ def spatial_overlapping(self, dataset):
+ """Return True if the spatial extents 2d overlap"""
+
+ return self.spatial_extent.overlap_2d(dataset.spatial_extent)
+
def reset(self, ident):
"""Reset the internal structure and set the identifier"""
Modified: grass/trunk/lib/python/temporal/space_time_datasets_tools.py
===================================================================
--- grass/trunk/lib/python/temporal/space_time_datasets_tools.py 2012-03-22 10:28:16 UTC (rev 51141)
+++ grass/trunk/lib/python/temporal/space_time_datasets_tools.py 2012-03-22 12:21:11 UTC (rev 51142)
@@ -465,8 +465,8 @@
###############################################################################
-def sample_stds_by_stds_topology(intype, sampletype, input, sampler, header, separator, method):
- """ Sample the input space time dataset with a sample space time dataset and print the result to stdout
+def sample_stds_by_stds_topology(intype, sampletype, inputs, sampler, header, separator, method, spatial=False):
+ """ Sample the input space time datasets with a sample space time dataset and print the result to stdout
In case multiple maps are located in the current granule, the map names are separated by comma.
@@ -480,67 +480,82 @@
@param sampler: Name of a space time dataset used for temporal sampling
@param header: Set True to print column names
@param separator: The field separator character between the columns
- @param method: The method to be used for sampling (start,during,contain,overlap,equal)
+ @param method: The method to be used for temporal sampling (start,during,contain,overlap,equal)
+ @param spatial: Perform spatial overlapping check
"""
mapset = core.gisenv()["MAPSET"]
- print intype, sampletype
+ input_list = inputs.split(",")
+ sts = []
- if input.find("@") >= 0:
- id = input
- else:
- id = input + "@" + mapset
+ for input in input_list:
+ if input.find("@") >= 0:
+ id = input
+ else:
+ id = input + "@" + mapset
- sp = dataset_factory(intype, id)
+ st = dataset_factory(intype, id)
+ sts.append(st)
if sampler.find("@") >= 0:
sid = sampler
else:
sid = sampler + "@" + mapset
- ssp = dataset_factory(sampletype, sid)
+ sst = dataset_factory(sampletype, sid)
dbif = sql_database_interface()
dbif.connect()
- if sp.is_in_db(dbif) == False:
- core.fatal(_("Dataset <%s> not found in temporal database") % (id))
+ for st in sts:
+ if st.is_in_db(dbif) == False:
+ core.fatal(_("Dataset <%s> not found in temporal database") % (id))
+ st.select(dbif)
- if ssp.is_in_db(dbif) == False:
+ if sst.is_in_db(dbif) == False:
core.fatal(_("Dataset <%s> not found in temporal database") % (sid))
- sp.select(dbif)
- ssp.select(dbif)
+ sst.select(dbif)
if separator == None or separator == "" or separator.find(",") >= 0:
separator = " | "
- mapmatrix = sp.sample_by_dataset_topology(ssp, method, dbif)
+ mapmatrizes = []
+ for st in sts:
+ mapmatrix = st.sample_by_dataset(sst, method, spatial, dbif)
+ if mapmatrix and len(mapmatrix) > 0:
+ mapmatrizes.append(mapmatrix)
- if mapmatrix and len(mapmatrix) > 0:
+ if len(mapmatrizes) > 0:
if header:
string = ""
- string += "%s%s" % ("sample_id", separator)
- string += "%s%s" % ("ids", separator)
+ string += "%s%s" % (sst.get_id(), separator)
+ for st in sts:
+ string += "%s%s" % (st.get_id(), separator)
string += "%s%s" % ("start_time", separator)
string += "%s%s" % ("end_time", separator)
string += "%s%s" % ("interval_length", separator)
string += "%s" % ("distance_from_begin")
print string
- first_time, dummy = mapmatrix[0]["granule"].get_valid_time()
+ first_time, dummy = mapmatrizes[0][0]["granule"].get_valid_time()
- for entry in mapmatrix:
- mapnames = ""
- count = 0
- for sample in entry["samples"]:
- if count == 0:
- mapnames += str(sample.get_id())
- else:
- mapnames += ",%s" % str(sample.get_id())
- count += 1
-
+ for i in range(len(mapmatrizes[0])):
+ mapname_list = []
+ for mapmatrix in mapmatrizes:
+ mapnames = ""
+ count = 0
+ entry = mapmatrix[i]
+ for sample in entry["samples"]:
+ if count == 0:
+ mapnames += str(sample.get_id())
+ else:
+ mapnames += ",%s" % str(sample.get_id())
+ count += 1
+ mapname_list.append(mapnames)
+
+ entry = mapmatrizes[0][i]
map = entry["granule"]
start, end = map.get_valid_time()
@@ -557,7 +572,8 @@
string = ""
string += "%s%s" % (map.get_id(), separator)
- string += "%s%s" % (mapnames, separator)
+ for mapnames in mapname_list:
+ string += "%s%s" % (mapnames, separator)
string += "%s%s" % (start, separator)
string += "%s%s" % (end, separator)
string += "%s%s" % (delta, separator)
Modified: grass/trunk/lib/python/temporal/spatial_extent.py
===================================================================
--- grass/trunk/lib/python/temporal/spatial_extent.py 2012-03-22 10:28:16 UTC (rev 51141)
+++ grass/trunk/lib/python/temporal/spatial_extent.py 2012-03-22 12:21:11 UTC (rev 51142)
@@ -31,25 +31,493 @@
self.set_spatial_extent(north, south, east, west, top, bottom)
self.set_projection(proj)
- def overlap_2d(self, extent):
- """Return True if the 2d extents overlap. Code is lend from wind_overlap.c in lib/gis"""
+ 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 overlap_2d for spatial extents"))
+ 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
+ """
+
+ 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_proj() == "LL":
+ 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 = spatial_extent(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.
+ """
+
+ 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
+
+ _____
+ |A _ |
+ | |_| |
+ |_____|
+
+ """
+ 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 """
+ 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
+ _____ _____ _____ _____
+ |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
+
+ 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
+ _____
+ |A __|__
+ | | | B|
+ |__|__| |
+ |_____|
+
+ 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
@@ -57,7 +525,13 @@
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
@@ -67,14 +541,60 @@
return True
def overlap(self, extent):
- """Return True if the extents overlap."""
+ """Return True if the three dimensional extents overlap
- if self.overlap_2d(extent) == False:
- return False
-
+ 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
@@ -82,7 +602,238 @@
return False
return True
+
+ def meet_2d(self,extent):
+ """ Check if self and extent meet each other in two dimensions
+ _____ _____ _____ _____
+ | A | B | | B | A |
+ |_____| | | | |
+ |_____| |_____|_____|
+
+ ___
+ | A |
+ | |
+ |___| _____
+ | B | | B |
+ | | | |
+ |_____| |_____|_
+ | A |
+ | |
+ |_____|
+
+ """
+
+ 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 touch meet 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 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
+ """
+
+ 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
+ """
+
+ 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"""
Modified: grass/trunk/lib/python/temporal/temporal_extent.py
===================================================================
--- grass/trunk/lib/python/temporal/temporal_extent.py 2012-03-22 10:28:16 UTC (rev 51141)
+++ grass/trunk/lib/python/temporal/temporal_extent.py 2012-03-22 12:21:11 UTC (rev 51142)
@@ -34,119 +34,119 @@
self.set_start_time(start_time)
self.set_end_time(end_time)
- def starts(self, map):
+ def starts(self, extent):
"""Return True if this time object starts at the start of the provided time object and finishes within it
A |-----|
B |---------|
"""
- if self.D["end_time"] == None or map.D["end_time"] == None :
+ if self.D["end_time"] == None or extent.D["end_time"] == None :
return False
- if self.D["start_time"] == map.D["start_time"] and self.D["end_time"] < map.D["end_time"]:
+ if self.D["start_time"] == extent.D["start_time"] and self.D["end_time"] < extent.D["end_time"]:
return True
else:
return False
- def started(self, map):
+ def started(self, extent):
"""Return True if this time object is started at the start of the provided time object
A |---------|
B |-----|
"""
- if self.D["end_time"] == None or map.D["end_time"] == None :
+ if self.D["end_time"] == None or extent.D["end_time"] == None :
return False
- if self.D["start_time"] == map.D["start_time"] and self.D["end_time"] > map.D["end_time"]:
+ if self.D["start_time"] == extent.D["start_time"] and self.D["end_time"] > extent.D["end_time"]:
return True
else:
return False
- def finishes(self, map):
+ def finishes(self, extent):
"""Return True if this time object finishes at the end and within of the provided time object
A |-----|
B |---------|
"""
- if self.D["end_time"] == None or map.D["end_time"] == None :
+ if self.D["end_time"] == None or extent.D["end_time"] == None :
return False
- if self.D["end_time"] == map.D["end_time"] and self.D["start_time"] > map.D["start_time"] :
+ if self.D["end_time"] == extent.D["end_time"] and self.D["start_time"] > extent.D["start_time"] :
return True
else:
return False
- def finished(self, map):
+ def finished(self, extent):
"""Return True if this time object finished at the end of the provided time object
A |---------|
B |-----|
"""
- if self.D["end_time"] == None or map.D["end_time"] == None :
+ if self.D["end_time"] == None or extent.D["end_time"] == None :
return False
- if self.D["end_time"] == map.D["end_time"] and self.D["start_time"] < map.D["start_time"] :
+ if self.D["end_time"] == extent.D["end_time"] and self.D["start_time"] < extent.D["start_time"] :
return True
else:
return False
- def after(self, map):
+ def after(self, extent):
"""Return True if this time object is temporal located after the provided time object
A |---------|
B |---------|
"""
- if map.D["end_time"] == None:
- if self.D["start_time"] > map.D["start_time"]:
+ if extent.D["end_time"] == None:
+ if self.D["start_time"] > extent.D["start_time"]:
return True
else:
return False
- if self.D["start_time"] > map.D["end_time"]:
+ if self.D["start_time"] > extent.D["end_time"]:
return True
else:
return False
- def before(self, map):
+ def before(self, extent):
"""Return True if this time object is temporal located before the provided time object
A |---------|
B |---------|
"""
if self.D["end_time"] == None:
- if self.D["start_time"] < map.D["start_time"]:
+ if self.D["start_time"] < extent.D["start_time"]:
return True
else:
return False
- if self.D["end_time"] < map.D["start_time"]:
+ if self.D["end_time"] < extent.D["start_time"]:
return True
else:
return False
- def adjacent(self, map):
+ def adjacent(self, extent):
"""Return True if this time object is a meeting neighbour the provided time object
A |---------|
B |---------|
A |---------|
B |---------|
"""
- if self.D["end_time"] == None and map.D["end_time"] == None :
+ if self.D["end_time"] == None and extent.D["end_time"] == None :
return False
- if (self.D["start_time"] == map.D["end_time"]) or (self.D["end_time"] == map.D["start_time"]):
+ if (self.D["start_time"] == extent.D["end_time"]) or (self.D["end_time"] == extent.D["start_time"]):
return True
else:
return False
- def follows(self, map):
+ def follows(self, extent):
"""Return True if this time object is temporal follows the provided time object
A |---------|
B |---------|
"""
- if map.D["end_time"] == None :
+ if extent.D["end_time"] == None :
return False
- if self.D["start_time"] == map.D["end_time"]:
+ if self.D["start_time"] == extent.D["end_time"]:
return True
else:
return False
- def precedes(self, map):
+ def precedes(self, extent):
"""Return True if this time object is temporal precedes the provided time object
A |---------|
B |---------|
@@ -154,33 +154,33 @@
if self.D["end_time"] == None:
return False
- if self.D["end_time"] == map.D["start_time"]:
+ if self.D["end_time"] == extent.D["start_time"]:
return True
else:
return False
- def during(self, map):
+ def during(self, extent):
"""Return True if this time object is temporal located during the provided time object
A |-------|
B |---------|
"""
# Check single point of time in interval
- if map.D["end_time"] == None:
+ if extent.D["end_time"] == None:
return False
# Check single point of time in interval
if self.D["end_time"] == None:
- if self.D["start_time"] > map.D["start_time"] and self.D["start_time"] < map.D["end_time"]:
+ if self.D["start_time"] > extent.D["start_time"] and self.D["start_time"] < extent.D["end_time"]:
return True
else:
return False
- if self.D["start_time"] > map.D["start_time"] and self.D["end_time"] < map.D["end_time"]:
+ if self.D["start_time"] > extent.D["start_time"] and self.D["end_time"] < extent.D["end_time"]:
return True
else:
return False
- def contains(self, map):
+ def contains(self, extent):
"""Return True if this time object contains the provided time object
A |---------|
B |-------|
@@ -190,65 +190,65 @@
return False
# Check single point of time in interval
- if map.D["end_time"] == None:
- if self.D["start_time"] < map.D["start_time"] and self.D["end_time"] > map.D["start_time"]:
+ if extent.D["end_time"] == None:
+ if self.D["start_time"] < extent.D["start_time"] and self.D["end_time"] > extent.D["start_time"]:
return True
else:
return False
- if self.D["start_time"] < map.D["start_time"] and self.D["end_time"] > map.D["end_time"]:
+ if self.D["start_time"] < extent.D["start_time"] and self.D["end_time"] > extent.D["end_time"]:
return True
else:
return False
- def equivalent(self, map):
+ def equivalent(self, extent):
"""Return True if this time object is temporal located equivalent the provided time object
A |---------|
B |---------|
"""
- if self.D["end_time"] == None and map.D["end_time"] == None :
- if self.D["start_time"] == map.D["start_time"]:
+ if self.D["end_time"] == None and extent.D["end_time"] == None :
+ if self.D["start_time"] == extent.D["start_time"]:
return True
else:
return False
- if self.D["end_time"] == None or map.D["end_time"] == None :
+ if self.D["end_time"] == None or extent.D["end_time"] == None :
return False
- if self.D["start_time"] == map.D["start_time"] and self.D["end_time"] == map.D["end_time"]:
+ if self.D["start_time"] == extent.D["start_time"] and self.D["end_time"] == extent.D["end_time"]:
return True
else:
return False
- def overlaps(self, map):
+ def overlaps(self, extent):
"""Return True if this time object is temporal overlaps the provided time object
A |---------|
B |---------|
"""
- if self.D["end_time"] == None or map.D["end_time"] == None :
+ if self.D["end_time"] == None or extent.D["end_time"] == None :
return False
- if self.D["start_time"] < map.D["start_time"] and self.D["end_time"] < map.D["end_time"] and\
- self.D["end_time"] > map.D["start_time"]:
+ if self.D["start_time"] < extent.D["start_time"] and self.D["end_time"] < extent.D["end_time"] and\
+ self.D["end_time"] > extent.D["start_time"]:
return True
else:
return False
- def overlapped(self, map):
+ def overlapped(self, extent):
"""Return True if this time object is temporal overlapped by the provided time object
A |---------|
B |---------|
"""
- if self.D["end_time"] == None or map.D["end_time"] == None :
+ if self.D["end_time"] == None or extent.D["end_time"] == None :
return False
- if self.D["start_time"] > map.D["start_time"] and self.D["end_time"] > map.D["end_time"] and\
- self.D["start_time"] < map.D["end_time"]:
+ if self.D["start_time"] > extent.D["start_time"] and self.D["end_time"] > extent.D["end_time"] and\
+ self.D["start_time"] < extent.D["end_time"]:
return True
else:
return False
- def temporal_relation(self, map):
+ def temporal_relation(self, extent):
"""Returns the temporal relation between temporal objects
Temporal relationships are implemented after [Allen and Ferguson 1994 Actions and Events in Interval Temporal Logic]
"""
@@ -258,39 +258,39 @@
return None
if not self.D.has_key("end_time"):
return None
- if not map.D.has_key("start_time"):
+ if not extent.D.has_key("start_time"):
return None
- if not map.D.has_key("end_time"):
+ if not extent.D.has_key("end_time"):
return None
- if self.D["start_time"] == None or map.D["start_time"] == None:
+ if self.D["start_time"] == None or extent.D["start_time"] == None:
return None
- if self.equivalent(map):
+ if self.equivalent(extent):
return "equivalent"
- if self.during(map):
+ if self.during(extent):
return "during"
- if self.contains(map):
+ if self.contains(extent):
return "contains"
- if self.overlaps(map):
+ if self.overlaps(extent):
return "overlaps"
- if self.overlapped(map):
+ if self.overlapped(extent):
return "overlapped"
- if self.after(map):
+ if self.after(extent):
return "after"
- if self.before(map):
+ if self.before(extent):
return "before"
- if self.starts(map):
+ if self.starts(extent):
return "starts"
- if self.finishes(map):
+ if self.finishes(extent):
return "finishes"
- if self.started(map):
+ if self.started(extent):
return "started"
- if self.finished(map):
+ if self.finished(extent):
return "finished"
- if self.follows(map):
+ if self.follows(extent):
return "follows"
- if self.precedes(map):
+ if self.precedes(extent):
return "precedes"
return None
@@ -300,11 +300,11 @@
self.D["id"] = ident
def set_start_time(self, start_time):
- """Set the valid start time of the map"""
+ """Set the valid start time of the extent"""
self.D["start_time"] = start_time
def set_end_time(self, end_time):
- """Set the valid end time of the map"""
+ """Set the valid end time of the extent"""
self.D["end_time"] = end_time
def get_id(self):
@@ -317,7 +317,7 @@
return None
def get_start_time(self):
- """Get the valid start time of the map
+ """Get the valid start time of the extent
@return None if not found"""
if self.D.has_key("start_time"):
return self.D["start_time"]
@@ -325,7 +325,7 @@
return None
def get_end_time(self):
- """Get the valid end time of the map
+ """Get the valid end time of the extent
@return None if not found"""
if self.D.has_key("end_time"):
return self.D["end_time"]
Modified: grass/trunk/lib/python/temporal/temporal_granularity.py
===================================================================
--- grass/trunk/lib/python/temporal/temporal_granularity.py 2012-03-22 10:28:16 UTC (rev 51141)
+++ grass/trunk/lib/python/temporal/temporal_granularity.py 2012-03-22 12:21:11 UTC (rev 51142)
@@ -26,7 +26,15 @@
###############################################################################
def compute_relative_time_granularity(maps):
- """ Compute the relative granularity"""
+ """ Compute the relative time granularity
+
+ Attention: The computation of the granularity is only correct in case of not
+ overlapping intervals. Hence a correct temporal topology is required for
+ computation.
+
+
+ @param maps: a ordered by start_time list of map objects
+ """
# The interval time must be scaled to days resolution
granularity = None
@@ -68,7 +76,16 @@
###############################################################################
-def compute_absolute_time_granularity(maps):
+def compute_absolute_time_granularity(maps):
+ """ Compute the absolute time granularity
+
+ Attention: The computation of the granularity is only correct in case of not
+ overlapping intervals. Hence a correct temporal topology is required for
+ computation.
+
+
+ @param maps: a ordered by start_time list of map objects
+ """
has_seconds = False
has_minutes = False
Modified: grass/trunk/lib/python/temporal/unit_tests.py
===================================================================
--- grass/trunk/lib/python/temporal/unit_tests.py 2012-03-22 10:28:16 UTC (rev 51141)
+++ grass/trunk/lib/python/temporal/unit_tests.py 2012-03-22 12:21:11 UTC (rev 51142)
@@ -570,7 +570,7 @@
for i in range(6):
end = start * fact
map = raster_dataset(None)
- map.set_relative_time(start, end)
+ map.set_relative_time(start, end, "years")
maps.append(map)
start = end
@@ -587,7 +587,7 @@
for i in range(10):
end = start * fact
map = raster_dataset(None)
- map.set_relative_time(start, end)
+ map.set_relative_time(start, end, "years")
maps.append(map)
start = end
@@ -972,3 +972,452 @@
gran = compute_absolute_time_granularity(maps)
if increment != gran:
core.error("Wrong granularity reference %s != gran %s" % (increment, gran))
+
+###############################################################################
+
+def test_spatial_extent_intersection():
+ # Generate the extents
+
+ A = spatial_extent(north=80, south=20, east=60, west=10, bottom=-50, top=50)
+ A.print_info()
+ B = spatial_extent(north=80, south=20, east=60, west=10, bottom=-50, top=50)
+ B.print_info()
+ C = A.intersect(B)
+ C.print_info()
+
+ if C.get_north() != B.get_north() or C.get_south() != B.get_south() or \
+ C.get_west() != B.get_west() or C.get_east() != B.get_east() or \
+ C.get_bottom() != B.get_bottom() or C.get_top() != B.get_top():
+ core.error("Wrong intersection computation")
+
+ B = spatial_extent(north=40, south=30, east=60, west=10, bottom=-50, top=50)
+ B.print_info()
+ C = A.intersect(B)
+ C.print_info()
+
+ if C.get_north() != B.get_north() or C.get_south() != B.get_south() or \
+ C.get_west() != B.get_west() or C.get_east() != B.get_east() or \
+ C.get_bottom() != B.get_bottom() or C.get_top() != B.get_top():
+ core.error("Wrong intersection computation")
+
+ B = spatial_extent(north=40, south=30, east=60, west=30, bottom=-50, top=50)
+ B.print_info()
+ C = A.intersect(B)
+ C.print_info()
+
+ if C.get_north() != B.get_north() or C.get_south() != B.get_south() or \
+ C.get_west() != B.get_west() or C.get_east() != B.get_east() or \
+ C.get_bottom() != B.get_bottom() or C.get_top() != B.get_top():
+ core.error("Wrong intersection computation")
+
+ B = spatial_extent(north=40, south=30, east=60, west=30, bottom=-30, top=50)
+ B.print_info()
+ C = A.intersect(B)
+ C.print_info()
+
+ if C.get_north() != B.get_north() or C.get_south() != B.get_south() or \
+ C.get_west() != B.get_west() or C.get_east() != B.get_east() or \
+ C.get_bottom() != B.get_bottom() or C.get_top() != B.get_top():
+ core.error("Wrong intersection computation")
+
+ B = spatial_extent(north=40, south=30, east=60, west=30, bottom=-30, top=30)
+ B.print_info()
+ C = A.intersect(B)
+ C.print_info()
+
+ if C.get_north() != B.get_north() or C.get_south() != B.get_south() or \
+ C.get_west() != B.get_west() or C.get_east() != B.get_east() or \
+ C.get_bottom() != B.get_bottom() or C.get_top() != B.get_top():
+ core.error("Wrong intersection computation")
+
+###############################################################################
+
+def test_spatial_relations():
+ # Generate the extents
+
+ A = spatial_extent(north=80, south=20, east=60, west=10, bottom=-50, top=50)
+ A.print_info()
+ B = spatial_extent(north=80, south=20, east=60, west=10, bottom=-50, top=50)
+ B.print_info()
+
+ relation = A.spatial_relation(B)
+ print relation
+ if relation!= "equivalent":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ B = spatial_extent(north=70, south=20, east=60, west=10, bottom=-50, top=50)
+ B.print_info()
+
+ relation = A.spatial_relation_2d(B)
+ print relation
+ if relation!= "cover":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ relation = A.spatial_relation(B)
+ print relation
+ if relation!= "cover":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ B = spatial_extent(north=70, south=30, east=60, west=10, bottom=-50, top=50)
+ B.print_info()
+
+ relation = A.spatial_relation_2d(B)
+ print relation
+ if relation!= "cover":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ relation = A.spatial_relation(B)
+ print relation
+ if relation!= "cover":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ relation = B.spatial_relation_2d(A)
+ print relation
+ if relation!= "covered":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ relation = B.spatial_relation(A)
+ print relation
+ if relation!= "covered":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ B = spatial_extent(north=70, south=30, east=50, west=10, bottom=-50, top=50)
+ B.print_info()
+
+ relation = A.spatial_relation_2d(B)
+ print relation
+ if relation!= "cover":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ relation = B.spatial_relation_2d(A)
+ print relation
+ if relation!= "covered":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ relation = A.spatial_relation(B)
+ print relation
+ if relation!= "cover":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ B = spatial_extent(north=70, south=30, east=50, west=20, bottom=-50, top=50)
+
+ relation = B.spatial_relation(A)
+ print relation
+ if relation!= "covered":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ B = spatial_extent(north=70, south=30, east=50, west=20, bottom=-50, top=50)
+ B.print_info()
+
+ relation = A.spatial_relation_2d(B)
+ print relation
+ if relation!= "contain":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ relation = A.spatial_relation(B)
+ print relation
+ if relation!= "cover":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ B = spatial_extent(north=70, south=30, east=50, west=20, bottom=-40, top=50)
+ B.print_info()
+
+ relation = A.spatial_relation(B)
+ print relation
+ if relation!= "cover":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ B = spatial_extent(north=70, south=30, east=50, west=20, bottom=-40, top=40)
+ B.print_info()
+
+ relation = A.spatial_relation(B)
+ print relation
+ if relation!= "contain":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ relation = B.spatial_relation(A)
+ print relation
+ if relation!= "in":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ B = spatial_extent(north=90, south=30, east=50, west=20, bottom=-40, top=40)
+ B.print_info()
+
+ relation = A.spatial_relation_2d(B)
+ print relation
+ if relation!= "overlap":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ relation = A.spatial_relation(B)
+ print relation
+ if relation!= "overlap":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ B = spatial_extent(north=90, south=5, east=70, west=5, bottom=-40, top=40)
+ A.print_info()
+ B.print_info()
+
+ relation = A.spatial_relation_2d(B)
+ print relation
+ if relation!= "in":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ relation = A.spatial_relation(B)
+ print relation
+ if relation!= "overlap":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ B = spatial_extent(north=90, south=5, east=70, west=5, bottom=-40, top=60)
+ A.print_info()
+ B.print_info()
+
+ relation = A.spatial_relation(B)
+ print relation
+ if relation!= "overlap":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+
+ B = spatial_extent(north=90, south=5, east=70, west=5, bottom=-60, top=60)
+ A.print_info()
+ B.print_info()
+
+ relation = A.spatial_relation(B)
+ print relation
+ if relation!= "in":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ A = spatial_extent(north=80, south=60, east=60, west=10, bottom=-50, top=50)
+ A.print_info()
+ B = spatial_extent(north=60, south=20, east=60, west=10, bottom=-50, top=50)
+ B.print_info()
+
+ relation = A.spatial_relation_2d(B)
+ print relation
+ if relation!= "meet":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ relation = A.spatial_relation(B)
+ print relation
+ if relation!= "meet":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ A = spatial_extent(north=60, south=40, east=60, west=10, bottom=-50, top=50)
+ A.print_info()
+ B = spatial_extent(north=80, south=60, east=60, west=10, bottom=-50, top=50)
+ B.print_info()
+
+ relation = A.spatial_relation_2d(B)
+ print relation
+ if relation!= "meet":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ relation = A.spatial_relation(B)
+ print relation
+ if relation!= "meet":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ A = spatial_extent(north=80, south=40, east=60, west=40, bottom=-50, top=50)
+ A.print_info()
+ B = spatial_extent(north=80, south=40, east=40, west=20, bottom=-50, top=50)
+ B.print_info()
+
+ relation = A.spatial_relation_2d(B)
+ print relation
+ if relation!= "meet":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ relation = A.spatial_relation(B)
+ print relation
+ if relation!= "meet":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ A = spatial_extent(north=80, south=40, east=40, west=20, bottom=-50, top=50)
+ A.print_info()
+ B = spatial_extent(north=90, south=30, east=60, west=40, bottom=-50, top=50)
+ B.print_info()
+
+ relation = A.spatial_relation_2d(B)
+ print relation
+ if relation!= "meet":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ relation = A.spatial_relation(B)
+ print relation
+ if relation!= "meet":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ A = spatial_extent(north=80, south=40, east=40, west=20, bottom=-50, top=50)
+ A.print_info()
+ B = spatial_extent(north=70, south=50, east=60, west=40, bottom=-50, top=50)
+ B.print_info()
+
+ relation = A.spatial_relation_2d(B)
+ print relation
+ if relation!= "meet":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ relation = A.spatial_relation(B)
+ print relation
+ if relation!= "meet":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ A = spatial_extent(north=80, south=40, east=40, west=20, bottom=-50, top=50)
+ A.print_info()
+ B = spatial_extent(north=60, south=20, east=60, west=40, bottom=-50, top=50)
+ B.print_info()
+
+ relation = A.spatial_relation_2d(B)
+ print relation
+ if relation!= "meet":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ relation = A.spatial_relation(B)
+ print relation
+ if relation!= "meet":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ A = spatial_extent(north=80, south=40, east=40, west=20, bottom=-50, top=50)
+ A.print_info()
+ B = spatial_extent(north=40, south=20, east=60, west=40, bottom=-50, top=50)
+ B.print_info()
+
+ relation = A.spatial_relation_2d(B)
+ print relation
+ if relation!= "disjoint":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ relation = A.spatial_relation(B)
+ print relation
+ if relation!= "disjoint":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ A = spatial_extent(north=80, south=40, east=40, west=20, bottom=-50, top=50)
+ A.print_info()
+ B = spatial_extent(north=60, south=20, east=60, west=40, bottom=-60, top=60)
+ B.print_info()
+
+ relation = A.spatial_relation(B)
+ print relation
+ if relation!= "meet":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ A = spatial_extent(north=80, south=40, east=40, west=20, bottom=-50, top=50)
+ A.print_info()
+ B = spatial_extent(north=90, south=30, east=60, west=40, bottom=-40, top=40)
+ B.print_info()
+
+ relation = A.spatial_relation(B)
+ print relation
+ if relation!= "meet":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ A = spatial_extent(north=80, south=40, east=60, west=20, bottom=0, top=50)
+ A.print_info()
+ B = spatial_extent(north=80, south=40, east=60, west=20, bottom=-50, top=0)
+ B.print_info()
+
+ relation = A.spatial_relation(B)
+ print relation
+ if relation!= "meet":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ A = spatial_extent(north=80, south=40, east=60, west=20, bottom=0, top=50)
+ A.print_info()
+ B = spatial_extent(north=80, south=50, east=60, west=30, bottom=-50, top=0)
+ B.print_info()
+
+ relation = A.spatial_relation(B)
+ print relation
+ if relation!= "meet":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ A = spatial_extent(north=80, south=40, east=60, west=20, bottom=0, top=50)
+ A.print_info()
+ B = spatial_extent(north=70, south=50, east=50, west=30, bottom=-50, top=0)
+ B.print_info()
+
+ relation = A.spatial_relation(B)
+ print relation
+ if relation!= "meet":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ A = spatial_extent(north=80, south=40, east=60, west=20, bottom=0, top=50)
+ A.print_info()
+ B = spatial_extent(north=90, south=30, east=70, west=10, bottom=-50, top=0)
+ B.print_info()
+
+ relation = A.spatial_relation(B)
+ print relation
+ if relation!= "meet":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ A = spatial_extent(north=80, south=40, east=60, west=20, bottom=0, top=50)
+ A.print_info()
+ B = spatial_extent(north=70, south=30, east=50, west=10, bottom=-50, top=0)
+ B.print_info()
+
+ relation = A.spatial_relation(B)
+ print relation
+ if relation!= "meet":
+ core.error("Wrong spatial relation: %s"%(relation))
+ ###
+
+ A = spatial_extent(north=80, south=40, east=60, west=20, bottom=-50, top=0)
+ A.print_info()
+ B = spatial_extent(north=80, south=40, east=60, west=20, bottom=0, top=50)
+ B.print_info()
+
+ relation = A.spatial_relation(B)
+ print relation
+ if relation!= "meet":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ A = spatial_extent(north=80, south=40, east=60, west=20, bottom=-50, top=0)
+ A.print_info()
+ B = spatial_extent(north=80, south=50, east=60, west=30, bottom=0, top=50)
+ B.print_info()
+
+ relation = A.spatial_relation(B)
+ print relation
+ if relation!= "meet":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ A = spatial_extent(north=80, south=40, east=60, west=20, bottom=-50, top=0)
+ A.print_info()
+ B = spatial_extent(north=70, south=50, east=50, west=30, bottom=0, top=50)
+ B.print_info()
+
+ relation = A.spatial_relation(B)
+ print relation
+ if relation!= "meet":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ A = spatial_extent(north=80, south=40, east=60, west=20, bottom=-50, top=0)
+ A.print_info()
+ B = spatial_extent(north=90, south=30, east=70, west=10, bottom=0, top=50)
+ B.print_info()
+
+ relation = A.spatial_relation(B)
+ print relation
+ if relation!= "meet":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+ A = spatial_extent(north=80, south=40, east=60, west=20, bottom=-50, top=0)
+ A.print_info()
+ B = spatial_extent(north=70, south=30, east=50, west=10, bottom=0, top=50)
+ B.print_info()
+
+ relation = A.spatial_relation(B)
+ print relation
+ if relation!= "meet":
+ core.error("Wrong spatial relation: %s"%(relation))
+
+if __name__ == "__main__":
+ test_increment_datetime_by_string()
+ test_adjust_datetime_to_granularity()
+ test_spatial_extent_intersection()
+ #test_compute_relative_time_granularity()
+ test_compute_absolute_time_granularity()
+ test_compute_datetime_delta()
+ test_spatial_extent_intersection()
+ test_spatial_relations()
More information about the grass-commit
mailing list