Beispiel #1
0
        public List <Plane3D> WalkTreeRecursive(Tube3D Tube, OctreeNode Node)
        {
            List <Plane3D> Suspects = new List <Plane3D>();

            bool IntersectsWithMe =
                Node.MyAABB.IntersectLine(Tube.Rays[0].Begin, Tube.Rays[0].End) ||
                Node.MyAABB.IntersectLine(Tube.Rays[1].Begin, Tube.Rays[1].End) ||
                Node.MyAABB.IntersectLine(Tube.Rays[2].Begin, Tube.Rays[2].End);

            if (IntersectsWithMe && Node.Final)
            {
                return(Node.Faces);
            }

            if (!IntersectsWithMe && Node.Final)
            {
                return(Suspects);
            }

            for (int i = 0; i < 8; ++i)
            {
                Suspects.AddRange(WalkTreeRecursive(Tube, Node.Childs[i]));
            }

            return(Suspects);
        }
Beispiel #2
0
        public Tube3D UniversalSplit(Vector3[] Points)
        {
            Tube3D t = new Tube3D(this);



            Plane3D UpperPlane = new Plane3D(Rays[0].End, Rays[1].End, Rays[2].End, false);

            try
            {
                UpperPlane.CalcNormal();
            }
            catch
            {
                return(null);
            }

            Plane3D LowerPlane = new Plane3D(Rays[0].Begin, Rays[1].Begin, Rays[2].Begin, false);

            for (int i = 0; i < 3; ++i)
            {
                double u, v, n;
                UpperPlane.GetUV(Points[i], out u, out v, out n);
                t.Rays[i] = new Ray3D(LowerPlane.UVToXYZ(u, v), Points[i], t.Rays[i]);
            }
            return(t);
        }
Beispiel #3
0
 public List <Plane3D> WalkTree(Tube3D Tube)
 {
     if (!Built)
     {
         return(new List <Plane3D>());
     }
     return(WalkTreeRecursive(Tube, Root));
 }
Beispiel #4
0
 public Tube3D(Tube3D old)
 {
     MyN             = old.MyN;
     MyDelta         = old.MyDelta;
     IsSPolarization = old.IsSPolarization;
     for (int i = 0; i < 3; ++i)
     {
         Rays[i] = new Ray3D(old.Rays[i]);
     }
 }
Beispiel #5
0
        public void CreateInitialRays(Vector3 Pos, int Details = 10)
        {
            InitialRays.Clear();

            for (int i = 0; i < Details; ++i)
            {
                for (int j = 0; j < Details; ++j)
                {
                    double Phi1 = Utils2D.I2Diap(i, Details, 0, Math.PI * 2);
                    double Phi2 = Utils2D.I2Diap(i + 1, Details, 0, Math.PI * 2);

                    double The1 = Utils2D.I2Diap(j, Details, -Math.PI, Math.PI);
                    double The2 = Utils2D.I2Diap(j + 1, Details, -Math.PI, Math.PI);

                    double x1, x2, x3, x4;
                    double y1, y2, y3, y4;
                    double z1, z2, z3, z4;

                    double r = 50;
                    Utils3D.SphToXYZ(r, Phi1, The1, out x1, out y1, out z1);
                    Utils3D.SphToXYZ(r, Phi2, The1, out x2, out y2, out z2);
                    Utils3D.SphToXYZ(r, Phi1, The2, out x3, out y3, out z3);
                    Utils3D.SphToXYZ(r, Phi2, The2, out x4, out y4, out z4);

                    Tube3D t = new Tube3D();

                    t.Rays[0].Begin = Pos + Vector3.xAxis * 0.005;
                    t.Rays[1].Begin = Pos + Vector3.yAxis * 0.005;
                    t.Rays[2].Begin = Pos;

                    t.Rays[0].End = new Vector3(x1 + Pos.X, y1 + Pos.Y, z1 + Pos.Z);
                    t.Rays[1].End = new Vector3(x2 + Pos.X, y2 + Pos.Y, z2 + Pos.Z);
                    t.Rays[2].End = new Vector3(x3 + Pos.X, y3 + Pos.Y, z3 + Pos.Z);

                    InitialRays.Add(t);

                    /*
                     *  Gl.glNormal3d(nx, ny, nz);
                     * Gl.glVertex3d(x1, y1, z1);
                     * Gl.glVertex3d(x2, y2, z2);
                     * Gl.glVertex3d(x3, y3, z3);
                     *
                     * NormalToVector(x2, y2, z2, x3, y3, z3, x4, y4, z4, out nx, out ny, out nz);
                     *
                     * Gl.glNormal3d(nx, ny, nz);
                     * Gl.glVertex3d(x2, y2, z2);
                     * Gl.glVertex3d(x3, y3, z3);
                     *
                     * Gl.glVertex3d(x4, y4, z4);*/
                }
            }
        }
