Canguro.Commands.View.Selection.SelectWindow C# (CSharp) Méthode

SelectWindow() private méthode

Método para determinar lo objetos que se encuentren dentro de la ventana. Para ello se obtienen primero los parámetros (normal n y punto en el plano s) de 4 planos correspondientes a las 4 aristas de la ventana. Estos pueden ser ortogonales o piramidales (perspectiva) según el tipo de proyección activo. Las esquinas se nombran como sigue: A----------B (fx1,fy1)-----------(fx2,fy1) | World | | Screen space | | Space | | | D----------C (fx1,fy2)-----------(fx2,fy2) Tomando las siguientes ecuaciones vectoriales: X = P + rQ (Ec. Recta) 0 = (X - S) . N (Ec. Plano) Se puede conocer la distancia entre un punto P y un plano si se crea una recta con base en P y dirección N y se interseca con el plano. La intersección de una recta y un plano es como sigue: 0 = (P + rQ - S) . N, y si la dirección de la recta es perpendicular al plano, tenemos que: Q = N lo que nos lleva a: r = (P - S) . N/|N| = (P.(N/|N|)) - (S.(N/|N|)) Si N es un vector unitario, entonces: N = N / |N| Por lo tanto: r = P.N - S.N y la distancia entre P y el plano es igual a r. P.N es la distancia desde el punto al origen, perpendicular al plano posX es P.N con N = la normal al plano BC posY es P.N con N = la normal al plano AB deltaX es la distancia entre los planos BC y DA deltaY es la distancia entre los planos AB y CD Si N apunta hacia afuera en los 4 planos mencionados arriba, entonces una r positiva corresponde a estar en la parte interna del plano (con respecto a la caja formada por los 4). Por lo tanto un punto con las 4 r's positivas será un punto dentro de dicha caja.
private SelectWindow ( Canguro activeView, int fx1, int fy1, int fx2, int fy2, List selectedItems, Controller selectionFilter ) : void
activeView Canguro La vista (ventana) activa
fx1 int
fy1 int
fx2 int
fy2 int
selectedItems List
selectionFilter Controller
Résultat void
        internal void SelectWindow(Canguro.View.GraphicView activeView, int fx1, int fy1, int fx2, int fy2, List<Canguro.Model.Item> selectedItems, Controller.SelectionFilter selectionFilter)
        {
            int idJ1, idJ2, idJ3, idJ4;
            Canguro.Model.Model model = Canguro.Model.Model.Instance;

            #region Get the selection Box Params
            Vector3 nAB, sAB, nBC, sBC, nCD, sCD, nDA, sDA;
            Vector3[] corners1, corners2;
            corners1 = new Vector3[4];
            corners2 = new Vector3[4];

            // Checar si el cuadro está vacío
            if (fx1 == fx2 && fy1 == fy2)
                return;

            // Obtener parámetros de los 4 planos
            getPlanes(activeView, fx1, fy1, fx2, fy2, out nAB, out sAB, out nBC, out sBC, out nCD, out sCD, out nDA, out sDA, ref corners1, ref corners2);

            // Calcular los parámetros que dependen únicamente de los planos
            // (Como sólo nos interesa el signo de r y no su magnitud real,
            // no es necesario calcular N.N)
            float snAB, snBC, snCD, snDA; // nnAB, nnBC, nnCD, nnDA;
            snAB = Vector3.Dot(sAB, nAB);
            snBC = Vector3.Dot(sBC, nBC);
            snCD = Vector3.Dot(sCD, nCD);
            snDA = Vector3.Dot(sDA, nDA);
            #endregion

            #region Displacements and Deformation factors
            float[,] displacements = null;
            float deformedScaleFactor = 0f;
            if (model.HasResults && model.Results.JointDisplacements != null)
            {
                displacements = model.Results.JointDisplacements;
                if (activeView.ModelRenderer.RenderOptions.ShowDeformed)
                {
                    deformedScaleFactor = model.Results.PaintScaleFactorTranslation;
                    if (activeView.ModelRenderer.RenderOptions.ShowAnimated)
                        deformedScaleFactor *= activeView.ModelRenderer.RenderOptions.DeformationScale;
                }
            }
            #endregion

            #region Joints select window/crossing (Cohen-Sutherland classification)
            Vector3 jPos;
            float posY, posX;
            float distY, distX;

            distY = (float)-(snCD + snAB);
            distX = (float)-(snBC + snDA);

            #region Array memory management
            // Array to qualify all the joints as in the Cohen Sutherland Algorithm
            // See http://www.cs.helsinki.fi/group/goa/viewing/leikkaus/lineClip.html for more info
            int jointCount = model.JointList.Count;
            int newBufferLength = jointPos.Length;
            if (newBufferLength != jointCount)
            {
                while (jointCount > newBufferLength)
                    newBufferLength *= 2;

                jointPos = new byte[newBufferLength];
                jointPosY = new float[newBufferLength];
                jointPosX = new float[newBufferLength];
            }
            #endregion

            // Determinar los Joints que se encuentren dentro de la caja, si es lo que se pide
            foreach (Canguro.Model.Joint j in model.JointList)
            {
                if (j != null)
                {
                    idJ1 = (int)j.Id;
                    jPos = getJointPos(j, displacements, deformedScaleFactor);
                    jointPosY[idJ1] = posY = Vector3.Dot(jPos, nAB);
                    jointPosX[idJ1] = posX = Vector3.Dot(jPos, nBC);

                    #region Cohen Sutherland classification
                    // Se divide la pantalla de la siguiente forma:
                    // 1001 | 1000 | 1010
                    // 0001 | 0000 | 0010
                    // 0101 | 0100 | 0110
                    //
                    // Si el puntoA OR puntoB == 0 está dentro
                    // Si el puntoA AND puntoB != 0 está fuera
                    // Si no se cumple ninguna de las anteriores, hay que checar la intersección para ver si está dentro
                    if (snAB <= posY)
                    {
                        if (snBC <= posX)
                        {
                            if (snCD <= (- posY)) // posCD
                            {
                                if (snDA <= (- posX)) // posDA
                                {
                                    // Está dentro --> seleccionar
                                    if (j.IsVisible && ((selectionFilter & Canguro.Controller.SelectionFilter.Joints) > 0))
                                    {
                                        if (selectedItems == null)
                                        {
                                            j.IsSelected = true;
                                            newlySelected = true;
                                        }
                                        else
                                            selectedItems.Add(j);
                                    }

                                    jointPos[idJ1] = 0x0;
                                }
                                else
                                    jointPos[idJ1] = 0x8;
                            }
                            else
                            {
                                if (snDA <= (- posX)) // posDA
                                    jointPos[idJ1] = 0x2;
                                else
                                    jointPos[idJ1] = 0xA;
                            }
                        }
                        else
                        {
                            if (snCD <= (- posY)) // posCD
                                jointPos[idJ1] = 0x4;
                            else
                                jointPos[idJ1] = 0x6;
                        }
                    }
                    else
                    {
                        if (snDA >= (- posX)) // posDA
                            jointPos[idJ1] = 0x9;
                        else if (snBC <= posX)
                            jointPos[idJ1] = 0x1;
                        else
                            jointPos[idJ1] = 0x5;
                    }
                    #endregion
                }
            }
            #endregion

            if (crossingSelectionOn || selectedItems != null)
            {
                #region Crossing Selection

                #region Lines crossing selection
                if ((selectionFilter & Canguro.Controller.SelectionFilter.Lines) > 0)
                {
                    // Selección de LineElements tipo Select Crossing
                    foreach (Canguro.Model.LineElement l in model.LineList)
                    {
                        if (l != null && l.IsVisible)
                        {
                            idJ1 = (int)l.I.Id;
                            idJ2 = (int)l.J.Id;
                            if ((jointPos[idJ1] & jointPos[idJ2]) == 0)
                            {
                                if (jointPos[idJ1] == 0 || jointPos[idJ2] == 0 || (jointPos[idJ1] == 0x1 && jointPos[idJ2] == 0x2) || (jointPos[idJ1] == 0x2 && jointPos[idJ2] == 0x1) || (jointPos[idJ1] == 0x8 && jointPos[idJ2] == 0x4) || (jointPos[idJ1] == 0x4 && jointPos[idJ2] == 0x8))
                                {
                                    if (selectedItems == null)
                                    {
                                        l.IsSelected = true;
                                        newlySelected = true;
                                    }
                                    else
                                        selectedItems.Add(l);
                                }
                                else
                                {
                                    // Check if line is inside
                                    float yL, yR;
                                    yL = (jointPosY[idJ1] - snAB) +
                                        ((snBC - jointPosX[idJ1]) / (jointPosX[idJ2] - jointPosX[idJ1])) * (jointPosY[idJ2] - jointPosY[idJ1]);
                                    yR = (jointPosY[idJ1] - snAB) +
                                        ((snDA + jointPosX[idJ1]) / (jointPosX[idJ1] - jointPosX[idJ2])) * (jointPosY[idJ2] - jointPosY[idJ1]);

                                    if ((yL >= 0 && yR <= distY) || (yL <= distY && yR >= 0))
                                    {
                                        if (selectedItems == null)
                                        {
                                            l.IsSelected = true;
                                            newlySelected = true;
                                        }
                                        else
                                            selectedItems.Add(l);
                                    }
                                }
                            }
                        }
                    }
                }
                #endregion

                #region Areas crossing selection
                if ((selectionFilter & Canguro.Controller.SelectionFilter.Areas) > 0)
                {
                    Vector3 cornersDir = Vector3.Normalize(corners2[0] - corners1[0]);

                    // Selección de AreaElements tipo Select Crossing
                    foreach (Canguro.Model.AreaElement a in model.AreaList)
                    {
                        if (a != null && a.IsVisible)
                        {
                            idJ1 = (int)a.J1.Id;
                            idJ2 = (int)a.J2.Id;
                            idJ3 = (int)a.J3.Id;
                            idJ4 = (int)a.J4.Id;

                            if ((jointPos[idJ1] & jointPos[idJ2] & jointPos[idJ3] & jointPos[idJ4]) == 0)
                            {
                                if (jointPos[idJ1] == 0 || jointPos[idJ2] == 0 || jointPos[idJ3] == 0 || jointPos[idJ4] == 0 ||
                                    ((jointPos[idJ1] | jointPos[idJ2]) == 0x3) || ((jointPos[idJ1] | jointPos[idJ3]) == 0x3) || ((jointPos[idJ1] | jointPos[idJ4]) == 0x3) || ((jointPos[idJ2] | jointPos[idJ3]) == 0x3) || ((jointPos[idJ2] | jointPos[idJ4]) == 0x3) || ((jointPos[idJ3] | jointPos[idJ4]) == 0x3) ||
                                    ((jointPos[idJ1] | jointPos[idJ2]) == 0xC) || ((jointPos[idJ1] | jointPos[idJ3]) == 0xC) || ((jointPos[idJ1] | jointPos[idJ4]) == 0xC) || ((jointPos[idJ2] | jointPos[idJ3]) == 0xC) || ((jointPos[idJ2] | jointPos[idJ4]) == 0xC) || ((jointPos[idJ3] | jointPos[idJ4]) == 0xC))
                                {
                                    if (selectedItems == null)
                                    {
                                        a.IsSelected = true;
                                        newlySelected = true;
                                    }
                                    else
                                        selectedItems.Add(a);
                                }
                                else
                                {
                                    // Check if area intersect selection box

                                    Vector3 p, u, v, w, rst;
                                    p = a.J1.Position;
                                    u = a.J2.Position - p;
                                    v = a.J3.Position - p;
                                    w = Vector3.Scale(cornersDir, -1f);

                                    bool cornerInside = isCornerInsideTriangle(ref p, ref u, ref v, ref w, ref corners1);
                                    if (!cornerInside && a.J4 != null)
                                    {
                                        u = a.J4.Position - p;
                                        cornerInside = isCornerInsideTriangle(ref p, ref u, ref v, ref w, ref corners1);
                                    }

                                    if (cornerInside)
                                    {
                                        if (selectedItems == null)
                                        {
                                            a.IsSelected = true;
                                            newlySelected = true;
                                        }
                                        else
                                            selectedItems.Add(a);
                                    }
                                }
                            }
                        }
                    }
                }
                #endregion
                #endregion
            }
            else
            {
                #region Window Selection
                // Line select window
                if ((selectionFilter & Canguro.Controller.SelectionFilter.Lines) > 0)
                {
                    // Selección de LineElements tipo Select Window
                    foreach (Canguro.Model.LineElement l in model.LineList)
                    {
                        if (l != null && l.IsVisible)
                        {
                            if (jointPos[(int)l.I.Id] + jointPos[(int)l.J.Id] == 0)
                            {
                                if (selectedItems == null)
                                {
                                    l.IsSelected = true;
                                    newlySelected = true;
                                }
                                else
                                    selectedItems.Add(l);
                            }
                        }
                    }
                }

                // Areas select window
                if ((selectionFilter & Canguro.Controller.SelectionFilter.Areas) > 0)
                {
                    // Selección de LineElements tipo Select Window
                    foreach (Canguro.Model.AreaElement a in model.AreaList)
                    {
                        if (a != null && a.IsVisible)
                        {
                            int sumJPos = jointPos[(int)a.J1.Id] + jointPos[(int)a.J2.Id] + jointPos[(int)a.J3.Id] + ((a.J4 != null) ? jointPos[(int)a.J4.Id] : (byte)0);
                            if (sumJPos == 0)
                            {
                                if (selectedItems == null)
                                {
                                    a.IsSelected = true;
                                    newlySelected = true;
                                }
                                else
                                    selectedItems.Add(a);
                            }
                        }
                    }
                }
                #endregion
            }
        }