Tessellation of a Unit Sphere Starting with an Inscribed Convex Triangular Mesh

Similar documents
Intersection of Moving Sphere and Triangle

Intersection of a Triangle and a Cone

1 Introduction 2. 2 A Simple Algorithm 2. 3 A Fast Algorithm 2

Clipping a Mesh Against a Plane

Intersection of an Oriented Box and a Cone

Distance Between Point and Triangle in 3D

Extraction of Level Sets from 2D Images

Triangulation by Ear Clipping

GEOMETRIC TOOLS FOR COMPUTER GRAPHICS

Level Set Extraction from Gridded 2D and 3D Data

Constructions Quiz Review November 29, 2017

Solutions to the ARML Power Question 2006: The Power of Origami

Least-Squares Fitting of Data with B-Spline Curves

Constructing a Cycle Basis for a Planar Graph

CS 4620 Final Exam. (a) Is a circle C 0 continuous?

Perspective Mappings. Contents

MA 323 Geometric Modelling Course Notes: Day 36 Subdivision Surfaces

Minimum-Volume Box Containing a Set of Points

CS354 Computer Graphics Surface Representation IV. Qixing Huang March 7th 2018

C 1 Quadratic Interpolation of Meshes

Harvard-MIT Mathematics Tournament February 19, 2005

The Three Dimensional Coordinate System

Advanced Algorithm Homework 4 Results and Solutions

PURPLE COMET MATH MEET April 2011 HIGH SCHOOL - PROBLEMS. The ratio of 3 to the positive number n is the same as the ratio of n to 192. Find n.

Geometry Vocabulary. acute angle-an angle measuring less than 90 degrees

Scanning Real World Objects without Worries 3D Reconstruction

Subdivision curves and surfaces. Brian Curless CSE 557 Fall 2015

Indiana State Math Contest Geometry

Minimum-Area Rectangle Containing a Set of Points

Mth 97 Fall 2013 Chapter 4

MAKE GEOMETRIC CONSTRUCTIONS

Suggested List of Mathematical Language. Geometry

Topological Issues in Hexahedral Meshing

Homework #2. Shading, Projections, Texture Mapping, Ray Tracing, and Bezier Curves

Kochanek-Bartels Cubic Splines (TCB Splines)

Grade 9 Math Terminology

Ideas beyond Number. Teacher s guide to Activity worksheets

Elementary Planar Geometry

2. A straightedge can create straight line, but can't measure. A ruler can create straight lines and measure distances.

Geometry AP Book 8, Part 2: Unit 7

Intersection of Box and Ellipsoid

Rendering Curves and Surfaces. Ed Angel Professor of Computer Science, Electrical and Computer Engineering, and Media Arts University of New Mexico

Near-Optimum Adaptive Tessellation of General Catmull-Clark Subdivision Surfaces

Course Number: Course Title: Geometry

Definitions. Topology/Geometry of Geodesics. Joseph D. Clinton. SNEC June Magnus J. Wenninger

ECE 600, Dr. Farag, Summer 09

Discrete Mathematics I So Practice Sheet Solutions 1

Geometric Constructions

Lecture 25 of 41. Spatial Sorting: Binary Space Partitioning Quadtrees & Octrees

High School Geometry. Correlation of the ALEKS course High School Geometry to the ACT College Readiness Standards for Mathematics

Convex Hulls in Three Dimensions. Polyhedra

Geometry Practice. 1. Angles located next to one another sharing a common side are called angles.

Cross-Parameterization and Compatible Remeshing of 3D Models

Sorting. Order in the court! sorting 1

Chapter 10 Similarity

1 Appendix to notes 2, on Hyperbolic geometry:

On-Line Computer Graphics Notes CLIPPING

On a nested refinement of anisotropic tetrahedral grids under Hessian metrics

Homework 1: Implicit Surfaces, Collision Detection, & Volumetric Data Structures. Loop Subdivision. Loop Subdivision. Questions/Comments?

Curves and Surfaces. Shireen Elhabian and Aly A. Farag University of Louisville

4.2 and 4.6 filled in notes.notebook. December 08, Integration. Copyright Cengage Learning. All rights reserved.

CS 465 Program 4: Modeller

NAME DATE PERIOD. An angle is formed by two rays that share a common endpoint called the.

UNIT 1 GEOMETRY TEMPLATE CREATED BY REGION 1 ESA UNIT 1

