/*
 * Colorization.java
 *
 * Created on 16. Februar 2002, 14:29
 */

package cutnglue;

/**
 *
 * @author  Administrator
 * @version 
 */

import java.util.*;
import javax.vecmath.*;
import javax.media.j3d.*;

public class Colorization {

    /** The geometry whose vertex colors should be modified */
    //public IndexedGeometryArray iga;
    public IndexedTriangleArray iga;
    
    /** The priority-sorted links from the sewing pattern */
    TreeMap sortedLinks;
    
    /** Vector of color lists for each vertex
     * The lists contain one color per edge the vertex is part of
     */
    public Vector vertexColorLists = new Vector();
    
    int numWeights=0;
    
    /** Creates new Colorization */
    public Colorization(TreeMap sortedLinks, IndexedGeometryArray iga) {
        this.iga = (IndexedTriangleArray)iga;
        this.sortedLinks = sortedLinks;
        
        int vf = iga.getVertexFormat();
        String s = Integer.toBinaryString(vf>>1);
        boolean foundNormals = false;
        boolean foundColor3 = false;
        boolean foundColor4 = false;
        if ( s.endsWith("1")) {
            foundNormals = true;
            s = Integer.toBinaryString(vf>>2);
            if ( s.endsWith("1")) {
                foundColor3 = true;
                //s = s.substring(0, s.length()-1);
                s = Integer.toBinaryString(vf>>3);
                if ( s.endsWith("1")) foundColor4 = true;
            }
        }
        System.out.println("color3 : " + foundColor3);
        System.out.println("color4 : " + foundColor4);
        
        double min = ((Double)sortedLinks.firstKey()).doubleValue();
        double max = ((Double)sortedLinks.lastKey()).doubleValue();
        double range = max-min;
        System.out.println("min key : " + min);
        System.out.println("max key : " + max);
        System.out.println("range : " + range);
        
        numWeights = sortedLinks.size();
        System.out.println("numWeights : " + numWeights);
        double[] weights = new double[numWeights];
        
        IndexedTriangleArray ita;
        int vc = iga.getVertexCount();
        int ic = iga.getIndexCount();
        double[] coords = new double[vc*3];
        iga.getCoordinates(0,coords);
        int[] coordIndices = new int[ic];
        iga.getCoordinateIndices(0,coordIndices);
        //float[] colors = new float[numWeights*3];
        float[] colors = new float[vc*3];
        int[] colorIndices = new int[ic];
        for (int i=0;i<colors.length;i+=3) {
            colors[i]   = 1.f;
            colors[i+1] = 1.f;
            colors[i+2] = 0.f;
        }
        for (int i=0;i<colorIndices.length;++i) {
            colorIndices[i] = 0;
        }

        if (foundNormals) {
            ita = new IndexedTriangleArray(vc, IndexedTriangleArray.COORDINATES | IndexedTriangleArray.NORMALS | IndexedTriangleArray.COLOR_3 , ic);
            float[] normals = new float[vc*3];
            iga.getNormals(0,normals);
            ita.setNormals(0,normals);
            int[] nind = new int[ic];
            iga.getNormalIndices(0,nind);
            ita.setNormalIndices(0,nind);
        }
        else {
            ita = new IndexedTriangleArray(vc, IndexedTriangleArray.COORDINATES | IndexedTriangleArray.COLOR_3 , ic);
        }
        ita.setCoordinates(0,coords);
        ita.setCoordinateIndices(0,coordIndices);
        ita.setColors(0,colors); 
        ita.setColorIndices(0,colorIndices);
        
        
        int currentWeight = 0;
        Iterator it = sortedLinks.keySet().iterator();
        System.out.println("\nprinting sortedLinks...");
        while ( it.hasNext() ) {
            Object key = it.next();
            System.out.println("k"+currentWeight + " : " + ((Double)key).doubleValue());
            weights[currentWeight] = (((Double)key).doubleValue()-min) / range;
            System.out.println("w"+currentWeight + " : " + weights[currentWeight]);
            
            Color3f nc3 = new Color3f(1.f, 1.f-(float)weights[currentWeight], 0.f);
            System.out.println("Color " + currentWeight + " : " + nc3.toString());
            ita.setColor(currentWeight, nc3);
            // vector of links with equal priority
            Vector links = (Vector) sortedLinks.get(key);
            System.out.println("Vector for key " + key + " : " + "    size : " + links.size());
            
            for ( int j=0; j<links.size(); ++j ) {
                System.out.println("entry " + j + " : ");
                // indices of triangles i and j which are linked by an edge
                Triangle2D[] ij = (Triangle2D[])links.elementAt(j);
                System.out.println("tri0 : " + ij[0].toString());
                System.out.println("tri1 : " + ij[1].toString());
                
                // find indices of two vertices of connecting edge
                int v1 = -1;
                int v2 = -1;
                boolean v1found = false;
                int numTri1 = iga.getCoordinateIndex(ij[0].getNumber());
                int numTri2 = iga.getCoordinateIndex(ij[1].getNumber());
                System.out.println("numTri0 : " + numTri1 + "      numTri1 : " + numTri2);
                
                for ( int k=0 ; k<3; ++k ) {
                    for ( int l=0 ; l<3; ++l ) {
                        //System.out.println("#1: " + iga.getCoordinateIndex(ij[0].getNumber()*3 + k) + "    #2: " + iga.getCoordinateIndex(ij[1].getNumber()*3 + l));
                        if (iga.getCoordinateIndex(ij[0].getNumber()*3 + k) == iga.getCoordinateIndex(ij[1].getNumber()*3 + l)) {
                            if (!v1found) {
                                v1 = iga.getCoordinateIndex(ij[0].getNumber()*3 + k);
                                v1found = true;
                            }
                            else v2 = iga.getCoordinateIndex(ij[0].getNumber()*3 + k);
                        }
                    }
                }
                System.out.println("vertex1 : " + v1 + "      vertex2 : " + v2);
                
                /*
                if (foundColor3) {
                    if (foundColor4) {
                        Color4f nc4 = new Color4f((float)weights[currentWeight], 1.f, 0.f, 0.f);
                        Color4f c4 = new Color4f();
                        iga.getColor(iga.getCoordinateIndex(v1), c4);
                        if ((float)weights[currentWeight] > c4.x) {
                            iga.setColor(iga.getCoordinateIndex(v1), nc4);
                        }
                        iga.getColor(iga.getCoordinateIndex(v2), c4);
                        if ((float)weights[currentWeight] > c4.x) {
                            iga.setColor(iga.getCoordinateIndex(v2), nc4);
                        }
                    }
                    else {
                        Color3f nc3 = new Color3f((float)weights[currentWeight], 1.f, 0.f);
                        Color3f c3 = new Color3f();
                        iga.getColor(iga.getCoordinateIndex(v1), c3);
                        if ((float)weights[currentWeight] > c3.x) {
                            iga.setColor(iga.getCoordinateIndex(v1), nc3);
                        }
                        iga.getColor(iga.getCoordinateIndex(v2), c3);
                        if ((float)weights[currentWeight] > c3.x) {
                            iga.setColor(iga.getCoordinateIndex(v2), nc3);
                        }
                    }
                }
                else {
                //}
                */

                Color3f c3 = new Color3f();
                ita.getColor(ita.getColorIndex(v1), c3);
                if ( 1.f-(float)weights[currentWeight] < c3.y ) {
                    ita.setColorIndex(ita.getColorIndex(v1), currentWeight); 
                }
            }
            currentWeight++;
        }
        iga = ita;
    }
    
    public Shape3D getColorizedShape3D() {
        //return ShapeFactory.buildShape3D(iga);
        Shape3D shape3d = new Shape3D(iga, ShapeFactory.createAppearance(.5f,.5f,.5f));
        return shape3d;

    }
    
    public IndexedTriangleArray getIndexedGeometryArray() {
        return iga;
    }
    
    public int getNumWeights() {
        return numWeights;
    }

}
