Search code examples
matplotlibplotorientationcurve

Contour/curve with orientation


How would I plot a curve (in 3d perhaps) with something to show the direction that it's going. For example, to show that a circular plane curve is going clockwise or counterclockwise.

A curve like the one here, http://mathworld.wolfram.com/CauchyIntegralFormula.html

I am not sure even if there is a comparable function right now, so I don't have an example to show you. Thanks for reading.

Edit: I search quite a bit on this, don't think you can do this on gnuplot either.


Solution

  • Interesting question. I have no time for more than a quick and dirty hack, so here we go (liberally inspired from the code in mpl streamplot)

    import matplotlib.lines as mlines
    import matplotlib.patches as mpatches
    import matplotlib.pyplot as plt
    import numpy as np
    
    def add_arrow_to_line2D(
        axes, line, arrow_locs=[0.2, 0.4, 0.6, 0.8],
        arrowstyle='-|>', arrowsize=1, transform=None):
        """
        Add arrows to a matplotlib.lines.Line2D at selected locations.
    
        Parameters:
        -----------
        axes: 
        line: list of 1 Line2D obbject as returned by plot command
        arrow_locs: list of locations where to insert arrows, % of total length
        arrowstyle: style of the arrow
        arrowsize: size of the arrow
        transform: a matplotlib transform instance, default to data coordinates
    
        Returns:
        --------
        arrows: list of arrows
        """
        if (not(isinstance(line, list)) or not(isinstance(line[0], 
                                               mlines.Line2D))):
            raise ValueError("expected a matplotlib.lines.Line2D object")
        x, y = line[0].get_xdata(), line[0].get_ydata()
    
        arrow_kw = dict(arrowstyle=arrowstyle, mutation_scale=10 * arrowsize)
        if transform is None:
            transform = axes.transData
    
        arrows = []
        for loc in arrow_locs:
            s = np.cumsum(np.sqrt(np.diff(x) ** 2 + np.diff(y) ** 2))
            n = np.searchsorted(s, s[-1] * loc)
            arrow_tail = (x[n], y[n])
            arrow_head = (np.mean(x[n:n + 2]), np.mean(y[n:n + 2]))
            p = mpatches.FancyArrowPatch(
                arrow_tail, arrow_head, transform=transform,
                **arrow_kw)
            axes.add_patch(p)
            arrows.append(p)
        return arrows
    
    
    fig, ax = plt.subplots(1, 1)
    t = np.linspace(0., 4*np.pi, 100.)
    line = ax.plot(np.log(t+1)*np.cos(t), np.log(t+1)*np.sin(t),"-")
    add_arrow_to_line2D(ax, line, arrow_locs=[0.1, 0.2, 0.3, 0.4, 0.6, 0.8, 0.99],
                        arrowsize=1.5)
    
    ax.axis("equal")
    ax.set_xlim([-4., 4.])
    ax.set_ylim([-4., 4.])
    plt.show()
    

    enter image description here