osg实现鼠标框选

目录

1. 需求的提出

2. 具体实现

     2.1. 禁止场景跟随鼠标转动

     2.2. 矩形框前置绘制

3. 附加说明

        3.1. 颜色设置说明

        3.2.矩形框显示和隐藏的另一种实现


1. 需求的提出

       有时需要在屏幕通过按住键盘上的某个键如Ctrl键且按住鼠标左键,拖出一个矩形,实现框选三维物体,如下效果:

现在的问题是:

  1. 在osg中,拖动鼠标时,物体会随鼠标一起转动,这样框选是不行的,至少是不友好的,我们需要的是,按住鼠标框选时,物体不能随鼠标一起转动。
  2. 如何根据鼠标拖动的起始点和终止点,绘制出这个矩形框?矩形框要在所有三维物体的前面而不能被三维物体遮挡且要是透明的,能透过它看到背后的三维物体,否则框选就失去了意义。
  3. 按住鼠标右键,矩形框消失。

2. 具体实现

     2.1. 禁止场景跟随鼠标转动

        对第1节中提到的第1个问题,默认情况下osgViewer::Viewer事件处理器在鼠标左键按下并拖动时,整个场景会随鼠标一起转动。为了不让转动,可以通过改写osgViewer::Viewer osgGA::GUIEventHandler事件处理器,重载如下方法:

 virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa, osg::Object* obj, osg::NodeVisitor*nv)

当按住键盘上的某个键如Ctrl键且按住鼠标左键,让该函数返回true,这样后续的流程就不会处理鼠标拖动事件,三维物体也就不会跟随鼠标旋转了。

     2.2. 矩形框前置绘制

         矩形框要绘制在所有三维物体的前面而不能被三维物体遮挡,这就要用到三维中的HUD技术(Head Up Display)。所谓HUD节点,说白了就是无论三维场景中的内容怎么改变,它都能在屏幕上固定位置显示的节点。实现要点:

  • 关闭光照,不受场景光照影响,所有内容以同一亮度显示。
  • 关闭深度测试。
  • 调整渲染顺序,使它的内容最后绘制。
  • 设定参考贴为绝对型:setReferenceFrame(osg::Transform:ABSOLUTE_RF)。
  • 使其不受父节点变换的影响:setMatrix(osg::Matrix::identity())。
  • 使用平行投影,设定虚拟投影窗口的大小,这个窗口的大小决定了后面绘制的图形和文字的尺度比例。

  实现代码如下:

