How to implement Processingview in React Native Expo? - react-native

Here I have implemented ProcessingView in Expo App. But I am getting this error "Check the render method of ProcessingView.". I am not able to find the solution. If anyone has idea then please guide me.
Here I have also attached the image of the screen
import React from 'react';
import { ProcessingView } from 'expo-processing';
export default class App extends React.Component {
render() {
return (
<ProcessingView style={{ flex: 1 }} sketch={this._sketch} />
);
}
_sketch = (p) => {
p.setup = () => {
p.strokeWeight(7);
}
const harom = (ax, ay, bx, by, level, ratio) => {
if (level <= 0) {
return;
}
const vx = bx - ax;
const vy = by - ay;
const nx = p.cos(p.PI / 3) * vx - p.sin(p.PI / 3) * vy;
const ny = p.sin(p.PI / 3) * vx + p.cos(p.PI / 3) * vy;
const cx = ax + nx;
const cy = ay + ny;
p.line(ax, ay, bx, by);
p.line(ax, ay, cx, cy);
p.line(cx, cy, bx, by);
harom(
ax * ratio + cx * (1 - ratio),
ay * ratio + cy * (1 - ratio),
ax * (1 - ratio) + bx * ratio,
ay * (1 - ratio) + by * ratio,
level - 1,
ratio);
}
p.draw = () => {
p.background(240);
harom(
p.width - 142, p.height - 142, 142, p.height - 142, 6,
(p.sin(0.0005 * Date.now() % (2 * p.PI)) + 1) / 2);
}
}
}

Related

React native SVG building pie chart with Path

I have a code that builds a SVG figure for a pie chart, using this function:
export const generateArc = (percentage: number, radius: number) => {
const a = (percentage * 2 * Math.PI) / 100 // angle (in radian) depends on percentage
const r = radius // radius of the circle
const rx = r
const ry = r
const xAxisRotation = 0
let largeArcFlag = 1
const sweepFlag = 1
const x = r + r * Math.sin(a)
const y = r - r * Math.cos(a)
if (percentage <= 50) {
largeArcFlag = 0
} else {
largeArcFlag = 1
}
return `A${rx} ${ry} ${xAxisRotation} ${largeArcFlag} ${sweepFlag} ${x} ${y}`
}
Everything works fine, except when percentage is 100, the chart disappears, you can look here
I feel like that there's some miscalculation, but i don't have much experience in such things with SVGS, and i can't figure it out.
The workarounds I've found are:
iOS: check if percentage is 100, then use 99.9, but that doesn't work for android (i've tested on real device, there's a little gap that's not filled, but on some emulators 99.9999 gives the full circle), you can check it in a snack
For both platform just use a full circle SVG instead, if percentage is 100, but i don't like that workaround
Thanks to #Robert Longson I've modified the function that generates arc a bit, so now it generates 2 arcs if percentage is 100
const generatePath = (percentage: number, radius: number) => {
if (percentage === 100) {
const x = radius
const y = radius
// in path x has to be 0 = starting point
return `M ${0}, ${y}
a ${x},${y} 0 1,1 ${radius * 2},0
a ${x},${y} 0 1,1 -${radius * 2},0
`
}
const a = (percentage * 2 * Math.PI) / 100 // angle (in radian) depends on percentage
const r = radius // radius of the circle
const rx = r
const ry = r
const xAxisRotation = 0
let largeArcFlag = 1
const sweepFlag = 1
const x = r + r * Math.sin(a)
const y = r - r * Math.cos(a)
if (percentage <= 50) {
largeArcFlag = 0
} else {
largeArcFlag = 1
}
return `M${radius} ${radius} L${radius} 0 A${rx} ${ry} ${xAxisRotation} ${largeArcFlag} ${sweepFlag} ${x} ${y} Z`
}

Rounded corners for Arc Progress in react-native-svg

