/// <summary> /// Ray-Triangle intersection algorithm, based on the algorithm published by Tomas Akenine-Möller, May 2000 /// </summary> /// <param name="orig">Ray origin point</param> /// <param name="dir">Ray direction vector</param> /// <param name="vert0">First triangle vertex</param> /// <param name="vert1">Second triangle vertex</param> /// <param name="vert2">Third triangle vertex</param> /// <param name="t">t-value along ray where an intersection point has been found (if any).</param> /// <param name="u">u-value on triangle where an intersection point has been found (if any).</param> /// <param name="v">v-value on triangle where an intersection point has been found (if any).</param> /// <returns>True if an intersection was found, false if not.</returns> protected bool RayXtri(Point orig, Vector dir, Point vert0, Point vert1, Point vert2, ref double t, ref double u, ref double v) { /* find vectors for two edges sharing vert0 */ Vector edge1 = vert1 - vert0; Vector edge2 = vert2 - vert0; /* begin calculating determinant - also used to calculate U parameter */ Vector pvec = Hare_math.Cross(dir, edge2); /* if determinant is near zero, ray lies in plane of triangle */ double det = Hare_math.Dot(edge1, pvec); /* calculate distance from vert0 to ray origin */ Vector tvec = orig - vert0; double invdet = 1.0 / det; Vector qvec = Hare_math.Cross(tvec, edge1); if (det > 0.000001) { u = Hare_math.Dot(tvec, pvec); if (u < 0.0 || u > det) { return(false); } /* calculate V parameter and test bounds */ v = Hare_math.Dot(dir, qvec); if (v < 0.0 || u + v > det) { return(false); } } else if (det < -0.000001) { /* calculate U parameter and test bounds */ u = Hare_math.Dot(tvec, pvec); if (u > 0.0 || u < det) { return(false); } /* calculate V parameter and test bounds */ v = Hare_math.Dot(dir, qvec); if (v > 0.0 || u + v < det) { return(false); } } else { return(false); /* ray is parallell to the plane of the triangle */ } t = Hare_math.Dot(edge2, qvec) * invdet; u *= invdet; v *= invdet; return(true); }
public Quadrilateral(ref List <Point> Vertices, int index, int id) : base(ref Vertices, index, id) { if (VertexCount != 4) { throw new ApplicationException("Faulty Quadrilateral"); } area_Fraction[0] = 0.5 * Hare_math.Cross((Points[1] - Points[0]), (Points[2] - Points[0])).Length(); area_Fraction[1] = 0.5 * Hare_math.Cross((Points[2] - Points[3]), (Points[1] - Points[3])).Length(); double Area = area_Fraction[0] + area_Fraction[1]; area_Fraction[0] /= Area; area_Fraction[1] /= Area; }
public EdgeSource(int[] attr_in, Hare.Geometry.Point PtZ0, Hare.Geometry.Point _PtZ, Vector[] _Tangents) { attr = attr_in; Tangent = _Tangents; Z_Norm = _PtZ - PtZ0; Z_Range = Z_Norm.Length(); Z_dot = Z_Range * Z_Range;//Hare_math.Dot(Z_Norm, Z_Norm); Z_Norm /= Z_Range; Z_Range_2 = Z_Range / 2; Z_mid = (PtZ0 + _PtZ) / 2; Vector Bisector = (Tangent[0] + Tangent[1]) / 2; Bisector.Normalize(); double BisectAngle = Math.Acos(Hare_math.Dot(Tangent[0], Bisector)); if (BisectAngle == 0) { BisectAngle = 1E-12; } v = new double[2] { Math.PI / (2 * BisectAngle), Math.PI / (Utilities.Numerics.PiX2 - 2 * BisectAngle) }; v_4pi = new double[2] { v[0] / (4 * Math.PI), v[1] / (4 * Math.PI) }; v_2pi = new double[2] { v[0] / (2 * Math.PI), v[1] / (2 * Math.PI) }; Normal[0] = Hare_math.Cross(_Tangents[0], Z_Norm); Normal[1] = Hare_math.Cross(_Tangents[1], Z_Norm * -1); if (Hare_math.Dot(Normal[0], Bisector) > 0) { Normal[0] *= -1; Normal[1] *= -1; } //////////////////////////// //VisCheck// Rhino.Geometry.Point3d pt = new Rhino.Geometry.Point3d(Z_mid.x, Z_mid.y, Z_mid.z); Rhino.RhinoDoc.ActiveDoc.Objects.AddLine(pt, pt + new Rhino.Geometry.Point3d(Normal[0].x, Normal[0].y, Normal[0].z)); Rhino.RhinoDoc.ActiveDoc.Objects.AddLine(pt, pt + new Rhino.Geometry.Point3d(Normal[1].x, Normal[1].y, Normal[1].z)); //Rhino.RhinoDoc.ActiveDoc.Objects.AddLine(pt, pt + new Rhino.Geometry.Point3d(Tangent[0].x, Tangent[0].y, Tangent[0].z)); //Rhino.RhinoDoc.ActiveDoc.Objects.AddLine(pt, pt + new Rhino.Geometry.Point3d(Tangent[1].x, Tangent[1].y, Tangent[1].z)); //////Rhino.RhinoDoc.ActiveDoc.Objects.AddPoint(new Rhino.Geometry.Point3d(Z_mid.x, Z_mid.y, Z_mid.z)); }
public Polygon(ref List <Point> Vertices, int index, int id) { top_index = index; for (int j = 2; j < Vertices.Count; j++) { Normal = Hare_math.Cross(Vertices[1] - Vertices[0], Vertices[j] - Vertices[0]); if (!Normal.IsZeroVector()) { break; } } Points = new Point[Vertices.Count]; for (int p = 0; p < Vertices.Count; p++) { Points[p] = Vertices[p]; } Normal.Normalize(); diffz = new Vector(Normal.x, Normal.y, Normal.z); diffx = new Vector(0, 0, 1); double proj = Math.Abs(Hare_math.Dot(diffz, diffx)); if (0.99 < proj && 1.01 > proj) { diffx = new Vector(1, 0, 0); } diffy = new Vector(diffz.x, diffz.y, diffz.z); diffy = Hare_math.Cross(diffy, diffx); diffx = Hare_math.Cross(diffy, diffz); diffx.Normalize(); diffy.Normalize(); diffz.Normalize(); d = Hare_math.Dot(Normal, Points[0]); VertexCount = Points.Length; Inv_Dot_Normal = 1 / (Hare_math.Dot(Normal, Normal)); if (VertexCount < 3) { IsDegenerate = true; } Poly_index = id; IsConvex = Convexity(); }
/// <summary> /// Determines whether or not all triangular subdivisions of a convex polygon can be considered coplanar. /// </summary> /// <param name="P"></param> /// <returns></returns> public static bool IsCoPlanar(Point[] P) { if (P.Length > 3) { Vector First_Tri_CP = Hare_math.Cross(P[1] - P[0], P[2] - P[0]); First_Tri_CP.Normalize(); for (int j = 2, k = 3; k < P.Length; j++, k++) { Vector V = Hare_math.Cross(P[j] - P[0], P[k] - P[0]); double x = Hare_math.Dot(First_Tri_CP, V); if (x < 1) { return(false); } } } return(true); }
public EdgeSource(int[] attr_in, Hare.Geometry.Point Z_mid_in, double Delta_Z, Vector[] _Tangents) { attr = attr_in; Tangent = _Tangents; Z_Norm = Hare.Geometry.Hare_math.Cross(_Tangents[0], _Tangents[1]); Z_Range = Delta_Z; Z_dot = Z_Range * Z_Range;//Hare_math.Dot(Z_Norm, Z_Norm); Z_Range_2 = Z_Range / 2; Z_Norm.Normalize(); Z_mid = Z_mid_in; Vector Bisector = (Tangent[0] + Tangent[1]) / 2; Bisector.Normalize(); double BisectAngle = Math.Acos(Hare_math.Dot(Tangent[0], Bisector)); if (BisectAngle == 0) { BisectAngle = 1E-12; } v = new double[2] { Math.PI / (2 * BisectAngle), Math.PI / (Utilities.Numerics.PiX2 - 2 * BisectAngle) }; v_4pi = new double[2] { v[0] / (4 * Math.PI), v[1] / (4 * Math.PI) }; v_2pi = new double[2] { v[0] / (2 * Math.PI), v[1] / (2 * Math.PI) }; //BisectAngle = Math.Cos(BisectAngle); Normal[0] = Hare_math.Cross(_Tangents[0], Z_Norm); Normal[1] = Hare_math.Cross(_Tangents[1], Z_Norm * -1); if (Hare_math.Dot(Normal[0], Bisector) > 0) { Normal[0] *= -1; Normal[1] *= -1; } }
public bool Poly_Overlap_Area(Polygon Pts, out double Area) { System.Collections.Generic.List <Point> XPts = new System.Collections.Generic.List <Point>(); int ct = 0; for (int i = 0; i < Pts.VertextCT; i++) { if (this.IsPointInBox(Pts.Points[i])) { ct++; XPts.Add(Pts.Points[i]); } } if (ct == Pts.VertextCT) { if (ct == 3) { Area = Hare_math.Cross(Pts.Points[1] - Pts.Points[0], Pts.Points[2] - Pts.Points[0]).Length() / 2; } else { Area = Hare_math.Cross((Pts.Points[2] - Pts.Points[0]), (Pts.Points[3] - Pts.Points[1])).Length() / 2; } return(true); } for (int i = 0; i < Pts.VertextCT; i++) { int j = (i + 1) % Pts.VertextCT; double tmin = 0; Point X = new Point(); this.Intersect(new Ray(Pts.Points[i], Pts.Points[j] - Pts.Points[i], 0, 0), ref tmin, ref X); if (tmin < 1) { XPts.Add(X); } } Point I; double u; double v; double t; int id; for (int i = 0; i < 12; i++) { if (Pts.Intersect(Edge(i), Pts.Points, out I, out u, out v, out t, out id)) { XPts.Add(I); } } if (XPts.Count == 0) { Area = 0; return(false); } //Sort XPts by polar angle. Point Center = new Point(); foreach (Point Pt in XPts) { Center += Pt; } Center /= XPts.Count; System.Collections.SortedList PtSort = new System.Collections.SortedList(); if (Pts.Normal.x == 1) { foreach (Point Pt in XPts) { PtSort.Add(System.Math.Atan2(Pt.y - Center.y, Pt.z - Center.z), Pt); } } else if (Pts.Normal.y == 1) { foreach (Point Pt in XPts) { PtSort.Add(System.Math.Atan2(Pt.x - Center.x, Pt.z - Center.z), Pt); } } else { foreach (Point Pt in XPts) { PtSort.Add(System.Math.Atan2(Pt.x - Center.x, Pt.y - Center.y), Pt); } } Area = 0; for (int i = 0; i < PtSort.Count - 2; i++) { Area += Hare_math.Cross((Point)PtSort[i + 1] - (Point)PtSort[i], (Point)PtSort[i + 2] - (Point)PtSort[i]).Length() / 2; } return(true); }
public bool PolyBoxOverlap(Point[] P) { Point[][] triangles = new Point[P.Length - 2][]; for (int q = 0, j = 1, k = 2; k < P.Length; q++, j++, k++) { triangles[q] = new Point[] { P[0], P[j], P[k] }; } foreach (Point[] triverts in triangles) { /* use separating axis theorem to test overlap between triangle and box */ /* need to test for overlap in these directions: */ /* 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle */ /* we do not even need to test these) */ /* 2) normal of the triangle */ /* 3) crossproduct(edge from tri, {x,y,z}-directin) */ /* this gives 3x3=9 more tests */ v0 = new Vector(0, 0, 0); v1 = new Vector(0, 0, 0); v2 = new Vector(0, 0, 0); // float axis[3]; double fex, fey, fez; // -NJMP- "d" local variable removed Vector normal, e0, e1, e2; /* This is the fastest branch on Sun */ /* move everything so that the boxcenter is in (0,0,0) */ v0 = triverts[0] - Center; v1 = triverts[1] - Center; v2 = triverts[2] - Center; /* compute triangle edges */ e0 = v1 - v0; /* tri edge 0 */ e1 = v2 - v1; /* tri edge 1 */ e2 = v0 - v2; /* tri edge 2 */ /* Bullet 3: */ /* test the 9 tests first (this was faster) */ fex = Math.Abs(e0.x); fey = Math.Abs(e0.y); fez = Math.Abs(e0.z); if (!AXISTEST_X01(e0.z, e0.y, fez, fey)) { continue; } if (!AXISTEST_Y02(e0.z, e0.x, fez, fex)) { continue; } if (!AXISTEST_Z12(e0.y, e0.x, fey, fex)) { continue; } fex = Math.Abs(e1.x); fey = Math.Abs(e1.y); fez = Math.Abs(e1.z); if (!AXISTEST_X01(e1.z, e1.y, fez, fey)) { continue; } if (!AXISTEST_Y02(e1.z, e1.x, fez, fex)) { continue; } if (!AXISTEST_Z0(e1.y, e1.x, fey, fex)) { continue; } fex = Math.Abs(e2.x); fey = Math.Abs(e2.y); fez = Math.Abs(e2.z); if (!AXISTEST_X2(e2.z, e2.y, fez, fey)) { continue; } if (!AXISTEST_Y1(e2.z, e2.x, fez, fex)) { continue; } if (!AXISTEST_Z12(e2.y, e2.x, fey, fex)) { continue; } /* Bullet 1: */ /* first test overlap in the {x,y,z}-directions */ /* find min, max of the triangle each direction, and test for overlap in */ /* that direction -- this is equivalent to testing a minimal AABB around */ /* the triangle against the AABB */ /* test in X-direction */ FINDMINMAX(v0.x, v1.x, v2.x, ref min, ref max); if (min > halfwidth.x || max < -halfwidth.x) { continue; } /* test in Y-direction */ FINDMINMAX(v0.y, v1.y, v2.y, ref min, ref max); if (min > halfwidth.y || max < -halfwidth.y) { continue; } /* test in Z-direction */ FINDMINMAX(v0.z, v1.z, v2.z, ref min, ref max); if (min > halfwidth.z || max < -halfwidth.z) { continue; } /* Bullet 2: */ /* test if the box intersects the plane of the triangle */ /* compute plane equation of triangle: normal*x+d=0 */ normal = Hare_math.Cross(e0, e1); if (!planeBoxOverlap(normal, v0, halfwidth)) { continue; // -NJMP- } return(true); /* box and triangle overlaps */ } return(false); }