def test_distance_point_grad(self): # Test gradient with respect to each projected point, leaving the # polyline fixed. # Move pts along simple polyline and compare gradients. # Points are a bit tunes, because at discontinuous points, the numerical # gradient jumps to far for the tested precision, although the plots are # perfectly ok pl = Polyline([[0, 0], [1, 0.8], [1.1, 1.9]]) test_eps = 1e-2 # Max allowed deviation, chose suitable for num grad npts = 1000 # Test x gradient ys = [-1, 2] x = np.linspace(-1, 2, npts) for yi in ys: y = yi + np.zeros_like(x) pts = np.vstack((x, y)).T dists, _, _, proj_vecs = pl.get_dist_to_line(pts) # Gradients are simply the normalized negative projection vectors _norm = np.linalg.norm(proj_vecs, axis=1).reshape(len(proj_vecs), 1) gradients = -proj_vecs / _norm # Directional gradient along x num_grad = np.gradient(dists, x) grad = np.dot(gradients, [1, 0]) assert np.allclose(num_grad, grad, atol=test_eps) # Test y gradient xs = [-1, 2] y = np.linspace(-1, 1.5, npts) for xi in xs: x = xi + np.zeros_like(y) pts = np.vstack((x, y)).T dists, dists_grad, _, proj_vecs = pl.get_dist_to_line(pts) # Gradients are simply the normalized negative projection vectors _norm = np.linalg.norm(proj_vecs, axis=1).reshape(len(proj_vecs), 1) gradients = -proj_vecs / _norm # Directional gradient along x num_grad = np.gradient(dists, y) grad = np.dot(gradients, [0, 1]) assert np.allclose(num_grad, grad, atol=test_eps) return
def test_distance(self): v = [[1, 3], [3, 5], [6, 2], [2, 2]] pl = Polyline(v) # Test values are chosen to yield simple distances and vectors and were # calculated by hand apriori pts = [[1, 2], [1.5, 5.5], [3, 6], [3.5, 3.5], [5.5, 3.5], [4, 1], [2, 2.5]] dists, _, proj_to, proj_vecs = pl.get_dist_to_line(pts) # Should show from pt to closest part of the polyline proj_vecs_exp = [[0, 1], [1, -1], [0, -1], [0.5, 0.5], [-0.5, -0.5], [0, 1], [0, -0.5]] dists_exp = [1., sqrt(2.), 1., sqrt(2.) / 2., sqrt(2.) / 2., 1., 0.5] # id < 0: Onto segment with -id-1, else onto vertex with id # Last point projects exactly orthogonally to end of segment, thus -3 proj_to_exp = [0, -1, 1, -2, -2, -3, -3] for i, (pvexp, dexp, ptexp) in enumerate(zip(proj_vecs_exp, dists_exp, proj_to_exp)): assert proj_vecs[i, 0] == approx(pvexp[0]) assert proj_vecs[i, 1] == approx(pvexp[1]) assert dists[i] == approx(dexp) assert proj_to[i] == ptexp return