Files
test/source/blender/freestyle/intern/view_map/ViewMap.cpp
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

846 lines
23 KiB
C++

/* SPDX-FileCopyrightText: 2008-2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup freestyle
* \brief Classes to define a View Map (ViewVertex, ViewEdge, etc.)
*/
#include <cfloat>
#include "ViewMap.h"
#include "ViewMapAdvancedIterators.h"
#include "ViewMapIterators.h"
#include "../geometry/GeomUtils.h"
#include "BLI_sys_types.h"
namespace Freestyle {
/**********************************/
/* */
/* */
/* ViewMap */
/* */
/* */
/**********************************/
ViewMap *ViewMap::_pInstance = nullptr;
ViewMap::~ViewMap()
{
// The view vertices must be deleted here as some of them are shared between two shapes:
for (vector<ViewVertex *>::iterator vv = _VVertices.begin(), vvend = _VVertices.end();
vv != vvend;
vv++)
{
delete (*vv);
}
_VVertices.clear();
for (vector<ViewShape *>::iterator vs = _VShapes.begin(), vsend = _VShapes.end(); vs != vsend;
vs++)
{
delete (*vs);
}
_VShapes.clear();
_FEdges.clear();
_SVertices.clear();
_VEdges.clear();
}
void ViewMap::Clean()
{
vector<FEdge *> tmpEdges;
for (vector<ViewShape *>::iterator vs = _VShapes.begin(), vsend = _VShapes.end(); vs != vsend;
vs++)
{
vector<FEdge *> &edges = (*vs)->sshape()->getEdgeList();
for (vector<FEdge *>::iterator it = edges.begin(), itend = edges.end(); it != itend; it++) {
if ((*it)->isTemporary()) {
(*it)->setTemporary(false); // avoid being counted multiple times
tmpEdges.push_back(*it);
}
}
}
for (vector<FEdge *>::iterator it = tmpEdges.begin(), itend = tmpEdges.end(); it != itend; it++)
{
for (vector<ViewShape *>::iterator vs = _VShapes.begin(), vsend = _VShapes.end(); vs != vsend;
vs++)
{
(*vs)->sshape()->RemoveEdge(*it);
}
(*it)->vertexA()->RemoveFEdge(*it);
(*it)->vertexB()->RemoveFEdge(*it);
delete (*it);
}
}
ViewShape *ViewMap::viewShape(uint id)
{
int index = _shapeIdToIndex[id];
return _VShapes[index];
}
void ViewMap::AddViewShape(ViewShape *iVShape)
{
_shapeIdToIndex[iVShape->getId().getFirst()] = _VShapes.size();
_VShapes.push_back(iVShape);
}
const FEdge *ViewMap::getClosestFEdge(real x, real y) const
{
// find the closest of this candidates:
real minDist = DBL_MAX;
FEdge *winner = nullptr;
for (fedges_container::const_iterator fe = _FEdges.begin(), feend = _FEdges.end(); fe != feend;
fe++)
{
Vec2d A((*fe)->vertexA()->point2D()[0], (*fe)->vertexA()->point2D()[1]);
Vec2d B((*fe)->vertexB()->point2D()[0], (*fe)->vertexB()->point2D()[1]);
real dist = GeomUtils::distPointSegment<Vec2r>(Vec2r(x, y), A, B);
if (dist < minDist) {
minDist = dist;
winner = (*fe);
}
}
return winner;
}
const ViewEdge *ViewMap::getClosestViewEdge(real x, real y) const
{
// find the closest of this candidates:
real minDist = DBL_MAX;
FEdge *winner = nullptr;
for (fedges_container::const_iterator fe = _FEdges.begin(), feend = _FEdges.end(); fe != feend;
fe++)
{
Vec2d A((*fe)->vertexA()->point2D()[0], (*fe)->vertexA()->point2D()[1]);
Vec2d B((*fe)->vertexB()->point2D()[0], (*fe)->vertexB()->point2D()[1]);
real dist = GeomUtils::distPointSegment<Vec2r>(Vec2r(x, y), A, B);
if (dist < minDist) {
minDist = dist;
winner = (*fe);
}
}
if (!winner) {
return nullptr;
}
return winner->viewedge();
}
TVertex *ViewMap::CreateTVertex(const Vec3r &iA3D,
const Vec3r &iA2D,
FEdge *iFEdgeA,
const Vec3r &iB3D,
const Vec3r &iB2D,
FEdge *iFEdgeB,
const Id &id)
{
ViewShape *vshapeA = iFEdgeA->viewedge()->viewShape();
SShape *shapeA = iFEdgeA->shape();
ViewShape *vshapeB = iFEdgeB->viewedge()->viewShape();
SShape *shapeB = iFEdgeB->shape();
SVertex *Ia = shapeA->CreateSVertex(iA3D, iA2D, iFEdgeA->vertexA()->getId());
SVertex *Ib = shapeB->CreateSVertex(iB3D, iB2D, iFEdgeB->vertexA()->getId());
// depending on which of these 2 svertices is the nearest from the viewpoint, we're going to
// build the TVertex by giving them in an order or another (the first one must be the nearest)
real dista = Ia->point2D()[2];
real distb = Ib->point2D()[2];
TVertex *tvertex;
if (dista < distb) {
tvertex = new TVertex(Ia, Ib);
}
else {
tvertex = new TVertex(Ib, Ia);
}
tvertex->setId(id);
// add these vertices to the view map
AddViewVertex(tvertex);
AddSVertex(Ia);
AddSVertex(Ib);
// and this T Vertex to the view shapes:
vshapeA->AddVertex(tvertex);
vshapeB->AddVertex(tvertex);
return tvertex;
}
ViewVertex *ViewMap::InsertViewVertex(SVertex *iVertex, vector<ViewEdge *> &newViewEdges)
{
NonTVertex *vva = dynamic_cast<NonTVertex *>(iVertex->viewvertex());
if (vva) {
return vva;
}
// because it is not already a ViewVertex, this SVertex must have only 2 FEdges. The incoming one
// still belongs to ioEdge, the outgoing one now belongs to newVEdge
const vector<FEdge *> &fedges = iVertex->fedges();
if (fedges.size() != 2) {
cerr << "ViewMap warning: Can't split the ViewEdge" << endl;
return nullptr;
}
FEdge *fend(nullptr), *fbegin(nullptr);
for (vector<FEdge *>::const_iterator fe = fedges.begin(), feend = fedges.end(); fe != feend;
++fe) {
if ((*fe)->vertexB() == iVertex) {
fend = (*fe);
}
if ((*fe)->vertexA() == iVertex) {
fbegin = (*fe);
}
if ((fbegin != nullptr) && (fend != nullptr)) {
break;
}
}
ViewEdge *ioEdge = fbegin->viewedge();
ViewShape *vshape = ioEdge->viewShape();
vva = new NonTVertex(iVertex);
// if the ViewEdge is a closed loop, we don't create a new VEdge
if (ioEdge->A() == nullptr) {
// closed loop
ioEdge->setA(vva);
ioEdge->setB(vva);
// update sshape
vshape->sshape()->RemoveEdgeFromChain(ioEdge->fedgeA());
vshape->sshape()->RemoveEdgeFromChain(ioEdge->fedgeB());
ioEdge->setFEdgeA(fbegin);
ioEdge->setFEdgeB(fend);
// Update FEdges
fend->setNextEdge(nullptr);
fbegin->setPreviousEdge(nullptr);
// update new View Vertex:
vva->AddOutgoingViewEdge(ioEdge);
vva->AddIncomingViewEdge(ioEdge);
vshape->sshape()->AddChain(ioEdge->fedgeA());
vshape->sshape()->AddChain(ioEdge->fedgeB());
}
else {
// Create new ViewEdge
ViewEdge *newVEdge = new ViewEdge(vva, ioEdge->B(), fbegin, ioEdge->fedgeB(), vshape);
newVEdge->setId(Id(ioEdge->getId().getFirst(), ioEdge->getId().getSecond() + 1));
newVEdge->setNature(ioEdge->getNature());
// newVEdge->UpdateFEdges(); // done in the ViewEdge constructor
// Update old ViewEdge
ioEdge->setB(vva);
ioEdge->setFEdgeB(fend);
// Update FEdges
fend->setNextEdge(nullptr);
fbegin->setPreviousEdge(nullptr);
// update new View Vertex:
vva->AddOutgoingViewEdge(newVEdge);
vva->AddIncomingViewEdge(ioEdge);
NonTVertex *vvb = dynamic_cast<NonTVertex *>(newVEdge->B());
if (vvb) {
vvb->Replace(ioEdge, newVEdge);
}
// update ViewShape
// vshape->AddEdge(newVEdge);
// update SShape
vshape->sshape()->AddChain(fbegin);
// update ViewMap
//_VEdges.push_back(newVEdge);
newViewEdges.push_back(newVEdge);
}
// update ViewShape
vshape->AddVertex(vva);
// update ViewMap
_VVertices.push_back(vva);
return vva;
}
#if 0
FEdge *ViewMap::Connect(FEdge *ioEdge, SVertex *ioVertex, vector<ViewEdge *> &oNewVEdges)
{
SShape *sshape = ioEdge->shape();
FEdge *newFEdge = sshape->SplitEdgeIn2(ioEdge, ioVertex);
AddFEdge(newFEdge);
InsertViewVertex(ioVertex, oNewVEdges);
return newFEdge;
}
#endif
/**********************************/
/* */
/* */
/* TVertex */
/* */
/* */
/**********************************/
// is dve1 before dve2 ? (does it have a smaller angle ?)
static bool ViewEdgeComp(ViewVertex::directedViewEdge &dve1, ViewVertex::directedViewEdge &dve2)
{
FEdge *fe1;
if (dve1.second) {
fe1 = dve1.first->fedgeB();
}
else {
fe1 = dve1.first->fedgeA();
}
FEdge *fe2;
if (dve2.second) {
fe2 = dve2.first->fedgeB();
}
else {
fe2 = dve2.first->fedgeA();
}
Vec3r V1 = fe1->orientation2d();
Vec2r v1(V1.x(), V1.y());
v1.normalize();
Vec3r V2 = fe2->orientation2d();
Vec2r v2(V2.x(), V2.y());
v2.normalize();
if (v1.y() > 0) {
if (v2.y() < 0) {
return true;
}
return (v1.x() > v2.x());
}
if (v2.y() > 0) {
return false;
}
return (v1.x() < v2.x());
}
void TVertex::setFrontEdgeA(ViewEdge *iFrontEdgeA, bool incoming)
{
if (!iFrontEdgeA) {
cerr << "Warning: null pointer passed as argument of TVertex::setFrontEdgeA()" << endl;
return;
}
_FrontEdgeA = directedViewEdge(iFrontEdgeA, incoming);
if (!_sortedEdges.empty()) {
edge_pointers_container::iterator dve = _sortedEdges.begin(), dveend = _sortedEdges.end();
for (; (dve != dveend) && ViewEdgeComp(**dve, _FrontEdgeA); ++dve) {
/* pass */
}
_sortedEdges.insert(dve, &_FrontEdgeA);
}
else {
_sortedEdges.push_back(&_FrontEdgeA);
}
}
void TVertex::setFrontEdgeB(ViewEdge *iFrontEdgeB, bool incoming)
{
if (!iFrontEdgeB) {
cerr << "Warning: null pointer passed as argument of TVertex::setFrontEdgeB()" << endl;
return;
}
_FrontEdgeB = directedViewEdge(iFrontEdgeB, incoming);
if (!_sortedEdges.empty()) {
edge_pointers_container::iterator dve = _sortedEdges.begin(), dveend = _sortedEdges.end();
for (; (dve != dveend) && ViewEdgeComp(**dve, _FrontEdgeB); ++dve) {
/* pass */
}
_sortedEdges.insert(dve, &_FrontEdgeB);
}
else {
_sortedEdges.push_back(&_FrontEdgeB);
}
}
void TVertex::setBackEdgeA(ViewEdge *iBackEdgeA, bool incoming)
{
if (!iBackEdgeA) {
cerr << "Warning: null pointer passed as argument of TVertex::setBackEdgeA()" << endl;
return;
}
_BackEdgeA = directedViewEdge(iBackEdgeA, incoming);
if (!_sortedEdges.empty()) {
edge_pointers_container::iterator dve = _sortedEdges.begin(), dveend = _sortedEdges.end();
for (; (dve != dveend) && ViewEdgeComp(**dve, _BackEdgeA); ++dve) {
/* pass */
}
_sortedEdges.insert(dve, &_BackEdgeA);
}
else {
_sortedEdges.push_back(&_BackEdgeA);
}
}
void TVertex::setBackEdgeB(ViewEdge *iBackEdgeB, bool incoming)
{
if (!iBackEdgeB) {
cerr << "Warning: null pointer passed as argument of TVertex::setBackEdgeB()" << endl;
return;
}
_BackEdgeB = directedViewEdge(iBackEdgeB, incoming);
if (!_sortedEdges.empty()) {
edge_pointers_container::iterator dve = _sortedEdges.begin(), dveend = _sortedEdges.end();
for (; (dve != dveend) && ViewEdgeComp(**dve, _BackEdgeB); ++dve) {
/* pass */
}
_sortedEdges.insert(dve, &_BackEdgeB);
}
else {
_sortedEdges.push_back(&_BackEdgeB);
}
}
void TVertex::Replace(ViewEdge *iOld, ViewEdge *iNew)
{
// theoretically, we only replace edges for which this
// view vertex is the B vertex
if ((iOld == _FrontEdgeA.first) && (_FrontEdgeA.first->B() == this)) {
_FrontEdgeA.first = iNew;
return;
}
if ((iOld == _FrontEdgeB.first) && (_FrontEdgeB.first->B() == this)) {
_FrontEdgeB.first = iNew;
return;
}
if ((iOld == _BackEdgeA.first) && (_BackEdgeA.first->B() == this)) {
_BackEdgeA.first = iNew;
return;
}
if ((iOld == _BackEdgeB.first) && (_BackEdgeB.first->B() == this)) {
_BackEdgeB.first = iNew;
return;
}
}
/** iterators access */
ViewVertex::edge_iterator TVertex::edges_begin()
{
// return edge_iterator(_FrontEdgeA, _FrontEdgeB, _BackEdgeA, _BackEdgeB, _FrontEdgeA);
return edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin());
}
ViewVertex::const_edge_iterator TVertex::edges_begin() const
{
// return const_edge_iterator(_FrontEdgeA, _FrontEdgeB, _BackEdgeA, _BackEdgeB, _FrontEdgeA);
return const_edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin());
}
ViewVertex::edge_iterator TVertex::edges_end()
{
// return edge_iterator(_FrontEdgeA, _FrontEdgeB, _BackEdgeA, _BackEdgeB,
// directedViewEdge(0,true));
return edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.end());
}
ViewVertex::const_edge_iterator TVertex::edges_end() const
{
// return const_edge_iterator(_FrontEdgeA, _FrontEdgeB, _BackEdgeA, _BackEdgeB,
// directedViewEdge(0, true));
return const_edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.end());
}
ViewVertex::edge_iterator TVertex::edges_iterator(ViewEdge *iEdge)
{
for (edge_pointers_container::iterator it = _sortedEdges.begin(), itend = _sortedEdges.end();
it != itend;
it++)
{
if ((*it)->first == iEdge) {
return edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), it);
}
}
return edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin());
#if 0
directedViewEdge dEdge;
if (_FrontEdgeA.first == iEdge) {
dEdge = _FrontEdgeA;
}
else if (_FrontEdgeB.first == iEdge) {
dEdge = _FrontEdgeB;
}
else if (_BackEdgeA.first == iEdge) {
dEdge = _BackEdgeA;
}
else if (_BackEdgeB.first == iEdge) {
dEdge = _BackEdgeB;
}
return edge_iterator(_FrontEdgeA, _FrontEdgeB, _BackEdgeA, _BackEdgeB, dEdge);
#endif
}
ViewVertex::const_edge_iterator TVertex::edges_iterator(ViewEdge *iEdge) const
{
for (edge_pointers_container::const_iterator it = _sortedEdges.begin(),
itend = _sortedEdges.end();
it != itend;
it++)
{
if ((*it)->first == iEdge) {
return const_edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), it);
}
}
return const_edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin());
#if 0
directedViewEdge dEdge;
if (_FrontEdgeA.first == iEdge) {
dEdge = _FrontEdgeA;
}
else if (_FrontEdgeB.first == iEdge) {
dEdge = _FrontEdgeB;
}
else if (_BackEdgeA.first == iEdge) {
dEdge = _BackEdgeA;
}
else if (_BackEdgeB.first == iEdge) {
dEdge = _BackEdgeB;
}
return const_edge_iterator(_FrontEdgeA, _FrontEdgeB, _BackEdgeA, _BackEdgeB, dEdge);
#endif
}
ViewVertexInternal::orientedViewEdgeIterator TVertex::edgesBegin()
{
return ViewVertexInternal::orientedViewEdgeIterator(
_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin());
}
ViewVertexInternal::orientedViewEdgeIterator TVertex::edgesEnd()
{
return ViewVertexInternal::orientedViewEdgeIterator(
_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.end());
}
ViewVertexInternal::orientedViewEdgeIterator TVertex::edgesIterator(ViewEdge *iEdge)
{
for (edge_pointers_container::iterator it = _sortedEdges.begin(), itend = _sortedEdges.end();
it != itend;
it++)
{
if ((*it)->first == iEdge) {
return ViewVertexInternal::orientedViewEdgeIterator(
_sortedEdges.begin(), _sortedEdges.end(), it);
}
}
return ViewVertexInternal::orientedViewEdgeIterator(
_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin());
}
/**********************************/
/* */
/* */
/* NonTVertex */
/* */
/* */
/**********************************/
void NonTVertex::AddOutgoingViewEdge(ViewEdge *iVEdge)
{
// let's keep the viewedges ordered in CCW order in the 2D image plan
directedViewEdge idve(iVEdge, false);
if (!_ViewEdges.empty()) {
edges_container::iterator dve = _ViewEdges.begin(), dveend = _ViewEdges.end();
for (; (dve != dveend) && ViewEdgeComp(*dve, idve); ++dve) {
/* pass */
}
_ViewEdges.insert(dve, idve);
}
else {
_ViewEdges.push_back(idve);
}
}
void NonTVertex::AddIncomingViewEdge(ViewEdge *iVEdge)
{
// let's keep the viewedges ordered in CCW order in the 2D image plan
directedViewEdge idve(iVEdge, true);
if (!_ViewEdges.empty()) {
edges_container::iterator dve = _ViewEdges.begin(), dveend = _ViewEdges.end();
for (; (dve != dveend) && ViewEdgeComp(*dve, idve); ++dve) {
/* pass */
}
_ViewEdges.insert(dve, idve);
}
else {
_ViewEdges.push_back(idve);
}
}
/** iterators access */
ViewVertex::edge_iterator NonTVertex::edges_begin()
{
return edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin());
}
ViewVertex::const_edge_iterator NonTVertex::edges_begin() const
{
return const_edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin());
}
ViewVertex::edge_iterator NonTVertex::edges_end()
{
return edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.end());
}
ViewVertex::const_edge_iterator NonTVertex::edges_end() const
{
return const_edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.end());
}
ViewVertex::edge_iterator NonTVertex::edges_iterator(ViewEdge *iEdge)
{
for (edges_container::iterator it = _ViewEdges.begin(), itend = _ViewEdges.end(); it != itend;
it++)
{
if ((it)->first == iEdge) {
return edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), it);
}
}
return edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin());
}
ViewVertex::const_edge_iterator NonTVertex::edges_iterator(ViewEdge *iEdge) const
{
for (edges_container::const_iterator it = _ViewEdges.begin(), itend = _ViewEdges.end();
it != itend;
it++)
{
if ((it)->first == iEdge) {
return const_edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), it);
}
}
return const_edge_iterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin());
}
ViewVertexInternal::orientedViewEdgeIterator NonTVertex::edgesBegin()
{
return ViewVertexInternal::orientedViewEdgeIterator(
_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin());
}
ViewVertexInternal::orientedViewEdgeIterator NonTVertex::edgesEnd()
{
return ViewVertexInternal::orientedViewEdgeIterator(
_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.end());
}
ViewVertexInternal::orientedViewEdgeIterator NonTVertex::edgesIterator(ViewEdge *iEdge)
{
for (edges_container::iterator it = _ViewEdges.begin(), itend = _ViewEdges.end(); it != itend;
it++)
{
if ((it)->first == iEdge) {
return ViewVertexInternal::orientedViewEdgeIterator(
_ViewEdges.begin(), _ViewEdges.end(), it);
}
}
return ViewVertexInternal::orientedViewEdgeIterator(
_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin());
}
/**********************************/
/* */
/* */
/* ViewEdge */
/* */
/* */
/**********************************/
real ViewEdge::getLength2D() const
{
float length = 0.0f;
ViewEdge::const_fedge_iterator itlast = fedge_iterator_last();
ViewEdge::const_fedge_iterator it = fedge_iterator_begin(), itend = fedge_iterator_end();
Vec2r seg;
do {
seg = Vec2r((*it)->orientation2d()[0], (*it)->orientation2d()[1]);
length += seg.norm();
++it;
} while ((it != itend) && (it != itlast));
return length;
}
//! view edge iterator
ViewEdge::edge_iterator ViewEdge::ViewEdge_iterator()
{
return edge_iterator(this);
}
ViewEdge::const_edge_iterator ViewEdge::ViewEdge_iterator() const
{
return const_edge_iterator((ViewEdge *)this);
}
//! feature edge iterator
ViewEdge::fedge_iterator ViewEdge::fedge_iterator_begin()
{
return fedge_iterator(this->_FEdgeA, this->_FEdgeB);
}
ViewEdge::const_fedge_iterator ViewEdge::fedge_iterator_begin() const
{
return const_fedge_iterator(this->_FEdgeA, this->_FEdgeB);
}
ViewEdge::fedge_iterator ViewEdge::fedge_iterator_last()
{
return fedge_iterator(this->_FEdgeB, this->_FEdgeB);
}
ViewEdge::const_fedge_iterator ViewEdge::fedge_iterator_last() const
{
return const_fedge_iterator(this->_FEdgeB, this->_FEdgeB);
}
ViewEdge::fedge_iterator ViewEdge::fedge_iterator_end()
{
return fedge_iterator(nullptr, this->_FEdgeB);
}
ViewEdge::const_fedge_iterator ViewEdge::fedge_iterator_end() const
{
return const_fedge_iterator(nullptr, this->_FEdgeB);
}
//! embedding vertex iterator
ViewEdge::const_vertex_iterator ViewEdge::vertices_begin() const
{
return const_vertex_iterator(this->_FEdgeA->vertexA(), nullptr, _FEdgeA);
}
ViewEdge::vertex_iterator ViewEdge::vertices_begin()
{
return vertex_iterator(this->_FEdgeA->vertexA(), nullptr, _FEdgeA);
}
ViewEdge::const_vertex_iterator ViewEdge::vertices_last() const
{
return const_vertex_iterator(this->_FEdgeB->vertexB(), _FEdgeB, nullptr);
}
ViewEdge::vertex_iterator ViewEdge::vertices_last()
{
return vertex_iterator(this->_FEdgeB->vertexB(), _FEdgeB, nullptr);
}
ViewEdge::const_vertex_iterator ViewEdge::vertices_end() const
{
return const_vertex_iterator(nullptr, _FEdgeB, nullptr);
}
ViewEdge::vertex_iterator ViewEdge::vertices_end()
{
return vertex_iterator(nullptr, _FEdgeB, nullptr);
}
Interface0DIterator ViewEdge::verticesBegin()
{
Interface0DIterator ret(new ViewEdgeInternal::SVertexIterator(
this->_FEdgeA->vertexA(), this->_FEdgeA->vertexA(), nullptr, _FEdgeA, 0.0f));
return ret;
}
Interface0DIterator ViewEdge::verticesEnd()
{
Interface0DIterator ret(new ViewEdgeInternal::SVertexIterator(
nullptr, this->_FEdgeA->vertexA(), _FEdgeB, nullptr, getLength2D()));
return ret;
}
Interface0DIterator ViewEdge::pointsBegin(float /*t*/)
{
return verticesBegin();
}
Interface0DIterator ViewEdge::pointsEnd(float /*t*/)
{
return verticesEnd();
}
/**********************************/
/* */
/* */
/* ViewShape */
/* */
/* */
/**********************************/
ViewShape::~ViewShape()
{
_Vertices.clear();
if (!_Edges.empty()) {
for (vector<ViewEdge *>::iterator e = _Edges.begin(), eend = _Edges.end(); e != eend; e++) {
delete (*e);
}
_Edges.clear();
}
if (_SShape) {
delete _SShape;
_SShape = nullptr;
}
}
void ViewShape::RemoveEdge(ViewEdge *iViewEdge)
{
FEdge *fedge = iViewEdge->fedgeA();
for (vector<ViewEdge *>::iterator ve = _Edges.begin(), veend = _Edges.end(); ve != veend; ve++) {
if (iViewEdge == (*ve)) {
_Edges.erase(ve);
_SShape->RemoveEdge(fedge);
break;
}
}
}
void ViewShape::RemoveVertex(ViewVertex *iViewVertex)
{
for (vector<ViewVertex *>::iterator vv = _Vertices.begin(), vvend = _Vertices.end(); vv != vvend;
vv++)
{
if (iViewVertex == (*vv)) {
_Vertices.erase(vv);
break;
}
}
}
/**********************************/
/* */
/* */
/* ViewEdge */
/* */
/* */
/**********************************/
void ViewEdge::UpdateFEdges()
{
FEdge *currentEdge = _FEdgeA;
do {
currentEdge->setViewEdge(this);
currentEdge = currentEdge->nextEdge();
} while (!ELEM(currentEdge, nullptr, _FEdgeB));
// last one
_FEdgeB->setViewEdge(this);
}
} /* namespace Freestyle */