【三維幾何學習】自制簡單的網格可視化軟件 — Mesh Visualization

自制簡單的網格可視化軟件 — Mesh Visualization

  • 引言
  • 一、整體框架
    • 1.1 三角形網格
    • 1.2 界面管理
    • 1.3 VTK可視化界面
  • 二、核心源碼
    • 2.1 三角形網格:TriMesh類
    • 2.2 界面Widget_Mesh_Manager
    • 2.3 VTK可視化
    • 2.4 main

引言

使用PyQt自制簡單的網格可視化軟件 - 視頻展示

本是為了方便輸入模型分析、網格分割結果可視化,使用PyQt做的一款小軟件,后續通過增刪變成了Mesh Visualization,主要針對三角形網格。主要功能包括:讀取網格(目前僅支持.obj),關于網格頂點、邊、面的一些可視化小操作(是否顯示、更改顏色等)、比較簡單的燈光以及背景設置、一些基本功能(模型列表、操作日志等)。


一、整體框架

在這里插入圖片描述

  • MainWindow:主窗體。包含縮小、放大、關閉、菜單欄等
  • Mesh:三角網格,包含網格的讀取、保存、網格的一些基本屬性
  • Resource:資源文件夾。包含界面樣式和圖片
  • Widget_Mesh_Manager:界面管理,內含多個子控件。包含模型列表、網格信息顯示界面、日志界面
  • Widget_Vtk:模型渲染界面,就是VTK渲染窗口。包含VTK顯示代碼actor、mapper、light等
    在這里插入圖片描述

關于界面 統一采用一個界面三個文件:

  1. xxx.ui (可編輯的界面,pyqt插件可打開)
  2. ui_xxx.py (ui界面轉的py界面文件) 參數設置 $FileName$ -o ui_$FileNameWithoutExtension$.py -x
  3. xxx.py (主要在這里寫代碼)

1.1 三角形網格

三角形網格Mesh文件夾中含有兩個文件:

  • load_and_save.py 讀取保存三角形網格,目前只支持obj文件,可用現有的庫代替 /todo
  • TriMesh.py 三角形網格類,保存三角形網格的文件名、格式、頂點、面片等信息,每個網格都有一個獨立vtk actor,方便操作以及顯示

1.2 界面管理

  • 模型列表:顯示打開的每一個模型,可以進行模型間的切換顯示
  • 模型信息:包括頂點和面片數量,可修改點、邊、面以及燈光顏色
  • 日志顯示:記錄每一步操作,但目前只顯示部分操作 /todo
    在這里插入圖片描述

1.3 VTK可視化界面

主要用于模型渲染顯示 (self.vtk_widget = QVTKRenderWindowInteractor(self)):

  • mapper 映射器,將數據轉為圖形數據
  • renderer 渲染器,將三維圖形轉為二維圖片
  • light 燈光,只設置了一個燈光 /todo
  • 交互方式 vtk.vtkInteractorStyleTrackballCamera()

其中actor每個三角形網格一個,方便單獨操作


二、核心源碼

2.1 三角形網格:TriMesh類

