1 /* $NoKeywords: $ */
2 /*
3 //
4 // Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved.
5 // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
6 // McNeel & Associates.
7 //
8 // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
9 // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
10 // MERCHANTABILITY ARE HEREBY DISCLAIMED.
11 //
12 // For complete openNURBS copyright information see <http://www.opennurbs.org>.
13 //
14 ////////////////////////////////////////////////////////////////
15 */
16 
17 #include "pcl/surface/3rdparty/opennurbs/opennurbs.h"
18 
ON_Cone()19 ON_Cone::ON_Cone()
20 {
21   height = 0.0;
22 }
23 
ON_Cone(const ON_Plane & p,double h,double r)24 ON_Cone::ON_Cone(
25     const ON_Plane& p,
26     double h,
27     double r
28     )
29 {
30   Create(p,h,r);
31 }
32 
~ON_Cone()33 ON_Cone::~ON_Cone()
34 {}
35 
36 
Create(const ON_Plane & p,double h,double r)37 ON_BOOL32 ON_Cone::Create(
38     const ON_Plane& p,
39     double h,
40     double r
41     )
42 {
43   plane = p;
44   height = h;
45   radius = r;
46   return IsValid();
47 }
48 
IsValid() const49 ON_BOOL32 ON_Cone::IsValid() const
50 {
51   return (plane.IsValid() && height != 0.0 && radius != 0.0);
52 }
53 
54 
Axis() const55 const ON_3dVector& ON_Cone::Axis() const
56 {
57   return plane.zaxis;
58 }
59 
ApexPoint() const60 const ON_3dPoint& ON_Cone::ApexPoint() const
61 {
62   return plane.origin;
63 }
64 
BasePoint() const65 ON_3dPoint ON_Cone::BasePoint() const
66 {
67   return plane.origin + height*plane.zaxis;
68 }
69 
AngleInRadians() const70 double ON_Cone::AngleInRadians() const
71 {
72   return height == 0.0 ? (radius!=0.0?ON_PI:0.0) : atan(radius/height);
73 }
74 
AngleInDegrees() const75 double ON_Cone::AngleInDegrees() const
76 {
77   return 180.0*AngleInRadians()/ON_PI;
78 }
79 
CircleAt(double height_parameter) const80 ON_Circle ON_Cone::CircleAt(
81       double height_parameter
82       ) const
83 {
84   ON_Circle c(plane,radius);
85   c.Translate(height_parameter*plane.zaxis);
86   if ( height != 0.0 )
87     c.radius *= height_parameter/height;
88   else if (height_parameter==0.0)
89     c.radius = 0.0;
90   return c;
91 }
92 
LineAt(double radial_parameter) const93 ON_Line ON_Cone::LineAt(
94       double radial_parameter
95       ) const
96 {
97   return ON_Line(PointAt(radial_parameter,height),ApexPoint());
98 }
99 
100 
PointAt(double radial_parameter,double height_parameter) const101 ON_3dPoint ON_Cone::PointAt( double radial_parameter, double height_parameter ) const
102 {
103   double r;
104   if ( height != 0.0 )
105     r = (radius/height)*height_parameter;
106   else
107     r = (height_parameter == 0.0)?0.0:radius;
108   return plane.PointAt(r*cos(radial_parameter),r*sin(radial_parameter)) + height_parameter*plane.zaxis;
109 }
110 
NormalAt(double radial_parameter,double) const111 ON_3dVector ON_Cone::NormalAt( double radial_parameter, double ) const
112 {
113   double s = sin(radial_parameter);
114   double c = cos(radial_parameter);
115   if ( radius<0.) {
116     c = -c;
117     s = -s;
118   }
119   ON_3dVector ds = c*plane.yaxis - s*plane.xaxis;
120   ON_3dVector N = ON_CrossProduct( ((radius<0.0)?-ds:ds),
121                                    plane.PointAt(radius*c,radius*s,height) - plane.origin
122                                    );
123   N.Unitize();
124   return N;
125 }
126 
Transform(const ON_Xform & xform)127 ON_BOOL32 ON_Cone::Transform( const ON_Xform& xform )
128 {
129   ON_Circle xc(plane,radius);
130   ON_BOOL32 rc = xc.Transform(xform);
131   if (rc)
132   {
133     ON_3dPoint xH = xform*(plane.origin + height*plane.zaxis);
134     double xh = (xH-xc.plane.origin)*xc.plane.zaxis;
135     plane = xc.plane;
136     radius = xc.radius;
137     height = xh;
138   }
139   return rc;
140 }
141 
ClosestPointTo(ON_3dPoint point,double * radial_parameter,double * height_parameter) const142 bool ON_Cone::ClosestPointTo(
143           ON_3dPoint point,
144           double* radial_parameter,
145           double* height_parameter
146        ) const
147 {
148   // untested code
149 
150   bool rc = false;
151 
152   ON_3dVector v = (point-plane.origin);
153   double x = v*plane.xaxis;
154   double y = v*plane.yaxis;
155   double z = v*plane.zaxis;
156 
157   if ( radial_parameter )
158   {
159     double a = ( 0.0 == y && 0.0 == x ) ? 0.0 : atan2(y,x);
160 
161     if (a > 2.0*ON_PI )
162     {
163       a -= 2.0*ON_PI;
164     }
165 
166     if (a < 0.0 )
167     {
168       a += 2.0*ON_PI;
169     }
170 
171     *radial_parameter = a;
172   }
173 
174   if (height_parameter)
175   {
176     point.x -= plane.origin.x;
177     point.y -= plane.origin.y;
178     point.z -= plane.origin.z;
179     v.x = x;
180     v.y = y;
181     v.z = 0.0;
182     v.Unitize();
183     v.x *= radius;
184     v.y *= radius;
185     ON_Line line(ON_origin, v.x*plane.xaxis + v.y*plane.yaxis + height*plane.zaxis );
186     rc = line.ClosestPointTo(point,&z);
187     if (rc)
188     {
189       *height_parameter = z*height;
190     }
191   }
192 
193   return rc;
194 }
195 
196 // returns point on cylinder that is closest to given point
ClosestPointTo(ON_3dPoint point) const197 ON_3dPoint ON_Cone::ClosestPointTo(
198        ON_3dPoint point
199        ) const
200 {
201   // untested code
202 
203   ON_3dVector v = (point-plane.origin);
204   double x = v*plane.xaxis;
205   double y = v*plane.yaxis;
206   //double z = v*plane.zaxis;
207 
208   point.x -= plane.origin.x;
209   point.y -= plane.origin.y;
210   point.z -= plane.origin.z;
211   v.x = x;
212   v.y = y;
213   v.z = 0.0;
214   v.Unitize();
215   v.x *= radius;
216   v.y *= radius;
217   ON_Line line(ON_origin, v.x*plane.xaxis + v.y*plane.yaxis + height*plane.zaxis );
218   return line.ClosestPointTo(point);
219 }
220 
Rotate(double sin_angle,double cos_angle,const ON_3dVector & axis_of_rotation)221 ON_BOOL32 ON_Cone::Rotate(
222       double sin_angle,
223       double cos_angle,
224       const ON_3dVector& axis_of_rotation
225       )
226 {
227   return Rotate( sin_angle, cos_angle, axis_of_rotation, plane.origin );
228 }
229 
Rotate(double angle,const ON_3dVector & axis_of_rotation)230 ON_BOOL32 ON_Cone::Rotate(
231       double angle,
232       const ON_3dVector& axis_of_rotation
233       )
234 {
235   return Rotate( sin(angle), cos(angle), axis_of_rotation, plane.origin );
236 }
237 
238 // rotate plane about a point and axis
Rotate(double sin_angle,double cos_angle,const ON_3dVector & axis_of_rotation,const ON_3dPoint & center_of_rotation)239 ON_BOOL32 ON_Cone::Rotate(
240       double sin_angle,
241       double cos_angle,
242       const ON_3dVector& axis_of_rotation,
243       const ON_3dPoint& center_of_rotation
244       )
245 {
246   return plane.Rotate( sin_angle, cos_angle, axis_of_rotation, center_of_rotation );
247 }
248 
Rotate(double angle,const ON_3dVector & axis,const ON_3dPoint & point)249 ON_BOOL32 ON_Cone::Rotate(
250       double angle,              // angle in radians
251       const ON_3dVector& axis, // axis of rotation
252       const ON_3dPoint&  point  // center of rotation
253       )
254 {
255   return Rotate( sin(angle), cos(angle), axis, point );
256 }
257 
Translate(const ON_3dVector & delta)258 ON_BOOL32 ON_Cone::Translate(
259       const ON_3dVector& delta
260       )
261 {
262   return plane.Translate( delta );
263 }
264 
GetNurbForm(ON_NurbsSurface & s) const265 int ON_Cone::GetNurbForm( ON_NurbsSurface& s ) const
266 {
267   int rc = 0;
268   if ( IsValid() ) {
269     ON_Circle c = CircleAt(height);
270     ON_NurbsCurve n;
271     c.GetNurbForm(n);
272     ON_3dPoint apex = ApexPoint();
273     ON_4dPoint cv;
274     int i, j0, j1;
275 
276     s.Create(3,true,3,2,9,2);
277     for ( i = 0; i < 10; i++ )
278       s.m_knot[0][i] = n.m_knot[i];
279 
280     if ( height >= 0.0 ) {
281       s.m_knot[1][0] = 0.0;
282       s.m_knot[1][1] = height;
283       j0 = 0;
284       j1 = 1;
285     }
286     else {
287       s.m_knot[1][0] = height;
288       s.m_knot[1][1] = 0.0;
289       j0 = 1;
290       j1 = 0;
291     }
292 
293     for ( i = 0; i < 9; i++ ) {
294       cv = n.CV(i);
295       s.SetCV(i, j1, ON::homogeneous_rational, &cv.x );
296       cv.x = apex.x*cv.w;
297       cv.y = apex.y*cv.w;
298       cv.z = apex.z*cv.w;
299       s.SetCV(i, j0, cv);
300     }
301     rc = 2;
302   }
303   return rc;
304 }
305 
RevSurfaceForm(ON_RevSurface * srf) const306 ON_RevSurface* ON_Cone::RevSurfaceForm( ON_RevSurface* srf ) const
307 {
308   if ( srf )
309     srf->Destroy();
310   ON_RevSurface* pRevSurface = NULL;
311   if ( IsValid() )
312   {
313     ON_Line line;
314     ON_Interval line_domain;
315     if ( height >= 0.0 )
316       line_domain.Set(0.0,height);
317     else
318       line_domain.Set(height,0.0);
319     line.from = PointAt(0.0,line_domain[0]);
320     line.to = PointAt(0.0,line_domain[1]);
321     ON_LineCurve* line_curve = new ON_LineCurve( line, line_domain[0], line_domain[1] );
322     if ( srf )
323       pRevSurface = srf;
324     else
325       pRevSurface = new ON_RevSurface();
326     pRevSurface->m_angle.Set(0.0,2.0*ON_PI);
327     pRevSurface->m_t = pRevSurface->m_angle;
328     pRevSurface->m_curve = line_curve;
329     pRevSurface->m_axis.from = plane.origin;
330     pRevSurface->m_axis.to = plane.origin + plane.zaxis;
331     pRevSurface->m_bTransposed = false;
332     pRevSurface->m_bbox.m_min = plane.origin;
333     pRevSurface->m_bbox.m_max = plane.origin;
334     pRevSurface->m_bbox.Union(CircleAt(height).BoundingBox());
335   }
336   return pRevSurface;
337 }
338 
339 /*
340 // obsolete use ON_BrepCone
341 ON_Brep* ON_Cone::BrepForm( ON_Brep* brep ) const
342 {
343   ON_Brep* pBrep = 0;
344   if ( brep )
345     brep->Destroy();
346   ON_RevSurface* pRevSurface = RevSurfaceForm();
347   if ( pRevSurface )
348   {
349     if ( brep )
350       pBrep = brep;
351     else
352       pBrep = new ON_Brep();
353     if ( !pBrep->Create(pRevSurface) )
354     {
355       if ( !brep )
356         delete pBrep;
357       pBrep = 0;
358       if ( !pRevSurface )
359       {
360         delete pRevSurface;
361         pRevSurface = 0;
362       }
363     }
364     else
365     {
366       // add cap
367       ON_Circle circle = CircleAt(height);
368       ON_NurbsSurface* pCapSurface = ON_NurbsSurfaceQuadrilateral(
369         circle.plane.PointAt(-radius,-radius),
370         circle.plane.PointAt(+radius,-radius),
371         circle.plane.PointAt(+radius,+radius),
372         circle.plane.PointAt(-radius,+radius)
373         );
374       pCapSurface->m_knot[0][0] = -fabs(radius);
375       pCapSurface->m_knot[0][1] =  fabs(radius);
376       pCapSurface->m_knot[1][0] = pCapSurface->m_knot[0][0];
377       pCapSurface->m_knot[1][1] = pCapSurface->m_knot[0][1];
378       circle.Create( ON_xy_plane, ON_origin, radius );
379       ON_NurbsCurve* c2 = new ON_NurbsCurve();
380       circle.GetNurbForm(*c2);
381       c2->ChangeDimension(2);
382 
383       pBrep->m_S.Append(pCapSurface);
384       pBrep->m_C2.Append(c2);
385       ON_BrepFace& cap = pBrep->NewFace( pBrep->m_S.Count()-1 );
386       ON_BrepLoop& loop = pBrep->NewLoop( ON_BrepLoop::outer, cap );
387       ON_BrepEdge& edge = pBrep->m_E[1];
388       ON_BrepTrim& trim = pBrep->NewTrim( edge, true, loop, pBrep->m_C2.Count()-1 );
389       trim.m_tolerance[0] = 0.0;
390       trim.m_tolerance[1] = 0.0;
391       trim.m_pbox.m_min.x = -radius;
392       trim.m_pbox.m_min.y = -radius;
393       trim.m_pbox.m_min.z = 0.0;
394       trim.m_pbox.m_max.x = radius;
395       trim.m_pbox.m_max.y = radius;
396       trim.m_pbox.m_max.z = 0.0;
397       loop.m_pbox = trim.m_pbox;
398       pBrep->SetTrimIsoFlags(trim);
399       for ( int eti = 0; eti < edge.m_ti.Count(); eti++ )
400         pBrep->m_T[ edge.m_ti[eti] ].m_type = ON_BrepTrim::mated;
401       if ( !pBrep->IsValid() )
402       {
403         if (brep)
404           brep->Destroy();
405         else
406           delete pBrep;
407         pBrep = 0;
408       }
409     }
410   }
411   return pBrep;
412 }
413 */
414