Пример #1
0
        private List <TriangleLinked>[] GetLinked(TriangleLinked triangle)
        {
            List <TriangleLinked>[] linked = new List <TriangleLinked> [3];

            for (int i = 0; i < 3; i++)
            {
                List <int> linkedIndices = triangle.m_LinkedTriangles[i];
                for (int j = 0; j < linkedIndices.Count; j++)
                {
                    // Make sure it doesn't count itself as a neighbour
                    if (m_Triangles[m_Triangles.IndexOf(triangle)].Equals(linkedIndices[j]))
                    {
                        linkedIndices.RemoveAt(j);
                        continue;
                    }
                    // Ignore marked triangles (already in a strip)
                    if (m_Triangles[linkedIndices[j]].m_Marked)
                    {
                        linkedIndices.RemoveAt(j);
                        continue;
                    }
                }
                linked[i] = new List <TriangleLinked>();
                for (int j = 0; j < linkedIndices.Count; j++)
                {
                    linked[i].Add(m_Triangles[linkedIndices[j]]);
                }
            }

            return(linked);
        }
Пример #2
0
        private int GetNumLinked(TriangleLinked triangle)
        {
            List <TriangleLinked>[] linked = GetLinked(triangle);
            int count = 0;

            for (int i = 0; i < 3; i++)
            {
                count += linked[i].Count;
            }
            return(count);
        }
Пример #3
0
        private TriangleLinked DetermineBestNextNeighbour(TriangleLinked triangle, List <TriangleLinked> neighbours, TriangleEdge edge,
                                                          bool tieBreak = false)
        {
            if (neighbours.Count == 0)
            {
                return(null);
            }

            if (neighbours.Count == 1)
            {
                return(neighbours[0]);
            }

            neighbours.Sort((a, b) => GetNumLinked(a).CompareTo(GetNumLinked(b)));

            TriangleLinked[] twoTop = new TriangleLinked[2];
            twoTop[0] = neighbours[0]; twoTop[1] = neighbours[1];

            int[] numLinkedOfNeighbours = new int[] { GetNumLinked(twoTop[0]), GetNumLinked(twoTop[1]) };

            if (numLinkedOfNeighbours[0] < numLinkedOfNeighbours[1])
            {
                return(twoTop[0]);
            }
            else if (numLinkedOfNeighbours[1] < numLinkedOfNeighbours[0])
            {
                return(twoTop[1]);
            }
            else if (!tieBreak)
            {
                List <TriangleLinked> firstLinked  = GetLinked(twoTop[0])[(int)edge];
                List <TriangleLinked> secondLinked = GetLinked(twoTop[1])[(int)edge];

                TriangleLinked firstBest  = DetermineBestNextNeighbour(twoTop[0], firstLinked, edge, true);
                TriangleLinked secondBest = DetermineBestNextNeighbour(twoTop[1], secondLinked, edge, true);

                if (GetNumLinked(firstBest) < GetNumLinked(secondBest))
                {
                    return(twoTop[0]);
                }
                else
                {
                    return(twoTop[1]);
                }
            }
            else if (tieBreak)
            {
                return(twoTop[0]);
            }
            else
            {
                return(null);
            }
        }
Пример #4
0
    public void AddTriangleLink(Connection c)
    {
        if (TriangleLinked == null)
        {
            TriangleLinked = new List <Connection>();
        }

        if (!TriangleLinked.Contains(c))
        {
            TriangleLinked.Add(c);
        }
    }
