package yi.iu.processor.clc;

import yi.iu.processor.clc.*;
import yi.iu.processor.*;
import yi.iu.processor.building.*;
import yi.iu.processor.ort.*;
import yi.iu.processor.filter.GaussianSmooth;
import yi.iu.ui.*;
import yi.iu.processor.color.*;
import yi.util.io.*;
import yi.dp.Histogram;

import java.awt.*;
import java.util.Vector;
import java.io.*;

/**
 * Construct orientation consistent line clusters
 * @depracated replaced by CLC_Orientation
 */
public class CSOCLC extends yi.iu.processor.clc.ConsistentLineCluster
{
    public static double SMOOTH_SIGMA=4;
    public static int ANGEL_BINS=180;   //the number of bins for angel quantilization
    //arguments to do the canny edge detection
    public static double sigma=1;
    public static double tlow=0.5;
    public static double thigh=50;
    public static int min_length=4;
    //arguments to do the line extraction
    public static int MaxJumpPixels=1;


    double Tcpm=0.3;    //threshold for color portion: when calculate the color of a line,
                        //if one color takes more than Tcp of the whole line, then the color
                        //of the line is decided    (stands for color portion multi)
    int Tsp=4;       //threshold for shift pixels: shift the line until it arrives Tsp

    double Ths= 0.18;   //threshold for the size of considered color

    int last=-1;
    int outputfornext=-1;
    int outputlines=-1;

    public int getArguNum() { return 2;}

    public void setArgument(int i, String st)
    {
        if (st.length()==0) return;
        if (i==0) last= Integer.valueOf(st).intValue();
        if (i==1) outputfornext= Integer.valueOf(st).intValue();
        if (i==2) outputlines= Integer.valueOf(st).intValue();
    }

    public String getArgument(int i)
    {
        if (i==0) return (new Integer(last)).toString();
        if (i==1) return (new Integer(outputfornext)).toString();
        if (i==2) return (new Integer(outputlines)).toString();
        return null;
    }

    public String getArguName(int i)
    {
        if (i==0)  return "last mon";
        if (i==1)  return "output 4 next";
        if (i==2)  return "output lines";
        return null;
    }

    public LineCluster[] getProcessed_ex(int source[], Dimension d, Object ref[])
    {
        int i,j;

        CSCLC csclc= new CSCLC();
        csclc.illustration=false;
        csclc.getProcessed_ex(source, d, ref);
        int[] dominant_colors= (int[])ref[0];
        int cNum=dominant_colors.length;
        Vector lines= (Vector)ref[1];
        int[][] lineColor= (int[][])ref[2];

        //represent the color of the lines by a single integer
        int numLines= lines.size();
        int[] lineIndexColor= new int[numLines];
        for (i=0;i<numLines;i++) {
            lineIndexColor[i]=singleColorIndex(lineColor[i], cNum);
        }

        //get the orienation histogram of the colored lines
        int[][] cloh= colorsLineOrientationHistogram(lines, lineIndexColor, cNum);
        //OutputResult.outputResult("hist", cloh);

        /*
        //make the statics information of the lines' colors
        //[0]: the lines not belonging to any cluster
        int[][] lineStat= new int[cNum+1][cNum+1];
        double[][] lengthStat= new double[cNum+1][cNum+1];
        for (i=0;i<lineColor.length;i++) {
            int c1,c2;
            if (lineColor[i][0]<lineColor[i][1]) { c1=lineColor[i][0];c2=lineColor[i][1];}
            else { c1=lineColor[i][1];c2=lineColor[i][0];}
            lineStat[c1+1][c2+1]++;
            ORTLine l=(ORTLine)lines.elementAt(i);
            lengthStat[c1+1][c2+1]+=l.Length;
        }
        OutputResult.outputResult("lines_color_stat", lineStat);
        //OutputResult.outputResult("lines_length_stat", lengthStat);
        //*/

        //get all the clusters
        //int ths= (int)(Math.max(Math.sqrt(source.length)*Ths,1));
        //Vector lineClusters= colorLineCluster(cloh, cNum, ths);
        //try Ths=0
        int ths= (int)(LineCluster.STANDARDLEN*TCS);
        Vector lineClusters= colorLineCluster(cloh, cNum, ths);
        int[][] _clusters= new int[lineClusters.size()][];
        for (i=0;i<lineClusters.size();i++) _clusters[i]= (int[])lineClusters.elementAt(i);
        //OutputResult.outputResult("cluster_stat", _clusters);

        //assign the lines to the clusters
        LineCluster[] lc= new LineCluster[lineClusters.size()];
        for (i=0;i<lineClusters.size();i++) {
            int[] info= (int[])lineClusters.elementAt(i);
            lc[i]= new LineCluster(info[0],info[1],info[2]);
            if (info[0]==last) {
                System.err.println("monitor:"+last+"->"+i+"("+info[1]+","+info[2]+")");
            }
        }
        for (i=0;i<lines.size();i++) {
            ORTLine line= (ORTLine)lines.elementAt(i);
            int angel= (int)Math.round(line.Theta*ANGEL_BINS/Math.PI);
            for (j=0;j<lc.length;j++) {
                if (lc[j].insertByCondition(line,lineIndexColor[i],angel)) break;
            }
        }

        //display the monitored line cluster
        if (last>=0) {
            int[] label= new int[d.width*d.height];
            for (i=0;i<label.length;i++) label[i]=-1;
            for (i=0;i<lc.length;i++) {
                if (lc[i].color!=last) continue;
                if (lc[i]==null) continue;
                for (j=0;j<lc[i].size();j++) {
                    ORTLine line= lc[i].getLineAt(j);
                    DrawUtil.ort2image(label, d, line, i, 1);
                }
            }
            int[] cluster_img2= yi.util.ImageUtil.makeNewImageFromLabel_back(label);
            (new SegFrame("monitored", cluster_img2, d.width, d.height, label)).show();
        }


        //filter the small line clusters
        int size1= this.realClusterNum(lc);
        //get rid of the small clusters
        int size2= filterSmallClusters(lc);
        System.err.println("filter the small clusters after orientation: "+size1+"-->"+size2);

        return lc;
    }


