/* shallow.cc */
/* #cxe- Sat Apr 27 21:11:32 PDT 2002 */
/* This is the function that looks at each line and checks to see if its */
/* endpoints share edges with 2 triangles. If so, the angles of the */
/* triangles are checked against each other. If the angle is "shallow" as */
/* supplied by the given angle (15 degrees is a good number BTW) then the */
/* line shouldn't be included in subsequent HLR activity. The exception */
/* to this is if the line is critical in defining the outline of a form. */
/* This occurs at the edge of a group of tri/lines. For example, an */
/* approximated circle could have many faces separated by lines that */
/* change only slightly as they progress around the circle. The only ones */
/* that need to be rendered are the ones at the extreme widths of the */
/* cylinder with respect to the viewer. */


#include "vmaster.h"
const bool TESTOUT = 0;

Llist * shallowanglecull(Llist *allL, Tlist *allT, float ang, char *hids)
{
/* Start main loops */
Llist *indexL=allL, *previousL=NULL;
while (indexL) {  /* process every line */

  if (TESTOUT) cout << "#-----checking for shallow line "
   << indexL->querypnumA() << "-"
   << indexL->querypnumB() << "--------------------" << endl;

  Tlist *indexT=allT, *T1=NULL, *T2=NULL;
  bool found=0, toomanyfound=0;
  Vector C,D; /* Other points of a matching set */
  while (indexT) {   /* for each line, look at every tri */
/*=============================================*/
 
/* Check for a tri with indexL's points.... */
/* ----------------------------------------- */
Vector other;
if ( /* A->B or B->A = T(A->B) */
( ( indexL->querypointA() == indexT->querypointA() ) &&
         ( indexL->querypointB() == indexT->querypointB() ) ) ||
( ( indexL->querypointB() == indexT->querypointA() ) &&
         ( indexL->querypointA() == indexT->querypointB() ) )
) { other=indexT->querypointC(); found =1;
    if (TESTOUT) cout << "# Coincident tri found - other C"<< endl;}

else if ( /* A->B or B->A = T(A->C) */
( ( indexL->querypointA() == indexT->querypointA() ) &&
         ( indexL->querypointB() == indexT->querypointC() ) ) ||
( ( indexL->querypointB() == indexT->querypointA() ) &&
         ( indexL->querypointA() == indexT->querypointC() ) )
) { other=indexT->querypointB(); found =1;
    if (TESTOUT) cout << "# Coincident tri found - other B"<< endl;}

else if ( /* A->B or B->A = T(B->C) */
( ( indexL->querypointA() == indexT->querypointB() ) &&
         ( indexL->querypointB() == indexT->querypointC() ) ) ||
( ( indexL->querypointB() == indexT->querypointB() ) &&
         ( indexL->querypointA() == indexT->querypointC() ) ) 
) { other=indexT->querypointA(); found =1;
    if (TESTOUT) cout << "# Coincident tri found - other A"<< endl;}


if (found)
{ found=0; /* reset this for the next time through */

/* Is this 1st tri that uses indexL's points? */
/* ----------------------------------------- */
if (!T1) {T1=indexT; C=other;}

/* Is this a 2nd tri that uses indexL's points? */
/* --------------------------------------------- */
else if (!T2) {T2=indexT; D=other;}

/* Is this a third tri that uses indexL's points? */
/* ----------------------------------------------- */
else { indexT = NULL; toomanyfound=1; break; }

} /* end if check for tri with indexL's points */

if (indexT) indexT = indexT->querylink(); 
} /* end while through every tri (for each line) */
/*==============================================*/

if (!toomanyfound && T1 && T2) {
if (TESTOUT) cout << "# Found exactly 2 tris coincident" << endl; 
/* Is the angle between these two tris' normals < ang? */
/* ------------------------------------------ */
Vector N1, N2; /* Normals */
N1 = (T1->querypointA() - T1->querypointB()) &
     (T1->querypointC() - T1->querypointB());
N2 = (T2->querypointA() - T2->querypointB()) &
     (T2->querypointC() - T2->querypointB());
if (TESTOUT) cout << "# Angle between tris:"
                  << N1.gg_angle(N2) << " > arg:"<< ang << endl;
if ( N1.gg_angle(N2) < ang ) 
{
/* Are the two tri's points which are not on the line */
/* on different sides of it? */
/* -------------------------------------------------- */
float Ax_Bx = indexL->querypointA().gg_valX() -
              indexL->querypointB().gg_valX(),
      Ay_By = indexL->querypointA().gg_valY() -
              indexL->querypointB().gg_valY(),
      Cx_Bx = C.gg_valX() - indexL->querypointB().gg_valX(),
      Cy_By = C.gg_valY() - indexL->querypointB().gg_valY(),
      Dx_Bx = D.gg_valX() - indexL->querypointB().gg_valX(),
      Dy_By = D.gg_valY() - indexL->querypointB().gg_valY();
if (TESTOUT)
      cout << "# Side check:" << ( ((Ax_Bx*Cy_By)-(Ay_By*Cx_Bx)) > 0 ) 
           << " XOR " << !( ((Ax_Bx*Dy_By)-(Ay_By*Dx_Bx)) > 0 ) << endl; 

bool m=  ( ((Ax_Bx*Cy_By)-(Ay_By*Cx_Bx)) > 0 ), 
     n= !( ((Ax_Bx*Dy_By)-(Ay_By*Dx_Bx)) > 0 ); 
/* if one is and one isn't on a particular side */
if ( (m||!n) && (!m||n) ) /* XOR */
{
/* If this point is reached, then delete the line */
/* ---------------------------------------------- */

if (TESTOUT) {cout << "# Deleting shallow line" << endl; }
/* Draw it in a different color before deleting if hidscolor is on */
if ( strcmp(hids,"off") && indexL ){
   cout << "p c " << hids << endl;
   cout << indexL << endl;
   cout << "p c white" << endl;}

        /* COMPLETELY REMOVE LINE FROM Llist */
   //if (previousL) /* if not top of the stack (something points here) */
   if (indexL!=allL) /* if not top of the stack (something points here) */
    {if (indexL) previousL->setlink( indexL->querylink() );
     delete indexL;  /* Previous gets set to index anyway soon */
     indexL = previousL; } /* Previous is still the same! */
   else /* deleting the first node - top of stack */
    { if (indexL) indexL= indexL->querylink();
     delete allL;
     allL=indexL;   } /* end delete line node */

} /* end check for other points on same side of line */
} /* end if shallow angles */
} /* end if this is a candidate for shallow angle cull */

previousL = indexL;
if (indexL) indexL = indexL->querylink(); 
} /* end while through every line */

return allL;}

