C++ osgEarth 多窗口 同步绘制geometry

news2024/10/8 18:25:50

开发环境:

win10 64bit、Qt5.15.2、C++ 、MSVC2019 、osg3.5.6、 osgEarth3.1 

接触osgEarth不久,贴出来,希望大家指正。

注意osgEarth版本。

采用观察者设计模式,设置 master 和 slave 窗口,通过管理类和信号槽维护窗口观察者列表,实现信息高效传递。

达成多窗口在视点、视口、键鼠操作等方面的同步,确保操作连贯性和流畅性。

在 2D 和 3D 地图实现线、多边形、矩形同步绘制及 geometry 贴地显示,设置便捷绘制模式,提高绘图效率。

不同窗口可加载相同地理区域不同类型的文件。

观察者接口:

#ifndef OBSERVER_H
#define OBSERVER_H

#include <osg/Matrixd>

#include <osgEarth/EarthManipulator>

namespace MyProject {

// 观察者接口类,定义多个窗口需要同步的行为
class Observer {

public:
    virtual ~Observer() = default;

    // 同步更新视图矩阵
    virtual void updateViewMatrix(const osg::Matrixd& viewMatrix) = 0;

    // 同步更新投影矩阵
    virtual void updateProjectionMatrix(const osg::Matrixd& projectionMatrix) = 0;

    // 同步鼠标事件
    virtual void updateMouseEvent(int x, int y) = 0;

    // 同步键盘事件
    virtual void updateKeyEvent(int key) = 0;

    // 同步滚轮事件
    virtual void updateViewpoint(const osgEarth::Viewpoint &vp) = 0;

    // 同步2D 3D切换
    virtual void updatePitch(const double &pitch) = 0;

    // 同步 航向角
    virtual void updateHeading(const double &heading) = 0;

    // 新建 geometry
    virtual void updateCreateGeometry() = 0;

    // 同步 绘制图形
    virtual void updateGeometry(osg::ref_ptr<osgEarth::Geometry> geometry) = 0;
};

}

#endif // OBSERVER_H

窗口应用:用到了osgQt 这个库, 大佬应该知道,osgQOpenGLWidget是继承自QOpenGLWidget。

#include "MyWidget.h"
#include "PickHandler.h"
#include "qdebug.h"
#include "qicon.h"

#include <osgDB/ReadFile>
#include <osgEarth/MapNode>


#include <osgEarth/ImageOverlay>
#include <osgEarth/AnnotationLayer>

#include <osgEarth/Registry>

//! Callback that you install on the RTTPicker.
struct MyCallback : public RTTPicker::Callback
{

    MyCallback(){ }

    void onHit(ObjectID id)
    {
        qDebugV0()<<id;
    }

    void onMiss()
    {
        qDebugV0()<<"Miss";
    }

    // pick whenever the mouse moves.
    bool accept(const osgGA::GUIEventAdapter& ea, const osgGA::GUIActionAdapter& aa)
    {
       // qDebugV0()<<"accept";

        return ea.getEventType() == ea.PUSH;
    }
};


MyWidget::MyWidget( QWidget* parent ) : osgQOpenGLWidget( parent ) {

    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

    setParent(nullptr);
    setWindowIcon(QIcon(""));
    setFocusPolicy(Qt::StrongFocus);
    setFocus();
    setMouseTracking(true);

    osgEarth::initialize();

    Global::initStyle(_style);

    _map = new Map();

    _mapNode = new osgEarth::MapNode( _map );

    _map->addLayer( new GeodeticGraticule() );//经纬度网格

    _group = new osg::Group();
    _mapNode->addChild(_group);

    _controlCanvas = new Controls::ControlCanvas;

    _group->addChild( _controlCanvas );

    // coordinate label
    _labelReadout = new LabelControl();
    _labelReadout->setHorizAlign(Control::ALIGN_LEFT);
    _labelReadout->setVertAlign(Control::ALIGN_BOTTOM);

    _labelReadout->setForeColor( 255, 0, 0, 1 );

    _controlCanvas->addControl( _labelReadout.get() );

    // _mouseCoordsTool = new osgEarth::Contrib::MouseCoordsTool( _mapNode );

    // _mouseCoordsTool->addCallback(new osgEarth::Contrib::MouseCoordsLabelCallback(_labelReadout));

    poLayerImage = Global::loadImage("C:/Users/xuanm/Pictures/shp/mid.tif");
    _map->addLayer( poLayerImage );

    // poLayerElevation = Global::loadElevation("C:/Users/xuanm/Pictures/vector_demo/n44_w092_1arc_v3.tif");
    // _map->addLayer( poLayerElevation );

    poLayerVector = Global::loadShapefile("C:/Users/xuanm/Pictures/shp/mid.shp");
    _map->addLayer( poLayerVector );



    connect(this, &osgQOpenGLWidget::initialized, this, &MyWidget::updateWidget);
}

MyWidget::~MyWidget() {


}

void MyWidget::updateWidget() {

    osgEarth::initialize( );

    _viewer = getOsgViewer();


    _viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);//设置单线程模式

    _viewer->realize();

    _viewer->addEventHandler( new PickHandler(new osgText::Text) );



    _viewer->setSceneData( _mapNode );

    updateViewpoint( poLayerVector );

    _viewer->requestRedraw();
}

void MyWidget::slotType(int type)
{
    this->type = type;

    if(eventHandler){
        eventHandler->updateType(type);
    }

    featureNode = nullptr;
}

void MyWidget::enterEvent(QEvent *event) {

    setFocus();

    emit sigEnter(true);

    // //widget 由没有获得焦点--->获得焦点
    if(!isEnter){
        _earthManipulator->setHomeViewpoint(currentViewpoint );
    }

    isEnter = true;

    //至关重要
    _viewer->setCameraManipulator(_earthManipulator);
}

void MyWidget::leaveEvent(QEvent *event) {

    clearFocus();

    _labelReadout->setText("");
    emit sigEnter(false);

    isEnter = false;
}

void MyWidget::updateViewpoint(Layer * poLayer) {

    // 设置相机的初始视图,以聚焦在加载的图像区域上        // 获取 Shapefile 的地理范围
    GeoExtent extent = poLayer->getExtent();

    if (extent.isValid())
    {
        // 获取地理范围的最小和最大经纬度
        double minLon = extent.xMin();
        double maxLon = extent.xMax();

        double minLat = extent.yMin();
        double maxLat = extent.yMax();

        // 计算中心点
        double centerLon = (minLon + maxLon) / 2.0;
        double centerLat = (minLat + maxLat) / 2.0;

        // 创建 GeoPoint 作为中心点
        GeoPoint center(extent.getSRS(), centerLon, centerLat, 0.0);

        // 创建 GeoPoint 表示四个角的经纬度
        GeoPoint bottomLeft(extent.getSRS(), minLon, minLat, 0.0);
        GeoPoint topRight(extent.getSRS(), maxLon, maxLat, 0.0);

        // 计算宽度和高度(物理距离,单位:米)
        double width  = bottomLeft.distanceTo(GeoPoint(extent.getSRS(), maxLon, minLat));
        double height = bottomLeft.distanceTo(GeoPoint(extent.getSRS(), minLon, maxLat));

        // 使用勾股定理计算影像对角线的长度
        double diagonal = std::sqrt(width * width + height * height);

        //qDebugV0() << "实际的对角线长度 (米) " << diagonal;

        // 根据经验公式(可以根据实际效果调整系数)计算Range
        double range = diagonal / ( 2.0 * std::tan(osg::DegreesToRadians(45.0)) );

        if(_viewpoint == nullptr) {

            //设置 Viewpoint
            _viewpoint = new Viewpoint();
            _viewpoint->setName( "Shapefile Viewpoint" );
            _viewpoint->setFocalPoint( center );
            _viewpoint->setHeading(Angle(0.0, Units::DEGREES));
            _viewpoint->setPitch(Angle(-90.0, Units::DEGREES));
            _viewpoint->setRange(Distance(range, Units::METERS));

            // 创建 EarthManipulator 并设置 Viewpoint
            _earthManipulator = new osgEarth::Util::EarthManipulator();
            _earthManipulator->setHomeViewpoint(*_viewpoint);
            _earthManipulator->home(0.0);

            // 设置 Viewer 的 Camera Manipulator
            _viewer->setCameraManipulator( _earthManipulator.get() );
        }

        if(eventHandler == nullptr){
            eventHandler = new CustomEventHandler();
            _viewer->addEventHandler( eventHandler );
        }

        _viewpoint->setFocalPoint( center );
        _viewpoint->setRange(Distance(range, Units::METERS));

        currentViewpoint = *_viewpoint;

        _earthManipulator->setViewpoint(*_viewpoint);
    }
}

void MyWidget::updateCreateGeometry()
{
    qDebugV0()<<"type: "<<type;

    feature = new osgEarth::Feature(new osgEarth::Geometry, _map->getSRS());

    feature->geoInterp() = GEOINTERP_RHUMB_LINE;

    featureNode = new FeatureNode(feature, _style);

    _mapNode->addChild(featureNode);
}

void MyWidget::updateGeometry(osg::ref_ptr<osgEarth::Geometry> geometry)
{
    feature->setGeometry(geometry);

    featureNode->dirty();

    _viewer->requestRedraw(); // 请求视图重绘   // 触发重新绘制
}

// 观察者接口实现 - 更新视图矩阵
void MyWidget::updateViewMatrix(const osg::Matrixd& viewMatrix) {

    _viewer->setCameraManipulator(nullptr);
    _viewer->getCamera()->setViewMatrix(viewMatrix);
    _viewer->requestRedraw();
}

// 观察者接口实现 - 更新投影矩阵
void MyWidget::updateProjectionMatrix(const osg::Matrixd& projectionMatrix) {

    _viewer->setCameraManipulator(nullptr);
    _viewer->getCamera()->setProjectionMatrix( projectionMatrix );
    _viewer->requestRedraw();
}

// 观察者接口实现 - 同步鼠标事件
void MyWidget::updateMouseEvent(int x, int y) {

        //qDebugV0() << "Mouse Event received at: (" << x << ", " << y << ")";
}

// 观察者接口实现 - 同步键盘事件
void MyWidget::updateKeyEvent(int key) {

        //qDebugV0() << "Key Event received: " << key;
}

//更新视点
void MyWidget::updateViewpoint(const osgEarth::Viewpoint& viewpoint) {

    currentViewpoint = viewpoint;

    // _earthManipulator->setViewpoint(viewpoint );

    // _viewer->setCameraManipulator(_earthManipulator);
}

void MyWidget::updatePitch(const double &pitch)
{
    _earthManipulator->setHomeViewpoint(currentViewpoint );
    _viewer->setCameraManipulator(_earthManipulator);

    _viewpoint->setPitch(Angle(pitch, Units::DEGREES));

    _earthManipulator->setViewpoint(*_viewpoint);

    _viewer->requestRedraw();
}

void MyWidget::updateHeading(const double &heading)
{
    _earthManipulator->setHomeViewpoint(currentViewpoint );
    _viewer->setCameraManipulator(_earthManipulator);

    _viewpoint->setHeading(Angle(heading, Units::DEGREES));

    _earthManipulator->setViewpoint(*_viewpoint);

    _viewer->requestRedraw();
}
void MyWidget::resizeEvent(QResizeEvent* event) {
    // Call base class implementation
    osgQOpenGLWidget::resizeEvent(event);

    //qDebug() << "MyWidget resized to:" << event->size();

    // 如果需要,处理OpenGL视口
    glViewport(0, 0, event->size().width(), event->size().height());
}

自定义osgGA::GUIEventHandler,实现绘制交互。这个逻辑写得乱,希望大佬们抽空给指正哈。

#include "CustomEventHandler.h"

#include "Global.h"

#include "MyWidget.h"

CustomEventHandler::CustomEventHandler() {

    Global::initStyle(_style);

    observers.clear();
}

void CustomEventHandler::addObserver(MyWidget* observer) {

    observers.insert(observer);
}

void CustomEventHandler::removeObserver(MyWidget* observer) {

    observers.erase(observer);
}

void CustomEventHandler::updateType(const int& type)
{
    this->type = type;

    _geometry = nullptr;
}

bool CustomEventHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) {

    //将aa强制转换为viewer对象
    poViewer = dynamic_cast<osgViewer::Viewer*>(&aa);
    if (poViewer == nullptr){
        return false;
    }

    poEarthManipulator = dynamic_cast<osgEarth::Util::EarthManipulator *> (poViewer->getCameraManipulator());

    if(poEarthManipulator == nullptr){
        return false;
    }

    viewpoint = poEarthManipulator->getViewpoint();

    //获取 MaNode;
    poMapNode = dynamic_cast<osgEarth::MapNode*>(poViewer->getSceneData());

    if(poMapNode == nullptr){
        return false;
    }

    poMap = poMapNode->getMap();
    if(poMap == nullptr){
        return false;
    }

    mx = ea.getX();
    my = ea.getY();

    eEventType = ea.getEventType();

    eModKeyMask = ea.getModKeyMask();

    eKey = ea.getKey();

    eButton = ea.getButton();

    this->getModKeyMask();//shift   ctrl

    // 同步视图和投影矩阵
    osg::Matrixd viewMatrix = poViewer->getCamera()->getViewMatrix();
    osg::Matrixd projMatrix = poViewer->getCamera()->getProjectionMatrix();

    notifyViewMatrixChanged(viewMatrix);
    notifyProjectionMatrixChanged(projMatrix);    

    notifyViewpoint(viewpoint);

    if(type == 0 ){
        return this->handleNone();
    }else{
        return this->handleDraw();
    }
}

bool CustomEventHandler::handleNone()
{
    switch (eEventType) {

    case osgGA::GUIEventAdapter::KEYDOWN:  // 键盘按下事件
    {
        //2D 3D 切换;viewPoint  heading 航向角切换
        if(_ctrlDown) {

            switch (eKey) {
            case osgGA::GUIEventAdapter::KEY_2: {

                viewpoint.setPitch(Angle(-90.0, Units::DEGREES));

                break;
            }

            case osgGA::GUIEventAdapter::KEY_3: {

                viewpoint.setPitch(Angle(-15.0, Units::DEGREES));

                break;
            }

            case osgGA::GUIEventAdapter::KEY_Up: {
                viewpoint.setHeading(Angle(0.0, Units::DEGREES));
                break;
            }

            case osgGA::GUIEventAdapter::KEY_Left: {
                viewpoint.setHeading(Angle(90.0, Units::DEGREES));
                break;
            }

            case osgGA::GUIEventAdapter::KEY_Down: {
                viewpoint.setHeading(Angle(180.0, Units::DEGREES));
                break;
            }

            case osgGA::GUIEventAdapter::KEY_Right: {
                viewpoint.setHeading(Angle(270.0, Units::DEGREES));
                break;
            }

            default:
                break;
            }

            poEarthManipulator->setViewpoint(viewpoint);
        }

        break;
    }
    default:
        break;
    }

    return false;
}


// 按住 shift键, 绘制 点 线 面
bool CustomEventHandler::handleDraw()
{
    if(!_shiftDown){
        return false;
    }

    switch (eEventType) {
    case osgGA::GUIEventAdapter::PUSH:
    {
        if(eButton != osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON){
            return false;
        }

        if(_geometry == nullptr){

            switch(type){

            case GEOMETRY_LINE:
                // qDebugV0()<<"line";
                _geometry = new osgEarth::LineString;
                break;
            case GEOMETRY_RECT:
            case GEOMETRY_POLYGON:
                qDebugV0()<<"rect or polygon ";
                _geometry = new osgEarth::Polygon;
                break;
            case GEOMETRY_FENCE:
                break;
            }

            _feature = new osgEarth::Feature(_geometry, poMap->getSRS());

            _feature->geoInterp() = GEOINTERP_RHUMB_LINE;

            _featureNode = new FeatureNode(_feature, _style);

            poMapNode->addChild(_featureNode);

            notifyCreateGeometry();
        }

        osg::Vec3d worldPos;

        if (poMapNode->getTerrain()->getWorldCoordsUnderMouse(poViewer, mx, my, worldPos))
        {
            GeoPoint _GeoPoint;
            _GeoPoint.fromWorld(poMapNode->getMapSRS(), worldPos);

            osg::Vec3d mapPos;
            mapPos = osg::Vec3d(_GeoPoint.x(), _GeoPoint.y(), _GeoPoint.z());

            mapPosFirst = mapPos;

            _geometry->push_back(mapPos);

            _featureNode->dirty();

            notifyGeometry(_geometry);
        }
        break;
    }
    case osgGA::GUIEventAdapter::RELEASE:
    {
        if(eButton != osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON){
            return false;
        }

        // 绘制矩形的时候,鼠标左键一旦松开,则表示绘制结束
        if (type == GEOMETRY_RECT) {
            _geometry = nullptr;
        }
        break;
    }

    case osgGA::GUIEventAdapter::DRAG:
    {
        if (type == GEOMETRY_RECT) {

            osg::Vec3d worldPos;

            if (poMapNode->getTerrain()->getWorldCoordsUnderMouse(poViewer, mx, my, worldPos))
            {
                GeoPoint _GeoPoint;
                _GeoPoint.fromWorld(poMapNode->getMapSRS(), worldPos);

                osg::Vec3d mapPos;
                mapPos = osg::Vec3d(_GeoPoint.x(), _GeoPoint.y(), _GeoPoint.z());

                _geometry->clear();

                _geometry->push_back(mapPosFirst);
                _geometry->push_back(osg::Vec3d(mapPos.x(), mapPosFirst.y(), _GeoPoint.z()));
                _geometry->push_back(mapPos);
                _geometry->push_back(osg::Vec3d(mapPosFirst.x(), mapPos.y(), _GeoPoint.z()));

                _featureNode->dirty();

                notifyGeometry(_geometry);
            }
        }
        break;
    }
    default:
        break;
    }

    return false;
}

// shift ctrl 键 状态 检测
void CustomEventHandler::getModKeyMask()
{
    //键盘 有键按下
    if (eEventType == osgGA::GUIEventAdapter::KEYDOWN) {
        if (eKey == osgGA::GUIEventAdapter::KEY_Shift_L || eKey == osgGA::GUIEventAdapter::KEY_Shift_R) {
            _shiftDown = true;
        }

        if (eKey == osgGA::GUIEventAdapter::KEY_Control_L || eKey == osgGA::GUIEventAdapter::KEY_Control_R) {
            _ctrlDown = true;
        }
    }

    //键盘 有键抬起
    if(eEventType == osgGA::GUIEventAdapter::KEYUP){
        if (eKey == osgGA::GUIEventAdapter::KEY_Shift_L || eKey == osgGA::GUIEventAdapter::KEY_Shift_R) {
            _shiftDown = false;

            _geometry = nullptr;
        }

        if (eKey == osgGA::GUIEventAdapter::KEY_Control_L || eKey == osgGA::GUIEventAdapter::KEY_Control_R) {
            _ctrlDown = false;
        }
    }
}

void CustomEventHandler::notifyViewMatrixChanged(const osg::Matrixd& viewMatrix) {

    for (auto observer : observers) {
        if(observer) {
            observer->updateViewMatrix(viewMatrix);
        }
    }
}

void CustomEventHandler::notifyProjectionMatrixChanged(const osg::Matrixd& projectionMatrix) {

    for (auto observer : observers) {
        if(observer) {
            observer->updateProjectionMatrix(projectionMatrix);
        }
    }
}

void CustomEventHandler::notifyMouseEvent(int x, int y) {

    for (auto observer : observers) {
        observer->updateMouseEvent(x, y);
    }
}

void CustomEventHandler::notifyKeyEvent(int key) {

    for (auto observer : observers) {
        observer->updateKeyEvent(key);
    }
}

void CustomEventHandler::notifyViewpoint(const osgEarth::Viewpoint &vp)
{
    for (auto observer : observers) {
        observer->updateViewpoint(vp);
    }
}

void CustomEventHandler::notifyPitch(const double &pitch)
{
    for (auto observer : observers) {
        observer->updatePitch(pitch);
    }
}

void CustomEventHandler::notifyHeading(const double &heading)
{
    for (auto observer : observers) {
        observer->updateHeading(heading);
    }
}

void CustomEventHandler::notifyCreateGeometry()
{
    for (auto observer : observers) {
        observer->updateCreateGeometry();
    }
}

void CustomEventHandler::notifyGeometry(osg::ref_ptr<osgEarth::Geometry> geometry)
{
    for (auto observer : observers) {
        observer->updateGeometry(geometry);
    }
}

在一个管理类里面维护观察者列表:


// 实时 维护 观察者 列表
void MainWindow::slotEnterStatus(bool isEnter) {

    // sender() 返回一个 QObject 指针,指向发出信号的对象
    QObject* obj = sender();

    MyWidget* poWidget = qobject_cast<MyWidget*>(obj);

    if(!poWidget) {
        return;
    }

    // qDebugV0()<<poWidget->windowTitle()<<"   Focus-->"<<(isFocusIn?"IN":"OUT");

    for(auto observer : listWidget) {

        if(observer == poWidget) {
            continue;
        }

        if(isEnter) {
            poWidget->eventHandler->addObserver(observer);
        }
        else {
            poWidget->eventHandler->removeObserver(observer);
        }
    }
}