import ntpath
import numpy as np
from scipy.sparse import csr_matrix
from Mesh.load_and_save import load_obj, load_obj_with_edges
import vtkmodules.all as vtkclass TriMesh:# 0.文件filename = None  # 文件名path = None  # 路徑file = None  # 完整路徑format = None  # 格式# 1.基本屬性vs = None     # 頂點faces = None  # 面片name = None   # 自定義名稱actor = None  # 保存可視化的數據# 2.進階屬性point_adjacency_matrix = None  # 點的鄰接矩陣edges = Noneedge_labels = Noneedge_actor = Nonedef __init__(self, file=None, mode=None):# 賦值self.path = ntpath.split(file)[0]self.filename = ntpath.split(file)[1]self.file = fileself.format = self.filename.split('.')[-1]self.actor = vtk.vtkActor()self.edge_actor = vtk.vtkActor()# 讀取if self.format == 'obj':if mode == 1:self.vs, self.faces, self.edges, self.edge_labels = load_obj_with_edges(file)else:self.vs, self.faces = load_obj(file)else:print('Unsupported format')return# 計算點鄰接矩陣self.point_adjacency_matrix = self.computer_point_adjacency_matrix()def computer_point_adjacency_matrix(self):num = len(self.vs)row = np.hstack([self.faces[:, 0], self.faces[:, 1], self.faces[:, 2]])col = np.hstack([self.faces[:, 1], self.faces[:, 2], self.faces[:, 0]])value = 0 * row + 1point_adjacency_matrix = csr_matrix((value, (row, col)), shape=(num, num)).toarray()return point_adjacency_matrixdef boundary_edge(self):edge_cnt = self.point_adjacency_matrix + self.point_adjacency_matrix.Ttwo_point = np.where(edge_cnt == 1)return two_pointdef creat_edges(self):edge2key = dict()edges = []for face_id, face in enumerate(self.faces):faces_edges = []for i in range(3):cur_edge = (face[i], face[(i + 1) % 3])faces_edges.append(cur_edge)for idx, edge in enumerate(faces_edges):edge = tuple(sorted(list(edge)))faces_edges[idx] = edgeif edge not in edge2key:edge2key[edge] = 1edges.append(list(edge))self.edges = np.array(edges, dtype=np.int32)if __name__ == '__main__':cs = TriMesh('../00ceshi/1.obj')# print(cs.point_adjacency_matrix)point = cs.boundary_edge()print(1)

2.2 界面Widget_Mesh_Manager

from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from Widget_Mesh_Manager.ui_Widget_Mesh_Manager import Ui_Widget_Mesh_Manager
import datetime
from Mesh.TriMesh import TriMesh
import numpy as npclass Widget_Mesh_Manager(QWidget, Ui_Widget_Mesh_Manager):TriMesh_list = []mesh_show = pyqtSignal(int)def __init__(self, parent=None):super(Widget_Mesh_Manager, self).__init__(parent)self.setupUi(self)# 滾動條設置self.hSlider_pointSize.setMinimum(1)       # 點self.hSlider_pointSize.setMaximum(9)self.hSlider_pointSize.setSingleStep(1)# self.hSlider_pointSize.setTickInterval(2)     # 帶有樣式 不顯示刻度# self.hSlider_pointSize.setTickPosition(QSlider.TicksBelow)self.hSlider_edgeSize.setMinimum(1)        # 邊self.hSlider_edgeSize.setMaximum(9)self.hSlider_edgeSize.setSingleStep(1)self.hSlider_lightIntensity.setMinimum(0)  # 燈光self.hSlider_lightIntensity.setMaximum(10)self.hSlider_lightIntensity.setSingleStep(1)# 按鈕點擊函數self.initBtn()# UI布局self.initUI()def initBtn(self):passdef initUI(self):# tableWidgetself.tableWidget.setColumnCount(1)  # 列數self.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)  # 所有列自動拉伸,充滿界面self.tableWidget.setSelectionMode(QAbstractItemView.SingleSelection)           # 設置只能選中一行self.tableWidget.setEditTriggers(QTableView.NoEditTriggers)                    # 不可編輯self.tableWidget.setSelectionBehavior(QAbstractItemView.SelectRows)            # 設置只有行選中self.tableWidget.verticalHeader().setVisible(False)         # 隱藏列表頭self.tableWidget.horizontalHeader().setVisible(False)       # 隱藏行def addMesh(self, mesh: TriMesh):# 添加到listself.TriMesh_list.append(mesh)# 添加到uirow = self.tableWidget.rowCount()self.tableWidget.insertRow(row)item = QTableWidgetItem(mesh.filename)self.tableWidget.setItem(row, 0, item)self.tableWidget.clearFocus()self.tableWidget.selectRow(row)     # 新加入的行被選中# item.setSelected(True)# 刷新Infoself.showMesh_Info(row)def addLog(self, info):time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S: ")self.textEdit.append(time + info)def showMesh_Info(self, mesh_id):mesh = self.TriMesh_list[mesh_id]self.groupBox.setTitle(mesh.filename)self.label_vs_num.setText('頂點個數:' + str(len(mesh.vs)))self.label_face_num.setText('面片個數:' + str(len(mesh.faces)))self.mesh_show.emit(mesh_id)# 重寫tableWidget的點擊事件def on_tableWidget_cellClicked(self, row, col):self.showMesh_Info(row)pass

