Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added qfactor compensation on RA, also made RA3D #221

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/rsts/api/qsrlib_io.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ Submodules

.. toctree::

qsrlib_io.world_trace
qsrlib_io.world_qsr_trace
qsrlib_io.world_trace

Module contents
---------------
Expand Down
7 changes: 7 additions & 0 deletions docs/rsts/api/qsrlib_qsrs.qsr_ra3d.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
qsrlib_qsrs.qsr_ra3d module
===========================

.. automodule:: qsrlib_qsrs.qsr_ra3d
:members:
:undoc-members:
:show-inheritance:
7 changes: 7 additions & 0 deletions docs/rsts/api/qsrlib_qsrs.qsr_ra_abstract.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
qsrlib_qsrs.qsr_ra_abstract module
==================================

.. automodule:: qsrlib_qsrs.qsr_ra_abstract
:members:
:undoc-members:
:show-inheritance:
2 changes: 2 additions & 0 deletions docs/rsts/api/qsrlib_qsrs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ Submodules
qsrlib_qsrs.qsr_qtc_c_simplified
qsrlib_qsrs.qsr_qtc_simplified_abstractclass
qsrlib_qsrs.qsr_ra
qsrlib_qsrs.qsr_ra3d
qsrlib_qsrs.qsr_ra_abstract
qsrlib_qsrs.qsr_rcc2
qsrlib_qsrs.qsr_rcc3_rectangle_bounding_boxes_2d
qsrlib_qsrs.qsr_rcc4
Expand Down
2 changes: 2 additions & 0 deletions docs/rsts/handwritten/qsrs/qsrs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ Currently, the following QSRs are supported:
+----------------+---------------------------------------------------+---------------------------------------------------------------------------------------------------------+----------------+
| **ra** | Rectangle Algebra | :doc:`descr. <ra>` \| :mod:`api <qsrlib_qsrs.qsr_ra>` | [5]_ |
+----------------+---------------------------------------------------+---------------------------------------------------------------------------------------------------------+----------------+
| **ra3d** | Rectangle Algebra 3D | :doc:`descr. <ra>` \| :mod:`api <qsrlib_qsrs.qsr_ra3d>` | [5]_ |
+----------------+---------------------------------------------------+---------------------------------------------------------------------------------------------------------+----------------+
| **rcc2** | Region Connection Calculus 2 | :doc:`descr. <rcc2>` \| :mod:`api <qsrlib_qsrs.qsr_rcc2>` | [2]_ [3]_ |
+----------------+---------------------------------------------------+---------------------------------------------------------------------------------------------------------+----------------+
| **rcc3** | Region Connection Calculus 3 | :doc:`descr. <rcc3>` \| :mod:`api <qsrlib_qsrs.qsr_rcc3_rectangle_bounding_boxes_2d>` | [2]_ [3]_ |
Expand Down
2 changes: 1 addition & 1 deletion docs/rsts/handwritten/qsrs/ra.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ of two rectangles.
API
---

The API can be found :mod:`here <qsrlib_qsrs.qsr_ra>`.
The API for RA can be found in the following links: :mod:`2D version<qsrlib_qsrs.qsr_ra>` | :mod:`3D version <qsrlib_qsrs.qsr_ra3d>`.


References
Expand Down
17 changes: 17 additions & 0 deletions qsr_lib/src/qsrlib_io/world_trace.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,23 @@ def return_bounding_box_2d(self, xsize_minimal=0, ysize_minimal=0):
ysize = ysize_minimal if isnan(self.ysize) else self.ysize
return [self.x-xsize/2, self.y-ysize/2, self.x+xsize/2, self.y+ysize/2]

