public void Initialize(float scale) { mScale = scale; mArea = GeoPolygonUtils.CalcualetArea(mPolygonData); if (mArea < 0) { mPolygonData.Reverse(); mArea = -mArea; } mAABB = GeoPolygonUtils.CalculateAABB(mPolygonData); mMaxSize = mAABB.mMax - mAABB.mMin; mIsConvex = IsAllConvex(); Decompose(); mLeftRectangle.Clear(); }
public static List <Vector3> CalculateConvexHull(List <Vector3> vertices, bool use2d, int ignore = 1) { List <Vector3> temp = new List <Vector3>(); if (use2d) { int x = 0; int y = 1; if (ignore == 0) { x = 1; y = 2; } else if (ignore == 1) { x = 0; y = 2; } else { x = 0; y = 1; } List <Vector2> temp2 = new List <Vector2>(); foreach (Vector3 v in vertices) { temp2.Add(new Vector2(v[x], v[y])); } temp2 = JarvisConvex.BuildHull(temp2); GeoPolygonUtils.ReverseIfCW(ref temp2); foreach (Vector2 v in temp2) { temp.Add(vertices.Find((Vector3 v3) => { return(v3[x] == v[0] && v3[y] == v[1]); })); } } else { temp = QuickHull.BuildHull(vertices); } return(temp); }
private static void UpdateEdge(HalfEdge edgeToRemove, KeyedPriorityQueue <int, HalfEdge, float> priorityQueue, HashSet <EdgeID> deletedEdgeSet, List <Vector2> pointList) { HalfEdge left = GetUndeletedLeft(edgeToRemove, deletedEdgeSet); HalfEdge right = GetUndeletedRight(edgeToRemove, deletedEdgeSet); HalfEdge reLeft = RepresentActive(left); if (priorityQueue.Contain(reLeft.mKey)) { // Check if this is still removable HalfEdge leftOfLeft = GetUndeletedLeft(left.mPartner, deletedEdgeSet); if ((leftOfLeft.mPartner != null && (leftOfLeft.mPartner.mKey == right.mKey || leftOfLeft.mPartner.mKey == edgeToRemove.mKey)) || !GeoPolygonUtils.IsConvex(pointList[edgeToRemove.mIndex], pointList[right.mNext.mIndex], pointList[leftOfLeft.mIndex])) { priorityQueue.Remove(reLeft.mKey); } else { // Need to update the priority float pri = GetSmallestAdjacentAngleOnEdge(left, deletedEdgeSet, pointList); priorityQueue.Remove(reLeft.mKey); priorityQueue.Enqueue(reLeft.mKey, reLeft, pri); } } HalfEdge reRight = RepresentActive(right); if (priorityQueue.Contain(reRight.mKey)) { HalfEdge rightOfRight = GetUndeletedRight(right, deletedEdgeSet); if ((rightOfRight.mPartner != null && (rightOfRight.mPartner.mKey == left.mKey || rightOfRight.mKey == edgeToRemove.mKey)) || !GeoPolygonUtils.IsConvex(pointList[edgeToRemove.mIndex], pointList[rightOfRight.mNext.mIndex], pointList[left.mIndex])) { priorityQueue.Remove(reRight.mKey); } else { priorityQueue.Remove(reRight.mKey); priorityQueue.Enqueue(reRight.mKey, reRight, GetSmallestAdjacentAngleOnEdge(right, deletedEdgeSet, pointList)); } } }
private void RemovePointsInPolygon(List <Vector2> innerPoly) { List <Vector2> temp = new List <Vector2>(); temp.AddRange(innerPoly); GeoPolygonUtils.ReverseIfCW(ref temp); GeoPointsArray2 poly = new GeoPointsArray2(temp); List <int> removeIndex = new List <int>(); for (int i = 0; i < mCenterList.Count; ++i) { Vector2 t = mCenterList[i]; if (GeoPolygonUtils.IsPointInPolygon2(poly, ref t)) { removeIndex.Add(i); } } for (int i = removeIndex.Count - 1; i >= 0; --i) { mCenterList.RemoveAt(removeIndex[i]); } }
private static List <Vector2> ExpandPolygonSegments(List <Vector2> original, float length = 1.0f) { List <Vector2> tempOrigin = new List <Vector2>(); tempOrigin.AddRange(original); if (GeoPolygonUtils.CalcualetArea(tempOrigin) < 0) { tempOrigin.Reverse(); } List <Vector2> result = new List <Vector2>(); for (int i = 0; i < tempOrigin.Count; ++i) { int j = i + 1; if (j == tempOrigin.Count) { j = 0; } int k = i - 1; if (k == -1) { k = tempOrigin.Count - 1; } Vector2 vk = tempOrigin[k] - tempOrigin[i]; Vector2 vj = tempOrigin[j] - tempOrigin[i]; Vector2 dir = vk.normalized + vj.normalized; dir.Normalize(); if (GeoPolygonUtils.IsConvexAngle(tempOrigin[k], tempOrigin[i], dir + tempOrigin[i])) { dir = -dir; } result.Add(tempOrigin[i]); result.Add(tempOrigin[i] + dir * length); } return(result); }
private bool CheckRectangleValid(Vector2 min, Vector2 max, float w, float h) { Vector2 p4 = new Vector2(min[0], max[1]); Vector2 p2 = new Vector2(max[0], min[1]); // 点都在polygon 内部 // 使用 bvh 判断 if (mIsConvex) { bool isInconvex = GeoPolygonUtils.IsPointInConvexPolygon2(mPolygonData, ref max); if (!isInconvex) { return(false); } isInconvex = GeoPolygonUtils.IsPointInConvexPolygon2(mPolygonData, ref min); if (!isInconvex) { return(false); } isInconvex = GeoPolygonUtils.IsPointInConvexPolygon2(mPolygonData, ref p2); if (!isInconvex) { return(false); } isInconvex = GeoPolygonUtils.IsPointInConvexPolygon2(mPolygonData, ref p4); if (!isInconvex) { return(false); } } else { if (mSegmentsBvh != null) { bool insect = mSegmentsBvh.TestIntersection(new GeoAABB2(min, max)); if (insect) { return(false); } } else { bool isInconvex = GeoPolygonUtils.IsPointInPolygon2(mPolygonData, ref max); if (!isInconvex) { return(false); } isInconvex = GeoPolygonUtils.IsPointInPolygon2(mPolygonData, ref min); if (!isInconvex) { return(false); } isInconvex = GeoPolygonUtils.IsPointInPolygon2(mPolygonData, ref p2); if (!isInconvex) { return(false); } isInconvex = GeoPolygonUtils.IsPointInPolygon2(mPolygonData, ref p4); if (!isInconvex) { return(false); } } } // 矩形与矩形是否有交叉 bool isInsectAABB = IsIntersectOtherAABB(min, max); if (isInsectAABB) { return(false); } return(true); }
private bool IsAllConvex() { return(GeoPolygonUtils.IsConvexPolygon2(mPolygonData)); }
private void AddPoint(GeoPointsArray2 polygon2, Vector2 p) { int cnt = polygon2.Count; List <bool> convexMask = new List <bool>(); for (int i = 0; i < cnt; ++i) { int j = i + 1; if (j == cnt) { j = 0; } convexMask.Add(GeoPolygonUtils.IsConvexAngle(polygon2[i], polygon2[j], p)); } int start = -1; int end = -1; for (int i = 0; i < cnt; i++) { int j = i + 1; if (j == cnt) { j = 0; } if (start == -1 && convexMask[i] == false && convexMask[j] == true) { start = j; } if (end == -1 && convexMask[i] == true && convexMask[j] == false) { end = j; } if (start != -1 && end != -1) { break; } } if (start != -1 && end != -1) { GeoPointsArray2 other = new GeoPointsArray2(); if (start <= end) { for (int i = start; i <= end; ++i) { other.Add(polygon2[i]); } } else { for (int i = start; i < cnt; ++i) { other.Add(polygon2[i]); } for (int i = 0; i <= end; ++i) { other.Add(polygon2[i]); } } other.Add(p); polygon2.Clear(); polygon2.mPointArray.AddRange(other.mPointArray); } }
// 对于环状问题,暂时没处理。处理起来,稍作修改即可。后期遇到时加入(检测环状,然后分离环状,及带孔的多边形环形区域。) public static void PolygonExpand(List <Vector2> original, List <Vector2> results, float length = 1.0f, bool useHull = true) { List <Vector2> origin = new List <Vector2>(); origin.AddRange(original); GeoPointsArray2 hullArray = null; if (useHull) { List <Vector2> hull = JarvisConvex.BuildHull(original); GeoPolygonUtils.ReverseIfCW(ref hull); hullArray = new GeoPointsArray2(hull); } float len = length; while (results.Count == 0) { List <Vector2> segs = ExpandPolygonSegments(origin, len); float min = CheckSegmentsIntersect(segs); if (min > len) { min = len; } if (min > 1e-5f) { List <Vector2> expands = ExpandPolygon(origin, min); //List<int> vLst = GeoUtils.VertexIndexList(expands); //List<List<int>> circles = CommonUtils.CheckCircle(vLst); // GeoUtils.Split(origin, circles); origin = PolygonIntersectRemove(expands); len = len - min; if (len < 0.01f) { results.AddRange(origin); } } else { for (int i = 1; i < segs.Count; i += 2) { results.Add(segs[i]); } } if (useHull && results.Count == 0 && hullArray != null) { bool flag = false; for (int i = 0; i < origin.Count; i++) { Vector2 refV = origin[i]; if (GeoPolygonUtils.IsPointInConvexPolygon2(hullArray, ref refV)) { flag = true; break; } } if (!flag) { List <Vector2> split = JarvisConvex.BuildHull(origin); GeoPolygonUtils.ReverseIfCW(ref split); split = ConvexMarginalExpand(split, len); results.AddRange(split); len = 0; } } } }
private bool IsConvex(int i, int j, int k) { return(GeoPolygonUtils.IsConvexAngle(mPoints[i], mPoints[j], mPoints[k])); }