/* $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_Cylinder::ON_Cylinder() { height[0] = 0.0; height[1] = 0.0; } ON_Cylinder::ON_Cylinder( const ON_Circle& c ) { Create(c); } ON_Cylinder::ON_Cylinder( const ON_Circle& c, double h ) { Create(c,h); } ON_Cylinder::~ON_Cylinder() {} bool ON_Cylinder::Create( const ON_Circle& c ) { return Create( c, 0.0 ); } bool ON_Cylinder::Create( const ON_Circle& c, double h ) { circle = c; if ( h > 0.0 ) { height[0] = 0.0; height[1] = h; } else { height[0] = h; height[1] = 0.0; } return IsValid(); } bool ON_Cylinder::IsValid() const { return circle.IsValid(); } bool ON_Cylinder::IsFinite() const { return height[0] != height[1]; } const ON_3dVector& ON_Cylinder::Axis() const { return circle.plane.zaxis; } const ON_3dPoint& ON_Cylinder::Center() const { return circle.plane.origin; } double ON_Cylinder::Height() const { return height[1] - height[0]; } ON_Circle ON_Cylinder::CircleAt( double t // linear parameter ) const { ON_Circle c = circle; if ( t != 0.0 ) c.Translate(t*circle.plane.zaxis); return c; } ON_Line ON_Cylinder::LineAt( double s // angular parameter ) const { ON_3dPoint p = circle.PointAt(s); ON_Line line; line.from = p + height[0]*circle.plane.zaxis; line.to = p + height[1]*circle.plane.zaxis; return line; } ON_3dPoint ON_Cylinder::PointAt( double s, double t ) const { return ( circle.PointAt(s) + t*circle.plane.zaxis ); } ON_3dPoint ON_Cylinder::NormalAt( double s, double t ) const { ON_3dVector N = ON_CrossProduct( circle.TangentAt(s), circle.plane.zaxis ); N.Unitize(); return N; } // returns parameters of point on cylinder that is closest to given point bool ON_Cylinder::ClosestPointTo( ON_3dPoint point, double* s, // angular parameter double* t // linear parameter ) const { bool rc = true; //const ON_3dVector v = point - circle.plane.origin; double h = (point - circle.plane.origin)*circle.plane.zaxis; if ( s ) rc = circle.ClosestPointTo( point - h*circle.plane.zaxis, s ); if ( t ) { if ( height[0] < height[1] ) { if ( h < height[0] ) h = height[0]; else if ( h > height[1] ) h = height[1]; } else if ( height[0] > height[1] ) { if ( h > height[0] ) h = height[0]; else if ( h < height[1] ) h = height[1]; } *t = h; } return rc; } // returns point on cylinder that is closest to given point ON_3dPoint ON_Cylinder::ClosestPointTo( ON_3dPoint point ) const { double s, t; ClosestPointTo( point, &s, &t ); return PointAt( s, t ); } // rotate plane about its origin bool ON_Cylinder::Rotate( double sin_angle, double cos_angle, const ON_3dVector& axis // axis of rotation ) { return Rotate( sin_angle, cos_angle, axis, circle.plane.origin ); } bool ON_Cylinder::Rotate( double angle, // angle in radians const ON_3dVector& axis // axis of rotation ) { return Rotate( sin(angle), cos(angle), axis, circle.plane.origin ); } // rotate plane about a point and axis bool ON_Cylinder::Rotate( double sin_angle, // sin(angle) double cos_angle, // cos(angle) const ON_3dVector& axis, // axis of rotation const ON_3dPoint& point // center of rotation ) { return circle.Rotate( sin_angle, cos_angle, axis, point ); } bool ON_Cylinder::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_Cylinder::Translate( const ON_3dVector& delta ) { return circle.Translate( delta ); } int ON_Cylinder::GetNurbForm( ON_NurbsSurface& s ) const { int rc = 0; if ( IsValid() && height[0] != height[1] ) { ON_NurbsCurve n0, n1; int i; ON_Circle c0 = CircleAt(height[0]); ON_Circle c1 = CircleAt(height[1]); if ( height[0] <= height[1] ) { c0.GetNurbForm(n0); c1.GetNurbForm(n1); } else { c0.GetNurbForm(n1); c1.GetNurbForm(n0); } if ( n0.m_dim != n1.m_dim || n0.m_is_rat != n1.m_is_rat || n0.m_order != n1.m_order || n0.m_cv_count != n1.m_cv_count ) return 0; s.Create(3,true, n0.m_order, 2, n0.m_cv_count, 2 ); if ( height[0] <= height[1] ) { s.m_knot[1][0] = height[0]; s.m_knot[1][1] = height[1]; } else { s.m_knot[1][0] = height[1]; s.m_knot[1][1] = height[0]; } for ( i = 0; i < n0.KnotCount(); i++ ) s.m_knot[0][i] = n0.m_knot[i]; for ( i = 0; i < n0.m_cv_count; i++ ) { s.SetCV(i,0,ON::homogeneous_rational,n0.CV(i)); s.SetCV(i,1,ON::homogeneous_rational,n1.CV(i)); } rc = 2; } return rc; } ON_RevSurface* ON_Cylinder::RevSurfaceForm( ON_RevSurface* srf ) const { if ( srf ) srf->Destroy(); ON_RevSurface* pRevSurface = nullptr; if ( IsFinite() && IsValid() ) { ON_Line line; line.from = PointAt(0.0,height[0]); line.to = PointAt(0.0,height[1]); ON_Interval h(height[0],height[1]); // h = evaluation domain for line (must be increasing) if ( h.IsDecreasing() ) h.Swap(); ON_LineCurve* line_curve = new ON_LineCurve( line, h[0], h[1] ); 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 = line_curve; pRevSurface->m_axis.from = circle.plane.origin; pRevSurface->m_axis.to = circle.plane.origin + circle.plane.zaxis; pRevSurface->m_bTransposed = false; ON_Circle c0(circle); c0.Translate(height[0]*circle.plane.zaxis); ON_Circle c1(circle); c1.Translate(height[1]*circle.plane.zaxis); pRevSurface->m_bbox = c0.BoundingBox(); pRevSurface->m_bbox.Union(c1.BoundingBox()); } return pRevSurface; } /* // obsolete use ON_BrepCylinder ON_Brep* ON_Cylinder::BrepForm( ON_Brep* brep ) const { if ( brep ) brep->Destroy(); ON_Brep* pBrep = 0; ON_RevSurface* pRevSurface = RevSurfaceForm(); if ( pRevSurface ) { if ( brep ) pBrep = brep; else pBrep = new ON_Brep(); if ( !pBrep->Create(pRevSurface) ) { if ( !brep ) delete pBrep; pBrep = 0; if (pRevSurface) { delete pRevSurface; pRevSurface = 0; } } else { // add caps for ( int capcount = 0; capcount < 2; capcount++ ) { // capcount = 0 for bottom cap and 1 for top cap ON_Circle circle = CircleAt(height[capcount]); if ( capcount == 0 ) circle.Reverse(); double radius = circle.radius; ON_NurbsSurface* pCapSurface = ON_NurbsSurfaceQuadrilateral( circle.plane.PointAt(-radius,-radius), circle.plane.PointAt(+radius,-radius), circle.plane.PointAt(+radius,+radius), circle.plane.PointAt(-radius,+radius) ); pCapSurface->m_knot[0][0] = -fabs(radius); pCapSurface->m_knot[0][1] = fabs(radius); pCapSurface->m_knot[1][0] = pCapSurface->m_knot[0][0]; pCapSurface->m_knot[1][1] = pCapSurface->m_knot[0][1]; circle.Create( ON_xy_plane, ON_3dPoint::Origin, radius ); ON_NurbsCurve* c2 = new ON_NurbsCurve(); circle.GetNurbForm(*c2); c2->ChangeDimension(2); pBrep->m_S.Append(pCapSurface); pBrep->m_C2.Append(c2); ON_BrepFace& cap = pBrep->NewFace( pBrep->m_S.Count()-1 ); ON_BrepLoop& loop = pBrep->NewLoop( ON_BrepLoop::outer, cap ); ON_BrepEdge& edge = pBrep->m_E[capcount?0:2]; ON_BrepTrim& trim = pBrep->NewTrim( edge, true, loop, pBrep->m_C2.Count()-1 ); for ( int eti = 0; eti < edge.m_ti.Count(); eti++ ) pBrep->m_T[ edge.m_ti[eti] ].m_type = ON_BrepTrim::mated; trim.m_tolerance[0] = 0.0; trim.m_tolerance[1] = 0.0; trim.m_pbox.m_min.x = -radius; trim.m_pbox.m_min.y = -radius; trim.m_pbox.m_min.z = 0.0; trim.m_pbox.m_max.x = radius; trim.m_pbox.m_max.y = radius; trim.m_pbox.m_max.z = 0.0; loop.m_pbox = trim.m_pbox; pBrep->SetTrimTypeFlags(trim); pBrep->SetTrimIsoFlags(trim); } if ( !pBrep->IsValid() ) { if (brep) brep->Destroy(); else delete pBrep; pBrep = 0; } } } return pBrep; } */