Pixyz Studio 和 Pixyz Scenario Processor 使用入门

介绍

Pixyz产品官网
下载、安装与技术文档

官网介绍:Pixyz 支持超过 45 种工业文件格式,包括 CATIA、JT、STEP、IFC、PVZ、NWD、USD 及 glTF。包括 CAD、曲面细分/网格模型、点云等。Unity 中的资产将实时关联到原始数据,可自动更新文件的修改。在 Unity 中创建 LOD 和 UV、合并和拆解网格、更改枢轴等,构建随时可用的资产。无需重新导入即可在 Unity 编辑器中优化任何数据。

有 4 条产品线:

  1. pixyz studio:独立的软件工具
    • 导入/转换 CAD、网格和点云数据
    • 优化/导出数据
    • 利用 Python API 自动完成任务
  2. pixyz plugin:安装于 unity 的插件,专门为 unity 定制,在导出CAD模型并导入unity的流程上优于从 studio 导出再导入unity
    • 将 CAD/3D/BIM 数据导入到 Unity
    • 保留层级结构与元数据
    • 用规则引擎自动运行脚本
  3. Pixyz Review
    • 拖放 CAD、网格或点云数据
    • 一键进入虚拟现实
    • 在模型上进行研究与互动
  4. Pixyz Scenario Processor
    • 批量转换、优化模型
    • 在 AWS Cloud 或单机上运行
    • 提供扩展可能

版本对比

版本的不同版本对比,可以看到每次的更新内容和情况

支持的文件格式

支持导入、导出的文件格式可见文档:Import/Export 的文件格式

请添加图片描述请添加图片描述

入门使用

只介绍pixyz studio、pixyz Scenario Processor的一些简单的内容。

Pixyz Studio

独立的软件,拥有可视化界面,安装完成并且激活(可以免费试用)后,可以进行模型处理。
请添加图片描述

包含最基本的导入、导出等功能

导入

左上角,点击小箭头,可以选择 Guided import 或者 Raw import
请添加图片描述

选择 Guided Import 之后,可以选择文件,并且根据预设进行配置,选择读取的质量、坐标设置、导入点线等

请添加图片描述

点击 Execute 开始导入模型

此时,可以看到模型的左下角 Output 开始输出,是在导入模型过程中执行的命令(executing command xxxxx),例如,这里导入执行了:

executing command process.guidedImport
executing command scene.deleteEmptyAnimation
executing command scene.applyTransformation
executing command scene.cleanUnusedMaterials
executing command scene.removeSymmetryMatrices

请添加图片描述

导入后,可以在左侧 Occurrences 中看到模型的树状结构:
请添加图片描述

在中间最大的 Viewer 窗口中可视化地看见模型

其它功能

顶部导航栏有常见的CAD、面片、模型优化等功能

请添加图片描述

下面以减面为例(Decimate To Target):

可以选择对某个 occurrence 下所属的子结构进行减面,如果不选的话默认就是根目录(Root),减面策略(Target Strategy)可以选择:

  1. Triangle Count:减到某个数量的三角面片(默认10000个)
  2. Ratio:减到一定比例(默认50%)

请添加图片描述

这里设置减面到50%(Ratio),选择 Execute 之后,开始减面。

同样,在Output中可以看到减面的执行过程和结果:

请添加图片描述

导出

点击Export可以将导入的模型导出,导出的时候会根据你设置的文件类型进行转换

请添加图片描述

因此,只要先导入某个格式的模型再导出另一个格式,即可完成模型的类型转换

例如,导入’.fbx’,导出 ‘.prefab’,即可以把 fbx 的模型转化成为 unity 的预制体(prefab)

在左下角的 Output中可以看到执行了导出命令:

请添加图片描述

执行 python 脚本

可以看到在 Output 旁边有一个 Scripting 窗口,可以用于编写和运行python脚本

请添加图片描述

点击 “+” 可以新建一个python脚本,点击 Sample Scripts 会打开本地的文件夹,在安装 Pixyz Studio 时,同时也下载了脚本样例,可以打开每个样例查看学习
请添加图片描述

例如,101_GenericProcess.py

