Bentley二次开发教程24-交互式类工具

交互式工具概念简述

本次内容主要涉及到交互式工具的使用,在MicroStation中,超过一半的功能都是以交互式工具的形式而存在的,因此交互式工具在MicroStation二次开发中便显得非常重要。当我们的鼠标或键盘在视图中产生交互操作时,不同的动作会调用不同的回调函数。这种方式是“面向过程”编程思想的产物,在“面向对象”的编程思想下,SDK封装了DgnTool、DgnPrimitiveTool、DgnElementSetTool等类来供各位使用。我们只要从相应的类派生一个我们自己的类,根据交互式工具的不同功能,重写一些基类的成员函数很容易就能实现我们的交互式工具。
在这里插入图片描述
MicroStation SDK案例地址:
C:\Program Files\Bentley\MicroStationCONNECTSDK\examples\Elements\exampletool(默认路径)
这张图中是我们从MicroStationAPI.chm中截取的DgnElementSetTool在整个DgnTool工具类中的层次关系。我们可以看到DgnTool是所有工具类最顶层的基类,它定义了交互式工具使用过程中大部分的鼠标和键盘相关的事件处理函数。而DgnElementSetTool的基类除了DgnPrimitiveTool以外还有IRedrawOperation和ModifyOp这两个基类,从DgnPrimitiveTool继承了视图及鼠标键盘等交互事件的响应功能,从IRedrawOperation继承实现了元素动态重绘的功能,从ModifyOp继承实现了元素修改逻辑的功能,而DgnElementSetTool自身又添加了元素选取(包括点选、划选框选、选择集以及围栅)的功能。
在这里插入图片描述
图中是DgnTool常用事件相关成员虚函数。我们从DgnTool直接或间接派生了我们自己的类,重写了某一事件对应的虚函数时,如果对应事件被触发,系统后台会调用我们重写的虚函数。例如如果我们重写了OnDataButton函数的话,当我们在视图中单击鼠标左键时,重写OnDataButton函数就会被调用。我们的交互式工具就是在这些事件处理函数中根据用户输入的信息,而完成各种复杂的交互功能。
简单的来说,所谓继承就是拥有基类的所有功能,打个比方,就像是ORD中除了拥有MicroStation软件的所有功能,还具有道路专业的一些特色功能。对于交互式工具的使用,首先需要明确自身希望实现的最终目标,如果您只是需要做一些元素单选,或需要配合键盘Ctrl,Shift等做简单交互时,使用Dgntool即可;若您需要具有视图及鼠标键盘等交互事件,那么使用DgnPrimitiveTool即可;若需实现元素的动态绘制,元素修改及框选,划选功能,那么需要使用DgnElementSetTool实现既定目标。因为三个工具依次继承,后者拥有前者的功能,因此也会导致其中机制越来越复杂,因此在这里建议:按照实际需求选择满足功能需求的交互式工具
关于交互式工具中可重写的虚方法为了方便理解大致可归为三类,分别为流程类方法,交互类方法,控制类方法。其中,流程类方法指在工具执行流程导致触发的方法,比如说,当我们将交互式工具加载后,会按照流程触发OnPostInstall( ),在这个方法中我们可以对交互式工具中可能需要使用到的变量进行声明或初始化;交互类方法指的是其方法的触发与流程无关,主要在用户执行执行操作便会自动触发,比如说,在用户点击确认键(默认为左键)时便会触发事件,调用该方法;控制类方法,指的是用于控制流程的方法,比如说,当我们需要进行动态绘制时,首先需要使用BeginDynamics( )开启动态绘制,此时当我们的鼠标在屏幕中移动时才会触发OnDynamicFrame( ),其中可供我们将在动态绘制过程中需要实现的业务功能写入其中。
在这里插入图片描述
关于DgnElementSetTool的交互逻辑非常复杂,如果您第一次接触该工具,其中纷繁复杂的交互逻辑与众多可重写的虚方法会让您有一种无法下手的感觉。在这里需要感谢符老师与郭老师对MicroStation中交互式工具的详细阐述,以下为根据LearnDgnTool-05_DgnElementSetTool详解将文字进行梳理并转换为流程导图的形式,更加直观的展示了DgnElementSetTool的交互逻辑。