Пример #5
0
        public List <ModelBase.FaceListDef> Stripify(bool keepVertexOrderDuringStripping = false)
        {
            for (int i = 0; i < m_Triangles.Count; i++)
            {
                ModelBase.FaceDef triangle = m_Triangles[i].m_Triangle;

                List <int> vertexALinked = GetVertex(triangle.m_Vertices[0]).m_LinkedTriangles;
                List <int> vertexBLinked = GetVertex(triangle.m_Vertices[1]).m_LinkedTriangles;
                List <int> vertexCLinked = GetVertex(triangle.m_Vertices[2]).m_LinkedTriangles;

                // Shares edge AB if both triangles reference vertices A and B
                var edgeAB = vertexALinked.Intersect(vertexBLinked).Except(new int[] { i });
                var edgeBC = vertexBLinked.Intersect(vertexCLinked).Except(new int[] { i });
                var edgeCA = vertexCLinked.Intersect(vertexALinked).Except(new int[] { i });

                if (edgeAB.Count() > 0)
                {
                    m_Triangles[i].m_LinkedTriangles[(int)TriangleEdge.Edge_AB].AddRange(edgeAB);
                }
                if (edgeBC.Count() > 0)
                {
                    m_Triangles[i].m_LinkedTriangles[(int)TriangleEdge.Edge_BC].AddRange(edgeBC);
                }
                if (edgeCA.Count() > 0)
                {
                    m_Triangles[i].m_LinkedTriangles[(int)TriangleEdge.Edge_CA].AddRange(edgeCA);
                }
            }

            m_TrianglesToProcess.AddRange(m_Triangles);

            // Sort by number of neighbours
            if (!keepVertexOrderDuringStripping)
            {
                m_TrianglesToProcess.Sort((a, b) => GetNumLinked(a).CompareTo(GetNumLinked(b)));
            }

            List <ModelBase.FaceListDef> tStrips = new List <ModelBase.FaceListDef>();

            // For storing triangles that have no neighbours or don't end up in a strip
            ModelBase.FaceListDef separateTriangles = new ModelBase.FaceListDef(ModelBase.PolyListType.Triangles);

            TriangleLinked currentTriangle = null;

            while (m_TrianglesToProcess.Count > 0)
            {
                while (true)
                {
                    if (m_TrianglesToProcess.Count <= 0)
                    {
                        currentTriangle = null;
                        break;
                    }

                    currentTriangle = m_TrianglesToProcess[0];
                    m_TrianglesToProcess.RemoveAt(0);
                    if (currentTriangle.m_Marked)
                    {
                        continue;
                    }
                    else
                    {
                        break;
                    }
                }
                if (currentTriangle == null)
                {
                    break;
                }

                List <TriangleLinked>[] linked = GetLinked(currentTriangle);
                int numLinked = GetNumLinked(currentTriangle);

                currentTriangle.m_Marked = true;

                if (numLinked == 0)
                {
                    separateTriangles.m_Faces.Add(currentTriangle.m_Triangle);
                    continue;
                }

                // For each face build a strip off each of its edges and keep the longest one, discarding the
                // rest. Not part of SGI.
                Tuple <ModelBase.FaceListDef, List <int> > tStripAB =
                    GetStripAndIndicesForStartingEvenEdge(currentTriangle, TriangleEdge.Edge_AB);
                Tuple <ModelBase.FaceListDef, List <int> > tStripBC =
                    GetStripAndIndicesForStartingEvenEdge(currentTriangle, TriangleEdge.Edge_BC);
                Tuple <ModelBase.FaceListDef, List <int> > tStripCA =
                    GetStripAndIndicesForStartingEvenEdge(currentTriangle, TriangleEdge.Edge_CA);

                List <Tuple <ModelBase.FaceListDef, List <int> > > candidates = new List <Tuple <ModelBase.FaceListDef, List <int> > >()
                {
                    tStripAB, tStripBC, tStripCA
                };

                List <int> stripLengths = new List <int>();
                foreach (Tuple <ModelBase.FaceListDef, List <int> > strip in candidates)
                {
                    stripLengths.Add(strip.Item1.m_Faces.Count);
                }
                int longestStripIndex = stripLengths.IndexOf(stripLengths.Max());

                Tuple <ModelBase.FaceListDef, List <int> > longestStrip = candidates[longestStripIndex];

                if (longestStrip.Item1.m_Faces.Count == 0)
                {
                    separateTriangles.m_Faces.Add(currentTriangle.m_Triangle);
                    continue;
                }

                foreach (int tri in longestStrip.Item2)
                {
                    m_Triangles[tri].m_Marked = true;
                }

                tStrips.Add(longestStrip.Item1);
            }

            if (separateTriangles.m_Faces.Count > 0)
            {
                tStrips.Add(separateTriangles);
            }

            return(tStrips);
        }
