コード例 #1
0
ファイル: Operators.cpp プロジェクト: Ichthyostega/blender
// recursive split with pred 0D
static int __recursiveSplit(Chain *_curve, UnaryFunction0D<double>& func, UnaryPredicate0D& pred0d,
                            UnaryPredicate1D& pred, float sampling,
                            Operators::I1DContainer& newChains, Operators::I1DContainer& splitted_chains)
{
	if (((_curve->nSegments() == 1) && (sampling == 0)) || (_curve->getLength2D() <= sampling)) {
		newChains.push_back(_curve);
		return 0;
	}

	CurveInternal::CurvePointIterator first  = _curve->curvePointsBegin(sampling);
	CurveInternal::CurvePointIterator second = first;
	++second;
	CurveInternal::CurvePointIterator end      = _curve->curvePointsEnd(sampling);
	CurveInternal::CurvePointIterator it       = second;
	CurveInternal::CurvePointIterator split    = second;
	Interface0DIterator it0d                   = it.castToInterface0DIterator();
#if 0
	real _min                                  = func(it0d);
	++it;
#endif
	real _min                                  = FLT_MAX;
	++it;
	real mean                                  = 0.f;
	//soc unused - real variance                              = 0.0f;
	unsigned count                             = 0;
	CurveInternal::CurvePointIterator next     = it;
	++next;

	bool bsplit = false;
	for (; ((it != end) && (next != end)); ++it, ++next) {
		++count;
		it0d = it.castToInterface0DIterator();
		if (pred0d(it0d) < 0)
			return -1;
		if (!pred0d.result)
			continue;
		if (func(it0d) < 0)
			return -1;
		mean += func.result;
		if (func.result < _min) {
			_min = func.result;
			split = it;
			bsplit = true;
		}
	}
	mean /= (float)count;

	//if ((!bsplit) || (mean - _min > mean)) { // we didn't find any minimum
	if (!bsplit) { // we didn't find any minimum
		newChains.push_back(_curve);
		return 0;
	}

	// retrieves the current splitting id
	Id *newId = _curve->getSplittingId();
	if (newId == NULL) {
		newId = new Id(_curve->getId());
		_curve->setSplittingId(newId);
	}

	Chain *new_curve_a = new Chain(*newId);
	newId->setSecond(newId->getSecond() + 1);
	new_curve_a->setSplittingId(newId);
	Chain *new_curve_b = new Chain(*newId);
	newId->setSecond(newId->getSecond() + 1);
	new_curve_b->setSplittingId(newId);

	CurveInternal::CurvePointIterator vit = _curve->curveVerticesBegin(), vitend = _curve->curveVerticesEnd();
	CurveInternal::CurvePointIterator vnext = vit;
	++vnext;

	for (;
	     (vit != vitend) && (vnext != vitend) && (vnext._CurvilinearLength < split._CurvilinearLength);
	     ++vit, ++vnext)
	{
		new_curve_a->push_vertex_back(&(*vit));
	}
	if ((vit == vitend) || (vnext == vitend)) {
		if (G.debug & G_DEBUG_FREESTYLE) {
			cout << "The split takes place in bad location" << endl;
		}
		newChains.push_back(_curve);
		delete new_curve_a;
		delete new_curve_b;
		return 0;
	}

	// build the two resulting chains
	new_curve_a->push_vertex_back(&(*vit));
	new_curve_a->push_vertex_back(&(*split));
	new_curve_b->push_vertex_back(&(*split));

	for (vit = vnext; vit != vitend; ++vit)
		new_curve_b->push_vertex_back(&(*vit));

	// let's check whether one or two of the two new curves satisfy the stopping condition or not.
	// (if one of them satisfies it, we don't split)
	if (pred(*new_curve_a) < 0 || (!pred.result && pred(*new_curve_b) < 0)) {
		delete new_curve_a;
		delete new_curve_b;
		return -1;
	}
	if (pred.result) {
		// we don't actually create these two chains
		newChains.push_back(_curve);
		delete new_curve_a;
		delete new_curve_b;
		return 0;
	}
	// here we know we'll split _curve:
	splitted_chains.push_back(_curve);

	__recursiveSplit(new_curve_a, func, pred0d, pred, sampling, newChains, splitted_chains);
	__recursiveSplit(new_curve_b, func, pred0d, pred, sampling, newChains, splitted_chains);
	return 0;
}
コード例 #2
0
ファイル: Operators.cpp プロジェクト: Ichthyostega/blender
int Operators::sequentialSplit(UnaryPredicate0D& startingPred, UnaryPredicate0D& stoppingPred, float sampling)
{
	if (_current_chains_set.empty()) {
		cerr << "Warning: current set empty" << endl;
		return 0;
	}
	CurvePoint *point;
	Chain *new_curve;
	I1DContainer splitted_chains;
	Interface0DIterator first;
	Interface0DIterator end;
	Interface0DIterator last;
	Interface0DIterator itStart;
	Interface0DIterator itStop;
	I1DContainer::iterator cit = _current_chains_set.begin(), citend = _current_chains_set.end();
	for (; cit != citend; ++cit) {
		Id currentId = (*cit)->getId();
		first = (*cit)->pointsBegin(sampling);
		end = (*cit)->pointsEnd(sampling);
		last = end;
		--last;
		itStart = first;
		do {
			itStop = itStart;
			++itStop;

			new_curve = new Chain(currentId);
			currentId.setSecond(currentId.getSecond() + 1);

			point = dynamic_cast<CurvePoint*>(&(*itStart));
			new_curve->push_vertex_back(point);
			do {
				point = dynamic_cast<CurvePoint*>(&(*itStop));
				new_curve->push_vertex_back(point);
				++itStop;
				if (itStop == end)
					break;
				if (stoppingPred(itStop) < 0) {
					delete new_curve;
					goto error;
				}
			} while (!stoppingPred.result);
			if (itStop != end) {
				point = dynamic_cast<CurvePoint*>(&(*itStop));
				new_curve->push_vertex_back(point);
			}
			if (new_curve->nSegments() == 0) {
				delete new_curve;
			}
			else {
				splitted_chains.push_back(new_curve);
			}
			// find next start
			do {
				++itStart;
				if (itStart == end)
					break;
				if (startingPred(itStart) < 0)
					goto error;
			} while (!startingPred.result);
		} while ((itStart != end) && (itStart != last));
	}

	// Update the current set of chains:
	cit = _current_chains_set.begin();
	for (; cit != citend; ++cit) {
		delete (*cit);
	}
	_current_chains_set.clear();
#if 0
	_current_chains_set = splitted_chains;
#else
	for (cit = splitted_chains.begin(), citend = splitted_chains.end(); cit != citend; ++cit) {
		if ((*cit)->getLength2D() < M_EPSILON) {
			delete (*cit);
			continue;
		}
		_current_chains_set.push_back(*cit);
	}
#endif
	splitted_chains.clear();

	if (!_current_chains_set.empty())
		_current_set = &_current_chains_set;
	return 0;

error:
	cit = splitted_chains.begin();
	citend = splitted_chains.end();
	for (; cit != citend; ++cit) {
		delete (*cit);
	}
	splitted_chains.clear();
	return -1;
}