# Pixyz Python API sample (2022.1)
#
# 101 Generic Process
#
# Example of a typical simple process to transform a CAD model into optimized mesh(es)from pxz import *def process():allScene = [scene.getRoot()]# repair CAD with 0.1mm tolerancealgo.repairCAD(allScene, 0.1, True)	# tessellates with maxSag=0.2mm and maxAngle=10degalgo.tessellate(allScene, 0.2, -1, 10)# repairs with a tolerance of 0.1mmalgo.repairMesh(allScene, 0.1)# removes through holes with diameter under 10mmalgo.removeHoles(allScene, True, False, False, 10)# removes hidden patchesalgo.hiddenRemoval(allScene,algo.SelectionLevel.Patches, 1024, 16)# deletes patches to allow the decimation to remesh over the base CAD patchesalgo.deletePatches(allScene)# decimates with surfacic tolerance to 1mm, lineic tolerance to 0.1mm and normal distorsion tolerance to 5mmalgo.decimate(allScene, 1, 0.1, 5)# processes the model
process()

可以把这行代码复制到 Script 窗口中执行

更多可以查看官方给出的 Python 的 api

但是在 Pixyz Studio 中有一个更为简单的方法,在之前的界面执行任务的过程中,可以看到每一个单独的窗口上都有一个按钮:Copy python code to clipboard,比如导入窗口、减面窗口:

请添加图片描述

请添加图片描述

点击Copy python code to clipboard 按钮后,可以将代码复制到 Script 窗口中:

导入模型的 python 代码:

_ret_ = process.guidedImport(["D:/furniture_knoll_for_offices.dwg"], pxz.process.CoordinateSystemOptions(["automaticOrientation",0], ["automaticScale",0], False, False), ["usePreset",2], pxz.process.ImportOptions(False, True, True), True, True, False, False, False, False)

对模型减面的 python 代码:

algo.decimateTarget([1], ["ratio",50.000000000000], 0, False, 5000000)

点击运行后,可以得到与用可视化面板来减面相同的效果:
请添加图片描述

通过脚本可以进行统一流程化的处理,但是在导入导出时还是会有一些小问题。

想要对多个模型进行批处理,可以使用 Pixyz Scenario Processor

Pixyz Scenario Processor

如何运行 Pixyz Scenario Processor

参考官方文档: 如何运行 Pixyz Scenario Processor

目前参考 windows 的命令,有两种执行方式:

  1. python script:直接当成 python 脚本执行
  2. plugin:编译成 .pxzext 的插件使用

它还给出了 Scenario 的脚本样例,下面直接参考 gitlab 库内的代码进行魔改。

Scenario Processor sample

仓库内有三个主要的文件夹,readme 里给了一段介绍(写得很抽象),根据个人理解解释一下:

  1. Folder Watcher : 监测本地硬盘上的文件夹,所有放到这个文件夹里的文件都会执行某个 python 脚本,进行相应的操作
    2a. Scenario sample:把某个 python 脚本发布(publish)成插件执行
    2b. Folder watcher with Scenario:配合 2a 发布的插件,执行插件内的脚本,进行相应的操作

请添加图片描述

总而言之,1 和 2a+2b 的效果是一样的,一个是 python script,一个是 plugin,可以根据个人需要选择不同的执行方法

必备软件:

  1. Pixyz Scenario Processor
  2. Pixyz Studio:用于创建和发布插件
  3. 记得安装和配置好 python 的路径,保证可以在命令行中通过 python xxx.py 执行脚本。

准备工作:

  1. 把整个仓库拉到本地
  2. 去申请 Pixyz Scenario Processor 的试用许可证,申请与激活方法,很重要!!!
Python Script

打开 1_Folder watcher, 它的目录结构为:

│   config.json
│   run.bat
├───scripts
│       sampleScript.py
│       watcher.py
├───_input
└───_output

运行 run.bat 即可执行 sampleScript.py,对模型进行处理

文件的运行逻辑:

  1. run.bat 是批处理脚本,双击运行run.bat ,用编辑器打开可以看到:
python scripts/watcher.py config.json
pause

