// polypool.js - definition of the polypool class
// (c) 2000 Gareth Richards
// garethrichards@gersolutions.com

var ID_INDEX=0;
var MINZ_INDEX=1;
var COLOR_INDEX=2;
var DOM_OBJECT=3;
var LINE_COLOR=4;
var VCOUNT_INDEX=5;

function gpoint(xx,yy,zz){
	this.x=xx;
	this.y=yy;
	this.z=zz;
}

function polypool(){
	this.points=new Array();
	this.faces=new Array();
	this.domFaces=new Array();
	this.tpoints=new Array();
	this.sorted=new Array();
	this.minz=new Array();
	this.matrix=new Matrix3D();

	this.SV=4000;
	this.w=0;
	this.h=0;
	this.cx=0;
	this.cy=0;
	this.fill=true;
}

function findNode(nList,name){
	var i;
	for(i=0;i<nList.length;i++){
		if (nList.item(i).nodeName==name)
			return nList.item(i);
	}
}

function ApolypoolCreateObject(doc,scale){
// todo optimize
	var dscale=findNode(doc.documentElement.childNodes,"SCALE");
	scale=scale/dscale.text;		
	var dpoints=findNode(doc.documentElement.childNodes,"POINTS");
	this.matrix.scale(scale);
	var i,j,k,point,face,f;
	for (i=0; i<dpoints.childNodes.length; i++){
		point=dpoints.childNodes.item(i);
		// need some error checking
		x=point.childNodes.item(0).text;
		y=point.childNodes.item(1).text;
		z=point.childNodes.item(2).text;

		this.points[i]=new gpoint(x,y,z);
	}

	f=findNode(doc.documentElement.childNodes,"FACES");
	for (i=0; i<f.childNodes.length; i++){
		face=f.childNodes.item(i);
		// need some error checking
		this.faces[i]=new Array();
		tface=this.faces[i];
		tface[ID_INDEX]=i; // id
		tface[MINZ_INDEX]=0; // minz
		tface[COLOR_INDEX]="blue";
		tface[LINE_COLOR]="black";

		tface[VCOUNT_INDEX]=face.childNodes.length;
		for (j=0; j<face.childNodes.length; j++){
			tface[j+1+VCOUNT_INDEX]=face.childNodes.item(j).text;
		}
		for (k=0; k<face.attributes.length; k++){
			if (face.attributes.item(k).nodeName=="color")
				tface[COLOR_INDEX]=face.attributes.item(k).text;
			if (face.attributes.item(k).nodeName=="id")
				tface[ID_INDEX]=face.attributes.item(k).text;
		}
	}

	for (i=0;i<this.points.length;i++){
		this.tpoints[i]=new gpoint(0,0,0);
	}
}

function ATransformPoints(pa,ya,ra,tx,ty,tz){
	var m=this.matrix;
	m.yrot(pa);
	m.xrot(ya);
	m.transform(this.points,this.tpoints,this.points.length);
}

var gpolyfaces;

function sortfn(lhs,rhs){
	if (gpolyfaces[lhs][MINZ_INDEX]<gpolyfaces[rhs][MINZ_INDEX])
		return -1;
	else
		return 1;
}

function AzOrder(){
	var fa=this.faces;
	var s=this.sorted;
	var dnf=fa.length;
	var i;
	for (i=0;i<dnf;i++){
		s[i]=i;
	}
	var t=this.tpoints;
	var nv,f;
	for (i=0;i<dnf;i++){
		f=fa[i];
		f[MINZ_INDEX]=0;
		nv=f[VCOUNT_INDEX]+VCOUNT_INDEX;
		for (j=VCOUNT_INDEX+1;j<=nv;j++){
			f[MINZ_INDEX]+=t[f[j]].z;
		}
		f[MINZ_INDEX]/=nv;
	}

	gpolyfaces=this.faces;
	s.sort(sortfn);
}

