package yi.iu.processor.clc;

import java.util.*;

import yi.ai.cluster.*;
import yi.ds.*;
import yi.iu.processor.ort.*;
import yi.stat.hist.*;
import yi.util.io.*;
import yi.util.config.Configuration;

/**
 * Construct Orientation Consistent Line Cluster.
 */
public class CLC_VerticalPosition extends CLC_Clustering
{

  public boolean DEMO_VERTIACAL_CLUSTERING = false;

  /**
   * The suspension ability of the a suspension tower.  It is an argument when
   * using histogram based 1-D clustering to cluster the lines based on their
   * vertical positions.
   * @see yi.ai.cluster.OneDHistBasedCluster#suspensionBridgeClustering
   */
  public double SUSPENSION_TOWER_ABILITY = 0.5;
//  public double SUSPENSION_TOWER_ABILITY = 0.18;

  /**
   * The maximum suspension width of a suspension tower.  It is an argument when
   * using histogram based 1-D clustering to cluster the lines based on their
   * vertical positions.  It is normalized by max(image_width, image_height)
   * @see yi.ai.cluster.OneDHistBasedCluster#suspensionBridgeClustering
   */
  //public double MAX_SUSPENSION_WIDTH = 0.12;
  public double MAX_SUSPENSION_WIDTH = 1;

  /**
   * The minimum suspension width of a suspension tower.  It is an argument when
   * using histogram based 1-D clustering to cluster the lines based on their
   * vertical positions.  It is normalized by max(image_width, image_height)
   * @see yi.ai.cluster.OneDHistBasedCluster#suspensionBridgeClustering
   */
  public double MIN_SUSPENSION_WIDTH = 0.03;
  //public double MIN_SUSPENSION_WIDTH = 0.03;

  public CLC_VerticalPosition() {
    Configuration.configParameters(this);
  }

  public String[] getParameterNames() {
    return super.getParameterNames(new String[] {
      "DEMO_VERTIACAL_CLUSTERING",
    });
  }

  /**
   * Clustering the lines according to their vertical position
   * @param t 0.18 is used before
   * @return
   */
  public LineClusterSets getClusters(LineClusterSet lines, int[] rgb, int width, int height) {
    if (lines == null || lines.size() <= 0) return new LineClusterSets(width, height);

    // get the y position of all the lines
//    ORTLine[] lines_without_perspective = lines.getLinesWithoutPerspectiveEffects();
    ORTLine[] lines_without_perspective = lines.getLinesWRTBaseLine();
    double[] y_positions = new double[lines.size()];
    for (int i=0; i<y_positions.length; i++) {
      y_positions[i] = lines_without_perspective[i].midPoint().Row;
    }

    // convert double type to integer
    int[] qPos = yi.util.data.Conversion.toInt(y_positions);
    if (Configuration.getStringParameter("DEBUG", "false").compareTo("true") == 0) {
      yi.util.io.OutputResult.print(System.out, qPos);
    }


    // make the histogram
    //double[] weights = lines.getWeightedLength();
    double[] weights = new double[lines.size()];
    int i_count = 0;
    for (Iterator i=lines.iterator(); i.hasNext(); ) {
      ORTLine l = (ORTLine)i.next();
      weights[i_count++] = l.getLength();
    }
    if (Configuration.getStringParameter("DEBUG", "false").compareTo("true") == 0) {
      yi.util.io.OutputResult.print(System.out, weights);
    }
    yi.stat.hist.WeightedHistogram hist = new WeightedHistogram(qPos, weights);

    /*
    System.err.println("min="+min+", max="+max);
    double[] h1= new double[480];
    for (i=0;i<lines.size();i++) {
        ORTLine l=(ORTLine)lines.elementAt(i);
        int index= (qPos[i]-(-240));
        //h[index]+= l.Length;
        h1[index]+= l.weightedLength(STANDARDLEN, MAXWEIGHT);
    }
    OutputResult.outputResult("hist", h1, 1, h1.length);
    //*/

    //get the range, and don't remove any ranges
    int image_size = Math.max(lines.getImageWidth(), lines.getImageHeight());
    OneDClusters clusters = OneDHistBasedCluster.suspensionBridgeClustering(
      hist, SUSPENSION_TOWER_ABILITY, 0, (int)Math.round(MAX_SUSPENSION_WIDTH * image_size),
      (int)Math.round(MIN_SUSPENSION_WIDTH * image_size));

    // new line cluster sets for clustering
    LineClusterSets line_clusters = new LineClusterSets(width, height);
    DataRange[] ranges = clusters.getClusters();
    Iterator iter = lines.iterator();
    int count = 0;
    while (iter.hasNext()) {
      ORTLine l = (ORTLine)iter.next();
      // which cluster the line belongs to
      int label = clusters.getLabel(qPos[count++]);
      if (label < 0) continue;  // it doesn't belong to any cluster
      // put it in
      line_clusters.add(ranges[label], l);
    }

    // filter the result
    line_clusters.filter(
      CLCConfig.getMinQualifiedLineLen(),
      CLCConfig.getMinQualifiedCLCLineLenSum(lines.getImageWidth(), lines.getImageHeight()));

    // inherit the properties from the parent (clustered from)
    line_clusters.inheritProperties(lines);

    // demo the results
    if (DEMO_VERTIACAL_CLUSTERING) {
      int[] cluster_img = lines.demo();
      int[] clusters_img = line_clusters.demo();
      OutputResult.outputGIFImage("a_vertical_clustering", cluster_img, lines.getImageWidth(), lines.getImageHeight(), true);
      OutputResult.outputGIFImage("b_vertical_clustering", clusters_img, lines.getImageWidth(), lines.getImageHeight(), true);
    }

    return line_clusters;
  }

}