/*
!=======================================================================
!
!  PROGRAM  PHASE-Viewer  (PHASE-Viewer 2014.01 ver.3.3.0)
!
!  Created on ----
!  AUTHOR(S): KOGA, Junichiro
!  File : CrossPoint.java
!  
!  Contact address :  Phase System Consortium
!                     E-mail: phase_system@nims.go.jp URL https://azuma.nims.go.jp
!
!
!   Since 2002, this program set had been intensively developed as a part of the following 
!  national projects supported by the Ministry of Education, Culture, Sports, Science and
!  Technology (MEXT) of Japan; "Frontier Simulation Software for Industrial Science
!  (FSIS)" from 2002 to 2005, "Revolutionary Simulation Software (RSS21)" from 2006 to
!  2008. "Research and Development of Innovative Simulation Software (RISS)" from 2008
!  to 2013. These projects is lead by the Center for Research on Innovative Simulation 
!  Software (CISS), the Institute of Industrial Science (IIS), the University of Tokyo.
!   Since 2013, this program set has been further developed centering on PHASE System
!  Consortium. 
!   The activity of development of this program set has been supervised by Takahisa Ohno.
!
!=======================================================================
 */
//======================================================================
//                                                                     #
// Software Name : BioStationViewer Version 4.00                       #
//                                                                     #
//      Class Name :  This file name                                   #
//                                                                     #
//                             Written by Akifumi Kato  2003/11/07     #
//                                                                     #
//      Contact address :  The University of Tokyo, FSIS project       #
//                                                                     #
//      "Quantum Molecular Inreraction Analysis"  Group.               #
//                                                                     #
//======================================================================

//package AbinitMp.Display;
package ciss.phase_viewer.acviewer.scenegraphelements.abinitmp;

import AbinitMp.Tool.MathFunc;

public class CrossPoint {

    // cross point

    /*
     * value 1,2 * value @
     * 
     * type 0
     * 
     * @ *-----------------* @ 1 2 type 1-----@-----------* 1 2 type 2
     * 
     * @-----------------* 1 2 type 3-----------------@ 1 2 type 4
     * 
     * @-----------------@ 1 2
     */

    private final static float ZERO_VALUE_LIMIT = 8.0f;
    private final static float ZERO_VALUE_LOG = -8.0f;
    private final static float ZERO_VALUE = 1e-8f;

