Unable to rotate a matplotlib patch object about a specific point using rotate_around( )

前端 未结 3 548
梦谈多话
梦谈多话 2021-01-19 09:32

I am trying to rotate a matplotlib rectangular patch object about a specific point using the rotate_around() and rotate_deg_around() functions. However, the patch is always

相关标签:
3条回答
  • 2021-01-19 09:54

    The coordinates you rotate around are not the data coordinates. You have to transform them first, i.e.

    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.patches as patches
    import matplotlib as mpl
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.set_xlim(-0.05,1);ax.set_ylim(-0.05,1);
    plt.grid('on');
    
    #Rotate rectangle patch object
    ts = ax.transData
    coords = ts.transform([0.2, 0.5])
    tr = mpl.transforms.Affine2D().rotate_deg_around(coords[0], coords[1], 10)
    t= ts + tr
    
    rec0 = patches.Rectangle((0.2,0.5),0.25,0.2,alpha=0.5)
    ax.add_patch(rec0)
    
    #Rotated rectangle patch
    rect1 = patches.Rectangle((0.2,0.5),0.25,0.2,color='blue',alpha=0.5,transform=t)
    ax.add_patch(rect1);
    
    #The (desired) point of rotation
    ax.scatter([0.0,0.2],[0.0,0.5],c=['g','r'],zorder=10)
    txt = ax.annotate('Desired point of rotation',xy=(0.2,0.5),fontsize=16,\
    xytext=(0.25,0.35),arrowprops=dict(arrowstyle="->",connectionstyle="arc3,rad=-.2"))
    txt2 = ax.annotate('Actual point of rotation',xy=(0.0,0.0),fontsize=16,\
    xytext=(0.15,0.15),arrowprops=dict(arrowstyle="->",connectionstyle="arc3,rad=.2"))
    
    plt.show()
    

    Edit:

    Apparently, the code only works for the interactive display, but not when the window is resized or the figure is saved. Compare these two images:

    interactive display saved figure

    0 讨论(0)
  • 2021-01-19 10:04

    @David Zwicker, thanks for pointing me to the right direction. The following code works properly in interactive mode (i.e. can re-size the figure window), executed either independently or within the Ipython QtConsole environment. See the embedded figures below. However, it still doesn't work within an Ipython webnotebook environment! Any help/ideas on that would be great. Thank you.

    #Imports
    import matplotlib.pyplot as plt
    import matplotlib as mpl
    mpl.rcParams['figure.dpi'] = 80   # default = 80
    mpl.rcParams['savefig.dpi'] = 80  # default = 100
    import matplotlib.patches as patches
    import numpy as np
    
    #Need to ensure that the figure.dpi (for displaying figure window) and 
    #savefig.dpi are consistent.
    
    def redraw(event):
        """Redraw the plot on a resize event"""
        if  np.size(plt.get_figlabels()):
            #Need to check if figure is closed or not and only then do the following
            #operations. Else, the following operations will create a new figure
            ax.clear()
            drawRectangles(ax)
            fig.canvas.draw()
        else:
            pass
    
    
    def drawRectangles(ax):
        """Function to draw the normal and rotated patch in the transformed domain"""
        #Transform for data coordinates to display coordinates
        td2dis = ax.transData
        coords = td2dis.transform([0.2, 0.5])
        #rotate transform
        tr = mpl.transforms.Affine2D().rotate_deg_around(coords[0], coords[1], 10)
        t = td2dis + tr
        rec0 = patches.Rectangle((0.2,0.5),0.25,0.2,color='blue',alpha=0.5)
        ax.add_patch(rec0)
        #Rotated rectangle patch
        rect1 = patches.Rectangle((0.2,0.5),0.25,0.2,color='blue',alpha=0.5,transform=t)
        ax.add_patch(rect1);
        plt.grid()
    
    
    figSize = (8,6)
    fig = plt.figure("Patch rotate",figsize=figSize)
    
    ax = fig.add_subplot(111)
    ax.set_xlim(0,1);ax.set_ylim(0,1);
    fig.canvas.mpl_connect('resize_event', redraw)
    drawRectangles(ax)
    
    plt.savefig("myfigure.png")
    plt.show()
    

    Here are some samples from the above code:

    Image saved using the savefig( ) function within the code: enter image description here

    Image saved using the save button in the navigation panel: enter image description here

    Image(s) saved using the save button in the navigation panel after re-sizing: enter image description here enter image description here

    0 讨论(0)
  • 2021-01-19 10:14

    It seems that when saving, Ipython changes the layer out. The transformation for the rotating the rectangle depends on the display coordinate which can be change when zooming or changing the layer out, eg.zooming in the interactive window.

    We can just rotated rectangle in the data coordinate. See Rotating a figure (patch) and applying colors in python

    While we need "ax.set_aspect('equal')" to avoid the rotated rectangle is deformed.

    0 讨论(0)
提交回复
热议问题