< Summary

Information
Class: MorphoGeometry.Intersection
Assembly: MorphoGeometry
File(s): D:\a\Morpho\Morpho\project\Morpho\MorphoGeometry\Intersection.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 133
Coverable lines: 133
Total lines: 227
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 46
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
RayFaceIntersect(...)0%140%
RaysFaceGroupIntersect(...)0%120%
RayFaceIntersectFrontBack(...)0%20%
IsPointInsideFaceGroup(...)0%40%
IsPointInside(...)0%140%

File(s)

D:\a\Morpho\Morpho\project\Morpho\MorphoGeometry\Intersection.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using System.Threading.Tasks;
 5
 6namespace MorphoGeometry
 7{
 8    /// <summary>
 9    /// Intersection class.
 10    /// </summary>
 11    public class Intersection
 12    {
 13        /// <summary>
 14        /// Ray face intersection.
 15        /// </summary>
 16        /// <param name="ray">Ray.</param>
 17        /// <param name="face">Face.</param>
 18        /// <param name="reverse">Reverse the face.</param>
 19        /// <param name="project">Project the intersection points.</param>
 20        /// <returns>Intersection point.</returns>
 21        public static Vector RayFaceIntersect(Ray ray, Face face,
 22            bool reverse = false, bool project = false)
 023        {
 24            Vector v0, v1, v2;
 25
 026            if (reverse)
 027            {
 028                v1 = face.A;
 029                v0 = face.B;
 030                v2 = face.C;
 031            }
 32            else
 033            {
 034                v0 = face.A;
 035                v1 = face.B;
 036                v2 = face.C;
 037            }
 38
 039            Vector v0v1 = v1.Sub(v0);
 040            Vector v0v2 = v2.Sub(v0);
 041            Vector pvec = ray.direction.Cross(v0v2);
 042            float det = v0v1.Dot(pvec);
 43
 044            if (det < 0.000001)
 045                return null;
 46
 047            float invDet = (float)(1.0 / det);
 048            Vector tvec = ray.origin.Sub(v0);
 049            float u = tvec.Dot(pvec) * invDet;
 50
 051            if (u < 0 || u > 1)
 052                return null;
 53
 054            Vector qvec = tvec.Cross(v0v1);
 055            float v = ray.direction.Dot(qvec) * invDet;
 56
 057            if (v < 0 || u + v > 1)
 058                return null;
 59
 060            float distance = (v0v2.Dot(qvec) * invDet);
 061            float c = (float) Math.Sqrt(ray.direction.x *
 062                ray.direction.x + ray.direction.y * ray.direction.y +
 063                ray.direction.z * ray.direction.z);
 064            float angle = distance / c;
 65
 066            Vector intersection = new Vector(ray.origin.x +
 067                ray.direction.x * angle, ray.origin.y +
 068                ray.direction.y * angle, ray.origin.z + ray.direction.z * angle);
 69
 070            if (project)
 071                intersection = new Vector(ray.origin.x, ray.origin.y, ray.origin.z);
 72
 073            return intersection;
 074        }
 75
 76        /// <summary>
 77        /// Rays facegroup intersection.
 78        /// </summary>
 79        /// <param name="rays">Rays.</param>
 80        /// <param name="facegroup">Facegroup to hit.</param>
 81        /// <param name="RayMethod">Intersection method.</param>
 82        /// <param name="reverse">Reverse the faces.</param>
 83        /// <param name="project">Project the intersection points.</param>
 84        /// <returns>Intersection points.</returns>
 85        public static IEnumerable<Vector> RaysFaceGroupIntersect(IEnumerable<Ray> rays,
 86            FaceGroup facegroup,
 87            Func<Ray, Face, bool, bool, Vector> RayMethod,
 88            bool reverse = false,
 89            bool project = false)
 090        {
 091            var faceIntersectArr = new List<Vector>[facegroup.Faces.Count];
 92
 093            Parallel.For(0, facegroup.Faces.Count, i =>
 094            {
 095                var partial = new List<Vector>();
 096                var face = facegroup.Faces[i];
 097                var min = face.Min();
 098                var max = face.Max();
 099
 0100                foreach (var ray in rays)
 0101                {
 0102                    if (ray.origin.x < min.x) continue;
 0103                    if (ray.origin.y < min.y) continue;
 0104                    if (ray.origin.x > max.x) continue;
 0105                    if (ray.origin.y > max.y) continue;
 0106
 0107                    var intersection = RayMethod(ray, face, reverse, project);
 0108                    if (intersection != null)
 0109                    {
 0110                        partial.Add(intersection);
 0111                    }
 0112                }
 0113                faceIntersectArr[i] = partial;
 0114            });
 0115            var intersections = faceIntersectArr
 0116                .SelectMany(i => i)
 0117                .Where(_ => _ != null);
 118
 0119            return intersections;
 0120        }
 121
 122        /// <summary>
 123        /// Ray face intersection both face directions.
 124        /// </summary>
 125        /// <param name="ray">Ray.</param>
 126        /// <param name="face">Face.</param>
 127        /// <param name="reverse">Reverse the face.</param>
 128        /// <param name="project">Project intersection points.</param>
 129        /// <returns>Intersection point.</returns>
 130        public static Vector RayFaceIntersectFrontBack(Ray ray,
 131            Face face, bool reverse, bool project)
 0132        {
 0133            if (face.IsPointBehind(ray.origin) < 0)
 0134            {
 0135                return RayFaceIntersect(ray, face, true, project);
 136            }
 137            else
 0138            {
 0139                return RayFaceIntersect(ray, face, reverse, project);
 140            }
 0141        }
 142
 143        /// <summary>
 144        /// Is point inside a facegroup.
 145        /// </summary>
 146        /// <param name="vectors">Points to test.</param>
 147        /// <param name="facegroup">Facegroup.</param>
 148        /// <returns>Inside points.</returns>
 149        public static IEnumerable<Vector> IsPointInsideFaceGroup(List<Vector> vectors,
 150            FaceGroup facegroup)
 0151        {
 0152            var points = new Vector[vectors.Count()];
 153
 0154            for (int i = 0; i < vectors.Count; i++)
 0155            {
 0156                if (IsPointInside(facegroup, vectors[i]))
 0157                {
 0158                    points[i] = vectors[i];
 0159                }
 0160            }
 0161            var intersections = points
 0162                .Where(_ => _ != null);
 163
 0164            return intersections;
 0165        }
 166
 167        /// <summary>
 168        /// Is point inside a facegroup.
 169        /// </summary>
 170        /// <param name="facegroup">Facegroup.</param>
 171        /// <param name="point">Point to test.</param>
 172        /// <returns>True or false.</returns>
 173        public static bool IsPointInside(FaceGroup facegroup, Vector point)
 0174        {
 0175            var triangles = facegroup.ToArray();
 0176            var P = point.ToArray();
 177
 0178            foreach (var tri in triangles)
 0179                foreach (var pt in tri)
 0180                    for (var i = 0; i < pt.Length; i++)
 0181                        pt[i] -= P[i];
 182
 0183            var qM = new float[triangles.Length][][];
 0184            var Mnorm = new float[triangles.Length][];
 0185            for (var i = 0; i < triangles.Length; i++)
 0186            {
 0187                var tri = triangles[i];
 0188                qM[i] = new float[tri.Length][];
 0189                Mnorm[i] = new float[tri.Length];
 0190                for (var j = 0; j < tri.Length; j++)
 0191                {
 0192                    var pt = tri[j];
 0193                    qM[i][j] = new float[pt.Length];
 0194                    for (int k = 0; k < pt.Length; k++)
 0195                    {
 0196                        qM[i][j][k] = Convert.ToSingle(Math.Pow((double)pt[k],
 0197                            (double)2));
 0198                    }
 0199                    Mnorm[i][j] = Convert.ToSingle(Math
 0200                        .Sqrt((double)qM[i][j].Sum()));
 0201                }
 0202            }
 203
 0204            var winding_number = 0.0;
 0205            for (var i = 0; i < Mnorm.Length; i++)
 0206            {
 0207                triangles[i].Deconstruct(out float[] A, out float[] B, out float[] C);
 0208                Mnorm[i].Deconstruct(out float a, out float b, out float c);
 209
 0210                var j = (a * b * c);
 0211                var jj = c * (Vector.FromArray(A)
 0212                    .Dot(Vector.FromArray(B)));
 0213                var jjj = a * (Vector.FromArray(B)
 0214                    .Dot(Vector.FromArray(C)));
 0215                var jjjj = b * (Vector.FromArray(C)
 0216                    .Dot(Vector.FromArray(A)));
 217
 0218                var tot = j + jj + jjj + jjjj;
 219
 0220                var det = Vector.Det3x3(new float[3][] { A, B, C });
 0221                winding_number += Math.Atan2((double)det, (double)tot - 1);
 222
 0223            }
 0224            return winding_number >= (2.0 * Math.PI);
 0225        }
 226    }
 227}