一个网站锚文本可以做几个,网站无法打开的原因,新闻30分,sae更新wordpress一#xff1a;主要的知识点
1、说明
本文只是教程内容的一小段#xff0c;因博客字数限制#xff0c;故进行拆分。主教程链接#xff1a;vtk教程——逐行解析官网所有Python示例-CSDN博客
2、知识点纪要
本段代码主要涉及的有①如何根据顶点索引找到邻接顶点的索引主要的知识点1、说明本文只是教程内容的一小段因博客字数限制故进行拆分。主教程链接vtk教程——逐行解析官网所有Python示例-CSDN博客2、知识点纪要本段代码主要涉及的有①如何根据顶点索引找到邻接顶点的索引②特征边缘③曲率的计算二代码及注释import vtkmodules.vtkRenderingOpenGL2 from vtkmodules.vtkIOXML import vtkXMLPolyDataReader from vtkmodules.vtkFiltersGeneral import vtkCurvatures from vtkmodules.vtkCommonDataModel import vtkPolyData from vtkmodules.numpy_interface import dataset_adapter as dsa from vtkmodules.vtkFiltersCore import vtkIdFilter, vtkFeatureEdges from vtkmodules.vtkCommonCore import vtkIdList, VTK_DOUBLE import numpy as np from vtkmodules.vtkRenderingAnnotation import vtkScalarBarActor from vtkmodules.util import numpy_support from vtkmodules.vtkCommonColor import vtkColorSeries, vtkNamedColors from vtkmodules.vtkRenderingCore import ( vtkActor, vtkColorTransferFunction, vtkPolyDataMapper, vtkRenderWindow, vtkRenderWindowInteractor, vtkRenderer ) from vtkmodules.vtkInteractionWidgets import vtkCameraOrientationWidget def point_neighbourhood(source: vtkPolyData, pt_id: int): 找到对应索引顶点的拓扑邻接顶点索引 cell_ids vtkIdList() GetPointCells 拿到模型中与点p_id相连的所有面的ID source.GetPointCells(pt_id, cell_ids) neighbour set() for cell_idx in range(0, cell_ids.GetNumberOfIds()): cell_id cell_ids.GetId(cell_idx) cell_point_ids vtkIdList() GetCellPoints 拿到指定单元(cell)的所有顶点的ID source.GetCellPoints(cell_id, cell_point_ids) for cell_pt_idx in range(0, cell_point_ids.GetNumberOfIds()): neighbour.add(cell_point_ids.GetId(cell_pt_idx)) return neighbour def compute_distance(source: vtkPolyData, pt_id_a: int, pt_id_b: int) - float: pt_a np.array(source.GetPoint(pt_id_a)) pt_b np.array(source.GetPoint(pt_id_b)) return np.linalg.norm(pt_a - pt_b) def adjust_edge_curvatures(source: vtkPolyData, curvature_name: str, epsilon1.0e-08) - None: source.GetPointData().SetActiveScalars(cruvature_name) 这段代码的含义是 将模型的指定曲率数组设置为活动标量active scalars 一个 vtkPolyData 对象可以包含多个不同的数据数组比如法线TextureCoordinates 纹理坐标Gauss_Curvature 等 source: 指的是你的 vtkPolyData 对象也就是牛头模型的数据。 GetPointData(): 获取与模型每个点相关联的所有数据数组的集合vtkPointData。这包括坐标、法线、纹理坐标以及像曲率这样的自定义数据。 SetActiveScalars(curvature_name): 这是最关键的方法。它告诉 VTK 的管线在接下来的操作中例如映射和渲染应该使用哪个数据数组作为主要的标量数据。 在这里curvature_name 可以是 Gauss_Curvature 或 Mean_Curvature。通过这行代码你明确指定了 “请把这个模型上的 Gauss_Curvature或 Mean_Curvature数组作为主要颜色值来源用于渲染。 source.GetPointData().SetActiveScalars(curvature_name) dataset_adapter 了把 VTK 的数据对象vtkDataSet, vtkArray, …和 NumPy 数组 之间建立一个桥梁 np_source dsa.WrapDataObject(source) WrapDataObject 把一个 VTK 数据对象包一层壳adapter让它可以直接用 NumPy 的方式访问 np_source.Points → 得到点坐标的 numpy.ndarray np_source.PointData - 得到点数据标量场/向量场的数组字典 np_source.CellData - 得到单元数据 curvatures np_source.PointData[curvature_name] # 得到了各个点的高斯曲率大小长度与点数保持一致 # 下面的一段代码是给数据source的点生产成一个ID数组并存储在指定名字的数组里 array_name ids vtkIdFilter 把隐含的索引点/单元 ID转换成显式的数组在数据中生成点 ID 和/或单元 ID并把它们存储为数组方便后续访问、映射或可视化 在 VTK 里几乎所有的数据集都有 点 (Points) 和 单元 (Cells) 点 ID每个点的索引从 0 开始编号 单元 ID每个单元的索引也是从 0 开始编号 平时这些 ID 是隐含存在的你用 GetPoint(i)、GetCell(i) 可以拿到但并不是数据数组的一部分。 如果你想把这些 ID 当作数组存到 PointData 或 CellData 中就可以用 vtkIdFilter id_filter vtkIdFilter() id_filter.SetInputData(source) id_filter.SetPointIds(True) # 是否生成点ID id_filter.SetCellIds(False) # 是否生成单元的ID id_filter.SetPointIdsArrayName(array_name) # 指定生成的ID数组的名字 # id_filter.SetCellIdsArrayName(array_name) 没有生成单元的ID没必要 id_filter.Update() vtkFeatureEdges 从一个曲面PolyData中提取“特征边缘”并把这些边缘输出为一条条 polyline折线 什么是“特征边缘” 在 VTK 里三角形网格的边大体可以分成几类 Boundary Edges边界边 只属于一个多边形的边即网格开口处的边。 打开BoundaryEdgesOn() Feature Edges特征边 被两个多边形共享但这两个面的夹角大于某个阈值默认 30°。 打开FeatureEdgesOn() 用 SetFeatureAngle(angle) 设置角度阈值。 Manifold Edges流形边 被恰好两个多边形共享且夹角小于阈值即正常相邻面。 打开ManifoldEdgesOn() Non-Manifold Edges非流形边 被两个以上的多边形共享。 打开NonManifoldEdgesOn() edges vtkFeatureEdges() edges.SetInputConnection(id_filter.GetOutputPort()) edges.BoundaryEdgesOn() # 检测边缘边 edges.ManifoldEdgesOff() # 不检测流行边 edges.NonManifoldEdgesOff() # 不检测非流行边 edges.FeatureEdgesOff() # 不检测特征边 edges.Update() edge_array edges.GetOutput().GetPointData().GetArray(array_name) boundary_ids [] # mesh边缘顶点的索引 for i in range(edges.GetOutput().GetNumberOfPoints()): boundary_ids.append(edge_array.GetValue(i)) # 删除可能存在的边缘索引 p_ids_set set(boundary_ids) count_invalid 0 for p_id in boundary_ids: # 获取到p_id这个索引定点的邻接点的索引 p_ids_neighbours point_neighbourhood(source, p_id) # 这里减去了边缘索引说明只想保留非边缘顶点的索引 p_ids_neighbours - p_ids_set curvs [curvatures[p_id_n] for p_id_n in p_ids_neighbours] # 计算两个顶点的欧式距离 dists [compute_distance(source, p_id_n, p_id) for p_id_n in p_ids_neighbours] curvs np.array(curvs) dists np.array(dists) # 避免因计算精度原因导致的出现距离为0的现象或者避免比较自身点 curvs curvs[dists 0] dists dists[dists 0] if len(curvs) 0: # 距离的大小与权重成反比 weights 1 / np.array(dists) weights / weights.sum() new_curv np.dot(curvs, weights) else: count_invalid 1 new_curv 0.0 curvatures[p_id] new_curv if epsilon ! 0: 下面这段代码的含义是指如果某个曲率值的绝对值小于阈值 epsilon就把它替换成 0否则保持原值 curvatures np.where(abs(curvatures) epsilon, 0, curvatures) 把 NumPy 数组转换成 VTK 的 vtkDataArray deepTrue 表示复制一份数据而不是引用同一块内存 curv numpy_support.numpy_to_vtk(num_arraycurvatures.ravel(), deepTrue, array_typeVTK_DOUBLE) curv.SetName(curvature_name) # 给这个vtk数组命名 source.GetPointData().RemoveArray(curvature_name) # 将之前同名的数组删掉避免冲突 source.GetPointData().AddArray(curv) source.GetPointData().SetActiveScalars(curvature_name) def main(): file_name Data/cowHead.vtp color_map_idx 16 gaussian_curvature True if gaussian_curvature: curvature Gauss_Curvature # 高斯曲率 else: curvature Mean_Curvature # 平均曲率 reader vtkXMLPolyDataReader() reader.SetFileName(file_name) reader.Update() source reader.GetOutput() vtkCurvatures 计算曲面曲率的一个滤波器 输入vtkPolyData通常是一个三角网格曲面。 输出在网格的 点数据point data 中生成一个标量数组表示每个点的曲率值。 这个过滤器会将计算出的曲率值作为新的点数据数组添加到模型中 cc vtkCurvatures() cc.SetInputConnection(reader.GetOutputPort()) if gaussian_curvature: cc.SetCurvatureTypeToGaussian() # 计算高斯曲率 cc.Update() else: cc.SetCurvatureTypeToMean() # 计算平均曲率 cc.Update() adjust_edge_curvatures 这个函数通过将曲面边缘的曲率值替换为其邻域内点的曲率平均值来调整边缘的曲率 该函数首先通过 vtkFeatureEdges 过滤器识别出模型的边界点。 然后它遍历每个边界点并计算其邻近内部点的曲率值的加权平均值。 最后它用这个加权平均值替换掉原始的边界曲率值从而平滑了边界上的曲率使得渲染结果更加合理 adjust_edge_curvatures(cc.GetOutput(), curvature) GetPointData().GetAbstractArray 和 GetPointData().GetArray的区别 GetArray(name_or_index) 返回类型vtkDataArray或其子类 vtkDataArray 是数值数组专门存 数值型标量/向量/张量比如 float、double、int 也就是说GetArray() 只适用于 数值数组对非数值的数组例如字符串会失败或者返回 None GetAbstractArray(name_or_index) 返回类型vtkAbstractArray vtkAbstractArray 是 vtkDataArray 的基类它更泛化可以表示 任意类型的数组不仅仅是数值型 数值数组vtkDoubleArray、vtkFloatArray … 字符串数组vtkStringArray 稀疏数组等其他类型 适合在你 不确定数组类型 时使用比如不知道是数值还是字符串 source.GetPointData().AddArray(cc.GetOutput().GetPointData().GetAbstractArray(curvature)) GetScalars 返回 点数据 (PointData) 或单元数据 (CellData) 中的 “活动 (active)”标量数组 下面是一种类似语法糖的写法当正确设置活动标量后 应该这样写 source.GetPointData().GetScalars().GetRange() GetRange() 获取这个标量值的最大和最小值 scalar_range source.GetPointData().GetScalars(curvature).GetRange() # vtkColorSeries 快速生成一组颜色用于着色 color_series vtkColorSeries() # SetColorScheme 选择某一种预定义的配色方案 color_series.SetColorScheme(color_map_idx) vtkColorTransferFunction 专门用来定义标量数值到颜色之间映射关系 的类 输入一个 标量值通常是数据里的 scalar比如密度、强度、温度等。 输出一个 颜色RGB 值。 lut vtkColorTransferFunction() lut.SetColorSpaceToHSV() for i in range(0, color_series.GetNumberOfColors()): color color_series.GetColor(i) # rgb三色范围0~255 double_color list(map(lambda x: x / 255.0, color)) # 映射到0~1 下面这段代码是将标量范围线性映射到颜色索引 把整个标量范围 等分 为 N-1 段N 颜色数第 i 个颜色点对应的标量位置就是 t t scalar_range[0] (scalar_range[1] - scalar_range[0]) / (color_series.GetNumberOfColors() - 1) * i AddRGBPoint 往lut添加一个颜色控制点 t 这个控制点对应的标量值 double_color[0], double_color[1], double_color[2] → 这个标量值对应的 RGB 颜色 这样渲染时数据里的数值如果等于 t就会显示为这个 RGB 如果数值在两个控制点之间VTK 会自动插值 lut.AddRGBPoint(t, double_color[0], double_color[1], double_color[2]) colors vtkNamedColors() mapper vtkPolyDataMapper() mapper.SetInputData(source) mapper.SetScalarModeToUsePointFieldData() # 使用点数据上色 mapper.SelectColorArray(curvature) # 选择具体的标量数组进行上色 mapper.SetScalarRange(scalar_range) # 设置标量值映射到颜色查找表的范围超过的会被裁剪到边界颜色 mapper.SetLookupTable(lut) actor vtkActor() actor.SetMapper(mapper) window_width 800 window_height 800 vtkScalarBarActor 专门用于创建和显示一个颜色标尺color bar 或 legend 它的主要作用是为你的可视化结果添加一个解释性的图例。 当你使用颜色来映射数据比如温度、压力或曲率时 这个颜色标尺会告诉你每种颜色代表的数值范围从而让你的可视化结果更具可读性和科学性 scalar_bar vtkScalarBarActor() scalar_bar.SetLookupTable(mapper.GetLookupTable()) scalar_bar.SetTitle(curvature.replace(_, \n)) UnconstrainedFontSizeOn 让颜色标尺上的字体大小不受限制从而能够根据标尺的大小自动调整 scalar_bar.UnconstrainedFontSizeOn() scalar_bar.SetNumberOfLabels(5) scalar_bar.SetMaximumWidthInPixels(window_width // 8) scalar_bar.SetMaximumHeightInPixels(window_height // 3) renderer vtkRenderer() ren_win vtkRenderWindow() ren_win.AddRenderer(renderer) ren_win.SetSize(window_width, window_height) ren_win.SetWindowName(Curvatures) iren vtkRenderWindowInteractor() iren.SetRenderWindow(ren_win) # Important: The interactor must be set prior to enabling the widget. iren.SetRenderWindow(ren_win) vtkCameraOrientationWidget 控制相机视角的组件 cam_orient_manipulator vtkCameraOrientationWidget() cam_orient_manipulator.SetParentRenderer(renderer) # Enable the widget. cam_orient_manipulator.On() # Add the actors to the scene renderer.AddActor(actor) renderer.AddViewProp(scalar_bar) renderer.SetBackground(colors.GetColor3d(DarkSlateGray)) # Render and interact ren_win.Render() iren.Start() print() if __name__ __main__: main()