// File:	CSLib_Class2d.cxx
// Created:	Wed Mar  8 15:06:24 1995
// Author:	Laurent BUCHARD
//		<lbr@mastox>

#define No_Standard_OutOfRange

#include <CSLib_Class2d.ixx>


static inline Standard_Real Transform2d(const Standard_Real u,const Standard_Real umin,const Standard_Real umaxmumin) { 
  if(umaxmumin>1e-10) { 
    Standard_Real U = (u-umin)/umaxmumin;
    return(U);
  }
  else { 
    return(u);
  }
}


CSLib_Class2d::CSLib_Class2d(const TColgp_Array1OfPnt2d& TP2d,
					       const Standard_Real aTolu,
					       const Standard_Real aTolv,
					       const Standard_Real umin,
					       const Standard_Real vmin,
					       const Standard_Real umax,
					       const Standard_Real vmax) {
  Umin=umin;
  Vmin=vmin;
  Umax=umax;
  Vmax=vmax;

  if(umax<=umin || vmax<=vmin) { 
    MyPnts2dX=MyPnts2dY=NULL;
    N=0;
    return;
  }

  Standard_Integer l = TP2d.Length();
  N = l;
  Tolu = aTolu;
  Tolv = aTolv;
  MyPnts2dX = new Standard_Real [N+1];
  MyPnts2dY = new Standard_Real [N+1];
  Standard_Real du=umax-umin;
  Standard_Real dv=vmax-vmin;
  Standard_Real *Pnts2dX = (Standard_Real *)MyPnts2dX;
  Standard_Real *Pnts2dY = (Standard_Real *)MyPnts2dY;
  for(Standard_Integer i = 0; i<l; i++) { 
    Pnts2dX[i] = Transform2d(TP2d(i+TP2d.Lower()).X(),umin,du);
    Pnts2dY[i] = Transform2d(TP2d(i+TP2d.Lower()).Y(),vmin,dv);
  }
  Pnts2dX[l] = Transform2d(TP2d(TP2d.Lower()).X(),umin,du);
  Pnts2dY[l] = Transform2d(TP2d(TP2d.Lower()).Y(),vmin,dv);
  if(du>1e-10) Tolu/=du;
  if(dv>1e-10) Tolv/=dv;
}



void CSLib_Class2d::Destroy() { 
  if(MyPnts2dX) { 
//  Standard_Real *Pnts2dX = (Standard_Real *)MyPnts2dX;
    delete [] MyPnts2dX;
    MyPnts2dX=NULL;
  }
  if(MyPnts2dY) { 
//  Standard_Real *Pnts2dY = (Standard_Real *)MyPnts2dY;
    delete [] MyPnts2dY;
    MyPnts2dY=NULL;
  }
}

//-- Attention   Tableau de 0 ------> N + 1 
//--                        P1 ..... Pn P1
//--
//--     1  2  3
//--     4  0  5
//--     6  7  8
//-- 


Standard_Integer CSLib_Class2d::SiDans(const gp_Pnt2d& P) const { 
  if(N==0) return(0);
  
  Standard_Real x,y;
  x = P.X(); y = P.Y();

  Standard_Real aTolu=Tolu*(Umax-Umin);
  Standard_Real aTolv=Tolv*(Vmax-Vmin);
  if(Umin<Umax && Vmin<Vmax)
    {
      // modified by NIZHNY-OFV  Thu May 31 14:23:33 2001
      if( ( x<(Umin-aTolu) ) || ( x>(Umax+aTolu) ) || ( y<(Vmin-aTolv) ) || ( y>(Vmax+aTolv) ) ) return (-1);
      x=Transform2d(x,Umin,Umax-Umin);
      y=Transform2d(y,Vmin,Vmax-Vmin);
    }


  Standard_Integer res = InternalSiDansOuOn(x,y);
  if(res==-1) { 
    //-- on est peut etre ON 
    return(0);
  }
  if(Tolu || Tolv) {
    if(res != InternalSiDans(x-Tolu,y-Tolv)) return(0);
    if(res != InternalSiDans(x+Tolu,y-Tolv)) return(0);
    if(res != InternalSiDans(x-Tolu,y+Tolv)) return(0);
    if(res != InternalSiDans(x+Tolu,y+Tolv)) return(0); 
  }
  return((res)? 1: -1);
}