//perspective transform
function AperspTransform(){
var i,k;
	var dnp=this.points.length;
	var s=this.SV;
	var ccx=this.cx;
	var ccy=this.cy;
	var tp=this.tpoints;
	for (i=0;i<dnp;i++){
		var p=tp[i]
		k=s-p.z;
		p.x=Math.floor(ccx+s*p.x/k);
		p.y=Math.floor(ccy-s*p.y/k);
	}
}

function Adraw(){
	this.zOrder();
	var dnf=this.faces.length;
	var dfa=this.domFaces;
	var tsorted=this.sorted;
	var fa=this.faces;
	var i,p,f;
	for(i=0;i<dnf;i++){
		s=tsorted[i];
		f=fa[s];		
		sp=this.makePath(f);
		p=dfa[i];
		f[DOM_OBJECT]=p;
		p.path=sp;
		p.fillcolor=f[COLOR_INDEX];
		p.fill.type="gradient";
		p.strokecolor=f[LINE_COLOR];
	}
}

//create a path for the v:shape for this face
function AmakePath(f){
var s="";
var nv,i;
	nv=f[VCOUNT_INDEX];
	var tp=this.tpoints;
	var vert=VCOUNT_INDEX+1;
	var p=tp[f[vert]];
	s="m "+p.x+","+p.y+" l ";
	for(i=1;i<nv;i++){
		vert++;
		p=tp[f[vert]];
		s+=p.x+","+p.y;
		if(i+1<nv)s+=",";
	}
	s+=" x e";
	return(s);
}

function AcreateDomObjects(p){
	var i;
	for(i=0;i<this.faces.length;i++){
		this.createShapeWithDom(p,i);
	}
}

function AcreateShapeWithDom(p,id){
  var l;

  l = document.createElement("v:shape");
  l.id=id;
  l.style.position="absolute";
  l.style.left=0;
  l.style.top=0;
  l.style.width=this.h;
  l.style.height=this.h;
  l.style.stroke=true;
  l.coordsize="1000,1000";
  l.coordorigin="0,0";
  l.strokecolor="#fd0000";
  l.path=this.makePath(this.faces[id]);
  p.insertBefore(l, null);
  this.domFaces[id]=l;
}

function Aerase(p){
	var i;
	for (i=0; i<this.faces.length; i++){
		p.removeChild(this.domFaces[i]);
	}
}

function AgetObject(oid){
	var i;
	for (i=0; i<this.faces.length; i++){
		if (this.faces[i][ID_INDEX]==oid){
			return this.faces[i][DOM_OBJECT];
		}
	}
}

function AsetColor(oid,color){
	var i;
	for (i=0; i<this.faces.length; i++){
		if (this.faces[i][ID_INDEX]==oid){
			this.faces[i][DOM_OBJECT].fillcolor=color;
			this.faces[i][COLOR_INDEX]=color;
		}
	}

}

function AsetBorder(oid,color,width){
	var i;
	for (i=0; i<this.faces.length; i++){
		if (this.faces[i][ID_INDEX]==oid){
			this.faces[i][DOM_OBJECT].strokecolor=color;
			this.faces[i][DOM_OBJECT].strokeweight=width;
			this.faces[i][LINE_COLOR]=color;
		}
	}

}

function AgetID(mid)
{
	if (this.sorted[mid]==null)
		return mid;
	var res=this.faces[this.sorted[mid]][ID_INDEX];
	if (res==null)
		return mid;
	else
		return res;
}

polypool.prototype.getObject=AgetObject;
polypool.prototype.transformPoints=ATransformPoints;
polypool.prototype.zOrder=AzOrder;
polypool.prototype.perspTransform=AperspTransform;
polypool.prototype.draw=Adraw;
polypool.prototype.makePath=AmakePath;
polypool.prototype.createShapeWithDom=AcreateShapeWithDom;
polypool.prototype.createDomObjects=AcreateDomObjects;
polypool.prototype.createObject=ApolypoolCreateObject;
polypool.prototype.erase=Aerase;
polypool.prototype.getId=AgetID;
polypool.prototype.setColor=AsetColor;
polypool.prototype.setBorder=AsetBorder;

