Mercurial > hg > orthanc-stone
changeset 742:fa5febe0f0c2
moved OrientedBoundingBox in the Volumes folder
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 22 May 2019 09:41:03 +0200 |
parents | c1d6a566dfd3 |
children | bcd3ea868bcd |
files | Framework/Toolbox/FiniteProjectiveCamera.h Framework/Toolbox/OrientedBoundingBox.cpp Framework/Toolbox/OrientedBoundingBox.h Framework/Toolbox/ParallelSlices.h Framework/Toolbox/VolumeImageGeometry.cpp Framework/Toolbox/VolumeImageGeometry.h Framework/Volumes/OrientedVolumeBoundingBox.cpp Framework/Volumes/OrientedVolumeBoundingBox.h Framework/Volumes/VolumeImageGeometry.cpp Framework/Volumes/VolumeImageGeometry.h Framework/Volumes/VolumeReslicer.cpp Framework/Volumes/VolumeReslicer.h Resources/CMake/OrthancStoneConfiguration.cmake Samples/Sdl/Loader.cpp |
diffstat | 14 files changed, 790 insertions(+), 791 deletions(-) [+] |
line wrap: on
line diff
--- a/Framework/Toolbox/FiniteProjectiveCamera.h Wed May 22 09:27:21 2019 +0200 +++ b/Framework/Toolbox/FiniteProjectiveCamera.h Wed May 22 09:41:03 2019 +0200 @@ -23,7 +23,7 @@ #include "LinearAlgebra.h" #include "../Volumes/ImageBuffer3D.h" -#include "VolumeImageGeometry.h" +#include "../Volumes/VolumeImageGeometry.h" namespace OrthancStone {
--- a/Framework/Toolbox/OrientedBoundingBox.cpp Wed May 22 09:27:21 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,268 +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 "OrientedBoundingBox.h" - -#include "GeometryToolbox.h" -#include "../Volumes/ImageBuffer3D.h" - -#include <Core/OrthancException.h> - -#include <cassert> - -namespace OrthancStone -{ - OrientedBoundingBox::OrientedBoundingBox(const VolumeImageGeometry& geometry) - { - unsigned int n = geometry.GetDepth(); - if (n < 1) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageSize); - } - - Vector dim = geometry.GetVoxelDimensions(VolumeProjection_Axial); - - u_ = geometry.GetAxialGeometry().GetAxisX(); - v_ = geometry.GetAxialGeometry().GetAxisY(); - w_ = geometry.GetAxialGeometry().GetNormal(); - - hu_ = static_cast<double>(geometry.GetWidth() * dim[0] / 2.0); - hv_ = static_cast<double>(geometry.GetHeight() * dim[1] / 2.0); - hw_ = static_cast<double>(geometry.GetDepth() * dim[2] / 2.0); - - c_ = (geometry.GetAxialGeometry().GetOrigin() + - (hu_ - dim[0] / 2.0) * u_ + - (hv_ - dim[1] / 2.0) * v_ + - (hw_ - dim[2] / 2.0) * w_); - } - - - bool OrientedBoundingBox::HasIntersectionWithPlane(std::vector<Vector>& points, - const Vector& normal, - double d) const - { - assert(normal.size() == 3); - - double r = (hu_ * fabs(boost::numeric::ublas::inner_prod(normal, u_)) + - hv_ * fabs(boost::numeric::ublas::inner_prod(normal, v_)) + - hw_ * fabs(boost::numeric::ublas::inner_prod(normal, w_))); - - double s = boost::numeric::ublas::inner_prod(normal, c_) + d; - - if (fabs(s) >= r) - { - // No intersection, or intersection is reduced to a single point - return false; - } - else - { - Vector p; - - // Loop over all the 12 edges (segments) of the oriented - // bounding box, and check whether they intersect the plane - - // X-aligned edges - if (GeometryToolbox::IntersectPlaneAndSegment - (p, normal, d, - c_ - u_ * hu_ - v_ * hv_ - w_ * hw_, - c_ + u_ * hu_ - v_ * hv_ - w_ * hw_)) - { - points.push_back(p); - } - - if (GeometryToolbox::IntersectPlaneAndSegment - (p, normal, d, - c_ - u_ * hu_ + v_ * hv_ - w_ * hw_, - c_ + u_ * hu_ + v_ * hv_ - w_ * hw_)) - { - points.push_back(p); - } - - if (GeometryToolbox::IntersectPlaneAndSegment - (p, normal, d, - c_ - u_ * hu_ - v_ * hv_ + w_ * hw_, - c_ + u_ * hu_ - v_ * hv_ + w_ * hw_)) - { - points.push_back(p); - } - - if (GeometryToolbox::IntersectPlaneAndSegment - (p, normal, d, - c_ - u_ * hu_ + v_ * hv_ + w_ * hw_, - c_ + u_ * hu_ + v_ * hv_ + w_ * hw_)) - { - points.push_back(p); - } - - // Y-aligned edges - if (GeometryToolbox::IntersectPlaneAndSegment - (p, normal, d, - c_ - u_ * hu_ - v_ * hv_ - w_ * hw_, - c_ - u_ * hu_ + v_ * hv_ - w_ * hw_)) - { - points.push_back(p); - } - - if (GeometryToolbox::IntersectPlaneAndSegment - (p, normal, d, - c_ + u_ * hu_ - v_ * hv_ - w_ * hw_, - c_ + u_ * hu_ + v_ * hv_ - w_ * hw_)) - { - points.push_back(p); - } - - if (GeometryToolbox::IntersectPlaneAndSegment - (p, normal, d, - c_ - u_ * hu_ - v_ * hv_ + w_ * hw_, - c_ - u_ * hu_ + v_ * hv_ + w_ * hw_)) - { - points.push_back(p); - } - - if (GeometryToolbox::IntersectPlaneAndSegment - (p, normal, d, - c_ + u_ * hu_ - v_ * hv_ + w_ * hw_, - c_ + u_ * hu_ + v_ * hv_ + w_ * hw_)) - { - points.push_back(p); - } - - // Z-aligned edges - if (GeometryToolbox::IntersectPlaneAndSegment - (p, normal, d, - c_ - u_ * hu_ - v_ * hv_ - w_ * hw_, - c_ - u_ * hu_ - v_ * hv_ + w_ * hw_)) - { - points.push_back(p); - } - - if (GeometryToolbox::IntersectPlaneAndSegment - (p, normal, d, - c_ + u_ * hu_ - v_ * hv_ - w_ * hw_, - c_ + u_ * hu_ - v_ * hv_ + w_ * hw_)) - { - points.push_back(p); - } - - if (GeometryToolbox::IntersectPlaneAndSegment - (p, normal, d, - c_ - u_ * hu_ + v_ * hv_ - w_ * hw_, - c_ - u_ * hu_ + v_ * hv_ + w_ * hw_)) - { - points.push_back(p); - } - - if (GeometryToolbox::IntersectPlaneAndSegment - (p, normal, d, - c_ + u_ * hu_ + v_ * hv_ - w_ * hw_, - c_ + u_ * hu_ + v_ * hv_ + w_ * hw_)) - { - points.push_back(p); - } - - return true; - } - } - - - bool OrientedBoundingBox::HasIntersection(std::vector<Vector>& points, - const CoordinateSystem3D& plane) const - { - // From the vector equation of a 3D plane (specified by origin - // and normal), to the general equation of a 3D plane (which - // looses information about the origin of the coordinate system) - const Vector& normal = plane.GetNormal(); - const Vector& origin = plane.GetOrigin(); - double d = -(normal[0] * origin[0] + normal[1] * origin[1] + normal[2] * origin[2]); - - return HasIntersectionWithPlane(points, normal, d); - } - - - bool OrientedBoundingBox::Contains(const Vector& p) const - { - assert(p.size() == 3); - - const Vector q = p - c_; - - return (fabs(boost::numeric::ublas::inner_prod(q, u_)) <= hu_ && - fabs(boost::numeric::ublas::inner_prod(q, v_)) <= hv_ && - fabs(boost::numeric::ublas::inner_prod(q, w_)) <= hw_); - } - - - void OrientedBoundingBox::FromInternalCoordinates(Vector& target, - double x, - double y, - double z) const - { - target = (c_ + - u_ * 2.0 * hu_ * (x - 0.5) + - v_ * 2.0 * hv_ * (y - 0.5) + - w_ * 2.0 * hw_ * (z - 0.5)); - } - - - void OrientedBoundingBox::FromInternalCoordinates(Vector& target, - const Vector& source) const - { - assert(source.size() == 3); - FromInternalCoordinates(target, source[0], source[1], source[2]); - } - - - void OrientedBoundingBox::ToInternalCoordinates(Vector& target, - const Vector& source) const - { - assert(source.size() == 3); - const Vector q = source - c_; - - double x = boost::numeric::ublas::inner_prod(q, u_) / (2.0 * hu_) + 0.5; - double y = boost::numeric::ublas::inner_prod(q, v_) / (2.0 * hv_) + 0.5; - double z = boost::numeric::ublas::inner_prod(q, w_) / (2.0 * hw_) + 0.5; - - LinearAlgebra::AssignVector(target, x, y, z); - } - - - bool OrientedBoundingBox::ComputeExtent(Extent2D& extent, - const CoordinateSystem3D& plane) const - { - extent.Reset(); - - std::vector<Vector> points; - if (HasIntersection(points, plane)) - { - for (size_t i = 0; i < points.size(); i++) - { - double x, y; - plane.ProjectPoint(x, y, points[i]); - extent.AddPoint(x, y); - } - - return true; - } - else - { - return false; - } - } -}
--- a/Framework/Toolbox/OrientedBoundingBox.h Wed May 22 09:27:21 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 "CoordinateSystem3D.h" -#include "Extent2D.h" -#include "LinearAlgebra.h" -#include "VolumeImageGeometry.h" - -namespace OrthancStone -{ - class OrientedBoundingBox : public boost::noncopyable - { - private: - Vector c_; // center - Vector u_; // normalized width vector - Vector v_; // normalized height vector - Vector w_; // normalized depth vector - double hu_; // half width - double hv_; // half height - double hw_; // half depth - - public: - OrientedBoundingBox(const VolumeImageGeometry& geometry); - - const Vector& GetCenter() const - { - return c_; - } - - bool HasIntersectionWithPlane(std::vector<Vector>& points, - const Vector& normal, - double d) const; - - bool HasIntersection(std::vector<Vector>& points, - const CoordinateSystem3D& plane) const; - - bool Contains(const Vector& p) const; - - void FromInternalCoordinates(Vector& target, - double x, - double y, - double z) const; - - void FromInternalCoordinates(Vector& target, - const Vector& source) const; - - void ToInternalCoordinates(Vector& target, - const Vector& source) const; - - bool ComputeExtent(Extent2D& extent, - const CoordinateSystem3D& plane) const; - }; -} -
--- a/Framework/Toolbox/ParallelSlices.h Wed May 22 09:27:21 2019 +0200 +++ b/Framework/Toolbox/ParallelSlices.h Wed May 22 09:41:03 2019 +0200 @@ -22,7 +22,7 @@ #pragma once #include "CoordinateSystem3D.h" -#include "VolumeImageGeometry.h" +#include "../Volumes/VolumeImageGeometry.h" namespace OrthancStone {
--- a/Framework/Toolbox/VolumeImageGeometry.cpp Wed May 22 09:27:21 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,309 +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 "VolumeImageGeometry.h" - -#include "../Toolbox/GeometryToolbox.h" - -#include <Core/OrthancException.h> - - -namespace OrthancStone -{ - void VolumeImageGeometry::Invalidate() - { - Vector p = (axialGeometry_.GetOrigin() + - static_cast<double>(depth_ - 1) * voxelDimensions_[2] * axialGeometry_.GetNormal()); - - coronalGeometry_ = CoordinateSystem3D(p, - axialGeometry_.GetAxisX(), - -axialGeometry_.GetNormal()); - - sagittalGeometry_ = CoordinateSystem3D(p, - axialGeometry_.GetAxisY(), - axialGeometry_.GetNormal()); - - Vector origin = ( - axialGeometry_.MapSliceToWorldCoordinates(-0.5 * voxelDimensions_[0], - -0.5 * voxelDimensions_[1]) - - 0.5 * voxelDimensions_[2] * axialGeometry_.GetNormal()); - - Vector scaling; - - if (width_ == 0 || - height_ == 0 || - depth_ == 0) - { - LinearAlgebra::AssignVector(scaling, 1, 1, 1); - } - else - { - scaling = ( - axialGeometry_.GetAxisX() * voxelDimensions_[0] * static_cast<double>(width_) + - axialGeometry_.GetAxisY() * voxelDimensions_[1] * static_cast<double>(height_) + - axialGeometry_.GetNormal() * voxelDimensions_[2] * static_cast<double>(depth_)); - } - - transform_ = LinearAlgebra::Product( - GeometryToolbox::CreateTranslationMatrix(origin[0], origin[1], origin[2]), - GeometryToolbox::CreateScalingMatrix(scaling[0], scaling[1], scaling[2])); - - LinearAlgebra::InvertMatrix(transformInverse_, transform_); - } - - - VolumeImageGeometry::VolumeImageGeometry() : - width_(0), - height_(0), - depth_(0) - { - LinearAlgebra::AssignVector(voxelDimensions_, 1, 1, 1); - Invalidate(); - } - - - void VolumeImageGeometry::SetSize(unsigned int width, - unsigned int height, - unsigned int depth) - { - width_ = width; - height_ = height; - depth_ = depth; - Invalidate(); - } - - - void VolumeImageGeometry::SetAxialGeometry(const CoordinateSystem3D& geometry) - { - axialGeometry_ = geometry; - Invalidate(); - } - - - void VolumeImageGeometry::SetVoxelDimensions(double x, - double y, - double z) - { - if (x <= 0 || - y <= 0 || - z <= 0) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - else - { - LinearAlgebra::AssignVector(voxelDimensions_, x, y, z); - Invalidate(); - } - } - - - const CoordinateSystem3D& VolumeImageGeometry::GetProjectionGeometry(VolumeProjection projection) const - { - switch (projection) - { - case VolumeProjection_Axial: - return axialGeometry_; - - case VolumeProjection_Coronal: - return coronalGeometry_; - - case VolumeProjection_Sagittal: - return sagittalGeometry_; - - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - } - - - Vector VolumeImageGeometry::GetVoxelDimensions(VolumeProjection projection) const - { - switch (projection) - { - case VolumeProjection_Axial: - return voxelDimensions_; - - case VolumeProjection_Coronal: - return LinearAlgebra::CreateVector(voxelDimensions_[0], voxelDimensions_[2], voxelDimensions_[1]); - - case VolumeProjection_Sagittal: - return LinearAlgebra::CreateVector(voxelDimensions_[1], voxelDimensions_[2], voxelDimensions_[0]); - - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - } - - - unsigned int VolumeImageGeometry::GetProjectionWidth(VolumeProjection projection) const - { - switch (projection) - { - case VolumeProjection_Axial: - return width_; - - case VolumeProjection_Coronal: - return width_; - - case VolumeProjection_Sagittal: - return height_; - - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - } - - - unsigned int VolumeImageGeometry::GetProjectionHeight(VolumeProjection projection) const - { - switch (projection) - { - case VolumeProjection_Axial: - return height_; - - case VolumeProjection_Coronal: - return depth_; - - case VolumeProjection_Sagittal: - return depth_; - - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - } - - - unsigned int VolumeImageGeometry::GetProjectionDepth(VolumeProjection projection) const - { - switch (projection) - { - case VolumeProjection_Axial: - return depth_; - - case VolumeProjection_Coronal: - return height_; - - case VolumeProjection_Sagittal: - return width_; - - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - } - - - Vector VolumeImageGeometry::GetCoordinates(float x, - float y, - float z) const - { - Vector p = LinearAlgebra::Product(transform_, LinearAlgebra::CreateVector(x, y, z, 1)); - - assert(LinearAlgebra::IsNear(p[3], 1)); // Affine transform, no perspective effect - - // Back to non-homogeneous coordinates - return LinearAlgebra::CreateVector(p[0], p[1], p[2]); - } - - - bool VolumeImageGeometry::DetectProjection(VolumeProjection& projection, - const Vector& planeNormal) const - { - if (GeometryToolbox::IsParallel(planeNormal, axialGeometry_.GetNormal())) - { - projection = VolumeProjection_Axial; - return true; - } - else if (GeometryToolbox::IsParallel(planeNormal, coronalGeometry_.GetNormal())) - { - projection = VolumeProjection_Coronal; - return true; - } - else if (GeometryToolbox::IsParallel(planeNormal, sagittalGeometry_.GetNormal())) - { - projection = VolumeProjection_Sagittal; - return true; - } - else - { - return false; - } - } - - - bool VolumeImageGeometry::DetectSlice(VolumeProjection& projection, - unsigned int& slice, - const CoordinateSystem3D& plane) const - { - if (!DetectProjection(projection, plane.GetNormal())) - { - return false; - } - - // Transforms the coordinates of the origin of the plane, into the - // coordinates of the axial geometry - const Vector& origin = plane.GetOrigin(); - Vector p = LinearAlgebra::Product( - transformInverse_, - LinearAlgebra::CreateVector(origin[0], origin[1], origin[2], 1)); - - assert(LinearAlgebra::IsNear(p[3], 1)); - - double z; - - switch (projection) - { - case VolumeProjection_Axial: - z = p[2]; - break; - - case VolumeProjection_Coronal: - z = p[1]; - break; - - case VolumeProjection_Sagittal: - z = p[0]; - break; - - default: - throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); - } - - const unsigned int projectionDepth = GetProjectionDepth(projection); - - z *= static_cast<double>(projectionDepth); - if (z < 0) - { - return false; - } - - unsigned int d = static_cast<unsigned int>(std::floor(z)); - if (d >= projectionDepth) - { - return false; - } - else - { - slice = d; - return true; - } - } -}
--- a/Framework/Toolbox/VolumeImageGeometry.h Wed May 22 09:27:21 2019 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,122 +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 "../StoneEnumerations.h" -#include "CoordinateSystem3D.h" - -namespace OrthancStone -{ - class VolumeImageGeometry - { - private: - unsigned int width_; - unsigned int height_; - unsigned int depth_; - CoordinateSystem3D axialGeometry_; - CoordinateSystem3D coronalGeometry_; - CoordinateSystem3D sagittalGeometry_; - Vector voxelDimensions_; - Matrix transform_; - Matrix transformInverse_; - - void Invalidate(); - - public: - VolumeImageGeometry(); - - unsigned int GetWidth() const - { - return width_; - } - - unsigned int GetHeight() const - { - return height_; - } - - unsigned int GetDepth() const - { - return depth_; - } - - const CoordinateSystem3D& GetAxialGeometry() const - { - return axialGeometry_; - } - - const CoordinateSystem3D& GetCoronalGeometry() const - { - return coronalGeometry_; - } - - const CoordinateSystem3D& GetSagittalGeometry() const - { - return sagittalGeometry_; - } - - const CoordinateSystem3D& GetProjectionGeometry(VolumeProjection projection) const; - - const Matrix& GetTransform() const - { - return transform_; - } - - const Matrix& GetTransformInverse() const - { - return transformInverse_; - } - - void SetSize(unsigned int width, - unsigned int height, - unsigned int depth); - - // Set the geometry of the first axial slice (i.e. the one whose - // depth == 0) - void SetAxialGeometry(const CoordinateSystem3D& geometry); - - void SetVoxelDimensions(double x, - double y, - double z); - - Vector GetVoxelDimensions(VolumeProjection projection) const; - - unsigned int GetProjectionWidth(VolumeProjection projection) const; - - unsigned int GetProjectionHeight(VolumeProjection projection) const; - - unsigned int GetProjectionDepth(VolumeProjection projection) const; - - // Get the 3D position of a point in the volume, where x, y and z - // lie in the [0;1] range - Vector GetCoordinates(float x, - float y, - float z) const; - - bool DetectProjection(VolumeProjection& projection, - const Vector& planeNormal) const; - - bool DetectSlice(VolumeProjection& projection, - unsigned int& slice, - const CoordinateSystem3D& plane) const; - }; -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Volumes/OrientedVolumeBoundingBox.cpp Wed May 22 09:41:03 2019 +0200 @@ -0,0 +1,268 @@ +/** + * 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 "OrientedVolumeBoundingBox.h" + +#include "../Toolbox/GeometryToolbox.h" +#include "ImageBuffer3D.h" + +#include <Core/OrthancException.h> + +#include <cassert> + +namespace OrthancStone +{ + OrientedVolumeBoundingBox::OrientedVolumeBoundingBox(const VolumeImageGeometry& geometry) + { + unsigned int n = geometry.GetDepth(); + if (n < 1) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_IncompatibleImageSize); + } + + Vector dim = geometry.GetVoxelDimensions(VolumeProjection_Axial); + + u_ = geometry.GetAxialGeometry().GetAxisX(); + v_ = geometry.GetAxialGeometry().GetAxisY(); + w_ = geometry.GetAxialGeometry().GetNormal(); + + hu_ = static_cast<double>(geometry.GetWidth() * dim[0] / 2.0); + hv_ = static_cast<double>(geometry.GetHeight() * dim[1] / 2.0); + hw_ = static_cast<double>(geometry.GetDepth() * dim[2] / 2.0); + + c_ = (geometry.GetAxialGeometry().GetOrigin() + + (hu_ - dim[0] / 2.0) * u_ + + (hv_ - dim[1] / 2.0) * v_ + + (hw_ - dim[2] / 2.0) * w_); + } + + + bool OrientedVolumeBoundingBox::HasIntersectionWithPlane(std::vector<Vector>& points, + const Vector& normal, + double d) const + { + assert(normal.size() == 3); + + double r = (hu_ * fabs(boost::numeric::ublas::inner_prod(normal, u_)) + + hv_ * fabs(boost::numeric::ublas::inner_prod(normal, v_)) + + hw_ * fabs(boost::numeric::ublas::inner_prod(normal, w_))); + + double s = boost::numeric::ublas::inner_prod(normal, c_) + d; + + if (fabs(s) >= r) + { + // No intersection, or intersection is reduced to a single point + return false; + } + else + { + Vector p; + + // Loop over all the 12 edges (segments) of the oriented + // bounding box, and check whether they intersect the plane + + // X-aligned edges + if (GeometryToolbox::IntersectPlaneAndSegment + (p, normal, d, + c_ - u_ * hu_ - v_ * hv_ - w_ * hw_, + c_ + u_ * hu_ - v_ * hv_ - w_ * hw_)) + { + points.push_back(p); + } + + if (GeometryToolbox::IntersectPlaneAndSegment + (p, normal, d, + c_ - u_ * hu_ + v_ * hv_ - w_ * hw_, + c_ + u_ * hu_ + v_ * hv_ - w_ * hw_)) + { + points.push_back(p); + } + + if (GeometryToolbox::IntersectPlaneAndSegment + (p, normal, d, + c_ - u_ * hu_ - v_ * hv_ + w_ * hw_, + c_ + u_ * hu_ - v_ * hv_ + w_ * hw_)) + { + points.push_back(p); + } + + if (GeometryToolbox::IntersectPlaneAndSegment + (p, normal, d, + c_ - u_ * hu_ + v_ * hv_ + w_ * hw_, + c_ + u_ * hu_ + v_ * hv_ + w_ * hw_)) + { + points.push_back(p); + } + + // Y-aligned edges + if (GeometryToolbox::IntersectPlaneAndSegment + (p, normal, d, + c_ - u_ * hu_ - v_ * hv_ - w_ * hw_, + c_ - u_ * hu_ + v_ * hv_ - w_ * hw_)) + { + points.push_back(p); + } + + if (GeometryToolbox::IntersectPlaneAndSegment + (p, normal, d, + c_ + u_ * hu_ - v_ * hv_ - w_ * hw_, + c_ + u_ * hu_ + v_ * hv_ - w_ * hw_)) + { + points.push_back(p); + } + + if (GeometryToolbox::IntersectPlaneAndSegment + (p, normal, d, + c_ - u_ * hu_ - v_ * hv_ + w_ * hw_, + c_ - u_ * hu_ + v_ * hv_ + w_ * hw_)) + { + points.push_back(p); + } + + if (GeometryToolbox::IntersectPlaneAndSegment + (p, normal, d, + c_ + u_ * hu_ - v_ * hv_ + w_ * hw_, + c_ + u_ * hu_ + v_ * hv_ + w_ * hw_)) + { + points.push_back(p); + } + + // Z-aligned edges + if (GeometryToolbox::IntersectPlaneAndSegment + (p, normal, d, + c_ - u_ * hu_ - v_ * hv_ - w_ * hw_, + c_ - u_ * hu_ - v_ * hv_ + w_ * hw_)) + { + points.push_back(p); + } + + if (GeometryToolbox::IntersectPlaneAndSegment + (p, normal, d, + c_ + u_ * hu_ - v_ * hv_ - w_ * hw_, + c_ + u_ * hu_ - v_ * hv_ + w_ * hw_)) + { + points.push_back(p); + } + + if (GeometryToolbox::IntersectPlaneAndSegment + (p, normal, d, + c_ - u_ * hu_ + v_ * hv_ - w_ * hw_, + c_ - u_ * hu_ + v_ * hv_ + w_ * hw_)) + { + points.push_back(p); + } + + if (GeometryToolbox::IntersectPlaneAndSegment + (p, normal, d, + c_ + u_ * hu_ + v_ * hv_ - w_ * hw_, + c_ + u_ * hu_ + v_ * hv_ + w_ * hw_)) + { + points.push_back(p); + } + + return true; + } + } + + + bool OrientedVolumeBoundingBox::HasIntersection(std::vector<Vector>& points, + const CoordinateSystem3D& plane) const + { + // From the vector equation of a 3D plane (specified by origin + // and normal), to the general equation of a 3D plane (which + // looses information about the origin of the coordinate system) + const Vector& normal = plane.GetNormal(); + const Vector& origin = plane.GetOrigin(); + double d = -(normal[0] * origin[0] + normal[1] * origin[1] + normal[2] * origin[2]); + + return HasIntersectionWithPlane(points, normal, d); + } + + + bool OrientedVolumeBoundingBox::Contains(const Vector& p) const + { + assert(p.size() == 3); + + const Vector q = p - c_; + + return (fabs(boost::numeric::ublas::inner_prod(q, u_)) <= hu_ && + fabs(boost::numeric::ublas::inner_prod(q, v_)) <= hv_ && + fabs(boost::numeric::ublas::inner_prod(q, w_)) <= hw_); + } + + + void OrientedVolumeBoundingBox::FromInternalCoordinates(Vector& target, + double x, + double y, + double z) const + { + target = (c_ + + u_ * 2.0 * hu_ * (x - 0.5) + + v_ * 2.0 * hv_ * (y - 0.5) + + w_ * 2.0 * hw_ * (z - 0.5)); + } + + + void OrientedVolumeBoundingBox::FromInternalCoordinates(Vector& target, + const Vector& source) const + { + assert(source.size() == 3); + FromInternalCoordinates(target, source[0], source[1], source[2]); + } + + + void OrientedVolumeBoundingBox::ToInternalCoordinates(Vector& target, + const Vector& source) const + { + assert(source.size() == 3); + const Vector q = source - c_; + + double x = boost::numeric::ublas::inner_prod(q, u_) / (2.0 * hu_) + 0.5; + double y = boost::numeric::ublas::inner_prod(q, v_) / (2.0 * hv_) + 0.5; + double z = boost::numeric::ublas::inner_prod(q, w_) / (2.0 * hw_) + 0.5; + + LinearAlgebra::AssignVector(target, x, y, z); + } + + + bool OrientedVolumeBoundingBox::ComputeExtent(Extent2D& extent, + const CoordinateSystem3D& plane) const + { + extent.Reset(); + + std::vector<Vector> points; + if (HasIntersection(points, plane)) + { + for (size_t i = 0; i < points.size(); i++) + { + double x, y; + plane.ProjectPoint(x, y, points[i]); + extent.AddPoint(x, y); + } + + return true; + } + else + { + return false; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Volumes/OrientedVolumeBoundingBox.h Wed May 22 09:41:03 2019 +0200 @@ -0,0 +1,74 @@ +/** + * 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 "../Toolbox/CoordinateSystem3D.h" +#include "../Toolbox/Extent2D.h" +#include "../Toolbox/LinearAlgebra.h" +#include "VolumeImageGeometry.h" + +namespace OrthancStone +{ + class OrientedVolumeBoundingBox : public boost::noncopyable + { + private: + Vector c_; // center + Vector u_; // normalized width vector + Vector v_; // normalized height vector + Vector w_; // normalized depth vector + double hu_; // half width + double hv_; // half height + double hw_; // half depth + + public: + OrientedVolumeBoundingBox(const VolumeImageGeometry& geometry); + + const Vector& GetCenter() const + { + return c_; + } + + bool HasIntersectionWithPlane(std::vector<Vector>& points, + const Vector& normal, + double d) const; + + bool HasIntersection(std::vector<Vector>& points, + const CoordinateSystem3D& plane) const; + + bool Contains(const Vector& p) const; + + void FromInternalCoordinates(Vector& target, + double x, + double y, + double z) const; + + void FromInternalCoordinates(Vector& target, + const Vector& source) const; + + void ToInternalCoordinates(Vector& target, + const Vector& source) const; + + bool ComputeExtent(Extent2D& extent, + const CoordinateSystem3D& plane) const; + }; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Volumes/VolumeImageGeometry.cpp Wed May 22 09:41:03 2019 +0200 @@ -0,0 +1,309 @@ +/** + * 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 "VolumeImageGeometry.h" + +#include "../Toolbox/GeometryToolbox.h" + +#include <Core/OrthancException.h> + + +namespace OrthancStone +{ + void VolumeImageGeometry::Invalidate() + { + Vector p = (axialGeometry_.GetOrigin() + + static_cast<double>(depth_ - 1) * voxelDimensions_[2] * axialGeometry_.GetNormal()); + + coronalGeometry_ = CoordinateSystem3D(p, + axialGeometry_.GetAxisX(), + -axialGeometry_.GetNormal()); + + sagittalGeometry_ = CoordinateSystem3D(p, + axialGeometry_.GetAxisY(), + axialGeometry_.GetNormal()); + + Vector origin = ( + axialGeometry_.MapSliceToWorldCoordinates(-0.5 * voxelDimensions_[0], + -0.5 * voxelDimensions_[1]) - + 0.5 * voxelDimensions_[2] * axialGeometry_.GetNormal()); + + Vector scaling; + + if (width_ == 0 || + height_ == 0 || + depth_ == 0) + { + LinearAlgebra::AssignVector(scaling, 1, 1, 1); + } + else + { + scaling = ( + axialGeometry_.GetAxisX() * voxelDimensions_[0] * static_cast<double>(width_) + + axialGeometry_.GetAxisY() * voxelDimensions_[1] * static_cast<double>(height_) + + axialGeometry_.GetNormal() * voxelDimensions_[2] * static_cast<double>(depth_)); + } + + transform_ = LinearAlgebra::Product( + GeometryToolbox::CreateTranslationMatrix(origin[0], origin[1], origin[2]), + GeometryToolbox::CreateScalingMatrix(scaling[0], scaling[1], scaling[2])); + + LinearAlgebra::InvertMatrix(transformInverse_, transform_); + } + + + VolumeImageGeometry::VolumeImageGeometry() : + width_(0), + height_(0), + depth_(0) + { + LinearAlgebra::AssignVector(voxelDimensions_, 1, 1, 1); + Invalidate(); + } + + + void VolumeImageGeometry::SetSize(unsigned int width, + unsigned int height, + unsigned int depth) + { + width_ = width; + height_ = height; + depth_ = depth; + Invalidate(); + } + + + void VolumeImageGeometry::SetAxialGeometry(const CoordinateSystem3D& geometry) + { + axialGeometry_ = geometry; + Invalidate(); + } + + + void VolumeImageGeometry::SetVoxelDimensions(double x, + double y, + double z) + { + if (x <= 0 || + y <= 0 || + z <= 0) + { + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + else + { + LinearAlgebra::AssignVector(voxelDimensions_, x, y, z); + Invalidate(); + } + } + + + const CoordinateSystem3D& VolumeImageGeometry::GetProjectionGeometry(VolumeProjection projection) const + { + switch (projection) + { + case VolumeProjection_Axial: + return axialGeometry_; + + case VolumeProjection_Coronal: + return coronalGeometry_; + + case VolumeProjection_Sagittal: + return sagittalGeometry_; + + default: + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + } + + + Vector VolumeImageGeometry::GetVoxelDimensions(VolumeProjection projection) const + { + switch (projection) + { + case VolumeProjection_Axial: + return voxelDimensions_; + + case VolumeProjection_Coronal: + return LinearAlgebra::CreateVector(voxelDimensions_[0], voxelDimensions_[2], voxelDimensions_[1]); + + case VolumeProjection_Sagittal: + return LinearAlgebra::CreateVector(voxelDimensions_[1], voxelDimensions_[2], voxelDimensions_[0]); + + default: + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + } + + + unsigned int VolumeImageGeometry::GetProjectionWidth(VolumeProjection projection) const + { + switch (projection) + { + case VolumeProjection_Axial: + return width_; + + case VolumeProjection_Coronal: + return width_; + + case VolumeProjection_Sagittal: + return height_; + + default: + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + } + + + unsigned int VolumeImageGeometry::GetProjectionHeight(VolumeProjection projection) const + { + switch (projection) + { + case VolumeProjection_Axial: + return height_; + + case VolumeProjection_Coronal: + return depth_; + + case VolumeProjection_Sagittal: + return depth_; + + default: + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + } + + + unsigned int VolumeImageGeometry::GetProjectionDepth(VolumeProjection projection) const + { + switch (projection) + { + case VolumeProjection_Axial: + return depth_; + + case VolumeProjection_Coronal: + return height_; + + case VolumeProjection_Sagittal: + return width_; + + default: + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + } + + + Vector VolumeImageGeometry::GetCoordinates(float x, + float y, + float z) const + { + Vector p = LinearAlgebra::Product(transform_, LinearAlgebra::CreateVector(x, y, z, 1)); + + assert(LinearAlgebra::IsNear(p[3], 1)); // Affine transform, no perspective effect + + // Back to non-homogeneous coordinates + return LinearAlgebra::CreateVector(p[0], p[1], p[2]); + } + + + bool VolumeImageGeometry::DetectProjection(VolumeProjection& projection, + const Vector& planeNormal) const + { + if (GeometryToolbox::IsParallel(planeNormal, axialGeometry_.GetNormal())) + { + projection = VolumeProjection_Axial; + return true; + } + else if (GeometryToolbox::IsParallel(planeNormal, coronalGeometry_.GetNormal())) + { + projection = VolumeProjection_Coronal; + return true; + } + else if (GeometryToolbox::IsParallel(planeNormal, sagittalGeometry_.GetNormal())) + { + projection = VolumeProjection_Sagittal; + return true; + } + else + { + return false; + } + } + + + bool VolumeImageGeometry::DetectSlice(VolumeProjection& projection, + unsigned int& slice, + const CoordinateSystem3D& plane) const + { + if (!DetectProjection(projection, plane.GetNormal())) + { + return false; + } + + // Transforms the coordinates of the origin of the plane, into the + // coordinates of the axial geometry + const Vector& origin = plane.GetOrigin(); + Vector p = LinearAlgebra::Product( + transformInverse_, + LinearAlgebra::CreateVector(origin[0], origin[1], origin[2], 1)); + + assert(LinearAlgebra::IsNear(p[3], 1)); + + double z; + + switch (projection) + { + case VolumeProjection_Axial: + z = p[2]; + break; + + case VolumeProjection_Coronal: + z = p[1]; + break; + + case VolumeProjection_Sagittal: + z = p[0]; + break; + + default: + throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); + } + + const unsigned int projectionDepth = GetProjectionDepth(projection); + + z *= static_cast<double>(projectionDepth); + if (z < 0) + { + return false; + } + + unsigned int d = static_cast<unsigned int>(std::floor(z)); + if (d >= projectionDepth) + { + return false; + } + else + { + slice = d; + return true; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Volumes/VolumeImageGeometry.h Wed May 22 09:41:03 2019 +0200 @@ -0,0 +1,122 @@ +/** + * 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 "../StoneEnumerations.h" +#include "../Toolbox/CoordinateSystem3D.h" + +namespace OrthancStone +{ + class VolumeImageGeometry + { + private: + unsigned int width_; + unsigned int height_; + unsigned int depth_; + CoordinateSystem3D axialGeometry_; + CoordinateSystem3D coronalGeometry_; + CoordinateSystem3D sagittalGeometry_; + Vector voxelDimensions_; + Matrix transform_; + Matrix transformInverse_; + + void Invalidate(); + + public: + VolumeImageGeometry(); + + unsigned int GetWidth() const + { + return width_; + } + + unsigned int GetHeight() const + { + return height_; + } + + unsigned int GetDepth() const + { + return depth_; + } + + const CoordinateSystem3D& GetAxialGeometry() const + { + return axialGeometry_; + } + + const CoordinateSystem3D& GetCoronalGeometry() const + { + return coronalGeometry_; + } + + const CoordinateSystem3D& GetSagittalGeometry() const + { + return sagittalGeometry_; + } + + const CoordinateSystem3D& GetProjectionGeometry(VolumeProjection projection) const; + + const Matrix& GetTransform() const + { + return transform_; + } + + const Matrix& GetTransformInverse() const + { + return transformInverse_; + } + + void SetSize(unsigned int width, + unsigned int height, + unsigned int depth); + + // Set the geometry of the first axial slice (i.e. the one whose + // depth == 0) + void SetAxialGeometry(const CoordinateSystem3D& geometry); + + void SetVoxelDimensions(double x, + double y, + double z); + + Vector GetVoxelDimensions(VolumeProjection projection) const; + + unsigned int GetProjectionWidth(VolumeProjection projection) const; + + unsigned int GetProjectionHeight(VolumeProjection projection) const; + + unsigned int GetProjectionDepth(VolumeProjection projection) const; + + // Get the 3D position of a point in the volume, where x, y and z + // lie in the [0;1] range + Vector GetCoordinates(float x, + float y, + float z) const; + + bool DetectProjection(VolumeProjection& projection, + const Vector& planeNormal) const; + + bool DetectSlice(VolumeProjection& projection, + unsigned int& slice, + const CoordinateSystem3D& plane) const; + }; +}
--- a/Framework/Volumes/VolumeReslicer.cpp Wed May 22 09:27:21 2019 +0200 +++ b/Framework/Volumes/VolumeReslicer.cpp Wed May 22 09:41:03 2019 +0200 @@ -230,7 +230,7 @@ FastRowIterator(const Orthanc::ImageAccessor& slice, const Extent2D& extent, const CoordinateSystem3D& plane, - const OrientedBoundingBox& box, + const OrientedVolumeBoundingBox& box, unsigned int y) { const double width = static_cast<double>(slice.GetWidth()); @@ -285,7 +285,7 @@ const Orthanc::ImageAccessor& slice_; const Extent2D& extent_; const CoordinateSystem3D& plane_; - const OrientedBoundingBox& box_; + const OrientedVolumeBoundingBox& box_; unsigned int x_; unsigned int y_; @@ -293,7 +293,7 @@ SlowRowIterator(const Orthanc::ImageAccessor& slice, const Extent2D& extent, const CoordinateSystem3D& plane, - const OrientedBoundingBox& box, + const OrientedVolumeBoundingBox& box, unsigned int y) : slice_(slice), extent_(extent), @@ -342,7 +342,7 @@ const Extent2D& extent, const ImageBuffer3D& source, const CoordinateSystem3D& plane, - const OrientedBoundingBox& box, + const OrientedVolumeBoundingBox& box, float scaling, float offset) { @@ -386,7 +386,7 @@ const Extent2D& extent, const ImageBuffer3D& source, const CoordinateSystem3D& plane, - const OrientedBoundingBox& box, + const OrientedVolumeBoundingBox& box, ImageInterpolation interpolation, bool hasLinearFunction, float scaling, @@ -452,7 +452,7 @@ const Extent2D& extent, const ImageBuffer3D& source, const CoordinateSystem3D& plane, - const OrientedBoundingBox& box, + const OrientedVolumeBoundingBox& box, ImageInterpolation interpolation, bool hasLinearFunction, float scaling, @@ -501,7 +501,7 @@ void VolumeReslicer::CheckIterators(const ImageBuffer3D& source, const CoordinateSystem3D& plane, - const OrientedBoundingBox& box) const + const OrientedVolumeBoundingBox& box) const { for (unsigned int y = 0; y < slice_->GetHeight(); y++) { @@ -785,7 +785,7 @@ // to 6 vertices. We compute the extent of the intersection // polygon, with respect to the coordinate system of the reslicing // plane. - OrientedBoundingBox box(geometry); + OrientedVolumeBoundingBox box(geometry); if (!box.ComputeExtent(extent_, plane)) {
--- a/Framework/Volumes/VolumeReslicer.h Wed May 22 09:27:21 2019 +0200 +++ b/Framework/Volumes/VolumeReslicer.h Wed May 22 09:41:03 2019 +0200 @@ -22,7 +22,7 @@ #pragma once #include "../Toolbox/Extent2D.h" -#include "../Toolbox/OrientedBoundingBox.h" +#include "OrientedVolumeBoundingBox.h" #include "ImageBuffer3D.h" namespace OrthancStone @@ -46,7 +46,7 @@ void CheckIterators(const ImageBuffer3D& source, const CoordinateSystem3D& plane, - const OrientedBoundingBox& box) const; + const OrientedVolumeBoundingBox& box) const; void Reset();
--- a/Resources/CMake/OrthancStoneConfiguration.cmake Wed May 22 09:27:21 2019 +0200 +++ b/Resources/CMake/OrthancStoneConfiguration.cmake Wed May 22 09:41:03 2019 +0200 @@ -409,8 +409,8 @@ ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/OneGesturePointerTracker.h ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/PointerTypes.h ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/ViewportController.cpp - ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/ViewportController.h - + ${ORTHANC_STONE_ROOT}/Framework/Scene2DViewport/ViewportController.h + ${ORTHANC_STONE_ROOT}/Framework/Fonts/FontRenderer.cpp ${ORTHANC_STONE_ROOT}/Framework/Fonts/Glyph.cpp ${ORTHANC_STONE_ROOT}/Framework/Fonts/GlyphAlphabet.cpp @@ -448,17 +448,16 @@ ${ORTHANC_STONE_ROOT}/Framework/Toolbox/ImageGeometry.cpp ${ORTHANC_STONE_ROOT}/Framework/Toolbox/LinearAlgebra.cpp ${ORTHANC_STONE_ROOT}/Framework/Toolbox/MessagingToolbox.cpp - ${ORTHANC_STONE_ROOT}/Framework/Toolbox/OrientedBoundingBox.cpp - ${ORTHANC_STONE_ROOT}/Framework/Toolbox/ParallelSlices.cpp ${ORTHANC_STONE_ROOT}/Framework/Toolbox/ParallelSlicesCursor.cpp ${ORTHANC_STONE_ROOT}/Framework/Toolbox/ShearWarpProjectiveTransform.cpp ${ORTHANC_STONE_ROOT}/Framework/Toolbox/SlicesSorter.cpp ${ORTHANC_STONE_ROOT}/Framework/Toolbox/UndoRedoStack.cpp - ${ORTHANC_STONE_ROOT}/Framework/Toolbox/VolumeImageGeometry.cpp ${ORTHANC_STONE_ROOT}/Framework/Viewport/CairoContext.cpp ${ORTHANC_STONE_ROOT}/Framework/Viewport/CairoSurface.cpp ${ORTHANC_STONE_ROOT}/Framework/Volumes/ImageBuffer3D.cpp + ${ORTHANC_STONE_ROOT}/Framework/Volumes/OrientedVolumeBoundingBox.cpp + ${ORTHANC_STONE_ROOT}/Framework/Volumes/VolumeImageGeometry.cpp ${ORTHANC_STONE_ROOT}/Framework/Volumes/VolumeReslicer.cpp ${ORTHANC_STONE_ROOT}/Framework/Messages/ICallable.h
--- a/Samples/Sdl/Loader.cpp Wed May 22 09:27:21 2019 +0200 +++ b/Samples/Sdl/Loader.cpp Wed May 22 09:41:03 2019 +0200 @@ -31,8 +31,8 @@ #include "../../Framework/StoneInitialization.h" #include "../../Framework/Toolbox/GeometryToolbox.h" #include "../../Framework/Toolbox/SlicesSorter.h" -#include "../../Framework/Toolbox/VolumeImageGeometry.h" #include "../../Framework/Volumes/ImageBuffer3D.h" +#include "../../Framework/Volumes/VolumeImageGeometry.h" // From Orthanc framework #include <Core/Compression/GzipCompressor.h>