Beispiel #6
0
        public Tube3D Split2(int SaveVertex, int FirstEdgeIndex, Vector3 One, Vector3 Two)
        {
            Tube3D t = new Tube3D(this);

            t.Rays[SaveVertex] = new Ray3D(Rays[SaveVertex]);

            int LastIndex = 3 - SaveVertex - FirstEdgeIndex;


            double FirstEdgeSplitFactor  = Rays[SaveVertex].End.Distance(One) / Rays[FirstEdgeIndex].End.Distance(Rays[SaveVertex].End);
            double SecondEdgeSplitFactor = Rays[FirstEdgeIndex].End.Distance(Two) / Rays[LastIndex].End.Distance(Rays[FirstEdgeIndex].End);

            Vector3 BottomOne = Rays[SaveVertex].Begin.Interpolate(Rays[FirstEdgeIndex].Begin, FirstEdgeSplitFactor);
            Vector3 BottomTwo = Rays[FirstEdgeIndex].Begin.Interpolate(Rays[LastIndex].Begin, SecondEdgeSplitFactor);

            t.Rays[FirstEdgeIndex] = new Ray3D(BottomOne, One, Rays[FirstEdgeIndex]);
            t.Rays[LastIndex]      = new Ray3D(BottomTwo, Two, Rays[LastIndex]);

            return(t);
        }
