예제 #1
0
파일: genetic.cpp 프로젝트: Arkezar/TSP_GA
void GA::CycleCrossover(Candidate p1, Candidate p2){
	int startingGene = std::rand() % p1.getCandidate().size();
	int currentGene = -1;
	std::vector<City> child1(p1.getCandidate());
	std::vector<City> child2(p2.getCandidate());
		
	CycleCrossover_MixGenes(child1,child2,currentGene,startingGene);
	//newPopulation.push_back(p1);
	//newPopulation.push_back(p2);

	Candidate newChild1 = Candidate(child1,distances);
	Candidate newChild2 = Candidate(child2,distances);
	if(!newChild1.isUnique() || !newChild2.isUnique())
		throw new std::logic_error("Invalid child sequence");

	newPopulation.push_back(newChild1);
	newPopulation.push_back(newChild2);

	//std::cout << "P1 " << p1 << "\n";
	//std::cout << "P2 " << p2 << "\n";
	//std::cout << "C1 " << newChild1 << "\n";
	//std::cout << "C2 " << newChild2 << "\n";
	//if(newChild1.getFitness() > p1.getFitness())

}
예제 #2
0
/*
函数说明:
    递归遍历数组,寻找多数元素
输入参数:
    int A[]  : 输入数组
    int n    : 数组大小
    int m    : 从第几个元素开始遍历
输出参数:
    0
    */
int Candidate(int A[],int n, int m)
{
	int j = m;
	int c = A[m];
	int count = 1;

	for (;j < n-1 && count > 0;)
	{
		j++;
		if (c == A[j])
		{
			count++;
		}
		else
		{
			count--;
		}
	}

	if (j == n-1)
	{
		return c;     //递归结束时,c在小范围内出现的次数至少有%50
	}
	else
	{
		return Candidate(A, n, j+1);
	}

}
예제 #3
0
 void operator() (const Vector3 &v0, const Vector3 &v1, 
         const Vector3 &v2, double a)
 {
     Vector3 c = (v0 + v1 + v2)/3;
     double distance = Norm(p - c)/divisor;
     double probability = a*lambda*exp(-lambda*distance);
     candidate.push_back(Candidate(v0, v1, v2, probability));
 }
