diff options
Diffstat (limited to 'android-app/app/src/main/temp/HeadingDataProcessor.kt')
| -rwxr-xr-x | android-app/app/src/main/temp/HeadingDataProcessor.kt | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/android-app/app/src/main/temp/HeadingDataProcessor.kt b/android-app/app/src/main/temp/HeadingDataProcessor.kt new file mode 100755 index 0000000..7625f90 --- /dev/null +++ b/android-app/app/src/main/temp/HeadingDataProcessor.kt @@ -0,0 +1,108 @@ +package org.terst.nav.temp // Temporarily placing in 'temp' due to permissions + +import android.hardware.GeomagneticField +import android.location.Location +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.update +import java.util.Date + +/** + * Data class representing processed heading information. + * @param trueHeading The heading relative to true North (0-359.9 degrees). + * @param magneticHeading The heading relative to magnetic North (0-359.9 degrees). + * @param magneticVariation The difference between true and magnetic North at the current location (+E, -W). + * @param cog Course Over Ground (0-359.9 degrees). + */ +data class HeadingInfo( + val trueHeading: Float, + val magneticHeading: Float, + val magneticVariation: Float, + val cog: Float +) + +/** + * Processor for handling heading data, including magnetic variation calculations + * using the Android GeomagneticField. + */ +class HeadingDataProcessor { + + private val _headingInfoFlow = MutableStateFlow(HeadingInfo(0f, 0f, 0f, 0f)) + val headingInfoFlow: StateFlow<HeadingInfo> = _headingInfoFlow.asStateFlow() + + private var currentLatitude: Double = 0.0 + private var currentLongitude: Double = 0.0 + private var currentAltitude: Double = 0.0 + + /** + * Updates the current geographic location for magnetic variation calculations. + */ + fun updateLocation(latitude: Double, longitude: Double, altitude: Double) { + currentLatitude = latitude + currentLongitude = longitude + currentAltitude = altitude + // Recalculate magnetic variation if location changes + updateHeadingInfo(_headingInfoFlow.value.trueHeading, _headingInfoFlow.value.cog, true) + } + + /** + * Processes a new true heading and Course Over Ground (COG) value. + * @param newTrueHeading The new true heading in degrees. + * @param newCog The new COG in degrees. + */ + fun updateTrueHeadingAndCog(newTrueHeading: Float, newCog: Float) { + updateHeadingInfo(newTrueHeading, newCog, true) + } + + /** + * Processes a new magnetic heading and Course Over Ground (COG) value. + * @param newMagneticHeading The new magnetic heading in degrees. + * @param newCog The new COG in degrees. + */ + fun updateMagneticHeadingAndCog(newMagneticHeading: Float, newCog: Float) { + updateHeadingInfo(newMagneticHeading, newCog, false) + } + + private fun updateHeadingInfo(heading: Float, cog: Float, isTrueHeadingInput: Boolean) { + val magneticVariation = calculateMagneticVariation() + val (finalTrueHeading, finalMagneticHeading) = if (isTrueHeadingInput) { + Pair(heading, (heading - magneticVariation + 360) % 360) + } else { + Pair((heading + magneticVariation + 360) % 360, heading) + } + + _headingInfoFlow.update { + it.copy( + trueHeading = finalTrueHeading, + magneticHeading = finalMagneticHeading, + magneticVariation = magneticVariation, + cog = cog + ) + } + } + + /** + * Calculates the magnetic variation (declination) for the current location. + * @return Magnetic variation in degrees (+E, -W). + */ + private fun calculateMagneticVariation(): Float { + // GeomagneticField requires current time in milliseconds + val currentTimeMillis = System.currentTimeMillis() + + // Create a dummy Location object to get altitude if only lat/lon are updated + // GeomagneticField needs altitude, using 0 if not provided + val geoField = GeomagneticField( + currentLatitude.toFloat(), + currentLongitude.toFloat(), + currentAltitude.toFloat(), // Altitude in meters + currentTimeMillis + ) + return geoField.declination // Declination is the magnetic variation + } + + // Helper function to normalize angles (0-359.9) - though modulo handles this for positive floats + private fun normalizeAngle(angle: Float): Float { + return (angle % 360 + 360) % 360 + } +} |