2.3 VTK可視化

from PyQt5.QtWidgets import *
from Widget_Vtk.ui_Widget_Vtk import Ui_Widget_Vtk
from Mesh.TriMesh import TriMesh
import numpy as np
from vtkmodules.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
import vtkmodules.all as vtkclass Widget_Vtk(QWidget, Ui_Widget_Vtk):mapper = None    # 映射器 數據actor = None     # 演員 get mapperrenderer = None  # 渲染light = None     # 燈光 只有一個def __init__(self, parent=None):super(Widget_Vtk, self).__init__(parent)self.setupUi(self)#self.vtk_widget = QVTKRenderWindowInteractor(self)self.colors = np.array([[0, 0, 255], [0, 255, 255], [255, 0, 255], [0, 255, 0],[255, 255, 0], [255, 0, 0], [100, 180, 51], [255, 150, 51]])self.colors = np.array([[80, 136, 240], [0, 255, 255], [255, 0, 255], [0, 255, 0],[255, 255, 0], [255, 0, 0], [70, 70, 220], [255, 150, 51], [0,0,0]])self.colors1 = np.array([[180, 90, 90], [121, 185, 128], [90, 90, 180], [180, 180, 0],[255, 255, 0], [255, 0, 0], [100, 255, 51], [255, 150, 51]])# 初始化renderself.renderer = vtk.vtkRenderer()self.renderer.SetBackground(1, 1, 1)self.vtk_widget.GetRenderWindow().AddRenderer(self.renderer)self.interactor = self.vtk_widget.GetRenderWindow().GetInteractor()interactor_style = vtk.vtkInteractorStyleTrackballCamera()self.interactor.SetInteractorStyle(interactor_style)self.interactor.Initialize()# 初始化lightself.light = vtk.vtkLight()self.light.SwitchOff()      # 默認關閉self.renderer.AddLight(self.light)self.vtk_widget.Render()self.vtk_widget.Start()self.renderer.ResetCamera()self.vtk_widget.update()def resizeEvent(self, e):"""重寫窗口移動事件"""self.vtk_widget.resize(self.size())def removeAllActors(self):al = self.renderer.GetActors()n = al.GetNumberOfItems()al.InitTraversal()for i in range(n):actor = al.GetNextActor()self.renderer.RemoveActor(actor)self.vtk_widget.update()def showTrimesh(self, mesh: TriMesh):# 添加點points = vtk.vtkPoints()for v in mesh.vs:points.InsertNextPoint(v)# 添加面片polys = vtk.vtkCellArray()for f in mesh.faces:polys.InsertNextCell(len(f), f)# 創建PolyDatacube = vtk.vtkPolyData()cube.SetPoints(points)cube.SetPolys(polys)# 創建 mapper 和 actormapper = vtk.vtkPolyDataMapper()mapper.ScalarVisibilityOff()mapper.SetInputData(cube)mesh.actor.SetMapper(mapper)mesh.actor.GetProperty().SetColor([0.5, 0.5, 0.5])self.renderer.AddActor(mesh.actor)self.renderer.ResetCamera()self.vtk_widget.update()def show_boundary_edge(self, mesh: TriMesh):# 添加點points = vtk.vtkPoints()for v in mesh.vs:points.InsertNextPoint(v)pa, pb = mesh.boundary_edge()# 添加邊edges = vtk.vtkCellArray()for i in range(len(pa)):edges.InsertNextCell(2, np.array([pa[i], pb[i]]))# 添加邊界mapper2 = vtk.vtkPolyDataMapper()cube1 = vtk.vtkPolyData()cube1.SetPoints(points)cube1.SetLines(edges)mapper2.SetInputData(cube1)mesh.edge_actor.SetMapper(mapper2)# mesh.edge_actor.GetProperty().SetEdgeColor(0, 0, 1)# mesh.edge_actor.GetProperty().SetEdgeVisibility(1)mesh.edge_actor.GetProperty().SetLineWidth(2)self.renderer.AddActor(mesh.edge_actor)self.vtk_widget.update()def show_mesh_color(self, mesh: TriMesh):# 添加點points = vtk.vtkPoints()for v in mesh.vs:points.InsertNextPoint(v)# 添加面片polys = vtk.vtkCellArray()cellColor = vtk.vtkFloatArray()for f in mesh.faces:polys.InsertNextCell(len(f), f)cellColor.InsertNextValue(mesh.vs[f[0]][0])# 創建PolyDatacube = vtk.vtkPolyData()cube.SetPoints(points)cube.SetPolys(polys)cube.GetCellData().SetScalars(cellColor)# 創建 mapper 和 actorself.mapper = vtk.vtkPolyDataMapper()self.mapper.SetScalarRange(min(mesh.vs[:, 0]), max(mesh.vs[:, 0]))self.mapper.SetInputData(cube)mesh.actor.SetMapper(self.mapper)mesh.actor.GetProperty().SetEdgeVisibility(1)self.vtk_widget.update()def show_point_color(self, mesh: TriMesh, seg=[]):# 添加點points = vtk.vtkPoints()pColor = vtk.vtkFloatArray()for v in mesh.vs:points.InsertNextPoint(v)# id = np.random.randint(0, 2)pColor.InsertNextValue(v[0])if len(seg) > 0:pColor = vtk.vtkFloatArray()for s in seg:pColor.InsertNextValue(s)# 添加面片polys = vtk.vtkCellArray()for f in mesh.faces:polys.InsertNextCell(len(f), f)# 創建PolyDatacube = vtk.vtkPolyData()cube.SetPoints(points)cube.SetPolys(polys)cube.GetPointData().SetScalars(pColor)mapper = vtk.vtkPolyDataMapper()mapper.SetScalarRange(min(mesh.vs[:, 2]), max(mesh.vs[:, 2]))mapper.SetInputData(cube)mesh.actor.SetMapper(mapper)mesh.actor.GetProperty().SetColor([0.5, 0.5, 0.5])self.vtk_widget.update()def show_mesh_seg(self, mesh: TriMesh, seg):# 添加點points = vtk.vtkPoints()for v in mesh.vs:points.InsertNextPoint(v)# 添加面片polys = vtk.vtkCellArray()cellColor = vtk.vtkUnsignedCharArray()cellColor.SetNumberOfComponents(3)for f in mesh.faces:polys.InsertNextCell(len(f), f)for s in seg:c = self.colors[s]cellColor.InsertNextTuple(c)# 創建PolyDatacube = vtk.vtkPolyData()cube.SetPoints(points)cube.SetPolys(polys)cube.GetCellData().SetScalars(cellColor)# 創建 mappermapper = vtk.vtkPolyDataMapper()mapper.SetColorModeToDefault()  # 需要設置為默認顏色Modemapper.SetInputData(cube)mesh.actor.SetMapper(mapper)self.vtk_widget.update()def show_points(self, mesh: TriMesh):# 添加點points = vtk.vtkPoints()for v in mesh.vs:points.InsertNextPoint(v)vs = vtk.vtkPolyData()vs.SetPoints(points)# 生成頂點vertex = vtk.vtkVertexGlyphFilter()vertex.SetInputData(vs)# 創建 mapper 和 actormapper = vtk.vtkPolyDataMapper()mapper.SetInputConnection(vertex.GetOutputPort())mesh.actor.SetMapper(mapper)mesh.actor.GetProperty().SetColor([0, 0, 0])mesh.actor.GetProperty().SetPointSize(5)self.vtk_widget.update()def saveToimage(self):from vtkmodules.vtkRenderingCore import vtkWindowToImageFilterfrom vtkmodules.vtkIOImage import (vtkBMPWriter,vtkJPEGWriter,vtkPNGWriter,vtkPNMWriter,vtkPostScriptWriter,vtkTIFFWriter)im_filter = vtkWindowToImageFilter()                   #im_filter.SetInput(self.vtk_widget.GetRenderWindow())  # QVTKRenderWindowInteractorim_filter.SetScale(3)                                  #im_filter.SetInputBufferTypeToRGBA()writer = vtkBMPWriter()#writer = vtkPostScriptWriter()writer.SetFileName('cs.bmp')#writer.SetFileName('cs.ps')writer.SetInputConnection(im_filter.GetOutputPort())writer.Write()def showTrimesh_with_edge(self, mesh: TriMesh):# 添加點points = vtk.vtkPoints()for v in mesh.vs:points.InsertNextPoint(v)# 添加面片c = 255face_color = [c, c, c]polys = vtk.vtkCellArray()cellColor = vtk.vtkUnsignedCharArray()cellColor.SetNumberOfComponents(3)for f in mesh.faces:polys.InsertNextCell(len(f), f)cellColor.InsertNextTuple(face_color)# 添加邊 和 邊的顏色edges = vtk.vtkCellArray()edge_colors = vtk.vtkUnsignedCharArray()edge_colors.SetNumberOfComponents(3)for e in mesh.edges:edges.InsertNextCell(2, e)for edge_labels in mesh.edge_labels:# edge_colors.InsertNextTuple(self.colors[edge_labels])  # colors1edge_colors.InsertNextTuple(self.colors[edge_labels])# 創建PolyDatacube = vtk.vtkPolyData()cube.SetPoints(points)cube.SetPolys(polys)# cube.SetLines(edges)cube.GetCellData().SetScalars(cellColor)# 細分loop = vtk.vtkLoopSubdivisionFilter()# loop = vtk.vtkButterflySubdivisionFilter()# loop = vtk.vtkLinearSubdivisionFilter()loop.SetInputData(cube)loop.SetNumberOfSubdivisions(0)loop.Update()print(loop.GetOutput().GetNumberOfPolys())# 平滑smoothFilter = vtk.vtkSmoothPolyDataFilter()# smoothFilter = vtk.vtkWindowedSincPolyDataFilter()smoothFilter.SetInputConnection(loop.GetOutputPort())# smoothFilter.SetInputData(cube)smoothFilter.SetNumberOfIterations(1)  # 控制平滑次數,次數越大平滑越厲害smoothFilter.Update()# 創建 mapper 和 actorself.mapper = vtk.vtkPolyDataMapper()self.mapper.SetColorModeToDefault()     # 需要設置為默認顏色Mode# self.mapper.SetInputData(cube)# self.mapper.SetInputConnection(loop.GetOutputPort())self.mapper.SetInputConnection(smoothFilter.GetOutputPort())print(smoothFilter.GetOutput().GetNumberOfPolys())self.actor = vtk.vtkActor()self.actor.SetMapper(self.mapper)# 添加邊self.mapper2 = vtk.vtkPolyDataMapper()cube1 = vtk.vtkPolyData()cube1.SetPoints(points)# cube1.SetPolys(edges)cube1.SetLines(edges)cube1.GetCellData().SetScalars(edge_colors)self.mapper2.SetInputData(cube1)self.actor2 = vtk.vtkActor()self.actor2.SetMapper(self.mapper2)# self.actor2.GetProperty().SetEdgeColor(0, 0, 1)self.actor2.GetProperty().SetEdgeVisibility(1)self.actor2.GetProperty().SetLineWidth(4)# 顯示self.vtk_widget.Render()self.vtk_widget.Start()# self.renderer.self.renderer = vtk.vtkRenderer()self.renderer.SetBackground(0.7, 0.7, 0.7)self.renderer.SetBackground2(1, 1, 1)self.renderer.SetGradientBackground(1)# 燈光myLight = vtk.vtkLight()# myLight.SetColor(1, 1, 1)  # 設置燈光的顏色,以RGB的形式指定顏色# myLight.SetPosition(100, 100, 100)  # 設燈光照位置myLight.SetLightType(vtk.VTK_LIGHT_TYPE_HEADLIGHT)#vtk.VTK_LIGHT_TYPE_SCENE_LIGHT#vtk.VTK_LIGHT_TYPE_CAMERA_LIGHT# myLight.SetFocalPoint(self.renderer.GetActiveCamera().GetFocalPoint())  # 設置燈光焦點myLight.SetIntensity(1)      # 可視化邊的時候設置為0.9# myLight.SwitchOff()self.renderer.AddLight(myLight)  # 因為renderer里可以有多個燈光,所以是AddLight() 而不是 SetLight()# self.renderer.Setself.vtk_widget.GetRenderWindow().AddRenderer(self.renderer)self.renderer.AddActor(self.actor)self.renderer.AddActor(self.actor2)self.renderer.ResetCamera()self.vtk_widget.update()def cs(self):# 三角網格vs = np.array([[-1, 1, -0.5],[-1, 0, 0],[-1, -1, -0.5],[0, 0.3, 0],[0, -0.3, 0],[0.5, 0, 0.5]], dtype=np.float32)  # 0.5 -0.5faces = np.array([[4, 1, 3], [4, 1, 2], [0, 3, 1], [3, 5, 4]], dtype=np.int16)# 顏色c = np.array([[0, 1, 1], [0.5, 1, 0.5], [0.5, 1, 0.5], [1, 1, 0.5]]) * 255# 添加點points = vtk.vtkPoints()for v in vs:points.InsertNextPoint(v)# 添加面片polys = vtk.vtkCellArray()for f in faces:polys.InsertNextCell(3, f)cellColor = vtk.vtkUnsignedCharArray()cellColor.SetNumberOfComponents(3)for tmp in c:cellColor.InsertNextTuple(tmp)# 創建PolyDatacube = vtk.vtkPolyData()cube.SetPoints(points)cube.SetPolys(polys)cube.GetCellData().SetScalars(cellColor)# 細分l = vtk.vtkLinearSubdivisionFilter()l.SetInputData(cube)l.SetNumberOfSubdivisions(1)l.Update()loop = vtk.vtkLoopSubdivisionFilter()#loop.SetInputData(l.GetOutputPort())loop.SetInputConnection(l.GetOutputPort())loop.SetNumberOfSubdivisions(5)loop.Update()# 創建Mappermapper = vtk.vtkPolyDataMapper()mapper.SetColorModeToDefault()mapper.SetInputData(cube)mapper.SetInputConnection(loop.GetOutputPort())# 創建actoractor = vtk.vtkActor()actor.SetMapper(mapper)# actor.GetProperty().SetColor([1, 1, 1])# actor.GetProperty().SetEdgeColor(0, 0, 0)actor.GetProperty().SetEdgeVisibility(0)# 燈光myLight = vtk.vtkLight()myLight.SetColor(1, 1, 1)  # 設置燈光的顏色,以RGB的形式指定顏色myLight.SetPosition(0, 0, 1)myLight.SetLightType(vtk.VTK_LIGHT_TYPE_SCENE_LIGHT)# vtk.VTK_LIGHT_TYPE_SCENE_LIGHT# vtk.VTK_LIGHT_TYPE_CAMERA_LIGHTmyLight.SetFocalPoint(self.renderer.GetActiveCamera().GetFocalPoint())  # 設置燈光焦點myLight.SetIntensity(0.5)  # 可視化邊的時候設置為0.9# myLight.SwitchOff()self.renderer.AddLight(myLight)  # 因為renderer里可以有多個燈光,所以是AddLight() 而不是 SetLight()self.renderer.AddActor(actor)self.renderer.ResetCamera()self.vtk_widget.update()