From curves to surfaces. Parametric surfaces and solid modeling. Extrusions. Surfaces of revolution. So far have discussed spline curves in 2D

Lecture 25: Bezier Subdivision. And he took unto him all these, and divided them in the midst, and laid each piece one against another: Genesis 15:10

Curves and Surfaces 1

Efficient Storage and Processing of Adaptive Triangular Grids using Sierpinski Curves

6.837 Introduction to Computer Graphics Final Exam Tuesday, December 20, :05-12pm Two hand-written sheet of notes (4 pages) allowed 1 SSD [ /17]

Grissom High School Math Tournament Geometry March 15, 2003

On Your Own. ). Another way is to multiply the. ), and the image. Applications. Unit 3 _ _

1 The Platonic Solids

Lofting 3D Shapes. Abstract

Investigating Properties of Kites

The goal is the definition of points with numbers and primitives with equations or functions. The definition of points with numbers requires a

Polygonal Meshes: Representing 3D Objects

CGT 581 G Geometric Modeling Surfaces (part I)

Information Coding / Computer Graphics, ISY, LiTH. Splines

Glossary of dictionary terms in the AP geometry units

We can use a max-heap to sort data.

Chapter 3. Sukhwinder Singh

COMPUTER AIDED GEOMETRIC DESIGN. Thomas W. Sederberg

INF3320 Computer Graphics and Discrete Geometry

Study Guide - Geometry

Geometry Final Exam - Study Guide

Geometry Definitions and Theorems. Chapter 9. Definitions and Important Terms & Facts

Geodesic Domes. Tom Davis December 2, 2007

A triangle that has three acute angles Example:

Partitioning Regular Polygons Into Circular Pieces II: Nonconvex Partitions

SHAPE AND STRUCTURE. Shape and Structure. An explanation of Mathematical terminology

Obtaining the H and T Honeycomb from a Cross-Section of the 16-cell Honeycomb

Acute Triangulations of Polygons

The Volume of a Platonic Solid

Note: For all questions, answer (E) NOTA means none of the above answers is correct. Unless otherwise specified, all angles are measured in degrees.

Mesh Representations & Geometry Processing

2D rendering takes a photo of the 2D scene with a virtual camera that selects an axis aligned rectangle from the scene. The photograph is placed into

Lecture IV Bézier Curves

Mth 97 Winter 2013 Sections 4.3 and 4.4

25. How would you make the octahedral die shown below?

Ideas beyond Number. Activity worksheets

Transcription:

Tessellation of a Unit Sphere Starting with an Inscribed Convex Triangular Mesh David Eberly, Geometric Tools, Redmond WA 98052 https://www.geometrictools.com/ This work is licensed under the Creative Commons Attribution 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA. Created: March 2, 1999 Last Modified: January 5, 2015 Contents 1 Introduction 2 2 Data Structures for the Algorithm 2 3 Subdivision Algorithm 3 3.1 Centroid of Polyhedron....................................... 3 3.2 Intersection of Ray with Sphere................................... 3 3.3 Memory Organization........................................ 4 3.4 Pseudocode for a Single Subdivision................................ 5 1

