2

I have a function that takes two objects and uses a switch on the enum types of the objects.

The problem I have is this is getting painful to manage as I add more and more primitive types and i need two case statements for each variation.

My switch is setup like this:

switch (obj1.Type, obj2.Type){
    case (GeometryType.Polygon, GeometryType.Polygon):
       return GetIntersectingPoints(obj1 as Polygon, obj2 as Polygon, contactPoints);
   case (GeometryType.Polygon, GeometryType.Circle):
      return GetIntersectingPoints(obj1 as Polygon, obj2 as Circle, contactPoints);
   case (GeometryType.Polygon, GeometryType.Arc):
      return GetIntersectingPoints(obj1 as Polygon, obj2 as Arc, contactPoints);
   case (GeometryType.Polygon, GeometryType.Line2D):
      return GetIntersectingPoints(obj1 as Polygon, obj2 as LineSegment, contactPoints);
   case (GeometryType.Polygon, GeometryType.BiArc):
      return GetIntersectingPoints(obj1 as Polygon, obj2 as BiArc, contactPoints);

    //same as second case but the other way around
   case (GeometryType.Circle, GeometryType.Polygon):
     return GetIntersectingPoints(obj2 as Polygon, obj1 as Circle, contactPoints);
    // and so on

Since the objects provided could either be A and B or B and A every time i add a new primitive type this switch becomes painfully longer and longer and its just a huge hassle to deal with.

Is there a smarter design pattern to do this that requires less management? How do people usually handle this situation in physics collision design ?

6
  • 1
    I'm not sure there's enough information to properly answer the question: 2D or 3D (looks like 2D)? What are the performance requirements? Do you care about the exact intersection coordinates, the amount of intersection points or only that two objects intersect? What prevents you from turning everything into polygons? – Philipp Schmid Jul 22 at 7:46
  • I don't see why it matters if it's 2D, 3D or what i require out of a method. I am talking about if theres is a better design pattern for handling all the type combinations other than making gigantic switch statement for every combination like i currently have - it seems unmanageable. The current switch is like a middle man to direct the compiler to the relevant methods but its getting long and very repetitive. – WDUK Jul 22 at 7:56
  • 1
    Related SO: multiple dispatch – Caleth Jul 22 at 8:17
  • 3
    It matters because there's no one-fits-all design pattern. If you don't care about performance or where points intersect, create an interface or abstract class that rasterizes every primitive and compare them on the pixel level. Done. If your requirement is soft realtime, it may be time to think about ditching object orientation alltogether and only work with polygons. If your requirement is exact intersections, look up those math formulas specific to your primitives. – Philipp Schmid Jul 22 at 8:29
  • Assuming that GetIntersectingPoints is commutative, you can deal with "the other way around" issue by swapping obj1 and obj2 if necessary so that type(obj1) <= type(obj2) (you may need to define an ordering for your types. It doesn't matter what it is so long as it's consistent). This won't fix your combinatorial explosion problem though. – Philip Kendall Jul 22 at 8:56
3

The "real world" solution: convert everything to polygons in the input data, then you only have one intersection function.

There might be interesting solutions if those GetIntersectingPoints() were simply the same code using different types, but in your case they aren't; the code for computing all these different kinds of intersection will be different because they're geometrically different.

You might still be able to reduce the combinational explosion if you can find a way to reduce the number of really different bits of geometry you support. For example, a Line2D is a degenerate polygon and circles and arcs are degenerate cases of BiArc. So maybe you could just have polygon and BiArc?

2

Another way to deal with this is to use multiple dispatch. You still need to write code for the possible combinations, but instead of a very long switch, you’d just add new implementations of the multimethod.

In C# you are lucky, since it’s one of the very few languages that support it natively, via the keyword dynamic for method arguments, the overload resolution being in this case performed at runtime. A comprehensive example here.

0

Another way to achieve multiple dispatch is via the visitor pattern. See how to implement visitor pattern in c# for details. An advantage of visitor pattern over dynamic is that the later has a rather large overhead, .

If implemented correctly, this allow you to have a default method that converts both objects to polygons, while still allowing you to specify optimized paths for any particular combination of shapes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.