Contenido principal

Resultados de

Tim
Tim
Última actividad el 20 de Abr. de 2024

If you've dabbled in "procedural generation," (algorithmically generating natural features), you may have come across the problem of sphere texturing. How to seamlessly texture a sphere is not immediately obvious. Watch what happens, for example, if you try adding power law noise to an evenly sampled grid of spherical angle coordinates (i.e. a "UV sphere" in Blender-speak):
% Example: how [not] to texture a sphere:
rng(2, 'twister'); % Make what I have here repeatable for you
% Make our radial noise, mapped onto an equal spaced longitude and latitude
% grid.
N = 51;
b = linspace(-1, 1, N).^2;
r = abs(ifft2(exp(6i*rand(N))./(b'+b+1e-5))); % Power law noise
r = rescale(r, 0, 1) + 5;
[lon, lat] = meshgrid(linspace(0, 2*pi, N), linspace(-pi/2, pi/2, N));
[x2, y2, z2] = sph2cart(lon, lat, r);
r2d = @(x)x*180/pi;
% Radial surface texture
subplot(1, 3, 1);
imagesc(r, 'Xdata', r2d(lon(1,:)), 'Ydata', r2d(lat(:, 1)));
xlabel('Longitude (Deg)');
ylabel('Latitude (Deg)');
title('Texture (radial variation)');
% View from z axis
subplot(1, 3, 2);
surf(x2, y2, z2, r);
axis equal
view([0, 90]);
title('Top view');
% Side view
subplot(1, 3, 3);
surf(x2, y2, z2, r);
axis equal
view([-90, 0]);
title('Side view');
The created surface shows "pinching" at the poles due to different radial values mapping to the same location. Furthermore, the noise statistics change based on the density of the sampling on the surface.
How can this be avoided? One standard method is to create a textured volume and sample the volume at points on a sphere. Code for doing this is quite simple:
rng default % Make our noise realization repeatable
% Create our 3D power-law noise
N = 201;
b = linspace(-1, 1, N);
[x3, y3, z3] = meshgrid(b, b, b);
b3 = x3.^2 + y3.^2 + z3.^2;
r = abs(ifftn(ifftshift(exp(6i*randn(size(b3)))./(b3.^1.2 + 1e-6))));
% Modify it - make it more interesting
r = rescale(r);
r = r./(abs(r - 0.5) + .1);
% Sample on a sphere
[x, y, z] = sphere(500);
% Plot
ir = interp3(x3, y3, z3, r, x, y, z, 'linear', 0);
surf(x, y, z, ir);
shading flat
axis equal off
set(gcf, 'color', 'k');
colormap(gray);
The result of evaluating this code is a seamless, textured sphere with no discontinuities at the poles or variation in the spatial statistics of the noise texture:
But what if you want to smooth it or perform some other local texture modification? Smoothing the volume and resampling is not equivalent to smoothing the surficial features shown on the map above.
A more flexible alternative is to treat the samples on the sphere surface as a set of interconnected nodes that are influenced by adjacent values. Using this approach we can start by defining the set of nodes on a sphere surface. These can be sampled almost arbitrarily, though the noise statistics will vary depending on the sampling strategy.
One noise realisation I find attractive can be had by randomly sampling a sphere. Normalizing a point in N-dimensional space by its 2-norm projects it to the surface of an N-dimensional unit sphere, so randomly sampling a sphere can be done very easily using randn() and vecnorm():
N = 5e3; % Number of nodes on our sphere
g=randn(3,N); % Random 3D points around origin
p=g./vecnorm(g); % Projected to unit sphere
The next step is to find each point's "neighbors." The first step is to find the convex hull. Since each point is on the sphere, the convex hull will include each point as a vertex in the triangulation:
k=convhull(p');
In the above, k is an N x 3 set of indices where each row represents a unique triangle formed by a triplicate of points on the sphere surface. The vertices of the full set of triangles containing a point describe the list of neighbors to that point.
What we want now is a large, sparse symmetric matrix where the indices of the columns & rows represent the indices of the points on the sphere and the nth row (and/or column) contains non-zero entries at the indices corresponding to the neighbors of the nth point.
How to do this? You could set up a tiresome nested for-loop searching for all rows (triangles) in k that contain some index n, or you could directly index via:
c=@(x)sparse(k(:,x)*[1,1,1],k,1,N,N);
t=c(1)|c(2)|c(3);
The result is the desired sparse connectivity matrix: a matrix with non-zero entries defining neighboring points.
So how do we create a textured sphere with this connectivity matrix? We will use it to form a set of equations that, when combined with the concept of "regularization," will allow us to determine the properties of the randomness on the surface. Our regularizer will penalize the difference of the radial distance of a point and the average of its neighbors. To do this we replace the main diagonal with the negative of the sum of the off-diagonal components so that the rows and columns are zero-mean. This can be done via:
w=spdiags(-sum(t,2)+1,0,double(t));
Now we invoke a bit of linear algebra. Pretend x is an N-length vector representing the radial distance of each point on our sphere with the noise realization we desire. Y will be an N-length vector of "observations" we are going to generate randomly, in this case using a uniform distribution (because it has a bias and we want a non-zero average radius, but you can play around with different distributions than uniform to get different effects):
Y=rand(N,1);
and A is going to be our "transformation" matrix mapping x to our noisy observations:
Ax = Y
In this case both x and Y are N length vectors and A is just the identity matrix:
A = speye(N);
Y, however, doesn't create the noise realization we want. So in the equation above, when solving for x we are going to introduce a regularizer which is going to penalize unwanted behavior of x by some amount. That behavior is defined by the point-neighbor radial differences represented in matrix w. Our estimate of x can then be found using one of my favorite Matlab assets, the "\" operator:
smoothness = 10; % Smoothness penalty: higher is smoother
x = (A+smoothness*w'*w)\Y; % Solving for radii
The vector x now contains the radii with the specified noise realization for the sphere which can be created simply by multiplying x by p and plotting using trisurf:
p2 = p.*x';
trisurf(k,p2(1,:),p2(2,:),p2(3,:),'FaceC', 'w', 'EdgeC', 'none','AmbientS',0,'DiffuseS',0.6,'SpecularS',1);
light;
set(gca, 'color', 'k');
axis equal
The following images show what happens as you change the smoothness parameter using values [.1, 1, 10, 100] (left to right):
Now you know a couple ways to make a textured sphere: that's the starting point for having a lot of fun with basic procedural planet, moon, or astroid generation! Here's some examples of things you can create based on these general ideas:
Adam Danz
Adam Danz
Última actividad el 20 de Feb. de 2024

The MATLAB command window isn't just for commands and outputs—it can also host interactive hyperlinks. These can serve as powerful shortcuts, enhancing the feedback you provide during code execution. Here are some hyperlinks I frequently use in fprintf statements, warnings, or error messages.
1. Open a website.
msg = "Could not download data from website.";
url = "https://blogs.mathworks.com/graphics-and-apps/";
hypertext = "Go to website"
fprintf(1,'%s <a href="matlab: web(''%s'') ">%s</a>\n',msg,url,hypertext);
Could not download data from website. Go to website
2. Open a folder in file explorer (Windows)
msg = "File saved to current directory.";
directory = cd();
hypertext = "[Open directory]";
fprintf(1,'%s <a href="matlab: winopen(''%s'') ">%s</a>\n',msg,directory,hypertext)
File saved to current directory. [Open directory]
3. Open a document (Windows)
msg = "Created database.csv.";
filepath = fullfile(cd,'database.csv');
hypertext = "[Open file]";
fprintf(1,'%s <a href="matlab: winopen(''%s'') ">%s</a>\n',msg,filepath,hypertext)
Created database.csv. [Open file]
4. Open an m-file and go to a specific line
msg = 'Go to';
file = 'streamline.m';
line = 51;
fprintf(1,'%s <a href="matlab: matlab.desktop.editor.openAndGoToLine(which(''%s''), %d); ">%s line %d</a>', msg, file, line, file, line);
5. Display more text
msg = 'Incomplete data detected.';
extendedInfo = '\tFilename: m32c4r28\n\tDate: 12/20/2014\n\tElectrode: (3,7)\n\tDepth: ???\n';
hypertext = '[Click for more info]';
warning('%s <a href="matlab: fprintf(''%s'') ">%s</a>', msg,extendedInfo,hypertext);
Warning: Incomplete data detected. [Click for more info]
<click>
  • Filename: m32c4r28
  • Date: 12/20/2014
  • Electrode: (3,7)
  • Depth: ???
6. Run a function
Similarly, you can also add hyperlinks in figures and apps
New to ThingsSpeak. I have a Photon 2 and vreated a webhook with simple code to send random numbers reprsented as 'temp' to a channel in ThingSpeak. All good with the code and my device shows the webhook is sending data and the events corespond to the same number of entries received in my channel. However, I do not see any visual graph of the data. What am i missing?
Hi Everyone. I am facing a problem while connecting the FMU to the buses. I have one FMU which expects 9 inputs and I did clarify the same while using bus creator. But in the end i am getting this error which i am trying to solve for couple of hours but didn't get any solution. So if any knows about the same please help me. I would give details as well if you need any other information.
Komal Memon
Komal Memon
Última actividad el 15 de Feb. de 2024

Hello Im tring to connect my master node to thingspeak but it gives error like:
Data received from slave - Temperature: 25.90, Humidity: 46.00, Soil Moisture: 0, pH: 4.26
Failed to send data to ThingSpeak, status code: -301
Data received from slave - Temperature: 25.90, Humidity: 46.00, Soil Moisture: 0, pH: 4.26
Failed to send data to ThingSpeak, status code: -301
What should I do?
Chen Lin
Chen Lin
Última actividad el 14 de Feb. de 2024

See code here in our community contest area. (author: @Zhaoxu Liu / slandarer)
And what do you do for Valentine's Day?
I need to copy Channel field data from a specific data range (e.g. January 2024) from field 6 of channel A(see sample attached) to field 1 of channel B.
I have tried to adopt the Template "Get data from private channel" in the Matlab analysis area of Thingspeak. The last data can be copied according the sample, but I cannot manage to copy the complete datarange. My channel field contains half empty data in field 6, because I have posted data asynchrously from 2 devices to 1 channel up to now.
Any advice for proper Matlab code sample or the like is welcome!
K
K
Última actividad el 10 de Feb. de 2024

which technical support should I contact/ask for the published Simscape example?
Chen Lin
Chen Lin
Última actividad el 10 de Feb. de 2024

To enlarge an array with more rows and/or columns, you can set the lower right index to zero. This will pad the matrix with zeros.
m = rand(2, 3) % Initial matrix is 2 rows by 3 columns
mCopy = m;
% Now make it 2 rows by 5 columns
m(2, 5) = 0
m = mCopy; % Go back to original matrix.
% Now make it 3 rows by 3 columns
m(3, 3) = 0
m = mCopy; % Go back to original matrix.
% Now make it 3 rows by 7 columns
m(3, 7) = 0
Mt Uniacke
Mt Uniacke
Última actividad el 9 de Feb. de 2024

Is anyone having issues downloading the entire data from a channel? I usually include this line to the url but it no longer works: /feed.csv?days=1000000. Any suggestions on a way forward?
Hannah
Hannah
Última actividad el 8 de Feb. de 2024

I was looking into the possibility of making a spin-to-win prize wheel in MATLAB. I was looking around, and if someone has made one before they haven't shared. A labeled colored spinning wheel, that would slow down and stop (or I would take just stopping) at a random spot each time. I would love any tips or links to helpful resources!
Many of the examples in the MATLAB documentation are extremely high quality articles, often worthy of attention in their own right. Time to start celebrating them! Today's is how to increase Image Resolution using deep learning
Hannah
Hannah
Última actividad el 8 de Feb. de 2024

I have been procrastinating on schoolwork by looking at all the amazing designs created in the last MATLAB Flipbook Mini Hack! They are just amazing. The voting is over but what are y'all's personal favorites? Mine is the flapping butterfly, it is for sure a creation I plan to share with others in the future!
Xiang Xu
Xiang Xu
Última actividad el 11 de Mzo. de 2024

Struct is an easy way to combine different types of variants. But now MATLAB supports classes well, and I think class is always a better alternative than struct. I can't find a single scenario that struct is necessary. There are many shortcomings using structs in a project, e.g. uncontrollable field names, unexamined values, etc. What's your opinion?
function dragon24
% Copyright (c) 2024, Zhaoxu Liu / slandarer
baseV=[ -.016,.822; -.074,.809; -.114,.781; -.147,.738; -.149,.687; -.150,.630;
-.157,.554; -.166,.482; -.176,.425; -.208,.368; -.237,.298; -.284,.216;
-.317,.143; -.338,.091; -.362,.037;-.382,-.006;-.420,-.051;-.460,-.084;
-.477,-.110;-.430,-.103;-.387,-.084;-.352,-.065;-.317,-.060;-.300,-.082;
-.331,-.139;-.359,-.201;-.385,-.262;-.415,-.342;-.451,-.418;-.494,-.510;
-.533,-.599;-.569,-.675;-.607,-.753;-.647,-.829;-.689,-.932;-.699,-.988;
-.639,-.905;-.581,-.809;-.534,-.717;-.489,-.642;-.442,-.543;-.393,-.447;
-.339,-.362;-.295,-.296;-.251,-.251;-.206,-.241;-.183,-.281;-.175,-.350;
-.156,-.434;-.136,-.521;-.128,-.594;-.103,-.677;-.083,-.739;-.067,-.813;-.039,-.852];
% 基础比例、上色方式数据
baseV=[0,.82;baseV;baseV(end:-1:1,:).*[-1,1];0,.82];
baseV=baseV-mean(baseV,1);
baseF=1:size(baseV,1);
baseY=baseV(:,2);
baseY=(baseY-min(baseY))./(max(baseY)-min(baseY));
N=30;
baseR=sin(linspace(pi/4,5*pi/6,N))./1.2;
baseR=[baseR',baseR'];baseR(1,:)=[1,1];
baseR(5,:)=[2,.6];
baseR(10,:)=[3.7,.4];
baseR(15,:)=[1.8,.6];
baseT=[zeros(N,1),ones(N,1)];
baseM=zeros(N,2);
baseD=baseM;
ratioT=@(Mat,t)Mat*[cos(t),sin(t);-sin(t),cos(t)];
% 配色数据
CList=[211,56,32;56,105,166;253,209,95]./255;
% CList=bone(4);CList=CList(2:4,:);
% CList=flipud(bone(3));
% CList=lines(3);
% CList=colorcube(3);
% CList=rand(3)
baseC1=CList(2,:)+baseY.*(CList(1,:)-CList(2,:));
baseC2=CList(3,:)+baseY.*(CList(1,:)-CList(3,:));
% 构建图窗
fig=figure('units','normalized','position',[.1,.1,.5,.8],...
'UserData',[98,121,32,115,108,97,110,100,97,114,101,114]);
axes('parent',fig,'NextPlot','add','Color',[0,0,0],...
'DataAspectRatio',[1,1,1],'XLim',[-6,6],'YLim',[-6,6],'Position',[0,0,1,1]);
% 构造龙每个部分句柄
dragonHdl(1)=patch('Faces',baseF,'Vertices',baseV,'FaceVertexCData',baseC1,'FaceColor','interp','EdgeColor','none','FaceAlpha',.95);disp(char(fig.UserData))
for i=2:N
dragonHdl(i)=patch('Faces',baseF,'Vertices',baseV.*baseR(i,:)-[0,i./2.5-.3],'FaceVertexCData',baseC2,'FaceColor','interp','EdgeColor','none','FaceAlpha',.7);
end
set(dragonHdl(5),'FaceVertexCData',baseC1,'FaceAlpha',.7)
set(dragonHdl(10),'FaceVertexCData',baseC1,'FaceAlpha',.7)
set(dragonHdl(15),'FaceVertexCData',baseC1,'FaceAlpha',.7)
for i=N:-1:1,uistack(dragonHdl(i),'top');end
for i=1:N
baseM(i,:)=mean(get(dragonHdl(i),'Vertices'),1);
end
baseD=diff(baseM(:,2));Pos=[0,2];
% 主循环及旋转、运动计算
set(gcf,'WindowButtonMotionFcn',@dragonFcn)
fps=8;
game=timer('ExecutionMode', 'FixedRate', 'Period',1/fps, 'TimerFcn', @dragonGame);
start(game)
% Copyright (c) 2023, Zhaoxu Liu / slandarer
set(gcf,'tag','co','CloseRequestFcn',@clo);
function clo(~,~)
stop(game);delete(findobj('tag','co'));clf;close
end
function dragonGame(~,~)
Dir=Pos-baseM(1,:);
Dir=Dir./norm(Dir);
baseT=(baseT(1:end,:)+[Dir;baseT(1:end-1,:)])./2;
baseT=baseT./(vecnorm(baseT')');
theta=atan2(baseT(:,2),baseT(:,1))-pi/2;
baseM(1,:)=baseM(1,:)+(Pos-baseM(1,:))./30;
baseM(2:end,:)=baseM(1,:)+[cumsum(baseD.*baseT(2:end,1)),cumsum(baseD.*baseT(2:end,2))];
for ii=1:N
set(dragonHdl(ii),'Vertices',ratioT(baseV.*baseR(ii,:),theta(ii))+baseM(ii,:))
end
end
function dragonFcn(~,~)
xy=get(gca,'CurrentPoint');
x=xy(1,1);y=xy(1,2);
Pos=[x,y];
Pos(Pos>6)=6;
Pos(Pos<-6)=6;
end
end