00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "mitkDisplayGeometry.h"
00020
00021 mitk::AffineGeometryFrame3D::Pointer mitk::DisplayGeometry::Clone() const
00022 {
00023 itkExceptionMacro(<<"calling mitk::DisplayGeometry::Clone does not make much sense.");
00024 }
00025
00026 bool mitk::DisplayGeometry::IsValid() const
00027 {
00028 return m_Valid && m_WorldGeometry.IsNotNull() && m_WorldGeometry->IsValid();
00029 }
00030
00031 unsigned long mitk::DisplayGeometry::GetMTime() const
00032 {
00033 if((m_WorldGeometry.IsNotNull()) && (Geometry2D::GetMTime() < m_WorldGeometry->GetMTime()))
00034 {
00035 Modified();
00036 }
00037 return Geometry2D::GetMTime();
00038 }
00039
00040 const mitk::TimeBounds& mitk::DisplayGeometry::GetTimeBounds() const
00041 {
00042 if(m_WorldGeometry.IsNull())
00043 {
00044 return m_TimeBounds;
00045 }
00046
00047 return m_WorldGeometry->GetTimeBounds();
00048 }
00049
00050
00051
00052
00053
00054
00055
00056
00057 void mitk::DisplayGeometry::SetWorldGeometry(const Geometry2D* aWorldGeometry)
00058 {
00059 m_WorldGeometry = aWorldGeometry;
00060
00061 Modified();
00062 }
00063
00064 bool mitk::DisplayGeometry::SetOriginInMM(const Vector2D& origin_mm)
00065 {
00066 m_OriginInMM = origin_mm;
00067 WorldToDisplay(m_OriginInMM, m_OriginInDisplayUnits);
00068
00069 Modified();
00070
00071 return !this->RefitVisibleRect();
00072 }
00073
00074 mitk::Vector2D mitk::DisplayGeometry::GetOriginInMM() const
00075 {
00076 return m_OriginInMM;
00077 }
00078
00079 mitk::Vector2D mitk::DisplayGeometry::GetOriginInDisplayUnits() const
00080 {
00081 return m_OriginInDisplayUnits;
00082 }
00083
00084 void mitk::DisplayGeometry::SetSizeInDisplayUnits(unsigned int width, unsigned int height, bool keepDisplayedRegion)
00085 {
00086 Vector2D oldSizeInMM( m_SizeInMM );
00087 Point2D oldCenterInMM;
00088 if(keepDisplayedRegion)
00089 {
00090 Point2D centerInDisplayUnits;
00091 centerInDisplayUnits[0] = m_SizeInDisplayUnits[0]*0.5;
00092 centerInDisplayUnits[1] = m_SizeInDisplayUnits[1]*0.5;
00093 DisplayToWorld(centerInDisplayUnits, oldCenterInMM);
00094 }
00095
00096 m_SizeInDisplayUnits[0]=width;
00097 m_SizeInDisplayUnits[1]=height;
00098
00099 if(m_SizeInDisplayUnits[0] <= 0)
00100 m_SizeInDisplayUnits[0] = 1;
00101 if(m_SizeInDisplayUnits[1] <= 0)
00102 m_SizeInDisplayUnits[1] = 1;
00103
00104 DisplayToWorld(m_SizeInDisplayUnits, m_SizeInMM);
00105
00106 if(keepDisplayedRegion)
00107 {
00108 Point2D positionOfOldCenterInCurrentDisplayUnits;
00109 WorldToDisplay(oldCenterInMM, positionOfOldCenterInCurrentDisplayUnits);
00110
00111 Point2D currentNewCenterInDisplayUnits;
00112 currentNewCenterInDisplayUnits[0] = m_SizeInDisplayUnits[0]*0.5;
00113 currentNewCenterInDisplayUnits[1] = m_SizeInDisplayUnits[1]*0.5;
00114
00115 Vector2D shift;
00116 shift=positionOfOldCenterInCurrentDisplayUnits.GetVectorFromOrigin()-currentNewCenterInDisplayUnits;
00117
00118 MoveBy(shift);
00119 Zoom(m_SizeInMM.GetNorm()/oldSizeInMM.GetNorm(), currentNewCenterInDisplayUnits);
00120 }
00121
00122 Modified();
00123 }
00124
00125 mitk::Vector2D mitk::DisplayGeometry::GetSizeInDisplayUnits() const
00126 {
00127 return m_SizeInDisplayUnits;
00128 }
00129
00130 mitk::Vector2D mitk::DisplayGeometry::GetSizeInMM() const
00131 {
00132 return m_SizeInMM;
00133 }
00134
00135 unsigned int mitk::DisplayGeometry::GetDisplayWidth() const
00136 {
00137 assert(m_SizeInDisplayUnits[0] >= 0);
00138 return (unsigned int)m_SizeInDisplayUnits[0];
00139 }
00140
00141 unsigned int mitk::DisplayGeometry::GetDisplayHeight() const
00142 {
00143 assert(m_SizeInDisplayUnits[1] >= 0);
00144 return (unsigned int)m_SizeInDisplayUnits[1];
00145 }
00146
00147
00148
00149
00150
00151
00152
00153 void mitk::DisplayGeometry::SetConstrainZoomingAndPanning(bool constrain)
00154 {
00155 m_ConstrainZoomingAndPanning = constrain;
00156 if (m_ConstrainZoomingAndPanning)
00157 {
00158 this->RefitVisibleRect();
00159 }
00160 }
00161
00162 bool mitk::DisplayGeometry::GetConstrainZommingAndPanning() const
00163 {
00164 return m_ConstrainZoomingAndPanning;
00165 }
00166
00167 bool mitk::DisplayGeometry::SetScaleFactor(ScalarType mmPerDisplayUnit)
00168 {
00169 if(mmPerDisplayUnit<0.0001)
00170 {
00171 mmPerDisplayUnit=0.0001;
00172 }
00173
00174 m_ScaleFactorMMPerDisplayUnit = mmPerDisplayUnit;
00175 assert(m_ScaleFactorMMPerDisplayUnit < ScalarTypeNumericTraits::infinity());
00176
00177 DisplayToWorld(m_SizeInDisplayUnits, m_SizeInMM);
00178
00179 return !this->RefitVisibleRect();
00180 }
00181
00182 mitk::ScalarType mitk::DisplayGeometry::GetScaleFactorMMPerDisplayUnit() const
00183 {
00184 return m_ScaleFactorMMPerDisplayUnit;
00185 }
00186
00187
00188 bool mitk::DisplayGeometry::Zoom(ScalarType factor, const Point2D& centerInDisplayUnits)
00189 {
00190 assert(factor > 0);
00191
00192 if ( SetScaleFactor(m_ScaleFactorMMPerDisplayUnit/factor) )
00193 {
00194 return SetOriginInMM(m_OriginInMM-centerInDisplayUnits.GetVectorFromOrigin()*(1-factor)*m_ScaleFactorMMPerDisplayUnit);
00195 }
00196 else
00197 {
00198 return false;
00199 }
00200 }
00201
00202
00203
00204 bool mitk::DisplayGeometry::ZoomWithFixedWorldCoordinates(ScalarType factor, const Point2D& focusDisplayUnits, const Point2D& focusUnitsInMM )
00205 {
00206 assert(factor > 0);
00207
00208 SetScaleFactor(m_ScaleFactorMMPerDisplayUnit/factor);
00209 SetOriginInMM(focusUnitsInMM.GetVectorFromOrigin()-focusDisplayUnits.GetVectorFromOrigin()*m_ScaleFactorMMPerDisplayUnit);
00210 return true;
00211 }
00212
00213
00214 bool mitk::DisplayGeometry::MoveBy(const Vector2D& shiftInDisplayUnits)
00215 {
00216 SetOriginInMM(m_OriginInMM+shiftInDisplayUnits*m_ScaleFactorMMPerDisplayUnit);
00217
00218 Modified();
00219
00220 return !this->RefitVisibleRect();
00221 }
00222
00223 void mitk::DisplayGeometry::Fit()
00224 {
00225 if((m_WorldGeometry.IsNull()) || (m_WorldGeometry->IsValid() == false)) return;
00226
00228 int width=(int)m_SizeInDisplayUnits[0];
00229 int height=(int)m_SizeInDisplayUnits[1];
00230
00231 ScalarType w = width;
00232 ScalarType h = height;
00233
00234 const ScalarType& widthInMM = m_WorldGeometry->GetParametricExtentInMM(0);
00235 const ScalarType& heightInMM = m_WorldGeometry->GetParametricExtentInMM(1);
00236 ScalarType aspRatio=((ScalarType)widthInMM)/heightInMM;
00237
00238 ScalarType x = (ScalarType)w/widthInMM;
00239 ScalarType y = (ScalarType)h/heightInMM;
00240
00241 if (x > y)
00242 {
00243 w = (int) (aspRatio*h);
00244 }
00245 else
00246 {
00247 h = (int) (w/aspRatio);
00248 }
00249
00250 if(w>0)
00251 {
00252 SetScaleFactor(widthInMM/w);
00253 }
00254
00255 Vector2D origin_display;
00256 origin_display[0]=-(width-w)/2.0;
00257 origin_display[1]=-(height-h)/2.0;
00258 SetOriginInMM(origin_display*m_ScaleFactorMMPerDisplayUnit);
00259
00260 this->RefitVisibleRect();
00261
00262 Modified();
00263 }
00264
00265
00266
00267
00268
00269
00270
00271 void mitk::DisplayGeometry::DisplayToWorld(const Point2D &pt_display, Point2D &pt_mm) const
00272 {
00273 pt_mm[0]=m_ScaleFactorMMPerDisplayUnit*pt_display[0]+m_OriginInMM[0];
00274 pt_mm[1]=m_ScaleFactorMMPerDisplayUnit*pt_display[1]+m_OriginInMM[1];
00275 }
00276
00277 void mitk::DisplayGeometry::WorldToDisplay(const Point2D &pt_mm, Point2D &pt_display) const
00278 {
00279 pt_display[0]=(pt_mm[0]-m_OriginInMM[0])*(1.0/m_ScaleFactorMMPerDisplayUnit);
00280 pt_display[1]=(pt_mm[1]-m_OriginInMM[1])*(1.0/m_ScaleFactorMMPerDisplayUnit);
00281 }
00282
00283 void mitk::DisplayGeometry::DisplayToWorld(const Vector2D &vec_display, Vector2D &vec_mm) const
00284 {
00285 vec_mm=vec_display*m_ScaleFactorMMPerDisplayUnit;
00286 }
00287
00288 void mitk::DisplayGeometry::WorldToDisplay(const Vector2D &vec_mm, Vector2D &vec_display) const
00289 {
00290 vec_display=vec_mm*(1.0/m_ScaleFactorMMPerDisplayUnit);
00291 }
00292
00293 void mitk::DisplayGeometry::ULDisplayToMM(const Point2D &pt_ULdisplay, Point2D &pt_mm) const
00294 {
00295 ULDisplayToDisplay(pt_ULdisplay, pt_mm);
00296 DisplayToWorld(pt_mm, pt_mm);
00297 }
00298
00299 void mitk::DisplayGeometry::MMToULDisplay(const Point2D &pt_mm, Point2D &pt_ULdisplay) const
00300 {
00301 WorldToDisplay(pt_mm, pt_ULdisplay);
00302 DisplayToULDisplay(pt_ULdisplay, pt_ULdisplay);
00303 }
00304
00305 void mitk::DisplayGeometry::ULDisplayToMM(const Vector2D &vec_ULdisplay, Vector2D &vec_mm) const
00306 {
00307 ULDisplayToDisplay(vec_ULdisplay, vec_mm);
00308 DisplayToWorld(vec_mm, vec_mm);
00309 }
00310
00311 void mitk::DisplayGeometry::MMToULDisplay(const Vector2D &vec_mm, Vector2D &vec_ULdisplay) const
00312 {
00313 WorldToDisplay(vec_mm, vec_ULdisplay);
00314 DisplayToULDisplay(vec_ULdisplay, vec_ULdisplay);
00315 }
00316
00317 void mitk::DisplayGeometry::ULDisplayToDisplay(const Point2D &pt_ULdisplay, Point2D &pt_display) const
00318 {
00319 pt_display[0]=pt_ULdisplay[0];
00320 pt_display[1]=GetDisplayHeight()-pt_ULdisplay[1];
00321 }
00322
00323 void mitk::DisplayGeometry::DisplayToULDisplay(const Point2D &pt_display, Point2D &pt_ULdisplay) const
00324 {
00325 ULDisplayToDisplay(pt_display, pt_ULdisplay);
00326 }
00327
00328 void mitk::DisplayGeometry::ULDisplayToDisplay(const Vector2D &vec_ULdisplay, Vector2D &vec_display) const
00329 {
00330 vec_display[0]= vec_ULdisplay[0];
00331 vec_display[1]=-vec_ULdisplay[1];
00332 }
00333
00334 void mitk::DisplayGeometry::DisplayToULDisplay(const Vector2D &vec_display, Vector2D &vec_ULdisplay) const
00335 {
00336 ULDisplayToDisplay(vec_display, vec_ULdisplay);
00337 }
00338
00339 bool mitk::DisplayGeometry::Project(const Point3D &pt3d_mm, Point3D &projectedPt3d_mm) const
00340 {
00341 if(m_WorldGeometry.IsNotNull())
00342 {
00343 return m_WorldGeometry->Project(pt3d_mm, projectedPt3d_mm);
00344 }
00345 else
00346 {
00347 return false;
00348 }
00349 }
00350
00351 bool mitk::DisplayGeometry::Project(const Point3D & atPt3d_mm, const Vector3D &vec3d_mm, Vector3D &projectedVec3d_mm) const
00352 {
00353 if(m_WorldGeometry.IsNotNull())
00354 {
00355 return m_WorldGeometry->Project(atPt3d_mm, vec3d_mm, projectedVec3d_mm);
00356 }
00357 else
00358 {
00359 return false;
00360 }
00361 }
00362
00363 bool mitk::DisplayGeometry::Map(const Point3D &pt3d_mm, Point2D &pt2d_mm) const
00364 {
00365 if(m_WorldGeometry.IsNotNull())
00366 {
00367 return m_WorldGeometry->Map(pt3d_mm, pt2d_mm);
00368 }
00369 else
00370 {
00371 return false;
00372 }
00373 }
00374
00375 void mitk::DisplayGeometry::Map(const Point2D &pt2d_mm, Point3D &pt3d_mm) const
00376 {
00377 if(m_WorldGeometry.IsNull()) return;
00378 m_WorldGeometry->Map(pt2d_mm, pt3d_mm);
00379 }
00380
00381 bool mitk::DisplayGeometry::Map(const Point3D & atPt3d_mm, const Vector3D &vec3d_mm, Vector2D &vec2d_mm) const
00382 {
00383 if(m_WorldGeometry.IsNotNull())
00384 {
00385 return m_WorldGeometry->Map(atPt3d_mm, vec3d_mm, vec2d_mm);
00386 }
00387 else
00388 {
00389 return false;
00390 }
00391 }
00392
00393 void mitk::DisplayGeometry::Map(const Point2D & atPt2d_mm, const Vector2D &vec2d_mm, Vector3D &vec3d_mm) const
00394 {
00395 if(m_WorldGeometry.IsNull()) return;
00396
00397 m_WorldGeometry->Map(atPt2d_mm, vec2d_mm, vec3d_mm);
00398 }
00399
00400
00401
00402
00403
00404
00405
00406 mitk::DisplayGeometry::DisplayGeometry()
00407 :m_ScaleFactorMMPerDisplayUnit(1.0)
00408 ,m_WorldGeometry(NULL)
00409 ,m_ConstrainZoomingAndPanning(true)
00410 ,m_MaxWorldViewPercentage(1.0)
00411 ,m_MinWorldViewPercentage(0.1)
00412 {
00413 m_OriginInMM.Fill(0.0);
00414 m_OriginInDisplayUnits.Fill(0.0);
00415 m_SizeInMM.Fill(1.0);
00416 m_SizeInDisplayUnits.Fill(10.0);
00417 }
00418
00419 mitk::DisplayGeometry::~DisplayGeometry()
00420 {
00421 }
00422
00423 bool mitk::DisplayGeometry::RefitVisibleRect()
00424 {
00425
00426 if (!m_ConstrainZoomingAndPanning) return false;
00427
00428
00429 static bool inRecalculate = false;
00430 if (inRecalculate) return false;
00431 inRecalculate = true;
00432
00433
00434 float displayXMM = m_OriginInMM[0];
00435 float displayYMM = m_OriginInMM[1];
00436 float displayWidthPx = m_SizeInDisplayUnits[0];
00437 float displayHeightPx = m_SizeInDisplayUnits[1];
00438 float displayWidthMM = m_SizeInDisplayUnits[0] * m_ScaleFactorMMPerDisplayUnit;
00439 float displayHeightMM = m_SizeInDisplayUnits[1] * m_ScaleFactorMMPerDisplayUnit;
00440
00441 float worldWidthMM = m_WorldGeometry->GetParametricExtentInMM(0);
00442 float worldHeightMM = m_WorldGeometry->GetParametricExtentInMM(1);
00443
00444
00445 Vector2D newOrigin = m_OriginInMM;
00446 bool correctPanning = false;
00447
00448 float newScaleFactor = m_ScaleFactorMMPerDisplayUnit;
00449 bool correctZooming = false;
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460 bool zoomXtooSmall = displayWidthPx * m_ScaleFactorMMPerDisplayUnit > m_MaxWorldViewPercentage * worldWidthMM;
00461 bool zoomXtooBig = displayWidthPx * m_ScaleFactorMMPerDisplayUnit < m_MinWorldViewPercentage * worldWidthMM;
00462
00463 bool zoomYtooSmall = displayHeightPx * m_ScaleFactorMMPerDisplayUnit > m_MaxWorldViewPercentage * worldHeightMM;
00464 bool zoomYtooBig = displayHeightPx * m_ScaleFactorMMPerDisplayUnit < m_MinWorldViewPercentage * worldHeightMM;
00465
00466
00467 if ( zoomXtooBig && zoomYtooBig)
00468 {
00469 double fx = worldWidthMM * m_MinWorldViewPercentage / displayWidthPx;
00470 double fy = worldHeightMM * m_MinWorldViewPercentage / displayHeightPx;
00471 newScaleFactor = fx < fy ? fx : fy;
00472 correctZooming = true;
00473 }
00474
00475 else if ( zoomXtooBig )
00476 {
00477 newScaleFactor = worldWidthMM * m_MinWorldViewPercentage / displayWidthPx;
00478 correctZooming = true;
00479 }
00480
00481
00482 else if ( zoomYtooBig )
00483 {
00484 newScaleFactor = worldHeightMM * m_MinWorldViewPercentage / displayHeightPx;
00485 correctZooming = true;
00486 }
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520 if ( zoomXtooSmall && zoomYtooSmall )
00521 {
00522
00523 float fx = worldWidthMM * m_MaxWorldViewPercentage / displayWidthPx;
00524 float fy = worldHeightMM * m_MaxWorldViewPercentage / displayHeightPx;
00525 newScaleFactor = fx > fy ? fx : fy;
00526
00527 correctZooming = true;
00528 }
00529
00530
00531
00532 if (correctZooming)
00533 {
00534 SetScaleFactor(newScaleFactor);
00535 }
00536
00537 displayWidthMM = m_SizeInDisplayUnits[0] * m_ScaleFactorMMPerDisplayUnit;
00538 displayHeightMM = m_SizeInDisplayUnits[1] * m_ScaleFactorMMPerDisplayUnit;
00539
00540
00541 if(worldWidthMM<displayWidthMM)
00542 {
00543
00544
00545 newOrigin[0] = (worldWidthMM - displayWidthMM) / 2.0;
00546 correctPanning = true;
00547 }
00548 else
00549 {
00550
00551 if (displayXMM < 0)
00552 {
00553 newOrigin[0] = 0;
00554 correctPanning = true;
00555 }
00556
00557 else if (displayXMM + displayWidthMM > worldWidthMM)
00558 {
00559 newOrigin[0] = worldWidthMM - displayWidthMM;
00560 correctPanning = true;
00561 }
00562 }
00563
00564
00565 if (worldHeightMM<displayHeightMM)
00566 {
00567
00568
00569 newOrigin[1] = (worldHeightMM - displayHeightMM) / 2.0;
00570 correctPanning = true;
00571 }
00572 else
00573 {
00574
00575 if (displayYMM + displayHeightMM > worldHeightMM)
00576 {
00577 newOrigin[1] = worldHeightMM - displayHeightMM;
00578 correctPanning = true;
00579 }
00580
00581 else
00582 if (displayYMM < 0)
00583 {
00584 newOrigin[1] = 0;
00585 correctPanning = true;
00586 }
00587
00588 }
00589
00590
00591 if (correctPanning)
00592 {
00593 SetOriginInMM( newOrigin );
00594 }
00595
00596 if ( correctPanning || correctZooming )
00597 {
00598 Modified();
00599 }
00600
00601 inRecalculate = false;
00602
00603
00604 return correctPanning || correctZooming;
00605 }
00606
00607 void mitk::DisplayGeometry::PrintSelf(std::ostream& os, itk::Indent indent) const
00608 {
00609 if(m_WorldGeometry.IsNull())
00610 {
00611 os << indent << " WorldGeometry: " << "NULL" << std::endl;
00612 }
00613 else
00614 {
00615 m_WorldGeometry->Print(os, indent);
00616 os << indent << " OriginInMM: " << m_OriginInMM << std::endl;
00617 os << indent << " OriginInDisplayUnits: " << m_OriginInDisplayUnits << std::endl;
00618 os << indent << " SizeInMM: " << m_SizeInMM << std::endl;
00619 os << indent << " SizeInDisplayUnits: " << m_SizeInDisplayUnits << std::endl;
00620 os << indent << " ScaleFactorMMPerDisplayUni: " << m_ScaleFactorMMPerDisplayUnit << std::endl;
00621 }
00622
00623 Superclass::PrintSelf(os,indent);
00624 }
00625