package br.com.etyllica.util.math;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import br.com.etyllica.core.linear.Triangle;
import com.badlogic.gdx.math.Vector3;
public class MathHelper {
public static Vector3 calculateNormal(Triangle triangle) {
Vector3 a = new Vector3(triangle.getA());
Vector3 b = new Vector3(triangle.getB());
Vector3 c = new Vector3(triangle.getC());
Vector3 v = new Vector3(b).sub(a);
Vector3 u = new Vector3(c).sub(a);
Vector3 normal = new Vector3(v).crs(u);
normal.nor();
return normal;
}
public static boolean isClockwise(Triangle triangle) {
return isClockwise(triangle.getA(), triangle.getB(), triangle.getC());
}
public static boolean isClockwise(Vector3 a, Vector3 b, Vector3 c) {
PointLinePosition res = PointLineTest.pointLineTest(a, b, c);
return (res == PointLinePosition.ON_SEGMENT) ||
(res == PointLinePosition.LEFT) ||
(res == PointLinePosition.INFRONT_OF_A) ||
(res == PointLinePosition.BEHIND_B);
}
public static float triangleArea(Triangle triangle) {
Vector3 a = triangle.getA();
Vector3 b = triangle.getB();
Vector3 c = triangle.getC();
Vector3 ab = new Vector3(b.sub(a));
Vector3 ac = new Vector3(c.sub(a));
Vector3 result = ab.crs(ac);
return result.len()/2;
}
public static float trianglularPrismVolume(Triangle triangle, float height) {
float triangleArea = triangleArea(triangle);
return triangleArea * height;
}
/**
* Method to calculate the volume under the triangle
* @param triangle
* @return volume between the triangle and the plane z = 0
*/
public static double volumeUnderTriangle(Triangle triangle) {
return volumeUnderTriangle(triangle, 0);
}
public static double volumeUnderTriangle(Triangle triangle, float z) {
Vector3 a = triangle.getA();
Vector3 b = triangle.getB();
Vector3 c = triangle.getC();
//Projection points
Vector3 pa = new Vector3(a.x,a.y,z);
Vector3 pb = new Vector3(b.x,b.y,z);
Vector3 pc = new Vector3(c.x,c.y,z);
Triangle t1 = new Triangle(a, c, pa);
Triangle t2 = new Triangle(c, pc, pa);
Triangle t3 = new Triangle(c, b, pc);
Triangle t4 = new Triangle(b, pb, pc);
Triangle t5 = new Triangle(b, a, pb);
Triangle t6 = new Triangle(a, pa, pb);
Triangle tp = new Triangle(pa, pb, pb);
Set<Triangle> triangles = new HashSet<Triangle>();
triangles.add(triangle);
triangles.add(t1);
triangles.add(t2);
triangles.add(t3);
triangles.add(t4);
triangles.add(t5);
triangles.add(t6);
triangles.add(tp);
return volumeOfMesh(triangles);
}
/**
* Method to calculate volume of a 3d mesh
* Cha Zhang and Tsuhan Chen - EFFICIENT FEATURE EXTRACTION
* FOR 2D/3D OBJECTS IN MESH REPRESENTATION
* @param triangles
* @return the volume
*/
public static double volumeOfMesh(Set<Triangle> triangles) {
double sum = 0;
for(Triangle triangle: triangles) {
sum += signedVolumeOfTriangle(triangle);
}
return sum;
}
public static double signedVolumeOfTriangle(Triangle triangle) {
return signedVolumeOfTriangle(triangle.getA(), triangle.getB(), triangle.getC());
}
public static double signedVolumeOfTriangle(Vector3 p1, Vector3 p2, Vector3 p3) {
double v321 = p3.x*p2.y*p1.z;
double v231 = p2.x*p3.y*p1.z;
double v312 = p3.x*p1.y*p2.z;
double v132 = p1.x*p3.y*p2.z;
double v213 = p2.x*p1.y*p3.z;
double v123 = p1.x*p2.y*p3.z;
return (-v321 + v231 + v312 - v132 - v213 + v123)/6.0f;
}
public static List<Vector3> orderedInZ(Vector3 ... points) {
List<Vector3> ordered = Arrays.asList(points);
Collections.sort(ordered, LOWER_Z_COMPARATOR);
return ordered;
}
private static final Comparator<Vector3> LOWER_Z_COMPARATOR = new Comparator<Vector3>() {
@Override
public int compare(Vector3 a, Vector3 b) {
double diff = a.z - b.z;
if (diff > 0) {
return 1;
} else if (diff < 0) {
return -1;
} else {
return 0;
}
}
};
}