STL Collection Types

本文介绍了标准模板库(STL)中的各种容器类型及其应用场景,包括vector、map、deque等,并详细阐述了STL字符串的功能和支持的字符类型,以及如何使用这些容器来提升程序效率。
 

STL Collection Types

Each STL collection type has its own template parameters, which will be discussed later. What type of collection you use is up to your needs and tastes. From past experience, the vector and map classes are the most useful. The vector class is ideal for simple and complex collection types, while the map class is used when an associative type of collection is needed. The deque collection is excellent for use in systems that have queued based processing, such as a message based system.

vector
A collection of elements of type T.
list
A collection of elements of type T. The collection is stored as a bi-directional linked list of elements, each containing a member of type T.

To include the class definition use:

#include <list>
deque
A collection of varying length of elements of type T. The sequence is represented in a way that permits insertion and removal of an element at either end with a single element copy, and supports insertion and removal anywhere in the sequence, but a sequence copy follows each operation.

To include the class definition use:

#include <deque>
map
A collection for a varying length sequence of elements of type pair<const Key, T>. The first element of each pair is the sort key and the second is its associated value. The sequence is represented in a way that permits lookup, insertion, and removal of an arbitrary element. The key can be a simple as a number or string or as complex a key class. The key class must support normal comparison operations so that the collection can be sorted or searched.

To include the class definition use:

#include <map>
set
A collection that controls a varying length sequence of elements of type const Key. Each element serves as both a sort key and a value. The sequence is represented in a way that permits lookup, insertion, and removal of an arbitrary element.

To include the class definition use:

#include <set>
multimap
A collection of a varying length sequence of elements of type pair<const Key, T>. The first element of each pair is the sort key and the second is its associated value. The sequence is represented in a way that permits lookup, insertion, and removal of an arbitrary element.

To include the class definition use:

#include <map>
multiset
A collection of a varying-length sequence of elements of type const Key. Each element serves as both a sort key and a value. The sequence is represented in a way that permits lookup, insertion, and removal of an arbitrary element.

To include the class definition use:

#include <set>

STL Strings

STL strings support both ascii and unicode character strings.

string
A string is a collection of ascii characters that supports both insertion and removal.

To include the string class definitions use:

#include <string>
wstring
A wstring is a collection of wide characters that it supports both insertion and removal. In MFC the string class is CString, which provides a Format and other methods to manipulate the string. CString has the advantage of providing methods such as Format, TrimLeft, TrimRight and LoadString. It is easy to provide a string-based class that contains these methods.

To include the wstring class definitions use:

#include <xstring>

STL Streams

Streams provide the developer with classes that can output to a container variable types of stream elements.

stringstream
A string stream that supports insertions of elements, and elements are inserted via the overloaded operator <<. The method str() gives a reference back to the underlying string, and the c_str() can be used to get a constant pointer to the string buffer.
wstringstream
A wstring stream that supports insertions of elements, and elements are inserted via the overloaded operator <<. The method str() gives a reference back to the underlying string, and the c_str() can be used to get a constant pointer to the string buffer.

To use a string stream we would do the follwing:

stringstream strStr;
for ( long i=0; i< 10; i++ )
strStr << "Element " << i << endl;

To include the string class definitions use:

