How to find z by arbitrary x,y coordinates within triangle if you have triangle vertices - optimization

Given vertices V1 (x1,y1,z1), V2 (x2,y2,z2), V3 (x3,y3,z3) of a triangle T, I have to find z coordinate of a point by it's x,y coordinate if I know that (x,y) lies within projection of triangle Tp (x1,y1), (x2,y2), (x3,y3).
Actually, triangle plane in 3D is defined by equation: Ax+By+Cz+D=0, and I can find z = (D-Ax-By)/C
The problem is that A, B, C, D are too expensive to calculate in run-time:
A = y1(z2-z3) + y2(z3-z1) + y3(z1-z2)
B = z1(x2-x3) + z2(x3-x1) + z3(x1-x2)
C = x1(y2-y3) + x2(y3-y1) + x3(y1-y2)
D = -x1(y2*z3 – y3*z2) – x2(y3*z1 – y1*z3) – x3 (y1*z2 – y2*z1)
Is it possible to calculate A, B, C, D using, say, opengl shaders? Are there optimized algorithms to find plane coefficients?

The technique is called Barycentric coordinates but the wiki page is pretty hard to follow -
See http://www.alecjacobson.com/weblog/?p=1596
float calcY(vec3 p1, vec3 p2, vec3 p3, float x, float z) {
float det = (p2.z - p3.z) * (p1.x - p3.x) + (p3.x - p2.x) * (p1.z - p3.z);
float l1 = ((p2.z - p3.z) * (x - p3.x) + (p3.x - p2.x) * (z - p3.z)) / det;
float l2 = ((p3.z - p1.z) * (x - p3.x) + (p1.x - p3.x) * (z - p3.z)) / det;
float l3 = 1.0f - l1 - l2;
return l1 * p1.y + l2 * p2.y + l3 * p3.y;
}
Code from http://www.gamedev.net/topic/597393-getting-the-height-of-a-point-on-a-triangle/ - carefull about computer graphics vs maths use of Y Z
ps. I Don't know of any faster version using shaders. One quick dirty+solution is to render the triangle using colors based on the height of the vertices and pick the pixel color at your X,Y - in practice this never ends up being much faster on a desktop machine, don't know about opengl-es

Related

Sphere-plane collision resolve

I want to write a c++ program that will calculate collision between sphere and plane.
The rule is that the angle of the falling object equals to angle of reflection.
What do I have for sphere:
//sphere coordinates and radius
float x;
float y;
float z;
float r;
//sphere velocity vector projections
float vx;
float vy;
float vz;
Plane is described by plane equation coefficients:
float A;
float B;
float C;
float D;
With sphere-plane collision detection I have no problem. But how to find velocity after collision?
What did I find:
So, ultimately I need to calculate updated values for vx vy vz.
#Beta’s answer on c++:
float wl = sqrt(plane->A*plane->A+plane->B*plane->B+plane->C+plane->C); // “W” vector length
float nx = plane->A/wl; //Normal components
float ny = plane->B/wl;
float nz = plane->C/wl;
float scope = (sphere->vx*nx + sphere->vy*ny + sphere->vz*nz)*2; // 2(V . n)
nx = nx*scope; // 2(V . n)n
ny = ny*scope;
nz = nz*scope;
sphere->vx -= nx; // V' = V - 2(V . n)n
sphere->vy -= ny;
sphere->vz -= nz;
The equation defining the plane is
Ax + By + Cz + D = 0
So the vector normal to the plane is
W = (A, B, C)
Normalize it:
n = W/|W|
Now take the velocity vector:
V = (vx, vy, vz)
Its component normal to the plane is
Vn = (V . n) n
and the rest of it, the part parallel to the plane is
Vp = V - Vn
We want to reverse the normal component and leave the parallel component unchanged:
V' = -Vn + Vp
which works out to
V' = V - 2(V . n)n

counter-clockwise cgpath/uibezierpath

How can I tell if these points are connected counter-clockwise or clockwise?
I have this code in my GameScene.m:
CGFloat radius = (self.frame.size.width - 6) / 2;
CGFloat a = radius * sqrt((CGFloat)3.0) / 2;
CGFloat b = radius / 2;
UIBezierPath *pathFirstTrigon = [UIBezierPath bezierPath];
[pathFirstTrigon moveToPoint:CGPointMake(0, -radius)];
[pathFirstTrigon addLineToPoint:CGPointMake(a, b)];
[pathFirstTrigon addLineToPoint:CGPointMake(-a, b)];
[pathFirstTrigon closePath];
The orientation can be deduced from the signed area. You can calculate the signed area from the sum of cross products of consecutive points:
2 * area = (0, -radius) x (a, b) + (a, b) ⨯ (-a, b) + (-a, b) ⨯ (0, -radius)
With the definition of the 2D cross product:
(a, b) ⨯ (c, d) = a * d - b * c
This gets you:
area = a * radius + a * b
Use the sign of the area to determine if the path is clockwise or counter-clockwise (which one refers to what sign depends on your coordinate system).
What you have is something similar to :
Y
(-a,b) ^ (a,b)
+ | +
|
|
|
|
--------+---------> X
|
+ (0,r)
|
So it is counter-clockwise on standard coordinates system.

