Skip to content

DOCS: add examples of how one "should" use Bbox #17090

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

Merged
merged 1 commit into from
Apr 13, 2020
Merged
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
82 changes: 76 additions & 6 deletions lib/matplotlib/transforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,82 @@ def intersection(bbox1, bbox2):
class Bbox(BboxBase):
"""
A mutable bounding box.

Examples
--------
**Create from known bounds**

The default constructor takes the boundary "points" ``[[xmin, ymin],
[xmax, ymax]]``.

>>> Bbox([[1, 1], [3, 7]])
Bbox([[1.0, 1.0], [3.0, 7.0]])

Alternatively, a Bbox can be created from the flattened points array, the
so-called "extents" ``(xmin, ymin, xmax, ymax)``

>>> Bbox.from_extents(1, 1, 3, 7)
Bbox([[1.0, 1.0], [3.0, 7.0]])

or from the "bounds" ``(xmin, ymin, width, height)``.

>>> Bbox.from_bounds(1, 1, 2, 6)
Bbox([[1.0, 1.0], [3.0, 7.0]])

**Create from collections of points**

The "empty" object for accumulating Bboxs is the null bbox, which is a
stand-in for the empty set.

>>> Bbox.null()
Bbox([[inf, inf], [-inf, -inf]])

Adding points to the null bbox will give you the bbox of those points.

>>> box = Bbox.null()
>>> box.update_from_data_xy([[1, 1]])
>>> box
Bbox([[1.0, 1.0], [1.0, 1.0]])
>>> box.update_from_data_xy([[2, 3], [3, 2]], ignore=False)
>>> box
Bbox([[1.0, 1.0], [3.0, 3.0]])

Setting ``ignore=True`` is equivalent to starting over from a null bbox.

>>> box.update_from_data_xy([[1, 1]], ignore=True)
>>> box
Bbox([[1.0, 1.0], [1.0, 1.0]])

.. warning::

It is recommended to always specify ``ignore`` explicitly. If not, the
default value of ``ignore`` can be changed at any time by code with
access to your Bbox, for example using the method `~.Bbox.ignore`.

**Properties of the ``null`` bbox**

.. note::

The current behavior of `Bbox.null()` may be surprising as it does
not have all of the properties of the "empty set", and as such does
not behave like a "zero" object in the mathematical sense. We may
change that in the future (with a deprecation period).

The null bbox is the identity for intersections

>>> Bbox.intersection(Bbox([[1, 1], [3, 7]]), Bbox.null())
Bbox([[1.0, 1.0], [3.0, 7.0]])

except with itself, where it returns the full space.

>>> Bbox.intersection(Bbox.null(), Bbox.null())
Bbox([[-inf, -inf], [inf, inf]])

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a reasonable behavior? Seems to contradict the semantics of update_from_data_xy.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah part of why I'm documenting this is because this behavior was very unexpected. I expected Bbox.null() to be the "zero" object of the intersection/union ring over the Bbox's.

But it's not technically a bug per se since it's not documented, so I didn't open an issue.

Copy link
Contributor Author

@brunobeltran brunobeltran Apr 10, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That said, I'd be happy to make a separate PR to fix this "bug", if other people also agree that it shouldn't be this way, but don't want to get bogged down talking about deprecation timelines, etc. here, would rather open a separate issue.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This and below clearly look like bugs, but I'm fine documenting these here and changing them later.

A union containing null will always return the full space (not the other
set!)

>>> Bbox.union([Bbox([[0, 0], [0, 0]]), Bbox.null()])
Bbox([[-inf, -inf], [inf, inf]])
"""

def __init__(self, points, **kwargs):
Expand All @@ -690,12 +766,6 @@ def __init__(self, points, **kwargs):
----------
points : ndarray
A 2x2 numpy array of the form ``[[x0, y0], [x1, y1]]``.

Notes
-----
If you need to create a `Bbox` object from another form
of data, consider the static methods :meth:`unit`,
:meth:`from_bounds` and :meth:`from_extents`.
"""
BboxBase.__init__(self, **kwargs)
points = np.asarray(points, float)
Expand Down