diff --git a/ApplicationCode/Commands/IntersectionBoxCommands/CMakeLists_files.cmake b/ApplicationCode/Commands/IntersectionBoxCommands/CMakeLists_files.cmake index 93d454fd4a..7f3ae05eaf 100644 --- a/ApplicationCode/Commands/IntersectionBoxCommands/CMakeLists_files.cmake +++ b/ApplicationCode/Commands/IntersectionBoxCommands/CMakeLists_files.cmake @@ -5,6 +5,8 @@ if (${CMAKE_VERSION} VERSION_GREATER "2.8.2") endif() set (SOURCE_GROUP_HEADER_FILES +${CEE_CURRENT_LIST_DIR}RicBoxManipulatorEventHandler.h +${CEE_CURRENT_LIST_DIR}RicEditIntersectionBoxFeature.h ${CEE_CURRENT_LIST_DIR}RicAppendIntersectionBoxFeature.h ${CEE_CURRENT_LIST_DIR}RicIntersectionBoxXSliceFeature.h ${CEE_CURRENT_LIST_DIR}RicIntersectionBoxYSliceFeature.h @@ -12,6 +14,8 @@ ${CEE_CURRENT_LIST_DIR}RicIntersectionBoxZSliceFeature.h ) set (SOURCE_GROUP_SOURCE_FILES +${CEE_CURRENT_LIST_DIR}RicBoxManipulatorEventHandler.cpp +${CEE_CURRENT_LIST_DIR}RicEditIntersectionBoxFeature.cpp ${CEE_CURRENT_LIST_DIR}RicAppendIntersectionBoxFeature.cpp ${CEE_CURRENT_LIST_DIR}RicIntersectionBoxXSliceFeature.cpp ${CEE_CURRENT_LIST_DIR}RicIntersectionBoxYSliceFeature.cpp @@ -26,4 +30,11 @@ list(APPEND CODE_SOURCE_FILES ${SOURCE_GROUP_SOURCE_FILES} ) +set (QT_MOC_HEADERS +${QT_MOC_HEADERS} +${CEE_CURRENT_LIST_DIR}RicBoxManipulatorEventHandler.h +${CEE_CURRENT_LIST_DIR}RicEditIntersectionBoxFeature.h +) + + source_group( "CommandFeature\\IntersectionBox" FILES ${SOURCE_GROUP_HEADER_FILES} ${SOURCE_GROUP_SOURCE_FILES} ${CEE_CURRENT_LIST_DIR}CMakeLists_files.cmake ) diff --git a/ApplicationCode/Commands/IntersectionBoxCommands/RicAppendIntersectionBoxFeature.h b/ApplicationCode/Commands/IntersectionBoxCommands/RicAppendIntersectionBoxFeature.h index 78ae599703..c2802b9755 100644 --- a/ApplicationCode/Commands/IntersectionBoxCommands/RicAppendIntersectionBoxFeature.h +++ b/ApplicationCode/Commands/IntersectionBoxCommands/RicAppendIntersectionBoxFeature.h @@ -22,7 +22,6 @@ #include "cafCmdExecuteCommand.h" #include "cafPdmPointer.h" -class RimIntersectionCollection; //================================================================================================== /// diff --git a/ApplicationCode/Commands/IntersectionBoxCommands/RicBoxManipulatorEventHandler.cpp b/ApplicationCode/Commands/IntersectionBoxCommands/RicBoxManipulatorEventHandler.cpp new file mode 100644 index 0000000000..2d852e7875 --- /dev/null +++ b/ApplicationCode/Commands/IntersectionBoxCommands/RicBoxManipulatorEventHandler.cpp @@ -0,0 +1,160 @@ + +#include "RicBoxManipulatorEventHandler.h" + +#include "cafBoxManipulatorPartManager.h" +#include "cafEffectGenerator.h" +#include "cafViewer.h" + +#include "cvfCamera.h" +#include "cvfDrawableGeo.h" +#include "cvfHitItemCollection.h" +#include "cvfModelBasicList.h" +#include "cvfPart.h" +#include "cvfRay.h" + +#include +#include + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RicBoxManipulatorEventHandler::RicBoxManipulatorEventHandler(caf::Viewer* viewer) + : m_viewer(viewer), + m_currentPartIndex(cvf::UNDEFINED_SIZE_T) +{ + m_partManager = new caf::BoxManipulatorPartManager; + m_model = new cvf::ModelBasicList; + + m_viewer->installEventFilter(this); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RicBoxManipulatorEventHandler::~RicBoxManipulatorEventHandler() +{ + m_viewer->removeEventFilter(this); + + // Make sure the model owned by this manipulator is not used anywhere else + CVF_ASSERT(m_model->refCount() == 1); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicBoxManipulatorEventHandler::setOrigin(const cvf::Vec3d& origin) +{ + m_partManager->setOrigin(origin); + + updateParts(); + emit notifyRedraw(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicBoxManipulatorEventHandler::setSize(const cvf::Vec3d& size) +{ + m_partManager->setSize(size); + + updateParts(); + emit notifyRedraw(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Model* RicBoxManipulatorEventHandler::model() +{ + return m_model.p(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicBoxManipulatorEventHandler::eventFilter(QObject *obj, QEvent* inputEvent) +{ + if (inputEvent->type() == QEvent::MouseButtonPress) + { + QMouseEvent* mouseEvent = static_cast(inputEvent); + + if (mouseEvent->button() == Qt::LeftButton) + { + cvf::HitItemCollection hitItems; + if (m_viewer->rayPick(mouseEvent->x(), mouseEvent->y(), &hitItems)) + { + if (hitItems.firstItem() && hitItems.firstItem()->part()) + { + m_currentPartIndex = m_partManager->partIndexFromSourceInfo(hitItems.firstItem()->part(), hitItems.firstItem()->intersectionPoint()); + + if (m_currentPartIndex != cvf::UNDEFINED_SIZE_T) + { + updateParts(); + emit notifyRedraw(); + + return true; + } + } + } + } + } + else if (inputEvent->type() == QEvent::MouseMove) + { + if (m_currentPartIndex != cvf::UNDEFINED_SIZE_T) + { + QMouseEvent* mouseEvent = static_cast(inputEvent); + + //qDebug() << "Inside mouse move"; + //qDebug() << mouseEvent->pos(); + + int translatedMousePosX = mouseEvent->pos().x(); + int translatedMousePosY = m_viewer->height() - mouseEvent->pos().y(); + + cvf::ref ray = m_viewer->mainCamera()->rayFromWindowCoordinates(translatedMousePosX, translatedMousePosY); + { + m_partManager->updateFromPartIndexAndRay(m_currentPartIndex, ray.p()); + + updateParts(); + + cvf::Vec3d origin; + cvf::Vec3d size; + m_partManager->originAndSize(&origin, &size); + + emit notifyUpdate(origin, size); + + emit notifyRedraw(); + + return true; + } + } + } + else if (inputEvent->type() == QEvent::MouseButtonRelease) + { + if (m_currentPartIndex != cvf::UNDEFINED_SIZE_T) + { + m_currentPartIndex = cvf::UNDEFINED_SIZE_T; + + cvf::Vec3d origin; + cvf::Vec3d size; + m_partManager->originAndSize(&origin, &size); + + emit notifyUpdate(origin, size); + + return true; + } + } + + return false; +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicBoxManipulatorEventHandler::updateParts() +{ + m_model->removeAllParts(); + + m_partManager->appendPartsToModel(m_model.p()); +} + diff --git a/ApplicationCode/Commands/IntersectionBoxCommands/RicBoxManipulatorEventHandler.h b/ApplicationCode/Commands/IntersectionBoxCommands/RicBoxManipulatorEventHandler.h new file mode 100644 index 0000000000..aeb233e602 --- /dev/null +++ b/ApplicationCode/Commands/IntersectionBoxCommands/RicBoxManipulatorEventHandler.h @@ -0,0 +1,62 @@ + +#pragma once + +#include "cvfBase.h" +#include "cvfObject.h" +#include "cvfMatrix4.h" +#include "cvfVector3.h" + +#include +#include + +namespace cvf { + class Model; + class ModelBasicList; +}; + + +namespace caf { + class BoxManipulatorPartManager; + class Viewer; +}; + +class QMouseEvent; + + + +//================================================================================================== +// +// +//================================================================================================== +class RicBoxManipulatorEventHandler : public QObject +{ + Q_OBJECT + +public: + RicBoxManipulatorEventHandler(caf::Viewer* viewer); + ~RicBoxManipulatorEventHandler(); + + void setOrigin(const cvf::Vec3d& origin); + void setSize(const cvf::Vec3d& size); + + cvf::Model* model(); + +signals: + void notifyRedraw(); + void notifyUpdate(const cvf::Vec3d& origin, const cvf::Vec3d& size); + +protected: + bool eventFilter(QObject *obj, QEvent *event); + +private: + void updateParts(); + +private: + cvf::ref m_model; + QPointer m_viewer; + + size_t m_currentPartIndex; + + cvf::ref m_partManager; +}; + diff --git a/ApplicationCode/Commands/IntersectionBoxCommands/RicEditIntersectionBoxFeature.cpp b/ApplicationCode/Commands/IntersectionBoxCommands/RicEditIntersectionBoxFeature.cpp new file mode 100644 index 0000000000..bbc526194f --- /dev/null +++ b/ApplicationCode/Commands/IntersectionBoxCommands/RicEditIntersectionBoxFeature.cpp @@ -0,0 +1,146 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2016- Statoil ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RicEditIntersectionBoxFeature.h" + +#include "RiaApplication.h" + +#include "RicBoxManipulatorEventHandler.h" + +#include "RimCase.h" +#include "RimIntersectionBox.h" +#include "RimView.h" + +#include "RiuViewer.h" + +#include "cafDisplayCoordTransform.h" + +#include + +CAF_CMD_SOURCE_INIT(RicEditIntersectionBoxFeature, "RicEditIntersectionBoxFeature"); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +RicEditIntersectionBoxFeature::RicEditIntersectionBoxFeature() + : m_eventHandler(nullptr), + m_intersectionBox(nullptr) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicEditIntersectionBoxFeature::slotScheduleRedraw() +{ + RimView* activeView = RiaApplication::instance()->activeReservoirView(); + if (activeView && activeView->viewer()) + { + activeView->viewer()->addStaticModelOnce(m_eventHandler->model()); + + activeView->scheduleCreateDisplayModelAndRedraw(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicEditIntersectionBoxFeature::slotUpdateGeometry(const cvf::Vec3d& origin, const cvf::Vec3d& size) +{ + if (m_intersectionBox) + { + RimView* activeView = RiaApplication::instance()->activeReservoirView(); + if (activeView) + { + cvf::ref transForm = activeView->displayCoordTransform(); + + cvf::Vec3d domainOrigin = transForm->transformToDomainCoord(origin); + cvf::Vec3d domainSize = transForm->scaleToDomainSize(size); + + m_intersectionBox->setFromOriginAndSize(domainOrigin, domainSize); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicEditIntersectionBoxFeature::isCommandEnabled() +{ + return true; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicEditIntersectionBoxFeature::onActionTriggered(bool isChecked) +{ + RiuViewer* viewer = nullptr; + + RimView* activeView = RiaApplication::instance()->activeReservoirView(); + if (activeView && activeView->viewer()) + { + viewer = activeView->viewer(); + } + + if (isCommandChecked() && m_eventHandler) + { + if (viewer) + { + viewer->removeStaticModel(m_eventHandler->model()); + } + + m_eventHandler->deleteLater(); + m_eventHandler = nullptr; + + m_intersectionBox = nullptr; + } + else if (viewer) + { + m_intersectionBox = dynamic_cast(viewer->lastPickedObject()); + if (m_intersectionBox) + { + m_eventHandler = new RicBoxManipulatorEventHandler(viewer); + connect(m_eventHandler, SIGNAL(notifyRedraw()), this, SLOT(slotScheduleRedraw())); + connect(m_eventHandler, SIGNAL(notifyUpdate(const cvf::Vec3d&, const cvf::Vec3d&)), this, SLOT(slotUpdateGeometry(const cvf::Vec3d&, const cvf::Vec3d&))); + + cvf::ref transForm = activeView->displayCoordTransform(); + + m_eventHandler->setOrigin(transForm->transformToDisplayCoord(m_intersectionBox->boxOrigin().translation())); + m_eventHandler->setSize(transForm->scaleToDisplaySize(m_intersectionBox->boxSize())); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RicEditIntersectionBoxFeature::setupActionLook(QAction* actionToSetup) +{ + actionToSetup->setIcon(QIcon(":/IntersectionBox16x16.png")); + actionToSetup->setText("Edit Intersection Box"); + actionToSetup->setCheckable(true); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool RicEditIntersectionBoxFeature::isCommandChecked() +{ + return m_eventHandler != NULL; +} diff --git a/ApplicationCode/Commands/IntersectionBoxCommands/RicEditIntersectionBoxFeature.h b/ApplicationCode/Commands/IntersectionBoxCommands/RicEditIntersectionBoxFeature.h new file mode 100644 index 0000000000..334c89ff5e --- /dev/null +++ b/ApplicationCode/Commands/IntersectionBoxCommands/RicEditIntersectionBoxFeature.h @@ -0,0 +1,55 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2016- Statoil ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "cafCmdFeature.h" + + +class RicBoxManipulatorEventHandler; +class RimIntersectionBox; + + +//================================================================================================== +/// +//================================================================================================== +class RicEditIntersectionBoxFeature : public caf::CmdFeature +{ + Q_OBJECT; + + CAF_CMD_HEADER_INIT; + +public: + RicEditIntersectionBoxFeature(); + +public slots: + void slotScheduleRedraw(); + void slotUpdateGeometry(const cvf::Vec3d& origin, const cvf::Vec3d& size); + +protected: + // Overrides + virtual bool isCommandEnabled() override; + virtual void onActionTriggered( bool isChecked ) override; + virtual void setupActionLook( QAction* actionToSetup ) override; + virtual bool isCommandChecked() override; + +private: + RicBoxManipulatorEventHandler* m_eventHandler; + RimIntersectionBox* m_intersectionBox; +}; + diff --git a/ApplicationCode/ModelVisualization/Intersections/RivIntersectionBoxSourceInfo.cpp b/ApplicationCode/ModelVisualization/Intersections/RivIntersectionBoxSourceInfo.cpp index 59a8b22ae6..9c5202243c 100644 --- a/ApplicationCode/ModelVisualization/Intersections/RivIntersectionBoxSourceInfo.cpp +++ b/ApplicationCode/ModelVisualization/Intersections/RivIntersectionBoxSourceInfo.cpp @@ -40,3 +40,11 @@ const std::vector& RivIntersectionBoxSourceInfo::triangleToCellIndex() c return m_intersectionBoxGeometryGenerator->triangleToCellIndex(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const RimIntersectionBox* RivIntersectionBoxSourceInfo::intersectionBox() const +{ + return m_intersectionBoxGeometryGenerator->intersectionBox(); +} + diff --git a/ApplicationCode/ModelVisualization/Intersections/RivIntersectionBoxSourceInfo.h b/ApplicationCode/ModelVisualization/Intersections/RivIntersectionBoxSourceInfo.h index e4f4aeb010..7718c35893 100644 --- a/ApplicationCode/ModelVisualization/Intersections/RivIntersectionBoxSourceInfo.h +++ b/ApplicationCode/ModelVisualization/Intersections/RivIntersectionBoxSourceInfo.h @@ -32,6 +32,8 @@ public: const std::vector& triangleToCellIndex() const; + const RimIntersectionBox* intersectionBox() const; + private: cvf::cref m_intersectionBoxGeometryGenerator; }; diff --git a/ApplicationCode/ProjectDataModel/RimIntersectionBox.cpp b/ApplicationCode/ProjectDataModel/RimIntersectionBox.cpp index b44901d10a..1aeb60410c 100644 --- a/ApplicationCode/ProjectDataModel/RimIntersectionBox.cpp +++ b/ApplicationCode/ProjectDataModel/RimIntersectionBox.cpp @@ -104,6 +104,24 @@ cvf::Vec3d RimIntersectionBox::boxSize() const return cvf::Vec3d(m_maxXCoord, m_maxYCoord, m_maxDepth) - cvf::Vec3d(m_minXCoord, m_minYCoord, m_minDepth); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimIntersectionBox::setFromOriginAndSize(const cvf::Vec3d& origin, const cvf::Vec3d& size) +{ + m_minXCoord = origin.x(); + m_minYCoord = origin.y(); + m_minZCoord = origin.z(); + + m_maxXCoord = origin.x() + size.x(); + m_maxYCoord = origin.y() + size.y(); + m_maxZCoord = origin.z() + size.z(); + + updateConnectedEditors(); + + rebuildGeometryAndScheduleCreateDisplayModel(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/ProjectDataModel/RimIntersectionBox.h b/ApplicationCode/ProjectDataModel/RimIntersectionBox.h index 97e6d749e6..4b9013c350 100644 --- a/ApplicationCode/ProjectDataModel/RimIntersectionBox.h +++ b/ApplicationCode/ProjectDataModel/RimIntersectionBox.h @@ -55,6 +55,7 @@ public: cvf::Mat4d boxOrigin() const; cvf::Vec3d boxSize() const; SinglePlaneState singlePlaneState() const; + void setFromOriginAndSize(const cvf::Vec3d& origin, const cvf::Vec3d& size); RivIntersectionBoxPartMgr* intersectionBoxPartMgr(); diff --git a/ApplicationCode/ProjectDataModel/RimView.cpp b/ApplicationCode/ProjectDataModel/RimView.cpp index 64a4583f87..a2ac2e1150 100644 --- a/ApplicationCode/ProjectDataModel/RimView.cpp +++ b/ApplicationCode/ProjectDataModel/RimView.cpp @@ -24,8 +24,10 @@ #include "RivWellPathCollectionPartMgr.h" +#include "cafDisplayCoordTransform.h" #include "cafFrameAnimationControl.h" #include "cafPdmObjectFactory.h" + #include "cvfCamera.h" #include "cvfModel.h" #include "cvfModelBasicList.h" @@ -921,3 +923,22 @@ void RimView::zoomAll() } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref RimView::displayCoordTransform() +{ + cvf::ref coordTrans = new caf::DisplayCoordTransform; + + cvf::Vec3d scale(1.0, 1.0, scaleZ); + coordTrans->setScale(scale); + + RimCase* rimCase = ownerCase(); + if (rimCase) + { + coordTrans->setTranslation(rimCase->displayModelOffset()); + } + + return coordTrans; +} + diff --git a/ApplicationCode/ProjectDataModel/RimView.h b/ApplicationCode/ProjectDataModel/RimView.h index 79c6188de3..9bb2dc1a9a 100644 --- a/ApplicationCode/ProjectDataModel/RimView.h +++ b/ApplicationCode/ProjectDataModel/RimView.h @@ -61,6 +61,10 @@ namespace cvf class Part; } +namespace caf +{ + class DisplayCoordTransform; +} //================================================================================================== /// /// @@ -159,6 +163,8 @@ public: virtual void zoomAll() override; + cvf::ref displayCoordTransform(); + public: virtual void loadDataAndUpdate() = 0; virtual RimCase* ownerCase() = 0; diff --git a/ApplicationCode/UserInterface/RiuViewer.cpp b/ApplicationCode/UserInterface/RiuViewer.cpp index 6381e11a60..29e0f0de59 100644 --- a/ApplicationCode/UserInterface/RiuViewer.cpp +++ b/ApplicationCode/UserInterface/RiuViewer.cpp @@ -710,6 +710,16 @@ cvf::Vec3d RiuViewer::lastPickPositionInDomainCoords() const return m_viewerCommands->lastPickPositionInDomainCoords(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::PdmObject* RiuViewer::lastPickedObject() const +{ + CVF_ASSERT(m_viewerCommands); + + return m_viewerCommands->currentPickedObject(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/UserInterface/RiuViewer.h b/ApplicationCode/UserInterface/RiuViewer.h index 6c5cc28d0c..658c5cfee8 100644 --- a/ApplicationCode/UserInterface/RiuViewer.h +++ b/ApplicationCode/UserInterface/RiuViewer.h @@ -90,6 +90,7 @@ public: void setAxisLabels(const cvf::String& xLabel, const cvf::String& yLabel, const cvf::String& zLabel); cvf::Vec3d lastPickPositionInDomainCoords() const; + caf::PdmObject* lastPickedObject() const; public slots: virtual void slotSetCurrentFrame(int frameIndex); diff --git a/ApplicationCode/UserInterface/RiuViewerCommands.cpp b/ApplicationCode/UserInterface/RiuViewerCommands.cpp index 0b0a26a855..bbe8fd8195 100644 --- a/ApplicationCode/UserInterface/RiuViewerCommands.cpp +++ b/ApplicationCode/UserInterface/RiuViewerCommands.cpp @@ -47,6 +47,7 @@ #include "RimGeoMechCase.h" #include "RimGeoMechCellColors.h" #include "RimGeoMechView.h" +#include "RimIntersectionBox.h" #include "RimLegendConfig.h" #include "RimTernaryLegendConfig.h" #include "RimViewController.h" @@ -133,6 +134,7 @@ void RiuViewerCommands::displayContextMenu(QMouseEvent* event) { m_currentGridIdx = cvf::UNDEFINED_SIZE_T; m_currentCellIndex = cvf::UNDEFINED_SIZE_T; + m_currentPickedObject = nullptr; int winPosX = event->x(); int winPosY = event->y(); @@ -195,7 +197,7 @@ void RiuViewerCommands::displayContextMenu(QMouseEvent* event) { findCellAndGridIndex(crossSectionSourceInfo, firstPartTriangleIndex, &m_currentCellIndex, &m_currentGridIdx); m_currentFaceIndex = cvf::StructGridInterface::NO_FACE; - m_currentCrossSection = const_cast(crossSectionSourceInfo->crossSection()); + m_currentPickedObject = const_cast(crossSectionSourceInfo->crossSection()); menu.addAction(QString("Hide intersection"), this, SLOT(slotHideIntersection())); } @@ -203,6 +205,14 @@ void RiuViewerCommands::displayContextMenu(QMouseEvent* event) { findCellAndGridIndex(intersectionBoxSourceInfo, firstPartTriangleIndex, &m_currentCellIndex, &m_currentGridIdx); m_currentFaceIndex = cvf::StructGridInterface::NO_FACE; + + m_currentPickedObject = const_cast(intersectionBoxSourceInfo->intersectionBox()); + menu.addAction(caf::CmdFeatureManager::instance()->action("RicEditIntersectionBoxFeature")); + menu.addSeparator(); + + QStringList commandIdList; + commandIdList << "RicEditIntersectionBoxFeature"; + caf::CmdFeatureManager::instance()->refreshCheckedState(commandIdList); } // IJK -slice commands @@ -442,10 +452,11 @@ void RiuViewerCommands::slotAddGeoMechPropertyFilter() //-------------------------------------------------------------------------------------------------- void RiuViewerCommands::slotHideIntersection() { - if (m_currentCrossSection) + RimIntersection* rimIntersection = dynamic_cast(currentPickedObject()); + if (rimIntersection) { - m_currentCrossSection->isActive = false; - m_currentCrossSection->updateConnectedEditors(); + rimIntersection->isActive = false; + rimIntersection->updateConnectedEditors(); if (m_reservoirView) { @@ -591,6 +602,14 @@ cvf::Vec3d RiuViewerCommands::lastPickPositionInDomainCoords() const return m_currentPickPositionInDomainCoords; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::PdmObject* RiuViewerCommands::currentPickedObject() const +{ + return m_currentPickedObject; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationCode/UserInterface/RiuViewerCommands.h b/ApplicationCode/UserInterface/RiuViewerCommands.h index f753f9ecc0..1e4c3f7efe 100644 --- a/ApplicationCode/UserInterface/RiuViewerCommands.h +++ b/ApplicationCode/UserInterface/RiuViewerCommands.h @@ -36,6 +36,10 @@ class RivIntersectionSourceInfo; class QMouseEvent; +namespace caf { + class PdmObject; +} + namespace cvf { class HitItemCollection; class Part; @@ -55,6 +59,8 @@ public: void handlePickAction(int winPosX, int winPosY, Qt::KeyboardModifiers keyboardModifiers); cvf::Vec3d lastPickPositionInDomainCoords() const; + caf::PdmObject* currentPickedObject() const; + private slots: void slotRangeFilterI(); void slotRangeFilterJ(); @@ -80,7 +86,7 @@ private: cvf::Vec3d m_currentPickPositionInDomainCoords; caf::PdmPointer m_reservoirView; - caf::PdmPointer m_currentCrossSection; + caf::PdmPointer m_currentPickedObject; QPointer m_viewer; diff --git a/Fwk/AppFwk/cafVizExtensions/CMakeLists.txt b/Fwk/AppFwk/cafVizExtensions/CMakeLists.txt index 4a0aa4a512..a743f3b293 100644 --- a/Fwk/AppFwk/cafVizExtensions/CMakeLists.txt +++ b/Fwk/AppFwk/cafVizExtensions/CMakeLists.txt @@ -15,6 +15,12 @@ include_directories( ) add_library( ${PROJECT_NAME} + cafDisplayCoordTransform.cpp + cafDisplayCoordTransform.h + cafBoxManipulatorPartManager.cpp + cafBoxManipulatorPartManager.h + cafBoxManipulatorGeometryGenerator.cpp + cafBoxManipulatorGeometryGenerator.h cafCategoryLegend.cpp cafCategoryLegend.h cafCategoryMapper.cpp diff --git a/Fwk/AppFwk/cafVizExtensions/cafBoxManipulatorGeometryGenerator.cpp b/Fwk/AppFwk/cafVizExtensions/cafBoxManipulatorGeometryGenerator.cpp new file mode 100644 index 0000000000..8a1254cc76 --- /dev/null +++ b/Fwk/AppFwk/cafVizExtensions/cafBoxManipulatorGeometryGenerator.cpp @@ -0,0 +1,125 @@ + +#include "cafBoxManipulatorGeometryGenerator.h" + +#include "cvfBoxGenerator.h" +#include "cvfDrawableGeo.h" +#include "cvfGeometryBuilderFaceList.h" +#include "cvfPrimitiveSetIndexedUInt.h" + + +using namespace cvf; + +namespace caf { + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +BoxManipulatorGeometryGenerator::BoxManipulatorGeometryGenerator() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +BoxManipulatorGeometryGenerator::~BoxManipulatorGeometryGenerator() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void BoxManipulatorGeometryGenerator::setOrigin(const cvf::Vec3d& origin) +{ + m_origin = origin; + + m_vertices = nullptr; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void BoxManipulatorGeometryGenerator::setSize(const cvf::Vec3d& size) +{ + m_size = size; + + m_vertices = nullptr; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref BoxManipulatorGeometryGenerator::createBoundingBoxMeshDrawable() +{ + if (m_vertices.isNull()) + { + calculateArrays(); + } + + if (!(m_vertices.notNull() && m_vertices->size() != 0)) return NULL; + + cvf::ref geo = new cvf::DrawableGeo; + geo->setVertexArray(m_vertices.p()); + + cvf::ref indices = lineIndicesFromQuadVertexArray(m_vertices.p()); + cvf::ref prim = new cvf::PrimitiveSetIndexedUInt(cvf::PT_LINES); + prim->setIndices(indices.p()); + + geo->addPrimitiveSet(prim.p()); + + return geo; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void BoxManipulatorGeometryGenerator::calculateArrays() +{ + BoxGenerator gen; + + cvf::Vec3d min = m_origin; + cvf::Vec3d max = m_origin + m_size; + + gen.setMinMax(min, max); + gen.setSubdivisions(1, 1, 1); + GeometryBuilderFaceList builder; + gen.generate(&builder); + + m_vertices = builder.vertices(); + + // TODO: Rotate generated vertices +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref BoxManipulatorGeometryGenerator::lineIndicesFromQuadVertexArray(const cvf::Vec3fArray* vertexArray) +{ + CVF_ASSERT(vertexArray); + + size_t numVertices = vertexArray->size(); + int numQuads = static_cast(numVertices / 4); + CVF_ASSERT(numVertices % 4 == 0); + + cvf::ref indices = new cvf::UIntArray; + indices->resize(numQuads * 8); + +#pragma omp parallel for + for (int i = 0; i < numQuads; i++) + { + int idx = 8 * i; + indices->set(idx + 0, i * 4 + 0); + indices->set(idx + 1, i * 4 + 1); + indices->set(idx + 2, i * 4 + 1); + indices->set(idx + 3, i * 4 + 2); + indices->set(idx + 4, i * 4 + 2); + indices->set(idx + 5, i * 4 + 3); + indices->set(idx + 6, i * 4 + 3); + indices->set(idx + 7, i * 4 + 0); + } + + return indices; +} + +} // namespace cvf + diff --git a/Fwk/AppFwk/cafVizExtensions/cafBoxManipulatorGeometryGenerator.h b/Fwk/AppFwk/cafVizExtensions/cafBoxManipulatorGeometryGenerator.h new file mode 100644 index 0000000000..9d12a4bab6 --- /dev/null +++ b/Fwk/AppFwk/cafVizExtensions/cafBoxManipulatorGeometryGenerator.h @@ -0,0 +1,45 @@ + +#pragma once + +#include "cvfBase.h" +#include "cvfObject.h" +#include "cvfVector3.h" +#include "cvfArray.h" +#include "cvfBoundingBox.h" + +namespace cvf { + class DrawableGeo; +} + + +namespace caf { + + +//================================================================================================== +// +// +//================================================================================================== +class BoxManipulatorGeometryGenerator : public cvf::Object +{ +public: + BoxManipulatorGeometryGenerator(); + ~BoxManipulatorGeometryGenerator(); + + void setOrigin(const cvf::Vec3d& origin); + void setSize(const cvf::Vec3d& size); + + cvf::ref createBoundingBoxMeshDrawable(); + +private: + void calculateArrays(); + + static cvf::ref lineIndicesFromQuadVertexArray(const cvf::Vec3fArray* vertexArray); + +private: + cvf::Vec3d m_origin; + cvf::Vec3d m_size; + + cvf::ref m_vertices; +}; + +} diff --git a/Fwk/AppFwk/cafVizExtensions/cafBoxManipulatorPartManager.cpp b/Fwk/AppFwk/cafVizExtensions/cafBoxManipulatorPartManager.cpp new file mode 100644 index 0000000000..03eee25f3e --- /dev/null +++ b/Fwk/AppFwk/cafVizExtensions/cafBoxManipulatorPartManager.cpp @@ -0,0 +1,470 @@ + +#include "cafBoxManipulatorPartManager.h" + +#include "cafBoxManipulatorGeometryGenerator.h" +#include "cafEffectGenerator.h" + +#include "cvfBoxGenerator.h" +#include "cvfDrawableGeo.h" +#include "cvfGeometryBuilderFaceList.h" +#include "cvfModelBasicList.h" +#include "cvfPart.h" +#include "cvfPrimitiveSetIndexedUInt.h" +#include "cvfPrimitiveSetIndexedUShort.h" +#include "cvfRay.h" + + +using namespace cvf; + +namespace caf { + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +BoxManipulatorPartManager::BoxManipulatorPartManager() +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void BoxManipulatorPartManager::setOrigin(const cvf::Vec3d& origin) +{ + m_origin = origin; + + clearAllGeometryAndParts(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void BoxManipulatorPartManager::setSize(const cvf::Vec3d& size) +{ + m_size = size; + + clearAllGeometryAndParts(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void BoxManipulatorPartManager::originAndSize(cvf::Vec3d* origin, cvf::Vec3d* size) +{ + *origin = m_origin; + *size = m_size; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void BoxManipulatorPartManager::appendPartsToModel(cvf::ModelBasicList* model) +{ + if (m_boundingBoxPart.isNull()) + { + recreateAllGeometryAndParts(); + } + + CVF_ASSERT(m_boundingBoxPart.notNull()); + model->addPart(m_boundingBoxPart.p()); + + for (size_t i = 0; i < m_cubeParts.size(); i++) + { + model->addPart(m_cubeParts.at(i)); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +size_t BoxManipulatorPartManager::partIndexFromSourceInfo(const cvf::Part* candidatePart, const cvf::Vec3d& intersectionPoint) +{ + if (!candidatePart) return cvf::UNDEFINED_SIZE_T; + + const cvf::Object* siConstObj = candidatePart->sourceInfo(); + cvf::Object* siObj = const_cast(siConstObj); + + BoxManipulatorSourceInfo* candidateSourceInfo = dynamic_cast(siObj); + if (!candidateSourceInfo) return cvf::UNDEFINED_SIZE_T; + + for (size_t i = 0; i < m_cubeParts.size(); i++) + { + cvf::Part* part = m_cubeParts.at(i); + BoxManipulatorSourceInfo* si = static_cast(part->sourceInfo()); + + if (si->m_cubeFace == candidateSourceInfo->m_cubeFace && + si->m_cubeFaceItem == candidateSourceInfo->m_cubeFaceItem) + { + m_initialPickPoint = intersectionPoint; + + return i; + } + } + + return cvf::UNDEFINED_SIZE_T; +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void BoxManipulatorPartManager::updateFromPartIndexAndRay(size_t partIndex, const cvf::Ray* ray) +{ + BoxCubeFace face = m_cubeItemType[partIndex].first; + cvf::Vec3d faceDir = normalFromFace(face); + + cvf::Vec3d closestPoint1; + cvf::Vec3d closestPoint2; + BoxManipulatorPartManager::closestPointOfTwoLines(ray->origin(), ray->origin() + ray->direction(), m_initialPickPoint, m_initialPickPoint + faceDir, &closestPoint1, &closestPoint2); + + cvf::Vec3d newOrigin = m_origin; + cvf::Vec3d newSize = m_size; + + switch (face) + { + case caf::BoxManipulatorPartManager::BCF_X_POS: + newSize.x() = CVF_MAX(0.0, closestPoint2.x() - m_origin.x()); + break; + case caf::BoxManipulatorPartManager::BCF_X_NEG: + if (m_size.x() - (closestPoint2.x() - m_origin.x()) > 0.0) + { + newOrigin.x() = closestPoint2.x(); + newSize.x() = m_size.x() - (closestPoint2.x() - m_origin.x()); + } + else + { + newOrigin.x() = m_origin.x() + m_size.x(); + newSize.x() = 0.0; + } + break; + case caf::BoxManipulatorPartManager::BCF_Y_POS: + newSize.y() = CVF_MAX(0.0, closestPoint2.y() - m_origin.y()); + break; + case caf::BoxManipulatorPartManager::BCF_Y_NEG: + if (m_size.y() - (closestPoint2.y() - m_origin.y()) > 0.0) + { + newOrigin.y() = closestPoint2.y(); + newSize.y() = m_size.y() - (closestPoint2.y() - m_origin.y()); + } + else + { + newOrigin.y() = m_origin.y() + m_size.y(); + newSize.y() = 0.0; + } + break; + case caf::BoxManipulatorPartManager::BCF_Z_POS: + newSize.z() = CVF_MAX(0.0, closestPoint2.z() - m_origin.z()); + break; + case caf::BoxManipulatorPartManager::BCF_Z_NEG: + if (m_size.z() - (closestPoint2.z() - m_origin.z()) > 0.0) + { + newOrigin.z() = closestPoint2.z(); + newSize.z() = m_size.z() - (closestPoint2.z() - m_origin.z()); + } + else + { + newOrigin.z() = m_origin.z() + m_size.z(); + newSize.z() = 0.0; + } + break; + default: + break; + } + + setOrigin(newOrigin); + setSize(newSize); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Vec3d BoxManipulatorPartManager::normalFromFace(BoxCubeFace face) +{ + switch (face) + { + case caf::BoxManipulatorPartManager::BCF_X_POS: + return cvf::Vec3d::X_AXIS; + break; + case caf::BoxManipulatorPartManager::BCF_X_NEG: + return -cvf::Vec3d::X_AXIS; + break; + case caf::BoxManipulatorPartManager::BCF_Y_POS: + return cvf::Vec3d::Y_AXIS; + break; + case caf::BoxManipulatorPartManager::BCF_Y_NEG: + return -cvf::Vec3d::Y_AXIS; + break; + case caf::BoxManipulatorPartManager::BCF_Z_POS: + return cvf::Vec3d::Z_AXIS; + break; + case caf::BoxManipulatorPartManager::BCF_Z_NEG: + return -cvf::Vec3d::Z_AXIS; + break; + default: + CVF_ASSERT(false); + break; + } + + return cvf::Vec3d::UNDEFINED; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void BoxManipulatorPartManager::createCubeGeos() +{ + Vec3f cp[8]; + navCubeCornerPoints(cp); + + createCubeFaceGeos(BCF_Y_NEG, cp[0], cp[1], cp[5], cp[4]); + createCubeFaceGeos(BCF_Y_POS, cp[2], cp[3], cp[7], cp[6]); + + createCubeFaceGeos(BCF_Z_POS, cp[4], cp[5], cp[6], cp[7]); + createCubeFaceGeos(BCF_Z_NEG, cp[3], cp[2], cp[1], cp[0]); + + createCubeFaceGeos(BCF_X_NEG, cp[3], cp[0], cp[4], cp[7]); + createCubeFaceGeos(BCF_X_POS, cp[1], cp[2], cp[6], cp[5]); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void BoxManipulatorPartManager::createCubeFaceGeos(BoxCubeFace face, cvf::Vec3f p1, cvf::Vec3f p2, cvf::Vec3f p3, cvf::Vec3f p4) +{ + float centerItemHeight = (p1 - p2).length(); + if ((p2 - p3).length() < centerItemHeight) + { + centerItemHeight = (p2 - p3).length(); + } + + float centerItemFactor = 0.1f; + centerItemHeight *= centerItemFactor; + + Vec3f center = (p1 + p3) / 2.0f; + Vec3f u = (p2 - p1).getNormalized() * centerItemHeight; + Vec3f v = (p4 - p1).getNormalized() * centerItemHeight; + + Vec3f pi1 = center - u / 2.0 - v / 2.0; + + Vec3f pi2 = pi1 + u; + Vec3f pi3 = pi2 + v; + Vec3f pi4 = pi1 + v; + + // Inner part + m_cubeItemType.push_back(navCubeItem(face, BCFI_CENTER)); + m_cubeGeos.push_back(createQuadGeo(pi1, pi2, pi3, pi4).p()); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref BoxManipulatorPartManager::createQuadGeo(const cvf::Vec3f& v1, const cvf::Vec3f& v2, const cvf::Vec3f& v3, const cvf::Vec3f& v4) +{ + ref geo = new DrawableGeo; + + ref vertexArray = new Vec3fArray(4); + vertexArray->set(0, v1); + vertexArray->set(1, v2); + vertexArray->set(2, v3); + vertexArray->set(3, v4); + + geo->setVertexArray(vertexArray.p()); + + ref indices = new cvf::UShortArray(6); + indices->set(0, 0); + indices->set(1, 1); + indices->set(2, 2); + indices->set(3, 0); + indices->set(4, 2); + indices->set(5, 3); + + ref primSet = new cvf::PrimitiveSetIndexedUShort(cvf::PT_TRIANGLES); + primSet->setIndices(indices.p()); + geo->addPrimitiveSet(primSet.p()); + geo->computeNormals(); + + return geo; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void BoxManipulatorPartManager::navCubeCornerPoints(cvf::Vec3f points[8]) +{ + Vec3f offset(1.0, 1.0, 1.0); + + Vec3f min(m_origin); + min -= offset; + + Vec3f max(m_origin + m_size); + max += offset; + + points[0].set(min.x(), min.y(), min.z()); + points[1].set(max.x(), min.y(), min.z()); + points[2].set(max.x(), max.y(), min.z()); + points[3].set(min.x(), max.y(), min.z()); + points[4].set(min.x(), min.y(), max.z()); + points[5].set(max.x(), min.y(), max.z()); + points[6].set(max.x(), max.y(), max.z()); + points[7].set(min.x(), max.y(), max.z()); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::pair BoxManipulatorPartManager::navCubeItem(BoxCubeFace face, NavCubeFaceItem faceItem) const +{ + return std::make_pair(face, faceItem); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void BoxManipulatorPartManager::clearAllGeometryAndParts() +{ + m_boundingBoxPart = nullptr; + m_cubeGeos.clear(); + m_cubeItemType.clear(); + m_cubeParts.clear(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void BoxManipulatorPartManager::recreateAllGeometryAndParts() +{ + createBoundingBoxPart(); + createCubeGeos(); + createCubeParts(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void BoxManipulatorPartManager::createBoundingBoxPart() +{ + m_boundingBoxPart = nullptr; + + cvf::ref geometryGenerator = new caf::BoxManipulatorGeometryGenerator; + geometryGenerator->setOrigin(m_origin); + geometryGenerator->setSize(m_size); + + cvf::ref geoMesh = geometryGenerator->createBoundingBoxMeshDrawable(); + if (geoMesh.notNull()) + { + cvf::ref part = new cvf::Part; + part->setName("Box Manipulator Mesh"); + part->setDrawable(geoMesh.p()); + + part->updateBoundingBox(); + // part->setEnableMask(meshFaultBit); + // part->setPriority(priMesh); + + cvf::ref eff; + caf::MeshEffectGenerator effectGenerator(cvf::Color3::WHITE); + eff = effectGenerator.generateCachedEffect(); + part->setEffect(eff.p()); + + m_boundingBoxPart = part; + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void BoxManipulatorPartManager::createCubeParts() +{ + for (size_t i = 0; i < m_cubeGeos.size(); i++) + { + cvf::DrawableGeo* geoMesh = m_cubeGeos.at(i); + if (geoMesh) + { + cvf::ref part = new cvf::Part; + part->setName("Box Manipulator Mesh"); + part->setDrawable(geoMesh); + + part->updateBoundingBox(); + // part->setEnableMask(meshFaultBit); + // part->setPriority(priMesh); + + + caf::SurfaceEffectGenerator surfaceGen(cvf::Color3::GREEN, caf::PO_1); + cvf::ref eff = surfaceGen.generateCachedEffect(); + part->setEffect(eff.p()); + + auto pair = m_cubeItemType[i]; + BoxManipulatorSourceInfo* sourceInfo = new BoxManipulatorSourceInfo(pair.first, pair.second); + part->setSourceInfo(sourceInfo); + + m_cubeParts.push_back(part.p()); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool BoxManipulatorPartManager::closestPointOfTwoLines(const cvf::Vec3d& p1, const cvf::Vec3d& q1, const cvf::Vec3d& p2, const cvf::Vec3d& q2, cvf::Vec3d* closestPoint1, cvf::Vec3d* closestPoint2) +{ + // qDebug() << p1 << " " << q1 << " " << p2 << " " << q2; + + // Taken from Real-Time Collistion Detection, Christer Ericson, 2005, p146-147 + + // L1(s) = P1 + sd1 + // L2(t) = P2 + td2 + + // d1 = Q1-P1 + // d2 = Q2-P2 + + // r = P1-P2 + + // a = d1*d1 + // b = d1*d2 + // c = d1*r + // e = d2*d2; + // d = ae-b^2 + // f = d2*r + + // s = (bf-ce)/d + // t = (af-bc)/d + + + cvf::Vec3d d1 = q1 - p1; + cvf::Vec3d d2 = q2 - p2; + + double a = d1.dot(d1); + double b = d1.dot(d2); + double e = d2.dot(d2); + + double d = a*e - b*b; + + if (d < std::numeric_limits::epsilon()) + { + // Parallel lines + if (closestPoint1) *closestPoint1 = p1; + if (closestPoint2) *closestPoint2 = p2; + return false; + } + + cvf::Vec3d r = p1 - p2; + double c = d1.dot(r); + double f = d2.dot(r); + + double s = (b*f - c*e) / d; + double t = (a*f - b*c) / d; + + if (closestPoint1) *closestPoint1 = p1 + s*d1; + if (closestPoint2) *closestPoint2 = p2 + t*d2; + + if (s >= 0 && s <= 1 && t >= 0 && t <= 1) + { + return true; + } + else + { + return false; + } +} + +} // namespace cvf + diff --git a/Fwk/AppFwk/cafVizExtensions/cafBoxManipulatorPartManager.h b/Fwk/AppFwk/cafVizExtensions/cafBoxManipulatorPartManager.h new file mode 100644 index 0000000000..7019f0bc8f --- /dev/null +++ b/Fwk/AppFwk/cafVizExtensions/cafBoxManipulatorPartManager.h @@ -0,0 +1,111 @@ + +#pragma once + +#include "cvfBase.h" +#include "cvfObject.h" + +#include "cvfVector3.h" +#include "cvfCollection.h" +#include "cvfMatrix4.h" + +namespace cvf { + class ModelBasicList; + class Part; + class DrawableGeo; + class Ray; +} + +namespace caf { + class BoxManipulatorGeometryGenerator; +}; + + +namespace caf { + + +//================================================================================================== +// +// +//================================================================================================== +class BoxManipulatorPartManager : public cvf::Object +{ +public: + enum BoxCubeFace + { + BCF_X_POS, + BCF_X_NEG, + BCF_Y_POS, + BCF_Y_NEG, + BCF_Z_POS, + BCF_Z_NEG + }; + + enum NavCubeFaceItem + { + BCFI_NONE, + BCFI_CENTER + }; + +public: + BoxManipulatorPartManager(); + + void setOrigin(const cvf::Vec3d& origin); + void setSize(const cvf::Vec3d& size); + void originAndSize(cvf::Vec3d* origin, cvf::Vec3d* size); + + size_t partIndexFromSourceInfo(const cvf::Part* part, const cvf::Vec3d& intersectionPoint); + void updateFromPartIndexAndRay(size_t partIndex, const cvf::Ray* ray); + + void appendPartsToModel(cvf::ModelBasicList* model); + +private: + cvf::Vec3d normalFromFace(BoxCubeFace face); + + void createCubeGeos(); + void createCubeFaceGeos(BoxCubeFace face, cvf::Vec3f p1, cvf::Vec3f p2, cvf::Vec3f p3, cvf::Vec3f p4); + void navCubeCornerPoints(cvf::Vec3f points[8]); + + + void clearAllGeometryAndParts(); + void recreateAllGeometryAndParts(); + + void createBoundingBoxPart(); + void createCubeParts(); + + cvf::ref createQuadGeo(const cvf::Vec3f& v1, const cvf::Vec3f& v2, const cvf::Vec3f& v3, const cvf::Vec3f& v4); + std::pair navCubeItem(BoxCubeFace face, NavCubeFaceItem item) const; + + static bool closestPointOfTwoLines(const cvf::Vec3d& p1, const cvf::Vec3d& q1, const cvf::Vec3d& p2, const cvf::Vec3d& q2, cvf::Vec3d* closestPoint1, cvf::Vec3d* closestPoint2); + +private: + cvf::Collection m_cubeGeos; // These arrays have the same length + std::vector< std::pair > m_cubeItemType; // These arrays have the same length + cvf::Collection m_cubeParts; // These arrays have the same length + + cvf::ref m_boundingBoxPart; + + cvf::Vec3d m_origin; + cvf::Vec3d m_size; + + cvf::Vec3d m_initialPickPoint; +}; + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +class BoxManipulatorSourceInfo : public cvf::Object +{ +public: + BoxManipulatorSourceInfo(BoxManipulatorPartManager::BoxCubeFace cubeFace, BoxManipulatorPartManager::NavCubeFaceItem cubeFaceItem) + : m_cubeFace(cubeFace), + m_cubeFaceItem(cubeFaceItem) + { + } + + BoxManipulatorPartManager::BoxCubeFace m_cubeFace; + BoxManipulatorPartManager::NavCubeFaceItem m_cubeFaceItem; +}; + + +} diff --git a/Fwk/AppFwk/cafVizExtensions/cafDisplayCoordTransform.cpp b/Fwk/AppFwk/cafVizExtensions/cafDisplayCoordTransform.cpp new file mode 100644 index 0000000000..413f99ebfd --- /dev/null +++ b/Fwk/AppFwk/cafVizExtensions/cafDisplayCoordTransform.cpp @@ -0,0 +1,82 @@ + +#include "cafDisplayCoordTransform.h" +#include "cvfMatrix4.h" + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::DisplayCoordTransform::DisplayCoordTransform() + : m_scale(1.0, 1.0, 1.0), + m_translation(cvf::Vec3d::ZERO) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void caf::DisplayCoordTransform::setScale(const cvf::Vec3d& scale) +{ + m_scale = scale; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void caf::DisplayCoordTransform::setTranslation(const cvf::Vec3d& translation) +{ + m_translation = translation; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Vec3d caf::DisplayCoordTransform::transformToDisplayCoord(const cvf::Vec3d& domainCoord) const +{ + cvf::Vec3d coord = domainCoord - m_translation; + coord.x() *= m_scale.x(); + coord.y() *= m_scale.y(); + coord.z() *= m_scale.z(); + + return coord; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Vec3d caf::DisplayCoordTransform::scaleToDisplaySize(const cvf::Vec3d& domainSize) const +{ + cvf::Vec3d coord = domainSize; + coord.x() *= m_scale.x(); + coord.y() *= m_scale.y(); + coord.z() *= m_scale.z(); + + return coord; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Vec3d caf::DisplayCoordTransform::transformToDomainCoord(const cvf::Vec3d& displayCoord) const +{ + cvf::Vec3d coord = displayCoord; + coord.x() /= m_scale.x(); + coord.y() /= m_scale.y(); + coord.z() /= m_scale.z(); + + coord += m_translation; + + return coord; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Vec3d caf::DisplayCoordTransform::scaleToDomainSize(const cvf::Vec3d& displaySize) const +{ + cvf::Vec3d coord = displaySize; + coord.x() /= m_scale.x(); + coord.y() /= m_scale.y(); + coord.z() /= m_scale.z(); + + return coord; +} diff --git a/Fwk/AppFwk/cafVizExtensions/cafDisplayCoordTransform.h b/Fwk/AppFwk/cafVizExtensions/cafDisplayCoordTransform.h new file mode 100644 index 0000000000..73eaf5d980 --- /dev/null +++ b/Fwk/AppFwk/cafVizExtensions/cafDisplayCoordTransform.h @@ -0,0 +1,33 @@ + +#pragma once + +#include "cvfBase.h" +#include "cvfObject.h" +#include "cvfVector3.h" + +namespace caf { + +//================================================================================================== +// +// +//================================================================================================== +class DisplayCoordTransform : public cvf::Object +{ +public: + DisplayCoordTransform(); + + void setScale(const cvf::Vec3d& scale); + void setTranslation(const cvf::Vec3d& translation); + + cvf::Vec3d transformToDisplayCoord(const cvf::Vec3d& domainCoord) const; + cvf::Vec3d scaleToDisplaySize(const cvf::Vec3d& domainSize) const; + + cvf::Vec3d transformToDomainCoord(const cvf::Vec3d& displayCoord) const; + cvf::Vec3d scaleToDomainSize(const cvf::Vec3d& displaySize) const; + +private: + cvf::Vec3d m_scale; + cvf::Vec3d m_translation; +}; + +}