Creating Aesthetically Pleasing Vector Toroidal Vortex Surface Plots with Python & MATLAB

Creating Aesthetically Pleasing Vector Toroidal Vortex Surface Plots with Python & MATLABIntroductionFollowing our previous article where we plotted scalar topological vortex surfaces, this time we will learn how to plot vector field surfaces, as physical fields are often vector fields. Let’s dive straight into the content!

🌄 MATLAB Vector Topological Vortex Surface Plot

    clc     clear all    close all    %% Vector Topological Vortex    % Initialize window    figure('Color', 'w', 'Position', [100, 100, 800, 600]);    hold on;    axis equal;    axis off;
    %% Parameter Settings    R = 4; % Major Radius - Distance from the center of the torus to the center of the pipe    r = 1.5; % Minor Radius - Radius of the pipe
    %% 1. Draw the orange toroidal surface (Surface)    % Generate mesh data    [theta, phi] = meshgrid(linspace(0, 2*pi, 100), linspace(0, 2*pi, 50));
    % Toroidal parameter equations    X = (R + r * cos(phi)) .* cos(theta);    Y = (R + r * cos(phi)) .* sin(theta);    Z = r * sin(phi);
    % Draw surface    hSurf = surf(X, Y, Z);
    % Set material and lighting effects    set(hSurf, 'FaceColor', [1, 0.6, 0.1], ... % Orange               'EdgeColor', 'none', ...      % Remove grid lines               'FaceAlpha', 0.8, ...         % Set transparency               'AmbientStrength', 0.4, ...               'DiffuseStrength', 0.6, ...               'SpecularStrength', 0.5);
    %% 2. & 3. Draw red streamlines and arrows     num_rings = 12; % Number of red rings    ring_angles = linspace(0, 2*pi, num_rings + 1);     ring_angles(end) = []; % Remove the last duplicate angle
    % For generating a single streamline's phi angle    t = linspace(0, 2*pi, 100); 
    for i = 1:num_rings        th = ring_angles(i); % Fixed angle of the current ring on the large circle
        % Calculate streamline coordinates (poloidal wrapping)        % Note: In the figure, the lines wrap around the pipe (Poloidal direction)        x_line = (R + (r + 0.05) * cos(t)) * cos(th); % r+0.05 is to slightly lift the line above the surface        y_line = (R + (r + 0.05) * cos(t)) * sin(th);        z_line = (r + 0.05) * sin(t);
        % Draw lines        plot3(x_line, y_line, z_line, 'r-', 'LineWidth', 2);
        % --- Add arrows ---        % Select several points on each line to draw arrows        arrow_indices = 10:25:90; % Select several positions on the line
        for idx = arrow_indices            % Current point coordinates            p0 = [x_line(idx), y_line(idx), z_line(idx)];
            % Calculate tangent vector (derivative)            % dx/dt = -r*sin(t)*cos(th)            % dy/dt = -r*sin(t)*sin(th)            % dz/dt = r*cos(t)
            dt_val = t(idx);            vx = -(r) * sin(dt_val) * cos(th);            vy = -(r) * sin(dt_val) * sin(th);            vz = (r) * cos(dt_val);
            % Normalize vector and scale            vec = [vx, vy, vz];            vec = vec / norm(vec) * 0.8; % Length 0.8
            % Use quiver3 to draw arrows            q = quiver3(p0(1), p0(2), p0(3), vec(1), vec(2), vec(3), 0);
            % Set arrow style            set(q, 'Color', 'r', 'LineWidth', 2, 'MaxHeadSize', 0.5, 'ShowArrowHead', 'on');        end    end
    %% 4. Beautify the environment    % Add lighting    light('Position', [10, 10, 10], 'Style', 'local');    light('Position', [-10, -10, 10], 'Style', 'local');    lighting gouraud; % Smooth lighting
    % Adjust title    title('Vector Toroidal Vortex', 'FontSize', 16, 'FontName', 'Arial');
    % Rotate the view slightly to match the 3D effect of the image    view(45, 45); 
    hold off;

