Skip to main content

py3d is a python 3d computational geometry library, which can deal with points, lines, planes and 3d meshes in batches.

Project description

Copyright (c) Tumiz. Distributed under the terms of the GPL-3.0 License.

py3d is a 3d computational geometry library.

It is designed to be simple, stable and customizable:

  • simple means api will be less than usual and progressive
  • stable means it will have less dependeces and modules, and it will be fully tested
  • customizable means it will be a libaray rather than an application, it only provide data structures and functions handling basic geometry concepts

For more information, please visit https://tumiz.github.io/scenario/

Vector3 --Type for position, velocity & scale

Vector3 represents point or position, velocity and scale. Note! Angular velocity cant be represented by this type, it should be represented by Rotation3 which will indroduced in next section. It is a class inheriting numpy.ndarray, so it is also ndarray.

Defination

Vector3(x:int|float|list|tuple|ndarray,y:int|float,z:int|float,n:int):Vector3

Vector3 can be a vector or a collection of vectors.

from py3d import Vector3
from numpy import array
a=Vector3(1,2,3)
b=Vector3([1,2,3])
c=Vector3((1,2,3))
d=Vector3(array([1,2,3]))
e=Vector3(1,2,3,4)
a,b,c,d,e
(Vector3([1., 2., 3.]),
 Vector3([1., 2., 3.]),
 Vector3([1., 2., 3.]),
 Vector3([1., 2., 3.]),
 Vector3([[1., 2., 3.],
          [1., 2., 3.],
          [1., 2., 3.],
          [1., 2., 3.]]))
Vector3.Rand(n:int):Vector3

Return a random vector or a collection of random vectors.

Vector3.Zeros(n:int):Vector3

Return a zero vector or a collection of zero vectors.

Vector3.Ones(n:int):Vector3

Return a vector or a collection of vectors filled with 1

from py3d import Vector3
Vector3.Rand(4),Vector3.Zeros(4),Vector3.Ones(4)
(Vector3([[0.00240872, 0.06259652, 0.58789827],
          [0.84172269, 0.54447431, 0.02050995],
          [0.50090265, 0.00939204, 0.95925715],
          [0.72912007, 0.97297814, 0.65798418]]),
 Vector3([[0., 0., 0.],
          [0., 0., 0.],
          [0., 0., 0.],
          [0., 0., 0.]]),
 Vector3([[1., 1., 1.],
          [1., 1., 1.],
          [1., 1., 1.],
          [1., 1., 1.]]))
from py3d import Vector3
Vector3([1,2,3,4,5,6,7,8,9]),Vector3([[1,2,3],[4,5,6],[7,8,9]])
(Vector3([[1., 2., 3.],
          [4., 5., 6.],
          [7., 8., 9.]]),
 Vector3([[1., 2., 3.],
          [4., 5., 6.],
          [7., 8., 9.]]))
from py3d import Vector3
Vector3(1,2,3,5),Vector3(y=1,n=4),Vector3(x=1,n=6)
(Vector3([[1., 2., 3.],
          [1., 2., 3.],
          [1., 2., 3.],
          [1., 2., 3.],
          [1., 2., 3.]]),
 Vector3([[0., 1., 0.],
          [0., 1., 0.],
          [0., 1., 0.],
          [0., 1., 0.]]),
 Vector3([[1., 0., 0.],
          [1., 0., 0.],
          [1., 0., 0.],
          [1., 0., 0.],
          [1., 0., 0.],
          [1., 0., 0.]]))
from py3d import Vector3
from numpy import array, equal
a=Vector3(array([1,2,3]))
b=Vector3(a)
a==b,id(a),id(b)
(True, 140613749197056, 140613749196832)

Deep copy

.copy()

It will return deep copy of origin vector, and their value are equal.

from py3d import Vector3
a=Vector3(1,2,3)
b=a
c=a.copy() # deep copy
id(a),id(b),id(c), a==c
(140613746450832, 140613746450832, 140613746451168, True)
from py3d import Vector3
points=Vector3.Rand(5)
print(points.norm())
points_copy=points.copy()
points==points_copy
[[1.08873624]
 [0.56201636]
 [0.81603114]
 [0.69572861]
 [1.33044297]]





array([[ True],
       [ True],
       [ True],
       [ True],
       [ True]])

Modify

