Mercurial > hg > orthanc-stone
comparison Framework/Radiography/RadiographyScene.cpp @ 409:99c9b3238008
AffineTransform2D
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 12 Nov 2018 15:38:11 +0100 |
parents | 6834c236b36d |
children | 6decc0ba9da5 |
comparison
equal
deleted
inserted
replaced
408:6834c236b36d | 409:99c9b3238008 |
---|---|
41 { | 41 { |
42 return x * x; | 42 return x * x; |
43 } | 43 } |
44 | 44 |
45 | 45 |
46 static Matrix CreateOffsetMatrix(double dx, | |
47 double dy) | |
48 { | |
49 Matrix m = LinearAlgebra::IdentityMatrix(3); | |
50 m(0, 2) = dx; | |
51 m(1, 2) = dy; | |
52 return m; | |
53 } | |
54 | |
55 | |
56 static Matrix CreateScalingMatrix(double sx, | |
57 double sy) | |
58 { | |
59 Matrix m = LinearAlgebra::IdentityMatrix(3); | |
60 m(0, 0) = sx; | |
61 m(1, 1) = sy; | |
62 return m; | |
63 } | |
64 | |
65 | |
66 static Matrix CreateRotationMatrix(double angle) | |
67 { | |
68 Matrix m; | |
69 const double v[] = { cos(angle), -sin(angle), 0, | |
70 sin(angle), cos(angle), 0, | |
71 0, 0, 1 }; | |
72 LinearAlgebra::FillMatrix(m, 3, 3, v); | |
73 return m; | |
74 } | |
75 | |
76 | |
77 static void ApplyTransform(double& x /* inout */, | |
78 double& y /* inout */, | |
79 const Matrix& transform) | |
80 { | |
81 Vector p; | |
82 LinearAlgebra::AssignVector(p, x, y, 1); | |
83 | |
84 Vector q = LinearAlgebra::Product(transform, p); | |
85 | |
86 if (!LinearAlgebra::IsNear(q[2], 1.0)) | |
87 { | |
88 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); | |
89 } | |
90 else | |
91 { | |
92 x = q[0]; | |
93 y = q[1]; | |
94 } | |
95 } | |
96 | |
97 | |
98 | |
99 void RadiographyScene::Layer::UpdateTransform() | 46 void RadiographyScene::Layer::UpdateTransform() |
100 { | 47 { |
101 transform_ = CreateScalingMatrix(pixelSpacingX_, pixelSpacingY_); | 48 transform_ = AffineTransform2D::CreateScaling(pixelSpacingX_, pixelSpacingY_); |
102 | 49 |
103 double centerX, centerY; | 50 double centerX, centerY; |
104 GetCenter(centerX, centerY); | 51 GetCenter(centerX, centerY); |
105 | 52 |
106 transform_ = LinearAlgebra::Product( | 53 transform_ = AffineTransform2D::Combine( |
107 CreateOffsetMatrix(panX_ + centerX, panY_ + centerY), | 54 AffineTransform2D::CreateOffset(panX_ + centerX, panY_ + centerY), |
108 CreateRotationMatrix(angle_), | 55 AffineTransform2D::CreateRotation(angle_), |
109 CreateOffsetMatrix(-centerX, -centerY), | 56 AffineTransform2D::CreateOffset(-centerX, -centerY), |
110 transform_); | 57 transform_); |
111 | 58 |
112 LinearAlgebra::InvertMatrix(transformInverse_, transform_); | 59 transformInverse_ = AffineTransform2D::Invert(transform_); |
113 } | 60 } |
114 | 61 |
115 | 62 |
116 void RadiographyScene::Layer::AddToExtent(Extent2D& extent, | 63 void RadiographyScene::Layer::AddToExtent(Extent2D& extent, |
117 double x, | 64 double x, |
118 double y) const | 65 double y) const |
119 { | 66 { |
120 ApplyTransform(x, y, transform_); | 67 transform_.Apply(x, y); |
121 extent.AddPoint(x, y); | 68 extent.AddPoint(x, y); |
122 } | 69 } |
123 | 70 |
124 | 71 |
125 void RadiographyScene::Layer::GetCornerInternal(double& x, | 72 void RadiographyScene::Layer::GetCornerInternal(double& x, |
159 | 106 |
160 default: | 107 default: |
161 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | 108 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); |
162 } | 109 } |
163 | 110 |
164 ApplyTransform(x, y, transform_); | 111 transform_.Apply(x, y); |
165 } | 112 } |
166 | 113 |
167 | 114 |
168 bool RadiographyScene::Layer::Contains(double x, | 115 bool RadiographyScene::Layer::Contains(double x, |
169 double y) const | 116 double y) const |
170 { | 117 { |
171 ApplyTransform(x, y, transformInverse_); | 118 transformInverse_.Apply(x, y); |
172 | 119 |
173 unsigned int cropX, cropY, cropWidth, cropHeight; | 120 unsigned int cropX, cropY, cropWidth, cropHeight; |
174 GetCrop(cropX, cropY, cropWidth, cropHeight); | 121 GetCrop(cropX, cropY, cropWidth, cropHeight); |
175 | 122 |
176 return (x >= cropX && x <= cropX + cropWidth && | 123 return (x >= cropX && x <= cropX + cropWidth && |
193 cairo_set_line_width(cr, 2.0 / zoom); | 140 cairo_set_line_width(cr, 2.0 / zoom); |
194 | 141 |
195 double x, y; | 142 double x, y; |
196 x = dx; | 143 x = dx; |
197 y = dy; | 144 y = dy; |
198 ApplyTransform(x, y, transform_); | 145 transform_.Apply(x, y); |
199 cairo_move_to(cr, x, y); | 146 cairo_move_to(cr, x, y); |
200 | 147 |
201 x = dx + dwidth; | 148 x = dx + dwidth; |
202 y = dy; | 149 y = dy; |
203 ApplyTransform(x, y, transform_); | 150 transform_.Apply(x, y); |
204 cairo_line_to(cr, x, y); | 151 cairo_line_to(cr, x, y); |
205 | 152 |
206 x = dx + dwidth; | 153 x = dx + dwidth; |
207 y = dy + dheight; | 154 y = dy + dheight; |
208 ApplyTransform(x, y, transform_); | 155 transform_.Apply(x, y); |
209 cairo_line_to(cr, x, y); | 156 cairo_line_to(cr, x, y); |
210 | 157 |
211 x = dx; | 158 x = dx; |
212 y = dy + dheight; | 159 y = dy + dheight; |
213 ApplyTransform(x, y, transform_); | 160 transform_.Apply(x, y); |
214 cairo_line_to(cr, x, y); | 161 cairo_line_to(cr, x, y); |
215 | 162 |
216 x = dx; | 163 x = dx; |
217 y = dy; | 164 y = dy; |
218 ApplyTransform(x, y, transform_); | 165 transform_.Apply(x, y); |
219 cairo_line_to(cr, x, y); | 166 cairo_line_to(cr, x, y); |
220 | 167 |
221 cairo_stroke(cr); | 168 cairo_stroke(cr); |
222 } | 169 } |
223 | 170 |
343 { | 290 { |
344 return false; | 291 return false; |
345 } | 292 } |
346 else | 293 else |
347 { | 294 { |
348 ApplyTransform(sceneX, sceneY, transformInverse_); | 295 transformInverse_.Apply(sceneX, sceneY); |
349 | 296 |
350 int x = static_cast<int>(std::floor(sceneX)); | 297 int x = static_cast<int>(std::floor(sceneX)); |
351 int y = static_cast<int>(std::floor(sceneY)); | 298 int y = static_cast<int>(std::floor(sceneY)); |
352 | 299 |
353 if (x < 0) | 300 if (x < 0) |
402 void RadiographyScene::Layer::GetCenter(double& centerX, | 349 void RadiographyScene::Layer::GetCenter(double& centerX, |
403 double& centerY) const | 350 double& centerY) const |
404 { | 351 { |
405 centerX = static_cast<double>(width_) / 2.0; | 352 centerX = static_cast<double>(width_) / 2.0; |
406 centerY = static_cast<double>(height_) / 2.0; | 353 centerY = static_cast<double>(height_) / 2.0; |
407 ApplyTransform(centerX, centerY, transform_); | 354 transform_.Apply(centerX, centerY); |
408 } | 355 } |
409 | 356 |
410 | 357 |
411 void RadiographyScene::Layer::GetCorner(double& x /* out */, | 358 void RadiographyScene::Layer::GetCorner(double& x /* out */, |
412 double& y /* out */, | 359 double& y /* out */, |
596 return false; | 543 return false; |
597 } | 544 } |
598 | 545 |
599 | 546 |
600 virtual void Render(Orthanc::ImageAccessor& buffer, | 547 virtual void Render(Orthanc::ImageAccessor& buffer, |
601 const Matrix& viewTransform, | 548 const AffineTransform2D& viewTransform, |
602 ImageInterpolation interpolation) const | 549 ImageInterpolation interpolation) const |
603 { | 550 { |
604 if (alpha_.get() == NULL) | 551 if (alpha_.get() == NULL) |
605 { | 552 { |
606 return; | 553 return; |
612 } | 559 } |
613 | 560 |
614 unsigned int cropX, cropY, cropWidth, cropHeight; | 561 unsigned int cropX, cropY, cropWidth, cropHeight; |
615 GetCrop(cropX, cropY, cropWidth, cropHeight); | 562 GetCrop(cropX, cropY, cropWidth, cropHeight); |
616 | 563 |
617 Matrix m = LinearAlgebra::Product(viewTransform, | 564 const AffineTransform2D t = AffineTransform2D::Combine( |
618 GetTransform(), | 565 viewTransform, GetTransform(), |
619 CreateOffsetMatrix(cropX, cropY)); | 566 AffineTransform2D::CreateOffset(cropX, cropY)); |
620 | 567 |
621 Orthanc::ImageAccessor cropped; | 568 Orthanc::ImageAccessor cropped; |
622 alpha_->GetRegion(cropped, cropX, cropY, cropWidth, cropHeight); | 569 alpha_->GetRegion(cropped, cropX, cropY, cropWidth, cropHeight); |
623 | 570 |
624 Orthanc::Image tmp(Orthanc::PixelFormat_Grayscale8, buffer.GetWidth(), buffer.GetHeight(), false); | 571 Orthanc::Image tmp(Orthanc::PixelFormat_Grayscale8, buffer.GetWidth(), buffer.GetHeight(), false); |
625 ApplyProjectiveTransform(tmp, cropped, m, interpolation, true /* clear */); | 572 |
573 t.Apply(tmp, cropped, interpolation, true /* clear */); | |
626 | 574 |
627 // Blit | 575 // Blit |
628 const unsigned int width = buffer.GetWidth(); | 576 const unsigned int width = buffer.GetWidth(); |
629 const unsigned int height = buffer.GetHeight(); | 577 const unsigned int height = buffer.GetHeight(); |
630 | 578 |
754 ApplyConverter(); | 702 ApplyConverter(); |
755 } | 703 } |
756 | 704 |
757 | 705 |
758 virtual void Render(Orthanc::ImageAccessor& buffer, | 706 virtual void Render(Orthanc::ImageAccessor& buffer, |
759 const Matrix& viewTransform, | 707 const AffineTransform2D& viewTransform, |
760 ImageInterpolation interpolation) const | 708 ImageInterpolation interpolation) const |
761 { | 709 { |
762 if (converted_.get() != NULL) | 710 if (converted_.get() != NULL) |
763 { | 711 { |
764 if (converted_->GetFormat() != Orthanc::PixelFormat_Float32) | 712 if (converted_->GetFormat() != Orthanc::PixelFormat_Float32) |
767 } | 715 } |
768 | 716 |
769 unsigned int cropX, cropY, cropWidth, cropHeight; | 717 unsigned int cropX, cropY, cropWidth, cropHeight; |
770 GetCrop(cropX, cropY, cropWidth, cropHeight); | 718 GetCrop(cropX, cropY, cropWidth, cropHeight); |
771 | 719 |
772 Matrix m = LinearAlgebra::Product(viewTransform, | 720 AffineTransform2D t = AffineTransform2D::Combine( |
773 GetTransform(), | 721 viewTransform, GetTransform(), |
774 CreateOffsetMatrix(cropX, cropY)); | 722 AffineTransform2D::CreateOffset(cropX, cropY)); |
775 | 723 |
776 Orthanc::ImageAccessor cropped; | 724 Orthanc::ImageAccessor cropped; |
777 converted_->GetRegion(cropped, cropX, cropY, cropWidth, cropHeight); | 725 converted_->GetRegion(cropped, cropX, cropY, cropWidth, cropHeight); |
778 | 726 |
779 ApplyProjectiveTransform(buffer, cropped, m, interpolation, false); | 727 t.Apply(buffer, cropped, interpolation, false); |
780 } | 728 } |
781 } | 729 } |
782 | 730 |
783 | 731 |
784 virtual bool GetDefaultWindowing(float& center, | 732 virtual bool GetDefaultWindowing(float& center, |
1050 return extent; | 998 return extent; |
1051 } | 999 } |
1052 | 1000 |
1053 | 1001 |
1054 void RadiographyScene::Render(Orthanc::ImageAccessor& buffer, | 1002 void RadiographyScene::Render(Orthanc::ImageAccessor& buffer, |
1055 const Matrix& viewTransform, | 1003 const AffineTransform2D& viewTransform, |
1056 ImageInterpolation interpolation) const | 1004 ImageInterpolation interpolation) const |
1057 { | 1005 { |
1058 Orthanc::ImageProcessing::Set(buffer, 0); | 1006 Orthanc::ImageProcessing::Set(buffer, 0); |
1059 | 1007 |
1060 // Render layers in the background-to-foreground order | 1008 // Render layers in the background-to-foreground order |
1171 | 1119 |
1172 Orthanc::Image layers(Orthanc::PixelFormat_Float32, | 1120 Orthanc::Image layers(Orthanc::PixelFormat_Float32, |
1173 static_cast<unsigned int>(w), | 1121 static_cast<unsigned int>(w), |
1174 static_cast<unsigned int>(h), false); | 1122 static_cast<unsigned int>(h), false); |
1175 | 1123 |
1176 Matrix view = LinearAlgebra::Product( | 1124 AffineTransform2D view = AffineTransform2D::Combine( |
1177 CreateScalingMatrix(1.0 / pixelSpacingX, 1.0 / pixelSpacingY), | 1125 AffineTransform2D::CreateScaling(1.0 / pixelSpacingX, 1.0 / pixelSpacingY), |
1178 CreateOffsetMatrix(-extent.GetX1(), -extent.GetY1())); | 1126 AffineTransform2D::CreateOffset(-extent.GetX1(), -extent.GetY1())); |
1179 | 1127 |
1180 Render(layers, view, interpolation); | 1128 Render(layers, view, interpolation); |
1181 | 1129 |
1182 Orthanc::Image rendered(Orthanc::PixelFormat_Grayscale16, | 1130 Orthanc::Image rendered(Orthanc::PixelFormat_Grayscale16, |
1183 layers.GetWidth(), layers.GetHeight(), false); | 1131 layers.GetWidth(), layers.GetHeight(), false); |