mirror of
https://github.com/mcneel/opennurbs.git
synced 2026-03-01 03:26:09 +08:00
309 lines
7.9 KiB
C++
309 lines
7.9 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_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;
|
|
}
|