unity 简单的四边形位置矫正

 

此功能将右边的四边行内的坐标点转换成左侧的矩形坐标点

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Calibration : MonoBehaviour
{
    
    [Header("四边形内要校准的点")]
    public Vector2 PointsToBeCalibratedInQuadrilateral;
    
    [Header("四边形左上边点")]
    public Vector2 UpperLeftPointOfQuadrilateral;
    
    [Header("四边形左下边点")]
    public Vector2 LowerLeftPointOfQuadrilateral;
    
    [Header("四边形右上边点")]
    public Vector2 UpperRightPointOfQuadrilateral;
    
    [Header("四边形右下边点")]
    public Vector2 LowerIightPointOfQuadrilateral;
    
    [Header("要缩放的大小")]
    public Vector2 ZoomSize;
    
    [Header("矫正后位置")]
    public Vector2 CorrectedPosition;
    
    [Header("四边形焦点")]
    public Vector2 QuadrilateralFocus;


  

    
    void Start()
    {
        


        QuadrilateralFocus = CrossPoint(UpperLeftPointOfQuadrilateral, LowerIightPointOfQuadrilateral, LowerLeftPointOfQuadrilateral, UpperRightPointOfQuadrilateral);
    }
   
    public  Vector2  UPdateVector(Vector2 vector )
    {
       
      
        PointsToBeCalibratedInQuadrilateral = vector;

        StartCalibration();
        return CorrectedPosition;
       
    }
    //开始校准
    void StartCalibration() {
        if (IsThePointWithinTheQuadrilateral(PointsToBeCalibratedInQuadrilateral))
        {
           // Debug.Log("在四边行内");
            if (PointsToBeCalibratedInQuadrilateral == QuadrilateralFocus)
            {
              //  Debug.Log("点在中点");
                CorrectedPosition = QuadrilateralFocus;
            }
            else
            {

                if (IsThePointOnTheDiagonal(PointsToBeCalibratedInQuadrilateral, UpperLeftPointOfQuadrilateral, LowerIightPointOfQuadrilateral))
                {
                 //   Debug.Log("在左上到右下的对角线上");
                   
                    float Di1 = Vector2.Distance(UpperLeftPointOfQuadrilateral, QuadrilateralFocus);
                    float Di2 = Vector2.Distance(PointsToBeCalibratedInQuadrilateral, UpperLeftPointOfQuadrilateral);
                    if (Di1 > Di2)
                    {
                     //   Debug.Log("点在左上半段线上");
                        float BiLi = Di1 / Di2;
                        Vector2 FdZ = ZoomSize / 2;
                        Vector2 fanhui = new Vector2(FdZ.x / BiLi, ZoomSize.y - (FdZ.y / BiLi));
                        CorrectedPosition = fanhui;
                        
                    }
                    else
                    {
                       // Debug.Log("点在右下半段线上");
                        float Di3 = Vector2.Distance(LowerIightPointOfQuadrilateral, QuadrilateralFocus);
                        float Di4 = Vector2.Distance(PointsToBeCalibratedInQuadrilateral, LowerIightPointOfQuadrilateral);
                        float BiLi = Di3 / Di4;
                        Vector2 FdZ = ZoomSize / 2;
                        Vector2 fanhui = new Vector2(ZoomSize.x - (FdZ.x / BiLi), FdZ.y / BiLi);
                        CorrectedPosition = fanhui;
                        
                    }

                }
                else
                {
                    if (IsThePointOnTheDiagonal(PointsToBeCalibratedInQuadrilateral, UpperRightPointOfQuadrilateral, LowerLeftPointOfQuadrilateral))
                    {
                       // Debug.Log(" 在左下到右上的对角线上");

                        float Di1 = Vector2.Distance(LowerLeftPointOfQuadrilateral, QuadrilateralFocus);
                        float Di2 = Vector2.Distance(PointsToBeCalibratedInQuadrilateral, LowerLeftPointOfQuadrilateral);
                        if (Di1 > Di2)
                        {
                          //  Debug.Log("点在左下半段线上");
                            float BiLi = Di1 / Di2;
                            Vector2 FdZ = ZoomSize / 2;
                            Vector2 fanhui = new Vector2(FdZ.x / BiLi, FdZ.y / BiLi);
                            CorrectedPosition = fanhui;
                           

                        }
                        else
                        {
                          //  Debug.Log("点在右上半段线上");
                            float Di3 = Vector2.Distance(UpperRightPointOfQuadrilateral, QuadrilateralFocus);
                            float Di4 = Vector2.Distance(PointsToBeCalibratedInQuadrilateral, UpperRightPointOfQuadrilateral);
                            float BiLi = Di3 / Di4;
                            Vector2 FdZ = ZoomSize / 2;
                            Vector2 fanhui = new Vector2(ZoomSize.x - (FdZ.x / BiLi), ZoomSize.y - (FdZ.y / BiLi));
                            CorrectedPosition = fanhui;
                            
                        }





                    }
                    else
                    {
                        if (InTriangleOrNot(PointsToBeCalibratedInQuadrilateral, QuadrilateralFocus, LowerLeftPointOfQuadrilateral, UpperLeftPointOfQuadrilateral))
                        {

                          //  Debug.Log("在左侧三角形内");

                            InsideLeftTriangle();



                        }
                        else
                        {
                          //  Debug.Log("没有在对角线上");
                            if (InTriangleOrNot(PointsToBeCalibratedInQuadrilateral, QuadrilateralFocus, UpperLeftPointOfQuadrilateral, UpperRightPointOfQuadrilateral))
                            {
                            //    Debug.Log("在上侧三角形内");
                                InsideTheUpperTriangle();
                            }
                            else
                            {
                                if (InTriangleOrNot(PointsToBeCalibratedInQuadrilateral, QuadrilateralFocus, UpperRightPointOfQuadrilateral, LowerIightPointOfQuadrilateral))
                                {
                                //    Debug.Log("在右侧三角形内");
                                    InsideRightTriangle();
                                }
                                else
                                {

                                    if (InTriangleOrNot(PointsToBeCalibratedInQuadrilateral, QuadrilateralFocus, LowerIightPointOfQuadrilateral, LowerLeftPointOfQuadrilateral))
                                    {

                                     //   Debug.Log("在下测三角形内");
                                        InsideTheLowerTriangle();
                                    }
                                }


                            }

                        }

                    }



                }
            }

        }
        else {
         //   Debug.Log("没有在四边形内");
        }

    }



    
    //四边形中心点
    void Zhong() {
        //已知直线上的两点P1(X1,Y1) P2(X2,Y2), P1 P2两点不重合。  故直线方程为(y2-y1)x+(x1-x2)y+x2y1-x1y2=0

        // 左上到右下 方程
        float a= LowerIightPointOfQuadrilateral.y - UpperLeftPointOfQuadrilateral.y;
        
        float b= UpperLeftPointOfQuadrilateral.x - LowerIightPointOfQuadrilateral.x;
       
        float c = (LowerIightPointOfQuadrilateral.x * UpperLeftPointOfQuadrilateral.y) - (UpperLeftPointOfQuadrilateral.x * LowerIightPointOfQuadrilateral.y);
        
        // 所以直线AX+BY+C=0

        //右上到左下方程
        float d = UpperRightPointOfQuadrilateral.y - LowerLeftPointOfQuadrilateral.y;
        float e = LowerLeftPointOfQuadrilateral.x - UpperRightPointOfQuadrilateral.x;
        float f = (UpperRightPointOfQuadrilateral.x * LowerLeftPointOfQuadrilateral.y) - (LowerLeftPointOfQuadrilateral.x * UpperRightPointOfQuadrilateral.y);


        float y = ((-(c*d/a/e)-(-f/e))) / ((b * d / a / e) - 1);
        float x = (-c / a) - (b / a * y);
        
        QuadrilateralFocus.x = x;
        QuadrilateralFocus.y = y;

       
    }

    


    // 点是否在三角形内
    bool InTriangleOrNot(Vector3 p, Vector3 a, Vector3 b, Vector3 c)
    {
        Vector3 pa = a - p;
        Vector3 pb = b - p;
        Vector3 pc = c - p;
        Vector3 pab = Vector3.Cross(pa, pb);
        Vector3 pbc = Vector3.Cross(pb, pc);
        Vector3 pca = Vector3.Cross(pc, pa);

        float d1 = Vector3.Dot(pab, pbc);
        float d2 = Vector3.Dot(pab, pca);
        float d3 = Vector3.Dot(pbc, pca);

        if (d1 > 0 && d2 > 0 && d3 > 0) return true;
        return false;

    }
    //点是否在对角线上
    bool IsThePointOnTheDiagonal(Vector2 p ,Vector2 a, Vector2 b) {
        float A = a.y - b.y;
        float B = b.x - a.x;
        float C = (a.x * b.y) - (b.x * a.y);
        if ((A * p.x) + (B * p.y) + C == 0) {
            return true;
        }

        return false;
    }
    // 点是否在四边形内
    bool IsThePointWithinTheQuadrilateral(Vector2 p ) {
       
        Vector3 pa = LowerLeftPointOfQuadrilateral - p;
        Vector3 pb = UpperLeftPointOfQuadrilateral - p;
        Vector3 pc = UpperRightPointOfQuadrilateral - p;
        Vector3 pd = LowerIightPointOfQuadrilateral - p;
        Vector3 pab = Vector3.Cross(pa, pb);
        Vector3 pbc = Vector3.Cross(pb, pc);
        Vector3 pcd = Vector3.Cross(pc, pd);
        Vector3 pca = Vector3.Cross(pd, pa);

        float d1 = Vector3.Dot(pab, pbc);
        float d2 = Vector3.Dot(pab, pcd);
        float d3 = Vector3.Dot(pab, pca);
        float d4 = Vector3.Dot(pbc, pcd);
        float d5 = Vector3.Dot(pbc, pca);
        float d6 = Vector3.Dot(pcd, pca);
        // float d4 = Vector3.Dot(pbc, pca);
        if (d1 > 0 && d2 > 0 && d3 > 0 && d4 > 0 && d5 > 0 && d6 > 0)
        {
            return true;
        }

        return false;
    }
    //计算三角形面积
    float CalculateTriangleArea(Vector2 a, Vector2 b, Vector2 c)
    {
        //海伦公式:p=(a+b+c)/2; S = √[p(p-a)(p-b)(p-c)]
        float dab = Vector2.Distance(a, b);
        float dac = Vector2.Distance(a, c);
        float dbc = Vector2.Distance(b, c);
        float half = (dab + dac + dbc) / 2;
        return Mathf.Sqrt(half * (half - dab) * (half - dac) * (half - dbc));

    }


  //左侧三角形内
    void InsideLeftTriangle() {
       

        Vector2 Jiaodian = CrossPoint(LowerLeftPointOfQuadrilateral, UpperLeftPointOfQuadrilateral, QuadrilateralFocus, PointsToBeCalibratedInQuadrilateral);

        float Di1 = Vector2.Distance(Jiaodian, LowerLeftPointOfQuadrilateral);
        float Di2 = Vector2.Distance(LowerLeftPointOfQuadrilateral, UpperLeftPointOfQuadrilateral);
        float BiLi = Di2 / Di1;

        Vector2 Fdjiaodian = new Vector2(0, ZoomSize.y / BiLi);

        Vector2 FdZ = ZoomSize / 2;

        float Di3 = Vector2.Distance(QuadrilateralFocus, Jiaodian);
        float Di4 = Vector2.Distance(PointsToBeCalibratedInQuadrilateral, Jiaodian);
        float BiLi1 = Di3 / Di4;

        float fx = (FdZ.x - Fdjiaodian.x) / BiLi1;
        float fy = (FdZ.y - Fdjiaodian.y) / BiLi1+Fdjiaodian.y;

        Vector2 fanhui = new Vector2(fx, fy); CorrectedPosition = fanhui;
        

    }
    //右侧三角形内
    void InsideRightTriangle()
    {


        Vector2 Jiaodian = CrossPoint(LowerIightPointOfQuadrilateral, UpperRightPointOfQuadrilateral, QuadrilateralFocus, PointsToBeCalibratedInQuadrilateral);

        float Di1 = Vector2.Distance(Jiaodian, LowerIightPointOfQuadrilateral);
        float Di2 = Vector2.Distance(LowerIightPointOfQuadrilateral, UpperRightPointOfQuadrilateral);
        float BiLi = Di2 / Di1;

        Vector2 Fdjiaodian = new Vector2(ZoomSize.x, ZoomSize.y / BiLi);

        Vector2 FdZ = ZoomSize / 2;

        float Di3 = Vector2.Distance(QuadrilateralFocus, Jiaodian);
        float Di4 = Vector2.Distance(PointsToBeCalibratedInQuadrilateral, Jiaodian);
        float BiLi1 = Di3 / Di4;

        float fx = (FdZ.x - Fdjiaodian.x) / BiLi1 + ZoomSize.x;
        float fy = (FdZ.y - Fdjiaodian.y) / BiLi1 + Fdjiaodian.y;

        Vector2 fanhui = new Vector2(fx, fy); CorrectedPosition = fanhui;


    }
    //上侧三角形内
    void InsideTheUpperTriangle() {
       
        Vector2 Jiaodian = CrossPoint(UpperLeftPointOfQuadrilateral,UpperRightPointOfQuadrilateral,QuadrilateralFocus,PointsToBeCalibratedInQuadrilateral);
        
        float Di1 = Vector2.Distance(Jiaodian, UpperLeftPointOfQuadrilateral);
        float Di2 = Vector2.Distance(UpperRightPointOfQuadrilateral, UpperLeftPointOfQuadrilateral);
        float BiLi = Di2 / Di1;

        Vector2 Fdjiaodian = new Vector2(ZoomSize.x/BiLi, ZoomSize.y);

        

        Vector2 FdZ = ZoomSize / 2;

        float Di3 = Vector2.Distance(QuadrilateralFocus, Jiaodian);
        float Di4 = Vector2.Distance(PointsToBeCalibratedInQuadrilateral, Jiaodian);
        float BiLi1 = Di3 / Di4;

        float fx = ( FdZ.x -Fdjiaodian.x ) / BiLi1+Fdjiaodian.x;
        float fy = ZoomSize.y-( (FdZ.y) / BiLi1) ;
        Vector2 fanhui = new Vector2(fx, fy); CorrectedPosition = fanhui;
        
    }
    //下侧三角形内
    void InsideTheLowerTriangle()
    {

        Vector2 Jiaodian = CrossPoint(LowerLeftPointOfQuadrilateral, LowerIightPointOfQuadrilateral, QuadrilateralFocus, PointsToBeCalibratedInQuadrilateral);

        float Di1 = Vector2.Distance(Jiaodian, LowerLeftPointOfQuadrilateral);
        float Di2 = Vector2.Distance(LowerIightPointOfQuadrilateral, LowerLeftPointOfQuadrilateral);
        float BiLi = Di2 / Di1;

        Vector2 Fdjiaodian = new Vector2(ZoomSize.x / BiLi, 0);



        Vector2 FdZ = ZoomSize / 2;

        float Di3 = Vector2.Distance(QuadrilateralFocus, Jiaodian);
        float Di4 = Vector2.Distance(PointsToBeCalibratedInQuadrilateral, Jiaodian);
        float BiLi1 = Di3 / Di4;

        float fx = (FdZ.x -Fdjiaodian.x) / BiLi1+Fdjiaodian.x ;
        float fy = (FdZ.y) / BiLi1;
        Vector2 fanhui = new Vector2(fx, fy); CorrectedPosition = fanhui;
        
    }

    



    // 两条直线焦点
    Vector2 CrossPoint(Vector2 line1, Vector2 line2, Vector2 line3, Vector2 line4) //交点
{
    float x_member, x_denominator, y_member, y_denominator;
    Vector2 cross_point;
    x_denominator = line4.x* line2.y - line4.x* line1.y - line3.x* line2.y + line3.x* line1.y
        - line2.x* line4.y + line2.x* line3.y + line1.x* line4.y - line1.x* line3.y;

    x_member = line3.y* line4.x*line2.x - line4.y* line3.x* line2.x - line3.y* line4.x* line1.x + line4.y* line3.x* line1.x
        - line1.y* line2.x* line4.x + line2.y* line1.x* line4.x + line1.y* line2.x* line3.x - line2.y* line1.x* line3.x;

    if (x_denominator == 0)
        cross_point.x = 0;
    else
        cross_point.x = x_member / x_denominator;

    y_denominator = line4.y* line2.x - line4.y* line1.x - line3.y* line2.x + line1.x* line3.y
        - line2.y* line4.x + line2.y* line3.x + line1.y* line4.x - line1.y* line3.x;

    y_member = -line3.y* line4.x*line2.y + line4.y* line3.x* line2.y + line3.y* line4.x* line1.y - line4.y* line3.x* line1.y
        + line1.y* line2.x* line4.y - line1.y* line2.x* line3.y - line2.y* line1.x* line4.y + line2.y* line1.x* line3.y;

    if (y_denominator == 0)
        cross_point.y = 0;
    else
        cross_point.y = y_member / y_denominator;

    return cross_point;  //平行返回(0,0)
}

}

使用方法,  先要设置号四边形的四个顶点坐标,   和要缩放的大小,   之后调用 Vector2  UPdateVector(Vector2 vector )        传入四边形内点的位置。

 

posted @ 2019-10-24 17:20  GP19  阅读(660)  评论(0)    收藏  举报