2.4 main

from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from MainWindow.MainWindow import MainWindow
import sysif __name__ == '__main__':app = QApplication(sys.argv)# 加載圖標app.setWindowIcon(QIcon('./Resource/rabbit.ico'))# 加載樣式s = './Resource/blue.css'with open(s, "r") as f:app.setPalette(QPalette(QColor('#EAF7FF')))app.setStyleSheet(f.read())# 顯示mainWindow = MainWindow()mainWindow.show()sys.exit(app.exec_())

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/160544.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/160544.shtml
英文地址,請注明出處:http://en.pswp.cn/news/160544.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Node.js入門指南(一)

目錄 Node.js入門 什么是Node.js Node.js的作用 Node.js安裝 Node.js編碼注意事項 Buffer(緩沖器) 定義 使用 fs模塊 概念 文件寫入 文件讀取 文件移動與重命名 文件刪除 文件夾操作 查看資源狀態 路徑問題 path模塊 Node.js入門 什么是Node.js …

2023最新面試題

第一家 自我介紹介紹一下最近一個(最熟悉的一個)項目 項目幾個人在負責 項目實際在用了嗎,哪個平臺在用啊(在哪里上線) 你認為你自己做的項目里面哪個比較難做呢,項目里面有什么難點?常用的是V…

安卓隱私指示器學習筆記

