/// <summary> /// Gets the next safe edge for the mst /// </summary> /// <param name="parents"></param> /// <returns></returns> private VertexPair GetNextSafeEdge(Dictionary <Vertex, Vertex> parents) { List <VertexPair> safeEdges = new List <VertexPair>(); foreach (var kV in connectedVertices) { foreach (var vertex in kV.Value) { Vertex v0 = kV.Key; Vertex v1 = vertex; // If one vertex is a part of the mst, and one is not if ((parents[v0] == null && parents[v1] != null) || (parents[v1] == null && parents[v0] != null)) { safeEdges.Add(new VertexPair(v0, v1)); } } } // Find the safe edge with the smallest distance VertexPair closestSafeEdge = null; float smallestDistance = float.PositiveInfinity; foreach (var edge in safeEdges) { float distance = EdgeLength(edge); if (distance < smallestDistance) { closestSafeEdge = edge; smallestDistance = distance; } } return(closestSafeEdge); }
/// <summary> /// Calculate length of an edge /// </summary> /// <param name="edge"></param> /// <returns></returns> public float EdgeLength(VertexPair edge) { Vector2 vec1 = new Vector2((float)edge.v0.X, (float)edge.v0.Y); Vector2 vec2 = new Vector2((float)edge.v1.X, (float)edge.v1.Y); return(Vector2.Distance(vec2, vec1)); }
/// <summary> /// Remove long and short edges from the connections so we don't choose really long or stubby connections accidentally /// </summary> /// <param name="num"></param> private void RemoveLongShortEdges(int num) { num = Mathf.RoundToInt(num / 2f); for (int i = 0; i < num; i++) { float longestLength = 0; VertexPair longestEdge = null; float shortestLength = float.PositiveInfinity; VertexPair shortestEdge = null; foreach (var kV in triangulator.connectedVertices) { foreach (var vertex in kV.Value) { VertexPair edge = new VertexPair(kV.Key, vertex); float distance = triangulator.EdgeLength(edge); if (distance > longestLength) { longestLength = distance; longestEdge = edge; } if (distance < shortestLength) { shortestLength = distance; shortestEdge = edge; } } } triangulator.connectedVertices[longestEdge.v1].Remove(longestEdge.v0); triangulator.connectedVertices[longestEdge.v0].Remove(longestEdge.v1); triangulator.connectedVertices[shortestEdge.v1].Remove(shortestEdge.v0); triangulator.connectedVertices[shortestEdge.v0].Remove(shortestEdge.v1); } }
/// <summary> /// Get the DungeonLevel graph from a list of vectors /// </summary> /// <param name="vectors"></param> /// <param name="connectedness"></param> Determines how connected the DungeonLevel is - 0.0 being a minimum spanning tree /// <returns></returns> public Dictionary <Vector2Int, List <Vector2Int> > GetDungeonMap(List <Vector2Int> vectors, float connectedness) { triangulator = new Triangulator(); triangulator.GenerateMst(vectors); dungeonExits = FindStartAndEnd(); // Prime mst to be more like DungeonLevel hallways RemoveMstFromGraph(); RemoveLongShortEdges(Mathf.RoundToInt(triangulator.connectedVertices.Count / 3f)); AddRandomEdgesToMst(Mathf.RoundToInt(triangulator.connectedVertices.Count * connectedness)); // Convert back to vectors Dictionary <Vector2Int, List <Vector2Int> > links = new Dictionary <Vector2Int, List <Vector2Int> >(); foreach (var kV in triangulator.mst) { List <Vector2Int> adj = new List <Vector2Int>(); foreach (var vertex in kV.Value) { adj.Add(new Vector2Int(Mathf.RoundToInt((float)vertex.X), Mathf.RoundToInt((float)vertex.Y))); } links.Add(new Vector2Int(Mathf.RoundToInt((float)kV.Key.X), Mathf.RoundToInt((float)kV.Key.Y)), adj); } return(links); }
private void Render() { for (int p = 0; p < generator.IterableVertices.Count; p++) { generator.IterableVertices[p].isFaded = true; } for (int p = 0; p < added.Count; p++) { added[p].isFaded = false; } List <VertexPair> vertexPairs = new List <VertexPair>(); for (int t = 0; t < container.Count; t++) { Triangle tri = container[t]; var e1 = new VertexPair(tri.a, tri.b); var e2 = new VertexPair(tri.b, tri.c); var e3 = new VertexPair(tri.c, tri.a); if (tri.isHighlighted) { e1.isHighlighted = true; e2.isHighlighted = true; e3.isHighlighted = true; } vertexPairs.Add(e1); vertexPairs.Add(e2); vertexPairs.Add(e3); } for (int i = 0; i < vertexPairs.Count; i++) { if (i >= edges.Count) { Edge edge = Instantiate(edgePrefab).GetComponent <Edge>(); edges.Add(edge); } edges[i].Point1 = vertexPairs[i].a; edges[i].Point2 = vertexPairs[i].b; edges[i].transform.SetParent(transform); edges[i].isHighlighted = vertexPairs[i].isHighlighted; edges[i].gameObject.SetActive(true); } for (int i = vertexPairs.Count; i < edges.Count; i++) { edges[i].gameObject.SetActive(false); } }
internal Triangle FindNeighbor(Triangle triangle, VertexPair edge) { foreach (var t in triangles) { if (t.IsNeighbor(edge) && t != triangle) { return(t); } } return(null); }
/// given a vertex in the graph, find its upper and lower neighbor vertices protected Tuple <Vertex, Vertex> find_neighbor_vertices(VertexPair v_pair, Interval ival) { Interval.VertexPairIterator itr = ival.intersections2.lower_bound(v_pair); // returns first that is not less than argument (equal or greater) Debug.Assert(itr != ival.intersections2.end()); // we must find a lower_bound Interval.VertexPairIterator v_above = itr; // lower_bound returns one beyond the give key, i.e. what we want Interval.VertexPairIterator v_below = --itr; // this is the vertex below the give vertex Tuple <Vertex, Vertex> @out = new Tuple <Vertex, Vertex>(null, null); @out.Item1 = v_above.first; // vertex above v (xu) @out.Item2 = v_below.first; // vertex below v (xl) Debug.Assert(@out.Item1 != @out.Item2); return(new Tuple <Vertex, Vertex>(@out.Item1, @out.Item2)); }
/// <summary> /// Generates the DungeonLevel and writes it to the map 2d array /// </summary> private void GenerateDungeon() { DungeonMst dungeonMst = new DungeonMst(); RoomGenerator roomGenerator = new RoomGenerator(); rooms = roomGenerator.GenerateRooms( DungeonLevel.InitialRoomDensity, DungeonLevel.Width, DungeonLevel.Height, new Vector2Int(DungeonLevel.MinRoomHeight, DungeonLevel.MaxRoomHeight), new Vector2Int(DungeonLevel.MinRoomWidth, DungeonLevel.MaxRoomWidth) ); links = dungeonMst.GetDungeonMap(rooms.Keys.ToList(), DungeonLevel.RoomConnectedness); LinksIntoHallways(); dungeonExits = dungeonMst.dungeonExits; // Adds hubs foreach (var room in rooms.Values) { WriteRoomToMap(room); } foreach (var edge in hallways) { WriteEdgeToMap(edge); } CellularAutomata caveGen = new CellularAutomata(DungeonLevel); List <List <Vector2Int> > caveRooms = caveGen.Generate(); foreach (var caveRoom in caveRooms) { foreach (var tile in caveRoom) { map[tile.x, tile.y] = Tiles.caveTile; } } // Place the physical objects into the world PlaceExits(); AddFloorsAndWalls(); PlaceDoors(); foreach (WeightedGeneratedStructure type in DungeonLevel.generatedStructures) { PlaceGeneratedStructures(type.structure, type.amountPerLevel); } PlaceObjects(PlaceChest, DungeonLevel.ChestsPerLevel); PlaceObjects(PlaceDecorObjects, DungeonLevel.FreeStandingDecorationCount); PlaceObjects(PlaceEnemy, DungeonLevel.EnemiesPerLevel); PlaceObjects(PlaceDestrucibleObjects, DungeonLevel.DestructibleObjectCount); }
Edge addEdge(Vertex v0, Vertex v1) { var pair = new VertexPair(v0, v1); if (edges.TryGetValue(pair, out var found)) { return(found); } var result = new Edge(); result.a = v0; result.b = v1; edges.Add(pair, result); return(result); }
internal Vertex OppositeVertex(VertexPair edge) { if (a != edge.a && a != edge.b) { return(a); } else if (b != edge.a && b != edge.b) { return(b); } else if (c != edge.a && c != edge.b) { return(c); } return(null); }
/// <summary> /// Shuffles the vertex indices so the two vertex indices contained in the given vertex pair correspond with Vertex0Index and Vertex1Index. /// </summary> /// <param name="vertexPair">The vertex pair whose vertex indices we want up front.</param> public void ShuffleVertexIndices(VertexPair vertexPair) { if (new VertexPair(vertex1Index, vertex2Index) == vertexPair) { int temp = vertex1Index; vertex1Index = vertex2Index; vertex2Index = vertex0Index; vertex0Index = temp; } else if (new VertexPair(vertex0Index, vertex2Index) == vertexPair) { int temp = vertex2Index; vertex2Index = vertex1Index; vertex1Index = vertex0Index; vertex0Index = temp; } }
/// <summary> /// Add in some edges back to make the DungeonLevel more connected /// </summary> /// <param name="num"></param> private void AddRandomEdgesToMst(int num) { for (int i = 0; i < num; i++) { List <VertexPair> allEdges = new List <VertexPair>(); foreach (var kV in triangulator.connectedVertices) { foreach (var vertex in kV.Value) { allEdges.Add(new VertexPair(kV.Key, vertex)); } } VertexPair randomEdge = allEdges[Random.Range(0, allEdges.Count)]; triangulator.mst[randomEdge.v0].Add(randomEdge.v1); triangulator.mst[randomEdge.v1].Add(randomEdge.v0); } }
private IEnumerator MakeDelaunay(Triangle triangle, VertexPair edge, Vertex point) { Triangle neighbor = container.FindNeighbor(triangle, edge); if (neighbor != null) { if (neighbor.PointInCircumcircle(point)) { triangle.isHighlighted = true; neighbor.isHighlighted = true; yield return(new WaitForSecondsRealtime(speed)); container.Remove(triangle); container.Remove(neighbor); Vertex n = neighbor.OppositeVertex(edge); Triangle t1 = new Triangle(n, edge.a, point); Triangle t2 = new Triangle(n, edge.b, point); t1.isHighlighted = true; t2.isHighlighted = true; container.Add(t1); container.Add(t2); yield return(new WaitForSecondsRealtime(speed)); t1.isHighlighted = false; t2.isHighlighted = false; yield return(MakeDelaunay(t1, new VertexPair(n, edge.a), point)); yield return(MakeDelaunay(t2, new VertexPair(n, edge.b), point)); } } else { //Debug.Log("No neighbor!"); } yield return(null); }
// given a VertexPair and an Interval, in the Interval find the Vertex above and below the given vertex protected Tuple <Vertex, Vertex> find_neighbor_vertices(VertexPair v_pair, Interval ival, bool above_equality) { Interval.VertexPairIterator itr = ival.intersections2.lower_bound(v_pair); // returns first that is not less than argument (equal or greater) Debug.Assert(itr != ival.intersections2.end()); // we must find a lower_bound Interval.VertexPairIterator v_above = new Interval.VertexPairIterator(); if (above_equality) { //C++ TO C# CONVERTER TODO TASK: The following line was determined to be a copy assignment (rather than a reference assignment) - this should be verified and a 'CopyFrom' method should be created: //ORIGINAL LINE: v_above = itr; v_above.CopyFrom(itr); // lower_bound returns one beyond the give key, i.e. what we want } else { v_above = ++itr; --itr; } Interval.VertexPairIterator v_below = --itr; // this is the vertex below the given vertex Tuple <Vertex, Vertex> @out = new Tuple <Vertex, Vertex>(null, null); @out.Item1 = v_above.first; // vertex above v (xu) @out.Item2 = v_below.first; // vertex below v (xl) return(new Tuple <Vertex, Vertex>(@out.Item1, @out.Item2)); }
private VertexPair Split(Vertex root, int key) { VertexPair result = new VertexPair(); VertexPair findAndRoot = FindInRoot(root, key); root = findAndRoot.Right; result.Right = findAndRoot.Left; if (result.Right == null) { result.Left = root; return(result); } result.Right = Splay(result.Right); result.Left = result.Right.Left; result.Right.Left = null; if (result.Left != null) { result.Left.Parent = null; } Update(result.Left); Update(result.Right); return(result); }
/// <summary> /// Find the mst of the triangulated vertices /// </summary> /// <returns></returns> private void JarnikPrimsMst() { // Keeps track of the parents for every vertex Dictionary <Vertex, Vertex> parents = new Dictionary <Vertex, Vertex>(); mst = new Dictionary <Vertex, List <Vertex> >(); foreach (var vertex in connectedVertices.Keys) { parents.Add(vertex, null); } Vertex root = mesh.vertices[0]; parents[root] = root; // Make the root's parent not null mst.Add(root, new List <Vertex>()); while (mst.Count < connectedVertices.Count) { VertexPair edge = GetNextSafeEdge(parents); //Add the new vertex - it has to be one or the other if (mst.ContainsKey(edge.v0)) { mst.Add(edge.v1, new List <Vertex>()); parents[edge.v1] = edge.v0; } else { mst.Add(edge.v0, new List <Vertex>()); parents[edge.v0] = edge.v1; } //Add the edge that connects the two mst[edge.v0].Add(edge.v1); mst[edge.v1].Add(edge.v0); } }
internal bool IsNeighbor(VertexPair edge) { return((a == edge.a || b == edge.a || c == edge.a) && (a == edge.b || b == edge.b || c == edge.b)); }
public LogFailureVerbose(VertexPair n, ReadOnlyCollection <VertexPair> fn) : base(n) { FailureNotifications = fn; }
private void Contract(int targetTriangles, IProgressListener listener = null) { SelectValidPairs(); if (listener != null) { listener.OnStarted("Compacting"); } int totalTriangles = m_Faces.Count - targetTriangles; int currentTriangle = 0; while (m_Faces.Count > targetTriangles) { if (listener != null) { listener.OnStep(currentTriangle, totalTriangles); } ++currentTriangle; double minError = (double)int.MaxValue; //KeyValuePair<VertexPair, double> min; VertexPair minPair = new VertexPair() { First = 0, Second = 0 }; foreach (KeyValuePair<VertexPair, double> e in m_Errors) { if (e.Value < minError) { minError = e.Value; minPair = e.Key; } } Vector3 error; ComputeError(minPair.First, minPair.Second, out error); #if false VertexSplit split = new VertexSplit(); //var fv split.First.Position = m_Vertices[minPair.First].Position; split.Second.Position = m_Vertices[minPair.Second].Position; split.Target.Position = error; m_Splits.Add(split); #endif var vertex = m_Vertices[minPair.First]; vertex.Position = error; m_Quadrics[minPair.First] = m_Quadrics[minPair.First] + m_Quadrics[minPair.Second]; for (int i = m_Faces.Count - 1; i != 0; ) { var face = m_Faces[i]; for (int j = 0; j < 3; ++j) { if (face[j] == minPair.Second) { if (face[0] == minPair.First || face[1] == minPair.First || face[2] == minPair.First) { m_Faces.Remove(face); } else { face[j] = minPair.First; } --i; break; } else if (j == 2) { --i; } } } m_Vertices.Remove(minPair.Second); KeyValuePair<VertexPair, double> pair; #if false for (int iter = m_Errors.Count - 1; iter != 0; ) { pair = m_Errors.ElementAt(iter); if (pair.Key.First == minPair.Second && pair.Key.Second != minPair.First) { m_Errors.Remove(m_Errors.ElementAt(iter).Key); m_Errors.Add( new VertexPair() { First = Math.Min(minPair.First, pair.Key.Second), Second = Math.Max(minPair.First, pair.Key.Second) }, 0.0); --iter; } else if (pair.Key.Second == minPair.Second && pair.Key.First != minPair.First) { m_Errors.Remove(m_Errors.ElementAt(iter).Key); m_Errors.Add( new VertexPair() { First = Math.Min(minPair.First, pair.Key.First), Second = Math.Max(minPair.First, pair.Key.First) }, 0.0); --iter; } else { --iter; } } #else for (int it = 0; it < m_Errors.Count; ++it) { pair = m_Errors.ElementAt(it); if (pair.Key.First == minPair.Second && pair.Key.Second != minPair.First) { m_Errors.Remove(m_Errors.ElementAt(it).Key); var key = new VertexPair() { First = Math.Min(minPair.First, pair.Key.Second), Second = Math.Max(minPair.First, pair.Key.Second) }; if (!m_Errors.ContainsKey(key)) { m_Errors.Add( key, 0.0); } } else if (pair.Key.Second == minPair.Second && pair.Key.First != minPair.First) { m_Errors.Remove(m_Errors.ElementAt(it).Key); var key = new VertexPair() { First = Math.Min(minPair.First, pair.Key.First), Second = Math.Max(minPair.First, pair.Key.First) }; if (!m_Errors.ContainsKey(key)) { m_Errors.Add( key, 0.0); } } } #endif m_Errors.Remove(minPair); for (int it = 0; it < m_Errors.Count; ++it) { var key = m_Errors.ElementAt(it).Key; if (key.First == minPair.First) { m_Errors[key] = ComputeError(minPair.First, key.Second); } if (key.Second == minPair.First) { m_Errors[key] = ComputeError(minPair.First, key.First); } } /*foreach (var e in m_Errors) { var p = e.Key; if (p.First == minPair.First) { m_Errors[p] = ComputeError(minPair.First, p.Second); } if (p.Second == minPair.First) { m_Errors[p] = ComputeError(minPair.First, p.First); } }*/ } if (listener != null) { listener.OnComplete("Compacting"); } }
/// <summary> /// Returns whether the given vertex pair is considered equal to this object. /// </summary> /// <param name="other">The other vertex pair.</param> /// <returns>Whether the given vertex pair is considered equal to this object.</returns> public bool Equals(VertexPair other) { return (((vertex0Index == other.vertex0Index) && (vertex1Index == other.vertex1Index)) || ((vertex0Index == other.vertex1Index) && (vertex1Index == other.vertex0Index))); }
static void RepairSector(SECTORS sector, List <Line> lines) { if (lines.Count < 2) { // sector with a single line, don't repair return; } // generate a list of all vertices List <Vertex> vertices = new List <Vertex>(); foreach (Line line in lines) { if (!vertices.Contains(line.vertices[0])) { vertices.Add(line.vertices[0]); } if (!vertices.Contains(line.vertices[1])) { vertices.Add(line.vertices[1]); } } // find all vertices that only have one line List <Vertex> loneVertices = new List <Vertex>(); foreach (Vertex vertex in vertices) { int count = 0; foreach (Line line in lines) { if (line.vertices.Contains(vertex)) { count++; } } if (count < 2) { loneVertices.Add(vertex); } } if (loneVertices.Count == 0) { // nothing wrong here return; } Debug.Log("BAD SECTOR: " + sector.sectorIndex); // find lines that intersect foreach (Line line1 in lines) { foreach (Line line2 in lines) { if (line1 == line2) { continue; } Vertex intersect = line1.Intersection(line2); if (intersect == null) { continue; } Debug.Log("REPAIRING: intersection, SECTOR: " + sector.sectorIndex); // find closest vertex to intersection point Vertex closestVertex = line1.vertices[0]; foreach (Vertex vertex in line1.vertices) { if (vertex.DistanceTo(intersect) < closestVertex.DistanceTo(intersect)) { closestVertex = vertex; } } foreach (Vertex vertex in line2.vertices) { if (vertex.DistanceTo(intersect) < closestVertex.DistanceTo(intersect)) { closestVertex = vertex; } } // move closest to intersection point closestVertex.x = intersect.x; closestVertex.y = intersect.y; // replace closest line1 vertex with closest vertex if (line1.vertices[0].DistanceTo(intersect) < line1.vertices[1].DistanceTo(intersect)) { line1.vertices[0] = closestVertex; loneVertices.Remove(line1.vertices[0]); } else { line1.vertices[1] = closestVertex; loneVertices.Remove(line1.vertices[1]); } // replace closest line2 vertex with closest vertex if (line2.vertices[0].DistanceTo(intersect) < line2.vertices[1].DistanceTo(intersect)) { line2.vertices[0] = closestVertex; loneVertices.Remove(line2.vertices[0]); } else { line2.vertices[1] = closestVertex; loneVertices.Remove(line2.vertices[1]); } } } if (loneVertices.Count == 0) { // sector was repaired return; } // generate every combination of vertices in pairs SortedList <double, VertexPair> pairs = new SortedList <double, VertexPair>(); foreach (Vertex v1 in loneVertices) { foreach (Vertex v2 in loneVertices) { if (v1 == v2) { continue; } // make sure pair is unique foreach (VertexPair pair in pairs.Values) { if (pair.vertices.Contains(v1) && pair.vertices.Contains(v2)) { goto nextPair; } } VertexPair vertexPair = new VertexPair(v1, v2); double dist = vertexPair.Distance(); while (pairs.ContainsKey(dist)) { dist += 0.001; } pairs.Add(dist, vertexPair); nextPair :; } } // generate a line for every pair, sorted by distance while (pairs.Count > 0) { // grab a pair with the least distance between them VertexPair pair = pairs.Values.First(); pairs.RemoveAt(0); // generate the line between the two vertices Line line = new Line(pair.vertices[0], pair.vertices[1], false, false); // check for collision foreach (Line line2 in lines) { if (line.Intersects(line2)) { goto nextPair; } } // add the line to the list lines.Add(line); Debug.Log("REPAIRING: missing line, SECTOR: " + sector.sectorIndex); Debug.DrawLine(new Vector3((float)pair.vertices[0].x, 0, (float)pair.vertices[0].y), new Vector3((float)pair.vertices[1].x, 0, (float)pair.vertices[1].y), Color.red, 10000); // remove any pairs that contain a shared vertex to this one for (int i = 0; i < pairs.Count; i++) { if (pairs.Values[i].vertices.Contains(pair.vertices[0]) || pairs.Values[i].vertices.Contains(pair.vertices[1])) { pairs.RemoveAt(i); i--; continue; } } nextPair :; } }
public LogFailure(VertexPair n) { Notification = n; }
/// comparison operator //C++ TO C# CONVERTER WARNING: 'const' methods are not available in C#: //ORIGINAL LINE: bool operator ()(const VertexPair& lhs, const VertexPair& rhs) const public static bool functorMethod(VertexPair lhs, VertexPair rhs) { return(lhs.second < rhs.second); }
protected bool Equals(VertexPair other) { return(Vertex1 == other.Vertex1 && Vertex2 == other.Vertex2); }
private void Contract(int targetTriangles, IProgressListener listener = null) { SelectValidPairs(); if (listener != null) { listener.OnStarted("Compacting"); } int totalTriangles = m_Faces.Count - targetTriangles; int currentTriangle = 0; while (m_Faces.Count > targetTriangles) { if (listener != null) { listener.OnStep(currentTriangle, totalTriangles); } ++currentTriangle; double minError = (double)int.MaxValue; //KeyValuePair<VertexPair, double> min; VertexPair minPair = new VertexPair() { First = 0, Second = 0 }; foreach (KeyValuePair <VertexPair, double> e in m_Errors) { if (e.Value < minError) { minError = e.Value; minPair = e.Key; } } Vector3 error; ComputeError(minPair.First, minPair.Second, out error); #if false VertexSplit split = new VertexSplit(); //var fv split.First.Position = m_Vertices[minPair.First].Position; split.Second.Position = m_Vertices[minPair.Second].Position; split.Target.Position = error; m_Splits.Add(split); #endif var vertex = m_Vertices[minPair.First]; vertex.Position = error; m_Quadrics[minPair.First] = m_Quadrics[minPair.First] + m_Quadrics[minPair.Second]; for (int i = m_Faces.Count - 1; i != 0;) { var face = m_Faces[i]; for (int j = 0; j < 3; ++j) { if (face[j] == minPair.Second) { if (face[0] == minPair.First || face[1] == minPair.First || face[2] == minPair.First) { m_Faces.Remove(face); } else { face[j] = minPair.First; } --i; break; } else if (j == 2) { --i; } } } m_Vertices.Remove(minPair.Second); KeyValuePair <VertexPair, double> pair; #if false for (int iter = m_Errors.Count - 1; iter != 0;) { pair = m_Errors.ElementAt(iter); if (pair.Key.First == minPair.Second && pair.Key.Second != minPair.First) { m_Errors.Remove(m_Errors.ElementAt(iter).Key); m_Errors.Add( new VertexPair() { First = Math.Min(minPair.First, pair.Key.Second), Second = Math.Max(minPair.First, pair.Key.Second) }, 0.0); --iter; } else if (pair.Key.Second == minPair.Second && pair.Key.First != minPair.First) { m_Errors.Remove(m_Errors.ElementAt(iter).Key); m_Errors.Add( new VertexPair() { First = Math.Min(minPair.First, pair.Key.First), Second = Math.Max(minPair.First, pair.Key.First) }, 0.0); --iter; } else { --iter; } } #else for (int it = 0; it < m_Errors.Count; ++it) { pair = m_Errors.ElementAt(it); if (pair.Key.First == minPair.Second && pair.Key.Second != minPair.First) { m_Errors.Remove(m_Errors.ElementAt(it).Key); var key = new VertexPair() { First = Math.Min(minPair.First, pair.Key.Second), Second = Math.Max(minPair.First, pair.Key.Second) }; if (!m_Errors.ContainsKey(key)) { m_Errors.Add( key, 0.0); } } else if (pair.Key.Second == minPair.Second && pair.Key.First != minPair.First) { m_Errors.Remove(m_Errors.ElementAt(it).Key); var key = new VertexPair() { First = Math.Min(minPair.First, pair.Key.First), Second = Math.Max(minPair.First, pair.Key.First) }; if (!m_Errors.ContainsKey(key)) { m_Errors.Add( key, 0.0); } } } #endif m_Errors.Remove(minPair); for (int it = 0; it < m_Errors.Count; ++it) { var key = m_Errors.ElementAt(it).Key; if (key.First == minPair.First) { m_Errors[key] = ComputeError(minPair.First, key.Second); } if (key.Second == minPair.First) { m_Errors[key] = ComputeError(minPair.First, key.First); } } /*foreach (var e in m_Errors) * { * var p = e.Key; * if (p.First == minPair.First) * { * m_Errors[p] = ComputeError(minPair.First, p.Second); * } * * if (p.Second == minPair.First) * { * m_Errors[p] = ComputeError(minPair.First, p.First); * } * }*/ } if (listener != null) { listener.OnComplete("Compacting"); } }