Mercurial > hg > orthanc-stone
comparison Framework/Volumes/ImageBuffer3D.cpp @ 683:dbc1d8bfc68a
reorganizing ImageBuffer3D
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 16 May 2019 16:01:36 +0200 |
parents | e9339f2b5de7 |
children | 7719eb852dd5 |
comparison
equal
deleted
inserted
replaced
681:9723fceccb9f | 683:dbc1d8bfc68a |
---|---|
19 **/ | 19 **/ |
20 | 20 |
21 | 21 |
22 #include "ImageBuffer3D.h" | 22 #include "ImageBuffer3D.h" |
23 | 23 |
24 #include "../Toolbox/GeometryToolbox.h" | |
25 | |
24 #include <Core/Images/ImageProcessing.h> | 26 #include <Core/Images/ImageProcessing.h> |
25 #include <Core/Logging.h> | 27 #include <Core/Logging.h> |
26 #include <Core/OrthancException.h> | 28 #include <Core/OrthancException.h> |
27 | 29 |
28 #include <string.h> | 30 #include <string.h> |
119 LinearAlgebra::AssignVector(voxelDimensions_, 1, 1, 1); | 121 LinearAlgebra::AssignVector(voxelDimensions_, 1, 1, 1); |
120 | 122 |
121 LOG(INFO) << "Created a 3D image of size " << width << "x" << height | 123 LOG(INFO) << "Created a 3D image of size " << width << "x" << height |
122 << "x" << depth << " in " << Orthanc::EnumerationToString(format) | 124 << "x" << depth << " in " << Orthanc::EnumerationToString(format) |
123 << " (" << (GetEstimatedMemorySize() / (1024ll * 1024ll)) << "MB)"; | 125 << " (" << (GetEstimatedMemorySize() / (1024ll * 1024ll)) << "MB)"; |
126 | |
127 UpdateGeometry(); | |
124 } | 128 } |
125 | 129 |
126 | 130 |
127 void ImageBuffer3D::Clear() | 131 void ImageBuffer3D::Clear() |
128 { | 132 { |
131 | 135 |
132 | 136 |
133 void ImageBuffer3D::SetAxialGeometry(const CoordinateSystem3D& geometry) | 137 void ImageBuffer3D::SetAxialGeometry(const CoordinateSystem3D& geometry) |
134 { | 138 { |
135 axialGeometry_ = geometry; | 139 axialGeometry_ = geometry; |
140 UpdateGeometry(); | |
136 } | 141 } |
137 | 142 |
138 | 143 |
139 void ImageBuffer3D::SetVoxelDimensions(double x, | 144 void ImageBuffer3D::SetVoxelDimensions(double x, |
140 double y, | 145 double y, |
144 y <= 0 || | 149 y <= 0 || |
145 z <= 0) | 150 z <= 0) |
146 { | 151 { |
147 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | 152 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); |
148 } | 153 } |
149 | 154 else |
150 { | 155 { |
151 LinearAlgebra::AssignVector(voxelDimensions_, x, y, z); | 156 LinearAlgebra::AssignVector(voxelDimensions_, x, y, z); |
157 UpdateGeometry(); | |
152 } | 158 } |
153 } | 159 } |
154 | 160 |
155 | 161 |
156 Vector ImageBuffer3D::GetVoxelDimensions(VolumeProjection projection) const | 162 Vector ImageBuffer3D::GetVoxelDimensions(VolumeProjection projection) const |
157 { | 163 { |
158 Vector result; | |
159 switch (projection) | 164 switch (projection) |
160 { | 165 { |
161 case VolumeProjection_Axial: | 166 case VolumeProjection_Axial: |
162 result = voxelDimensions_; | 167 return voxelDimensions_; |
163 break; | |
164 | 168 |
165 case VolumeProjection_Coronal: | 169 case VolumeProjection_Coronal: |
166 LinearAlgebra::AssignVector(result, voxelDimensions_[0], voxelDimensions_[2], voxelDimensions_[1]); | 170 return LinearAlgebra::CreateVector(voxelDimensions_[0], voxelDimensions_[2], voxelDimensions_[1]); |
167 break; | |
168 | 171 |
169 case VolumeProjection_Sagittal: | 172 case VolumeProjection_Sagittal: |
170 LinearAlgebra::AssignVector(result, voxelDimensions_[1], voxelDimensions_[2], voxelDimensions_[0]); | 173 return LinearAlgebra::CreateVector(voxelDimensions_[1], voxelDimensions_[2], voxelDimensions_[0]); |
171 break; | |
172 | 174 |
173 default: | 175 default: |
174 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | 176 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); |
175 } | 177 } |
176 | |
177 return result; | |
178 } | 178 } |
179 | 179 |
180 | 180 |
181 void ImageBuffer3D::GetSliceSize(unsigned int& width, | 181 void ImageBuffer3D::GetSliceSize(unsigned int& width, |
182 unsigned int& height, | 182 unsigned int& height, |
457 const void* p = image_.GetConstRow(y + height_ * (depth_ - 1 - z)); | 457 const void* p = image_.GetConstRow(y + height_ * (depth_ - 1 - z)); |
458 return reinterpret_cast<const uint16_t*>(p) [x]; | 458 return reinterpret_cast<const uint16_t*>(p) [x]; |
459 } | 459 } |
460 | 460 |
461 | 461 |
462 void ImageBuffer3D::UpdateGeometry() | |
463 { | |
464 Vector p = (axialGeometry_.GetOrigin() + | |
465 static_cast<double>(depth_ - 1) * voxelDimensions_[2] * axialGeometry_.GetNormal()); | |
466 | |
467 coronalGeometry_ = CoordinateSystem3D(p, | |
468 axialGeometry_.GetAxisX(), | |
469 -axialGeometry_.GetNormal()); | |
470 | |
471 sagittalGeometry_ = CoordinateSystem3D(p, | |
472 axialGeometry_.GetAxisY(), | |
473 -axialGeometry_.GetNormal()); | |
474 | |
475 Vector origin = ( | |
476 axialGeometry_.MapSliceToWorldCoordinates(-0.5 * voxelDimensions_[0], | |
477 -0.5 * voxelDimensions_[1]) - | |
478 0.5 * voxelDimensions_[2] * axialGeometry_.GetNormal()); | |
479 | |
480 Vector scaling = ( | |
481 axialGeometry_.GetAxisX() * voxelDimensions_[0] * static_cast<double>(width_) + | |
482 axialGeometry_.GetAxisY() * voxelDimensions_[1] * static_cast<double>(height_) + | |
483 axialGeometry_.GetNormal() * voxelDimensions_[2] * static_cast<double>(depth_)); | |
484 | |
485 transform_ = LinearAlgebra::Product( | |
486 GeometryToolbox::CreateTranslationMatrix(origin[0], origin[1], origin[2]), | |
487 GeometryToolbox::CreateScalingMatrix(scaling[0], scaling[1], scaling[2])); | |
488 | |
489 LinearAlgebra::InvertMatrix(transformInverse_, transform_); | |
490 } | |
491 | |
492 | |
462 Vector ImageBuffer3D::GetCoordinates(float x, | 493 Vector ImageBuffer3D::GetCoordinates(float x, |
463 float y, | 494 float y, |
464 float z) const | 495 float z) const |
465 { | 496 { |
466 Vector ps = GetVoxelDimensions(OrthancStone::VolumeProjection_Axial); | 497 Vector p = LinearAlgebra::Product(transform_, LinearAlgebra::CreateVector(x, y, z, 1)); |
467 | 498 |
468 const CoordinateSystem3D& axial = GetAxialGeometry(); | 499 assert(LinearAlgebra::IsNear(p[3], 1)); // Affine transform, no perspective effect |
469 | 500 |
470 Vector origin = (axial.MapSliceToWorldCoordinates(-0.5 * ps[0], -0.5 * ps[1]) - | 501 // Back to non-homogeneous coordinates |
471 0.5 * ps[2] * axial.GetNormal()); | 502 return LinearAlgebra::CreateVector(p[0], p[1], p[2]); |
472 | 503 } |
473 return (origin + | 504 |
474 axial.GetAxisX() * ps[0] * x * static_cast<double>(GetWidth()) + | 505 |
475 axial.GetAxisY() * ps[1] * y * static_cast<double>(GetHeight()) + | 506 bool ImageBuffer3D::DetectProjection(VolumeProjection& projection, |
476 axial.GetNormal() * ps[2] * z * static_cast<double>(GetDepth())); | 507 const CoordinateSystem3D& plane) const |
508 { | |
509 if (GeometryToolbox::IsParallel(plane.GetNormal(), | |
510 axialGeometry_.GetNormal())) | |
511 { | |
512 projection = VolumeProjection_Axial; | |
513 return true; | |
514 } | |
515 | |
516 { | |
517 if (GeometryToolbox::IsParallel(plane.GetNormal(), | |
518 coronalGeometry_.GetNormal())) | |
519 { | |
520 projection = VolumeProjection_Coronal; | |
521 return true; | |
522 } | |
523 } | |
524 | |
525 { | |
526 if (GeometryToolbox::IsParallel(plane.GetNormal(), | |
527 sagittalGeometry_.GetNormal())) | |
528 { | |
529 projection = VolumeProjection_Sagittal; | |
530 return true; | |
531 } | |
532 } | |
533 | |
534 return false; | |
477 } | 535 } |
478 } | 536 } |