# HG changeset patch # User Sebastien Jodogne # Date 1542034323 -3600 # Node ID 6decc0ba9da5da10b77c186f64aea05b01fb2661 # Parent 99c9b32380080f8342e796dccc12603deb664097 rename RadiographyScene::Layer as RadiographyLayer diff -r 99c9b3238008 -r 6decc0ba9da5 Applications/Samples/SingleFrameEditorApplication.h --- a/Applications/Samples/SingleFrameEditorApplication.h Mon Nov 12 15:38:11 2018 +0100 +++ b/Applications/Samples/SingleFrameEditorApplication.h Mon Nov 12 15:52:03 2018 +0100 @@ -58,9 +58,9 @@ size_t layer_; protected: - virtual void UndoInternal(RadiographyScene::Layer& layer) const = 0; + virtual void UndoInternal(RadiographyLayer& layer) const = 0; - virtual void RedoInternal(RadiographyScene::Layer& layer) const = 0; + virtual void RedoInternal(RadiographyLayer& layer) const = 0; public: RadiographyLayerCommand(RadiographyScene& scene, @@ -143,13 +143,13 @@ } protected: - virtual void UndoInternal(RadiographyScene::Layer& layer) const + virtual void UndoInternal(RadiographyLayer& layer) const { LOG(INFO) << "Undo - Set angle to " << ToDegrees(sourceAngle_) << " degrees"; layer.SetAngle(sourceAngle_); } - virtual void RedoInternal(RadiographyScene::Layer& layer) const + virtual void RedoInternal(RadiographyLayer& layer) const { LOG(INFO) << "Redo - Set angle to " << ToDegrees(sourceAngle_) << " degrees"; layer.SetAngle(targetAngle_); @@ -256,12 +256,12 @@ double targetY_; protected: - virtual void UndoInternal(RadiographyScene::Layer& layer) const + virtual void UndoInternal(RadiographyLayer& layer) const { layer.SetPan(sourceX_, sourceY_); } - virtual void RedoInternal(RadiographyScene::Layer& layer) const + virtual void RedoInternal(RadiographyLayer& layer) const { layer.SetPan(targetX_, targetY_); } @@ -352,7 +352,7 @@ private: UndoRedoStack& undoRedoStack_; RadiographyScene::LayerAccessor accessor_; - RadiographyScene::Corner corner_; + Corner corner_; unsigned int cropX_; unsigned int cropY_; unsigned int cropWidth_; @@ -371,12 +371,12 @@ unsigned int targetCropHeight_; protected: - virtual void UndoInternal(RadiographyScene::Layer& layer) const + virtual void UndoInternal(RadiographyLayer& layer) const { layer.SetCrop(sourceCropX_, sourceCropY_, sourceCropWidth_, sourceCropHeight_); } - virtual void RedoInternal(RadiographyScene::Layer& layer) const + virtual void RedoInternal(RadiographyLayer& layer) const { layer.SetCrop(targetCropX_, targetCropY_, targetCropWidth_, targetCropHeight_); } @@ -402,7 +402,7 @@ size_t layer, double x, double y, - RadiographyScene::Corner corner) : + Corner corner) : undoRedoStack_(undoRedoStack), accessor_(scene, layer), corner_(corner) @@ -441,13 +441,13 @@ { unsigned int x, y; - RadiographyScene::Layer& layer = accessor_.GetLayer(); + RadiographyLayer& layer = accessor_.GetLayer(); if (layer.GetPixel(x, y, sceneX, sceneY)) { unsigned int targetX, targetWidth; - if (corner_ == RadiographyScene::Corner_TopLeft || - corner_ == RadiographyScene::Corner_BottomLeft) + if (corner_ == Corner_TopLeft || + corner_ == Corner_BottomLeft) { targetX = std::min(x, cropX_ + cropWidth_); targetWidth = cropX_ + cropWidth_ - targetX; @@ -460,8 +460,8 @@ unsigned int targetY, targetHeight; - if (corner_ == RadiographyScene::Corner_TopLeft || - corner_ == RadiographyScene::Corner_TopRight) + if (corner_ == Corner_TopLeft || + corner_ == Corner_TopRight) { targetY = std::min(y, cropY_ + cropHeight_); targetHeight = cropY_ + cropHeight_ - targetY; @@ -489,7 +489,7 @@ double originalSpacingY_; double originalPanX_; double originalPanY_; - RadiographyScene::Corner oppositeCorner_; + Corner oppositeCorner_; double oppositeX_; double oppositeY_; double baseScaling_; @@ -517,13 +517,13 @@ double targetPanY_; protected: - virtual void UndoInternal(RadiographyScene::Layer& layer) const + virtual void UndoInternal(RadiographyLayer& layer) const { layer.SetPixelSpacing(sourceSpacingX_, sourceSpacingY_); layer.SetPan(sourcePanX_, sourcePanY_); } - virtual void RedoInternal(RadiographyScene::Layer& layer) const + virtual void RedoInternal(RadiographyLayer& layer) const { layer.SetPixelSpacing(targetSpacingX_, targetSpacingY_); layer.SetPan(targetPanX_, targetPanY_); @@ -551,7 +551,7 @@ size_t layer, double x, double y, - RadiographyScene::Corner corner, + Corner corner, bool roundScaling) : undoRedoStack_(undoRedoStack), accessor_(scene, layer), @@ -567,20 +567,20 @@ switch (corner) { - case RadiographyScene::Corner_TopLeft: - oppositeCorner_ = RadiographyScene::Corner_BottomRight; + case Corner_TopLeft: + oppositeCorner_ = Corner_BottomRight; break; - case RadiographyScene::Corner_TopRight: - oppositeCorner_ = RadiographyScene::Corner_BottomLeft; + case Corner_TopRight: + oppositeCorner_ = Corner_BottomLeft; break; - case RadiographyScene::Corner_BottomLeft: - oppositeCorner_ = RadiographyScene::Corner_TopRight; + case Corner_BottomLeft: + oppositeCorner_ = Corner_TopRight; break; - case RadiographyScene::Corner_BottomRight: - oppositeCorner_ = RadiographyScene::Corner_TopLeft; + case Corner_BottomRight: + oppositeCorner_ = Corner_TopLeft; break; default: @@ -639,7 +639,7 @@ scaling = boost::math::round((scaling / ROUND_SCALING) * ROUND_SCALING); } - RadiographyScene::Layer& layer = accessor_.GetLayer(); + RadiographyLayer& layer = accessor_.GetLayer(); layer.SetPixelSpacing(scaling * originalSpacingX_, scaling * originalSpacingY_); @@ -1148,7 +1148,8 @@ tool_ == Tool_Resize) { RadiographyScene::LayerAccessor accessor(widget.GetScene(), selected); - RadiographyScene::Corner corner; + + Corner corner; if (accessor.GetLayer().LookupCorner(corner, x, y, view.GetZoom(), GetHandleSize())) { switch (tool_) @@ -1253,7 +1254,7 @@ { RadiographyScene::LayerAccessor accessor(widget.GetScene(), selected); - RadiographyScene::Corner corner; + Corner corner; if (accessor.GetLayer().LookupCorner(corner, x, y, view.GetZoom(), GetHandleSize())) { accessor.GetLayer().GetCorner(x, y, corner); @@ -1465,16 +1466,14 @@ //scene_->LoadDicomFrame("61f3143e-96f34791-ad6bbb8d-62559e75-45943e1b", 0, false); { - RadiographyScene::Layer& layer = scene_->LoadText(fonts.GetFont(0), "Hello\nworld"); - //dynamic_cast(layer).SetForegroundValue(256); - dynamic_cast(layer).SetResizeable(true); + RadiographyLayer& layer = scene_->LoadText(fonts.GetFont(0), "Hello\nworld"); + layer.SetResizeable(true); } { - RadiographyScene::Layer& layer = scene_->LoadTestBlock(100, 50); - //dynamic_cast(layer).SetForegroundValue(256); - dynamic_cast(layer).SetResizeable(true); - dynamic_cast(layer).SetPan(0, 200); + RadiographyLayer& layer = scene_->LoadTestBlock(100, 50); + layer.SetResizeable(true); + layer.SetPan(0, 200); } diff -r 99c9b3238008 -r 6decc0ba9da5 Framework/Radiography/RadiographyLayer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Radiography/RadiographyLayer.cpp Mon Nov 12 15:52:03 2018 +0100 @@ -0,0 +1,391 @@ +/** + * 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 . + **/ + + +#include "RadiographyLayer.h" + +#include + + +namespace OrthancStone +{ + static double Square(double x) + { + return x * x; + } + + + void RadiographyLayer::UpdateTransform() + { + transform_ = AffineTransform2D::CreateScaling(pixelSpacingX_, pixelSpacingY_); + + double centerX, centerY; + GetCenter(centerX, centerY); + + transform_ = AffineTransform2D::Combine( + AffineTransform2D::CreateOffset(panX_ + centerX, panY_ + centerY), + AffineTransform2D::CreateRotation(angle_), + AffineTransform2D::CreateOffset(-centerX, -centerY), + transform_); + + transformInverse_ = AffineTransform2D::Invert(transform_); + } + + + void RadiographyLayer::AddToExtent(Extent2D& extent, + double x, + double y) const + { + transform_.Apply(x, y); + extent.AddPoint(x, y); + } + + + void RadiographyLayer::GetCornerInternal(double& x, + double& y, + Corner corner, + unsigned int cropX, + unsigned int cropY, + unsigned int cropWidth, + unsigned int cropHeight) const + { + double dx = static_cast(cropX); + double dy = static_cast(cropY); + double dwidth = static_cast(cropWidth); + double dheight = static_cast(cropHeight); + + switch (corner) + { + case Corner_TopLeft: + x = dx; + y = dy; + break; + + case Corner_TopRight: + x = dx + dwidth; + y = dy; + break; + + case Corner_BottomLeft: + x = dx; + y = dy + dheight; + break; + + case Corner_BottomRight: + x = dx + dwidth; + y = dy + dheight; + break; + + default: + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + + transform_.Apply(x, y); + } + + + bool RadiographyLayer::Contains(double x, + double y) const + { + transformInverse_.Apply(x, y); + + unsigned int cropX, cropY, cropWidth, cropHeight; + GetCrop(cropX, cropY, cropWidth, cropHeight); + + return (x >= cropX && x <= cropX + cropWidth && + y >= cropY && y <= cropY + cropHeight); + } + + + void RadiographyLayer::DrawBorders(CairoContext& context, + double zoom) + { + unsigned int cx, cy, width, height; + GetCrop(cx, cy, width, height); + + double dx = static_cast(cx); + double dy = static_cast(cy); + double dwidth = static_cast(width); + double dheight = static_cast(height); + + cairo_t* cr = context.GetObject(); + cairo_set_line_width(cr, 2.0 / zoom); + + double x, y; + x = dx; + y = dy; + transform_.Apply(x, y); + cairo_move_to(cr, x, y); + + x = dx + dwidth; + y = dy; + transform_.Apply(x, y); + cairo_line_to(cr, x, y); + + x = dx + dwidth; + y = dy + dheight; + transform_.Apply(x, y); + cairo_line_to(cr, x, y); + + x = dx; + y = dy + dheight; + transform_.Apply(x, y); + cairo_line_to(cr, x, y); + + x = dx; + y = dy; + transform_.Apply(x, y); + cairo_line_to(cr, x, y); + + cairo_stroke(cr); + } + + + RadiographyLayer::RadiographyLayer() : + index_(0), + hasSize_(false), + width_(0), + height_(0), + hasCrop_(false), + pixelSpacingX_(1), + pixelSpacingY_(1), + panX_(0), + panY_(0), + angle_(0), + resizeable_(false) + { + UpdateTransform(); + } + + + void RadiographyLayer::SetCrop(unsigned int x, + unsigned int y, + unsigned int width, + unsigned int height) + { + if (!hasSize_) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); + } + + if (x + width > width_ || + y + height > height_) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + + hasCrop_ = true; + cropX_ = x; + cropY_ = y; + cropWidth_ = width; + cropHeight_ = height; + + UpdateTransform(); + } + + + void RadiographyLayer::GetCrop(unsigned int& x, + unsigned int& y, + unsigned int& width, + unsigned int& height) const + { + if (hasCrop_) + { + x = cropX_; + y = cropY_; + width = cropWidth_; + height = cropHeight_; + } + else + { + x = 0; + y = 0; + width = width_; + height = height_; + } + } + + + void RadiographyLayer::SetAngle(double angle) + { + angle_ = angle; + UpdateTransform(); + } + + + void RadiographyLayer::SetSize(unsigned int width, + unsigned int height) + { + if (hasSize_ && + (width != width_ || + height != height_)) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageSize); + } + + hasSize_ = true; + width_ = width; + height_ = height; + + UpdateTransform(); + } + + + Extent2D RadiographyLayer::GetExtent() const + { + Extent2D extent; + + unsigned int x, y, width, height; + GetCrop(x, y, width, height); + + double dx = static_cast(x); + double dy = static_cast(y); + double dwidth = static_cast(width); + double dheight = static_cast(height); + + AddToExtent(extent, dx, dy); + AddToExtent(extent, dx + dwidth, dy); + AddToExtent(extent, dx, dy + dheight); + AddToExtent(extent, dx + dwidth, dy + dheight); + + return extent; + } + + + bool RadiographyLayer::GetPixel(unsigned int& imageX, + unsigned int& imageY, + double sceneX, + double sceneY) const + { + if (width_ == 0 || + height_ == 0) + { + return false; + } + else + { + transformInverse_.Apply(sceneX, sceneY); + + int x = static_cast(std::floor(sceneX)); + int y = static_cast(std::floor(sceneY)); + + if (x < 0) + { + imageX = 0; + } + else if (x >= static_cast(width_)) + { + imageX = width_; + } + else + { + imageX = static_cast(x); + } + + if (y < 0) + { + imageY = 0; + } + else if (y >= static_cast(height_)) + { + imageY = height_; + } + else + { + imageY = static_cast(y); + } + + return true; + } + } + + + void RadiographyLayer::SetPan(double x, + double y) + { + panX_ = x; + panY_ = y; + UpdateTransform(); + } + + + void RadiographyLayer::SetPixelSpacing(double x, + double y) + { + pixelSpacingX_ = x; + pixelSpacingY_ = y; + UpdateTransform(); + } + + + void RadiographyLayer::GetCenter(double& centerX, + double& centerY) const + { + centerX = static_cast(width_) / 2.0; + centerY = static_cast(height_) / 2.0; + transform_.Apply(centerX, centerY); + } + + + void RadiographyLayer::GetCorner(double& x /* out */, + double& y /* out */, + Corner corner) const + { + unsigned int cropX, cropY, cropWidth, cropHeight; + GetCrop(cropX, cropY, cropWidth, cropHeight); + GetCornerInternal(x, y, corner, cropX, cropY, cropWidth, cropHeight); + } + + + bool RadiographyLayer::LookupCorner(Corner& corner /* out */, + double x, + double y, + double zoom, + double viewportDistance) const + { + static const Corner CORNERS[] = { + Corner_TopLeft, + Corner_TopRight, + Corner_BottomLeft, + Corner_BottomRight + }; + + unsigned int cropX, cropY, cropWidth, cropHeight; + GetCrop(cropX, cropY, cropWidth, cropHeight); + + double threshold = Square(viewportDistance / zoom); + + for (size_t i = 0; i < 4; i++) + { + double cx, cy; + GetCornerInternal(cx, cy, CORNERS[i], cropX, cropY, cropWidth, cropHeight); + + double d = Square(cx - x) + Square(cy - y); + + if (d <= threshold) + { + corner = CORNERS[i]; + return true; + } + } + + return false; + } +} diff -r 99c9b3238008 -r 6decc0ba9da5 Framework/Radiography/RadiographyLayer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Radiography/RadiographyLayer.h Mon Nov 12 15:52:03 2018 +0100 @@ -0,0 +1,198 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2018 Osimis S.A., Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + **/ + + +#pragma once + +#include "../Toolbox/AffineTransform2D.h" +#include "../Toolbox/Extent2D.h" +#include "../Viewport/CairoContext.h" + +namespace OrthancStone +{ + class RadiographyLayer : public boost::noncopyable + { + friend class RadiographyScene; + + private: + size_t index_; + bool hasSize_; + unsigned int width_; + unsigned int height_; + bool hasCrop_; + unsigned int cropX_; + unsigned int cropY_; + unsigned int cropWidth_; + unsigned int cropHeight_; + AffineTransform2D transform_; + AffineTransform2D transformInverse_; + double pixelSpacingX_; + double pixelSpacingY_; + double panX_; + double panY_; + double angle_; + bool resizeable_; + + protected: + const AffineTransform2D& GetTransform() const + { + return transform_; + } + + private: + void UpdateTransform(); + + void AddToExtent(Extent2D& extent, + double x, + double y) const; + + void GetCornerInternal(double& x, + double& y, + Corner corner, + unsigned int cropX, + unsigned int cropY, + unsigned int cropWidth, + unsigned int cropHeight) const; + + void SetIndex(size_t index) + { + index_ = index; + } + + bool Contains(double x, + double y) const; + + void DrawBorders(CairoContext& context, + double zoom); + + public: + RadiographyLayer(); + + virtual ~RadiographyLayer() + { + } + + size_t GetIndex() const + { + return index_; + } + + void ResetCrop() + { + hasCrop_ = false; + } + + void SetCrop(unsigned int x, + unsigned int y, + unsigned int width, + unsigned int height); + + void GetCrop(unsigned int& x, + unsigned int& y, + unsigned int& width, + unsigned int& height) const; + + void SetAngle(double angle); + + double GetAngle() const + { + return angle_; + } + + void SetSize(unsigned int width, + unsigned int height); + + unsigned int GetWidth() const + { + return width_; + } + + unsigned int GetHeight() const + { + return height_; + } + + Extent2D GetExtent() const; + + bool GetPixel(unsigned int& imageX, + unsigned int& imageY, + double sceneX, + double sceneY) const; + + void SetPan(double x, + double y); + + void SetPixelSpacing(double x, + double y); + + double GetPixelSpacingX() const + { + return pixelSpacingX_; + } + + double GetPixelSpacingY() const + { + return pixelSpacingY_; + } + + double GetPanX() const + { + return panX_; + } + + double GetPanY() const + { + return panY_; + } + + void GetCenter(double& centerX, + double& centerY) const; + + void GetCorner(double& x /* out */, + double& y /* out */, + Corner corner) const; + + bool LookupCorner(Corner& corner /* out */, + double x, + double y, + double zoom, + double viewportDistance) const; + + bool IsResizeable() const + { + return resizeable_; + } + + void SetResizeable(bool resizeable) + { + resizeable_ = resizeable; + } + + virtual bool GetDefaultWindowing(float& center, + float& width) const = 0; + + virtual void Render(Orthanc::ImageAccessor& buffer, + const AffineTransform2D& viewTransform, + ImageInterpolation interpolation) const = 0; + + virtual bool GetRange(float& minValue, + float& maxValue) const = 0; + }; +} diff -r 99c9b3238008 -r 6decc0ba9da5 Framework/Radiography/RadiographyScene.cpp --- a/Framework/Radiography/RadiographyScene.cpp Mon Nov 12 15:38:11 2018 +0100 +++ b/Framework/Radiography/RadiographyScene.cpp Mon Nov 12 15:52:03 2018 +0100 @@ -21,7 +21,6 @@ #include "RadiographyScene.h" -#include "../Toolbox/ImageGeometry.h" #include "../Toolbox/DicomFrameConverter.h" #include @@ -37,371 +36,6 @@ namespace OrthancStone { - static double Square(double x) - { - return x * x; - } - - - void RadiographyScene::Layer::UpdateTransform() - { - transform_ = AffineTransform2D::CreateScaling(pixelSpacingX_, pixelSpacingY_); - - double centerX, centerY; - GetCenter(centerX, centerY); - - transform_ = AffineTransform2D::Combine( - AffineTransform2D::CreateOffset(panX_ + centerX, panY_ + centerY), - AffineTransform2D::CreateRotation(angle_), - AffineTransform2D::CreateOffset(-centerX, -centerY), - transform_); - - transformInverse_ = AffineTransform2D::Invert(transform_); - } - - - void RadiographyScene::Layer::AddToExtent(Extent2D& extent, - double x, - double y) const - { - transform_.Apply(x, y); - extent.AddPoint(x, y); - } - - - void RadiographyScene::Layer::GetCornerInternal(double& x, - double& y, - Corner corner, - unsigned int cropX, - unsigned int cropY, - unsigned int cropWidth, - unsigned int cropHeight) const - { - double dx = static_cast(cropX); - double dy = static_cast(cropY); - double dwidth = static_cast(cropWidth); - double dheight = static_cast(cropHeight); - - switch (corner) - { - case Corner_TopLeft: - x = dx; - y = dy; - break; - - case Corner_TopRight: - x = dx + dwidth; - y = dy; - break; - - case Corner_BottomLeft: - x = dx; - y = dy + dheight; - break; - - case Corner_BottomRight: - x = dx + dwidth; - y = dy + dheight; - break; - - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - transform_.Apply(x, y); - } - - - bool RadiographyScene::Layer::Contains(double x, - double y) const - { - transformInverse_.Apply(x, y); - - unsigned int cropX, cropY, cropWidth, cropHeight; - GetCrop(cropX, cropY, cropWidth, cropHeight); - - return (x >= cropX && x <= cropX + cropWidth && - y >= cropY && y <= cropY + cropHeight); - } - - - void RadiographyScene::Layer::DrawBorders(CairoContext& context, - double zoom) - { - unsigned int cx, cy, width, height; - GetCrop(cx, cy, width, height); - - double dx = static_cast(cx); - double dy = static_cast(cy); - double dwidth = static_cast(width); - double dheight = static_cast(height); - - cairo_t* cr = context.GetObject(); - cairo_set_line_width(cr, 2.0 / zoom); - - double x, y; - x = dx; - y = dy; - transform_.Apply(x, y); - cairo_move_to(cr, x, y); - - x = dx + dwidth; - y = dy; - transform_.Apply(x, y); - cairo_line_to(cr, x, y); - - x = dx + dwidth; - y = dy + dheight; - transform_.Apply(x, y); - cairo_line_to(cr, x, y); - - x = dx; - y = dy + dheight; - transform_.Apply(x, y); - cairo_line_to(cr, x, y); - - x = dx; - y = dy; - transform_.Apply(x, y); - cairo_line_to(cr, x, y); - - cairo_stroke(cr); - } - - - RadiographyScene::Layer::Layer() : - index_(0), - hasSize_(false), - width_(0), - height_(0), - hasCrop_(false), - pixelSpacingX_(1), - pixelSpacingY_(1), - panX_(0), - panY_(0), - angle_(0), - resizeable_(false) - { - UpdateTransform(); - } - - - void RadiographyScene::Layer::SetCrop(unsigned int x, - unsigned int y, - unsigned int width, - unsigned int height) - { - if (!hasSize_) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); - } - - if (x + width > width_ || - y + height > height_) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - hasCrop_ = true; - cropX_ = x; - cropY_ = y; - cropWidth_ = width; - cropHeight_ = height; - - UpdateTransform(); - } - - - void RadiographyScene::Layer::GetCrop(unsigned int& x, - unsigned int& y, - unsigned int& width, - unsigned int& height) const - { - if (hasCrop_) - { - x = cropX_; - y = cropY_; - width = cropWidth_; - height = cropHeight_; - } - else - { - x = 0; - y = 0; - width = width_; - height = height_; - } - } - - - void RadiographyScene::Layer::SetAngle(double angle) - { - angle_ = angle; - UpdateTransform(); - } - - - void RadiographyScene::Layer::SetSize(unsigned int width, - unsigned int height) - { - if (hasSize_ && - (width != width_ || - height != height_)) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageSize); - } - - hasSize_ = true; - width_ = width; - height_ = height; - - UpdateTransform(); - } - - - Extent2D RadiographyScene::Layer::GetExtent() const - { - Extent2D extent; - - unsigned int x, y, width, height; - GetCrop(x, y, width, height); - - double dx = static_cast(x); - double dy = static_cast(y); - double dwidth = static_cast(width); - double dheight = static_cast(height); - - AddToExtent(extent, dx, dy); - AddToExtent(extent, dx + dwidth, dy); - AddToExtent(extent, dx, dy + dheight); - AddToExtent(extent, dx + dwidth, dy + dheight); - - return extent; - } - - - bool RadiographyScene::Layer::GetPixel(unsigned int& imageX, - unsigned int& imageY, - double sceneX, - double sceneY) const - { - if (width_ == 0 || - height_ == 0) - { - return false; - } - else - { - transformInverse_.Apply(sceneX, sceneY); - - int x = static_cast(std::floor(sceneX)); - int y = static_cast(std::floor(sceneY)); - - if (x < 0) - { - imageX = 0; - } - else if (x >= static_cast(width_)) - { - imageX = width_; - } - else - { - imageX = static_cast(x); - } - - if (y < 0) - { - imageY = 0; - } - else if (y >= static_cast(height_)) - { - imageY = height_; - } - else - { - imageY = static_cast(y); - } - - return true; - } - } - - - void RadiographyScene::Layer::SetPan(double x, - double y) - { - panX_ = x; - panY_ = y; - UpdateTransform(); - } - - - void RadiographyScene::Layer::SetPixelSpacing(double x, - double y) - { - pixelSpacingX_ = x; - pixelSpacingY_ = y; - UpdateTransform(); - } - - - void RadiographyScene::Layer::GetCenter(double& centerX, - double& centerY) const - { - centerX = static_cast(width_) / 2.0; - centerY = static_cast(height_) / 2.0; - transform_.Apply(centerX, centerY); - } - - - void RadiographyScene::Layer::GetCorner(double& x /* out */, - double& y /* out */, - Corner corner) const - { - unsigned int cropX, cropY, cropWidth, cropHeight; - GetCrop(cropX, cropY, cropWidth, cropHeight); - GetCornerInternal(x, y, corner, cropX, cropY, cropWidth, cropHeight); - } - - - bool RadiographyScene::Layer::LookupCorner(Corner& corner /* out */, - double x, - double y, - double zoom, - double viewportDistance) const - { - static const Corner CORNERS[] = { - Corner_TopLeft, - Corner_TopRight, - Corner_BottomLeft, - Corner_BottomRight - }; - - unsigned int cropX, cropY, cropWidth, cropHeight; - GetCrop(cropX, cropY, cropWidth, cropHeight); - - double threshold = Square(viewportDistance / zoom); - - for (size_t i = 0; i < 4; i++) - { - double cx, cy; - GetCornerInternal(cx, cy, CORNERS[i], cropX, cropY, cropWidth, cropHeight); - - double d = Square(cx - x) + Square(cy - y); - - if (d <= threshold) - { - corner = CORNERS[i]; - return true; - } - } - - return false; - } - - - RadiographyScene::LayerAccessor::LayerAccessor(RadiographyScene& scene, size_t index) : scene_(scene), @@ -473,7 +107,7 @@ } - RadiographyScene::Layer& RadiographyScene::LayerAccessor::GetLayer() const + RadiographyLayer& RadiographyScene::LayerAccessor::GetLayer() const { if (IsValid()) { @@ -487,7 +121,7 @@ - class RadiographyScene::AlphaLayer : public Layer + class RadiographyScene::AlphaLayer : public RadiographyLayer { private: const RadiographyScene& scene_; @@ -631,7 +265,7 @@ - class RadiographyScene::DicomLayer : public Layer + class RadiographyScene::DicomLayer : public RadiographyLayer { private: std::auto_ptr source_; // Content of PixelData @@ -767,14 +401,14 @@ }; - RadiographyScene::Layer& RadiographyScene::RegisterLayer(RadiographyScene::Layer* layer) + RadiographyLayer& RadiographyScene::RegisterLayer(RadiographyLayer* layer) { if (layer == NULL) { throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer); } - std::auto_ptr raii(layer); + std::auto_ptr raii(layer); size_t index = countLayers_++; raii->SetIndex(index); @@ -846,8 +480,8 @@ } - RadiographyScene::Layer& RadiographyScene::LoadText(const Orthanc::Font& font, - const std::string& utf8) + RadiographyLayer& RadiographyScene::LoadText(const Orthanc::Font& font, + const std::string& utf8) { std::auto_ptr alpha(new AlphaLayer(*this)); alpha->LoadText(font, utf8); @@ -856,8 +490,8 @@ } - RadiographyScene::Layer& RadiographyScene::LoadTestBlock(unsigned int width, - unsigned int height) + RadiographyLayer& RadiographyScene::LoadTestBlock(unsigned int width, + unsigned int height) { std::auto_ptr block(new Orthanc::Image(Orthanc::PixelFormat_Grayscale8, width, height, false)); @@ -887,11 +521,11 @@ } - RadiographyScene::Layer& RadiographyScene::LoadDicomFrame(const std::string& instance, - unsigned int frame, - bool httpCompression) + RadiographyLayer& RadiographyScene::LoadDicomFrame(const std::string& instance, + unsigned int frame, + bool httpCompression) { - Layer& layer = RegisterLayer(new DicomLayer); + RadiographyLayer& layer = RegisterLayer(new DicomLayer); { IWebService::Headers headers; diff -r 99c9b3238008 -r 6decc0ba9da5 Framework/Radiography/RadiographyScene.h --- a/Framework/Radiography/RadiographyScene.h Mon Nov 12 15:38:11 2018 +0100 +++ b/Framework/Radiography/RadiographyScene.h Mon Nov 12 15:52:03 2018 +0100 @@ -21,10 +21,8 @@ #pragma once -#include "../Toolbox/AffineTransform2D.h" -#include "../Toolbox/Extent2D.h" +#include "RadiographyLayer.h" #include "../Toolbox/OrthancApiClient.h" -#include "../Viewport/CairoContext.h" namespace OrthancStone @@ -37,193 +35,12 @@ typedef OriginMessage GeometryChangedMessage; typedef OriginMessage ContentChangedMessage; - enum Corner - { - Corner_TopLeft, - Corner_TopRight, - Corner_BottomLeft, - Corner_BottomRight - }; - - - class Layer : public boost::noncopyable - { - friend class RadiographyScene; - - private: - size_t index_; - bool hasSize_; - unsigned int width_; - unsigned int height_; - bool hasCrop_; - unsigned int cropX_; - unsigned int cropY_; - unsigned int cropWidth_; - unsigned int cropHeight_; - AffineTransform2D transform_; - AffineTransform2D transformInverse_; - double pixelSpacingX_; - double pixelSpacingY_; - double panX_; - double panY_; - double angle_; - bool resizeable_; - - - protected: - const AffineTransform2D& GetTransform() const - { - return transform_; - } - - - private: - void UpdateTransform(); - - void AddToExtent(Extent2D& extent, - double x, - double y) const; - - void GetCornerInternal(double& x, - double& y, - Corner corner, - unsigned int cropX, - unsigned int cropY, - unsigned int cropWidth, - unsigned int cropHeight) const; - - void SetIndex(size_t index) - { - index_ = index; - } - - bool Contains(double x, - double y) const; - - void DrawBorders(CairoContext& context, - double zoom); - - public: - Layer(); - - virtual ~Layer() - { - } - - size_t GetIndex() const - { - return index_; - } - - void ResetCrop() - { - hasCrop_ = false; - } - - void SetCrop(unsigned int x, - unsigned int y, - unsigned int width, - unsigned int height); - - void GetCrop(unsigned int& x, - unsigned int& y, - unsigned int& width, - unsigned int& height) const; - - void SetAngle(double angle); - - double GetAngle() const - { - return angle_; - } - - void SetSize(unsigned int width, - unsigned int height); - - unsigned int GetWidth() const - { - return width_; - } - - unsigned int GetHeight() const - { - return height_; - } - - Extent2D GetExtent() const; - - bool GetPixel(unsigned int& imageX, - unsigned int& imageY, - double sceneX, - double sceneY) const; - - void SetPan(double x, - double y); - - void SetPixelSpacing(double x, - double y); - - double GetPixelSpacingX() const - { - return pixelSpacingX_; - } - - double GetPixelSpacingY() const - { - return pixelSpacingY_; - } - - double GetPanX() const - { - return panX_; - } - - double GetPanY() const - { - return panY_; - } - - void GetCenter(double& centerX, - double& centerY) const; - - void GetCorner(double& x /* out */, - double& y /* out */, - Corner corner) const; - - bool LookupCorner(Corner& corner /* out */, - double x, - double y, - double zoom, - double viewportDistance) const; - - bool IsResizeable() const - { - return resizeable_; - } - - void SetResizeable(bool resizeable) - { - resizeable_ = resizeable; - } - - virtual bool GetDefaultWindowing(float& center, - float& width) const = 0; - - virtual void Render(Orthanc::ImageAccessor& buffer, - const AffineTransform2D& viewTransform, - ImageInterpolation interpolation) const = 0; - - virtual bool GetRange(float& minValue, - float& maxValue) const = 0; - }; - - class LayerAccessor : public boost::noncopyable { private: RadiographyScene& scene_; size_t index_; - Layer* layer_; + RadiographyLayer* layer_; public: LayerAccessor(RadiographyScene& scene, @@ -247,7 +64,7 @@ size_t GetIndex() const; - Layer& GetLayer() const; + RadiographyLayer& GetLayer() const; }; @@ -255,7 +72,7 @@ class AlphaLayer; class DicomLayer; - typedef std::map Layers; + typedef std::map Layers; OrthancApiClient& orthanc_; size_t countLayers_; @@ -264,7 +81,7 @@ float windowingWidth_; Layers layers_; - Layer& RegisterLayer(Layer* layer); + RadiographyLayer& RegisterLayer(RadiographyLayer* layer); void OnTagsReceived(const OrthancApiClient::BinaryResponseReadyMessage& message); @@ -287,15 +104,15 @@ void SetWindowing(float center, float width); - Layer& LoadText(const Orthanc::Font& font, - const std::string& utf8); + RadiographyLayer& LoadText(const Orthanc::Font& font, + const std::string& utf8); - Layer& LoadTestBlock(unsigned int width, - unsigned int height); + RadiographyLayer& LoadTestBlock(unsigned int width, + unsigned int height); - Layer& LoadDicomFrame(const std::string& instance, - unsigned int frame, - bool httpCompression); + RadiographyLayer& LoadDicomFrame(const std::string& instance, + unsigned int frame, + bool httpCompression); Extent2D GetSceneExtent() const; diff -r 99c9b3238008 -r 6decc0ba9da5 Framework/StoneEnumerations.h --- a/Framework/StoneEnumerations.h Mon Nov 12 15:38:11 2018 +0100 +++ b/Framework/StoneEnumerations.h Mon Nov 12 15:52:03 2018 +0100 @@ -166,7 +166,16 @@ MessageType_CustomMessage // Custom messages ids ust be greater than this (this one must remain in last position) }; + + enum Corner + { + Corner_TopLeft, + Corner_TopRight, + Corner_BottomLeft, + Corner_BottomRight + }; + bool StringToSopClassUid(SopClassUid& result, const std::string& source); diff -r 99c9b3238008 -r 6decc0ba9da5 Resources/CMake/OrthancStoneConfiguration.cmake --- a/Resources/CMake/OrthancStoneConfiguration.cmake Mon Nov 12 15:38:11 2018 +0100 +++ b/Resources/CMake/OrthancStoneConfiguration.cmake Mon Nov 12 15:52:03 2018 +0100 @@ -246,6 +246,8 @@ ${ORTHANC_STONE_ROOT}/Framework/Layers/LineMeasureTracker.cpp ${ORTHANC_STONE_ROOT}/Framework/Layers/RenderStyle.cpp ${ORTHANC_STONE_ROOT}/Framework/Layers/SliceOutlineRenderer.cpp + ${ORTHANC_STONE_ROOT}/Framework/Radiography/RadiographyLayer.cpp + ${ORTHANC_STONE_ROOT}/Framework/Radiography/RadiographyLayer.h ${ORTHANC_STONE_ROOT}/Framework/Radiography/RadiographyScene.cpp ${ORTHANC_STONE_ROOT}/Framework/Radiography/RadiographyScene.h ${ORTHANC_STONE_ROOT}/Framework/SmartLoader.cpp