Suppose we have a long list of 3D Cartesian coordinates, defining a distribution of random points in 3D space. How could we remove all the points inside a sphere of radius sphereRadius
located at coordinates sphereLocation = {X, Y, Z}
?
This Boolean subtraction is probably trivial, but I didn't found any useful info on how to do it with Mathematica 7.0. Maybe it isn't trivial, after all.
Generalisation : How can we do the same with an arbitrary closed surface, instead of a sphere, if the hole is defined as a deformed sphere ?
holeLocation = {X, Y, Z};
hole[theta_, phi_] = holeLocation +
radius[theta, phi] {Sin[theta]Cos[phi], Sin[theta]Sin[phi], Cos[theta]};
where theta
and phi
are the usual spherical coordinates.
Answer
Using my solution to a similar question asked on StackOverflow some time ago,
Pick[dalist,UnitStep[criticalRadius^2-Total[(Transpose[dalist]-frameCenter)^2]],0]
which is for any number of (Euclidean) dimensions and should be quite fast.
EDIT
Ok, here is a generalization of the vectorized approach I proposed:
ClearAll[cutHole];
cutHole[relativeData_, holdRadiusF_] :=
Module[{r, theta, phi, x, y, z},
{x, y, z} = Transpose[relativeData];
r = Sqrt[Total[relativeData^2, {2}]];
theta = ArcCos[z/r];
phi = ArcTan[x,y];
Pick[relativeData, UnitStep[r - holdRadiusF[theta, phi]], 1]];
Here is an illustration:
data = RandomReal[6, {10^6, 3}];
holeLoc = {3, 3, 3};
relativeData = Transpose[ Transpose[data] - holeLoc];
Define some particular shape of the hole:
holeRad[theta_, phi_] := 1 + 4 Sqrt[Abs[Cos[theta]]]
Pick the points:
kept =cutHole[relativeData,holeRad];//AbsoluteTiming
(* {0.631836,Null} *)
Visualize:
Show[{
ListPointPlot3D[Cases[kept, {_, _, _?Positive}]],
SphericalPlot3D[
holeRad[\[Theta], \[Phi]], {\[Theta], Pi/4, Pi/2}, {\[Phi], 0, 2 Pi},
PlotStyle -> Directive[Orange, Specularity[White, 10]], Mesh -> None]}]
The main point here is that the filtering function is vectorized and therefore quite fast.
Comments
Post a Comment