其中调用的是python命令,输入的第0个参数是脚本 scripts/watcher.py,运行 scripts 目录下的 watcher.py 脚本,输入的第1个参数是 config.json,一个配置文件

如果没有把python配置为系统的默认环境,也可以在能够运行python的命令行(cmd,powershell)中输入python scripts/watcher.py config.json来执行代码

  1. config.json:配置文件,打开可以看到它的配置
{"input_folder":  "_input/","output_folder": "_output/","optimization":  "True","extensions":[".pxz",".fbx",".glb",".pdf",".usdz",".obj",".3dxml"]
}
  • 输入文件夹为:_input/
  • 输出文件夹为:_output/
  • optimization为True,表示需要优化
  • extensions表示接受的模型的类型为:.pxz.fbx.glb.pdf.usdz.obj.3dxml,如果有额外需要的类型,可以在这里添加,可以删除不需要的类型
  1. watcher.py:对文件夹进行监控,while(1) 的死循环,只要 _input 文件夹中有文件,且已经复制完毕(isCopyFinished),就执行 executeScenarioProcessor
import sys
import json
import os
import subprocess
from ctypes import windlldef main(config_file):# 读取输入参数# 输入文件夹 input_folder、输出文件 output_folder、后缀 extensions、是否要优化 optimizationinput_folder, output_folder, extensions, optimization = read_config(config_file)waiting = Falsewhile(1):# 从 input_folder 中读取文件文件 input_filesinput_files = [file for file in os.listdir(input_folder)\if (os.path.isfile(input_folder + '/' + file)\and getFileExtension(file) not in ['.xml', ''])]# 如果 input_folder 中没有文件了,就不处理,继续等待if len(input_files) == 0:if not waiting:print('\n')print('Waiting for files to process...\n')waiting = Truecontinue# 如果 input_folder 有文件,但是还没有复制完,不处理,继续等待elif not isCopyFinished(input_folder + '/' + input_files[0]):continue# 如果 input_folder 有文件,且已经复制完了,停止等待,开始处理文件else:waiting = False# 目前正在处理的文件 input_file 的路径:输入文件夹路径 + 第0个文件名input_file = input_folder + '/' + input_files[0]# 开始处理文件executeScenarioProcessor(input_file, output_folder, extensions, optimization)# 处理完文件后,把文件删除,否则会一直处理这个文件,真的陷入死循环了os.remove(input_file)def read_config(config_file):# 打开配置文件 config.json,加载内容到 inputswith open(config_file) as config:inputs = json.load(config)# 读取输入文件夹 "input_folder" 对应的字段input_folder = inputs['input_folder']input_folder = os.path.abspath(input_folder) # 读取输出文件夹 "output_folder" 对应的字段output_folder = inputs['output_folder'] output_folder = os.path.abspath(output_folder)# 读取输出后缀 "extensions" 对应的字段extensions = inputs['extensions']# 读取输出优化选项 "optimization" 对应的字段optimization = inputs['optimization']print('\n')print('Input folder: %s\n' % input_folder)print('Output folder: %s\n' % output_folder)print('Extensions: %s\n' % ' '.join(extensions))print('Optimization: %s\n' % optimization)return input_folder, output_folder, extensions, optimization# 判断文件是否复制完成的函数
def isCopyFinished(inputFile):"""Check if the file that was dropped in the input folder has finished being copied"""GENERIC_WRITE         = 1 << 30FILE_SHARE_READ       = 0x00000001OPEN_EXISTING         = 3FILE_ATTRIBUTE_NORMAL = 0x80handle = windll.Kernel32.CreateFileW(inputFile, GENERIC_WRITE, FILE_SHARE_READ, None, OPEN_EXISTING,\FILE_ATTRIBUTE_NORMAL, None)if handle != -1:windll.Kernel32.CloseHandle(handle)return Truereturn False# 获取文件的后缀
def getFileExtension(file):return os.path.splitext(file)[1]# 用 PiXYZScenarioProcessor 执行命令,核心步骤
def executeScenarioProcessor(input_file, output_folder, extensions, optimization):# 注意:把 PiXYZScenarioProcessor.exe 的路径换成自己本地的路径args = ['C:\Program Files\PiXYZScenarioProcessor\PiXYZScenarioProcessor.exe', 'scripts/sampleScript.py', input_file, output_folder, str(extensions), str(optimization)]print(sys.argv[0])print(args)# 启动子进程运行指令p = subprocess.Popen(args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)while p.poll() is None:l = str(p.stdout.readline().rstrip()) # This blocks until it receives a newline.print(l)print(p.stdout.read())if __name__ == "__main__":main(sys.argv[1])

