Regina 7.3 Calculation Engine
Public Member Functions | Static Public Member Functions | Protected Attributes | Friends | List of all members
regina::NormalSurface Class Reference

Represents a single normal surface in a 3-manifold triangulation. More...

#include <surface/normalsurface.h>

Inheritance diagram for regina::NormalSurface:
regina::ShortOutput< NormalSurface > regina::Output< NormalSurface, false >

Public Member Functions

 NormalSurface (const NormalSurface &)=default
 Creates a new copy of the given normal surface. More...
 
 NormalSurface (const NormalSurface &src, const Triangulation< 3 > &triangulation)
 Creates a new copy of the given normal surface, but relocated to the given triangulation. More...
 
 NormalSurface (const NormalSurface &src, const SnapshotRef< Triangulation< 3 > > &triangulation)
 Creates a new copy of the given normal surface, but relocated to the given triangulation. More...
 
 NormalSurface (NormalSurface &&) noexcept=default
 Moves the given surface into this new normal surface. More...
 
 NormalSurface (const Triangulation< 3 > &triang)
 Create the empty surface within the given triangulation. More...
 
 NormalSurface (const SnapshotRef< Triangulation< 3 > > &triang)
 Create the empty surface within the given triangulation. More...
 
 NormalSurface (const Triangulation< 3 > &triang, NormalEncoding enc, const Vector< LargeInteger > &vector)
 Creates a new normal surface inside the given triangulation with the given coordinate vector, using the given vector encoding. More...
 
 NormalSurface (const Triangulation< 3 > &triang, NormalEncoding enc, Vector< LargeInteger > &&vector)
 Creates a new normal surface inside the given triangulation with the given coordinate vector, using the given vector encoding. More...
 
 NormalSurface (const SnapshotRef< Triangulation< 3 > > &triang, NormalEncoding enc, const Vector< LargeInteger > &vector)
 Creates a new normal surface inside the given triangulation with the given coordinate vector, using the given vector encoding. More...
 
 NormalSurface (const SnapshotRef< Triangulation< 3 > > &triang, NormalEncoding enc, Vector< LargeInteger > &&vector)
 Creates a new normal surface inside the given triangulation with the given coordinate vector, using the given vector encoding. More...
 
 NormalSurface (const Triangulation< 3 > &triang, NormalCoords coords, const Vector< LargeInteger > &vector)
 Creates a new normal surface inside the given triangulation with the given coordinate vector, using the given coordinate system. More...
 
 NormalSurface (const Triangulation< 3 > &triang, NormalCoords coords, Vector< LargeInteger > &&vector)
 Creates a new normal surface inside the given triangulation with the given coordinate vector, using the given coordinate system. More...
 
 NormalSurface (const SnapshotRef< Triangulation< 3 > > &triang, NormalCoords coords, const Vector< LargeInteger > &vector)
 Creates a new normal surface inside the given triangulation with the given coordinate vector, using the given coordinate system. More...
 
 NormalSurface (const SnapshotRef< Triangulation< 3 > > &triang, NormalCoords coords, Vector< LargeInteger > &&vector)
 Creates a new normal surface inside the given triangulation with the given coordinate vector, using the given coordinate system. More...
 
NormalSurfaceoperator= (const NormalSurface &)=default
 Sets this to be a copy of the given normal surface. More...
 
NormalSurfaceoperator= (NormalSurface &&) noexcept=default
 Moves the contents of the given normal surface to this surface. More...
 
void swap (NormalSurface &other) noexcept
 Swaps the contents of this and the given normal surface. More...
 
NormalSurface doubleSurface () const
 Deprecated routine that returns the double of this surface. More...
 
NormalSurface operator+ (const NormalSurface &rhs) const
 Returns the sum of this and the given surface. More...
 
NormalSurface operator* (const LargeInteger &coeff) const
 Returns the given integer multiple of this surface. More...
 
NormalSurfaceoperator*= (const LargeInteger &coeff)
 Converts this surface into the given integer multiple of itself. More...
 
LargeInteger scaleDown ()
 Converts this surface into its smallest positive rational multiple with integer coordinates. More...
 
LargeInteger triangles (size_t tetIndex, int vertex) const
 Returns the number of triangular discs of the given type in this normal surface. More...
 
LargeInteger quads (size_t tetIndex, int quadType) const
 Returns the number of quadrilateral discs of the given type in this normal surface. More...
 
LargeInteger octs (size_t tetIndex, int octType) const
 Returns the number of octagonal discs of the given type in this normal surface. More...
 
LargeInteger edgeWeight (size_t edgeIndex) const
 Returns the number of times this normal surface crosses the given edge. More...
 
LargeInteger arcs (size_t triIndex, int triVertex) const
 Returns the number of arcs in which this normal surface intersects the given triangle in the given direction. More...
 
DiscType octPosition () const
 Determines the first coordinate position at which this surface has a non-zero octagonal coordinate. More...
 
const Triangulation< 3 > & triangulation () const
 Returns the triangulation in which this normal surface resides. More...
 
const std::string & name () const
 Returns the name associated with this normal surface. More...
 
void setName (const std::string &name)
 Sets the name associated with this normal surface. More...
 
void writeTextShort (std::ostream &out) const
 Writes this surface to the given output stream, using standard triangle-quad-oct coordinates. More...
 
void writeXMLData (std::ostream &out, FileFormat format, const NormalSurfaces *list) const
 Writes a chunk of XML containing this normal surface and all of its properties. More...
 
bool isEmpty () const
 Determines if this normal surface is empty (has no discs whatsoever). More...
 
bool hasMultipleOctDiscs () const
 Determines if this normal surface has more than one octagonal disc. More...
 
bool isCompact () const
 Determines if this normal surface is compact (has finitely many discs). More...
 
LargeInteger eulerChar () const
 Returns the Euler characteristic of this surface. More...
 
bool isOrientable () const
 Returns whether or not this surface is orientable. More...
 
bool isTwoSided () const
 Returns whether or not this surface is two-sided. More...
 
bool isConnected () const
 Returns whether or not this surface is connected. More...
 
bool hasRealBoundary () const
 Determines if this surface has any real boundary, that is, whether it meets any boundary triangles of the triangulation. More...
 
std::vector< NormalSurfacecomponents () const
 Splits this surface into connected components. More...
 
bool isVertexLinking () const
 Determines whether or not this surface is vertex linking. More...
 
const Vertex< 3 > * isVertexLink () const
 Determines whether or not a positive rational multiple of this surface is the link of a single vertex. More...
 
std::pair< const Edge< 3 > *, const Edge< 3 > * > isThinEdgeLink () const
 Determines whether or not a positive rational multiple of this surface is the thin link of a single edge. More...
 
std::pair< std::vector< const Edge< 3 > * >, unsigned > isNormalEdgeLink () const
 Determines whether or not a positive rational multiple of this surface is the normalised link of a single edge. More...
 
std::pair< const Triangle< 3 > *, const Triangle< 3 > * > isThinTriangleLink () const
 Determines whether or not a positive rational multiple of this surface is the thin link of a single triangle. More...
 
std::pair< std::vector< const Triangle< 3 > * >, unsigned > isNormalTriangleLink () const
 Determines whether or not a positive rational multiple of this surface is the normalised link of a single triangle. More...
 
bool isSplitting () const
 Determines whether or not this surface is a splitting surface. More...
 
size_t isCentral () const
 Determines whether or not this surface is a central surface. More...
 
size_t countBoundaries () const
 Returns the number of disjoint boundary curves on this surface. More...
 
bool isCompressingDisc (bool knownConnected=false) const
 Determines whether this surface represents a compressing disc in the underlying 3-manifold. More...
 
bool isIncompressible () const
 Determines whether this is an incompressible surface within the surrounding 3-manifold. More...
 
Triangulation< 3 > cutAlong () const
 Cuts the underlying triangulation along this surface and returns the result as a new triangulation. More...
 
Triangulation< 3 > crush () const
 Crushes this surface to a point in the underlying triangulation and returns the result as a new triangulation. More...
 
NormalSurface removeOcts () const
 Returns an isotopic normal surface that contains no octagons, placed within a homeomorphic (but possibly different) triangulation. More...
 
bool operator== (const NormalSurface &other) const
 Determines whether this and the given surface in fact represent the same normal (or almost normal) surface. More...
 
bool operator!= (const NormalSurface &other) const
 Determines whether this and the given surface represent different normal (or almost normal) surfaces. More...
 
