sfstoolbox / sfs-matlab

SFS Toolbox for Matlab/Octave
https://sfs-matlab.readthedocs.io
MIT License
97 stars 39 forks source link

Add tapering window for 3D secondary sources #21

Open hagenw opened 11 years ago

hagenw commented 11 years ago

At the moment we can only calculate a tapering window for 2D arrays like circle, line, box. For 3D the edge detection is not working, which is a prerequisite for calculating a tapering window. The challenge is to find a edge detection algorithm that works for 3D and 2D geometries. If this is not possible maybe we should detect first, if we have a 2D or 3D geometry and apply different algorithms.

fietew commented 8 years ago

Assuming that the points in 3D belong to common parametric surface, e.g. a sphere, one may convert the points' coordinates to a 2D respresentation, e.g. azimuth and polar angle, which reduces the edge detection to the computation of 2D convex hull ( See https://en.wikipedia.org/wiki/Convex_hull ). There are many algorithms which solve this problem for Euclidean space. As a sphere is not Euclidean one may have to modify things (See http://stackoverflow.com/questions/9678624/convex-hull-of-longitude-latitude-points-on-the-surface-of-a-sphere)

hagenw commented 8 years ago

Interesting, maybe we could in general look for a 2D projection of our 3D arrays and then find a convex hull in 2D. In the following I did in example in python for the simple case of a planar array:

import numpy as np
import sfs
from scipy.spatial import ConvexHull

array = sfs.array.planar(30, 0.1, center=[0, 0, 0], orientation=[1, 0, 0])
x0 = array.x
hull = ConvexHull(x0[:,1:3]) # use only 2D projection

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(x0[:,0], x0[:,1], x0[:,2], c='r', marker='o')
for simplex in hull.simplices:
    ax.plot(x0[simplex, 0], x0[simplex, 1], x0[simplex, 2], c='k', linewidth=2.0)

ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')

plt.show()

hull_planar_array

If we have more complicated shapes then we have to figure out what to do. Here, I have an example using a cube shaped array and looking for the 3D convex hull:

import numpy as np
import sfs
from scipy.spatial import ConvexHull

array = sfs.array.cube(30, 0.1, center=[0, 0, 0])
n0 = array.n
a = sfs.mono.drivingfunction.source_selection_plane(n0, [1, 1, 0])
x0 = array.x[a, :]
hull = ConvexHull(x0)

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(x0[:,0], x0[:,1], x0[:,2], c='r', marker='o')
for simplex in hull.simplices:
    ax.plot(x0[simplex, 0], x0[simplex, 1], x0[simplex, 2], c='k', linewidth=2.0)

ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')

plt.show()

hull_cube_array

This could also be solved via a 2D projection, but I don't know yet if there is always an automatic way to find the plane that is best suited for the projection.

hagenw commented 8 years ago

The convhull() function is also available in Matlab, so we only have to get the projection to work correctly. One idea would be to use always the plane vertical to the virtual source direction. The virtual source direction is easy to get for a plane wave and a focused source. In the case of a line source or a point source we could calculate their directions by using the vector pointing from the source position to the center of the loudspeaker array.

Do you know how to easily implement such a projection?