Пример #6
0
        Tuple <ModelBase.FaceListDef, List <int> > GetStripAndIndicesForStartingEvenEdge(
            TriangleLinked start, TriangleEdge startForwardEdge)
        {
            List <int> stripIndices = new List <int>();
            List <TriangleRotation> stripRotations = new List <TriangleRotation>();

            List <TriangleLinked> linked        = GetLinked(start)[(int)startForwardEdge];
            TriangleLinked        bestNeighbour = DetermineBestNextNeighbour(start, linked, startForwardEdge);

            if (bestNeighbour == null)
            {
                return(new Tuple <ModelBase.FaceListDef, List <int> >(new ModelBase.FaceListDef(), new List <int>()));
            }

            TriangleRotation startRotation = (TriangleRotation)((int)(startForwardEdge - TriangleEdge.Edge_BC + 3) % 3);

            TriangleLinked   t               = start;
            TriangleEdge     currentEdge     = startForwardEdge;
            TriangleRotation currentRotation = startRotation;
            bool             even            = true;
            int index_t = -1;

            while (t != null && !stripIndices.Contains((index_t = m_Triangles.IndexOf(t))))
            {
                stripIndices.Add(index_t);
                stripRotations.Add(currentRotation);

                linked        = GetLinked(t)[(int)currentEdge];
                bestNeighbour = DetermineBestNextNeighbour(t, linked, currentEdge);

                t = bestNeighbour;

                even = !even;

                if (t != null)
                {
                    // Determine rotation and the edge to be used to get the next face

                    ModelBase.FaceDef triangleC_CW = new ModelBase.FaceDef(3);
                    if (even)
                    {
                        triangleC_CW.m_Vertices[0] = t.m_Triangle.m_Vertices[0];
                        triangleC_CW.m_Vertices[1] = t.m_Triangle.m_Vertices[1];
                        triangleC_CW.m_Vertices[2] = t.m_Triangle.m_Vertices[2];
                    }
                    else
                    {
                        triangleC_CW.m_Vertices[0] = t.m_Triangle.m_Vertices[2];
                        triangleC_CW.m_Vertices[1] = t.m_Triangle.m_Vertices[1];
                        triangleC_CW.m_Vertices[2] = t.m_Triangle.m_Vertices[0];
                    }

                    // The edge of the vertices which match the preceding triangle's
                    TriangleEdge linkBackEdge = TriangleEdge.Edge_AB;
                    // The vertices which match the preceding triangle's
                    ModelBase.VertexDef[] currentMatchedEdge = new ModelBase.VertexDef[2];
                    TriangleLinked        previous           = m_Triangles[stripIndices[stripIndices.Count - 1]];
                    currentMatchedEdge[0] = previous.m_Triangle.m_Vertices[(int)(currentEdge + 0) % 3];
                    currentMatchedEdge[1] = previous.m_Triangle.m_Vertices[(int)(currentEdge + 1) % 3];
                    // Find the edge in the current triangle which if odd has been made CW which matches
                    // that from the preceding triangle. This will be set as the current triangle's first,
                    // or 'AB' edge and the next edge (next two vertices) will be used to match the next
                    // triangle.
                    for (int i = 0; i < 3; i++)
                    {
                        ModelBase.VertexDef[] edge = new ModelBase.VertexDef[2];
                        edge[0] = triangleC_CW.m_Vertices[(i + 0) % 3];
                        edge[1] = triangleC_CW.m_Vertices[(i + 1) % 3];
                        if (edge.Except(currentMatchedEdge).Count() == 0)
                        {
                            linkBackEdge = (TriangleEdge)i;
                            break;
                        }
                    }

                    TriangleEdge nextEdgeNoC_CW = (TriangleEdge)((int)(linkBackEdge + 1) % 3);

                    TriangleEdge nextEdge = nextEdgeNoC_CW;
                    if (!even)
                    {
                        // If odd, nextEdgeNoC_CW points to the edge to be used if written CW, however
                        // all triangles have been read in as CCW so need to get the corresponding edge
                        // in CCW version.
                        ModelBase.VertexDef[] nextEdgeNoC_CW_Vertices = new ModelBase.VertexDef[2];
                        nextEdgeNoC_CW_Vertices[0] = triangleC_CW.m_Vertices[(int)(nextEdgeNoC_CW + 0) % 3];
                        nextEdgeNoC_CW_Vertices[1] = triangleC_CW.m_Vertices[(int)(nextEdgeNoC_CW + 1) % 3];
                        for (int i = 0; i < 3; i++)
                        {
                            ModelBase.VertexDef[] ccwEdge = new ModelBase.VertexDef[2];
                            ccwEdge[0] = t.m_Triangle.m_Vertices[(i + 0) % 3];
                            ccwEdge[1] = t.m_Triangle.m_Vertices[(i + 1) % 3];
                            if (nextEdgeNoC_CW_Vertices.Except(ccwEdge).Count() == 0)
                            {
                                nextEdge = (TriangleEdge)i;
                                break;
                            }
                        }
                    }

                    // Now we need to determine the required rotation of the current triangle so that for
                    // even triangles the new vertex in at index 0 and for odd triangles it occurs at
                    // index 2.
                    ModelBase.VertexDef uniqueVertex  = t.m_Triangle.m_Vertices.Except(previous.m_Triangle.m_Vertices).ElementAt(0);
                    int uniqueVertexIndex             = Array.IndexOf(t.m_Triangle.m_Vertices, uniqueVertex);
                    TriangleRotation requiredRotation =
                        (even) ? (TriangleRotation)((uniqueVertexIndex - 2 + 3) % 3) :
                        (TriangleRotation)(uniqueVertexIndex);

                    currentRotation = requiredRotation;
                    currentEdge     = nextEdge;

                    // To best understand how this works, debug and step-through how the following model is handled:
                    //
                    // An example:
                    // Faces as defined in model (all Counter-Clockwise (CCW)):
                    // f 1 2 3
                    // f 4 1 3
                    // f 4 5 1
                    // Build strip from edge CA.
                    // # 2 3 1 (LS)      <- Need to Left Shift vertices so that CA is the second edge (in a tri. strip it's
                    //                      always the second edge that's shared - see diagram at top).
                    // #   3 1 4 (4 1 3) <- For odd faces the new vertex must be at index [0]
                    //                      No Rot required, link-back CW: AB, CW forward: AB + 1 = BC,
                    //                      CCW forward: edge in CCW that contains vertices in (CW forward) = AB
                    //                      The next triangle is the one that shares the CCW edge AB (vertices 1 and 4)
                    // #     1 4 5 (RS)  <- Even face the new vertex needs to be in index [2] so need to Right Shift vertices
                    //                      Repeat steps as for above face but don't need to worry about converting between CCW and CW order
                }
            }

            ModelBase.FaceListDef tStrip = new ModelBase.FaceListDef(ModelBase.PolyListType.TriangleStrip);

            for (int i = 0; i < stripIndices.Count; i++)
            {
                TriangleRotation requiredRotation = (TriangleRotation)stripRotations[i];

                ModelBase.FaceDef rotated = new ModelBase.FaceDef(3);
                rotated.m_Vertices[0] = m_Triangles[stripIndices[i]].m_Triangle.m_Vertices[((int)(0 + requiredRotation) % 3)];
                rotated.m_Vertices[1] = m_Triangles[stripIndices[i]].m_Triangle.m_Vertices[((int)(1 + requiredRotation) % 3)];
                rotated.m_Vertices[2] = m_Triangles[stripIndices[i]].m_Triangle.m_Vertices[((int)(2 + requiredRotation) % 3)];

                tStrip.m_Faces.Add(rotated);
            }

            return(new Tuple <ModelBase.FaceListDef, List <int> >(tStrip, stripIndices));
        }
