1 module evael.utils.math.Functions; 2 3 import std.math; 4 5 import dnogc.DynamicArray; 6 7 import evael.utils.Math; 8 9 enum degToRad = (PI * 2) / 360; 10 enum pi = 180 / PI; 11 12 alias PolygonDefinition = DynamicArray!vec3; 13 14 /** 15 * Returns angle between two points. 16 */ 17 @nogc 18 float getAngle(in float deltaX, in float deltaY) nothrow 19 { 20 return atan2(deltaX, deltaY) * pi; 21 } 22 23 /** 24 * Returns angle between two points. 25 */ 26 @nogc 27 float getAngle()(in auto ref vec3 a, in auto ref vec3 b) nothrow 28 { 29 return getAngle(b.x - a.x, b.z - a.z); 30 } 31 32 /** 33 * Returns distance between two points. 34 */ 35 @nogc 36 int getDistance()(in auto ref vec2 a, in auto ref vec2 b) nothrow 37 { 38 return cast(int)ceil(sqrt(cast(float)(pow(a.x - b.x, 2) + pow(a.y - b.y, 2)))); 39 } 40 41 /** 42 * Returns distance between two points. 43 */ 44 @nogc 45 int getDistance()(in auto ref vec3 a, in auto ref vec3 b) nothrow 46 { 47 return cast(int)ceil(sqrt(cast(float)(pow(a.x - b.x, 2) + pow(a.z - b.z, 2)))); 48 } 49 50 @nogc 51 bool isPointInTriangle()(in auto ref vec3 p, in auto ref vec3 p0, in auto ref vec3 p1, in auto ref vec3 p2) nothrow 52 { 53 auto s = p0.z * p2.x - p0.x * p2.z + (p2.z - p0.z) * p.x + (p0.x - p2.x) * p.z; 54 auto t = p0.x * p1.z - p0.z * p1.x + (p0.z - p1.z) * p.x + (p1.x - p0.x) * p.z; 55 56 if ((s < 0) != (t < 0)) 57 return false; 58 59 auto A = -p1.z * p2.x + p0.z * (p2.x - p1.x) + p0.x * (p1.z - p2.z) + p1.x * p2.z; 60 if (A < 0.0) 61 { 62 s = -s; 63 t = -t; 64 A = -A; 65 } 66 return s > 0 && t > 0 && (s + t) < A; 67 } 68 69 @nogc 70 bool isPointInTriangle2()(in auto ref vec3 p, in auto ref vec3 p0, in auto ref vec3 p1, in auto ref vec3 p2) nothrow 71 { 72 if ((p.x == p0.x && p.z == p0.z) || (p.x == p1.x && p.z == p1.z) || (p.x == p2.x && p.z == p2.z)) 73 return true; 74 75 return isPointInTriangle(p, p0, p1, p2); 76 } 77 78 /** 79 * Checks if a point is inside a polygon 80 * Note : im using z axis instead of y axis 81 */ 82 @nogc 83 bool isPointInPolygon()(in auto ref vec3 p, in auto ref PolygonDefinition polygon) nothrow 84 { 85 // http://stackoverflow.com/questions/217578/how-can-i-determine-whether-a-2d-point-is-within-a-polygon 86 // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html 87 bool inside = false; 88 for(int i = 0, j = polygon.length - 1 ; i < polygon.length; j = i++) 89 { 90 if ( ( polygon[ i ].z > p.z ) != ( polygon[ j ].z > p.z ) && 91 p.x < ( polygon[ j ].x - polygon[ i ].x ) * ( p.z - polygon[ i ].z ) / ( polygon[ j ].z - polygon[ i ].z ) + polygon[ i ].x ) 92 { 93 inside = !inside; 94 } 95 } 96 97 return inside; 98 } 99 100 101 /** 102 * Checks if two segments interesect 103 */ 104 bool intersect()(in auto ref vec3 p1, in auto ref vec3 p2, in auto ref vec3 p3, in auto ref vec3 p4, out vec3 intersection) nothrow @nogc 105 { 106 // Get the segments' parameters. 107 immutable float dx12 = p2.x - p1.x; 108 immutable float dy12 = p2.z - p1.z; 109 immutable float dx34 = p4.x - p3.x; 110 immutable float dy34 = p4.z - p3.z; 111 112 // Solve for t1 and t2 113 immutable float denominator = (dy12 * dx34 - dx12 * dy34); 114 immutable float t1 = ((p1.x - p3.x) * dy34 + (p3.z - p1.z) * dx34) / denominator; 115 immutable float t2 = ((p3.x - p1.x) * dy12 + (p1.z - p3.z) * dx12) / -denominator; 116 117 // Find the point of intersection. 118 intersection = vec3(p1.x + dx12 * t1, 0, p1.z + dy12 * t1); 119 120 // The segments intersect if t1 and t2 are between 0 and 1. 121 return ((t1 >= 0) && (t1 <= 1) && (t2 >= 0) && (t2 <= 1)); 122 } 123 124 /** 125 * Checks if a ray intersect with polygon 126 */ 127 bool intersectPolygon()(in auto ref vec3 p1, in auto ref vec3 p2, ref PolygonDefinition polygonVertices, out vec3 intersection) nothrow @nogc 128 { 129 for(int i = 0; i < polygonVertices.length; i++) 130 { 131 int j = ( i + 1 ) % polygonVertices.length; 132 133 if((polygonVertices[i] == p2 || polygonVertices[j] == p2) || (polygonVertices[i] == p1 || polygonVertices[j] == p1)) 134 continue; 135 136 if(intersect(p1, p2, polygonVertices[i], polygonVertices[j], intersection)) 137 { 138 return true; 139 } 140 } 141 142 return false; 143 }