1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
|
/*
* edge_classes.c
*
* This file provides the functions
*
* void create_edge_classes(Triangulation *manifold);
* void replace_edge_classes(Triangulation *manifold);
* void orient_edge_classes(Triangulation *manifold);
*
* which are used within the kernel.
*
* create_edge_classes() adds EdgeClasses to a partially
* constructed manifold which does not yet have them.
* It assumes the tet->neighbor and tet->gluing fields
* contain correct values.
*
* replace_edge_classes() removes all EdgeClasses from a manifold
* and adds fresh ones. replace_edge_classes() is typically called
* by functions which would rather replace invalid EdgeClasses
* at the end of an algorithm rather than try to maintain them
* as they go along.
*
* orient_edge_classes() orients a neighborhood of each EdgeClass.
* Relative to this orientation, each of the incident tetrahedra
* will be seen as right_ or left_handed.
*
* The edges of a tetrahedron are indexed according to the following table:
*
* lies lies
* edge between between
* faces vertices
* 0 0,1 2,3
* 1 0,2 1,3
* 2 0,3 1,2
* 3 1,2 0,3
* 4 1,3 0,2
* 5 2,3 0,1
*
* orient_edge_classes() sets the field tet->edge_orientation[e] to be the
* orientation of Tetrahedron tet as seen by EdgeClass tet->edge_class[e].
* In an oriented manifold, all edge_orientations will be right_handed.
*
* orient_edge_classes() should be called as soon as a Triangulation
* is created, and functions which modify a Triangulation should
* maintain the edge_orientation[] fields.
*
* As explained in the documentation at the top of orient.c, orient()
* and orient_edge_classes() may be called in either order, but both
* should be called.
*/
#include "kernel.h"
static void initialize_tet_edge_classes(Triangulation *manifold);
static void create_one_edge_class(Triangulation *manifold, Tetrahedron *tet, EdgeIndex e);
void create_edge_classes(
Triangulation *manifold)
{
Tetrahedron *tet;
EdgeIndex e;
/*
* First set tet->edge_class[] to NULL for all
* edges of all Tetrahedra.
*/
initialize_tet_edge_classes(manifold);
/*
* Go down the list of Tetrahedra, and whenever
* an edge is found with no EdgeClass, create one
* for it.
*/
for (tet = manifold->tet_list_begin.next;
tet != &manifold->tet_list_end;
tet = tet->next)
for (e = 0; e < 6; e++)
if (tet->edge_class[e] == NULL)
create_one_edge_class(manifold, tet, e);
}
static void initialize_tet_edge_classes(
Triangulation *manifold)
{
Tetrahedron *tet;
EdgeIndex e;
for (tet = manifold->tet_list_begin.next;
tet != &manifold->tet_list_end;
tet = tet->next)
for (e = 0; e < 6; e++)
tet->edge_class[e] = NULL;
}
static void create_one_edge_class(
Triangulation *manifold,
Tetrahedron *tet,
EdgeIndex e)
{
EdgeClass *new_edge_class;
FaceIndex front,
back,
temp;
Permutation gluing;
Tetrahedron *tet0;
EdgeIndex e0;
/*
* Create the new EdgeClass and add it to the list.
*/
new_edge_class = NEW_STRUCT(EdgeClass);
initialize_edge_class(new_edge_class);
INSERT_BEFORE(new_edge_class, &manifold->edge_list_end);
/*
* Initialize the fields of the EdgeClass.
*/
new_edge_class->order = 0;
new_edge_class->incident_tet = tet;
new_edge_class->incident_edge_index = e;
/*
* Walk around the edge class, setting the tet->edge_class
* field for each edge we encounter.
*/
front = one_face_at_edge[e];
back = other_face_at_edge[e];
tet0 = tet;
e0 = e;
do
{
/*
* Set the edge_class pointer . . .
*/
tet->edge_class[e] = new_edge_class;
/*
* . . . increment new_edge_class->order . . .
*/
new_edge_class->order++;
/*
* . . . and move on to the next edge.
*/
gluing = tet->gluing[front];
tet = tet->neighbor[front];
temp = front;
front = EVALUATE(gluing, back);
back = EVALUATE(gluing, temp);
e = edge_between_faces[front][back];
}
while (tet != tet0 || e != e0);
}
void replace_edge_classes(
Triangulation *manifold)
{
EdgeClass *dead_edge_class;
/*
* Remove all existing EdgeClasses . . .
*/
while (manifold->edge_list_begin.next != &manifold->edge_list_end)
{
dead_edge_class = manifold->edge_list_begin.next;
REMOVE_NODE(dead_edge_class);
my_free(dead_edge_class);
}
/*
* . . . and add fresh ones.
*/
create_edge_classes(manifold);
}
void orient_edge_classes(
Triangulation *manifold)
{
EdgeClass *edge;
Tetrahedron *tet;
EdgeIndex e;
FaceIndex front,
back,
temp;
Orientation relative_orientation;
Permutation gluing;
int count;
/*
* For each EdgeClass in the Triangulation . . .
*/
for (edge = manifold->edge_list_begin.next;
edge != &manifold->edge_list_end;
edge = edge->next)
{
/*
* Find an incident edge.
*/
tet = edge->incident_tet;
e = edge->incident_edge_index;
front = one_face_at_edge[e];
back = other_face_at_edge[e];
/*
* View the incident Tetrahedron relative to the
* right_handed Orientation.
*/
relative_orientation = right_handed;
/*
* We'll walk around the EdgeClass, setting
* the Orientation of each incident edge.
*/
for (count = edge->order; --count >= 0; )
{
/*
* Set the edge_orientation of the present edge . . .
*/
tet->edge_orientation[e] = relative_orientation;
/*
* . . . and move on to the next edge.
*/
gluing = tet->gluing[front];
tet = tet->neighbor[front];
temp = front;
front = EVALUATE(gluing, back);
back = EVALUATE(gluing, temp);
e = edge_between_faces[front][back];
/*
* Change the relative_orientation iff the new
* new Tetrahedron is oriented differently than
* the old one.
*/
if (parity[gluing] == orientation_reversing)
relative_orientation = ! relative_orientation;
}
/*
* When we return to the initial Tetrahedron,
* the relative_orientation should again be right_handed.
* If it isn't, the triangulation defines an orbifold
* with a cone-on-a-projective-plane at the center of
* the current edge class. This error should be rare --
* in fact is should be possible only for hand-coded
* Triangulations.
*/
if (relative_orientation != right_handed)
{
uAcknowledge("The triangulation has a cone-on-a-projective-plane singularity at the midpoint of an edge class.");
uFatalError("orient_edge_classes", "edge_classes");
}
}
}
|