I've created an Arc Progress based on a tutorial (v. https://www.youtube.com/watch?v=UMvw20nRZls) and worked fine
But, since i have no experience using svg path, i'm struggling with my Arc trying to get it's corners rounded
Here is how the Arc's result so far
const { PI, cos, sin } = Math;
const { width } = Dimensions.get('window');
const size = width - 32;
const strokeWidth = 20;
const AnimatedPath = Animated.createAnimatedComponent(Path);
const r = (size - strokeWidth) / 2;
const cx = size / 2;
const cy = size / 2;
const A = PI + PI * 0.4;
const startAngle = PI + PI * 0.2;
const endAngle = 2 * PI - PI * 0.2;
// A rx ry x-axis-rotation large-arc-flag sweep-flag x y
const x1 = cx - r * cos(startAngle);
const y1 = -r * sin(startAngle) + cy;
const x2 = cx - r * cos(endAngle);
const y2 = -r * sin(endAngle) + cy;
const d = `M ${x1} ${y1} A ${r} ${r} 0 1 0 ${x2} ${y2}`;
<Path
stroke="#FFF"
fill="none"
strokeDasharray={`${circumference}, ${circumference}`}
{...{ d, strokeWidth }}
/>
And i expect to have the corners like this:
ps: i'm using an expo app, so , i needed to install react-native-svg with expo to work
You could set the strokeLinecap prop on the Path to round:
<Path
stroke="black"
fill="none"
strokeLinecap="round"
strokeDasharray={`${circumference}, ${circumference}`}
{...{d, strokeWidth}}
/>
The strokeLinecap prop specifies the shape to be used at the end of open subpaths when they are stroked. Can be either 'butt', 'square' or 'round'.
Source: https://github.com/react-native-community/react-native-svg#common-props.

How calulate the area of a polygon in react-native-maps?

I am passing the array of co-ordinates to the polygon and want to find the area of the polygon through that co-ordinates. I have checked the documentation of the react-native-maps but there is no function provided.
Is there is any way to calculate the area.
Thanks in advance.
Library will not give you this functionality.
Try this
function calcArea(locations) {
if (!locations.length) {
return 0;
}
if (locations.length < 3) {
return 0;
}
let radius = 6371000;
const diameter = radius * 2;
const circumference = diameter * Math.PI;
const listY = [];
const listX = [];
const listArea = [];
// calculate segment x and y in degrees for each point
const latitudeRef = locations[0].latitude;
const longitudeRef = locations[0].longitude;
for (let i = 1; i < locations.length; i++) {
let latitude = locations[i].latitude;
let longitude = locations[i].longitude;
listY.push(this.calculateYSegment(latitudeRef, latitude, circumference));
listX.push(this.calculateXSegment(longitudeRef, longitude, latitude, circumference));
}
// calculate areas for each triangle segment
for (let i = 1; i < listX.length; i++) {
let x1 = listX[i - 1];
let y1 = listY[i - 1];
let x2 = listX[i];
let y2 = listY[i];
listArea.push(this.calculateAreaInSquareMeters(x1, x2, y1, y2));
}
// sum areas of all triangle segments
let areasSum = 0;
listArea.forEach(area => areasSum = areasSum + area)
// get abolute value of area, it can't be negative
let areaCalc = Math.abs(areasSum);// Math.sqrt(areasSum * areasSum);
return areaCalc;
}
function calculateAreaInSquareMeters(x1, x2, y1, y2) {
return (y1 * x2 - x1 * y2) / 2;
}
function calculateYSegment(latitudeRef, latitude, circumference) {
return (latitude - latitudeRef) * circumference / 360.0;
}
function calculateXSegment(longitudeRef, longitude, latitude, circumference) {
return (longitude - longitudeRef) * circumference * Math.cos((latitude * (Math.PI / 180))) / 360.0;
}
Reference

Calculate vertical bearing between two GPS coordinates with altitudes