from py3d import Vector3
points=Vector3(1,2,3,4)
points
Vector3([[1., 2., 3.],
         [1., 2., 3.],
         [1., 2., 3.],
         [1., 2., 3.]])
points[2]=Vector3(-1,-2,-3)
points
Vector3([[ 1.,  2.,  3.],
         [ 1.,  2.,  3.],
         [-1., -2., -3.],
         [ 1.,  2.,  3.]])
points[0:2]=Vector3.Ones(2)
points
Vector3([[ 1.,  1.,  1.],
         [ 1.,  1.,  1.],
         [-1., -2., -3.],
         [ 1.,  2.,  3.]])

Reverse

.reverse():ndarray
from py3d import *
a=Vector3.Rand(3)
print(a)
a.reverse()
print(a)
a.reversed()
[[0.37239685 0.85223555 0.27793704]
 [0.75213452 0.16901494 0.44511578]
 [0.9494015  0.35997485 0.57413589]]
[[0.9494015  0.35997485 0.57413589]
 [0.75213452 0.16901494 0.44511578]
 [0.37239685 0.85223555 0.27793704]]





Vector3([[0.37239685, 0.85223555, 0.27793704],
         [0.75213452, 0.16901494, 0.44511578],
         [0.9494015 , 0.35997485, 0.57413589]])

Append

.append(Vector3|ndarray):ndarray
from py3d import *
a=Vector3.Rand(4)
a.append(Vector3(1,2,3,2))
a
Vector3([[0.1919075 , 0.46747677, 0.91061577],
         [0.02682452, 0.15863966, 0.5067785 ],
         [0.83158459, 0.27005634, 0.35526737],
         [0.65509237, 0.54353389, 0.11015612],
         [1.        , 2.        , 3.        ],
         [1.        , 2.        , 3.        ]])

Insert

from py3d import *
a=Vector3.Rand(4)
a.insert(2,Vector3(1,2,3,3))
a
Vector3([[0.6605133 , 0.37618622, 0.64276519],
         [0.38142681, 0.40017373, 0.13127457],
         [1.        , 2.        , 3.        ],
         [1.        , 2.        , 3.        ],
         [1.        , 2.        , 3.        ],
         [0.21344712, 0.00533367, 0.50443668],
         [0.21560269, 0.51254746, 0.65253392]])
from py3d import *
a=Vector3.Rand(4)
a.insert(slice(0,3),Vector3(1,2,3))
a
Vector3([[1.        , 2.        , 3.        ],
         [0.79471519, 0.74496138, 0.68758799],
         [1.        , 2.        , 3.        ],
         [0.68778039, 0.18272503, 0.15025641],
         [1.        , 2.        , 3.        ],
         [0.78909031, 0.89734503, 0.50305253],
         [0.39830959, 0.40794724, 0.06154772]])
from py3d import *
a=Vector3.Rand(4)
a.insert(0,Vector3(1,2,3))
a
Vector3([[1.        , 2.        , 3.        ],
         [0.36243349, 0.90058189, 0.91439372],
         [0.50756061, 0.16305892, 0.63210915],
         [0.07187428, 0.21402741, 0.43172284],
         [0.6327147 , 0.83150476, 0.40701695]])

Remove

from py3d import *
a=Vector3.Rand(4)
print(a)
a.remove(0)
a
[[0.53362679 0.9637612  0.79709125]
 [0.9183582  0.69815294 0.9979033 ]
 [0.97920985 0.57807659 0.72873601]
 [0.62200499 0.23591995 0.53537224]]





Vector3([[0.9183582 , 0.69815294, 0.9979033 ],
         [0.97920985, 0.57807659, 0.72873601],
         [0.62200499, 0.23591995, 0.53537224]])
from py3d import *
a=Vector3.Rand(5)
print(a)
a.remove(slice(2,4))
a
[[0.61816345 0.21342644 0.06906031]
 [0.44855753 0.41317524 0.27265141]
 [0.981912   0.2943863  0.77828021]
 [0.4782964  0.40162783 0.28036749]
 [0.16483228 0.9366734  0.23671958]]





Vector3([[0.61816345, 0.21342644, 0.06906031],
         [0.44855753, 0.41317524, 0.27265141],
         [0.16483228, 0.9366734 , 0.23671958]])
