Changeset View
Changeset View
Standalone View
Standalone View
extern/opennurbs/opennurbs_torus.cpp
- This file was added.
| /* $NoKeywords: $ */ | |||||
| /* | |||||
| // | |||||
| // Copyright (c) 1993-2012 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" | |||||
| ON_Torus::ON_Torus() : major_radius(0.0), minor_radius(0.0) | |||||
| {} | |||||
| ON_Torus::ON_Torus( const ON_Plane& major_plane, double major__radius, double minor__radius ) | |||||
| { | |||||
| Create(major_plane,major__radius,minor__radius); | |||||
| } | |||||
| ON_Torus::ON_Torus( const ON_Circle& major__circle, double minor__radius ) | |||||
| { | |||||
| Create(major__circle,minor__radius); | |||||
| } | |||||
| ON_Torus::~ON_Torus() | |||||
| {} | |||||
| ON_BOOL32 ON_Torus::IsValid( ON_TextLog* text_log ) const | |||||
| { | |||||
| bool rc=false; | |||||
| if ( minor_radius <= 0.0 ) | |||||
| { | |||||
| if ( text_log ) | |||||
| text_log->Print("ON_Torus.minor_radius = %g (should be > 0)\n",minor_radius); | |||||
| } | |||||
| else if ( major_radius <= minor_radius) | |||||
| { | |||||
| if ( text_log ) | |||||
| text_log->Print("ON_Torus.major_radius = %g (should be > minor_radius=%g)\n",major_radius,minor_radius); | |||||
| } | |||||
| else if ( !plane.IsValid() ) | |||||
| { | |||||
| if ( text_log ) | |||||
| text_log->Print("ON_Torus.plane is not valid.\n"); | |||||
| } | |||||
| else | |||||
| rc = true; | |||||
| return rc; | |||||
| } | |||||
| ON_BOOL32 ON_Torus::Create( const ON_Plane& major_plane, double major__radius, double minor__radius ) | |||||
| { | |||||
| plane = major_plane; | |||||
| major_radius = major__radius; | |||||
| minor_radius = minor__radius; | |||||
| return IsValid(); | |||||
| } | |||||
| ON_BOOL32 ON_Torus::Create( const ON_Circle& major__circle, double minor__radius ) | |||||
| { | |||||
| return Create( major__circle.plane, major__circle.radius, minor__radius ); | |||||
| } | |||||
| #define EVAL_SETUP_MINOR \ | |||||
| const double sin_ma = sin(minor_angle_radians);\ | |||||
| const double cos_ma = cos(minor_angle_radians) | |||||
| #define EVAL_SETUP_MAJOR \ | |||||
| const double sin_MA = sin(major_angle_radians);\ | |||||
| const double cos_MA = cos(major_angle_radians);\ | |||||
| const ON_3dVector raxis = cos_MA*plane.xaxis + sin_MA*plane.yaxis | |||||
| ON_3dPoint ON_Torus::PointAt(double major_angle_radians, double minor_angle_radians) const | |||||
| { | |||||
| EVAL_SETUP_MINOR; | |||||
| EVAL_SETUP_MAJOR; | |||||
| return ((major_radius + cos_ma*minor_radius)*raxis + sin_ma*minor_radius*plane.zaxis + plane.origin); | |||||
| } | |||||
| ON_3dVector ON_Torus::NormalAt(double major_angle_radians, double minor_angle_radians) const | |||||
| { | |||||
| EVAL_SETUP_MINOR; | |||||
| EVAL_SETUP_MAJOR; | |||||
| return (cos_ma*raxis + sin_ma*plane.zaxis); | |||||
| } | |||||
| ON_Circle ON_Torus::MajorCircleRadians(double minor_angle_radians ) const | |||||
| { | |||||
| EVAL_SETUP_MINOR; | |||||
| ON_Circle c(plane,major_radius); | |||||
| c.radius = major_radius + cos_ma*minor_radius; | |||||
| c.plane.origin += sin_ma*minor_radius*plane.zaxis; | |||||
| c.plane.UpdateEquation(); | |||||
| return c; | |||||
| } | |||||
| ON_Circle ON_Torus::MajorCircleDegrees(double minor_angle_degrees ) const | |||||
| { | |||||
| return MajorCircleRadians(minor_angle_degrees*ON_PI/180.0); | |||||
| } | |||||
| ON_Circle ON_Torus::MinorCircleRadians(double major_angle_radians ) const | |||||
| { | |||||
| EVAL_SETUP_MAJOR; | |||||
| ON_Circle c; | |||||
| c.plane.xaxis = raxis; | |||||
| c.plane.yaxis = plane.zaxis; | |||||
| c.plane.zaxis = ON_CrossProduct( c.plane.xaxis, c.plane.yaxis ); | |||||
| c.plane.origin = plane.origin + major_radius*raxis; | |||||
| c.plane.UpdateEquation(); | |||||
| c.radius = minor_radius; | |||||
| return c; | |||||
| } | |||||
| ON_Circle ON_Torus::MinorCircleDegrees(double minor_angle_degrees ) const | |||||
| { | |||||
| return MinorCircleRadians(minor_angle_degrees*ON_PI/180.0); | |||||
| } | |||||
| ON_3dPoint ON_Torus::Center() const | |||||
| { | |||||
| return plane.origin; | |||||
| } | |||||
| ON_3dVector ON_Torus::Axis() const | |||||
| { | |||||
| return plane.zaxis; | |||||
| } | |||||
| double ON_Torus::MajorRadius() const | |||||
| { | |||||
| return major_radius; | |||||
| } | |||||
| double ON_Torus::MinorRadius() const | |||||
| { | |||||
| return minor_radius; | |||||
| } | |||||
| ON_BOOL32 ON_Torus::ClosestPointTo( | |||||
| ON_3dPoint test_point, | |||||
| double* major__angle_radians, | |||||
| double* minor__angle_radians | |||||
| ) const | |||||
| { | |||||
| double major_angle_radians, minor_angle_radians; | |||||
| const ON_Circle major_circle(plane,major_radius); | |||||
| ON_BOOL32 rc = major_circle.ClosestPointTo( test_point, &major_angle_radians ); | |||||
| if ( rc && minor__angle_radians ) | |||||
| { | |||||
| EVAL_SETUP_MAJOR; | |||||
| ON_3dVector v = test_point - major_radius*raxis; | |||||
| rc = v.Unitize(); | |||||
| if ( rc ) | |||||
| { | |||||
| double sma = v*plane.zaxis; | |||||
| double cma = v*raxis; | |||||
| minor_angle_radians = atan2(sma,cma); | |||||
| if ( minor_angle_radians < 0.0 ) | |||||
| minor_angle_radians += 2.0*ON_PI; | |||||
| } | |||||
| else | |||||
| minor_angle_radians = 0.0; | |||||
| *minor__angle_radians = minor_angle_radians; | |||||
| } | |||||
| if ( major__angle_radians ) | |||||
| *major__angle_radians = major_angle_radians; | |||||
| return rc; | |||||
| } | |||||
| ON_3dPoint ON_Torus::ClosestPointTo( ON_3dPoint test_point ) const | |||||
| { | |||||
| const ON_Circle major_circle(plane,major_radius); | |||||
| ON_3dPoint C = major_circle.ClosestPointTo( test_point ); | |||||
| ON_3dVector v = test_point - C; | |||||
| if ( !v.Unitize() ) | |||||
| { | |||||
| v = C - plane.origin; | |||||
| v.Unitize(); | |||||
| } | |||||
| return C + minor_radius*v; | |||||
| } | |||||
| // rotate cylinder about its origin | |||||
| ON_BOOL32 ON_Torus::Rotate( | |||||
| double sin_angle, | |||||
| double cos_angle, | |||||
| const ON_3dVector& axis // axis of rotation | |||||
| ) | |||||
| { | |||||
| return Rotate(sin_angle, cos_angle, axis, plane.origin ); | |||||
| } | |||||
| ON_BOOL32 ON_Torus::Rotate( | |||||
| double angle, // angle in radians | |||||
| const ON_3dVector& axis // axis of rotation | |||||
| ) | |||||
| { | |||||
| return Rotate(sin(angle), cos(angle), axis, plane.origin ); | |||||
| } | |||||
| ON_BOOL32 ON_Torus::Rotate( | |||||
| double sin_angle, | |||||
| double cos_angle, | |||||
| const ON_3dVector& axis, // axis of rotation | |||||
| const ON_3dPoint& point // center of rotation | |||||
| ) | |||||
| { | |||||
| return plane.Rotate( sin_angle, cos_angle, axis, point ); | |||||
| } | |||||
| ON_BOOL32 ON_Torus::Rotate( | |||||
| double angle, // angle in radians | |||||
| const ON_3dVector& axis, // axis of rotation | |||||
| const ON_3dPoint& point // center of rotation | |||||
| ) | |||||
| { | |||||
| return Rotate(sin(angle),cos(angle),axis,point); | |||||
| } | |||||
| ON_BOOL32 ON_Torus::Translate( const ON_3dVector& delta ) | |||||
| { | |||||
| return plane.Translate(delta); | |||||
| } | |||||
| ON_BOOL32 ON_Torus::Transform( const ON_Xform& xform ) | |||||
| { | |||||
| ON_Circle major_c(plane,major_radius); | |||||
| ON_BOOL32 rc = major_c.Transform(xform); | |||||
| if (rc) | |||||
| { | |||||
| double s = (0.0==major_radius) ? 1.0 : major_c.radius/major_radius; | |||||
| plane = major_c.plane; | |||||
| major_radius = major_c.radius; | |||||
| minor_radius *= s; | |||||
| } | |||||
| return rc; | |||||
| } | |||||
| int ON_Torus::GetNurbForm( ON_NurbsSurface& s ) const | |||||
| { | |||||
| int rc = 0; | |||||
| ON_RevSurface revsrf; | |||||
| if ( RevSurfaceForm(&revsrf) ) | |||||
| { | |||||
| rc = revsrf.GetNurbForm(s); | |||||
| } | |||||
| else | |||||
| s.Destroy(); | |||||
| return rc; | |||||
| } | |||||
| ON_RevSurface* ON_Torus::RevSurfaceForm( ON_RevSurface* srf ) const | |||||
| { | |||||
| if ( srf ) | |||||
| srf->Destroy(); | |||||
| ON_RevSurface* pRevSurface = NULL; | |||||
| if ( IsValid() ) | |||||
| { | |||||
| ON_Circle circle = MinorCircleRadians(0.0); | |||||
| ON_ArcCurve* circle_crv = new ON_ArcCurve(circle); | |||||
| if ( srf ) | |||||
| pRevSurface = srf; | |||||
| else | |||||
| pRevSurface = new ON_RevSurface(); | |||||
| pRevSurface->m_angle.Set(0.0,2.0*ON_PI); | |||||
| pRevSurface->m_t = pRevSurface->m_angle; | |||||
| pRevSurface->m_curve = circle_crv; | |||||
| pRevSurface->m_axis.from = plane.origin; | |||||
| pRevSurface->m_axis.to = plane.origin + plane.zaxis; | |||||
| pRevSurface->m_bTransposed = false; | |||||
| double r[2], h[2]; | |||||
| h[0] = fabs(minor_radius); | |||||
| h[1] = -h[0]; | |||||
| r[0] = fabs(major_radius) + h[0]; | |||||
| r[1] = -r[0]; | |||||
| int i, j, k, n=0; | |||||
| ON_3dPoint pt[8]; | |||||
| for (i=0;i<2;i++) | |||||
| { | |||||
| for (j=0;j<2;j++) | |||||
| { | |||||
| for (k=0;k<2;k++) | |||||
| { | |||||
| pt[n++] = plane.PointAt( r[i], r[j], h[k] ); | |||||
| } | |||||
| } | |||||
| } | |||||
| pRevSurface->m_bbox.Set( 3, 0, 8, 3, &pt[0].x ); | |||||
| } | |||||
| return pRevSurface; | |||||
| } | |||||