Useful Method for PhysicsSimulator

Topics: Developer Forum
Dec 3, 2007 at 10:10 AM
Edited Dec 3, 2007 at 10:12 AM
I had to add this method to Farseer for our current project. It's very useful for situations where you have layered physics objects (static bodies, or because of collision categories). They return a list of geometries that collide with a point, rather than simply the first one.

public List<Geom> CollideAll(float x, float y)
{
return CollideAll(new Vector2(x, y));
}

public List<Geom> CollideAll(Vector2 point)
{
List<Geom> ret = new List<Geom>();
foreach (Geom geometry in geometryList)
{
if (geometry.Collide(point))
{
ret.Add(geometry);
}
}
return ret;
}

Edit: forgot to mention I added this is in PhysicsSimulator.cs
Coordinator
Dec 3, 2007 at 11:33 AM
Added. Thanks.
Dec 10, 2007 at 1:31 AM
Edited Dec 10, 2007 at 1:49 AM
Yeah, this would be a very helpful procedure. I would suggest that an enumerator be used however. You could then search for the collision you're looking for as it is looking for them, and stop once you find it. This could save a lot of processing time and memory. I tend to cram things on one line a lot, but I think it's understandable.

public IEnumerable<Geom> Collisions(Vector2 point)
{
    foreach (Geom geom in geometryList) if (geom.Collide(point)) yield return geom;
}
public IEnumerable<Geom> Collisions(Vector2 point, Predicate<Geometry> pred)
{
    foreach (Geom geom in geometryList) if (geom.Collide(point) && pred(geom)) yield return geom;
}

When you call this, a special IEnumerable is returned and none of the code in the body is executed. The code only runs when a Geom is requested (by 'foreach' or otherwise) and only returns one Geom at a time rather than a huge list. (Which saves memory.) The second overload would be much more convenient in C# 3.0 due to lambda expressions, but is just as useful now.

I wanted this in my code because I was implementing your mouse spring (that thing is very convenient) and wanted it to ignore static bodies.
public static T GetFirst<T>(IEnumerable<T> enumerable) // Use the 'this' keyword in C# 3.0 to make it an extention method, but I think System.Data.Linq already has one like this.
{
    IEnumerator<T> enumerator = enumerable.GetEnumerator();
    return enumerator.MoveNext() ? enumerator.Current : default(T);
}
private void UpdateMouseSpring()
{
    ...
    pickedGeometry = GetFirst(physicsSimulator.Collisions(point, delegate(Geometry geo) { return !geo.Body.IsStatic; }));
    ...
}
Developer
Jan 13, 2008 at 5:25 PM

crashlander wrote:
Added. Thanks.


Sorry crashlander but you made a little mistake while implementing.

public List<Geom> CollideAll(Vector2 point)
{
List<Geom> geomList = new List<Geom>();
foreach (Geom geom in geomList)
{
if (geom.Collide(point))
{
geomList.Add(geom);
}
}
return geomList;
}


Should be:

public List<Geom> CollideAll(Vector2 point)
{
List<Geom> returnGeomList = new List<Geom>();
foreach (Geom geom in geomList)
{
if (geom.Collide(point))
{
returnGeomList.Add(geom);
}
}
return returnGeomList;
}
Coordinator
Jan 14, 2008 at 11:28 AM
Ok, fixed.... again. Will be in next release.

Thanks for catching that.