    public int[] getProcessedPseudoColor(int source[], Dimension d)
    {
        int i,j;

        Object[] ref= new Object[3];
        LineCluster[] lc= getProcessed_ex(source, d, ref);
        int[] dominant_colors= (int[])ref[0];
        int cNum=dominant_colors.length;
        Vector lines= (Vector)ref[1];
        int[][] lineColor= (int[][])ref[2];

        drawLineClusters("co-clc",d,lc,outputfornext);
        System.err.println("lc size:"+lc.length);
        if (outputfornext>=0) {
            if (lc[outputfornext]==null)
                System.err.println("can't output");
            else {
                System.err.println("output"+outputfornext+":"+lc[outputfornext].size());
                lc[outputfornext].output();
            }
        }

        return null;
    }


    /**
     * Given the color pair index, return the color pair.
     *
     * @param color Color pair index
     * @param cNum The total number of the colors.
     * @return The color pair
     */
    public int[] colorPairs(int color, int cNum)
    {
        int[] c= new int[2];
        int c1= color/(cNum+1);
        int c2= color-c1*(cNum+1);
        if (c1<c2) {
            c[0]=c1-1;c[1]=c2-1;
        }
        else {
            c[0]=c2-1;c[1]=c1-1;
        }
        return c;
    }


    /**
     * Return a integer as the index to represent a the color pairs.  For example,
     * the lines have two colors, c1 and c2, on their sides, but we could represent this
     * attribute by one number, c1*(size of color count)+c2.
     *
     * @param colors The color pair.
     * @param cNum The color count.
     * @return The signal value to represent the color pair.
     */
    public int singleColorIndex(int[] colors, int cNum)
    {
        if (colors[0]>=cNum||colors[1]>=cNum) {
            System.err.println("wrong color index!");
        }
        if (colors[0]<colors[1])
            return ((colors[0]+1)*(cNum+1)+colors[1]+1);
        return ((colors[1]+1)*(cNum+1)+colors[0]+1);
    }

    public int[][] colorsLineOrientationHistogram(Vector lines, int[]colors, int cNum)
    {
        //h is the the variance of histogram[color1][color2][orientation]
        //instead of representing the colors on two sides by two dimension,
        //we use histogram[color1*size+color2][orientation].
        //we lose nothing for this representation (the colors are not continuous)
        int[][] h= new int[(cNum+1)*(cNum+1)][ANGEL_BINS];
        int i;
        for (i=0;i<lines.size();i++) {
            ORTLine line= (ORTLine)lines.elementAt(i);
            int angel= (int)Math.round(line.Theta*ANGEL_BINS/Math.PI);
            if (angel<0) angel+=ANGEL_BINS;
            if (angel>=ANGEL_BINS) angel-=ANGEL_BINS;

            //get the color-index on two sides
            //because there is a the non-index color, (color index = -1 )
            //we should use color_index+1
            //h[colors[i]][angel]+=line.Length;
            h[colors[i]][angel]+=line.weightedLength(LineCluster.STANDARDLEN, LineCluster.MAXWEIGHT)
                *LineCluster.STANDARDLEN;
        }

        return h;
    }

    //calculate the colors on the both side of the line
    //return null if can't decide (don't count on the non-decided pixel)
    int[][] getLineColors_mul(int[] img, Dimension d, ORTLine l, int cNum, double tcpm, int tsp)
    {
        int i,j;
        ORTLine shift= null;
        int[][] result= new int[2][];

        //color on the +90 side
        int[] color_his= new int[cNum];
        int length= -1;
        for (i=1;i<=tsp;i++)    {
            shift=l.makeNewLineByAngleShift(i, Math.PI/2);
            int[] p_length= new int[1];
            //the length of returned colors is cNum+1,
            //the colors[cNum] is the number of un-decided piexls.
            int[] colors= colorsOnVirtualLine(img, d, shift, cNum, 1, p_length);

            if (length==-1) length= p_length[0];
            for (j=0;j<color_his.length;j++)
                if (color_his[j]<colors[j]) color_his[j]=colors[j];
        }
        //examine how many satisfy the requirement
        int sat=0;
        int threshold= (int)Math.ceil(length*tcpm);
        for (i=0;i<color_his.length;i++) if (color_his[i]>threshold) sat++;
        if (sat>0) {
            int[] colors= new int[sat];
            for (i=0;i<color_his.length;i++) if (color_his[i]>threshold) colors[--sat]=i;
            result[0]= colors;
        }
        else result[0]=null;

        //color on the -90 side
        for (i=0;i<color_his.length;i++) color_his[i]= 0;
        for (i=1;i<=tsp;i++)    {
            shift=l.makeNewLineByAngleShift(i, -Math.PI/2);
            int[] p_length= new int[1];
            int[] colors= colorsOnVirtualLine(img, d, shift, cNum, 1, p_length);
            for (j=0;j<color_his.length;j++)
                if (color_his[j]<colors[j]) color_his[j]=colors[j];
        }
        //examine how many satisfy the requirement
        sat=0;
        for (i=0;i<color_his.length;i++) if (color_his[i]>threshold) sat++;
        if (sat>0) {
            int[] colors= new int[sat];
            for (i=0;i<color_his.length;i++) if (color_his[i]>threshold) colors[--sat]=i;
            result[1]= colors;
        }
        else result[1]=null;

        return result;
    }