from py3d import *
a=Vector3.Rand(5)
print(a)
a.remove(slice(2,4))
a
[[0.23022599 0.79078078 0.83306751]
 [0.76219755 0.62387302 0.94054235]
 [0.38409679 0.91891268 0.21859557]
 [0.0472911  0.81482236 0.52050563]
 [0.55440996 0.23135002 0.03196446]]





Vector3([[0.23022599, 0.79078078, 0.83306751],
         [0.76219755, 0.62387302, 0.94054235],
         [0.55440996, 0.23135002, 0.03196446]])

Discrete difference

.diff(n:int):Vector3
from py3d import Vector3
points=Vector3([
    [1,2,1],
    [2,3,1],
    [4,6,2],
    [8,3,0]
])
points.diff(),points.diff(2)
(Vector3([[ 1.,  1.,  0.],
          [ 2.,  3.,  1.],
          [ 4., -3., -2.]]),
 Vector3([[ 1.,  2.,  1.],
          [ 2., -6., -3.]]))

Cumulative Sum

.cumsum():Vector3

Return the cumulative sum of the elements along a given axis.

from py3d import Vector3
points=Vector3([
    [1,2,1],
    [2,3,1],
    [4,6,2],
    [8,3,0]
])
points.cumsum()
Vector3([[ 1.,  2.,  1.],
         [ 3.,  5.,  2.],
         [ 7., 11.,  4.],
         [15., 14.,  4.]])

Add

from py3d import Vector3
Vector3(1,2,3)+Vector3(2,3,4)
Vector3([3., 5., 7.])
from py3d import Vector3
Vector3.Zeros(3)+Vector3.Ones(3)
Vector3([[1., 1., 1.],
         [1., 1., 1.],
         [1., 1., 1.]])
from py3d import Vector3
a=Vector3([1,2,3,4,5,6,7,8,9,-1,-2,-3])
b=Vector3([1,-2,-4,-5,-1,-4,3,5,6,9,10,8])
a+b
Vector3([[ 2.,  0., -1.],
         [-1.,  4.,  2.],
         [10., 13., 15.],
         [ 8.,  8.,  5.]])

Subtract

from py3d import Vector3
Vector3(1,2,3)-Vector3(-1,-2,-3)
Vector3([2., 4., 6.])
from py3d import Vector3
Vector3([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15])-Vector3(1,-1,3,5)
Vector3([[ 0.,  3.,  0.],
         [ 3.,  6.,  3.],
         [ 6.,  9.,  6.],
         [ 9., 12.,  9.],
         [12., 15., 12.]])

Multiply

Multiply a number

from py3d import Vector3
a=Vector3(1,-2,3)*3
b=3*Vector3(1,-2,3)
a,b,a==b
(Vector3([ 3., -6.,  9.]), Vector3([ 3., -6.,  9.]), True)

Multiply element by element

support multiplication between Vector3,Numpy.ndarray,list and tuple.

from py3d import Vector3
from numpy import array
Vector3(1,-2,3)*Vector3(1,-1,3),\
Vector3(1,-2,3)*array([1,-1,3]),\
array([1,-1,3])*Vector3(1,-2,3),\
Vector3(1,-1,3)*[1,-2,3],\
(1,-1,3)*Vector3(1,-2,3)
(Vector3([1., 2., 9.]),
 Vector3([1., 2., 9.]),
 Vector3([1., 2., 9.]),
 Vector3([1., 2., 9.]),
 Vector3([1., 2., 9.]))

Dot product

Two vectors' dot product can be used to calculate angle between them. If angle

$\bf{a}\cdot\bf{b}=|\bf{a}|\cdot|\bf{b}|\cdot cos\theta$

$\bf{a}\cdot\bf{b}=\bf{b}\cdot\bf{a}$

.dot(Vector3):Vector3

dot() will return a new Vector3, the original one wont be changed

from py3d import Vector3
from numpy import cos
a=Vector3(1,-2,3)
b=Vector3(0,4,-1)
product=a.dot(b) # dot product
theta=a.angle_to_vector(b)
print(a.norm(),b.norm(),cos(theta))
print(a.norm()*b.norm()*cos(theta),product)
3.7416573867739413 4.123105625617661 -0.7130240959073809
-11.000000000000002 -11.0
a.dot(b),b.dot(a),a.dot(b)==b.dot(a)
(-11.0, -11.0, True)
from py3d import Vector3
a=Vector3.Rand(4)
b=Vector3.Rand(4)
a.dot(b)
Vector3([[0.52828999],
         [0.30207483],
         [1.10503466],
         [0.68242945]])

