# HG changeset patch # User Benjamin Golinvaux # Date 1558518952 -7200 # Node ID 712ff6ff3c19ea599b2b02066cd6c4b025acb59e # Parent 284f37dc1c660e9062c93dfef12e47987416e64f - undo redo now works fine for both measure tool creation commands - added LayerHolder to streamline layer index management - added overloads for ORTHANC_ASSERT with no string message (some heavy preprocessor wizardry in there) - fixing wasm BasicScene is *not* finished. diff -r 284f37dc1c66 -r 712ff6ff3c19 .hgignore --- a/.hgignore Tue May 21 13:18:35 2019 +0200 +++ b/.hgignore Wed May 22 11:55:52 2019 +0200 @@ -34,3 +34,5 @@ Samples/Sdl/ThirdPartyDownloads/ Samples/Sdl/CMakeLists.txt.orig +Samples/WebAssembly/build/ +Samples/WebAssembly/ThirdPartyDownloads/ diff -r 284f37dc1c66 -r 712ff6ff3c19 Framework/Scene2DViewport/AngleMeasureTool.cpp --- a/Framework/Scene2DViewport/AngleMeasureTool.cpp Tue May 21 13:18:35 2019 +0200 +++ b/Framework/Scene2DViewport/AngleMeasureTool.cpp Wed May 22 11:55:52 2019 +0200 @@ -20,15 +20,33 @@ #include "AngleMeasureTool.h" #include "MeasureToolsToolbox.h" +#include "LayerHolder.h" #include #include +#include -extern void TrackerSample_SetInfoDisplayMessage(std::string key, std::string value); +// +// REMOVE THIS +#ifndef NDEBUG +extern void +TrackerSample_SetInfoDisplayMessage(std::string key, std::string value); +#endif +// namespace OrthancStone { + // the params in the LayerHolder ctor specify the number of polyline and text + // layers + AngleMeasureTool::AngleMeasureTool( + MessageBroker& broker, ViewportControllerWPtr controllerW) + : MeasureTool(broker, controllerW) + , layerHolder_(boost::make_shared(controllerW,1,5)) + { + + } + AngleMeasureTool::~AngleMeasureTool() { // this measuring tool is a RABI for the corresponding visual layers @@ -39,12 +57,9 @@ void AngleMeasureTool::RemoveFromScene() { - if (layersCreated) + if (layerHolder_->AreLayersCreated() && IsSceneAlive()) { - assert(GetScene()->HasLayer(polylineZIndex_)); - assert(GetScene()->HasLayer(textBaseZIndex_)); - GetScene()->DeleteLayer(polylineZIndex_); - GetScene()->DeleteLayer(textBaseZIndex_); + layerHolder_->DeleteLayers(); } } @@ -66,79 +81,25 @@ 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 (IsSceneAlive()) { - 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()); + layerHolder_->CreateLayersIfNeeded(); - } - { - 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(); + // Fill the polyline layer with the measurement lines + PolylineSceneLayer* polylineLayer = layerHolder_->GetPolylineLayer(0); polylineLayer->ClearAllChains(); polylineLayer->SetColor(0, 183, 17); + // sides { { @@ -155,30 +116,29 @@ } } - // handles + // Create the 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 + //TODO: take DPI into account + AddSquare(chain, GetScene(), side1End_, 10.0 * pixelToScene); polylineLayer->AddChain(chain, true); } - { PolylineSceneLayer::Chain chain; - AddSquare(chain, *GetScene(), side2End_, 10.0 * pixelToScene); //TODO: take DPI into account + //TODO: take DPI into account + AddSquare(chain, GetScene(), side2End_, 10.0 * pixelToScene); polylineLayer->AddChain(chain, true); } } - // arc + // Create the arc { PolylineSceneLayer::Chain chain; const double ARC_RADIUS_CANVAS_COORD = 30.0; - AddShortestArc(chain, *GetScene(), side1End_, center_, side2End_, - ARC_RADIUS_CANVAS_COORD * pixelToScene); + AddShortestArc(chain, side1End_, center_, side2End_, + ARC_RADIUS_CANVAS_COORD * pixelToScene); polylineLayer->AddChain(chain, false); } } @@ -189,21 +149,16 @@ 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; @@ -216,7 +171,7 @@ sprintf(buf, "%0.02f\xc2\xb0", angleDeg); SetTextLayerOutlineProperties( - *GetScene(), textBaseZIndex_, buf, ScenePoint2D(pointX, pointY)); + GetScene(), layerHolder_, buf, ScenePoint2D(pointX, pointY)); // TODO:make it togglable bool enableInfoDisplay = false; @@ -267,18 +222,11 @@ TrackerSample_SetInfoDisplayMessage("angleDeg", boost::lexical_cast(angleDeg)); } - - - } } else { - if (layersCreated) - { - RemoveFromScene(); - layersCreated = false; - } + RemoveFromScene(); } } } diff -r 284f37dc1c66 -r 712ff6ff3c19 Framework/Scene2DViewport/AngleMeasureTool.h --- a/Framework/Scene2DViewport/AngleMeasureTool.h Tue May 21 13:18:35 2019 +0200 +++ b/Framework/Scene2DViewport/AngleMeasureTool.h Wed May 22 11:55:52 2019 +0200 @@ -22,10 +22,12 @@ #include "MeasureTools.h" -#include -#include -#include -#include +#include "../Scene2D/Scene2D.h" +#include "../Scene2D/ScenePoint2D.h" +#include "../Scene2D/PolylineSceneLayer.h" +#include "../Scene2D/TextSceneLayer.h" + +#include "../Scene2DViewport/LayerHolder.h" #include #include @@ -38,14 +40,7 @@ class AngleMeasureTool : public MeasureTool { public: - AngleMeasureTool(MessageBroker& broker, ViewportControllerWPtr controllerW) - : MeasureTool(broker, controllerW) - , layersCreated(false) - , polylineZIndex_(-1) - , textBaseZIndex_(-1) - { - - } + AngleMeasureTool(MessageBroker& broker, ViewportControllerWPtr controllerW); ~AngleMeasureTool(); @@ -54,23 +49,15 @@ 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_; + ScenePoint2D side1End_; + ScenePoint2D side2End_; + ScenePoint2D center_; + LayerHolderPtr layerHolder_; }; - } diff -r 284f37dc1c66 -r 712ff6ff3c19 Framework/Scene2DViewport/LayerHolder.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/LayerHolder.cpp Wed May 22 11:55:52 2019 +0200 @@ -0,0 +1,137 @@ +/** + * 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 "LayerHolder.h" +#include "../Scene2D/TextSceneLayer.h" +#include "../Scene2D/PolylineSceneLayer.h" +#include "../Scene2D/Scene2D.h" +#include "../Scene2DViewport/ViewportController.h" +#include "../StoneException.h" + +using namespace Orthanc; + +namespace OrthancStone +{ + LayerHolder::LayerHolder( + ViewportControllerWPtr controllerW, + int polylineLayerCount, + int textLayerCount) + : textLayerCount_(textLayerCount) + , polylineLayerCount_(polylineLayerCount) + , controllerW_(controllerW) + , baseLayerIndex_(-1) + { + + } + + void LayerHolder::CreateLayers() + { + assert(baseLayerIndex_ == -1); + + baseLayerIndex_ = GetScene()->GetMaxDepth() + 100; + + for (int i = 0; i < polylineLayerCount_; ++i) + { + std::auto_ptr layer(new PolylineSceneLayer()); + GetScene()->SetLayer(baseLayerIndex_ + i, layer.release()); + } + + for (int i = 0; i < textLayerCount_; ++i) + { + std::auto_ptr layer(new TextSceneLayer()); + GetScene()->SetLayer( + baseLayerIndex_ + polylineLayerCount_ + i, + layer.release()); + } + + } + + void LayerHolder::CreateLayersIfNeeded() + { + if (baseLayerIndex_ == -1) + CreateLayers(); + } + + bool LayerHolder::AreLayersCreated() const + { + return (baseLayerIndex_ != -1); + } + + OrthancStone::Scene2DPtr LayerHolder::GetScene() + { + ViewportControllerPtr controller = controllerW_.lock(); + ORTHANC_ASSERT(controller.get() != 0, "Zombie attack!"); + return controller->GetScene(); + } + + void LayerHolder::DeleteLayers() + { + for (int i = 0; i < textLayerCount_ + polylineLayerCount_; ++i) + { + ORTHANC_ASSERT(GetScene()->HasLayer(baseLayerIndex_ + i), "No layer"); + GetScene()->DeleteLayer(baseLayerIndex_ + i); + } + baseLayerIndex_ = -1; + } + + PolylineSceneLayer* LayerHolder::GetPolylineLayer(int index /*= 0*/) + { + ORTHANC_ASSERT(baseLayerIndex_ != -1); + ORTHANC_ASSERT(GetScene()->HasLayer(GetPolylineLayerIndex(index))); + ISceneLayer* layer = + &(GetScene()->GetLayer(GetPolylineLayerIndex(index))); + + PolylineSceneLayer* concreteLayer = + dynamic_cast(layer); + + ORTHANC_ASSERT(concreteLayer != NULL); + return concreteLayer; + } + + TextSceneLayer* LayerHolder::GetTextLayer(int index /*= 0*/) + { + ORTHANC_ASSERT(baseLayerIndex_ != -1); + ORTHANC_ASSERT(GetScene()->HasLayer(GetTextLayerIndex(index))); + ISceneLayer* layer = + &(GetScene()->GetLayer(GetTextLayerIndex(index))); + + TextSceneLayer* concreteLayer = + dynamic_cast(layer); + + ORTHANC_ASSERT(concreteLayer != NULL); + return concreteLayer; + } + + int LayerHolder::GetPolylineLayerIndex(int index /*= 0*/) + { + ORTHANC_ASSERT(index < polylineLayerCount_); + return baseLayerIndex_ + index; + } + + + int LayerHolder::GetTextLayerIndex(int index /*= 0*/) + { + ORTHANC_ASSERT(index < textLayerCount_); + + // the text layers are placed right after the polyline layers + // this means they are drawn ON TOP + return baseLayerIndex_ + polylineLayerCount_ + index; + } +} diff -r 284f37dc1c66 -r 712ff6ff3c19 Framework/Scene2DViewport/LayerHolder.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/LayerHolder.h Wed May 22 11:55:52 2019 +0200 @@ -0,0 +1,99 @@ +/** + * 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 "boost/noncopyable.hpp" + +namespace OrthancStone +{ + class PolylineSceneLayer; + class TextSceneLayer; + + /** + This class holds the indices of a set a layer and supplies + getters to the concrete layer objects. Sounds very ad hoc, and it is. + */ + class LayerHolder : public boost::noncopyable + { + public: + /** + This ctor merely stores the scene and layer counts. No layer creation + performed at this time + */ + LayerHolder( + ViewportControllerWPtr controllerW, + int polylineLayerCount, int textLayerCount); + + /** + This actually creates the layers + */ + void CreateLayers(); + + /** + This creates the layers if they are not created yet. Can be useful in + some scenarios + */ + void CreateLayersIfNeeded(); + + /** + Whether the various text and polylines layers have all been created or + none at all + */ + bool AreLayersCreated() const; + + /** + This removes the layers from the scene + */ + void DeleteLayers(); + + /** + Please note that the returned pointer belongs to the scene.Don't you dare + storing or deleting it, you fool! + + This throws if the index is not valid or if the layers are not created or + have been deleted + */ + PolylineSceneLayer* GetPolylineLayer(int index = 0); + + /** + Please note that the returned pointer belongs to the scene. Don't you dare + storing or deleting it, you fool! + + This throws if the index is not valid or if the layers are not created or + have been deleted + */ + TextSceneLayer* GetTextLayer(int index = 0); + + private: + int GetPolylineLayerIndex(int index = 0); + int GetTextLayerIndex(int index = 0); + Scene2DPtr GetScene(); + + int textLayerCount_; + int polylineLayerCount_; + ViewportControllerWPtr controllerW_; + int baseLayerIndex_; + }; + + typedef boost::shared_ptr LayerHolderPtr; +} + diff -r 284f37dc1c66 -r 712ff6ff3c19 Framework/Scene2DViewport/LineMeasureTool.cpp --- a/Framework/Scene2DViewport/LineMeasureTool.cpp Tue May 21 13:18:35 2019 +0200 +++ b/Framework/Scene2DViewport/LineMeasureTool.cpp Wed May 22 11:55:52 2019 +0200 @@ -20,12 +20,23 @@ #include "LineMeasureTool.h" #include "MeasureToolsToolbox.h" +#include "LayerHolder.h" #include +#include namespace OrthancStone { + + LineMeasureTool::LineMeasureTool( + MessageBroker& broker, ViewportControllerWPtr controllerW) + : MeasureTool(broker, controllerW) + , layerHolder_(boost::make_shared(controllerW, 1, 5)) + { + + } + LineMeasureTool::~LineMeasureTool() { // this measuring tool is a RABI for the corresponding visual layers @@ -36,16 +47,12 @@ void LineMeasureTool::RemoveFromScene() { - if (layersCreated) + if (layerHolder_->AreLayersCreated() && IsSceneAlive()) { - assert(GetScene()->HasLayer(polylineZIndex_)); - assert(GetScene()->HasLayer(textZIndex_)); - GetScene()->DeleteLayer(polylineZIndex_); - GetScene()->DeleteLayer(textZIndex_); + layerHolder_->DeleteLayers(); } } - - + void LineMeasureTool::SetStart(ScenePoint2D start) { start_ = start; @@ -65,58 +72,22 @@ 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 (IsSceneAlive()) { if (IsEnabled()) { - if (!layersCreated) - { - // Create the layers if need be + // get the scaling factor + const double pixelToScene = + GetScene()->GetCanvasToSceneTransform().ComputeZoom(); - 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_)); - } + layerHolder_->CreateLayersIfNeeded(); + { // Fill the polyline layer with the measurement line - PolylineSceneLayer* polylineLayer = GetPolylineLayer(); + PolylineSceneLayer* polylineLayer = layerHolder_->GetPolylineLayer(0); polylineLayer->ClearAllChains(); polylineLayer->SetColor(0, 223, 21); @@ -133,68 +104,46 @@ { PolylineSceneLayer::Chain chain; - AddSquare(chain, *GetScene(), start_, 10.0); //TODO: take DPI into account + + //TODO: take DPI into account + AddSquare(chain, GetScene(), start_, 10.0 * pixelToScene); + polylineLayer->AddChain(chain, true); } { PolylineSceneLayer::Chain chain; - AddSquare(chain, *GetScene(), end_, 10.0); //TODO: take DPI into account + + //TODO: take DPI into account + AddSquare(chain, GetScene(), end_, 10.0 * pixelToScene); + 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); + + SetTextLayerOutlineProperties( + GetScene(), layerHolder_, buf, ScenePoint2D(midX, midY)); } } else { - if (layersCreated) - { - RemoveFromScene(); - layersCreated = false; - } + RemoveFromScene(); } } } diff -r 284f37dc1c66 -r 712ff6ff3c19 Framework/Scene2DViewport/LineMeasureTool.h --- a/Framework/Scene2DViewport/LineMeasureTool.h Tue May 21 13:18:35 2019 +0200 +++ b/Framework/Scene2DViewport/LineMeasureTool.h Wed May 22 11:55:52 2019 +0200 @@ -38,14 +38,7 @@ class LineMeasureTool : public MeasureTool { public: - LineMeasureTool(MessageBroker& broker, ViewportControllerWPtr controllerW) - : MeasureTool(broker, controllerW) - , layersCreated(false) - , polylineZIndex_(-1) - , textZIndex_(-1) - { - - } + LineMeasureTool(MessageBroker& broker, ViewportControllerWPtr controllerW); ~LineMeasureTool(); @@ -54,17 +47,14 @@ 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_; + ScenePoint2D start_; + ScenePoint2D end_; + LayerHolderPtr layerHolder_; + int baseLayerIndex_; }; } diff -r 284f37dc1c66 -r 712ff6ff3c19 Framework/Scene2DViewport/MeasureCommands.cpp --- a/Framework/Scene2DViewport/MeasureCommands.cpp Tue May 21 13:18:35 2019 +0200 +++ b/Framework/Scene2DViewport/MeasureCommands.cpp Wed May 22 11:55:52 2019 +0200 @@ -28,11 +28,13 @@ void CreateMeasureCommand::Undo() { // simply disable the measure tool upon undo + GetMeasureTool()->Disable(); GetController()->RemoveMeasureTool(GetMeasureTool()); } void CreateMeasureCommand::Redo() { + GetMeasureTool()->Enable(); GetController()->AddMeasureTool(GetMeasureTool()); } diff -r 284f37dc1c66 -r 712ff6ff3c19 Framework/Scene2DViewport/MeasureTools.h --- a/Framework/Scene2DViewport/MeasureTools.h Tue May 21 13:18:35 2019 +0200 +++ b/Framework/Scene2DViewport/MeasureTools.h Wed May 22 11:55:52 2019 +0200 @@ -93,6 +93,5 @@ }; } - extern void TrackerSample_SetInfoDisplayMessage( std::string key, std::string value); diff -r 284f37dc1c66 -r 712ff6ff3c19 Framework/Scene2DViewport/MeasureToolsToolbox.cpp --- a/Framework/Scene2DViewport/MeasureToolsToolbox.cpp Tue May 21 13:18:35 2019 +0200 +++ b/Framework/Scene2DViewport/MeasureToolsToolbox.cpp Wed May 22 11:55:52 2019 +0200 @@ -19,8 +19,11 @@ **/ #include "MeasureToolsToolbox.h" +#include "PointerTypes.h" +#include "LayerHolder.h" -#include +#include "../Scene2D/TextSceneLayer.h" +#include "../Scene2D/Scene2D.h" #include @@ -31,6 +34,24 @@ namespace OrthancStone { + 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); + } + double RadiansToDegrees(double angleRad) { static const double factor = 180.0 / g_pi; @@ -38,27 +59,31 @@ } void AddSquare(PolylineSceneLayer::Chain& chain, - const Scene2D& scene, + Scene2DConstPtr scene, const ScenePoint2D& centerS, - const double& sideLength) + const double& sideLengthS) { + // get the scaling factor + const double sceneToCanvas = + scene->GetSceneToCanvasTransform().ComputeZoom(); + chain.clear(); chain.reserve(4); - ScenePoint2D centerC = centerS.Apply(scene.GetSceneToCanvasTransform()); + 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; + double handleLX = centerC.GetX() - sideLengthS * sceneToCanvas * 0.5; + double handleTY = centerC.GetY() - sideLengthS * sceneToCanvas * 0.5; + double handleRX = centerC.GetX() + sideLengthS * sceneToCanvas * 0.5; + double handleBY = centerC.GetY() + sideLengthS * sceneToCanvas * 0.5; 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()); + 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); @@ -86,7 +111,6 @@ void AddShortestArc( PolylineSceneLayer::Chain& chain - , const Scene2D& scene , const ScenePoint2D& p1 , const ScenePoint2D& c , const ScenePoint2D& p2 @@ -96,30 +120,11 @@ 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); + chain, 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 @@ -197,7 +202,6 @@ #endif void AddCircle(PolylineSceneLayer::Chain& chain, - const Scene2D& scene, const ScenePoint2D& centerS, const double& radiusS, const int numSubdivisions) @@ -278,38 +282,25 @@ #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; - } - } - + /** + This utility function assumes that the layer holder contains 5 text layers + and will use the first four ones for the text background and the fifth one + for the actual text + */ void SetTextLayerOutlineProperties( - Scene2D& scene, int baseLayerIndex, const char* text, ScenePoint2D p) + Scene2DPtr scene, LayerHolderPtr layerHolder, + 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(); + scene->GetCanvasToSceneTransform().ComputeZoom(); for (int i = 0; i < 5; ++i) { - TextSceneLayer* textLayer = GetOutlineTextLayer(scene, baseLayerIndex, i); + TextSceneLayer* textLayer = layerHolder->GetTextLayer(i); textLayer->SetText(text); if (i == 4) diff -r 284f37dc1c66 -r 712ff6ff3c19 Framework/Scene2DViewport/MeasureToolsToolbox.h --- a/Framework/Scene2DViewport/MeasureToolsToolbox.h Tue May 21 13:18:35 2019 +0200 +++ b/Framework/Scene2DViewport/MeasureToolsToolbox.h Wed May 22 11:55:52 2019 +0200 @@ -18,8 +18,8 @@ * along with this program. If not, see . **/ -#include -#include +#include "../Scene2D/PolylineSceneLayer.h" +#include "PointerTypes.h" namespace OrthancStone { @@ -30,10 +30,9 @@ square sides are parallel to the canvas boundaries. */ void AddSquare(PolylineSceneLayer::Chain& chain, - const Scene2D& scene, + Scene2DConstPtr scene, const ScenePoint2D& centerS, - const double& sideLength); - + const double& sideLengthS); /** Creates an arc centered on c that goes @@ -49,7 +48,6 @@ */ void AddShortestArc( PolylineSceneLayer::Chain& chain - , const Scene2D& scene , const ScenePoint2D& p1 , const ScenePoint2D& c , const ScenePoint2D& p2 @@ -64,7 +62,6 @@ */ void AddShortestArc( PolylineSceneLayer::Chain& chain - , const Scene2D& scene , const ScenePoint2D& centerS , const double& radiusS , const double startAngleRad @@ -182,6 +179,6 @@ from layerIndex, up to (and not including) layerIndex+5. */ void SetTextLayerOutlineProperties( - Scene2D& scene, int baseLayerIndex, const char* text, ScenePoint2D p); - + Scene2DPtr scene, LayerHolderPtr layerHolder, + const char* text, ScenePoint2D p); } diff -r 284f37dc1c66 -r 712ff6ff3c19 Framework/Scene2DViewport/PointerTypes.h --- a/Framework/Scene2DViewport/PointerTypes.h Tue May 21 13:18:35 2019 +0200 +++ b/Framework/Scene2DViewport/PointerTypes.h Wed May 22 11:55:52 2019 +0200 @@ -29,6 +29,7 @@ { class Scene2D; typedef boost::shared_ptr Scene2DPtr; + typedef boost::shared_ptr Scene2DConstPtr; typedef boost::weak_ptr Scene2DWPtr; @@ -69,13 +70,13 @@ 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; + + class LayerHolder; + typedef boost::shared_ptr LayerHolderPtr; } diff -r 284f37dc1c66 -r 712ff6ff3c19 Framework/Scene2DViewport/ViewportController.cpp --- a/Framework/Scene2DViewport/ViewportController.cpp Tue May 21 13:18:35 2019 +0200 +++ b/Framework/Scene2DViewport/ViewportController.cpp Wed May 22 11:55:52 2019 +0200 @@ -130,8 +130,9 @@ { ORTHANC_ASSERT(std::find(measureTools_.begin(), measureTools_.end(), measureTool) != measureTools_.end(), "Measure tool not found"); - measureTools_.push_back(measureTool); + measureTools_.erase( + std::remove(measureTools_.begin(), measureTools_.end(), measureTool), + measureTools_.end()); } - } diff -r 284f37dc1c66 -r 712ff6ff3c19 Framework/StoneException.h --- a/Framework/StoneException.h Tue May 21 13:18:35 2019 +0200 +++ b/Framework/StoneException.h Wed May 22 11:55:52 2019 +0200 @@ -115,7 +115,7 @@ // See https://isocpp.org/wiki/faq/misc-technical-issues#macros-with-multi-stmts // (or google "Multiple lines macro C++ faq lite" if link is dead) -#define ORTHANC_ASSERT(cond,streamChainMessage) \ +#define ORTHANC_ASSERT2(cond,streamChainMessage) \ if (!(cond)) { \ std::stringstream sst; \ sst << "Assertion failed. Condition = \"" #cond "\" Message = \"" << streamChainMessage << "\""; \ @@ -123,3 +123,38 @@ throw OrthancException(ErrorCode_InternalError,sstr.c_str()); \ } else (void)0 +#define ORTHANC_ASSERT1(cond) \ + if (!(cond)) { \ + std::stringstream sst; \ + sst << "Assertion failed. Condition = \"" #cond "\""; \ + std::string sstr = sst.str(); \ + throw OrthancException(ErrorCode_InternalError,sstr.c_str()); \ + } else (void)0 + + + +# define ORTHANC_EXPAND( x ) x +# define GET_ORTHANC_ASSERT(_1,_2,NAME,...) NAME +# define ORTHANC_ASSERT(...) ORTHANC_EXPAND(GET_ORTHANC_ASSERT(__VA_ARGS__, ORTHANC_ASSERT2, ORTHANC_ASSERT1, UNUSED)(__VA_ARGS__)) + +/* +Explanation: + +ORTHANC_ASSERT(a) +ORTHANC_EXPAND(GET_ORTHANC_ASSERT(a, ORTHANC_ASSERT2, ORTHANC_ASSERT1, UNUSED)(a)) +ORTHANC_EXPAND(ORTHANC_ASSERT1(a)) +ORTHANC_ASSERT1(a) + +ORTHANC_ASSERT(a,b) +ORTHANC_EXPAND(GET_ORTHANC_ASSERT(a, b, ORTHANC_ASSERT2, ORTHANC_ASSERT1, UNUSED)(a,b)) +ORTHANC_EXPAND(ORTHANC_ASSERT2(a,b)) +ORTHANC_ASSERT2(a,b) + +Note: ORTHANC_EXPAND is required for some older compilers (MS v100 cl.exe ) +*/ + + + + + + diff -r 284f37dc1c66 -r 712ff6ff3c19 Resources/CMake/OrthancStoneConfiguration.cmake --- a/Resources/CMake/OrthancStoneConfiguration.cmake Tue May 21 13:18:35 2019 +0200 +++ b/Resources/CMake/OrthancStoneConfiguration.cmake Wed May 22 11:55:52 2019 +0200 @@ -328,7 +328,6 @@ ${ORTHANC_STONE_ROOT}/Framework/Scene2D/TextSceneLayer.cpp ${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 @@ -347,6 +346,8 @@ ${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/LayerHolder.cpp + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/LayerHolder.h ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/LineMeasureTool.cpp ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/LineMeasureTool.h ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/MeasureCommands.cpp