Creating Aesthetically Pleasing Vector Toroidal Vortex Surface Plots with Python & MATLAB

    % Initialize window    figure('Color', 'w', 'Position', [100, 100, 800, 700]);    hold on;    axis equal;    axis off;
    % Set view angle (match the perspective angle of the original image)    view(-30, 35);
    %% Core Parameters    R = 4;      % Major Radius (Distance from the center of the ring to the center of the pipe)    r_shell = 2.0;  % Shell Radius (widest)    r_red = 1.95;   % Red line radius (close to the surface)    r_blue = 1.2;   % Blue line radius (located in the inner core)
    %% 1. Draw semi-transparent rainbow shell (Scalar Shell)    % Generate mesh    num_pts = 120;    [theta, phi] = meshgrid(linspace(0, 2*pi, num_pts), linspace(0, 2*pi, num_pts));
    % Toroidal coordinates    X = (R + r_shell .* cos(phi)) .* cos(theta);    Y = (R + r_shell .* cos(phi)) .* sin(theta);    Z = r_shell .* sin(phi);
    % Color mapping (changes based on the poloidal angle phi)    % Adjust phase_shift to make the outer side appear yellow-green and the inner side appear purple-red    phase_shift = 3.5;     C = mod(phi + phase_shift, 2*pi);
    % Draw surface    hSurf = surf(X, Y, Z, C);
    % Beautify the shell    colormap(hsv);         % Rainbow color map    shading interp;        % Smooth interpolation, remove grid lines    set(hSurf, 'FaceAlpha', 0.3, ...   % Key: set transparency (0.0-1.0)               'EdgeColor', 'none', ...               'AmbientStrength', 0.5, ...               'DiffuseStrength', 0.5, ...               'SpecularStrength', 0.6);
    %% 2. Draw red poloidal coils (E Field - Poloidal)    % These coils rotate around the cross-section of the pipe
    num_red_loops = 12; % Number of coils    red_angles = linspace(0, 2*pi, num_red_loops+1);    red_angles(end) = []; 
    t = linspace(0, 2*pi, 100); % Single loop parameters
    for th = red_angles        % Calculate coordinates of a single red line        xr = (R + r_red * cos(t)) * cos(th);        yr = (R + r_red * cos(t)) * sin(th);        zr = r_red * sin(t);
        % Draw lines        plot3(xr, yr, zr, 'Color', [0.8, 0, 0], 'LineWidth', 1.5);
        % --- Add red arrows ---        % Select several points on each line to draw arrows        arrow_indices = [20, 50, 80]; % Arrow positions        for idx = arrow_indices:            p = [xr(idx), yr(idx), zr(idx)];
            % Poloidal tangent vector (derivative)            vx = -sin(t(idx)) * cos(th);            vy = -sin(t(idx)) * sin(th);            vz = cos(t(idx));
            % Normalize and scale            vec = [vx, vy, vz];            vec = vec / norm(vec) * 0.6;
            quiver3(p(1), p(2), p(3), vec(1), vec(2), vec(3), 0, ...                'Color', 'r', 'LineWidth', 2, 'MaxHeadSize', 0.8);        end    end
    %% 3. Draw blue toroidal coils (H Field - Toroidal)    % These coils rotate along the large circle direction of the torus (located inside the pipe)
    % We select several positions inside the pipe to place blue lines (e.g., inner side, outer side, top, bottom)    blue_phi_angles = [0, pi/2, pi, 3*pi/2]; 
    t_blue = linspace(0, 2*pi, 200);
    for phi_val = blue_phi_angles        % Calculate coordinates of a single blue line        xb = (R + r_blue * cos(phi_val)) .* cos(t_blue);        yb = (R + r_blue * cos(phi_val)) .* sin(t_blue);        zb = r_blue * sin(phi_val) .* ones(size(t_blue));
        % Draw lines (using Cyan color, clearer against the rainbow background)        plot3(xb, yb, zb, 'c-', 'LineWidth', 2);
        % --- Add blue arrows ---        arrow_indices = 15:30:200; % More arrows        for idx = arrow_indices:            p = [xb(idx), yb(idx), zb(idx)];
            % Toroidal tangent vector (along the large circle tangent)            vx = -sin(t_blue(idx));            vy = cos(t_blue(idx));            vz = 0;
            vec = [vx, vy, vz];            vec = vec / norm(vec) * 0.6;
            quiver3(p(1), p(2), p(3), vec(1), vec(2), vec(3), 0, ...                'Color', 'c', 'LineWidth', 2, 'MaxHeadSize', 0.8);        end    end
    %% 4. Labeling Text (Labels)    % Calculate text positions to make them appear to float in the corresponding areas    % E (Red)    text(R+r_shell+0.5, 0, 1.5, 'E', 'Color', 'r', 'FontSize', 24, ...        'FontWeight', 'bold', 'FontName', 'Arial');
    % H (Blue)    text(R+r_shell+0.5, 0, -1.5, 'H', 'Color', 'c', 'FontSize', 24, ...        'FontWeight', 'bold', 'FontName', 'Arial');
    % F (Title/Bottom label)    text(0, -(R+r_shell), -3, 'F', 'Color', 'k', 'FontSize', 20, 'FontWeight', 'bold');
    title('Hybrid Toroidal Vortex', 'FontSize', 18);
    %% 5. Lighting and Environment Settings    % Set lights to enhance the 3D effect and reflections of the transparent material    light('Position', [0, -20, 10], 'Style', 'local'); % Front light    light('Position', [10, 10, 10], 'Style', 'local');  % Side fill light    lighting phong; % Make highlights smoother
    % Slightly zoom in    camzoom(1.1);
    hold off;