예제 #4
0
파일: genetic.cpp 프로젝트: Arkezar/TSP_GA
Candidate GA::PMXCrossover(const Candidate& p1, const Candidate& p2){
//	std::cout << "Starting crossover\n";
	int startPos = std::rand() % p1.getCandidate().size();
	int endPos = -1;
	while(endPos == -1){
		int tmpPos = std::rand() % p1.getCandidate().size();
		if(tmpPos > startPos)
			endPos = tmpPos;
		else if(tmpPos < startPos){
			endPos = startPos;
			startPos = tmpPos;
		}
	}

//	std::cout << "swath start: " << startPos << "\nswath end: " << endPos << "\n";

	std::vector<City> child(p1.getCandidate().size());
	std::vector<bool> childCompletion(p1.getCandidate().size());
	//COPY RANDOM SWATH OF GENES
	//std::copy(p1.getCandidate().begin() + startPos, 
	//		p1.getCandidate().begin() + endPos, 
	//		child.begin() + startPos);
	//
	for(int i = startPos; i <= endPos; i++){
		child[i] = p1.getCandidate().at(i);
	}

	//for(const auto& c : child){
	//	std::cout << c << "\n";
	//}
	for(int i = startPos; i <= endPos; i++)
		childCompletion[i] = true;
	//FIND FIRST GENE IN PARENT 2 THAT WASN'T COPIED TO CHILD
	
	for(int i = startPos; i <= endPos; i++){
		auto tmpGene = std::find(child.begin(), child.end(), p2.getCandidate().at(i));
		if(tmpGene == child.end()){
			int destPosition = PMXCrossover_FindDestPosition(p1.getCandidate(),p2.getCandidate(),startPos,endPos,i);
//			std::cout << "Place " << p2.getCandidate().at(i) << " at pos " << destPosition << "\n";
			child[destPosition] = p2.getCandidate().at(i);
			childCompletion[destPosition] = true;
		}
	}

	for(int i = 0; i< child.size(); i++){
		if(!childCompletion[i])
			child[i] = p2.getCandidate().at(i);
	}

	Candidate result = Candidate(child, distances);
	if(!result.isUnique()){
		for(const auto& c : result.getCandidate())
			std::cout << c << "\n";
		throw new std::logic_error("Invalid child sequence");
	}	
	return result;
}
예제 #5
0
bool Reprojector::reprojectPoint(FramePtr frame, Point* point)
{
  Vector2d px(frame->w2c(point->pos_));
  if(frame->cam_->isInFrame(px.cast<int>(), 8)) // 8px is the patch size in the matcher
  {
    const int k = static_cast<int>(px[1]/grid_.cell_size)*grid_.grid_n_cols
                + static_cast<int>(px[0]/grid_.cell_size);
    grid_.cells.at(k)->push_back(Candidate(point, px));
    return true;
  }
  return false;
}
예제 #6
0
// Explore the neighborhood around a vertex looking for missing overlaps
SGEdgeStatsVisitor::CandidateVector SGEdgeStatsVisitor::getMissingCandidates(StringGraph* /*pGraph*/, 
                                                                             Vertex* pVertex, 
                                                                             int minOverlap) const
{
    CandidateVector out;

    // Mark the vertices that are reached from this vertex as black to indicate
    // they already are overlapping
    EdgePtrVec edges = pVertex->getEdges();
    for(size_t i = 0; i < edges.size(); ++i)
    {
        edges[i]->getEnd()->setColor(GC_BLACK);
    }
    pVertex->setColor(GC_BLACK);

    for(size_t i = 0; i < edges.size(); ++i)
    {
        Edge* pXY = edges[i];
        EdgePtrVec neighborEdges = pXY->getEnd()->getEdges();
        for(size_t j = 0; j < neighborEdges.size(); ++j)
        {
            Edge* pYZ = neighborEdges[j];
            if(pYZ->getEnd()->getColor() != GC_BLACK)
            {
                // Infer the overlap object from the edges
                Overlap ovrXY = pXY->getOverlap();
                Overlap ovrYZ = pYZ->getOverlap();

                if(SGAlgorithms::hasTransitiveOverlap(ovrXY, ovrYZ))
                {
                    Overlap ovr_xz = SGAlgorithms::inferTransitiveOverlap(ovrXY, ovrYZ);
                    if(ovr_xz.match.getMinOverlapLength() >= minOverlap)
                    {
                        out.push_back(Candidate(pYZ->getEnd(), ovr_xz));
                        pYZ->getEnd()->setColor(GC_BLACK);
                    }
                }
            }
        }
    }

    // Reset colors
    for(size_t i = 0; i < edges.size(); ++i)
        edges[i]->getEnd()->setColor(GC_WHITE);
    pVertex->setColor(GC_WHITE);
    for(size_t i = 0; i < out.size(); ++i)
        out[i].pEndpoint->setColor(GC_WHITE);
    return out;
}
예제 #7
0
int main()
{
    int c, j, count;
    c = Candidate(1);
    count = 0;
    for(j = 1; j <= N; ++j)
    {
        if(A[j] == c)
        {
            count = count + 1;
        }
    }
    if(count > (N / 2))
        printf("%d", c);
    else
        printf("none");
    return 0;
}
예제 #8
0
int main(void)
{
	int A[SIZE] = {0};

	int c = 0;
	int count = 0;
	int j = 0;
	int n = 0;

	printf("please input the size of the array:");
	scanf("%d",&n);
	printf("please input the number : ");
	for (j = 0; j < n ; j++)
	{
		scanf("%d",&A[j]);
	}

	c = Candidate(A, n - 1, 0);  //得到可能是多少元素的数组元素

	count = 0;

	for (j = 0;j < n;j++)
	{
		if (c == A[j])
		{
			count++;
		}
	}

	if (count > n/2)   //检查c出现的次数是否大于n/2,是则是多数元素,否则不是
	{
		printf("the candidate is %d\n",c);
	}
	else
	{
		printf("there is no candidate num!\n");
	}
	

	system("pause");
	return 0;
}
예제 #9
0
파일: genetic.cpp 프로젝트: Arkezar/TSP_GA
void GA::Initialize(std::string filePath){
	std::string fpath(filePath);
	baseCityVector = loadDataFromFile(fpath);
	std::cout << "City vector size: " << baseCityVector.size() << "\n";
	for(const auto& c : baseCityVector)
		std::cout << c << "\n";

	distances = createDistanceMatrix(baseCityVector);
	for(int i = 0; i < populationSize ; i++){
		population.push_back( Candidate(generateRandomCandidate(baseCityVector),distances) );
	}
	maxXPosition = 0;
	maxYPosition = 0;
	for(const auto& city : population[0].getCandidate()){
		if(city.getX() > maxXPosition)
			maxXPosition = city.getX();
		if(city.getY() > maxYPosition)
			maxYPosition = city.getY();
	}
}
예제 #10
0
int Candidate(int m)
{
    int c, j, count;
    j = m; c = A[m]; count = 1;
    while(j < N && count > 0)
    {
        j = j + 1;
        if(A[j] == c)
        {
            count = count + 1;
        }
        else
        {
            count = count - 1;
        }
    }
    if(j == N)
        return c;
    else 
        return Candidate(j + 1);
}
예제 #11
0
파일: a1q1.cpp 프로젝트: Arcanfel/dsa
bool MajorityElement(int arr[], int& majority, int sz){
    bool result = false;
    int numOfCandidate = 0;
    int can;
    
    //Names of variables are pretty desriptive
    //and the following code speaks for itself
    
    if(Candidate(arr, sz, can))
    {
        for(int i = 0; i < sz; i++)
        {
            if(can == arr[i])
                numOfCandidate++;
        }
        if(numOfCandidate > sz/2)
            result = true;
    }
    if(result)
        majority = can;
    
    return result;
}
예제 #12
0
파일: a1q1.cpp 프로젝트: Arcanfel/dsa
bool Candidate(int arr[], int sz, int& can){
    bool result = false;
    int temp[sz];
    int temp_counter = 0;
    
    // temp is an array to hold new values from 
    // original array. Temp_counter is needed as
    // counter (obviously) and as an array size
    // to be passed to another Candidate function
    
    if(sz != 0)
    {
        if(sz == 1)
        {
            can = arr[0];
            result = true;
        }
        else
        {
            for(int i = 0; i < sz; i+=2)
            {
                if(arr[i] == arr[i+1])
                    temp[temp_counter++] = arr[i];
                temp[temp_counter] = NULL;
            }
            
            result = Candidate(temp,temp_counter,can);
            
            if(sz%2 != 0 && !result) // if array size is odd and no candidate
            {                        // is found then the last number is candidate
                can = arr[sz-1];
                result = true;
            }
        }
    }
    return result;
}
    EndCriteria::Type DifferentialEvolution::minimize(Problem& p, const EndCriteria& endCriteria) {
        EndCriteria::Type ecType;

        upperBound_ = p.constraint().upperBound(p.currentValue());
        lowerBound_ = p.constraint().lowerBound(p.currentValue());
        currGenSizeWeights_ = Array(configuration().populationMembers,
                                    configuration().stepsizeWeight);
        currGenCrossover_ = Array(configuration().populationMembers,
                                  configuration().crossoverProbability);

        std::vector<Candidate> population(configuration().populationMembers,
                                          Candidate(p.currentValue().size()));
        fillInitialPopulation(population, p);

        std::partial_sort(population.begin(), population.begin() + 1, population.end(),
                          sort_by_cost());
        bestMemberEver_ = population.front();
        Real fxOld = population.front().cost;
        Size iteration = 0, stationaryPointIteration = 0;

        // main loop - calculate consecutive emerging populations
        while (!endCriteria.checkMaxIterations(iteration++, ecType)) {
            calculateNextGeneration(population, p.costFunction());
            std::partial_sort(population.begin(), population.begin() + 1, population.end(),
                              sort_by_cost());
            if (population.front().cost < bestMemberEver_.cost)
                bestMemberEver_ = population.front();
            Real fxNew = population.front().cost;
            if (endCriteria.checkStationaryFunctionValue(fxOld, fxNew, stationaryPointIteration,
                                                         ecType))
                break;
            fxOld = fxNew;
        };
        p.setCurrentValue(bestMemberEver_.values);
        p.setFunctionValue(bestMemberEver_.cost);
        return ecType;
    }
