Rotation of points in Android - android

I have point A, B and width of CD (A' = A). If user will move point B to B'how I can know coordinates of points C' D'. I would be very grateful if someone write method in java with 3 input parameters (A, B, and width of CD) which output coordinates of C' and D'. As reward I can pay 50$ via Paypal.

The background:
First, if I understand correctly, the task actually is "given the coordinates of A and B, find coordinates of C and D if we know that AB and CD are perpendicular, and we know the length of CD"
To calculate the coordinates, we use 3 basic math equations:
Line from 2 points A, B: y = (x - B.x)* (A.y - B.y)/(A.x - B.x) + B.y
If we set m = (A.y - B.y)/(A.x - B.x)
The equation from 2 points A, B will be: y = m * (x - B.x) + B.y
Line which is perpendicular with the line above (CD): y = (-1/m) * x + y0
Since CD goes through A, the equation can be written as: y = (-1/m) * (x - A.x) + A.y
The length (d) between 2 points A, C: d * d = (C.x - A.x) * (C.x - A.x) + (C.y - A.y) * (C.y - A.y)
From the equation of CD, we know C.y = (-1/m)*(C.x - A.x) + A.y
Therefore:
d*d = (C.x - A.x)*(C.x - A.x) + (1/(m*m))*(C.x - A.x)* (C.x - A.x)
Easily find out that C.x - A.x = (+|-) (m*d)/Math.sqrt(m*m + 1)
In java, I guess you can write the function as
public Point[] findCD(Point A, Point B, int widthCD) {
if (A.x == B.x) {
return [new Point(A.x - widthCD/2, A.y), new Point(A.x + widthCD/2, A.y)]
}
if (A.y == B.y) {
return [new Point(A.x, A.y - widthCD/2), new Point(A.x, A.y + widthCD/2)]
}
var m = (A.y - B.y)/(A.x - B.x);
var xC = A.x - m*widthCD/(2 * Math.sqrt(m*m + 1));
var xD = A.x + m*widthCD/(2 * Math.sqrt(m*m + 1));
var yC = (A.x - xC) / m + A.y;
var yD = (A.x - xD) / m + A.y;
return [new Point(xC, yC), new Point(xD, yD)];
}
Note: I don't have java, please correct if I write the pointer or array wrong

Related

Find nearest KML point to a Geo-location

In my Android app I am showing a KML on Google Map. I am also showing device location on the Map.
Now I want to find the point/line on KML which is closest to the device location on the Map. How can achieve that?
Also, I want to know if any KML point/line is within 10 meters of device location.
Solved. I followed the following steps to solve the 2nd part:
Added function to detect if line-segment collides with circle:
ref: https://stackoverflow.com/a/21989358/1397821
Java converted function:
static boolean checkLineSegmentCircleIntersection(double x1, double y1, double x2 , double y2, double xc, double yc, double r) {
double xd = 0.0;
double yd = 0.0;
double t = 0.0;
double d = 0.0;
double dx_2_1 = 0.0;
double dy_2_1 = 0.0;
dx_2_1 = x2 - x1;
dy_2_1 = y2 - y1;
t = ((yc - y1) * dy_2_1 + (xc - x1) * dx_2_1) / (dy_2_1 * dy_2_1 + dx_2_1 * dx_2_1);
if( 0 <= t && t <=1) {
xd = x1 + t * dx_2_1;
yd = y1 + t * dy_2_1;
d = Math.sqrt((xd - xc) * (xd - xc) + (yd - yc) * (yd - yc));
return d <= r;
}
else {
d = Math.sqrt((xc - x1) * (xc - x1) + (yc - y1) * (yc - y1));
if (d <= r)
return true;
else {
d = Math.sqrt((xc - x2) * (xc - x2) + (yc - y2) * (yc - y2));
if (d <= r)
return true;
else
return false;
}
}
}
Parsed the KML coordinates and passed the coordinates of line segments to this function, like :
boolean lineInRadius = checkLineSegmentCircleIntersection(points.get(i - 1).latitude, points.get(i - 1).longitude,
points.get(i).latitude, points.get(i).longitude, latDecimal, lngDecimal, RADIUS);
Note: your radius can be aprx 0.000009 for 1 meter (https://stackoverflow.com/a/39540339/1397821). This is not exact radius, it'll be oval.
To solve the 1st part, you can edit the above function and find the minimum distance. Check the line d <= r where distance is compared with radius.

error: non-aggregate type 'Point' (aka 'Point_<int>') cannot be initialized with an initializer list

I'm using c++ in Android Studio. However, when I run the code below :
int GetAngleABC(Point a, Point b, Point c)
{
Point ab = { b.x - a.x, b.y - a.y };
Point cb = { b.x - c.x, b.y - c.y };
float dot = (ab.x * cb.x + ab.y * cb.y); // dot product
float cross = (ab.x * cb.y - ab.y * cb.x); // cross product
float alpha = atan2(cross, dot);
return (int)floor(alpha * 180.0 / CV_PI + 0.5);
}
The Studio output error message :
Error:(30, 11) error: non-aggregate type 'Point' (aka 'Point_') cannot be initialized with an initializer list
And the error spots is :
Point ab = { b.x - a.x, b.y - a.y };
Point cb = { b.x - c.x, b.y - c.y };

How do you convert quaternion/accelerometer data to opengl usable data

I have some data from a sensor device, i.e., accelerometer x,y,z and a quaternion. Using this information i would like to render a "line image" in an Android OpenGL View. Can someone help me about the part on how to convert acceleration values to something that can be used by OpenGL glTranslatef and glRotatef function's.
You shouldn't be using the deprecate gltranslate or glrotate. instead just manage the correct transformation matrices directly.
converting a quaternion to matrix can be done with the following: (sourced from my previous code)
float[] quatToMat(quaternion q, float* result)
{
//based on algorithm on wikipedia
// http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion
float w = q.scalar ();
float x = q.x();
float y = q.y();
float z = q.z();
float n = x*x + y*y + z*z + w*w;
float s = n == 0? 0 : 2 / n;
float wx = s * w * x, wy = s * w * y, wz = s * w * z;
float xx = s * x * x, xy = s * x * y, xz = s * x * z;
float yy = s * y * y, yz = s * y * z, zz = s * z * z;
return new float[]{ 1 - (yy + zz), xy + wz , xz - wy ,0,
xy - wz , 1 - (xx + zz), yz + wx ,0,
xz + wy , yz - wx , 1 - (xx + yy),0,
0 , 0 , 0 ,1 };
}
If you still want to use the fixed function pipeline then push that into glMultMatrix.

Algorithm to draw arrowhead at the end of arbitrary line in an Android custom View

I've been trying to come up with an algorithm to draw an arrow in a custom View, using Path, but I haven't figured out how to get the coordinates of the arrowhead tips. The line startpoint and endpoint coordinates are arbitrary, the angle of the arrowhead relative to the line and the length of the arrowhead are fixed.
I think I have to use trigonometry somehow, but I'm not sure how.
My friend came up with a math equation, which I have translated into java code here:
public static void calculateArrowHead(Point start, Point end, double angleInDeg, double tipLength){
double x1 = end.getX();
double x2 = start.getX();
double y1 = end.getY();
double y2 = start.getY();
double alpha = Math.toRadians(angleInDeg);
double l1 = Math.sqrt(Math.pow(x2-x1, 2) + Math.pow(y2-y1, 2)); // length of the arrow line
double l2 = tipLength;
double a = Math.pow(y2-y1, 2) + Math.pow(x2-x1, 2);
double b = -2 * l1 * l2 * Math.cos(alpha) * (y2 - y1);
double c = Math.pow(l1, 2) * Math.pow(l2, 2) * Math.pow(Math.cos(alpha), 2) - Math.pow(l2, 2) * Math.pow(x2-x1, 2);
double s2a = (-b + Math.sqrt(Math.pow(b, 2) - 4 * a * c)) / (2 * a);
double s2b = (-b - Math.sqrt(Math.pow(b, 2) - 4 * a * c)) / (2 * a);
double s1a = (l1 * l2 * Math.cos(alpha) - s2a * (y2 - y1)) / (x2-x1);
double s1b = (l1 * l2 * Math.cos(alpha) - s2b * (y2 - y1)) / (x2-x1);
double x3a = s1a + x1;
double y3a = s2a + y1;
double x3b = s1b + x1;
double y3b = s2b + y1;
System.out.println("(A) x:" + (int)x3a + "; y:" + (int)y3a);
System.out.println("(B) x:" + (int)x3b + "; y:" + (int)y3b);
}
I haven't tested it thoroughly, but for the first few tests, it appears to be correct.

Android Canvas: Get Y position of drawn line in canvas [duplicate]

I'd like to calculate a point on a quadratic curve. To use it with the canvas element of HTML5.
When I use the quadraticCurveTo() function in JavaScript, I have a source point, a target point and a control point.
How can I calculate a point on the created quadratic curve at let's say t=0.5 with "only" knowing this three points?
Use the quadratic Bézier formula, found, for instance, on the Wikipedia page for Bézier Curves:
In pseudo-code, that's
t = 0.5; // given example value
x = (1 - t) * (1 - t) * p[0].x + 2 * (1 - t) * t * p[1].x + t * t * p[2].x;
y = (1 - t) * (1 - t) * p[0].y + 2 * (1 - t) * t * p[1].y + t * t * p[2].y;
p[0] is the start point, p[1] is the control point, and p[2] is the end point. t is the parameter, which goes from 0 to 1.
In case somebody needs the cubic form:
//B(t) = (1-t)**3 p0 + 3(1 - t)**2 t P1 + 3(1-t)t**2 P2 + t**3 P3
x = (1-t)*(1-t)*(1-t)*p0x + 3*(1-t)*(1-t)*t*p1x + 3*(1-t)*t*t*p2x + t*t*t*p3x;
y = (1-t)*(1-t)*(1-t)*p0y + 3*(1-t)*(1-t)*t*p1y + 3*(1-t)*t*t*p2y + t*t*t*p3y;
I created this demo :
// x = a * (1-t)³ + b * 3 * (1-t)²t + c * 3 * (1-t)t² + d * t³
//------------------------------------------------------------
// x = a - 3at + 3at² - at³
// + 3bt - 6bt² + 3bt³
// + 3ct² - 3ct³
// + dt³
//--------------------------------
// x = - at³ + 3bt³ - 3ct³ + dt³
// + 3at² - 6bt² + 3ct²
// - 3at + 3bt
// + a
//--------------------------------
// 0 = t³ (-a+3b-3c+d) + => A
// t² (3a-6b+3c) + => B
// t (-3a+3b) + => c
// a - x => D
//--------------------------------
var A = d - 3*c + 3*b - a,
B = 3*c - 6*b + 3*a,
C = 3*b - 3*a,
D = a-x;
// So we need to solve At³ + Bt² + Ct + D = 0
Full example here
may help someone.
I edited talkhabis answer (cubic curve) so the curve is displayed with the right coordinates. (Couldn't comment)
The Y-coordinates needed to be changed (-p[].y+150). (A new variable for that might be a nicer and more efficient solution, but you get the idea)
// Apply points to SVG and create the curve and controllers :
var path = document.getElementById('path'),
ctrl1 = document.getElementById('ctrl1'),
ctrl2 = document.getElementById('ctrl2'),
D = 'M ' + p0.x + ' ' + (-p0.y+150) +
'C ' + c0.x + ' ' + (-c0.y+150) +', ' + c1.x + ' ' + (-c1.y+150) + ', ' + p1.x + ' ' + (-p1.y+150);
path.setAttribute('d',D);
ctrl1.setAttribute('d','M'+p0.x+','+(-p0.y+150)+'L'+c0.x+','+(-c0.y+150));
ctrl2.setAttribute('d','M'+p1.x+','+(-p1.y+150)+'L'+c1.x+','+(-c1.y+150));
// Lets test the "Bezier Function"
var t = 0, point = document.getElementById('point');
setInterval(function(){
var p = Bezier(p0,c0,c1,p1,t);
point.setAttribute('cx',p.x);
point.setAttribute('cy',-p.y+150);
t += 0.01;
if(t>=1) t=0;
},50);
// OK ... Now tring to get "y" on cruve based on mouse "x" :
var svg = document.getElementById('svg'),
point2 = document.getElementById('point2');
svg.onmousemove = function(e){
var x = (e.pageX - 50)/2,
y = (e.pageY - 50)/2;
// "-50" because of "50px margin" on the left side
// and "/2" because the svg width is 300 units and 600 px => 300 = 600/2
// Get the x,y by mouse x
var p = YBX(p0,c0,c1,p1,x);
point2.setAttribute('cx',p.x);
point2.setAttribute('cy',-p.y+150);
}
http://jsfiddle.net/u214gco8/1/
I also created some C-Code to test the results for the cubic curve. Just enter the X and Y coordinates in the main function.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void bezierCurve(int x[] , int y[])
{
double xu = 0.0 , yu = 0.0 , u = 0.0 ;
int i = 0 ;
for(u = 0.0 ; u <= 1.0 ; u += 0.05)
{
xu = pow(1-u,3)*x[0]+3*u*pow(1-u,2)*x[1]+3*pow(u,2)*(1-u)*x[2]
+pow(u,3)*x[3];
yu = pow(1-u,3)*y[0]+3*u*pow(1-u,2)*y[1]+3*pow(u,2)*(1-u)*y[2]
+pow(u,3)*y[3];
printf("X: %i Y: %i \n" , (int)xu , (int)yu) ;
}
}
int main(void) {
int x[] = {0,75,50,300};
int y[] = {0,2,140,100};
bezierCurve(x,y);
return 0;
}
https://ideone.com/glLXcB
Just a note: If you are using the usual formulas presented here then don't expect t = 0.5 to return the point at half of the curve's length.. In most cases it won't.
More on this here under "§23 — Tracing a curve at fixed distance intervals" and here.

Categories

Resources