public void evaluate()

in endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/ExtentSelector.java [416:523]


    public void evaluate(final GeographicBoundingBox bbox, final Temporal startTime, final Temporal endTime, final T object) {
        /*
         * Get the geographic and temporal intersections. If there is no intersection, no more analysis is done.
         * Note that the intersection is allowed to be zero (empty), which is not the same as no intersection.
         * An empty intersection may happen if the AOI is a single point or the TOI is a single instant.
         */
        Temporal tmin = startTime;
        Temporal tmax = endTime;
        if (tmin != null && minTOI != null && TemporalDate.compare(tmin, minTOI) < 0) tmin = minTOI;
        if (tmax != null && maxTOI != null && TemporalDate.compare(tmax, maxTOI) > 0) tmax = maxTOI;
        final Duration duration;
        if (tmin != null && tmax != null) {
            duration = Duration.between(tmin, tmax);
            if (duration.isNegative()) return;
        } else {
            duration = null;
        }
        final double area = Extents.area(Extents.intersection(bbox, areaOfInterest));
        if (Double.isNaN(area) && bbox != null) {
            return;
        }
        /*
         * Accept the given object if it is the first one (`best == null`) or if it meets the first
         * criterion documented in class javadoc (i.e. covers a longer time than previous object).
         * Other special cases:
         *
         *   - duration == null while old value has  a duration: reject (with comparison < 0).
         *   - duration != null while old value had no duration: accept (with comparison > 0).
         *
         * Those special cases are controlled by the +1 or -1 argument in calls to `compare(…)`.
         * The same pattern is applied for all criteria in inner conditions, using one of:
         *
         *     comparison(…, -1) <= 0
         *     comparison(…, +1) >= 0
         *
         * The criteria are always tested as below:
         *
         *     if ((comparison = comparison(…, ±1)) ⪌ 0) {
         *         if (comparison != 0) return;
         *         // Compute and test criteria.
         *     }
         */
        final Duration durationRounded = round(duration);
        int comparison, remainingFieldsToCompute = OVERTIME;
        if (best != null && (comparison = compare(durationRounded, longestTime, -1)) <= 0) {
            if (comparison != 0) return;
            /*
             * Criterion #2: select the object having smallest amount of time outside Time Of Interest (TOI).
             * See class javadoc for a rational about why this criterion is applied before `temporalDistance`.
             */
            remainingFieldsToCompute = TEMPORAL_DISTANCE;
            final Duration et = overtime(startTime, endTime, duration);
            if ((comparison = compare(et, overtime, +1)) >= 0) {
                if (comparison != 0) return;
                /*
                 * Criterion #3: select the object having median time closest to TOI median time.
                 * This condition is skipped in the "alternate condition ordering" mode.
                 */
                remainingFieldsToCompute = OUTSIDE_AREA;
                final double td = temporalDistance(startTime, endTime);
                if (alternateOrdering || (comparison = compare(td, temporalDistance, +1)) >= 0) {
                    if (comparison != 0) return;
                    /*
                     * Criterion #4: select the object covering largest geographic area.
                     */
                    if ((comparison = compare(area, largestArea, -1)) <= 0) {
                        if (comparison != 0) return;
                        /*
                         * Criterion #5: select the object having less surface outside Area Of Interest (AOI).
                         * Tested before `pseudoDistance` criterion for consistency with temporal domain.
                         */
                        remainingFieldsToCompute = PSEUDO_DISTANCE;
                        final double out = Extents.area(bbox) - area;
                        if ((comparison = compare(out, outsideArea, +1)) >= 0) {
                            if (comparison != 0) return;
                            /*
                             * Criterion #5: select the object having center closest to AOI center.
                             * Distances are computed with inexact formulas (not a real distance).
                             * TOI is also compared here in "alternate condition ordering" mode.
                             */
                            remainingFieldsToCompute = NONE;
                            final double pd = pseudoDistance(bbox);
                            if (compare(pd, pseudoDistance, +1) >= 0) {
                                if (comparison != 0 || !alternateOrdering) return;
                            }
                            if (alternateOrdering && compare(td, temporalDistance, +1) >= 0) {
                                return;
                            }
                            pseudoDistance = pd;
                        }
                        outsideArea = out;
                    }
                    // largestArea = area; assigned below because was computed early.
                }
                temporalDistance = td;
            }
            overtime = et;
        }
        longestTime = durationRounded;
        largestArea = area;
        switch (remainingFieldsToCompute) {           // Intentional fallthrough in every cases.
            case OVERTIME:          overtime          = overtime(startTime, endTime, duration);
            case TEMPORAL_DISTANCE: temporalDistance  = temporalDistance(startTime, endTime);
            case OUTSIDE_AREA:      outsideArea       = Extents.area(bbox) - area;
            case PSEUDO_DISTANCE:   pseudoDistance    = pseudoDistance(bbox);
        }
        best = object;
    }