如果不需要对 input 文件夹实时监控,不需要删除 input 文件夹里的模型,只是将 input 里所有的模型转化成 output 文件夹里的,可以简化上述代码为:

import sys
import json
import os
import subprocessdef main(config_file):input_folder, output_folder = read_config(config_file)input_files = [file for file in os.listdir(input_folder)\if (os.path.isfile(input_folder + '/' + file)\and getFileExtension(file) not in ['.xml', ''])]print(input_files)if len(input_files)>0:for i in range(len(input_files)):print("-"*30, i, input_files[i], "-"*30)input_file = input_folder + '/' + input_files[i]executeScenarioProcessor(input_file, output_folder)def read_config(config_file):with open(config_file) as config:inputs = json.load(config)input_folder = inputs['input_folder']input_folder = os.path.abspath(input_folder) output_folder = inputs['output_folder'] output_folder = os.path.abspath(output_folder)print('\n')print('Input folder: %s\n' % input_folder)print('Output folder: %s\n' % output_folder)return input_folder, output_folderdef getFileExtension(file):return os.path.splitext(file)[1]def try_decode_bytes(b):for encoding in ['utf-8', 'gbk']:try:return b.decode(encoding, errors="ignore")except Exception as e:passreturn '{}'.format(b)def executeScenarioProcessor(input_file, output_folder, extensions, optimization):args = ['C:\Program Files\PiXYZScenarioProcessor\PiXYZScenarioProcessor.exe', 'scripts/sampleScript.py', input_file, output_folder, str(extensions), str(optimization)]print(sys.argv[0])print(args)p = subprocess.Popen(args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)while p.poll() is None:l = str(p.stdout.readline().rstrip()) # This blocks until it receives a newline.print(l)print(p.stdout.read())if __name__ == "__main__":main(sys.argv[1])
  1. sampleScript.py
import os
import time
import sysdef convertFile(inputFile, outputFolder, extensions, optimization):fileName = getFileNameWithoutExtension(inputFile)# Set log file in output folder for debug purposes (otherwise it will be overwritten by next 3d file processing)core.setLogFile(outputFolder + '/' + fileName + '.log')# Imports and prepares the input_files using the automatic "Guided import" process (see documentation)roots = process.guidedImport([inputFile], pxz.process.CoordinateSystemOptions(["automaticOrientation",0], ["automaticScale",0], False, True), ["usePreset",2], pxz.process.ImportOptions(False, True, True), False, False, False, False, False, False)if optimization:# Comment or delete the lines not necessary to your workflow, adjust parameters' values if necessaryt0, n_triangles, n_vertices, n_parts = getStats(roots[0])# Automatically selects and deletes parts in the scene, whose size is lower than a maximum size defined in by the parameter Size (in millimeters)SIZE = 20scene.selectByMaximumSize(roots, SIZE, -1, False)scene.deleteSelection()# Removes through holes from CAD models whose diameter is below the defined diameterDIAMETER = 10algo.removeHoles(roots, True, False, False, DIAMETER, 0)# Deletes patches borders (black lines delimiting CAD models' faces) to allow decimation (run in the next step) to be more efficient. Otherwise, patches borders are considered as important information to preserve.algo.deletePatches(roots, True)# Reduces meshes density (triangles count) by decimating them, using the "Decimate To Quality" function (see documentation). The values used here are meant to decimate meshes just enough to lower the triangles count without affecting the visual quality too much, especially on CAD models.algo.decimate(roots, 1, 0.1, 3, -1, False)# Removes triangles not visible from a set of cameras automatically placed around the model.algo.hiddenRemoval(roots, 2, 1024, 16, 90, False, 1)t1, _n_triangles, _n_vertices, _n_parts = getStats(roots[0])# Export filesfor extension in extensions:io.exportScene(outputFolder + '/' + fileName + extension)if optimization:printStats(fileName, t1 - t0, n_triangles, _n_triangles, n_vertices, _n_vertices, n_parts, _n_parts)def getFileNameWithoutExtension(file):return os.path.splitext(os.path.basename(file))[0]def getStats(root):core.configureInterfaceLogger(False, False, False) # hide next lines from logst = time.time()n_triangles = scene.getPolygonCount([root], True, False, False)n_vertices = scene.getVertexCount([root], False, False, False)n_parts = len(scene.getPartOccurrences(root))core.configureInterfaceLogger(True, True, True) # reenable logsreturn t, n_triangles, n_vertices, n_partsdef printStats(fileName, t, n_triangles, _n_triangles, n_vertices, _n_vertices, n_parts, _n_parts):print('\n')print('{:<20s}{:<3s}\n'.format('file ', fileName))print('{:<20s}{:<8.3f}{:<3s}\n'.format('optimization ', t, ' s'))print('{:<20s}{:<3s}\n'.format('triangles ', str(n_triangles) + ' -> ' + str(_n_triangles)))print('{:<20s}{:<3s}\n'.format('vertices ', str(n_vertices) + ' -> ' + str(_n_vertices)))print('{:<20s}{:<3s}\n'.format('parts ', str(n_parts) + ' -> ' + str(_n_parts)))# Get arguments passed in command line and call main function
if __name__ == "__main__":convertFile(sys.argv[1], sys.argv[2], eval(sys.argv[3]), eval(sys.argv[4]))