Пример #7
0
        Tuple<ModelBase.FaceListDef, List<int>> GetStripAndIndicesForStartingEvenEdge(
            TriangleLinked start, TriangleEdge startForwardEdge)
        {
            List<int> stripIndices = new List<int>();
            List<TriangleRotation> stripRotations = new List<TriangleRotation>();

            List<TriangleLinked> linked = GetLinked(start)[(int)startForwardEdge];
            TriangleLinked bestNeighbour = DetermineBestNextNeighbour(start, linked, startForwardEdge);

            if (bestNeighbour == null)
                return new Tuple<ModelBase.FaceListDef, List<int>>(new ModelBase.FaceListDef(), new List<int>());

            TriangleRotation startRotation = (TriangleRotation)((int)(startForwardEdge - TriangleEdge.Edge_BC + 3) % 3);

            TriangleLinked t = start;
            TriangleEdge currentEdge = startForwardEdge;
            TriangleRotation currentRotation = startRotation;
            bool even = true;
            int index_t = -1;
            while (t != null && !stripIndices.Contains((index_t = m_Triangles.IndexOf(t))))
            {
                stripIndices.Add(index_t);
                stripRotations.Add(currentRotation);

                linked = GetLinked(t)[(int)currentEdge];
                bestNeighbour = DetermineBestNextNeighbour(t, linked, currentEdge);

                t = bestNeighbour;

                even = !even;

                if (t != null)
                {
                    // Determine rotation and the edge to be used to get the next face

                    ModelBase.FaceDef triangleC_CW = new ModelBase.FaceDef(3);
                    if (even)
                    {
                        triangleC_CW.m_Vertices[0] = t.m_Triangle.m_Vertices[0];
                        triangleC_CW.m_Vertices[1] = t.m_Triangle.m_Vertices[1];
                        triangleC_CW.m_Vertices[2] = t.m_Triangle.m_Vertices[2];
                    }
                    else
                    {
                        triangleC_CW.m_Vertices[0] = t.m_Triangle.m_Vertices[2];
                        triangleC_CW.m_Vertices[1] = t.m_Triangle.m_Vertices[1];
                        triangleC_CW.m_Vertices[2] = t.m_Triangle.m_Vertices[0];
                    }

                    // The edge of the vertices which match the preceding triangle's
                    TriangleEdge linkBackEdge = TriangleEdge.Edge_AB;
                    // The vertices which match the preceding triangle's
                    ModelBase.VertexDef[] currentMatchedEdge = new ModelBase.VertexDef[2];
                    TriangleLinked previous = m_Triangles[stripIndices[stripIndices.Count - 1]];
                    currentMatchedEdge[0] = previous.m_Triangle.m_Vertices[(int)(currentEdge + 0) % 3];
                    currentMatchedEdge[1] = previous.m_Triangle.m_Vertices[(int)(currentEdge + 1) % 3];
                    // Find the edge in the current triangle which if odd has been made CW which matches
                    // that from the preceding triangle. This will be set as the current triangle's first,
                    // or 'AB' edge and the next edge (next two vertices) will be used to match the next
                    // triangle.
                    for (int i = 0; i < 3; i++)
                    {
                        ModelBase.VertexDef[] edge = new ModelBase.VertexDef[2];
                        edge[0] = triangleC_CW.m_Vertices[(i + 0) % 3];
                        edge[1] = triangleC_CW.m_Vertices[(i + 1) % 3];
                        if (edge.Except(currentMatchedEdge).Count() == 0)
                        {
                            linkBackEdge = (TriangleEdge)i;
                            break;
                        }
                    }

                    TriangleEdge nextEdgeNoC_CW = (TriangleEdge)((int)(linkBackEdge + 1) % 3);

                    TriangleEdge nextEdge = nextEdgeNoC_CW;
                    if (!even)
                    {
                        // If odd, nextEdgeNoC_CW points to the edge to be used if written CW, however
                        // all triangles have been read in as CCW so need to get the corresponding edge
                        // in CCW version.
                        ModelBase.VertexDef[] nextEdgeNoC_CW_Vertices = new ModelBase.VertexDef[2];
                        nextEdgeNoC_CW_Vertices[0] = triangleC_CW.m_Vertices[(int)(nextEdgeNoC_CW + 0) % 3];
                        nextEdgeNoC_CW_Vertices[1] = triangleC_CW.m_Vertices[(int)(nextEdgeNoC_CW + 1) % 3];
                        for (int i = 0; i < 3; i++)
                        {
                            ModelBase.VertexDef[] ccwEdge = new ModelBase.VertexDef[2];
                            ccwEdge[0] = t.m_Triangle.m_Vertices[(i + 0) % 3];
                            ccwEdge[1] = t.m_Triangle.m_Vertices[(i + 1) % 3];
                            if (nextEdgeNoC_CW_Vertices.Except(ccwEdge).Count() == 0)
                            {
                                nextEdge = (TriangleEdge)i;
                                break;
                            }
                        }
                    }

                    // Now we need to determine the required rotation of the current triangle so that for
                    // even triangles the new vertex in at index 0 and for odd triangles it occurs at
                    // index 2.
                    ModelBase.VertexDef uniqueVertex = t.m_Triangle.m_Vertices.Except(previous.m_Triangle.m_Vertices).ElementAt(0);
                    int uniqueVertexIndex = Array.IndexOf(t.m_Triangle.m_Vertices, uniqueVertex);
                    TriangleRotation requiredRotation =
                        (even) ? (TriangleRotation)((uniqueVertexIndex - 2 + 3) % 3) :
                        (TriangleRotation)(uniqueVertexIndex);

                    currentRotation = requiredRotation;
                    currentEdge = nextEdge;

                    // To best understand how this works, debug and step-through how the following model is handled:
                    //
                    // An example:
                    // Faces as defined in model (all Counter-Clockwise (CCW)):
                    // f 1 2 3
                    // f 4 1 3
                    // f 4 5 1
                    // Build strip from edge CA.
                    // # 2 3 1 (LS)      <- Need to Left Shift vertices so that CA is the second edge.
                    // #   3 1 4 (4 1 3) <- For odd faces the new vertex must be at index [0]
                    //                      No Rot required, link-back CW: AB, CW forward: AB + 1 = BC,
                    //                      CCW forward: edge in CCW that contains vertices in (CW forward) = AB
                    //                      The next triangle is the one that shares the CCW edge AB (vertices 1 and 4)
                    // #     1 4 5 (RS)  <- Even face the new vertex needs to be in index [2] so need to Right Shift vertices
                    //                      Repeat steps as for above face but don't need to worry about converting between CCW and CW order
                }

            }

            ModelBase.FaceListDef tStrip = new ModelBase.FaceListDef(ModelBase.PolyListType.TriangleStrip);

            even = true;
            for (int i = 0; i < stripIndices.Count; i++)
            {
                TriangleRotation requiredRotation = (TriangleRotation)stripRotations[i];

                ModelBase.FaceDef rotated = new ModelBase.FaceDef(3);
                rotated.m_Vertices[0] = m_Triangles[stripIndices[i]].m_Triangle.m_Vertices[((int)(0 + requiredRotation) % 3)];
                rotated.m_Vertices[1] = m_Triangles[stripIndices[i]].m_Triangle.m_Vertices[((int)(1 + requiredRotation) % 3)];
                rotated.m_Vertices[2] = m_Triangles[stripIndices[i]].m_Triangle.m_Vertices[((int)(2 + requiredRotation) % 3)];

                tStrip.m_Faces.Add(rotated);

                even = !even;
            }

            return new Tuple<ModelBase.FaceListDef, List<int>>(tStrip, stripIndices);
        }
