I am trying to design an object-oriented library to handle geometric calculations. However, I am trying to exaggerate on being “tightly” object-oriented and applying relevant “best practices”. I **know** that there is no reason to be dogmatic about patterns, I am just trying to squeeze out every bit of possibility that I have not found out any different way for what I am about to ask.

Consider trying to design a path, composed of segments. I consider having a common interface for segments, which offers a method to calculate points of intersection with another segment. In short, the tentative signature of such a method might look like:

`abstract class Segment { ... Point[] Intersection(Segment other); ... } `

However, when implementing such a method, it might be necessary to check what actual implementation lies behind the “other” Segment. This can be done through run-time type checks, given that the language supports it, otherwise, I have to use some kind of `enum`

to differentiate between segments and, potentially, cast the object to call corresponding methods. In any case, I cannot “extract” some common interface for this kind of design.

I have considered “forcingly” establishing a base-assumption that all path segments boil down to sequences of points, and unify the algorithmic intersection process as being always a line-to-line intersection between all sub-segments, but this will rob the design of a very significant (in my opinion) optimization possibility. Considering the ubiquity and “temporal density” of geometry-based operations the library will be built to support, it is very important, in terms of performance, to take advantage of special shapes having “closed forms” to calculate intersections between them (such as a circular arc with a line), instead of testing a multitude of small line-segment pairs to identify intersection points.

Apart from that, if I make the simplifying assumption of paths consisting of path sequences, I will have to make another relatively pervasive (for such a library) design choice, that of point density, to trace, for example, the various segment types. This would be, in my opinion, a reasonably architecturally-relevant parameter when considering an end result of drawing, e.g. on-screen, in order to achieve a given level of smoothness, for example. However, I feel this is, conceptually” an unsuitable abstraction for the geometric operations between pure geometric abstractions. A circle is not a series of line segments and should not need 5,10 or 100 coordinate pairs to be represented. It is just a center and a radius.

My question is, is there any other way to be object-oriented when dealing with base classes for geometry entities, or the “usual” way of doing things is with an enumeration and implementations checking segment type and exploiting specific geometric relations to potentially optimize the procedures?

The reason I am giving so much thought on this is that I might find myself having to implement special segment types, such as, for example, parametric curves, in the future, or simply allow extension of the API outside of the API itself. If I use the enum-based, type-checked everything-with-everything intersection tests (and do so also for other spatial operations between segments besides intersection), “outsider” extensions of the API will have to “register” themselves in the segment-types enumeration, which would necessitate either changing and rebuilding the original API, or providing a mechanism for external registrations. Or simply make a true global capture of all possible segment geometric forms to account for everything.

To make it simple, assume that I implement this only with segments, and then I add a new implementation of a circular arc. I can “teach” the circular arc how to intersect itself with straight line segments (by checking the segment type for “line”, for example), but I can not “teach” the line segment how to intersect itself with arcs without going back to change the original library.

I understand that there are methods or techniques to provide all this flexibility (I could make segments register special “injected” intersection methods for specific identifiers, which would be determined by the external API extension objects, so that lines will first check whether the object they intersect with is such a “special” type, or simply make intersection methods virtual, so that the developer trying to extend my API will be able to manually “teach” all existing segment implementations how to intersect themselves with my original objects). All I am asking is, is there any other **elegant** way to tackle this situation?

The top-voted answer to this question suggests excluding the method entirely and delegating it to a different class. This does sound somewhat counter-intuitive, given that segments **do** know their geometries. However, segments **do not** know other segments’ geometries, so it appears to be reasonable design decision to “outsource” the intersection method, one that still necessitates knowing the segment type at run-time, however. Since I am trying to represent segments as interfaces “ignorant” of the underlying type (as in “I want to support the use of the segment interface as being ignorant of the underlying implementation”). Apart from that, I would not resort to empty marker interfaces to differentiate between classes. An external “intersector”-like class would look interesting, though I would avoid making it static, in order to allow for extensions and potential changes of strategy (different implementations, optimizing for speed, employing snapping, etc).