React.js output shows as NaN - javascript

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))}`,
})
}}
/>

Related

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

Create three.js components with map method

I've created a react-three-fiber functional component to load a glb file of a butterfly with animation and I am returning a primitive with the scene of the glb passed as an object prop. It is nested in a mesh, that is nested in a scene, that is nested in a group.
function Butterfly({ speed, factor, url, ...props }) {
const { scene, nodes, materials, animations } = useLoader(GLTFLoader, url);
const group = useRef()
const [mixer] = useState(() => new THREE.AnimationMixer())
useEffect(() => mixer.clipAction(animations[0], group.current).play(), [])
useFrame((state, delta) => {
group.current.rotation.y -= Math.sin((delta * factor) / 2) * Math.cos((delta * factor) / 2) * 2
mixer.update(delta * speed)
})
return (
<group ref={group} dispose={null}>
<scene name="Scene" {...props}>
<mesh
name="Object_0"
>
<primitive object={scene}/>
</mesh>
</scene>
</group>
)
}
This component is then returned in separate function in each iteration of an array.
function Butterflies() {
const copyArray = new Array(100).fill()
console.log(copyArray);
return copyArray.map((j, i) => {
const x = (15 + Math.random() * 30) * (Math.round(Math.random()) ? -1 : 1)
const y = -10 + Math.random() * 20
const z = -5 + Math.random() * 10
return <Butterfly key={i} position={[x, y, z]} rotation={[0, x > 0 ? Math.PI : 0, 0]} speed='5' factor='1.5' url='/blue_butterfly.glb' />
})
}
However, this function is only returning one butterfly instead of 100.
single butterfly
I think my issue has something to do with the return in the Butterfly component. I've tried only returning the primitive with props and a ref, but that doesn't render anything. I've tried going through the console.log of the the glb file and found the geometry and tried passing that as a prop to the mesh along with the materials, but that only rendered a white butterfly shape without the animation from the scene. Why is this only returning 1 butterfly instead of 100?
I assume Butterflies() is in Butterflies.js and you are trying return many <Butterfly> here, however react component can only have one parent.
try this in Butterflies():
function Butterflies() {
const copyArray = new Array(100).fill()
console.log(copyArray);
return(
<>
{copyArray.map((j, i) => {
const x = (15 + Math.random() * 30) * (Math.round(Math.random()) ? -1 : 1)
const y = -10 + Math.random() * 20
const z = -5 + Math.random() * 10
return <Butterfly key={i} position={[x, y, z]} rotation={[0, x > 0 ? Math.PI : 0, 0]} speed='5' factor='1.5' url='/blue_butterfly.glb' />
})}
</>)}
Or store it in a variable first, for the example:
function Butterflies() {
const copyArray = new Array(100).fill()
console.log(copyArray);
const items=copyArray.map((j, i) => {
const x = (15 + Math.random() * 30) * (Math.round(Math.random()) ? -1 : 1)
const y = -10 + Math.random() * 20
const z = -5 + Math.random() * 10
return <Butterfly key={i} position={[x, y, z]} rotation={[0, x > 0 ? Math.PI : 0, 0]} speed='5' factor='1.5' url='/blue_butterfly.glb' />
})
return(
<>
{items}
</>
)}

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);

React-konva double connected objects with arrow

I'm trying to expand the Connected Objects demo by allowing two nodes (shapes of Circle class) to be double referenced (A connects to B with Arrow1 and B connects to A with Arrow2). I work with react-konva package.
I have implemented a demo on Code Sandbox with some basic functionality.
On line 5, 6 you'll find the Nodes info, on line 21 there exists a high-order component that creates the Arrow based on the start Node and end Node position.
In the default example, the arrows are working as expected. If you try to set the value of redNode.x to 300 the arrows overlap. The same happens when blueNode.x is equal to -100. This has something to do with the way I calculate the arrows (I suspect the equations on line 38).
Also note that as redNode.x moves to value 300, the two arrows approach each other (this happens on other values too), which is something I do not want to happen. I expect the arrows to have the same shape when the two nodes change position and not to overlap or approach each other. Unfortunately, my lack of mathematics does not help me solve the problem. I also tried to create a custom shape using quadraticCurveTo method without success.
Thanks in advance for the help. I appreciate all the solutions.
There are many ways to make curved lines. Here is my attempt to make it better:
import React from "react";
import ReactDOM from "react-dom";
import { Stage, Layer, Circle, Arrow, Text } from "react-konva";
const BLUE_DEFAULTS = {
x: 100,
y: 100,
fill: "blue",
width: 30,
height: 30,
draggable: true
};
const RED_DEFAULTS = {
x: 100,
y: 300,
fill: "red",
width: 30,
height: 30,
draggable: true
};
const Edge = ({ node1, node2 }) => {
const dx = node1.x - node2.x;
const dy = node1.y - node2.y;
let angle = Math.atan2(-dy, dx);
const radius = 20;
const curvePower = 30;
const arrowStart = {
x: node2.x + -radius * Math.cos(angle + Math.PI),
y: node2.y + radius * Math.sin(angle + Math.PI)
};
const arrowEnd = {
x: node1.x + -radius * Math.cos(angle),
y: node1.y + radius * Math.sin(angle)
};
const arrowCurve = {
x:
(arrowStart.x + arrowEnd.x) / 2 +
curvePower * Math.cos(angle + Math.PI / 2),
y:
(arrowStart.y + arrowEnd.y) / 2 +
curvePower * Math.sin(angle - Math.PI / 2)
};
return (
<Arrow
tension={0.2}
points={[
arrowStart.x,
arrowStart.y,
arrowCurve.x,
arrowCurve.y,
arrowEnd.x,
arrowEnd.y
]}
stroke="#000"
fill="#000"
strokeWidth={3}
pointerWidth={6}
/>
);
};
const App = () => {
const [blueNode, updateBlueNode] = React.useState(BLUE_DEFAULTS);
const [redNode, updateRedNode] = React.useState(RED_DEFAULTS);
return (
<Stage width={window.innerWidth} height={window.innerHeight}>
<Layer>
<Text text="Drag any node to see connections change" />
<Edge node1={blueNode} node2={redNode} />
<Edge node1={redNode} node2={blueNode} />
<Circle
{...blueNode}
onDragMove={e => {
updateBlueNode({ ...blueNode, ...e.target.position() });
}}
/>
<Circle
{...redNode}
onDragMove={e => {
updateRedNode({ ...redNode, ...e.target.position() });
}}
/>
</Layer>
</Stage>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Demo: https://codesandbox.io/s/react-konva-double-connected-objects-m5g22

React Native: importing a component within componentWillMount

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

Categories