1 Introduction This document describes how to tessellate a unit radius sphere with a triangular mesh starting with an inscribed convex triangular mesh. A typical starting mesh is an inscribed octahedron with equilateral triangular faces, but the algorithm applies equally well to any inscribed convex triangular mesh. Choice of initial mesh affects the final distribution of triangless. I do not discuss the problem of selecting an initial mesh to produce a final mesh with desired distributional features. Each triangle in the initial mesh is assumed to have its vertices ordered in a counterclockwise fashion as you look at the triangle from the outside of the polyhedron. Each triangle is subdivided into four triangles by computing the midpoints of the triangle edges and connecting them together. The midpoints are not on the unit sphere, but must be moved onto the sphere. Unitizing the points does not necessarily yield a convex polyhedron, especially when the origin is not in the initial convex polyhedron. What I do instead is compute the centroid of the polyhedron (guaranteed to be inside the polyhedron), then project the edge midpoints onto the sphere along the rays connecting the centroid and midpoints. Subdividing the polyhedron is simple to implement if all you keep track of is a list of triangles and the three vertex locations per triangle. However, if you need more connectivity relationships between the among the vertices, edges, and triangles of the mesh, the implementation becomes more difficult. While simple to describe, the difficult problem is maintaining data structures 2 Data Structures for the Algorithm The following data types are used. The implementation uses pointers for efficiency by avoiding full copying of the data members. s t r u c t P o i n t 3 f l o a t x, y, z ; ; s t r u c t V e r t e x P o i n t 3 p o i n t ; i n t numedges ; // number o f e d g e s s h a r i n g t h e v e r t e x s t r u c t Edge edge ; // a r r a y o f numedges edge p o i n t e r s ; s t r u c t Edge s t r u c t V e r t e x v e r t e x [ 2 ] ; // end p o i n t s o f edge s t r u c t T r i a n g l e t r i a n g l e [ 2 ] ; // t [ 0 ] and t [ 1 ] s h a r e t h e edge ; s t r u c t T r i a n g l e s t r u c t V e r t e x v e r t e x [ 3 ] ; // v e r t i c e s o f t r i a n g l e s t r u c t Edge edge [ 3 ] ; // e0 = <v0, v1 >, e1 = <v1, v2 >, e2 = <v2, v0> s t r u c t T r i a n g l e a d j a c e n t [ 3 ] ; // a d j [ i ] s h a r e s e [ i ] w i t h t r i a n g l e ; s t r u c t ConvexPolyhedron i n t n u m V e r t i c e s ; V e r t e x v e r t e x ; 2

i n t numedges ; Edge edge ; i n t numtriangles ; T r i a n g l e t r i a n g l e ; ; P o i n t 3 c e n t r o i d ; While other variations on the data types may be required for an application, this one is used in the algorithm for computing the terminator and silhouette of a convex polyhedron (see the Projection page gr proj.htm). Goals in the construction are to have no reallocation of memory (avoids fragmentation of the heap) and to update the data structures in-place (efficient use of memory). Let the initial mesh have ν 0 vertices, ɛ 0 edges, and τ 0 triangles. Let ν i, ɛ i, and τ i be the number of vertices, edges, and triangles, respectively, after the i-th subdivision step. The number of vertices increases by the number of edges. The number of edges is first doubled by the edge splitting, then increased by three times the number of triangles due to connecting the midpoints of the edges. The number of triangles quadruples. The recurrence relations are ν i+1 = ν i + ɛ i, ɛ i+1 = 2ɛ i + 3τ i, τ i+1 = 4τ i, i 0. While these can be solved in closed form, the code just iterates the equations for the desired number of subdivision steps n to compute the total number of vertices, edges, and triangles required for the final convex polyhedron. The required memory for vertices, edges, and triangles can be allocated all at once for the polyhedron. The other dynamically allocated quantities are the arrays of edge pointers in the Vertex structure. The arrays for the initial vertices never change size. For each added vertex, the number of edges is always six. Because of the edge splitting, the actual edge pointers may change during a subdivision step. 3 Subdivision Algorithm 3.1 Centroid of Polyhedron Initially, and after each subdivision step, the centroid of the convex polyhedron is computed to be used in the midpoint projection phase of the subdivision. This point is computed as the average of the current vertices in the polyhedron. The centroid at step s is where the vertex locations are P 0 through P νs 1. ν s C = j=0 P j 3.2 Intersection of Ray with Sphere A new vertex is added per edge by computing the midpoint M of the edge, then projecting that point along the ray starting at the centroid C and passing through M. If edge E has endpoints P 0 and P 1, then 3

M = (P 0 + P 1 )/2. The ray is given parametrically as X(t) = C + t(m C) where t 0. Since both C and M are inside the sphere, X(t) must be inside the sphere for any t [0, 1]. The new vertex location occurs where the ray and sphere intersect. If t is the parameter value at the intersection, then t > 1 and the squared length of X( t) is 1. This condition is a quadratic equation 1 = X( t) X( t) = [C + t(m C)] [C + t(m C)] = C C + 2C (M C)t + (M C) (M C)t 2. If D = M C, the quadratic equation is a 2 t 2 +a 1 t+a 0 = 0 where a 2 = D D, a 1 = 2C D, and a 0 = C C 1. As argued earlier, the equation has one root larger than 1, namely t = a 1 + a 2 1 4a 0a 2 2a 2. The location for the new vertex is therefore P = C + td. 3.3 Memory Organization The total amount of memory required for the vertex, edge, and triangle arrays in the final polyhedron is computed and the corresponding memory is allocated. The vertex array has ν n elements, the edge array has ɛ n elements, and the triangle array has τ n elements. The initial items are stored at the beginning of each of the arrays. For a single subdivision step, the working set in memory is shown in Figure 1. Figure 1. Working set of vertices, edges, and triangles. The values ν, ɛ, and τ are the current numbers of vertices, edges, and triangles, respectively. The partitioning of the triangle subarray into four sections corresponds to splitting the triangle into four pieces as shown in Figure 2. 4

