std::pair<PairPoints, size_t> getNearestPoints_optimum(std::vector<Point>& points, size_t debInter, size_t finInter, Integer xBorneLeft, Integer xBorneRight) { if (finInter - debInter < 2) { std::cerr << "Erreure sur la taille de l'entrée: trop petite" << std::endl; } if (finInter - debInter <= MAX_POINTS_N2) { PairPoints pairMin = brutalGetClosestPoints(points, debInter, finInter); std::sort(points.begin()+debInter, points.begin()+finInter, [](const Point& p1, const Point& p2) { return isP1BeforeP2_Y(p1, p2); }); return std::make_pair(pairMin, finInter); } // couper en deux, appels récursifs size_t indexCoupe = (debInter+finInter)/2; Integer xCoupe = points[indexCoupe].x; auto coupe1 = getNearestPoints_optimum(points, debInter, indexCoupe, xBorneLeft, xCoupe); auto coupe2 = getNearestPoints_optimum(points, indexCoupe, finInter, xCoupe, xBorneRight); PairPoints pairMin = std::min(coupe1.first, coupe2.first); Integer delta = pairMin.distanceSquare; pairMin = distMinBetweenSides(points, debInter, coupe1.second, indexCoupe, coupe2.second, [&](const Point& p) { return carr(p.x - xCoupe) < pairMin.distanceSquare; }, pairMin); // mettre les deux parties au début, triée par y (uniquement ceux près des bords) delta = pairMin.distanceSquare; std::vector<Point> nearBords = merge_ySorted_nearLine(points, debInter, coupe1.second, indexCoupe, coupe2.second, [&](const Point& p) { return carr(p.x - xBorneLeft) < delta || carr(p.x - xBorneRight) < delta; }); for (size_t iPoint = 0; iPoint < nearBords.size(); iPoint++) { points[debInter+iPoint] = nearBords[iPoint]; } return std::make_pair(pairMin, debInter+(Integer)nearBords.size()); }
void update(Point a, Point b) { Integer da = carr(a.x-b.x) + carr(a.y-b.y); if (da < distanceSquare) { p1 = a, p2 = b; distanceSquare = da; } }
std::pair<std::vector<Point>*, std::vector<Point>*> getNearestPoints_optimum2(std::vector<Point>& points, size_t debInter, size_t finInter, Integer xBorneLeft, Integer xBorneRight, PairPoints& pairMin) { /*nbTab++; std::cerr << "\n"; errTab(); std::cerr << "--------- getNearestPoints entre " << xBorneLeft << " et " << xBorneRight << "\n"; errTab(); for (Integer i = debInter; i < finInter; i++) std::cerr << points[i].x << "-" << points[i].y << " "; std::cerr << "\n";*/ if (finInter - debInter < 2) { std::cerr << "Erreure sur la taille de l'entrée: trop petite" << std::endl; exit(-1); } if (finInter - debInter <= MAX_POINTS_N2) { pairMin = std::min(pairMin, brutalGetClosestPoints(points, debInter, finInter)); std::sort(points.begin()+debInter, points.begin()+finInter, [](const Point& p1, const Point& p2) { return isP1BeforeP2_Y(p1, p2); }); std::vector<Point>* v1 = new std::vector<Point>(points.begin()+debInter, points.begin()+finInter); std::vector<Point>* v2 = new std::vector<Point>(points.begin()+debInter, points.begin()+finInter); //errTab(); std::cerr << "delta trouvé: " << pairMin.distanceSquare << "\n"; //nbTab--; return std::make_pair(v1, v2); } size_t indexCoupe = (debInter+finInter)/2; Integer xCoupe = points[indexCoupe].x; auto coupe1 = getNearestPoints_optimum2(points, debInter, indexCoupe, xBorneLeft, xCoupe, pairMin); auto coupe2 = getNearestPoints_optimum2(points, indexCoupe, finInter, xCoupe, xBorneRight, pairMin); //errTab(); std::cerr << "delta trouvé: " << pairMin.distanceSquare << "\n"; //nbTab--; std::vector<Point> *side1 = coupe1.first, *side2 = coupe2.second; if (pairMin.distanceSquare > carr(xCoupe-xBorneLeft)) { //errTab(); std::cerr << "==> Étendre depuis la gauche !"<< xBorneLeft << " " << xBorneRight << "\n"; side1 = new std::vector<Point>(coupe1.first->size()+coupe2.first->size()); mergeYsorted(coupe1.first, coupe2.first, side1); } if (pairMin.distanceSquare > carr(xBorneRight-xCoupe)) { //errTab(); std::cerr << "==> Étendre depuis la droite !"<< xBorneLeft << " " << xBorneRight << "\n"; side2 = new std::vector<Point>(coupe1.second->size() + coupe2.second->size()); mergeYsorted(coupe1.second, coupe2.second, side2); } distMinBetweenSides_v2(coupe1.second, coupe2.first, pairMin, xCoupe); delete coupe1.second; delete coupe2.first; if (side1 != coupe1.first) delete coupe1.first; if (side2 != coupe2.second) delete coupe2.second; return std::make_pair(side1, side2); }
std::pair<PairPoints, size_t> getNearestPoints(std::vector<Point>& points, size_t debInter, size_t finInter, Integer xBorneLeft, Integer xBorneRight) { /*nbTab++; std::cerr << "\n"; errTab(); std::cerr << "--------- getNearestPoints entre " << xBorneLeft << " et " << xBorneRight << "\n"; errTab(); for (Integer i = debInter; i < finInter; i++) std::cerr << points[i].x << "-" << points[i].y << " "; std::cerr << "\n";*/ if (finInter - debInter < 2) { std::cerr << "Erreure sur la taille de l'entrée: trop petite" << std::endl; } if (finInter - debInter <= MAX_POINTS_N2) { PairPoints pairMin = brutalGetClosestPoints(points, debInter, finInter); std::sort(points.begin()+debInter, points.begin()+finInter, [](const Point& p1, const Point& p2) { return isP1BeforeP2_Y(p1, p2); }); //errTab(); std::cerr << "delta trouvé: " << pairMin.distanceSquare << "\n"; //nbTab--; return std::make_pair(pairMin, finInter); } // couper en deux, appels récursifs size_t indexCoupe = (debInter+finInter)/2; Integer xCoupe = points[indexCoupe].x; auto coupe1 = getNearestPoints(points, debInter, indexCoupe, xBorneLeft, xCoupe); auto coupe2 = getNearestPoints(points, indexCoupe, finInter, xCoupe, xBorneRight); PairPoints pairMin = std::min(coupe1.first, coupe2.first); std::vector<Point> nearLine = merge_ySorted_nearLine(points, debInter, coupe1.second, indexCoupe, coupe2.second, [&](const Point& p) { return carr(p.x - xCoupe) < pairMin.distanceSquare; }); /*errTab(); std::cerr << "Fusion: "; for (Point p : nearLine) { std::cerr << p.x << "-" << p.y << " "; } std::cerr << "\n";*/ for (size_t p1 = 0; p1 < nearLine.size(); p1++) { for (size_t nx = p1+1; nx < nearLine.size() && nx < p1+8; nx++) { pairMin = std::min(pairMin, PairPoints(nearLine[p1], nearLine[nx])); } } // mettre les deux parties au début, triée par y (uniquement ceux près des bords) std::vector<Point> nearBords = merge_ySorted_nearLine(points, debInter, coupe1.second, indexCoupe, coupe2.second, [&](const Point& p) { return carr(p.x - xBorneLeft) < pairMin.distanceSquare || carr(p.x - xBorneRight) < pairMin.distanceSquare; }); for (size_t iPoint = 0; iPoint < nearBords.size(); iPoint++) { points[debInter+iPoint] = nearBords[iPoint]; } //errTab(); std::cerr << "delta trouvé: " << pairMin.distanceSquare << " avec " << pairMin.p1.x << "-" << pairMin.p1.y << " " << pairMin.p2.x << "-" << pairMin.p2.y << "\n"; //nbTab--; return std::make_pair(pairMin, debInter+(Integer)nearBords.size()); }
arrayRing_array::arrayRing_array() { if(thisIndex==0) { CProxy_arrayRing_array carr(thisArrayID); carr[0].start(new arrayMessage); } }
void distMinBetweenSides_v2(std::vector<Point>* side1, std::vector<Point>* side2, PairPoints& pairMin, Integer xCoupe) { /*errTab(); std::cerr << "------> Fusion de \n";errTab(); for (Point p : *side1){ //if (carr(p.x - xCoupe) < pairMin.distanceSquare) std::cerr << p.x << "-" << p.y << " "; } std::cerr << "\n"; errTab(); std::cerr << "Et:\n";errTab(); for (Point p : *side2){ //if (carr(p.x - xCoupe) < pairMin.distanceSquare) std::cerr << p.x << "-" << p.y << " "; } std::cerr << "\n";*/ while (!side1->empty() && !side2->empty()) { while (!side1->empty() && carr(side1->back().x - xCoupe) >= pairMin.distanceSquare) side1->pop_back(); while (!side2->empty() && carr(side2->back().x - xCoupe) >= pairMin.distanceSquare) side2->pop_back(); if (side1->empty() || side2->empty()) return ; if (isP1BeforeP2_Y(side1->back(), side2->back())) std::swap(side1, side2); Point fpSide2 = side2->back(); //std::cerr << "compare: [" << side1->back().x << " " << side1->back().y << "] et [" << side2->back().x << " " << side2->back().y << "]\n"; pairMin.update(side1->back(), fpSide2); side2->pop_back(); while (!side2->empty() && carr(side2->back().x - xCoupe) >= pairMin.distanceSquare) side2->pop_back(); if (!side2->empty()) { //std::cerr << "compare: [" << side1->back().x << " " << side1->back().y << "] et [" << side2->back().x << " " << side2->back().y << "]\n"; pairMin.update(side1->back() ,side2->back()); } side2->push_back(fpSide2); side1->pop_back(); } }
ModelPtr DatIO::read(string filename, int n, int reduction) { ModelPtr model( new Model); PointBufferPtr pointBuffer(new PointBuffer); // Allocate point buffer and read data from file int c = 0; ifstream in(filename.c_str(), std::ios::binary); int numPoints = 0; in.read((char*)&numPoints, sizeof(int)); // Determine modulo value suitable for desired reduction int mod_filter = 1; if(reduction != 0 && numPoints > reduction) { mod_filter = (int)(numPoints / reduction); cout << timestamp << "Reduction mode. Reading every " << mod_filter << "th point." << endl; numPoints = reduction; } else { reduction = numPoints; // needed for progress estimation } float* pointArray = new float[3 * numPoints]; unsigned char* colorArray = new unsigned char[3 * numPoints]; float* buffer = new float[n-1]; int reflect; string msg = timestamp.getElapsedTime() + "Loading points"; ProgressBar progress(numPoints, msg); int d = 0; while(in.good()) { memset(buffer, 0, (n - 1) * sizeof(float)); in.read((char*)buffer, (n - 1) * sizeof(float)); in.read((char*)&reflect, sizeof(int)); if(c % mod_filter == 0 && d < numPoints) { // Copy point data to point array int pos = 3 * d; pointArray[pos] = buffer[0]; pointArray[pos + 1] = buffer[1]; pointArray[pos + 2] = buffer[2]; if(n > 3) { colorArray[pos] = (unsigned char)reflect; colorArray[pos + 1] = (unsigned char)reflect; colorArray[pos + 2] = (unsigned char)reflect; } else { colorArray[pos] = (unsigned char)0; colorArray[pos + 1] = (unsigned char)0; colorArray[pos + 2] = (unsigned char)0; } d++; ++progress; } c++; } delete[] buffer; in.close(); // Truncate arrays to actual size pointArray = (float*)realloc(pointArray, 3 * d * sizeof(float)); colorArray = (unsigned char*)realloc(colorArray, 3 * d * sizeof(unsigned char)); cout << timestamp << "Creating point buffer with " << d << "points." << endl; // Setup model pointer floatArr parr(pointArray); ucharArr carr(colorArray); pointBuffer->setPointArray(parr, d); pointBuffer->setPointColorArray(carr, d); model->m_pointCloud = pointBuffer; return model; }
PairPoints(Point a, Point b) { p1 = a, p2 = b; distanceSquare = carr(p1.x-p2.x) + carr(p1.y-p2.y); }
Integer getDistBtw(Point& p1, Point& p2) { return carr(p1.x-p2.x) + carr(p1.y-p2.y); }