Estimating distance between two features in a shape file using Python - python

I am new to ArcGIS and trying to learn how I should make it work with Python.
I have a few points plotted on ArcGIS software. Now I want to measure the distance between those points using Python. Say I have 7 points (A,B,C,D,E,F,G). I want to measure the distance between points A and B, A and C, A and D, and so on. I know it is simple just do it in ArcGIS but wanted to learn how I should do it in Python.
If there is a way to do it exactly or if there is any better alternative, any leads would help.
Thanks!

I don't have experience with ArcGis and you do not specify if you need a 2D distance or a 3D distance or a non-euclidian distance. So my answer may not be appropriate.
The 2D distance between 2 points is based on Pythagore's theorem:
d = sqrt( (y2-y1)**2 + (x2-x1)**2))
In python (2 or 3), it would be:
import math
d = math.sqrt((y2-y1)**2 + (x2-x1)**2)
For those who are afraid of typing "sqrt", there is now (since python3.8) a math.dist() function:
import math
d = math.dist((x1,x2), (y1,y2))
If your data points are in lists, math.dist shines because if will compute all your distances in a single call and return a list of distances.
For a 3D distance, we are back to Pythagore's theorem:
d = math.sqrt( (z2-z1)**2 + (y2-y1)**2 + (x2-x1)**2)
And if you need a more accurate answer that take into account that the earth is not a perfect sphere, you should search for "delft stack haversine".
DuckDuckGo (duckduckgo.com) will be your friend.

Related

Fitting a curve in points with associated normals (with spline)

I have faced a similar situation with this question, which was asked 8 years ago but in matlab not python Fit a curve in MATLAB where points have specified normals
Similar to this question I have 3 points (in 3d space) with their associated normals. I need to find a polynomial (in 3d maybe surface) that joins the 3 points and agrees with their normals.
I want to use spline for this, and I'm searching for an answer in python, but it's kinda rare thing when it comes to normals to be taken into account.
So, how to implement this or change matlab code into python one in the link above.
My points and their associated normals: A,B,C are points and N_A, N_B, N_C are normals.
A = np.array([ 348.92065834, -1402.3305998, 32.69313966])
N_A = np.array([-0.86925426, 0.02836434, -0.49355091])
B = np.array([282.19332067, 82.52027998, -5.92595371])
N_B = np.array([-0.82339849, 0.43041935, 0.3698028])
C = np.array([247.37475615, -3.70129865, -22.10494737])
N_C = np.array([-0.83989222, 0.23796899, 0.48780305])
First, I tried to use fitting, but it seems spline is much better in this case.

Measure distance between meshes

For my project, I need to measure the distance between two STL files. I wrote a script that allows reading the files, positioning them in relation to each other in the desired position. Now, in the next step I need to check the distance from one object to the other. Is there a function or script available on a library that allows me to carry out this process? Because then I’m going to want to define metrics like interpenetration area, maximum negative distance etc etc so I need to check first the distance between those objects and see if there is like mesh intersection and mesure that distance. I put the url for the combination of the 2 objects that I want to mesure the distance:
https://imgur.com/wgNaalh
Pyvista offers a really easy way of calculating just that:
import pyvista as pv
import numpy as np
mesh_1 = pv.read(**path to mesh 1**)
mesh_2 = pv.read(**path to mesh 2**)
closest_cells, closest_points = mesh_2.find_closest_cell(mesh_1.points, return_closest_point=True)
d_exact = np.linalg.norm(mesh_1 .points - closest_points, axis=1)
print(f'mean distance is: {np.mean(d_exact)}')
For more methods and examples, have a look at:
https://docs.pyvista.org/examples/01-filter/distance-between-surfaces.html#using-pyvista-filter
To calculate the distance between two meshes, first one needs to check whether these meshes intersect. If not, then the resulting distance can be computed as the distance between two closest points, one from each mesh (as on the picture below).
If the meshes do intersect, then it is necessary to find the part of each mesh, which is inside the other mesh, then find two most distant points, one from each inner part. The distance between these points will be the maximum deepness of the meshes interpenetration. It can be returned with negative sign to distinguish it from the distance between separated meshes.
In Python, one can use MeshLib library and findSignedDistance function from it as follows:
import meshlib.mrmeshpy as mr
mesh1 = mr.loadMesh("Cube.stl")
mesh2 = mr.loadMesh("Torus.stl"))
z = mr.findSignedDistance(mesh1, mesh2)
print(z.signedDist) // 0.3624192774295807

Calculating distances on grid

