Sep 5, 2020

Introducing an Enum

In my work with my geometry library I noticed that some of the more basic classes, like LineSegment, Line, Interval etc. had basic functions, where a specific behaviour for the edge cases made implementation of the more complex classes like Polygon simpler.

Of course, since every developer likes simplicity, I used these conventions when doing the implementations. My problem was that after a while I noticed that a convention that made since in one scenario, didn't necessarily make sense in another one. Now I had a problem. I needed a way to make both scenarios to work.

The solution became to introduce an enum that governed over which convention that would be used. In my case it was about how to interpret the endpoints of my line segments, whether they were part of the segment or not when checking overlapping.

Code of the Day

  /**
   * Returns the point where the given line segments intersect, if such point exists.
   * If the line segments are parallel none is return since the intersect can potentially
   * be many points.
   * @param ls2
   * The other line segment.
   * @param otherInterval
   * How the endpoints should be interpreted of the other line segment.
   * @param thisInterval
   * How the endpoints should be interpreted on this line segment.
   */
  intersect(ls2: LineSegment, otherInterval: IntervalType = IntervalType.Closed, 
            thisInterval: IntervalType = IntervalType.Closed)
    : Optional<Point> {
    const l1 = this.asLine();
    const l2 = ls2.asLine();

    const intersect = l1.intersect(l2);

    return intersect.filter(intersect => this.containsPoint(intersect)
      && ls2.containsPoint(intersect));
  }

The code here definitely becomes more wordy, but in the end the code that uses these functions becomes more clear since you don't need to second guess the edge cases anymore.