Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Adding ellipse_arrow.py example and closes #25477 #25779

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 34 commits into from
Jun 12, 2023

Conversation

photoniker
Copy link
Contributor

@photoniker photoniker commented Apr 27, 2023

PR Summary

In this PR I want to add a Demo file. This Demo shows how an ellipse is plotted with an additional arrow showing the orientation of rotation.

image

Closes #25477
pre-commit.ci autofix

PR Checklist

Linked Issue

  • Added "closes #0000" in the PR description to link it to the original issue.

Documentation and Tests

  • Has pytest style unit tests (and pytest passes)
  • Documentation is sphinx and numpydoc compliant (the docs should build without error).
  • New plotting related features are documented with examples.

Release Notes

  • New features are marked with a .. versionadded:: directive in the docstring and documented in doc/users/next_whats_new/
  • API changes are marked with a .. versionchanged:: directive in the docstring and documented in doc/api/next_api_changes/
  • Release notes conform with instructions in next_whats_new/README.rst or next_api_changes/README.rst

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Thank you for opening your first PR into Matplotlib!

If you have not heard from us in a while, please feel free to ping @matplotlib/developers or anyone who has commented on the PR. Most of our reviewers are volunteers and sometimes things fall through the cracks.

You can also join us on gitter for real-time discussion.

For details on testing, writing docs, and our review process, please see the developer guide

We strive to be a welcoming and open project. Please follow our Code of Conduct.

@photoniker photoniker changed the title Adding ellipse_arrow.py example and fix #25477 Adding ellipse_arrow.py example and closes #25477 Apr 28, 2023
@timhoffm
Copy link
Member

Unfortunately, arrow() is not a good way to draw the arrow head. It is affected by Axes aspect ration and limits (see the note at the bottom of https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.arrow.html). Likely, the clean solution is to draw a single trangular marker and rotate it according to https://matplotlib.org/stable/gallery/lines_bars_and_markers/marker_reference.html#advanced-marker-modifications-with-transform.

@ksunden
Copy link
Member

ksunden commented Apr 29, 2023

FYI, the "Closes #25477" needs to go in the body of the PR description to automatically link, not the title. I've gone ahead and added it for this one

…end point position of the ellipse minor axis rotated by the transform.Affine2D method.
@photoniker
Copy link
Contributor Author

photoniker commented Apr 29, 2023

I changed the demo in the last commit to use paches.Ellipse and a marker rotated by transform.Affine2D.

One example almost looks a little sad. Do you want me to add anything more?

Copy link
Member

@timhoffm timhoffm left a comment

Choose a reason for hiding this comment

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

Examples should focus on their main aspect. Less code makes them more comprehensible.

Not sure we need two ellipses. You could also just write

Note: To reverse the orientation arrow, switch the marker type from > to <.

and only show one ellipse, which would remove again half of the code an the need for legend and labels.

Copy link
Member

@timhoffm timhoffm left a comment

Choose a reason for hiding this comment

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

Also, please add your new functions to the type stubs

class Ellipse(Patch):

@photoniker
Copy link
Contributor Author

How do I solve the failed checks? @matplotlib/developers

@timhoffm
Copy link
Member

timhoffm commented May 8, 2023

How do I solve the failed checks? @matplotlib/developers

The failures in the OSX build pipeline are unrelated to this PR and can be ignored.

@timhoffm timhoffm added this to the v3.8.0 milestone May 8, 2023
@photoniker
Copy link
Contributor Author

@timhoffm Thanks for approving! How is responsible to do the Release Note actions metioned by GitHub actions? Or is there something else for me to do?

@story645
Copy link
Member

story645 commented May 9, 2023

How is responsible to do the Release Note actions metioned by GitHub actions? Or is there something else for me to do?

If you've got the time, please write release notes about the new functions-otherwise I put on the new feature label so we can find this at release time and hopefully catch that the notes are missing.

They can be really simple-something like https://github.com/matplotlib/matplotlib/blob/main/doc/users/next_whats_new/get_suptitle.rst

Ellipse.get_vertices() and Ellipse.get_co_vertices()
These methods return the vertices and co vertices of the Ellipse

Copy link
Member

@ksunden ksunden left a comment

Choose a reason for hiding this comment

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

I think the distinction between "vertex" and "co-vertex" is unclear here...

By the source (wiki article) listed, I believe that a "vertex" should be on the line defined by the foci, and a "co-vertex" should be on the perpendicular bisector of the foci.

Here, we define the ellipse by its bounding box, rather than by its foci.

If it is defined with height > width, then I think the definition would be reversed from if height < width, but the computation does not account for that.

Additionally, "left" vs "right" doesn't necessarily make sense (They could be aligned along the vertical axis, and even if they aren't then it's not really adding anything to the definition)

Perhaps this could be implemented as a single function that returns all four points, without necessarily specifying order?

Finally, should probably have a .. versionadded:: 3.8 directive in the docstring if we are trying to do that.

@ksunden
Copy link
Member

ksunden commented May 12, 2023

I think it could be implemented as get_corners is:

    def get_corners(self):
        """
        Return the corners of the ellipse bounding box.

        The bounding box orientation is moving anti-clockwise from the
        lower left corner defined before rotation.
        """
        return self.get_patch_transform().transform(
            [(-1, -1), (1, -1), (1, 1), (-1, 1)])
            
    def get_vertices(self):
        """
        Return the vertices and covertices of the ellipse.

        ...Maybe look at order that would be desired
        """
        return self.get_patch_transform().transform(
            [(0, 1), (1, 0), (0, -1), (-1, 0)])

