#include "Matrix.H"
#include "Solid.H"

Solid::Solid(const Matrix& pts, const Matrix& norms, int init)
   :vertices(pts), normals(norms), faces(sizeof(SolidFace *), init)
{
     num_faces = 0;
}

Solid::Solid(const Solid& s)
   :vertices(s.vertices), normals(s.normals),
	faces(sizeof(SolidFace *), s.NumFaces()) 
{
     int i;

     for (i=0; i < s.NumFaces(); i++) {
	  SolidFace *newface = new SolidFace(*s.Face(i));
	  faces += (char *) &newface;
     }

     num_faces = s.num_faces;
}

Solid::~Solid()
{
     int i;

     for (i=0; i < faces.High(); i++)
	  delete Face(i);
}

Solid& Solid::operator=(const Solid& s)
{
     int i;

     vertices = s.vertices;
     normals = s.normals;

     /* Clean up the faces */
     for (i=NumFaces()-1; i >= 0; i--) {
	  delete Face(i);
	  faces.Delete(i);
     }

     for (i=0; i < s.NumFaces(); i++) {
	  SolidFace *p = new SolidFace(*s.Face(i));
	  faces += (char *) &p;
     }

     num_faces = s.num_faces;

     return *this;
}

void Solid::AddFace(const SolidFace& face)
{
     SolidFace *newface = new SolidFace(face);

     faces += (char *) &newface;
     num_faces += 1;
}

Solid operator*(const Solid& s1, const CTM& ctm)
{
     Solid s2(s1);

     s2.Vertices() = s2.Vertices() * ctm.Points();
     s2.Normals() = s2.Normals() * ctm.Vectors();
     return s2;
}

Solid operator*(const Solid& s1, const Matrix& m)
{
     Solid s2(s1);

     s2.Vertices() = s2.Vertices() * m;
     return s2;
}

Solid operator+(const Solid& s1, const Solid& s2)
{
     Solid temp(s2);
     Solid sum(s1.vertices & temp.vertices, s1.normals & temp.normals);
     SolidFace *face;
     int i, j;

     for (i = 0; i < s1.NumFaces(); i++)
	  sum.AddFace(*s1.Face(i));
     for (i = 0; i < temp.NumFaces(); i++) {
	  face = temp.Face(i);
	  
	  for (j = 0; j < face->NumVerts(); j++)
	       face->VIndxs()[j] += s1.Vertices().Rows();
	  for (j = 0; j < face->NumNorms(); j++)
	       face->NIndxs()[j] += s1.Normals().Rows();

     	  sum.AddFace(*face);
     }

     return(sum);
}

void Solid::Print() const
{
     int i, j;
     
     printf("Vertices:\n");
     vertices.Print();
     printf("Normals:\n");
     normals.Print();

     for (i = 0; i < num_faces; i++) {
	  printf("Face %d, verts %d, norms %d:", i, Face(i)->NumVerts(),
		 Face(i)->NumNorms());
	  for (j = 0; j < Face(i)->NumVerts(); j++)
	       printf(" %d", Face(i)->VIndxs()[j]);
	  printf(",");

	  for (j = 0; j < Face(i)->NumNorms(); j++)
	       printf(" %d", Face(i)->NIndxs()[j]);
	  printf("\n");
     }
}
