gt: 	for(int i=0; i<vertices.length; i++){
context: /*---
  
      iGeo - http://igeo.jp
  
      Copyright (c) 2002-2013 Satoru Sugihara
  
      This file is part of iGeo.
  
      iGeo is free software: you can redistribute it and/or modify
      it under the terms of the GNU Lesser General Public License as
      published by the Free Software Foundation, version 3.
  
      iGeo is distributed in the hope that it will be useful,
      but WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      GNU Lesser General Public License for more details.
  
      You should have received a copy of the GNU Lesser General Public
      License along with iGeo.  If not, see <http://www.gnu.org/licenses/>.
  
  ---*/
  
  package igeo;
  
  import java.util.ArrayList;
  import java.awt.Color;
  
  /**
     Class of a face of polygon mesh.
     
     @author Satoru Sugihara
  */
  public class IFace{
      public IVertex[] vertices;
      public IEdge[] edges;
      public IVec normal;
      
      /** used in deleting process */
      public boolean deleted=false;
      
      public boolean invalid=false; // in case init fails due to unmatching edge, vertex etc
      
      public IColor clr; // face color
      
      public IFace(IEdge[] e){ init(e); }
      public IFace(IEdge e1, IEdge e2, IEdge e3){ this(new IEdge[]{e1, e2, e3}); }
      public IFace(IEdge e1, IEdge e2, IEdge e3, IEdge e4){ this(new IEdge[]{e1, e2, e3, e4}); }
      
      public IFace(IVertex[] v){
  	int num = v.length;
  	vertices = v;
  	edges = new IEdge[num];
  	for(int i=0; i<num; i++){
  	    edges[i] = new IEdge(v[i],v[(i+1)%num]);
  	    vertices[i].addFace(this);
  	    edges[i].addFace(this);
  	}
      }
      
      public IFace(IVertex v1, IVertex v2, IVertex v3){ this(new IVertex[]{v1,v2,v3}); }
      public IFace(IVertex v1, IVertex v2, IVertex v3, IVertex v4){ this(new IVertex[]{v1,v2,v3,v4}); }
      
      /**
         Copis a face but shareing same vertices and edges with the original
      */
      public IFace(IFace f){
  	vertices = new IVertex[f.vertices.length];
  	for(int i=0; i<vertices.length; i++) vertices[i]=f.vertices[i];
  	edges = new IEdge[f.edges.length];
  	for(int i=0; i<edges.length; i++) edges[i]=f.edges[i];
  	if(f.normal!=null) normal = f.normal.dup();
      }
  
      public boolean isValid(){
  	if(invalid) return false;
  	if(vertices==null || edges==null) return false;
  	for(int i=0; i<vertices.length; i++){
  	    if(vertices[i]==null) return false;
  	}
  	for(int i=0; i<edges.length; i++){
  	    if(edges[i]==null) return false;
  	}
  	return true;
      }
      
      public void init(IEdge[] e){
  	int num = e.length;
  	
  	vertices = new IVertex[num];
  	edges = new IEdge[num];
  	
  	for(int i=0; i<num; i++) edges[i] = e[i];
  	
  	if(edges[1].contains(edges[0].vertices[0])) vertices[0]=edges[0].vertices[1];
  	else if(edges[1].contains(edges[0].vertices[1])) vertices[0]=edges[0].vertices[0];
  	else{
  	    invalid=true;
  	    IOut.err("first&second edges don't match");
  	    IOut.err("edges[0] = "+edges[0].vertices[0].pos+", "+edges[0].vertices[1].pos); //
  	    IOut.err("edges[1] = "+edges[1].vertices[0].pos+", "+edges[1].vertices[1].pos); //
  	}
  	
  	for(int i=1; i<num; i++){
  	    if(edges[i-1].contains(vertices[i-1]))
  		vertices[i]=edges[i-1].getOtherVertex(vertices[i-1]);
  	    else{
  		invalid=true;
  		IOut.err((i-1)+"&"+i+" edges don't match");
  		//IOut.err("vertex["+(i-1)+"] =" + vertices[i-1]); //
  		//IOut.err("edges["+(i-1)+"] = "+edges[i-1].vertices[0]+", "+edges[i-1].vertices[1]); //
  	    }
  	}
  	
  	if(edges[num-1].getOtherVertex(vertices[num-1]) != vertices[0]){
  	    invalid=true;
  	    IOut.err("first&last vertex doesn't match");
  	    //new ICurve(edges[num-1]).clr(1.0,0,0).weight(5); //
  	    //new IPoint(vertices[0]).clr(1.0,0,0).size(6); //
  	    //new ISurface(vertices[0],vertices[1],vertices[2]).clr(1.0,0,0); //
  	}
  
  	if(invalid) return; // exit in case of error
  	
  	for(int i=0; i<num; i++){
  	    vertices[i].addFace(this);
  	    edges[i].addFace(this);
  	}
      }
      
      
      public IFace dup(){ return new IFace(this); }
      
      
      /*
      public IFace dup(){ // duplicate vertices, edges  
  	int num = vertices.length;
  	IVertex v[] = new IVertex[num];
  	for(int i=0; i<num; i++) v[i] = vertices[i].dup();
  	
  	IEdge e[] = new IEdge[num];
  	for(int i=0; i<num; i++) e[i] = new IEdge(v[i],v[(i+1)%num]);
  	
  	IFace f = new IFace(e);
  	f.normal = normal;
  	return f;
      }
      */
      
      
      public IVertex getVertex(int i){ return vertex(i); }
      public IVertex vertex(int i){ return vertices[i]; }
      public IEdge getEdge(int i){ return edge(i); }
      public IEdge edge(int i){ return edges[i]; }
      
      public int vertexNum(){ return vertices.length; }
      public int edgeNum(){ return edges.length; }
      
      public IEdge getEdge(IVertex v1, IVertex v2){
  	for(int i=0; i<edges.length; i++){
  	    if( edges[i].vertices[0]==v1 && edges[i].vertices[1]==v2 ||
  		edges[i].vertices[0]==v2 && edges[i].vertices[1]==v1 ){
  		return edges[i];
  	    }
  	}
  	return null;
      }
      
      /** returns edges which aren't a link between any two of given vertex variable vtx. matching only one is fine to be returned. */
      public /*ArrayList<IEdge>*/ IEdge[] getOtherEdges(IVertex v1, IVertex v2, IVertex... otherVtx){
  	IVertex[] vtx = new IVertex[otherVtx.length+2];
  	vtx[0] = v1;
  	vtx[1] = v2;	
  	for(int i=0; i<otherVtx.length; i++) vtx[i+1] = otherVtx[i+2];
  	
  	ArrayList<IEdge> otherEdges = new ArrayList<IEdge>();
  	for(int i=0; i<edges.length; i++){
  	    boolean matchAny=false;
  	    for(int j=0; j<vtx.length&&!matchAny; j++){
  		if(edges[i].vertices[0]==vtx[j]) matchAny=true;
  
  	    }
  	    if(!matchAny){ otherEdges.add(edges[i]); }
  	    else{
  		matchAny=false;
  		for(int j=0; j<vtx.length&&!matchAny; j++){
  		    if(edges[i].vertices[1]==vtx[j]) matchAny=true;
  		}
  		if(!matchAny){ otherEdges.add(edges[i]); }
  	    }
  	}
  	//return otherEdges;
  	return otherEdges.toArray(new IEdge[otherEdges.size()]);
      }
      
      
      public IEdge[] getOtherEdges(IVertex v){
  	ArrayList<IEdge> otherEdges = new ArrayList<IEdge>();
  	for(int i=0; i<edges.length; i++){
  	    if(!edges[i].contains(v)) otherEdges.add(edges[i]);
  	}
  	return otherEdges.toArray(new IEdge[otherEdges.size()]);
      }
      
      public IEdge getOtherEdge(IVertex v){
  	for(int i=0; i<edges.length; i++){
  	    if(!edges[i].contains(v)) return edges[i];
  	}
  	return null;
      }
      
      public IEdge[] getOtherEdges(IEdge e){
  	ArrayList<IEdge> otherEdges = new ArrayList<IEdge>();
  	for(int i=0; i<edges.length; i++){
  	    if(edges[i]!=e && !edges[i].eq(e)) otherEdges.add(edges[i]);
  	}
  	return otherEdges.toArray(new IEdge[otherEdges.size()]);
      }
      
      public IEdge getOtherEdge(IEdge e){
  	for(int i=0; i<edges.length; i++){ if(edges[i]!=e) return edges[i]; }
  	return null;
      }
      
      public IVertex getOtherVertex(IVertex v1, IVertex v2){
  	for(int i=0; i<vertices.length; i++){
  	    if( (vertices[i] != v1) && (vertices[i] != v2) ) return vertices[i];
  	}
  	return null;
      }
      
      public IVertex getOtherVertex(IEdge e){
  