|
| 1 | +# -*- coding: utf-8 -*- |
| 2 | +from __future__ import print_function, division |
| 3 | +from numpy import isnan |
| 4 | +from qsrlib_qsrs.qsr_dyadic_abstractclass import QSR_Dyadic_1t_Abstractclass |
| 5 | + |
| 6 | + |
| 7 | +class QSR_RA(QSR_Dyadic_1t_Abstractclass): |
| 8 | + """Regional Algebra. |
| 9 | +
|
| 10 | + Members: |
| 11 | + * _unique_id: "ra" |
| 12 | + * _all_possible_relations: ("<", ">", "m", "mi", "o", "oi", "s", "si", "d", "di", "f", "fi", "=") |
| 13 | + * _dtype: "bounding_boxes" |
| 14 | +
|
| 15 | + Some explanation about the QSR. Maybe a reference if it exists. |
| 16 | + """ |
| 17 | + |
| 18 | + _unique_id = "ra" |
| 19 | + """str: Unique identifier name of the QSR.""" |
| 20 | + |
| 21 | + _all_possible_relations = ("<", ">", "m", "mi", "o", "oi", "s", "si", "d", "di", "f", "fi", "=") |
| 22 | + """tuple: All possible relations of the QSR.""" |
| 23 | + |
| 24 | + _dtype = "bounding_boxes" |
| 25 | + """str: On what kind of data the QSR works with.""" |
| 26 | + |
| 27 | + _inverse_map = {"<": ">", "m": "mi", "o": "oi", "s": "si", "d": "di", "f": "fi", |
| 28 | + ">": "<", "mi": "m", "o1": "o", "si": "s", "di": "d", "fi": "f"} |
| 29 | + """dict: Inverse relations""" |
| 30 | + |
| 31 | + def __init__(self): |
| 32 | + """Constructor. |
| 33 | +
|
| 34 | + :return: |
| 35 | + """ |
| 36 | + super(QSR_RA, self).__init__() |
| 37 | + |
| 38 | + def _compute_qsr(self, bb1, bb2, qsr_params, **kwargs): |
| 39 | + """Compute QSR value. |
| 40 | +
|
| 41 | + :param bb1: First object's bounding box. |
| 42 | + :type bb2: tuple or list |
| 43 | + :param bb2: Second object's bounding box. |
| 44 | + :type bb2: tuple or list |
| 45 | + :param qsr_params: QSR specific parameters passed in `dynamic_args`. |
| 46 | + :type qsr_params: dict |
| 47 | + :param kwargs: Optional further arguments. |
| 48 | + :return: The computed QSR value: two/three comma separated Allen relations for 2D/3D. |
| 49 | + :rtype: str |
| 50 | + """ |
| 51 | + if len(bb1) == 4 and len(bb2) == 4: # 2D version |
| 52 | + return ",".join([self.__allen((bb1[0], bb1[2]), (bb2[0], bb2[2])), |
| 53 | + self.__allen((bb1[1], bb1[3]), (bb2[1], bb2[3]))]) |
| 54 | + elif len(bb1) == 6 and len(bb2) == 6: # 3D version |
| 55 | + return ",".join([self.__allen((bb1[0], bb1[3]), (bb2[0], bb2[3])), |
| 56 | + self.__allen((bb1[1], bb1[4]), (bb2[1], bb2[4])), |
| 57 | + self.__allen((bb1[2], bb1[5]), (bb2[2], bb2[5]))]) |
| 58 | + else: |
| 59 | + raise ValueError("bb1 and bb2 must have length of 4 (2D) or 6 (3D)") |
| 60 | + |
| 61 | + def __allen(self, i1, i2): |
| 62 | + if isnan(i1).any() or isnan(i2).any(): # nan values cause dragons |
| 63 | + raise ValueError("illegal 'nan' values found") |
| 64 | + |
| 65 | + if i1[1] < i2[0]: |
| 66 | + return "<" |
| 67 | + if i1[1] == i2[0]: |
| 68 | + return "m" |
| 69 | + if i1[0] < i2[0] < i1[1] and i2[0] < i1[1] < i2[1]: |
| 70 | + return "o" |
| 71 | + if i1[0] == i2[0] and i1[1] < i2[1]: |
| 72 | + return "s" |
| 73 | + if i2[0] < i1[0] < i2[1] and i2[0] < i1[1] < i2[1]: |
| 74 | + return "d" |
| 75 | + if i2[0] < i1[0] < i2[1] and i1[1] == i2[1]: |
| 76 | + return "f" |
| 77 | + if i1[0] == i2[0] and i1[1] == i2[1]: |
| 78 | + return "=" |
| 79 | + return self._inverse_map[self.__allen(i2, i1)] |
0 commit comments