React Native: importing a component within componentWillMount - javascript

I need to call a function in componentWillMount, but I don't want it to sit in the same file.
Is there a way to reference the function in componentWillMount?
Here is the code, I have left off a lot of the code which isn't relevant to this problem as I'm in the middle of refactoring (thus this question!):
Midpoint.js:
import React, { Component } from 'react';
class Midpoint extends Component {
midpoint(lat1, lng1, lat2, lng2) {
const rad = (Math.PI) / 180;
const rlat1 = lat1 * rad;
const rlng1 = lng1 * rad;
const rlat2 = lat2 * rad;
const rlng2 = lng2 * rad;
const dlng = rlng2 - rlng1;
const Bx = Math.cos(rlat2) * Math.cos(dlng);
const By = Math.cos(rlat2) * Math.sin(dlng);
const lat3 = Math.atan2(Math.sin(rlat1) + Math.sin(rlat2),
Math.sqrt(((Math.cos(rlat1) + Bx) * (Math.cos(rlat1) + Bx)) + (By * By)));
const lng3 = rlng1 + Math.atan2(By, (Math.cos(rlat1) + Bx));
const lat = (lat3 * 180) / Math.PI;
const lng = (lng3 * 180) / Math.PI;
this.setState({ lat2: lat, lng2: lng });
}
}
export default Midpoint;
This is the function I want to import into the below:
ResultsPage.js:
import React, { Component } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import getDirections from 'react-native-google-maps-directions';
import axios from 'axios';
import Midpoint from './Midpoint';
import { Card, CardSection, Button } from './common';
class ResultsPage extends Component {
state = {}
componentWillMount() {
.then(response => { Midpoint.midpoint(this.state.p1Latitude, this.state.p1Longitude, this.state.p2Latitude, this.state.p2Longitude) })
}
The error I receive is _Midpoint2.default.midpoint is not a function

You are trying to call a component like it is was a function, if the only objective of Midpoint is to calculate the latlng then don`t make it a React Component just export the function
export default function calculateMidpoint(lat1, lng1, lat2, lng2) {
const rad = (Math.PI) / 180;
const rlat1 = lat1 * rad;
const rlng1 = lng1 * rad;
const rlat2 = lat2 * rad;
const rlng2 = lng2 * rad;
const dlng = rlng2 - rlng1;
const Bx = Math.cos(rlat2) * Math.cos(dlng);
const By = Math.cos(rlat2) * Math.sin(dlng);
const lat3 = Math.atan2(Math.sin(rlat1) + Math.sin(rlat2),
Math.sqrt(((Math.cos(rlat1) + Bx) * (Math.cos(rlat1) + Bx)) + (By * By)));
const lng3 = rlng1 + Math.atan2(By, (Math.cos(rlat1) + Bx));
const lat = (lat3 * 180) / Math.PI;
const lng = (lng3 * 180) / Math.PI;
return { lat, lng }
}
but if Midpoint has to be a component just extract the logic like we did in the last example and put it in a diferent file and call it in the Results and Midpoint components
let say you put the function in Utils.js in the same directory
ResultsPage.js
import React, { Component } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import getDirections from 'react-native-google-maps-directions';
import axios from 'axios';
import calculateMidpoint from './Utils';
import { Card, CardSection, Button } from './common';
class ResultsPage extends Component {
state = {}
componentWillMount() {
let latlng = calculateMidpoint(this.state.p1Latitude, this.state.p1Longitude, this.state.p2Latitude, this.state.p2Longitude)
}
and Midpoint.js
import React, { Component } from 'react';
import calculateMidpoint from './Utils';
class Midpoint extends Component {
midpoint(lat1, lng1, lat2, lng2) {
let latlng = calculateMidpoint(lat1, lng1, lat2, lng2)
this.setState({ lat2: latlng.lat, lng2: latlng,lng });
}
}
export default Midpoint;
also, you have an error in componentWillMount where you are calling a .then() out of nowhere

Related

error: Error: Unable to resolve module ./styles from C:\Users\user\Desktop\project\project\src\Screens\OtpVerification\OtpVerifications.js:

How can i fix this error i have done import the file but still that problem can anyone can tell how to fix this i just want to use my responsiveSize file in my otpverificaltion file earlier their was not error but after i want to test a function so i copy optveri code than test the function and than paste the same code as it was written earlier but now the error is coming the file was clear when i pasted my optveri code
error is
error: Error: Unable to resolve module ./styles from C:\Users\user\Desktop\project\project\src\Screens\OtpVerification\OtpVerifications.js:
None of these files exist:
* src\Screens\OtpVerification\styles(.native|.android.js|.native.js|.js|.android.json|.native.json|.json|.android.ts|.native.ts|.ts|.android.tsx|.native.tsx|.tsx)
* src\Screens\OtpVerification\styles\index(.native|.android.js|.native.js|.js|.android.json|.native.json|.json|.android.ts|.native.ts|.ts|.android.tsx|.native.tsx|.tsx)
8 | import strings from '../../constatns/lang';
9 | import navigationStrings from '../../constatns/navigationStrings';
> 10 | import { moderateScale, } from '../../styles/responsiveSize';
| ^
11 | import styles from './styles';
12 | import OtpInputs from 'react-native-otp-inputs';
13 | import actions from '../../reudx/actions';
My import code
//import liraries
import React, { Component } from 'react';
import { View, Text, StyleSheet, TouchableOpacity, Image } from 'react-native';
import HeaderComponent from '../../Components/HeaderComponent';
import HorizontalLine from '../../Components/HorizontalLine';
import WrapperContainer from '../../Components/WrapperContainer';
import imagePath from '../../constatns/imagePath';
import strings from '../../constatns/lang';
import navigationStrings from '../../constatns/navigationStrings';
import { moderateScale, moderateScaleVertical } from '../../styles/responsiveSize';
import styles from './styles';
import OtpInputs from 'react-native-otp-inputs';
import actions from '../../reudx/actions';
why i am using responsiveSize file
i am just using that because i want that the app screen ui can change according to the user phone size you can see the code also
import { Dimensions, StatusBar } from 'react-native';
const { width, height } = Dimensions.get('window');
const guidelineBaseWidth = 375;
const guidelineBaseHeight = 812;
const scale = size => (width / guidelineBaseWidth) * size;
const verticalScale = size => (height / guidelineBaseHeight) * size;
const moderateScale = (size, factor = 0.5) => size + (scale(size) - size) * factor;
const moderateScaleVertical = (size, factor = 0.5) => size + (verticalScale(size) - size) * factor;
const textScale = percent => {
const screenHeight = Dimensions.get('window').height;
//calculate absolute ratio for bigger screens 18.5:9 requiring smaller scaling
const ratio = Dimensions.get('window').height / Dimensions.get('window').width;
//Guideline sizes are based on standard ~5″ screen mobile device
const deviceHeight = 375
? screenHeight * (ratio > 1.8 ? 0.126 : 0.15) //Set guideline depending on absolute ratio
: Platform.OS === 'android'
? screenHeight - StatusBar.currentHeight
: screenHeight;
const heightPercent = (percent * deviceHeight) / 100;
return Math.round(heightPercent);
};
export { scale, verticalScale, textScale, moderateScale, moderateScaleVertical,width,height };

React native and firestore: geohash nearby search to given distance with wrong results

I need to work with geohashs. I have to check if a target position as geohash is in the range (distance) of my current position as geohash. Its actually working but I have noticed large range differences. So I have written a Tester where I don't need my database to show you the problem.
Start reading in the GeoTest() function I have defined a start position as lat, lon coordinates and also encoded as geohash.
Then I have put a distance/range value in miles.
With both I can compute the lower and upper geohashs.
With the lower and upper geohashs I could compare geohashs of other places (in firestore) to check if they are in the the range or not. At this point there are wrong results. For example a place is in 600 mile distance but at 320 mile the result is already its in range. Thats wrong.
I decode the upper and lower again to the lat, lon values and compute the distance just on the coordinates (not geohashs) to show you the difference and that the distance is nearly doubled up. Sometimes its higher as factor 2, sometimes lower. Its different if I chose different distance values.
In my opinion if I put in 10 miles distance, encode the ranges and decode them to recalculate the distance it should stay 10 miles. Maybe some small difference because of roundings but no 20.37, thats twice as high as expected.
The question is now, why is the distance after decoding higher as before? Did I miss some calculation anywhere?
So I can't check exactly if positions are in the given range of or not.
I know in client code I could work on coordinates only but the places are given as geohashs in firestore and I have to fetch the places which are in the range directly from there without filtering on client side. So thats not an option and I think it could work if I had the right Math. Thank you.
GeoTester.js:
import geohash from "ngeohash";
export const GeoTester = () => {
const getDistance = (startLat, startLon, targetLat, targetLon) => {
const dLat = (startLat-targetLat) * Math.PI / 180;
const dLon = (startLon-targetLon) * Math.PI / 180;
const lat1 = targetLat * Math.PI / 180;
const lat2 = startLat * Math.PI / 180;
const a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
const d = 6371 * c;
return d;
}
const getGeohashRange = (latitude, longitude, distance) => {
const latDeg = 0.0144927536231884; // degrees latitude per mile
const lonDeg = 0.0181818181818182; // degrees longitude per mile
const lowerLat = latitude - latDeg * distance;
const lowerLon = longitude - lonDeg * distance;
const upperLat = latitude + latDeg * distance;
const upperLon = longitude + lonDeg * distance;
const lowerGeohash = geohash.encode(lowerLat, lowerLon);
const upperGeohash = geohash.encode(upperLat, upperLon);
return { lowerGeohash, upperGeohash };
}
const geoTest = () => {
const startLat = 52.00991050587265;
const startLon = 4.708180705155277;
const startGeohash = geohash.encode(startLat, startLon);
const distance = 10; // miles
const { lowerGeohash, upperGeohash } = getGeohashRange(startLat, startLon, distance);
const lowerDecoded = geohash.decode(lowerGeohash);
const upperDecoded = geohash.decode(upperGeohash);
const distLower = getDistance(startLat, startLon, lowerDecoded.latitude, lowerDecoded.longitude);
const distUpper = getDistance(startLat, startLon, upperDecoded.latitude, upperDecoded.longitude);
const diffLower = (distLower / distance);
const diffUpper = (distUpper / distance);
console.log('distance and diff lower', distLower, diffLower);
console.log('distance and diff upper', distUpper, diffUpper);
}
return {
geoTest
};
}
App.js:
import React from 'react';
import {View, Button} from 'react-native';
import {GeoTester} from '../helpers/GeoTester';
const App = () => {
const { geoTest } = GeoTester();
return (
<View>
<Button title="Test" onPress={() => geoTest()} />
</View>
);
}
export default App;
console.log output:
distance and diff lower 20.374469782722997 2.0374469782722997
distance and diff upper 20.347694449540903 2.0347694449540903

React.js output shows as NaN

Hi as stated above my output keeps showing up as NaN and I'm really struggling to fix it.
There are ultimately three classes that will touch the code. App.js, Calculate.js, and Calculations.js where all of the functions are stored. In Calculate.js, I am importing two functions from Calculations.js with the hopes of producing their output after data is taken in from four input fields and a button press. The code for all three files is below.Please help, I truly am lost now.
Edit: it should be noted the calculations were given to us and are basically unmodifiable.
App.js
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import Calculate from './components/Calculate';
import Clear from './components/Clear';
//need to put clear underneath Calculate
export default function App() {
return (
<View style={styles.container}>
<Text> 'Please enter your coordinates you wish to calculate.' </Text>
<Calculate buttonTitle = 'Calculate'/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
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, lon1, lat2, lon2);
state.bearing = computeBearing(lat1, lon1, lat2, lon2);
updateStateObject({distance: `Distance: ${distance}`});
updateStateObject({bearing: `Bearing: ${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);
}
Output
So apparently I have had a misunderstanding on what state is and how it is used. The working button should read as the following:
<Button
title={buttonTitle}
onPress = {() =>{updateStateObject({
distance: `Distance: ${computeDistance( parseFloat(lat1), parseFloat(lon1), parseFloat(lat2), parseFloat(lon2))}`,
bearing: `Bearing: ${computeBearing( parseFloat(lat1), parseFloat(lon1), parseFloat(lat2), parseFloat(lon2))}`,
})
}}
/>

