# HG changeset patch # User Sebastien Jodogne # Date 1604071599 -3600 # Node ID ad9b425f27ae824f3d8c4a95a3902200d5664f26 # Parent 5f0660fe06c31429040084bdb58f5672771fde31 new class: ArrowSceneLayer diff -r 5f0660fe06c3 -r ad9b425f27ae Applications/StoneWebViewer/WebApplication/app.js --- a/Applications/StoneWebViewer/WebApplication/app.js Fri Oct 30 11:07:38 2020 +0100 +++ b/Applications/StoneWebViewer/WebApplication/app.js Fri Oct 30 16:26:39 2020 +0100 @@ -751,7 +751,7 @@ window.postMessage({ 'type': 'show-osirix-annotations', 'xml': response.data, - 'clear': true + 'clear': false }, targetOrigin); }); } diff -r 5f0660fe06c3 -r ad9b425f27ae Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp --- a/Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp Fri Oct 30 11:07:38 2020 +0100 +++ b/Applications/StoneWebViewer/WebAssembly/StoneWebViewer.cpp Fri Oct 30 16:26:39 2020 +0100 @@ -70,6 +70,7 @@ #include #include #include +#include #include #include #include @@ -1548,15 +1549,23 @@ if (GetCurrentFrameGeometry().ProjectPoint(x1, y1, line.GetPoint1()) && GetCurrentFrameGeometry().ProjectPoint(x2, y2, line.GetPoint2())) { - std::unique_ptr layer(new OrthancStone::PolylineSceneLayer); - OrthancStone::PolylineSceneLayer::Chain chain; - chain.push_back(OrthancStone::ScenePoint2D(x1, y1)); - chain.push_back(OrthancStone::ScenePoint2D(x2, y2)); - - // TODO - IsArrow - - layer->AddChain(chain, false, 0, 255, 0); - annotationsLayer->AddLayer(layer.release()); + if (line.IsArrow()) + { + std::unique_ptr layer( + new OrthancStone::ArrowSceneLayer(OrthancStone::ScenePoint2D(x1, y1), + OrthancStone::ScenePoint2D(x2, y2))); + layer->SetColor(0, 255, 0); + annotationsLayer->AddLayer(layer.release()); + } + else + { + std::unique_ptr layer(new OrthancStone::PolylineSceneLayer); + OrthancStone::PolylineSceneLayer::Chain chain; + chain.push_back(OrthancStone::ScenePoint2D(x1, y1)); + chain.push_back(OrthancStone::ScenePoint2D(x2, y2)); + layer->AddChain(chain, false, 0, 255, 0); + annotationsLayer->AddLayer(layer.release()); + } } break; } @@ -2303,7 +2312,7 @@ static boost::shared_ptr context_; static std::string stringBuffer_; static bool softwareRendering_ = false; -static WebViewerAction leftButtonAction_ = WebViewerAction_GrayscaleWindowing; +static WebViewerAction leftButtonAction_ = WebViewerAction_Rotate; // WebViewerAction_GrayscaleWindowing; static WebViewerAction middleButtonAction_ = WebViewerAction_Pan; static WebViewerAction rightButtonAction_ = WebViewerAction_Zoom; diff -r 5f0660fe06c3 -r ad9b425f27ae OrthancStone/Resources/CMake/OrthancStoneConfiguration.cmake --- a/OrthancStone/Resources/CMake/OrthancStoneConfiguration.cmake Fri Oct 30 11:07:38 2020 +0100 +++ b/OrthancStone/Resources/CMake/OrthancStoneConfiguration.cmake Fri Oct 30 16:26:39 2020 +0100 @@ -255,6 +255,8 @@ ${ORTHANC_STONE_ROOT}/Oracle/ParseDicomFromFileCommand.cpp ${ORTHANC_STONE_ROOT}/Oracle/ParseDicomFromWadoCommand.cpp + ${ORTHANC_STONE_ROOT}/Scene2D/ArrowSceneLayer.cpp + ${ORTHANC_STONE_ROOT}/Scene2D/ArrowSceneLayer.h ${ORTHANC_STONE_ROOT}/Scene2D/CairoCompositor.cpp ${ORTHANC_STONE_ROOT}/Scene2D/CairoCompositor.h ${ORTHANC_STONE_ROOT}/Scene2D/Color.h @@ -297,6 +299,8 @@ ${ORTHANC_STONE_ROOT}/Scene2D/ZoomSceneTracker.cpp ${ORTHANC_STONE_ROOT}/Scene2D/ZoomSceneTracker.h + ${ORTHANC_STONE_ROOT}/Scene2D/Internals/CairoArrowRenderer.cpp + ${ORTHANC_STONE_ROOT}/Scene2D/Internals/CairoArrowRenderer.h ${ORTHANC_STONE_ROOT}/Scene2D/Internals/CairoBaseRenderer.h ${ORTHANC_STONE_ROOT}/Scene2D/Internals/CairoColorTextureRenderer.cpp ${ORTHANC_STONE_ROOT}/Scene2D/Internals/CairoColorTextureRenderer.h @@ -471,6 +475,8 @@ ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLAdvancedPolylineRenderer.cpp ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLAdvancedPolylineRenderer.h + ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLArrowRenderer.cpp + ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLArrowRenderer.h ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLBasicPolylineRenderer.cpp ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLBasicPolylineRenderer.h ${ORTHANC_STONE_ROOT}/Scene2D/Internals/OpenGLColorTextureProgram.cpp diff -r 5f0660fe06c3 -r ad9b425f27ae OrthancStone/Sources/Scene2D/ArrowSceneLayer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancStone/Sources/Scene2D/ArrowSceneLayer.cpp Fri Oct 30 16:26:39 2020 +0100 @@ -0,0 +1,86 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2020 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, see + * . + **/ + + +#include "ArrowSceneLayer.h" + +#include + +namespace OrthancStone +{ + ArrowSceneLayer::ArrowSceneLayer(const ScenePoint2D& a, + const ScenePoint2D& b) : + a_(a), + b_(b), + thickness_(1.0), + revision_(0), + arrowLength_(10), // 10 pixels + arrowAngle_(boost::math::constants::pi() / 12.0) // 15 degrees + { + } + + + ISceneLayer* ArrowSceneLayer::Clone() const + { + std::unique_ptr copy(new ArrowSceneLayer(a_, b_)); + copy->color_ = color_; + copy->thickness_ = thickness_; + copy->arrowLength_ = arrowLength_; + copy->arrowAngle_ = arrowAngle_; + return copy.release(); + } + + + void ArrowSceneLayer::SetThickness(double thickness) + { + thickness_ = thickness; + revision_ += 1; + } + + + void ArrowSceneLayer::SetColor(const Color& color) + { + color_ = color; + revision_ += 1; + } + + + void ArrowSceneLayer::SetArrowLength(double length) + { + arrowLength_ = length; + revision_ += 1; + } + + + void ArrowSceneLayer::SetArrowAngle(double angle) + { + arrowAngle_ = angle; + revision_ += 1; + } + + + void ArrowSceneLayer::GetBoundingBox(Extent2D& target) const + { + target.Clear(); + target.AddPoint(a_.GetX(), a_.GetY()); + target.AddPoint(b_.GetX(), b_.GetY()); + } +} diff -r 5f0660fe06c3 -r ad9b425f27ae OrthancStone/Sources/Scene2D/ArrowSceneLayer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancStone/Sources/Scene2D/ArrowSceneLayer.h Fri Oct 30 16:26:39 2020 +0100 @@ -0,0 +1,107 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2020 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, see + * . + **/ + + +#pragma once + +#include "Color.h" +#include "ScenePoint2D.h" +#include "ISceneLayer.h" + +#include // For ORTHANC_OVERRIDE + +namespace OrthancStone +{ + class ArrowSceneLayer : public ISceneLayer + { + private: + ScenePoint2D a_; + ScenePoint2D b_; + Color color_; + double thickness_; + uint64_t revision_; + double arrowLength_; // in pixels + double arrowAngle_; // in radians + + public: + ArrowSceneLayer(const ScenePoint2D& a, + const ScenePoint2D& b); + + virtual uint64_t GetRevision() const ORTHANC_OVERRIDE + { + return revision_; + } + + virtual ISceneLayer* Clone() const ORTHANC_OVERRIDE; + + const ScenePoint2D& GetA() const + { + return a_; + } + + const ScenePoint2D& GetB() const + { + return b_; + } + + void SetThickness(double thickness); + + double GetThickness() const + { + return thickness_; + } + + void SetColor(const Color& color); + + void SetColor(uint8_t red, + uint8_t green, + uint8_t blue) + { + SetColor(Color(red, green, blue)); + } + + const Color& GetColor() const + { + return color_; + } + + void SetArrowLength(double length); + + double GetArrowLength() const + { + return arrowLength_; + } + + void SetArrowAngle(double angle); + + double GetArrowAngle() const + { + return arrowAngle_; + } + + virtual Type GetType() const ORTHANC_OVERRIDE + { + return Type_Arrow; + } + + virtual void GetBoundingBox(Extent2D& target) const ORTHANC_OVERRIDE; + }; +} diff -r 5f0660fe06c3 -r ad9b425f27ae OrthancStone/Sources/Scene2D/CairoCompositor.cpp --- a/OrthancStone/Sources/Scene2D/CairoCompositor.cpp Fri Oct 30 11:07:38 2020 +0100 +++ b/OrthancStone/Sources/Scene2D/CairoCompositor.cpp Fri Oct 30 16:26:39 2020 +0100 @@ -22,6 +22,7 @@ #include "CairoCompositor.h" +#include "Internals/CairoArrowRenderer.h" #include "Internals/CairoColorTextureRenderer.h" #include "Internals/CairoFloatTextureRenderer.h" #include "Internals/CairoInfoPanelRenderer.h" @@ -84,6 +85,9 @@ case ISceneLayer::Type_Macro: return new Internals::MacroLayerRenderer(*this, layer); + case ISceneLayer::Type_Arrow: + return new Internals::CairoArrowRenderer(*this, layer); + default: return NULL; } diff -r 5f0660fe06c3 -r ad9b425f27ae OrthancStone/Sources/Scene2D/ISceneLayer.h --- a/OrthancStone/Sources/Scene2D/ISceneLayer.h Fri Oct 30 11:07:38 2020 +0100 +++ b/OrthancStone/Sources/Scene2D/ISceneLayer.h Fri Oct 30 16:26:39 2020 +0100 @@ -41,7 +41,8 @@ Type_Text, Type_FloatTexture, Type_LookupTableTexture, - Type_Macro + Type_Macro, + Type_Arrow }; virtual ~ISceneLayer() diff -r 5f0660fe06c3 -r ad9b425f27ae OrthancStone/Sources/Scene2D/Internals/CairoArrowRenderer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancStone/Sources/Scene2D/Internals/CairoArrowRenderer.cpp Fri Oct 30 16:26:39 2020 +0100 @@ -0,0 +1,77 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2020 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, see + * . + **/ + + +#include "CairoArrowRenderer.h" + +#include "../ArrowSceneLayer.h" + +namespace OrthancStone +{ + namespace Internals + { + void CairoArrowRenderer::Render(const AffineTransform2D& transform, + unsigned int canvasWidth, + unsigned int canvasHeight) + { + const ArrowSceneLayer& layer = GetLayer(); + + cairo_t* cr = GetCairoContext(); + + cairo_set_line_width(cr, layer.GetThickness()); + + const Color& color = layer.GetColor(); + cairo_set_source_rgb(cr, color.GetRedAsFloat(), + color.GetGreenAsFloat(), + color.GetBlueAsFloat()); + + const double zoom = transform.ComputeZoom(); + + ScenePoint2D axis = layer.GetB() - layer.GetA(); + double n = ScenePoint2D::SquaredMagnitude(axis); + + if (!LinearAlgebra::IsCloseToZero(n)) + { + axis = axis * layer.GetArrowLength() / (sqrt(n) * zoom); + + const ScenePoint2D a = layer.GetA().Apply(transform); + const ScenePoint2D b = layer.GetB().Apply(transform); + + cairo_move_to(cr, a.GetX(), a.GetY()); + cairo_line_to(cr, b.GetX(), b.GetY()); + + AffineTransform2D r1 = AffineTransform2D::CreateRotation(layer.GetArrowAngle()); + const ScenePoint2D c = (layer.GetA() + axis.Apply(r1)).Apply(transform); + + AffineTransform2D r2 = AffineTransform2D::CreateRotation(-layer.GetArrowAngle()); + const ScenePoint2D d = (layer.GetA() + axis.Apply(r2)).Apply(transform); + + cairo_move_to(cr, a.GetX(), a.GetY()); + cairo_line_to(cr, c.GetX(), c.GetY()); + + cairo_move_to(cr, a.GetX(), a.GetY()); + cairo_line_to(cr, d.GetX(), d.GetY()); + + cairo_stroke(cr); + } + } + } +} diff -r 5f0660fe06c3 -r ad9b425f27ae OrthancStone/Sources/Scene2D/Internals/CairoArrowRenderer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancStone/Sources/Scene2D/Internals/CairoArrowRenderer.h Fri Oct 30 16:26:39 2020 +0100 @@ -0,0 +1,45 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2020 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, see + * . + **/ + + +#pragma once + +#include "CairoBaseRenderer.h" + +namespace OrthancStone +{ + namespace Internals + { + class CairoArrowRenderer : public CairoBaseRenderer + { + public: + CairoArrowRenderer(ICairoContextProvider& target, + const ISceneLayer& layer) : + CairoBaseRenderer(target, layer) + { + } + + virtual void Render(const AffineTransform2D& transform, + unsigned int canvasWidth, + unsigned int canvasHeight) ORTHANC_OVERRIDE; + }; + } +} diff -r 5f0660fe06c3 -r ad9b425f27ae OrthancStone/Sources/Scene2D/Internals/OpenGLAdvancedPolylineRenderer.cpp --- a/OrthancStone/Sources/Scene2D/Internals/OpenGLAdvancedPolylineRenderer.cpp Fri Oct 30 11:07:38 2020 +0100 +++ b/OrthancStone/Sources/Scene2D/Internals/OpenGLAdvancedPolylineRenderer.cpp Fri Oct 30 16:26:39 2020 +0100 @@ -35,7 +35,7 @@ if (data_.get() == NULL) { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); } } @@ -48,5 +48,16 @@ { LoadLayer(layer); } + + + void OpenGLAdvancedPolylineRenderer::Render(const AffineTransform2D& transform, + unsigned int canvasWidth, + unsigned int canvasHeight) + { + if (!context_.IsContextLost()) + { + program_.Apply(*data_, transform, canvasWidth, canvasHeight, true, true); + } + } } } diff -r 5f0660fe06c3 -r ad9b425f27ae OrthancStone/Sources/Scene2D/Internals/OpenGLAdvancedPolylineRenderer.h --- a/OrthancStone/Sources/Scene2D/Internals/OpenGLAdvancedPolylineRenderer.h Fri Oct 30 11:07:38 2020 +0100 +++ b/OrthancStone/Sources/Scene2D/Internals/OpenGLAdvancedPolylineRenderer.h Fri Oct 30 16:26:39 2020 +0100 @@ -46,13 +46,7 @@ virtual void Render(const AffineTransform2D& transform, unsigned int canvasWidth, - unsigned int canvasHeight) ORTHANC_OVERRIDE - { - if (!context_.IsContextLost()) - { - program_.Apply(*data_, transform, canvasWidth, canvasHeight, true, true); - } - } + unsigned int canvasHeight) ORTHANC_OVERRIDE; virtual void Update(const ISceneLayer& layer) ORTHANC_OVERRIDE { diff -r 5f0660fe06c3 -r ad9b425f27ae OrthancStone/Sources/Scene2D/Internals/OpenGLArrowRenderer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancStone/Sources/Scene2D/Internals/OpenGLArrowRenderer.cpp Fri Oct 30 16:26:39 2020 +0100 @@ -0,0 +1,134 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2020 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, see + * . + **/ + + +#include "OpenGLArrowRenderer.h" + +#include + +#include + + +namespace OrthancStone +{ + namespace Internals + { + void OpenGLArrowRenderer::LoadLayer(const ArrowSceneLayer& layer) + { + // "dataBody_" contains the "body" of the arrow, in scene coordinates + { + PolylineSceneLayer l; + l.SetThickness(layer.GetThickness()); + + PolylineSceneLayer::Chain chain; + chain.push_back(layer.GetA()); + chain.push_back(layer.GetB()); + l.AddChain(chain, false, layer.GetColor()); + + dataBody_.reset(new OpenGLLinesProgram::Data(context_, l)); + } + + // "dataHead_" contains the "head" of the arrow, properly scaled in + // pixel coordinates, but with center at (0,0) + { + PolylineSceneLayer l; + l.SetThickness(layer.GetThickness()); + + const double c = cos(layer.GetArrowAngle()); + const double s = sin(layer.GetArrowAngle()); + + PolylineSceneLayer::Chain chain; + chain.push_back(ScenePoint2D(c, s) * layer.GetArrowLength()); + chain.push_back(ScenePoint2D(0, 0)); + chain.push_back(ScenePoint2D(c, -s) * layer.GetArrowLength()); + l.AddChain(chain, false, layer.GetColor()); + + dataHead_.reset(new OpenGLLinesProgram::Data(context_, l)); + } + + // Compute a unit vector encoding the direction of the body of the arrow + ScenePoint2D direction = layer.GetB() - layer.GetA(); + double n = ScenePoint2D::SquaredMagnitude(direction); + if (LinearAlgebra::IsCloseToZero(n)) + { + direction = ScenePoint2D(1, 0); + } + else + { + direction = direction / sqrt(n); + } + + // Compute a rotation matrix, to bring the "head" in the axis of the "body" + // https://math.stackexchange.com/a/3565068 + Matrix rotation = LinearAlgebra::ZeroMatrix(3, 3); + rotation(0, 0) = direction.GetX(); + rotation(1, 0) = direction.GetY(); + rotation(0, 1) = -direction.GetY(); + rotation(1, 1) = direction.GetX(); + rotation(2, 2) = 1; + + transformHead_ = AffineTransform2D::Combine( + AffineTransform2D::CreateOffset(layer.GetA().GetX(), layer.GetA().GetY()), + AffineTransform2D(rotation)); + + if (dataBody_.get() == NULL || + dataHead_.get() == NULL) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); + } + } + + + OpenGLArrowRenderer::OpenGLArrowRenderer(OpenGL::IOpenGLContext& context, + OpenGLLinesProgram& program, + const ArrowSceneLayer& layer) : + context_(context), + program_(program) + { + LoadLayer(layer); + } + + + void OpenGLArrowRenderer::Render(const AffineTransform2D& transform, + unsigned int canvasWidth, + unsigned int canvasHeight) + { + if (!context_.IsContextLost()) + { + program_.Apply(*dataBody_, transform, canvasWidth, canvasHeight, true, true); + + const double z = 1.0 / transform.ComputeZoom(); + const AffineTransform2D t2 = AffineTransform2D::Combine( + transform, // 3. Apply the original transform + transformHead_, // 2. Bring the "head" of the arrow at the proper position/angle + AffineTransform2D::CreateScaling(z, z)); // 1. Neutralize the zoom level + + program_.Apply(*dataHead_, t2, canvasWidth, canvasHeight, true, true); + } + } + + + void OpenGLArrowRenderer::Update(const ISceneLayer& layer) + { + LoadLayer(dynamic_cast(layer)); + } + } +} diff -r 5f0660fe06c3 -r ad9b425f27ae OrthancStone/Sources/Scene2D/Internals/OpenGLArrowRenderer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OrthancStone/Sources/Scene2D/Internals/OpenGLArrowRenderer.h Fri Oct 30 16:26:39 2020 +0100 @@ -0,0 +1,57 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2020 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, see + * . + **/ + + +#pragma once + +#include "../ArrowSceneLayer.h" +#include "CompositorHelper.h" +#include "OpenGLLinesProgram.h" + + +namespace OrthancStone +{ + namespace Internals + { + class OpenGLArrowRenderer : public CompositorHelper::ILayerRenderer + { + private: + OpenGL::IOpenGLContext& context_; + OpenGLLinesProgram& program_; + std::unique_ptr dataBody_; + std::unique_ptr dataHead_; + AffineTransform2D transformHead_; + + void LoadLayer(const ArrowSceneLayer& layer); + + public: + OpenGLArrowRenderer(OpenGL::IOpenGLContext& context, + OpenGLLinesProgram& program, + const ArrowSceneLayer& layer); + + virtual void Render(const AffineTransform2D& transform, + unsigned int canvasWidth, + unsigned int canvasHeight) ORTHANC_OVERRIDE; + + virtual void Update(const ISceneLayer& layer) ORTHANC_OVERRIDE; + }; + } +} diff -r 5f0660fe06c3 -r ad9b425f27ae OrthancStone/Sources/Scene2D/OpenGLCompositor.cpp --- a/OrthancStone/Sources/Scene2D/OpenGLCompositor.cpp Fri Oct 30 11:07:38 2020 +0100 +++ b/OrthancStone/Sources/Scene2D/OpenGLCompositor.cpp Fri Oct 30 16:26:39 2020 +0100 @@ -22,6 +22,7 @@ #include "OpenGLCompositor.h" #include "Internals/OpenGLAdvancedPolylineRenderer.h" +#include "Internals/OpenGLArrowRenderer.h" #include "Internals/OpenGLBasicPolylineRenderer.h" #include "Internals/OpenGLColorTextureRenderer.h" #include "Internals/OpenGLFloatTextureRenderer.h" @@ -122,6 +123,10 @@ case ISceneLayer::Type_Macro: return new Internals::MacroLayerRenderer(*this, layer); + case ISceneLayer::Type_Arrow: + return new Internals::OpenGLArrowRenderer + (context_, linesProgram_, dynamic_cast(layer)); + default: return NULL; }