I am planning to build an antenna tracker. I need to get bearing and tilt from GPS point A with altitude and GPS point B with altitude.
This is the example points:
latA = 39.099912
lonA = -94.581213
altA = 273.543
latB = 38.627089
lonB = -90.200203
altB = 1380.245
I've already got the formula for horizontal bearing and it gives me 97.89138167122422
This is the code:
function toRadian(num) {
return num * (Math.PI / 180);
}
function toDegree(num) {
return num * (180 / Math.PI);
}
function getHorizontalBearing(fromLat, fromLon, toLat, toLon) {
fromLat = toRadian(fromLat);
fromLon = toRadian(fromLon);
toLat = toRadian(toLat);
toLon = toRadian(toLon);
let dLon = toLon - fromLon;
let x = Math.tan(toLat / 2 + Math.PI / 4);
let y = Math.tan(fromLat / 2 + Math.PI / 4);
let dPhi = Math.log(x / y);
if (Math.abs(dLon) > Math.PI) {
if (dLon > 0.0) {
dLon = -(2 * Math.PI - dLon);
} else {
dLon = (2 * Math.PI + dLon);
}
}
return (toDegree(Math.atan2(dLon, dPhi)) + 360) % 360;
}
let n = getHorizontalBearing(39.099912, -94.581213, 38.627089, -90.200203);
console.info(n);
But I don't know how to find the tilt angle. Anyone could help me?
I think I got the answer after searching around.
This is the complete code, if you think this is wrong, feel free to correct me.
function toRadian(num) {
return num * (Math.PI / 180);
}
function toDegree(num) {
return num * (180 / Math.PI);
}
// North is 0 degree, South is 180 degree
function getHorizontalBearing(fromLat, fromLon, toLat, toLon, currentBearing) {
fromLat = toRadian(fromLat);
fromLon = toRadian(fromLon);
toLat = toRadian(toLat);
toLon = toRadian(toLon);
let dLon = toLon - fromLon;
let x = Math.tan(toLat / 2 + Math.PI / 4);
let y = Math.tan(fromLat / 2 + Math.PI / 4);
let dPhi = Math.log(x / y);
if (Math.abs(dLon) > Math.PI) {
if (dLon > 0.0) {
dLon = -(2 * Math.PI - dLon);
} else {
dLon = (2 * Math.PI + dLon);
}
}
let targetBearing = (toDegree(Math.atan2(dLon, dPhi)) + 360) % 360;
return targetBearing - currentBearing;
}
// Horizon is 0 degree, Up is 90 degree
function getVerticalBearing(fromLat, fromLon, fromAlt, toLat, toLon, toAlt, currentElevation) {
fromLat = toRadian(fromLat);
fromLon = toRadian(fromLon);
toLat = toRadian(toLat);
toLon = toRadian(toLon);
let fromECEF = getECEF(fromLat, fromLon, fromAlt);
let toECEF = getECEF(toLat, toLon, toAlt);
let deltaECEF = getDeltaECEF(fromECEF, toECEF);
let d = (fromECEF[0] * deltaECEF[0] + fromECEF[1] * deltaECEF[1] + fromECEF[2] * deltaECEF[2]);
let a = ((fromECEF[0] * fromECEF[0]) + (fromECEF[1] * fromECEF[1]) + (fromECEF[2] * fromECEF[2]));
let b = ((deltaECEF[0] * deltaECEF[0]) + (deltaECEF[2] * deltaECEF[2]) + (deltaECEF[2] * deltaECEF[2]));
let elevation = toDegree(Math.acos(d / Math.sqrt(a * b)));
elevation = 90 - elevation;
return elevation - currentElevation;
}
function getDeltaECEF(from, to) {
let X = to[0] - from[0];
let Y = to[1] - from[1];
let Z = to[2] - from[2];
return [X, Y, Z];
}
function getECEF(lat, lon, alt) {
let radius = 6378137;
let flatteningDenom = 298.257223563;
let flattening = 0.003352811;
let polarRadius = 6356752.312106893;
let asqr = radius * radius;
let bsqr = polarRadius * polarRadius;
let e = Math.sqrt((asqr-bsqr)/asqr);
// let eprime = Math.sqrt((asqr-bsqr)/bsqr);
let N = getN(radius, e, lat);
let ratio = (bsqr / asqr);
let X = (N + alt) * Math.cos(lat) * Math.cos(lon);
let Y = (N + alt) * Math.cos(lat) * Math.sin(lon);
let Z = (ratio * N + alt) * Math.sin(lat);
return [X, Y, Z];
}
function getN(a, e, latitude) {
let sinlatitude = Math.sin(latitude);
let denom = Math.sqrt(1 - e * e * sinlatitude * sinlatitude);
return a / denom;
}
let n = getHorizontalBearing(39.099912, -94.581213, 39.099912, -94.588032, 0.00);
console.info("Horizontal bearing:\t", n);
let m = getVerticalBearing(39.099912, -94.581213, 273.543, 39.099912, -94.588032, 873.543, 0.0);
console.info("Vertical bearing:\t", m);
Don Cross's javascript code produces good results. It takes into consideration the curvature of the earth plus the fact that the earth is oblate.
Example:
var elDegrees = calculateElevationAngleCosineKitty(
{latitude: 35.346257, longitude: -97.863801, altitudeMetres: 10},
{latitude: 34.450545, longitude: -96.500167, altitudeMetres: 9873}
);
console.log("El: " + elDegrees);
/***********************************
Code by Don Cross at cosinekitty.com
http://cosinekitty.com/compass.html
************************************/
function calculateElevationAngleCosineKitty(source, target)
{
var oblate = true;
var a = {'lat':source.latitude, 'lon':source.longitude, 'elv':source.altitudeMetres};
var b = {'lat':target.latitude, 'lon':target.longitude, 'elv':target.altitudeMetres};
var ap = LocationToPoint(a, oblate);
var bp = LocationToPoint(b, oblate);
var bma = NormalizeVectorDiff(bp, ap);
var elevation = 90.0 - (180.0 / Math.PI)*Math.acos(bma.x*ap.nx + bma.y*ap.ny + bma.z*ap.nz);
return elevation;
}
function NormalizeVectorDiff(b, a)
{
// Calculate norm(b-a), where norm divides a vector by its length to produce a unit vector.
var dx = b.x - a.x;
var dy = b.y - a.y;
var dz = b.z - a.z;
var dist2 = dx*dx + dy*dy + dz*dz;
if (dist2 == 0) {
return null;
}
var dist = Math.sqrt(dist2);
return { 'x':(dx/dist), 'y':(dy/dist), 'z':(dz/dist), 'radius':1.0 };
}
function EarthRadiusInMeters (latitudeRadians) // latitude is geodetic, i.e. that reported by GPS
{
// http://en.wikipedia.org/wiki/Earth_radius
var a = 6378137.0; // equatorial radius in meters
var b = 6356752.3; // polar radius in meters
var cos = Math.cos (latitudeRadians);
var sin = Math.sin (latitudeRadians);
var t1 = a * a * cos;
var t2 = b * b * sin;
var t3 = a * cos;
var t4 = b * sin;
return Math.sqrt ((t1*t1 + t2*t2) / (t3*t3 + t4*t4));
}
function GeocentricLatitude(lat)
{
// Convert geodetic latitude 'lat' to a geocentric latitude 'clat'.
// Geodetic latitude is the latitude as given by GPS.
// Geocentric latitude is the angle measured from center of Earth between a point and the equator.
// https://en.wikipedia.org/wiki/Latitude#Geocentric_latitude
var e2 = 0.00669437999014;
var clat = Math.atan((1.0 - e2) * Math.tan(lat));
return clat;
}
function LocationToPoint(c, oblate)
{
// Convert (lat, lon, elv) to (x, y, z).
var lat = c.lat * Math.PI / 180.0;
var lon = c.lon * Math.PI / 180.0;
var radius = oblate ? EarthRadiusInMeters(lat) : 6371009;
var clat = oblate ? GeocentricLatitude(lat) : lat;
var cosLon = Math.cos(lon);
var sinLon = Math.sin(lon);
var cosLat = Math.cos(clat);
var sinLat = Math.sin(clat);
var x = radius * cosLon * cosLat;
var y = radius * sinLon * cosLat;
var z = radius * sinLat;
// We used geocentric latitude to calculate (x,y,z) on the Earth's ellipsoid.
// Now we use geodetic latitude to calculate normal vector from the surface, to correct for elevation.
var cosGlat = Math.cos(lat);
var sinGlat = Math.sin(lat);
var nx = cosGlat * cosLon;
var ny = cosGlat * sinLon;
var nz = sinGlat;
x += c.elv * nx;
y += c.elv * ny;
z += c.elv * nz;
return {'x':x, 'y':y, 'z':z, 'radius':radius, 'nx':nx, 'ny':ny, 'nz':nz};
}
/***********************
END cosinekitty.com code
************************/

