void KMCentersTree::split_by_mid_point( int start_ind, int end_ind, int &cut_dim, double &cut_val, int &n_lo) { KMPoint *lo,*hi; lo = bnd_box_->get_point(0); hi = bnd_box_->get_point(1); // find the long side with the largest spread (the cutting dimension) double max_length = bnd_box_->max_length(); double max_spread = -1; for (int d = 0; d < data_points_->get_dim(); d++) { if (std::abs((*hi)[d] - (*lo)[d]-max_length) <1E-6){ double spr = spread(start_ind,end_ind,d); if (spr > max_spread) { max_spread = spr; cut_dim = d; } } } // find the splitting value double ideal_cut_val = ((*lo)[cut_dim] + (*hi)[cut_dim])/2; //min_max represent the minimal and maximal //values of points along the cutting dimension std::pair<double,double> min_max = limits_along_dimension(start_ind,end_ind, cut_dim); //slide to min or max as needed if (ideal_cut_val < min_max.first) cut_val = min_max.first; else if (ideal_cut_val > min_max.second) cut_val = min_max.second; else cut_val = ideal_cut_val; // permute points accordingly std::pair<int,int> break_ind = split_by_plane(start_ind,end_ind,cut_dim, cut_val); IMP_LOG(VERBOSE, "split by mid point for indexes: " << start_ind << " to " << end_ind << "break index: " << break_ind.first << " to " << break_ind.second << std::endl); //set n_lo such that each side of the split will contain at least one point n_lo = (start_ind+end_ind)/2; // if ideal_cut_val < min (y >= 1), we set n_lo = 1 (so there is one // point on left) if (ideal_cut_val < min_max.first) n_lo = start_ind+1; // if ideal_cut_val > max (x <= n-1), we set n_lo = n-1 (so there is one // point on right). else if (ideal_cut_val > min_max.second) n_lo = end_ind; // Otherwise, we select n_lo as close to the middle of [x..y] as possbile else if (break_ind.first > n_lo) n_lo = break_ind.first; else if (break_ind.second < n_lo) n_lo = break_ind.second; }
/* * receiver - points to the base room frustum, which portal leads to - it's taken from the portal! * returns a pointer to newly generated frustum. */ std::shared_ptr<Frustum> Frustum::portalFrustumIntersect(Portal *portal, std::shared_ptr<Frustum> emitter, Render *render) { assert(emitter); if(!portal->dest_room) return nullptr; if(portal->normal.distance(render->camera()->m_pos) < -SPLIT_EPSILON) // non face or degenerate to the line portal { return nullptr; } if(!portal->dest_room->frustum.empty() && emitter->hasParent(portal->dest_room->frustum.front())) { return nullptr; // Abort infinite loop! } bool in_dist = false, in_face = false; for(const btVector3& v : portal->vertices) { if(!in_dist && render->camera()->frustum->norm.distance(v) < render->camera()->m_distFar) in_dist = true; if(!in_face && emitter->norm.distance(v) > 0.0) in_face = true; if(in_dist && in_face) break; } if(!in_dist || !in_face) return nullptr; /* * Search for the first free room's frustum */ portal->dest_room->frustum.emplace_back(std::make_shared<Frustum>()); auto current_gen = portal->dest_room->frustum.back(); current_gen->splitPrepare(portal); // prepare for clipping if(current_gen->split_by_plane(emitter->norm)) // splitting by main frustum clip plane { for(size_t i = 0; i < emitter->vertices.size(); i++) { const auto& n = emitter->planes[i]; if(!current_gen->split_by_plane(n)) { portal->dest_room->frustum.pop_back(); return nullptr; } } current_gen->genClipPlanes(render->camera()); // all is OK, let's generate clip planes current_gen->parent = emitter; // add parent pointer current_gen->parents_count = emitter->parents_count + 1; if(portal->dest_room->max_path < current_gen->parents_count) { portal->dest_room->max_path = current_gen->parents_count; // maximum path to the room } return current_gen; } portal->dest_room->frustum.pop_back(); return nullptr; }