00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00015
00016
00017 #include "pcl/surface/3rdparty/opennurbs/opennurbs.h"
00018
00019
00020
00021 #define ON_BOZO_VACCINE_17F24E7521BE4a7b9F3D7F85225247E3
00022 #define ON_BOZO_VACCINE_B5628CA982C44CAE9883487B3E4AB28B
00023
00024
00025
00026
00027
00029
00030
00031
00032
00033 class ON_MeshDoubleVertices : public ON_UserData
00034 {
00035 ON_OBJECT_DECLARE(ON_MeshDoubleVertices);
00036
00037 public:
00038 ON_MeshDoubleVertices();
00039 ~ON_MeshDoubleVertices();
00040
00041
00042
00043
00044
00045
00046
00047 static ON_MeshDoubleVertices* Get(const ON_Mesh* mesh);
00048
00049
00050
00051
00052
00053
00054 static ON_MeshDoubleVertices* Attach(const ON_Mesh* mesh);
00055
00056
00057 ON_BOOL32 IsValid( ON_TextLog* = NULL ) const;
00058 void Dump( ON_TextLog& ) const;
00059 unsigned int SizeOf() const;
00060 ON__UINT32 DataCRC(ON__UINT32) const;
00061 ON_BOOL32 Write(ON_BinaryArchive&) const;
00062 ON_BOOL32 Read(ON_BinaryArchive&);
00063
00064
00065 ON_BOOL32 GetDescription( ON_wString& );
00066 ON_BOOL32 Archive() const;
00067 ON_BOOL32 Transform( const ON_Xform& );
00068
00069 #if !defined(ON_BOZO_VACCINE_17F24E7521BE4a7b9F3D7F85225247E3)
00070 #error DO NOT copy, move or export the definition of ON_MeshDoubleVertices
00071 #endif
00072 #undef ON_BOZO_VACCINE_17F24E7521BE4a7b9F3D7F85225247E3
00073
00074 ON__UINT32 DoubleCRC() const;
00075 static ON__UINT32 FloatCRC( const ON_3fPointArray& );
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092 int m_fcount;
00093 int m_dcount;
00094 ON__UINT32 m_fCRC;
00095 ON__UINT32 m_dCRC;
00096
00097 ON_3dPointArray m_dV;
00098 };
00099
00100 static const ON_3dPoint* Mesh_dV(const ON_Mesh& mesh)
00101 {
00102 if ( mesh.HasDoublePrecisionVertices() && mesh.DoublePrecisionVerticesAreValid() )
00103 {
00104 const ON_3dPointArray& a = mesh.DoublePrecisionVertices();
00105 if ( a.Count() == mesh.m_V.Count() )
00106 return a.Array();
00107 }
00108 return 0;
00109 }
00110
00111 ON_MeshCurveParameters::ON_MeshCurveParameters()
00112 {
00113 memset(this,0,sizeof(*this));
00114 }
00115
00116 ON_OBJECT_IMPLEMENT(ON_Mesh,ON_Geometry,"4ED7D4E4-E947-11d3-BFE5-0010830122F0");
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 bool
00156 ON_MeshFace::IsValid(int mesh_vertex_count) const
00157 {
00158 return ( vi[0] >= 0 && vi[0] < mesh_vertex_count
00159 && vi[1] >= 0 && vi[1] < mesh_vertex_count
00160 && vi[2] >= 0 && vi[2] < mesh_vertex_count
00161 && vi[3] >= 0 && vi[3] < mesh_vertex_count
00162 && vi[0] != vi[1] && vi[1] != vi[2] && vi[2] != vi[0]
00163 && (vi[2]==vi[3]||(vi[0] != vi[3] && vi[1] != vi[3])) );
00164 }
00165
00166
00167 bool
00168 ON_MeshFace::IsValid(int mesh_vertex_count, const ON_3fPoint* V ) const
00169 {
00170 if ( !IsValid(mesh_vertex_count) )
00171 return false;
00172 if ( !(V[vi[0]] != V[vi[1]]) )
00173 return false;
00174 if ( !(V[vi[0]] != V[vi[2]]) )
00175 return false;
00176 if ( !(V[vi[1]] != V[vi[2]]) )
00177 return false;
00178 if ( vi[2] != vi[3] )
00179 {
00180 if ( !(V[vi[0]] != V[vi[3]]) )
00181 return false;
00182 if ( !(V[vi[1]] != V[vi[3]]) )
00183 return false;
00184 if ( !(V[vi[2]] != V[vi[3]]) )
00185 return false;
00186 }
00187 return true;
00188 }
00189
00190
00191 bool
00192 ON_MeshFace::IsValid(int mesh_vertex_count, const ON_3dPoint* V ) const
00193 {
00194 if ( !IsValid(mesh_vertex_count) )
00195 return false;
00196 if ( !(V[vi[0]] != V[vi[1]]) )
00197 return false;
00198 if ( !(V[vi[0]] != V[vi[2]]) )
00199 return false;
00200 if ( !(V[vi[1]] != V[vi[2]]) )
00201 return false;
00202 if ( vi[2] != vi[3] )
00203 {
00204 if ( !(V[vi[0]] != V[vi[3]]) )
00205 return false;
00206 if ( !(V[vi[1]] != V[vi[3]]) )
00207 return false;
00208 if ( !(V[vi[2]] != V[vi[3]]) )
00209 return false;
00210 }
00211 return true;
00212 }
00213
00214
00215 bool ON_MeshFace::Repair(
00216 int mesh_vertex_count
00217 )
00218 {
00219 ON_MeshFace f;
00220 int fvi_count = 0;
00221 f.vi[0] = f.vi[1] = f.vi[2] = f.vi[3] = -1;
00222
00223 if ( vi[0] >= 0 && vi[0] < mesh_vertex_count )
00224 f.vi[fvi_count++] = vi[0];
00225
00226 if ( vi[1] >= 0 && vi[1] < mesh_vertex_count && f.vi[0] != vi[1] )
00227 f.vi[fvi_count++] = vi[1];
00228
00229 if ( vi[2] >= 0 && vi[2] < mesh_vertex_count && f.vi[0] != vi[2] && f.vi[1] != vi[2] )
00230 f.vi[fvi_count++] = vi[2];
00231
00232 if ( vi[3] >= 0 && vi[3] < mesh_vertex_count && f.vi[0] != vi[3] && f.vi[1] != vi[3] && f.vi[2] != vi[3] )
00233 f.vi[fvi_count++] = vi[3];
00234
00235 if ( fvi_count < 3 )
00236 return false;
00237
00238 if ( 3 == fvi_count )
00239 f.vi[3] = f.vi[2];
00240
00241 if ( !f.IsValid(mesh_vertex_count) )
00242 return false;
00243
00244 vi[0] = f.vi[0];
00245 vi[1] = f.vi[1];
00246 vi[2] = f.vi[2];
00247 vi[3] = f.vi[3];
00248
00249 return true;
00250 }
00251
00252 bool ON_MeshFace::Repair(
00253 int mesh_vertex_count,
00254 const ON_3fPoint* V
00255 )
00256 {
00257 ON_MeshFace f;
00258 int fvi_count = 0;
00259 f.vi[0] = f.vi[1] = f.vi[2] = f.vi[3] = -1;
00260
00261 if ( vi[0] >= 0 && vi[0] < mesh_vertex_count )
00262 f.vi[fvi_count++] = vi[0];
00263
00264 if ( vi[1] >= 0 && vi[1] < mesh_vertex_count && f.vi[0] != vi[1] )
00265 {
00266 if ( 0 == fvi_count || V[f.vi[0]] != V[vi[1]] )
00267 f.vi[fvi_count++] = vi[1];
00268 }
00269
00270 if ( fvi_count < 1 )
00271 return false;
00272
00273 if ( vi[2] >= 0 && vi[2] < mesh_vertex_count && f.vi[0] != vi[2] && f.vi[1] != vi[2] && V[f.vi[0]] != V[vi[2]] )
00274 {
00275 if ( 1 == fvi_count || V[f.vi[1]] != V[vi[2]] )
00276 f.vi[fvi_count++] = vi[2];
00277 }
00278
00279 if ( fvi_count < 2 )
00280 return false;
00281
00282 if ( vi[3] >= 0 && vi[3] < mesh_vertex_count && f.vi[0] != vi[3] && f.vi[1] != vi[3] && f.vi[2] != vi[3] && V[f.vi[0]] != V[vi[3]] && V[f.vi[1]] != V[vi[3]] )
00283 {
00284 if ( 2 == fvi_count || V[f.vi[2]] != V[vi[3]] )
00285 f.vi[fvi_count++] = vi[3];
00286 }
00287
00288 if ( fvi_count < 3 )
00289 return false;
00290
00291 if ( 3 == fvi_count )
00292 f.vi[3] = f.vi[2];
00293
00294 if ( !f.IsValid(mesh_vertex_count) )
00295 return false;
00296
00297 vi[0] = f.vi[0];
00298 vi[1] = f.vi[1];
00299 vi[2] = f.vi[2];
00300 vi[3] = f.vi[3];
00301
00302 return true;
00303 }
00304
00305
00306 bool ON_MeshFace::Repair(
00307 int mesh_vertex_count,
00308 const ON_3dPoint* V
00309 )
00310 {
00311 ON_MeshFace f;
00312 int fvi_count = 0;
00313 f.vi[0] = f.vi[1] = f.vi[2] = f.vi[3] = -1;
00314
00315 if ( vi[0] >= 0 && vi[0] < mesh_vertex_count )
00316 f.vi[fvi_count++] = vi[0];
00317
00318 if ( vi[1] >= 0 && vi[1] < mesh_vertex_count && f.vi[0] != vi[1] )
00319 {
00320 if ( 0 == fvi_count || V[f.vi[0]] != V[vi[1]] )
00321 f.vi[fvi_count++] = vi[1];
00322 }
00323
00324 if ( fvi_count < 1 )
00325 return false;
00326
00327 if ( vi[2] >= 0 && vi[2] < mesh_vertex_count && f.vi[0] != vi[2] && f.vi[1] != vi[2] && V[f.vi[0]] != V[vi[2]] )
00328 {
00329 if ( 1 == fvi_count || V[f.vi[1]] != V[vi[2]] )
00330 f.vi[fvi_count++] = vi[2];
00331 }
00332
00333 if ( fvi_count < 2 )
00334 return false;
00335
00336 if ( vi[3] >= 0 && vi[3] < mesh_vertex_count && f.vi[0] != vi[3] && f.vi[1] != vi[3] && f.vi[2] != vi[3] && V[f.vi[0]] != V[vi[3]] && V[f.vi[1]] != V[vi[3]] )
00337 {
00338 if ( 2 == fvi_count || V[f.vi[2]] != V[vi[3]] )
00339 f.vi[fvi_count++] = vi[3];
00340 }
00341
00342 if ( fvi_count < 3 )
00343 return false;
00344
00345 if ( 3 == fvi_count )
00346 f.vi[3] = f.vi[2];
00347
00348 if ( !f.IsValid(mesh_vertex_count) )
00349 return false;
00350
00351 vi[0] = f.vi[0];
00352 vi[1] = f.vi[1];
00353 vi[2] = f.vi[2];
00354 vi[3] = f.vi[3];
00355
00356 return true;
00357 }
00358
00359 ON_Mesh::ON_Mesh()
00360 : m_packed_tex_rotate(0)
00361 , m_parent(0)
00362 , m_mesh_parameters(0)
00363 , m_invalid_count(0)
00364 , m_quad_count(0)
00365 , m_triangle_count(0)
00366 , m_mesh_is_closed(0)
00367 , m_mesh_is_manifold(0)
00368 , m_mesh_is_oriented(0)
00369 , m_mesh_is_solid(0)
00370 {
00371 m_top.m_mesh = this;
00372 m_srf_scale[0] = 0.0;
00373 m_srf_scale[1] = 0.0;
00374 m_kstat[0] = 0;
00375 m_kstat[1] = 0;
00376 m_kstat[2] = 0;
00377 m_kstat[3] = 0;
00378 InvalidateBoundingBoxes();
00379 m_partition = 0;
00380 m_hidden_count = 0;
00381 }
00382
00383
00384 ON_Mesh::ON_Mesh(
00385 int initial_facet_capacity,
00386 int initial_vertex_capacity,
00387 bool bHasVertexNormals,
00388 bool bHasTextureCoordinates
00389 )
00390 : m_V(initial_vertex_capacity)
00391 , m_F(initial_facet_capacity)
00392 , m_N(bHasVertexNormals?initial_vertex_capacity:0)
00393 , m_T(bHasTextureCoordinates?initial_vertex_capacity:0)
00394 , m_packed_tex_rotate(0)
00395 , m_parent(0)
00396 , m_mesh_parameters(0)
00397 , m_invalid_count(0)
00398 , m_quad_count(0)
00399 , m_triangle_count(0)
00400 , m_mesh_is_closed(0)
00401 , m_mesh_is_manifold(0)
00402 , m_mesh_is_oriented(0)
00403 , m_mesh_is_solid(0)
00404 {
00405 m_top.m_mesh = this;
00406 m_srf_scale[0] = 0.0;
00407 m_srf_scale[1] = 0.0;
00408 m_kstat[0] = 0;
00409 m_kstat[1] = 0;
00410 m_kstat[2] = 0;
00411 m_kstat[3] = 0;
00412 InvalidateBoundingBoxes();
00413 m_partition = 0;
00414 m_hidden_count = 0;
00415 }
00416
00417 ON_Mesh::ON_Mesh( const ON_Mesh& src )
00418 : m_packed_tex_rotate(0)
00419 , m_parent(0)
00420 , m_mesh_parameters(0)
00421 , m_invalid_count(0)
00422 , m_quad_count(0)
00423 , m_triangle_count(0)
00424 , m_mesh_is_closed(0)
00425 , m_mesh_is_manifold(0)
00426 , m_mesh_is_oriented(0)
00427 , m_mesh_is_solid(0)
00428 {
00429
00430
00431 m_top.m_mesh = this;
00432 m_srf_scale[0] = 0.0;
00433 m_srf_scale[1] = 0.0;
00434
00435 m_kstat[0] = 0;
00436 m_kstat[1] = 0;
00437 m_kstat[2] = 0;
00438 m_kstat[3] = 0;
00439 InvalidateBoundingBoxes();
00440 m_partition = 0;
00441 m_hidden_count = 0;
00442 ON_Mesh::operator=(src);
00443 }
00444
00445
00446 unsigned int ON_Mesh::SizeOf() const
00447 {
00448 unsigned int sz = ON_Geometry::SizeOf();
00449 sz += m_V.SizeOfArray();
00450 sz += m_F.SizeOfArray();
00451 sz += m_N.SizeOfArray();
00452 sz += m_FN.SizeOfArray();
00453 sz += m_T.SizeOfArray();
00454 sz += m_S.SizeOfArray();
00455 sz += m_K.SizeOfArray();
00456 sz += m_C.SizeOfArray();
00457 sz += m_top.m_topv_map.SizeOfArray();
00458 sz += m_top.m_topv.SizeOfArray();
00459 sz += m_top.m_tope.SizeOfArray();
00460 sz += m_top.m_topf.SizeOfArray();
00461 return sz;
00462 }
00463
00464 ON__UINT32 ON_Mesh::DataCRC(ON__UINT32 current_remainder) const
00465 {
00466 const ON_3fPoint* p = m_V.Array();
00467 current_remainder = ON_CRC32(current_remainder,m_V.Count()*sizeof(p[0]),p);
00468 current_remainder = ON_CRC32(current_remainder,m_F.Count()*sizeof(ON_MeshFace),m_F.Array());
00469 const ON_3fVector* v = m_N.Array();
00470 current_remainder = ON_CRC32(current_remainder,m_N.Count()*sizeof(v[0]),v);
00471 return current_remainder;
00472 }
00473
00474 ON_Mesh& ON_Mesh::operator=( const ON_Mesh& src )
00475 {
00476 if ( this != &src )
00477 {
00478 Destroy();
00479 ON_Geometry::operator=(src);
00480
00481 m_V = src.m_V;
00482 m_F = src.m_F;
00483 m_N = src.m_N;
00484 m_FN = src.m_FN;
00485 m_T = src.m_T;
00486 m_TC = src.m_TC;
00487 m_S = src.m_S;
00488 m_H = src.m_H;
00489 m_hidden_count = src.m_hidden_count;
00490
00491 m_Ctag = src.m_Ctag;
00492 m_Ttag = src.m_Ttag;
00493 m_packed_tex_domain[0] = src.m_packed_tex_domain[0];
00494 m_packed_tex_domain[1] = src.m_packed_tex_domain[1];
00495 m_srf_domain[0] = src.m_srf_domain[0];
00496 m_srf_domain[1] = src.m_srf_domain[1];
00497 m_srf_scale[0] = src.m_srf_scale[0];
00498 m_srf_scale[1] = src.m_srf_scale[1];
00499 m_packed_tex_rotate = src.m_packed_tex_rotate;
00500
00501 m_K = src.m_K;
00502 m_C = src.m_C;
00503
00504 m_parent = src.m_parent;
00505
00506
00507 if ( m_mesh_parameters ) {
00508 delete m_mesh_parameters;
00509 m_mesh_parameters = 0;
00510 }
00511 if ( src.m_mesh_parameters )
00512 m_mesh_parameters = new ON_MeshParameters(*src.m_mesh_parameters);
00513
00514 m_invalid_count = src.m_invalid_count;
00515 m_quad_count = src.m_quad_count;
00516 m_triangle_count = src.m_triangle_count;
00517
00518 m_mesh_is_closed = src.m_mesh_is_closed;
00519 m_mesh_is_manifold = src.m_mesh_is_manifold;
00520 m_mesh_is_oriented = src.m_mesh_is_oriented;
00521 m_mesh_is_solid = src.m_mesh_is_solid;
00522
00523 memcpy(m_vbox,src.m_vbox,sizeof(m_vbox));
00524 memcpy(m_nbox,src.m_nbox,sizeof(m_nbox));
00525 memcpy(m_tbox,src.m_tbox,sizeof(m_tbox));
00526
00527 int i;
00528 for ( i = 0; i < 4; i++ ) {
00529 if ( m_kstat[i] )
00530 {
00531 delete m_kstat[i];
00532 m_kstat[i] = 0;
00533 }
00534 if ( src.m_kstat[i] )
00535 {
00536 m_kstat[i] = new ON_MeshCurvatureStats(*src.m_kstat[i]);
00537 }
00538 }
00539
00540
00541
00542
00543
00544 }
00545 return *this;
00546 }
00547
00548 ON_Mesh::~ON_Mesh()
00549 {
00550 Destroy();
00551 m_top.m_mesh = 0;
00552 }
00553
00554 void ON_Mesh::MemoryRelocate()
00555 {
00556
00557 m_top.m_mesh = this;
00558 }
00559
00560 void ON_Mesh::Destroy()
00561 {
00562 PurgeUserData();
00563 DestroyRuntimeCache( true );
00564 m_Ttag.Default();
00565 m_Ctag.Default();
00566 m_V.Destroy();
00567 m_F.Destroy();
00568 m_N.Destroy();
00569 m_FN.Destroy();
00570 m_T.Destroy();
00571 m_TC.Destroy();
00572 m_S.Destroy();
00573 m_K.Destroy();
00574 m_C.Destroy();
00575 }
00576
00577 void ON_Mesh::EmergencyDestroy()
00578 {
00579 DestroyRuntimeCache( false );
00580 m_V.EmergencyDestroy();
00581 m_F.EmergencyDestroy();
00582 m_N.EmergencyDestroy();
00583 m_FN.EmergencyDestroy();
00584 m_T.EmergencyDestroy();
00585 m_TC.EmergencyDestroy();
00586 m_S.EmergencyDestroy();
00587 m_K.EmergencyDestroy();
00588 m_C.EmergencyDestroy();
00589 }
00590
00591 static bool ON_MeshIsNotValid(bool bSilentError)
00592 {
00593 return bSilentError ? false : ON_IsNotValid();
00594 }
00595
00596 ON_BOOL32 ON_Mesh::IsValid( ON_TextLog* text_logx ) const
00597 {
00598
00599
00600 const ON__INT_PTR lowbit = 1;
00601 const ON__INT_PTR hightbits = ~lowbit;
00602 bool bSilentError = ( 0 != (lowbit & ((ON__INT_PTR)text_logx)) );
00603 ON_TextLog* text_log = (ON_TextLog*)(((ON__INT_PTR)text_logx) & hightbits);
00604
00605 const int facet_count = FaceCount();
00606 const int vertex_count = VertexCount();
00607 int fi, vi;
00608
00609 if (facet_count < 1)
00610 {
00611 if ( text_log )
00612 {
00613 text_log->Print("ON_Mesh.m_F.Count() < 1 (should be at least 1).\n");
00614 }
00615 return ON_MeshIsNotValid(bSilentError);
00616 }
00617
00618 if ( vertex_count < 3 )
00619 {
00620 if ( text_log )
00621 {
00622 text_log->Print("ON_Mesh.m_V.Count() < 3 (should be at least 3).\n");
00623 }
00624 return ON_MeshIsNotValid(bSilentError);
00625 }
00626
00627 if ( m_N.Count() > 0 && m_N.Count() != vertex_count )
00628 {
00629 if ( text_log )
00630 {
00631 text_log->Print("ON_Mesh.m_N.Count() = %d (should be 0 or %d=vertex_count).\n",
00632 m_N.Count(),vertex_count);
00633 }
00634 return ON_MeshIsNotValid(bSilentError);
00635 }
00636
00637 if ( m_T.Count() > 0 && m_T.Count() != vertex_count )
00638 {
00639 if ( text_log )
00640 {
00641 text_log->Print("ON_Mesh.m_T.Count() = %d (should be 0 or %d=vertex_count).\n",
00642 m_T.Count(),vertex_count);
00643 }
00644 return ON_MeshIsNotValid(bSilentError);
00645 }
00646
00647 if ( m_S.Count() > 0 && m_S.Count() != vertex_count )
00648 {
00649 if ( text_log )
00650 {
00651 text_log->Print("ON_Mesh.m_S.Count() = %d (should be 0 or %d=vertex_count).\n",
00652 m_S.Count(),vertex_count);
00653 }
00654 return ON_MeshIsNotValid(bSilentError);
00655 }
00656
00657 if ( HasVertexNormals() )
00658 {
00659 float x;
00660 for ( vi = 0; vi < vertex_count; vi++ ) {
00661 x = m_N[vi][0]*m_N[vi][0] + m_N[vi][1]*m_N[vi][1] + m_N[vi][2]*m_N[vi][2];
00662 if ( x < 0.985 || x > 1.015 )
00663 {
00664 if ( text_log )
00665 {
00666 text_log->Print("ON_Mesh.m_N[%d] is not a unit vector (length = %g).\n",vi,sqrt(x));
00667 }
00668 return ON_MeshIsNotValid(bSilentError);
00669 }
00670 }
00671 }
00672
00673
00674
00675 int i;
00676 for ( i = 0; i < 3; i++ )
00677 {
00678 if ( !ON_IsValid( m_vbox[0][i] ) || !ON_IsValid( m_vbox[1][i] ) )
00679 {
00680 if ( text_log )
00681 {
00682 text_log->Print("ON_Mesh.m_vbox is not finite. Check for invalid vertices\n");
00683 }
00684 return ON_MeshIsNotValid(bSilentError);
00685 }
00686 }
00687
00688 const ON_3dPoint* dV = 0;
00689 while ( HasDoublePrecisionVertices() )
00690 {
00691 bool bValidDoubles = DoublePrecisionVerticesAreValid();
00692 if ( bValidDoubles )
00693 dV = DoublePrecisionVertices().Array();
00694 bool bValidFloats = SinglePrecisionVerticesAreValid();
00695 bool bSynchronized = HasSynchronizedDoubleAndSinglePrecisionVertices();
00696 if ( bSynchronized && bValidDoubles && bValidFloats )
00697 break;
00698
00699 if ( !bSynchronized )
00700 {
00701 if ( text_log )
00702 {
00703 text_log->Print("Single and double precision vertices are not synchronized.\n");
00704 }
00705 return ON_MeshIsNotValid(bSilentError);
00706 }
00707
00708 if ( !bValidDoubles )
00709 {
00710 if ( text_log )
00711 {
00712 text_log->Print("Double precision vertices appear to be ok but are not marked as valid\n");
00713 }
00714 return ON_MeshIsNotValid(bSilentError);
00715 }
00716
00717 if ( !bValidFloats )
00718 {
00719 if ( text_log )
00720 {
00721 text_log->Print("Single precision vertices appear to be ok but are not marked as valid\n");
00722 }
00723 return ON_MeshIsNotValid(bSilentError);
00724 }
00725
00726
00727 break;
00728 }
00729
00730 if ( 0 != dV )
00731 {
00732 for ( fi = 0; fi < facet_count; fi++ )
00733 {
00734 if ( !m_F[fi].IsValid( vertex_count, dV ) )
00735 {
00736 if ( text_log )
00737 {
00738 if ( !m_F[fi].IsValid( vertex_count) )
00739 text_log->Print("ON_Mesh.m_F[%d].vi[] has invalid vertex indices.\n",fi);
00740 else
00741 text_log->Print("ON_Mesh.m_F[%d] has degenerate double precision vertex locations.\n",fi);
00742 }
00743 return ON_MeshIsNotValid(bSilentError);
00744 }
00745 }
00746 }
00747 else
00748 {
00749
00750 for ( fi = 0; fi < facet_count; fi++ )
00751 {
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770 if ( !m_F[fi].IsValid( vertex_count ) )
00771 {
00772 if ( text_log )
00773 text_log->Print("ON_Mesh.m_F[%d].vi[] has invalid vertex indices.\n",fi);
00774 return ON_MeshIsNotValid(bSilentError);
00775 }
00776 }
00777 }
00778
00779
00780 return true;
00781 }
00782
00783 void ON_Mesh::Dump( ON_TextLog& dump ) const
00784 {
00785 const int half_max = 8;
00786
00787 const int fcount = m_F.Count();
00788 int i;
00789 const int vcount = m_V.Count();
00790 ON_3dPoint p, q;
00791
00792 bool bDoubles = vcount > 0
00793 && HasDoublePrecisionVertices()
00794 && HasSynchronizedDoubleAndSinglePrecisionVertices();
00795
00796 dump.Print("ON_Mesh: vertex count = %d facet count = %d\n", m_V.Count(), m_F.Count() );
00797 dump.Print("double precision: %s\n",bDoubles?"true":"false");
00798 dump.Print("vertex normals: %s\n",HasVertexNormals()?"true":"false");
00799 dump.Print("face normals: %s\n",HasFaceNormals()?"true":"false");
00800 dump.Print("srf parameters: %s\n",HasSurfaceParameters()?"true":"false");
00801 dump.Print("tex coords: %s\n",HasTextureCoordinates()?"true":"false");
00802 dump.Print("vertex kappa: %s\n",HasPrincipalCurvatures()?"true":"false");
00803 dump.Print("vertex colors: %s\n",HasVertexColors()?"true":"false");
00804 dump.Print("m_Ctag:\n"); dump.PushIndent(); m_Ctag.Dump(dump); dump.PopIndent();
00805 dump.Print("m_packed_tex_rotate: %s\n",m_packed_tex_rotate?"true":"false");
00806 dump.Print("m_packed_tex_domain: (%g,%g)x(%g,%g)\n",
00807 m_packed_tex_domain[0][0],m_packed_tex_domain[0][1],
00808 m_packed_tex_domain[1][0],m_packed_tex_domain[1][1]);
00809 dump.Print("m_srf_domain: (%g,%g)x(%g,%g)\n",m_srf_domain[0][0],m_srf_domain[0][1],m_srf_domain[1][0],m_srf_domain[1][1]);
00810 dump.Print("m_srf_scale: %g,%g\n",m_srf_scale[0],m_srf_scale[0]);
00811 dump.Print("m_Ttag:\n"); dump.PushIndent(); m_Ttag.Dump(dump); dump.PopIndent();
00812
00813 dump.PushIndent();
00814
00815 dump.Print("%d mesh vertices:\n",m_V.Count());
00816 {
00817 dump.PushIndent();
00818 const ON_3dPoint* D = 0;
00819 if ( bDoubles )
00820 {
00821 D = DoublePrecisionVertices().Array();
00822 }
00823 for (i = 0; i < vcount; i++)
00824 {
00825 if ( i == half_max && 2*half_max < vcount )
00826 {
00827 dump.Print("...\n");
00828 i = vcount-half_max;
00829 }
00830 else
00831 {
00832 p = m_V[i];
00833 if ( 0 != D )
00834 {
00835 q = D[i];
00836 dump.Print("m_V[%d] = (%.17g,%.17g,%.17g) D = (%.17g,%.17g,%.17g)\n",
00837 i,
00838 p.x,p.y,p.z,
00839 q.x,q.y,q.z
00840 );
00841 }
00842 else
00843 {
00844 dump.Print("m_V[%d] = (%g,%g,%g)\n",i,p.x,p.y,p.z);
00845 }
00846 }
00847 }
00848 dump.PopIndent();
00849 }
00850
00851 if ( HasVertexNormals() )
00852 {
00853 dump.Print("%d mesh vertex normals:\n",m_N.Count());
00854 {
00855 dump.PushIndent();
00856 for (i = 0; i < vcount; i++)
00857 {
00858 if ( i == half_max && 2*half_max < vcount )
00859 {
00860 dump.Print("...\n");
00861 i = vcount-half_max;
00862 }
00863 else
00864 {
00865 p = m_N[i];
00866 dump.Print("m_N[%d] = (%g,%g,%g)\n",i,p.x,p.y,p.z);
00867 }
00868 }
00869 dump.PopIndent();
00870 }
00871 }
00872
00873 if ( HasTextureCoordinates() )
00874 {
00875 dump.Print("%d mesh vertex texture coordinates:\n",m_T.Count());
00876 {
00877 dump.PushIndent();
00878 for (i = 0; i < vcount; i++)
00879 {
00880 if ( i == half_max && 2*half_max < vcount )
00881 {
00882 dump.Print("...\n");
00883 i = vcount-half_max;
00884 }
00885 else
00886 {
00887 ON_2fPoint tp = m_T[i];
00888 p.x = tp.x;
00889 p.y = tp.y;
00890 dump.Print("m_T[%d] = (%g,%g)\n",i,p.x,p.y);
00891 }
00892 }
00893 dump.PopIndent();
00894 }
00895 }
00896
00897
00898 if ( HasSurfaceParameters() )
00899 {
00900 dump.Print("%d mesh vertex surface parameters:\n",m_S.Count());
00901 {
00902 dump.PushIndent();
00903 for (i = 0; i < vcount; i++)
00904 {
00905 if ( i == half_max && 2*half_max < vcount )
00906 {
00907 dump.Print("...\n");
00908 i = vcount-half_max;
00909 }
00910 else
00911 {
00912 ON_2dPoint srfuv = m_S[i];
00913 dump.Print("m_S[%d] = (%g,%g)\n",i,srfuv.x,srfuv.y);
00914 }
00915 }
00916 dump.PopIndent();
00917 }
00918 }
00919
00920 dump.Print("%d mesh faces:\n",m_F.Count());
00921 {
00922 dump.PushIndent();
00923 for (i = 0; i < fcount; i++)
00924 {
00925 if ( i == half_max && 2*half_max < fcount )
00926 {
00927 dump.Print("...\n");
00928 i = fcount-half_max;
00929 }
00930 else if ( m_F[i].vi[2] == m_F[i].vi[3] )
00931 dump.Print("m_F[%d].vi = (%d,%d,%d)\n",i,m_F[i].vi[0],m_F[i].vi[1],m_F[i].vi[2]);
00932 else
00933 dump.Print("m_F[%d].vi = (%d,%d,%d,%d)\n",i,m_F[i].vi[0],m_F[i].vi[1],m_F[i].vi[2],m_F[i].vi[3]);
00934 }
00935 dump.PopIndent();
00936 }
00937
00938 if ( HasFaceNormals() )
00939 {
00940 dump.Print("%d mesh face normals:\n",m_FN.Count());
00941 {
00942 dump.PushIndent();
00943 for (i = 0; i < fcount; i++)
00944 {
00945 if ( i == half_max && 2*half_max < fcount )
00946 {
00947 dump.Print("...\n");
00948 i = fcount-half_max;
00949 }
00950 else
00951 {
00952 p = m_FN[i];
00953 dump.Print("m_FN[%d] = (%g,%g,%g)\n",i,p.x,p.y,p.z);
00954 }
00955 }
00956 dump.PopIndent();
00957 }
00958 }
00959
00960
00961 dump.PopIndent();
00962 }
00963
00964
00965 bool ON_Mesh::WriteFaceArray( int vcount, int fcount, ON_BinaryArchive& file ) const
00966 {
00967 unsigned char cvi[4];
00968 unsigned short svi[4];
00969 const int* vi;
00970 int i_size = 0;
00971 if ( vcount < 256 ) {
00972 i_size = 1;
00973 }
00974 else if (vcount < 65536 ) {
00975 i_size = 2;
00976 }
00977 else {
00978 i_size = 4;
00979 }
00980
00981 bool rc = file.WriteInt( i_size );
00982 int i;
00983 switch(i_size) {
00984 case 1:
00985 for ( i = 0; i < fcount && rc ; i++ ) {
00986 vi = m_F[i].vi;
00987 cvi[0] = (unsigned char)vi[0];
00988 cvi[1] = (unsigned char)vi[1];
00989 cvi[2] = (unsigned char)vi[2];
00990 cvi[3] = (unsigned char)vi[3];
00991 rc = file.WriteChar( 4, cvi );
00992 }
00993 break;
00994 case 2:
00995 for ( i = 0; i < fcount && rc ; i++ ) {
00996 vi = m_F[i].vi;
00997 svi[0] = (unsigned short)vi[0];
00998 svi[1] = (unsigned short)vi[1];
00999 svi[2] = (unsigned short)vi[2];
01000 svi[3] = (unsigned short)vi[3];
01001 rc = file.WriteShort( 4, svi );
01002 }
01003 break;
01004 case 4:
01005 for ( i = 0; i < fcount && rc ; i++ ) {
01006 rc = file.WriteInt( 4, m_F[i].vi );
01007 }
01008 break;
01009 }
01010
01011 return rc;
01012 }
01013
01014 bool ON_Mesh::ReadFaceArray( int vcount, int fcount, ON_BinaryArchive& file )
01015 {
01016 unsigned char cvi[4];
01017 unsigned short svi[4];
01018 unsigned int* vi;
01019 int i_size = 0;
01020
01021 if ( m_F.Capacity() < fcount )
01022 m_F.SetCapacity(fcount);
01023 bool rc = file.ReadInt( &i_size );
01024 int i = 0;
01025 switch(i_size) {
01026 case 1:
01027 for ( i = 0; i < fcount && rc ; i++ ) {
01028 rc = file.ReadChar( 4, cvi );
01029 vi = (unsigned int*)m_F[i].vi;
01030 vi[0] = cvi[0];
01031 vi[1] = cvi[1];
01032 vi[2] = cvi[2];
01033 vi[3] = cvi[3];
01034 }
01035 break;
01036 case 2:
01037 for ( i = 0; i < fcount && rc ; i++ ) {
01038 rc = file.ReadShort( 4, svi );
01039 vi = (unsigned int*)m_F[i].vi;
01040 vi[0] = svi[0];
01041 vi[1] = svi[1];
01042 vi[2] = svi[2];
01043 vi[3] = svi[3];
01044 }
01045 break;
01046 case 4:
01047 for ( i = 0; i < fcount && rc ; i++ ) {
01048 rc = file.ReadInt( 4, m_F[i].vi );
01049 }
01050 break;
01051 }
01052 m_F.SetCount(i);
01053
01054 return rc;
01055 }
01056
01057
01058 bool ON_Mesh::Write_1( ON_BinaryArchive& file ) const
01059 {
01060
01061
01062 bool rc = file.WriteArray( m_V );
01063 if (rc) rc = file.WriteArray( m_N );
01064 if (rc) rc = file.WriteArray( m_T );
01065 if (rc) rc = file.WriteArray( m_K );
01066 if (rc) rc = file.WriteArray( m_C );
01067
01068 return rc;
01069 }
01070
01071 bool ON_Mesh::Read_1( ON_BinaryArchive& file )
01072 {
01073
01074
01075 bool rc = file.ReadArray( m_V );
01076 if (rc) rc = file.ReadArray( m_N );
01077 if (rc) rc = file.ReadArray( m_T );
01078 if (rc) rc = file.ReadArray( m_K );
01079 if (rc) rc = file.ReadArray( m_C );
01080
01081 return rc;
01082 }
01083
01084 bool ON_Mesh::Write_2( int Vcount, ON_BinaryArchive& file ) const
01085 {
01086
01087 const ON::endian e = file.Endian();
01088
01089 bool rc = true;
01090
01091 if ( Vcount > m_V.Count() )
01092 return false;
01093
01094 if ( Vcount > 0 )
01095 {
01096 const int Ncount = (m_V.Count() == m_N.Count()) ? Vcount : 0;
01097 const int Tcount = (m_V.Count() == m_T.Count()) ? Vcount : 0;
01098 const int Kcount = (m_V.Count() == m_K.Count()) ? Vcount : 0;
01099 const int Ccount = (m_V.Count() == m_C.Count()) ? Vcount : 0;
01100
01101 if ( e == ON::big_endian )
01102 {
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114 file.ToggleByteOrder( Vcount*3, 4, m_V.Array(), (void*)m_V.Array() );
01115 file.ToggleByteOrder( Ncount*3, 4, m_N.Array(), (void*)m_N.Array() );
01116 file.ToggleByteOrder( Tcount*2, 4, m_T.Array(), (void*)m_T.Array() );
01117 file.ToggleByteOrder( Kcount*2, 8, m_K.Array(), (void*)m_K.Array() );
01118 file.ToggleByteOrder( Ccount, 4, m_C.Array(), (void*)m_C.Array() );
01119 }
01120 if (rc) rc = file.WriteCompressedBuffer( Vcount*sizeof(ON_3fPoint), m_V.Array() );
01121 if (rc) rc = file.WriteCompressedBuffer( Ncount*sizeof(ON_3fVector), m_N.Array() );
01122 if (rc) rc = file.WriteCompressedBuffer( Tcount*sizeof(ON_2fPoint), m_T.Array() );
01123 if (rc) rc = file.WriteCompressedBuffer( Kcount*sizeof(ON_SurfaceCurvature),m_K.Array() );
01124 if (rc) rc = file.WriteCompressedBuffer( Ccount*sizeof(ON_Color), m_C.Array() );
01125 if ( e == ON::big_endian )
01126 {
01127
01128
01129
01130 file.ToggleByteOrder( Vcount*3, 4, m_V.Array(), (void*)m_V.Array() );
01131 file.ToggleByteOrder( Ncount*3, 4, m_N.Array(), (void*)m_N.Array() );
01132 file.ToggleByteOrder( Tcount*2, 4, m_T.Array(), (void*)m_T.Array() );
01133 file.ToggleByteOrder( Kcount*2, 8, m_K.Array(), (void*)m_K.Array() );
01134 file.ToggleByteOrder( Ccount, 4, m_C.Array(), (void*)m_C.Array() );
01135 }
01136 }
01137
01138 return rc;
01139 }
01140
01141 bool ON_Mesh::Read_2( int vcount, ON_BinaryArchive& file )
01142 {
01143
01144 const ON::endian e = file.Endian();
01145
01146 bool rc = true;
01147
01148
01149 if ( vcount > 0 )
01150 {
01151 size_t sz = 0;
01152 int bFailedCRC;
01153
01154 sz = 0;
01155 if (rc) rc = file.ReadCompressedBufferSize( &sz );
01156 if (rc && sz)
01157 {
01158 if ( sz == vcount*sizeof(m_V[0]) )
01159 {
01160 m_V.SetCapacity(vcount);
01161 if (rc) rc = file.ReadCompressedBuffer( sz,m_V.Array(),&bFailedCRC);
01162 if (rc) m_V.SetCount(vcount);
01163 }
01164 else
01165 {
01166 ON_ERROR("ON_Mesh::Read - compressed vertex point buffer size is wrong.");
01167 rc = false;
01168 }
01169 }
01170
01171 sz = 0;
01172 if (rc) rc = file.ReadCompressedBufferSize( &sz );
01173 if (rc && sz)
01174 {
01175 if ( sz == vcount*sizeof(m_N[0]) )
01176 {
01177 m_N.SetCapacity(vcount);
01178 if (rc) rc = file.ReadCompressedBuffer( sz,m_N.Array(),&bFailedCRC );
01179 if (rc) m_N.SetCount(vcount);
01180 }
01181 else
01182 {
01183 ON_ERROR("ON_Mesh::Read - compressed vertex normal buffer size is wrong.");
01184 rc = false;
01185 }
01186 }
01187
01188 sz = 0;
01189 if (rc) rc = file.ReadCompressedBufferSize( &sz );
01190 if (rc && sz)
01191 {
01192 if ( sz == vcount*sizeof(m_T[0]) )
01193 {
01194 m_T.SetCapacity(vcount);
01195 if (rc) rc = file.ReadCompressedBuffer( sz,m_T.Array(),&bFailedCRC );
01196 if (rc) m_T.SetCount(vcount);
01197 }
01198 else
01199 {
01200 ON_ERROR("ON_Mesh::Read - compressed texture coordinate buffer size is wrong.");
01201 rc = false;
01202 }
01203 }
01204
01205 sz = 0;
01206 if (rc) rc = file.ReadCompressedBufferSize( &sz );
01207 if (rc && sz)
01208 {
01209 if ( sz == vcount*sizeof(m_K[0]) )
01210 {
01211 m_K.SetCapacity(vcount);
01212 if (rc) rc = file.ReadCompressedBuffer( sz,m_K.Array(),&bFailedCRC );
01213 if (rc) m_K.SetCount(vcount);
01214 }
01215 else
01216 {
01217 ON_ERROR("ON_Mesh::Read - compressed vertex curvature buffer size is wrong.");
01218 rc = false;
01219 }
01220 }
01221
01222 sz = 0;
01223 if (rc) rc = file.ReadCompressedBufferSize( &sz );
01224 if (rc && sz)
01225 {
01226 if ( sz == vcount*sizeof(m_C[0]) )
01227 {
01228 m_C.SetCapacity(vcount);
01229 if (rc) rc = file.ReadCompressedBuffer( sz,m_C.Array(),&bFailedCRC );
01230 if (rc) m_C.SetCount(vcount);
01231 }
01232 else
01233 {
01234 ON_ERROR("ON_Mesh::Read - compressed vertex color buffer size is wrong.");
01235 rc = false;
01236 }
01237 }
01238
01239 if ( e == ON::big_endian )
01240 {
01241
01242
01243
01244
01245
01246
01247
01248 file.ToggleByteOrder( m_V.Count()*3, 4, m_V.Array(), (void*)m_V.Array() );
01249 file.ToggleByteOrder( m_N.Count()*3, 4, m_N.Array(), (void*)m_N.Array() );
01250 file.ToggleByteOrder( m_T.Count()*2, 4, m_T.Array(), (void*)m_T.Array() );
01251 file.ToggleByteOrder( m_K.Count()*2, 8, m_K.Array(), (void*)m_K.Array() );
01252 file.ToggleByteOrder( m_C.Count()*3, 4, m_C.Array(), (void*)m_C.Array() );
01253 }
01254 }
01255
01256 return rc;
01257 }
01258
01259
01260 ON_BOOL32 ON_Mesh::Write( ON_BinaryArchive& file ) const
01261 {
01262 int i;
01263
01264
01265 const int major_version = 3;
01266 bool rc = file.Write3dmChunkVersion(major_version,5);
01267
01268 const int vcount = VertexCount();
01269 const int fcount = FaceCount();
01270
01271 if (rc) rc = file.WriteInt( vcount );
01272 if (rc) rc = file.WriteInt( fcount );
01273 if (rc) rc = file.WriteInterval( m_packed_tex_domain[0] );
01274 if (rc) rc = file.WriteInterval( m_packed_tex_domain[1] );
01275 if (rc) rc = file.WriteInterval( m_srf_domain[0] );
01276 if (rc) rc = file.WriteInterval( m_srf_domain[1] );
01277 if (rc) rc = file.WriteDouble( 2, m_srf_scale );
01278 if (rc) rc = file.WriteFloat( 6, &m_vbox[0][0] );
01279 if (rc) rc = file.WriteFloat( 6, &m_nbox[0][0] );
01280 if (rc) rc = file.WriteFloat( 4, &m_tbox[0][0] );
01281
01282
01283 i = -1;
01284 switch( m_mesh_is_closed )
01285 {
01286 case 0:
01287 i = -1;
01288 break;
01289 case 1:
01290 i = 1;
01291 break;
01292 case 2:
01293 i = 0;
01294 break;
01295 }
01296 if (rc) rc = file.WriteInt( i );
01297
01298 unsigned char b = m_mesh_parameters ? 1 : 0;
01299 if (rc) rc = file.WriteChar(b);
01300 if (rc && b) {
01301 if (rc) rc = file.BeginWrite3dmChunk( TCODE_ANONYMOUS_CHUNK, 0 );
01302 if (rc) {
01303 rc = m_mesh_parameters->Write(file);
01304 if ( !file.EndWrite3dmChunk() )
01305 rc = false;
01306 }
01307 }
01308
01309 for ( i = 0; rc && i < 4; i++ ) {
01310 b = m_kstat[i] ? 1 : 0;
01311 rc = file.WriteChar(b);
01312 if (b) {
01313 rc = file.BeginWrite3dmChunk( TCODE_ANONYMOUS_CHUNK, 0 );
01314 if (rc) {
01315 rc = m_kstat[i]->Write(file);
01316 if ( !file.EndWrite3dmChunk() )
01317 rc = false;
01318 }
01319 }
01320 }
01321
01322 if (rc) rc = WriteFaceArray( vcount, fcount, file );
01323
01324 if (rc) {
01325
01326
01327
01328
01329
01330 rc = Write_2(vcount,file);
01331
01332
01333 }
01334
01335
01336 i = m_packed_tex_rotate ? 1 : 0;
01337 if (rc) rc = file.WriteInt( i );
01338
01339
01340 if (rc) rc = file.WriteUuid( m_Ttag.m_mapping_id );
01341
01342
01343 if ( rc && vcount > 0 )
01344 {
01345
01346
01347 const int Scount = (vcount == m_S.Count()) ? m_S.Count() : 0;
01348 const ON::endian e = file.Endian();
01349 if ( e == ON::big_endian )
01350 {
01351 file.ToggleByteOrder( Scount*2, 8, m_S.Array(), (void*)m_S.Array() );
01352 }
01353 if (rc) rc = file.WriteCompressedBuffer( Scount*sizeof(ON_2dPoint),m_S.Array() );
01354 if ( e == ON::big_endian )
01355 {
01356 file.ToggleByteOrder( Scount*2, 8, m_S.Array(), (void*)m_S.Array() );
01357 }
01358 }
01359
01360
01361 if (rc) rc = m_Ttag.Write(file);
01362
01363
01364 if (rc) rc = file.WriteChar( m_mesh_is_manifold );
01365 if (rc) rc = file.WriteChar( m_mesh_is_oriented );
01366 if (rc) rc = file.WriteChar( m_mesh_is_solid );
01367
01368
01369 return rc;
01370 }
01371
01377
01379 static const ON_UUID obsolete_default_srfp_mapping_id = { 0xb988a6c2, 0x61a6, 0x45a7, { 0xaa, 0xee, 0x9a, 0xed, 0x7e, 0xf4, 0xe3, 0x16 } };
01380
01381
01382 ON_BOOL32 ON_TextureMapping::Write(
01383 ON_BinaryArchive& file
01384 ) const
01385 {
01386 bool rc = file.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,1);
01387 if (rc)
01388 {
01389
01390 for(;;)
01391 {
01392 rc = file.WriteUuid( m_mapping_id);
01393 if (!rc) break;
01394
01395 rc = file.WriteInt( m_type );
01396 if (!rc) break;
01397
01398 rc = file.WriteInt( m_projection );
01399 if (!rc) break;
01400
01401 rc = file.WriteXform( m_Pxyz );
01402 if (!rc) break;
01403
01404
01405 rc = file.WriteXform( m_uvw );
01406 if (!rc) break;
01407
01408 rc = file.WriteString(m_mapping_name);
01409 if (!rc) break;
01410
01411 rc = file.WriteObject(m_mapping_primitive);
01412 if (!rc) break;
01413
01414
01415 rc = file.WriteInt(m_texture_space);
01416 if (!rc) break;
01417
01418 rc = file.WriteBool(m_bCapped);
01419 if (!rc) break;
01420
01421 break;
01422 }
01423
01424 if ( !file.EndWrite3dmChunk() )
01425 rc = false;
01426 }
01427
01428 return rc;
01429 }
01430
01431
01432 ON_BOOL32 ON_TextureMapping::Read(
01433 ON_BinaryArchive& file
01434 )
01435 {
01436 Default();
01437
01438 int major_version = 0;
01439 int minor_version = 0;
01440 int i;
01441
01442 bool rc = file.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
01443 if (rc)
01444 {
01445 if ( 1 == major_version )
01446 {
01447
01448
01449 for(;;)
01450 {
01451 rc = file.ReadUuid( m_mapping_id );
01452 if (!rc) break;
01453 if ( 0 == ON_UuidCompare(&obsolete_default_srfp_mapping_id,&m_mapping_id) )
01454 m_mapping_id = ON_nil_uuid;
01455
01456 rc = file.ReadInt( &i );
01457 if (!rc) break;
01458 m_type = TypeFromInt(i);
01459
01460 rc = file.ReadInt( &i );
01461 if (!rc) break;
01462 m_projection = ProjectionFromInt(i);
01463
01464 rc = file.ReadXform( m_Pxyz );
01465 if (!rc) break;
01466
01467 m_Pxyz.GetSurfaceNormalXform(m_Nxyz);
01468
01469 rc = file.ReadXform( m_uvw );
01470 if (!rc) break;
01471
01472 rc = file.ReadString(m_mapping_name);
01473 if (!rc) break;
01474
01475 rc = (file.ReadObject(&m_mapping_primitive) >= 0);
01476 if (!rc) break;
01477
01478 if ( minor_version >= 1 )
01479 {
01480 rc = file.ReadInt(&i);
01481 if (!rc) break;
01482 m_texture_space = TextureSpaceFromInt(i);
01483
01484 rc = file.ReadBool(&m_bCapped);
01485 if (!rc) break;
01486 }
01487
01488 break;
01489 }
01490 }
01491
01492 if ( !file.EndRead3dmChunk() )
01493 rc = false;
01494 }
01495
01496 return rc;
01497 }
01498
01499 static
01500 void GetSurfaceParametersHelper( const ON_Mesh& mesh,
01501 double tex_x, double tex_y,
01502 double* srf_s, double* srf_t )
01503 {
01504
01505
01506 double tex_s, tex_t;
01507
01508 if ( mesh.m_packed_tex_rotate )
01509 {
01510
01511 tex_s = mesh.m_packed_tex_domain[1].NormalizedParameterAt( tex_y );
01512 tex_t = 1.0 - mesh.m_packed_tex_domain[0].NormalizedParameterAt( tex_x );
01513 }
01514 else
01515 {
01516
01517 tex_s = mesh.m_packed_tex_domain[0].NormalizedParameterAt( tex_x );
01518 tex_t = mesh.m_packed_tex_domain[1].NormalizedParameterAt( tex_y );
01519 }
01520 *srf_s = mesh.m_srf_domain[0].ParameterAt(tex_s);
01521 *srf_t = mesh.m_srf_domain[1].ParameterAt(tex_t);
01522 }
01523
01524
01525 ON_BOOL32 ON_Mesh::Read( ON_BinaryArchive& file )
01526 {
01527 Destroy();
01528
01529 int major_version = 0;
01530 int minor_version = 0;
01531 int i;
01532 bool rc = file.Read3dmChunkVersion(&major_version,&minor_version);
01533
01534 if (rc && (1 == major_version || 3 == major_version) )
01535 {
01536 int vcount = 0;
01537 int fcount = 0;
01538
01539 if (rc) rc = file.ReadInt( &vcount );
01540 if (rc) rc = file.ReadInt( &fcount );
01541 if (rc) rc = file.ReadInterval( m_packed_tex_domain[0] );
01542 if (rc) rc = file.ReadInterval( m_packed_tex_domain[1] );
01543 if (rc) rc = file.ReadInterval( m_srf_domain[0] );
01544 if (rc) rc = file.ReadInterval( m_srf_domain[1] );
01545 if (rc) rc = file.ReadDouble( 2, m_srf_scale );
01546 if (rc) rc = file.ReadFloat( 6, &m_vbox[0][0] );
01547 if (rc) rc = file.ReadFloat( 6, &m_nbox[0][0] );
01548 if (rc) rc = file.ReadFloat( 4, &m_tbox[0][0] );
01549
01550
01551 i = -1;
01552 if (rc) rc = file.ReadInt( &i );
01553 if (rc)
01554 {
01555 switch(i)
01556 {
01557 case 0:
01558 SetClosed(0);
01559 break;
01560 case 1:
01561 SetClosed(1);
01562 break;
01563 case 2:
01564 SetClosed(1);
01565 break;
01566 }
01567 }
01568
01569 unsigned char b = 0;
01570 ON__UINT32 tcode=0;
01571 ON__INT64 big_value=0;
01572 if (rc) rc = file.ReadChar(&b);
01573 if (rc && b)
01574 {
01575
01576 rc = file.BeginRead3dmBigChunk(&tcode,&big_value);
01577 if (rc)
01578 {
01579 if ( TCODE_ANONYMOUS_CHUNK == tcode )
01580 {
01581 m_mesh_parameters = new ON_MeshParameters();
01582 rc = m_mesh_parameters->Read( file );
01583 }
01584 else
01585 rc = false;
01586 if (!file.EndRead3dmChunk())
01587 rc = false;
01588 }
01589 }
01590
01591 for ( i = 0; rc && i < 4; i++ )
01592 {
01593 rc = file.ReadChar(&b);
01594 if (rc && b)
01595 {
01596
01597 tcode = 0;
01598 big_value = 0;
01599 rc = file.BeginRead3dmBigChunk( &tcode, &big_value );
01600 if (rc)
01601 {
01602 if ( TCODE_ANONYMOUS_CHUNK == tcode )
01603 {
01604 m_kstat[i] = new ON_MeshCurvatureStats();
01605 rc = m_kstat[i]->Read(file);
01606 }
01607 else
01608 rc = false;
01609 if ( !file.EndRead3dmChunk() )
01610 rc = false;
01611 }
01612 }
01613 }
01614
01615 if (rc) rc = ReadFaceArray( vcount, fcount, file );
01616
01617 if (rc) {
01618 if ( major_version==1) {
01619 rc = Read_1(file);
01620 }
01621 else if ( major_version == 3 ) {
01622 rc = Read_2(vcount,file);
01623 }
01624 else
01625 rc = false;
01626 }
01627
01628 if ( minor_version >= 2 )
01629 {
01630 int b = m_packed_tex_rotate;
01631 if (rc) rc = file.ReadInt( &b );
01632 m_packed_tex_rotate = b?true:false;
01633 }
01634
01635 if ( 3 == major_version )
01636 {
01637 if ( minor_version >= 3 )
01638 {
01639
01640 if (rc) rc = file.ReadUuid( m_Ttag.m_mapping_id );
01641
01642
01643 if ( rc && vcount > 0 )
01644 {
01645 size_t sz = 0;
01646 ON_BOOL32 bFailedCRC=false;
01647 if (rc) rc = file.ReadCompressedBufferSize( &sz );
01648 if (rc && sz)
01649 {
01650 if ( sz == vcount*sizeof(ON_2dPoint) )
01651 {
01652 m_S.SetCapacity(vcount);
01653 if (rc) rc = file.ReadCompressedBuffer( sz, m_S.Array(), &bFailedCRC );
01654 if (rc) m_S.SetCount(vcount);
01655 if ( ON::big_endian == file.Endian() )
01656 {
01657 file.ToggleByteOrder( m_S.Count()*2, 8, m_S.Array(), (void*)m_S.Array() );
01658 }
01659 }
01660 else
01661 {
01662 ON_ERROR("ON_Mesh::Read - surface parameter buffer size is wrong.");
01663 if ( rc
01664 && file.ArchiveOpenNURBSVersion() <= 201011049
01665 && 0 == (sz % sizeof(ON_2dPoint))
01666 && sz >= sizeof(ON_2dPoint)
01667 )
01668 {
01669
01670
01671
01672
01673
01674
01675 int Scount = (int)(sz / sizeof(ON_2dPoint));
01676 m_S.SetCapacity(Scount);
01677 rc = file.ReadCompressedBuffer( sz, m_S.Array(), &bFailedCRC );
01678 m_S.Destroy();
01679 }
01680 else
01681 {
01682 rc = false;
01683 }
01684 }
01685 }
01686 }
01687 if ( minor_version >= 4 && file.ArchiveOpenNURBSVersion() >= 200606010 )
01688 {
01689 if (rc) rc = m_Ttag.Read(file);
01690 if ( minor_version >= 5 )
01691 {
01692 if (rc) rc = file.ReadChar( &m_mesh_is_manifold );
01693 if (rc) rc = file.ReadChar( &m_mesh_is_oriented );
01694 if (rc) rc = file.ReadChar( &m_mesh_is_solid );
01695 }
01696 }
01697 }
01698 }
01699
01700 if ( 0 == m_S.Count()
01701 && m_V.Count() > 0
01702 && HasTextureCoordinates()
01703 && m_srf_domain[0].IsIncreasing()
01704 && m_srf_domain[1].IsIncreasing()
01705 && m_packed_tex_domain[0].IsInterval()
01706 && m_packed_tex_domain[1].IsInterval()
01707 && 0 == m_Ttag.m_mapping_crc
01708 && ON_UuidIsNil(m_Ttag.m_mapping_id)
01709 )
01710 {
01711
01712
01713
01714 m_S.SetCapacity(vcount);
01715 m_S.SetCount(0);
01716 ON_2dPoint sp;
01717 ON_2fPoint tc;
01718 for ( i = 0; i < vcount; i++)
01719 {
01720 tc = m_T[i];
01721 sp.x = tc.x;
01722 sp.y = tc.y;
01723 GetSurfaceParametersHelper(*this,sp.x,sp.y,&sp.x,&sp.y);
01724 m_S.Append(sp);
01725 }
01726 m_Ttag.SetDefaultSurfaceParameterMappingTag();
01727 }
01728 }
01729
01730 return rc;
01731 }
01732
01733 ON::object_type ON_Mesh::ObjectType() const
01734 {
01735 return ON::mesh_object;
01736 }
01737
01738 int ON_Mesh::Dimension() const
01739 {
01740 return 3;
01741 }
01742
01743 #if defined(ON_COMPILER_MSC)
01744
01745
01746
01747
01748
01749
01750 #pragma warning( push )
01751 #pragma warning( disable : 4189 )
01752 #endif
01753
01754 float ON_FloatFloor(double x)
01755 {
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777 const double e = (x < 0.0) ? (1.0 + 0.5*ON_FLOAT_EPSILON) : (1.0 - 0.5*ON_FLOAT_EPSILON);
01778 float f;
01779 f = (float)(e*x);
01780 return f;
01781 }
01782
01783 float ON_FloatCeil(double x)
01784 {
01785 float f = (x != 0.0) ? (-ON_FloatFloor(-x)) : ((float)x);
01786 return f;
01787 }
01788
01789 ON_BOOL32 ON_Mesh::GetBBox(
01790 double* boxmin,
01791 double* boxmax,
01792 ON_BOOL32 bGrowBox
01793 ) const
01794 {
01795 ON_BOOL32 rc = false;
01796 const int facet_count = FaceCount();
01797 const int vertex_count = VertexCount();
01798 if ( facet_count >= 1 && vertex_count >= 3 )
01799 {
01800 ON_BoundingBox vbox;
01801 if ( m_vbox[0][0] > m_vbox[1][0] )
01802 {
01803
01804 float* fbbox[2] = {const_cast<float*>(&m_vbox[0][0]),const_cast<float*>(&m_vbox[1][0])};
01805 while ( HasDoublePrecisionVertices() && DoublePrecisionVerticesAreValid() )
01806 {
01807 double dbbox[2][3];
01808 const ON_3dPointArray& dV = DoublePrecisionVertices();
01809 rc = ON_GetPointListBoundingBox(
01810 3, 0, vertex_count, 3, &dV[0].x,
01811 &dbbox[0][0], &dbbox[1][0],
01812 false
01813 );
01814 if (!rc)
01815 break;
01816
01817
01818 fbbox[0][0] = ON_FloatFloor(dbbox[0][0]);
01819 fbbox[0][1] = ON_FloatFloor(dbbox[0][1]);
01820 fbbox[0][2] = ON_FloatFloor(dbbox[0][2]);
01821 fbbox[1][0] = ON_FloatCeil(dbbox[1][0]);
01822 fbbox[1][1] = ON_FloatCeil(dbbox[1][1]);
01823 fbbox[1][2] = ON_FloatCeil(dbbox[1][2]);
01824
01825
01826 if ( SinglePrecisionVerticesAreValid() )
01827 {
01828 ON_GetPointListBoundingBox(
01829 3, 0, vertex_count, 3, &m_V[0].x,
01830 &fbbox[0][0], &fbbox[1][0],
01831 true
01832 );
01833 }
01834 break;
01835 }
01836
01837 if (!rc)
01838 {
01839 rc = ON_GetPointListBoundingBox( 3, 0,
01840 vertex_count, 3, &m_V[0].x,
01841 fbbox[0],fbbox[1],
01842 false
01843 );
01844 }
01845 }
01846 else
01847 {
01848 rc = true;
01849 }
01850
01851 if ( rc )
01852 {
01853 vbox.m_min.x = m_vbox[0][0];
01854 vbox.m_min.y = m_vbox[0][1];
01855 vbox.m_min.z = m_vbox[0][2];
01856 vbox.m_max.x = m_vbox[1][0];
01857 vbox.m_max.y = m_vbox[1][1];
01858 vbox.m_max.z = m_vbox[1][2];
01859 rc = vbox.IsValid();
01860 if (rc)
01861 {
01862 if ( bGrowBox )
01863 {
01864 vbox.Union( ON_BoundingBox(boxmin,boxmax) );
01865 }
01866
01867 boxmin[0] = vbox.m_min.x;
01868 boxmin[1] = vbox.m_min.y;
01869 boxmin[2] = vbox.m_min.z;
01870
01871 boxmax[0] = vbox.m_max.x;
01872 boxmax[1] = vbox.m_max.y;
01873 boxmax[2] = vbox.m_max.z;
01874 }
01875 #if defined(ON_DEBUG) && !defined(ON_COMPILER_GNU)
01876
01877 else
01878 {
01879 int breakpoint_here_for_bad_vbox=0;
01880 }
01881 #endif
01882 }
01883 }
01884 return rc;
01885 }
01886
01887 #if defined(ON_COMPILER_MSC)
01888 #pragma warning( pop )
01889 #endif
01890
01891 bool ON_Mesh::IsDeformable() const
01892 {
01893 return true;
01894 }
01895
01896 bool ON_Mesh::MakeDeformable()
01897 {
01898 return true;
01899 }
01900
01901 ON_BOOL32 ON_Mesh::Transform(
01902 const ON_Xform& xform
01903 )
01904 {
01905 const bool bIsValid_fV = SinglePrecisionVerticesAreValid();
01906 const bool bIsValid_dV = DoublePrecisionVerticesAreValid();
01907 const bool bSyncheddV = bIsValid_fV && bIsValid_dV && HasSynchronizedDoubleAndSinglePrecisionVertices();
01908 TransformUserData(xform);
01909 DestroyTree();
01910
01911 double d = xform.Determinant();
01912 const int vertex_count = VertexCount();
01913 bool rc = false;
01914 if ( bSyncheddV )
01915 {
01916
01917
01918 UpdateSinglePrecisionVertices();
01919 rc = true;
01920 }
01921 else
01922 {
01923 rc = ON_TransformPointList( 3, false, vertex_count, 3, &m_V[0][0], xform );
01924 }
01925
01926 if ( rc )
01927 {
01928 m_Ctag.Transform(xform);
01929 m_Ttag.Transform(xform);
01930 int tci, tccnt = m_TC.Count();
01931 for ( tci = 0; tci < tccnt; tci++ )
01932 {
01933 m_TC[tci].m_tag.Transform(xform);
01934 }
01935 }
01936
01937 if ( rc && 0.0 == d )
01938 {
01939
01940 if ( HasVertexNormals() )
01941 {
01942 ComputeFaceNormals();
01943 ComputeVertexNormals();
01944 }
01945 else if ( HasFaceNormals() )
01946 {
01947 ComputeFaceNormals();
01948 }
01949 }
01950 else if ( rc )
01951 {
01952 if ( HasVertexNormals() )
01953 {
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966
01967
01968 ON_Xform N_xform;
01969 double d = xform.GetSurfaceNormalXform(N_xform);
01970 rc = ON_TransformVectorList( 3, vertex_count, 3, &m_N[0][0], N_xform )?true:false;
01971 if ( d < 0.0 )
01972 {
01973 FlipVertexNormals();
01974 }
01975 UnitizeVertexNormals();
01976 }
01977
01978 if ( rc && HasFaceNormals() )
01979 {
01980 ComputeFaceNormals();
01981 }
01982 }
01983
01984 if ( rc && HasPrincipalCurvatures() )
01985 {
01986 if ( fabs(fabs(d) - 1.0) > ON_SQRT_EPSILON )
01987 {
01988
01989 double scale = xform.m_xform[0][0];
01990 if ( 0.0 != scale && 0.0 != d
01991 && scale == xform.m_xform[1][1]
01992 && scale == xform.m_xform[2][2]
01993 && fabs(d - scale*scale*scale) <= d*ON_SQRT_EPSILON )
01994 {
01995
01996 const double ks = 1.0/scale;
01997 ON_SurfaceCurvature* sc = m_K.Array();
01998 int ki = m_K.Count();
01999 while ( ki-- )
02000 {
02001 sc->k1 *= ks;
02002 sc->k2 *= ks;
02003 sc++;
02004 }
02005
02006
02007 for ( int j = 0; j < 4; j++ )
02008 {
02009 if ( m_kstat[j] )
02010 m_kstat[j]->Set( m_kstat[j]->m_style,m_K.Count(),m_K.Array(),m_N.Array() );
02011 }
02012 }
02013 else
02014 {
02015 ON_ERROR("ON_Mesh::Transform() cannot apply this transform to curvatures.\n");
02016 rc = false;
02017 }
02018 }
02019 }
02020
02021 InvalidateVertexBoundingBox();
02022 InvalidateVertexNormalBoundingBox();
02023 if ( fabs(d) <= ON_ZERO_TOLERANCE )
02024 DestroyTopology();
02025
02026 if ( bIsValid_fV )
02027 SetSinglePrecisionVerticesAsValid();
02028 if ( bIsValid_dV )
02029 SetDoublePrecisionVerticesAsValid();
02030
02031 return rc;
02032 }
02033
02034 void ON_Mesh::DestroyRuntimeCache( bool bDelete )
02035 {
02036 int i;
02037
02038 DestroyTree(bDelete);
02039
02040 if (bDelete )
02041 {
02042 DestroyPartition();
02043 m_top.Destroy();
02044 DeleteMeshParameters();
02045 InvalidateCurvatureStats();
02046 }
02047 else
02048 {
02049
02050 m_top.EmergencyDestroy();
02051 }
02052
02053 InvalidateBoundingBoxes();
02054 m_partition = 0;
02055 m_mesh_parameters = 0;
02056 m_top.m_mesh = this;
02057 m_parent = 0;
02058
02059 m_mesh_is_closed = 0;
02060 m_mesh_is_manifold = 0;
02061 m_mesh_is_oriented = 0;
02062 m_mesh_is_solid = 0;
02063 for ( i = 0; i < 4; i++ )
02064 {
02065 m_kstat[i] = 0;
02066 }
02067 }
02068
02069 ON_BOOL32 ON_Mesh::SwapCoordinates(
02070 int i, int j
02071 )
02072 {
02073 if ( i == j )
02074 return true;
02075
02076 const bool bIsValid_fV = SinglePrecisionVerticesAreValid();
02077 const bool bIsValid_dV = DoublePrecisionVerticesAreValid();
02078
02079 const int vertex_count = VertexCount();
02080 ON_BOOL32 rc = ON_SwapPointListCoordinates( vertex_count, 3, &m_V[0][0], i, j );
02081 if ( rc && HasVertexNormals() ) {
02082 rc = ON_SwapPointListCoordinates( vertex_count, 3, &m_N[0][0], i, j );
02083 }
02084 if ( rc )
02085 {
02086 float x;
02087 if ( m_vbox[0][0] <= m_vbox[1][0] ) {
02088 x = m_vbox[0][i]; m_vbox[0][i] = m_vbox[0][j]; m_vbox[0][j] = x;
02089 x = m_vbox[1][i]; m_vbox[1][i] = m_vbox[1][j]; m_vbox[1][j] = x;
02090 }
02091 if ( m_nbox[0][0] <= m_nbox[1][0] ) {
02092 x = m_nbox[0][i]; m_nbox[0][i] = m_nbox[0][j]; m_nbox[0][j] = x;
02093 x = m_nbox[1][i]; m_nbox[1][i] = m_nbox[1][j]; m_nbox[1][j] = x;
02094 }
02095 }
02096
02097 if ( HasDoublePrecisionVertices() )
02098 {
02099 DoublePrecisionVertices().SwapCoordinates(i,j);
02100 if ( bIsValid_fV )
02101 SetSinglePrecisionVerticesAsValid();
02102 if ( bIsValid_dV )
02103 SetDoublePrecisionVerticesAsValid();
02104 }
02105
02106 return rc;
02107 }
02108
02109 void ON_Mesh::SetClosed(int b)
02110 {
02111
02112 char mesh_is_closed = 0;
02113 switch(b)
02114 {
02115 case 0:
02116 mesh_is_closed = 2;
02117 SetSolidOrientation(0);
02118 break;
02119 case 1:
02120
02121
02122 mesh_is_closed = 1;
02123 break;
02124 case 2:
02125 mesh_is_closed = 1;
02126
02127
02128 break;
02129 default:
02130 mesh_is_closed = 0;
02131 break;
02132 }
02133 if ( 0 == mesh_is_closed || m_mesh_is_closed != mesh_is_closed )
02134 {
02135 m_mesh_is_closed = mesh_is_closed;
02136 m_mesh_is_manifold = 0;
02137 m_mesh_is_oriented = 0;
02138 }
02139 }
02140
02141 void ON_Mesh::SetSolidOrientation(int solid_orientation)
02142 {
02143 switch(solid_orientation)
02144 {
02145 case -1:
02146 SetClosed(1);
02147 m_mesh_is_manifold = 1;
02148 m_mesh_is_oriented = 1;
02149 m_mesh_is_solid = 2;
02150 break;
02151
02152 case 0:
02153 m_mesh_is_solid = 3;
02154
02155
02156 break;
02157
02158 case 1:
02159 SetClosed(1);
02160 m_mesh_is_manifold = 1;
02161 m_mesh_is_oriented = 1;
02162 m_mesh_is_solid = 1;
02163 break;
02164
02165 default:
02166 m_mesh_is_solid = 0;
02167 break;
02168 }
02169 }
02170
02171
02172 static
02173 int ON_MeshIsManifold_CompareV( const void* a, const void* b )
02174 {
02175 return memcmp(a,b,sizeof(ON_3fPoint));
02176
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189
02190 }
02191
02192 static
02193 int ON_MeshGetVertexEdges_Compare2dex( const void* a, const void* b )
02194 {
02195 return ON_Compare2dex((const ON_2dex*)a,(const ON_2dex*)b);
02196 }
02197
02198 static
02199 int ON_MeshIsManifold_Compare3dex( const void* a, const void* b )
02200 {
02201 return ON_Compare3dex((const ON_3dex*)a,(const ON_3dex*)b);
02202 }
02203
02204
02205
02206
02207
02208
02209
02210
02211 int ON_Mesh::GetVertexEdges(
02212 int vertex_index_count,
02213 const int* vertex_index,
02214 bool bNoDuplicates,
02215 ON_SimpleArray<ON_2dex>& edges
02216 ) const
02217 {
02218
02219 const int edges_count0 = edges.Count();
02220
02221 const int mesh_vcount = m_V.Count();
02222
02223
02224
02225 const int mesh_fcount = m_F.Count();
02226
02227 if ( vertex_index_count <= 0 || 0 == vertex_index
02228 || mesh_fcount <= 0 || mesh_vcount < 3 )
02229 {
02230 return 0;
02231 }
02232
02233 int vei, efi, fvi, ei, fi, j, n, vi;
02234 const int* f_vi;
02235 ON_2dex edge_ends;
02236 const ON_MeshFace* f = m_F.Array();
02237
02238 if ( TopologyExists()
02239 && mesh_vcount == m_top.m_topv_map.Count()
02240 && m_top.m_tope.Count() > 0 )
02241 {
02242
02243 const int* topv_map = m_top.m_topv_map;
02244 const int top_vcount = m_top.m_topv.Count();
02245 const int top_ecount = m_top.m_tope.Count();
02246 int top_vi;
02247 for ( n = 0; n < vertex_index_count; n++ )
02248 {
02249 vi = vertex_index[n];
02250 if ( vi < 0 || vi >= mesh_vcount )
02251 continue;
02252 top_vi = topv_map[vi];
02253 if ( top_vi < 0 || top_vi > top_vcount )
02254 continue;
02255 edge_ends.i = vi;
02256 const ON_MeshTopologyVertex& v = m_top.m_topv[top_vi];
02257 for ( vei = 0; vei < v.m_tope_count; vei++ )
02258 {
02259 ei = v.m_topei[vei];
02260 if ( ei < 0 || ei >= top_ecount )
02261 continue;
02262 const ON_MeshTopologyEdge& e = m_top.m_tope[ei];
02263 for ( efi = 0; efi < e.m_topf_count; efi++ )
02264 {
02265 fi = e.m_topfi[efi];
02266 if ( fi < 0 || fi >= mesh_fcount )
02267 continue;
02268 f_vi = f[fi].vi;
02269 for ( fvi = 0; fvi < 4; fvi++ )
02270 {
02271 if ( f_vi[fvi] == vi )
02272 {
02273 j = f_vi[(fvi+3)%4];
02274 if ( j >= 0 && j < mesh_vcount && vi != j )
02275 {
02276 edge_ends.i = j;
02277 edge_ends.j = vi;
02278 edges.Append(edge_ends);
02279 }
02280 j = f_vi[ (2==fvi && f_vi[2]==f_vi[3]) ? 0 : ((fvi+1)%4) ];
02281 if ( j >= 0 && j < mesh_vcount && vi != j )
02282 {
02283 edge_ends.i = vi;
02284 edge_ends.j = j;
02285 edges.Append(edge_ends);
02286 }
02287 break;
02288 }
02289 }
02290 }
02291 }
02292 }
02293 }
02294 else
02295 {
02296
02297
02298
02299
02300
02301 ON_Workspace ws;
02302 for ( vi = 1; vi < vertex_index_count; vi++ )
02303 {
02304 if ( vertex_index[vi] < vertex_index[vi-1] )
02305 {
02306
02307 int* tmp = ws.GetIntMemory(vertex_index_count);
02308 memcpy(tmp,vertex_index,vertex_index_count*sizeof(tmp[0]));
02309 ON_SortIntArray(ON::quick_sort,tmp,vertex_index_count);
02310 vertex_index = tmp;
02311 break;
02312 }
02313 }
02314
02315
02316 for ( fi = 0; fi < mesh_fcount; fi++ )
02317 {
02318 f_vi = f[fi].vi;
02319 for ( fvi = 0; fvi < 4; fvi++ )
02320 {
02321 vi = f_vi[fvi];
02322 if ( ON_BinarySearchIntArray(vi,vertex_index,vertex_index_count) )
02323 {
02324
02325
02326 j = f_vi[(fvi+3)%4];
02327 if ( j >= 0 && j < mesh_vcount && vi != j )
02328 {
02329 edge_ends.i = j;
02330 edge_ends.j = vi;
02331 edges.Append(edge_ends);
02332 }
02333 j = f_vi[ (2==fvi && f_vi[2]==f_vi[3]) ? 0 : ((fvi+1)%4) ];
02334 if ( j >= 0 && j < mesh_vcount && vi != j )
02335 {
02336 edge_ends.i = vi;
02337 edge_ends.j = j;
02338 edges.Append(edge_ends);
02339 }
02340 }
02341 }
02342 }
02343 }
02344
02345 if ( bNoDuplicates && edges.Count() > edges_count0 )
02346 {
02347 for ( ei = edges_count0; ei < edges.Count(); ei++ )
02348 {
02349 edge_ends = edges[ei];
02350 if ( edge_ends.i > edge_ends.j )
02351 {
02352 j = edge_ends.i; edge_ends.i = edge_ends.j; edge_ends.j = j;
02353 }
02354 }
02355 ON_qsort( edges.Array() + edges_count0,
02356 edges.Count() - edges_count0,
02357 sizeof(edge_ends),
02358 ON_MeshGetVertexEdges_Compare2dex);
02359 edge_ends = edges[edges_count0];
02360 for ( ei = j = edges_count0+1; ei < edges.Count(); ei++ )
02361 {
02362 if ( ON_Compare2dex(&edge_ends,&edges[ei]) )
02363 {
02364 edge_ends = edges[ei];
02365 if ( j != ei )
02366 edges[j] = edge_ends;
02367 j++;
02368 }
02369 }
02370 edges.SetCount(j);
02371 }
02372
02373 return (edges.Count() - edges_count0);
02374 }
02375
02376 int ON_Mesh::GetMeshEdges(
02377 ON_SimpleArray<ON_2dex>& edges
02378 ) const
02379 {
02380 const int edges_count0 = edges.Count();
02381 int fi, ei, j, fvi;
02382 const int* f_vi;
02383 const ON_MeshFace* f = m_F.Array();
02384 const int mesh_vcount = m_V.Count();
02385 const int mesh_fcount = m_F.Count();
02386 edges.Reserve( edges_count0 + 4*mesh_fcount );
02387 ON_2dex e;
02388
02389
02390 for ( fi = 0; fi < mesh_fcount; fi++ )
02391 {
02392 f_vi = f[fi].vi;
02393 ei = f_vi[3];
02394 for ( fvi = 0; fvi < 4; fvi++ )
02395 {
02396 e.i = ei;
02397 ei = *f_vi++;
02398 e.j = ei;
02399 if ( e.i > e.j )
02400 {
02401 j = e.i; e.i = e.j; e.j = j;
02402 }
02403 if ( e.i != e.j && e.i >= 0 && e.j < mesh_vcount )
02404 {
02405 edges.Append(e);
02406 }
02407 }
02408 }
02409
02410
02411 if ( edges.Count() > edges_count0 )
02412 {
02413 ON_qsort( edges.Array() + edges_count0,
02414 edges.Count() - edges_count0,
02415 sizeof(e),
02416 ON_MeshGetVertexEdges_Compare2dex);
02417 e = edges[edges_count0];
02418 for ( ei = j = edges_count0+1; ei < edges.Count(); ei++ )
02419 {
02420 if ( ON_Compare2dex(&e,&edges[ei]) )
02421 {
02422 e = edges[ei];
02423 if ( j != ei )
02424 edges[j] = e;
02425 j++;
02426 }
02427 }
02428 edges.SetCount(j);
02429 }
02430
02431 return edges.Count() - edges_count0;
02432 }
02433
02434
02435 int ON_Mesh::SolidOrientation() const
02436 {
02437
02438 if ( m_mesh_is_solid <= 0 || m_mesh_is_solid > 3 )
02439 {
02440
02441
02442 IsSolid();
02443 }
02444
02445 switch(m_mesh_is_solid)
02446 {
02447 case 1:
02448 return 1;
02449 break;
02450
02451 case 2:
02452 return -1;
02453 break;
02454
02455 case 3:
02456 return 0;
02457 break;
02458 }
02459
02460 return 0;
02461 }
02462
02463
02464 bool ON_Mesh::IsSolid() const
02465 {
02466 return ( IsClosed() && IsManifold() && IsOriented() );
02467 }
02468
02469
02470 bool ON_Mesh::IsManifold(
02471 bool bTopologicalTest,
02472 bool* pbIsOriented,
02473 bool* pbHasBoundary
02474 ) const
02475 {
02476 bool bIsManifold = false;
02477 if ( pbIsOriented )
02478 *pbIsOriented = false;
02479 if ( pbHasBoundary )
02480 *pbHasBoundary = false;
02481 const int vcount = m_V.Count();
02482 const int fcount = m_F.Count();
02483 if ( vcount > 0 && fcount > 0 )
02484 {
02485 ON_Workspace ws;
02486 ON_3dex e;
02487 int i, j, ecount;
02488 const int* fvi;
02489 ON_3fPoint v0;
02490 const ON_3fPoint* v;
02491 const ON_MeshFace* f;
02492 int* vid = ws.GetIntMemory(vcount);
02493 ON_3dex* edge = (ON_3dex*)ws.GetMemory(4*fcount*sizeof(*edge));
02494
02495 if ( bTopologicalTest )
02496 {
02497
02498 ON_Sort(ON::quick_sort,vid,m_V.Array(),vcount,sizeof(m_V[0]),ON_MeshIsManifold_CompareV);
02499 ecount = 0;
02500 v = m_V.Array();
02501 ecount = 0;
02502 j = vcount;
02503 for ( i = 0; i < vcount; i = j)
02504 {
02505 v0 = v[vid[i]];
02506 vid[i] = ecount;
02507 for ( j = i+1; j < vcount; j++ )
02508 {
02509 if ( ON_MeshIsManifold_CompareV(&v,v+vid[j]) )
02510 {
02511 ecount++;
02512 break;
02513 }
02514 vid[j] = ecount;
02515 }
02516 }
02517 }
02518 else
02519 {
02520
02521 for ( i = 0; i < vcount; i++ )
02522 vid[i] = i;
02523 }
02524
02525
02526 f = m_F.Array();
02527 ecount = 0;
02528 for ( i = 0; i < fcount; i++ )
02529 {
02530 fvi = (f++)->vi;
02531 if ( fvi[0] >= 0 && fvi[0] < vcount
02532 && fvi[1] >= 0 && fvi[1] < vcount
02533 && fvi[2] >= 0 && fvi[2] < vcount
02534 && fvi[3] >= 0 && fvi[3] < vcount )
02535 {
02536
02537 j = ecount;
02538 e.i = vid[fvi[0]]; e.j = vid[fvi[1]];
02539 if ( 0 != (e.k = e.j - e.i) )
02540 {
02541 if ( e.k < 0 ) {e.k = e.i; e.i = e.j; e.j = e.k; e.k = 1;} else e.k = 0;
02542 edge[ecount++] = e;
02543 }
02544 e.i = vid[fvi[1]]; e.j = vid[fvi[2]];
02545 if ( 0 != (e.k = e.j - e.i) )
02546 {
02547 if ( e.k < 0 ) {e.k = e.i; e.i = e.j; e.j = e.k; e.k = 1;} else e.k = 0;
02548 edge[ecount++] = e;
02549 }
02550 e.i = vid[fvi[2]]; e.j = vid[fvi[3]];
02551 if ( 0 != (e.k = e.j - e.i) )
02552 {
02553 if ( e.k < 0 ) {e.k = e.i; e.i = e.j; e.j = e.k; e.k = 1;} else e.k = 0;
02554 edge[ecount++] = e;
02555 }
02556 e.i = vid[fvi[3]]; e.j = vid[fvi[0]];
02557 if ( 0 != (e.k = e.j - e.i) )
02558 {
02559 if ( e.k < 0 ) {e.k = e.i; e.i = e.j; e.j = e.k; e.k = 1;} else e.k = 0;
02560 edge[ecount++] = e;
02561 }
02562 if ( ecount < j+3 )
02563 ecount = j;
02564 }
02565 }
02566
02567 if ( ecount >= 4 )
02568 {
02569 bIsManifold = true;
02570 bool bIsOriented = (pbIsOriented) ? true : false;
02571 bool bHasBoundary = (pbHasBoundary) ? false : true;
02572 ON_qsort(edge,ecount,sizeof(edge[0]),ON_MeshIsManifold_Compare3dex);
02573
02574 i = 0;
02575 e = *edge;
02576 while ( --ecount )
02577 {
02578 edge++;
02579 if ( memcmp(&e,edge,2*sizeof(int)) )
02580 {
02581 if (!i)
02582 bHasBoundary = true;
02583 e = *edge;
02584 i = 0;
02585 }
02586 else
02587 {
02588 if ( i++ )
02589 {
02590 bIsManifold = false;
02591 break;
02592 }
02593 if ( e.k == edge->k )
02594 bIsOriented = false;
02595 }
02596 }
02597
02598 if ( bIsManifold )
02599 {
02600 if ( pbIsOriented )
02601 *pbIsOriented = bIsOriented;
02602 if ( pbHasBoundary )
02603 *pbHasBoundary = bHasBoundary;
02604 }
02605 }
02606 }
02607
02608 return bIsManifold;
02609 }
02610
02611 static void ON_hsort_3dex(ON_3dex *e, size_t nel)
02612 {
02613
02614 size_t i_end,k,i,j;
02615 ON_3dex e_tmp;
02616
02617 if (nel < 2) return;
02618 k = nel >> 1;
02619 i_end = nel-1;
02620 for (;;)
02621 {
02622 if (k)
02623 {
02624 --k;
02625 e_tmp = e[k];
02626 }
02627 else
02628 {
02629 e_tmp = e[i_end];
02630 e[i_end] = e[0];
02631 if (!(--i_end))
02632 {
02633 e[0] = e_tmp;
02634 break;
02635 }
02636 }
02637 i = k;
02638 j = (k<<1) + 1;
02639 while (j <= i_end)
02640 {
02641 if ( j < i_end && ( e[j].i < e[j + 1].i || (e[j].i == e[j + 1].i && (e[j].j < e[j + 1].j || ( e[j].j == e[j + 1].j && e[j].k < e[j + 1].k)) ) ) )
02642 j++;
02643
02644 if ( e_tmp.i < e[j].i || (e_tmp.i == e[j].i && (e_tmp.j < e[j].j || ( e_tmp.j == e[j].j && e_tmp.k < e[j].k) ) ) )
02645 {
02646 e[i] = e[j];
02647 i = j;
02648 j = (j<<1) + 1;
02649 }
02650 else
02651 j = i_end + 1;
02652 }
02653 e[i] = e_tmp;
02654 }
02655 }
02656
02657 static void ON_Mesh_SetClosedHelper(
02658 bool bClosedOnly,
02659 const ON_Mesh& mesh,
02660 const char& m_mesh_is_manifold,
02661 const char& m_mesh_is_oriented
02662 )
02663 {
02664
02665
02666
02667 int is_closed = 0;
02668 char is_manifold = 2;
02669 char is_oriented = 2;
02670 for (;;)
02671 {
02672 const int Vcount = mesh.m_V.Count();
02673 const int Fcount = mesh.m_F.Count();
02674 if ( Vcount < 3 || Fcount < 1 )
02675 {
02676 ON_ERROR("Mesh is not valid.");
02677 break;
02678 }
02679 if ( bClosedOnly && (Vcount < 4 || Fcount < 4) )
02680 {
02681
02682 break;
02683 }
02684
02685 int i, j;
02686 int Vidbuffer[256];
02687 int* Vid = mesh.GetVertexLocationIds(
02688 1,
02689 (Vcount*sizeof(*Vid) <= sizeof(Vidbuffer) ? &Vidbuffer[0] : 0),
02690 0
02691 );
02692 if ( 0 == Vid )
02693 {
02694 ON_ERROR("Mesh has corrupt vertex information.");
02695 bClosedOnly = false;
02696 break;
02697 }
02698
02699
02700 ON_3dex* E_list = (ON_3dex*)onmalloc(4*Fcount*sizeof(E_list[0]));
02701 ON_3dex E;
02702 int Vid0;
02703 const int* fvi;
02704 int E_count = 0;
02705 const ON_MeshFace* F = mesh.m_F.Array();
02706 for ( j = 0; j < Fcount; j++ )
02707 {
02708 fvi = F[j].vi;
02709 E.i = Vid[fvi[0]];
02710 Vid0 = E.j = Vid[fvi[1]];
02711 if ( E.i == E.j )
02712 break;
02713 if ( E.i > E.j )
02714 {
02715 i = E.i; E.i = E.j; E.j = i;
02716 E.k = 1;
02717 }
02718 else
02719 {
02720 E.k = 0;
02721 }
02722 E_list[E_count++] = E;
02723
02724 E.i = Vid0;
02725 Vid0 = E.j = Vid[fvi[2]];
02726 if ( E.i == E.j )
02727 break;
02728 if ( E.i > E.j )
02729 {
02730 i = E.i; E.i = E.j; E.j = i;
02731 E.k = 1;
02732 }
02733 else
02734 {
02735 E.k = 0;
02736 }
02737 E_list[E_count++] = E;
02738
02739 if ( fvi[2] != fvi[3] )
02740 {
02741
02742 E.i = Vid0;
02743 Vid0 = E.j = Vid[fvi[3]];
02744 if ( E.i == E.j )
02745 break;
02746 if ( E.i > E.j )
02747 {
02748 i = E.i; E.i = E.j; E.j = i;
02749 E.k = 1;
02750 }
02751 else
02752 {
02753 E.k = 0;
02754 }
02755 E_list[E_count++] = E;
02756 }
02757
02758 E.i = Vid0;
02759 E.j = Vid[fvi[0]];
02760 if ( E.i == E.j )
02761 break;
02762 if ( E.i > E.j )
02763 {
02764 i = E.i; E.i = E.j; E.j = i;
02765 E.k = 1;
02766 }
02767 else
02768 {
02769 E.k = 0;
02770 }
02771 E_list[E_count++] = E;
02772 }
02773 if ( Vid != &Vidbuffer[0] )
02774 onfree(Vid);
02775
02776 if ( E_count < 3 || j != Fcount )
02777 {
02778 ON_ERROR("Mesh is corrupt or collapsed");
02779 bClosedOnly = false;
02780 break;
02781 }
02782
02783
02784 ON_hsort_3dex(E_list,E_count);
02785
02786
02787
02788
02789 is_closed = (Fcount >= 4 && E_count >= 6) ? 1 : 0;
02790 is_oriented = 1;
02791 is_manifold = 1;
02792 i = -1;
02793 if ( !bClosedOnly || 1 == is_closed ) for ( i = 0; i < E_count; )
02794 {
02795 E = E_list[i];
02796 if ( ++i >= E_count )
02797 {
02798
02799 is_closed = 0;
02800 break;
02801 }
02802
02803 if ( E.i != E_list[i].i || E.j != E_list[i].j )
02804 {
02805
02806 is_closed = 0;
02807 if ( 2 == is_oriented && 2 == is_manifold )
02808 {
02809 bClosedOnly = false;
02810 break;
02811 }
02812 if ( bClosedOnly )
02813 break;
02814 continue;
02815 }
02816
02817 if ( E.k == E_list[i].k )
02818 {
02819
02820 is_oriented = 2;
02821 }
02822
02823 if ( ++i >= E_count || E.i != E_list[i].i || E.j != E_list[i].j )
02824 {
02825
02826 continue;
02827 }
02828
02829
02830 is_oriented = 2;
02831 is_manifold = 2;
02832 if ( 0 == is_closed )
02833 {
02834 bClosedOnly = false;
02835 break;
02836 }
02837
02838
02839 for ( i++; i < E_count; i++ )
02840 {
02841 if ( E.i != E_list[i].i || E.j != E_list[i].j )
02842 {
02843
02844 break;
02845 }
02846 }
02847 }
02848 if ( i >= E_count )
02849 {
02850
02851 bClosedOnly = false;
02852 }
02853
02854 onfree(E_list);
02855
02856 break;
02857 }
02858
02859 const_cast<ON_Mesh&>(mesh).SetClosed(is_closed);
02860 if ( !bClosedOnly )
02861 {
02862
02863 if ( 2 == is_manifold )
02864 is_oriented = 2;
02865 const_cast<char&>(m_mesh_is_manifold) = is_manifold;
02866 const_cast<char&>(m_mesh_is_oriented) = is_oriented;
02867 }
02868 }
02869
02870 bool ON_Mesh::IsClosed() const
02871 {
02872 if ( m_mesh_is_closed <= 0 || m_mesh_is_closed > 2)
02873 {
02874
02875 ON_Mesh_SetClosedHelper( true, *this, m_mesh_is_manifold, m_mesh_is_oriented );
02876 }
02877
02878 return (1 == m_mesh_is_closed);
02879 }
02880
02881 bool ON_Mesh::IsManifold() const
02882 {
02883 if ( m_mesh_is_manifold <= 0 || m_mesh_is_manifold > 2 )
02884 {
02885
02886 ON_Mesh_SetClosedHelper( false, *this, m_mesh_is_manifold, m_mesh_is_oriented );
02887 }
02888 return (1 == m_mesh_is_manifold);
02889 }
02890
02891 bool ON_Mesh::IsOriented() const
02892 {
02893 if ( m_mesh_is_oriented <= 0 || m_mesh_is_oriented > 2 )
02894 {
02895
02896 ON_Mesh_SetClosedHelper( false, *this, m_mesh_is_manifold, m_mesh_is_oriented );
02897 }
02898 return (1 == m_mesh_is_oriented);
02899 }
02900
02901
02902 bool ON_Mesh::SetVertex(
02903 int vertex_index,
02904 const ON_3dPoint& vertex_location
02905 )
02906 {
02907 bool rc = false;
02908 int vertex_count = m_V.Count();
02909 if ( vertex_index >= 0 && vertex_index <= vertex_count )
02910 {
02911 bool bIsValid_fV = false;
02912 if ( HasDoublePrecisionVertices() )
02913 {
02914 bIsValid_fV = SinglePrecisionVerticesAreValid();
02915 ON_3dPointArray& dV = DoublePrecisionVertices();
02916 if ( vertex_count == dV.Count() )
02917 {
02918 bool bIsValid_dV = DoublePrecisionVerticesAreValid();
02919 if ( vertex_index < vertex_count )
02920 dV[vertex_index] = vertex_location;
02921 else
02922 dV.Append(vertex_location);
02923 if ( bIsValid_dV )
02924 SetDoublePrecisionVerticesAsValid();
02925 }
02926 }
02927 if ( vertex_index < vertex_count )
02928 m_V[vertex_index] = vertex_location;
02929 else
02930 m_V.Append(vertex_location);
02931 if ( bIsValid_fV )
02932 SetSinglePrecisionVerticesAsValid();
02933 rc = true;
02934 }
02935 return rc;
02936 }
02937
02938 bool ON_Mesh::SetVertex(
02939 int vertex_index,
02940 const ON_3fPoint& vertex_location
02941 )
02942 {
02943 bool rc = false;
02944 int vertex_count = m_V.Count();
02945 if ( vertex_index >= 0 && vertex_index <= vertex_count )
02946 {
02947 bool bIsValid_fV = false;
02948 if ( HasDoublePrecisionVertices() )
02949 {
02950 bIsValid_fV = SinglePrecisionVerticesAreValid();
02951 ON_3dPointArray& dV = DoublePrecisionVertices();
02952 if ( vertex_count == dV.Count() )
02953 {
02954 bool bIsValid_dV = DoublePrecisionVerticesAreValid();
02955 if ( vertex_index < vertex_count )
02956 dV[vertex_index] = vertex_location;
02957 else
02958 dV.Append(vertex_location);
02959 if ( bIsValid_dV )
02960 SetDoublePrecisionVerticesAsValid();
02961 }
02962 }
02963 if ( vertex_index < vertex_count )
02964 m_V[vertex_index] = vertex_location;
02965 else
02966 m_V.Append(vertex_location);
02967 if ( bIsValid_fV )
02968 SetSinglePrecisionVerticesAsValid();
02969 rc = true;
02970 }
02971 return rc;
02972 }
02973
02974 bool ON_Mesh::SetVertexNormal(
02975 int vertex_index,
02976 const ON_3dVector& normal
02977 )
02978 {
02979 bool rc = false;
02980
02981 ON_3dVector unit_vector = normal;
02982 const bool bUnitVector = unit_vector.Unitize();
02983 ON_3fVector v((float)unit_vector.x, (float)unit_vector.y, (float)unit_vector.z);
02984 int normal_count = m_N.Count();
02985 if ( vertex_index >= 0 ) {
02986 if ( vertex_index < normal_count ) {
02987 m_N[vertex_index] = v;
02988 rc = bUnitVector;
02989 }
02990 else if ( vertex_index == normal_count ) {
02991 m_N.Append(v);
02992 rc = bUnitVector;
02993 }
02994 }
02995 return rc;
02996 }
02997
02998 bool ON_Mesh::SetVertexNormal(
02999 int vertex_index,
03000 const ON_3fVector& normal
03001 )
03002 {
03003 ON_3dVector v(normal.x,normal.y,normal.z);
03004 return SetVertexNormal(vertex_index,v);
03005 }
03006
03007 bool ON_Mesh::SetTextureCoord(
03008 int vertex_index,
03009 double s, double t
03010 )
03011 {
03012 ON_2fPoint tc((float)s,(float)t);
03013 bool rc = false;
03014 int vertex_count = m_T.Count();
03015 if ( vertex_index >= 0 ) {
03016 if ( vertex_index < vertex_count ) {
03017 m_T[vertex_index] = tc;
03018 rc = true;
03019 }
03020 else if ( vertex_index == vertex_count ) {
03021 m_T.Append(tc);
03022 rc = true;
03023 }
03024 }
03025 return rc;
03026 }
03027
03028
03029 bool ON_Mesh::SetTriangle(
03030 int face_index,
03031 int a,int b ,int c
03032 )
03033 {
03034 return SetQuad( face_index, a,b,c,c );
03035 }
03036
03037 bool ON_Mesh::SetQuad(
03038 int face_index,
03039 int a, int b, int c, int d
03040 )
03041 {
03042 bool rc = false;
03043 int face_count = m_F.Count();
03044 if ( face_index >= 0 ) {
03045 ON_MeshFace f;
03046 f.vi[0] = a;
03047 f.vi[1] = b;
03048 f.vi[2] = c;
03049 f.vi[3] = d;
03050 if ( face_index < face_count ) {
03051 m_F[face_index] = f;
03052 rc = true;
03053 }
03054 else if ( face_index == face_count ) {
03055 m_F.Append(f);
03056 rc = true;
03057 }
03058 if ( rc )
03059 rc = f.IsValid(m_V.Count());
03060 }
03061 return rc;
03062 }
03063
03064
03065
03066 int ON_Mesh::FaceCount() const
03067 {
03068 return m_F.Count();
03069 }
03070
03071 int ON_Mesh::QuadCount() const
03072 {
03073
03074 if ( m_quad_count < 0
03075 || m_triangle_count < 0
03076 || m_invalid_count < 0
03077 || m_quad_count + m_triangle_count + m_invalid_count != FaceCount() )
03078 {
03079 const_cast<ON_Mesh*>(this)->CountQuads();
03080 }
03081 return m_quad_count;
03082 }
03083
03084 int ON_Mesh::TriangleCount() const
03085 {
03086
03087 QuadCount();
03088 return m_triangle_count;
03089 }
03090
03091 int ON_Mesh::InvalidFaceCount() const
03092 {
03093
03094 QuadCount();
03095 return m_invalid_count;
03096 }
03097
03098
03099 int ON_Mesh::VertexCount() const
03100 {
03101 return m_V.Count();
03102 }
03103
03104 bool ON_Mesh::HasVertexNormals() const
03105 {
03106 const int vertex_count = VertexCount();
03107 return ( vertex_count > 0 && m_N.Count() == vertex_count ) ? true : false;
03108 }
03109
03110 bool ON_Mesh::HasFaceNormals() const
03111 {
03112 const int face_count = FaceCount();
03113 return ( face_count > 0 && m_FN.Count() == face_count ) ? true : false;
03114 }
03115
03116 bool ON_Mesh::HasTextureCoordinates() const
03117 {
03118 const int vertex_count = VertexCount();
03119 return ( vertex_count > 0 && m_T.Count() == vertex_count ) ? true : false;
03120 }
03121
03122 bool ON_Mesh::HasCachedTextureCoordinates() const
03123 {
03124 const int vertex_count = VertexCount();
03125 if (vertex_count > 0 )
03126 {
03127 int tci, tccount = m_TC.Count();
03128 for ( tci = 0; tci < tccount; tci++ )
03129 {
03130 if ( vertex_count == m_TC[tci].m_T.Count() )
03131 return true;
03132 }
03133 }
03134 return false;
03135 }
03136
03137 const ON_TextureCoordinates*
03138 ON_Mesh::CachedTextureCoordinates( const ON_UUID& mapping_id ) const
03139 {
03140 const int vertex_count = VertexCount();
03141 if (vertex_count > 0 )
03142 {
03143 const ON_TextureCoordinates* TC = m_TC.Array();
03144 int tci, tccount = m_TC.Count();
03145 for ( tci = 0; tci < tccount; tci++ )
03146 {
03147 if ( vertex_count == TC->m_T.Count()
03148 && mapping_id == TC->m_tag.m_mapping_id )
03149 {
03150 return TC;
03151 }
03152 }
03153 }
03154 return 0;
03155 }
03156
03157 bool ON_Mesh::HasSurfaceParameters() const
03158 {
03159 const int vertex_count = VertexCount();
03160 return ( vertex_count > 0 && m_S.Count() == vertex_count ) ? true : false;
03161 }
03162
03163 bool ON_Mesh::HasPrincipalCurvatures() const
03164 {
03165 const int vertex_count = VertexCount();
03166 return ( vertex_count > 0 && m_K.Count() == vertex_count ) ? true : false;
03167 }
03168
03169 bool ON_Mesh::HasVertexColors() const
03170 {
03171 const int vertex_count = VertexCount();
03172 return ( vertex_count > 0 && m_C.Count() == vertex_count ) ? true : false;
03173 }
03174
03175 void ON_Mesh::InvalidateBoundingBoxes()
03176 {
03177 InvalidateVertexBoundingBox();
03178 InvalidateVertexNormalBoundingBox();
03179 InvalidateTextureCoordinateBoundingBox();
03180 InvalidateCurvatureStats();
03181 }
03182
03183 void ON_Mesh::InvalidateVertexBoundingBox()
03184 {
03185 m_vbox[0][0] = m_vbox[0][1] = m_vbox[0][2] = 1.0;
03186 m_vbox[1][0] = m_vbox[1][1] = m_vbox[1][2] = -1.0;
03187 }
03188
03189 void ON_Mesh::InvalidateVertexNormalBoundingBox()
03190 {
03191 m_nbox[0][0] = m_nbox[0][1] = m_nbox[0][2] = 1.0;
03192 m_nbox[1][0] = m_nbox[1][1] = m_nbox[1][2] = -1.0;
03193 }
03194
03195 void ON_Mesh::InvalidateTextureCoordinateBoundingBox()
03196 {
03197 m_tbox[0][0] = m_tbox[0][1] = 1.0;
03198 m_tbox[1][0] = m_tbox[1][1] = -1.0;
03199 }
03200
03201 void ON_Mesh::InvalidateCurvatureStats()
03202 {
03203 int i;
03204 for ( i = 0; i < 4; i++ ) {
03205 if ( m_kstat[i] ) {
03206 delete m_kstat[i];
03207 m_kstat[i] = 0;
03208 }
03209 }
03210 }
03211
03212 bool ON_Mesh::UnitizeVertexNormals()
03213 {
03214 bool rc = HasVertexNormals();
03215 if ( rc ) {
03216 const int vertex_count = VertexCount();
03217 float* n = &m_N[0][0];
03218 int i;
03219 ON_3dVector N;
03220 for ( i = 0; i < vertex_count; i++ ) {
03221 N.x = n[0];
03222 N.y = n[1];
03223 N.z = n[2];
03224 if ( !N.Unitize() )
03225 rc = false;
03226 *n++ = (float)N.x;
03227 *n++ = (float)N.y;
03228 *n++ = (float)N.z;
03229 }
03230 }
03231 return rc;
03232 }
03233
03234 bool ON_Mesh::UnitizeFaceNormals()
03235 {
03236 bool rc = HasFaceNormals();
03237 if ( rc ) {
03238 const int face_count = FaceCount();
03239 float* n = &m_FN[0][0];
03240 int i;
03241 ON_3dVector N;
03242 for ( i = 0; i < face_count; i++ ) {
03243 N.x = n[0];
03244 N.y = n[1];
03245 N.z = n[2];
03246 if ( !N.Unitize() )
03247 rc = false;
03248 *n++ = (float)N.x;
03249 *n++ = (float)N.y;
03250 *n++ = (float)N.z;
03251 }
03252 }
03253 return rc;
03254 }
03255
03256
03257 bool ON_Mesh::GetCurvatureStats(
03258 ON::curvature_style kappa_style,
03259 ON_MeshCurvatureStats& stats
03260 ) const
03261 {
03262 bool rc = false;
03263 stats.Destroy();
03264 int ksi;
03265 switch ( kappa_style ) {
03266 case ON::gaussian_curvature:
03267 ksi = 0;
03268 break;
03269 case ON::mean_curvature:
03270 ksi = 1;
03271 break;
03272 case ON::min_curvature:
03273 ksi = 2;
03274 break;
03275 case ON::max_curvature:
03276 ksi = 3;
03277 break;
03278
03279
03280
03281
03282
03283
03284
03285
03286
03287 default:
03288 ksi = -1;
03289 break;
03290 }
03291 if ( ksi >= 0 && ksi <= 3 && HasPrincipalCurvatures() ) {
03292 ON_Mesh* p = (ON_Mesh*)this;
03293 if ( !m_kstat[ksi] ) {
03294 p->m_kstat[ksi] = new ON_MeshCurvatureStats();
03295 p->m_kstat[ksi]->Set( kappa_style, m_K.Count(), m_K.Array(), m_N.Array() );
03296 }
03297 if ( p->m_kstat[ksi] ) {
03298 stats = *p->m_kstat[ksi];
03299 rc = true;
03300 }
03301 }
03302 return rc;
03303 }
03304
03305 int ON_MeshTopology::WaitUntilReady(int sleep_value) const
03306 {
03307 return m_b32IsValid;
03308 }
03309
03310
03311 bool ON_Mesh::TopologyExists() const
03312 {
03313 return (1 == m_top.WaitUntilReady(0));
03314 }
03315
03316 const ON_MeshTopology& ON_Mesh::Topology() const
03317 {
03318 int top_b32IsValid = m_top.WaitUntilReady(-1);
03319
03320 if ( 0 == top_b32IsValid )
03321 {
03322 ON_MeshTopology& top = const_cast<ON_MeshTopology&>(m_top);
03323 top.m_mesh = this;
03324 top_b32IsValid = top.Create() ? 1 : 0;
03325 top.m_b32IsValid = top_b32IsValid;
03326 }
03327
03328 return m_top;
03329 }
03330
03331 void ON_Mesh::DestroyTopology()
03332 {
03333 m_top.Destroy();
03334 }
03335
03336 bool
03337 ON_MeshFace::IsTriangle() const
03338 {
03339 return vi[2]==vi[3];
03340 }
03341
03342 bool
03343 ON_MeshFace::IsQuad() const
03344 {
03345 return vi[2]!=vi[3];
03346 }
03347
03348 void
03349 ON_MeshFace::Flip()
03350 {
03351 int i;
03352 if ( vi[2] == vi[3] ) {
03353 i = vi[1];
03354 vi[1] = vi[2];
03355 vi[2] = i;
03356 vi[3] = i;
03357 }
03358 else {
03359 i = vi[1];
03360 vi[1] = vi[3];
03361 vi[3] = i;
03362 }
03363 }
03364
03365
03366
03367
03368
03369
03370
03371
03372
03373
03374
03375
03376
03377
03378
03379
03380
03381
03382
03383
03384
03385
03386
03387
03388
03389
03390
03391
03392
03393
03394
03395
03396
03397
03398
03399
03400
03401
03402
03403
03404 void
03405 ON_Mesh::Flip()
03406 {
03407 FlipFaceOrientation();
03408 FlipFaceNormals();
03409 FlipVertexNormals();
03410
03411
03412
03413 }
03414
03415 void
03416 ON_Mesh::FlipVertexNormals()
03417 {
03418 int i;
03419 const int vcount = VertexCount();
03420 if ( HasVertexNormals() ) {
03421 for ( i = 0; i < vcount; i++ ) {
03422 m_N[i].Reverse();
03423 }
03424 }
03425 }
03426
03427 void
03428 ON_Mesh::FlipFaceNormals()
03429 {
03430 int i;
03431 const int fcount = FaceCount();
03432 if ( HasFaceNormals() ) {
03433 for( i = 0; i < fcount; i++ ) {
03434 m_FN[i].Reverse();
03435 }
03436 }
03437 }
03438
03439 void
03440 ON_Mesh::FlipFaceOrientation()
03441 {
03442 int i;
03443 const int fcount = FaceCount();
03444 for( i = 0; i < fcount; i++ ) {
03445 m_F[i].Flip();
03446 }
03447 if ( fcount > 0 )
03448 DestroyTopology();
03449 }
03450
03451 bool ON_MeshFace::ComputeFaceNormal( const ON_3dPoint* dV, ON_3dVector& FN ) const
03452 {
03453 if ( 0 != dV )
03454 {
03455 ON_3dVector a = dV[vi[2]] - dV[vi[0]];
03456 ON_3dVector b = dV[vi[3]] - dV[vi[1]];
03457 FN = ON_CrossProduct( a, b );
03458 if ( FN.Unitize() )
03459 return true;
03460 }
03461
03462 FN.Zero();
03463 return false;
03464 }
03465
03466 bool ON_MeshFace::ComputeFaceNormal( const ON_3fPoint* fV, ON_3dVector& FN ) const
03467 {
03468 if ( 0 != fV )
03469 {
03470 ON_3dVector a = fV[vi[2]] - fV[vi[0]];
03471 ON_3dVector b = fV[vi[3]] - fV[vi[1]];
03472 FN = ON_CrossProduct( a, b );
03473 if ( FN.Unitize() )
03474 return true;
03475 }
03476
03477 FN.Zero();
03478 return false;
03479 }
03480
03481 bool
03482 ON_Mesh::ComputeFaceNormal( int fi )
03483 {
03484 if ( fi < 0 )
03485 return false;
03486 if ( fi >= m_F.Count() )
03487 return false;
03488 if ( m_FN.Count() != m_F.Count() )
03489 return false;
03490
03491 ON_3dVector FN;
03492 bool rc = ( HasDoublePrecisionVertices() )
03493 ? m_F[fi].ComputeFaceNormal(DoublePrecisionVertices().Array(),FN)
03494 : m_F[fi].ComputeFaceNormal(m_V.Array(),FN);
03495
03496 m_FN[fi] = FN;
03497
03498 return rc;
03499 }
03500
03501 bool
03502 ON_Mesh::ComputeFaceNormals()
03503 {
03504 bool rc = false;
03505 const int fcount = FaceCount();
03506 if ( fcount > 0 )
03507 {
03508 ON_3dVector a, b, n;
03509 int fi;
03510 const int* vi;
03511 if ( m_FN.Capacity() < fcount )
03512 m_FN.SetCapacity(fcount);
03513 m_FN.SetCount(0);
03514 rc = true;
03515 if ( HasDoublePrecisionVertices() && DoublePrecisionVerticesAreValid() )
03516 {
03517 const ON_3dPointArray& dV = DoublePrecisionVertices();
03518 for ( fi = 0; fi < fcount; fi++ ) {
03519 vi = m_F[fi].vi;
03520 a = dV[vi[2]] - dV[vi[0]];
03521 b = dV[vi[3]] - dV[vi[1]];
03522 n = ON_CrossProduct( a, b );
03523 n.Unitize();
03524 m_FN.Append(n);
03525 }
03526 }
03527 else
03528 {
03529 for ( fi = 0; fi < fcount; fi++ ) {
03530 vi = m_F[fi].vi;
03531 a = m_V[vi[2]] - m_V[vi[0]];
03532 b = m_V[vi[3]] - m_V[vi[1]];
03533 n = ON_CrossProduct( a, b );
03534 n.Unitize();
03535 m_FN.Append(n);
03536 }
03537 }
03538 }
03539 else
03540 {
03541 m_FN.Destroy();
03542 }
03543 return rc;
03544 }
03545
03546
03547
03548
03549
03550
03551
03552
03553
03554
03555
03556
03557
03558 bool ON_Mesh::CombineCoincidentVertices(
03559 const ON_3fVector tolerance,
03560 double cos_normal_angle
03561 )
03562 {
03563
03564
03565
03566
03567
03568
03569
03570
03571
03572
03573
03574
03575
03576
03577
03578
03579
03580
03581
03582 return false;
03583 }
03584
03585
03586 struct tagMESHPOINTS
03587 {
03588
03589
03590 const char* p0;
03591 ON_3fPoint* V;
03592 ON_2fPoint* T;
03593 ON_3fVector* N;
03594 ON_SurfaceCurvature* K;
03595 ON_Color* C;
03596 };
03597
03598 static int CompareMeshPoint(const void* a,const void* b,void* ptr)
03599 {
03600 float d;
03601 const struct tagMESHPOINTS * mp = (const struct tagMESHPOINTS *)ptr;
03602
03603
03604 int i = (int)(((const char*)a) - mp->p0);
03605 int j = (int)(((const char*)b) - mp->p0);
03606
03607 d = mp->V[j].x - mp->V[i].x;
03608 if ( d == 0.0f )
03609 {
03610 d = mp->V[j].y - mp->V[i].y;
03611 if ( d == 0.0f )
03612 {
03613 d = mp->V[j].z - mp->V[i].z;
03614
03615
03616
03617
03618 if ( d == 0.0f && 0 != mp->N)
03619 {
03620 d = mp->N[j].x - mp->N[i].x;
03621 if ( d == 0.0f )
03622 {
03623 d = mp->N[j].y - mp->N[i].y;
03624 if ( d == 0.0f )
03625 {
03626 d = mp->N[j].z - mp->N[i].z;
03627 }
03628 }
03629 }
03630
03631 if ( d == 0.0f && 0 != mp->T)
03632 {
03633 d = mp->T[j].x - mp->T[i].x;
03634 if ( d == 0.0f )
03635 {
03636 d = mp->T[j].y - mp->T[i].y;
03637 }
03638 }
03639
03640 if ( d == 0.0f && 0 != mp->C )
03641 {
03642 int u = ((int)mp->C[j])-((int)mp->C[i]);
03643 if ( u < 0 )
03644 d = -1.0f;
03645 else if ( u > 0 )
03646 d = 1.0f;
03647 }
03648
03649 if ( d == 0.0f && 0 != mp->K )
03650 {
03651 double dk = mp->K[j].k1 - mp->K[i].k1;
03652 if ( dk < 0.0 )
03653 d = -1.0;
03654 else if ( dk > 0.0 )
03655 d = 1.0;
03656 else
03657 {
03658 dk = mp->K[j].k2 - mp->K[i].k2;
03659 if ( dk < 0.0 )
03660 d = -1.0;
03661 else if ( dk > 0.0 )
03662 d = 1.0;
03663 }
03664 }
03665 }
03666 }
03667
03668 if ( d < 0.0f )
03669 return -1;
03670 if ( d > 0.0f )
03671 return 1;
03672 return 0;
03673 }
03674
03675 bool ON_Mesh::CombineIdenticalVertices(
03676 bool bIgnoreVertexNormals,
03677 bool bIgnoreTextureCoordinates
03678 )
03679 {
03680
03681 bool rc = false;
03682 ON_Mesh& mesh = *this;
03683
03684 int vertex_count = mesh.VertexCount();
03685 if ( vertex_count > 0 )
03686 {
03687 ON_SimpleArray<int> index_array(vertex_count);
03688 ON_SimpleArray<int> remap_array(vertex_count);
03689
03690 int remap_vertex_count = 0;
03691 int merge_count = 0;
03692 int i0, i1, k;
03693
03694 struct tagMESHPOINTS mp;
03695 memset(&mp,0,sizeof(mp));
03696 mp.p0 = (const char*)∓
03697 mp.V = mesh.m_V.Array();
03698 mp.N = mesh.HasVertexNormals() ? mesh.m_N.Array() : 0;
03699 mp.T = mesh.HasTextureCoordinates() ? mesh.m_T.Array() : 0;
03700 mp.C = mesh.HasVertexColors() ? mesh.m_C.Array() : 0;
03701 mp.K = mesh.HasPrincipalCurvatures() ? mesh.m_K.Array() : 0;
03702
03703 if ( bIgnoreVertexNormals )
03704 {
03705 mp.N = 0;
03706 }
03707
03708 if ( bIgnoreTextureCoordinates )
03709 {
03710 mp.T = 0;
03711 mp.C = 0;
03712 mp.K = 0;
03713 }
03714
03715 index_array.SetCount(vertex_count);
03716 index_array.Zero();
03717 int* index = index_array.Array();
03718
03719 remap_array.SetCount(vertex_count);
03720 int* remap = remap_array.Array();
03721 for ( k = 0; k < vertex_count; k++ )
03722 remap[k] = -1;
03723
03724 ON_Sort(
03725 ON::quick_sort,
03726 index,
03727 mp.p0,
03728 vertex_count,
03729 sizeof(*mp.p0),
03730 CompareMeshPoint,
03731 &mp
03732 );
03733
03734 for ( i0 = 0; i0 < vertex_count; i0 = i1 )
03735 {
03736 for ( i1 = i0+1; i1 < vertex_count; i1++ )
03737 {
03738 if ( CompareMeshPoint( mp.p0+index[i0], mp.p0+index[i1], &mp ) )
03739 break;
03740 else
03741 merge_count++;
03742 }
03743 for ( ; i0 < i1; i0++ )
03744 {
03745 remap[index[i0]] = remap_vertex_count;
03746 }
03747 remap_vertex_count++;
03748 }
03749
03750 if ( bIgnoreVertexNormals )
03751 {
03752 mp.N = mesh.HasVertexNormals() ? mesh.m_N.Array() : 0;
03753 }
03754
03755 if ( bIgnoreTextureCoordinates )
03756 {
03757 mp.T = mesh.HasTextureCoordinates() ? mesh.m_T.Array() : 0;
03758 mp.C = mesh.HasVertexColors() ? mesh.m_C.Array() : 0;
03759 mp.K = mesh.HasPrincipalCurvatures() ? mesh.m_K.Array() : 0;
03760 }
03761
03762 if ( remap_vertex_count > 0 && remap_vertex_count < vertex_count )
03763 {
03764 ON_SimpleArray<ON_3fPoint> p_array(remap_vertex_count);
03765 p_array.SetCount(remap_vertex_count);
03766 ON_3fPoint* p = p_array.Array();
03767 ON_3fVector* v = (ON_3fVector*)p;
03768
03769 for ( k = 0; k < vertex_count; k++ )
03770 {
03771 p[remap[k]] = mp.V[k];
03772 }
03773 for ( k = 0; k < remap_vertex_count; k++ )
03774 mp.V[k] = p[k];
03775 mesh.m_V.SetCount(remap_vertex_count);
03776
03777 if ( 0 != mp.N )
03778 {
03779 if ( bIgnoreVertexNormals )
03780 {
03781
03782 p_array.Zero();
03783 for ( k = 0; k < vertex_count; k++ )
03784 {
03785 v[remap[k]] += mp.N[k];
03786 }
03787 for ( k = 0; k < remap_vertex_count; k++ )
03788 {
03789 v[k].Unitize();
03790 }
03791 }
03792 else
03793 {
03794 for ( k = 0; k < vertex_count; k++ )
03795 {
03796 v[remap[k]] = mp.N[k];
03797 }
03798 }
03799 for ( k = 0; k < remap_vertex_count; k++ )
03800 mp.N[k] = v[k];
03801 mesh.m_N.SetCount(remap_vertex_count);
03802 }
03803 else
03804 mesh.m_N.SetCount(0);
03805
03806 if ( 0 != mp.T && !bIgnoreTextureCoordinates )
03807 {
03808 for ( k = 0; k < vertex_count; k++ )
03809 {
03810 p[remap[k]] = mp.T[k];
03811 }
03812 for ( k = 0; k < remap_vertex_count; k++ )
03813 mp.T[k] = p[k];
03814 mesh.m_T.SetCount(remap_vertex_count);
03815 }
03816 else
03817 mesh.m_T.SetCount(0);
03818
03819 if ( 0 != mp.C && !bIgnoreTextureCoordinates )
03820 {
03821 ON_SimpleArray<ON_Color> c_array(remap_vertex_count);
03822 c_array.SetCount(remap_vertex_count);
03823 ON_Color* c = c_array.Array();
03824 for ( k = 0; k < vertex_count; k++ )
03825 {
03826 c[remap[k]] = mp.C[k];
03827 }
03828 for ( k = 0; k < remap_vertex_count; k++ )
03829 mp.C[k] = c[k];
03830 mesh.m_C.SetCount(remap_vertex_count);
03831 }
03832 else
03833 mesh.m_C.SetCount(0);
03834
03835 if ( 0 != mp.K && !bIgnoreTextureCoordinates )
03836 {
03837 ON_SimpleArray<ON_SurfaceCurvature> s_array(remap_vertex_count);
03838 s_array.SetCount(remap_vertex_count);
03839 ON_SurfaceCurvature* s = s_array.Array();
03840 for ( k = 0; k < vertex_count; k++ )
03841 {
03842 s[remap[k]] = mp.K[k];
03843 }
03844 for ( k = 0; k < remap_vertex_count; k++ )
03845 mp.K[k] = s[k];
03846 mesh.m_K.SetCount(remap_vertex_count);
03847 }
03848 else
03849 mesh.m_K.SetCount(0);
03850
03851 const int face_count = mesh.m_F.Count();
03852 ON_MeshFace* f = mesh.m_F.Array();
03853 int* fvi;
03854 for ( k = 0; k < face_count; k++ )
03855 {
03856 fvi = f[k].vi;
03857 fvi[0] = remap[fvi[0]];
03858 fvi[1] = remap[fvi[1]];
03859 fvi[2] = remap[fvi[2]];
03860 fvi[3] = remap[fvi[3]];
03861 }
03862
03863 if (0 != NgonList())
03864 {
03865
03866
03867
03868 ON_MeshNgonList* ngonlist = ModifyNgonList();
03869 int kk, kkct = ngonlist->NgonCount();
03870 for (kk = 0; kk < kkct; kk++)
03871 {
03872 ON_MeshNgon* ngon = ngonlist->Ngon(kk);
03873 if (0 == ngon)
03874 continue;
03875 for ( k = 0; k < ngon->N; k++ )
03876 ngon->vi[k] = remap[ngon->vi[k]];
03877 }
03878 }
03879
03880 mesh.DestroyPartition();
03881 mesh.DestroyTopology();
03882
03883 if ( mesh.m_V.Capacity() > 4*mesh.m_V.Count() && mesh.m_V.Capacity() > 50 )
03884 {
03885
03886
03887 mesh.Compact();
03888 }
03889 rc = true;
03890 }
03891 }
03892 return rc;
03893 }
03894
03895 void ON_Mesh::Append( int mesh_count, const ON_Mesh* const* meshes )
03896 {
03897 if ( mesh_count <= 0 || 0 == meshes )
03898 return;
03899
03900 int mi;
03901 int vcount0 = VertexCount();
03902 if ( vcount0 <= 0 )
03903 m_F.SetCount(0);
03904 int fcount0 = FaceCount();
03905 int* vi;
03906 int j;
03907 const ON_Mesh* m;
03908
03909
03910
03911
03912 bool bHasVertexNormals = (0 == vcount0 || HasVertexNormals());
03913 bool bHasFaceNormals = (0 == vcount0 || 0 == fcount0 || HasFaceNormals());
03914 bool bHasTextureCoordinates = (0 == vcount0 || HasTextureCoordinates());
03915 bool bHasPrincipalCurvatures = (0 == vcount0 || HasPrincipalCurvatures());
03916 bool bHasVertexColors = (0 == vcount0 || HasVertexColors());
03917 bool bHasSurfaceParameters = (0 == vcount0 || HasSurfaceParameters());
03918 bool bHasDoubles = (0 == vcount0 || HasSynchronizedDoubleAndSinglePrecisionVertices());
03919
03920 int fcount = fcount0;
03921 int vcount = vcount0;
03922 for ( mi = 0; mi < mesh_count; mi++ )
03923 {
03924 m = meshes[mi];
03925 if ( 0 == m )
03926 continue;
03927 int vcount1 = m->m_V.Count();
03928 if ( vcount1 <= 0 )
03929 continue;
03930 int fcount1 = m->m_F.Count();
03931 if ( fcount1 > 0 )
03932 fcount += fcount1;
03933 vcount += vcount1;
03934 if ( bHasVertexNormals && !m->HasVertexNormals() )
03935 bHasVertexNormals = false;
03936 if ( bHasTextureCoordinates && !m->HasTextureCoordinates())
03937 bHasTextureCoordinates = false;
03938 if ( bHasPrincipalCurvatures && !m->HasPrincipalCurvatures())
03939 bHasPrincipalCurvatures = false;
03940 if ( bHasVertexColors && !m->HasVertexColors())
03941 bHasVertexColors = false;
03942 if ( bHasSurfaceParameters && !m->HasSurfaceParameters())
03943 bHasSurfaceParameters = false;
03944 if ( bHasDoubles && !m->HasSynchronizedDoubleAndSinglePrecisionVertices())
03945 bHasDoubles = false;
03946 if ( bHasFaceNormals && fcount1 > 0 && !m->HasFaceNormals() )
03947 bHasFaceNormals = false;
03948 }
03949
03950 if ( vcount <= vcount0 && fcount <= fcount0 )
03951 return;
03952
03953 m_top.Destroy();
03954
03955
03956
03957
03958
03959 ON_MeshDoubleVertices* dv = 0;
03960 if ( bHasDoubles )
03961 {
03962 dv = ON_MeshDoubleVertices::Get(this);
03963 if ( 0 == dv && 0 == m_V.Count() )
03964 {
03965 DoublePrecisionVertices();
03966 dv = ON_MeshDoubleVertices::Get(this);
03967 }
03968 if ( 0 == dv )
03969 bHasDoubles = false;
03970 }
03971
03972 m_V.Reserve(vcount);
03973 m_F.Reserve(fcount);
03974 for (mi = 0; mi < mesh_count; mi++ )
03975 {
03976 m = meshes[mi];
03977 if ( 0 == m )
03978 continue;
03979 int vcount1 = m->m_V.Count();
03980 if ( vcount1 <= 0 )
03981 continue;
03982 int fcount1 = m->m_F.Count();
03983 if ( fcount1 > 0 )
03984 {
03985 int vc0 = m_V.Count();
03986 j = m_F.Count();
03987 m_F.Append(fcount1,m->m_F.Array());
03988 fcount1 += j;
03989 while (j < fcount1)
03990 {
03991 vi = m_F[j].vi;
03992 vi[0] += vc0;
03993 vi[1] += vc0;
03994 vi[2] += vc0;
03995 vi[3] += vc0;
03996 j++;
03997 }
03998 }
03999 m_V.Append(vcount1,m->m_V.Array());
04000 }
04001
04002 if ( bHasDoubles)
04003 {
04004
04005 dv->m_dV.Reserve(vcount);
04006 for (mi = 0; mi < mesh_count; mi++ )
04007 {
04008 m = meshes[mi];
04009 if ( 0 == m || m->m_V.Count() <= 0 )
04010 continue;
04011 ON_MeshDoubleVertices* dv1 = ON_MeshDoubleVertices::Get(m);
04012 if ( 0 == dv1 )
04013 break;
04014 dv->m_dV.Append(dv1->m_dV.Count(),dv1->m_dV.Array());
04015 }
04016 if ( dv->m_dV.Count() == vcount )
04017 {
04018
04019
04020
04021
04022
04023 SetSinglePrecisionVerticesAsValid();
04024 SetDoublePrecisionVerticesAsValid();
04025 }
04026 else
04027 {
04028 DestroyDoublePrecisionVertices();
04029 }
04030 }
04031 else
04032 {
04033 DestroyDoublePrecisionVertices();
04034 }
04035
04036
04037 if ( bHasVertexNormals )
04038 {
04039 m_N.Reserve(vcount);
04040 for (mi = 0; mi < mesh_count; mi++ )
04041 {
04042 m = meshes[mi];
04043 if ( 0 == m )
04044 continue;
04045 m_N.Append(m->m_N.Count(), m->m_N.Array());
04046 }
04047 }
04048 else
04049 {
04050 m_N.Destroy();
04051 }
04052
04053
04054 if ( bHasFaceNormals )
04055 {
04056 m_FN.Reserve(fcount);
04057 for (mi = 0; mi < mesh_count; mi++ )
04058 {
04059 m = meshes[mi];
04060 if ( 0 == m || m->m_V.Count() <= 0 )
04061 continue;
04062 m_FN.Append(m->m_FN.Count(), m->m_FN.Array());
04063 }
04064 }
04065 else
04066 {
04067 m_FN.Destroy();
04068 }
04069
04070 if ( bHasTextureCoordinates )
04071 {
04072 m_T.Reserve(vcount);
04073 for (mi = 0; mi < mesh_count; mi++ )
04074 {
04075 m = meshes[mi];
04076 if ( 0 == m )
04077 continue;
04078 m_T.Append(m->m_T.Count(), m->m_T.Array());
04079 }
04080 }
04081 else
04082 {
04083 m_T.Destroy();
04084 }
04085
04086
04087 if ( bHasSurfaceParameters )
04088 {
04089 m_S.Reserve(vcount);
04090 for (mi = 0; mi < mesh_count; mi++ )
04091 {
04092 m = meshes[mi];
04093 if ( 0 == m )
04094 continue;
04095 m_S.Append(m->m_S.Count(), m->m_S.Array());
04096 }
04097 }
04098 else
04099 {
04100 m_S.Destroy();
04101 }
04102
04103 if ( bHasPrincipalCurvatures )
04104 {
04105 m_K.Reserve(vcount);
04106 for (mi = 0; mi < mesh_count; mi++ )
04107 {
04108 m = meshes[mi];
04109 if ( 0 == m )
04110 continue;
04111 m_K.Append(m->m_K.Count(), m->m_K.Array());
04112 }
04113 }
04114 else
04115 {
04116 m_K.Destroy();
04117 }
04118
04119 if ( bHasVertexColors )
04120 {
04121 m_C.Reserve(vcount);
04122 for (mi = 0; mi < mesh_count; mi++ )
04123 {
04124 m = meshes[mi];
04125 if ( 0 == m )
04126 continue;
04127 m_C.Append(m->m_C.Count(), m->m_C.Array());
04128 }
04129 }
04130 else
04131 {
04132 m_C.Destroy();
04133 }
04134
04135 if ( 0 != m_mesh_parameters )
04136 {
04137 for (mi = 0; mi < mesh_count; mi++ )
04138 {
04139 m = meshes[mi];
04140 if ( 0 == m )
04141 continue;
04142 if ( 0 == m->m_mesh_parameters || *m_mesh_parameters != *m->m_mesh_parameters )
04143 {
04144 delete m_mesh_parameters;
04145 m_mesh_parameters = 0;
04146 break;
04147 }
04148 }
04149 }
04150
04151 for ( j = 0; j < 4; j++ )
04152 {
04153 if ( m_kstat[j] )
04154 {
04155
04156 delete m_kstat[j];
04157 m_kstat[j] = 0;
04158 }
04159 }
04160
04161 SetClosed(-99);
04162 SetSolidOrientation(-99);
04163 InvalidateBoundingBoxes();
04164 }
04165
04166 void ON_Mesh::Append( const ON_Mesh& m )
04167 {
04168 const ON_Mesh* meshes[1];
04169 meshes[0] = &m;
04170 Append(1,meshes);
04171 }
04172
04173 ON_MeshParameters::ON_MeshParameters()
04174 {
04175 Default();
04176 }
04177
04178 ON_MeshParameters::~ON_MeshParameters()
04179 {
04180 }
04181
04182 double ON_MeshParameters::MinEdgeLength( double max_edge_length, double tolerance )
04183 {
04184
04185
04186 double min_edge_length = 1.0e-4;
04187 if ( max_edge_length > 0.0 && min_edge_length > 1.0e-3*max_edge_length )
04188 min_edge_length = 1.0e-3*max_edge_length;
04189 if ( tolerance > 0.0 && min_edge_length > 1.0e-2*tolerance )
04190 min_edge_length = 1.0e-2*tolerance;
04191 return min_edge_length;
04192 }
04193
04194 double ON_MeshParameters::Tolerance( double density, double actual_size )
04195 {
04196
04197
04198
04199
04200
04201
04202
04203
04204
04205
04206
04207
04208
04209
04210
04211
04212 double tol = 0.0;
04213 double x, e;
04214 if ( ON_IsValid(density) && ON_IsValid(actual_size)
04215 && density > 0.0 && actual_size > 0.0 )
04216 {
04217 if ( density > 1.0 )
04218 density = 1.0;
04219
04220
04221
04222
04223
04224
04225 e = (density < 0.5)
04226 ? 1.0 + density*(6.0 - 4.0*density)
04227 : 2.0 + 2.0*density;
04228 x = pow(10.0,-e);
04229
04230 tol = actual_size*x;
04231 }
04232 return tol;
04233 }
04234
04235 static ON_MeshParameters FastRenderMeshParameters()
04236 {
04237
04238
04239
04240 ON_MeshParameters mp;
04241
04242
04243
04244
04245
04246
04247 mp.m_bComputeCurvature = false;
04248 mp.m_tolerance = 0.0;
04249 mp.m_bJaggedSeams = false;
04250 mp.m_max_edge_length = 0.0;
04251 mp.m_grid_aspect_ratio = 0.0;
04252 mp.m_grid_max_count = 0;
04253 mp.m_grid_angle = 0.0;
04254 mp.m_grid_amplification = 0.0;
04255 mp.m_refine_angle = 0.0;
04256
04257
04258
04259
04260 mp.m_relative_tolerance = 0.65;
04261
04262
04263 mp.m_grid_min_count = 16;
04264 mp.m_min_edge_length = 0.0001;
04265 mp.m_bRefine = true;
04266 mp.m_bSimplePlanes = true;
04267
04268 mp.m_texture_range = 2;
04269
04270
04271
04272
04273
04274
04275
04276
04277
04278
04279
04280
04281
04282
04283
04284
04285
04286 return mp;
04287 }
04288
04289 static ON_MeshParameters QualityRenderMeshParameters()
04290 {
04291
04292
04293
04294 ON_MeshParameters mp;
04295
04296
04297
04298
04299
04300
04301 mp.m_bComputeCurvature = false;
04302 mp.m_tolerance = 0.0;
04303 mp.m_bJaggedSeams = false;
04304 mp.m_max_edge_length = 0.0;
04305 mp.m_grid_aspect_ratio = 0.0;
04306 mp.m_grid_max_count = 0;
04307 mp.m_grid_angle = 0.0;
04308 mp.m_grid_amplification = 0.0;
04309
04310
04311
04312
04313 mp.m_relative_tolerance = 0.8;
04314
04315
04316 mp.m_grid_min_count = 16;
04317 mp.m_min_edge_length = 0.0001;
04318 mp.m_bRefine = true;
04319 mp.m_bSimplePlanes = true;
04320 mp.m_refine_angle = 20.0*ON_PI/180.0;
04321
04322 mp.m_texture_range = 2;
04323
04324
04328
04329
04330
04331
04332
04333
04334
04335
04336
04337
04338
04339 return mp;
04340 }
04341
04342 const ON_MeshParameters ON_MeshParameters::FastRenderMesh(FastRenderMeshParameters());
04343
04344 const ON_MeshParameters ON_MeshParameters::QualityRenderMesh(QualityRenderMeshParameters());
04345
04346 void ON_MeshParameters::JaggedAndFasterMeshParameters()
04347 {
04348 *this = ON_MeshParameters::FastRenderMesh;
04349 }
04350
04351 void ON_MeshParameters::SmoothAndSlowerMeshParameters()
04352 {
04353 *this = ON_MeshParameters::QualityRenderMesh;
04354 }
04355
04356 void ON_MeshParameters::DefaultAnalysisMeshParameters()
04357 {
04358 Default();
04359
04360
04361
04362 Set( 0.5, m_min_edge_length );
04363
04364 m_texture_range = 1;
04365
04366
04367
04368
04369 }
04370
04371 bool ON_MeshParameters::operator==(const ON_MeshParameters& m2) const
04372 {
04373 return (Compare(m2)==0) ? true : false;
04374 }
04375
04376 bool ON_MeshParameters::operator!=(const ON_MeshParameters& m2) const
04377 {
04378 return (Compare(m2)) ? true : false;
04379 }
04380
04381 bool ON_MeshParameters::operator==(const ON_Mesh& mesh) const
04382 {
04383 const ON_MeshParameters* mp1 = mesh.MeshParameters();
04384 return mp1 ? (*this == *mp1) : false;
04385 }
04386
04387 bool ON_MeshParameters::operator!=(const ON_Mesh& mesh) const
04388 {
04389 const ON_MeshParameters* mp1 = mesh.MeshParameters();
04390 return mp1 ? (*this != *mp1) : true;
04391 }
04392
04393 void ON_MeshParameters::Dump( ON_TextLog& text_log ) const
04394 {
04395 text_log.Print("Gridding:\n");
04396 text_log.PushIndent();
04397 text_log.Print("Min grid count = %d\n",m_grid_min_count);
04398 text_log.Print("Max grid count = %d\n",m_grid_max_count);
04399 text_log.Print("Gridding angle = %g radians (%g degrees)\n",m_grid_angle,180.0*m_grid_angle/ON_PI);
04400 text_log.Print("Aspect ratio = %g\n",m_grid_aspect_ratio);
04401 text_log.Print("Amplification = %g\n",m_grid_amplification);
04402 text_log.PopIndent();
04403
04404 text_log.Print("Refining:\n");
04405 text_log.PushIndent();
04406 text_log.Print("Refine = %s\n",m_bRefine?"true":"false");
04407 text_log.Print("Refine angle = %g radians (%g degrees)\n",m_refine_angle,180.0*m_refine_angle/ON_PI);
04408 text_log.PopIndent();
04409
04410 text_log.Print("Metrics:\n");
04411 text_log.PushIndent();
04412 text_log.Print("Density = %g (relative tolerance = %g)\n",m_relative_tolerance,ON_MeshParameters::Tolerance(m_relative_tolerance,1.0));
04413 text_log.Print("Minimum tolerance = %g\n",m_min_tolerance);
04414 text_log.Print("Tolerance = %g\n",m_tolerance);
04415 text_log.Print("Min edge length = %g\n",m_min_edge_length);
04416 text_log.Print("Max edge length = %g\n",m_max_edge_length);
04417 text_log.PopIndent();
04418
04419 text_log.Print("Misceleanous:\n");
04420 text_log.PushIndent();
04421 text_log.Print("Face type = %d\n",m_face_type );
04422 text_log.Print("Compute curvature = %s\n",m_bComputeCurvature?"true":"false");
04423 text_log.Print("Texture range = %d\n",m_texture_range);
04424 text_log.Print("Simple planes = %s\n",m_bSimplePlanes?"true":"false");
04425 text_log.Print("Jagged Seams = %s\n",m_bJaggedSeams?"true":"false");
04426 text_log.Print("Double Precision = %s\n",m_bDoublePrecision?"true":"false");
04427 text_log.Print("Custom settings = %s\n",m_bCustomSettings?"true":"false");
04428 text_log.PopIndent();
04429 }
04430
04431 void ON_MeshParameters::Default()
04432 {
04433 memset(this,0,sizeof(*this));
04434
04435 m_bCustomSettings = false;
04436 m_bComputeCurvature = false;
04437 m_bSimplePlanes = false;
04438 m_bRefine = true;
04439 m_bJaggedSeams = false;
04440 m_bDoublePrecision = false;
04441 m_bCustomSettingsEnabled = true;
04442 m_mesher = 0;
04443 m_texture_range = 2;
04444 m_reserved2 = 0;
04445 m_tolerance = 0.0;
04446 m_relative_tolerance = 0.0;
04447 m_min_tolerance = 0.0;
04448 m_min_edge_length = 0.0001;
04449 m_max_edge_length = 0.0;
04450 m_grid_aspect_ratio = 6.0;
04451 m_grid_min_count = 0;
04452 m_grid_max_count = 0;
04453 m_grid_angle = 20.0*ON_PI/180.0;
04454 m_grid_amplification = 1.0;
04455 m_refine_angle = 20.0*ON_PI/180.0;
04456 m_face_type = 0;
04457 m_reserved3 = 0;
04458 }
04459
04460 void ON_MeshParameters::Set( double density, double min_edge_length )
04461 {
04462 bool bRelTolTest = true;
04463
04464 Default();
04465
04466
04467 m_bComputeCurvature = false;
04468 m_min_edge_length = min_edge_length;
04469 m_texture_range = 0;
04470 m_tolerance = 0.0;
04471
04472 if ( bRelTolTest )
04473 {
04474
04475 m_relative_tolerance = density;
04476
04477
04478
04479
04480
04481
04482
04483
04484
04485 m_bRefine = (density < 0.65);
04486 m_bSimplePlanes = (density <= 0.0);
04487 m_bJaggedSeams = false;
04488 m_max_edge_length = 0.0;
04489 m_grid_aspect_ratio = 0.0;
04490 m_grid_min_count = 0;
04491 m_grid_max_count = 0;
04492 m_grid_angle = 0.0;
04493 m_grid_amplification = 0.0;
04494 m_refine_angle = 0.0;
04495 }
04496 else
04497 {
04498
04499 double t0, t1;
04500
04501 m_bRefine = true;
04502 m_bSimplePlanes = false;
04503 m_bJaggedSeams = false;
04504 m_max_edge_length = 0.0;
04505 m_grid_aspect_ratio = 0.0;
04506 m_grid_min_count = 16;
04507 m_grid_max_count = 0;
04508 m_grid_angle = 20.0*ON_PI/180.0;
04509 m_grid_amplification = 1.0;
04510 m_refine_angle = 20.0*ON_PI/180.0;
04511
04512 if ( density <= 0.0)
04513 {
04514 m_bSimplePlanes = true;
04515 m_bRefine = false;
04516
04517 m_grid_min_count = 0;
04518 m_grid_aspect_ratio = 0.0;
04519 m_grid_angle = 0.0;
04520 m_grid_amplification = 1.0;
04521
04522 m_refine_angle = m_grid_angle;
04523 }
04524 else if ( density < 0.5)
04525 {
04526 t1 = 2.0*density;
04527 t0 = 1.0-t1;
04528
04529 m_bRefine = density < 0.10 ? false : true;
04530
04531 m_grid_min_count = 0;
04532 m_grid_aspect_ratio = 6.0;
04533 m_grid_angle = 20.0*ON_PI/180.0;
04534 m_grid_amplification = (t1 > 0.0 ) ? t1 : 1.0;
04535
04536 m_refine_angle = (t0*65.0 + t1*20.0)*ON_PI/180.0;
04537 }
04538 else if ( density == 0.5 )
04539 {
04540 m_bRefine = true;
04541
04542 m_grid_min_count = 0;
04543 m_grid_aspect_ratio = 6.0;
04544 m_grid_angle = 20.0*ON_PI/180.0;
04545 m_grid_amplification = 1.0;
04546
04547 m_refine_angle = m_grid_angle;
04548 }
04549 else
04550 {
04551 t1 = 2.0*(density - 0.5);
04552 if ( t1 > 1.0 )
04553 t1 = 1.0;
04554 t0 = 1.0-t1;
04555
04556 m_bRefine = true;
04557
04558 m_grid_min_count = 0;
04559 m_grid_aspect_ratio = t0*6.0 + t1;
04560 m_grid_angle = (t0*20.0 + t1*5.0)*ON_PI/180.0;
04561 m_grid_amplification = 1.0 + t1;
04562
04563 m_refine_angle = m_grid_angle;
04564 }
04565 }
04566 }
04567
04568
04569 int ON_MeshParameters::Compare( const ON_MeshParameters& src ) const
04570 {
04571
04572 if ( !m_bCustomSettings && src.m_bCustomSettings )
04573 return -1;
04574 if ( m_bCustomSettings && !src.m_bCustomSettings )
04575 return 1;
04576 if ( m_texture_range < src.m_texture_range )
04577 return -1;
04578 if ( m_texture_range > src.m_texture_range )
04579 return 1;
04580 return CompareGeometrySettings(src);
04581 }
04582
04583 static int ON_MeshParameters_CompareDouble(double t0, double t1, double default_value)
04584 {
04585 if ( !ON_IsValid(t0) || t0 <= 0.0 )
04586 t0 = default_value;
04587 if ( !ON_IsValid(t1) || t1 <= 0.0 )
04588 t1 = default_value;
04589 if ( t0 < t1 )
04590 return 1;
04591 if ( t1 < t0 )
04592 return -1;
04593 return 0;
04594 }
04595
04596 static int ON_MeshParameters_CompareInt(int i0, int i1)
04597 {
04598 if ( i0 <= 0 )
04599 i0 = 0;
04600 if ( i1 <= 0 )
04601 i1 = 0;
04602 return i1-i0;
04603 }
04604
04605 static int ON_MeshParameters_CompareBool(bool b0, bool b1)
04606 {
04607 const int i0 = b0 ? 1 : 0;
04608 const int i1 = b1 ? 1 : 0;
04609 return i1-i0;
04610 }
04611
04612 int ON_MeshParameters::CompareGeometrySettings( const ON_MeshParameters& src ) const
04613 {
04614 int rc;
04615
04616
04617 rc = ON_MeshParameters_CompareBool(m_bSimplePlanes,src.m_bSimplePlanes);
04618 if (rc)
04619 return rc;
04620 rc = ON_MeshParameters_CompareBool(m_bRefine,src.m_bRefine);
04621 if (rc)
04622 return rc;
04623 rc = ON_MeshParameters_CompareBool(m_bJaggedSeams,src.m_bJaggedSeams);
04624 if (rc)
04625 return rc;
04626 if ( m_mesher < src.m_mesher )
04627 return -1;
04628 if ( m_mesher > src.m_mesher )
04629 return 1;
04630
04631 rc = ON_MeshParameters_CompareDouble(m_tolerance,src.m_tolerance,0.0);
04632 if (rc)
04633 return rc;
04634
04635 rc = ON_MeshParameters_CompareDouble(m_relative_tolerance,src.m_relative_tolerance,0.0);
04636 if (rc)
04637 return rc;
04638
04639
04640
04641
04642
04643 rc = ON_MeshParameters_CompareDouble(m_min_edge_length,src.m_min_edge_length,0.0);
04644 if (rc)
04645 return rc;
04646
04647 rc = ON_MeshParameters_CompareDouble(m_max_edge_length,src.m_max_edge_length,0.0);
04648 if (rc)
04649 return rc;
04650
04651 rc = ON_MeshParameters_CompareDouble(m_grid_aspect_ratio,src.m_grid_aspect_ratio,0.0);
04652 if (rc)
04653 return rc;
04654
04655 rc = ON_MeshParameters_CompareInt(m_grid_min_count,src.m_grid_min_count);
04656 if (rc)
04657 return rc;
04658
04659 rc = ON_MeshParameters_CompareInt(m_grid_max_count,src.m_grid_max_count);
04660 if (rc)
04661 return rc;
04662
04663 rc = ON_MeshParameters_CompareDouble(m_grid_angle,src.m_grid_angle,ON_PI);
04664 if (rc)
04665 return rc;
04666
04667 rc = ON_MeshParameters_CompareDouble(m_refine_angle,src.m_refine_angle,0.0);
04668 if (rc)
04669 return rc;
04670
04671 rc = ON_MeshParameters_CompareDouble(m_grid_amplification,src.m_grid_amplification,1.0);
04672 if (rc)
04673 return rc;
04674
04675 if ( m_face_type < src.m_face_type )
04676 return -1;
04677 if ( m_face_type > src.m_face_type )
04678 return 1;
04679
04680 return 0;
04681 }
04682
04683 ON__UINT32 ON_MeshParameters::DataCRC(ON__UINT32 current_remainder) const
04684 {
04685 ON__UINT32 crc = ON_CRC32(current_remainder,sizeof(m_bComputeCurvature),&m_bComputeCurvature);
04686 crc = ON_CRC32(crc,sizeof(m_bSimplePlanes),&m_bSimplePlanes);
04687 crc = ON_CRC32(crc,sizeof(m_bRefine),&m_bRefine);
04688 crc = ON_CRC32(crc,sizeof(m_bJaggedSeams),&m_bJaggedSeams);
04689 crc = ON_CRC32(crc,sizeof(m_tolerance),&m_tolerance);
04690 crc = ON_CRC32(crc,sizeof(m_min_edge_length),&m_min_edge_length);
04691 crc = ON_CRC32(crc,sizeof(m_max_edge_length),&m_max_edge_length);
04692 crc = ON_CRC32(crc,sizeof(m_grid_aspect_ratio),&m_grid_aspect_ratio);
04693 crc = ON_CRC32(crc,sizeof(m_grid_min_count),&m_grid_min_count);
04694 crc = ON_CRC32(crc,sizeof(m_grid_max_count),&m_grid_max_count);
04695 crc = ON_CRC32(crc,sizeof(m_grid_angle),&m_grid_angle);
04696 crc = ON_CRC32(crc,sizeof(m_grid_amplification),&m_grid_amplification);
04697 crc = ON_CRC32(crc,sizeof(m_refine_angle),&m_refine_angle);
04698 crc = ON_CRC32(crc,sizeof(m_face_type),&m_face_type);
04699 crc = ON_CRC32(crc,sizeof(m_texture_range),&m_texture_range);
04700 crc = ON_CRC32(crc,sizeof(m_bCustomSettings),&m_bCustomSettings);
04701 crc = ON_CRC32(crc,sizeof(m_relative_tolerance),&m_relative_tolerance);
04702 crc = ON_CRC32(crc,sizeof(m_mesher),&m_mesher);
04703 return crc;
04704 }
04705
04706 bool ON_MeshParameters::Write( ON_BinaryArchive& file ) const
04707 {
04708 bool rc = file.Write3dmChunkVersion(1,4);
04709 if (rc) {
04710 if (rc) rc = file.WriteInt(m_bComputeCurvature);
04711 if (rc) rc = file.WriteInt(m_bSimplePlanes);
04712 if (rc) rc = file.WriteInt(m_bRefine);
04713 if (rc) rc = file.WriteInt(m_bJaggedSeams);
04714 if (rc) rc = file.WriteInt(0);
04715 if (rc) rc = file.WriteDouble(m_tolerance);
04716 if (rc) rc = file.WriteDouble(m_min_edge_length);
04717 if (rc) rc = file.WriteDouble(m_max_edge_length);
04718 if (rc) rc = file.WriteDouble(m_grid_aspect_ratio);
04719 if (rc) rc = file.WriteInt(m_grid_min_count);
04720 if (rc) rc = file.WriteInt(m_grid_max_count);
04721 if (rc) rc = file.WriteDouble(m_grid_angle);
04722 if (rc) rc = file.WriteDouble(m_grid_amplification);
04723 if (rc) rc = file.WriteDouble(m_refine_angle);
04724 if (rc) rc = file.WriteDouble(5.0*ON_PI/180.0);
04725 int mft = m_face_type;
04726 if ( mft < 0 || mft > 2 )
04727 {
04728 ON_ERROR("ON_MeshParameters::Read() - m_face_type out of bounds.");
04729 mft = 0;
04730 }
04731 if (rc) rc = file.WriteInt(mft);
04732
04733
04734 if (rc) rc = file.WriteInt( m_texture_range );
04735
04736
04737 if (rc) rc = file.WriteBool( m_bCustomSettings );
04738 if (rc) rc = file.WriteDouble( m_relative_tolerance );
04739
04740
04741
04742 if (rc) rc = file.WriteChar(m_mesher);
04743
04744
04745 if (rc) rc = file.WriteBool( m_bCustomSettingsEnabled );
04746 }
04747 return rc;
04748 }
04749
04750 bool ON_MeshParameters::Read( ON_BinaryArchive& file )
04751 {
04752 Default();
04753 int major_version = 0;
04754 int minor_version = 0;
04755 bool rc = file.Read3dmChunkVersion(&major_version,&minor_version);
04756 if ( rc && major_version == 1 )
04757 {
04758 int i;
04759
04760 i = m_bComputeCurvature;
04761 if (rc) rc = file.ReadInt(&i);
04762 m_bComputeCurvature = i?true:false;
04763
04764 i = m_bSimplePlanes;
04765 if (rc) rc = file.ReadInt(&i);
04766 m_bSimplePlanes = i?true:false;
04767
04768 i = m_bRefine;
04769 if (rc) rc = file.ReadInt(&i);
04770 m_bRefine = i?true:false;
04771
04772 i = m_bJaggedSeams;
04773 if (rc) rc = file.ReadInt(&i);
04774 m_bJaggedSeams = i?true:false;
04775
04776 int obsolete_m_bWeld;
04777 if (rc) rc = file.ReadInt(&obsolete_m_bWeld);
04778
04779 if (rc) rc = file.ReadDouble(&m_tolerance);
04780 if (rc) rc = file.ReadDouble(&m_min_edge_length);
04781 if (rc) rc = file.ReadDouble(&m_max_edge_length);
04782 if (rc) rc = file.ReadDouble(&m_grid_aspect_ratio);
04783 if (rc) rc = file.ReadInt(&m_grid_min_count);
04784 if (rc) rc = file.ReadInt(&m_grid_max_count);
04785 if (rc) rc = file.ReadDouble(&m_grid_angle);
04786 if (rc) rc = file.ReadDouble(&m_grid_amplification);
04787 if (rc) rc = file.ReadDouble(&m_refine_angle);
04788 double obsolete_m_combine_angle;
04789 if (rc) rc = file.ReadDouble(&obsolete_m_combine_angle);
04790 if (rc) rc = file.ReadInt(&m_face_type);
04791 if ( m_face_type < 0 || m_face_type > 2 )
04792 {
04793 ON_ERROR("ON_MeshParameters::Read() - m_face_type out of bounds.");
04794 m_face_type = 0;
04795 }
04796
04797 if ( rc && minor_version >= 1 )
04798 {
04799 rc = file.ReadInt( &m_texture_range );
04800 if ( rc && minor_version >= 2 )
04801 {
04802 rc = file.ReadBool(&m_bCustomSettings);
04803 if (rc) rc = file.ReadDouble(&m_relative_tolerance);
04804 if ( rc && minor_version >= 3 )
04805 {
04806 rc = file.ReadChar(&m_mesher);
04807 if ( rc && minor_version >= 4 )
04808 {
04809 rc = file.ReadBool(&m_bCustomSettingsEnabled);
04810 }
04811 }
04812 }
04813 }
04814 }
04815 return rc;
04816 }
04817
04818
04819
04820 ON_MeshCurvatureStats::ON_MeshCurvatureStats()
04821 {
04822 Destroy();
04823 }
04824
04825 ON_MeshCurvatureStats::~ON_MeshCurvatureStats()
04826 {}
04827
04828 void ON_MeshCurvatureStats::Destroy()
04829 {
04830 m_style = ON::unknown_curvature_style;
04831 m_infinity = 0.0;
04832 m_count_infinite = 0;
04833 m_count = 0;
04834 m_mode = 0.0;
04835 m_average = 0.0;
04836 m_adev = 0.0;
04837 m_range.Set(0.0,0.0);
04838 }
04839
04840 void ON_MeshCurvatureStats::EmergencyDestroy()
04841 {
04842 Destroy();
04843 }
04844
04845 ON_MeshCurvatureStats::ON_MeshCurvatureStats(const ON_MeshCurvatureStats& src)
04846 {
04847 *this = src;
04848 }
04849
04850 ON_MeshCurvatureStats& ON_MeshCurvatureStats::operator=(const ON_MeshCurvatureStats& src)
04851 {
04852 if ( this != &src ) {
04853 m_style = src.m_style;
04854 m_infinity = src.m_infinity;
04855 m_count_infinite = src.m_count_infinite;
04856 m_count = src.m_count;
04857 m_mode = src.m_mode;
04858 m_average = src.m_average;
04859 m_adev = src.m_adev;
04860 m_range = src.m_range;
04861 }
04862 return *this;
04863 }
04864
04865 bool ON_MeshCurvatureStats::Write( ON_BinaryArchive& file ) const
04866 {
04867 int i;
04868 bool rc = file.Write3dmChunkVersion(1,1);
04869 if (rc) {
04870 i = m_style;
04871 if (rc) rc = file.WriteInt(i);
04872 if (rc) rc = file.WriteDouble(m_infinity);
04873 if (rc) rc = file.WriteInt(m_count_infinite);
04874 if (rc) rc = file.WriteInt(m_count);
04875 if (rc) rc = file.WriteDouble(m_mode);
04876 if (rc) rc = file.WriteDouble(m_average);
04877 if (rc) rc = file.WriteDouble(m_adev);
04878 if (rc) rc = file.WriteInterval(m_range);
04879 }
04880 return rc;
04881 }
04882
04883
04884 bool ON_MeshCurvatureStats::Read( ON_BinaryArchive& file )
04885 {
04886 int major_version = 0;
04887 int minor_version = 0;
04888 Destroy();
04889 bool rc = file.Read3dmChunkVersion(&major_version,&minor_version);
04890 if (rc && major_version == 1) {
04891 int i=0;
04892 if (rc) rc = file.ReadInt(&i);
04893 if (rc) m_style = ON::CurvatureStyle(i);
04894 if (rc) rc = file.ReadDouble(&m_infinity);
04895 if (rc) rc = file.ReadInt(&m_count_infinite);
04896 if (rc) rc = file.ReadInt(&m_count);
04897 if (rc) rc = file.ReadDouble(&m_mode);
04898 if (rc) rc = file.ReadDouble(&m_average);
04899 if (rc) rc = file.ReadDouble(&m_adev);
04900 if (rc) rc = file.ReadInterval(m_range);
04901 }
04902 return rc;
04903 }
04904
04905 bool ON_MeshCurvatureStats::Set( ON::curvature_style kappa_style,
04906 int Kcount,
04907 const ON_SurfaceCurvature* K,
04908 const ON_3fVector* N,
04909 double infinity
04910 )
04911 {
04912 bool rc = (Kcount > 0 && K != NULL);
04913
04914 Destroy();
04915
04916 if (rc) {
04917 ON_Workspace ws;
04918
04919 double k;
04920 double* kappa = ws.GetDoubleMemory(Kcount);
04921 int i;
04922
04923 switch( kappa_style ) {
04924 case ON::gaussian_curvature:
04925 m_style = kappa_style;
04926 m_infinity = ( infinity > 0.0 ) ? infinity : 1.0e20;
04927 break;
04928 case ON::mean_curvature:
04929 m_style = kappa_style;
04930 m_infinity = ( infinity > 0.0 ) ? infinity : 1.0e10;
04931 break;
04932 case ON::min_curvature:
04933 m_style = kappa_style;
04934 m_infinity = ( infinity > 0.0 ) ? infinity : 1.0e10;
04935 break;
04936 case ON::max_curvature:
04937 m_style = kappa_style;
04938 m_infinity = ( infinity > 0.0 ) ? infinity : 1.0e10;
04939 break;
04940
04941
04942
04943
04944
04945
04946
04947
04948
04949
04950
04951
04952
04953
04954
04955
04956
04957
04958 default:
04959 rc = false;
04960 break;
04961 }
04962
04963 for ( i = 0; i < Kcount; i++ ) {
04964 switch( kappa_style ) {
04965 case ON::gaussian_curvature:
04966 k = K[i].GaussianCurvature();
04967 break;
04968 case ON::mean_curvature:
04969 k = fabs(K[i].MeanCurvature());
04970 break;
04971 case ON::min_curvature:
04972 k = fabs(K[i].MinimumRadius());
04973 break;
04974 case ON::max_curvature:
04975 k = fabs(K[i].MaximumRadius());
04976 break;
04977
04978
04979
04980
04981
04982
04983
04984
04985
04986
04987
04988
04989
04990
04991
04992
04993
04994
04995
04996
04997
04998
04999
05000
05001 default:
05002 k=0.0;
05003 break;
05004 }
05005 if ( fabs(k) >= m_infinity ) {
05006 m_count_infinite++;
05007 continue;
05008 }
05009 if ( m_count ) {
05010 if ( k < m_range.m_t[0] )
05011 m_range.m_t[0] = k;
05012 else if ( k > m_range.m_t[1] )
05013 m_range.m_t[1] = k;
05014 }
05015 else {
05016 m_range.m_t[0] = m_range.m_t[1] = k;
05017 }
05018 kappa[m_count++] = k;
05019 }
05020
05021
05022 if ( m_count == 0 )
05023 rc = false;
05024 else {
05025
05026 ON_SortDoubleArray( ON::quick_sort, kappa, m_count );
05027
05028
05029 m_mode = kappa[m_count/2];
05030 if ( 0 == (m_count % 2) ) {
05031 m_mode += kappa[(m_count/2)-1];
05032 m_mode *= 0.5;
05033 }
05034
05035
05036 for ( i = 0; i < m_count; i++ ) {
05037 m_average += kappa[i];
05038 }
05039 m_average = m_average/m_count;
05040
05041
05042 for ( i = 0; i < m_count; i++ ) {
05043 m_adev += fabs(kappa[i] - m_average);
05044 }
05045 m_adev = m_adev/m_count;
05046 }
05047 }
05048
05049 return rc;
05050 }
05051
05052 struct EDGEINFO
05053 {
05054 int fi[2];
05055 int vi[4];
05056 int flag;
05057
05058
05059
05060
05061
05062
05063
05064 double length;
05065 };
05066
05067 bool ON_Mesh::ConvertTrianglesToQuads(
05068 double angle_tol_radians,
05069 double min_diagonal_length_ratio
05070 )
05071 {
05072 ON_Workspace ws;
05073
05074 double d;
05075
05076 int i, ii, jj;
05077 int diagonal_count;
05078 const int* f0vi;
05079 const int* f1vi;
05080 const int* fei;
05081
05082 diagonal_count = 0;
05083
05084 if ( angle_tol_radians < 0.0 || !ON_IsValid(angle_tol_radians) )
05085 {
05086
05087 angle_tol_radians = 0.043633231299858239423092269212215;
05088 }
05089 else if ( angle_tol_radians < ON_ZERO_TOLERANCE )
05090 {
05091 angle_tol_radians = ON_ZERO_TOLERANCE;
05092 }
05093
05094 angle_tol_radians = cos(angle_tol_radians);
05095 if ( angle_tol_radians < 0.5 )
05096 angle_tol_radians = 0.5;
05097 else if ( angle_tol_radians > 1.0-ON_SQRT_EPSILON )
05098 angle_tol_radians = 1.0-ON_SQRT_EPSILON;
05099
05100 const ON_MeshTopology& top = Topology();
05101
05102 if ( !HasFaceNormals() )
05103 ComputeFaceNormals();
05104
05105 if ( min_diagonal_length_ratio < ON_ZERO_TOLERANCE )
05106 min_diagonal_length_ratio = ON_ZERO_TOLERANCE;
05107
05108 double max_diagonal_length_ratio = 1.0/min_diagonal_length_ratio;
05109
05110 if( min_diagonal_length_ratio > max_diagonal_length_ratio )
05111 {
05112 d = min_diagonal_length_ratio;
05113 min_diagonal_length_ratio = max_diagonal_length_ratio;
05114 max_diagonal_length_ratio = d;
05115 }
05116
05117
05118 double rel_tol = 8.0*ON_SQRT_EPSILON;
05119 if ( min_diagonal_length_ratio > 1.0-rel_tol )
05120 min_diagonal_length_ratio = 1.0-rel_tol;
05121 if ( max_diagonal_length_ratio < 1.0+rel_tol )
05122 max_diagonal_length_ratio = 1.0+rel_tol;
05123
05124
05125 const int face_count = m_F.Count();
05126 int* face_flag = ws.GetIntMemory(face_count);
05127 for ( i = 0; i < face_count; i++ )
05128 {
05129 f0vi = m_F[i].vi;
05130 face_flag[i] = ( f0vi[2] == f0vi[3] ) ? 0 : 1;
05131 }
05132
05133 const int edge_count = top.m_tope.Count();
05134 struct EDGEINFO* EI = (struct EDGEINFO*)ws.GetMemory(edge_count*sizeof(*EI));
05135 for ( i = 0; i < edge_count; i++ )
05136 {
05137 struct EDGEINFO& ei = EI[i];
05138 const ON_MeshTopologyEdge& tope = top.m_tope[i];
05139 ei.flag = 0;
05140 ei.vi[0] = top.m_topv[tope.m_topvi[0]].m_vi[0];
05141 ei.vi[2] = top.m_topv[tope.m_topvi[1]].m_vi[0];
05142 ei.length = m_V[ei.vi[0]].DistanceTo(m_V[ei.vi[2]]);
05143 if ( ei.length <= 0.0 || !ON_IsValid(ei.length) )
05144 {
05145 ei.flag = 5;
05146 }
05147 else if ( tope.m_topf_count != 2 )
05148 {
05149 ei.flag = 2;
05150 }
05151 else
05152 {
05153 ei.fi[0] = tope.m_topfi[0];
05154 ei.fi[1] = tope.m_topfi[1];
05155 if (face_flag[ei.fi[0]] || face_flag[ei.fi[1]] )
05156 {
05157 ei.flag = 1;
05158 }
05159 else if ( m_FN[ei.fi[0]] * m_FN[ei.fi[1]] < angle_tol_radians )
05160 {
05161 ei.flag = 3;
05162 }
05163 else
05164 {
05165 f0vi = m_F[ei.fi[0]].vi;
05166 f1vi = m_F[ei.fi[1]].vi;
05167 ei.flag = 6;
05168 for ( ii = 0; ii < 3 && ei.flag; ii++ )
05169 {
05170 for (jj = 0; jj < 3; jj++)
05171 {
05172 if ( f0vi[ii] == f1vi[jj]
05173 && f0vi[(ii+1)%3] == f1vi[(jj+2)%3]
05174 && f0vi[(ii+2)%3] != f1vi[(jj+1)%3] )
05175 {
05176 if ( ei.fi[0] > ei.fi[1] )
05177 {
05178 jj = ei.fi[0]; ei.fi[0] = ei.fi[1]; ei.fi[1] = jj;
05179 }
05180 ei.vi[0] = f0vi[ii];
05181 ei.vi[1] = f1vi[(jj+1)%3];
05182 ei.vi[2] = f0vi[(ii+1)%3];
05183 ei.vi[3] = f0vi[(ii+2)%3];
05184 ei.flag = 0;
05185 break;
05186 }
05187 }
05188 }
05189 }
05190 }
05191 }
05192
05193 for ( i = 0; i < edge_count; i++ )
05194 {
05195 struct EDGEINFO& ei = EI[i];
05196 if ( ei.flag )
05197 continue;
05198
05199 ei.flag = 16;
05200
05201
05202
05203
05204 fei = top.m_topf[ei.fi[0]].m_topei;
05205 if ( ( i != fei[0] && EI[fei[0]].length >= ei.length )
05206 || ( i != fei[1] && EI[fei[1]].length >= ei.length )
05207 || ( i != fei[2] && EI[fei[2]].length >= ei.length )
05208 )
05209 {
05210
05211 continue;
05212 }
05213
05214
05215
05216
05217 fei = top.m_topf[ei.fi[1]].m_topei;
05218 if ( ( i != fei[0] && EI[fei[0]].length >= ei.length )
05219 || ( i != fei[1] && EI[fei[1]].length >= ei.length )
05220 || ( i != fei[2] && EI[fei[2]].length >= ei.length )
05221 )
05222 {
05223
05224 continue;
05225 }
05226
05227 d = m_V[ei.vi[1]].DistanceTo(m_V[ei.vi[3]]);
05228 d /= ei.length;
05229 if ( d < min_diagonal_length_ratio || d > max_diagonal_length_ratio )
05230 {
05231
05232 continue;
05233 }
05234
05235 ei.flag = 0;
05236
05237 diagonal_count++;
05238 }
05239
05240 if ( diagonal_count > 0 )
05241 {
05242 DestroyTree();
05243 DestroyPartition();
05244 m_top.Destroy();
05245 for ( i = 0; i < edge_count; i++ )
05246 {
05247 struct EDGEINFO& ei = EI[i];
05248 if ( ei.flag )
05249 continue;
05250 memcpy( m_F[ei.fi[0]].vi, ei.vi, 4*sizeof(ei.vi[0]) );
05251 memset( m_F[ei.fi[1]].vi, 0xFF, 4*sizeof(ei.vi[0]) );
05252 m_triangle_count--;
05253 m_quad_count++;
05254 }
05255 CullDegenerateFaces();
05256 }
05257
05258 return (diagonal_count > 0 );
05259 }
05260
05261 bool ON_Mesh::ConvertQuadsToTriangles()
05262 {
05263 const bool bHasFaceNormals = HasFaceNormals();
05264 const int fcount = FaceCount();
05265 const int vcount = VertexCount();
05266 int fi, idmin;;
05267 double d0, d1, dmin, d;
05268 if ( fcount > 0 && QuadCount() > 0 )
05269 {
05270
05271
05272
05273 if ( m_F.Capacity() < fcount + m_quad_count )
05274 m_F.SetCapacity( fcount + m_quad_count );
05275 if ( bHasFaceNormals && m_FN.Capacity() < fcount + m_quad_count )
05276 m_FN.SetCapacity( fcount + m_quad_count );
05277
05278 const ON_3dPoint* dV = ( vcount > 0 && HasDoublePrecisionVertices()
05279 && ( HasSynchronizedDoubleAndSinglePrecisionVertices() || DoublePrecisionVerticesAreValid() )
05280 )
05281 ? DoublePrecisionVertices().Array()
05282 : 0;
05283
05284 const ON_3fPoint* fV = m_V.Array();
05285
05286 const double rel_tol = 8.0*( (0 != dV) ? ON_EPSILON : ON_FLOAT_EPSILON );
05287
05288 ON_3dVector FN;
05289
05290 for ( fi = 0; fi < fcount; fi++ )
05291 {
05292 ON_MeshFace& f0 = m_F[fi];
05293 if ( f0.IsValid(vcount) && f0.IsQuad() )
05294 {
05295 if ( 0 != dV )
05296 {
05297 d0 = dV[f0.vi[0]].DistanceTo(dV[f0.vi[2]]);
05298 d1 = dV[f0.vi[1]].DistanceTo(dV[f0.vi[3]]);
05299
05300
05301 idmin = -1;
05302 dmin = ((d0<=d1)?d0:d1)*rel_tol;
05303 if ( dmin > ON_ZERO_TOLERANCE )
05304 dmin = ON_ZERO_TOLERANCE;
05305 d = dV[f0.vi[0]].DistanceTo(dV[f0.vi[1]]);
05306 if ( d < dmin )
05307 {
05308 idmin = 0;
05309 dmin = d;
05310 }
05311 d = dV[f0.vi[1]].DistanceTo(dV[f0.vi[2]]);
05312 if ( d < dmin )
05313 {
05314 idmin = 1;
05315 dmin = d;
05316 }
05317 d = dV[f0.vi[2]].DistanceTo(dV[f0.vi[3]]);
05318 if ( d < dmin )
05319 {
05320 idmin = 2;
05321 dmin = d;
05322 }
05323 d = dV[f0.vi[3]].DistanceTo(dV[f0.vi[0]]);
05324 if ( d < dmin )
05325 {
05326 idmin = 3;
05327 dmin = d;
05328 }
05329 }
05330 else
05331 {
05332 d0 = m_V[f0.vi[0]].DistanceTo(m_V[f0.vi[2]]);
05333 d1 = m_V[f0.vi[1]].DistanceTo(m_V[f0.vi[3]]);
05334
05335
05336 idmin = -1;
05337 dmin = ((d0<=d1)?d0:d1)*rel_tol;
05338 if ( dmin > ON_ZERO_TOLERANCE )
05339 dmin = ON_ZERO_TOLERANCE;
05340 d = m_V[f0.vi[0]].DistanceTo(m_V[f0.vi[1]]);
05341 if ( d < dmin )
05342 {
05343 idmin = 0;
05344 dmin = d;
05345 }
05346 d = m_V[f0.vi[1]].DistanceTo(m_V[f0.vi[2]]);
05347 if ( d < dmin )
05348 {
05349 idmin = 1;
05350 dmin = d;
05351 }
05352 d = m_V[f0.vi[2]].DistanceTo(m_V[f0.vi[3]]);
05353 if ( d < dmin )
05354 {
05355 idmin = 2;
05356 dmin = d;
05357 }
05358 d = m_V[f0.vi[3]].DistanceTo(m_V[f0.vi[0]]);
05359 if ( d < dmin )
05360 {
05361 idmin = 3;
05362 dmin = d;
05363 }
05364 }
05365
05366 if ( !(d0 > 0.0) )
05367 {
05368 if ( !(d1 > 0.0) )
05369 continue;
05370
05371
05372 idmin = -1;
05373 d0 = 1.0;
05374 d1 = 0.0;
05375 }
05376 else if ( !(d1 > 0.0) )
05377 {
05378
05379
05380 idmin = -1;
05381 d1 = 1.0;
05382 d0 = 0.0;
05383 }
05384
05385 m_quad_count--;
05386 m_triangle_count++;
05387 if ( 0 == idmin )
05388 {
05389
05390 f0.vi[0] = f0.vi[1];
05391 f0.vi[1] = f0.vi[2];
05392 f0.vi[2] = f0.vi[3];
05393 }
05394 else if ( 1 == idmin )
05395 {
05396
05397 int vi0 = f0.vi[0];
05398 f0.vi[0] = f0.vi[2];
05399 f0.vi[1] = f0.vi[3];
05400 f0.vi[2] = vi0;
05401 f0.vi[3] = vi0;
05402 }
05403 else if ( 2 == idmin )
05404 {
05405
05406 f0.vi[2] = f0.vi[1];
05407 f0.vi[1] = f0.vi[0];
05408 f0.vi[0] = f0.vi[3];
05409 f0.vi[3] = f0.vi[2];
05410 }
05411 else if ( 3 == idmin )
05412 {
05413
05414 f0.vi[3] = f0.vi[2];
05415 }
05416 else
05417 {
05418
05419 ON_MeshFace& f1 = m_F.AppendNew();
05420 if ( d0 <= d1 )
05421 {
05422 f1.vi[0] = f0.vi[0];
05423 f1.vi[1] = f0.vi[2];
05424 f1.vi[2] = f0.vi[3];
05425 f1.vi[3] = f1.vi[2];
05426 f0.vi[3] = f0.vi[2];
05427 }
05428 else
05429 {
05430 f1.vi[0] = f0.vi[1];
05431 f1.vi[1] = f0.vi[2];
05432 f1.vi[2] = f0.vi[3];
05433 f1.vi[3] = f1.vi[2];
05434 f0.vi[2] = f0.vi[3];
05435 }
05436 if ( bHasFaceNormals )
05437 {
05438 if ( 0 != dV )
05439 {
05440 m_F[fi].ComputeFaceNormal(dV,FN);
05441 m_FN[fi] = FN;
05442 m_F[m_F.Count()-1].ComputeFaceNormal(dV,FN);
05443 }
05444 else
05445 {
05446 m_F[fi].ComputeFaceNormal(fV,FN);
05447 m_FN[fi] = FN;
05448 m_F[m_F.Count()-1].ComputeFaceNormal(fV,FN);
05449 }
05450 m_FN.AppendNew() = FN;
05451 }
05452 }
05453 }
05454 }
05455 if ( fcount != m_F.Count() )
05456 DestroyTopology();
05457 }
05458 return ( QuadCount() == 0 && TriangleCount() == FaceCount() ) ? true : false;
05459 }
05460
05461 bool ON_Mesh::CountQuads()
05462 {
05463 const int fcount = FaceCount();
05464 const int vcount = VertexCount();
05465 int fi;
05466 m_quad_count = 0;
05467 m_triangle_count = 0;
05468 m_invalid_count = 0;
05469 for ( fi = 0; fi < fcount; fi++ ) {
05470 const ON_MeshFace& f = m_F[fi];
05471 if ( f.IsValid(vcount) ) {
05472 if ( f.IsTriangle() )
05473 m_triangle_count++;
05474 else
05475 m_quad_count++;
05476 }
05477 else
05478 m_invalid_count++;
05479 }
05480 return true;
05481 }
05482
05483 bool ON_Mesh::ComputeVertexNormals()
05484 {
05485 bool rc = false;
05486 const int fcount = FaceCount();
05487 const int vcount = VertexCount();
05488 int vi, fi, j;
05489 ON_3fVector n;
05490
05491 if ( fcount > 0 && vcount > 0 ) {
05492 rc = HasFaceNormals();
05493 if ( !rc )
05494 rc = ComputeFaceNormals();
05495 if ( rc ) {
05496 ON_Workspace ws;
05497
05498 int* vfcount = ws.GetIntMemory( vcount );
05499 memset ( vfcount, 0, vcount*sizeof(*vfcount) );
05500
05501
05502 for ( fi = 0; fi < fcount; fi++ ) {
05503 ON_MeshFace& f = m_F[fi];
05504 if ( f.IsValid(vcount) ) {
05505 vfcount[f.vi[0]]++;
05506 vfcount[f.vi[1]]++;
05507 vfcount[f.vi[2]]++;
05508 if ( f.IsQuad() )
05509 vfcount[f.vi[3]]++;
05510 }
05511 }
05512
05513
05514 int** vfi = (int**)ws.GetMemory( vcount*sizeof(vfi[0] ) );
05515 {
05516 int scratch_sz = 0;
05517 for ( vi = 0; vi < vcount; vi++ ) {
05518 scratch_sz += vfcount[vi];
05519 }
05520 int* scratch = ws.GetIntMemory(scratch_sz);
05521 for ( vi = 0; vi < vcount; vi++ ) {
05522 if ( vfcount[vi] ) {
05523 vfi[vi] = scratch;
05524 scratch += vfcount[vi];
05525 }
05526 vfcount[vi] = 0;
05527 }
05528 }
05529 for ( fi = 0; fi < fcount; fi++ ) {
05530 ON_MeshFace& f = m_F[fi];
05531 if ( f.IsValid(vcount) ) {
05532 vi = f.vi[0]; vfi[vi][vfcount[vi]++] = fi;
05533 vi = f.vi[1]; vfi[vi][vfcount[vi]++] = fi;
05534 vi = f.vi[2]; vfi[vi][vfcount[vi]++] = fi;
05535 if ( f.IsQuad() ) {
05536 vi = f.vi[3]; vfi[vi][vfcount[vi]++] = fi;
05537 }
05538 }
05539 }
05540
05541
05542 m_N.SetCapacity(vcount);
05543 m_N.SetCount(0);
05544 for ( vi = 0; vi < vcount; vi++ ) {
05545 n.Zero();
05546 for ( j = vfcount[vi]-1; j >= 0; j-- ) {
05547 n += m_FN[vfi[vi][j]];
05548 }
05549 if ( !n.Unitize() )
05550 {
05551
05552
05553 n.Set(0,0,1);
05554 }
05555 m_N.Append(n);
05556 }
05557 }
05558 }
05559 return rc;
05560 }
05561
05562 bool ON_Mesh::NormalizeTextureCoordinates()
05563 {
05564 ON_2fPoint t0;
05565 int ti;
05566 const int vertex_count = m_V.Count();
05567 bool rc = HasSurfaceParameters();
05568 if ( rc )
05569 {
05570 const ON_2dPoint* S = m_S.Array();
05571 ON_Interval udom = m_srf_domain[0];
05572 ON_Interval vdom = m_srf_domain[1];
05573 rc = udom.IsIncreasing() && vdom.IsIncreasing();
05574 if ( !rc )
05575 {
05576 udom.Set(S[0].x,S[0].x);
05577 vdom.Set(S[0].y,S[0].y);
05578 for ( ti = 1; ti < vertex_count; ti++ )
05579 {
05580 if ( S[ti].x < udom.m_t[0] ) udom.m_t[0] = S[ti].x;
05581 else if ( S[ti].x > udom.m_t[1] ) udom.m_t[1] = S[ti].x;
05582 if ( S[ti].y < vdom.m_t[0] ) vdom.m_t[0] = S[ti].y;
05583 else if ( S[ti].y > vdom.m_t[1] ) vdom.m_t[1] = S[ti].y;
05584 }
05585 rc = udom.IsIncreasing() && vdom.IsIncreasing();
05586 }
05587
05588 if (rc)
05589 {
05590 m_T.Reserve(vertex_count);
05591 m_T.SetCount(0);
05592 for (ti = 0; ti < vertex_count; ti++ )
05593 {
05594 t0.x = (float)udom.NormalizedParameterAt(S[ti].x);
05595 t0.y = (float)vdom.NormalizedParameterAt(S[ti].y);
05596 m_T.Append(t0);
05597 }
05598 m_packed_tex_domain[0].Set(0.0,1.0);
05599 m_packed_tex_domain[1].Set(0.0,1.0);
05600 m_packed_tex_rotate = false;
05601 m_Ttag.SetDefaultSurfaceParameterMappingTag();
05602 if ( m_mesh_parameters )
05603 m_mesh_parameters->m_texture_range = 1;
05604 }
05605 }
05606
05607 return rc;
05608 }
05609
05610 bool ON_Mesh::TransposeSurfaceParameters()
05611 {
05612
05613 ON_Interval temp = m_srf_domain[0];
05614 m_srf_domain[0] = m_srf_domain[1];
05615 m_srf_domain[1] = temp;
05616
05617 double t = m_srf_scale[0];
05618 m_srf_scale[0] = m_srf_scale[1];
05619 m_srf_scale[1] = t;
05620
05621 int S_count = m_S.Count();
05622 ON_2dPoint* S_array = m_S.Array();
05623 for (int i = 0; i < S_count; i++ )
05624 {
05625 ON_2dPoint& S = S_array[i];
05626 t = S.x; S.x = S.y; S.y = t;
05627 }
05628 return true;
05629 }
05630
05631 bool ON_Mesh::HasPackedTextureRegion() const
05632 {
05633 return ( ON_IsValid(m_srf_scale[0])
05634 && m_srf_scale[0] > 0.0
05635 && ON_IsValid(m_srf_scale[1])
05636 && m_srf_scale[1] > 0.0
05637 && m_packed_tex_domain[0].IsInterval()
05638 && m_packed_tex_domain[1].IsInterval()
05639 && 0.0 <= m_packed_tex_domain[0].Min()
05640 && m_packed_tex_domain[0].Max() <= 1.0
05641 && 0.0 <= m_packed_tex_domain[1].Min()
05642 && m_packed_tex_domain[1].Max() <= 1.0
05643 && ( fabs(m_packed_tex_domain[0].Length()) < 1.0
05644 || fabs(m_packed_tex_domain[1].Length()) < 1.0)
05645 );
05646 }
05647
05648
05649 bool ON_Mesh::TransposeTextureCoordinates()
05650 {
05651 if ( !HasTextureCoordinates() )
05652 return false;
05653
05654 const int vcnt = m_T.Count();
05655 int i;
05656
05657 bool bPackedRegion = HasPackedTextureRegion();
05658
05659 bool bSrfParamTag = (!m_Ttag.IsSet() || m_Ttag.IsDefaultSurfaceParameterMapping());
05660
05661 if ( bPackedRegion && bSrfParamTag )
05662 {
05663
05664
05665
05666
05667
05668
05669 bool bRevU = m_packed_tex_domain[0].IsDecreasing();
05670 bool bRevV = m_packed_tex_domain[1].IsDecreasing();
05671 bool llur = (bRevU == bRevV) ? true : false;
05672 if ( m_packed_tex_rotate )
05673 llur = !llur;
05674
05675 ON_Interval TD[2];
05676 TD[0] = m_packed_tex_domain[0];
05677 TD[1] = m_packed_tex_domain[1];
05678 TD[0].MakeIncreasing();
05679 TD[1].MakeIncreasing();
05680 for( i=0; i<vcnt; i++)
05681 {
05682 ON_2fPoint tc = m_T[i];
05683 double x = TD[0].NormalizedParameterAt(tc[0]);
05684 double y = TD[1].NormalizedParameterAt(tc[1]);
05685 if(!llur)
05686 {
05687 x = 1.0-x;
05688 y = 1.0-y;
05689 }
05690 double s = TD[0].ParameterAt(y);
05691 double t = TD[1].ParameterAt(x);
05692 m_T[i].Set((float)s,(float)t);
05693 }
05694 }
05695 else
05696 {
05697 float f;
05698 for(i=0; i<vcnt; i++)
05699 {
05700 ON_2fPoint& tc = m_T[i];
05701 f = tc.x; tc.x = tc.y; tc.y = f;
05702 }
05703 }
05704 return true;
05705 }
05706
05707 bool ON_Mesh::ReverseTextureCoordinates( int dir )
05708 {
05709 if ( dir < 0 || dir > 1 || !HasTextureCoordinates() )
05710 return false;
05711
05712 bool bPackedRegion = HasPackedTextureRegion();
05713
05714 bool bSrfParamTag = (!m_Ttag.IsSet() || m_Ttag.IsDefaultSurfaceParameterMapping());
05715
05716 const int vcount = m_T.Count();
05717 int i;
05718 if ( bPackedRegion && bSrfParamTag )
05719 {
05720
05721
05722
05723
05724
05725
05726 if ( m_packed_tex_rotate )
05727 dir = 1-dir;
05728 const ON_Interval tex_dom = m_packed_tex_domain[dir];
05729 double s;
05730 m_packed_tex_domain[dir].Swap();
05731 for (i = 0; i < vcount; i++ )
05732 {
05733 ON_2fPoint& tc = m_T[i];
05734 s = 1.0 - tex_dom.NormalizedParameterAt(tc[dir]);
05735 if ( dir )
05736 tc.y = (float)tex_dom.ParameterAt(s);
05737 else
05738 tc.x = (float)tex_dom.ParameterAt(s);
05739 }
05740 }
05741 else
05742 {
05743 for (i = 0; i < vcount; i++ )
05744 {
05745 ON_2fPoint& tc = m_T[i];
05746 if ( dir )
05747 tc.y = 1.0f-tc.y;
05748 else
05749 tc.x = 1.0f-tc.x;
05750 }
05751 }
05752 return true;
05753 }
05754
05755 bool ON_Mesh::ReverseSurfaceParameters( int dir )
05756 {
05757 if ( dir < 0 || dir > 1 || !HasSurfaceParameters() )
05758 return false;
05759 if ( m_srf_domain[dir].IsIncreasing() )
05760 m_srf_domain[dir].Reverse();
05761 int i, vcount = m_S.Count();
05762 for (i = 0; i < vcount; i++)
05763 {
05764 ON_2dPoint& S = m_S[i];
05765 if ( dir )
05766 S.y = -S.y;
05767 else
05768 S.x = -S.x;
05769 }
05770 return true;
05771 }
05772
05773
05774 bool ON_Mesh::EvaluateMeshGeometry( const ON_Surface& srf )
05775 {
05776 bool rc = false;
05777 const int vcount = VertexCount();
05778 const bool bHasSurfaceParameters = HasSurfaceParameters();
05779 if ( bHasSurfaceParameters )
05780 {
05781 const bool bHasVertexNormals = HasVertexNormals();
05782 m_N.SetCapacity(vcount);
05783 int vi, side, hint[2];
05784 ON_3dPoint point;
05785 ON_3dVector normal, Ds, Dt, Dss, Dst, Dtt, K1, K2;
05786 const ON_2dPoint* srf_st;
05787 double s, t, kgauss, kmean;
05788 side = 0;
05789 hint[0] = 0;
05790 hint[1] = 0;
05791 const double smax = srf.Domain(0)[1];
05792 const double tmax = srf.Domain(1)[1];
05793 if ( HasPrincipalCurvatures() )
05794 {
05795 for ( vi = 0; vi < vcount; vi++ )
05796 {
05797
05798
05799 srf_st = &m_S[vi];
05800 s = srf_st->x;
05801 t = srf_st->y;
05802
05803
05804 side = ( smax == s ) ? ((tmax == t) ? 3 : 2) : ((tmax == t) ? 4 : 1);
05805 srf.Ev2Der( s, t, point, Ds, Dt, Dss, Dst, Dtt, side, hint );
05806 ON_EvNormal( side, Ds, Dt, Dss, Dst, Dtt, normal );
05807 ON_EvPrincipalCurvatures( Ds, Dt, Dss, Dst, Dtt, normal,
05808 &kgauss, &kmean,
05809 &m_K[vi].k1, &m_K[vi].k2,
05810 K1, K2 );
05811 m_V[vi] = &point.x;
05812 if ( bHasVertexNormals )
05813 m_N[vi] = &normal.x;
05814 }
05815 InvalidateCurvatureStats();
05816 }
05817 else if ( bHasVertexNormals )
05818 {
05819 for ( vi = 0; vi < vcount; vi++ )
05820 {
05821
05822 srf_st = &m_S[vi];
05823 s = srf_st->x;
05824 t = srf_st->y;
05825
05826
05827 side = ( smax == s ) ? ((tmax == t) ? 3 : 2) : ((tmax == t) ? 4 : 1);
05828 srf.EvNormal( s, t, point, normal, side, hint );
05829 m_V[vi] = &point.x;
05830 m_N[vi] = &normal.x;
05831 }
05832 }
05833 else
05834 {
05835 for ( vi = 0; vi < vcount; vi++ )
05836 {
05837
05838 srf_st = &m_S[vi];
05839 s = srf_st->x;
05840 t = srf_st->y;
05841 srf.EvPoint( s, t, point, side, hint );
05842 m_V[vi] = &point.x;
05843 }
05844 }
05845 if ( HasFaceNormals() )
05846 {
05847 ComputeFaceNormals();
05848 }
05849 rc = true;
05850
05851 m_Ctag.Default();
05852 InvalidateVertexBoundingBox();
05853 InvalidateVertexNormalBoundingBox();
05854 DeleteMeshParameters();
05855 DestroyTree();
05856 }
05857 return rc;
05858 }
05859
05860 void ON_Mesh::SetMeshParameters( const ON_MeshParameters& mp )
05861 {
05862 DeleteMeshParameters();
05863 m_mesh_parameters = new ON_MeshParameters(mp);
05864 }
05865
05866 const ON_MeshParameters* ON_Mesh::MeshParameters() const
05867 {
05868 return m_mesh_parameters;
05869 }
05870
05871 void ON_Mesh::DeleteMeshParameters()
05872 {
05873 if ( m_mesh_parameters ) {
05874 delete m_mesh_parameters;
05875 m_mesh_parameters = 0;
05876 }
05877 }
05878
05879 static int compare3fPoint( const ON_3fPoint* a, const ON_3fPoint* b )
05880 {
05881 if ( a->x < b->x ) return -1;
05882 if ( a->x > b->x ) return 1;
05883 if ( a->y < b->y ) return -1;
05884 if ( a->y > b->y ) return 1;
05885 if ( a->z < b->z ) return -1;
05886 if ( a->z > b->z ) return 1;
05887 return 0;
05888 }
05889
05890 static int compare3dPoint( const ON_3dPoint* a, const ON_3dPoint* b )
05891 {
05892 if ( a->x < b->x ) return -1;
05893 if ( a->x > b->x ) return 1;
05894 if ( a->y < b->y ) return -1;
05895 if ( a->y > b->y ) return 1;
05896 if ( a->z < b->z ) return -1;
05897 if ( a->z > b->z ) return 1;
05898 return 0;
05899 }
05900
05901 typedef int (*ON_COMPAR_LPVOID_LPVOID)(const void*,const void*);
05902
05903 static
05904 int GetPointMap( int pt_count, const ON_3fPoint* fV, const ON_3dPoint* dV, ON_SimpleArray<int>& pt_map )
05905 {
05906
05907
05908
05909 int vt0, vt1;
05910 ON_3fPoint fp0;
05911 ON_3dPoint dp0;
05912 int* map;
05913 int* index;
05914 int max_pt_index = 0;
05915 if ( pt_count > 0 && (dV || fV) )
05916 {
05917 index = (int*)onmalloc(pt_count*sizeof(*index));
05918
05919 if ( dV )
05920 ON_Sort( ON::quick_sort, index, dV, pt_count, sizeof(*dV), (ON_COMPAR_LPVOID_LPVOID)compare3dPoint );
05921 else
05922 ON_Sort( ON::quick_sort, index, fV, pt_count, sizeof(*fV), (ON_COMPAR_LPVOID_LPVOID)compare3fPoint );
05923
05924 pt_map.SetCapacity( pt_count );
05925 pt_map.SetCount( pt_count );
05926 map = pt_map.Array();
05927 for ( vt0 = 0; vt0 < pt_count; vt0++ )
05928 map[vt0] = -1;
05929
05930 if ( dV )
05931 {
05932 for (vt0 = 0; vt0 < pt_count; vt0 = vt1, max_pt_index++)
05933 {
05934 dp0 = dV[index[vt0]];
05935 for ( vt1=vt0+1; vt1<pt_count && 0==compare3dPoint(&dp0,dV+index[vt1]); vt1++ ) {
05936
05937 }
05938 while ( vt0 < vt1 ) {
05939 map[index[vt0++]] = max_pt_index;
05940 }
05941 }
05942 }
05943 else
05944 {
05945 for (vt0 = 0; vt0 < pt_count; vt0 = vt1, max_pt_index++)
05946 {
05947 fp0 = fV[index[vt0]];
05948 for ( vt1=vt0+1; vt1<pt_count && 0==compare3fPoint(&fp0,fV+index[vt1]); vt1++ ) {
05949
05950 }
05951 while ( vt0 < vt1 ) {
05952 map[index[vt0++]] = max_pt_index;
05953 }
05954 }
05955 }
05956 onfree(index);
05957 }
05958 if ( max_pt_index == 0 )
05959 pt_map.Destroy();
05960 return max_pt_index;
05961 }
05962
05963 int ON_Mesh::CullDegenerateFaces()
05964 {
05965
05966
05967
05968 int bad_count = 0;
05969 int degenerate_count = 0;
05970 const int fcount = m_F.Count();
05971 const int vcount = m_V.Count();
05972 ON_MeshFace f;
05973 int fi;
05974
05975 if ( fcount > 0 )
05976 {
05977
05978
05979 ON_SimpleArray<int> topv_map;
05980 const ON_3dPoint* dV = Mesh_dV(*this);
05981 const ON_3fPoint* fV = (0 == dV) ? m_V.Array() : 0;
05982 const int topv_count = GetPointMap( m_V.Count(), fV, dV, topv_map );
05983 if ( topv_count > 0 && topv_map.Count() == m_V.Count() )
05984 {
05985 ON_Workspace ws;
05986 const int* vtop = topv_map.Array();
05987 unsigned char* bBadFace = (unsigned char*)ws.GetMemory(fcount*sizeof(*bBadFace));
05988 memset( bBadFace, 0, fcount*sizeof(*bBadFace) );
05989 for ( fi = 0; fi < fcount; fi++ )
05990 {
05991 ON_MeshFace& f0 = m_F[fi];
05992
05993 {
05994 int f0vi = f0.vi[0];
05995 f.vi[0] = (f0vi < 0 || f0vi >= vcount) ? -1 : vtop[f0vi];
05996
05997 f0vi = f0.vi[1];
05998 f.vi[1] = (f0vi < 0 || f0vi >= vcount) ? -1 : vtop[f0vi];
05999
06000 f0vi = f0.vi[2];
06001 f.vi[2] = (f0vi < 0 || f0vi >= vcount) ? -1 : vtop[f0vi];
06002
06003 f0vi = f0.vi[3];
06004 f.vi[3] = (f0vi < 0 || f0vi >= vcount) ? -1 : vtop[f0vi];
06005 }
06006
06007 if ( !f.IsValid(topv_count) )
06008 {
06009 degenerate_count++;
06010
06011 if ( f.vi[0] == f.vi[1] || f.vi[0] < 0 || f.vi[0] >= topv_count )
06012 {
06013 f0.vi[0] = f0.vi[1];
06014 f0.vi[1] = f0.vi[2];
06015 f0.vi[2] = f0.vi[3];
06016 f.vi[0] = f.vi[1];
06017 f.vi[1] = f.vi[2];
06018 f.vi[2] = f.vi[3];
06019 }
06020
06021 if ( f.vi[1] == f.vi[2] || f.vi[1] < 0 || f.vi[1] >= topv_count )
06022 {
06023 f0.vi[1] = f0.vi[2];
06024 f0.vi[2] = f0.vi[3];
06025 f.vi[1] = f.vi[2];
06026 f.vi[2] = f.vi[3];
06027 }
06028
06029 if ( f.vi[2] < 0 || f.vi[2] >= topv_count )
06030 {
06031 f0.vi[2] = f0.vi[3];
06032 f.vi[2] = f.vi[3];
06033 }
06034
06035 if ( f.vi[3] < 0 || f.vi[3] >= topv_count )
06036 {
06037 f0.vi[3] = f0.vi[2];
06038 f.vi[3] = f.vi[2];
06039 }
06040 else if ( f.vi[0] == f.vi[3] && f.vi[2] != f.vi[3] )
06041 {
06042 f0.vi[0] = f0.vi[1];
06043 f0.vi[1] = f0.vi[2];
06044 f0.vi[2] = f0.vi[3];
06045 f.vi[0] = f.vi[1];
06046 f.vi[1] = f.vi[2];
06047 f.vi[2] = f.vi[3];
06048 }
06049
06050 if ( !f0.IsValid(vcount) || !f.IsValid(topv_count) )
06051 {
06052
06053 bBadFace[fi] = 1;
06054 bad_count++;
06055 }
06056 }
06057 }
06058
06059 if ( bad_count > 0 )
06060 {
06061
06062 bool bHasFN = (m_FN.Count() == m_F.Count());
06063 if ( !bHasFN )
06064 m_FN.SetCount(0);
06065
06066 int fcnt = 0;
06067 for ( fi = fcnt = 0; fi < fcount; fi++ )
06068 {
06069 if ( !bBadFace[fi] )
06070 {
06071 if ( fcnt < fi )
06072 {
06073 m_F[fcnt] = m_F[fi];
06074 if ( bHasFN )
06075 m_FN[fcnt] = m_FN[fi];
06076 }
06077 fcnt++;
06078 }
06079 }
06080
06081 m_F.SetCount(fcnt);
06082 if ( bHasFN )
06083 m_FN.SetCount(fcnt);
06084 }
06085
06086 if ( degenerate_count > 0 )
06087 {
06088
06089
06090 DestroyTree();
06091 DestroyPartition();
06092 DestroyTopology();
06093 m_invalid_count = 0;
06094 m_quad_count = 0;
06095 m_triangle_count = 0;
06096 }
06097 }
06098 }
06099 return degenerate_count;
06100 }
06101
06102 int ON_Mesh::CullUnusedVertices()
06103 {
06104
06105 int vi, fi;
06106 ON_Workspace ws;
06107 CullDegenerateFaces();
06108 int fcnt = m_F.Count();
06109 int vcnt = m_V.Count();
06110 int * vmap = ws.GetIntMemory( vcnt );
06111 memset ( vmap, 0, vcnt*sizeof(vmap[0]) );
06112 for ( fi = 0; fi < fcnt; fi++ )
06113 {
06114 const ON_MeshFace& f = m_F[fi];
06115 vmap[f.vi[0]] = 1;
06116 vmap[f.vi[1]] = 1;
06117 vmap[f.vi[2]] = 1;
06118 vmap[f.vi[3]] = 1;
06119 }
06120
06121 int newvcnt = 0;
06122 for ( vi = 0; vi < vcnt; vi++ )
06123 {
06124 if ( vmap[vi] )
06125 vmap[vi] = newvcnt++;
06126 else {
06127 vmap[vi] = -1;
06128 }
06129 }
06130
06131 if ( newvcnt == 0 )
06132 Destroy();
06133 else if ( newvcnt < vcnt )
06134 {
06135 DestroyTopology();
06136
06137
06138 void* buffer = ws.GetMemory(vcnt*9*sizeof(double));
06139
06140 if ( HasSurfaceParameters() ) {
06141 ON_2dPoint* s = (ON_2dPoint*)buffer;
06142 for ( vi = 0; vi < vcnt; vi++ )
06143 {
06144 if ( vmap[vi]>=0 )
06145 s[vmap[vi]] = m_S[vi];
06146 }
06147 memcpy( m_S.Array(), s, newvcnt*sizeof(s[0]) );
06148 m_S.SetCount(newvcnt);
06149 }
06150
06151 if ( HasDoublePrecisionVertices() )
06152 {
06153 ON_3dPointArray& D = DoublePrecisionVertices();
06154 if ( vcnt == D.Count() )
06155 {
06156 bool bValidDoubles = DoublePrecisionVerticesAreValid();
06157 ON_3dPoint* s = (ON_3dPoint*)buffer;
06158 for ( vi = 0; vi < vcnt; vi++ )
06159 {
06160 if ( vmap[vi]>=0 )
06161 s[vmap[vi]] = D[vi];
06162 }
06163 memcpy( D.Array(), s, newvcnt*sizeof(s[0]) );
06164 D.SetCount(newvcnt);
06165 if ( bValidDoubles )
06166 SetDoublePrecisionVerticesAsValid();
06167 }
06168 else
06169 {
06170 DestroyDoublePrecisionVertices();
06171 }
06172 }
06173
06174 if ( HasVertexNormals() ) {
06175 ON_3fVector* v = (ON_3fVector*)buffer;
06176 for ( vi = 0; vi < vcnt; vi++ )
06177 {
06178 if ( vmap[vi]>=0 )
06179 v[vmap[vi]] = m_N[vi];
06180 }
06181 memcpy( m_N.Array(), v, newvcnt*sizeof(v[0]) );
06182 m_N.SetCount(newvcnt);
06183 }
06184
06185 if ( HasTextureCoordinates() ) {
06186 ON_2fPoint* t = (ON_2fPoint*)buffer;
06187 for ( vi = 0; vi < vcnt; vi++ )
06188 {
06189 if ( vmap[vi]>=0 )
06190 t[vmap[vi]] = m_T[vi];
06191 }
06192 memcpy( m_T.Array(), t, newvcnt*sizeof(t[0]) );
06193 m_T.SetCount(newvcnt);
06194 }
06195
06196 if ( HasPrincipalCurvatures() ) {
06197 ON_SurfaceCurvature* k = (ON_SurfaceCurvature*)buffer;
06198 for ( vi = 0; vi < vcnt; vi++ )
06199 {
06200 if ( vmap[vi]>=0 )
06201 k[vmap[vi]] = m_K[vi];
06202 }
06203 memcpy( m_K.Array(), k, newvcnt*sizeof(k[0]) );
06204 m_K.SetCount(newvcnt);
06205 }
06206
06207 if ( HasVertexColors() ) {
06208 ON_Color* c = (ON_Color*)buffer;
06209 for ( vi = 0; vi < vcnt; vi++ )
06210 {
06211 if ( vmap[vi]>=0 )
06212 c[vmap[vi]] = m_C[vi];
06213 }
06214 memcpy( m_C.Array(), c, newvcnt*sizeof(c[0]) );
06215 m_C.SetCount(newvcnt);
06216 }
06217
06218 {
06219 bool bValidSingles = SinglePrecisionVerticesAreValid();
06220 ON_3fPoint* p = (ON_3fPoint*)buffer;
06221 for ( vi = 0; vi < vcnt; vi++ )
06222 {
06223 if ( vmap[vi]>=0 )
06224 p[vmap[vi]] = m_V[vi];
06225 }
06226 memcpy( m_V.Array(), p, newvcnt*sizeof(p[0]) );
06227 m_V.SetCount(newvcnt);
06228 if ( bValidSingles )
06229 SetSinglePrecisionVerticesAsValid();
06230 }
06231
06232 for ( fi = 0; fi < fcnt; fi++ )
06233 {
06234 ON_MeshFace& f = m_F[fi];
06235 f.vi[0] = vmap[f.vi[0]];
06236 f.vi[1] = vmap[f.vi[1]];
06237 f.vi[2] = vmap[f.vi[2]];
06238 f.vi[3] = vmap[f.vi[3]];
06239 }
06240
06241 }
06242 return vcnt - newvcnt;
06243 }
06244
06245 bool ON_Mesh::Compact()
06246 {
06247
06248 CullUnusedVertices();
06249 m_V.Shrink();
06250 m_F.Shrink();
06251 m_N.Shrink();
06252 m_FN.Shrink();
06253 m_K.Shrink();
06254 m_C.Shrink();
06255 m_S.Shrink();
06256 m_T.Shrink();
06257 return true;
06258 }
06259
06261
06262
06263
06264 double ON_SurfaceCurvature::GaussianCurvature() const
06265 {
06266 return k1*k2;
06267 }
06268
06269 double ON_SurfaceCurvature::MeanCurvature() const
06270 {
06271 return 0.5*(k1+k2);
06272 }
06273
06274 double ON_SurfaceCurvature::MinimumRadius() const
06275 {
06276 double k;
06277 k = (fabs(k1)>=fabs(k2)) ? fabs(k1) : fabs(k2);
06278 k = ( k > 1.0e-300 ) ? 1.0/k : 1.0e300;
06279 return k;
06280 }
06281
06282 double ON_SurfaceCurvature::MaximumRadius() const
06283 {
06284 double k;
06285 if ( k1*k2 <= 0.0 ) {
06286
06287
06288 k = 0.0;
06289 }
06290 else {
06291 k = (fabs(k1)<=fabs(k2)) ? fabs(k1) : fabs(k2);
06292 }
06293
06294 k = ( k > 1.0e-300 ) ? 1.0/k : 1.0e300;
06295 return k;
06296 }
06297
06298
06299
06300
06301
06302
06303
06304
06305
06306
06307
06308
06309
06310
06311
06312
06313
06314
06315 ON_MeshTopology::ON_MeshTopology()
06316 : m_mesh(0)
06317 , m_memchunk(0)
06318 , m_b32IsValid(0)
06319 {
06320 }
06321
06322 ON_MeshTopology::~ON_MeshTopology()
06323 {
06324 Destroy();
06325 }
06326
06327 void ON_MeshTopology::Destroy()
06328 {
06329 m_topv_map.Destroy();
06330 m_topv.Destroy();
06331 m_tope.Destroy();
06332 m_topf.Destroy();
06333 struct memchunk *p, *n;
06334 n = m_memchunk;
06335 while(n)
06336 {
06337 p = n;
06338 n = n->next;
06339 onfree(p);
06340 }
06341 m_memchunk = 0;
06342 if ( -1 != m_b32IsValid)
06343 m_b32IsValid = 0;
06344 }
06345
06346 void ON_MeshTopology::EmergencyDestroy()
06347 {
06348 m_mesh = 0;
06349 m_topv_map.EmergencyDestroy();
06350 m_topv.EmergencyDestroy();
06351 m_tope.EmergencyDestroy();
06352 m_topf.EmergencyDestroy();
06353 m_memchunk = 0;
06354 m_b32IsValid = 0;
06355 }
06356
06357 int ON_MeshTopology::TopVertexCount() const
06358 {
06359 return m_topv.Count();
06360 }
06361
06363
06364 int ON_MeshTopology::TopEdgeCount() const
06365 {
06366 return m_tope.Count();
06367 }
06368
06370
06371 int ON_MeshTopology::TopFaceCount() const
06372 {
06373 return m_topf.Count();
06374 }
06375
06376 ON_3fPoint ON_MeshTopology::TopVertexPoint( int vtopi ) const
06377 {
06378 return m_mesh->m_V[m_topv[vtopi].m_vi[0]];
06379 }
06380
06381 ON_Line ON_MeshTopology::TopEdgeLine( int tope_index ) const
06382 {
06383 ON_Line L(ON_UNSET_POINT,ON_UNSET_POINT);
06384 if ( m_mesh && tope_index >= 0 && tope_index < m_tope.Count() )
06385 {
06386 const int* topvi = m_tope[tope_index].m_topvi;
06387 if ( topvi[0] >= 0 && topvi[0] < m_topv.Count()
06388 && topvi[1] >= 0 && topvi[1] < m_topv.Count() )
06389 {
06390 const ON_MeshTopologyVertex& v0 = m_topv[topvi[0]];
06391 const ON_MeshTopologyVertex& v1 = m_topv[topvi[1]];
06392 if ( v0.m_v_count > 0 && v0.m_vi && v1.m_v_count > 0 && v1.m_vi )
06393 {
06394 int vi0 = v0.m_vi[0];
06395 int vi1 = v1.m_vi[0];
06396 int vcount = m_mesh->m_V.Count();
06397 if ( vi0 >= 0 && vi0 < vcount && vi1 >= 0 && vi1 < vcount )
06398 {
06399 L.from = m_mesh->m_V[vi0];
06400 L.to = m_mesh->m_V[vi1];
06401 }
06402 }
06403 }
06404 }
06405 return L;
06406 }
06407
06409
06410
06411 int ON_MeshTopology::TopEdge( int vtopi0, int vtopi1 ) const
06412 {
06413 int i0, i1, ei, vi0;
06414 if ( vtopi0 > vtopi1 ) {vi0 = vtopi0; vtopi0 = vtopi1; vtopi1 = vi0;}
06415 if ( vtopi0 < vtopi1 ) {
06416 const int tope_count = TopEdgeCount();
06417 const ON_MeshTopologyEdge* tope = m_tope.Array();
06418 i0 = 0;
06419 i1 = tope_count;
06420 while ( i0 < i1 )
06421 {
06422 ei = (i0+i1)/2;
06423 vi0 = tope[ei].m_topvi[0];
06424 if ( vi0 < vtopi0 ) {
06425 if ( i0 == ei )
06426 break;
06427 i0 = ei;
06428 }
06429 else if ( vi0 > vtopi0 ) {
06430 if ( i1 == ei )
06431 break;
06432 i1 = ei;
06433 }
06434 else {
06435 while (ei > 0 && tope[ei-1].m_topvi[0] == vtopi0 )
06436 ei--;
06437 while ( ei < tope_count && tope[ei].m_topvi[0] == vtopi0 ) {
06438 if ( tope[ei].m_topvi[1] == vtopi1 )
06439 return ei;
06440 ei++;
06441 }
06442 break;
06443 }
06444 }
06445 }
06446 return -1;
06447 }
06448
06449 bool ON_MeshTopology::GetTopFaceVertices( int fi, int topvi[4] ) const
06450 {
06451 if ( fi >= 0 && fi < m_mesh->m_F.Count() ) {
06452 const int* fvi = m_mesh->m_F[fi].vi;
06453 topvi[0] = m_topv_map[fvi[0]];
06454 topvi[1] = m_topv_map[fvi[1]];
06455 topvi[2] = m_topv_map[fvi[2]];
06456 topvi[3] = m_topv_map[fvi[3]];
06457 }
06458 return true;
06459 }
06460
06461 bool ON_MeshTopology::SortVertexEdges() const
06462 {
06463 bool rc = true;
06464 int topvi, topv_count = m_topv.Count();
06465 for ( topvi = 0; topvi < topv_count; topvi++ )
06466 {
06467 if ( !SortVertexEdges(topvi) )
06468 rc = false;
06469 }
06470 return rc;
06471 }
06472
06473
06474 static
06475 void ON_ReverseIntArray(
06476 int* e,
06477 size_t nel
06478 )
06479 {
06480 int ei;
06481 size_t i;
06482 nel--;
06483 for ( i = 0; i<nel; i++, nel--)
06484 {
06485 ei = e[i];
06486 e[i] = e[nel];
06487 e[nel] = ei;
06488 }
06489 }
06490
06491 bool ON_MeshTopology::SortVertexEdges(int topvi) const
06492 {
06493 if ( topvi < 0 || topvi >= m_topv.Count() )
06494 return false;
06495
06496 const ON_MeshTopologyVertex& topv = m_topv[topvi];
06497 if ( topv.m_tope_count < 2 )
06498 return true;
06499
06500
06501
06502
06503
06504 int i, j;
06505 int topei;
06506 int vei;
06507 int efcnt;
06508 int* new_tope = (int*)alloca(5*topv.m_tope_count*sizeof(new_tope[0]));
06509 int* e2f = new_tope + topv.m_tope_count;
06510 int* e1f = e2f + topv.m_tope_count;
06511 int e1fcnt = 0;
06512 int e2fcnt = 0;
06513 {
06514 int* e3f = e1f + topv.m_tope_count;
06515 int* e0f = e3f + topv.m_tope_count;
06516 int e3fcnt = 0;
06517 int e0fcnt = 0;
06518
06519 for ( vei = 0; vei < topv.m_tope_count; vei++ )
06520 {
06521 topei = topv.m_topei[vei];
06522 if ( topei >= 0 && topei < m_tope.Count() )
06523 {
06524 const ON_MeshTopologyEdge& tope = m_tope[topei];
06525 if ( tope.m_topvi[0] == topvi || tope.m_topvi[1] == topvi )
06526 {
06527 efcnt = m_tope[topei].m_topf_count;
06528 if ( efcnt < 0 )
06529 {
06530 ON_ERROR("ON_MeshTopology::SortVertexEdges(int topvi) - m_tope[topei].m_topf_count < 0");
06531 return false;
06532 }
06533 switch(efcnt)
06534 {
06535 case 0:
06536
06537 e0f[e0fcnt++] = topei;
06538 break;
06539
06540 case 1:
06541 e1f[e1fcnt++] = topei;
06542 break;
06543
06544 case 2:
06545 e2f[e2fcnt++] = topei;
06546 break;
06547
06548 default:
06549
06550 e3f[e3fcnt++] = topei;
06551 break;
06552 }
06553 }
06554 }
06555 }
06556
06557
06558 for ( i = 0; i < e3fcnt; i++ )
06559 {
06560 e1f[e1fcnt++] = e3f[i];
06561 }
06562
06563
06564 for ( i = 0; i < e0fcnt; i++ )
06565 {
06566 e1f[e1fcnt++] = e0f[i];
06567 }
06568
06569 e0fcnt = 0;
06570 e3fcnt = 0;
06571 e0f = 0;
06572 e3f = 0;
06573 }
06574
06575
06576
06577
06578
06579 if ( e1fcnt + e2fcnt != topv.m_tope_count )
06580 {
06581 ON_ERROR("ON_MeshTopology::SortVertexEdges() input vertex had bogus m_topei[]");
06582 return false;
06583 }
06584 int fi = -1;
06585 int next_topei = -1;
06586 int efi, fecnt, fei, next_fei;
06587 vei = 0;
06588 int vei0 = 0;
06589 int vei1 = 0;
06590 int elist_dir = 0;
06591 while(vei < topv.m_tope_count)
06592 {
06593 if ( next_topei >= 0 )
06594 {
06595
06596 topei = next_topei;
06597 next_topei = -1;
06598 }
06599 else if ( e1fcnt > 0 )
06600 {
06601
06602 topei = *e1f++;
06603 e1fcnt--;
06604 vei1 = vei;
06605 }
06606 else if ( e2fcnt > 0 )
06607 {
06608
06609
06610 topei = *e2f++;
06611 e2fcnt--;
06612 vei1 = vei;
06613 }
06614 else
06615 {
06616 ON_ERROR("ON_MeshTopology::SortVertexEdges() input vertex had bogus topology information.");
06617 return false;
06618 }
06619
06620 if ( vei0 < vei1 )
06621 {
06622 if ( 1 == elist_dir )
06623 {
06624
06625
06626
06627
06628
06629
06630 ON_ReverseIntArray( new_tope+vei0, vei1-vei0 );
06631 }
06632 elist_dir = 0;
06633 vei0 = vei1;
06634 }
06635
06636 new_tope[vei++] = topei;
06637
06638
06639 const ON_MeshTopologyEdge& tope = m_tope[topei];
06640 for ( efi = 0; next_topei < 0 && efi < tope.m_topf_count; efi++ )
06641 {
06642 fi = tope.m_topfi[efi];
06643 if ( fi < 0 || fi >= m_topf.Count() )
06644 {
06645
06646 continue;
06647 }
06648
06649
06650 const ON_MeshTopologyFace& topf = m_topf[fi];
06651 fecnt = topf.IsQuad() ? 4 : 3;
06652 for ( fei = 0; fei < fecnt; fei++ )
06653 {
06654 if ( topf.m_topei[fei] != topei )
06655 continue;
06656
06657 if ( tope.m_topvi[0] == topvi )
06658 {
06659 next_fei = ( topf.m_reve[fei] ) ? 1 : -1;
06660 }
06661 else
06662 {
06663 next_fei = ( topf.m_reve[fei] ) ? -1 : 1;
06664 }
06665
06666 if ( 0 == elist_dir )
06667 elist_dir = next_fei;
06668
06669 next_fei = (fei+next_fei+fecnt)%fecnt;
06670 next_topei = topf.m_topei[next_fei];
06671
06672
06673
06674
06675 j = 0;
06676 for ( i = 0; i < e1fcnt; i++ )
06677 {
06678 if ( next_topei == e1f[i] )
06679 {
06680
06681 for ( j = i+1; j < e1fcnt; j++ )
06682 e1f[j-1] = e1f[j];
06683 e1fcnt--;
06684 break;
06685 }
06686 }
06687 if ( 0 == j )
06688 {
06689
06690 for ( i = 0; i < e2fcnt; i++ )
06691 {
06692 if ( next_topei == e2f[i] )
06693 {
06694 for ( j = i+1; j < e2fcnt; j++ )
06695 e2f[j-1] = e2f[j];
06696 e2fcnt--;
06697 break;
06698 }
06699 }
06700 }
06701 if ( 0 == j )
06702 {
06703
06704
06705 next_topei = -1;
06706 }
06707 else
06708 {
06709 break;
06710 }
06711 }
06712 }
06713 }
06714
06715 if ( topv.m_tope_count != vei )
06716 {
06717 ON_ERROR("ON_MeshTopology::SortVertexEdges() edge sorting error.");
06718 return false;
06719 }
06720
06721 vei1 = vei;
06722 if ( vei0 < vei1 )
06723 {
06724 if ( 1 == elist_dir )
06725 {
06726
06727
06728
06729
06730
06731
06732 ON_ReverseIntArray( new_tope+vei0, vei1-vei0 );
06733 }
06734 elist_dir = 0;
06735 vei0 = vei1;
06736 }
06737
06738 int* topv_m_topei = const_cast<int*>(topv.m_topei);
06739 for ( vei = 0; vei < topv.m_tope_count; vei++ )
06740 {
06741 topv_m_topei[vei] = new_tope[vei];
06742 }
06743
06744 return true;
06745 }
06746
06747 int* ON_MeshTopology::GetIntArray(int length)
06748 {
06749 int* a = 0;
06750 if ( length > 0 ) {
06751 struct memchunk* pm;
06752 pm = (struct memchunk*)onmalloc(length*sizeof(*a) + sizeof(*pm));
06753 if ( pm ) {
06754 pm->next = m_memchunk;
06755 m_memchunk = pm++;
06756 a = (int*)pm;
06757 }
06758 }
06759 return a;
06760 }
06761
06762 bool ON_MeshTopologyFace::IsTriangle() const
06763 {
06764 return ( m_topei[2] == m_topei[3] && m_topei[0] != m_topei[1] )
06765 ? true : false;
06766 }
06767
06768 bool ON_MeshTopologyFace::IsQuad() const
06769 {
06770 return ( m_topei[2] != m_topei[3] ) ? true : false;
06771 }
06772
06773 bool ON_MeshTopologyFace::IsValid() const
06774 {
06775 return ( m_topei[0] != m_topei[1] ) ? true : false;
06776 }
06777
06778
06779 bool ON_MeshTopology::IsValid() const
06780 {
06781 ON_Workspace ws;
06782 int topvi, topei, topfi, vi, fi, j, jmax, k, tfvi[4];
06783 ON_3fPoint p;
06784
06785 WaitUntilReady(0);
06786
06787
06788 if ( 1 != m_b32IsValid )
06789 return false;
06790 if ( !m_mesh )
06791 return false;
06792 if ( this != &(m_mesh->Topology()) )
06793 return false;
06794 const int v_count = m_mesh->VertexCount();
06795 const int f_count = m_mesh->FaceCount();
06796 const int topv_count = TopVertexCount();
06797 const int tope_count = TopEdgeCount();
06798 const int topf_count = TopFaceCount();
06799 if ( topv_count > v_count || topv_count < 0 )
06800 return false;
06801 if ( topv_count == 0 && v_count > 0 )
06802 return false;
06803 if ( topf_count != f_count )
06804 return false;
06805 if ( f_count > 0 && tope_count < 3 )
06806 return false;
06807 if ( m_topv_map.Count() != v_count )
06808 return false;
06809
06810
06811 for ( vi = 0; vi < v_count; vi++ ) {
06812 topvi = m_topv_map[vi];
06813 if ( topvi < 0 || topvi >= topv_count )
06814 return false;
06815 }
06816
06817 char* vCheck = (char*)ws.GetMemory( v_count*sizeof(*vCheck) );
06818 memset( vCheck, 0, v_count*sizeof(*vCheck) );
06819 for ( topvi = 0; topvi < topv_count; topvi++ )
06820 {
06821 const ON_MeshTopologyVertex& topv = m_topv[topvi];
06822 if ( topv.m_v_count <= 0 )
06823 return false;
06824 if ( !topv.m_vi )
06825 return false;
06826 p = TopVertexPoint(topvi);
06827 for ( j = 0; j < topv.m_v_count; j++ ) {
06828 vi = topv.m_vi[j];
06829 if ( vi < 0 )
06830 return false;
06831 if ( vi >= v_count )
06832 return false;
06833 if ( vCheck[vi] != 0 )
06834 return false;
06835 if ( compare3fPoint( &p, &m_mesh->m_V[vi] ) )
06836 return false;
06837 if ( m_topv_map[vi] != topvi )
06838 return false;
06839 vCheck[vi] = 1;
06840 }
06841
06842
06843 if ( topv.m_tope_count < 0 )
06844 return false;
06845 if ( topv.m_tope_count == 0 && topv.m_topei )
06846 return false;
06847 if ( topv.m_tope_count > 0 && !topv.m_topei )
06848 return false;
06849 for ( j = 0; j < topv.m_tope_count; j++ ) {
06850 topei = topv.m_topei[j];
06851 if ( topei < 0 )
06852 return false;
06853 if ( topei >= tope_count )
06854 return false;
06855 const ON_MeshTopologyEdge& tope = m_tope[topei];
06856 if ( tope.m_topvi[0] != topvi && tope.m_topvi[1] != topvi )
06857 return false;
06858 for ( k = 0; k < j; k++ ) {
06859 if ( topv.m_topei[k] == topei )
06860 return false;
06861 }
06862 }
06863 }
06864
06865
06866 for ( vi = 0; vi < v_count; vi++ ) {
06867 if ( vCheck[vi] != 1 )
06868 return false;
06869 topvi = m_topv_map[vi];
06870 if ( topvi < 0 )
06871 return false;
06872 if ( topvi >= topv_count )
06873 return false;
06874 const ON_MeshTopologyVertex& topv = m_topv[topvi];
06875 for ( j = 0; j < topv.m_v_count; j++ ) {
06876 if ( topv.m_vi[j] == vi )
06877 break;
06878 }
06879 if ( j >= topv.m_v_count )
06880 return false;
06881 }
06882
06883
06884 for ( topei = 0; topei < tope_count; topei++ ) {
06885 const ON_MeshTopologyEdge& tope = m_tope[topei];
06886 if ( tope.m_topvi[0] < 0 || tope.m_topvi[0] >= topv_count )
06887 return false;
06888 if ( tope.m_topvi[1] < 0 || tope.m_topvi[1] >= topv_count )
06889 return false;
06890 if ( tope.m_topvi[0] == tope.m_topvi[1] )
06891 return false;
06892
06893 const ON_MeshTopologyVertex& topv0 = m_topv[tope.m_topvi[0]];
06894 for ( j = 0; j < topv0.m_tope_count; j++ ) {
06895 if ( topv0.m_topei[j] == topei )
06896 break;
06897 }
06898 if ( j >= topv0.m_tope_count )
06899 return false;
06900
06901 const ON_MeshTopologyVertex& topv1 = m_topv[tope.m_topvi[1]];
06902 for ( j = 0; j < topv1.m_tope_count; j++ ) {
06903 if ( topv1.m_topei[j] == topei )
06904 break;
06905 }
06906 if ( j >= topv1.m_tope_count )
06907 return false;
06908
06909 if ( tope.m_topf_count < 0 )
06910 return false;
06911 if ( tope.m_topf_count == 0 && tope.m_topfi )
06912 return false;
06913 if ( tope.m_topf_count > 0 && !tope.m_topfi )
06914 return false;
06915 for ( j = 0; j < tope.m_topf_count; j++ ) {
06916 fi = tope.m_topfi[j];
06917 if ( fi < 0 || fi >= f_count )
06918 return false;
06919 const ON_MeshTopologyFace& topf = m_topf[fi];
06920 for ( k = 0; k < 4; k++ ) {
06921 if ( topf.m_topei[k] == topei )
06922 break;
06923 }
06924 if ( k >= 4 )
06925 return false;
06926 }
06927 }
06928
06929
06930 for ( fi = 0; fi < f_count; fi++ ) {
06931 topfi = fi;
06932 const ON_MeshTopologyFace& topf = m_topf[topfi];
06933 const ON_MeshFace& f = m_mesh->m_F[fi];
06934 if ( topf.m_topei[0] < 0 || topf.m_topei[0] >= tope_count )
06935 return false;
06936 if ( topf.m_topei[1] < 0 || topf.m_topei[1] >= tope_count )
06937 return false;
06938 if ( topf.m_topei[2] < 0 || topf.m_topei[2] >= tope_count )
06939 return false;
06940 if ( topf.m_topei[3] < 0 || topf.m_topei[3] >= tope_count )
06941 return false;
06942 tfvi[0] = m_topv_map[f.vi[0]];
06943 tfvi[1] = m_topv_map[f.vi[1]];
06944 tfvi[2] = m_topv_map[f.vi[2]];
06945 tfvi[3] = m_topv_map[f.vi[3]];
06946 if ( topf.m_topei[0] != 0 || topf.m_topei[1] != 0
06947 || topf.m_topei[2] != 0 || topf.m_topei[3] != 0 ) {
06948 if ( !f.IsValid(v_count) )
06949 return false;
06950 if ( f.IsTriangle() ) {
06951 if (topf.m_topei[2] != topf.m_topei[3] )
06952 return false;
06953 jmax = 3;
06954 }
06955 else {
06956 if (topf.m_topei[2] == topf.m_topei[3] )
06957 return false;
06958 jmax = 4;
06959 }
06960 for ( j = 0; j < jmax; j++ ) {
06961 const ON_MeshTopologyEdge& tope = m_tope[topf.m_topei[j]];
06962 for ( k = 0; k < tope.m_topf_count; k++ ) {
06963 if ( tope.m_topfi[k] == topfi )
06964 break;
06965 }
06966 if ( k >= tope.m_topf_count )
06967 return false;
06968
06969
06970 if ( topf.m_reve[j] ) {
06971 if ( tope.m_topvi[1] != tfvi[(j+3)%4] )
06972 return false;
06973 if ( tope.m_topvi[0] != tfvi[j] )
06974 return false;
06975 }
06976 else {
06977 if ( tope.m_topvi[0] != tfvi[(j+3)%4] )
06978 return false;
06979 if ( tope.m_topvi[1] != tfvi[j] )
06980 return false;
06981 }
06982 }
06983 }
06984 else {
06985
06986 if ( topf.m_topei[0] != 0 || topf.m_topei[1] != 0
06987 || topf.m_topei[2] != 0 || topf.m_topei[3] != 0 )
06988 return false;
06989 }
06990 }
06991 return true;
06992 }
06993
06994 void ON_MeshTopology::Dump( ON_TextLog& dump ) const
06995 {
06996 ON_3fPoint p;
06997 int vi, ei, fi, j;
06998 const int topv_count = m_topv.Count();
06999 const int tope_count = m_tope.Count();
07000 const int topf_count = m_topf.Count();
07001
07002
07003 for ( vi = 0; vi < topv_count; vi++ ) {
07004 const ON_MeshTopologyVertex& v = m_topv[vi];
07005 dump.Print("topv %d: ",vi);
07006 if (m_mesh) {
07007
07008 p = m_mesh->m_V[v.m_vi[0]];
07009 dump.Print("{%g,%g,%g} ", p.x, p.y, p.z);
07010 }
07011
07012
07013
07014 dump.Print("(");
07015 for ( j = 0; j < v.m_v_count; j++ ) {
07016 if ( j )
07017 dump.Print(",");
07018 dump.Print("m_V[%d]",v.m_vi[j]);
07019 }
07020
07021
07022 dump.Print(") (");
07023 for ( j = 0; j < v.m_tope_count; j++ ) {
07024 if ( j )
07025 dump.Print(",");
07026 dump.Print("%d",v.m_topei[j]);
07027 }
07028 dump.Print(")\n");
07029 }
07030
07031
07032 for ( ei = 0; ei < tope_count; ei++ ) {
07033 const ON_MeshTopologyEdge& e = m_tope[ei];
07034 dump.Print("tope %d: topv%d to topvv%d (", ei, e.m_topvi[0], e.m_topvi[1] );
07035
07036 for ( j = 0; j < e.m_topf_count; j++ ) {
07037 if (j)
07038 dump.Print(",");
07039 dump.Print("f%d",e.m_topfi[j]);
07040 }
07041 dump.Print(")\n");
07042 }
07043
07044
07045
07046 for ( fi = 0; fi < topf_count; fi++ ) {
07047 const ON_MeshTopologyFace& f = m_topf[fi];
07048 dump.Print("topf %d: (",fi);
07049 for ( j = 0; j < 4; j++ ) {
07050 if ( j == 3 && f.m_topei[3] == f.m_topei[2] )
07051 break;
07052 if (j)
07053 dump.Print(",");
07054 dump.Print("%ce%d",f.m_reve[j]?'-':'+',f.m_topei[j]);
07055 }
07056 dump.Print(")\n");
07057 }
07058 }
07059
07060
07061 bool ON_MeshTopology::Create()
07062 {
07063
07064
07065
07066
07067
07068
07069
07070
07071
07072
07073
07074
07075 if ( 1 == m_b32IsValid )
07076 return true;
07077
07078 const int b32IsValid0 = m_b32IsValid;
07079
07080 if ( 0 == b32IsValid0 )
07081 {
07082
07083 m_b32IsValid = -1;
07084 }
07085 int b32IsValid = b32IsValid0;
07086
07087 while ( 0 == b32IsValid || -1 == b32IsValid )
07088 {
07089
07090 Destroy();
07091 b32IsValid = 0;
07092
07093
07094 const int fcount = m_mesh->FaceCount();
07095 const int vcount = m_mesh->VertexCount();
07096 if ( 0 == vcount )
07097 break;
07098
07099 int* vindex = GetIntArray(vcount);
07100 m_topv_map.SetCapacity( vcount );
07101 m_topv_map.SetCount( vcount );
07102 if ( 0 == m_mesh->GetVertexLocationIds( 0, m_topv_map.Array(), vindex ) )
07103 {
07104 Destroy();
07105 break;
07106 }
07107
07108 {
07109 int topv_count = m_topv_map[vindex[vcount-1]]+1;
07110 m_topv_map.SetCapacity( vcount );
07111 m_topv_map.SetCount( vcount );
07112 m_topv.SetCapacity( topv_count );
07113 int vt0, vt1, topvi;
07114 ON_3fPoint p0;
07115 for (vt0 = 0; vt0 < vcount; vt0 = vt1)
07116 {
07117 topvi = m_topv.Count();
07118 #if defined(ON_DEBUG)
07119 if ( topvi != m_topv_map[vindex[vt0]] )
07120 {
07121
07122
07123 ON_ERROR("ON_MeshTopology::Create() - topvi != vertex id from GetVertexLocationIds()");
07124 }
07125 #endif
07126 ON_MeshTopologyVertex& topv = m_topv.AppendNew();
07127 topv.m_vi = vindex+vt0;
07128 for ( vt1=vt0+1; vt1<vcount && topvi == m_topv_map[vindex[vt1]]; vt1++ ) {
07129
07130 }
07131 topv.m_v_count = vt1-vt0;
07132 }
07133 }
07134
07135
07136 const int topv_count = m_topv.Count();
07137 if ( topv_count >= 2 )
07138 {
07139 bool rc = false;
07140 int ei, ecnt, fi, vi0, vi1, efi, topfvi[4];
07141 ON_MeshFace f;
07142
07143 if ( fcount > 0 && vcount > 0 )
07144 {
07145
07146 ON_Workspace ws;
07147 struct ON_MeshFaceSide* e = (struct ON_MeshFaceSide*)ws.GetMemory( 4*fcount*sizeof(*e) );
07148 ecnt = m_mesh->GetMeshFaceSideList( m_topv_map.Array(), e );
07149
07150 if ( ecnt > 0 )
07151 {
07152 rc = true;
07153 ON_SortMeshFaceSidesByVertexIndex( ecnt, e );
07154
07155
07156 int etop_count = 0;
07157 ei = 0;
07158 while( ei < ecnt )
07159 {
07160 vi0 = e[ei].vi[0];
07161 vi1 = e[ei].vi[1];
07162 ei++;
07163 while (ei < ecnt && e[ei].vi[0] == vi0 && e[ei].vi[1] == vi1 )
07164 ei++;
07165 etop_count++;
07166 }
07167 m_tope.SetCapacity(etop_count);
07168
07169
07170 int* efindex = GetIntArray(ecnt);
07171 for ( ei = 0; ei < ecnt; )
07172 {
07173 ON_MeshTopologyEdge& tope = m_tope.AppendNew();
07174 tope.m_topvi[0] = vi0 = e[ei].vi[0];
07175 tope.m_topvi[1] = vi1 = e[ei].vi[1];
07176 tope.m_topfi = efindex;
07177 tope.m_topf_count = 0;
07178 *efindex++ = e[ei].fi;
07179 tope.m_topf_count++;
07180 ei++;
07181 while( ei < ecnt && e[ei].vi[0] == vi0 && e[ei].vi[1] == vi1 )
07182 {
07183 *efindex++ = e[ei].fi;
07184 tope.m_topf_count++;
07185 ei++;
07186 }
07187 }
07188 efindex = 0;
07189
07190
07191 ecnt = m_tope.Count();
07192 int* ve_count = (int*)onmalloc(topv_count*sizeof(*ve_count));
07193
07194 memset( ve_count, 0, topv_count*sizeof(*ve_count));
07195 for ( ei = 0; ei < ecnt; ei++ ) {
07196 const ON_MeshTopologyEdge& tope = m_tope[ei];
07197 ve_count[tope.m_topvi[0]]++;
07198 ve_count[tope.m_topvi[1]]++;
07199 }
07200
07201 int* vei = GetIntArray(2*ecnt);
07202 for ( vi0 = 0; vi0 < topv_count; vi0++ ) {
07203 ON_MeshTopologyVertex& topv = m_topv[vi0];
07204 if ( ve_count[vi0] > 0 ) {
07205 topv.m_topei = vei;
07206 vei += ve_count[vi0];
07207 }
07208 }
07209 onfree(ve_count); ve_count = 0;
07210 vei = 0;
07211
07212
07213 for ( ei = 0; ei < ecnt; ei++ ) {
07214 ON_MeshTopologyEdge& tope = m_tope[ei];
07215 ON_MeshTopologyVertex& topv0 = m_topv[tope.m_topvi[0]];
07216 ON_MeshTopologyVertex& topv1 = m_topv[tope.m_topvi[1]];
07217 vei = const_cast<int*>(topv0.m_topei);
07218 vei[topv0.m_tope_count++] = ei;
07219 vei = const_cast<int*>(topv1.m_topei);
07220 vei[topv1.m_tope_count++] = ei;
07221 }
07222
07223
07224 m_topf.SetCapacity(fcount);
07225 m_topf.SetCount(fcount);
07226 memset( m_topf.Array(), 0, fcount*sizeof(ON_MeshTopologyFace) );
07227 for ( fi = 0; fi < fcount; fi++ ) {
07228 ON_MeshTopologyFace& f = m_topf[fi];
07229 f.m_topei[0] = -1;
07230 f.m_topei[1] = -1;
07231 f.m_topei[2] = -1;
07232 f.m_topei[3] = -1;
07233 }
07234 for ( ei = 0; ei < ecnt; ei++ ) {
07235 ON_MeshTopologyEdge& tope = m_tope[ei];
07236 for (efi = 0; efi < tope.m_topf_count; efi++ ) {
07237
07238
07239 fi = tope.m_topfi[efi];
07240 f = m_mesh->m_F[fi];
07241 topfvi[0] = m_topv_map[f.vi[0]];
07242 topfvi[1] = m_topv_map[f.vi[1]];
07243 topfvi[2] = m_topv_map[f.vi[2]];
07244 topfvi[3] = m_topv_map[f.vi[3]];
07245 ON_MeshTopologyFace& topf = m_topf[fi];
07246 vi0 = tope.m_topvi[0];
07247 vi1 = tope.m_topvi[1];
07248
07249 if ( vi0 == topfvi[3] && vi1 == topfvi[0] ) {
07250 topf.m_topei[0] = ei;
07251 topf.m_reve[0] = 0;
07252 }
07253 else if ( vi0 == topfvi[0] && vi1 == topfvi[1] ) {
07254 topf.m_topei[1] = ei;
07255 topf.m_reve[1] = 0;
07256 }
07257 else if ( vi0 == topfvi[1] && vi1 == topfvi[2] ) {
07258 topf.m_topei[2] = ei;
07259 topf.m_reve[2] = 0;
07260 }
07261 else if ( vi0 == topfvi[2] && vi1 == topfvi[3] ) {
07262 topf.m_topei[3] = ei;
07263 topf.m_reve[3] = 0;
07264 }
07265 else if ( vi1 == topfvi[3] && vi0 == topfvi[0] ) {
07266 topf.m_topei[0] = ei;
07267 topf.m_reve[0] = 1;
07268 }
07269 else if ( vi1 == topfvi[0] && vi0 == topfvi[1] ) {
07270 topf.m_topei[1] = ei;
07271 topf.m_reve[1] = 1;
07272 }
07273 else if ( vi1 == topfvi[1] && vi0 == topfvi[2] ) {
07274 topf.m_topei[2] = ei;
07275 topf.m_reve[2] = 1;
07276 }
07277 else if ( vi1 == topfvi[2] && vi0 == topfvi[3] ) {
07278 topf.m_topei[3] = ei;
07279 topf.m_reve[3] = 1;
07280 }
07281 }
07282 }
07283 for ( fi = 0; fi < fcount; fi++ ) {
07284 ON_MeshTopologyFace& f = m_topf[fi];
07285 bool bIsGood = false;
07286 if ( f.m_topei[0] >= 0 && f.m_topei[1] >= 0 && f.m_topei[2] >=0
07287 && f.m_topei[0] != f.m_topei[1]
07288 && f.m_topei[1] != f.m_topei[2]
07289 && f.m_topei[2] != f.m_topei[0]
07290 ) {
07291 if ( m_mesh->m_F[fi].IsTriangle() ) {
07292 bIsGood = true;
07293 f.m_topei[3] = f.m_topei[2];
07294 }
07295 else if ( f.m_topei[3] >= 0
07296 && f.m_topei[0] != f.m_topei[3]
07297 && f.m_topei[1] != f.m_topei[3]
07298 && f.m_topei[2] != f.m_topei[3] ) {
07299 bIsGood = true;
07300 }
07301 }
07302 if ( !bIsGood ) {
07303 f.m_topei[0] = 0;
07304 f.m_topei[1] = 0;
07305 f.m_topei[2] = 0;
07306 f.m_topei[3] = 0;
07307 f.m_reve[0] = 0;
07308 f.m_reve[1] = 0;
07309 f.m_reve[2] = 0;
07310 f.m_reve[3] = 0;
07311 }
07312 }
07313
07314 }
07315 }
07316 }
07317
07318 b32IsValid = 1;
07319 break;
07320 }
07321
07322 if ( -1 != b32IsValid0 )
07323 {
07324
07325 m_b32IsValid = b32IsValid;
07326 }
07327
07328 if ( 1 != b32IsValid )
07329 {
07330 Destroy();
07331 }
07332
07333 return (1 == b32IsValid);
07334 }
07335
07336 struct tagFPT
07337 {
07338 int x, y, z;
07339 };
07340
07341
07342
07343
07344
07345
07346
07347
07348
07349
07350
07351
07352
07353
07354
07355
07356
07357
07358 static int compare_pmark( const int* a, const int* b )
07359 {
07360 if ( *a < *b )
07361 return -1;
07362 if ( *a > *b )
07363 return 1;
07364 if ( a < b )
07365 return -1;
07366 if ( a > b )
07367 return 1;
07368 return 0;
07369 }
07370
07371 static int compare_vmap( const void* a, const void* b )
07372 {
07373 int i = *((int*)a);
07374 int j = *((int*)b);
07375 if ( i < j )
07376 return -1;
07377 if ( i > j )
07378 return 1;
07379 return 0;
07380 }
07381
07382 static int DupVertex( ON_Mesh* mesh, int vi )
07383 {
07384 int vertex_count = mesh->m_V.Count();
07385 ON_3fVector n;
07386 ON_3fPoint v;
07387 ON_Color c;
07388 ON_2fPoint t;
07389 ON_SurfaceCurvature k;
07390 v = mesh->m_V[vi];
07391 mesh->m_V.Append(v);
07392 if (mesh->m_N.Count() == vertex_count) {
07393 n = mesh->m_N[vi];
07394 mesh->m_N.Append(n);
07395 }
07396 if (mesh->m_T.Count() == vertex_count) {
07397 t = mesh->m_T[vi];
07398 mesh->m_T.Append(t);
07399 }
07400 if (mesh->m_K.Count() == vertex_count) {
07401 k = mesh->m_K[vi];
07402 mesh->m_K.Append(k);
07403 }
07404 if (mesh->m_C.Count() == vertex_count) {
07405 c = mesh->m_C[vi];
07406 mesh->m_C.Append(c);
07407 }
07408 return vertex_count;
07409 }
07410
07411
07412 static int AddToPartition( ON_Mesh* mesh, ON_SimpleArray<int>& pmark, int vi, int partition_mark, int fi0 )
07413 {
07414 bool b = true;
07415 int i, fi, new_vi, face_count, *fvi;
07416 i = pmark[vi];
07417 if ( !i ) {
07418 pmark[vi] = partition_mark;
07419 }
07420 else if ( i != partition_mark && i != partition_mark-1 ) {
07421 if ( i == partition_mark-2 )
07422 pmark[vi] = partition_mark-1;
07423 else {
07424 new_vi = DupVertex(mesh,vi);
07425 face_count = mesh->m_F.Count();
07426 for ( fi = fi0; fi < face_count; fi++ ) {
07427 fvi = mesh->m_F[fi].vi;
07428 if ( fvi[0] == vi )
07429 fvi[0] = new_vi;
07430 if ( fvi[1] == vi )
07431 fvi[1] = new_vi;
07432 if ( fvi[2] == vi )
07433 fvi[2] = new_vi;
07434 if ( fvi[3] == vi )
07435 fvi[3] = new_vi;
07436 }
07437 pmark.Append(partition_mark);
07438 }
07439 }
07440 else
07441 b = false;
07442 return b;
07443 }
07444
07445 bool ON_MeshPartition_IsValid( const ON_MeshPartition& p, const ON_Mesh& mesh )
07446 {
07447 bool rc = false;
07448 const int* fvi;
07449 int j, tcnt, fi, parti, partcount;
07450 partcount = p.m_part.Count();
07451 rc = ( partcount > 0 );
07452 if ( p.m_partition_max_triangle_count < 1 )
07453 rc = false;
07454 if ( p.m_partition_max_vertex_count < 3 )
07455 rc = false;
07456 for ( parti = 0; parti < partcount && rc; parti++ ) {
07457 const ON_MeshPart& part = p.m_part[parti];
07458 if ( part.triangle_count < 1 )
07459 rc = false;
07460 if ( part.vertex_count < 1 )
07461 rc = false;
07462 if ( part.vertex_count != part.vi[1] - part.vi[0] )
07463 rc = false;
07464 tcnt = 0;
07465 for ( fi = part.fi[0]; fi < part.fi[1]; fi++ ) {
07466 fvi = mesh.m_F[fi].vi;
07467 tcnt++;
07468 if ( fvi[2] != fvi[3] )
07469 tcnt++;
07470 for ( j = 0; j < 4; j++ ) {
07471 if ( fvi[j] < part.vi[0] || fvi[j] >= part.vi[1] )
07472 rc = false;
07473 }
07474 }
07475 if ( tcnt != part.triangle_count )
07476 rc = false;
07477 if ( parti ) {
07478 if ( part.fi[0] != p.m_part[parti-1].fi[1] )
07479 rc = false;
07480 if ( part.vi[0] > p.m_part[parti-1].vi[1] )
07481 rc = false;
07482 }
07483 }
07484 if ( partcount ) {
07485 if ( p.m_part[0].fi[0] != 0 || p.m_part[partcount-1].fi[1] != mesh.m_F.Count() )
07486 rc = false;
07487 }
07488 return rc;
07489 }
07490
07491 static
07492 bool ON_Mesh_CreatePartition_SortFaces(const ON_Mesh& mesh, int* fmap )
07493 {
07494 ON_RTree rt;
07495 if ( !rt.CreateMeshFaceTree(&mesh) )
07496 return false;
07497
07498 const int mesh_F_count = mesh.m_F.Count();
07499 int fmap_count = 0;
07500
07501 const ON_RTreeBranch* branch;
07502 ON_RTreeIterator rit(rt);
07503 for ( rit.First(); 0 != (branch = rit.Value()); rit.Next() )
07504 {
07505 if ( fmap_count > mesh_F_count )
07506 break;
07507 fmap[fmap_count++] = (int)(branch->m_id);
07508 }
07509
07510 if ( fmap_count != mesh_F_count )
07511 {
07512 ON_ERROR("ON_Mesh::CreatePartition unable to get fmap[]");
07513 return false;
07514 }
07515
07516 return true;
07517 }
07518
07519 const ON_MeshPartition* ON_Mesh::CreatePartition(
07520 int partition_max_vertex_count,
07521 int partition_max_triangle_count
07522 )
07523 {
07524 ON_Workspace ws;
07525 bool bNeedFaceSort = true;
07526 if ( m_partition )
07527 {
07528 bNeedFaceSort = false;
07529 if ( m_partition->m_partition_max_triangle_count > partition_max_triangle_count
07530 || m_partition->m_partition_max_vertex_count > partition_max_vertex_count )
07531 DestroyPartition();
07532 }
07533 if ( !m_partition )
07534 {
07535
07536 struct ON_MeshPart p;
07537 int vertex_count = VertexCount();
07538 const int face_count = FaceCount();
07539 const int triangle_count = TriangleCount() + 2*QuadCount();
07540 m_partition = new ON_MeshPartition();
07541 int k = triangle_count/partition_max_triangle_count;
07542 if ( k < vertex_count/partition_max_vertex_count )
07543 k = vertex_count/partition_max_vertex_count;
07544 k++;
07545 m_partition->m_part.Reserve(k);
07546 if ( vertex_count <= partition_max_vertex_count &&
07547 triangle_count <= partition_max_triangle_count )
07548 {
07549 m_partition->m_partition_max_vertex_count = vertex_count;
07550 m_partition->m_partition_max_triangle_count = triangle_count;
07551 memset(&p,0,sizeof(p));
07552 p.vi[0] = 0;
07553 p.vi[1] = vertex_count;
07554 p.fi[0] = 0;
07555 p.fi[1] = face_count;
07556 p.vertex_count = vertex_count;
07557 p.triangle_count = triangle_count;
07558 m_partition->m_part.Append(p);
07559 }
07560 else
07561 {
07562 int fi;
07563 int* fvi;
07564 DestroyTopology();
07565
07566
07567 int* fmap = (int*)ws.GetMemory( face_count*sizeof(fmap[0]) );
07568 if ( !ON_Mesh_CreatePartition_SortFaces(*this,fmap) )
07569 {
07570 for ( fi = 0; fi < face_count; fi++ )
07571 fmap[fi] = fi;
07572 }
07573
07574
07575
07576
07577
07578
07579
07580
07581
07582
07583
07584
07585
07586
07587
07588
07589
07590
07591
07592
07593
07594
07595
07596
07597
07598
07599
07600
07601
07602
07603
07604
07605
07606
07607
07608
07609
07610
07611
07612
07613
07614
07615
07616 m_F.Permute( fmap );
07617 if ( m_FN.Count() == face_count )
07618 m_FN.Permute( fmap );
07619
07620
07621 ON_SimpleArray<int>pmark(2*vertex_count);
07622 pmark.SetCount(vertex_count);
07623 pmark.Zero();
07624 int fi0, fi1, partition_mark, partition_vertex_count, partition_triangle_count;
07625 fi1 = 0;
07626 fi0 = 0;
07627 for ( partition_mark = 3, fi0 = 0; fi0 < face_count; fi0 = fi1, partition_mark += 2 )
07628 {
07629 partition_vertex_count = 0;
07630 partition_triangle_count = 0;
07631 for ( fi1 = fi0;
07632 fi1 < face_count
07633 && partition_triangle_count+2 <= partition_max_triangle_count
07634 && partition_vertex_count+4 <= partition_max_vertex_count;
07635 fi1++ )
07636 {
07637 fvi = m_F[fi1].vi;
07638 partition_triangle_count++;
07639 if ( AddToPartition( this, pmark, fvi[0], partition_mark, fi0 ) )
07640 partition_vertex_count++;
07641 if ( AddToPartition( this, pmark, fvi[1], partition_mark, fi0 ) )
07642 partition_vertex_count++;
07643 if ( AddToPartition( this, pmark, fvi[2], partition_mark, fi0 ) )
07644 partition_vertex_count++;
07645 if ( fvi[2] != fvi[3] ) {
07646 partition_triangle_count++;
07647 if ( AddToPartition( this, pmark, fvi[3], partition_mark, fi0 ) )
07648 partition_vertex_count++;
07649 }
07650 }
07651 if ( fi0 < fi1 ) {
07652 struct ON_MeshPart p;
07653 memset(&p,0,sizeof(p));
07654 p.fi[0] = fi0;
07655 p.fi[1] = fi1;
07656 p.vertex_count = partition_vertex_count;
07657 p.triangle_count = partition_triangle_count;
07658 m_partition->m_part.Append(p);
07659 }
07660 if ( partition_triangle_count > m_partition->m_partition_max_triangle_count )
07661 m_partition->m_partition_max_triangle_count = partition_triangle_count;
07662 if ( partition_vertex_count > m_partition->m_partition_max_vertex_count )
07663 m_partition->m_partition_max_vertex_count = partition_vertex_count;
07664 }
07665
07666
07667 vertex_count = m_V.Count();
07668
07669
07670 int* vmap = (int*)ws.GetMemory( vertex_count*sizeof(vmap[0]) );
07671 pmark.Sort( ON::quick_sort, vmap, compare_pmark );
07672 m_V.Permute( vmap );
07673 if ( m_N.Count() == vertex_count )
07674 m_N.Permute( vmap );
07675 if ( m_T.Count() == vertex_count )
07676 m_T.Permute( vmap );
07677 if ( m_K.Count() == vertex_count )
07678 m_K.Permute( vmap );
07679 if ( m_C.Count() == vertex_count )
07680 m_C.Permute( vmap );
07681 pmark.Permute( vmap );
07682
07683 int* pamv = (int*)ws.GetMemory( vertex_count*sizeof(pamv[0]) );
07684 ON_Sort( ON::quick_sort, pamv, vmap, vertex_count, sizeof(vmap[0]), compare_vmap );
07685 for ( fi = 0; fi < face_count; fi++ ) {
07686 fvi = m_F[fi].vi;
07687 fvi[0] = pamv[fvi[0]];
07688 fvi[1] = pamv[fvi[1]];
07689 fvi[2] = pamv[fvi[2]];
07690 fvi[3] = pamv[fvi[3]];
07691 }
07692
07693
07694 int m, pi, partition_count = m_partition->m_part.Count();
07695 int vi0, vi1, vi2, vi3;
07696 for (vi2 = 0; vi2 < vertex_count && pmark[vi2]<2; vi2++)
07697 {}
07698 vi3=vi2;
07699 for ( pi = 0; pi < partition_count; pi++ ) {
07700 vi0 = vi2;
07701 vi1 = vi3;
07702 m = 2*pi + 4;
07703 for ( vi2 = vi3; vi2 < vertex_count && pmark[vi2] < m; vi2++)
07704 {}
07705 for ( vi3 = vi2; vi3 < vertex_count && pmark[vi3] <= m; vi3++)
07706 {}
07707 m_partition->m_part[pi].vi[0] = vi0;
07708 m_partition->m_part[pi].vi[1] = vi3;
07709 }
07710 }
07711
07712 if ( m_partition && !ON_MeshPartition_IsValid( *m_partition, *this ) ) {
07713 delete m_partition;
07714 m_partition = 0;
07715 }
07716 }
07717
07718 return m_partition;
07719 }
07720
07721 const ON_MeshPartition* ON_Mesh::Partition() const
07722 {
07723 return m_partition;
07724 }
07725
07726 void ON_Mesh::DestroyPartition()
07727 {
07728 if ( m_partition ) {
07729 delete m_partition;
07730 m_partition = 0;
07731 }
07732 }
07733
07734 ON_MeshPartition::ON_MeshPartition()
07735 {
07736 m_partition_max_vertex_count = 0;
07737 m_partition_max_triangle_count = 0;
07738 m_part = 0;
07739 }
07740
07741 ON_MeshPartition::~ON_MeshPartition()
07742 {
07743 m_part.Destroy();
07744 }
07745
07746
07747 ON_Mesh* ON_Mesh::MeshPart(
07748 const ON_MeshPart& mesh_part,
07749 ON_Mesh* mesh
07750 ) const
07751 {
07752 if ( this == mesh )
07753 {
07754 ON_ERROR("ON_Mesh::MeshPart this == mesh");
07755 return 0;
07756 }
07757
07758 if ( mesh )
07759 mesh->Destroy();
07760
07761 if ( mesh_part.fi[0] < 0
07762 || mesh_part.fi[1] > m_F.Count()
07763 || mesh_part.fi[0] > mesh_part.fi[1]
07764 )
07765 {
07766 ON_ERROR("ON_Mesh::MeshPart mesh_part.fi[] is not valid");
07767 return 0;
07768 }
07769
07770 if ( mesh_part.vi[0] < 0
07771 || mesh_part.vi[1] > m_V.Count()
07772 || mesh_part.vi[0] >= mesh_part.vi[1]
07773 )
07774 {
07775 ON_ERROR("ON_Mesh::MeshPart mesh_part.vi[] is not valid");
07776 return 0;
07777 }
07778
07779 const int submesh_V_count = mesh_part.vi[1] - mesh_part.vi[0];
07780 const int submesh_F_count = mesh_part.fi[1] - mesh_part.fi[0];
07781
07782 const bool bHasVertexNormals = HasVertexNormals();
07783 const bool bHasTextureCoordinates = HasTextureCoordinates();
07784 const bool bHasVertexColors = HasVertexColors();
07785 const bool bHasFaceNormals = HasFaceNormals();
07786 const bool bHasSurfaceParameters = HasSurfaceParameters();
07787 const bool bHasPrincipalCurvatures = HasPrincipalCurvatures();
07788 const bool bHasHiddenVertices = HiddenVertexCount() > 0;
07789
07790 ON_Mesh* submesh = (0 != mesh)
07791 ? mesh
07792 : new ON_Mesh(mesh_part.triangle_count,
07793 mesh_part.vertex_count,
07794 bHasVertexNormals,
07795 bHasTextureCoordinates
07796 );
07797
07798 if ( bHasVertexColors )
07799 submesh->m_C.Reserve(submesh_V_count);
07800 if ( bHasSurfaceParameters )
07801 submesh->m_S.Reserve(submesh_V_count);
07802 if ( bHasPrincipalCurvatures )
07803 submesh->m_K.Reserve(submesh_V_count);
07804 if ( bHasHiddenVertices )
07805 submesh->m_H.Reserve(submesh_V_count);
07806 if ( bHasFaceNormals )
07807 submesh->m_FN.Reserve(submesh_F_count);
07808
07809
07810 const int vi0 = mesh_part.vi[0];
07811 const int vi1 = mesh_part.vi[1];
07812 for ( int vi = vi0; vi < vi1; vi++ )
07813 {
07814 submesh->m_V.Append(m_V[vi]);
07815 if ( bHasVertexNormals )
07816 submesh->m_N.Append(m_N[vi]);
07817 if ( bHasTextureCoordinates )
07818 submesh->m_T.Append(m_T[vi]);
07819 if ( bHasVertexColors )
07820 submesh->m_C.Append(m_C[vi]);
07821 if ( bHasSurfaceParameters )
07822 submesh->m_S.Append(m_S[vi]);
07823 if ( bHasPrincipalCurvatures )
07824 submesh->m_K.Append(m_K[vi]);
07825 if ( bHasHiddenVertices )
07826 {
07827 bool bHidden = m_H[vi];
07828 submesh->m_H.Append(bHidden);
07829 if ( bHidden )
07830 submesh->m_hidden_count++;
07831 }
07832 }
07833 if ( submesh->m_hidden_count <= 0 )
07834 {
07835 submesh->m_H.Destroy();
07836 submesh->m_hidden_count = 0;
07837 }
07838
07839
07840 int bad_face_count = 0;
07841 const int fi0 = mesh_part.fi[0];
07842 const int fi1 = mesh_part.fi[1];
07843 for ( int fi = fi0; fi < fi1; fi++ )
07844 {
07845 ON_MeshFace f = m_F[fi];
07846 f.vi[0] -= vi0;
07847 f.vi[1] -= vi0;
07848 f.vi[2] -= vi0;
07849 f.vi[3] -= vi0;
07850 if ( f.vi[0] >= submesh_V_count || f.vi[0] < 0
07851 || f.vi[1] >= submesh_V_count || f.vi[1] < 0
07852 || f.vi[2] >= submesh_V_count || f.vi[2] < 0
07853 || f.vi[3] >= submesh_V_count || f.vi[3] < 0
07854 )
07855 {
07856 bad_face_count++;
07857 ON_ERROR("ON_Mesh::MeshPart Invalid face in partition");
07858 continue;
07859 }
07860 submesh->m_F.Append(f);
07861 if ( bHasFaceNormals )
07862 submesh->m_FN.Append(m_FN[fi]);
07863 }
07864
07865 if ( submesh->m_F.Count() < 1 && bad_face_count > 0 )
07866 {
07867 if ( submesh != mesh )
07868 delete submesh;
07869 else
07870 mesh->Destroy();
07871
07872 submesh = 0;
07873 }
07874
07875 return submesh;
07876 }
07877
07878 ON_Mesh* ON_Mesh::DuplicateFace( int face_index, ON_Mesh* mesh ) const
07879 {
07880 if ( mesh == this )
07881 return 0;
07882 if ( 0 != mesh )
07883 mesh->Destroy();
07884 if ( face_index < 0 || face_index >= m_F.Count() )
07885 return 0;
07886 const int vcnt = m_V.Count();
07887 if ( vcnt < 3 )
07888 return 0;
07889
07890 const ON_3dPoint* dV = ( HasDoublePrecisionVertices() && DoublePrecisionVerticesAreValid() )
07891 ? DoublePrecisionVertices().Array()
07892 : 0;
07893 const ON_3fPoint* fV = (0 == dV) ? m_V.Array() : 0;
07894 bool bHasFaceNormals = HasFaceNormals();
07895 bool bHasVertexNormals = HasVertexNormals();
07896 bool bHasVertexColors = HasVertexColors();
07897 bool bHasTextureCoordinates = HasTextureCoordinates();
07898 bool bHasSurfaceParameters = HasSurfaceParameters();
07899 bool bHasPrincipalCurvatures = HasPrincipalCurvatures();
07900
07901 ON_MeshFace f = m_F[face_index];
07902 if ( dV )
07903 {
07904 if ( !f.IsValid(vcnt,dV) )
07905 {
07906
07907 if ( !f.Repair(vcnt,dV) )
07908 return 0;
07909 }
07910 }
07911 else
07912 {
07913 if ( !f.IsValid(vcnt,fV) )
07914 {
07915
07916 if ( !f.Repair(vcnt,fV) )
07917 return 0;
07918 }
07919 }
07920 const int newvcnt = f.IsTriangle() ? 3 : 4;
07921 if ( 0 == mesh )
07922 mesh = new ON_Mesh();
07923 ON_3dPointArray* newdV = 0;
07924 if ( dV )
07925 {
07926 newdV = &mesh->DoublePrecisionVertices();
07927 newdV->Reserve(newvcnt);
07928 }
07929 mesh->m_V.Reserve(newvcnt);
07930 mesh->m_F.Reserve(1);
07931 ON_MeshFace& newface = mesh->m_F.AppendNew();
07932 newface.vi[0] = 0;
07933 newface.vi[1] = 1;
07934 newface.vi[2] = 2;
07935 newface.vi[3] = (4 == newvcnt) ? 3 : newface.vi[2];
07936
07937 if ( bHasFaceNormals )
07938 {
07939 mesh->m_FN.Reserve(1);
07940 mesh->m_FN.Append(m_FN[face_index]);
07941 }
07942
07943 if ( bHasVertexNormals )
07944 mesh->m_N.Reserve(newvcnt);
07945 if ( bHasTextureCoordinates )
07946 mesh->m_T.Reserve(newvcnt);
07947 if ( bHasVertexColors )
07948 mesh->m_C.Reserve(newvcnt);
07949 if ( bHasSurfaceParameters )
07950 mesh->m_S.Reserve(newvcnt);
07951 if ( bHasPrincipalCurvatures )
07952 mesh->m_K.Reserve(newvcnt);
07953 for ( int vi = 0; vi < newvcnt; vi++ )
07954 {
07955 if ( dV )
07956 newdV->Append(dV[f.vi[vi]]);
07957 else
07958 mesh->m_V.Append(fV[f.vi[vi]]);
07959 if ( bHasVertexNormals )
07960 mesh->m_N.Append(m_N[f.vi[vi]]);
07961 if ( bHasTextureCoordinates )
07962 mesh->m_T.Append(m_T[f.vi[vi]]);
07963 if ( bHasVertexColors )
07964 mesh->m_C.Append(m_C[f.vi[vi]]);
07965 if ( bHasSurfaceParameters )
07966 mesh->m_S.Append(m_S[f.vi[vi]]);
07967 if ( bHasPrincipalCurvatures )
07968 mesh->m_K.Append(m_K[f.vi[vi]]);
07969 }
07970 if ( dV )
07971 {
07972 mesh->SetDoublePrecisionVerticesAsValid();
07973 mesh->UpdateSinglePrecisionVertices();
07974 }
07975
07976 return mesh;
07977 }
07978
07979
07980 ON_OBJECT_IMPLEMENT(ON_MeshVertexRef,ON_Geometry,"C547B4BD-BDCD-49b6-A983-0C4A7F02E31A");
07981
07982 ON_OBJECT_IMPLEMENT(ON_MeshEdgeRef,ON_Geometry,"ED727872-463A-4424-851F-9EC02CB0F155");
07983
07984 ON_OBJECT_IMPLEMENT(ON_MeshFaceRef,ON_Geometry,"4F529AA5-EF8D-4c25-BCBB-162D510AA280");
07985
07986 ON_MeshVertexRef::ON_MeshVertexRef()
07987 {
07988 m_mesh = 0;
07989 m_mesh_vi = -1;
07990 m_top_vi = -1;
07991 }
07992
07993 ON_MeshVertexRef::~ON_MeshVertexRef()
07994 {
07995 m_mesh = 0;
07996 m_mesh_vi = -1;
07997 m_top_vi = -1;
07998 }
07999
08000 ON_MeshVertexRef& ON_MeshVertexRef::operator=(const ON_MeshVertexRef& src)
08001 {
08002 if ( this != &src )
08003 {
08004 ON_Geometry::operator=(src);
08005 m_mesh = src.m_mesh;
08006 m_mesh_vi = src.m_mesh_vi;
08007 m_top_vi = src.m_top_vi;
08008 }
08009 return *this;
08010 }
08011
08012
08013 ON_BOOL32 ON_MeshVertexRef::IsValid( ON_TextLog* text_log ) const
08014 {
08015 if ( 0 == m_mesh )
08016 {
08017 if ( 0 != text_log )
08018 {
08019 text_log->Print("m_mesh = NULL\n");
08020 }
08021 return false;
08022 }
08023
08024 if ( -1 != m_mesh_vi )
08025 {
08026 if ( m_mesh_vi < 0 || m_mesh_vi >= m_mesh->m_V.Count() )
08027 {
08028 if ( 0 != text_log )
08029 {
08030 text_log->Print("m_mesh_vi = %d (should have 0 <= m_mesh_vi < %d)\n",m_mesh_vi,m_mesh->m_V.Count());
08031 }
08032 return false;
08033 }
08034 }
08035 else if ( -1 == m_top_vi )
08036 {
08037 if ( 0 != text_log )
08038 {
08039 text_log->Print("m_mesh_vi = -1 and m_top_vi = -1\n");
08040 }
08041 return false;
08042 }
08043
08044 if ( -1 != m_top_vi )
08045 {
08046 const ON_MeshTopology* top = MeshTopology();
08047 if ( 0 == top )
08048 {
08049 if ( 0 != text_log )
08050 {
08051 text_log->Print("m_top_vi = %d and MeshTopology()=NULL\n",m_top_vi);
08052 }
08053 return false;
08054 }
08055 if ( m_top_vi < 0 || m_top_vi >= top->m_tope.Count() )
08056 {
08057 if ( 0 != text_log )
08058 {
08059 text_log->Print("m_top_vi = %d (should have 0 <= m_top_vi < %d)\n",m_top_vi,top->m_topv.Count());
08060 }
08061 return false;
08062 }
08063
08064 if ( -1 != m_mesh_vi )
08065 {
08066 const ON_MeshTopologyVertex& topv = top->m_topv[m_top_vi];
08067 int i;
08068 for ( i = 0; i < topv.m_v_count; i++ )
08069 {
08070 if ( topv.m_vi[i] == m_mesh_vi )
08071 break;
08072 }
08073 if ( i >= topv.m_v_count )
08074 {
08075 if ( 0 != text_log )
08076 {
08077 text_log->Print("m_mesh_vi=%d is not in m_top->m_topv[m_top_vi=%d].m_vi[] array.\n",
08078 m_mesh_vi,m_top_vi);
08079
08080 }
08081 return false;
08082 }
08083 }
08084 }
08085
08086 return true;
08087 }
08088
08089 void ON_MeshVertexRef::Dump( ON_TextLog& text_log ) const
08090 {
08091 text_log.Print("m_mesh=%08x m_mesh_vi=%d m_top_vi=%d\n",
08092 m_mesh,m_mesh_vi,m_top_vi);
08093 ON_3dPoint v = Point();
08094 if ( v.IsValid() )
08095 {
08096 text_log.PushIndent();
08097 text_log.Print("Location: ");
08098 text_log.Print(v);
08099 text_log.Print("\n");
08100 text_log.PopIndent();
08101 }
08102
08103 }
08104 unsigned int ON_MeshVertexRef::SizeOf() const
08105 {
08106 unsigned int sz = sizeof(*this) - sizeof(ON_Geometry);
08107 sz += ON_Geometry::SizeOf();
08108 return sz;
08109 }
08110
08111 ON::object_type ON_MeshVertexRef::ObjectType() const
08112 {
08113 return ON::meshvertex_object;
08114 }
08115
08116
08117 int ON_MeshVertexRef::Dimension() const
08118 {
08119 return 3;
08120 }
08121
08122 ON_BOOL32 ON_MeshVertexRef::GetBBox(
08123 double* boxmin,
08124 double* boxmax,
08125 ON_BOOL32 bGrowBox
08126 ) const
08127 {
08128 bool rc = false;
08129 ON_3dPoint v = Point();
08130 if ( v.IsValid() )
08131 {
08132 rc = ON_GetPointListBoundingBox( 3, 0, 1, 3, &v.x, boxmin, boxmax, bGrowBox?true:false );
08133 }
08134 return rc;
08135 }
08136
08137 ON_BOOL32 ON_MeshVertexRef::Transform(
08138 const ON_Xform& xform
08139 )
08140 {
08141 return false;
08142 }
08143
08144 const ON_MeshTopology* ON_MeshVertexRef::MeshTopology() const
08145 {
08146 return (0 != m_mesh) ? &m_mesh->m_top : 0;
08147 }
08148
08149 ON_3dPoint ON_MeshVertexRef::Point() const
08150 {
08151 ON_3dPoint v = ON_UNSET_POINT;
08152 if ( 0 != m_mesh )
08153 {
08154 int vi = m_mesh_vi;
08155 if ( -1 == vi && m_top_vi >= 0 && m_top_vi < m_mesh->m_top.m_topv.Count() )
08156 {
08157 const ON_MeshTopologyVertex& topv = m_mesh->m_top.m_topv[m_top_vi];
08158 if ( topv.m_v_count > 0 )
08159 vi = topv.m_vi[0];
08160 }
08161 if ( vi >= 0 && vi < m_mesh->m_V.Count() )
08162 v = m_mesh->m_V[vi];
08163 }
08164 return v;
08165 }
08166
08167 const ON_MeshTopologyVertex* ON_MeshVertexRef::MeshTopologyVertex() const
08168 {
08169 const ON_MeshTopologyVertex* topv = 0;
08170 if ( 0 != m_mesh && m_top_vi >= 0 && m_top_vi < m_mesh->m_top.m_topv.Count() )
08171 {
08172 topv = &m_mesh->m_top.m_topv[m_top_vi];
08173 }
08174 return topv;
08175 }
08176
08177 ON_MeshEdgeRef::ON_MeshEdgeRef()
08178 {
08179 m_mesh = 0;
08180 m_top_ei = -1;
08181 }
08182
08183 ON_MeshEdgeRef::~ON_MeshEdgeRef()
08184 {
08185 m_mesh = 0;
08186 m_top_ei = -1;
08187 }
08188
08189 ON_MeshEdgeRef& ON_MeshEdgeRef::operator=(const ON_MeshEdgeRef& src)
08190 {
08191 if ( this != &src )
08192 {
08193 ON_Geometry::operator=(src);
08194 m_mesh = src.m_mesh;
08195 m_top_ei = src.m_top_ei;
08196 }
08197 return *this;
08198 }
08199
08200
08201 ON_BOOL32 ON_MeshEdgeRef::IsValid( ON_TextLog* text_log ) const
08202 {
08203 if ( 0 == m_mesh)
08204 {
08205 if ( 0 != text_log )
08206 {
08207 text_log->Print("m_mesh = NULL\n");
08208 }
08209 return false;
08210 }
08211
08212 if ( m_top_ei < 0 || m_top_ei >= m_mesh->m_top.m_tope.Count() )
08213 {
08214 if ( 0 != text_log )
08215 {
08216 text_log->Print("m_top_ei = %d (should have 0 <= m_top_ei < %d)\n",m_top_ei,m_mesh->m_top.m_tope.Count());
08217 }
08218 return false;
08219 }
08220
08221 return true;
08222 }
08223
08224 void ON_MeshEdgeRef::Dump( ON_TextLog& text_log ) const
08225 {
08226 text_log.Print("m_mesh=%08x, m_top_ei=%d\n",m_mesh,m_top_ei);
08227 ON_Line line = Line();
08228 if ( line.from.IsValid() )
08229 {
08230 text_log.PushIndent();
08231 text_log.Print("Location: ");
08232 text_log.Print(line.from);
08233 text_log.Print(" to ");
08234 text_log.Print(line.to);
08235 text_log.Print("\n");
08236 text_log.PopIndent();
08237 }
08238
08239 }
08240 unsigned int ON_MeshEdgeRef::SizeOf() const
08241 {
08242 unsigned int sz = sizeof(*this) - sizeof(ON_Geometry);
08243 sz += ON_Geometry::SizeOf();
08244 return sz;
08245 }
08246
08247 ON::object_type ON_MeshEdgeRef::ObjectType() const
08248 {
08249 return ON::meshedge_object;
08250 }
08251
08252
08253 int ON_MeshEdgeRef::Dimension() const
08254 {
08255 return 3;
08256 }
08257
08258 ON_BOOL32 ON_MeshEdgeRef::GetBBox(
08259 double* boxmin,
08260 double* boxmax,
08261 ON_BOOL32 bGrowBox
08262 ) const
08263 {
08264 bool rc = false;
08265 ON_Line line = Line();
08266 if ( line.from.IsValid() && line.to.IsValid() )
08267 {
08268 rc = ON_GetPointListBoundingBox( 3, 0, 2, 3, &line.from.x, boxmin, boxmax, bGrowBox?true:false );
08269 }
08270 return rc;
08271 }
08272
08273 ON_BOOL32 ON_MeshEdgeRef::Transform(
08274 const ON_Xform& xform
08275 )
08276 {
08277 return false;
08278 }
08279
08280 const ON_MeshTopology* ON_MeshEdgeRef::MeshTopology() const
08281 {
08282 return (0 != m_mesh) ? &m_mesh->m_top : 0;
08283 }
08284
08285 ON_Line ON_MeshEdgeRef::Line() const
08286 {
08287 ON_Line line(ON_UNSET_POINT,ON_UNSET_POINT);
08288 const ON_MeshTopologyEdge* tope = MeshTopologyEdge();
08289 if ( 0 != tope )
08290 {
08291 ON_MeshVertexRef vr;
08292 vr.m_mesh = m_mesh;
08293 vr.m_top_vi = tope->m_topvi[0];
08294 line.from = vr.Point();
08295 if ( line.from.IsValid() )
08296 {
08297 vr.m_top_vi = tope->m_topvi[1];
08298 line.to = vr.Point();
08299 if ( !line.to.IsValid() )
08300 line.from = ON_UNSET_POINT;
08301 }
08302 }
08303 return line;
08304 }
08305
08306 const ON_MeshTopologyEdge* ON_MeshEdgeRef::MeshTopologyEdge() const
08307 {
08308 const ON_MeshTopologyEdge* tope = 0;
08309 if ( m_top_ei >= 0 )
08310 {
08311 const ON_MeshTopology* top = MeshTopology();
08312 if ( 0 != top && m_top_ei < top->m_tope.Count() )
08313 tope = &top->m_tope[m_top_ei];
08314 }
08315 return tope;
08316 }
08317
08319
08320
08321 ON_MeshFaceRef::ON_MeshFaceRef()
08322 {
08323 m_mesh = 0;
08324 m_mesh_fi = -1;
08325 }
08326
08327 ON_MeshFaceRef::~ON_MeshFaceRef()
08328 {
08329 m_mesh = 0;
08330 m_mesh_fi = -1;
08331 }
08332
08333 ON_MeshFaceRef& ON_MeshFaceRef::operator=(const ON_MeshFaceRef& src)
08334 {
08335 if ( this != &src )
08336 {
08337 ON_Geometry::operator=(src);
08338 m_mesh = src.m_mesh;
08339 m_mesh_fi = src.m_mesh_fi;
08340 }
08341 return *this;
08342 }
08343
08344
08345 ON_BOOL32 ON_MeshFaceRef::IsValid( ON_TextLog* text_log ) const
08346 {
08347 if ( 0 == m_mesh)
08348 {
08349 if ( 0 != text_log )
08350 {
08351 text_log->Print("m_mesh = NULL\n");
08352 }
08353 return false;
08354 }
08355
08356 if ( m_mesh_fi < 0 || m_mesh_fi >= m_mesh->m_F.Count() )
08357 {
08358 if ( 0 != text_log )
08359 {
08360 text_log->Print("m_mesh_fi = %d (should have 0 <= m_mesh_fi < %d)\n",m_mesh_fi,m_mesh->m_F.Count());
08361 }
08362 return false;
08363 }
08364
08365 return true;
08366 }
08367
08368 void ON_MeshFaceRef::Dump( ON_TextLog& text_log ) const
08369 {
08370 text_log.Print("m_mesh=%08x, m_mesh_fi=%d\n",m_mesh,m_mesh_fi);
08371 }
08372
08373 unsigned int ON_MeshFaceRef::SizeOf() const
08374 {
08375 unsigned int sz = sizeof(*this) - sizeof(ON_Geometry);
08376 sz += ON_Geometry::SizeOf();
08377 return sz;
08378 }
08379
08380 ON::object_type ON_MeshFaceRef::ObjectType() const
08381 {
08382 return ON::meshface_object;
08383 }
08384
08385
08386 int ON_MeshFaceRef::Dimension() const
08387 {
08388 return 3;
08389 }
08390
08391 ON_BOOL32 ON_MeshFaceRef::GetBBox(
08392 double* boxmin,
08393 double* boxmax,
08394 ON_BOOL32 bGrowBox
08395 ) const
08396 {
08397 bool rc = false;
08398 if ( 0 != m_mesh && m_mesh_fi >= 0 && m_mesh_fi < m_mesh->m_F.Count() )
08399 {
08400 const int vcnt = m_mesh->m_V.Count();
08401 const int* Fvi = m_mesh->m_F[m_mesh_fi].vi;
08402 ON_3dPoint v[4];
08403
08404 int i;
08405 for ( i = 0; i < 4; i++ )
08406 {
08407 if ( Fvi[i] >= 0 && Fvi[i] < vcnt )
08408 {
08409 v[i] = m_mesh->m_V[Fvi[i]];
08410 }
08411 else
08412 return false;
08413 }
08414 rc = ON_GetPointListBoundingBox( 3, 0, 4, 3, &v[0].x, boxmin, boxmax, bGrowBox?true:false );
08415 }
08416 return rc;
08417 }
08418
08419 ON_BOOL32 ON_MeshFaceRef::Transform(
08420 const ON_Xform& xform
08421 )
08422 {
08423 return false;
08424 }
08425
08426 const ON_MeshTopology* ON_MeshFaceRef::MeshTopology() const
08427 {
08428 return (0 != m_mesh) ? &m_mesh->m_top : 0;
08429 }
08430
08431
08432
08433 const ON_MeshFace* ON_MeshFaceRef::MeshFace() const
08434 {
08435 const ON_MeshFace* f = 0;
08436 if ( 0 != m_mesh && m_mesh_fi >= 0 && m_mesh_fi < m_mesh->m_F.Count() )
08437 {
08438 f = &m_mesh->m_F[m_mesh_fi];
08439 }
08440 return f;
08441 }
08442
08443
08444 const ON_MeshTopologyFace* ON_MeshFaceRef::MeshTopologyFace() const
08445 {
08446 const ON_MeshTopologyFace* topf = 0;
08447 if ( m_mesh_fi >= 0 )
08448 {
08449 const ON_MeshTopology* top = MeshTopology();
08450 if ( 0 != top && m_mesh_fi < top->m_topf.Count() )
08451 topf = &top->m_topf[m_mesh_fi];
08452 }
08453 return topf;
08454 }
08455
08456 ON_MeshVertexRef ON_Mesh::VertexRef(int mesh_V_index) const
08457 {
08458 ON_MeshVertexRef vr;
08459 if ( mesh_V_index >= 0 && mesh_V_index < m_V.Count() )
08460 {
08461 vr.m_mesh = this;
08462 vr.m_mesh_vi = mesh_V_index;
08463 if ( m_top.m_topv_map.Count() == m_V.Count() )
08464 {
08465 vr.m_top_vi = m_top.m_topv_map[mesh_V_index];
08466 }
08467 }
08468
08469 return vr;
08470 }
08471
08472 ON_MeshVertexRef ON_Mesh::VertexRef(ON_COMPONENT_INDEX ci) const
08473 {
08474 ON_MeshVertexRef vr;
08475
08476
08477 switch (ci.m_type)
08478 {
08479 case ON_COMPONENT_INDEX::meshtop_vertex:
08480 vr = m_top.VertexRef(ci);
08481 break;
08482 case ON_COMPONENT_INDEX::mesh_vertex:
08483 if ( ci.m_index >= 0 && ci.m_index < m_V.Count() )
08484 {
08485 vr.m_mesh = this;
08486 vr.m_mesh_vi = ci.m_index;
08487 if ( m_top.m_topv_map.Count() == m_V.Count() )
08488 {
08489 vr.m_top_vi = m_top.m_topv_map[vr.m_mesh_vi];
08490 }
08491 }
08492 break;
08493 default:
08494
08495 break;
08496 }
08497
08498 return vr;
08499 }
08500
08501
08502 ON_MeshEdgeRef ON_Mesh::EdgeRef(int tope_index) const
08503 {
08504 return m_top.EdgeRef(tope_index);
08505 }
08506
08507 ON_MeshEdgeRef ON_Mesh::EdgeRef(ON_COMPONENT_INDEX ci) const
08508 {
08509 return m_top.EdgeRef(ci);
08510 }
08511
08512 ON_MeshFaceRef ON_Mesh::FaceRef(int mesh_F_index) const
08513 {
08514 ON_MeshFaceRef fr;
08515
08516 if ( mesh_F_index >= 0 && mesh_F_index < m_F.Count() )
08517 {
08518 fr.m_mesh = this;
08519 fr.m_mesh_fi = mesh_F_index;
08520 }
08521
08522 return fr;
08523 }
08524
08525 ON_MeshFaceRef ON_Mesh::FaceRef(ON_COMPONENT_INDEX ci) const
08526 {
08527 ON_MeshFaceRef fr;
08528
08529 if ( ci.m_type == ON_COMPONENT_INDEX::mesh_face )
08530 {
08531 if ( ci.m_index >= 0 && ci.m_index < m_F.Count() )
08532 {
08533 fr.m_mesh = this;
08534 fr.m_mesh_fi = ci.m_index;
08535 }
08536 }
08537
08538 return fr;
08539 }
08540
08541 ON_MeshVertexRef ON_MeshTopology::VertexRef(ON_COMPONENT_INDEX ci) const
08542 {
08543 ON_MeshVertexRef vr;
08544 if ( ci.m_index >= 0 )
08545 {
08546 switch(ci.m_type)
08547 {
08548 case ON_COMPONENT_INDEX::mesh_vertex:
08549 if (m_mesh)
08550 {
08551 vr = m_mesh->VertexRef(ci);
08552 }
08553 break;
08554 case ON_COMPONENT_INDEX::meshtop_vertex:
08555 if ( ci.m_index < m_topv.Count() )
08556 {
08557 vr.m_mesh = m_mesh;
08558 vr.m_top_vi = ci.m_index;
08559 if ( m_topv[ci.m_index].m_vi && 1 == m_topv[ci.m_index].m_v_count )
08560 {
08561 vr.m_mesh_vi = m_topv[ci.m_index].m_vi[0];
08562 }
08563 }
08564 break;
08565 default:
08566
08567
08568 break;
08569 }
08570 }
08571 return vr;
08572 }
08573
08574 ON_MeshVertexRef ON_MeshTopology::VertexRef(int topv_index) const
08575 {
08576 ON_MeshVertexRef vr;
08577
08578 if ( topv_index >= 0 && topv_index < m_topv.Count() )
08579 {
08580 vr.m_mesh = m_mesh;
08581 vr.m_top_vi = topv_index;
08582 if ( 1 == m_topv[topv_index].m_v_count )
08583 {
08584 vr.m_mesh_vi = m_topv[topv_index].m_vi[0];
08585 }
08586 }
08587
08588 return vr;
08589 }
08590
08591 ON_MeshEdgeRef ON_MeshTopology::EdgeRef(ON_COMPONENT_INDEX ci) const
08592 {
08593 ON_MeshEdgeRef er;
08594 if ( ON_COMPONENT_INDEX::meshtop_edge == ci.m_type && ci.m_index >= 0 && ci.m_index < m_tope.Count() )
08595 {
08596 er.m_mesh = m_mesh;
08597 er.m_top_ei = ci.m_index;
08598 }
08599 return er;
08600 }
08601
08602 ON_MeshEdgeRef ON_MeshTopology::EdgeRef(int tope_index) const
08603 {
08604 ON_MeshEdgeRef er;
08605
08606 if ( tope_index >= 0 && tope_index < m_tope.Count() )
08607 {
08608 er.m_mesh = m_mesh;
08609 er.m_top_ei = tope_index;
08610 }
08611
08612 return er;
08613 }
08614
08615 ON_MeshFaceRef ON_MeshTopology::FaceRef(ON_COMPONENT_INDEX ci) const
08616 {
08617 ON_MeshFaceRef fr;
08618 if ( m_mesh )
08619 {
08620 fr = m_mesh->FaceRef(ci.m_index);
08621 }
08622 return fr;
08623 }
08624
08625 ON_MeshFaceRef ON_MeshTopology::FaceRef(int topf_index) const
08626 {
08627 return ( 0 != m_mesh ) ? m_mesh->FaceRef(topf_index) : ON_MeshFaceRef();
08628 }
08629
08630
08631
08632
08633
08634
08635
08636
08637
08638
08639
08640
08641
08642
08643
08644
08645 ON_COMPONENT_INDEX ON_MeshVertexRef::ComponentIndex() const
08646 {
08647 ON_COMPONENT_INDEX ci(ON_COMPONENT_INDEX::invalid_type,-1);
08648 if ( m_mesh_vi >= 0 )
08649 {
08650 if ( 0 == m_mesh || m_mesh_vi < m_mesh->m_V.Count() )
08651 {
08652 ci.Set(ON_COMPONENT_INDEX::mesh_vertex,m_mesh_vi);
08653 }
08654 }
08655 else if ( m_top_vi >= 0 )
08656 {
08657 if ( 0 == m_mesh )
08658 {
08659
08660
08661
08662 ci.Set(ON_COMPONENT_INDEX::meshtop_vertex,m_top_vi);
08663 }
08664 else if (m_top_vi < m_mesh->m_V.Count())
08665 {
08666 if ( 0 == m_mesh->m_top.m_topv.Count() )
08667 {
08668
08669
08670
08671 ci.Set(ON_COMPONENT_INDEX::meshtop_vertex,m_top_vi);
08672 }
08673 else if ( m_top_vi < m_mesh->m_top.m_topv.Count() )
08674 {
08675
08676 ci.Set(ON_COMPONENT_INDEX::meshtop_vertex,m_top_vi);
08677 }
08678 }
08679 }
08680 return ci;
08681 }
08682
08683 ON_COMPONENT_INDEX ON_MeshEdgeRef::ComponentIndex() const
08684 {
08685 ON_COMPONENT_INDEX ci(ON_COMPONENT_INDEX::invalid_type,-1);
08686 if ( m_top_ei >= 0 )
08687 {
08688 if ( 0 == m_mesh || 0 == m_mesh->m_top.m_tope.Count() )
08689 {
08690
08691
08692
08693 ci.Set(ON_COMPONENT_INDEX::meshtop_edge,m_top_ei);
08694 }
08695 else if ( m_top_ei < m_mesh->m_top.m_tope.Count() )
08696 {
08697
08698 ci.Set(ON_COMPONENT_INDEX::meshtop_edge,m_top_ei);
08699 }
08700 }
08701 return ci;
08702 }
08703
08704 ON_COMPONENT_INDEX ON_MeshFaceRef::ComponentIndex() const
08705 {
08706 ON_COMPONENT_INDEX ci(ON_COMPONENT_INDEX::invalid_type,-1);
08707 if ( m_mesh_fi >= 0 )
08708 {
08709 if ( 0 == m_mesh || m_mesh_fi < m_mesh->m_F.Count() )
08710 {
08711 ci.Set(ON_COMPONENT_INDEX::mesh_face,m_mesh_fi);
08712 }
08713 }
08714 return ci;
08715 }
08716
08717 ON_Geometry* ON_Mesh::MeshComponent(
08718 ON_COMPONENT_INDEX ci
08719 ) const
08720 {
08721 ON_Geometry* component = 0;
08722 if ( ci.m_index >= 0 )
08723 {
08724 switch( ci.m_type )
08725 {
08726 case ON_COMPONENT_INDEX::mesh_vertex:
08727 {
08728 ON_MeshVertexRef r = VertexRef(ci);
08729 component = new ON_MeshVertexRef(r);
08730 }
08731 break;
08732
08733 case ON_COMPONENT_INDEX::meshtop_vertex:
08734 {
08735 ON_MeshVertexRef r = Topology().VertexRef(ci);
08736 component = new ON_MeshVertexRef(r);
08737 }
08738 break;
08739
08740 case ON_COMPONENT_INDEX::meshtop_edge:
08741 {
08742 ON_MeshEdgeRef r = EdgeRef(ci);
08743 component = new ON_MeshEdgeRef(r);
08744 }
08745 break;
08746
08747 case ON_COMPONENT_INDEX::mesh_face:
08748 {
08749 ON_MeshFaceRef r = FaceRef(ci);
08750 component = new ON_MeshFaceRef(r);
08751 }
08752 break;
08753
08754 default:
08755
08756
08757 break;
08758 }
08759 }
08760 return component;
08761 }
08762
08763 ON_3dVector ON_TriangleNormal(
08764 const ON_3dPoint& A,
08765 const ON_3dPoint& B,
08766 const ON_3dPoint& C
08767 )
08768 {
08769
08770 ON_3dVector N;
08771 double a, b, c, d;
08772 N.x = A.y*(B.z-C.z) + B.y*(C.z-A.z) + C.y*(A.z-B.z);
08773 N.y = A.z*(B.x-C.x) + B.z*(C.x-A.x) + C.z*(A.x-B.x);
08774 N.z = A.x*(B.y-C.y) + B.x*(C.y-A.y) + C.x*(A.y-B.y);
08775
08776 a = fabs(N.x);
08777 b = fabs(N.y);
08778 c = fabs(N.z);
08779 if ( b > a )
08780 {
08781 if ( c > b )
08782 {
08783
08784 if ( c > ON_DBL_MIN )
08785 {
08786 a /= c; b /= c; d = c*sqrt(1.0 + a*a + b*b);
08787 }
08788 else
08789 {
08790 d = c;
08791 }
08792 }
08793 else
08794 {
08795 if ( b > ON_DBL_MIN )
08796 {
08797
08798 a /= b; c /= b; d = b*sqrt(1.0 + c*c + a*a);
08799 }
08800 else
08801 {
08802 d = b;
08803 }
08804 }
08805 }
08806 else if ( c > a )
08807 {
08808
08809 if ( c > ON_DBL_MIN )
08810 {
08811 a /= c; b /= c; d = c*sqrt(1.0 + a*a + b*b);
08812 }
08813 else
08814 {
08815 d = c;
08816 }
08817 }
08818 else if ( a > ON_DBL_MIN )
08819 {
08820
08821 b /= a; c /= a; d = a*sqrt(1.0 + b*b + c*c);
08822 }
08823 else
08824 {
08825 d = a;
08826 }
08827
08828 if ( d > 0.0 )
08829 {
08830 N.x /= d; N.y /= d; N.z /= d;
08831 }
08832
08833 return N;
08834 }
08835
08836 bool ON_GetTrianglePlaneEquation(
08837 const ON_3dPoint& A,
08838 const ON_3dPoint& B,
08839 const ON_3dPoint& C,
08840 double* a,
08841 double* b,
08842 double* c,
08843 double* d,
08844 double* evaluation_tol
08845 )
08846 {
08847 const ON_3dVector N(ON_TriangleNormal(A,B,C));
08848 const double dd( -(N.x*A.x + N.y*A.y + N.z*A.z) );
08849
08850 *a = N.x;
08851 *b = N.y;
08852 *c = N.z;
08853 *d = dd;
08854
08855 if ( 0 != evaluation_tol )
08856 {
08857 *evaluation_tol = fabs(N.x*A.x + N.y*A.y + N.z*A.z + dd);
08858 double e = fabs(N.x*B.x + N.y*B.y + N.z*B.z + dd);
08859 if ( e > *evaluation_tol )
08860 *evaluation_tol = e;
08861 e = fabs(N.x*C.x + N.y*C.y + N.z*C.z + dd);
08862 if ( e > *evaluation_tol )
08863 *evaluation_tol = e;
08864 *evaluation_tol *= (1.0 + ON_EPSILON);
08865 }
08866
08867 return (0.0 != N.x || 0.0 != N.y || 0.0 != N.z);
08868 }
08869
08870 const bool* ON_Mesh::HiddenVertexArray() const
08871 {
08872 return ( ( m_hidden_count > 0 && m_H.Count() == m_V.Count() ) ? m_H.Array() : 0);
08873 }
08874
08875 void ON_Mesh::DestroyHiddenVertexArray()
08876 {
08877 m_H.Destroy();
08878 m_hidden_count = 0;
08879 }
08880
08881 int ON_Mesh::HiddenVertexCount() const
08882 {
08883 return ((m_H.Count() == m_V.Count()) ? m_hidden_count : 0);
08884 }
08885
08886 void ON_Mesh::SetVertexHiddenFlag( int meshvi, bool bHidden )
08887 {
08888 const int vcount = m_V.Count();
08889 if ( meshvi >= 0 && meshvi < vcount )
08890 {
08891 if ( bHidden )
08892 {
08893 if ( vcount != m_H.Count() )
08894 {
08895 m_H.SetCapacity(vcount);
08896 m_H.SetCount(vcount);
08897 m_H.Zero();
08898 m_H[meshvi] = true;
08899 m_hidden_count = 1;
08900 }
08901 else if ( false == m_H[meshvi] )
08902 {
08903 m_H[meshvi] = true;
08904 m_hidden_count++;
08905 }
08906 }
08907 else
08908 {
08909
08910 if ( m_hidden_count > 0 && vcount == m_H.Count() )
08911 {
08912 if ( m_H[meshvi] )
08913 {
08914 m_H[meshvi] = false;
08915 m_hidden_count--;
08916 if ( 0 == m_hidden_count )
08917 {
08918 DestroyHiddenVertexArray();
08919 }
08920 }
08921 }
08922 else if ( m_hidden_count > 0 || m_H.Capacity() > 0 )
08923 {
08924
08925 DestroyHiddenVertexArray();
08926 }
08927 }
08928 }
08929 }
08930
08931
08932 bool ON_Mesh::VertexIsHidden(int meshvi) const
08933 {
08934 const int vcount = m_V.Count();
08935 return ((m_hidden_count > 0 && meshvi >= 0 && meshvi < vcount && vcount == m_H.Count())
08936 ? m_H[meshvi]
08937 : false);
08938 }
08939
08940 bool ON_Mesh::FaceIsHidden(int meshfi) const
08941 {
08942 const bool* bHiddenVertex = HiddenVertexArray();
08943 if ( bHiddenVertex && meshfi >= 0 && meshfi < m_F.Count() )
08944 {
08945 ON_MeshFace f = m_F[meshfi];
08946 if ( bHiddenVertex[f.vi[0]] || bHiddenVertex[f.vi[1]] || bHiddenVertex[f.vi[2]] || bHiddenVertex[f.vi[3]] )
08947 return true;
08948 }
08949 return false;
08950 }
08951
08952 bool ON_MeshTopology::TopVertexIsHidden( int topvi ) const
08953 {
08954 const bool* bHiddenVertex = m_mesh ? m_mesh->HiddenVertexArray() : 0;
08955 if ( bHiddenVertex && topvi >= 0 && topvi < m_topv.Count() )
08956 {
08957 const ON_MeshTopologyVertex& topv = m_topv[topvi];
08958 int i;
08959 for ( i = 0; i < topv.m_v_count; i++ )
08960 {
08961 if ( !bHiddenVertex[topv.m_vi[i]] )
08962 return false;
08963 }
08964 return true;
08965 }
08966 return false;
08967 }
08968
08969 bool ON_MeshTopology::TopEdgeIsHidden( int topei ) const
08970 {
08971
08972 const bool* bHiddenVertex = m_mesh ? m_mesh->HiddenVertexArray() : 0;
08973 if ( bHiddenVertex && topei >= 0 && topei < m_tope.Count() )
08974 {
08975 const ON_MeshTopologyEdge& tope = m_tope[topei];
08976 const ON_MeshTopologyVertex& topv0 = m_topv[tope.m_topvi[0]];
08977 const ON_MeshTopologyVertex& topv1 = m_topv[tope.m_topvi[1]];
08978 int i;
08979
08980 for ( i = 0; i < topv0.m_v_count; i++ )
08981 {
08982 if ( !bHiddenVertex[topv0.m_vi[i]] )
08983 break;
08984 }
08985 if ( i >= topv0.m_v_count )
08986 return true;
08987
08988 for ( i = 0; i < topv1.m_v_count; i++ )
08989 {
08990 if ( !bHiddenVertex[topv1.m_vi[i]] )
08991 return false;
08992 }
08993
08994 return true;
08995 }
08996 return false;
08997 }
08998
08999 bool ON_MeshTopology::TopFaceIsHidden( int topfi ) const
09000 {
09001
09002 return m_mesh ? m_mesh->FaceIsHidden(topfi) : false;
09003 }
09004
09005
09006 ON_MappingTag::ON_MappingTag()
09007 {
09008 Default();
09009 }
09010
09011 void ON_MappingTag::Dump( ON_TextLog& text_log ) const
09012 {
09013 text_log.Print("Texture/color coordinates tag:\n");
09014 text_log.PushIndent();
09015 text_log.Print("mapping id: "); text_log.Print(m_mapping_id); text_log.Print("\n");
09016 text_log.Print("mapping crc: %08x\n",m_mapping_crc);
09017 text_log.Print("mesh xform:\n");
09018 text_log.PushIndent(); text_log.Print(m_mesh_xform); text_log.PopIndent();
09019 text_log.PushIndent();
09020 text_log.Print(m_mesh_xform);
09021 text_log.PopIndent();
09022 text_log.PopIndent();
09023 }
09024
09025 void ON_MappingTag::Transform( const ON_Xform& xform )
09026 {
09027 if ( !ON_UuidIsNil(m_mapping_id) )
09028 {
09029
09030
09031 m_mesh_xform = xform*m_mesh_xform;
09032 }
09033 }
09034
09035 void ON_MappingTag::SetDefaultSurfaceParameterMappingTag()
09036 {
09037 ON_TextureMapping srfp_mapping;
09038 srfp_mapping.m_type = ON_TextureMapping::srfp_mapping;
09039 srfp_mapping.m_mapping_id = ON_nil_uuid;
09040 Set(srfp_mapping);
09041 }
09042
09043 void ON_MappingTag::Set(const ON_TextureMapping& mapping)
09044 {
09045 Default();
09046 m_mapping_id = mapping.m_mapping_id;
09047 m_mapping_type = mapping.m_type;
09048 m_mapping_crc = mapping.MappingCRC();
09049 }
09050
09051 bool ON_MappingTag::IsSet() const
09052 {
09053 return (0 != m_mapping_crc || !ON_UuidIsNil(m_mapping_id));
09054 }
09055
09056 bool ON_MappingTag::IsDefaultSurfaceParameterMapping() const
09057 {
09058 bool rc = (ON_TextureMapping::srfp_mapping == m_mapping_type);
09059 if ( rc )
09060 {
09061
09062
09063 ON_TextureMapping tmp;
09064 tmp.m_type = ON_TextureMapping::srfp_mapping;
09065 rc = (m_mapping_crc == tmp.MappingCRC());
09066 }
09067 return rc;
09068 }
09069
09070
09071 void ON_MappingTag::Default()
09072 {
09073 memset(this,0,sizeof(*this));
09074 m_mesh_xform.m_xform[0][0] = 1.0;
09075 m_mesh_xform.m_xform[1][1] = 1.0;
09076 m_mesh_xform.m_xform[2][2] = 1.0;
09077 m_mesh_xform.m_xform[3][3] = 1.0;
09078 }
09079
09080 int ON_MappingTag::Compare(
09081 const ON_MappingTag& other,
09082 bool bCompareId,
09083 bool bCompareCRC,
09084 bool bCompareXform
09085 ) const
09086 {
09087 int rc = 0;
09088 if ( !rc && bCompareId )
09089 {
09090 rc = ON_UuidCompare(m_mapping_id,other.m_mapping_id);
09091 }
09092 if ( !rc && bCompareCRC )
09093 {
09094 rc = ((int)m_mapping_crc) - ((int)other.m_mapping_crc);
09095 }
09096 if ( !rc && bCompareXform )
09097 {
09098 rc = m_mesh_xform.Compare(other.m_mesh_xform);
09099 }
09100 return rc;
09101 }
09102
09103
09104
09105 bool ON_MappingTag::Write(ON_BinaryArchive& archive) const
09106 {
09107 bool rc = archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,1);
09108 if (!rc)
09109 return false;
09110
09111 for(;;)
09112 {
09113 rc = archive.WriteUuid(m_mapping_id);
09114 if(!rc) break;
09115 rc = archive.WriteInt(m_mapping_crc);
09116 if(!rc) break;
09117 rc = archive.WriteXform(m_mesh_xform);
09118 if(!rc) break;
09119
09120
09121 rc = archive.WriteInt(m_mapping_type);
09122 if (!rc) break;
09123
09124 break;
09125 }
09126
09127 if ( !archive.EndWrite3dmChunk() )
09128 rc = false;
09129
09130 return rc;
09131 }
09132
09133 bool ON_MappingTag::Read(ON_BinaryArchive& archive)
09134 {
09135 Default();
09136 int mjv = 0, mnv = 0;
09137 bool rc = archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&mjv,&mnv);
09138 if (!rc)
09139 return false;
09140
09141 for(;;)
09142 {
09143 rc = (1 == mjv);
09144 if (!rc) break;
09145 rc = archive.ReadUuid(m_mapping_id);
09146 if(!rc) break;
09147 if ( 0 == ON_UuidCompare(&obsolete_default_srfp_mapping_id,&m_mapping_id) )
09148 m_mapping_id = ON_nil_uuid;
09149 rc = archive.ReadInt(&m_mapping_crc);
09150 if(!rc) break;
09151 rc = archive.ReadXform(m_mesh_xform);
09152 if(!rc) break;
09153
09154 if ( mnv >= 1 )
09155 {
09156
09157 int i = m_mapping_type;
09158 rc = archive.ReadInt(&i);
09159 if ( rc )
09160 m_mapping_type = ON_TextureMapping::TypeFromInt(i);
09161 if (!rc) break;
09162 }
09163
09164
09165 break;
09166 }
09167
09168 if ( !archive.EndRead3dmChunk() )
09169 rc = false;
09170
09171 return rc;
09172 }
09173
09174 ON_TextureCoordinates::ON_TextureCoordinates()
09175 {
09176 m_dim = 0;
09177 }
09178
09179
09181
09182
09183
09184
09185 ON_OBJECT_IMPLEMENT(ON_MeshDoubleVertices,ON_UserData,"17F24E75-21BE-4a7b-9F3D-7F85225247E3");
09186
09187 ON_MeshDoubleVertices* ON_MeshDoubleVertices::Get(const ON_Mesh* mesh)
09188 {
09189 return ON_MeshDoubleVertices::Cast(mesh->GetUserData(ON_MeshDoubleVertices::m_ON_MeshDoubleVertices_class_id.Uuid()));
09190 }
09191
09192 ON_MeshDoubleVertices* ON_MeshDoubleVertices::Attach(const ON_Mesh* mesh)
09193 {
09194 ON_MeshDoubleVertices* dv = ON_MeshDoubleVertices::Get(mesh);
09195 if ( 0 != dv )
09196 return 0;
09197 dv = new ON_MeshDoubleVertices();
09198 const_cast<ON_Mesh*>(mesh)->AttachUserData(dv);
09199 return dv;
09200 }
09201
09202 ON_MeshDoubleVertices::ON_MeshDoubleVertices()
09203 : ON_UserData()
09204 , m_fcount(0)
09205 , m_dcount(0)
09206 , m_fCRC(0)
09207 , m_dCRC(0)
09208 {
09209 m_userdata_uuid = ON_MeshDoubleVertices::m_ON_MeshDoubleVertices_class_id.Uuid();
09210 m_application_uuid = ON_opennurbs5_id;
09211 m_userdata_copycount = 1;
09212 }
09213
09214 ON_MeshDoubleVertices::~ON_MeshDoubleVertices()
09215 {}
09216
09217 ON_BOOL32 ON_MeshDoubleVertices::IsValid( ON_TextLog* ) const
09218 {
09219 return true;
09220 }
09221
09222 void ON_MeshDoubleVertices::Dump( ON_TextLog& text_log ) const
09223 {
09224
09225 ON_UserData::Dump(text_log);
09226 }
09227
09228 unsigned int ON_MeshDoubleVertices::SizeOf() const
09229 {
09230 return m_dV.SizeOfArray() + ON_UserData::SizeOf();
09231 }
09232
09233 ON__UINT32 ON_MeshDoubleVertices::DataCRC(ON__UINT32 current_remainder) const
09234 {
09235 current_remainder = ON_CRC32(current_remainder,sizeof(m_fcount),&m_fcount);
09236 current_remainder = ON_CRC32(current_remainder,sizeof(m_dcount),&m_dcount);
09237 current_remainder = ON_CRC32(current_remainder,sizeof(m_fCRC),&m_fCRC);
09238 current_remainder = ON_CRC32(current_remainder,sizeof(m_dCRC),&m_dCRC);
09239 current_remainder = m_dV.DataCRC(current_remainder);
09240 return current_remainder;
09241 }
09242
09243 ON_BOOL32 ON_MeshDoubleVertices::Write(ON_BinaryArchive& file) const
09244 {
09245 bool rc = file.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0);
09246 if (!rc)
09247 return false;
09248 for(;;)
09249 {
09250 rc = file.WriteInt(m_fcount);
09251 if (!rc)
09252 break;
09253 rc = file.WriteInt(m_dcount);
09254 if (!rc)
09255 break;
09256 rc = file.WriteInt(m_fCRC);
09257 if (!rc)
09258 break;
09259 rc = file.WriteInt(m_dCRC);
09260 if (!rc)
09261 break;
09262 rc = file.WriteArray(m_dV);
09263 if (!rc)
09264 break;
09265 break;
09266 }
09267 if ( !file.EndWrite3dmChunk() )
09268 rc = false;
09269 return rc;
09270 }
09271
09272 ON_BOOL32 ON_MeshDoubleVertices::Read(ON_BinaryArchive& file)
09273 {
09274 m_fcount = 0;
09275 m_dcount = 0;
09276 m_fCRC = 0;
09277 m_dCRC = 0;
09278 m_dV.Destroy();
09279
09280 int major_version = 0;
09281 int minor_version = 0;
09282 bool rc = file.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
09283 if (!rc)
09284 return false;
09285 for(;;)
09286 {
09287 rc = file.ReadInt(&m_fcount);
09288 if (!rc)
09289 break;
09290 rc = file.ReadInt(&m_dcount);
09291 if (!rc)
09292 break;
09293 rc = file.ReadInt(&m_fCRC);
09294 if (!rc)
09295 break;
09296 rc = file.ReadInt(&m_dCRC);
09297 if (!rc)
09298 break;
09299 rc = file.ReadArray(m_dV);
09300 if (!rc)
09301 break;
09302 break;
09303 }
09304 if ( !file.EndRead3dmChunk() )
09305 rc = false;
09306 return rc;
09307 }
09308
09309
09310 ON_BOOL32 ON_MeshDoubleVertices::GetDescription( ON_wString& description )
09311 {
09312 description = L"ON_Mesh double precision vertices";
09313 return true;
09314 }
09315
09316 ON_BOOL32 ON_MeshDoubleVertices::Archive() const
09317 {
09318
09319
09320 if ( m_fcount != m_dcount )
09321 {
09322 ON_ERROR("m_fcount != m_dcount");
09323 return false;
09324 }
09325
09326 if ( m_dcount != m_dV.Count() )
09327 {
09328 ON_ERROR("m_dcount != m_dV.Count()");
09329 return false;
09330 }
09331
09332 if ( m_dCRC != DoubleCRC() )
09333 {
09334 ON_ERROR("m_dCRC != DoubleCRC()");
09335 return false;
09336 }
09337
09338 const ON_Mesh* mesh = ON_Mesh::Cast( Owner() );
09339 if ( 0 == mesh )
09340 {
09341 ON_ERROR("0 = ON_Mesh::Cast( Owner() )");
09342 return false;
09343 }
09344
09345 if ( m_fcount != mesh->m_V.Count() )
09346 {
09347 ON_ERROR("m_fcount != mesh->m_V.Count()");
09348 return false;
09349 }
09350
09351 if ( m_fCRC != ON_MeshDoubleVertices::FloatCRC(mesh->m_V) )
09352 {
09353 ON_ERROR("m_fCRC != ON_MeshDoubleVertices::FloatCRC(mesh->m_V)");
09354 return false;
09355 }
09356
09357 return true;
09358 }
09359
09360 ON_BOOL32 ON_MeshDoubleVertices::Transform( const ON_Xform& xform )
09361 {
09362 if ( !xform.IsIdentity() )
09363 {
09364 const ON__UINT32 crc0 = DoubleCRC();
09365 m_dV.Transform(xform);
09366 const ON__UINT32 crc1 = DoubleCRC();
09367 if ( crc0 == m_dCRC && m_dV.Count() == m_dcount )
09368 m_dCRC = crc1;
09369 else
09370 m_dCRC = (0==crc1)?1:0;
09371 }
09372 return true;
09373 }
09374
09375 bool ON_Mesh::HasSynchronizedDoubleAndSinglePrecisionVertices() const
09376 {
09377 ON_3fPoint P;
09378 const ON_MeshDoubleVertices* dv = ON_MeshDoubleVertices::Get(this);
09379 if ( 0 == dv )
09380 return false;
09381 int count = m_V.Count();
09382 if ( count != dv->m_dV.Count() )
09383 return false;
09384 const ON_3fPoint* FV = m_V.Array();
09385 const ON_3dPoint* DV = dv->m_dV.Array();
09386 while (count--)
09387 {
09388
09389 P.x = (float)DV->x;
09390 P.y = (float)DV->y;
09391 P.z = (float)DV->z;
09392 if ( !(P.x == FV->x && P.y == FV->y && P.z == FV->z) )
09393 return false;
09394 }
09395 return true;
09396 }
09397
09398 bool ON_Mesh::HasDoublePrecisionVertices() const
09399 {
09400 return ( 0 != ON_MeshDoubleVertices::Get(this));
09401 }
09402
09403 void ON_Mesh::DestroyDoublePrecisionVertices()
09404 {
09405 ON_MeshDoubleVertices* dv = ON_MeshDoubleVertices::Get(this);
09406 if ( dv )
09407 delete dv;
09408 }
09409
09410 void ON_Mesh::EnableDoublePrecisionVertices(bool bEnableDoublePrecisionVertices)
09411 {
09412 ON_MeshDoubleVertices* dv = ON_MeshDoubleVertices::Get(this);
09413 if ( bEnableDoublePrecisionVertices )
09414 {
09415 if ( 0 == dv )
09416 {
09417 dv = ON_MeshDoubleVertices::Attach(this);
09418 UpdateDoublePrecisionVertices();
09419 }
09420 }
09421 else
09422 {
09423
09424 if ( 0 != dv )
09425 delete dv;
09426 }
09427 }
09428
09429 ON__UINT32 ON_MeshDoubleVertices::FloatCRC( const ON_3fPointArray& V )
09430 {
09431 return V.DataCRC(0);
09432 }
09433
09434 ON__UINT32 ON_MeshDoubleVertices::DoubleCRC() const
09435 {
09436 return m_dV.DataCRC(0);
09437 }
09438
09439 void ON_Mesh::UpdateSinglePrecisionVertices()
09440 {
09441 ON_MeshDoubleVertices* dv = ON_MeshDoubleVertices::Get(this);
09442 if ( 0 == dv )
09443 return;
09444 int count = dv->m_dV.Count();
09445 m_V.Reserve(count);
09446 m_V.SetCount(count);
09447 ON_3fPoint* fV = m_V.Array();
09448 const ON_3dPoint* dV = dv->m_dV.Array();
09449 while(count--)
09450 {
09451 fV->x = (float)dV->x;
09452 fV->y = (float)dV->y;
09453 fV->z = (float)dV->z;
09454 fV++;
09455 dV++;
09456 }
09457 dv->m_fcount = dv->m_dV.Count();
09458 dv->m_dcount = dv->m_dV.Count();
09459 dv->m_fCRC = ON_MeshDoubleVertices::FloatCRC(m_V);
09460 dv->m_dCRC = dv->DoubleCRC();
09461 }
09462
09463 void ON_Mesh::UpdateDoublePrecisionVertices()
09464 {
09465 ON_MeshDoubleVertices* dv = ON_MeshDoubleVertices::Get(this);
09466 if ( 0 == dv )
09467 return;
09468 int count = m_V.Count();
09469 bool bSelectiveUpdate = (count == dv->m_dV.Count());
09470 dv->m_dV.Reserve(count);
09471 dv->m_dV.SetCount(count);
09472 ON_3dPoint* dV = dv->m_dV.Array();
09473 const ON_3fPoint* fV = m_V.Array();
09474 if ( bSelectiveUpdate )
09475 {
09476
09477
09478
09479
09480
09481
09482
09483 ON_3fPoint P;
09484 while(count--)
09485 {
09486 P.x = (float)dV->x;
09487 P.y = (float)dV->y;
09488 P.z = (float)dV->z;
09489 if ( !(P.x == fV->x && P.y == fV->y && P.z == fV->z) )
09490 {
09491
09492 dV->x = (double)fV->x;
09493 dV->y = (double)fV->y;
09494 dV->z = (double)fV->z;
09495 }
09496 dV++;
09497 fV++;
09498 }
09499 }
09500 else
09501 {
09502 while(count--)
09503 {
09504 dV->x = (double)fV->x;
09505 dV->y = (double)fV->y;
09506 dV->z = (double)fV->z;
09507 dV++;
09508 fV++;
09509 }
09510 }
09511 dv->m_fcount = m_V.Count();
09512 dv->m_dcount = m_V.Count();
09513 dv->m_fCRC = ON_MeshDoubleVertices::FloatCRC(m_V);
09514 dv->m_dCRC = dv->DoubleCRC();
09515 }
09516
09517 void ON_Mesh::SetSinglePrecisionVerticesAsValid()
09518 {
09519 ON_MeshDoubleVertices* dv = ON_MeshDoubleVertices::Get(this);
09520 if ( 0 == dv )
09521 return;
09522 dv->m_fcount = m_V.Count();
09523 dv->m_fCRC = ON_MeshDoubleVertices::FloatCRC(m_V);
09524 }
09525
09526 void ON_Mesh::SetDoublePrecisionVerticesAsValid()
09527 {
09528 ON_MeshDoubleVertices* dv = ON_MeshDoubleVertices::Get(this);
09529 if ( 0 == dv )
09530 return;
09531 dv->m_dcount = dv->m_dV.Count();
09532 dv->m_dCRC = dv->DoubleCRC();
09533 }
09534
09535 bool ON_Mesh::SinglePrecisionVerticesAreValid() const
09536 {
09537 const ON_MeshDoubleVertices* dv = ON_MeshDoubleVertices::Get(this);
09538 if ( 0 == dv )
09539 return true;
09540 return ( dv->m_fcount == m_V.Count() && dv->m_fCRC == ON_MeshDoubleVertices::FloatCRC(m_V) );
09541 }
09542
09543 bool ON_Mesh::DoublePrecisionVerticesAreValid() const
09544 {
09545 const ON_MeshDoubleVertices* dv = ON_MeshDoubleVertices::Get(this);
09546 if ( 0 == dv )
09547 return true;
09548
09549
09550 return ( dv->m_dcount == dv->m_dV.Count() && dv->m_dCRC == dv->DoubleCRC() );
09551 }
09552
09553
09554
09555 ON_3dPointArray& ON_Mesh::DoublePrecisionVertices()
09556 {
09557 ON_MeshDoubleVertices* dv = ON_MeshDoubleVertices::Get(this);
09558
09559 bool bUpdate = false;
09560 if ( 0 == dv )
09561 {
09562 dv = ON_MeshDoubleVertices::Attach(this);
09563 bUpdate = true;
09564 }
09565 else if ( dv->m_dcount != dv->m_dV.Count()|| dv->m_dCRC != dv->DoubleCRC() )
09566 {
09567 if ( dv->m_fcount == m_V.Count() && dv->m_fCRC == ON_MeshDoubleVertices::FloatCRC(m_V) )
09568 bUpdate = true;
09569 }
09570
09571 if ( bUpdate )
09572 UpdateDoublePrecisionVertices();
09573
09574 return dv->m_dV;
09575 }
09576
09577 ON_3dPoint ON_Mesh::Vertex(int vertex_index) const
09578 {
09579 if ( vertex_index < 0 || vertex_index >= m_V.Count() )
09580 return ON_3dPoint::UnsetPoint;
09581
09582 const ON_3fPoint F = m_V[vertex_index];
09583 ON_MeshDoubleVertices* dv = ON_MeshDoubleVertices::Get(this);
09584 if ( 0 != dv && dv->m_dV.Count() == m_V.Count() )
09585 {
09586 ON_3dPoint D = dv->m_dV[vertex_index];
09587 if ( F.x == (float)D.x && F.y == (float)D.y && F.z == (float)D.z )
09588 {
09589
09590 return D;
09591 }
09592 }
09593
09594 return F;
09595 }
09596
09597 const ON_3dPointArray& ON_Mesh::DoublePrecisionVertices() const
09598 {
09599 ON_Mesh& mesh = const_cast<ON_Mesh&>(*this);
09600 ON_3dPointArray& a = mesh.DoublePrecisionVertices();
09601 return a;
09602 }
09603
09604 ON_3fPointArray& ON_Mesh::SinglePrecisionVertices()
09605 {
09606 ON_MeshDoubleVertices* dv = ON_MeshDoubleVertices::Get(this);
09607
09608 if ( 0 != dv )
09609 {
09610 if ( dv->m_fcount != m_V.Count()|| dv->m_fCRC != ON_MeshDoubleVertices::FloatCRC(m_V) )
09611 {
09612 if ( dv->m_dcount == dv->m_dV.Count() && dv->m_dCRC == dv->DoubleCRC() )
09613 UpdateSinglePrecisionVertices();
09614 }
09615 }
09616
09617 return m_V;
09618 }
09619
09620 const ON_3fPointArray& ON_Mesh::SinglePrecisionVertices() const
09621 {
09622 ON_Mesh& mesh = const_cast<ON_Mesh&>(*this);
09623 ON_3fPointArray& a = mesh.SinglePrecisionVertices();
09624 return a;
09625 }
09626
09627
09629
09630
09631
09632
09633
09634 class ON_PerObjectMeshParameters : public ON_UserData
09635 {
09636 #if !defined(ON_BOZO_VACCINE_B5628CA982C44CAE9883487B3E4AB28B)
09637 #error Never copy this class definition or put this definition in a header file!
09638 #endif
09639 ON_OBJECT_DECLARE(ON_PerObjectMeshParameters);
09640
09641 public:
09642 ON_PerObjectMeshParameters();
09643 ~ON_PerObjectMeshParameters();
09644
09645
09646 public:
09647
09648 ON_BOOL32 IsValid( ON_TextLog* text_log = NULL ) const;
09649
09650 unsigned int SizeOf() const;
09651
09652 ON__UINT32 DataCRC(ON__UINT32 current_remainder) const;
09653
09654 ON_BOOL32 Write(ON_BinaryArchive& binary_archive) const;
09655
09656 ON_BOOL32 Read(ON_BinaryArchive& binary_archive);
09657
09658 ON_BOOL32 Archive() const;
09659
09660 ON_BOOL32 GetDescription( ON_wString& description );
09661
09662 public:
09663 static
09664 ON_PerObjectMeshParameters* FindOrCreate( const ON_Object*, bool bCreate );
09665
09666 ON_MeshParameters m_mp;
09667 };
09668
09669 #undef ON_BOZO_VACCINE_B5628CA982C44CAE9883487B3E4AB28B
09670
09671 ON_OBJECT_IMPLEMENT(ON_PerObjectMeshParameters,ON_UserData,"B5628CA9-82C4-4CAE-9883-487B3E4AB28B");
09672
09673 ON_PerObjectMeshParameters* ON_PerObjectMeshParameters::FindOrCreate(const ON_Object* object,bool bCreate)
09674 {
09675 if ( 0 == object )
09676 return 0;
09677 ON_PerObjectMeshParameters* ud = ON_PerObjectMeshParameters::Cast(object->GetUserData(ON_PerObjectMeshParameters::m_ON_PerObjectMeshParameters_class_id.Uuid()));
09678 if ( !ud && bCreate )
09679 {
09680 ud = new ON_PerObjectMeshParameters();
09681 const_cast< ON_Object* >(object)->AttachUserData(ud);
09682 }
09683 return ud;
09684 }
09685
09686 ON_PerObjectMeshParameters::ON_PerObjectMeshParameters()
09687 : m_mp(ON_MeshParameters::FastRenderMesh)
09688 {
09689 m_userdata_uuid = ON_PerObjectMeshParameters::m_ON_PerObjectMeshParameters_class_id.Uuid();
09690 m_application_uuid = ON_opennurbs5_id;
09691 m_userdata_copycount = 1;
09692 m_mp.m_bCustomSettings = true;
09693 m_mp.m_bComputeCurvature = false;
09694 }
09695
09696 ON_PerObjectMeshParameters::~ON_PerObjectMeshParameters()
09697 {
09698 }
09699
09700
09701 ON_BOOL32 ON_PerObjectMeshParameters::IsValid( ON_TextLog* text_log ) const
09702 {
09703 return true;
09704 }
09705
09706
09707 unsigned int ON_PerObjectMeshParameters::SizeOf() const
09708 {
09709 size_t sz = sizeof(*this) - sizeof(ON_UserData);
09710 return (unsigned int)sz;
09711 }
09712
09713
09714 ON__UINT32 ON_PerObjectMeshParameters::DataCRC(ON__UINT32 current_remainder) const
09715 {
09716 return m_mp.DataCRC(current_remainder);
09717 }
09718
09719
09720 ON_BOOL32 ON_PerObjectMeshParameters::Write(ON_BinaryArchive& binary_archive) const
09721 {
09722 if ( !binary_archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0) )
09723 return false;
09724
09725 bool rc = false;
09726 for(;;)
09727 {
09728 if ( !binary_archive.BeginWrite3dmBigChunk(TCODE_ANONYMOUS_CHUNK,0) )
09729 break;
09730 bool mprc = m_mp.Write(binary_archive);
09731 if ( !binary_archive.EndWrite3dmChunk() )
09732 break;
09733 if ( !mprc )
09734 break;
09735 rc = true;
09736 break;
09737 }
09738
09739 if ( !binary_archive.EndWrite3dmChunk() )
09740 rc = false;
09741
09742 return rc;
09743 }
09744
09745
09746 ON_BOOL32 ON_PerObjectMeshParameters::Read(ON_BinaryArchive& binary_archive)
09747 {
09748 m_mp = ON_MeshParameters::FastRenderMesh;
09749 m_mp.m_bCustomSettings = true;
09750 m_mp.m_bComputeCurvature = false;
09751
09752 int major_version = 0;
09753 int minor_version = 0;
09754 if ( !binary_archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version) )
09755 return false;
09756
09757 bool rc = false;
09758 for(;;)
09759 {
09760 if ( 1 != major_version )
09761 break;
09762
09763 unsigned int tcode(0);
09764 ON__INT64 value(0);
09765 if (!binary_archive.BeginRead3dmBigChunk(&tcode,&value))
09766 break;
09767 bool mprc = false;
09768 for(;;)
09769 {
09770 if (TCODE_ANONYMOUS_CHUNK != tcode )
09771 break;
09772 if (value <= 0)
09773 break;
09774 if (!m_mp.Read(binary_archive))
09775 break;
09776 mprc = true;
09777 break;
09778 }
09779 if (!binary_archive.EndRead3dmChunk())
09780 break;
09781 if (!mprc)
09782 break;
09783
09784 rc = true;
09785 break;
09786 }
09787
09788 if ( !binary_archive.EndRead3dmChunk() )
09789 rc = false;
09790
09791 m_mp.m_bCustomSettings = true;
09792 m_mp.m_bComputeCurvature = false;
09793
09794 return rc;
09795 }
09796
09797
09798 ON_BOOL32 ON_PerObjectMeshParameters::Archive() const
09799 {
09800 return true;
09801 }
09802
09803
09804 ON_BOOL32 ON_PerObjectMeshParameters::GetDescription( ON_wString& description )
09805 {
09806 description = L"Custom Render Mesh Parameters";
09807 return true;
09808 }
09809
09810
09811
09812
09814
09815 const ON_MeshParameters* ON_3dmObjectAttributes::CustomRenderMeshParameters() const
09816 {
09817 const ON_PerObjectMeshParameters* ud = ON_PerObjectMeshParameters::FindOrCreate(this,false);
09818 return (0 != ud) ? &ud->m_mp : 0;
09819 }
09820
09821 bool ON_3dmObjectAttributes::SetCustomRenderMeshParameters( const ON_MeshParameters& mp )
09822 {
09823 ON_PerObjectMeshParameters* ud = ON_PerObjectMeshParameters::FindOrCreate(this,true);
09824 if ( 0 == ud )
09825 return false;
09826 ud->m_mp = mp;
09827 ud->m_mp.m_bCustomSettings = true;
09828 ud->m_mp.m_bComputeCurvature = false;
09829 if ( 1 != ud->m_mp.m_texture_range && 2 != ud->m_mp.m_texture_range )
09830 ud->m_mp.m_texture_range = 2;
09831 return true;
09832 }
09833
09834 void ON_3dmObjectAttributes::DeleteCustomRenderMeshParameters()
09835 {
09836 ON_PerObjectMeshParameters* ud = ON_PerObjectMeshParameters::FindOrCreate(this,false);
09837 if ( 0 != ud )
09838 delete ud;
09839 }
09840
09841 bool ON_3dmObjectAttributes::EnableCustomRenderMeshParameters(bool bEnable)
09842 {
09843 ON_PerObjectMeshParameters* ud = ON_PerObjectMeshParameters::FindOrCreate(this,false);
09844 if ( 0 != ud )
09845 ud->m_mp.m_bCustomSettingsEnabled = bEnable ? true : false;
09846 return (!bEnable || 0 != ud);
09847 }
09848
09849 void ON_Mesh::DestroyTree( bool bDeleteTree )
09850 {
09851 }
09852
09853
09854 int* ON_Mesh_GetVidHelper( const int Vcount, const ON_3fPoint* fV, const ON_3dPoint* dV, int first_vid, int* Vid, int* Vindex );
09855 static int comparefV( const void* a, const void* b )
09856 {
09857 const float* af = (const float*)a;
09858 const float* bf = (const float*)b;
09859 if ( af[0] < bf[0] )
09860 return -1;
09861 if ( af[0] > bf[0] )
09862 return 1;
09863 if ( af[1] < bf[1] )
09864 return -1;
09865 if ( af[1] > bf[1] )
09866 return 1;
09867 if ( af[2] < bf[2] )
09868 return -1;
09869 if ( af[2] > bf[2] )
09870 return 1;
09871 return 0;
09872 }
09873
09874 static int comparedV( const void* a, const void* b )
09875 {
09876 const double* af = (const double*)a;
09877 const double* bf = (const double*)b;
09878 if ( af[0] < bf[0] )
09879 return -1;
09880 if ( af[0] > bf[0] )
09881 return 1;
09882 if ( af[1] < bf[1] )
09883 return -1;
09884 if ( af[1] > bf[1] )
09885 return 1;
09886 if ( af[2] < bf[2] )
09887 return -1;
09888 if ( af[2] > bf[2] )
09889 return 1;
09890 return 0;
09891 }
09892
09893 int* ON_Mesh_GetVidHelper( const int Vcount, const ON_3fPoint* fV, const ON_3dPoint* dV, int first_vid, int* Vid, int* Vindex )
09894 {
09895
09896
09897 if ( Vcount <= 0 || (0 == dV && 0 == fV) )
09898 return 0;
09899
09900 int Vmapbuffer[1024];
09901 int* Vmap;
09902 int id, i;
09903 const ON_3fPoint* fP0;
09904 const ON_3fPoint* fP1;
09905 const ON_3dPoint* dP0;
09906 const ON_3dPoint* dP1;
09907 if ( Vindex )
09908 {
09909 Vmap = Vindex;
09910 }
09911 else
09912 {
09913 Vmap = ( Vcount*sizeof(*Vmap) <= sizeof(Vmapbuffer) )
09914 ? &Vmapbuffer[0]
09915 : (int*)onmalloc( Vcount*sizeof(*Vmap) );
09916 }
09917 if ( 0 == Vmap )
09918 return 0;
09919
09920
09921
09922
09923
09924
09925
09926 if ( 0 != dV )
09927 ON_Sort( ON::quick_sort, Vmap, dV, Vcount, sizeof(dV[0]), comparedV );
09928 else
09929 ON_Sort( ON::quick_sort, Vmap, fV, Vcount, sizeof(fV[0]), comparefV );
09930
09931
09932 if ( 0 == Vid )
09933 Vid = (int*)onmalloc(Vcount*sizeof(*Vid));
09934
09935 if ( 0 != dV )
09936 {
09937 dP0 = dV + Vmap[0];
09938 id = first_vid;
09939 Vid[Vmap[0]] = id;
09940 for ( i = 1; i < Vcount; i++ )
09941 {
09942 dP1 = dV + Vmap[i];
09943 if ( dP0->x != dP1->x || dP0->y != dP1->y || dP0->z != dP1->z )
09944 {
09945 dP0 = dP1;
09946 id++;
09947 }
09948 Vid[Vmap[i]] = id;
09949 }
09950 }
09951 else
09952 {
09953 fP0 = fV + Vmap[0];
09954 id = first_vid;
09955 Vid[Vmap[0]] = id;
09956 for ( i = 1; i < Vcount; i++ )
09957 {
09958 fP1 = fV + Vmap[i];
09959 if ( fP0->x != fP1->x || fP0->y != fP1->y || fP0->z != fP1->z )
09960 {
09961 fP0 = fP1;
09962 id++;
09963 }
09964 Vid[Vmap[i]] = id;
09965 }
09966 }
09967
09968 if ( 0 != Vmap && Vmap != &Vmapbuffer[0] && Vmap != Vindex )
09969 onfree(Vmap);
09970
09971 return Vid;
09972 }
09973
09974 int* ON_Mesh::GetVertexLocationIds( int first_vid, int* Vid, int* Vindex ) const
09975 {
09976 const ON_3dPoint* dV = Mesh_dV(*this);
09977 const ON_3fPoint* fV = (0 == dV) ? m_V.Array() : 0;
09978 return ON_Mesh_GetVidHelper( m_V.Count(), fV, dV, first_vid, Vid, Vindex );
09979 }
09980
09981
09982
09983
09984
09985
09986
09987
09988
09989
09990
09991
09992
09993
09994 int ON_Mesh_GetEidHelper(
09995 const int Vcount,
09996 const int Fcount,
09997 const ON_MeshFace* F,
09998 const int* Vid,
09999 ON_MeshFaceSide* Eid_list
10000 )
10001 {
10002
10003 const int* fvi;
10004 int i, Vid0;
10005 int Eid_count = 0;
10006 struct ON_MeshFaceSide Eid;
10007 memset(&Eid,0,sizeof(Eid));
10008
10009 if ( 0 == Vid )
10010 {
10011
10012 for ( Eid.fi = 0; Eid.fi < Fcount; Eid.fi++ )
10013 {
10014 fvi = F[Eid.fi].vi;
10015
10016
10017 if ( fvi[0] < 0 || fvi[0] >= Vcount )
10018 continue;
10019 if ( fvi[1] < 0 || fvi[1] >= Vcount )
10020 continue;
10021 if ( fvi[2] < 0 || fvi[2] >= Vcount )
10022 continue;
10023 if ( fvi[3] < 0 || fvi[3] >= Vcount )
10024 continue;
10025
10026 Eid.vi[0] = fvi[0];
10027 Vid0 = Eid.vi[1] = fvi[1];
10028 Eid.side = 0;
10029 if ( Eid.vi[0] < Eid.vi[1] )
10030 {
10031 Eid.dir = 0;
10032 Eid_list[Eid_count++] = Eid;
10033 }
10034 else if ( Eid.vi[0] > Eid.vi[1] )
10035 {
10036 i = Eid.vi[0]; Eid.vi[0] = Eid.vi[1]; Eid.vi[1] = i;
10037 Eid.dir = 1;
10038 Eid_list[Eid_count++] = Eid;
10039 }
10040
10041 Eid.vi[0] = Vid0;
10042 Vid0 = Eid.vi[1] = fvi[2];
10043 Eid.side = 1;
10044 if ( Eid.vi[0] < Eid.vi[1] )
10045 {
10046 Eid.dir = 0;
10047 Eid_list[Eid_count++] = Eid;
10048 }
10049 else if ( Eid.vi[0] > Eid.vi[1] )
10050 {
10051 i = Eid.vi[0]; Eid.vi[0] = Eid.vi[1]; Eid.vi[1] = i;
10052 Eid.dir = 1;
10053 Eid_list[Eid_count++] = Eid;
10054 }
10055
10056 if ( fvi[2] != fvi[3] )
10057 {
10058
10059 Eid.vi[0] = Vid0;
10060 Vid0 = Eid.vi[1] = fvi[3];
10061 Eid.side = 2;
10062 if ( Eid.vi[0] < Eid.vi[1] )
10063 {
10064 Eid.dir = 0;
10065 Eid_list[Eid_count++] = Eid;
10066 }
10067 else if ( Eid.vi[0] > Eid.vi[1] )
10068 {
10069 i = Eid.vi[0]; Eid.vi[0] = Eid.vi[1]; Eid.vi[1] = i;
10070 Eid.dir = 1;
10071 Eid_list[Eid_count++] = Eid;
10072 }
10073 }
10074
10075 Eid.vi[0] = Vid0;
10076 Eid.vi[1] = fvi[0];
10077 Eid.side = 3;
10078 if ( Eid.vi[0] < Eid.vi[1] )
10079 {
10080 Eid.dir = 0;
10081 Eid_list[Eid_count++] = Eid;
10082 }
10083 else if ( Eid.vi[0] > Eid.vi[1] )
10084 {
10085 i = Eid.vi[0]; Eid.vi[0] = Eid.vi[1]; Eid.vi[1] = i;
10086 Eid.dir = 1;
10087 Eid_list[Eid_count++] = Eid;
10088 }
10089 }
10090 }
10091 else
10092 {
10093
10094
10095 for ( Eid.fi = 0; Eid.fi < Fcount; Eid.fi++ )
10096 {
10097 fvi = F[Eid.fi].vi;
10098
10099
10100 if ( fvi[0] < 0 || fvi[0] >= Vcount )
10101 continue;
10102 if ( fvi[1] < 0 || fvi[1] >= Vcount )
10103 continue;
10104 if ( fvi[2] < 0 || fvi[2] >= Vcount )
10105 continue;
10106 if ( fvi[3] < 0 || fvi[3] >= Vcount )
10107 continue;
10108
10109 Eid.vi[0] = Vid[fvi[0]];
10110 Vid0 = Eid.vi[1] = Vid[fvi[1]];
10111 Eid.side = 0;
10112 if ( Eid.vi[0] < Eid.vi[1] )
10113 {
10114 Eid.dir = 0;
10115 Eid_list[Eid_count++] = Eid;
10116 }
10117 else if ( Eid.vi[0] > Eid.vi[1] )
10118 {
10119 i = Eid.vi[0]; Eid.vi[0] = Eid.vi[1]; Eid.vi[1] = i;
10120 Eid.dir = 1;
10121 Eid_list[Eid_count++] = Eid;
10122 }
10123
10124 Eid.vi[0] = Vid0;
10125 Vid0 = Eid.vi[1] = Vid[fvi[2]];
10126 Eid.side = 1;
10127 if ( Eid.vi[0] < Eid.vi[1] )
10128 {
10129 Eid.dir = 0;
10130 Eid_list[Eid_count++] = Eid;
10131 }
10132 else if ( Eid.vi[0] > Eid.vi[1] )
10133 {
10134 i = Eid.vi[0]; Eid.vi[0] = Eid.vi[1]; Eid.vi[1] = i;
10135 Eid.dir = 1;
10136 Eid_list[Eid_count++] = Eid;
10137 }
10138
10139 if ( fvi[2] != fvi[3] )
10140 {
10141
10142 Eid.vi[0] = Vid0;
10143 Vid0 = Eid.vi[1] = Vid[fvi[3]];
10144 Eid.side = 2;
10145 if ( Eid.vi[0] < Eid.vi[1] )
10146 {
10147 Eid.dir = 0;
10148 Eid_list[Eid_count++] = Eid;
10149 }
10150 else if ( Eid.vi[0] > Eid.vi[1] )
10151 {
10152 i = Eid.vi[0]; Eid.vi[0] = Eid.vi[1]; Eid.vi[1] = i;
10153 Eid.dir = 1;
10154 Eid_list[Eid_count++] = Eid;
10155 }
10156 }
10157
10158 Eid.vi[0] = Vid0;
10159 Eid.vi[1] = Vid[fvi[0]];
10160 Eid.side = 3;
10161 if ( Eid.vi[0] < Eid.vi[1] )
10162 {
10163 Eid.dir = 0;
10164 Eid_list[Eid_count++] = Eid;
10165 }
10166 else if ( Eid.vi[0] > Eid.vi[1] )
10167 {
10168 i = Eid.vi[0]; Eid.vi[0] = Eid.vi[1]; Eid.vi[1] = i;
10169 Eid.dir = 1;
10170 Eid_list[Eid_count++] = Eid;
10171 }
10172 }
10173 }
10174
10175 return Eid_count;
10176 }
10177
10178 int ON_Mesh::GetMeshFaceSideList(
10179 const int* Vid,
10180 struct ON_MeshFaceSide*& sides
10181 ) const
10182 {
10183 const int Vcount = m_V.Count();
10184 const int Fcount = m_F.Count();
10185 const ON_MeshFace* F = m_F.Array();
10186
10187 if ( Fcount < 1 || 0 == F || Vcount < 2 )
10188 return 0;
10189
10190 struct ON_MeshFaceSide* Elist = sides;
10191 if ( 0 == Elist )
10192 {
10193 Elist = (struct ON_MeshFaceSide*)onmalloc(4*Fcount*sizeof(Elist[0]));
10194 if ( 0 == Elist )
10195 return 0;
10196 }
10197
10198 int sides_count = ON_Mesh_GetEidHelper( Vcount, Fcount, F, Vid, Elist );
10199 if ( sides_count <= 0 )
10200 {
10201 if ( 0 == sides )
10202 delete(Elist);
10203 }
10204 else if ( 0 == sides )
10205 {
10206 sides = Elist;
10207 }
10208
10209 return sides_count;
10210 }
10211
10212 #define ON_COMPILING_OPENNURBS_QSORT_FUNCTIONS
10213 #define ON_SORT_TEMPLATE_STATIC_FUNCTION
10214 #define ON_SORT_TEMPLATE_TYPE struct ON_MeshFaceSide
10215
10216 #define ON_SORT_TEMPLATE_COMPARE ON_qsort_MeshFaceSide_compare
10217 static int ON_SORT_TEMPLATE_COMPARE(
10218 ON_SORT_TEMPLATE_TYPE const * side1,
10219 ON_SORT_TEMPLATE_TYPE const * side2
10220 )
10221 {
10222 if ( side1->vi[0] < side2->vi[0] )
10223 return -1;
10224 if ( side1->vi[0] > side2->vi[0] )
10225 return 1;
10226 if ( side1->vi[1] < side2->vi[1] )
10227 return -1;
10228 if ( side1->vi[1] > side2->vi[1] )
10229 return 1;
10230 if ( side1->fi < side2->fi )
10231 return -1;
10232 if ( side1->fi > side2->fi )
10233 return 1;
10234 if ( side1->side < side2->side )
10235 return -1;
10236 if ( side1->side > side2->side )
10237 return 1;
10238 return 0;
10239 }
10240
10241 #define ON_QSORT_FNAME ON_qsort_MeshFaceSide
10242 #include "pcl/surface/3rdparty/opennurbs/opennurbs_qsort_template.h"
10243
10244 void ON_SortMeshFaceSidesByVertexIndex( int sides_count, struct ON_MeshFaceSide* sides )
10245 {
10246 if ( sides_count >= 2 && 0 != sides )
10247 ON_QSORT_FNAME( sides, sides_count );
10248 }
10249
10250 #undef ON_COMPILING_OPENNURBS_QSORT_FUNCTIONS
10251 #undef ON_SORT_TEMPLATE_STATIC_FUNCTION
10252 #undef ON_SORT_TEMPLATE_TYPE
10253 #undef ON_QSORT_FNAME