# HG changeset patch # User Benjamin Golinvaux # Date 1558276316 -7200 # Node ID d4d6c5b502b54df739172d7e1e37334567add85f # Parent 75deb0acd632073a88e82180f2b30eb3f4457490# Parent c0a5eb9a4290cd216b226302039e5cce2a81d1a5 Merging refactor-viewport-controller diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/OpenGL/OpenGLShader.cpp --- a/Framework/OpenGL/OpenGLShader.cpp Fri May 17 18:04:26 2019 +0200 +++ b/Framework/OpenGL/OpenGLShader.cpp Sun May 19 16:31:56 2019 +0200 @@ -35,7 +35,7 @@ GLint sourceStringLengths[1]; sourceString[0] = source.c_str(); - sourceStringLengths[0] = source.length(); + sourceStringLengths[0] = static_cast(source.length()); GLuint shader = glCreateShader(type); if (shader == 0) diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2D/IPointerTracker.h --- a/Framework/Scene2D/IPointerTracker.h Fri May 17 18:04:26 2019 +0200 +++ b/Framework/Scene2D/IPointerTracker.h Sun May 19 16:31:56 2019 +0200 @@ -21,6 +21,8 @@ #pragma once +#if 0 + #include "PointerEvent.h" namespace OrthancStone @@ -44,3 +46,5 @@ virtual void Release() = 0; }; } + +#endif diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2D/Internals/FixedPointAligner.cpp --- a/Framework/Scene2D/Internals/FixedPointAligner.cpp Fri May 17 18:04:26 2019 +0200 +++ b/Framework/Scene2D/Internals/FixedPointAligner.cpp Sun May 19 16:31:56 2019 +0200 @@ -18,29 +18,31 @@ * along with this program. If not, see . **/ - +#include #include "FixedPointAligner.h" namespace OrthancStone { namespace Internals { - FixedPointAligner::FixedPointAligner(Scene2D& scene, - const ScenePoint2D& p) : - scene_(scene), - canvas_(p) + FixedPointAligner::FixedPointAligner(ViewportControllerWPtr controllerW, + const ScenePoint2D& p) + : controllerW_(controllerW) + , canvas_(p) { - pivot_ = canvas_.Apply(scene_.GetCanvasToSceneTransform()); + ViewportControllerPtr controller = controllerW_.lock(); + pivot_ = canvas_.Apply(controller->GetCanvasToSceneTransform()); } void FixedPointAligner::Apply() { - ScenePoint2D p = canvas_.Apply(scene_.GetCanvasToSceneTransform()); + ViewportControllerPtr controller = controllerW_.lock(); + ScenePoint2D p = canvas_.Apply(controller->GetCanvasToSceneTransform()); - scene_.SetSceneToCanvasTransform( + controller->SetSceneToCanvasTransform( AffineTransform2D::Combine( - scene_.GetSceneToCanvasTransform(), + controller->GetSceneToCanvasTransform(), AffineTransform2D::CreateOffset(p.GetX() - pivot_.GetX(), p.GetY() - pivot_.GetY()))); } diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2D/Internals/FixedPointAligner.h --- a/Framework/Scene2D/Internals/FixedPointAligner.h Fri May 17 18:04:26 2019 +0200 +++ b/Framework/Scene2D/Internals/FixedPointAligner.h Sun May 19 16:31:56 2019 +0200 @@ -18,11 +18,10 @@ * along with this program. If not, see . **/ - #pragma once -#include "../Scene2D.h" -#include "../ScenePoint2D.h" +#include +#include namespace OrthancStone { @@ -33,12 +32,12 @@ class FixedPointAligner : public boost::noncopyable { private: - Scene2D& scene_; - ScenePoint2D pivot_; - ScenePoint2D canvas_; + ViewportControllerWPtr controllerW_; + ScenePoint2D pivot_; + ScenePoint2D canvas_; public: - FixedPointAligner(Scene2D& scene, + FixedPointAligner(ViewportControllerWPtr controllerW, const ScenePoint2D& p); void Apply(); diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2D/Internals/OpenGLLinesProgram.cpp diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2D/Internals/OpenGLTextProgram.cpp diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2D/PanSceneTracker.cpp --- a/Framework/Scene2D/PanSceneTracker.cpp Fri May 17 18:04:26 2019 +0200 +++ b/Framework/Scene2D/PanSceneTracker.cpp Sun May 19 16:31:56 2019 +0200 @@ -20,27 +20,34 @@ #include "PanSceneTracker.h" +#include namespace OrthancStone { - PanSceneTracker::PanSceneTracker(Scene2D& scene, - const PointerEvent& event) : - scene_(scene), - originalSceneToCanvas_(scene_.GetSceneToCanvasTransform()), - originalCanvasToScene_(scene_.GetCanvasToSceneTransform()) + PanSceneTracker::PanSceneTracker(ViewportControllerWPtr controllerW, + const PointerEvent& event) + : OneGesturePointerTracker(controllerW) + , originalSceneToCanvas_(GetController()->GetSceneToCanvasTransform()) + , originalCanvasToScene_(GetController()->GetCanvasToSceneTransform()) { pivot_ = event.GetMainPosition().Apply(originalCanvasToScene_); } - void PanSceneTracker::Update(const PointerEvent& event) + void PanSceneTracker::PointerMove(const PointerEvent& event) { ScenePoint2D p = event.GetMainPosition().Apply(originalCanvasToScene_); - scene_.SetSceneToCanvasTransform( + GetController()->SetSceneToCanvasTransform( AffineTransform2D::Combine( originalSceneToCanvas_, AffineTransform2D::CreateOffset(p.GetX() - pivot_.GetX(), p.GetY() - pivot_.GetY()))); } + + void PanSceneTracker::Cancel() + { + GetController()->SetSceneToCanvasTransform(originalSceneToCanvas_); + } + } diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2D/PanSceneTracker.h --- a/Framework/Scene2D/PanSceneTracker.h Fri May 17 18:04:26 2019 +0200 +++ b/Framework/Scene2D/PanSceneTracker.h Sun May 19 16:31:56 2019 +0200 @@ -21,27 +21,25 @@ #pragma once -#include "IPointerTracker.h" -#include "Scene2D.h" +#include "../Scene2DViewport/OneGesturePointerTracker.h" namespace OrthancStone { - class PanSceneTracker : public IPointerTracker + class ViewportController; + + class PanSceneTracker : public OneGesturePointerTracker { - private: - Scene2D& scene_; - ScenePoint2D pivot_; - AffineTransform2D originalSceneToCanvas_; - AffineTransform2D originalCanvasToScene_; - public: - PanSceneTracker(Scene2D& scene, + PanSceneTracker(ViewportControllerWPtr controllerW, const PointerEvent& event); - virtual void Update(const PointerEvent& event); + virtual void PointerMove(const PointerEvent& event) ORTHANC_OVERRIDE; + virtual void Cancel() ORTHANC_OVERRIDE; - virtual void Release() - { - } + private: + ViewportControllerWPtr controllerW_; + ScenePoint2D pivot_; + AffineTransform2D originalSceneToCanvas_; + AffineTransform2D originalCanvasToScene_; }; } diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2D/RotateSceneTracker.cpp --- a/Framework/Scene2D/RotateSceneTracker.cpp Fri May 17 18:04:26 2019 +0200 +++ b/Framework/Scene2D/RotateSceneTracker.cpp Sun May 19 16:31:56 2019 +0200 @@ -18,23 +18,22 @@ * along with this program. If not, see . **/ - #include "RotateSceneTracker.h" +#include namespace OrthancStone { - RotateSceneTracker::RotateSceneTracker(Scene2D& scene, - const PointerEvent& event) : - scene_(scene), - click_(event.GetMainPosition()), - aligner_(scene, click_), - isFirst_(true), - originalSceneToCanvas_(scene.GetSceneToCanvasTransform()) + RotateSceneTracker::RotateSceneTracker(ViewportControllerWPtr controllerW, + const PointerEvent& event) + : OneGesturePointerTracker(controllerW) + , click_(event.GetMainPosition()) + , aligner_(controllerW, click_) + , isFirst_(true) + , originalSceneToCanvas_(GetController()->GetSceneToCanvasTransform()) { } - - - void RotateSceneTracker::Update(const PointerEvent& event) + + void RotateSceneTracker::PointerMove(const PointerEvent& event) { ScenePoint2D p = event.GetMainPosition(); double dx = p.GetX() - click_.GetX(); @@ -51,7 +50,7 @@ isFirst_ = false; } - scene_.SetSceneToCanvasTransform( + GetController()->SetSceneToCanvasTransform( AffineTransform2D::Combine( AffineTransform2D::CreateRotation(a - referenceAngle_), originalSceneToCanvas_)); @@ -59,4 +58,10 @@ aligner_.Apply(); } } + + void RotateSceneTracker::Cancel() + { + GetController()->SetSceneToCanvasTransform(originalSceneToCanvas_); + } + } diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2D/RotateSceneTracker.h --- a/Framework/Scene2D/RotateSceneTracker.h Fri May 17 18:04:26 2019 +0200 +++ b/Framework/Scene2D/RotateSceneTracker.h Sun May 19 16:31:56 2019 +0200 @@ -21,29 +21,27 @@ #pragma once -#include "IPointerTracker.h" +#include "../Scene2DViewport/OneGesturePointerTracker.h" #include "Internals/FixedPointAligner.h" namespace OrthancStone { - class RotateSceneTracker : public IPointerTracker + class ViewportController; + + class RotateSceneTracker : public OneGesturePointerTracker { - private: - Scene2D& scene_; - ScenePoint2D click_; - Internals::FixedPointAligner aligner_; - double referenceAngle_; - bool isFirst_; - AffineTransform2D originalSceneToCanvas_; - public: - RotateSceneTracker(Scene2D& scene, + RotateSceneTracker(ViewportControllerWPtr controllerW, const PointerEvent& event); - virtual void Update(const PointerEvent& event); + virtual void PointerMove(const PointerEvent& event) ORTHANC_OVERRIDE; + virtual void Cancel() ORTHANC_OVERRIDE; - virtual void Release() - { - } + private: + ScenePoint2D click_; + Internals::FixedPointAligner aligner_; + double referenceAngle_; + bool isFirst_; + AffineTransform2D originalSceneToCanvas_; }; } diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2D/Scene2D.cpp --- a/Framework/Scene2D/Scene2D.cpp Fri May 17 18:04:26 2019 +0200 +++ b/Framework/Scene2D/Scene2D.cpp Sun May 19 16:31:56 2019 +0200 @@ -76,8 +76,7 @@ Scene2D::Scene2D(const Scene2D& other) - : IObservable(other.GetBroker()) - , sceneToCanvas_(other.sceneToCanvas_) + : sceneToCanvas_(other.sceneToCanvas_) , canvasToScene_(other.canvasToScene_) , layerCounter_(0) { @@ -221,7 +220,6 @@ sceneToCanvas_ = transform; canvasToScene_ = inverse; - BroadcastMessage(SceneTransformChanged(*this)); } void Scene2D::FitContent(unsigned int canvasWidth, diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2D/Scene2D.h --- a/Framework/Scene2D/Scene2D.h Fri May 17 18:04:26 2019 +0200 +++ b/Framework/Scene2D/Scene2D.h Sun May 19 16:31:56 2019 +0200 @@ -30,11 +30,9 @@ namespace OrthancStone { - class Scene2D : public IObservable + class Scene2D : public boost::noncopyable { public: - ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, SceneTransformChanged, Scene2D); - class IVisitor : public boost::noncopyable { public: @@ -60,9 +58,7 @@ Scene2D(const Scene2D& other); public: - Scene2D(MessageBroker& broker) - : IObservable(broker) - , layerCounter_(0) + Scene2D() : layerCounter_(0) { } diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2D/ScenePoint2D.h diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2D/ZoomSceneTracker.cpp --- a/Framework/Scene2D/ZoomSceneTracker.cpp Fri May 17 18:04:26 2019 +0200 +++ b/Framework/Scene2D/ZoomSceneTracker.cpp Sun May 19 16:31:56 2019 +0200 @@ -20,16 +20,17 @@ #include "ZoomSceneTracker.h" +#include namespace OrthancStone { - ZoomSceneTracker::ZoomSceneTracker(Scene2D& scene, + ZoomSceneTracker::ZoomSceneTracker(ViewportControllerWPtr controllerW, const PointerEvent& event, - unsigned int canvasHeight) : - scene_(scene), - clickY_(event.GetMainPosition().GetY()), - aligner_(scene, event.GetMainPosition()), - originalSceneToCanvas_(scene.GetSceneToCanvasTransform()) + unsigned int canvasHeight) + : OneGesturePointerTracker(controllerW) + , clickY_(event.GetMainPosition().GetY()) + , aligner_(controllerW, event.GetMainPosition()) + , originalSceneToCanvas_(GetController()->GetSceneToCanvasTransform()) { if (canvasHeight <= 3) { @@ -42,8 +43,7 @@ } } - - void ZoomSceneTracker::Update(const PointerEvent& event) + void ZoomSceneTracker::PointerMove(const PointerEvent& event) { static const double MIN_ZOOM = -4; static const double MAX_ZOOM = 4; @@ -51,7 +51,10 @@ if (active_) { double y = event.GetMainPosition().GetY(); - double dy = static_cast(y - clickY_) * normalization_; // In the range [-1,1] + + // In the range [-1,1] + double dy = static_cast(y - clickY_) * normalization_; + double z; // Linear interpolation from [-1, 1] to [MIN_ZOOM, MAX_ZOOM] @@ -70,7 +73,7 @@ double zoom = pow(2.0, z); - scene_.SetSceneToCanvasTransform( + GetController()->SetSceneToCanvasTransform( AffineTransform2D::Combine( AffineTransform2D::CreateScaling(zoom, zoom), originalSceneToCanvas_)); @@ -78,4 +81,9 @@ aligner_.Apply(); } } + + void ZoomSceneTracker::Cancel() + { + GetController()->SetSceneToCanvasTransform(originalSceneToCanvas_); + } } diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2D/ZoomSceneTracker.h --- a/Framework/Scene2D/ZoomSceneTracker.h Fri May 17 18:04:26 2019 +0200 +++ b/Framework/Scene2D/ZoomSceneTracker.h Sun May 19 16:31:56 2019 +0200 @@ -22,32 +22,29 @@ #pragma once -#include "IPointerTracker.h" +#include "../Scene2DViewport/OneGesturePointerTracker.h" #include "Internals/FixedPointAligner.h" namespace OrthancStone { class Scene2D; - class ZoomSceneTracker : public IPointerTracker + class ZoomSceneTracker : public OneGesturePointerTracker { + public: + ZoomSceneTracker(ViewportControllerWPtr controllerW, + const PointerEvent& event, + unsigned int canvasHeight); + + virtual void PointerMove(const PointerEvent& event) ORTHANC_OVERRIDE; + virtual void Cancel() ORTHANC_OVERRIDE; + private: - Scene2D& scene_; double clickY_; bool active_; double normalization_; Internals::FixedPointAligner aligner_; AffineTransform2D originalSceneToCanvas_; - public: - ZoomSceneTracker(Scene2D& scene, - const PointerEvent& event, - unsigned int canvasHeight); - - virtual void Update(const PointerEvent& event); - - virtual void Release() - { - } }; } diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2DViewport/AngleMeasureTool.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/AngleMeasureTool.cpp Sun May 19 16:31:56 2019 +0200 @@ -0,0 +1,283 @@ +/** + * 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 "AngleMeasureTool.h" +#include "MeasureToolsToolbox.h" + +#include + +#include + +extern void TrackerSample_SetInfoDisplayMessage(std::string key, std::string value); + +namespace OrthancStone +{ + AngleMeasureTool::~AngleMeasureTool() + { + // this measuring tool is a RABI for the corresponding visual layers + // stored in the 2D scene + Disable(); + RemoveFromScene(); + } + + void AngleMeasureTool::RemoveFromScene() + { + if (layersCreated) + { + assert(GetScene()->HasLayer(polylineZIndex_)); + assert(GetScene()->HasLayer(textBaseZIndex_)); + GetScene()->DeleteLayer(polylineZIndex_); + GetScene()->DeleteLayer(textBaseZIndex_); + } + } + + void AngleMeasureTool::SetSide1End(ScenePoint2D pt) + { + side1End_ = pt; + RefreshScene(); + } + + void AngleMeasureTool::SetSide2End(ScenePoint2D pt) + { + side2End_ = pt; + RefreshScene(); + } + + void AngleMeasureTool::SetCenter(ScenePoint2D pt) + { + center_ = pt; + RefreshScene(); + } + + PolylineSceneLayer* AngleMeasureTool::GetPolylineLayer() + { + assert(GetScene()->HasLayer(polylineZIndex_)); + ISceneLayer* layer = &(GetScene()->GetLayer(polylineZIndex_)); + PolylineSceneLayer* concreteLayer = dynamic_cast(layer); + assert(concreteLayer != NULL); + return concreteLayer; + } + + void AngleMeasureTool::RefreshScene() + { + if (IsEnabled()) + { + // get the scaling factor + const double pixelToScene = + GetScene()->GetCanvasToSceneTransform().ComputeZoom(); + + if (!layersCreated) + { + // Create the layers if need be + + assert(textBaseZIndex_ == -1); + { + polylineZIndex_ = GetScene()->GetMaxDepth() + 100; + //LOG(INFO) << "set polylineZIndex_ to: " << polylineZIndex_; + std::auto_ptr layer(new PolylineSceneLayer()); + GetScene()->SetLayer(polylineZIndex_, layer.release()); + + } + { + textBaseZIndex_ = GetScene()->GetMaxDepth() + 100; + // create the four text background layers + { + std::auto_ptr layer(new TextSceneLayer()); + GetScene()->SetLayer(textBaseZIndex_, layer.release()); + } + { + std::auto_ptr layer(new TextSceneLayer()); + GetScene()->SetLayer(textBaseZIndex_+1, layer.release()); + } + { + std::auto_ptr layer(new TextSceneLayer()); + GetScene()->SetLayer(textBaseZIndex_+2, layer.release()); + } + { + std::auto_ptr layer(new TextSceneLayer()); + GetScene()->SetLayer(textBaseZIndex_+3, layer.release()); + } + + // and the text layer itself + { + std::auto_ptr layer(new TextSceneLayer()); + GetScene()->SetLayer(textBaseZIndex_+4, layer.release()); + } + + } + layersCreated = true; + } + else + { + assert(GetScene()->HasLayer(polylineZIndex_)); + assert(GetScene()->HasLayer(textBaseZIndex_)); + } + { + // Fill the polyline layer with the measurement line + + PolylineSceneLayer* polylineLayer = GetPolylineLayer(); + polylineLayer->ClearAllChains(); + polylineLayer->SetColor(0, 183, 17); + + // sides + { + { + PolylineSceneLayer::Chain chain; + chain.push_back(side1End_); + chain.push_back(center_); + polylineLayer->AddChain(chain, false); + } + { + PolylineSceneLayer::Chain chain; + chain.push_back(side2End_); + chain.push_back(center_); + polylineLayer->AddChain(chain, false); + } + } + + // handles + { + //void AddSquare(PolylineSceneLayer::Chain& chain,const Scene2D& scene,const ScenePoint2D& centerS,const double& sideLength) + + { + PolylineSceneLayer::Chain chain; + AddSquare(chain, *GetScene(), side1End_, 10.0* pixelToScene); //TODO: take DPI into account + polylineLayer->AddChain(chain, true); + } + + { + PolylineSceneLayer::Chain chain; + AddSquare(chain, *GetScene(), side2End_, 10.0* pixelToScene); //TODO: take DPI into account + polylineLayer->AddChain(chain, true); + } + } + + // arc + { + PolylineSceneLayer::Chain chain; + + const double ARC_RADIUS_CANVAS_COORD = 30.0; + AddShortestArc(chain, *GetScene(), side1End_, center_, side2End_, + ARC_RADIUS_CANVAS_COORD*pixelToScene); + polylineLayer->AddChain(chain, false); + } + } + { + // Set the text layer + + double p1cAngle = atan2( + side1End_.GetY() - center_.GetY(), + side1End_.GetX() - center_.GetX()); + + + double p2cAngle = atan2( + side2End_.GetY() - center_.GetY(), + side2End_.GetX() - center_.GetX()); + + double delta = NormalizeAngle(p2cAngle - p1cAngle); + + + double theta = p1cAngle + delta/2; + + + const double TEXT_CENTER_DISTANCE_CANVAS_COORD = 90; + + double offsetX = TEXT_CENTER_DISTANCE_CANVAS_COORD * cos(theta); + + double offsetY = TEXT_CENTER_DISTANCE_CANVAS_COORD * sin(theta); + + double pointX = center_.GetX() + offsetX * pixelToScene; + double pointY = center_.GetY() + offsetY * pixelToScene; + + char buf[64]; + double angleDeg = RadiansToDegrees(delta); + + // http://www.ltg.ed.ac.uk/~richard/utf-8.cgi?input=00B0&mode=hex + sprintf(buf, "%0.02f\xc2\xb0", angleDeg); + + SetTextLayerOutlineProperties( + *GetScene(), textBaseZIndex_, buf, ScenePoint2D(pointX, pointY)); + + // TODO:make it togglable + bool enableInfoDisplay = false; + if (enableInfoDisplay) + { + TrackerSample_SetInfoDisplayMessage("center_.GetX()", + boost::lexical_cast(center_.GetX())); + + TrackerSample_SetInfoDisplayMessage("center_.GetY()", + boost::lexical_cast(center_.GetY())); + + TrackerSample_SetInfoDisplayMessage("side1End_.GetX()", + boost::lexical_cast(side1End_.GetX())); + + TrackerSample_SetInfoDisplayMessage("side1End_.GetY()", + boost::lexical_cast(side1End_.GetY())); + + TrackerSample_SetInfoDisplayMessage("side2End_.GetX()", + boost::lexical_cast(side2End_.GetX())); + + TrackerSample_SetInfoDisplayMessage("side2End_.GetY()", + boost::lexical_cast(side2End_.GetY())); + + TrackerSample_SetInfoDisplayMessage("p1cAngle (deg)", + boost::lexical_cast(RadiansToDegrees(p1cAngle))); + + TrackerSample_SetInfoDisplayMessage("delta (deg)", + boost::lexical_cast(RadiansToDegrees(delta))); + + TrackerSample_SetInfoDisplayMessage("theta (deg)", + boost::lexical_cast(RadiansToDegrees(theta))); + + TrackerSample_SetInfoDisplayMessage("p2cAngle (deg)", + boost::lexical_cast(RadiansToDegrees(p2cAngle))); + + TrackerSample_SetInfoDisplayMessage("offsetX (pix)", + boost::lexical_cast(offsetX)); + + TrackerSample_SetInfoDisplayMessage("offsetY (pix)", + boost::lexical_cast(offsetY)); + + TrackerSample_SetInfoDisplayMessage("pointX", + boost::lexical_cast(pointX)); + + TrackerSample_SetInfoDisplayMessage("pointY", + boost::lexical_cast(pointY)); + + TrackerSample_SetInfoDisplayMessage("angleDeg", + boost::lexical_cast(angleDeg)); + } + + + + } + } + else + { + if (layersCreated) + { + RemoveFromScene(); + layersCreated = false; + } + } + } + + +} diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2DViewport/AngleMeasureTool.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/AngleMeasureTool.h Sun May 19 16:31:56 2019 +0200 @@ -0,0 +1,76 @@ +/** + * 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 "MeasureTools.h" + +#include +#include +#include +#include + +#include +#include + +#include +#include + +namespace OrthancStone +{ + class AngleMeasureTool : public MeasureTool + { + public: + AngleMeasureTool(MessageBroker& broker, ViewportControllerWPtr controllerW) + : MeasureTool(broker, controllerW) + , layersCreated(false) + , polylineZIndex_(-1) + , textBaseZIndex_(-1) + { + + } + + ~AngleMeasureTool(); + + void SetSide1End(ScenePoint2D start); + void SetCenter(ScenePoint2D start); + void SetSide2End(ScenePoint2D start); + + private: + PolylineSceneLayer* GetPolylineLayer(); + + // 0 --> 3 are for the text background (outline) + // 4 is for the actual text + TextSceneLayer* GetTextLayer(int index); + virtual void RefreshScene() ORTHANC_OVERRIDE; + void RemoveFromScene(); + + private: + ScenePoint2D side1End_; + ScenePoint2D side2End_; + ScenePoint2D center_; + bool layersCreated; + int polylineZIndex_; + int textBaseZIndex_; + }; + +} + + diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2DViewport/CreateAngleMeasureTracker.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/CreateAngleMeasureTracker.cpp Sun May 19 16:31:56 2019 +0200 @@ -0,0 +1,130 @@ +/** + * 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 "CreateAngleMeasureTracker.h" +#include + +using namespace Orthanc; + +namespace OrthancStone +{ + CreateAngleMeasureTracker::CreateAngleMeasureTracker( + MessageBroker& broker, + ViewportControllerWPtr controllerW, + std::vector& undoStack, + MeasureToolList& measureTools, + const PointerEvent& e) + : CreateMeasureTracker(controllerW, undoStack, measureTools) + , state_(CreatingSide1) + { + command_.reset( + new CreateAngleMeasureCommand( + broker, + controllerW, + measureTools, + e.GetMainPosition().Apply(GetScene()->GetCanvasToSceneTransform()))); + } + + CreateAngleMeasureTracker::~CreateAngleMeasureTracker() + { + } + + void CreateAngleMeasureTracker::PointerMove(const PointerEvent& event) + { + assert(GetScene()); + + if (!alive_) + { + throw OrthancException(ErrorCode_InternalError, + "Internal error: wrong state in CreateAngleMeasureTracker::" + "PointerMove: active_ == false"); + } + + ScenePoint2D scenePos = event.GetMainPosition().Apply( + GetScene()->GetCanvasToSceneTransform()); + + switch (state_) + { + case CreatingSide1: + GetCommand()->SetCenter(scenePos); + break; + case CreatingSide2: + GetCommand()->SetSide2End(scenePos); + break; + default: + throw OrthancException(ErrorCode_InternalError, + "Wrong state in CreateAngleMeasureTracker::" + "PointerMove: state_ invalid"); + } + //LOG(TRACE) << "scenePos.GetX() = " << scenePos.GetX() << " " << + // "scenePos.GetY() = " << scenePos.GetY(); + } + + void CreateAngleMeasureTracker::PointerUp(const PointerEvent& e) + { + // TODO: the current app does not prevent multiple PointerDown AND + // PointerUp to be sent to the tracker. + // Unless we augment the PointerEvent structure with the button index, + // we cannot really tell if this pointer up event matches the initial + // pointer down event. Let's make it simple for now. + + switch (state_) + { + case CreatingSide1: + state_ = CreatingSide2; + break; + case CreatingSide2: + throw OrthancException(ErrorCode_InternalError, + "Wrong state in CreateAngleMeasureTracker::" + "PointerUp: state_ == CreatingSide2 ; this should not happen"); + break; + default: + throw OrthancException(ErrorCode_InternalError, + "Wrong state in CreateAngleMeasureTracker::" + "PointerMove: state_ invalid"); + } + } + + void CreateAngleMeasureTracker::PointerDown(const PointerEvent& e) + { + switch (state_) + { + case CreatingSide1: + throw OrthancException(ErrorCode_InternalError, + "Wrong state in CreateAngleMeasureTracker::" + "PointerDown: state_ == CreatingSide1 ; this should not happen"); + break; + case CreatingSide2: + // we are done + alive_ = false; + break; + default: + throw OrthancException(ErrorCode_InternalError, + "Wrong state in CreateAngleMeasureTracker::" + "PointerMove: state_ invalid"); + } + } + + CreateAngleMeasureCommandPtr CreateAngleMeasureTracker::GetCommand() + { + return boost::dynamic_pointer_cast(command_); + } + +} diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2DViewport/CreateAngleMeasureTracker.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/CreateAngleMeasureTracker.h Sun May 19 16:31:56 2019 +0200 @@ -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 "MeasureTrackers.h" +#include "MeasureCommands.h" + +#include + +namespace OrthancStone +{ + class CreateAngleMeasureTracker : public CreateMeasureTracker + { + public: + /** + When you create this tracker, you need to supply it with the undo stack + where it will store the commands that perform the actual measure tool + creation and modification. + In turn, a container for these commands to store the actual measuring + must be supplied, too + */ + CreateAngleMeasureTracker( + MessageBroker& broker, + ViewportControllerWPtr controllerW, + std::vector& undoStack, + MeasureToolList& measureTools, + const PointerEvent& e); + + ~CreateAngleMeasureTracker(); + + virtual void PointerMove(const PointerEvent& e) ORTHANC_OVERRIDE; + virtual void PointerUp(const PointerEvent& e) ORTHANC_OVERRIDE; + virtual void PointerDown(const PointerEvent& e) ORTHANC_OVERRIDE; + + private: + CreateAngleMeasureCommandPtr GetCommand(); + + enum State + { + CreatingSide1, + CreatingSide2, + Finished // just for debug + }; + State state_; + + }; +} diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2DViewport/CreateCircleMeasureTracker.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/CreateCircleMeasureTracker.cpp Sun May 19 16:31:56 2019 +0200 @@ -0,0 +1,23 @@ +/** + * 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 . + **/ + +namespace OrthancStone +{ +} diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2DViewport/CreateCircleMeasureTracker.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/CreateCircleMeasureTracker.h Sun May 19 16:31:56 2019 +0200 @@ -0,0 +1,25 @@ +/** + * 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 + +namespace OrthancStone +{ +} diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2DViewport/CreateLineMeasureTracker.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/CreateLineMeasureTracker.cpp Sun May 19 16:31:56 2019 +0200 @@ -0,0 +1,93 @@ +/** + * 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 "CreateLineMeasureTracker.h" +#include + +using namespace Orthanc; + +namespace OrthancStone +{ + CreateLineMeasureTracker::CreateLineMeasureTracker( + MessageBroker& broker, + ViewportControllerWPtr controllerW, + std::vector& undoStack, + MeasureToolList& measureTools, + const PointerEvent& e) + : CreateMeasureTracker(controllerW, undoStack, measureTools) + { + command_.reset( + new CreateLineMeasureCommand( + broker, + controllerW, + measureTools, + e.GetMainPosition().Apply(GetScene()->GetCanvasToSceneTransform()))); + } + + CreateLineMeasureTracker::~CreateLineMeasureTracker() + { + + } + + void CreateLineMeasureTracker::PointerMove(const PointerEvent& event) + { + assert(GetScene()); + + if (!alive_) + { + throw OrthancException(ErrorCode_InternalError, + "Internal error: wrong state in CreateLineMeasureTracker::" + "PointerMove: active_ == false"); + } + + ScenePoint2D scenePos = event.GetMainPosition().Apply( + GetScene()->GetCanvasToSceneTransform()); + + //LOG(TRACE) << "scenePos.GetX() = " << scenePos.GetX() << " " << + // "scenePos.GetY() = " << scenePos.GetY(); + + CreateLineMeasureTracker* concreteThis = + dynamic_cast(this); + assert(concreteThis != NULL); + GetCommand()->SetEnd(scenePos); + } + + void CreateLineMeasureTracker::PointerUp(const PointerEvent& e) + { + // TODO: the current app does not prevent multiple PointerDown AND + // PointerUp to be sent to the tracker. + // Unless we augment the PointerEvent structure with the button index, + // we cannot really tell if this pointer up event matches the initial + // pointer down event. Let's make it simple for now. + alive_ = false; + } + + void CreateLineMeasureTracker::PointerDown(const PointerEvent& e) + { + LOG(WARNING) << "Additional touches (fingers, pen, mouse buttons...) " + "are ignored when the line measure creation tracker is active"; + } + + CreateLineMeasureCommandPtr CreateLineMeasureTracker::GetCommand() + { + return boost::dynamic_pointer_cast(command_); + } + +} diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2DViewport/CreateLineMeasureTracker.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/CreateLineMeasureTracker.h Sun May 19 16:31:56 2019 +0200 @@ -0,0 +1,53 @@ +/** + * 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 "MeasureTrackers.h" + +namespace OrthancStone +{ + class CreateLineMeasureTracker : public CreateMeasureTracker + { + public: + /** + When you create this tracker, you need to supply it with the undo stack + where it will store the commands that perform the actual measure tool + creation and modification. + In turn, a container for these commands to store the actual measuring + must be supplied, too + */ + CreateLineMeasureTracker( + MessageBroker& broker, + ViewportControllerWPtr controllerW, + std::vector& undoStack, + MeasureToolList& measureTools, + const PointerEvent& e); + + ~CreateLineMeasureTracker(); + + virtual void PointerMove(const PointerEvent& e) ORTHANC_OVERRIDE; + virtual void PointerUp(const PointerEvent& e) ORTHANC_OVERRIDE; + virtual void PointerDown(const PointerEvent& e) ORTHANC_OVERRIDE; + + private: + CreateLineMeasureCommandPtr GetCommand(); + }; +} diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2DViewport/CreateMeasureTracker.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/CreateMeasureTracker.cpp Sun May 19 16:31:56 2019 +0200 @@ -0,0 +1,20 @@ +/** + * 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 . + **/ + diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2DViewport/CreateMeasureTracker.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/CreateMeasureTracker.h Sun May 19 16:31:56 2019 +0200 @@ -0,0 +1,22 @@ +/** + * 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 + diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2DViewport/CreateSimpleTrackerAdapter.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/CreateSimpleTrackerAdapter.cpp Sun May 19 16:31:56 2019 +0200 @@ -0,0 +1,79 @@ +/** + * 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 "IFlexiblePointerTracker.h" +#include + + +namespace OrthancStone +{ +#if 0 + namespace + { + class SimpleTrackerAdapter : public IFlexiblePointerTracker + { + public: + SimpleTrackerAdapter(PointerTrackerPtr wrappedTracker) + : wrappedTracker_(wrappedTracker) + , active_(true) + { + } + + virtual void PointerMove(const PointerEvent& event) ORTHANC_OVERRIDE + { + if(active_) + wrappedTracker_->Update(event); + }; + virtual void PointerUp(const PointerEvent& event) ORTHANC_OVERRIDE + { + if (wrappedTracker_) + { + wrappedTracker_->Release(); + wrappedTracker_ = NULL; + } + active_ = false; + } + virtual void PointerDown(const PointerEvent& event) ORTHANC_OVERRIDE + { + // nothing to do atm + } + virtual bool IsActive() const ORTHANC_OVERRIDE + { + return active_; + } + + virtual void Cancel() ORTHANC_OVERRIDE + { + wrappedTracker_ = NULL; + active_ = false; + } + + private: + PointerTrackerPtr wrappedTracker_; + bool active_; + }; + } + + FlexiblePointerTrackerPtr CreateSimpleTrackerAdapter(PointerTrackerPtr t) + { + return FlexiblePointerTrackerPtr(new SimpleTrackerAdapter(t)); + } +#endif +} diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2DViewport/EditAngleMeasureTracker.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/EditAngleMeasureTracker.cpp Sun May 19 16:31:56 2019 +0200 @@ -0,0 +1,23 @@ +/** + * 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 . + **/ + +namespace OrthancStone +{ +} diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2DViewport/EditAngleMeasureTracker.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/EditAngleMeasureTracker.h Sun May 19 16:31:56 2019 +0200 @@ -0,0 +1,25 @@ +/** + * 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 + +namespace OrthancStone +{ +} diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2DViewport/EditCircleMeasureTracker.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/EditCircleMeasureTracker.cpp Sun May 19 16:31:56 2019 +0200 @@ -0,0 +1,23 @@ +/** + * 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 . + **/ + +namespace OrthancStone +{ +} diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2DViewport/EditCircleMeasureTracker.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/EditCircleMeasureTracker.h Sun May 19 16:31:56 2019 +0200 @@ -0,0 +1,25 @@ +/** + * 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 + +namespace OrthancStone +{ +} diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2DViewport/EditLineMeasureTracker.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/EditLineMeasureTracker.cpp Sun May 19 16:31:56 2019 +0200 @@ -0,0 +1,23 @@ +/** + * 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 . + **/ + +namespace OrthancStone +{ +} diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2DViewport/EditLineMeasureTracker.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/EditLineMeasureTracker.h Sun May 19 16:31:56 2019 +0200 @@ -0,0 +1,25 @@ +/** + * 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 + +namespace OrthancStone +{ +} diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2DViewport/IFlexiblePointerTracker.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/IFlexiblePointerTracker.h Sun May 19 16:31:56 2019 +0200 @@ -0,0 +1,81 @@ +/** + * 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 "PointerTypes.h" + +#include + +namespace OrthancStone +{ + /** + This interface represents a flexible mouse tracker that can respond to + several events and is not automatically deleted upon mouse up or when touch + interaction is suspended : for instance, a stateful tracker with a two-step + interaction like: click & drag --> mouse up --> drag --> mouse click + (for instance, for an angle measuring tracker or an ellipse tracker) + */ + class IFlexiblePointerTracker : public boost::noncopyable + { + public: + virtual ~IFlexiblePointerTracker() {} + + /** + This method will be repeatedly called during user interaction + */ + virtual void PointerMove(const PointerEvent& event) = 0; + + /** + This method will be called when a touch/pointer is removed (mouse up, + pen lift, finger removed...) + */ + virtual void PointerUp(const PointerEvent& event) = 0; + + /** + This method will be called when a touch/pointer is added (mouse down, + pen or finger press) + */ + virtual void PointerDown(const PointerEvent& event) = 0; + + /** + This method will be repeatedly called by the tracker owner (for instance, + the application) to check whether the tracker must keep on receiving + interaction or if its job is done and it should be deleted. + */ + virtual bool IsAlive() const = 0; + + /** + This will be called if the tracker needs to be dismissed without committing + its changes to the underlying model. If the model has been modified during + tracker lifetime, it must be restored to its initial value + */ + virtual void Cancel() = 0; + }; + + + /** + This factory adopts the supplied simple tracker and creates a flexible + tracker wrapper around it. + */ + FlexiblePointerTrackerPtr CreateSimpleTrackerAdapter(PointerTrackerPtr); +} + diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2DViewport/LineMeasureTool.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/LineMeasureTool.cpp Sun May 19 16:31:56 2019 +0200 @@ -0,0 +1,200 @@ +/** + * 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 "LineMeasureTool.h" +#include "MeasureToolsToolbox.h" + +#include + + +namespace OrthancStone +{ + LineMeasureTool::~LineMeasureTool() + { + // this measuring tool is a RABI for the corresponding visual layers + // stored in the 2D scene + Disable(); + RemoveFromScene(); + } + + void LineMeasureTool::RemoveFromScene() + { + if (layersCreated) + { + assert(GetScene()->HasLayer(polylineZIndex_)); + assert(GetScene()->HasLayer(textZIndex_)); + GetScene()->DeleteLayer(polylineZIndex_); + GetScene()->DeleteLayer(textZIndex_); + } + } + + + void LineMeasureTool::SetStart(ScenePoint2D start) + { + start_ = start; + RefreshScene(); + } + + void LineMeasureTool::SetEnd(ScenePoint2D end) + { + end_ = end; + RefreshScene(); + } + + void LineMeasureTool::Set(ScenePoint2D start, ScenePoint2D end) + { + start_ = start; + end_ = end; + RefreshScene(); + } + + PolylineSceneLayer* LineMeasureTool::GetPolylineLayer() + { + assert(GetScene()->HasLayer(polylineZIndex_)); + ISceneLayer* layer = &(GetScene()->GetLayer(polylineZIndex_)); + PolylineSceneLayer* concreteLayer = dynamic_cast(layer); + assert(concreteLayer != NULL); + return concreteLayer; + } + + TextSceneLayer* LineMeasureTool::GetTextLayer() + { + assert(GetScene()->HasLayer(textZIndex_)); + ISceneLayer* layer = &(GetScene()->GetLayer(textZIndex_)); + TextSceneLayer* concreteLayer = dynamic_cast(layer); + assert(concreteLayer != NULL); + return concreteLayer; + } + + void LineMeasureTool::RefreshScene() + { + if (IsEnabled()) + { + if (!layersCreated) + { + // Create the layers if need be + + assert(textZIndex_ == -1); + { + polylineZIndex_ = GetScene()->GetMaxDepth() + 100; + //LOG(INFO) << "set polylineZIndex_ to: " << polylineZIndex_; + std::auto_ptr layer(new PolylineSceneLayer()); + GetScene()->SetLayer(polylineZIndex_, layer.release()); + } + { + textZIndex_ = GetScene()->GetMaxDepth() + 100; + //LOG(INFO) << "set textZIndex_ to: " << textZIndex_; + std::auto_ptr layer(new TextSceneLayer()); + GetScene()->SetLayer(textZIndex_, layer.release()); + } + layersCreated = true; + } + else + { + assert(GetScene()->HasLayer(polylineZIndex_)); + assert(GetScene()->HasLayer(textZIndex_)); + } + { + // Fill the polyline layer with the measurement line + + PolylineSceneLayer* polylineLayer = GetPolylineLayer(); + polylineLayer->ClearAllChains(); + polylineLayer->SetColor(0, 223, 21); + + { + PolylineSceneLayer::Chain chain; + chain.push_back(start_); + chain.push_back(end_); + polylineLayer->AddChain(chain, false); + } + + // handles + { + //void AddSquare(PolylineSceneLayer::Chain& chain,const Scene2D& scene,const ScenePoint2D& centerS,const double& sideLength) + + { + PolylineSceneLayer::Chain chain; + AddSquare(chain, *GetScene(), start_, 10.0); //TODO: take DPI into account + polylineLayer->AddChain(chain, true); + } + + { + PolylineSceneLayer::Chain chain; + AddSquare(chain, *GetScene(), end_, 10.0); //TODO: take DPI into account + polylineLayer->AddChain(chain, true); + } + + //ScenePoint2D startC = start_.Apply(GetScene()->GetSceneToCanvasTransform()); + //double squareSize = 10.0; + //double startHandleLX = startC.GetX() - squareSize/2; + //double startHandleTY = startC.GetY() - squareSize / 2; + //double startHandleRX = startC.GetX() + squareSize / 2; + //double startHandleBY = startC.GetY() + squareSize / 2; + //ScenePoint2D startLTC(startHandleLX, startHandleTY); + //ScenePoint2D startRTC(startHandleRX, startHandleTY); + //ScenePoint2D startRBC(startHandleRX, startHandleBY); + //ScenePoint2D startLBC(startHandleLX, startHandleBY); + + //ScenePoint2D startLT = startLTC.Apply(GetScene()->GetCanvasToSceneTransform()); + //ScenePoint2D startRT = startRTC.Apply(GetScene()->GetCanvasToSceneTransform()); + //ScenePoint2D startRB = startRBC.Apply(GetScene()->GetCanvasToSceneTransform()); + //ScenePoint2D startLB = startLBC.Apply(GetScene()->GetCanvasToSceneTransform()); + + //PolylineSceneLayer::Chain chain; + //chain.push_back(startLT); + //chain.push_back(startRT); + //chain.push_back(startRB); + //chain.push_back(startLB); + //polylineLayer->AddChain(chain, true); + } + + } + { + // Set the text layer proporeties + + TextSceneLayer* textLayer = GetTextLayer(); + double deltaX = end_.GetX() - start_.GetX(); + double deltaY = end_.GetY() - start_.GetY(); + double squareDist = deltaX * deltaX + deltaY * deltaY; + double dist = sqrt(squareDist); + char buf[64]; + sprintf(buf, "%0.02f units", dist); + textLayer->SetText(buf); + textLayer->SetColor(0, 223, 21); + + // TODO: for now we simply position the text overlay at the middle + // of the measuring segment + double midX = 0.5*(end_.GetX() + start_.GetX()); + double midY = 0.5*(end_.GetY() + start_.GetY()); + textLayer->SetPosition(midX, midY); + } + } + else + { + if (layersCreated) + { + RemoveFromScene(); + layersCreated = false; + } + } + } + + +} \ No newline at end of file diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2DViewport/LineMeasureTool.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/LineMeasureTool.h Sun May 19 16:31:56 2019 +0200 @@ -0,0 +1,71 @@ +/** + * 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 "MeasureTools.h" + +#include +#include +#include +#include + +#include +#include + +#include +#include + +namespace OrthancStone +{ + class LineMeasureTool : public MeasureTool + { + public: + LineMeasureTool(MessageBroker& broker, ViewportControllerWPtr controllerW) + : MeasureTool(broker, controllerW) + , layersCreated(false) + , polylineZIndex_(-1) + , textZIndex_(-1) + { + + } + + ~LineMeasureTool(); + + void SetStart(ScenePoint2D start); + void SetEnd(ScenePoint2D end); + void Set(ScenePoint2D start, ScenePoint2D end); + + private: + PolylineSceneLayer* GetPolylineLayer(); + TextSceneLayer* GetTextLayer(); + virtual void RefreshScene() ORTHANC_OVERRIDE; + void RemoveFromScene(); + + private: + ScenePoint2D start_; + ScenePoint2D end_; + bool layersCreated; + int polylineZIndex_; + int textZIndex_; + }; + +} + diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2DViewport/MeasureCommands.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/MeasureCommands.cpp Sun May 19 16:31:56 2019 +0200 @@ -0,0 +1,93 @@ +/** + * 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 "MeasureCommands.h" + +namespace OrthancStone +{ + void CreateMeasureCommand::Undo() + { + // simply disable the measure tool upon undo + GetMeasureTool()->Disable(); + } + + void CreateMeasureCommand::Redo() + { + GetMeasureTool()->Enable(); + } + + CreateMeasureCommand::CreateMeasureCommand( + ViewportControllerWPtr controllerW, MeasureToolList& measureTools) + : TrackerCommand(controllerW) + , measureTools_(measureTools) + { + + } + + CreateMeasureCommand::~CreateMeasureCommand() + { + // deleting the command should not change the model state + // we thus leave it as is + } + + CreateLineMeasureCommand::CreateLineMeasureCommand( + MessageBroker& broker, + ViewportControllerWPtr controllerW, + MeasureToolList& measureTools, + ScenePoint2D point) + : CreateMeasureCommand(controllerW, measureTools) + , measureTool_(new LineMeasureTool(broker, controllerW)) + { + measureTools_.push_back(measureTool_); + measureTool_->Set(point, point); + } + + void CreateLineMeasureCommand::SetEnd(ScenePoint2D scenePos) + { + measureTool_->SetEnd(scenePos); + } + + CreateAngleMeasureCommand::CreateAngleMeasureCommand( + MessageBroker& broker, + ViewportControllerWPtr controllerW, + MeasureToolList& measureTools, + ScenePoint2D point) + : CreateMeasureCommand(controllerW, measureTools) + , measureTool_(new AngleMeasureTool(broker, controllerW)) + { + measureTools_.push_back(measureTool_); + measureTool_->SetSide1End(point); + measureTool_->SetCenter(point); + measureTool_->SetSide2End(point); + } + + /** This method sets center*/ + void CreateAngleMeasureCommand::SetCenter(ScenePoint2D scenePos) + { + measureTool_->SetCenter(scenePos); + } + + /** This method sets end of side 2*/ + void CreateAngleMeasureCommand::SetSide2End(ScenePoint2D scenePos) + { + measureTool_->SetSide2End(scenePos); + } + +} diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2DViewport/MeasureCommands.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/MeasureCommands.h Sun May 19 16:31:56 2019 +0200 @@ -0,0 +1,110 @@ +/** + * 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 +#include +#include + +// to be moved into Stone +#include "PointerTypes.h" +#include "MeasureTools.h" +#include "LineMeasureTool.h" +#include "AngleMeasureTool.h" + +namespace OrthancStone +{ + class TrackerCommand : public boost::noncopyable + { + public: + TrackerCommand(ViewportControllerWPtr controllerW) + : controllerW_(controllerW) + { + + } + virtual void Undo() = 0; + virtual void Redo() = 0; + + protected: + ViewportControllerWPtr controllerW_; + }; + + class CreateMeasureCommand : public TrackerCommand + { + public: + CreateMeasureCommand( + ViewportControllerWPtr controllerW, MeasureToolList& measureTools); + ~CreateMeasureCommand(); + virtual void Undo() ORTHANC_OVERRIDE; + virtual void Redo() ORTHANC_OVERRIDE; + protected: + MeasureToolList& measureTools_; + private: + /** Must be implemented by the subclasses that create the actual tool */ + virtual MeasureToolPtr GetMeasureTool() = 0; + }; + + class CreateLineMeasureCommand : public CreateMeasureCommand + { + public: + CreateLineMeasureCommand( + MessageBroker& broker, + ViewportControllerWPtr controllerW, + MeasureToolList& measureTools, + ScenePoint2D point); + + // the starting position is set in the ctor + void SetEnd(ScenePoint2D scenePos); + + private: + virtual MeasureToolPtr GetMeasureTool() ORTHANC_OVERRIDE + { + return measureTool_; + } + LineMeasureToolPtr measureTool_; + }; + + + class CreateAngleMeasureCommand : public CreateMeasureCommand + { + public: + /** Ctor sets end of side 1*/ + CreateAngleMeasureCommand( + MessageBroker& broker, + ViewportControllerWPtr controllerW, + MeasureToolList& measureTools, + ScenePoint2D point); + + /** This method sets center*/ + void SetCenter(ScenePoint2D scenePos); + + /** This method sets end of side 2*/ + void SetSide2End(ScenePoint2D scenePos); + + private: + virtual MeasureToolPtr GetMeasureTool() ORTHANC_OVERRIDE + { + return measureTool_; + } + AngleMeasureToolPtr measureTool_; + }; + +} + diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2DViewport/MeasureTools.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/MeasureTools.cpp Sun May 19 16:31:56 2019 +0200 @@ -0,0 +1,90 @@ +/** + * 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 "MeasureTools.h" + +#include +#include +#include + +#include + +using namespace Orthanc; + +namespace OrthancStone +{ + + MeasureTool::~MeasureTool() + { + + } + + void MeasureTool::Enable() + { + enabled_ = true; + RefreshScene(); + } + + void MeasureTool::Disable() + { + enabled_ = false; + RefreshScene(); + } + + bool MeasureTool::IsEnabled() const + { + return enabled_; + } + + + ViewportControllerPtr MeasureTool::GetController() + { + ViewportControllerPtr controller = controllerW_.lock(); + if (!controller) + throw OrthancException(ErrorCode_InternalError, + "Using dead ViewportController object!"); + return controller; + } + + OrthancStone::Scene2DPtr MeasureTool::GetScene() + { + return GetController()->GetScene(); + } + + MeasureTool::MeasureTool(MessageBroker& broker, + ViewportControllerWPtr controllerW) + : IObserver(broker) + , controllerW_(controllerW) + , enabled_(true) + { + GetController()->RegisterObserverCallback( + new Callable + (*this, &MeasureTool::OnSceneTransformChanged)); + } + + void MeasureTool::OnSceneTransformChanged( + const ViewportController::SceneTransformChanged& message) + { + RefreshScene(); + } + + +} + diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2DViewport/MeasureTools.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/MeasureTools.h Sun May 19 16:31:56 2019 +0200 @@ -0,0 +1,91 @@ +/** + * 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 +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include + +namespace OrthancStone +{ + class MeasureTool : public IObserver + { + public: + virtual ~MeasureTool(); + + /** + Enabled tools are rendered in the scene. + */ + void Enable(); + + /** + Disabled tools are not rendered in the scene. This is useful to be able + to use them as their own memento in command stacks (when a measure tool + creation command has been undone, the measure remains alive in the + command object but is disabled so that it can be redone later on easily) + */ + void Disable(); + + /** + This method is called when the scene transform changes. It allows to + recompute the visual elements whose content depend upon the scene transform + */ + void OnSceneTransformChanged( + const ViewportController::SceneTransformChanged& message); + + protected: + MeasureTool(MessageBroker& broker, ViewportControllerWPtr controllerW); + + /** + This is the meat of the tool: this method must [create (if needed) and] + update the layers and their data according to the measure tool kind and + current state. This is repeatedly called during user interaction + */ + virtual void RefreshScene() = 0; + + ViewportControllerPtr GetController(); + Scene2DPtr GetScene(); + + /** + enabled_ is not accessible by subclasses because there is a state machine + that we do not wanna mess with + */ + bool IsEnabled() const; + + private: + ViewportControllerWPtr controllerW_; + bool enabled_; + }; +} + + +extern void TrackerSample_SetInfoDisplayMessage( + std::string key, std::string value); diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2DViewport/MeasureToolsToolbox.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/MeasureToolsToolbox.cpp Sun May 19 16:31:56 2019 +0200 @@ -0,0 +1,336 @@ +/** + * 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 "MeasureToolsToolbox.h" + +#include + +#include + +namespace +{ + double g_pi = boost::math::constants::pi(); +} + +namespace OrthancStone +{ + double RadiansToDegrees(double angleRad) + { + static const double factor = 180.0 / g_pi; + return angleRad * factor; + } + + void AddSquare(PolylineSceneLayer::Chain& chain, + const Scene2D& scene, + const ScenePoint2D& centerS, + const double& sideLength) + { + chain.clear(); + chain.reserve(4); + ScenePoint2D centerC = centerS.Apply(scene.GetSceneToCanvasTransform()); + //TODO: take DPI into account + double handleLX = centerC.GetX() - sideLength / 2; + double handleTY = centerC.GetY() - sideLength / 2; + double handleRX = centerC.GetX() + sideLength / 2; + double handleBY = centerC.GetY() + sideLength / 2; + ScenePoint2D LTC(handleLX, handleTY); + ScenePoint2D RTC(handleRX, handleTY); + ScenePoint2D RBC(handleRX, handleBY); + ScenePoint2D LBC(handleLX, handleBY); + + ScenePoint2D startLT = LTC.Apply(scene.GetCanvasToSceneTransform()); + ScenePoint2D startRT = RTC.Apply(scene.GetCanvasToSceneTransform()); + ScenePoint2D startRB = RBC.Apply(scene.GetCanvasToSceneTransform()); + ScenePoint2D startLB = LBC.Apply(scene.GetCanvasToSceneTransform()); + + chain.push_back(startLT); + chain.push_back(startRT); + chain.push_back(startRB); + chain.push_back(startLB); + } +#if 0 + void AddArc( + PolylineSceneLayer::Chain& chain + , const Scene2D& scene + , const ScenePoint2D& p1 + , const ScenePoint2D& c + , const ScenePoint2D& p2 + , const double& radiusS + , const bool clockwise + , const int subdivisionsCount) + { + double p1cAngle = atan2(p1.GetY() - c.GetY(), p1.GetX() - c.GetX()); + double p2cAngle = atan2(p2.GetY() - c.GetY(), p2.GetX() - c.GetX()); + AddArc( + chain, scene, c, radiusS, p1cAngle, p2cAngle, + clockwise, subdivisionsCount); + } +#endif + + void AddShortestArc( + PolylineSceneLayer::Chain& chain + , const Scene2D& scene + , const ScenePoint2D& p1 + , const ScenePoint2D& c + , const ScenePoint2D& p2 + , const double& radiusS + , const int subdivisionsCount) + { + double p1cAngle = atan2(p1.GetY() - c.GetY(), p1.GetX() - c.GetX()); + double p2cAngle = atan2(p2.GetY() - c.GetY(), p2.GetX() - c.GetX()); + AddShortestArc( + chain, scene, c, radiusS, p1cAngle, p2cAngle, subdivisionsCount); + } + + void GetPositionOnBisectingLine( + ScenePoint2D& result + , const ScenePoint2D& p1 + , const ScenePoint2D& c + , const ScenePoint2D& p2 + , const double d) + { + // TODO: fix correct half-plane + double p1cAngle = atan2(p1.GetY() - c.GetY(), p1.GetX() - c.GetX()); + double p2cAngle = atan2(p2.GetY() - c.GetY(), p2.GetX() - c.GetX()); + double angle = 0.5*(p1cAngle + p2cAngle); + double unitVectorX = cos(angle); + double unitVectorY = sin(angle); + double posX = c.GetX() + d * unitVectorX; + double posY = c.GetX() + d * unitVectorY; + result = ScenePoint2D(posX, posY); + } + + void AddShortestArc( + PolylineSceneLayer::Chain& chain + , const Scene2D& scene + , const ScenePoint2D& centerS + , const double& radiusS + , const double startAngleRad + , const double endAngleRad + , const int subdivisionsCount) + { + // this gives a signed difference between angle which + // is the smallest difference (in magnitude) between + // the angles + double delta = NormalizeAngle(endAngleRad-startAngleRad); + + chain.clear(); + chain.reserve(subdivisionsCount + 1); + + double angleIncr = delta/static_cast(subdivisionsCount); + + double theta = startAngleRad; + for (int i = 0; i < subdivisionsCount + 1; ++i) + { + double offsetX = radiusS * cos(theta); + double offsetY = radiusS * sin(theta); + double pointX = centerS.GetX() + offsetX; + double pointY = centerS.GetY() + offsetY; + chain.push_back(ScenePoint2D(pointX, pointY)); + theta += angleIncr; + } + } + +#if 0 + void AddArc( + PolylineSceneLayer::Chain& chain + , const Scene2D& scene + , const ScenePoint2D& centerS + , const double& radiusS + , const double startAngleRad + , const double endAngleRad + , const bool clockwise + , const int subdivisionsCount) + { + double startAngleRadN = NormalizeAngle(startAngleRad); + double endAngleRadN = NormalizeAngle(endAngleRad); + + double angle1Rad = std::min(startAngleRadN, endAngleRadN); + double angle2Rad = std::max(startAngleRadN, endAngleRadN); + + // now we are sure angle1Rad < angle2Rad + // this means that if we draw from 1 to 2, it will be clockwise ( + // increasing angles). + // let's fix this: + if (!clockwise) + { + angle2Rad -= 2 * g_pi; + // now we are sure angle2Rad < angle1Rad (since they were normalized) + // and, thus, going from 1 to 2 means the angle values will DECREASE, + // which is the definition of anticlockwise + } + + chain.clear(); + chain.reserve(subdivisionsCount + 1); + + double angleIncr = (angle2Rad - angle1Rad) + / static_cast(subdivisionsCount); + + double theta = angle1Rad; + for (int i = 0; i < subdivisionsCount + 1; ++i) + { + double offsetX = radiusS * cos(theta); + double offsetY = radiusS * sin(theta); + double pointX = centerS.GetX() + offsetX; + double pointY = centerS.GetY() + offsetY; + chain.push_back(ScenePoint2D(pointX, pointY)); + theta += angleIncr; + } + } +#endif + + void AddCircle(PolylineSceneLayer::Chain& chain, + const Scene2D& scene, + const ScenePoint2D& centerS, + const double& radiusS, + const int numSubdivisions) + { + //ScenePoint2D centerC = centerS.Apply(scene.GetSceneToCanvasTransform()); + //TODO: take DPI into account + + // TODO: automatically compute the number for segments for smooth + // display based on the radius in pixels. + + chain.clear(); + chain.reserve(numSubdivisions); + + double angleIncr = (2.0 * g_pi) + / static_cast(numSubdivisions); + + double theta = 0; + for (int i = 0; i < numSubdivisions; ++i) + { + double offsetX = radiusS * cos(theta); + double offsetY = radiusS * sin(theta); + double pointX = centerS.GetX() + offsetX; + double pointY = centerS.GetY() + offsetY; + chain.push_back(ScenePoint2D(pointX, pointY)); + theta += angleIncr; + } + } + + double NormalizeAngle(double angle) + { + double retAngle = angle; + while (retAngle < -1.0*g_pi) + retAngle += 2 * g_pi; + while (retAngle >= g_pi) + retAngle -= 2 * g_pi; + return retAngle; + } + + double MeasureAngle(const ScenePoint2D& p1, const ScenePoint2D& c, const ScenePoint2D& p2) + { + double p1cAngle = atan2(p1.GetY() - c.GetY(), p1.GetX() - c.GetX()); + double p2cAngle = atan2(p2.GetY() - c.GetY(), p2.GetX() - c.GetX()); + double delta = p2cAngle - p1cAngle; + return NormalizeAngle(delta); + } + + +#if 0 + void AddEllipse(PolylineSceneLayer::Chain& chain, + const Scene2D& scene, + const ScenePoint2D& centerS, + const double& halfHAxis, + const double& halfVAxis) + { + chain.clear(); + chain.reserve(4); + ScenePoint2D centerC = centerS.Apply(scene.GetSceneToCanvasTransform()); + //TODO: take DPI into account + double handleLX = centerC.GetX() - sideLength / 2; + double handleTY = centerC.GetY() - sideLength / 2; + double handleRX = centerC.GetX() + sideLength / 2; + double handleBY = centerC.GetY() + sideLength / 2; + ScenePoint2D LTC(handleLX, handleTY); + ScenePoint2D RTC(handleRX, handleTY); + ScenePoint2D RBC(handleRX, handleBY); + ScenePoint2D LBC(handleLX, handleBY); + + ScenePoint2D startLT = LTC.Apply(scene.GetCanvasToSceneTransform()); + ScenePoint2D startRT = RTC.Apply(scene.GetCanvasToSceneTransform()); + ScenePoint2D startRB = RBC.Apply(scene.GetCanvasToSceneTransform()); + ScenePoint2D startLB = LBC.Apply(scene.GetCanvasToSceneTransform()); + + chain.push_back(startLT); + chain.push_back(startRT); + chain.push_back(startRB); + chain.push_back(startLB); +} +#endif + + + namespace + { + /** + Helper function for outlined text rendering + */ + TextSceneLayer* GetOutlineTextLayer( + Scene2D& scene, int baseLayerIndex, int index) + { + assert(scene.HasLayer(baseLayerIndex)); + assert(index >= 0); + assert(index < 5); + + ISceneLayer * layer = &(scene.GetLayer(baseLayerIndex + index)); + TextSceneLayer * concreteLayer = dynamic_cast(layer); + assert(concreteLayer != NULL); + return concreteLayer; + } + } + + void SetTextLayerOutlineProperties( + Scene2D& scene, int baseLayerIndex, const char* text, ScenePoint2D p) + { + double xoffsets[5] = { 2, 0, -2, 0, 0 }; + double yoffsets[5] = { 0, -2, 0, 2, 0 }; + + // get the scaling factor + const double pixelToScene = + scene.GetCanvasToSceneTransform().ComputeZoom(); + + for (int i = 0; i < 5; ++i) + { + TextSceneLayer* textLayer = GetOutlineTextLayer(scene, baseLayerIndex, i); + textLayer->SetText(text); + + if (i == 4) + textLayer->SetColor(0, 223, 81); + else + textLayer->SetColor(0, 56, 21); + + ScenePoint2D textAnchor; + //GetPositionOnBisectingLine( + // textAnchor, side1End_, center_, side2End_, 40.0*pixelToScene); + textLayer->SetPosition( + p.GetX() + xoffsets[i] * pixelToScene, + p.GetY() + yoffsets[i] * pixelToScene); + } + } + + + + + + + + +} diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2DViewport/MeasureToolsToolbox.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/MeasureToolsToolbox.h Sun May 19 16:31:56 2019 +0200 @@ -0,0 +1,187 @@ +/** + * 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 +#include + +namespace OrthancStone +{ + + /** + This function will create a square around the center point supplied in + scene coordinates, with a side length given in canvas coordinates. The + square sides are parallel to the canvas boundaries. + */ + void AddSquare(PolylineSceneLayer::Chain& chain, + const Scene2D& scene, + const ScenePoint2D& centerS, + const double& sideLength); + + + /** + Creates an arc centered on c that goes + - from a point r1: + - so that r1 belongs to the p1,c line + - so that the distance from c to r1 equals radius + - to a point r2: + - so that r2 belongs to the p2,c line + - so that the distance from c to r2 equals radius + - that follows the shortest among the two possible paths + + Warning: the existing chain content will be wiped out. + */ + void AddShortestArc( + PolylineSceneLayer::Chain& chain + , const Scene2D& scene + , const ScenePoint2D& p1 + , const ScenePoint2D& c + , const ScenePoint2D& p2 + , const double& radiusS + , const int subdivisionsCount = 63); + + /** + Creates an arc (open curve) with "numSubdivisions" (N + 1 points) from + start angle to end angle, by following the shortest arc. + + Warning: the existing chain content will be wiped out. + */ + void AddShortestArc( + PolylineSceneLayer::Chain& chain + , const Scene2D& scene + , const ScenePoint2D& centerS + , const double& radiusS + , const double startAngleRad + , const double endAngleRad + , const int subdivisionsCount = 63); + +#if 0 + /** + Creates an arc centered on c that goes + - from a point r1: + - so that r1 belongs to the p1,c line + - so that the distance from c to r1 equals radius + - to a point r2: + - so that r2 belongs to the p2,c line + - so that the distance from c to r2 equals radius + + if clockwise is true, the arc is drawn from r1 to r2 with increasing + angle values. Otherwise, the angle values decrease. + + Warning: the existing chain content will be wiped out. + */ + + void AddArc( + PolylineSceneLayer::Chain& chain + , const Scene2D& scene + , const ScenePoint2D& p1 + , const ScenePoint2D& c + , const ScenePoint2D& p2 + , const double& radiusS + , const bool clockwise + , const int subdivisionsCount = 63); + + /** + Creates an arc (open curve) with "numSubdivisions" (N + 1 points) from + start angle to end angle with the supplied radius. + + if clockwise is true, the arc is drawn from start to end by increasing the + angle values. + + Otherwise, the angle value decreases from start to end. + + Warning: the existing chain content will be wiped out. + */ + void AddArc( + PolylineSceneLayer::Chain& chain + , const Scene2D& scene + , const ScenePoint2D& centerS + , const double& radiusS + , const double startAngleRad + , const double endAngleRad + , const bool clockwise + , const int subdivisionsCount = 63); +#endif + /** + Creates a circle (closed curve) with "numSubdivisions" + (N points) + + Warning: the existing chain content will be wiped out. + */ + void AddCircle(PolylineSceneLayer::Chain& chain, + const Scene2D& scene, + const ScenePoint2D& centerS, + const double& radiusS, + const int numSubdivisions = 63); + + /** + Adds or subtracts 2*pi as many times as need to shift the specified + angle to a value such as: -pi <= value < pi + */ + double NormalizeAngle(double angle); + + /** + Returns the angle magnitude between the p1,c and p2,c lines. + The returned angle is between 0 and 2*pi + + If the angle is between 0 and pi, this means that the shortest arc + from p1 to p2 is clockwise. + + If the angle is between pi and 2*pi, this means that the shortest arc + from p1 to p2 is COUNTERclockwise. + + */ + double MeasureAngle( + const ScenePoint2D& p1 + , const ScenePoint2D& c + , const ScenePoint2D& p2); + + /** + RadiansToDegrees + */ + double RadiansToDegrees(double angleRad); + + /** + This function will return the coordinates of a point that: + - belongs to the two bisecting lines of the p1 c p2 angle. + - is a distance d from c. + Among the four possible points, the one returned will be the one belonging + to the *smallest* half-plane defined by the [c,p1[ and [c,p2[ half-lines. + */ + void GetPositionOnBisectingLine( + ScenePoint2D& result + , const ScenePoint2D& p1 + , const ScenePoint2D& c + , const ScenePoint2D& p2 + , const double d); + + + /** + This helper is used when drawing text with an outline. + It set the properties for several text layers at once : first the + four outline layers, with a position shift and then the actual main text + layer. + + The five text layers are supposed to already exist in the scene, starting + from layerIndex, up to (and not including) layerIndex+5. + */ + void SetTextLayerOutlineProperties( + Scene2D& scene, int baseLayerIndex, const char* text, ScenePoint2D p); + +} diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2DViewport/MeasureTrackers.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/MeasureTrackers.cpp Sun May 19 16:31:56 2019 +0200 @@ -0,0 +1,72 @@ +/** + * 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 "MeasureTrackers.h" +#include + +using namespace Orthanc; + +namespace OrthancStone +{ + + CreateMeasureTracker::CreateMeasureTracker( + ViewportControllerWPtr controllerW, + std::vector& undoStack, + std::vector& measureTools) + : controllerW_(controllerW) + , alive_(true) + , undoStack_(undoStack) + , measureTools_(measureTools) + , commitResult_(true) + { + } + + void CreateMeasureTracker::Cancel() + { + commitResult_ = false; + alive_ = false; + } + + bool CreateMeasureTracker::IsAlive() const + { + return alive_; + } + + CreateMeasureTracker::~CreateMeasureTracker() + { + // if the tracker completes successfully, we add the command + // to the undo stack + + // otherwise, we simply undo it + if (commitResult_) + undoStack_.push_back(command_); + else + command_->Undo(); + } + + + OrthancStone::Scene2DPtr CreateMeasureTracker::GetScene() + { + return controllerW_.lock()->GetScene(); + } + +} + + diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2DViewport/MeasureTrackers.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/MeasureTrackers.h Sun May 19 16:31:56 2019 +0200 @@ -0,0 +1,59 @@ +/** + * 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 "IFlexiblePointerTracker.h" +#include "../../Framework/Scene2D/Scene2D.h" +#include "../../Framework/Scene2D/PointerEvent.h" + +#include "MeasureTools.h" +#include "MeasureCommands.h" + +#include + +namespace OrthancStone +{ + class CreateMeasureTracker : public IFlexiblePointerTracker + { + public: + virtual void Cancel() ORTHANC_OVERRIDE; + virtual bool IsAlive() const ORTHANC_OVERRIDE; + protected: + CreateMeasureTracker( + ViewportControllerWPtr controllerW, + std::vector& undoStack, + std::vector& measureTools); + + ~CreateMeasureTracker(); + + protected: + CreateMeasureCommandPtr command_; + ViewportControllerWPtr controllerW_; + bool alive_; + Scene2DPtr GetScene(); + + private: + std::vector& undoStack_; + std::vector& measureTools_; + bool commitResult_; + }; +} + diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2DViewport/OneGesturePointerTracker.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/OneGesturePointerTracker.cpp Sun May 19 16:31:56 2019 +0200 @@ -0,0 +1,56 @@ +/** + * 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 "OneGesturePointerTracker.h" +#include + +using namespace Orthanc; + +namespace OrthancStone +{ + OneGesturePointerTracker::OneGesturePointerTracker( + ViewportControllerWPtr controllerW) + : controllerW_(controllerW) + , alive_(true) + { + } + + void OneGesturePointerTracker::PointerUp(const PointerEvent& event) + { + alive_ = false; + } + + void OneGesturePointerTracker::PointerDown(const PointerEvent& event) + { + throw OrthancException(ErrorCode_InternalError, "Wrong state in tracker"); + } + + bool OneGesturePointerTracker::IsAlive() const + { + return alive_; + } + + ViewportControllerPtr OneGesturePointerTracker::GetController() + { + return controllerW_.lock(); + } +} diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2DViewport/OneGesturePointerTracker.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/OneGesturePointerTracker.h Sun May 19 16:31:56 2019 +0200 @@ -0,0 +1,54 @@ +/** + * 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 "IFlexiblePointerTracker.h" + +namespace OrthancStone +{ + /** + This base is class allows to write simple trackers that deal with single + drag gestures. It is *not* suitables for multi-state trackers where various + mouse operations need to be handled. + + In order to write such a tracker: + - subclass this class + - you may store the initial click/touch position in the constructor + - implement PointerMove to react to pointer/touch events + - implement Cancel to restore the state at initial tracker creation time + */ + class OneGesturePointerTracker : public IFlexiblePointerTracker + { + public: + OneGesturePointerTracker(ViewportControllerWPtr controllerW); + virtual void PointerUp(const PointerEvent& event) ORTHANC_OVERRIDE; + virtual void PointerDown(const PointerEvent& event) ORTHANC_OVERRIDE; + virtual bool IsAlive() const ORTHANC_OVERRIDE; + + protected: + ViewportControllerPtr GetController(); + + private: + ViewportControllerWPtr controllerW_; + bool alive_; + }; +} + diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2DViewport/PointerTypes.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/PointerTypes.h Sun May 19 16:31:56 2019 +0200 @@ -0,0 +1,83 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2018 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 +#include + +#include + +namespace OrthancStone +{ + class Scene2D; + typedef boost::shared_ptr Scene2DPtr; + + typedef boost::weak_ptr Scene2DWPtr; + + class MeasureTool; + typedef boost::shared_ptr + MeasureToolPtr; + typedef boost::weak_ptr + MeasureToolWPtr; + typedef std::vector + MeasureToolList; + + class LineMeasureTool; + typedef boost::shared_ptr + LineMeasureToolPtr; + + class AngleMeasureTool; + typedef boost::shared_ptr + AngleMeasureToolPtr; + + class IPointerTracker; + typedef boost::shared_ptr + PointerTrackerPtr; + + class IFlexiblePointerTracker; + typedef boost::shared_ptr + FlexiblePointerTrackerPtr; + + typedef boost::shared_ptr + LineMeasureToolPtr; + + class CreateMeasureCommand; + typedef boost::shared_ptr + CreateMeasureCommandPtr; + + class CreateLineMeasureCommand; + typedef boost::shared_ptr + CreateLineMeasureCommandPtr; + + class CreateAngleMeasureCommand; + typedef boost::shared_ptr + CreateAngleMeasureCommandPtr; + + + typedef boost::shared_ptr Scene2DPtr; + + class TrackerCommand; + typedef boost::shared_ptr TrackerCommandPtr; + + class ViewportController; + typedef boost::shared_ptr ViewportControllerPtr; + typedef boost::weak_ptr ViewportControllerWPtr; +} diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2DViewport/ViewportController.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/ViewportController.cpp Sun May 19 16:31:56 2019 +0200 @@ -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 . + **/ + +#include "ViewportController.h" + +#include + +#include + +using namespace Orthanc; + +namespace OrthancStone +{ + ViewportController::ViewportController(MessageBroker& broker) + : IObservable(broker) + { + scene_ = boost::make_shared(); + } + + Scene2DPtr ViewportController::GetScene() + { + return scene_; + } + + bool ViewportController::HandlePointerEvent(PointerEvent e) + { + throw StoneException(ErrorCode_NotImplemented); + } + + const OrthancStone::AffineTransform2D& ViewportController::GetCanvasToSceneTransform() const + { + return scene_->GetCanvasToSceneTransform(); + } + + const OrthancStone::AffineTransform2D& ViewportController::GetSceneToCanvasTransform() const + { + return scene_->GetSceneToCanvasTransform(); + } + + void ViewportController::SetSceneToCanvasTransform( + const AffineTransform2D& transform) + { + scene_->SetSceneToCanvasTransform(transform); + BroadcastMessage(SceneTransformChanged(*this)); + } + +} + diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Scene2DViewport/ViewportController.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/ViewportController.h Sun May 19 16:31:56 2019 +0200 @@ -0,0 +1,86 @@ +/** + * 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 "PointerTypes.h" + +#include +#include +#include + +namespace OrthancStone +{ + /** + This object is responsible for hosting a scene, responding to messages from + the model and updating the scene accordingly. + + It contains the list of active measuring tools as well as the stack + where measuring tool commands are stored. + + The active tracker is also stored in the viewport controller. + + Each canvas or other GUI area where we want to display a 2D image, either + directly or through slicing must be assigned a ViewportController. + */ + class ViewportController : public IObservable + { + public: + ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, \ + SceneTransformChanged, ViewportController); + + ViewportController(MessageBroker& broker); + + Scene2DPtr GetScene(); + + /** + This method is called by the GUI system and should update/delete the + current tracker + */ + bool HandlePointerEvent(PointerEvent e); + + /** + This method returns the list of measure tools containing the supplied point + (in scene coords). A tracker can then be requested from the chosen + measure tool, if needed + */ + std::vector HitTestMeasureTools(ScenePoint2D p); + + /** + With this method, the object takes ownership of the supplied tracker and + updates it according to user interaction + */ + void SetActiveTracker(FlexiblePointerTrackerPtr tracker); + + /** Forwarded to the underlying scene */ + const AffineTransform2D& GetCanvasToSceneTransform() const; + + /** Forwarded to the underlying scene */ + const AffineTransform2D& GetSceneToCanvasTransform() const; + + /** Forwarded to the underlying scene, and broadcasted to the observers */ + void SetSceneToCanvasTransform(const AffineTransform2D& transform); + + + private: + Scene2DPtr scene_; + FlexiblePointerTrackerPtr tracker_; + }; +} diff -r 75deb0acd632 -r d4d6c5b502b5 Framework/Toolbox/ShearWarpProjectiveTransform.cpp --- a/Framework/Toolbox/ShearWarpProjectiveTransform.cpp Fri May 17 18:04:26 2019 +0200 +++ b/Framework/Toolbox/ShearWarpProjectiveTransform.cpp Sun May 19 16:31:56 2019 +0200 @@ -543,7 +543,8 @@ } else { - *p = *qacc / static_cast(*qcount); + *p = static_cast + (*qacc / static_cast(*qcount)); if (*p > maxValue) { diff -r 75deb0acd632 -r d4d6c5b502b5 README.md --- a/README.md Fri May 17 18:04:26 2019 +0200 +++ b/README.md Sun May 19 16:31:56 2019 +0200 @@ -251,7 +251,8 @@ ``` TODO trackers: -- text overlay 50% --> ColorTextureLayer 50% -- angle tracker: draw arcs +- CANCELLED (using outlined text now) text overlay 50% --> ColorTextureLayer 50% +- DONE angle tracker: draw arcs +- Handles on arc +- Select measure tool with hit test --> Delete command - diff -r 75deb0acd632 -r d4d6c5b502b5 Resources/CMake/OrthancStoneConfiguration.cmake --- a/Resources/CMake/OrthancStoneConfiguration.cmake Fri May 17 18:04:26 2019 +0200 +++ b/Resources/CMake/OrthancStoneConfiguration.cmake Sun May 19 16:31:56 2019 +0200 @@ -329,6 +329,40 @@ ${ORTHANC_STONE_ROOT}/Framework/Scene2D/TextureBaseSceneLayer.cpp ${ORTHANC_STONE_ROOT}/Framework/Scene2D/ZoomSceneTracker.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/AngleMeasureTool.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/AngleMeasureTool.h + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/CreateAngleMeasureTracker.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/CreateAngleMeasureTracker.h + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/CreateCircleMeasureTracker.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/CreateCircleMeasureTracker.h + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/CreateLineMeasureTracker.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/CreateLineMeasureTracker.h + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/CreateMeasureTracker.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/CreateMeasureTracker.h + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/CreateSimpleTrackerAdapter.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/EditAngleMeasureTracker.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/EditAngleMeasureTracker.h + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/EditCircleMeasureTracker.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/EditCircleMeasureTracker.h + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/EditLineMeasureTracker.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/EditLineMeasureTracker.h + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/IFlexiblePointerTracker.h + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/LineMeasureTool.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/LineMeasureTool.h + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/MeasureCommands.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/MeasureCommands.h + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/MeasureTools.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/MeasureTools.h + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/MeasureToolsToolbox.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/MeasureToolsToolbox.h + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/MeasureTrackers.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/MeasureTrackers.h + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/OneGesturePointerTracker.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/OneGesturePointerTracker.h + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/PointerTypes.h + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/ViewportController.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/ViewportController.h + ${ORTHANC_STONE_ROOT}/Framework/Fonts/FontRenderer.cpp ${ORTHANC_STONE_ROOT}/Framework/Fonts/Glyph.cpp ${ORTHANC_STONE_ROOT}/Framework/Fonts/GlyphAlphabet.cpp diff -r 75deb0acd632 -r d4d6c5b502b5 Samples/Common/AngleMeasureTool.cpp --- a/Samples/Common/AngleMeasureTool.cpp Fri May 17 18:04:26 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,261 +0,0 @@ -/** - * 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 "AngleMeasureTool.h" -#include "MeasureToolsToolbox.h" - -#include - -#include - -extern void TrackerSample_SetInfoDisplayMessage(std::string key, std::string value); - -namespace OrthancStone -{ - AngleMeasureTool::~AngleMeasureTool() - { - // this measuring tool is a RABI for the corresponding visual layers - // stored in the 2D scene - Disable(); - RemoveFromScene(); - } - - void AngleMeasureTool::RemoveFromScene() - { - if (layersCreated) - { - assert(GetScene().HasLayer(polylineZIndex_)); - assert(GetScene().HasLayer(textZIndex_)); - GetScene().DeleteLayer(polylineZIndex_); - GetScene().DeleteLayer(textZIndex_); - } - } - - void AngleMeasureTool::SetSide1End(ScenePoint2D pt) - { - side1End_ = pt; - RefreshScene(); - } - - void AngleMeasureTool::SetSide2End(ScenePoint2D pt) - { - side2End_ = pt; - RefreshScene(); - } - - void AngleMeasureTool::SetCenter(ScenePoint2D pt) - { - center_ = pt; - RefreshScene(); - } - - PolylineSceneLayer* AngleMeasureTool::GetPolylineLayer() - { - assert(GetScene().HasLayer(polylineZIndex_)); - ISceneLayer* layer = &(GetScene().GetLayer(polylineZIndex_)); - PolylineSceneLayer* concreteLayer = dynamic_cast(layer); - assert(concreteLayer != NULL); - return concreteLayer; - } - - TextSceneLayer* AngleMeasureTool::GetTextLayer() - { - assert(GetScene().HasLayer(textZIndex_)); - ISceneLayer* layer = &(GetScene().GetLayer(textZIndex_)); - TextSceneLayer* concreteLayer = dynamic_cast(layer); - assert(concreteLayer != NULL); - return concreteLayer; - } - - - void AngleMeasureTool::RefreshScene() - { - if (IsEnabled()) - { - // get the scaling factor - const double pixelToScene = - GetScene().GetCanvasToSceneTransform().ComputeZoom(); - - if (!layersCreated) - { - // Create the layers if need be - - assert(textZIndex_ == -1); - { - polylineZIndex_ = GetScene().GetMaxDepth() + 100; - //LOG(INFO) << "set polylineZIndex_ to: " << polylineZIndex_; - std::auto_ptr layer(new PolylineSceneLayer()); - GetScene().SetLayer(polylineZIndex_, layer.release()); - } - { - textZIndex_ = GetScene().GetMaxDepth() + 100; - //LOG(INFO) << "set textZIndex_ to: " << textZIndex_; - std::auto_ptr layer(new TextSceneLayer()); - GetScene().SetLayer(textZIndex_, layer.release()); - } - layersCreated = true; - } - else - { - assert(GetScene().HasLayer(polylineZIndex_)); - assert(GetScene().HasLayer(textZIndex_)); - } - { - // Fill the polyline layer with the measurement line - - PolylineSceneLayer* polylineLayer = GetPolylineLayer(); - polylineLayer->ClearAllChains(); - polylineLayer->SetColor(0, 223, 21); - - // sides - { - { - PolylineSceneLayer::Chain chain; - chain.push_back(side1End_); - chain.push_back(center_); - polylineLayer->AddChain(chain, false); - } - { - PolylineSceneLayer::Chain chain; - chain.push_back(side2End_); - chain.push_back(center_); - polylineLayer->AddChain(chain, false); - } - } - - // handles - { - //void AddSquare(PolylineSceneLayer::Chain& chain,const Scene2D& scene,const ScenePoint2D& centerS,const double& sideLength) - - { - PolylineSceneLayer::Chain chain; - AddSquare(chain, GetScene(), side1End_, 10.0* pixelToScene); //TODO: take DPI into account - polylineLayer->AddChain(chain, true); - } - - { - PolylineSceneLayer::Chain chain; - AddSquare(chain, GetScene(), side2End_, 10.0* pixelToScene); //TODO: take DPI into account - polylineLayer->AddChain(chain, true); - } - } - - // arc - { - PolylineSceneLayer::Chain chain; - - const double ARC_RADIUS_CANVAS_COORD = 30.0; - AddShortestArc(chain, GetScene(), side1End_, center_, side2End_, - ARC_RADIUS_CANVAS_COORD*pixelToScene); - polylineLayer->AddChain(chain, false); - } - } - { - // Set the text layer - - double p1cAngle = atan2( - side1End_.GetY() - center_.GetY(), - side1End_.GetX() - center_.GetX()); - - TrackerSample_SetInfoDisplayMessage("center_.GetX()", - boost::lexical_cast(center_.GetX())); - - TrackerSample_SetInfoDisplayMessage("center_.GetY()", - boost::lexical_cast(center_.GetY())); - - TrackerSample_SetInfoDisplayMessage("side1End_.GetX()", - boost::lexical_cast(side1End_.GetX())); - - TrackerSample_SetInfoDisplayMessage("side1End_.GetY()", - boost::lexical_cast(side1End_.GetY())); - - TrackerSample_SetInfoDisplayMessage("side2End_.GetX()", - boost::lexical_cast(side2End_.GetX())); - - TrackerSample_SetInfoDisplayMessage("side2End_.GetY()", - boost::lexical_cast(side2End_.GetY())); - - TrackerSample_SetInfoDisplayMessage("p1cAngle (deg)", - boost::lexical_cast(RadiansToDegrees(p1cAngle))); - - double p2cAngle = atan2( - side2End_.GetY() - center_.GetY(), - side2End_.GetX() - center_.GetX()); - - double delta = NormalizeAngle(p2cAngle - p1cAngle); - TrackerSample_SetInfoDisplayMessage("delta (deg)", - boost::lexical_cast(RadiansToDegrees(delta))); - - double theta = p1cAngle + delta/2; - - TrackerSample_SetInfoDisplayMessage("theta (deg)", - boost::lexical_cast(RadiansToDegrees(theta))); - - TrackerSample_SetInfoDisplayMessage("p2cAngle (deg)", - boost::lexical_cast(RadiansToDegrees(p2cAngle))); - - const double TEXT_CENTER_DISTANCE_CANVAS_COORD = 90; - - double offsetX = TEXT_CENTER_DISTANCE_CANVAS_COORD * cos(theta); - TrackerSample_SetInfoDisplayMessage("offsetX (pix)", - boost::lexical_cast(offsetX)); - - double offsetY = TEXT_CENTER_DISTANCE_CANVAS_COORD * sin(theta); - TrackerSample_SetInfoDisplayMessage("offsetY (pix)", - boost::lexical_cast(offsetY)); - - double pointX = center_.GetX() + offsetX * pixelToScene; - double pointY = center_.GetY() + offsetY * pixelToScene; - TrackerSample_SetInfoDisplayMessage("pointX", - boost::lexical_cast(pointX)); - - TrackerSample_SetInfoDisplayMessage("pointY", - boost::lexical_cast(pointY)); - - TextSceneLayer* textLayer = GetTextLayer(); - - char buf[64]; - double angleDeg = RadiansToDegrees(delta); - - TrackerSample_SetInfoDisplayMessage("angleDeg", - boost::lexical_cast(angleDeg)); - - sprintf(buf, "%0.02f deg", angleDeg); - textLayer->SetText(buf); - textLayer->SetColor(0, 223, 21); - - ScenePoint2D textAnchor; - //GetPositionOnBisectingLine( - // textAnchor, side1End_, center_, side2End_, 40.0*pixelToScene); - textLayer->SetPosition(pointX, pointY); - } - } - else - { - if (layersCreated) - { - RemoveFromScene(); - layersCreated = false; - } - } - } - - -} diff -r 75deb0acd632 -r d4d6c5b502b5 Samples/Common/AngleMeasureTool.h --- a/Samples/Common/AngleMeasureTool.h Fri May 17 18:04:26 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -/** - * 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 "MeasureTools.h" - -#include -#include -#include -#include - -#include -#include - -#include -#include - -namespace OrthancStone -{ - class AngleMeasureTool : public MeasureTool - { - public: - AngleMeasureTool(MessageBroker& broker, Scene2D& scene) - : MeasureTool(broker, scene) - , layersCreated(false) - , polylineZIndex_(-1) - , textZIndex_(-1) - { - - } - - ~AngleMeasureTool(); - - void SetSide1End(ScenePoint2D start); - void SetCenter(ScenePoint2D start); - void SetSide2End(ScenePoint2D start); - - private: - PolylineSceneLayer* GetPolylineLayer(); - TextSceneLayer* GetTextLayer(); - virtual void RefreshScene() ORTHANC_OVERRIDE; - void RemoveFromScene(); - - private: - ScenePoint2D side1End_; - ScenePoint2D side2End_; - ScenePoint2D center_; - bool layersCreated; - int polylineZIndex_; - int textZIndex_; - }; - - typedef boost::shared_ptr AngleMeasureToolPtr; -} - - diff -r 75deb0acd632 -r d4d6c5b502b5 Samples/Common/CreateAngleMeasureTracker.cpp --- a/Samples/Common/CreateAngleMeasureTracker.cpp Fri May 17 18:04:26 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,128 +0,0 @@ -/** - * 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 "CreateAngleMeasureTracker.h" -#include - -using namespace Orthanc; - -namespace OrthancStone -{ - CreateAngleMeasureTracker::CreateAngleMeasureTracker( - MessageBroker& broker, - Scene2D& scene, - std::vector& undoStack, - std::vector& measureTools, - const PointerEvent& e) - : CreateMeasureTracker(scene, undoStack, measureTools) - , state_(CreatingSide1) - { - command_.reset( - new CreateAngleMeasureCommand( - broker, - scene, - measureTools, - e.GetMainPosition().Apply(scene.GetCanvasToSceneTransform()))); - } - - CreateAngleMeasureTracker::~CreateAngleMeasureTracker() - { - } - - void CreateAngleMeasureTracker::PointerMove(const PointerEvent& event) - { - if (!active_) - { - throw OrthancException(ErrorCode_InternalError, - "Internal error: wrong state in CreateAngleMeasureTracker::" - "PointerMove: active_ == false"); - } - - ScenePoint2D scenePos = event.GetMainPosition().Apply( - scene_.GetCanvasToSceneTransform()); - - switch (state_) - { - case CreatingSide1: - GetCommand()->SetCenter(scenePos); - break; - case CreatingSide2: - GetCommand()->SetSide2End(scenePos); - break; - default: - throw OrthancException(ErrorCode_InternalError, - "Wrong state in CreateAngleMeasureTracker::" - "PointerMove: state_ invalid"); - } - //LOG(TRACE) << "scenePos.GetX() = " << scenePos.GetX() << " " << - // "scenePos.GetY() = " << scenePos.GetY(); - } - - void CreateAngleMeasureTracker::PointerUp(const PointerEvent& e) - { - // TODO: the current app does not prevent multiple PointerDown AND - // PointerUp to be sent to the tracker. - // Unless we augment the PointerEvent structure with the button index, - // we cannot really tell if this pointer up event matches the initial - // pointer down event. Let's make it simple for now. - - switch (state_) - { - case CreatingSide1: - state_ = CreatingSide2; - break; - case CreatingSide2: - throw OrthancException(ErrorCode_InternalError, - "Wrong state in CreateAngleMeasureTracker::" - "PointerUp: state_ == CreatingSide2 ; this should not happen"); - break; - default: - throw OrthancException(ErrorCode_InternalError, - "Wrong state in CreateAngleMeasureTracker::" - "PointerMove: state_ invalid"); - } - } - - void CreateAngleMeasureTracker::PointerDown(const PointerEvent& e) - { - switch (state_) - { - case CreatingSide1: - throw OrthancException(ErrorCode_InternalError, - "Wrong state in CreateAngleMeasureTracker::" - "PointerDown: state_ == CreatingSide1 ; this should not happen"); - break; - case CreatingSide2: - // we are done - active_ = false; - break; - default: - throw OrthancException(ErrorCode_InternalError, - "Wrong state in CreateAngleMeasureTracker::" - "PointerMove: state_ invalid"); - } - } - - CreateAngleMeasureCommandPtr CreateAngleMeasureTracker::GetCommand() - { - return boost::dynamic_pointer_cast(command_); - } - -} diff -r 75deb0acd632 -r d4d6c5b502b5 Samples/Common/CreateAngleMeasureTracker.h --- a/Samples/Common/CreateAngleMeasureTracker.h Fri May 17 18:04:26 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/** - * 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 "MeasureTrackers.h" -#include "MeasureCommands.h" - -#include - -namespace OrthancStone -{ - class CreateAngleMeasureTracker : public CreateMeasureTracker - { - public: - /** - When you create this tracker, you need to supply it with the undo stack - where it will store the commands that perform the actual measure tool - creation and modification. - In turn, a container for these commands to store the actual measuring - must be supplied, too - */ - CreateAngleMeasureTracker( - MessageBroker& broker, - Scene2D& scene, - std::vector& undoStack, - std::vector& measureTools, - const PointerEvent& e); - - ~CreateAngleMeasureTracker(); - - virtual void PointerMove(const PointerEvent& e) ORTHANC_OVERRIDE; - virtual void PointerUp(const PointerEvent& e) ORTHANC_OVERRIDE; - virtual void PointerDown(const PointerEvent& e) ORTHANC_OVERRIDE; - - private: - CreateAngleMeasureCommandPtr GetCommand(); - - enum State - { - CreatingSide1, - CreatingSide2, - Finished // just for debug - }; - State state_; - - }; -} diff -r 75deb0acd632 -r d4d6c5b502b5 Samples/Common/CreateCircleMeasureTracker.cpp --- a/Samples/Common/CreateCircleMeasureTracker.cpp Fri May 17 18:04:26 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -/** - * 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 . - **/ - -namespace OrthancStone -{ -} diff -r 75deb0acd632 -r d4d6c5b502b5 Samples/Common/CreateCircleMeasureTracker.h --- a/Samples/Common/CreateCircleMeasureTracker.h Fri May 17 18:04:26 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -/** - * 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 - -namespace OrthancStone -{ -} diff -r 75deb0acd632 -r d4d6c5b502b5 Samples/Common/CreateLineMeasureTracker.cpp --- a/Samples/Common/CreateLineMeasureTracker.cpp Fri May 17 18:04:26 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ -/** - * 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 "CreateLineMeasureTracker.h" -#include - -using namespace Orthanc; - -namespace OrthancStone -{ - CreateLineMeasureTracker::CreateLineMeasureTracker( - MessageBroker& broker, - Scene2D& scene, - std::vector& undoStack, - std::vector& measureTools, - const PointerEvent& e) - : CreateMeasureTracker(scene, undoStack, measureTools) - { - command_.reset( - new CreateLineMeasureCommand( - broker, - scene, - measureTools, - e.GetMainPosition().Apply(scene.GetCanvasToSceneTransform()))); - } - - CreateLineMeasureTracker::~CreateLineMeasureTracker() - { - - } - - void CreateLineMeasureTracker::PointerMove(const PointerEvent& event) - { - if (!active_) - { - throw OrthancException(ErrorCode_InternalError, - "Internal error: wrong state in CreateLineMeasureTracker::" - "PointerMove: active_ == false"); - } - - ScenePoint2D scenePos = event.GetMainPosition().Apply( - scene_.GetCanvasToSceneTransform()); - - //LOG(TRACE) << "scenePos.GetX() = " << scenePos.GetX() << " " << - // "scenePos.GetY() = " << scenePos.GetY(); - - CreateLineMeasureTracker* concreteThis = - dynamic_cast(this); - assert(concreteThis != NULL); - GetCommand()->SetEnd(scenePos); - } - - void CreateLineMeasureTracker::PointerUp(const PointerEvent& e) - { - // TODO: the current app does not prevent multiple PointerDown AND - // PointerUp to be sent to the tracker. - // Unless we augment the PointerEvent structure with the button index, - // we cannot really tell if this pointer up event matches the initial - // pointer down event. Let's make it simple for now. - active_ = false; - } - - void CreateLineMeasureTracker::PointerDown(const PointerEvent& e) - { - LOG(WARNING) << "Additional touches (fingers, pen, mouse buttons...) " - "are ignored when the line measure creation tracker is active"; - } - - CreateLineMeasureCommandPtr CreateLineMeasureTracker::GetCommand() - { - return boost::dynamic_pointer_cast(command_); - } - -} diff -r 75deb0acd632 -r d4d6c5b502b5 Samples/Common/CreateLineMeasureTracker.h --- a/Samples/Common/CreateLineMeasureTracker.h Fri May 17 18:04:26 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -/** - * 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 "MeasureTrackers.h" - -namespace OrthancStone -{ - class CreateLineMeasureTracker : public CreateMeasureTracker - { - public: - /** - When you create this tracker, you need to supply it with the undo stack - where it will store the commands that perform the actual measure tool - creation and modification. - In turn, a container for these commands to store the actual measuring - must be supplied, too - */ - CreateLineMeasureTracker( - MessageBroker& broker, - Scene2D& scene, - std::vector& undoStack, - std::vector& measureTools, - const PointerEvent& e); - - ~CreateLineMeasureTracker(); - - virtual void PointerMove(const PointerEvent& e) ORTHANC_OVERRIDE; - virtual void PointerUp(const PointerEvent& e) ORTHANC_OVERRIDE; - virtual void PointerDown(const PointerEvent& e) ORTHANC_OVERRIDE; - - private: - CreateLineMeasureCommandPtr GetCommand(); - }; -} diff -r 75deb0acd632 -r d4d6c5b502b5 Samples/Common/CreateMeasureTracker.cpp --- a/Samples/Common/CreateMeasureTracker.cpp Fri May 17 18:04:26 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ -/** - * 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 . - **/ - diff -r 75deb0acd632 -r d4d6c5b502b5 Samples/Common/CreateMeasureTracker.h --- a/Samples/Common/CreateMeasureTracker.h Fri May 17 18:04:26 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -/** - * 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 - diff -r 75deb0acd632 -r d4d6c5b502b5 Samples/Common/CreateSimpleTrackerAdapter.cpp --- a/Samples/Common/CreateSimpleTrackerAdapter.cpp Fri May 17 18:04:26 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +0,0 @@ -/** - * 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 "IFlexiblePointerTracker.h" -#include - - -namespace OrthancStone -{ - namespace - { - class SimpleTrackerAdapter : public IFlexiblePointerTracker - { - public: - SimpleTrackerAdapter(PointerTrackerPtr wrappedTracker) - : wrappedTracker_(wrappedTracker) - , active_(true) - { - } - - virtual void PointerMove(const PointerEvent& event) ORTHANC_OVERRIDE - { - if(active_) - wrappedTracker_->Update(event); - }; - virtual void PointerUp(const PointerEvent& event) ORTHANC_OVERRIDE - { - if (wrappedTracker_) - { - wrappedTracker_->Release(); - wrappedTracker_ = NULL; - } - active_ = false; - } - virtual void PointerDown(const PointerEvent& event) ORTHANC_OVERRIDE - { - // nothing to do atm - } - virtual bool IsActive() const ORTHANC_OVERRIDE - { - return active_; - } - - virtual void Cancel() ORTHANC_OVERRIDE - { - wrappedTracker_ = NULL; - active_ = false; - } - - private: - PointerTrackerPtr wrappedTracker_; - bool active_; - }; - } - - FlexiblePointerTrackerPtr CreateSimpleTrackerAdapter(PointerTrackerPtr t) - { - return FlexiblePointerTrackerPtr(new SimpleTrackerAdapter(t)); - } -} diff -r 75deb0acd632 -r d4d6c5b502b5 Samples/Common/EditAngleMeasureTracker.cpp --- a/Samples/Common/EditAngleMeasureTracker.cpp Fri May 17 18:04:26 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -/** - * 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 . - **/ - -namespace OrthancStone -{ -} diff -r 75deb0acd632 -r d4d6c5b502b5 Samples/Common/EditAngleMeasureTracker.h --- a/Samples/Common/EditAngleMeasureTracker.h Fri May 17 18:04:26 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -/** - * 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 - -namespace OrthancStone -{ -} diff -r 75deb0acd632 -r d4d6c5b502b5 Samples/Common/EditCircleMeasureTracker.cpp --- a/Samples/Common/EditCircleMeasureTracker.cpp Fri May 17 18:04:26 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -/** - * 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 . - **/ - -namespace OrthancStone -{ -} diff -r 75deb0acd632 -r d4d6c5b502b5 Samples/Common/EditCircleMeasureTracker.h --- a/Samples/Common/EditCircleMeasureTracker.h Fri May 17 18:04:26 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -/** - * 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 - -namespace OrthancStone -{ -} diff -r 75deb0acd632 -r d4d6c5b502b5 Samples/Common/EditLineMeasureTracker.cpp --- a/Samples/Common/EditLineMeasureTracker.cpp Fri May 17 18:04:26 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -/** - * 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 . - **/ - -namespace OrthancStone -{ -} diff -r 75deb0acd632 -r d4d6c5b502b5 Samples/Common/EditLineMeasureTracker.h --- a/Samples/Common/EditLineMeasureTracker.h Fri May 17 18:04:26 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -/** - * 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 - -namespace OrthancStone -{ -} diff -r 75deb0acd632 -r d4d6c5b502b5 Samples/Common/IFlexiblePointerTracker.h --- a/Samples/Common/IFlexiblePointerTracker.h Fri May 17 18:04:26 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,84 +0,0 @@ -/** - * 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 -#include - -namespace OrthancStone -{ - class IPointerTracker; - typedef boost::shared_ptr PointerTrackerPtr; - - /** - This interface represents a flexible mouse tracker that can respond to - several events and is not automatically deleted upon mouse up or when touch - interaction is suspended : for instance, a stateful tracker with a two-step - interaction like: click & drag --> mouse up --> drag --> mouse click - (for instance, for an angle measuring tracker or an ellipse tracker) - */ - class IFlexiblePointerTracker : public boost::noncopyable - { - public: - virtual ~IFlexiblePointerTracker() {} - - /** - This method will be repeatedly called during user interaction - */ - virtual void PointerMove(const PointerEvent& event) = 0; - - /** - This method will be called when a touch/pointer is removed (mouse up, - pen lift, finger removed...) - */ - virtual void PointerUp(const PointerEvent& event) = 0; - - /** - This method will be called when a touch/pointer is added (mouse down, - pen or finger press) - */ - virtual void PointerDown(const PointerEvent& event) = 0; - - /** - This method will be repeatedly called by the tracker owner (for instance, - the application) to check whether the tracker must keep on receiving - interaction or if its job is done and it should be deleted. - */ - virtual bool IsActive() const = 0; - - /** - This will be called if the tracker needs to be dismissed without committing - its changes to the underlying model. If the model has been modified during - tracker lifetime, it must be restored to its initial value - */ - virtual void Cancel() = 0; - }; - - typedef boost::shared_ptr FlexiblePointerTrackerPtr; - - /** - This factory adopts the supplied simple tracker and creates a flexible - tracker wrapper around it. - */ - FlexiblePointerTrackerPtr CreateSimpleTrackerAdapter(PointerTrackerPtr); -} - diff -r 75deb0acd632 -r d4d6c5b502b5 Samples/Common/LineMeasureTool.cpp --- a/Samples/Common/LineMeasureTool.cpp Fri May 17 18:04:26 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,200 +0,0 @@ -/** - * 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 "LineMeasureTool.h" -#include "MeasureToolsToolbox.h" - -#include - - -namespace OrthancStone -{ - LineMeasureTool::~LineMeasureTool() - { - // this measuring tool is a RABI for the corresponding visual layers - // stored in the 2D scene - Disable(); - RemoveFromScene(); - } - - void LineMeasureTool::RemoveFromScene() - { - if (layersCreated) - { - assert(GetScene().HasLayer(polylineZIndex_)); - assert(GetScene().HasLayer(textZIndex_)); - GetScene().DeleteLayer(polylineZIndex_); - GetScene().DeleteLayer(textZIndex_); - } - } - - - void LineMeasureTool::SetStart(ScenePoint2D start) - { - start_ = start; - RefreshScene(); - } - - void LineMeasureTool::SetEnd(ScenePoint2D end) - { - end_ = end; - RefreshScene(); - } - - void LineMeasureTool::Set(ScenePoint2D start, ScenePoint2D end) - { - start_ = start; - end_ = end; - RefreshScene(); - } - - PolylineSceneLayer* LineMeasureTool::GetPolylineLayer() - { - assert(GetScene().HasLayer(polylineZIndex_)); - ISceneLayer* layer = &(GetScene().GetLayer(polylineZIndex_)); - PolylineSceneLayer* concreteLayer = dynamic_cast(layer); - assert(concreteLayer != NULL); - return concreteLayer; - } - - TextSceneLayer* LineMeasureTool::GetTextLayer() - { - assert(GetScene().HasLayer(textZIndex_)); - ISceneLayer* layer = &(GetScene().GetLayer(textZIndex_)); - TextSceneLayer* concreteLayer = dynamic_cast(layer); - assert(concreteLayer != NULL); - return concreteLayer; - } - - void LineMeasureTool::RefreshScene() - { - if (IsEnabled()) - { - if (!layersCreated) - { - // Create the layers if need be - - assert(textZIndex_ == -1); - { - polylineZIndex_ = GetScene().GetMaxDepth() + 100; - //LOG(INFO) << "set polylineZIndex_ to: " << polylineZIndex_; - std::auto_ptr layer(new PolylineSceneLayer()); - GetScene().SetLayer(polylineZIndex_, layer.release()); - } - { - textZIndex_ = GetScene().GetMaxDepth() + 100; - //LOG(INFO) << "set textZIndex_ to: " << textZIndex_; - std::auto_ptr layer(new TextSceneLayer()); - GetScene().SetLayer(textZIndex_, layer.release()); - } - layersCreated = true; - } - else - { - assert(GetScene().HasLayer(polylineZIndex_)); - assert(GetScene().HasLayer(textZIndex_)); - } - { - // Fill the polyline layer with the measurement line - - PolylineSceneLayer* polylineLayer = GetPolylineLayer(); - polylineLayer->ClearAllChains(); - polylineLayer->SetColor(0, 223, 21); - - { - PolylineSceneLayer::Chain chain; - chain.push_back(start_); - chain.push_back(end_); - polylineLayer->AddChain(chain, false); - } - - // handles - { - //void AddSquare(PolylineSceneLayer::Chain& chain,const Scene2D& scene,const ScenePoint2D& centerS,const double& sideLength) - - { - PolylineSceneLayer::Chain chain; - AddSquare(chain, GetScene(), start_, 10.0); //TODO: take DPI into account - polylineLayer->AddChain(chain, true); - } - - { - PolylineSceneLayer::Chain chain; - AddSquare(chain, GetScene(), end_, 10.0); //TODO: take DPI into account - polylineLayer->AddChain(chain, true); - } - - //ScenePoint2D startC = start_.Apply(GetScene().GetSceneToCanvasTransform()); - //double squareSize = 10.0; - //double startHandleLX = startC.GetX() - squareSize/2; - //double startHandleTY = startC.GetY() - squareSize / 2; - //double startHandleRX = startC.GetX() + squareSize / 2; - //double startHandleBY = startC.GetY() + squareSize / 2; - //ScenePoint2D startLTC(startHandleLX, startHandleTY); - //ScenePoint2D startRTC(startHandleRX, startHandleTY); - //ScenePoint2D startRBC(startHandleRX, startHandleBY); - //ScenePoint2D startLBC(startHandleLX, startHandleBY); - - //ScenePoint2D startLT = startLTC.Apply(GetScene().GetCanvasToSceneTransform()); - //ScenePoint2D startRT = startRTC.Apply(GetScene().GetCanvasToSceneTransform()); - //ScenePoint2D startRB = startRBC.Apply(GetScene().GetCanvasToSceneTransform()); - //ScenePoint2D startLB = startLBC.Apply(GetScene().GetCanvasToSceneTransform()); - - //PolylineSceneLayer::Chain chain; - //chain.push_back(startLT); - //chain.push_back(startRT); - //chain.push_back(startRB); - //chain.push_back(startLB); - //polylineLayer->AddChain(chain, true); - } - - } - { - // Set the text layer proporeties - - TextSceneLayer* textLayer = GetTextLayer(); - double deltaX = end_.GetX() - start_.GetX(); - double deltaY = end_.GetY() - start_.GetY(); - double squareDist = deltaX * deltaX + deltaY * deltaY; - double dist = sqrt(squareDist); - char buf[64]; - sprintf(buf, "%0.02f units", dist); - textLayer->SetText(buf); - textLayer->SetColor(0, 223, 21); - - // TODO: for now we simply position the text overlay at the middle - // of the measuring segment - double midX = 0.5*(end_.GetX() + start_.GetX()); - double midY = 0.5*(end_.GetY() + start_.GetY()); - textLayer->SetPosition(midX, midY); - } - } - else - { - if (layersCreated) - { - RemoveFromScene(); - layersCreated = false; - } - } - } - - -} \ No newline at end of file diff -r 75deb0acd632 -r d4d6c5b502b5 Samples/Common/LineMeasureTool.h --- a/Samples/Common/LineMeasureTool.h Fri May 17 18:04:26 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -/** - * 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 "MeasureTools.h" - -#include -#include -#include -#include - -#include -#include - -#include -#include - -namespace OrthancStone -{ - class LineMeasureTool : public MeasureTool - { - public: - LineMeasureTool(MessageBroker& broker, Scene2D& scene) - : MeasureTool(broker, scene) - , layersCreated(false) - , polylineZIndex_(-1) - , textZIndex_(-1) - { - - } - - ~LineMeasureTool(); - - void SetStart(ScenePoint2D start); - void SetEnd(ScenePoint2D end); - void Set(ScenePoint2D start, ScenePoint2D end); - - private: - PolylineSceneLayer* GetPolylineLayer(); - TextSceneLayer* GetTextLayer(); - virtual void RefreshScene() ORTHANC_OVERRIDE; - void RemoveFromScene(); - - private: - ScenePoint2D start_; - ScenePoint2D end_; - bool layersCreated; - int polylineZIndex_; - int textZIndex_; - }; - - typedef boost::shared_ptr LineMeasureToolPtr; -} - diff -r 75deb0acd632 -r d4d6c5b502b5 Samples/Common/MeasureCommands.cpp --- a/Samples/Common/MeasureCommands.cpp Fri May 17 18:04:26 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -/** - * 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 "MeasureCommands.h" - -namespace OrthancStone -{ - void CreateMeasureCommand::Undo() - { - // simply disable the measure tool upon undo - GetMeasureTool()->Disable(); - } - - void CreateMeasureCommand::Redo() - { - GetMeasureTool()->Enable(); - } - - CreateMeasureCommand::CreateMeasureCommand( - Scene2D& scene, MeasureToolList& measureTools) - : TrackerCommand(scene) - , measureTools_(measureTools) - { - - } - - CreateMeasureCommand::~CreateMeasureCommand() - { - // deleting the command should not change the model state - // we thus leave it as is - } - - CreateLineMeasureCommand::CreateLineMeasureCommand( - MessageBroker& broker, - Scene2D& scene, - MeasureToolList& measureTools, - ScenePoint2D point) - : CreateMeasureCommand(scene, measureTools) - , measureTool_(new LineMeasureTool(broker,scene)) - { - measureTools_.push_back(measureTool_); - measureTool_->Set(point, point); - } - - void CreateLineMeasureCommand::SetEnd(ScenePoint2D scenePos) - { - measureTool_->SetEnd(scenePos); - } - - CreateAngleMeasureCommand::CreateAngleMeasureCommand( - MessageBroker& broker, - Scene2D& scene, - MeasureToolList& measureTools, - ScenePoint2D point) - : CreateMeasureCommand(scene, measureTools) - , measureTool_(new AngleMeasureTool(broker,scene)) - { - measureTools_.push_back(measureTool_); - measureTool_->SetSide1End(point); - measureTool_->SetCenter(point); - measureTool_->SetSide2End(point); - } - - /** This method sets center*/ - void CreateAngleMeasureCommand::SetCenter(ScenePoint2D scenePos) - { - measureTool_->SetCenter(scenePos); - } - - /** This method sets end of side 2*/ - void CreateAngleMeasureCommand::SetSide2End(ScenePoint2D scenePos) - { - measureTool_->SetSide2End(scenePos); - } - -} diff -r 75deb0acd632 -r d4d6c5b502b5 Samples/Common/MeasureCommands.h --- a/Samples/Common/MeasureCommands.h Fri May 17 18:04:26 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,118 +0,0 @@ -/** - * 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 -#include - -// to be moved into Stone -#include "MeasureTools.h" -#include "LineMeasureTool.h" -#include "AngleMeasureTool.h" - -namespace OrthancStone -{ - //class LineMeasureTool; - //typedef boost::shared_ptr LineMeasureToolPtr; - //class AngleMeasureTool; - //typedef boost::shared_ptr AngleMeasureToolPtr; - - class TrackerCommand - { - public: - TrackerCommand(Scene2D& scene) : scene_(scene) - { - - } - virtual void Undo() = 0; - virtual void Redo() = 0; - Scene2D& GetScene() - { - return scene_; - } - - protected: - Scene2D& scene_; - private: - TrackerCommand(const TrackerCommand&); - TrackerCommand& operator=(const TrackerCommand&); - }; - - typedef boost::shared_ptr TrackerCommandPtr; - - class CreateMeasureCommand : public TrackerCommand - { - public: - CreateMeasureCommand(Scene2D& scene, MeasureToolList& measureTools); - ~CreateMeasureCommand(); - virtual void Undo() ORTHANC_OVERRIDE; - virtual void Redo() ORTHANC_OVERRIDE; - protected: - MeasureToolList& measureTools_; - private: - /** Must be implemented by the subclasses that create the actual tool */ - virtual MeasureToolPtr GetMeasureTool() = 0; - }; - - typedef boost::shared_ptr CreateMeasureCommandPtr; - - class CreateLineMeasureCommand : public CreateMeasureCommand - { - public: - CreateLineMeasureCommand( - MessageBroker& broker, Scene2D& scene, MeasureToolList& measureTools, ScenePoint2D point); - - // the starting position is set in the ctor - void SetEnd(ScenePoint2D scenePos); - - private: - virtual MeasureToolPtr GetMeasureTool() ORTHANC_OVERRIDE - { - return measureTool_; - } - LineMeasureToolPtr measureTool_; - }; - - typedef boost::shared_ptr CreateLineMeasureCommandPtr; - - class CreateAngleMeasureCommand : public CreateMeasureCommand - { - public: - /** Ctor sets end of side 1*/ - CreateAngleMeasureCommand( - MessageBroker& broker, Scene2D& scene, MeasureToolList& measureTools, ScenePoint2D point); - - /** This method sets center*/ - void SetCenter(ScenePoint2D scenePos); - - /** This method sets end of side 2*/ - void SetSide2End(ScenePoint2D scenePos); - - private: - virtual MeasureToolPtr GetMeasureTool() ORTHANC_OVERRIDE - { - return measureTool_; - } - AngleMeasureToolPtr measureTool_; - }; - - typedef boost::shared_ptr CreateAngleMeasureCommandPtr; -} - diff -r 75deb0acd632 -r d4d6c5b502b5 Samples/Common/MeasureTools.cpp --- a/Samples/Common/MeasureTools.cpp Fri May 17 18:04:26 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -/** - * 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 "MeasureTools.h" - -#include - -#include - -namespace OrthancStone -{ - - MeasureTool::~MeasureTool() - { - - } - - void MeasureTool::Enable() - { - enabled_ = true; - RefreshScene(); - } - - void MeasureTool::Disable() - { - enabled_ = false; - RefreshScene(); - } - - bool MeasureTool::IsEnabled() const - { - return enabled_; - } - - OrthancStone::Scene2D& MeasureTool::GetScene() - { - return scene_; - } - - MeasureTool::MeasureTool(MessageBroker& broker, Scene2D& scene) - : IObserver(broker) - , scene_(scene) - , enabled_(true) - { - scene_.RegisterObserverCallback( - new Callable - (*this, &MeasureTool::OnSceneTransformChanged)); - } - - void MeasureTool::OnSceneTransformChanged( - const Scene2D::SceneTransformChanged& message) - { - RefreshScene(); - } - - -} - diff -r 75deb0acd632 -r d4d6c5b502b5 Samples/Common/MeasureTools.h --- a/Samples/Common/MeasureTools.h Fri May 17 18:04:26 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,89 +0,0 @@ -/** - * 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 -#include -#include -#include - -#include -#include - -#include -#include - -namespace OrthancStone -{ - class MeasureTool : public IObserver - { - public: - virtual ~MeasureTool(); - - /** - Enabled tools are rendered in the scene. - */ - void Enable(); - - /** - Disabled tools are not rendered in the scene. This is useful to be able - to use them as their own memento in command stacks (when a measure tool - creation command has been undone, the measure remains alive in the - command object but is disabled so that it can be redone later on easily) - */ - void Disable(); - - /** - This method is called when the scene transform changes. It allows to - recompute the visual elements whose content depend upon the scene transform - */ - void OnSceneTransformChanged(const Scene2D::SceneTransformChanged& message); - - protected: - MeasureTool(MessageBroker& broker, Scene2D& scene); - - /** - This is the meat of the tool: this method must [create (if needed) and] - update the layers and their data according to the measure tool kind and - current state. This is repeatedly called during user interaction - */ - virtual void RefreshScene() = 0; - - Scene2D& GetScene(); - - /** - enabled_ is not accessible by subclasses because there is a state machine - that we do not wanna mess with - */ - bool IsEnabled() const; - - private: - Scene2D& scene_; - bool enabled_; - }; - - typedef boost::shared_ptr MeasureToolPtr; - typedef std::vector MeasureToolList; -} - - -extern void TrackerSample_SetInfoDisplayMessage( - std::string key, std::string value); diff -r 75deb0acd632 -r d4d6c5b502b5 Samples/Common/MeasureToolsToolbox.cpp --- a/Samples/Common/MeasureToolsToolbox.cpp Fri May 17 18:04:26 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,278 +0,0 @@ -/** - * 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 "MeasureToolsToolbox.h" - -#include - -namespace -{ - double g_pi = boost::math::constants::pi(); -} - -namespace OrthancStone -{ - double RadiansToDegrees(double angleRad) - { - static const double factor = 180.0 / g_pi; - return angleRad * factor; - } - - void AddSquare(PolylineSceneLayer::Chain& chain, - const Scene2D& scene, - const ScenePoint2D& centerS, - const double& sideLength) - { - chain.clear(); - chain.reserve(4); - ScenePoint2D centerC = centerS.Apply(scene.GetSceneToCanvasTransform()); - //TODO: take DPI into account - double handleLX = centerC.GetX() - sideLength / 2; - double handleTY = centerC.GetY() - sideLength / 2; - double handleRX = centerC.GetX() + sideLength / 2; - double handleBY = centerC.GetY() + sideLength / 2; - ScenePoint2D LTC(handleLX, handleTY); - ScenePoint2D RTC(handleRX, handleTY); - ScenePoint2D RBC(handleRX, handleBY); - ScenePoint2D LBC(handleLX, handleBY); - - ScenePoint2D startLT = LTC.Apply(scene.GetCanvasToSceneTransform()); - ScenePoint2D startRT = RTC.Apply(scene.GetCanvasToSceneTransform()); - ScenePoint2D startRB = RBC.Apply(scene.GetCanvasToSceneTransform()); - ScenePoint2D startLB = LBC.Apply(scene.GetCanvasToSceneTransform()); - - chain.push_back(startLT); - chain.push_back(startRT); - chain.push_back(startRB); - chain.push_back(startLB); - } -#if 0 - void AddArc( - PolylineSceneLayer::Chain& chain - , const Scene2D& scene - , const ScenePoint2D& p1 - , const ScenePoint2D& c - , const ScenePoint2D& p2 - , const double& radiusS - , const bool clockwise - , const int subdivisionsCount) - { - double p1cAngle = atan2(p1.GetY() - c.GetY(), p1.GetX() - c.GetX()); - double p2cAngle = atan2(p2.GetY() - c.GetY(), p2.GetX() - c.GetX()); - AddArc( - chain, scene, c, radiusS, p1cAngle, p2cAngle, - clockwise, subdivisionsCount); - } -#endif - - void AddShortestArc( - PolylineSceneLayer::Chain& chain - , const Scene2D& scene - , const ScenePoint2D& p1 - , const ScenePoint2D& c - , const ScenePoint2D& p2 - , const double& radiusS - , const int subdivisionsCount) - { - double p1cAngle = atan2(p1.GetY() - c.GetY(), p1.GetX() - c.GetX()); - double p2cAngle = atan2(p2.GetY() - c.GetY(), p2.GetX() - c.GetX()); - AddShortestArc( - chain, scene, c, radiusS, p1cAngle, p2cAngle, subdivisionsCount); - } - - void GetPositionOnBisectingLine( - ScenePoint2D& result - , const ScenePoint2D& p1 - , const ScenePoint2D& c - , const ScenePoint2D& p2 - , const double d) - { - // TODO: fix correct half-plane - double p1cAngle = atan2(p1.GetY() - c.GetY(), p1.GetX() - c.GetX()); - double p2cAngle = atan2(p2.GetY() - c.GetY(), p2.GetX() - c.GetX()); - double angle = 0.5*(p1cAngle + p2cAngle); - double unitVectorX = cos(angle); - double unitVectorY = sin(angle); - double posX = c.GetX() + d * unitVectorX; - double posY = c.GetX() + d * unitVectorY; - result = ScenePoint2D(posX, posY); - } - - - void AddShortestArc( - PolylineSceneLayer::Chain& chain - , const Scene2D& scene - , const ScenePoint2D& centerS - , const double& radiusS - , const double startAngleRad - , const double endAngleRad - , const int subdivisionsCount) - { - // this gives a signed difference between angle which - // is the smallest difference (in magnitude) between - // the angles - double delta = NormalizeAngle(endAngleRad-startAngleRad); - - chain.clear(); - chain.reserve(subdivisionsCount + 1); - - double angleIncr = delta/static_cast(subdivisionsCount); - - double theta = startAngleRad; - for (int i = 0; i < subdivisionsCount + 1; ++i) - { - double offsetX = radiusS * cos(theta); - double offsetY = radiusS * sin(theta); - double pointX = centerS.GetX() + offsetX; - double pointY = centerS.GetY() + offsetY; - chain.push_back(ScenePoint2D(pointX, pointY)); - theta += angleIncr; - } - } - -#if 0 - void AddArc( - PolylineSceneLayer::Chain& chain - , const Scene2D& scene - , const ScenePoint2D& centerS - , const double& radiusS - , const double startAngleRad - , const double endAngleRad - , const bool clockwise - , const int subdivisionsCount) - { - double startAngleRadN = NormalizeAngle(startAngleRad); - double endAngleRadN = NormalizeAngle(endAngleRad); - - double angle1Rad = std::min(startAngleRadN, endAngleRadN); - double angle2Rad = std::max(startAngleRadN, endAngleRadN); - - // now we are sure angle1Rad < angle2Rad - // this means that if we draw from 1 to 2, it will be clockwise ( - // increasing angles). - // let's fix this: - if (!clockwise) - { - angle2Rad -= 2 * g_pi; - // now we are sure angle2Rad < angle1Rad (since they were normalized) - // and, thus, going from 1 to 2 means the angle values will DECREASE, - // which is the definition of anticlockwise - } - - chain.clear(); - chain.reserve(subdivisionsCount + 1); - - double angleIncr = (angle2Rad - angle1Rad) - / static_cast(subdivisionsCount); - - double theta = angle1Rad; - for (int i = 0; i < subdivisionsCount + 1; ++i) - { - double offsetX = radiusS * cos(theta); - double offsetY = radiusS * sin(theta); - double pointX = centerS.GetX() + offsetX; - double pointY = centerS.GetY() + offsetY; - chain.push_back(ScenePoint2D(pointX, pointY)); - theta += angleIncr; - } - } -#endif - - void AddCircle(PolylineSceneLayer::Chain& chain, - const Scene2D& scene, - const ScenePoint2D& centerS, - const double& radiusS, - const int numSubdivisions) - { - //ScenePoint2D centerC = centerS.Apply(scene.GetSceneToCanvasTransform()); - //TODO: take DPI into account - - // TODO: automatically compute the number for segments for smooth - // display based on the radius in pixels. - - chain.clear(); - chain.reserve(numSubdivisions); - - double angleIncr = (2.0 * g_pi) - / static_cast(numSubdivisions); - - double theta = 0; - for (int i = 0; i < numSubdivisions; ++i) - { - double offsetX = radiusS * cos(theta); - double offsetY = radiusS * sin(theta); - double pointX = centerS.GetX() + offsetX; - double pointY = centerS.GetY() + offsetY; - chain.push_back(ScenePoint2D(pointX, pointY)); - theta += angleIncr; - } - } - - double NormalizeAngle(double angle) - { - double retAngle = angle; - while (retAngle < -1.0*g_pi) - retAngle += 2 * g_pi; - while (retAngle >= g_pi) - retAngle -= 2 * g_pi; - return retAngle; - } - - double MeasureAngle(const ScenePoint2D& p1, const ScenePoint2D& c, const ScenePoint2D& p2) - { - double p1cAngle = atan2(p1.GetY() - c.GetY(), p1.GetX() - c.GetX()); - double p2cAngle = atan2(p2.GetY() - c.GetY(), p2.GetX() - c.GetX()); - double delta = p2cAngle - p1cAngle; - return NormalizeAngle(delta); - } - - -#if 0 - void AddEllipse(PolylineSceneLayer::Chain& chain, - const Scene2D& scene, - const ScenePoint2D& centerS, - const double& halfHAxis, - const double& halfVAxis) - { - chain.clear(); - chain.reserve(4); - ScenePoint2D centerC = centerS.Apply(scene.GetSceneToCanvasTransform()); - //TODO: take DPI into account - double handleLX = centerC.GetX() - sideLength / 2; - double handleTY = centerC.GetY() - sideLength / 2; - double handleRX = centerC.GetX() + sideLength / 2; - double handleBY = centerC.GetY() + sideLength / 2; - ScenePoint2D LTC(handleLX, handleTY); - ScenePoint2D RTC(handleRX, handleTY); - ScenePoint2D RBC(handleRX, handleBY); - ScenePoint2D LBC(handleLX, handleBY); - - ScenePoint2D startLT = LTC.Apply(scene.GetCanvasToSceneTransform()); - ScenePoint2D startRT = RTC.Apply(scene.GetCanvasToSceneTransform()); - ScenePoint2D startRB = RBC.Apply(scene.GetCanvasToSceneTransform()); - ScenePoint2D startLB = LBC.Apply(scene.GetCanvasToSceneTransform()); - - chain.push_back(startLT); - chain.push_back(startRT); - chain.push_back(startRB); - chain.push_back(startLB); -} -#endif -} diff -r 75deb0acd632 -r d4d6c5b502b5 Samples/Common/MeasureToolsToolbox.h --- a/Samples/Common/MeasureToolsToolbox.h Fri May 17 18:04:26 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,173 +0,0 @@ -/** - * 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 -#include - -namespace OrthancStone -{ - - /** - This function will create a square around the center point supplied in - scene coordinates, with a side length given in canvas coordinates. The - square sides are parallel to the canvas boundaries. - */ - void AddSquare(PolylineSceneLayer::Chain& chain, - const Scene2D& scene, - const ScenePoint2D& centerS, - const double& sideLength); - - - /** - Creates an arc centered on c that goes - - from a point r1: - - so that r1 belongs to the p1,c line - - so that the distance from c to r1 equals radius - - to a point r2: - - so that r2 belongs to the p2,c line - - so that the distance from c to r2 equals radius - - that follows the shortest among the two possible paths - - Warning: the existing chain content will be wiped out. - */ - void AddShortestArc( - PolylineSceneLayer::Chain& chain - , const Scene2D& scene - , const ScenePoint2D& p1 - , const ScenePoint2D& c - , const ScenePoint2D& p2 - , const double& radiusS - , const int subdivisionsCount = 63); - - /** - Creates an arc (open curve) with "numSubdivisions" (N + 1 points) from - start angle to end angle, by following the shortest arc. - - Warning: the existing chain content will be wiped out. - */ - void AddShortestArc( - PolylineSceneLayer::Chain& chain - , const Scene2D& scene - , const ScenePoint2D& centerS - , const double& radiusS - , const double startAngleRad - , const double endAngleRad - , const int subdivisionsCount = 63); - -#if 0 - /** - Creates an arc centered on c that goes - - from a point r1: - - so that r1 belongs to the p1,c line - - so that the distance from c to r1 equals radius - - to a point r2: - - so that r2 belongs to the p2,c line - - so that the distance from c to r2 equals radius - - if clockwise is true, the arc is drawn from r1 to r2 with increasing - angle values. Otherwise, the angle values decrease. - - Warning: the existing chain content will be wiped out. - */ - - void AddArc( - PolylineSceneLayer::Chain& chain - , const Scene2D& scene - , const ScenePoint2D& p1 - , const ScenePoint2D& c - , const ScenePoint2D& p2 - , const double& radiusS - , const bool clockwise - , const int subdivisionsCount = 63); - - /** - Creates an arc (open curve) with "numSubdivisions" (N + 1 points) from - start angle to end angle with the supplied radius. - - if clockwise is true, the arc is drawn from start to end by increasing the - angle values. - - Otherwise, the angle value decreases from start to end. - - Warning: the existing chain content will be wiped out. - */ - void AddArc( - PolylineSceneLayer::Chain& chain - , const Scene2D& scene - , const ScenePoint2D& centerS - , const double& radiusS - , const double startAngleRad - , const double endAngleRad - , const bool clockwise - , const int subdivisionsCount = 63); -#endif - /** - Creates a circle (closed curve) with "numSubdivisions" - (N points) - - Warning: the existing chain content will be wiped out. - */ - void AddCircle(PolylineSceneLayer::Chain& chain, - const Scene2D& scene, - const ScenePoint2D& centerS, - const double& radiusS, - const int numSubdivisions = 63); - - /** - Adds or subtracts 2*pi as many times as need to shift the specified - angle to a value such as: -pi <= value < pi - */ - double NormalizeAngle(double angle); - - /** - Returns the angle magnitude between the p1,c and p2,c lines. - The returned angle is between 0 and 2*pi - - If the angle is between 0 and pi, this means that the shortest arc - from p1 to p2 is clockwise. - - If the angle is between pi and 2*pi, this means that the shortest arc - from p1 to p2 is COUNTERclockwise. - - */ - double MeasureAngle( - const ScenePoint2D& p1 - , const ScenePoint2D& c - , const ScenePoint2D& p2); - - /** - RadiansToDegrees - */ - double RadiansToDegrees(double angleRad); - - /** - This function will return the coordinates of a point that: - - belongs to the two bisecting lines of the p1 c p2 angle. - - is a distance d from c. - Among the four possible points, the one returned will be the one belonging - to the *smallest* half-plane defined by the [c,p1[ and [c,p2[ half-lines. - */ - void GetPositionOnBisectingLine( - ScenePoint2D& result - , const ScenePoint2D& p1 - , const ScenePoint2D& c - , const ScenePoint2D& p2 - , const double d); -} diff -r 75deb0acd632 -r d4d6c5b502b5 Samples/Common/MeasureTrackers.cpp --- a/Samples/Common/MeasureTrackers.cpp Fri May 17 18:04:26 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/** - * 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 "MeasureTrackers.h" -#include - -using namespace Orthanc; - -namespace OrthancStone -{ - - CreateMeasureTracker::CreateMeasureTracker( - Scene2D& scene, - std::vector& undoStack, - std::vector& measureTools) - : scene_(scene) - , active_(true) - , undoStack_(undoStack) - , measureTools_(measureTools) - , commitResult_(true) - { - } - - void CreateMeasureTracker::Cancel() - { - commitResult_ = false; - active_ = false; - } - - bool CreateMeasureTracker::IsActive() const - { - return active_; - } - - CreateMeasureTracker::~CreateMeasureTracker() - { - // if the tracker completes successfully, we add the command - // to the undo stack - - // otherwise, we simply undo it - if (commitResult_) - undoStack_.push_back(command_); - else - command_->Undo(); - } -} - - diff -r 75deb0acd632 -r d4d6c5b502b5 Samples/Common/MeasureTrackers.h --- a/Samples/Common/MeasureTrackers.h Fri May 17 18:04:26 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -/** - * 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 "IFlexiblePointerTracker.h" -#include "../../Framework/Scene2D/Scene2D.h" -#include "../../Framework/Scene2D/PointerEvent.h" - -#include "MeasureTools.h" -#include "MeasureCommands.h" - -#include - -namespace OrthancStone -{ - class CreateMeasureTracker : public IFlexiblePointerTracker - { - public: - virtual void Cancel() ORTHANC_OVERRIDE; - virtual bool IsActive() const ORTHANC_OVERRIDE; - protected: - CreateMeasureTracker( - Scene2D& scene, - std::vector& undoStack, - std::vector& measureTools); - - ~CreateMeasureTracker(); - - protected: - CreateMeasureCommandPtr command_; - Scene2D& scene_; - bool active_; - private: - std::vector& undoStack_; - std::vector& measureTools_; - bool commitResult_; - }; -} - diff -r 75deb0acd632 -r d4d6c5b502b5 Samples/Sdl/BasicScene.cpp --- a/Samples/Sdl/BasicScene.cpp Fri May 17 18:04:26 2019 +0200 +++ b/Samples/Sdl/BasicScene.cpp Sun May 19 16:31:56 2019 +0200 @@ -28,6 +28,8 @@ #include "../../Framework/Scene2D/RotateSceneTracker.h" #include "../../Framework/Scene2D/Scene2D.h" #include "../../Framework/Scene2D/ZoomSceneTracker.h" +#include "../../Framework/Scene2DViewport/ViewportController.h" + #include "../../Framework/StoneInitialization.h" #include "../../Framework/Messages/MessageBroker.h" @@ -44,11 +46,11 @@ static const unsigned int FONT_SIZE = 32; static const int LAYER_POSITION = 150; +using namespace OrthancStone; -void PrepareScene(OrthancStone::Scene2D& scene) +void PrepareScene(ViewportControllerPtr controller) { - using namespace OrthancStone; - + Scene2D& scene(*controller->GetScene()); // Texture of 2x2 size { Orthanc::Image i(Orthanc::PixelFormat_RGB24, 2, 2, false); @@ -137,12 +139,12 @@ void TakeScreenshot(const std::string& target, - const OrthancStone::Scene2D& scene, + const Scene2D& scene, unsigned int canvasWidth, unsigned int canvasHeight) { // Take a screenshot, then save it as PNG file - OrthancStone::CairoCompositor compositor(scene, canvasWidth, canvasHeight); + CairoCompositor compositor(scene, canvasWidth, canvasHeight); compositor.SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, FONT_SIZE, Orthanc::Encoding_Latin1); compositor.Refresh(); @@ -157,11 +159,12 @@ } -void HandleApplicationEvent(OrthancStone::Scene2D& scene, - const OrthancStone::OpenGLCompositor& compositor, +void HandleApplicationEvent(ViewportControllerPtr controller, + const OpenGLCompositor& compositor, const SDL_Event& event, - std::auto_ptr& activeTracker) + FlexiblePointerTrackerPtr& activeTracker) { + Scene2D& scene(*controller->GetScene()); if (event.type == SDL_MOUSEMOTION) { int scancodeCount = 0; @@ -173,28 +176,29 @@ { // The "left-ctrl" key is down, while no tracker is present - OrthancStone::PointerEvent e; + PointerEvent e; e.AddPosition(compositor.GetPixelCenterCoordinates(event.button.x, event.button.y)); - OrthancStone::ScenePoint2D p = e.GetMainPosition().Apply(scene.GetCanvasToSceneTransform()); + ScenePoint2D p = e.GetMainPosition().Apply(scene.GetCanvasToSceneTransform()); char buf[64]; sprintf(buf, "(%0.02f,%0.02f)", p.GetX(), p.GetY()); if (scene.HasLayer(LAYER_POSITION)) { - OrthancStone::TextSceneLayer& layer = - dynamic_cast(scene.GetLayer(LAYER_POSITION)); + TextSceneLayer& layer = + dynamic_cast(scene.GetLayer(LAYER_POSITION)); layer.SetText(buf); layer.SetPosition(p.GetX(), p.GetY()); } else { - std::auto_ptr layer(new OrthancStone::TextSceneLayer); + std::auto_ptr + layer(new TextSceneLayer); layer->SetColor(0, 255, 0); layer->SetText(buf); layer->SetBorder(20); - layer->SetAnchor(OrthancStone::BitmapAnchor_BottomCenter); + layer->SetAnchor(BitmapAnchor_BottomCenter); layer->SetPosition(p.GetX(), p.GetY()); scene.SetLayer(LAYER_POSITION, layer.release()); } @@ -206,22 +210,24 @@ } else if (event.type == SDL_MOUSEBUTTONDOWN) { - OrthancStone::PointerEvent e; + PointerEvent e; e.AddPosition(compositor.GetPixelCenterCoordinates(event.button.x, event.button.y)); switch (event.button.button) { case SDL_BUTTON_MIDDLE: - activeTracker.reset(new OrthancStone::PanSceneTracker(scene, e)); + activeTracker.reset(new PanSceneTracker( + controller, e)); break; case SDL_BUTTON_RIGHT: - activeTracker.reset(new OrthancStone::ZoomSceneTracker(scene, e, - compositor.GetCanvasHeight())); + activeTracker.reset(new ZoomSceneTracker( + controller, e, compositor.GetCanvasHeight())); break; case SDL_BUTTON_LEFT: - activeTracker.reset(new OrthancStone::RotateSceneTracker(scene, e)); + activeTracker.reset(new RotateSceneTracker( + controller, e)); break; default: @@ -269,20 +275,21 @@ } -void Run(OrthancStone::Scene2D& scene) +void Run(ViewportControllerPtr controller) { - OrthancStone::SdlOpenGLWindow window("Hello", 1024, 768); + SdlOpenGLWindow window("Hello", 1024, 768); - scene.FitContent(window.GetCanvasWidth(), window.GetCanvasHeight()); + controller->GetScene()->FitContent( + window.GetCanvasWidth(), window.GetCanvasHeight()); glEnable(GL_DEBUG_OUTPUT); glDebugMessageCallback(OpenGLMessageCallback, 0); - OrthancStone::OpenGLCompositor compositor(window, scene); + OpenGLCompositor compositor(window, *controller->GetScene()); compositor.SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, FONT_SIZE, Orthanc::Encoding_Latin1); - std::auto_ptr tracker; + FlexiblePointerTrackerPtr tracker; bool stop = false; while (!stop) @@ -300,25 +307,30 @@ } else if (event.type == SDL_MOUSEMOTION) { - if (tracker.get() != NULL) + if (tracker) { - OrthancStone::PointerEvent e; - e.AddPosition(compositor.GetPixelCenterCoordinates(event.button.x, event.button.y)); - tracker->Update(e); + PointerEvent e; + e.AddPosition(compositor.GetPixelCenterCoordinates( + event.button.x, event.button.y)); + tracker->PointerMove(e); } } else if (event.type == SDL_MOUSEBUTTONUP) { - if (tracker.get() != NULL) + if (tracker) { - tracker->Release(); - tracker.reset(NULL); + PointerEvent e; + e.AddPosition(compositor.GetPixelCenterCoordinates( + event.button.x, event.button.y)); + tracker->PointerUp(e); + if(!tracker->IsAlive()) + tracker = NULL; } } else if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) { - tracker.reset(NULL); + tracker = NULL; compositor.UpdateSize(); } else if (event.type == SDL_KEYDOWN && @@ -339,7 +351,7 @@ } } - HandleApplicationEvent(scene, compositor, event, tracker); + HandleApplicationEvent(controller, compositor, event, tracker); } SDL_Delay(1); @@ -356,22 +368,23 @@ **/ int main(int argc, char* argv[]) { - OrthancStone::StoneInitialize(); + StoneInitialize(); Orthanc::Logging::EnableInfoLevel(true); try { - OrthancStone::MessageBroker broker; - OrthancStone::Scene2D scene(broker); - PrepareScene(scene); - Run(scene); + MessageBroker broker; + ViewportControllerPtr controller( + new ViewportController(broker)); + PrepareScene(controller); + Run(controller); } catch (Orthanc::OrthancException& e) { LOG(ERROR) << "EXCEPTION: " << e.What(); } - OrthancStone::StoneFinalize(); + StoneFinalize(); return 0; } diff -r 75deb0acd632 -r d4d6c5b502b5 Samples/Sdl/CMakeLists.txt --- a/Samples/Sdl/CMakeLists.txt Fri May 17 18:04:26 2019 +0200 +++ b/Samples/Sdl/CMakeLists.txt Sun May 19 16:31:56 2019 +0200 @@ -69,44 +69,6 @@ LIST(APPEND TRACKERSAMPLE_SOURCE "../../../SDL-Console/SDL_Console.h") endif() -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/AngleMeasureTool.cpp") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/AngleMeasureTool.h") - -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/CreateAngleMeasureTracker.cpp") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/CreateAngleMeasureTracker.h") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/CreateCircleMeasureTracker.cpp") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/CreateCircleMeasureTracker.h") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/CreateLineMeasureTracker.cpp") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/CreateLineMeasureTracker.h") - -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/CreateMeasureTracker.cpp") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/CreateMeasureTracker.h") - -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/CreateSimpleTrackerAdapter.cpp") - -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/EditAngleMeasureTracker.cpp") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/EditAngleMeasureTracker.h") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/EditCircleMeasureTracker.cpp") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/EditCircleMeasureTracker.h") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/EditLineMeasureTracker.cpp") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/EditLineMeasureTracker.h") - -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/IFlexiblePointerTracker.h") - -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/LineMeasureTool.cpp") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/LineMeasureTool.h") - -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/MeasureCommands.cpp") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/MeasureCommands.h") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/MeasureTools.cpp") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/MeasureTools.h") - -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/MeasureToolsToolbox.cpp") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/MeasureToolsToolbox.h") - -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/MeasureTrackers.cpp") -LIST(APPEND TRACKERSAMPLE_SOURCE "../Common/MeasureTrackers.h") - LIST(APPEND TRACKERSAMPLE_SOURCE "TrackerSample.cpp") LIST(APPEND TRACKERSAMPLE_SOURCE "TrackerSampleApp.cpp") LIST(APPEND TRACKERSAMPLE_SOURCE "TrackerSampleApp.h") diff -r 75deb0acd632 -r d4d6c5b502b5 Samples/Sdl/TrackerSampleApp.cpp --- a/Samples/Sdl/TrackerSampleApp.cpp Fri May 17 18:04:26 2019 +0200 +++ b/Samples/Sdl/TrackerSampleApp.cpp Sun May 19 16:31:56 2019 +0200 @@ -20,21 +20,22 @@ #include "TrackerSampleApp.h" -#include "../Common/CreateLineMeasureTracker.h" -#include "../Common/CreateAngleMeasureTracker.h" - -#include "../../Applications/Sdl/SdlOpenGLWindow.h" +#include +#include -#include "../../Framework/Scene2D/PanSceneTracker.h" -#include "../../Framework/Scene2D/RotateSceneTracker.h" -#include "../../Framework/Scene2D/Scene2D.h" -#include "../../Framework/Scene2D/ZoomSceneTracker.h" -#include "../../Framework/Scene2D/CairoCompositor.h" -#include "../../Framework/Scene2D/ColorTextureSceneLayer.h" -#include "../../Framework/Scene2D/OpenGLCompositor.h" -#include "../../Framework/StoneInitialization.h" +#include +#include +#include +#include +#include +#include +#include - // From Orthanc framework +#include + +#include + +// From Orthanc framework #include #include #include @@ -67,9 +68,9 @@ return descs[i]; } - Scene2D& TrackerSampleApp::GetScene() + Scene2DPtr TrackerSampleApp::GetScene() { - return scene_; + return controller_->GetScene(); } void TrackerSampleApp::SelectNextTool() @@ -94,10 +95,10 @@ auto msgS = msg.str(); TextSceneLayer* layerP = NULL; - if (scene_.HasLayer(FIXED_INFOTEXT_LAYER_ZINDEX)) + if (GetScene()->HasLayer(FIXED_INFOTEXT_LAYER_ZINDEX)) { TextSceneLayer& layer = dynamic_cast( - scene_.GetLayer(FIXED_INFOTEXT_LAYER_ZINDEX)); + GetScene()->GetLayer(FIXED_INFOTEXT_LAYER_ZINDEX)); layerP = &layer; } else @@ -109,29 +110,29 @@ layer->SetBorder(20); layer->SetAnchor(BitmapAnchor_TopLeft); //layer->SetPosition(0,0); - scene_.SetLayer(FIXED_INFOTEXT_LAYER_ZINDEX, layer.release()); + GetScene()->SetLayer(FIXED_INFOTEXT_LAYER_ZINDEX, layer.release()); } // position the fixed info text in the upper right corner layerP->SetText(msgS.c_str()); double cX = compositor_->GetCanvasWidth() * (-0.5); double cY = compositor_->GetCanvasHeight() * (-0.5); - scene_.GetCanvasToSceneTransform().Apply(cX,cY); + GetScene()->GetCanvasToSceneTransform().Apply(cX,cY); layerP->SetPosition(cX, cY); } void TrackerSampleApp::DisplayFloatingCtrlInfoText(const PointerEvent& e) { - ScenePoint2D p = e.GetMainPosition().Apply(scene_.GetCanvasToSceneTransform()); + ScenePoint2D p = e.GetMainPosition().Apply(GetScene()->GetCanvasToSceneTransform()); char buf[128]; sprintf(buf, "S:(%0.02f,%0.02f) C:(%0.02f,%0.02f)", p.GetX(), p.GetY(), e.GetMainPosition().GetX(), e.GetMainPosition().GetY()); - if (scene_.HasLayer(FLOATING_INFOTEXT_LAYER_ZINDEX)) + if (GetScene()->HasLayer(FLOATING_INFOTEXT_LAYER_ZINDEX)) { TextSceneLayer& layer = - dynamic_cast(scene_.GetLayer(FLOATING_INFOTEXT_LAYER_ZINDEX)); + dynamic_cast(GetScene()->GetLayer(FLOATING_INFOTEXT_LAYER_ZINDEX)); layer.SetText(buf); layer.SetPosition(p.GetX(), p.GetY()); } @@ -143,13 +144,13 @@ layer->SetBorder(20); layer->SetAnchor(BitmapAnchor_BottomCenter); layer->SetPosition(p.GetX(), p.GetY()); - scene_.SetLayer(FLOATING_INFOTEXT_LAYER_ZINDEX, layer.release()); + GetScene()->SetLayer(FLOATING_INFOTEXT_LAYER_ZINDEX, layer.release()); } } void TrackerSampleApp::HideInfoText() { - scene_.DeleteLayer(FLOATING_INFOTEXT_LAYER_ZINDEX); + GetScene()->DeleteLayer(FLOATING_INFOTEXT_LAYER_ZINDEX); } void TrackerSampleApp::HandleApplicationEvent( @@ -191,7 +192,7 @@ // e.GetMainPosition().GetX() << " " << e.GetMainPosition().GetY(); activeTracker_->PointerMove(e); - if (!activeTracker_->IsActive()) + if (!activeTracker_->IsAlive()) activeTracker_ = NULL; } } @@ -203,7 +204,7 @@ PointerEvent e; e.AddPosition(compositor_->GetPixelCenterCoordinates(event.button.x, event.button.y)); activeTracker_->PointerUp(e); - if (!activeTracker_->IsActive()) + if (!activeTracker_->IsAlive()) activeTracker_ = NULL; } } @@ -215,7 +216,7 @@ if (activeTracker_) { activeTracker_->PointerDown(e); - if (!activeTracker_->IsActive()) + if (!activeTracker_->IsAlive()) activeTracker_ = NULL; } else @@ -233,7 +234,7 @@ if (activeTracker_) { activeTracker_->Cancel(); - if (!activeTracker_->IsActive()) + if (!activeTracker_->IsAlive()) activeTracker_ = NULL; } break; @@ -249,7 +250,7 @@ break; case SDLK_s: - scene_.FitContent(compositor_->GetCanvasWidth(), + GetScene()->FitContent(compositor_->GetCanvasWidth(), compositor_->GetCanvasHeight()); break; @@ -267,7 +268,8 @@ } - void TrackerSampleApp::OnSceneTransformChanged(const Scene2D::SceneTransformChanged& message) + void TrackerSampleApp::OnSceneTransformChanged( + const ViewportController::SceneTransformChanged& message) { DisplayInfoText(); } @@ -279,12 +281,12 @@ switch (event.button.button) { case SDL_BUTTON_MIDDLE: - return CreateSimpleTrackerAdapter(PointerTrackerPtr( - new PanSceneTracker(scene_, e))); + return FlexiblePointerTrackerPtr(new PanSceneTracker + (controller_, e)); case SDL_BUTTON_RIGHT: - return CreateSimpleTrackerAdapter(PointerTrackerPtr( - new ZoomSceneTracker(scene_, e, compositor_->GetCanvasHeight()))); + return FlexiblePointerTrackerPtr(new ZoomSceneTracker + (controller_, e, compositor_->GetCanvasHeight())); case SDL_BUTTON_LEFT: { @@ -309,26 +311,26 @@ { case GuiTool_Rotate: //LOG(TRACE) << "Creating RotateSceneTracker"; - return CreateSimpleTrackerAdapter(PointerTrackerPtr( - new RotateSceneTracker(scene_, e))); + return FlexiblePointerTrackerPtr(new RotateSceneTracker( + controller_, e)); case GuiTool_Pan: - return CreateSimpleTrackerAdapter(PointerTrackerPtr( - new PanSceneTracker(scene_, e))); + return FlexiblePointerTrackerPtr(new PanSceneTracker( + controller_, e)); case GuiTool_Zoom: - return CreateSimpleTrackerAdapter(PointerTrackerPtr( - new ZoomSceneTracker(scene_, e, compositor_->GetCanvasHeight()))); + return FlexiblePointerTrackerPtr(new ZoomSceneTracker( + controller_, e, compositor_->GetCanvasHeight())); //case GuiTool_AngleMeasure: - // return new AngleMeasureTracker(scene_, measureTools_, undoStack_, e); + // return new AngleMeasureTracker(GetScene(), measureTools_, undoStack_, e); //case GuiTool_CircleMeasure: - // return new CircleMeasureTracker(scene_, measureTools_, undoStack_, e); + // return new CircleMeasureTracker(GetScene(), measureTools_, undoStack_, e); //case GuiTool_EllipseMeasure: - // return new EllipseMeasureTracker(scene_, measureTools_, undoStack_, e); + // return new EllipseMeasureTracker(GetScene(), measureTools_, undoStack_, e); case GuiTool_LineMeasure: return FlexiblePointerTrackerPtr(new CreateLineMeasureTracker( - IObserver::GetBroker(), scene_, undoStack_, measureTools_, e)); + IObserver::GetBroker(), controller_, undoStack_, measureTools_, e)); case GuiTool_AngleMeasure: return FlexiblePointerTrackerPtr(new CreateAngleMeasureTracker( - IObserver::GetBroker(), scene_, undoStack_, measureTools_, e)); + IObserver::GetBroker(), controller_, undoStack_, measureTools_, e)); return NULL; case GuiTool_CircleMeasure: LOG(ERROR) << "Not implemented yet!"; @@ -348,11 +350,12 @@ TrackerSampleApp::TrackerSampleApp(MessageBroker& broker) : IObserver(broker) - , scene_(broker) , currentTool_(GuiTool_Rotate) { - scene_.RegisterObserverCallback( - new Callable + controller_ = ViewportControllerPtr(new ViewportController(broker)); + + controller_->RegisterObserverCallback( + new Callable (*this, &TrackerSampleApp::OnSceneTransformChanged)); TEXTURE_2x2_1_ZINDEX = 1; @@ -362,8 +365,6 @@ LINESET_2_ZINDEX = 5; FLOATING_INFOTEXT_LAYER_ZINDEX = 6; FIXED_INFOTEXT_LAYER_ZINDEX = 7; - - } void TrackerSampleApp::PrepareScene() @@ -390,13 +391,13 @@ p[4] = 0; p[5] = 0; - scene_.SetLayer(TEXTURE_2x2_1_ZINDEX, new ColorTextureSceneLayer(i)); + GetScene()->SetLayer(TEXTURE_2x2_1_ZINDEX, new ColorTextureSceneLayer(i)); std::auto_ptr l(new ColorTextureSceneLayer(i)); l->SetOrigin(-3, 2); l->SetPixelSpacing(1.5, 1); l->SetAngle(20.0 / 180.0 * M_PI); - scene_.SetLayer(TEXTURE_2x2_2_ZINDEX, l.release()); + GetScene()->SetLayer(TEXTURE_2x2_2_ZINDEX, l.release()); } // Texture of 1x1 size @@ -411,7 +412,7 @@ std::auto_ptr l(new ColorTextureSceneLayer(i)); l->SetOrigin(-2, 1); l->SetAngle(20.0 / 180.0 * M_PI); - scene_.SetLayer(TEXTURE_1x1_ZINDEX, l.release()); + GetScene()->SetLayer(TEXTURE_1x1_ZINDEX, l.release()); } // Some lines @@ -443,14 +444,14 @@ layer->AddChain(chain, false); layer->SetColor(0, 255, 255); - scene_.SetLayer(LINESET_1_ZINDEX, layer.release()); + GetScene()->SetLayer(LINESET_1_ZINDEX, layer.release()); } // Some text { std::auto_ptr layer(new TextSceneLayer); layer->SetText("Hello"); - scene_.SetLayer(LINESET_2_ZINDEX, layer.release()); + GetScene()->SetLayer(LINESET_2_ZINDEX, layer.release()); } } @@ -468,7 +469,7 @@ unsigned int canvasWidth, unsigned int canvasHeight) { - CairoCompositor compositor(scene_, canvasWidth, canvasHeight); + CairoCompositor compositor(*GetScene(), canvasWidth, canvasHeight); compositor.SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, FONT_SIZE_0, Orthanc::Encoding_Latin1); compositor.Refresh(); @@ -514,12 +515,12 @@ // that needs to be scaled SdlOpenGLWindow window("Hello", 1024, 1024, false); - GetScene().FitContent(window.GetCanvasWidth(), window.GetCanvasHeight()); + GetScene()->FitContent(window.GetCanvasWidth(), window.GetCanvasHeight()); glEnable(GL_DEBUG_OUTPUT); glDebugMessageCallback(OpenGLMessageCallback, 0); - compositor_.reset(new OpenGLCompositor(window, GetScene())); + compositor_.reset(new OpenGLCompositor(window, *GetScene())); compositor_->SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, FONT_SIZE_0, Orthanc::Encoding_Latin1); @@ -564,6 +565,9 @@ } SDL_Delay(1); } + + // the following is paramount because the compositor holds a reference + // to the scene and we do not want this reference to become dangling compositor_.reset(NULL); } diff -r 75deb0acd632 -r d4d6c5b502b5 Samples/Sdl/TrackerSampleApp.h --- a/Samples/Sdl/TrackerSampleApp.h Fri May 17 18:04:26 2019 +0200 +++ b/Samples/Sdl/TrackerSampleApp.h Sun May 19 16:31:56 2019 +0200 @@ -18,11 +18,15 @@ * along with this program. If not, see . **/ -#include +#include + #include -#include "../Common/IFlexiblePointerTracker.h" -#include "../Common/MeasureTools.h" +#include + +#include +#include +#include #include @@ -32,9 +36,6 @@ namespace OrthancStone { - class TrackerCommand; - typedef boost::shared_ptr TrackerCommandPtr; - enum GuiTool { GuiTool_Rotate = 0, @@ -65,7 +66,7 @@ void SetInfoDisplayMessage(std::string key, std::string value); void DisableTracker(); - Scene2D& GetScene(); + Scene2DPtr GetScene(); void HandleApplicationEvent(const SDL_Event& event); @@ -73,7 +74,8 @@ This method is called when the scene transform changes. It allows to recompute the visual elements whose content depend upon the scene transform */ - void OnSceneTransformChanged(const Scene2D::SceneTransformChanged& message); + void OnSceneTransformChanged( + const ViewportController::SceneTransformChanged& message); private: void SelectNextTool(); @@ -108,7 +110,7 @@ WARNING: the measuring tools do store a reference to the scene, and it paramount that the scene gets destroyed AFTER the measurement tools. */ - Scene2D scene_; + ViewportControllerPtr controller_; std::map infoTextMap_; FlexiblePointerTrackerPtr activeTracker_;