    /**
     * Given the colored-line histogram, return all the orientation-consistent line clusters. <p>
     * Ignore the color if the sum of the length of the lines falling into a color is less than t
     *
     * @param h Color-Orientation histogram.<p>
     * In format of h[color-index][orientation].<p>
     * @param cNum The number of the colors.  The color index could be greater than cNum because
     * we could use c1,c2 as the color-index to represent the two colored lines.
     * @param t The threshold for the size of a line cluster.  Those cluster, whose size is less than t,
     * will be ignored.
     * @return Vector of int[3], in which <p>
     * int[0]:color-index, int[1]-left limitation on orientation, int[2]-right limitation on orientation
     */
    public Vector colorLineCluster(int[][] h, int cNum, int t)
    {
        if (t<1) t=1;   //t must>0
        int c,o,i;
        int sum;
        Vector _ranges=new Vector();
        for (c=0;c<h.length;c++) {
            //calculate the sum of the histogram on a special color
            sum=0;
            for (o=0;o<h[c].length;o++) sum+=h[c][o];
            if (sum==0) continue;
            if (sum<t) {
                if (VERBOSE) System.err.println("the total length in color-index "+c+"="+sum+"<t="+t+" ignored!");
                continue;
            }

            /*
            double[] smooth= (new GaussianSmooth(SMOOTH_SIGMA)).smoothing_period(h[c]);
            int[][] peaks= Histogram.findPeaks(smooth);
            int[][] ranges= Histogram.peaks2Ranges(peaks);    //convert the peaks to the range of peaks
            */
            int[][] ranges= histogramRanges(h[c], SMOOTH_SIGMA);
            for (i=0;i<ranges.length;i++){
                int[] new_r= {c, ranges[i][0], ranges[i][1], (int)sum};
                _ranges.addElement(new_r);
            }
            //System.err.println("    peaks on color-"+c+"= "+ranges.length);
        }
        System.err.println("All peaks # after color-orientation= "+_ranges.size());
        return _ranges;

    }

    public int[][] histogramRanges(int[] h, double sigma)
    {
        double[] smooth= (new GaussianSmooth(sigma)).smoothing_period(h);

        int[] h_r= new int[h.length]; double[] s_r= new double[smooth.length];
        if (false) {
            for (int i=0;i<h_r.length;i++) { h_r[i]=h[h_r.length-1-i];s_r[i]=smooth[s_r.length-1-i];}
            OutputResult.outputResult("h1", h_r);
            OutputResult.outputResult("h2", s_r);
        }

        int[][] peaks= Histogram.findFatPeaks(smooth,0);
        int[][] ranges= Histogram.peaks2Ranges(peaks);    //convert the peaks to the range of peaks
        return ranges;
        /*
        int[][] r= Histogram.getPeaksSimple_period_decent(h, 8, 4);
        return r;
        */

    }

    /*
    public int[][] histogramRanges(int[] h, double sigma)
    {
        int[][] r= Histogram.getPeaksSimple_period_decent(h, 10, 4*15);
        //int[][] r= {{132,145}};
        //OutputResult.outputResult("h48", h);

        return r;
    }

    */

    int[] colorsOnVirtualLine(int[] img, Dimension d, ORTLine line, int cNum, int LineThickness, int[] p_length)
    {
        int[] cHist= new int[cNum+1];   //color histogram

      int temp, deltax, deltay, xincrement, yincrement, e, a, b, i;
        int k,l;

        int num=0;
        int red=0,green=0,blue=0;
        int xsize=d.width,ysize=d.height;
        double XCenter = ((double) (xsize))/2.0;
        double YCenter = ((double) (ysize))/2.0;
        int x1= (int)(Math.round(line.Start.Col+XCenter)), y1= (int)Math.round(line.Start.Row+YCenter);
        int x2= (int)(Math.round(line.End.Col+XCenter)), y2= (int)(Math.round(line.End.Row+YCenter));
        if (Math.abs(x2-x1) > Math.abs(y2-y1)) {
            if (x1 > x2) {
                temp = x1; x1 = x2; x2 = temp;
                temp = y1; y1 = y2; y2 = temp;
            }
            deltax = x2 - x1;
            deltay = Math.abs (y2 - y1);
            e = (2 * deltay) - deltax;
            a = (2 * deltay) - (2 * deltax);
            b = (2 * deltay);
            if (y2 > y1) {
              yincrement = 1;
            } else {
              yincrement = -1;
            }
            for (i= 0;i<=deltax;i++) {

                if ((x1>0) && (x1<=xsize) && (y1>0) && (y1<=ysize)) {
                    for(k =(x1-LineThickness); k<=(x1+LineThickness); k++){
                        for(l =(y1-LineThickness); l<=(y1+LineThickness); l++){
                            if (l>=0&&l<ysize&&k>=0&&k<xsize) {
                                int c= img[l*xsize+k];
                                cHist[c]++;
                                num++;
                            }
                        }
                    }
                }
                if (e > 0) {
                    y1 = y1 + yincrement;
                    e = e + a;
                } else {
                    e = e + b;
                }
                x1 = x1 + 1;
            }
        }
        else {
            if (y1 > y2) {
                temp = x1; x1 = x2; x2 = temp;
                temp = y1; y1 = y2; y2 = temp;
            }
            deltay = y2 - y1;
            deltax = Math.abs(x2 - x1);
            e = (2 * deltax) - deltay;
            a = (2 * deltax) - (2 * deltay);
            b = (2 * deltax);
            if (x2 > x1) {
              xincrement = 1;
            } else {
              xincrement = -1;
            }
            for (i= 0;i<=deltay;i++) {
                if ((x1>0) && (x1<=xsize) && (y1>0) && (y1<=ysize)) {
                        for(k =(x1-LineThickness); k<=(x1+LineThickness); k++){
                        for(l =(y1-LineThickness); l<=(y1+LineThickness); l++){
                            if (l>=0&&l<ysize&&k>=0&&k<xsize) {
                                int c= img[l*xsize+k];
                                cHist[c]++;
                                num++;
                            }
                        }
                        }
                }
                if (e > 0) {
                    x1 = x1 + xincrement;
                    e = e + a;
                } else {
                    e = e + b;
                }
                    y1 = y1 + 1;
            }
        }

        p_length[0] = num;
        return cHist;
        /*
        int max=0;
        int max_i=cNum;
        int threshold= (int)(num*tcp);
        for (i=0;i<=cNum;i++)
            if (cHist[i]>max) {
                max=cHist[i];
                max_i=i;
            }
        if (max<threshold) max_i=-1;

        int[] rst={max_i,max,num};
        return rst;
        */
    }

    public int[] getProcessed(int source[], Dimension d)
    {
        // This method is derived from class yi.iu.processor.ImageProcessor
        // to do: code goes here
        return null;
    }

