Listing the "Blender Foundation" as copyright holder implied the Blender Foundation holds copyright to files which may include work from many developers. While keeping copyright on headers makes sense for isolated libraries, Blender's own code may be refactored or moved between files in a way that makes the per file copyright holders less meaningful. Copyright references to the "Blender Foundation" have been replaced with "Blender Authors", with the exception of `./extern/` since these this contains libraries which are more isolated, any changed to license headers there can be handled on a case-by-case basis. Some directories in `./intern/` have also been excluded: - `./intern/cycles/` it's own `AUTHORS` file is planned. - `./intern/opensubdiv/`. An "AUTHORS" file has been added, using the chromium projects authors file as a template. Design task: #110784 Ref !110783.
291 lines
6.4 KiB
C++
291 lines
6.4 KiB
C++
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
#pragma once
|
|
|
|
/** \file
|
|
* \ingroup freestyle
|
|
* \brief Iterators used to iterate over the elements of the Curve
|
|
*/
|
|
|
|
#include "Curve.h"
|
|
#include "Stroke.h"
|
|
|
|
namespace Freestyle {
|
|
|
|
namespace CurveInternal {
|
|
|
|
/**
|
|
* Iterator on a curve. Allows an iterating outside
|
|
* initial vertices. A CurvePoint is instantiated an returned
|
|
* when the iterator is dereferenced.
|
|
*/
|
|
class CurvePointIterator : public Interface0DIteratorNested {
|
|
public:
|
|
friend class Freestyle::Curve;
|
|
|
|
public:
|
|
float _CurvilinearLength;
|
|
float _step;
|
|
Curve::vertex_container::iterator __A;
|
|
Curve::vertex_container::iterator __B;
|
|
Curve::vertex_container::iterator _begin;
|
|
Curve::vertex_container::iterator _end;
|
|
int _n;
|
|
int _currentn;
|
|
float _t;
|
|
mutable CurvePoint _Point;
|
|
float _CurveLength;
|
|
|
|
public:
|
|
inline CurvePointIterator(float step = 0.0f) : Interface0DIteratorNested()
|
|
{
|
|
_step = step;
|
|
_CurvilinearLength = 0.0f;
|
|
_t = 0.0f;
|
|
//_Point = 0;
|
|
_n = 0;
|
|
_currentn = 0;
|
|
_CurveLength = 0;
|
|
}
|
|
|
|
inline CurvePointIterator(const CurvePointIterator &iBrother) : Interface0DIteratorNested()
|
|
{
|
|
__A = iBrother.__A;
|
|
__B = iBrother.__B;
|
|
_begin = iBrother._begin;
|
|
_end = iBrother._end;
|
|
_CurvilinearLength = iBrother._CurvilinearLength;
|
|
_step = iBrother._step;
|
|
_t = iBrother._t;
|
|
_Point = iBrother._Point;
|
|
_n = iBrother._n;
|
|
_currentn = iBrother._currentn;
|
|
_CurveLength = iBrother._CurveLength;
|
|
}
|
|
|
|
inline CurvePointIterator &operator=(const CurvePointIterator &iBrother)
|
|
{
|
|
__A = iBrother.__A;
|
|
__B = iBrother.__B;
|
|
_begin = iBrother._begin;
|
|
_end = iBrother._end;
|
|
_CurvilinearLength = iBrother._CurvilinearLength;
|
|
_step = iBrother._step;
|
|
_t = iBrother._t;
|
|
_Point = iBrother._Point;
|
|
_n = iBrother._n;
|
|
_currentn = iBrother._currentn;
|
|
_CurveLength = iBrother._CurveLength;
|
|
return *this;
|
|
}
|
|
|
|
virtual ~CurvePointIterator() {}
|
|
|
|
protected:
|
|
inline CurvePointIterator(Curve::vertex_container::iterator iA,
|
|
Curve::vertex_container::iterator iB,
|
|
Curve::vertex_container::iterator ibegin,
|
|
Curve::vertex_container::iterator iend,
|
|
int currentn,
|
|
int n,
|
|
float iCurveLength,
|
|
float step,
|
|
float t = 0.0f,
|
|
float iCurvilinearLength = 0.0f)
|
|
: Interface0DIteratorNested()
|
|
{
|
|
__A = iA;
|
|
__B = iB;
|
|
_begin = ibegin;
|
|
_end = iend;
|
|
_CurvilinearLength = iCurvilinearLength;
|
|
_step = step;
|
|
_t = t;
|
|
_n = n;
|
|
_currentn = currentn;
|
|
_CurveLength = iCurveLength;
|
|
}
|
|
|
|
public:
|
|
virtual CurvePointIterator *copy() const
|
|
{
|
|
return new CurvePointIterator(*this);
|
|
}
|
|
|
|
inline Interface0DIterator castToInterface0DIterator() const
|
|
{
|
|
Interface0DIterator ret(new CurveInternal::CurvePointIterator(*this));
|
|
return ret;
|
|
}
|
|
|
|
virtual string getExactTypeName() const
|
|
{
|
|
return "CurvePointIterator";
|
|
}
|
|
|
|
// operators
|
|
inline CurvePointIterator &operator++() // operator corresponding to ++i
|
|
{
|
|
increment();
|
|
return *this;
|
|
}
|
|
|
|
inline CurvePointIterator &operator--() // operator corresponding to --i
|
|
{
|
|
decrement();
|
|
return *this;
|
|
}
|
|
|
|
// comparibility
|
|
virtual bool operator==(const Interface0DIteratorNested &b) const
|
|
{
|
|
const CurvePointIterator *it_exact = dynamic_cast<const CurvePointIterator *>(&b);
|
|
if (!it_exact) {
|
|
return false;
|
|
}
|
|
return ((__A == it_exact->__A) && (__B == it_exact->__B) && (_t == it_exact->_t));
|
|
}
|
|
|
|
// dereferencing
|
|
virtual CurvePoint &operator*()
|
|
{
|
|
return (_Point = CurvePoint(*__A, *__B, _t));
|
|
}
|
|
|
|
virtual CurvePoint *operator->()
|
|
{
|
|
return &(operator*());
|
|
}
|
|
|
|
virtual bool isBegin() const
|
|
{
|
|
if ((__A == _begin) && (_t < (float)M_EPSILON)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
virtual bool isEnd() const
|
|
{
|
|
if (__B == _end) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// protected:
|
|
virtual int increment()
|
|
{
|
|
if ((_currentn == _n - 1) && (_t == 1.0f)) {
|
|
// we're setting the iterator to end
|
|
++__A;
|
|
++__B;
|
|
++_currentn;
|
|
_t = 0.0f;
|
|
return 0;
|
|
}
|
|
|
|
if (0 == _step) { // means we iterate over initial vertices
|
|
Vec3r vec_tmp((*__B)->point2d() - (*__A)->point2d());
|
|
_CurvilinearLength += (float)vec_tmp.norm();
|
|
if (_currentn == _n - 1) {
|
|
_t = 1.0f;
|
|
return 0;
|
|
}
|
|
++__B;
|
|
++__A;
|
|
++_currentn;
|
|
return 0;
|
|
}
|
|
|
|
// compute the new position:
|
|
Vec3r vec_tmp2((*__A)->point2d() - (*__B)->point2d());
|
|
float normAB = (float)vec_tmp2.norm();
|
|
|
|
if (normAB > M_EPSILON) {
|
|
_CurvilinearLength += _step;
|
|
_t = _t + _step / normAB;
|
|
}
|
|
else {
|
|
_t = 1.0f; // AB is a null segment, we're directly at its end
|
|
}
|
|
// if normAB ~= 0, we don't change these values
|
|
if (_t >= 1) {
|
|
_CurvilinearLength -= normAB * (_t - 1);
|
|
if (_currentn == _n - 1) {
|
|
_t = 1.0f;
|
|
}
|
|
else {
|
|
_t = 0.0f;
|
|
++_currentn;
|
|
++__A;
|
|
++__B;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
virtual int decrement()
|
|
{
|
|
if (_t == 0.0f) { // we're at the beginning of the edge
|
|
_t = 1.0f;
|
|
--_currentn;
|
|
--__A;
|
|
--__B;
|
|
if (_currentn == _n - 1) {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if (0 == _step) { // means we iterate over initial vertices
|
|
Vec3r vec_tmp((*__B)->point2d() - (*__A)->point2d());
|
|
_CurvilinearLength -= (float)vec_tmp.norm();
|
|
_t = 0;
|
|
return 0;
|
|
}
|
|
|
|
// compute the new position:
|
|
Vec3r vec_tmp2((*__A)->point2d() - (*__B)->point2d());
|
|
float normAB = (float)vec_tmp2.norm();
|
|
|
|
if (normAB > M_EPSILON) {
|
|
_CurvilinearLength -= _step;
|
|
_t = _t - _step / normAB;
|
|
}
|
|
else {
|
|
_t = -1.0f; // We just need a negative value here
|
|
}
|
|
|
|
// round value
|
|
if (fabs(_t) < (float)M_EPSILON) {
|
|
_t = 0.0f;
|
|
}
|
|
if (_t < 0) {
|
|
if (_currentn == 0) {
|
|
_CurvilinearLength = 0.0f;
|
|
}
|
|
else {
|
|
_CurvilinearLength += normAB * (-_t);
|
|
}
|
|
_t = 0.0f;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
virtual float t() const
|
|
{
|
|
return _CurvilinearLength;
|
|
}
|
|
|
|
virtual float u() const
|
|
{
|
|
return _CurvilinearLength / _CurveLength;
|
|
}
|
|
};
|
|
|
|
} // end of namespace CurveInternal
|
|
|
|
} /* namespace Freestyle */
|