Cross product

$ \bf{a}\times\bf{b}=|\bf{a}|\cdot|\bf{b}|\cdot sin\theta$

$\bf{a}\times\bf{b}=-\bf{b}\times\bf{a}$

.cross(Vector3):Vector3

cross() will return a new Vector3, the original one wont be changed.

from py3d import Vector3
a=Vector3(1,2,0)
b=Vector3(0,-1,3)
c=a.cross(b)
a.cross(b),b.cross(a) # cross product
(Vector3([ 6., -3., -1.]), Vector3([-6.,  3.,  1.]))

array([1,2,0]).cross(Vector3(0,-1,3)) is not allowed since numpy.ndarray has no such a function to do cross product. But you can do it by a global function numpy.cross(array1, array2) like this

from numpy import cross,array
from py3d import Vector3
cross(array([1,2,0]), Vector3(0,-1,3))
array([ 6., -3., -1.])

Have a look to see the origin vectors and the product vector

from py3d import Vector3
v1=Vector3(1,2,0)
v2=Vector3(0,-1,3)
vp=Vector3(1,2,0).cross(Vector3(0,-1,3))
from py3d import Vector3
a=Vector3.Rand(4)
b=Vector3.Rand(4)
c=a.cross(b)

Divide

Divide by scalar

from py3d import Vector3
Vector3(1,2,3)/3
Vector3([0.33333333, 0.66666667, 1.        ])
from py3d import Vector3
a=Vector3(3,0,3)
b=a/3
a/=3
a,b
(Vector3([1., 0., 1.]), Vector3([1., 0., 1.]))

Divide by vector

from py3d import Vector3
Vector3(1,2,3)/Vector3(1,2,3)
Vector3([1., 1., 1.])

Divide by Numpy.ndarray, list and tuple

Vector3 is divided element by element

from py3d import Vector3
from numpy import array
Vector3(1,2,3)/array([1,2,3]), Vector3(1,2,3)/[1,2,3], Vector3(1,2,3)/(1,2,3)
(Vector3([1., 1., 1.]), Vector3([1., 1., 1.]), Vector3([1., 1., 1.]))

Compare

from py3d import *
a=Vector3(1,0,0.7)
b=Vector3(1.0,0.,0.7)
c=Vector3(1.1,0,0.7)
a==b,b==c,a!=c
(True, False, True)
from py3d import Vector3
a=Vector3([[1,2,3],
           [4,5,6],
           [7,8,9]])
b=Vector3([[1,1,3],
           [4,5,6],
           [7,1,9]])
a==b
array([[False],
       [ True],
       [False]])

Angle

.angle_to_vector(v:Vector3):float|ndarray

It will return the angle (in radian) between two vector. The angle is always positive and smaller than $\pi$.

from py3d import Vector3
v1=Vector3(1,-0.1,0)
v2=Vector3(0,1,0)
v1.angle_to_vector(v2),v2.angle_to_vector(v1)
(1.6704649792860586, 1.6704649792860586)
from py3d import Vector3
a=Vector3([[1,2,3],
           [4,5,6],
           [7,8,9]])
b=Vector3([[1,1,3],
           [4,5,6],
           [7,1,9]])
a.angle_to_vector(b)
Vector3([[2.57665272e-01],
         [2.10734243e-08],
         [5.24348139e-01]])
.angle_to_plane(normal:Vector3):float|ndarray

It will return the angle (in radian) between a vector and a plane. Result will be positive when normal and the vector have same direction, 0 when the plane and the vector is parallel, and negtive when normal and the vector have different direction.

from py3d import Vector3
v=Vector3(1,-0.1,0)
normal=Vector3(0,1,0)
v.angle_to_plane(normal)
-0.09966865249116208

Rotation

.rotation_to(Vector3):Vector3,float

It will return axis-angle tuple representing the rotation from this vector to another

from py3d import Vector3
v1=Vector3(1,-0.1,0)
v2=Vector3(0,1,0)
v1.rotation_to(v2),v2.rotation_to(v1)
((Vector3([-0.,  0.,  1.]), 1.6704649792860586),
 (Vector3([ 0.,  0., -1.]), 1.6704649792860586))