DgnElementSetTool流程导图

流程导图
在这里插入图片描述

对于我们的日常开发来说,其实并不需要将其中所有的重写虚方法面面俱到的掌握,其中只需要根据实际的业务需求,分析应用场景,抽象出工具的交互流程后,对个别虚方法进行重写并添加业务功能即可。

交互式工具案例

动态绘制绘制圆Demo

该工具涉及左右键点击,动态绘制等操作。
需求说明:
对圆实现动态绘制并可进行重复操作,并具有取消绘制功能。
要求:
首先点击确定圆心位置,然后随着鼠标拖动以鼠标与圆心之间的距离为半径动态绘制圆,确认圆半径后点击左键生成圆,同时全程需要根据不同状态提供相应的提示说明。
分析:
根据需求说明及要求,该工具主要涉及到的功能及设置有:

  • 在执行命令加载工具后输出“选择圆心”的提示(OnPostInstall)
  • 点击左键后记录圆心坐标,启动动态绘制并输出“选择终点”的提示(OnDataButton)
  • 当需要退出程序时,点击右键退出程序(OnResetButton)
  • 在动态绘制的过程中根据圆心坐标与鼠标停留的坐标点绘制面向视图的椭圆元素并在视图中展示(OnDynamicFrame)
  • 当圆心坐标点输入错误需要撤回时,点击右键,此时对储存圆坐标信息的列表执行清空,并输出“选择圆心”的提示,重新选择圆心坐标(OnResetButton)
  • 在确认圆心点与圆半径无误后点击左键,此时结束动态绘制并根据信息生成圆绘制结果(OnDataButton)
    从以上分析可以看出,我们在该交互式工具中使用的OnDataButton与OnResetButton在不同使用场景下执行了两种不同的功能,因此我们需要使用某种机制来区分同一种方法的不同业务功能,在本案例中采用的方法为根据列表中储存的坐标值个数执行不同的业务功能。
    在这里插入图片描述
    基于以上分析,我们将对应的业务功能写入重写的虚函数中,创建出用于绘制圆的交互式工具。