最近了解到Google 在Android12上新增了權限指示器,可以在信號欄的右側顯示當前訪問錄音機和Camera的應用,點擊后可以跳轉到相應應用的權限界面,消費者可以控制權限的開啟和關閉。國內手機廠商最近幾年都在增加隱私看板供能,消費者…

java 中漢字轉拼音

需要引入的jar <!-- pinyin --><dependency><groupId>com.belerweb</groupId><artifactId>pinyin4j</artifactId><version>2.5.0</version></dependency> 實現工具類 package com.julong.util;import java.util.regex…

編程語言發展史:高級語言的興起

一、高級語言的定義 高級語言是相對于匯編語言而言的&#xff0c;它是一種更加抽象、更加易于理解和使用的計算機編程語言。高級語言的特點是語法簡單、易于學習、易于使用、可讀性強、可移植性好等。高級語言的出現極大地提高了程序員的工作效率&#xff0c;同時也使得計算機…

Qt connect()方法Qt::ConnectionType

connect() Qt&#xff0c;綁定信號和槽原型&#xff1a; static QMetaObject::Connection connect(const QObject *sender, const char *signal,const QObject *receiver, const char *member, Qt::ConnectionType Qt::AutoConnection);static QMetaObject::Connection conn…

JSP:Javabean

起初&#xff0c;JavaBean的目的是為了將可以重復使用的代碼進行打包&#xff0c;在傳統的應用中&#xff0c;JavaBean主要用于實現一些可視化界面&#xff0c;如一個窗體、按鈕、文本框等&#xff0c;這樣的JavaBean稱之可視化的JavaBean。 隨著技術的不斷發展與項目的需求&am…

