#ifndef FILE_POLYHEDRA
#define FILE_POLYHEDRA


/**************************************************************************/
/* File:   polyhedra.hh                                                   */
/* Author: Joachim Schoeberl                                              */
/* Date:   19. Mar. 2000                                                  */
/**************************************************************************/

namespace netgen
{

  /*

  Polyhedral primitive
  
  */

  class Polyhedra : public Primitive
  {
    class Face {
    public:
      int pnums[3];
      int planenr;

      int inputnr;

      Box<3> bbox;
      //    Point<3> center;
      Vec<3> v1, v2;   // edges
      Vec<3> w1, w2;   // pseudo-inverse
      Vec<3> n;        // normal to face
      Vec<3> nn;       // normed normal

      Face () { ; }
      Face (int pi1, int pi2, int pi3, 
	    const Array<Point<3> > & points,
	    int ainputnr);
    };

    Array<Point<3> > points;
    Array<Face> faces;
    Array<Plane*> planes;
    Box<3> poly_bbox;

    double eps_base1;

  public:
    Polyhedra ();
    virtual ~Polyhedra ();
    static Primitive * CreateDefault ();

    virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const;
    virtual INSOLID_TYPE PointInSolid (const Point<3> & p,
				       double eps) const;
    virtual INSOLID_TYPE VecInSolid (const Point<3> & p,
				     const Vec<3> & v,
				     double eps) const;

    // checks if lim s->0 lim t->0  p + t(v1 + s v2) in solid
    virtual INSOLID_TYPE VecInSolid2 (const Point<3> & p,
				      const Vec<3> & v1,
				      const Vec<3> & v2,
				      double eps) const;

    virtual void GetTangentialSurfaceIndices (const Point<3> & p, 
					      Array<int> & surfind, double eps) const;


    virtual void GetTangentialVecSurfaceIndices2 (const Point<3> & p, const Vec<3> & v1, const Vec<3> & v2,
						  Array<int> & surfind, double eps) const;

    virtual void CalcSpecialPoints (Array<Point<3> > & pts) const;
    virtual void AnalyzeSpecialPoint (const Point<3> & pt, 
				      Array<Point<3> > & specpts) const;
    virtual Vec<3> SpecialPointTangentialVector (const Point<3> & p, int s1, int s2) const;

    virtual int GetNSurfaces() const 
    { return planes.Size(); }
    virtual Surface & GetSurface (int i) 
    { return *planes[i]; }
    virtual const Surface & GetSurface (int i) const
    { return *planes[i]; }

    virtual void GetPrimitiveData (const char *& classname, Array<double> & coeffs) const;
    virtual void SetPrimitiveData (Array<double> & coeffs);

    virtual void Reduce (const BoxSphere<3> & box);
    virtual void UnReduce ();

    int AddPoint (const Point<3> & p);
    int AddFace (int pi1, int pi2, int pi3, int inputnum);

    void GetPolySurfs(Array < Array<int> * > & polysurfs);
  
  protected:
    int FaceBoxIntersection (int fnr, const BoxSphere<3> & box) const;
    //  void CalcData();
  };

}

#endif
