Changeset View
Changeset View
Standalone View
Standalone View
extern/opennurbs/opennurbs_photogrammetry.cpp
- This file was added.
| /* $NoKeywords: $ */ | |||||
| /* | |||||
| // | |||||
| // Copyright (c) 1993-2013 Robert McNeel & Associates. All rights reserved. | |||||
| // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert | |||||
| // McNeel & Associates. | |||||
| // | |||||
| // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. | |||||
| // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF | |||||
| // MERCHANTABILITY ARE HEREBY DISCLAIMED. | |||||
| // | |||||
| // For complete openNURBS copyright information see <http://www.opennurbs.org>. | |||||
| // | |||||
| //////////////////////////////////////////////////////////////// | |||||
| */ | |||||
| #include "opennurbs.h" | |||||
| #if !defined(ON_COMPILING_OPENNURBS) | |||||
| // This check is included in all opennurbs source .c and .cpp files to insure | |||||
| // ON_COMPILING_OPENNURBS is defined when opennurbs source is compiled. | |||||
| // When opennurbs source is being compiled, ON_COMPILING_OPENNURBS is defined | |||||
| // and the opennurbs .h files alter what is declared and how it is declared. | |||||
| #error ON_COMPILING_OPENNURBS must be defined when compiling opennurbs | |||||
| #endif | |||||
| ON_AerialPhotoImage::ON_AerialPhotoImage() | |||||
| : m_id(ON_nil_uuid) | |||||
| , m_image_width_pixels(0) | |||||
| , m_image_height_pixels(0) | |||||
| { | |||||
| } | |||||
| void ON_AerialPhotoImage::Unset() | |||||
| { | |||||
| m_name.Destroy(); | |||||
| m_id = ON_nil_uuid; | |||||
| m_camera_position.Unset(); | |||||
| m_image_frustum.Unset(); | |||||
| m_image_file_name.Destroy(); | |||||
| m_image_width_pixels = 0; | |||||
| m_image_height_pixels = 0; | |||||
| } | |||||
| void ON_AerialPhotoImage::SetName( | |||||
| const wchar_t* name | |||||
| ) | |||||
| { | |||||
| m_name = name; | |||||
| } | |||||
| void ON_AerialPhotoImage::GetName( | |||||
| ON_wString& name | |||||
| ) const | |||||
| { | |||||
| name = m_name.Array(); | |||||
| } | |||||
| void ON_AerialPhotoImage::SetId( ON_UUID id ) | |||||
| { | |||||
| m_id = id; | |||||
| } | |||||
| ON_UUID ON_AerialPhotoImage::Id() const | |||||
| { | |||||
| return m_id; | |||||
| } | |||||
| bool ON_AerialPhotoImage::CameraPositionIsSet() const | |||||
| { | |||||
| return m_camera_position.IsSet(); | |||||
| } | |||||
| bool ON_AerialPhotoImage::CameraLocationIsSet() const | |||||
| { | |||||
| return m_camera_position.LocationIsSet(); | |||||
| } | |||||
| bool ON_AerialPhotoImage::CameraOrientationIsSet() const | |||||
| { | |||||
| return m_camera_position.OrientationIsSet(); | |||||
| } | |||||
| void ON_AerialPhotoImage::SetCameraPosition( | |||||
| ON_AerialPhotoCameraPosition camera_position | |||||
| ) | |||||
| { | |||||
| m_camera_position = camera_position; | |||||
| } | |||||
| void ON_AerialPhotoImage::GetCameraPosition( | |||||
| ON_AerialPhotoCameraPosition& camera_position | |||||
| ) const | |||||
| { | |||||
| camera_position = m_camera_position; | |||||
| } | |||||
| void ON_AerialPhotoImage::UnsetCameraPosition() | |||||
| { | |||||
| m_camera_position.Unset(); | |||||
| } | |||||
| ///////////////////////////////////////////////////////// | |||||
| // | |||||
| // Image frustum interface | |||||
| // | |||||
| bool ON_AerialPhotoImage::ImageFrustumIsSet() const | |||||
| { | |||||
| return m_image_frustum.IsSet(); | |||||
| } | |||||
| void ON_AerialPhotoImage::SetImageFrustum( | |||||
| ON_AerialPhotoImageFrustum image_frustum | |||||
| ) | |||||
| { | |||||
| m_image_frustum = image_frustum; | |||||
| } | |||||
| void ON_AerialPhotoImage::GetImageFrustum( | |||||
| ON_AerialPhotoImageFrustum& image_frustum | |||||
| ) const | |||||
| { | |||||
| image_frustum = m_image_frustum; | |||||
| } | |||||
| void ON_AerialPhotoImage::UnsetImageFrustum() | |||||
| { | |||||
| m_image_frustum.Unset(); | |||||
| } | |||||
| bool ON_AerialPhotoImage::ImageFileNameIsSet() const | |||||
| { | |||||
| return (m_image_file_name.Length() > 0); | |||||
| } | |||||
| bool ON_AerialPhotoImage::ImageSizeIsSet() const | |||||
| { | |||||
| return (m_image_width_pixels > 0 && m_image_height_pixels > 0); | |||||
| } | |||||
| bool ON_AerialPhotoImage::SetImageSize( | |||||
| int image_width_pixels, | |||||
| int image_height_pixels | |||||
| ) | |||||
| { | |||||
| bool rc = false; | |||||
| if ( image_width_pixels > 0 && image_height_pixels > 0 ) | |||||
| { | |||||
| m_image_width_pixels = image_width_pixels; | |||||
| m_image_height_pixels = image_height_pixels; | |||||
| rc = true; | |||||
| } | |||||
| else | |||||
| UnsetImageSize(); | |||||
| return rc; | |||||
| } | |||||
| bool ON_AerialPhotoImage::GetImageSize( | |||||
| int* width_pixels, | |||||
| int* height_pixels | |||||
| ) const | |||||
| { | |||||
| if ( 0 != width_pixels ) | |||||
| *width_pixels = m_image_width_pixels; | |||||
| if ( 0 != height_pixels ) | |||||
| *height_pixels = m_image_height_pixels; | |||||
| return ImageSizeIsSet(); | |||||
| } | |||||
| void ON_AerialPhotoImage::UnsetImageSize() | |||||
| { | |||||
| m_image_width_pixels = 0; | |||||
| m_image_height_pixels = 0; | |||||
| } | |||||
| void ON_AerialPhotoImage::SetImageFileName( | |||||
| const wchar_t* image_file_name | |||||
| ) | |||||
| { | |||||
| m_image_file_name = image_file_name; | |||||
| } | |||||
| void ON_AerialPhotoImage::GetImageFileName( | |||||
| ON_wString& image_file_name | |||||
| ) const | |||||
| { | |||||
| // copy array | |||||
| const wchar_t* s = static_cast< const wchar_t* >(m_image_file_name); | |||||
| image_file_name = s; | |||||
| } | |||||
| void ON_AerialPhotoImage::UnsetImageFileName() | |||||
| { | |||||
| m_image_file_name.Destroy(); | |||||
| } | |||||
| ON_AerialPhotoImageFrustum::ON_AerialPhotoImageFrustum() | |||||
| { | |||||
| Unset(); | |||||
| } | |||||
| bool ON_AerialPhotoImageFrustum::IsSet() const | |||||
| { | |||||
| return HeightIsSet() && CornersAreSet() && UnitSystemIsSet(); | |||||
| } | |||||
| void ON_AerialPhotoImageFrustum::Unset() | |||||
| { | |||||
| m_height = ON_UNSET_VALUE; | |||||
| m_corners[0] = ON_2dPoint::UnsetPoint; | |||||
| m_corners[1] = ON_2dPoint::UnsetPoint; | |||||
| m_corners[2] = ON_2dPoint::UnsetPoint; | |||||
| m_corners[3] = ON_2dPoint::UnsetPoint; | |||||
| m_unit_system = ON_UnitSystem::None; | |||||
| } | |||||
| bool ON_AerialPhotoImageFrustum::HeightIsSet() const | |||||
| { | |||||
| return (m_height > 0.0 && ON_IsValid(m_height)); | |||||
| } | |||||
| bool ON_AerialPhotoImageFrustum::CornersAreSet() const | |||||
| { | |||||
| for(;;) | |||||
| { | |||||
| if ( !m_corners[0].IsValid() ) | |||||
| break; | |||||
| if ( !m_corners[1].IsValid() ) | |||||
| break; | |||||
| if ( !m_corners[2].IsValid() ) | |||||
| break; | |||||
| if ( !m_corners[3].IsValid() ) | |||||
| break; | |||||
| // corners must form a non-empty convex 2d region and | |||||
| // be in counter-clockwise order. They can be a | |||||
| // the corners of a 3 or 4 sided region. | |||||
| double max_z = 0.0; | |||||
| double z; | |||||
| ON_2dVector A, B; | |||||
| for ( int i = 0; i < 4; i++ ) | |||||
| { | |||||
| A = m_corners[(i+3)%4] - m_corners[i]; | |||||
| B = m_corners[(i+1)%4] - m_corners[i]; | |||||
| z = B.x*A.y - A.x*B.y; | |||||
| if (z >= 0.0 && ON_IsValid(z)) | |||||
| { | |||||
| if ( z > max_z ) | |||||
| max_z = z; | |||||
| continue; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| if ( max_z > 0.0 ) | |||||
| return true; | |||||
| break; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| bool ON_AerialPhotoImageFrustum::UnitSystemIsSet() const | |||||
| { | |||||
| return (m_unit_system.IsSet()); | |||||
| } | |||||
| ON_AerialPhotoCameraPosition::ON_AerialPhotoCameraPosition() | |||||
| : m_status(0) | |||||
| { | |||||
| Unset(); | |||||
| } | |||||
| void ON_AerialPhotoCameraPosition::Unset() | |||||
| { | |||||
| UnsetUnitSystem(); | |||||
| UnsetLocation(); | |||||
| UnsetOrientation(); | |||||
| } | |||||
| bool ON_AerialPhotoCameraPosition::IsSet() const | |||||
| { | |||||
| return UnitSystemIsSet() && LocationIsSet() && OrientationIsSet(); | |||||
| } | |||||
| bool ON_AerialPhotoCameraPosition::UnitSystemIsSet() const | |||||
| { | |||||
| return m_unit_system.IsSet(); | |||||
| } | |||||
| bool ON_AerialPhotoCameraPosition::SetUnitSystem( ON::LengthUnitSystem unit_system ) | |||||
| { | |||||
| if ( ON::LengthUnitSystem::None != unit_system | |||||
| && ON::LengthUnitSystem::CustomUnits != unit_system | |||||
| && unit_system == ON::LengthUnitSystemFromUnsigned(static_cast<unsigned int>(unit_system)) | |||||
| ) | |||||
| { | |||||
| m_unit_system = ON_UnitSystem(unit_system); | |||||
| } | |||||
| else | |||||
| Unset(); | |||||
| return UnitSystemIsSet(); | |||||
| } | |||||
| bool ON_AerialPhotoCameraPosition::SetUnitSystem ( ON_UnitSystem unit_system ) | |||||
| { | |||||
| if ( unit_system.IsSet() ) | |||||
| m_unit_system = unit_system; | |||||
| else | |||||
| Unset(); | |||||
| return UnitSystemIsSet(); | |||||
| } | |||||
| ON_UnitSystem ON_AerialPhotoCameraPosition::UnitSystem() const | |||||
| { | |||||
| return m_unit_system; | |||||
| } | |||||
| bool ON_AerialPhotoCameraPosition::GetUnitSystem( ON_UnitSystem& unit_system ) const | |||||
| { | |||||
| unit_system = m_unit_system; | |||||
| return UnitSystemIsSet(); | |||||
| } | |||||
| void ON_AerialPhotoCameraPosition::UnsetUnitSystem() | |||||
| { | |||||
| m_unit_system = ON_UnitSystem(ON::LengthUnitSystem::None); | |||||
| } | |||||
| bool ON_AerialPhotoCameraPosition::LocationIsSet() const | |||||
| { | |||||
| return m_location.IsValid(); | |||||
| } | |||||
| bool ON_AerialPhotoCameraPosition::SetLocation( | |||||
| ON_3dPoint camera_location | |||||
| ) | |||||
| { | |||||
| const bool rc = camera_location.IsValid(); | |||||
| if (rc) | |||||
| m_location = camera_location; | |||||
| else | |||||
| UnsetLocation(); | |||||
| return rc; | |||||
| } | |||||
| bool ON_AerialPhotoCameraPosition::GetLocation( | |||||
| ON_3dPoint& camera_location | |||||
| ) const | |||||
| { | |||||
| camera_location = Location(); | |||||
| return LocationIsSet(); | |||||
| } | |||||
| ON_3dPoint ON_AerialPhotoCameraPosition::Location() const | |||||
| { | |||||
| return m_location; | |||||
| } | |||||
| void ON_AerialPhotoCameraPosition::UnsetLocation() | |||||
| { | |||||
| m_status &= 0xFE; // clear bit 1 | |||||
| m_location = ON_3dPoint::UnsetPoint; | |||||
| } | |||||
| bool ON_AerialPhotoCameraPosition::OrientationIsSet() const | |||||
| { | |||||
| return ( 0 != (m_status & 2) | |||||
| && m_orientation_angles_radians.IsValid() | |||||
| && m_orientation_angles_degrees.IsValid() | |||||
| && m_orientation_right.IsValid() | |||||
| && m_orientation_up.IsValid() | |||||
| && m_orientation_direction.IsValid() | |||||
| && m_orientation_rotation.IsValid() | |||||
| ); | |||||
| } | |||||
| void ON_AerialPhotoCameraPosition::UnsetOrientation() | |||||
| { | |||||
| m_status &= 0xFD; // clear bit 2 | |||||
| m_orientation_angles_radians.Set(ON_UNSET_VALUE,ON_UNSET_VALUE,ON_UNSET_VALUE); | |||||
| m_orientation_angles_degrees.Set(ON_UNSET_VALUE,ON_UNSET_VALUE,ON_UNSET_VALUE); | |||||
| m_orientation_rotation = ON_Xform::Zero4x4; | |||||
| m_orientation_right = ON_3dVector::ZeroVector; | |||||
| m_orientation_up = ON_3dVector::ZeroVector; | |||||
| m_orientation_direction = ON_3dVector::ZeroVector; | |||||
| } | |||||
| bool ON_AerialPhotoCameraPosition::GetOrientationRotation( | |||||
| ON_Xform& camera_rotaion | |||||
| ) const | |||||
| { | |||||
| camera_rotaion = m_orientation_rotation; | |||||
| return (0 != (m_status & 2)); | |||||
| } | |||||
| /* | |||||
| Description: | |||||
| Get a right handed ortho normal camera frame. | |||||
| Parameters: | |||||
| camera_X - [out] | |||||
| world coordinate unit vector pointing to the right in the camera image | |||||
| = OrientationRotation * (1,0,0) | |||||
| camera_Y - [out] | |||||
| world coordinate unit vector in the camera up direction. | |||||
| = OrientationRotation * (0,1,0) | |||||
| camera_Z - [out] | |||||
| world coordinate unit vector pointing into the cameara (from the | |||||
| image toward the camera). | |||||
| = OrientationRotation * (0,0,1) | |||||
| */ | |||||
| bool ON_AerialPhotoCameraPosition::GetOrientationFrame( | |||||
| ON_3dVector& camera_X, | |||||
| ON_3dVector& camera_Y, | |||||
| ON_3dVector& camera_Z | |||||
| ) const | |||||
| { | |||||
| camera_X.x = m_orientation_rotation.m_xform[0][0]; | |||||
| camera_X.y = m_orientation_rotation.m_xform[1][0]; | |||||
| camera_X.z = m_orientation_rotation.m_xform[2][0]; | |||||
| camera_Y.x = m_orientation_rotation.m_xform[0][1]; | |||||
| camera_Y.y = m_orientation_rotation.m_xform[1][1]; | |||||
| camera_Y.z = m_orientation_rotation.m_xform[2][1]; | |||||
| camera_Z.x = m_orientation_rotation.m_xform[0][2]; | |||||
| camera_Z.y = m_orientation_rotation.m_xform[1][2]; | |||||
| camera_Z.z = m_orientation_rotation.m_xform[2][2]; | |||||
| return (0 != (m_status & 2)); | |||||
| } | |||||
| ON_Xform ON_AerialPhotoCameraPosition::OrientationRotation() const | |||||
| { | |||||
| return m_orientation_rotation; | |||||
| } | |||||
| bool ON_AerialPhotoCameraPosition::SetOrientationVectors( | |||||
| ON_3dVector camera_up, | |||||
| ON_3dVector camera_right, | |||||
| ON_3dVector camera_direction | |||||
| ) | |||||
| { | |||||
| ON_3dVector X(camera_right); | |||||
| ON_3dVector Y(camera_up); | |||||
| ON_3dVector Z(-camera_direction); | |||||
| bool bHaveX = ( X.IsValid() && X.Unitize() ); | |||||
| bool bHaveY = ( Y.IsValid() && Y.Unitize() ); | |||||
| bool bHaveZ = ( Z.IsValid() && Z.Unitize() ); | |||||
| if ( !bHaveX && bHaveY && bHaveZ ) | |||||
| { | |||||
| X = ON_CrossProduct(Y,Z); | |||||
| bHaveX = X.Unitize(); | |||||
| if ( bHaveX ) | |||||
| camera_right = X; | |||||
| } | |||||
| else if ( !bHaveY && bHaveZ && bHaveX ) | |||||
| { | |||||
| Y = ON_CrossProduct(Z,X); | |||||
| bHaveY = Y.Unitize(); | |||||
| if ( bHaveY ) | |||||
| camera_up = Y; | |||||
| } | |||||
| else if ( !bHaveZ && bHaveX && bHaveY ) | |||||
| { | |||||
| Z = ON_CrossProduct(X,Y); | |||||
| bHaveZ = Z.Unitize(); | |||||
| if ( bHaveZ ) | |||||
| camera_direction = -Z; | |||||
| } | |||||
| bool rc = false; | |||||
| for (;;) | |||||
| { | |||||
| if ( !bHaveX || !bHaveY || !bHaveZ ) | |||||
| break; | |||||
| double max_dot = 0.0; | |||||
| double d = fabs(X*Y); | |||||
| if ( d > max_dot ) | |||||
| max_dot = d; | |||||
| d = fabs(Y*Z); | |||||
| if ( d > max_dot ) | |||||
| max_dot = d; | |||||
| d = fabs(Z*X); | |||||
| if ( d > max_dot ) | |||||
| max_dot = d; | |||||
| if ( max_dot > 1.0e-8 ) | |||||
| break; | |||||
| d = Z*ON_CrossProduct(X,Y); | |||||
| if ( !(d > 0.0) ) | |||||
| break; | |||||
| ON_Xform R; | |||||
| R.m_xform[0][0] = X.x; R.m_xform[0][1] = Y.x; R.m_xform[0][2] = Z.x; R.m_xform[0][3] = 0.0; | |||||
| R.m_xform[1][0] = X.y; R.m_xform[1][1] = Y.y; R.m_xform[1][2] = Z.y; R.m_xform[1][3] = 0.0; | |||||
| R.m_xform[2][0] = X.z; R.m_xform[2][1] = Y.z; R.m_xform[2][2] = Z.z; R.m_xform[2][3] = 0.0; | |||||
| R.m_xform[3][0] = 0.0; R.m_xform[3][1] = 0.0; R.m_xform[3][2] = 0.0; R.m_xform[3][3] = 1.0; | |||||
| rc = SetOrientationRotation(R); | |||||
| if (rc) | |||||
| { | |||||
| // preserve exact values of input parameters | |||||
| m_orientation_right = camera_right; | |||||
| m_orientation_up = camera_up; | |||||
| m_orientation_direction = camera_direction; | |||||
| } | |||||
| break; | |||||
| } | |||||
| if (!rc) | |||||
| { | |||||
| UnsetOrientation(); | |||||
| } | |||||
| return rc; | |||||
| } | |||||
| bool ON_AerialPhotoCameraPosition::SetOrientationRotation( | |||||
| ON_Xform camera_rotation | |||||
| ) | |||||
| { | |||||
| m_orientation_rotation = camera_rotation; | |||||
| const ON_3dVector X(camera_rotation.m_xform[0][0],camera_rotation.m_xform[1][0],camera_rotation.m_xform[2][0]); | |||||
| const ON_3dVector Y(camera_rotation.m_xform[0][1],camera_rotation.m_xform[1][1],camera_rotation.m_xform[2][1]); | |||||
| const ON_3dVector Z(camera_rotation.m_xform[0][2],camera_rotation.m_xform[1][2],camera_rotation.m_xform[2][2]); | |||||
| m_orientation_right = X; | |||||
| m_orientation_up = Y; | |||||
| m_orientation_direction = -Z; | |||||
| double s1, c1, s2, c2, s3, c3; | |||||
| s2 = Z.x; | |||||
| double a = 1.0 - s2*s2; | |||||
| c2 = (a > 0.0) ? sqrt(a) : 0.0; | |||||
| if ( fabs(c2) <= ON_EPSILON || fabs(s2) >= 1.0-ON_EPSILON ) | |||||
| { | |||||
| s2 = (s2 < 0.0) ? -1.0 : 1.0; | |||||
| c2 = 0.0; | |||||
| } | |||||
| else if ( fabs(s2) <= ON_EPSILON || fabs(c2) >= 1.0-ON_EPSILON ) | |||||
| { | |||||
| c2 = (c2 < 0.0) ? -1.0 : 1.0; | |||||
| s2 = 0.0; | |||||
| } | |||||
| if ( c2 > 0.0 ) | |||||
| { | |||||
| s1 = -Z.y/c2; | |||||
| c1 = Z.z/c2; | |||||
| s3 = -Y.x/c2; | |||||
| c3 = X.x/c2; | |||||
| } | |||||
| else | |||||
| { | |||||
| s1 = 0.0; | |||||
| c1 = 1.0; | |||||
| s3 = ( X.y == Y.z ) ? X.y : 0.5*(X.y + Y.z); | |||||
| c3 = ( Y.y == -X.z ) ? Y.y : 0.5*(Y.y - X.z); | |||||
| } | |||||
| m_orientation_angles_radians.x = atan2(s1,c1); | |||||
| m_orientation_angles_radians.y = atan2(s2,c2); | |||||
| m_orientation_angles_radians.z = atan2(s2,c3); | |||||
| m_orientation_angles_degrees.x = m_orientation_angles_radians.x*180.0/ON_PI; | |||||
| m_orientation_angles_degrees.y = m_orientation_angles_radians.y*180.0/ON_PI; | |||||
| m_orientation_angles_degrees.z = m_orientation_angles_radians.z*180.0/ON_PI; | |||||
| m_status |= 2; | |||||
| return true; | |||||
| } | |||||
| bool ON_AerialPhotoCameraPosition::SetOrientationAnglesDegrees( | |||||
| double omega_degrees, | |||||
| double phi_degrees, | |||||
| double kappa_degrees | |||||
| ) | |||||
| { | |||||
| bool rc = false; | |||||
| if ( ON_IsValid(omega_degrees) && ON_IsValid(phi_degrees) && ON_IsValid(kappa_degrees) ) | |||||
| { | |||||
| rc = SetOrientationAnglesRadians(omega_degrees*ON_PI/180.0,phi_degrees*ON_PI/180.0,kappa_degrees*ON_PI/180.0); | |||||
| // Directly set m_camera_angles_degrees after SetCameraAnglesRadians() | |||||
| // so we don't loose a few bits of precision lost by converting to radians | |||||
| // and then converting back to degrees. | |||||
| m_orientation_angles_degrees.Set(omega_degrees,phi_degrees,kappa_degrees); | |||||
| } | |||||
| else | |||||
| { | |||||
| UnsetOrientation(); | |||||
| } | |||||
| return rc; | |||||
| } | |||||
| bool ON_AerialPhotoCameraPosition::SetOrientationAnglesRadians( | |||||
| double omega_radians, | |||||
| double phi_radians, | |||||
| double kappa_radians | |||||
| ) | |||||
| { | |||||
| bool rc = false; | |||||
| if ( ON_IsValid(omega_radians) && ON_IsValid(phi_radians) && ON_IsValid(kappa_radians) ) | |||||
| { | |||||
| m_orientation_angles_radians.Set(omega_radians,phi_radians,kappa_radians); | |||||
| m_orientation_angles_degrees.Set(omega_radians*180.0/ON_PI,phi_radians*180.0/ON_PI,kappa_radians*180.0/ON_PI); | |||||
| const double c1 = cos(omega_radians); | |||||
| const double s1 = sin(omega_radians); | |||||
| const double c2 = cos(phi_radians); | |||||
| const double s2 = sin(phi_radians); | |||||
| const double c3 = cos(kappa_radians); | |||||
| const double s3 = sin(kappa_radians); | |||||
| const ON_3dVector X( c3*c2, s3*c1 + c3*s2*s1, s3*s1 - c3*s2*c1); | |||||
| const ON_3dVector Y(-s3*c2, c3*c1 - s3*s2*s1, c3*s1 + s3*s2*c1); | |||||
| const ON_3dVector Z( s2, -c2*s1, c2*c1); | |||||
| ON_Xform R; | |||||
| R.m_xform[0][0] = X.x; R.m_xform[0][1] = Y.x; R.m_xform[0][2] = Z.x; R.m_xform[0][3] = 0.0; | |||||
| R.m_xform[1][0] = X.y; R.m_xform[1][1] = Y.y; R.m_xform[1][2] = Z.y; R.m_xform[1][3] = 0.0; | |||||
| R.m_xform[2][0] = X.z; R.m_xform[2][1] = Y.z; R.m_xform[2][2] = Z.z; R.m_xform[2][3] = 0.0; | |||||
| R.m_xform[3][0] = 0.0; R.m_xform[3][1] = 0.0; R.m_xform[3][2] = 0.0; R.m_xform[3][3] = 1.0; | |||||
| m_orientation_rotation = R; | |||||
| m_orientation_right = X; | |||||
| m_orientation_up = Y; | |||||
| m_orientation_direction = -Z; | |||||
| m_status |= 2; | |||||
| rc = true; | |||||
| { | |||||
| // Debugging validation tests | |||||
| const ON_3dVector x0(1.0,0.0,0.0); | |||||
| const ON_3dVector y0(0.0,1.0,0.0); | |||||
| const ON_3dVector z0(0.0,0.0,1.0); | |||||
| const ON_3dVector x1 = x0; | |||||
| const ON_3dVector y1 = c1*y0 + s1*z0; | |||||
| const ON_3dVector z1 = -s1*y0 + c1*z0; | |||||
| const ON_3dVector y2 = y1; | |||||
| const ON_3dVector z2 = s2*x1 + c2*z1; | |||||
| const ON_3dVector x2 = c2*x1 - s2*z1; | |||||
| const ON_3dVector z3 = z2; | |||||
| const ON_3dVector x3 = c3*x2 + s3*y2; | |||||
| const ON_3dVector y3 = -s3*x2 + c3*y2; | |||||
| /* | |||||
| const ON_3dVector x1 = x0; | |||||
| const ON_3dVector y1 = (0.0, c1, s1); | |||||
| const ON_3dVector z1 = (0.0, -s1, c1); | |||||
| const ON_3dVector x2 = (c2, s2*s1, -s2*c1); // c2*x1 - s2*z1; | |||||
| const ON_3dVector y2 = (0.0, c1, s1); | |||||
| const ON_3dVector z2 = (s2, -c2*s1, c2*c1); // s2*x1 + c2*z1 | |||||
| */ | |||||
| ON_Xform r1; | |||||
| r1.Rotation(omega_radians,x0,ON_3dPoint::Origin); | |||||
| ON_3dVector r1y0 = r1*y0; | |||||
| ON_Xform r2; | |||||
| r2.Rotation(phi_radians,r1y0,ON_3dPoint::Origin); | |||||
| ON_3dVector r2r1z0 = r2*r1*z0; | |||||
| ON_Xform r3; | |||||
| r3.Rotation(kappa_radians,r2r1z0,ON_3dPoint::Origin); | |||||
| ON_Xform r321 = r3*r2*r1; | |||||
| ON_Xform zero = r321 - R; | |||||
| double a, b; | |||||
| double max_zero = 0.0; | |||||
| for ( int i = 0; i < 4; i++ ) for ( int j = 0; j < 4; j++ ) | |||||
| { | |||||
| a = fabs(zero[i][j]); | |||||
| if (a > max_zero ) | |||||
| max_zero = a; | |||||
| } | |||||
| b = fabs((x3-X).MaximumCoordinate()); | |||||
| if ( b > max_zero ) | |||||
| max_zero = b; | |||||
| b = fabs((y3-Y).MaximumCoordinate()); | |||||
| if ( b > max_zero ) | |||||
| max_zero = b; | |||||
| b = fabs((z3-Z).MaximumCoordinate()); | |||||
| if ( b > max_zero ) | |||||
| max_zero = b; | |||||
| if ( max_zero > 1.0e-15 ) | |||||
| ON_ERROR("Transform trauma"); | |||||
| } | |||||
| } | |||||
| else | |||||
| { | |||||
| UnsetOrientation(); | |||||
| } | |||||
| return rc; | |||||
| } | |||||
| bool ON_AerialPhotoImage::GetViewProjection( | |||||
| ON_BoundingBox target_bbox, | |||||
| ON_Viewport& viewport | |||||
| ) const | |||||
| { | |||||
| viewport = ON_Viewport::DefaultTopViewYUp; | |||||
| if ( !this->ImageSizeIsSet() ) | |||||
| return false; | |||||
| const int image_width_pixels = m_image_width_pixels; | |||||
| const int image_height_pixels = m_image_height_pixels; | |||||
| const ON_AerialPhotoImageFrustum& pg_if( m_image_frustum ); | |||||
| if ( !pg_if.IsSet() ) | |||||
| return false; | |||||
| const ON_AerialPhotoCameraPosition& pg_cp( m_camera_position ); | |||||
| if ( !pg_cp.LocationIsSet() ) | |||||
| return false; | |||||
| if ( !pg_cp.OrientationIsSet() ) | |||||
| return false; | |||||
| ON_3dPoint camera_location; | |||||
| if ( !pg_cp.GetLocation(camera_location) || !camera_location.IsValid() ) | |||||
| return false; | |||||
| ON_Xform camera_rotation; | |||||
| if ( !pg_cp.GetOrientationRotation(camera_rotation) | |||||
| || !camera_rotation.IsValid() | |||||
| ) | |||||
| return false; | |||||
| ON_Plane camera_plane; | |||||
| if (!pg_cp.GetOrientationFrame(camera_plane.xaxis,camera_plane.yaxis,camera_plane.zaxis)) | |||||
| return false; | |||||
| camera_plane.origin = camera_location; | |||||
| camera_plane.UpdateEquation(); | |||||
| const double frustum_to_position_unit_scale = ON::UnitScale( pg_if.m_unit_system, pg_cp.UnitSystem() ); | |||||
| if ( !ON_IsValid(frustum_to_position_unit_scale) | |||||
| || !(frustum_to_position_unit_scale > 0.0) | |||||
| ) | |||||
| return false; | |||||
| // The values of frus_near and frus_far are adjusted later | |||||
| // so the view's frustum contains the region in target_bbox. | |||||
| double frus_near = pg_if.m_height*frustum_to_position_unit_scale; | |||||
| if ( !ON_IsValid(frus_near) || !(frus_near > 0.0) ) | |||||
| return false; | |||||
| double frus_far = 128.0*frus_near; | |||||
| double frus_left, frus_right; | |||||
| double frus_bottom, frus_top; | |||||
| frus_left = frus_right = pg_if.m_corners[0].x; | |||||
| frus_bottom = frus_top = pg_if.m_corners[0].y; | |||||
| for ( size_t i = 1; i < sizeof(pg_if.m_corners)/sizeof(pg_if.m_corners[0]); i++ ) | |||||
| { | |||||
| if ( pg_if.m_corners[i].x < frus_left ) | |||||
| frus_left = pg_if.m_corners[i].x; | |||||
| else if ( pg_if.m_corners[i].x > frus_right ) | |||||
| frus_right = pg_if.m_corners[i].x; | |||||
| if ( pg_if.m_corners[i].y < frus_bottom ) | |||||
| frus_bottom = pg_if.m_corners[i].y; | |||||
| else if ( pg_if.m_corners[i].y > frus_top ) | |||||
| frus_top = pg_if.m_corners[i].y; | |||||
| } | |||||
| frus_left *= frustum_to_position_unit_scale; | |||||
| frus_right *= frustum_to_position_unit_scale; | |||||
| frus_bottom *= frustum_to_position_unit_scale; | |||||
| frus_top *= frustum_to_position_unit_scale; | |||||
| bool rc = false; | |||||
| ON_Viewport vp; | |||||
| for(;;) | |||||
| { | |||||
| if ( !vp.SetProjection( ON::perspective_view ) ) | |||||
| break; | |||||
| if ( !vp.SetCameraLocation( pg_cp.Location() ) ) | |||||
| break; | |||||
| if ( !vp.SetCameraDirection( -camera_plane.zaxis ) ) | |||||
| break; | |||||
| if ( !vp.SetCameraUp( camera_plane.yaxis ) ) | |||||
| break; | |||||
| if ( !vp.SetFrustum(frus_left,frus_right,frus_bottom,frus_top,frus_near,frus_far) ) | |||||
| break; | |||||
| if ( !vp.SetScreenPort(0,image_width_pixels,0,image_height_pixels) ) | |||||
| break; | |||||
| double bbox_near = ON_UNSET_VALUE; | |||||
| double bbox_far = ON_UNSET_VALUE; | |||||
| if ( vp.GetBoundingBoxDepth(target_bbox,&bbox_near,&bbox_far,false) ) | |||||
| { | |||||
| if ( frus_near > 0.0 && ON_IsValid(bbox_near) && frus_near < bbox_near ) | |||||
| { | |||||
| double s = 1.0; | |||||
| while ( 2.0*s*frus_near <= bbox_near ) | |||||
| s *= 2.0; | |||||
| if ( s >= 2.0 ) | |||||
| { | |||||
| frus_near *= s; | |||||
| frus_left *= s; | |||||
| frus_right *= s; | |||||
| frus_bottom *= s; | |||||
| frus_top *= s; | |||||
| frus_far = 1.0625*frus_near; | |||||
| } | |||||
| } | |||||
| if ( ON_IsValid(bbox_far) && frus_far < bbox_far ) | |||||
| { | |||||
| frus_far = 1.0625*bbox_far; | |||||
| const double max_frus_far = 67108864.0*frus_near; // 2^26 * frus_near | |||||
| if ( !(frus_far <= max_frus_far) ) | |||||
| frus_far = max_frus_far; | |||||
| } | |||||
| if ( !vp.SetFrustum(frus_left,frus_right,frus_bottom,frus_top,frus_near,frus_far) ) | |||||
| break; | |||||
| } | |||||
| rc = vp.IsValid() ? true : false; | |||||
| if ( rc ) | |||||
| viewport = vp; | |||||
| break; | |||||
| } | |||||
| return rc; | |||||
| } | |||||