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 Animate() { foreach (Circle circle in circles) { double deltaX = Math.Abs(circle.x - circle.BoundingCircle_x); double deltaY = Math.Abs(circle.y - circle.BoundingCircle_y); double dist = Math.Sqrt(deltaX * deltaX + deltaY * deltaY); double distR = dist + circle.r; if (distR <= circle.BoundingCircle_r) { circle.x += RandomManager.getDistance(); } else if (distR > circle.BoundingCircle_r) { } } }
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("-----------------------"); } }
public static Pack BuildPack(int circleNb, int numBig, int diametreMax, int yCircle) { Pack pack = new Pack() { DiametreMax = diametreMax }; R = diametreMax; // Create circles circles = new List <Circle>() { new Circle() { num = 1 }, new Circle() { num = 2 }, new Circle() { num = 3 } }; if (circleNb > 3) { circles.Add(new Circle() { num = 4 }); } if (circleNb > 4) { circles.Add(new Circle() { num = 5 }); } if (circleNb > 5) { circles.Add(new Circle() { num = 6 }); } // Big One position int bigOnePosition = numBig; // Radius List <double> rayon = new List <double>(); //if (circleNb == 6) //{ // rayon.Add(1.0); // rayon.Add(rayon[0] * 0.8); // rayon.Add(rayon[1] * 0.9); // rayon.Add(rayon[2] * 0.95); // rayon.Add(rayon[3] * 0.975); // rayon.Add(rayon[4] * 1); //} //2015_03_24 définition position en dur (dans un 1er temps) des cercles englobants if (circleNb == 6) { circles[0].BoundingCircle_x = 400; circles[0].BoundingCircle_y = 400; circles[0].BoundingCircle_r = 100; // Millieu circles[1].BoundingCircle_x = 200; circles[1].BoundingCircle_y = 450; circles[1].BoundingCircle_r = 100; // Gauche circles[2].BoundingCircle_x = 400; circles[2].BoundingCircle_y = 600; circles[2].BoundingCircle_r = 100; // Gauche circles[3].BoundingCircle_x = 280; circles[3].BoundingCircle_y = 230; circles[3].BoundingCircle_r = 100; // Gauche circles[4].BoundingCircle_x = 600; circles[4].BoundingCircle_y = 450; circles[4].BoundingCircle_r = 100; // Gauche circles[5].BoundingCircle_x = 510; circles[5].BoundingCircle_y = 230; circles[5].BoundingCircle_r = 100; // Gauche foreach (Circle c in circles) { c.x = c.BoundingCircle_x; c.y = c.BoundingCircle_y; c.r = c.BoundingCircle_r / 3; } } return(pack); if (circleNb == 6) { int parent = 0; int fils = 1; // Un Y n'est possible que sur les noeuds 2 à 4 // puisque le 1er noeud n'a pas de parent, on ne peut pas faire de Y if (yCircle == 1) { yCircle = 2; } // On ne peut pas dépasser 4 car il n'y a plus assez de fils pour faire un Y if (yCircle > 3) { yCircle = 4; } for (int i = 0; fils < circleNb; i++) { circles[parent].next.Add(circles[fils]); circles[fils].previous = circles[parent]; if (yCircle == parent + 1) { // On est dans le cas où on a 2 enfants à ce noeud // On reclacul l'angleWithPrevious du fils courant avant de passer au suivant. double min = 0; min = circles[fils].angleWithPrevious = RandomManager.getDouble2(min, Math.PI / 2); fils++; circles[parent].next.Add(circles[fils]); circles[fils].previous = circles[parent]; circles[fils].angleWithPrevious = RandomManager.getDouble2(-Math.PI / 2, min / 6); } if (yCircle < parent + 1) { circles[fils].angleWithPrevious = circles[parent].angleWithPrevious + RandomManager.getDouble2(-0.8, 0.8); } parent++; fils++; } } circlesInitial = new List <Circle>(); // Création des cercles dans la représentation initiale des cercles. foreach (var item in circles) { circlesInitial.Add(new Circle() { x = item.x, y = item.y, num = item.num, r = item.r, angleWithPrevious = item.angleWithPrevious, angleWithPreviousVelocity = item.angleWithPreviousVelocity }); } // Hiérarchisation de la représentation initiale des cercles. return(pack); }