This is a physics problem*
So I have a group of rectangles I am trying to movie towards a point. I wanted to prevent them from getting into each other so I developed a custom physics engine that detects rectangle collision.
my problem here is that I can’t seem to get the wanted behaviour at all.
Here is what I have :
Here is what I need as a result:
And Here is my current code and Gh file:
private void RunScript(int iterations, List<Rectangle3d> spaces, Polyline boundary, List<int> lineStartIndices, List<int> lineEndIndices, List<int> viewIndex, List<int> orientationIndex, List<Point3d> cardinals, double moveDistance, double collisionDistance, double approximationMultiplier, double orientationMultiplier, List<double> spaceProximityMultipliers, List<double> spaceOrientationMultipliers, bool iterationMode, bool start, bool reset, ref object Vectors, ref object A, ref object B, ref object C)
{
List<Line> collisionDisplay = new List<Line>();
List<Line> collisionDisplay2 = new List<Line>();
if(iterationMode)
{
tempSpaces = spaces;
//--------------------------------------------------------------------
//iterate is start button is set to true
//--------------------------------------------------------------------
for(int i = 0; i < iterations;i++)
// Parallel.For(0, iterations, i =>
{
var collision = new RectangleCollider(moveDistance, collisionDistance,
approximationMultiplier, orientationMultiplier, boundary, tempSpaces);
collision.MoveRectangles();
collision.ApplyMove();
tempSpaces = collision.ResultingSpacesArr.ToList();
}
}
else
{
//--------------------------------------------------------------------
//reset loop on switch press
//--------------------------------------------------------------------
if(reset || counter == 0)
{
tempSpaces = spaces;
velocity = moveDistance;
counter = 0;
}
//--------------------------------------------------------------------
//iterate is start button is set to true
//--------------------------------------------------------------------
if(start)
{
GrasshopperDocument.ScheduleSolution(10, ScheduleSolutionCallback);
//loop logic if start is true
var collision = new RectangleCollider(velocity, collisionDistance,
approximationMultiplier, orientationMultiplier, boundary, tempSpaces);
collision.MoveRectangles();
collision.CollideRectangles();
collision.ApplyMove();
tempSpaces = collision.ResultingSpacesArr.ToList();
velocity = collision.MoveDistance;
counter++;
//output
Vectors = collision.MovementVectors;
}
}
//--------------------------------------------------------------------
//output
//--------------------------------------------------------------------
//gh conversion
var ghRects = new List<GH_Rectangle>();
for(int i = 0; i < tempSpaces.Count; i++)
ghRects.Add(new GH_Rectangle(tempSpaces[i]));
var ghCollisionDisplay = new List<GH_Line>();
for(int i = 0; i < collisionDisplay.Count; i++)
ghCollisionDisplay.Add(new GH_Line(collisionDisplay[i]));
var ghCollisionDisplay2 = new List<GH_Line>();
for(int i = 0; i < collisionDisplay2.Count; i++)
ghCollisionDisplay2.Add(new GH_Line(collisionDisplay2[i]));
A = ghRects;
B = ghCollisionDisplay;
C = ghCollisionDisplay2;
//display no of iterations on console
Print("Iterations: " + (counter).ToString());
Print("velocity: " + (velocity).ToString());
}
// <Custom additional code>
//params
List<Rectangle3d> tempSpaces = new List<Rectangle3d>();
double velocity;
int counter;
//iteration logic
public void ScheduleSolutionCallback(GH_Document doc)
{
this.Component.ExpireSolution(false);
}
//--------------------------------------------------------------------
//Collision class
//--------------------------------------------------------------------
public class RectangleCollider
{
public double MoveDistance;
public double CollisionDistance;
public double ApproximationMultiplier;
public double OrientationMultiplier;
public Polyline Boundary;
public Point3d Center;
public List<Rectangle3d> Spaces;
public Rectangle3d[] ResultingSpacesArr;
public Vector3d[ ] MovementVectors;
public bool IsColliding = false;
public RectangleCollider(double moveDistance, double collisionDistance,
double approximationMultiplier, double orientationMultiplier,
Polyline boundary, List<Rectangle3d> spaces)
{
MoveDistance = moveDistance;
CollisionDistance = collisionDistance;
ApproximationMultiplier = approximationMultiplier;
OrientationMultiplier = orientationMultiplier;
Boundary = boundary;
Spaces = spaces;
Center = boundary.CenterPoint();
MovementVectors = new Vector3d[spaces.Count];
}
//Move Points
public void MoveRectangles()
{
for(int i = 0; i < Spaces.Count; i++)
{
if(Spaces[i].Center.DistanceTo(Center) > 1 && !IsColliding)
{
Vector3d translationVector = Center - Spaces[i].Center;
if(Math.Abs(Center.X - Spaces[i].Center.X) > Math.Abs(Center.Y - Spaces[i].Center.Y))
{
var xVector = new Vector3d(translationVector.X, 0, 0);
xVector.Unitize();
MovementVectors[i] += xVector * 0.5;
}
else
{
var yVector = new Vector3d(0, translationVector.Y, 0);
yVector.Unitize();
MovementVectors[i] += yVector * 0.5;
}
}
}
}
//collide rectangles
public void CollideRectangles()
{
Parallel.For(0, Spaces.Count, i =>
{
for(int j = 0; j < Spaces.Count; j++)
{
if(i != j)
{
var rect1MinX = Spaces[i].Corner(0).X;
var rect1MaxX = Spaces[i].Corner(2).X;
var rect1MinY = Spaces[i].Corner(0).Y;
var rect1MaxY = Spaces[i].Corner(2).Y;
var rect1Center = Spaces[i].Center;
var rect2MinX = Spaces[j].Corner(0).X;
var rect2MaxX = Spaces[j].Corner(2).X;
var rect2MinY = Spaces[j].Corner(0).Y;
var rect2MaxY = Spaces[j].Corner(2).Y;
var rect2Center = Spaces[j].Center;
if((rect1MinX < rect2MaxX && rect1MaxX > rect2MinX) &&
(rect1MinY < rect2MaxY && rect1MaxY > rect2MinY))
{
//stop if they collide
IsColliding = true;
//if they collide in x
if ( rect1MinX < rect2MaxX && rect1MaxX > rect2MinX )
{
MovementVectors[j].X += -MovementVectors[j].X;
}
//if they collide in y
if ( rect1MinY < rect2MaxY && rect1MaxY > rect2MinY )
{
MovementVectors[j].Y += -MovementVectors[j].Y;
}
}
else {
IsColliding = false;
}
}
}
}
);
}
//apply move
public void ApplyMove()
{
var spacesArr = Spaces.ToArray();
for(int i = 0; i < Spaces.Count; i++)
{
var move = Transform.Translation(MovementVectors[i]);
spacesArr[i].Transform(move);
}
ResultingSpacesArr = spacesArr;
}
}
// </Custom additional code>
}
211003-01-RectangleCollisionProblem-YA.gh (20.6 KB)
I will also be tagging @DanielPiker @Dani_Abalde @DavidRutten @PeterFotiadis
since you guys might have knowledge of this topic.
please tell me anything you know. As have been stuck in this for months and researched it so much on many engines but didn’t find the right answer(or didn’t have enough understanding)
thank you in advance.strong text