Apply constant-value MATLAB function to array - arrays

Assume I generate MATLAB function using symbolic expression, which sometimes can be a constant. For example, if I compute gradient of different curves, one of the vector components can be a number:
syms x y;
expr = x^2 - 4*y;
grad = gradient(expr, [x, y]);
grad_func = matlabFunction(grad, 'Vars', [x, y]);
Assume that I want to apply this to an array of points. Is there a way to make generated MATLAB function robust enough to always return an array of the same size as input, even if original analytical expression (or a certain component of it) was a constant?
I try the following:
X = [-1:0.2:1];
Y = [-1:0.2:1];
[Gx, Gy] = grad_func(X,Y);
but get the error:
Error using vertcat
Dimensions of matrices being concatenated are not consistent.
Error in symengine>makeFhandle/#(x,y)[x.*2.0;-4.0]
I also tried to use ARRAYFUN:
[Gx, Gy] = arrayfun(grad_func,X,Y);
but failed as well:
The right hand side of this assignment has too few values to satisfy the left hand side.
Error in symengine>makeFhandle/#(x,y)[x.*2.0;-4.0]

Here is how you do the array function
g = cell2mat(arrayfun(#(x,y) grad_func(x,y), X(:)',Y(:)', 'uni', 0));
Gx = reshape(g(1, :), size(X));
Gy = reshape(g(2, :), size(Y));

Related

Matlab Array Division

I have been playing with matlab and was trying to calculate absolute relative error using two arrays. However, when I divide the two arrays, my resulting array has the same value throughout the array even though when I calculate the values by hand, they are not all the same. I was wondering why my resulting array shows the same answer for every value in the array.
Here is my code:
function [X] = absrelerror(A, B)
% Calculates absolute relative error for true value A and approximate value B.
A = linspace(sin(-pi/6), sin(pi/6), 50); %True
B = linspace(-pi/6, pi/6, 50); %Approximate
Y = abs((A-B) ./ A); %ARE equation
X = Y * 100; %convert to percent
end
I think you have approached the problem in a wrong way.
Here, the first elements of both A and B are constant. Also, the spacing between two elements of any of the vectors is also constant. Say, they are c and d where c = {A(50) - A(1)}/49 and d = {B(50) - B(1)}/49. Now, the nth value of Y is {A(1)*nc - B(1)*nd}/{A(1)*c} = {A(1)*c - B(1)*c}/A(1) which is constant. So, it's not surprising that MATLAB is giving a constant value in Y.
If I have understood correctly what you are trying to do, then you should do it in the following way:
%A = linspace(sin(-pi/6), sin(pi/6), 50); %True
B = linspace(-pi/6, pi/6, 50); %Approximate
%Y = abs((A-B) ./ A); %ARE equation
%X = Y * 100; %convert to percent
A = sin(B);
X = abs((A-B)./A) * 100;
fprintf('%f ', X)
The output is:
4.719755 4.330958 3.960262 3.607413 3.272170 2.954306 2.653606 2.369868 2.102903 1.852533 1.618593 1.400927 1.199394 1.013862 0.844209 0.690325 0.552111 0.429477 0.322344 0.230643 0.154315 0.093311 0.047592 0.017130 0.001903 0.001903 0.017130 0.047592 0.093311 0.154315 0.230643 0.322344 0.429477 0.552111 0.690325 0.844209 1.013862 1.199394 1.400927 1.618593 1.852533 2.102903 2.369868 2.653606 2.954306 3.272170 3.607413 3.960262 4.330958 4.719755

Load stl file in matlab and convert to a 3D array

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);

How to implement conjugate matrix transpose function in matlab?

I'm new into matlab and my problem is that I'm trying to implement conjugate matrix transpose function('), but I have no idea how to change sign only in imaginary number. I know it may be stupid question but thanks for any tips and advice.
I tried something like this, but I got these errors:
error: complex matrix type invalid as index value
error: assignment failed, or no method for ' = matrix'
function [ result ] = transpose_matrix( a )
[Row,Col] = size(a);
result = zeros(Col, Row);
iY=1;
for iRow=1:Row
iX=iRow;
for iCol=1:Col
result(iX)=a(iY);
iX=iX+Row;
iY=iY+1;
end
end
imag(result)=imag(result)*-1;
end
MATLAB is confused because the following statement tries to treat imag as a variable with result as an index since it's on the left-hand side of the assignment.
imag(result) = imag(result) * (-1);
Also, it's important to note that imag returns a real number which is the magnitude of the imaginary component. Once you modify the output of imag, you need to multiply by sqrt(-1) to get it back to an imaginary number
imag(a) * (-1) * 1i;
Now to modify only the imaginary component of result, you'll want to simply add this new imaginary component with the real component of result.
result = real(result) + imag(result) * (-1) * 1i;
Or more simply:
result = real(result) - imag(result) * 1i;
A Potential Alternative
If you can use the normal transpose function you could replace your entire function with the following:
result = transpose(a);
result = real(result) - imag(result) * 1i;

Arrays operations in Matlab

I would like a function to compute the following operation:
I made this function that requires a matrix at its input, and returns the distances between every two lines of it in another matrix.
RGB_dist_full definition:
function[D]=RGB_dist_full(x)
I = nchoosek(1:size(x,1),2);
D = RGB_dist(x(I(:,1),:), x(I(:,2),:));
squareform(D)
end
RGB_dist definition:
function[distance]=RGB_dist(x,y)
distance=sqrt(sum((x-y).^2*[3;4;2],2));
end
Main program looks like this:
clc
clear all
rgbImage = imread('peppers.png');
K=6;
N=uint64(K*2);
rgb_columns = reshape(rgbImage, [], 3);
[unique_colors, m, n] = unique(rgb_columns, 'rows','stable');
color_counts = accumarray(n, 1);
[max_count, idx] = max(color_counts);
Imgsize=size(rgbImage);
U=unique_colors(1:N,:)
size(U)
x=[62,29,64;
63,31,62;
65,29,60;
63,29,62;
63,31,62;];
RGB_dist_full(x);
RGB_dist_full(U);
Why do I get 'Error using *
MTIMES is not fully supported for
integer classes. At least one input
must be scalar.
To compute elementwise TIMES, use
TIMES (.*) instead.' for the second call of the function, whereas the first one returns the desired output?
For these types of calculations you want to cast to double precision , because sqrt(integer) is usually not an integer. For that just double(rgbImage) immediately after reading the image will do.

Values of Variables Matrix NumPy

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))

Resources