The view map is mostly treated as a read-only data structure by line stylization operations (i.e., selection, chaining, splitting, sorting and stroke creation). The only exception is the chaining operation in some cases where insertion of extra FEdge objects is necessary to ensure the continuity of underlying FEdges from which a chain is constructed. The present revision addresses the removal of extra FEdges so to keep the view map clean and suitable for reuse in subsequent render frames.
1808 lines
46 KiB
C++
1808 lines
46 KiB
C++
/*
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
*/
|
|
|
|
#ifndef __FREESTYLE_VIEW_MAP_H__
|
|
#define __FREESTYLE_VIEW_MAP_H__
|
|
|
|
/** \file blender/freestyle/intern/view_map/ViewMap.h
|
|
* \ingroup freestyle
|
|
* \brief Classes to define a View Map (ViewVertex, ViewEdge, etc.)
|
|
* \author Stephane Grabli
|
|
* \date 03/09/2002
|
|
*/
|
|
|
|
#include <map>
|
|
|
|
#include "Interface0D.h"
|
|
#include "Interface1D.h"
|
|
#include "Silhouette.h" // defines the embedding
|
|
|
|
#include "../geometry/GeomUtils.h"
|
|
|
|
#include "../system/BaseIterator.h"
|
|
#include "../system/FreestyleConfig.h"
|
|
|
|
#ifdef WITH_CXX_GUARDEDALLOC
|
|
#include "MEM_guardedalloc.h"
|
|
#endif
|
|
|
|
namespace Freestyle {
|
|
|
|
/**********************************/
|
|
/* */
|
|
/* */
|
|
/* ViewMap */
|
|
/* */
|
|
/* */
|
|
/**********************************/
|
|
|
|
|
|
/* Density
|
|
* Mean area depth value
|
|
* distance to a point
|
|
*/
|
|
|
|
class ViewVertex;
|
|
class ViewEdge;
|
|
class ViewShape;
|
|
class TVertex;
|
|
|
|
/*! Class defining the ViewMap.*/
|
|
class ViewMap
|
|
{
|
|
public:
|
|
typedef vector<ViewEdge*> viewedges_container;
|
|
typedef vector<ViewVertex*> viewvertices_container;
|
|
typedef vector<ViewShape*> viewshapes_container;
|
|
typedef vector<SVertex*> svertices_container;
|
|
typedef vector<FEdge*> fedges_container;
|
|
typedef map<int, int> id_to_index_map;
|
|
|
|
private:
|
|
static ViewMap *_pInstance;
|
|
viewshapes_container _VShapes; // view shapes
|
|
viewedges_container _VEdges; // view edges
|
|
viewvertices_container _VVertices; // view vertices
|
|
fedges_container _FEdges; // feature edges (embedded edges)
|
|
svertices_container _SVertices; // embedded vertices
|
|
BBox<Vec3r> _scene3DBBox;
|
|
// Mapping between the WShape or VShape id to the VShape index in the _VShapes vector. Used in the method
|
|
// viewShape(int id) to access a shape from its id.
|
|
id_to_index_map _shapeIdToIndex;
|
|
|
|
public:
|
|
/*! A field that can be used by the user to store any data.
|
|
* This field must be reseted afterwards using ResetUserData().
|
|
*/
|
|
void *userdata;
|
|
|
|
/*! Default constructor. */
|
|
ViewMap()
|
|
{
|
|
_pInstance = this;
|
|
userdata = NULL;
|
|
}
|
|
|
|
/*! Destructor. */
|
|
virtual ~ViewMap();
|
|
|
|
/*! Gets the viewedge the nearest to the 2D position specified as argument */
|
|
const ViewEdge *getClosestViewEdge(real x, real y) const;
|
|
|
|
/*! Gets the Fedge the nearest to the 2D position specified as argument */
|
|
const FEdge *getClosestFEdge(real x, real y) const;
|
|
|
|
/* accessors */
|
|
/*! The ViewMap is a singleton class. This static method returns the instance of the ViewMap. */
|
|
static inline ViewMap *getInstance()
|
|
{
|
|
return _pInstance;
|
|
}
|
|
|
|
/* Returns the list of ViewShapes of the scene. */
|
|
inline viewshapes_container& ViewShapes()
|
|
{
|
|
return _VShapes;
|
|
}
|
|
|
|
/* Returns the list of ViewEdges of the scene. */
|
|
inline viewedges_container& ViewEdges()
|
|
{
|
|
return _VEdges;
|
|
}
|
|
|
|
/* Returns the list of ViewVertices of the scene. */
|
|
inline viewvertices_container& ViewVertices()
|
|
{
|
|
return _VVertices;
|
|
}
|
|
|
|
/* Returns the list of FEdges of the scene. */
|
|
inline fedges_container& FEdges()
|
|
{
|
|
return _FEdges;
|
|
}
|
|
|
|
/* Returns the list of SVertices of the scene. */
|
|
inline svertices_container& SVertices()
|
|
{
|
|
return _SVertices;
|
|
}
|
|
|
|
/* Returns an iterator pointing onto the first ViewEdge of the list. */
|
|
inline viewedges_container::iterator viewedges_begin()
|
|
{
|
|
return _VEdges.begin();
|
|
}
|
|
|
|
inline viewedges_container::iterator viewedges_end()
|
|
{
|
|
return _VEdges.end();
|
|
}
|
|
|
|
inline int viewedges_size()
|
|
{
|
|
return _VEdges.size();
|
|
}
|
|
|
|
ViewShape *viewShape(unsigned index);
|
|
|
|
id_to_index_map& shapeIdToIndexMap()
|
|
{
|
|
return _shapeIdToIndex;
|
|
}
|
|
|
|
/*! Returns the scene 3D bounding box. */
|
|
inline BBox<Vec3r> getScene3dBBox() const
|
|
{
|
|
return _scene3DBBox;
|
|
}
|
|
|
|
/* modifiers */
|
|
void AddViewShape(ViewShape *iVShape);
|
|
|
|
inline void AddViewEdge(ViewEdge *iVEdge)
|
|
{
|
|
_VEdges.push_back(iVEdge);
|
|
}
|
|
|
|
inline void AddViewVertex(ViewVertex *iVVertex)
|
|
{
|
|
_VVertices.push_back(iVVertex);
|
|
}
|
|
|
|
inline void AddFEdge(FEdge *iFEdge)
|
|
{
|
|
_FEdges.push_back(iFEdge);
|
|
}
|
|
|
|
inline void AddSVertex(SVertex *iSVertex)
|
|
{
|
|
_SVertices.push_back(iSVertex);
|
|
}
|
|
|
|
/*! Sets the scene 3D bounding box. */
|
|
inline void setScene3dBBox(const BBox<Vec3r>& bbox)
|
|
{
|
|
_scene3DBBox = bbox;
|
|
}
|
|
|
|
/* Creates a T vertex in the view map.
|
|
* A T vertex is the intersection between 2 FEdges (before these ones are splitted).
|
|
* The TVertex is a 2D intersection but it corresponds to a 3D point on each of the 2 FEdges.
|
|
* iA3D
|
|
* The 3D coordinates of the point corresponding to the intersection on the first edge.
|
|
* iA2D
|
|
* The x,y,z 2D coordinates of the projection of iA3D
|
|
* iFEdgeA
|
|
* The first FEdge
|
|
* iB3D
|
|
* The 3D coordinates of the point corresponding to the intersection on the second edge.
|
|
* iB2D
|
|
* The x,y,z 2D coordinates of the projection of iB3D
|
|
* iFEdgeB
|
|
* The second FEdge
|
|
* id
|
|
* The id that must be given to that TVertex
|
|
*/
|
|
TVertex *CreateTVertex(const Vec3r& iA3D, const Vec3r& iA2D, FEdge *iFEdgeA, const Vec3r& iB3D, const Vec3r& iB2D,
|
|
FEdge *iFEdgeB, const Id& id);
|
|
|
|
/* Updates the structures to take into account the fact that a SVertex must now be considered as a ViewVertex
|
|
* iVertex
|
|
* The SVertex on top of which the ViewVertex is built (it is necessarily a NonTVertex because it is a SVertex)
|
|
* newViewEdges
|
|
* The new ViewEdges that must be add to the ViewMap
|
|
*/
|
|
ViewVertex *InsertViewVertex(SVertex *iVertex, vector<ViewEdge*>& newViewEdges);
|
|
|
|
/* connects a FEdge to the graph trough a SVertex */
|
|
//FEdge *Connect(FEdge *ioEdge, SVertex *ioVertex);
|
|
|
|
/* Clean temporary FEdges created by chaining */
|
|
virtual void Clean();
|
|
|
|
#ifdef WITH_CXX_GUARDEDALLOC
|
|
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:ViewMap")
|
|
#endif
|
|
};
|
|
|
|
/**********************************/
|
|
/* */
|
|
/* */
|
|
/* ViewVertex */
|
|
/* */
|
|
/* */
|
|
/**********************************/
|
|
|
|
class ViewEdge;
|
|
class SShape;
|
|
|
|
namespace ViewVertexInternal {
|
|
|
|
class edge_const_traits;
|
|
class edge_nonconst_traits;
|
|
template<class Traits> class edge_iterator_base;
|
|
class orientedViewEdgeIterator;
|
|
|
|
} // end of namespace ViewEdgeInternal
|
|
|
|
/*! Class to define a view vertex.
|
|
* A view vertex is a feature vertex corresponding to a point of the image graph, where the characteristics of an
|
|
* edge might change (nature, visibility, ...).
|
|
* A ViewVertex can be of two kinds: a TVertex when it corresponds to the intersection between two ViewEdges or a
|
|
* NonTVertex when it corresponds to a vertex of the initial input mesh (it is the case for vertices such as corners
|
|
* for example). Thus, this class can be specialized into two classes, the TVertex class and the NonTVertex class.
|
|
*/
|
|
class ViewVertex : public Interface0D
|
|
{
|
|
public: // Implementation of Interface0D
|
|
/*! Returns the string "ViewVertex". */
|
|
virtual string getExactTypeName() const
|
|
{
|
|
return "ViewVertex";
|
|
}
|
|
|
|
public:
|
|
friend class ViewShape;
|
|
typedef pair<ViewEdge *, bool> directedViewEdge; // if bool = true, the ViewEdge is incoming
|
|
|
|
typedef vector<directedViewEdge> edges_container;
|
|
|
|
typedef ViewVertexInternal::edge_iterator_base<ViewVertexInternal::edge_nonconst_traits> edge_iterator;
|
|
typedef ViewVertexInternal::edge_iterator_base<ViewVertexInternal::edge_const_traits> const_edge_iterator;
|
|
|
|
private:
|
|
Nature::VertexNature _Nature;
|
|
|
|
public:
|
|
/*! A field that can be used by the user to store any data.
|
|
* This field must be reseted afterwards using ResetUserData().
|
|
*/
|
|
void *userdata;
|
|
|
|
/*! Default constructor.*/
|
|
inline ViewVertex()
|
|
{
|
|
userdata = NULL;
|
|
_Nature = Nature::VIEW_VERTEX;
|
|
}
|
|
|
|
inline ViewVertex(Nature::VertexNature nature)
|
|
{
|
|
userdata = NULL;
|
|
_Nature = Nature::VIEW_VERTEX | nature;
|
|
}
|
|
|
|
protected:
|
|
/*! Copy constructor. */
|
|
inline ViewVertex(ViewVertex& iBrother)
|
|
{
|
|
_Nature = iBrother._Nature;
|
|
iBrother.userdata = this;
|
|
userdata = NULL;
|
|
}
|
|
|
|
/*! Cloning method. */
|
|
virtual ViewVertex *duplicate() = 0;
|
|
|
|
public:
|
|
/*! Destructor. */
|
|
virtual ~ViewVertex() {}
|
|
|
|
/* accessors */
|
|
/*! Returns the nature of the vertex .*/
|
|
virtual Nature::VertexNature getNature() const
|
|
{
|
|
return _Nature;
|
|
}
|
|
|
|
/* modifiers */
|
|
/*! Sets the nature of the vertex. */
|
|
inline void setNature(Nature::VertexNature iNature)
|
|
{
|
|
_Nature = iNature;
|
|
}
|
|
|
|
/* Replaces old edge by new edge */
|
|
virtual void Replace(ViewEdge *, ViewEdge *) {}
|
|
|
|
public:
|
|
/* iterators access */
|
|
// allows iteration on the edges that comes from/goes to this vertex in CCW order (order defined in 2D in the
|
|
// image plan)
|
|
virtual edge_iterator edges_begin() = 0;
|
|
virtual const_edge_iterator edges_begin() const = 0;
|
|
virtual edge_iterator edges_end() = 0;
|
|
virtual const_edge_iterator edges_end() const = 0;
|
|
virtual edge_iterator edges_iterator(ViewEdge *iEdge) = 0;
|
|
virtual const_edge_iterator edges_iterator(ViewEdge *iEdge) const = 0;
|
|
|
|
// Iterator access
|
|
/*! Returns an iterator over the ViewEdges that goes to or comes from this ViewVertex pointing to the first
|
|
* ViewEdge of the list. The orientedViewEdgeIterator allows to iterate in CCW order over these ViewEdges
|
|
* and to get the orientation for each ViewEdge (incoming/outgoing).
|
|
*/
|
|
virtual ViewVertexInternal::orientedViewEdgeIterator edgesBegin() = 0;
|
|
|
|
/*! Returns an orientedViewEdgeIterator over the ViewEdges around this ViewVertex, pointing after the last ViewEdge.
|
|
*/
|
|
virtual ViewVertexInternal::orientedViewEdgeIterator edgesEnd() = 0;
|
|
|
|
/*! Returns an orientedViewEdgeIterator pointing to the ViewEdge given as argument. */
|
|
virtual ViewVertexInternal::orientedViewEdgeIterator edgesIterator(ViewEdge *iEdge) = 0;
|
|
|
|
#ifdef WITH_CXX_GUARDEDALLOC
|
|
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:ViewVertex")
|
|
#endif
|
|
};
|
|
|
|
/**********************************/
|
|
/* */
|
|
/* */
|
|
/* TVertex */
|
|
/* */
|
|
/* */
|
|
/**********************************/
|
|
|
|
/*! class to define a T vertex, i.e. an intersection between two edges.
|
|
* It points towards 2 SVertex and 4 View edges.
|
|
* Among these ViewEdges, 2 are front and 2 are back.
|
|
* Basically the front edge hides part of the back edge.
|
|
* So, among the back edges, 1 is of invisibility n and the other of visibility n+1
|
|
*/
|
|
class TVertex : public ViewVertex
|
|
{
|
|
public:
|
|
typedef vector<directedViewEdge*> edge_pointers_container;
|
|
|
|
public: // Implementation of Interface0D
|
|
/*! Returns the string "TVertex". */
|
|
virtual string getExactTypeName() const
|
|
{
|
|
return "TVertex";
|
|
}
|
|
|
|
// Data access methods
|
|
/* Returns the 3D x coordinate of the vertex. Ambiguous in this case. */
|
|
virtual real getX() const
|
|
{
|
|
cerr << "Warning: getX() undefined for this point" << endl;
|
|
return _FrontSVertex->point3D().x();
|
|
}
|
|
|
|
virtual real getY() const
|
|
{
|
|
cerr << "Warning: getX() undefined for this point" << endl;
|
|
return _FrontSVertex->point3D().y();
|
|
}
|
|
|
|
virtual real getZ() const
|
|
{
|
|
cerr << "Warning: getX() undefined for this point" << endl;
|
|
return _FrontSVertex->point3D().z();
|
|
}
|
|
|
|
/*! Returns the 3D point. */
|
|
virtual Vec3r getPoint3D() const
|
|
{
|
|
cerr << "Warning: getPoint3D() undefined for this point" << endl;
|
|
return _FrontSVertex->getPoint3D();
|
|
}
|
|
|
|
/*! Returns the projected 3D x coordinate of the vertex. */
|
|
virtual real getProjectedX() const
|
|
{
|
|
return _FrontSVertex->point2D().x();
|
|
}
|
|
|
|
/*! Returns the projected 3D y coordinate of the vertex. */
|
|
virtual real getProjectedY() const
|
|
{
|
|
return _FrontSVertex->point2D().y();
|
|
}
|
|
|
|
virtual real getProjectedZ() const
|
|
{
|
|
return _FrontSVertex->point2D().z();
|
|
}
|
|
|
|
/*! Returns the 2D point. */
|
|
virtual Vec2r getPoint2D() const
|
|
{
|
|
return _FrontSVertex->getPoint2D();
|
|
}
|
|
|
|
/*! Returns the Id of the TVertex. */
|
|
virtual Id getId() const
|
|
{
|
|
return _Id;
|
|
}
|
|
|
|
/*! Cast the Interface0D in SVertex if it can be. */
|
|
// it can't
|
|
virtual ViewVertex *castToViewVertex()
|
|
{
|
|
return this;
|
|
}
|
|
|
|
/*! Cast the Interface0D in TVertex if it can be. */
|
|
virtual TVertex *castToTVertex()
|
|
{
|
|
return this;
|
|
}
|
|
|
|
private:
|
|
SVertex *_FrontSVertex;
|
|
SVertex *_BackSVertex;
|
|
directedViewEdge _FrontEdgeA;
|
|
directedViewEdge _FrontEdgeB;
|
|
directedViewEdge _BackEdgeA;
|
|
directedViewEdge _BackEdgeB;
|
|
Id _Id; // id to identify t vertices . these id will be negative in order not to be mixed with NonTVertex ids.
|
|
edge_pointers_container _sortedEdges; // the list of the four ViewEdges, ordered in CCW order (in the image plan)
|
|
|
|
public:
|
|
/*! Default constructor.*/
|
|
inline TVertex() : ViewVertex(Nature::T_VERTEX)
|
|
{
|
|
_FrontSVertex = NULL;
|
|
_BackSVertex = NULL;
|
|
_FrontEdgeA.first = 0;
|
|
_FrontEdgeB.first = 0;
|
|
_BackEdgeA.first = 0;
|
|
_BackEdgeB.first = 0;
|
|
}
|
|
|
|
inline TVertex(SVertex *svFront, SVertex *svBack) : ViewVertex(Nature::T_VERTEX)
|
|
{
|
|
_FrontSVertex = svFront;
|
|
_BackSVertex = svBack;
|
|
_FrontEdgeA.first = 0;
|
|
_FrontEdgeB.first = 0;
|
|
_BackEdgeA.first = 0;
|
|
_BackEdgeB.first = 0;
|
|
svFront->setViewVertex(this);
|
|
svBack->setViewVertex(this);
|
|
}
|
|
|
|
protected:
|
|
/*! Copy constructor. */
|
|
inline TVertex(TVertex& iBrother) : ViewVertex(iBrother)
|
|
{
|
|
_FrontSVertex = iBrother._FrontSVertex;
|
|
_BackSVertex = iBrother._BackSVertex;
|
|
_FrontEdgeA = iBrother._FrontEdgeA;
|
|
_FrontEdgeB = iBrother._FrontEdgeB;
|
|
_BackEdgeA = iBrother._BackEdgeA;
|
|
_BackEdgeB = iBrother._BackEdgeB;
|
|
_sortedEdges = iBrother._sortedEdges;
|
|
}
|
|
|
|
/*! Cloning method. */
|
|
virtual ViewVertex *duplicate()
|
|
{
|
|
TVertex *clone = new TVertex(*this);
|
|
return clone;
|
|
}
|
|
|
|
public:
|
|
/* accessors */
|
|
/*! Returns the SVertex that is closer to the viewpoint. */
|
|
inline SVertex *frontSVertex()
|
|
{
|
|
return _FrontSVertex;
|
|
}
|
|
|
|
/*! Returns the SVertex that is further away from the viewpoint. */
|
|
inline SVertex *backSVertex()
|
|
{
|
|
return _BackSVertex;
|
|
}
|
|
|
|
inline directedViewEdge& frontEdgeA()
|
|
{
|
|
return _FrontEdgeA;
|
|
}
|
|
|
|
inline directedViewEdge& frontEdgeB()
|
|
{
|
|
return _FrontEdgeB;
|
|
}
|
|
|
|
inline directedViewEdge& backEdgeA()
|
|
{
|
|
return _BackEdgeA;
|
|
}
|
|
|
|
inline directedViewEdge& backEdgeB()
|
|
{
|
|
return _BackEdgeB;
|
|
}
|
|
|
|
/* modifiers */
|
|
/*! Sets the SVertex that is closer to the viewpoint. */
|
|
inline void setFrontSVertex(SVertex *iFrontSVertex)
|
|
{
|
|
_FrontSVertex = iFrontSVertex;
|
|
_FrontSVertex->setViewVertex(this);
|
|
}
|
|
|
|
/*! Sets the SVertex that is further away from the viewpoint. */
|
|
inline void setBackSVertex(SVertex *iBackSVertex)
|
|
{
|
|
_BackSVertex = iBackSVertex;
|
|
_BackSVertex->setViewVertex(this);
|
|
}
|
|
|
|
void setFrontEdgeA(ViewEdge *iFrontEdgeA, bool incoming = true);
|
|
void setFrontEdgeB(ViewEdge *iFrontEdgeB, bool incoming = true);
|
|
void setBackEdgeA(ViewEdge *iBackEdgeA, bool incoming = true);
|
|
void setBackEdgeB(ViewEdge *iBackEdgeB, bool incoming = true);
|
|
|
|
/*! Sets the Id. */
|
|
inline void setId(const Id& iId)
|
|
{
|
|
_Id = iId;
|
|
}
|
|
|
|
/*! Returns the SVertex (among the 2) belonging to the FEdge iFEdge */
|
|
inline SVertex *getSVertex(FEdge *iFEdge)
|
|
{
|
|
const vector<FEdge*>& vfEdges = _FrontSVertex->fedges();
|
|
vector<FEdge*>::const_iterator fe, fend;
|
|
for (fe = vfEdges.begin(), fend = vfEdges.end(); fe != fend; fe++) {
|
|
if ((*fe) == iFEdge)
|
|
return _FrontSVertex;
|
|
}
|
|
|
|
const vector<FEdge*>& vbEdges = _BackSVertex->fedges();
|
|
for (fe = vbEdges.begin(), fend = vbEdges.end(); fe != fend; fe++) {
|
|
if ((*fe) == iFEdge)
|
|
return _BackSVertex;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
virtual void Replace(ViewEdge *iOld, ViewEdge *iNew);
|
|
|
|
/*! returns the mate edge of iEdgeA.
|
|
* For example, if iEdgeA is frontEdgeA, then frontEdgeB is returned. If iEdgeA is frontEdgeB then frontEdgeA
|
|
* is returned. Same for back edges
|
|
*/
|
|
virtual ViewEdge *mate(ViewEdge *iEdgeA)
|
|
{
|
|
if (iEdgeA == _FrontEdgeA.first)
|
|
return _FrontEdgeB.first;
|
|
if (iEdgeA == _FrontEdgeB.first)
|
|
return _FrontEdgeA.first;
|
|
if (iEdgeA == _BackEdgeA.first)
|
|
return _BackEdgeB.first;
|
|
if (iEdgeA == _BackEdgeB.first)
|
|
return _BackEdgeA.first;
|
|
return NULL;
|
|
}
|
|
|
|
/* iterators access */
|
|
virtual edge_iterator edges_begin();
|
|
virtual const_edge_iterator edges_begin() const;
|
|
virtual edge_iterator edges_end();
|
|
virtual const_edge_iterator edges_end() const;
|
|
virtual edge_iterator edges_iterator(ViewEdge *iEdge);
|
|
virtual const_edge_iterator edges_iterator(ViewEdge *iEdge) const;
|
|
|
|
/*! Returns an iterator over the ViewEdges that goes to or comes from this ViewVertex pointing to the first
|
|
* ViewEdge of the list. The orientedViewEdgeIterator allows to iterate in CCW order over these ViewEdges
|
|
* and to get the orientation for each ViewEdge (incoming/outgoing).
|
|
*/
|
|
virtual ViewVertexInternal::orientedViewEdgeIterator edgesBegin();
|
|
|
|
/*! Returns an orientedViewEdgeIterator over the ViewEdges around this ViewVertex, pointing after the last ViewEdge.
|
|
*/
|
|
virtual ViewVertexInternal::orientedViewEdgeIterator edgesEnd();
|
|
|
|
/*! Returns an orientedViewEdgeIterator pointing to the ViewEdge given as argument. */
|
|
virtual ViewVertexInternal::orientedViewEdgeIterator edgesIterator(ViewEdge *iEdge);
|
|
|
|
#ifdef WITH_CXX_GUARDEDALLOC
|
|
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:TVertex")
|
|
#endif
|
|
};
|
|
|
|
|
|
/**********************************/
|
|
/* */
|
|
/* */
|
|
/* NonTVertex */
|
|
/* */
|
|
/* */
|
|
/**********************************/
|
|
|
|
|
|
// (non T vertex)
|
|
/*! View vertex for corners, cusps, etc...
|
|
* Associated to a single SVertex.
|
|
* Can be associated to 2 or several view edges
|
|
*/
|
|
class NonTVertex : public ViewVertex
|
|
{
|
|
public:
|
|
typedef vector<directedViewEdge> edges_container;
|
|
|
|
public: // Implementation of Interface0D
|
|
/*! Returns the string "ViewVertex". */
|
|
virtual string getExactTypeName() const
|
|
{
|
|
return "NonTVertex";
|
|
}
|
|
|
|
// Data access methods
|
|
/*! Returns the 3D x coordinate of the vertex. */
|
|
virtual real getX() const
|
|
{
|
|
return _SVertex->point3D().x();
|
|
}
|
|
|
|
/*! Returns the 3D y coordinate of the vertex. */
|
|
virtual real getY() const
|
|
{
|
|
return _SVertex->point3D().y();
|
|
}
|
|
|
|
/*! Returns the 3D z coordinate of the vertex. */
|
|
virtual real getZ() const
|
|
{
|
|
return _SVertex->point3D().z();
|
|
}
|
|
|
|
/*! Returns the 3D point. */
|
|
virtual Vec3r getPoint3D() const
|
|
{
|
|
return _SVertex->getPoint3D();
|
|
}
|
|
|
|
/*! Returns the projected 3D x coordinate of the vertex. */
|
|
virtual real getProjectedX() const
|
|
{
|
|
return _SVertex->point2D().x();
|
|
}
|
|
|
|
/*! Returns the projected 3D y coordinate of the vertex. */
|
|
virtual real getProjectedY() const
|
|
{
|
|
return _SVertex->point2D().y();
|
|
}
|
|
|
|
/*! Returns the projected 3D z coordinate of the vertex. */
|
|
virtual real getProjectedZ() const
|
|
{
|
|
return _SVertex->point2D().z();
|
|
}
|
|
|
|
/*! Returns the 2D point. */
|
|
virtual Vec2r getPoint2D() const
|
|
{
|
|
return _SVertex->getPoint2D();
|
|
}
|
|
|
|
/*! Returns the Id of the vertex. */
|
|
virtual Id getId() const
|
|
{
|
|
return _SVertex->getId();
|
|
}
|
|
|
|
/*! Cast the Interface0D in SVertex if it can be. */
|
|
virtual SVertex *castToSVertex()
|
|
{
|
|
return _SVertex;
|
|
}
|
|
|
|
/*! Cast the Interface0D in ViewVertex if it can be. */
|
|
virtual ViewVertex *castToViewVertex()
|
|
{
|
|
return this;
|
|
}
|
|
|
|
/*! Cast the Interface0D in NonTVertex if it can be. */
|
|
virtual NonTVertex *castToNonTVertex()
|
|
{
|
|
return this;
|
|
}
|
|
|
|
private:
|
|
SVertex *_SVertex;
|
|
edges_container _ViewEdges;
|
|
|
|
public:
|
|
/*! Default constructor.*/
|
|
inline NonTVertex() : ViewVertex(Nature::NON_T_VERTEX)
|
|
{
|
|
_SVertex = NULL;
|
|
}
|
|
|
|
/*! Builds a NonTVertex from a SVertex. */
|
|
inline NonTVertex(SVertex *iSVertex) : ViewVertex(Nature::NON_T_VERTEX)
|
|
{
|
|
_SVertex = iSVertex;
|
|
_SVertex->setViewVertex(this);
|
|
}
|
|
|
|
protected:
|
|
/*! Copy constructor. */
|
|
inline NonTVertex(NonTVertex& iBrother) : ViewVertex(iBrother)
|
|
{
|
|
_SVertex = iBrother._SVertex;
|
|
_SVertex->setViewVertex(this);
|
|
_ViewEdges = iBrother._ViewEdges;
|
|
}
|
|
|
|
/*! Cloning method. */
|
|
virtual ViewVertex *duplicate()
|
|
{
|
|
NonTVertex *clone = new NonTVertex(*this);
|
|
return clone;
|
|
}
|
|
|
|
public:
|
|
/*! destructor. */
|
|
virtual ~NonTVertex() {}
|
|
|
|
/* accessors */
|
|
/*! Returns the SVertex on top of which this NonTVertex is built. */
|
|
inline SVertex *svertex()
|
|
{
|
|
return _SVertex;
|
|
}
|
|
|
|
inline edges_container& viewedges()
|
|
{
|
|
return _ViewEdges;
|
|
}
|
|
|
|
/* modifiers */
|
|
/*! Sets the SVertex on top of which this NonTVertex is built. */
|
|
inline void setSVertex(SVertex *iSVertex)
|
|
{
|
|
_SVertex = iSVertex;
|
|
_SVertex->setViewVertex(this);
|
|
}
|
|
|
|
inline void setViewEdges(const vector<directedViewEdge>& iViewEdges)
|
|
{
|
|
_ViewEdges = iViewEdges;
|
|
}
|
|
|
|
void AddIncomingViewEdge(ViewEdge *iVEdge);
|
|
void AddOutgoingViewEdge(ViewEdge *iVEdge);
|
|
|
|
inline void AddViewEdge(ViewEdge *iVEdge, bool incoming = true)
|
|
{
|
|
if (incoming)
|
|
AddIncomingViewEdge(iVEdge);
|
|
else
|
|
AddOutgoingViewEdge(iVEdge);
|
|
}
|
|
|
|
/* Replaces old edge by new edge */
|
|
virtual void Replace(ViewEdge *iOld, ViewEdge *iNew)
|
|
{
|
|
edges_container::iterator insertedve;
|
|
for (edges_container::iterator ve = _ViewEdges.begin(), vend = _ViewEdges.end(); ve != vend; ve++) {
|
|
if ((ve)->first == iOld) {
|
|
insertedve = _ViewEdges.insert(ve, directedViewEdge(iNew, ve->second));// inserts e2 before ve.
|
|
// returns an iterator pointing toward e2. ve is invalidated.
|
|
// we want to remove e1, but we can't use ve anymore:
|
|
insertedve++; // insertedve points now to e1
|
|
_ViewEdges.erase(insertedve);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* iterators access */
|
|
virtual edge_iterator edges_begin();
|
|
virtual const_edge_iterator edges_begin() const;
|
|
virtual edge_iterator edges_end();
|
|
virtual const_edge_iterator edges_end() const;
|
|
virtual edge_iterator edges_iterator(ViewEdge *iEdge);
|
|
virtual const_edge_iterator edges_iterator(ViewEdge *iEdge) const;
|
|
|
|
/*! Returns an iterator over the ViewEdges that goes to or comes from this ViewVertex pointing to the first
|
|
* ViewEdge of the list. The orientedViewEdgeIterator allows to iterate in CCW order over these ViewEdges
|
|
* and to get the orientation for each ViewEdge (incoming/outgoing).
|
|
*/
|
|
virtual ViewVertexInternal::orientedViewEdgeIterator edgesBegin();
|
|
|
|
/*! Returns an orientedViewEdgeIterator over the ViewEdges around this ViewVertex, pointing after the last ViewEdge.
|
|
*/
|
|
virtual ViewVertexInternal::orientedViewEdgeIterator edgesEnd();
|
|
|
|
/*! Returns an orientedViewEdgeIterator pointing to the ViewEdge given as argument. */
|
|
virtual ViewVertexInternal::orientedViewEdgeIterator edgesIterator(ViewEdge *iEdge);
|
|
|
|
#ifdef WITH_CXX_GUARDEDALLOC
|
|
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:NonTVertex")
|
|
#endif
|
|
};
|
|
|
|
/**********************************/
|
|
/* */
|
|
/* */
|
|
/* ViewEdge */
|
|
/* */
|
|
/* */
|
|
/**********************************/
|
|
|
|
/* Geometry(normals...)
|
|
* Nature of edges
|
|
* 2D spaces (1or2, material, z...)
|
|
* Parent Shape
|
|
* 3D Shading, material
|
|
* Importance
|
|
* Occluders
|
|
*/
|
|
class ViewShape;
|
|
|
|
namespace ViewEdgeInternal {
|
|
|
|
template<class Traits> class edge_iterator_base;
|
|
template<class Traits> class fedge_iterator_base;
|
|
template<class Traits> class vertex_iterator_base;
|
|
|
|
} // end of namespace ViewEdgeInternal
|
|
|
|
/*! Class defining a ViewEdge. A ViewEdge in an edge of the image graph. it connects two ViewVertex.
|
|
* It is made by connecting a set of FEdges.
|
|
*/
|
|
class ViewEdge : public Interface1D
|
|
{
|
|
public: // Implementation of Interface0D
|
|
/*! Returns the string "ViewEdge". */
|
|
virtual string getExactTypeName() const
|
|
{
|
|
return "ViewEdge";
|
|
}
|
|
|
|
// Data access methods
|
|
/*! Returns the Id of the vertex. */
|
|
virtual Id getId() const
|
|
{
|
|
return _Id;
|
|
}
|
|
|
|
/*! Returns the nature of the ViewEdge. */
|
|
virtual Nature::EdgeNature getNature() const
|
|
{
|
|
return _Nature;
|
|
}
|
|
|
|
public:
|
|
typedef SVertex vertex_type;
|
|
friend class ViewShape;
|
|
// for ViewEdge iterator
|
|
typedef ViewEdgeInternal::edge_iterator_base<Nonconst_traits<ViewEdge*> > edge_iterator;
|
|
typedef ViewEdgeInternal::edge_iterator_base<Const_traits<ViewEdge*> > const_edge_iterator;
|
|
// for fedge iterator
|
|
typedef ViewEdgeInternal::fedge_iterator_base<Nonconst_traits<FEdge*> > fedge_iterator;
|
|
typedef ViewEdgeInternal::fedge_iterator_base<Const_traits<FEdge*> > const_fedge_iterator;
|
|
// for svertex iterator
|
|
typedef ViewEdgeInternal::vertex_iterator_base<Nonconst_traits<SVertex*> > vertex_iterator;
|
|
typedef ViewEdgeInternal::vertex_iterator_base<Const_traits<SVertex*> > const_vertex_iterator;
|
|
|
|
private:
|
|
ViewVertex *__A; // edge starting vertex
|
|
ViewVertex *__B; // edge ending vertex
|
|
Nature::EdgeNature _Nature; // nature of view edge
|
|
ViewShape *_Shape; // shape to which the view edge belongs
|
|
FEdge *_FEdgeA; // first edge of the embedded fedges chain
|
|
FEdge *_FEdgeB; // last edge of the embedded fedges chain
|
|
Id _Id;
|
|
unsigned _ChainingTimeStamp;
|
|
// The silhouette view edge separates 2 2D spaces. The one on the left is necessarly the Shape _Shape (the one to
|
|
// which this edge belongs to) and _aShape is the one on its right
|
|
// NOT HANDLED BY THE COPY CONSTRUCTOR
|
|
ViewShape *_aShape;
|
|
int _qi;
|
|
vector<ViewShape*> _Occluders;
|
|
bool _isInImage;
|
|
|
|
// tmp
|
|
Id *_splittingId;
|
|
|
|
public:
|
|
/*! A field that can be used by the user to store any data.
|
|
* This field must be reseted afterwards using ResetUserData().
|
|
*/
|
|
void *userdata;
|
|
|
|
/*! Default constructor. */
|
|
inline ViewEdge()
|
|
{
|
|
__A = NULL;
|
|
__B = NULL;
|
|
_FEdgeA = NULL;
|
|
_FEdgeB = NULL;
|
|
_ChainingTimeStamp = 0;
|
|
_qi = 0;
|
|
_aShape = NULL;
|
|
userdata = NULL;
|
|
_splittingId = NULL;
|
|
_isInImage = true;
|
|
}
|
|
|
|
inline ViewEdge(ViewVertex *iA, ViewVertex *iB)
|
|
{
|
|
__A = iA;
|
|
__B = iB;
|
|
_FEdgeA = NULL;
|
|
_FEdgeB = NULL;
|
|
_Shape = 0;
|
|
_ChainingTimeStamp = 0;
|
|
_qi = 0;
|
|
_aShape = NULL;
|
|
userdata = NULL;
|
|
_splittingId = NULL;
|
|
_isInImage = true;
|
|
}
|
|
|
|
inline ViewEdge(ViewVertex *iA, ViewVertex *iB, FEdge *iFEdgeA)
|
|
{
|
|
__A = iA;
|
|
__B = iB;
|
|
_FEdgeA = iFEdgeA;
|
|
_FEdgeB = NULL;
|
|
_Shape = NULL;
|
|
_ChainingTimeStamp = 0;
|
|
_qi = 0;
|
|
_aShape = NULL;
|
|
userdata = NULL;
|
|
_splittingId = NULL;
|
|
_isInImage = true;
|
|
}
|
|
|
|
inline ViewEdge(ViewVertex *iA, ViewVertex *iB, FEdge *iFEdgeA, FEdge *iFEdgeB, ViewShape *iShape)
|
|
{
|
|
__A = iA;
|
|
__B = iB;
|
|
_FEdgeA = iFEdgeA;
|
|
_FEdgeB = iFEdgeB;
|
|
_Shape = iShape;
|
|
_ChainingTimeStamp = 0;
|
|
_qi = 0;
|
|
_aShape = NULL;
|
|
userdata = NULL;
|
|
_splittingId = NULL;
|
|
_isInImage = true;
|
|
UpdateFEdges(); // tells every FEdge between iFEdgeA and iFEdgeB that this is theit ViewEdge
|
|
}
|
|
|
|
//soc protected:
|
|
/*! Copy constructor. */
|
|
inline ViewEdge(ViewEdge& iBrother)
|
|
{
|
|
__A = iBrother.__A;
|
|
__B = iBrother.__B;
|
|
_FEdgeA = iBrother._FEdgeA;
|
|
_FEdgeB = iBrother._FEdgeB;
|
|
_Nature = iBrother._Nature;
|
|
_Shape = NULL;
|
|
_Id = iBrother._Id;
|
|
_ChainingTimeStamp = iBrother._ChainingTimeStamp;
|
|
_aShape = iBrother._aShape;
|
|
_qi = iBrother._qi;
|
|
_splittingId = NULL;
|
|
_isInImage = iBrother._isInImage;
|
|
iBrother.userdata = this;
|
|
userdata = NULL;
|
|
}
|
|
|
|
/*! Cloning method. */
|
|
virtual ViewEdge *duplicate()
|
|
{
|
|
ViewEdge *clone = new ViewEdge(*this);
|
|
return clone;
|
|
}
|
|
|
|
public:
|
|
/*! Destructor. */
|
|
virtual ~ViewEdge()
|
|
{
|
|
#if 0
|
|
if (_aFace) {
|
|
delete _aFace;
|
|
_aFace = NULL;
|
|
}
|
|
#endif
|
|
// only the last splitted deletes this id
|
|
if (_splittingId) {
|
|
if (*_splittingId == _Id)
|
|
delete _splittingId;
|
|
}
|
|
}
|
|
|
|
/* accessors */
|
|
/*! Returns the first ViewVertex. */
|
|
inline ViewVertex *A()
|
|
{
|
|
return __A;
|
|
}
|
|
|
|
/*! Returns the second ViewVertex. */
|
|
inline ViewVertex *B()
|
|
{
|
|
return __B;
|
|
}
|
|
|
|
/*! Returns the first FEdge that constitues this ViewEdge. */
|
|
inline FEdge *fedgeA()
|
|
{
|
|
return _FEdgeA;
|
|
}
|
|
|
|
/*! Returns the last FEdge that constitues this ViewEdge. */
|
|
inline FEdge *fedgeB()
|
|
{
|
|
return _FEdgeB;
|
|
}
|
|
|
|
/*! Returns the ViewShape to which this ViewEdge belongs to .*/
|
|
inline ViewShape *viewShape()
|
|
{
|
|
return _Shape;
|
|
}
|
|
|
|
/*! Returns the shape that is occluded by the ViewShape to which this ViewEdge belongs to. If no object is occluded,
|
|
* NULL is returned.
|
|
* \return The occluded ViewShape.
|
|
*/
|
|
inline ViewShape *aShape()
|
|
{
|
|
return _aShape;
|
|
}
|
|
|
|
/*! Tells whether this ViewEdge forms a closed loop or not. */
|
|
inline bool isClosed()
|
|
{
|
|
if (!__B)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
/*! Returns the time stamp of this ViewEdge. */
|
|
inline unsigned getChainingTimeStamp()
|
|
{
|
|
return _ChainingTimeStamp;
|
|
}
|
|
|
|
inline const ViewShape *aShape() const
|
|
{
|
|
return _aShape;
|
|
}
|
|
|
|
inline const ViewShape *bShape() const
|
|
{
|
|
return _Shape;
|
|
}
|
|
|
|
inline vector<ViewShape*>& occluders()
|
|
{
|
|
return _Occluders;
|
|
}
|
|
|
|
inline Id *splittingId()
|
|
{
|
|
return _splittingId;
|
|
}
|
|
|
|
inline bool isInImage() const
|
|
{
|
|
return _isInImage;
|
|
}
|
|
|
|
/* modifiers */
|
|
/*! Sets the first ViewVertex of the ViewEdge. */
|
|
inline void setA(ViewVertex *iA)
|
|
{
|
|
__A = iA;
|
|
}
|
|
|
|
/*! Sets the last ViewVertex of the ViewEdge. */
|
|
inline void setB(ViewVertex *iB)
|
|
{
|
|
__B = iB;
|
|
}
|
|
|
|
/*! Sets the nature of the ViewEdge. */
|
|
inline void setNature(Nature::EdgeNature iNature)
|
|
{
|
|
_Nature = iNature;
|
|
}
|
|
|
|
/*! Sets the first FEdge of the ViewEdge. */
|
|
inline void setFEdgeA(FEdge *iFEdge)
|
|
{
|
|
_FEdgeA = iFEdge;
|
|
}
|
|
|
|
/*! Sets the last FEdge of the ViewEdge. */
|
|
inline void setFEdgeB(FEdge *iFEdge)
|
|
{
|
|
_FEdgeB = iFEdge;
|
|
}
|
|
|
|
/*! Sets the ViewShape to which this ViewEdge belongs to.*/
|
|
inline void setShape(ViewShape *iVShape)
|
|
{
|
|
_Shape = iVShape;
|
|
}
|
|
|
|
/*! Sets the ViewEdge id. */
|
|
inline void setId(const Id& id)
|
|
{
|
|
_Id = id;
|
|
}
|
|
|
|
/*! Sets Viewedge to this for all embedded fedges */
|
|
void UpdateFEdges();
|
|
|
|
/*! Sets the occluded ViewShape */
|
|
inline void setaShape(ViewShape *iShape)
|
|
{
|
|
_aShape = iShape;
|
|
}
|
|
|
|
/*! Sets the quantitative invisibility value. */
|
|
inline void setQI(int qi)
|
|
{
|
|
_qi = qi;
|
|
}
|
|
|
|
/*! Sets the time stamp value. */
|
|
inline void setChainingTimeStamp(unsigned ts)
|
|
{
|
|
_ChainingTimeStamp = ts;
|
|
}
|
|
|
|
inline void AddOccluder(ViewShape *iShape)
|
|
{
|
|
_Occluders.push_back(iShape);
|
|
}
|
|
|
|
inline void setSplittingId(Id *id)
|
|
{
|
|
_splittingId = id;
|
|
}
|
|
|
|
inline void setIsInImage(bool iFlag)
|
|
{
|
|
_isInImage = iFlag;
|
|
}
|
|
|
|
/* stroke interface definition */
|
|
inline bool intersect_2d_area(const Vec2r& iMin, const Vec2r& iMax) const
|
|
{
|
|
// parse edges to check if one of them is intersection the region:
|
|
FEdge *current = _FEdgeA;
|
|
do {
|
|
if (GeomUtils::intersect2dSeg2dArea(iMin, iMax,
|
|
Vec2r(current->vertexA()->point2D()[0],
|
|
current->vertexA()->point2D()[1]),
|
|
Vec2r(current->vertexB()->point2D()[0],
|
|
current->vertexB()->point2D()[1])))
|
|
{
|
|
return true;
|
|
}
|
|
current = current->nextEdge();
|
|
} while ((current != 0) && (current != _FEdgeA));
|
|
|
|
return false;
|
|
}
|
|
|
|
inline bool include_in_2d_area(const Vec2r& iMin, const Vec2r& iMax) const
|
|
{
|
|
// parse edges to check if all of them are intersection the region:
|
|
FEdge *current = _FEdgeA;
|
|
|
|
do {
|
|
if (!GeomUtils::include2dSeg2dArea(iMin, iMax,
|
|
Vec2r(current->vertexA()->point2D()[0],
|
|
current->vertexA()->point2D()[1]),
|
|
Vec2r(current->vertexB()->point2D()[0],
|
|
current->vertexB()->point2D()[1])))
|
|
{
|
|
return false;
|
|
}
|
|
current = current->nextEdge();
|
|
} while ((current != 0) && (current != _FEdgeA));
|
|
|
|
return true;
|
|
}
|
|
|
|
/* Information access interface */
|
|
|
|
#if 0
|
|
inline Nature::EdgeNature viewedge_nature() const
|
|
{
|
|
return getNature();
|
|
}
|
|
|
|
float viewedge_length() const;
|
|
#endif
|
|
|
|
/*! Returns the 2D length of the Viewedge. */
|
|
real getLength2D() const;
|
|
|
|
#if 0
|
|
inline Material material() const
|
|
{
|
|
return _FEdgeA->vertexA()->shape()->material();
|
|
}
|
|
#endif
|
|
|
|
inline int qi() const
|
|
{
|
|
return _qi;
|
|
}
|
|
|
|
inline occluder_container::const_iterator occluders_begin() const
|
|
{
|
|
return _Occluders.begin();
|
|
}
|
|
|
|
inline occluder_container::const_iterator occluders_end() const
|
|
{
|
|
return _Occluders.end();
|
|
}
|
|
|
|
inline int occluders_size() const
|
|
{
|
|
return _Occluders.size();
|
|
}
|
|
|
|
inline bool occluders_empty() const
|
|
{
|
|
return _Occluders.empty();
|
|
}
|
|
|
|
inline const Polygon3r& occludee() const
|
|
{
|
|
return (_FEdgeA->aFace());
|
|
}
|
|
|
|
inline const SShape *occluded_shape() const;
|
|
|
|
inline const bool occludee_empty() const
|
|
{
|
|
if (_aShape == 0)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
//inline real z_discontinuity(int iCombination = 0) const;
|
|
|
|
inline Id shape_id() const
|
|
{
|
|
return _FEdgeA->vertexA()->shape()->getId();
|
|
}
|
|
|
|
inline const SShape *shape() const
|
|
{
|
|
return _FEdgeA->vertexA()->shape();
|
|
}
|
|
|
|
inline float shape_importance() const
|
|
{
|
|
return _FEdgeA->shape_importance();
|
|
}
|
|
|
|
/* iterators access */
|
|
// view edge iterator
|
|
edge_iterator ViewEdge_iterator();
|
|
const_edge_iterator ViewEdge_iterator() const;
|
|
// feature edge iterator
|
|
fedge_iterator fedge_iterator_begin();
|
|
const_fedge_iterator fedge_iterator_begin() const;
|
|
fedge_iterator fedge_iterator_last();
|
|
const_fedge_iterator fedge_iterator_last() const;
|
|
fedge_iterator fedge_iterator_end();
|
|
const_fedge_iterator fedge_iterator_end() const;
|
|
// embedding vertex iterator
|
|
const_vertex_iterator vertices_begin() const;
|
|
vertex_iterator vertices_begin();
|
|
const_vertex_iterator vertices_last() const;
|
|
vertex_iterator vertices_last();
|
|
const_vertex_iterator vertices_end() const;
|
|
vertex_iterator vertices_end();
|
|
|
|
// Iterator access (Interface1D)
|
|
/*! Returns an Interface0DIterator to iterate over the SVertex constituting the embedding of this ViewEdge.
|
|
* The returned Interface0DIterator points to the first SVertex of the ViewEdge.
|
|
*/
|
|
virtual Interface0DIterator verticesBegin();
|
|
|
|
/*! Returns an Interface0DIterator to iterate over the SVertex constituting the embedding of this ViewEdge.
|
|
* The returned Interface0DIterator points after the last SVertex of the ViewEdge.
|
|
*/
|
|
virtual Interface0DIterator verticesEnd();
|
|
|
|
/*! Returns an Interface0DIterator to iterate over the points of this ViewEdge at a given resolution.
|
|
* The returned Interface0DIterator points on the first Point of the ViewEdge.
|
|
* \param t
|
|
* the sampling value.
|
|
*/
|
|
virtual Interface0DIterator pointsBegin(float t = 0.0f);
|
|
|
|
/*! Returns an Interface0DIterator to iterate over the points of this ViewEdge at a given resolution.
|
|
* The returned Interface0DIterator points after the last Point of the ViewEdge.
|
|
* \param t
|
|
* the sampling value.
|
|
*/
|
|
virtual Interface0DIterator pointsEnd(float t = 0.0f);
|
|
|
|
#ifdef WITH_CXX_GUARDEDALLOC
|
|
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:ViewEdge")
|
|
#endif
|
|
};
|
|
|
|
|
|
/**********************************/
|
|
/* */
|
|
/* */
|
|
/* ViewShape */
|
|
/* */
|
|
/* */
|
|
/**********************************/
|
|
|
|
/*! Class gathering the elements of the ViewMap (ViewVertex, ViewEdge) that are issued from the same input shape. */
|
|
class ViewShape
|
|
{
|
|
private:
|
|
vector<ViewVertex*> _Vertices;
|
|
vector<ViewEdge*> _Edges;
|
|
SShape *_SShape;
|
|
|
|
public:
|
|
/*! A field that can be used by the user to store any data.
|
|
* This field must be reseted afterwards using ResetUserData().
|
|
*/
|
|
void *userdata;
|
|
|
|
/*! Default constructor.*/
|
|
inline ViewShape()
|
|
{
|
|
userdata = NULL;
|
|
_SShape = NULL;
|
|
}
|
|
|
|
/*! Builds a ViewShape from a SShape. */
|
|
inline ViewShape(SShape *iSShape)
|
|
{
|
|
userdata = NULL;
|
|
_SShape = iSShape;
|
|
//_SShape->setViewShape(this);
|
|
}
|
|
|
|
/*! Copy constructor. */
|
|
inline ViewShape(ViewShape& iBrother)
|
|
{
|
|
userdata = NULL;
|
|
vector<ViewVertex *>::iterator vv, vvend;
|
|
vector<ViewEdge *>::iterator ve, veend;
|
|
|
|
_SShape = iBrother._SShape;
|
|
|
|
vector<ViewVertex*>& vvertices = iBrother.vertices();
|
|
// duplicate vertices
|
|
for (vv = vvertices.begin(), vvend = vvertices.end(); vv != vvend; vv++) {
|
|
ViewVertex *newVertex = (*vv)->duplicate();
|
|
AddVertex(newVertex);
|
|
}
|
|
|
|
vector<ViewEdge*>& vvedges = iBrother.edges();
|
|
// duplicate edges
|
|
for (ve = vvedges.begin(), veend = vvedges.end(); ve != veend; ve++) {
|
|
ViewEdge *newEdge = (*ve)->duplicate();
|
|
AddEdge(newEdge); // here the shape is set as the edge's shape
|
|
}
|
|
|
|
//-------------------------
|
|
// remap edges in vertices:
|
|
//-------------------------
|
|
for (vv = _Vertices.begin(), vvend = _Vertices.end(); vv != vvend; vv++) {
|
|
switch ((*vv)->getNature()) {
|
|
case Nature::T_VERTEX:
|
|
{
|
|
TVertex *v = (TVertex *)(*vv);
|
|
ViewEdge *veFrontA = (ViewEdge *)(v)->frontEdgeA().first->userdata;
|
|
ViewEdge *veFrontB = (ViewEdge *)(v)->frontEdgeB().first->userdata;
|
|
ViewEdge *veBackA = (ViewEdge *)(v)->backEdgeA().first->userdata;
|
|
ViewEdge *veBackB = (ViewEdge *)(v)->backEdgeB().first->userdata;
|
|
|
|
v->setFrontEdgeA(veFrontA, v->frontEdgeA().second);
|
|
v->setFrontEdgeB(veFrontB, v->frontEdgeB().second);
|
|
v->setBackEdgeA(veBackA, v->backEdgeA().second);
|
|
v->setBackEdgeB(veBackB, v->backEdgeB().second);
|
|
}
|
|
break;
|
|
case Nature::NON_T_VERTEX:
|
|
{
|
|
NonTVertex *v = (NonTVertex *)(*vv);
|
|
vector<ViewVertex::directedViewEdge>& vedges = (v)->viewedges();
|
|
vector<ViewVertex::directedViewEdge> newEdges;
|
|
for (vector<ViewVertex::directedViewEdge>::iterator ve = vedges.begin(), veend = vedges.end();
|
|
ve != veend;
|
|
ve++)
|
|
{
|
|
ViewEdge *current = (ViewEdge *)((ve)->first)->userdata;
|
|
newEdges.push_back(ViewVertex::directedViewEdge(current, ve->second));
|
|
}
|
|
(v)->setViewEdges(newEdges);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
//-------------------------------------
|
|
// remap vertices in edges:
|
|
//-------------------------------------
|
|
for (ve = _Edges.begin(), veend = _Edges.end(); ve != veend; ve++) {
|
|
(*ve)->setA((ViewVertex *)((*ve)->A()->userdata));
|
|
(*ve)->setB((ViewVertex *)((*ve)->B()->userdata));
|
|
//---------------------------------------
|
|
// Update all embedded FEdges
|
|
//---------------------------------------
|
|
(*ve)->UpdateFEdges();
|
|
}
|
|
|
|
// reset all brothers userdata to NULL:
|
|
//-------------------------------------
|
|
//---------
|
|
// vertices
|
|
//---------
|
|
for (vv = vvertices.begin(), vvend = vvertices.end(); vv != vvend; vv++) {
|
|
(*vv)->userdata = NULL;
|
|
}
|
|
|
|
//------
|
|
// edges
|
|
//------
|
|
for (ve = vvedges.begin(), veend = vvedges.end(); ve != veend; ve++) {
|
|
(*ve)->userdata = NULL;
|
|
}
|
|
}
|
|
|
|
/*! Cloning method. */
|
|
virtual ViewShape *duplicate()
|
|
{
|
|
ViewShape *clone = new ViewShape(*this);
|
|
return clone;
|
|
}
|
|
|
|
/*! Destructor. */
|
|
virtual ~ViewShape();
|
|
|
|
/* splits a view edge into several view edges.
|
|
* fe
|
|
* The FEdge that gets splitted
|
|
* iViewVertices
|
|
* The view vertices corresponding to the different intersections for the edge fe.
|
|
* This list need to be sorted such as the first view vertex is the farther away from fe->vertexA.
|
|
* ioNewEdges
|
|
* The feature edges that are newly created (the initial edges are not included) are added to this list.
|
|
* ioNewViewEdges
|
|
* The view edges that are newly created (the initial edges are not included) are added to this list.
|
|
*/
|
|
inline void SplitEdge(FEdge *fe, const vector<TVertex*>& iViewVertices, vector<FEdge*>& ioNewEdges,
|
|
vector<ViewEdge*>& ioNewViewEdges);
|
|
|
|
/* accessors */
|
|
/*! Returns the SShape on top of which this ViewShape is built. */
|
|
inline SShape *sshape()
|
|
{
|
|
return _SShape;
|
|
}
|
|
|
|
/*! Returns the SShape on top of which this ViewShape is built. */
|
|
inline const SShape *sshape() const
|
|
{
|
|
return _SShape;
|
|
}
|
|
|
|
/*! Returns the list of ViewVertex contained in this ViewShape. */
|
|
inline vector<ViewVertex*>& vertices()
|
|
{
|
|
return _Vertices;
|
|
}
|
|
|
|
/*! Returns the list of ViewEdge contained in this ViewShape. */
|
|
inline vector<ViewEdge*>& edges()
|
|
{
|
|
return _Edges;
|
|
}
|
|
|
|
/*! Returns the ViewShape id. */
|
|
inline Id getId() const
|
|
{
|
|
return _SShape->getId();
|
|
}
|
|
|
|
/*! Returns the ViewShape id. */
|
|
inline const string& getName() const
|
|
{
|
|
return _SShape->getName();
|
|
}
|
|
|
|
/* modifiers */
|
|
/*! Sets the SShape on top of which the ViewShape is built. */
|
|
inline void setSShape(SShape *iSShape)
|
|
{
|
|
_SShape = iSShape;
|
|
}
|
|
|
|
/*! Sets the list of ViewVertex contained in this ViewShape. */
|
|
inline void setVertices(const vector<ViewVertex*>& iVertices)
|
|
{
|
|
_Vertices = iVertices;
|
|
}
|
|
|
|
/*! Sets the list of ViewEdge contained in this ViewShape. */
|
|
inline void setEdges(const vector<ViewEdge*>& iEdges)
|
|
{
|
|
_Edges = iEdges;
|
|
}
|
|
|
|
/*! Adds a ViewVertex to the list. */
|
|
inline void AddVertex(ViewVertex *iVertex)
|
|
{
|
|
_Vertices.push_back(iVertex);
|
|
//_SShape->AddNewVertex(iVertex->svertex());
|
|
}
|
|
|
|
/*! Adds a ViewEdge to the list */
|
|
inline void AddEdge(ViewEdge *iEdge)
|
|
{
|
|
_Edges.push_back(iEdge);
|
|
iEdge->setShape(this);
|
|
//_SShape->AddNewEdge(iEdge->fedge());
|
|
}
|
|
|
|
/* removes the view edge iViewEdge in the View Shape and the associated FEdge chain entry in the underlying SShape
|
|
*/
|
|
void RemoveEdge(ViewEdge *iViewEdge);
|
|
|
|
/* removes the view vertex iViewVertex in the View Shape. */
|
|
void RemoveVertex(ViewVertex *iViewVertex);
|
|
|
|
#ifdef WITH_CXX_GUARDEDALLOC
|
|
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:ViewShape")
|
|
#endif
|
|
};
|
|
|
|
|
|
/*
|
|
#############################################
|
|
#############################################
|
|
#############################################
|
|
###### ######
|
|
###### I M P L E M E N T A T I O N ######
|
|
###### ######
|
|
#############################################
|
|
#############################################
|
|
#############################################
|
|
*/
|
|
/* for inline functions */
|
|
|
|
void ViewShape::SplitEdge(FEdge *fe, const vector<TVertex*>& iViewVertices, vector<FEdge*>& ioNewEdges,
|
|
vector<ViewEdge*>& ioNewViewEdges)
|
|
{
|
|
ViewEdge *vEdge = fe->viewedge();
|
|
|
|
// We first need to sort the view vertices from farther to closer to fe->vertexA
|
|
SVertex *sv, *sv2;
|
|
ViewVertex *vva, *vvb;
|
|
vector<TVertex*>::const_iterator vv, vvend;
|
|
for (vv = iViewVertices.begin(), vvend = iViewVertices.end(); vv != vvend; vv++) {
|
|
// Add the viewvertices to the ViewShape
|
|
AddVertex((*vv));
|
|
|
|
// retrieve the correct SVertex from the view vertex
|
|
//--------------------------------------------------
|
|
sv = (*vv)->frontSVertex();
|
|
sv2 = (*vv)->backSVertex();
|
|
|
|
if (sv->shape() != sv2->shape()) {
|
|
if (sv->shape() != _SShape)
|
|
sv = sv2;
|
|
}
|
|
else {
|
|
// if the shape is the same we can safely differ the two vertices using their ids:
|
|
if (sv->getId() != fe->vertexA()->getId())
|
|
sv = sv2;
|
|
}
|
|
|
|
vva = vEdge->A();
|
|
vvb = vEdge->B();
|
|
|
|
// We split Fedge AB into AA' and A'B. A' and A'B are created.
|
|
// AB becomes (address speaking) AA'. B is updated.
|
|
//--------------------------------------------------
|
|
SShape *shape = fe->shape();
|
|
|
|
// a new edge, A'B is created.
|
|
FEdge *newEdge = shape->SplitEdgeIn2(fe, sv);
|
|
/* One of the two FEdges (fe and newEdge) may have a 2D length less than M_EPSILON.
|
|
* (22 Feb 2011, T.K.)
|
|
*/
|
|
|
|
ioNewEdges.push_back(newEdge);
|
|
ViewEdge *newVEdge;
|
|
|
|
if ((vva == 0) || (vvb == 0)) { // that means we're dealing with a closed viewedge (loop)
|
|
// remove the chain that was starting by the fedge A of vEdge (which is different from fe !!!!)
|
|
shape->RemoveEdgeFromChain(vEdge->fedgeA());
|
|
// we set
|
|
vEdge->setA(*vv);
|
|
vEdge->setB(*vv);
|
|
vEdge->setFEdgeA(newEdge);
|
|
//FEdge *previousEdge = newEdge->previousEdge();
|
|
vEdge->setFEdgeB(fe);
|
|
newVEdge = vEdge;
|
|
vEdge->fedgeA()->setViewEdge(newVEdge);
|
|
}
|
|
else {
|
|
// while we create the view edge, it updates the "ViewEdge" pointer of every underlying FEdges to this.
|
|
newVEdge = new ViewEdge((*vv), vvb); //, newEdge, vEdge->fedgeB());
|
|
newVEdge->setNature((fe)->getNature());
|
|
newVEdge->setFEdgeA(newEdge);
|
|
//newVEdge->setFEdgeB(fe);
|
|
// If our original viewedge is made of one FEdge, then
|
|
if ((vEdge->fedgeA() == vEdge->fedgeB()) || (fe == vEdge->fedgeB()))
|
|
newVEdge->setFEdgeB(newEdge);
|
|
else
|
|
newVEdge->setFEdgeB(vEdge->fedgeB()); //MODIF
|
|
|
|
Id *newId = vEdge->splittingId();
|
|
if (newId == 0) {
|
|
newId = new Id(vEdge->getId());
|
|
vEdge->setSplittingId(newId);
|
|
}
|
|
newId->setSecond(newId->getSecond() + 1);
|
|
newVEdge->setId(*newId);
|
|
newVEdge->setSplittingId(newId);
|
|
#if 0
|
|
Id id(vEdge->getId().getFirst(), vEdge->getId().getSecond() + 1);
|
|
newVEdge->setId(vEdge->getId());
|
|
vEdge->setId(id);
|
|
#endif
|
|
|
|
AddEdge(newVEdge); // here this shape is set as the edge's shape
|
|
|
|
// add new edge to the list of new edges passed as argument:
|
|
ioNewViewEdges.push_back(newVEdge);
|
|
|
|
if (0 != vvb)
|
|
vvb->Replace((vEdge), newVEdge);
|
|
|
|
// we split the view edge:
|
|
vEdge->setB((*vv));
|
|
vEdge->setFEdgeB(fe); //MODIF
|
|
|
|
// Update fedges so that they point to the new viewedge:
|
|
newVEdge->UpdateFEdges();
|
|
}
|
|
// check whether this vertex is a front vertex or a back one
|
|
if (sv == (*vv)->frontSVertex()) {
|
|
// -- View Vertex A' --
|
|
(*vv)->setFrontEdgeA(vEdge, true);
|
|
(*vv)->setFrontEdgeB(newVEdge, false);
|
|
}
|
|
else {
|
|
// -- View Vertex A' --
|
|
(*vv)->setBackEdgeA(vEdge, true);
|
|
(*vv)->setBackEdgeB(newVEdge, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**********************************/
|
|
/* */
|
|
/* */
|
|
/* ViewEdge */
|
|
/* */
|
|
/* */
|
|
/**********************************/
|
|
|
|
#if 0
|
|
inline Vec3r ViewEdge::orientation2d(int iCombination) const
|
|
{
|
|
return edge_orientation2d_function<ViewEdge>(*this, iCombination);
|
|
}
|
|
|
|
inline Vec3r ViewEdge::orientation3d(int iCombination) const
|
|
{
|
|
return edge_orientation3d_function<ViewEdge>(*this, iCombination);
|
|
}
|
|
|
|
inline real ViewEdge::z_discontinuity(int iCombination) const
|
|
{
|
|
return z_discontinuity_edge_function<ViewEdge>(*this, iCombination);
|
|
}
|
|
|
|
inline float ViewEdge::local_average_depth(int iCombination ) const
|
|
{
|
|
return local_average_depth_edge_function<ViewEdge>(*this, iCombination);
|
|
}
|
|
|
|
inline float ViewEdge::local_depth_variance(int iCombination) const
|
|
{
|
|
return local_depth_variance_edge_function<ViewEdge>(*this, iCombination);
|
|
}
|
|
|
|
inline real ViewEdge::local_average_density(float sigma, int iCombination) const
|
|
{
|
|
return density_edge_function<ViewEdge>(*this, iCombination);
|
|
}
|
|
#endif
|
|
|
|
inline const SShape *ViewEdge::occluded_shape() const
|
|
{
|
|
if (0 == _aShape)
|
|
return 0;
|
|
return _aShape->sshape();
|
|
}
|
|
|
|
#if 0
|
|
inline Vec3r ViewEdge::curvature2d_as_vector(int iCombination) const
|
|
{
|
|
return curvature2d_as_vector_edge_function<ViewEdge>(*this, iCombination);
|
|
}
|
|
|
|
inline real ViewEdge::curvature2d_as_angle(int iCombination) const
|
|
{
|
|
return curvature2d_as_angle_edge_function<ViewEdge>(*this, iCombination);
|
|
}
|
|
#endif
|
|
|
|
} /* namespace Freestyle */
|
|
|
|
#endif // __FREESTYLE_VIEW_MAP_H__
|