Beispiel #7
0
        public TubeProcessResult ProcessTubeStageTwo(TubeProcessingData t, Tube3D tube, List <Tube3D> ReflRefrTubes, List <Tube3D> SplitTubes, List <Tube3D> AddTubes)
        {
            TubeProcessResult Tpr = new TubeProcessResult();

            /* Попробуем иначе!!!
             *
             * */

            /*
             * ВОТ СЮДА ВСТАВЛЯЮ ТЕСТОВЫЙ КОД!!!
             */
            // Список вершин для триангуляции
            List <Vector2> VertsForDelauney1 = new List <Vector2>();

            // Важно, что сначала я добавляю PinTs
            for (int i = 0; i < t.PinTs.Count; ++i)
            {
                VertsForDelauney1.Add(t.Vert[t.PinTs[i]]);
            }

            // Затем пересечения
            int Ic = t.Intersections.Count;

            for (int i = 0; i < Ic; ++i)
            {
                VertsForDelauney1.Add(new Vector2(t.Intersections[i].u, t.Intersections[i].v));
            }


            // Случай такой: часть грани оказалась под нижней плоскостью трубки
            bool PlaneIntersectsBottomTubePlane = t.DoNotAddPP[0] || t.DoNotAddPP[1] || t.DoNotAddPP[2];

            Log("Stage 2: BEGIN - Addional actions need? " + PlaneIntersectsBottomTubePlane.ToString());
            if (PlaneIntersectsBottomTubePlane)
            {
                // удалим из массива для триангуляции все точки, лежажие ниже нижней плоскости трубки
                int Dt = VertsForDelauney1.Count;
                VertsForDelauney1.RemoveAll(xx =>
                                            (xx != t.UVs[0] && xx != t.UVs[1] && xx != t.UVs[2]) &&
                                            ((t.DoNotAddPP[0] && xx == t.Vert[0]) ||
                                             (t.DoNotAddPP[1] && xx == t.Vert[1]) ||
                                             (t.DoNotAddPP[2] && xx == t.Vert[2]) ||
                                             t.UnderPlane(UVToXYZ(xx.x, xx.y) - tube.Rays[0].Begin))
                                            );

                Log("Excl case Delta -> VertsForDelauney1.Count = " + (Dt - VertsForDelauney1.Count));

                // Созданим треугольник из нижней плоскости трубки
                Plane3D Bp = new Plane3D(tube.Rays[0].Begin, tube.Rays[1].Begin, tube.Rays[2].Begin, true);

                // Теперь выясним какие именно стороны грани пересекают эту плосокость

                // Индексы i<номер стороны>_<вершина>
                int i1_1, i1_2, i2_1, i2_2;

                // Число вершин под плосотью Bp
                int UnderVertNum = (t.DoNotAddPP[0] ? 1 : 0) + (t.DoNotAddPP[1] ? 1 : 0) + (t.DoNotAddPP[2] ? 1 : 0);
                int iUnderOrAbove;
                // одна снизу
                if (UnderVertNum == 1)
                {
                    // Определили какая снизу
                    iUnderOrAbove = (t.DoNotAddPP[0] ? 0 : (t.DoNotAddPP[1] ? 1 : 2));
                }
                // две снизу
                else
                {
                    // Какая сверху оказалась?
                    iUnderOrAbove = (!t.DoNotAddPP[0] ? 0 : (!t.DoNotAddPP[1] ? 1 : 2));
                }
                // Значит две стороны от нее исходят к остальным двум вершинам
                i1_1 = iUnderOrAbove;
                i2_1 = iUnderOrAbove;
                switch (iUnderOrAbove)
                {
                case 0: i1_2 = 1; i2_2 = 2; break;

                case 1: i1_2 = 0; i2_2 = 2; break;

                default: i1_2 = 0; i2_2 = 1; break;
                }
                //Log("Indices i1_1 = " + i1_1 + " i1_2 = " + i1_2 + " i2_1 = " + i2_1 + " i2_2 = " + i2_2);

                // сюда занесем точки пересечения сторон грани с плосокотью Bp
                Vector2 PIB1 = new Vector2();
                Vector2 PIB2 = new Vector2();

                // собственно поиск пересечений сторон грани с плосоктью Bp
                int res1 = Bp.RayIntersect(new Ray3D(Vertex[i1_1], Vertex[i1_2]), out PIB1.x, out PIB1.y);
                int res2 = Bp.RayIntersect(new Ray3D(Vertex[i2_1], Vertex[i2_2]), out PIB2.x, out PIB2.y);
                Log("res1 = " + res1 + " res2 = " + res2);

                // проверим пересечия уже в плосокти Bp
                Vector2[] Rps = new Vector2[3] {
                    new Vector2(0, 0), new Vector2(1, 0), new Vector2(0, 1)
                };
                if (res1 < 0 || res2 < 0)
                {
                    for (int i = 0; i < 3; ++i)
                    {
                        int nexti = i == 2 ? 0 : i + 1;
                        var cr    = Utils2D.Crossing(Rps[i], Rps[nexti], PIB1, PIB2);
                        if (cr.type == Utils2D.EnumCrossType.ctInBounds || cr.type == Utils2D.EnumCrossType.ctOnBounds)
                        {
                            double u, v, n;
                            GetUV(Bp.UVToXYZ(cr.pt.x, cr.pt.y), out u, out v, out n);
                            VertsForDelauney1.Add(new Vector2(u, v));
                        }
                    }
                }

                // добавим в массив для триангуляции точки отрезка, если они внутри треуголньика
                if (res1 > 0)
                {
                    double u, v, n;
                    GetUV(Bp.UVToXYZ(PIB1.x, PIB1.y), out u, out v, out n);
                    VertsForDelauney1.Add(new Vector2(u, v));
                }
                if (res2 > 0)
                {
                    double u, v, n;
                    GetUV(Bp.UVToXYZ(PIB2.x, PIB2.y), out u, out v, out n);
                    VertsForDelauney1.Add(new Vector2(u, v));
                }

                if (VertsForDelauney1.Count < 3)
                {
                    AddTubes.Add(tube);
                    Log("!!!1");

                    return(Tpr);
                }
            }


            List <Triangle> Triangles = new List <Triangle>();

            int cnt1 = VertsForDelauney1.Count;

            // удаляем всех дублеров
            VertsForDelauney1 = VertsForDelauney1.Distinct(new RealPointComparer()).ToList();
            // сколько убавилось?
            Log("Delta -> cnt : VertsForDelauney1 = " + (VertsForDelauney1.Count - cnt1));

            // Индекс с которого ядро в списке кончилось
            int CoreEndIndex = 0;

            if (t.cs == TTCase.CaseA)
            {
                for (int i = 0; i < 3; ++i)
                {
                    VertsForDelauney1.Add(t.UVs[i]);
                }
                Triangles.Add(new Triangle(0, 1, 2, true));
                CoreEndIndex = 1;
            }
            else
            {
                // ядро триангулируем
                Triangles    = Utils2D.RoundTrianglulationWOCenter(VertsForDelauney1);
                CoreEndIndex = Triangles.Count;

                int TubePStartIndex = VertsForDelauney1.Count;
                // Потом точки трубки добавим туда же после триангуляции ядра
                for (int i = 0; i < 3; ++i)
                {
                    VertsForDelauney1.Add(t.UVs[i]);
                }

                // Что теперь? Берем произвольное ребро выпулклого многоугольника ядра и рассекаем им пространоство
                for (int iE = 0; iE < TubePStartIndex; ++iE)
                {
                    int F1 = iE;
                    int F2 = iE == TubePStartIndex - 1 ? 0 : iE + 1;

                    // Сперва, нам нужно найти все точки трубки, лежащие левее от этого ребра
                    List <int> LeftToEdge = new List <int>();
                    for (int i = 0; i < VertsForDelauney1.Count; ++i)
                    {
                        if (
                            F1 == i || F2 == i ||
                            Utils2D.Classify(VertsForDelauney1[F1].x, VertsForDelauney1[F1].y, VertsForDelauney1[F2].x, VertsForDelauney1[F2].y, VertsForDelauney1[i].x, VertsForDelauney1[i].y) > Tracer3D.GeometryEpsilon)
                        {
                            LeftToEdge.Add(i);
                        }
                    }

                    // есть, о чем говорить
                    if (LeftToEdge.Count == 3)
                    {
                        Triangles.Add(new Triangle(LeftToEdge[0], LeftToEdge[1], LeftToEdge[2]));
                        Triangles[Triangles.Count - 1].Dump("Single T[" + (Triangles.Count - 1) + "] on core-edge F1 = " + F1 + " F2 = " + F2, VertsForDelauney1);
                    }
                    else if (LeftToEdge.Count > 3)
                    {
                        List <Vector2> Region = new List <Vector2>();
                        LeftToEdge.ForEach(delegate(int p)
                        {
                            VertsForDelauney1[p].Tag = p;
                            Region.Add(VertsForDelauney1[p]);
                        });

                        List <Triangle> RegionTriangles = Utils2D.RoundTrianglulationWOCenter(Region);

                        RegionTriangles.ForEach(delegate(Triangle tr)
                        {
                            Triangles.Add(new Triangle(
                                              Region[tr.p1].Tag,
                                              Region[tr.p2].Tag,
                                              Region[tr.p3].Tag
                                              ));
                            Triangles[Triangles.Count - 1].Dump("Multi  T[" + (Triangles.Count - 1) + "] on core-edge F1 = " + F1 + " F2 = " + F2, VertsForDelauney1);
                        });
                    }
                }

                // Все таки костыль!
                // Ищем ребро, на котором нет пересечений, оно подозрительно
                for (int i = 0; i < 3; ++i)
                {
                    // их нет!
                    if (t.HasNoIc[i])
                    {
                        int j = i == 2 ? 0 : i + 1;
                        j += TubePStartIndex;
                        int ii = i + TubePStartIndex;

                        // Есть ли треугольник, содержащий его?
                        int itr = Triangles.FindIndex(x =>
                                                      x.HasVertex(ii) && x.HasVertex(j)
                                                      );
                        Log("KOST! ");
                        if (itr == -1)
                        {
                            // АГА! Нет такого треугольника! Создадим его
                            // Для этого нам нужно найти точку ядра наиболее близкую к ребру i
                            int iWTF = 0;

                            Vector3 P2P1        = new Vector3(VertsForDelauney1[ii].x - VertsForDelauney1[j].x, VertsForDelauney1[ii].y - VertsForDelauney1[j].y, 0);
                            double  MinDistance = 10e5;
                            for (int k = 0; k < TubePStartIndex; ++k)
                            {
                                double distanceFromPtoP2P1 = P2P1.CrossProduct(new Vector3(VertsForDelauney1[j].x - VertsForDelauney1[k].x, VertsForDelauney1[j].y - VertsForDelauney1[k].y, 0)).Magnitude;
                                if (MinDistance > distanceFromPtoP2P1)
                                {
                                    MinDistance = distanceFromPtoP2P1;
                                    iWTF        = k;
                                }
                            }

                            Triangles.Add(new Triangle(ii, j, iWTF));
                            Triangles[Triangles.Count - 1].Dump("KOST!  T[" + (Triangles.Count - 1) + "]", VertsForDelauney1);
                        }
                    }
                }
            }

            /* DEBUG */

            /*  // Определим количество внутренних треугольников
             * int Num = Triangles.Count(x => x.IsInner(VertsForDelauney1));
             *
             * // если их нет, значит попали мимо, значит на зачем дробить исходный
             * if (Num == 0)
             * {
             *
             *    Log("Miss!");
             *    Tpr.Cs = TTCase.CaseNo;
             *    return Tpr;
             *
             * }*/
            /* DEBUG */



            Tube3D tube2 = new Tube3D(tube); // КОСТЫЛЬ №2

            // Отрубим хвосты лучей до плоскости грани!
            for (int i = 0; i < 3; ++i)
            {
                tube2.Rays[i].End = t.IPoints[i];
            }
            // площадь трубки
            double Area = tube2.AreaTop();

            int Cnt = -1;

            foreach (Triangle tr in Triangles)
            {
                ++Cnt;
                // разбиваем трубку, вычленяем нужную
                Tube3D TubeToTrace1 = tube2.UniversalSplit(new Vector3[3] {
                    UVToXYZ(VertsForDelauney1[tr.p1].x, VertsForDelauney1[tr.p1].y),
                    UVToXYZ(VertsForDelauney1[tr.p2].x, VertsForDelauney1[tr.p2].y),
                    UVToXYZ(VertsForDelauney1[tr.p3].x, VertsForDelauney1[tr.p3].y)
                });

                if (TubeToTrace1 == null)
                {
                    continue;
                }

                /*   if (TubeToTrace1.WrongTubeTest())
                 *     Log("Stop");*/

                // DEBUG

                /*     TubeToTrace1.Tags[0] = "(" + tr.p1 + ")";
                 *   TubeToTrace1.Tags[1] = "(" + tr.p2 + ")";
                 *   TubeToTrace1.Tags[2] = "(" + tr.p3 + ")";
                 */

                // вдруг смотрит вниз? исправить, должна смотреть вверх
                for (int i = 0; i < 3; ++i)
                {
                    TubeToTrace1.Rays[i].Begin += t.WaveDirection * Tracer3D.GeometryEpsilon; // КОСТЫЛЬ №3
                    TubeToTrace1.Rays[i].End   += t.WaveDirection * Tracer3D.GeometryEpsilon * 2;
                    if (t.UnderPlane(TubeToTrace1.Rays[i].End - TubeToTrace1.Rays[i].Begin))
                    {
                        TubeToTrace1.Rays[i].End = 2 * TubeToTrace1.Rays[i].Begin - TubeToTrace1.Rays[i].End;
                    }
                }
                // наши потомки не должны воспринимать эту грань, чтобы повтроно ее не трассировать на след. шаге
                TubeToTrace1.Prohibit = this;

                // площаь потомка
                double AddArea = TubeToTrace1.AreaTop(); // ЭТО НЕ ПРАВИЛЬНО, КОГДА ГРАНЬ ПОД УКЛОНОМ!!!!

                // отгрызем кусок мощности
                TubeToTrace1.Power = tube.Power * AddArea / Area;
                //TubeToTrace1.

                // "внутренняя" трубка - та, что попала на грань, должна претерпеть отражение и преломление
                tr.Dump("", VertsForDelauney1);
                if (tr.IsInner(VertsForDelauney1))//Cnt < CoreEndIndex)//)//tr.Inner) // ?????????????????????????
                {
                    Log(" $$$ This triange is being traced! $$$");

                    // [0] - отраженная, [1] - преломленная
                    Tube3D[] RRT = ReflectAndRefractTube(TubeToTrace1);
                    if (RRT[0] != null)
                    {
                        // DEBUG
                        RRT[0].Comment = tube.Comment + " ; refl ";

                        // добавим ее в отраженные
                        RRT[0].Prohibit = this;
                        ReflRefrTubes.Add(RRT[0]);
                    }

                    if (RRT[1] != null)
                    {
                        // DEBUG
                        RRT[1].Comment = tube.Comment + " ; refr ";

                        // добавим ее в преломленные
                        RRT[1].Prohibit = this;
                        ReflRefrTubes.Add(RRT[1]);
                    }

                    // DEBUG
                    TubeToTrace1.Comment = tube.Comment + " ; me split ";

                    // а исходную - в дополнительные
                    SplitTubes.Add(TubeToTrace1);
                }
                else
                {
                    // DEBUG
                    TubeToTrace1.Comment = tube.Comment + " ; me add ";

                    // мимо грани - сразу в дополнительные
                    AddTubes.Add(TubeToTrace1);
                }
            }

            /* for (int i = 0; i < 3; ++i)
             *   if (t.UnderPlane(tube.Rays[i].End - tube.Rays[i].Begin))
             *   {
             *       Log("WWTF?");
             *       tube.Rays[i].End = 2 * tube.Rays[i].Begin - tube.Rays[i].End;
             *   }*/

            Tpr.Cs             = t.cs;
            Tpr.NumOfTriangles = Triangles.Count;
            Tpr.TotalNewTubes  = SplitTubes.Count + AddTubes.Count + ReflRefrTubes.Count;
            return(Tpr);
        }
