public double distanceWithinPolygon(final int lon1, final int lat1, final int lon2, final int lat2) {
        double distance = 0.;

        // Extremities of the segments
        final Point p1 = new Point(lon1, lat1);
        final Point p2 = new Point(lon2, lat2);

        Point previousIntersectionOnSegment = null;
        if (isWithin(lon1, lat1)) {
            // Start point of the segment is within the polygon, this is the first
            // "intersection".
            previousIntersectionOnSegment = p1;
        }

        // Loop over edges of the polygon to find intersections
        final int iLast = points.size() - 1;
        for (int i = isClosed ? 0 : 1, j = isClosed ? iLast : 0; i <= iLast; j = i++) {
            final Point edgePoint1 = points.get(j);
            final Point edgePoint2 = points.get(i);
            final int intersectsEdge = intersect2D2Segments(p1, p2, edgePoint1, edgePoint2);

            if (isClosed && intersectsEdge == 1) {
                // Intersects with a (closed) polygon edge on a single point
                // Distance is zero when crossing a polyline.
                // Let's find this intersection point
                final int xdiffSegment = lon1 - lon2;
                final int xdiffEdge = edgePoint1.x - edgePoint2.x;
                final int ydiffSegment = lat1 - lat2;
                final int ydiffEdge = edgePoint1.y - edgePoint2.y;
                final int div = xdiffSegment * ydiffEdge - xdiffEdge * ydiffSegment;
                final long dSegment = (long) lon1 * (long) lat2 - (long) lon2 * (long) lat1;
                final long dEdge = (long) edgePoint1.x * (long) edgePoint2.y - (long) edgePoint2.x * (long) edgePoint1.y;
                // Coordinates of the intersection
                final Point intersection = new Point(
                        (int) ((dSegment * xdiffEdge - dEdge * xdiffSegment) / div),
                        (int) ((dSegment * ydiffEdge - dEdge * ydiffSegment) / div)
                );
                if (
                        previousIntersectionOnSegment != null
                                && isWithin(
                                (intersection.x + previousIntersectionOnSegment.x) >> 1,
                                (intersection.y + previousIntersectionOnSegment.y) >> 1
                        )
                ) {
                    // There was a previous match within the polygon and this part of the
                    // segment is within the polygon.
                    distance += CheapRulerHelper.distance(
                            previousIntersectionOnSegment.x, previousIntersectionOnSegment.y,
                            intersection.x, intersection.y
                    );
                }
                previousIntersectionOnSegment = intersection;
            } else if (intersectsEdge == 2) {
                // Segment and edge overlaps
                // FIXME: Could probably be done in a smarter way
                distance += Math.min(
                        CheapRulerHelper.distance(p1.x, p1.y, p2.x, p2.y),
                        Math.min(
                                CheapRulerHelper.distance(edgePoint1.x, edgePoint1.y, edgePoint2.x, edgePoint2.y),
                                Math.min(
                                        CheapRulerHelper.distance(p1.x, p1.y, edgePoint2.x, edgePoint2.y),
                                        CheapRulerHelper.distance(edgePoint1.x, edgePoint1.y, p2.x, p2.y)
                                )
                        )
                );
                // FIXME: We could store intersection.
                previousIntersectionOnSegment = null;
            }
        }

        if (
                previousIntersectionOnSegment != null
                        && isWithin(lon2, lat2)
        ) {
            // Last point is within the polygon, add the remaining missing distance.
            distance += CheapRulerHelper.distance(
                    previousIntersectionOnSegment.x, previousIntersectionOnSegment.y,
                    lon2, lat2
            );
        }
        return distance;
    }
Compute the length of the segment within the polygon.

@param lon1 Integer longitude of the first point of the segment.
@param lat1 Integer latitude of the first point of the segment.
@param lon2 Integer longitude of the last point of the segment.
@param lat2 Integer latitude of the last point of the segment.
@return The length, in meters, of the portion of the segment which is
included in the polygon.
main/src/main/java/cgeo/geocaching/brouter/core/OsmNogoPolygon.java