Пример #8
0
 private int GetNumLinked(TriangleLinked triangle)
 {
     List<TriangleLinked>[] linked = GetLinked(triangle);
     int count = 0;
     for (int i = 0; i < 3; i++)
     {
         count += linked[i].Count;
     }
     return count;
 }
Пример #9
0
        private List<TriangleLinked>[] GetLinked(TriangleLinked triangle)
        {
            List<TriangleLinked>[] linked = new List<TriangleLinked>[3];

            for (int i = 0; i < 3; i++)
            {
                List<int> linkedIndices = triangle.m_LinkedTriangles[i];
                for (int j = 0; j < linkedIndices.Count; j++)
                {
                    // Make sure it doesn't count itself as a neighbour
                    if (m_Triangles[m_Triangles.IndexOf(triangle)].Equals(linkedIndices[j]))
                    {
                        linkedIndices.RemoveAt(j);
                        continue;
                    }
                    // Ignore marked triangles (already in a strip)
                    if (m_Triangles[linkedIndices[j]].m_Marked)
                    {
                        linkedIndices.RemoveAt(j);
                        continue;
                    }
                }
                linked[i] = new List<TriangleLinked>();
                for (int j = 0; j < linkedIndices.Count; j++)
                {
                    linked[i].Add(m_Triangles[linkedIndices[j]]);
                }
            }

            return linked;
        }
