OpenSubdiv
topologyRefinerFactory.h
Go to the documentation of this file.
1 //
2 // Copyright 2014 DreamWorks Animation LLC.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24 #ifndef OPENSUBDIV3_FAR_TOPOLOGY_REFINER_FACTORY_H
25 #define OPENSUBDIV3_FAR_TOPOLOGY_REFINER_FACTORY_H
26 
27 #include "../version.h"
28 
29 #include "../far/topologyRefiner.h"
30 #include "../far/error.h"
31 
32 #include <cassert>
33 
34 namespace OpenSubdiv {
35 namespace OPENSUBDIV_VERSION {
36 
37 namespace Far {
38 
46 //
48 protected:
49 
50  //
51  // Protected methods invoked by the subclass template to verify and process each
52  // stage of construction implemented by the subclass:
53  //
54  typedef Vtr::internal::Level::ValidationCallback TopologyCallback;
55 
56  static bool prepareComponentTopologySizing(TopologyRefiner& refiner);
57  static bool prepareComponentTopologyAssignment(TopologyRefiner& refiner, bool fullValidation,
58  TopologyCallback callback, void const * callbackData);
60  static bool prepareFaceVaryingChannels(TopologyRefiner& refiner);
61 };
62 
63 
77 template <class MESH>
79 
80 public:
81 
84  struct Options {
85 
87  schemeType(sdcType),
88  schemeOptions(sdcOptions),
89  validateFullTopology(false) { }
90 
93  unsigned int validateFullTopology : 1;
95  };
98 
108  //
113  static TopologyRefiner* Create(MESH const& mesh, Options options = Options());
114 
128  static TopologyRefiner* Create(TopologyRefiner const & baseLevel);
129 
130 protected:
131  typedef Vtr::internal::Level::TopologyError TopologyError;
132 
134 
151  static bool resizeComponentTopology(TopologyRefiner& newRefiner, MESH const& mesh);
152 
155  static bool assignComponentTopology(TopologyRefiner& newRefiner, MESH const& mesh);
156 
158  static bool assignComponentTags(TopologyRefiner& newRefiner, MESH const& mesh);
159 
161  static bool assignFaceVaryingTopology(TopologyRefiner& newRefiner, MESH const& mesh);
162 
164  static void reportInvalidTopology(TopologyError errCode, char const * msg, MESH const& mesh);
165 
167 
168 protected:
170 
189  static void setNumBaseVertices(TopologyRefiner & newRefiner, int count);
190 
192  static void setNumBaseFaces(TopologyRefiner & newRefiner, int count);
193 
195  static void setNumBaseEdges(TopologyRefiner & newRefiner, int count);
196 
198  static void setNumBaseFaceVertices(TopologyRefiner & newRefiner, Index f, int count);
199 
201  static void setNumBaseEdgeFaces(TopologyRefiner & newRefiner, Index e, int count);
202 
204  static void setNumBaseVertexFaces(TopologyRefiner & newRefiner, Index v, int count);
205 
207  static void setNumBaseVertexEdges(TopologyRefiner & newRefiner, Index v, int count);
208 
209  static int getNumBaseVertices(TopologyRefiner const & newRefiner);
210  static int getNumBaseFaces(TopologyRefiner const & newRefiner);
211  static int getNumBaseEdges(TopologyRefiner const & newRefiner);
213 
215 
239  static IndexArray getBaseFaceVertices(TopologyRefiner & newRefiner, Index f);
240 
242  static IndexArray getBaseFaceEdges(TopologyRefiner & newRefiner, Index f);
243 
245  static IndexArray getBaseEdgeVertices(TopologyRefiner & newRefiner, Index e);
246 
248  static IndexArray getBaseEdgeFaces(TopologyRefiner & newRefiner, Index e);
249 
251  static IndexArray getBaseVertexFaces(TopologyRefiner & newRefiner, Index v);
252 
254  static IndexArray getBaseVertexEdges(TopologyRefiner & newRefiner, Index v);
255 
262 
264  static void populateBaseLocalIndices(TopologyRefiner & newRefiner);
265 
267  static void setBaseEdgeNonManifold(TopologyRefiner & newRefiner, Index e, bool b);
268 
270  static void setBaseVertexNonManifold(TopologyRefiner & newRefiner, Index v, bool b);
272 
274 
285  static Index findBaseEdge(TopologyRefiner const & newRefiner, Index v0, Index v1);
286 
288  static void setBaseEdgeSharpness(TopologyRefiner & newRefiner, Index e, float sharpness);
289 
291  static void setBaseVertexSharpness(TopologyRefiner & newRefiner, Index v, float sharpness);
292 
294  static void setBaseFaceHole(TopologyRefiner & newRefiner, Index f, bool isHole);
296 
298 
310  static int createBaseFVarChannel(TopologyRefiner & newRefiner, int numValues);
311 
313  static int createBaseFVarChannel(TopologyRefiner & newRefiner, int numValues, Sdc::Options const& fvarOptions);
314 
316  static IndexArray getBaseFaceFVarValues(TopologyRefiner & newRefiner, Index face, int channel = 0);
317 
319 
320 protected:
321  //
322  // Not to be specialized:
323  //
324  static bool populateBaseLevel(TopologyRefiner& refiner, MESH const& mesh, Options options);
325 
326 private:
327  //
328  // An oversight in the interfaces of the error reporting function between the factory
329  // class and the Vtr::Level requires this adapter function to avoid warnings.
330  //
331  // The static class method requires a reference as the MESH argument, but the interface
332  // for Vtr::Level requires a pointer (void*). So this adapter with a MESH* argument is
333  // used to effectively cast the function pointer required by Vtr::Level error reporting:
334  //
335  static void reportInvalidTopologyAdapter(TopologyError errCode, char const * msg, MESH const * mesh) {
336  reportInvalidTopology(errCode, msg, *mesh);
337  }
338 };
339 
340 
341 //
342 // Generic implementations:
343 //
344 template <class MESH>
345 TopologyRefiner*
346 TopologyRefinerFactory<MESH>::Create(MESH const& mesh, Options options) {
347 
348  TopologyRefiner * refiner = new TopologyRefiner(options.schemeType, options.schemeOptions);
349 
350  if (! populateBaseLevel(*refiner, mesh, options)) {
351  delete refiner;
352  return 0;
353  }
354 
355  // Eventually want to move the Refiner's inventory initialization here. Currently it
356  // is handled after topology assignment, but if the inventory is to include additional
357  // features (e.g. holes, etc.) it is better off deferred to here.
358 
359  return refiner;
360 }
361 
362 template <class MESH>
365 
366  return new TopologyRefiner(source);
367 }
368 
369 template <class MESH>
370 bool
372 
373  //
374  // Construction of a specialized topology refiner involves four steps, each of which
375  // involves a method specialized for MESH followed by one that takes an action in
376  // response to it or in preparation for the next step.
377  //
378  // Both the specialized methods and those that follow them may find fault in the
379  // construction and trigger failure at any time:
380  //
381 
382  //
383  // Sizing of the topology -- this is a required specialization for MESH. This defines
384  // an inventory of all components and their relations that is used to allocate buffers
385  // to be efficiently populated in the subsequent topology assignment step.
386  //
387  if (! resizeComponentTopology(refiner, mesh)) return false;
388  if (! prepareComponentTopologySizing(refiner)) return false;
389 
390  //
391  // Assignment of the topology -- this is a required specialization for MESH. If edges
392  // are specified, all other topological relations are expected to be defined for them.
393  // Otherwise edges and remaining topology will be completed from the face-vertices:
394  //
395  bool validate = options.validateFullTopology;
396  TopologyCallback callback = reinterpret_cast<TopologyCallback>(reportInvalidTopologyAdapter);
397  void const * userData = &mesh;
398 
399  if (! assignComponentTopology(refiner, mesh)) return false;
400  if (! prepareComponentTopologyAssignment(refiner, validate, callback, userData)) return false;
401 
402  //
403  // User assigned and internal tagging of components -- an optional specialization for
404  // MESH. Allows the specification of sharpness values, holes, etc.
405  //
406  if (! assignComponentTags(refiner, mesh)) return false;
407  if (! prepareComponentTagsAndSharpness(refiner)) return false;
408 
409  //
410  // Defining channels of face-varying primvar data -- an optional specialization for MESH.
411  //
412  if (! assignFaceVaryingTopology(refiner, mesh)) return false;
413  if (! prepareFaceVaryingChannels(refiner)) return false;
414 
415  return true;
416 }
417 
418 template <class MESH>
419 inline void
421  newRefiner._levels[0]->resizeFaces(count);
422 }
423 template <class MESH>
424 inline void
426  newRefiner._levels[0]->resizeEdges(count);
427 }
428 template <class MESH>
429 inline void
431  newRefiner._levels[0]->resizeVertices(count);
432 }
433 
434 template <class MESH>
435 inline int
437  return newRefiner._levels[0]->getNumFaces();
438 }
439 template <class MESH>
440 inline int
442  return newRefiner._levels[0]->getNumEdges();
443 }
444 template <class MESH>
445 inline int
447  return newRefiner._levels[0]->getNumVertices();
448 }
449 
450 template <class MESH>
451 inline void
453  newRefiner._levels[0]->resizeFaceVertices(f, count);
454  newRefiner._hasIrregFaces = newRefiner._hasIrregFaces || (count != newRefiner._regFaceSize);
455 }
456 template <class MESH>
457 inline void
459  newRefiner._levels[0]->resizeEdgeFaces(e, count);
460 }
461 template <class MESH>
462 inline void
464  newRefiner._levels[0]->resizeVertexFaces(v, count);
465 }
466 template <class MESH>
467 inline void
469  newRefiner._levels[0]->resizeVertexEdges(v, count);
470 }
471 
472 template <class MESH>
473 inline IndexArray
475  return newRefiner._levels[0]->getFaceVertices(f);
476 }
477 template <class MESH>
478 inline IndexArray
480  return newRefiner._levels[0]->getFaceEdges(f);
481 }
482 template <class MESH>
483 inline IndexArray
485  return newRefiner._levels[0]->getEdgeVertices(e);
486 }
487 template <class MESH>
488 inline IndexArray
490  return newRefiner._levels[0]->getEdgeFaces(e);
491 }
492 template <class MESH>
493 inline IndexArray
495  return newRefiner._levels[0]->getVertexFaces(v);
496 }
497 template <class MESH>
498 inline IndexArray
500  return newRefiner._levels[0]->getVertexEdges(v);
501 }
502 
503 template <class MESH>
504 inline LocalIndexArray
506  return newRefiner._levels[0]->getEdgeFaceLocalIndices(e);
507 }
508 template <class MESH>
509 inline LocalIndexArray
511  return newRefiner._levels[0]->getVertexFaceLocalIndices(v);
512 }
513 template <class MESH>
514 inline LocalIndexArray
516  return newRefiner._levels[0]->getVertexEdgeLocalIndices(v);
517 }
518 
519 template <class MESH>
520 inline Index
522  return newRefiner._levels[0]->findEdge(v0, v1);
523 }
524 
525 template <class MESH>
526 inline void
528  newRefiner._levels[0]->populateLocalIndices();
529 }
530 
531 template <class MESH>
532 inline void
534  newRefiner._levels[0]->setEdgeNonManifold(e, b);
535 }
536 template <class MESH>
537 inline void
539  newRefiner._levels[0]->setVertexNonManifold(v, b);
540 }
541 
542 template <class MESH>
543 inline void
545  newRefiner._levels[0]->getEdgeSharpness(e) = s;
546 }
547 template <class MESH>
548 inline void
550  newRefiner._levels[0]->getVertexSharpness(v) = s;
551 }
552 template <class MESH>
553 inline void
555  newRefiner._levels[0]->setFaceHole(f, b);
556  newRefiner._hasHoles = newRefiner._hasHoles || b;
557 }
558 
559 template <class MESH>
560 inline int
562  return newRefiner._levels[0]->createFVarChannel(numValues, newRefiner._subdivOptions);
563 }
564 template <class MESH>
565 inline int
566 TopologyRefinerFactory<MESH>::createBaseFVarChannel(TopologyRefiner & newRefiner, int numValues, Sdc::Options const& fvarOptions) {
567  Sdc::Options newOptions = newRefiner._subdivOptions;
568  newOptions.SetFVarLinearInterpolation(fvarOptions.GetFVarLinearInterpolation());
569  return newRefiner._levels[0]->createFVarChannel(numValues, newOptions);
570 }
571 template <class MESH>
572 inline IndexArray
574  return newRefiner._levels[0]->getFaceFVarValues(face, channel);
575 }
576 
577 
578 template <class MESH>
579 bool
581 
583  "Failure in TopologyRefinerFactory<>::resizeComponentTopology() -- no specialization provided.");
584 
585  //
586  // Sizing the topology tables:
587  // This method is for determining the sizes of the various topology tables (and other
588  // data) associated with the mesh. Once completed, appropriate memory will be allocated
589  // and an additional method invoked to populate it accordingly.
590  //
591  // The following methods should be called -- first those to specify the number of faces,
592  // edges and vertices in the mesh:
593  //
594  // void setBaseFaceCount( TopologyRefiner& newRefiner, int count)
595  // void setBaseEdgeCount( TopologyRefiner& newRefiner, int count)
596  // void setBaseVertexCount(TopologyRefiner& newRefiner, int count)
597  //
598  // and then for each face, edge and vertex, the number of its incident components:
599  //
600  // void setBaseFaceVertexCount(TopologyRefiner& newRefiner, Index face, int count)
601  // void setBaseEdgeFaceCount( TopologyRefiner& newRefiner, Index edge, int count)
602  // void setBaseVertexFaceCount(TopologyRefiner& newRefiner, Index vertex, int count)
603  // void setBaseVertexEdgeCount(TopologyRefiner& newRefiner, Index vertex, int count)
604  //
605  // The count/size for a component type must be set before indices associated with that
606  // component type can be used.
607  //
608  // Note that it is only necessary to size 4 of the 6 supported topological relations --
609  // the number of edge-vertices is fixed at two per edge, and the number of face-edges is
610  // the same as the number of face-vertices.
611  //
612  // So a single pass through your mesh to gather up all of this sizing information will
613  // allow the Tables to be allocated appropriately once and avoid any dynamic resizing as
614  // it grows.
615  //
616  return false;
617 }
618 
619 template <class MESH>
620 bool
622 
624  "Failure in TopologyRefinerFactory<>::assignComponentTopology() -- no specialization provided.");
625 
626  //
627  // Assigning the topology tables:
628  // Once the topology tables have been allocated, the six required topological
629  // relations can be directly populated using the following methods:
630  //
631  // IndexArray setBaseFaceVertices(TopologyRefiner& newRefiner, Index face)
632  // IndexArray setBaseFaceEdges(TopologyRefiner& newRefiner, Index face)
633  //
634  // IndexArray setBaseEdgeVertices(TopologyRefiner& newRefiner, Index edge)
635  // IndexArray setBaseEdgeFaces(TopologyRefiner& newRefiner, Index edge)
636  //
637  // IndexArray setBaseVertexEdges(TopologyRefiner& newRefiner, Index vertex)
638  // IndexArray setBaseVertexFaces(TopologyRefiner& newRefiner, Index vertex)
639  //
640  // For the last two relations -- the faces and edges incident a vertex -- there are
641  // also "local indices" that must be specified (considering doing this internally),
642  // where the "local index" of each incident face or edge is the index of the vertex
643  // within that face or edge, and so ranging from 0-3 for incident quads and 0-1 for
644  // incident edges. These are assigned through similarly retrieved arrays:
645  //
646  // LocalIndexArray setBaseVertexFaceLocalIndices(TopologyRefiner& newRefiner, Index vertex)
647  // LocalIndexArray setBaseVertexEdgeLocalIndices(TopologyRefiner& newRefiner, Index vertex)
648  // LocalIndexArray setBaseEdgeFaceLocalIndices( TopologyRefiner& newRefiner, Index edge)
649  //
650  // or, if the mesh is manifold, explicit assignment of these can be deferred and
651  // all can be determined by calling:
652  //
653  // void populateBaseLocalIndices(TopologyRefiner& newRefiner)
654  //
655  // All components are assumed to be locally manifold and ordering of components in
656  // the above relations is expected to be counter-clockwise.
657  //
658  // For non-manifold components, no ordering/orientation of incident components is
659  // assumed or required, but be sure to explicitly tag such components (vertices and
660  // edges) as non-manifold:
661  //
662  // void setBaseEdgeNonManifold(TopologyRefiner& newRefiner, Index edge, bool b);
663  //
664  // void setBaseVertexNonManifold(TopologyRefiner& newRefiner, Index vertex, bool b);
665  //
666  // Also consider using TopologyLevel::ValidateTopology() when debugging to ensure
667  // that topology has been completely and correctly specified.
668  //
669  return false;
670 }
671 
672 template <class MESH>
673 bool
675 
676  //
677  // Optional assigning face-varying topology tables:
678  //
679  // Create independent face-varying primitive variable channels:
680  // int createBaseFVarChannel(TopologyRefiner& newRefiner, int numValues)
681  //
682  // For each channel, populate the face-vertex values:
683  // IndexArray setBaseFaceFVarValues(TopologyRefiner& newRefiner, Index face, int channel = 0)
684  //
685  return true;
686 }
687 
688 template <class MESH>
689 bool
691 
692  //
693  // Optional tagging:
694  // This is where any additional feature tags -- sharpness, holes, etc. -- can be
695  // specified using:
696  //
697  // void setBaseEdgeSharpness(TopologyRefiner& newRefiner, Index edge, float sharpness)
698  // void setBaseVertexSharpness(TopologyRefiner& newRefiner, Index vertex, float sharpness)
699  //
700  // void setBaseFaceHole(TopologyRefiner& newRefiner, Index face, bool hole)
701  //
702  return true;
703 }
704 
705 template <class MESH>
706 void
708  TopologyError /* errCode */, char const * /* msg */, MESH const& /* mesh */) {
709 
710  //
711  // Optional topology validation error reporting:
712  // This method is called whenever the factory encounters topology validation
713  // errors. By default, nothing is reported
714  //
715 }
716 
717 } // end namespace Far
718 
719 } // end namespace OPENSUBDIV_VERSION
720 using namespace OPENSUBDIV_VERSION;
721 } // end namespace OpenSubdiv
722 
723 #endif /* OPENSUBDIV3_FAR_TOPOLOGY_REFINER_FACTORY_H */
static int getNumBaseFaces(TopologyRefiner const &newRefiner)
static int getNumBaseEdges(TopologyRefiner const &newRefiner)
static void setBaseFaceHole(TopologyRefiner &newRefiner, Index f, bool isHole)
Tag a face as a hole.
static void setBaseEdgeNonManifold(TopologyRefiner &newRefiner, Index e, bool b)
Tag an edge as non-manifold.
static Index findBaseEdge(TopologyRefiner const &newRefiner, Index v0, Index v1)
Identify an edge to be assigned a sharpness value given a vertex pair.
static IndexArray getBaseFaceEdges(TopologyRefiner &newRefiner, Index f)
Assign the edges incident each face.
static void setBaseVertexSharpness(TopologyRefiner &newRefiner, Index v, float sharpness)
Assign a sharpness value to a given vertex.
static void setNumBaseVertices(TopologyRefiner &newRefiner, int count)
Specify the number of vertices to be accommodated.
static void setBaseEdgeSharpness(TopologyRefiner &newRefiner, Index e, float sharpness)
Assign a sharpness value to a given edge.
static bool populateBaseLevel(TopologyRefiner &refiner, MESH const &mesh, Options options)
static int getNumBaseVertices(TopologyRefiner const &newRefiner)
static LocalIndexArray getBaseEdgeFaceLocalIndices(TopologyRefiner &newRefiner, Index e)
Assign the local indices of an edge within each of its incident faces.
static IndexArray getBaseVertexEdges(TopologyRefiner &newRefiner, Index v)
Assign the edges incident each vertex.
static bool prepareComponentTopologyAssignment(TopologyRefiner &refiner, bool fullValidation, TopologyCallback callback, void const *callbackData)
Options(Sdc::SchemeType sdcType=Sdc::SCHEME_CATMARK, Sdc::Options sdcOptions=Sdc::Options())
static void setNumBaseVertexFaces(TopologyRefiner &newRefiner, Index v, int count)
Specify the number of faces incident each vertex.
static LocalIndexArray getBaseVertexFaceLocalIndices(TopologyRefiner &newRefiner, Index v)
Assign the local indices of a vertex within each of its incident faces.
static bool assignComponentTopology(TopologyRefiner &newRefiner, MESH const &mesh)
Specify the relationships between vertices, faces, etc. ie the face-vertices, vertex-faces,...
SchemeType
Enumerated type for all subdivision schemes supported by OpenSubdiv.
Definition: types.h:37
static void setNumBaseVertexEdges(TopologyRefiner &newRefiner, Index v, int count)
Specify the number of edges incident each vertex.
static void setBaseVertexNonManifold(TopologyRefiner &newRefiner, Index v, bool b)
Tag a vertex as non-manifold.
static bool prepareComponentTopologySizing(TopologyRefiner &refiner)
static bool assignComponentTags(TopologyRefiner &newRefiner, MESH const &mesh)
(Optional) Specify edge or vertex sharpness or face holes
static bool assignFaceVaryingTopology(TopologyRefiner &newRefiner, MESH const &mesh)
(Optional) Specify face-varying data per face
static TopologyRefiner * Create(MESH const &mesh, Options options=Options())
Instantiates a TopologyRefiner from client-provided topological representation.
static IndexArray getBaseFaceVertices(TopologyRefiner &newRefiner, Index f)
Assign the vertices incident each face.
Sdc::SchemeType schemeType
The subdivision scheme type identifier.
void Error(ErrorType err, const char *format,...)
Sends an OSD error with a message (internal use only)
static bool prepareComponentTagsAndSharpness(TopologyRefiner &refiner)
static void populateBaseLocalIndices(TopologyRefiner &newRefiner)
Determine all local indices by inspection (only for pure manifold meshes)
static bool resizeComponentTopology(TopologyRefiner &newRefiner, MESH const &mesh)
Specify the number of vertices, faces, face-vertices, etc.
Factory for constructing TopologyRefiners from specific mesh classes.
static IndexArray getBaseFaceFVarValues(TopologyRefiner &newRefiner, Index face, int channel=0)
Assign the face-varying values for the corners of each face.
static bool prepareFaceVaryingChannels(TopologyRefiner &refiner)
All supported options applying to subdivision scheme.
Definition: options.h:51
void SetFVarLinearInterpolation(FVarLinearInterpolation b)
Set face-varying interpolation rule.
Definition: options.h:98
Options related to the construction of each TopologyRefiner.
static void setNumBaseEdgeFaces(TopologyRefiner &newRefiner, Index e, int count)
Specify the number of faces incident each edge.
static void setNumBaseFaces(TopologyRefiner &newRefiner, int count)
Specify the number of faces to be accommodated.
Issue a generic runtime error, but continue execution.
Definition: error.h:40
static void reportInvalidTopology(TopologyError errCode, char const *msg, MESH const &mesh)
(Optional) Control run-time topology validation and error reporting
static IndexArray getBaseVertexFaces(TopologyRefiner &newRefiner, Index v)
Assign the faces incident each vertex.
Private base class of Factories for constructing TopologyRefiners.
Stores topology data for a specified set of refinement options.
static int createBaseFVarChannel(TopologyRefiner &newRefiner, int numValues)
Create a new face-varying channel with the given number of values.
FVarLinearInterpolation GetFVarLinearInterpolation() const
Get face-varying interpolation rule.
Definition: options.h:95
static LocalIndexArray getBaseVertexEdgeLocalIndices(TopologyRefiner &newRefiner, Index v)
Assign the local indices of a vertex within each of its incident edges.
static void setNumBaseFaceVertices(TopologyRefiner &newRefiner, Index f, int count)
Specify the number of vertices incident each face.
static IndexArray getBaseEdgeFaces(TopologyRefiner &newRefiner, Index e)
Assign the faces incident each edge.
static void setNumBaseEdges(TopologyRefiner &newRefiner, int count)
Specify the number of edges to be accommodated.
static IndexArray getBaseEdgeVertices(TopologyRefiner &newRefiner, Index e)
Assign the vertices incident each edge.