using Bentley.DgnPlatformNET;
using Bentley.DgnPlatformNET.Elements;
using Bentley.GeometryNET;
using Bentley.MstnPlatformNET;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace InteractiveToolsIntroduction.Tools
{/** 参考资料:* https://communities.bentley.com/communities/other_communities/bdn_other_communities/w/chinabdn-wiki/45167/learndgntool-05_5f00_dgnelementsettool*/class CreateEllipse : DgnElementSetTool{private DgnModel m_dgnModel;private List<DPoint3d> m_pos;public CreateEllipse(int toolId, int prompt) : base(toolId, prompt){}public static void InstallNewInstance()//交互式工具的入口函数,用于声明工具并进行加载{CreateEllipse primitiveTool = new CreateEllipse(0, 0);//创建实例primitiveTool.InstallTool();//加载工具       }protected override void OnPostInstall()//工具激活后执行{            string tips = "Please select start point:";//设置提示语NotificationManager.OutputPrompt(tips);//将提示语输出到提示框中m_dgnModel = Session.Instance.GetActiveDgnModel();//获得当前的模型空间m_pos = new List<DPoint3d>();//创建用于储存坐标的列表            }/** 如果我们对通过参数传递进来的元素进行修改,并且返回SUCCESS的话,在_DoOperationForModify* 中会用修改后的元素替换掉原来的元素,当然前提是_IsModifyOriginal返回true。否则的话会直接* 把修改后的元素重新添加到Dgn文件中。*/public override StatusInt OnElementModify(Element element){            return StatusInt.Error;}protected override bool OnDataButton(DgnButtonEvent ev)//点击确认键(默认为左键)后触发{if(m_pos.Count()==0)//判断列表中点个数,若列表中没有坐标点{m_pos.Add(ev.Point);//添加捕捉点string tips = "Please select end point:";//设置提示语NotificationManager.OutputPrompt(tips);//将提示语输出到提示框中BeginDynamics();//启动动态绘制}else{EndDynamics();//关闭动态绘制m_pos.Add(ev.Point);//添加捕捉点EllipseElement element = CreateEllipseElement(m_pos[0], m_pos[1]);//创建椭圆元素element.AddToModel();//将椭圆元素写入模型m_pos.Clear();//清空列表string tips = "Please select start point:";//设置提示语NotificationManager.OutputPrompt(tips);//将提示语输出到提示框中}return true;}protected override void OnDynamicFrame(DgnButtonEvent ev)//动态绘制时触发{EllipseElement element = CreateEllipseElement(m_pos[0],ev.Point);//创建椭圆元素if (null == element)//若未成功生成椭圆元素return;//返回RedrawElems redrawElems = new RedrawElems();//使用元素用于动态绘制redrawElems.SetDynamicsViewsFromActiveViewSet(Session.GetActiveViewport());//设置视角redrawElems.DrawMode = DgnDrawMode.TempDraw;//设置绘制模式redrawElems.DrawPurpose = DrawPurpose.Dynamics;//设置绘制目标            redrawElems.DoRedraw(element);//使用元素用于动态绘制}     protected override bool OnResetButton(DgnButtonEvent ev)//点击重置键(默认为右键)触发{if(m_pos.Count()==0)//判断列表中点个数,若列表中没有坐标点则退出{ExitTool();//退出工具}else{EndDynamics();//停止动态捕捉m_pos.Clear();//清空列表中的数据string tips = "Please select start point:";//设置提示语NotificationManager.OutputPrompt(tips);//将提示语输出到提示框中}return true;//返回}protected override void OnRestartTool()//重启工具时触发{InstallNewInstance();//重新启动交互式工具}private EllipseElement CreateEllipseElement(DPoint3d startPo,DPoint3d endPo){            double distance = startPo.Distance(endPo);//确定绘制圆的半径EllipseElement ellipse = new EllipseElement(m_dgnModel, null, DPoint3d.Zero, distance, distance, DMatrix3d.Identity);//创建椭圆元素(长轴=短轴,即圆)Session.GetActiveViewport().GetRotation().TryInvert(out DMatrix3d invertMatrix);//获得当前视角的旋转转置矩阵DTransform3d dTransform3D = new DTransform3d(invertMatrix);//使用旋转矩阵创建几何变换TransformInfo transform = new TransformInfo(dTransform3D);//使用几何变换创建变换信息ellipse.ApplyTransform(transform);//对椭圆元素应用变换dTransform3D = DTransform3d.FromTranslation(startPo);//创建用于平移的几何变换transform = new TransformInfo(dTransform3D);//使用几何变换创建变换信息ellipse.ApplyTransform(transform); //对椭圆元素应用变换return ellipse;//返回椭圆}}
}

在这里插入图片描述

修改实体元素颜色Demo

该工具涉及批量选择(框选/划选),单项选择(按住Ctrl点选)正选/反选元素的操作。
需求说明:
使用工具采用框选/划选/点选的方法选择元素,并对获取到的元素集执行颜色修改操作。
要求:
在使用过程中可以对选择集中的元素进行添加或删除。
分析:
根据需求说明及要求,该工具主要涉及到的功能及设置有:

  • 在执行命令加载工具后输出“选择需要修改颜色的元素”提示(OnPostInstall)
  • 保证在选择元素阶段可以由左键拖拽框选/点Alt后切换为划选/点Ctrl点选的方式正选/反选元素,在选择元素不为空后点击左键进行下一步操作(AllowDragSelect,WantAdditionalLocate)
  • 无需点击左键才开始处理元素(NeedAcceptPoint)
  • 在确定选择的元素后,点击左键接受,此时对选择集中的元素进行颜色修改与修改结果输出(OnModifyComplete)
  • 点击重置键(默认右键)时退出该工具(OnResetButton)
    在这里插入图片描述
    基于以上分析,我们将对应的业务功能写入重写的虚函数中,创建出用于颜色修改的交互式工具。在这里我们需要注意,关于选择元素的行为是根据我们在重写WantAdditionalLocate( )中进行设置的,该方法是用于判断是否需要拾取元素,而拖拽,Ctrl点选行为是我们在重写其中的内容控制的,由此看出通过重写虚方法赋予交互式工具极大的自由度与可定制性。
using Bentley.DgnPlatformNET;
using Bentley.DgnPlatformNET.Elements;
using Bentley.MstnPlatformNET;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace InteractiveToolsIntroduction.Tools
{class ChangeSolidColorTool : DgnElementSetTool//Case: ChangeSolidColorTool{private DgnModelRef m_dgnModelRef;private int m_count;public ChangeSolidColorTool(int toolId, int prompt) : base(toolId, prompt){}public static void InstallNewInstance()//交互式工具的入口函数,用于声明工具并进行加载{ChangeSolidColorTool primitiveTool = new ChangeSolidColorTool(0, 0);//创建实例primitiveTool.InstallTool();//加载工具       }/** 如果我们对通过参数传递进来的元素进行修改,并且返回SUCCESS的话,在_DoOperationForModify* 中会用修改后的元素替换掉原来的元素,当然前提是_IsModifyOriginal返回true。否则的话会直接* 把修改后的元素重新添加到Dgn文件中。*/public override StatusInt OnElementModify(Element element){                        return StatusInt.Error;}       protected override void OnRestartTool()//重启工具时触发{InstallNewInstance();//重新启动交互式工具}protected override void OnPostInstall()//工具激活后执行{string tips = "Please select solids to be filled:";//设置提示语NotificationManager.OutputPrompt(tips);//将提示语输出到提示框中m_dgnModelRef = Session.Instance.GetActiveDgnModelRef();//获得当前激活的模型            m_count = 0;//计数清零}protected override bool WantAdditionalLocate(DgnButtonEvent ev)//判断当前是否需要拾取元素{if(ev==null)//若没有选择到元素{return true;}if(ev.IsControlKey)//若检测到按动Ctrl行为{return true;}if(ElementAgenda.GetCount()==0)//若选择集中没有元素{return true;}return false;}protected override bool OnResetButton(DgnButtonEvent ev)//重置键(默认右键)点击时触发{ExitTool();//退出交互式工具return true;}protected override UsesDragSelect AllowDragSelect()//判断是否要启用框选或者划选{return UsesDragSelect.Box;//使用框选选择元素}protected override bool NeedAcceptPoint()//判断是否需要用户再点击左键才开始处理元素{return false;}protected override bool OnModifyComplete(DgnButtonEvent ev)//修改完毕,对选择集中的元素进行处理{ChangeSolidsColor();//修改实体填充颜色OuputFilledResultMessage();//输出填充结果return base.OnModifyComplete(ev);}private void ChangeSolidsColor(){for (uint i = 0; i < ElementAgenda.GetCount(); i++)//遍历选择集中的元素{Element element = SetSolidColor(ElementAgenda.GetEntry(i));//对元素设置实体填充if (element != null)//判断元素是否被成功填充{element.ReplaceInModel(ElementAgenda.GetEntry(i));//替换模型中的元素}}}private Element SetSolidColor(Element element){if (element.ElementType == MSElementType.Solid)//判断元素类型是否为Solid{ElementPropertiesSetter setter = new ElementPropertiesSetter();//修改元素属性setter.SetColor(3);//设置索引值3的颜色为元素颜色setter.Apply(element);//将设置应用于指定元素m_count++;//计数加一return element;}return null;}private void OuputFilledResultMessage(){string tips = "Filled " + m_count + " solids.";//设置提示语MessageCenter.Instance.ShowInfoMessage(tips, tips, false);//将提示语输出到提示框中}}
}

在这里插入图片描述

围栅剪切Demo

该工具涉及使用围栅获取元素,使用激活的围栅剪切元素的操作。

需求说明:
在绘制剪切围栅后,使用交互式工具对围栅中的元素进行剪切。
分析:
根据需求说明,该工具主要涉及到的功能及设置有:

  • 在执行命令加载工具后输出“确认围栅存在”的提示(OnPostInstall)
  • 确定获取元素的方式为从围栅中获取(SetElementSource)
  • 点击重置键(默认右键)时退出该工具(OnResetButton)
  • 无需用户输入额外的确认点才开始处理选择集元素(NeedPointForSelection)
  • 无需点击左键才开始处理元素(NeedAcceptPoint)
  • 确定使用激活围栅(UseActiveFence)
  • 保证通过围栅获取元素(AllowFence)
  • 确认后执行元素修改流程(ProcessAgenda)
    在这里插入图片描述
    在本案例中,需要对交互式工具中获取元素的方法与对元素的操作进行设置。其中,在激活工具时触发OnInstall( ),设置元素来源为通过围栅获得SetElementSource(ElementSource.Fence),重写NeedPointForSelection( )并返回false设置用户无需输入额外的确认点即开始处理选择集元素,重写NeedAcceptPoint( )并返回false设置无需用户再点击左键即开始处理元素,重写UseActiveFence( )返回true设置使用激活的围栅,重写AllowFence( )并返回UsesFence.Required设置必须通过围栅获取元素。同时,在OnPostInstall( )写入初始化模型与输出提示的内容,在OnResetButton( )中写入退出交互式工具的命令,在ProcessAgenda( )中执行使用激活围栅对元素进行切割的业务功能。
using Bentley.DgnPlatformNET;protected override bool OnResetButton(DgnButtonEvent ev)//点击重置键(默认为右键)触发{ExitTool();return true;}protected override StatusInt ProcessAgenda(DgnButtonEvent ev)//执行元素修改的流程{int count= ClipElementsByFence();//使用围栅对元素进行剪切OuputFilledResultMessage(count);//输出剪切结果return StatusInt.Success;}private int ClipElementsByFence(){int count = 0;//输出生成剪切元素个数FenceParameters fenceParams = new FenceParameters(m_dgnModelRef, DTransform3d.Identity);//声明围栅信息FenceManager.InitFromActiveFence(fenceParams, true, true, FenceClipMode.Original);//使用围栅信息初始化围栅       for (uint i = 0; i < ElementAgenda.GetCount(); i++)//遍历元素容器中的元素{ElementAgenda insideElems = new ElementAgenda();//声明元素容器ElementAgenda outsideElems = new ElementAgenda();//声明元素容器Element element = ElementAgenda.GetEntry(i);//获得元素容器中的元素                    FenceManager.ClipElement(fenceParams, insideElems, outsideElems, element, FenceClipFlags.Optimized);//对围栅内的元素进行剪切for (uint j = 0; j < outsideElems.GetCount(); j++)//遍历围栅切割后生成的外围元素{using (ElementCopyContext copyContext = new ElementCopyContext(m_dgnModelRef))//复制元素{Element elemToCopy = outsideElems.GetEntry(j);//获得切割后生成的外围元素copyContext.DoCopy(elemToCopy);//将元素复制到指定模型中count++;//剪切个数增加}}for (uint j = 0; j < insideElems.GetCount(); j++)//遍历围栅切割后生成的外围元素{using (ElementCopyContext copyContext = new ElementCopyContext(m_dgnModelRef))//复制元素{Element elemToCopy = insideElems.GetEntry(j);//获得切割后生成的外围元素copyContext.DoCopy(elemToCopy);//将元素复制到指定模型中                        }}}FenceManager.ClearFence();//清除围栅return count;}private void OuputFilledResultMessage(int count){string tips = count + " elements clipped.";//设置提示语MessageCenter.Instance.ShowInfoMessage(tips, tips, false);//将提示语输出到提示框中}}    
}