def return_bounding_box_3d(self, xsize_minimal=0, ysize_minimal=0, zsize_minimal=0):
"""Compute the 3D bounding box of the object.

:param xsize_minimal: If object has no x-size (i.e. a point) then compute bounding box based on this minimal x-size.
:type xsize_minimal: positive int or float
:param ysize_minimal: If object has no y-size (i.e. a point) then compute bounding box based on this minimal y-size.
:type ysize_minimal: positive int or float
:param zsize_minimal: If object has no z-size (i.e. a point) then compute bounding box based on this minimal z-size.
:type zsize_minimal: positive int or float
:return: The 3D coordinates of the first (closest to origin) and third (farthest from origin) corners of the bounding box.
:rtype: list of 6 int or float
"""
xsize = xsize_minimal if isnan(self.xsize) else self.xsize
ysize = ysize_minimal if isnan(self.ysize) else self.ysize
zsize = zsize_minimal if isnan(self.zsize) else self.zsize
return [self.x-xsize/2, self.y-ysize/2, self.z-zsize/2, self.x+xsize/2, self.y+ysize/2, self.z+zsize/2]


class World_State(object):
"""Data class structure that is holding various information about the world at a particular time."""
Expand Down
3 changes: 3 additions & 0 deletions qsr_lib/src/qsrlib_qsrs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
from qsr_moving_or_stationary import QSR_Moving_or_Stationary
from qsr_new_mwe import QSR_MWE
from qsr_ra import QSR_RA
from qsr_ra3d import QSR_RA3D
from qsr_tpcc import QSR_TPCC

# register new qsrs by class name below
qsrs_registry = (QSR_RCC2,
QSR_RCC3_Rectangle_Bounding_Boxes_2D,
Expand All @@ -28,4 +30,5 @@
QSR_Moving_or_Stationary,
QSR_MWE,
QSR_RA,
QSR_RA3D,
QSR_TPCC)
9 changes: 9 additions & 0 deletions qsr_lib/src/qsrlib_qsrs/qsr_abstractclass.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class QSR_Abstractclass(object):
* "points": self._return_points
* "bounding_boxes": self._return_bounding_boxes_2d
* "bounding_boxes_2d": self._return_bounding_boxes_2d
* "bounding_boxes_3d": self._return_bounding_boxes_3d

"""

Expand Down Expand Up @@ -123,6 +124,14 @@ def _return_bounding_boxes_2d(self):
"""
return

@abstractmethod
def _return_bounding_boxes_3d(self):
"""Return the 3D bounding boxes of the arguments.

:return: 3D bounding boxes of the arguments.
"""
return

@property
def unique_id(self):
"""Getter for the unique identifier of a QSR.
Expand Down
11 changes: 11 additions & 0 deletions qsr_lib/src/qsrlib_qsrs/qsr_dyadic_abstractclass.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,17 @@ def _return_bounding_boxes_2d(self, data1, data2):
"""
return data1.return_bounding_box_2d(), data2.return_bounding_box_2d()

def _return_bounding_boxes_3d(self, data1, data2):
"""Return the 3D bounding boxes of the arguments.

:param data1: First object data.
:type data1: :class:`Object_State <qsrlib_io.world_trace.Object_State>`
:param data2: Second object data.
:type data2: :class:`Object_State <qsrlib_io.world_trace.Object_State>`
:return: `bbox1`, `bbox2`
:rtype: two lists of floats
"""
return data1.return_bounding_box_3d(), data2.return_bounding_box_3d()

class QSR_Dyadic_1t_Abstractclass(QSR_Dyadic_Abstractclass):
"""Special case abstract class of dyadic QSRs. Works with dyadic QSRs that require data over one timestamp."""
Expand Down
11 changes: 11 additions & 0 deletions qsr_lib/src/qsrlib_qsrs/qsr_monadic_abstractclass.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,17 @@ def _return_bounding_boxes_2d(self, data1, data2):
"""
raise data1.return_bounding_box_2d(), data2.return_bounding_box_2d()

def _return_bounding_boxes_3d(self, data1, data2):
"""Return the 3D bounding boxes of the arguments.