Beispiel #8
0
        public TubeProcessingData ProcessTubeStageOne(Tube3D tube)
        {
            TubeProcessingData tpd = new TubeProcessingData();

            Vector2[] Vert = new Vector2[3] {
                new Vector2(0, 0), new Vector2(1, 0), new Vector2(0, 1)
            };

            /* 1. Сохраним дно трубки */

            /*    for (int i = 0; i < 3; ++i)
             *      tpd.OldDno[i] = new Vector3(tube.Rays[i].Begin);
             *  tube.AntiRayize();*/

            /* 2. Найдем точки пересечения каждого из лучей с плоскостью треугольника */


            int Fails      = 0;
            int UnderFails = 0;

            for (int i = 0; i < 3; ++i)
            {
                tpd.IFact[i] = RayIntersect(tube.Rays[i], out tpd.UVs[i].x, out tpd.UVs[i].y);

                /* Плоские координаты u, v в 3D x, y, z */
                tpd.IPoints[i] = UVToXYZ(tpd.UVs[i].x, tpd.UVs[i].y);

                double t = tube.Rays[i].GetT(tpd.IPoints[i]);
                /* Если вдруг луч параллелен грани или вообще в другую сторону*/
                if (tpd.IFact[i] == -1 || tpd.IFact[i] == -2 /*|| t <= GeometryEpsilon*/ || t > 1 + Tracer3D.GeometryEpsilon)
                {
                    tpd.cs = TTCase.CaseNo;
                    //    Log("Stage1 : reject because tpd.IFact[" + i + "] = " + tpd.IFact[i] + " and t = " + t);
                    return(tpd);
                }
                else if (t <= Tracer3D.GeometryEpsilon)
                {
                    Fails++;
                    tpd.ExclusiveCaseUnderDno = true;
                    tpd.ExclusiveCaseIV[i]    = true;
                    //   Log("tpd.ExclusiveCaseUnderDno = true;");
                }
                // Log(" i = " + i + " ; t = " + t);

                /* трубка внутри треугольника */
                if (tpd.IFact[i] == 1)
                {
                    ++tpd.TinP;
                    tpd.TinPs.Add(i);
                    tpd.LastIndexTinP = i;
                }

                // Log("Stage 1: UnderPlane test: IPoints[i] = {" + tpd.IPoints[i].X + " , " + tpd.IPoints[i].Y + " , " + tpd.IPoints[i].Z + "}");
                //   Log("Stage 1: UnderPlane test: tube.Rays[0].Begin = {" + tube.Rays[0].Begin.X + " , " + tube.Rays[0].Begin.Y + " , " + tube.Rays[0].Begin.Z + "}");
                if (tpd.UnderPlane(UVToXYZ(tpd.Vert[i].x, tpd.Vert[i].y) - tube.Rays[0].Begin))
                {
                    UnderFails++;
                    tpd.DoNotAddPP[i] = true;
                    Log("Stage1 : underfail on i = " + i);

                    if (UnderFails == 3)
                    {
                        tpd.cs = TTCase.CaseNo;
                        Log("Stage1 : reject because UnderFails = 3");
                        return(tpd);
                    }
                }

                //if (cw != null) cw("IPoints[" + i + "] = " + IPoints[i].ToString() + " >>>>> u = " + UVs[i].x + " ; v = " + UVs[i].y);
            }

            if (Fails > 2)
            {
                tpd.cs = TTCase.CaseNo;
                return(tpd);
            }


            /* 3. ищем и пересчитываем все пересечения граней треугольника с гранями трубки */
            for (int i = 0; i < 3; ++i)
            {
                /* точки треугольника в трубке ? */

                double q1 = Utils2D.Classify(tpd.UVs[0].x, tpd.UVs[0].y, tpd.UVs[1].x, tpd.UVs[1].y, Vert[i].x, Vert[i].y);
                double q2 = Utils2D.Classify(tpd.UVs[1].x, tpd.UVs[1].y, tpd.UVs[2].x, tpd.UVs[2].y, Vert[i].x, Vert[i].y);
                double q3 = Utils2D.Classify(tpd.UVs[2].x, tpd.UVs[2].y, tpd.UVs[0].x, tpd.UVs[0].y, Vert[i].x, Vert[i].y);

                if ((q1 > 0 && q2 > 0 && q3 > 0) || (q1 < 0 && q2 < 0 && q3 < 0))
                {
                    ++tpd.PinT;
                    tpd.PinTs.Add(i);
                    tpd.LastIndexPinT = i;
                }

                int nexti = i == 2 ? 0 : i + 1;
                for (int j = 0; j < 3; ++j)
                {
                    int nextj = j == 2 ? 0 : j + 1;
                    Utils2D.CrossResultRec crr = Utils2D.Crossing(Vert[j], Vert[nextj], tpd.UVs[i], tpd.UVs[nexti]);
                    if (crr.type == Utils2D.EnumCrossType.ctOnLine)
                    {
                        //   double t1 = Utils2D.GetParameterLinesPoint(tpd.Vert[j], tpd.Vert[nextj], tpd.UVs[i]);
                        //   double t2 = Utils2D.GetParameterLinesPoint(tpd.Vert[j], tpd.Vert[nextj], tpd.UVs[nexti]);
                        tpd.Intersections.Add(new IntersectRecord(tpd.UVs[i], i, nexti, j, nextj));
                        tpd.Intersections.Add(new IntersectRecord(tpd.UVs[nexti], i, nexti, j, nextj));
                        //  tpd.DoNotAddPT[i] = true;
                        //  tpd.DoNotAddPT[nexti] = true;
                        tpd.HasNoIc[i] = false;
                    }
                    else if (crr.type == Utils2D.EnumCrossType.ctInBounds || crr.type == Utils2D.EnumCrossType.ctOnBounds)
                    {
                        tpd.Intersections.Add(new IntersectRecord(crr.pt, i, nexti, j, nextj));
                        tpd.HasNoIc[i] = false;
                    }

                    /* else if (crr.type == Utils2D.EnumCrossType.ctOutBounds)
                     * {
                     *   tpd.OutIntersections.Add(new IntersectRecord(crr.pt, i, nexti, j, nextj));
                     * }*/
                }
            }

            int Ic = tpd.Intersections.Count;

            if (tpd.PinT == 0 && tpd.TinP == 0 && Ic < 4)
            {
                tpd.cs = TTCase.CaseNo;
                return(tpd);
            }

            /* 4. теперь зная TinP, PinT, Intersections.Count можно рассмотреть все 8 случаев */
            tpd.cs = WhichCase(tpd.TinP, tpd.PinT, Ic); // определим случай

            /* 5. если пересечение есть, смотрим минимальную дистанцию до каждого луча */
            if (tpd.cs != TTCase.CaseNo)
            {
                tpd.Distance = Math.Min(Math.Min(
                                            (tube.Rays[0].Begin - tpd.IPoints[0]).SumComponentSqrs(),
                                            (tube.Rays[1].Begin - tpd.IPoints[1]).SumComponentSqrs()),
                                        (tube.Rays[2].Begin - tpd.IPoints[2]).SumComponentSqrs());
                tpd.WaveDirection = tube.CenterDirection();
                tpd.WaveDirection.Normalize();
            }

            /*  for (int i = 0; i < 3; ++i)
             *    tube.Rays[i].Begin = tpd.OldDno[i];*/

            return(tpd);
        }
