How to create smooth spheres in the unit cell of a crystal structure?

12 次查看(过去 30 天)
Hello,
I am currently trying to create of crystallographic unit cell and am having trouble making the atom spheres smooth and unfaceted. Currently, I get the below structure using the code attached to this question. I am new to MatLab (and coding in general honestly) so any and all help is welcome. I am also using SpinW if that gives any other helpful info.
% Define lattice parameters
a = 6.778;
c = 12.340; % angstrom
lat_const = [a a c];
% Create the SpinW object
crystal = spinw;
Unrecognized function or variable 'spinw'.
crystal.genlattice('angled', [90 90 90], 'lat_const', lat_const, 'sym', 'P 41 21 2', 'label', 'Er');
% Define atom positions (fractional coordinates)
positions = [
0.87559 0.35274 0.35274
];
spins = 1.5;
labels = {'Er3+'};
colors = {'green'};
crystal.addatom('r', positions', 'S', spins, 'label', labels, 'color', colors);
% Step 1: Definitively determine the number of magnetic atoms
atom_table = crystal.table('atom');
mag_atom_indices = find(atom_table.S ~= 0);
num_mag_atoms = numel(mag_atom_indices);
disp(['Number of magnetic atoms (after symmetry): ', num2str(num_mag_atoms)])
% Step 2: Generate random spins matching num_mag_atoms
random_spins = randn(3, num_mag_atoms);
random_spins = random_spins ./ vecnorm(random_spins);
% Step 3: Assign spins
crystal.genmagstr('mode','direct','S',random_spins);
hFig = plot(crystal, 'atomLabel', false, 'magAtomMode', 'arrow', 'cellMode', 'inside');
hold on; % hold current figure to overlay spheres
% Extract atom positions from crystal object
atom_positions = crystal.atom.r; % fractional coordinates
lattice_vectors = crystal.lattice.lat_const;
% Convert fractional coordinates to Cartesian coordinates
atom_cart_coords = crystal.basisvector * atom_positions;
% Plot each atom as a 3D sphere
[XS, YS, ZS] = sphere(50); % smoother sphere
atom_radius = 0.3; % Adjust radius as needed
default_color = [0.8 0.8 0.8];
num_defined_colors = numel(colors);
for idx = size(atom_cart_coords)
if idx <= num_defined_colors
color_to_use = colors{idx}; % predefined colors
else
color_to_use = default_color; % default color for symmetry-expanded atoms
end
surf(atom_radius*XS + atom_cart_coords(1,idx), ...
atom_radius*YS + atom_cart_coords(2,idx), ...
atom_radius*ZS + atom_cart_coords(3,idx), ...
'FaceColor', default_color, ... % use predefined atom colors
'EdgeColor', 'none');
end
%axis equal;
material shiny;
light;
lighting gouraud; % smoother lighting
camlight headlight; % uniform lighting from camera position
% Access and modify arrow objects directly
hArrow = findobj(hFig, 'Tag', 'arrow');
% Change arrow color explicitly to red
set(hArrow, 'FaceVertexCData', [1 0 0]);
% Optional: Adjust arrow thickness (line width)
set(hArrow, 'LineWidth', 2);
swplot.zoom(1.5);

回答(2 个)

Charu
Charu 2025-3-26
编辑:Charu 2025-3-26
Hello Daniel,
From my perspective, you are trying to create more smooth spheres in the unit cell of a crystal structure. To achieve smooth and unfaceted spheres representing atoms in the provided MATLAB code, you can modify the configuration settings as follows:
1. Sphere Resolution: You can increase the sphere resolution for smoother spheres.
% Increase this number for smoother spheres
resolution = 100;
[XS, YS, ZS] = sphere(resolution)
2. Color Assignment: Ensure that the colors are correctly assigned to each atom. You can use the "size" function to use correct number of atoms.
size(atom_cart_coords,2)
SpinW” uses its own plotting functions, such as “swplot.plot”, to visualize structures. You can use these functions, to work in conjunction with MATLAB’s graphic settings to render the visualisations.
Hope this helps!
For more information, refer to the following MathWorks Documentation:
“size” function:

Simon
Simon 2025-8-20,6:56
Hi,
It is already answered well previously but it looks like you're aiming to improve the visual quality of atom spheres in your spinw visualizations but have noticed that simply increasing the sphere resolution in MATLAB (e.g., using [XS, YS, ZS] = sphere(100)) doesn't affect how "spinwrenders these objects in your code.
  1. You can custom code blended with spinw to achieve the visualisation you’re trying to achieve. This is a sample code that I tried in the manual format which might help you in blending it with your code:
% Atom positions: corners and face centers of a box
atom_cart_coords = [ ...
0 1 1 0 0.5 0.5 0.5 0.5; % X
0 0 1 1 0 1 0 1; % Y
0 0 0 0 1 1 1 1]; % Z
N = size(atom_cart_coords,2);
% Arrow directions: **inward** toward box center (0.5,0.5,0.5)
center = [0.5; 0.5; 0.5];
arrow_dirs = center - atom_cart_coords; % <-- Opposite direction!
arrow_dirs = arrow_dirs ./ vecnorm(arrow_dirs); % Normalize
atom_radius = 0.1; % Slightly smaller radius for clarity
figure;
set(gcf, 'Renderer', 'opengl')
hold on
[XS, YS, ZS] = sphere(100);
% Draw green spheres and red arrows
for idx = 1:N
% Draw sphere
surf(atom_radius*XS + atom_cart_coords(1,idx), ...
atom_radius*YS + atom_cart_coords(2,idx), ...
atom_radius*ZS + atom_cart_coords(3,idx), ...
'FaceColor', [0 0.7 0], ...
'EdgeColor', 'none', ...
'FaceLighting', 'gouraud', ...
'AmbientStrength', 0.3, ...
'SpecularStrength', 0.8, ...
'DiffuseStrength', 0.8);
% Draw 3D arrow as a cone (for realism)
startPt = atom_cart_coords(:,idx);
dirVec = arrow_dirs(:,idx)*0.3; % Arrow length
% Arrow shaft
quiver3(startPt(1), startPt(2), startPt(3), ...
dirVec(1), dirVec(2), dirVec(3), ...
0, 'Color', [1 0 0], 'LineWidth', 2, 'MaxHeadSize', 0.8);
% Arrow head (cone, reversed direction)
[coneX, coneY, coneZ] = cylinder([0.06 0], 30); % Small cone, base at Z=0
coneZ = coneZ * 0.18; % Height of cone
% Rotate and position cone
[az,el,~] = cart2sph(dirVec(1),dirVec(2),dirVec(3));
R = makehgtform('zrotate',az,'yrotate',-el+pi/2);
coneXYZ = R(1:3,1:3) * [coneX(:)'; coneY(:)'; coneZ(:)'];
% Place the base at the tip of the shaft
coneXr = reshape(coneXYZ(1,:),size(coneX)) + startPt(1) + dirVec(1);
coneYr = reshape(coneXYZ(2,:),size(coneY)) + startPt(2) + dirVec(2);
coneZr = reshape(coneXYZ(3,:),size(coneZ)) + startPt(3) + dirVec(3);
surf(coneXr, coneYr, coneZr, 'FaceColor', [1 0 0], 'EdgeColor', 'none');
end
% Draw box outline (unit cell)
plot3([0 1 1 0 0 0 0 1 1 1 1 0], ...
[0 0 1 1 1 1 0 0 0 0 1 1], ...
[0 0 0 0 0 1 1 1 1 0 0 0], 'k--', 'LineWidth', 1)
plot3([0 1 1 0 0 0 1 1 0 0 1 1], ...
[0 0 1 1 0 0 0 0 1 1 1 1], ...
[1 1 1 1 1 0 0 0 0 1 1 1], 'k--', 'LineWidth', 1)
shading interp
lighting gouraud
material shiny
camlight headlight
axis equal
box on
xlabel('X'); ylabel('Y'); zlabel('Z');
view([-30 20]) % Similar to your image
set(gca,'visible','off') % Hide axes
hold off
% Helper function for rotation
function R = makehgtform(varargin)
R = eye(4);
for k=1:2:length(varargin)
switch varargin{k}
case 'zrotate'
theta = varargin{k+1};
R = R * [cos(theta) -sin(theta) 0 0;
sin(theta) cos(theta) 0 0;
0 0 1 0;
0 0 0 1];
case 'yrotate'
theta = varargin{k+1};
R = R * [cos(theta) 0 sin(theta) 0;
0 1 0 0;
-sin(theta) 0 cos(theta) 0;
0 0 0 1];
end
end
end
This approach allows you to render high-quality spheres and arrows at custom positions, providing flexibility for visualizing atomic arrangements.
Hope it helps!

类别

Help CenterFile Exchange 中查找有关 Lighting, Transparency, and Shading 的更多信息

产品


版本

R2024b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by