Calculate Wheel Data XY Position

I tried to create a lucky draw wheel using reactjs, first, I need to place all the input data to a certain XY position. Below is the expected output XY position example what I need.
var renderData = ["1","2","3","4","5","6","7","8","9","10","11","12"];
React.createElement('div', { className: '_data'},
renderData.map((index,item)=>{
var itemPosition = index / renderData.length * 360;
var itemX = itemPosition * Math.PI/180;
var itemY = itemPosition * Math.PI/180;
return React.createElement('div', { className: '_items',
style:{top:itemX,left:itemY}
},item);
})
)
So I use createElement to create div for each of the data, then using top and left for XY position.
How to calculate the XY position for each div
Update
After tried the #keikai answer
var renderData = ["1","2","3","4","5","6","7","8","9","10","11","12"];
const r = 350;
const len = renderData.length;
const radiusList = renderData.map(x => (360 / len) * (x - 1));
const positionPairList = radiusList.map(x => ({
x: Math.sin((Math.PI * x) / 180) * r,
y: Math.cos((Math.PI * x) / 180) * r
}));
React.createElement('div', { className: '_data'},
renderData.map((item, index) => {
return React.createElement('div', { className: `_items`,
style:{top:`${positionPairList[index].x.toFixed(2)}px`,left:`${positionPairList[index].y.toFixed(2)}px`}
},item);
})
)
all data are rotated 0deg
child div still not place to the right position inside parent div
for clockwise, it starts from 10?
Update: rotate display with clock styles
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
function App() {
const n = 12;
const r = 500;
const radiusList = Array.from(Array(n).keys()).map(x => (360 / n) * x);
const positionPairList = radiusList.map(item => ({
x: Math.sin((Math.PI * item) / 180) * r,
y: Math.cos((Math.PI * item) / 180) * r
}));
return (
<div className="App">
{positionPairList.map((item, index) => {
const offset = index === 0 ? n : 0;
return (
<div
className="Parts"
style={{
top: `${r - item.y.toFixed(0)}px`,
right: `${r + 200 - item.x.toFixed(0)}px`,
transform: `rotate(${radiusList[index]}deg)`
}}
>
{index + offset}
</div>
);
})}
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Calculate distance between 2 co-ordinates [duplicate]

How do you calculate the distance between two markers in Google maps V3? (Similar to the distanceFrom function inV2.)
Thanks..
If you want to calculate it yourself, then you can use the Haversine formula:
var rad = function(x) {
return x * Math.PI / 180;
};
var getDistance = function(p1, p2) {
var R = 6378137; // Earth’s mean radius in meter
var dLat = rad(p2.lat() - p1.lat());
var dLong = rad(p2.lng() - p1.lng());
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(rad(p1.lat())) * Math.cos(rad(p2.lat())) *
Math.sin(dLong / 2) * Math.sin(dLong / 2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var d = R * c;
return d; // returns the distance in meter
};
There actually seems to be a method in GMap3. It's a static method of the google.maps.geometry.spherical namespace.
It takes as arguments two LatLng objects and will utilize a default Earth radius of 6378137 meters, although the default radius can be overridden with a custom value if necessary.
Make sure you include:
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false&v=3&libraries=geometry"></script>
in your head section.
The call will be:
google.maps.geometry.spherical.computeDistanceBetween (latLngA, latLngB);
Example using GPS latitude/longitude of 2 points.
var latitude1 = 39.46;
var longitude1 = -0.36;
var latitude2 = 40.40;
var longitude2 = -3.68;
var distance = google.maps.geometry.spherical.computeDistanceBetween(new google.maps.LatLng(latitude1, longitude1), new google.maps.LatLng(latitude2, longitude2));
Just add this to the beginning of your JavaScript code:
google.maps.LatLng.prototype.distanceFrom = function(latlng) {
var lat = [this.lat(), latlng.lat()]
var lng = [this.lng(), latlng.lng()]
var R = 6378137;
var dLat = (lat[1]-lat[0]) * Math.PI / 180;
var dLng = (lng[1]-lng[0]) * Math.PI / 180;
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(lat[0] * Math.PI / 180 ) * Math.cos(lat[1] * Math.PI / 180 ) *
Math.sin(dLng/2) * Math.sin(dLng/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;
return Math.round(d);
}
and then use the function like this:
var loc1 = new GLatLng(52.5773139, 1.3712427);
var loc2 = new GLatLng(52.4788314, 1.7577444);
var dist = loc2.distanceFrom(loc1);
alert(dist/1000);
//p1 and p2 are google.maps.LatLng(x,y) objects
function calcDistance(p1, p2) {
var d = (google.maps.geometry.spherical.computeDistanceBetween(p1, p2) / 1000).toFixed(2);
console.log(d);
}
Here is the c# implementation of the this forumula
public class DistanceAlgorithm
{
const double PIx = 3.141592653589793;
const double RADIO = 6378.16;
/// <summary>
/// This class cannot be instantiated.
/// </summary>
private DistanceAlgorithm() { }
/// <summary>
/// Convert degrees to Radians
/// </summary>
/// <param name="x">Degrees</param>
/// <returns>The equivalent in radians</returns>
public static double Radians(double x)
{
return x * PIx / 180;
}
/// <summary>
/// Calculate the distance between two places.
/// </summary>
/// <param name="lon1"></param>
/// <param name="lat1"></param>
/// <param name="lon2"></param>
/// <param name="lat2"></param>
/// <returns></returns>
public static double DistanceBetweenPlaces(
double lon1,
double lat1,
double lon2,
double lat2)
{
double dlon = Radians(lon2 - lon1);
double dlat = Radians(lat2 - lat1);
double a = (Math.Sin(dlat / 2) * Math.Sin(dlat / 2)) + Math.Cos(Radians(lat1)) * Math.Cos(Radians(lat2)) * (Math.Sin(dlon / 2) * Math.Sin(dlon / 2));
double angle = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
return (angle * RADIO) * 0.62137;//distance in miles
}
}
With google you can do it using the spherical api, google.maps.geometry.spherical.computeDistanceBetween (latLngA, latLngB);.
However, if the precision of a spherical projection or a haversine solution is not precise enough for you (e.g. if you're close to the pole or computing longer distances), you should use a different library.
Most information on the subject I found on Wikipedia here.
A trick to see if the precision of any given algorithm is adequate is to fill in the maximum and minimum radius of the earth and see if the difference might cause problems for your use case. Many more details can be found in this article
In the end the google api or haversine will serve most purposes without problems.
Using PHP, you can calculate the distance using this simple function :
// to calculate distance between two lat & lon
function calculate_distance($lat1, $lon1, $lat2, $lon2, $unit='N')
{
$theta = $lon1 - $lon2;
$dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
$dist = acos($dist);
$dist = rad2deg($dist);
$miles = $dist * 60 * 1.1515;
$unit = strtoupper($unit);
if ($unit == "K") {
return ($miles * 1.609344);
} else if ($unit == "N") {
return ($miles * 0.8684);
} else {
return $miles;
}
}
// function ends here
OFFLINE SOLUTION - Haversine Algorithm
In Javascript
var _eQuatorialEarthRadius = 6378.1370;
var _d2r = (Math.PI / 180.0);
function HaversineInM(lat1, long1, lat2, long2)
{
return (1000.0 * HaversineInKM(lat1, long1, lat2, long2));
}
function HaversineInKM(lat1, long1, lat2, long2)
{
var dlong = (long2 - long1) * _d2r;
var dlat = (lat2 - lat1) * _d2r;
var a = Math.pow(Math.sin(dlat / 2.0), 2.0) + Math.cos(lat1 * _d2r) * Math.cos(lat2 * _d2r) * Math.pow(Math.sin(dlong / 2.0), 2.0);
var c = 2.0 * Math.atan2(Math.sqrt(a), Math.sqrt(1.0 - a));
var d = _eQuatorialEarthRadius * c;
return d;
}
var meLat = -33.922982;
var meLong = 151.083853;
var result1 = HaversineInKM(meLat, meLong, -32.236457779983745, 148.69094705162837);
var result2 = HaversineInKM(meLat, meLong, -33.609020205923713, 150.77061469270831);
C#
using System;
public class Program
{
public static void Main()
{
Console.WriteLine("Hello World");
var meLat = -33.922982;
double meLong = 151.083853;
var result1 = HaversineInM(meLat, meLong, -32.236457779983745, 148.69094705162837);
var result2 = HaversineInM(meLat, meLong, -33.609020205923713, 150.77061469270831);
Console.WriteLine(result1);
Console.WriteLine(result2);
}
static double _eQuatorialEarthRadius = 6378.1370D;
static double _d2r = (Math.PI / 180D);
private static int HaversineInM(double lat1, double long1, double lat2, double long2)
{
return (int)(1000D * HaversineInKM(lat1, long1, lat2, long2));
}
private static double HaversineInKM(double lat1, double long1, double lat2, double long2)
{
double dlong = (long2 - long1) * _d2r;
double dlat = (lat2 - lat1) * _d2r;
double a = Math.Pow(Math.Sin(dlat / 2D), 2D) + Math.Cos(lat1 * _d2r) * Math.Cos(lat2 * _d2r) * Math.Pow(Math.Sin(dlong / 2D), 2D);
double c = 2D * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1D - a));
double d = _eQuatorialEarthRadius * c;
return d;
}
}
Reference:
https://en.wikipedia.org/wiki/Great-circle_distance
Had to do it... The action script way
//just make sure you pass a number to the function because it would accept you mother in law...
public var rad = function(x:*) {return x*Math.PI/180;}
protected function distHaversine(p1:Object, p2:Object):Number {
var R:int = 6371; // earth's mean radius in km
var dLat:Number = rad(p2.lat() - p1.lat());
var dLong:Number = rad(p2.lng() - p1.lng());
var a:Number = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(rad(p1.lat())) * Math.cos(rad(p2.lat())) * Math.sin(dLong/2) * Math.sin(dLong/2);
var c:Number = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d:Number = R * c;
return d;
}
In my case it was best to calculate this in SQL Server, since i wanted to take current location and then search for all zip codes within a certain distance from current location. I also had a DB which contained a list of zip codes and their lat longs. Cheers
--will return the radius for a given number
create function getRad(#variable float)--function to return rad
returns float
as
begin
declare #retval float
select #retval=(#variable * PI()/180)
--print #retval
return #retval
end
go
--calc distance
--drop function dbo.getDistance
create function getDistance(#cLat float,#cLong float, #tLat float, #tLong float)
returns float
as
begin
declare #emr float
declare #dLat float
declare #dLong float
declare #a float
declare #distance float
declare #c float
set #emr = 6371--earth mean
set #dLat = dbo.getRad(#tLat - #cLat);
set #dLong = dbo.getRad(#tLong - #cLong);
set #a = sin(#dLat/2)*sin(#dLat/2)+cos(dbo.getRad(#cLat))*cos(dbo.getRad(#tLat))*sin(#dLong/2)*sin(#dLong/2);
set #c = 2*atn2(sqrt(#a),sqrt(1-#a))
set #distance = #emr*#c;
set #distance = #distance * 0.621371 -- i needed it in miles
--print #distance
return #distance;
end
go
--get all zipcodes within 2 miles, the hardcoded #'s would be passed in by C#
select *
from cityzips a where dbo.getDistance(29.76,-95.38,a.lat,a.long) <3
order by zipcode
//JAVA
public Double getDistanceBetweenTwoPoints(Double latitude1, Double longitude1, Double latitude2, Double longitude2) {
final int RADIUS_EARTH = 6371;
double dLat = getRad(latitude2 - latitude1);
double dLong = getRad(longitude2 - longitude1);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(getRad(latitude1)) * Math.cos(getRad(latitude2)) * Math.sin(dLong / 2) * Math.sin(dLong / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return (RADIUS_EARTH * c) * 1000;
}
private Double getRad(Double x) {
return x * Math.PI / 180;
}
/**
* Calculates the haversine distance between point A, and B.
* #param {number[]} latlngA [lat, lng] point A
* #param {number[]} latlngB [lat, lng] point B
* #param {boolean} isMiles If we are using miles, else km.
*/
function haversineDistance(latlngA, latlngB, isMiles) {
const squared = x => x * x;
const toRad = x => (x * Math.PI) / 180;
const R = 6371; // Earth’s mean radius in km
const dLat = toRad(latlngB[0] - latlngA[0]);
const dLon = toRad(latlngB[1] - latlngA[1]);
const dLatSin = squared(Math.sin(dLat / 2));
const dLonSin = squared(Math.sin(dLon / 2));
const a = dLatSin +
(Math.cos(toRad(latlngA[0])) * Math.cos(toRad(latlngB[0])) * dLonSin);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
let distance = R * c;
if (isMiles) distance /= 1.609344;
return distance;
}
I found a version online which is 80% right but plugged in the wrong parameter and is inconsistent in using the inputs, this version fixed that completely
It's Quite easy using Google Distance Matrix service
First step is to activate Distance Matrix service from google API console.
it returns distances between a set of locations.
And apply this simple function
function initMap() {
var bounds = new google.maps.LatLngBounds;
var markersArray = [];
var origin1 = {lat:23.0203, lng: 72.5562};
//var origin2 = 'Ahmedabad, India';
var destinationA = {lat:23.0436503, lng: 72.55008939999993};
//var destinationB = {lat: 23.2156, lng: 72.6369};
var destinationIcon = 'https://chart.googleapis.com/chart?' +
'chst=d_map_pin_letter&chld=D|FF0000|000000';
var originIcon = 'https://chart.googleapis.com/chart?' +
'chst=d_map_pin_letter&chld=O|FFFF00|000000';
var map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 55.53, lng: 9.4},
zoom: 10
});
var geocoder = new google.maps.Geocoder;
var service = new google.maps.DistanceMatrixService;
service.getDistanceMatrix({
origins: [origin1],
destinations: [destinationA],
travelMode: 'DRIVING',
unitSystem: google.maps.UnitSystem.METRIC,
avoidHighways: false,
avoidTolls: false
}, function(response, status) {
if (status !== 'OK') {
alert('Error was: ' + status);
} else {
var originList = response.originAddresses;
var destinationList = response.destinationAddresses;
var outputDiv = document.getElementById('output');
outputDiv.innerHTML = '';
deleteMarkers(markersArray);
var showGeocodedAddressOnMap = function(asDestination) {
var icon = asDestination ? destinationIcon : originIcon;
return function(results, status) {
if (status === 'OK') {
map.fitBounds(bounds.extend(results[0].geometry.location));
markersArray.push(new google.maps.Marker({
map: map,
position: results[0].geometry.location,
icon: icon
}));
} else {
alert('Geocode was not successful due to: ' + status);
}
};
};
for (var i = 0; i < originList.length; i++) {
var results = response.rows[i].elements;
geocoder.geocode({'address': originList[i]},
showGeocodedAddressOnMap(false));
for (var j = 0; j < results.length; j++) {
geocoder.geocode({'address': destinationList[j]},
showGeocodedAddressOnMap(true));
//outputDiv.innerHTML += originList[i] + ' to ' + destinationList[j] + ': ' + results[j].distance.text + ' in ' + results[j].duration.text + '<br>';
outputDiv.innerHTML += results[j].distance.text + '<br>';
}
}
}
});
}
Where origin1 is your location and destinationA is destindation location.you can add above two or more data.
Rad Full Documentation with an example
To calculate distance on Google Maps, you can use Directions API. That will be one of the easiest way to do it. To get data from Google Server, you can use Retrofit or Volley. Both has their own advantage. Take a look at following code where I have used retrofit to implement it:
private void build_retrofit_and_get_response(String type) {
String url = "https://maps.googleapis.com/maps/";
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.build();
RetrofitMaps service = retrofit.create(RetrofitMaps.class);
Call<Example> call = service.getDistanceDuration("metric", origin.latitude + "," + origin.longitude,dest.latitude + "," + dest.longitude, type);
call.enqueue(new Callback<Example>() {
#Override
public void onResponse(Response<Example> response, Retrofit retrofit) {
try {
//Remove previous line from map
if (line != null) {
line.remove();
}
// This loop will go through all the results and add marker on each location.
for (int i = 0; i < response.body().getRoutes().size(); i++) {
String distance = response.body().getRoutes().get(i).getLegs().get(i).getDistance().getText();
String time = response.body().getRoutes().get(i).getLegs().get(i).getDuration().getText();
ShowDistanceDuration.setText("Distance:" + distance + ", Duration:" + time);
String encodedString = response.body().getRoutes().get(0).getOverviewPolyline().getPoints();
List<LatLng> list = decodePoly(encodedString);
line = mMap.addPolyline(new PolylineOptions()
.addAll(list)
.width(20)
.color(Color.RED)
.geodesic(true)
);
}
} catch (Exception e) {
Log.d("onResponse", "There is an error");
e.printStackTrace();
}
}
#Override
public void onFailure(Throwable t) {
Log.d("onFailure", t.toString());
}
});
}
Above is the code of function build_retrofit_and_get_response for calculating distance. Below is corresponding Retrofit Interface:
package com.androidtutorialpoint.googlemapsdistancecalculator;
import com.androidtutorialpoint.googlemapsdistancecalculator.POJO.Example;
import retrofit.Call;
import retrofit.http.GET;
import retrofit.http.Query;
public interface RetrofitMaps {
/*
* Retrofit get annotation with our URL
* And our method that will return us details of student.
*/
#GET("api/directions/json?key=AIzaSyC22GfkHu9FdgT9SwdCWMwKX1a4aohGifM")
Call<Example> getDistanceDuration(#Query("units") String units, #Query("origin") String origin, #Query("destination") String destination, #Query("mode") String mode);
}
I hope this explains your query. All the best :)
Source: Google Maps Distance Calculator
First, are you referring to distance as in length of the entire path or you want to know only the displacement (straight line distance)? I see no one is pointing the difference between distance and displacement here. For distance calculate each route point given by JSON/XML data, as for displacement there is a built-in solution using Spherical class
//calculates distance between two points in km's
function calcDistance(p1, p2) {
return (google.maps.geometry.spherical.computeDistanceBetween(p1, p2) / 1000).toFixed(2);
}
In PHP, with Google Map Distance Matrix API:
//Get the Driving(Mode) distance between two Geo-location points(Latitude, Longitude) pair.
function get_distance($lat1, $lat2, $long1, $long2)
{
$url = "https://maps.googleapis.com/maps/api/distancematrix/json?origins=".$lat1.",".$long1."&destinations=".$lat2.",".$long2."&mode=driving"."&units=imperial";
//You can request distance data for different travel modes, request distance data in different units such as kilometers or miles, and estimate travel time in traffic.
try{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_PROXYPORT, 3128);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
$response = curl_exec($ch);
curl_close($ch);
$response_a = json_decode($response, true);
//Invalid request OR Empty response
if(isset($response_a['error_message']) || empty($response_a['rows']))
throw new Exception($response_a['error_message']);
} catch(Exception $e){
//Handle error here.
return [];
}
//The unit parameter in the request URL only affects the text displayed within distance fields. The distance fields in response also contain values that are always expressed in meters.
$dist = $response_a['rows'][0]['elements'][0]['distance']['text'];
$time = $response_a['rows'][0]['elements'][0]['duration']['text'];
return ['distance' => $dist, 'time' => $time];
}
Reference: Distance Matrix API request and response

Categories