package cn.sagacloud.android.cadengine;

import android.graphics.Point;
import android.graphics.PointF;
import android.util.Log;

import java.util.List;

/**
 * Created by lihao.
 * Date: 2021/6/4
 */
public class Lasso {
    // polygon coordinates
    private float[] mPolyX, mPolyY;

    // number of size in polygon
    private int mPolySize;

    /**
     * default constructor
     *
     * @param px polygon coordinates X
     * @param py polygon coordinates Y
     * @param ps polygon sides count
     */
    public Lasso(float[] px, float[] py, int ps) {
        this.mPolyX = px;
        this.mPolyY = py;
        this.mPolySize = ps;
    }

    /**
     * constructor
     *
     * @param pointFs points list of the lasso
     */
    public Lasso(List<PointF> pointFs) {
        this.mPolySize = pointFs.size();
        this.mPolyX = new float[this.mPolySize];
        this.mPolyY = new float[this.mPolySize];

        for (int i = 0; i < this.mPolySize; i++) {
            this.mPolyX[i] = pointFs.get(i).x;
            this.mPolyY[i] = pointFs.get(i).y;
        }
        Log.d("lasso", "lasso size:" + mPolySize);
    }

    /**
     * check if this polygon contains the point.
     *
     * @param x point coordinate X
     * @param y point coordinate Y
     * @return point is in polygon flag
     */
    public boolean contains(float x, float y) {
        boolean result = false;
        for (int i = 0, j = mPolySize - 1; i < mPolySize; j = i++) {
            if ((mPolyY[i] < y && mPolyY[j] >= y)
                    || (mPolyY[j] < y && mPolyY[i] >= y)) {
                if (mPolyX[i] + (y - mPolyY[i]) / (mPolyY[j] - mPolyY[i])
                        * (mPolyX[j] - mPolyX[i]) < x) {
                    result = !result;
                }
            }
        }
        return result;
    }

    public static boolean isPolygonContainsPoint(List<PointF> mPoints, Point point) {
        int nCross = 0;
        for (int i = 0; i < mPoints.size(); i++) {
            PointF p1 = mPoints.get(i);
            PointF p2 = mPoints.get((i + 1) % mPoints.size());
            // 取多边形任意一个边,做点point的水平延长线,求解与当前边的交点个数
            // p1p2是水平线段,要么没有交点,要么有无限个交点
            if (p1.y == p2.y)
                continue;
            // point 在p1p2 底部 --> 无交点
            if (point.y < Math.min(p1.y, p2.y))
                continue;
            // point 在p1p2 顶部 --> 无交点
            if (point.y >= Math.max(p1.y, p2.y))
                continue;
            // 求解 point点水平线与当前p1p2边的交点的 X 坐标
            double x = (point.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;
            if (x > point.x) // 当x=point.x时,说明point在p1p2线段上
                nCross++; // 只统计单边交点
        }
        // 单边交点为偶数，点在多边形之外 ---
        return (nCross % 2 == 1);
    }
}
