2

Suppose the two vectors are defined by the two vertices (1,2,3) and (0,2,-1) from a common point (1,1,1). How to show the acute angle (in a 3D plot by dashed arc) subjected by these two vectors or lines? In my code, I am already using

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

I am a beginner, kindly help.

deltasata
  • 377
  • 1
  • 4
  • 21
  • 1
    There is no command that can automatically do this. You may have to generate a local coordinate system such that the two vectors lie in the x-y plane. Then, you need to generate points lying on the circular arc that lies in the local x-y plane. Finally, you will have to transform the coordinates of these points to global coordinates. If you can write the equations that do all these things, `ax.plot(x,y,z)` can make the arc for you. –  Nov 16 '17 at 05:12
  • Thanks. I though of that but too tedious to do. Instead can I draw a arc by hand with some drawing tool in python? I need the figure in vector format (pdf). Is it possible? – deltasata Nov 16 '17 at 05:21
  • You can use [InkScape](https://inkscape.org/en/). It has nothing to do with Python but you can use it for post-processing. It can export figures as PDF, EPS, SVG etc. It is the open source alternative to [Adobe Illustrator](http://www.adobe.com/products/illustrator.html) –  Nov 16 '17 at 05:24
  • Okay, I will give it a try. I hope the vector format remains unchanged. – deltasata Nov 16 '17 at 05:29
  • Since the question seems to be ending up as "How can I draw something?" I would guess it is off-topic here. – ImportanceOfBeingErnest Nov 16 '17 at 09:38

1 Answers1

1

I had a similar problem, and bashed together the following solution:

import numpy as np
import math
from math import sin, cos
from mpl_toolkits.mplot3d import proj3d

def plot_arc3d(vector1, vector2, radius=0.2, fig=None, colour='C0'):
    """ Plot arc between two given vectors in 3D space. """

    """ Confirm correct input arguments """
    assert len(vector1) == 3
    assert len(vector2) == 3

    """ Calculate vector between two vector end points, and the resulting spherical angles for various points along 
        this vector. From this, derive points that lie along the arc between vector1 and vector2 """
    v = [i-j for i, j in zip(vector1, vector2)]
    v_points_direct = [(vector2[0]+v[0]*l, vector2[1]+v[1]*l, vector2[2]+v[2]*l) for l in np.linspace(0, 1)]
    v_phis = [math.atan2(v_point[1], v_point[0]) for v_point in v_points_direct]
    v_thetas = [math.acos(v_point[2]/np.linalg.norm(v_point)) for v_point in v_points_direct]

    v_points_arc = [(radius*sin(theta)*cos(phi), radius*sin(theta)*sin(phi), radius*cos(theta))
                    for theta, phi in zip(v_thetas, v_phis)]
    v_points_arc.append((0, 0, 0))

    if fig is None:
        fig = plt.figure()
        ax = fig.add_subplot(111, projection='3d')
    else:
        ax = fig.gca()

    from mpl_toolkits.mplot3d.art3d import Poly3DCollection
    """ Plot polygon (face colour must be set afterwards, otherwise it over-rides the transparency)
        https://stackoverflow.com/questions/18897786/transparency-for-poly3dcollection-plot-in-matplotlib """
    points_collection = Poly3DCollection([v_points_arc], alpha=0.4)
    points_collection.set_facecolor(colour)
    ax.add_collection3d(points_collection)

    return fig
Phil G
  • 171
  • 1
  • 9