在这里插入图片描述

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

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

相关文章

黑马微服务课程2

课程地址&#xff1a;2024最新SpringCloud微服务开发与实战&#xff0c;java黑马商城项目微服务实战开发&#xff08;涵盖MybatisPlus、Docker、MQ、ES、Redis高级等&#xff09;_哔哩哔哩_bilibili 课程名称&#xff1a;2024最新SpringCloud微服务开发与实战&#xff0c;java…

《A More Fine-Grained Aspect-Sentiment-Opinion Triplet Extraction Task》阅读笔记

一、论文简介 在自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;情感分析一直是一个热门的研究主题&#xff0c;它帮助机器理解文本中的情感倾向。随着技术的进步&#xff0c;研究者们不断推动情感分析向更细粒度的方向发展&#xff0c;即从简单的正负情感判断&#…

【VueUse】重新定义状态管理在 Vue 中的体验

在 Vue 生态系统中&#xff0c;状态管理一直是开发者们关注的焦点之一。而随着 VueUse 的出现&#xff0c;我们迎来了一种全新的方式来处理状态管理&#xff0c;它让我们能够以更简单、更灵活的方式来管理应用程序的状态。 在本文中我们将深入探讨 VueUse 中与状态管理相关的内…

StrongSORT——基于DeepSORT,提高多目标跟踪的准确性和鲁棒性