#include<osgViewer/Viewer>
#include<osg/ShapeDrawable>
#include<osgDB/readFile>
#include<osg/BlendFunc>
class selectBoxEventHandler: public osgGA::GUIEventHandler
{
public:selectBoxEventHandler(osg::ref_ptr<osg::Camera> spHudCamera){m_spHudCamera = spHudCamera;}
private:virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa, osg::Object* obj, osg::NodeVisitor*nv){m_pViewer = (osgViewer::Viewer*)(&aa);if (m_pViewer == nullptr){return false;}auto width = m_pViewer->getCamera()->getViewport()->width();auto height = m_pViewer->getCamera()->getViewport()->height();/* 设置HUD相机为正投影,这样绘制的矩形框和鼠标拖动的框选框大小就一样了且要设置正投影的区域和视图窗体一样大小,因为鼠标可以在窗体任何位置进行框选*/m_spHudCamera->setProjectionMatrix(osg::Matrix::ortho2D(0, width, 0, height));auto eventType = ea.getEventType();switch (eventType){case osgGA::GUIEventAdapter::KEYDOWN:{if ((osgGA::GUIEventAdapter::KEY_Control_L == ea.getKey()) || (osgGA::GUIEventAdapter::KEY_Control_R == ea.getKey())) // Ctrl键被按下{m_ctrlKeyPressed = true;}}break;case osgGA::GUIEventAdapter::KEYUP:{if ((osgGA::GUIEventAdapter::KEY_Control_L == ea.getKey())|| (osgGA::GUIEventAdapter::KEY_Control_R == ea.getKey())) // Ctrl键被释放{m_ctrlKeyPressed = false;}}break;case osgGA::GUIEventAdapter::PUSH:  // 鼠标左键按下{auto buttonMask = ea.getButtonMask();auto bIsMouseBtn = buttonMask & osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON;if (bIsMouseBtn){m_fStartPosX = ea.getX();m_fStartPosY = ea.getY();m_bPush = true;}else if (buttonMask & osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON) // 鼠标右键按下,则删除选择框{if (m_spOldNode != nullptr){m_spHudCamera->removeChild(m_spOldNode);}}}break;case osgGA::GUIEventAdapter::RELEASE:  // 释放鼠标左键{m_bPush = false;}break;case osgGA::GUIEventAdapter::DRAG:    // 拖动鼠标{auto buttonMask = ea.getButtonMask();auto bIsMouseBtn = buttonMask & osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON;if (bIsMouseBtn && m_ctrlKeyPressed && m_bPush){m_fEndPosX = ea.getX();m_fEndPosY = ea.getY();auto pSelectBox = createSelectBox(m_fStartPosX, m_fStartPosY, m_fEndPosX, m_fEndPosY);if (m_spOldNode != nullptr){m_spHudCamera->removeChild(m_spOldNode);}m_spHudCamera->addChild(pSelectBox);m_spOldNode = pSelectBox;return true;}}} // end swithreturn  false;}osg::Geode* createSelectBox(float fStartPosX, float fStartPosY, float fEndPosX, float fEndPosY){osg::Geode* pGeode = new osg::Geode();auto pQuardGeomerty = new osg::Geometry();pGeode->addChild(pQuardGeomerty);osg::Vec3Array* pVertArray = new osg::Vec3Array;pVertArray->push_back(osg::Vec3(fStartPosX, fStartPosY, 0.0));pVertArray->push_back(osg::Vec3(fStartPosX, fEndPosY, 0.0));pVertArray->push_back(osg::Vec3(fEndPosX, fEndPosY, 0.0));pVertArray->push_back(osg::Vec3(fEndPosX, fStartPosY, 0.0));pQuardGeomerty->setVertexArray(pVertArray);osg::Vec4Array* pColorArray = new osg::Vec4Array;pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.4));/*  pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.40));pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.40));pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.40));*/pQuardGeomerty->setColorArray(pColorArray);//pQuardGeomerty->setColorBinding(osg::Geometry::AttributeBinding::BIND_PER_VERTEX);pQuardGeomerty->setColorBinding(osg::Geometry::AttributeBinding::BIND_PER_PRIMITIVE_SET);pQuardGeomerty->addPrimitiveSet(new osg::DrawArrays(GL_QUADS, 0, 4));pGeode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); // 关闭光照pGeode->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON); // 开启透明,否则就不能透过选择框看到后面的牛pGeode->addDrawable(pQuardGeomerty);return pGeode;}private:/* 鼠标按下的起始坐标点 */float m_fStartPosX{0.0};float m_fStartPosY{ 0.0 };float m_fEndPosX{ 0.0 };float m_fEndPosY{ 0.0 };bool m_ctrlKeyPressed{false};             // Ctrl键被按下bool m_bPush{false};                      // 鼠标左键是否被按下osgViewer::Viewer* m_pViewer{nullptr};osg::ref_ptr<osg::Camera> m_spHudCamera;  // 用于HUD的相机osg::ref_ptr<osg::Node> m_spOldNode;      // 上次鼠标框选绘制出的矩形框};
int main(int argc, char *argv[])
{osgViewer::Viewer viewer;auto cowNode = osgDB::readNodeFile(R"(E:\osg\OpenSceneGraph-Data\cow.osg)");if (nullptr == cowNode){OSG_WARN << "node is null!";return 1;}auto spRoot = new osg::Group();osg::ref_ptr<osg::Camera> spHudCamera = new osg::Camera;spHudCamera->setClearMask(GL_DEPTH_BUFFER_BIT);  // 关闭深度缓冲// 设置渲染顺序为后渲染,即始终在其它绘制物体的上面,防止被其它绘制的物体遮挡spHudCamera->setRenderOrder(osg::Camera::RenderOrder::POST_RENDER); spHudCamera->setAllowEventFocus(false);  // 不接受任何焦点事件,即不响应键盘、鼠标事件spHudCamera->setReferenceFrame(osg::Transform::ReferenceFrame::ABSOLUTE_RF); // 设置参考帧为绝对帧spHudCamera->setViewMatrix(osg::Matrix::identity()); // 设置相机视图矩阵为单位矩阵,这样就矩形框选框就不受相机旋转等变换影响spRoot->addChild(cowNode);spRoot->addChild(spHudCamera);viewer.setSceneData(spRoot);viewer.addEventHandler(new selectBoxEventHandler(spHudCamera));return viewer.run();
}

3. 附加说明

        3.1. 颜色设置说明

              2.2节代码对颜色的设置,也可以按如下代码一样达到同样的效果:

 osg::Vec4Array* pColorArray = new osg::Vec4Array;pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.4));pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.40));pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.40));pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.40));pQuardGeomerty->setColorArray(pColorArray);pQuardGeomerty->setColorBinding(osg::Geometry::AttributeBinding::BIND_PER_VERTEX);

