00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00015
00016 #include "pcl/surface/3rdparty/opennurbs/opennurbs.h"
00017
00018
00019 #if defined(ON_COMPILER_MSC)
00020
00021
00022
00023
00024
00025
00026
00027 #pragma warning( push )
00028 #pragma warning( disable : 4127 )
00029 #endif
00030
00031
00032 #if defined(ON_DLL_EXPORTS)
00033
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 #pragma message( " --- OpenNURBS overriding ONX_Model new and delete" )
00050
00051
00052
00053 void* ONX_Model_UserData::operator new(size_t sz)
00054 {
00055
00056 return onmalloc(sz);
00057 }
00058
00059 void ONX_Model_UserData::operator delete(void* p)
00060 {
00061
00062 onfree(p);
00063 }
00064
00065 void* ONX_Model_UserData::operator new[] (size_t sz)
00066 {
00067
00068 return onmalloc(sz);
00069 }
00070
00071 void ONX_Model_UserData::operator delete[] (void* p)
00072 {
00073
00074 onfree(p);
00075 }
00076
00077 void* ONX_Model_UserData::operator new(size_t, void* p)
00078 {
00079
00080 return p;
00081 }
00082
00083 void ONX_Model_UserData::operator delete(void*, void*)
00084 {
00085
00086 return;
00087 }
00088
00089
00090
00091
00092 void* ONX_Model_Object::operator new(size_t sz)
00093 {
00094
00095 return onmalloc(sz);
00096 }
00097
00098 void ONX_Model_Object::operator delete(void* p)
00099 {
00100
00101 onfree(p);
00102 }
00103
00104 void* ONX_Model_Object::operator new[] (size_t sz)
00105 {
00106
00107 return onmalloc(sz);
00108 }
00109
00110 void ONX_Model_Object::operator delete[] (void* p)
00111 {
00112
00113 onfree(p);
00114 }
00115
00116 void* ONX_Model_Object::operator new(size_t, void* p)
00117 {
00118
00119 return p;
00120 }
00121
00122 void ONX_Model_Object::operator delete(void*, void*)
00123 {
00124
00125 return;
00126 }
00127
00128
00129
00130
00131 void* ONX_Model_RenderLight::operator new(size_t sz)
00132 {
00133
00134 return onmalloc(sz);
00135 }
00136
00137 void ONX_Model_RenderLight::operator delete(void* p)
00138 {
00139
00140 onfree(p);
00141 }
00142
00143 void* ONX_Model_RenderLight::operator new[] (size_t sz)
00144 {
00145
00146 return onmalloc(sz);
00147 }
00148
00149 void ONX_Model_RenderLight::operator delete[] (void* p)
00150 {
00151
00152 onfree(p);
00153 }
00154
00155 void* ONX_Model_RenderLight::operator new(size_t, void* p)
00156 {
00157
00158 return p;
00159 }
00160
00161 void ONX_Model_RenderLight::operator delete(void*, void*)
00162 {
00163
00164 return;
00165 }
00166
00167
00168
00169
00170 void* ONX_Model::operator new(size_t sz)
00171 {
00172
00173 return onmalloc(sz);
00174 }
00175
00176 void ONX_Model::operator delete(void* p)
00177 {
00178
00179 onfree(p);
00180 }
00181
00182 void* ONX_Model::operator new[] (size_t sz)
00183 {
00184
00185 return onmalloc(sz);
00186 }
00187
00188 void ONX_Model::operator delete[] (void* p)
00189 {
00190
00191 onfree(p);
00192 }
00193
00194 void* ONX_Model::operator new(size_t, void* p)
00195 {
00196
00197 return p;
00198 }
00199
00200 void ONX_Model::operator delete(void*, void*)
00201 {
00202
00203 return;
00204 }
00205
00206 #endif
00207
00208
00209
00211
00212
00213 static
00214 bool ONX_IsValidNameFirstChar( wchar_t c )
00215 {
00216 if ( c > 127 )
00217 return true;
00218 if ( c < '0' )
00219 return false;
00220 if ( c <= '9' )
00221 return true;
00222 if ( c < 'A' )
00223 return false;
00224 if ( c <= 'Z' )
00225 return true;
00226 if ( c == '_' )
00227 return true;
00228 if ( c < 'a' )
00229 return false;
00230 if ( c <= 'z' )
00231 return true;
00232 return false;
00233 }
00234
00235 static
00236 bool ONX_IsValidNameSecondChar( wchar_t c )
00237 {
00238
00239
00240 return (c >= 32 && c != 34 && c != 127);
00241 }
00242
00243 bool ONX_IsValidName(
00244 const wchar_t* name
00245 )
00246 {
00247 bool is_valid = (0 != name && ONX_IsValidNameFirstChar(*name));
00248 if ( is_valid )
00249 {
00250 bool is_integer = (*name >= '0' && *name <= '9');
00251 name++;
00252 while ( ONX_IsValidNameSecondChar(*name) )
00253 {
00254 if ( *name < '0' || *name >= '9' )
00255 is_integer = false;
00256 name++;
00257 }
00258 if ( *name || is_integer )
00259 is_valid = false;
00260 else if ( name[-1] <= 32 )
00261 is_valid = false;
00262 }
00263 return is_valid;
00264 }
00265
00268
00269 ONX_Model_RenderLight::ONX_Model_RenderLight()
00270 {
00271 }
00272
00273 ONX_Model_RenderLight::~ONX_Model_RenderLight()
00274 {
00275 }
00276
00277 ONX_Model_RenderLight::ONX_Model_RenderLight(const ONX_Model_RenderLight& src)
00278 : m_light(src.m_light),
00279 m_attributes(src.m_attributes)
00280 {
00281 }
00282
00283 ONX_Model_RenderLight& ONX_Model_RenderLight::operator=(const ONX_Model_RenderLight& src)
00284 {
00285 if ( this != &src )
00286 {
00287 m_light = src.m_light;
00288 m_attributes = src.m_attributes;
00289 }
00290 return *this;
00291 }
00292
00295
00296
00297 ONX_Model_Object::ONX_Model_Object()
00298 : m_bDeleteObject(0),
00299 m_object(0),
00300 m_ref_count(0)
00301 {
00302 }
00303
00304 void ONX_Model_Object::Destroy()
00305 {
00306 if ( m_ref_count )
00307 {
00308 if ( *m_ref_count > 0 )
00309 (*m_ref_count)--;
00310 if ( *m_ref_count <= 0 )
00311 {
00312 delete m_ref_count;
00313 m_ref_count = 0;
00314 }
00315 }
00316 if ( 0 == m_ref_count && 0 != m_object && m_bDeleteObject )
00317 {
00318 delete m_object;
00319 }
00320 m_object = 0;
00321 m_bDeleteObject = false;
00322 }
00323
00324 ONX_Model_Object::~ONX_Model_Object()
00325 {
00326 Destroy();
00327 }
00328
00329 ONX_Model_Object::ONX_Model_Object(const ONX_Model_Object& src)
00330 : m_bDeleteObject(0),
00331 m_object(0),
00332 m_ref_count(0)
00333 {
00334 *this = src;
00335 }
00336
00337 ONX_Model_Object& ONX_Model_Object::operator=(const ONX_Model_Object& src)
00338 {
00339 if ( this != &src )
00340 {
00341 Destroy();
00342 m_bDeleteObject = src.m_bDeleteObject;
00343 m_object = src.m_object;
00344 m_attributes = src.m_attributes;
00345 m_ref_count = src.m_ref_count;
00346 if ( 0 != m_object && m_bDeleteObject )
00347 {
00348 if ( 0 != m_ref_count )
00349 (*m_ref_count)++;
00350 else
00351 {
00352 m_ref_count = new unsigned int;
00353 *m_ref_count = 2;
00354 const_cast<ONX_Model_Object*>(&src)->m_ref_count = m_ref_count;
00355 }
00356 }
00357 }
00358 return *this;
00359 }
00360
00363
00364
00365 ONX_Model_UserData::ONX_Model_UserData()
00366 : m_uuid(ON_nil_uuid)
00367 , m_usertable_3dm_version(0)
00368 , m_usertable_opennurbs_version(0)
00369 {
00370 }
00371
00372 ONX_Model_UserData::~ONX_Model_UserData()
00373 {
00374 }
00375
00376 ONX_Model_UserData::ONX_Model_UserData(const ONX_Model_UserData& src)
00377 : m_uuid(src.m_uuid)
00378 , m_goo(src.m_goo)
00379 , m_usertable_3dm_version(src.m_usertable_3dm_version)
00380 , m_usertable_opennurbs_version(src.m_usertable_opennurbs_version)
00381 {
00382 }
00383
00384 ONX_Model_UserData& ONX_Model_UserData::operator=(const ONX_Model_UserData& src)
00385 {
00386 if ( this != &src )
00387 {
00388 m_uuid = src.m_uuid;
00389 m_goo = src.m_goo;
00390 m_usertable_3dm_version = src.m_usertable_3dm_version;
00391 m_usertable_opennurbs_version = src.m_usertable_opennurbs_version;
00392 }
00393 return *this;
00394 }
00395
00398
00399 ONX_Model::ONX_Model()
00400 : m_3dm_file_version(0),
00401 m_3dm_opennurbs_version(0),
00402 m_file_length(0),
00403 m_crc_error_count(0)
00404 {
00405 m_sStartSectionComments.Empty();
00406 m_properties.Default();
00407 m_settings.Default();
00408 }
00409
00410 ONX_Model::~ONX_Model()
00411 {
00412 Destroy();
00413 }
00414
00415 void ONX_Model::Destroy()
00416 {
00417 int i;
00418 m_3dm_file_version = 0;
00419 m_3dm_opennurbs_version = 0;
00420 m_sStartSectionComments.Empty();
00421 m_properties.Default();
00422 m_settings.Default();
00423
00424 for ( i = 0; i < m_history_record_table.Count(); i++ )
00425 delete m_history_record_table[i];
00426 m_history_record_table.Zero();
00427
00428 for ( i = 0; i < m_bitmap_table.Count(); i++ )
00429 delete m_bitmap_table[i];
00430 m_bitmap_table.Zero();
00431
00432 m_bitmap_table.SetCapacity(0);
00433 m_mapping_table.SetCapacity(0);
00434 m_material_table.SetCapacity(0);
00435 m_linetype_table.SetCapacity(0);
00436 m_layer_table.SetCapacity(0);
00437 m_group_table.SetCapacity(0);
00438 m_font_table.SetCapacity(0);
00439 m_dimstyle_table.SetCapacity(0);
00440 m_light_table.SetCapacity(0);
00441 m_hatch_pattern_table.SetCapacity(0);
00442 m_idef_table.SetCapacity(0);
00443 m_object_table.SetCapacity(0);
00444 m_history_record_table.SetCapacity(0);
00445 m_userdata_table.SetCapacity(0);
00446
00447 m_file_length = 0;
00448 m_crc_error_count = 0;
00449
00450 DestroyCache();
00451 }
00452
00453
00454 void ONX_Model::DestroyCache()
00455 {
00456 m_mapping_id_index.Empty();
00457 m_material_id_index.Empty();
00458 m_idef_id_index.Empty();
00459 m_object_id_index.Empty();
00460
00461 m__object_table_bbox.Destroy();
00462 }
00463
00464 ON_BoundingBox ONX_Model::BoundingBox() const
00465 {
00466 if( !m__object_table_bbox.IsValid() && m_object_table.Count() > 0 )
00467 {
00468 ON_BoundingBox bbox;
00469 int i, object_count = m_object_table.Count();
00470 for ( i = 0; i < object_count; i++ )
00471 {
00472 const ON_Geometry* geo = ON_Geometry::Cast(m_object_table[i].m_object);
00473 if ( geo )
00474 bbox.Union(geo->BoundingBox());
00475 const_cast<ONX_Model*>(this)->m__object_table_bbox = bbox;
00476 }
00477 }
00478 return m__object_table_bbox;
00479 }
00480
00481 void ONX_Model::GetRenderMaterial( const ON_3dmObjectAttributes& attributes, ON_Material& material ) const
00482 {
00483 int material_index = -1;
00484
00485 switch ( attributes.MaterialSource() )
00486 {
00487 case ON::material_from_layer:
00488 if ( attributes.m_layer_index >= 0 && attributes.m_layer_index < m_layer_table.Count() )
00489 material_index = m_layer_table[attributes.m_layer_index].RenderMaterialIndex();
00490 break;
00491 case ON::material_from_object:
00492 material_index = attributes.m_material_index;
00493 break;
00494
00495 case ON::material_from_parent:
00496 material_index = attributes.m_material_index;
00497
00498 break;
00499 }
00500
00501 if ( material_index < 0 || material_index >= m_material_table.Count() )
00502 {
00503 material_index = -1;
00504 material.Default();
00505 }
00506 else
00507 {
00508 material = m_material_table[material_index];
00509 }
00510
00511 material.SetMaterialIndex(material_index);
00512 }
00513
00514 void ONX_Model::GetRenderMaterial(
00515 int object_index,
00516 ON_Material& material
00517 ) const
00518 {
00519 if ( object_index < 0 || object_index >= m_object_table.Count() )
00520 {
00521 material.Default();
00522 material.SetMaterialIndex(-1);
00523 }
00524 else
00525 GetRenderMaterial( m_object_table[object_index].m_attributes, material );
00526 }
00527
00528 void ONX_Model::GetLinetype( const ON_3dmObjectAttributes& attributes, ON_Linetype& linetype ) const
00529 {
00530 int linetype_index = -1;
00531
00532 switch ( attributes.LinetypeSource() )
00533 {
00534 case ON::linetype_from_layer:
00535 if ( attributes.m_layer_index >= 0 && attributes.m_layer_index < m_layer_table.Count() )
00536 linetype_index = m_layer_table[attributes.m_layer_index].LinetypeIndex();
00537 break;
00538 case ON::linetype_from_object:
00539 linetype_index = attributes.m_linetype_index;
00540 break;
00541 case ON::linetype_from_parent:
00542 linetype_index = attributes.m_linetype_index;
00543
00544
00545 break;
00546 }
00547
00548 if ( linetype_index < 0 || linetype_index >= m_linetype_table.Count() )
00549 {
00550 linetype_index = -1;
00551 linetype.Default();
00552 }
00553 else
00554 {
00555 linetype = m_linetype_table[linetype_index];
00556 }
00557
00558 linetype.SetLinetypeIndex(linetype_index);
00559 }
00560
00561 void ONX_Model::GetLinetype(
00562 int object_index,
00563 ON_Linetype& linetype
00564 ) const
00565 {
00566 if ( object_index < 0 || object_index >= m_object_table.Count() )
00567 {
00568 linetype.Default();
00569 linetype.SetLinetypeIndex(-1);
00570 }
00571 else
00572 {
00573 GetLinetype( m_object_table[object_index].m_attributes, linetype );
00574 }
00575 }
00576
00577
00578
00579 ON_Color ONX_Model::WireframeColor( const ON_3dmObjectAttributes& attributes ) const
00580 {
00581 ON_Color color = ON_UNSET_COLOR;
00582
00583 switch ( attributes.ColorSource() )
00584 {
00585 case ON::color_from_layer:
00586 if ( attributes.m_layer_index >= 0 && attributes.m_layer_index < m_layer_table.Count() )
00587 color = m_layer_table[attributes.m_layer_index].Color();
00588 break;
00589
00590 case ON::color_from_object:
00591 color = attributes.m_color;
00592 break;
00593
00594 case ON::color_from_material:
00595 {
00596 ON_Material mat;
00597 GetRenderMaterial( attributes, mat );
00598 color = mat.Diffuse();
00599 }
00600 break;
00601
00602 case ON::color_from_parent:
00603 color = attributes.m_color;
00604
00605
00606 break;
00607 }
00608
00609 if ( color == ON_UNSET_COLOR )
00610 color.SetRGB(128,128,128);
00611
00612 return color;
00613 }
00614
00615 ON_Color ONX_Model::WireframeColor(int object_index) const
00616 {
00617 ON_Color c;
00618 if ( object_index < 0 || object_index >= m_object_table.Count() )
00619 {
00620 ON_3dmObjectAttributes a;
00621 c = a.m_color;
00622 }
00623 else
00624 c = WireframeColor( m_object_table[object_index].m_attributes );
00625 return c;
00626 }
00627
00628
00629 void ONX_DumpView( ON_TextLog& dump, const ON_3dmView& view )
00630 {
00631 view.Dump(dump);
00632 }
00633
00634 void ONX_Model::DumpSummary( ON_TextLog& dump ) const
00635 {
00636 dump.Print("File version: %d\n",m_3dm_file_version);
00637 dump.Print("File openNURBS version: %d\n",m_3dm_opennurbs_version);
00638 if ( m_file_length > 0 )
00639 dump.Print("File length: %d bytes\n",m_file_length);
00640
00641 if ( m_sStartSectionComments.Length() > 0 )
00642 {
00643 dump.Print("Start section comments:\n");
00644 dump.PushIndent();
00645 dump.PrintWrappedText(m_sStartSectionComments);
00646 dump.PopIndent();
00647 dump.Print("\n");
00648 }
00649
00650 m_properties.Dump(dump);
00651
00652 dump.Print("\n");
00653
00654 m_settings.Dump(dump);
00655
00656 dump.Print("\n");
00657
00658 dump.Print("Contents:\n");
00659 dump.PushIndent();
00660 dump.Print("%d embedded bitmaps\n",m_bitmap_table.Count());
00661 dump.Print("%d render material definitions\n",m_material_table.Count());
00662 dump.Print("%d line type definitions\n",m_linetype_table.Count());
00663 dump.Print("%d layers\n",m_layer_table.Count());
00664 dump.Print("%d render lights\n",m_light_table.Count());
00665 dump.Print("%d groups\n",m_group_table.Count());
00666 dump.Print("%d objects\n",m_object_table.Count());
00667 dump.Print("%d user data objects\n",m_userdata_table.Count());
00668 dump.PopIndent();
00669 }
00670
00671 void ONX_Model::DumpBitmapTable( ON_TextLog& dump) const
00672 {
00673 int i;
00674 for ( i = 0; i < m_bitmap_table.Count(); i++ )
00675 {
00676 dump.Print("Bitmap %d:\n",i);
00677 dump.PushIndent();
00678 m_bitmap_table[i]->Dump(dump);
00679 dump.PopIndent();
00680 }
00681 }
00682
00683 void ONX_Model::DumpTextureMappingTable( ON_TextLog& dump) const
00684 {
00685 int i;
00686 for ( i = 0; i < m_mapping_table.Count(); i++ )
00687 {
00688 dump.Print("Texture Mapping %d:\n",i);
00689 dump.PushIndent();
00690 m_mapping_table[i].Dump(dump);
00691 dump.PopIndent();
00692 }
00693 }
00694
00695 void ONX_Model::DumpMaterialTable( ON_TextLog& dump) const
00696 {
00697 int i;
00698 for ( i = 0; i < m_material_table.Count(); i++ )
00699 {
00700 dump.Print("Material %d:\n",i);
00701 dump.PushIndent();
00702 m_material_table[i].Dump(dump);
00703 dump.PopIndent();
00704 }
00705 }
00706
00707 void ONX_Model::DumpLinetypeTable( ON_TextLog& dump ) const
00708 {
00709 int i;
00710 for ( i = 0; i < m_linetype_table.Count(); i++ )
00711 {
00712 dump.Print("Linetype %d:\n",i);
00713 dump.PushIndent();
00714 m_linetype_table[i].Dump(dump);
00715 dump.PopIndent();
00716 }
00717 }
00718
00719 void ONX_Model::DumpLayerTable( ON_TextLog& dump) const
00720 {
00721 int i;
00722 for ( i = 0; i < m_layer_table.Count(); i++ )
00723 {
00724 dump.Print("Layer %d:\n",i);
00725 dump.PushIndent();
00726 m_layer_table[i].Dump(dump);
00727 dump.PopIndent();
00728 }
00729 }
00730
00731 void ONX_Model::DumpLightTable( ON_TextLog& dump) const
00732 {
00733 int i;
00734 for ( i = 0; i < m_light_table.Count(); i++ )
00735 {
00736 dump.Print("Light %d:\n",i);
00737 dump.PushIndent();
00738 m_light_table[i].m_attributes.Dump(dump);
00739 m_light_table[i].m_light.Dump(dump);
00740 dump.PopIndent();
00741 }
00742 }
00743
00744 void ONX_Model::DumpGroupTable( ON_TextLog& dump) const
00745 {
00746 int i;
00747 for ( i = 0; i < m_group_table.Count(); i++ )
00748 {
00749 dump.Print("Group %d:\n",i);
00750 dump.PushIndent();
00751 m_group_table[i].Dump(dump);
00752 dump.PopIndent();
00753 }
00754 }
00755
00756 void ONX_Model::DumpFontTable( ON_TextLog& dump) const
00757 {
00758 int i;
00759 for ( i = 0; i < m_font_table.Count(); i++ )
00760 {
00761 dump.Print("Font %d:\n",i);
00762 dump.PushIndent();
00763 m_font_table[i].Dump(dump);
00764 dump.PopIndent();
00765 }
00766 }
00767
00768 void ONX_Model::DumpDimStyleTable( ON_TextLog& dump) const
00769 {
00770 int i;
00771 for ( i = 0; i < m_dimstyle_table.Count(); i++ )
00772 {
00773 dump.Print("DimStyle %d:\n",i);
00774 dump.PushIndent();
00775 m_dimstyle_table[i].Dump(dump);
00776 dump.PopIndent();
00777 }
00778 }
00779
00780
00781 void ONX_Model::DumpHatchPatternTable( ON_TextLog& dump) const
00782 {
00783 int i;
00784 for ( i = 0; i < m_hatch_pattern_table.Count(); i++ )
00785 {
00786 dump.Print("HatchPattern %d:\n",i);
00787 dump.PushIndent();
00788 m_hatch_pattern_table[i].Dump(dump);
00789 dump.PopIndent();
00790 }
00791 }
00792
00793 void ONX_Model::DumpIDefTable( ON_TextLog& dump) const
00794 {
00795 int i;
00796 for ( i = 0; i < m_idef_table.Count(); i++ )
00797 {
00798 dump.Print("Instance Definition %d:\n",i);
00799 dump.PushIndent();
00800 m_idef_table[i].Dump(dump);
00801 dump.PopIndent();
00802 }
00803 }
00804
00805 void ONX_Model_Object::Dump( ON_TextLog& dump ) const
00806 {
00807 if ( 0 != m_object )
00808 {
00809 m_object->Dump(dump);
00810
00811
00812 const ON_UserData* ud = m_object->FirstUserData();
00813 while(0 != ud)
00814 {
00815 dump.Print("object user data:\n");
00816 dump.PushIndent();
00817 ud->Dump(dump);
00818 dump.PopIndent();
00819 ud = ud->Next();
00820 }
00821 }
00822 else
00823 {
00824 dump.Print("NULL m_object pointer\n");
00825 }
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913 }
00914
00915 void ONX_Model::DumpObjectTable( ON_TextLog& dump) const
00916 {
00917 int i;
00918 for ( i = 0; i < m_object_table.Count(); i++ )
00919 {
00920 dump.Print("Object %d:\n",i);
00921 dump.PushIndent();
00922
00923
00924 m_object_table[i].m_attributes.Dump(dump);
00925
00926
00927 m_object_table[i].Dump(dump);
00928
00929 dump.PopIndent();
00930 }
00931 }
00932
00933 void ONX_Model::DumpHistoryRecordTable( ON_TextLog& dump) const
00934 {
00935 int i;
00936 for ( i = 0; i < m_history_record_table.Count(); i++ )
00937 {
00938 dump.Print("History record %d:\n",i);
00939 dump.PushIndent();
00940
00941 const ON_HistoryRecord* history_record = m_history_record_table[i];
00942 if ( history_record )
00943 {
00944 history_record->Dump(dump);
00945 }
00946 else
00947 {
00948 dump.Print("Missing.\n");
00949 }
00950
00951 dump.PopIndent();
00952 }
00953 }
00954
00955 void ONX_Model::DumpUserDataTable( ON_TextLog& dump) const
00956 {
00957 int i;
00958 for ( i = 0; i < m_userdata_table.Count(); i++ )
00959 {
00960 const ONX_Model_UserData& ud = m_userdata_table[i];
00961 dump.Print("User Data Table %d:\n",i);
00962 dump.PushIndent();
00963 dump.Print("uuid = "); dump.Print(ud.m_uuid); dump.Print("\n");
00964 ud.m_goo.Dump(dump);
00965 dump.PopIndent();
00966 }
00967 }
00968
00969 void ONX_Model::Dump( ON_TextLog& dump ) const
00970 {
00971 dump.Print("Model summary:\n");
00972 dump.PushIndent();
00973 DumpSummary(dump);
00974 dump.PopIndent();
00975 dump.Print("\n");
00976
00977 dump.Print("Bitmap table:\n");
00978 dump.PushIndent();
00979 DumpBitmapTable(dump);
00980 dump.PopIndent();
00981 dump.Print("\n");
00982
00983 dump.Print("TextureMapping table:\n");
00984 dump.PushIndent();
00985 DumpTextureMappingTable(dump);
00986 dump.PopIndent();
00987 dump.Print("\n");
00988
00989 dump.Print("Material table:\n");
00990 dump.PushIndent();
00991 DumpMaterialTable(dump);
00992 dump.PopIndent();
00993 dump.Print("\n");
00994
00995 dump.Print("Line type table:\n");
00996 dump.PushIndent();
00997 DumpLinetypeTable(dump);
00998 dump.PopIndent();
00999 dump.Print("\n");
01000
01001 dump.Print("Layer table:\n");
01002 dump.PushIndent();
01003 DumpLayerTable(dump);
01004 dump.PopIndent();
01005 dump.Print("\n");
01006
01007 dump.Print("Group table:\n");
01008 dump.PushIndent();
01009 DumpGroupTable(dump);
01010 dump.PopIndent();
01011 dump.Print("\n");
01012
01013 dump.Print("Font table:\n");
01014 dump.PushIndent();
01015 DumpFontTable(dump);
01016 dump.PopIndent();
01017 dump.Print("\n");
01018
01019 dump.Print("DimStyle table:\n");
01020 dump.PushIndent();
01021 DumpDimStyleTable(dump);
01022 dump.PopIndent();
01023 dump.Print("\n");
01024
01025 dump.Print("Light table:\n");
01026 dump.PushIndent();
01027 DumpLightTable(dump);
01028 dump.PopIndent();
01029 dump.Print("\n");
01030
01031 dump.Print("HatchPattern table:\n");
01032 dump.PushIndent();
01033 DumpHatchPatternTable(dump);
01034 dump.PopIndent();
01035 dump.Print("\n");
01036
01037 dump.Print("Instance Definition table:\n");
01038 dump.PushIndent();
01039 DumpIDefTable(dump);
01040 dump.PopIndent();
01041 dump.Print("\n");
01042
01043 dump.Print("Object table:\n");
01044 dump.PushIndent();
01045 DumpObjectTable(dump);
01046 dump.PopIndent();
01047 dump.Print("\n");
01048
01049 dump.Print("History record table:\n");
01050 dump.PushIndent();
01051 DumpHistoryRecordTable(dump);
01052 dump.PopIndent();
01053 dump.Print("\n");
01054
01055 dump.Print("User data table:\n");
01056 dump.PushIndent();
01057 DumpUserDataTable(dump);
01058 dump.PopIndent();
01059 dump.Print("\n");
01060 }
01061
01062 static
01063 bool CheckForCRCErrors(
01064 ON_BinaryArchive& archive,
01065 ONX_Model& model,
01066 ON_TextLog* error_log,
01067 const char* sSection
01068 )
01069 {
01070
01071 bool rc = false;
01072 int new_crc_count = archive.BadCRCCount();
01073
01074 if ( model.m_crc_error_count != new_crc_count )
01075 {
01076 if ( error_log )
01077 {
01078 error_log->Print("ERROR: Corrupt %s. (CRC errors).\n",sSection);
01079 error_log->Print("-- Attempting to continue.\n");
01080 }
01081 model.m_crc_error_count = new_crc_count;
01082 rc = true;
01083 }
01084
01085 return rc;
01086 }
01087
01088 class ON__CIndexPair
01089 {
01090 public:
01091 static int CompareOldIndex( const ON__CIndexPair* a, const ON__CIndexPair* b );
01092 static int CompareOldAndNewIndex( const ON__CIndexPair* a, const ON__CIndexPair* b );
01093 int m_old_index;
01094 int m_new_index;
01095 };
01096
01097 int ON__CIndexPair::CompareOldIndex( const ON__CIndexPair* a, const ON__CIndexPair* b )
01098 {
01099 return (a->m_old_index - b->m_old_index);
01100 }
01101
01102 int ON__CIndexPair::CompareOldAndNewIndex( const ON__CIndexPair* a, const ON__CIndexPair* b )
01103 {
01104 int i;
01105 if ( 0 == (i = a->m_old_index - b->m_old_index) )
01106 i = a->m_new_index - b->m_new_index;
01107 return i;
01108 }
01109
01110 class ON__CIndexMaps
01111 {
01112 public:
01113 ON__CIndexMaps( ONX_Model& model )
01114 : m_model(model),
01115 m_bRemapLayerIndex(0),
01116 m_bRemapMaterialIndex(0),
01117 m_bRemapLinetypeIndex(0),
01118 m_bRemapGroupIndex(0),
01119 m_bRemapFontIndex(0),
01120 m_bRemapDimstyleIndex(0),
01121 m_bRemapHatchPatternIndex(0),
01122 m_layer_count(0),
01123 m_group_count(0),
01124 m_material_count(0),
01125 m_linetype_count(0),
01126 m_font_count(0),
01127 m_dimstyle_count(0),
01128 m_hatch_pattern_count(0),
01129 m_default_layer_index(0),
01130 m_default_group_index(-1),
01131 m_default_material_index(-1),
01132 m_default_linetype_index(-1),
01133 m_default_font_index(0),
01134 m_default_dimstyle_index(0),
01135 m_default_hatch_pattern_index(-1)
01136 {
01137 CreateHelper();
01138 }
01139
01140
01141
01142
01143
01144
01145
01146 int RemapModel();
01147
01148 ONX_Model& m_model;
01149
01150 bool m_bRemapLayerIndex;
01151 bool m_bRemapMaterialIndex;
01152 bool m_bRemapLinetypeIndex;
01153 bool m_bRemapGroupIndex;
01154 bool m_bRemapFontIndex;
01155 bool m_bRemapDimstyleIndex;
01156 bool m_bRemapHatchPatternIndex;
01157
01158 int m_layer_count;
01159 int m_group_count;
01160 int m_material_count;
01161 int m_linetype_count;
01162 int m_font_count;
01163 int m_dimstyle_count;
01164 int m_hatch_pattern_count;
01165
01166 int m_default_layer_index;
01167 int m_default_group_index;
01168 int m_default_material_index;
01169 int m_default_linetype_index;
01170 int m_default_font_index;
01171 int m_default_dimstyle_index;
01172 int m_default_hatch_pattern_index;
01173
01174 ON_SimpleArray<ON__CIndexPair> m_layer_map;
01175 ON_SimpleArray<ON__CIndexPair> m_group_map;
01176 ON_SimpleArray<ON__CIndexPair> m_material_map;
01177 ON_SimpleArray<ON__CIndexPair> m_linetype_map;
01178 ON_SimpleArray<ON__CIndexPair> m_font_map;
01179 ON_SimpleArray<ON__CIndexPair> m_dimstyle_map;
01180 ON_SimpleArray<ON__CIndexPair> m_hatch_pattern_map;
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192 int RemapLayerIndex( int old_layer_index ) const;
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204 int RemapMaterialIndex( int old_material_index ) const;
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216 int RemapLinetypeIndex( int old_linetype_index ) const;
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227 int RemapGroupIndex( int old_group_index ) const;
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238 int RemapFontIndex( int old_font_index ) const;
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249 int RemapDimstyleIndex( int old_dimstyle_index ) const;
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260 int RemapHatchPatternIndex( int old_hatch_pattern_index ) const;
01261
01262
01263
01264
01265
01266
01267 int RemapGeometryAndObjectAttributes( ONX_Model_Object& );
01268
01269
01270
01271
01272
01273
01274
01275
01276 int RemapGeometryAttributes( ON_Object* );
01277
01278
01279
01280
01281
01282
01283
01284
01285 int RemapObjectAttributes( ON_3dmObjectAttributes& );
01286
01287
01288
01289
01290
01291
01292
01293
01294 int RemapLayerAttributes( ON_Layer& );
01295
01296
01297
01298
01299
01300
01301
01302
01303 int RemapRenderingAttributes( ON_RenderingAttributes& ra );
01304
01305 private:
01306 int CreateHelper();
01307
01308 private:
01309
01310 ON__CIndexMaps(const ON__CIndexMaps&);
01311 ON__CIndexMaps& operator=(const ON__CIndexMaps&);
01312 };
01313
01314
01315 int ON__CIndexMaps::CreateHelper()
01316 {
01317 int change_count = 0;
01318 int i;
01319
01320
01321
01322 for ( i = 0; i < m_model.m_bitmap_table.Count(); i++ )
01323 {
01324 ON_Bitmap* bitmap = m_model.m_bitmap_table[i];
01325 if ( !bitmap )
01326 {
01327 change_count++;
01328 m_model.m_bitmap_table.Remove(i);
01329 i--;
01330 continue;
01331 }
01332
01333 if ( bitmap->m_bitmap_index != i )
01334 {
01335 bitmap->m_bitmap_index = i;
01336 change_count++;
01337 }
01338 if ( ON_nil_uuid == bitmap->m_bitmap_id )
01339 {
01340 ON_CreateUuid(bitmap->m_bitmap_id);
01341 change_count++;
01342 }
01343 }
01344
01345
01346
01347
01348 m_model.m_mapping_id_index.Empty();
01349 m_model.m_mapping_id_index.Reserve(m_model.m_mapping_table.Count());
01350 for ( i = 0; i < m_model.m_mapping_table.Count(); i++ )
01351 {
01352 ON_TextureMapping& mapping = m_model.m_mapping_table[i];
01353 if ( mapping.m_mapping_index != i )
01354 {
01355 mapping.m_mapping_index = i;
01356 change_count++;
01357 }
01358 if ( ON_nil_uuid == mapping.m_mapping_id )
01359 {
01360 ON_CreateUuid(mapping.m_mapping_id);
01361 change_count++;
01362 }
01363 m_model.m_mapping_id_index.AddUuidIndex(mapping.m_mapping_id,i,false);
01364 }
01365
01366
01367 m_model.m_material_id_index.Empty();
01368 m_model.m_material_id_index.Reserve(m_model.m_material_table.Count());
01369 m_bRemapMaterialIndex = false;
01370 m_material_count = m_model.m_material_table.Count();
01371 m_material_map.SetCount(0);
01372 m_material_map.Reserve(m_material_count);
01373 for ( i = 0; i < m_material_count; i++ )
01374 {
01375 ON_Material& material = m_model.m_material_table[i];
01376 ON__CIndexPair& ip = m_material_map.AppendNew();
01377 ip.m_new_index = i;
01378 ip.m_old_index = material.m_material_index;
01379 if ( material.m_material_index != i )
01380 {
01381 material.m_material_index = i;
01382 m_bRemapMaterialIndex = true;
01383 change_count++;
01384 }
01385 if ( ON_nil_uuid == material.m_material_id )
01386 {
01387 ON_CreateUuid(material.m_material_id);
01388 change_count++;
01389 }
01390 m_model.m_material_id_index.AddUuidIndex(material.m_material_id,i,false);
01391 }
01392
01393
01394 m_bRemapLinetypeIndex = false;
01395 m_linetype_count = m_model.m_linetype_table.Count();
01396 m_linetype_map.SetCount(0);
01397 m_linetype_map.Reserve(m_linetype_count);
01398 for ( i = 0; i < m_linetype_count; i++ )
01399 {
01400 ON_Linetype& linetype = m_model.m_linetype_table[i];
01401 ON__CIndexPair& ip = m_linetype_map.AppendNew();
01402 ip.m_new_index = i;
01403 ip.m_old_index = linetype.m_linetype_index;
01404 if ( linetype.m_linetype_index != i )
01405 {
01406 linetype.m_linetype_index = i;
01407 m_bRemapLinetypeIndex = true;
01408 change_count++;
01409 }
01410 if ( ON_nil_uuid == linetype.m_linetype_id )
01411 {
01412 ON_CreateUuid(linetype.m_linetype_id);
01413 change_count++;
01414 }
01415 }
01416
01417
01418 if ( m_model.m_layer_table.Count() < 1 )
01419 {
01420 ON_Layer layer;
01421 layer.Default();
01422 m_model.GetUnusedLayerName(layer.m_name);
01423 if ( !ONX_IsValidName(layer.m_name) )
01424 layer.m_name = L"Default";
01425 layer.m_layer_index = 0;
01426 ON_CreateUuid(layer.m_layer_id);
01427 m_model.m_layer_table.Append(layer);
01428 change_count++;
01429 }
01430
01431
01432 m_bRemapLayerIndex = false;
01433 m_layer_count = m_model.m_layer_table.Count();
01434 m_layer_map.SetCount(0);
01435 m_layer_map.Reserve(m_layer_count);
01436 for ( i = 0; i < m_layer_count; i++ )
01437 {
01438 ON_Layer& layer = m_model.m_layer_table[i];
01439 ON__CIndexPair& ip = m_layer_map.AppendNew();
01440 ip.m_new_index = i;
01441 ip.m_old_index = layer.m_layer_index;
01442 if ( layer.m_layer_index != i )
01443 {
01444 layer.m_layer_index = i;
01445 m_bRemapLayerIndex = true;
01446 change_count++;
01447 }
01448 if ( ON_nil_uuid == layer.m_layer_id )
01449 {
01450 ON_CreateUuid(layer.m_layer_id);
01451 change_count++;
01452 }
01453 }
01454
01455
01456 m_bRemapGroupIndex = false;
01457 m_group_count = m_model.m_group_table.Count();
01458 m_group_map.SetCount(0);
01459 m_group_map.Reserve(m_group_count);
01460 for ( i = 0; i < m_group_count; i++ )
01461 {
01462 ON_Group& group = m_model.m_group_table[i];
01463 ON__CIndexPair& ip = m_group_map.AppendNew();
01464 ip.m_new_index = i;
01465 ip.m_old_index = group.m_group_index;
01466 if ( group.m_group_index != i )
01467 {
01468 group.m_group_index = i;
01469 m_bRemapGroupIndex = true;
01470 change_count++;
01471 }
01472 if ( ON_nil_uuid == group.m_group_id )
01473 {
01474 ON_CreateUuid(group.m_group_id);
01475 change_count++;
01476 }
01477 }
01478
01479
01480 if ( m_model.m_font_table.Count() < 1 )
01481 {
01482 ON_Font font;
01483 font.Defaults();
01484 if ( !ONX_IsValidName(font.m_font_name) )
01485 font.m_font_name = L"Default";
01486 font.m_font_index = 0;
01487 ON_CreateUuid(font.m_font_id);
01488 m_model.m_font_table.Append(font);
01489 change_count++;
01490 }
01491
01492
01493 m_bRemapFontIndex = false;
01494 m_font_count = m_model.m_font_table.Count();
01495 m_font_map.SetCount(0);
01496 m_font_map.Reserve(m_font_count);
01497 for ( i = 0; i < m_font_count; i++ )
01498 {
01499 ON_Font& font = m_model.m_font_table[i];
01500 ON__CIndexPair& ip = m_font_map.AppendNew();
01501 ip.m_new_index = i;
01502 ip.m_old_index = font.m_font_index;
01503 if ( font.m_font_index != i )
01504 {
01505 font.m_font_index = i;
01506 m_bRemapFontIndex = true;
01507 change_count++;
01508 }
01509 if ( ON_nil_uuid == font.m_font_id )
01510 {
01511 ON_CreateUuid(font.m_font_id);
01512 change_count++;
01513 }
01514 }
01515
01516
01517 if ( m_model.m_dimstyle_table.Count() < 1 )
01518 {
01519 ON_DimStyle dimstyle;
01520 dimstyle.SetDefaults();
01521 if ( !ONX_IsValidName(dimstyle.m_dimstyle_name) )
01522 dimstyle.m_dimstyle_name = L"Default";
01523 dimstyle.m_dimstyle_index = 0;
01524 ON_CreateUuid(dimstyle.m_dimstyle_id);
01525 dimstyle.m_fontindex = 0;
01526 m_model.m_dimstyle_table.Append(dimstyle);
01527 change_count++;
01528 }
01529
01530
01531 m_bRemapDimstyleIndex = false;
01532 m_dimstyle_count = m_model.m_dimstyle_table.Count();
01533 m_dimstyle_map.SetCount(0);
01534 m_dimstyle_map.Reserve(m_dimstyle_count);
01535 for ( i = 0; i < m_dimstyle_count; i++ )
01536 {
01537 ON_DimStyle& dimstyle = m_model.m_dimstyle_table[i];
01538 ON__CIndexPair& ip = m_dimstyle_map.AppendNew();
01539 ip.m_new_index = i;
01540 ip.m_old_index = dimstyle.m_dimstyle_index;
01541 if ( dimstyle.m_dimstyle_index != i )
01542 {
01543 dimstyle.m_dimstyle_index = i;
01544 m_bRemapDimstyleIndex = true;
01545 change_count++;
01546 }
01547 if ( ON_nil_uuid == dimstyle.m_dimstyle_id )
01548 {
01549 ON_CreateUuid(dimstyle.m_dimstyle_id);
01550 change_count++;
01551 }
01552 }
01553
01554
01555
01556 for ( i = 0; i < m_model.m_light_table.Count(); i++ )
01557 {
01558 ONX_Model_RenderLight& light = m_model.m_light_table[i];
01559 if ( light.m_light.m_light_index != i )
01560 {
01561 light.m_light.m_light_index = i;
01562 change_count++;
01563 }
01564
01565 if ( light.m_light.m_light_id == light.m_attributes.m_uuid )
01566 {
01567
01568 if ( ON_nil_uuid == light.m_light.m_light_id )
01569 {
01570
01571 ON_CreateUuid(light.m_light.m_light_id);
01572 light.m_attributes.m_uuid = light.m_light.m_light_id;
01573 change_count++;
01574 }
01575 }
01576 else if ( ON_nil_uuid == light.m_light.m_light_id )
01577 {
01578
01579 light.m_light.m_light_id = light.m_attributes.m_uuid;
01580 change_count++;
01581 }
01582 else if ( ON_nil_uuid == light.m_attributes.m_uuid )
01583 {
01584
01585 light.m_attributes.m_uuid = light.m_light.m_light_id;
01586 change_count++;
01587 }
01588 else
01589 {
01590
01591 light.m_attributes.m_uuid = light.m_light.m_light_id;
01592 change_count++;
01593 }
01594 }
01595
01596
01597 m_bRemapHatchPatternIndex = false;
01598 m_hatch_pattern_count = m_model.m_hatch_pattern_table.Count();
01599 m_hatch_pattern_map.SetCount(0);
01600 m_hatch_pattern_map.Reserve(m_hatch_pattern_count);
01601 for ( i = 0; i < m_hatch_pattern_count; i++ )
01602 {
01603 ON_HatchPattern& hatchpattern = m_model.m_hatch_pattern_table[i];
01604 ON__CIndexPair& ip = m_hatch_pattern_map.AppendNew();
01605 ip.m_new_index = i;
01606 ip.m_old_index = hatchpattern.m_hatchpattern_index;
01607 if ( ip.m_new_index != ip.m_old_index )
01608 {
01609 hatchpattern.m_hatchpattern_index = i;
01610 m_bRemapHatchPatternIndex = true;
01611 change_count++;
01612 }
01613 if ( ON_nil_uuid == hatchpattern.m_hatchpattern_id )
01614 {
01615 ON_CreateUuid(hatchpattern.m_hatchpattern_id);
01616 change_count++;
01617 }
01618 }
01619
01620
01621 m_model.m_idef_id_index.Empty();
01622 m_model.m_idef_id_index.Reserve(m_model.m_idef_table.Count());
01623 for ( i = 0; i < m_model.m_idef_table.Count(); i++ )
01624 {
01625 ON_InstanceDefinition& idef = m_model.m_idef_table[i];
01626 if ( ON_nil_uuid == idef.m_uuid )
01627 {
01628 ON_CreateUuid(idef.m_uuid);
01629 change_count++;
01630 }
01631 m_model.m_idef_id_index.AddUuidIndex(idef.m_uuid,i,false);
01632 }
01633
01634
01635 m_model.m_object_id_index.Empty();
01636 m_model.m_object_id_index.Reserve(m_model.m_object_table.Count());
01637 for ( i = 0; i < m_model.m_object_table.Count(); i++ )
01638 {
01639 ONX_Model_Object& mo = m_model.m_object_table[i];
01640 if ( ON_nil_uuid == mo.m_attributes.m_uuid )
01641 {
01642 ON_CreateUuid(mo.m_attributes.m_uuid);
01643 change_count++;
01644 }
01645 m_model.m_object_id_index.AddUuidIndex(mo.m_attributes.m_uuid,i,false);
01646 }
01647
01648
01649 for ( i = 0; i < m_model.m_history_record_table.Count(); i++ )
01650 {
01651 ON_HistoryRecord* hr = m_model.m_history_record_table[i];
01652 if ( !hr )
01653 {
01654 change_count++;
01655 m_model.m_history_record_table.Remove(i);
01656 i--;
01657 continue;
01658 }
01659 if ( ON_nil_uuid == hr->m_record_id )
01660 {
01661 ON_CreateUuid(hr->m_record_id);
01662 change_count++;
01663 }
01664 }
01665
01666
01667 if ( m_bRemapLayerIndex )
01668 m_layer_map.QuickSort( ON__CIndexPair::CompareOldAndNewIndex );
01669 if ( m_bRemapGroupIndex )
01670 m_group_map.QuickSort( ON__CIndexPair::CompareOldAndNewIndex );
01671 if ( m_bRemapMaterialIndex )
01672 m_material_map.QuickSort( ON__CIndexPair::CompareOldAndNewIndex );
01673 if ( m_bRemapLinetypeIndex )
01674 m_linetype_map.QuickSort( ON__CIndexPair::CompareOldAndNewIndex );
01675 if ( m_bRemapFontIndex )
01676 m_font_map.QuickSort( ON__CIndexPair::CompareOldAndNewIndex );
01677 if ( m_bRemapDimstyleIndex )
01678 m_dimstyle_map.QuickSort( ON__CIndexPair::CompareOldAndNewIndex );
01679 if ( m_bRemapHatchPatternIndex )
01680 m_hatch_pattern_map.QuickSort( ON__CIndexPair::CompareOldAndNewIndex );
01681
01682 return change_count;
01683 }
01684
01685 int ON__CIndexMaps::RemapGeometryAttributes( ON_Object* object )
01686 {
01687 int change_count = 0;
01688
01689 switch(object ? object->ObjectType() : ON::unknown_object_type )
01690 {
01691 case ON::layer_object:
01692 {
01693 ON_Layer* layer = ON_Layer::Cast(object);
01694 if ( layer )
01695 change_count += RemapLayerAttributes(*layer);
01696 }
01697 break;
01698
01699 case ON::annotation_object:
01700 {
01701 ON_Annotation2* ann = ON_Annotation2::Cast(object);
01702 if ( ann )
01703 {
01704 if (ann->IsText() )
01705 {
01706
01707 int old_font_index = ann->m_index;
01708 int new_font_index = RemapFontIndex(old_font_index);
01709 if ( new_font_index != old_font_index )
01710 {
01711 ann->m_index = new_font_index;
01712 change_count++;
01713 }
01714 }
01715 else
01716 {
01717
01718 int old_dimstyle_index = ann->m_index;
01719 int new_dimstyle_index = RemapDimstyleIndex(old_dimstyle_index);
01720 {
01721 if ( old_dimstyle_index != new_dimstyle_index )
01722 {
01723 ann->m_index = new_dimstyle_index;
01724 change_count++;
01725 }
01726 }
01727 }
01728 }
01729 }
01730 break;
01731
01732 case ON::hatch_object:
01733 {
01734 ON_Hatch* hatch_object = ON_Hatch::Cast(object);
01735 if ( hatch_object )
01736 {
01737 int old_hatch_pattern_index = hatch_object->PatternIndex();
01738 int new_hatch_pattern_index = RemapHatchPatternIndex(old_hatch_pattern_index);
01739 if ( old_hatch_pattern_index != new_hatch_pattern_index )
01740 hatch_object->SetPatternIndex(new_hatch_pattern_index);
01741 }
01742 }
01743 break;
01744
01745 default:
01746
01747 break;
01748 }
01749
01750 return change_count;
01751 }
01752
01753 int ON__CIndexMaps::RemapGeometryAndObjectAttributes( ONX_Model_Object& model_object )
01754 {
01755 int geometry_change_count = RemapGeometryAttributes(const_cast<ON_Object*>(model_object.m_object));
01756 int attribute_change_count = RemapObjectAttributes( model_object.m_attributes );
01757 return (geometry_change_count + attribute_change_count);
01758 }
01759
01760 int ON__CIndexMaps::RemapModel()
01761 {
01762 int change_count = 0;
01763
01764 int i, old_index, new_index;
01765
01766
01767 old_index = m_model.m_settings.m_current_layer_index;
01768 new_index = RemapLayerIndex(old_index);
01769 if ( new_index < 0 || new_index >= m_layer_count )
01770 {
01771 new_index = 0;
01772 }
01773 m_model.m_settings.m_current_layer_index = new_index;
01774 if ( !m_model.m_layer_table[new_index].IsVisibleAndNotLocked() )
01775 {
01776 m_model.m_layer_table[new_index].SetVisible( true );
01777 m_model.m_layer_table[new_index].SetLocked( false );
01778 }
01779 m_default_layer_index = m_model.m_settings.m_current_layer_index;
01780
01781 for ( i = 0; i < m_model.m_layer_table.Count(); i++ )
01782 {
01783 change_count += RemapLayerAttributes(m_model.m_layer_table[i]);
01784 }
01785
01786 for ( i = 0; i < m_model.m_dimstyle_table.Count(); i++ )
01787 {
01788 old_index = m_model.m_dimstyle_table[i].m_fontindex;
01789 new_index = RemapFontIndex(old_index);
01790 if ( new_index != old_index )
01791 {
01792 m_model.m_dimstyle_table[i].m_fontindex = new_index;
01793 change_count++;
01794 }
01795 }
01796
01797 for ( i = 0; i < m_model.m_light_table.Count(); i++ )
01798 {
01799 change_count += RemapObjectAttributes( m_model.m_light_table[i].m_attributes );
01800 }
01801
01802 for ( i = 0; i < m_model.m_object_table.Count(); i++ )
01803 {
01804 change_count += RemapGeometryAndObjectAttributes( m_model.m_object_table[i] );
01805 }
01806
01807 return change_count;
01808 }
01809
01810
01811
01812 static int RemapIndexHelper(
01813 int old_index,
01814 bool bRemapIndex,
01815 int count,
01816 int default_index,
01817 const ON_SimpleArray<ON__CIndexPair>& imap
01818 )
01819 {
01820 int new_index = old_index;
01821 if ( bRemapIndex )
01822 {
01823 ON__CIndexPair ip;
01824 memset(&ip,0,sizeof(ip));
01825 ip.m_old_index = old_index;
01826 int j = imap.BinarySearch(&ip,ON__CIndexPair::CompareOldIndex);
01827 if ( j >= 0 )
01828 new_index = imap[j].m_new_index;
01829 }
01830 if ( new_index < 0 || new_index >= count )
01831 new_index = default_index;
01832 return new_index;
01833 }
01834
01835 int ON__CIndexMaps::RemapLayerIndex( int old_layer_index ) const
01836 {
01837 return RemapIndexHelper(
01838 old_layer_index,
01839 m_bRemapLayerIndex,
01840 m_layer_count,
01841 m_default_layer_index,
01842 m_layer_map
01843 );
01844 }
01845
01846 int ON__CIndexMaps::RemapMaterialIndex( int old_material_index ) const
01847 {
01848 return RemapIndexHelper(
01849 old_material_index,
01850 m_bRemapMaterialIndex,
01851 m_material_count,
01852 m_default_material_index,
01853 m_material_map
01854 );
01855 }
01856
01857 int ON__CIndexMaps::RemapLinetypeIndex( int old_linetype_index ) const
01858 {
01859 return RemapIndexHelper(
01860 old_linetype_index,
01861 m_bRemapLinetypeIndex,
01862 m_linetype_count,
01863 m_default_linetype_index,
01864 m_linetype_map
01865 );
01866 }
01867
01868 int ON__CIndexMaps::RemapGroupIndex( int old_group_index ) const
01869 {
01870 return RemapIndexHelper(
01871 old_group_index,
01872 m_bRemapGroupIndex,
01873 m_group_count,
01874 m_default_group_index,
01875 m_group_map
01876 );
01877 }
01878
01879 int ON__CIndexMaps::RemapFontIndex( int old_font_index ) const
01880 {
01881 return RemapIndexHelper(
01882 old_font_index,
01883 m_bRemapFontIndex,
01884 m_font_count,
01885 m_default_font_index,
01886 m_font_map
01887 );
01888 }
01889
01890 int ON__CIndexMaps::RemapDimstyleIndex( int old_dimstyle_index ) const
01891 {
01892 return RemapIndexHelper(
01893 old_dimstyle_index,
01894 m_bRemapDimstyleIndex,
01895 m_dimstyle_count,
01896 m_default_dimstyle_index,
01897 m_dimstyle_map
01898 );
01899 }
01900
01901 int ON__CIndexMaps::RemapHatchPatternIndex( int old_hatch_pattern_index ) const
01902 {
01903 return RemapIndexHelper(
01904 old_hatch_pattern_index,
01905 m_bRemapHatchPatternIndex,
01906 m_hatch_pattern_count,
01907 m_default_hatch_pattern_index,
01908 m_hatch_pattern_map
01909 );
01910 }
01911
01912 int ON__CIndexMaps::RemapRenderingAttributes( ON_RenderingAttributes& ra )
01913 {
01914 int change_count = 0;
01915 int old_material_index, new_material_index, i;
01916 for ( i = ra.m_materials.Count()-1; i >= 0; i-- )
01917 {
01918 ON_MaterialRef& mr = ra.m_materials[i];
01919
01920 old_material_index = mr.m_material_index;
01921 if ( old_material_index >= 0 )
01922 {
01923 new_material_index = RemapMaterialIndex(old_material_index);
01924 if ( old_material_index != new_material_index )
01925 {
01926 mr.m_material_index = new_material_index;
01927 change_count++;
01928 }
01929 }
01930 else
01931 mr.m_material_index = -1;
01932
01933 old_material_index = mr.m_material_backface_index;
01934 if ( old_material_index >= 0 )
01935 {
01936 new_material_index = RemapMaterialIndex(old_material_index);
01937 if ( old_material_index != new_material_index )
01938 {
01939 mr.m_material_backface_index = new_material_index;
01940 change_count++;
01941 }
01942 }
01943 else
01944 mr.m_material_backface_index = -1;
01945
01946 if ( -1 == mr.m_material_index || mr.m_material_index >= m_material_count )
01947 {
01948 if ( ON_nil_uuid == mr.m_material_id )
01949 mr.m_material_index = -1;
01950 else if ( !m_model.m_material_id_index.FindUuid(mr.m_material_id,&mr.m_material_index) )
01951 mr.m_material_index = -1;
01952 }
01953 else if ( m_model.m_material_table[mr.m_material_index].m_material_id != mr.m_material_id )
01954 {
01955 new_material_index = -1;
01956 if ( !ON_UuidIsNil(mr.m_material_id)
01957 && m_model.m_material_id_index.FindUuid(mr.m_material_id,&new_material_index)
01958 && new_material_index >= 0
01959 && new_material_index < m_material_count
01960 )
01961 {
01962 mr.m_material_index = new_material_index;
01963 }
01964 else
01965 {
01966 mr.m_material_id = m_model.m_material_table[mr.m_material_index].m_material_id;
01967 }
01968 }
01969
01970 if ( -1 == mr.m_material_backface_index || mr.m_material_backface_index >= m_material_count )
01971 {
01972 if ( ON_nil_uuid == mr.m_material_backface_id )
01973 mr.m_material_backface_index = -1;
01974 else if ( !m_model.m_material_id_index.FindUuid(mr.m_material_backface_id,&mr.m_material_backface_index) )
01975 mr.m_material_backface_index = -1;
01976 }
01977 else if ( m_model.m_material_table[mr.m_material_backface_index].m_material_id != mr.m_material_backface_id )
01978 {
01979 new_material_index = -1;
01980 if ( !ON_UuidIsNil(mr.m_material_backface_id)
01981 && m_model.m_material_id_index.FindUuid(mr.m_material_backface_id,&new_material_index)
01982 && new_material_index >= 0
01983 && new_material_index < m_material_count
01984 )
01985 {
01986 mr.m_material_backface_index = new_material_index;
01987 }
01988 else
01989 {
01990 mr.m_material_backface_id = m_model.m_material_table[mr.m_material_backface_index].m_material_id;
01991 }
01992 }
01993
01994 if ( mr.m_material_index < 0 && mr.m_material_backface_index < 0 )
01995 {
01996 ra.m_materials.Remove(i);
01997 }
01998 }
01999 return change_count;
02000 }
02001
02002 int ON__CIndexMaps::RemapLayerAttributes( ON_Layer& layer )
02003 {
02004 int change_count = 0;
02005
02006 if ( ON_UuidIsNil(layer.m_layer_id) )
02007 {
02008 ON_CreateUuid(layer.m_layer_id);
02009 change_count++;
02010 }
02011
02012 int old_linetype_index = layer.m_linetype_index;
02013 int new_linetype_index = RemapLinetypeIndex(old_linetype_index);
02014 if ( old_linetype_index != new_linetype_index )
02015 {
02016 layer.m_linetype_index = new_linetype_index;
02017 change_count++;
02018 }
02019
02020 int old_material_index = layer.m_material_index;
02021 int new_material_index = RemapMaterialIndex(old_material_index);
02022 if ( old_material_index != new_material_index )
02023 {
02024 layer.m_material_index = new_material_index;
02025 change_count++;
02026 }
02027
02028 change_count += RemapRenderingAttributes(layer.m_rendering_attributes);
02029
02030 return change_count;
02031 }
02032
02033 int ON__CIndexMaps::RemapObjectAttributes( ON_3dmObjectAttributes& a )
02034 {
02035 int change_count = 0;
02036
02037 int i;
02038 if ( ON_UuidIsNil(a.m_uuid) )
02039 {
02040 ON_CreateUuid(a.m_uuid);
02041 change_count++;
02042 }
02043
02044 int old_layer_index = a.m_layer_index;
02045 int new_layer_index = RemapLayerIndex(old_layer_index);
02046 if ( old_layer_index != new_layer_index )
02047 {
02048 a.m_layer_index = new_layer_index;
02049 change_count++;
02050 }
02051
02052 int old_linetype_index = a.m_linetype_index;
02053 int new_linetype_index = RemapLinetypeIndex(old_linetype_index);
02054 if ( old_linetype_index != new_linetype_index )
02055 {
02056 a.m_linetype_index = new_linetype_index;
02057 change_count++;
02058 }
02059
02060 int old_material_index = a.m_material_index;
02061 int new_material_index = RemapMaterialIndex(old_material_index);
02062 if ( old_material_index != new_material_index )
02063 {
02064 a.m_material_index = new_material_index;
02065 change_count++;
02066 }
02067
02068 if ( a.TopGroup() != -1 )
02069 {
02070 bool bUpdateGroupList = true;
02071 ON_SimpleArray<int> group_list;
02072 a.GetGroupList(group_list);
02073 for ( i = group_list.Count()-1; i >= 0; i-- )
02074 {
02075 int old_group_index = group_list[i];
02076 int new_group_index = RemapGroupIndex(old_group_index);
02077 if ( new_group_index < 0 )
02078 {
02079 group_list.Remove(i);
02080 bUpdateGroupList = true;
02081 change_count++;
02082 }
02083 else if ( old_group_index != new_group_index )
02084 {
02085 group_list[i] = new_group_index;
02086 bUpdateGroupList = true;
02087 change_count++;
02088 }
02089 }
02090
02091 if ( bUpdateGroupList || group_list.Count() == 0 )
02092 {
02093 a.RemoveFromAllGroups();
02094 for( i = 0; i < group_list.Count(); i++ )
02095 a.AddToGroup(group_list[i]);
02096 }
02097 }
02098
02099 change_count += RemapRenderingAttributes(a.m_rendering_attributes);
02100
02101 return change_count;
02102 }
02103
02104 void ONX_Model::Polish()
02105 {
02106 DestroyCache();
02107
02108
02109 if ( m_properties.m_RevisionHistory.m_revision_count == 0 )
02110 m_properties.m_RevisionHistory.NewRevision();
02111
02112
02113
02114
02115 ON__CIndexMaps imaps(*this);
02116 imaps.RemapModel();
02117 }
02118
02119 bool ONX_Model::Read(
02120 const char* filename,
02121 ON_TextLog* error_log
02122 )
02123 {
02124 Destroy();
02125 bool rc = false;
02126 if ( 0 != filename )
02127 {
02128 FILE* fp = ON::OpenFile(filename,"rb");
02129 if ( 0 != fp )
02130 {
02131 ON_BinaryFile file(ON::read3dm,fp);
02132 rc = Read(file,error_log);
02133 ON::CloseFile(fp);
02134 }
02135 }
02136 return rc;
02137 }
02138
02139 bool ONX_Model::Read(
02140 const wchar_t* filename,
02141 ON_TextLog* error_log
02142 )
02143 {
02144 Destroy();
02145 bool rc = false;
02146 if ( 0 != filename )
02147 {
02148 FILE* fp = ON::OpenFile(filename,L"rb");
02149 if ( 0 != fp )
02150 {
02151 ON_BinaryFile file(ON::read3dm,fp);
02152 rc = Read(file,error_log);
02153 ON::CloseFile(fp);
02154 }
02155 }
02156 return rc;
02157 }
02158
02159 bool ONX_Model::Read(
02160 ON_BinaryArchive& archive,
02161 ON_TextLog* error_log
02162 )
02163 {
02164 const int max_error_count = 2000;
02165 int error_count = 0;
02166 bool return_code = true;
02167 int count, rc;
02168
02169 Destroy();
02170
02171
02172 if ( !archive.Read3dmStartSection( &m_3dm_file_version, m_sStartSectionComments ) )
02173 {
02174 if ( error_log) error_log->Print("ERROR: Unable to read start section. (ON_BinaryArchive::Read3dmStartSection() returned false.)\n");
02175 return false;
02176 }
02177 else if ( CheckForCRCErrors( archive, *this, error_log, "start section" ) )
02178 return_code = false;
02179
02180
02181 if ( !archive.Read3dmProperties( m_properties ) )
02182 {
02183 if ( error_log) error_log->Print("ERROR: Unable to read properties section. (ON_BinaryArchive::Read3dmProperties() returned false.)\n");
02184 return false;
02185 }
02186 else if ( CheckForCRCErrors( archive, *this, error_log, "properties section" ) )
02187 return_code = false;
02188
02189
02190 m_3dm_opennurbs_version = archive.ArchiveOpenNURBSVersion();
02191
02192
02193 if ( !archive.Read3dmSettings( m_settings ) )
02194 {
02195 if ( error_log) error_log->Print("ERROR: Unable to read settings section. (ON_BinaryArchive::Read3dmSettings() returned false.)\n");
02196 return false;
02197 }
02198 else if ( CheckForCRCErrors( archive, *this, error_log, "settings section" ) )
02199 return_code = false;
02200
02201
02202 if ( archive.BeginRead3dmBitmapTable() )
02203 {
02204
02205 ON_Bitmap* pBitmap = NULL;
02206 for( count = 0; true; count++ )
02207 {
02208 pBitmap = NULL;
02209 rc = archive.Read3dmBitmap(&pBitmap);
02210 if ( rc==0 )
02211 break;
02212 if ( rc < 0 )
02213 {
02214 if ( error_log)
02215 {
02216 error_log->Print("ERROR: Corrupt bitmap found. (ON_BinaryArchive::Read3dmBitmap() < 0.)\n");
02217 error_count++;
02218 if ( error_count > max_error_count )
02219 return false;
02220 error_log->Print("-- Attempting to continue.\n");
02221 }
02222 return_code = false;
02223 }
02224 m_bitmap_table.Append(pBitmap);
02225 }
02226
02227
02228
02229 if ( !archive.EndRead3dmBitmapTable() )
02230 {
02231 if ( error_log) error_log->Print("ERROR: Corrupt bitmap table. (ON_BinaryArchive::EndRead3dmBitmapTable() returned false.)\n");
02232 return false;
02233 }
02234 if ( CheckForCRCErrors( archive, *this, error_log, "bitmap table" ) )
02235 return_code = false;
02236 }
02237 else
02238 {
02239 if ( error_log)
02240 {
02241 error_log->Print("WARNING: Missing or corrupt bitmap table. (ON_BinaryArchive::BeginRead3dmBitmapTable() returned false.)\n");
02242 error_log->Print("-- Attempting to continue.\n");
02243 }
02244 return_code = false;
02245 }
02246
02247
02248
02249
02250 if ( archive.BeginRead3dmTextureMappingTable() )
02251 {
02252 ON_TextureMapping* pTextureMapping = NULL;
02253 for( count = 0; true; count++ )
02254 {
02255 rc = archive.Read3dmTextureMapping(&pTextureMapping);
02256 if ( rc==0 )
02257 break;
02258 if ( rc < 0 )
02259 {
02260 if ( error_log)
02261 {
02262 error_log->Print("ERROR: Corrupt render texture_mapping found. (ON_BinaryArchive::Read3dmTextureMapping() < 0.)\n");
02263 error_count++;
02264 if ( error_count > max_error_count )
02265 return false;
02266 error_log->Print("-- Attempting to continue.\n");
02267 }
02268 continue;
02269 }
02270 ON_UserDataHolder ud;
02271 ud.MoveUserDataFrom(*pTextureMapping);
02272 m_mapping_table.Append(*pTextureMapping);
02273 pTextureMapping->m_mapping_index = count;
02274 ud.MoveUserDataTo(*m_mapping_table.Last(),false);
02275 delete pTextureMapping;
02276 pTextureMapping = NULL;
02277 }
02278
02279
02280
02281 if ( !archive.EndRead3dmTextureMappingTable() )
02282 {
02283 if ( error_log) error_log->Print("ERROR: Corrupt render texture_mapping table. (ON_BinaryArchive::EndRead3dmTextureMappingTable() returned false.)\n");
02284 return false;
02285 }
02286 if ( CheckForCRCErrors( archive, *this, error_log, "render texture_mapping table" ) )
02287 return_code = false;
02288 }
02289 else
02290 {
02291 if ( error_log)
02292 {
02293 error_log->Print("WARNING: Missing or corrupt render texture_mapping table. (ON_BinaryArchive::BeginRead3dmTextureMappingTable() returned false.)\n");
02294 error_log->Print("-- Attempting to continue.\n");
02295 }
02296 return_code = false;
02297 }
02298
02299
02300
02301 if ( archive.BeginRead3dmMaterialTable() )
02302 {
02303 ON_Material* pMaterial = NULL;
02304 for( count = 0; true; count++ )
02305 {
02306 rc = archive.Read3dmMaterial(&pMaterial);
02307 if ( rc==0 )
02308 break;
02309 if ( rc < 0 )
02310 {
02311 if ( error_log)
02312 {
02313 error_log->Print("ERROR: Corrupt render material found. (ON_BinaryArchive::Read3dmMaterial() < 0.)\n");
02314 error_count++;
02315 if ( error_count > max_error_count )
02316 return false;
02317 error_log->Print("-- Attempting to continue.\n");
02318 }
02319 pMaterial = new ON_Material;
02320 pMaterial->m_material_index = count;
02321 }
02322 ON_UserDataHolder ud;
02323 ud.MoveUserDataFrom(*pMaterial);
02324 m_material_table.Append(*pMaterial);
02325 ud.MoveUserDataTo(*m_material_table.Last(),false);
02326 delete pMaterial;
02327 pMaterial = NULL;
02328 }
02329
02330
02331
02332 if ( !archive.EndRead3dmMaterialTable() )
02333 {
02334 if ( error_log) error_log->Print("ERROR: Corrupt render material table. (ON_BinaryArchive::EndRead3dmMaterialTable() returned false.)\n");
02335 return false;
02336 }
02337 if ( CheckForCRCErrors( archive, *this, error_log, "render material table" ) )
02338 return_code = false;
02339 }
02340 else
02341 {
02342 if ( error_log)
02343 {
02344 error_log->Print("WARNING: Missing or corrupt render material table. (ON_BinaryArchive::BeginRead3dmMaterialTable() returned false.)\n");
02345 error_log->Print("-- Attempting to continue.\n");
02346 }
02347 return_code = false;
02348 }
02349
02350
02351
02352 if ( archive.BeginRead3dmLinetypeTable() )
02353 {
02354 ON_Linetype* pLinetype = NULL;
02355 for( count = 0; true; count++ )
02356 {
02357 rc = archive.Read3dmLinetype(&pLinetype);
02358 if ( rc==0 )
02359 break;
02360 if ( rc < 0 )
02361 {
02362 if ( error_log)
02363 {
02364 error_log->Print("ERROR: Corrupt render linetype found. (ON_BinaryArchive::Read3dmLinetype() < 0.)\n");
02365 error_count++;
02366 if ( error_count > max_error_count )
02367 return false;
02368 error_log->Print("-- Attempting to continue.\n");
02369 }
02370 pLinetype = new ON_Linetype;
02371 pLinetype->m_linetype_index = count;
02372 }
02373 ON_UserDataHolder ud;
02374 ud.MoveUserDataFrom(*pLinetype);
02375 m_linetype_table.Append(*pLinetype);
02376 ud.MoveUserDataTo(*m_linetype_table.Last(),false);
02377 delete pLinetype;
02378 pLinetype = NULL;
02379 }
02380
02381
02382
02383 if ( !archive.EndRead3dmLinetypeTable() )
02384 {
02385 if ( error_log) error_log->Print("ERROR: Corrupt render linetype table. (ON_BinaryArchive::EndRead3dmLinetypeTable() returned false.)\n");
02386 return false;
02387 }
02388 if ( CheckForCRCErrors( archive, *this, error_log, "render linetype table" ) )
02389 return_code = false;
02390 }
02391 else
02392 {
02393 if ( error_log)
02394 {
02395 error_log->Print("WARNING: Missing or corrupt render linetype table. (ON_BinaryArchive::BeginRead3dmLinetypeTable() returned false.)\n");
02396 error_log->Print("-- Attempting to continue.\n");
02397 }
02398 return_code = false;
02399 }
02400
02401
02402 if ( archive.BeginRead3dmLayerTable() )
02403 {
02404 ON_Layer* pLayer = NULL;
02405 for( count = 0; true; count++ )
02406 {
02407 pLayer = NULL;
02408 rc = archive.Read3dmLayer(&pLayer);
02409 if ( rc==0 )
02410 break;
02411 if ( rc < 0 )
02412 {
02413 if ( error_log)
02414 {
02415 error_log->Print("ERROR: Corrupt layer found. (ON_BinaryArchive::Read3dmLayer() < 0.)\n");
02416 error_count++;
02417 if ( error_count > max_error_count )
02418 return false;
02419 error_log->Print("-- Attempting to continue.\n");
02420 }
02421 pLayer = new ON_Layer;
02422 pLayer->m_layer_index = count;
02423 }
02424 ON_UserDataHolder ud;
02425 ud.MoveUserDataFrom(*pLayer);
02426 m_layer_table.Append(*pLayer);
02427 ud.MoveUserDataTo(*m_layer_table.Last(),false);
02428 delete pLayer;
02429 pLayer = NULL;
02430 }
02431
02432
02433
02434 if ( !archive.EndRead3dmLayerTable() )
02435 {
02436 if ( error_log) error_log->Print("ERROR: Corrupt render layer table. (ON_BinaryArchive::EndRead3dmLayerTable() returned false.)\n");
02437 return false;
02438 }
02439 if ( CheckForCRCErrors( archive, *this, error_log, "layer table" ) )
02440 return_code = false;
02441 }
02442 else
02443 {
02444 if ( error_log)
02445 {
02446 error_log->Print("WARNING: Missing or corrupt layer table. (ON_BinaryArchive::BeginRead3dmLayerTable() returned false.)\n");
02447 error_log->Print("-- Attempting to continue.\n");
02448 }
02449 return_code = false;
02450 }
02451
02452
02453 if ( archive.BeginRead3dmGroupTable() )
02454 {
02455 ON_Group* pGroup = NULL;
02456 for( count = 0; true; count++ )
02457 {
02458 rc = archive.Read3dmGroup(&pGroup);
02459 if ( rc==0 )
02460 break;
02461 if ( rc < 0 )
02462 {
02463 if ( error_log)
02464 {
02465 error_log->Print("ERROR: Corrupt group found. (ON_BinaryArchive::Read3dmGroup() < 0.)\n");
02466 error_count++;
02467 if ( error_count > max_error_count )
02468 return false;
02469 error_log->Print("-- Attempting to continue.\n");
02470 }
02471 pGroup = new ON_Group;
02472 pGroup->m_group_index = -1;
02473 }
02474 ON_UserDataHolder ud;
02475 ud.MoveUserDataFrom(*pGroup);
02476 m_group_table.Append(*pGroup);
02477 ud.MoveUserDataTo(*m_group_table.Last(),false);
02478 delete pGroup;
02479 pGroup = NULL;
02480 }
02481
02482
02483
02484 if ( !archive.EndRead3dmGroupTable() )
02485 {
02486 if ( error_log) error_log->Print("ERROR: Corrupt group table. (ON_BinaryArchive::EndRead3dmGroupTable() returned false.)\n");
02487 return false;
02488 }
02489 if ( CheckForCRCErrors( archive, *this, error_log, "group table" ) )
02490 return_code = false;
02491 }
02492 else
02493 {
02494 if ( error_log)
02495 {
02496 error_log->Print("WARNING: Missing or corrupt group table. (ON_BinaryArchive::BeginRead3dmGroupTable() returned false.)\n");
02497 error_log->Print("-- Attempting to continue.\n");
02498 }
02499 return_code = false;
02500 }
02501
02502
02503 if ( archive.BeginRead3dmFontTable() )
02504 {
02505 ON_Font* pFont = NULL;
02506 for( count = 0; true; count++ )
02507 {
02508 rc = archive.Read3dmFont(&pFont);
02509 if ( rc==0 )
02510 break;
02511 if ( rc < 0 )
02512 {
02513 if ( error_log)
02514 {
02515 error_log->Print("ERROR: Corrupt font found. (ON_BinaryArchive::Read3dmFont() < 0.)\n");
02516 error_count++;
02517 if ( error_count > max_error_count )
02518 return false;
02519 error_log->Print("-- Attempting to continue.\n");
02520 }
02521 pFont = new ON_Font;
02522 pFont->m_font_index = -1;
02523 }
02524 ON_UserDataHolder ud;
02525 ud.MoveUserDataFrom(*pFont);
02526 m_font_table.Append(*pFont);
02527 ud.MoveUserDataTo(*m_font_table.Last(),false);
02528 delete pFont;
02529 pFont = NULL;
02530 }
02531
02532
02533
02534 if ( !archive.EndRead3dmFontTable() )
02535 {
02536 if ( error_log) error_log->Print("ERROR: Corrupt font table. (ON_BinaryArchive::EndRead3dmFontTable() returned false.)\n");
02537 return false;
02538 }
02539 if ( CheckForCRCErrors( archive, *this, error_log, "font table" ) )
02540 return_code = false;
02541 }
02542 else
02543 {
02544 if ( error_log)
02545 {
02546 error_log->Print("WARNING: Missing or corrupt font table. (ON_BinaryArchive::BeginRead3dmFontTable() returned false.)\n");
02547 error_log->Print("-- Attempting to continue.\n");
02548 }
02549 return_code = false;
02550 }
02551
02552
02553 if ( archive.BeginRead3dmDimStyleTable() )
02554 {
02555 ON_DimStyle* pDimStyle = NULL;
02556 for( count = 0; true; count++ )
02557 {
02558 rc = archive.Read3dmDimStyle(&pDimStyle);
02559 if ( rc==0 )
02560 break;
02561 if ( rc < 0 )
02562 {
02563 if ( error_log)
02564 {
02565 error_log->Print("ERROR: Corrupt dimstyle found. (ON_BinaryArchive::Read3dmDimStyle() < 0.)\n");
02566 error_count++;
02567 if ( error_count > max_error_count )
02568 return false;
02569 error_log->Print("-- Attempting to continue.\n");
02570 }
02571 pDimStyle = new ON_DimStyle;
02572 pDimStyle->m_dimstyle_index = count;
02573 }
02574 ON_UserDataHolder ud;
02575 ud.MoveUserDataFrom(*pDimStyle);
02576 m_dimstyle_table.Append(*pDimStyle);
02577 ud.MoveUserDataTo(*m_dimstyle_table.Last(),false);
02578 delete pDimStyle;
02579 pDimStyle = NULL;
02580 }
02581
02582
02583
02584 if ( !archive.EndRead3dmDimStyleTable() )
02585 {
02586 if ( error_log) error_log->Print("ERROR: Corrupt dimstyle table. (ON_BinaryArchive::EndRead3dmDimStyleTable() returned false.)\n");
02587 return false;
02588 }
02589 if ( CheckForCRCErrors( archive, *this, error_log, "dimstyle table" ) )
02590 return_code = false;
02591 }
02592 else
02593 {
02594 if ( error_log)
02595 {
02596 error_log->Print("WARNING: Missing or corrupt dimstyle table. (ON_BinaryArchive::BeginRead3dmDimStyleTable() returned false.)\n");
02597 error_log->Print("-- Attempting to continue.\n");
02598 }
02599 return_code = false;
02600 }
02601
02602
02603 if ( archive.BeginRead3dmLightTable() )
02604 {
02605 ON_Light* pLight = NULL;
02606 ON_3dmObjectAttributes object_attributes;
02607 for( count = 0; true; count++ )
02608 {
02609 object_attributes.Default();
02610 rc = archive.Read3dmLight(&pLight,&object_attributes);
02611 if ( rc==0 )
02612 break;
02613 if ( rc < 0 )
02614 {
02615 if ( error_log)
02616 {
02617 error_log->Print("ERROR: Corrupt render light found. (ON_BinaryArchive::Read3dmLight() < 0.)\n");
02618 error_count++;
02619 if ( error_count > max_error_count )
02620 return false;
02621 error_log->Print("-- Attempting to continue.\n");
02622 }
02623 continue;
02624 }
02625 ONX_Model_RenderLight& light = m_light_table.AppendNew();
02626 ON_UserDataHolder ud;
02627 ud.MoveUserDataFrom(*pLight);
02628 light.m_light = *pLight;
02629 ud.MoveUserDataTo(light.m_light,false);
02630 light.m_attributes = object_attributes;
02631 delete pLight;
02632 pLight = NULL;
02633 }
02634
02635
02636
02637 if ( !archive.EndRead3dmLightTable() )
02638 {
02639 if ( error_log) error_log->Print("ERROR: Corrupt render light table. (ON_BinaryArchive::EndRead3dmLightTable() returned false.)\n");
02640 return false;
02641 }
02642 if ( CheckForCRCErrors( archive, *this, error_log, "render light table" ) )
02643 return_code = false;
02644 }
02645 else
02646 {
02647 if ( error_log)
02648 {
02649 error_log->Print("WARNING: Missing or corrupt render light table. (ON_BinaryArchive::BeginRead3dmLightTable() returned false.)\n");
02650 error_log->Print("-- Attempting to continue.\n");
02651 }
02652 return_code = false;
02653 }
02654
02655
02656 if ( archive.BeginRead3dmHatchPatternTable() )
02657 {
02658 ON_HatchPattern* pHatchPattern = NULL;
02659 for( count = 0; true; count++ )
02660 {
02661 rc = archive.Read3dmHatchPattern(&pHatchPattern);
02662 if ( rc==0 )
02663 break;
02664 if ( rc < 0 )
02665 {
02666 if ( error_log)
02667 {
02668 error_log->Print("ERROR: Corrupt hatchpattern found. (ON_BinaryArchive::Read3dmHatchPattern() < 0.)\n");
02669 error_count++;
02670 if ( error_count > max_error_count )
02671 return false;
02672 error_log->Print("-- Attempting to continue.\n");
02673 }
02674 pHatchPattern = new ON_HatchPattern;
02675 pHatchPattern->m_hatchpattern_index = count;
02676 }
02677 ON_UserDataHolder ud;
02678 ud.MoveUserDataFrom(*pHatchPattern);
02679 m_hatch_pattern_table.Append(*pHatchPattern);
02680 ud.MoveUserDataTo(*m_hatch_pattern_table.Last(),false);
02681 delete pHatchPattern;
02682 pHatchPattern = NULL;
02683 }
02684
02685
02686
02687 if ( !archive.EndRead3dmHatchPatternTable() )
02688 {
02689 if ( error_log) error_log->Print("ERROR: Corrupt hatchpattern table. (ON_BinaryArchive::EndRead3dmHatchPatternTable() returned false.)\n");
02690 return false;
02691 }
02692 if ( CheckForCRCErrors( archive, *this, error_log, "hatchpattern table" ) )
02693 return_code = false;
02694 }
02695 else
02696 {
02697 if ( error_log)
02698 {
02699 error_log->Print("WARNING: Missing or corrupt hatchpattern table. (ON_BinaryArchive::BeginRead3dmHatchPatternTable() returned false.)\n");
02700 error_log->Print("-- Attempting to continue.\n");
02701 }
02702 return_code = false;
02703 }
02704
02705
02706 if ( archive.BeginRead3dmInstanceDefinitionTable() )
02707 {
02708 ON_InstanceDefinition* pIDef = NULL;
02709 for( count = 0; true; count++ )
02710 {
02711 rc = archive.Read3dmInstanceDefinition(&pIDef);
02712 if ( rc==0 )
02713 break;
02714 if ( rc < 0 )
02715 {
02716 if ( error_log)
02717 {
02718 error_log->Print("ERROR: Corrupt instance definition found. (ON_BinaryArchive::Read3dmInstanceDefinition() < 0.)\n");
02719 error_count++;
02720 if ( error_count > max_error_count )
02721 return false;
02722 error_log->Print("-- Attempting to continue.\n");
02723 }
02724 continue;
02725 }
02726 ON_UserDataHolder ud;
02727 ud.MoveUserDataFrom(*pIDef);
02728 m_idef_table.Append(*pIDef);
02729 ud.MoveUserDataTo(*m_idef_table.Last(),false);
02730 delete pIDef;
02731 }
02732
02733
02734
02735 if ( !archive.EndRead3dmInstanceDefinitionTable() )
02736 {
02737 if ( error_log) error_log->Print("ERROR: Corrupt instance definition table. (ON_BinaryArchive::EndRead3dmInstanceDefinitionTable() returned false.)\n");
02738 return false;
02739 }
02740 if ( CheckForCRCErrors( archive, *this, error_log, "instance definition table" ) )
02741 return_code = false;
02742 }
02743 else
02744 {
02745 if ( error_log)
02746 {
02747 error_log->Print("WARNING: Missing or corrupt instance definition table. (ON_BinaryArchive::BeginRead3dmInstanceDefinitionTable() returned false.)\n");
02748 error_log->Print("-- Attempting to continue.\n");
02749 }
02750 return_code = false;
02751 }
02752
02753
02754
02755
02756 if ( archive.BeginRead3dmObjectTable() )
02757 {
02758
02759
02760
02761 int object_filter = 0;
02762
02763 for( count = 0; true; count++ )
02764 {
02765 ON_Object* pObject = NULL;
02766 ON_3dmObjectAttributes attributes;
02767 rc = archive.Read3dmObject(&pObject,&attributes,object_filter);
02768 if ( rc == 0 )
02769 break;
02770 if ( rc < 0 )
02771 {
02772 if ( error_log)
02773 {
02774 error_log->Print("ERROR: Object table entry %d is corrupt. (ON_BinaryArchive::Read3dmObject() < 0.)\n",count);
02775 error_count++;
02776 if ( error_count > max_error_count )
02777 return false;
02778 error_log->Print("-- Attempting to continue.\n");
02779 }
02780 continue;
02781 }
02782 if ( m_crc_error_count != archive.BadCRCCount() )
02783 {
02784 if ( error_log)
02785 {
02786 error_log->Print("ERROR: Object table entry %d is corrupt. (CRC errors).\n",count);
02787 error_log->Print("-- Attempting to continue.\n");
02788 }
02789 m_crc_error_count = archive.BadCRCCount();
02790 }
02791 if ( pObject )
02792 {
02793 ONX_Model_Object& mo = m_object_table.AppendNew();
02794 mo.m_object = pObject;
02795 mo.m_bDeleteObject = true;
02796 mo.m_attributes = attributes;
02797 }
02798 else
02799 {
02800 if ( error_log)
02801 {
02802 if ( rc == 2 )
02803 error_log->Print("WARNING: Skipping object table entry %d because it's filtered.\n",count);
02804 else if ( rc == 3 )
02805 error_log->Print("WARNING: Skipping object table entry %d because it's newer than this code. Update your OpenNURBS toolkit.\n",count);
02806 else
02807 error_log->Print("WARNING: Skipping object table entry %d for unknown reason.\n",count);
02808 }
02809 }
02810 }
02811
02812
02813
02814 if ( !archive.EndRead3dmObjectTable() )
02815 {
02816 if ( error_log) error_log->Print("ERROR: Corrupt object light table. (ON_BinaryArchive::EndRead3dmObjectTable() returned false.)\n");
02817 return false;
02818 }
02819 if ( CheckForCRCErrors( archive, *this, error_log, "object table" ) )
02820 return_code = false;
02821 }
02822 else
02823 {
02824 if ( error_log)
02825 {
02826 error_log->Print("WARNING: Missing or corrupt object table. (ON_BinaryArchive::BeginRead3dmObjectTable() returned false.)\n");
02827 error_log->Print("-- Attempting to continue.\n");
02828 }
02829 return_code = false;
02830 }
02831
02832
02833 if ( archive.BeginRead3dmHistoryRecordTable() )
02834 {
02835 for( count = 0; true; count++ )
02836 {
02837 ON_HistoryRecord* pHistoryRecord = NULL;
02838 rc = archive.Read3dmHistoryRecord(pHistoryRecord);
02839 if ( rc == 0 )
02840 break;
02841 if ( rc < 0 )
02842 {
02843 if ( error_log)
02844 {
02845 error_log->Print("ERROR: History record table entry %d is corrupt. (ON_BinaryArchive::Read3dmHistoryRecord() < 0.)\n",count);
02846 error_count++;
02847 if ( error_count > max_error_count )
02848 return false;
02849 error_log->Print("-- Attempting to continue.\n");
02850 }
02851 continue;
02852 }
02853 if ( m_crc_error_count != archive.BadCRCCount() )
02854 {
02855 if ( error_log)
02856 {
02857 error_log->Print("ERROR: History record table entry %d is corrupt. (CRC errors).\n",count);
02858 error_log->Print("-- Attempting to continue.\n");
02859 }
02860 m_crc_error_count = archive.BadCRCCount();
02861 }
02862 if ( pHistoryRecord )
02863 {
02864 m_history_record_table.Append(pHistoryRecord);
02865 }
02866 else
02867 {
02868 if ( error_log)
02869 {
02870 error_log->Print("WARNING: Skipping history record table entry %d for unknown reason.\n",count);
02871 }
02872 }
02873 }
02874
02875
02876
02877 if ( !archive.EndRead3dmHistoryRecordTable() )
02878 {
02879 if ( error_log) error_log->Print("ERROR: Corrupt object light table. (ON_BinaryArchive::EndRead3dmObjectTable() returned false.)\n");
02880 return false;
02881 }
02882 if ( CheckForCRCErrors( archive, *this, error_log, "history record table" ) )
02883 return_code = false;
02884 }
02885 else
02886 {
02887 if ( error_log)
02888 {
02889 error_log->Print("WARNING: Missing or corrupt history record table. (ON_BinaryArchive::BeginRead3dmHistoryRecordTable() returned false.)\n");
02890 error_log->Print("-- Attempting to continue.\n");
02891 }
02892 return_code = false;
02893 }
02894
02895
02896
02897
02898 for(count=0;true;count++)
02899 {
02900 if ( archive.Archive3dmVersion() <= 1 )
02901 {
02902
02903 break;
02904 }
02905
02906 {
02907 ON__UINT32 tcode = 0;
02908 ON__INT64 big_value = 0;
02909 if ( !archive.PeekAt3dmBigChunkType(&tcode,&big_value) )
02910 break;
02911 if ( TCODE_USER_TABLE != tcode )
02912 break;
02913 }
02914 ON_UUID plugin_id = ON_nil_uuid;
02915 bool bGoo = false;
02916 int usertable_3dm_version = 0;
02917 int usertable_opennurbs_version = 0;
02918 if ( !archive.BeginRead3dmUserTable( plugin_id, &bGoo, &usertable_3dm_version, &usertable_opennurbs_version ) )
02919 {
02920
02921 const ON__UINT64 pos0 = archive.CurrentPosition();
02922 ON__UINT32 tcode = 0;
02923 ON__INT64 big_value = 0;
02924 if ( !archive.BeginRead3dmBigChunk(&tcode,&big_value) )
02925 break;
02926 if ( !archive.EndRead3dmChunk() )
02927 break;
02928 const ON__UINT64 pos1 = archive.CurrentPosition();
02929 if (pos1 <= pos0)
02930 break;
02931 if ( TCODE_USER_TABLE != tcode )
02932 break;
02933
02934 continue;
02935 }
02936
02937 ONX_Model_UserData& ud = m_userdata_table.AppendNew();
02938 ud.m_uuid = plugin_id;
02939 ud.m_usertable_3dm_version = usertable_3dm_version;
02940 ud.m_usertable_opennurbs_version = usertable_opennurbs_version;
02941
02942 if ( !archive.Read3dmAnonymousUserTable( usertable_3dm_version, usertable_opennurbs_version, ud.m_goo ) )
02943 {
02944 if ( error_log) error_log->Print("ERROR: User data table entry %d is corrupt. (ON_BinaryArchive::Read3dmAnonymousUserTable() is false.)\n",count);
02945 break;
02946 }
02947
02948
02949
02950 if ( !archive.EndRead3dmUserTable() )
02951 {
02952 if ( error_log) error_log->Print("ERROR: Corrupt user data table. (ON_BinaryArchive::EndRead3dmUserTable() returned false.)\n");
02953 break;
02954 }
02955 }
02956
02957
02958 if ( !archive.Read3dmEndMark(&m_file_length) )
02959 {
02960 if ( archive.Archive3dmVersion() != 1 )
02961 {
02962
02963 if ( error_log) error_log->Print("ERROR: ON_BinaryArchive::Read3dmEndMark(&m_file_length) returned false.\n");
02964 }
02965 }
02966
02967
02968
02969
02970
02971
02972
02973
02974 const ON_3dmRevisionHistory saved_revision_history(m_properties.m_RevisionHistory);
02975 Polish();
02976 m_properties.m_RevisionHistory = saved_revision_history;
02977
02978 return return_code;
02979 }
02980
02981 static
02982 void ONX_Model_WriteHelper(ON_BinaryFile& file)
02983 {
02984 file.EnableSave3dmRenderMeshes(true);
02985 file.EnableSave3dmAnalysisMeshes(true);
02986 file.EnableSaveUserData(true);
02987 }
02988
02989 bool ONX_Model::Write(
02990 const char* filename,
02991 int version,
02992 const char* sStartSectionComment,
02993 ON_TextLog* error_log
02994 )
02995 {
02996 bool rc = false;
02997 if ( 0 != filename )
02998 {
02999 FILE* fp = ON::OpenFile( filename, "wb" );
03000 if ( 0 != fp )
03001 {
03002 ON_BinaryFile file( ON::write3dm, fp );
03003 ONX_Model_WriteHelper(file);
03004 rc = Write( file, version, sStartSectionComment, error_log );
03005 ON::CloseFile(fp);
03006 }
03007 }
03008 return rc;
03009 }
03010
03011 bool ONX_Model::Write(
03012 const wchar_t* filename,
03013 int version,
03014 const char* sStartSectionComment,
03015 ON_TextLog* error_log
03016 )
03017 {
03018 bool rc = false;
03019 if ( 0 != filename )
03020 {
03021 FILE* fp = ON::OpenFile( filename, L"wb" );
03022 if ( 0 != fp )
03023 {
03024 ON_BinaryFile file( ON::write3dm, fp );
03025 ONX_Model_WriteHelper(file);
03026 rc = Write( file, version, sStartSectionComment, error_log );
03027 ON::CloseFile(fp);
03028 }
03029 }
03030 return rc;
03031 }
03032
03033
03034 bool ONX_Model::Write(
03035 ON_BinaryArchive& archive,
03036 int version,
03037 const char* sStartSectionComment,
03038 ON_TextLog* error_log
03039 )
03040 {
03041 int i;
03042
03043 if ( !IsValid(error_log) )
03044 {
03045
03046 if ( error_log) error_log->Print("ONX_Model::Write Your model is not valid and will not be saved.\n");
03047 return false;
03048 }
03049
03050 if ( 0 != version )
03051 {
03052 if ( version < 2
03053 || version > ON_BinaryArchive::CurrentArchiveVersion()
03054 || (version >= 50 && 0 != (version%10))
03055 || (version < 50 && version > ON_BinaryArchive::CurrentArchiveVersion()/10)
03056 )
03057 {
03058
03059 version = 0;
03060 if ( error_log) error_log->Print("ONX_Model::Write version parameter = %d; it must be 0, or >= 2 and <= %d, or a multiple of 10 >= 50 and <= %d.\n",
03061 version,ON_BinaryArchive::CurrentArchiveVersion()/10,ON_BinaryArchive::CurrentArchiveVersion());
03062 }
03063 }
03064
03065 if ( !archive.WriteMode() )
03066 {
03067
03068
03069 if ( error_log) error_log->Print("ONX_Model::Write archive.Mode() is not ON::write3dm.\n"
03070 "See ONX_Model::Write example in the header file.\n");
03071 return false;
03072 }
03073
03074 bool ok;
03075
03076
03077 ok = archive.Write3dmStartSection( version, m_sStartSectionComments );
03078 if ( !ok )
03079 {
03080
03081 if ( error_log) error_log->Print("ONX_Model::Write archive.Write3dmStartSection() failed.\n"
03082 "Your archive is not properly initialized\n"
03083 "(make sure you passed ON::write3dm to the constructor),\n"
03084 "a file is locked, a disk is locked, or something along those lines.\n");
03085 return false;
03086 }
03087
03088
03089 ok = archive.Write3dmProperties( m_properties );
03090 if ( !ok )
03091 {
03092
03093 if ( error_log) error_log->Print("ONX_Model::Write archive.Write3dmProperties() failed.\n"
03094 "Your m_properties information is not valid or basic file writing failed.\n"
03095 );
03096 return false;
03097 }
03098
03099
03100 ok = archive.Write3dmSettings( m_settings );
03101 if ( !ok )
03102 {
03103
03104 if ( error_log) error_log->Print("ONX_Model::Write archive.Write3dmSettings() failed.\n"
03105 "Your m_settings information is not valid or basic file writing failed.\n");
03106 return false;
03107 }
03108
03109
03110 ok = archive.BeginWrite3dmBitmapTable();
03111 if ( !ok )
03112 {
03113 if ( error_log) error_log->Print("ONX_Model::Write archive.BeginWrite3dmBitmapTable() failed.\n");
03114 return false;
03115 }
03116 for( i = 0; ok && i < m_bitmap_table.Count(); i++ )
03117 {
03118 ok = archive.Write3dmBitmap(*m_bitmap_table[i]);
03119 if ( !ok )
03120 {
03121 if ( error_log) error_log->Print("ONX_Model::Write archive.Write3dmBitmap(m_bitmap_table[%d]) failed.\n",i);
03122 }
03123 }
03124 if ( !archive.EndWrite3dmBitmapTable() )
03125 {
03126 if ( error_log) error_log->Print("ONX_Model::Write archive.EndWrite3dmBitmapTable() failed.\n");
03127 return false;
03128 }
03129 if (!ok)
03130 return false;
03131
03132
03133 if ( archive.Archive3dmVersion() >= 4 )
03134 {
03135 ok = archive.BeginWrite3dmTextureMappingTable();
03136 if ( !ok )
03137 {
03138 if ( error_log) error_log->Print("ONX_Model::Write archive.BeginWrite3dmTextureMappingTable() failed.\n");
03139 return false;
03140 }
03141 for( i = 0; ok && i < m_mapping_table.Count(); i++ )
03142 {
03143 ok = archive.Write3dmTextureMapping(m_mapping_table[i]);
03144 if ( !ok )
03145 {
03146 if ( error_log) error_log->Print("ONX_Model::Write archive.Write3dmTextureMapping(m_mapping_table[%d]) failed.\n",i);
03147 }
03148 }
03149 if ( !archive.EndWrite3dmTextureMappingTable() )
03150 {
03151 if ( error_log) error_log->Print("ONX_Model::Write archive.EndWrite3dmTextureMappingTable() failed.\n");
03152 return false;
03153 }
03154 if (!ok)
03155 return false;
03156 }
03157
03158
03159 ok = archive.BeginWrite3dmMaterialTable();
03160 if ( !ok )
03161 {
03162 if ( error_log) error_log->Print("ONX_Model::Write archive.BeginWrite3dmMaterialTable() failed.\n");
03163 return false;
03164 }
03165 for( i = 0; ok && i < m_material_table.Count(); i++ )
03166 {
03167 ok = archive.Write3dmMaterial(m_material_table[i]);
03168 if ( !ok )
03169 {
03170 if ( error_log) error_log->Print("ONX_Model::Write archive.Write3dmMaterial(m_material_table[%d]) failed.\n",i);
03171 }
03172 }
03173 if ( !archive.EndWrite3dmMaterialTable() )
03174 {
03175 if ( error_log) error_log->Print("ONX_Model::Write archive.EndWrite3dmMaterialTable() failed.\n");
03176 return false;
03177 }
03178 if (!ok)
03179 return false;
03180
03181
03182
03183 if ( archive.Archive3dmVersion() >= 4 )
03184 {
03185 ok = archive.BeginWrite3dmLinetypeTable();
03186 if ( !ok )
03187 {
03188 if ( error_log) error_log->Print("ONX_Model::Write archive.BeginWrite3dmLinetypeTable() failed.\n");
03189 return false;
03190 }
03191 for( i = 0; ok && i < m_linetype_table.Count(); i++ )
03192 {
03193 ok = archive.Write3dmLinetype(m_linetype_table[i]);
03194 if ( !ok )
03195 {
03196 if ( error_log) error_log->Print("ONX_Model::Write archive.Write3dmLinetype(m_linetype_table[%d]) failed.\n",i);
03197 }
03198 }
03199 if ( !archive.EndWrite3dmLinetypeTable() )
03200 {
03201 if ( error_log) error_log->Print("ONX_Model::Write archive.EndWrite3dmLinetypeTable() failed.\n");
03202 return false;
03203 }
03204 if (!ok)
03205 return false;
03206 }
03207
03208
03209 ok = archive.BeginWrite3dmLayerTable();
03210 if ( !ok )
03211 {
03212
03213 if ( error_log) error_log->Print("ONX_Model::Write archive.BeginWrite3dmLayerTable() failed.\n");
03214 return false;
03215 }
03216 for( i = 0; ok && i < m_layer_table.Count(); i++ )
03217 {
03218 ok = archive.Write3dmLayer(m_layer_table[i]);
03219 if ( !ok )
03220 {
03221 if ( error_log) error_log->Print("ONX_Model::Write archive.Write3dmLayer(m_layer_table[%d]) failed.\n",i);
03222 }
03223 }
03224 if ( !archive.EndWrite3dmLayerTable() )
03225 {
03226 if ( error_log) error_log->Print("ONX_Model::Write archive.EndWrite3dmLayerTable() failed.\n");
03227 return false;
03228 }
03229 if (!ok)
03230 return false;
03231
03232
03233 ok = archive.BeginWrite3dmGroupTable();
03234 if ( !ok )
03235 {
03236
03237 if ( error_log) error_log->Print("ONX_Model::Write archive.BeginWrite3dmGroupTable() failed.\n");
03238 return false;
03239 }
03240 for( i = 0; ok && i < m_group_table.Count(); i++ )
03241 {
03242 ok = archive.Write3dmGroup(m_group_table[i]);
03243 if ( !ok )
03244 {
03245 if ( error_log) error_log->Print("ONX_Model::Write archive.Write3dmGroup(m_group_table[%d]) failed.\n",i);
03246 }
03247 }
03248 if ( !archive.EndWrite3dmGroupTable() )
03249 {
03250 if ( error_log) error_log->Print("ONX_Model::Write archive.EndWrite3dmGroupTable() failed.\n");
03251 return false;
03252 }
03253 if (!ok)
03254 return false;
03255
03256
03257
03258 if ( archive.Archive3dmVersion() >= 3 )
03259 {
03260 ok = archive.BeginWrite3dmFontTable();
03261 if ( !ok )
03262 {
03263
03264 if ( error_log) error_log->Print("ONX_Model::Write archive.BeginWrite3dmFontTable() failed.\n");
03265 return false;
03266 }
03267 for( i = 0; ok && i < m_font_table.Count(); i++ )
03268 {
03269 ok = archive.Write3dmFont(m_font_table[i]);
03270 if ( !ok )
03271 {
03272 if ( error_log) error_log->Print("ONX_Model::Write archive.Write3dmFont(m_font_table[%d]) failed.\n",i);
03273 }
03274 }
03275 if ( !archive.EndWrite3dmFontTable() )
03276 {
03277 if ( error_log) error_log->Print("ONX_Model::Write archive.EndWrite3dmFontTable() failed.\n");
03278 return false;
03279 }
03280 if (!ok)
03281 return false;
03282 }
03283
03284
03285
03286 if ( archive.Archive3dmVersion() >= 3 )
03287 {
03288 ok = archive.BeginWrite3dmDimStyleTable();
03289 if ( !ok )
03290 {
03291
03292 if ( error_log) error_log->Print("ONX_Model::Write archive.BeginWrite3dmDimStyleTable() failed.\n");
03293 return false;
03294 }
03295 for( i = 0; ok && i < m_dimstyle_table.Count(); i++ )
03296 {
03297 ok = archive.Write3dmDimStyle(m_dimstyle_table[i]);
03298 if ( !ok )
03299 {
03300 if ( error_log) error_log->Print("ONX_Model::Write archive.Write3dmDimStyle(m_dimstyle_table[%d]) failed.\n",i);
03301 }
03302 }
03303 if ( !archive.EndWrite3dmDimStyleTable() )
03304 {
03305 if ( error_log) error_log->Print("ONX_Model::Write archive.EndWrite3dmDimStyleTable() failed.\n");
03306 return false;
03307 }
03308 if (!ok)
03309 return false;
03310 }
03311
03312
03313
03314 ok = archive.BeginWrite3dmLightTable();
03315 if ( !ok )
03316 {
03317
03318 if ( error_log) error_log->Print("ONX_Model::Write archive.BeginWrite3dmLightTable() failed.\n");
03319 return false;
03320 }
03321 for( i = 0; ok && i < m_light_table.Count(); i++ )
03322 {
03323 ok = archive.Write3dmLight(m_light_table[i].m_light,&m_light_table[i].m_attributes);
03324 if ( !ok )
03325 {
03326 if ( error_log) error_log->Print("ONX_Model::Write archive.Write3dmLight(m_light_table[%d]) failed.\n",i);
03327 }
03328 }
03329 if ( !archive.EndWrite3dmLightTable() )
03330 {
03331 if ( error_log) error_log->Print("ONX_Model::Write archive.EndWrite3dmLightTable() failed.\n");
03332 return false;
03333 }
03334 if (!ok)
03335 return false;
03336
03337
03338
03339 if ( archive.Archive3dmVersion() >= 4 )
03340 {
03341 ok = archive.BeginWrite3dmHatchPatternTable();
03342 if ( !ok )
03343 {
03344 if ( error_log) error_log->Print("ONX_Model::Write archive.BeginWrite3dmHatchPatternTable() failed.\n");
03345 return false;
03346 }
03347 for( i = 0; ok && i < m_hatch_pattern_table.Count(); i++ )
03348 {
03349 ok = archive.Write3dmHatchPattern(m_hatch_pattern_table[i]);
03350 if ( !ok )
03351 {
03352 if ( error_log) error_log->Print("ONX_Model::Write archive.Write3dmHatchPattern(m_hatch_pattern_table[%d]) failed.\n",i);
03353 }
03354 }
03355 if ( !archive.EndWrite3dmHatchPatternTable() )
03356 {
03357 if ( error_log) error_log->Print("ONX_Model::Write archive.EndWrite3dmHatchPatternTable() failed.\n");
03358 return false;
03359 }
03360 if (!ok)
03361 return false;
03362 }
03363
03364
03365
03366 if ( archive.Archive3dmVersion() >= 3 )
03367 {
03368 ok = archive.BeginWrite3dmInstanceDefinitionTable();
03369 if ( !ok )
03370 {
03371
03372 if ( error_log) error_log->Print("ONX_Model::Write archive.BeginWrite3dmInstanceDefinitionTable() failed.\n");
03373 return false;
03374 }
03375 for( i = 0; ok && i < m_idef_table.Count(); i++ )
03376 {
03377 ok = archive.Write3dmInstanceDefinition(m_idef_table[i]);
03378 if ( !ok )
03379 {
03380 if ( error_log) error_log->Print("ONX_Model::Write archive.Write3dmInstanceDefinition(m_IDef_table[%d]) failed.\n",i);
03381 }
03382 }
03383 if ( !archive.EndWrite3dmInstanceDefinitionTable() )
03384 {
03385 if ( error_log) error_log->Print("ONX_Model::Write archive.EndWrite3dmInstanceDefinitionTable() failed.\n");
03386 return false;
03387 }
03388 if (!ok)
03389 return false;
03390 }
03391
03392
03393
03394 ok = archive.BeginWrite3dmObjectTable();
03395 if ( !ok )
03396 {
03397 if ( error_log) error_log->Print("ONX_Model::Write archive.BeginWrite3dmObjectTable() failed.\n");
03398 return false;
03399 }
03400 for( i = 0; ok && i < m_object_table.Count(); i++ )
03401 {
03402 if ( 0 != m_object_table[i].m_object )
03403 {
03404 ok = archive.Write3dmObject(*m_object_table[i].m_object,&m_object_table[i].m_attributes);
03405 if ( !ok )
03406 {
03407 if ( error_log) error_log->Print("ONX_Model::Write archive.Write3dmObject(m_IDef_table[%d]) failed.\n",i);
03408 }
03409 }
03410 }
03411 if ( !archive.EndWrite3dmObjectTable() )
03412 {
03413 if ( error_log) error_log->Print("ONX_Model::Write archive.EndWrite3dmObjectTable() failed.\n");
03414 return false;
03415 }
03416 if (!ok)
03417 return false;
03418
03419
03420
03421 if ( archive.Archive3dmVersion() >= 4 )
03422 {
03423 ok = archive.BeginWrite3dmHistoryRecordTable();
03424 if ( !ok )
03425 {
03426 if ( error_log) error_log->Print("ONX_Model::Write archive.BeginWrite3dmHistoryRecordTable() failed.\n");
03427 return false;
03428 }
03429 for ( i = 0; ok && i < m_history_record_table.Count(); i++ )
03430 {
03431 const ON_HistoryRecord* history_record = m_history_record_table[i];
03432 if( history_record)
03433 ok = archive.Write3dmHistoryRecord( *history_record );
03434 }
03435 if( !archive.EndWrite3dmHistoryRecordTable() )
03436 {
03437 if ( error_log) error_log->Print("ONX_Model::Write archive.EndWrite3dmHistoryTable() failed.\n");
03438 return false;
03439 }
03440 if (!ok)
03441 return false;
03442 }
03443
03444
03445 for( i = 0; ok && i < m_userdata_table.Count(); i++ )
03446 {
03447 const ONX_Model_UserData& ud = m_userdata_table[i];
03448 if ( ON_UuidIsNotNil(ud.m_uuid) )
03449 {
03450 if ( !archive.Write3dmAnonymousUserTableRecord(
03451 ud.m_uuid,
03452 ud.m_usertable_3dm_version,
03453 ud.m_usertable_opennurbs_version,ud.m_goo
03454 ) )
03455 {
03456 continue;
03457 }
03458 }
03459 }
03460
03461 if ( !archive.Write3dmEndMark() )
03462 {
03463 ok = false;
03464 if ( error_log) error_log->Print("ONX_Model::Write archive.Write3dmEndMark() failed.\n");
03465 }
03466
03467 return ok;
03468 }
03469
03470 bool ONX_Model::IsValid( ON_TextLog* text_log ) const
03471 {
03472
03473
03474 int i = const_cast<ONX_Model*>(this)->Audit(false,NULL,text_log,NULL);
03475 return (i>=0);
03476 }
03477
03478 int ONX_Model::ObjectIndex( ON_UUID object_uuid ) const
03479 {
03480
03481
03482
03483 int object_index = -1;
03484 if ( ON_UuidIsNotNil(object_uuid) )
03485 {
03486 int i, object_count = m_object_table.Count();
03487 if ( object_count > 0 )
03488 {
03489 if ( object_count != m_object_id_index.Count() )
03490 {
03491
03492 ON_UuidIndexList* p = const_cast< ON_UuidIndexList* >(&m_object_id_index);
03493 p->Empty();
03494 p->Reserve(object_count);
03495 for ( i = 0; i < object_count; i++ )
03496 {
03497 ON_UUID id = m_object_table[i].m_attributes.m_uuid;
03498 if ( ON_UuidIsNil(id) )
03499 {
03500 ON_ERROR("Nil object ids in model");
03501 ON_CreateUuid(id);
03502 *(const_cast<ON_UUID*>(&m_object_table[i].m_attributes.m_uuid)) = id;
03503 }
03504 if ( !p->AddUuidIndex(id,i,true) )
03505 {
03506 ON_ERROR("Duplicate object ids in model");
03507 ON_CreateUuid(id);
03508 *(const_cast<ON_UUID*>(&m_object_table[i].m_attributes.m_uuid)) = id;
03509 p->AddUuidIndex(id,i,false);
03510 }
03511 }
03512 }
03513
03514 if ( !m_object_id_index.FindUuid(object_uuid,&object_index) )
03515 object_index = -1;
03516 }
03517 }
03518
03519 return object_index;
03520 }
03521
03522 int ONX_Model::IDefIndex( ON_UUID idef_uuid ) const
03523 {
03524
03525
03526
03527 int idef_index = -1;
03528 if ( ON_UuidIsNotNil(idef_uuid) )
03529 {
03530 int i, idef_count = m_idef_table.Count();
03531 if ( idef_count > 0 )
03532 {
03533 if ( idef_count != m_idef_id_index.Count() )
03534 {
03535
03536 ON_UuidIndexList* p = const_cast<ON_UuidIndexList*>(&m_idef_id_index);
03537 p->Empty();
03538 p->Reserve(idef_count);
03539 for ( i = 0; i < idef_count; i++ )
03540 {
03541 ON_UUID id = m_idef_table[i].m_uuid;
03542 if ( ON_UuidIsNil(id) )
03543 {
03544 ON_ERROR("Nil idef ids in model");
03545 ON_CreateUuid(id);
03546 (const_cast<ON_InstanceDefinition*>(&m_idef_table[i]))->m_uuid = id;
03547 }
03548 if ( !p->AddUuidIndex(id,i,true) )
03549 {
03550 ON_ERROR("Duplicate idef ids in model");
03551 ON_CreateUuid(id);
03552 (const_cast<ON_InstanceDefinition*>(&m_idef_table[i]))->m_uuid = id;
03553 p->AddUuidIndex(id,i,false);
03554 }
03555 }
03556 }
03557
03558 if ( !m_idef_id_index.FindUuid(idef_uuid,&idef_index) )
03559 idef_index = -1;
03560 }
03561 }
03562
03563 return idef_index;
03564 }
03565
03566 int ONX_Model::IDefIndex( const wchar_t* idef_name ) const
03567 {
03568
03569
03570
03571
03572 int idef_index = -1;
03573 if ( 0 != idef_name && 0 != idef_name[0] )
03574 {
03575 int i, idef_count = m_idef_table.Count();
03576 for ( i = 0; i < idef_count; i++ )
03577 {
03578 if ( 0 == on_wcsicmp(idef_name, m_idef_table[i].Name() ) )
03579 {
03580 idef_index = i;
03581 break;
03582 }
03583 }
03584 }
03585 return idef_index;
03586 }
03587
03588 void ONX_Model::GetUnusedIDefName( ON_wString& idef_name ) const
03589 {
03590 int i = 1;
03591 for(i = 1; i < 100000; i++ )
03592 {
03593 idef_name.Format("IDef_%02d",i);
03594 if ( IDefIndex(idef_name) < 0 )
03595 return;
03596 }
03597 idef_name = "IDef";
03598 return;
03599 }
03600
03601 int ONX_Model::UsesIDef(
03602 const ON_InstanceRef& iref,
03603 ON_UUID idef_uuid
03604 ) const
03605 {
03606
03607 if ( ON_UuidIsNil(idef_uuid) )
03608 return 0;
03609
03610
03611 ON_UUID iref_idef_uuid = iref.m_instance_definition_uuid;
03612 if ( 0 == ON_UuidCompare( idef_uuid, iref_idef_uuid ) )
03613 return 1;
03614
03615 const int iref_idef_index = IDefIndex(iref_idef_uuid);
03616 if ( -1 == iref_idef_index )
03617 return -1;
03618 const ON_InstanceDefinition& iref_idef = m_idef_table[iref_idef_index];
03619
03620
03621 int i0 = 0;
03622 int i1 = 0;
03623 int i, j, k, depth, obj_index;
03624 const ON_InstanceRef* pNestedIRef;
03625
03626
03627 ON_SimpleArray<const ON_InstanceRef*> iref_list(256);
03628 for ( j = 0; j < iref_idef.m_object_uuid.Count(); j++ )
03629 {
03630 obj_index = ObjectIndex(iref_idef.m_object_uuid[j]);
03631 if ( obj_index < 0 )
03632 continue;
03633 const ONX_Model_Object& obj = m_object_table[obj_index];
03634 if ( 0 == obj.m_object )
03635 continue;
03636 if ( obj.m_object->ObjectType() == ON::instance_reference )
03637 {
03638 pNestedIRef = ON_InstanceRef::Cast(obj.m_object);
03639 if ( 0 != pNestedIRef )
03640 {
03641 if ( 0 == ON_UuidCompare( idef_uuid, pNestedIRef->m_instance_definition_uuid ) )
03642 return 2;
03643 iref_list.Append(pNestedIRef);
03644 }
03645 }
03646 }
03647
03648
03649 const int max_depth = 1000;
03650 for ( depth=3; depth < max_depth && i1 < iref_list.Count(); depth++ )
03651 {
03652 i0 = i1;
03653 i1 = iref_list.Count();
03654 for ( i = i0; i < i1; i++ )
03655 {
03656 pNestedIRef = iref_list[i];
03657 if ( 0 == pNestedIRef )
03658 continue;
03659 k = IDefIndex( pNestedIRef->m_instance_definition_uuid );
03660 if ( k < 0 )
03661 continue;
03662 const ON_InstanceDefinition& nested_idef = m_idef_table[k];
03663 for ( j = 0; j < nested_idef.m_object_uuid.Count(); j++ )
03664 {
03665 obj_index = ObjectIndex(nested_idef.m_object_uuid[j]);
03666 if ( obj_index < 0 )
03667 continue;
03668 const ONX_Model_Object& obj = m_object_table[obj_index];
03669 if ( 0 == obj.m_object )
03670 continue;
03671 if ( obj.m_object->ObjectType() == ON::instance_reference )
03672 {
03673 pNestedIRef = ON_InstanceRef::Cast(obj.m_object);
03674 if ( 0 != pNestedIRef )
03675 {
03676 if ( 0 == ON_UuidCompare( idef_uuid, pNestedIRef->m_instance_definition_uuid ) )
03677 return depth;
03678 iref_list.Append(pNestedIRef);
03679 }
03680 }
03681 }
03682 }
03683 }
03684
03685 return (depth < max_depth) ? 0 : -2;
03686 }
03687
03688 int ONX_Model::LayerIndex( const wchar_t* layer_name ) const
03689 {
03690
03691
03692
03693
03694 int layer_index = -1;
03695 if ( 0 != layer_name && 0 != layer_name[0] )
03696 {
03697 int i, layer_count = m_layer_table.Count();
03698 for ( i = 0; i < layer_count; i++ )
03699 {
03700 if ( 0 == on_wcsicmp(layer_name, m_layer_table[i].LayerName() ) )
03701 {
03702 layer_index = i;
03703 break;
03704 }
03705 }
03706 }
03707 return layer_index;
03708 }
03709
03710
03711 void ONX_Model::GetUnusedLayerName( ON_wString& layer_name ) const
03712 {
03713 int i = 1;
03714 for(i = 1; i < 100000; i++ )
03715 {
03716 layer_name.Format("Layer_%02d",i);
03717 if ( LayerIndex(layer_name) < 0 )
03718 return;
03719 }
03720 layer_name = "Layer";
03721 return;
03722 }
03723
03724
03725
03726 bool ONX_Model::SetDocumentUserString( const wchar_t* key, const wchar_t* string_value )
03727 {
03728
03729
03730
03731
03732 bool rc = false;
03733 if ( 0 != key && 0 != key[0] )
03734 {
03735 ON_UUID doc_userstring_id = ON_DocumentUserStringList::m_ON_DocumentUserStringList_class_id.Uuid();
03736 for (int i = 0; i < m_userdata_table.Count(); i++ )
03737 {
03738 ONX_Model_UserData& ud = m_userdata_table[i];
03739 if ( ud.m_uuid == doc_userstring_id )
03740 {
03741 if ( TCODE_USER_RECORD == ud.m_goo.m_typecode && ud.m_goo.m_value != 0 )
03742 {
03743 ON_Read3dmBufferArchive ba(
03744 (unsigned int)ud.m_goo.m_value,
03745 ud.m_goo.m_goo,
03746 false,
03747 m_3dm_file_version,
03748 m_3dm_opennurbs_version
03749 );
03750 ON_Object* p = 0;
03751 if ( ba.ReadObject(&p) )
03752 {
03753 ON_DocumentUserStringList* sl = ON_DocumentUserStringList::Cast(p);
03754 if ( 0 != sl )
03755 {
03756
03757 rc = sl->SetUserString(key,string_value);
03758 if ( rc )
03759 {
03760
03761 ON_Write3dmBufferArchive newgoo(ud.m_goo.m_value+1024,0,m_3dm_file_version,ON::Version());
03762 if ( newgoo.BeginWrite3dmUserTable(doc_userstring_id,false,0,0)
03763 && newgoo.WriteObject(sl)
03764 && newgoo.EndWrite3dmUserTable()
03765 )
03766 {
03767 if ( newgoo.SizeOfArchive() > 0
03768 && newgoo.SizeOfArchive() <= 0xFFFFFFFF
03769 )
03770 {
03771
03772 unsigned char* goo = (unsigned char*)newgoo.HarvestBuffer();
03773 unsigned int value = (unsigned int)newgoo.SizeOfArchive();
03774 if ( 0 != goo && value > 0 )
03775 {
03776 onfree(ud.m_goo.m_goo);
03777 ud.m_goo.m_value = (int)value;
03778 ud.m_goo.m_goo = goo;
03779 }
03780 }
03781 }
03782 }
03783 }
03784 }
03785 if ( 0 != p )
03786 {
03787 delete p;
03788 p = 0;
03789 }
03790 }
03791 break;
03792 }
03793 }
03794 }
03795 return rc;
03796 }
03797
03798
03799 bool ONX_Model::GetDocumentUserString( const wchar_t* key, ON_wString& string_value ) const
03800 {
03801 const wchar_t* s = 0;
03802 if ( 0 != key && 0 != key[0] )
03803 {
03804
03805
03806
03807
03808 ON_ClassArray<ON_UserString> user_strings;
03809 GetDocumentUserStrings( user_strings );
03810 for ( int i = 0; i < user_strings.Count(); i++ )
03811 {
03812 if ( !user_strings[i].m_key.CompareNoCase(key) )
03813 {
03814 s = user_strings[i].m_string_value;
03815 break;
03816 }
03817 }
03818 }
03819 string_value = s;
03820 return (0 != s);
03821 }
03822
03823
03824 int ONX_Model::GetDocumentUserStrings( ON_ClassArray<ON_UserString>& user_strings ) const
03825 {
03826 int rc = 0;
03827
03828
03829
03830 ON_UUID doc_userstring_id = ON_DocumentUserStringList::m_ON_DocumentUserStringList_class_id.Uuid();
03831 for (int i = 0; i < m_userdata_table.Count(); i++ )
03832 {
03833 const ONX_Model_UserData& ud = m_userdata_table[i];
03834 if ( ud.m_uuid == doc_userstring_id )
03835 {
03836 if ( TCODE_USER_RECORD == ud.m_goo.m_typecode && ud.m_goo.m_value != 0 )
03837 {
03838 ON_Read3dmBufferArchive ba(
03839 (unsigned int)ud.m_goo.m_value,
03840 ud.m_goo.m_goo,
03841 false,
03842 m_3dm_file_version,
03843 m_3dm_opennurbs_version
03844 );
03845
03846 ON_Object* p = 0;
03847 if ( ba.ReadObject(&p) )
03848 {
03849 const ON_DocumentUserStringList* sl = ON_DocumentUserStringList::Cast(p);
03850 if ( 0 != sl )
03851 {
03852 rc = sl->GetUserStrings(user_strings);
03853 }
03854 }
03855 if ( 0 != p )
03856 {
03857 delete p;
03858 p = 0;
03859 }
03860 }
03861 break;
03862 }
03863 }
03864 return rc;
03865 }
03866
03867
03868 static int AuditTextureMappingTableHelper(
03869 ONX_Model& model,
03870 bool bAttemptRepair,
03871 int* repair_count,
03872 ON_TextLog* text_log
03873 )
03874 {
03875 if ( repair_count )
03876 *repair_count = 0;
03877 int i, count = model.m_mapping_table.Count();
03878 for ( i = 0; i < count; i++ )
03879 {
03880 ON_TextureMapping& mapping = model.m_mapping_table[i];
03881 if ( mapping.m_mapping_index != i )
03882 {
03883 if ( text_log )
03884 {
03885 text_log->Print("m_mapping_table[%d].m_mapping_index == %d (should be %d)\n",
03886 i,mapping.m_mapping_index,i);
03887 }
03888 if ( bAttemptRepair )
03889 {
03890 mapping.m_mapping_index = i;
03891 if ( text_log )
03892 {
03893 text_log->PushIndent();
03894 text_log->Print("Repaired.\n");
03895 text_log->PopIndent();
03896 }
03897 if ( repair_count )
03898 *repair_count += 1;
03899 }
03900 else
03901 {
03902 return -1;
03903 }
03904 }
03905 if ( !mapping.IsValid(text_log) )
03906 return 1;
03907 }
03908 return 0;
03909 }
03910
03911
03912 static int AuditGroupTableHelper(
03913 ONX_Model& model,
03914 bool bAttemptRepair,
03915 int* repair_count,
03916 ON_TextLog* text_log
03917 )
03918 {
03919 if ( repair_count )
03920 *repair_count = 0;
03921 int i, count = model.m_group_table.Count();
03922 for ( i = 0; i < count; i++ )
03923 {
03924 ON_Group& group = model.m_group_table[i];
03925 if ( group.m_group_index != i )
03926 {
03927 if ( text_log )
03928 {
03929 text_log->Print("m_group_table[%d].m_group_index == %d (should be %d)\n",
03930 i,group.m_group_index,i);
03931 }
03932 if ( bAttemptRepair )
03933 {
03934 group.m_group_index = i;
03935 if ( text_log )
03936 {
03937 text_log->PushIndent();
03938 text_log->Print("Repaired.\n");
03939 text_log->PopIndent();
03940 }
03941 if ( repair_count )
03942 *repair_count += 1;
03943 }
03944 else
03945 {
03946 return -1;
03947 }
03948 }
03949 if ( !group.IsValid(text_log) )
03950 return 1;
03951 }
03952 return 0;
03953 }
03954
03955
03956 static int AuditFontTableHelper(
03957 ONX_Model& model,
03958 bool bAttemptRepair,
03959 int* repair_count,
03960 ON_TextLog* text_log
03961 )
03962 {
03963 if ( repair_count )
03964 *repair_count = 0;
03965 int i, count = model.m_font_table.Count();
03966 for ( i = 0; i < count; i++ )
03967 {
03968 ON_Font& font = model.m_font_table[i];
03969 if ( font.m_font_index != i )
03970 {
03971 if ( text_log )
03972 {
03973 text_log->Print("m_font_table[%d].m_font_index == %d (should be %d)\n",
03974 i,font.m_font_index,i);
03975 }
03976 if ( bAttemptRepair )
03977 {
03978 font.m_font_index = i;
03979 if ( text_log )
03980 {
03981 text_log->PushIndent();
03982 text_log->Print("Repaired.\n");
03983 text_log->PopIndent();
03984 }
03985 if ( repair_count )
03986 *repair_count += 1;
03987 }
03988 else
03989 {
03990 return -1;
03991 }
03992 }
03993 if ( !font.IsValid(text_log) )
03994 return 1;
03995 }
03996 return 0;
03997 }
03998
03999
04000 static int AuditDimStyleTableHelper(
04001 ONX_Model& model,
04002 bool bAttemptRepair,
04003 int* repair_count,
04004 ON_TextLog* text_log
04005 )
04006 {
04007 if ( repair_count )
04008 *repair_count = 0;
04009 int i, count = model.m_dimstyle_table.Count();
04010 for ( i = 0; i < count; i++ )
04011 {
04012 ON_DimStyle& dimstyle = model.m_dimstyle_table[i];
04013 if ( dimstyle.m_dimstyle_index != i )
04014 {
04015 if ( text_log )
04016 {
04017 text_log->Print("m_dimstyle_table[%d].m_dimstyle_index == %d (should be %d)\n",
04018 i,dimstyle.m_dimstyle_index,i);
04019 }
04020 if ( bAttemptRepair )
04021 {
04022 dimstyle.m_dimstyle_index = i;
04023 if ( text_log )
04024 {
04025 text_log->PushIndent();
04026 text_log->Print("Repaired.\n");
04027 text_log->PopIndent();
04028 }
04029 if ( repair_count )
04030 *repair_count += 1;
04031 }
04032 else
04033 {
04034 return -1;
04035 }
04036 }
04037 if ( !dimstyle.IsValid(text_log) )
04038 return 1;
04039 }
04040 return 0;
04041 }
04042
04043
04044 static int AuditHatchPatternTableHelper(
04045 ONX_Model& model,
04046 bool bAttemptRepair,
04047 int* repair_count,
04048 ON_TextLog* text_log
04049 )
04050 {
04051 if ( repair_count )
04052 *repair_count = 0;
04053 int i, count = model.m_hatch_pattern_table.Count();
04054 for ( i = 0; i < count; i++ )
04055 {
04056 ON_HatchPattern& hatchpattern = model.m_hatch_pattern_table[i];
04057 if ( hatchpattern.m_hatchpattern_index != i )
04058 {
04059 if ( text_log )
04060 {
04061 text_log->Print("m_hatch_pattern_table[%d].m_hatchpattern_index == %d (should be %d)\n",
04062 i,hatchpattern.m_hatchpattern_index,i);
04063 }
04064 if ( bAttemptRepair )
04065 {
04066 hatchpattern.m_hatchpattern_index = i;
04067 if ( text_log )
04068 {
04069 text_log->PushIndent();
04070 text_log->Print("Repaired.\n");
04071 text_log->PopIndent();
04072 }
04073 if ( repair_count )
04074 *repair_count += 1;
04075 }
04076 else
04077 {
04078 return -1;
04079 }
04080 }
04081 if ( !hatchpattern.IsValid(text_log) )
04082 return 1;
04083 }
04084 return 0;
04085 }
04086
04087
04088 static int AuditObjectAttributesHelper(
04089 ONX_Model& model,
04090 ON_3dmObjectAttributes& attributes,
04091 const char* parent_name,
04092 int parent_index,
04093 bool bAttemptRepair,
04094 int* repair_count,
04095 ON_TextLog* text_log
04096 )
04097 {
04098 int repcount = 0;
04099 int errcount = 0;
04100
04101
04102 int layer_index = attributes.m_layer_index;
04103 if ( layer_index < 0 || layer_index >= model.m_layer_table.Count() )
04104 {
04105 errcount++;
04106 if ( text_log )
04107 {
04108 text_log->Print(parent_name,parent_index);
04109 text_log->Print("m_layer_index = %d is not valid.",layer_index);
04110 }
04111
04112 if ( bAttemptRepair )
04113 {
04114 layer_index = model.m_settings.m_current_layer_index;
04115 if ( layer_index < 0 || layer_index >= model.m_layer_table.Count()
04116 )
04117 {
04118 layer_index = 0;
04119 }
04120 if ( layer_index >= 0 && layer_index < model.m_layer_table.Count() )
04121 {
04122 repcount++;
04123 attributes.m_layer_index = layer_index;
04124 if ( text_log )
04125 text_log->Print(" Repaired.");
04126 }
04127 }
04128 if ( text_log )
04129 {
04130 text_log->Print("\n");
04131 }
04132 }
04133
04134 int linetype_index = attributes.m_linetype_index;
04135 if ( linetype_index < -1 || linetype_index >= model.m_linetype_table.Count() )
04136 {
04137 errcount++;
04138 if ( text_log )
04139 {
04140 text_log->Print(parent_name,parent_index);
04141 text_log->Print("m_linetype_index = %d is not valid.",linetype_index);
04142 }
04143
04144 if ( bAttemptRepair )
04145 {
04146 linetype_index = -1;
04147 repcount++;
04148 attributes.m_linetype_index = linetype_index;
04149 if ( text_log )
04150 text_log->Print(" Repaired.");
04151 }
04152 if ( text_log )
04153 {
04154 text_log->Print("\n");
04155 }
04156 }
04157
04158 int material_index = attributes.m_material_index;
04159 if ( material_index < -1 || material_index >= model.m_material_table.Count() )
04160 {
04161 errcount++;
04162 if ( text_log )
04163 {
04164 text_log->Print(parent_name,parent_index);
04165 text_log->Print("m_material_index = %d is not valid.",material_index);
04166 }
04167
04168 if ( bAttemptRepair )
04169 {
04170 material_index = -1;
04171 repcount++;
04172 attributes.m_material_index = material_index;
04173 if ( text_log )
04174 text_log->Print(" Repaired.");
04175 }
04176 if ( text_log )
04177 {
04178 text_log->Print("\n");
04179 }
04180 }
04181
04182 if ( repcount > 0 && repair_count )
04183 *repair_count = *repair_count + repcount;
04184
04185 return (errcount>0) ? 9 : 0;
04186 }
04187
04188
04189
04190 static int AuditLightTableHelper(
04191 ONX_Model& model,
04192 bool bAttemptRepair,
04193 int* repair_count,
04194 ON_TextLog* text_log
04195 )
04196 {
04197 int rc = 0;
04198 if ( repair_count )
04199 *repair_count = 0;
04200 int i, count = model.m_light_table.Count();
04201 for ( i = 0; i < count; i++ )
04202 {
04203 ONX_Model_RenderLight& xlight = model.m_light_table[i];
04204 ON_Light& light = xlight.m_light;
04205 if ( light.m_light_index != i )
04206 {
04207 if ( text_log )
04208 {
04209 text_log->Print("m_light_table[%d].m_light_index == %d (should be %d)\n",
04210 i,light.m_light_index,i);
04211 }
04212 if ( bAttemptRepair )
04213 {
04214 light.m_light_index = i;
04215 if ( text_log )
04216 {
04217 text_log->PushIndent();
04218 text_log->Print("Repaired.\n");
04219 text_log->PopIndent();
04220 }
04221 if ( repair_count )
04222 *repair_count += 1;
04223 }
04224 else
04225 {
04226 return -1;
04227 }
04228 }
04229
04230 int attrc = AuditObjectAttributesHelper(model,
04231 xlight.m_attributes,
04232 "m_light_table[%d].m_attributes",
04233 i,
04234 bAttemptRepair,
04235 repair_count,
04236 text_log
04237 );
04238
04239 if ( attrc && 0 == rc )
04240 rc = 9;
04241
04242 if ( !light.IsValid(text_log) )
04243 {
04244 if ( 0 == rc )
04245 rc = 1;
04246 }
04247
04248 }
04249 return rc;
04250 }
04251
04252 static int AuditMaterialTableHelper(
04253 ONX_Model& model,
04254 bool bAttemptRepair,
04255 int* repair_count,
04256 ON_TextLog* text_log
04257 )
04258 {
04259 if ( repair_count )
04260 *repair_count = 0;
04261 int i, count = model.m_material_table.Count();
04262 for ( i = 0; i < count; i++ )
04263 {
04264 ON_Material& mat = model.m_material_table[i];
04265 if ( mat.MaterialIndex() != i )
04266 {
04267 if ( text_log )
04268 {
04269 text_log->Print("m_material_table[%d].MaterialIndex() == %d (should be %d)\n",
04270 i,mat.MaterialIndex(),i);
04271 }
04272 if ( bAttemptRepair )
04273 {
04274 mat.SetMaterialIndex(i);
04275 if ( text_log )
04276 {
04277 text_log->PushIndent();
04278 text_log->Print("Repaired.\n");
04279 text_log->PopIndent();
04280 }
04281 if ( repair_count )
04282 *repair_count += 1;
04283 }
04284 else
04285 {
04286 return -1;
04287 }
04288 }
04289 if ( !mat.IsValid(text_log) )
04290 return 1;
04291 }
04292 return 0;
04293 }
04294
04295 static int AuditLinetypeTableHelper(
04296 ONX_Model& model,
04297 bool bAttemptRepair,
04298 int* repair_count,
04299 ON_TextLog* text_log
04300 )
04301 {
04302 if ( repair_count )
04303 *repair_count = 0;
04304 int i, count = model.m_linetype_table.Count();
04305 for ( i = 0; i < count; i++ )
04306 {
04307 ON_Linetype& lt = model.m_linetype_table[i];
04308 if ( lt.LinetypeIndex() != i )
04309 {
04310 if ( text_log )
04311 {
04312 text_log->Print("m_linetype_table[%d].LinetypeIndex() == %d (should be %d)\n",
04313 i,lt.LinetypeIndex(),i);
04314 }
04315 if ( bAttemptRepair )
04316 {
04317 lt.SetLinetypeIndex(i);
04318 if ( text_log )
04319 {
04320 text_log->PushIndent();
04321 text_log->Print("Repaired.\n");
04322 text_log->PopIndent();
04323 }
04324 if ( repair_count )
04325 *repair_count += 1;
04326 }
04327 else
04328 {
04329 return -1;
04330 }
04331 }
04332 if ( !lt.IsValid(text_log) )
04333 return 10;
04334 }
04335 return 0;
04336 }
04337
04338 static int AuditLayerTableHelper(
04339 ONX_Model& model,
04340 bool bAttemptRepair,
04341 int* repair_count,
04342 ON_TextLog* text_log
04343 )
04344 {
04345 int rc = 0;
04346 if ( repair_count )
04347 *repair_count = 0;
04348 int i, count = model.m_layer_table.Count();
04349 if ( count == 0 && (model.m_object_table.Count()>0 || model.m_light_table.Count()>0))
04350 rc = 2;
04351 for ( i = 0; i < count; i++ )
04352 {
04353 ON_Layer& layer = model.m_layer_table[i];
04354 if ( layer.LayerIndex() != i )
04355 {
04356 if ( text_log )
04357 {
04358 text_log->Print("m_layer_table[%d].LayerIndex() == %d (should be %d)\n",
04359 i,layer.LayerIndex(),i);
04360 }
04361 if ( bAttemptRepair )
04362 {
04363 layer.SetLayerIndex(i);
04364 if ( text_log )
04365 {
04366 text_log->PushIndent();
04367 text_log->Print("Repaired.\n");
04368 text_log->PopIndent();
04369 }
04370 if ( repair_count )
04371 *repair_count += 1;
04372 }
04373 else
04374 {
04375 rc = -1;
04376 }
04377 }
04378
04379 const wchar_t* layer_name = layer.LayerName();
04380
04381 if ( 0 == layer_name || 0 == layer_name[0] )
04382 {
04383 if ( text_log )
04384 {
04385 text_log->Print("m_layer_table[%d].LayerName() is empty\n",i);
04386 }
04387 if ( bAttemptRepair )
04388 {
04389 ON_wString name;
04390 model.GetUnusedLayerName( name );
04391 layer.SetLayerName( name );
04392 if ( text_log )
04393 {
04394 text_log->PushIndent();
04395 text_log->Print("Repaired.\n");
04396 text_log->PopIndent();
04397 }
04398 if ( repair_count )
04399 *repair_count += 1;
04400 layer_name = layer.LayerName();
04401 }
04402 else if ( rc == 0 )
04403 {
04404 rc = 2;
04405 }
04406 }
04407
04408 if ( !ONX_IsValidName(layer_name) )
04409 {
04410 if ( text_log )
04411 {
04412 text_log->Print("m_layer_table[%d].LayerName() is not valid\n",i);
04413 }
04414 if ( bAttemptRepair )
04415 {
04416 ON_wString name;
04417 model.GetUnusedLayerName( name );
04418 layer.SetLayerName( name );
04419 if ( text_log )
04420 {
04421 text_log->PushIndent();
04422 text_log->Print("Repaired.\n");
04423 text_log->PopIndent();
04424 }
04425 if ( repair_count )
04426 *repair_count += 1;
04427 layer_name = layer.LayerName();
04428 }
04429 else if ( rc == 0 )
04430 {
04431 rc = 2;
04432 }
04433 }
04434
04435 int j = model.LayerIndex(layer_name);
04436 if ( i != j )
04437 {
04438 if ( text_log )
04439 {
04440 text_log->Print("m_layer_table[%d] and m_layer_table[%d] have same layer name.\n",i,j);
04441 }
04442 if ( bAttemptRepair )
04443 {
04444 ON_wString name;
04445 model.GetUnusedLayerName( name );
04446 layer.SetLayerName( name );
04447 if ( text_log )
04448 {
04449 text_log->PushIndent();
04450 text_log->Print("Repaired.\n");
04451 text_log->PopIndent();
04452 }
04453 if ( repair_count )
04454 *repair_count += 1;
04455 }
04456 else if ( rc == 0 )
04457 {
04458 rc = 2;
04459 }
04460 }
04461
04462 if ( rc == 0 && !layer.IsValid(text_log) )
04463 rc = 2;
04464 }
04465 return rc;
04466 }
04467
04468 static int AuditIdsHelper(
04469 ON_SimpleArray<ON_UuidIndex>& id_list,
04470 ON_UuidIndexList* index_list,
04471 bool bAttemptRepair,
04472 int* repair_count,
04473 ON_TextLog* text_log,
04474 const char* nil_id_msg,
04475 const char* dup_id_msg
04476 )
04477 {
04478 int nil_count = 0;
04479 int dup_count = 0;
04480 int rep_count = 0;
04481
04482 if ( index_list )
04483 index_list->Empty();
04484 const int count = id_list.Count();
04485 if ( count > 0 )
04486 {
04487 int i;
04488 ON_UUID id;
04489
04490
04491 for ( i = 0; i < count; i++ )
04492 {
04493 id_list[i].m_i = i;
04494 if ( ON_nil_uuid == id_list[i].m_id )
04495 {
04496 nil_count++;
04497 if ( text_log )
04498 text_log->Print(nil_id_msg,i);
04499
04500 if ( bAttemptRepair )
04501 {
04502 id = ON_nil_uuid;
04503 if ( ON_CreateUuid(id) && !ON_UuidIsNil(id) )
04504 {
04505 id_list[i].m_id = id;
04506 rep_count++;
04507 if ( text_log )
04508 text_log->Print(" Repaired.");
04509 }
04510 }
04511 if ( text_log )
04512 text_log->Print("\n");
04513 }
04514 }
04515
04516 if ( count > 1 )
04517 {
04518
04519 id_list.QuickSort( ON_UuidIndex::CompareIdAndIndex );
04520 ON_UuidIndex id0 = id_list[0];
04521 for ( i = 1; i < count; i++ )
04522 {
04523 if ( ON_nil_uuid == id_list[i].m_id )
04524 {
04525
04526
04527
04528
04529 continue;
04530 }
04531
04532 if ( id_list[i].m_id == id0.m_id )
04533 {
04534 dup_count++;
04535 if ( text_log )
04536 text_log->Print(dup_id_msg,id0.m_i,id_list[i].m_i);
04537
04538 if ( bAttemptRepair )
04539 {
04540
04541 id = ON_nil_uuid;
04542 if ( ON_CreateUuid(id) && !ON_UuidIsNil(id) )
04543 {
04544 rep_count++;
04545 id_list[i].m_id = id;
04546 if ( text_log )
04547 text_log->Print(" Repaired.");
04548 }
04549 }
04550 if ( text_log )
04551 text_log->Print("\n");
04552 }
04553 else
04554 {
04555 id0 = id_list[i];
04556 }
04557 }
04558 }
04559
04560 if ( index_list )
04561 {
04562
04563 index_list->Reserve(count);
04564 for ( i = 0; i < count; i++ )
04565 {
04566 index_list->AddUuidIndex(id_list[i].m_id,id_list[i].m_i,false);
04567 }
04568 }
04569 }
04570
04571 if ( repair_count )
04572 *repair_count = rep_count;
04573
04574 return dup_count + nil_count;
04575 }
04576
04577 static int AuditObjectIdsHelper(
04578 ONX_Model& model,
04579 bool bAttemptRepair,
04580 int* repair_count,
04581 ON_TextLog* text_log
04582 )
04583 {
04584 int rc = 0;
04585 const int count = model.m_object_table.Count();
04586 model.m_object_id_index.Empty();
04587 if ( count > 0 )
04588 {
04589 int i;
04590 ON_SimpleArray<ON_UuidIndex> id_list(count);
04591 for ( i = 0; i < count; i++ )
04592 {
04593 id_list.AppendNew().m_id = model.m_object_table[i].m_attributes.m_uuid;
04594 }
04595 rc = AuditIdsHelper(
04596 id_list,
04597 &model.m_object_id_index,
04598 bAttemptRepair,
04599 repair_count,
04600 text_log,
04601 "m_object_table[%d].m_attributes.m_uuid is nil.",
04602 "m_object_table[%d] and [%d] have the same id."
04603 );
04604 if (rc && bAttemptRepair )
04605 {
04606 for ( i = 0; i < count; i++ )
04607 {
04608 model.m_object_table[id_list[i].m_i].m_attributes.m_uuid = id_list[i].m_id;
04609 }
04610 }
04611 }
04612 return rc;
04613 }
04614
04615
04616 static int AuditLightIdsHelper(
04617 ONX_Model& model,
04618 bool bAttemptRepair,
04619 int* repair_count,
04620 ON_TextLog* text_log
04621 )
04622 {
04623 int rc = 0;
04624 int mismatch_count = 0;
04625 const int count = model.m_light_table.Count();
04626 if ( count > 0 )
04627 {
04628 int i;
04629 ON_SimpleArray<ON_UuidIndex> id_list(count);
04630 for ( i = 0; i < count; i++ )
04631 {
04632 ONX_Model_RenderLight& light = model.m_light_table[i];
04633 if ( ON_UuidCompare(light.m_light.m_light_id,light.m_attributes.m_uuid) )
04634 {
04635 mismatch_count++;
04636 if ( text_log )
04637 {
04638 text_log->Print("m_light_table[%d] light id and attributes id differ.",i);
04639 }
04640 if ( bAttemptRepair )
04641 {
04642 if ( repair_count )
04643 *repair_count = *repair_count + 1;
04644 if ( ON_nil_uuid == light.m_light.m_light_id )
04645 light.m_light.m_light_id = light.m_attributes.m_uuid;
04646 else
04647 light.m_attributes.m_uuid = light.m_light.m_light_id;
04648 if ( text_log )
04649 text_log->Print(" Repaired.");
04650 }
04651 if ( text_log )
04652 text_log->Print("\n");
04653 }
04654
04655 if ( ON_nil_uuid == light.m_light.m_light_id )
04656 {
04657 id_list.AppendNew().m_id = light.m_attributes.m_uuid;
04658 }
04659 else
04660 {
04661 id_list.AppendNew().m_id = light.m_light.m_light_id;
04662 }
04663 }
04664
04665 rc = AuditIdsHelper(
04666 id_list,
04667 0,
04668 bAttemptRepair,
04669 repair_count,
04670 text_log,
04671 "m_light_table[%d] light id is nil.",
04672 "m_light_table[%d] and[%d] have the same id."
04673 );
04674
04675 rc += mismatch_count;
04676
04677 if ( rc && bAttemptRepair )
04678 {
04679 for ( i = 0; i < count; i++ )
04680 {
04681 ONX_Model_RenderLight& light = model.m_light_table[id_list[i].m_i];
04682 light.m_light.m_light_id = id_list[i].m_id;
04683 light.m_attributes.m_uuid = light.m_light.m_light_id;
04684 }
04685 }
04686
04687
04688 for ( i = 0; i < count; i++ )
04689 {
04690 ONX_Model_RenderLight& light = model.m_light_table[i];
04691 int oi = -1;
04692 if ( model.m_object_id_index.FindUuid(light.m_light.m_light_id,&oi) )
04693 {
04694 rc++;
04695 if ( text_log )
04696 {
04697 text_log->Print("m_light_table[%d] and m_object_table[%d] have same id.",
04698 i,
04699 oi
04700 );
04701 }
04702 if ( bAttemptRepair )
04703 {
04704 ON_UuidIndex light_id;
04705 memset(&light_id,0,sizeof(light_id));
04706 light_id.m_id = ON_nil_uuid;
04707 light_id.m_i = -1;
04708 if ( ON_CreateUuid(light_id.m_id) && ON_nil_uuid != light_id.m_id )
04709 {
04710 if ( !model.m_object_id_index.FindUuid(light_id.m_id)
04711 && id_list.BinarySearch( &light_id, ON_UuidIndex::CompareId ) < 0
04712 )
04713 {
04714 if ( repair_count )
04715 *repair_count = *repair_count + 1;
04716 light.m_light.m_light_id = light_id.m_id;
04717 light.m_attributes.m_uuid = light.m_light.m_light_id;
04718 if ( text_log )
04719 text_log->Print(" Repaired.");
04720 }
04721 }
04722 }
04723 if ( text_log )
04724 text_log->Print("\n");
04725 }
04726 }
04727 }
04728
04729 return rc;
04730 }
04731
04732 static int AuditIDefIdsHelper(
04733 ONX_Model& model,
04734 bool bAttemptRepair,
04735 int* repair_count,
04736 ON_TextLog* text_log
04737 )
04738 {
04739 int rc = 0;
04740 const int count = model.m_idef_table.Count();
04741 model.m_idef_id_index.Empty();
04742 if ( count > 0 )
04743 {
04744 int i;
04745 ON_SimpleArray<ON_UuidIndex> id_list(count);
04746 for ( i = 0; i < count; i++ )
04747 {
04748 id_list.AppendNew().m_id = model.m_idef_table[i].m_uuid;
04749 }
04750 rc = AuditIdsHelper(
04751 id_list,
04752 &model.m_idef_id_index,
04753 bAttemptRepair,
04754 repair_count,
04755 text_log,
04756 "m_idef_table[%d].m_attributes.m_uuid is nil.",
04757 "m_idef_table[%d] and[%d] are the same."
04758 );
04759 if (rc && bAttemptRepair )
04760 {
04761 for ( i = 0; i < count; i++ )
04762 {
04763 model.m_idef_table[id_list[i].m_i].m_uuid = id_list[i].m_id;
04764 }
04765 }
04766 }
04767 return rc;
04768 }
04769
04770 static int AuditMappingIdsHelper(
04771 ONX_Model& model,
04772 bool bAttemptRepair,
04773 int* repair_count,
04774 ON_TextLog* text_log
04775 )
04776 {
04777 int rc = 0;
04778 const int count = model.m_mapping_table.Count();
04779 model.m_mapping_id_index.Empty();
04780 if ( count > 0 )
04781 {
04782 int i;
04783 ON_SimpleArray<ON_UuidIndex> id_list(count);
04784 for ( i = 0; i < count; i++ )
04785 {
04786 id_list.AppendNew().m_id = model.m_mapping_table[i].m_mapping_id;
04787 }
04788 rc = AuditIdsHelper(
04789 id_list,
04790 &model.m_mapping_id_index,
04791 bAttemptRepair,
04792 repair_count,
04793 text_log,
04794 "m_mapping_table[%d].m_mapping_id is nil.",
04795 "m_mapping_table[%d] and[%d] are the same."
04796 );
04797 if (rc && bAttemptRepair )
04798 {
04799 for ( i = 0; i < count; i++ )
04800 {
04801 model.m_mapping_table[id_list[i].m_i].m_mapping_id = id_list[i].m_id;
04802 }
04803 }
04804 }
04805 return rc;
04806 }
04807
04808
04809 static int AuditMaterialIdsHelper(
04810 ONX_Model& model,
04811 bool bAttemptRepair,
04812 int* repair_count,
04813 ON_TextLog* text_log
04814 )
04815 {
04816 int rc = 0;
04817 const int count = model.m_material_table.Count();
04818 model.m_material_id_index.Empty();
04819 if ( count > 0 )
04820 {
04821 int i;
04822 ON_SimpleArray<ON_UuidIndex> id_list(count);
04823 for ( i = 0; i < count; i++ )
04824 {
04825 id_list.AppendNew().m_id = model.m_material_table[i].m_material_id;
04826 }
04827 rc = AuditIdsHelper(
04828 id_list,
04829 &model.m_material_id_index,
04830 bAttemptRepair,
04831 repair_count,
04832 text_log,
04833 "m_material_table[%d].m_material_id is nil.",
04834 "m_material_table[%d] and[%d] are the same."
04835 );
04836 if (rc && bAttemptRepair )
04837 {
04838 for ( i = 0; i < count; i++ )
04839 {
04840 model.m_material_table[id_list[i].m_i].m_material_id = id_list[i].m_id;
04841 }
04842 }
04843 }
04844 return rc;
04845 }
04846
04847 static int AuditModelIdsHelper(
04848 ONX_Model& model,
04849 bool bAttemptRepair,
04850 int* repair_count,
04851 ON_TextLog* text_log,
04852 ON_SimpleArray<int>* warnings
04853 )
04854 {
04855 int warning_count = 0;
04856 int i;
04857
04858
04859 i = AuditObjectIdsHelper(model,bAttemptRepair,repair_count,text_log);
04860 if (i < 0 )
04861 return i;
04862 if (i > 0 )
04863 {
04864 warning_count += i;
04865 if (warnings)
04866 warnings->Append(3);
04867 }
04868
04869
04870 i = AuditLightIdsHelper(model,bAttemptRepair,repair_count,text_log);
04871 if (i < 0 )
04872 return i;
04873 if (i > 0 )
04874 {
04875 warning_count += i;
04876 if (warnings)
04877 warnings->Append(15);
04878 }
04879
04880
04881 i = AuditIDefIdsHelper(model,bAttemptRepair,repair_count,text_log);
04882 if (i < 0 )
04883 return i;
04884 if (i > 0 )
04885 {
04886 warning_count += i;
04887 if (warnings)
04888 warnings->Append(12);
04889 }
04890
04891
04892 i = AuditMappingIdsHelper(model,bAttemptRepair,repair_count,text_log);
04893 if (i < 0 )
04894 return i;
04895 if (i > 0 )
04896 {
04897 warning_count += i;
04898 if (warnings)
04899 warnings->Append(13);
04900 }
04901
04902
04903 i = AuditMaterialIdsHelper(model,bAttemptRepair,repair_count,text_log);
04904 if (i < 0 )
04905 return i;
04906 if (i > 0 )
04907 {
04908 warning_count += i;
04909 if (warnings)
04910 warnings->Append(13);
04911 }
04912
04913 return warning_count;
04914 }
04915
04916 static int AuditIDefTableHelper(
04917 ONX_Model& model,
04918 bool bAttemptRepair,
04919 int* repair_count,
04920 ON_TextLog* text_log
04921 )
04922 {
04923 int rc = 0;
04924 int i, j, count = model.m_idef_table.Count();
04925
04926
04927
04928
04929 for ( i = 0; i < count; i++ )
04930 {
04931 bool idef_ok = true;
04932 ON_InstanceDefinition& idef = model.m_idef_table[i];
04933 const wchar_t* idef_name = idef.Name();
04934 if ( 0 == idef_name )
04935 continue;
04936
04937 if ( !ONX_IsValidName(idef_name) )
04938 {
04939 if ( text_log )
04940 text_log->Print("m_idef_table[%d].Name() = \"%ls\" is not valid.\n",i,idef_name);
04941 idef_ok = false;
04942 }
04943 else
04944 {
04945 j = model.IDefIndex( idef_name );
04946 if ( j != i )
04947 {
04948 if ( text_log )
04949 text_log->Print("m_idef_table[%d].Name() = m_idef_table[%d].Name().\n",i,j);
04950 idef_ok = false;
04951 }
04952 }
04953 if ( bAttemptRepair )
04954 {
04955 ON_wString new_name;
04956 model.GetUnusedIDefName(new_name);
04957 if ( ONX_IsValidName(new_name) && -1 == model.IDefIndex(new_name) )
04958 {
04959 idef.SetName(new_name);
04960 if ( repair_count )
04961 *repair_count = *repair_count + 1;
04962 if ( text_log )
04963 text_log->Print("Repaired.\n");
04964 idef_ok = true;
04965 }
04966 }
04967 if ( !idef_ok && rc == 0 )
04968 {
04969 rc = 5;
04970 }
04971 }
04972
04973 for ( i = 0; i < count; i++ )
04974 {
04975 bool idef_ok = true;
04976 ON_InstanceDefinition& idef = model.m_idef_table[i];
04977
04978
04979 int k;
04980 j = 0;
04981 for ( j = k = 0; j < idef.m_object_uuid.Count(); k++ )
04982 {
04983 ON_UUID obj_uuid = idef.m_object_uuid[j];
04984 int obj_index = model.ObjectIndex(obj_uuid);
04985 if ( obj_index < 0 )
04986 {
04987 if ( text_log )
04988 text_log->Print("m_idef_table[%d].m_object_uuid[%d] is not an object's uuid.\n",i,k);
04989 if ( bAttemptRepair )
04990 {
04991 idef.m_object_uuid.Remove(j);
04992 if ( repair_count )
04993 *repair_count = *repair_count + 1;
04994 if ( text_log )
04995 text_log->Print("Repaired.\n");
04996 }
04997 else
04998 {
04999 j++;
05000 idef_ok = false;
05001 }
05002 }
05003 else
05004 {
05005 ONX_Model_Object& obj = model.m_object_table[obj_index];
05006 if ( ON::idef_object != obj.m_attributes.Mode() )
05007 {
05008 if ( text_log )
05009 text_log->Print("Object with uuid m_idef_table[%d].m_object_uuid[%d] does not have m_attributes.Mode()=ON::idef_object.\n",i,k);
05010 if ( bAttemptRepair )
05011 {
05012 idef.m_object_uuid.Remove(j);
05013 if ( repair_count )
05014 *repair_count = *repair_count + 1;
05015 if ( text_log )
05016 text_log->Print("Repaired.\n");
05017 }
05018 else
05019 {
05020 j++;
05021 idef_ok = false;
05022 }
05023 }
05024 else if ( 0 == obj.m_object )
05025 {
05026 if ( text_log )
05027 text_log->Print("Object with uuid m_idef_table[%d].m_object_uuid[%d] has NULL m_object.\n",i,k);
05028 if ( bAttemptRepair )
05029 {
05030 idef.m_object_uuid.Remove(j);
05031 if ( repair_count )
05032 *repair_count = *repair_count + 1;
05033 if ( text_log )
05034 text_log->Print("Repaired.\n");
05035 }
05036 else
05037 {
05038 j++;
05039 idef_ok = false;
05040 }
05041 }
05042 else if ( obj.m_object->ObjectType() == ON::instance_reference )
05043 {
05044 const ON_InstanceRef* pNestedRef = ON_InstanceRef::Cast(obj.m_object);
05045 if ( pNestedRef )
05046 {
05047 if ( model.UsesIDef( *pNestedRef, idef.Uuid() ) )
05048 {
05049 if ( text_log )
05050 text_log->Print("m_idef_table[%d].m_object_uuid[%d] is a circular reference.\n",i,k);
05051 if ( bAttemptRepair )
05052 {
05053 idef.m_object_uuid.Remove(j);
05054 if ( repair_count )
05055 *repair_count = *repair_count + 1;
05056 if ( text_log )
05057 text_log->Print("Repaired.\n");
05058 }
05059 else
05060 {
05061 j++;
05062 idef_ok = false;
05063 rc = -1;
05064 }
05065 }
05066 else
05067 j++;
05068 }
05069 else
05070 j++;
05071 }
05072 else
05073 j++;
05074 }
05075 }
05076 if ( idef.m_object_uuid.Count() <= 0 )
05077 {
05078 if ( text_log )
05079 text_log->Print("m_idef_table[%d].m_object_uuid.Count() = 0.\n",i);
05080 idef_ok = false;
05081 }
05082 if ( !idef_ok && rc == 0 )
05083 rc = 6;
05084
05085 }
05086
05087 return rc;
05088 }
05089
05090
05091 static int AuditObjectTableHelper(
05092 ONX_Model& model,
05093 bool bAttemptRepair,
05094 int* repair_count,
05095 ON_TextLog* text_log
05096 )
05097 {
05098
05099
05100 int rc = 0;
05101 int i, count = model.m_object_table.Count();
05102
05103 for ( i = 0; i < count; i++ )
05104 {
05105 ONX_Model_Object& obj = model.m_object_table[i];
05106 if ( 0 == obj.m_object )
05107 {
05108 rc = 7;
05109 if ( text_log )
05110 text_log->Print("m_object_table[%d].m_object is NULL.\n",i);
05111 }
05112 else if ( false == obj.m_object->IsValid(NULL) )
05113 {
05114 rc = 8;
05115 if ( text_log )
05116 {
05117 text_log->Print("m_object_table[%d].m_object->IsValid() = false.\n",i);
05118 text_log->PushIndent();
05119 text_log->PushIndent();
05120 obj.m_object->IsValid(text_log);
05121 text_log->PopIndent();
05122 text_log->PopIndent();
05123 }
05124 }
05125
05126 int attrc = AuditObjectAttributesHelper(model,
05127 obj.m_attributes,
05128 "m_object_table[%d].m_attributes",
05129 i,
05130 bAttemptRepair,
05131 repair_count,
05132 text_log
05133 );
05134 if ( 0 == rc && attrc )
05135 rc = attrc;
05136 }
05137
05138 return rc;
05139 }
05140
05141 static int AuditHistoryRecordTableHelper(
05142 ONX_Model& model,
05143 bool bAttemptRepair,
05144 int* repair_count,
05145 ON_TextLog* text_log
05146 )
05147 {
05148
05149 return 0;
05150 }
05151
05152 int ONX_Model::Audit(
05153 bool bAttemptRepair,
05154 int* repair_count,
05155 ON_TextLog* text_log,
05156 ON_SimpleArray<int>* warnings
05157 )
05158 {
05159 int warning_count = 0;
05160 int rc = 0, i;
05161 int repcnt;
05162 if ( repair_count )
05163 *repair_count = 0;
05164
05165 repcnt = 0;
05166 i = AuditModelIdsHelper( *this, bAttemptRepair, &repcnt, text_log, warnings );
05167 if ( repair_count )
05168 *repair_count += repcnt;
05169 if ( i < 0 )
05170 return i;
05171 warning_count += i;
05172
05173 repcnt = 0;
05174 i = AuditTextureMappingTableHelper( *this, bAttemptRepair, &repcnt, text_log );
05175 if ( repair_count )
05176 *repair_count += repcnt;
05177 if ( i < 0 )
05178 return i;
05179 if ( 0 == rc && 0 != i )
05180 rc = i;
05181
05182 repcnt = 0;
05183 i = AuditMaterialTableHelper( *this, bAttemptRepair, &repcnt, text_log );
05184 if ( repair_count )
05185 *repair_count += repcnt;
05186 if ( i < 0 )
05187 return i;
05188 if ( 0 == rc && 0 != i )
05189 rc = i;
05190
05191 repcnt = 0;
05192 i = AuditLinetypeTableHelper( *this, bAttemptRepair, &repcnt, text_log );
05193 if ( repair_count )
05194 *repair_count += repcnt;
05195 if ( i < 0 )
05196 return i;
05197 if ( 0 == rc && 0 != i )
05198 rc = i;
05199
05200 repcnt = 0;
05201 i = AuditLayerTableHelper( *this, bAttemptRepair, &repcnt, text_log );
05202 if ( repair_count )
05203 *repair_count += repcnt;
05204 if ( i < 0 )
05205 return i;
05206 if ( 0 == rc && 0 != i )
05207 rc = i;
05208
05209 repcnt = 0;
05210 i = AuditGroupTableHelper( *this, bAttemptRepair, &repcnt, text_log );
05211 if ( repair_count )
05212 *repair_count += repcnt;
05213 if ( i < 0 )
05214 return i;
05215 if ( 0 == rc && 0 != i )
05216 rc = i;
05217
05218 repcnt = 0;
05219 i = AuditFontTableHelper( *this, bAttemptRepair, &repcnt, text_log );
05220 if ( repair_count )
05221 *repair_count += repcnt;
05222 if ( i < 0 )
05223 return i;
05224 if ( 0 == rc && 0 != i )
05225 rc = i;
05226
05227 repcnt = 0;
05228 i = AuditDimStyleTableHelper( *this, bAttemptRepair, &repcnt, text_log );
05229 if ( repair_count )
05230 *repair_count += repcnt;
05231 if ( i < 0 )
05232 return i;
05233 if ( 0 == rc && 0 != i )
05234 rc = i;
05235
05236 repcnt = 0;
05237 i = AuditLightTableHelper( *this, bAttemptRepair, &repcnt, text_log );
05238 if ( repair_count )
05239 *repair_count += repcnt;
05240 if ( i < 0 )
05241 return i;
05242 if ( 0 == rc && 0 != i )
05243 rc = i;
05244
05245 repcnt = 0;
05246 i = AuditHatchPatternTableHelper( *this, bAttemptRepair, &repcnt, text_log );
05247 if ( repair_count )
05248 *repair_count += repcnt;
05249 if ( i < 0 )
05250 return i;
05251 if ( 0 == rc && 0 != i )
05252 rc = i;
05253
05254 repcnt = 0;
05255 i = AuditIDefTableHelper( *this, bAttemptRepair, &repcnt, text_log );
05256 if ( repair_count )
05257 *repair_count += repcnt;
05258 if ( i < 0 )
05259 return i;
05260 if ( 0 == rc && 0 != i )
05261 rc = i;
05262
05263 repcnt = 0;
05264 i = AuditObjectTableHelper( *this, bAttemptRepair, &repcnt, text_log );
05265 if ( repair_count )
05266 *repair_count += repcnt;
05267 if ( i < 0 )
05268 return i;
05269 if ( 0 == rc && 0 != i )
05270 rc = i;
05271
05272 repcnt = 0;
05273 i = AuditHistoryRecordTableHelper( *this, bAttemptRepair, &repcnt, text_log );
05274 if ( repair_count )
05275 *repair_count += repcnt;
05276 if ( i < 0 )
05277 return i;
05278 if ( 0 == rc && 0 != i )
05279 rc = i;
05280
05281 return warning_count;
05282 }
05283
05284 static const ON_UnknownUserData* RDKObjectUserDataHelper(const ON_UserData* objectud)
05285 {
05286
05287
05288
05289
05290
05291 static const ON_UUID CRhRdkUserData_object_id =
05292 { 0xAFA82772, 0x1525, 0x43dd, { 0xA6, 0x3C, 0xC8, 0x4A, 0xC5, 0x80, 0x69, 0x11 } };
05293
05294
05295
05296 static const ON_UUID CRhRdkUserData_userdata_uuid =
05297 { 0xB63ED079, 0xCF67, 0x416c, { 0x80, 0x0D, 0x22, 0x02, 0x3A, 0xE1, 0xBE, 0x21 } };
05298
05299 const ON_UnknownUserData* unknown_ud = ON_UnknownUserData::Cast(objectud);
05300
05301 bool rc = ( 0 != unknown_ud
05302 && unknown_ud->m_sizeof_buffer > 0
05303 && 0 != unknown_ud->m_buffer
05304 && 0 == ON_UuidCompare(CRhRdkUserData_object_id,unknown_ud->m_unknownclass_uuid)
05305 && 0 == ON_UuidCompare(CRhRdkUserData_userdata_uuid,unknown_ud->m_userdata_uuid)
05306 );
05307 return rc ? unknown_ud : 0;
05308 }
05309
05310 bool ONX_Model::IsRDKObjectInformation(const ON_UserData& objectud)
05311 {
05312 return 0 != RDKObjectUserDataHelper(&objectud);
05313 }
05314
05315 bool ONX_Model::GetRDKObjectInformation(const ON_Object& object,ON_wString& rdk_xml_object_data)
05316 {
05317 rdk_xml_object_data.SetLength(0);
05318 const ON_UnknownUserData* unknown_ud = 0;
05319 const ON_UserData* ud = ON_UserData::Cast(&object);
05320 if ( 0 != ud )
05321 {
05322 unknown_ud = RDKObjectUserDataHelper(ud);
05323 }
05324 else
05325 {
05326 for ( ud = object.FirstUserData(); 0 != ud && 0 == unknown_ud; ud = ud->Next() )
05327 {
05328 unknown_ud = RDKObjectUserDataHelper(ud);
05329 }
05330 }
05331
05332 if ( 0 == unknown_ud )
05333 return false;
05334
05335 ON_Read3dmBufferArchive a(unknown_ud->m_sizeof_buffer,unknown_ud->m_buffer,false,unknown_ud->m_3dm_version,unknown_ud->m_3dm_opennurbs_version);
05336 int version = 0;
05337 if (!a.ReadInt(&version) )
05338 return false;
05339
05340 if ( 1 == version )
05341 {
05342 if ( !a.ReadString(rdk_xml_object_data) )
05343 return false;
05344 }
05345 else if ( 2 == version )
05346 {
05347
05348 ON_SimpleArray< char > s;
05349 int slen = 0;
05350 if ( !a.ReadInt(&slen) )
05351 return false;
05352 if ( slen <= 0 )
05353 return false;
05354 if ( slen + 4 > unknown_ud->m_sizeof_buffer )
05355 return false;
05356 s.Reserve(slen+1);
05357 s.SetCount(slen+1);
05358 s[slen] = 0;
05359 if ( !a.ReadChar(slen,s.Array() ) )
05360 return false;
05361 const char* sArray = s.Array();
05362 if ( 0 != sArray && 0 != sArray[0] )
05363 {
05364 unsigned int error_status = 0;
05365 int wLen = ON_ConvertUTF8ToWideChar(sArray,-1,0,0,&error_status,0,0,0);
05366 if ( wLen > 0 && 0 == error_status )
05367 {
05368 rdk_xml_object_data.SetLength(wLen+2);
05369 wLen = ON_ConvertUTF8ToWideChar(sArray,-1,rdk_xml_object_data.Array(),wLen+1,&error_status,0,0,0);
05370 if ( wLen > 0 && 0 == error_status )
05371 rdk_xml_object_data.SetLength(wLen);
05372 else
05373 rdk_xml_object_data.SetLength(0);
05374 }
05375 if ( 0 != error_status )
05376 {
05377 ON_ERROR("RDK xml object information is not a valid UTF-8 string.");
05378 }
05379 }
05380 }
05381
05382 return rdk_xml_object_data.Length() > 0;
05383 }
05384
05385 bool ONX_Model::IsRDKDocumentInformation(const ONX_Model_UserData& docud)
05386 {
05387
05388 static const ON_UUID rdk_plugin_id =
05389 { 0x16592D58, 0x4A2F, 0x401D, { 0xBF, 0x5E, 0x3B, 0x87, 0x74, 0x1C, 0x1B, 0x1B } };
05390
05391 return ( 0 == ON_UuidCompare(rdk_plugin_id,docud.m_uuid) && docud.m_goo.m_value >= 4 && 0 != docud.m_goo.m_goo );
05392 }
05393
05394
05395 bool ONX_Model::GetRDKDocumentInformation(const ONX_Model_UserData& docud,ON_wString& rdk_xml_document_data)
05396 {
05397 if ( !ONX_Model::IsRDKDocumentInformation(docud) )
05398 return false;
05399
05400 ON_Read3dmBufferArchive a(docud.m_goo.m_value,docud.m_goo.m_goo,false,docud.m_usertable_3dm_version,docud.m_usertable_opennurbs_version);
05401
05402 int version = 0;
05403 if (!a.ReadInt(&version) )
05404 return false;
05405
05406 if ( 1 == version )
05407 {
05408
05409 if ( !a.ReadString(rdk_xml_document_data) )
05410 return false;
05411 }
05412 else if ( 3 == version )
05413 {
05414
05415 int slen = 0;
05416 if ( !a.ReadInt(&slen) )
05417 return 0;
05418 if ( slen <= 0 )
05419 return 0;
05420 if ( slen + 4 > docud.m_goo.m_value )
05421 return 0;
05422 ON_String s;
05423 s.SetLength(slen);
05424 if ( !a.ReadChar(slen,s.Array()) )
05425 return 0;
05426 const char* sArray = s.Array();
05427 if ( 0 != sArray && 0 != sArray[0] )
05428 {
05429 unsigned int error_status = 0;
05430 int wLen = ON_ConvertUTF8ToWideChar(sArray,-1,0,0,&error_status,0,0,0);
05431 if ( wLen > 0 && 0 == error_status )
05432 {
05433 rdk_xml_document_data.SetLength(wLen+2);
05434 wLen = ON_ConvertUTF8ToWideChar(sArray,-1,rdk_xml_document_data.Array(),wLen+1,&error_status,0,0,0);
05435 if ( wLen > 0 && 0 == error_status )
05436 rdk_xml_document_data.SetLength(wLen);
05437 else
05438 {
05439 rdk_xml_document_data.SetLength(0);
05440 }
05441 }
05442 if ( 0 != error_status )
05443 {
05444 ON_ERROR("RDK xml document settings is not a valid UTF-8 string.");
05445 }
05446 }
05447 }
05448
05449 return rdk_xml_document_data.Length() > 0;
05450 }
05451
05452 #if defined(ON_COMPILER_MSC)
05453 #pragma warning( pop )
05454 #endif