解读:

watcher.pyexecuteScenarioProcessor 函数中,封装了输入参数:

args = ['C:\Program Files\PiXYZScenarioProcessor\PiXYZScenarioProcessor.exe', 'scripts/sampleScript.py', input_file, output_folder, str(extensions), str(optimization)]

分别对应 sampleScript.py 中的 argv:

if __name__ == "__main__":convertFile(sys.argv[1], sys.argv[2], eval(sys.argv[3]), eval(sys.argv[4]))

即:

  • sys.argv[1] = input_file
  • sys.argv[2] = output_folder
  • eval(sys.argv[3]) = extensions
  • eval(sys.argv[4])) = optimization

利用 guidedImport ,将 inputFile 导入,返回存储到 roots 中

	# Imports and prepares the input_files using the automatic "Guided import" process (see documentation)roots = process.guidedImport([inputFile], pxz.process.CoordinateSystemOptions(["automaticOrientation",0], ["automaticScale",0], False, True), ["usePreset",2], pxz.process.ImportOptions(False, True, True), False, False, False, False, False, False)

之后便是对 roots 的一系列操作,例如:统计 roots 下的三角面片数量、顶点数量、part数量(也许part可以翻译成部件?)

t0, n_triangles, n_vertices, n_parts = getStats(roots[0])def getStats(root):core.configureInterfaceLogger(False, False, False) # hide next lines from logst = time.time()n_triangles = scene.getPolygonCount([root], True, False, False)n_vertices = scene.getVertexCount([root], False, False, False)n_parts = len(scene.getPartOccurrences(root))core.configureInterfaceLogger(True, True, True) # reenable logsreturn t, n_triangles, n_vertices, n_parts

选择并删除某些parts

SIZE = 20
scene.selectByMaximumSize(roots, SIZE, -1, False)
scene.deleteSelection()

其它的可以参考官方给出的 Python 的 api 和 studio 里自带的样例

Plugin

发布成插件的脚本和上述是一个脚本,但是需要分两步:

  1. 打开 2a_Scenario sample,把 sampleScript.py 发布插件,把插件放到 PiXYZScenarioProcessor\plugins 目录下
  2. 打开 2b_Folder watcher with Scenario,用 run.bat 执行 watcher.py,运行插件

2a_Scenario sample 的目录结构如下:

│   publish.bat
│   sample.pxzext
└───sample│   plugin.xml└───scriptssampleScript.py
  1. sampleScript.py 和 1_Folder watcher 最大的差别就是,少了执行代码:
