/* $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 . // //////////////////////////////////////////////////////////////// */ #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_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() {} bool 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; } bool 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(); } bool 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; } bool 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); bool 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 bool 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 ); } bool ON_Torus::Rotate( double angle, // angle in radians const ON_3dVector& axis // axis of rotation ) { return Rotate(sin(angle), cos(angle), axis, plane.origin ); } bool 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 ); } bool 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); } bool ON_Torus::Translate( const ON_3dVector& delta ) { return plane.Translate(delta); } bool ON_Torus::Transform( const ON_Xform& xform ) { ON_Circle major_c(plane,major_radius); bool 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 = nullptr; 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_t[0] = 0.0; pRevSurface->m_t[1] = 2.0*ON_PI*MajorRadius(); 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; }