bool operator< (const NormalSurface &other) const
 Imposes a total order on all normal and almost normal surfaces. More...
 
bool normal () const
 Determines whether this surface contains only triangle and/or quadrilateral discs. More...
 
bool embedded () const
 Determines whether this surface is embedded. More...
 
bool locallyCompatible (const NormalSurface &other) const
 Determines whether this and the given surface are locally compatible. More...
 
bool disjoint (const NormalSurface &other) const
 Determines whether this and the given surface can be placed within the surrounding triangulation so that they do not intersect anywhere at all, without changing either normal isotopy class. More...
 
MatrixInt boundaryIntersections () const
 Computes the information about the boundary slopes of this surface at each cusp of the triangulation. More...
 
const Vector< LargeInteger > & vector () const
 Gives read-only access to the integer vector that Regina uses internally to represent this surface. More...
 
NormalEncoding encoding () const
 Returns the specific integer vector encoding that this surface uses internally. More...
 
bool couldBeAlmostNormal () const
 Indicates whether the internal vector encoding for this surface supports almost normal surfaces. More...
 
bool couldBeNonCompact () const
 Indicates whether the internal vector encoding for this surface supports non-compact surfaces. More...
 
void writeTextLong (std::ostream &out) const
 A default implementation for detailed output. More...
 
std::string str () const
 Returns a short text representation of this object. More...
 
std::string utf8 () const
 Returns a short text representation of this object using unicode characters. More...
 
std::string detail () const
 Returns a detailed text representation of this object. More...
 

Static Public Member Functions

static NormalEncoding reconstructTriangles (const Triangulation< 3 > &tri, Vector< LargeInteger > &vector, NormalEncoding enc)
 Reconstructs the triangle coordinates in the given integer vector. More...
 

Protected Attributes

NormalEncoding enc_
 The specific encoding of a normal surface used by the coordinate vector. More...
 
Vector< LargeIntegervector_
 Contains the coordinates of the normal surface. More...
 
SnapshotRef< Triangulation< 3 > > triangulation_
 The triangulation in which this normal surface resides. More...
 
std::string name_
 An optional name associated with this surface. More...
 
std::optional< DiscTypeoctPosition_
 The position of the first non-zero octagonal coordinate, or a null disc type if there is no non-zero octagonal coordinate. More...
 
std::optional< LargeIntegereulerChar_
 The Euler characteristic of this surface. More...
 
std::optional< size_t > boundaries_
 The number of disjoint boundary curves on this surface. More...
 
std::optional< bool > orientable_
 Is this surface orientable? This is std::nullopt if it has not yet been computed. More...
 
std::optional< bool > twoSided_
 Is this surface two-sided? This is std::nullopt if it has not yet been computed. More...
 
std::optional< bool > connected_
 Is this surface connected? This is std::nullopt if it has not yet been computed. More...
 
