VTK随笔十四:QT与VTK的交互示例(平移)
VTK(Visualization Toolkit)是一个开源的软件系统,用于三维计算机图形学、图像处理和可视化。它提供了丰富的工具和类来处理三维数据和交互。在 VTK 中,拾取操作通常通过 vtkCellPicker
或 vtkPointPicker
等类来实现。
本文将展示如何使用 vtkCellPicker
来拾取点,并判断该点是否在多个嵌套的封闭区域内。如果存在多个包含该点的封闭区域,我们将选择离拾取点最近的那个区域。之后可对选择区域进行平移操作。
实现步骤
1. 定义自定义交互器样式
首先,我们需要定义一个自定义的交互器样式类vtkCustomInteractorStyle,继承自 vtkInteractorStyleTrackballCamera
。这个类将处理鼠标点击和移动事件。
vtkCustomInteractorStyle.h
#ifndef VTKCUSTOMINTERACTORSTYLE_H
#define VTKCUSTOMINTERACTORSTYLE_H#include <vtkInteractorStyleTrackballCamera.h>
#include <vector>
#include <vtkPoints.h>
#include <vtkActor.h>
#include <vtkSmartPointer.h>class vtkCustomInteractorStyle : public vtkInteractorStyleTrackballCamera
{
public:static vtkCustomInteractorStyle* New();vtkTypeMacro(vtkCustomInteractorStyle, vtkInteractorStyleTrackballCamera);//左键按下virtual void OnLeftButtonDown() override;//左键抬起virtual void OnLeftButtonUp() override;//右键按下virtual void OnRightButtonDown() override;//右键抬起virtual void OnRightButtonUp() override;//鼠标移动virtual void OnMouseMove() override;protected://构造函数vtkCustomInteractorStyle();//析构~vtkCustomInteractorStyle();private://将选取的屏幕点转为世界坐标double* ComputeWorldPosition(int x, int y);//使用射线法判断点是否在任意多边形内bool IsPointInPolygon(double* point, const std::vector<double*> &polygonPoints);//获取Actor的顶点void GetActorVertices(vtkSmartPointer<vtkActor> actor, std::vector<double*> &polygonPoints);//更新Actor的顶点void UpdateActorPoints(vtkSmartPointer<vtkActor> actor, double dx, double dy);//计算点与多边形顶点的的距离double ComputeDistanceToPolygon(double* point, const std::vector<double*> &polygonPoints);private:vtkSmartPointer<vtkActor> SelectedActor;double InitialPosition[3];double InitialActorPosition[3];double dx;double dy;
};#endif // VTKCUSTOMINTERACTORSTYLE_H
2. 实现自定义交互器样式
接下来,我们实现自定义交互器样式类中的各个方法。
vtkCustomInteractorStyle.cpp
#include "vtkCustomInteractorStyle.h"
#include <vtkObjectFactory.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkCellPicker.h>
#include <vtkPolyDataMapper.h>
#include <vtkPolyData.h>
#include <vtkRenderer.h>
#include <vtkProperty.h>
#include <vtkTransform.h>
#include <vtkTransformPolyDataFilter.h>vtkStandardNewMacro(vtkCustomInteractorStyle);vtkCustomInteractorStyle::vtkCustomInteractorStyle()
{
}vtkCustomInteractorStyle::~vtkCustomInteractorStyle()
{
}void vtkCustomInteractorStyle::OnLeftButtonDown()
{this->SelectedActor = nullptr;dx = 0;dy = 0;int x, y;this->GetInteractor()->GetEventPosition(x, y);double* pickPosition = this->ComputeWorldPosition(x, y);//获取所有ActorvtkSmartPointer<vtkPropCollection> actors = this->CurrentRenderer->GetActors();actors->InitTraversal();vtkSmartPointer<vtkActor> actor = nullptr;vtkSmartPointer<vtkActor> closestActor = nullptr;double minDistance = std::numeric_limits<double>::max();while ((actor = dynamic_cast<vtkActor*>(actors->GetNextProp()))){std::vector<double*> polygonPoints;GetActorVertices(actor, polygonPoints);if (IsPointInPolygon(pickPosition, polygonPoints)){double distance = ComputeDistanceToPolygon(pickPosition, polygonPoints);if (distance < minDistance){minDistance = distance;closestActor = actor;}}// 释放动态分配的内存for (const auto& point : polygonPoints){delete[] point;}polygonPoints.clear();}if (closestActor){this->SelectedActor = closestActor;this->InitialPosition[0] = pickPosition[0];this->InitialPosition[1] = pickPosition[1];this->InitialActorPosition[0] = this->SelectedActor->GetPosition()[0];this->InitialActorPosition[1] = this->SelectedActor->GetPosition()[1];}return;
}void vtkCustomInteractorStyle::OnLeftButtonUp()
{if (this->SelectedActor){UpdateActorPoints(this->SelectedActor, dx, dy);this->SelectedActor = nullptr;}return;
}void vtkCustomInteractorStyle::OnRightButtonDown()
{return;
}void vtkCustomInteractorStyle::OnRightButtonUp()
{return;
}void vtkCustomInteractorStyle::OnMouseMove()
{if (this->SelectedActor){int x, y;this->GetInteractor()->GetEventPosition(x, y);double* pickPosition = this->ComputeWorldPosition(x, y);dx = pickPosition[0] - this->InitialPosition[0];dy = pickPosition[1] - this->InitialPosition[1];this->SelectedActor->SetPosition(this->InitialActorPosition[0] + dx, this->InitialActorPosition[1] + dy, 0.0);this->Interactor->Render();}this->Superclass::OnMouseMove();
}double* vtkCustomInteractorStyle::ComputeWorldPosition(int x, int y)
{vtkSmartPointer<vtkCellPicker> picker = vtkSmartPointer<vtkCellPicker>::New();picker->SetTolerance(0.01);picker->Pick(x, y, 0, this->CurrentRenderer);return picker->GetPickPosition();
}bool vtkCustomInteractorStyle::IsPointInPolygon(double* point, const std::vector<double*> &polygonPoints)
{double x = point[0];double y = point[1];int n = polygonPoints.size();bool inside = false;for (int i = 0, j = n - 1; i < n; j = i++){double xi = polygonPoints[i][0];double yi = polygonPoints[i][1];double xj = polygonPoints[j][0];double yj = polygonPoints[j][1];bool intersect = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);if (intersect){inside = !inside;}}return inside;
}void vtkCustomInteractorStyle::GetActorVertices(vtkSmartPointer<vtkActor> actor, std::vector<double*> &polygonPoints)
{vtkSmartPointer<vtkPolyDataMapper> mapper = dynamic_cast<vtkPolyDataMapper*>(actor->GetMapper());if (!mapper) return;vtkSmartPointer<vtkPolyData> polyData = mapper->GetInput();if (!polyData) return;vtkSmartPointer<vtkPoints> points = polyData->GetPoints();if (!points) return;for (vtkIdType i = 0; i < points->GetNumberOfPoints(); ++i){double point[3] = {0.0};points->GetPoint(i, point);polygonPoints.push_back(new double[3]{point[0], point[1], point[2]});}
}void vtkCustomInteractorStyle::UpdateActorPoints(vtkSmartPointer<vtkActor> actor, double dx, double dy)
{vtkSmartPointer<vtkPolyDataMapper> mapper = dynamic_cast<vtkPolyDataMapper*>(actor->GetMapper());if (!mapper) return;vtkSmartPointer<vtkPolyData> polyData = mapper->GetInput();if (!polyData) return;vtkSmartPointer<vtkPoints> points = polyData->GetPoints();if (!points) return;for (vtkIdType i = 0; i < points->GetNumberOfPoints(); ++i){double point[3] = {0.0};points->GetPoint(i, point);point[0] += dx;point[1] += dy;points->SetPoint(i, point);}polyData->Modified();
}double vtkCustomInteractorStyle::ComputeDistanceToPolygon(double* point, const std::vector<double*> &polygonPoints)
{double x = point[0];double y = point[1];double minDistance = std::numeric_limits<double>::max();for (const auto& polyPoint : polygonPoints){double distance = std::sqrt((polyPoint[0] - x) * (polyPoint[0] - x) + (polyPoint[1] - y) * (polyPoint[1] - y));if (distance < minDistance){minDistance = distance;}}return minDistance;
}
3. 代码解释
3.1 头文件 vtkCustomInteractorStyle.h
- 类声明:定义了一个自定义交互器样式类
vtkCustomInteractorStyle
,继承自vtkInteractorStyleTrackballCamera
。 - 方法声明:
OnLeftButtonDown
:处理左键按下事件。OnLeftButtonUp
:处理左键抬起事件。OnRightButtonDown
和OnRightButtonUp
:处理右键按下和抬起事件。OnMouseMove
:处理鼠标移动事件。
- 辅助方法:
ComputeWorldPosition
:计算鼠标点击位置的世界坐标。IsPointInPolygon
:判断点是否在多边形内。GetActorVertices
:获取 Actor 的顶点。UpdateActorPoints
:更新 Actor 的顶点坐标。ComputeDistanceToPolygon
:计算点到多边形顶点的最小距离。
3.2 源文件 vtkCustomInteractorStyle.cpp
- 构造函数和析构函数:初始化和清理类成员变量。
OnLeftButtonDown
方法:- 获取鼠标点击位置的世界坐标。
- 遍历渲染器中的所有 Actor,获取每个 Actor 的顶点。
- 使用
IsPointInPolygon
判断拾取点是否在多边形内。 - 如果在多边形内,使用
ComputeDistanceToPolygon
计算点到多边形顶点的最小距离,并记录离拾取点最近的 Actor。 - 释放动态分配的内存。
- 设置
SelectedActor
为离拾取点最近的 Actor。
OnLeftButtonUp
方法:- 如果有选中的 Actor,更新其顶点坐标并重置选中状态。
OnRightButtonDown
和OnRightButtonUp
方法:- 调用父类的方法处理右键事件。
OnMouseMove
方法:- 如果有选中的 Actor,根据鼠标移动更新 Actor 的位置。
ComputeWorldPosition
方法:- 使用
vtkCellPicker
获取拾取点的世界坐标。
- 使用
IsPointInPolygon
方法:- 使用射线法判断点是否在多边形内。
GetActorVertices
方法:- 获取 Actor 的顶点坐标。
UpdateActorPoints
方法:- 更新 Actor 的顶点坐标。
ComputeDistanceToPolygon
方法:- 计算点到多边形顶点的最小距离。
4. 使用自定义交互器样式
最后,我们需要在主程序中使用自定义的交互器样式。
首先在QT界面中嵌套VTK窗口,详情见VTK随笔一:初识VTK(QT中嵌入VTK窗口)-CSDN博客
主要代码:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <vtkSmartPointer.h>
#include <vtkPoints.h>
#include <vtkCellArray.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkNamedColors.h>
#include <vtkRegularPolygonSource.h>
#include <vtkCellPicker.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkCommand.h>
#include <vtkCallbackCommand.h>
#include <vtkLine.h>
#include <vtkProperty.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <vtkCamera.h>
#include "vtkCustomInteractorStyle.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);vtkSmartPointer<vtkNamedColors> colors = vtkSmartPointer<vtkNamedColors>::New();// 创建矩形的点集vtkSmartPointer<vtkPoints> rectanglePoints = vtkSmartPointer<vtkPoints>::New();rectanglePoints->InsertNextPoint(0.0, 0.0, 0.0); // 左下角rectanglePoints->InsertNextPoint(1.0, 0.0, 0.0); // 右下角rectanglePoints->InsertNextPoint(1.0, 1.0, 0.0); // 右上角rectanglePoints->InsertNextPoint(0.0, 1.0, 0.0); // 左上角// 创建矩形的线段vtkSmartPointer<vtkCellArray> rectangleLines = vtkSmartPointer<vtkCellArray>::New();vtkSmartPointer<vtkLine> line = vtkSmartPointer<vtkLine>::New();// 左下角到右下角line->GetPointIds()->SetId(0, 0);line->GetPointIds()->SetId(1, 1);rectangleLines->InsertNextCell(line);// 右下角到右上角line->GetPointIds()->SetId(0, 1);line->GetPointIds()->SetId(1, 2);rectangleLines->InsertNextCell(line);// 右上角到左上角line->GetPointIds()->SetId(0, 2);line->GetPointIds()->SetId(1, 3);rectangleLines->InsertNextCell(line);// 左上角到左下角line->GetPointIds()->SetId(0, 3);line->GetPointIds()->SetId(1, 0);rectangleLines->InsertNextCell(line);// 创建矩形的PolyDatavtkSmartPointer<vtkPolyData> rectanglePolyData = vtkSmartPointer<vtkPolyData>::New();rectanglePolyData->SetPoints(rectanglePoints);rectanglePolyData->SetLines(rectangleLines);// 创建矩形的MappervtkSmartPointer<vtkPolyDataMapper> rectangleMapper = vtkSmartPointer<vtkPolyDataMapper>::New();rectangleMapper->SetInputData(rectanglePolyData);// 创建矩形的ActorvtkSmartPointer<vtkActor> rectangleActor = vtkSmartPointer<vtkActor>::New();rectangleActor->SetMapper(rectangleMapper);rectangleActor->GetProperty()->SetColor(colors->GetColor3d("Tomato").GetData());// 创建圆形vtkSmartPointer<vtkRegularPolygonSource> circleSource = vtkSmartPointer<vtkRegularPolygonSource>::New();circleSource->SetNumberOfSides(100); // 多边形近似圆形circleSource->SetRadius(0.5);circleSource->SetCenter(2.0, 0.5, 0.0);circleSource->SetNormal(0.0, 0.0, 1.0);// 创建圆形的MappervtkSmartPointer<vtkPolyDataMapper> circleMapper = vtkSmartPointer<vtkPolyDataMapper>::New();circleMapper->SetInputConnection(circleSource->GetOutputPort());// 创建圆形的ActorvtkSmartPointer<vtkActor> circleActor = vtkSmartPointer<vtkActor>::New();circleActor->SetMapper(circleMapper);circleActor->GetProperty()->SetColor(colors->GetColor3d("Cyan").GetData());// 创建嵌套的矩形vtkSmartPointer<vtkPoints> nestedRectanglePoints = vtkSmartPointer<vtkPoints>::New();nestedRectanglePoints->InsertNextPoint(1.2, 0.2, 0.0); // 左下角nestedRectanglePoints->InsertNextPoint(1.8, 0.2, 0.0); // 右下角nestedRectanglePoints->InsertNextPoint(1.8, 0.8, 0.0); // 右上角nestedRectanglePoints->InsertNextPoint(1.2, 0.8, 0.0); // 左上角// 创建嵌套矩形的线段vtkSmartPointer<vtkCellArray> nestedRectangleLines = vtkSmartPointer<vtkCellArray>::New();line = vtkSmartPointer<vtkLine>::New();// 左下角到右下角line->GetPointIds()->SetId(0, 0);line->GetPointIds()->SetId(1, 1);nestedRectangleLines->InsertNextCell(line);// 右下角到右上角line->GetPointIds()->SetId(0, 1);line->GetPointIds()->SetId(1, 2);nestedRectangleLines->InsertNextCell(line);// 右上角到左上角line->GetPointIds()->SetId(0, 2);line->GetPointIds()->SetId(1, 3);nestedRectangleLines->InsertNextCell(line);// 左上角到左下角line->GetPointIds()->SetId(0, 3);line->GetPointIds()->SetId(1, 0);nestedRectangleLines->InsertNextCell(line);// 创建嵌套矩形的PolyDatavtkSmartPointer<vtkPolyData> nestedRectanglePolyData = vtkSmartPointer<vtkPolyData>::New();nestedRectanglePolyData->SetPoints(nestedRectanglePoints);nestedRectanglePolyData->SetLines(nestedRectangleLines);// 创建嵌套矩形的MappervtkSmartPointer<vtkPolyDataMapper> nestedRectangleMapper = vtkSmartPointer<vtkPolyDataMapper>::New();nestedRectangleMapper->SetInputData(nestedRectanglePolyData);// 创建嵌套矩形的ActorvtkSmartPointer<vtkActor> nestedRectangleActor = vtkSmartPointer<vtkActor>::New();nestedRectangleActor->SetMapper(nestedRectangleMapper);nestedRectangleActor->GetProperty()->SetColor(colors->GetColor3d("Lime").GetData());// 创建渲染器并添加Actor到渲染器vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();renderer->AddActor(rectangleActor);renderer->AddActor(circleActor);renderer->AddActor(nestedRectangleActor);renderer->SetBackground(colors->GetColor3d("SlateGray").GetData());renderer->AddActor(rectangleActor);renderer->ResetCamera();// 设置自定义交互器样式vtkSmartPointer<vtkCustomInteractorStyle> style = vtkSmartPointer<vtkCustomInteractorStyle>::New();style->SetCurrentRenderer(renderer);vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();renderWindow->AddRenderer(renderer);ui->widget->setRenderWindow(renderWindow);ui->widget->interactor()->SetInteractorStyle(style);// 渲染renderWindow->Render();
}MainWindow::~MainWindow()
{delete ui;
}
5. 代码解释
5.1 创建几何对象
- 矩形:使用
vtkPoints
和vtkCellArray
创建矩形的顶点和线段。 - 圆形:使用
vtkRegularPolygonSource
创建一个近似的圆形。 - 嵌套矩形:创建一个嵌套在矩形内的较小矩形。
5.2 创建Mapper和Actor
- 矩形:将
vtkPolyData
设置到vtkPolyDataMapper
中,然后将vtkPolyDataMapper
设置到vtkActor
中。 - 圆形:将
vtkRegularPolygonSource
的输出设置到vtkPolyDataMapper
中,然后将vtkPolyDataMapper
设置到vtkActor
中。 - 嵌套矩形:将
vtkPolyData
设置到vtkPolyDataMapper
中,然后将vtkPolyDataMapper
设置到vtkActor
中。
5.3 设置Actor的名称
- 为每个 Actor 设置名称,方便调试和识别。
5.4 添加Actor到渲染器
- 将所有 Actor 添加到渲染器中,并设置背景颜色。
5.5 渲染并启动交互
- 渲染场景并启动交互器,使用户可以通过鼠标进行操作。
6. 运行效果
运行上述代码后,你将看到一个包含矩形、圆形和嵌套矩形的 3D 场景。当你点击场景中的某个点时,程序会判断该点是否在多个封闭区域内,并选择离拾取点最近的那个区域。选中的区域将被移动,以响应鼠标移动事件。
7. 总结
本文介绍了如何在 VTK 中实现拾取点并获取离拾取点最近的包含该点的封闭区域。通过定义自定义交互器样式类 vtkCustomInteractorStyle
,我们可以处理鼠标点击和移动事件,并使用 vtkCellPicker
获取拾取点的世界坐标。通过遍历所有 Actor 并计算点到多边形顶点的最小距离,我们可以准确地选择离拾取点最近的区域。
这种方法在处理复杂的嵌套几何体时非常有用,可以确保用户选择的是最内层的区域。希望这篇文章对你在使用 VTK 进行三维图形渲染和交互有所帮助!
相关文章:
VTK随笔十四:QT与VTK的交互示例(平移)
VTK(Visualization Toolkit)是一个开源的软件系统,用于三维计算机图形学、图像处理和可视化。它提供了丰富的工具和类来处理三维数据和交互。在 VTK 中,拾取操作通常通过 vtkCellPicker 或 vtkPointPicker 等类来实现。 本文将展示…...
用户注册(阿里云手机验证码)
阿里云开通三网106短信 ①、在阿里云市场搜索“短信”,开通三网短信,并可以查看其中的请求示例(java PHP^) 并在个人中心的管理控制台中查到,获取其中的AppKey AppCode ②、接口开发 service-user模块中依赖spr…...
【BFT帝国】20250409更新PBFT总结
2411 2411 2411 Zhang G R, Pan F, Mao Y H, et al. Reaching Consensus in the Byzantine Empire: A Comprehensive Review of BFT Consensus Algorithms[J]. ACM COMPUTING SURVEYS, 2024,56(5).出版时间: MAY 2024 索引时间(可被引用): 240412 被引:…...
学习海康VisionMaster之边缘交点
一:进一步学习了 今天学习下VisionMaster中的边缘交点,这个还是拟合直线的衍生应用,可以同时测量两条直线并且输出交点或者判定是否有交点 二:开始学习 1:什么是边缘交点? 按照传统的算法,必须…...
公司级项目-AD9914扫频源(三)评估板与上位机的初步调试
硬件平台搭建1-评估板与上位机 第一阶段,先使用评估板配套的上位机软件进行控制,学习一下各种功能的实现方式和寄存器配置方式。 硬件连接 需要的设备仪器包括:多路直流稳压电源、信号发生器、示波器、电脑。 按照图中的方式进行连接&am…...
技术优化实战解析:Stream重构与STAR法则应用指南
目录 一、真实案例背景:老代码的"历史厚重感" 二、屎山代码解剖课:这些写法到底烂在哪? 三、Stream流式重构:给老代码做个大保健 2.1 重构后代码实现 2.2 核心API技术拆解 2.3 进阶优化技巧 三、STAR法则技术文档…...
基于Qt的串口通信工具
程序介绍 该程序是一个基于Qt的串口通信工具,专用于ESP8266 WiFi模块的AT指令配置与调试。主要功能包括: 1. 核心功能 串口通信:支持串口开关、参数配置(波特率、数据位、停止位、校验位)及数据收发。 AT指令操作&a…...
Xilinx FPGA XCZU5EV‑2FBVB900I Zynq UltraScale+™ MPSoC EV 系列
XCZU5EV‑1FBVB900I XCZU5EV‑2FBVB900E XCZU5EV‑1FBVB900I 是 Xilinx Zynq UltraScale™ MPSoC EV 系列中功能最为丰富的器件之一,采用 16 nm FinFET 工艺,封装为 31 mm 31 mm、900‑ball FCBGA(FBVB900)。该系列在传统的…...
如何更改OCP与metadb集群的连接方式 —— OceanBase运维管理
背景 许多用户都会借助OCP平台来进行OceanBase集群的运维与监控,且因为考虑单节点的OCP部署,在遇故障时可能会短时间出现无法管控 OceanBase集群,多数用户倾向于采用多节点方式来部署OCP,即 OCP的 metadb集群也是三节点的集群部署…...
Databricks: Why did your cluster disappear?
You may found that you created a cluster many days ago, and you didnt delete it, but it is disapear. Why did this happen? Who deleted the cluster? Actually, 30 days after a compute is terminated, it is permanently deleted automaticlly. If your workspac…...
深入解析Java内存与缓存:从原理到实践优化
一、Java内存管理:JVM的核心机制 1. JVM内存模型全景图 ┌───────────────────────────────┐ │ JVM Memory │ ├─────────────┬─────────────────┤ │ Thread │ 共享…...
macos下 ragflow二次开发环境搭建
参考官网链接 https://ragflow.io/docs/dev/launch_ragflow_from_source虚拟环境 git clone https://github.com/infiniflow/ragflow.git cd ragflow/ # if not pipx, please install it at first pip3 install pipxpipx install uv uv sync --python 3.10 --all-extras 安装 …...
从 Excel 到你的表格应用:条件格式功能的嵌入实践指南
一、引言 在日常工作中,面对海量数据时,如何快速识别关键信息、发现数据趋势或异常值,是每个数据分析师面临的挑战。Excel的条件格式功能通过自动化的视觉标记,帮助用户轻松应对这一难题。 本文将详细介绍条件格式的应用场景&am…...
安徽京准:NTP网络时钟服务器功能及同步模式的介绍
安徽京准:NTP网络时钟服务器功能及同步模式的介绍 安徽京准:NTP网络时钟服务器功能及同步模式的介绍 1、NTP网络时钟服务器概念: NTP时钟服务器,表面意思是时间计量工具的服务设备,其在现代工业中是用于对客户端设备…...
基于ueditor编辑器的功能开发之百度编辑器自带的查找和替换功能无法对目标文字进行滚动定位修复
在查找百度编辑器的查找和替换功能,发现当页面文字过多,用户在检索文字点击上一个下一个的时候,滚动条不跟随滚动了 分析了ueditor关于searchpalce方法的处理时,他会在目标文字的前面插入一个span标签用户获取当前需要高亮的文字节…...
MYSQL——SQL语句到底怎么执行
查询语句执行流程 MySQL 查询语句执行流程 查询缓存(Query Cache) MySQL内部自带了一个缓存模块,默认是关闭的。主要是因为MySQL自带的缓存应用场景有限。 它要求SQL语句必须一摸一样表里面的任何一条数据发生变化时,该表所有缓…...
[蓝桥杯 2022 省 B] 李白打酒加强版
题目链接: 思路: ①定义dp数组,f[i][j][k],表示经过 i 店, 遇到 j 花, 还有 k 酒。如果酒的数量超过了花的数量,那么一定喝不完。因此,k 不能超过 M。 ②从店推过来,f[…...
计算机视觉——图像金字塔与目标图像边缘检测原理与实践
一、两个图像块之间的相似性或距离度量 1.1 平方差和(SSD) 平方差和(SSD) 是一种常用的图像相似性度量方法。它通过计算两个图像在每个对应位置的像素值差的平方和来衡量两个图像之间的整体差异。如果两个图像在每个位置的像素值…...
复现QGIS-MCP教程
由于Claude国内下载不了尝试使用Cursor 下载安装Cursor Cursor - The AI Code Editor 本示例安装的是0.46版本 UV安装 简介 安装 安装成功 配置环境变量 验证 下载代码 git clone gitgithub.com:jjsantos01/qgis_mcp.git QGIS插件安装 文件拷贝 您需要将 qgis_mcp_plu…...
人工智能图像识别Spark Core
Spark Core 一.spark运行架构 1.运行架构 Spark 框架的核心是一个计算引擎,整体来说,它采用了标准 master-slave 的结构。 如下图所示,它展示了一个 Spark 执行时的基本结构。图形中的 Driver 表示 master,负责管理整个集群中的作…...
决策树+泰坦尼克号生存案例
决策树简介 学习目标 1.理解决策树算法的基本思想 2.知道构建决策树的步骤 【理解】决策树例子 决策树算法是一种监督学习算法,英文是Decision tree。 决策树思想的来源非常朴素,试想每个人的大脑都有类似于if-else这样的逻辑判断,这其中…...
怎么查看苹果手机和ipad的设备信息和ios udid
你知道吗?我们每天使用的iPhone和iPad,其实隐藏着大量详细的硬件与系统信息。除了常见的系统版本和序列号外,甚至连电池序列号、摄像头序列号、销售地区、芯片型号等信息,也都可以轻松查到! 如果你是开发者、维修工程…...
智能驱动教育变革:人工智能在高中教育中的实践路径与创新策略
一、引言 随着信息技术的飞速发展,人工智能(Artificial Intelligence, AI)已成为推动社会进步的重要力量。在教育领域,人工智能的应用正逐渐改变着传统的教学模式和方法,为教育现代化注入了新的活力。高中教育作为教育…...
TCP 和 UDP 可以使用同一个端口吗?
TCP 和 UDP 可以使用同一个端口吗? 前言 在深入探讨 TCP 和 UDP 是否可以使用同一个端口之前,我们首先需要理解网络通信的基本原理。网络通信是一个复杂的过程,涉及到多个层次的协议和机制。在 OSI 模型中,传输层是负责端到端数…...
MySQL事务管理
MySQL事务管理 事务的概念 事务由一条或多条SQL语句组成,这些语句在逻辑上存在相关性,共同完成一个任务,事务主要用于处理操作量大,复杂度高的数据。比如转账就涉及多条SQL语句,包括查询余额(select&…...
通过 SSH 方式访问 GitHub 仓库
我们来一步一步讲解如何让 Git 通过 SSH 方式访问 GitHub 仓库,包括从零开始的详细步骤,适用于大多数系统(Linux、macOS、Windows Git Bash)。 注意最好只用 Git bash 比较好!他能够直接在 Windows 系统上面使用一些 L…...
数据库学习
DDL(数据定义语言)、DML(数据操纵语言)、DQL(数据查询语言)和DCL(数据控制语言)。 DDL用于创建、删除和修改数据库对象,如表和数据库;DML涉及数据的增删改操…...
DeepSeek在安全领域的应用案例全景解析
DeepSeek作为人工智能领域的标杆技术,已在网络安全、公共安全、工业安全、军事防护等领域形成系统性应用。以下从六大核心场景展开分析,结合技术实现与行业标杆案例,呈现其多维度的安全赋能价值。 一、网络安全防护体系创新 威胁检测与响应闭环安胜"星盾"平台:通…...
AI驱动SEO关键词精准定位
内容概要 在传统SEO实践中,关键词定位往往依赖人工经验与有限的数据样本,导致策略滞后性与覆盖盲区并存。随着AI技术的深度介入,这一过程正经历系统性重构:从搜索意图的智能识别到关键词的自动化挖掘,算法模型通过分析…...
邮件营销:如何巧妙平衡发送频率与客户体验
在邮件营销领域,发送频率和客户体验就像跷跷板的两端,需要精心平衡。如果邮件发得太多,客户可能会觉得烦,甚至取消订阅,对品牌产生不好的印象;但如果发得太少,客户又容易把你忘了,错…...
Acrel-1000DP分布式光伏监控系统在嘉兴亨泰新能源有限公司2996.37KWP分布式光伏项目中的应用
摘 要:分布式光伏发电系统其核心特点是发电设备靠近用电负荷中心,通常安装在屋顶、建筑立面或闲置空地上,截至2025年,分布式光伏发电系统在全球和中国范围内取得了显著发展,成为能源转型和可持续发展的重要推动力量。国…...
vue3中左右布局两个个组件使用vuedraggable实现左向右拖动,右组件列表可上下拖动
需求:左侧是个菜单组件,有对应的表单类型。 右侧是渲染组件,点击左侧菜单或者拖动即可渲染出对应的组件 项目中采用vuedraggable实现拖拽功能。 具体实现是使用elementplus的组件,然后根据tagName的类型去渲染不同的组件。 首先…...
gevent 高并发、 RabbitMQ 消息队列、Celery 分布式的案例和说明
1. gevent 高并发请求示例 gevent:基于协程的Python库,通过异步非阻塞模式实现高并发请求。例如,同时抓取100个网页时,无需等待每个请求完成,提升效率。 import gevent from gevent import monkey monkey.patch_…...
直线模组在电子行业具体的应用
在工业自动化高速发展的今天,直线模组作为重要的传动和控制元件,凭借其高效、精准、稳定的特性。在众多行业中得到了广泛应用,尤其是在电子行业中,通过提供精确的运动控制和定位,帮助提高电子制造过程的效率、质量和自…...
Ubuntu 24.04启用root账户
1.启用ubuntu中的root账号 ubuntu默认是禁用了root账号的,需要手动开始root权限 # 设置root账号密码 sudo passwd root # 用以下命令启用 root 账户: sudo usermod -aG sudo rootsu - root 然后输入你之前设置的 root 密码。 一旦你成功登录为 root 用户&#x…...
【ES系列】Elasticsearch简介:为什么需要它?(基础篇)
🔥 本文将详细介绍Elasticsearch的前世今生,以及为什么它在当今的技术栈中如此重要。本文是ES起飞之路系列的基础篇第一章,适合想要了解ES的读者。 文章目录 一、什么是Elasticsearch?1. ES的定义2. ES的核心特性2.1 分布式存储2.2 实时搜索2.3 高可用性2.4 RESTful API3.…...
SvelteKit 最新中文文档教程(19)—— 最佳实践之身份认证
前言 Svelte,一个语法简洁、入门容易,面向未来的前端框架。 从 Svelte 诞生之初,就备受开发者的喜爱,根据统计,从 2019 年到 2024 年,连续 6 年一直是开发者最感兴趣的前端框架 No.1: Svelte …...
Droris(强制)删除某一个分区数据
Doris如果想删除某一个分区的数据,可以这么操作: DROP PARTITION [IF EXISTS] partition_name [FORCE]需要注意的是: 必须为使用分区的表保留至少一个分区。执行DROP PARTITION一段时间后,可以通过RECOVER语句恢复被删除的分区:…...
Meta 最新 AI 模型系列 ——Llama 4
Meta 发布了最新 AI 模型系列 ——Llama 4,这是其 Llama 家族的最新成员。 在大模型竞技场(Arena),Llama 4 Maverick 的总排名第二,成为第四个突破 1400 分的大模型。其中开放模型排名第一,超越了 DeepSeek…...
软考 系统架构设计师系列知识点 —— 设计模式之工厂模式
本文内容参考: 软考 系统架构设计师系列知识点之设计模式(2)_系统架构设计师中考设计模式吗-CSDN博客 https://baike.baidu.com/item/%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F?fromModulelemma_search-box 设计模式-工厂方法模式࿰…...
Jetpack Compose 状态保存机制全面解析:让UI状态持久化
在Android开发中,Jetpack Compose 的状态管理是一个核心话题,而状态保存则是确保良好用户体验的关键。本文将深入探讨Compose中各种状态保存技术,帮助你在配置变更和进程重建时保持UI状态。 一、基础保存:rememberSaveable reme…...
阿里云原生AI网关Higress:架构解析与应用实践
摘要 随着云原生与AI技术的深度融合,API网关作为流量治理的核心组件,正面临新的挑战与机遇。阿里云开源的Higress网关,凭借其“三网合一”(流量网关、微服务网关、安全网关)的高集成能力,以及面向AI场景的…...
如何在数据仓库中集成数据共享服务?
目录 1. Snowflake 数据共享服务:云端的最佳实践 2. 数据共享服务的重要性 3. 麦聪 QuickAPI:企业本地的理想选择 4. 云端与本地的互补 总结 数据共享服务是现代数据仓库的核心功能,能够提升协作效率、降低成本并释放数据潜力。 以 Sno…...
spark RDD相关概念和运行架构
核心概念 - RDD定义:弹性分布式数据集,是Spark中基础数据处理抽象,具弹性、不可变、可分区及并行计算特性。 弹性 存储的弹性:内存与磁盘的自动切换; 容错的弹性:数据丢失可以自动恢复; 计算…...
2025.04.09【Sankey】| 生信数据流可视化精讲
文章目录 引言Sankey图简介R语言中的Sankey图实现安装和加载networkD3包创建Sankey图的数据结构创建Sankey图绘制Sankey图 结论 引言 在生物信息学领域,数据可视化是理解和分析复杂数据集的关键工具之一。今天,我们将深入探讨一种特别适用于展示数据流动…...
《系统分析师-案例实践篇-16-22章总结》
案例实践篇...
spark core
Executor的核心功能 运行任务:Executor负责运行组成Spark应用的任务,并将结果返回给驱动器进程。 缓存管理:Executor通过自身的块管理器为用户程序中要求缓存的RDD提供内存或存储。 Master和Worker的角色 Master:负责资源调度和分…...
crawl4ai的实践(爬虫)
1.准备环境 !pip install -U crawl4ai !pip install nest_asynciocrawl4ai-setup 验证是否安装成功 # Check crawl4ai version import crawl4ai print(crawl4ai.__version__.__version__) 验证是否可以爬 crawl4ai-doctor 2.简单示例 import asyncio from playwright.as…...
Python从入门到精通全套视频教程免费
概述 📢 所有想学Python的小伙伴看过来!作为深耕编程领域的技术分享者,最新整理了一份Python从0到1的视频教程。 💡亮点 ✅ 保姆级系统路线:从环境搭建、语法精讲,到爬虫/数据分析/AI/Web全栈开发&#…...
Node.js是js语言在服务器编译运行的环境,什么是IP和域名
一句话结论 Node.js 不是语言也不是框架,而是一个让 JavaScript 能运行在服务器端的“环境”(类似 Python 的解释器)。JavaScript 是语言,Node.js 是它的“执行工具”。 🌰 用 Python 类比理解 Python 和 JavaScript …...