Metadata-Version: 2.1
Name: py3d
Version: 0.0.8
Summary: a 3d library
Home-page: https://github.com/Tumiz/scenario
Author: Tumiz
Author-email: hh11698@163.com
License: GPL-3.0 License
Platform: UNKNOWN
Requires-Python: >=3.5.0
Description-Content-Type: text/markdown
Requires-Dist: numpy
Requires-Dist: tornado

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

py3d is a python 3d computational geometry library.
It provides basic classes related to 3d computational geometry, which can batch process point, line and surface calculation tasks.
py3d 是一个python写的三维计算几何库。
py3d 基于numpy提供了和三维几何计算有关的基础类，可以批量处理点、线、面的计算任务。

# 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

```python
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. 


```python
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.]]))



```python
Vector3.Rand(n:int):Vector3
```
Return a random vector or a collection of random vectors.
```python
Vector3.Zeros(n:int):Vector3
```
Return a zero vector or a collection of zero vectors.
```python
Vector3.Ones(n:int):Vector3
```
Return a vector or a collection of vectors filled with 1


```python
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.]]))




```python
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.]]))




```python
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.]]))




```python
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
```python
.copy()
```
It will return deep copy of origin vector, and their value are equal.


```python
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)




```python
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


```python
from py3d import Vector3
points=Vector3(1,2,3,4)
points
```




    Vector3([[1., 2., 3.],
             [1., 2., 3.],
             [1., 2., 3.],
             [1., 2., 3.]])




```python
points[2]=Vector3(-1,-2,-3)
points
```




    Vector3([[ 1.,  2.,  3.],
             [ 1.,  2.,  3.],
             [-1., -2., -3.],
             [ 1.,  2.,  3.]])




```python
points[0:2]=Vector3.Ones(2)
points
```




    Vector3([[ 1.,  1.,  1.],
             [ 1.,  1.,  1.],
             [-1., -2., -3.],
             [ 1.,  2.,  3.]])



## Reverse
```python
.reverse():ndarray
```


```python
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
```python
.append(Vector3|ndarray):ndarray
```


```python
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


```python
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]])




```python
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]])




```python
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


```python
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]])




```python
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]])




```python
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
```python
.diff(n:int):Vector3
```



```python
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
```python
.cumsum():Vector3
```
Return the cumulative sum of the elements along a given axis.


```python
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


```python
from py3d import Vector3
Vector3(1,2,3)+Vector3(2,3,4)
```




    Vector3([3., 5., 7.])




```python
from py3d import Vector3
Vector3.Zeros(3)+Vector3.Ones(3)
```




    Vector3([[1., 1., 1.],
             [1., 1., 1.],
             [1., 1., 1.]])




```python
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


```python
from py3d import Vector3
Vector3(1,2,3)-Vector3(-1,-2,-3)
```




    Vector3([2., 4., 6.])




```python
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


```python
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.


```python
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


```python
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



```python
a.dot(b),b.dot(a),a.dot(b)==b.dot(a)
```




    (-11.0, -11.0, True)




```python
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}$
```python
.cross(Vector3):Vector3
```
cross() will return a new Vector3, the original one wont be changed.


```python
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


```python
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


```python
from py3d import Vector3
v1=Vector3(1,2,0)
v2=Vector3(0,-1,3)
vp=Vector3(1,2,0).cross(Vector3(0,-1,3))
```


```python
from py3d import Vector3
a=Vector3.Rand(4)
b=Vector3.Rand(4)
c=a.cross(b)
```

## Divide

### Divide by scalar


```python
from py3d import Vector3
Vector3(1,2,3)/3
```




    Vector3([0.33333333, 0.66666667, 1.        ])




```python
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


```python
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


```python
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


```python
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)




```python
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
```python
.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$.


```python
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)




```python
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]])



```python
.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.


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




    -0.09966865249116208



## Rotation

```python
.rotation_to(Vector3):Vector3,float
```
It will return axis-angle tuple representing the rotation from this vector to another


```python
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))




```python
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$

```python
    .is_perpendicular_to_vector(v:Vector3): bool
    .is_perpendicular_to_plane(normal:Vector3): bool
```


```python
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}$


```python
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


```python
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

```python
.scalar_projection(v:Vector3):float
```
```python
.vector_projection(v:Vector3):Vector3
```


```python
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.]))




```python
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
```python
.area(Vector3):float
```
It will return area of triangle constucted by two vectors.
```python
.area(Vector3,Vector3):float
```
It will return area of triangle constructed by three points.


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




    2.345207879911715



## Distance, Length, Norm
```python
.norm():float
```


```python
from py3d import Vector3
Vector3(1,2,3).norm()
```




    3.7416573867739413



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


```python
point1=Vector3(1,2,3)
point2=Vector3(-10,87,11)
distance=(point1-point2).norm()
print(distance)
```

    86.08135686662938



```python
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


```python
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


```python
from py3d import Vector3
v=Vector3(1,2,3)
v.normalized()
```




    Vector3([0.26726124, 0.53452248, 0.80178373])




```python

```


