This chapter contains examples of implementations of some of the methods in the package SimplicialSurfaces
. We chose examples which illustrate many of the different fundamental features and methods of the package while at the same time require only a few lines of code to implement. Every section discusses the implementation of an already existing method by giving:
A short explanation of the method
A presentation of the code
The development of the code
The method StronglyConnectedComponentOfFace
(8.6-4) finds all faces that are connected to a given face by edge-face-paths (8.3) and returns the polygonal complex consisting of these faces.
We illustrate this with an octahedron (14.3-4):
gap> octa := Octahedron();; gap> octa = StronglyConnectedComponentOfFace(octa,7); true
This could be implemented like this:
gap> StrongComponent_custom := function( complex, face ) > local component, f, edge, newFace; > > component := [ face ]; > for f in component do > for edge in EdgesOfFace(complex, f) do > newFace := NeighbourFaceByEdge( complex, f, edge ); > if not newFace in component then > Add(component, newFace); > fi; > od; > od; > > return SubcomplexByFaces( complex, component ); > end;; gap> gap> StrongComponent_custom(octa,7) = StronglyConnectedComponentOfFace(octa,7); true
To develop this code we first have to find an algorithm to compute the strongly connected component of an face. We begin with the starting face (for example 7) and add all faces to the strong component that are adjacent to it (so 1, 5 and 6). Then we add the neighbours of those faces (and so on). We will end up with all faces of the strongly connected component of 7. The initialization of this algorithm is easy.
gap> component := [ 7 ]; [ 7 ]
For each edge of this face there is a neighbour. Therefore we need the edges of this face.
gap> EdgesOfFace( octa, 7 ); [ 2, 3, 8 ]
The neighbours can be computed by calling the method NeighbourFaceByEdge
(10.3-3).
gap> newFace := NeighbourFaceByEdge( octa, 7, 2 ); 1
If this face is not already accounted for, we have to add it to our component.
gap> if not newFace in component then > Add( component, newFace ); > fi;
To check all neighbours, we loop over the incident edges:
gap> for edge in EdgesOfFace(octa, 7) do > newFace := NeighbourFaceByEdge( octa, 7, edge ); > if not newFace in component then > Add( component, newFace ); > fi; > od;
Finally we have to loop over all faces in the component. At this point we use a feature of GAP: We can loop over a list that is changed during the loop. So our algorithm can simply be written as
gap> for f in component do > for edge in EdgesOfFace(octa, f) do > newFace := NeighbourFaceByEdge( octa, f, edge ); > if not newFace in component then > Add(component, newFace); > fi; > od; > od; gap> component; [ 7, 1, 5, 6, 3, 4, 8, 2 ]
Now we have computed all faces of the strongly connected component of our starting face. To make a polygonal complex out of it, we use the method SubcomplexByFaces
that returns the induced subcomplex of a given list of faces.
gap> SubcomplexByFaces( octa, component ) = octa; true
The method CounterOfVertices
(9.2-4) creates a list of pairs [degree,multiplicity] such that the second entry of each pair counts the number of vertices that have exactly degree incident faces.
We illustrate it on the example of a pyramid with square base.
gap> pyr := PolygonalSurfaceByVerticesInFaces( > [ [3,4,5,6], [1,3,4], [1,4,5], [1,5,6], [1,6,3] ]);; gap> ListCounter(CounterOfVertices( pyr )); [ [ 3, 4 ], [ 4, 1 ] ]
This could be implemented like this:
gap> VertexCounter_custom := function( complex ) > local faceDegrees; > > faceDegrees := List( FacesOfVertices(complex), Size ); > return Collected( Compacted( faceDegrees ) ); > end;; gap> gap> VertexCounter_custom( pyr ); [ [ 3, 4 ], [ 4, 1 ] ]
How do we arrive at this code? First of all we have to find the relevant information. We want to count how many faces are incident to a vertex. Therefore we use the method FacesOfVertices
(3.2-2) that gives us exactly this information. Since we only want to know the number of faces, we apply the method Size
to every component.
gap> faceDegrees := List( FacesOfVertices(pyr), Size ); [ 4, , 3, 3, 3, 3 ]
Alternatively we could have used the specialized method FaceDegreesOfVertices
(9.2-2) directly.
gap> FaceDegreesOfVertices( pyr ); [ 4, , 3, 3, 3, 3 ]
Now we need to count how often each entry appears. This can be done by a loop but we will use the GAP-function Collected
instead. Unfortunately it only works for lists without holes:
gap> Collected( faceDegrees ); Error, List Element: <list>[2] must have an assigned value
If we want to program with this package, we have to expect holes. In this case it is sufficient to remove all holes with the GAP-function Compacted
.
gap> Compacted( faceDegrees ); [ 4, 3, 3, 3, 3 ] gap> colDegrees := Collected( Compacted( faceDegrees ) ); [ [ 3, 4 ], [ 4, 1 ] ]
This is exactly the result we aimed for.
generated by GAPDoc2HTML