opennurbs_object.cpp
Go to the documentation of this file.
00001 /* $NoKeywords: $ */
00002 /*
00003 //
00004 // Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved.
00005 // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
00006 // McNeel & Associates.
00007 //
00008 // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
00009 // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
00010 // MERCHANTABILITY ARE HEREBY DISCLAIMED.
00011 //                              
00012 // For complete openNURBS copyright information see <http://www.opennurbs.org>.
00013 //
00015 */
00016 #include "pcl/surface/3rdparty/opennurbs/opennurbs.h"
00017 
00018 
00019 
00020 #if defined(ON_DLL_EXPORTS)
00021 
00022 #if defined(ON_COMPILER_MSC)
00023 // Force this module to be inited first so the important globals
00024 // are initialized before there is any possibility they are used.
00025 #pragma warning( push )
00026 #pragma warning( disable : 4073 )
00027 #pragma init_seg(lib)
00028 #pragma warning( pop )
00029 #endif
00030 
00031 //
00032 //
00034 
00035 #endif
00036 
00037 const ON_UUID ON_nil_uuid = {0,0,0,{0,0,0,0,0,0,0,0}};
00038 const ON_UUID ON_max_uuid = {0xFFFFFFFF,0xFFFF,0xFFFF,{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}};
00039 
00040 const ON_UUID ON_rhino2_id = { 0x16d0eca6, 0x359, 0x4e4c, { 0x9f, 0xe, 0xf2, 0x69, 0xfd, 0x47, 0x6c, 0xc4 } };
00041 
00042 const ON_UUID ON_rhino3_id = { 0xA7BBFF3C, 0xFF19, 0x4883, { 0x85, 0x8D, 0xB1, 0xE7, 0xDB, 0x4F, 0x1A, 0x7E } };
00043 
00044 // {E2143A46-BB01-4b0c-AC4D-C34B5652FAE0}
00045 const ON_UUID ON_rhino4_id = { 0xe2143a46, 0xbb01, 0x4b0c, { 0xac, 0x4d, 0xc3, 0x4b, 0x56, 0x52, 0xfa, 0xe0 } };
00046 
00047 // {60515F84-8F7F-41da-801D-1C87E32F88F5}
00048 const ON_UUID ON_rhino5_id = { 0x60515f84, 0x8f7f, 0x41da, { 0x80, 0x1d, 0x1c, 0x87, 0xe3, 0x2f, 0x88, 0xf5 } };
00049 
00050 // ON_rhino_id is always set to the value for the current version
00051 // of Rhino.  ON_rhino_id is the id that should be used as the
00052 // userdata application id for userdata class definitions that are
00053 // in the core Rhino executable.
00054 const ON_UUID ON_rhino_id = ON_rhino5_id;
00055 
00056 // Used to identifiy userdata read from V2 files
00057 // which were written before userdata had application ids.
00058 // {132F2340-DB90-494e-BF02-C36F0EA3197C}
00059 const ON_UUID ON_v2_userdata_id = { 0x132f2340, 0xdb90, 0x494e, { 0xbf, 0x2, 0xc3, 0x6f, 0xe, 0xa3, 0x19, 0x7c } };
00060 
00061 // Used to identifiy userdata read from V3 files
00062 // which were written before userdata had application ids.
00063 // {4307B91D-6A9D-478e-B0A2-7C577997C663}
00064 const ON_UUID ON_v3_userdata_id = { 0x4307b91d, 0x6a9d, 0x478e, { 0xb0, 0xa2, 0x7c, 0x57, 0x79, 0x97, 0xc6, 0x63 } };
00065 
00066 // Used to identifiy userdata read from V4 files
00067 // which were written before opennurbs 200609190
00068 // required application ids.
00069 // {F73F2953-A244-44c2-B7C2-7E27390D1196}
00070 const ON_UUID ON_v4_userdata_id = { 0xf73f2953, 0xa244, 0x44c2, { 0xb7, 0xc2, 0x7e, 0x27, 0x39, 0xd, 0x11, 0x96 } };
00071 
00072 // {17B3ECDA-17BA-4e45-9E67-A2B8D9BE520D}
00073 const ON_UUID ON_opennurbs4_id = { 0x17b3ecda, 0x17ba, 0x4e45, { 0x9e, 0x67, 0xa2, 0xb8, 0xd9, 0xbe, 0x52, 0xd } };
00074 
00075 // {C8CDA597-D957-4625-A4B3-A0B510FC30D4}
00076 const ON_UUID ON_opennurbs5_id = { 0xc8cda597, 0xd957, 0x4625, { 0xa4, 0xb3, 0xa0, 0xb5, 0x10, 0xfc, 0x30, 0xd4 } };
00077 
00078 // ON_opennurbs_id is always set to the value for the current version
00079 // of opennurbs.  ON_opennurbs_id is the id that should be used as
00080 // the userdata application id for userdata classes definitions that
00081 // are in the opennurbs library.
00082 const ON_UUID ON_opennurbs_id = ON_opennurbs5_id;
00083 
00084 /*
00085 IEEE 754
00086 
00087 Storage
00088            size      sign     exponent         fraction
00089   float    4 bytes   bit 31    8 bits (30-23)  23 bits (22-0)
00090   double   8 bytes   bit 63   11 bits (62-52)  52 bits (51-0)
00091 
00092 sign bit = 1 indicates negative
00093 sign bit = 0 indicates positive
00094 
00095 float  absolute value = 2^(e-127)  * 1+(f/2^23)
00096   e = value of the 8 bit number in the exponent field
00097   f = value of the 23 bit number in the fraction field
00098 
00099 double absolute value = 2^(e-1023) * 1+(f/2^51)
00100   e = value of the 11 bit number in the exponent field
00101   f = value of the 51 bit number in the fraction field
00102 
00103 Exceptions:
00104   If all exponent bits are all 0 (e = 0) and the fraction bits
00105   are all zero, then the value of the number is zero.
00106 
00107   If all exponent bits are all 0 (e = 0) and at least one fraction
00108   bits is not zero, then the representaion is "denormalized".
00109   In this case, the float absolute value is 0.f*2^-126 and the
00110   double absolute value is 0.f*2^-1022.
00111 
00112   If all exponent bits are 1 (float e = 11111111binary = 255decimal
00113   or double e = 11111111111 binary = 2047 decimal) and the fraction
00114   bits are all zero, the number is infinity.  The sign bit
00115   determines the sign of infinity.
00116   
00117   If all exponent bits are 1 and at least one fraction bit is
00118   not zero, the number is a "NaN" (not a number).  If the most
00119   significant fraction bit is 1, the number is a quiet NaN or
00120   "QNaN".  If the most significan fraction bit is 0, the number
00121   is a signalling NaN or "SNaN".
00122   
00123   Some authors (SH)   QNaNs are used to indicate
00124   indeterminant operations, like sqrt(-1.0).  SNaNs are used
00125   to indicate invalid operations.
00126 
00127   SH - http://steve.hollasch.net/cgindex/coding/ieeefloat.html
00128   Intel - 
00129 */
00130 static double ON__dblinithelper(int i)
00131 {
00132   // called twice - performance is not important
00133   union 
00134   {
00135     double x;
00136     unsigned char b[8];
00137   } u;
00138   unsigned int i7, i6;
00139 
00140   // different bytes on
00141   u.x = 2.0; // sign = 0; fraction = 0; exponent = 100 0000 0000 binary
00142 
00143   if ( 0x40 == u.b[7] && 0 == u.b[0]
00144        && 0 == u.b[1] && 0 == u.b[2] && 0 == u.b[3]
00145        && 0 == u.b[4] && 0 == u.b[5] && 0 == u.b[6] 
00146      )
00147   {
00148     // little endian doubles
00149     i7 = 7; i6 = 6;
00150   }
00151   else if ( 0x40 == u.b[0]  && 0 == u.b[7]
00152             && 0 == u.b[1] && 0 == u.b[2] && 0 == u.b[3]
00153             && 0 == u.b[4] && 0 == u.b[5] && 0 == u.b[6] 
00154           )
00155   {
00156     // big endian doubles
00157     i7 = 0; i6 = 1;
00158   }
00159   else
00160   {
00161     // this sitation is not handled by this algorithm
00162     // and that is a bug in the algorithm.
00163     ON_ERROR("CPU has unexpected bit pattern in double 2.0.");
00164     i7 = 0;
00165     i6 = 0;
00166     i = 99;
00167   }
00168 
00169   if      ( 1 == i ) // positive quiet NaN
00170   {
00171     // all exponent bits = 1
00172     // fraction bits = 100...0
00173     u.b[i7]   = 0x7F; // 0111 1111
00174     u.b[i6]   = 0xF8; // 1111 1000
00175     u.b[5]    = 0;    // 0...
00176     u.b[4]    = 0;
00177     u.b[3]    = 0;
00178     u.b[2]    = 0;
00179     u.b[7-i6] = 0;
00180     u.b[7-i7] = 0;
00181   }
00182   else if ( 2 == i ) // positive infinity
00183   {
00184     // all exponent bits = 1
00185     // all fraction bits = 0
00186     u.b[i7]   = 0x7F; // 0111 1111
00187     u.b[i6]   = 0xF0; // 1111 0000
00188     u.b[5]    = 0;    // 0...
00189     u.b[4]    = 0;
00190     u.b[3]    = 0;
00191     u.b[2]    = 0;
00192     u.b[7-i6] = 0;
00193     u.b[7-i7] = 0;
00194   }
00195   else
00196   {
00197     // invalid input 
00198     u.b[0] = 0xFF;
00199     u.b[1] = 0xFF;
00200     u.b[2] = 0xFF;
00201     u.b[3] = 0xFF;
00202     u.b[4] = 0xFF;
00203     u.b[5] = 0xFF;
00204     u.b[6] = 0xFF;
00205     u.b[7] = 0xFF;
00206   }
00207 
00208   return u.x;
00209 }
00210 
00211 
00212 static float ON__fltinithelper(int i)
00213 {
00214   // called twice - performance is not important
00215   union 
00216   {
00217     float x;
00218     unsigned char b[4];
00219   } u;
00220   unsigned int i3, i2;
00221 
00222   // different bytes on
00223   u.x = 2.0f; // sign = 0; mantissa = 0; exponent = 1000 0000
00224   if ( 0x40 == u.b[3] && 0 == u.b[0] && 0 == u.b[1] && 0 == u.b[2] )
00225   {
00226     // little endian doubles
00227     i3 = 3; i2 = 2;
00228   }
00229   else if ( 0x40 == u.b[0] && 0 == u.b[3] && 0 == u.b[1] && 0 == u.b[2] )
00230   {
00231     // big endian doubles
00232     i3 = 0; i2 = 1;
00233   }
00234   else
00235   {
00236     // this sitation is not handled by this algorithm
00237     // and that is a bug in the algorithm.
00238     ON_ERROR("CPU has unexpected bit pattern in float 2.0f.");
00239     i3 = 0;
00240     i2 = 0;
00241     i = 99;
00242   }
00243 
00244   if      ( 1 == i ) // positive quiet NaN
00245   {
00246     // all exponent bits = 1
00247     // fraction bits = 100...0
00248     u.b[i3]   = 0x7F; // 0111 1111
00249     u.b[i2]   = 0xC0; // 1100 0000
00250     u.b[3-i2] = 0;    // 0...
00251     u.b[3-i3] = 0;
00252   }
00253   else if ( 2 == i ) // positive infinity
00254   {
00255     // all exponent bits = 1
00256     // all fraction bits = 0
00257     u.b[i3]   = 0x7F; // 0111 1111
00258     u.b[i2]   = 0x80; // 1000 0000
00259     u.b[3-i2] = 0;    // 0...
00260     u.b[3-i3] = 0;
00261   }
00262   else
00263   {
00264     // invalid input 
00265     u.b[0] = 0xFF;
00266     u.b[1] = 0xFF;
00267     u.b[2] = 0xFF;
00268     u.b[3] = 0xFF;
00269   }
00270 
00271   return u.x;
00272 }
00273 
00274 const double ON_DBL_QNAN =  ON__dblinithelper(1);
00275 const double ON_DBL_PINF =  ON__dblinithelper(2);
00276 const double ON_DBL_NINF = -ON__dblinithelper(2);
00277 
00278 const float  ON_FLT_QNAN =  ON__fltinithelper(1);
00279 const float  ON_FLT_PINF =  ON__fltinithelper(2);
00280 const float  ON_FLT_NINF = -ON__fltinithelper(2);
00281 
00282 void ON_DBL_SNAN( double* x)
00283 {
00284   union 
00285   {
00286     double x;
00287     unsigned char b[8];
00288   } u;
00289 
00290 #if   defined(ON_LITTLE_ENDIAN)
00291 #define i7 7
00292 #define i6 6
00293 #elif defined(ON_BIG_ENDIAN)
00294 #define i7 0
00295 #define i6 1
00296 #else
00297   unsigned int i7, i6;
00298 
00299   u.x = 2.0; // sign = 0; fraction = 0; exponent = 100 0000 0000 binary
00300 
00301   if ( 0x40 == u.b[7] && 0 == u.b[0]
00302        && 0 == u.b[1] && 0 == u.b[2] && 0 == u.b[3]
00303        && 0 == u.b[4] && 0 == u.b[5] && 0 == u.b[6] 
00304      )
00305   {
00306     // little endian doubles
00307     i7 = 7; i6 = 6;
00308   }
00309   else if ( 0x40 == u.b[0]  && 0 == u.b[7]
00310             && 0 == u.b[1] && 0 == u.b[2] && 0 == u.b[3]
00311             && 0 == u.b[4] && 0 == u.b[5] && 0 == u.b[6] 
00312           )
00313   {
00314     // big endian doubles
00315     i7 = 0; i6 = 1;
00316   }
00317   else
00318   {
00319     // this sitation is not handled by this algorithm
00320     // and that is a bug in the algorithm.
00321     ON_ERROR("CPU has unexpected bit pattern in double 2.0.");
00322     i7 = 0;
00323     i6 = 0;
00324     memset(&x,0xFF,sizeof(*x));
00325     return;
00326   }
00327 #endif
00328 
00329   // all exponent bits = 1
00330   // fraction bits = 010...0
00331   u.b[i7]   = 0x7F; // 0111 1111
00332   u.b[i6]   = 0xF4; // 1111 0100
00333   u.b[5]    = 0;    // 0...
00334   u.b[4]    = 0;
00335   u.b[3]    = 0;
00336   u.b[2]    = 0;
00337   u.b[7-i6] = 0;
00338   u.b[7-i7] = 0;
00339 
00340 #if defined(i7)
00341 #undef i7
00342 #undef i6
00343 #endif
00344 
00345 
00346   // must use memcpy().  On Intel FPU, assignment using x = u.x 
00347   // will set x to qnan and invalid op exception occures.
00348   memcpy(x,&u.x,sizeof(*x));
00349 }
00350 
00351 void ON_FLT_SNAN( float* x)
00352 {
00353   union 
00354   {
00355     float x;
00356     unsigned char b[4];
00357   } u;
00358 
00359 #if   defined(ON_LITTLE_ENDIAN)
00360 #define i3 3
00361 #define i2 2
00362 #elif defined(ON_BIG_ENDIAN)
00363 #define i3 0
00364 #define i2 1
00365 #else
00366   unsigned int i3, i2;
00367 
00368   u.x = 2.0f; // sign = 0; mantissa = 0; exponent = 1000 0000
00369 
00370   if ( 0x40 == u.b[3] && 0 == u.b[0] && 0 == u.b[1] && 0 == u.b[2] )
00371   {
00372     // little endian doubles
00373     i3 = 3; i2 = 2;
00374   }
00375   else if ( 0x40 == u.b[0] && 0 == u.b[3] && 0 == u.b[1] && 0 == u.b[2] )
00376   {
00377     // big endian doubles
00378     i3 = 0; i2 = 1;
00379   }
00380   else
00381   {
00382     // this sitation is not handled by this algorithm
00383     // and that is a bug in the algorithm.
00384     ON_ERROR("CPU has unexpected bit pattern in float 2.0f.");
00385     memset(&x,0xFF,sizeof(*x));
00386     return;
00387   }
00388 #endif
00389 
00390   // all exponent bits = 1
00391   // fraction bits = 011...1
00392   u.b[i3]   = 0x7F; // 0111 1111
00393   u.b[i2]   = 0xA0; // 1010 0000
00394   u.b[3-i2] = 0;    // 0...
00395   u.b[3-i3] = 0;
00396 
00397 #if defined(i3)
00398 #undef i3
00399 #undef i2
00400 #endif
00401 
00402   // must use memcpy().  On Intel FPU, assignment using x = u.x 
00403   // will set x to qnan and invalid op exception occures.
00404   memcpy(x,&u.x,sizeof(*x));
00405 }
00406 
00407 void ON::End()
00408 {
00409 }
00410 
00411 
00412 #if 8 == ON_SIZEOF_POINTER
00413 
00414 #if !defined(ON_64BIT_POINTER)
00415 #error 8 = ON_SIZEOF_POINTER and ON_64BIT_POINTER is not defined
00416 #endif
00417 #if defined(ON_32BIT_POINTER)
00418 #error 8 = ON_SIZEOF_POINTER and ON_32BIT_POINTER is defined
00419 #error
00420 #endif
00421 
00422 #elif 4 == ON_SIZEOF_POINTER
00423 
00424 #if !defined(ON_32BIT_POINTER)
00425 #error 4 = ON_SIZEOF_POINTER and ON_32BIT_POINTER is not defined
00426 #endif
00427 #if defined(ON_64BIT_POINTER)
00428 #error 4 = ON_SIZEOF_POINTER and ON_64BIT_POINTER is defined
00429 #endif
00430 
00431 #else
00432 
00433 #error OpenNURBS assumes sizeof(void*) is 4 or 8 bytes
00434 
00435 #endif
00436 
00437 static void ValidateSizesHelper()
00438 {
00439   static bool bSizedValidated = false;
00440   if ( !bSizedValidated )
00441   {
00442     // Validate int and pointer sizes
00443     bSizedValidated = true;
00444 
00445     // These conditional expressions are all constant and should
00446     // all be false.  If any are true, then portions of OpenNURBS
00447     // code will fail and probably crash.
00448 
00449 #if defined(ON_COMPILER_MSC)
00450 #pragma warning( push )
00451 // Disable warning C4127: conditional expression is constant
00452 #pragma warning( disable : 4127 )
00453 #endif
00454 
00455     if ( ON_SIZEOF_POINTER != sizeof(void*) )
00456     {
00457       ON_ERROR("ON_SIZEOF_POINTER is not correctly defined.");
00458     }
00459     if ( ON_SIZEOF_POINTER != sizeof(ON__INT_PTR) )
00460     {
00461       ON_ERROR("ON_INT_PTR is not correctly defined.");
00462     }
00463     if ( 1 !=  sizeof(char) )
00464     {
00465       ON_ERROR("OpenNURBS assumes sizeof(char) = 1.");
00466     }
00467     if ( 2 !=  sizeof(ON__INT16) )
00468     {
00469       ON_ERROR("ON__INT16 is not correctly defined.");
00470     }
00471     if ( 4 !=  sizeof(ON__INT32) )
00472     {
00473       ON_ERROR("ON__INT32 is not correctly defined.");
00474     }
00475     if ( 8 !=  sizeof(ON__INT64) )
00476     {
00477       ON_ERROR("ON__INT32 is not correctly defined.");
00478     }
00479     if ( sizeof(int) > sizeof(void*) )
00480     {
00481       ON_ERROR("OpenNURBS assumes sizeof(int) <= sizeof(void*).");
00482     }
00483     if ( 4 !=  sizeof(float) )
00484     {
00485       ON_ERROR("OpenNURBS assumes sizeof(float) = 4.");
00486     }
00487     if ( 8 !=  sizeof(double) )
00488     {
00489       ON_ERROR("OpenNURBS assumes sizeof(double) = 8.");
00490     }
00491 
00492 #if defined(ON_COMPILER_MSC)
00493 #pragma warning( pop )
00494 #endif
00495   }
00496 }
00497 
00498 void ON::Begin()
00499 {
00500   ValidateSizesHelper();
00501 
00502 #if !defined(ON_DLL_EXPORTS)
00503   // Some statically linked library optimizations discard
00504   // object code that is not explicitly referenced.
00505   // By explicitly calling all the ON_Object::Cast overrides,
00506   // we can insure that the class definitions get linked in
00507   // by making a single call to ON::Begin().  These definitions
00508   // are needed for the file reading code to work right.
00509   static bool bRunning = false;
00510   if ( !bRunning )
00511   {
00512     bRunning = true;
00513     const ON_Object* p=0;
00514 
00515     ON_Object::Cast(p);
00516     ON_3dmObjectAttributes::Cast(p);
00517     ON_Bitmap::Cast(p);
00518     ON_EmbeddedBitmap::Cast(p);
00519     ON_WindowsBitmap::Cast(p);
00520     ON_WindowsBitmapEx::Cast(p);
00521     ON_DimStyle::Cast(p);
00522     ON_DocumentUserStringList::Cast(p);
00523     ON_Font::Cast(p);
00524     ON_Geometry::Cast(p);
00525     ON_Annotation::Cast(p);
00526     ON_AngularDimension::Cast(p);
00527     ON_Leader::Cast(p);
00528     ON_LinearDimension::Cast(p);
00529     ON_RadialDimension::Cast(p);
00530     ON_TextEntity::Cast(p);
00531     ON_Annotation2::Cast(p);
00532     ON_AngularDimension2::Cast(p);
00533     ON_Leader2::Cast(p);
00534     ON_LinearDimension2::Cast(p);
00535     ON_OrdinateDimension2::Cast(p);
00536     ON_RadialDimension2::Cast(p);
00537     ON_TextEntity2::Cast(p);
00538     ON_AnnotationArrow::Cast(p);
00539     ON_Brep::Cast(p);
00540     ON_BrepLoop::Cast(p);
00541     ON_Curve::Cast(p);
00542     ON_ArcCurve::Cast(p);
00543     //ON__OBSOLETE__CircleCurve::Cast(p);
00544     ON_CurveOnSurface::Cast(p);
00545     ON_CurveProxy::Cast(p);
00546     ON_BrepEdge::Cast(p);
00547     ON_BrepTrim::Cast(p);
00548     //ON_PolyEdgeSegment::Cast(p);
00549     ON_LineCurve::Cast(p);
00550     ON_NurbsCurve::Cast(p);
00551     ON_PolyCurve::Cast(p);
00552     //ON_PolyEdgeCurve::Cast(p);
00553     ON_PolylineCurve::Cast(p);
00554     ON_DetailView::Cast(p);
00555     ON_Hatch::Cast(p);
00556     ON_InstanceDefinition::Cast(p);
00557     ON_InstanceRef::Cast(p);
00558     ON_Light::Cast(p);
00559     ON_Mesh::Cast(p);
00560     ON_MeshEdgeRef::Cast(p);
00561     ON_MeshFaceRef::Cast(p);
00562     ON_MeshVertexRef::Cast(p);
00563     ON_MorphControl::Cast(p);
00564     ON_NurbsCage::Cast(p);
00565     ON_Point::Cast(p);
00566     ON_AnnotationTextDot::Cast(p);
00567     ON_BrepVertex::Cast(p);
00568     ON_PointCloud::Cast(p);
00569     ON_PointGrid::Cast(p);
00570     ON_Surface::Cast(p);
00571     ON_Extrusion::Cast(p);
00572     ON_NurbsSurface::Cast(p);
00573     ON_PlaneSurface::Cast(p);
00574     ON_ClippingPlaneSurface::Cast(p);
00575     ON_RevSurface::Cast(p);
00576     ON_SumSurface::Cast(p);
00577     ON_SurfaceProxy::Cast(p);
00578     ON_BrepFace::Cast(p);
00579     ON_OffsetSurface::Cast(p);
00580     ON_TextDot::Cast(p);
00581     ON_Viewport::Cast(p);
00582     ON_Group::Cast(p);
00583     ON_HatchPattern::Cast(p);
00584     ON_HistoryRecord::Cast(p);
00585     ON_Layer::Cast(p);
00586     ON_Linetype::Cast(p);
00587     ON_Material::Cast(p);
00588     ON_Texture::Cast(p);
00589     ON_TextureMapping::Cast(p);
00590     ON_UserData::Cast(p);
00591     //ON__LayerExtensions::Cast(p);
00592     //ON_AngularDimension2Extra::Cast(p);
00593     //ON_AnnotationTextFormula::Cast(p);
00594     //ON_DimensionExtra::Cast(p);
00595     //ON_DimStyleExtra::Cast(p);
00596     //ON_HatchExtra::Cast(p);
00597     //ON_MeshDoubleVertices::Cast(p);
00598     //ON_MeshNgonUserData::Cast(p);
00599     ON_TextExtra::Cast(p);
00600     ON_UnknownUserData::Cast(p);
00601     ON_UserStringList::Cast(p);
00602   }
00603 #endif
00604 }
00605 
00606 
00607 ON_ClassId* ON_ClassId::m_p0 = 0; // static pointer to first id in list
00608 ON_ClassId* ON_ClassId::m_p1 = 0; // static pointer to last id in list
00609 int ON_ClassId::m_mark0 = 0;
00610 
00611 int ON_ClassId::CurrentMark()
00612 {
00613   return m_mark0;
00614 }
00615 
00616 int ON_ClassId::IncrementMark()
00617 {
00618   m_mark0++;
00619   return m_mark0;
00620 }
00621 
00622 int ON_ClassId::Purge( int mark_value )
00623 {
00624   // Fundamental openNURBS class ids have a mark value of 0 and cannot be purged.
00625   int purge_count = 0;
00626   if ( mark_value > 0 ) {
00627     ON_ClassId* prev = 0;
00628     ON_ClassId* next = 0;
00629     ON_ClassId* p;
00630     for ( p = m_p0; p; p = next )
00631     {
00632       next = p->m_pNext;
00633       if ( (0x7FFFFFFF & p->m_mark) == mark_value ) {
00634         purge_count++;
00635         if ( prev )
00636           prev->m_pNext = next;
00637         else
00638           m_p0 = next;
00639         p->m_pNext = 0;
00640       }
00641       else
00642         prev = p;
00643     }
00644   }
00645   return purge_count;
00646 }
00647 
00648 const ON_ClassId* ON_ClassId::LastClassId()
00649 {
00650   return m_p1;
00651 }
00652 
00653 bool ON_ClassId::PurgeAfter(const ON_ClassId* pClassId)
00654 {
00655   // If you crash in on the p=p->m_pNext iterator in
00656   // the for() loop, it is because somebody incorrectly
00657   // unloaded a dll that contains an ON_OBJECT_IMPLEMENT 
00658   // macro.
00659   for (ON_ClassId* p = m_p0; p; p = p->m_pNext)
00660   {
00661     if (pClassId == p)
00662     {
00663       // All class ids after pClassId are assumed to
00664       // be bad.
00665       p->m_pNext = 0;
00666       m_p1 = p;
00667       return true;
00668     }
00669   }
00670 
00671   ON_ERROR("ON_ClassId::PurgeAfter pClassId is not active");
00672   return false;
00673 }
00674 
00676 
00677 static ON_BOOL32 g_bDisableDemotion = false;
00678 
00679 static void IntToString( int i, char s[7] )
00680 {
00681   // avoid format printing during early start up
00682   int j;
00683   int digit;
00684   char sdig[10];
00685   sdig[0] = '0';
00686   sdig[1] = '1';
00687   sdig[2] = '2';
00688   sdig[3] = '3';
00689   sdig[4] = '4';
00690   sdig[5] = '5';
00691   sdig[6] = '6';
00692   sdig[7] = '7';
00693   sdig[8] = '8';
00694   sdig[9] = '9';
00695   for ( digit = 5; digit > 0; digit-- )
00696   {
00697     j = i%10;
00698     if ( j > 9 || j < 0 )
00699     {
00700       s[digit] = '-';
00701     }
00702     else
00703     {
00704       s[digit] = sdig[j];
00705     }
00706     i /= 10;
00707   }
00708   s[0] = '-';
00709   s[6] = 0;
00710 }
00711 
00712 ON_ClassId::ON_ClassId( const char* sClassName, 
00713                         const char* sBaseClassName, 
00714                         ON_Object* (*create)(),
00715                         bool (*copy)( const ON_Object*, ON_Object* ),
00716                         const char* sUUID // UUID in registry format from guidgen
00717                         ) 
00718                         : m_pNext(0),
00719                           m_pBaseClassId(0),
00720                           m_create(create),
00721                           m_mark(m_mark0),
00722                           m_class_id_version(1),
00723                           m_copy(copy),
00724                           m_f2(0),
00725                           m_f3(0),
00726                           m_f4(0),
00727                           m_f5(0),
00728                           m_f6(0),
00729                           m_f7(0),
00730                           m_f8(0)
00731 {
00732   // code compiled on or after opennurbs 200703060 calls this constructor
00733   ConstructorHelper(sClassName,sBaseClassName,sUUID);
00734   m_mark |= 0x80000000; // This bit of m_mark is a flag that indicates 
00735                         // the new constructor was called.
00736 }
00737 
00738 
00739 ON_ClassId::ON_ClassId( const char* sClassName, 
00740                         const char* sBaseClassName, 
00741                         ON_Object* (*create)(),
00742                         const char* sUUID // UUID in registry format from guidgen
00743                         ) 
00744                         : m_pNext(0),
00745                           m_pBaseClassId(0),
00746                           m_create(create),
00747                           m_mark(m_mark0)
00748 {
00749   // Code COMPILED before opennurbs 200703060 calls this constructor.
00750   // DO NOT INITIALIZE m_class_id_version or any ON_ClassId fields
00751   // after m_class_id_version because the executable calling this 
00752   // constructor did not allocate room for this these members.
00753   ConstructorHelper(sClassName,sBaseClassName,sUUID);
00754 }
00755 
00756 void ON_ClassId::ConstructorHelper( const char* sClassName, 
00757                         const char* sBaseClassName, 
00758                         const char* sUUID // UUID in registry format from guidgen
00759                         ) 
00760 {
00761   // Do not initialize "m_class_id_version" or any fields
00762   // after it in this helper.  See comments in the constructors
00763   // for more information.
00764   memset( m_sClassName, 0, sizeof(m_sClassName) );
00765   memset( m_sBaseClassName, 0, sizeof(m_sBaseClassName) );
00766   m_uuid = ON_UuidFromString(sUUID);
00767   if ( sClassName ) {
00768     strncpy( m_sClassName, sClassName, sizeof(m_sClassName)-1 );
00769   }
00770   if ( sBaseClassName ) {
00771     strncpy( m_sBaseClassName, sBaseClassName, sizeof(m_sBaseClassName)-1 );
00772   }
00773   m_pBaseClassId = ClassId( m_sBaseClassName );
00774 
00775   if ( !m_sClassName[0] ) {
00776     ON_ERROR("ON_ClassId::ON_ClassId() - missing class name");
00777     return;
00778   }
00779 
00780   const ON_ClassId* duplicate_class = ClassId( m_sClassName );
00781   // The m_mark0 > 2 test prevents opennurbs and Rhino from
00782   // having two ON_Object derived classes that have the same
00783   // name.  Plug-ins are free to use any name.
00784   if ( 0 != duplicate_class && m_mark0 > 2 )
00785   {
00786     char s[7];
00787     int ver;
00788     ON_WARNING("ON_ClassId::ON_ClassId() - class name already in use.  Will append number to make it unique.");
00789     for ( ver = 1; ver < 10000 && 0 != duplicate_class; ver++ )
00790     {
00791       IntToString(ver,s);
00792       s[6] = 0;
00793       strncpy( m_sClassName, sClassName, sizeof(m_sClassName)-1 );
00794       strncat( m_sClassName, s, sizeof(m_sClassName)-1 );
00795       duplicate_class = ClassId( m_sClassName );
00796     }
00797   }
00798 
00799   if ( 0 != duplicate_class )
00800   {
00801     // Do NOT permit core classes to have duplicate names.
00802     ON_ERROR("ON_ClassId::ON_ClassId() - class name already in use.");
00803     return;
00804   }
00805 
00806   if (    m_sClassName[0] != 'O'
00807        || m_sClassName[1] != 'N'
00808        || m_sClassName[2] != '_'
00809        || m_sClassName[3] != 'O'
00810        || m_sClassName[4] != 'b'
00811        || m_sClassName[5] != 'j'
00812        || m_sClassName[6] != 'e'
00813        || m_sClassName[7] != 'c'
00814        || m_sClassName[8] != 't'
00815        || m_sClassName[9] != 0 ) {
00816     if ( !m_sBaseClassName[0] ) 
00817     {
00818       ON_ERROR("ON_ClassId::ON_ClassId() - missing baseclass name.");
00819       return;
00820     }
00821   }
00822 
00823   g_bDisableDemotion = true;
00824   if ( ClassId( m_uuid ) ) 
00825   {
00826     g_bDisableDemotion = false;
00827     ON_ERROR("ON_ClassId::ON_ClassId() - class uuid already in use.");
00828     return;
00829   }
00830   g_bDisableDemotion = false;
00831 
00832   if ( ON_UuidIsNil( m_uuid ) ) {
00833     ON_ERROR("ON_ClassId::ON_ClassId() - class uuid is nill.");
00834     return;
00835   }
00836 
00837   // see if any derived classes need to be updated because their static
00838   // members got initialized first
00839   if ( m_sClassName[0] ) 
00840   {
00841     for ( ON_ClassId* p = m_p0; p; p = p->m_pNext )
00842     {
00843       if ( !p->m_pBaseClassId && p->m_sBaseClassName ) {
00844         if ( !strcmp( m_sClassName, p->m_sBaseClassName ) )
00845           p->m_pBaseClassId = this;
00846       }
00847     }
00848   }
00849 
00850   // Append to the list of class ids
00851   if ( m_p0 && m_p1 )
00852   {
00853     m_p1->m_pNext = this;
00854     m_p1 = this;
00855   }
00856   else
00857   {
00858     // first class id
00859     m_p0 = this;
00860   }
00861   m_p1 = this;
00862   m_p1->m_pNext = 0;
00863 }
00864 
00865 ON_ClassId::~ON_ClassId()
00866 {}
00867 
00868 static ON_UUID s_most_recent_class_id_create_uuid;
00869 
00870 ON_UUID ON_GetMostRecentClassIdCreateUuid()
00871 {
00872   return s_most_recent_class_id_create_uuid;
00873 }
00874 
00875 ON_Object* ON_ClassId::Create() const
00876 {
00877   // Save the uuid so that Rhino's .NET SDK
00878   // can create approprate class.  The C++
00879   // opennurbs toolkit never uses this value.
00880   s_most_recent_class_id_create_uuid = m_uuid;
00881   return m_create ? m_create() : 0;
00882 }
00883 
00884 const ON_ClassId* ON_ClassId::ClassId( const char* sClassName )
00885 {
00886   // static member function
00887   // search list of class ids for one with a matching class name
00888   ON_ClassId* p;
00889   const char* s0;
00890   const char* s1;
00891   if ( !sClassName || !sClassName[0] || sClassName[0] == '0' )
00892     return NULL;
00893   for(p = m_p0; p; p = p->m_pNext) {
00894     // avoid strcmp() because it crashes on NULL strings
00895     s0 = sClassName;
00896     s1 = p->m_sClassName;
00897     if ( s0 && s1 && *s0 ) {
00898       while ( *s0 && *s0 == *s1 )
00899         {s0++; s1++;}
00900       if ( !(*s0) && !(*s1) )
00901         break;
00902     }
00903     else {
00904       break;
00905     }
00906   }
00907   return p;
00908 }
00909 
00910 
00911 const ON_ClassId* ON_ClassId::ClassId( ON_UUID uuid )
00912 {
00913   // static member function
00914   // search list of class ids for one with a matching typecode
00915   const ON_ClassId* p;
00916   for(p = m_p0; p; p = p->m_pNext) 
00917   {
00918     if ( !ON_UuidCompare(&p->m_uuid,&uuid) )
00919       break;
00920   }
00921 
00922   if ( !p && !g_bDisableDemotion) 
00923   {
00924     // enable OpenNURBS toolkit to read files that contain old uuids even when
00925     // old class definitions are not loaded.
00926 
00927     // 5EAF1119-0B51-11d4-BFFE-0010830122F0 = TL_NurbsCurve
00928     ON_UUID nc0 = {0x5EAF1119,0x0B51,0x11d4,{0xBF,0xFE,  0x00,0x10,0x83,0x01,0x22,0xF0}};
00929 
00930     // 76A709D5-1550-11d4-8000-0010830122F0 = old nurbs curve
00931     ON_UUID nc1 = {0x76A709D5,0x1550,0x11d4,{0x80,0x00,  0x00,0x10,0x83,0x01,0x22,0xF0}};
00932 
00933     // 4760C817-0BE3-11d4-BFFE-0010830122F0 = TL_NurbsSurface
00934     ON_UUID ns0 = {0x4760C817,0x0BE3,0x11d4,{0xBF,0xFE,  0x00,0x10,0x83,0x01,0x22,0xF0}};
00935 
00936     // FA4FD4B5-1613-11d4-8000-0010830122F0 = old nurbs surface
00937     ON_UUID ns1 = {0xFA4FD4B5,0x1613,0x11d4,{0x80,0x00,  0x00,0x10,0x83,0x01,0x22,0xF0}};
00938 
00939     // EF638317-154B-11d4-8000-0010830122F0 = old poly curve
00940     ON_UUID pc0 = {0xEF638317,0x154B,0x11d4,{0x80,0x00,  0x00,0x10,0x83,0x01,0x22,0xF0}};
00941 
00942     // 0705FDEF-3E2A-11d4-800E-0010830122F0 = old trimmed surface
00943     ON_UUID br0 = {0x0705FDEF,0x3E2A,0x11d4,{0x80,0x0E,  0x00,0x10,0x83,0x01,0x22,0xF0}};
00944 
00945     // 2D4CFEDB-3E2A-11d4-800E-0010830122F0 = old b-rep
00946     ON_UUID br1 = {0x2D4CFEDB,0x3E2A,0x11d4,{0x80,0x0E,  0x00,0x10,0x83,0x01,0x22,0xF0}};
00947 
00948     // F06FC243-A32A-4608-9DD8-A7D2C4CE2A36 = TL_Brep
00949     ON_UUID br2 = {0xF06FC243,0xA32A,0x4608,{0x9D,0xD8, 0xA7,0xD2,0xC4,0xCE,0x2A,0x36}};
00950 
00951     // 0A8401B6-4D34-4b99-8615-1B4E723DC4E5 = TL_RevSurface
00952     ON_UUID revsrf = { 0xa8401b6, 0x4d34, 0x4b99, { 0x86, 0x15, 0x1b, 0x4e, 0x72, 0x3d, 0xc4, 0xe5 } };
00953 
00954     // 665F6331-2A66-4cce-81D0-B5EEBD9B5417 = TL_SumSurface
00955     ON_UUID sumsrf = { 0x665f6331, 0x2a66, 0x4cce, { 0x81, 0xd0, 0xb5, 0xee, 0xbd, 0x9b, 0x54, 0x17 } };
00956 
00957     if      ( !ON_UuidCompare( &uuid, &nc0 ) || !ON_UuidCompare( &uuid, &nc1 ) )
00958       p = &ON_NurbsCurve::m_ON_NurbsCurve_class_id;
00959     else if ( !ON_UuidCompare( &uuid, &ns0 ) || !ON_UuidCompare( &uuid, &ns1 ) )
00960       p = &ON_NurbsSurface::m_ON_NurbsSurface_class_id;
00961     else if ( !ON_UuidCompare( &uuid, &pc0 ) )
00962       p = &ON_PolyCurve::m_ON_PolyCurve_class_id;
00963     else if ( !ON_UuidCompare( &uuid, &br0 ) || !ON_UuidCompare( &uuid, &br1 ) || !ON_UuidCompare( &uuid, &br2 ) )
00964       p = &ON_Brep::m_ON_Brep_class_id;
00965     else if ( !ON_UuidCompare( &uuid, &revsrf ) )
00966       p = &ON_RevSurface::m_ON_RevSurface_class_id;
00967     else if ( !ON_UuidCompare( &uuid, &sumsrf ) )
00968       p = &ON_SumSurface::m_ON_SumSurface_class_id;
00969     else
00970       p = 0; // <- does nothing but it's a good place for debugger breakpoint
00971   }
00972   return p;
00973 }
00974 
00975 class ON__ClassIdDumpNode
00976 {
00977 public:
00978   ON__ClassIdDumpNode();
00979   ~ON__ClassIdDumpNode();
00980   const ON_ClassId* m_class_id;
00981   class ON__ClassIdDumpNode* m_parent_node;
00982   int m_depth;
00983   ON_SimpleArray<class ON__ClassIdDumpNode*> m_child_nodes;
00984   int CompareClassUuid( const class ON__ClassIdDumpNode& ) const;
00985   int CompareClassName( const class ON__ClassIdDumpNode& ) const;
00986   bool Dump( int depth, ON_TextLog& text_log );
00987 };
00988 
00989 ON__ClassIdDumpNode::ON__ClassIdDumpNode() 
00990 {
00991   m_class_id=0;
00992   m_parent_node=0;
00993   m_depth=0;
00994 };
00995 
00996 ON__ClassIdDumpNode::~ON__ClassIdDumpNode() 
00997 {
00998 }
00999 
01000 int ON__ClassIdDumpNode::CompareClassUuid( const class ON__ClassIdDumpNode& other ) const
01001 {
01002   int rc = 0;
01003   const ON_ClassId* a = m_class_id;
01004   const ON_ClassId* b = other.m_class_id;
01005   if ( a != b )
01006   {
01007     if ( 0 == a )
01008     {
01009       rc = -1;
01010     }
01011     else if ( 0 == b )
01012       rc = 1;
01013     else
01014     {
01015       rc = ON_UuidCompare(a->Uuid(),b->Uuid());
01016       if ( 0 == rc )
01017       {
01018         rc = CompareClassName(other);
01019       }
01020     }
01021   }
01022   return rc;
01023 }
01024 
01025 int ON__ClassIdDumpNode::CompareClassName( const class ON__ClassIdDumpNode& other ) const
01026 {
01027   int rc = 0;
01028   const ON_ClassId* a = m_class_id;
01029   const ON_ClassId* b = other.m_class_id;
01030   if ( a != b )
01031   {
01032     if ( 0 == a )
01033     {
01034       rc = -1;
01035     }
01036     else if ( 0 == b )
01037       rc = 1;
01038     else
01039     {
01040       const char* a_name = a->ClassName();
01041       const char* b_name = b->ClassName();
01042       if ( 0 == a_name )
01043       {
01044         if ( 0 == b_name )
01045         {
01046           rc = b->Mark() - a->Mark();
01047           if ( 0 == rc )
01048             rc = ON_UuidCompare(a->Uuid(),b->Uuid());
01049         }
01050         else
01051           rc = -1;
01052       }
01053       else if ( 0 == b_name )
01054       {
01055         rc = 1;
01056       }
01057       else
01058       {
01059         rc = on_stricmp(a_name,b_name);
01060         if ( 0 == rc )
01061         {
01062           rc = strcmp(a_name,b_name);
01063           if ( 0 == rc )
01064           {
01065             rc = b->Mark() - a->Mark();
01066             if ( 0 == rc )
01067               rc = ON_UuidCompare(a->Uuid(),b->Uuid());
01068           }
01069         }
01070       }
01071     }
01072   }
01073   return rc;
01074 }
01075 
01076 
01077 static int ON__ClassIdDumpNode_CompareUuid( const ON__ClassIdDumpNode* a, const ON__ClassIdDumpNode* b )
01078 {
01079   int rc = 0;
01080   if ( 0 == a )
01081   {
01082     rc = (0 == b) ? 0 : -1;
01083   }
01084   else if ( 0 == b )
01085   {
01086     rc = 1;
01087   }
01088   else
01089   {
01090     rc = a->CompareClassUuid(*b);
01091   }
01092   return rc;
01093 }
01094 
01095 static int ON__ClassIdDumpNode_CompareName( ON__ClassIdDumpNode *const* a, ON__ClassIdDumpNode *const* b )
01096 {
01097   int rc = 0;
01098   if ( 0 == a )
01099   {
01100     rc = (0 == b) ? 0 : -1;
01101   }
01102   else if ( 0 == b )
01103   {
01104     rc = 1;
01105   }
01106   else
01107   {
01108     rc = (*a)->CompareClassName(*(*b));
01109   }
01110   return rc;
01111 }
01112 
01113 bool ON__ClassIdDumpNode::Dump( int depth, ON_TextLog& text_log )
01114 {
01115   bool rc = true;
01116   if ( 0 == m_class_id || m_depth != 0 || depth < 1)
01117     rc = false;
01118   else
01119   {
01120     m_depth = depth;
01121     const char* class_name = m_class_id->ClassName();
01122     if ( 0 == class_name )
01123     {
01124       class_name = "!!ERROR!!";
01125       rc = false;
01126     }
01127     text_log.Print("%s::ClassId: ",m_class_id->ClassName());
01128     text_log.Print( "mark=%d ",m_class_id->Mark() );
01129     text_log.Print( m_class_id->Uuid() );
01130     text_log.Print("  (%08x)\n",m_class_id);
01131     int i, count = m_child_nodes.Count();
01132     if ( count > 0 )
01133     {
01134       // dump children names alphabetically
01135       m_child_nodes.QuickSort( ON__ClassIdDumpNode_CompareName );
01136 
01137       text_log.PushIndent();
01138       for ( i = 0; i < count; i++ )
01139       {
01140         ON__ClassIdDumpNode* child_node = m_child_nodes[i];
01141         if ( 0 == child_node )
01142           rc = false;
01143         else
01144         {
01145           if ( !child_node->Dump(depth+1,text_log) )
01146             rc = false;
01147         }
01148       }
01149       text_log.PopIndent();
01150     }
01151   }
01152   return rc;
01153 }
01154 
01155 void ON_ClassId::Dump( ON_TextLog& dump )
01156 {
01157   int i, j, count = 0;
01158   const ON_ClassId* p;
01159   for(p = m_p0; p && count < 1000000; p = p->m_pNext) 
01160   {
01161     count++;
01162   }
01163   if ( 0 != p )
01164   {
01165     dump.Print("ON_ClassId::m_p0 list is damaged.\n");
01166   }
01167   else
01168   {
01169     ON__ClassIdDumpNode tmp_node;
01170     ON_ClassArray<ON__ClassIdDumpNode> nodes(count);
01171     for(p = m_p0; p; p = p->m_pNext) 
01172     {
01173       ON__ClassIdDumpNode& node = nodes.AppendNew();
01174       node.m_class_id = p;
01175     }
01176 
01177     // sort nodes by class id's uuid
01178     nodes.QuickSort(ON__ClassIdDumpNode_CompareUuid);
01179 
01180     // fill in m_parent_node and m_child_nodes[]
01181     for ( i = 0; i < count; i++ )
01182     {
01183       ON__ClassIdDumpNode& node = nodes[i];
01184       p = node.m_class_id;
01185       if ( 0 != p )
01186       {
01187         tmp_node.m_class_id = p->BaseClass();
01188         j = nodes.BinarySearch(&tmp_node,ON__ClassIdDumpNode_CompareUuid);
01189         if ( j >= 0 && i != j)
01190         {
01191           ON__ClassIdDumpNode& base_node = nodes[j];
01192           node.m_parent_node = &base_node;
01193           base_node.m_child_nodes.Append(&node);
01194         }
01195       }      
01196     }
01197 
01198     // print class tree
01199         tmp_node.m_class_id = &ON_Object::m_ON_Object_class_id;
01200     i = nodes.BinarySearch(&tmp_node,ON__ClassIdDumpNode_CompareUuid);
01201     bool rc = false;
01202     if ( i >= 0 )
01203     {
01204       // recursively dump class tree
01205       rc = nodes[i].Dump(1,dump);
01206       for ( i = 0; i < count && rc; i++ )
01207       {
01208         if ( nodes[i].m_depth <= 0 )
01209           rc = false;
01210       }
01211     }
01212 
01213     if (!rc)
01214     {
01215       // should never happen
01216       for(p = m_p0; p; p = p->m_pNext) 
01217       {
01218         dump.Print("%s::ClassId: ",p->m_sClassName);
01219         dump.Print( "mark=%d ",p->m_mark );
01220         dump.Print( p->m_uuid );
01221         dump.Print("  (%08x)\n",p);
01222       }
01223     }
01224   }
01225 }
01226 
01227 const char* ON_ClassId::ClassName() const
01228 {
01229   return m_sClassName;
01230 }
01231 
01232 const char* ON_ClassId::BaseClassName() const
01233 {
01234   return m_sBaseClassName;
01235 }
01236 
01237 ON_UUID ON_ClassId::Uuid() const
01238 {
01239   return m_uuid;
01240 }
01241 
01242 int ON_ClassId::Mark() const
01243 {
01244   return (m_mark & 0x7FFFFFFF);
01245 }
01246 
01247 unsigned int ON_ClassId::ClassIdVersion() const
01248 {
01249   return (0 != (m_mark & 0x80000000)) ? m_class_id_version : 0;
01250 }
01251 
01252 
01253 const ON_ClassId* ON_ClassId::BaseClass() const
01254 {
01255   return m_pBaseClassId;
01256 }
01257 
01258 ON_BOOL32 ON_ClassId::IsDerivedFrom( const ON_ClassId* pBaseClassId ) const
01259 {
01260   // determine if this is derived from pBaseClassId
01261   ON_BOOL32 b = false;
01262   if ( pBaseClassId ) {
01263     const ON_ClassId* p = this;
01264     for(;p;) {
01265       if ( p == pBaseClassId ) {
01266         b = true;
01267         break;
01268       }
01269       p = p->m_pBaseClassId;
01270     }
01271   }
01272   return b;
01273 }
01274 
01276 
01277 ON_VIRTUAL_OBJECT_IMPLEMENT(ON_Object,0,"60B5DBBD-E660-11d3-BFE4-0010830122F0");
01278 
01279 bool ON_Object::CopyFrom( const ON_Object* src )
01280 {
01281   // In V6 this will be a virtual function that will be
01282   // declared in the ON_OBJECT_DECLARE macro and defined
01283   // in the ON_OBJECT_IMPLEMENT macro.  The check for
01284   // cid->ClassIdVersion() >= 1 is CRITICAL and it must
01285   // happen before looking at the cid->m_copy member.
01286   // See the comments in the ON_ClassId constructors for
01287   // details.
01288   const ON_ClassId* cid = ClassId();
01289   return (cid && cid->ClassIdVersion() >= 1 && cid->m_copy) ? cid->m_copy(src,this) : false;
01290 }
01291 
01292 ON_Object::ON_Object()
01293 : 
01294 m_userdata_list(0)
01295 {}
01296 
01297 ON_Object::ON_Object(const ON_Object& src)
01298 :
01299 m_userdata_list(0)
01300 {
01301   CopyUserData(src);
01302 }
01303 
01304 ON_Object& ON_Object::operator=(const ON_Object& src)
01305 {
01306   // DO NOT MODIFY this->m_mempool here
01307   if ( this !=&src ) {
01308     PurgeUserData();
01309     CopyUserData(src);
01310   }
01311   return *this;
01312 }
01313 
01314 ON_Object::~ON_Object()
01315 {
01316   PurgeUserData();
01317 }
01318 
01319 // DO NOT PUT THIS DECL IN A HEADER FILE.
01320 // THIS FUNCTION IS USED IN SPECIAL CIRCUMSTANCES
01321 // AND IS NOT INTENDED TO BE CALLED.
01322 ON_DECL bool ON__EnableLeakUserData(bool bEnable);
01323 
01324 static bool g__bLeakUserData = false;
01325 
01326 bool ON__EnableLeakUserData(bool bEnable)
01327 {
01328   bool b = bEnable;
01329   g__bLeakUserData = bEnable ? true : false;
01330   return b;
01331 }
01332 
01333 void ON_Object::EmergencyDestroy()
01334 {
01335   m_userdata_list = 0;
01336 }
01337 
01338 
01339 void ON_Object::PurgeUserData()
01340 {
01341   if ( m_userdata_list ) 
01342   {
01343     ON_UserData* p = m_userdata_list;
01344     ON_UserData* next;
01345     while(p) 
01346     {
01347       next = p->m_userdata_next;
01348       p->m_userdata_owner = 0;
01349       p->m_userdata_next = 0;
01350       if ( !g__bLeakUserData )
01351         delete p;
01352       p = next;
01353     }
01354     m_userdata_list = 0;
01355   }
01356 }
01357 
01358 ON_BOOL32 ON_Object::AttachUserData( ON_UserData* p )
01359 {
01360   ON_BOOL32 rc = false;
01361   if ( p 
01362        && NULL == p->m_userdata_owner
01363        && ON_UuidCompare( &ON_nil_uuid, &p->m_userdata_uuid) 
01364        && NULL == GetUserData( p->m_userdata_uuid )
01365        ) {
01366     if ( p->IsUnknownUserData() ) {
01367       // make sure we have valid user data - the first beta release of Rhino 2.0 
01368       // created empty user data.
01369       ON_UnknownUserData* uud = ON_UnknownUserData::Cast(p);
01370       if (uud)
01371         rc = uud->IsValid();
01372       if ( !rc ) {
01373         ON_ERROR("ON_Object::AttachUserData() - attempt to attach invalid UnknownUserData.");
01374       }
01375     }
01376     else
01377       rc = true;
01378     if (rc) 
01379     {
01380       p->m_userdata_owner = this;
01381       p->m_userdata_next = m_userdata_list;
01382       m_userdata_list = p;
01383     }
01384   }
01385   return rc;
01386 }
01387 
01388 ON_BOOL32 ON_Object::DetachUserData( ON_UserData* p )
01389 {
01390   ON_BOOL32 rc = false;
01391   if ( p && p->m_userdata_owner == this ) 
01392   {
01393     ON_UserData* prev = 0;
01394     ON_UserData* ud = m_userdata_list;
01395     while ( ud ) 
01396     {
01397       if ( ud == p ) 
01398       {
01399         if ( prev )
01400           prev->m_userdata_next = ud->m_userdata_next;
01401         else
01402           m_userdata_list = ud->m_userdata_next;
01403         ud->m_userdata_owner = 0;
01404         ud->m_userdata_next = 0;
01405         rc = true;
01406         break;
01407       }
01408       prev = ud;
01409       ud = ud->m_userdata_next;
01410     }
01411   }
01412   return rc;
01413 }
01414 
01415 
01416 ON_UserData* ON_Object::GetUserData( const ON_UUID& userdata_uuid ) const
01417 {
01418   ON_UserData* prev = NULL;
01419   ON_UserData* p;
01420   for ( p = m_userdata_list; p; prev = p, p = p->m_userdata_next ) 
01421   {
01422     if ( !ON_UuidCompare( &p->m_userdata_uuid, &userdata_uuid ) ) 
01423     {
01424       if ( p->IsUnknownUserData() ) 
01425       {
01426         // See if we can convert this unknown user data into something useful.
01427         // Unknown user data is created when a 3dm archive is read and
01428         // the definition of the specific user data class is not loaded.
01429         // If something is getting around to asking for a specific kind
01430         // of user data, the class definition has probably be dynamically
01431         // loaded.
01432         ON_UnknownUserData* uud = ON_UnknownUserData::Cast(p);
01433         if ( uud ) {
01434           ON_UserData* realp = uud->Convert();
01435           if ( realp ) 
01436           {
01437             // replace unknown user data with the real thing
01438             if ( prev )
01439               prev->m_userdata_next = realp;
01440             else if ( p == m_userdata_list ) 
01441             {
01442               // little white lie to attach the "real" user
01443               // data to the object in place of the unknown
01444               // user data.
01445               ON_Object* pNotConst = const_cast<ON_Object*>(this);
01446               pNotConst->m_userdata_list = realp;
01447               realp->m_userdata_owner = pNotConst; // Dale Lear added 22 Jan 2004 to fix I/O bug 
01448             }
01449             realp->m_userdata_next = p->m_userdata_next;
01450             p->m_userdata_next = 0;
01451             p->m_userdata_owner = 0;
01452             delete p;
01453             p = realp;
01454           }
01455         }
01456       }
01457       break;
01458     }
01459   }
01460   return p; 
01461 }
01462 
01463 ON_UserData* ON_Object::FirstUserData() const
01464 {
01465   return m_userdata_list;
01466 }
01467 
01468 
01469 void ON_Object::TransformUserData( const ON_Xform& x )
01470 {
01471   ON_UserData *p, *next;
01472   for ( p = m_userdata_list; p; p = next ) {
01473     next = p->m_userdata_next;
01474     if ( !p->Transform(x) )
01475       delete p;
01476   }
01477 }
01478 
01479 void ON_Object::CopyUserData( const ON_Object& src )
01480 {
01481   const ON_UserData* p;
01482   for ( p = src.m_userdata_list; p; p = p->m_userdata_next ) {
01483     if ( p->m_userdata_copycount ) {
01484       ON_Object* o = p->Duplicate();
01485       if ( o ) {
01486         if ( !AttachUserData(ON_UserData::Cast(o)) )
01487           delete o;
01488       }
01489     }
01490   }
01491 }
01492 
01493 void ON_Object::MoveUserData( ON_Object& src )
01494 {
01495   ON_UserData *p, *next;
01496 
01497   if ( 0 == m_userdata_list )
01498   {
01499     // quick and simple when the "this" doesn't
01500     // have any user data.
01501     if ( 0 != src.m_userdata_list )
01502     {
01503       m_userdata_list = src.m_userdata_list;
01504       src.m_userdata_list = 0;
01505       for ( p = m_userdata_list; p; p = p->m_userdata_next )
01506       {
01507         p->m_userdata_owner = this;
01508       }
01509     }
01510   }
01511   else
01512   {    
01513     // Carefully move userdata an item at a time to
01514     // avoid conflicts with existing items on "this".
01515 
01516     // delete source user data that already exists on this
01517     for ( p = src.m_userdata_list; p; p = next ) {
01518       next = p->m_userdata_next;
01519       if ( GetUserData( p->m_userdata_uuid ) )
01520         delete p;
01521     }
01522 
01523     // append source user data to this user data
01524     next = src.m_userdata_list;
01525     src.m_userdata_list = 0;
01526     for ( p = next; p; p = p->m_userdata_next ) {
01527       p->m_userdata_owner = this;
01528     }
01529 
01530     if ( !m_userdata_list ) 
01531       m_userdata_list = next;
01532     else 
01533     {
01534       p = m_userdata_list;
01535       while ( p->m_userdata_next )
01536         p = p->m_userdata_next;
01537       p->m_userdata_next = next;
01538     }
01539   }
01540 }
01541 
01542 
01543 void ON_Object::MemoryRelocate()
01544 {
01545   // When the memory location of an ON_Object changes,
01546   // the back-pointers on its user data need to be updated.
01547   ON_UserData* ud;
01548   for ( ud = m_userdata_list; ud; ud = ud->m_userdata_next )
01549   {
01550     ud->m_userdata_owner = this;
01551   }
01552 }
01553 
01554 ON_BOOL32 ON_Object::IsKindOf( const ON_ClassId* pBaseClassId ) const
01555 {
01556   ON_BOOL32 b = false;
01557   const ON_ClassId* p = ClassId();
01558   if ( p )
01559     b = p->IsDerivedFrom( pBaseClassId );
01560   return b;
01561 }
01562 
01563 
01564 ON::object_type ON_Object::ObjectType() const
01565 {
01566   // virtual function that is generally overridden
01567   return ON::unknown_object_type;
01568 }
01569 
01570 ON_UUID ON_Object::ModelObjectId() const
01571 {
01572   return ON_nil_uuid;
01573 }
01574 
01575 ON_UUID ON_Material::ModelObjectId() const
01576 {
01577   return m_material_id;
01578 }
01579 
01580 ON_UUID ON_Layer::ModelObjectId() const
01581 {
01582   return m_layer_id;
01583 }
01584 
01585 ON_UUID ON_Font::ModelObjectId() const
01586 {
01587   return m_font_id;
01588 }
01589 
01590 ON_UUID ON_DimStyle::ModelObjectId() const
01591 {
01592   return m_dimstyle_id;
01593 }
01594 
01595 ON_UUID ON_HatchPattern::ModelObjectId() const
01596 {
01597   return m_hatchpattern_id;
01598 }
01599 
01600 ON_UUID ON_Linetype::ModelObjectId() const
01601 {
01602   return m_linetype_id;
01603 }
01604 
01605 ON_UUID ON_Bitmap::ModelObjectId() const
01606 {
01607   return m_bitmap_id;
01608 }
01609 
01610 ON_UUID ON_Light::ModelObjectId() const
01611 {
01612   return m_light_id;
01613 }
01614 
01615 ON_UUID ON_TextureMapping::ModelObjectId() const
01616 {
01617   return m_mapping_id;
01618 }
01619 
01620 ON_UUID ON_InstanceDefinition::ModelObjectId() const
01621 {
01622   return m_uuid;
01623 }
01624 
01625 unsigned int ON_Object::SizeOf() const
01626 {
01627   unsigned int sz = sizeof(*this);
01628   const ON_UserData* ud = m_userdata_list;
01629   while ( ud )
01630   {
01631     sz += ud->SizeOf();
01632     ud = ud->m_userdata_next;
01633   }
01634   return sz;
01635 }
01636 
01637 ON__UINT32 ON_Object::DataCRC(ON__UINT32 current_remainder) const
01638 {
01639   // do not include user data.
01640   return current_remainder;
01641 }
01642 
01643 void ON_Object::Dump( ON_TextLog& dump ) const
01644 {
01645   const ON_ClassId* p = ClassId();
01646   if ( p ) 
01647   {
01648     const char* class_name = p->ClassName();
01649     if ( 0 == class_name ) 
01650       class_name = "unknown";
01651     dump.Print("class name: %s\n",class_name);
01652     dump.Print("class uuid: ");
01653     dump.Print(p->Uuid());
01654     dump.Print("\n");
01655   }
01656   else 
01657   {
01658     dump.Print("ON_Object::ClassId() FAILED\n");
01659   }
01660 }
01661 
01662 ON_BOOL32 ON_Object::Write(
01663        ON_BinaryArchive&
01664      ) const
01665 {
01666   // default Write() does nothing.
01667   return false;
01668 
01669   // object derived from ON_Object should have a Write() that looks
01670   // something like
01671 
01672   /*
01673   ON_BOOL32 rc = file.Write3dmChunkVersion(1,0);
01674   if (rc) {
01675     // TODO
01676   }
01677   return rc;
01678   */
01679 
01680 }
01681 
01682 ON_BOOL32 ON_Object::Read(
01683        ON_BinaryArchive&
01684      )
01685 {
01686   // default Read() does nothing.
01687   return false;
01688 
01689   // object derived from ON_Object should have a Read() that looks
01690   // something like
01691 
01692   /*
01693   int major_version = 0;
01694   int minor_version = 0;
01695   ON_BOOL32 rc = file.Read3dmChunkVersion(&major_version,&minor_version);
01696   if (rc && major_version==1) {
01697     // common to all 1.x versions
01698     // TODO
01699   }
01700   return rc;
01701   */
01702 
01703 }
01704 
01705 void ON_Object::DestroyRuntimeCache( bool bDelete )
01706 {
01707 }
01708 
01709 void ON_Curve::DestroyRuntimeCache( bool bDelete )
01710 {
01711 }
01712 
01713 
01714 void ON_CurveProxy::DestroyRuntimeCache( bool bDelete )
01715 {
01716   ON_Curve::DestroyRuntimeCache(bDelete);
01717   if ( 0 != m_real_curve && m_real_curve != this )
01718   {
01719     ON_Curve* curve = const_cast<ON_Curve*>(m_real_curve);
01720     if ( 0 != curve )
01721       curve->DestroyRuntimeCache( bDelete );
01722   }
01723 }
01724 
01725 void ON_Surface::DestroyRuntimeCache( bool bDelete )
01726 {
01727 }
01728 
01729 void ON_SurfaceProxy::DestroyRuntimeCache( bool bDelete )
01730 {
01731   ON_Surface::DestroyRuntimeCache( bDelete );
01732   if ( 0 != m_surface && m_surface != this )
01733   {
01734     ON_Surface* surface = const_cast<ON_Surface*>(m_surface);
01735     if ( 0 != surface )
01736       surface->DestroyRuntimeCache( bDelete );
01737   }
01738 }
01739 
01740 void ON_Brep::DestroyRuntimeCache( bool bDelete )
01741 {
01742   int i, count;
01743 
01744   count = m_C2.Count();
01745   for ( i = 0; i < count; i++ )
01746   {
01747     if ( m_C2[i] )
01748       m_C2[i]->DestroyRuntimeCache(bDelete);
01749   }
01750 
01751   count = m_C3.Count();
01752   for ( i = 0; i < count; i++ )
01753   {
01754     if ( m_C3[i] )
01755       m_C3[i]->DestroyRuntimeCache(bDelete);
01756   }
01757 
01758   count = m_S.Count();
01759   for ( i = 0; i < count; i++ )
01760   {
01761     if ( m_S[i] )
01762       m_S[i]->DestroyRuntimeCache(bDelete);
01763   }
01764 
01765   count = m_T.Count();
01766   for ( i = 0; i < count; i++ )
01767   {
01768     m_T[i].DestroyRuntimeCache(bDelete);
01769   }
01770 
01771   count = m_E.Count();
01772   for ( i = 0; i < count; i++ )
01773   {
01774     m_E[i].DestroyRuntimeCache(bDelete);
01775   }
01776 
01777   count = m_F.Count();
01778   for ( i = 0; i < count; i++ )
01779   {
01780     m_F[i].DestroyRuntimeCache(bDelete);
01781   }
01782 
01783   // 15 August 2003 Dale Lear:
01784   //    I added the line to destroy the face's m_bbox.
01785   //    Since m_bbox is private, it will be recalculated
01786   //    when it is needed.  (We hope.)  The fact the face
01787   //    m_bbox is private and recalculated as needed makes
01788   //    it different than the m_pbox info on trims and loops.
01789   m_bbox.Destroy();
01790 }
01791 


pcl
Author(s): Open Perception
autogenerated on Wed Aug 26 2015 15:27:02