1

I have an app that calculates the distance traveled and bearing between one coordinate to another. What I want to happen onPress is to display the distance and bearing beneath the button. I've been trying for some time and cannot figure out how to supply an output. I have the calculate class that exports to the app.js which controls the display.

After pressing calculate the only output is: Bearing: NaN.

What it should be printing beneath the input boxes and buttons is:

Distance: (distance)km
Bearing: (bearing)

Any guidance would be very much appreciated.

Calculate.js

import React, { useState} from 'react';
import {StyleSheet, Text, View, TextInput} from 'react-native';
import {Button} from 'react-native-elements';
import {computeDistance, computeBearing} from './Calculations';

const Calculate = ({buttonTitle, lat1, lon1, lat2,lon2, distance, bearing}) => {
    const [state, setState] = useState({lat1: '', lon1: '', lat2: '', lon2: '', distance: '', bearing: ''});

    const updateStateObject = (vals) =>{
        setState({
            ...state,
            ...vals,
        });
    };
    return (
        <View style={styles.container}>
            <TextInput 
                placeholder = 'Starting latitude' 
                onChangeText = {(lat1) => updateStateObject({lat1: lat1})} //or you could do (val) => {setName(val);}
                value = {state.lat1}/>
            <TextInput 
                placeholder = 'Starting longitude' 
                onChangeText = {(lon1) => updateStateObject({lon1: lon1})} //or you could do (val) => {setName(val);}
                value = {state.lon1}/>
            <TextInput 
                placeholder = 'Ending latitude' 
                onChangeText = {(lat2) => updateStateObject({lat2: lat2})} //or you could do (val) => {setName(val);}
                value = {state.lat2}/>
            <TextInput 
                placeholder = 'Ending longitude' 
                onChangeText = {(lon2) => updateStateObject({lon2: lon2})} //or you could do (val) => {setName(val);}
                value = {state.lon2}/>
            <Button 
            title= {buttonTitle}
            onPress = {() =>{
               state.distance = computeDistance({lat1: lat1}, {lon1: lon1}, {lat2: lat2}, {lon2: lon2});
               state.bearing = computeBearing({lat1: lat1}, {lon1: lon1}, {lat2: lat2}, {lon2: lon2})
                updateStateObject({distance: `Distance: ${state.distance}`});
                updateStateObject({bearing: `Bearing: ${state.bearing}`});
            }} />
            <Text> {state.distance}</Text>
            <Text> {state.bearing}</Text>
        </View>
    );
};

const styles = StyleSheet.create({
    container: {
      flex: 1,
      backgroundColor: '#fff',
      alignItems: 'center',
      justifyContent: 'center',
    },
  });
export default Calculate;

Calculations.js

 // Converts from degrees to radians.
 function toRadians(degrees) {
    return (degrees * Math.PI) / 180;
  }

  // Converts from radians to degrees.
  function toDegrees(radians) {
    return (radians * 180) / Math.PI;
  }

  // Computes distance between two geo coordinates in kilometers.
  export function computeDistance(lat1, lon1, lat2, lon2) {
    console.log(`p1={${lat1},${lon1}} p2={${lat2},${lon2}}`);
    var R = 6371; // km (change this constant to get miles)
    var dLat = ((lat2 - lat1) * Math.PI) / 180;
    var dLon = ((lon2 - lon1) * Math.PI) / 180;
    var a =
      Math.sin(dLat / 2) * Math.sin(dLat / 2) +
      Math.cos((lat1 * Math.PI) / 180) *
        Math.cos((lat2 * Math.PI) / 180) *
        Math.sin(dLon / 2) *
        Math.sin(dLon / 2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    var d = R * c;
    return `${round(d, 3)} km`;
  }

  // Computes bearing between two geo coordinates in degrees.
 export function computeBearing(startLat, startLng, destLat, destLng) {
    startLat = toRadians(startLat);
    startLng = toRadians(startLng);
    destLat = toRadians(destLat);
    destLng = toRadians(destLng);

    var y = Math.sin(destLng - startLng) * Math.cos(destLat);
    var x =
      Math.cos(startLat) * Math.sin(destLat) -
      Math.sin(startLat) * Math.cos(destLat) * Math.cos(destLng - startLng);
    var brng = Math.atan2(y, x);
    brng = toDegrees(brng);
    return (brng + 360) % 360;
  }

  function round(value, decimals) {
    return Number(Math.round(value + "e" + decimals) + "e-" + decimals);
  }

Edit: updated Calculate.js and added Calculations.js

same problem still persists though.

3
  • There is a big chance the bug is in Calculations.js but you didn't provide it :) You need to add code for computeDistance, computeBearing Commented May 20, 2020 at 17:51
  • Setting state is asynchronous, and multiple updates in short succession are batched together. You also have a single coordinate variable in your stare, but you actually have four coordinates. Commented May 20, 2020 at 17:51
  • So I added the calculations file however, I do not think that is the problem because essentially it has been copied and pasted from our assignment as plain text. As far as the coordinates, I updated them to differentiate them from one another. Once again, any help is appreciated. Commented May 20, 2020 at 19:14

1 Answer 1

1

I think in your Calculate component, you are passing objects into your functions but in Calculations.js your functions are expecting variables which are simple values not objects. And the other thing is that the value you are passing in form of objects is the one you are getting as props, not the one you have setted in state, you should use state.lat1, etc.

on your function call, you should change the arguments you are passing into that function

state.distance = computeDistance(state.lat1, state.lon1,state.lat2, state.lon2);

and same in other function call

state.bearing = computeBearing(state.lat1, state.lon1, state.lat2, state.lon2);

and also in your round function in Calculation.js, you are contaminating number with string which will again result in NaN(since the end value will be a string).

Number(Math.round(value + "e" + decimals) + "e-" + decimals);

Sign up to request clarification or add additional context in comments.

4 Comments

Can you expand on this a little bit. I'm pretty to new to JS so sometimes the terminology gets lost in me.
So I have it displaying ``` NaN km Bearing: NaN ``` So I'm one step closer. The code I have is the following. Any suggestions? I'll update the code up top.
on your function call, you should change the arguments you are passing into that function state.distance = computeDistance(state.lat1, state.lon1,state.lat2, state.lon2); and same in other call state.bearing = computeBearing(state.lat1, state.lon1, state.lat2, state.lon2)
I have updated the answer, It may give some help now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.