Пример #10
0
        private TriangleLinked DetermineBestNextNeighbour(TriangleLinked triangle, List<TriangleLinked> neighbours, TriangleEdge edge, 
            bool tieBreak = false)
        {
            if (neighbours.Count == 0) return null;

            if (neighbours.Count == 1) return neighbours[0];

            neighbours.Sort((a, b) => GetNumLinked(a).CompareTo(GetNumLinked(b)));

            TriangleLinked[] twoTop = new TriangleLinked[2];
            twoTop[0] = neighbours[0]; twoTop[1] = neighbours[1];

            int[] numLinkedOfNeighbours = new int[] { GetNumLinked(twoTop[0]), GetNumLinked(twoTop[1]) };

            if (numLinkedOfNeighbours[0] < numLinkedOfNeighbours[1])
            {
                return twoTop[0];
            }
            else if (numLinkedOfNeighbours[1] < numLinkedOfNeighbours[0])
            {
                return twoTop[1];
            }
            else if (!tieBreak)
            {
                List<TriangleLinked> firstLinked = GetLinked(twoTop[0])[(int)edge];
                List<TriangleLinked> secondLinked = GetLinked(twoTop[1])[(int)edge];

                TriangleLinked firstBest = DetermineBestNextNeighbour(twoTop[0], firstLinked, edge, true);
                TriangleLinked secondBest = DetermineBestNextNeighbour(twoTop[1], secondLinked, edge, true);

                if (GetNumLinked(firstBest) < GetNumLinked(secondBest))
                    return twoTop[0];
                else
                    return twoTop[1];
            }
            else if (tieBreak)
            {
                return twoTop[0];
            }
            else
            {
                return null;
            }
        }