V is a 3D matrix with uniformly spaced voxels. A way to get a coordinate grid / meshgrid would be:
[x y z] = ndgrid( 1:size(V,1), 1:size(V,2), 1:size(V,3) );
which feels redundant, especially if the number of dimensions is even higher. Is there a neater way to do this?
I guess you could do it like this is you have a lot of dimensions (or a changing number of dimensions):
C = arrayfun(#(x)(1:size(V,x)),1:ndims(V),'UniformOutput',false);
[outArgs{1:ndims(V)}] = ndgrid(C{:})
So now using your example
outArgs{1} == x;
outArgs{2} == y;
outArgs{3} == z;
But for 3 dimensions, either leave it has you have it or else maybe you'll find this neater:
[m, n, p] = size(V);
[x, y, z] = ndgrid(1:m, 1:n, 1:p);
Related
I'm trying to make a contour plot in IDL of quantity described by and equation, which here I'll take to be x^2 + y.
In order to do that, I first need to create a 2D array ("pxx").
Being a novice, I'm currently just moving my fist step into this direction and so far I've been trying to make this simpler foreach loop work:
pxx=fltarr(10, 10)
xx = indgen(10)
yy = indgen(10)
foreach k, xx do begin
pxx[k,*]=3*k
endforeach
print, pxx
But this only seems to work for the last column. Any idea on how to fix that? And how would you suggest I proceed to create a 2D array in space for the equation above?
Thank you in advance, any help is appreciated
Choose the range of x and y values you want to evaluate on:
n = 10
x = findgen(n) - (n - 1)/2.0
y = findgen(n) - (n - 1)/2.0
Expand x and y to 2-dimensional versions of themselves:
xx = rebin(reform(x, n, 1), n, n)
yy = rebin(reform(y, 1, n), n, n)
Evaluate the function:
z = xx^2 + yy
Plot:
contour, z, x, y
I have a stl file and I've loaded it in Matlab using stlread function. At this point I have a set of faces and vertices. How can I convert these faces and vertices in a 3D binary array like 512x512x100 array to obtain a binary 3D volume?
Ah lucky you. I am working with STL files recently and I coded some functions to do exactly this.
First, note that you lose precision. STL files represent arbitrary shapes with arbitrary precision and converting it into a volume results in discretization and losses.
That said, there is a very easy method to know if something is inside or outside a closed, connected triangulated surface, regardless if its convex or not: Throw a ray to the infinite and count intersection with the surface. If odd, its inside, if even, outside.
The only special code you need is the line-triangle intersection, and the Möller Trumbore algorithm is one of the most common ones.
function in=inmesh(fv,points)
%INMESH tells you if a point is inside a closed,connected triangulated surface mesh
% Author: Ander Biguri
maxZ=max(fv.vertices(:,3));
counts=zeros(size(points,1),1);
for ii=1:size(points,1)
ray=[points(ii,:);points(ii,1:2) maxZ+1];
for jj=1:size(fv.faces,1)
v=fv.vertices(fv.faces(jj,:),:);
if all(v(:,3)<ray(1,3))
continue;
end
isin=mollerTrumbore(ray, fv.vertices(fv.faces(jj,:),:));
counts(ii)=counts(ii)+isin;
end
end
in=mod(counts,2);
end
From FileExchange, with small modifications:
function [flag, u, v, t] = mollerTrumbore (ray,tri)
% Ray/triangle intersection using the algorithm proposed by Moller and Trumbore (1997).
%
% IMPORTANT NOTE: Assumes infinite legth rays.
% Input:
% ray(1,:) : origin.
% d : direction.
% tri(1,:), tri(2,:), tri(3,:): vertices of the triangle.
% Output:
% flag: (0) Reject, (1) Intersect.
% u,v: barycentric coordinates.
% t: distance from the ray origin.
% Author:
% Jesus Mena
d=ray(2,:)-ray(1,:);
epsilon = 0.00001;
e1 = tri(2,:)-tri(1,:);
e2 = tri(3,:)-tri(1,:);
q = cross(d,e2);
a = dot(e1,q); % determinant of the matrix M
if (a>-epsilon && a<epsilon)
% the vector is parallel to the plane (the intersection is at infinity)
[flag, u, v, t] = deal(0,0,0,0);
return;
end
f = 1/a;
s = ray(1,:)-tri(1,:);
u = f*dot(s,q);
if (u<0.0)
% the intersection is outside of the triangle
[flag, u, v, t] = deal(0,0,0,0);
return;
end
r = cross(s,e1);
v = f*dot(d,r);
if (v<0.0 || u+v>1.0)
% the intersection is outside of the triangle
[flag, u, v, t] = deal(0,0,0,0);
return;
end
if nargout>3
t = f*dot(e2,r); % verified!
end
flag = 1;
return
end
Just generate your points:
yourboundaries=% get the range of your data from the STL file.
[x,y,z]=meshgrid(yourboundaries);
P=[x(:) y(:) z(:)];
in=inmesh(fv,P);
img=reshape(in,yourboundariesSize);
I want to draw the contourf of a certain function and my code was as follows:
xlist = linspace(0, 100, 100)
ylist = linspace(0, 100, 200)
X, Y = meshgrid(xlist, ylist)
#print "X = " + str(X)
#print "Y = " + str(Y)
Z = power_at_each_point(X, Y)
#print "Z = " + str(Z)
figure()
CP2 = contourf(X, Y, Z)
colorbar(CP2)
title('Contour Plot')
xlabel('Room-x (m)')
ylabel('Room-y (m)')
show()
The function power_at_each_point(X,Y) when I test it alone I write:
print power_at_each_point(50, 50)
and the output is -80.9187477018
which basically represents the power reached to this point in the room and it outputs a number normally but when I call it after the meshgrid command it returns an error:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
I want to take each coordinate of points in the room x-coord and y-coord and calculate the power reached at this point using the power_at_each_point method
which is supposed to return a number and I'd represent it in the contourf plot.
My guess is that the arguments (X,Y) of Z = power_at_each_point changed from being just numbers to being arrays which I don't want and that's what is causing the error.
How can I let the function Z = power_at_each_point(X,Y) take as arguments X as a number ex :1 and Y ex :2 and return a value for the power at this point so that I can represent it in my contourf plot.
Any help would be appreciated.
I've found that the function meshgrid wants a Matrix pretty much as an argument so I went ahead and created a Matrix called Z and I filled by myself the values in it and then I went ahead and entered Z as an argument to the meshgrid function:
x_list = linspace(0, 100, 100)
y_list = linspace(0, 100, 100)
X, Y = meshgrid(x_list, y_list)
Z = [[0 for x in range(len(x_list))] for x in range(len(y_list))]
for each_axes in range(len(Z)):
for each_point in range(len(Z[each_axes])):
Z[each_axes][each_point] = power_at_each_point(each_axes, each_point)
figure()
CP2 = contourf(X, Y, Z)
and that got me the result I wanted as far as I was asking here.
The points is reversed in the Z Matrix or as you can say mirrored along the horizontal but that's something i'm gonna play with so that I can get those elements in Z to match how the meshgrid actually sets it's grid points.
I know that to get 10 0's, one can do
A = zeros(10, 1);
To get 10 1's, one can do
A = ones(10, 1);
What about any arbitrary number? Say, I want 10 3's. I have come up with a way of doing it.
A = linspace(3, 3, 10);
Is this satisfactory? Is there a more elegant way of doing this?
Some alternatives:
Using repmat:
A = repmat(3, [5 7]); %// 5x7 matrix filled with the value 3
Using indexing:
A(1:m, 1:n) = x;
Following is a timing comparison between all proposed approaches. As you can see, #Dennis' solutions are the fastest (at least on my system).
Functions:
function y = f1(x,m,n) %// Dennis' "ones"
y = x*ones(m,n);
function y = f2(x,m,n) %// Dennis' "zeros"
y = x+zeros(m,n);
function y = f3(x,m,n) %// Luis' "repmat"
y = repmat(x,[m n]);
function y = f4(x,m,n) %// Luis' "dirty"
y(m,n) = 0;
y(:) = x;
function y = f5(x,m,n) %// Luis' "indexing"
y(1:m,1:n) = x;
function y = f6(x,m,n) %// Divakar's "matrix porod"
y = x*ones(m,1)*ones(1,n);
Benchmarking script for square arrays:
x = 3;
sizes = round(logspace(1,3.7,10)); %// max limited by computer memory
for s = 1:numel(sizes)
n = sizes(s);
m = sizes(s);
time_f1(s) = timeit(#() f1(x,m,n));
time_f2(s) = timeit(#() f2(x,m,n));
time_f3(s) = timeit(#() f3(x,m,n));
time_f4(s) = timeit(#() f4(x,m,n));
time_f5(s) = timeit(#() f5(x,m,n));
time_f6(s) = timeit(#() f6(x,m,n));
end
loglog(sizes, time_f1, 'r.-');
hold on
loglog(sizes, time_f2, 'g.:');
loglog(sizes, time_f3, 'b.-');
loglog(sizes, time_f4, 'm.-');
loglog(sizes, time_f5, 'c.:');
loglog(sizes, time_f6, 'k.:');
xlabel('Array size')
ylabel('Time')
legend('ones', 'zeros', 'repmat', 'dirty', 'indexing', 'matrix prod')
For column arrays: just change the following lines:
sizes = round(logspace(1,3.7,10)).^2; %// max limited by computer memory
n = 1;
m = sizes(s);
For row arrays:
sizes = round(logspace(1,3.7,10)).^2; %// max limited by computer memory
n = sizes(s);
m = 1;
Results for a dual-core CPU, 2-GB RAM, Windows Vista, Matlab R2010b:
Square arrays;
Column arrays;
Row arrays.
There are two basic ways to do this:
A = ones(10,1)*3
B = zeros(10,1)+3
The first one is most commonly used in examples, yet if I am not mistaken, the second one performs slightly better. All in all it is just a matter of taste.
Of course, if you have an existing matrix, there is another simple way:
C = zeros(10,1)
C(:) = 3;
And for completeness, the repmat solution as suggested by #Luis is also fine.
As an alternative, a matrix multiplication (which is supposed to be pretty fast on MATLAB) based method could be also be suggested for 2D or multidimensional array assignment work.
Thus, assuming m as rows, n as columns and x as the value to be assigned for all elements, the code would be -
y = x*ones(m,1)*ones(1,n);
I'm working on a program that determines if lines intersect. I'm using matrices to do this. I understand all the math concepts, but I'm new to Python and NumPy.
I want to add my slope variables and yint variables to a new matrix. They are all floats. I can't seem to figure out the correct format for entering them. Here's an example:
import numpy as np
x = 2
y = 5
w = 9
z = 12
I understand that if I were to just be entering the raw numbers, it would look something like this:
matr = np.matrix('2 5; 9 12')
My goal, though, is to enter the variable names instead of the ints.
You can do:
M = np.matrix([[x, y], [w, z]])
# or
A = np.array([[x, y], [w, z]])
I included the array as well because I would suggest using arrays instead of of matrices. Though matrices seem like a good idea at first (or at least they did for me), imo you'll avoid a lot of headache by using arrays. Here's a comparison of the two that will help you decide which is right for you.
The only disadvantage of arrays that I can think of is that matrix multiply operations are not as pretty:
# With an array the matrix multiply like this
matrix_product = array.dot(vector)
# With a matrix it look like this
matrix_product = matrix * vector
Can you just format the string like this?:
import numpy as np
x = 2
y = 5
w = 9
z = 12
matr = np.matrix('%s %s; %s %s' % (x, y, w, z))