# Plot simple vectors, that go from the origin of the plane to a given point, in a 3d space

I want to be able to plot simple vectors (not vector fields or anything more fancy) in a 3d space, like some lines each with an arrow head that go from the origin of the plane to any other given point.

The simpler it is to use (input vectors, labels, customize, etc), the better, since this tool is intended to be used in education with a wide range of different ages and experience levels.

I've tried both Matlab and Octave, and through quiver3 I can do stuff like this: Which is ok, but has some issues:

1. With the flexibility of those tools there also comes some complexity cost. In some age ranges and some experience levels I'll lose too much time and attention using them.

2. In Octave, I can't get the axis to pass through the origin! It can be done in Matlab with a 3rd party library, but Matlab is not cheap, and at this task plots end up looking like in Octave anyway.

I'm looking for something more simple to customize and work with, I don't need it to be flexible (I'm looking for very simple customizations, like axis positions, labels, colors, etc), it doesn't need to perform calculations (only need the plot).

As an example, I use Desmos graphic calculator for 2d stuff all the time, while not as flexible and powerful as the above programs, it's very easy to do 2d plots that look great with straight to the point customization.

So, which are the options/alternatives? What do you use for school, work, lab?

## GeoGebra • Easy to use, I obtained the above screenshot by these steps:

• Start GeoGebra
• Select in the menu View -> 3D Graphics
• In the input bar, enter `a = Vector((1, 2, 3))`, for example.
You can also enter a start and end point for direction vectors: `Vector((1, 1, 1), (2, 2, 2))`. Generally, entering any command already shows its possible parameters and overloads in an IntelliSense fashion.
• Labels can be created using the `Text` command: `Text("hello", (1,1,1))`.
Be sure to then right-click the object in the Algebra Pane, select Properties, Advanced and activate "3D Graphics" under Location as per this answer.

• Customizable: by right-clicking any object and selecting Properties, you can change numerous settings, e.g. the font size, color and line style.

General Features:

• Gratis and open source
• Cross-platform
• Can export images to various formats (PNG, EPS and some LaTeX code)
• Has JavaScript scripting support.
• Supports "variable sliders" (think of `<input type="range">` if you know HTML) and their animation/automatic increase & decrease mode every XX milliseconds.

I use it regularly for quickly sketching things or gaining an intuitive understanding of some formulae. One downside, however, is that the input bar/CAS system is sometimes unable to understand some deeply nested commands which are dependent on slider variables.

This sort of thing is ideal to do with python and one of the plotting libraries such as MatPlotLib or Bokeh.

• Free, Gratis & Open Source
• Cross Platform (will run on Windows, Mac or Linux and on a RaspberryPi upwards)
• Small installation
• Flexible
• Plots can be saved and exported as pdf files or images.

A couple of the MatPlotLib examples from the 3D plotting gallery:

## 3D Quiver:

``````==============
3D quiver plot
==============

Demonstrates plotting directional arrows at points on a 3d meshgrid.

from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = fig.gca(projection='3d')

# Make the grid
x, y, z = np.meshgrid(np.arange(-0.8, 1, 0.2),
np.arange(-0.8, 1, 0.2),
np.arange(-0.8, 1, 0.8))

# Make the direction data for the arrows
u = np.sin(np.pi * x) * np.cos(np.pi * y) * np.cos(np.pi * z)
v = -np.cos(np.pi * x) * np.sin(np.pi * y) * np.cos(np.pi * z)
w = (np.sqrt(2.0 / 3.0) * np.cos(np.pi * x) * np.cos(np.pi * y) *
np.sin(np.pi * z))

ax.quiver(x, y, z, u, v, w, length=0.1, normalize=True)

plt.show()
``````

## 3D Text

``````'''
======================
Text annotations in 3D
======================

Demonstrates the placement of text annotations on a 3D plot.

Functionality shown:
- Using the text function with three types of 'zdir' values: None,
an axis name (ex. 'x'), or a direction tuple (ex. (1, 1, 0)).
- Using the text function with the color keyword.
- Using the text2D function to place text on a fixed position on the ax object.
'''

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.gca(projection='3d')

# Demo 1: zdir
zdirs = (None, 'x', 'y', 'z', (1, 1, 0), (1, 1, 1))
xs = (1, 4, 4, 9, 4, 1)
ys = (2, 5, 8, 10, 1, 2)
zs = (10, 3, 8, 9, 1, 8)

for zdir, x, y, z in zip(zdirs, xs, ys, zs):
label = '(%d, %d, %d), dir=%s' % (x, y, z, zdir)
ax.text(x, y, z, label, zdir)

# Demo 2: color
ax.text(9, 0, 0, "red", color='red')

# Demo 3: text2D
# Placement 0, 0 would be the bottom left, 1, 1 would be the top right.
ax.text2D(0.05, 0.95, "2D Text", transform=ax.transAxes)

# Tweaking display region and labels
ax.set_xlim(0, 10)
ax.set_ylim(0, 10)
ax.set_zlim(0, 10)
ax.set_xlabel('X axis')
ax.set_ylabel('Y axis')
ax.set_zlabel('Z axis')

plt.show()
``````

I would also strongly suggest taking a look at Jupyter + the VPython kernel as this opens up more possibilities:

• Free, Gratis & Open Source
• Cross Platform (runs on Windows, OS-X & Linux)
• Interface via the web browser
• Much more interactive
• Animation
• More visually grasping

I would also suggest taking a look at the GlowScript site which makes extensive use of VPython: ``````GlowScript 2.6 VPython

# Written by Bruce Sherwood, licensed under Creative Commons 4.0.
# All uses permitted, but you must not claim that you wrote it, and
# you must include this license information in any copies you make.

# Angular momentum of a binary star
scene.background = color.white
scene.y = 0
scene.width = 600
scene.height = 600
G = 6.7e-11
d = 1.5e11
star1 = sphere(pos=vector(d,0,0), radius=5e9, color=color.magenta, make_trail=True, retain=200, interval=10)
star1.mass = 1e30
star2 = sphere(pos=vector(0,0,0), radius=1e10, color=color.blue, make_trail=True, retain=200, interval=10)
star2.mass = 2*star1.mass

# make elliptical orbit in xz plane
ev = (2*pi*d/(365*24*60*60))
star1.p = vector(0, star1.mass*ev, 0)
star2.p = -star1.p
dt = 12*60*60

scene.center = vector(-0.2*d,0.3*d,0)
scene.range = 1.8*d # set size of window in meters
scene.forward = vector(0,1,-1) # tip camera angle
scene.lights = []
distant_light(direction=vector(0,-1,0.2))

# A in the xz plane
locationA = vector(-0.4*d, 0, 0)

Lscale = 3.7e-35
pscale = 4e-24
Larr1 = arrow(pos=locationA-vector(offset,0,0), shaftwidth=star1.radius, axis=vector(0,0,0), color=star1.color)
rarr1 = arrow(pos=locationA, shaftwidth=star1.radius, axis=vector(0,0,0), color=color.cyan)
parr1 = arrow(pos=star1.pos, shaftwidth=star1.radius, axis=vector(0,0,0), color=color.red)
Larr2 = arrow(pos=locationA+vector(offset,0,0), shaftwidth=star1.radius, axis=vector(0,0,0), color=star2.color)
rarr2 = arrow(pos=locationA, shaftwidth=star1.radius, axis=vector(0,0,0), color=color.cyan)
parr2 = arrow(pos=star2.pos, shaftwidth=star1.radius, axis=vector(0,0,0), color=color.red)
Larr = arrow(pos=locationA, shaftwidth=star1.radius, axis=vector(0,0,0), color=vector(.7,.5,0))
Llabel1 = label(pos=locationA, text='L1', box=0, opacity=0, color=color.black)
Llabel2 = label(pos=locationA, text='L2', box=0, opacity=0, color=color.black)
Llabel = label(pos=locationA, text='L1+L2', box=0, opacity=0, color=color.black)

while True:
rate(200)
r = star2.pos-star1.pos
F = -(G*star2.mass*star1.mass/mag(r)**2)*norm(r)
star2.p = star2.p + F*dt
star2.pos = star2.pos + (star2.p/star2.mass)*dt
star1.p = star1.p - F*dt
star1.pos = star1.pos + (star1.p/star1.mass)*dt
parr2.pos = star2.pos
parr2.axis = star2.p*pscale
parr1.pos = star1.pos
parr1.axis = star1.p*pscale
rA1 = star1.pos-locationA
rarr1.axis = rA1
L1 = cross(rA1,star1.p)
Larr1.axis = L1*Lscale
rA2 = star2.pos-locationA
rarr2.axis = rA2
L2 = cross(rA2,star2.p)
Larr2.axis = L2*Lscale
Larr.axis = (L1+L2)*Lscale
Llabel1.pos = Larr1.pos+Larr1.axis+vector(0,h,0)
Llabel2.pos = Larr2.pos+Larr2.axis+vector(0,h,0)
Llabel.pos = Larr.pos+Larr.axis+vector(0,h,0)
``````