# Get arguments passed in command line and call main function
if __name__ == "__main__":convertFile(sys.argv[1], sys.argv[2], eval(sys.argv[3]), eval(sys.argv[4]))
  1. plugin.xml 中指定了执行的函数function为convertFile,输入的参数 parameters:
<?xml version="1.0" encoding="utf-8" ?>
<module name="sample" version="2021.1.1.5"><include module="Core"/><include module="IO"/><function name="convertFile" state="Stable" scriptable="true" guiable="true" description="" logName="" scriptFile="sampleScript.py"><parameters><parameter name="inputFile" type="ImportFilePath" state="Stable"/><parameter name="outputFolder" type="OutputDirectoryPath" state="Stable"/><parameter name="extensions" type="StringList" state="Stable"/><parameter name="optimization" type="Bool" state="Stable"/></parameters></function>
</module>
  1. publish.bat 中指定了使用 PiXYZStudioPiXYZStudioPublishPlugin 来发布插件(注意:这里需要用到 PiXYZStudio 下的PiXYZStudioPublishPlugin.exe,而不是之前的 PiXYZScenarioProcessor.exe

编译的文件夹为 sample,编译出的插件名字为 sample.pxzext,并且之后将 sample.pxzext 复制到 PiXYZScenarioProcessor 目录下的 plugins 目录中

PiXYZStudioPiXYZScenarioProcessor 的路径都改为自己本地的,也可以依次执行,然后手动把编译出的 sample.pxzext 放到 PiXYZScenarioProcessor\plugins 下面

rem Compile plugin sources
"C:\Program Files\PiXYZStudio\PiXYZStudioPublishPlugin.exe" "%cd%\sample" "%cd%\sample.pxzext"rem Copy scenario plugin in SP installation folder
copy "%cd%\sample.pxzext" "C:\ProgramData\PiXYZScenarioProcessor\plugins\"pause

编译完成,将 sample.pxzext 放到 PiXYZScenarioProcessor\plugins 下面之后,可以打开2b_Folder watcher with Scenario

2b_Folder watcher with Scenario 的目录结构为:

│   config.json
│   run.bat
├───scripts
│       watcher.py
├───_input
└───_output

和 1 的差别是在scripts下面的 sampleScript.py 此时变成了PiXYZScenarioProcessor\plugins\sample.pxzext

watcher.py 和 1 的最大差别是输入的参数 args 变了:

1_Folder watcher\scripts\watcher.py

args = ['C:\Program Files\PiXYZScenarioProcessor\PiXYZScenarioProcessor.exe', 'scripts/sampleScript.py', input_file, output_folder, str(extensions), str(optimization)]

2b_Folder watcher with Scenario\scripts\watcher.py

args = ['C:\Program Files\PiXYZScenarioProcessor\PiXYZScenarioProcessor.exe', 'sample', 'convertFile', "\"" + input_file.replace("\\", "\\\\") + "\"", "\"" + output_folder.replace("\\", "\\\\") + "\"", str(extensions), "\"" + str(optimization) + "\""]

输入的 sample, convertFile 和 plugin.xml 中指定的 modulefunction 对应

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

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

相关文章

【每日一题】—— D. Divide and Equalize(Codeforces Round 903 (Div. 3))(数学、数论)

&#x1f30f;博客主页&#xff1a;PH_modest的博客主页 &#x1f6a9;当前专栏&#xff1a;每日一题 &#x1f48c;其他专栏&#xff1a; &#x1f534; 每日反刍 &#x1f7e1; C跬步积累 &#x1f7e2; C语言跬步积累 &#x1f308;座右铭&#xff1a;广积粮&#xff0c;缓称…

堆栈与堆(Stack vs Heap):有什么区别?

程序内存大致分四块如下&#xff1a; 下面以两个例子来解释堆栈和堆如何在程序中体现&#xff1a; #include <iostream>int add(int a, int b){int sum a b;return aum; }int main(){int x 5;int result add(x, 10);std::cout << "Result: " <&l…

<JavaEE> 经典设计模式之 -- 单例模式(“饿汉模式”和“懒汉模式”实现单例模式)

目录 一、单例模式概述 二、“饿汉模式”实现单例模式 三、“懒汉模式”实现单例模式 3.1 单线程下的“懒汉模式” 3.2 多线程下的“懒汉模式” 一、单例模式概述 1&#xff09;什么是单例模式&#xff1f; 单例模式是一种设计模式。 单例模式可以保证某个类在程序中只存…

HarmonyOS4.0从零开始的开发教程05 应用程序入口—UIAbility的使用

HarmonyOS&#xff08;三&#xff09;应用程序入口—UIAbility的使用 UIAbility概述 UIAbility是一种包含用户界面的应用组件&#xff0c;主要用于和用户进行交互。UIAbility也是系统调度的单元&#xff0c;为应用提供窗口在其中绘制界面。 每一个UIAbility实例&#xff0c;…

利用R语言heatmap.2函数进行聚类并画热图

数据聚类然后展示聚类热图是生物信息中组学数据分析的常用方法&#xff0c;在R语言中有很多函数可以实现&#xff0c;譬如heatmap,kmeans等&#xff0c;除此外还有一个用得比较多的就是heatmap.2。最近在网上看到一个笔记文章关于《一步一步学heatmap.2函数》&#xff0c;在此与…

[RK-Linux] 移植Linux-5.10到RK3399(四)| 检查HDMI配置与打开内核LOGO显示

文章目录 一、HDMI二、VOP三、显示内核LOGO一、HDMI RK3399 的 HDMI 接口如图: datasheet 介绍: HDMI 接口各个引脚的作用如下: 接口标签作用HDMI_TX0P HDMI_TX0PA差分信号线,用于传输 HDMI 通道 0 的正向数据HDMI_TX0N HDMI_TX0NA

算法___

文章目录 算法两数之和 算法 两数之和 题目如下图&#xff1a; 我的答案如下图&#xff1a; 我采用的是最笨的思路&#xff0c;直接暴力的两次循环&#xff0c;第一次外循环是取数组的第一个元素&#xff0c;然后内循环会遍历数组后面除第一个的所有元素&#xff0c;然后和…

Python-Opencv图像处理的小坑

1.背景 最近在做一点图像处理的事情&#xff0c;在做处理时的cv2遇到一些小坑&#xff0c;希望大家遇到的相关的问题可以注意&#xff01;&#xff01; 2. cv2.imwrite保存图像 cv2.imwrite(filename, img, [params]) filename&#xff1a;需要写入的文件名&#xff0c;包括路…

代码随想录算法训练营 ---第五十八天

今天开启单调栈的征程。 第一题&#xff1a; 简介&#xff1a; 本题有两种解法&#xff0c;第一种&#xff1a;暴力破解 两层for循环 时间复杂度为O(n^2) 超时了 第二种&#xff1a;单调栈解法也是今天的主角。 单调栈是什么&#xff1f; 单调递增栈&#xff1a;单调递增栈…

计算机操作系统4

1.什么是进程同步 2.什么是进程互斥 3.进程互斥的实现方法(软件) 4.进程互斥的实现方法(硬件) 5.遵循原则 6.总结&#xff1a; 线程是一个基本的cpu执行单元&#xff0c;也是程序执行流的最小单位。 调度算法&#xff1a;先来先服务FCFS、短作业优先、高响应比优先、时间片…

大数据项目——基于Django/协同过滤算法的房源可视化分析推荐系统的设计与实现

大数据项目——基于Django/协同过滤算法的房源可视化分析推荐系统的设计与实现 技术栈&#xff1a;大数据爬虫/机器学习学习算法/数据分析与挖掘/大数据可视化/Django框架/Mysql数据库 本项目基于 Django框架开发的房屋可视化分析推荐系统。这个系统结合了大数据爬虫、机器学…

第七次作业

1&#xff0c; 给定一个包含n1个整数的数组nums&#xff0c;其数字在1到n之间&#xff08;包含1和n)&#xff0c;可知至少存在一个重复的整数&#xff0c;假设只有一个重复的整数&#xff0c;请找出这个重复的数 arr input("") num [int(n) for n in arr.split()]…