addInsideTurn method

void addInsideTurn(
  1. int orientation,
  2. bool addStartPoint
)

Adds the offset points for an inside (concave) turn.

@param orientation @param addStartPoint

Implementation

void addInsideTurn(int orientation, bool addStartPoint) {
  /**
   * add intersection point of offset segments (if any)
   */
  li!.computeIntersection(offset0.p0, offset0.p1, offset1.p0, offset1.p1);
  if (li!.hasIntersection()) {
    segList.addPt(li!.getIntersection(0));
  } else {
    /**
     * If no intersection is detected,
     * it means the angle is so small and/or the offset so
     * large that the offsets segments don't intersect.
     * In this case we must
     * add a "closing segment" to make sure the buffer curve is continuous,
     * fairly smooth (e.g. no sharp reversals in direction)
     * and tracks the buffer correctly around the corner. The curve connects
     * the endpoints of the segment offsets to points
     * which lie toward the centre point of the corner.
     * The joining curve will not appear in the final buffer outline, since it
     * is completely internal to the buffer polygon.
     *
     * In complex buffer cases the closing segment may cut across many other
     * segments in the generated offset curve.  In order to improve the
     * performance of the noding, the closing segment should be kept as short as possible.
     * (But not too short, since that would defeat its purpose).
     * This is the purpose of the closingSegFactor heuristic value.
     */

    /**
     * The intersection test above is vulnerable to robustness errors; i.e. it
     * may be that the offsets should intersect very close to their endpoints,
     * but aren't reported as such due to rounding. To handle this situation
     * appropriately, we use the following test: If the offset points are very
     * close, don't add closing segments but simply use one of the offset
     * points
     */
    _hasNarrowConcaveAngle = true;
    //System.out.println("NARROW ANGLE - distance = " + distance);
    if (offset0.p1.distance(offset1.p0) <
        distance * INSIDE_TURN_VERTEX_SNAP_DISTANCE_FACTOR) {
      segList.addPt(offset0.p1);
    } else {
      // add endpoint of this segment offset
      segList.addPt(offset0.p1);

      /**
       * Add "closing segment" of required length.
       */
      if (closingSegLengthFactor > 0) {
        Coordinate mid0 = new Coordinate(
            (closingSegLengthFactor * offset0.p1.x + s1.x) /
                (closingSegLengthFactor + 1),
            (closingSegLengthFactor * offset0.p1.y + s1.y) /
                (closingSegLengthFactor + 1));
        segList.addPt(mid0);
        Coordinate mid1 = new Coordinate(
            (closingSegLengthFactor * offset1.p0.x + s1.x) /
                (closingSegLengthFactor + 1),
            (closingSegLengthFactor * offset1.p0.y + s1.y) /
                (closingSegLengthFactor + 1));
        segList.addPt(mid1);
      } else {
        /**
         * This branch is not expected to be used except for testing purposes.
         * It is equivalent to the JTS 1.9 logic for closing segments
         * (which results in very poor performance for large buffer distances)
         */
        segList.addPt(s1);
      }

      //*/
      // add start point of next segment offset
      segList.addPt(offset1.p0);
    }
  }
}