public bool DoFracture(ref Particle other, ref Particle me) { bool somethingBroke = false; double len = (other.goal - goal).Length(); double rest = (other.x0 - x0).Length(); double off = Math.Abs((len / rest) - 1.0); if (off > LsmBody.fractureLengthTolerance) { somethingBroke = true; Testbed.PostMessage("Length fracture: Rest = " + rest + ", actual = " + len); } if (!somethingBroke) { Vector2 a = new Vector2(other.R[0, 0], other.R[1, 0]); Vector2 b = new Vector2(R[0, 0], R[1, 0]); a.Normalize(); b.Normalize(); double angleDifference = Math.Acos(a.Dot(b)); if (angleDifference > LsmBody.fractureAngleTolerance) { somethingBroke = true; Testbed.PostMessage("Angle fracture: angle difference = " + angleDifference); } } if (somethingBroke) { Particle saved = other; me = null; other = null; // Check if the chunks are still connected Queue <Particle> edge = new Queue <Particle>(); List <Particle> found = new List <Particle>(); edge.Enqueue(this); bool connected = false; while (edge.Count > 0) { Particle p = edge.Dequeue(); if (!found.Contains(p)) { found.Add(p); if (p == saved) { // Connected connected = true; break; } if (p.xPos != null) { edge.Enqueue(p.xPos); } if (p.xNeg != null) { edge.Enqueue(p.xNeg); } if (p.yPos != null) { edge.Enqueue(p.yPos); } if (p.yNeg != null) { edge.Enqueue(p.yNeg); } } } if (connected == false) { // The chunks broke - there are now two separate chunks (maximally connected subgraphs) chunk.particles.Clear(); chunk.particles.AddRange(found); chunk.CalculateInvariants(); Chunk newChunk = new Chunk(); edge.Clear(); found.Clear(); edge.Enqueue(saved); while (edge.Count > 0) { Particle p = edge.Dequeue(); if (!found.Contains(p)) { found.Add(p); p.chunk = newChunk; if (p.xPos != null) { edge.Enqueue(p.xPos); } if (p.xNeg != null) { edge.Enqueue(p.xNeg); } if (p.yPos != null) { edge.Enqueue(p.yPos); } if (p.yNeg != null) { edge.Enqueue(p.yNeg); } } } newChunk.particles.AddRange(found); newChunk.CalculateInvariants(); body.chunks.Add(newChunk); Testbed.PostMessage("Chunk broken: the original chunk now has " + chunk.particles.Count + " particles, the new chunk has " + newChunk.particles.Count + " particles."); Testbed.PostMessage("Number of chunks / particles: " + body.chunks.Count + " / " + body.particles.Count); } } return(somethingBroke); }
public bool DoFracture(ref Particle other, ref Particle me) { bool somethingBroke = false; double len = (other.goal - goal).Length(); double rest = (other.x0 - x0).Length(); double off = Math.Abs((len / rest) - 1.0); if (off > LsmBody.fractureLengthTolerance) { somethingBroke = true; Testbed.PostMessage("Length fracture: Rest = " + rest + ", actual = " + len); } if (!somethingBroke) { Vector2 a = new Vector2(other.R[0, 0], other.R[1, 0]); Vector2 b = new Vector2(R[0, 0], R[1, 0]); a.Normalize(); b.Normalize(); double angleDifference = Math.Acos(a.Dot(b)); if (angleDifference > LsmBody.fractureAngleTolerance) { somethingBroke = true; Testbed.PostMessage("Angle fracture: angle difference = " + angleDifference); } } if (somethingBroke) { Particle saved = other; me = null; other = null; // Check if the chunks are still connected Queue<Particle> edge = new Queue<Particle>(); List<Particle> found = new List<Particle>(); edge.Enqueue(this); bool connected = false; while (edge.Count > 0) { Particle p = edge.Dequeue(); if (!found.Contains(p)) { found.Add(p); if (p == saved) { // Connected connected = true; break; } if (p.xPos != null) edge.Enqueue(p.xPos); if (p.xNeg != null) edge.Enqueue(p.xNeg); if (p.yPos != null) edge.Enqueue(p.yPos); if (p.yNeg != null) edge.Enqueue(p.yNeg); } } if (connected == false) { // The chunks broke - there are now two separate chunks (maximally connected subgraphs) chunk.particles.Clear(); chunk.particles.AddRange(found); chunk.CalculateInvariants(); Chunk newChunk = new Chunk(); edge.Clear(); found.Clear(); edge.Enqueue(saved); while (edge.Count > 0) { Particle p = edge.Dequeue(); if (!found.Contains(p)) { found.Add(p); p.chunk = newChunk; if (p.xPos != null) edge.Enqueue(p.xPos); if (p.xNeg != null) edge.Enqueue(p.xNeg); if (p.yPos != null) edge.Enqueue(p.yPos); if (p.yNeg != null) edge.Enqueue(p.yNeg); } } newChunk.particles.AddRange(found); newChunk.CalculateInvariants(); body.chunks.Add(newChunk); Testbed.PostMessage("Chunk broken: the original chunk now has " + chunk.particles.Count + " particles, the new chunk has " + newChunk.particles.Count + " particles."); Testbed.PostMessage("Number of chunks / particles: " + body.chunks.Count + " / " + body.particles.Count); } } return somethingBroke; }
public void GenerateFromBlueprint(bool[,] blueprint) { this.blueprint = blueprint; width = blueprint.GetLength(0); height = blueprint.GetLength(1); lattice = new LatticePoint[width, height]; int x, y; for (x = 0; x < width; x++) { for (y = 0; y < height; y++) { lattice[x, y] = new LatticePoint(); lattice[x,y].index = new Point(x,y); if (blueprint[x, y] == true) { // Generate particle Particle p = new Particle(); lattice[x, y].particle = p; p.body = this; p.x0 = new Vector2(spacing.X * x, spacing.Y * y); p.x = offset + p.x0; p.latticePoint = lattice[x, y]; p.goal = p.x; particles.Add(p); } else { } } } // Set up the neighbors for (x = 0; x < width; x++) { for (y = 0; y < height; y++) { if (blueprint[x, y] == true) { if (InBounds(x + 1, y) && blueprint[x + 1, y] == true) { lattice[x, y].particle.xPos = lattice[x + 1, y].particle; lattice[x + 1, y].particle.xNeg = lattice[x, y].particle; } if (InBounds(x, y + 1) && blueprint[x, y + 1] == true) { lattice[x, y].particle.yPos = lattice[x, y + 1].particle; lattice[x, y + 1].particle.yNeg = lattice[x, y].particle; } } } } // Create the smoothing regions and have them generate themselves foreach (Particle p in particles) { SmoothingRegion s = new SmoothingRegion(w); s.body = this; s.latticePoint = p.latticePoint; s.latticePoint.smoothingRegion = s; s.RegenerateRegion(); smoothingRegions.Add(s); } // Create one chunk with all the particles in it Chunk c = new Chunk(); foreach (Particle p in particles) { c.particles.Add(p); p.chunk = c; } c.CalculateInvariants(); chunks.Add(c); // Setup the regions foreach (SmoothingRegion s in smoothingRegions) { s.CalculateInvariants(); } }
public void GenerateFromBlueprint(bool[,] blueprint) { this.blueprint = blueprint; width = blueprint.GetLength(0); height = blueprint.GetLength(1); lattice = new LatticePoint[width, height]; int x, y; for (x = 0; x < width; x++) { for (y = 0; y < height; y++) { lattice[x, y] = new LatticePoint(); lattice[x, y].index = new Point(x, y); if (blueprint[x, y] == true) { // Generate particle Particle p = new Particle(); lattice[x, y].particle = p; p.body = this; p.x0 = new Vector2(spacing.X * x, spacing.Y * y); p.x = offset + p.x0; p.latticePoint = lattice[x, y]; p.goal = p.x; particles.Add(p); } else { } } } // Set up the neighbors for (x = 0; x < width; x++) { for (y = 0; y < height; y++) { if (blueprint[x, y] == true) { if (InBounds(x + 1, y) && blueprint[x + 1, y] == true) { lattice[x, y].particle.xPos = lattice[x + 1, y].particle; lattice[x + 1, y].particle.xNeg = lattice[x, y].particle; } if (InBounds(x, y + 1) && blueprint[x, y + 1] == true) { lattice[x, y].particle.yPos = lattice[x, y + 1].particle; lattice[x, y + 1].particle.yNeg = lattice[x, y].particle; } } } } // Create the smoothing regions and have them generate themselves foreach (Particle p in particles) { SmoothingRegion s = new SmoothingRegion(w); s.body = this; s.latticePoint = p.latticePoint; s.latticePoint.smoothingRegion = s; s.RegenerateRegion(); smoothingRegions.Add(s); } // Create one chunk with all the particles in it Chunk c = new Chunk(); foreach (Particle p in particles) { c.particles.Add(p); p.chunk = c; } c.CalculateInvariants(); chunks.Add(c); // Setup the regions foreach (SmoothingRegion s in smoothingRegions) { s.CalculateInvariants(); } }