001/*-
002 * #%L
003 * HAPI FHIR Search Parameters
004 * %%
005 * Copyright (C) 2014 - 2023 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                }
037                else {
038                        return normalizeLongitudeInclusive( longitude );
039                }
040        }
041
042        public static double normalizeLongitudeInclusive(double longitude) {
043                if ( (longitude < -( LONGITUDE_DEGREE_RANGE / 2 ) ) || (longitude > ( LONGITUDE_DEGREE_RANGE / 2 ) ) ) {
044                        double _longitude;
045                        // shift 180 and normalize full circle turn
046                        _longitude = ( ( longitude + ( LONGITUDE_DEGREE_RANGE / 2 ) ) % WHOLE_CIRCLE_DEGREE_RANGE );
047                        // as Java % is not a math modulus we may have negative numbers so the unshift is sign dependant
048                        if ( _longitude < 0 ) {
049                                _longitude = _longitude + ( LONGITUDE_DEGREE_RANGE / 2 );
050                        }
051                        else {
052                                _longitude = _longitude - ( LONGITUDE_DEGREE_RANGE / 2 );
053                        }
054                        return _longitude;
055                }
056                else {
057                        return longitude;
058                }
059        }
060
061        /**
062         * @param latitude in degrees
063         * @return latitude normalized in [-90;+90]
064         */
065        public static double normalizeLatitude(double latitude) {
066                if ( latitude > LATITUDE_DEGREE_MAX || latitude < LATITUDE_DEGREE_MIN ) {
067                        // shift 90, normalize full circle turn and 'symmetry' on the lat axis with abs
068                        double _latitude = Math.abs( ( latitude + ( LATITUDE_DEGREE_RANGE / 2 ) ) % ( WHOLE_CIRCLE_DEGREE_RANGE ) );
069                        // Push 2nd and 3rd quadran in 1st and 4th by 'symmetry'
070                        if ( _latitude > LATITUDE_DEGREE_RANGE ) {
071                                _latitude = WHOLE_CIRCLE_DEGREE_RANGE - _latitude;
072                        }
073                        // unshift
074                        _latitude = _latitude - ( LATITUDE_DEGREE_RANGE / 2 );
075                        return _latitude;
076                }
077                else {
078                        return latitude;
079                }
080        }
081}