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
}
}