1、概述 1.1 DeepSORT DeepSORT算法是在SORT基础上发展起来的一种多目标跟踪算法。SORT算法结合了目标检测器和跟踪器&#xff0c;其中跟踪器的核心是卡尔曼滤波和匈牙利算法。 卡尔曼滤波用于预测目标在下一帧的位置和状态而匈牙利算法则用于将预测状态与实际检测结果进行最…

SpringCloud基础 Consul的引入

前言 首先是为什么引入consul这个组件 我们知道微服务分为很多个模块,这里模块中相互调用,我使用硬编码的模式是不好的 比如微服务模块需要更新的时候,我们使用硬编码的方式可能需要修改很多个地方 但是使用consul之后,就引入了注册中心,我们只需要将对应的服务注册为节点 这样…

android脱壳第二发:grpc-dumpdex加修复

上一篇我写的dex脱壳&#xff0c;写到银行类型的app的dex修复问题&#xff0c;因为dex中被抽取出来的函数的code_item_off 的偏移所在的内存&#xff0c;不在dex文件范围内&#xff0c;所以需要进行一定的修复&#xff0c;然后就停止了。本来不打算接着搞得&#xff0c;但是写了…

【论文阅读】EgoPCA: A New Framework for Egocentric Hand-Object Interaction

论文主要贡献 提出一种新的框架&#xff1a;Ego-HOI recognition by Probing, Curation and Adaption (EgoPCA)。构建了全面的预训练集&#xff0c;平衡的测试集&#xff0c;以及一个包含了微调策略的baseline。 在Ego-HOI达到了SOTA&#xff0c;并且建立了有效的机制方法。 …

