Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Euclidean distance of Delaney triangulation - Scipy

The spatial package imported from Scipy can measure the Euclidean distance between specified points. Is it possible to return the same measurement by using the Delaunay package? Using the df below, the average distance between all points is measured grouped by Time. However, I'm hoping to use Delaunay triangulation to measure the average distance.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.spatial import Delaunay

df = pd.DataFrame({
    'Time' : [1,1,1,1,2,2,2,2],                  
    'A_X' : [5, 5, 6, 6, 4, 3, 3, 4], 
    'A_Y' : [5, 6, 6, 5, 5, 6, 5, 6],                         
        })

def make_points(x):
    return np.array(list(zip(x['A_X'], x['A_Y'])))

points = df.groupby("Time").apply(make_points)

for p in points:
    tri = Delaunay(p)
    ax.triplot(*p.T, tri.simplices)

Average distance between all points can be measured using below but I'm hoping to incorporate Delaunay.

 avg_dist = (df.groupby(['Time'])
             .apply(lambda x: spatial.distance.pdist
             (np.array(list(zip(x['A_X'], x['A_Y']))))
             .mean() if len(x) > 1 else 0)
             .reset_index()
             )

Intended Output:

   Time         0
0     1  1.082842
1     2  1.082842
like image 518
jonboy Avatar asked Oct 26 '20 00:10

jonboy


People also ask

What is Scipy spatial distance Euclidean?

scipy.spatial.distance. euclidean(u, v, w=None)[source] Computes the Euclidean distance between two 1-D arrays. The Euclidean distance between 1-D arrays u and v, is defined as. ‖ u − v ‖ 2 ( ∑ ( w i | ( u i − v i ) | 2 ) ) 1 / 2.

What Scipy spatial?

scipy. spatial can compute triangulations, Voronoi diagrams, and convex hulls of a set of points, by leveraging the Qhull library. Moreover, it contains KDTree implementations for nearest-neighbor point queries, and utilities for distance computations in various metrics.

How do you construct Delaunay triangulation?

The most straightforward way of efficiently computing the Delaunay triangulation is to repeatedly add one vertex at a time, retriangulating the affected parts of the graph. When a vertex v is added, we split in three the triangle that contains v, then we apply the flip algorithm.

What is Cdist?

cdist(array, axis=0) function calculates the distance between each pair of the two collections of inputs. Parameters : array: Input array or object having the elements to calculate the distance between each pair of the two collections of inputs.


1 Answers

You can try this function

from itertools import combinations
import numpy as np
    
def edges_with_no_replacement(points):
    
    # get the unique coordinates
    points = np.unique(points.loc[:,['A_X','A_Y']].values,return_index=False,axis=0)
    if len(points) <= 1: return 0
    # for two points, no triangle
    # I think return the distance between the two points make more sense? You can change the return value to zero.
    if len(points) == 2: return np.linalg.norm(points[0]-points[1])
    
    tri = Delaunay(points)
    triangles = tri.simplices
    # get all the unique edges 
    all_edges = set([tuple(sorted(edge)) for item in triangles for edge in combinations(item,2)])
    # compute the average dist 
    return np.mean([np.linalg.norm(points[edge[0]]-points[edge[1]]) for edge in all_edges])

This function will first find all the unique edges given triangles, then return the average length of the triangle edges. Apply this function

avg_dist = (df.groupby(['Time']).apply(edges_with_no_replacement).reset_index())

The output is

    Time    0
0   1   1.082843
1   2   1.082843

Note that the function edges_with_no_replacement will still throw QhullError if points are on the same line, for example

Delaunay(np.array([[1,2],[1,3],[1,4]]))

So, you have to make sure the points are not on the same line.

like image 198
meTchaikovsky Avatar answered Sep 19 '22 07:09

meTchaikovsky