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