Skip to content

Instantly share code, notes, and snippets.

@dam2k
Created May 17, 2020 22:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dam2k/960ecac776c506a9f3474d4e467969b5 to your computer and use it in GitHub Desktop.
Save dam2k/960ecac776c506a9f3474d4e467969b5 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <math.h>
// ported in C from http://totologic.blogspot.com/2014/01/accurate-point-in-triangle-test.html?m=1
// really really really thank you!
// compile with -lm (math library)
#define EPSILON 0.00001
const static float epsilon = EPSILON;
const static float epsilon2 = EPSILON*EPSILON;
float side(float x1, float y1, float x2, float y2, float x, float y) {
return (y2-y1)*(x-x1)+(-x2+x1)*(y-y1);
}
int naivePointInTriangle(float x1, float y1, float x2, float y2, float x3, float y3, float x, float y) {
if((side(x1, y1, x2, y2, x, y) >= 0) && (side(x2, y2, x3, y3, x, y) >= 0) && (side(x3, y3, x1, y1, x, y) >= 0)) return 1;
return 0;
}
int pointInTriangleBoundingBox(float x1, float y1, float x2, float y2, float x3, float y3, float x, float y) {
float xMin, xMax, yMin, yMax;
xMin = fminf(x1, fminf(x2, x3)) - epsilon;
xMax = fmaxf(x1, fmaxf(x2, x3)) + epsilon;
yMin = fminf(y1, fminf(y2, y3)) - epsilon;
yMax = fmaxf(y1, fmaxf(y2, y3)) + epsilon;
if(x < xMin || xMax < x || y < yMin || yMax < y ) return 0;
return 1;
}
float distanceSquarePointToSegment(float x1, float y1, float x2, float y2, float x, float y) {
float p1_p2_squareLength, dotProduct, p_p1_squareLength;
p1_p2_squareLength = (x2 - x1) * (x2 - x1) + (y2 - y1)*(y2 - y1);
dotProduct = ((x - x1)*(x2 - x1) + (y - y1)*(y2 - y1)) / p1_p2_squareLength;
if(dotProduct < 0) {
return (x - x1) * (x - x1) + (y - y1) * (y - y1);
}
if (dotProduct <= 1) {
p_p1_squareLength = (x1 - x) * (x1 - x) + (y1 - y) * (y1 - y);
return p_p1_squareLength - dotProduct * dotProduct * p1_p2_squareLength;
}
return (x - x2) * (x - x2) + (y - y2) * (y - y2);
}
int accuratePointInTriangle(float x1, float y1, float x2, float y2, float x3, float y3, float x, float y) {
if(!pointInTriangleBoundingBox(x1, y1, x2, y2, x3, y3, x, y)) return 0;
if(naivePointInTriangle(x1, y1, x2, y2, x3, y3, x, y)) return 1;
if(distanceSquarePointToSegment(x1, y1, x2, y2, x, y) <= epsilon2) return 1;
if(distanceSquarePointToSegment(x2, y2, x3, y3, x, y) <= epsilon2) return 1;
if(distanceSquarePointToSegment(x3, y3, x1, y1, x, y) <= epsilon2) return 1;
return 0;
}
int main() {
float x1, y1, x2, y2, x3, y3, x, y;
// testo un triangolo rettangolo
x1=100; y1=100; x2=100; y2=200; x3=200; y3=100;
x=150; y=150;
//x=150; y=150.00001;
printf("XY point is into the triangle with vertex x1.y1, x2.y2, x3.y3? Response: %s\n", accuratePointInTriangle(x1,y1,x2,y2,x3,y3,x,y) ? "yes" : "no");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment