diff --git a/src/scene/OEScene.cpp b/src/scene/OEScene.cpp index f5ce9c5e..2c595a4e 100644 --- a/src/scene/OEScene.cpp +++ b/src/scene/OEScene.cpp @@ -103,6 +103,64 @@ osg::Viewport* OEScene::GetViewport() const { return curentView_->getCamera()->getViewport(); } +bool OEScene::ScreenToWorldCoordinate(int x, int y, osg::Vec3d* output) const { + if (nullptr == output) { + LOG_WARN("OEScene::ScreenToWorldCoordinate - worldPoint is null"); + return false; + } + + osg::Camera* camera = curentView_->getCamera(); + if (!camera) { + LOG_WARN("OEScene::ScreenToWorldCoordinate - camera is null"); + return false; + } + + osg::ref_ptr intersector = + new osgUtil::LineSegmentIntersector(osgUtil::Intersector::WINDOW, x, y); + + osgUtil::IntersectionVisitor iv(intersector.get()); + camera->accept(iv); + + if (intersector->containsIntersections()) { + osgUtil::LineSegmentIntersector::Intersections& intersections = intersector->getIntersections(); + osgUtil::LineSegmentIntersector::Intersection intersection = *intersections.begin(); + + osg::Vec3d worldPoint = intersection.getWorldIntersectPoint(); + + Vec3ToLocation(worldPoint, output); + + LOG_INFO("OsgWidget::ScreenToWorldCoordinate - Screen({}, {}) -> World({:.6f}, {:.6f}, {:.2f})", + x, y, output->x(), output->y(), output->z()); + return true; + } + + LOG_WARN("OsgWidget::ScreenToWorldCoordinate - No intersection found for screen coordinates ({}, {})", x, y); + return false; +} + +bool OEScene::Vec3ToLocation(const osg::Vec3& input, osg::Vec3d* output) const { + if (nullptr == output) { + LOG_WARN("OEScene::vec3ToLocation - output is null"); + return false; + } + const osgEarth::SpatialReference* srs = OEScene::GetSrs(); + if (!srs) { + LOG_WARN("OEScene::vec3ToLocation - spatial reference system is null"); + return false; + } + + osgEarth::GeoPoint geoPoint; + geoPoint.fromWorld(srs, input); + + const osgEarth::SpatialReference* wgs84 = osgEarth::SpatialReference::get("wgs84"); + if (wgs84) { + geoPoint = geoPoint.transform(wgs84); + } + + output->set(geoPoint.x(), geoPoint.y(),geoPoint.z()); + return true; +} + const osgEarth::SpatialReference* OEScene::GetSrs() { dyt_check(nullptr != g_srs_); return g_srs_; diff --git a/src/scene/OEScene.h b/src/scene/OEScene.h index d56a954c..f3ba50c6 100644 --- a/src/scene/OEScene.h +++ b/src/scene/OEScene.h @@ -35,6 +35,8 @@ public: } osg::Viewport* GetViewport() const; + bool ScreenToWorldCoordinate(int x, int y, osg::Vec3d* output) const; + bool Vec3ToLocation(const osg::Vec3& input, osg::Vec3d* output) const; static const osgEarth::SpatialReference* GetSrs(); diff --git a/src/translations/Dyt_zh_CN.ts b/src/translations/Dyt_zh_CN.ts index 114ec4c7..49825d5e 100644 --- a/src/translations/Dyt_zh_CN.ts +++ b/src/translations/Dyt_zh_CN.ts @@ -2082,12 +2082,12 @@ OsgWidget - + warning - + open dyt file failed diff --git a/src/ui/ModelBrowser/PresetModelListWidget.cpp b/src/ui/ModelBrowser/PresetModelListWidget.cpp index 3942decf..c0cabf0b 100644 --- a/src/ui/ModelBrowser/PresetModelListWidget.cpp +++ b/src/ui/ModelBrowser/PresetModelListWidget.cpp @@ -57,7 +57,7 @@ void PresetModelListWidget::startDrag(Qt::DropActions supportedActions) { painter.setRenderHint(QPainter::Antialiasing); // Draw semi-transparent background - painter.setBrush(QColor(255, 255, 255, 80)); // White with 70% opacity + painter.setBrush(QColor(255, 255, 255, 50)); // White with 70% opacity painter.setPen(QPen(QColor(200, 200, 200, 200), 1)); // Light gray border painter.drawRoundedRect(2, 2, totalWidth - 4, totalHeight - 4, 4, 4); diff --git a/src/ui/ModelBrowser/PresetModelPanel.ui b/src/ui/ModelBrowser/PresetModelPanel.ui index f0b9eab7..60d64214 100644 --- a/src/ui/ModelBrowser/PresetModelPanel.ui +++ b/src/ui/ModelBrowser/PresetModelPanel.ui @@ -32,7 +32,7 @@ - 1 + 0 @@ -119,8 +119,8 @@ 0 0 - 290 - 470 + 98 + 73 @@ -159,8 +159,8 @@ 0 0 - 290 - 470 + 98 + 73 diff --git a/src/viewer/OsgWidget.cpp b/src/viewer/OsgWidget.cpp index 96628894..5280a035 100644 --- a/src/viewer/OsgWidget.cpp +++ b/src/viewer/OsgWidget.cpp @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include #include @@ -24,6 +26,11 @@ #include "workspace/WorkSpace.h" #include "scutcheon/osgScutcheon.h" +#include "entities/EntitiesManager.h" +#include "entities/ComponentFactory.h" +#include "entities/Entity.h" +#include "entities/Component.h" + static void ConfigureView( osgViewer::View* view ) { view->addEventHandler(new osgViewer::StatsHandler()); view->addEventHandler(new osgViewer::WindowSizeHandler()); @@ -245,13 +252,102 @@ void OsgWidget::dropEvent(QDropEvent* event) { } void OsgWidget::OnPresetModelDropped(const QString& modelType, const QString& modelName, const QPointF& position) { - // TODO: 实现预制模型拖拽处理逻辑 - // 1. 将屏幕坐标转换为世界坐标 - // 2. 创建对应的Entity和MeshComponent - // 3. 添加到场景中 - LOG_INFO("OsgWidget::OnPresetModelDropped - Dropped model type:{} name:{} position:({}, {})", modelType.toStdString(), modelName.toStdString(), position.x(), position.y()); - // 这里暂时只是输出调试信息,后续需要集成实体系统 + WorkSpace* currentWorkSpace = WorkSpaceManager::Get().GetCurrent(); + if (nullptr == currentWorkSpace) { + LOG_WARN("OsgWidget::OnPresetModelDropped - Current workspace is nullptr"); + return; + } + + // 将屏幕坐标转换为世界坐标 + double longitude, latitude, height; + if (!ScreenToWorldCoordinate(static_cast(position.x()), static_cast(position.y()), longitude, latitude, height)) { + LOG_WARN("OsgWidget::OnPresetModelDropped - Failed to convert screen coordinates to world coordinates"); + // 使用默认位置 + longitude = 0.0; + latitude = 0.0; + height = 0.0; + } + + QString meshPath; + if (modelType == "boke") { + meshPath = "boke/boke.ive"; + } else if (modelType == "lsjhqt") { + meshPath = "lsjhqt/lsjhqt.flt"; + } else if (modelType == "nimizi") { + meshPath = "nimizi/nimizi.ive"; + } else if (modelType == "tkdlj") { + meshPath = "tkdlj/tkdlj.ive"; + } else if (modelType == "jiaofan") { + meshPath = "jf/decorative-shape-008.obj"; + } else if (modelType == "satellite") { + meshPath = "satellite/satellite.ive"; + } else { + LOG_WARN("OsgWidget::OnPresetModelDropped - Unknown model type: {}", modelType.toStdString()); + return; + } + + // 创建实体 + Entity* entity = EntitiesManager::Get().CreateMesh(meshPath); + if (nullptr == entity) { + LOG_ERROR("OsgWidget::OnPresetModelDropped - Failed to create entity for mesh: {}", meshPath.toStdString()); + return; + } + + // 设置实体名称(添加序号避免重名) + int count = currentWorkSpace->GetEntities().size(); + entity->SetName(QString("%1_%2").arg(modelName).arg(count)); + + // 设置实体位置 + SceneComponent* rootComponent = entity->GetRootComponent(); + if (rootComponent) { + // 将经纬高坐标转换为OSG世界坐标 + osg::Vec3 worldPos(longitude, latitude, height); + rootComponent->SetLocation(worldPos); + LOG_INFO("OsgWidget::OnPresetModelDropped - Set entity position to ({:.6f}, {:.6f}, {:.2f})", longitude, latitude, height); + } + + // 添加到工作空间 + currentWorkSpace->AddEntity(entity); + + // 添加标签组件 + if (rootComponent) { + SceneComponent* labelComponent = ComponentFactory::Create("LabelComponent", rootComponent); + if (labelComponent) { + labelComponent->AttachTo(rootComponent); + } + } + + // 如果是卫星类型,添加锥波组件 + if (modelType == "satellite") { + if (rootComponent) { + SceneComponent* coneWaveComponent = ComponentFactory::Create("ConeWaveComponent", rootComponent); + if (coneWaveComponent) { + coneWaveComponent->AttachTo(rootComponent); + } + } + } + + LOG_INFO("OsgWidget::OnPresetModelDropped - Successfully created entity: {} with mesh: {} at position ({:.6f}, {:.6f}, {:.2f})", + entity->GetName().toStdString(), meshPath.toStdString(), longitude, latitude, height); +} + +bool OsgWidget::ScreenToWorldCoordinate(int x, int y, double& longitude, double& latitude, double& height) { + if (!activeScene_.valid()) { + LOG_WARN("OsgWidget::ScreenToWorldCoordinate - active scene is null"); + return false; + } + + osg::Vec3d output; + if (!activeScene_->ScreenToWorldCoordinate(x, y, &output)) { + LOG_WARN("OsgWidget::ScreenToWorldCoordinate - Failed to convert screen coordinates to world coordinates"); + return false; + } + + longitude = output.x(); + latitude = output.y(); + height = output.z(); + return true; } diff --git a/src/viewer/OsgWidget.h b/src/viewer/OsgWidget.h index b8664ac4..e8cfc972 100644 --- a/src/viewer/OsgWidget.h +++ b/src/viewer/OsgWidget.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include #include @@ -43,6 +43,8 @@ public slots: */ void OnPresetModelDropped(const QString& modelType, const QString& modelName, const QPointF& position = QPointF()); + bool ScreenToWorldCoordinate(int x, int y, double& longitude, double& latitude, double& altitude); + private: QTimer timer_;