:param data1: First object data.
:type data1: :class:`Object_State <qsrlib_io.world_trace.Object_State>`
:param data2: Second object data.
:type data2: :class:`Object_State <qsrlib_io.world_trace.Object_State>`
:return: `bbox1`, `bbox2`
:rtype: two lists of floats
"""
return data1.return_bounding_box_3d(), data2.return_bounding_box_3d()

class QSR_Monadic_2t_Abstractclass(QSR_Monadic_Abstractclass):
"""Special case abstract class of monadic QSRs. Works with monadic QSRs that require data over two timestamps."""
Expand Down
72 changes: 26 additions & 46 deletions qsr_lib/src/qsrlib_qsrs/qsr_ra.py
Original file line number Diff line number Diff line change
@@ -1,38 +1,45 @@
# -*- coding: utf-8 -*-
from __future__ import print_function, division
from numpy import isnan
from qsrlib_qsrs.qsr_dyadic_abstractclass import QSR_Dyadic_1t_Abstractclass
import itertools
from qsrlib_qsrs.qsr_ra_abstract import QSR_RA_Abstract


class QSR_RA(QSR_Dyadic_1t_Abstractclass):
class QSR_RA(QSR_RA_Abstract):
"""Rectangle Algebra.

Members:
* _unique_id: "ra"
* _all_possible_relations: ("<", ">", "m", "mi", "o", "oi", "s", "si", "d", "di", "f", "fi", "=")
* _dtype: "bounding_boxes"
* **_unique_id** = "ra"
* **_all_possible_relations** = quite long to list here (169) but they are all possible pairs between the 13 Allen's relations
* **_dtype** = "bounding_boxes_2d"

QSR specific `dynamic_args`
* **'qfactor'** (*int or float*) = 0.0: This factor provides some tolerance on the edges that are difficult
when the variables are floats, e.g. in the 'meets' relation it is unlikely that the end of one
segment will meet the beginning of the other to the decimal value.

.. warning::
Use of 'qfactor' might have strange and undesired results. Use it at your own risk.

For further details, you might want to consult with the exact implementation of the method
`_allen`_ in class `QSR_RA`.

.. seealso:: For further details about RA, refer to its :doc:`description. <../handwritten/qsrs/ra>`

.. _`_allen`: https://github.com/strands-project/strands_qsr_lib/blob/master/qsr_lib/src/qsrlib_qsrs/qsr_ra.py
"""

_unique_id = "ra"
"""str: Unique identifier name of the QSR."""

_all_possible_relations = ("<", ">", "m", "mi", "o", "oi", "s", "si", "d", "di", "f", "fi", "=")
"""tuple: All possible relations of the QSR."""

_dtype = "bounding_boxes"
_dtype = "bounding_boxes_2d"
"""str: On what kind of data the QSR works with."""

_inverse_map = {"<": ">", "m": "mi", "o": "oi", "s": "si", "d": "di", "f": "fi",
">": "<", "mi": "m", "o1": "o", "si": "s", "di": "d", "fi": "f"}
"""dict: Inverse relations"""
_all_possible_relations = tuple(itertools.product(("<", ">", "m", "mi", "o", "oi", "s", "si", "d", "di", "f", "fi", "="),
repeat=2))
"""tuple: All possible relations of the QSR."""

def __init__(self):
"""Constructor.

:return:
"""
"""Constructor."""
super(QSR_RA, self).__init__()

def _compute_qsr(self, bb1, bb2, qsr_params, **kwargs):
Expand All @@ -48,32 +55,5 @@ def _compute_qsr(self, bb1, bb2, qsr_params, **kwargs):
:return: The computed QSR value: two/three comma separated Allen relations for 2D/3D.
:rtype: str
"""
if len(bb1) == 4 and len(bb2) == 4: # 2D version
return ",".join([self.__allen((bb1[0], bb1[2]), (bb2[0], bb2[2])),
self.__allen((bb1[1], bb1[3]), (bb2[1], bb2[3]))])
elif len(bb1) == 6 and len(bb2) == 6: # 3D version
return ",".join([self.__allen((bb1[0], bb1[3]), (bb2[0], bb2[3])),
self.__allen((bb1[1], bb1[4]), (bb2[1], bb2[4])),
self.__allen((bb1[2], bb1[5]), (bb2[2], bb2[5]))])
else:
raise ValueError("bb1 and bb2 must have length of 4 (2D) or 6 (3D)")

