news 2026/6/10 6:32:40

LineOnMesh 在三维网格曲面上绘制一条平滑的路径线

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LineOnMesh 在三维网格曲面上绘制一条平滑的路径线

一:主要的知识点

1、说明

本文只是教程内容的一小段,因博客字数限制,故进行拆分。主教程链接:vtk教程——逐行解析官网所有Python示例-CSDN博客

2、知识点纪要

本段代码主要涉及的有①vtkLoopSubdivisionFilter上采样,②着色,③Cell最近网格面的查询


二:代码及注释

import vtkmodules.vtkRenderingOpenGL2 from vtkmodules.vtkCommonColor import vtkNamedColors from vtkmodules.vtkCommonCore import vtkUnsignedCharArray, vtkPoints, mutable from vtkmodules.vtkCommonDataModel import vtkCellArray, vtkTriangle, vtkPolyData, vtkCellLocator from vtkmodules.vtkFiltersCore import vtkCleanPolyData from vtkmodules.vtkFiltersModeling import vtkLoopSubdivisionFilter from vtkmodules.vtkCommonComputationalGeometry import vtkParametricSpline from vtkmodules.vtkFiltersSources import vtkParametricFunctionSource import numpy as np from vtkmodules.vtkRenderingCore import vtkPolyDataMapper, vtkActor, vtkRenderer, vtkRenderWindow, \ vtkRenderWindowInteractor def main(): named_colors = vtkNamedColors() size = 32 np.random.seed(3) topography = np.random.randint(0, 5, (size, size)) colors = vtkUnsignedCharArray() colors.SetNumberOfComponents(3) points = vtkPoints() triangles = vtkCellArray() count = 0 for i in range(size - 1): for j in range(size - 1): # 第一个三角 z1 = topography[i][j] z2 = topography[i][j + 1] z3 = topography[i + 1][j] points.InsertNextPoint(i, j, z1) points.InsertNextPoint(i, j + 1, z2) points.InsertNextPoint(i + 1, j, z3) triangle = vtkTriangle() triangle.GetPointIds().SetId(0, count) triangle.GetPointIds().SetId(1, count + 1) triangle.GetPointIds().SetId(2, count + 2) triangles.InsertNextCell(triangle) # 第二个三角 z1 = topography[i][j + 1] z2 = topography[i + 1][j + 1] z3 = topography[i + 1][j] points.InsertNextPoint(i, (j + 1), z1) points.InsertNextPoint((i + 1), (j + 1), z2) points.InsertNextPoint((i + 1), j, z3) triangle = vtkTriangle() triangle.GetPointIds().SetId(0, count + 3) triangle.GetPointIds().SetId(1, count + 4) triangle.GetPointIds().SetId(2, count + 5) count += 6 triangles.InsertNextCell(triangle) r = [int(i / float(size) * 255), int(j / float(size) * 255), 0] # 这里写6次,是因为每次循环都有6个点,需要赋予颜色 colors.InsertNextTypedTuple(r) colors.InsertNextTypedTuple(r) colors.InsertNextTypedTuple(r) colors.InsertNextTypedTuple(r) colors.InsertNextTypedTuple(r) colors.InsertNextTypedTuple(r) # 创建polydata trianglePolydata = vtkPolyData() trianglePolydata.SetPoints(points) trianglePolydata.SetPolys(triangles) trianglePolydata.GetPointData().SetScalars(colors) # 去除可能的重复的点 cleanPolyData = vtkCleanPolyData() cleanPolyData.SetInputData(trianglePolydata) # 平滑 """ vtkLoopSubdivisionFilter 是 VTK 中一个非常常用的 网格平滑细分滤波器, 用来让一个多边形(尤其是三角网格)模型的表面变得更平滑、更细腻 简而言之就是上采样+平滑 """ smooth_loop = vtkLoopSubdivisionFilter() smooth_loop.SetNumberOfSubdivisions(3) # 设置细分次数 smooth_loop.SetInputConnection(cleanPolyData.GetOutputPort()) smooth_loop.Update() mapper = vtkPolyDataMapper() mapper.SetInputConnection(smooth_loop.GetOutputPort()) actor_loop = vtkActor() actor_loop.SetMapper(mapper) """ SetInterpolationToFlat置模型的着色模式(Shading Model)为平面着色(Flat Shading) 平面着色的含义: 颜色计算:对于模型中的每一个多边形(例如,一个三角形),光照和颜色计算只在多边形的一个顶点上进行 颜色应用:将计算出的单一颜色应用于整个多边形表面 结果:多边形内部的颜色是均匀的、平坦的。每个多边形边界处都会出现明显的颜色或亮度变化, 使得模型看起来像是由许多独立的、扁平的小平面拼成的,具有明显的棱角感 通常,平面着色用于强调**单元格(Cell)**本身的重要性,而不是曲面的光滑度, 或者用于处理那些颜色是基于单元格而不是顶点来定义的模型 """ actor_loop.GetProperty().SetInterpolationToFlat() """ actor_loop.GetProperty().SetInterpolationToGouraud() 它的作用是将模型的着色模式设置为 Gouraud 着色(Gouraud Shading),使模型表面看起来更平滑、更真实 Gouraud 着色的含义: 光照计算(仅在顶点)Gouraud 着色在模型中每个多边形的所有顶点上计算光照强度和颜色(例如,基于法线、光源和相机位置) 颜色插值(在表面)它通过线性插值的方法,将顶点的颜色平滑地混合到多边形内部的所有像素上 结果:最终的模型表面看起来是连续和圆润的,消除了多边形之间的突兀边界。这种模式适用于渲染有机形状、曲面或任何需要平滑外观的几何体 actor_loop.GetProperty().SetInterpolationToPhong() Phong 着色是最复杂、最昂贵,但通常也是最能产生逼真高光效果的技术 Phong 着色旨在修正 Gouraud 着色的两个主要缺陷:无法准确显示模型内部的高光点(Specular Highlights)和移动的光源 工作原理如下: 光照计算(仅在顶点)和 Gouraud 着色一样,法线在每个顶点处计算一次,并在多边形表面进行插值。 高光和颜色插值(在像素):关键区别:它不是插值颜色,而是插值法线向量。对于多边形上的每个像素(在渲染时),VTK 使用插值后的法线、光源和相机位置来重新计算光照方程。 结果:由于光照计算是在每个像素上进行的,Phong 着色能够渲染出真实、锐利且移动准确的高光点。这使得模型表面的质感(如金属光泽、塑料质感)看起来更加逼真 """ # 定义一个cell的定位 """ vtkCellLocator 是 VTK 中一个非常常用、非常高效的 空间查询与碰撞检测 工具 核心用途是:在三维空间中快速定位一个点、线或其他几何体与 mesh(网格)之间的几何关系 核心功能有最近点查询,射线——网格相交,点所在单元,多点最近单元,构建空间索引 """ locator = vtkCellLocator() locator.SetDataSet(smooth_loop.GetOutput()) locator.BuildLocator() # 执行索引构建操作。 # 这是计算成本最高的一步,但只执行一次。定位器会分析输入网格的所有几何单元(三角形),并建立它的内部数据结构 maxloop = 1000 dist = 20.0 / maxloop tolerance = 0.001 # X 轴上等间距地发射一系列垂直的射线,然后使用 vtkCellLocator 来精确找到每条射线与三维地形曲面的交点 points = vtkPoints() for i in range(maxloop): p1 = [2 + i * dist, 16, -1] p2 = [2 + i * dist, 16, 6] # p1 p2点形成的线段在Z轴上是穿过上面形成的mesh的 t = mutable(0) # 交点在线段 P1→P2 上的位置。如果 t=0,交点是 P1;如果 t=1,交点是 P2;如果 0<t<1,交点在线段内部 pos = [0.0, 0.0, 0.0] # 三维空间中的绝对坐标 pcoords = [0.0, 0.0, 0.0] # 交点在它所处的那个cell内部的相对坐标 """ pcoords 在你的地形网格示例中,cell 是一个三角形。三角形通常使用两个参数 (ξ,η) 来定义内部位置: 维度:2 个参数,通常写作 P =(ξ,η,0),其中第三个值总是 0。 物理意义:这两个参数代表了点到三角形三个顶点的相对权重或距离 (1,0) 点位于第一个顶点上。 (0,1) 点位于第二个顶点上。 (0,0) 点位于第三个顶点上。 (0.5,0.5) 点位于三角形某条边的中点。 (0.33,0.33) 点位于三角形的质心(重心) 在 VTK 中对于颜色插值、法线计算以及进一步的几何处理(比如计算梯度)都至关重要 """ subId = mutable(0) # 交点所在那个cell的ID locator.IntersectWithLine(p1, p2, tolerance, t, pos, pcoords, subId) # 如果IntersectWithLine没有找到交点,一切的值都会是初始值 pos[2] += 0.01 # 增加一点偏移值,方便可视化 points.InsertNextPoint(pos) """ vtkParametricSpline 主要用于在 一系列离散点之间生成平滑曲线(样条曲线 / Spline) """ spline = vtkParametricSpline() spline.SetPoints(points) functionSource = vtkParametricFunctionSource() functionSource.SetUResolution(maxloop) # 设置采样点的密度(或分辨率) functionSource.SetParametricFunction(spline) # Map the spline mapper = vtkPolyDataMapper() mapper.SetInputConnection(functionSource.GetOutputPort()) # Define the line actor actor = vtkActor() actor.SetMapper(mapper) actor.GetProperty().SetColor(named_colors.GetColor3d('Red')) actor.GetProperty().SetLineWidth(3) # Visualize renderer = vtkRenderer() renderWindow = vtkRenderWindow() renderWindow.AddRenderer(renderer) renderWindowInteractor = vtkRenderWindowInteractor() renderWindowInteractor.SetRenderWindow(renderWindow) # Add actors and render renderer.AddActor(actor) renderer.AddActor(actor_loop) renderer.SetBackground(named_colors.GetColor3d('Cornsilk')) renderWindow.SetSize(800, 800) renderWindow.Render() renderer.GetActiveCamera().SetPosition(-32.471276, 53.258788, 61.209332) renderer.GetActiveCamera().SetFocalPoint(15.500000, 15.500000, 2.000000) renderer.GetActiveCamera().SetViewUp(0.348057, -0.636740, 0.688055) renderer.ResetCameraClippingRange() renderWindow.SetWindowName('LineOnMesh') renderWindow.Render() renderWindowInteractor.Start() if __name__ == '__main__': main()
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 4:13:02

