Esempio n. 1
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);
        }
Esempio n. 2
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);
        }