public GeoAABB2 GetRectangle(float sizew, float sizeh, int index) { if (CanContinue()) { Vector2i temp = new Vector2i((int)(sizew * 100), (int)(sizeh * 100)); if (!mCacheWH.Contains(temp)) { GeoAABB2 aabb = new GeoAABB2(); if (!mWrapper.GetRectangle(sizew, sizeh, ref aabb)) { mCacheWH.Add(temp); if (!mCacheIndex.Add(index)) { mInsertedCount++; } } else { // mResults[index].Add(aabb); float aabbArea = aabb.Area(); mResultsArea[index] += aabbArea; mCacheIndex.Clear(); mInsertedCount = 0; mAreaProb.Clear(); mProbTotal = 0.0f; for (int a = 0; a < mProb; ++a) { float newProb = mResultsArea[a] / mArea - mProbs[a].mProbablity; newProb = newProb > 0 ? 0 : -newProb; mAreaProb.Add(newProb); mProbTotal += newProb; } return(aabb); } } else { if (!mCacheIndex.Add(index)) { mInsertedCount++; } } } return(null); }
/// <summary> /// 1 在某一个段内找不到时,并且找的概率为1,容易出现死循环 nowCount insertMaxCount 来控制 退出循环 /// 2 wrapper.IsFull() 设置占比,退出循环 /// 3 cacheIndex.Count < prob 退出循环 /// </summary> /// <param name="original"></param> /// <param name="probablities"></param> /// <param name="connects"></param> /// <returns></returns> private static List <List <GeoAABB2> > PolygonPartition(List <Vector2> original, List <PartitionUnit> probablities, List <Vector4> connects = null) { List <PartitionUnit> newUnits = new List <PartitionUnit>(); newUnits.AddRange(probablities); PolygonWrapper wrapper = PolygonWrapper.Create(original, true, connects, 2); float total = wrapper.Area; int prob = newUnits.Count; List <List <GeoAABB2> > results = new List <List <GeoAABB2> >(); List <float> resultsArea = new List <float>(); List <float> areaProb = new List <float>(); // 更新概率 float proSum = 0.0f; for (int i = 0; i < prob; ++i) { results.Add(new List <GeoAABB2>()); resultsArea.Add(0.0f); areaProb.Add(newUnits[i].mProbablity); proSum += newUnits[i].mProbablity; } int insertMaxCount = prob * 10; int nowCount = 0; HashSet <Vector2i> cacheWH = new HashSet <Vector2i>(); HashSet <int> cacheIndex = new HashSet <int>(); int index = RandomInt(areaProb, proSum); while (!wrapper.IsFull() && cacheIndex.Count < prob && nowCount < insertMaxCount) { float sizew = RandomUtils.GetRandomFloat(newUnits[index].mMinW, newUnits[index].mMaxW); float sizeh = RandomUtils.GetRandomFloat(newUnits[index].mMinH, newUnits[index].mMaxH); Vector2i temp = new Vector2i((int)(sizew * 100), (int)(sizeh * 100)); if (!cacheWH.Contains(temp)) { GeoAABB2 aabb = new GeoAABB2(); if (!wrapper.GetRectangle(sizew, sizeh, ref aabb)) { cacheWH.Add(temp); if (!cacheIndex.Add(index)) { nowCount++; } } else { results[index].Add(aabb); float aabbArea = aabb.Area(); resultsArea[index] += aabbArea; cacheIndex.Clear(); nowCount = 0; areaProb.Clear(); proSum = 0.0f; for (int a = 0; a < prob; ++a) { float newProb = resultsArea[a] / total - newUnits[a].mProbablity; newProb = newProb > 0 ? 0 : -newProb; areaProb.Add(newProb); proSum += newProb; } if (proSum == 0) { break; } } } else { if (!cacheIndex.Add(index)) { nowCount++; } } index = RandomInt(areaProb, proSum); } for (int a = 0; a < resultsArea.Count; ++a) { float abs = resultsArea[a] / total; Debug.Log(string.Format("count: {0}, xLen: {1}", results[a].Count, abs)); } return(results); }