Reputation: 10996
I am porting some Matlab code to python and I have the following statement in Matlab:
cross([pt1,1]-[pp,0],[pt2,1]-[pp,0]);
pt1
, pt2
and pp
are 2D points.
So, my corresponding python code looks as follows:
np.cross(np.c_[pt1 - pp, 1], np.c_[pt2 - pp, 1])
The points are defined as:
pt1 = np.asarray((440.0, 59.0))
pt2 = np.asarray((-2546.23, 591.03))
pp = np.asarray([563., 456.5])
When I execute the statement with the cross product, I get the following error:
ValueError: all the input array dimensions except for the concatenation axis must match exactly
So looking at some other posts, here I thought I would try np.column_stack
but I get the same error:
np.cross(np.column_stack((pt1 - pp, 1)), np.column_stack((pt2 - pp, 1)))
Upvotes: 0
Views: 310
Reputation: 231375
If you use np.r_
instead it works:
In [40]: np.cross(np.r_[pt1 - pp, 1], np.r_[pt2 - pp, 1])
Out[40]: array([-5.32030000e+02, -2.98623000e+03, -1.25246611e+06])
Your pt1
and pp
are (2,) arrays. To add a 1
to them you need to use a 1d concatenate, np.r_
for 'row', as opposed to columns
.
There are lots of ways of constructing a 3 element array:
In [43]: np.r_[pt1 - pp, 1]
Out[43]: array([-123. , -397.5, 1. ])
In [44]: np.append(pt1 - pp, 1)
Out[44]: array([-123. , -397.5, 1. ])
In [45]: np.concatenate((pt1 - pp, [1]))
Out[45]: array([-123. , -397.5, 1. ])
concatenate
is the base operation. The others tweak the 1
to produce a 1d array that can be joined with the (2,) shape array to make a (3,).
Concatenate turns all of its inputs into arrays, if they aren't already: np.concatenate((pt1 - pp, np.array([1])))
.
Note that np.c_
docs say it is the equivalent of
np.r_['-1,2,0', index expression]
That initial string expression is a bit complicated. The key point is it tries to concatenate 2d arrays (whereas your pt1
is 1d).
It is like column_stack, joining
n(2,1)
arrays to make a
(2,n)` array.
In [48]: np.c_[pt1, pt2]
Out[48]:
array([[ 440. , -2546.23],
[ 59. , 591.03]])
In [50]: np.column_stack((pt1, pt2))
Out[50]:
array([[ 440. , -2546.23],
[ 59. , 591.03]])
In MATLAB everything has at least 2 dimensions, and because it is Fortran based, the outer dimensions are last. So in a sense its most natural 'vector' shape is n x 1, a column matrix. numpy
is built on Python, with a natural interface to its scalars and nested lists. Order is c
based; the initial dimensions are outer most. So numpy
code can have true scalars (Python numbers without shape or size), or arrays with 0 or more dimensions. A 'vector' most naturally has shape (n,)
(a 1 element tuple). It can easily be reshaped to (1,n) or (n,1) if needed.
If you want a (3,1) array (instead of (3,) shaped), you'd need to use some sort of 'vertical' concatenation, joining a (2,1) array with a (1,1):
In [51]: np.r_['0,2,0', pt1-pp, 1]
Out[51]:
array([[-123. ],
[-397.5],
[ 1. ]])
In [53]: np.vstack([(pt1-pp)[:,None], 1])
Out[53]:
array([[-123. ],
[-397.5],
[ 1. ]])
(But np.cross
wants (n,3) or (3,) arrays, not (3,1)!)
In [58]: np.cross(np.r_['0,2,0', pt1-pp, 1], np.r_['0,2,0', pt2-pp, 1])
...
ValueError: incompatible dimensions for cross product
(dimension must be 2 or 3)
To get around this specify an axis:
In [59]: np.cross(np.r_['0,2,0', pt1-pp, 1], np.r_['0,2,0', pt2-pp, 1], axis=0)
Out[59]:
array([[-5.32030000e+02],
[-2.98623000e+03],
[-1.25246611e+06]])
Study np.cross
if you want an example of manipulating dimensions. In this axis=0
case it transposes the arrays so they are (1,3) and then does the calculation.
Upvotes: 1
Reputation: 1248
This might be what you are looking for:
np.cross(np.append(pt1-pp, 1), np.append(pt2-pp, 1))
Upvotes: 2