001/*-
002 * #%L
003 * HAPI FHIR JPA - Search Parameters
004 * %%
005 * Copyright (C) 2014 - 2024 Smile CDR, Inc.
006 * %%
007 * Licensed under the Apache License, Version 2.0 (the "License");
008 * you may not use this file except in compliance with the License.
009 * You may obtain a copy of the License at
010 *
011 *      http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 * #L%
019 */
020package ca.uhn.fhir.jpa.searchparam.extractor;
021
022/**
023 * This class fully and unabashedly stolen from Hibernate search 5.11.4 FINAL's implementation as it was stripped in HS6
024 */
025public class GeopointNormalizer {
026
027        static int WHOLE_CIRCLE_DEGREE_RANGE = 360;
028        static int LONGITUDE_DEGREE_RANGE = WHOLE_CIRCLE_DEGREE_RANGE;
029        static int LATITUDE_DEGREE_RANGE = WHOLE_CIRCLE_DEGREE_RANGE / 2;
030        static int LATITUDE_DEGREE_MIN = -LATITUDE_DEGREE_RANGE / 2;
031        static int LATITUDE_DEGREE_MAX = LATITUDE_DEGREE_RANGE / 2;
032
033        public static double normalizeLongitude(double longitude) {
034                if (longitude == (-LONGITUDE_DEGREE_RANGE / 2)) {
035                        return LONGITUDE_DEGREE_RANGE / 2;
036                } else {
037                        return normalizeLongitudeInclusive(longitude);
038                }
039        }
040
041        public static double normalizeLongitudeInclusive(double longitude) {
042                if ((longitude < -(LONGITUDE_DEGREE_RANGE / 2)) || (longitude > (LONGITUDE_DEGREE_RANGE / 2))) {
043                        double _longitude;
044                        // shift 180 and normalize full circle turn
045                        _longitude = ((longitude + (LONGITUDE_DEGREE_RANGE / 2)) % WHOLE_CIRCLE_DEGREE_RANGE);
046                        // as Java % is not a math modulus we may have negative numbers so the unshift is sign dependant
047                        if (_longitude < 0) {
048                                _longitude = _longitude + (LONGITUDE_DEGREE_RANGE / 2);
049                        } else {
050                                _longitude = _longitude - (LONGITUDE_DEGREE_RANGE / 2);
051                        }
052                        return _longitude;
053                } else {
054                        return longitude;
055                }
056        }
057
058        /**
059         * @param latitude in degrees
060         * @return latitude normalized in [-90;+90]
061         */
062        public static double normalizeLatitude(double latitude) {
063                if (latitude > LATITUDE_DEGREE_MAX || latitude < LATITUDE_DEGREE_MIN) {
064                        // shift 90, normalize full circle turn and 'symmetry' on the lat axis with abs
065                        double _latitude = Math.abs((latitude + (LATITUDE_DEGREE_RANGE / 2)) % (WHOLE_CIRCLE_DEGREE_RANGE));
066                        // Push 2nd and 3rd quadran in 1st and 4th by 'symmetry'
067                        if (_latitude > LATITUDE_DEGREE_RANGE) {
068                                _latitude = WHOLE_CIRCLE_DEGREE_RANGE - _latitude;
069                        }
070                        // unshift
071                        _latitude = _latitude - (LATITUDE_DEGREE_RANGE / 2);
072                        return _latitude;
073                } else {
074                        return latitude;
075                }
076        }
077}