Path Tracing - Generate Camera Rays with a Left Handed coordinate system

Been having some issues implementing a camera for my renderer. As the question states,I would like to know the necessary steps to generate such a camera.With field of view and aspect ratio included.Its important that the Coordinate system be left handed such that -z pushes the camera away from the screen(as I understand it).I have tried looking online but most of the implementations are incomplete or have failed me.Any help is appreciated.Thank You.
I had trouble with this and took a long time to figure out. Here is the code for camera class.
#ifndef CAMERA_H_
#define CAMERA_H_
#include "common.h"
struct Camera {
Vec3fa position, direction;
float fovDist, aspectRatio;
double imgWidth, imgHeight;
Mat4 camMatrix;
Camera(Vec3fa pos, Vec3fa cRot, Vec3fa cDir, float cfov, int width, int height) {
position = pos;
aspectRatio = width / (float)height;
imgWidth = width;
imgHeight = height;
Vec3fa angle = Vec3fa(cRot.x, cRot.y, -cRot.z);
camMatrix.setRotationRadians(angle * M_PI / 180.0f);
direction = Vec3fa(0.0f, 0.0f, -1.0f);
camMatrix.rotateVect(direction);
fovDist = 2.0f * tan(M_PI * 0.5f * cfov / 180.0);
}
Vec3fa getRayDirection(float x, float y) {
Vec3fa delta = Vec3fa((x-0.5f) * fovDist * aspectRatio, (y-0.5f) * fovDist, 0.0f);
camMatrix.rotateVect(delta);
return (direction + delta);
}
};
#endif
Incase if you need the rotateVect() code in the Mat4 class
void Mat4::rotateVect(Vector3& vect) const
{
Vector3 tmp = vect;
vect.x = tmp.x * (*this)[0] + tmp.y * (*this)[4] + tmp.z * (*this)[8];
vect.y = tmp.x * (*this)[1] + tmp.y * (*this)[5] + tmp.z * (*this)[9];
vect.z = tmp.x * (*this)[2] + tmp.y * (*this)[6] + tmp.z * (*this)[10];
}
Here is our setRotationRadians code
void Mat4::setRotationRadians(Vector3 rotation)
{
const float cr = cos(rotation.x);
const float sr = sin(rotation.x);
const float cp = cos(rotation.y);
const float sp = sin(rotation.y);
const float cy = cos(rotation.z);
const float sy = sin(rotation.z);
(*this)[0] = (cp * cy);
(*this)[1] = (cp * sy);
(*this)[2] = (-sp);
const float srsp = sr * sp;
const float crsp = cr * sp;
(*this)[4] = (srsp * cy - cr * sy);
(*this)[5] = (srsp * sy + cr * cy);
(*this)[6] = (sr * cp);
(*this)[8] = (crsp * cy + sr * sy);
(*this)[9] = (crsp * sy - sr * cy);
(*this)[10] = (cr * cp);
}