Figure 2. Subdivided triangle. If the figure represents the triangle stored at the t-th location in the array, then the subtriangle T k is stored at location t + kτ for k = 1, 2, 3. The subtriangle T 0 is stored at the same location as the original triangle. This in-place storage requires careful bookkeeping to avoid overwriting old triangle information with new information before the old information is no longer needed for other parts of the algorithm. 3.4 Pseudocode for a Single Subdivision As the data structures are updated, it is important to retain old vertex, edge, or triangle information that is necessary for use at a later stage of the update. In the pseudocode, variables vmax, emax, and tmax correspond to ν, ɛ, and τ, the current number of vertices, edges, and triangles. The variables vertex, edge, and triangle refer to the arrays V, E, and T shown in Figure 1. The variable centroid is the centroid of the current polyhedron. The first two safe operations are to add the new vertex locations and to split the edges. f o r ( e = 0 ; e < emax ; e++) // g e n e r a t e new v e r t e x M from edge [ e ] E0 l o c a t e d a t edge [ e ] ; P0 = E0. v e r t e x [ 0 ]. p o i n t ; P1 = E0. v e r t e x [ 0 ]. p o i n t ; mid = ( P0+P1 ) / 2 ; M l o c a t e d a t v e r t e x [ vmax+e ] ; M. p o i n t = R a y S p h e r e I n t e r s e c t i o n ( c e n t r o i d, mid ) ; M. numberofedges = 6 ; M. edge = a l l o c a t e 6 edge p o i n t e r s ; // s p l i t edge E0 = <V0, V1> i n t o E0 = <V0,M> and E1 = <V1,M> E1 l o c a t e d a t edge [ emax+e ] ; E1. v e r t e x [ 0 ] = E0. v e r t e x [ 1 ] ; E0. v e r t e x [ 1 ] = M; E1. v e r t e x [ 1 ] = M; 5

The edge pointers for the new vertices are set later to point to the subdivided edges. The triangle pointers for the split edges are the old ones and are updated later to point to the subdivided triangles. Once the new vertex locations are known, the centroid of the old and new vertices can be precomputed for the next subdivision pass. An iteration can now be made over the current triangles to update various fields in the data structures. The function VertexIndex(V) returns the index of vertex V in the array of vertices. Similarly EdgeIndex(E) returns the index of edge E in the array of edges and TriangleIndex(T) returns the index of triangle T in the array of triangles. The code uses four indices into the triangle array, t0 for the current triangles (then later to represent the middle triangle in the subdivision), and t1, t2, and t3 for the other subdivided triangles. Initially t0 = 0 ; t1 = tmax ; t2 = 2 tmax ; t3 = 3 tmax ; In the following discussion, each displayed block of code is contained in a loop where t0 varies from 0 to tmax-1. All four counters are incremented each pass of the loop. The first displayed block of code indicates the relationships that are immediately discernable from Figure 2. // g e t t r i a n g l e s to p r o c e s s Tj l o c a t e d a t t r i a n g l e [ t j ] f o r j = 0, 1, 2, 3 ; Vi = T0. v e r t e x [ i ] f o r i = 0, 1, 2 ; // v e r t i c e s E i = T0. edge [ i ] f o r i = 0, 1, 2 ; // o r i g i n a l e d g e s E i i s o t h e r h a l f o f o r i g i n a l edge formed by s p l i t ; Ai = T0. a d j a c e n t [ i ] f o r i = 0, 1, 2 ; // a d j a c e n t t r i a n g l e s Mi l o c a t e d a t v e r t e x [ vmax+edgeindex ( E i ) ] f o r i = 0, 1, 2 ; // m i d p o i n t s // e d g e s c o r r e s p o n d i n g to c o n n e c t i o n s o f m i d p o i n t s E i l o c a t e d a t edge [2 emax+3 t0+i ] f o r i = 0, 1, 2 ; // s e t v e r t i c e s and t r i a n g l e s f o r e d g e s E0. v e r t e x [ 0 ] = M2; E0. v e r t e x [ 1 ] = M0; E0. t r i a n g l e [ 0 ] = T0 ; E0. t r i a n g l e [ 1 ] = T1 ; E1. v e r t e x [ 0 ] = M0; E1. v e r t e x [ 1 ] = M1; E1. t r i a n g l e [ 0 ] = T0 ; E1. t r i a n g l e [ 1 ] = T2 ; E2. v e r t e x [ 0 ] = M1; E2. v e r t e x [ 1 ] = M2; E2. t r i a n g l e [ 0 ] = T0 ; E2. t r i a n g l e [ 1 ] = T3 ; // s e t some members o f t r i a n g l e T1 T1. v e r t e x [ 0 ] = V0 ; T1. v e r t e x [ 1 ] = M0; T1. v e r t e x [ 2 ] = M2; T1. edge [ 0 ] = E0 ; T1. edge [ 1 ] = E0 ; T1. edge [ 2 ] = E2 ; T1. a d j a c e n t [ 1 ] = T0 ; // s e t some members o f t r i a n g l e T2 T2. v e r t e x [ 0 ] = M0; T2. v e r t e x [ 1 ] = V1 ; T2. v e r t e x [ 2 ] = M1; T2. edge [ 0 ] = E0 ; T2. edge [ 1 ] = E1 ; T2. edge [ 2 ] = E1 ; T2. a d j a c e n t [ 2 ] = T0 ; // s e t some members o f t r i a n g l e T2 6

