public int median3(int low, int high) { int l = low; int c = (high + low) >> 1; int h = high - 2; SortItem lv = g_items[l]; SortItem cv = g_items[c]; SortItem hv = g_items[h]; if (hv.v < lv.v || (hv.v == lv.v && hv.iptr < lv.iptr)) { swap(ref l, ref h); swap(lv, hv); } if (cv.v < lv.v || (cv.v == lv.v && cv.iptr < lv.iptr)) { swap(ref l, ref c); swap(lv, cv); } if (hv.v < cv.v || (hv.v == cv.v && hv.iptr < cv.iptr)) { swap(ref c, ref h); swap(cv, hv); } return(c); }
void swap(SortItem a, SortItem b) { SortItem tmp = new SortItem(ref a); a.polygon = b.polygon; a.v = b.v; a.iptr = b.iptr; b.polygon = tmp.polygon; b.v = tmp.v; b.iptr = tmp.iptr; }
int getPartition(int i, int j) { SortItem pivot = g_items[i]; while (i < j) { while (i < j && g_items[i].v < pivot.v || (g_items[i].v == pivot.v && g_items[i].iptr < pivot.iptr)) { i++; } while (i < j && j >= 0 && pivot.v < g_items[j].v || (pivot.v == g_items[j].v && pivot.iptr < g_items[j].iptr)) { j--; } swap(g_items[i], g_items[j]); } swap(g_items[i], pivot); return(i); }
public SortItem(SortItem s) { v = s.v; iptr = s.iptr; polygon = new Polygon(ref s.polygon); }
// 选则最好分割面 int getOptimalSplitPlane(ref List <Polygon> polygons, int numPolygons, ref float bestSplitPos, ref AABB aabb) { int bestSplitAxis = -1; float bestCost = 0; for (int axis = 0; axis < 3; axis++) { int[] nextAxis = new int[] { 1, 2, 0, 1 }; // 构建 item 数组 int k = 0; for (int i = 0; i < numPolygons; i++) { Polygon poly = polygons[i]; float mn = poly[0][axis]; float mx = mn; for (int j = 1; j < poly.numPoints(); j++) // 得到每个多边形的包围盒 { mn = Math.Min(mn, poly[j][axis]); mx = Math.Max(mx, poly[j][axis]); } g_items[k].v = mn; g_items[k].polygon = polygons[i]; g_items[k].iptr = (uint)k; g_items[k + 1].v = mx; g_items[k + 1].iptr = (uint)k + 1;; k += 2; } //for (int i = 0; i < numPolygons * 2; i++) //{ // Console.WriteLine("{0},{1},{2}", i, g_items[i].v, g_items[i].iptr); //} //Console.WriteLine(); // 排序 quickSort(0, numPolygons * 2); //for (int i = 0; i < numPolygons * 2; i++) //{ // Console.WriteLine("{0},{1},{2}", i, g_items[i].v, g_items[i].iptr); //} //Console.WriteLine(); //Console.WriteLine(); // 区域 int c1 = nextAxis[axis]; int c2 = nextAxis[axis + 1]; float areaConst = 2 * (aabb.m_mx[c1] - aabb.m_mn[c1]) * (aabb.m_mx[c2] - aabb.m_mn[c2]); float areaFactor = 2 * ((aabb.m_mx[c1] - aabb.m_mn[c1]) + (aabb.m_mx[c2] - aabb.m_mn[c2])); float boundLeft = aabb.m_mn[axis]; float boundRight = aabb.m_mx[axis]; // 遍历,寻找最小代价分割面 float bestAxisCost = 0; float bestAxisSplit = 0; int leftPolys = 0; int rightPolys = numPolygons; int bothPolys = 0; for (int i = 0; i < numPolygons * 2; i++) { SortItem it = g_items[i]; if (it.iptr % 2 == 0) { leftPolys++; bothPolys++; } if (it.v >= boundRight) { break; } if (it.v > boundLeft) { float split = it.v; float aLeft = areaConst + areaFactor * (split - boundLeft); float aRight = areaConst + areaFactor * (boundRight - split); float cost = aLeft * leftPolys + aRight * rightPolys; if (cost < bestAxisCost || bestAxisCost == 0) { bestAxisCost = cost; bestAxisSplit = split; } } if (it.iptr % 2 == 1) { rightPolys--; bothPolys--; } } if ((bestAxisCost < bestCost || bestCost == 0) && bestAxisCost > 0) { bestCost = bestAxisCost; bestSplitPos = bestAxisSplit; bestSplitAxis = axis; } } return(bestSplitAxis); }