Пример #1
0
        /// <summary>
        /// 创建内接圆
        /// </summary>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <param name="p3"></param>
        /// <returns></returns>
        public static Circle2D CreateInscribedCircle(Double2 p1, Double2 p2, Double2 p3)
        {
            // 排除三点共线
            Double2 diff1 = p2 - p1;
            Double2 diff2 = p3 - p1;

            if (diff1 == Double2.zero || diff2 == Double2.zero)
            {
                return(null);
            }

            double value = Double2.Cross(diff1, diff2);

            if (System.Math.Abs(value) < MathUtil.kEpsilon)
            {
                return(null);
            }
            // 2垂直平分线就是圆心。
            Double2 mid1dir = diff1.normalized + diff2.normalized;
            Double2 mid2dir = (p3 - p2).normalized - diff1.normalized;
            Line2D  line1   = new Line2D(p1, mid1dir);
            Line2D  line2   = new Line2D(p2, mid2dir);

            Double2 center = Double2.zero;

            if (line1.GetIntersectPoint(line2, ref center) == true)
            {
                double radius = line1.CalcDistance(center);
                return(new Circle2D(center, radius));
            }
            else
            {
                return(null);
            }
        }
Пример #2
0
        /// <summary>
        /// 创建外接圆
        /// </summary>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <param name="p3"></param>
        /// <returns></returns>
        public static Circle2D CreateCircumCircle(Double2 p1, Double2 p2, Double2 p3)
        {
            // 排除三点共线
            Double2 diff1 = p2 - p1;
            Double2 diff2 = p3 - p1;

            if (diff1 == Double2.zero || diff2 == Double2.zero)
            {
                return(null);
            }

            double value = Double2.Cross(diff1, diff2);

            if (System.Math.Abs(value) < MathUtil.kEpsilon)
            {
                return(null);
            }
            // 2垂直平分线就是圆心。
            Double2 mid1  = p1 + diff1 * 0.5f;
            Double2 mid2  = p1 + diff2 * 0.5f;
            Line2D  line1 = new Line2D(mid1, Double2.Perpendicular(diff1));
            Line2D  line2 = new Line2D(mid2, Double2.Perpendicular(diff2));

            Double2 center = Double2.zero;

            if (line1.GetIntersectPoint(line2, ref center) == true)
            {
                double radius = (center - p1).magnitude;
                return(new Circle2D(center, radius));
            }
            else
            {
                return(null);
            }
        }
Пример #3
0
        /// <summary>
        /// 与线段的关系
        /// </summary>
        /// <param name="line"></param>
        /// <returns></returns>
        public LineRelation CheckLineRelation(LineSegment2D line)
        {
            // 快速排斥实验,后续优化实现
            // 进行跨立实验
            double r1     = Double2.Cross(this.normalizedDir, line.startPoint - this.startPoint);
            double r2     = Double2.Cross(this.normalizedDir, line.endPoint - this.startPoint);
            double cross1 = r1 * r2;
            double t1     = Double2.Cross(line.normalizedDir, this.startPoint - line.startPoint);
            double t2     = Double2.Cross(line.normalizedDir, this.endPoint - line.startPoint);
            double cross2 = t1 * t2;

            if (cross1 > 0 || cross2 > 0)
            {
                return(LineRelation.Detach);
            }
            else if (cross1 == 0 || cross2 == 0)
            {
                if (cross1 == 0)
                {
                    if (r1 == 0)
                    {
                        if (Double2.Dot(line.startPoint - this.startPoint, line.startPoint - this.endPoint) <= 0)
                        {
                            return(LineRelation.Intersect);
                        }
                    }
                    if (r2 == 0)
                    {
                        if (Double2.Dot(line.endPoint - this.startPoint, line.endPoint - this.endPoint) <= 0)
                        {
                            return(LineRelation.Intersect);
                        }
                    }
                }
                if (cross2 == 0)
                {
                    if (t1 == 0)
                    {
                        if (Double2.Dot(this.startPoint - line.startPoint, this.startPoint - line.endPoint) <= 0)
                        {
                            return(LineRelation.Intersect);
                        }
                    }
                    if (t2 == 0)
                    {
                        if (Double2.Dot(this.endPoint - line.startPoint, this.endPoint - line.endPoint) <= 0)
                        {
                            return(LineRelation.Intersect);
                        }
                    }
                }
                return(LineRelation.Detach);
            }
            return(LineRelation.Intersect);
        }
