예제 #1
0
파일: Phisics.cs 프로젝트: zurk/KIProgect
        /// <summary>
        /// Функция, которая нахоидит конец волны и задает отраженную
        /// </summary>
        /// <param name="prevWave">предыдущая волна </param>
        /// <param name="polygons">препятствия в комнате</param>
        /// <param name="room"> комната </param>
        /// <returns>отраженная волна</returns>
        static void FindNextWaves(Wave prevWave, List<Polygon> polygons, Polygon room, out Wave nextReflWave, out Wave nextRefrWave)
        {
            float A1 = 0, B1 = 0, C1 = 0; // коэффициенты прямой предыдущей волны
            float A2 = 0, B2 = 0, C2 = 0; // коэффициенты прямой, на которой лежит сторона многоугольника
            float x0 = 0, y0 = 0;         // точка 0
            float x1 = 0, y1 = 0;         // точка 1
            float TurnA = 0, TurnB=0;               // угол поворота для отражения
            Point refl = new Point();     // точка начала новой волны
            List<float> length = new List<float>(); // список длин возможных волн
            List<int> nomb = new List<int>();       // номера многоуголиников, с которыми возможно пересечение
            List<Point> points = new List<Point>(); // точки пересечения стороны многоугольника и волны
            List<float> AAll = new List<float>(); // списки
            List<float> BAll = new List<float>(); //    коэффицентов
            List<float> CAll = new List<float>(); //        для прямых
            float temp = float.PositiveInfinity;
            Vector vect = new Vector();
            int k = 0;

            polygons.Add(room);
            nextReflWave = null;
            nextRefrWave = null;

            A1 = - prevWave.direct.y; // находим коэффициенты прямой предыдущей волны
            B1 = prevWave.direct.x;
            C1 = -B1 * prevWave.direct.nullP.y - A1 * prevWave.direct.nullP.x;

            for (int i = 0; i < polygons.Count; i++)
                for (int j = 0; j < polygons[i].Tops.Count; j++)
                {
                    x0 = polygons[i].Tops[j].x;
                    y0 = polygons[i].Tops[j].y;
                    if (j != polygons[i].Tops.Count - 1)
                    {
                        x1 = polygons[i].Tops[j+1].x;
                        y1 = polygons[i].Tops[j+1].y;
                    }
                    else
                    {
                        x1 = polygons[i].Tops[0].x;
                        y1 = polygons[i].Tops[0].y;
                    }

                    A2 = y0 - y1; // составляем уравнение прямой, на которой лежит сторона многоугольника
                    B2 = x1 - x0;
                    C2 = -y0 * B2 - x0 * A2;

                    refl.x = (C2 * B1 - C1 * B2) / (A1 * B2 - A2 * B1); // ищем точку пересечения волны и стороны
                    refl.y = (A2 * C1 - A1 * C2) / (A1 * B2 - A2 * B1);

                    if (((x0 <= refl.x && refl.x <= x1) || (x0 >= refl.x && refl.x >= x1)) &&
                        ((y0 <= refl.y && refl.y <= y1) || (y0 >= refl.y && refl.y >= y1)) &&
                        (((refl.x - prevWave.direct.nullP.x) / prevWave.direct.x > 0.0001) || ((refl.y - prevWave.direct.nullP.y) / prevWave.direct.y > 0.0001))) // если точка пересечения принадлежит стороне многоугольника
                    { // если точка лежит по ходу движения волны и на стороне многоугольника
                        length.Add(GetLengthFromTo(prevWave.direct.nullP, refl));
                        nomb.Add(i); // запонимаем её характеристики
                        nomb.Add(j);
                        points.Add(refl);
                        refl = new Point();
                        AAll.Add(A2);
                        BAll.Add(B2);
                        CAll.Add(C2);
                    }
                }
            if (length.Count == 0)
            {
                polygons.RemoveAt(polygons.Count - 1);
                return;
            }
            for (int i = 0; i < length.Count; i++) //находим самую короткую новую волну
                if (length[i] < temp)
                {
                    temp = length[i];
                    k = i * 2;
                    refl = points[i];
                }

            prevWave.end = refl;
            A2 = AAll[k / 2];
            B2 = BAll[k / 2];
            C2 = CAll[k / 2];

            Vector wallNorm = new Vector(A2, B2, null);
            wallNorm.NormalizeVector();
            vect = Vector.Minus(prevWave.direct, Vector.Mul(2 * Vector.DOT(wallNorm, prevWave.direct), wallNorm));
            vect.NormalizeVector();
            vect.nullP = refl;
            nextReflWave = new Wave(vect, prevWave.previousDist + temp,FrequencyMod.Refl( polygons[nomb[k]].mods , prevWave.waveMod)); // отраженная волна

            TurnA = (float)Math.PI / 2 - (float)Math.Acos((A1 * A2 + B1 * B2) / Math.Sqrt((A1 * A1 + B1 * B1) * (A2 * A2 + B2 * B2)));//Math.PI/2 - Math.Asin(prevWave.direct.x * polygons[nomb[k]].mods.soundSpeed / prevWave.speed);
            if (prevWave.speed != polygons[nomb[k]].mods.soundSpeed)
                TurnB = (float)Math.Asin(Math.Sin(TurnA) * polygons[nomb[k]].mods.soundSpeed / prevWave.speed);
            else
            {
                TurnB = -(float)Math.Asin(Math.Sin(TurnA) * 331.2f / prevWave.speed);
                TurnA = -TurnA;
            }
            if (TurnB > Math.Abs(Math.PI / 2))
            {
                polygons.RemoveAt(polygons.Count - 1);
                return;//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            }
            else
            {
                x0 = prevWave.direct.nullP.x;
                y0 = prevWave.direct.nullP.y;
                TurnB = -TurnB + (float)Math.PI + TurnA;
                x1 = (float)((x0 - refl.x) * Math.Cos(TurnB) - (y0 - refl.y) * Math.Sin(TurnB)) + refl.x;  //преломление волны
                y1 = (float)((x0 - refl.x) * Math.Sin(TurnB) + (y0 - refl.y) * Math.Cos(TurnB)) + refl.y;
                vect = new Vector(x1 - refl.x, y1 - refl.y, refl);
                vect.NormalizeVector();
                nextRefrWave = new Wave(vect, prevWave.previousDist + temp, FrequencyMod.Refr(prevWave.waveMod, polygons[nomb[k]].mods));
                if (prevWave.speed != polygons[nomb[k]].mods.soundSpeed)
                    nextRefrWave.speed = polygons[nomb[k]].mods.soundSpeed;
                else
                    nextRefrWave.speed = 331.2f;
                polygons.RemoveAt(polygons.Count - 1);
            }

            /*Turn = 2 * (float)(Math.PI / 2 - Math.Acos((A1 * A2 + B1 * B2) / Math.Sqrt((A1 * A1 + B1 * B1) * (A2 * A2 + B2 * B2)))); //считаем угол поворота для прямой

            x0 = prevWave.direct.nullP.x;
            y0 = prevWave.direct.nullP.y;
            x1 = (float)((x0 - refl.x) * Math.Cos(Turn) - (y0 - refl.y) * Math.Sin(Turn)) + refl.x;  //отражение волны
            y1 = (float)((x0 - refl.x) * Math.Sin(Turn) + (y0 - refl.y) * Math.Cos(Turn)) + refl.y;

            vect = new Vector( x1 - refl.x ,y1 - refl.y , refl);
            vect.NormalizeVector();
            result = new Wave(vect, prevWave.previousDist + temp,FrequencyMod.Mul( polygons[nomb[k]].mods.AmpMod , prevWave.waveMod.AmpMod)); // отраженная волна
            polygons.RemoveAt(polygons.Count-1);*/
        }
예제 #2
0
파일: Phisics.cs 프로젝트: zurk/KIProgect
        /// <summary>
        /// Функция которая создает сетку модификаторов волны
        /// </summary>
        /// <param name="polygons">список объектов в помещении</param>
        /// <param name="sourses"> источники звука</param>
        /// <param name="room"> комната</param>
        /// <param name="xSizeOfMatr">размер1 матрицы</param>
        /// <param name="ySizeOfMatr">размер2 матрицы</param>
        /// <param name="int">количество лучей для трассировки </param>
        /// <param name="float">порог энергии волны, поле которого она не рассматривается. </param>
        /*ModifiersKnot[,]*/
        public static List<BTreeNode<Wave>> GetModifiersKnots(List<Polygon> polygons, 
            List<Sourse> sourses, Polygon room, int xSizeOfMatr, int ySizeOfMatr, int RaysCount, float minAmplitude, int reflCount)
        {
            Vector vect = new Vector();
            //List<Wave> wayOfWave = new List<Wave>();
            Wave wave = new Wave();
            BTreeNode<Wave> wayOfWave = new BTreeNode<Wave>();
            List<BTreeNode<Wave>> r = new List<BTreeNode<Wave>>();
            ModifiersKnot[,] result = new ModifiersKnot[xSizeOfMatr + 2, ySizeOfMatr + 2];
            for (int i = 0; i < xSizeOfMatr+2; i++)
                for (int j = 0; j < ySizeOfMatr+2; j++)
                    result[i, j] = new ModifiersKnot();
            xSizeOfMatr = xSizeOfMatr - 2;
            ySizeOfMatr = ySizeOfMatr - 2;

            float stepX = room.FindMaxDeltaX() / xSizeOfMatr;
            float stepY = room.FindMaxDeltaY() / ySizeOfMatr;
            float b=0;
            float temp;
            float koef;
            float x0, y0;
            float xEnd, yEnd;
            float d = 0.02f;

            for (int i = 0; i < sourses.Count; i++)
                for (int j = 0; j < RaysCount; j++)
                {
                  //  j = 36;
                    vect = new Vector((float)Math.Cos(2 * Math.PI * (float)j / (float)RaysCount),
                                      (float)Math.Sin(2 * Math.PI * (float)j / (float)RaysCount), sourses[i].Coords);
                    wave = new Wave(vect);
                    wave.speed = 331.2f;
                    wave.waveMod.soundSpeed = 331.2f;
                    wayOfWave = CreateWave(wave, polygons, room, minAmplitude, 0, reflCount);
                    r.Add(wayOfWave);

                    //result = GetResultMatrix(wayOfWave, minAmplitude, xSizeOfMatr, xSizeOfMatr);
                    /* for (int k = 0; k < wayOfWave.Count; k++)
                    {

                        x0 = (wayOfWave[k].direct.nullP.x / stepX);
                        y0 = (wayOfWave[k].direct.nullP.y / stepY);
                        xEnd = (wayOfWave[k].end.x / stepX);
                        yEnd = (wayOfWave[k].end.y / stepY);

                        if (!(xEnd < x0 + 0.0001 && xEnd > x0 - 0.0001))
                        {
                            koef = (yEnd - y0) / (xEnd - x0);
                            b = y0 - koef * x0;
                            if (x0 > xEnd)
                            {
                                temp = x0;
                                x0 = xEnd;
                                xEnd = temp;
                            }
                            for (float a = x0; a < xEnd; a = a + 1)
                            {
                                wayOfWave[k].waveMod.SetAmp((float)wayOfWave[k].previousDist + Math.Abs(a * stepX - wayOfWave[k].direct.nullP.x));
                                wayOfWave[k].SetDelay(Math.Abs(wayOfWave[k].previousDist + Math.Abs(a * stepX - wayOfWave[k].direct.nullP.x)));
                                result[(int)a, (int)(a * koef + b)].AddModifier(wayOfWave[k].waveMod);
                            }
                        }
                        else
                        {
                            if (y0 > xEnd)
                            {
                                temp = y0;
                                y0 = yEnd;
                                yEnd = temp;
                            }
                            for (float a = y0; a < yEnd; a = a + 1)
                            {
                                wayOfWave[k].waveMod.SetAmp(wayOfWave[k].previousDist + Math.Abs(a * stepY - wayOfWave[k].direct.nullP.y));
                                wayOfWave[k].SetDelay(Math.Abs(wayOfWave[k].previousDist + Math.Abs(a * stepY - wayOfWave[k].direct.nullP.y)));
                                result[(int)x0, (int)a].AddModifier(wayOfWave[k].waveMod);
                            }
                        }
                    }*/
                }

            return /*result*/ r;
        }
예제 #3
0
파일: Phisics.cs 프로젝트: zurk/KIProgect
        /* static ModifiersKnot[,] GetResultMatrix(List<BTreeNode<Wave>> wayOfWave, float minAmplitude, int xSizeOfMatr, int xSizeOfMatr)
        {

        }*/
        static BTreeNode<Wave> CreateWave(Wave prevWave, List<Polygon> polygons, Polygon room, float minAmplitude, int iteration, int maxIter)
        {
            if (prevWave == null || iteration> maxIter || prevWave.waveMod.AmpMod[0].Amplitude< minAmplitude)
                return null;

            BTreeNode<Wave> result = new BTreeNode<Wave>();
            BTreeNode<Wave> nextT;
            Wave nextReflWave = new Wave();
            Wave nextRefrWave = new Wave();
            FindNextWaves(prevWave,polygons,room, out nextReflWave, out nextRefrWave);
            result.Value = prevWave;
            if (nextReflWave != null)
            {
                nextT = new BTreeNode<Wave>();
                nextT = CreateWave(nextReflWave, polygons, room, minAmplitude, iteration + 1, maxIter);
                if (nextT != null)
                {
                    nextT.Value = nextReflWave;
                    result.L = nextT;
                }
            }
            if (nextRefrWave != null)
            {
                nextT = new BTreeNode<Wave>();
                nextT = CreateWave(nextRefrWave, polygons, room, minAmplitude, iteration + 1, maxIter);
                if (nextT != null)
                {
                    nextT.Value = nextRefrWave;
                    result.R = nextT;
                }
            }
            return result;
        }
예제 #4
0
파일: Form1.cs 프로젝트: zurk/KIProgect
        private void DrawWave(object sender, PaintEventArgs e, Wave A, float scale, Pen p)
        {
            if (A.end.x != 0 || A.end.y != 0)
                try
                {

                    e.Graphics.DrawLine(p, scale * A.direct.nullP.x + dx, scale * A.direct.nullP.y + dy,
                                                  scale * A.end.x + dx, scale * A.end.y + dy);
                }
                catch { }
        }