예제 #14
0
bool Reprojector::reprojectPoint(FramePtr frame, Point* point, int print)
{
  // point->pos_[2] = point->pos_[2] * 600;
  Vector2d px(frame->w2c(point->pos_));
  if(frame->cam_->isInFrame(px.cast<int>(), 8)) // 8px is the patch size in the matcher
  {

    // cout << "point pos" << point->pos_ << endl;
    // cout << "px" << px << endl;
    if(print)
      // cout << "repro" << endl;

    if(print) {
      outfile << round(px[0]) << " " << round(px[1]) << " " << point->pos_[2] << " ";
      outfile2 << point->pos_[0] << " " << point->pos_[1] << " " << point->pos_[2] << "\n";
    }

    const int k = static_cast<int>(px[1]/grid_.cell_size)*grid_.grid_n_cols
                + static_cast<int>(px[0]/grid_.cell_size);
    grid_.cells.at(k)->push_back(Candidate(point, px));
    return true;
  }
  return false;
}
예제 #15
0
bool GeometryUtilities::placeRectAtLine(const QRectF &rect, const QLineF &line, double lineOffset, double distance,
                                        const QLineF &intersectionLine, QPointF *placement, Side *horizontalAlignedSide)
{
    QMT_CHECK(placement);

    QList<Candidate> candidates;
    candidates << Candidate(QVector2D(rect.topRight() - rect.topLeft()), QPointF(0.0, 0.0), SideTop)
               << Candidate(QVector2D(rect.topLeft() - rect.topRight()), rect.topRight() - rect.topLeft(), SideTop)
               << Candidate(QVector2D(rect.bottomLeft() - rect.topLeft()), QPointF(0.0, 0.0), SideLeft)
               << Candidate(QVector2D(rect.topLeft() - rect.bottomLeft()), rect.bottomLeft() - rect.topLeft(), SideLeft)
               << Candidate(QVector2D(rect.bottomRight() - rect.bottomLeft()), rect.bottomLeft() - rect.topLeft(), SideBottom)
               << Candidate(QVector2D(rect.bottomLeft() - rect.bottomRight()), rect.bottomRight() - rect.topLeft(), SideBottom)
               << Candidate(QVector2D(rect.bottomRight() - rect.topRight()), rect.topRight() - rect.topLeft(), SideRight)
               << Candidate(QVector2D(rect.topRight() - rect.bottomRight()), rect.bottomRight() - rect.topLeft(), SideRight);

    QVector<QVector2D> rectEdgeVectors;
    rectEdgeVectors << QVector2D(rect.topLeft() - rect.topLeft())
                    << QVector2D(rect.topRight() - rect.topLeft())
                    << QVector2D(rect.bottomLeft() - rect.topLeft())
                    << QVector2D(rect.bottomRight() -rect.topLeft());

    QVector2D directionVector(line.p2() - line.p1());
    directionVector.normalize();

    QVector2D sideVector(directionVector.y(), -directionVector.x());

    QVector2D intersectionVector(intersectionLine.p2() - intersectionLine.p1());
    intersectionVector.normalize();

    QVector2D outsideVector = QVector2D(intersectionVector.y(), -intersectionVector.x());
    double p = QVector2D::dotProduct(directionVector, outsideVector);
    if (p < 0.0)
        outsideVector = outsideVector * -1.0;

    double smallestA = -1.0;
    QPointF rectTranslation;
    Side side = SideUnspecified;
    int bestSign = 0;

    foreach (const Candidate &candidate, candidates) {
        // solve equation a * directionVector + candidate.first = b * intersectionVector to find smallest a
        double r = directionVector.x() * intersectionVector.y() - directionVector.y() * intersectionVector.x();
        if (r <= -1e-5 || r >= 1e-5) {
            double a = (candidate.first.y() * intersectionVector.x()
                        - candidate.first.x() * intersectionVector.y()) / r;
            if (a >= 0.0 && (smallestA < 0.0 || a < smallestA)) {
                // verify that all rectangle edges lay outside of shape (by checking for positiv projection to intersection)
                bool ok = true;
                int sign = 0;
                QVector2D rectOriginVector = directionVector * a - QVector2D(candidate.second);
                foreach (const QVector2D &rectEdgeVector, rectEdgeVectors) {
                    QVector2D edgeVector = rectOriginVector + rectEdgeVector;
                    double aa = QVector2D::dotProduct(outsideVector, edgeVector);
                    if (aa < 0.0) {
                        ok = false;
                        break;
                    }
                    int s = sgn(QVector2D::dotProduct(sideVector, edgeVector));
                    if (s) {
                        if (sign) {
                            if (s != sign) {
                                ok = false;
                                break;
                            }
                        } else {
                            sign = s;
                        }
                    }
                }
예제 #16
0
bool ccKdTreeForFacetExtraction::FuseCells(	ccKdTree* kdTree,
											double maxError,
											CCLib::DistanceComputationTools::ERROR_MEASURES errorMeasure,
											double maxAngle_deg,
											PointCoordinateType overlapCoef/*=1*/,
											bool closestFirst/*=true*/,
											CCLib::GenericProgressCallback* progressCb/*=0*/)
{
	if (!kdTree)
		return false;

	ccGenericPointCloud* associatedGenericCloud = kdTree->associatedGenericCloud();
	if (!associatedGenericCloud || !associatedGenericCloud->isA(CC_TYPES::POINT_CLOUD) || maxError < 0.0)
		return false;

	//get leaves
	std::vector<ccKdTree::Leaf*> leaves;
	if (!kdTree->getLeaves(leaves) || leaves.empty())
		return false;

	//progress notification
	CCLib::NormalizedProgress nProgress(progressCb, static_cast<unsigned>(leaves.size()));
	if (progressCb)
	{
		progressCb->update(0);
		if (progressCb->textCanBeEdited())
		{
			progressCb->setMethodTitle("Fuse Kd-tree cells");
			progressCb->setInfo(qPrintable(QString("Cells: %1\nMax error: %2").arg(leaves.size()).arg(maxError)));
		}
		progressCb->start();
	}

	ccPointCloud* pc = static_cast<ccPointCloud*>(associatedGenericCloud);

	//sort cells based on their population size (we start by the biggest ones)
	SortAlgo(leaves.begin(), leaves.end(), DescendingLeafSizeComparison);

	//set all 'userData' to -1 (i.e. unfused cells)
	{
		for (size_t i=0; i<leaves.size(); ++i)
		{
			leaves[i]->userData = -1;
			//check by the way that the plane normal is unit!
			assert(static_cast<double>(fabs(CCVector3(leaves[i]->planeEq).norm2()) - 1.0) < 1.0e-6);
		}
	}

	// cosine of the max angle between fused 'planes'
	const double c_minCosNormAngle = cos(maxAngle_deg * CC_DEG_TO_RAD);

	//fuse all cells, starting from the ones with the best error
	const int unvisitedNeighborValue = -1;
	bool cancelled = false;
	int macroIndex = 1; //starts at 1 (0 is reserved for cells already above the max error)
	{
		for (size_t i=0; i<leaves.size(); ++i)
		{
			ccKdTree::Leaf* currentCell = leaves[i];
			if (currentCell->error >= maxError)
				currentCell->userData = 0; //0 = special group for cells already above the user defined threshold!

			//already fused?
			if (currentCell->userData != -1)
			{
				if (progressCb && !nProgress.oneStep()) //process canceled by user
				{
					cancelled = true;
					break;
				}
				continue;
			}

			//we create a new "macro cell" index
			currentCell->userData = macroIndex++;

			//we init the current set of 'fused' points with the cell's points
			CCLib::ReferenceCloud* currentPointSet = currentCell->points;
			//get current fused set centroid and normal
			CCVector3 currentCentroid = *CCLib::Neighbourhood(currentPointSet).getGravityCenter();
			CCVector3 currentNormal(currentCell->planeEq);

			//visited neighbors
			ccKdTree::LeafSet visitedNeighbors;
			//set of candidates
			std::list<Candidate> candidates;

			//we are going to iteratively look for neighbor cells that could be fused to this one
			ccKdTree::LeafVector cellsToTest;
			cellsToTest.push_back(currentCell);

			if (progressCb && !nProgress.oneStep()) //process canceled by user
			{
				cancelled = true;
				break;
			}

			while (!cellsToTest.empty() || !candidates.empty())
			{
				//get all neighbors around the 'waiting' cell(s)
				if (!cellsToTest.empty())
				{
					ccKdTree::LeafSet neighbors;
					while (!cellsToTest.empty())
					{
						if (!kdTree->getNeighborLeaves(cellsToTest.back(), neighbors, &unvisitedNeighborValue)) //we only consider unvisited cells!
						{
							//an error occurred
							return false;
						}
						cellsToTest.pop_back();
					}

					//add those (new) neighbors to the 'visitedNeighbors' set
					//and to the candidates set by the way if they are not yet there
					for (ccKdTree::LeafSet::iterator it=neighbors.begin(); it != neighbors.end(); ++it)
					{
						ccKdTree::Leaf* neighbor = *it;
						std::pair<ccKdTree::LeafSet::iterator,bool> ret = visitedNeighbors.insert(neighbor);
						//neighbour not already in the set?
						if (ret.second)
						{
							//we create the corresponding candidate
							try
							{
								candidates.push_back(Candidate(neighbor));
							}
							catch (const std::bad_alloc&)
							{
								//not enough memory!
								ccLog::Warning("[ccKdTreeForFacetExtraction] Not enough memory!");
								return false;
							}
						}
					}
				}

				//is there remaining candidates?
				if (!candidates.empty())
				{
					//update the set of candidates
					if (closestFirst && candidates.size() > 1)
					{
						for (std::list<Candidate>::iterator it = candidates.begin(); it !=candidates.end(); ++it)
							it->dist = (it->centroid-currentCentroid).norm2();

						//sort candidates by their distance
						candidates.sort(CandidateDistAscendingComparison);
					}
					
					//we will keep track of the best fused 'couple' at each pass
					std::list<Candidate>::iterator bestIt = candidates.end();
					CCLib::ReferenceCloud* bestFused = 0;
					CCVector3 bestNormal(0,0,0);
					double bestError = -1.0;

					unsigned skipCount = 0;
					for (std::list<Candidate>::iterator it = candidates.begin(); it != candidates.end(); /*++it*/)
					{
						assert(it->leaf && it->leaf->points);
						assert(currentPointSet->getAssociatedCloud() == it->leaf->points->getAssociatedCloud());

						//if the leaf orientation is too different
						if (fabs(CCVector3(it->leaf->planeEq).dot(currentNormal)) < c_minCosNormAngle)
						{
							it = candidates.erase(it);
							//++it;
							//++skipCount;
							continue;
						}

						//compute the minimum distance between the candidate centroid and the 'currentPointSet'
						PointCoordinateType minDistToMainSet = 0.0;
						{
							for (unsigned j=0; j<currentPointSet->size(); ++j)
							{
								const CCVector3* P = currentPointSet->getPoint(j);
								PointCoordinateType d2 = (*P-it->centroid).norm2();
								if (d2 < minDistToMainSet || j == 0)
									minDistToMainSet = d2;
							}
							minDistToMainSet = sqrt(minDistToMainSet);
						}
						
						//if the leaf is too far
						if (it->radius < minDistToMainSet / overlapCoef)
						{
							++it;
							++skipCount;
							continue;
						}

						//fuse the main set with the current candidate
						CCLib::ReferenceCloud* fused = new CCLib::ReferenceCloud(*currentPointSet);
						if (!fused->add(*(it->leaf->points)))
						{
							//not enough memory!
							ccLog::Warning("[ccKdTreeForFacetExtraction] Not enough memory!");
							delete fused;
							if (currentPointSet != currentCell->points)
								delete currentPointSet;
							return false;
						}

						//fit a plane and estimate the resulting error
						double error = -1.0;
						const PointCoordinateType* planeEquation = CCLib::Neighbourhood(fused).getLSPlane();
						if (planeEquation)
							error = CCLib::DistanceComputationTools::ComputeCloud2PlaneDistance(fused, planeEquation, errorMeasure);

						if (error < 0.0 || error > maxError)
						{
							//candidate is rejected
							it = candidates.erase(it);
						}
						else
						{
							//otherwise we keep track of the best one!
							if (bestError < 0.0 || error < bestError)
							{
								bestIt = it;
								bestError = error;
								if (bestFused)
									delete bestFused;
								bestFused = fused;
								bestNormal = CCVector3(planeEquation);
								fused = 0;
								
								if (closestFirst)
									break; //if we have found a good candidate, we stop here (closest first ;)
							}
							++it;
						}

						if (fused)
						{
							delete fused;
							fused = 0;
						}
					}

					//we have a (best) candidate for this pass?
					if (bestIt != candidates.end())
					{
						assert(bestFused && bestError >= 0.0);
						if (currentPointSet != currentCell->points)
							delete currentPointSet;
						currentPointSet = bestFused;
						{
							//update infos
							CCLib::Neighbourhood N(currentPointSet);
							//currentCentroid = *N.getGravityCenter(); //if we update it, the search will naturally shift along one dimension!
							//currentNormal = bestNormal; //same thing here for normals
						}

						bestIt->leaf->userData = currentCell->userData;
						//bestIt->leaf->userData = macroIndex++; //FIXME TEST

						//we will test this cell's neighbors as well
						cellsToTest.push_back(bestIt->leaf);

						if (progressCb && !nProgress.oneStep()) //process canceled by user
						{
							//premature end!
							candidates.clear();
							cellsToTest.clear();
							cancelled = true;
							break;
						}
						QApplication::processEvents();

						//we also remove it from the candidates list
						candidates.erase(bestIt);
					}

					if (skipCount == candidates.size() && cellsToTest.empty())
					{
						//only far leaves remain...
						candidates.clear();
					}

				}
			
			} //no more candidates or cells to test

			//end of the fusion process for the current leaf
			if (currentPointSet != currentCell->points)
				delete currentPointSet;
			currentPointSet = 0;

			if (cancelled)
				break;
		}
	}

	//convert fused indexes to SF
	if (!cancelled)
	{
		pc->enableScalarField();

		for (size_t i=0; i<leaves.size(); ++i)
		{
			CCLib::ReferenceCloud* subset = leaves[i]->points;
			if (subset)
			{
				ScalarType scalar = (ScalarType)leaves[i]->userData;
				if (leaves[i]->userData <= 0) //for unfused cells, we create new individual groups
					scalar = static_cast<ScalarType>(macroIndex++);
					//scalar = NAN_VALUE; //FIXME TEST
				for (unsigned j=0; j<subset->size(); ++j)
					subset->setPointScalarValue(j,scalar);
			}
		}

		//pc->setCurrentDisplayedScalarField(sfIdx);
	}

	return !cancelled;
}