LizardWizard LizardWizard - 2 years ago 136
Python Question

I am using a numpy array of randomly generated ordered pairs, I need to determin if the ordered pairs are different types of triangles

I jst started using numpy this week, and am very confused with it. seems very different from normal python functions.

With an array, shape of 1000X6, is there a way to go row by row in the array and check for example a equilateral triangle.I have 6 columns so that there are triples in each row, 2 integers for each point.

import numpy as np
pnts = np.random.randint(0,50,(1000, 6))

I also thought it may be better to create 3 arrays that are like this:

import numpy as np
A = np.random.random((10,2))
B = np.random.random((10,2))
C = np.random.random((10,2))

to create the ordered pairs and then use a algorithm to find a triangle.

Is there a better way to create an array that represent 1000 triples of ordered pairs and how can I find triangles in that array, like a equilateral triangle for example.

I have made some changes now. I made two arrays for x coordinates and y coordinates.

x = np.random.randint(0,10,(3,1000))
y = np.random.randint(0,10,(3,1000))

############# Adding to question #############

I have algorithms that take each matching x and y coordinates that find there side length and angles for each triangle. I would post but its too much code. And also now I have functions that use angles and side lengths to find a Scalene, Equilateral, Right Isoceles, And Non-right Isoceles.

My question is now more index related. I will use equilateral triangle again as an example because that is what we have been working with.

E = np.column_stack((ACXY,ABXY,CBXY))
ES = np.logical_and(E[:,0] == E[:,1], E[:,1] == E[:,2])

I Have this to find equilateral triangles.

- ACXY = the distance from point A to C
- ABXY = the distance from point A to B
- CBXY = the distance from point C to B

I want to be able to take all the coordinate triples that are equilateral triangles, index them and put them into a new array called E_Tri. I dont think i need the function creating boolean values. Ive thought that maybe If: else: statements maybe a better way to do it.

Also this may help too, I will display
E = np.column_stack((ACXY,ABXY,CBXY))

to help understand the array of (E).

[[ 4. 4.47213595 7.21110255]
[ 3.60555128 2.23606798 5.83095189]
[ 2.23606798 9.05538514 8.54400375]
[ 3.60555128 9.05538514 6.08276253]
[ 8.94427191 8.54400375 1. ]
[ 10.63014581 1. 10. ]]

E will look like that. Hopefully this will make sense, if not please let me know.

Something like this perhaps, Even though this will not work just adding to the question.

E = np.column_stack((ACXY,ABXY,CBXY))
equilateral = []
def E_Tri(E):
if E[:,0] == E[:,1] and E[:,1] == E[:,2]:
return E

Answer Source

You've described well how you are storing the data, but not what the algorithm is. For example, if we want to answer the question "Is this set of three (x,y) points P1..P3 an equilateral triangle," we can formulate it this way:

dist(P1,P2) == dist(P2,P3) == dist(P3,P1)

Where dist(P1,P2) uses the Pythagorean Theorem:

sqrt((P1.x - P2.x)**2 + (P1.y - P2.y)**2)

But note the sqrt() is unnecessary because all we care about is if all three legs are equal length (and if they are, their squares will be equal as well).

In NumPy we want to do everything in a parallelizable way. So if you have a 1000x6 array representing 1000 triangles, you need to do all the operations on 1000 elements at a time. If the array is called A and its columns are:

P1.x, P1.y, P2.x, P2.y, P3.x, P3.y

Then the first operations are:

A[0] - A[2] # P1.x - P2.x
A[1] - A[3] # P1.y - P2.y
A[2] - A[4]
A[3] - A[5]
A[4] - A[0]
A[5] - A[1]

Which can be more succinctly written:

R = A - np.roll(A, -2, axis=0) # 1000x6 array of all differences

That being done, you can square all those 1000x6 results at once, giving us a 1000x6 array R from which we add the x and y pairs to get the squares-of-distances:

R[0] + R[1] # (P1.x - P2.x)**2 + (P1.y - P2.y)**2
R[2] + R[3]
R[4] + R[5]

Which is to say:

S = R[0::2] + R[1::2] # three column-wise additions at once

This gives us the 1000x3 squares-of-distances array S. Now we simply check for each row if its columns are all equal:

np.logical_and(S[0] == S[1], S[1] == S[2])

This gives us the 1000x1 boolean vector which tells us if each row is an equilateral triangle.

Note that we never went row-by-row in an iterative fashion. That's because doing so in NumPy is much slower than doing column-wise operations.

Note that I have written the above assuming the shape of the arrays are actually (6,1000) when I say 1000x6. This is for convenience of notation (A[0] instead of A[:,0]) and also because it is more efficient when we are operating on columns since NumPy by default uses row-major order. You can np.transpose() your input data if needed.

So in the end it's just:

A = pnts.T
R = np.square(A - np.roll(A, -2, axis=0))
S = R[0::2] + R[1::2] # 1000x3 squares of distances
np.logical_and(S[0] == S[1], S[1] == S[2]) # 1000 True/False results
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download