int trap(vector<int>& height) { int len = height.size(); vector<int> max_left(len, 0); vector<int> max_right(len, 0); for(int i=1; i<len; i++) { max_left[i] = max(max_left[i-1], height[i-1]); max_right[len-1-i] = max(max_right[len-i], height[len-i]); } int sum = 0; for(int k=0; k<len;k++) { sum += max ( min(max_left[k], max_right[k]) - height[k], 0); } return sum; }
AbstractKDNode *KDTree::Build(__in std::vector<Triangle const *> const &set, __in float3_t const &min, __in float3_t const &max, __in std::size_t depth) { if ((set.size() <= max_bucket_size_) || (depth > max_hierarchy_depth_)) { // std::tcerr << set.size(); if (set.empty()) { return new KDNull(); } else { return new KDLeaf(set); } } depth++; float3_t const range(max - min); std::size_t axis = ~0U; // 分割次元 float_t value = std::numeric_limits<float_t>::signaling_NaN(); // 分割位置 // surface area heuristic float_t min_cost = std::numeric_limits<float_t>::max(); // event struct open_close_event { bool operator<(open_close_event const &e) const { // value が等しい場合 open Event < close Event とする return (value < e.value) ? true : (value > e.value) ? false : type < e.type; } bool type; // event type: {false: open, true: close} float_t value; }; #define EVENT_UPDATE(v) \ { \ float_t const r = v - min[k]; \ float_t const sa_left = a + b * r; \ float_t const sa_right = a + b * (range[k] - r); \ float_t const cost = n_left * sa_left + n_right * sa_right; \ if (min_cost > cost) { \ min_cost = cost; \ axis = k; \ value = v; \ } \ } std::vector<open_close_event> event_list(set.size() * 2); for (std::size_t k = 0; k < 3; ++k) { // init event list for (std::size_t i = 0, size = set.size(); i < size; ++i) { event_list[i].type = false; event_list[i].value = set[i]->min(k); // 最小値 event_list[i + size].type = true; event_list[i + size].value = set[i]->max(k) + EPSILON; // 最大値 } // sort event list std::sort(event_list.begin(), event_list.end()); // compute min cost float_t const a = range[(k + 1) % 3] * range[(k + 2) % 3]; float_t const b = range[(k + 1) % 3] + range[(k + 2) % 3]; std::size_t n_left = 0; std::size_t n_right = set.size(); { float_t const v = event_list[0].value - EPSILON; EVENT_UPDATE(v); } for (std::size_t i = 0, size = event_list.size(); i < size; ++i) { if (event_list[i].type) { n_right--; // close event } else { n_left++; // open event } float_t v = event_list[i].value; if ((i + 1) < size) { if (v == event_list[i + 1].value) { continue; // do not evalute } // v += (event_list[i+1].value - v) * float_t(0.5); } else { v += EPSILON; } EVENT_UPDATE(v); } } #undef EVENT_UPDATE // 左右に分類 std::vector<Triangle const *> set_left; std::vector<Triangle const *> set_right; for (std::size_t i = 0, size = set.size(); i < size; ++i) { switch (set[i]->Overlap(axis, value)) { case 1: set_left.push_back(set[i]); break; // 左 case 2: set_right.push_back(set[i]); break; // 右 case 3: set_left.push_back(set[i]); set_right.push_back(set[i]); break; // 両方 default: assert(!"bad Triangle::Overlap"); break; } } // set.swap(std::vector<Triangle const *>()); // clear & trim // create nodes KDNode *node = new KDNode(axis, value); { float3_t max_left(max); max_left[axis] = value; node->SetChild(0, Build(set_left, min, max_left, depth)); } { float3_t min_right(min); min_right[axis] = value; node->SetChild(1, Build(set_right, min_right, max, depth)); } return node; }