    void outputColoredLines(Vector lines, int[] colors)
    {
        int i,j;
        if (lines.size()!=colors.length) {
            System.err.println("|lines| != |colors|");
        }
        try {
            ObjectOutputStream out= new ObjectOutputStream (
                new FileOutputStream ("coloredlines.out"));
            out.writeObject(lines);
            out.writeObject(colors);
            out.close();
        }
        catch (Exception e) {
            System.err.println(e.toString());
        }
    }

    void outputColoredLines(LineCluster[] lcs)
    {
        int i,j;
        try {
            ObjectOutputStream out= new ObjectOutputStream (
                new FileOutputStream ("csocls.out"));
            out.writeObject(lcs);
            out.close();
        }
        catch (Exception e) {
            System.err.println(e.toString());
        }
    }

    public static class DemoColorCLCs {

      public static void drawColorCLCs(int source[], Dimension d) {
        int i;

        CSCLC csclc= new CSCLC();
        csclc.illustration=false;
        Object[] ref = new Object[3];
        csclc.getProcessed_ex(source, d, ref);
        int[] dominant_colors= (int[])ref[0];
        int cNum=dominant_colors.length;
        Vector lines= (Vector)ref[1];
        int[][] lineColor= (int[][])ref[2];
        //represent the color of the lines by a single integer
        int numLines= lines.size();
        int[] lineIndexColor= new int[numLines];
        for (i=0;i<numLines;i++) {
            lineIndexColor[i]=csclc.singleColorIndex(lineColor[i], cNum);
        }

        // total possible line clusters
        int[] cluster_stat = new int[(cNum+1)*(cNum+1)];
        for (i=0;i<numLines;i++) cluster_stat[lineIndexColor[i]]++;

        //draw
        int[] label= new int[d.width*d.height];
        for (int k=0; k<cluster_stat.length; k++) {
          if (cluster_stat[k]==0) continue;
          for (i=0;i<label.length;i++) label[i]=-1;
          for (i=0;i<lineColor.length;i++) {
                if (lineIndexColor[i]!=k) continue;
                ORTLine line= (ORTLine)lines.elementAt(i);
                DrawUtil.ort2image(label, d, line, k, 1);
          }
          int[] cluster_img2= yi.util.ImageUtil.makeNewImageFromLabel_back(label);
          String outfilename = "color_clc_"+k+".gif";
          System.out.println(String.valueOf(k)+":"+ outfilename);
          yi.util.io.OutputResult.outputGIFImage(
            outfilename, cluster_img2, d.width, d.height);
        }
      }
      public static void main(String[] args) {
        if (args.length<1) return;
        try {
          String img_name = args[0];
          System.out.println("image = " + img_name);
          Image img = yi.util.io.ImageReader.readImageFile(img_name);
          Dimension d = new Dimension();
          int[] pixels = ImageReader.getPixels(img, d);
          drawColorCLCs(pixels, d);
        } catch (IOException e) {
          e.printStackTrace();
        }

      }
    }