def __allen(self, i1, i2):
if isnan(i1).any() or isnan(i2).any(): # nan values cause dragons
raise ValueError("illegal 'nan' values found")

if i1[1] < i2[0]:
return "<"
if i1[1] == i2[0]:
return "m"
if i1[0] < i2[0] < i1[1] and i2[0] < i1[1] < i2[1]:
return "o"
if i1[0] == i2[0] and i1[1] < i2[1]:
return "s"
if i2[0] < i1[0] < i2[1] and i2[0] < i1[1] < i2[1]:
return "d"
if i2[0] < i1[0] < i2[1] and i1[1] == i2[1]:
return "f"
if i1[0] == i2[0] and i1[1] == i2[1]:
return "="
return self._inverse_map[self.__allen(i2, i1)]
return ",".join([self._allen((bb1[0], bb1[2]), (bb2[0], bb2[2]), qsr_params),
self._allen((bb1[1], bb1[3]), (bb2[1], bb2[3]), qsr_params)])
60 changes: 60 additions & 0 deletions qsr_lib/src/qsrlib_qsrs/qsr_ra3d.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# -*- coding: utf-8 -*-
from __future__ import print_function, division
import itertools
from qsr_ra_abstract import QSR_RA_Abstract


class QSR_RA3D(QSR_RA_Abstract):
"""Rectangle Algebra.

Members:
* **_unique_id** = "ra3d"
* **_all_possible_relations** = quite long to list here (2197) but they are all possible triplets between the 13 Allen's relations
* **_dtype** = "bounding_boxes_3d"

QSR specific `dynamic_args`
* **'qfactor'** (*int or float*) = 0.0: This factor provides some tolerance on the edges that are difficult
when the variables are floats, e.g. in the 'meets' relation it is unlikely that the end of one
segment will meet the beginning of the other to the decimal value.

.. warning::
Use of 'qfactor' might have strange and undesired results. Use it at your own risk.

For further details, you might want to consult with the exact implementation of the method
`_allen`_ in class `QSR_RA`.

.. seealso:: For further details about RA, refer to its :doc:`description. <../handwritten/qsrs/ra>`

.. _`_allen`: https://github.com/strands-project/strands_qsr_lib/blob/master/qsr_lib/src/qsrlib_qsrs/qsr_ra.py
"""

_unique_id = "ra3d"
"""str: Unique identifier name of the QSR."""

_dtype = "bounding_boxes_3d"
"""str: On what kind of data the QSR works with."""

_all_possible_relations = tuple(itertools.product(("<", ">", "m", "mi", "o", "oi", "s", "si", "d", "di", "f", "fi", "="),
repeat=3))
"""tuple: All possible relations of the QSR."""

def __init__(self):
"""Constructor."""
super(QSR_RA3D, self).__init__()

def _compute_qsr(self, bb1, bb2, qsr_params, **kwargs):
"""Compute QSR value.

:param bb1: First object's 3D bounding box.
:type bb2: tuple or list
:param bb2: Second object's 3D bounding box.
:type bb2: tuple or list
:param qsr_params: QSR specific parameters passed in `dynamic_args`.
:type qsr_params: dict
:param kwargs: Optional further arguments.
:return: The computed QSR value: two/three comma separated Allen relations for 2D/3D.
:rtype: str
"""
return ",".join([self._allen((bb1[0], bb1[3]), (bb2[0], bb2[3])),
self._allen((bb1[1], bb1[4]), (bb2[1], bb2[4])),
self._allen((bb1[2], bb1[5]), (bb2[2], bb2[5]))])
Loading