/**********************************************************************************/

编辑*.shp文件,实现增删改。看了好多帖子,还是没搞定。有大佬知道的话留言。谢谢。

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

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

相关文章

_c++11

嗨喽大家好呀&#xff0c;今天阿鑫给大家带来的是c进阶——c11的内容&#xff0c;好久不见啦&#xff0c;下面让我们进入本节博客的内容吧&#xff01; _c11 统一的列表初始化右值引用可变模板参数(了解&#xff0c;不常接触)lambda表达式function和bind包装器 1. 统一的列表…

JavaWeb 15.详解Servlet及其源码

所有受过的委屈&#xff0c;都在提醒你 要好好争气。 —— 24.10.7 一、Servlet简介 1.动态资源和静态资源 静态资源 无需在程序运行时通过代码运行生成的资源&#xff0c;在程序运行之前就写好的资源&#xff0c;例如&#xff1a;html、css、js、img、音频文件和视频文件 …

职场秘籍:面试加薪,竟然拥有不同的技巧!

假如你是一位测试主管&#xff0c;去评价一名测试工程师是否优秀&#xff0c;那么你将如何去判断呢&#xff1f;你最看重的是哪方面的能力呢&#xff1f; 对于这个问题&#xff0c;是不能一概而论的&#xff0c;要分为两种情况&#xff0c;情况不同&#xff0c;答案一定是不同…

高校新生报道管理系统使用SpringBootSSM框架开发

&#xff01;&#xff01;&#xff01;页面底部,文章结尾,加我好友,获取计算机毕设开发资料 目录 一、引言 二、相关技术介绍 三、系统需求分析 四、系统设计 五、关键技术实现 六、测试与优化 七、总结与展望 一、引言 当前高校新生报到过程中存在许多问题&#xff0c;…

从0到1:用Python构建你人生中的第一个人工智能AI模型

文章目录 摘要引言数据预处理&#xff1a;为模型打下坚实基础数据预处理的步骤Python示例代码说明&#xff1a;注意事项&#xff1a; 模型建立&#xff1a;选择合适的模型神经网络示例代码说明&#xff1a; 模型训练与测试训练示例代码说明&#xff1a; 解读模型结果性能指标 深…

原生小程序开发|小程序卡片(Widget) 开发指南

开发 Widget 代表应用的一个小程序卡片&#xff0c;负责小程序卡片的展示和交互。 小程序卡片(Widget) 的开发在智能小程序的基础上增加一个目录即可&#xff0c;用于存放小程序卡片(Widget)的代码。并在 project.tuya.json 中增加一个声明。 创建小程序卡片(Widget)项目 在 …

九、Drf序列化器

九、序列化器 9.1序列化 从数据库取QuerySet或数据对象转换成JSON 9.1.1序列化器的简易使用 #新建一张部门表 class Depart(models.Model):title=models.CharField(verbose_name=部门,max_length=32)order=models.IntegerField(verbose_name=顺序)count=models.IntegerFiel…

vscode中安装python的包

首先需要调出命令行。然后运行代码&#xff0c;找到你所需要的环境。 PS C:\Users\Administrator\AppData\Local\ESRI\conda\envs\arcgispro-env> conda env list # conda environments: #C:\ProgramData\Anaconda3 base * C:\Users\Administrator\.con…

【无人机设计与控制】无人机三维路径规划,对比蚁群算法,ACO_Astar_RRT算法

摘要 本文探讨了三种不同的无人机三维路径规划算法&#xff0c;即蚁群算法&#xff08;ACO&#xff09;、A算法&#xff08;Astar&#xff09;以及快速随机树算法&#xff08;RRT&#xff09;。通过仿真实验对比了各算法在不同环境下的性能&#xff0c;包括路径长度、计算效率…

软考越来越难了,2024年软考究竟还值不值得考?

最近不少同学沟通&#xff0c;聊到软考现在越来越难了&#xff0c;考了两三次都没过&#xff0c;也有不少新同学咨询软考考试的一些福利政策&#xff0c;投入大量的物力&#xff0c;财力&#xff0c;精力&#xff0c;那么到底软考值不值得考呢&#xff1f; 01 / 关于软考 软考…

【FlagScale】异构算力混合训练方案