from py3d import Vector3
a=Vector3([[1,-0.1,0],
        [0,1,0]])
b=Vector3([[0,1,0],
          [1,-0.1,0]])
a.rotation_to(b)
(Vector3([[-0.,  0.,  1.],
          [ 0.,  0., -1.]]),
 Vector3([[1.67046498],
          [1.67046498]]))

Perpendicular

$\bf{a}\perp\bf{b}\Leftrightarrow\bf{a}\cdot\bf{b}=0$

$\bf{a}\perp\bf{b}\Leftrightarrow<\bf{a},\bf{b}>=\pi/2$

    .is_perpendicular_to_vector(v:Vector3): bool
    .is_perpendicular_to_plane(normal:Vector3): bool
from py3d import Vector3
a=Vector3(0,1,1)
b=Vector3(1,0,0)
a.is_perpendicular_to_vector(b), a.angle_to_vector(b)
(True, 1.5707963267948966)

Parallel

$\bf{a}//\bf{b}(\bf{b}\ne\bf{0})\Leftrightarrow\bf{a}=\lambda\bf{b}$

from py3d import Vector3
a=Vector3(1,2,3)
b=Vector3(2,4,6)
plane = Vector3(1,2,)
a.is_parallel_to_vector(b),a==b
(True, False)

$\bf{v}\perp\bf{0}, \bf{v}\cdot\bf{0}=0$ is always true no matter what $\bf{v}$ is

from py3d import Vector3
a=Vector3(1,2,3)
b=Vector3(-2,3,9)
a.dot(Vector3()),a.is_parallel_to_vector(Vector3()),b.is_parallel_to_vector(b)
/mnt/d/codes/scenario/py3d/py3d/vector3.py:52: RuntimeWarning: invalid value encountered in true_divide
  return self/l





(0.0, False, True)

Projection

.scalar_projection(v:Vector3):float
.vector_projection(v:Vector3):Vector3
from py3d import Vector3
a=Vector3(2,1,1)
b=Vector3(1,0,0)
a.scalar_projection(b),a.vector_projection(b)
(2.0, Vector3([2., 0., 0.]))
from py3d import Vector3
a=Vector3(1,2,3)
p0=Vector3()
p1=Vector3(1,0,0)
a.projection_point_on_line(p0,p1)
Vector3([1., 0., 0.])

Area

.area(Vector3):float

It will return area of triangle constucted by two vectors.

.area(Vector3,Vector3):float

It will return area of triangle constructed by three points.

from py3d import Vector3
triangle=Vector3([[1,2,3],
                [1,0,0],
                [0,1,0]])
triangle.area()
2.345207879911715

Distance, Length, Norm

.norm():float
from py3d import Vector3
Vector3(1,2,3).norm()
3.7416573867739413

You can use this function to calculate distance between two points.

point1=Vector3(1,2,3)
point2=Vector3(-10,87,11)
distance=(point1-point2).norm()
print(distance)
86.08135686662938
from py3d import Vector3
points=Vector3.Rand(5)
points.norm()
array([[1.00952545],
       [0.48242001],
       [0.89271163],
       [0.89204501],
       [0.73384055]])

Calculate distances between a point and a collection of points

from py3d import Vector3
p=Vector3(1,-1,0)
points=Vector3.Rand(7)
points,(p-points).norm()
(Vector3([[0.92626725, 0.11644017, 0.08594409],
          [0.16715586, 0.38188221, 0.67990894],
          [0.81794796, 0.89077802, 0.00486246],
          [0.45000451, 0.48546387, 0.55692739],
          [0.68920177, 0.88953077, 0.46585984],
          [0.7319839 , 0.25516827, 0.40738851],
          [0.93042351, 0.79431006, 0.1907029 ]]),
 array([[1.12216824],
        [1.75085807],
        [1.89952839],
        [1.67906702],
        [1.97077332],
        [1.34656801],
        [1.80575665]]))

Normalize

<font color="red">! Zero vector can not be normalized </font>

normalized(), get a new vector, which is the unit vector of the origin

from py3d import Vector3
v=Vector3(1,2,3)
v.normalized()
Vector3([0.26726124, 0.53452248, 0.80178373])


          

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

py3d-0.0.23.tar.gz (272.6 kB view hashes)

Uploaded Source

Built Distribution

py3d-0.0.23-py3-none-any.whl (268.1 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page