opennurbs_subd_data.h
1 /* $NoKeywords: $ */
2 /*
3 //
4 // Copyright (c) 1993-2014 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_INC_IN_PROGRESS)
18 ///////////////////////////////////////////////////////////////////
19 //
20 // Including opennurbs.h must NEVER include this file.
21 //
22 ///////////////////////////////////////////////////////////////////
23 #error Please read the comment above this line.
24 #endif
25 
26 #if defined(ON_COMPILING_OPENNURBS)
27 #if !defined(OPENNURBS_SUBD_UNSTABLE_CORE_AVAIALABLE)
28 #define OPENNURBS_SUBD_UNSTABLE_CORE_AVAIALABLE
29 #endif
30 #endif
31 
32 
33 #if !defined(OPENNURBS_SUBD_UNSTABLE_CORE_AVAIALABLE)
34 ///////////////////////////////////////////////////////////////////
35 //
36 // WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
37 //
38 // The definitions in opennurbs_subd_data.h change randomly and unpredictably.
39 // Never include this file in any code you write, even as a hack.
40 // If you ignore this warning, your code will crash randomly and unpredictably
41 //
42 ///////////////////////////////////////////////////////////////////
43 #error Please read the comment above this line.
44 #endif
45 
46 #if !defined(OPENNURBS_SUBD_DATA_INC_)
47 #define OPENNURBS_SUBD_DATA_INC_
48 
49 #if defined(OPENNURBS_SUBD_WIP)
50 
51 
52 //////////////////////////////////////////////////////////////////////////
53 //
54 // ON_SubDFaceNeighborhood
55 //
56 class ON_CLASS ON_SubDFaceNeighborhood
57 {
58 public:
59  ON_SubDFaceNeighborhood() = default;
60  ~ON_SubDFaceNeighborhood();
61 
62  // initial face
63  const ON_SubDFace* m_face0 = nullptr;
64 
65  // subdivision algorithm
66  ON_SubD::SubDType m_subd_type = ON_SubD::SubDType::Unset;
67 
68  // When the subd_type is ON_SubD::SubDType::QuadCatmullClark,
69  // the center vertex will be a smooth vertex with valence = m_face0->m_edge_count.
70  // The edges and faces are sorted radially and all faces are quads.
71  //
72  // When the subd_type is ON_SubD::SubDType::TriLoopWarren and m_face0 is not a triangle,
73  // m_center_vertex is a smooth vertex with valence = m_face0->m_edge_count.
74  // The edges and faces are sorted radially and all faces are tris.
75  //
76  // In all other cases, m_center_vertex is null.
77  const ON_SubDVertex* m_center_vertex1 = nullptr;
78 
79  // m_face1[] is a list of the subdivision faces that subdivide the
80  // original face. When the subd_type is ON_SubD::SubDType::TriLoopWarren
81  // and the initial face is a triangle, the first face is the interior
82  // subdivision triangle. In all othr cases, m_face1 is identical
83  // to m_center_vertex1->m_faces[]. The m_next_face pointers are set so
84  // that m_face1[i]->m_next_face = m_face1[i+1]. Note that
85  // m_face1[m_face1_count-1]->m_next_face may not be null.
86  unsigned int m_face1_count = 0;
87  const class ON_SubDFace** m_face1 = nullptr;
88 
89  /*
90  Description:
91  Apply a single iteration of the subdivision algorithm to face
92  and save the results in this ON_SubDFaceNeighborhood. If a vertex
93  of the initial face is extraordinary, the limit point and normal
94  are calculated from face and saved on the subdivision.
95 
96  The resulting section of a subdivision surface is suitable for
97  limit surface and limit mesh evaluation of the original face.
98  The ON_SubDFaceNeighborhood is designed to be used to calculate
99  the limit surface and limit mesh for faces that have an extraordinary
100  number of edges.
101  */
102  bool Subdivide(
103  ON_SubD::SubDType subd_type,
104  const ON_SubDFace* face
105  );
106 
107 private:
108  bool TriSubdivideHelper(
109  const ON_SubDFace* face
110  );
111 
112  bool QuadSubdivideHelper(
113  const ON_SubDFace* face
114  );
115 
116  bool ReserveCapacity(
117  ON_SubD::SubDType subd_type,
118  const ON_SubDFace* face
119  );
120 
121  ON_SubD_FixedSizeHeap m_fsh;
122 };
123 
124 //////////////////////////////////////////////////////////////////////////
125 //
126 // ON_SubDQuadNeighborhood
127 //
128 
129 class ON_CLASS ON_SubDQuadNeighborhood
130 {
131 public:
132  ON_SubDQuadNeighborhood() = default;
133  ~ON_SubDQuadNeighborhood();
134 private:
135  void Internal_Destroy(bool bReinitialize);
136 
137 private:
138  ON_SubDQuadNeighborhood(const ON_SubDQuadNeighborhood&) = delete;
139  ON_SubDQuadNeighborhood& operator=(const ON_SubDQuadNeighborhood&) = delete;
140 
141 public:
142  // true if the limit surface of the center quad is a smooth bi-cubic surface with CVs
143  // at the m_vertex_grid[][] locations.
144  bool m_bIsCubicPatch = false;
145  unsigned char m_initial_subdivision_level = 0; // parent SubD subdivsion level at source
146  unsigned char m_current_subdivision_level = 0; // current subdivision level of contents
147 
148  // m_face_grid[1][1] is extraordinary and interpolation through the limit point
149  // will eventually be reqired to get an approximate cubic patch or an exact
150  // quad mesh vertex.
151  unsigned char m_extraordinary_corner_vertex_count = 0;
152  // m_bExtraordinaryCornerVertex[] = true if the corresponding corner vertex of
153  // the center quad is extraordinary.
154  bool m_bExtraordinaryCornerVertex[4];
155 
156  // m_bExactCubicPatchCorner[] = true if the sub 4x4 grid of subdivision points
157  // for the corresponding quadrant can be used to create an exact quadrant cubic patch.
158  unsigned char m_exact_quadrant_patch_count = 0;
159  bool m_bExactQuadrantPatch[4];
160 
161  // m_bBoundaryCrease[] = true if the corresponding m_center_edges[] is a crease
162  // and both end vertices are not darts.
163  unsigned char m_boundary_crease_count = 0;
164  bool m_bBoundaryCrease[4];
165 
166 private:
167  unsigned short m_reserved2 = 0;
168 
169 public:
170  const ON_SubDVertex* m_vertex_grid[4][4]; // vertex net m_quad_face corners = ([1][1], [2][1], [2][2], [1][2])
171 
172  const ON_SubDEdge* m_edge_grid[4][2];
173 
174  // m_face[][] is a 3x3 grid of faces.
175  // Center face
176  // m_face[1][1] is the "central" quad face.
177  // Side faces
178  // Side faces are null if the edge is a crease or has 1 == m_face_count.
179  // m_face[1][0] = the neighbor across m_center_edges[0]
180  // m_face[2][1] = the neighbor across m_center_edges[1]
181  // m_face[1][2] = the neighbor across m_center_edges[2]
182  // m_face[0][1] = the neighbor across m_center_edges[3]
183  const ON_SubDFace* m_face_grid[3][3];
184 
185  // edges of center face;
186  // m_center_edge[0] connects m_vertex_grid[1][1] and m_vertex_grid[2][1]
187  // m_center_edge[1] connects m_vertex_grid[2][1] and m_vertex_grid[2][2]
188  // m_center_edge[2] connects m_vertex_grid[2][2] and m_vertex_grid[1][2]
189  // m_center_edge[3] connects m_vertex_grid[1][2] and m_vertex_grid[1][1]
190  const ON_SubDEdge* m_center_edges[4];
191 
192  // If not null, the storage for the referenced subd information is from m_fsh.
193  class ON_SubD_FixedSizeHeap* m_fsh = nullptr;
194 
195  // level 1 subdivision control points
196  double m_srf_cv1[5][5][3];
197 
198  /*
199  Returns:
200  The center quad face m_face[1][1].
201  */
202  const ON_SubDFace* CenterQuad() const;
203 
204  const ON_SubDVertex* CenterVertex(
205  int vi
206  ) const;
207 
208  /*
209  Parameters:
210  fei - [in]
211  center quad face edge index (0 to 3)
212  Returns:
213  A pointer to the neighbor face across m_face[1][1]->Edge(fei)
214  This face will be null if the edge is a crease or has 2 != m_face_count
215  m_face[0][1] = the neighbor across m_face[1][1]->Edge(0) or null if the Edge(0) is a crease.
216  m_face[1][2] = the neighbor across m_face[1][1]->Edge(1) or null if the Edge(1) is a crease
217  m_face[2][1] = the neighbor across m_face[1][1]->Edge(2) or null if the Edge(2) is a crease
218  m_face[1][0] = the neighbor across m_face[1][1]->Edge(3) or null if the Edge(3) is a crease
219  */
220  const ON_SubDFace* SideFace(
221  unsigned int fei
222  ) const;
223 
224  /*
225  Parameters:
226  fei - [in]
227  center quad face vertex index (0 to 3)
228  Returns:
229  A pointer to the neighbor face opposite m_face[1][1]->Vertex(fvi).
230  This face will be null if the vertex valence is not 4 or any of its edges are creases.
231  m_face[0][0] = the neighbor diagonal from m_face[1][1]->Vertex(0)
232  m_face[0][2] = the neighbor diagonal from m_face[1][1]->Vertex(1)
233  m_face[2][2] = the neighbor diagonal from m_face[1][1]->Vertex(2)
234  m_face[2][0] = the neighbor diagonal from m_face[1][1]->Vertex(3)
235  */
236  const ON_SubDFace* CornerFace(
237  unsigned int fvi
238  ) const;
239 
240  bool Set(
241  const ON_SubDFace* center_quad_face
242  );
243 
244  /*
245  Description:
246  Clear current settings so the ON_SubDQuadNeighborhood can be reused.
247  Parameters:
248  subd_quad_nbd - [in/out]
249  ON_SubDQuadNeighborhood to clear.
250  bRetainFixedSizeHeap - [in]
251  The m_fsh heap is always reset. When bRetainFixedSizeHeap is true,
252  m_fsh is not set to nullptr.
253  */
254  static void Clear(
255  ON_SubDQuadNeighborhood* subd_quad_nbd,
256  bool bRetainFixedSizeHeap
257  );
258 
259  bool IsValid() const;
260 
261  bool IsSet() const
262  {
263  return (nullptr != m_face_grid[1][1]);
264  }
265 
266  /*
267  Description:
268  Get the limit surface for the entrie quad
269  */
270  bool GetLimitSurfaceCV(
271  //double srf_cv[4][4][3]
272  double* srf_cv,
273  unsigned int srf_cv_grid_size // 4 or 5
274  ) const;
275 
276  /*
277  Description:
278  Get the limit sub surface exact patch for the specifed corner.
279  Returns:
280  true when srf_cv are set to a the CVs for a bicubic uniform cubic NURBS bispan patch
281  */
282  bool GetLimitSubSurfaceSinglePatchCV(
283  unsigned int fvi,
284  double srf_cv[4][4][3]
285  );
286 
287  /*
288  Parameters:
289  unset_cv - [in]
290  If a patch cv srf_cv[j][j] does not exist or cannot be set, then all three
291  coordinates of srf_cv[j][j] are set to unset_cv. Use a value like
292  ON_UNSET_VALUE or ON_DBL_QNAN.
293  bEnableApproximatePatch - [in]
294  If true, an approximate patches may be generated.
295  This parameter should be true only when all permitted subdivisions have
296  been performed and a mininimum of 2 subdivisions have been performed.
297  This insures all faces are quads and each quad has at most one extraordinary
298  vertex and the approximate patches will have C2 continuity with any
299  neighboring exact patches.
300  srf_cv[5][5]
301  CVs for a uniform cubic NURBS patch.
302  patch_type - [out]
303  patch_type[0]
304  the type of cubic bispan for the 4x4 grid (srf_cv[0][0] ... srf_cv[3][3])
305  patch_type[1]
306  the type of cubic bispan for the 4x4 grid (srf_cv[1][0] ... srf_cv[4][3])
307  patch_type[2]
308  the type of cubic bispan for the 4x4 grid (srf_cv[1][1] ... srf_cv[4][4])
309  patch_type[3]
310  the type of cubic bispan for the 4x4 grid (srf_cv[0][1] ... srf_cv[3][4])
311  Returns:
312  0 - 4:
313  Number of bispans set in srf_cv[5][5]
314  */
315  unsigned int GetLimitSubSurfaceMultiPatchCV(
316  double unset_cv,
317  bool bEnableApproximatePatch,
318  double srf_cv[5][5][3],
319  ON_SubDLimitPatchFragment::PatchType patch_type[4]
320  );
321 
322 private:
323  unsigned int SetLimitSubSurfaceExactCVs(
324  unsigned int quadrant_index // 0,1,2,3 sets quadrant, 4 sets all non extraordinary patches
325  );
326 
327 private:
328  /*
329  Parameters:
330  i - [in] (0 <= i < 5)
331  j - [in] (0 <= j < 5)
332  srf_cv[i][j]
333  unset_cv - [in]
334  unset cv coordinate value
335  (uses when false is returned)
336  approximate_cv - [out]
337  location for a cubic NURBS CV that will yield a smooth result but
338  approximate the true subdivision surface.
339  */
340  bool GetApproximateCV(
341  int i,
342  int j,
343  double unset_cv,
344  double approximate_cv[3]
345  ) const;
346 
347 private:
348  // After m_face_grid, m_vertex_grid, m_edge_grid and m_bBoundaryCrease[] are set,
349  // this helper function sets the remaining information.
350  void SetPatchStatus(
351  const unsigned int fvi0
352  );
353 
354  // SetPatchStatus() uses this helper to set m_bIsCubicPatch
355  bool VertexGridIsExactCubicPatch(
356  const ON_2dex min_face_grid_dex,
357  const ON_2dex max_face_grid_dex,
358  unsigned int boundary_corner_index
359  ) const;
360 
361 public:
362 
363  /*
364  Description:
365  Apply a single iteration of the built-in quad subdivision algorithm to
366  this.
367  */
368  bool Subdivide(
369  const unsigned int q0fvi,
370  ON_SubD_FixedSizeHeap& fsh,
371  class ON_SubDQuadNeighborhood* q1ft
372  ) const;
373 
374  static ON_2dex GridDex(
375  unsigned int grid_size,
376  unsigned int corner_index,
377  unsigned int i,
378  unsigned int j
379  );
380 
381  static ON_2dex DeltaDex(
382  unsigned int corner_index,
383  int delta_i,
384  int delta_j
385  );
386 
387  static bool GetSubdivisionPoint(
388  const ON_SubDVertex* vertex,
389  double P1[3]
390  );
391 
392  static bool GetLimitPoint(
393  const ON_SubDVertex* vertex,
394  double limitP[3],
395  double limitN[3]
396  );
397 
398  static bool GetSubdivisionPoint(
399  const ON_SubDEdge* edge,
400  double P1[3]
401  );
402 
403  static bool GetSubdivisionPoint(
404  const ON_SubDFace* face,
405  double P1[3]
406  );
407 };
408 
409 #if defined(ON_COMPILING_OPENNURBS)
410 
411 ////////////////////////////////////////////////////////////////
412 //
413 // Implementation of subdivision surface
414 //
415 // This implementation will change randomly and unpredictably.
416 //
417 ////////////////////////////////////////////////////////////////
418 
419 
420 //////////////////////////////////////////////////////////////////////////
421 //
422 // ON_SubDIncrementErrorCount()
423 //
424 // Appears in places where the code traps error conditions.
425 // Putting a breakpoint on the line indicated below is an easy way
426 // to have the debugger break on all error conditions and inspect
427 // the first place something goes wrong in a complex calculation.
428 //
429 void ON_SubDIncrementErrorCount(); // defined in opennurbs_subd.cpp
430 #define ON_SUBD_RETURN_ERROR(rc) (ON_SubDIncrementErrorCount(),rc)
431 #define ON_SUBD_ERROR(msg) (ON_SubDIncrementErrorCount(),ON_ERROR(msg))
432 
433 //////////////////////////////////////////////////////////////////////////
434 //
435 // ON_SubDEdgePtr and ON_SubDFacePtr are unsigned ints that store a
436 // pointer to an ON_SubDEdge or ON_SubDFace along with a bit that
437 // is 0 or 1 which is used to indicate the end of the edge that is
438 // the "start" or if an edge is "reversed" along the side of a face.
439 //
440 // This code assumes that ON_SubDVertex, ON_SubDEdge, and ON_SubDFace
441 // classes begin on an 8 bytes boundary because they contain doubles.
442 // If this assumption is false, you will get lots of crashes.
443 //
444 #define ON_SUBD_ELEMENT_MARK_MASK (0x1U)
445 #define ON_SUBD_ELEMENT_TYPE_MASK (0x6U)
446 #define ON_SUBD_ELEMENT_FLAGS_MASK (0x7U)
447 #if (8 == ON_SIZEOF_POINTER)
448 #define ON_SUBD_ELEMENT_POINTER_MASK (0xFFFFFFFFFFFFFFF8ULL)
449 #else
450 #define ON_SUBD_ELEMENT_POINTER_MASK (0xFFFFFFF8U)
451 #endif
452 
453 #define ON_SUBD_ELEMENT_TYPE_VERTEX (0x2U)
454 #define ON_SUBD_ELEMENT_TYPE_EDGE (0x4U)
455 #define ON_SUBD_ELEMENT_TYPE_FACE (0x6U)
456 
457 #define ON_SUBD_ELEMENT_POINTER(p) ((void*)((p) & ON_SUBD_ELEMENT_POINTER_MASK))
458 #define ON_SUBD_ELEMENT_MARK(p) ((p) & ON_SUBD_ELEMENT_MARK_MASK)
459 #define ON_SUBD_ELEMENT_TYPE(p) ((p) & ON_SUBD_ELEMENT_TYPE_MASK)
460 #define ON_SUBD_ELEMENT_FLAGS(p) ((p) & ON_SUBD_ELEMENT_FLAGS_MASK)
461 
462 #define ON_SUBD_VERTEX_POINTER(p) ((class ON_SubDVertex*)ON_SUBD_ELEMENT_POINTER(p))
463 #define ON_SUBD_VERTEX_MARK(p) ON_SUBD_ELEMENT_MARK(p)
464 
465 #define ON_SUBD_EDGE_POINTER(p) ((class ON_SubDEdge*)ON_SUBD_ELEMENT_POINTER(p))
466 #define ON_SUBD_FACE_POINTER(p) ((class ON_SubDFace*)ON_SUBD_ELEMENT_POINTER(p))
467 
468 #define ON_SUBD_EDGE_DIRECTION(p) ON_SUBD_ELEMENT_MARK(p)
469 #define ON_SUBD_FACE_DIRECTION(p) ON_SUBD_ELEMENT_MARK(p)
470 
471 
472 //////////////////////////////////////////////////////////////////////////
473 //
474 // m_saved_points_flags
475 //
476 #define ON_SUBD_CACHE_TYPE_MASK (0x1FU)
477 
478 #define ON_SUBD_CACHE_POINT_FLAG_MASK (0x20U)
479 #define ON_SUBD_CACHE_DISPLACEMENT_FLAG_MASK (0x40U)
480 #define ON_SUBD_CACHE_LIMIT_FLAG_MASK (0x80U)
481 #define ON_SUBD_CACHE_FLAGS_MASK (ON_SUBD_CACHE_POINT_FLAG_MASK|ON_SUBD_CACHE_DISPLACEMENT_FLAG_MASK|ON_SUBD_CACHE_LIMIT_FLAG_MASK)
482 
483 #define ON_SUBD_CACHE_TYPE(cache_subd_flags) (ON_SUBD_CACHE_TYPE_MASK&(cache_subd_flags))
484 #define ON_SUBD_CACHE_FLAGS(cache_subd_flags) (ON_SUBD_CACHE_FLAGS_MASK&(cache_subd_flags))
485 #define ON_SUBD_CACHE_POINT_FLAG(cache_subd_flags) (ON_SUBD_CACHE_POINT_FLAG_MASK&(cache_subd_flags))
486 #define ON_SUBD_CACHE_DISPLACEMENT_FLAG(cache_subd_flags) (ON_SUBD_CACHE_DISPLACEMENT_FLAG_MASK&(cache_subd_flags))
487 #define ON_SUBD_CACHE_LIMIT_FLAG(cache_subd_flags) (ON_SUBD_CACHE_LIMIT_FLAG_MASK&(cache_subd_flags))
488 
489 #define ON_SUBD_CACHE_CLEAR_POINT_FLAG(cache_subd_flags) (cache_subd_flags &= (ON_SUBD_CACHE_TYPE_MASK|ON_SUBD_CACHE_DISPLACEMENT_FLAG_MASK|ON_SUBD_CACHE_LIMIT_FLAG_MASK))
490 #define ON_SUBD_CACHE_CLEAR_DISPLACEMENT_FLAG(cache_subd_flags) (cache_subd_flags &= (ON_SUBD_CACHE_TYPE_MASK|ON_SUBD_CACHE_POINT_FLAG_MASK|ON_SUBD_CACHE_LIMIT_FLAG_MASK))
491 #define ON_SUBD_CACHE_CLEAR_LIMIT_FLAG(cache_subd_flags) (cache_subd_flags &= (ON_SUBD_CACHE_TYPE_MASK|ON_SUBD_CACHE_POINT_FLAG_MASK|ON_SUBD_CACHE_DISPLACEMENT_FLAG_MASK))
492 
493 
494 //////////////////////////////////////////////////////////////////////////
495 //
496 // ON_SubDAggregates
497 //
498 class ON_SubDAggregates
499 {
500 public:
501  void UpdateBoundingBox(
502  const ON_SubDLevel* level
503  );
504 
505  void UpdateEdgeFlags(
506  const ON_SubDLevel* level
507  );
508 
509  void UpdateAggregateComponentStatus(
510  const ON_SubDLevel* level
511  );
512 
513  void MarkAllAsNotCurrent()
514  {
515  m_bDirtyEdgeFlags = true;
516  m_bDirtyBoundingBox = true;
517  m_aggregate_status.MarkAsNotCurrent();
518  }
519 
520  bool m_bDirtyEdgeFlags = false;
521  bool m_bDirtyBoundingBox = false;
523  unsigned int m_edge_flags;
525 };
526 
527 //////////////////////////////////////////////////////////////////////////
528 //
529 // ON_SubDLevel
530 //
531 
532 class ON_SubDLevel
533 {
534 public:
535  static const ON_SubDLevel Empty;
536 
537  bool IsEmpty() const;
538 
539  ON_SubDLevel()
540  {
541  m_vertex[0] = m_vertex[1] = nullptr;
542  m_edge[0] = m_edge[1] = nullptr;
543  m_face[0] = m_face[1] = nullptr;
544  }
545 
546 private:
547  ON_SubDLevel(const ON_SubDLevel&) = delete;
548  ON_SubDLevel& operator=(const ON_SubDLevel&) = delete;
549 
550 public:
551  unsigned int m_level_index = ON_UNSET_UINT_INDEX;
552 
553  ON_SubD::SubDType m_subdivision_type = ON_SubD::SubDType::Unset;
554 
555  unsigned char m_ordinary_vertex_valence = 0; // 0 = none, 4 = quads, 6 = triangles
556  unsigned char m_ordinary_face_edge_count = 0; // 0 = none, 4 = quads, 3 = triangles
557 
558 private:
559  unsigned char m_reserved1 = 0;
560 
561 public:
562  bool CopyHelper(
563  const ON_SubDLevel& src,
564  class ON_SubDArchiveIdMap& eptrlist,
565  class ON_SubDimple& subdimple,
566  bool bCopyComponentStatus
567  );
568 
569 public:
570  /*
571  Returns:
572  Number of changes to vertex tag, edge tag and edge sector coefficent values.
573  */
574  unsigned int UpdateEdgeTags(
575  bool bUnsetEdgeTagsOnly
576  );
577 
578  unsigned int UpdateVertexTags(
579  bool bVertexEdgeTagsOnly
580  );
581 
582  unsigned int UpdateAllTagsAndSectorCoefficients(
583  bool bUnsetValuesOnly
584  );
585 
586 private:
587  void DestroyOnError()
588  {
589  ON_SubDIncrementErrorCount();
590  m_vertex_count = 0;
591  m_edge_count = 0;
592  m_face_count = 0;
593  m_vertex_array_count = 0;
594  m_edge_array_count = 0;
595  m_face_array_count = 0; m_vertex[0] = m_vertex[1] = nullptr;
596  m_edge[0] = m_edge[1] = nullptr;
597  m_face[0] = m_face[1] = nullptr;
598  ResetVertexArray();
599  ResetEdgeArray();
600  ResetFaceArray();
601  }
602 
603 public:
604 
605  // m_vertex[2] = (head,tail) of linked list of vertices for this level
606  class ON_SubDVertex* m_vertex[2];
607 
608  // m_edge[2] = (head,tail) of linked list of edges for this level
609  class ON_SubDEdge* m_edge[2];
610 
611  // m_face[2] = (head,tail) of linked list of faces for this level
612  class ON_SubDFace* m_face[2];
613 
614  unsigned int m_vertex_count = 0;
615  unsigned int m_edge_count = 0;
616  unsigned int m_face_count = 0;
617  unsigned int m_vertex_array_count = 0;
618  unsigned int m_edge_array_count = 0;
619  unsigned int m_face_array_count = 0;
620 
621  std::shared_ptr<const ON_SubDVertex*> VertexArray() const;
622  std::shared_ptr<const ON_SubDEdge*> EdgeArray() const;
623  std::shared_ptr<const ON_SubDFace*> FaceArray() const;
624 
625  mutable ON_SubDLimitMesh m_limit_mesh;
626 
627  /*
628  Description:
629  Sets the mutable m_archive_id value for every vertex, edge and face
630  in this level.
631  Parameters:
632  archive_id_partition - [out]
633  archive_id_partition[0] = 1 = first vertex archive_id
634  archive_id_partition[1]-1 = last vertex archive_id
635  archive_id_partition[1] = first edge archive_id
636  archive_id_partition[2]-1 = last edge archive_id
637  archive_id_partition[2] = first face archive_id
638  archive_id_partition[3]-1 = last face archive_id
639  Returns:
640  The number of vertices, edges and faces on this level.
641  */
642  unsigned int SetArchiveId(
643  unsigned int archive_id_partition[4]
644  ) const;
645 
646  void ClearArchiveId() const;
647 
648  bool Read(
649  ON_BinaryArchive& archive,
650  class ON_SubDArchiveIdMap& element_list,
651  ON_SubD& subd
652  );
653 
654  bool Write(
655  ON_BinaryArchive& archive
656  ) const;
657 
658  /*
659  Description:
660  Apply a tranxfomration matrix to the entire level.
661  Parameters:
662  bGlobalTransformationIsIsometricOrUniformScale - [in]
663  true if the transformation is isomectirc (rotation, translation),
664  a dialoation (uniforma scale), or a compbination of those, and
665  it will be applied to every component in the subdivision
666  object.
667  false otherwise.
668  If you don't know, pass false.
669  xform - [in]
670  */
671  bool Transform(
672  bool bGlobalTransformationIsIsometricOrDilation,
673  const class ON_Xform& xform
674  );
675 
676  bool SetSubDType(
677  ON_SubD::SubDType subdivision_type
678  );
679 
680  void ResetVertexArray()
681  {
682  if (m_vertex_array_count)
683  {
684  m_vertex_array_count = 0;
685  m_vertex_array.reset();
686  }
687  }
688 
689  void ResetEdgeArray()
690  {
691  if (m_edge_array_count)
692  {
693  m_edge_array_count = 0;
694  m_edge_array.reset();
695  }
696  }
697 
698  void ResetFaceArray()
699  {
700  if (m_face_array_count)
701  {
702  m_face_array_count = 0;
703  m_face_array.reset();
704  }
705  }
706 
707  std::shared_ptr<const ON_SubDVertex*> m_vertex_array;
708  std::shared_ptr<const ON_SubDEdge*> m_edge_array;
709  std::shared_ptr<const ON_SubDFace*> m_face_array;
710 
711  bool RemoveVertex(class ON_SubDVertex* vertex)
712  {
713  m_aggregates.m_bDirtyBoundingBox = true;
714  if (nullptr == vertex || vertex->m_level != this->m_level_index )
715  return ON_SUBD_RETURN_ERROR(false);
716  if ( 0 == m_vertex_count)
717  return ON_SUBD_RETURN_ERROR(false);
718  ON_SubDVertex* prev_vertex = const_cast<ON_SubDVertex*>(vertex->m_prev_vertex);
719  ON_SubDVertex* next_vertex = const_cast<ON_SubDVertex*>(vertex->m_next_vertex);
720  vertex->m_prev_vertex = nullptr;
721  vertex->m_next_vertex = nullptr;
722  if (1 == m_vertex_count)
723  {
724  if (m_vertex[0] == vertex && m_vertex[1] == vertex && nullptr == prev_vertex && nullptr == next_vertex)
725  {
726  m_vertex[0] = nullptr;
727  m_vertex[1] = nullptr;
728  }
729  else
730  {
731  // error - same action taken
732  DestroyOnError();
733  return false;
734  }
735  }
736  else
737  {
738  if (m_vertex[0] == vertex)
739  {
740  if (m_vertex_count >= 2 && nullptr == prev_vertex && nullptr != next_vertex )
741  {
742  m_vertex[0] = next_vertex;
743  next_vertex->m_prev_vertex = nullptr;
744  }
745  else
746  {
747  DestroyOnError();
748  return false;
749  }
750  }
751  else if (m_vertex[1] == vertex)
752  {
753  if (m_vertex_count >= 2 && nullptr == next_vertex && nullptr != prev_vertex)
754  {
755  m_vertex[1] = prev_vertex;
756  prev_vertex->m_next_vertex = nullptr;
757  }
758  else
759  {
760  DestroyOnError();
761  return false;
762  }
763  }
764  else
765  {
766  if (m_vertex_count > 2 && nullptr != prev_vertex && nullptr != next_vertex)
767  {
768  prev_vertex->m_next_vertex = next_vertex;
769  next_vertex->m_prev_vertex = prev_vertex;
770  }
771  else
772  {
773  DestroyOnError();
774  return false;
775  }
776  }
777  }
778  m_vertex_count--;
779  ResetVertexArray();
780  return true;
781  }
782 
783 
784  bool RemoveEdge(class ON_SubDEdge* edge)
785  {
786  m_aggregates.m_bDirtyEdgeFlags = true;
787  if (nullptr == edge || edge->m_level != this->m_level_index )
788  return ON_SUBD_RETURN_ERROR(false);
789  if ( 0 == m_edge_count)
790  return ON_SUBD_RETURN_ERROR(false);
791  ON_SubDEdge* prev_edge = const_cast<ON_SubDEdge*>(edge->m_prev_edge);
792  ON_SubDEdge* next_edge = const_cast<ON_SubDEdge*>(edge->m_next_edge);
793  edge->m_prev_edge = nullptr;
794  edge->m_next_edge = nullptr;
795  if (1 == m_edge_count)
796  {
797  if (m_edge[0] == edge && m_edge[1] == edge && nullptr == prev_edge && nullptr == next_edge)
798  {
799  m_edge[0] = nullptr;
800  m_edge[1] = nullptr;
801  }
802  else
803  {
804  // error - same action taken
805  DestroyOnError();
806  return false;
807  }
808  }
809  else
810  {
811  if (m_edge[0] == edge)
812  {
813  if (m_edge_count >= 2 && nullptr == prev_edge && nullptr != next_edge )
814  {
815  m_edge[0] = next_edge;
816  next_edge->m_prev_edge = nullptr;
817  }
818  else
819  {
820  DestroyOnError();
821  return false;
822  }
823  }
824  else if (m_edge[1] == edge)
825  {
826  if (m_edge_count >= 2 && nullptr == next_edge && nullptr != prev_edge)
827  {
828  m_edge[1] = prev_edge;
829  prev_edge->m_next_edge = nullptr;
830  }
831  else
832  {
833  DestroyOnError();
834  return false;
835  }
836  }
837  else
838  {
839  if (m_edge_count > 2 && nullptr != prev_edge && nullptr != next_edge)
840  {
841  prev_edge->m_next_edge = next_edge;
842  next_edge->m_prev_edge = prev_edge;
843  }
844  else
845  {
846  DestroyOnError();
847  return false;
848  }
849  }
850  }
851  m_edge_count--;
852  ResetEdgeArray();
853  return true;
854  }
855 
856 
857  bool RemoveFace(class ON_SubDFace* face)
858  {
859  if (nullptr == face || face->m_level != this->m_level_index )
860  return ON_SUBD_RETURN_ERROR(false);
861  if ( 0 == m_face_count)
862  return ON_SUBD_RETURN_ERROR(false);
863  ON_SubDFace* prev_face = const_cast<ON_SubDFace*>(face->m_prev_face);
864  ON_SubDFace* next_face = const_cast<ON_SubDFace*>(face->m_next_face);
865  face->m_prev_face = nullptr;
866  face->m_next_face = nullptr;
867  if (1 == m_face_count)
868  {
869  if (m_face[0] == face && m_face[1] == face && nullptr == prev_face && nullptr == next_face)
870  {
871  m_face[0] = nullptr;
872  m_face[1] = nullptr;
873  }
874  else
875  {
876  // error - same action taken
877  DestroyOnError();
878  return false;
879  }
880  }
881  else
882  {
883  if (m_face[0] == face)
884  {
885  if (m_face_count >= 2 && nullptr == prev_face && nullptr != next_face )
886  {
887  m_face[0] = next_face;
888  next_face->m_prev_face = nullptr;
889  }
890  else
891  {
892  DestroyOnError();
893  return false;
894  }
895  }
896  else if (m_face[1] == face)
897  {
898  if (m_face_count >= 2 && nullptr == next_face && nullptr != prev_face)
899  {
900  m_face[1] = prev_face;
901  prev_face->m_next_face = nullptr;
902  }
903  else
904  {
905  DestroyOnError();
906  return false;
907  }
908  }
909  else
910  {
911  if (m_face_count > 2 && nullptr != prev_face && nullptr != next_face)
912  {
913  prev_face->m_next_face = next_face;
914  next_face->m_prev_face = prev_face;
915  }
916  else
917  {
918  DestroyOnError();
919  return false;
920  }
921  }
922  }
923  m_face_count--;
924  ResetFaceArray();
925  return true;
926  }
927 
928  const ON_SubDVertex* AddVertex(class ON_SubDVertex* vertex)
929  {
930  m_aggregates.m_bDirtyBoundingBox = true;
931  if (nullptr == vertex)
932  return nullptr;
933  if (nullptr == m_vertex[1])
934  {
935  m_vertex[0] = vertex;
936  vertex->m_prev_vertex = nullptr;
937  }
938  else
939  {
940  m_vertex[1]->m_next_vertex = vertex;
941  vertex->m_prev_vertex = m_vertex[1];
942  }
943  m_vertex[1] = vertex;
944  vertex->m_next_vertex = nullptr;
945  m_vertex_count++;
946  ResetVertexArray();
947  return vertex;
948  }
949 
950  const ON_SubDEdge* AddEdge(class ON_SubDEdge* edge)
951  {
952  m_aggregates.m_bDirtyEdgeFlags = true;
953  if (nullptr == edge)
954  return nullptr;
955  if (nullptr == m_edge[1])
956  {
957  m_edge[0] = edge;
958  edge->m_prev_edge = nullptr;
959  }
960  else
961  {
962  m_edge[1]->m_next_edge = edge;
963  edge->m_prev_edge = m_edge[1];
964  }
965  m_edge[1] = edge;
966  edge->m_next_edge = nullptr;
967  m_edge_count++;
968  ResetEdgeArray();
969  return edge;
970  }
971 
972  const ON_SubDFace* AddFace(class ON_SubDFace* face)
973  {
974  if (nullptr == face)
975  return nullptr;
976  if (nullptr == m_face[1])
977  {
978  m_face[0] = face;
979  face->m_prev_face = nullptr;
980  }
981  else
982  {
983  m_face[1]->m_next_face = face;
984  face->m_prev_face = m_face[1];
985  }
986  m_face[1] = face;
987  face->m_next_face = nullptr;
988  m_face_count++;
989  ResetFaceArray();
990  return face;
991  }
992 
993 private:
994  unsigned int m_reserved4 = 0;
995 public:
996 
997  unsigned int UpdateEdgeSectorCoefficients(
998  bool bUnsetEdgeSectorCoefficientsOnly
999  );
1000 
1001 
1002  void ClearSubdivisonAndLimitPoints() const;
1003 
1004  /*
1005  Description:
1006  If a state is set in the status parameter, it will be cleared
1007  from all components on the level.
1008  Returns:
1009  Number of components where a state setting chanaged.
1010  */
1011  unsigned int ClearStates(
1012  ON_ComponentStatus states_to_clear
1013  ) const;
1014 
1015  unsigned int GetComponentsWithSetStates(
1016  ON_ComponentStatus states_filter,
1017  bool bAllEqualStates,
1018  ON_SimpleArray< ON_SubDComponentPtr >& components_with_set_states
1019  ) const;
1020 
1021  unsigned int SetStates(
1022  ON_SubDComponentPtr component_ptr,
1023  ON_ComponentStatus states_to_set
1024  ) const;
1025 
1026  unsigned int ClearStates(
1027  ON_SubDComponentPtr component_ptr,
1028  ON_ComponentStatus states_to_clear
1029  ) const;
1030 
1031  unsigned int SetStatus(
1032  ON_SubDComponentPtr component_ptr,
1033  ON_ComponentStatus status_to_copy
1034  ) const;
1035 
1036  ON_AggregateComponentStatus AggregateComponentStatus() const;
1037 
1038  void MarkAggregateComponentStatusAsNotCurrent() const
1039  {
1040  m_aggregates.m_aggregate_status.MarkAsNotCurrent();
1041  }
1042 
1043  void ClearBoundingBox() const
1044  {
1045  m_aggregates.m_bDirtyBoundingBox = true;
1046  }
1047 
1048  ON_BoundingBox BoundingBox() const;
1049 
1050  void ClearEdgeFlags() const
1051  {
1052  m_aggregates.m_bDirtyEdgeFlags = true;
1053  }
1054 
1055  unsigned int EdgeFlags() const;
1056 
1057  ON_SubDLimitMesh UpdateLimitSurfaceMesh(
1058  const ON_SubD& subd,
1059  const class ON_SubDDisplayParameters& display_parameters
1060  ) const;
1061 
1062  unsigned int LimitSurfaceMeshFragmentCount() const;
1063 
1064 private:
1065  mutable ON_SubDAggregates m_aggregates;
1066 };
1067 
1068 //////////////////////////////////////////////////////////////////////////
1069 //
1070 // ON_SubDLevelIterator
1071 //
1072 class ON_SubDLevelIterator
1073 {
1074 public:
1075  class ON_SubDLevel* First()
1076  {
1077  for (m_level_index = 0; m_level_index < m_level_count; m_level_index++)
1078  {
1079  if (nullptr != m_levels[m_level_index])
1080  return m_levels[m_level_index];
1081  }
1082  return nullptr;
1083  }
1084 
1085  class ON_SubDLevel* Next()
1086  {
1087  for (m_level_index++; m_level_index < m_level_count; m_level_index++)
1088  {
1089  if (nullptr != m_levels[m_level_index])
1090  return m_levels[m_level_index];
1091  }
1092  return nullptr;
1093  }
1094 
1095  unsigned int LevelIndex()
1096  {
1097  return m_level_index;
1098  }
1099 
1100  unsigned int LevelCount()
1101  {
1102  return m_level_count;
1103  }
1104 
1105 private:
1106  friend class ON_SubDimple;
1107  ON_SubDLevelIterator() = default;
1108  ~ON_SubDLevelIterator() = default;
1109  ON_SubDLevelIterator(const ON_SubDLevelIterator&) = default;
1110  ON_SubDLevelIterator& operator=(const ON_SubDLevelIterator&) = default;
1111 
1112  class ON_SubDLevel** m_levels = nullptr;
1113  unsigned int m_level_count = 0;
1114  unsigned int m_level_index = 0;
1115 };
1116 
1117 //////////////////////////////////////////////////////////////////////////
1118 //
1119 // ON_SubDHeap
1120 //
1121 
1122 class ON_SubDHeap
1123 {
1124 public:
1125  ON_SubDHeap();
1126  ~ON_SubDHeap();
1127 
1128  class ON_SubDVertex* AllocateVertexAndSetId(unsigned int& max_vertex_id);
1129 
1130  void ReturnVertex(class ON_SubDVertex* v);
1131 
1132  class ON_SubDEdge* AllocateEdgeAndSetId(unsigned int& max_edge_id);
1133 
1134  void ReturnEdge(class ON_SubDEdge* e);
1135 
1136  class ON_SubDFace* AllocateFaceAndSetId(unsigned int& max_face_id);
1137 
1138  void ReturnFace(class ON_SubDFace* f);
1139 
1140  /*
1141  Description:
1142  Sets mutable m_archive_id values to 0.
1143  */
1144  void ClearArchiveId();
1145 
1146  const class ON_SubDVertex* VertexFromId(
1147  unsigned int vertex_id
1148  ) const;
1149 
1150  const class ON_SubDEdge* EdgeFromId(
1151  unsigned int edge_id
1152  ) const;
1153 
1154  const class ON_SubDFace* FaceFromId(
1155  unsigned int face_id
1156  ) const;
1157 
1158 private:
1159 
1160 
1161  /*
1162  Returns:
1163  Array of count ON__UINT_PTR
1164  */
1165  ON__UINT_PTR* AllocateArray(
1166  size_t* capacity
1167  );
1168  void ReturnArray(
1169  size_t capacity,
1170  ON__UINT_PTR* a
1171  );
1172  static ON__UINT_PTR ArrayCapacity(
1173  size_t capacity,
1174  ON__UINT_PTR* a
1175  );
1176  ON__UINT_PTR* ResizeArray(
1177  size_t current_count,
1178  size_t current_capacity,
1179  ON__UINT_PTR* current_a,
1180  size_t* new_capacity
1181  );
1182 
1183 public:
1184  bool GrowVertexEdgeArray(
1185  ON_SubDVertex* v,
1186  size_t capacity
1187  );
1188  bool GrowVertexFaceArray(
1189  ON_SubDVertex* v,
1190  size_t capacity
1191  );
1192  bool GrowEdgeFaceArray(
1193  ON_SubDEdge* e,
1194  size_t capacity
1195  );
1196  bool GrowFaceEdgeArray(
1197  ON_SubDFace* f,
1198  size_t capacity
1199  );
1200 
1201  bool GrowVertexEdgeArrayByOne(
1202  ON_SubDVertex* v
1203  );
1204  bool GrowVertexFaceArrayByOne(
1205  ON_SubDVertex* v
1206  );
1207  bool GrowEdgeFaceArrayByOne(
1208  ON_SubDEdge* e
1209  );
1210  bool GrowFaceEdgeArrayByOne(
1211  ON_SubDFace* f
1212  );
1213 
1214  bool ReturnVertexEdgeAndFaceArrays(
1215  ON_SubDVertex* v
1216  );
1217 
1218  bool ReturnEdgeExtraArray(
1219  ON_SubDEdge* e
1220  );
1221 
1222  bool ReturnFaceExtraArray(
1223  ON_SubDFace* f
1224  );
1225 
1226 
1227  /*
1228  Description:
1229  Discard all contents of this ON_SubDHeap.
1230  Remarks:
1231  More efficient than Destroy() if this ON_SubDHeap will be reused soon.
1232  */
1233  void Clear();
1234 
1235  /*
1236  Description:
1237  Delete all contents release all memory used by this ON_SubDHeap.
1238  */
1239  void Destroy();
1240 
1241  size_t SizeOf() const
1242  {
1243  size_t sz = sizeof(*this);
1244  sz += m_fsp5.SizeofElement()*m_fsp5.TotalElementCount();
1245  sz += m_fsp9.SizeofElement()*m_fsp9.TotalElementCount();
1246  sz += m_fsp17.SizeofElement()*m_fsp17.TotalElementCount();
1247  // todo - include m_ws;
1248  return sz;
1249  }
1250 
1251 private:
1252  class tagWSItem
1253  {
1254  public:
1255  class tagWSItem* m_prev;
1256  class tagWSItem* m_next;
1257  };
1258 
1259  class tagWSItem* m_ws = nullptr; // oversized arrays of ON__UINT_PTRs
1260 
1261  ON_FixedSizePool m_fspv; // element = ON_SubDVertex
1262  ON_FixedSizePool m_fspe; // element = ON_SubDEdge
1263  ON_FixedSizePool m_fspf; // element = ON_SubDFace
1264  ON_FixedSizePool m_fsp5; // element = capacity + array of 4 ON__UINT_PTRs
1265  ON_FixedSizePool m_fsp9; // element = capacity + array of 8 ON__UINT_PTRs
1266  ON_FixedSizePool m_fsp17; // element = capacity + array of 16 ON__UINT_PTRs
1267 
1268  ON_SubDVertex* m_unused_vertex = nullptr;
1269  ON_SubDEdge* m_unused_edge = nullptr;
1270  ON_SubDFace* m_unused_face = nullptr;
1271 
1272  ON__UINT_PTR* AllocateOversizedElementQWERTY(
1273  size_t* capacity
1274  );
1275  void ReturnOversizedElement(
1276  size_t capacity,
1277  ON__UINT_PTR* a
1278  );
1279  static size_t OversizedElementCapacityQWERTY(
1280  size_t count
1281  );
1282 
1283  static size_t m_offset_vertex_id;
1284  static size_t m_offset_edge_id;
1285  static size_t m_offset_face_id;
1286 };
1287 
1288 
1289 //////////////////////////////////////////////////////////////////////////
1290 //
1291 // ON_SubDimple
1292 //
1293 
1294 class ON_SubDimple
1295 {
1296 #if defined(ON_SUBD_CENSUS)
1297  ON_SubDImpleCensusCounter m_census_counter;
1298 #endif
1299 public:
1300  ON_SubDimple() = default;
1301  ~ON_SubDimple();
1302  ON_SubDimple(const ON_SubDimple&);
1303 
1304  bool IsValid(
1305  const ON_SubD& subd,
1306  bool bSilentError,
1307  ON_TextLog*
1308  ) const;
1309 
1310  //unsigned int MaximumVertexId() const
1311  //{
1312  // return m_max_vertex_id;
1313  //}
1314 
1315  //unsigned int MaximumEdgeId() const
1316  //{
1317  // return m_max_edge_id;
1318  //}
1319 
1320  //unsigned int MaximumFaceId() const
1321  //{
1322  // return m_max_face_id;
1323  //}
1324 
1325  bool Write(
1326  ON_BinaryArchive& archive
1327  ) const;
1328 
1329  bool Read(
1330  ON_BinaryArchive& archive,
1331  class ON_SubD& subd
1332  );
1333 
1334  bool Transform(
1335  const ON_Xform& xform
1336  );
1337 
1338  const class ON_SubDVertex* VertexFromId(
1339  unsigned int vertex_id
1340  ) const
1341  {
1342  return m_heap.VertexFromId(vertex_id);
1343  }
1344 
1345  const class ON_SubDEdge* EdgeFromId(
1346  unsigned int edge_id
1347  ) const
1348  {
1349  return m_heap.EdgeFromId(edge_id);
1350  }
1351 
1352  const class ON_SubDFace* FaceFromId(
1353  unsigned int face_id
1354  ) const
1355  {
1356  return m_heap.FaceFromId(face_id);
1357  }
1358 
1359  ON_SubDLevelIterator LevelIterator() const
1360  {
1361  ON_SubDLevelIterator lit;
1362  lit.m_levels = (ON_SubDLevel**)m_levels.Array();
1363  lit.m_level_count = m_levels.UnsignedCount();
1364  return lit;
1365  }
1366 
1367  unsigned int LevelCount() const
1368  {
1369  return m_levels.UnsignedCount();
1370  }
1371 
1372 public:
1373  class ON_SubDEdge* AddEdge(
1374  ON_SubD::EdgeTag edge_tag,
1375  ON_SubDVertex* v0,
1376  double v0_sector_weight,
1377  ON_SubDVertex* v1,
1378  double v1_sector_weight
1379  );
1380 
1381  /*
1382  Description:
1383  Split and edge.
1384  The input edge is modifed to terminate at the input vertex.
1385  The new edge begins at the input vertex and ends at the final vertex
1386  of the original input edge.
1387  edge - [in]
1388  edge to split.
1389  vertex_location - [in]
1390  location of inserted vertex.
1391  Returns:
1392  A pointer to the new edge or nullptr if the input is not valid.
1393  */
1394  const ON_SubDEdge* SplitEdge(
1395  ON_SubDEdge* edge,
1396  ON_3dPoint vertex_location
1397  );
1398 
1399  class ON_SubDFace* AddFace(
1400  unsigned int edge_count,
1401  const ON_SubDEdgePtr* edge
1402  );
1403 
1404  /*
1405  Description:
1406  Split a face into two faces by inserting and edge connecting the
1407  specified vertices.
1408  Parameters:
1409  face - [in]
1410  A face with at least four edges.
1411  fvi0 - [in]
1412  fvi1 - [in]
1413  Indices of the inserted edge ends.
1414  Returns:
1415  A pointer to the inserted edge.
1416  The inserted edge runs from face->Vertex(fvi0) to face->Vertex(fvi1).
1417  ON_SubDEdge.Face(0) is the original face and ON_SubDEdge::Face(1) is
1418  the added face.
1419  The first edge of the input face remains the first edge of face.
1420  The inserted edge is the first edge of the added face.
1421  */
1422  const ON_SubDEdge* SplitFace(
1423  ON_SubDFace* face,
1424  unsigned int fvi0,
1425  unsigned int fvi1
1426  );
1427 
1428  bool SetSubDType(
1429  ON_SubD::SubDType subdivision_type
1430  );
1431 
1432  class ON_SubDVertex* AllocateVertex(
1433  ON_SubD::VertexTag vertex_tag,
1434  unsigned int level,
1435  const double* P
1436  )
1437  {
1438  class ON_SubDVertex* v = m_heap.AllocateVertexAndSetId(m_max_vertex_id);
1439  v->m_level = (unsigned short)level;
1440  v->m_vertex_tag = vertex_tag;
1441  if (nullptr != P)
1442  {
1443  v->m_P[0] = P[0];
1444  v->m_P[1] = P[1];
1445  v->m_P[2] = P[2];
1446  }
1447  return v;
1448  }
1449 
1450  class ON_SubDVertex* AllocateVertex(
1451  ON_SubD::VertexTag vertex_tag,
1452  unsigned int level,
1453  const double* P,
1454  unsigned int edge_capacity,
1455  unsigned int face_capacity
1456  )
1457  {
1458  class ON_SubDVertex* v = AllocateVertex(vertex_tag,level,P);
1459 
1460  if (edge_capacity > 0 && edge_capacity < ON_SubDVertex::MaximumEdgeCount )
1461  m_heap.GrowVertexEdgeArray(v,edge_capacity);
1462  if (face_capacity > 0 && face_capacity < ON_SubDVertex::MaximumFaceCount )
1463  m_heap.GrowVertexFaceArray(v,face_capacity);
1464  return v;
1465  }
1466 
1467  const class ON_SubDVertex* AddVertexToLevel(class ON_SubDVertex* v)
1468  {
1469  class ON_SubDLevel* subd_level = SubDLevel(v->m_level,true);
1470  return (subd_level) ? subd_level->AddVertex(v) : nullptr;
1471  }
1472 
1473  void ReturnVertex(class ON_SubDVertex* v)
1474  {
1475  if (nullptr != v && v->m_level < m_levels.UnsignedCount())
1476  {
1477  ON_SubDLevel* level = m_levels[v->m_level];
1478  if (level)
1479  level->RemoveVertex(v);
1480  }
1481  v->ClearSavedLimitPoints(); // return extras to pool
1482  m_heap.ReturnVertex(v);
1483  }
1484 
1485  class ON_SubDEdge* AllocateEdge(
1486  ON_SubD::EdgeTag edge_tag
1487  )
1488  {
1489  class ON_SubDEdge* e = m_heap.AllocateEdgeAndSetId(m_max_edge_id);
1490  e->m_edge_tag = edge_tag;
1491  return e;
1492  }
1493 
1494  class ON_SubDEdge* AllocateEdge(
1495  ON_SubD::EdgeTag edge_tag,
1496  unsigned int level,
1497  unsigned int face_capacity
1498  )
1499  {
1500  class ON_SubDEdge* e = AllocateEdge(edge_tag);
1501  e->m_level = (unsigned short)level;
1502  if (face_capacity > 0 && face_capacity <= ON_SubDEdge::MaximumFaceCount )
1503  m_heap.GrowEdgeFaceArray(e,face_capacity);
1504  return e;
1505  }
1506 
1507  const class ON_SubDEdge* AddEdgeToLevel(class ON_SubDEdge* e)
1508  {
1509  class ON_SubDLevel* subd_level = SubDLevel(e->m_level,true);
1510  return (subd_level) ? subd_level->AddEdge(e) : nullptr;
1511  }
1512 
1513  void ReturnEdge(class ON_SubDEdge* e)
1514  {
1515  if (nullptr != e && e->m_level < m_levels.UnsignedCount())
1516  {
1517  ON_SubDLevel* level = m_levels[e->m_level];
1518  if (level)
1519  level->RemoveEdge(e);
1520  }
1521  m_heap.ReturnEdge(e);
1522  }
1523 
1524  class ON_SubDFace* AllocateFace()
1525  {
1526  class ON_SubDFace* f = m_heap.AllocateFaceAndSetId(m_max_face_id);
1527  return f;
1528  }
1529 
1530  class ON_SubDFace* AllocateFace(
1531  unsigned int level,
1532  unsigned int edge_capacity
1533  )
1534  {
1535  class ON_SubDFace* f = AllocateFace();
1536  if (nullptr != f)
1537  {
1538  f->m_level = (unsigned short)level;
1539  if (edge_capacity > sizeof(f->m_edge4)/sizeof(f->m_edge4[0]) && edge_capacity <= ON_SubDFace::MaximumEdgeCount)
1540  m_heap.GrowFaceEdgeArray(f,edge_capacity);
1541  }
1542  return f;
1543  }
1544 
1545  const class ON_SubDFace* AddFaceToLevel(class ON_SubDFace* f)
1546  {
1547  class ON_SubDLevel* subd_level = SubDLevel(f->m_level,true);
1548  return (subd_level) ? subd_level->AddFace(f) : nullptr;
1549  }
1550 
1551  void ReturnFace(class ON_SubDFace* f)
1552  {
1553  if (nullptr != f && f->m_level < m_levels.UnsignedCount())
1554  {
1555  ON_SubDLevel* level = m_levels[f->m_level];
1556  if (level)
1557  level->RemoveFace(f);
1558  }
1559  m_heap.ReturnFace(f);
1560  }
1561 
1562  unsigned int DeleteComponents(
1563  unsigned int level_index
1564  );
1565 
1566  /*
1567  Description:
1568  Discard all contents of this ON_SubDimple.
1569  Remarks:
1570  More efficient than Destroy() if this ON_SubDimple will be reused soon.
1571  */
1572  void Clear();
1573 
1574  void ClearSubdivisionLevels(
1575  unsigned int max_level_index
1576  );
1577 
1578  size_t SizeOf() const
1579  {
1580  size_t sz = sizeof(*this) + m_heap.SizeOf() - sizeof(m_heap);
1581  return sz;
1582  }
1583 
1584  bool Subdivide(
1585  ON_SubD::SubDType subd_type,
1586  unsigned int level_index,
1587  unsigned int count
1588  );
1589 
1590  /*
1591  Description:
1592  Apply global subdivision to m_levels[].Last().
1593  */
1594  unsigned int GlobalSubdivide(
1595  ON_SubD::SubDType subdivision_type,
1596  bool bUseSavedSubdivisionPoints
1597  );
1598 
1599  unsigned int MergeColinearEdges(
1600  double distance_tolerance,
1601  double maximum_aspect,
1602  double sin_angle_tolerance
1603  );
1604 
1605  ON_SubDEdgePtr MergeEdges(
1606  ON_SubDEdgePtr eptr0,
1607  ON_SubDEdgePtr eptr1
1608  );
1609 
1610 public:
1611  bool GrowVertexEdgeArray(
1612  ON_SubDVertex* v,
1613  size_t capacity
1614  );
1615  bool GrowVertexFaceArray(
1616  ON_SubDVertex* v,
1617  size_t capacity
1618  );
1619  bool GrowEdgeFaceArray(
1620  ON_SubDEdge* e,
1621  size_t capacity
1622  );
1623  bool GrowFaceEdgeArray(
1624  ON_SubDFace* f,
1625  size_t capacity
1626  );
1627 
1628 private:
1629  ON_SubDHeap m_heap;
1630 
1631  unsigned int m_max_vertex_id = 0;
1632  unsigned int m_max_edge_id = 0;
1633  unsigned int m_max_face_id = 0;
1634 
1636  ON_SubDLevel* m_active_level = nullptr; // m_active_level = nullptr or m_active_level = m_levels[m_active_level->m_level_index].
1637 
1638 public:
1639  /*
1640  Returns:
1641  Active level
1642  */
1643  const ON_SubDLevel& ActiveLevel() const
1644  {
1645  return (nullptr != m_active_level) ? *m_active_level : ON_SubDLevel::Empty;
1646  }
1647 
1648  ON_SubDLevel* ActiveLevelPointer()
1649  {
1650  return m_active_level;
1651  }
1652 
1653  bool SetActiveLevel(
1654  unsigned int level_index
1655  )
1656  {
1657  if (level_index < m_levels.UnsignedCount())
1658  {
1659  m_active_level = m_levels[level_index];
1660  return true;
1661  }
1662  return false;
1663  }
1664 
1665  class ON_SubDLevel const * SubDLevel(
1666  unsigned int level_index
1667  ) const;
1668 
1669 private:
1670  ON_SubDLevel* ActiveLevel(
1671  bool bCreateIfNeeded
1672  );
1673 
1674  class ON_SubDLevel* SubDLevel(
1675  unsigned int level_index,
1676  bool bCreateIfNeeded
1677  );
1678 
1679  /*
1680  Description:
1681  Delete all contents release all memory used by this ON_SubDimple.
1682  */
1683  void Destroy();
1684 
1685  bool IsValidLevel(
1686  const ON_SubD& subd,
1687  unsigned int level_index,
1688  bool bSilentError,
1689  ON_TextLog* text_log
1690  ) const;
1691 
1692  /*
1693  Returns:
1694  Number of quads added. When all input is valid the
1695  returned value is >= 4 and equal to face->m_edge_count.
1696  */
1697  unsigned int GlobalQuadSubdivideFace(
1698  bool bUseSavedSubdivisionPoint,
1699  const ON_SubDFace* face
1700  );
1701 
1702  /*
1703  Parameters:
1704  face - [in]
1705  bUseSavedSubdivisionPoint - [in]
1706  bUnsetEdgeWeight - [out]
1707  false - new edges have weights set
1708  true - the value of one or more ON_SubDEdge::m_vertex_weight[]
1709  was set to ON_SubDSectorType::UnsetSectorWeight because it cannot
1710  be calculated until the the rest of the subdivision is complete.
1711  This happens when sector face counts are required
1712  and a non-triangluar face is present in the level bing subdivided.
1713  Returns:
1714  Number of triangles added.
1715  If the input is valid and face->m_edge_count = 3, then the
1716  returned value will be 4.
1717  If the input is valid and face->m_edge_count > 3, then the
1718  returned value will be 2*face->m_edge_count.
1719  */
1720  unsigned int GlobalTriSubdivideFace(
1721  const ON_SubDFace* face,
1722  bool bUseSavedSubdivisionPoint,
1723  bool* bUnsetEdgeWeight
1724  );
1725 
1726  private:
1727  ON_SubDimple& operator=(const ON_SubDimple&) = delete;
1728 };
1729 
1730 
1731 
1732 class ON_SubDQuadFaceSubdivisionCounter
1733 {
1734 public:
1735  const ON_SubDFace* m_level0_face = nullptr;
1736  unsigned int m_level0_face_id = 0;
1737 
1738  unsigned short m_subdivision_count = 0;
1739  unsigned short m_corner_index[9];
1740 
1741  void SetLevel0Face(
1742  const ON_SubDFace* face
1743  )
1744  {
1745  m_level0_face = face;
1746  m_level0_face_id = (nullptr == face) ? 0 : face->m_id;
1747  m_subdivision_count = 0;
1748  }
1749 
1750  bool BreakpointTest();
1751 
1752  void Push(
1753  unsigned int face_corner_index
1754  )
1755  {
1756  if ( face_corner_index >= 0xFFFFU )
1757  face_corner_index = 0xFFFFU;
1758  if ( m_subdivision_count < sizeof(m_corner_index)/sizeof(m_corner_index[0]) )
1759  m_corner_index[m_subdivision_count] = (unsigned short)face_corner_index;
1760  m_subdivision_count++;
1761  BreakpointTest();
1762  }
1763 
1764  void Pop()
1765  {
1766  if ( m_subdivision_count > 0 )
1767  m_subdivision_count--;
1768  }
1769 };
1770 
1771 
1772 //////////////////////////////////////////////////////////////////////////
1773 //
1774 // ON_SubDQuadFaceMesher
1775 //
1776 
1777 class ON_SubDQuadFacePatcher
1778 {
1779 public:
1780  ON_SubDLimitPatchFragment m_patch_fragment = ON_SubDLimitPatchFragment::Empty;
1781  unsigned int m_display_density = 0;
1782  unsigned int m_patch_count = 0;
1783  ON__UINT_PTR m_fragment_callback_context = 0;
1784  bool (*m_fragment_callback_function)(ON__UINT_PTR, const class ON_SubDLimitPatchFragment*) = nullptr;
1785  bool m_bCallbackResult = false;
1786 
1787  bool SendSinglePatch(
1788  unsigned int display_density,
1789  const class ON_SubDQuadFaceSubdivisionCounter& quad_face_subdivision_counter,
1790  ON_SubDLimitPatchFragment::PatchType patch_type
1791  );
1792 
1793  bool SendMultiPatch(
1794  unsigned int display_density,
1795  const class ON_SubDQuadFaceSubdivisionCounter& quad_face_subdivision_counter,
1796  const ON_SubDLimitPatchFragment::PatchType patch_type[4]
1797  );
1798 };
1799 
1800 class ON_SubDQuadFaceMesher
1801 {
1802 public:
1803  ON_SubDQuadFaceMesher() = default;
1804 
1805  ~ON_SubDQuadFaceMesher()
1806  {
1807  if (nullptr != m__buffer)
1808  {
1809  delete[] m__buffer;
1810  m__buffer = nullptr;
1811  m__buffer_capacity = 0;
1812  }
1813  }
1814 
1815  enum class Output : unsigned int
1816  {
1817  unset = 0,
1818  mesh = 1,
1819  patches = 2
1820  };
1821 
1822  ON_SubDQuadFaceMesher::Output m_output = ON_SubDQuadFaceMesher::Output::unset;
1823 
1824  // The m_display_density parameter determines the density of output.
1825  unsigned int m_display_density = 0;
1826 
1827 private:
1828  unsigned int m_reserved = 0;
1829 public:
1830 
1831  //////////////////////////////////////////////////////////////////////////////////
1832  //
1833  // SubD limit surface mesh output
1834  //
1835  // The mesh has m_count x m_count quads, where m_count = 2^m_mesh_density.
1836  // There are (m_count+1)*(m_count+1) points in the mesh.
1837  unsigned int m_count = 0;
1838  unsigned int m_capacity = 0;
1839 
1840 
1841  // Point(i,j) = (m_points + i*m_point_stride0 + j*m_point_stride1)[0,1,2]
1842  size_t m_point_stride0 = 0;
1843  size_t m_point_stride1 = 0;
1844  double* m_points = nullptr;
1845 
1846  // Normal(i,j) = (m_normals + i*m_normal_stride0 + j*m_normal_stride1)[0,1,2]
1847  size_t m_normal_stride0 = 0;
1848  size_t m_normal_stride1 = 0;
1849  double* m_normals = nullptr;
1850 
1851  //////////////////////////////////////////////////////////////////////////////////
1852  //
1853  // SubD limit surface NURBS patch output
1854  //
1855  class ON_SubDQuadFacePatcher* m_patcher = nullptr;
1856 
1857  /*
1858  Description:
1859  Allocates memory this ON_SubDQuadFaceMesher manages (m_buffer) and
1860  uses it for the m_points and m_normals arrays.
1861  */
1862  bool SetDestinationToLocalMeshBuffer(
1863  unsigned int mesh_density
1864  );
1865 
1866  /*
1867  Description:
1868  Set the first coordinate of every point to ON_UNSET_VALUE.
1869  */
1870  bool UnsetMeshPoints();
1871 
1872  /*
1873  Description:
1874  Uses memory on fragment as the destination and sets the m_points and m_normals
1875  arrays on this to point to appropriate locations in fragment.m_P and fragment.m_N.
1876  */
1877  bool SetDestinationToMeshFragment(
1878  unsigned int mesh_density,
1879  class ON_SubDLimitMeshFragment& mesh_fragment
1880  );
1881 
1882  bool SetDestinationToPatchFragment(
1883  class ON_SubDQuadFacePatcher& patcher
1884  );
1885 
1886  bool GetLimitMesh(
1887  class ON_SubDQuadFaceSubdivisionCounter& quad_face_subdivision_counter,
1888  const ON_SubDFace* face
1889  );
1890 
1891  bool GetLimitPatches(
1892  class ON_SubDQuadFaceSubdivisionCounter& quad_face_subdivision_counter,
1893  const ON_SubDFace* face
1894  );
1895 
1896 private:
1897  double* Internal_Buffer(size_t buffer_capacity);
1898 
1899  size_t m__buffer_capacity = 0;
1900  double* m__buffer = nullptr;
1901 
1902  /*
1903  Description:
1904  Get values of cubic uniform B-spline basis functions times 6.
1905  Parameters:
1906  t - [in] 0.0 <= t <= 1.0
1907  Evaluation parameter
1908  b - [out]
1909  t^3,
1910  (1 + 3t + 3t^2 - 3t^3)
1911  (1 + 3(1-t) + 3(1-t)^2 - 3(1-t)^3)
1912  (1-t)^3
1913  Remarks:
1914  If C0, C1, C2, C3 are the control points for a span
1915  of a uniform cubic B-spline and the domain of the
1916  span is 0 <= t <= 1, then
1917  C(t) = (b[0]*C0 + b[1]*C1 + b[2]*C2 + b[3]*C3)/6.
1918  */
1919  static void Get6xCubicBasis(
1920  double t,
1921  double b6[4]
1922  );
1923 
1924  /*
1925  Description:
1926  Get values of derviatives of cubic uniform B-spline basis functions.
1927  Parameters:
1928  t - [in] 0.0 <= t <= 1.0
1929  Evaluation parameter
1930  b - [out]
1931  t^3,
1932  (1 + 3t + 3t^2 - 3t^3)
1933  (1 + 3(1-t) + 3(1-t)^2 - 3(1-t)^3)
1934  (1-t)^3
1935  Remarks:
1936  If C0, C1, C2, C3 are the control points for a span
1937  of a uniform cubic B-spline and the domain of the
1938  span is 0 <= t <= 1, then the first derivative is
1939  C'(t) = (b[0]*C0 + b[1]*C1 + b[2]*C2 + b[3]*C3).
1940  */
1941  static void GetCubicBasisDerivative(
1942  double t,
1943  double b[4]
1944  );
1945 
1946  /*
1947  Description:
1948  Calcululate a quad mesh from the bi-cubic uniform B-spline surface.
1949  Parameters:
1950  Returns:
1951  true:
1952  successful
1953  false:
1954  failure
1955  */
1956  bool EvaluateSurface(
1957  unsigned int count,
1958  unsigned int point_i0,
1959  unsigned int point_j0
1960  ) const;
1961 
1962  bool GetLimitSubMeshOrPatch(
1963  class ON_SubDQuadFaceSubdivisionCounter& quad_face_subdivision_counter,
1964  class ON_SubDQuadNeighborhood* qft, // may be destroyed
1965  unsigned int display_density,
1966  unsigned int point_i0,
1967  unsigned int point_j0
1968  );
1969 
1970 private:
1971  bool Internal_EvaluateSurfaceNormalBackup1(
1972  double s,
1973  double t,
1974  unsigned int count,
1975  unsigned int i,
1976  unsigned int j,
1977  double* N
1978  ) const;
1979  bool Internal_EvaluateSurfaceNormalBackup2(
1980  const double* P00,
1981  unsigned int count,
1982  unsigned int i,
1983  unsigned int j,
1984  double* N
1985  ) const;
1986  // Workspaces used by GetLimitSubMesh()
1987  double m_srf_cv[4][4][3];
1988  ON_SubD_FixedSizeHeap m_fshx[5];
1989 
1990  ON_SubD_FixedSizeHeap* CheckOutLocalFixedSizeHeap()
1991  {
1992  const size_t count = sizeof(m_fshx) / sizeof(m_fshx[0]);
1993  for (size_t i = 0; i < count; i++)
1994  {
1995  if ( false == m_fshx[i].InUse() )
1996  return &m_fshx[i];
1997  }
1998  return ON_SUBD_RETURN_ERROR(nullptr);
1999  }
2000 
2001  bool ReturnLocalFixedSizeHeap(ON_SubD_FixedSizeHeap* fsh)
2002  {
2003  if ( nullptr == fsh)
2004  return ON_SUBD_RETURN_ERROR(false);
2005 
2006  const size_t count = sizeof(m_fshx) / sizeof(m_fshx[0]);
2007  for (size_t i = 0; i < count; i++)
2008  {
2009  if (fsh == &m_fshx[i])
2010  {
2011  m_fshx[i].Reset();
2012  return true;
2013  }
2014  }
2015 
2016  return false; // not an error
2017  }
2018 
2019  void ReturnAllFixedSizeHeaps()
2020  {
2021  const size_t count = sizeof(m_fshx) / sizeof(m_fshx[0]);
2022  for (size_t i = 0; i < count; i++)
2023  {
2024  m_fshx[i].Reset();
2025  }
2026  }
2027 
2028 private:
2029  void SetDestinationInitialize(
2030  ON_SubDQuadFaceMesher::Output output
2031  );
2032 
2033 
2034 private:
2035  // copies not supported
2036  ON_SubDQuadFaceMesher(const ON_SubDQuadFaceMesher&) = delete;
2037  ON_SubDQuadFaceMesher& operator=(const ON_SubDQuadFaceMesher&) = delete;
2038 };
2039 
2040 
2041 class ON_SubDArchiveIdMap
2042 {
2043  // used for file IO, copy construction, and operator= where the problem
2044  // of converting to/from pointers to archive_ids is necessary.
2045 public:
2046  static unsigned int ArchiveIdFromComponentPtr(
2047  ON__UINT_PTR ptr
2048  );
2049 
2050  bool ConvertArchiveIdToRuntimeVertexPtr(
2051  unsigned int vertex_count,
2052  size_t vertex_capacity,
2053  ON_SubDVertex** vertex
2054  );
2055 
2056  bool ConvertArchiveIdToRuntimeEdgePtr(
2057  unsigned int edge_count,
2058  size_t edgeN_capacity,
2059  ON_SubDEdgePtr* edgeN,
2060  unsigned int edgeX_capacity,
2061  ON_SubDEdgePtr* edgeX
2062  );
2063 
2064  bool ConvertArchiveIdToRuntimeFacePtr(
2065  unsigned int face_count,
2066  size_t faceN_capacity,
2067  ON_SubDFacePtr* faceN,
2068  unsigned int faceX_capacity,
2069  ON_SubDFacePtr* faceX
2070  );
2071 
2072  static void ValidateArrayCounts(
2073  unsigned short& array_count,
2074  size_t arrayN_capacity,
2075  const void* arrayN,
2076  unsigned short arrayX_capacity,
2077  const void* arrayX
2078  );
2079 
2080  static ON_SubDComponentPtr FromVertex(
2081  ON_SubDVertexPtr vertex_ptr
2082  );
2083 
2084  static ON_SubDComponentPtr FromEdge(
2085  ON_SubDEdgePtr edge_ptr
2086  );
2087 
2088  static ON_SubDComponentPtr FromFace(
2089  ON_SubDFacePtr face_ptr
2090  );
2091 
2092  static ON_SubDComponentPtr FromVertex(
2093  const ON_SubDVertex* vertex
2094  );
2095 
2096  static ON_SubDComponentPtr FromEdge(
2097  const ON_SubDEdge* edge
2098  );
2099 
2100  static ON_SubDComponentPtr FromFace(
2101  const ON_SubDFace* face
2102  );
2103 
2104  static ON_SubDVertex* CopyVertex(
2105  const ON_SubDVertex* src,
2106  class ON_SubDimple& subdimple
2107  );
2108 
2109  static ON_SubDEdge* CopyEdge(
2110  const ON_SubDEdge* src,
2111  class ON_SubDimple& subdimple
2112  );
2113 
2114  static ON_SubDFace* CopyFace(
2115  const ON_SubDFace* src,
2116  class ON_SubDimple& subdimple
2117  );
2118 
2119  ON_SubDArchiveIdMap();
2120 
2121  bool Reset();
2122 
2123  unsigned int Count();
2124 
2125  const ON_SubDComponentPtr* First();
2126  const ON_SubDComponentPtr* Next();
2127 
2128  bool Add(const ON_SubDVertex* vertex);
2129  bool Add(const ON_SubDEdge* edge);
2130  bool Add(const ON_SubDFace* face);
2131 
2132  class ON_SubDVertex* AddCopy(const class ON_SubDVertex* source_vertex, class ON_SubDimple& subdimple);
2133  class ON_SubDEdge* AddCopy(const class ON_SubDEdge* source_edgeclass, class ON_SubDimple& subdimple);
2134  class ON_SubDFace* AddCopy(const class ON_SubDFace* source_faceclass, class ON_SubDimple& subdimple);
2135 
2136  const ON_SubDComponentPtr* ComponentPtrFromArchiveId(
2137  unsigned int archive_id
2138  ) const;
2139 
2140  unsigned int m_archive_id_partition[4];
2141 
2142  unsigned int ConvertArchiveIdsToRuntimePointers();
2143 
2144 private:
2145  bool AddComponentPtr(ON_SubDComponentPtr eptr, unsigned int archive_id);
2146 
2147  unsigned int m_element_index = ON_UNSET_UINT_INDEX;
2148  unsigned int m_element_count = 0;
2149  ON_FixedSizePool m_fsp;
2150  ON_FixedSizePoolIterator m_fsp_it;
2151 };
2152 
2153 //////////////////////////////////////////////////////////////////////////
2154 //
2155 // ON_SubDLimitMesh
2156 //
2157 
2158 class /*DO NOT EXPORT*/ON_SubDLimitMeshImpl
2159 {
2160 #if defined(ON_SUBD_CENSUS)
2161  ON_SubDLimitMeshImplCensusCounter m_census_counter;
2162 #endif
2163 
2164 public:
2165  ON_SubDLimitMeshImpl();
2166  ~ON_SubDLimitMeshImpl() = default;
2167  ON_SubDLimitMeshImpl(const ON_SubDLimitMeshImpl& src);
2168 
2169 private:
2170  // no operator =
2171  ON_SubDLimitMeshImpl& operator=(const ON_SubDLimitMeshImpl&) = delete;
2172 
2173 public:
2174  ON_SubD::FacetType m_facet_type = ON_SubD::FacetType::Unset;
2175 private:
2176  unsigned char m_reserved1 = 0;
2177  unsigned short m_reserved2 = 0;
2178  unsigned int m_reserved3 = 0;
2179 public:
2180  unsigned int m_limit_mesh_content_serial_number;
2181 private:
2182  static unsigned int Internal_NextContentSerialNumber();
2183 public:
2184  unsigned int m_display_density = 0;
2185  unsigned int m_fragment_count = 0;
2186  unsigned int m_fragment_point_count = 0;
2187  ON_SubDLimitMeshFragment* m_first_fragment = nullptr;
2188  ON_SubDLimitMeshFragment* m_last_fragment = nullptr;
2189 
2190  bool ReserveCapacity(
2191  unsigned int subd_fragment_count,
2192  ON_SubD::FacetType facet_type,
2193  unsigned int display_density
2194  );
2195 
2196  /*
2197  Description:
2198  ON_SubDLimitMeshImpl_CallbackContext::FragmentCallbackFunction()
2199  uses CopyCallbackFragment() to make a copy of callback_fragment
2200  delivered by ON_SubD::GetLimitSurfaceMeshInFragments().
2201  */
2202  ON_SubDLimitMeshFragment* CopyCallbackFragment(
2203  const ON_SubDLimitMeshFragment* callback_fragment
2204  );
2205 
2206  /*
2207  Description:
2208  ON_SubDLimitMeshImpl_CallbackContext::FragmentCallbackFunction()
2209  uses AddFinishedFragment() to add finished fragments to this
2210  ON_SubDLimitMeshImpl's m_first_fragment ... m_list_fragment list.
2211  */
2212  bool AddFinishedFragment(
2213  ON_SubDLimitMeshFragment* fragment
2214  );
2215 
2216  const ON_RTree& FragmentTree() const;
2217 
2218  void ClearTree();
2219 
2220  bool Transform(
2221  const ON_Xform& xform
2222  );
2223 
2224 
2225  bool GetTightBoundingBox(
2226  ON_BoundingBox& bbox,
2227  bool bGrowBox,
2228  const ON_Xform* xform
2229  ) const;
2230 
2231  ON_BoundingBox m_bbox;
2232 
2233  // The weak pointer to the ON_SubDimple is used to
2234  // check that the ON_SubDimple managing the
2235  // ON_SubDLimitMeshFragment.m_face pointers is valid
2236  // before those pointers are used. This must be a weak
2237  // pointer and not a shared_ptr because limit meshes
2238  // are stored on ON_SubDLevels that are members of
2239  // ON_SubDimple.
2240  std::weak_ptr<class ON_SubDimple> m_subdimple_wp;
2241 
2242  void ClearFragmentFacePointers();
2243 
2244 private:
2245  ON_RTree* m_fragment_tree = nullptr;
2246 
2247 private:
2248  ON_FixedSizePool m_fsp;
2249 };
2250 
2251 #endif // ON_COMPILING_OPENNURBS)
2252 
2253 #endif // OPENNURBS_SUBD_WIP
2254 
2255 #endif // OPENNURBS_SUBD_DATA_INC_
2256 
static const ON_BoundingBox EmptyBoundingBox
Definition: opennurbs_bounding_box.h:28
Definition: opennurbs_rtree.h:398
Definition: opennurbs_array.h:36
static const ON_AggregateComponentStatus Empty
Definition: opennurbs_compstat.h:399
Definition: opennurbs_fsp.h:19
Definition: opennurbs_compstat.h:396
Definition: opennurbs_bounding_box.h:25
unsigned int UnsignedCount() const
Definition: opennurbs_array_defs.h:167
Definition: opennurbs_xform.h:28
Definition: opennurbs_compstat.h:88
Definition: opennurbs_textlog.h:20
Definition: opennurbs_archive.h:1783
Definition: opennurbs_point.h:460
Definition: opennurbs_fsp.h:239