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 "opennurbs.h"
18 
19 
ON_Localizer()20 ON_Localizer::ON_Localizer()
21 {
22   m_nurbs_curve = 0;
23   m_nurbs_surface = 0;
24   Destroy();
25 }
26 
~ON_Localizer()27 ON_Localizer::~ON_Localizer()
28 {
29   Destroy();
30 }
31 
ON_Localizer(const ON_Localizer & src)32 ON_Localizer::ON_Localizer(const ON_Localizer& src)
33 {
34   m_nurbs_curve = 0;
35   m_nurbs_surface = 0;
36   Destroy();
37   *this = src;
38 }
39 
operator =(const ON_Localizer & src)40 ON_Localizer& ON_Localizer::operator=(const ON_Localizer& src)
41 {
42   if ( this != &src )
43   {
44     Destroy();
45     m_type = src.m_type;
46     m_d = src.m_d;
47     m_P = src.m_P;
48     m_V = src.m_V;
49     if ( src.m_nurbs_curve )
50       m_nurbs_curve = src.m_nurbs_curve->Duplicate();
51     if ( src.m_nurbs_surface )
52       m_nurbs_surface = src.m_nurbs_surface->Duplicate();
53   }
54   return *this;
55 }
56 
57 
Destroy()58 void ON_Localizer::Destroy()
59 {
60   m_type = no_type;
61   m_P.Set(0.0,0.0,0.0);
62   m_V.Set(0.0,0.0,0.0);
63   m_d.Set(0.0,0.0);
64   if (m_nurbs_curve)
65   {
66     delete m_nurbs_curve;
67     m_nurbs_curve = 0;
68   }
69   if (m_nurbs_surface)
70   {
71     delete m_nurbs_surface;
72     m_nurbs_surface = 0;
73   }
74 }
75 
Write(ON_BinaryArchive & archive) const76 bool ON_Localizer::Write(ON_BinaryArchive& archive) const
77 {
78   bool rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0);
79   if (!rc)
80     return false;
81 
82   for(;;)
83   {
84     rc = archive.WriteInt(m_type);
85     if ( !rc ) break;
86     rc = archive.WritePoint(m_P);
87     if ( !rc ) break;
88     rc = archive.WriteVector(m_V);
89     if ( !rc ) break;
90     rc = archive.WriteInterval(m_d);
91     if ( !rc ) break;
92 
93     rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0);
94     if (!rc) break;
95     rc = archive.WriteBool( m_nurbs_curve ? true : false );
96     if ( rc && m_nurbs_curve )
97       rc = m_nurbs_curve->Write(archive)?true:false;
98     if ( !archive.EndWrite3dmChunk() )
99       rc = false;
100     if (!rc) break;
101 
102     rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0);
103     if (!rc) break;
104     rc = archive.WriteBool( m_nurbs_surface ? true : false );
105     if ( rc && m_nurbs_surface )
106       rc = m_nurbs_surface->Write(archive)?true:false;
107     if ( !archive.EndWrite3dmChunk() )
108       rc = false;
109     if (!rc) break;
110 
111     break;
112   }
113 
114   if ( !archive.EndWrite3dmChunk() )
115     rc = false;
116 
117   return rc;
118 }
119 
Read(ON_BinaryArchive & archive)120 bool ON_Localizer::Read(ON_BinaryArchive& archive)
121 {
122   Destroy();
123 
124   int major_version = 0;
125   int minor_version = 0;
126   bool rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
127   if (!rc)
128     return false;
129 
130   for(;;)
131   {
132     rc = (1 == major_version);
133     if ( !rc ) break;
134 
135     int i = no_type;
136     rc = archive.ReadInt(&i);
137     if ( !rc ) break;
138 
139     switch(i)
140     {
141     case sphere_type:   m_type = sphere_type;   break;
142     case plane_type:    m_type = plane_type;    break;
143     case cylinder_type: m_type = cylinder_type; break;
144     case curve_type:    m_type = curve_type;    break;
145     case surface_type:  m_type = surface_type;  break;
146     case distance_type: m_type = distance_type; break;
147     }
148 
149     rc = archive.ReadPoint(m_P);
150     if ( !rc ) break;
151     rc = archive.ReadVector(m_V);
152     if ( !rc ) break;
153     rc = archive.ReadInterval(m_d);
154     if ( !rc ) break;
155 
156     int mjv = 0, mnv = 0;
157     rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&mjv,&mnv);
158     if (!rc) break;
159     rc = (1 == mjv);
160     bool bReadCurve = false;
161     if (rc)
162       rc = archive.ReadBool( &bReadCurve );
163     if ( rc && bReadCurve)
164     {
165       m_nurbs_curve = new ON_NurbsCurve();
166       rc = m_nurbs_curve->Read(archive)?true:false;
167     }
168     if ( !archive.EndRead3dmChunk() )
169       rc = false;
170     if (!rc) break;
171 
172     rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&mjv,&mnv);
173     if (!rc) break;
174     rc = (1 == mjv);
175     bool bReadSurface = false;
176     rc = archive.ReadBool( &bReadSurface );
177     if ( rc && bReadSurface )
178     {
179       m_nurbs_surface = new ON_NurbsSurface();
180       rc = m_nurbs_surface->Read(archive)?true:false;
181     }
182     if ( !archive.EndRead3dmChunk() )
183       rc = false;
184     if (!rc) break;
185 
186     break;
187   }
188 
189   if ( !archive.EndRead3dmChunk() )
190     rc = false;
191 
192   return rc;
193 }
194 
195 
CreateCylinderLocalizer(ON_3dPoint P,ON_3dVector V,double r0,double r1)196 bool ON_Localizer::CreateCylinderLocalizer( ON_3dPoint P, ON_3dVector V, double r0, double r1 )
197 {
198   Destroy();
199   if (    P.IsValid()
200        && V.IsValid()
201        && V.Length() > 0.0
202        && ON_IsValid(r0)
203        && ON_IsValid(r1)
204        && r0 > 0.0
205        && r1 > 0.0
206        && r0 != r1 )
207   {
208     m_P = P;
209     m_V = V;
210     m_V.Unitize();
211     m_d.Set(r0,r1);
212     m_type = cylinder_type;
213   }
214   return (cylinder_type == m_type);
215 }
216 
CreatePlaneLocalizer(ON_3dPoint P,ON_3dVector N,double h0,double h1)217 bool ON_Localizer::CreatePlaneLocalizer( ON_3dPoint P, ON_3dVector N, double h0, double h1 )
218 {
219   Destroy();
220   if ( P.IsValid()
221        && N.IsValid()
222        && N.Length() > 0.0
223        && ON_IsValid(h0)
224        && ON_IsValid(h1)
225        && h0 != h1 )
226   {
227     m_V = N;
228     m_V.Unitize();
229     m_P.Set( -(m_V.x*P.x + m_V.y*P.y + m_V.z*P.z), 0.0, 0.0 );
230     m_d.Set(h0,h1);
231     m_type = plane_type;
232   }
233   return (plane_type == m_type);
234 }
235 
CreateSphereLocalizer(ON_3dPoint P,double r0,double r1)236 bool ON_Localizer::CreateSphereLocalizer( ON_3dPoint P, double r0, double r1 )
237 {
238   Destroy();
239   if ( P.IsValid()
240        && ON_IsValid(r0)
241        && ON_IsValid(r1)
242        && r0 > 0.0
243        && r1 > 0.0
244        && r0 != r1 )
245   {
246     m_P = P;
247     m_V.Zero();
248     m_d.Set(r0,r1);
249     m_type = sphere_type;
250   }
251   return (sphere_type == m_type);
252 }
253 
Value(double t) const254 double ON_Localizer::Value(double t) const
255 {
256   double s = m_d.NormalizedParameterAt(t);
257   if ( s <= 0.0 )
258     s = 0.0;
259   else if ( s >= 1.0 )
260     s = 1.0;
261   else
262     s = s*s*(3.0 - 2.0*s);
263 
264   return s;
265 }
266 
Value(ON_3dPoint P) const267 double ON_Localizer::Value(ON_3dPoint P) const
268 {
269   double t = m_d.m_t[1];
270 
271   switch ( m_type )
272   {
273   case cylinder_type:
274     // t = distance from P to axis
275     t = ON_CrossProduct( P-m_P, m_V ).Length();
276     break;
277 
278   case plane_type:
279     // t = distance above plane
280     t = m_V.x*P.x + m_V.y*P.y + m_V.z*P.z + m_P.x;
281     break;
282 
283   case sphere_type:
284     // t = distance to P
285     t = (P-m_P).Length();
286     break;
287 
288   case curve_type:
289     break;
290 
291   case surface_type:
292     break;
293 
294   case distance_type:
295     // confused user should be calling Value(double)
296     return 1.0; // default must be one
297     break;
298 
299   default:
300     return 1.0; // default must be one
301   }
302 
303   return Value(t);
304 }
305 
306 
IsZero(const ON_BoundingBox & bbox) const307 bool ON_Localizer::IsZero( const ON_BoundingBox& bbox ) const
308 {
309   bool rc = false;
310 
311   ON_BoundingBox loc_bbox;
312   bool bTestLocBox = false;
313   double d;
314 
315   switch ( m_type )
316   {
317   case cylinder_type:
318     {
319       ON_3dPointArray corners;
320       bbox.GetCorners(corners);
321       int i;
322       double t0, t1;
323       t0 = t1 = (corners[0]-m_P)*m_V;
324       for ( i = 1; i < 8; i++ )
325       {
326         d = (corners[i]-m_P)*m_V;
327         if ( d < t0 )
328           t0 = d;
329         else if (d > t1 )
330           t1 = d;
331       }
332       ON_Line L(m_P+t0*m_V,m_P+t1*m_V);
333       if ( m_d[0] > m_d[1] )
334       {
335         // function is supported along the line
336         d = bbox.MinimumDistanceTo(L);
337         if ( d >= m_d[0] )
338           rc = true;
339       }
340       else
341       {
342         // function is supported outside cylinder
343         d = bbox.MaximumDistanceTo(L);
344         if ( d <= m_d[0] )
345           rc = true;
346       }
347     }
348     break;
349 
350   case plane_type:
351     {
352       ON_PlaneEquation e;
353       e.x = m_V.x; e.y = m_V.y; e.z = m_V.z; e.d = m_P.x;
354       e.d -= m_d[0];
355       if ( m_d[0] > m_d[1] )
356       {
357         e.x = -e.x; e.y = -e.y; e.z = -e.z; e.d = -e.d;
358       }
359       if ( e.MaximumValueAt(bbox) <= 0.0 )
360         rc = true;
361     }
362     break;
363 
364   case sphere_type:
365     loc_bbox.m_min = m_P;
366     loc_bbox.m_max = m_P;
367     bTestLocBox = true;
368     break;
369 
370   case curve_type:
371     if ( m_nurbs_curve)
372     {
373       loc_bbox = m_nurbs_curve->BoundingBox();
374       bTestLocBox = true;
375     }
376     break;
377 
378   case surface_type:
379     if ( m_nurbs_surface)
380     {
381       loc_bbox = m_nurbs_surface->BoundingBox();
382       bTestLocBox = true;
383     }
384     break;
385 
386   case distance_type:
387     rc = false;
388     break;
389 
390   default:
391     rc = true;
392   }
393 
394   if ( bTestLocBox )
395   {
396     if ( m_d[1] < m_d[0] && m_d[0] > 0.0 )
397     {
398       // function is zero outside loc_bbox + m_d[0]
399       double d = loc_bbox.MinimumDistanceTo(bbox);
400       if ( d > m_d[0] )
401         rc = true;
402     }
403     else if ( m_d[0] > 0.0 )
404     {
405       // function is zero inside loc_bbox-m_d[0]
406       loc_bbox.m_min.x += m_d[0];
407       loc_bbox.m_min.y += m_d[0];
408       loc_bbox.m_min.z += m_d[0];
409       loc_bbox.m_max.x -= m_d[0];
410       loc_bbox.m_max.y -= m_d[0];
411       loc_bbox.m_max.z -= m_d[0];
412       if ( loc_bbox.IsValid() && loc_bbox.Includes(bbox) )
413         rc = true;
414     }
415   }
416   return rc;
417 }
418 
ON_SpaceMorph()419 ON_SpaceMorph::ON_SpaceMorph()
420 {
421   m_tolerance = 0.0;
422   m_bQuickPreview = false;
423   m_bPreserveStructure = false;
424 }
425 
~ON_SpaceMorph()426 ON_SpaceMorph::~ON_SpaceMorph()
427 {
428 }
429 
Tolerance() const430 double ON_SpaceMorph::Tolerance() const
431 {
432   return m_tolerance;
433 }
434 
SetTolerance(double tolerance)435 void ON_SpaceMorph::SetTolerance(double tolerance)
436 {
437   m_tolerance = (ON_IsValid(tolerance) && tolerance > 0.0 )
438               ? tolerance
439               : 0.0;
440 }
441 
QuickPreview() const442 bool ON_SpaceMorph::QuickPreview() const
443 {
444   return m_bQuickPreview;
445 }
446 
SetQuickPreview(bool bQuickPreview)447 void ON_SpaceMorph::SetQuickPreview( bool bQuickPreview )
448 {
449   m_bQuickPreview = bQuickPreview ? true : false;
450 }
451 
IsIdentity(const ON_BoundingBox & bbox) const452 bool ON_SpaceMorph::IsIdentity( const ON_BoundingBox& bbox ) const
453 {
454   return false;
455 }
456 
PreserveStructure() const457 bool ON_SpaceMorph::PreserveStructure() const
458 {
459   return m_bPreserveStructure;
460 }
461 
SetPreserveStructure(bool bPreserveStructure)462 void ON_SpaceMorph::SetPreserveStructure( bool bPreserveStructure )
463 {
464   m_bPreserveStructure = bPreserveStructure ? true : false;
465 }
466 
EvaluatePoint(const class ON_ObjRef & objref,ON_3dPoint & P) const467 bool ON_Mesh::EvaluatePoint( const class ON_ObjRef& objref, ON_3dPoint& P ) const
468 {
469   // virtual function default
470   P = ON_UNSET_POINT;
471   ON_COMPONENT_INDEX ci = objref.m_component_index;
472 
473   switch ( ci.m_type )
474   {
475   case ON_COMPONENT_INDEX::mesh_vertex:
476     if ( ci.m_index >= 0 && ci.m_index < m_V.Count() )
477       P = m_V[ci.m_index];
478     break;
479 
480   case ON_COMPONENT_INDEX::meshtop_vertex:
481     if ( ci.m_index >= 0 && ci.m_index < m_top.m_topv.Count() )
482     {
483       const ON_MeshTopologyVertex& topv = m_top.m_topv[ci.m_index];
484       if ( topv.m_v_count > 0 && topv.m_vi )
485       {
486         int vi = topv.m_vi[0];
487         if ( vi >= 0 && vi < m_V.Count() )
488           P = m_V[vi];
489       }
490     }
491     break;
492 
493   case ON_COMPONENT_INDEX::meshtop_edge:
494     if ( 5 == objref.m_evp.m_t_type
495          && fabs(objref.m_evp.m_t[0] + objref.m_evp.m_t[1] - 1.0) <= ON_SQRT_EPSILON )
496     {
497       ON_Line L = m_top.TopEdgeLine(ci.m_index);
498       if ( L.IsValid() )
499       {
500         P = L.PointAt(objref.m_evp.m_t[0]);
501       }
502     }
503     break;
504 
505   case ON_COMPONENT_INDEX::mesh_face:
506     if ( 4 == objref.m_evp.m_t_type
507          && fabs(objref.m_evp.m_t[0] + objref.m_evp.m_t[1] + objref.m_evp.m_t[2] + objref.m_evp.m_t[3] - 1.0) <= ON_SQRT_EPSILON )
508     {
509       if ( ci.m_index >= 0 && ci.m_index < m_F.Count() )
510       {
511         const int* fvi = m_F[ci.m_index].vi;
512         if ( fvi[0] < 0 || fvi[0] >= m_V.Count() )
513           break;
514         if ( fvi[1] < 0 || fvi[1] >= m_V.Count() )
515           break;
516         if ( fvi[2] < 0 || fvi[2] >= m_V.Count() )
517           break;
518         if ( fvi[3] < 0 || fvi[3] >= m_V.Count() )
519           break;
520         ON_3dPoint V[4];
521         V[0] = m_V[fvi[0]];
522         V[1] = m_V[fvi[1]];
523         V[2] = m_V[fvi[2]];
524         V[3] = m_V[fvi[3]];
525         P = objref.m_evp.m_t[0]*V[0] + objref.m_evp.m_t[1]*V[1] + objref.m_evp.m_t[2]*V[2] + objref.m_evp.m_t[3]*V[3];
526       }
527     }
528     break;
529 
530   default:
531     // intentionally skipping other ON_COMPONENT_INDEX::TYPE enum values
532     break;
533   }
534 
535   return P.IsValid();
536 }
537 
538