背景以及必要性 算力需求的高峰&#xff1a;随着人工智能&#xff08;AI&#xff09;和生成内容&#xff08;AIGC&#xff09;的发展&#xff0c;对计算资源的需求急剧增加。尤其是参数规模达到数百亿的大模型训练&#xff0c;需要大量的计算资源。 算力市场供应紧张&#xff…

一键拯救废片!3个在线教程,实现光线重塑、表情迁移、模糊图像修复

每逢国庆「黄金周」&#xff0c;都是旅游业的高光时刻。根据研判&#xff0c;今年国庆假期全社会跨区域人员流动量将达到 19.4 亿人次&#xff0c;平均每天 2.77 亿人次。 与旅游业同步增长的还有摄影行业&#xff0c;旅拍带动的妆造、服饰租赁等相关环节发展火热&#xff0c;…

Linux安装Redis7.40

一、环境检查 1.1 查看是否已经安装了Redis应用 ps -ef |grep redis或者 whereis redis1.2 若已经安装了redis应用或者有遗留的Redis文件&#xff0c;进行移除或者启动即可。 二、下载&安装 2.1 找到对应的安装包资源&#xff0c;使用wget命令下载&#xff0c;这里安装…

小众交友软件有哪些?小众交友APP排行榜前十名推荐

在网络的广袤天地中&#xff0c;小众交友软件如隐藏的宝藏&#xff0c;散发着独特魅力。它们为人们提供别样的社交舞台&#xff0c;让孤独的灵魂有处可栖。今天&#xff0c;就让我们一同探寻那些小众交友软件的奇妙世界。 1. 咕哇找搭子小程序&#xff1a;这是一个实名制的找搭…

想要加密电脑?盘点2024年企业常用的10款电脑文件加密软件

在企业数据安全的时代背景下&#xff0c;文件加密已经成为保护企业核心信息、应对网络安全威胁的关键举措。无论是保护机密的商业数据&#xff0c;还是遵守数据隐私合规性要求&#xff0c;企业对文件加密软件的需求日益增长。本文将盘点2024年企业常用的10款电脑文件加密软件&a…

【Java 问题】基础——序列化

接上文 序列化 45.什么是序列化&#xff1f;什么是反序列化&#xff1f;46.说说有几种序列化方式&#xff1f; 45.什么是序列化&#xff1f;什么是反序列化&#xff1f; 什么是序列化&#xff0c;序列化就是把Java对象转为二进制流&#xff0c;方便存储和传输。 所以反序列化…

SOA是什么

SOA SOA 即 Service-Oriented Architecture&#xff08;面向服务的架构&#xff09;。 一、定义 SOA 是一种软件设计方法和架构理念&#xff0c;它将应用程序的不同功能单元&#xff08;称为服务&#xff09;通过定义良好的接口和契约联系起来。这些服务可以独立部署、独立运…

【JavaEE初阶】深入理解不同锁的意义,synchronized的加锁过程理解以及CAS的原子性实现(面试经典题);

前言 &#x1f31f;&#x1f31f;本期讲解关于锁的相关知识了解&#xff0c;这里涉及到高频面试题哦~~~ &#x1f308;上期博客在这里&#xff1a;【JavaEE初阶】深入理解线程池的概念以及Java标准库提供的方法参数分析-CSDN博客 &#x1f308;感兴趣的小伙伴看一看小编主页&am…

(笔记)第三期书生·浦语大模型实战营(十一卷王场)–书生基础岛第6关---OpenCompass 评测 InternLM-1.8B 实践

学员闯关手册&#xff1a;https://aicarrier.feishu.cn/wiki/ZcgkwqteZi9s4ZkYr0Gcayg1n1g?open_in_browsertrue 课程视频&#xff1a;https://www.bilibili.com/video/BV1RM4m1279j/ 课程文档&#xff1a; https://github.com/InternLM/Tutorial/blob/camp3/docs/L1/OpenComp…

嵌入式设备硬件和软件安全设计

1. 引言 哪个领域的网络安全实施记录最差&#xff1f; 既不是 PKI/数字证书&#xff0c;也不是 密钥管理&#xff0c;也不是 OAuth。很可能是嵌入式设备和物联网 领域。 总的来说&#xff0c;这似乎是一个梦想&#xff0c;但如果可设计出“设计安全”的系统&#xff0c;而不…