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