void PointVec::makePntsUnique (std::vector<GeoLib::Point*>* pnt_vec, std::vector<size_t> &pnt_id_map, double eps) { size_t n_pnts_in_file (pnt_vec->size()); std::vector<size_t> perm; pnt_id_map.reserve (n_pnts_in_file); for (size_t k(0); k < n_pnts_in_file; k++) { perm.push_back (k); pnt_id_map.push_back(k); } // sort the points BaseLib::Quicksort<GeoLib::Point*> (*pnt_vec, 0, n_pnts_in_file, perm); // unfortunately quicksort is not stable - // sort identical points by id - to make sorting stable // determine intervals with identical points to resort for stability of sorting std::vector<size_t> identical_pnts_interval; bool identical (false); for (size_t k = 0; k < n_pnts_in_file - 1; k++) { if ( fabs((*((*pnt_vec)[k + 1]))[0] - (*((*pnt_vec)[k]))[0]) < eps && fabs( (*((*pnt_vec)[k + 1]))[1] - (*((*pnt_vec)[k]))[1]) < eps && fabs( (*((*pnt_vec)[k + 1]))[2] - (*((*pnt_vec)[k]))[2]) < eps) { // points are identical, sort by id if (!identical) identical_pnts_interval.push_back (k); identical = true; } else { if (identical) identical_pnts_interval.push_back (k + 1); identical = false; } } if (identical) identical_pnts_interval.push_back (n_pnts_in_file); for (size_t i(0); i < identical_pnts_interval.size() / 2; i++) { // bubble sort by id size_t beg (identical_pnts_interval[2 * i]); size_t end (identical_pnts_interval[2 * i + 1]); for (size_t j (beg); j < end; j++) for (size_t k (beg); k < end - 1; k++) if (perm[k] > perm[k + 1]) std::swap (perm[k], perm[k + 1]); } // check if there are identical points for (size_t k = 0; k < n_pnts_in_file - 1; k++) if ( fabs((*((*pnt_vec)[k + 1]))[0] - (*((*pnt_vec)[k]))[0]) < eps && fabs( (*((*pnt_vec)[k + 1]))[1] - (*((*pnt_vec)[k]))[1]) < eps && fabs( (*((*pnt_vec)[k + 1]))[2] - (*((*pnt_vec)[k]))[2]) < eps) pnt_id_map[perm[k + 1]] = pnt_id_map[perm[k]]; // reverse permutation BaseLib::Quicksort<GeoLib::Point*> (perm, 0, n_pnts_in_file, *pnt_vec); // remove the second, third, ... occurrence from vector for (size_t k(0); k < n_pnts_in_file; k++) if (pnt_id_map[k] < k) { delete (*pnt_vec)[k]; (*pnt_vec)[k] = NULL; } // remove NULL-ptr from vector for (std::vector<GeoLib::Point*>::iterator it(pnt_vec->begin()); it != pnt_vec->end(); ) { if (*it == NULL) it = pnt_vec->erase (it); else it++; } // renumber id-mapping size_t cnt (0); for (size_t k(0); k < n_pnts_in_file; k++) { if (pnt_id_map[k] == k) // point not removed, if necessary: id change { pnt_id_map[k] = cnt; cnt++; } else pnt_id_map[k] = pnt_id_map[pnt_id_map[k]]; } // KR correct renumbering of indices // size_t cnt(0); // std::map<size_t, size_t> reg_ids; // for (size_t k(0); k < n_pnts_in_file; k++) { // if (pnt_id_map[k] == k) { // reg_ids.insert(std::pair<size_t, size_t>(k, cnt)); // cnt++; // } else reg_ids.insert(std::pair<size_t, size_t>(k, reg_ids[pnt_id_map[k]])); // } // for (size_t k(0); k < n_pnts_in_file; k++) // pnt_id_map[k] = reg_ids[k]; }
void PointVec::makePntsUnique (std::vector<GeoLib::Point*>* pnt_vec, std::vector<std::size_t> &pnt_id_map, double eps) { std::size_t n_pnts_in_file(pnt_vec->size()); std::vector<std::size_t> perm; pnt_id_map.reserve(n_pnts_in_file); for (std::size_t k(0); k < n_pnts_in_file; k++) { perm.push_back(k); pnt_id_map.push_back(k); } // sort the points BaseLib::Quicksort<GeoLib::Point*>(*pnt_vec, 0, n_pnts_in_file, perm); // unfortunately quicksort is not stable - // sort identical points by id - to make sorting stable // determine intervals with identical points to resort for stability of sorting std::vector<std::size_t> identical_pnts_interval; bool identical(false); for (std::size_t k = 0; k < n_pnts_in_file - 1; k++) { if (MathLib::maxNormDist((*pnt_vec)[k + 1], (*pnt_vec)[k]) <= eps) { // points are identical, sort by id if (!identical) identical_pnts_interval.push_back(k); identical = true; } else { if (identical) identical_pnts_interval.push_back(k + 1); identical = false; } } if (identical) identical_pnts_interval.push_back(n_pnts_in_file); for (std::size_t i(0); i < identical_pnts_interval.size() / 2; i++) { // bubble sort by id std::size_t beg(identical_pnts_interval[2 * i]); std::size_t end(identical_pnts_interval[2 * i + 1]); for (std::size_t j(beg); j < end; j++) for (std::size_t k(beg); k < end - 1; k++) if (perm[k] > perm[k + 1]) std::swap(perm[k], perm[k + 1]); } // check if there are identical points for (std::size_t k = 0; k < n_pnts_in_file - 1; k++) if (MathLib::maxNormDist((*pnt_vec)[k + 1], (*pnt_vec)[k]) <= eps) pnt_id_map[perm[k + 1]] = pnt_id_map[perm[k]]; // reverse permutation BaseLib::Quicksort<std::size_t, GeoLib::Point*>(perm, 0, n_pnts_in_file, *pnt_vec); // remove the second, third, ... occurrence from vector std::size_t cnt(0); // counts the points that are deleted for (std::size_t k(0); k < n_pnts_in_file; k++) { if (pnt_id_map[k] < k) { delete (*pnt_vec)[k]; (*pnt_vec)[k] = nullptr; cnt++; } } auto const pnt_vec_end = std::remove(pnt_vec->begin(), pnt_vec->end(), nullptr); pnt_vec->erase(pnt_vec_end, pnt_vec->end()); // renumber id-mapping cnt = 0; for (std::size_t k(0); k < n_pnts_in_file; k++) { if (pnt_id_map[k] == k) { // point not removed, if necessary: id change pnt_id_map[k] = cnt; cnt++; } else { pnt_id_map[k] = pnt_id_map[pnt_id_map[k]]; } } }