【后端】git与python的结合使用

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、git介绍二、git常见使用三、git与python的结合使用四、总结 前言 随着开发语言及人工智能工具的普及&#xff0c;使得越来越多的人会主动学习使用一些开发…

【OceanBase系列】—— 常用运维操作(备忘)

作者简介&#xff1a; 花名&#xff1a;绪宁&#xff0c;OceanBase 数据库解决方案架构师 创建租户 方法一&#xff1a;OCP 创建 确认可分配资源 具体可以分配多少内存&#xff0c;可以通过【资源管理】查看各节点的剩余资源 2. 新建租户 3. 填写租户信息 zone 优先级主要是 p…

STM32玩转物联网实战篇:5.ESP8266 WIFI模块MQTT通信示例详解

1、准备开发板 开发板功能区分布图 开发板俯视图 2、实验讲解 在之前的章节中&#xff0c;已经讲解过了MQTT的通讯原理和组包过程&#xff0c;现在开始手把手的教大家用代码来实现连接MQTT平台以及数据的交互&#xff0c;实际上这篇文章已经拖更接近两年了&#xff0c;非常…

《QT实用小工具·三十九》仿 Windows10 画图3D 的颜色选择器, 但更加强大

1、概述 源码放在文章末尾 该项目实现了仿 Windows10 画图3D 的颜色选择器&#xff0c;功能更加丰富更加强大。 项目部分代码如下所示&#xff1a; import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 import QtGraphicalEffects 1.15Item {id…

