Files
test/source/blender/freestyle/intern/stroke/CurveIterators.h
Campbell Barton e955c94ed3 License Headers: Set copyright to "Blender Authors", add AUTHORS
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.
2023-08-16 00:20:26 +10:00

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 */