Creating Aesthetically Pleasing Vector Toroidal Vortex Surface Plots with Python & MATLAB🌄 PythonVector Toroidal Vortex Plotting

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D  
from matplotlib.colors import LightSource
from matplotlib import cm
# ==========================#  Initialize window# ==========================fig = plt.figure(figsize=(8, 6))
fig.patch.set_facecolor('white')
ax = fig.add_subplot(111, projection='3d')
ax.set_box_aspect((1, 1, 1))  ax.set_axis_off()             # ==========================#  Parameter Settings# ==========================R = 4.0   # Major Radius
r = 1.5   # Minor Radius
# ==========================#  1. Draw the toroidal surface# ==========================theta, phi = np.meshgrid(    np.linspace(0, 2 * np.pi, 100),    np.linspace(0, 2 * np.pi, 50))
X = (R + r * np.cos(phi)) * np.cos(theta)
Y = (R + r * np.cos(phi)) * np.sin(theta)
Z = r * np.sin(phi)
# Use LightSource for simple lighting effect
ls = LightSource(azdeg=45, altdeg=45)
rgb = ls.shade(Z, cmap=cm.Oranges, vert_exag=1, blend_mode='soft')
surf = ax.plot_surface(    X, Y, Z,    facecolors=rgb,           linewidth=0,    antialiased=True,    alpha=0.8,    shade=False           )
# ==========================#  2 & 3. Draw red streamlines and arrows# ==========================num_rings = 12                        ring_angles = np.linspace(0, 2 * np.pi, num_rings + 1)[:-1]
t = np.linspace(0, 2 * np.pi, 100)     for th in ring_angles:    # Poloidal wrapped streamlines, radius slightly larger than r, to make the lines "float" above the surface    x_line = (R + (r + 0.05) * np.cos(t)) * np.cos(th)    y_line = (R + (r + 0.05) * np.cos(t)) * np.sin(th)    z_line = (r + 0.05) * np.sin(t)    ax.plot3D(x_line, y_line, z_line, 'r-', linewidth=2)    # Select several points on the line to draw arrows    arrow_indices = [10, 35, 60, 85]    for idx in arrow_indices:        # Current point coordinates        p0 = np.array([x_line[idx], y_line[idx], z_line[idx]])        # Tangent vector (derivative)        dt_val = t[idx]        vx = -r * np.sin(dt_val) * np.cos(th)        vy = -r * np.sin(dt_val) * np.sin(th)        vz =  r * np.cos(dt_val)        vec = np.array([vx, vy, vz])        vec = vec / np.linalg.norm(vec) * 0.8          # 3D arrow        ax.quiver(            p0[0], p0[1], p0[2],            vec[0], vec[1], vec[2],            color='r',            linewidth=2,            arrow_length_ratio=0.3,  # Arrow head size            length=1.0,            normalize=False        )
# ==========================#  4. View and Title (Environment Beautification)# ==========================ax.view_init(elev=45, azim=45)
ax.set_title('Vector Toroidal Vortex', fontsize=16, fontname='Arial')
plt.tight_layout()
plt.show()