也就是说设置一个顶点的颜色且颜色绑定方式为BIND_PER_PRIMITIVE_SET和分别设置4个顶点颜色,颜色绑定方式为BIND_PER_VERTEX效果相同。关于BIND_PER_PRIMITIVE_SET和BIND_PER_VERTEX的具体含义和不同点,请参考:osg图元绑定方式总结博文。

        3.2.矩形框显示和隐藏的另一种实现

       上面矩形框的显示和隐藏是通过removeChild和addChild函数来实现的,即将新的矩形框节点加入到相机作为其子节点之前,删除上次创建的矩形框节点。也可以通过osg::Node的setNodeMask函数来实现,如下为更改后的代码:

#include<osgViewer/Viewer>
#include<osg/ShapeDrawable>
#include<osgDB/readFile>
#include<osg/BlendFunc>#define HIDE_SELECT_BOX 0X0
#define  SHOW_SELECT_BOX ~HIDE_SELECT_BOXclass selectBoxEventHandler : public osgGA::GUIEventHandler
{
public:selectBoxEventHandler(osg::ref_ptr<osg::Camera> spHudCamera){m_spHudCamera = spHudCamera;}
private:virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa, osg::Object* obj, osg::NodeVisitor* nv){m_pViewer = (osgViewer::Viewer*)(&aa);if (m_pViewer == nullptr){return false;}auto width = m_pViewer->getCamera()->getViewport()->width();auto height = m_pViewer->getCamera()->getViewport()->height();/* 设置HuD相机为正投影,这样绘制的矩形框和鼠标拖动的框选框大小就一样了且要设置正投影的区域和视图窗体一样大小,因为鼠标可以在窗体任何位置进行框选*/m_spHudCamera->setProjectionMatrix(osg::Matrix::ortho2D(0, width, 0, height));auto eventType = ea.getEventType();switch (eventType){case osgGA::GUIEventAdapter::KEYDOWN:{if ((osgGA::GUIEventAdapter::KEY_Control_L == ea.getKey())|| (osgGA::GUIEventAdapter::KEY_Control_R == ea.getKey())) // Ctrl键被按下{m_ctrlKeyPressed = true;}}break;case osgGA::GUIEventAdapter::KEYUP:{if ((osgGA::GUIEventAdapter::KEY_Control_L == ea.getKey())|| (osgGA::GUIEventAdapter::KEY_Control_R == ea.getKey())) // Ctrl键被按下{m_ctrlKeyPressed = false;}}break;case osgGA::GUIEventAdapter::PUSH:  // 鼠标左键按下{auto buttonMask = ea.getButtonMask();auto bIsMouseBtn = buttonMask & osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON;if (bIsMouseBtn){m_fStartPosX = ea.getX();m_fStartPosY = ea.getY();m_bPush = true;}else if (buttonMask & osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON) // 鼠标右键按下,则删除选择框{if (m_spRectGeometry != nullptr){m_spRectGeometry->setNodeMask(HIDE_SELECT_BOX);}}}break;case osgGA::GUIEventAdapter::RELEASE:  // 释放鼠标左键{m_bPush = false;}break;case osgGA::GUIEventAdapter::DRAG:    // 拖动鼠标{auto buttonMask = ea.getButtonMask();auto bIsMouseBtn = buttonMask & osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON;if (bIsMouseBtn && m_ctrlKeyPressed && m_bPush){m_fEndPosX = ea.getX();m_fEndPosY = ea.getY();if (nullptr != m_spRectGeometry){auto pVertArray = (osg::Vec3Array*)m_spRectGeometry->getVertexArray();(*pVertArray)[0].set(m_fStartPosX, m_fStartPosY, 0.0);(*pVertArray)[1].set(m_fStartPosX, m_fEndPosY, 0.0);(*pVertArray)[2].set(m_fEndPosX, m_fEndPosY, 0.0);(*pVertArray)[3].set(m_fEndPosX, m_fStartPosY, 0.0);// m_spRectGeometry->setVertexArray(pVertArray);m_spRectGeometry->dirtyDisplayList(); // 告知底层,外层顶点数据更改了,否则不会用新的坐标绘制矩形m_spRectGeometry->setNodeMask(SHOW_SELECT_BOX);}else{auto spSelectBox = createSelectBox(m_fStartPosX, m_fStartPosY, m_fEndPosX, m_fEndPosY);m_spRectGeometry = spSelectBox->asGeode()->getChild(0)->asGeometry();m_spHudCamera->addChild(spSelectBox);}return true;}}} // end swithreturn  false;}osg::Geode* createSelectBox(float fStartPosX, float fStartPosY, float fEndPosX, float fEndPosY){osg::Geode* pGeode = new osg::Geode();auto pQuardGeomerty = new osg::Geometry();pGeode->addChild(pQuardGeomerty);osg::Vec3Array* pVertArray = new osg::Vec3Array;pVertArray->push_back(osg::Vec3(fStartPosX, fStartPosY, 0.0));pVertArray->push_back(osg::Vec3(fStartPosX, fEndPosY, 0.0));pVertArray->push_back(osg::Vec3(fEndPosX, fEndPosY, 0.0));pVertArray->push_back(osg::Vec3(fEndPosX, fStartPosY, 0.0));pQuardGeomerty->setVertexArray(pVertArray);osg::Vec4Array* pColorArray = new osg::Vec4Array;pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.4));/*  pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.40));pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.40));pColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 0.40));*/pQuardGeomerty->setColorArray(pColorArray);//pQuardGeomerty->setColorBinding(osg::Geometry::AttributeBinding::BIND_PER_VERTEX);pQuardGeomerty->setColorBinding(osg::Geometry::AttributeBinding::BIND_PER_PRIMITIVE_SET);pQuardGeomerty->addPrimitiveSet(new osg::DrawArrays(GL_QUADS, 0, 4));pGeode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); // 关闭光照pGeode->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON); // 开启透明,否则就不能透过选择框看到后面的牛pGeode->addDrawable(pQuardGeomerty);return pGeode;}private:/* 鼠标按下的起始坐标点 */float m_fStartPosX{ 0.0 };float m_fStartPosY{ 0.0 };float m_fEndPosX{ 0.0 };float m_fEndPosY{ 0.0 };bool m_ctrlKeyPressed{ false };             // Ctrl键被按下bool m_bPush{ false };                      // 鼠标左键是否被按下osgViewer::Viewer* m_pViewer{ nullptr };osg::ref_ptr<osg::Camera> m_spHudCamera;  // 用于HUD的相机osg::ref_ptr<osg::Geometry> m_spRectGeometry;      // 矩形框};int main(int argc, char *argv[])
{osgViewer::Viewer viewer;auto cowNode = osgDB::readNodeFile(R"(E:\osg\OpenSceneGraph-Data\cow.osg)");if (nullptr == cowNode){OSG_WARN << "node is null!";return 1;}auto spRoot = new osg::Group();osg::ref_ptr<osg::Camera> spHudCamera = new osg::Camera;spHudCamera->setClearMask(GL_DEPTH_BUFFER_BIT);  // 开启深度缓冲// 设置渲染顺序为后渲染,即始终在其它绘制物体的上面,防止被其它绘制的物体遮挡spHudCamera->setRenderOrder(osg::Camera::RenderOrder::POST_RENDER); spHudCamera->setAllowEventFocus(false);  // 不接受任何焦点事件,即不响应键盘、鼠标事件spHudCamera->setReferenceFrame(osg::Transform::ReferenceFrame::ABSOLUTE_RF); // 设置参考帧为绝对帧spHudCamera->setViewMatrix(osg::Matrix::identity()); // 设置相机视图矩阵为单位矩阵,这样就矩形框选框就不受相机旋转等变换影响spRoot->addChild(cowNode);spRoot->addChild(spHudCamera);viewer.setSceneData(spRoot);viewer.addEventHandler(new selectBoxEventHandler(spHudCamera));return viewer.run();
}

说明

  • 在鼠标拖动坐标改变重新设置矩形框坐标时,记得调用:           
// 告知底层,外层顶点数据更改了,否则不会用新的坐标绘制矩形 
m_spRectGeometry->setVertexArray(pVertArray);

或调用:

 m_spRectGeometry->dirtyDisplayList(); // 告知底层,外层顶点数据更改了,否则不会用新的坐标绘制矩形

在C++中,只要把指针指向的内容改了,也就是立马改了,但在上述代码中如果以为只把顶点数据改了,新矩形就会呈现出来是错误的,不调用上述代码中的某一种,新矩形不会绘制,因为只改了顶点数据,但osg还没执行重绘。

  • 上述采用节点的setNodeMask函数,通过设置节点掩码来实现矩形框的显示或隐藏,其实最好的方法是采用osg::Switch来控制矩形框的显示和隐藏,在此不再详述列出代码,关于这两者的详述,参见:osg利用setNodeMask和Switch隐藏节点用法说明博文。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

[Machine learning][Part3] numpy 矢量矩阵操作的基础知识

很久不接触数学了&#xff0c;machine learning需要用到一些数学知识&#xff0c;这里在重温一下相关的数学基础知识 矢量 矢量是有序的数字数组。在表示法中&#xff0c;矢量用小写粗体字母表示。矢量的元素都是相同的类型。例如&#xff0c;矢量不包含字符和数字。数组中元…

vertx的学习总结7

这里我就简单的聊几句&#xff0c;如何用vertx web来搞一个web项目的 1、首先先引入几个依赖&#xff0c;这里我就用maven了&#xff0c;这个是kotlinvertx web <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apac…

Modelsim测试覆盖率操作说明

1、打开Project窗口界面 2、在project界面下&#xff0c;选中所有需要测试覆盖率的.v文件&#xff08;不包括tb文件&#xff09;&#xff0c;鼠标点击右键&#xff0c;在Properties选项中选择Coverage选项&#xff0c;选择需要测试的覆盖率类型 3、重新编译所有的源文件&#x…

(三) Markdown插入互联网或本地视频解决方案

前言 不论博客系统是WordPress还是Typecho&#xff0c;绕不开的是两种书写语言&#xff0c;一种称之为富文本&#xff0c;一种叫做Markdown。 Markdown有很多好处&#xff0c;也有很多坏处&#xff0c;比如Markdown本身不具备段落居中的功能&#xff0c;以及Markdown也不具有…

Java架构师职责和技能

目录 1 架构师简介2 架构师职责2.1 架构师是技术领导架构设计做决策2.2 架构师可以是团队或者组织2.3 架构师必须掌握足够的技术知识2.4 架构师必须掌握足够的架构设计技能2.5 架构师必须具备很好的编程能力2.6 架构师必须深入理解业务及其业务的领域知识2.7架构师应该具备很好…

基于Java的驾校收支管理可视化平台设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…

二层VLAN配置实验

四台PC的IP地址如图所示&#xff0c;子网掩码均为255.255.255.0&#xff0c;四台PC处在同一个局域网之中&#xff0c;在配置VLAN之前能够彼此ping通。配置的目的是将PC1和PC3划分到VLAN10中&#xff0c;PC2和PC4划分到VLAN20中。 在配置之前需要进入系统视角。 创建VLAN 在两…

设计加速!11个Adobe XD插件推荐!

你是否一直在寻找可以提升 Adobe XD 工作流程和体验的方法&#xff1f;如果是&#xff0c;一定要试试这些 Adobe XD 插件&#xff01;本文将介绍 11 款好用的 Adobe XD 插件&#xff0c;这些插件可以为 UI/UX 设计添加很酷的新功能&#xff0c;极大提升你的工作效率和产出。让我…

SQL与关系数据库基本操作

SQL与关系数据库基本操作 文章目录 第一节 SQL概述一、SQL的发展二、SQL的特点三、SQL的组成 第二节 MySQL预备知识一、MySQL使用基础二、MySQL中的SQL1、常量&#xff08;1&#xff09;字符串常量&#xff08;2&#xff09;数值常量&#xff08;3&#xff09;十六进制常量&…

论文学习:RT-DETR

RT-DETR 摘要 DETR取得显著性能&#xff0c;但高成本计算使其无法发挥无NMS的优势&#xff0c;无法实际应用。本文分析了NMS对准确性和速度的负面影响&#xff0c;并建立端到端的速度基准。第一个实时端到端检测器&#xff0c;高效处理多尺度特征&#xff0c;并提出IoU-aware…

osgPBR(十五)镜面IBL--查看不同级别的HDR环境贴图

首先&#xff0c;设置可以使用Mipmap&#xff0c;启用三线性过滤&#xff0c;设置最大级别和最小级别 osg::ref_ptr<osg::TextureCubeMap> tcm new osg::TextureCubeMap; tcm->setTextureSize(128, 128);tcm->setFilter(osg::Texture::MIN_FILTER, osg::Texture:…

《幸福之路》罗素(读书笔记)

目录 作者简介 作者的感悟 经典摘录 一、不幸福的成因 1、一部分要归咎于社会制度 2、一部分则得归咎于个人心理——当然&#xff0c;你可以说个人心理是社会制度的产物。 二、欠缺某些想要的东西&#xff0c;是快乐的必要条件 三、无聊与刺激 四、现代人的精神疲劳 五…

【C++】vector相关OJ

文章目录 1. 只出现一次的数字2. 杨辉三角3. 电话号码字母组合 ヾ(๑╹◡╹)&#xff89;" 人总要为过去的懒惰而付出代价ヾ(๑╹◡╹)&#xff89;" 1. 只出现一次的数字 力扣链接 代码展示&#xff1a; class Solution { public:int singleNumber(vector<i…

【“栈、队列”的应用】408数据结构代码

王道数据结构强化课——【“栈、队列”的应用】代码&#xff0c;持续更新 链式存储栈&#xff08;单链表实现&#xff09;&#xff0c;并基于上述定义&#xff0c;栈顶在链头&#xff0c;实现“出栈、入栈、判空、判满”四个基本操作 #include <stdio.h> #include <…

大数据-玩转数据-Flink SQL编程实战 (热门商品TOP N)

一、需求描述 每隔30min 统计最近 1hour的热门商品 top3, 并把统计的结果写入到mysql中。 二、需求分析 1.统计每个商品的点击量, 开窗2.分组窗口分组3.over窗口 三、需求实现 3.1、创建数据源示例 input/UserBehavior.csv 543462,1715,1464116,pv,1511658000 662867,22…

基于阶梯碳交易的含P2G-CCS耦合和燃气掺氢的虚拟电厂优化调度(matlab代码)

目录 1 主要内容 系统结构图 P2G-CCS 耦合模型 其他算例对比 2 部分代码 3 下载链接 1 主要内容 该程序复现《基于阶梯碳交易的含P2G-CCS耦合和燃气掺氢的虚拟电厂优化调度》模型&#xff0c;以碳交易和碳封存成本、燃煤机组启停和煤耗成本、弃风成本、购气成本之和为目标…

vertx的学习总结6

Beyond the event bus 一、章节覆盖&#xff1a; 如何在事件总线之上公开服务 verticles和事件总线服务的异步测试 动态代理&#xff1a; MyService 接口 package porxy.test;import io.vertx.codegen.annotations.ProxyGen;ProxyGen public interface MyService {void he…

智慧公厕:城市公共厕所的未来之路

随着城市化进程的不断推进&#xff0c;人们对城市环境质量的要求也越来越高。在城市管理中&#xff0c;公厕作为一个必不可少的公共设施&#xff0c;不仅关乎城市的文明形象&#xff0c;还与市民的生活质量密切相关。为了解决传统公厕存在的问题&#xff0c;智慧公厕应运而生。…

Go-Python-Java-C-LeetCode高分解法-第八周合集

前言 本题解Go语言部分基于 LeetCode-Go 其他部分基于本人实践学习 个人题解GitHub连接&#xff1a;LeetCode-Go-Python-Java-C 欢迎订阅CSDN专栏&#xff0c;每日一题&#xff0c;和博主一起进步 LeetCode专栏 我搜集到了50道精选题&#xff0c;适合速成概览大部分常用算法 突…

大模型部署手记(3)通义千问+Windows GPU

1.简介 组织机构&#xff1a;阿里 代码仓&#xff1a;GitHub - QwenLM/Qwen: The official repo of Qwen (通义千问) chat & pretrained large language model proposed by Alibaba Cloud. 模型&#xff1a;Qwen/Qwen-7B-Chat-Int4 下载&#xff1a;http://huggingface…