I have a circle and a polyline and I want to know the coordination of the intersection point
user3591040 its quite tricky....
I hope that you have data related to circle and line.
equations and all polylines
You want to find this point
**
Consider this image
We will try to detect any collision
**
Collision Detection Algorithm:try to implement this algorithm
Taking
E is the starting point of the ray,
L is the end point of the ray,
C is the center of sphere you're testing against
r is the radius of that sphere
Compute:
d = L - E ( Direction vector of ray, from start to end )
f = E - C ( Vector from center sphere to ray start )
Then the intersection is found by..
Plugging:
P = E + t * d
This is a parametric equation:
Px = Ex + tdx
Py = Ey + tdy
into
(x - h)2 + (y - k)2 = r2
(h,k) = center of circle.
Note: We've simplified the problem to 2D here, the solution we get applies also in 3D
to get:
Expand
x2 - 2xh + h2 + y2 - 2yk + k2 - r2 = 0
Plug
x = ex + tdx
y = ey + tdy
( ex + tdx )2 - 2( ex + tdx )h + h2 + ( ey + tdy )2 - 2( ey + tdy )k + k2 - r2 = 0
Explode
ex2 + 2extdx + t2dx2 - 2exh - 2tdxh + h2 + ey2 + 2eytdy + t2dy2 - 2eyk - 2tdyk + k2 - r2 = 0
Group
t2( dx2 + dy2 ) + 2t( exdx + eydy - dxh - dyk ) + ex2 + ey2 - 2exh - 2eyk + h2 + k2 - r2 = 0
Finally,
t2( _d * _d ) + 2t( _e * _d - _d * _c ) + _e * _e - 2( _e*_c ) + _c * _c - r2 = 0
*Where _d is the vector d and * is the dot product.*
And then,
t2( _d * _d ) + 2t( _d * ( _e - _c ) ) + ( _e - _c ) * ( _e - _c ) - r2 = 0
Letting _f = _e - _c
t2( _d * _d ) + 2t( _d * _f ) + _f * _f - r2 = 0
So we get:
t2 * (d DOT d) + 2t*( f DOT d ) + ( f DOT f - r2 ) = 0
So solving the quadratic equation:
float a = d.Dot( d ) ;
float b = 2*f.Dot( d ) ;
float c = f.Dot( f ) - r*r ;
float discriminant = b*b-4*a*c;
if( discriminant < 0 )
{
// no intersection
}
else
{
// ray didn't totally miss sphere,
// so there is a solution to
// the equation.
discriminant = sqrt( discriminant );
// either solution may be on or off the ray so need to test both
// t1 is always the smaller value, because BOTH discriminant and
// a are nonnegative.
float t1 = (-b - discriminant)/(2*a);
float t2 = (-b + discriminant)/(2*a);
// 3x HIT cases:
// -o-> --|--> | | --|->
// Impale(t1 hit,t2 hit), Poke(t1 hit,t2>1), ExitWound(t1<0, t2 hit),
// 3x MISS cases:
// -> o o -> | -> |
// FallShort (t1>1,t2>1), Past (t1<0,t2<0), CompletelyInside(t1<0, t2>1)
if( t1 >= 0 && t1 <= 1 )
{
// t1 is the intersection, and it's closer than t2
// (since t1 uses -b - discriminant)
// Impale, Poke
return true ;
}
Related
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
I have a problem of finding the angle of three points with mouse pointer. The rotation doesn't following the mouse as the mouse move around the rotating object.
This is my formula :
double degree = Math.toDegrees( Math.atan2(
(now.y - point.y) - (previous.y - point.y),
(now.x - point.x) - (previous.x - point.x)));
Log.w("RESULT", "DEGREE = " + degree);
if ( degree < 0 )
degree = 360 - (-degree);
This last 2 line was added later.
This is the full code of tracking the mouse rotation.
Camera camera = Camera.getInstance();
if (event.getActionMasked() == MotionEvent.ACTION_DOWN &&
event.getPointerCount() == 1) {
previous = new Point(event.getX(), event.getY());
previous = camera.getMapPoint(previous);
}
else if (event.getActionMasked() == MotionEvent.ACTION_MOVE &&
event.getPointerCount() == 1)
{
Point now = new Point(event.getX(), event.getY());
now = camera.getMapPoint(now);
ArrayList<GameObject> list = mObject.getSubObjects();
GameObject part = list.get(0);
Point point = part.getPolygon().getCenter();
Log.w("RESULT", "Previous = " + previous.x + " " + previous.y);
Log.w("RESULT", "Next = " + now.x + " " + now.y);
Log.w("RESULT", "Center = " + point.x + " " + now.y);
double degree = Math.toDegrees( Math.atan2(
(now.y - point.y) - (previous.y - point.y),
(now.x - point.x) - (previous.x - point.x)));
Log.w("RESULT", "DEGREE = " + degree);
if ( degree < 0 )
degree = 360 - (-degree);
android.graphics.Matrix matrix = new android.graphics.Matrix();
matrix.postRotate((float) degree, point.x, point.y);
// Polygon polygon;
// Polygon.Builder builder = new Polygon.Builder();
for (int i=0; i<part.getPolygon().getVertex().size(); i++)
{
float[] newPoint = new float[2];
Point p = part.getPolygon().getVertex().get(i);
newPoint[0] = p.x;
newPoint[1] = p.y;
matrix.mapPoints(newPoint);
part.getPolygon().getVertex().remove(i);
part.getPolygon().getVertex().add(i, new Point(newPoint[0], newPoint[1]));
}
previous = new Point(event.getX(), event.getY());
previous = camera.getMapPoint(previous);
}
else if (event.getActionMasked() == MotionEvent.ACTION_UP)
{
previous = null;
isSelected = false;
}
If you want to find angle between vectors (point-previous) and (point-now), use:
Math.atan2((now.x - point.x)*(previous.y - point.y) -
(now.y - point.y)*(previous.x - point.x),
(now.x - point.x)*(now.y - point.y) -
(previous.x - point.x)*(previous.y - point.y))
(This is atan2(vectorproduct, scalarproduct))
You may also use
angle = atan2(now.y-point.y, now.y-point.y)-
atan2(previous.y-point.y, previous.x-point.x);
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.
problem on calculation of x coordinate for plotting on iPhone screen.When points are within the range of 300 meter we are getting all the point of interest closer even-though In actual they are spread.I have even changed the width of the viewPort from 0.5 to 0.17(In degrees converted 28.647889757 to 10.0).Can anyone suggest such that every points of interest are properly placed with respect to the actual position.
The standard way(Mixare,ARToolkit) of calculating points on AR is
Calculate using ARKit
double pointAzimuth = coordinate.coordinateAzimuth;
//our x numbers are left based.
double leftAzimuth = self.currentCoordinate.coordinateAzimuth - VIEWPORT_WIDTH_RADIANS / 2.0;
if (leftAzimuth < 0.0) {
leftAzimuth = 2 * M_PI + leftAzimuth;
}
if (pointAzimuth < leftAzimuth) {
//it's past the 0 point.
point.x = ((2 * M_PI - leftAzimuth + pointAzimuth) / VIEWPORT_WIDTH_RADIANS) * 480.0;
} else {
point.x = ((pointAzimuth - leftAzimuth) / VIEWPORT_WIDTH_RADIANS) * 480.0;
}
IN Mixare:
CGPoint point;
CGRect viewBounds = self.overlayView.bounds;
//NSLog(#"pointForCoordinate: viewBounds.size.width = %.3f, height = %.3f", viewBounds.size.width, viewBounds.size.height );
double currentAzimuth = self.currentCoordinate.coordinateAzimuth;
double pointAzimuth = coordinate.coordinateAzimuth;
//NSLog(#"pointForCoordinate: location = %#, pointAzimuth = %.3f, pointInclination = %.3f, currentAzimuth = %.3f", coordinate.coordinateTitle, point.x, point.y, radiansToDegrees(pointAzimuth), radiansToDegrees(currentAzimuth), radiansToDegrees(pointInclination) );
double deltaAzimuth = [self deltaAzimuthForCoordinate:coordinate];
BOOL isBetweenNorth = [self isNorthForCoordinate:coordinate];
//NSLog(#"pointForCoordinate: (1) currentAzimuth = %.3f, pointAzimuth = %.3f, isNorth = %d", radiansToDegrees(currentAzimuth), radiansToDegrees(pointAzimuth), isBetweenNorth );
// NSLog(#"pointForCoordinate: deltaAzimuth = %.3f", radiansToDegrees(deltaAzimuth));
//NSLog(#"pointForCoordinate: (2) currentAzimuth = %.3f, pointAzimuth = %.3f, isNorth = %d", radiansToDegrees(currentAzimuth), radiansToDegrees(pointAzimuth), isBetweenNorth );
if ((pointAzimuth > currentAzimuth && !isBetweenNorth) ||
(currentAzimuth > degreesToRadians(360-self.viewRange) &&
pointAzimuth < degreesToRadians(self.viewRange))) {
// Right side of Azimuth
point.x = (viewBounds.size.width / 2) + ((deltaAzimuth / degreesToRadians(1)) * 12);
} else {
// Left side of Azimuth
point.x = (viewBounds.size.width / 2) - ((deltaAzimuth / degreesToRadians(1)) * 12);
}
I have created a method which performs a sobel edge detection.
I use the Camera yuv byte array to perform the detection on.
Now my problem is that I only get 5fps or something, which is really low.
I know it can be done faster because there are other apps on the market who are able to do it at good fps on good quality.
I pass images in a 800x400 resolution.
Can anyone check if my algorithm can be made shorter or more performant?
I already put the algorithm in native code but there seems to be no difference in fps.
public void process() {
progress=0;
index = 0;
// calculate size
// pixel index
size = width*(height-2) - 2;
// pixel loop
while (size>0)
{
// get Y matrix values from YUV
ay = input[index];
by = input[index+1];
cy = input[index+2];
gy = input[index+doubleWidth];
hy = input[index+doubleWidth+1];
iy = input[index+doubleWidth+2];
// get X matrix values from YUV
ax = input[index];
cx = input[index+2];
dx = input[index+width];
fx = input[index+width+2];
gx = input[index+doubleWidth];
ix = input[index+doubleWidth+2];
// 1 2 1
// 0 0 0
// -1 -2 -1
sumy = ay + (by*2) + cy - gy - (2*hy) - iy;
// -1 0 1
// -2 0 2
// -1 0 1
sumx = -ax + cx -(2*dx) + (2*fx) - gx + ix;
total[index] = (int) Math.sqrt(sumx*sumx+sumy*sumy);
// Math.atan2(sumx,sumy);
if(max < total[index])
max = total[index];
// sum = - a -(2*b) - c + g + (2*h) + i;
if (total[index] <0)
total[index] = 0;
// clamp to 255
if (total[index] >255)
total[index] = 0;
sum = (int) (total[index]);
output[index] = 0xff000000 | (sum << 16) | (sum << 8) | sum;
size--;
// next
index++;
}
//ratio = max/255;
}
Thx in Advance !
greetings
So I have two things:
I would consider loosing the Math.sqrt() expression: If you
are only interested in edge detection, I see no need for the this,
as the sqrt function is monotonic and it is really costly to
calculate.
I would consider another algorithm, especially I have had good results with a seperated convolution-filter: http://www.songho.ca/dsp/convolution/convolution.html#separable_convolution as this might bring down the number of arithmetic floating-point operations (which is probably your bottleneck).
I hope this helps, or at least sparks some inspiration. Good luck.
If you are using your algorithm in real-time, call it less often, maybe every ~20 frames instead of every frame.
Do more work per iteration, 800x400 in your algorithm is 318,398 iterations. Each iteration is pulling from the input array in a (to the processor) random way which causes issues with caching. Try pulling ay, ay2, by, by2, cy, cy2 and do twice the calculations per loop, you'll notice that the variables in the next iteration will relate to the previous. ay is now ay2 etc...
Here's a rewrite of your algo, doing twice the work per iteration. It saves a bit in redundant memory access, and ignores square root mentioned in another answer.
public void process() {
progress=0;
index = 0;
// calculate size
// pixel index
size = width*(height-2) - 2;
// do FIRST iteration outside of loop
// grab input avoid redundant memory accesses
ay = ax = input[index];
by = ay2 = ax2 = input[index+1];
cy = by2 = cx = input[index+2];
cy2 = cx2 = input[index+3];
gy = gx = input[index+doubleWidth];
hy = gy2 = gx2 = input[index+doubleWidth+1];
iy = hy2 = ix = input[index+doubleWidth+2];
iy2 = ix2 = input[index+doubleWidth+3];
dx = input[index+width];
dx2 = input[index+width+1];
fx = input[index+width+2];
fx2 = input[index+width+3];
//
sumy = ay + (by*2) + cy - gy - (2*hy) - iy;
sumy2 = ay2 + (by2*2) + cy2 - gy2 - (2*hy2) - iy2;
sumx = -ax + cx -(2*dx) + (2*fx) - gx + ix;
sumx2 = -ax2 + cx2 -(2*dx2) + (2*fx2) - gx2 + ix2;
// ignore the square root
total[index] = fastSqrt(sumx*sumx+sumy*sumy);
total[index+1] = fastSqrt(sumx2*sumx2+sumy2*sumy2);
max = Math.max(max, Math.max(total[index], total[index+1]));
// skip the test for negative value it can never happen
if(total[index] > 255) total[index] = 0;
if(total[index+1] > 255) total[index+1] = 0;
sum = (int) (total[index]);
sum2 = (int) (total[index+1]);
output[index] = 0xff000000 | (sum << 16) | (sum << 8) | sum;
output[index+1] = 0xff000000 | (sum2 << 16) | (sum2 << 8) | sum2;
size -= 2;
index += 2;
while (size>0)
{
// grab input avoid redundant memory accesses
ay = ax = cy;
by = ay2 = ax2 = cy2;
cy = by2 = cs = input[index+2];
cy2 = cx2 = input[index+3];
gy = gx = iy;
hy = gy2 = gx2 = iy2;
iy = hy2 = ix = input[index+doubleWidth+2];
iy2 = ix2 = input[index+doubleWidth+3];
dx = fx;
dx2 = fx2;
fx = input[index+width+2];
fx2 = input[index+width+3];
//
sumy = ay + (by*2) + cy - gy - (2*hy) - iy;
sumy2 = ay2 + (by2*2) + cy2 - gy2 - (2*hy2) - iy2;
sumx = -ax + cx -(2*dx) + (2*fx) - gx + ix;
sumx2 = -ax2 + cx2 -(2*dx2) + (2*fx2) - gx2 + ix2;
// ignore the square root
total[index] = fastSqrt(sumx*sumx+sumy*sumy);
total[index+1] = fastSqrt(sumx2*sumx2+sumy2*sumy2);
max = Math.max(max, Math.max(total[index], total[index+1]));
// skip the test for negative value it can never happen
if(total[index] >= 65536) total[index] = 0;
if(total[index+1] >= 65536) total[index+1] = 0;
sum = (int) (total[index]);
sum2 = (int) (total[index+1]);
output[index] = 0xff000000 | (sum << 16) | (sum << 8) | sum;
output[index+1] = 0xff000000 | (sum2 << 16) | (sum2 << 8) | sum2;
size -= 2;
index += 2;
}
}
// some faster integer only implementation of square root.
public static int fastSqrt(int x) {
}
Please note, the above code was not tested, it was written inside the browser window and may contain syntax errors.
EDIT You could try using a fast integer only square root function to avoid the Math.sqrt.
http://atoms.alife.co.uk/sqrt/index.html