Creating Aesthetically Pleasing Vector Toroidal Vortex Surface Plots with Python & MATLAB

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D  # Enable 3D support
from matplotlib import cm
# ==========================# 1. Initialize window# ==========================fig = plt.figure(figsize=(8, 7))
ax = fig.add_subplot(111, projection='3d')
ax.set_box_aspect((1, 1, 1))  # Equal proportions
ax.set_axis_off()             # Turn off axes
# Corresponding MATLAB: view(-30, 35)  ->  elev=35, azim=-30
ax.view_init(elev=35, azim=-30)
# ==========================# 2. Core Parameters# ==========================R = 4.0          # Major Radius
r_shell = 2.0    # Shell Radius
r_red = 1.95     # Red line radius
r_blue = 1.2     # Blue line radius (internal)
# ==========================# 3. Semi-transparent rainbow shell# ==========================num_pts = 120
theta, phi = np.meshgrid(    np.linspace(0, 2 * np.pi, num_pts),    np.linspace(0, 2 * np.pi, num_pts))
X = (R + r_shell * np.cos(phi)) * np.cos(theta)
Y = (R + r_shell * np.cos(phi)) * np.sin(theta)
Z = r_shell * np.sin(phi)
# Color mapping: Generate HSV rainbow based on phi
phase_shift = 3.5
C = np.mod(phi + phase_shift, 2 * np.pi)
C_norm = (C - C.min()) / (C.max() - C.min())  # Normalize to [0,1]
colors = cm.hsv(C_norm)
colors[..., 3] = 0.3  # alpha = 0.3, semi-transparent
surf = ax.plot_surface(    X, Y, Z,    facecolors=colors,    rstride=1, cstride=1,    linewidth=0,    antialiased=True,    shade=False  # We provided colors ourselves, no automatic shading)
# ==========================# 4. Red poloidal coils (E Field)# ==========================num_red_loops = 12
red_angles = np.linspace(0, 2 * np.pi, num_red_loops + 1)[:-1]
t = np.linspace(0, 2 * np.pi, 100)
for th in red_angles:    xr = (R + r_red * np.cos(t)) * np.cos(th)    yr = (R + r_red * np.cos(t)) * np.sin(th)    zr = r_red * np.sin(t)    ax.plot3D(xr, yr, zr, color=(0.8, 0, 0), linewidth=1.5)    # Add red arrows    arrow_indices = [20, 50, 80]    for idx in arrow_indices:        p = np.array([xr[idx], yr[idx], zr[idx]])        # Poloidal direction tangent vector (consistent with MATLAB formula, missing r is just a scalar, normalized is the same)
        vx = -np.sin(t[idx]) * np.cos(th)
        vy = -np.sin(t[idx]) * np.sin(th)
        vz =  np.cos(t[idx])
        vec = np.array([vx, vy, vz])
        vec = vec / np.linalg.norm(vec) * 0.6
        ax.quiver(            p[0], p[1], p[2],            vec[0], vec[1], vec[2],            length=1.0,            normalize=False,            color='r',            linewidth=2,            arrow_length_ratio=0.4  # Arrow head size        )
# ==========================# 5. Blue toroidal coils (H Field)# ==========================blue_phi_angles = [0, 0.5 * np.pi, np.pi, 1.5 * np.pi]
t_blue = np.linspace(0, 2 * np.pi, 200)
for phi_val in blue_phi_angles:    xb = (R + r_blue * np.cos(phi_val)) * np.cos(t_blue)    yb = (R + r_blue * np.cos(phi_val)) * np.sin(t_blue)    zb = r_blue * np.sin(phi_val) * np.ones_like(t_blue)    ax.plot3D(xb, yb, zb, 'c-', linewidth=2)    # Blue arrows    arrow_indices = range(15, 200, 30)    for idx in arrow_indices:        p = np.array([xb[idx], yb[idx], zb[idx]])        # Tangential vector along the large circle direction        vx = -np.sin(t_blue[idx])        vy =  np.cos(t_blue[idx])        vz = 0.0        vec = np.array([vx, vy, vz])        vec = vec / np.linalg.norm(vec) * 0.6        ax.quiver(            p[0], p[1], p[2],            vec[0], vec[1], vec[2],            length=1.0,            normalize=False,            color='c',            linewidth=2,            arrow_length_ratio=0.4        )
# ==========================# 6. Text Labels# ==========================ax.text(    R + r_shell + 0.5, 0, 1.5, 'E',    color='r', fontsize=24, fontweight='bold')
ax.text(    R + r_shell + 0.5, 0, -1.5, 'H',    color='c', fontsize=24, fontweight='bold')
ax.text(    0, -(R + r_shell), -3, 'F',    color='k', fontsize=20, fontweight='bold')
ax.set_title('Hybrid Toroidal Vortex', fontsize=18)
# ==========================# 7. View Range Adjustment# ==========================max_extent = R + r_shell + 1.0
ax.set_xlim(-max_extent, max_extent)
ax.set_ylim(-max_extent, max_extent)
ax.set_zlim(-max_extent, max_extent)
plt.tight_layout()
plt.show()
plt.savefig('/root/result.png')
print("Image saved to /root/result.png")

Creating Aesthetically Pleasing Vector Toroidal Vortex Surface Plots with Python & MATLAB

Leave a Comment