Пример #4
0
        /// <summary>
        /// 多边形决策。
        /// </summary>
        /// <param name="ls2d"></param>
        /// <param name="targetPoint"></param>
        /// <param name="middlePoint"></param>
        public static bool GetNearPointInEdge(Polygon2D poly, Polygon2D mainPoly_, Polygon2D diffPoly_, Point2D ls2d, Double2 curPoint, List <Double3> listMiddlePoint, ref Double3 nextPoint)
        {
            if (listMiddlePoint == null || listMiddlePoint.Count == 0)
            {
                return(false);
            }
            else
            {
                int k = 0;
                if (curPoint != ls2d.startPoint)
                {
                    for (int i = listMiddlePoint.Count - 1; i >= 0; i--)
                    {
                        // 找到了
                        Double2 temp = new Double2(listMiddlePoint[i].x, listMiddlePoint[i].y);
                        Double2 diff = curPoint - temp;
                        bool    ret  = System.Math.Abs(diff.x) <= MathUtil.kEpsilon && System.Math.Abs(diff.y) <= MathUtil.kEpsilon;

                        if (ret == true)
                        {
                            if (i < listMiddlePoint.Count - 1)
                            {
                                k = i + 1;
                                break;
                            }
                            else
                            {
                                return(false);
                            }
                        }
                    }
                }
                else
                {
                    // 过重复点
                    while (k < listMiddlePoint.Count - 1 && (listMiddlePoint[k].x == listMiddlePoint[k + 1].x && listMiddlePoint[k].y == listMiddlePoint[k + 1].y))
                    {
                        k++;
                    }
                }
                Point2D otherEdge = PolygonBool.GetOtherEdge(poly, mainPoly_, diffPoly_, (int)listMiddlePoint[k].z);
                if (Double2.Cross(ls2d.endPoint - ls2d.startPoint, otherEdge.endPoint - otherEdge.startPoint) == 0 && k < listMiddlePoint.Count - 1)
                {
                    k++;
                }
                //
                nextPoint = listMiddlePoint[k];
                if (curPoint == new Double2(nextPoint.x, nextPoint.y))
                {
                    return(false);
                }
                return(true);
            }
        }
Пример #5
0
        public bool ContainsPoint(Double2 p)
        {
            // Pulled from https://stackoverflow.com/a/20861130
            // Barycentric coordinates
            var s = C.Cross(A) + p.Cross(C - A);
            var t = A.Cross(B) + p.Cross(A - B);

            if ((s < 0) != (t < 0))
            {
                return(false);
            }

            // Area
            var a = B.Cross(C) + A.Cross(B - C);

            if (a < 0)
            {
                return(s <= 0 && s + t >= a);
            }
            else
            {
                return(s >= 0 && s + t <= a);
            }
        }
Пример #6
0
        /// <summary>
        /// 圆弧上的2个向量夹角
        /// </summary>
        /// <param name="from"></param>
        /// <param name="to"></param>
        /// <returns></returns>
        private double SignedAngleInCircle(Double2 from, Double2 to, double r)
        {
            // [-PI / 2,  PI /2]  Asin
            // [0,  PI]  acos
            double sqrRadius = r * r;
            double sinValue  = Double2.Cross(from, to) / sqrRadius;

            sinValue = System.Math.Min(sinValue, 1.0f);
            sinValue = System.Math.Max(sinValue, -1.0f);
            double cosValue = Double2.Dot(from, to) / sqrRadius;

            cosValue = System.Math.Min(cosValue, 1.0f);
            cosValue = System.Math.Max(cosValue, -1.0f);
            return(MathFunc.GetAngle(cosValue, sinValue));
        }
Пример #7
0
 /// <summary>
 /// 计算某个顶点叉乘。
 /// </summary>
 /// <param name="index"></param>
 /// <returns></returns>
 private double CalcRotateValue(int index)
 {
     if (index < 0 || index >= this.pointArr.Length)
     {
         return(0);
     }
     if (index > 0)
     {
         return(Double2.Cross(GetEdge(index - 1).normalizedDir, GetEdge(index).normalizedDir));
     }
     else if (index == 0)
     {
         return(Double2.Cross(GetEdge(this.pointArr.Length - 1).normalizedDir, GetEdge(0).normalizedDir));
     }
     return(0);
 }