Standard_Integer CSLib_Class2d::SiDans_OnMode(const gp_Pnt2d& P,
						       const Standard_Real Tol) const { 
  if(N==0) return(0);
  
  Standard_Real x,y;
  x = P.X(); y = P.Y();

  Standard_Real aTolu=Tol; //-- Tolu*(Umax-Umin);
  Standard_Real aTolv=Tol; //-- Tolv*(Vmax-Vmin);

  //-- ****** A FAIRE PLUS TARD, ESTIMER EN CHAQUE POINT la Tol2d en fct de la Tol3d *****

  if(Umin<Umax && Vmin<Vmax) { 
    if(x<(Umin-aTolu) || (x>Umax+aTolu) || (y<Vmin-aTolv) || (y>Vmax+aTolv)) 
      return(-1);
    
    x=Transform2d(x,Umin,Umax-Umin);
    y=Transform2d(y,Vmin,Vmax-Vmin);
  }


  Standard_Integer res = InternalSiDansOuOn(x,y);
  //-- if(res==-1) { 
        //-- on est peut etre ON 
  //--  return(0);
  //-- }
  if(aTolu || aTolv) {
    if(res != InternalSiDans(x-aTolu,y-aTolv)) return(0);
    if(res != InternalSiDans(x+aTolu,y-aTolv)) return(0);
    if(res != InternalSiDans(x-aTolu,y+aTolv)) return(0);
    if(res != InternalSiDans(x+aTolu,y+aTolv)) return(0); 
  }
  return((res)? 1: -1);
}


Standard_Integer CSLib_Class2d::InternalSiDans(const Standard_Real Px,const Standard_Real Py) const { 
  Standard_Integer nbc = 0;
  Standard_Integer i   = 0;
  Standard_Integer ip1 = 1;
  Standard_Real *Pnts2dX = (Standard_Real *)MyPnts2dX;
  Standard_Real *Pnts2dY = (Standard_Real *)MyPnts2dY;
  Standard_Real    x   = (Pnts2dX[i]-Px);
  Standard_Real    y   = (Pnts2dY[i]-Py);
  Standard_Integer SH  = (y<0.0)? -1 : 1;
  Standard_Integer NH;
  Standard_Real    nx,ny;
  for(i=0; i<N ; i++,ip1++) { 
    nx = Pnts2dX[ip1] - Px;
    ny = Pnts2dY[ip1] - Py;
    
    NH = (ny<0.0)? -1 : 1;
    if(NH!=SH) { 
      if(x>0.0 && nx>0.0) nbc++;
      else { 
	if(x>0.0 || nx>0.0) { 
	  if((x-y*(nx-x)/(ny-y))>0.0) nbc++;
	}
      }
      SH = NH;
    }
    x = nx; y = ny;
  }
  return(nbc&1);
}


//--
//-- meme code que ci-dessus + test sur ON (return(-1) dans ce cas 
//--
Standard_Integer CSLib_Class2d::InternalSiDansOuOn(const Standard_Real Px,const Standard_Real Py) const { 
  Standard_Integer nbc = 0;
  Standard_Integer i   = 0;
  Standard_Integer ip1 = 1;
  Standard_Real *Pnts2dX = (Standard_Real *)MyPnts2dX;
  Standard_Real *Pnts2dY = (Standard_Real *)MyPnts2dY;
  Standard_Real    x   = (Pnts2dX[i]-Px);
  Standard_Real    y   = (Pnts2dY[i]-Py);
  Standard_Integer SH  = (y<0.0)? -1 : 1;
  Standard_Integer NH;
  Standard_Real    nx,ny;
  for(i=0; i<N ; i++,ip1++) { 
    nx = Pnts2dX[ip1] - Px;
    ny = Pnts2dY[ip1] - Py;
    //--
    //-- le 14 oct 97 
    if(nx<Tolu && nx>-Tolu && ny<Tolv && ny>-Tolv) { 
      //-- cout<<" BRTA_FClass2d -> In "<<endl;
      return(-1);
    }
    //--
    
    NH = (ny<0.0)? -1 : 1;
    if(NH!=SH) { 
      if(x>0.0 && nx>0.0) nbc++;
      else { 
	if(x>0.0 || nx>0.0) { 
	  if((x-y*(nx-x)/(ny-y))>0.0) nbc++;
	}
      }
      SH = NH;
    }
    x = nx; y = ny;
  }
  return(nbc&1);
}

#include <Standard_ConstructionError.hxx>


const CSLib_Class2d &  CSLib_Class2d::Copy(const CSLib_Class2d& Other) const { 
  cerr<<"Copy not allowed in CSLib_Class2d"<<endl;
  Standard_ConstructionError::Raise();
  return(*this);
}