59、SQL网络、分布式数据库与数据管理策略

SQL网络、分布式数据库与数据管理策略 1. 两阶段提交协议 两阶段提交协议可保护分布式事务免受系统B、系统C或通信网络中任何单一故障的影响。以下是该协议在故障恢复方面的两个示例: - 故障发生在系统C发送YES消息之前 :假设在步骤3中系统C发送YES消息之前发生故障,系…

作者头像 李华
网站建设 2026/6/10 15:54:46

55、SQL 在数据仓库与应用服务器中的应用与发展

SQL 在数据仓库与应用服务器中的应用与发展 数据仓库性能 数据仓库的性能是其发挥作用的关键因素之一。若商业分析查询耗时过长,人们便不太会临时使用该仓库进行决策;若向仓库加载数据耗时过久,企业信息系统(IS)组织可能会抵制频繁更新,陈旧的数据会降低仓库的实用性。…

作者头像 李华
网站建设 2026/6/10 16:14:43

64、SQL与XML的融合:探索数据处理新境界

SQL与XML的融合:探索数据处理新境界 1. 引言 在互联网和Web技术不断发展的今天,可扩展标记语言(XML)和结构化查询语言(SQL)成为了处理和管理数据的重要工具。XML是一种用于表示和交换结构化数据的标准语言,而SQL则是定义、访问和更新关系数据库中结构化数据的标准语言…