防火墻部署模式 -- 鏡像流量(旁路模式)

鏡像流量&#xff08;旁路模式&#xff09; 如圖&#xff0c;與單臂路由模式不同&#xff0c;旁路模式中&#xff0c;PC的流量不會流經防火墻&#xff0c;就算防火墻宕機也不會影他們之間的數據傳輸。 鏡像的原理是交換機把被鏡像端口的流量復制一份&#xff0c;發到監聽端口&…

尋找二叉樹最近公共祖先

二叉樹為BST LCR 193. 二叉搜索樹的最近公共祖先 1.1 遞歸 利用BST的性質 p root 或者 q root ,顯然根為公共祖先p < root < q 或者 p > root > q,顯然p&#xff0c;q分別位于root的一顆子樹上&#xff0c;故根為公共祖先max{p,q} < root ,顯然 p 和q 均在…

基于單片機聲光控智能路燈系統仿真設計

**單片機設計介紹&#xff0c; 基于單片機聲光控智能路燈系統仿真設計 文章目錄 一 概要二、功能設計設計思路 三、 軟件設計原理圖 五、 程序六、 文章目錄 一 概要 基于單片機的聲光控智能路燈系統是一種利用單片機技術實現智能控制的路燈系統。它通過感知環境音量和光照強度…