    public static void main(String[] args) {
//line cluster for orientation classifying (the building on the right)
LineCluster lc= new LineCluster(0,0,0);
lc.insert(new ORTLine(-10.0,-195.0,0.0,-198.0));
lc.insert(new ORTLine(-27.0,-238.0,-30.0,-234.0));
lc.insert(new ORTLine(-19.0,-238.0,-15.0,-238.0));
lc.insert(new ORTLine(49.0,-238.0,46.0,-234.0));
lc.insert(new ORTLine(76.0,-238.0,77.0,-213.0));
lc.insert(new ORTLine(125.0,-239.0,128.0,-236.0));
lc.insert(new ORTLine(129.0,-233.0,129.0,-219.0));
lc.insert(new ORTLine(132.0,-222.0,132.0,-237.0));
lc.insert(new ORTLine(150.0,-205.0,144.0,-233.0));
lc.insert(new ORTLine(168.0,-233.0,168.0,-238.0));
lc.insert(new ORTLine(171.0,-238.0,171.0,-232.0));
lc.insert(new ORTLine(174.0,-229.0,182.0,-219.0));
lc.insert(new ORTLine(184.0,-222.0,183.0,-238.0));
lc.insert(new ORTLine(176.0,-238.0,175.0,-234.0));
lc.insert(new ORTLine(42.0,-231.0,42.0,-209.0));
lc.insert(new ORTLine(181.0,-235.0,181.0,-224.0));
lc.insert(new ORTLine(23.0,-233.0,11.0,-223.0));
lc.insert(new ORTLine(10.0,-220.0,10.0,-204.0));
lc.insert(new ORTLine(17.0,-231.0,13.0,-227.0));
lc.insert(new ORTLine(-3.0,-228.0,-10.0,-228.0));
lc.insert(new ORTLine(99.0,-226.0,80.0,-221.0));
lc.insert(new ORTLine(141.0,-227.0,145.0,-223.0));
lc.insert(new ORTLine(146.0,-220.0,146.0,-210.0));
lc.insert(new ORTLine(308.0,-223.0,306.0,-219.0));
lc.insert(new ORTLine(13.0,-222.0,13.0,-205.0));
lc.insert(new ORTLine(34.0,-221.0,34.0,-208.0));
lc.insert(new ORTLine(31.0,-207.0,13.0,-202.0));
lc.insert(new ORTLine(95.0,-215.0,80.0,-211.0));
lc.insert(new ORTLine(77.0,-209.0,78.0,-179.0));
lc.insert(new ORTLine(81.0,-178.0,104.0,-183.0));
lc.insert(new ORTLine(106.0,-186.0,106.0,-192.0));
lc.insert(new ORTLine(68.0,-218.0,46.0,-211.0));
lc.insert(new ORTLine(104.0,-215.0,82.0,-209.0));
lc.insert(new ORTLine(79.0,-207.0,80.0,-196.0));
lc.insert(new ORTLine(186.0,-215.0,192.0,-209.0));
lc.insert(new ORTLine(195.0,-209.0,196.0,-215.0));
lc.insert(new ORTLine(160.0,-212.0,161.0,-198.0));
lc.insert(new ORTLine(168.0,-201.0,169.0,-188.0));
lc.insert(new ORTLine(198.0,-210.0,198.0,-205.0));
lc.insert(new ORTLine(178.0,-207.0,179.0,-183.0));
lc.insert(new ORTLine(309.0,-207.0,308.0,-203.0));
lc.insert(new ORTLine(306.0,-207.0,297.0,-210.0));
lc.insert(new ORTLine(212.0,-204.0,206.0,-199.0));
lc.insert(new ORTLine(191.0,-197.0,192.0,-172.0));
lc.insert(new ORTLine(183.0,-179.0,182.0,-199.0));
lc.insert(new ORTLine(130.0,-203.0,120.0,-213.0));
lc.insert(new ORTLine(132.0,-177.0,131.0,-197.0));
lc.insert(new ORTLine(147.0,-192.0,139.0,-199.0));
lc.insert(new ORTLine(60.0,-199.0,46.0,-195.0));
lc.insert(new ORTLine(45.0,-201.0,66.0,-207.0));
lc.insert(new ORTLine(68.0,-206.0,47.0,-199.0));
lc.insert(new ORTLine(69.0,-198.0,69.0,-176.0));
lc.insert(new ORTLine(66.0,-175.0,47.0,-170.0));
lc.insert(new ORTLine(44.0,-171.0,43.0,-196.0));
lc.insert(new ORTLine(175.0,-198.0,175.0,-187.0));
lc.insert(new ORTLine(32.0,-198.0,15.0,-193.0));
lc.insert(new ORTLine(12.0,-192.0,10.0,-183.0));
lc.insert(new ORTLine(11.0,-180.0,9.0,-152.0));
lc.insert(new ORTLine(8.0,-149.0,9.0,-113.0));
lc.insert(new ORTLine(35.0,-193.0,35.0,-168.0));
lc.insert(new ORTLine(32.0,-167.0,14.0,-162.0));
lc.insert(new ORTLine(151.0,-192.0,152.0,-165.0));
lc.insert(new ORTLine(149.0,-165.0,148.0,-172.0));
lc.insert(new ORTLine(2.0,-190.0,-15.0,-185.0));
lc.insert(new ORTLine(-18.0,-184.0,-19.0,-169.0));
lc.insert(new ORTLine(148.0,-190.0,148.0,-175.0));
lc.insert(new ORTLine(187.0,-190.0,188.0,-177.0));
lc.insert(new ORTLine(3.0,-188.0,2.0,-166.0));
lc.insert(new ORTLine(203.0,-189.0,204.0,-164.0));
lc.insert(new ORTLine(197.0,-185.0,203.0,-158.0));
lc.insert(new ORTLine(210.0,-181.0,214.0,-154.0));
lc.insert(new ORTLine(99.0,-172.0,80.0,-168.0));
lc.insert(new ORTLine(79.0,-165.0,79.0,-136.0));
lc.insert(new ORTLine(82.0,-134.0,105.0,-139.0));
lc.insert(new ORTLine(108.0,-141.0,107.0,-170.0));
lc.insert(new ORTLine(104.0,-171.0,100.0,-169.0));
lc.insert(new ORTLine(170.0,-171.0,171.0,-151.0));
lc.insert(new ORTLine(178.0,-147.0,177.0,-168.0));
lc.insert(new ORTLine(175.0,-171.0,170.0,-175.0));
lc.insert(new ORTLine(180.0,-168.0,182.0,-145.0));
lc.insert(new ORTLine(210.0,-169.0,211.0,-159.0));
lc.insert(new ORTLine(219.0,-165.0,221.0,-151.0));
lc.insert(new ORTLine(94.0,-168.0,89.0,-167.0));
lc.insert(new ORTLine(184.0,-167.0,189.0,-160.0));
lc.insert(new ORTLine(190.0,-157.0,191.0,-140.0));
lc.insert(new ORTLine(-20.0,-166.0,-20.0,-147.0));
lc.insert(new ORTLine(193.0,-158.0,194.0,-136.0));
lc.insert(new ORTLine(316.0,-163.0,304.0,-157.0));
lc.insert(new ORTLine(3.0,-160.0,-17.0,-154.0));
lc.insert(new ORTLine(59.0,-160.0,69.0,-162.0));
lc.insert(new ORTLine(68.0,-165.0,51.0,-161.0));
lc.insert(new ORTLine(44.0,-151.0,44.0,-129.0));
lc.insert(new ORTLine(47.0,-128.0,70.0,-132.0));
lc.insert(new ORTLine(71.0,-135.0,70.0,-155.0));
lc.insert(new ORTLine(136.0,-160.0,137.0,-133.0));
lc.insert(new ORTLine(134.0,-133.0,133.0,-156.0));
lc.insert(new ORTLine(6.0,-158.0,6.0,-152.0));
lc.insert(new ORTLine(55.0,-159.0,48.0,-157.0));
lc.insert(new ORTLine(149.0,-125.0,149.0,-151.0));
lc.insert(new ORTLine(147.0,-153.0,143.0,-156.0));
lc.insert(new ORTLine(153.0,-150.0,154.0,-124.0));
lc.insert(new ORTLine(34.0,-157.0,14.0,-152.0));
lc.insert(new ORTLine(11.0,-150.0,12.0,-122.0));
lc.insert(new ORTLine(15.0,-121.0,35.0,-125.0));
lc.insert(new ORTLine(36.0,-128.0,36.0,-152.0));
lc.insert(new ORTLine(-48.0,-152.0,-51.0,-160.0));
lc.insert(new ORTLine(2.0,-150.0,-18.0,-145.0));
lc.insert(new ORTLine(-20.0,-142.0,-20.0,-117.0));
lc.insert(new ORTLine(208.0,-150.0,212.0,-143.0));
lc.insert(new ORTLine(212.0,-140.0,213.0,-126.0));
lc.insert(new ORTLine(14.0,-147.0,17.0,-125.0));
lc.insert(new ORTLine(168.0,-140.0,169.0,-115.0));
lc.insert(new ORTLine(5.0,-148.0,3.0,-131.0));
lc.insert(new ORTLine(3.0,-128.0,2.0,-117.0));
lc.insert(new ORTLine(215.0,-142.0,216.0,-122.0));
lc.insert(new ORTLine(213.0,-122.0,209.0,-129.0));
lc.insert(new ORTLine(158.0,-147.0,164.0,-142.0));
lc.insert(new ORTLine(165.0,-139.0,166.0,-118.0));
lc.insert(new ORTLine(2.0,-144.0,-2.0,-120.0));
lc.insert(new ORTLine(-4.0,-117.0,-10.0,-116.0));
lc.insert(new ORTLine(206.0,-129.0,205.0,-151.0));
lc.insert(new ORTLine(222.0,-133.0,223.0,-119.0));
lc.insert(new ORTLine(172.0,-134.0,173.0,-112.0));
lc.insert(new ORTLine(-45.0,-157.0,-49.0,-160.0));
lc.insert(new ORTLine(182.0,-133.0,184.0,-108.0));
lc.insert(new ORTLine(181.0,-107.0,179.0,-132.0));
lc.insert(new ORTLine(138.0,-116.0,139.0,-89.0));
lc.insert(new ORTLine(136.0,-89.0,134.0,-112.0));
lc.insert(new ORTLine(190.0,-126.0,193.0,-104.0));
lc.insert(new ORTLine(195.0,-122.0,196.0,-102.0));
lc.insert(new ORTLine(80.0,-121.0,81.0,-81.0));
lc.insert(new ORTLine(68.0,-122.0,47.0,-117.0));
lc.insert(new ORTLine(44.0,-115.0,45.0,-86.0));
lc.insert(new ORTLine(48.0,-84.0,70.0,-88.0));
lc.insert(new ORTLine(72.0,-90.0,72.0,-96.0));
lc.insert(new ORTLine(102.0,-125.0,106.0,-126.0));
lc.insert(new ORTLine(108.0,-128.0,83.0,-124.0));
lc.insert(new ORTLine(97.0,-124.0,90.0,-123.0));
lc.insert(new ORTLine(207.0,-116.0,208.0,-94.0));
lc.insert(new ORTLine(204.0,-97.0,204.0,-116.0));
lc.insert(new ORTLine(103.0,-120.0,108.0,-120.0));
lc.insert(new ORTLine(108.0,-117.0,110.0,-95.0));
lc.insert(new ORTLine(107.0,-93.0,85.0,-90.0));
lc.insert(new ORTLine(217.0,-107.0,218.0,-88.0));
lc.insert(new ORTLine(215.0,-89.0,211.0,-91.0));
lc.insert(new ORTLine(1.0,-113.0,-3.0,-107.0));
lc.insert(new ORTLine(-6.0,-107.0,-18.0,-105.0));
lc.insert(new ORTLine(210.0,-113.0,213.0,-110.0));
lc.insert(new ORTLine(214.0,-107.0,215.0,-92.0));
lc.insert(new ORTLine(26.0,-111.0,33.0,-112.0));
lc.insert(new ORTLine(32.0,-115.0,15.0,-111.0));
lc.insert(new ORTLine(12.0,-109.0,12.0,-81.0));
lc.insert(new ORTLine(15.0,-79.0,37.0,-83.0));
lc.insert(new ORTLine(37.0,-86.0,37.0,-98.0));
lc.insert(new ORTLine(71.0,-109.0,72.0,-99.0));
lc.insert(new ORTLine(224.0,-101.0,225.0,-86.0));
lc.insert(new ORTLine(3.0,-105.0,-3.0,-102.0));
lc.insert(new ORTLine(155.0,-107.0,156.0,-82.0));
lc.insert(new ORTLine(151.0,-103.0,152.0,-85.0));
lc.insert(new ORTLine(181.0,-93.0,182.0,-71.0));
lc.insert(new ORTLine(184.0,-92.0,185.0,-69.0));
lc.insert(new ORTLine(2.0,-87.0,0.0,-80.0));
lc.insert(new ORTLine(2.0,-77.0,4.0,-85.0));
lc.insert(new ORTLine(219.0,-77.0,220.0,-57.0));
lc.insert(new ORTLine(216.0,-74.0,216.0,-58.0));
lc.insert(new ORTLine(156.0,-69.0,158.0,-39.0));
lc.insert(new ORTLine(222.0,-77.0,226.0,-70.0));
lc.insert(new ORTLine(226.0,-67.0,226.0,-51.0));
lc.insert(new ORTLine(229.0,-49.0,229.0,-71.0));
lc.insert(new ORTLine(-3.0,-74.0,-7.0,-41.0));
lc.insert(new ORTLine(-13.0,-37.0,-18.0,-38.0));
lc.insert(new ORTLine(0.0,-74.0,1.0,-58.0));
lc.insert(new ORTLine(153.0,-65.0,154.0,-41.0));
lc.insert(new ORTLine(189.0,-72.0,191.0,-65.0));
lc.insert(new ORTLine(136.0,-72.0,137.0,-46.0));
lc.insert(new ORTLine(140.0,-45.0,139.0,-75.0));
lc.insert(new ORTLine(194.0,-68.0,193.0,-87.0));
lc.insert(new ORTLine(197.0,-86.0,198.0,-64.0));
lc.insert(new ORTLine(4.0,-65.0,5.0,-59.0));
lc.insert(new ORTLine(206.0,-62.0,205.0,-82.0));
lc.insert(new ORTLine(209.0,-62.0,208.0,-82.0));
lc.insert(new ORTLine(198.0,-50.0,199.0,-32.0));
lc.insert(new ORTLine(195.0,-50.0,196.0,-31.0));
lc.insert(new ORTLine(207.0,-46.0,208.0,-25.0));
lc.insert(new ORTLine(210.0,-23.0,211.0,-27.0));
lc.insert(new ORTLine(211.0,-30.0,210.0,-48.0));
lc.insert(new ORTLine(-81.0,-49.0,-81.0,-37.0));
lc.insert(new ORTLine(115.0,-46.0,128.0,-45.0));
lc.insert(new ORTLine(221.0,-41.0,221.0,-21.0));
lc.insert(new ORTLine(218.0,-21.0,217.0,-43.0));
lc.insert(new ORTLine(231.0,-39.0,230.0,-17.0));
lc.insert(new ORTLine(107.0,-43.0,80.0,-41.0));
lc.insert(new ORTLine(107.0,-41.0,98.0,-40.0));
lc.insert(new ORTLine(95.0,-39.0,81.0,-39.0));
lc.insert(new ORTLine(227.0,-37.0,228.0,-18.0));
lc.insert(new ORTLine(111.0,-38.0,122.0,-41.0));
lc.insert(new ORTLine(50.0,-37.0,44.0,-37.0));
lc.insert(new ORTLine(44.0,-34.0,44.0,-23.0));
lc.insert(new ORTLine(145.0,-35.0,162.0,7.0));
lc.insert(new ORTLine(163.0,-2.0,163.0,-19.0));
lc.insert(new ORTLine(160.0,-22.0,159.0,-29.0));
lc.insert(new ORTLine(118.0,-34.0,112.0,-2.0));
lc.insert(new ORTLine(142.0,-34.0,146.0,-23.0));
lc.insert(new ORTLine(153.0,10.0,177.0,13.0));
lc.insert(new ORTLine(178.0,10.0,162.0,-30.0));
lc.insert(new ORTLine(172.0,-62.0,173.0,-35.0));
lc.insert(new ORTLine(170.0,-35.0,169.0,-62.0));
lc.insert(new ORTLine(214.0,-33.0,214.0,-21.0));
lc.insert(new ORTLine(84.0,3.0,73.0,4.0));
lc.insert(new ORTLine(133.0,-31.0,135.0,-22.0));
lc.insert(new ORTLine(137.0,-28.0,138.0,-20.0));
lc.insert(new ORTLine(191.0,-13.0,191.0,-3.0));
lc.insert(new ORTLine(191.0,-22.0,203.0,8.0));
lc.insert(new ORTLine(201.0,-15.0,208.0,12.0));
lc.insert(new ORTLine(46.0,-20.0,46.0,-16.0));
lc.insert(new ORTLine(153.0,-21.0,152.0,-27.0));
lc.insert(new ORTLine(155.0,-26.0,156.0,-18.0));
lc.insert(new ORTLine(203.0,-19.0,205.0,-15.0));
lc.insert(new ORTLine(170.0,-23.0,171.0,-15.0));
lc.insert(new ORTLine(185.0,-18.0,185.0,-14.0));
lc.insert(new ORTLine(180.0,-16.0,193.0,11.0));
lc.insert(new ORTLine(195.0,10.0,195.0,-4.0));
lc.insert(new ORTLine(178.0,-15.0,177.0,-2.0));
lc.insert(new ORTLine(131.0,-8.0,130.0,-3.0));
lc.insert(new ORTLine(212.0,-14.0,213.0,-10.0));
lc.insert(new ORTLine(214.0,-7.0,214.0,-3.0));
lc.insert(new ORTLine(134.0,-12.0,136.0,-7.0));
lc.insert(new ORTLine(205.0,-12.0,214.0,7.0));
lc.insert(new ORTLine(217.0,-17.0,221.0,-15.0));
lc.insert(new ORTLine(217.0,-9.0,221.0,5.0));
lc.insert(new ORTLine(220.0,8.0,221.0,12.0));
lc.insert(new ORTLine(225.0,-12.0,228.0,-9.0));
lc.insert(new ORTLine(229.0,-6.0,231.0,14.0));
lc.insert(new ORTLine(223.0,-11.0,223.0,-6.0));
lc.insert(new ORTLine(233.0,-8.0,236.0,6.0));
lc.insert(new ORTLine(182.0,-7.0,180.0,13.0));
lc.insert(new ORTLine(183.0,14.0,252.0,23.0));
lc.insert(new ORTLine(255.0,23.0,315.0,20.0));
lc.insert(new ORTLine(237.0,-7.0,241.0,-1.0));
lc.insert(new ORTLine(218.0,2.0,218.0,10.0));
lc.insert(new ORTLine(227.0,0.0,227.0,8.0));
lc.insert(new ORTLine(238.0,0.0,246.0,16.0));
lc.insert(new ORTLine(245.0,2.0,243.0,6.0));
lc.insert(new ORTLine(171.0,3.0,172.0,7.0));
lc.insert(new ORTLine(173.0,3.0,174.0,7.0));
lc.insert(new ORTLine(185.0,4.0,185.0,8.0));
lc.insert(new ORTLine(188.0,10.0,188.0,5.0));
lc.insert(new ORTLine(199.0,4.0,198.0,11.0));
lc.insert(new ORTLine(201.0,12.0,201.0,7.0));
lc.insert(new ORTLine(209.0,6.0,210.0,12.0));
lc.insert(new ORTLine(-111.0,-8.0,-108.0,7.0));
lc.insert(new ORTLine(233.0,7.0,235.0,11.0));
lc.insert(new ORTLine(-150.0,15.0,-146.0,13.0));
lc.insert(new ORTLine(222.0,8.0,225.0,14.0));
lc.insert(new ORTLine(223.0,16.0,217.0,15.0));
lc.insert(new ORTLine(250.0,2.0,261.0,6.0));
lc.insert(new ORTLine(263.0,8.0,259.0,11.0));
lc.insert(new ORTLine(-183.0,10.0,-177.0,12.0));
lc.insert(new ORTLine(274.0,9.0,280.0,10.0));
lc.insert(new ORTLine(-169.0,9.0,-158.0,10.0));
lc.insert(new ORTLine(-170.0,12.0,-174.0,12.0));
lc.insert(new ORTLine(250.0,13.0,256.0,13.0));
lc.insert(new ORTLine(316.0,16.0,251.0,20.0));
lc.insert(new ORTLine(248.0,21.0,239.0,20.0));
lc.insert(new ORTLine(-153.0,16.0,-160.0,13.0));
lc.insert(new ORTLine(25.0,18.0,25.0,3.0));
lc.insert(new ORTLine(-102.0,64.0,-99.0,77.0));
lc.insert(new ORTLine(-102.0,76.0,-103.0,70.0));
lc.insert(new ORTLine(308.0,24.0,316.0,24.0));
lc.insert(new ORTLine(221.0,25.0,216.0,26.0));
lc.insert(new ORTLine(299.0,25.0,303.0,25.0));
lc.insert(new ORTLine(306.0,27.0,310.0,27.0));
lc.insert(new ORTLine(253.0,27.0,260.0,27.0));
lc.insert(new ORTLine(134.0,35.0,180.0,35.0));
lc.insert(new ORTLine(316.0,32.0,300.0,33.0));
lc.insert(new ORTLine(216.0,30.0,269.0,32.0));
lc.insert(new ORTLine(230.0,36.0,233.0,41.0));
lc.insert(new ORTLine(236.0,41.0,255.0,39.0));
lc.insert(new ORTLine(316.0,36.0,302.0,36.0));
lc.insert(new ORTLine(112.0,44.0,108.0,45.0));
lc.insert(new ORTLine(248.0,42.0,267.0,42.0));
lc.insert(new ORTLine(-33.0,2.0,-36.0,14.0));
lc.insert(new ORTLine(200.0,49.0,193.0,50.0));
lc.insert(new ORTLine(202.0,52.0,198.0,63.0));
lc.insert(new ORTLine(220.0,55.0,235.0,53.0));
lc.insert(new ORTLine(227.0,55.0,232.0,55.0));
lc.insert(new ORTLine(268.0,60.0,243.0,61.0));
lc.insert(new ORTLine(-21.0,64.0,-21.0,78.0));
lc.insert(new ORTLine(-115.0,65.0,-116.0,71.0));
lc.insert(new ORTLine(-113.0,73.0,-107.0,75.0));
lc.insert(new ORTLine(-105.0,72.0,-104.0,67.0));
lc.insert(new ORTLine(193.0,65.0,202.0,63.0));
lc.insert(new ORTLine(297.0,64.0,312.0,64.0));
lc.insert(new ORTLine(-31.0,82.0,-30.0,72.0));
lc.insert(new ORTLine(308.0,67.0,316.0,67.0));
lc.insert(new ORTLine(-156.0,68.0,-152.0,68.0));
lc.insert(new ORTLine(275.0,67.0,265.0,68.0));
lc.insert(new ORTLine(263.0,70.0,263.0,74.0));
lc.insert(new ORTLine(266.0,76.0,284.0,75.0));
lc.insert(new ORTLine(286.0,73.0,275.0,73.0));
lc.insert(new ORTLine(-69.0,71.0,-65.0,72.0));
lc.insert(new ORTLine(236.0,71.0,255.0,67.0));
lc.insert(new ORTLine(258.0,69.0,256.0,76.0));
lc.insert(new ORTLine(-98.0,80.0,-93.0,82.0));
lc.insert(new ORTLine(-46.0,84.0,-33.0,85.0));
lc.insert(new ORTLine(312.0,91.0,316.0,93.0));
lc.insert(new ORTLine(316.0,95.0,307.0,96.0));
lc.insert(new ORTLine(-22.0,106.0,-28.0,107.0));
lc.insert(new ORTLine(249.0,111.0,253.0,112.0));
lc.insert(new ORTLine(154.0,-188.0,160.0,-182.0));
lc.insert(new ORTLine(163.0,-180.0,164.0,-158.0));
lc.insert(new ORTLine(167.0,-156.0,166.0,-180.0));
lc.insert(new ORTLine(167.0,-102.0,168.0,-77.0));
lc.insert(new ORTLine(170.0,-74.0,170.0,-102.0));
lc.insert(new ORTLine(186.0,-57.0,187.0,-31.0));
lc.insert(new ORTLine(184.0,-31.0,183.0,-55.0));
lc.insert(new ORTLine(165.0,-5.0,166.0,1.0));
lc.insert(new ORTLine(169.0,0.0,168.0,-8.0));

        int i,j;
        Vector lines= new Vector();
        //int[] lineIndexColor= new int[lc.size()];
        LineCluster lc0= new LineCluster();
        int[] lineIndexColor= new int[lc.size()+lc0.size()];
        int cNum=2;
        for (i=0;i<lc.size();i++) lines.addElement(lc.getLineAt(i));
        for (i=0;i<lc.size();i++) lineIndexColor[i]=0;
        for (i=0;i<lc0.size();i++) lines.addElement(lc0.getLineAt(i));
        for (i=0;i<lc0.size();i++) lineIndexColor[lc.size()+i]=1;
        Dimension d= new Dimension(640, 480);
        CSOCLC csoclc= new CSOCLC();
        csoclc.drawLineClusters("bh", d, lines, 0xffffffff);
        //LineCluster[] lcs1= {lc};
        //csoclc.drawLineClusters("lcs", d, lcs1, -1);

        int[][] cloh= csoclc.colorsLineOrientationHistogram(lines, lineIndexColor, cNum);
        OutputResult.outputResult("cloh", cloh);
        //split
        Vector lineClusters= csoclc.colorLineCluster(cloh, cNum, 0);
        int[][] _clusters= new int[lineClusters.size()][];
        for (i=0;i<lineClusters.size();i++) _clusters[i]= (int[])lineClusters.elementAt(i);
        //OutputResult.outputResult("cluster_stat", _clusters);

        //assign the lines to the clusters
        LineCluster[] lcs= new LineCluster[lineClusters.size()];
        for (i=0;i<lineClusters.size();i++) {
            int[] info= (int[])lineClusters.elementAt(i);
            lcs[i]= new LineCluster(info[0],info[1],info[2]);
        }
        for (i=0;i<lines.size();i++) {
            ORTLine line= (ORTLine)lines.elementAt(i);
            int angel= (int)Math.round(line.Theta*ANGEL_BINS/Math.PI);
            for (j=0;j<lcs.length;j++) {
                if (lcs[j].insertByCondition(line,lineIndexColor[i],angel)) break;
            }

        }
        /*
        for (i=0;i<lcs.length;i++) {
            lcs[i].refineByPerspectiveRelation();
        }
        */
        lcs[4].output();
        csoclc.drawLineClusters("histogram", d, lcs, -1);

    }

}