/// <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); } }
/// <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); } }
/// <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); }
/// <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); } }
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); } }
/// <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)); }
/// <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); }
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 }); }
/// <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); }
public double WindingRelativeTo(Double2 v) => Winding - v.Cross(At(1) - At(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); }
/// <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()); }