T3. v e r t e x [ 0 ] = M2; T3. v e r t e x [ 1 ] = M1; T3. v e r t e x [ 2 ] = V2 ; T3. edge [ 0 ] = E2 ; T3. edge [ 1 ] = E1 ; T3. edge [ 2 ] = E2 ; T3. a d j a c e n t [ 0 ] = T0 ; The subdivided triangles T1, T2, and T3 have some adjacent triangles that are themselves subdivided triangles of adjacent triangles of the original triangle T0. At this point in the algorithm we know the index of each original adjacent triangle in the triangle array for the polyhedron. We can use this index to locate the triangle array elements for the subdivided triangle of the adjacent triangle. However, there is one complication. Figure 2 shows a triangle in a standard configuration based on how the vertices and edges were labeled (vertices start at lower left corner of triangle, others labeled in counterclockwise order). An adjacent triangle can have one of three possible orientations in its relationship to the central triangle. The code must determined which edge of the adjacent triangle is shared with the central triangle. This information allows proper labeling of the adjacency relationship between subdivided triangles between adjacent original triangles. Figure 3 shows the nine cases to consider, three choices for adjacent triangle and three orientations for that triangle. 7

Figure 3. Possible orientations of adjacent triangle with central triangle. The pseudocode for handling the adjacent triangle A0 is // g e t t h e i n d i c e s f o r t h e s u b d i v i d e d t r i a n g l e s o f A0 i 0 = T r i a n g l e I n d e x (A0 ) ; i 1 = i 0+tmax ; i 2 = i 1+tmax ; i 3 = i 2+tmax ; o r i e n t = s h a r e d ege o f A0 and T0 i s A0. edge [ o r i e n t ] ; i f ( o r i e n t == 0 ) T1. a d j a c e n t [ 0 ] i s t r i a n g l e [ i 2 ] ; T2. a d j a c e n t [ 0 ] i s t r i a n g l e [ i 1 ] ; t r i a n g l e [ i 2 ]. a d j a c e n t [ 0 ] i s T1 ; t r i a n g l e [ i 1 ]. a d j a c e n t [ 0 ] i s T2 ; e l s e i f ( o r i e n t == 1 ) T1. a d j a c e n t [ 0 ] i s t r i a n g l e [ i 3 ] ; T2. a d j a c e n t [ 0 ] i s t r i a n g l e [ i 2 ] ; t r i a n g l e [ i 3 ]. a d j a c e n t [ 1 ] i s T1 ; t r i a n g l e [ i 2 ]. a d j a c e n t [ 1 ] i s T2 ; e l s e 8