I have a 10 x 10 grid of cells (as a numpy array). I also have a list of 3 points on that grid. For each cell on the grid, I need to find the closest of the three points. I can do this in series of nested loops in python (2.7) which works but is slow (especially if I upscale to larger grids) but I suspect there is a faster way. Does anyone have any suggestions?
The simplest way I know of to calculate the distance between two points on a plane is using the Pythagorean theorem.
That is, picture a right angle triangle where the hypotenuse goes between the two points and the base of the triangle is parallel to the x axis and the height is parallel to the y axis. We then know that the distance (represented by the length of the hypotenuse) h adheres to the following: h^2 = a^2 + b^2, where a and b are the lengths of the two remaining sides of the triangle.
It's hard to give any other help without seeing your code. Have you tried something similar yet? You need to specify your question more if you want more specific answers.
If we assume that you know the point coord, then you can calculate the distance between a cell and the point using the distance formula: https://en.wikipedia.org/wiki/Distance
So for example, let's say that your cell correspond to 'x' and your 3 points correspond to y1, y2 and y3. You can simply get the distance between x - y1, x - y2 and x - y3 and then compare the three distances.
If we assume that you do not know the point coord, then you first have to find the point coord. You can find the point coord by scanning your grid and cheecking if a cell correspond to a point coord. When you found all your point, you can find the closest distance using the formula distance.
There is function in scipi called euclidean that will calculate the distances between points, if you want to loop through them.
from scipy.spatial.distance import euclidean
import numpy as np
a = np.array([1, 1, 1])
b = np.array([2, 2, 2])
dist = euclidean(a, b)
But I think for large data sets you would be better of using scipi's k-d tree to preform the search.

Generate, fill and plot a hexagonal lattice in Python

I'd like to modify a Python script of mine operating on a square lattice (it's an agent based model for biology), to work in a hexagonal universe.
This is how I create and initialize the 2D matrix in the square model: basically, N is the size of the lattice and R gives the radius of the part of the matrix where I need to change value at the beginning of the algorithm:
a = np.zeros(shape=(N,N))
center = N/2
for i in xrange(N):
for j in xrange(N):
if( ( pow((i-center),2) + pow((j-center),2) ) < pow(R,2) ):
a[i,j] = 1
I then let the matrix evolve according to certains rules and finally print via the creation of a pickle file:
name = "{0}-{1}-{2}-{3}-{4}.pickle".format(R, A1, A2, B1, B2)
pickle.dump(a, open(name,"w"))
Now, I'd like to do exactly the same but on an hexagonal lattice. I read this interesting StackOverflow question which clearified how to represent the positions on a hexagonal lattice with three coordinates, but a couple of things stay obscure to my knowledge, i.e.
(a) how should I deal with the three axes in Python, considering that what I want is not equivalent to a 3D matrix, due to the constraints on the coordinates, and
(b) how to plot it?
As for (a), this is what I was trying to do:
a = np.zeros(shape=(N,N,N))
for i in xrange(N/2-R, N/2+R+1):
for j in xrange(N/2-R, N/2+R+1):
for k in xrange(N/2-R, N/2+R+1):
if((abs(i)+abs(j)+abs(k))/2 <= 3*N/4+R/2):
a[i,j,k] = 1
It seems to me pretty convoluted to initialize a NxNxN matrix like that and then find a way to print a subset of it according to the constraints over the coordinates. I'm looking for a simpler way and, more importantly, for understanding how to plot the hexagonal lattice resulting from the algorithm (no clue on that, I haven't tried anything for the moment).
I agree that trying to shoehorn a hexagonal lattice into a cubic is problematic. My suggestion is to use a general scheme - represent the neighboring sites as a graph. This works very well with pythons dictionary object and it trivial to implement the "axial coordinate scheme" in one of the links you provided. Here is an example that creates and draws the "lattice" using networkx.
import networkx as nx
G = nx.Graph(directed=False)
G.add_node((0,0))
for n in xrange(4):
for (q,r) in G.nodes():
G.add_edge((q,r),(q,r-1))
G.add_edge((q,r),(q-1,r))
G.add_edge((q,r),(q-1,r+1))
G.add_edge((q,r),(q,r+1))
G.add_edge((q,r),(q+1,r-1))
G.add_edge((q,r),(q+1,r))
pos = nx.graphviz_layout(G,prog="neato")
nx.draw(G,pos,alpha=.75)
import pylab as plt
plt.axis('equal')
plt.show()
This is isn't the most optimal implementation but it can generate arbitrarily large lattices:

How to calculate cartesian coordinates from dihedral angle in python

I have an ensemble of points in a Cartesian space. I can compute dihedral angles defined by a given sub-ensemble of four points (a,b,c,d) using python with numpy. Below are my functions:
def getDihedral(a,b,c,d):
v1 = getNormedVector(a, b)
v2 = getNormedVector(b, c)
v3 = getNormedVector(c, d)
v1v2 = numpy.cross(v1,v2)
v2v3 = numpy.cross(v2,v3)
return getAngle(v1v2,v2v3)
def getNormedVector(a,b):
return (b-a)/numpy.linalg.norm(b-a)
def getAngle(a,b):
return numpy.rad2deg(numpy.arccos(numpy.dot(a/numpy.linalg.norm(a),b.T/numpy.linalg.norm(b))))[0,0]
I want to rotate only one dihedral angles, how can I calculate the new coordinates for a sub-ensembles of points using python with numpy and scipy?
If you can compute the dihedral, I assume you can obtain the axis about which you want to rotate you subset of points. Given that, you can easily do this by rotating all points around this axis by the angle you want in vpython - see this example (go to 'rotating a vector'). Otherwise, you need to program the appropriate equation (spelled out in this thread).

Categories

Resources