std::optional< bool > realBoundary_
 Does this surface have real boundary (i.e. More...
 
std::optional< bool > compact_
 Is this surface compact (i.e. More...
 
uint8_t linkOf_ { 0 }
 Indicates which dimensions of face a positive rational multiple of this surface is a thin or normalised link of. More...
 

Friends

class XMLNormalSurfaceReader
 

Detailed Description

Represents a single normal surface in a 3-manifold triangulation.

The normal surface is described internally by an integer vector (discussed in more detail below). Since different surfaces may use different vector encodings, you should not rely on the raw vector entries unless absolutely necessary. Instead, the query routines such as triangles(), quads(), edgeWeight() and so on are independent of the underlying vector encoding being used.

Note that non-compact surfaces (surfaces with infinitely many discs, such as spun-normal surfaces) are allowed; in these cases, the corresponding lookup routines (such as triangles()) will return LargeInteger::infinity where appropriate.

Since Regina 7.0, you can modify or even destroy the original triangulation that was used to create this normal surface. If you do, then this normal surface will automatically make a private copy of the original triangulation as an ongoing reference. Different normal surfaces (and angle structures) can all share the same private copy, so this is not an expensive process.

Internally, a normal surface is represented by a Vector<LargeInteger> (possibly using a different coordinate system from the one in which the surfaces were originally enumerated). This contains a block of coordinates for each tetrahedron, in order from the first tetrahedron to the last. Each block begins with four triangle coordinates (always), then three quadrilateral coordinates (always), and finally three octagon coordinates (only for some coordinate systems). Therefore the vector that is stored will always have length 7n or 10n where n is the number of tetrahedra in the underlying triangulation.

When adding support for a new coordinate system:

This class implements C++ move semantics and adheres to the C++ Swappable requirement. It is designed to avoid deep copies wherever possible, even when passing or returning objects by value.

Todo:

Feature: Calculation of Euler characteristic and orientability for non-compact surfaces.

Feature (long-term): Determine which faces in the solution space a normal surface belongs to.

Constructor & Destructor Documentation

◆ NormalSurface() [1/14]

regina::NormalSurface::NormalSurface ( const NormalSurface )
default

Creates a new copy of the given normal surface.

◆ NormalSurface() [2/14]

regina::NormalSurface::NormalSurface ( const NormalSurface src,
const Triangulation< 3 > &  triangulation 
)
inline

Creates a new copy of the given normal surface, but relocated to the given triangulation.

A snapshot will be taken of the given triangulation as it appears right now. You may change or even delete the triangulation later on; if so, then this normal surface will still refer to the frozen snapshot that was taken at the time of construction.

Precondition
The given triangulation is either the same as, or is combinatorially identical to, the triangulation in which src resides.
Parameters
srcthe normal surface to copy.
triangulationthe triangulation in which this new surface will reside.

◆ NormalSurface() [3/14]

regina::NormalSurface::NormalSurface ( const NormalSurface src,
const SnapshotRef< Triangulation< 3 > > &  triangulation 
)
inline

Creates a new copy of the given normal surface, but relocated to the given triangulation.

Precondition
The given triangulation is either the same as, or is combinatorially identical to, the triangulation in which src resides.
Python
Not present. Instead use the version that takes a "pure" triangulation.
Parameters
srcthe normal surface to copy.
triangulationa snapshot, frozen in time, of the triangulation in which this new surface will reside.

◆ NormalSurface() [4/14]

regina::NormalSurface::NormalSurface ( NormalSurface &&  )
defaultnoexcept

Moves the given surface into this new normal surface.

This is a fast (constant time) operation.

The surface that is passed will no longer be usable.

◆ NormalSurface() [5/14]

regina::NormalSurface::NormalSurface ( const Triangulation< 3 > &  triang)

Create the empty surface within the given triangulation.

All normal coordinates will be zero.

Parameters
triangthe triangulation in which this normal surface resides.

◆ NormalSurface() [6/14]

regina::NormalSurface::NormalSurface ( const SnapshotRef< Triangulation< 3 > > &  triang)

Create the empty surface within the given triangulation.

All normal coordinates will be zero.

Python
Not present. Instead use the version that takes a "pure" triangulation.
Parameters
trianga snapshot, frozen in time, of the triangulation in which this normal surface resides.

◆ NormalSurface() [7/14]

regina::NormalSurface::NormalSurface ( const Triangulation< 3 > &  triang,
NormalEncoding  enc,
const Vector< LargeInteger > &  vector 
)
inline

Creates a new normal surface inside the given triangulation with the given coordinate vector, using the given vector encoding.

There is no guarantee that this surface will keep the given encoding: NormalSurface will sometimes convert the vector to use a different encoding for its own internal storage.

Despite what is said in the class notes, it is okay if the given vector encoding does not include triangle coordinates. (If this is the case, the vector will be converted automatically.)

A snapshot will be taken of the given triangulation as it appears right now. You may change or even delete the triangulation later on; if so, then this normal surface will still refer to the frozen snapshot that was taken at the time of construction.

Precondition
The given coordinate vector does indeed represent a normal surface inside the given triangulation, using the given encoding. This will not be checked!
Python
Instead of a Vector<LargeInteger>, you may (if you prefer) pass a Python list of integers.
Parameters
triangthe triangulation in which this normal surface resides.
encindicates precisely how the given vector encodes a normal surface.
vectora vector containing the coordinates of the normal surface.

◆ NormalSurface() [8/14]

regina::NormalSurface::NormalSurface ( const Triangulation< 3 > &  triang,
NormalEncoding  enc,
Vector< LargeInteger > &&  vector 
)
inline

Creates a new normal surface inside the given triangulation with the given coordinate vector, using the given vector encoding.

There is no guarantee that this surface will keep the given encoding: NormalSurface will sometimes convert the vector to use a different encoding for its own internal storage.

Despite what is said in the class notes, it is okay if the given vector encoding does not include triangle coordinates. (If this is the case, the vector will be converted automatically.)

A snapshot will be taken of the given triangulation as it appears right now. You may change or even delete the triangulation later on; if so, then this normal surface will still refer to the frozen snapshot that was taken at the time of construction.

Precondition
The given coordinate vector does indeed represent a normal surface inside the given triangulation, using the given encoding. This will not be checked!
Python
Not present. Instead use the version that copies vector.
Parameters
triangthe triangulation in which this normal surface resides.
encindicates precisely how the given vector encodes a normal surface.
vectora vector containing the coordinates of the normal surface.

◆ NormalSurface() [9/14]

regina::NormalSurface::NormalSurface ( const SnapshotRef< Triangulation< 3 > > &  triang,
NormalEncoding  enc,
const Vector< LargeInteger > &  vector 
)
inline

Creates a new normal surface inside the given triangulation with the given coordinate vector, using the given vector encoding.

There is no guarantee that this surface will keep the given encoding: NormalSurface will sometimes convert the vector to use a different encoding for its own internal storage.

Despite what is said in the class notes, it is okay if the given vector encoding does not include triangle coordinates. (If this is the case, the vector will be converted automatically.)

Precondition
The given coordinate vector does indeed represent a normal surface inside the given triangulation, using the given encoding. This will not be checked!
Python
Not present. Instead use the version that takes a "pure" triangulation.
Parameters
trianga snapshot, frozen in time, of the triangulation in which this normal surface resides.
encindicates precisely how the given vector encodes a normal surface.
vectora vector containing the coordinates of the normal surface.

◆ NormalSurface() [10/14]

regina::NormalSurface::NormalSurface ( const SnapshotRef< Triangulation< 3 > > &  triang,
NormalEncoding  enc,
Vector< LargeInteger > &&  vector 
)
inline

Creates a new normal surface inside the given triangulation with the given coordinate vector, using the given vector encoding.

There is no guarantee that this surface will keep the given encoding: NormalSurface will sometimes convert the vector to use a different encoding for its own internal storage.

Despite what is said in the class notes, it is okay if the given vector encoding does not include triangle coordinates. (If this is the case, the vector will be converted automatically.)

Precondition
The given coordinate vector does indeed represent a normal surface inside the given triangulation, using the given encoding. This will not be checked!
Python
Not present. Instead use the version that takes a "pure" triangulation and copies vector.
Parameters
trianga snapshot, frozen in time, of the triangulation in which this normal surface resides.
encindicates precisely how the given vector encodes a normal surface.
vectora vector containing the coordinates of the normal surface.

◆ NormalSurface() [11/14]

regina::NormalSurface::NormalSurface ( const Triangulation< 3 > &  triang,
NormalCoords  coords,
const Vector< LargeInteger > &  vector 
)
inline

Creates a new normal surface inside the given triangulation with the given coordinate vector, using the given coordinate system.

It is assumed that this surface uses the vector encoding described by NormalEncoding(coords). Be careful with this if you are extracting the vector from some other normal surface, since Regina may internally convert to use a different encoding from whatever was used during enumeration and/or read from file. In the same spirit, there is no guarantee that this surface will use NormalEncoding(coords) as its internal encoding method.

Despite what is said in the class notes, it is okay if the given coordinate system does not include triangle coordinates. (If this is the case, the vector will be converted automatically.)

A snapshot will be taken of the given triangulation as it appears right now. You may change or even delete the triangulation later on; if so, then this normal surface will still refer to the frozen snapshot that was taken at the time of construction.

Precondition
The given coordinate vector does indeed represent a normal surface inside the given triangulation, using the encoding NormalEncoding(coords). This will not be checked!
Python
Instead of a Vector<LargeInteger>, you may (if you prefer) pass a Python list of integers.
Parameters
triangthe triangulation in which this normal surface resides.
coordsthe coordinate system from which the vector encoding will be deduced.
vectora vector containing the coordinates of the normal surface.

◆ NormalSurface() [12/14]

regina::NormalSurface::NormalSurface ( const Triangulation< 3 > &  triang,
NormalCoords  coords,
Vector< LargeInteger > &&  vector 
)
inline

Creates a new normal surface inside the given triangulation with the given coordinate vector, using the given coordinate system.

It is assumed that this surface uses the vector encoding described by NormalEncoding(coords). Be careful with this if you are extracting the vector from some other normal surface, since Regina may internally convert to use a different encoding from whatever was used during enumeration and/or read from file. In the same spirit, there is no guarantee that this surface will use NormalEncoding(coords) as its internal encoding method.

Despite what is said in the class notes, it is okay if the given coordinate system does not include triangle coordinates. (If this is the case, the vector will be converted automatically.)

A snapshot will be taken of the given triangulation as it appears right now. You may change or even delete the triangulation later on; if so, then this normal surface will still refer to the frozen snapshot that was taken at the time of construction.

Precondition
The given coordinate vector does indeed represent a normal surface inside the given triangulation, using the encoding NormalEncoding(coords). This will not be checked!
Python
Not present. Instead use the version that copies vector.
Parameters
triangthe triangulation in which this normal surface resides.
coordsthe coordinate system from which the vector encoding will be deduced.
vectora vector containing the coordinates of the normal surface.

◆ NormalSurface() [13/14]

regina::NormalSurface::NormalSurface ( const SnapshotRef< Triangulation< 3 > > &  triang,
NormalCoords  coords,
const Vector< LargeInteger > &  vector 
)
inline

Creates a new normal surface inside the given triangulation with the given coordinate vector, using the given coordinate system.

It is assumed that this surface uses the vector encoding described by NormalEncoding(coords). Be careful with this if you are extracting the vector from some other normal surface, since Regina may internally convert to use a different encoding from whatever was used during enumeration and/or read from file. In the same spirit, there is no guarantee that this surface will use NormalEncoding(coords) as its internal encoding method.

Despite what is said in the class notes, it is okay if the given coordinate system does not include triangle coordinates. (If this is the case, the vector will be converted automatically.)

Precondition
The given coordinate vector does indeed represent a normal surface inside the given triangulation, using the encoding NormalEncoding(coords). This will not be checked!
Python
Not present. Instead use the version that takes a "pure" triangulation.
Parameters
trianga snapshot, frozen in time, of the triangulation in which this normal surface resides.
coordsthe coordinate system from which the vector encoding will be deduced.
vectora vector containing the coordinates of the normal surface.

◆ NormalSurface() [14/14]

regina::NormalSurface::NormalSurface ( const SnapshotRef< Triangulation< 3 > > &  triang,
NormalCoords  coords,
Vector< LargeInteger > &&  vector 
)
inline

Creates a new normal surface inside the given triangulation with the given coordinate vector, using the given coordinate system.

It is assumed that this surface uses the vector encoding described by NormalEncoding(coords). Be careful with this if you are extracting the vector from some other normal surface, since Regina may internally convert to use a different encoding from whatever was used during enumeration and/or read from file. In the same spirit, there is no guarantee that this surface will use NormalEncoding(coords) as its internal encoding method.

Despite what is said in the class notes, it is okay if the given coordinate system does not include triangle coordinates. (If this is the case, the vector will be converted automatically.)

Precondition
The given coordinate vector does indeed represent a normal surface inside the given triangulation, using the encoding NormalEncoding(coords). This will not be checked!
Python
Not present. Instead use the version that takes a "pure" triangulation and copies vector.
Parameters
trianga snapshot, frozen in time, of the triangulation in which this normal surface resides.
coordsthe coordinate system from which the vector encoding will be deduced.
vectora vector containing the coordinates of the normal surface.

Member Function Documentation

◆ arcs()

LargeInteger regina::NormalSurface::arcs ( size_t  triIndex,
int  triVertex 
) const

Returns the number of arcs in which this normal surface intersects the given triangle in the given direction.

Parameters
triIndexthe index in the triangulation of the triangle in which we are interested; this should be between 0 and Triangulation<3>::countTriangles()-1 inclusive.
triVertexthe vertex of the triangle (0, 1 or 2) around which the arcs of intersection that we are interested in lie; only these arcs will be counted.
Returns
the number of times this normal surface intersect the given triangle with the given arc type.

◆ boundaryIntersections()

MatrixInt regina::NormalSurface::boundaryIntersections ( ) const

Computes the information about the boundary slopes of this surface at each cusp of the triangulation.

This is for use with spun-normal surfaces (since for closed surfaces all boundary slopes are zero).

This routine is only available for use with SnapPea triangulations, since it needs to know the specific meridian and longitude on each cusp. These meridians and longitudes are only available through the SnapPea kernel, since Regina does not use or store peripheral curves for its own Triangulation<3> class. Therefore:

  • If the underlying triangulation (as returned by triangulation()) is not of the subclass SnapPeaTriangulation, this routine will throw an exception (see below).
  • In particular, this will happen if you have edited or deleted the original triangulation that was used to construct this normal surface. This is because such a modification will trigger an internal deep copy of the original, and this will only copy Regina's native Triangulation<3> data.

All cusps are treated as complete. That is, any Dehn fillings stored in the SnapPea triangulation will be ignored.

The results are returned in a matrix with V rows and two columns, where V is the number of vertices in the triangulation. If row i of the matrix contains the integers M and L, this indicates that at the ith cusp, the boundary curves have algebraic intersection number M with the meridian and L with the longitude. Equivalently, the boundary curves pass L times around the meridian and -M times around the longitude. The rational boundary slope is therefore -L/M, and there are gcd(L,M) boundary curves with this slope.

The orientations of the boundary curves of a spun-normal surface are chosen so that if meridian and longitude are a positive basis as vieved from the cusp, then as one travels along an oriented boundary curve, the spun-normal surface spirals into the cusp to one's right and down into the manifold to one's left.

If the triangulation contains more than one vertex, the rows in the resulting matrix are ordered by cusp index (as stored by SnapPea). You can call SnapPeaTriangulation::cuspVertex() to map these to Regina's vertex indices if needed.

Precondition
As noted above, the underlying triangulation must be a SnapPeaTriangulation; this will be checked, and this routine will throw an exception if this requirement is not met.
At present, Regina can only compute boundary slopes if the triangulation is oriented, if every vertex link in the triangulation is a torus, and if the underlying coordinate system is for normal surfaces only (not almost normal surfaces). These conditions will likewise be checked, and this routine will throw an exception if they are not met.
Exceptions
SnapPeaIsNullThis is a null SnapPea triangulation.
FailedPreconditionOne or more of the preconditions listed above was not met.
Author
William Pettersson and Stephan Tillmann
Returns
a matrix with number_of_vertices rows and two columns as described above.

◆ components()

std::vector< NormalSurface > regina::NormalSurface::components ( ) const

Splits this surface into connected components.

A list of connected components will be returned. These components will always be encoded using standard (tri-quad or tri-quad-oct) coordinates, regardless of the internal vector encoding that is used by this surface.

Precondition
This normal surface is embedded (not singular or immersed).
This normal surface is compact (has finitely many discs).
Warning
This routine explicitly builds the normal discs, and so may run out of memory if the normal coordinates are extremely large.
Returns
the list of connected components.

◆ couldBeAlmostNormal()

bool regina::NormalSurface::couldBeAlmostNormal ( ) const
inline

Indicates whether the internal vector encoding for this surface supports almost normal surfaces.

If this routine returns true, it does not mean that the surface actually contains one or more octagons; you should use normal() to test for that. This routine simply queries a basic property of the vector encoding that is being used, and this property is often inherited from whatever coordinate system was used to perform the normal surface enumeration.

On the other hand, if this routine returns false, it is a guarantee that this surface is normal.

Returns
true if the internal encoding supports almost normal surfaces.

◆ couldBeNonCompact()

bool regina::NormalSurface::couldBeNonCompact ( ) const
inline

Indicates whether the internal vector encoding for this surface supports non-compact surfaces.

Non-compact surfaces are surfaces that contain infinitely many discs (i.e., spun-normal surfaces).

If this routine returns true, it does not mean that the surface actually is non-compact; you should use isCompact() to test for that. This routine simply queries a basic property of the vector encoding that is being used, and this property is often inherited from whatever coordinate system was used to perform the normal surface enumeration.

On the other hand, if this routine returns false, it is a guarantee that this surface is compact.

Returns
true if the internal encoding supports almost normal surfaces.

◆ countBoundaries()

size_t regina::NormalSurface::countBoundaries ( ) const
inline

Returns the number of disjoint boundary curves on this surface.

This routine caches its results, which means that once it has been called for a particular surface, subsequent calls return the answer immediately.

Precondition
This normal surface is embedded (not singular or immersed).
This normal surface is compact (has finitely many discs).
Warning
This routine explicitly builds the normal arcs on the boundary. If the normal coordinates are extremely large, (in particular, of a similar order of magnitude as the largest possible long integer), then the behaviour of this routine is undefined.
Author
Alex He
Returns
the number of disjoint boundary curves.

◆ crush()

Triangulation< 3 > regina::NormalSurface::crush ( ) const

Crushes this surface to a point in the underlying triangulation and returns the result as a new triangulation.

The original triangulation is not changed.

Crushing the surface will produce a number of tetrahedra, triangular pillows and/or footballs. The pillows and footballs will then be flattened to triangles and edges respectively (resulting in the possible changes mentioned below) to produce a proper triangulation.

Note that the new triangulation will have at most the same number of tetrahedra as the old triangulation, and will have strictly fewer tetrahedra if this surface is not vertex linking.

The act of flattening pillows and footballs as described above can lead to unintended topological side-effects, beyond the effects of merely cutting along this surface and identifying the new boundary surface(s) to points. Examples of these unintended side-effects can include connected sum decompositions, removal of 3-spheres and small Lens spaces and so on; a full list of possible changes is beyond the scope of this API documentation.

Warning
This routine can have unintended topological side-effects, as described above.
In exceptional cases with non-orientable 3-manifolds, these side-effects might lead to invalid edges (edges whose midpoints are projective plane cusps).
Precondition
This normal surface is compact and embedded.
This normal surface contains no octagonal discs.
Returns
the resulting crushed triangulation.

◆ cutAlong()

Triangulation< 3 > regina::NormalSurface::cutAlong ( ) const

Cuts the underlying triangulation along this surface and returns the result as a new triangulation.

The original triangulation is not changed.

Note that, unlike crushing a surface to a point, this operation will not change the topology of the underlying 3-manifold beyond simply slicing along this surface.

As of Regina 7.1, this routine can happily cut along almost normal surfaces as well as normal surfaces. That is, it can now handle octagons, including cases with multiple octagons in the same tetrahedron and/or octagons in multiple tetrahedra.

Warning
The number of tetrahedra in the new triangulation can be very large.
Precondition
This normal surface is compact and embedded.
Returns
the resulting cut-open triangulation.

◆ detail()

std::string regina::Output< NormalSurface , supportsUtf8 >::detail ( ) const
inherited

Returns a detailed text representation of this object.

This text may span many lines, and should provide the user with all the information they could want. It should be human-readable, should not contain extremely long lines (which cause problems for users reading the output in a terminal), and should end with a final newline. There are no restrictions on the underlying character set.

Returns
a detailed text representation of this object.

◆ disjoint()

bool regina::NormalSurface::disjoint ( const NormalSurface other) const

Determines whether this and the given surface can be placed within the surrounding triangulation so that they do not intersect anywhere at all, without changing either normal isotopy class.

This is a global constraint, and therefore gives a stronger test than locallyCompatible(). However, this global constraint is also much slower to test; the running time is proportional to the total number of normal discs in both surfaces.

Precondition
Both this and the given normal surface live within the same 3-manifold triangulation.
Both this and the given surface are compact (have finitely many discs), embedded, non-empty and connected.
Warning
This routine is slow, since it performs a depth-first search over the entire set of normal discs.
Parameters
otherthe other surface to test alongside this surface for potential intersections.
Returns
true if both surfaces can be embedded without intersecting anywhere, or false if this and the given surface are forced to intersect at some point.

◆ doubleSurface()

NormalSurface regina::NormalSurface::doubleSurface ( ) const
inline

Deprecated routine that returns the double of this surface.

Deprecated:
Normal surfaces can now be multiplied by integer constants. In particular, this routine has exactly the same effect as multiplying the surface by 2.
Returns
the double of this normal surface.

◆ edgeWeight()

LargeInteger regina::NormalSurface::edgeWeight ( size_t  edgeIndex) const

Returns the number of times this normal surface crosses the given edge.

Parameters
edgeIndexthe index in the triangulation of the edge in which we are interested; this should be between 0 and Triangulation<3>::countEdges()-1 inclusive.
Returns
the number of times this normal surface crosses the given edge.

◆ embedded()

bool regina::NormalSurface::embedded ( ) const

Determines whether this surface is embedded.

This is true if and only if the surface contains no conflicting quadrilateral and/or octagon types.

Returns
true if and only if this surface is embedded.

◆ encoding()

NormalEncoding regina::NormalSurface::encoding ( ) const
inline

Returns the specific integer vector encoding that this surface uses internally.

This is the encoding that should be used to interpret vector().

Note that this might differ from the encoding originally passed to the class constructor.

Returns
the internal vector encoding.

◆ eulerChar()

LargeInteger regina::NormalSurface::eulerChar ( ) const
inline

Returns the Euler characteristic of this surface.

This routine caches its results, which means that once it has been called for a particular surface, subsequent calls return the answer immediately.

Precondition
This normal surface is compact (has finitely many discs).
Returns
the Euler characteristic.

◆ hasMultipleOctDiscs()

bool regina::NormalSurface::hasMultipleOctDiscs ( ) const

Determines if this normal surface has more than one octagonal disc.

It may be assumed that at most one octagonal disc type exists in this surface. This routine will return true if an octagonal type does exist and its coordinate is greater than one.

Precondition
At most one octagonal disc type exists in this surface.
Returns
true if and only if there is an octagonal disc type present and its coordinate is greater than one.

◆ hasRealBoundary()

bool regina::NormalSurface::hasRealBoundary ( ) const
inline

Determines if this surface has any real boundary, that is, whether it meets any boundary triangles of the triangulation.

This routine caches its results, which means that once it has been called for a particular surface, subsequent calls return the answer immediately.

Returns
true if and only if this surface has real boundary.

◆ isCentral()

size_t regina::NormalSurface::isCentral ( ) const

Determines whether or not this surface is a central surface.

A central surface is a compact surface containing at most one normal or almost normal disc per tetrahedron. If this surface is central, the number of tetrahedra that it meets (i.e., the number of discs in the surface) will be returned.

Note that the results of this routine are not cached. Thus the results will be reevaluated every time this routine is called.

Returns
the number of tetrahedra that this surface meets if it is a central surface, or 0 if it is not a central surface.

◆ isCompact()

bool regina::NormalSurface::isCompact ( ) const

Determines if this normal surface is compact (has finitely many discs).

This routine caches its results, which means that once it has been called for a particular surface, subsequent calls return the answer immediately.

Returns
true if and only if this normal surface is compact.

◆ isCompressingDisc()

bool regina::NormalSurface::isCompressingDisc ( bool  knownConnected = false) const

Determines whether this surface represents a compressing disc in the underlying 3-manifold.

Let this surface be D and let the underlying 3-manifold be M with boundary B. To be a compressing disc, D must be a properly embedded disc in M, and the boundary of D must not bound a disc in B.

The implementation of this routine is somewhat inefficient at present, since it cuts along the disc, retriangulates and then examines the resulting boundary components.

Precondition
This normal surface is compact and embedded.
This normal surface contains no octagonal discs.
Todo:

Optimise: Reimplement this to avoid cutting along surfaces.

Bug: Check for absurdly large numbers of discs and bail accordingly.

Warning
This routine might cut along the surface and retriangulate, and so may run out of memory if the normal coordinates are extremely large.
Parameters
knownConnectedtrue if this normal surface is already known to be connected (for instance, if it came from an enumeration of vertex normal surfaces), or false if we should not assume any such information about this surface.
Returns
true if this surface is a compressing disc, or false if this surface is not a compressing disc.

◆ isConnected()

bool regina::NormalSurface::isConnected ( ) const
inline

Returns whether or not this surface is connected.

For our purposes, the empty surface is considered to be connected.

This routine caches its results, which means that once it has been called for a particular surface, subsequent calls return the answer immediately.

Precondition
This normal surface is embedded (not singular or immersed).
This normal surface is compact (has finitely many discs).
Warning
This routine explicitly builds the normal discs, and so may run out of memory if the normal coordinates are extremely large.
Returns
true if this surface is connected, or false if this surface is disconnected.

◆ isEmpty()

bool regina::NormalSurface::isEmpty ( ) const
inline

Determines if this normal surface is empty (has no discs whatsoever).

◆ isIncompressible()

bool regina::NormalSurface::isIncompressible ( ) const

Determines whether this is an incompressible surface within the surrounding 3-manifold.

At present, this routine is only implemented for surfaces embedded within closed and irreducible 3-manifold triangulations.

Let D be some disc embedded in the underlying 3-manifold, and let B be the boundary of D. We call D a compressing disc for this surface if (i) the intersection of D with this surface is the boundary B, and (ii) although B bounds a disc within the 3-manifold, it does not bound a disc within this surface.

We declare this surface to be incompressible if there are no such compressing discs. For our purposes, spheres are never considered incompressible (so if this surface is a sphere then this routine will always return false).

This test is designed exclusively for two-sided surfaces. If this surface is one-sided, the incompressibility test will be run on its two-sided double cover.

Warning
This routine may in some circumstances be extremely slow. This is because the underlying algorithm cuts along this surface, retriangulates (possibly using a very large number of tetrahedra), and then searches for a normal compressing disc in each component of the cut-open triangulation.
Precondition
The underlying triangulation is valid and closed, and represents an irreducible 3-manifold.
This normal surface is compact, embedded and connected, and contains no octagonal discs.
Returns
true if this surface is incompressible, or false if this surface is not incompressible (or if it is a sphere).

◆ isNormalEdgeLink()

std::pair< std::vector< const Edge< 3 > * >, unsigned > regina::NormalSurface::isNormalEdgeLink ( ) const

Determines whether or not a positive rational multiple of this surface is the normalised link of a single edge.

Here the phrase normalised link of an edge e means the frontier of a regular neighbourhood of e, converted into a normal surface by expanding away from the edge using the normalisation process. It could be that there is no normalisation required at all (in which case it is also a thin edge link). However, it could be that the normalisation process expands the surface far away from the edge itself, or changes its topology, or disconnects the surface, or even normalises it away to an empty surface.

In particular, this test behaves differently from isThinEdgeLink(), which tests for thin edge links only (where no additional normalisation is required). If you are only interested in thin edge links, then you should call isThinEdgeLink(), which has much less overhead.

A surface (or its positive rational multiple) could be the normalised link of many edges. The return value will be a pair (v, thin), where:

  • v is a vector containing all such edges. This will begin with the edges for which this surface is a thin link, followed by the edges where normalisation was required; within each category the edges will be ordered by their index within the triangulation.
  • thin is either 0, 1 or 2, indicating how many edges this surface is a thin link for. This uses an unsigned type, since it will often be compared to v.size().

If no positive rational multiple of this surface is the normalised link of any edge, then link will be 0 and v will be the empty vector.

Note that the results of this routine are not cached. Thus the results will be reevaluated every time this routine is called.

Returns
a vector containing the edge(s) linked by a positive rational multiple of this surface and an integer indicating how many of these links are thin, as described above.

◆ isNormalTriangleLink()

std::pair< std::vector< const Triangle< 3 > * >, unsigned > regina::NormalSurface::isNormalTriangleLink ( ) const

Determines whether or not a positive rational multiple of this surface is the normalised link of a single triangle.

Here the phrase normalised link of a triangle t means the frontier of a regular neighbourhood of t, converted into a normal surface by expanding away from the triangle using the normalisation process. It could be that there is no normalisation required at all (in which case it is also a thin triangle link). However, it could be that the normalisation process expands the surface far away from the triangle itself, or changes its topology, or disconnects the surface, or even normalises it away to an empty surface.

In particular, this test behaves differently from isThinTriangleLink(), which tests for thin triangle links only (where no additional normalisation is required). Unlike the tests for edge links, the routines isThinTriangleLink() and isNormalTriangleLink() use essentially the same implementation (so testing for only thin links may be a little faster, but not by much).

A surface (or its positive rational multiple) could be the normalised link of many triangles. The return value will be a pair (v, thin), where:

  • v is a vector containing all such triangles. This will begin with the triangles for which this surface is a thin link, followed by the triangles where normalisation was required; within each category the triangles will be ordered by their index within the triangulation.
  • thin is either 0, 1 or 2, indicating how many triangles this surface is a thin link for. This uses an unsigned type, since it will often be compared to v.size().

If no positive rational multiple of this surface is the normalised link of any triangle, then link will be 0 and v will be the empty vector.

Note that the results of this routine are not cached. Thus the results will be reevaluated every time this routine is called.

Returns
a vector containing the triangle(s) linked by a positive rational multiple of this surface and an integer indicating how many of these links are thin, as described above.

◆ isOrientable()

bool regina::NormalSurface::isOrientable ( ) const
inline

Returns whether or not this surface is orientable.

For our purposes, the empty surface is considered to be orientable.

This routine caches its results, which means that once it has been called for a particular surface, subsequent calls return the answer immediately.

Precondition
This normal surface is embedded (not singular or immersed).
This normal surface is compact (has finitely many discs).
Warning
This routine explicitly builds the normal discs, and so may run out of memory if the normal coordinates are extremely large.
Returns
true if this surface is orientable, or false if this surface is non-orientable.

◆ isSplitting()

bool regina::NormalSurface::isSplitting ( ) const

Determines whether or not this surface is a splitting surface.

A splitting surface is a compact surface containing precisely one quad per tetrahedron and no other normal (or almost normal) discs.

Note that the results of this routine are not cached. Thus the results will be reevaluated every time this routine is called.

Returns
true if and only if this is a splitting surface.

◆ isThinEdgeLink()

std::pair< const Edge< 3 > *, const Edge< 3 > * > regina::NormalSurface::isThinEdgeLink ( ) const

Determines whether or not a positive rational multiple of this surface is the thin link of a single edge.

Here a thin edge link is a normal surface which appears naturally as the frontier of a regular neighbourhood of an edge, with no need for any further normalisation.

This behaves differently from isNormalEdgeLink(), which tests for a normalised edge link (which could end up far away from the edge, or could be normalised into a surface with different topology, or could even be normalised away to nothing). Although isNormalEdgeLink() will also indicate thin edge links, this test has significantly less overhead (and so should be faster).

A surface (or its positive rational multiple) can be the thin edge link of at most two edges. If there are indeed two different edges e1 and e2 for which a multiple of this surface can be expressed as the thin edge link, then the pair (e1, e2) will be returned. If there is only one such edge e, then the pair (e, null) will be returned. If no positive rational multiple of this surface is the thin link of any edge, then the pair (null, null) will be returned.

Note that the results of this routine are not cached. Thus the results will be reevaluated every time this routine is called.

Returns
a pair containing the edge(s) linked by a positive rational multiple of this surface, as described above.

◆ isThinTriangleLink()

std::pair< const Triangle< 3 > *, const Triangle< 3 > * > regina::NormalSurface::isThinTriangleLink ( ) const

Determines whether or not a positive rational multiple of this surface is the thin link of a single triangle.

Here a thin triangle link is a normal surface which appears naturally as the frontier of a regular neighbourhood of a triangle, with no need for any further normalisation.

This behaves differently from isNormalTriangleLink(), which tests for a normalised triangle link (which could end up far away from the triangle, or could be normalised into a surface with different topology, or could even be normalised away to nothing). Unlike the tests for edge links, the routines isThinTriangleLink() and isNormalTriangleLink() use essentially the same implementation (so testing for only thin links may be a little faster, but not by much).

A surface (or its positive rational multiple) can be the thin link of at most two triangles. If there are indeed two different triangles t1 and t2 for which a multiple of this surface can be expressed as the thin triangle link, then the pair (t1, t2) will be returned. If there is only one such triangle t, then the pair (t, null) will be returned. If no positive rational multiple of this surface is the thin link of any triangle, then the pair (null, null) will be returned.

Note that the results of this routine are not cached. Thus the results will be reevaluated every time this routine is called.

Returns
a pair containing the triangle(s) linked by a positive rational multiple of this surface, as described above.

◆ isTwoSided()

bool regina::NormalSurface::isTwoSided ( ) const
inline

Returns whether or not this surface is two-sided.

For our purposes, the empty surface is considered to be two-sided.

This routine caches its results, which means that once it has been called for a particular surface, subsequent calls return the answer immediately.

Precondition
This normal surface is embedded (not singular or immersed).
This normal surface is compact (has finitely many discs).
Warning
This routine explicitly builds the normal discs, and so may run out of memory if the normal coordinates are extremely large.
Returns
true if this surface is two-sided, or false if this surface is one-sided.

◆ isVertexLink()

const Vertex< 3 > * regina::NormalSurface::isVertexLink ( ) const

Determines whether or not a positive rational multiple of this surface is the link of a single vertex.

This behaves differently from isVertexLinking(), which will also detect a union of several different vertex links. In contrast, this routine will only identify the link of a single vertex (or a multiple of such a link).

Note that the results of this routine are not cached. Thus the results will be reevaluated every time this routine is called.

Returns
the vertex linked by a positive rational multiple of this surface, or null if this surface is not a multiple of a single vertex link.

◆ isVertexLinking()

bool regina::NormalSurface::isVertexLinking ( ) const

Determines whether or not this surface is vertex linking.

A vertex linking surface contains only triangles.

This behaves differently from isVertexLink(), which only detects the link of a single vertex (or a multiple of such a link). In contrast, this routine will also detect the union of several different vertex links.

Note that the results of this routine are not cached. Thus the results will be reevaluated every time this routine is called.

Returns
true if and only if this surface is vertex linking.

◆ locallyCompatible()

bool regina::NormalSurface::locallyCompatible ( const NormalSurface other) const

Determines whether this and the given surface are locally compatible.

Local compatibility means that, within each individual tetrahedron of the triangulation, it is possible to arrange the normal discs of both surfaces so that none intersect.

This is a local constraint, not a global constraint. That is, we do not insist that we can avoid intersections within all tetrahedra simultaneously. To test the global constraint, see the (much slower) routine disjoint() instead.

Local compatibility can be formulated in terms of normal disc types. Two normal (or almost normal) surfaces are locally compatible if and only if they together have at most one quadrilateral or octagonal disc type per tetrahedron.

Note again that this is a local constraint only. In particular, for almost normal surfaces, it does not insist that there is at most one octagonal disc type anywhere within the triangulation.

If one of the two surfaces breaks the local compatibility constraints on its own (for instance, it contains two different quadrilateral disc types within the same tetrahedron), then this routine will return false regardless of what the other surface contains.

Precondition
Both this and the given normal surface live within the same 3-manifold triangulation.
Parameters
otherthe other surface to test for local compatibility with this surface.
Returns
true if the two surfaces are locally compatible, or false if they are not.

◆ name()

const std::string & regina::NormalSurface::name ( ) const
inline

Returns the name associated with this normal surface.

Names are optional and need not be unique. The default name for a surface is the empty string.

Returns
the name of associated with this surface.

◆ normal()

bool regina::NormalSurface::normal ( ) const
inline

Determines whether this surface contains only triangle and/or quadrilateral discs.

This is to distinguish normal surfaces from more general surfaces such as almost normal surfaces (which also contain octagonal pieces).

Even if the underlying vector encoding supports other disc types (such as octagons), this routine will still return true if this particular surface does not use them. This is in contrast to the routine NormalSurfaces::allowsAlmostNormal(), which only examines the underlying coordinate system.

Returns
true if and only if this surface contains only triangles and/or quadrilaterals.

◆ octPosition()

DiscType regina::NormalSurface::octPosition ( ) const
inline

Determines the first coordinate position at which this surface has a non-zero octagonal coordinate.

In other words, if this routine returns the disc type t, then the octagonal coordinate returned by octs(t.tetIndex, t.type) is non-zero. Here DiscType::type represents an octagon type within a tetrahedron, and takes values between 0 and 2 inclusive.

If this surface does not contain any octagons, this routine returns a null disc type instead.

This routine caches its results, which means that once it has been called for a particular surface, subsequent calls return the answer immediately. Moreover, if the underlying coordinate system does not support almost normal surfaces, then even the first call is fast (it returns a null disc type immediately).

Returns
the position of the first non-zero octagonal coordinate, or a null disc type if there is no such coordinate.

◆ octs()

LargeInteger regina::NormalSurface::octs ( size_t  tetIndex,
int  octType 
) const
inline

Returns the number of octagonal discs of the given type in this normal surface.

In each tetrahedron, there are three types of octagons, defined by how they separate the four tetrahedron vertices into two pairs. Octagon type i (for i = 0, 1 or 2) is defined to intersect edges i and (5-i) of the tetrahedron twice each, and to intersect the remaining edges once each. This means:

  • type 0 separates vertices 0,1 of the tetrahedron from vertices 2,3;
  • type 1 separates vertices 0,2 of the tetrahedron from vertices 1,3;
  • type 2 separates vertices 0,3 of the tetrahedron from vertices 1,2.
Parameters
tetIndexthe index in the triangulation of the tetrahedron in which the requested octagons reside; this should be between 0 and Triangulation<3>::size()-1 inclusive.
octTypethe type of this octagon in the given tetrahedron; this should be 0, 1 or 2, as described above.
Returns
the number of octagonal discs of the given type.

◆ operator!=()

bool regina::NormalSurface::operator!= ( const NormalSurface other) const
inline

Determines whether this and the given surface represent different normal (or almost normal) surfaces.

Specifically, this routine examines (or computes) the number of normal or almost normal discs of each type, and returns true if and only if these counts are not the same for both surfaces.

It does not matter what vector encodings the two surfaces use. In particular, it does not matter if the two surfaces use different encodings, or if one but not the other supports almost normal and/or spun-normal surfaces.

This routine is safe to call even if this and the given surface do not belong to the same triangulation:

  • If the two triangulations have the same size, then this routine will test whether this surface, if transplanted into the other triangulation using the same tetrahedron numbering and the same normal disc types, would be different from other.
  • If the two triangulations have different sizes, then this routine will return true.
Parameters
otherthe surface to be compared with this surface.
Returns
true if both surfaces represent different normal or almost normal surface, or false if not.

◆ operator*()

NormalSurface regina::NormalSurface::operator* ( const LargeInteger coeff) const

Returns the given integer multiple of this surface.

The resulting surface will use the same internal vector encoding as this surface.

Parameters
coeffthe coefficient to multiply this surface by; this must be non-negative.
Returns
the resulting multiple of this surface.

◆ operator*=()

NormalSurface & regina::NormalSurface::operator*= ( const LargeInteger coeff)

Converts this surface into the given integer multiple of itself.

The internal vector encoding used by this surface will not change.

Parameters
coeffthe coefficient to multiply this surface by; this must be non-negative.
Returns
a reference to this surface.

◆ operator+()

NormalSurface regina::NormalSurface::operator+ ( const NormalSurface rhs) const

Returns the sum of this and the given surface.

This will combine all triangles, quadrilaterals and/or octagons from both surfaces.

The two surfaces do not need to use the same coordinate system and/or internal vector encodings. Moreover, the resulting surface might well use an encoding different from both of these, or even a hybrid encoding that does not come from one of Regina's ready-made coordinate systems.

Precondition
Both this and the given normal surface use the same underlying triangulation.
Parameters
rhsthe surface to sum with this.
Returns
the sum of both normal surfaces.

◆ operator<()

bool regina::NormalSurface::operator< ( const NormalSurface other) const

Imposes a total order on all normal and almost normal surfaces.

This order is not mathematically meaningful; it is merely provided for scenarios where you need to be able to sort surfaces (e.g., when using them as keys in a map).

The order is well-defined, and will be preserved across copy/move operations, different program executions, and different platforms (since it is defined purely in terms of the normal coordinates, and does not use transient properties such as locations in memory).

This operation is consistent with the equality test. In particular, it does not matter whether the two surfaces belong to different triangulations, or use different encodings, or if one but not the other supports non-compact or almost normal surfaces. See the equality test operator==() for further details.

Parameters
otherthe surface to be compared with this surface.
Returns
true if and only if this appears before the given surface in the total order.

◆ operator=() [1/2]

NormalSurface & regina::NormalSurface::operator= ( const NormalSurface )
default

Sets this to be a copy of the given normal surface.

This and the given normal surface do not need to live in the same underlying triangulation, and they do not need to have the same length vectors or use the same normal coordinate system - if any of these properties differs then this surface will be adjusted accordingly.

This operator induces a deep copy of the given normal surface.

Returns
a reference to this normal surface.

◆ operator=() [2/2]

NormalSurface & regina::NormalSurface::operator= ( NormalSurface &&  )
defaultnoexcept

Moves the contents of the given normal surface to this surface.

This is a fast (constant time) operation.

This and the given normal surface do not need to live in the same underlying triangulation, and they do not need to have the same length vectors or use the same normal coordinate system - if any of these properties differs then this surface will be adjusted accordingly.

The surface that was passed will no longer be usable.

Returns
a reference to this normal surface.

◆ operator==()

bool regina::NormalSurface::operator== ( const NormalSurface other) const

Determines whether this and the given surface in fact represent the same normal (or almost normal) surface.

Specifically, this routine examines (or computes) the number of normal or almost normal discs of each type, and returns true if and only if these counts are the same for both surfaces.

It does not matter what vector encodings the two surfaces use. In particular, it does not matter if the two surfaces use different encodings, or if one but not the other supports almost normal and/or spun-normal surfaces.

This routine is safe to call even if this and the given surface do not belong to the same triangulation:

  • If the two triangulations have the same size, then this routine will test whether this surface, if transplanted into the other triangulation using the same tetrahedron numbering and the same normal disc types, would be the same as other.
  • If the two triangulations have different sizes, then this routine will return false.
Parameters
otherthe surface to be compared with this surface.
Returns
true if both surfaces represent the same normal or almost normal surface, or false if not.

◆ quads()

LargeInteger regina::NormalSurface::quads ( size_t  tetIndex,
int  quadType 
) const
inline

Returns the number of quadrilateral discs of the given type in this normal surface.

In each tetrahedron, there are three types of quadrilaterals, defined by how they separate the four tetrahedron vertices into two pairs. Quadrilateral type i (for i = 0, 1 or 2) is defined to separate edge i of the tetrahedron from edge (5-i). That is:

  • type 0 separates vertices 0,1 of the tetrahedron from vertices 2,3;
  • type 1 separates vertices 0,2 of the tetrahedron from vertices 1,3;
  • type 2 separates vertices 0,3 of the tetrahedron from vertices 1,2.
Parameters
tetIndexthe index in the triangulation of the tetrahedron in which the requested quadrilaterals reside; this should be between 0 and Triangulation<3>::size()-1 inclusive.
quadTypethe type of this quadrilateral in the given tetrahedron; this should be 0, 1 or 2, as described above.
Returns
the number of quadrilateral discs of the given type.

◆ reconstructTriangles()

static NormalEncoding regina::NormalSurface::reconstructTriangles ( const Triangulation< 3 > &  tri,
Vector< LargeInteger > &  vector,
NormalEncoding  enc 
)
static

Reconstructs the triangle coordinates in the given integer vector.

The given vector must represent a normal surface within the given triangulation, using the given vector encoding.

  • If the given encoding does not already store triangle coordinates, then the vector will be modified directly to use a new encoding that does, and this new encoding will be returned.
  • If the given encoding does already store triangles, then this routine will do nothing and immediately return enc.
Parameters
trithe triangulation in which the normal surface lives.
vectoran integer vector that encodes a normal (or almost normal) surface within tri; this will be modified directly.
encthe encoding used by the given integer vector.
Returns
the new encoding used by the modified vector.

◆ removeOcts()

NormalSurface regina::NormalSurface::removeOcts ( ) const

Returns an isotopic normal surface that contains no octagons, placed within a homeomorphic (but possibly different) triangulation.

Specifically: this routine returns a surface s within a triangulation t, where t is homeomorphic to the triangulation containing this surface, and where s is a normal (not almost normal) surface isotopic to this. Only the surface s is returned; you can access t by calling s.triangulation().

If this surface is already normal (i.e., it does not contain any octagons), then the surface returned will simply be a copy of this surface (but possibly using a different vector encoding), living within the same triangulation.

If this surface does contain octagons, then the triangulation t will be obtained from the original by replacing each tetrahedron containing octagons with three tetrahedra (essentially performing a 0-2 move). Each octagon can then be subdivided into a quadrilateral and four triangles. If the original triangulation is oriented, then the new triangulation t will preserve this orientation.

In all cases, the surface that is returned will use a vector encoding that does not store octagons.

Note: this routine can happily cope with multiple octagons in the same tetrahedron, and/or multiple tetrahedra containing octagons.

Precondition
This surface is embedded.
Returns
an isotopic normal (not almost normal) surface s, as described above.

◆ scaleDown()

LargeInteger regina::NormalSurface::scaleDown ( )

Converts this surface into its smallest positive rational multiple with integer coordinates.

Note that the scaling factor will be independent of which internal vector encoding is used. This is essentially because integer quad coordinates (which are stored in every encoding) and integer octagon coordinates (which are stored in every almost normal encoding) are enough to guarantee integer triangle coordinates (which might or might not be stored).

Returns
the integer by which the original surface was divided (i.e., the gcd of all normal coordinates in the original surface). This will always be strictly positive.

◆ setName()

void regina::NormalSurface::setName ( const std::string &  name)
inline

Sets the name associated with this normal surface.

Names are optional and need not be unique. The default name for a surface is the empty string.

Parameters
namethe new name to associate with this surface.

◆ str()

std::string regina::Output< NormalSurface , supportsUtf8 >::str ( ) const
inherited

Returns a short text representation of this object.

This text should be human-readable, should use plain ASCII characters where possible, and should not contain any newlines.

Within these limits, this short text ouptut should be as information-rich as possible, since in most cases this forms the basis for the Python __str__() and __repr__() functions.

Python
The Python "stringification" function __str__() will use precisely this function, and for most classes the Python __repr__() function will incorporate this into its output.
Returns
a short text representation of this object.

◆ swap()

void regina::NormalSurface::swap ( NormalSurface other)
inlinenoexcept

Swaps the contents of this and the given normal surface.

This is a fast (constant time) operation.

This and the given normal surface do not need to live in the same underlying triangulation, and they do not need to have the same length vectors or use the same normal coordinate system - if any of these properties differs then the two surfaces will be adjusted accordingly.

Parameters
otherthe normal surface whose contents should be swapped with this.

◆ triangles()

LargeInteger regina::NormalSurface::triangles ( size_t  tetIndex,
int  vertex 
) const
inline

Returns the number of triangular discs of the given type in this normal surface.

A triangular disc type is identified by specifying a tetrahedron and a vertex of that tetrahedron that the triangle surrounds.

Parameters
tetIndexthe index in the triangulation of the tetrahedron in which the requested triangles reside; this should be between 0 and Triangulation<3>::size()-1 inclusive.
vertexthe vertex of the given tetrahedron around which the requested triangles lie; this should be between 0 and 3 inclusive.
Returns
the number of triangular discs of the given type.

◆ triangulation()

const Triangulation< 3 > & regina::NormalSurface::triangulation ( ) const
inline

Returns the triangulation in which this normal surface resides.

This will be a snapshot frozen in time of the triangulation that was originally passed to the NormalSurface constructor.

This will return a correct result even if the original triangulation has since been modified or destroyed. However, in order to ensure this behaviour, it is possible that at different points in time this function may return references to different C++ objects.

The rules for using the triangulation() reference are:

  • Do not keep the resulting reference as a long-term reference or pointer of your own, since in time you may find yourself referring to the wrong object (see above). Just call this function again.
  • You must respect the read-only nature of the result (i.e., you must not cast the constness away). The snapshotting process detects modifications, and modifying the frozen snapshot may result in an exception being thrown.
Returns
a reference to the underlying triangulation.

◆ utf8()

std::string regina::Output< NormalSurface , supportsUtf8 >::utf8 ( ) const
inherited

Returns a short text representation of this object using unicode characters.

Like str(), this text should be human-readable, should not contain any newlines, and (within these constraints) should be as information-rich as is reasonable.

Unlike str(), this function may use unicode characters to make the output more pleasant to read. The string that is returned will be encoded in UTF-8.

Returns
a short text representation of this object.

◆ vector()

const Vector< LargeInteger > & regina::NormalSurface::vector ( ) const
inline

Gives read-only access to the integer vector that Regina uses internally to represent this surface.

Note that this vector might not use the same coordinate system in which the surfaces were originally enumerated. (For example, this vector will always include triangle coordinates, even if the surfaces were originally enumerated in quad or quad-oct coordinates.) You can call encoding() to find out precisley how the coordinates of this vector should be interpreted.

See the NormalSurface class notes for information on how this vector is structured.

Note
If you wish to access the numbers of triangles, quads and so on, you should use the functions triangles(), quads(), etc., which do not require any knowledge of the internal vector encoding that this surface uses.
Returns
the underlying integer vector.

◆ writeTextLong()

void regina::ShortOutput< NormalSurface , false >::writeTextLong ( std::ostream &  out) const
inlineinherited

A default implementation for detailed output.

This routine simply calls T::writeTextShort() and appends a final newline.

Python
Not present. Instead you can call detail() from the subclass T, which returns this output as a string.
Parameters
outthe output stream to which to write.

◆ writeTextShort()

void regina::NormalSurface::writeTextShort ( std::ostream &  out) const

Writes this surface to the given output stream, using standard triangle-quad-oct coordinates.

Octagonal coordinates will only be written if the surface is stored using an encoding that supports almost normal surfaces.

Python
Not present. Use str() instead.
Parameters
outthe output stream to which to write.

◆ writeXMLData()

void regina::NormalSurface::writeXMLData ( std::ostream &  out,
FileFormat  format,
const NormalSurfaces list 
) const

Writes a chunk of XML containing this normal surface and all of its properties.

This routine will be called from within NormalSurfaces::writeXMLPacketData().

Python
The argument out should be an open Python file object.
Parameters
outthe output stream to which the XML should be written.
formatindicates which of Regina's XML file formats to write.
listthe enclosing normal surface list. Currently this is only relevant when writing to the older REGINA_XML_GEN_2 format; it will be ignored (and may be null) for newer file formats.

Member Data Documentation

◆ boundaries_

std::optional<size_t> regina::NormalSurface::boundaries_
mutableprotected

The number of disjoint boundary curves on this surface.

This is std::nullopt if it has not yet been computed.

◆ compact_

std::optional<bool> regina::NormalSurface::compact_
mutableprotected

Is this surface compact (i.e.

does it only contain finitely many discs)? This is std::nullopt if it has not yet been computed.

◆ connected_

std::optional<bool> regina::NormalSurface::connected_
mutableprotected

Is this surface connected? This is std::nullopt if it has not yet been computed.

◆ enc_

NormalEncoding regina::NormalSurface::enc_
protected

The specific encoding of a normal surface used by the coordinate vector.

◆ eulerChar_

std::optional<LargeInteger> regina::NormalSurface::eulerChar_
mutableprotected

The Euler characteristic of this surface.

This is std::nullopt if it has not yet been computed.

◆ linkOf_

uint8_t regina::NormalSurface::linkOf_ { 0 }
mutableprotected

Indicates which dimensions of face a positive rational multiple of this surface is a thin or normalised link of.

This is treated as a bitmask: for each i=0,1,2, the (2i+1)th bit indicates whether this surface scales to the link of an i-face, and the (2i)th bit indicates whether this information has actually been computed yet; if it has not been computed, then the (2i+1)th bit will be zero.

◆ name_

std::string regina::NormalSurface::name_
protected

An optional name associated with this surface.

◆ octPosition_

std::optional<DiscType> regina::NormalSurface::octPosition_
mutableprotected

The position of the first non-zero octagonal coordinate, or a null disc type if there is no non-zero octagonal coordinate.

Here DiscType::type is an octagon type between 0 and 2 inclusive. This is std::nullopt if it has not yet been computed.

◆ orientable_

std::optional<bool> regina::NormalSurface::orientable_
mutableprotected

Is this surface orientable? This is std::nullopt if it has not yet been computed.

◆ realBoundary_

std::optional<bool> regina::NormalSurface::realBoundary_
mutableprotected

Does this surface have real boundary (i.e.

does it meet any boundary triangles)? This is std::nullopt if it has not yet been computed.

◆ triangulation_

SnapshotRef<Triangulation<3> > regina::NormalSurface::triangulation_
protected

The triangulation in which this normal surface resides.

◆ twoSided_

std::optional<bool> regina::NormalSurface::twoSided_
mutableprotected

Is this surface two-sided? This is std::nullopt if it has not yet been computed.

◆ vector_

Vector<LargeInteger> regina::NormalSurface::vector_
protected

Contains the coordinates of the normal surface.


The documentation for this class was generated from the following file:

Copyright © 1999-2023, The Regina development team
This software is released under the GNU General Public License, with some additional permissions; see the source code for details.
For further information, or to submit a bug or other problem, please contact Ben Burton (bab@maths.uq.edu.au).