#include <strstring>
# worm_gear_v2.py import numpy as np import matplotlib.pyplot as plt from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg import tkinter as tk from tkinter import ttk, messagebox import math from mpl_toolkits.mplot3d.art3d import Poly3DCollection import stl.mesh as stlmesh # pip install numpy-stl import time # 用于性能测量 # -------------------- 参数类 -------------------- class WormParams: def __init__(self, module=2.0, teeth=2, length=50.0, pressure_angle=20.0, helix_angle=5.0, backlash=0.1, root_factor=1.0): self.module = module self.teeth = int(teeth) self.length = length self.pressure_angle = np.radians(pressure_angle) self.helix_angle = np.radians(helix_angle) self.backlash = backlash self.root_factor = root_factor self._derive() def _derive(self): """计算蜗杆的派生参数""" self.pitch_radius = self.module * self.teeth / 2 self.addendum = self.module self.dedendum = 1.25 * self.module * self.root_factor self.base_radius = self.pitch_radius * np.cos(self.pressure_angle) self.lead = 2 * np.pi * self.pitch_radius / np.tan(self.helix_angle) self.root_radius = self.pitch_radius - self.dedendum self.tip_radius = self.pitch_radius + self.addendum # 根据复杂度动态调整分辨率 complexity = max(1, min(5, int(50 / self.module))) self.axial_res = 50 * complexity self.circum_res = 60 * complexity self.tooth_res = 50 * complexity def validate(self): """验证参数的有效性""" self.module = np.clip(self.module, 0.5, 10) self.teeth = int(np.clip(self.teeth, 1, 8)) self.pressure_angle = np.radians( np.clip(np.degrees(self.pressure_angle), 5, 35)) self.helix_angle = np.radians( np.clip(np.degrees(self.helix_angle), 2, 20)) self.root_factor = np.clip(self.root_factor, 0.6, 1.4) self._derive() if self.base_radius > self.tip_radius: self.pressure_angle = np.radians(20) self._derive() # -------------------- 几何生成 -------------------- def _involute(rb, r_end, n, side=1): """生成渐开线曲线""" t_max = np.sqrt((r_end / rb) ** 2 - 1) t = np.linspace(0, t_max, n) x = rb * (np.cos(side * t) + t * np.sin(side * t)) y = rb * (np.sin(side * t) - t * np.cos(side * t)) return np.column_stack((x, y)) def generate_tooth_profile(p, n_points): """生成齿形轮廓""" rb, ra, rf = p.base_radius, p.tip_radius, p.root_radius # 生成右侧和左侧渐开线 prof_r = _involute(rb, ra, n_points // 2, 1) prof_l = _involute(rb, ra, n_points // 2, -1)[::-1] # 齿根弧 ang = np.linspace(-np.pi / 2 + p.pressure_angle, np.pi / 2 - p.pressure_angle, n_points // 3) root = np.column_stack((rf * np.cos(ang), rf * np.sin(ang))) # 齿顶弧 ang = np.linspace(np.pi / 2 + p.pressure_angle, 3 * np.pi / 2 - p.pressure_angle, n_points // 3) tip = np.column_stack((ra * np.cos(ang), ra * np.sin(ang))) # 组合所有部分 profile = np.vstack((prof_r, tip, prof_l, root)) # 添加齿侧间隙 if p.backlash > 0: gap = np.array([np.cos(p.pressure_angle), np.sin(p.pressure_angle)]) * p.backlash / 2 profile[:len(prof_r)] -= gap profile[len(prof_r) + len(tip):-len(root)] += gap # 确保轮廓闭合 if not np.allclose(profile[0], profile[-1]): profile = np.vstack([profile, profile[0]]) return profile def build_worm_mesh(p): """构建蜗杆网格""" try: tooth = generate_tooth_profile(p, p.tooth_res) n_prof = len(tooth) z = np.linspace(0, p.length, p.axial_res) phase = 2 * np.pi * z / p.lead tooth_offset = 2 * np.pi * np.arange(p.teeth) / p.teeth vertices = [] # 生成顶点 for i in range(p.axial_res): rot = phase[i] for j, pt in enumerate(tooth): for k, off in enumerate(tooth_offset): x = pt[0] * np.cos(rot + off) - pt[1] * np.sin(rot + off) y = pt[0] * np.sin(rot + off) + pt[1] * np.cos(rot + off) vertices.append([x, y, z[i]]) vertices = np.array(vertices) # 生成面 faces = [] nV_slice = n_prof * p.teeth for i in range(p.axial_res - 1): for j in range(n_prof - 1): for k in range(p.teeth): idx = i * nV_slice + j * p.teeth + k next_k = (k + 1) % p.teeth # 处理最后一个齿的连接 nxt = idx + nV_slice # 创建两个三角形面片 faces.append([idx, idx + p.teeth, nxt]) faces.append([idx + p.teeth, nxt + p.teeth, nxt]) # 连接齿间间隙 if j == 0: # 齿根部分 faces.append([idx, nxt, idx + nV_slice - p.teeth + k]) faces.append([nxt, nxt + nV_slice - p.teeth + k, idx + nV_slice - p.teeth + k]) return vertices, np.array(faces) except Exception as e: print(f"构建网格时出错: {e}") return np.array([]), np.array([]) def laplacian_smooth(vertices, faces, it=2, lam=0.5): """拉普拉斯平滑算法""" from collections import defaultdict # 构建邻接表 adj = defaultdict(set) for tri in faces: for i in tri: adj[i].update(tri) adj = {k: list(v) for k, v in adj.items()} # 应用平滑 V = vertices.copy() for _ in range(it): for i, nei in adj.items(): if len(nei) < 3: # 避免边缘顶点过度平滑 continue V[i] = (1 - lam) * vertices[i] + lam * np.mean(vertices[nei], axis=0) vertices = V.copy() return vertices # -------------------- GUI -------------------- class WormVisualizer: def __init__(self, master): self.master = master master.title("高精度蜗杆3D可视化 v2") master.geometry("1000x700") self.params = WormParams() self.create_widgets() self.create_3d_canvas() self.last_mesh = None self.is_rendering = False # 初始渲染 self.master.after(100, self.render_worm) def create_widgets(self): """创建GUI控件""" main_frame = ttk.Frame(self.master) main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10) # 左侧参数面板 param_frame = ttk.LabelFrame(main_frame, text="参数控制", width=250) param_frame.pack(side=tk.LEFT, fill=tk.Y, padx=(0, 10)) param_frame.pack_propagate(False) keys = [("模数", "module", 0.5, 10, 0.1), ("齿数(=头数)", "teeth", 1, 8, 1), ("长度/mm", "length", 20, 100, 1), ("压力角/°", "pressure_angle", 5, 35, 1), ("螺旋升角/°", "helix_angle", 2, 20, 1), ("齿侧间隙/mm", "backlash", 0.0, 0.5, 0.01), ("齿根圆系数", "root_factor", 0.6, 1.4, 0.05)] self.vars = {} self.labels = {} for r, (lab, k, lo, hi, res) in enumerate(keys): frame = ttk.Frame(param_frame) frame.pack(fill=tk.X, pady=2) ttk.Label(frame, text=lab, width=12).pack(side=tk.LEFT) var = tk.DoubleVar(value=getattr(self.params, k)) spin = ttk.Spinbox(frame, from_=lo, to=hi, increment=res, textvariable=var, width=8, command=lambda k=k: self.param_changed(k)) spin.pack(side=tk.RIGHT) # 显示当前值 val_label = ttk.Label(frame, text=f"{var.get():.2f}", width=6) val_label.pack(side=tk.RIGHT, padx=5) self.vars[k] = var self.labels[k] = val_label # 绑定事件 var.trace_add("write", lambda *args, k=k: self.update_label(k)) # 按钮框架 btn_frame = ttk.Frame(param_frame) btn_frame.pack(fill=tk.X, pady=10) ttk.Button(btn_frame, text="重新生成", command=self.render_worm).pack(side=tk.TOP, fill=tk.X, pady=2) ttk.Button(btn_frame, text="导出 STL", command=self.export_stl).pack(side=tk.TOP, fill=tk.X, pady=2) ttk.Button(btn_frame, text="重置参数", command=self.reset_params).pack(side=tk.TOP, fill=tk.X, pady=2) # 状态栏 self.status_var = tk.StringVar(value="就绪") status_bar = ttk.Label(param_frame, textvariable=self.status_var, relief=tk.SUNKEN) status_bar.pack(side=tk.BOTTOM, fill=tk.X, pady=(10, 0)) def create_3d_canvas(self): """创建3D画布""" # 右侧3D可视化面板 viz_frame = ttk.Frame(self.master) viz_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True) self.fig = plt.Figure(figsize=(8, 6), dpi=100) self.ax = self.fig.add_subplot(111, projection='3d') self.canvas = FigureCanvasTkAgg(self.fig, master=viz_frame) self.canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True) # 添加工具栏 toolbar_frame = ttk.Frame(viz_frame) toolbar_frame.pack(fill=tk.X) ttk.Button(toolbar_frame, text="旋转", command=self.toggle_rotation).pack(side=tk.LEFT, padx=2) ttk.Button(toolbar_frame, text="重置视图", command=self.reset_view).pack(side=tk.LEFT, padx=2) self.rotation_enabled = False self.rotation_angle = 0 def param_changed(self, param_name): """参数变化时的回调""" value = self.vars[param_name].get() setattr(self.params, param_name, value) self.params.validate() self.update_label(param_name) def update_label(self, param_name): """更新参数标签""" value = self.vars[param_name].get() if param_name in ["pressure_angle", "helix_angle"]: value = np.degrees(value) self.labels[param_name].config(text=f"{value:.2f}") def reset_params(self): """重置参数到默认值""" default_params = WormParams() for k, var in self.vars.items(): var.set(getattr(default_params, k)) self.render_worm() def toggle_rotation(self): """切换自动旋转""" self.rotation_enabled = not self.rotation_enabled if self.rotation_enabled: self.rotate_view() def rotate_view(self): """自动旋转视图""" if self.rotation_enabled: self.rotation_angle = (self.rotation_angle + 2) % 360 self.ax.view_init(elev=20, azim=self.rotation_angle) self.canvas.draw() self.master.after(50, self.rotate_view) def reset_view(self): """重置视图""" self.ax.view_init(elev=20, azim=0) self.canvas.draw() def render_worm(self): """渲染蜗杆模型""" if self.is_rendering: return self.is_rendering = True self.status_var.set("正在生成模型...") self.master.update() try: start_time = time.time() # 更新参数 for k, var in self.vars.items(): setattr(self.params, k, var.get()) self.params.validate() # 清除当前图形 self.ax.clear() # 生成网格 verts, faces = build_worm_mesh(self.params) if len(verts) == 0 or len(faces) == 0: messagebox.showerror("错误", "无法生成蜗杆模型,请检查参数") return # 应用平滑 verts = laplacian_smooth(verts, faces) self.last_mesh = (verts, faces) # 降采样以提高性能 step = max(1, len(verts) // 20000) sample_verts = verts[::step] # 绘制模型 mesh = Poly3DCollection(sample_verts[faces], alpha=0.85, linewidth=0.1) mesh.set_facecolor(plt.cm.viridis(np.linspace(0, 1, len(faces)))) mesh.set_edgecolor('gray') self.ax.add_collection3d(mesh) # 设置坐标轴范围 lim = np.array([verts[:, i].ptp() for i in range(3)]).max() / 2 cen = verts.mean(axis=0) for i in range(3): self.ax.set_xlim3d(cen[0]-lim, cen[0]+lim) self.ax.set_ylim3d(cen[1]-lim, cen[1]+lim) self.ax.set_zlim3d(cen[2]-lim, cen[2]+lim) self.ax.set_xlabel('X/mm') self.ax.set_ylabel('Y/mm') self.ax.set_zlabel('Z/mm') self.ax.set_title(f"蜗杆3D模型 (生成时间: {time.time()-start_time:.2f}秒)") self.canvas.draw() self.status_var.set(f"就绪 - 顶点: {len(verts)}, 面: {len(faces)}") except Exception as e: messagebox.showerror("错误", f"生成模型时出错: {str(e)}") self.status_var.set("错误") finally: self.is_rendering = False def export_stl(self): """导出STL文件""" if self.last_mesh is None: messagebox.showwarning("警告", "没有可导出的模型") return try: self.status_var.set("正在导出STL...") self.master.update() # 弹出文件选择对话框 from tkinter import filedialog filename = filedialog.asksaveasfilename( defaultextension=".stl", filetypes=[("STL文件", "*.stl"), ("所有文件", "*.*")], title="保存STL文件" ) if filename: export_stl(*self.last_mesh, filename) messagebox.showinfo("完成", f"已成功导出到 {filename}") self.status_var.set("STL导出完成") except Exception as e: messagebox.showerror("错误", f"导出STL时出错: {str(e)}") self.status_var.set("导出失败") # -------------------- STL 导出 -------------------- def export_stl(vertices, faces, filename="worm.stl"): """导出STL文件""" mesh = stlmesh.Mesh(np.zeros(faces.shape[0], dtype=stlmesh.Mesh.dtype)) for i, f in enumerate(faces): for j in range(3): mesh.vectors[i][j] = vertices[f[j], :] mesh.save(filename) # -------------------- main -------------------- if __name__ == "__main__": root = tk.Tk() app = WormVisualizer(root) root.mainloop()
最新发布
09-19
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值