# HG changeset patch # User am@osimis.io # Date 1550135882 -3600 # Node ID 2f6ecb5037ea346dd1848cab91a77ce802d963f5 # Parent e3d316ba34ba0374b288f9a9411bfa516c979a28 added mouse tracker for Layer Mask. Everything seems ok diff -r e3d316ba34ba -r 2f6ecb5037ea Applications/Samples/SingleFrameEditorApplication.h --- a/Applications/Samples/SingleFrameEditorApplication.h Wed Feb 13 14:14:42 2019 +0100 +++ b/Applications/Samples/SingleFrameEditorApplication.h Thu Feb 14 10:18:02 2019 +0100 @@ -24,6 +24,7 @@ #include "SampleApplicationBase.h" #include "../../Framework/Radiography/RadiographyLayerCropTracker.h" +#include "../../Framework/Radiography/RadiographyLayerMaskTracker.h" #include "../../Framework/Radiography/RadiographyLayerMoveTracker.h" #include "../../Framework/Radiography/RadiographyLayerResizeTracker.h" #include "../../Framework/Radiography/RadiographyLayerRotateTracker.h" @@ -134,16 +135,9 @@ return NULL; } - else if (tool_ == Tool_Mask) - { -// maskLayer_ -// case Tool_Mask: -// return new RadiographyLayerMaskTracker -// (undoRedoStack_, widget.GetScene(), view, selected, x, y, corner); - return NULL; - } else if (tool_ == Tool_Crop || - tool_ == Tool_Resize) + tool_ == Tool_Resize || + tool_ == Tool_Mask) { RadiographyScene::LayerAccessor accessor(widget.GetScene(), selected); @@ -156,6 +150,9 @@ return new RadiographyLayerCropTracker (undoRedoStack_, widget.GetScene(), view, selected, controlPoint); + case Tool_Mask: + return new RadiographyLayerMaskTracker + (undoRedoStack_, widget.GetScene(), view, selected, controlPoint); case Tool_Resize: return new RadiographyLayerResizeTracker diff -r e3d316ba34ba -r 2f6ecb5037ea Framework/Radiography/RadiographyLayer.cpp --- a/Framework/Radiography/RadiographyLayer.cpp Wed Feb 13 14:14:42 2019 +0100 +++ b/Framework/Radiography/RadiographyLayer.cpp Thu Feb 14 10:18:02 2019 +0100 @@ -305,47 +305,41 @@ size_t RadiographyLayer::GetControlPointCount() const {return 4;} - void RadiographyLayer::GetControlPointInternal(ControlPoint& controlPoint, - size_t index) const + void RadiographyLayer::GetControlPoint(ControlPoint& cpScene /* out in scene coordinates */, + size_t index) const { unsigned int cropX, cropY, cropWidth, cropHeight; GetCrop(cropX, cropY, cropWidth, cropHeight); + ControlPoint cp; switch (index) { case ControlPoint_TopLeftCorner: - controlPoint = ControlPoint(cropX, cropY, ControlPoint_TopLeftCorner); + cp = ControlPoint(cropX, cropY, ControlPoint_TopLeftCorner); break; case ControlPoint_TopRightCorner: - controlPoint = ControlPoint(cropX + cropWidth, cropY, ControlPoint_TopRightCorner); + cp = ControlPoint(cropX + cropWidth, cropY, ControlPoint_TopRightCorner); break; case ControlPoint_BottomLeftCorner: - controlPoint = ControlPoint(cropX, cropY + cropHeight, ControlPoint_BottomLeftCorner); + cp = ControlPoint(cropX, cropY + cropHeight, ControlPoint_BottomLeftCorner); break; case ControlPoint_BottomRightCorner: - controlPoint = ControlPoint(cropX + cropWidth, cropY + cropHeight, ControlPoint_BottomRightCorner); + cp = ControlPoint(cropX + cropWidth, cropY + cropHeight, ControlPoint_BottomRightCorner); break; default: throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); } + // transforms image coordinates into scene coordinates + GetTransform().Apply(cp.x, cp.y); + cpScene = cp; } - - - void RadiographyLayer::GetControlPoint(ControlPoint& controlPoint /* out */, - size_t index) const - { - GetControlPointInternal(controlPoint, index); - GetTransform().Apply(controlPoint.x, controlPoint.y); - } - - - bool RadiographyLayer::LookupControlPoint(ControlPoint& controlPoint /* out */, + bool RadiographyLayer::LookupControlPoint(ControlPoint& cpScene /* out */, double x, double y, double zoom, @@ -362,7 +356,7 @@ if (d <= threshold) { - controlPoint = cp; + cpScene = cp; return true; } } diff -r e3d316ba34ba -r 2f6ecb5037ea Framework/Radiography/RadiographyLayer.h --- a/Framework/Radiography/RadiographyLayer.h Wed Feb 13 14:14:42 2019 +0100 +++ b/Framework/Radiography/RadiographyLayer.h Thu Feb 14 10:18:02 2019 +0100 @@ -178,9 +178,6 @@ prefferedPhotometricDisplayMode_ = prefferedPhotometricDisplayMode; } - virtual void GetControlPointInternal(ControlPoint& controlPoint, - size_t index) const; - private: void UpdateTransform(); @@ -260,10 +257,10 @@ Extent2D GetExtent() const; - bool GetPixel(unsigned int& imageX, - unsigned int& imageY, - double sceneX, - double sceneY) const; + virtual bool GetPixel(unsigned int& imageX, + unsigned int& imageY, + double sceneX, + double sceneY) const; void SetPixelSpacing(double x, double y); @@ -271,12 +268,12 @@ void GetCenter(double& centerX, double& centerY) const; - void GetControlPoint(ControlPoint& controlPoint, - size_t index) const; + virtual void GetControlPoint(ControlPoint& cpScene /* out in scene coordinates */, + size_t index) const; virtual size_t GetControlPointCount() const; - bool LookupControlPoint(ControlPoint& controlPoint /* out */, + bool LookupControlPoint(ControlPoint& cpScene /* out */, double x, double y, double zoom, diff -r e3d316ba34ba -r 2f6ecb5037ea Framework/Radiography/RadiographyLayerMaskTracker.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Radiography/RadiographyLayerMaskTracker.cpp Thu Feb 14 10:18:02 2019 +0100 @@ -0,0 +1,140 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program 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 + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + **/ + + +#include "RadiographyLayerMaskTracker.h" +#include "RadiographyMaskLayer.h" + +#include "RadiographySceneCommand.h" + +#include + +namespace OrthancStone +{ + class RadiographyLayerMaskTracker::UndoRedoCommand : public RadiographySceneCommand + { + private: + ControlPoint sourceSceneCp_; + ControlPoint targetSceneCp_; + + protected: + virtual void UndoInternal(RadiographyLayer& layer) const + { + RadiographyMaskLayer* maskLayer = dynamic_cast(&layer); + if (maskLayer == NULL) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); + } + unsigned int ix, iy; // image coordinates + if (maskLayer->GetPixel(ix, iy, sourceSceneCp_.x, sourceSceneCp_.y)) + { + maskLayer->SetCorner(MaskPoint(ix, iy), sourceSceneCp_.index); + } + } + + virtual void RedoInternal(RadiographyLayer& layer) const + { + RadiographyMaskLayer* maskLayer = dynamic_cast(&layer); + if (maskLayer == NULL) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); + } + unsigned int ix, iy; // image coordinates + if (maskLayer->GetPixel(ix, iy, targetSceneCp_.x, targetSceneCp_.y)) + { + maskLayer->SetCorner(MaskPoint(ix, iy), targetSceneCp_.index); + } + } + + public: + UndoRedoCommand(const RadiographyLayerMaskTracker& tracker) : + RadiographySceneCommand(tracker.accessor_), + sourceSceneCp_(tracker.startSceneCp_), + targetSceneCp_(tracker.endSceneCp_) + { + RadiographyMaskLayer* maskLayer = dynamic_cast(&(tracker.accessor_.GetLayer())); + if (maskLayer == NULL) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); + } + unsigned int ix, iy; // image coordinates + if (maskLayer->GetPixel(ix, iy, targetSceneCp_.x, targetSceneCp_.y)) + { + maskLayer->SetCorner(MaskPoint(ix, iy), targetSceneCp_.index); + } + } + }; + + + RadiographyLayerMaskTracker::RadiographyLayerMaskTracker(UndoRedoStack& undoRedoStack, + RadiographyScene& scene, + const ViewportGeometry& view, + size_t layer, + const ControlPoint& startSceneControlPoint) : + undoRedoStack_(undoRedoStack), + accessor_(scene, layer), + startSceneCp_(startSceneControlPoint), + endSceneCp_(startSceneControlPoint) + { + } + + + void RadiographyLayerMaskTracker::Render(CairoContext& context, + double zoom) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); + } + + + void RadiographyLayerMaskTracker::MouseUp() + { + if (accessor_.IsValid() && startSceneCp_.x != endSceneCp_.x && startSceneCp_.y != endSceneCp_.y) + { + undoRedoStack_.Add(new UndoRedoCommand(*this)); + } + } + + + void RadiographyLayerMaskTracker::MouseMove(int displayX, + int displayY, + double sceneX, + double sceneY, + const std::vector& displayTouches, + const std::vector& sceneTouches) + { + if (accessor_.IsValid()) + { + unsigned int ix, iy; // image coordinates + + RadiographyLayer& layer = accessor_.GetLayer(); + if (layer.GetPixel(ix, iy, sceneX, sceneY)) + { + endSceneCp_ = ControlPoint(sceneX, sceneY, startSceneCp_.index); + + RadiographyMaskLayer* maskLayer = dynamic_cast(&layer); + if (maskLayer == NULL) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); + } + maskLayer->SetCorner(MaskPoint(ix, iy), startSceneCp_.index); + } + } + } +} diff -r e3d316ba34ba -r 2f6ecb5037ea Framework/Radiography/RadiographyLayerMaskTracker.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Radiography/RadiographyLayerMaskTracker.h Thu Feb 14 10:18:02 2019 +0100 @@ -0,0 +1,65 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program 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 + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "../Toolbox/UndoRedoStack.h" +#include "../Toolbox/ViewportGeometry.h" +#include "../Widgets/IWorldSceneMouseTracker.h" +#include "RadiographyScene.h" + +namespace OrthancStone +{ + class RadiographyLayerMaskTracker : public IWorldSceneMouseTracker + { + private: + class UndoRedoCommand; + + UndoRedoStack& undoRedoStack_; + RadiographyScene::LayerAccessor accessor_; + ControlPoint startSceneCp_; + ControlPoint endSceneCp_; + + public: + RadiographyLayerMaskTracker(UndoRedoStack& undoRedoStack, + RadiographyScene& scene, + const ViewportGeometry& view, + size_t layer, + const ControlPoint& startSceneControlPoint); + + virtual bool HasRender() const + { + return false; + } + + virtual void Render(CairoContext& context, + double zoom); + + virtual void MouseUp(); + + virtual void MouseMove(int displayX, + int displayY, + double sceneX, + double sceneY, + const std::vector& displayTouches, + const std::vector& sceneTouches); + }; +} diff -r e3d316ba34ba -r 2f6ecb5037ea Framework/Radiography/RadiographyMaskLayer.cpp --- a/Framework/Radiography/RadiographyMaskLayer.cpp Wed Feb 13 14:14:42 2019 +0100 +++ b/Framework/Radiography/RadiographyMaskLayer.cpp Thu Feb 14 10:18:02 2019 +0100 @@ -42,6 +42,15 @@ return dicomLayer_.GetTransformInverse(); } + bool RadiographyMaskLayer::GetPixel(unsigned int& imageX, + unsigned int& imageY, + double sceneX, + double sceneY) const + { + return dicomLayer_.GetPixel(imageX, imageY, sceneX, sceneY); + } + + void ComputeMaskExtent(unsigned int& left, unsigned int& right, unsigned int& top, unsigned int& bottom, const std::vector& corners) { left = std::numeric_limits::max(); @@ -59,6 +68,15 @@ } } + void RadiographyMaskLayer::SetCorner(const MaskPoint& corner, size_t index) + { + if (index < corners_.size()) + corners_[index] = corner; + else + corners_.push_back(corner); + invalidated_ = true; + } + void RadiographyMaskLayer::SetCorners(const std::vector& corners) { corners_ = corners; @@ -161,8 +179,8 @@ for (i = 0; i < cpSize; i++) { - if ((cpy[i] <= y && cpy[j] >= y) - || (cpy[j] <= y && cpy[i] >= y)) + if ((cpy[i] < y && cpy[j] >= y) + || (cpy[j] < y && cpy[i] >= y)) { nodeX[nodes++]= (int)(cpx[i] + (y - cpy[i])/(cpy[j] - cpy[i]) *(cpx[j] - cpx[i])); } diff -r e3d316ba34ba -r 2f6ecb5037ea Framework/Radiography/RadiographyMaskLayer.h --- a/Framework/Radiography/RadiographyMaskLayer.h Wed Feb 13 14:14:42 2019 +0100 +++ b/Framework/Radiography/RadiographyMaskLayer.h Thu Feb 14 10:18:02 2019 +0100 @@ -60,6 +60,7 @@ } void SetCorners(const std::vector& corners); + void SetCorner(const MaskPoint& corner, size_t index); virtual void Render(Orthanc::ImageAccessor& buffer, const AffineTransform2D& viewTransform, @@ -70,10 +71,14 @@ return corners_.size(); } - virtual void GetControlPointInternal(ControlPoint& controlPoint, + virtual void GetControlPoint(ControlPoint& cpScene, size_t index) const { - controlPoint = ControlPoint(corners_[index].x, corners_[index].y, index); + ControlPoint cp(corners_[index].x, corners_[index].y, index); + + // transforms image coordinates into scene coordinates + GetTransform().Apply(cp.x, cp.y); + cpScene = cp; } virtual bool GetDefaultWindowing(float& center, @@ -102,6 +107,11 @@ } + virtual bool GetPixel(unsigned int& imageX, + unsigned int& imageY, + double sceneX, + double sceneY) const; + protected: virtual const AffineTransform2D& GetTransform() const; diff -r e3d316ba34ba -r 2f6ecb5037ea Resources/CMake/OrthancStoneConfiguration.cmake --- a/Resources/CMake/OrthancStoneConfiguration.cmake Wed Feb 13 14:14:42 2019 +0100 +++ b/Resources/CMake/OrthancStoneConfiguration.cmake Thu Feb 14 10:18:02 2019 +0100 @@ -258,6 +258,7 @@ ${ORTHANC_STONE_ROOT}/Framework/Radiography/RadiographyDicomLayer.cpp ${ORTHANC_STONE_ROOT}/Framework/Radiography/RadiographyLayer.cpp ${ORTHANC_STONE_ROOT}/Framework/Radiography/RadiographyLayerCropTracker.cpp + ${ORTHANC_STONE_ROOT}/Framework/Radiography/RadiographyLayerMaskTracker.cpp ${ORTHANC_STONE_ROOT}/Framework/Radiography/RadiographyLayerMoveTracker.cpp ${ORTHANC_STONE_ROOT}/Framework/Radiography/RadiographyLayerResizeTracker.cpp ${ORTHANC_STONE_ROOT}/Framework/Radiography/RadiographyLayerRotateTracker.cpp