From eeed6fcdbbe6b23597c35dee567284aa399046a8 Mon Sep 17 00:00:00 2001 From: Johann Krauter Date: Thu, 27 Apr 2023 13:43:21 +0200 Subject: [PATCH 01/33] Adding ellipse_arrow.py example and fix #25477 --- .../shapes_and_collections/ellipse_arrow.py | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 galleries/examples/shapes_and_collections/ellipse_arrow.py diff --git a/galleries/examples/shapes_and_collections/ellipse_arrow.py b/galleries/examples/shapes_and_collections/ellipse_arrow.py new file mode 100644 index 000000000000..9d4ef4483aa6 --- /dev/null +++ b/galleries/examples/shapes_and_collections/ellipse_arrow.py @@ -0,0 +1,46 @@ +""" +============ +Ellipse with arrow Demo +============ + +Draw an ellipses with an arrow showing rotation direction. Compare this +to the :doc:`Ellipse collection example +`. +""" + +import matplotlib.pyplot as plt +import numpy as np + +# Define start position of ellipse +xVec = 0.5 + 0.5j +yVec = 0.2 + 0.5j + +sampling = 101 +n = np.linspace(0, sampling, sampling) + +# Calculate ellipse data points +x = np.real(xVec * np.exp(1j * 2 * np.pi * n / sampling)) +y = np.real(yVec * np.exp(1j * 2 * np.pi * n / sampling)) + +# Draw ellipse +fig, ax = plt.subplots(1, 1, subplot_kw={"aspect": "equal"}) +ax.plot(x, y) + +# Calculate arrow position and orientation +dx = x[-1] - x[-2] +dy = y[-1] - y[-2] +ax.arrow(x=x[-1], y=y[-1], dx=dx, dy=dy, head_width=0.05) + +ax.set_xlim((-1, 1)) +ax.set_ylim((-1, 1)) +plt.show() + +# %% +# +# .. admonition:: References +# +# The use of the following functions, methods, classes and modules is shown +# in this example: +# +# - `matplotlib.patches` +# - `matplotlib.patches.Ellipse` From e16c81df8d1e15df1ed560d371644af3b7b6123b Mon Sep 17 00:00:00 2001 From: Johann Krauter Date: Thu, 27 Apr 2023 19:34:21 +0200 Subject: [PATCH 02/33] adapt the = lines to fix docu build test --- galleries/examples/shapes_and_collections/ellipse_arrow.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/galleries/examples/shapes_and_collections/ellipse_arrow.py b/galleries/examples/shapes_and_collections/ellipse_arrow.py index 9d4ef4483aa6..503c71ed89ad 100644 --- a/galleries/examples/shapes_and_collections/ellipse_arrow.py +++ b/galleries/examples/shapes_and_collections/ellipse_arrow.py @@ -1,7 +1,7 @@ """ -============ +======================= Ellipse with arrow Demo -============ +======================= Draw an ellipses with an arrow showing rotation direction. Compare this to the :doc:`Ellipse collection example From f8dc66f2abe15755127a12ff35b443ea772b491c Mon Sep 17 00:00:00 2001 From: Johann Krauter Date: Thu, 27 Apr 2023 20:46:03 +0200 Subject: [PATCH 03/33] use plt.subplot() --- galleries/examples/shapes_and_collections/ellipse_arrow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/galleries/examples/shapes_and_collections/ellipse_arrow.py b/galleries/examples/shapes_and_collections/ellipse_arrow.py index 503c71ed89ad..670029830975 100644 --- a/galleries/examples/shapes_and_collections/ellipse_arrow.py +++ b/galleries/examples/shapes_and_collections/ellipse_arrow.py @@ -23,7 +23,7 @@ y = np.real(yVec * np.exp(1j * 2 * np.pi * n / sampling)) # Draw ellipse -fig, ax = plt.subplots(1, 1, subplot_kw={"aspect": "equal"}) +ax = plt.subplot() ax.plot(x, y) # Calculate arrow position and orientation From 4ae516ecd65f4bb8db7a3ef523ad9781994a5088 Mon Sep 17 00:00:00 2001 From: Johann Krauter Date: Sat, 29 Apr 2023 21:20:09 +0200 Subject: [PATCH 04/33] Now the patches.Ellipse is used for the plot and a marker ">" at the end point position of the ellipse minor axis rotated by the transform.Affine2D method. --- .../shapes_and_collections/ellipse_arrow.py | 96 ++++++++++++++----- 1 file changed, 74 insertions(+), 22 deletions(-) diff --git a/galleries/examples/shapes_and_collections/ellipse_arrow.py b/galleries/examples/shapes_and_collections/ellipse_arrow.py index 670029830975..3f3d2cd1d085 100644 --- a/galleries/examples/shapes_and_collections/ellipse_arrow.py +++ b/galleries/examples/shapes_and_collections/ellipse_arrow.py @@ -1,40 +1,92 @@ """ -======================= -Ellipse with arrow Demo -======================= +=================================== +Ellipse with orientation arrow Demo +=================================== -Draw an ellipses with an arrow showing rotation direction. Compare this -to the :doc:`Ellipse collection example +This demo shows how to draw an ellipse with an orientation arrow. +Compare this to the :doc:`Ellipse collection example `. """ +# Import of namespaces import matplotlib.pyplot as plt +from matplotlib.patches import Ellipse +from matplotlib.markers import MarkerStyle +from matplotlib.transforms import Affine2D + import numpy as np +from typing import Tuple + + +def getMinorMajor(ellipse: Ellipse) -> Tuple[list, list]: + """Calculates the end points of minor and major axis of an ellipse. + + Args: + ellipse (Ellipse): Ellipse patch. -# Define start position of ellipse -xVec = 0.5 + 0.5j -yVec = 0.2 + 0.5j + Returns: + Tuple[list, list]: Coordinates of minor end points and major end points. + """ + # Calculate the endpoints of the minor axis + x0_minor = ellipse.center[0] - ellipse.height / 2 * np.sin( + np.deg2rad(ellipse.angle) + ) + y0_minor = ellipse.center[1] + ellipse.height / 2 * np.cos( + np.deg2rad(ellipse.angle) + ) + x1_minor = ellipse.center[0] + ellipse.height / 2 * np.sin( + np.deg2rad(ellipse.angle) + ) + y1_minor = ellipse.center[1] - ellipse.height / 2 * np.cos( + np.deg2rad(ellipse.angle) + ) -sampling = 101 -n = np.linspace(0, sampling, sampling) + # Calculate the endpoints of the major axis + x0_major = ellipse.center[0] - ellipse.width / 2 * np.cos(np.deg2rad(ellipse.angle)) + y0_major = ellipse.center[1] - ellipse.width / 2 * np.sin(np.deg2rad(ellipse.angle)) + x1_major = ellipse.center[0] + ellipse.width / 2 * np.cos(np.deg2rad(ellipse.angle)) + y1_major = ellipse.center[1] + ellipse.width / 2 * np.sin(np.deg2rad(ellipse.angle)) + return [(x0_minor, y0_minor), (x1_minor, y1_minor)], [ + (x0_major, y0_major), + (x1_major, y1_major), + ] -# Calculate ellipse data points -x = np.real(xVec * np.exp(1j * 2 * np.pi * n / sampling)) -y = np.real(yVec * np.exp(1j * 2 * np.pi * n / sampling)) -# Draw ellipse -ax = plt.subplot() -ax.plot(x, y) +# Define the ellipse +center = (2, 4) +width = 30 +height = 20 +angle = 35 +ellipse = Ellipse( + xy=center, + width=width, + height=height, + angle=angle, + facecolor="none", + edgecolor="b", +) -# Calculate arrow position and orientation -dx = x[-1] - x[-2] -dy = y[-1] - y[-2] -ax.arrow(x=x[-1], y=y[-1], dx=dx, dy=dy, head_width=0.05) +minor, major = getMinorMajor(ellipse) + +# Create a figure and axis +fig, ax = plt.subplots(1, 1, subplot_kw={"aspect": "equal"}) + +# Add the ellipse patch to the axis +ax.add_patch(ellipse) + +# Plot a arrow marker at the end point of minor axis +t = Affine2D().rotate_deg(angle) +ax.plot( + minor[0][0], + minor[0][1], + color="b", + marker=MarkerStyle(">", "full", t), + markersize=10, +) -ax.set_xlim((-1, 1)) -ax.set_ylim((-1, 1)) plt.show() + # %% # # .. admonition:: References From 0005c7e24b3a697acee97095fe952a79751cf029 Mon Sep 17 00:00:00 2001 From: Johann Krauter Date: Sat, 29 Apr 2023 21:39:35 +0200 Subject: [PATCH 05/33] changed function docstring to numpy style --- .../shapes_and_collections/ellipse_arrow.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/galleries/examples/shapes_and_collections/ellipse_arrow.py b/galleries/examples/shapes_and_collections/ellipse_arrow.py index 3f3d2cd1d085..39e21ea3db62 100644 --- a/galleries/examples/shapes_and_collections/ellipse_arrow.py +++ b/galleries/examples/shapes_and_collections/ellipse_arrow.py @@ -15,17 +15,22 @@ from matplotlib.transforms import Affine2D import numpy as np + from typing import Tuple def getMinorMajor(ellipse: Ellipse) -> Tuple[list, list]: - """Calculates the end points of minor and major axis of an ellipse. + """ + Calculates the end points of minor and major axis of an ellipse. - Args: - ellipse (Ellipse): Ellipse patch. + Parameters + ---------- + ellipse : ~matplotlib.patches.Ellipse + Ellipse patch. - Returns: - Tuple[list, list]: Coordinates of minor end points and major end points. + Returns + ------- + ~typing.Tuple[list, list] """ # Calculate the endpoints of the minor axis x0_minor = ellipse.center[0] - ellipse.height / 2 * np.sin( From 944a513a7340bc1f06779213f90bf21e139d6eba Mon Sep 17 00:00:00 2001 From: Johann Krauter Date: Sat, 29 Apr 2023 23:11:49 +0200 Subject: [PATCH 06/33] fix flake8 build fail --- .../examples/shapes_and_collections/ellipse_arrow.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/galleries/examples/shapes_and_collections/ellipse_arrow.py b/galleries/examples/shapes_and_collections/ellipse_arrow.py index 39e21ea3db62..ec28edbbd5fe 100644 --- a/galleries/examples/shapes_and_collections/ellipse_arrow.py +++ b/galleries/examples/shapes_and_collections/ellipse_arrow.py @@ -18,6 +18,16 @@ from typing import Tuple +# %% +# +# A method to calculate the end points of the ellipse major, minor axis +# """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +# +# Calculates the minor axis and major axis end points of the ellipse. +# It needs the ellipse parameter like widht, height, angle. +# The output are 2 lists of 2 xy coordinates +# (minor((x0, y0), (x1, y1)), major((x0, y0), (x1, y1))). + def getMinorMajor(ellipse: Ellipse) -> Tuple[list, list]: """ From 8acae1eed5403a870c7b0b47b4bdaf2a92ab0d04 Mon Sep 17 00:00:00 2001 From: Photoniker <17592823+photoniker@users.noreply.github.com> Date: Sat, 29 Apr 2023 23:21:15 +0200 Subject: [PATCH 07/33] Update ellipse_arrow.py --- galleries/examples/shapes_and_collections/ellipse_arrow.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/galleries/examples/shapes_and_collections/ellipse_arrow.py b/galleries/examples/shapes_and_collections/ellipse_arrow.py index ec28edbbd5fe..9c00b9ba105a 100644 --- a/galleries/examples/shapes_and_collections/ellipse_arrow.py +++ b/galleries/examples/shapes_and_collections/ellipse_arrow.py @@ -23,9 +23,9 @@ # A method to calculate the end points of the ellipse major, minor axis # """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" # -# Calculates the minor axis and major axis end points of the ellipse. -# It needs the ellipse parameter like widht, height, angle. -# The output are 2 lists of 2 xy coordinates +# Calculates the minor axis and major axis end points of the ellipse. +# It needs the ellipse parameter like widht, height, angle. +# The output are 2 lists of 2 xy coordinates # (minor((x0, y0), (x1, y1)), major((x0, y0), (x1, y1))). From 74c4480171ca63eaaffee2e282c89bb3575d73fc Mon Sep 17 00:00:00 2001 From: Photoniker <17592823+photoniker@users.noreply.github.com> Date: Sat, 29 Apr 2023 23:24:42 +0200 Subject: [PATCH 08/33] Update ellipse_arrow.py --- galleries/examples/shapes_and_collections/ellipse_arrow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/galleries/examples/shapes_and_collections/ellipse_arrow.py b/galleries/examples/shapes_and_collections/ellipse_arrow.py index 9c00b9ba105a..8c40cb0a7107 100644 --- a/galleries/examples/shapes_and_collections/ellipse_arrow.py +++ b/galleries/examples/shapes_and_collections/ellipse_arrow.py @@ -24,7 +24,7 @@ # """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" # # Calculates the minor axis and major axis end points of the ellipse. -# It needs the ellipse parameter like widht, height, angle. +# It needs the ellipse parameter like width, height, angle. # The output are 2 lists of 2 xy coordinates # (minor((x0, y0), (x1, y1)), major((x0, y0), (x1, y1))). From 02865ef076ad3d72626581aeaf01d3edecb83e9a Mon Sep 17 00:00:00 2001 From: Photoniker <17592823+photoniker@users.noreply.github.com> Date: Sun, 30 Apr 2023 05:02:29 +0200 Subject: [PATCH 09/33] Update ellipse_arrow.py --- galleries/examples/shapes_and_collections/ellipse_arrow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/galleries/examples/shapes_and_collections/ellipse_arrow.py b/galleries/examples/shapes_and_collections/ellipse_arrow.py index 8c40cb0a7107..e2e5a6d69734 100644 --- a/galleries/examples/shapes_and_collections/ellipse_arrow.py +++ b/galleries/examples/shapes_and_collections/ellipse_arrow.py @@ -3,7 +3,7 @@ Ellipse with orientation arrow Demo =================================== -This demo shows how to draw an ellipse with an orientation arrow. +This demo shows how to draw an ellipse with an orientation arrow (clockwise or counterclockwise). Compare this to the :doc:`Ellipse collection example `. """ From 15a84c1c938e92294feba56af50a7b821de5f92a Mon Sep 17 00:00:00 2001 From: Photoniker <17592823+photoniker@users.noreply.github.com> Date: Sun, 30 Apr 2023 05:07:02 +0200 Subject: [PATCH 10/33] Update ellipse_arrow.py --- galleries/examples/shapes_and_collections/ellipse_arrow.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/galleries/examples/shapes_and_collections/ellipse_arrow.py b/galleries/examples/shapes_and_collections/ellipse_arrow.py index e2e5a6d69734..0f63717292f2 100644 --- a/galleries/examples/shapes_and_collections/ellipse_arrow.py +++ b/galleries/examples/shapes_and_collections/ellipse_arrow.py @@ -3,7 +3,8 @@ Ellipse with orientation arrow Demo =================================== -This demo shows how to draw an ellipse with an orientation arrow (clockwise or counterclockwise). +This demo shows how to draw an ellipse with +an orientation arrow (clockwise or counterclockwise). Compare this to the :doc:`Ellipse collection example `. """ From f9fd86811e918c4faca34c5998723fb541152990 Mon Sep 17 00:00:00 2001 From: Photoniker <17592823+photoniker@users.noreply.github.com> Date: Sun, 30 Apr 2023 05:10:58 +0200 Subject: [PATCH 11/33] Update ellipse_arrow.py --- galleries/examples/shapes_and_collections/ellipse_arrow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/galleries/examples/shapes_and_collections/ellipse_arrow.py b/galleries/examples/shapes_and_collections/ellipse_arrow.py index 0f63717292f2..d310dde816d0 100644 --- a/galleries/examples/shapes_and_collections/ellipse_arrow.py +++ b/galleries/examples/shapes_and_collections/ellipse_arrow.py @@ -3,7 +3,7 @@ Ellipse with orientation arrow Demo =================================== -This demo shows how to draw an ellipse with +This demo shows how to draw an ellipse with an orientation arrow (clockwise or counterclockwise). Compare this to the :doc:`Ellipse collection example `. From e3ad826e292d14fbd62eea0299fcc26165d12647 Mon Sep 17 00:00:00 2001 From: Photoniker <17592823+photoniker@users.noreply.github.com> Date: Sun, 30 Apr 2023 05:29:36 +0200 Subject: [PATCH 12/33] Update ellipse_arrow.py --- galleries/examples/shapes_and_collections/ellipse_arrow.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/galleries/examples/shapes_and_collections/ellipse_arrow.py b/galleries/examples/shapes_and_collections/ellipse_arrow.py index d310dde816d0..a85246403bd2 100644 --- a/galleries/examples/shapes_and_collections/ellipse_arrow.py +++ b/galleries/examples/shapes_and_collections/ellipse_arrow.py @@ -10,12 +10,12 @@ """ # Import of namespaces +import numpy as np import matplotlib.pyplot as plt + +from matplotlib.transforms import Affine2D from matplotlib.patches import Ellipse from matplotlib.markers import MarkerStyle -from matplotlib.transforms import Affine2D - -import numpy as np from typing import Tuple From e12a72a7333a486c32d7af24d66bfe635e61263b Mon Sep 17 00:00:00 2001 From: Photoniker <17592823+photoniker@users.noreply.github.com> Date: Sun, 30 Apr 2023 05:47:22 +0200 Subject: [PATCH 13/33] Update ellipse_arrow.py --- .../examples/shapes_and_collections/ellipse_arrow.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/galleries/examples/shapes_and_collections/ellipse_arrow.py b/galleries/examples/shapes_and_collections/ellipse_arrow.py index a85246403bd2..6932f72d2888 100644 --- a/galleries/examples/shapes_and_collections/ellipse_arrow.py +++ b/galleries/examples/shapes_and_collections/ellipse_arrow.py @@ -9,15 +9,14 @@ `. """ -# Import of namespaces -import numpy as np +from typing import Tuple + import matplotlib.pyplot as plt +import numpy as np -from matplotlib.transforms import Affine2D -from matplotlib.patches import Ellipse from matplotlib.markers import MarkerStyle - -from typing import Tuple +from matplotlib.patches import Ellipse +from matplotlib.transforms import Affine2D # %% # From 303f957d01d846b517e678ef6219eb9c5f4effbd Mon Sep 17 00:00:00 2001 From: Johann Krauter Date: Sun, 30 Apr 2023 22:11:50 +0200 Subject: [PATCH 14/33] added get_vertices and get_co_vertices methods the Ellipse --- .../shapes_and_collections/ellipse_arrow.py | 125 +++++++++--------- lib/matplotlib/patches.py | 24 ++++ lib/matplotlib/tests/test_patches.py | 22 +++ 3 files changed, 106 insertions(+), 65 deletions(-) diff --git a/galleries/examples/shapes_and_collections/ellipse_arrow.py b/galleries/examples/shapes_and_collections/ellipse_arrow.py index 6932f72d2888..c444de6e7c29 100644 --- a/galleries/examples/shapes_and_collections/ellipse_arrow.py +++ b/galleries/examples/shapes_and_collections/ellipse_arrow.py @@ -1,6 +1,6 @@ """ =================================== -Ellipse with orientation arrow Demo +Ellipse with orientation arrow demo =================================== This demo shows how to draw an ellipse with @@ -9,98 +9,93 @@ `. """ -from typing import Tuple - import matplotlib.pyplot as plt -import numpy as np - from matplotlib.markers import MarkerStyle from matplotlib.patches import Ellipse from matplotlib.transforms import Affine2D -# %% -# -# A method to calculate the end points of the ellipse major, minor axis -# """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" -# -# Calculates the minor axis and major axis end points of the ellipse. -# It needs the ellipse parameter like width, height, angle. -# The output are 2 lists of 2 xy coordinates -# (minor((x0, y0), (x1, y1)), major((x0, y0), (x1, y1))). - - -def getMinorMajor(ellipse: Ellipse) -> Tuple[list, list]: - """ - Calculates the end points of minor and major axis of an ellipse. - - Parameters - ---------- - ellipse : ~matplotlib.patches.Ellipse - Ellipse patch. - - Returns - ------- - ~typing.Tuple[list, list] - """ - # Calculate the endpoints of the minor axis - x0_minor = ellipse.center[0] - ellipse.height / 2 * np.sin( - np.deg2rad(ellipse.angle) - ) - y0_minor = ellipse.center[1] + ellipse.height / 2 * np.cos( - np.deg2rad(ellipse.angle) - ) - x1_minor = ellipse.center[0] + ellipse.height / 2 * np.sin( - np.deg2rad(ellipse.angle) - ) - y1_minor = ellipse.center[1] - ellipse.height / 2 * np.cos( - np.deg2rad(ellipse.angle) - ) - - # Calculate the endpoints of the major axis - x0_major = ellipse.center[0] - ellipse.width / 2 * np.cos(np.deg2rad(ellipse.angle)) - y0_major = ellipse.center[1] - ellipse.width / 2 * np.sin(np.deg2rad(ellipse.angle)) - x1_major = ellipse.center[0] + ellipse.width / 2 * np.cos(np.deg2rad(ellipse.angle)) - y1_major = ellipse.center[1] + ellipse.width / 2 * np.sin(np.deg2rad(ellipse.angle)) - return [(x0_minor, y0_minor), (x1_minor, y1_minor)], [ - (x0_major, y0_major), - (x1_major, y1_major), - ] - - -# Define the ellipse + +# Create a figure and axis +fig, ax = plt.subplots(1, 1, subplot_kw={"aspect": "equal"}) + +# Define an ellipse clockwise center = (2, 4) width = 30 height = 20 angle = 35 -ellipse = Ellipse( +ellipse_clockwise = Ellipse( xy=center, width=width, height=height, angle=angle, facecolor="none", edgecolor="b", + label="clockwise" ) -minor, major = getMinorMajor(ellipse) - -# Create a figure and axis -fig, ax = plt.subplots(1, 1, subplot_kw={"aspect": "equal"}) +# Get position of vertex for arrow marker +vertices = ellipse_clockwise.get_co_vertices() # Add the ellipse patch to the axis -ax.add_patch(ellipse) +ax.add_patch(ellipse_clockwise) # Plot a arrow marker at the end point of minor axis -t = Affine2D().rotate_deg(angle) +t = Affine2D().rotate_deg(ellipse_clockwise.angle) ax.plot( - minor[0][0], - minor[0][1], + vertices[0][0], + vertices[0][1], color="b", marker=MarkerStyle(">", "full", t), - markersize=10, + markersize=10 ) +# Define an second ellipse counterclockwise +center = (2, 4) +width = 30 +height = 15 +angle = -20 +ellipse_counterclockwise = Ellipse( + xy=center, + width=width, + height=height, + angle=angle, + facecolor="none", + edgecolor="g", + label="counterclockwise" +) + +# Add the ellipse patch to the axis +ax.add_patch(ellipse_counterclockwise) + +# Get position of vertex for arrow marker +vertices = ellipse_counterclockwise.get_co_vertices() + +# Plot a arrow marker at the end point of minor axis +t = Affine2D().rotate_deg(ellipse_counterclockwise.angle) +ax.plot( + vertices[0][0], + vertices[0][1], + color="g", + marker=MarkerStyle("<", "full", t), + markersize=10 +) + + +plt.legend() plt.show() +center = (2, 4) +width = 30 +height = 20 +angle = 35 +ellipse = Ellipse( + xy=center, + width=width, + height=height, + angle=angle +) +print(ellipse.get_vertices()) +print(ellipse.get_co_vertices()) # %% # diff --git a/lib/matplotlib/patches.py b/lib/matplotlib/patches.py index 245bb7b777c8..665cf5b9f15f 100644 --- a/lib/matplotlib/patches.py +++ b/lib/matplotlib/patches.py @@ -1654,6 +1654,30 @@ def get_corners(self): return self.get_patch_transform().transform( [(-1, -1), (1, -1), (1, 1), (-1, 1)]) + def get_vertices(self): + """ + Return the left and right vertex coordinates of the ellipse. + + The definition can be found `here`_ + """ + x0 = self._center[0] - self._width / 2 * np.cos(np.deg2rad(self._angle)) + y0 = self._center[1] - self._width / 2 * np.sin(np.deg2rad(self._angle)) + x1 = self._center[0] + self._width / 2 * np.cos(np.deg2rad(self._angle)) + y1 = self._center[1] + self._width / 2 * np.sin(np.deg2rad(self._angle)) + return [(x0, y0), (x1, y1)] + + def get_co_vertices(self): + """ + Return the left and right co-vertex coordinates of the ellipse. + + The definition can be found `here`_ + """ + x0 = self._center[0] - self._height / 2 * np.sin(np.deg2rad(self._angle)) + y0 = self._center[1] + self._height / 2 * np.cos(np.deg2rad(self._angle)) + x1 = self._center[0] + self._height / 2 * np.sin(np.deg2rad(self._angle)) + y1 = self._center[1] - self._height / 2 * np.cos(np.deg2rad(self._angle)) + return [(x0, y0), (x1, y1)] + class Annulus(Patch): """ diff --git a/lib/matplotlib/tests/test_patches.py b/lib/matplotlib/tests/test_patches.py index b9e1db32d419..f72bce85ec05 100644 --- a/lib/matplotlib/tests/test_patches.py +++ b/lib/matplotlib/tests/test_patches.py @@ -104,6 +104,28 @@ def test_corner_center(): assert_almost_equal(ellipse.get_corners(), corners_rot) +def test_ellipse_vertices(): + center = (2, 4) + width = 30 + height = 20 + angle = 35 + ellipse = Ellipse(xy=center, width=width, height=height, angle=angle) + assert_almost_equal( + ellipse.get_vertices(), + [ + (-10.287280664334878, -4.60364654526569), + (14.287280664334878, 12.60364654526569), + ], + ) + assert_almost_equal( + ellipse.get_co_vertices(), + [ + (-3.7357643635104605, 12.191520442889917), + (7.7357643635104605, -4.191520442889917), + ], + ) + + def test_rotate_rect(): loc = np.asarray([1.0, 2.0]) width = 2 From 3df0bbb0368432a83fa4b95140926afa6f7c9ac8 Mon Sep 17 00:00:00 2001 From: Johann Krauter Date: Sun, 30 Apr 2023 22:14:54 +0200 Subject: [PATCH 15/33] deleted blank lines --- lib/matplotlib/patches.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/patches.py b/lib/matplotlib/patches.py index 665cf5b9f15f..2d7707fdde8c 100644 --- a/lib/matplotlib/patches.py +++ b/lib/matplotlib/patches.py @@ -1665,7 +1665,7 @@ def get_vertices(self): x1 = self._center[0] + self._width / 2 * np.cos(np.deg2rad(self._angle)) y1 = self._center[1] + self._width / 2 * np.sin(np.deg2rad(self._angle)) return [(x0, y0), (x1, y1)] - + def get_co_vertices(self): """ Return the left and right co-vertex coordinates of the ellipse. From bbf76e7d0627853164692203440939312af8f39d Mon Sep 17 00:00:00 2001 From: Johann Krauter Date: Sun, 30 Apr 2023 22:18:29 +0200 Subject: [PATCH 16/33] sorry, some more whitespaces in blank line --- lib/matplotlib/patches.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/patches.py b/lib/matplotlib/patches.py index 2d7707fdde8c..2c7ba8b0d22a 100644 --- a/lib/matplotlib/patches.py +++ b/lib/matplotlib/patches.py @@ -1669,7 +1669,7 @@ def get_vertices(self): def get_co_vertices(self): """ Return the left and right co-vertex coordinates of the ellipse. - + The definition can be found `here`_ """ x0 = self._center[0] - self._height / 2 * np.sin(np.deg2rad(self._angle)) From f07471313a4342ab30246c9dcb19ea00288c4585 Mon Sep 17 00:00:00 2001 From: Johann Krauter Date: Mon, 1 May 2023 14:29:02 +0200 Subject: [PATCH 17/33] added entries in stubs, resolve docu issues --- .../shapes_and_collections/ellipse_arrow.py | 71 +++---------------- lib/matplotlib/patches.py | 4 +- lib/matplotlib/patches.pyi | 3 + 3 files changed, 15 insertions(+), 63 deletions(-) diff --git a/galleries/examples/shapes_and_collections/ellipse_arrow.py b/galleries/examples/shapes_and_collections/ellipse_arrow.py index c444de6e7c29..004256d30e79 100644 --- a/galleries/examples/shapes_and_collections/ellipse_arrow.py +++ b/galleries/examples/shapes_and_collections/ellipse_arrow.py @@ -16,31 +16,26 @@ # Create a figure and axis -fig, ax = plt.subplots(1, 1, subplot_kw={"aspect": "equal"}) +fig, ax = plt.subplots(subplot_kw={"aspect": "equal"}) # Define an ellipse clockwise -center = (2, 4) -width = 30 -height = 20 -angle = 35 -ellipse_clockwise = Ellipse( +center=(2, 4) +width=30 +height=20 +angle=35 +ellipse = Ellipse( xy=center, width=width, height=height, angle=angle, facecolor="none", - edgecolor="b", - label="clockwise" + edgecolor="b" ) - -# Get position of vertex for arrow marker -vertices = ellipse_clockwise.get_co_vertices() - -# Add the ellipse patch to the axis -ax.add_patch(ellipse_clockwise) +ax.add_patch(ellipse) # Plot a arrow marker at the end point of minor axis -t = Affine2D().rotate_deg(ellipse_clockwise.angle) +vertices = ellipse.get_co_vertices() +t = Affine2D().rotate_deg(ellipse.angle) ax.plot( vertices[0][0], vertices[0][1], @@ -49,54 +44,8 @@ markersize=10 ) -# Define an second ellipse counterclockwise -center = (2, 4) -width = 30 -height = 15 -angle = -20 -ellipse_counterclockwise = Ellipse( - xy=center, - width=width, - height=height, - angle=angle, - facecolor="none", - edgecolor="g", - label="counterclockwise" -) - -# Add the ellipse patch to the axis -ax.add_patch(ellipse_counterclockwise) - -# Get position of vertex for arrow marker -vertices = ellipse_counterclockwise.get_co_vertices() - -# Plot a arrow marker at the end point of minor axis -t = Affine2D().rotate_deg(ellipse_counterclockwise.angle) -ax.plot( - vertices[0][0], - vertices[0][1], - color="g", - marker=MarkerStyle("<", "full", t), - markersize=10 -) - - -plt.legend() plt.show() -center = (2, 4) -width = 30 -height = 20 -angle = 35 -ellipse = Ellipse( - xy=center, - width=width, - height=height, - angle=angle -) -print(ellipse.get_vertices()) -print(ellipse.get_co_vertices()) - # %% # # .. admonition:: References diff --git a/lib/matplotlib/patches.py b/lib/matplotlib/patches.py index 2c7ba8b0d22a..faf070aadcf1 100644 --- a/lib/matplotlib/patches.py +++ b/lib/matplotlib/patches.py @@ -1658,7 +1658,7 @@ def get_vertices(self): """ Return the left and right vertex coordinates of the ellipse. - The definition can be found `here`_ + The definition can be found `here `_ """ x0 = self._center[0] - self._width / 2 * np.cos(np.deg2rad(self._angle)) y0 = self._center[1] - self._width / 2 * np.sin(np.deg2rad(self._angle)) @@ -1670,7 +1670,7 @@ def get_co_vertices(self): """ Return the left and right co-vertex coordinates of the ellipse. - The definition can be found `here`_ + The definition can be found `here `_ """ x0 = self._center[0] - self._height / 2 * np.sin(np.deg2rad(self._angle)) y0 = self._center[1] + self._height / 2 * np.cos(np.deg2rad(self._angle)) diff --git a/lib/matplotlib/patches.pyi b/lib/matplotlib/patches.pyi index 1e70a1efc3be..dcd8b638749f 100644 --- a/lib/matplotlib/patches.pyi +++ b/lib/matplotlib/patches.pyi @@ -258,6 +258,9 @@ class Ellipse(Patch): angle = property(get_angle, set_angle) def get_corners(self) -> np.ndarray: ... + + def get_vertices(self) -> list[float, float]: ... + def get_co_vertices(self) -> list[float, float]: ... class Annulus(Patch): a: float From 2578cd97b5449e7d025f1f814ed2c2f5b447d45b Mon Sep 17 00:00:00 2001 From: Johann Krauter Date: Mon, 1 May 2023 14:34:38 +0200 Subject: [PATCH 18/33] resolve flake8 --- .../examples/shapes_and_collections/ellipse_arrow.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/galleries/examples/shapes_and_collections/ellipse_arrow.py b/galleries/examples/shapes_and_collections/ellipse_arrow.py index 004256d30e79..3b53beca7d4a 100644 --- a/galleries/examples/shapes_and_collections/ellipse_arrow.py +++ b/galleries/examples/shapes_and_collections/ellipse_arrow.py @@ -19,10 +19,10 @@ fig, ax = plt.subplots(subplot_kw={"aspect": "equal"}) # Define an ellipse clockwise -center=(2, 4) -width=30 -height=20 -angle=35 +center = (2, 4) +width = 30 +height = 20 +angle = 35 ellipse = Ellipse( xy=center, width=width, @@ -43,6 +43,7 @@ marker=MarkerStyle(">", "full", t), markersize=10 ) +# Note: To reverse the orientation arrow, switch the marker type from > to <. plt.show() From 0b492d18fcd7d84fd902cdcc926c62af1813c95b Mon Sep 17 00:00:00 2001 From: Johann Krauter Date: Mon, 1 May 2023 14:37:04 +0200 Subject: [PATCH 19/33] resolve return values --- lib/matplotlib/patches.pyi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/patches.pyi b/lib/matplotlib/patches.pyi index dcd8b638749f..6f1a9b45a2db 100644 --- a/lib/matplotlib/patches.pyi +++ b/lib/matplotlib/patches.pyi @@ -259,8 +259,8 @@ class Ellipse(Patch): def get_corners(self) -> np.ndarray: ... - def get_vertices(self) -> list[float, float]: ... - def get_co_vertices(self) -> list[float, float]: ... + def get_vertices(self) -> list[tuple[float, float], tuple[float, float]]: ... + def get_co_vertices(self) -> list[tuple[float, float], tuple[float, float]]: ... class Annulus(Patch): a: float From 03869252a557bf54861090b9efe31866ed1ebbf2 Mon Sep 17 00:00:00 2001 From: Photoniker <17592823+photoniker@users.noreply.github.com> Date: Mon, 1 May 2023 14:40:50 +0200 Subject: [PATCH 20/33] Update patches.pyi --- lib/matplotlib/patches.pyi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/patches.pyi b/lib/matplotlib/patches.pyi index 6f1a9b45a2db..17ce9d6b21ff 100644 --- a/lib/matplotlib/patches.pyi +++ b/lib/matplotlib/patches.pyi @@ -259,8 +259,8 @@ class Ellipse(Patch): def get_corners(self) -> np.ndarray: ... - def get_vertices(self) -> list[tuple[float, float], tuple[float, float]]: ... - def get_co_vertices(self) -> list[tuple[float, float], tuple[float, float]]: ... + def get_vertices(self) -> list[tuple[float, float]]: ... + def get_co_vertices(self) -> list[tuple[float, float]]: ... class Annulus(Patch): a: float From f23854ddfded14dce3d094dd3db677481a239696 Mon Sep 17 00:00:00 2001 From: Johann Krauter Date: Mon, 1 May 2023 14:46:45 +0200 Subject: [PATCH 21/33] overseen some whitespaces, sorry --- lib/matplotlib/patches.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/patches.pyi b/lib/matplotlib/patches.pyi index 6f1a9b45a2db..fd0262c4f4a0 100644 --- a/lib/matplotlib/patches.pyi +++ b/lib/matplotlib/patches.pyi @@ -258,7 +258,7 @@ class Ellipse(Patch): angle = property(get_angle, set_angle) def get_corners(self) -> np.ndarray: ... - + def get_vertices(self) -> list[tuple[float, float], tuple[float, float]]: ... def get_co_vertices(self) -> list[tuple[float, float], tuple[float, float]]: ... From 135d7cb1387d61dae9b1696b2dd3f21217d02d1d Mon Sep 17 00:00:00 2001 From: Johann Krauter Date: Mon, 1 May 2023 14:55:33 +0200 Subject: [PATCH 22/33] soved isort fail. How to solve the subs fail? --- galleries/examples/shapes_and_collections/ellipse_arrow.py | 2 +- lib/matplotlib/patches.pyi | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/galleries/examples/shapes_and_collections/ellipse_arrow.py b/galleries/examples/shapes_and_collections/ellipse_arrow.py index 3b53beca7d4a..09f527fcfa55 100644 --- a/galleries/examples/shapes_and_collections/ellipse_arrow.py +++ b/galleries/examples/shapes_and_collections/ellipse_arrow.py @@ -10,11 +10,11 @@ """ import matplotlib.pyplot as plt + from matplotlib.markers import MarkerStyle from matplotlib.patches import Ellipse from matplotlib.transforms import Affine2D - # Create a figure and axis fig, ax = plt.subplots(subplot_kw={"aspect": "equal"}) diff --git a/lib/matplotlib/patches.pyi b/lib/matplotlib/patches.pyi index e9302563083c..6efb9e3347fc 100644 --- a/lib/matplotlib/patches.pyi +++ b/lib/matplotlib/patches.pyi @@ -259,8 +259,8 @@ class Ellipse(Patch): def get_corners(self) -> np.ndarray: ... - def get_vertices(self) -> list[tuple[float, float]]: ... - def get_co_vertices(self) -> list[tuple[float, float]]: ... + def get_vertices(self) -> tuple[float, float]: ... + def get_co_vertices(self) -> tuple[float, float]: ... class Annulus(Patch): From 9776379ac9f87389f0dcedda1f7ed79d44564e39 Mon Sep 17 00:00:00 2001 From: Johann Krauter Date: Mon, 1 May 2023 19:52:14 +0200 Subject: [PATCH 23/33] added some more unittest, just in case... --- lib/matplotlib/tests/test_patches.py | 36 ++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/lib/matplotlib/tests/test_patches.py b/lib/matplotlib/tests/test_patches.py index f72bce85ec05..90332e5573b7 100644 --- a/lib/matplotlib/tests/test_patches.py +++ b/lib/matplotlib/tests/test_patches.py @@ -125,6 +125,42 @@ def test_ellipse_vertices(): ], ) + assert_almost_equal( + Ellipse(xy=(0, 0), width=0, height=0, angle=0).get_vertices(), + [(0.0, 0.0), (0.0, 0.0)], + ) + assert_almost_equal( + Ellipse(xy=(0, 0), width=0, height=0, angle=0).get_co_vertices(), + [(0.0, 0.0), (0.0, 0.0)], + ) + + assert_almost_equal( + Ellipse(xy=(0, 0), width=1, height=0, angle=0).get_vertices(), + [(-0.5, 0.0), (0.5, 0.0)], + ) + assert_almost_equal( + Ellipse(xy=(0, 0), width=1, height=0, angle=0).get_co_vertices(), + [(0.0, 0.0), (0.0, 0.0)], + ) + + assert_almost_equal( + Ellipse(xy=(0, 0), width=1, height=1, angle=0).get_vertices(), + [(-0.5, 0.0), (0.5, 0.0)], + ) + assert_almost_equal( + Ellipse(xy=(0, 0), width=1, height=1, angle=0).get_co_vertices(), + [(0.0, 0.5), (0.0, -0.5)], + ) + + assert_almost_equal( + Ellipse(xy=(0, 0), width=1, height=0.5, angle=90).get_vertices(), + [(0.0, -0.5), (0.0, 0.5)], + ) + assert_almost_equal( + Ellipse(xy=(0, 0), width=1, height=0.5, angle=90).get_co_vertices(), + [(-0.25, 0.0), (0.25, 0.0)], + ) + def test_rotate_rect(): loc = np.asarray([1.0, 2.0]) From 801031f7565bcb2d6b66d46510018621110e6c59 Mon Sep 17 00:00:00 2001 From: Johann Krauter Date: Tue, 2 May 2023 21:14:32 +0200 Subject: [PATCH 24/33] adapted unittest --- lib/matplotlib/tests/test_patches.py | 79 +++++++++++++--------------- 1 file changed, 36 insertions(+), 43 deletions(-) diff --git a/lib/matplotlib/tests/test_patches.py b/lib/matplotlib/tests/test_patches.py index 90332e5573b7..ac26b75231f7 100644 --- a/lib/matplotlib/tests/test_patches.py +++ b/lib/matplotlib/tests/test_patches.py @@ -105,61 +105,54 @@ def test_corner_center(): def test_ellipse_vertices(): - center = (2, 4) - width = 30 - height = 20 - angle = 35 - ellipse = Ellipse(xy=center, width=width, height=height, angle=angle) + # expect 0 for 0 ellipse widht, height + ellipse = Ellipse(xy=(0, 0), width=0, height=0, angle=0) assert_almost_equal( ellipse.get_vertices(), - [ - (-10.287280664334878, -4.60364654526569), - (14.287280664334878, 12.60364654526569), - ], - ) - assert_almost_equal( - ellipse.get_co_vertices(), - [ - (-3.7357643635104605, 12.191520442889917), - (7.7357643635104605, -4.191520442889917), - ], - ) - - assert_almost_equal( - Ellipse(xy=(0, 0), width=0, height=0, angle=0).get_vertices(), [(0.0, 0.0), (0.0, 0.0)], ) assert_almost_equal( - Ellipse(xy=(0, 0), width=0, height=0, angle=0).get_co_vertices(), - [(0.0, 0.0), (0.0, 0.0)], - ) - - assert_almost_equal( - Ellipse(xy=(0, 0), width=1, height=0, angle=0).get_vertices(), - [(-0.5, 0.0), (0.5, 0.0)], - ) - assert_almost_equal( - Ellipse(xy=(0, 0), width=1, height=0, angle=0).get_co_vertices(), + ellipse.get_co_vertices(), [(0.0, 0.0), (0.0, 0.0)], ) + ellipse = Ellipse(xy=(0, 0), width=2, height=1, angle=30) assert_almost_equal( - Ellipse(xy=(0, 0), width=1, height=1, angle=0).get_vertices(), - [(-0.5, 0.0), (0.5, 0.0)], - ) - assert_almost_equal( - Ellipse(xy=(0, 0), width=1, height=1, angle=0).get_co_vertices(), - [(0.0, 0.5), (0.0, -0.5)], - ) - - assert_almost_equal( - Ellipse(xy=(0, 0), width=1, height=0.5, angle=90).get_vertices(), - [(0.0, -0.5), (0.0, 0.5)], + ellipse.get_vertices(), + [ + ( + ellipse.center[0] - ellipse.width / 4 * np.sqrt(3), + ellipse.center[1] - ellipse.width / 4, + ), + ( + ellipse.center[0] + ellipse.width / 4 * np.sqrt(3), + ellipse.center[1] + ellipse.width / 4, + ), + ], ) assert_almost_equal( - Ellipse(xy=(0, 0), width=1, height=0.5, angle=90).get_co_vertices(), - [(-0.25, 0.0), (0.25, 0.0)], + ellipse.get_co_vertices(), + [ + ( + ellipse.center[0] - ellipse.height / 4, + ellipse.center[1] + ellipse.height / 4 * np.sqrt(3), + ), + ( + ellipse.center[0] + ellipse.height / 4, + ellipse.center[1] - ellipse.height / 4 * np.sqrt(3), + ), + ], ) + v1, v2 = np.array(ellipse.get_vertices()) + np.testing.assert_almost_equal((v1 + v2) / 2, ellipse.center) + v1, v2 = np.array(ellipse.get_co_vertices()) + np.testing.assert_almost_equal((v1 + v2) / 2, ellipse.center) + + ellipse = Ellipse(xy=(2.252, -10.859), width=2.265, height=1.98, angle=68.78) + v1, v2 = np.array(ellipse.get_vertices()) + np.testing.assert_almost_equal((v1 + v2) / 2, ellipse.center) + v1, v2 = np.array(ellipse.get_co_vertices()) + np.testing.assert_almost_equal((v1 + v2) / 2, ellipse.center) def test_rotate_rect(): From 3a4ee04188d684428313ebbe255f4a277646d42e Mon Sep 17 00:00:00 2001 From: Johann Krauter Date: Tue, 2 May 2023 21:19:02 +0200 Subject: [PATCH 25/33] adapted stubs file --- lib/matplotlib/patches.pyi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/patches.pyi b/lib/matplotlib/patches.pyi index 6efb9e3347fc..e9302563083c 100644 --- a/lib/matplotlib/patches.pyi +++ b/lib/matplotlib/patches.pyi @@ -259,8 +259,8 @@ class Ellipse(Patch): def get_corners(self) -> np.ndarray: ... - def get_vertices(self) -> tuple[float, float]: ... - def get_co_vertices(self) -> tuple[float, float]: ... + def get_vertices(self) -> list[tuple[float, float]]: ... + def get_co_vertices(self) -> list[tuple[float, float]]: ... class Annulus(Patch): From 46898de656ef0ef828b060b3fa79bc73770262ba Mon Sep 17 00:00:00 2001 From: Johann Krauter Date: Tue, 2 May 2023 21:43:15 +0200 Subject: [PATCH 26/33] resolve pre-commit codespell --- lib/matplotlib/tests/test_patches.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/tests/test_patches.py b/lib/matplotlib/tests/test_patches.py index ac26b75231f7..416242de4d39 100644 --- a/lib/matplotlib/tests/test_patches.py +++ b/lib/matplotlib/tests/test_patches.py @@ -105,7 +105,7 @@ def test_corner_center(): def test_ellipse_vertices(): - # expect 0 for 0 ellipse widht, height + # expect 0 for 0 ellipse width, height ellipse = Ellipse(xy=(0, 0), width=0, height=0, angle=0) assert_almost_equal( ellipse.get_vertices(), From 28437f1e231fd57566953947fe3613ab40b41664 Mon Sep 17 00:00:00 2001 From: Photoniker <17592823+photoniker@users.noreply.github.com> Date: Mon, 8 May 2023 16:00:07 +0200 Subject: [PATCH 27/33] Update galleries/examples/shapes_and_collections/ellipse_arrow.py Co-authored-by: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> --- .../shapes_and_collections/ellipse_arrow.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/galleries/examples/shapes_and_collections/ellipse_arrow.py b/galleries/examples/shapes_and_collections/ellipse_arrow.py index 09f527fcfa55..1f0739d6f872 100644 --- a/galleries/examples/shapes_and_collections/ellipse_arrow.py +++ b/galleries/examples/shapes_and_collections/ellipse_arrow.py @@ -18,16 +18,11 @@ # Create a figure and axis fig, ax = plt.subplots(subplot_kw={"aspect": "equal"}) -# Define an ellipse clockwise -center = (2, 4) -width = 30 -height = 20 -angle = 35 ellipse = Ellipse( - xy=center, - width=width, - height=height, - angle=angle, + xy=(2, 4), + width=30, + height=20, + angle=35, facecolor="none", edgecolor="b" ) From 3bbe33f65de433fa97c5926ebfc1f8b17a1159cd Mon Sep 17 00:00:00 2001 From: Photoniker <17592823+photoniker@users.noreply.github.com> Date: Mon, 8 May 2023 20:37:00 +0200 Subject: [PATCH 28/33] Some correction :lipstick: ellipse_arrow.py --- galleries/examples/shapes_and_collections/ellipse_arrow.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/galleries/examples/shapes_and_collections/ellipse_arrow.py b/galleries/examples/shapes_and_collections/ellipse_arrow.py index 1f0739d6f872..4bcdc016faa6 100644 --- a/galleries/examples/shapes_and_collections/ellipse_arrow.py +++ b/galleries/examples/shapes_and_collections/ellipse_arrow.py @@ -28,7 +28,7 @@ ) ax.add_patch(ellipse) -# Plot a arrow marker at the end point of minor axis +# Plot an arrow marker at the end point of minor axis vertices = ellipse.get_co_vertices() t = Affine2D().rotate_deg(ellipse.angle) ax.plot( From 9cbe4ef82a994454ca48d5b4ee3df51e0f7c0f40 Mon Sep 17 00:00:00 2001 From: Johann Krauter Date: Wed, 10 May 2023 08:06:10 +0200 Subject: [PATCH 29/33] added get_vertices_co_vertices.rst to next_whats_new folder --- doc/users/next_whats_new/get_vertices_co_vertices.rst | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 doc/users/next_whats_new/get_vertices_co_vertices.rst diff --git a/doc/users/next_whats_new/get_vertices_co_vertices.rst b/doc/users/next_whats_new/get_vertices_co_vertices.rst new file mode 100644 index 000000000000..98254a82ce63 --- /dev/null +++ b/doc/users/next_whats_new/get_vertices_co_vertices.rst @@ -0,0 +1,7 @@ +``Ellipse.get_vertices()``, ``Ellipse.get_co_vertices()`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +These methods return the coordinates of ellipse vertices of +major and minor axis. Additionally, an example gallery demo is added which +shows how to add an arrow to an ellipse showing a clockwise or counter-clockwise +rotation of the ellipse. To place the arrow exactly on the ellipse, +the coordinates of the vertices are used. From 49d89d148f18fba10e5258aa0998827e39140538 Mon Sep 17 00:00:00 2001 From: photoniker Date: Sat, 13 May 2023 10:17:24 +0200 Subject: [PATCH 30/33] Update patches.py by .. versionadded:: 3.8 --- lib/matplotlib/patches.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/matplotlib/patches.py b/lib/matplotlib/patches.py index faf070aadcf1..76be484d3d66 100644 --- a/lib/matplotlib/patches.py +++ b/lib/matplotlib/patches.py @@ -1659,6 +1659,8 @@ def get_vertices(self): Return the left and right vertex coordinates of the ellipse. The definition can be found `here `_ + + .. versionadded:: 3.8 """ x0 = self._center[0] - self._width / 2 * np.cos(np.deg2rad(self._angle)) y0 = self._center[1] - self._width / 2 * np.sin(np.deg2rad(self._angle)) @@ -1671,6 +1673,8 @@ def get_co_vertices(self): Return the left and right co-vertex coordinates of the ellipse. The definition can be found `here `_ + + .. versionadded:: 3.8 """ x0 = self._center[0] - self._height / 2 * np.sin(np.deg2rad(self._angle)) y0 = self._center[1] + self._height / 2 * np.cos(np.deg2rad(self._angle)) From 501436fc575193b1e380edce35215daabf1292ee Mon Sep 17 00:00:00 2001 From: Johann Krauter Date: Sat, 13 May 2023 22:21:38 +0200 Subject: [PATCH 31/33] get_vertices and get_co_vertices returns now the coordinates of the major and minor axis depending on the length between the coordinates of points --- lib/matplotlib/patches.py | 50 +++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/lib/matplotlib/patches.py b/lib/matplotlib/patches.py index 76be484d3d66..2dcaa488e65e 100644 --- a/lib/matplotlib/patches.py +++ b/lib/matplotlib/patches.py @@ -1654,33 +1654,59 @@ def get_corners(self): return self.get_patch_transform().transform( [(-1, -1), (1, -1), (1, 1), (-1, 1)]) + def _calculate_length_between_points(self, x0, y0, x1, y1): + return np.sqrt((x1 - x0)**2 + (y1 - y0)**2) + + def _calculate_vertices_coordinates(self, return_major: bool = True): + # calculate the vertices of width axis + w_x0 = self._center[0] - self._width / 2 * np.cos(np.deg2rad(self._angle)) + w_y0 = self._center[1] - self._width / 2 * np.sin(np.deg2rad(self._angle)) + w_x1 = self._center[0] + self._width / 2 * np.cos(np.deg2rad(self._angle)) + w_y1 = self._center[1] + self._width / 2 * np.sin(np.deg2rad(self._angle)) + + # calculate the vertices of height axis + h_x0 = self._center[0] - self._height / 2 * np.sin(np.deg2rad(self._angle)) + h_y0 = self._center[1] + self._height / 2 * np.cos(np.deg2rad(self._angle)) + h_x1 = self._center[0] + self._height / 2 * np.sin(np.deg2rad(self._angle)) + h_y1 = self._center[1] - self._height / 2 * np.cos(np.deg2rad(self._angle)) + + if self._calculate_length_between_points( + w_x0, w_y0, w_x1, w_y1 + ) >= self._calculate_length_between_points( + h_x0, h_y0, h_x1, h_y1 + ): # width is major + major = [(w_x0, w_y0), (w_x1, w_y1)] + minor = [(h_x0, h_y0), (h_x1, h_y1)] + else: # minor + major = [(h_x0, h_y0), (h_x1, h_y1)] + minor = [(w_x0, w_y0), (w_x1, w_y1)] + + if return_major: + coordinates = major + else: + coordinates = minor + + return coordinates + def get_vertices(self): """ - Return the left and right vertex coordinates of the ellipse. + Return the vertices coordinates of the ellipse. The definition can be found `here `_ .. versionadded:: 3.8 """ - x0 = self._center[0] - self._width / 2 * np.cos(np.deg2rad(self._angle)) - y0 = self._center[1] - self._width / 2 * np.sin(np.deg2rad(self._angle)) - x1 = self._center[0] + self._width / 2 * np.cos(np.deg2rad(self._angle)) - y1 = self._center[1] + self._width / 2 * np.sin(np.deg2rad(self._angle)) - return [(x0, y0), (x1, y1)] + return self._calculate_vertices_coordinates() def get_co_vertices(self): """ - Return the left and right co-vertex coordinates of the ellipse. + Return the co-vertices coordinates of the ellipse. The definition can be found `here `_ .. versionadded:: 3.8 """ - x0 = self._center[0] - self._height / 2 * np.sin(np.deg2rad(self._angle)) - y0 = self._center[1] + self._height / 2 * np.cos(np.deg2rad(self._angle)) - x1 = self._center[0] + self._height / 2 * np.sin(np.deg2rad(self._angle)) - y1 = self._center[1] - self._height / 2 * np.cos(np.deg2rad(self._angle)) - return [(x0, y0), (x1, y1)] + return self._calculate_vertices_coordinates(return_major=False) class Annulus(Patch): From cf6e95ac01969e68b1b33e57a08d81d40cd7e1b4 Mon Sep 17 00:00:00 2001 From: Johann Krauter Date: Tue, 16 May 2023 09:04:38 +0200 Subject: [PATCH 32/33] Changed get_vertices and get_co_vertices using get_patch_transform().transform() for coordinate calculations. --- lib/matplotlib/patches.py | 43 +++++++++------------------------------ 1 file changed, 10 insertions(+), 33 deletions(-) diff --git a/lib/matplotlib/patches.py b/lib/matplotlib/patches.py index 2dcaa488e65e..ecf03ca4051b 100644 --- a/lib/matplotlib/patches.py +++ b/lib/matplotlib/patches.py @@ -1657,37 +1657,6 @@ def get_corners(self): def _calculate_length_between_points(self, x0, y0, x1, y1): return np.sqrt((x1 - x0)**2 + (y1 - y0)**2) - def _calculate_vertices_coordinates(self, return_major: bool = True): - # calculate the vertices of width axis - w_x0 = self._center[0] - self._width / 2 * np.cos(np.deg2rad(self._angle)) - w_y0 = self._center[1] - self._width / 2 * np.sin(np.deg2rad(self._angle)) - w_x1 = self._center[0] + self._width / 2 * np.cos(np.deg2rad(self._angle)) - w_y1 = self._center[1] + self._width / 2 * np.sin(np.deg2rad(self._angle)) - - # calculate the vertices of height axis - h_x0 = self._center[0] - self._height / 2 * np.sin(np.deg2rad(self._angle)) - h_y0 = self._center[1] + self._height / 2 * np.cos(np.deg2rad(self._angle)) - h_x1 = self._center[0] + self._height / 2 * np.sin(np.deg2rad(self._angle)) - h_y1 = self._center[1] - self._height / 2 * np.cos(np.deg2rad(self._angle)) - - if self._calculate_length_between_points( - w_x0, w_y0, w_x1, w_y1 - ) >= self._calculate_length_between_points( - h_x0, h_y0, h_x1, h_y1 - ): # width is major - major = [(w_x0, w_y0), (w_x1, w_y1)] - minor = [(h_x0, h_y0), (h_x1, h_y1)] - else: # minor - major = [(h_x0, h_y0), (h_x1, h_y1)] - minor = [(w_x0, w_y0), (w_x1, w_y1)] - - if return_major: - coordinates = major - else: - coordinates = minor - - return coordinates - def get_vertices(self): """ Return the vertices coordinates of the ellipse. @@ -1696,7 +1665,11 @@ def get_vertices(self): .. versionadded:: 3.8 """ - return self._calculate_vertices_coordinates() + if self.width < self.height: + ret = self.get_patch_transform().transform([(0, 1), (0, -1)]) + else: + ret = self.get_patch_transform().transform([(1, 0), (-1, 0)]) + return [tuple(x) for x in ret] def get_co_vertices(self): """ @@ -1706,7 +1679,11 @@ def get_co_vertices(self): .. versionadded:: 3.8 """ - return self._calculate_vertices_coordinates(return_major=False) + if self.width < self.height: + ret = self.get_patch_transform().transform([(1, 0), (-1, 0)]) + else: + ret = self.get_patch_transform().transform([(0, 1), (0, -1)]) + return [tuple(x) for x in ret] class Annulus(Patch): From 896a7754d16bfe4b419297d73732823fdc50e774 Mon Sep 17 00:00:00 2001 From: Johann Krauter Date: Tue, 16 May 2023 12:53:57 +0200 Subject: [PATCH 33/33] fix in unittest due to different ordering of vertices return values --- lib/matplotlib/tests/test_patches.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/matplotlib/tests/test_patches.py b/lib/matplotlib/tests/test_patches.py index 416242de4d39..fd872bac98d4 100644 --- a/lib/matplotlib/tests/test_patches.py +++ b/lib/matplotlib/tests/test_patches.py @@ -120,14 +120,14 @@ def test_ellipse_vertices(): assert_almost_equal( ellipse.get_vertices(), [ - ( - ellipse.center[0] - ellipse.width / 4 * np.sqrt(3), - ellipse.center[1] - ellipse.width / 4, - ), ( ellipse.center[0] + ellipse.width / 4 * np.sqrt(3), ellipse.center[1] + ellipse.width / 4, ), + ( + ellipse.center[0] - ellipse.width / 4 * np.sqrt(3), + ellipse.center[1] - ellipse.width / 4, + ), ], ) assert_almost_equal(