    /**
     * 指定された2点間に値が有るかどうか調べその座標をかえす。
     * 
     * @param value1
     *            : 値1
     * @param value2
     *            : 値2
     * @param value
     *            : 調べる値
     * @param point1
     *            : 値1の座標
     * @param point2
     *            : 値2の座標
     * @param cross_point
     *            : 交点の座標
     */
    public static int get(float value1, float value2, float value,
            float point1[], float point2[], float cross_point[]) {
        int rt = 0;
        float p, w, wp[], p1[], p2[];
        float log_value, log_value1, log_value2;
        int sign_value, sign_value1, sign_value2;
        float z;
        int n;
        boolean change = false;

        if (value == 0) {
            n = (int) (MathFunc.log10(ZERO_VALUE) / MathFunc.log10(ZERO_VALUE));
            value = ZERO_VALUE;
        } else if (value > 0) {
            n = (int) (MathFunc.log10(value) / MathFunc.log10(ZERO_VALUE));
        } else {
            n = (int) (MathFunc.log10(-value) / MathFunc.log10(ZERO_VALUE));
        }
        z = ZERO_VALUE;
        // 閾値の調整
        for (int i = 0; i < n; i++)
            z *= ZERO_VALUE;

        log_value = 0f;
        log_value1 = 0f;
        log_value2 = 0f;
        sign_value = 0;
        sign_value1 = 0;
        sign_value2 = 0;
        p = 0f;
        p1 = new float[3];
        p2 = new float[3];
        for (int i = 0; i < 3; i++) {
            p1[i] = point1[i];
            p2[i] = point2[i];
        }

        if (value1 > value2) {
            w = value2;
            value2 = value1;
            value1 = w;
            wp = p2;
            p2 = p1;
            p1 = wp;
            change = true;
        }

        /*
         * if ((value1 >= 0) && (value1 < ZERO_VALUE)) // value1 = 0.0f; value1
         * = ZERO_VALUE; if ((value2 >= 0) && (value2 < ZERO_VALUE)) // value2 =
         * 0.0f; value2 = ZERO_VALUE; if ((value1 < 0) && (value1 >
         * -ZERO_VALUE)) // value1 = 0.0f; value1 = -ZERO_VALUE; if ((value2 <
         * 0) && (value2 > -ZERO_VALUE)) // value2 = 0.0f; value2 = -ZERO_VALUE;
         * if ((value1 < 0) && (value2 > 0) && (value > 0)) // value1 = 0.0f;
         * value1 = ZERO_VALUE; if ((value1 < 0) && (value2 > 0) && (value < 0))
         * // value2 = 0.0f; value2 = -ZERO_VALUE;
         */
        /*
         * if (value > 0) { if (value1 < 0) value1 = ZERO_VALUE; if (value2 < 0)
         * value2 = ZERO_VALUE; } if (value < 0) { if (value1 > 0) value1 =
         * -ZERO_VALUE; if (value2 > 0) value2 = -ZERO_VALUE; }
         */

        if (value > 0) {
            if (value1 < 0)
                value1 = z;
            if (value2 < 0)
                value2 = z;
        } else {
            if (value1 > 0)
                value1 = -z;
            if (value2 > 0)
                value2 = -z;
        }

        if (value > value2)
            rt = 0;
        else if (value1 > value)
            rt = 0;
        else if ((value1 < value) && (value < value2)) {
            rt = 1;
            if (value > 0) {
                log_value = MathFunc.log10(value);
                sign_value = 1;
            } else if (value < 0) {
                log_value = MathFunc.log10(-value);
                sign_value = -1;
            } else {
                log_value = ZERO_VALUE_LOG;
                sign_value = 0;
            }
            if (value1 > 0) {
                log_value1 = MathFunc.log10(value1);
                sign_value1 = 1;
            } else if (value1 < 0) {
                log_value1 = MathFunc.log10(-value1);
                sign_value1 = -1;
            } else {
                log_value1 = ZERO_VALUE_LOG;
                sign_value1 = 0;
            }
            if (value2 > 0) {
                log_value2 = MathFunc.log10(value2);
                sign_value2 = 1;
            } else if (value2 < 0) {
                log_value2 = MathFunc.log10(-value2);
                sign_value2 = -1;
            } else {
                log_value2 = ZERO_VALUE_LOG;
                sign_value2 = 0;
            }

            if ((sign_value1 == sign_value2) || (sign_value1 == 0)
                    || (sign_value2 == 0)) {
                p = (log_value - log_value1) / (log_value2 - log_value1);
            } else { // center is +-1e-10
                if (sign_value == 1)
                    p = 1.0f - (log_value2 - log_value)
                            / (ZERO_VALUE_LIMIT + log_value1 + log_value2);
                else
                    p = (log_value1 - log_value)
                            / (ZERO_VALUE_LIMIT + log_value1 + log_value2);
            }
            if ((value1 == 0) && (value2 > 0) && (value > 0))
                p = p / 2f + 0.5f;
            if ((value1 < 0) && (value2 == 0) && (value < 0))
                p = p / 2f;

            for (int i = 0; i < 3; i++) {
                cross_point[i] = p * (p2[i] - p1[i]) + p1[i];
                // System.out.println("c "+cross_point[i]+" "+point1[i]+" "+point2[i]+
                // ")");
                // System.out.println("c "+cross_point[i]+" "+p1[i]+" "+p2[i]+
                // ")");
            }
        } else if ((value1 == value) && (value != value2)) {
            if (change) {
                rt = 3;
                cross_point[0] = point2[0];
                cross_point[1] = point2[1];
                cross_point[2] = point2[2];
            } else {
                rt = 2;
                cross_point[0] = point1[0];
                cross_point[1] = point1[1];
                cross_point[2] = point1[2];
            }
        } else if ((value1 != value) && (value == value2)) {
            if (change) {
                rt = 2;
                cross_point[0] = point1[0];
                cross_point[1] = point1[1];
                cross_point[2] = point1[2];
            } else {
                rt = 3;
                cross_point[0] = point2[0];
                cross_point[1] = point2[1];
                cross_point[2] = point2[2];
            }
        } else if ((value1 == value) && (value == value2)) {
            rt = 4;
            cross_point[0] = (p2[0] + p1[0]) / 2f + p1[0];
            cross_point[1] = (p2[1] + p1[1]) / 2f + p1[1];
            cross_point[2] = (p2[2] + p1[1]) / 2f + p1[2];
        }

        /******************************
         * System.out.println("rt "+rt+" "+ "v1  v2  v "+
         * value1+" "+value2+" "+value+ " l1 l2  l "+
         * log_value1+" "+log_value2+" "+log_value);
         * //System.out.println("s1 s2 s p "
         * +sign_value1+" "+sign_value2+" "+sign_value+" "+p);
         * 
         * if (rt!=0) { System.out.println("\nrt "+rt+" "+ "v1  v2  v "+
         * value1+" "+value2+" "+value); System.out.println("check ("+
         * p1[0]+" "+p1[1]+" "+p1[2]+") ("+ p2[0]+" "+p2[1]+" "+p2[2]+")");
         * System.out.println("cross ( "+cross_point[0]+" "+cross_point[1]+" "+
         * cross_point[2]+ ")"); }
         *****************************/

        return (rt);
    }

    public static void main(String argv[]) {

        float value1;
        float value2;
        float value;
        float point1[] = { 0f, 0f, 0f };
        float point2[] = { 1f, 0f, 0f };
        float cross_point[] = new float[3];
        int rt;

        if (argv.length == 3) {
            value1 = Float.parseFloat(argv[0]);
            value2 = Float.parseFloat(argv[1]);
            value = Float.parseFloat(argv[2]);
        } else {
            value1 = 1e-10f;
            value2 = 1f;
            value = 1e-2f;
        }

        rt = CrossPoint.get(value1, value2, value, point1, point2, cross_point);
        System.out.println("rt " + rt + " " + "v1  v2  v " + value1 + " "
                + value2 + " " + value);
        System.out.println("cross ( " + cross_point[0] + " " + cross_point[1]
                + " " + cross_point[2] + ")");

    }
}