【leetcode面试经典150题】72. 从前序与中序遍历序列构造二叉树(C++)

【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主&#xff0c;题解使用C语言。&#xff08;若有使用其他语言的同学也可了解题解思路&#xff0c;本质上语法内容一致&…

opencv绘制线段------c++

绘制线段 bool opencvTool::drawLines(std::string image_p, std::vector<cv::Point> points) {cv::Mat ima cv::imread(image_p.c_str()); // 读取图像&#xff0c;替换为你的图片路径 cv::Scalar red cv::Scalar(0, 0, 255); // Red color int thickness 2;// 遍…

面试遇到算法题:实现LRU缓存

请你设计并实现一个满足 LRU (最近最少使用) 缓存约束的数据结构。 这是一道大厂面试高频出现的算法题&#xff0c;难度为⭐️⭐️⭐️&#xff0c;属于中等&#xff0c;老铁们来一起看看这个题该怎么解&#xff1f; 1. 原题再现 没有废话&#xff0c;翠花&#xff0c;上酸菜&…

JS 添加数组元素( 4种方法 )

No.内容链接1Openlayers 【入门教程】 - 【源代码示例300】 2Leaflet 【入门教程】 - 【源代码图文示例 150】 3Cesium 【入门教程】 - 【源代码图文示例200】 4MapboxGL【入门教程】 - 【源代码图文示例150】 5前端就业宝典 【面试题详细答案 1000】 文章目录 一、四种…

Spring Boot 集成 EasyExcel 3.x

Spring Boot 集成 EasyExcel 3.x Spring Boot 集成 EasyExcel 3.x 本章节将介绍 Spring Boot 集成 EasyExcel&#xff08;优雅实现Excel导入导出&#xff09;。 &#x1f916; Spring Boot 2.x 实践案例&#xff08;代码仓库&#xff09; 介绍 EasyExcel 是一个基于 Java 的、…

HZNUCTF -- web

HZNUCTF第五届校赛实践赛初赛 Web方向 WriteUp-CSDN博客 ezssti 下载文件 访问 /login 可由源代码中看到 Eval 函数 &#xff0c;可以任意命令执行 按照格式&#xff0c;可执行命令 POST &#xff1a;name{{.Eval "env"}} 可以得到flag &#xff08;尝试ls 只能列出…

「ChatGPT」掀起新一轮AI热潮!超越GPT-4 Turbo,商汤日日新大升级!

目录 拳打 GPT-4 Turbo &#xff0c;脚踢 DALLE 3 端侧大模型&#xff0c;唯快不破 AI 应用落地需要一个即插即用的大模型超市 并不存在 AI 这个行业&#xff0c;只有 AI行业&#xff0c;强调 AI 需要与传统产业合作&#xff0c;这种关系是结合与赋能&#xff0c;而不是颠覆…

java开发之路——用户管理中心_简单初始化

用户管理中心_简单初始化 (一) 初始化项目1. 使用 Ant Design Pro(现成的管理系统) 进行前端初始化2. 后端初始化三种初始化java项目 (二) 遇到的问题【问题1】Ant design pro页面打不开&#xff0c;一直在budiling控制台出现错误error-./src/components/index.ts【问题2】初始…

基于SSM的物业管理系统(含源码+sql+视频导入教程+文档+PPT)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 基于SSM的物业管理系统2拥有三种角色 管理员&#xff1a;用户管理、物业管理、房产信息管理、小区概况管理、开发商管理、收费标准管理、物业公司管理等 物业&#xff1a;住户管理、收费…