public Circle() { x = 0; y = 0; r = 1; angleWithPrevious = RandomManager.getDouble(-1.2, 1.2); angleWithPreviousVelocity = RandomManager.getDouble(0.009, 0.015); if (RandomManager.getDouble(-1, 1) < 0) { angleWithPreviousVelocity = -angleWithPreviousVelocity; } collisions = new Dictionary <Circle, double>(); next = new List <Circle>(); }
public void PreventCollision() { // Console.WriteLine("===== PreventCollision 2 ====="); foreach (Circle current in circles) { // Console.WriteLine("----- Circle " + current.num + " -----"); if (current.collisions.Count > 0) { //if (current.collisions.Count == 1) { //Console.WriteLine("CAS 1"); // Une collision, on donne des impulsions opposées et dans le bon sens aux cercles en collision // 2 cas possibles : // Cas 1 : les cercles sont parents. // il n'y a pas de ramification entre les cercles (collision entre un cercle et 1 de ses ancêtres // il faut donc modifier l'angle des noeuds Circle collisionCircle = null; foreach (var item in current.collisions) { collisionCircle = item.Key; break; } // Recherche de parent Circle parent = current.previous; bool found = false; if (parent != null) { Circle collisionNext = current; // noeud fils du noeud en collision parent de current while (parent != null && parent != collisionCircle) { collisionNext = parent; parent = collisionNext.previous; if (parent == collisionCircle) { found = true; break; } } if (parent != null) // noeud parent { // Calcul de l'angle entre les centre des noeud en collision double angleCollision = GetAngleBetweenCircles(collisionNext, current); double _2pi = Math.PI * 2; double collisionNextAngle = (collisionNext.angleWithPrevious - Math.PI) < 0 ? _2pi + (collisionNext.angleWithPrevious - Math.PI) : (collisionNext.angleWithPrevious - Math.PI); collisionNextAngle = (collisionNextAngle) % _2pi >= 0 ? collisionNextAngle % _2pi : _2pi + collisionNextAngle % _2pi; if (collisionNextAngle < angleCollision || (collisionNextAngle - angleCollision > Math.PI && collisionNextAngle > angleCollision)) { // Alors current est plus à droite que parentNext // il faut appliquer une vélocité négative à current et une positive à //if (current.angleWithPreviousVelocity <= 0) current.angleWithPreviousVelocity -= RandomManager.getDouble(0.001, 0.005); //else current.angleWithPreviousVelocity = 0; if (current.angleWithPreviousVelocity <= 0 || (current.angleWithPreviousVelocity > 0 && (current.angleWithPreviousVelocity < collisionNext.angleWithPreviousVelocity || Math.Abs(current.angleWithPreviousVelocity - collisionNext.angleWithPreviousVelocity) < 0.5))) { if (Math.Abs(current.angleWithPreviousVelocity) < Circle.maxVelocity / 3.0) { current.angleWithPreviousVelocity += RandomManager.getDouble(0.0015, 0.006); } else { current.angleWithPreviousVelocity = current.angleWithPreviousVelocity / 2.0; } if (Math.Abs(collisionNext.angleWithPreviousVelocity) < Circle.maxVelocity / 3.0) { collisionNext.angleWithPreviousVelocity -= RandomManager.getDouble(0.0015, 0.006); } else if (collisionNext.angleWithPreviousVelocity > 0) { collisionNext.angleWithPreviousVelocity = collisionNext.angleWithPreviousVelocity / 2.0; } if (current.angleWithPreviousVelocity > Circle.maxVelocity) { current.angleWithPreviousVelocity = Circle.maxVelocity; } if (collisionNext.angleWithPreviousVelocity < -Circle.maxVelocity) { collisionNext.angleWithPreviousVelocity = -Circle.maxVelocity; } } } else { if (current.angleWithPreviousVelocity >= 0 || (current.angleWithPreviousVelocity < 0 && (current.angleWithPreviousVelocity < collisionNext.angleWithPreviousVelocity || Math.Abs(current.angleWithPreviousVelocity - collisionNext.angleWithPreviousVelocity) < 0.5))) { if (Math.Abs(current.angleWithPreviousVelocity) < Circle.maxVelocity / 3.0) { current.angleWithPreviousVelocity -= RandomManager.getDouble(0.0015, 0.006); } else { current.angleWithPreviousVelocity = current.angleWithPreviousVelocity / 2.0; } if (Math.Abs(collisionNext.angleWithPreviousVelocity) < Circle.maxVelocity / 3.0) { collisionNext.angleWithPreviousVelocity += RandomManager.getDouble(0.0015, 0.006); } else { collisionNext.angleWithPreviousVelocity = collisionNext.angleWithPreviousVelocity / 2.0; } if (current.angleWithPreviousVelocity < -Circle.maxVelocity) { current.angleWithPreviousVelocity = -Circle.maxVelocity; } if (collisionNext.angleWithPreviousVelocity > Circle.maxVelocity) { collisionNext.angleWithPreviousVelocity = Circle.maxVelocity; } } } // Calcul de la proximité entre les bords des cercles : distance entre les centre - les rayons des cercles. // La proximité permet de déterminer la force de la répulsion entre les cercles. } else { if (current.num > 2) { // Noeud d'une ramification // Cas 2 : il y a une ramification, il faut retrouver le premier parent commun et modifier les angles des cercles problématiques. // Construction de la liste des parent de current List <Circle> currentParents = new List <Circle>(); parent = current.previous; while (parent != null) { currentParents.Add(parent); parent = parent.previous; } List <Circle> collisionParents = new List <Circle>(); parent = collisionCircle.previous; while (parent != null) { collisionParents.Add(parent); parent = parent.previous; } Circle commonParent = null; foreach (var item in currentParents) { if (collisionParents.Contains(item)) { commonParent = item; break; } } // calcul des angles entre le parent commun et les cercle en collision double angleCurrent = GetAngleBetweenCircles(commonParent, current); double angleCollision = GetAngleBetweenCircles(commonParent, collisionCircle); double _2pi = Math.PI * 2; double collisionNextAngle = angleCollision < 0 ? _2pi + (angleCollision - Math.PI) : (angleCollision); if ((collisionNextAngle < angleCurrent && angleCurrent - collisionNextAngle < Math.PI) || (collisionNextAngle - angleCurrent > Math.PI && collisionNextAngle > angleCurrent)) { // Alors current est plus à droite que parentNext // il faut appliquer une vélocité négative à current et une positive à //if (current.angleWithPreviousVelocity <= 0) current.angleWithPreviousVelocity -= RandomManager.getDouble(0.001, 0.005); //else current.angleWithPreviousVelocity = 0; if (current.angleWithPreviousVelocity <= 0 || (current.angleWithPreviousVelocity > 0 && (current.angleWithPreviousVelocity < collisionCircle.angleWithPreviousVelocity || Math.Abs(current.angleWithPreviousVelocity - collisionCircle.angleWithPreviousVelocity) < 0.05))) { if (Math.Abs(current.angleWithPreviousVelocity) < Circle.maxVelocity / 3.0) { current.angleWithPreviousVelocity += RandomManager.getDouble(0.0015, 0.006); } else { current.angleWithPreviousVelocity = current.angleWithPreviousVelocity / 2.0; } //if (Math.Abs(collisionCircle.angleWithPreviousVelocity) < Circle.maxVelocity / 3.0) collisionCircle.angleWithPreviousVelocity -= RandomManager.getDouble(0.0015, 0.006); //else collisionCircle.angleWithPreviousVelocity = collisionCircle.angleWithPreviousVelocity / 2.0; if (current.angleWithPreviousVelocity > Circle.maxVelocity) { current.angleWithPreviousVelocity = Circle.maxVelocity; } //if (collisionCircle.angleWithPreviousVelocity < -Circle.maxVelocity) collisionCircle.angleWithPreviousVelocity = -Circle.maxVelocity; } } else { if (current.angleWithPreviousVelocity >= 0 || (current.angleWithPreviousVelocity < 0 && (current.angleWithPreviousVelocity < collisionCircle.angleWithPreviousVelocity || Math.Abs(current.angleWithPreviousVelocity - collisionCircle.angleWithPreviousVelocity) < 0.5))) { if (Math.Abs(current.angleWithPreviousVelocity) < Circle.maxVelocity / 3.0) { current.angleWithPreviousVelocity -= RandomManager.getDouble(0.0015, 0.006); } else { current.angleWithPreviousVelocity = current.angleWithPreviousVelocity / 2.0; } //if (Math.Abs(collisionCircle.angleWithPreviousVelocity) < Circle.maxVelocity / 3.0) collisionCircle.angleWithPreviousVelocity += RandomManager.getDouble(0.0015, 0.006); //else collisionCircle.angleWithPreviousVelocity = collisionCircle.angleWithPreviousVelocity / 2.0; if (current.angleWithPreviousVelocity < -Circle.maxVelocity) { current.angleWithPreviousVelocity = -Circle.maxVelocity; } //if (collisionCircle.angleWithPreviousVelocity > Circle.maxVelocity) collisionCircle.angleWithPreviousVelocity = Circle.maxVelocity; } } } } } } } else { //Console.WriteLine("Nothing to do"); } //Console.WriteLine("-----------------------"); } }