作者头像 李华
网站建设 2026/6/10 16:12:13

Unity AVPRO插件终极指南:解锁大分辨率视频播放新境界

Unity AVPRO插件终极指南&#xff1a;解锁大分辨率视频播放新境界 【免费下载链接】Unity使用AVPRO插件播放大分辨率视频 本资源文件提供了在Unity中使用AVPRO插件播放大分辨率视频的详细教程和相关资源。通过本教程&#xff0c;您可以学习如何在Unity项目中集成AVPRO插件&…

作者头像 李华
网站建设 2026/6/10 14:01:46

TachiyomiJ2K通知系统完整配置指南:从基础设置到高级功能

TachiyomiJ2K通知系统完整配置指南&#xff1a;从基础设置到高级功能 【免费下载链接】tachiyomiJ2K Free and open source manga reader for Android 项目地址: https://gitcode.com/gh_mirrors/ta/tachiyomiJ2K TachiyomiJ2K作为Android平台上最优秀的免费开源漫画阅读…

作者头像 李华
网站建设 2026/6/10 2:16:10

Brush引擎深度解析:高斯泼溅技术的革命性突破

在3D重建技术快速发展的今天&#xff0c;Brush项目以其创新的高斯泼溅算法架构&#xff0c;为实时3D渲染和训练领域带来了颠覆性变革。作为一项基于WebGPU的跨平台3D重建解决方案&#xff0c;Brush不仅实现了高质量的场景重建&#xff0c;更在渲染效率和兼容性方面达到了业界领…

作者头像 李华