1 /* $NoKeywords: $ */
2 /*
3 //
4 // Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved.
5 // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
6 // McNeel & Associates.
7 //
8 // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
9 // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
10 // MERCHANTABILITY ARE HEREBY DISCLAIMED.
11 //
12 // For complete openNURBS copyright information see <http://www.opennurbs.org>.
13 //
14 ////////////////////////////////////////////////////////////////
15 */
16 
17 #if !defined(OPENNURBS_MESH_INC_)
18 #define OPENNURBS_MESH_INC_
19 
20 ///////////////////////////////////////////////////////////////////////////////
21 //
22 // Class  ON_Mesh
23 //
24 class ON_CLASS ON_MeshParameters
25 {
26   // surface meshing perameters
27 public:
28 
29   enum MESH_STYLE
30   {
31     // All of these enum values must be in the range 0-255 because
32     // unsigned chars are use for storage in some locations.
33     unset_mesh_style      =   0,
34     render_mesh_fast      =   1, // Use ON_MeshParameters::FastRenderMesh
35     render_mesh_quality   =   2, // Use ON_MeshParameters::QualityRenderMesh
36     // 3 - 8 reserved for future predefined render mesh styles
37     render_mesh_custom    =   9,// Use ON_3dmSettings::m_CustomRenderMeshSettings
38     render_mesh_per_object = 10 // Use ON_Object::GetMeshParameters().
39   };
40 
41   /*
42   Description:
43     Parameters that create render meshes where meshing
44     speed is prefered over mesh quality.
45   */
46   static
47   const ON_MeshParameters FastRenderMesh;
48 
49   /*
50   Description:
51     Parameters that create render meshes where mesh quality
52     is prefered over meshing speed.
53   */
54   static
55   const ON_MeshParameters QualityRenderMesh;
56 
57   /*
58   Description:
59     Get a value to use for tolerance based on the relative_tolerance
60     and actual size.
61   Parameters:
62     relative_tolerance - [in]
63       See m_relative_tolerance field
64     actual_size - [in]
65       Diagonal ov object bounding box or some similar measure of
66       an object's 3d size.
67   Returns:
68     A value that can be used for m_tolerance if no
69     user specified value is available.
70   */
71   static
72   double Tolerance( double relative_tolerance, double actual_size );
73 
74   /*
75   Description:
76     Get a value to use for minimum edge length base on max_edge_length
77     and tolerance settings.
78   Parameters:
79     max_edge_length - [in]
80       3d maximum edge length used to create mesh.
81     tolerance - [in]
82       3d distance tolerance used to create mesh.
83   Returns:
84     A value that can be used for m_min_edge_length if no
85     user specified value is available.
86   */
87   static
88   double MinEdgeLength( double max_edge_length, double tolerance );
89 
90   ON_MeshParameters();
91   ~ON_MeshParameters();
92   // C++ default works fine // ON_MeshParameters(const ON_MeshParameters& );
93   // C++ default works fine // ON_MeshParameters& operator=(const ON_MeshParameters&);
94 
95   bool operator!=(const ON_MeshParameters&) const;
96   bool operator==(const ON_MeshParameters&) const;
97 
98   // compares with mesh's mesh parameters
99   bool operator==(const ON_Mesh&) const;
100   bool operator!=(const ON_Mesh&) const;
101 
102   void Dump( ON_TextLog& test_log ) const;
103 
104   void Default();
105 
106   /*
107   Description:
108     Tool for provding a simple slider interface.
109   Parameters:
110     density - [in] 0.0 <= density <= 1.0
111       0 quickly creates coarse meshes.
112       1 creates accurate meshes but takes lots of time.
113   */
114   void Set(
115     double density,
116     double min_edge_length = 0.0001
117     );
118 
119   /*
120   Description:
121     Sets the meshing parameters to ON_MeshParameters::FastRenderMesh.
122   */
123   ON_DEPRECATED
124   void JaggedAndFasterMeshParameters();
125 
126   /*
127   Description:
128     Sets the meshing parameters to ON_MeshParameters::QualityRenderMesh.
129   */
130   ON_DEPRECATED
131   void SmoothAndSlowerMeshParameters();
132 
133   /*
134   Description:
135     Sets the meshing parameters to create the default
136     analysis mesh.
137   */
138   void DefaultAnalysisMeshParameters();
139 
140   // Compare() ignores weld and curvature settings
141   // Ignores m_min_tolerance setting.
142   int Compare( const ON_MeshParameters& ) const;
143 
144   /*
145   Description:
146     Compares all meshing parameters that control mesh geometry.
147     Does not compare m_bCustomSettings, m_bComputeCurvature,
148     m_bDoublePrecision, m_min_tolerance, and m_texture_range.
149   */
150   int CompareGeometrySettings( const ON_MeshParameters& ) const;
151 
152 
153   bool Write( ON_BinaryArchive& ) const;
154   bool Read( ON_BinaryArchive& );
155   ON__UINT32 DataCRC(ON__UINT32) const;
156 
157 
158   // Meshing happens in two stages.  The first stage creates a
159   // rectangular grid.  The second stage refines the grid until
160   // the mesh meets all meshing requirements.  The third stage
161   // combines coincident vertices if the resulting mesh is a composite.
162 
163   bool m_bCustomSettings;    // false - if these settings were used to create
164                              //         a mesh and the app settings don't match,
165                              //         then remesh the object using the app
166                              //         settings.
167                              // true  - these settings are customized for a
168                              //         particular object - ignore app mesh
169                              //         settings.
170 
171   bool m_bComputeCurvature;  // false - (default) - ON_Mesh::m_K[] not computed
172                              // true  - ON_Mesh::m_K[] computed
173 
174   bool m_bSimplePlanes;      // false - (default) planar surfaces are meshed
175                              //          using the controls below.
176                              // true   - planar surfaces are meshed using
177                              //          minimal number of triangles and
178                              //          aspect/edge controls are ignored.
179 
180   bool m_bRefine;            // false - skip stage 2
181                              // true  - (default) do stage 2
182 
183   bool m_bJaggedSeams;       // false - (default) edges of meshes of joined
184                              //          b-rep faces match with no gaps or
185                              //          "T" joints.
186                              // true   - faces in b-reps are meshed independently.
187                              //          This is faster but results in gaps and
188                              //          "T" joints along seams between faces.
189 
190   bool m_bDoublePrecision;   // false - (default) the mesh vertices will be
191                              //         float precision values in the m_V[] array.
192                              // true -  The mesh vertices will be double precision
193                              //         values in the DoublePrecisionVertices()
194                              //         array.  Float precision values will also
195                              //         be returned in the m_V[] array.
196   bool m_bCustomSettingsEnabled; // false - if these settings should be ignored
197                              //         when used as per object custom render mesh
198                              //         settings.
199                              //  true - ignore these settings.
200   unsigned char m_mesher;    // 0 = slow mesher, 1 = fast mesher
201 
202   int m_texture_range;       // 1: normalized
203                              //
204                              //          each face has a normalized texture range
205                              //          [0,1]x[0,1].
206                              //
207                              // 2: packed normalized (default)
208                              //
209                              //          each face in a polysurface is assigned
210                              //          a texture range that is a subrectangle
211                              //          of [0,1]x[0,1].  The subrectangles are
212                              //          mutually disjoint and packed into
213                              //          into [0,1]x[0,1] in a way that minimizes
214                              //          distortion and maximizes the coverage
215                              //          of [0,1]x[0,1].  (This texture style
216                              //          is suitable for creating texture maps
217                              //          with popular 3D painting programs.)
218 
219 private:
220   unsigned int m_reserved2;
221 public:
222 
223   // These controls are used in both stages
224 
225   double m_tolerance; // maximum distance from center of edge to surface
226 
227 
228   double m_relative_tolerance; // If 0 < m_relative_tolerance < 1,
229   double m_min_tolerance;      // then the maximum distance from the
230                                // center of an edge to the surface will
231                                // be <= T, where T is the larger of
232                                // (m_min_tolerance,d*m_relative_tolerance),
233                                // where d is an esimate of the size of the
234                                // object being meshed.
235 
236 
237   double m_min_edge_length; // edges shorter than m_min_edge_length will
238                             // not be split even if the do not meet other
239                             // meshing requirements
240 
241   double m_max_edge_length; // edges longer than m_max_edge_length will
242                             // be split even when they meet all other
243                             // meshing requirements
244 
245   // These controls are used during stage 1 to generate the grid
246   double m_grid_aspect_ratio;  // desired aspect ratio of quads in grid
247                                // 0.0 = any aspect ratio is acceptable
248                                // values >0 and < sqrt(2) are treated as sqrt(2)
249   int    m_grid_min_count;     // minimum number of quads in initial grid
250   int    m_grid_max_count;     // desired masimum number of quads in initial grid
251   double m_grid_angle;         // (in radians) maximum angle between surface
252                                // normal evaluated at adjacent vertices.
253                                // 0.0 is treated as pi.
254   double m_grid_amplification; // The parameters above generate a grid.
255                                // If you want fewer quads, set m_grid_amplification
256                                // to a value < 1.  If you want more quads,
257                                // set m_grid_amplification to a value > 1.
258                                // default = 1 and values <= 0 are treated as 1.
259 
260   // These controls are used during stage 2 to refine the grid
261   double m_refine_angle;       // (in radians) maximum angle in radians between
262                                // surface normal evaluated at adjacent vertices.
263 
264   // These controls are used during stage 3
265   int     m_face_type;         // 0 = mixed triangle and quads
266                                // 1 = all triangles
267                                // 2 = all quads
268 private:
269   unsigned int m_reserved3;
270 };
271 
272 class ON_CLASS ON_MeshCurvatureStats
273 {
274 public:
275   ON_MeshCurvatureStats();
276   ~ON_MeshCurvatureStats();
277   ON_MeshCurvatureStats(const ON_MeshCurvatureStats& );
278   ON_MeshCurvatureStats& operator=(const ON_MeshCurvatureStats&);
279 
280   void Destroy();
281   void EmergencyDestroy();
282 
283   bool Set( ON::curvature_style,
284             int,           // Kcount,
285             const ON_SurfaceCurvature*, // K[]
286             const ON_3fVector*, // N[] surface normals needed for normal sectional curvatures
287             double = 0.0   // if > 0, value is used for "infinity"
288             );
289 
290   bool Write( ON_BinaryArchive& ) const;
291   bool Read( ON_BinaryArchive& );
292 
293   ON::curvature_style m_style;
294 
295   double m_infinity; // curvature values >= this are considered infinite
296                      // and not used to compute the m_average or m_adev
297   int    m_count_infinite; // number of "infinte" values
298   int    m_count;    // count of "finite" values
299   double m_mode;     // mode of "finite" values
300   double m_average;  // average of "finite" values
301   double m_adev;     // average deviation of "finite" values
302 
303   ON_Interval m_range;
304 };
305 
306 ///////////////////////////////////////////////////////////////////////////////
307 //
308 // Class  ON_MeshTopology
309 //
310 
311 struct ON_MeshTopologyVertex
312 {
313   // m_tope_count = number of topological edges that begin or
314   // end at this topological vertex.
315   int m_tope_count;
316 
317   // m_topei[] is an array of length m_tope_count with the indices
318   // of the topological edges that begin or end at this topological
319   // vertex.  Generally, these edges are listed in no particular
320   // order.  If you want the edges listed "radially", then call
321   // ON_MeshTopology::SortVertexEdges.
322   const int* m_topei;
323 
324   // m_v_count = number of ON_Mesh vertices that correspond to
325   // this topological vertex.
326   int m_v_count;
327 
328   // m_vi[] is an array of length m_v_count with the indices of the
329   // ON_Mesh vertices that correspond to this topological vertex.
330   const int* m_vi;
331 };
332 
333 struct ON_MeshTopologyEdge
334 {
335   // m_topvi[] = indices of the topological verteices where the
336   // edge begins and ends.
337   int m_topvi[2];
338 
339   // m_topf_count = number of topological faces tat share this topological edge
340   int m_topf_count;
341 
342   // m_topfi[] is an array of length m_topf_count with the indices of the
343   // topological faces that share this topological edge.
344   const int* m_topfi;
345 };
346 
347 struct ON_CLASS ON_MeshTopologyFace
348 {
349   /*
350     m_topei[] = indices of the topological edges that bound the face.
351     If m_topei[2] = m_topei[3], then the face is a triangle, otherwise
352     the face is a quad.
353 
354     NOTE WELL:
355       The topological edge with index m_topei[k] ENDS at the
356       vertex corresponding to ON_MeshFace.vi[k]. So, ...
357 
358       If the face is a quad, (ON_MeshFace.vi[2]!=ON_MeshFace.vi[3]),
359       the topological edge with index m_topei[0] STARTS at
360       ON_MeshFace.vi[3] and ENDS at ON_MeshFace.vi[0],
361       the topological edge with index m_topei[1] STARTS at
362       ON_MeshFace.vi[0] and ENDS at ON_MeshFace.vi[1],
363       the topological edge with index m_topei[2] STARTS at
364       ON_MeshFace.vi[1] and ENDS at ON_MeshFace.vi[2], and
365       the topological edge with index m_topei[3] STARTS at
366       ON_MeshFace.vi[0] and ENDS at ON_MeshFace.vi[1],
367 
368       If the face is a triangle, (ON_MeshFace.vi[2]==ON_MeshFace.vi[3]),
369       the topological edge with index m_topei[0] STARTS at
370       ON_MeshFace.vi[2] and ENDS at ON_MeshFace.vi[0],
371       the topological edge with index m_topei[1] STARTS at
372       ON_MeshFace.vi[0] and ENDS at ON_MeshFace.vi[1],
373       the topological edge with index m_topei[2] STARTS at
374       ON_MeshFace.vi[1] and ENDS at ON_MeshFace.vi[2].
375   */
376   int m_topei[4];
377 
378   /*
379     If m_reve[i] is 0, then the orientation of the edge matches the
380     orientation of the face.  If m_reve[i] is 1, then the orientation
381     of the edge is opposite that of the face.
382   */
383   char m_reve[4];
384 
385   /*
386   Description:
387     A topological mesh face is a valid triangle if m_topei[0],
388     m_topei[1], m_topei[2] are distinct edges and
389     m_topei[3]=m_topei[2].
390   Returns:
391     True if face is a triangle.
392   */
393   bool IsTriangle() const;
394 
395   /*
396   Description:
397     A topological mesh face is a valid quad if m_topei[0],
398     m_topei[1], m_topei[2], and m_topei[3] are distinct edges.
399   Returns:
400     True if face is a quad.
401   */
402   bool IsQuad() const;
403 
404   /*
405   Description:
406     A topological mesh face is valid if m_topei[0], m_topei[1],
407     and m_topei[2] are mutually distinct, and m_topei[3] is
408     either equal to m_topei[2] or mutually distinct from the
409     first three indices.
410   Returns:
411     True if face is valid.
412   */
413   bool IsValid( ) const;
414 };
415 
416 class ON_CLASS ON_MeshFace
417 {
418 public:
419   int vi[4]; // vertex index - vi[2]==vi[3] for tirangles
420 
421   /*
422   Returns:
423     True if vi[2] == vi[3];
424   Remarks:
425     Assumes the face is valid.
426   */
427   bool IsTriangle() const;
428 
429   /*
430   Returns:
431     True if vi[2] != vi[3];
432   Remarks:
433     Assumes the face is valid.
434   */
435   bool IsQuad() const;
436 
437   /*
438   Description:
439     Determine if a face is valid by checking that the vertices
440     are distinct.
441   Parameters:
442     mesh_vertex_count - [in]
443       number of vertices in the mesh
444     V - [in]
445       optional array of mesh_vertex_count vertex locations.
446   Returns:
447     true
448       The face is valid.
449     false
450       The face is not valid. It may be possible to repair the
451       face by calling ON_MeshFace::Repair().
452   */
453   bool IsValid(
454         int mesh_vertex_count
455         ) const;
456   bool IsValid(
457         int mesh_vertex_count,
458         const ON_3fPoint* V
459         ) const;
460   bool IsValid(
461         int mesh_vertex_count,
462         const ON_3dPoint* V
463         ) const;
464 
465   /*
466   Description:
467     Reverses the order of the vertices in v[].
468     vi[0] is not changed.
469   */
470   void Flip();
471 
472   /*
473   Description:
474     If IsValid() returns false, then you can use Repair()
475     to attempt to create a valid triangle.
476   Parameters:
477     mesh_vertex_count - [in]
478       number of vertices in the mesh
479     V - [in]
480       optional array of mesh_vertex_count vertex locations.
481   Returns:
482     true
483      repair was successful and v[0], v[1], vi[2] have distinct valid
484      values and v[2] == v[3].
485     false
486      this face's vi[] values cannot be repaired
487   */
488   bool Repair(
489         int mesh_vertex_count
490         );
491   bool Repair(
492         int mesh_vertex_count,
493         const ON_3fPoint* V
494         );
495   bool Repair(
496         int mesh_vertex_count,
497         const ON_3dPoint* V
498         );
499 
500   /*
501   Description:
502     Compute the face normal
503   Parameters:
504     dV - [in] double precision vertex array for the mesh
505     fV - [in] float precision vertex array for the mesh
506     FN - [out] face normal
507   Returns:
508     true if FN is valid.
509   */
510   bool ComputeFaceNormal( const ON_3dPoint* dV, ON_3dVector& FN ) const;
511   bool ComputeFaceNormal( const ON_3fPoint* fV, ON_3dVector& FN ) const;
512 };
513 
514 struct ON_MeshFaceSide
515 {
516   int vi[2]; // vertex indices
517   int fi;    // mesh m_F[] array face index
518   unsigned char  side;  // edge connects mesh m_V[m_F[fi].vi[side]] and m_V[m_F[fi].vi[(side+1)%4]]
519   unsigned char  dir;   // 0 = counterclockwise, 1 = clockwise (reversed)
520   unsigned short value; // Set to zero by ON_Mesh::GetFaceSideList(). Can be used as needed.
521 };
522 
523 
524 /*
525 Description:
526   Sort the sides[] array of ON_MeshFaceSide structs in dictionary
527   order by "vi[0]", "vi[1]", "fi", and "side" values.
528 Paramters:
529   sides_count - [in]
530     number of elements in the sides[] array.
531   sides - [in/out]
532 Remarks:
533   The function is thread safe.
534 */
535 ON_DECL
536 void ON_SortMeshFaceSidesByVertexIndex(
537         int sides_count,
538         struct ON_MeshFaceSide* sides
539         );
540 
541 struct ON_MeshPart
542 {
543   // ON_Mesh faces with indices fi[0] <= i < fi[1] reference
544   // vertices with indices vi[0] <= j < vi[1].
545   int vi[2]; // subinterval of mesh m_V[] array
546   int fi[2]; // subinterval of mesh m_F[] array
547   int vertex_count;   // = vi[1] - vi[0];
548   int triangle_count; // tris + 2*quads >= fi[1] - fi[0]
549 };
550 
551 #if defined(ON_DLL_TEMPLATE)
552 // This stuff is here because of a limitation in the way Microsoft
553 // handles templates and DLLs.  See Microsoft's knowledge base
554 // article ID Q168958 for details.
555 #pragma warning( push )
556 #pragma warning( disable : 4231 )
557 ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray<ON_MeshFace>;
558 ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray<ON_MeshTopologyVertex>;
559 ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray<ON_MeshTopologyEdge>;
560 ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray<ON_MeshTopologyFace>;
561 ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray<struct ON_MeshPart>;
562 #pragma warning( pop )
563 #endif
564 
565 class ON_CLASS ON_MeshTopology
566 {
567   // A mesh topology class is always associated with an ON_Mesh
568   // and can be retrieved by calling ON_Mesh::Topology()
569 public:
570   ON_MeshTopology();
571   ~ON_MeshTopology();
572 
573   bool IsValid() const;
574 
575   void Dump( ON_TextLog& ) const;
576 
577   //////////
578   // The parent ON_Mesh geometry used to compute this mesh topology.
579   const ON_Mesh* m_mesh;
580 
581   //////////
582   // number of topoligical vertices (<= m_mesh.VertexCount())
583   int TopVertexCount() const;
584 
585   //////////
586   // number of topoligical edges
587   int TopEdgeCount() const;
588 
589   //////////
590   // number of topoligical faces (same as m_mesh.FaceCount())
591   int TopFaceCount() const;
592 
593   /*
594   Description:
595     Get a vertex reference to a mesh vertex index.
596   Parameters:
597     ci - [in] component index with type mesh_vertex or meshtop_vertex.
598   Returns:
599     a reference to the vertex
600   */
601   class ON_MeshVertexRef VertexRef(ON_COMPONENT_INDEX ci) const;
602 
603   class ON_MeshVertexRef VertexRef(int topv_index) const;
604 
605   /*
606   Description:
607     Get an edge reference.
608   Parameters:
609     ci - [in] component index with type meshtop_edge.
610   Returns:
611     a reference to the edge
612   */
613   class ON_MeshEdgeRef EdgeRef(ON_COMPONENT_INDEX ci) const;
614 
615   class ON_MeshEdgeRef EdgeRef(int tope_index) const;
616 
617   /*
618   Description:
619     Get a face reference from a mesh face index.
620   Parameters:
621     ci - [in] component index with type mesh_face.
622   Returns:
623     a reference to the face.
624   Remarks:
625     The OM_Mesh.m_F[] and ON_MeshTopology.m_topf[] arrays
626     are parallel arrays; corresponding faces have identical
627     indices.
628   */
629   class ON_MeshFaceRef FaceRef(ON_COMPONENT_INDEX ci) const;
630 
631   class ON_MeshFaceRef FaceRef(int topf_index) const;
632 
633 
634   /*
635   Description:
636     Get the 3d point location of a vertex.
637   Parameters:
638     topv_index - [in];
639   Returns:
640     Location of vertex.
641   */
642   ON_3fPoint TopVertexPoint(
643     int topv_index
644     ) const;
645 
646   /*
647   Description:
648     Get the 3d line along an edge.
649   Parameters:
650     tope_index - [in];
651   Returns:
652     Line along edge.  If input is not valid,
653     the line.from and to are ON_UNSET_POINT
654   */
655   ON_Line TopEdgeLine(
656     int tope_index
657     ) const;
658 
659   ////////
660   // returns index of edge that connects topological vertices
661   // returns -1 if no edge is found.
662   int TopEdge(
663     int vtopi0,
664     int vtopi1 // ON_MeshTopology vertex topology indices
665     ) const;
666 
667   ////////
668   // returns ON_MeshTopology vertex topology index of a face
669   // corner.  The face is triangle iv TopFaceVertex(2) = TopFaceVertex(3)
670   bool GetTopFaceVertices(
671     int topfi,    // ON_MeshTopology face topology index (= ON_Mesh face index)
672     int topvi[4]  // ON_MeshTopology vertex indices returned here
673     ) const;
674 
675   /*
676   Description:
677     Sort the m_topei[] list of a mesh topology vertex so that
678     the edges are in radial order.  The "const" is a white
679     lie to make this function easier to call.
680   Parameter:
681     topvi - [in] index of vertex in m_topv[] array.
682   Remarks:
683     A nonmanifold edge is treated as a boundary edge with respect
684     to sorting.  If any boundary or nonmanifold edges end at the
685     vertex, then the first edge will be a boundary or nonmanifold
686     edge.
687   */
688   bool SortVertexEdges( int topvi ) const;
689 
690   /*
691   Description:
692     Sort the m_topei[] list of every mesh topology vertex so
693     that the edges are in radial order.  The "const" is a white
694     lie to make this function easier to call.
695   Remarks:
696     Same as
697     for ( int topvi = 0; topvi < m_topv.Count(); topvi++ )
698       SortVertexEdges(topvi);
699   */
700   bool SortVertexEdges() const;
701 
702   /*
703   Description:
704     Returns true if the topological vertex is hidden.
705   Parameters:
706     topvi - [in] mesh topology vertex index.
707   Returns:
708     True if mesh topology vertex is hidden.
709   Remarks:
710     The mesh topology vertex is hidden if and only if
711     all the ON_Mesh vertices it represents is hidden.
712   */
713   bool TopVertexIsHidden( int topvi ) const;
714 
715   /*
716   Description:
717     Returns true if the topological edge is hidden.
718   Parameters:
719     topei - [in] mesh topology edge index.
720   Returns:
721     True if mesh topology edge is hidden.
722   Remarks:
723     The mesh topology edge is hidden if and only if
724     either of its mesh topology vertices is hidden.
725   */
726   bool TopEdgeIsHidden( int topei ) const;
727 
728   /*
729   Description:
730     Returns true if the topological face is hidden.
731   Parameters:
732     topfi - [in] mesh topology face index.
733   Returns:
734     True if mesh topology face is hidden.
735   Remarks:
736     The mesh topology face is hidden if and only if
737     any of its mesh topology edges are hidden.
738   */
739   bool TopFaceIsHidden( int topfi ) const;
740 
741   //////////
742   // m_topv_map[] has length m_mesh.VertexCount() and
743   // m_topv[m_topv_map[vi]] is the topological mesh vertex that is assocated
744   // the with the mesh vertex m_mesh.m_V[vi].
745   ON_SimpleArray<int> m_topv_map;
746 
747   ////////////
748   // Array of topological mesh vertices.  See the comments in the definition
749   // of ON_MeshTopologyVertex for details.
750   ON_SimpleArray<ON_MeshTopologyVertex> m_topv;
751 
752   ////////////
753   // Array of topological mesh edges.  See the comments in the definition
754   // of ON_MeshTopologyEdge for details.
755   ON_SimpleArray<ON_MeshTopologyEdge> m_tope;
756 
757   ////////////
758   // Array of topological mesh faces.  The topological face
759   // m_topf[fi] corresponds to the mesh face ON_Mesh.m_F[fi].
760   // See the comments in the definition of ON_MeshTopologyFace
761   // for details. To get the indices of the mesh topology
762   // vertices at the face corners use
763   // topvi = m_topv_map[m_mesh.m_F[fi].vi[n]]
764   ON_SimpleArray<ON_MeshTopologyFace> m_topf;
765 
766   /*
767   Description:
768     Expert user function for efficiently getting the
769     integer arrays used by the ON_MeshTopologyVertex
770     and ON_MeshTopologyEdge classes.
771   Parameters:
772     count - [in] number of integers in array
773   Returns:
774     pointer to integer array.  The array memory
775     will be freed by ~ON_MeshTopology()
776   */
777   int* GetIntArray(int count);
778 
779 private:
780   friend class ON_Mesh;
781 
782   bool Create();
783   void Destroy();
784   void EmergencyDestroy();
785 
786   // efficient workspaces for
787   struct memchunk
788   {
789     struct memchunk* next;
790   } *m_memchunk;
791 
792   // NOTE: this field is a bool with valid values of 0 and 1.
793   volatile int m_b32IsValid; // sizeof(m_bIsValid) must be 4 - it is used in sleep locks.
794                     //    0: Not Valid
795                     //    1: Valid
796                     //   -1: Sleep locked - ON_Mesh::Topology() calculation is in progress
797   int WaitUntilReady(int sleep_value) const; // waits until m_b32IsValid >= 0
798 
799 private:
800   // no implementation
801   ON_MeshTopology(const ON_MeshTopology&);
802   ON_MeshTopology& operator=(const ON_MeshTopology&);
803 };
804 
805 struct ON_MeshNgon
806 {
807   // Number of N-gon corners (N >= 3)
808   int N;
809 
810   // N-gon vertex indices
811   // An array of N indices into the mesh's m_V[] vertex array.
812   // If the ON_MeshNgon is returned by the ON_MeshNgonList::AddNgon()
813   // function, then the memory for vi is managed by the ON_MeshNgonList
814   // class.
815   int* vi;
816 
817   // N-gon face indices
818   // An array of N indices into the mesh's m_F[] face array.
819   // Often, only N-2 indices are used. Unused indices are set to -1.
820   // If the ON_MeshNgon is returned by the ON_MeshNgonList::AddNgon()
821   // function, then the memory for fi is managed by the ON_MeshNgonList
822   // class.
823   int* fi;
824 };
825 
826 class ON_CLASS ON_MeshNgonList
827 {
828 public:
829   ON_MeshNgonList();
830   ~ON_MeshNgonList();
831   ON_MeshNgonList(const ON_MeshNgonList&);
832   ON_MeshNgonList& operator=(const ON_MeshNgonList&);
833 
834 
835   /*
836   Description:
837     Add an N-gon to the list
838   Parameters:
839     N - [in] number of vertices ( >= 5)
840     vi - [in] array of N vertex indices into the mesh's m_V[] array.
841     fi - [in] array of N face indices into the mesh's m_F[] array.
842               Unused indices are set to -1.  In many cases
843               there are N-2 valid indices and these are triangles.
844   Remarks:
845     Adding an N-gon may invalidate any pointers previously
846     returned by Ngon.
847   */
848   bool AddNgon(int N, const int* vi, const int* fi);
849   struct ON_MeshNgon* AddNgon(int N);
850 
851   /*
852   Returns:
853     Number of Ngons
854   */
855   int NgonCount() const;
856 
857   /*
858   Parameters:
859     Ngon_index - [in] zero based index
860   Returns:
861     NULL or a pointer to the Ngon
862   */
863   ON_MeshNgon* Ngon(int Ngon_index) const;
864 
865   /*
866   Description:
867     If you know about how many ngons you will need,
868     then use the function to reserve space for them.
869   */
870   bool ReserveNgonCapacity(int capacity);
871 
872   /*
873   Description:
874     Destroy N-gon list
875   */
876   void Destroy();
877 
878   /*
879   Returns:
880     Approximate number of bytes used by this class.
881   */
882   unsigned int SizeOf() const;
883 
884 private:
885   int m_ngons_count;
886   int m_ngons_capacity;
887   ON_MeshNgon* m_ngons;
888   struct ON_NGON_MEMBLK* m_memblk_list;
889 };
890 
891 class ON_CLASS ON_MeshPartition
892 {
893 public:
894   ON_MeshPartition();
895   ~ON_MeshPartition();
896 
897   // maximum number of vertices in a partition
898   int m_partition_max_vertex_count;
899   // maximum number of triangles in a partition (quads count as 2 triangles)
900   int m_partition_max_triangle_count;
901 
902   // Partition i uses
903   // vertices m_V[j] where
904   //
905   //   m_part[i].vi[0] <= j < m_part[i].vi[1]
906   //
907   // and uses faces m_F[k] where
908   //
909   //    m_part[i].fi[0] <= k < m_part[i].fi[1]
910   ON_SimpleArray<struct ON_MeshPart> m_part;
911 };
912 
913 
914 
915 class ON_CLASS ON_MappingTag
916 {
917 public:
918   ON_MappingTag();
919   void Default();
920   bool Write(ON_BinaryArchive&) const;
921   bool Read(ON_BinaryArchive&);
922   void Dump( ON_TextLog& ) const;
923   void Transform( const ON_Xform& xform );
924   void Set(const ON_TextureMapping& mapping);
925 
926   /*
927   Description:
928     Sets the tag to the value the meshes have that
929     come out of ON_Brep::CreateMesh().
930   */
931   void SetDefaultSurfaceParameterMappingTag();
932 
933   int Compare( const ON_MappingTag& other,
934                bool bCompareId = true,
935                bool bCompareCRC = true,
936                bool bCompareXform = true
937                ) const;
938 
939   /*
940   Returns:
941     True if the mapping tag is set.
942   */
943   bool IsSet() const;
944 
945   /*
946   Returns:
947     True if the mapping tag is for a mapping with
948     type ON_TextureMapping::srfp_mapping with
949     m_uvw = identity.
950   */
951   bool IsDefaultSurfaceParameterMapping() const;
952 
953   // Identifies the mapping used to create the texture
954   // coordinates and records transformations applied
955   // to the mesh after the texture coordinates were
956   // calculated.  If the texture mapping does not
957   // change when the mesh is transformed, then set
958   // m_mesh_xform to zero so that compares will work right.
959   //
960   //
961   ON_UUID                 m_mapping_id;   // ON_TextureMapping::m_mapping_id
962   ON_TextureMapping::TYPE m_mapping_type; // ON_TextureMapping::m_type
963   ON__UINT32              m_mapping_crc;  // ON_TextureMapping::MappingCRC()
964   ON_Xform                m_mesh_xform;
965 };
966 
967 class ON_CLASS ON_TextureCoordinates
968 {
969 public:
970   ON_TextureCoordinates();
971 
972   ON_MappingTag   m_tag;
973   int                        m_dim; // 1, 2, or 3
974   ON_SimpleArray<ON_3fPoint> m_T;   // texture coordinates
975 };
976 
977 
978 #if defined(ON_DLL_TEMPLATE)
979 // This stuff is here because of a limitation in the way Microsoft
980 // handles templates and DLLs.  See Microsoft's knowledge base
981 // article ID Q168958 for details.
982 #pragma warning( push )
983 #pragma warning( disable : 4231 )
984 ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray<ON_MappingTag>;
985 ON_DLL_TEMPLATE template class ON_CLASS ON_ClassArray<ON_TextureCoordinates>;
986 #pragma warning( pop )
987 #endif
988 
989 class ON_CLASS ON_Mesh : public ON_Geometry
990 {
991   ON_OBJECT_DECLARE(ON_Mesh);
992 public:
993   ON_Mesh();
994   ON_Mesh(
995     int   initial_face_array_capacity,   // initial face array capacity
996     int   initial_vertex_array_capacity, // initial vertex array capacity
997     bool  has_vertex_normals,            // true if mesh has vertex normals
998     bool  has_texture_coordinates        // true if mesh has texture coordinates
999     );
1000   ON_Mesh( const ON_Mesh& );
1001   ON_Mesh& operator=( const ON_Mesh& );
1002   ~ON_Mesh();
1003 
1004   // Override of virtual ON_Object::MemoryRelocate
1005   void MemoryRelocate();
1006 
1007   // virtual ON_Object::DestroyRuntimeCache override
1008   void DestroyRuntimeCache( bool bDelete = true );
1009 
1010   void Destroy();
1011   void EmergencyDestroy(); // Call only when memory used by this class's
1012                            // members will soon become invalid for reasons
1013                            // beyond your control. EmergencyDestroy() zeros
1014                            // anything that could possibly cause
1015                            // ~ON_Mesh() to crash.  Calling
1016                            // EmergencyDestroy() under normal conditions
1017                            // will result in ~ON_Mesh() leaking
1018                            // memory.
1019 
1020   void DestroyTree( bool bDeleteTree = true );
1021 
1022   /////////////////////////////////////////////////////////////////
1023   // ON_Object overrides
1024 
1025   // virtual ON_Object::SizeOf override
1026   unsigned int SizeOf() const;
1027 
1028   // virtual ON_Object::DataCRC override
1029   ON__UINT32 DataCRC(ON__UINT32 current_remainder) const;
1030 
1031   /*
1032   Description:
1033     Tests an object to see if its data members are correctly
1034     initialized.
1035   Parameters:
1036     text_log - [in] if the object is not valid and text_log
1037         is not NULL, then a brief englis description of the
1038         reason the object is not valid is appened to the log.
1039         The information appended to text_log is suitable for
1040         low-level debugging purposes by programmers and is
1041         not intended to be useful as a high level user
1042         interface tool.
1043   Returns:
1044     @untitled table
1045     true     object is valid
1046     false    object is invalid, uninitialized, etc.
1047   Remarks:
1048     Overrides virtual ON_Object::IsValid
1049   */
1050   ON_BOOL32 IsValid( ON_TextLog* text_log = NULL ) const;
1051 
1052   void Dump( ON_TextLog& ) const; // for debugging
1053 
1054   ON_BOOL32 Write( ON_BinaryArchive& ) const;
1055 
1056   ON_BOOL32 Read( ON_BinaryArchive& );
1057 
1058   ON::object_type ObjectType() const;
1059 
1060   /////////////////////////////////////////////////////////////////
1061   // ON_Geometry overrides
1062 
1063   int Dimension() const;
1064 
1065   ON_BOOL32 GetBBox( // returns true if successful
1066          double*,    // minimum
1067          double*,    // maximum
1068          ON_BOOL32 = false  // true means grow box
1069          ) const;
1070 
1071   /*
1072 	Description:
1073     Get tight bounding box of the mesh.
1074 	Parameters:
1075 		tight_bbox - [in/out] tight bounding box
1076 		bGrowBox -[in]	(default=false)
1077       If true and the input tight_bbox is valid, then returned
1078       tight_bbox is the union of the input tight_bbox and the
1079       mesh's tight bounding box.
1080 		xform -[in] (default=NULL)
1081       If not NULL, the tight bounding box of the transformed
1082       mesh is calculated.  The mesh is not modified.
1083 	Returns:
1084     True if the returned tight_bbox is set to a valid
1085     bounding box.
1086   */
1087 	bool GetTightBoundingBox(
1088 			ON_BoundingBox& tight_bbox,
1089       int bGrowBox = false,
1090 			const ON_Xform* xform = 0
1091       ) const;
1092 
1093   ON_BOOL32 Transform(
1094          const ON_Xform&
1095          );
1096 
1097   // virtual ON_Geometry::IsDeformable() override
1098   bool IsDeformable() const;
1099 
1100   // virtual ON_Geometry::MakeDeformable() override
1101   bool MakeDeformable();
1102 
1103   ON_BOOL32 SwapCoordinates(
1104         int, int        // indices of coords to swap
1105         );
1106 
1107   // virtual ON_Geometry override
1108   bool EvaluatePoint( const class ON_ObjRef& objref, ON_3dPoint& P ) const;
1109 
1110 
1111   /////////////////////////////////////////////////////////////////
1112   // Interface
1113   //
1114 
1115   // creation
1116   bool SetVertex(
1117          int,              // vertex index
1118          const ON_3dPoint& // vertex location
1119          );
1120   bool SetVertex(
1121          int,              // vertex index
1122          const ON_3fPoint& // vertex location
1123          );
1124   bool SetVertexNormal(
1125          int,               // vertex index
1126          const ON_3dVector& // unit normal
1127          );
1128   bool SetVertexNormal(
1129          int,               // vertex index
1130          const ON_3fVector& // unit normal
1131          );
1132   bool SetTextureCoord(
1133          int,               // vertex index
1134          double, double     // texture coordinates
1135          );
1136   bool SetTriangle(
1137          int, // face index
1138          int,int,int // vertex indices
1139          );
1140   bool SetQuad(
1141          int, // face index
1142          int,int,int,int // vertex indices
1143          );
1144 
1145   /*
1146   Description:
1147     Get a vertex reference to a mesh vertex index.
1148   Parameters:
1149     ci - [in] component index with type mesh_vertex or meshtop_vertex.
1150   Returns:
1151     a reference to the vertex
1152   */
1153   ON_MeshVertexRef VertexRef(ON_COMPONENT_INDEX ci) const;
1154 
1155   ON_MeshVertexRef VertexRef(int mesh_V_index) const;
1156 
1157   /*
1158   Description:
1159     Get an edge reference from a mesh topology edge index.
1160   Parameters:
1161     ci - [in] component index with type meshtop_edge
1162   Returns:
1163     a reference to the edge
1164   */
1165   ON_MeshEdgeRef EdgeRef(ON_COMPONENT_INDEX ci) const;
1166 
1167   ON_MeshEdgeRef EdgeRef(int tope_index) const;
1168 
1169   /*
1170   Description:
1171     Get a face reference from a mesh face index.
1172   Parameters:
1173     ci - [in] component index with type mesh_face.
1174   Returns:
1175     a reference to the face
1176   */
1177   ON_MeshFaceRef FaceRef(ON_COMPONENT_INDEX ci) const;
1178 
1179   ON_MeshFaceRef FaceRef(int mesh_F_index) const;
1180 
1181   /*
1182   Parameters:
1183    ci - [in] a component index with type mesh_vertex, meshtop_vertex,
1184              meshtop_edge, or mesh_face.
1185   Returns:
1186     A pointer to an ON_MeshVertexRef, ON_MeshEdgeRef, or ON_MeshFaceRef.
1187     The caller must delete the returned object when it is no longer
1188     needed.
1189   See Also:
1190     ON_Mesh::VertexRef
1191     ON_Mesh::EdgeRef
1192     ON_Mesh::FaceRef
1193   */
1194   ON_Geometry* MeshComponent(
1195       ON_COMPONENT_INDEX ci
1196       ) const;
1197 
1198   // query
1199   int VertexCount() const;
1200   int FaceCount() const;
1201   int QuadCount() const; // number of faces that are quads
1202   int TriangleCount() const; // number of faces that are triangles
1203   int InvalidFaceCount() const; // number of face that have invalid m_vi[] values.
1204   bool HasVertexNormals() const; // normals at vertices
1205   bool HasFaceNormals() const;
1206   bool HasTextureCoordinates() const;
1207   bool HasSurfaceParameters() const;
1208   bool HasPrincipalCurvatures() const;
1209   bool HasVertexColors() const;
1210 
1211   /*
1212   Returns:
1213     Number of vertices that are hidden.
1214   */
1215   int HiddenVertexCount() const;
1216 
1217   bool GetCurvatureStats(
1218          ON::curvature_style,
1219          ON_MeshCurvatureStats&
1220          ) const;
1221 
1222   void InvalidateVertexBoundingBox(); // Call if defining geometry is changed by
1223                              // directly manipulating the m_V[] array.
1224   void InvalidateVertexNormalBoundingBox(); // Call if defining geometry is changed by
1225                              // directly manipulating the m_N[] array.
1226   void InvalidateTextureCoordinateBoundingBox(); // Call if defining geometry is changed by
1227                              // directly manipulating the m_T[] array.
1228   void InvalidateCurvatureStats(); // Call if defining geometry is changed by
1229                              // directly manipulating the m_T[] array.
1230   void InvalidateBoundingBoxes(); // Invalidates all cached bounding box information.
1231 
1232 
1233   void Flip(); // reverses face orientations and flips vertex and face normals
1234 
1235   void FlipVertexNormals(); // reverses vertex normals
1236   void FlipFaceNormals(); // reverses face normals
1237   void FlipFaceOrientation(); // reverses face orientation (does nothing to normals)
1238 
1239   void SetMeshParameters( const ON_MeshParameters& );
1240   const ON_MeshParameters* MeshParameters() const;
1241   void DeleteMeshParameters();
1242 
1243 
1244   bool UnitizeVertexNormals();
1245   bool UnitizeFaceNormals();
1246   bool CountQuads();
1247 
1248   /*
1249   Description:
1250     Splits all quads along the short diagonal.
1251   */
1252   bool ConvertQuadsToTriangles();
1253 
1254   /*
1255   Description:
1256     Joins adjacent triangles into quads if the resulting quad
1257     is nice.
1258   Parameters:
1259     angle_tol_radians - [in] Used to compare adjacent
1260       triangles' face normals.  For two triangles to be considered,
1261       the angle between their face normals has to be <= angle_tol_radians.
1262       When in doubt use ON_PI/90.0 (2 degrees).
1263     min_diagonal_length_ratio - [in] ( <= 1.0) For two triangles to be
1264        considered the ratio of the resulting quad's diagonals
1265        (length of the shortest diagonal)/(length of longest diagonal).
1266        has to be >= min_diagonal_length_ratio.
1267        When in doubt us .875.
1268   */
1269   bool ConvertTrianglesToQuads(
1270     double angle_tol_radians,
1271     double min_diagonal_length_ratio
1272     );
1273 
1274   bool ComputeFaceNormals();   // compute face normals for all faces
1275   bool ComputeFaceNormal(int); // computes face normal of indexed face
1276 
1277   /*
1278   Description:
1279     Get a list of pairs of faces that clash.
1280   Parameters:
1281     max_pair_count - [in]
1282       If max_pair_count > 0, then at most this many pairs
1283       will be appended to the clashing_pairs[] array.
1284       If max_pair_count <= 0, then all clashing pairs
1285       will be appended to the clashing_pairs[] array.
1286     clashing_pairs - [out]
1287       The faces indices of clashing pairs are appended
1288       to this array.
1289   Returns:
1290     Number of pairs appended to clashing_pairs[].
1291   */
1292   int GetClashingFacePairs(
1293     int max_pair_count,
1294     ON_SimpleArray< ON_2dex >& clashing_pairs
1295     ) const;
1296 
1297   /*
1298   Description:
1299     Cull clashing faces from the mesh.
1300   Parameters:
1301     what_to_cull - [in]
1302       0: when a pair of faces clash, cull both faces
1303       1: when a pair of faces clash, leave the face with the
1304          longest edge.
1305       2: when a pair of faces clash, cull the face with the
1306          longest edge.
1307       3: when a pair of faces clash, leave the face with
1308          the largest area.
1309       4: when a pair of faces clash, cull the face with
1310          the largest area.
1311   Returns:
1312     Number of faces culled from the mesh.
1313   Remarks:
1314     If a large face clashes with many small faces, the large
1315     face and one small face will be removed.  When a degenerate
1316     face is encountered, it is also culled.
1317   */
1318   int CullClashingFaces( int what_to_cull );
1319 
1320   int CullDegenerateFaces(); // returns number of degenerate faces
1321 
1322   int CullUnusedVertices(); // returns number of culled vertices
1323 
1324   // Description:
1325   //   Removes any unreferenced objects from arrays, reindexes as needed,
1326   //   and shrinks arrays to minimum required size.
1327   bool Compact();
1328 
1329   bool ComputeVertexNormals();    // uses face normals to cook up a vertex normal
1330 
1331   //////////
1332   // Scales textures so the texture domains are [0,1] and
1333   // eliminates any texture rotations.
1334   bool NormalizeTextureCoordinates();
1335 
1336 	/////////
1337 	// Description:
1338 	//		Transposes the texture coordinates
1339 	//  Returns
1340 	//			true  -  success
1341 	bool TransposeTextureCoordinates();
1342 	bool TransposeSurfaceParameters();
1343 
1344 	/////////
1345 	// Description:
1346 	//		Reverse one coordinate direction of the texture coordinates, within texture domain m_tex_domain
1347 	//	Parameters:
1348 	//		dir  -[in]	-   dir=0  first texture coordinate is reversed
1349 	//									  dir=1 second texture coordinate is reversed
1350 	//  Returns
1351 	//			true  -  success
1352 	bool ReverseTextureCoordinates( int dir );
1353 	bool ReverseSurfaceParameters( int dir );
1354 
1355 
1356 
1357   /*
1358   Description:
1359     Use a texture mapping function to set the m_T[] values.
1360   Parameters:
1361     mapping - [in]
1362     mesh_xform - [in]
1363       If not NULL, the mapping calculation is performed as
1364       if the mesh were transformed by mesh_xform; the
1365       location of the mesh is not changed.
1366     bLazy - [in]
1367       If true and the m_T[] values were set using the same
1368       mapping parameters, then no calculation is performed.
1369   Returns:
1370     True if successful.
1371   See Also:
1372     ON_TextureMapping::GetTextureCoordinates
1373   */
1374   bool SetTextureCoordinates(
1375           const class ON_TextureMapping& mapping,
1376 					const class ON_Xform* mesh_xform = 0,
1377           bool bLazy = true
1378           );
1379 
1380   bool HasCachedTextureCoordinates() const;
1381 
1382   const ON_TextureCoordinates* CachedTextureCoordinates(
1383           const ON_UUID& mapping_id
1384           ) const;
1385 
1386   const ON_TextureCoordinates* SetCachedTextureCoordinates(
1387           const class ON_TextureMapping& mapping,
1388 					const class ON_Xform* mesh_xform = 0,
1389           bool bLazy = true
1390           );
1391 
1392   bool EvaluateMeshGeometry( const ON_Surface& ); // evaluate surface at tcoords
1393                                                   // to set mesh geometry
1394 
1395   // finds all coincident vertices and merges them if break angle is small enough
1396   bool CombineCoincidentVertices(
1397           ON_3fVector, // coordinate tols for considering vertices
1398                        // to be coincident
1399           double  // cosine normal angle tolerance in radians
1400                   // if vertices are coincident, then they are combined
1401                   // if NormalA o NormalB >= this value
1402           );
1403 
1404   /*
1405   Description:
1406     Combines identical vertices.
1407   Parameters:
1408     bIgnoreVertexNormals - [in] If true, then vertex normals
1409       are ignored when comparing vertices.
1410     bIgnoreTextureCoordinates - [in] If true, then vertex
1411       texture coordinates, colors, and principal curvatures
1412       are ignored when comparing vertices.
1413   Returns:
1414     True if the mesh is changed, in which case the returned
1415     mesh will have fewer vertices than the input mesh.
1416   */
1417   bool CombineIdenticalVertices(
1418           bool bIgnoreVertexNormals = false,
1419           bool bIgnoreTextureCoordinates = false
1420           );
1421 
1422   void Append( const ON_Mesh& ); // appends a copy of mesh to this and updates
1423                                  // indices of appended mesh parts
1424 
1425   /*
1426   Description:
1427     Append a list of meshes. This function is much more efficient
1428     than making repeated calls to ON_Mesh::Append(const ON_Mesh&)
1429     when lots of meshes are being joined into a single large mesh.
1430   Parameters:
1431     count - [in]
1432       length of meshes[] array.
1433     meshes - [in]
1434       array of meshes to append.
1435   */
1436   void Append( int count, const ON_Mesh* const* meshes );
1437 
1438   /*
1439   Description:
1440     Expert user function to set m_is_closed member.
1441     Setting this value correctly after a mesh is constructed
1442     can save time when IsClosed() is called.
1443     This function sets the private member variable m_is_closed.
1444   Paramters:
1445     closed - [in]
1446       0: The mesh is not closed.  There is at least one face with an
1447          edge that is geometrically distinct (as an unoriented line segment)
1448          from all other edges.
1449       1: The mesh is closed.  Every geometrically distict edge is used
1450          by two or more faces.
1451   */
1452   void SetClosed(int closed);
1453 
1454   /*
1455   Returns:
1456     True if every mesh "edge" has two or more faces.
1457   */
1458   bool IsClosed() const;
1459 
1460   /*
1461   Returns:
1462     True if every mesh "edge" has at most two faces.
1463   */
1464   bool IsManifold() const;
1465 
1466   /*
1467   Returns:
1468     True if the mesh is manifold and every pair of faces
1469     that share an "edge" have compatible orientations.
1470   */
1471   bool IsOriented() const;
1472 
1473   /*
1474   Description:
1475     Determine if the mesh is a manifold.
1476   Parameters:
1477     bTopologicalTest - [in]
1478       If true, the query treats coincident vertices as
1479       the same.
1480     pbIsOriented - [out]
1481       If the input pointer is not NULL, then the returned
1482       value of *pbIsOriented will be true if the mesh
1483       is a manifold and adjacent faces have compatible
1484       face normals.
1485     pbHasBoundary - [out]
1486       If the input pointer is not NULL, then the returned
1487       value of *pbHasBoundary will be true if the mesh
1488       is a manifold and there is at least one "edge"
1489       with no adjacent faces have compatible
1490       face normals.
1491   Returns:
1492     True if every mesh "edge" has at most two adjacent faces.
1493   */
1494   bool IsManifold(
1495     bool bTopologicalTest,
1496     bool* pbIsOriented = NULL,
1497     bool* pbHasBoundary = NULL
1498     ) const;
1499 
1500   /*
1501   Description:
1502     Expert user function to set m_is_solid member.
1503     Setting this value correctly after a mesh is constructed
1504     can save time when IsSolid() is called.
1505     This function sets the private member variable m_is_solid.
1506     If solid is nonzero, it will set m_is_closed to 1.
1507   Paramters:
1508     solid - [in]
1509       0: The mesh is not an oriented manifold solid mesh. Either
1510          the mesh is not closed, not manifold, or the faces are
1511          not oriented compatibly.
1512       1: The mesh is an oriented manifold solid whose face normals
1513          point outwards.
1514      -1: The mesh is an oriented manifold solid whose face normals
1515          point inwards.
1516   */
1517   void SetSolidOrientation(int solid_orientation);
1518 
1519   /*
1520   Description:
1521     Determine orientation of a mesh.
1522   Returns:
1523     +1     mesh is a solid with outward facing normals
1524     -1     mesh is a solid with inward facing normals
1525      0     mesh is not a solid
1526   See Also:
1527     ON_Mesh::IsSolid
1528   */
1529   int SolidOrientation() const;
1530 
1531   /*
1532   Description:
1533     Test mesh to see if it is a solid.  (A "solid" is
1534     a closed oriented manifold.)
1535   Returns:
1536     true       mesh is a solid
1537     fals       mesh is not a solid
1538   See Also:
1539     ON_Mesh::SolidOrientation
1540     ON_Mesh::IsManifold
1541   */
1542   bool IsSolid() const;
1543 
1544   /*
1545   Description:
1546     Appends a list of mesh edges that begin or end at the specified
1547     vertices to the edges[] array.
1548   Parameters:
1549     vcount - [in]
1550       number of vertices
1551     vertex_index - [in]
1552       array of vertex indices
1553     bNoDuplicates - [in]
1554       If true, then only one edges[] is added for each edge,
1555       the first vertex index will alwasy be less than the
1556       second, and the returned elements are sorted in dictionary
1557       order.
1558       If false and an edge is shared by multiple faces, then
1559       there will be an edges[] element added for each face and the
1560       order of the vertex indicies will indicate the orientation
1561       of the edge with respect to the face.  No sorting is performed
1562       in this case.
1563     edges - [out]
1564       Edges that begin or end at one of the specified vertices are
1565       appended to this array.  Each ON_2dex records the start and
1566       end vertex index.
1567   Returns:
1568     Number of ON_2dex values appended to the edges[] array.
1569   */
1570   int GetVertexEdges(
1571     int vcount,
1572     const int* vertex_index,
1573     bool bNoDuplicates,
1574     ON_SimpleArray<ON_2dex>& edges
1575     ) const;
1576 
1577 
1578   /*
1579   Description:
1580     Appends a list of mesh edges to the edges[] array.
1581   Parameters:
1582     edges - [out]
1583       Each edges[] element is a pair of vertex indices.  There
1584       is at least one face in the mesh with an edge running between
1585       the indicies.
1586   Returns:
1587     Number of ON_2dex values appended to the edges[] array.
1588   */
1589   int GetMeshEdges(
1590     ON_SimpleArray<ON_2dex>& edges
1591     ) const;
1592 
1593   /*
1594   Description:
1595     Assign a unique id to each vertex location.  Coincident vertices
1596     get the same id.
1597   Parameters:
1598     first_vid - [in]
1599       Initial vertex id.  Typically 1 or 0.
1600     Vid - [out]
1601       If not null, then Vid[] sould be an array of length VertexCount().
1602       and the vertex ids will be stored in this array.  If null,
1603       the array will be allocated by calling onmalloc().  The returned
1604       array Vid[i] is the id of the vertex m_V[i].  If m_V[i] and
1605       m_V[j] are the same 3d point, then Vid[i] and Vid[j] will have
1606       the same value.
1607     Vindex - [out] (can be null)
1608       If Vindex is not null, then it must have length at least m_V.Count()
1609       and the returned array will be a permutation of (0,1,...,m_V.Count()-1)
1610       such (Vid[Vindex[0]], Vid[Vindex[1]], ..., Vid[Vindex[m_V.Count()-1]])
1611       is an increasing list of value.
1612   Returns:
1613     null if the mesh has no vertices.
1614     An array of length VertexCount(). If vertices m_V[i] and m_V[j]
1615     are coincident, then Vid[i] = Vid[j].  The id values begin at first_vid.
1616     The maximum vertex id is Vid[Vindex[m_V.Count()-1]].  The number of
1617     unique vertex locations is (Vid[Vindex[m_V.Count()-1]] - first_vid + 1).
1618   */
1619   int* GetVertexLocationIds(
1620     int first_vid,
1621     int* Vid,
1622     int* Vindex
1623     ) const;
1624 
1625   /*
1626   Description:
1627     Get a list of the sides of every face.
1628   Parameters:
1629     Vid - [in] (can be null)
1630       If Vid is null, then the mesh m_V[] index values are used to set
1631       the ON_MeshFaceSide::vi[] values.
1632       If Vid is not null, then it must be an array of length VertexCount().
1633       The value Vid[mesh m_V[] index] will be used to set the
1634       ON_MeshFaceSide::vi[] values.
1635     sides - [out]
1636       If the input value of sides is not null, then sides[] must be long
1637       enough to hold the returned side list.  The maximum posssible length
1638       is 4*FaceCount() for a mesh contining FaceCount() nondegenerate quads.
1639       If the input value of sides is null, memory will be allocated using
1640       onmalloc() and the caller is responsible for calling onfree() at an
1641       appropriate time.  This function fills in the sides[] array
1642       with face side information.  The returned list is sorted by sides[].fi
1643       and the sides[].side and each element has vi[0] <= vi[1].
1644       The function ON_SortMeshFaceSidesByVertexIndex() can be used to sort the
1645       list by the sides[].vi[] values.
1646   Returns:
1647     Number of elements added to sides[].
1648   Remarks:
1649     Faces with out of range ON_MeshFace.vi[] values are skipped.
1650     Degenerate faces are processed, but degenerate sides (equal vertex indices)
1651     are not added to the list.
1652   */
1653   int GetMeshFaceSideList(
1654       const int* Vid,
1655       struct ON_MeshFaceSide*& sides
1656       ) const;
1657 
1658   /*
1659   Description:
1660     Get a list of the geometrically uniqued edges in a mesh.
1661   Parameters:
1662     edge_list - [out]
1663       The edge list for this mesh is appended to edge_list[].
1664       The ON_2dex i and j values are mesh->m_V[] array indices.
1665       There is exactly one element in edge_list[] for each
1666       unoriented 3d line segment in the mesh. The edges are
1667       oriented the same way the corresponding ON_MeshTopology
1668       edge is oriented.
1669     ci_meshtop_edge_map - [out]
1670       If you call the verson of GetMeshEdgeList() with the ci_meshtop_edge_map[],
1671       parameter, then the edge in edge_list[i] cooresponds to the edge
1672       in ON_MeshTopology.m_tope[ci_meshtop_edge_map[i]]. The value
1673       ci_meshtop_edge_map[i] is useful if you need to convert an edge_list[]
1674       index into an ON_COMPONENT_INDEX with type meshtop_edge.
1675     ci_meshtop_vertex_map - [out]
1676       If you call the verson of GetMeshEdgeList() with the ci_meshtop_vertex_map[],
1677       parameter, then the vertex m_V[i] cooresponds to the vertex
1678       in ON_MeshTopology.m_topv[ci_meshtop_vertex_map[i]]. The value
1679       ci_meshtop_vertex_map[i] is useful if you need to convert an m_V[]
1680       index into an ON_COMPONENT_INDEX with type meshtop_vertex.
1681     edge_list_partition - [out] (can be null)
1682       The edge_list[] is always ordered so that edge_types
1683       are partitioned into contiguous regions. The edge_list_partition[5]
1684       values report the edge type regions.
1685       * If edge_type_partition[0] <= ei < edge_type_partition[1], then
1686         edge_list[ei] is an edge of exactly two faces and the vertices
1687         used by the faces are identical.  These are also called
1688         "manifold edges".
1689       * If edge_type_partition[1] <= ei < edge_type_partition[2], then
1690         edge_list[ei] is an edge of exactly two faces, but at least
1691         one of the vertices is duplicated.  These are also called
1692         "crease edges".
1693       * If edge_type_partition[2] <= ei < edge_type_partition[3], then
1694         edge_list[ei] is an edge of 3 or more faces. These are also called
1695         "nonmanifold edges".
1696       * If edge_type_partition[3] <= ei < edge_type_partition[4],
1697         then edge_list[ei] is a boundary edge of exactly one mesh face.
1698         These are also called "naked edges".
1699   Returns:
1700     Number of edges added to edge_list[].
1701   Remarks:
1702     This calculation also sets m_closed.  If you modify the mesh's
1703     m_V or m_F information after calling this function, be sure to
1704     clear m_is_closed.
1705   */
1706   int GetMeshEdgeList(
1707       ON_SimpleArray<ON_2dex>& edge_list,
1708       int edge_type_partition[5]
1709       ) const;
1710 
1711   int GetMeshEdgeList(
1712       ON_SimpleArray<ON_2dex>& edge_list,
1713       ON_SimpleArray<int>& ci_meshtop_edge_map,
1714       int edge_type_partition[5]
1715       ) const;
1716 
1717   int GetMeshEdgeList(
1718       ON_SimpleArray<ON_2dex>& edge_list,
1719       ON_SimpleArray<int>& ci_meshtop_edge_map,
1720       ON_SimpleArray<int>& ci_meshtop_vertex_map,
1721       int edge_type_partition[5]
1722       ) const;
1723 
1724   ///////////////////////////////////////////////////////////////////////
1725   //
1726   // mesh editing
1727   //
1728 
1729   /*
1730   Description:
1731     Replace a mesh edge with a vertex at its center and update
1732     adjacent faces as needed.
1733   Parameters:
1734     topei - [in] index of edge in MeshTopology().m_tope[] array
1735   Returns:
1736     true if successful.
1737   */
1738   bool CollapseEdge( int topei );
1739 
1740   /*
1741   Description:
1742     Tests a mesh edge to see if it is valid as input to
1743     ON_Mesh::SwapMeshEdge.
1744   Parameters:
1745     topei - [in] index of edge in MeshTopology().m_tope[] array
1746   Returns:
1747     true if edge can be swapped by ON_Mesh::SwapMeshEdge.
1748   See Also:
1749     ON_Mesh::SwapEdge
1750   */
1751   bool IsSwappableEdge( int topei );
1752 
1753 
1754   /*
1755   Description:
1756     If the edge is shared by two triangular face, then
1757     the edge is "swapped".
1758   Parameters:
1759     topei - [in] index of edge in MeshTopology().m_tope[] array
1760   Returns:
1761     true if successful
1762   See Also:
1763     ON_Mesh::IsSwappableEdge
1764   */
1765   bool SwapEdge( int topei );
1766 
1767   /*
1768   Description:
1769     Removes a face from a mesh and does not alter the
1770     geometry of the remaining mesh.
1771   Parameters:
1772     meshfi - [in] index of face in ON_Mesh.m_F[] array
1773   Remarks:
1774     This function calls DestroyTopology() and DestroyPartition().
1775     The caller is responsible for calling Compact() if that step
1776     is required.
1777   Returns:
1778     true if successful
1779   */
1780   bool DeleteFace( int meshfi );
1781 
1782   /*
1783   Description:
1784     Destroys the m_H[] array and sets m_hidden_count=0.
1785   */
1786   void DestroyHiddenVertexArray();
1787 
1788   /*
1789   Returns:
1790     If the mesh has some hidden vertices, then an array
1791     of length VertexCount() is returned and the i-th
1792     element is true if the i-th vertex is hidden.
1793     If no vertices are hidden, NULL is returned.
1794   */
1795   const bool* HiddenVertexArray() const;
1796 
1797   /*
1798   Description:
1799     Set the runtime vertex hidden flag.
1800   Parameters:
1801     meshvi - [in] mesh vertex index
1802     bHidden - [in] true to hide vertex
1803   */
1804   void SetVertexHiddenFlag( int meshvi, bool bHidden );
1805 
1806   /*
1807   Description:
1808     Returns true if the mesh vertex is hidden.  This is a runtime
1809     setting that is not saved in 3dm files.
1810   Parameters:
1811     meshvi - [in] mesh vertex index.
1812   Returns:
1813     True if mesh vertex is hidden.
1814   */
1815   bool VertexIsHidden( int meshvi ) const;
1816 
1817   /*
1818   Description:
1819     Returns true if the mesh face is hidden.  This is a runtime
1820     setting that is not saved in 3dm files.
1821   Parameters:
1822     meshfi - [in] mesh face index.
1823   Returns:
1824     True if mesh face is hidden.
1825   Remarks:
1826     A face is hidden if, and only if, at least one of its
1827     vertices is hidden.
1828   */
1829   bool FaceIsHidden( int meshvi ) const;
1830 
1831 
1832   ///////////////////////////////////////////////////////////////////////
1833   //
1834   // mesh topology
1835   //
1836   // In order to keep the mesh facet definition simple and make the mesh
1837   // definition easily used in common rendering application, if two facets
1838   // share a vertex location but have different normals, curvatures,
1839   // textures, etc., at that common vertex location, then the vertex is
1840   // duplicated.  When the topology of the mesh needs to be known,
1841   // use Topology() to get a class that provides complete topological
1842   // information about the mesh.
1843   const ON_MeshTopology& Topology() const;
1844 
1845   ///////////////////////////////////////////////////////////////////////
1846   // If you modify the mesh in any way that may change its topology,
1847   // then call DestroyTopology().  Specifically if you add or remove
1848   // vertices or face, change vertex locations, or change the face m_vi[]
1849   // values, then you must call DestroyTopology().
1850   void DestroyTopology();
1851 
1852   /*
1853   Returns:
1854     This is an expert user function that returns true if the topology
1855     information is already calculated and cached.  It can be used to
1856     to avoid calling the Topology() function when the expensive creation
1857     step will be performed.
1858   */
1859   bool TopologyExists() const;
1860 
1861 
1862   ///////////////////////////////////////////////////////////////////////
1863   //
1864   // mesh partitions
1865   //
1866   // In ancient times, some rendering engines were only able to process
1867   // small batches of triangles and th CreatePartition() function was
1868   // provided to partition the mesh into subsets of vertices and faces
1869   // that those renering engines could handle.
1870   //
1871   const ON_MeshPartition* CreatePartition(
1872                 int, // maximum number of vertices in a partition
1873                 int  // maximum number of triangles in a partition
1874                 );
1875   const ON_MeshPartition* Partition() const;
1876   void DestroyPartition();
1877 
1878   /*
1879   Description:
1880     Extract the portion of this mesh defined by mesh_part.
1881   Parameters:
1882     mesh_part - [in]
1883       defines portion of the mesh to extract.
1884     mesh - [in] (can be null, cannot be = "this).
1885       If mesh is no null, the extracted mesh will be put into
1886       this mesh.  If mesh is null, the extracted mesh will
1887       be created in a mesh allocated on the heap using the
1888       new operator.
1889   Returns:
1890     A pointer to the submesh.  If the input mesh parameter is null,
1891     then the caller must delete this mesh when it is no longer needed.
1892     If the input is invalid, then null is returned.
1893   */
1894   ON_Mesh* MeshPart(
1895     const ON_MeshPart& mesh_part,
1896     ON_Mesh* mesh
1897     ) const;
1898 
1899   /*
1900   Description:
1901     Create a mesh that is a single face of this mesh.
1902   Parameters:
1903   Returns:
1904     A pointer to the submesh.  If the input mesh parameter is null,
1905     then the caller must delete this mesh when it is no longer needed.
1906     If the input is invalid, then null is returned.
1907   */
1908   ON_Mesh* DuplicateFace(
1909     int face_index,
1910     ON_Mesh* mesh
1911     ) const;
1912 
1913   ///////////////////////////////////////////////////////////////////////
1914   //
1915   // mesh N-gon lists.
1916   //   ON_Mesh objects support faces that are triangle or quads.
1917   //   When a mesh is created from a format that supports N-gons
1918   //   for N larger than 4, an optional N-gon list can be added
1919   //   that specifies the vertices and faces that make up the N-gon.
1920   //
1921 
1922   /*
1923   Description:
1924     If the mesh has an N-gon list, return a pointer to it.
1925   Returns:
1926     A pointer to the current N-gon list or NULL.
1927   */
1928   const class ON_MeshNgonList* NgonList() const;
1929 
1930   /*
1931   Description:
1932     If an N-gon list exists, it is returned and can be modified.
1933     If no N-gon list exists, a new empty list is returned and
1934     it can be modified.
1935   Returns:
1936     A pointer to the N-gon list that can be modified.
1937   */
1938   class ON_MeshNgonList* ModifyNgonList();
1939 
1940   /*
1941   Description:
1942     Destroy any existing N-gon list.
1943   */
1944   void DestroyNgonList();
1945 
1946   ///////////////////////////////////////////////////////////////////////
1947   //
1948   // mesh components
1949   //   ON_Mesh objects can consist of sets of faces that are isolated
1950   //   from any other sets of faces.  The following 2 functions will
1951   //   dissect a mesh into these sets, called components.  Not to be
1952   //   confused with ON_COMPONENT_INDEX.
1953 
1954   /*
1955     Description:
1956       Calculates the components of a mesh and sets a label for each face in
1957       the facet_component_labels array.
1958     Parameters:
1959       bUseVertexConnections- [in]
1960         If this parameter is true, then facets that share a common vertex
1961         are considered connected.
1962         If this parameter is false, then facets must share an edge to
1963         be considered connected.
1964       bUseTopologicalConnections - [in]
1965         If this parameter is true, then geometric location is used
1966         to determine if facets are connected.
1967         If this parameter is false, then facets must share the same vertex
1968         or vertices to be considered connected.
1969       facet_component_labels- [out]
1970         facet_component_labels[] will be an array with the same size
1971         as ON_Mesh.m_F.Count() and facet_component_labels[i]
1972         is the component id m_F[i] belongs to.  The component id
1973         will be 1 to the number of compoents.
1974     Returns:
1975       Number of components on success, 0 on failure
1976   */
1977 
1978   int GetConnectedComponents( bool bUseVertexConnections,
1979                               bool bTopologicalConnections,
1980                               ON_SimpleArray<int>& facet_component_labels
1981                             ) const;
1982 
1983   /*
1984     Description:
1985       Calculates the components of a mesh and sets a label for each face in
1986       the facet_component_labels array.
1987     Parameters:
1988       bUseVertexConnections- [in]
1989         If this parameter is true, then facets that share a common vertex
1990         are considered connected.
1991         If this parameter is false, then facets must share an edge to
1992         be considered connected.
1993       bUseTopologicalConnections - [in]
1994         If this parameter is true, then geometric location is used
1995         to determine if facets are connected.
1996         If this parameter is false, then facets must share the same vertex
1997         or vertices to be considered connected.
1998       components   - [out]
1999         New components are appended to this array
2000         if this parameter is null, then the components are just counted.
2001     Returns:
2002       Number of components on success, 0 on failure
2003   */
2004 
2005   int GetConnectedComponents( bool bUseVertexConnections,
2006                               bool bTopologicalConnections,
2007                               ON_SimpleArray<ON_Mesh*>* components
2008                             ) const;
2009 
2010 
2011   /////////////////////////////////////////////////////////////////
2012   //
2013   // Double precision vertex support
2014   //
2015 
2016   /*
2017   Returns:
2018     True if the mesh has single and double precision
2019     vertices, and the values of the two sets are synchronized.
2020   */
2021   bool HasSynchronizedDoubleAndSinglePrecisionVertices() const;
2022 
2023   /*
2024   Returns:
2025     True if the mesh has double precision vertices.
2026   Remarks:
2027     This function returns true if a mesh has double
2028     precision vertex information, even if it is not
2029     updated.
2030 
2031     Use ON_Mesh::DoublePrecisionVerticesAreValid()
2032     and ON_Mesh::SinglePrecisionVerticesAreValid() to
2033     check the validity.
2034 
2035     Use ON_Mesh::UpdateDoublePrecisionVertices()
2036     or ON_Mesh::UpdateSinglePrecisionVertices() to synchronize
2037     values of single and double precision vertices.
2038   */
2039   bool HasDoublePrecisionVertices() const;
2040 
2041   /*
2042   Parameters:
2043     bEnableDoublePrecisionVertices - [in]
2044       True to enable use of double precision vertices.
2045       False to destroy any existing precision vertices.
2046   */
2047   void EnableDoublePrecisionVertices(bool bEnableDoublePrecisionVertices);
2048 
2049   /*
2050   Description:
2051     If you modify the values of double precision vertices,
2052     then you must call UpdateSinglePrecisonVertices().
2053   Remarks:
2054     If double precision vertices are not present, this function
2055     does nothing.
2056   */
2057   void UpdateSinglePrecisionVertices();
2058 
2059   /*
2060   Description:
2061     If you modify the values of the single precision vertices
2062     in m_V[], then you must call UpdateDoublePrecisionVertices().
2063   Remarks:
2064     If double precision vertices are not present, this function
2065     does nothing.
2066   */
2067   void UpdateDoublePrecisionVertices();
2068 
2069   /*
2070   Description:
2071     If you have modified the single precision vertices
2072     and are certain they are valid, then call this
2073     function to update crc information.
2074   Remarks:
2075     If double precision vertices are not present, this function
2076     does nothing.
2077   */
2078   void SetSinglePrecisionVerticesAsValid();
2079 
2080   /*
2081   Description:
2082     If you have modified the double precision vertices
2083     and are certain they are valid, then call this
2084     function to update crc information.
2085   Remarks:
2086     If double precision vertices are not present, this function
2087     does nothing.
2088   */
2089   void SetDoublePrecisionVerticesAsValid();
2090 
2091   /*
2092   Description:
2093     The functions UpdateSinglePrecisionVertices(),
2094     UpdateDoublePrecisionVertices(), and
2095     SetSinglePrecisionVerticesAsValid() save
2096     the count and crc of the single precision vertex
2097     array. True is returned if there are no
2098     double precision vertices or the current
2099     count and crc of the single precision
2100     vertex array match the saved values.
2101   Remarks:
2102     If double precision vertices are not present, this function
2103     does nothing and returns true.
2104   */
2105   bool SinglePrecisionVerticesAreValid() const;
2106 
2107   /*
2108   Description:
2109     The functions UpdateSinglePrecisionVertices(),
2110     UpdateDoublePrecisionVertices(), and
2111     SetDoublePrecisionVerticesAsValid() save
2112     the count and crc of the double precision vertex
2113     array. True is returned if the current
2114     count and crc of the double precision
2115     vertex array match the saved values.
2116   Remarks:
2117     If double precision vertices are not present, this function
2118     does nothing and returns true.
2119   */
2120   bool DoublePrecisionVerticesAreValid() const;
2121 
2122   /*
2123   Description:
2124     The function removes all double precision vertex information.
2125   */
2126   void DestroyDoublePrecisionVertices();
2127 
2128 
2129   /////////////////////////////////////////////////////////////////
2130   // Implementation - mesh geometry
2131 
2132   // Vertex locations
2133   //   In a case where adjacent facets share a vertex
2134   //   location but have distinct normals or texture
2135   //   coordinates at that location, the vertex must
2136   //   be duplicated.
2137 
2138   /*
2139   Description:
2140     Get double precision vertices.  If they do not exist,
2141     they will be created and match the existing single
2142     precision vertices.
2143   Returns:
2144     Array of double precision vertices.  If you modify the
2145     values in this array, you must make the same modifications
2146     to the single precision vertices, or call
2147     UpdateSinglePrecisonVertices().
2148   Example:
2149 
2150           // add a bunch of double precision information
2151           ON_3dPointArray& dv = mesh.DoublePrecisionVertices();
2152           for ( i = 0; i < lots; i++ )
2153           {
2154             dv[i] = ...
2155           }
2156           // This call updates the single precison values
2157           // in m_V[] and sets all the counts and CRCs that
2158           // are used in validity checking.
2159           mesh.UpdateSinglePrecisonVertices();
2160 
2161   Remarks:
2162     Avoid mulitple calls to DoublePrecisionVertices().
2163     It is most efficient to make one call, save a local
2164     reference, and use the local reference as needed.
2165   */
2166   ON_3dPointArray& DoublePrecisionVertices();
2167   const ON_3dPointArray& DoublePrecisionVertices() const;
2168 
2169   /*
2170   Description:
2171     Get single precision vertices.
2172   Returns:
2173     Array of float precision vertices.  If you modify the
2174     values in this array, you must make the same modifications
2175     to the double precision vertices, or call
2176     UpdateSinglePrecisonVertices().
2177   */
2178   ON_3fPointArray& SinglePrecisionVertices();
2179   const ON_3fPointArray& SinglePrecisionVertices() const;
2180 
2181   /*
2182   Description:
2183     In general,use one of
2184     ON_Mesh::SinglePrecisionVertices()
2185     or
2186     ON_Mesh::DoublePrecisionVertices()
2187     to get the array of vertex locations.  If you modify
2188     m_V[] directly and HasDoublePrecisionVertices() is true,
2189     then you must make the same modifications to the array
2190     returned by DoublePrecisionVertices().
2191   */
2192   ON_3fPointArray m_V;
2193 
2194   /*
2195   Returns:
2196     Location of the vertex.  If double precision vertices
2197     are present, the double precision vertex location is
2198     returned.  If vertex_index is out of range,
2199     ON_UNSET_VALUE is returned.
2200   */
2201   ON_3dPoint Vertex(int vertex_index) const;
2202 
2203   // m_F[] facets (triangles or quads)
2204   ON_SimpleArray<ON_MeshFace> m_F;
2205 
2206   // m_N[] OPTIONAL vertex unit normals
2207   // If m_N[] is empty or m_N.Count() != m_V.Count(),
2208   // Either m_N[] has zero count or it m_N[j] is the
2209   // the unit vertex normal at m_V[j].
2210   ON_3fVectorArray m_N;
2211 
2212   // m_FN[] OPTIONAL face unit normals
2213   // If m_FN[] is empty or m_FN.Count() != m_F.Count(),
2214   // then m_FN is ignored.  Otherwise m_FN[j] is the
2215   // unit normal for the facet m_F[j].
2216   ON_3fVectorArray m_FN;
2217 
2218   /////////////////////////////////////////////////////////////////
2219   // Implementation - texture coordinates
2220   //
2221   // OPTIONAL texture coordinates for each vertex
2222 
2223   // It would be nice if this were an ON_TextureCoordinates,
2224   // but that breaks lots of checked out code that assumes
2225   // m_T is an array of ON_2fPoints.
2226   ON_MappingTag m_Ttag; // OPTIONAL tag for values in m_T[]
2227   ON_2fPointArray m_T;  // OPTIONAL texture coordinates for each vertex
2228 
2229   // RUNTIME ONLY
2230   //   This array is used to cache texture coordinates used by
2231   //   rendering applications that require 1d texture coordinates,
2232   //   3d texture coordinates, or multiple sets of texture
2233   //   coordinates (e.g. blended textures with different mappings).
2234   //   Users are responsible for verifying
2235   //   m_TC[i].m_T.Count() = m_V.Count()
2236   ON_ClassArray<ON_TextureCoordinates> m_TC;
2237 
2238   // If m_T.Count() == m_V.Count(), then the mesh has texture coordinates
2239   // and m_T[j] is the texture coordinate for vertex m_V[j].
2240   //
2241   // When opennurbs or Rhino meshes an ON_Surface or ON_Brep, the texture
2242   // coordinates have a "canonical" linear relationship with the surface
2243   // parameters that is described in the next section.  However, various
2244   // mappings, spherical, planar, cylindrical, etc., can be applied that
2245   // change the values of the texture coordinates.
2246   //
2247   // If a texture mapping function was used to set the m_T[] values,
2248   // then the id and serial number of the mapping function is saved
2249   // in m_mapping_id and m_mapping_sn. The intended use of these fields
2250   // is to make it easy to avoid unnecessary recalculation.
2251   // If a mesh is modified, then m_mapping_id should be set to nil
2252   // and m_mapping_crc should be set to 0.
2253   //
2254   /////////////////////////////////////////////////////////////////
2255 
2256 
2257   /////////////////////////////////////////////////////////////////
2258   // Implementation - surface parameters and packed texture
2259   // information
2260   //
2261   // If m_S.Count() == m_V.Count(), then the mesh is a tesselation
2262   // of a parameteric surface and m_S[j] is the surface parameter at
2263   // m_V[j].  Storing values in m_S[] is OPTIONAL.
2264   //
2265   // If m_srf_scale[] has positive values, then they report
2266   // the world coordinate size of a rectangle that would
2267   // minimize texture distortion if it were mapped to the
2268   // mesh using normalized surface evaluation parameters.
2269   // This information is used to calculate high quality
2270   // packed texture coordinates.
2271   ON_2dPointArray m_S;
2272   ON_Interval m_srf_domain[2]; // surface evaluation domain.
2273   double m_srf_scale[2];
2274 
2275 
2276   // Packed texture information.
2277   //
2278   // If either of the m_packed_tex_domain[] intervals is a
2279   // proper subinterval of (0,1), then a texture packing
2280   // calculation assigned this subrectangle to this mesh.
2281 
2282   ON_Interval m_packed_tex_domain[2];
2283 
2284   // The m_packed_tex_rotate setting is valid only when
2285   // m_S, m_srf_domain, m_packed_scale[] and
2286   // m_packed_tex_domain[] are all valid and the texture
2287   // coordinates are based on surface evaluation parameters.
2288   // In this special situation, this boolean records the
2289   // correspondence between the the surface parameters, (u,v),
2290   // and the packed texture coordinates, (s,t),
2291   //
2292   //   m_packed_tex_rotate = false:
2293   //     a = m_srf_domain[0].NormalizedParameterAt(u);
2294   //     b = m_srf_domain[1].NormalizedParameterAt(v);
2295   //     s = m_packed_tex_domain[0].ParameterAt(a);
2296   //     t = m_packed_tex_domain[1].ParameterAt(b);
2297   //
2298   //     x = m_packed_tex_domain[0].NormalizedParameterAt(s);
2299   //     y = m_packed_tex_domain[1].NormalizedParameterAt(t);
2300   //     u = m_srf_domain[0].ParameterAt(x);
2301   //     v = m_srf_domain[1].ParameterAt(y);
2302   //
2303   //   m_packed_tex_rotate = true:
2304   //     a = m_srf_domain[0].NormalizedParameterAt(u);
2305   //     b = m_srf_domain[1].NormalizedParameterAt(v);
2306   //     s = m_packed_tex_domain[0].ParameterAt(a);
2307   //     t = m_packed_tex_domain[1].ParameterAt(1.0-b);
2308   //
2309   //     x = m_packed_tex_domain[0].NormalizedParameterAt(s);
2310   //     y = m_packed_tex_domain[1].NormalizedParameterAt(t);
2311   //     u = m_srf_domain[0].ParameterAt(y);
2312   //     v = m_srf_domain[1].ParameterAt(1.0 - x);
2313   bool m_packed_tex_rotate;
2314 
2315   /*
2316   Returns:
2317     True if the m_srf_scale[] values are positive and
2318     the m_packed_tex_domain[] intervals are set to values
2319     that describe a proper subrectangle of (0,1)x(0,1).
2320     True does not necessarily mean the current values in
2321     m_T[] are packed texture coordinates.
2322   */
2323   bool HasPackedTextureRegion() const;
2324 
2325   /////////////////////////////////////////////////////////////////
2326   // Implementation - curvature
2327 
2328   ON_SimpleArray<ON_SurfaceCurvature> m_K;  // OPTIONAL surface curvatures
2329                                             // Either m_K[] has zero count or it has the same
2330                                             // count as m_V[], in which case m_K[j] reports
2331                                             // the surface curvatures at m_V[j].
2332 
2333   /////////////////////////////////////////////////////////////////
2334   // Implementation - false color
2335   ON_MappingTag m_Ctag; // OPTIONAL tag for values in m_C[]
2336   ON_SimpleArray<ON_Color> m_C;  // OPTIONAL vertex color
2337                                  // Either m_C[] has zero count or it has the same
2338                                  // count as m_V[], in which case m_C[j] reports
2339                                  // the color assigned to m_V[j].
2340 
2341   /////////////////////////////////////////////////////////////////
2342   // Implementation - runtime vertex visibility - not saved in 3dm files.
2343   ON_SimpleArray<bool> m_H; // OPTIONAL vertex visibility.
2344                             // If m_H.Count() = m_V.Count(), then
2345                             // m_H[vi] is true if the vertex m_V[vi]
2346                             // is hidden.  Otherwise, all vertices are visible.
2347   int m_hidden_count;       // number of vertices that are hidden
2348                             // = number of true values in m_H[] array.
2349 
2350   /////////////////////////////////////////////////////////////////
2351   // Implementation - runtime UI information
2352   const ON_Object* m_parent; // runtime parent geometry (use ...::Cast() to get it)
2353 
2354 protected:
2355   friend class ON_MeshVertexRef;
2356   friend class ON_MeshEdgeRef;
2357   friend class ON_MeshFaceRef;
2358 
2359 
2360   /////////////////////////////////////////////////////////////////
2361   // Implementation - mesh topology
2362   ON_MeshTopology m_top;
2363 
2364   ON_MeshParameters* m_mesh_parameters; // If mesh was created from a parametric surface,
2365                                         // these parameters were used to create the mesh.
2366   int                         m_invalid_count;
2367   int                         m_quad_count;
2368   int                         m_triangle_count;
2369 
2370 private:
2371   char m_mesh_is_closed;   // 0 = unset, 1 = all edges have 2 or more faces, 2 = at least one boundary edge
2372   char m_mesh_is_manifold; // 0 = unset, 1 = all edges have 1 or 2 faces, 2 = not manifold
2373   char m_mesh_is_oriented; // 0 = unset, 1 = faces normals agree across all edges that have 2 faces, 2 = not oriented
2374   char m_mesh_is_solid;    // 0 = unset, 1 = solid with outward face normals, 2 = solid with inward face normals, 3 = not solid
2375 
2376 protected:
2377   // The bounding boxes are valid if m_?box[0][0] <= m_?box[0][1];
2378   float m_vbox[2][3]; // 3d bounding box of all referenced vertices
2379   float m_nbox[2][3]; // 3d bounding box of all referenced unit normals
2380                       // (for estimation of Gauss map bounds)
2381   float m_tbox[2][2]; // 2d bounding box of all referenced texture coordinates
2382   ON_MeshCurvatureStats* m_kstat[4]; // gaussian,mean,min,max,sectionx,sectiony,sectionz
2383 
2384   // sub-mesh information rendering large meshes
2385   ON_MeshPartition* m_partition;
2386 
2387 private:
2388   bool Write_1( ON_BinaryArchive& ) const; // uncompressed 1.x format
2389   bool Write_2( int, ON_BinaryArchive& ) const; // compressed 2.x format
2390   bool Read_1( ON_BinaryArchive& );
2391   bool Read_2( int, ON_BinaryArchive& );
2392   bool WriteFaceArray( int, int, ON_BinaryArchive& ) const;
2393   bool ReadFaceArray( int, int, ON_BinaryArchive& );
2394   bool SwapEdge_Helper( int, bool );
2395 };
2396 
2397 class ON_CLASS ON_MeshVertexRef : public ON_Geometry
2398 {
2399   ON_OBJECT_DECLARE(ON_MeshVertexRef);
2400 public:
2401   ON_MeshVertexRef();
2402   ~ON_MeshVertexRef();
2403   ON_MeshVertexRef& operator=(const ON_MeshVertexRef&);
2404 
2405 
2406   // parent mesh
2407   const ON_Mesh* m_mesh;
2408 
2409   // m_mesh->m_V[] index
2410   // (can be -1 when m_top_vi references a shared vertex location)
2411   int m_mesh_vi;
2412 
2413   // m_mesh->m_top.m_tope[] index
2414   int m_top_vi;
2415 
2416 
2417   /*
2418   Description:
2419     Override of the virtual ON_Geometry::ComponentIndex().
2420   Returns:
2421     A component index for the vertex.  The type of the returned
2422     component index can be
2423     ON_COMPONENT_INDEX::mesh_vertex,
2424     ON_COMPONENT_INDEX::meshtop_vertex, or
2425     ON_COMPONENT_INDEX::invalid_type.
2426   */
2427   ON_COMPONENT_INDEX ComponentIndex() const;
2428 
2429   /*
2430   Returns:
2431     The mesh topology associated with this
2432     mesh vertex reference or NULL if it doesn't
2433     exist.
2434   */
2435   const ON_MeshTopology* MeshTopology() const;
2436 
2437   /*
2438   Returns:
2439     The 3d location of the mesh vertex.  Returns
2440     ON_UNSET_POINT is this ON_MeshVertexRef is not
2441     valid.
2442   */
2443   ON_3dPoint Point() const;
2444 
2445   /*
2446   Returns:
2447     The mesh topology vertex associated with this
2448     mesh vertex reference.
2449   */
2450   const ON_MeshTopologyVertex* MeshTopologyVertex() const;
2451 
2452   // overrides of virtual ON_Object functions
2453   ON_BOOL32 IsValid( ON_TextLog* text_log = NULL ) const;
2454   void Dump( ON_TextLog& ) const;
2455   unsigned int SizeOf() const;
2456   ON::object_type ObjectType() const;
2457 
2458   // overrides of virtual ON_Geometry functions
2459   int Dimension() const;
2460   ON_BOOL32 GetBBox(
2461          double* boxmin,
2462          double* boxmax,
2463          int bGrowBox = false
2464          ) const;
2465   ON_BOOL32 Transform(
2466          const ON_Xform& xform
2467          );
2468 };
2469 
2470 class ON_CLASS ON_MeshEdgeRef : public ON_Geometry
2471 {
2472   ON_OBJECT_DECLARE(ON_MeshEdgeRef);
2473 public:
2474   ON_MeshEdgeRef();
2475   ~ON_MeshEdgeRef();
2476   ON_MeshEdgeRef& operator=(const ON_MeshEdgeRef&);
2477 
2478   // parent mesh
2479   const ON_Mesh* m_mesh;
2480 
2481   // m_mesh->m_top.m_tope[] index
2482   int m_top_ei;
2483 
2484   /*
2485   Description:
2486     Override of the virtual ON_Geometry::ComponentIndex().
2487   Returns:
2488     A mesh component index for the edge.  The type is
2489     ON_COMPONENT_INDEX::meshtop_edge and the index is the
2490     index into the ON_MeshTopology.m_tope[] array.
2491   */
2492   ON_COMPONENT_INDEX ComponentIndex() const;
2493 
2494   /*
2495   Returns:
2496     The mesh topology associated with this
2497     mesh edge reference or NULL if it doesn't
2498     exist.
2499   */
2500 
2501   const ON_MeshTopology* MeshTopology() const;
2502   /*
2503   Returns:
2504     The 3d location of the mesh edge.  Returns
2505     ON_UNSET_POINT,ON_UNSET_POINT, is this ON_MeshEdgeRef
2506     is not valid.
2507   */
2508   ON_Line Line() const;
2509 
2510   /*
2511   Returns:
2512     The mesh topology edge associated with this
2513     mesh edge reference.
2514   */
2515   const ON_MeshTopologyEdge* MeshTopologyEdge() const;
2516 
2517   // overrides of virtual ON_Object functions
2518   ON_BOOL32 IsValid( ON_TextLog* text_log = NULL ) const;
2519   void Dump( ON_TextLog& ) const;
2520   unsigned int SizeOf() const;
2521   ON::object_type ObjectType() const;
2522 
2523   // overrides of virtual ON_Geometry functions
2524   int Dimension() const;
2525   ON_BOOL32 GetBBox(
2526          double* boxmin,
2527          double* boxmax,
2528          int bGrowBox = false
2529          ) const;
2530   ON_BOOL32 Transform(
2531          const ON_Xform& xform
2532          );
2533 };
2534 
2535 class ON_CLASS ON_MeshFaceRef : public ON_Geometry
2536 {
2537   ON_OBJECT_DECLARE(ON_MeshFaceRef);
2538 public:
2539   ON_MeshFaceRef();
2540   ~ON_MeshFaceRef();
2541   ON_MeshFaceRef& operator=(const ON_MeshFaceRef&);
2542 
2543   // parent mesh
2544   const ON_Mesh* m_mesh;
2545 
2546   // m_mesh->m_F[] and m_mesh->m_top.m_tope[] index.
2547   int m_mesh_fi;
2548 
2549   /*
2550   Description:
2551     Override of the virtual ON_Geometry::ComponentIndex().
2552   Returns:
2553     A mesh component index for the face.  The type is
2554     ON_COMPONENT_INDEX::mesh_face and the index is the
2555     index into the ON_Mesh.m_F[] array.
2556   */
2557   ON_COMPONENT_INDEX ComponentIndex() const;
2558 
2559   /*
2560   Returns:
2561     The mesh topology associated with this
2562     mesh face reference or NULL if it doesn't
2563     exist.
2564   */
2565   const ON_MeshTopology* MeshTopology() const;
2566 
2567   /*
2568   Returns:
2569     The mesh face associated with this mesh face reference.
2570   */
2571   const ON_MeshFace* MeshFace() const;
2572 
2573   /*
2574   Returns:
2575     The mesh topology face associated with this
2576     mesh face reference.
2577   */
2578   const ON_MeshTopologyFace* MeshTopologyFace() const;
2579 
2580   // overrides of virtual ON_Object functions
2581   ON_BOOL32 IsValid( ON_TextLog* text_log = NULL ) const;
2582   void Dump( ON_TextLog& ) const;
2583   unsigned int SizeOf() const;
2584   ON::object_type ObjectType() const;
2585 
2586   // overrides of virtual ON_Geometry functions
2587   int Dimension() const;
2588   ON_BOOL32 GetBBox(
2589          double* boxmin,
2590          double* boxmax,
2591          int bGrowBox = false
2592          ) const;
2593   ON_BOOL32 Transform(
2594          const ON_Xform& xform
2595          );
2596 };
2597 
2598 /*
2599 Description:
2600   Calculate a mesh representation of the NURBS surface's control polygon.
2601 Parameters:
2602   nurbs_surface - [in]
2603   bCleanMesh - [in] If true, then degenerate quads are cleaned
2604                     up to be triangles. Surfaces with singular
2605                     sides are a common source of degenerate qauds.
2606   input_mesh - [in] If NULL, then the returned mesh is created
2607        by a class to new ON_Mesh().  If not null, then this
2608        mesh will be used to store the conrol polygon.
2609 Returns:
2610   If successful, a pointer to a mesh.
2611 */
2612 ON_DECL
2613 ON_Mesh* ON_ControlPolygonMesh(
2614           const ON_NurbsSurface& nurbs_surface,
2615           bool bCleanMesh,
2616           ON_Mesh* input_mesh = NULL
2617           );
2618 
2619 /*
2620 Description:
2621   Finds the unit normal to the triangle
2622 Parameters:
2623   A - [in] triangle corner
2624   B - [in] triangle corner
2625   C - [in] triangle corner
2626 Returns:
2627   Unit normal
2628 */
2629 ON_DECL
2630 ON_3dVector ON_TriangleNormal(
2631         const ON_3dPoint& A,
2632         const ON_3dPoint& B,
2633         const ON_3dPoint& C
2634         );
2635 
2636 
2637 /*
2638 Description:
2639   Finds the unit normal to the triangle
2640 Parameters:
2641   A - [in] triangle corner
2642   B - [in] triangle corner
2643   C - [in] triangle corner
2644   a - [out] must not be null
2645   b - [out] must not be null
2646   c - [out] must not be null
2647   d - [out] must not be null
2648     The equation of the plane is a*x + b*y + c*z + d = 0
2649   ev_tol - [out]
2650     If ev_tol is not null, then it is the maximum absolute
2651     value of the plane equation evaluated at A,B,C.  Mathematically,
2652     ev_tol is zero.  Since these computations are performed with
2653     finite precision doubles, ev_tol is generally not zero.
2654 Returns:
2655   Unit normal
2656 */
2657 ON_DECL
2658 bool ON_GetTrianglePlaneEquation(
2659         const ON_3dPoint& A,
2660         const ON_3dPoint& B,
2661         const ON_3dPoint& C,
2662         double* a,
2663         double* b,
2664         double* c,
2665         double* d,
2666         double* evaluation_tol
2667         );
2668 
2669 #endif
2670