private void checkSegment(final int lon1, final int lat1, final int lon2, final int lat2) {
        // todo: bounding-box pre-filter

        final double[] lonlat2m = CheapRulerHelper.getLonLatToMeterScales((lat1 + lat2) >> 1);
        final double dlon2m = lonlat2m[0];
        final double dlat2m = lonlat2m[1];

        final double dx = (lon2 - lon1) * dlon2m;
        final double dy = (lat2 - lat1) * dlat2m;
        final double d = Math.sqrt(dy * dy + dx * dx);

        if (d == 0.) {
            return;
        }

        //for ( MatchedWaypoint mwp : waypoints )
        for (int i = 0; i < waypoints.size(); i++) {
            final MatchedWaypoint mwp = waypoints.get(i);

            if (mwp.direct && (i == 0 || waypoints.get(i - 1).direct)) {
                if (mwp.crosspoint == null) {
                    mwp.crosspoint = new OsmNode();
                    mwp.crosspoint.ilon = mwp.waypoint.ilon;
                    mwp.crosspoint.ilat = mwp.waypoint.ilat;
                    mwp.hasUpdate = true;
                    anyUpdate = true;
                }
                continue;
            }

            final OsmNode wp = mwp.waypoint;

            final double x1 = (lon1 - wp.ilon) * dlon2m;
            final double y1 = (lat1 - wp.ilat) * dlat2m;
            final double x2 = (lon2 - wp.ilon) * dlon2m;
            final double y2 = (lat2 - wp.ilat) * dlat2m;
            final double r12 = x1 * x1 + y1 * y1;
            final double r22 = x2 * x2 + y2 * y2;
            double radius = Math.abs(r12 < r22 ? y1 * dx - x1 * dy : y2 * dx - x2 * dy) / d;

            if (radius <= mwp.radius) {
                double s1 = x1 * dx + y1 * dy;
                double s2 = x2 * dx + y2 * dy;

                if (s1 < 0.) {
                    s1 = -s1;
                    s2 = -s2;
                }
                if (s2 > 0.) {
                    radius = Math.sqrt(s1 < s2 ? r12 : r22);
                    if (radius > mwp.radius) {
                        continue;
                    }
                }
                // new match for that waypoint
                mwp.radius = radius; // shortest distance to way
                mwp.hasUpdate = true;
                anyUpdate = true;
                // calculate crosspoint
                if (mwp.crosspoint == null) {
                    mwp.crosspoint = new OsmNode();
                }
                if (s2 < 0.) {
                    final double wayfraction = -s2 / (d * d);
                    final double xm = x2 - wayfraction * dx;
                    final double ym = y2 - wayfraction * dy;
                    mwp.crosspoint.ilon = (int) (xm / dlon2m + wp.ilon);
                    mwp.crosspoint.ilat = (int) (ym / dlat2m + wp.ilat);
                } else if (s1 > s2) {
                    mwp.crosspoint.ilon = lon2;
                    mwp.crosspoint.ilat = lat2;
                } else {
                    mwp.crosspoint.ilon = lon1;
                    mwp.crosspoint.ilat = lat1;
                }
            }
        }
    }
the WaypointMatcher is feeded by the decoder with geoemtries of ways that are
already check for allowed access according to the current routing profile
<p>
It matches these geometries against the list of waypoints to find the best
match for each waypoint
main/src/main/java/cgeo/geocaching/brouter/mapaccess/WaypointMatcherImpl.java