Пример #8
0
        private static Double2[] AdjustCircleLine(ref Double2 c1, ref double r1, Double2 n1, Double2 c, Double2 v)
        {
            // Negate if necessary, so we are working with positive values of the radius
            bool neg1 = r1 < 0;

            if (neg1)
            {
                r1 = -r1; n1 = -n1;
            }

            Double2 pt;

            // Get the coefficients
            var rot = v.Normalized;
            var h   = (c - c1).Cross(rot);
            var k   = n1.Cross(rot);

            // If k = -1, there is no solution
            if (RoughlyEquals(k, -1))
            {
                pt = new Double2(double.NaN, double.NaN);
            }
            else
            {
                // Get the solution
                var l = (h - r1) / (k + 1);

                r1 += l;
                c1 += n1 * l;

                // Get the solution
                pt = c1 - c - rot * (c1 - c).Dot(rot);
            }

            // Return back their signs
            if (neg1)
            {
                r1 = -r1;
            }

            if (double.IsNaN(pt.X))
            {
                return(new Double2[0]);
            }
            return(new[] { pt, pt });
        }
Пример #9
0
        /// <summary>
        /// 判断指定的点,在夹角内。不包括在边上。
        /// </summary>
        /// <param name="target"></param>
        /// <param name="startPoint"></param>
        /// <param name="indir"></param>
        /// <param name="outdir"></param>
        /// <returns></returns>
        private static bool CheckPointInCorns(Double2 target, Double2 startPoint, Double2 indir, Double2 outdir)
        {
            Double2 diff = target - startPoint;

            if (diff == Double2.zero)
            {
                return(false);
            }

            double ret = Double2.Cross(outdir, diff) * Double2.Cross(indir.normalized, diff);

            if (ret < 0)
            {
                // 添加异常处理,防止在反方向

                /*if (Float2.Dot(diff, indir.normalized + outdir) < 0)
                 *  return false;
                 * else return true;*/
                return(true);
            }
            else if (ret == 0)
            {
                if (Double2.Dot(diff, indir) <= 0)
                {
                    return(false);
                }

                if (indir.sqrMagnitude < diff.sqrMagnitude)
                {
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
            return(false);
        }
Пример #10
0
 public double WindingRelativeTo(Double2 v) => Winding - v.Cross(At(1) - At(0));
Пример #11
0
 /// <summary>
 /// 获取交点
 /// </summary>
 /// <param name="line"></param>
 /// <param name="intersectPoint"></param>
 /// <returns></returns>
 public bool GetIntersectPoint(LineSegment2D line, ref Double2 intersectStartPoint, ref Double2 intersectEndPoint)
 {
     if (CheckLineRelation(line) == LineRelation.Intersect)
     {
         Double2 aixsVector = AixsVector(line.startPoint);
         double  distance   = aixsVector.magnitude;
         if (distance == 0)
         {
             if (Double2.Cross(line.normalizedDir, this.normalizedDir) == 0)
             {
                 if (Double2.Dot(line.normalizedDir, this.normalizedDir) > 0)
                 {
                     if (Double2.Dot(line.normalizedDir, this.startPoint - line.startPoint) > 0)
                     {
                         intersectStartPoint = this.startPoint;
                     }
                     else
                     {
                         intersectStartPoint = line.startPoint;
                     }
                     //
                     if (Double2.Dot(line.normalizedDir, this.endPoint - line.endPoint) > 0)
                     {
                         intersectEndPoint = line.endPoint;
                     }
                     else
                     {
                         intersectEndPoint = this.endPoint;
                     }
                 }
                 else
                 {
                     if (Double2.Dot(line.normalizedDir, this.startPoint - line.endPoint) > 0)
                     {
                         intersectEndPoint = line.endPoint;
                     }
                     else
                     {
                         intersectEndPoint = line.startPoint;
                     }
                     //
                     if (Double2.Dot(line.normalizedDir, this.endPoint - line.startPoint) > 0)
                     {
                         intersectStartPoint = this.endPoint;
                     }
                     else
                     {
                         intersectStartPoint = line.startPoint;
                     }
                 }
             }
             else
             {
                 intersectStartPoint = line.startPoint;
                 intersectEndPoint   = line.startPoint;
             }
             return(true);
         }
         else
         {
             if (CalcDistance(line.endPoint) == 0)
             {
                 intersectStartPoint = line.endPoint;
                 intersectEndPoint   = intersectStartPoint;
                 return(true);
             }
             //
             double dot = Double2.Dot(aixsVector.normalized, line.normalizedDir);
             if (dot == 0)
             {
                 return(false);
             }
             else
             {
                 intersectStartPoint = line.startPoint - distance / dot * line.normalizedDir;
                 intersectEndPoint   = intersectStartPoint;
                 return(true);
             }
         }
     }
     return(false);
 }
Пример #12
0
        /// <summary>
        /// 求多边形的和。
        /// </summary>
        /// <param name="mainPoly">逆时针序列</param>
        /// <param name="addPoly">逆时针序列</param>
        /// <returns></returns>
        public static Double2[] CalcPoly(Double2[] mainPoly, Double2[] addPoly)
        {
            if (mainPoly == null || mainPoly.Length < 3)
            {
                return(null);
            }
            if (addPoly == null || addPoly.Length < 3)
            {
                return(mainPoly);
            }
            //
            Polygon2D mainPoly_ = new Polygon2D(mainPoly);
            Polygon2D diffPoly_ = new Polygon2D(addPoly);

            // 获取边上的交点
            List <Double3>[] mainPolyIntersectArray = new List <Double3> [mainPoly_.GetEdgeNum()];
            List <Double3>[] addPolyIntersectArray  = new List <Double3> [diffPoly_.GetEdgeNum()];
            PolygonBool.GetAllEdgeInterSectPoint(mainPoly_, diffPoly_, ref mainPolyIntersectArray, ref addPolyIntersectArray);

            // 没有交点直接返回呗
            bool CheckIntersect = false;

            foreach (List <Double3> list in mainPolyIntersectArray)
            {
                if (list != null && list.Count > 0)
                {
                    CheckIntersect = true;
                    break;
                }
            }
            if (CheckIntersect == false)
            {
                PolygonBool.ClearPolyIntersectArray(ref mainPolyIntersectArray, ref addPolyIntersectArray);
                return(mainPoly);
            }
            // 有交点的处理
            List <Double2> listPoint = new List <Double2>();
            int            curedge   = 0;
            Double2        curPoint  = Double2.zero;

            // 查找在diffpoly外的一个顶点。
            if (PolygonBool.FindOutDiffPointPoint(mainPoly_, diffPoly_, ref curPoint, ref curedge) == false)
            {
                return(mainPoly);
            }
            // 初始化数据。
            Polygon2D poly = mainPoly_;

            List <Double3>[] curPolyIntersectArray = mainPolyIntersectArray;

            while (poly != null && curedge >= 0 && curedge < poly.GetEdgeNum())
            {
                Point2D ls2d = poly.GetSimpleEdge(curedge);

                if (PolygonBool.AddPoint(listPoint, curPoint) == false)
                {
                    break;
                }
                Double3 nextPoint = Double3.zero;
                bool    ret       = PolygonBool.GetNearPointInEdge(poly, mainPoly_, diffPoly_, ls2d, curPoint, curPolyIntersectArray[curedge], ref nextPoint);
                if (ret == false)
                {
                    curedge++;
                    if (curedge >= poly.GetEdgeNum())
                    {
                        curedge = 0;
                    }
                    curPoint = poly.GetEdge(curedge).startPoint;
                }
                else // 则需要交换了。
                {
                    Point2D otherEdge = PolygonBool.GetOtherEdge(poly, mainPoly_, diffPoly_, (int)nextPoint.z);

                    if (Double2.Cross(ls2d.endPoint - ls2d.startPoint, otherEdge.endPoint - otherEdge.startPoint) <= 0)  // 进一步判断是否需要更换
                    {
                        curPoint = new Double2(nextPoint.x, nextPoint.y);
                        curedge  = (int)nextPoint.z;
                        PolygonBool.ExChangePoly(ref poly, mainPoly_, diffPoly_, ref curPolyIntersectArray, mainPolyIntersectArray, addPolyIntersectArray);
                    }
                    else // 不需要变换了。
                    {
                        curedge++;
                        if (curedge >= poly.GetEdgeNum())
                        {
                            curedge = 0;
                        }
                        curPoint = poly.GetEdge(curedge).startPoint;
                    }
                }
            }
            PolygonBool.ClearPolyIntersectArray(ref mainPolyIntersectArray, ref addPolyIntersectArray);
            return(listPoint.ToArray());
        }