Minimum distance between a point and a line in latitude, longitude

I have a line with two points in latitude and longitude
A: 3.222895, 101.719751
B: 3.227511, 101.724318
and 1 point
C: 3.224972, 101.722932
How can I calculate minimum distance between point C and a line consists of point A and B?
It will be convenient if you can provide the calculation and objective-c code too. The distance is around 89 meters (using ruler in Google Earth).
Thanks to mimi and this great article http://www.movable-type.co.uk/scripts/latlong.html but they don't give the whole picture. Here is a detail one. All this points are collected using Google Earth using Placemark to mark the locations. Make sure lat/long are set to decimal degrees in Preferences.
lat A = 3.222895
lon A = 101.719751
lat B = 3.222895
lon B = 101.719751
lat C = 3.224972
lon C = 101.722932
Earth radius, R = 6371
1. First you have to find the bearing from A to C and A to B.
Bearing formula
bearingAC = atan2( sin(Δλ)*cos(φ₂), cos(φ₁)*sin(φ₂) − sin(φ₁)*cos(φ₂)*cos(Δλ) )
bearingAB = atan2( sin(Δλ)*cos(φ₂), cos(φ₁)*sin(φ₂) − sin(φ₁)*cos(φ₂)*cos(Δλ) )
φ is latitude, λ is longitude, R is earth radius
2. Find A to C distance using spherical law of cosines
distanceAC = acos( sin(φ₁)*sin(φ₂) + cos(φ₁)*cos(φ₂)*cos(Δλ) )*R
3. Find cross-track distance
distance = asin(sin(distanceAC/ R) * sin(bearingAC − bearing AB)) * R
Objective-C code
double lat1 = 3.227511;
double lon1 = 101.724318;
double lat2 = 3.222895;
double lon2 = 101.719751;
double lat3 = 3.224972;
double lon3 = 101.722932;
double y = sin(lon3 - lon1) * cos(lat3);
double x = cos(lat1) * sin(lat3) - sin(lat1) * cos(lat3) * cos(lat3 - lat1);
double bearing1 = radiansToDegrees(atan2(y, x));
bearing1 = 360 - ((bearing1 + 360) % 360);
double y2 = sin(lon2 - lon1) * cos(lat2);
double x2 = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lat2 - lat1);
double bearing2 = radiansToDegrees(atan2(y2, x2));
bearing2 = 360 - ((bearing2 + 360) % 360);
double lat1Rads = degreesToRadians(lat1);
double lat3Rads = degreesToRadians(lat3);
double dLon = degreesToRadians(lon3 - lon1);
double distanceAC = acos(sin(lat1Rads) * sin(lat3Rads)+cos(lat1Rads)*cos(lat3Rads)*cos(dLon)) * 6371;
double min_distance = fabs(asin(sin(distanceAC/6371)*sin(degreesToRadians(bearing1)-degreesToRadians(bearing2))) * 6371);
NSLog(#"bearing 1: %g", bearing1);
NSLog(#"bearing 2: %g", bearing2);
NSLog(#"distance AC: %g", distanceAC);
NSLog(#"min distance: %g", min_distance);
Actually there's a library for this. You can find it here https://github.com/100grams/CoreLocationUtils
Calculate bearing for each: C to A , and C to B:
var y = Math.sin(dLon) * Math.cos(lat2);
var x = Math.cos(lat1)*Math.sin(lat2) -
Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon);
var brng = Math.atan2(y, x).toDeg();
dLon= lon2-lon1;
Calculate cross-track distance:
var dXt = Math.asin(Math.sin(distance_CB/R)*Math.sin(bearing_CA-bearing_CB)) * R;
R is the radius of earth, dXt is the minimum distance you wanted to calculate.
Code to carry out this calculation is posted at here.
This implements an accurate solution in terms of ellipsoidal geodesics.
For the basic geodesic calculations, you can use
GeographicLib or the port of these algorithms to C which are included in version 4.9.0 of PROJ.4. This C interface is documented here.
Here's the result of compiling and running intercept.cpp:
$ echo 3.222895 101.719751 3.227511 101.724318 3.224972 101.722932 | ./intercept
Initial guess 3.225203 101.7220345
Increment 0.0003349040566247297 0.0003313413822354505
Increment -4.440892098500626e-16 0
Increment 0 0
...
Final result 3.225537904056624 101.7223658413822
Azimuth to A1 -135.1593040635131
Azimuth to A2 44.84069593652217
Azimuth to B1 134.8406959363608
Distance to line is 88.743m:
$ echo 3.224972 101.722932 3.225537904056624 101.7223658413822 | GeodSolve -i
-45.15927221 -45.15930407 88.743
See post here:
https://stackoverflow.com/a/33343505/4083623
For distance up to a few thousands meters I would simplify the issue from sphere to plane.
Then, the issue is pretty simply as a easy triangle calculation can be used:
We have points A and B and look for a distance X to line AB. Then:
Location a;
Location b;
Location x;
double ax = a.distanceTo(x);
double alfa = (Math.abs(a.bearingTo(b) - a.bearingTo(x))) / 180
* Math.PI;
double distance = Math.sin(alfa) * ax;
If you know how to calculate the distance of two points, get the distances between each two points, you get AB, AC, and BC. You want to know the closest distance between point C and line AB.
First get the value of P
P=(AB+BC+AC)/2
Using P, you need to get S
S=SQRT((P(P-AC)(P-AB)(P-AC))
SQRT means square root. Then you get what you want by
2*S/AB

How can I find all points between point1 and point 2 - Objective c? [duplicate]

I've got two points between which im drawing a line (x1,y1 and x2,y2) but i need to know the coordinates of x3,y3 which is gapSize away from point x2,y2. Any ideas on how to solve this problem (the program is written in objective-c if that is helpful at all)?
You can simply calculate the angle in radians as
double rads = atan2(y2 - y1, x2 - x1);
Then you get the coordinates as follows:
double x3 = x2 + gapSize * cos(rads);
double y3 = y2 + gapSize * sin(rads);
Is this what you meant?
Compute the distance between P1 and P2: d=sqrt( (y2-y1)^2 + (x2-x1)^2)
Then x2 = (d*x1 + gapSize*x3) / (d+gapSize)
So x3 = (x2 * (d+gapSize) - d*x1) / gapSize
Similarly, y3 = (y2 * (d+gapSize) - d*y1) / gapSize
Sorry for the math. I didn't try to code it but it sounds right. I hope this helps.
There are many ways to do this. Simplest (to me) is the following. I'll write it in terms of mathematics since I can't even spell C.
Thus, we wish to find the point C = {x3,y3}, given points A = {x1,y1} and B = {x2,y2}.
The distance between the points is
d = ||B-A|| = sqrt((x2-x1)^2 + (y2-y1)^2)
A unit vector that points along the line is given by
V = (B - A)/d = {(x2 - x1)/d, (y2-y1)/d}
A new point that lies a distance of gapSize away from B, in the direction of that unit vector is
C = B + V*gapSize = {x2 + gapSize*(x2 - x1)/d, y2 + gapSize*(y2 - y1)/d}

how to find a point in the path of a line

I've got two points between which im drawing a line (x1,y1 and x2,y2) but i need to know the coordinates of x3,y3 which is gapSize away from point x2,y2. Any ideas on how to solve this problem (the program is written in objective-c if that is helpful at all)?
You can simply calculate the angle in radians as
double rads = atan2(y2 - y1, x2 - x1);
Then you get the coordinates as follows:
double x3 = x2 + gapSize * cos(rads);
double y3 = y2 + gapSize * sin(rads);
Is this what you meant?
Compute the distance between P1 and P2: d=sqrt( (y2-y1)^2 + (x2-x1)^2)
Then x2 = (d*x1 + gapSize*x3) / (d+gapSize)
So x3 = (x2 * (d+gapSize) - d*x1) / gapSize
Similarly, y3 = (y2 * (d+gapSize) - d*y1) / gapSize
Sorry for the math. I didn't try to code it but it sounds right. I hope this helps.
There are many ways to do this. Simplest (to me) is the following. I'll write it in terms of mathematics since I can't even spell C.
Thus, we wish to find the point C = {x3,y3}, given points A = {x1,y1} and B = {x2,y2}.
The distance between the points is
d = ||B-A|| = sqrt((x2-x1)^2 + (y2-y1)^2)
A unit vector that points along the line is given by
V = (B - A)/d = {(x2 - x1)/d, (y2-y1)/d}
A new point that lies a distance of gapSize away from B, in the direction of that unit vector is
C = B + V*gapSize = {x2 + gapSize*(x2 - x1)/d, y2 + gapSize*(y2 - y1)/d}