opennurbs_mesh.h
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  // The Rhino legacy mesher is the mesher used in Rhino 1, 2, 3, 4, 5, 6.
30  // {F15F67AA-4AF9-4B25-A3B8-517CEDDAB134}
32 
33  // {EB6F6F3F-F975-4546-9D1C-64E9423BEB7F}
34  static const ON_UUID PangolinMesherId;
35 
36  enum class MESH_STYLE : unsigned char
37  {
38  // All of these enum values must be in the range 0-255 because
39  // unsigned chars are use for storage in some locations.
40  unset_mesh_style = 0,
41  render_mesh_fast = 1, // Use ON_MeshParameters::FastRenderMesh
42  render_mesh_quality = 2, // Use ON_MeshParameters::QualityRenderMesh
43  // 3 - 8 reserved for future predefined render mesh styles
44  render_mesh_custom = 9,// Use ON_3dmSettings::m_CustomRenderMeshSettings
45  render_mesh_per_object = 10 // Use ON_Object::GetMeshParameters().
46  };
47 
48  static ON_MeshParameters::MESH_STYLE MeshStyleFromUnsigned(
49  unsigned int mesh_style_as_unsigned
50  );
51 
52 
53  //////////////////////////////////////////////////////////////
54  //
55  // The MESH_PARAMETER_ID enum values are used to identify
56  // mesh creation parameters.
57  //
58  enum class MESH_PARAMETER_ID : unsigned int
59  {
60  unspecified_mesh_parameter_id = 0,
61 
62  ////////////////////////////////////////////////////////
63  // BEGIN Legacy parameters.
64  //
65 
66  bComputeCurvature_parameter_id = 1,
67  bSimplePlanes_parameter_id = 2,
68  bRefine_parameter_id = 3,
69  bJaggedSeams_parameter_id = 4,
70  bDoublePrecision_parameter_id = 5,
71  mesher_parameter_id = 6,
72  texture_range_parameter_id = 7,
73  tolerance_parameter_id = 8,
74  relative_tolerance_parameter_id = 9,
75  min_tolerance_parameter_id = 10,
76  min_edge_length_parameter_id = 11,
77  max_edge_length_parameter_id = 12,
78  grid_aspect_ratio_parameter_id = 13,
79  grid_min_count_parameter_id = 14,
80  grid_max_count_parameter_id = 15,
81  grid_angle_parameter_id = 16,
82  grid_amplification_parameter_id = 17,
83  refine_angle_parameter_id = 18,
84  face_type_parameter_id = 19,
85  srf_domain_parameter_id = 20,
86  bClosedObjectPostProcess_id = 21,
87 
88  //
89  // END Legacy parameters.
90  ////////////////////////////////////////////////////////
91 
92  // UUID parameter identifying what mesher code created the mesh.
93  mesher_id = 22,
94 
95  ////////////////////////////////////////////////////////
96  // BEGIN Pangolin parameters
97  //
98 
99  crv_tess_min_num_segments_parameter_id = 23,
100  crv_tess_angle_tol_in_degrees_parameter_id = 24,
101  crv_tess_max_dist_between_points_parameter_id = 25, // Not same as 'max_edge_length_parameter_id' since
102  // 'curve_tess_max_dist_between_points' is only for
103  // curves, not surfaces.
104  crv_tess_min_parametric_ratio_parameter_id = 26,
105  bEvaluatorBasedTessellation_parameter_id = 27,
106  srf_tess_chord_height_parameter_id = 28, // Not same as 'tolerance_parameter_id' since
107  // 'surface_tess_chord_height' is only for
108  // surfaces, not curves.
109  srf_tess_angle_tol_in_degrees_parameter_id = 29,
110  srf_tess_max_edge_length_parameter_id = 30,
111  srf_tess_min_edge_length_parameter_id = 31,
112  srf_tess_min_edge_length_ratio_uv_parameter_id = 32,
113  srf_tess_max_aspect_ratio_parameter_id = 33,
114  smoothing_passes_parameter_id = 34,
115 
116  //
117  // END Pangolin parameters
118  ////////////////////////////////////////////////////////
119 
120  max_mesh_parameter_id
121  };
122 
123  static ON_MeshParameters::MESH_PARAMETER_ID MeshParameterIdFromUnsigned(
124  unsigned int mesh_parameter_id_as_unsigned
125  );
126 
127  /*
128  Description:
129  Mesh creationg parameters to create the default render mesh.
130  */
131  static
132  const ON_MeshParameters DefaultMesh;
133 
134  /*
135  Description:
136  Mesh creationg parameters to create the a render mesh
137  when meshing speed is prefered over mesh quality.
138  */
139  static
140  const ON_MeshParameters FastRenderMesh;
141 
142  /*
143  Description:
144  Mesh creationg parameters to create the a render mesh
145  when mesh quality is prefered over meshing speed.
146  */
147  static
148  const ON_MeshParameters QualityRenderMesh;
149 
150  /*
151  Description:
152  Mesh creationg parameters to create the default analysis mesh.
153  */
154  static
155  const ON_MeshParameters DefaultAnalysisMesh;
156 
157  /*
158  Description:
159  Get a value to use for tolerance based on the relative_tolerance
160  and actual size.
161  Parameters:
162  relative_tolerance - [in]
163  See m_relative_tolerance field
164  actual_size - [in]
165  Length of object's bounding box diagonal or some similar
166  measure of the object's 3d size.
167  Returns:
168  A value that can be used for m_tolerance if no
169  user specified value is available.
170  */
171  static
172  double ToleranceFromObjectSize( double relative_tolerance, double actual_size );
173 
174  /*
175  Description:
176  Get a value to use for minimum edge length base on max_edge_length
177  and tolerance settings.
178  Parameters:
179  max_edge_length - [in]
180  3d maximum edge length used to create mesh.
181  tolerance - [in]
182  3d distance tolerance used to create mesh.
183  Returns:
184  A value that can be used for m_min_edge_length if no
185  user specified value is available.
186  */
187  static
188  double MinimumEdgeLengthFromTolerance( double max_edge_length, double tolerance );
189 
190  ON_MeshParameters() = default;
191  ~ON_MeshParameters() = default;
192  ON_MeshParameters(const ON_MeshParameters&) = default;
193  ON_MeshParameters& operator=(const ON_MeshParameters&) = default;
194 
195  /*
196  Description:
197  Tool for provding a simple slider interface.
198  Parameters:
199  density - [in] 0.0 <= density <= 1.0
200  0 quickly creates coarse meshes.
201  1 slowly creates dense meshes.
202  min_edge_length - [in]
203  > 0.0 custom value
204  ON_UNSET_VALUE: for default (0.0001)
205  */
207  double density,
208  double min_edge_length = ON_UNSET_VALUE
209  );
210 
211  // C++ default works fine // ON_MeshParameters(const ON_MeshParameters& );
212  // C++ default works fine // ON_MeshParameters& operator=(const ON_MeshParameters&);
213 
214  void Dump( ON_TextLog& test_log ) const;
215 
216 
217  /*
218  */
219  static int Compare(
220  const ON_MeshParameters& a,
221  const ON_MeshParameters& b
222  );
223 
224  /*
225  Description:
226  Compares all meshing parameters that control mesh geometry.
227  Does not compare m_bCustomSettings, CustomSettingsEnabled(),
228  m_bComputeCurvature, m_bDoublePrecision, MinimumTolerance(),
229  m_texture_range, m_srf_domain0 and m_srf_domain1.
230  */
231  static int CompareGeometrySettings(
232  const ON_MeshParameters& a,
233  const ON_MeshParameters& b
234  );
235 
236  ON_SHA1_Hash ContentHash() const;
237  ON_SHA1_Hash GeometrySettingsHash() const;
238 
239  ON_UUID MesherId() const;
240  void SetMesherId(
241  ON_UUID
242  );
243 
244 
245  /*
246  Returns:
247  ON_MeshParameters::render_mesh_fast
248  ON_MeshParameters::FastRenderMesh and this have the same geometry settings
249  ON_MeshParameters::render_mesh_quality
250  ON_MeshParameters::QualityRenderMesh and this have the same geometry settings
251  ON_MeshParameters::render_mesh_custom
252  custom_mp is not null and has the same geometry settings
253  no_match_found_result
254  otherwise
255  */
256  const ON_MeshParameters::MESH_STYLE GeometrySettingsRenderMeshStyle(
257  const ON_MeshParameters* custom_mp,
258  ON_MeshParameters::MESH_STYLE no_match_found_result
259  ) const;
260 
261  /*
262  Returns:
263  n in the range 0 to 100, inclusive, when
264  (0 == ON_MeshParameters::CompareGeometrySettings(*this,ON_MeshParameters(n/100.0))
265  no_match_found_result:
266  otherwise
267  */
268  const int GeometrySettingsDensityPercentage(
269  int no_match_found_result
270  ) const;
271 
272  bool Write( ON_BinaryArchive& ) const;
273  bool Read( ON_BinaryArchive& );
274 
275  ON__UINT32 DataCRC(ON__UINT32) const;
276 
277  //////////////////////////////////////////////////////////////
278  //
279  // The CustomSettings() parameter applies when these mesh
280  // creation parameters specify how an object's mesh should
281  // be created and these parameters should override the
282  // the model or application default mesh creation parameters.
283  //
284  // When CustomSettings() is true, it indicates these mesh
285  // creation parameters are explictily set for the object
286  // and context in question and should override the model
287  // or application defaults.
288  //
289  // When CustomSettings() is false, it indicates these mesh
290  // creation parameters were inherited from from model or
291  // application defaults and any mesh created with these
292  // parameters should be updated when these parameters
293  // differ from the current model or application defaults.
294  //
295  const bool CustomSettings() const;
296  void SetCustomSettings(
297  bool bCustomSettings
298  );
299 
300  //////////////////////////////////////////////////////////////
301  //
302  // The CustomSettingsEnabled() value applies to mesh creation
303  // parameters that are on ON_3dmObjectAttributes and have
304  // CustomSettings() = true. In this situation:
305  //
306  // If CustomSettingsEnabled() is true, then the use of
307  // these mesh creation parameters is enabled.
308  //
309  // If CustomSettingsEnabled() is false, then these mesh
310  // creation parameters should be gnored.
311  //
312  const bool CustomSettingsEnabled() const;
313  void SetCustomSettingsEnabled(
314  bool bCustomSettingsEnabled
315  );
316 
317 
318  //////////////////////////////////////////////////////////////
319  //
320  // Meshing happens in two stages. The first stage creates a
321  // rectangular grid. The second stage refines the grid until
322  // the mesh meets all meshing requirements. The third stage
323  // combines coincident vertices if the resulting mesh is a composite.
324  //
325 
326 
327  // false - (default) - ON_Mesh::m_K[] not computed
328  // true - ON_Mesh::m_K[] computed bool ComputeCurvature() const;
329  const bool ComputeCurvature() const;
330  void SetComputeCurvature(
331  bool bComputeCurvature
332  );
333 
334  // false - (default) planar surfaces are meshed
335  // using the controls below.
336  // true - planar surfaces are meshed using
337  // minimal number of triangles and
338  // aspect/edge controls are ignored.
339  const bool SimplePlanes() const;
340  void SetSimplePlanes(
341  bool bSimplePlanes
342  );
343 
344 public:
345  // false - skip stage 2 mesh refinement step
346  // true - (default) do stage 2 mesh refinement step
347  const bool Refine() const;
348  void SetRefine(
349  bool bRefine
350  );
351 
352 public:
353  // false - (default) edges of meshes of joined
354  // b-rep faces match with no gaps or
355  // "T" joints.
356  // true - faces in b-reps are meshed independently.
357  // This is faster but results in gaps and
358  // "T" joints along seams between faces.
359  const bool JaggedSeams() const;
360  void SetJaggedSeams(
361  bool bJaggedSeams
362  );
363 
364 public:
365  // false - (default) the mesh vertices will be
366  // float precision values in the m_V[] array.
367  // true - The mesh vertices will be double precision
368  // values in the DoublePrecisionVertices()
369  // array. Float precision values will also
370  // be returned in the m_V[] array.
371  const bool DoublePrecision() const;
372  void SetDoublePrecision(
373  bool bDoublePrecision
374  );
375 
376  // 0 = slow mesher, 1 = fast mesher
377  const unsigned int Mesher() const;
378  void SetMesher(
379  unsigned int mesher
380  );
381 
382  // 1: unpacked, unscaled, normalized
383  // each face has a normalized texture range [0,1]x[0,1].
384  // The normalized coordinate is calculated using the
385  // entire surface domain. For meshes of trimmed
386  // surfaces when the active area is a small subset of
387  // the entire surface, there will be large regions of
388  // unsued texture space in [0,1]x[0,1]. When the 3d region
389  // being meshed is far from being sqaure-ish, there will be
390  // a substantual amount of distortion mapping [0,1]x[0,1]
391  // texture space to the 3d mesh.
392  //
393  // 2: packed, scaled, normalized (default)
394  // each face is assigned a texture range that is a
395  // subrectangle of [0,1]x[0,1]. The subrectangles are
396  // mutually disjoint and packed into into [0,1]x[0,1]
397  // in a way that minimizes distortion and maximizes the
398  // coverage of [0,1]x[0,1].
399  // When the surface or surfaces being meshed are trimmed,
400  // this option takes into account only the region of the
401  // base surface the mesh covers and uses as much of
402  // [0,1]x[0,1] as possible. unsigned int TextureRange() const;
403  const unsigned int TextureRange() const;
404  void SetTextureRange(
405  unsigned int texture_range
406  );
407  const bool TextureRangeIsValid() const;
408  void SetTextureRangePictureFrameHack();
409 
410  // If the object being meshed is closed, m_bClosedObjectPostProcess is true,
411  // m_bJaggedSeams = false, and the resultig mesh is not closed, then a post meshing process
412  // is applied to find and close gaps in the mesh. Typically the resulting mesh
413  // is not closed because the input object has a geometric flaw like loops in
414  // trimming curves.
415  const bool ClosedObjectPostProcess() const;
416  void SetClosedObjectPostProcess(
417  bool bClosedObjectPostProcess
418  );
419 
420  // These controls are used in both stages
421 
422  // approximate maximum distance from center of edge to surface
423  const double Tolerance() const;
424  void SetTolerance(
425  double tolerance
426  );
427 
428  /*
429  If 0.0 < RelativeTolerance() < 1.0,
430  then the maximum distance from the
431  center of an edge to the surface will
432  be <= T, where T is the larger of
433  (MinimumTolerance(),d*RelativeTolerance()),
434  where d is an esimate of the size of the
435  object being meshed.
436  */
437  const double RelativeTolerance() const;
438  void SetRelativeTolerance(
439  double relative_tolerance
440  );
441 
442  const double MinimumTolerance() const;
443  void SetMinimumTolerance(
444  double minimum_tolerance
445  );
446 
447  // edges shorter than MinimumEdgeLength() will
448  // not be split even if the do not meet other
449  // meshing requirements
450  const double MinimumEdgeLength() const;
451  void SetMinimumEdgeLength(
452  double minimum_edge_length
453  );
454 
455  /*
456  Returns:
457  SubD display mesh density.
458  Example:
459  Use ON_MeshParameters to control the density of a SubD limit mesh.
460  ON_MeshParameters mp = ...;
461  ON_Mesh* mesh = subd->GetLimitSurfaceMesh(
462  ON_SubDDisplayParameters::CreateFromDisplayDensity( mp.SubDDisplayMeshDensity() ),
463  nullptr
464  );
465  */
466  unsigned int SubDDisplayMeshDensity() const;
467 
468 public:
469  // edges longer than MaximumEdgeLength() will
470  // be split even when they meet all other
471  // meshing requirements
472  const double MaximumEdgeLength() const;
473  void SetMaximumEdgeLength(
474  double maximum_edge_length
475  );
476 
477  ////////////////////////////////////////////////////////////////////////////////////
478  //
479  // These controls are used during stage 1 to generate the grid
480  //
481 
482 
483  // desired aspect ratio of quads in grid
484  // 0.0 = any aspect ratio is acceptable
485  // values >0 and < sqrt(2) are treated as sqrt(2)
486  const double GridAspectRatio() const;
487  void SetGridAspectRatio(
488  double grid_aspect_ratio
489  );
490 
491  // minimum number of quads in initial grid
492  const int GridMinCount() const;
493  void SetGridMinCount(
494  int grid_min_count
495  );
496 
497  // desired masimum number of quads in initial grid
498  const int GridMaxCount() const;
499  void SetGridMaxCount(
500  int grid_max_count
501  );
502 
503  // maximum angle (radians) between surface
504  // normal evaluated at adjacent vertices.
505  // 0.0 is treated as pi.
506  const double GridAngleRadians() const;
507  void SetGridAngleRadians(
508  double grid_angle_radians
509  );
510 
511  // maximum angle (degrees) between surface
512  // normal evaluated at adjacent vertices.
513  // 0.0 is treated as 180.0.
514  const double GridAngleDegrees() const;
515  void SetGridAngleDegrees(
516  double grid_angle_degrees
517  );
518 
519  // The parameters above generate a grid.
520  // If you want fewer quads, set m_grid_amplification
521  // to a value < 1. If you want more quads,
522  // set m_grid_amplification to a value > 1.
523  // default = 1 and values <= 0 are treated as 1.
524  const double GridAmplification() const;
525  void SetGridAmplification(
526  double grid_amplification
527  );
528 
529  ////////////////////////////////////////////////////////////////////////////
530  //
531  // These controls are used during stage 2 to refine the grid
532  //
533 
534 
535  // (in radians) maximum angle in radians between
536  // surface normal evaluated at adjacent vertices.
537  const double RefineAngleRadians() const;
538  void SetRefineAngleRadians(
539  double refine_angle_radians
540  );
541  const double RefineAngleDegrees() const;
542  void SetRefineAngleDegrees(
543  double refine_angle_degrees
544  );
545 
546  ////////////////////////////////////////////////////////////////////////////
547  //
548  // These controls are used during stage 3
549  //
550 
551  // 0 = mixed triangle and quads
552  // 1 = all triangles
553  // 2 = all quads
554  const unsigned int FaceType() const;
555  void SetFaceType(
556  unsigned int face_type
557  );
558 
559 
560 private:
561  void Internal_SetBoolHelper(bool b, bool* dest);
562  void Internal_SetCharHelper(unsigned int u, unsigned char minc, unsigned char maxc, unsigned char*);
563  void Internal_SetDoubleHelper(double x, double minx, double maxx, double* dest);
564  void Internal_SetIntHelper(int i, int mini, int maxi, int* dest);
565 
566 private:
567  //////////////////////////////////////////////////////////
568  //
569  // BEGIN Rhino Legacy parameters
570  //
571  bool m_bCustomSettings = false;
572  bool m_bCustomSettingsEnabled = true;
573  bool m_bComputeCurvature = false;
574  bool m_bSimplePlanes = false;
575 
576  bool m_bRefine = true;
577  bool m_bJaggedSeams = false;
578  bool m_bDoublePrecision = false;
579  bool m_bClosedObjectPostProcess = false;
580 
581  ON_UUID m_mesher_id = ON_nil_uuid;
582 
583  unsigned char m_mesher = 0;
584  unsigned char m_texture_range = 2;
585  unsigned char m_face_type = 0;
586 
587  unsigned char m_reserved1 = 0;
588 
589  int m_grid_min_count = 0;
590  int m_grid_max_count = 0;
591  mutable ON_SHA1_Hash m_geometry_settings_hash = ON_SHA1_Hash::ZeroDigest;
592 
593  ON__UINT32 m_reserved2 = 0;
594 
595  double m_tolerance = 0.0;
596  double m_relative_tolerance = 0.0;
597  double m_min_tolerance = 0.0;
598  double m_min_edge_length = 0.0001;
599  double m_max_edge_length = 0.0;
600  double m_grid_aspect_ratio = 6.0;
601  double m_grid_angle_radians = 20.0*ON_PI/180.0;
602  double m_grid_amplification = 1.0;
603  double m_refine_angle_radians = 20.0*ON_PI/180.0;
604  //
605  // BEGIN Rhino Legacy parameters
606  //
607  //////////////////////////////////////////////////////////
608 
609 private:
610  bool m_reserved3 = false;
611  bool m_reserved4 = false;
612 
613 private:
614  //////////////////////////////////////////////////////////
615  //
616  // BEGIN Pangolin parameters
617  //
618 
619  bool m_bEvaluatorBasedTessellation = false;
620  int m_curve_tess_min_num_segments = 0;
621  double m_curve_tess_angle_tol_in_degrees = 20.0;
622  double m_curve_tess_max_dist_between_points = 0.0;
623  double m_curve_tess_min_parametric_ratio = 0.00001;
624  double m_surface_tess_angle_tol_in_degrees = 20.0;
625  double m_surface_tess_max_edge_length = 0.0;
626  double m_surface_tess_min_edge_length = 0.0;
627  double m_surface_tess_min_edge_length_ratio_uv = 0.0001;
628  double m_surface_tess_max_aspect_ratio = 0.0;
629  int m_smoothing_passes = 0;
630 
631 private:
632  void Internal_AccumulatePangolinParameters(
633  const ON_MeshParameters& pangolin_defaults,
634  class ON_SHA1& sha1
635  ) const;
636 
637  //
638  // END Pangolin parameters
639  //
640  //////////////////////////////////////////////////////////
641 
642 private:
643  ON__UINT_PTR m_reserved5 = 0;
644 };
646 ON_DECL
647 bool operator!=(const ON_MeshParameters& a, const ON_MeshParameters& b);
648 
649 ON_DECL
650 bool operator==(const ON_MeshParameters& a, const ON_MeshParameters& b);
651 
652 class ON_CLASS ON_MeshCurvatureStats
653 {
654 public:
658  ON_MeshCurvatureStats& operator=(const ON_MeshCurvatureStats&);
659 
660  void Destroy();
661  void EmergencyDestroy();
662 
663  bool Set( ON::curvature_style,
664  int, // Kcount,
665  const ON_SurfaceCurvature*, // K[]
666  const ON_3fVector*, // N[] surface normals needed for normal sectional curvatures
667  double = 0.0 // if > 0, value is used for "infinity"
668  );
669 
670  bool Write( ON_BinaryArchive& ) const;
671  bool Read( ON_BinaryArchive& );
673  ON::curvature_style m_style;
674 
675  double m_infinity; // curvature values >= this are considered infinite
676  // and not used to compute the m_average or m_adev
677  int m_count_infinite; // number of "infinte" values
678  int m_count; // count of "finite" values
679  double m_mode; // mode of "finite" values
680  double m_average; // average of "finite" values
681  double m_adev; // average deviation of "finite" values
682 
683  ON_Interval m_range;
684 };
685 
686 ///////////////////////////////////////////////////////////////////////////////
687 //
688 // Class ON_MeshTopology
689 //
690 
692 {
693  // m_tope_count = number of topological edges that begin or
694  // end at this topological vertex.
695  int m_tope_count;
696 
697  // m_topei[] is an array of length m_tope_count with the indices
698  // of the topological edges that begin or end at this topological
699  // vertex. Generally, these edges are listed in no particular
700  // order. If you want the edges listed "radially", then call
701  // ON_MeshTopology::SortVertexEdges.
702  const int* m_topei;
704  // m_v_count = number of ON_Mesh vertices that correspond to
705  // this topological vertex.
706  int m_v_count;
707 
708  // m_vi[] is an array of length m_v_count with the indices of the
709  // ON_Mesh vertices that correspond to this topological vertex.
710  const int* m_vi;
711 };
712 
714 {
715  // m_topvi[] = indices of the topological verteices where the
716  // edge begins and ends.
717  int m_topvi[2];
718 
719  // m_topf_count = number of topological faces tat share this topological edge
720  int m_topf_count;
721 
722  // m_topfi[] is an array of length m_topf_count with the indices of the
723  // topological faces that share this topological edge.
724  const int* m_topfi;
725 };
726 
727 struct ON_CLASS ON_MeshTopologyFace
728 {
729  /*
730  m_topei[] = indices of the topological edges that bound the face.
731  If m_topei[2] = m_topei[3], then the face is a triangle, otherwise
732  the face is a quad.
733 
734  NOTE WELL:
735  The topological edge with index m_topei[k] ENDS at the
736  vertex corresponding to ON_MeshFace.vi[k]. So, ...
737 
738  If the face is a quad, (ON_MeshFace.vi[2]!=ON_MeshFace.vi[3]),
739  the topological edge with index m_topei[0] STARTS at
740  ON_MeshFace.vi[3] and ENDS at ON_MeshFace.vi[0],
741  the topological edge with index m_topei[1] STARTS at
742  ON_MeshFace.vi[0] and ENDS at ON_MeshFace.vi[1],
743  the topological edge with index m_topei[2] STARTS at
744  ON_MeshFace.vi[1] and ENDS at ON_MeshFace.vi[2], and
745  the topological edge with index m_topei[3] STARTS at
746  ON_MeshFace.vi[2] and ENDS at ON_MeshFace.vi[3],
747 
748  If the face is a triangle, (ON_MeshFace.vi[2]==ON_MeshFace.vi[3]),
749  the topological edge with index m_topei[0] STARTS at
750  ON_MeshFace.vi[2] and ENDS at ON_MeshFace.vi[0],
751  the topological edge with index m_topei[1] STARTS at
752  ON_MeshFace.vi[0] and ENDS at ON_MeshFace.vi[1],
753  the topological edge with index m_topei[2] STARTS at
754  ON_MeshFace.vi[1] and ENDS at ON_MeshFace.vi[2].
755  */
756  int m_topei[4];
758  /*
759  If m_reve[i] is 0, then the orientation of the edge matches the
760  orientation of the face. If m_reve[i] is 1, then the orientation
761  of the edge is opposite that of the face.
762  */
763  char m_reve[4];
764 
765  /*
766  Description:
767  A topological mesh face is a valid triangle if m_topei[0],
768  m_topei[1], m_topei[2] are distinct edges and
769  m_topei[3]=m_topei[2].
770  Returns:
771  True if face is a triangle.
772  */
773  bool IsTriangle() const;
774 
775  /*
776  Description:
777  A topological mesh face is a valid quad if m_topei[0],
778  m_topei[1], m_topei[2], and m_topei[3] are distinct edges.
779  Returns:
780  True if face is a quad.
781  */
782  bool IsQuad() const;
783 
784  /*
785  Description:
786  A topological mesh face is valid if m_topei[0], m_topei[1],
787  and m_topei[2] are mutually distinct, and m_topei[3] is
788  either equal to m_topei[2] or mutually distinct from the
789  first three indices.
790  Returns:
791  True if face is valid.
792  */
793  bool IsValid( ) const;
794 };
795 
796 class ON_CLASS ON_MeshFace
797 {
798 public:
799  static const ON_MeshFace UnsetMeshFace; // all vi[] values are -1.
800 
801 
802  int vi[4]; // vertex index - vi[2]==vi[3] for tirangles
803 
804  /*
805  Returns:
806  True if vi[2] == vi[3];
807  Remarks:
808  Assumes the face is valid.
809  */
810  bool IsTriangle() const;
811 
812  /*
813  Returns:
814  True if vi[2] != vi[3];
815  Remarks:
816  Assumes the face is valid.
817  */
818  bool IsQuad() const;
819 
820  /*
821  Description:
822  Determine if a face is valid by checking that the vertices
823  are distinct.
824  Parameters:
825  mesh_vertex_count - [in]
826  number of vertices in the mesh
827  V - [in]
828  optional array of mesh_vertex_count vertex locations.
829  Returns:
830  true
831  The face is valid.
832  false
833  The face is not valid. It may be possible to repair the
834  face by calling ON_MeshFace::Repair().
835  */
836  bool IsValid(
837  int mesh_vertex_count
838  ) const;
839  bool IsValid(
840  unsigned int mesh_vertex_count
841  ) const;
842  bool IsValid(
843  int mesh_vertex_count,
844  const ON_3fPoint* V
845  ) const;
846  bool IsValid(
847  int mesh_vertex_count,
848  const ON_3dPoint* V
849  ) const;
850 
851  /*
852  Description:
853  Reverses the order of the vertices in v[].
854  vi[0] is not changed.
855  */
856  void Flip();
857 
858  /*
859  Description:
860  If IsValid() returns false, then you can use Repair()
861  to attempt to create a valid triangle.
862  Parameters:
863  mesh_vertex_count - [in]
864  number of vertices in the mesh
865  V - [in]
866  optional array of mesh_vertex_count vertex locations.
867  Returns:
868  true
869  repair was successful and v[0], v[1], vi[2] have distinct valid
870  values and v[2] == v[3].
871  false
872  this face's vi[] values cannot be repaired
873  */
874  bool Repair(
875  int mesh_vertex_count
876  );
877  bool Repair(
878  int mesh_vertex_count,
879  const ON_3fPoint* V
880  );
881  bool Repair(
882  int mesh_vertex_count,
883  const ON_3dPoint* V
884  );
885 
886  /*
887  Description:
888  Compute the face normal
889  Parameters:
890  dV - [in] double precision vertex array for the mesh
891  fV - [in] float precision vertex array for the mesh
892  FN - [out] face normal
893  Returns:
894  true if FN is valid.
895  */
896  bool ComputeFaceNormal( const ON_3dPoint* dV, ON_3dVector& FN ) const;
897  bool ComputeFaceNormal( const ON_3fPoint* fV, ON_3dVector& FN ) const;
898  bool ComputeFaceNormal( const class ON_3dPointListRef& vertex_list, ON_3dVector& FN ) const;
899 
900  /*
901  Parameters:
902  planar_tolerance - [in]
903  If planar_tolerance >= 0 and
904  (maximum plane equation value - minimum plane equation value) > planar_tolerance,
905  then false is returned.
906  angle_tolerance_radians - [in]
907  If angle_tolerance_radians >= 0.0 and the angle between opposite
908  corner normals is > angle_tolerance_radians, then false is returned.
909  A corner normal is the normal to the triangle formed by two
910  adjacent edges and the diagonal connecting their endpoints.
911  A quad has four corner normals.
912  Passing in ON_PI/2 is a good way will result in false being
913  returned for non-convex quads
914  face_plane_equation - [out]
915  If not null, the equation used to test planarity is returned here.
916  Returns:
917  True if the face is planar
918  */
919  bool IsPlanar(
920  double planar_tolerance,
921  double angle_tolerance_radians,
922  const class ON_3dPointListRef& vertex_list,
923  ON_PlaneEquation* face_plane_equation
924  ) const;
925 
926  /*
927  Description:
928  Get corner normals.
929  Parameters:
930  vertex_list - [in]
931  corner_normals[4] - [out]
932  For a triangle, all values are identical.
933  If a corner normal cannot be calculated, ON_3dVector::UnsetVector
934  is returned.
935  Returns:
936  Number of corner normals that are valid.
937  */
938  unsigned int GetCornerNormals(
939  const class ON_3dPointListRef& vertex_list,
940  ON_3dVector corner_normals[4]
941  ) const;
942 
943  bool GetPlaneEquation(
944  const class ON_3dPointListRef& vertex_list,
945  ON_PlaneEquation& face_plane_equation
946  ) const;
947 
948 };
949 
950 
951 class ON_CLASS ON_MeshTriangle
952 {
953 public:
954  static const ON_MeshTriangle UnsetMeshTriangle; // all vi[] values are ON_UNSET_UINT_INDEX.
955 
956  unsigned int m_vi[3]; // vertex index list
957 
958  /*
959  Description:
960  Determine if a triangle is valid by checking that the vertices
961  are distinct.
962  Parameters:
963  mesh_vertex_count - [in]
964  number of vertices in the mesh
965  vertex_list - [in]
966  optional list of mesh vertex locations.
967  Returns:
968  true
969  The triangle is valid.
970  false
971  The triangle is not valid.
972  */
973  bool IsValid(
974  size_t mesh_vertex_count
975  ) const;
976 
977  bool IsValid(
978  size_t mesh_vertex_count,
979  const class ON_3fPoint* vertex_list
980  ) const;
981 
982  bool IsValid(
983  size_t mesh_vertex_count,
984  const class ON_3dPoint* vertex_list
985  ) const;
986 
987  bool IsValid(
988  const class ON_3dPointListRef& vertex_list
989  ) const;
990 
991  /*
992  Description:
993  Swaps the values of m_vi[1] and m_vi[2]. m_vi[0] is not changed.
994  */
995  void Flip();
996 
997 
998  /*
999  Description:
1000  Compute the triangle normal
1001  Parameters:
1002  dV - [in] double precision vertex array for the mesh
1003  fV - [in] float precision vertex array for the mesh
1004  vertex_list - [in] vertex locations
1005  triangle_normal - [out] triangle normal
1006  Returns:
1007  true if triangle_normal is valid.
1008  */
1009  bool GetTriangleNormal(
1010  const class ON_3dPoint* dV,
1011  class ON_3dVector& triangle_normal
1012  ) const;
1013 
1014  bool GetTriangleNormal(
1015  const class ON_3fPoint* fV,
1016  class ON_3dVector& triangle_normal
1017  ) const;
1018 
1019  bool GetTriangleNormal(
1020  const class ON_3dPointListRef& vertex_list,
1021  class ON_3dVector& triangle_normal
1022  ) const;
1023 
1024  static bool GetTriangleNormal(
1025  ON_3dPoint point0,
1026  ON_3dPoint point1,
1027  ON_3dPoint point2,
1028  class ON_3dVector& triangle_normal
1029  );
1030 
1031 };
1032 
1033 class ON_CLASS ON_MeshFaceList
1034 {
1035 public:
1036  ON_MeshFaceList()
1037  : m_bQuadFaces(false)
1038  , m_face_count(0)
1039  , m_face_stride(0)
1040  , m_faces(0)
1041  {}
1042 
1044  const ON_Mesh* mesh
1045  );
1046 
1047  static const ON_MeshFaceList EmptyFaceList;
1048 
1049  unsigned int SetFromTriangleList(
1050  size_t triangle_count,
1051  size_t triangle_stride,
1052  const unsigned int* triangles
1053  );
1055  unsigned int SetFromQuadList(
1056  size_t quad_count,
1057  size_t quad_stride,
1058  const unsigned int* quads
1059  );
1060 
1061  unsigned int SetFromMesh(
1062  const ON_Mesh* mesh
1063  );
1064 
1065  inline const unsigned int* Fvi(unsigned int face_index) const
1066  {
1067  return (face_index < m_face_count) ? (m_faces + (face_index*m_face_stride)) : 0;
1068  }
1069 
1070  inline unsigned int* QuadFvi(unsigned int face_index, unsigned int buffer[4]) const
1071  {
1072  if ( face_index < m_face_count )
1073  {
1074  const unsigned int* p = m_faces + (face_index*m_face_stride);
1075  buffer[0] = *p;
1076  buffer[1] = *(++p);
1077  buffer[2] = *(++p);
1078  buffer[3] = m_bQuadFaces ? *(++p) : buffer[2];
1079  }
1080  else
1081  {
1082  buffer[0] = buffer[1] = buffer[2] = buffer[3] = 0;
1083  }
1084  return buffer;
1085  }
1086 
1088  inline bool IsQuad(unsigned int face_index) const
1089  {
1090  if ( m_bQuadFaces && face_index < m_face_count )
1091  {
1092  const unsigned int* p = m_faces + (face_index*m_face_stride);
1093  return p[2] != p[3];
1094  }
1095  return false;
1096  }
1097 
1098  inline unsigned int FaceCount() const
1099  {
1100  return m_face_count;
1101  }
1102 
1103  inline unsigned int FaceVertexCount() const
1104  {
1105  return m_bQuadFaces?4:3;
1106  }
1107 
1108  size_t FaceStride() const
1109  {
1110  return m_face_stride;
1111  }
1112 
1113  /*
1114  Description:
1115  Get the minimum and maximum vertex indices referenced by a face in the list.
1116  Parameters:
1117  minimum_valid_vertex_index - [in]
1118  Any face with a vertex index < minimum_valid_vertex_index will be ignored.
1119  maximum_valid_vertex_index - [in]
1120  Any face with a vertex index > maximum_valid_vertex_index will be ignored.
1121  minimum_vertex_index - [out]
1122  maximum_vertex_index - [out]
1123  If there are no valid faces, then both output values are 0.
1124  Returns:
1125  Number of valid faces.
1126  */
1127  unsigned int GetVertexIndexInterval(
1128  unsigned int minimum_valid_vertex_index,
1129  unsigned int maximum_valid_vertex_index,
1130  unsigned int* minimum_vertex_index,
1131  unsigned int* maximum_vertex_index
1132  ) const;
1133 
1134 private:
1135  bool m_bQuadFaces;
1136  unsigned int m_face_count;
1137  unsigned int m_face_stride;
1138  const unsigned int* m_faces;
1139 };
1140 
1141 class ON_CLASS ON_MeshVertexFaceMap
1142 {
1143 public:
1144  ON_MeshVertexFaceMap() ON_NOEXCEPT;
1147  ON_MeshVertexFaceMap& operator=(const ON_MeshVertexFaceMap&);
1148 
1149 #if defined(ON_HAS_RVALUEREF)
1150  // rvalue copy constructor
1151  ON_MeshVertexFaceMap( ON_MeshVertexFaceMap&& ) ON_NOEXCEPT;
1152  ON_MeshVertexFaceMap& operator=( ON_MeshVertexFaceMap&& ) ON_NOEXCEPT;
1153 #endif
1154 
1155  bool SetFromMesh(
1156  const ON_Mesh* mesh,
1157  bool bMapInvalidFaces
1158  );
1159 
1160  bool SetFromFaceList(
1161  unsigned int vertex_count,
1162  const class ON_MeshFaceList& face_list,
1163  bool bMapInvalidFaces
1164  );
1165 
1166  void Destroy();
1167 
1168  /*
1169  Returns:
1170  Number a vertices.
1171  */
1172  unsigned int VertexCount() const;
1173 
1174  /*
1175  Returns:
1176  Number a faces.
1177  */
1178  unsigned int FaceCount() const;
1179 
1180  /*
1181  Parameters:
1182  vertex_index - [in]
1183  Index of a vertex.
1184  Returns:
1185  The number of faces that reference the vertex.
1186  Remarks:
1187  If vertex_index is out of range, then zero is returned.
1188  */
1189  unsigned int VertexFaceCount(
1190  unsigned int vertex_index
1191  ) const;
1192 
1193  /*
1194  Parameters:
1195  vertex_index - [in]
1196  Index of a vertex.
1197  Returns:
1198  An array of indices of faces that reference the vertex.
1199  The array has length VertexFaceCount(vertex_index).
1200  When the value of VertexFaceCount(vertex_index) is zero,
1201  this function returns a null pointer.
1202  Remarks:
1203  If vertex_index is out of range, then null is returned.
1204  */
1205  const unsigned int* VertexFaceList(
1206  unsigned int vertex_index
1207  ) const;
1208 
1209  /*
1210  Description:
1211  Expert user function for situations where rapid access to the
1212  vertex face list information is required.
1213  Returns:
1214  An array of VertexCount() unsigned int arrays that list the
1215  indices of faces that reference each vertex.
1216  VertexFaceMap()[vertex_index] is null if zero faces reference the
1217  indicated vertex. Otherwise, VertexFaceMap()[vertex_index][0] is
1218  the number of faces that reference the vertex and
1219  VertexFaceMap()[vertex_index][1,...,n] are the indices of those faces,
1220  where "n" is the value of VertexFaceMap()[vertex_index][0].
1221  */
1222  const unsigned int *const* VertexFaceMap() const;
1223 
1224 private:
1225  unsigned int m_vertex_count;
1226  unsigned int m_face_count;
1227  const unsigned int *const* m_vertex_face_map;
1228  void* m_p;
1229  void m_copy(const ON_MeshVertexFaceMap&);
1230  void* m_alloc(size_t);
1231 };
1232 
1233 
1234 class ON_CLASS ON_MeshNgonBuffer
1235 {
1236  // An ON_MeshNgonBuffer provides memory for
1237  // creating an ON_MeshNgon that is a triangle or quad.
1238 public:
1240  const class ON_MeshNgon* Ngon() const;
1241 
1242  const class ON_MeshNgon* CreateFromMeshFaceIndex(
1243  const class ON_Mesh* mesh,
1244  unsigned int face_index
1245  );
1246 
1247  const class ON_MeshNgon* CreateFromMeshFace(
1248  const class ON_MeshFace* mesh_face,
1249  unsigned int face_index
1250  );
1251 
1252  const class ON_MeshNgon* CreateFromTriangle(
1253  const unsigned int triangle_vertex_indices[3],
1254  unsigned int face_index
1255  );
1256 
1257  const class ON_MeshNgon* CreateFromQuad(
1258  const unsigned int quad_vertex_indices[4],
1259  unsigned int face_index
1260  );
1261 
1262 public:
1263  ON__UINT_PTR m_ngon_buffer[10];
1264 };
1265 
1266 class ON_CLASS ON_MeshNgon
1267 {
1268 public:
1269  // Number of N-gon corners (N >= 3)
1270  unsigned int m_Vcount; // number of vertices and sides (the "n" in n-gon)
1271  unsigned int m_Fcount; // number of faces
1272 
1273  // N-gon vertex indices
1274  // An array of m_Vcount indices into the mesh's m_V[] vertex array.
1275  // Unset elements have the value ON_UNSET_UINT_INDEX. If the ngon
1276  // in managed by an ON_NgonAllocator, then the memory for m_vi[]
1277  // is also managed by that ON_NgonAllocator.
1278  unsigned int* m_vi;
1279 
1280  // N-gon face indices
1281  // An array of m_Fcount indices into the mesh's m_F[] face array.
1282  // Unset elements have the value ON_UNSET_UINT_INDEX. If the ngon
1283  // in managed by an ON_NgonAllocator, then the memory for m_fi[]
1284  // is also managed by that ON_NgonAllocator.
1285  unsigned int* m_fi;
1286 
1287  /*
1288  Returns:
1289  0: This n-gon is not managed by an ON_MeshNgonAllocator.
1290  >=0: The maximum capcity (maximum m_Vcount+m_Fcount) for this N-gon
1291  */
1292  unsigned int Capacity() const;
1293 
1294  static int Compare(
1295  const ON_MeshNgon* A,
1296  const ON_MeshNgon* B
1297  );
1298 
1299  /*
1300  Returns:
1301  32-bit cyclic redundancy check that can be used as a hash code.
1302  */
1303  ON__UINT32 CRC32() const;
1304 
1305  /*
1306  Returns:
1307  A SHA-1 has of the vertex and face indices.
1308  */
1309  ON_SHA1_Hash ContentHash() const;
1310 
1311  /*
1312  Parameters:
1313  mesh_face_list - [in]
1314  faces referenced by this n-gon.
1315  Returns:
1316  Total number of boundary edges, including interior edges.
1317  */
1318  unsigned int BoundaryEdgeCount(
1319  const ON_MeshFaceList& mesh_face_list
1320  ) const;
1321 
1322  /*
1323  Parameters:
1324  mesh - [in]
1325  mesh referenced by this n-gon.
1326  Returns:
1327  Total number of boundary edges, including interior edges.
1328  */
1329  unsigned int BoundaryEdgeCount(
1330  const ON_Mesh* mesh
1331  ) const;
1332 
1333  /*
1334  Returns:
1335  Total number of outer boundary edges.
1336  */
1337  unsigned int OuterBoundaryEdgeCount() const;
1338 
1339  /*
1340  Pamameters:
1341  mesh_face_list - [in]
1342  ON_Mesh face list.
1343  bPermitHoles - [in]
1344  true if the ngon is permitted to have interior holes
1345  false otherwise.
1346  Description:
1347  Determine if the ngon's boundary orientation matches that of the set of faces it is made from.
1348  Returns:
1349  1: The ngon does not have holes, the ngon's faces are compatibly oriented,
1350  and the ngon's outer boundary orientation matches the faces' orientation.
1351  -1: The ngon does not have holes, the ngon's faces are compatibly oriented,
1352  and the ngon's outer boundary orientation is opposite the faces' orientation.
1353  0: Otherwise. The ngon may be invalid, have holes, the ngon's faces may not be compatibly oriented,
1354  the ngons edges may not have a consistent orientation with respect to the faces, or some other issue.
1355  */
1356  int Orientation(
1357  const ON_MeshFaceList& mesh_face_list,
1358  bool bPermitHoles
1359  ) const;
1360 
1361  /*
1362  Pamameters:
1363  mesh_face_list - [in]
1364  ON_Mesh face list.
1365  bPermitHoles - [in]
1366  true if the ngon is permitted to have interior holes
1367  false otherwise.
1368  Description:
1369  Determine if the ngon's boundary orientation matches that of the set of faces it is made from.
1370  Returns:
1371  1: The ngon does not have holes, the ngon's faces are compatibly oriented,
1372  and the ngon's outer boundary orientation matches the faces' orientation.
1373  -1: The ngon does not have holes, the ngon's faces are compatibly oriented,
1374  and the ngon's outer boundary orientation is opposite the faces' orientation.
1375  0: Otherwise. The ngon may be invalid, have holes, the ngon's faces may not be compatibly oriented,
1376  the ngons edges may not have a consistent orientation with respect to the faces, or some other issue.
1377  */
1378  int Orientation(
1379  const ON_Mesh* mesh,
1380  bool bPermitHoles
1381  ) const;
1382 
1383  /*
1384  Description:
1385  Reverse the order of the m_vi[] array.
1386  */
1387  void ReverseOuterBoundary();
1388 
1389  /*
1390  Description:
1391  Use the ngon m_vi[] array to get a list of 3d points from
1392  mesh_vertex_list.
1393  Parameters:
1394  mesh_vertex_list - [in]
1395  bAppendStartPoint - [in]
1396  If true, the initial point in the boundary will be added
1397  as the first point of ngon_boundary_points[] and then
1398  added again as the last point of ngon_boundary_points[].
1399  This is useful when you need a closed polyline.
1400  ngon_boundary_points - [out]
1401  An array of ngon->m_Vcount + (bAppendStartPoint ? 1 : 0)
1402  points.
1403  Returns:
1404  Number of points added to ngon_boundary_points[] or 0 if invalid
1405  input is encountered.
1406  */
1407  unsigned int GetOuterBoundaryPoints(
1408  const class ON_3dPointListRef& mesh_vertex_list,
1409  bool bAppendStartPoint,
1410  ON_SimpleArray<ON_3dPoint>& ngon_boundary_points
1411  ) const;
1412 
1413  /*
1414  Description:
1415  Use the ngon m_vi[] array to get a list of 3d points from
1416  mesh_vertex_list.
1417  Parameters:
1418  mesh_vertex_list - [in]
1419  bAppendStartPoint - [in]
1420  If true, the initial point in the boundary will be added
1421  as the first point of ngon_boundary_points[] and then
1422  added again as the last point of ngon_boundary_points[].
1423  This is useful when you need a closed polyline.
1424  ngon_boundary_points - [out]
1425  An array of ngon->m_Vcount + (bAppendStartPoint ? 1 : 0) points
1426  is returned in ngon_boundary_points[]. The caller must insure
1427  that ngon_boundary_points[] has room for this many elements.
1428  Returns:
1429  Number of points added to ngon_boundary_points[] or 0 if invalid
1430  input is encountered.
1431  */
1432  unsigned int GetOuterBoundaryPoints(
1433  const class ON_3dPointListRef& mesh_vertex_list,
1434  bool bAppendStartPoint,
1435  ON_3dPoint* ngon_boundary_points
1436  ) const;
1437 
1438 
1439  /*
1440  Description:
1441  Use the ngon m_fi[] array to get a list of ngon boundary sides.
1442  Parameters:
1443  mesh_face_list - [in]
1444  ngon_boundary_sides - [out]
1445  ngon_boundary_sides[i]/8 = ON_MeshNon.m_fi[] array index
1446  ngon_boundary_sides[i]%4 = side index
1447  side index 0 identifies the side that runs from the first face
1448  vertex to the second face vertex.
1449  ngon_boundary_sides[i]&4 != 0 means the face side is reversed
1450  when used as an ngon boundary segment.
1451  Returns:
1452  Number of elements added to ngon_boundary_sides[] or 0 if invalid
1453  input is encountered.
1454  */
1455  unsigned int GetBoundarySides(
1456  const class ON_MeshFaceList& mesh_face_list,
1457  ON_SimpleArray<unsigned int>& ngon_boundary_sides
1458  ) const;
1459 
1460 
1461  //////////////////////////////////////////////////////////////
1462  //
1463  // Tools for finding a making n-gons
1464  //
1465  static unsigned int FindPlanarNgons(
1466  const class ON_3dPointListRef& vertex_list,
1467  const class ON_MeshFaceList& face_list,
1468  const unsigned int *const* vertex_face_map,
1469  double planar_tolerance,
1470  unsigned int minimum_ngon_vertex_count,
1471  unsigned int minimum_ngon_face_count,
1472  bool bAllowHoles,
1473  class ON_MeshNgonAllocator& NgonAllocator,
1476  );
1477 
1478  /*
1479  Description:
1480  Get a list of vertices that form the boundary of a set of faces.
1481  Parameters:
1482  mesh_vertex_list - [in]
1483  mesh_face_list - [in]
1484  vertex_face_map - [in]
1485  null or a vertex map made from the information in
1486  mesh_vertex_list and mesh_face_list.
1487  ngon_fi_count - [in]
1488  length of ngon_fi[] array
1489  ngon_fi - [in]
1490  An array of length ngon_fi_count that contains the indices
1491  of the faces that form the ngon.
1492  ngon_vi - [out]
1493  An array of vertex indices that make the ngon boundary.
1494  Returns:
1495  Number of vertices in the ngon outer boundary or 0 if the input is
1496  not valid.
1497  */
1498  static unsigned int FindNgonOuterBoundary(
1499  const class ON_3dPointListRef& mesh_vertex_list,
1500  const class ON_MeshFaceList& mesh_face_list,
1501  const unsigned int *const* vertex_face_map,
1502  size_t ngon_fi_count,
1503  const unsigned int* ngon_fi,
1505  );
1506 
1507  /*
1508  Description:
1509  Create an ngon pointer that contains a triangle (3-gon)
1510  or quad (4-gon) from a mesh face.
1511  This is handy when your code needs to handle both
1512  ngons and faces because it lets you convert a face to its
1513  ngon format and the rest of the code can work exclusively with
1514  ngons.
1515  Parameters:
1516  buffer - [in]
1517  an array with a capacity for at least 9 ON__UINT_PTR elements.
1518  The returned ngon information will be stored in this memory.
1519  mesh_face_index - [in]
1520  fvi - [in]
1521  mesh face vertex indices.
1522  If "f" is an ON_MeshFace, then pass (const unsigned int*)f.vi.
1523  Returns:
1524  If the input is valid, the returned ngon pointer is is the
1525  face's triangle or quad. All returned information is in the
1526  buffer[].
1527  null - invalid input.
1528  See Also:
1529  ON_Mesh::NgonFromComponentIndex()
1530  */
1531  static class ON_MeshNgon* NgonFromMeshFace(
1532  class ON_MeshNgonBuffer& ngon_buffer,
1533  unsigned int mesh_face_index,
1534  const unsigned int* fvi
1535  );
1536 
1537  /*
1538  Description:
1539  Create an array of a single ngon pointer that contains
1540  a triangle (3-gon) or quad (4-gon) from a mesh face.
1541  This is handy when your code needs to handle both
1542  ngons and faces because it lets you convert a face to its
1543  ngon format and the rest of the code can work exclusively with
1544  ngons.
1545  Parameters:
1546  ngon_buffer - [in]
1547  memory used to create ngon classan array with a capacity for at least 10 ON__UINT_PTR elements.
1548  mesh_face_index - [in]
1549  fvi - [in]
1550  mesh face vertex indices.
1551  If "f" is an ON_MeshFace, then pass (const unsigned int*)f.vi.
1552  Returns:
1553  If the input is valid, the returned pointer is an array of a single ngon
1554  that is the face's triangle or quad. All returned information is in the
1555  buffer[].
1556  null - invalid input.
1557  */
1558  static class ON_MeshNgon** NgonListFromMeshFace(
1559  class ON_MeshNgonBuffer& ngon_buffer,
1560  unsigned int mesh_face_index,
1561  const unsigned int* fvi
1562  );
1563 
1564  /*
1565  Description:
1566  If a component index identifies a face or ngon, Get an array Create an array of a single ngon pointer that contains
1567  a triangle (3-gon) or quad (4-gon) from a mesh face.
1568  This is handy when your code needs to handle both
1569  ngons and faces because it lets you convert a face to its
1570  ngon format and the rest of the code can work exclusively with
1571  ngons.
1572  Parameters:
1573  ngon_buffer - [in]
1574  memory used to create ON_MeshNgon class
1575  ci - [in]
1576  mesh - [in]
1577  ngon_list - [out]
1578  An array of ngon pointers. Some pointers may be null.
1579  Returns:
1580  Number of ngon pointers in ngon_list.
1581  */
1582  static unsigned int NgonListFromMeshFaceOrNgonComponent(
1583  class ON_MeshNgonBuffer& ngon_buffer,
1584  ON_COMPONENT_INDEX ci,
1585  const class ON_Mesh* mesh,
1586  const class ON_MeshNgon* const *& ngon_list
1587  );
1588 
1589  ////////////////////////////////////////////////////////////////////
1590  //
1591  // Tools for text output
1592  //
1593  ON_String ToString() const;
1594 
1595  ON_wString ToWideString() const;
1596 
1597  void Dump(
1598  class ON_TextLog& text_log
1599  )const;
1600 
1601  void AppendToString(
1602  class ON_String& s
1603  )const;
1604 
1605  void AppendToString(
1606  class ON_wString& s
1607  )const;
1608 
1609 
1610  ////////////////////////////////////////////////////////////////////
1611  //
1612  // Tools for validation output
1613  //
1614 
1615  /*
1616  Description:
1617  Test ngon to see if the vertex and face references are valid and
1618  pass partial boundary validity checks,
1619  Parameters:
1620  ngon - [in]
1621  ngon to test
1622  ngon_index - [in]
1623  This index is used in messages sent to text_log
1624  text_log - [in]
1625  nullptr or a place to send information about problems.
1626  mesh_vertex_count - [in]
1627  Number of vertices in the mesh
1628  mesh_face_count - [in]
1629  Number of face in the mesh
1630  mesh_F - [in]
1631  nullptr of mesh faces - required for boundary checks
1632  workspace_buffer - [in]
1633  If you are passing in mesh_F and you are testing testing multple
1634  ngons, then consider providing a workspace_buffer that will be automatically
1635  reused for successive ngons.
1636  Returns:
1637  0: ngon is not valid
1638  >0: number of boundary edges.
1639  If this number is > ngon->m_V_count, then the ngon has inner boundaries
1640  or duplicate vertices.
1641  */
1642  static unsigned int IsValid(
1643  const ON_MeshNgon* ngon,
1644  unsigned int ngon_index,
1645  ON_TextLog* text_log,
1646  unsigned int mesh_vertex_count,
1647  unsigned int mesh_face_count,
1648  const ON_MeshFace* mesh_F
1649  );
1650 
1651  static unsigned int IsValid(
1652  const ON_MeshNgon* ngon,
1653  unsigned int ngon_index,
1654  ON_TextLog* text_log,
1655  unsigned int mesh_vertex_count,
1656  unsigned int mesh_face_count,
1657  const ON_MeshFace* mesh_F,
1658  ON_SimpleArray< unsigned int >& workspace_buffer
1659  );
1660 };
1661 
1662 class ON_CLASS ON_MeshNgonAllocator
1663 {
1664 public:
1665  ON_MeshNgonAllocator() ON_NOEXCEPT;
1667 
1668  /*
1669  Parameters:
1670  Vcount - [in] >= 3
1671  Fcount - [in] >= 0
1672  */
1673  ON_MeshNgon* AllocateNgon(
1674  unsigned int Vcount,
1675  unsigned int Fcount
1676  );
1677 
1678  /*
1679  Parameters:
1680  Vcount - [in] >= 3
1681  Fcount - [in] >= 0
1682  */
1683  ON_MeshNgon* ReallocateNgon(
1684  ON_MeshNgon* ngon,
1685  unsigned int Vcount,
1686  unsigned int Fcount
1687  );
1688 
1689  /*
1690  Parameters:
1691  ngon - in]
1692  An ngon pointer value that was previously returned by
1693  this allocator's AllocateNgon() or CopyNgon() function.
1694  */
1695  bool DeallocateNgon(
1697  );
1698 
1699  /*
1700  Description:
1701  Returns a copy of ngon.
1702  Parameters:
1703  ngon - [in]
1704  Returns:
1705  If
1706  */
1707  ON_MeshNgon* CopyNgon(
1708  const ON_MeshNgon* ngon
1709  );
1710 
1711  /*
1712  Description:
1713  Deallocate every n-gon managed by this allocator.
1714  */
1715  void DeallocateAllNgons();
1716 
1717 #if defined(ON_HAS_RVALUEREF)
1720 #endif
1721 
1722 private:
1723 
1724  ON_FixedSizePool m_7; // Vcount+Fcount <= 7
1725  ON_FixedSizePool m_15; // Vcount+Fcount <= 15
1726  void* m_31; // available for Vcount+Fcount <= 31
1727  void* m_63; // available for Vcount+Fcount <= 63
1728  void* m_active; // active Vcount+Fcount >= 16
1729 
1730 private:
1731  // prohibit copy construction. No implentation.
1732  ON_MeshNgonAllocator(const ON_MeshNgonAllocator&) = delete;
1733 
1734  // prohibit operator=. No implentation.
1735  ON_MeshNgonAllocator& operator=(const ON_MeshNgonAllocator&) = delete;
1736 };
1737 
1738 class ON_MeshFaceSide
1739 {
1740 public:
1741  unsigned int m_vi[2]; // vertex indices or ids (equal values indicate unset)
1742  unsigned int m_fi; // face index or id
1743  unsigned char m_side; // triangles use 0,1,3, quads use 0,1,2,3
1744  // m_side 0 connect face vertex 0 to face vertex 1.
1745  unsigned char m_dir; // 0 = counterclockwise, 1 = clockwise (reversed)
1746  unsigned short m_value; // Use depends on context.
1747  unsigned int m_id; // Use depends on context - typically identifies and edge or ngon
1748 
1749  static const ON_MeshFaceSide Unset; // all values are zero
1750 
1751  /*
1752  Description:
1753  Compare a and b in dictionary order comparing the field values in the order
1754  m_fi
1755  m_vi[0]
1756  m_vi[1]
1757  m_side
1758  m_dir
1759  Parameters:
1760  a - [in]
1761  b - [in]
1762  Returns:
1763  -1: *a < *b
1764  0: *a < *b
1765  1: *a > *b
1766  Remarks:
1767  The function is thread safe.
1768  */
1769  static int CompareFaceIndex(
1770  const ON_MeshFaceSide* a,
1771  const ON_MeshFaceSide* b
1772  );
1773 
1774  /*
1775  Description:
1776  Compare a and b in dictionary order comparing the field values in the order
1777  m_vi[0]
1778  m_vi[1]
1779  m_fi
1780  m_side
1781  m_dir
1782  Parameters:
1783  a - [in]
1784  b - [in]
1785  Returns:
1786  -1: *a < *b
1787  0: *a < *b
1788  1: *a > *b
1789  Remarks:
1790  The function is thread safe.
1791  */
1792  static int CompareVertexIndex(
1793  const ON_MeshFaceSide* a,
1794  const ON_MeshFaceSide* b
1795  );
1796 
1797  /*
1798  Description:
1799  Sort the face_sides[] using the compare function
1800  ON_MeshFaceSide::CompareVertexIndex().
1801  Paramters:
1802  face_sides - [in/out]
1803  array to sort
1804  face_sides_count - [in]
1805  number of elements in the face_sides[] array.
1806  Remarks:
1807  The function is thread safe.
1808  */
1809  static void SortByVertexIndex(
1810  ON_MeshFaceSide* face_sides,
1811  size_t face_sides_count
1812  );
1813 
1814  /*
1815  Description:
1816  Sort the face_sides[] using the compare function
1817  ON_MeshFaceSide::CompareFaceIndex().
1818  Paramters:
1819  face_sides - [in/out]
1820  array to sort
1821  face_sides_count - [in]
1822  number of elements in the face_sides[] array.
1823  Remarks:
1824  The function is thread safe.
1825  */
1826  static void SortByFaceIndex(
1827  ON_MeshFaceSide* face_sides,
1828  size_t face_sides_count
1829  );
1830 
1831  /*
1832  Description:
1833  Get a list of mesh face sides.
1834  Parameters:
1835  mesh_vertex_count - [in]
1836  Number of vertices in the mesh.
1837  This value is used to validate vertex index values in mesh_face_list.
1838  mesh_face_list - [in]
1839  Mesh faces
1840  fi_list - [in]
1841  - If fi_list null, then sides for every face in mesh_face_list will
1842  be added and the ON_MeshFaceSide.m_fi values will be the
1843  mesh_face_list[] index.
1844  - If fi_list is not null, then fi_list[] is an array of mesh_face_list[]
1845  indices and the ON_MeshFaceSide.m_fi values will be fi_list[] array
1846  indices. For example, you may pass ON_MeshNon.m_fi as this parameter
1847  when you want a list of sides of faces in an ngon.
1848  fi_list_count - [in]
1849  - If fi_list is not null, then fi_list_count is the number of elements
1850  in the fi_list[] array.
1851  - If fi_list is null, then fi_list_count is ignored.
1852  vertex_id_map - [in] (can be null)
1853  - If vertex_id_map is null, then the ON_MeshFaceSide::m_vi[] values
1854  are the vertex index values from mesh_face_list[].
1855  - If vertex_id_map is not null, then vertex_id_map[] is an array
1856  with the mesh_vertex_count elements and ON_MeshFaceSide::m_vi[] values
1857  are vertex_id_map[mesh_face_list[] vertex indices]. A vertex_id_map[]
1858  is commonly used when coincident vertices need to be treated as
1859  a single topological entity.
1860  face_side_list - [out]
1861  - If the input value of face_side_list is not null, then face_side_list[]
1862  must be long enough to hold the returned face_side_list list.
1863  The maximum posssible length is 4*mesh_face_list.FaceCount().
1864  - If the input falue of face_side_list is null, memory will be allocated
1865  using onmalloc() and the caller is responsible for calling onfree() at
1866  an appropriate time.
1867  The returned is face_side_list[] is dictionary sorted by ON_MeshFaceSide.m_fi
1868  and then ON_MeshFaceSide.m_si. The vertex ids satisfy
1869  ON_MeshFaceSide.m_vi[0] < ON_MeshFaceSide.m_vi[1]. ON_MeshFaceSide.m_dir
1870  is 0 if the face vertex order is the same and 1 if the face vertex order
1871  is opposite. The static sorting functions on ON_MeshFaceSide can be used
1872  to change this ordering.
1873  Returns:
1874  Number of elements set in face_side_list[].
1875  Remarks:
1876  Faces in mesh_face_list with vertex indices that are >= mesh_vertex_count
1877  are ignored. Degenerate faces are processed, but degenerate sides
1878  (equal vertex ids) are not added to face_side_list[].
1879  */
1880  static unsigned int GetFaceSideList(
1881  size_t mesh_vertex_count,
1882  const class ON_MeshFaceList& mesh_face_list,
1883  const unsigned int* fi_list,
1884  size_t fi_list_count,
1885  const unsigned int* vertex_id_map,
1886  ON_MeshFaceSide*& face_side_list
1887  );
1888 };
1889 
1890 
1891 struct ON_MeshPart
1892 {
1893  // ON_Mesh faces with indices fi[0] <= i < fi[1] reference
1894  // vertices with indices vi[0] <= j < vi[1].
1895  int vi[2]; // subinterval of mesh m_V[] array
1896  int fi[2]; // subinterval of mesh m_F[] array
1897  int vertex_count; // = vi[1] - vi[0];
1898  int triangle_count; // tris + 2*quads >= fi[1] - fi[0]
1899 };
1900 
1901 #if defined(ON_DLL_TEMPLATE)
1902 ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray<ON_MeshFace>;
1903 ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray<ON_MeshNgon*>;
1904 ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray<ON_MeshTopologyVertex>;
1905 ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray<ON_MeshTopologyEdge>;
1906 ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray<ON_MeshTopologyFace>;
1907 ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray<struct ON_MeshPart>;
1908 #endif
1909 
1910 class ON_CLASS ON_MeshTopology
1911 {
1912  // A mesh topology class is always associated with an ON_Mesh
1913  // and can be retrieved by calling ON_Mesh::Topology()
1914 public:
1915  ON_MeshTopology();
1916  ~ON_MeshTopology();
1917 
1918  bool IsValid() const;
1919 
1920  void Dump( ON_TextLog& ) const;
1921 
1922  //////////
1923  // The parent ON_Mesh geometry used to compute this mesh topology.
1924  const ON_Mesh* m_mesh;
1925 
1926  //////////
1927  // number of topoligical vertices (<= m_mesh.VertexCount())
1928  int TopVertexCount() const;
1929 
1930  //////////
1931  // number of topoligical edges
1932  int TopEdgeCount() const;
1933 
1934  //////////
1935  // number of topoligical faces (same as m_mesh.FaceCount())
1936  int TopFaceCount() const;
1937 
1938  class ON_MeshComponentRef MeshComponentRef(
1939  ON_COMPONENT_INDEX ci
1940  ) const;
1941 
1942  /*
1943  Description:
1944  Get the 3d point location of a vertex.
1945  Parameters:
1946  topv_index - [in];
1947  Returns:
1948  Location of vertex.
1949  */
1950  ON_3dPoint TopVertexPoint(
1951  int topv_index
1952  ) const;
1953 
1954  /*
1955  Description:
1956  Get the 3d line along an edge.
1957  Parameters:
1958  tope_index - [in];
1959  Returns:
1960  Line along edge. If input is not valid,
1961  the line.from and to are ON_3dPoint::UnsetPoint
1962  */
1963  ON_Line TopEdgeLine(
1964  int tope_index
1965  ) const;
1966 
1967  ////////
1968  // returns index of edge that connects topological vertices
1969  // returns -1 if no edge is found.
1970  int TopEdge(
1971  int vtopi0,
1972  int vtopi1 // ON_MeshTopology vertex topology indices
1973  ) const;
1974 
1975  ////////
1976  // returns ON_MeshTopology vertex topology index of a face
1977  // corner. The face is triangle iv TopFaceVertex(2) = TopFaceVertex(3)
1978  bool GetTopFaceVertices(
1979  int topfi, // ON_MeshTopology face topology index (= ON_Mesh face index)
1980  int topvi[4] // ON_MeshTopology vertex indices returned here
1981  ) const;
1982 
1983  /*
1984  Parameters:
1985  topvi - [in]
1986  Topology vertex index
1987  mesh_facedex_to_ngondex_map - [in]
1988  If null, Mesh().NgonMap() will be used. In cases where Mesh().NgonMap()
1989  does not exist and cannot be created, an expert user may pass in
1990  a local map that converts a face index into an ngon index.
1991  Returns:
1992  If the vertex is interior to a single ngon, then the index of the
1993  ngon is returned. Otherwise ON_UNSET_UINT_INDEX is returned.
1994  */
1995  unsigned int NgonIndexFromTopologyVertexIndex(
1996  unsigned int topvi,
1997  const unsigned int* mesh_facedex_to_ngondex_map
1998  ) const;
1999 
2000  /*
2001  Parameters:
2002  topei - [in]
2003  Topology edge index
2004  mesh_facedex_to_ngondex_map - [in]
2005  If null, Mesh().NgonMap() will be used. In cases where Mesh().NgonMap()
2006  does not exist and cannot be created, an expert user may pass in
2007  a local map that converts a face index into an ngon index.
2008  Returns:
2009  If the vertex is interior to a single ngon, then the index of the
2010  ngon is returned. Otherwise ON_UNSET_UINT_INDEX is returned.
2011  */
2012  unsigned int NgonIndexFromTopologyEdgeIndex(
2013  unsigned int topei,
2014  const unsigned int* mesh_facedex_to_ngondex_map
2015  ) const;
2016 
2017  /*
2018  Description:
2019  Sort the m_topei[] list of a mesh topology vertex so that
2020  the edges are in radial order. The "const" is a white
2021  lie to make this function easier to call.
2022  Parameter:
2023  topvi - [in] index of vertex in m_topv[] array.
2024  Remarks:
2025  A nonmanifold edge is treated as a boundary edge with respect
2026  to sorting. If any boundary or nonmanifold edges end at the
2027  vertex, then the first edge will be a boundary or nonmanifold
2028  edge.
2029  */
2030  bool SortVertexEdges( int topvi ) const;
2031 
2032  /*
2033  Description:
2034  Sort the m_topei[] list of every mesh topology vertex so
2035  that the edges are in radial order. The "const" is a white
2036  lie to make this function easier to call.
2037  Remarks:
2038  Same as
2039  for ( int topvi = 0; topvi < m_topv.Count(); topvi++ )
2040  SortVertexEdges(topvi);
2041  */
2042  bool SortVertexEdges() const;
2044  /*
2045  Description:
2046  Returns true if the topological vertex is hidden.
2047  Parameters:
2048  topvi - [in] mesh topology vertex index.
2049  Returns:
2050  True if mesh topology vertex is hidden.
2051  Remarks:
2052  The mesh topology vertex is hidden if and only if
2053  all the ON_Mesh vertices it represents is hidden.
2054  */
2055  bool TopVertexIsHidden( int topvi ) const;
2056 
2057  /*
2058  Description:
2059  Returns true if the topological edge is hidden.
2060  Parameters:
2061  topei - [in] mesh topology edge index.
2062  Returns:
2063  True if mesh topology edge is hidden.
2064  Remarks:
2065  The mesh topology edge is hidden if and only if
2066  either of its mesh topology vertices is hidden.
2067  */
2068  bool TopEdgeIsHidden( int topei ) const;
2069 
2070  /*
2071  Description:
2072  Returns true if the topological face is hidden.
2073  Parameters:
2074  topfi - [in] mesh topology face index.
2075  Returns:
2076  True if mesh topology face is hidden.
2077  Remarks:
2078  The mesh topology face is hidden if and only if
2079  any of its mesh topology edges are hidden.
2080  */
2081  bool TopFaceIsHidden( int topfi ) const;
2082 
2083  //////////
2084  // m_topv_map[] has length m_mesh.VertexCount() and
2085  // m_topv[m_topv_map[vi]] is the topological mesh vertex that is assocated
2086  // the with the mesh vertex m_mesh.m_V[vi].
2087  ON_SimpleArray<int> m_topv_map;
2088 
2089  ////////////
2090  // Array of topological mesh vertices. See the comments in the definition
2091  // of ON_MeshTopologyVertex for details.
2092  ON_SimpleArray<ON_MeshTopologyVertex> m_topv;
2093 
2094  ////////////
2095  // Array of topological mesh edges. See the comments in the definition
2096  // of ON_MeshTopologyEdge for details.
2097  ON_SimpleArray<ON_MeshTopologyEdge> m_tope;
2098 
2099  ////////////
2100  // Array of topological mesh faces. The topological face
2101  // m_topf[fi] corresponds to the mesh face ON_Mesh.m_F[fi].
2102  // See the comments in the definition of ON_MeshTopologyFace
2103  // for details. To get the indices of the mesh topology
2104  // vertices at the face corners use
2105  // topvi = m_topv_map[m_mesh.m_F[fi].vi[n]]
2106  ON_SimpleArray<ON_MeshTopologyFace> m_topf;
2107 
2108  /*
2109  Description:
2110  Expert user function for efficiently getting the
2111  integer arrays used by the ON_MeshTopologyVertex
2112  and ON_MeshTopologyEdge classes.
2113  Parameters:
2114  count - [in] number of integers in array
2115  Returns:
2116  pointer to integer array. The array memory
2117  will be freed by ~ON_MeshTopology()
2118  */
2119  int* GetIntArray(int count);
2120 
2121 private:
2122  friend class ON_Mesh;
2124  bool Create();
2125  void Destroy();
2126  void EmergencyDestroy();
2127 
2128  // efficient workspaces for
2129  struct memchunk
2130  {
2131  struct memchunk* next;
2132  } *m_memchunk;
2133 
2134  // NOTE: this field is a bool with valid values of 0 and 1.
2135  volatile int m_b32IsValid; // sizeof(m_bIsValid) must be 4 - it is used in sleep locks.
2136  // 0: Not Valid
2137  // 1: Valid
2138  // -1: Sleep locked - ON_Mesh::Topology() calculation is in progress
2139  int WaitUntilReady(int sleep_value) const; // waits until m_b32IsValid >= 0
2140 
2141 private:
2142  // no implementation
2144  ON_MeshTopology& operator=(const ON_MeshTopology&);
2145 };
2146 
2147 
2148 
2149 class ON_CLASS ON_MeshPartition
2150 {
2151 public:
2152  ON_MeshPartition();
2153  ~ON_MeshPartition();
2154 
2155  // maximum number of vertices in a partition
2156  int m_partition_max_vertex_count;
2157  // maximum number of triangles in a partition (quads count as 2 triangles)
2158  int m_partition_max_triangle_count;
2159 
2160  // Partition i uses
2161  // vertices m_V[j] where
2162  //
2163  // m_part[i].vi[0] <= j < m_part[i].vi[1]
2164  //
2165  // and uses faces m_F[k] where
2166  //
2167  // m_part[i].fi[0] <= k < m_part[i].fi[1]
2168  ON_SimpleArray<struct ON_MeshPart> m_part;
2169 };
2170 
2171 
2173 class ON_CLASS ON_MappingTag
2174 {
2175 public:
2176  ON_MappingTag();
2177  void Default();
2178  bool Write(ON_BinaryArchive&) const;
2179  bool Read(ON_BinaryArchive&);
2180  void Dump( ON_TextLog& ) const;
2181  void Transform( const ON_Xform& xform );
2182  void Set(const ON_TextureMapping& mapping);
2183 
2184  /*
2185  Description:
2186  Sets the tag to the value the meshes have that
2187  come out of ON_Brep::CreateMesh().
2188  */
2189  void SetDefaultSurfaceParameterMappingTag();
2190 
2191  int Compare( const ON_MappingTag& other,
2192  bool bCompareId = true,
2193  bool bCompareCRC = true,
2194  bool bCompareXform = true
2195  ) const;
2196 
2197  /*
2198  Returns:
2199  True if the mapping tag is set.
2200  */
2201  bool IsSet() const;
2202 
2203  /*
2204  Returns:
2205  True if the mapping tag is for a mapping with
2206  type ON_TextureMapping::srfp_mapping with
2207  m_uvw = identity.
2208  */
2209  bool IsDefaultSurfaceParameterMapping() const;
2210 
2211  // Identifies the mapping used to create the texture
2212  // coordinates and records transformations applied
2213  // to the mesh after the texture coordinates were
2214  // calculated. If the texture mapping does not
2215  // change when the mesh is transformed, then set
2216  // m_mesh_xform to zero so that compares will work right.
2217  //
2218  //
2219  ON_UUID m_mapping_id; // ON_TextureMapping::m_mapping_id
2220  ON_TextureMapping::TYPE m_mapping_type; // ON_TextureMapping::m_type
2221  ON__UINT32 m_mapping_crc; // ON_TextureMapping::MappingCRC()
2222  ON_Xform m_mesh_xform;
2223 };
2224 
2225 class ON_CLASS ON_TextureCoordinates
2226 {
2227 public:
2229 
2230  ON_MappingTag m_tag;
2231  int m_dim; // 1, 2, or 3
2232  ON_SimpleArray<ON_3fPoint> m_T; // texture coordinates
2233 };
2234 
2235 
2236 #if defined(ON_DLL_TEMPLATE)
2237 ON_DLL_TEMPLATE template class ON_CLASS ON_SimpleArray<ON_MappingTag>;
2238 ON_DLL_TEMPLATE template class ON_CLASS ON_ClassArray<ON_TextureCoordinates>;
2239 #endif
2240 
2241 class ON_CLASS ON_Mesh : public ON_Geometry
2242 {
2243  ON_OBJECT_DECLARE(ON_Mesh);
2244 
2245 public:
2246  ON_Mesh();
2247  ON_Mesh(
2248  int initial_face_array_capacity, // initial face array capacity
2249  int initial_vertex_array_capacity, // initial vertex array capacity
2250  bool has_vertex_normals, // true if mesh has vertex normals
2251  bool has_texture_coordinates // true if mesh has texture coordinates
2252  );
2253  ON_Mesh( const ON_Mesh& );
2254  ON_Mesh& operator=( const ON_Mesh& );
2255  ~ON_Mesh();
2256 
2257 
2258  // Override of virtual ON_Object::MemoryRelocate
2259  void MemoryRelocate() override;
2260 
2261  // virtual ON_Object::DestroyRuntimeCache override
2262  void DestroyRuntimeCache( bool bDelete = true ) override;
2263 
2264  void Destroy();
2265  void EmergencyDestroy(); // Call only when memory used by this class's
2266  // members will soon become invalid for reasons
2267  // beyond your control. EmergencyDestroy() zeros
2268  // anything that could possibly cause
2269  // ~ON_Mesh() to crash. Calling
2270  // EmergencyDestroy() under normal conditions
2271  // will result in ~ON_Mesh() leaking
2272  // memory.
2273 
2274 
2275  void DestroyTree( bool bDeleteTree = true );
2276 
2277  /////////////////////////////////////////////////////////////////
2278  // ON_Object overrides
2279 
2280  // virtual ON_Object::SizeOf override
2281  unsigned int SizeOf() const override;
2282 
2283  // virtual ON_Object::DataCRC override
2284  ON__UINT32 DataCRC(ON__UINT32 current_remainder) const override;
2285 
2286  bool IsValid( class ON_TextLog* text_log = nullptr ) const override;
2287 
2288  void Dump( ON_TextLog& ) const override; // for debugging
2289 
2290  bool Write( ON_BinaryArchive& ) const override;
2291 
2292  bool Read( ON_BinaryArchive& ) override;
2293 
2294  ON::object_type ObjectType() const override;
2295 
2296  /////////////////////////////////////////////////////////////////
2297  // ON_Geometry overrides
2298 
2299  int Dimension() const override;
2300 
2301  // virtual ON_Geometry GetBBox override
2302  bool GetBBox( double* boxmin, double* boxmax, bool bGrowBox = false ) const override;
2303 
2304  // virtual ON_Geometry GetTightBoundingBox override
2305  bool GetTightBoundingBox( class ON_BoundingBox& tight_bbox, bool bGrowBox = false, const class ON_Xform* xform = nullptr ) const override;
2306 
2307  bool GetTightBoundingBox(
2308  ON_BoundingBox& tight_bbox,
2309  bool bGrowBox ,
2310  const ON_SimpleArray<ON_PlaneEquation>& clipping_planes,
2311  const ON_Xform* xform = nullptr
2312  ) const ;
2313 
2314  bool Transform(
2315  const ON_Xform&
2316  ) override;
2317 
2318  // virtual ON_Geometry::IsDeformable() override
2319  bool IsDeformable() const override;
2320 
2321  // virtual ON_Geometry::MakeDeformable() override
2322  bool MakeDeformable() override;
2323 
2324  bool SwapCoordinates(
2325  int, int // indices of coords to swap
2326  ) override;
2327 
2328 
2329  // virtual ON_Geometry override
2330  bool EvaluatePoint( const class ON_ObjRef& objref, ON_3dPoint& P ) const override;
2331 
2332 
2333  /////////////////////////////////////////////////////////////////
2334  // Interface
2335  //
2336 
2337  /*
2338  Returns
2339  true if there are zero vertices or zero faces.
2340  */
2341  bool IsEmpty() const;
2342 
2343  // creation
2344  bool SetVertex(
2345  int, // vertex index
2346  const ON_3dPoint& // vertex location
2347  );
2348  bool SetVertex(
2349  int, // vertex index
2350  const ON_3fPoint& // vertex location
2351  );
2352  bool SetVertexNormal(
2353  int, // vertex index
2354  const ON_3dVector& // unit normal
2355  );
2356  bool SetVertexNormal(
2357  int, // vertex index
2358  const ON_3fVector& // unit normal
2359  );
2360  bool SetTextureCoord(
2361  int, // vertex index
2362  double, double // texture coordinates
2363  );
2364  bool SetTriangle(
2365  int, // face index
2366  int,int,int // vertex indices
2367  );
2368  bool SetQuad(
2369  int, // face index
2370  int,int,int,int // vertex indices
2371  );
2372 
2373  /*
2374  Description:
2375  Use this function to append a duplicate of an existing vertex.
2376  Parameters:
2377  vertex_index - [in]
2378  index of the existing vertex
2379  Returns:
2380  If vertex_index is valid, the index of the duplicate is returned.
2381  Otherwise, ON_UNSET_UINT_INDEX is returned.
2382  Remarks:
2383  This function duplicates all information associated with
2384  the input vertex and is a good way to insure that
2385  optional vertex information like color, texture, surface
2386  parameters, curvatures, vertex normals, and so on get
2387  duplicated as well.
2388  */
2389  unsigned int AppendDuplicateVertex(
2390  unsigned int vertex_index
2391  );
2392 
2393  /*
2394  Description:
2395  Increases the capactiy of arrays used to hold vertex information.
2396  Parameters:
2397  new_vertex_capacity - [in]
2398  desired capacity
2399  Returns:
2400  true if successful.
2401  Remarks:
2402  This function is useful if you are getting ready to add a known number
2403  of vertices and want to increase the dynamic array capacities before
2404  you begin adding vertices.
2405  */
2406  bool ReserveVertexCapacity(
2407  size_t new_vertex_capacity
2408  );
2409 
2410  /*
2411  Parameters:
2412  ci - [in]
2413  component index to test
2414  Returns:
2415  True if ci identifies a component (vertex, edge, face, ngon) that exists in this mesh.
2416  */
2417  bool IsValidMeshComponentIndex(
2418  ON_COMPONENT_INDEX ci
2419  ) const;
2420 
2421  class ON_MeshComponentRef MeshComponentRef(
2422  ON_COMPONENT_INDEX ci
2423  ) const;
2424 
2425  /*
2426  Parameters:
2427  ci - [in] a component index with type mesh_vertex, meshtop_vertex,
2428  meshtop_edge, or mesh_face.
2429  Returns:
2430  A pointer to an ON_MeshComponentRef
2431  The caller must delete the returned object when it is no longer
2432  needed.
2433  */
2434  class ON_MeshComponentRef* MeshComponent(
2435  ON_COMPONENT_INDEX ci
2436  ) const;
2437 
2438  /*
2439  Description:
2440  Delete the portions of the mesh identified in ci_list[].
2441  Parameters:
2442  ci_list - [in]
2443  List of components to delete.
2444  ci_list_count - [in]
2445  Number of elements in the ci_list[] array.
2446  Can be zero if you are using this function to remove
2447  unused vertices or empty ngons.
2448  bIgnoreInvalidComponents - [in]
2449  If true, invalid elements in ci_list[] are ignored.
2450  If false and ci_list[] contains an invalid element,
2451  then no changes are made and false is returned.
2452  bRemoveDegenerateFaces - [in]
2453  If true, remove degenerate faces.
2454  bCullUnusedVertices - [in]
2455  Remove vertices that are not referenced by a face.
2456  Pass true unless you have a good reason for keeping
2457  unreferenced vertices.
2458  bRemoveEmptyNgons - [in]
2459  Remove ngons that are empty.
2460  Pass true unless you have a good reason for keeping
2461  empty ngons.
2462  Returns:
2463  True: succesful
2464  False: failure - no changes.
2465  */
2466  bool DeleteComponents(
2467  const ON_COMPONENT_INDEX* ci_list,
2468  size_t ci_count,
2469  bool bIgnoreInvalidComponents,
2470  bool bRemoveDegenerateFaces,
2471  bool bRemoveUnusedVertices,
2472  bool bRemoveEmptyNgons
2473  );
2474 
2475  /*
2476  Description:
2477  Calls the detailed version of DeleteComponents() with
2478  bool bIgnoreInvalidComponents = true;
2479  bool bRemoveDegenerateFaces = false;
2480  bool bRemoveUnusedVertices = true;
2481  bool bRemoveEmptyNgons = true;
2482  */
2483  bool DeleteComponents(
2484  const ON_COMPONENT_INDEX* ci_list,
2485  size_t ci_count
2486  ) override;
2487 
2488  /*
2489  Description:
2490  Calls the detailed version of DeleteComponents() with
2491  bool bIgnoreInvalidComponents = true;
2492  bool bRemoveDegenerateFaces = false;
2493  bool bRemoveUnusedVertices = true;
2494  bool bRemoveEmptyNgons = true;
2495  */
2496  bool DeleteComponents(
2497  const ON_SimpleArray<ON_COMPONENT_INDEX>& ci_list
2498  );
2499 
2500  /*
2501  Description:
2502  Calls the detailed version of DeleteComponents() with
2503  bool bIgnoreInvalidComponents = true;
2504  bool bRemoveDegenerateFaces = false;
2505  bool bRemoveUnusedVertices = true;
2506  bool bRemoveEmptyNgons = true;
2507  */
2508  bool DeleteComponent(
2509  ON_COMPONENT_INDEX ci
2510  );
2511 
2512  /*
2513  Description:
2514  Copy the subset of the mesh idenfied in the component list.
2515  Parameters:
2516  ci_list - [in]
2517  ci_count - [in]
2518  ci_list[] is an array of ci_count components that identify the
2519  parts of the mesh to copy. If a face or ngon is specified, then
2520  any vertices or faces needed for a valid copy are automatically
2521  copied as well.
2522  destination_mesh - [in]
2523  If null, a new mesh is allocated for the copy.
2524  If not null, the copy is put in this mesh.
2525  Return:
2526  null - invalid input - no copy created
2527  not null - a pointer to the copy.
2528  */
2529  ON_Mesh* CopyComponents(
2530  const ON_COMPONENT_INDEX* ci_list,
2531  size_t ci_count,
2532  class ON_Mesh* destination_mesh
2533  ) const;
2534 
2535  /*
2536  Description:
2537  Copy the subset of the mesh idenfied in the component list.
2538  Parameters:
2539  ci_list - [in]
2540  ci_list[] is an array of ci_count components that identify the
2541  parts of the mesh to copy. If a face or ngon is specified, then
2542  any vertices or faces needed for a valid copy are automatically
2543  copied as well.
2544  destination_mesh - [in]
2545  If null, a new mesh is allocated for the copy.
2546  If not null, the copy is put in this mesh.
2547  Return:
2548  null - invalid input - no copy created
2549  not null - a pointer to the copy.
2550  */
2551  ON_Mesh* CopyComponents(
2552  const ON_SimpleArray<ON_COMPONENT_INDEX>& ci_list,
2553  class ON_Mesh* destination_mesh
2554  ) const;
2555 
2556  // query
2557  int VertexCount() const;
2558  unsigned int VertexUnsignedCount() const;
2559  int FaceCount() const;
2560  unsigned int FaceUnsignedCount() const;
2561  int QuadCount() const; // number of faces that are quads
2562  int TriangleCount() const; // number of faces that are triangles
2563  int InvalidFaceCount() const; // number of face that have invalid m_vi[] values.
2564  bool HasVertexNormals() const; // normals at vertices
2565  bool HasFaceNormals() const;
2566  bool HasTextureCoordinates() const;
2567  bool HasSurfaceParameters() const;
2568  bool HasPrincipalCurvatures() const;
2569  bool HasVertexColors() const;
2570 
2571  /*
2572  Returns:
2573  True if the mesh has ngons.
2574  */
2575  bool HasNgons() const;
2576 
2577  /*
2578  Returns:
2579  Number of vertices that are hidden.
2580  */
2581  int HiddenVertexCount() const;
2582 
2583  bool GetCurvatureStats(
2584  ON::curvature_style,
2586  ) const;
2587 
2588  void InvalidateVertexBoundingBox(); // Call if defining geometry is changed by
2589  // directly manipulating the m_V[] array.
2590  void InvalidateVertexNormalBoundingBox(); // Call if defining geometry is changed by
2591  // directly manipulating the m_N[] array.
2592  void InvalidateTextureCoordinateBoundingBox(); // Call if defining geometry is changed by
2593  // directly manipulating the m_T[] array.
2594  void InvalidateCurvatureStats(); // Call if defining geometry is changed by
2595  // directly manipulating the m_T[] array.
2596  void InvalidateBoundingBoxes(); // Invalidates all cached bounding box information.
2597 
2598 
2599  void Flip(); // reverses face orientations and flips vertex and face normals
2600 
2601  void FlipVertexNormals(); // reverses vertex normals
2602  void FlipFaceNormals(); // reverses face normals
2603  void FlipFaceOrientation(); // reverses face orientation (does nothing to normals)
2604  void FlipNgonOrientation(); // reverses ngon boundary direction
2605 
2606  void SetMeshParameters( const ON_MeshParameters& );
2607  const ON_MeshParameters* MeshParameters() const;
2608  void DeleteMeshParameters();
2609 
2610 
2611  bool UnitizeVertexNormals();
2612  bool UnitizeFaceNormals();
2613  bool CountQuads();
2614 
2615  /*
2616  Description:
2617  Splits all quads along the short diagonal.
2618  */
2619  bool ConvertQuadsToTriangles();
2620 
2621  /*
2622  Description:
2623  Splits non-planer quads into two triangles.
2624 
2625  Parameters:
2626  planar_tolerance - [in]
2627  If planar_tolerance >= 0, then a quad is split if its vertices
2628  are not coplaner.
2629 
2630  If both planar_tolerance = ON_UNSET_VALUE and angle_tolerance_radians >= 0.0,
2631  then the planarity test is skipped.
2632 
2633  If both planar_tolerance = ON_UNSET_VALUE and angle_tolerance_radians = ON_UNSET_VALUE,
2634  then all quads are split.
2635 
2636  angle_tolerance_radians - [in]
2637  If angle_tolerance_radians >= 0.0, then a quad is split if the
2638  angle between opposite corner normals is > angle_tolerance_radians.
2639  The corner normal is the normal to the triangle formed by two
2640  adjacent edges and the diagonal connecting their endpoints.
2641  A quad has for corner normals.
2642 
2643  If both angle_tolerance_radians = ON_UNSET_VALUE and planar_tolerance >= 0.0,
2644  then the corner normal angle test is skipped.
2645 
2646  If both planar_tolerance = ON_UNSET_VALUE and angle_tolerance_radians = ON_UNSET_VALUE,
2647  then all quads are split.
2648 
2649  split_method - [in]
2650  0 default
2651  Currently divides along the short diagonal. This may be
2652  changed as better methods are found or preferences change.
2653  By passing zero, you let the developers of this code
2654  decide what's best for you over time.
2655  1 divide along the short diagonal
2656  2 divide along the long diagonal
2657  3 minimize resulting area
2658  4 maximize resulting area
2659  5 minimize angle between triangle normals
2660  6 maximize angle between triangle normals
2661 
2662  bDeleteNgonsContainingSplitQuads - [in]
2663  If true, ngons that contain a split quad are deleted.
2664 
2665  Returns:
2666  Number of quads that were converted to triangles.
2667  */
2668  unsigned int ConvertNonPlanarQuadsToTriangles(
2669  double planar_tolerance,
2670  double angle_tolerance_radians,
2671  unsigned int split_method
2672  );
2673 
2674  unsigned int ConvertNonPlanarQuadsToTriangles(
2675  double planar_tolerance,
2676  double angle_tolerance_radians,
2677  unsigned int split_method,
2678  bool bDeleteNgonsContainingSplitQuads
2679  );
2680 
2681  /*
2682  Description:
2683  Joins adjacent triangles into quads if the resulting quad
2684  is nice.
2685  Parameters:
2686  angle_tol_radians - [in] Used to compare adjacent
2687  triangles' face normals. For two triangles to be considered,
2688  the angle between their face normals has to be <= angle_tol_radians.
2689  When in doubt use ON_PI/90.0 (2 degrees).
2690  min_diagonal_length_ratio - [in] ( <= 1.0) For two triangles to be
2691  considered the ratio of the resulting quad's diagonals
2692  (length of the shortest diagonal)/(length of longest diagonal).
2693  has to be >= min_diagonal_length_ratio.
2694  When in doubt us .875.
2695  */
2696  bool ConvertTrianglesToQuads(
2697  double angle_tol_radians,
2698  double min_diagonal_length_ratio
2699  );
2700 
2701  bool ComputeFaceNormals(); // compute face normals for all faces
2702  bool ComputeFaceNormal(int); // computes face normal of indexed face
2703 
2704  /*
2705  Description:
2706  Get a list of pairs of faces that clash.
2707  Parameters:
2708  max_pair_count - [in]
2709  If max_pair_count > 0, then at most this many pairs
2710  will be appended to the clashing_pairs[] array.
2711  If max_pair_count <= 0, then all clashing pairs
2712  will be appended to the clashing_pairs[] array.
2713  clashing_pairs - [out]
2714  The faces indices of clashing pairs are appended
2715  to this array.
2716  Returns:
2717  Number of pairs appended to clashing_pairs[].
2718  */
2719  int GetClashingFacePairs(
2720  int max_pair_count,
2721  ON_SimpleArray< ON_2dex >& clashing_pairs
2722  ) const;
2723 
2724  /*
2725  Description:
2726  Cull clashing faces from the mesh.
2727  Parameters:
2728  what_to_cull - [in]
2729  0: when a pair of faces clash, cull both faces
2730  1: when a pair of faces clash, leave the face with the
2731  longest edge.
2732  2: when a pair of faces clash, cull the face with the
2733  longest edge.
2734  3: when a pair of faces clash, leave the face with
2735  the largest area.
2736  4: when a pair of faces clash, cull the face with
2737  the largest area.
2738  Returns:
2739  Number of faces culled from the mesh.
2740  Remarks:
2741  If a large face clashes with many small faces, the large
2742  face and one small face will be removed. When a degenerate
2743  face is encountered, it is also culled.
2744  */
2745  int CullClashingFaces( int what_to_cull );
2746 
2747  unsigned int CullDegenerateFaces(); // returns number of degenerate faces
2748 
2749  int CullUnusedVertices(); // returns number of culled vertices
2750 
2751  // Description:
2752  // Removes any unreferenced objects from arrays, reindexes as needed,
2753  // and shrinks arrays to minimum required size.
2754  bool Compact();
2755 
2756  /*
2757  Description:
2758  Removes and unsets all possible cached information and
2759  then calls Compact().
2760  Parameters:
2761  bRemoveNgons - [in]
2762  If true, all n-gon information is removed.
2763  bRemoveDegenerateFaces - [in]
2764  If true, CullDegenerateFaces() is used to remove degenerate faces.
2765  bCompact - [in]
2766  If true, Compact() is called after removing cached information.
2767  */
2768  void Cleanup(
2769  bool bRemoveNgons,
2770  bool bRemoveDegenerateFaces,
2771  bool bCompact
2772  );
2773 
2774  /*
2775  Description:
2776  Calls the latest version of the detailed cleanup command passing the value for bRemoveNgons
2777  and setting all other parameters to true.
2778  Parameters:
2779  bRemoveNgons - [in]
2780  If true, all n-gon information is removed.
2781  */
2782  void Cleanup(
2783  bool bRemoveNgons
2784  );
2785 
2786  bool ComputeVertexNormals(); // uses face normals to cook up a vertex normal
2787 
2788  //////////
2789  // Scales textures so the texture domains are [0,1] and
2790  // eliminates any texture rotations.
2791  bool NormalizeTextureCoordinates();
2792 
2793  /////////
2794  // Description:
2795  // Transposes the texture coordinates
2796  // Returns
2797  // true - success
2798  bool TransposeTextureCoordinates();
2799  bool TransposeSurfaceParameters();
2800 
2801  /////////
2802  // Description:
2803  // Reverse one coordinate direction of the texture coordinates, within texture domain m_tex_domain
2804  // Parameters:
2805  // dir -[in] - dir=0 first texture coordinate is reversed
2806  // dir=1 second texture coordinate is reversed
2807  // Returns
2808  // true - success
2809  bool ReverseTextureCoordinates( int dir );
2810  bool ReverseSurfaceParameters( int dir );
2811 
2812 
2813 
2814  /*
2815  Description:
2816  Use a texture mapping function to set the m_T[] values.
2817  Parameters:
2818  mapping - [in]
2819  mesh_xform - [in]
2820  If not nullptr, the mapping calculation is performed as
2821  if the mesh were transformed by mesh_xform; the
2822  location of the mesh is not changed.
2823  bLazy - [in]
2824  If true and the m_T[] values were set using the same
2825  mapping parameters, then no calculation is performed.
2826  Returns:
2827  True if successful.
2828  See Also:
2829  ON_TextureMapping::GetTextureCoordinates
2830  */
2831  bool SetTextureCoordinates(
2832  const class ON_TextureMapping& mapping,
2833  const class ON_Xform* mesh_xform = 0,
2834  bool bLazy = true
2835  );
2836 
2837  bool HasCachedTextureCoordinates() const;
2838 
2839  const ON_TextureCoordinates* CachedTextureCoordinates(
2840  const ON_UUID& mapping_id
2841  ) const;
2842 
2843  const ON_TextureCoordinates* SetCachedTextureCoordinates(
2844  const class ON_TextureMapping& mapping,
2845  const class ON_Xform* mesh_xform = 0,
2846  bool bLazy = true
2847  );
2848 
2849  bool EvaluateMeshGeometry( const ON_Surface& ); // evaluate surface at tcoords
2850  // to set mesh geometry
2851 
2852  // finds all coincident vertices and merges them if break angle is small enough
2853  bool CombineCoincidentVertices(
2854  ON_3fVector, // coordinate tols for considering vertices
2855  // to be coincident
2856  double // cosine normal angle tolerance in radians
2857  // if vertices are coincident, then they are combined
2858  // if NormalA o NormalB >= this value
2859  );
2860 
2861  /*
2862  Description:
2863  Combines identical vertices.
2864  Parameters:
2865  bIgnoreVertexNormals - [in] If true, then vertex normals
2866  are ignored when comparing vertices.
2867  bIgnoreTextureCoordinates - [in] If true, then vertex
2868  texture coordinates, colors, and principal curvatures
2869  are ignored when comparing vertices.
2870  Returns:
2871  True if the mesh is changed, in which case the returned
2872  mesh will have fewer vertices than the input mesh.
2873  */
2874  bool CombineIdenticalVertices(
2875  bool bIgnoreVertexNormals = false,
2876  bool bIgnoreTextureCoordinates = false
2877  );
2878 
2879  void Append( const ON_Mesh& ); // appends a copy of mesh to this and updates
2880  // indices of appended mesh parts
2881 
2882  /*
2883  Description:
2884  Append a list of meshes. This function is much more efficient
2885  than making repeated calls to ON_Mesh::Append(const ON_Mesh&)
2886  when lots of meshes are being joined into a single large mesh.
2887  Parameters:
2888  count - [in]
2889  length of meshes[] array.
2890  meshes - [in]
2891  array of meshes to append.
2892  */
2893  void Append( int count, const ON_Mesh* const* meshes );
2894 
2895  /*
2896  Description:
2897  Expert user function to set m_is_closed member.
2898  Setting this value correctly after a mesh is constructed
2899  can save time when IsClosed() is called.
2900  This function sets the private member variable m_is_closed.
2901  Paramters:
2902  closed - [in]
2903  0: The mesh is not closed. There is at least one face with an
2904  edge that is geometrically distinct (as an unoriented line segment)
2905  from all other edges.
2906  1: The mesh is closed. Every geometrically distict edge is used
2907  by two or more faces.
2908  */
2909  void SetClosed(int closed);
2910 
2911  /*
2912  Returns:
2913  True if every mesh "edge" has two or more faces.
2914  */
2915  bool IsClosed() const;
2916 
2917  /*
2918  Returns:
2919  True if every mesh "edge" has at most two faces.
2920  */
2921  bool IsManifold() const;
2922 
2923  /*
2924  Returns:
2925  True if the mesh is manifold and every pair of faces
2926  that share an "edge" have compatible orientations.
2927  */
2928  bool IsOriented() const;
2929 
2930  /*
2931  Description:
2932  Determine if the mesh is a manifold.
2933  Parameters:
2934  bTopologicalTest - [in]
2935  If true, the query treats coincident vertices as
2936  the same.
2937  pbIsOriented - [out]
2938  If the input pointer is not nullptr, then the returned
2939  value of *pbIsOriented will be true if the mesh
2940  is a manifold and adjacent faces have compatible
2941  face normals.
2942  pbHasBoundary - [out]
2943  If the input pointer is not nullptr, then the returned
2944  value of *pbHasBoundary will be true if the mesh
2945  is a manifold and there is at least one "edge"
2946  with no adjacent faces have compatible
2947  face normals.
2948  Returns:
2949  True if every mesh "edge" has at most two adjacent faces.
2950  */
2951  bool IsManifold(
2952  bool bTopologicalTest,
2953  bool* pbIsOriented = nullptr,
2954  bool* pbHasBoundary = nullptr
2955  ) const;
2956 
2957  /*
2958  Description:
2959  Expert user function to set m_is_solid member.
2960  Setting this value correctly after a mesh is constructed
2961  can save time when IsSolid() is called.
2962  This function sets the private member variable m_is_solid.
2963  If solid is nonzero, it will set m_is_closed to 1.
2964  Paramters:
2965  solid - [in]
2966  0: The mesh is not an oriented manifold solid mesh. Either
2967  the mesh is not closed, not manifold, or the faces are
2968  not oriented compatibly.
2969  1: The mesh is an oriented manifold solid whose face normals
2970  point outwards.
2971  -1: The mesh is an oriented manifold solid whose face normals
2972  point inwards.
2973  */
2974  void SetSolidOrientation(int solid_orientation);
2975 
2976  /*
2977  Description:
2978  Determine orientation of a mesh.
2979  Returns:
2980  +1 mesh is a solid with outward facing normals
2981  -1 mesh is a solid with inward facing normals
2982  0 mesh is not a solid
2983  See Also:
2984  ON_Mesh::IsSolid
2985  */
2986  int SolidOrientation() const;
2987 
2988  /*
2989  Description:
2990  Test mesh to see if it is a solid. (A "solid" is
2991  a closed oriented manifold.)
2992  Returns:
2993  true mesh is a solid
2994  fals mesh is not a solid
2995  See Also:
2996  ON_Mesh::SolidOrientation
2997  ON_Mesh::IsManifold
2998  */
2999  bool IsSolid() const;
3000 
3001  /*
3002  Description:
3003  Determine if a point is inside a solid brep.
3004  Paramters:
3005  test_point - [in]
3006  tolerance - [in] >= 0.0
3007  3d distance tolerance used for ray-mesh intersection
3008  and determining strict inclusion.
3009  bStrictlyInside - [in]
3010  If bStrictlyInside is true, then test_point must be inside mesh
3011  by at least tolerance in order for this function to return
3012  true. If bStrictlyInside is false, then this function will return
3013  true if test_point is inside or the distance from test_point to
3014  a mesh face is <= tolerance.
3015  Returns:
3016  True if test_point is inside the solid mesh.
3017  Remarks:
3018  The caller is responsible for making certing the mesh is
3019  solid before calling this function. If the mesh is not
3020  solid, the behavior is unpredictable.
3021  See Also:
3022  ON_Mesh::IsSolid()
3023  */
3024  bool IsPointInside(
3025  ON_3dPoint test_point,
3026  double tolerance,
3027  bool bStrictlyInside
3028  ) const;
3029 
3030  /*
3031  Description:
3032  Appends a list of mesh edges that begin or end at the specified
3033  vertices to the edges[] array.
3034  Parameters:
3035  vcount - [in]
3036  number of vertices
3037  vertex_index - [in]
3038  array of vertex indices
3039  bNoDuplicates - [in]
3040  If true, then only one edges[] is added for each edge,
3041  the first vertex index will alwasy be less than the
3042  second, and the returned elements are sorted in dictionary
3043  order.
3044  If false and an edge is shared by multiple faces, then
3045  there will be an edges[] element added for each face and the
3046  order of the vertex indicies will indicate the orientation
3047  of the edge with respect to the face. No sorting is performed
3048  in this case.
3049  edges - [out]
3050  Edges that begin or end at one of the specified vertices are
3051  appended to this array. Each ON_2dex records the start and
3052  end vertex index.
3053  Returns:
3054  Number of ON_2dex values appended to the edges[] array.
3055  */
3056  int GetVertexEdges(
3057  int vcount,
3058  const int* vertex_index,
3059  bool bNoDuplicates,
3061  ) const;
3062 
3063 
3064  /*
3065  Description:
3066  Appends a list of mesh edges to the edges[] array.
3067  Parameters:
3068  edges - [out]
3069  Each edges[] element is a pair of vertex indices. There
3070  is at least one face in the mesh with an edge running between
3071  the indicies.
3072  Returns:
3073  Number of ON_2dex values appended to the edges[] array.
3074  */
3075  int GetMeshEdges(
3077  ) const;
3078 
3079  /*
3080  Description:
3081  Assign a unique id to each vertex location. Coincident vertices
3082  get the same id.
3083  Parameters:
3084  first_vid - [in]
3085  Initial vertex id. Typically 1 or 0.
3086  Vid - [out]
3087  If not null, then Vid[] sould be an array of length VertexCount().
3088  and the vertex ids will be stored in this array. If null,
3089  the array will be allocated by calling onmalloc(). The returned
3090  array Vid[i] is the id of the vertex m_V[i]. If m_V[i] and
3091  m_V[j] are the same 3d point, then Vid[i] and Vid[j] will have
3092  the same value.
3093  Vindex - [out] (can be null)
3094  If Vindex is not null, then it must have length at least m_V.Count()
3095  and the returned array will be a permutation of (0,1,...,m_V.Count()-1)
3096  such (Vid[Vindex[0]], Vid[Vindex[1]], ..., Vid[Vindex[m_V.Count()-1]])
3097  is an increasing list of value.
3098  Returns:
3099  null if the mesh has no vertices.
3100  An array of length VertexCount(). If vertices m_V[i] and m_V[j]
3101  are coincident, then Vid[i] = Vid[j]. The id values begin at first_vid.
3102  The maximum vertex id is Vid[Vindex[m_V.Count()-1]]. The number of
3103  unique vertex locations is (Vid[Vindex[m_V.Count()-1]] - first_vid + 1).
3104  */
3105  unsigned int* GetVertexLocationIds(
3106  unsigned int first_vid,
3107  unsigned int* Vid,
3108  unsigned int* Vindex
3109  ) const;
3110 
3111  /*
3112  Description:
3113  Get a list of the sides of every face.
3114  Parameters:
3115  Vid - [in] (can be null)
3116  If Vid is null, then the mesh m_V[] index values are used to set
3117  the ON_MeshFaceSide::vi[] values.
3118  If Vid is not null, then it must be an array of length VertexCount().
3119  The value Vid[mesh m_V[] index] will be used to set the
3120  ON_MeshFaceSide::vi[] values.
3121  sides - [out]
3122  If the input value of sides is not null, then sides[] must be long
3123  enough to hold the returned side list. The maximum posssible length
3124  is 4*FaceCount() for a mesh contining FaceCount() nondegenerate quads.
3125  If the input value of sides is null, memory will be allocated using
3126  onmalloc() and the caller is responsible for calling onfree() at an
3127  appropriate time. This function fills in the sides[] array
3128  with face side information. The returned list is sorted by sides[].fi
3129  and the sides[].side and each element has vi[0] <= vi[1].
3130  The function ON_SortMeshFaceSidesByVertexIndex() can be used to sort the
3131  list by the sides[].vi[] values.
3132  Returns:
3133  Number of elements added to sides[].
3134  Remarks:
3135  Faces with out of range ON_MeshFace.vi[] values are skipped.
3136  Degenerate faces are processed, but degenerate sides (equal vertex indices)
3137  are not added to the list.
3138  */
3139  unsigned int GetMeshFaceSideList(
3140  const unsigned int* Vid,
3141  class ON_MeshFaceSide*& sides
3142  ) const;
3143 
3144 
3145  ///////////////////////////////////////////////////////////////////////
3146  //
3147  // mesh editing
3148  //
3149 
3150  /*
3151  Description:
3152  Replace a mesh edge with a vertex at its center and update
3153  adjacent faces as needed.
3154  Parameters:
3155  topei - [in] index of edge in MeshTopology().m_tope[] array
3156  Returns:
3157  true if successful.
3158  */
3159  bool CollapseEdge( int topei );
3160 
3161  /*
3162  Description:
3163  Tests a mesh edge to see if it is valid as input to
3164  ON_Mesh::SwapMeshEdge.
3165  Parameters:
3166  topei - [in] index of edge in MeshTopology().m_tope[] array
3167  Returns:
3168  true if edge can be swapped by ON_Mesh::SwapMeshEdge.
3169  See Also:
3170  ON_Mesh::SwapEdge
3171  */
3172  bool IsSwappableEdge( int topei );
3173 
3174 
3175  /*
3176  Description:
3177  If the edge is shared by two triangular face, then
3178  the edge is "swapped".
3179  Parameters:
3180  topei - [in] index of edge in MeshTopology().m_tope[] array
3181  Returns:
3182  true if successful
3183  See Also:
3184  ON_Mesh::IsSwappableEdge
3185  */
3186  bool SwapEdge( int topei );
3187 
3188  /*
3189  Description:
3190  Removes a face from a mesh and does not alter the
3191  geometry of the remaining mesh.
3192  Parameters:
3193  meshfi - [in] index of face in ON_Mesh.m_F[] array
3194  Remarks:
3195  This function calls DestroyTopology() and DestroyPartition().
3196  The caller is responsible for calling Compact() if that step
3197  is required.
3198  Returns:
3199  true if successful
3200  */
3201  bool DeleteFace( int meshfi );
3202 
3203  /*
3204  Description:
3205  Destroys the m_H[] array and sets m_hidden_count=0.
3206  */
3207  void DestroyHiddenVertexArray();
3208 
3209  /*
3210  Returns:
3211  If the mesh has some hidden vertices, then an array
3212  of length VertexCount() is returned and the i-th
3213  element is true if the i-th vertex is hidden.
3214  If no vertices are hidden, nullptr is returned.
3215  */
3216  const bool* HiddenVertexArray() const;
3217 
3218  /*
3219  Description:
3220  Set the runtime vertex hidden flag.
3221  Parameters:
3222  meshvi - [in] mesh vertex index
3223  bHidden - [in] true to hide vertex
3224  */
3225  void SetVertexHiddenFlag( int meshvi, bool bHidden );
3226 
3227  /*
3228  Description:
3229  Returns true if the mesh vertex is hidden. This is a runtime
3230  setting that is not saved in 3dm files.
3231  Parameters:
3232  meshvi - [in] mesh vertex index.
3233  Returns:
3234  True if mesh vertex is hidden.
3235  */
3236  bool VertexIsHidden( int meshvi ) const;
3237 
3238  /*
3239  Description:
3240  Returns true if the mesh face is hidden. This is a runtime
3241  setting that is not saved in 3dm files.
3242  Parameters:
3243  meshfi - [in] mesh face index.
3244  Returns:
3245  True if mesh face is hidden.
3246  Remarks:
3247  A face is hidden if, and only if, at least one of its
3248  vertices is hidden.
3249  */
3250  bool FaceIsHidden( int meshvi ) const;
3251 
3252 
3253  ///////////////////////////////////////////////////////////////////////
3254  //
3255  // mesh topology
3256  //
3257  // In order to keep the mesh facet definition simple and make the mesh
3258  // definition easily used in common rendering application, if two facets
3259  // share a vertex location but have different normals, curvatures,
3260  // textures, etc., at that common vertex location, then the vertex is
3261  // duplicated. When the topology of the mesh needs to be known,
3262  // use Topology() to get a class that provides complete topological
3263  // information about the mesh.
3264  const ON_MeshTopology& Topology() const;
3265 
3266  ///////////////////////////////////////////////////////////////////////
3267  // If you modify the mesh in any way that may change its topology,
3268  // then call DestroyTopology(). Specifically if you add or remove
3269  // vertices or face, change vertex locations, or change the face m_vi[]
3270  // values, then you must call DestroyTopology().
3271  void DestroyTopology();
3272 
3273  /*
3274  Returns:
3275  This is an expert user function that returns true if the topology
3276  information is already calculated and cached. It can be used to
3277  to avoid calling the Topology() function when the expensive creation
3278  step will be performed.
3279  */
3280  /* obsolete - used HasMeshTopology() */ bool TopologyExists() const;
3281  bool HasMeshTopology() const;
3282 
3283  ///////////////////////////////////////////////////////////////////////
3284  //
3285  // mesh partitions
3286  //
3287  // In ancient times, some rendering engines were only able to process
3288  // small batches of triangles and th CreatePartition() function was
3289  // provided to partition the mesh into subsets of vertices and faces
3290  // that those renering engines could handle.
3291  //
3292  const ON_MeshPartition* CreatePartition(
3293  int, // maximum number of vertices in a partition
3294  int // maximum number of triangles in a partition
3295  );
3296  const ON_MeshPartition* Partition() const;
3297  void DestroyPartition();
3298 
3299  /*
3300  Description:
3301  Extract the portion of this mesh defined by mesh_part.
3302  Parameters:
3303  mesh_part - [in]
3304  defines portion of the mesh to extract.
3305  mesh - [in] (can be null, cannot be = "this).
3306  If mesh is no null, the extracted mesh will be put into
3307  this mesh. If mesh is null, the extracted mesh will
3308  be created in a mesh allocated on the heap using the
3309  new operator.
3310  Returns:
3311  A pointer to the submesh. If the input mesh parameter is null,
3312  then the caller must delete this mesh when it is no longer needed.
3313  If the input is invalid, then null is returned.
3314  */
3315  ON_Mesh* MeshPart(
3316  const ON_MeshPart& mesh_part,
3317  ON_Mesh* mesh
3318  ) const;
3319 
3320  /*
3321  Description:
3322  Create a mesh that is a single face of this mesh.
3323  Parameters:
3324  Returns:
3325  A pointer to the submesh. If the input mesh parameter is null,
3326  then the caller must delete this mesh when it is no longer needed.
3327  If the input is invalid, then null is returned.
3328  */
3329  ON_Mesh* DuplicateFace(
3330  int face_index,
3331  ON_Mesh* mesh
3332  ) const;
3333 
3334  ///////////////////////////////////////////////////////////////////////
3335  //
3336  // mesh N-gon lists.
3337  // ON_Mesh objects support faces that are triangle or quads.
3338  // When a mesh is created from a format that supports N-gons
3339  // for N larger than 4, an optional N-gon list can be added
3340  // that specifies the vertices and faces that make up the N-gon.
3341  //
3342 
3343  /*
3344  Description:
3345  If the mesh has an N-gon list, return a pointer to it.
3346  Returns:
3347  A pointer to the current N-gon list or nullptr.
3348  */
3349  const class ON_V4V5_MeshNgonList* V4V5_NgonList() const;
3350 
3351  /*
3352  Description:
3353  If an N-gon list exists, it is returned and can be modified.
3354  If no N-gon list exists, a new empty list is returned and
3355  it can be modified.
3356  Returns:
3357  A pointer to the N-gon list that can be modified.
3358  */
3359  class ON_V4V5_MeshNgonList* V4V5_ModifyNgonList();
3360 
3361  /*
3362  Description:
3363  Destroy any existing N-gon list.
3364  */
3365  void V4V5_DestroyNgonList();
3366 
3367  ///////////////////////////////////////////////////////////////////////
3368  //
3369  // mesh components
3370  // ON_Mesh objects can consist of sets of faces that are isolated
3371  // from any other sets of faces. The following 2 functions will
3372  // dissect a mesh into these sets, called components. Not to be
3373  // confused with ON_COMPONENT_INDEX.
3374 
3375  /*
3376  Description:
3377  Calculates the components of a mesh and sets a label for each face in
3378  the facet_component_labels array.
3379  Parameters:
3380  bUseVertexConnections- [in]
3381  If this parameter is true, then facets that share a common vertex
3382  are considered connected.
3383  If this parameter is false, then facets must share an edge to
3384  be considered connected.
3385  bUseTopologicalConnections - [in]
3386  If this parameter is true, then geometric location is used
3387  to determine if facets are connected.
3388  If this parameter is false, then facets must share the same vertex
3389  or vertices to be considered connected.
3390  facet_component_labels- [out]
3391  facet_component_labels[] will be an array with the same size
3392  as ON_Mesh.m_F.Count() and facet_component_labels[i]
3393  is the component id m_F[i] belongs to. The component id
3394  will be 1 to the number of compoents.
3395  Returns:
3396  Number of components on success, 0 on failure
3397  */
3398 
3399  int GetConnectedComponents( bool bUseVertexConnections,
3400  bool bTopologicalConnections,
3401  ON_SimpleArray<int>& facet_component_labels
3402  ) const;
3403 
3404  /*
3405  Description:
3406  Calculates the components of a mesh and sets a label for each face in
3407  the facet_component_labels array.
3408  Parameters:
3409  bUseVertexConnections- [in]
3410  If this parameter is true, then facets that share a common vertex
3411  are considered connected.
3412  If this parameter is false, then facets must share an edge to
3413  be considered connected.
3414  bUseTopologicalConnections - [in]
3415  If this parameter is true, then geometric location is used
3416  to determine if facets are connected.
3417  If this parameter is false, then facets must share the same vertex
3418  or vertices to be considered connected.
3419  components - [out]
3420  New components are appended to this array
3421  if this parameter is null, then the components are just counted.
3422  Returns:
3423  Number of components on success, 0 on failure
3424  */
3425 
3426  int GetConnectedComponents( bool bUseVertexConnections,
3427  bool bTopologicalConnections,
3428  ON_SimpleArray<ON_Mesh*>* components
3429  ) const;
3430 
3431 
3432  /////////////////////////////////////////////////////////////////
3433  //
3434  // Double precision vertex support
3435  //
3436 
3437  /*
3438  Returns:
3439  True if the mesh vertex count is > 0, the mesh has single and double
3440  precision vertices, and the values of the locations are synchronized.
3441  */
3442  bool HasSynchronizedDoubleAndSinglePrecisionVertices() const;
3443 
3444  /*
3445  Returns:
3446  True if the mesh has double precision vertices (m_dV.Count() > 0).
3447  Remarks:
3448  Use ON_Mesh::UpdateDoublePrecisionVertices()
3449  or ON_Mesh::UpdateSinglePrecisionVertices() to synchronize
3450  values of single and double precision vertices.
3451  */
3452  bool HasDoublePrecisionVertices() const;
3453 
3454  bool HasSinglePrecisionVertices() const;
3455 
3456 
3457  /*
3458  Description:
3459  If you modify the values of double precision vertices,
3460  then you must call UpdateSinglePrecisonVertices().
3461  Remarks:
3462  If double precision vertices are not present, this function
3463  does nothing.
3464  */
3465  void UpdateSinglePrecisionVertices();
3466 
3467  /*
3468  Description:
3469  If you modify the values of the single precision vertices
3470  in m_V[], then you must call UpdateDoublePrecisionVertices().
3471  Remarks:
3472  If double precision vertices are not present, this function
3473  does nothing.
3474  */
3475  void UpdateDoublePrecisionVertices();
3476 
3477  /*
3478  Description:
3479  The function removes all double precision vertex information.
3480  */
3481  void DestroyDoublePrecisionVertices();
3482 
3483 
3484  /////////////////////////////////////////////////////////////////
3485  // Implementation - mesh geometry
3486 
3487  // Vertex locations
3488  // In a case where adjacent facets share a vertex
3489  // location but have distinct normals or texture
3490  // coordinates at that location, the vertex must
3491  // be duplicated.
3492 
3493  /*
3494  Description:
3495  Get double precision vertices. If they do not exist,
3496  they will be created and match the existing single
3497  precision vertices.
3498  Returns:
3499  Array of double precision vertices. If you modify the
3500  values in this array, you must make the same modifications
3501  to the single precision vertices, or call
3502  UpdateSinglePrecisonVertices().
3503  Example:
3504 
3505  // add a bunch of double precision information
3506  ON_3dPointArray& dv = mesh.DoublePrecisionVertices();
3507  for ( i = 0; i < lots; i++ )
3508  {
3509  dv[i] = ...
3510  }
3511  // This call updates the single precison values
3512  // in m_V[] and sets all the counts and CRCs that
3513  // are used in validity checking.
3514  mesh.UpdateSinglePrecisonVertices();
3515 
3516  Remarks:
3517  Avoid mulitple calls to DoublePrecisionVertices().
3518  It is most efficient to make one call, save a local
3519  reference, and use the local reference as needed.
3520  */
3521  ON_3dPointArray& DoublePrecisionVertices();
3522  const ON_3dPointArray& DoublePrecisionVertices() const;
3523 
3524  /*
3525  Description:
3526  m_dV[] double precision vertices.
3527  m_V[] single precision vertices.
3528 
3529  If m_dV[] is not empty, then m_V and m_dV should have the same length
3530  and HasSynchronizedDoubleAndSinglePrecisionVertices() should be true.
3531 
3532  Otherwise a bug incorrectly modified vertex location information.
3533 
3534  If m_dV[] and m_V[] are in use and you modify vertex locations or count,
3535  then your calculation should insure both are properly updated.
3536  */
3537  ON_3dPointArray m_dV;
3538  ON_3fPointArray m_V;
3539 
3540  /*
3541  Returns:
3542  Location of the vertex. If double precision vertices
3543  are present, the double precision vertex location is
3544  returned. If vertex_index is out of range,
3545  ON_UNSET_VALUE is returned.
3546  */
3547  ON_3dPoint Vertex(int vertex_index) const;
3548 
3549  // m_F[] facets (triangles or quads)
3550  ON_SimpleArray<ON_MeshFace> m_F;
3551 
3552  ////////////////////////////////////////////////////////////////////////
3553  //
3554  // N-gon
3555  //
3556  // An n-gon is a collection of faces that are grouped together.
3557  // The outer boundary of the face collection must be a closed
3558  // polyline.
3559  //
3560 
3561  ////////////////////////////////////////////////////////////////////////
3562  //
3563  // N-gon interface
3564  //
3565 
3566  /*
3567  Number of n-gons in this mesh.
3568  */
3569  int NgonCount() const;
3570 
3571  /*
3572  Number of n-gons in this mesh.
3573  */
3574  unsigned int NgonUnsignedCount() const;
3575 
3576  /*
3577  Returns:
3578  null - This mesh does ot have n-gon information.
3579  not null - a pointer to an array of ON_MeshNgon pointers.
3580  The array has length ON_Mesh::NgonCount().
3581  Remarks:
3582  If ON_Mesh::RemoveNgon has been called, then the array
3583  can contain null pointers.
3584  */
3585  const ON_MeshNgon* const * Ngons() const;
3586 
3587  /*
3588  Parameters:
3589  ngon_index - [in]
3590  Index of an ngon.
3591  Returns:
3592  A pointetr to the indexed n-gon or null if the
3593  indexed ngon is null or ngon_index is out of range.
3594  Remarks:
3595  If ON_Mesh::RemoveNgon has been called, then a null
3596  pointer can be returned even when ngon_index >= 0
3597  and ngon_index < ON_Mesh.NgonCount().
3598  */
3599  const ON_MeshNgon* Ngon(
3600  unsigned int ngon_index
3601  ) const;
3602 
3603  /*
3604  Parameters:
3605  ngon_index - [in]
3606  Index of an ngon.
3607  Returns:
3608  Total number of boundary edges, including interior edges
3609  */
3610  unsigned int NgonBoundaryEdgeCount(
3611  unsigned int ngon_index
3612  ) const;
3613 
3614  const ON_MeshNgon* NgonFromComponentIndex(
3615  class ON_MeshNgonBuffer& ngon_buffer,
3616  ON_COMPONENT_INDEX ci
3617  ) const;
3618 
3619  /*
3620  Description:
3621  Add a new ngon to the mesh.
3622  Parameters:
3623  Vcount - number of vertices and number of sides in the n-gon
3624  ngon_vi[] - in
3625  An array of N distinct ON_Mesh.m_V[] vertex indices
3626  Fcount - [in]
3627  Number of face that make up the ngon.
3628  ngon_fi[]
3629  An array of N distinct ON_Mesh.m_F[] face indices
3630  The outer boundary of this group of faces should
3631  be the list of vertices passes as ngon_vi[]
3632  Returns:
3633  index of the new n-gon.
3634  -1: If input information is not valid.
3635  */
3636  int AddNgon(
3637  unsigned int Vcount,
3638  const unsigned int* ngon_vi,
3639  unsigned int Fcount,
3640  const unsigned int* ngon_fi
3641  );
3642 
3643  bool ModifyNgon(
3644  unsigned int ngon_index,
3645  unsigned int Vcount,
3646  const unsigned int* ngon_vi,
3647  unsigned int Fcount,
3648  const unsigned int* ngon_fi
3649  );
3650 
3651  bool ModifyNgon(
3652  unsigned int ngon_index,
3653  const ON_MeshNgon* ngon
3654  );
3655 
3656  /*
3657  Description:
3658  Insert an n-gon in the ngon list. This is generally
3659  slow. Use AddNgon or ModifyNgon.
3660  */
3661  bool InsertNgon(
3662  unsigned int ngon_index,
3663  const ON_MeshNgon* ngon
3664  );
3665 
3666  /*
3667  Returns:
3668  Average of the n-gon vertex locations.
3669  */
3670  ON_3dPoint NgonCenter(
3671  unsigned int ngon_index
3672  ) const;
3673 
3674  /*
3675  Returns:
3676  Average of the n-gon vertex locations.
3677  */
3678  ON_3dPoint NgonCenter(
3679  const ON_MeshNgon* ngon
3680  ) const;
3681 
3682  /*
3683  Returns:
3684  Bounding box of the n-gon vertex locations.
3685  */
3686  ON_BoundingBox NgonBoundaryBoundingBox(
3687  unsigned int ngon_index
3688  ) const;
3689 
3690  /*
3691  Returns:
3692  Bounding box of the n-gon vertex locations.
3693  */
3694  ON_BoundingBox NgonBoundaryBoundingBox(
3695  const ON_MeshNgon* ngon
3696  ) const;
3697 
3698  /*
3699  Parameters:
3700  ngon - [in]
3701  bAppendStartPoint - [in]
3702  If true, the initial point in the boundary will be added
3703  as the first point of ngon_boundary_points[] and then
3704  added again as the last point of ngon_boundary_points[].
3705  This is useful when you need a closed polyline.
3706  ngon_boundary_points - [out]
3707  An array of ngon->m_Vcount + (bAppendStartPoint ? 1 : 0)
3708  points.
3709  Returns:
3710  Number of points added to ngon_boundary_points[] or 0 if invalid
3711  input is encountered.
3712  */
3713  unsigned int GetNgonBoundaryPoints(
3714  const ON_MeshNgon* ngon,
3715  bool bAppendStartPoint,
3716  ON_SimpleArray<ON_3dPoint>& ngon_boundary_points
3717  ) const;
3718 
3719  /*
3720  Parameters:
3721  ngon - [in]
3722  bAppendStartPoint - [in]
3723  If true, the initial point in the boundary will be added
3724  as the first point of ngon_boundary_points[] and then
3725  added again as the last point of ngon_boundary_points[].
3726  This is useful when you need a closed polyline.
3727  ngon_boundary_points - [out]
3728  An array of ngon->m_Vcount + (bAppendStartPoint ? 1 : 0) points
3729  is returned in ngon_boundary_points[]. The caller must insure
3730  that ngon_boundary_points[] has room for this many elements.
3731  Returns:
3732  Number of points added to ngon_boundary_points[] or 0 if invalid
3733  input is encountered.
3734  */
3735  unsigned int GetNgonBoundaryPoints(
3736  const ON_MeshNgon* ngon,
3737  bool bAppendStartPoint,
3738  ON_3dPoint* ngon_boundary_points
3739  ) const;
3740 
3741  /*
3742  Description:
3743  If the mesh has ngons with ON_MeshNgon.Orientation() = -1,
3744  the reverse the ngon's boundary orientation.
3745  Parameters:
3746  bPermitHoles - [in]
3747  ngons may contain holes.
3748  Returns:
3749  True if all non-empty ngons have ON_MeshNgon.Orientation()=1 after the call.
3750  */
3751  bool OrientNgons(
3752  bool bPermitHoles
3753  );
3754 
3755  /*
3756  Description:
3757  Remove an n-gon.
3758  Parameters:
3759  ngon_index - [in]
3760  Returns:
3761  True if ngon_index was valid and the corresponding n-gon was removed.
3762  Remarks:
3763  The mesh triangles that make up the n-gon are not deleted.
3764  */
3765  bool RemoveNgon(
3766  unsigned int ngon_index
3767  );
3768 
3769  unsigned int RemoveNgons(
3770  unsigned int ngon_index_count,
3771  const unsigned int* ngon_index_list
3772  );
3773 
3774  /*
3775  Description:
3776  Remove null and empty entries from the ON_Mesh n-gon list.
3777  */
3778  void RemoveEmptyNgons();
3779 
3780  /*
3781  Description:
3782  Remove all entries from the ON_Mesh n-gon list.
3783  Remarks:
3784  Same as SetNgonCount(0)
3785  */
3786  void RemoveAllNgons();
3787 
3788  /*
3789  Description:
3790  Set the n-gon count. Null n-gons are be appended
3791  when ngon_count > current count. Existing n-gons are
3792  removed when ngon_count < current count.
3793  Parameters:
3794  ngon_count - [in]
3795  Number of n-gons to have.
3796  0: removes all ngons.
3797  Remarks:
3798  The mesh triangles that make up any removed n-gons are not deleted.
3799  */
3800  void SetNgonCount(
3801  unsigned int ngon_count
3802  );
3803 
3804  /*
3805  Parameters:
3806  face_index - [in]
3807  Mesh face ON_Mesh.m_F[] index.
3808  Returns:
3809  ON_UNSET_UINT_INDEX:
3810  The face is not part of an n-gon.
3811  Otherwise:
3812  Index of the n-gon the face is part of.
3813  */
3814  unsigned int NgonIndexFromFaceIndex(
3815  unsigned int face_index
3816  ) const;
3817 
3818  /*
3819  Returns:
3820  null:
3821  The ngonMap does not exist.
3822  an array of length m_F.Count():
3823  The value of the i-th element is either the index of the n-gon
3824  the mesh face m_F[i] belongs to or ON_UNSET_UINT_INDEX when
3825  m_F[i] does not belong to an n-gon.
3826  */
3827  const unsigned int* NgonMap() const;
3828 
3829  const unsigned int* NgonMap(
3830  bool bCreateIfMissing
3831  );
3832 
3833  /*
3834  Returns:
3835  true if the n-gon information is valid for adding an n-gon to this mesh.
3836  Parameters:
3837  Vcount - [in]
3838  Number of vertices and sides in the n-gon.
3839  ngon_vi - [in]
3840  */
3841  bool IsValidNewNgonInformation(
3842  unsigned int Vcount,
3843  const unsigned int* ngon_vi,
3844  unsigned int Fcount,
3845  const unsigned int* ngon_fi
3846  ) const;
3847 
3848  /*
3849  Description:
3850  For each set of coplanar connected faces in the mesh that
3851  qualifies as an n-gon, an new ON_MeshNgon will be appended
3852  to the Ngons[] array. Faces belonging to existing ngons are
3853  ignored.
3854  Parameters:
3855  vertex_face_map - [in]
3856  - Pass null if you don't have one.
3857  - See ON_MeshVertexFaceMap for details about making one.
3858  The only reason to pass one in is because you
3859  need it for other reasons or you already have one.
3860  planar_tolerance - [in]
3861  For faces to be coplanar, all the points in the
3862  n-gon must be withing planar_tolerance of the plane
3863  defined by the first face in the n-gon.
3864  minimum_ngon_vertex_count - [in]
3865  n-gons must have at least this many sides in order
3866  to be added.
3867  minimum_ngon_face_count - [in]
3868  n-gons must have at least this many faces in order to
3869  be added.
3870  bAllowHoles - [in]
3871  If true, then the added ngons are permitted to have holes.
3872  bSeparateNgons - [in]
3873  If true, any face belonging to a new ngon, will not
3874  share vertices with a face that does not belong to that
3875  ngon and the vertex normals for all vertices in an ngon will
3876  be set to the plane's normal.
3877  bSetNgonVertexNormals - [in]
3878  If bSeparateNgons and bSetNgonVertexNormals are both true,
3879  then all vertex normals vertices in a new ngon will be
3880  set to the ngon's plane normal.
3881  bRemoveNgonInteriorPoints - [in]
3882  If true, the new ngons will not have interior vertices.
3883  This will result in the ngon being retriangluated
3884  when connected coplanar faces
3885  Returns:
3886  The number of new n-gons appended to m_Ngons[]
3887  */
3888  unsigned int AddPlanarNgons(
3889  const unsigned int *const* vertex_face_map,
3890  double planar_tolerance,
3891  unsigned int minimum_ngon_vertex_count,
3892  unsigned int minimum_ngon_face_count,
3893  bool bAllowHoles
3894  );
3895 
3896  /*
3897  Description:
3898  For each ngon with index in the specified range,
3899  duplicate vertices as needed so that the ngon
3900  does not share any vertices with faces that do not
3901  belong to the ngon.
3902  Parameters:
3903  vertex_face_map - [in]
3904  - Pass null if you don't have one.
3905  - See ON_MeshVertexFaceMap for details about making one.
3906  The only reason to pass one in is because you
3907  need it for other reasons or you already have one.
3908  - Note that if true is returned, then the information
3909  in this vertex_face_map will be changed and no
3910  information will be added for the new vertices.
3911  ngon_index0 - [in]
3912  ngon_index1 - [in]
3913  ngons with indices ni satisfying
3914  ngon_index0 <= ni < ngon_index1 will be separated.
3915  To separate every ngon in a mesh, pass
3916  ngon_index0 = 0 and ngon_index1 = mesh->NgonCount().
3917  Returns:
3918  true
3919  one or more vertices were duplicated to separate an ngon
3920  from it's neighboring faces. This changes the mesh's
3921  vertex and face information and invalidates any input
3922  vertex_face_map.
3923  false
3924  The mesh was not modified.
3925  */
3926  bool SeparateNgons(
3927  unsigned int** vertex_face_map,
3928  unsigned int ngon_index0,
3929  unsigned int ngon_index1
3930  );
3931 
3932  /*
3933  Description:
3934  For each ngon with index in the specified range,
3935  all vertices in the ngon will have their vertex normal
3936  set to the normal of the first face in the ngon.
3937  Parameters:
3938  ngon_index0 - [in]
3939  ngon_index1 - [in]
3940  ngons with indices ni satisfying
3941  ngon_index0 <= ni < ngon_index1 will be separated.
3942  To separate every ngon in a mesh, pass
3943  ngon_index0 = 0 and ngon_index1 = mesh->NgonCount().
3944  Returns:
3945  true
3946  one or more vertices were duplicated to separate an ngon
3947  from it's neighboring faces. This changes the mesh's
3948  vertex and face information and invalidates any input
3949  vertex_face_map.
3950  false
3951  The mesh was not modified.
3952  */
3953  bool SetNgonVertexNormals(
3954  unsigned int ngon_index0,
3955  unsigned int ngon_index1
3956  );
3957 
3958  /*
3959  Description:
3960  For each ngon with index in the specified range that has
3961  interior vertices, remove the interior vertices and
3962  triangluate the ngon.
3963  Parameters:
3964  vertex_face_map - [in]
3965  - Pass null if you don't have one.
3966  - See ON_MeshVertexFaceMap for details about making one.
3967  The only reason to pass one in is because you
3968  need it for other reasons or you already have one.
3969  - If true is returned, then the information
3970  in this vertex_face_map will be invalid because
3971  vertices will be removed.
3972  ngon_index0 - [in]
3973  ngon_index1 - [in]
3974  ngons with indices ni satisfying
3975  ngon_index0 <= ni < ngon_index1 will be separated.
3976  To separate every ngon in a mesh, pass
3977  ngon_index0 = 0 and ngon_index1 = mesh->NgonCount().
3978  Returns:
3979  true
3980  one or more vertices were removed and one or more ngons
3981  were triangluated. This changes the mesh's vertex and face
3982  information and invalidates any input vertex_face_map.
3983  false
3984  The mesh was not modified.
3985  Remarks:
3986  If true is returned and you are finished modify the mesh, then
3987  call ON_Mesh::Compact() or ON_Mesh::CullUnusedVertices() to remove
3988  the unreferenced interior vertices.
3989  */
3990  bool RemoveNgonInteriorVertices(
3991  const unsigned int *const* vertex_face_map,
3992  unsigned int ngon_index0,
3993  unsigned int ngon_index1
3994  );
3995 
3996  /*
3997  Descrption:
3998  Given a group of connected coplanar faces,
3999  find the n-gon boundary.
4000  ngon_fi_count - [in]
4001  number of indices in ngon_fi[]
4002  ngon_fi - [in]
4003  Indices of faces in the ON_Mesh.m_F[] array.
4004  ngon_vi - [out]
4005  An ordered list of indices of vertices in the ON_Mesh.m_V[]
4006  array that for the outer boundary of the n-gon. The natural
4007  counter-clockwise orientation of the first face with a
4008  boundary edge determines the order of the ngon_vi[] list.
4009  */
4010  unsigned int GetNgonOuterBoundary(
4011  unsigned int ngon_fi_count,
4012  const unsigned int* ngon_fi,
4014  ) const;
4015 
4016  /*
4017  Description:
4018  An expert user function that allocates an ngon from heap
4019  memory managed by this ON_Mesh.
4020  Parameters:
4021  N - [in] (>= 3)
4022  Fcount - [in]
4023  Returns:
4024  A pointer to an uninitialized ngon.
4025  Use the ON_Mesh::AddNgon(ngon) to add this ngon to the mesh
4026  or use DeallocateNgon(ngon) to deallocate the ngon.
4027  */
4028  ON_MeshNgon* AllocateNgon(
4029  unsigned int Vcount,
4030  unsigned int Fcount
4031  );
4032 
4033  /*
4034  Description:
4035  An expert user function that deallocates an ngon
4036  that was created by AllocateNgon().
4037  Parameters:
4038  ngon - [in]
4039  */
4040  bool DeallocateNgon(
4041  ON_MeshNgon* ngon
4042  );
4043 
4044  /*
4045  Description:
4046  An expert user function that unconditionally appends the ngon
4047  pointer to ON_Mesh.m_Ngon[].
4048  Parameters:
4049  ngon - [in]
4050  Returns:
4051  ON_UNSET_UINT_INDEX: invalid input
4052  < ON_UNSET_UINT_INDEX: index of the new n-gon.
4053  */
4054  unsigned int AddNgon(
4055  ON_MeshNgon* ngon
4056  );
4057 
4058  /*
4059  Description:
4060  Expert user function to update n-gon map after the expert user
4061  does something to make the current one invalid.
4062  Returns:
4063  null:
4064  The mesh does not have ngon-information.
4065  an array of length m_F.Count() ngon_map[]
4066  - If ngon_map[fi] >= 0, then ON_MeshFace.m_F[fi] belongs
4067  to ON_Mesh.Ngon(ngon_map[fi]).
4068  - Otherwise, ngon_map[fi] = -1.
4069  */
4070  const unsigned int* CreateNgonMap();
4071 
4072 
4073  /*
4074  Description:
4075  Expert user function to delete n-gon map information
4076  but leave n-gon definition information unchanged.
4077  Description:
4078  Removes any existing n-gon map.
4079  Does not remove other n-gon information.
4080  */
4081  void RemoveNgonMap();
4082 
4083  ////////////////////////////////////////////////////////////////////////
4084  //
4085  // N-gon implementation
4086  //
4087 
4088  // If ON_Mesh::HasNgons() is true, then the mesh has n-gons.
4089  // When a mesh has ngons, m_NgonMap[] is used to determine when
4090  // a face belongs to an n-gon.
4091  // If m_NgonMap[fi] >= 0, then it is the index of the ngon m_F[]
4092  // belongs to. Otherwise, m_Fngon[fi] is -1.
4093  ON_SimpleArray<unsigned int> m_NgonMap; // invalid if m_NgonMap.Count() != m_F.Count()
4094  ON_SimpleArray<ON_MeshNgon*> m_Ngon;
4095  ON_MeshNgonAllocator m_NgonAllocator; // use this to allocate elements added to m_Ngon;
4096 
4097  ////////////////////////////////////////////////////////////////////////
4098  //
4099  // Vertex and Face normal implementation
4100  //
4101 
4102  // m_N[] OPTIONAL vertex unit normals
4103  // If m_N[] is empty or m_N.Count() != m_V.Count(),
4104  // Either m_N[] has zero count or it m_N[j] is the
4105  // the unit vertex normal at m_V[j].
4106  ON_3fVectorArray m_N;
4107 
4108  // m_FN[] OPTIONAL face unit normals
4109  // If m_FN[] is empty or m_FN.Count() != m_F.Count(),
4110  // then m_FN is ignored. Otherwise m_FN[j] is the
4111  // unit normal for the facet m_F[j].
4112  ON_3fVectorArray m_FN;
4114  /////////////////////////////////////////////////////////////////
4115  // Implementation - texture coordinates
4116  //
4117  // OPTIONAL texture coordinates for each vertex
4118 
4119  // It would be nice if this were an ON_TextureCoordinates,
4120  // but that breaks lots of checked out code that assumes
4121  // m_T is an array of ON_2fPoints.
4122  ON_MappingTag m_Ttag; // OPTIONAL tag for values in m_T[]
4123  ON_2fPointArray m_T; // OPTIONAL texture coordinates for each vertex
4124 
4125  // RUNTIME ONLY
4126  // This array is used to cache texture coordinates used by
4127  // rendering applications that require 1d texture coordinates,
4128  // 3d texture coordinates, or multiple sets of texture
4129  // coordinates (e.g. blended textures with different mappings).
4130  // Users are responsible for verifying
4131  // m_TC[i].m_T.Count() = m_V.Count()
4132  ON_ClassArray<ON_TextureCoordinates> m_TC;
4133 
4134  // If m_T.Count() == m_V.Count(), then the mesh has texture coordinates
4135  // and m_T[j] is the texture coordinate for vertex m_V[j].
4136  //
4137  // When opennurbs or Rhino meshes an ON_Surface or ON_Brep, the texture
4138  // coordinates have a "canonical" linear relationship with the surface
4139  // parameters that is described in the next section. However, various
4140  // mappings, spherical, planar, cylindrical, etc., can be applied that
4141  // change the values of the texture coordinates.
4142  //
4143  // If a texture mapping function was used to set the m_T[] values,
4144  // then the id and serial number of the mapping function is saved
4145  // in m_mapping_id and m_mapping_sn. The intended use of these fields
4146  // is to make it easy to avoid unnecessary recalculation.
4147  // If a mesh is modified, then m_mapping_id should be set to nil
4148  // and m_mapping_crc should be set to 0.
4149  //
4150  /////////////////////////////////////////////////////////////////
4151 
4152 
4153  /////////////////////////////////////////////////////////////////
4154  // Implementation - surface parameters and packed texture
4155  // information
4156  //
4157  // If m_S.Count() == m_V.Count(), then the mesh is a tesselation
4158  // of a parameteric surface and m_S[j] is the surface parameter at
4159  // m_V[j]. Storing values in m_S[] is OPTIONAL.
4160  //
4161  // If m_srf_scale[] has positive values, then they report
4162  // the world coordinate size of a rectangle that would
4163  // minimize texture distortion if it were mapped to the
4164  // mesh using normalized surface evaluation parameters.
4165  // This information is used to calculate high quality
4166  // packed texture coordinates.
4167  ON_2dPointArray m_S;
4168  ON_Interval m_srf_domain[2]; // surface evaluation domain.
4169  double m_srf_scale[2];
4170 
4171 
4172  // Packed texture information.
4173  //
4174  // If either of the m_packed_tex_domain[] intervals is a
4175  // proper subinterval of (0,1), then a texture packing
4176  // calculation assigned this subrectangle to this mesh.
4177 
4178  ON_Interval m_packed_tex_domain[2];
4179 
4180  // The m_packed_tex_rotate setting is valid only when
4181  // m_S, m_srf_domain, m_packed_scale[] and
4182  // m_packed_tex_domain[] are all valid and the texture
4183  // coordinates are based on surface evaluation parameters.
4184  // In this special situation, this boolean records the
4185  // correspondence between the the surface parameters, (u,v),
4186  // and the packed texture coordinates, (s,t),
4187  //
4188  // m_packed_tex_rotate = false:
4189  // a = m_srf_domain[0].NormalizedParameterAt(u);
4190  // b = m_srf_domain[1].NormalizedParameterAt(v);
4191  // s = m_packed_tex_domain[0].ParameterAt(a);
4192  // t = m_packed_tex_domain[1].ParameterAt(b);
4193  //
4194  // x = m_packed_tex_domain[0].NormalizedParameterAt(s);
4195  // y = m_packed_tex_domain[1].NormalizedParameterAt(t);
4196  // u = m_srf_domain[0].ParameterAt(x);
4197  // v = m_srf_domain[1].ParameterAt(y);
4198  //
4199  // m_packed_tex_rotate = true:
4200  // a = m_srf_domain[0].NormalizedParameterAt(u);
4201  // b = m_srf_domain[1].NormalizedParameterAt(v);
4202  // s = m_packed_tex_domain[0].ParameterAt(a);
4203  // t = m_packed_tex_domain[1].ParameterAt(1.0-b);
4204  //
4205  // x = m_packed_tex_domain[0].NormalizedParameterAt(s);
4206  // y = m_packed_tex_domain[1].NormalizedParameterAt(t);
4207  // u = m_srf_domain[0].ParameterAt(y);
4208  // v = m_srf_domain[1].ParameterAt(1.0 - x);
4209  bool m_packed_tex_rotate;
4210 
4211  /*
4212  Returns:
4213  True if the m_srf_scale[] values are positive and
4214  the m_packed_tex_domain[] intervals are set to values
4215  that describe a proper subrectangle of (0,1)x(0,1).
4216  True does not necessarily mean the current values in
4217  m_T[] are packed texture coordinates.
4218  */
4219  bool HasPackedTextureRegion() const;
4220 
4221  /*
4222  Description:
4223  If the mesh does not have surface evaulation parameters,
4224  has texture coordinates, and the surface parameters can
4225  be set in a way so the existing texture coordinates can
4226  be computed from the surface parameters, then this function
4227  sets the surface parameters. This is useful when meshes
4228  that have texture coordinates and do not have surface
4229  parameters want ot set the surface parameters in a way
4230  so that the texture mapping
4231  ON_TextureMapping::SurfaceParameterTextureMapping
4232  will restore the texture coordinates.
4233  Returns:
4234  true - successful
4235  false - failure - no changes made to the mesh.
4236  */
4237  bool SetSurfaceParamtersFromTextureCoodinates();
4238 
4239 
4240  /////////////////////////////////////////////////////////////////
4241  // Implementation - curvature
4242 
4243  ON_SimpleArray<ON_SurfaceCurvature> m_K; // OPTIONAL surface curvatures
4244  // Either m_K[] has zero count or it has the same
4245  // count as m_V[], in which case m_K[j] reports
4246  // the surface curvatures at m_V[j].
4247 
4248  /////////////////////////////////////////////////////////////////
4249  // Implementation - false color
4250  ON_MappingTag m_Ctag; // OPTIONAL tag for values in m_C[]
4251  ON_SimpleArray<ON_Color> m_C; // OPTIONAL vertex color
4252  // Either m_C[] has zero count or it has the same
4253  // count as m_V[], in which case m_C[j] reports
4254  // the color assigned to m_V[j].
4255 
4256  /////////////////////////////////////////////////////////////////
4257  // Implementation - runtime vertex visibility - not saved in 3dm files.
4258  ON_SimpleArray<bool> m_H; // OPTIONAL vertex visibility.
4259  // If m_H.Count() = m_V.Count(), then
4260  // m_H[vi] is true if the vertex m_V[vi]
4261  // is hidden. Otherwise, all vertices are visible.
4262  int m_hidden_count; // number of vertices that are hidden
4263  // = number of true values in m_H[] array.
4264 
4265  /////////////////////////////////////////////////////////////////
4266  // Implementation - runtime UI information
4267  const ON_Object* m_parent; // runtime parent geometry (use ...::Cast() to get it)
4268 
4269 protected:
4270 
4271  /////////////////////////////////////////////////////////////////
4272  // Implementation - mesh topology
4273  ON_MeshTopology m_top;
4274 
4275  ON_MeshParameters* m_mesh_parameters; // If mesh was created from a parametric surface,
4276  // these parameters were used to create the mesh.
4277  int m_invalid_count;
4278  int m_quad_count;
4279  int m_triangle_count;
4280 
4281 private:
4282  char m_mesh_is_closed; // 0 = unset, 1 = all edges have 2 or more faces, 2 = at least one boundary edge
4283  char m_mesh_is_manifold; // 0 = unset, 1 = all edges have 1 or 2 faces, 2 = not manifold
4284  char m_mesh_is_oriented; // 0 = unset, 1 = faces normals agree across all edges that have 2 faces, 2 = not oriented
4285  char m_mesh_is_solid; // 0 = unset, 1 = solid with outward face normals, 2 = solid with inward face normals, 3 = not solid
4286 
4287 private:
4288  mutable ON_BoundingBox m_vertex_bbox = ON_BoundingBox::UnsetBoundingBox;
4289 
4290 protected:
4291  float m_nbox[2][3]; // 3d bounding box of all referenced unit normals
4292  // (for estimation of Gauss map bounds)
4293  float m_tbox[2][2]; // 2d bounding box of all referenced texture coordinates
4294 
4295 private:
4296  // m_vertex_bbox = bounding box of vertex locations
4297 
4298  // cache of recently used tight bounding boxes
4299  mutable ON_BoundingBoxCache m_tight_bbox_cache;
4300 
4301 protected:
4302 
4303  ON_MeshCurvatureStats* m_kstat[4]; // gaussian,mean,min,max,sectionx,sectiony,sectionz
4304 
4305  // sub-mesh information rendering large meshes
4306  ON_MeshPartition* m_partition;
4307 
4308 
4309 private:
4310  bool Write_1( ON_BinaryArchive& ) const; // uncompressed 1.x format
4311  bool Write_2( int, ON_BinaryArchive& ) const; // compressed 2.x format
4312  bool Read_1( ON_BinaryArchive& );
4313  bool Read_2( int, ON_BinaryArchive& );
4314  bool WriteFaceArray( int, int, ON_BinaryArchive& ) const;
4315  bool ReadFaceArray( int, int, ON_BinaryArchive& );
4316  bool SwapEdge_Helper( int, bool );
4317 };
4318 
4319 //////////////////////////////////////////////////////////////////////////
4320 //
4321 // ON_MeshCache
4322 //
4323 class ON_CLASS ON_MeshCache
4324 {
4325 public:
4326  static const ON_MeshCache Empty;
4327 
4328  static const ON_UUID RenderMeshId;
4329  static const ON_UUID AnalysisMeshId;
4330  static const ON_UUID PreviewMeshId;
4331  static const ON_UUID AnyMeshId;
4332 
4333  // Cached mesh with the fewest faces
4334  static const ON_UUID CoarseMeshId;
4335 
4336  // Cached mesh with the most faces
4337  static const ON_UUID FineMeshId;
4338 
4339  /*
4340  Returns:
4341  The id that corresonds to the obsolete ON::mesh_type enum value.
4342  Remarks:
4343  Ids are used to allow custom meshes to be cached.
4344  */
4345  static ON_UUID MeshIdFromMeshType(
4346  ON::mesh_type mesh_type
4347  );
4348 
4349 public:
4350  ON_MeshCache() = default;
4352  ON_MeshCache( const ON_MeshCache& src );
4353  ON_MeshCache& operator=( const ON_MeshCache& src );
4354 
4355 #if defined(ON_HAS_RVALUEREF)
4356  // rvalue copy constructor
4357  ON_MeshCache( ON_MeshCache&& ) ON_NOEXCEPT;
4358 
4359  ON_MeshCache& operator=( ON_MeshCache&& );
4360 #endif
4361 
4362 public:
4363 
4364  /*
4365  Parameters:
4366  mesh_id - [in]
4367  mesh_id cannot be nil or ON_MeshCache::AnyMeshId.
4368  */
4369  void SetMesh(
4370  ON_UUID mesh_id,
4371  const std::shared_ptr<ON_Mesh>& mesh_sp
4372  );
4373  void SetMesh(
4374  ON::mesh_type mesh_type,
4375  const std::shared_ptr<ON_Mesh>& mesh_sp
4376  );
4377 
4378  /*
4379  Parameters:
4380  mesh_id - [in]
4381  If mesh_id is ON_MeshCache::AnyMeshId, then every cached mesh
4382  will be deleted.
4383  */
4384  void ClearMesh(
4385  ON_UUID mesh_id
4386  );
4387  void ClearMesh(
4388  ON::mesh_type mesh_type
4389  );
4390 
4391  void ClearAllMeshes();
4392 
4393  /*
4394  Parameters:
4395  bDeleteMesh - [in]
4396  true
4397  ON_Mesh will be deleted.
4398  false
4399  ON_Mesh will not be deleted. This is typically done when the
4400  mesh was in the process of being created in a separate thread
4401  and memory pool, both of which were killed and the pointer
4402  to the mesh is no longer valid.
4403  */
4404  void ClearMesh(
4405  ON_UUID mesh_id,
4406  bool bDeleteMesh
4407  );
4408 
4409  /*
4410  Parameters:
4411  bDeleteMesh - [in]
4412  true
4413  ON_Mesh will be deleted.
4414  false
4415  ON_Mesh will not be deleted. This is typically done when the
4416  mesh was in the process of being created in a separate thread
4417  and memory pool, both of which were killed and the pointer
4418  to the mesh is no longer valid.
4419  */
4420  void ClearMesh(
4421  ON::mesh_type mesh_type,
4422  bool bDeleteMesh
4423  );
4424 
4425 
4426  /*
4427  Parameters:
4428  bDeleteMeshes - [in]
4429  true
4430  ON_Mesh will be deleted.
4431  false
4432  ON_Mesh will not be deleted. This is typically done when the
4433  mesh was in the process of being created in a separate thread
4434  and memory pool, both of which were killed and the pointer
4435  to the mesh is no longer valid.
4436  */
4437  void ClearAllMeshes(
4438  bool bDeleteMeshes
4439  );
4440 
4441  /*
4442  Parameters:
4443  mesh_id - [in]
4444  If mesh_id is ON_MeshCache::AnyMeshId, then the most recently cached mesh is returned.
4445  */
4446  const ON_Mesh* Mesh(
4447  ON_UUID mesh_id
4448  ) const;
4449  const ON_Mesh* Mesh(
4450  ON::mesh_type mesh_type
4451  ) const;
4452 
4453 
4454  /*
4455  Parameters:
4456  mesh_id - [in]
4457  If mesh_id is ON_MeshCache::AnyMeshId, then the most recently cached mesh is returned.
4458  */
4459  std::shared_ptr<ON_Mesh> MeshSharedPtr(
4460  ON_UUID mesh_id
4461  ) const;
4462 
4463  std::shared_ptr<ON_Mesh> MeshSharedPtr(
4464  ON::mesh_type mesh_type
4465  ) const;
4466 
4467  unsigned int MeshCount() const;
4468 
4469  bool Write(
4470  ON_BinaryArchive& archive
4471  ) const;
4472 
4473  bool Read(
4474  ON_BinaryArchive& archive
4475  );
4476 
4477  void Dump(
4478  ON_TextLog& text_log
4479  ) const;
4480 
4481  bool Transform(
4482  const ON_Xform& xform
4483  );
4484 
4485 private:
4486  void Internal_CopyHelper(
4487  const class ON_MeshCacheItem* src_item_list
4488  );
4489 
4490  class ON_MeshCacheItem* Internal_FindHelper(
4491  ON_UUID mesh_type
4492  ) const;
4493 
4494  class ON_MeshCacheItem* Internal_CreateItem();
4495  class ON_MeshCacheItem* Internal_CopyItem(const class ON_MeshCacheItem& src_item);
4496 
4497  void Internal_DeleteItem(class ON_MeshCacheItem*,bool bDeleteMesh);
4499  class ON_MeshCacheItem* m_impl = nullptr;
4500 };
4501 
4502 class ON_CLASS ON_MeshNgonIterator
4503 {
4504 public:
4505 
4506  static const ON_MeshNgonIterator EmptyMeshNgonIterator;
4507 
4508  ON_MeshNgonIterator() = default;
4509  ~ON_MeshNgonIterator() = default;
4510 
4512  const ON_MeshNgonIterator& src
4513  );
4514 
4515  ON_MeshNgonIterator& operator=(
4516  const ON_MeshNgonIterator& src
4517  );
4518 
4519 
4520  /*
4521  Parameters:
4522  mesh - [in]
4523  If the mesh has explicit ngons, then mesh->NgonMap() must
4524  return true;
4525  */
4527  const class ON_Mesh* mesh
4528  );
4529 
4530  /*
4531  Parameters:
4532  mesh - [in]
4533  If the mesh has explicit ngons,
4534  meshfdex_to_meshngondex_map - [in]
4535  It's generally best to pass the value of mesh->NgonMap(true).
4536  Expert users can specify a custom map if required.
4537  */
4538  void SetMesh(
4539  const class ON_Mesh* mesh,
4540  const unsigned int* meshfdex_to_meshngondex_map
4541  );
4542 
4543  /*
4544  Returns:
4545  The mesh being iterated.
4546  */
4547  const ON_Mesh* Mesh() const;
4548 
4549  /*
4550  Description:
4551  Returns the first ngon.
4552  Returns:
4553  The first ngon when iterating through the mesh
4554  triangles, quads and explicitly defined ngons.
4555  Remarks:
4556  If CurrentNgonIsMeshFace() is true after calling FirstNgon().
4557  the the returned ngon references a triangle or
4558  quad that is not part of an explicitly defined
4559  ngon in the mesh. If you need the information
4560  to persist after any subsequent calls to the iterator
4561  or after the destruction of the iterator, then
4562  you must make and manage a copy of the ngon.
4563  */
4564  const class ON_MeshNgon* FirstNgon();
4565 
4566  /*
4567  Description:
4568  Increments the iterator and returns the next ngon.
4569  Returns:
4570  The next ngon when iterating through the mesh
4571  triangles, quads and explicitly defined ngons.
4572  Remarks:
4573  If CurrentNgonIsMeshFace() is true after calling NextNgon().
4574  the the returned ngon references a triangle or
4575  quad that is not part of an explicitly defined
4576  ngon in the mesh. If you need the information
4577  to persist after any subsequent calls to the iterator
4578  or after the destruction of the iterator, then
4579  you must make and manage a copy of the ngon.
4580  */
4581  const class ON_MeshNgon* NextNgon();
4582 
4583  /*
4584  Description:
4585  Get the ngon most recently returned by FirstNgon()
4586  or NextNgon().
4587  Returns:
4588  Returns the ngon most recently returned by FirstNgon()
4589  or NextNgon().
4590  Remarks:
4591  If CurrentNgonIsMeshFace() is true after calling CurrentNgon().
4592  the the returned ngon references a triangle or
4593  quad that is not part of an explicitly defined
4594  ngon in the mesh. If you need the information
4595  to persist after any subsequent calls to the iterator
4596  or after the destruction of the iterator, then
4597  you must make and manage a copy of the ngon.
4598  */
4599  const class ON_MeshNgon* CurrentNgon();
4600 
4601  ON_COMPONENT_INDEX CurrentNgonComponentIndex() const;
4602  /*
4603  Returns:
4604  If the current iterator ngon references an ON_MeshFace
4605  that is in m_mesh->m_F[] but is not explictly referenced
4606  by an ON_MeshNgon in ON_Mesh.m_Ngon[], then true is returned.
4607  In this case, the ngon's m_fi[] array
4608  has length 1 and contains the face's index, and the ngon's
4609  m_vi[] array is a copy of the faces's vi[] array.
4610  Otherwise false is returned.
4611  */
4612  bool CurrentNgonIsMeshFace() const;
4613 
4614  /*
4615  Returns:
4616  If the current iterator ngon references an ON_MeshNgon
4617  that is in m_mesh->m_Ngon[], then true is returned.
4618  Otherwise false is returned.
4619  */
4620  bool CurrentNgonIsMeshNgon() const;
4621 
4622  /*
4623  Description:
4624  Sets the state of the iterator to the initial state that
4625  exists after construction. This is useful if the iterator
4626  has been used the get one or more elements and then
4627  the referenced mesh is modified or code wants
4628  to begin iteration again a used a call to NextNgon()
4629  to return the first element.
4630  */
4631  void Reset();
4632 
4633  /*
4634  Returns:
4635  Number of ngons that will be iterated over.
4636  Remarks:
4637  The count = explicit ngons + faces that are not in an ngon.
4638  */
4639  unsigned int Count() const;
4640 
4641 private:
4642  const class ON_Mesh* m_mesh = nullptr;
4643  const unsigned int* m_facedex_to_ngondex_map = nullptr;
4644  ON__UINT_PTR m_current_ngon = 0;
4645  ON_MeshNgonBuffer m_ngon_buffer;
4646  ON_COMPONENT_INDEX m_current_ngon_ci = ON_COMPONENT_INDEX::UnsetComponentIndex;
4647  unsigned int m_mesh_face_count = 0;
4648  unsigned int m_mesh_ngon_count = 0;
4649  unsigned int m_iterator_index = 0;
4650 };
4651 
4652 class ON_CLASS ON_MeshComponentRef : public ON_Geometry
4653 {
4654  ON_OBJECT_DECLARE(ON_MeshComponentRef);
4655 public:
4656  static const ON_MeshComponentRef Unset;
4657 
4660  const class ON_Mesh* mesh,
4661  ON_COMPONENT_INDEX ci
4662  );
4664  ON_MeshComponentRef& operator=(const ON_MeshComponentRef&);
4665 
4666 private:
4667  // referenced mesh
4668  const class ON_Mesh* m_mesh;
4669 
4670  // component
4671  ON_COMPONENT_INDEX m_mesh_ci;
4672 
4673 public:
4674  void Set(
4675  const class ON_Mesh* mesh,
4676  ON_COMPONENT_INDEX ci
4677  );
4678 
4679  /*
4680  Returns:
4681  The referenced mesh.
4682  */
4683  const class ON_Mesh* Mesh() const;
4684 
4685  /*
4686  Description:
4687  Override of the virtual ON_Geometry::ComponentIndex().
4688  Returns:
4689  A mesh component index for the face. The type is
4690  ON_COMPONENT_INDEX::mesh_face and the index is the
4691  index into the ON_Mesh.m_F[] array.
4692  */
4693  ON_COMPONENT_INDEX ComponentIndex() const override;
4694 
4695  /*
4696  Returns:
4697  If the mesh topology exists or the component references
4698  a mesh topology component, then this returns a pointer
4699  to the mesh topology.
4700  Otherwise null is returned.
4701  */
4702  const class ON_MeshTopology* MeshTopology() const;
4703 
4704  /*
4705  Returns:
4706  If the component is a vertex, this returns the vertex index.
4707  Otherwise ON_UNSET_UINT_INDEX is returned.
4708  */
4709  unsigned int VertexIndex() const;
4710 
4711  /*
4712  Returns:
4713  If the component is a mesh vertex or mesh topology vertex,
4714  then this returns the vertex location.
4715  Otherwise ON_3dPoint::UnsetPoint is returned.
4716  */
4717  ON_3dPoint VertexPoint() const;
4718 
4719  /*
4720  Parameters:
4721  point - [out]
4722  location of the vertex
4723  Returns:
4724  If the component is a vertex, this returns the vertex index.
4725  Otherwise ON_UNSET_UINT_INDEX is returned.
4726  */
4727  unsigned int GetVertexPoint(
4728  class ON_3dPoint& point
4729  ) const;
4730 
4731  /*
4732  Returns:
4733  If the component is a vertex and mesh topology exists or
4734  the component is a mesh topology vertex, then this returns
4735  a pointer to the mesh topology vertex index.
4736  Otherwise null is returned.
4737  */
4738  const struct ON_MeshTopologyVertex* MeshTopologyVertex() const;
4739 
4740  /*
4741  Returns:
4742  If the component is a vertex and mesh topology exists or
4743  the component is a mesh topology vertex, then this returns
4744  the mesh topology vertex index.
4745  Otherwise ON_UNSET_UINT_INDEX is returned.
4746  */
4747  unsigned int MeshTopologyVertexIndex() const;
4748 
4749  /*
4750  Returns:
4751  If the component is a vertex and mesh topology exists or
4752  the component is a mesh topology vertex, then this returns
4753  the mesh topology vertex index.
4754  Otherwise ON_UNSET_UINT_INDEX is returned.
4755  */
4756  unsigned int GetMeshTopologyVertexPoint(
4757  class ON_3dPoint& point
4758  ) const;
4759 
4760  /*
4761  Returns:
4762  If the component is a vertex and mesh topology exists or
4763  the component is a mesh topology vertex, then this returns
4764  the mesh topology vertex index.
4765  Otherwise ON_UNSET_UINT_INDEX is returned.
4766  */
4767  unsigned int GetMeshTopologyVertex(
4768  const struct ON_MeshTopologyVertex*& topv
4769  ) const;
4770 
4771  /*
4772  Returns:
4773  If the component is a vertex and mesh topology exists or
4774  the component is a mesh topology vertex, then this returns
4775  the mesh topology vertex index.
4776  Otherwise ON_UNSET_UINT_INDEX is returned.
4777  */
4778  unsigned int GetMeshTopologyVertexAndPoint(
4779  const struct ON_MeshTopologyVertex*& topv,
4780  class ON_3dPoint& point
4781  ) const;
4782 
4783  /*
4784  Returns:
4785  If the component is a mesh topology edge, this returns
4786  the mesh topology edge index.
4787  Otherwise ON_UNSET_UINT_INDEX is returned.
4788  */
4789  unsigned int MeshTopologyEdgeIndex() const;
4790 
4791  /*
4792  Returns:
4793  If the component is an edge, this returns the edge.
4794  Otherwise null is returned.
4795  */
4796  const struct ON_MeshTopologyEdge* MeshTopologyEdge() const;
4797 
4798  unsigned int GetMeshTopologyEdge(
4799  const struct ON_MeshTopologyEdge*& tope
4800  ) const;
4801 
4802  unsigned int GetMeshTopologyEdgeLine(
4803  class ON_Line& line
4804  ) const;
4805 
4806  /*
4807  Parameters:
4808  line - [out]
4809  If the component is an edge, the 3d line is returned here.
4810  Returns:
4811  If the component is an edge, this returns the edge.
4812  Otherwise null is returned.
4813  */
4814  unsigned int GetMeshTopologyEdgeAndLine(
4815  const struct ON_MeshTopologyEdge*& tope,
4816  ON_Line& line
4817  ) const;
4818 
4819  /*
4820  Returns:
4821  - If the component references to an ON_MeshNgon in the mesh, then a pointer
4822  to this ngon is returned.
4823  - If the component references an ON_MeshFace triangle or quad, then
4824  then a single face ON_MeshNgon is created in the memory in
4825  ngon_buffer.
4826  - Otherwise, null is returned.
4827  */
4828  const class ON_MeshNgon* MeshNgon(
4829  class ON_MeshNgonBuffer& ngon_buffer
4830  ) const;
4831 
4832  /*
4833  Returns:
4834  If the component is a face or an ngon containing a single face,
4835  this returns the face index.
4836  Otherwise ON_UNSET_UINT_INDEX is returned.
4837  Remarks:
4838  The best way to write code that works with triangle, quad
4839  and ngons is to use the ON_MeshComponent::MeshNgon(ngon_buffer).
4840  */
4841  unsigned int MeshFaceIndex() const;
4842 
4843  /*
4844  Returns:
4845  If the component is a face or an ngon made of a single face,
4846  this returns the face.
4847  Otherwise null is returned.
4848  Remarks:
4849  The best way to write code that works with triangle, quad
4850  and ngons is to use the ON_MeshComponent::MeshNgon(ngon_buffer).
4851  */
4852  const class ON_MeshFace* MeshFace() const;
4853 
4854  /*
4855  Returns:
4856  If the component is a face or an ngon made of a single face,
4857  this returns the face.
4858  Otherwise null is returned.
4859  Remarks:
4860  The best way to write code that works with triangle, quad
4861  and ngons is to use the ON_MeshComponent::MeshNgon(ngon_buffer).
4862  */
4863  unsigned int GetMeshFace(
4864  const class ON_MeshFace*& mesh_face
4865  ) const;
4866 
4867 
4868  /*
4869  Returns:
4870  If the component is an ngon or a face in an ngon,
4871  this returns the ngon index.
4872  Otherwise ON_UNSET_UINT_INDEX is returned.
4873  Remarks:
4874  The best way to write code that works with triangle, quad
4875  and ngons is to use the ON_MeshComponent::MeshNgon(ngon_buffer).
4876  */
4877  unsigned int MeshNgonIndex() const;
4878 
4879 
4880  /*
4881  Returns:
4882  If the component is an ngon or a face in an ngon, this returns the ngon.
4883  Otherwise null is returned.
4884  Remarks:
4885  The best way to write code that works with triangle, quad
4886  and ngons is to use the ON_MeshComponent::MeshNgon(ngon_buffer).
4887  */
4888  const class ON_MeshNgon* MeshNgon() const;
4889 
4890 
4891  // overrides of virtual ON_Object functions
4892  bool IsValid( class ON_TextLog* text_log = nullptr ) const override;
4893  void Dump( ON_TextLog& ) const override;
4894  unsigned int SizeOf() const override;
4895  ON::object_type ObjectType() const override;
4896 
4897  // overrides of virtual ON_Geometry functions
4898  int Dimension() const override;
4899 
4900  // virtual ON_Geometry GetBBox override
4901  bool GetBBox( double* boxmin, double* boxmax, bool bGrowBox = false ) const override;
4902 
4903  bool Transform(
4904  const ON_Xform& xform
4905  ) override;
4906 };
4907 
4908 
4909 /*
4910 Description:
4911  Calculate a mesh representation of the NURBS surface's control polygon.
4912 Parameters:
4913  nurbs_surface - [in]
4914  bCleanMesh - [in] If true, then degenerate quads are cleaned
4915  up to be triangles. Surfaces with singular
4916  sides are a common source of degenerate qauds.
4917  input_mesh - [in] If nullptr, then the returned mesh is created
4918  by a class to new ON_Mesh(). If not null, then this
4919  mesh will be used to store the conrol polygon.
4920 Returns:
4921  If successful, a pointer to a mesh.
4922 */
4923 ON_DECL
4924 ON_Mesh* ON_ControlPolygonMesh(
4925  const ON_NurbsSurface& nurbs_surface,
4926  bool bCleanMesh,
4927  ON_Mesh* input_mesh = nullptr
4928  );
4929 
4930 
4931 /*
4932 Description:
4933  Finds the unit normal to the triangle
4934 Parameters:
4935  A - [in] triangle corner
4936  B - [in] triangle corner
4937  C - [in] triangle corner
4938 Returns:
4939  Unit normal
4940 */
4941 ON_DECL
4942 ON_3dVector ON_TriangleNormal(
4943  const ON_3dPoint& A,
4944  const ON_3dPoint& B,
4945  const ON_3dPoint& C
4946  );
4947 
4948 
4949 /*
4950 Description:
4951  Finds the unit normal to the triangle
4952 Parameters:
4953  A - [in] triangle corner
4954  B - [in] triangle corner
4955  C - [in] triangle corner
4956  a - [out] must not be null
4957  b - [out] must not be null
4958  c - [out] must not be null
4959  d - [out] must not be null
4960  The equation of the plane is a*x + b*y + c*z + d = 0
4961  ev_tol - [out]
4962  If ev_tol is not null, then it is the maximum absolute
4963  value of the plane equation evaluated at A,B,C. Mathematically,
4964  ev_tol is zero. Since these computations are performed with
4965  finite precision doubles, ev_tol is generally not zero.
4966 Returns:
4967  Unit normal
4968 */
4969 ON_DECL
4970 bool ON_GetTrianglePlaneEquation(
4971  const ON_3dPoint& A,
4972  const ON_3dPoint& B,
4973  const ON_3dPoint& C,
4974  double* a,
4975  double* b,
4976  double* c,
4977  double* d,
4978  double* evaluation_tol
4979  );
4980 
4981 
4982 #endif
Definition: opennurbs_point.h:2231
Definition: opennurbs_mesh.h:1866
Definition: opennurbs_point.h:2374
Definition: opennurbs_fpoint.h:832
ON_UUID is a 16 byte universally unique identifier.
Definition: opennurbs_uuid.h:32
Definition: opennurbs_point.h:1933
Definition: opennurbs_bounding_box.h:606
void AppendToString(class ON_String &s) const
Definition: opennurbs_mesh.h:2172
Definition: opennurbs_mesh.h:4494
Definition: opennurbs_mesh.h:720
Definition: opennurbs_nurbssurface.h:62
Definition: opennurbs_mesh.h:2123
Definition: opennurbs_mesh.h:4351
Definition: opennurbs_mesh.h:1847
static const ON_UUID PangolinMesherId
{EB6F6F3F-F975-4546-9D1C-64E9423BEB7F}
Definition: opennurbs_mesh.h:34
Definition: opennurbs_sha1.h:19
Definition: opennurbs_point.h:2356
Definition: opennurbs_mesh.h:4193
TYPE
Definition: opennurbs_texture_mapping.h:75
ON_wString ToWideString() const
MESH_STYLE
Definition: opennurbs_mesh.h:36
Definition: opennurbs_fpoint.h:211
Definition: opennurbs_string.h:2020
static const ON_BoundingBox UnsetBoundingBox
Definition: opennurbs_bounding_box.h:29
static unsigned int IsValid(const ON_MeshNgon *ngon, unsigned int ngon_index, ON_TextLog *text_log, unsigned int mesh_vertex_count, unsigned int mesh_face_count, const ON_MeshFace *mesh_F)
Test ngon to see if the vertex and face references are valid and pass partial boundary validity check...
Base class for all geometry classes that must provide runtime class id. Provides interface for common...
Definition: opennurbs_geometry.h:37
static class ON_MeshNgon ** NgonListFromMeshFace(class ON_MeshNgonBuffer &ngon_buffer, unsigned int mesh_face_index, const unsigned int *fvi)
Create an array of a single ngon pointer that contains a triangle (3-gon) or quad (4-gon) from a mesh...
Definition: opennurbs_fsp.h:19
Definition: opennurbs_mesh.h:1245
Definition: opennurbs_mesh.h:706
Definition: opennurbs_point.h:2018
static const ON_UUID RhinoLegacyMesherId
surface meshing perameters
Definition: opennurbs_mesh.h:31
Definition: opennurbs_mesh.h:1124
MESH_PARAMETER_ID
Definition: opennurbs_mesh.h:58
Definition: opennurbs_bounding_box.h:25
Definition: opennurbs_mesh.h:1692
Definition: opennurbs_string.h:852
Definition: opennurbs_mesh.h:24
Definition: opennurbs_point.h:1996
Definition: opennurbs_mesh.h:1213
Definition: opennurbs_xform.h:28
ON_SHA1 is a small class for calculating the SHA-1 hash of a sequence of bytes. It may be use increme...
Definition: opennurbs_sha1.h:242
void Dump(class ON_TextLog &text_log) const
Definition: opennurbs_mesh.h:684
Definition: opennurbs_mesh.h:2188
Definition: opennurbs_texture_mapping.h:37
Definition: opennurbs_line.h:20
Definition: opennurbs_mesh.h:645
static unsigned int NgonListFromMeshFaceOrNgonComponent(class ON_MeshNgonBuffer &ngon_buffer, ON_COMPONENT_INDEX ci, const class ON_Mesh *mesh, const class ON_MeshNgon *const *&ngon_list)
If a component index identifies a face or ngon, Get an array Create an array of a single ngon pointer...
ON_String ToString() const
Definition: opennurbs_mesh.h:790
Definition: opennurbs_mesh.h:938
Pure virtual base class for all classes that must provide runtime class id or support object level 3D...
Definition: opennurbs_object.h:460
Definition: opennurbs_mesh.h:1627
static class ON_MeshNgon * NgonFromMeshFace(class ON_MeshNgonBuffer &ngon_buffer, unsigned int mesh_face_index, const unsigned int *fvi)
Create an ngon pointer that contains a triangle (3-gon) or quad (4-gon) from a mesh face...
Definition: opennurbs_textlog.h:20
Definition: opennurbs_archive.h:1783
Definition: opennurbs_objref.h:163
Definition: opennurbs_point.h:460
Definition: opennurbs_mesh.h:1017
Definition: opennurbs_surface.h:57
Typically the vector portion is a unit vector and m_d = -(x*P.x + y*P.y + z*P.z) for a point P on the...
Definition: opennurbs_point.h:1433
static const ON_SHA1_Hash ZeroDigest
Definition: opennurbs_sha1.h:22
Definition: opennurbs_point.h:1152
Definition: opennurbs_point.h:46
Definition: opennurbs_mesh.h:2099
Definition: opennurbs_point.h:1973