Mercurial > hg > orthanc-stone
changeset 698:8b6adfb62a2f refactor-viewport-controller
Code is broken -- stashing ongoing work in a branch
line wrap: on
line diff
--- a/Framework/Scene2D/Internals/OpenGLLinesProgram.cpp Tue May 14 19:38:51 2019 +0200 +++ b/Framework/Scene2D/Internals/OpenGLLinesProgram.cpp Wed May 15 16:56:17 2019 +0200 @@ -205,40 +205,40 @@ } // First triangle - coords.push_back(x1_); - coords.push_back(y1_); - coords.push_back(1); - coords.push_back(x2_); - coords.push_back(y2_); - coords.push_back(-1); - coords.push_back(x2_); - coords.push_back(y2_); - coords.push_back(1); + coords.push_back(static_cast<float>(x1_)); + coords.push_back(static_cast<float>(y1_)); + coords.push_back(static_cast<float>(1)); + coords.push_back(static_cast<float>(x2_)); + coords.push_back(static_cast<float>(y2_)); + coords.push_back(static_cast<float>(-1)); + coords.push_back(static_cast<float>(x2_)); + coords.push_back(static_cast<float>(y2_)); + coords.push_back(static_cast<float>(1)); - miterDirections.push_back(miterX1_); - miterDirections.push_back(miterY1_); - miterDirections.push_back(miterX2_); - miterDirections.push_back(miterY2_); - miterDirections.push_back(miterX2_); - miterDirections.push_back(miterY2_); + miterDirections.push_back(static_cast<float>(miterX1_)); + miterDirections.push_back(static_cast<float>(miterY1_)); + miterDirections.push_back(static_cast<float>(miterX2_)); + miterDirections.push_back(static_cast<float>(miterY2_)); + miterDirections.push_back(static_cast<float>(miterX2_)); + miterDirections.push_back(static_cast<float>(miterY2_)); // Second triangle - coords.push_back(x1_); - coords.push_back(y1_); - coords.push_back(1); - coords.push_back(x1_); - coords.push_back(y1_); - coords.push_back(-1); - coords.push_back(x2_); - coords.push_back(y2_); - coords.push_back(-1); + coords.push_back(static_cast<float>(x1_)); + coords.push_back(static_cast<float>(y1_)); + coords.push_back(static_cast<float>(1)); + coords.push_back(static_cast<float>(x1_)); + coords.push_back(static_cast<float>(y1_)); + coords.push_back(static_cast<float>(-1)); + coords.push_back(static_cast<float>(x2_)); + coords.push_back(static_cast<float>(y2_)); + coords.push_back(static_cast<float>(-1)); - miterDirections.push_back(miterX1_); - miterDirections.push_back(miterY1_); - miterDirections.push_back(miterX1_); - miterDirections.push_back(miterY1_); - miterDirections.push_back(miterX2_); - miterDirections.push_back(miterY2_); + miterDirections.push_back(static_cast<float>(miterX1_)); + miterDirections.push_back(static_cast<float>(miterY1_)); + miterDirections.push_back(static_cast<float>(miterX1_)); + miterDirections.push_back(static_cast<float>(miterY1_)); + miterDirections.push_back(static_cast<float>(miterX2_)); + miterDirections.push_back(static_cast<float>(miterY2_)); } }; @@ -247,7 +247,7 @@ const PolylineSceneLayer& layer) : context_(context), verticesCount_(0), - thickness_(layer.GetThickness()), + thickness_(static_cast<float>(layer.GetThickness())), red_(layer.GetRedAsFloat()), green_(layer.GetGreenAsFloat()), blue_(layer.GetBlueAsFloat()) @@ -418,12 +418,15 @@ double t1 = std::max(thickness, aliasingBorder); double t0 = std::max(0.0, thickness - aliasingBorder); - glUniform1f(program_->GetUniformLocation("u_thickness"), t1 / zoom); - glUniform1f(program_->GetUniformLocation("u_antialiasing_start"), t0 / t1); + glUniform1f(program_->GetUniformLocation("u_thickness"), + static_cast<GLfloat>(t1 / zoom)); + glUniform1f(program_->GetUniformLocation("u_antialiasing_start"), + static_cast<GLfloat>(t0 / t1)); } else { - glUniform1f(program_->GetUniformLocation("u_thickness"), thickness / zoom); + glUniform1f(program_->GetUniformLocation("u_thickness"), + static_cast<GLfloat>(thickness / zoom)); } } else @@ -433,12 +436,15 @@ double t1 = std::max(thickness, aliasingBorder / zoom); double t0 = std::max(0.0, thickness - aliasingBorder / zoom); - glUniform1f(program_->GetUniformLocation("u_thickness"), t1); - glUniform1f(program_->GetUniformLocation("u_antialiasing_start"), t0 / t1); + glUniform1f(program_->GetUniformLocation("u_thickness"), + static_cast<GLfloat>(t1)); + glUniform1f(program_->GetUniformLocation("u_antialiasing_start"), + static_cast<GLfloat>(t0 / t1)); } else { - glUniform1f(program_->GetUniformLocation("u_thickness"), thickness); + glUniform1f(program_->GetUniformLocation("u_thickness"), + static_cast<GLfloat>(thickness)); } } @@ -446,12 +452,14 @@ { glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - glDrawArrays(GL_TRIANGLES, 0, data.GetVerticesCount()); + glDrawArrays(GL_TRIANGLES, 0, + static_cast<GLsizei>(data.GetVerticesCount())); glDisable(GL_BLEND); } else { - glDrawArrays(GL_TRIANGLES, 0, data.GetVerticesCount()); + glDrawArrays(GL_TRIANGLES, 0, + static_cast<GLsizei>(data.GetVerticesCount())); } glDisableVertexAttribArray(locationPosition);
--- a/Framework/Scene2D/Internals/OpenGLTextProgram.cpp Tue May 14 19:38:51 2019 +0200 +++ b/Framework/Scene2D/Internals/OpenGLTextProgram.cpp Wed May 15 16:56:17 2019 +0200 @@ -155,8 +155,8 @@ program_->Use(); double dx, dy; // In pixels - ComputeAnchorTranslation(dx, dy, data.GetAnchor(), - data.GetTextWidth(), data.GetTextHeight(), data.GetBorder()); + ComputeAnchorTranslation(dx, dy, data.GetAnchor(), data.GetTextWidth(), + data.GetTextHeight(), static_cast<unsigned int>(data.GetBorder())); double x = data.GetX(); double y = data.GetY(); @@ -182,7 +182,8 @@ glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - glDrawArrays(GL_TRIANGLES, 0, data.GetCoordinatesCount() / COMPONENTS); + glDrawArrays(GL_TRIANGLES, 0, + static_cast<GLsizei>(data.GetCoordinatesCount() / COMPONENTS)); glDisable(GL_BLEND); glDisableVertexAttribArray(positionLocation_);
--- a/Framework/Scene2D/Scene2D.h Tue May 14 19:38:51 2019 +0200 +++ b/Framework/Scene2D/Scene2D.h Wed May 15 16:56:17 2019 +0200 @@ -119,3 +119,4 @@ unsigned int canvasHeight); }; } +
--- a/Framework/Scene2D/ScenePoint2D.h Tue May 14 19:38:51 2019 +0200 +++ b/Framework/Scene2D/ScenePoint2D.h Wed May 15 16:56:17 2019 +0200 @@ -23,7 +23,6 @@ #include "../Toolbox/AffineTransform2D.h" - namespace OrthancStone { class ScenePoint2D
--- a/Framework/Scene2D/ZoomSceneTracker.h Tue May 14 19:38:51 2019 +0200 +++ b/Framework/Scene2D/ZoomSceneTracker.h Wed May 15 16:56:17 2019 +0200 @@ -21,11 +21,14 @@ #pragma once + #include "IPointerTracker.h" #include "Internals/FixedPointAligner.h" namespace OrthancStone { + class Scene2D; + class ZoomSceneTracker : public IPointerTracker { private:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/AngleMeasureTool.cpp Wed May 15 16:56:17 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 <http://www.gnu.org/licenses/>. + **/ + +#include "AngleMeasureTool.h" +#include "MeasureToolsToolbox.h" + +#include <Core/Logging.h> + +#include <boost/math/constants/constants.hpp> + +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<PolylineSceneLayer*>(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<PolylineSceneLayer> layer(new PolylineSceneLayer()); + GetScene()->SetLayer(polylineZIndex_, layer.release()); + + } + { + textBaseZIndex_ = GetScene()->GetMaxDepth() + 100; + // create the four text background layers + { + std::auto_ptr<TextSceneLayer> layer(new TextSceneLayer()); + GetScene()->SetLayer(textBaseZIndex_, layer.release()); + } + { + std::auto_ptr<TextSceneLayer> layer(new TextSceneLayer()); + GetScene()->SetLayer(textBaseZIndex_+1, layer.release()); + } + { + std::auto_ptr<TextSceneLayer> layer(new TextSceneLayer()); + GetScene()->SetLayer(textBaseZIndex_+2, layer.release()); + } + { + std::auto_ptr<TextSceneLayer> layer(new TextSceneLayer()); + GetScene()->SetLayer(textBaseZIndex_+3, layer.release()); + } + + // and the text layer itself + { + std::auto_ptr<TextSceneLayer> 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<std::string>(center_.GetX())); + + TrackerSample_SetInfoDisplayMessage("center_.GetY()", + boost::lexical_cast<std::string>(center_.GetY())); + + TrackerSample_SetInfoDisplayMessage("side1End_.GetX()", + boost::lexical_cast<std::string>(side1End_.GetX())); + + TrackerSample_SetInfoDisplayMessage("side1End_.GetY()", + boost::lexical_cast<std::string>(side1End_.GetY())); + + TrackerSample_SetInfoDisplayMessage("side2End_.GetX()", + boost::lexical_cast<std::string>(side2End_.GetX())); + + TrackerSample_SetInfoDisplayMessage("side2End_.GetY()", + boost::lexical_cast<std::string>(side2End_.GetY())); + + TrackerSample_SetInfoDisplayMessage("p1cAngle (deg)", + boost::lexical_cast<std::string>(RadiansToDegrees(p1cAngle))); + + TrackerSample_SetInfoDisplayMessage("delta (deg)", + boost::lexical_cast<std::string>(RadiansToDegrees(delta))); + + TrackerSample_SetInfoDisplayMessage("theta (deg)", + boost::lexical_cast<std::string>(RadiansToDegrees(theta))); + + TrackerSample_SetInfoDisplayMessage("p2cAngle (deg)", + boost::lexical_cast<std::string>(RadiansToDegrees(p2cAngle))); + + TrackerSample_SetInfoDisplayMessage("offsetX (pix)", + boost::lexical_cast<std::string>(offsetX)); + + TrackerSample_SetInfoDisplayMessage("offsetY (pix)", + boost::lexical_cast<std::string>(offsetY)); + + TrackerSample_SetInfoDisplayMessage("pointX", + boost::lexical_cast<std::string>(pointX)); + + TrackerSample_SetInfoDisplayMessage("pointY", + boost::lexical_cast<std::string>(pointY)); + + TrackerSample_SetInfoDisplayMessage("angleDeg", + boost::lexical_cast<std::string>(angleDeg)); + } + + + + } + } + else + { + if (layersCreated) + { + RemoveFromScene(); + layersCreated = false; + } + } + } + + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/AngleMeasureTool.h Wed May 15 16:56:17 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 <http://www.gnu.org/licenses/>. + **/ + +#pragma once + +#include "MeasureTools.h" + +#include <Framework/Scene2D/Scene2D.h> +#include <Framework/Scene2D/ScenePoint2D.h> +#include <Framework/Scene2D/PolylineSceneLayer.h> +#include <Framework/Scene2D/TextSceneLayer.h> + +#include <boost/shared_ptr.hpp> +#include <boost/weak_ptr.hpp> + +#include <vector> +#include <cmath> + +namespace OrthancStone +{ + class AngleMeasureTool : public MeasureTool + { + public: + AngleMeasureTool(MessageBroker& broker, Scene2DWPtr sceneW) + : MeasureTool(broker, sceneW) + , 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_; + }; + +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/CreateAngleMeasureTracker.cpp Wed May 15 16:56:17 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 <http://www.gnu.org/licenses/>. + **/ + +#include "CreateAngleMeasureTracker.h" +#include <Core/OrthancException.h> + +using namespace Orthanc; + +namespace OrthancStone +{ + CreateAngleMeasureTracker::CreateAngleMeasureTracker( + MessageBroker& broker, + Scene2DWPtr sceneW, + std::vector<TrackerCommandPtr>& undoStack, + MeasureToolList& measureTools, + const PointerEvent& e) + : CreateMeasureTracker(sceneW, undoStack, measureTools) + , state_(CreatingSide1) + { + Scene2DPtr scene = sceneW.lock(); + command_.reset( + new CreateAngleMeasureCommand( + broker, + sceneW, + measureTools, + e.GetMainPosition().Apply(scene->GetCanvasToSceneTransform()))); + } + + CreateAngleMeasureTracker::~CreateAngleMeasureTracker() + { + } + + void CreateAngleMeasureTracker::PointerMove(const PointerEvent& event) + { + Scene2DPtr scene = scene_.lock(); + 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<CreateAngleMeasureCommand>(command_); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/CreateAngleMeasureTracker.h Wed May 15 16:56:17 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 <http://www.gnu.org/licenses/>. + **/ + +#pragma once + +#include "MeasureTrackers.h" +#include "MeasureCommands.h" + +#include <vector> + +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, + Scene2DWPtr scene, + std::vector<TrackerCommandPtr>& 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_; + + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/CreateCircleMeasureTracker.cpp Wed May 15 16:56:17 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 <http://www.gnu.org/licenses/>. + **/ + +namespace OrthancStone +{ +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/CreateCircleMeasureTracker.h Wed May 15 16:56:17 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 <http://www.gnu.org/licenses/>. + **/ + +#pragma once + +namespace OrthancStone +{ +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/CreateLineMeasureTracker.cpp Wed May 15 16:56:17 2019 +0200 @@ -0,0 +1,95 @@ +/** + * 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 <http://www.gnu.org/licenses/>. + **/ + +#include "CreateLineMeasureTracker.h" +#include <Core/OrthancException.h> + +using namespace Orthanc; + +namespace OrthancStone +{ + CreateLineMeasureTracker::CreateLineMeasureTracker( + MessageBroker& broker, + Scene2DWPtr sceneW, + std::vector<TrackerCommandPtr>& undoStack, + MeasureToolList& measureTools, + const PointerEvent& e) + : CreateMeasureTracker(sceneW, undoStack, measureTools) + { + Scene2DPtr scene = sceneW.lock(); + command_.reset( + new CreateLineMeasureCommand( + broker, + sceneW, + measureTools, + e.GetMainPosition().Apply(scene->GetCanvasToSceneTransform()))); + } + + CreateLineMeasureTracker::~CreateLineMeasureTracker() + { + + } + + void CreateLineMeasureTracker::PointerMove(const PointerEvent& event) + { + Scene2DPtr scene = scene_.lock(); + assert(scene); + + 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<CreateLineMeasureTracker*>(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<CreateLineMeasureCommand>(command_); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/CreateLineMeasureTracker.h Wed May 15 16:56:17 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 <http://www.gnu.org/licenses/>. + **/ + +#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, + Scene2DWPtr scene, + std::vector<TrackerCommandPtr>& 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(); + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/CreateMeasureTracker.cpp Wed May 15 16:56:17 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 <http://www.gnu.org/licenses/>. + **/ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/CreateMeasureTracker.h Wed May 15 16:56:17 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 <http://www.gnu.org/licenses/>. + **/ + +#pragma once +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/CreateSimpleTrackerAdapter.cpp Wed May 15 16:56:17 2019 +0200 @@ -0,0 +1,77 @@ +/** + * 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 <http://www.gnu.org/licenses/>. + **/ + +#include "IFlexiblePointerTracker.h" +#include <Framework/Scene2D/IPointerTracker.h> + + +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)); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/EditAngleMeasureTracker.cpp Wed May 15 16:56:17 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 <http://www.gnu.org/licenses/>. + **/ + +namespace OrthancStone +{ +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/EditAngleMeasureTracker.h Wed May 15 16:56:17 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 <http://www.gnu.org/licenses/>. + **/ + +#pragma once + +namespace OrthancStone +{ +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/EditCircleMeasureTracker.cpp Wed May 15 16:56:17 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 <http://www.gnu.org/licenses/>. + **/ + +namespace OrthancStone +{ +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/EditCircleMeasureTracker.h Wed May 15 16:56:17 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 <http://www.gnu.org/licenses/>. + **/ + +#pragma once + +namespace OrthancStone +{ +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/EditLineMeasureTracker.cpp Wed May 15 16:56:17 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 <http://www.gnu.org/licenses/>. + **/ + +namespace OrthancStone +{ +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/EditLineMeasureTracker.h Wed May 15 16:56:17 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 <http://www.gnu.org/licenses/>. + **/ + +#pragma once + +namespace OrthancStone +{ +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/IFlexiblePointerTracker.h Wed May 15 16:56:17 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 <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "PointerTypes.h" + +#include <Framework/Scene2D/PointerEvent.h> + +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 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; + }; + + + /** + This factory adopts the supplied simple tracker and creates a flexible + tracker wrapper around it. + */ + FlexiblePointerTrackerPtr CreateSimpleTrackerAdapter(PointerTrackerPtr); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/LineMeasureTool.cpp Wed May 15 16:56:17 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 <http://www.gnu.org/licenses/>. + **/ + +#include "LineMeasureTool.h" +#include "MeasureToolsToolbox.h" + +#include <Core/Logging.h> + + +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<PolylineSceneLayer*>(layer); + assert(concreteLayer != NULL); + return concreteLayer; + } + + TextSceneLayer* LineMeasureTool::GetTextLayer() + { + assert(GetScene()->HasLayer(textZIndex_)); + ISceneLayer* layer = &(GetScene()->GetLayer(textZIndex_)); + TextSceneLayer* concreteLayer = dynamic_cast<TextSceneLayer*>(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<PolylineSceneLayer> layer(new PolylineSceneLayer()); + GetScene()->SetLayer(polylineZIndex_, layer.release()); + } + { + textZIndex_ = GetScene()->GetMaxDepth() + 100; + //LOG(INFO) << "set textZIndex_ to: " << textZIndex_; + std::auto_ptr<TextSceneLayer> 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/LineMeasureTool.h Wed May 15 16:56:17 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 <http://www.gnu.org/licenses/>. + **/ + +#pragma once + +#include "MeasureTools.h" + +#include <Framework/Scene2D/Scene2D.h> +#include <Framework/Scene2D/ScenePoint2D.h> +#include <Framework/Scene2D/PolylineSceneLayer.h> +#include <Framework/Scene2D/TextSceneLayer.h> + +#include <boost/shared_ptr.hpp> +#include <boost/weak_ptr.hpp> + +#include <vector> +#include <cmath> + +namespace OrthancStone +{ + class LineMeasureTool : public MeasureTool + { + public: + LineMeasureTool(MessageBroker& broker, Scene2DWPtr sceneW) + : MeasureTool(broker, sceneW) + , 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_; + }; + +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/MeasureCommands.cpp Wed May 15 16:56:17 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 <http://www.gnu.org/licenses/>. + **/ + +#include "MeasureCommands.h" + +namespace OrthancStone +{ + void CreateMeasureCommand::Undo() + { + // simply disable the measure tool upon undo + GetMeasureTool()->Disable(); + } + + void CreateMeasureCommand::Redo() + { + GetMeasureTool()->Enable(); + } + + CreateMeasureCommand::CreateMeasureCommand( + Scene2DWPtr sceneW, MeasureToolList& measureTools) + : TrackerCommand(sceneW) + , measureTools_(measureTools) + { + + } + + CreateMeasureCommand::~CreateMeasureCommand() + { + // deleting the command should not change the model state + // we thus leave it as is + } + + CreateLineMeasureCommand::CreateLineMeasureCommand( + MessageBroker& broker, + Scene2DWPtr sceneW, + MeasureToolList& measureTools, + ScenePoint2D point) + : CreateMeasureCommand(sceneW, measureTools) + , measureTool_(new LineMeasureTool(broker,sceneW)) + { + measureTools_.push_back(measureTool_); + measureTool_->Set(point, point); + } + + void CreateLineMeasureCommand::SetEnd(ScenePoint2D scenePos) + { + measureTool_->SetEnd(scenePos); + } + + CreateAngleMeasureCommand::CreateAngleMeasureCommand( + MessageBroker& broker, + Scene2DWPtr sceneW, + MeasureToolList& measureTools, + ScenePoint2D point) + : CreateMeasureCommand(sceneW, measureTools) + , measureTool_(new AngleMeasureTool(broker,sceneW)) + { + 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); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/MeasureCommands.h Wed May 15 16:56:17 2019 +0200 @@ -0,0 +1,113 @@ +/** + * 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 <http://www.gnu.org/licenses/>. + **/ +#pragma once + +#include <Framework/Scene2D/Scene2D.h> +#include <boost/shared_ptr.hpp> +#include <boost/noncopyable.hpp> + +// 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(Scene2DWPtr sceneW) : scene_(sceneW) + { + + } + virtual void Undo() = 0; + virtual void Redo() = 0; + Scene2DPtr GetScene() + { + return scene_.lock(); + } + + protected: + Scene2DWPtr scene_; + }; + + class CreateMeasureCommand : public TrackerCommand + { + public: + CreateMeasureCommand(Scene2DWPtr sceneW, 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, + Scene2DWPtr 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_; + }; + + + class CreateAngleMeasureCommand : public CreateMeasureCommand + { + public: + /** Ctor sets end of side 1*/ + CreateAngleMeasureCommand( + MessageBroker& broker, + Scene2DWPtr 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_; + }; + +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/MeasureTools.cpp Wed May 15 16:56:17 2019 +0200 @@ -0,0 +1,82 @@ +/** + * 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 <http://www.gnu.org/licenses/>. + **/ + +#include "MeasureTools.h" + +#include <Core/Logging.h> +#include <Core/Enumerations.h> +#include <Core> + +#include <boost/math/constants/constants.hpp> + +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_; + } + + OrthancStone::Scene2DPtr MeasureTool::GetScene() + { + Scene2DPtr scene = scene_.lock(); + if (!scene) + throw OrthancException(ErrorCode_InternalError, "Using dead object!"); + return scene; + } + + MeasureTool::MeasureTool(MessageBroker& broker, Scene2DWPtr sceneW) + : IObserver(broker) + , scene_(sceneW) + , enabled_(true) + { + GetScene()->RegisterObserverCallback( + new Callable<MeasureTool, Scene2D::SceneTransformChanged> + (*this, &MeasureTool::OnSceneTransformChanged)); + } + + void MeasureTool::OnSceneTransformChanged( + const Scene2D::SceneTransformChanged& message) + { + RefreshScene(); + } + + +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/MeasureTools.h Wed May 15 16:56:17 2019 +0200 @@ -0,0 +1,88 @@ +/** + * 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 <http://www.gnu.org/licenses/>. + **/ + +#pragma once + +#include <Framework/Scene2DViewport/PointerTypes.h> + +#include <Framework/Scene2D/Scene2D.h> +#include <Framework/Scene2D/ScenePoint2D.h> +#include <Framework/Scene2D/PolylineSceneLayer.h> +#include <Framework/Scene2D/TextSceneLayer.h> + +#include <boost/shared_ptr.hpp> +#include <boost/weak_ptr.hpp> + +#include <vector> +#include <cmath> + +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, Scene2DWPtr sceneW); + + /** + 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; + + 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: + Scene2DWPtr scene_; + bool enabled_; + }; +} + + +extern void TrackerSample_SetInfoDisplayMessage( + std::string key, std::string value);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/MeasureToolsToolbox.cpp Wed May 15 16:56:17 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 <http://www.gnu.org/licenses/>. + **/ + +#include "MeasureToolsToolbox.h" + +#include <Framework/Scene2D/TextSceneLayer.h> + +#include <boost/math/constants/constants.hpp> + +namespace +{ + double g_pi = boost::math::constants::pi<double>(); +} + +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<double>(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<double>(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<double>(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<TextSceneLayer*>(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); + } + } + + + + + + + + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/MeasureToolsToolbox.h Wed May 15 16:56:17 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 <http://www.gnu.org/licenses/>. + **/ + +#include <Framework/Scene2D/PolylineSceneLayer.h> +#include <Framework/Scene2D/Scene2D.h> + +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); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/MeasureTrackers.cpp Wed May 15 16:56:17 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 <http://www.gnu.org/licenses/>. + **/ + +#include "MeasureTrackers.h" +#include <Core/OrthancException.h> + +using namespace Orthanc; + +namespace OrthancStone +{ + + CreateMeasureTracker::CreateMeasureTracker( + Scene2DWPtr sceneW, + std::vector<TrackerCommandPtr>& undoStack, + std::vector<MeasureToolPtr>& measureTools) + : scene_(sceneW) + , 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(); + } +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/MeasureTrackers.h Wed May 15 16:56:17 2019 +0200 @@ -0,0 +1,57 @@ +/** + * 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 <http://www.gnu.org/licenses/>. + **/ + +#pragma once + +#include "IFlexiblePointerTracker.h" +#include "../../Framework/Scene2D/Scene2D.h" +#include "../../Framework/Scene2D/PointerEvent.h" + +#include "MeasureTools.h" +#include "MeasureCommands.h" + +#include <vector> + +namespace OrthancStone +{ + class CreateMeasureTracker : public IFlexiblePointerTracker + { + public: + virtual void Cancel() ORTHANC_OVERRIDE; + virtual bool IsActive() const ORTHANC_OVERRIDE; + protected: + CreateMeasureTracker( + Scene2DWPtr scene, + std::vector<TrackerCommandPtr>& undoStack, + std::vector<MeasureToolPtr>& measureTools); + + ~CreateMeasureTracker(); + + protected: + CreateMeasureCommandPtr command_; + Scene2DWPtr scene_; + bool active_; + private: + std::vector<TrackerCommandPtr>& undoStack_; + std::vector<MeasureToolPtr>& measureTools_; + bool commitResult_; + }; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/PointerTypes.h Wed May 15 16:56:17 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 <http://www.gnu.org/licenses/>. + **/ + +#pragma once + +#include <boost/shared_ptr.hpp> +#include <boost/weak_ptr.hpp> + +#include <vector> + +namespace OrthancStone +{ + class Scene2D; + typedef boost::shared_ptr<Scene2D> Scene2DPtr; + + typedef boost::weak_ptr<Scene2D> Scene2DWPtr; + + class MeasureTool; + typedef boost::shared_ptr<MeasureTool> + MeasureToolPtr; + typedef boost::weak_ptr<MeasureTool> + MeasureToolWPtr; + typedef std::vector<MeasureToolPtr> + MeasureToolList; + + class LineMeasureTool; + typedef boost::shared_ptr<LineMeasureTool> + LineMeasureToolPtr; + + class AngleMeasureTool; + typedef boost::shared_ptr<AngleMeasureTool> + AngleMeasureToolPtr; + + class IPointerTracker; + typedef boost::shared_ptr<IPointerTracker> + PointerTrackerPtr; + + class IFlexiblePointerTracker; + typedef boost::shared_ptr<IFlexiblePointerTracker> + FlexiblePointerTrackerPtr; + + typedef boost::shared_ptr<LineMeasureTool> + LineMeasureToolPtr; + + class CreateMeasureCommand; + typedef boost::shared_ptr<CreateMeasureCommand> + CreateMeasureCommandPtr; + + class CreateLineMeasureCommand; + typedef boost::shared_ptr<CreateLineMeasureCommand> + CreateLineMeasureCommandPtr; + + class CreateAngleMeasureCommand; + typedef boost::shared_ptr<CreateAngleMeasureCommand> + CreateAngleMeasureCommandPtr; + + + typedef boost::shared_ptr<Scene2D> Scene2DPtr; + + class TrackerCommand; + typedef boost::shared_ptr<TrackerCommand> TrackerCommandPtr; + + class ViewportController; + typedef boost::shared_ptr<ViewportController> ViewportControllerPtr; + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/ViewportController.cpp Wed May 15 16:56:17 2019 +0200 @@ -0,0 +1,49 @@ +/** + * 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 <http://www.gnu.org/licenses/>. + **/ + +#include "ViewportController.h" + +#include <Framework/StoneException.h> + +using namespace Orthanc; + +namespace OrthancStone +{ + + ViewportController::ViewportController(MessageBroker& broker) + : broker_(broker) + { + + } + + Scene2DPtr ViewportController::GetScene() + { + Scene2DPtr scene = scene_.lock(); + if (!scene) + throw OrthancException(ErrorCode_InternalError, "Using dead object!"); + return scene; + } + + bool ViewportController::HandlePointerEvent(PointerEvent e) + { + throw StoneException(ErrorCode_NotImplemented); + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Scene2DViewport/ViewportController.h Wed May 15 16:56:17 2019 +0200 @@ -0,0 +1,75 @@ +/** + * 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 <http://www.gnu.org/licenses/>. + **/ + +#pragma once + +#include "PointerTypes.h" + +#include <Framework/Scene2D/Scene2D.h> +#include <Framework/Scene2D/PointerEvent.h> +#include <Framework/Scene2DViewport/MeasureTools.h> +#include <Framework/Scene2DViewport/IFlexiblePointerTracker.h> + +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 boost::noncopyable + { + public: + 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<MeasureToolPtr> 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); + + private: + MessageBroker& broker_; + Scene2DWPtr scene_; + FlexiblePointerTrackerPtr tracker_; + }; +}
--- a/README.md Tue May 14 19:38:51 2019 +0200 +++ b/README.md Wed May 15 16:56:17 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 -
--- a/Resources/CMake/OrthancStoneConfiguration.cmake Tue May 14 19:38:51 2019 +0200 +++ b/Resources/CMake/OrthancStoneConfiguration.cmake Wed May 15 16:56:17 2019 +0200 @@ -323,6 +323,38 @@ ${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/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
--- a/Samples/Common/AngleMeasureTool.cpp Tue May 14 19:38:51 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 <http://www.gnu.org/licenses/>. - **/ - -#include "AngleMeasureTool.h" -#include "MeasureToolsToolbox.h" - -#include <Core/Logging.h> - -#include <boost/math/constants/constants.hpp> - -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<PolylineSceneLayer*>(layer); - assert(concreteLayer != NULL); - return concreteLayer; - } - - TextSceneLayer* AngleMeasureTool::GetTextLayer() - { - assert(GetScene().HasLayer(textZIndex_)); - ISceneLayer* layer = &(GetScene().GetLayer(textZIndex_)); - TextSceneLayer* concreteLayer = dynamic_cast<TextSceneLayer*>(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<PolylineSceneLayer> layer(new PolylineSceneLayer()); - GetScene().SetLayer(polylineZIndex_, layer.release()); - } - { - textZIndex_ = GetScene().GetMaxDepth() + 100; - //LOG(INFO) << "set textZIndex_ to: " << textZIndex_; - std::auto_ptr<TextSceneLayer> 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<std::string>(center_.GetX())); - - TrackerSample_SetInfoDisplayMessage("center_.GetY()", - boost::lexical_cast<std::string>(center_.GetY())); - - TrackerSample_SetInfoDisplayMessage("side1End_.GetX()", - boost::lexical_cast<std::string>(side1End_.GetX())); - - TrackerSample_SetInfoDisplayMessage("side1End_.GetY()", - boost::lexical_cast<std::string>(side1End_.GetY())); - - TrackerSample_SetInfoDisplayMessage("side2End_.GetX()", - boost::lexical_cast<std::string>(side2End_.GetX())); - - TrackerSample_SetInfoDisplayMessage("side2End_.GetY()", - boost::lexical_cast<std::string>(side2End_.GetY())); - - TrackerSample_SetInfoDisplayMessage("p1cAngle (deg)", - boost::lexical_cast<std::string>(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<std::string>(RadiansToDegrees(delta))); - - double theta = p1cAngle + delta/2; - - TrackerSample_SetInfoDisplayMessage("theta (deg)", - boost::lexical_cast<std::string>(RadiansToDegrees(theta))); - - TrackerSample_SetInfoDisplayMessage("p2cAngle (deg)", - boost::lexical_cast<std::string>(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<std::string>(offsetX)); - - double offsetY = TEXT_CENTER_DISTANCE_CANVAS_COORD * sin(theta); - TrackerSample_SetInfoDisplayMessage("offsetY (pix)", - boost::lexical_cast<std::string>(offsetY)); - - double pointX = center_.GetX() + offsetX * pixelToScene; - double pointY = center_.GetY() + offsetY * pixelToScene; - TrackerSample_SetInfoDisplayMessage("pointX", - boost::lexical_cast<std::string>(pointX)); - - TrackerSample_SetInfoDisplayMessage("pointY", - boost::lexical_cast<std::string>(pointY)); - - TextSceneLayer* textLayer = GetTextLayer(); - - char buf[64]; - double angleDeg = RadiansToDegrees(delta); - - TrackerSample_SetInfoDisplayMessage("angleDeg", - boost::lexical_cast<std::string>(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; - } - } - } - - -}
--- a/Samples/Common/AngleMeasureTool.h Tue May 14 19:38:51 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 <http://www.gnu.org/licenses/>. - **/ - -#pragma once - -#include "MeasureTools.h" - -#include <Framework/Scene2D/Scene2D.h> -#include <Framework/Scene2D/ScenePoint2D.h> -#include <Framework/Scene2D/PolylineSceneLayer.h> -#include <Framework/Scene2D/TextSceneLayer.h> - -#include <boost/shared_ptr.hpp> -#include <boost/weak_ptr.hpp> - -#include <vector> -#include <cmath> - -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<AngleMeasureTool> AngleMeasureToolPtr; -} - -
--- a/Samples/Common/CreateAngleMeasureTracker.cpp Tue May 14 19:38:51 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 <http://www.gnu.org/licenses/>. - **/ - -#include "CreateAngleMeasureTracker.h" -#include <Core/OrthancException.h> - -using namespace Orthanc; - -namespace OrthancStone -{ - CreateAngleMeasureTracker::CreateAngleMeasureTracker( - MessageBroker& broker, - Scene2D& scene, - std::vector<TrackerCommandPtr>& undoStack, - std::vector<MeasureToolPtr>& 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<CreateAngleMeasureCommand>(command_); - } - -}
--- a/Samples/Common/CreateAngleMeasureTracker.h Tue May 14 19:38:51 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 <http://www.gnu.org/licenses/>. - **/ - -#pragma once - -#include "MeasureTrackers.h" -#include "MeasureCommands.h" - -#include <vector> - -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<TrackerCommandPtr>& undoStack, - std::vector<MeasureToolPtr>& 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_; - - }; -}
--- a/Samples/Common/CreateCircleMeasureTracker.cpp Tue May 14 19:38:51 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 <http://www.gnu.org/licenses/>. - **/ - -namespace OrthancStone -{ -}
--- a/Samples/Common/CreateCircleMeasureTracker.h Tue May 14 19:38:51 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 <http://www.gnu.org/licenses/>. - **/ - -#pragma once - -namespace OrthancStone -{ -}
--- a/Samples/Common/CreateLineMeasureTracker.cpp Tue May 14 19:38:51 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 <http://www.gnu.org/licenses/>. - **/ - -#include "CreateLineMeasureTracker.h" -#include <Core/OrthancException.h> - -using namespace Orthanc; - -namespace OrthancStone -{ - CreateLineMeasureTracker::CreateLineMeasureTracker( - MessageBroker& broker, - Scene2D& scene, - std::vector<TrackerCommandPtr>& undoStack, - std::vector<MeasureToolPtr>& 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<CreateLineMeasureTracker*>(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<CreateLineMeasureCommand>(command_); - } - -}
--- a/Samples/Common/CreateLineMeasureTracker.h Tue May 14 19:38:51 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 <http://www.gnu.org/licenses/>. - **/ - -#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<TrackerCommandPtr>& undoStack, - std::vector<MeasureToolPtr>& 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(); - }; -}
--- a/Samples/Common/CreateMeasureTracker.cpp Tue May 14 19:38:51 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 <http://www.gnu.org/licenses/>. - **/ -
--- a/Samples/Common/CreateMeasureTracker.h Tue May 14 19:38:51 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 <http://www.gnu.org/licenses/>. - **/ - -#pragma once -
--- a/Samples/Common/CreateSimpleTrackerAdapter.cpp Tue May 14 19:38:51 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 <http://www.gnu.org/licenses/>. - **/ - -#include "IFlexiblePointerTracker.h" -#include <Framework/Scene2D/IPointerTracker.h> - - -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)); - } -}
--- a/Samples/Common/EditAngleMeasureTracker.cpp Tue May 14 19:38:51 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 <http://www.gnu.org/licenses/>. - **/ - -namespace OrthancStone -{ -}
--- a/Samples/Common/EditAngleMeasureTracker.h Tue May 14 19:38:51 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 <http://www.gnu.org/licenses/>. - **/ - -#pragma once - -namespace OrthancStone -{ -}
--- a/Samples/Common/EditCircleMeasureTracker.cpp Tue May 14 19:38:51 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 <http://www.gnu.org/licenses/>. - **/ - -namespace OrthancStone -{ -}
--- a/Samples/Common/EditCircleMeasureTracker.h Tue May 14 19:38:51 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 <http://www.gnu.org/licenses/>. - **/ - -#pragma once - -namespace OrthancStone -{ -}
--- a/Samples/Common/EditLineMeasureTracker.cpp Tue May 14 19:38:51 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 <http://www.gnu.org/licenses/>. - **/ - -namespace OrthancStone -{ -}
--- a/Samples/Common/EditLineMeasureTracker.h Tue May 14 19:38:51 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 <http://www.gnu.org/licenses/>. - **/ - -#pragma once - -namespace OrthancStone -{ -}
--- a/Samples/Common/IFlexiblePointerTracker.h Tue May 14 19:38:51 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 <http://www.gnu.org/licenses/>. - **/ - - -#pragma once - -#include <Framework/Scene2D/PointerEvent.h> -#include <boost/shared_ptr.hpp> - -namespace OrthancStone -{ - class IPointerTracker; - typedef boost::shared_ptr<IPointerTracker> 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<IFlexiblePointerTracker> FlexiblePointerTrackerPtr; - - /** - This factory adopts the supplied simple tracker and creates a flexible - tracker wrapper around it. - */ - FlexiblePointerTrackerPtr CreateSimpleTrackerAdapter(PointerTrackerPtr); -} -
--- a/Samples/Common/LineMeasureTool.cpp Tue May 14 19:38:51 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 <http://www.gnu.org/licenses/>. - **/ - -#include "LineMeasureTool.h" -#include "MeasureToolsToolbox.h" - -#include <Core/Logging.h> - - -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<PolylineSceneLayer*>(layer); - assert(concreteLayer != NULL); - return concreteLayer; - } - - TextSceneLayer* LineMeasureTool::GetTextLayer() - { - assert(GetScene().HasLayer(textZIndex_)); - ISceneLayer* layer = &(GetScene().GetLayer(textZIndex_)); - TextSceneLayer* concreteLayer = dynamic_cast<TextSceneLayer*>(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<PolylineSceneLayer> layer(new PolylineSceneLayer()); - GetScene().SetLayer(polylineZIndex_, layer.release()); - } - { - textZIndex_ = GetScene().GetMaxDepth() + 100; - //LOG(INFO) << "set textZIndex_ to: " << textZIndex_; - std::auto_ptr<TextSceneLayer> 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
--- a/Samples/Common/LineMeasureTool.h Tue May 14 19:38:51 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 <http://www.gnu.org/licenses/>. - **/ - -#pragma once - -#include "MeasureTools.h" - -#include <Framework/Scene2D/Scene2D.h> -#include <Framework/Scene2D/ScenePoint2D.h> -#include <Framework/Scene2D/PolylineSceneLayer.h> -#include <Framework/Scene2D/TextSceneLayer.h> - -#include <boost/shared_ptr.hpp> -#include <boost/weak_ptr.hpp> - -#include <vector> -#include <cmath> - -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<LineMeasureTool> LineMeasureToolPtr; -} -
--- a/Samples/Common/MeasureCommands.cpp Tue May 14 19:38:51 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 <http://www.gnu.org/licenses/>. - **/ - -#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); - } - -}
--- a/Samples/Common/MeasureCommands.h Tue May 14 19:38:51 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 <http://www.gnu.org/licenses/>. - **/ -#pragma once - -#include <Framework/Scene2D/Scene2D.h> -#include <boost/shared_ptr.hpp> - -// to be moved into Stone -#include "MeasureTools.h" -#include "LineMeasureTool.h" -#include "AngleMeasureTool.h" - -namespace OrthancStone -{ - //class LineMeasureTool; - //typedef boost::shared_ptr<LineMeasureTool> LineMeasureToolPtr; - //class AngleMeasureTool; - //typedef boost::shared_ptr<AngleMeasureTool> 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<TrackerCommand> 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<CreateMeasureCommand> 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<CreateLineMeasureCommand> 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<CreateAngleMeasureCommand> CreateAngleMeasureCommandPtr; -} -
--- a/Samples/Common/MeasureTools.cpp Tue May 14 19:38:51 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 <http://www.gnu.org/licenses/>. - **/ - -#include "MeasureTools.h" - -#include <Core/Logging.h> - -#include <boost/math/constants/constants.hpp> - -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<MeasureTool, Scene2D::SceneTransformChanged> - (*this, &MeasureTool::OnSceneTransformChanged)); - } - - void MeasureTool::OnSceneTransformChanged( - const Scene2D::SceneTransformChanged& message) - { - RefreshScene(); - } - - -} -
--- a/Samples/Common/MeasureTools.h Tue May 14 19:38:51 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 <http://www.gnu.org/licenses/>. - **/ - -#pragma once - -#include <Framework/Scene2D/Scene2D.h> -#include <Framework/Scene2D/ScenePoint2D.h> -#include <Framework/Scene2D/PolylineSceneLayer.h> -#include <Framework/Scene2D/TextSceneLayer.h> - -#include <boost/shared_ptr.hpp> -#include <boost/weak_ptr.hpp> - -#include <vector> -#include <cmath> - -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<MeasureTool> MeasureToolPtr; - typedef std::vector<MeasureToolPtr> MeasureToolList; -} - - -extern void TrackerSample_SetInfoDisplayMessage( - std::string key, std::string value);
--- a/Samples/Common/MeasureToolsToolbox.cpp Tue May 14 19:38:51 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 <http://www.gnu.org/licenses/>. - **/ - -#include "MeasureToolsToolbox.h" - -#include <boost/math/constants/constants.hpp> - -namespace -{ - double g_pi = boost::math::constants::pi<double>(); -} - -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<double>(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<double>(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<double>(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 -}
--- a/Samples/Common/MeasureToolsToolbox.h Tue May 14 19:38:51 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 <http://www.gnu.org/licenses/>. - **/ - -#include <Framework/Scene2D/PolylineSceneLayer.h> -#include <Framework/Scene2D/Scene2D.h> - -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); -}
--- a/Samples/Common/MeasureTrackers.cpp Tue May 14 19:38:51 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 <http://www.gnu.org/licenses/>. - **/ - -#include "MeasureTrackers.h" -#include <Core/OrthancException.h> - -using namespace Orthanc; - -namespace OrthancStone -{ - - CreateMeasureTracker::CreateMeasureTracker( - Scene2D& scene, - std::vector<TrackerCommandPtr>& undoStack, - std::vector<MeasureToolPtr>& 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(); - } -} - -
--- a/Samples/Common/MeasureTrackers.h Tue May 14 19:38:51 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 <http://www.gnu.org/licenses/>. - **/ - -#pragma once - -#include "IFlexiblePointerTracker.h" -#include "../../Framework/Scene2D/Scene2D.h" -#include "../../Framework/Scene2D/PointerEvent.h" - -#include "MeasureTools.h" -#include "MeasureCommands.h" - -#include <vector> - -namespace OrthancStone -{ - class CreateMeasureTracker : public IFlexiblePointerTracker - { - public: - virtual void Cancel() ORTHANC_OVERRIDE; - virtual bool IsActive() const ORTHANC_OVERRIDE; - protected: - CreateMeasureTracker( - Scene2D& scene, - std::vector<TrackerCommandPtr>& undoStack, - std::vector<MeasureToolPtr>& measureTools); - - ~CreateMeasureTracker(); - - protected: - CreateMeasureCommandPtr command_; - Scene2D& scene_; - bool active_; - private: - std::vector<TrackerCommandPtr>& undoStack_; - std::vector<MeasureToolPtr>& measureTools_; - bool commitResult_; - }; -} -
--- a/Samples/Sdl/CMakeLists.txt Tue May 14 19:38:51 2019 +0200 +++ b/Samples/Sdl/CMakeLists.txt Wed May 15 16:56:17 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")
--- a/Samples/Sdl/TrackerSampleApp.cpp Tue May 14 19:38:51 2019 +0200 +++ b/Samples/Sdl/TrackerSampleApp.cpp Wed May 15 16:56:17 2019 +0200 @@ -20,21 +20,22 @@ #include "TrackerSampleApp.h" -#include "../Common/CreateLineMeasureTracker.h" -#include "../Common/CreateAngleMeasureTracker.h" - -#include "../../Applications/Sdl/SdlOpenGLWindow.h" +#include <Framework/Scene2DViewport/CreateLineMeasureTracker.h> +#include <Framework/Scene2DViewport/CreateAngleMeasureTracker.h> -#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 <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> - // From Orthanc framework +#include <Framework/StoneInitialization.h> + +#include <Applications/Sdl/SdlOpenGLWindow.h> + +// From Orthanc framework #include <Core/Logging.h> #include <Core/OrthancException.h> #include <Core/Images/Image.h> @@ -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<TextSceneLayer&>( - 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<TextSceneLayer&>(scene_.GetLayer(FLOATING_INFOTEXT_LAYER_ZINDEX)); + dynamic_cast<TextSceneLayer&>(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( @@ -249,7 +250,7 @@ break; case SDLK_s: - scene_.FitContent(compositor_->GetCanvasWidth(), + GetScene()->FitContent(compositor_->GetCanvasWidth(), compositor_->GetCanvasHeight()); break; @@ -280,11 +281,11 @@ { case SDL_BUTTON_MIDDLE: return CreateSimpleTrackerAdapter(PointerTrackerPtr( - new PanSceneTracker(scene_, e))); + new PanSceneTracker(*GetScene(), e))); case SDL_BUTTON_RIGHT: return CreateSimpleTrackerAdapter(PointerTrackerPtr( - new ZoomSceneTracker(scene_, e, compositor_->GetCanvasHeight()))); + new ZoomSceneTracker(*GetScene(), e, compositor_->GetCanvasHeight()))); case SDL_BUTTON_LEFT: { @@ -310,25 +311,25 @@ case GuiTool_Rotate: //LOG(TRACE) << "Creating RotateSceneTracker"; return CreateSimpleTrackerAdapter(PointerTrackerPtr( - new RotateSceneTracker(scene_, e))); + new RotateSceneTracker(*GetScene(), e))); case GuiTool_Pan: return CreateSimpleTrackerAdapter(PointerTrackerPtr( - new PanSceneTracker(scene_, e))); + new PanSceneTracker(*GetScene(), e))); case GuiTool_Zoom: return CreateSimpleTrackerAdapter(PointerTrackerPtr( - new ZoomSceneTracker(scene_, e, compositor_->GetCanvasHeight()))); + new ZoomSceneTracker(*GetScene(), 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(), GetScene(), undoStack_, measureTools_, e)); case GuiTool_AngleMeasure: return FlexiblePointerTrackerPtr(new CreateAngleMeasureTracker( - IObserver::GetBroker(), scene_, undoStack_, measureTools_, e)); + IObserver::GetBroker(), GetScene(), undoStack_, measureTools_, e)); return NULL; case GuiTool_CircleMeasure: LOG(ERROR) << "Not implemented yet!"; @@ -349,10 +350,11 @@ TrackerSampleApp::TrackerSampleApp(MessageBroker& broker) : IObserver(broker) , currentTool_(GuiTool_Rotate) - , scene_(broker) { - scene_.RegisterObserverCallback( - new Callable<TrackerSampleApp, Scene2D::SceneTransformChanged> + controller_ = ViewportControllerPtr(new ViewportController(broker)); + + controller_->RegisterObserverCallback( + new Callable<TrackerSampleApp, ViewportController::SceneTransformChanged> (*this, &TrackerSampleApp::OnSceneTransformChanged)); TEXTURE_2x2_1_ZINDEX = 1; @@ -362,8 +364,6 @@ LINESET_2_ZINDEX = 5; FLOATING_INFOTEXT_LAYER_ZINDEX = 6; FIXED_INFOTEXT_LAYER_ZINDEX = 7; - - } void TrackerSampleApp::PrepareScene() @@ -390,13 +390,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<ColorTextureSceneLayer> 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 +411,7 @@ std::auto_ptr<ColorTextureSceneLayer> 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 +443,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<TextSceneLayer> layer(new TextSceneLayer); layer->SetText("Hello"); - scene_.SetLayer(LINESET_2_ZINDEX, layer.release()); + GetScene()->SetLayer(LINESET_2_ZINDEX, layer.release()); } } @@ -468,7 +468,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,7 +514,7 @@ // 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);
--- a/Samples/Sdl/TrackerSampleApp.h Tue May 14 19:38:51 2019 +0200 +++ b/Samples/Sdl/TrackerSampleApp.h Wed May 15 16:56:17 2019 +0200 @@ -18,11 +18,15 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. **/ -#include <Framework/Scene2D/OpenGLCompositor.h> +#include <Framework/Scene2DViewport/PointerTypes.h> + #include <Framework/Messages/IObserver.h> -#include "../Common/IFlexiblePointerTracker.h" -#include "../Common/MeasureTools.h" +#include <Framework/Scene2D/OpenGLCompositor.h> + +#include <Framework/Scene2DViewport/ViewportController.h> +#include <Framework/Scene2DViewport/IFlexiblePointerTracker.h> +#include <Framework/Scene2DViewport/MeasureTools.h> #include <SDL.h> @@ -32,9 +36,6 @@ namespace OrthancStone { - class TrackerCommand; - typedef boost::shared_ptr<TrackerCommand> 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); @@ -108,7 +109,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<std::string, std::string> infoTextMap_; FlexiblePointerTrackerPtr activeTracker_;