T1. a d j a c e n t [ 0 ] i s t r i a n g l e [ i 1 ] ; T2. a d j a c e n t [ 0 ] i s t r i a n g l e [ i 3 ] ; t r i a n g l e [ i 1 ]. a d j a c e n t [ 2 ] i s T1 ; t r i a n g l e [ i 3 ]. a d j a c e n t [ 2 ] i s T2 ; Similar blocks of code are in the source file for adjacent triangles A1 and A2. Finally in this loop, the edge pointers for the new vertices can be set. The real code initializes the number of edges of each new vertex to zero as a flag. The first time a new vertex is encountered, it is processed as a midpoint of an edge of a triangle. At this time four of the edges sharing the vertex are known. At at later pass through the loop, the adjacent triangle sharing the edge whose midpoint generated the new vertex. At this time the remaining two edge pointers can be set. For example, // add edge l i n k s to m i d p o i n t v e r t i c e s i f ( M0. numedges == 0 ) // add f o u r e d g e s ( f i r s t time e d g e s a r e added f o r t h i s v e r t e x ) M0. numedges = 4 ; M0. edge [ 0 ] i s T1. edge [ 0 ] ; M0. edge [ 1 ] i s T1. edge [ 1 ] ; M0. edge [ 2 ] i s T2. edge [ 2 ] ; M0. edge [ 3 ] i s T2. edge [ 0 ] ; e l s e i f ( M0. numedges == 4 ) // add two e d g e s ( l a s t time e d g e s a r e added f o r t h i s v e r t e x ) M0. numedges = 6 ; M0. edge [ 4 ] i s T1. edge [ 1 ] ; M0. edge [ 5 ] i s T2. edge [ 2 ] ; Similar blocks of code are in the source file for new vertices M1 and M2. A second iteration over the current triangles is made. This step requires information produce by the first iteration over all triangles. The following blocks of pseudocode are contained in a loop over the four triangle counters, just as before. The initial values of the counters are t0 = 0 ; t1 = tmax ; t2 = 2 tmax ; t3 = 3 tmax ; The first part of the loop is // g e t t r i a n g l e s to p r o c e s s Tj l o c a t e d a t t r i a n g l e [ t j ] f o r j = 0, 1, 2, 3 ; E i = T0. edge [ i ] f o r i = 0, 1, 2 ; Mi = v e r t e x [ vmax+edgeindex ( E i ) ] f o r i = 0, 1, 2 ; // s e t v e r t i c e s, edges, a d j a c e n c i e s f o r m i d d l e t r i a n g l e T0. v e r t e x [ 0 ] i s M2; T0. v e r t e x [ 1 ] i s M0; T0. v e r t e x [ 2 ] i s M1; T0. edge [ 0 ] i s T1. edge [ 1 ] ; T0. edge [ 1 ] i s T2. edge [ 2 ] ; T0. edge [ 2 ] i s T3. edge [ 0 ] ; T0. a d j a c e n t [ 0 ] i s T1 ; T0. a d j a c e n t [ 1 ] i s T2 ; T0. a d j a c e n t [ 2 ] i s T3 ; The subdivided triangle edge pointers can be set at this time. For example, at T1, 9

T1. edge [ 0 ]. t r i a n g l e [ 0 ] i s T1 ; T1. edge [ 0 ]. t r i a n g l e [ 1 ] i s T1. a d j a c e n t [ 0 ] ; T1. edge [ 2 ]. t r i a n g l e [ 0 ] i s T1 ; T1. edge [ 2 ]. t r i a n g l e [ 1 ] i s T1. a d j a c e n t [ 2 ] ; The actual code initializes the triangle pointers to zero and tests before the pointers are set. Otherwise, each triangle pointer is written twice (simply an efficiency gain). Similar blocks of code exist for T2 and T3. The last step is to adjust the edge pointers of the original vertices to account for the edge splitting. The main concern is to select the correct half edge to store a pointer to. This can be determined by comparing the vertex pointer values of the half edges to the testing vertex. f o r ( v = 0 ; v < vmax ; v++) V i s v e r t e x [ v ] ; f o r ( e = 0 ; e < V. numedges ; e++) E i s V. edge [ e ] ; i f ( E. v e r t e x [ 0 ] not e q u a l V and E. v e r t e x [ 1 ] not e q u a l V ) // V. edge [ e ] c u r r e n t l y p o i n t s to wrong h a l f edge, s w i t c h i t V. edge [ e ] = edge [ emax+edgeindex (E ) ] ; 10