@photoniker
Copy link
Contributor Author

I think the distinction between "vertex" and "co-vertex" is unclear here...

By the source (wiki article) listed, I believe that a "vertex" should be on the line defined by the foci, and a "co-vertex" should be on the perpendicular bisector of the foci.

Here, we define the ellipse by its bounding box, rather than by its foci.

If it is defined with height > width, then I think the definition would be reversed from if height < width, but the computation does not account for that.

Additionally, "left" vs "right" doesn't necessarily make sense (They could be aligned along the vertical axis, and even if they aren't then it's not really adding anything to the definition)

Perhaps this could be implemented as a single function that returns all four points, without necessarily specifying order?

Finally, should probably have a .. versionadded:: 3.8 directive in the docstring if we are trying to do that.

I agree by defining width and height it is not clear which is the minor or major axis. But I understand the definiton of vertex and co-vertex as the end points of such axes not related to the foci!?

Screenshot_2023-05-13-09-32-32-256_org.wikipedia-edit.jpg

Would it be clear if depending on the length of the major and minor axes the vertex are returned?

@photoniker
Copy link
Contributor Author

I think the distinction between "vertex" and "co-vertex" is unclear here...

By the source (wiki article) listed, I believe that a "vertex" should be on the line defined by the foci, and a "co-vertex" should be on the perpendicular bisector of the foci.

Here, we define the ellipse by its bounding box, rather than by its foci.

If it is defined with height > width, then I think the definition would be reversed from if height < width, but the computation does not account for that.

Additionally, "left" vs "right" doesn't necessarily make sense (They could be aligned along the vertical axis, and even if they aren't then it's not really adding anything to the definition)

Perhaps this could be implemented as a single function that returns all four points, without necessarily specifying order?

Finally, should probably have a .. versionadded:: 3.8 directive in the docstring if we are trying to do that.

I agree by defining width and height it is not clear which is the minor or major axis. But I understand the definiton of vertex and co-vertex as the end points of such axes not related to the foci!?

Screenshot_2023-05-13-09-32-32-256_org.wikipedia-edit.jpg

Would it be clear if depending on the length of the major and minor axes the vertex are returned? Circle of course is a special case...

photoniker and others added 2 commits May 13, 2023 10:17
…ajor and minor axis depending on the length between the coordinates of points
@timhoffm
Copy link
Member

Perhaps this could be implemented as a single function that returns all four points, without necessarily specifying order?

@ksunden I believe it's important to be able to distinguish between the vertices and covertices easily. A single function makes this hard (even if it had a guarantee on the order). I therefore believe that the two separate functions are the right API choice.

@ksunden
Copy link
Member

ksunden commented May 15, 2023

I agree by defining width and height it is not clear which is the minor or major axis. But I understand the definiton of vertex and co-vertex as the end points of such axes not related to the foci!?

I mean, the foci definition is exactly the same.

From the wiki article, section "Definition as a locus of points":

The line through the foci is called the major axis, and the line perpendicular to it through the center is the minor axis.

I do stand by that computing using the transform as is done for the get_corners method is still possible and cleaner:

def get_vertices(self):
    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):
    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]

I will also point out that the Ellipse patch already has a get_verts method (via Patch, though it is related to the Bezier segments used to approximate the ellipse) and find this a potentially significant point of confusion. I will defer to @timhoffm for whether or not that name collision is a significant concern, though.

@photoniker
Copy link
Contributor Author

I agree by defining width and height it is not clear which is the minor or major axis. But I understand the definiton of vertex and co-vertex as the end points of such axes not related to the foci!?

I mean, the foci definition is exactly the same.

From the wiki article, section "Definition as a locus of points":

The line through the foci is called the major axis, and the line perpendicular to it through the center is the minor axis.

I do stand by that computing using the transform as is done for the get_corners method is still possible and cleaner:

def get_vertices(self):
    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):
    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]

I will also point out that the Ellipse patch already has a get_verts method (via Patch, though it is related to the Bezier segments used to approximate the ellipse) and find this a potentially significant point of confusion. I will defer to @timhoffm for whether or not that name collision is a significant concern, though.

Ok, I understand. get_patch_transform().transform() is doing the same thing. So it makes it cleaner. Didn't know that methods. Thanks.

@timhoffm
Copy link
Member

I will also point out that the Ellipse patch already has a get_verts method (via Patch, though it is related to the Bezier segments used to approximate the ellipse) and find this a potentially significant point of confusion. I will defer to @timhoffm for whether or not that name collision is a significant concern, though.

The naming similarity is not so nice but it's the best we can do: Changing the existing API get_verts does not make sense. The technical names for the points here are vertex and co-vertex. We should use them for clarity.

My approval still stands.

@ksunden ksunden dismissed their stale review June 12, 2023 15:40

Implementation has been adjusted, and api concerns approved by Tim

@ksunden ksunden merged commit c3a2794 into matplotlib:main Jun 12, 2023
@oscargus oscargus mentioned this pull request Jul 19, 2023
5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Development

Successfully merging this pull request may close these issues.

Plot ellipse with arrow showing rotation
5 participants