mirror of
https://github.com/mcneel/opennurbs.git
synced 2026-03-01 03:26:09 +08:00
879 lines
21 KiB
C++
879 lines
21 KiB
C++
//
|
|
// Copyright (c) 1993-2022 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 camera (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;
|
|
}
|