python+form+opengl显示动态图形数据

说明:
python+form+opengl显示动态图形数据
我希望做一款动态opengl图形数据
1.用python脚本,输入指定参数
2.生成一组数据,
3.将数据保持成本地文件
4.在c#中调用此文件,解析
5.将数据用opengl展示

效果图:
在这里插入图片描述

step1:添加依赖
C:\Users\wangrusheng\RiderProjects\WinFormsApp8\WinFormsApp8\WinFormsApp8.csproj

<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup><OutputType>WinExe</OutputType><TargetFramework>net9.0-windows</TargetFramework><Nullable>enable</Nullable><UseWindowsForms>true</UseWindowsForms><ImplicitUsings>enable</ImplicitUsings><AllowUnsafeBlocks>true</AllowUnsafeBlocks></PropertyGroup><ItemGroup><PackageReference Include="ncalc" Version="1.3.8" /><PackageReference Include="Silk.NET.Core" Version="2.22.0" /><PackageReference Include="Silk.NET.GLFW" Version="2.22.0" /><PackageReference Include="Silk.NET.OpenGL" Version="2.22.0" /></ItemGroup></Project>

step2:forms
C:\Users\wangrusheng\RiderProjects\WinFormsApp8\WinFormsApp8\Form1.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Windows.Forms;
using System.Drawing;
using NCalc;
using Silk.NET.GLFW;
using Silk.NET.OpenGL;
using System.Runtime.InteropServices;namespace WinFormsApp8
{public unsafe partial class Form1 : Form{// OpenGL相关成员private GL gl;private Glfw glfw;private WindowHandle* glfwWindow;private System.Windows.Forms.Panel glPanel;private uint shaderProgram;private uint vao;private uint vbo;// 数据相关成员private readonly Dictionary<string, double> variables = new Dictionary<string, double>();private readonly List<float> verticesData = new List<float>();private DateTime _startTime = DateTime.Now;// 摄像机控制private Vector2 _cameraAngle = new Vector2(0, (float)(Math.PI / 6)); // 30度的弧度值 ≈ 0.5236private Point _lastMousePos;private bool _mouseDown;// Win32 API[DllImport("user32.dll")]private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);[DllImport("user32.dll")]private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter,int X, int Y, int cx, int cy, SetWindowPosFlags uFlags);[DllImport("glfw3.dll", CallingConvention = CallingConvention.Cdecl)]private static extern IntPtr glfwGetWin32Window(WindowHandle* window);// 使用逐字字符串(@)避免转义反斜杠private string absolutePath = @"C:\Users\wangrusheng\PycharmProjects\FastAPIProject1\input.txt";[Flags]private enum SetWindowPosFlags : uint{FrameChanged = 0x0020}public Form1(){InitializeComponent();InitializeOpenGLPanel();this.Load += Form1_Load;this.Resize += Form1_Resize;this.MouseDown += Form1_MouseDown;this.MouseMove += Form1_MouseMove;this.MouseUp += Form1_MouseUp;}private void Form1_Load(object? sender, EventArgs e){try{SetupGLFWWindow();InitializeOpenGL();ProcessInputFile(absolutePath);SetupGeometry();StartRenderTimer();}catch (Exception ex){MessageBox.Show($"初始化失败: {ex.Message}");Close();}}private void InitializeOpenGLPanel(){glPanel = new Panel{Dock = DockStyle.Fill,BackColor = Color.Black};Controls.Add(glPanel);}private void SetupGLFWWindow(){glfw = Glfw.GetApi();glfw.Init();glfw.WindowHint(WindowHintInt.ContextVersionMajor, 3);glfw.WindowHint(WindowHintInt.ContextVersionMinor, 3);glfw.WindowHint(WindowHintOpenGlProfile.OpenGlProfile, OpenGlProfile.Core);glfw.WindowHint(WindowHintBool.Decorated, false);unsafe{glfwWindow = glfw.CreateWindow(glPanel.Width, glPanel.Height, "GLFW", null, null);glfw.ShowWindow(glfwWindow);var hwnd = glfwGetWin32Window(glfwWindow);SetParent(hwnd, glPanel.Handle);SetWindowPos(hwnd, IntPtr.Zero, 0, 0,glPanel.Width, glPanel.Height, SetWindowPosFlags.FrameChanged);glfw.MakeContextCurrent(glfwWindow);glfw.SwapInterval(1); }}private void InitializeOpenGL(){gl = GL.GetApi(glfw.GetProcAddress);gl.Viewport(0, 0, (uint)glPanel.Width, (uint)glPanel.Height);gl.Enable(EnableCap.DepthTest);// 着色器程序const string vertexShaderSource = @"#version 330 corelayout (location = 0) in vec3 aPos;layout (location = 1) in vec3 aColor;out vec3 ourColor;uniform mat4 projection;uniform mat4 view;uniform mat4 model;void main(){gl_Position = projection * view * model * vec4(aPos, 1.0);ourColor = aColor;}";const string fragmentShaderSource = @"#version 330 corein vec3 ourColor;out vec4 FragColor;void main(){FragColor = vec4(ourColor, 1.0);}";uint vertexShader = gl.CreateShader(ShaderType.VertexShader);gl.ShaderSource(vertexShader, vertexShaderSource);gl.CompileShader(vertexShader);uint fragmentShader = gl.CreateShader(ShaderType.FragmentShader);gl.ShaderSource(fragmentShader, fragmentShaderSource);gl.CompileShader(fragmentShader);shaderProgram = gl.CreateProgram();gl.AttachShader(shaderProgram, vertexShader);gl.AttachShader(shaderProgram, fragmentShader);gl.LinkProgram(shaderProgram);gl.DeleteShader(vertexShader);gl.DeleteShader(fragmentShader);}private void ProcessInputFile(string path){if (!File.Exists(path))throw new FileNotFoundException("找不到输入文件", path);variables.Clear();verticesData.Clear();foreach (var line in File.ReadLines(path)){var trimmed = line.Trim();if (string.IsNullOrEmpty(trimmed) || trimmed.StartsWith("#"))continue;ProcessLine(trimmed);}if (verticesData.Count % 6 != 0)throw new InvalidDataException("顶点数据格式不正确,应为每行6个浮点数");}private void ProcessLine(string line){try{if (line.Contains("=")) // 变量赋值{var parts = line.Split(new[] { '=' }, 2);var varName = parts[0].Trim();var expr = parts[1].Trim();variables[varName] = EvaluateExpression(expr);}else // 顶点数据{var values = line.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);foreach (var value in values){var result = EvaluateExpression(value.Trim());verticesData.Add((float)result);}}}catch (Exception ex){throw new InvalidDataException($"处理行时出错: {line}\n错误信息: {ex.Message}");}}private double EvaluateExpression(string expr){var e = new Expression(expr, EvaluateOptions.IgnoreCase);var paramDict = variables.ToDictionary(kvp => kvp.Key, kvp => (object)kvp.Value );e.Parameters = paramDict;e.EvaluateFunction += (name, args) =>{if (name.Equals("sin", StringComparison.OrdinalIgnoreCase))args.Result = Math.Sin(Convert.ToDouble(args.Parameters[0].Evaluate()));else if (name.Equals("cos", StringComparison.OrdinalIgnoreCase))args.Result = Math.Cos(Convert.ToDouble(args.Parameters[0].Evaluate()));};return Convert.ToDouble(e.Evaluate());}private void SetupGeometry(){vao = gl.GenVertexArray();vbo = gl.GenBuffer();gl.BindVertexArray(vao);gl.BindBuffer(BufferTargetARB.ArrayBuffer, vbo);var vertices = verticesData.ToArray();unsafe{fixed (float* ptr = vertices){gl.BufferData(BufferTargetARB.ArrayBuffer,(nuint)(vertices.Length * sizeof(float)),ptr, BufferUsageARB.StaticDraw);}}gl.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 6 * sizeof(float), (void*)0);gl.EnableVertexAttribArray(0);gl.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 6 * sizeof(float), (void*)(3 * sizeof(float)));gl.EnableVertexAttribArray(1);}private void StartRenderTimer(){var timer = new System.Windows.Forms.Timer { Interval = 16 };timer.Tick += (s, e) => Render();timer.Start();}private void Render(){if (gl == null) return;gl.ClearColor(0.1f, 0.1f, 0.1f, 1.0f);gl.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);// 计算矩阵float aspect = (float)glPanel.Width / glPanel.Height;float time = (float)(DateTime.Now - _startTime).TotalSeconds;var model = Matrix4x4.CreateRotationY(time);var view = CreateViewMatrix();var projection = Matrix4x4.CreatePerspectiveFieldOfView(MathHelper.PiOver4, aspect, 0.1f, 100.0f);// 传递矩阵到着色器gl.UseProgram(shaderProgram);unsafe{gl.UniformMatrix4(gl.GetUniformLocation(shaderProgram, "model"), 1, false, (float*)&model);gl.UniformMatrix4(gl.GetUniformLocation(shaderProgram, "view"), 1, false, (float*)&view);gl.UniformMatrix4(gl.GetUniformLocation(shaderProgram, "projection"), 1, false, (float*)&projection);}// 绘制gl.BindVertexArray(vao);gl.DrawArrays(PrimitiveType.Triangles, 0, (uint)(verticesData.Count / 6));unsafe { glfw.SwapBuffers(glfwWindow); }glfw.PollEvents();}private Matrix4x4 CreateViewMatrix(){var eyePos = new Vector3((float)(Math.Sin(_cameraAngle.X) * Math.Cos(_cameraAngle.Y)),(float)Math.Sin(_cameraAngle.Y),(float)(Math.Cos(_cameraAngle.X) * Math.Cos(_cameraAngle.Y))) * 3.0f;return Matrix4x4.CreateLookAt(eyePos,Vector3.Zero,Vector3.UnitY);}private void Form1_Resize(object? sender, EventArgs e){if (glfwWindow == null || glPanel == null) return;glfw.SetWindowSize(glfwWindow, glPanel.Width, glPanel.Height);var hwnd = glfwGetWin32Window(glfwWindow);SetWindowPos(hwnd, IntPtr.Zero, 0, 0,glPanel.Width, glPanel.Height, SetWindowPosFlags.FrameChanged);gl?.Viewport(0, 0, (uint)glPanel.Width, (uint)glPanel.Height);}private void Form1_MouseDown(object sender, MouseEventArgs e){_mouseDown = true;_lastMousePos = e.Location;}private void Form1_MouseMove(object sender, MouseEventArgs e){if (_mouseDown){var delta = new Vector2(e.X - _lastMousePos.X, e.Y - _lastMousePos.Y);_cameraAngle += delta * 0.01f;_cameraAngle.Y = Math.Clamp(_cameraAngle.Y, -MathHelper.PiOver2 + 0.1f, MathHelper.PiOver2 - 0.1f);_lastMousePos = e.Location;}}private void Form1_MouseUp(object sender, MouseEventArgs e){_mouseDown = false;}protected override void OnFormClosing(FormClosingEventArgs e){base.OnFormClosing(e);if (gl != null){gl.DeleteBuffer(vbo);gl.DeleteVertexArray(vao);gl.DeleteProgram(shaderProgram);}glfw?.Terminate();}}public static class MathHelper{public const float Pi = (float)Math.PI;public const float PiOver2 = Pi / 2.0f;public const float PiOver4 = Pi / 4.0f;}}

step3:到这里opengl写完了 运行 验证没问题,至少渲染部分解决了,接下来处理python脚本
C:\Users\wangrusheng\PycharmProjects\FastAPIProject1\generate_shape.py

import math
import argparsedef generate_triangle(size=0.5, color=(1.0, 0.0, 0.0)):"""生成三角形顶点数据"""return [(-size, -size, 0.0, *color),(size, -size, 0.0, *color),(0.0, size, 0.0, *color)]def generate_cube(size=0.5):"""生成立方体顶点数据(每个面不同颜色)"""vertices = []# 前面(红色)vertices.extend(_cube_face(size, "front", (1.0, 0.0, 0.0)))# 后面(绿色)vertices.extend(_cube_face(size, "back", (0.0, 1.0, 0.0)))# 左面(蓝色)vertices.extend(_cube_face(size, "left", (0.0, 0.0, 1.0)))# 右面(黄色)vertices.extend(_cube_face(size, "right", (1.0, 1.0, 0.0)))# 顶面(品红)vertices.extend(_cube_face(size, "top", (1.0, 0.0, 1.0)))# 底面(青色)vertices.extend(_cube_face(size, "bottom", (0.0, 1.0, 1.0)))return verticesdef _cube_face(size, face, color):"""生成单个立方体面的两个三角形"""s = sizeif face == "front":return [(-s, -s, s, *color), (s, -s, s, *color), (s, s, s, *color),(s, s, s, *color), (-s, s, s, *color), (-s, -s, s, *color)]elif face == "back":return [(-s, -s, -s, *color), (s, -s, -s, *color), (s, s, -s, *color),(s, s, -s, *color), (-s, s, -s, *color), (-s, -s, -s, *color)]elif face == "left":return [(-s, -s, -s, *color), (-s, -s, s, *color), (-s, s, s, *color),(-s, s, s, *color), (-s, s, -s, *color), (-s, -s, -s, *color)]elif face == "right":return [(s, -s, -s, *color), (s, -s, s, *color), (s, s, s, *color),(s, s, s, *color), (s, s, -s, *color), (s, -s, -s, *color)]elif face == "top":return [(-s, s, -s, *color), (s, s, -s, *color), (s, s, s, *color),(s, s, s, *color), (-s, s, s, *color), (-s, s, -s, *color)]elif face == "bottom":return [(-s, -s, -s, *color), (s, -s, -s, *color), (s, -s, s, *color),(s, -s, s, *color), (-s, -s, s, *color), (-s, -s, -s, *color)]import mathdef generate_sphere(radius=0.5,rings=16,sectors=32,color_top=(1.0, 0.0, 0.0),color_bottom=(0.0, 0.0, 1.0)
):vertices = []# 生成顶点数据(带颜色插值)for i in range(rings + 1):phi = math.pi * i / rings  # 纬度角 0~πfor j in range(sectors + 1):theta = 2 * math.pi * j / sectors  # 经度角 0~2πx = radius * math.sin(phi) * math.cos(theta)y = radius * math.cos(phi)z = radius * math.sin(phi) * math.sin(theta)# 颜色插值t = i / ringsred = color_top[0] * (1 - t) + color_bottom[0] * tgreen = color_top[1] * (1 - t) + color_bottom[1] * tblue = color_top[2] * (1 - t) + color_bottom[2] * tvertices.append((x, y, z, red, green, blue))# 生成三角形索引indices = []for i in range(rings):for j in range(sectors):a = i * (sectors + 1) + jb = a + 1c = (i + 1) * (sectors + 1) + jd = c + 1# 三角形1: a-c-bindices.extend([a, c, b])# 三角形2: b-c-dindices.extend([b, c, d])# 展开索引为顶点数据expanded_vertices = [vertices[i] for i in indices]return expanded_verticesdef save_to_file(filename, vertices, variables=None):"""保存到文件"""with open(filename, 'w') as f:# 写入变量定义if variables:for name, value in variables.items():f.write(f"{name} = {value}\n")# 写入顶点数据for v in vertices:line = ", ".join(f"{x:.4f}" if isinstance(x, float) else str(x) for x in v)f.write(line + "\n")if __name__ == "__main__":parser = argparse.ArgumentParser(description='生成3D形状的顶点数据文件')parser.add_argument('shape', choices=['triangle', 'cube', 'sphere'],help='要生成的形状')parser.add_argument('-o', '--output', default='input.txt',help='输出文件名')parser.add_argument('--size', type=float, default=0.5,help='形状尺寸(立方体边长/球体半径)')parser.add_argument('--color', nargs=3, type=float, default=None,metavar=('R', 'G', 'B'),help='统一颜色(0.0-1.0)')parser.add_argument('--rings', type=int, default=16,help='球体的纬度分段数(默认:16)')parser.add_argument('--sectors', type=int, default=32,help='球体的经度分段数(默认:32)')parser.add_argument('--color-top', nargs=3, type=float, default=[1.0, 0.0, 0.0],metavar=('R', 'G', 'B'),help='球体顶部颜色(默认:红色)')parser.add_argument('--color-bottom', nargs=3, type=float, default=[0.0, 0.0, 1.0],metavar=('R', 'G', 'B'),help='球体底部颜色(默认:蓝色)')args = parser.parse_args()# 生成顶点数据color = args.color if args.color else Nonevariables = {"object_size": args.size}if args.shape == 'triangle':vertices = generate_triangle(args.size, color or (1.0, 0.0, 0.0))elif args.shape == 'cube':vertices = generate_cube(args.size)elif args.shape == 'sphere':vertices = generate_sphere(radius=args.size,rings=args.rings,sectors=args.sectors,color_top=args.color_top,color_bottom=args.color_bottom)# 保存文件save_to_file(args.output, vertices, variables)print(f"成功生成 {args.shape} 数据到 {args.output},包含 {len(vertices)} 个顶点")

step4:在终端里,输入指令,生成数据文件


(.venv) PS C:\Users\wangrusheng\PycharmProjects\FastAPIProject1> python generate_shape.py sphere --rings 20 --sectors 40 --color-top 1 1 0 --color-bottom 0 1 0 -o input.txt
成功生成 sphere 数据到 input.txt,包含 4800 个顶点
(.venv) PS C:\Users\wangrusheng\PycharmProjects\FastAPIProject1> python generate_shape.py sphere -o input.txt                                                               
成功生成 sphere 数据到 input.txt,包含 3072 个顶点
(.venv) PS C:\Users\wangrusheng\PycharmProjects\FastAPIProject1> python generate_shape.py cube --size 0.8 -o input.txt                                                      
成功生成 cube 数据到 input.txt,包含 36 个顶点
(.venv) PS C:\Users\wangrusheng\PycharmProjects\FastAPIProject1> python generate_shape.py triangle -o input.txt       
成功生成 triangle 数据到 input.txt,包含 3 个顶点
(.venv) PS C:\Users\wangrusheng\PycharmProjects\FastAPIProject1>

step5:生成的文件路径
C:\Users\wangrusheng\PycharmProjects\FastAPIProject1\input.txt

object_size = 0.5
-0.5000, -0.5000, 0.0000, 1.0000, 0.0000, 0.0000
0.5000, -0.5000, 0.0000, 1.0000, 0.0000, 0.0000
0.0000, 0.5000, 0.0000, 1.0000, 0.0000, 0.0000

///我是分割线 旧的实现方式
step101:


至少旧样式可以了
参考下面的代码格式,给我生成一个立方体的参数 ,在input.txt文件中4. 示例输入文件格式 (input.txt)# 变量定义
size = 0.8
color_red = 1.0# 顶点数据(前3个为位置,后3个为颜色)
-size, -size, 0, color_red, 0, 0
size, -size, 0, 0, 1, 0
0, size, 0, 0, 0, 15. 示例输入文件格式 (input.txt)# 定义变量
size = 0.5
red = 1.0
green = 0.5
blue = sin(3.14159/2)  # 支持数学函数# 顶点数据(位置xyz + 颜色rgb)
-size, -size, 0, red, 0, 0
size, -size, 0, 0, green, 0
0, size, 0, 0, 0, blue# 第二个三角形
0.2, 0.2, 0, 1, 1, 0
0.7, 0.2, 0, 1, 0, 1
0.45, 0.7, 0, 0, 1, 16. 立方体 示例输入文件格式 (input.txt)
# 定义变量
size = 0.5
red = 1.0
green = 1.0
blue = 1.0# 顶点数据(位置xyz + 颜色rgb)# 前面(红色)
-size, -size, size, red, 0, 0
size, -size, size, red, 0, 0
size, size, size, red, 0, 0
size, size, size, red, 0, 0
-size, size, size, red, 0, 0
-size, -size, size, red, 0, 0# 后面(绿色)
-size, -size, -size, 0, green, 0
size, -size, -size, 0, green, 0
size, size, -size, 0, green, 0
size, size, -size, 0, green, 0
-size, size, -size, 0, green, 0
-size, -size, -size, 0, green, 0# 左面(蓝色)
-size, -size, size, 0, 0, blue
-size, size, size, 0, 0, blue
-size, size, -size, 0, 0, blue
-size, size, -size, 0, 0, blue
-size, -size, -size, 0, 0, blue
-size, -size, size, 0, 0, blue# 右面(黄色:红+绿)
size, -size, size, red, green, 0
size, size, size, red, green, 0
size, size, -size, red, green, 0
size, size, -size, red, green, 0
size, -size, -size, red, green, 0
size, -size, size, red, green, 0# 顶面(品红:红+蓝)
-size, size, size, red, 0, blue
size, size, size, red, 0, blue
size, size, -size, red, 0, blue
size, size, -size, red, 0, blue
-size, size, -size, red, 0, blue
-size, size, size, red, 0, blue# 底面(青色:绿+蓝)
-size, -size, size, 0, green, blue
size, -size, size, 0, green, blue
size, -size, -size, 0, green, blue
size, -size, -size, 0, green, blue
-size, -size, -size, 0, green, blue
-size, -size, size, 0, green, blue7. 钻石形 示例输入文件格式 (input.txt)# 定义变量
radius = 0.8
red = 1.0
green = 0.5
blue = sin(3.14159/2)# 顶点数据(位置xyz + 颜色rgb)
# -------------------------------
# 顶部顶点 (北极点,红色渐变)
0, 0, radius, red, 0, 0# 赤道顶点 (动态颜色混合)
radius, 0, 0, 0, green, 0
0, radius, 0, red, green, 0
-radius, 0, 0, 0, green, blue
0, -radius, 0, red, 0, blue# 底部顶点 (南极点,蓝色渐变)
0, 0, -radius, 0, 0, blue# -------------------------------
# 三角形面数据(每个面3个顶点)
# 上半球
0, 0, radius, radius, 0, 0, 0, radius, 0, 0, green, 0
0, 0, radius, 0, radius, 0, -radius, 0, 0, 0, green, blue
0, 0, radius, -radius, 0, 0, 0, -radius, 0, red, 0, blue
0, 0, radius, 0, -radius, 0, radius, 0, 0, 0, green, 0# 下半球
0, 0, -radius, radius, 0, 0, 0, radius, 0, 0, green, 0
0, 0, -radius, 0, radius, 0, -radius, 0, 0, 0, green, blue
0, 0, -radius, -radius, 0, 0, 0, -radius, 0, red, 0, blue
0, 0, -radius, 0, -radius, 0, radius, 0, 0, 0, green, 0

step102:

 using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using System.Drawing;
using NCalc;
using Silk.NET.GLFW;
using Silk.NET.OpenGL;
using System.Runtime.InteropServices;namespace WinFormsApp8
{public unsafe partial class Form1 : Form{// OpenGL相关成员private GL gl;private Glfw glfw;private WindowHandle* glfwWindow;private System.Windows.Forms.Panel glPanel;private uint shaderProgram;private uint vao;private uint vbo;// 数据相关成员private readonly Dictionary<string, double> variables = new Dictionary<string, double>();private readonly List<float> verticesData = new List<float>();private DateTime _startTime = DateTime.Now;// Win32 API[DllImport("user32.dll")]private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);[DllImport("user32.dll")]private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter,int X, int Y, int cx, int cy, SetWindowPosFlags uFlags);[DllImport("glfw3.dll", CallingConvention = CallingConvention.Cdecl)]private static extern IntPtr glfwGetWin32Window(WindowHandle* window);// 使用逐字字符串(@)避免转义反斜杠private string absolutePath = @"C:\Users\wangrusheng\PycharmProjects\FastAPIProject1\input.txt";[Flags]private enum SetWindowPosFlags : uint{FrameChanged = 0x0020}public Form1(){InitializeComponent();InitializeOpenGLPanel();this.Load += Form1_Load;this.Resize += Form1_Resize;}private void Form1_Load(object? sender, EventArgs e){try{SetupGLFWWindow();InitializeOpenGL();ProcessInputFile(absolutePath);SetupGeometry();StartRenderTimer();}catch (Exception ex){MessageBox.Show($"初始化失败: {ex.Message}");Close();}}private void InitializeOpenGLPanel(){glPanel = new Panel{Dock = DockStyle.Fill,BackColor = Color.Black};Controls.Add(glPanel);}private void SetupGLFWWindow(){glfw = Glfw.GetApi();glfw.Init();glfw.WindowHint(WindowHintInt.ContextVersionMajor, 3);glfw.WindowHint(WindowHintInt.ContextVersionMinor, 3);glfw.WindowHint(WindowHintOpenGlProfile.OpenGlProfile, OpenGlProfile.Core);glfw.WindowHint(WindowHintBool.Decorated, false);unsafe{glfwWindow = glfw.CreateWindow(glPanel.Width, glPanel.Height, "GLFW", null, null);glfw.ShowWindow(glfwWindow);var hwnd = glfwGetWin32Window(glfwWindow);SetParent(hwnd, glPanel.Handle);SetWindowPos(hwnd, IntPtr.Zero, 0, 0,glPanel.Width, glPanel.Height, SetWindowPosFlags.FrameChanged);glfw.MakeContextCurrent(glfwWindow);glfw.SwapInterval(1); }}private void InitializeOpenGL(){gl = GL.GetApi(glfw.GetProcAddress);gl.Viewport(0, 0, (uint)glPanel.Width, (uint)glPanel.Height);gl.Enable(EnableCap.DepthTest);// 着色器程序const string vertexShaderSource = @"#version 330 corelayout (location = 0) in vec3 aPos;layout (location = 1) in vec3 aColor;out vec3 ourColor;uniform float time;void main(){mat4 rotate = mat4(cos(time), 0.0, sin(time), 0.0,0.0, 1.0, 0.0, 0.0,-sin(time), 0.0, cos(time), 0.0,0.0, 0.0, 0.0, 1.0);gl_Position = rotate * vec4(aPos, 1.0);ourColor = aColor;}";const string fragmentShaderSource = @"#version 330 corein vec3 ourColor;out vec4 FragColor;void main(){FragColor = vec4(ourColor, 1.0);}";uint vertexShader = gl.CreateShader(ShaderType.VertexShader);gl.ShaderSource(vertexShader, vertexShaderSource);gl.CompileShader(vertexShader);uint fragmentShader = gl.CreateShader(ShaderType.FragmentShader);gl.ShaderSource(fragmentShader, fragmentShaderSource);gl.CompileShader(fragmentShader);shaderProgram = gl.CreateProgram();gl.AttachShader(shaderProgram, vertexShader);gl.AttachShader(shaderProgram, fragmentShader);gl.LinkProgram(shaderProgram);gl.DeleteShader(vertexShader);gl.DeleteShader(fragmentShader);}private void ProcessInputFile(string path){if (!File.Exists(path))throw new FileNotFoundException("找不到输入文件", path);variables.Clear();verticesData.Clear();foreach (var line in File.ReadLines(path)){var trimmed = line.Trim();if (string.IsNullOrEmpty(trimmed) || trimmed.StartsWith("#"))continue;ProcessLine(trimmed);}if (verticesData.Count % 6 != 0)throw new InvalidDataException("顶点数据格式不正确,应为每行6个浮点数");}private void ProcessLine(string line){try{if (line.Contains("=")) // 变量赋值{var parts = line.Split(new[] { '=' }, 2);var varName = parts[0].Trim();var expr = parts[1].Trim();variables[varName] = EvaluateExpression(expr);}else // 顶点数据{var values = line.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);foreach (var value in values){var result = EvaluateExpression(value.Trim());verticesData.Add((float)result);}}}catch (Exception ex){throw new InvalidDataException($"处理行时出错: {line}\n错误信息: {ex.Message}");}}private double EvaluateExpression(string expr){var e = new Expression(expr, EvaluateOptions.IgnoreCase);// 转换字典类型:Dictionary<string, double> → Dictionary<string, object>var paramDict = variables.ToDictionary(kvp => kvp.Key, kvp => (object)kvp.Value // 添加显式类型转换);e.Parameters = paramDict;e.EvaluateFunction += (name, args) =>{// 示例:支持sin函数if (name.Equals("sin", StringComparison.OrdinalIgnoreCase)){args.Result = Math.Sin(Convert.ToDouble(args.Parameters[0].Evaluate()));}};var result = e.Evaluate();return Convert.ToDouble(result);}private void SetupGeometry(){vao = gl.GenVertexArray();vbo = gl.GenBuffer();gl.BindVertexArray(vao);gl.BindBuffer(BufferTargetARB.ArrayBuffer, vbo);var vertices = verticesData.ToArray();unsafe{fixed (float* ptr = vertices){gl.BufferData(BufferTargetARB.ArrayBuffer,(nuint)(vertices.Length * sizeof(float)),ptr, BufferUsageARB.StaticDraw);}}gl.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 6 * sizeof(float), (void*)0);gl.EnableVertexAttribArray(0);gl.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 6 * sizeof(float), (void*)(3 * sizeof(float)));gl.EnableVertexAttribArray(1);}private void StartRenderTimer(){var timer = new System.Windows.Forms.Timer { Interval = 16 };timer.Tick += (s, e) => Render();timer.Start();}private void SetupTriangle(){float[] vertices = {-0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, // 左下 - 红色0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, // 右下 - 绿色0.0f,  0.5f, 0.0f, 0.0f, 0.0f, 1.0f  // 顶部 - 蓝色};// 创建VAO/VBOvao = gl.GenVertexArray();vbo = gl.GenBuffer();gl.BindVertexArray(vao);gl.BindBuffer(BufferTargetARB.ArrayBuffer, vbo);fixed (float* ptr = vertices){gl.BufferData(BufferTargetARB.ArrayBuffer,(nuint)(vertices.Length * sizeof(float)),ptr, BufferUsageARB.StaticDraw);}// 位置属性gl.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 6 * sizeof(float), (void*)0);gl.EnableVertexAttribArray(0);// 颜色属性gl.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 6 * sizeof(float), (void*)(3 * sizeof(float)));gl.EnableVertexAttribArray(1);}private void SetupCube(){float[] vertices = {// 前面(红色)-0.5f, -0.5f,  0.5f, 1.0f, 0.0f, 0.0f,0.5f, -0.5f,  0.5f, 1.0f, 0.0f, 0.0f,0.5f,  0.5f,  0.5f, 1.0f, 0.0f, 0.0f,0.5f,  0.5f,  0.5f, 1.0f, 0.0f, 0.0f,-0.5f,  0.5f,  0.5f, 1.0f, 0.0f, 0.0f,-0.5f, -0.5f,  0.5f, 1.0f, 0.0f, 0.0f,// 后面(绿色)-0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.0f,0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.0f,0.5f,  0.5f, -0.5f, 0.0f, 1.0f, 0.0f,0.5f,  0.5f, -0.5f, 0.0f, 1.0f, 0.0f,-0.5f,  0.5f, -0.5f, 0.0f, 1.0f, 0.0f,-0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.0f,// 左面(蓝色)-0.5f,  0.5f,  0.5f, 0.0f, 0.0f, 1.0f,-0.5f,  0.5f, -0.5f, 0.0f, 0.0f, 1.0f,-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f,-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f,-0.5f, -0.5f,  0.5f, 0.0f, 0.0f, 1.0f,-0.5f,  0.5f,  0.5f, 0.0f, 0.0f, 1.0f,// 右面(黄色)0.5f,  0.5f,  0.5f, 1.0f, 1.0f, 0.0f,0.5f,  0.5f, -0.5f, 1.0f, 1.0f, 0.0f,0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.0f,0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.0f,0.5f, -0.5f,  0.5f, 1.0f, 1.0f, 0.0f,0.5f,  0.5f,  0.5f, 1.0f, 1.0f, 0.0f,// 顶面(品红)-0.5f,  0.5f, -0.5f, 1.0f, 0.0f, 1.0f,0.5f,  0.5f, -0.5f, 1.0f, 0.0f, 1.0f,0.5f,  0.5f,  0.5f, 1.0f, 0.0f, 1.0f,0.5f,  0.5f,  0.5f, 1.0f, 0.0f, 1.0f,-0.5f,  0.5f,  0.5f, 1.0f, 0.0f, 1.0f,-0.5f,  0.5f, -0.5f, 1.0f, 0.0f, 1.0f,// 底面(青色)-0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 1.0f,0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 1.0f,0.5f, -0.5f,  0.5f, 0.0f, 1.0f, 1.0f,0.5f, -0.5f,  0.5f, 0.0f, 1.0f, 1.0f,-0.5f, -0.5f,  0.5f, 0.0f, 1.0f, 1.0f,-0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 1.0f};vao = gl.GenVertexArray();vbo = gl.GenBuffer();gl.BindVertexArray(vao);gl.BindBuffer(BufferTargetARB.ArrayBuffer, vbo);fixed (float* ptr = vertices){gl.BufferData(BufferTargetARB.ArrayBuffer,(nuint)(vertices.Length * sizeof(float)),ptr, BufferUsageARB.StaticDraw);}gl.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 6 * sizeof(float), (void*)0);gl.EnableVertexAttribArray(0);gl.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 6 * sizeof(float), (void*)(3 * sizeof(float)));gl.EnableVertexAttribArray(1);}private void Render(){if (gl == null) return;gl.ClearColor(0.2f, 0.3f, 0.3f, 1.0f);gl.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);gl.UseProgram(shaderProgram);float time = (float)(DateTime.Now - _startTime).TotalSeconds;gl.Uniform1(gl.GetUniformLocation(shaderProgram, "time"), time);gl.BindVertexArray(vao);gl.DrawArrays(PrimitiveType.Triangles, 0, (uint)(verticesData.Count / 6));unsafe{glfw.SwapBuffers(glfwWindow);}glfw.PollEvents();}protected override void OnResize(EventArgs e){base.OnResize(e);if (glfwWindow != null && glPanel != null){glfw.SetWindowSize(glfwWindow, glPanel.Width, glPanel.Height);nint hwnd = glfwGetWin32Window(glfwWindow);SetWindowPos(hwnd, IntPtr.Zero, 0, 0,glPanel.Width, glPanel.Height, SetWindowPosFlags.FrameChanged);gl?.Viewport(0, 0, (uint)glPanel.Width, (uint)glPanel.Height);}}#region 窗口事件处理private void Form1_Resize(object? sender, EventArgs e){if (glfwWindow == null || glPanel == null) return;glfw.SetWindowSize(glfwWindow, glPanel.Width, glPanel.Height);var hwnd = glfwGetWin32Window(glfwWindow);SetWindowPos(hwnd, IntPtr.Zero, 0, 0,glPanel.Width, glPanel.Height, SetWindowPosFlags.FrameChanged);gl?.Viewport(0, 0, (uint)glPanel.Width, (uint)glPanel.Height);}protected override void OnFormClosing(FormClosingEventArgs e){base.OnFormClosing(e);if (gl != null){gl.DeleteBuffer(vbo);gl.DeleteVertexArray(vao);gl.DeleteProgram(shaderProgram);}glfw?.Terminate();}#endregion}}

我是分割线
我希望用python生成 人体3d图
step201:

import math
import argparsedef generate_triangle(size=0.5, color=(1.0, 0.0, 0.0)):"""生成三角形顶点数据"""return [(-size, -size, 0.0, *color),(size, -size, 0.0, *color),(0.0, size, 0.0, *color)]def generate_cuboid(width, height, depth, color):"""生成长方体顶点数据(单一颜色)"""vertices = []w, h, d = width / 2, height / 2, depth / 2# 前面 (z = d)vertices.extend([(-w, -h, d, *color), (w, -h, d, *color), (w, h, d, *color)])vertices.extend([(w, h, d, *color), (-w, h, d, *color), (-w, -h, d, *color)])# 后面 (z = -d)vertices.extend([(-w, -h, -d, *color), (w, -h, -d, *color), (w, h, -d, *color)])vertices.extend([(w, h, -d, *color), (-w, h, -d, *color), (-w, -h, -d, *color)])# 左面 (x = -w)vertices.extend([(-w, -h, -d, *color), (-w, -h, d, *color), (-w, h, d, *color)])vertices.extend([(-w, h, d, *color), (-w, h, -d, *color), (-w, -h, -d, *color)])# 右面 (x = w)vertices.extend([(w, -h, -d, *color), (w, -h, d, *color), (w, h, d, *color)])vertices.extend([(w, h, d, *color), (w, h, -d, *color), (w, -h, -d, *color)])# 顶面 (y = h)vertices.extend([(-w, h, -d, *color), (w, h, -d, *color), (w, h, d, *color)])vertices.extend([(w, h, d, *color), (-w, h, d, *color), (-w, h, -d, *color)])# 底面 (y = -h)vertices.extend([(-w, -h, -d, *color), (w, -h, -d, *color), (w, -h, d, *color)])vertices.extend([(w, -h, d, *color), (-w, -h, d, *color), (-w, -h, -d, *color)])return verticesdef generate_sphere(radius=0.5,rings=16,sectors=32,color_top=(1.0, 0.0, 0.0),color_bottom=(0.0, 0.0, 1.0)
):"""生成球体顶点数据"""vertices = []for i in range(rings + 1):phi = math.pi * i / ringsfor j in range(sectors + 1):theta = 2 * math.pi * j / sectorsx = radius * math.sin(phi) * math.cos(theta)y = radius * math.cos(phi)z = radius * math.sin(phi) * math.sin(theta)t = i / ringsr = color_top[0] * (1 - t) + color_bottom[0] * tg = color_top[1] * (1 - t) + color_bottom[1] * tb = color_top[2] * (1 - t) + color_bottom[2] * tvertices.append((x, y, z, r, g, b))indices = []for i in range(rings):for j in range(sectors):a = i * (sectors + 1) + jb = a + 1c = (i + 1) * (sectors + 1) + jd = c + 1indices.extend([a, c, b, b, c, d])return [vertices[i] for i in indices]def generate_human(torso_size=(0.3, 0.5, 0.2),head_radius=0.2,arm_length=0.4,arm_thickness=0.1,leg_length=0.6,leg_thickness=0.15,torso_color=(0.5, 0.5, 0.5),head_color=(1.0, 0.8, 0.6),arm_color=(0.0, 0.0, 1.0),leg_color=(0.0, 0.0, 1.0)
):"""生成人体模型顶点数据"""vertices = []torso_w, torso_h, torso_d = torso_size# 躯干torso = generate_cuboid(torso_w, torso_h, torso_d, torso_color)vertices.extend(torso)# 头部head = generate_sphere(radius=head_radius,rings=10,sectors=20,color_top=head_color,color_bottom=head_color)head = [(x, y + torso_h / 2 + head_radius, z, *c) for x, y, z, *c in head]vertices.extend(head)# 手臂arm_w, arm_h, arm_d = arm_thickness, arm_length, arm_thickness# 左臂left_arm = generate_cuboid(arm_w, arm_h, arm_d, arm_color)left_arm = [(x - torso_w / 2 - arm_w / 2, y, z, *c) for x, y, z, *c in left_arm]vertices.extend(left_arm)# 右臂right_arm = generate_cuboid(arm_w, arm_h, arm_d, arm_color)right_arm = [(x + torso_w / 2 + arm_w / 2, y, z, *c) for x, y, z, *c in right_arm]vertices.extend(right_arm)# 腿部leg_w, leg_h, leg_d = leg_thickness, leg_length, leg_thickness# 左腿left_leg = generate_cuboid(leg_w, leg_h, leg_d, leg_color)left_leg = [(x - torso_w / 4, y - torso_h / 2 - leg_h / 2, z, *c) for x, y, z, *c in left_leg]vertices.extend(left_leg)# 右腿right_leg = generate_cuboid(leg_w, leg_h, leg_d, leg_color)right_leg = [(x + torso_w / 4, y - torso_h / 2 - leg_h / 2, z, *c) for x, y, z, *c in right_leg]vertices.extend(right_leg)return verticesdef save_to_file(filename, vertices):with open(filename, 'w') as f:for v in vertices:line = ", ".join(f"{x:.4f}" if isinstance(x, float) else str(x) for x in v)f.write(line + "\n")if __name__ == "__main__":parser = argparse.ArgumentParser(description="生成3D形状顶点数据")parser.add_argument("shape", choices=["triangle", "cube", "sphere", "human"])parser.add_argument("-o", "--output", default="output.txt")# 通用参数parser.add_argument("--size", type=float, default=0.5)parser.add_argument("--color", nargs=3, type=float)# 球体参数parser.add_argument("--rings", type=int, default=16)parser.add_argument("--sectors", type=int, default=32)parser.add_argument("--color-top", nargs=3, type=float, default=[1, 0, 0])parser.add_argument("--color-bottom", nargs=3, type=float, default=[0, 0, 1])# 人体参数parser.add_argument("--torso-size", nargs=3, type=float, default=[0.3, 0.5, 0.2])parser.add_argument("--head-radius", type=float, default=0.2)parser.add_argument("--arm-length", type=float, default=0.4)parser.add_argument("--arm-thickness", type=float, default=0.1)parser.add_argument("--leg-length", type=float, default=0.6)parser.add_argument("--leg-thickness", type=float, default=0.15)parser.add_argument("--torso-color", nargs=3, type=float, default=[0.5, 0.5, 0.5])parser.add_argument("--head-color", nargs=3, type=float, default=[1.0, 0.8, 0.6])parser.add_argument("--arm-color", nargs=3, type=float, default=[0, 0, 1])parser.add_argument("--leg-color", nargs=3, type=float, default=[0, 0, 1])args = parser.parse_args()# 生成顶点数据if args.shape == "triangle":vertices = generate_triangle(args.size, args.color or (1, 0, 0))elif args.shape == "cube":vertices = generate_cuboid(args.size, args.size, args.size, args.color or (1, 0, 0))elif args.shape == "sphere":vertices = generate_sphere(radius=args.size,rings=args.rings,sectors=args.sectors,color_top=args.color_top,color_bottom=args.color_bottom)elif args.shape == "human":vertices = generate_human(torso_size=args.torso_size,head_radius=args.head_radius,arm_length=args.arm_length,arm_thickness=args.arm_thickness,leg_length=args.leg_length,leg_thickness=args.leg_thickness,torso_color=args.torso_color,head_color=args.head_color,arm_color=args.arm_color,leg_color=args.leg_color)save_to_file(args.output, vertices)print(f"已生成 {len(vertices)} 个顶点到 {args.output}")

step202:新建文件 C:\Users\wangrusheng\PycharmProjects\FastAPIProject1\run_script.bat

@echo off
python generate_shape.py human --torso-size 0.25 0.6 0.15 --head-radius 0.18 --arm-length 0.35 --arm-thickness 0.08 --leg-length 0.7 --leg-thickness 0.12 --torso-color 0.7 0.7 0.7 --head-color 1.0 0.9 0.7 --arm-color 0.2 0.2 1.0 --leg-color 0.2 0.2 1.0 -o custom_human.txt
pause

或者使用默认数据也行

(.venv) PS C:\Users\wangrusheng\PycharmProjects\FastAPIProject1> python generate_shape.py human -o human.txt
已生成 1380 个顶点到 human.txt

end

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/75521.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android Gradle、Android Gradle Plugin、BuildTool关系

1. Gradle 的定位&#xff1a;通用构建工具 Gradle 是一个通用的跨平台构建工具&#xff0c;支持多种语言&#xff08;如 Java、Kotlin、C&#xff09;和项目类型 它的核心功能包括&#xff1a; ​任务自动化&#xff1a;通过 Groovy/Kotlin DSL 脚本定义编译、测试、打包等…

DHCP之报文格式

字段说明&#xff1a; op (op code): 表示报文的类型&#xff0c;取值为 1 或 2&#xff0c;含义如下 1:客户端请求报 2:服务器响应报文 Secs (seconds):由客户端填充&#xff0c;表示从客户端开始获得 IP 地址或 IP 地址续借后所使用了的秒数&#xff0c;缺省值为 3600s。 F…

观察者模式在Java微服务间的使用

一.、使用RabbitMQ来实现 (1) 生产者&#xff08;订单微服务&#xff09; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.stereotype.Service;Service public class OrderService {private final RabbitTemplate rabbitTemplate;…

OSPF五种数据包详解

一、OSPF头部封装 OSPF是跨四层封装协议&#xff0c;直接封装在网络层之上&#xff0c;需要IP协议使用一个协议号来标定——89。 OSPF头部结构&#xff1a; 版本&#xff1a;标识OSPF的版本&#xff0c;OSPFv2&#xff08;2&#xff09;、OSPFv3&#xff08;3&#xff09;&am…

NO.64十六届蓝桥杯备战|基础算法-简单贪心|货仓选址|最大子段和|纪念品分组|排座椅|矩阵消除(C++)

贪⼼算法是两极分化很严重的算法。简单的问题会让你觉得理所应当&#xff0c;难⼀点的问题会让你怀疑⼈⽣ 什么是贪⼼算法&#xff1f; 贪⼼算法&#xff0c;或者说是贪⼼策略&#xff1a;企图⽤局部最优找出全局最优。 把解决问题的过程分成若⼲步&#xff1b;解决每⼀步时…

Linux(十二)信号

今天我们就要来一起学习信号啦&#xff01;&#xff01;&#xff01;还记得小编在之前的文章中说过的ctrlc吗&#xff1f;之前小编没有详细介绍过&#xff0c;现在我们就要来学习啦&#xff01;&#xff01;&#xff01; 一、信号的基本介绍 首先&#xff0c;小编带领大家先一…

Dify开发实战-自制插件 和安装python3最新版本 记录版本 后续会持续更新

自定义插件 Dify 插件脚手架工具Python 环境&#xff0c;版本号 ≥ 3.12 安装Python 一 进入官网 https://www.python.org/downloads/windows/ 点击下载 二、安装python&#xff08;本文中有借鉴其他图片 所以图片展示python版本可能不一致 请忽略&#xff09; 1.双击打开py…

Docker安装、配置Redis

1.如果没有docker-compose.yml文件的话&#xff0c;先创建docker-compose.yml 配置文件一般长这个样子 version: 3services:redis:image: redis:latestcontainer_name: redisports:- "6379:6379"command: redis-server --requirepass "123456"restart: a…

Parasoft C++Test软件单元测试_操作指南

系列文章目录 Parasoft C++Test软件静态分析:操作指南(编码规范、质量度量)、常见问题及处理 Parasoft C++Test软件单元测试:操作指南、实例讲解、常见问题及处理 Parasoft C++Test软件集成测试:操作指南、实例讲解、常见问题及处理 进阶扩展:自动生成静态分析文档、自动…

二级索引详解

二级索引详解 二级索引(Secondary Index)是数据库系统中除主键索引外的附加索引结构,用于加速基于非主键列的查询操作。以下是关于二级索引的全面解析: 一、核心概念 特性主键索引 (Primary Index)二级索引 (Secondary Index)唯一性必须唯一可以唯一或非唯一数量每表只有…

Python_level1_字符串_11

目录 一、基本概念 二、字符串基本操作&#xff1a;【索引、切片、遍历】 1.字符串与列表&#xff08;相同&#xff09; 1&#xff09;索引&#xff08;从0开始&#xff09;(可以获取某一个/某几个连续的字符) 2&#xff09;切片 [xx:xx] 与 列表 语法规则一样 [起…

Axure数据可视化科技感大屏设计资料——赋能多领域,展示无限价值

可视化大屏如何高效、直观地展示数据&#xff0c;并将其转化为有价值的决策依据&#xff0c;成为了许多企业和组织面临的共同挑战。Axure大屏可视化模板&#xff0c;作为一款强大的数据展示工具&#xff0c;正在以其出色的交互性和可定制性&#xff0c;赋能多个领域&#xff0c…

MySQL 性能调优:数据库的极限运动训练

就像运动员需要不断训练才能突破极限&#xff0c;数据库也需要各种调优才能跑得更快…让我们一起给 MySQL 安排一套专业的"健身计划"&#xff01; 什么是 MySQL 性能调优&#xff1f;&#x1f914; MySQL 性能调优是指通过各种配置优化、结构调整和查询改进&#x…

4.5/Q1,GBD数据库最新文章解读

文章题目&#xff1a;Emerging trends and cross-country health inequalities in congenital birth defects: insights from the GBD 2021 study DOI&#xff1a;10.1186/s12939-025-02412-7 中文标题&#xff1a;先天性出生缺陷的新趋势和跨国健康不平等&#xff1a;GBD 202…

基于DeepSeek、ChatGPT支持下的地质灾害风险评估、易发性分析、信息化建库及灾后重建

前言&#xff1a; 地质灾害是指全球地壳自然地质演化过程中&#xff0c;由于地球内动力、外动力或者人为地质动力作用下导致的自然地质和人类的自然灾害突发事件。在降水、地震等自然诱因的作用下&#xff0c;地质灾害在全球范围内频繁发生。我国不仅常见滑坡灾害&#xff0c;还…

Linux | 安装超级终端串口软件连接i.MX6ULL开发板(8)

01 它的安装步骤也非常简单,安装语言选择中文简体,点击确定,如下图所示。 点击下一步,如下图所示。 02

蓝桥杯15届 宝石组合

问题描述 在一个神秘的森林里&#xff0c;住着一个小精灵名叫小蓝。有一天&#xff0c;他偶然发现了一个隐藏在树洞里的宝藏&#xff0c;里面装满了闪烁着美丽光芒的宝石。这些宝石都有着不同的颜色和形状&#xff0c;但最引人注目的是它们各自独特的 “闪亮度” 属性。每颗宝…

Lua:第1-4部分 语言基础

1 Lua语言入门 1.1 程序段 我们将 Lua 语言执行的每一段代码&#xff08;例如&#xff0c;一个文件或交互模式下的一行&#xff09;称为一个程序段 &#xff08; Chunk &#xff09; &#xff0c;即一组命令或表达式组成的序列 。 1.2 一些词法规范 Lua 语言中的标识符&#…

CTF类题目复现总结-hashcat 1

一、题目地址 https://buuoj.cn/challenges#hashcat二、复现步骤 1、下载附件&#xff0c;解压得到What kind of document is this_文件&#xff1b; 2、用010 Editor打开What kind of document is this_文件&#xff0c;发现是office文件&#xff1b; 3、将后缀名改为ppt时…

手机归属地查询Api接口,数据准确可靠

手机归属地查询是一项非常实用的功能&#xff0c;它可以帮助我们快速了解一个手机号码的所属地区、区号、邮政编码等信息。在互联网时代&#xff0c;随着大数据和人工智能技术的发展&#xff0c;手机归属地查询的API接口也变得越来越普及和便捷。 在本文中&#xff0c;我们将介…