Axios 請求響應結果的結構

發送請求 this.$axios.get(https://apis.jxcxin.cn/api/title?urlhttps://apis.jxcxin.cn/,{params: {id: 10}}).then(res > {console.log(res)})輸出返回結果 confing 請求時的配置對象&#xff0c;如果請求的url&#xff0c;請求的方法&#xff0c;請求的參數&#xff0c…

深入理解Java注解的實現原理以及前世今生

深入理解Java注解的實現原理以及前世今生 小雪初寒&#xff0c;請添衣&#xff0c;冬棋如意&#xff0c;待良人&#xff0c;望歸期。 1.Java注解的前世今生 Java注解是一種元數據標記&#xff0c;它提供了一種在Java代碼中添加元數據&#xff08;注釋&#xff09;的方式。注解…

Linux文件

目錄 一、基本概念 二、研究進程和被打開文件的關系 &#xff08;一&#xff09;w方式 &#xff08;二&#xff09;a方式 三、認識系統接口&#xff0c;操作文件 &#xff08;一&#xff09;認識文件描述符 &#xff08;二&#xff09;舉例 &#xff08;三&#xff09;…

2023年中國油墨樹脂主要環節、產量及市場規模分析[圖]

油墨樹脂是指用于油墨制造中的一種高分子材料&#xff0c;主要用于改善油墨的粘性、流動性、光澤度和耐磨性等性能。其主要成分為合成樹脂&#xff0c;如聚酯、聚酰胺、聚丙烯酸酯等。油墨樹脂在油墨制造中的應用非常廣泛&#xff0c;可以用于各種類型的油墨&#xff0c;包括印…

github訪問不了問題

git clone github上的項目的時候&#xff0c;不是訪問不了&#xff0c;就是克隆過程被中斷了 最近找到一個代理&#xff0c;從代理那里clone而不是github上 GitHub代理 – 初果編程

python BDD 的相關概念

在Python 語言中進行BDD的規格和測試文件的編寫的時候&#xff0c;常常會遇到下面的概念&#xff1a; Fixture : 測試設施。設定測試環境的預設狀態或值的機制。Background&#xff1a; 背景。所有場景的公共部分。Scenario&#xff1a; 場景。Given &#xff1a; 前置條件Whe…

centos7 安裝node.js,不用wget也不用解壓文件

更新系統&#xff1a;首先&#xff0c;更新系統的軟件包列表和已安裝的軟件包。在終端中以root用戶或具有sudo權限的用戶身份運行以下命令&#xff1a; sudo yum update添加Node.js源&#xff1a;CentOS 7默認的軟件倉庫中可能不包含最新的Node.js版本。因此&#xff0c;我們需…

[leetcode 數位運算] 2939. 最大異或乘積 M

給你三個整數 a &#xff0c;b 和 n &#xff0c;請你返回 (a XOR x) * (b XOR x) 的 最大值 且 x 需要滿足 0 < x < 2n。 由于答案可能會很大&#xff0c;返回它對 109 7 取余 后的結果。 注意&#xff0c;XOR 是按位異或操作。 示例 1&#xff1a; 輸入&#xff1…

git中的分支管理:git branch,git checkout,解決git中的分支沖突的方法【Git學習三】

&#x1f601; 作者簡介&#xff1a;一名大四的學生&#xff0c;致力學習前端開發技術 ??個人主頁&#xff1a;夜宵餑餑的主頁 ? 系列專欄&#xff1a;Git等軟件工具技術的使用 &#x1f450;學習格言&#xff1a;成功不是終點&#xff0c;失敗也并非末日&#xff0c;最重要…

vue2 識別頁面參數中的html

在Vue 2中&#xff0c;你可以使用v-html指令來識別頁面參數中的HTML內容。v-html指令允許你將HTML代碼作為Vue模板的一部分進行渲染。 以下是一個示例&#xff0c;演示了如何在Vue 2中使用v-html指令來識別頁面參數中的HTML內容&#xff1a; <template><div v-html&…