Beispiel #9
0
        // 0 - REFLECT
        // 1 - REFRACT
        public Tube3D[] ReflectAndRefractTube(Tube3D itube)
        {
            Tube3D[] rtube = new Tube3D[2] {
                null, null
            };

            // центральное направление падающей трубки
            Vector3 Dir = itube.CenterDirection();
            // косинус угла падения
            double CosThetaI = Dir.DotProduct(Normal) / Dir.Magnitude;

            CosThetaI = Math.Abs(CosThetaI);

            // просветвляющее покрытие - нет отраженной трубки
            if (Tp != PlaneType.Antireflection)
            {
                rtube[0]         = new Tube3D(); // всегда есть отражение
                rtube[0].MyN     = itube.MyN;
                rtube[0].MyDelta = itube.MyDelta;
            }

            // показатель преломления в среде 2
            double n2;
            double n1 = itube.MyN;
            // флаг того, что лучи идут из среды в вакуум (true) или наоборот (fasle)
            bool FromMediumToVacuum;

            if (itube.MyN == InnerN) // это значит луч распространялся в толще вещества и теперь выходит наружу
            {
                n2 = 1;              // вакуум
                FromMediumToVacuum = true;
            }
            else // перешли из вакуума в среду
            {
                n2 = InnerN;
                FromMediumToVacuum = false;
            }

            // косинус угла преломления
            double CosThetaTSqr = 1 - (n1 * n1) / (n2 * n2) * (1 - CosThetaI * CosThetaI);

            // коэффициент отражения по формулам Френеля
            double ReCoeff = 1.0;


            // если этот косинус не в [-1,1], значит и нет преломления; так же, если поверхность - металл его тоже нет
            if (Tp != PlaneType.Metal && Math.Abs(CosThetaTSqr) <= 1)
            {
                // это - не полное внутреннее отражение, значит есть (возможно) преломленный
                rtube[1]         = new Tube3D();
                rtube[1].MyN     = n2;
                rtube[1].MyDelta = FromMediumToVacuum ? 0.0 : InnerDelta;

                double CosThetaT = Math.Sqrt(CosThetaTSqr);

                if (n1 != n2)
                {
                    if (itube.IsSPolarization)
                    {
                        ReCoeff = (n1 * CosThetaI - n2 * CosThetaT) / (n1 * CosThetaI + n2 * CosThetaT);
                    }
                    else
                    {
                        ReCoeff = (n1 * CosThetaT - n2 * CosThetaI) / (n1 * CosThetaT + n2 * CosThetaI);
                    }

                    ReCoeff *= ReCoeff;
                }
                else
                {
                    ReCoeff  = 0;
                    rtube[0] = null;
                }
            }

            // в каждой трубке - три луча
            for (int i = 0; i < 3; ++i)
            {
                if (rtube[0] != null)
                {
                    // отраженные лучи
                    rtube[0].Rays[i] = Reflected(itube.Rays[i]);
                    rtube[0].Color   = new Vector4(0, 0, 1, 1);

                    // добавим к лучу пройденную дистанцию от соответствующего луча падающей трубки

                    rtube[0].Rays[i].AddPath(itube.Rays[i], itube.MyN); // !!! добавить фазу на отражение
                }
                if (rtube[1] != null)
                {
                    // преломленный луч
                    rtube[1].Rays[i] = Refracted(itube.Rays[i], itube.MyN, rtube[1].MyN);
                    if (rtube[1].Rays[i] == null) // если хоть один из лучей испытывает полное внутрненнее отражение - нафиг всю трубку
                    {
                        rtube[1] = null;
                        continue;
                    }
                    rtube[1].Color = new Vector4(0, 0.5, 0, 1);

                    rtube[1].Rays[i].AddPath(itube.Rays[i], itube.MyN);
                }
            }
            if (rtube[0] != null)
            {
                rtube[0].Power = itube.Power * ReCoeff; rtube[0].Color.A = rtube[0].Power;
            }
            if (rtube[1] != null)
            {
                rtube[1].Power = itube.Power * (1 - ReCoeff); rtube[1].Color.A = rtube[1].Power;
            }

            return(rtube);
        }