diff options
author | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:17:24 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:21:24 +0300 |
commit | e12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch) | |
tree | 8cf3453d12edb177a218ef8009357518ec6cab6a /source/blender/freestyle/intern/view_map | |
parent | b3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff) |
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211.
For details on usage and instructions for migrating branches
without conflicts, see:
https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'source/blender/freestyle/intern/view_map')
46 files changed, 14376 insertions, 14029 deletions
diff --git a/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.cpp b/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.cpp index 37273b0dd1e..6c5cbc71a76 100644 --- a/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.cpp +++ b/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.cpp @@ -25,91 +25,102 @@ namespace Freestyle { -ArbitraryGridDensityProvider::ArbitraryGridDensityProvider(OccluderSource& source, const real proscenium[4], +ArbitraryGridDensityProvider::ArbitraryGridDensityProvider(OccluderSource &source, + const real proscenium[4], unsigned numCells) -: GridDensityProvider(source), numCells(numCells) + : GridDensityProvider(source), numCells(numCells) { - initialize (proscenium); + initialize(proscenium); } -ArbitraryGridDensityProvider::ArbitraryGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox, - const GridHelpers::Transform& transform, unsigned numCells) -: GridDensityProvider(source), numCells(numCells) +ArbitraryGridDensityProvider::ArbitraryGridDensityProvider(OccluderSource &source, + const BBox<Vec3r> &bbox, + const GridHelpers::Transform &transform, + unsigned numCells) + : GridDensityProvider(source), numCells(numCells) { - real proscenium[4]; - calculateQuickProscenium(transform, bbox, proscenium); + real proscenium[4]; + calculateQuickProscenium(transform, bbox, proscenium); - initialize (proscenium); + initialize(proscenium); } -ArbitraryGridDensityProvider::ArbitraryGridDensityProvider(OccluderSource& source, unsigned numCells) -: GridDensityProvider(source), numCells(numCells) +ArbitraryGridDensityProvider::ArbitraryGridDensityProvider(OccluderSource &source, + unsigned numCells) + : GridDensityProvider(source), numCells(numCells) { - real proscenium[4]; - calculateOptimalProscenium(source, proscenium); + real proscenium[4]; + calculateOptimalProscenium(source, proscenium); - initialize (proscenium); + initialize(proscenium); } -ArbitraryGridDensityProvider::~ArbitraryGridDensityProvider() {} +ArbitraryGridDensityProvider::~ArbitraryGridDensityProvider() +{ +} void ArbitraryGridDensityProvider::initialize(const real proscenium[4]) { - float prosceniumWidth = (proscenium[1] - proscenium[0]); - float prosceniumHeight = (proscenium[3] - proscenium[2]); - real cellArea = prosceniumWidth * prosceniumHeight / numCells; - if (G.debug & G_DEBUG_FREESTYLE) { - cout << prosceniumWidth << " x " << prosceniumHeight << " grid with cells of area " << cellArea << "." << endl; - } - - _cellSize = sqrt(cellArea); - // Now we know how many cells make each side of our grid - _cellsX = ceil(prosceniumWidth / _cellSize); - _cellsY = ceil(prosceniumHeight / _cellSize); - if (G.debug & G_DEBUG_FREESTYLE) { - cout << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square." << endl; - } - - // Make sure the grid exceeds the proscenium by a small amount - float safetyZone = 0.1f; - if (_cellsX * _cellSize < prosceniumWidth * (1.0 + safetyZone)) { - _cellsX = ceil(prosceniumWidth * (1.0 + safetyZone) / _cellSize); - } - if (_cellsY * _cellSize < prosceniumHeight * (1.0 + safetyZone)) { - _cellsY = ceil(prosceniumHeight * (1.0 + safetyZone) / _cellSize); - } - if (G.debug & G_DEBUG_FREESTYLE) { - cout << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square." << endl; - } - - // Find grid origin - _cellOrigin[0] = ((proscenium[0] + proscenium[1]) / 2.0) - (_cellsX / 2.0) * _cellSize; - _cellOrigin[1] = ((proscenium[2] + proscenium[3]) / 2.0) - (_cellsY / 2.0) * _cellSize; + float prosceniumWidth = (proscenium[1] - proscenium[0]); + float prosceniumHeight = (proscenium[3] - proscenium[2]); + real cellArea = prosceniumWidth * prosceniumHeight / numCells; + if (G.debug & G_DEBUG_FREESTYLE) { + cout << prosceniumWidth << " x " << prosceniumHeight << " grid with cells of area " << cellArea + << "." << endl; + } + + _cellSize = sqrt(cellArea); + // Now we know how many cells make each side of our grid + _cellsX = ceil(prosceniumWidth / _cellSize); + _cellsY = ceil(prosceniumHeight / _cellSize); + if (G.debug & G_DEBUG_FREESTYLE) { + cout << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square." << endl; + } + + // Make sure the grid exceeds the proscenium by a small amount + float safetyZone = 0.1f; + if (_cellsX * _cellSize < prosceniumWidth * (1.0 + safetyZone)) { + _cellsX = ceil(prosceniumWidth * (1.0 + safetyZone) / _cellSize); + } + if (_cellsY * _cellSize < prosceniumHeight * (1.0 + safetyZone)) { + _cellsY = ceil(prosceniumHeight * (1.0 + safetyZone) / _cellSize); + } + if (G.debug & G_DEBUG_FREESTYLE) { + cout << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square." << endl; + } + + // Find grid origin + _cellOrigin[0] = ((proscenium[0] + proscenium[1]) / 2.0) - (_cellsX / 2.0) * _cellSize; + _cellOrigin[1] = ((proscenium[2] + proscenium[3]) / 2.0) - (_cellsY / 2.0) * _cellSize; } ArbitraryGridDensityProviderFactory::ArbitraryGridDensityProviderFactory(unsigned numCells) -: numCells(numCells) + : numCells(numCells) { } -ArbitraryGridDensityProviderFactory::~ArbitraryGridDensityProviderFactory() {} +ArbitraryGridDensityProviderFactory::~ArbitraryGridDensityProviderFactory() +{ +} -AutoPtr<GridDensityProvider> ArbitraryGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, - const real proscenium[4]) +AutoPtr<GridDensityProvider> ArbitraryGridDensityProviderFactory::newGridDensityProvider( + OccluderSource &source, const real proscenium[4]) { - return AutoPtr<GridDensityProvider>(new ArbitraryGridDensityProvider(source, proscenium, numCells)); + return AutoPtr<GridDensityProvider>( + new ArbitraryGridDensityProvider(source, proscenium, numCells)); } -AutoPtr<GridDensityProvider> -ArbitraryGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox, - const GridHelpers::Transform& transform) +AutoPtr<GridDensityProvider> ArbitraryGridDensityProviderFactory::newGridDensityProvider( + OccluderSource &source, const BBox<Vec3r> &bbox, const GridHelpers::Transform &transform) { - return AutoPtr<GridDensityProvider>(new ArbitraryGridDensityProvider(source, bbox, transform, numCells)); + return AutoPtr<GridDensityProvider>( + new ArbitraryGridDensityProvider(source, bbox, transform, numCells)); } -AutoPtr<GridDensityProvider> ArbitraryGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source) +AutoPtr<GridDensityProvider> ArbitraryGridDensityProviderFactory::newGridDensityProvider( + OccluderSource &source) { - return AutoPtr<GridDensityProvider>(new ArbitraryGridDensityProvider(source, numCells)); + return AutoPtr<GridDensityProvider>(new ArbitraryGridDensityProvider(source, numCells)); } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.h b/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.h index 8b616002279..97aae3d653c 100644 --- a/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.h +++ b/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.h @@ -26,41 +26,45 @@ namespace Freestyle { -class ArbitraryGridDensityProvider : public GridDensityProvider -{ - // Disallow copying and assignment - ArbitraryGridDensityProvider(const ArbitraryGridDensityProvider& other); - ArbitraryGridDensityProvider& operator=(const ArbitraryGridDensityProvider& other); +class ArbitraryGridDensityProvider : public GridDensityProvider { + // Disallow copying and assignment + ArbitraryGridDensityProvider(const ArbitraryGridDensityProvider &other); + ArbitraryGridDensityProvider &operator=(const ArbitraryGridDensityProvider &other); -public: - ArbitraryGridDensityProvider(OccluderSource& source, const real proscenium[4], unsigned numCells); - ArbitraryGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox, - const GridHelpers::Transform& transform, unsigned numCells); - ArbitraryGridDensityProvider(OccluderSource& source, unsigned numCells); - virtual ~ArbitraryGridDensityProvider(); + public: + ArbitraryGridDensityProvider(OccluderSource &source, + const real proscenium[4], + unsigned numCells); + ArbitraryGridDensityProvider(OccluderSource &source, + const BBox<Vec3r> &bbox, + const GridHelpers::Transform &transform, + unsigned numCells); + ArbitraryGridDensityProvider(OccluderSource &source, unsigned numCells); + virtual ~ArbitraryGridDensityProvider(); -protected: - unsigned numCells; + protected: + unsigned numCells; -private: - void initialize (const real proscenium[4]); + private: + void initialize(const real proscenium[4]); }; -class ArbitraryGridDensityProviderFactory : public GridDensityProviderFactory -{ -public: - ArbitraryGridDensityProviderFactory(unsigned numCells); - ~ArbitraryGridDensityProviderFactory(); +class ArbitraryGridDensityProviderFactory : public GridDensityProviderFactory { + public: + ArbitraryGridDensityProviderFactory(unsigned numCells); + ~ArbitraryGridDensityProviderFactory(); - AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const real proscenium[4]); - AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox, - const GridHelpers::Transform& transform); - AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource& source); + AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource &source, + const real proscenium[4]); + AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource &source, + const BBox<Vec3r> &bbox, + const GridHelpers::Transform &transform); + AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource &source); -protected: - unsigned numCells; + protected: + unsigned numCells; }; } /* namespace Freestyle */ -#endif // __FREESTYLE_ARBITRARY_GRID_DENSITY_PROVIDER_H__ +#endif // __FREESTYLE_ARBITRARY_GRID_DENSITY_PROVIDER_H__ diff --git a/source/blender/freestyle/intern/view_map/AutoPtrHelper.h b/source/blender/freestyle/intern/view_map/AutoPtrHelper.h index 2554d303b08..9da109ab2a6 100644 --- a/source/blender/freestyle/intern/view_map/AutoPtrHelper.h +++ b/source/blender/freestyle/intern/view_map/AutoPtrHelper.h @@ -27,28 +27,36 @@ namespace Freestyle { #if __cplusplus > 199711L -template<typename T> -class AutoPtr : public std::unique_ptr<T> { -public: - AutoPtr() : std::unique_ptr<T>() {} - AutoPtr(T *ptr) : std::unique_ptr<T>(ptr) {} - - /* TODO(sergey): Is there more clear way to do this? */ - template<typename X> - AutoPtr(AutoPtr<X>& other) : std::unique_ptr<T>(other.get()) { - other.release(); - } +template<typename T> class AutoPtr : public std::unique_ptr<T> { + public: + AutoPtr() : std::unique_ptr<T>() + { + } + AutoPtr(T *ptr) : std::unique_ptr<T>(ptr) + { + } + + /* TODO(sergey): Is there more clear way to do this? */ + template<typename X> AutoPtr(AutoPtr<X> &other) : std::unique_ptr<T>(other.get()) + { + other.release(); + } }; #else -template<typename T> -class AutoPtr : public std::auto_ptr<T> { -public: - AutoPtr() : std::auto_ptr<T>() {} - AutoPtr(T *ptr) : std::auto_ptr<T>(ptr) {} - AutoPtr(std::auto_ptr_ref<T> ref) : std::auto_ptr<T>(ref) {} +template<typename T> class AutoPtr : public std::auto_ptr<T> { + public: + AutoPtr() : std::auto_ptr<T>() + { + } + AutoPtr(T *ptr) : std::auto_ptr<T>(ptr) + { + } + AutoPtr(std::auto_ptr_ref<T> ref) : std::auto_ptr<T>(ref) + { + } }; #endif -} /* namespace Freestyle */ +} /* namespace Freestyle */ #endif // __FREESTYLE_AUTOPTR_HELPER_H__ diff --git a/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.cpp b/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.cpp index 8fc3fe810af..1384dc0f78b 100644 --- a/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.cpp +++ b/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.cpp @@ -25,112 +25,123 @@ namespace Freestyle { -AverageAreaGridDensityProvider::AverageAreaGridDensityProvider(OccluderSource& source, const real proscenium[4], +AverageAreaGridDensityProvider::AverageAreaGridDensityProvider(OccluderSource &source, + const real proscenium[4], real sizeFactor) -: GridDensityProvider(source) + : GridDensityProvider(source) { - initialize (proscenium, sizeFactor); + initialize(proscenium, sizeFactor); } -AverageAreaGridDensityProvider::AverageAreaGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox, - const GridHelpers::Transform& transform, real sizeFactor) -: GridDensityProvider(source) +AverageAreaGridDensityProvider::AverageAreaGridDensityProvider( + OccluderSource &source, + const BBox<Vec3r> &bbox, + const GridHelpers::Transform &transform, + real sizeFactor) + : GridDensityProvider(source) { - real proscenium[4]; - calculateQuickProscenium(transform, bbox, proscenium); + real proscenium[4]; + calculateQuickProscenium(transform, bbox, proscenium); - initialize(proscenium, sizeFactor); + initialize(proscenium, sizeFactor); } -AverageAreaGridDensityProvider::AverageAreaGridDensityProvider(OccluderSource& source, real sizeFactor) -: GridDensityProvider(source) +AverageAreaGridDensityProvider::AverageAreaGridDensityProvider(OccluderSource &source, + real sizeFactor) + : GridDensityProvider(source) { - real proscenium[4]; - calculateOptimalProscenium(source, proscenium); + real proscenium[4]; + calculateOptimalProscenium(source, proscenium); - initialize(proscenium, sizeFactor); + initialize(proscenium, sizeFactor); } -AverageAreaGridDensityProvider::~AverageAreaGridDensityProvider() {} +AverageAreaGridDensityProvider::~AverageAreaGridDensityProvider() +{ +} void AverageAreaGridDensityProvider::initialize(const real proscenium[4], real sizeFactor) { - float prosceniumWidth = (proscenium[1] - proscenium[0]); - float prosceniumHeight = (proscenium[3] - proscenium[2]); - - real cellArea = 0.0; - unsigned numFaces = 0; - for (source.begin(); source.isValid(); source.next()) { - Polygon3r& poly(source.getGridSpacePolygon()); - Vec3r min, max; - poly.getBBox(min, max); - cellArea += (max[0] - min[0]) * (max[1] - min[1]); - ++numFaces; - } - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Total area: " << cellArea << ". Number of faces: " << numFaces << "." << endl; - } - cellArea /= numFaces; - cellArea *= sizeFactor; - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Building grid with average area " << cellArea << endl; - } - - _cellSize = sqrt(cellArea); - unsigned maxCells = 931; // * 1.1 = 1024 - if (std::max(prosceniumWidth, prosceniumHeight) / _cellSize > maxCells) { - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Scene-dependent cell size (" << _cellSize << " square) is too small." << endl; - } - _cellSize = std::max(prosceniumWidth, prosceniumHeight) / maxCells; - } - // Now we know how many cells make each side of our grid - _cellsX = ceil(prosceniumWidth / _cellSize); - _cellsY = ceil(prosceniumHeight / _cellSize); - if (G.debug & G_DEBUG_FREESTYLE) { - cout << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square." << endl; - } - - // Make sure the grid exceeds the proscenium by a small amount - float safetyZone = 0.1f; - if (_cellsX * _cellSize < prosceniumWidth * (1.0 + safetyZone)) { - _cellsX = ceil(prosceniumWidth * (1.0 + safetyZone) / _cellSize); - } - if (_cellsY * _cellSize < prosceniumHeight * (1.0 + safetyZone)) { - _cellsY = ceil(prosceniumHeight * (1.0 + safetyZone) / _cellSize); - } - if (G.debug & G_DEBUG_FREESTYLE) { - cout << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square." << endl; - } - - // Find grid origin - _cellOrigin[0] = ((proscenium[0] + proscenium[1]) / 2.0) - (_cellsX / 2.0) * _cellSize; - _cellOrigin[1] = ((proscenium[2] + proscenium[3]) / 2.0) - (_cellsY / 2.0) * _cellSize; + float prosceniumWidth = (proscenium[1] - proscenium[0]); + float prosceniumHeight = (proscenium[3] - proscenium[2]); + + real cellArea = 0.0; + unsigned numFaces = 0; + for (source.begin(); source.isValid(); source.next()) { + Polygon3r &poly(source.getGridSpacePolygon()); + Vec3r min, max; + poly.getBBox(min, max); + cellArea += (max[0] - min[0]) * (max[1] - min[1]); + ++numFaces; + } + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Total area: " << cellArea << ". Number of faces: " << numFaces << "." << endl; + } + cellArea /= numFaces; + cellArea *= sizeFactor; + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Building grid with average area " << cellArea << endl; + } + + _cellSize = sqrt(cellArea); + unsigned maxCells = 931; // * 1.1 = 1024 + if (std::max(prosceniumWidth, prosceniumHeight) / _cellSize > maxCells) { + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Scene-dependent cell size (" << _cellSize << " square) is too small." << endl; + } + _cellSize = std::max(prosceniumWidth, prosceniumHeight) / maxCells; + } + // Now we know how many cells make each side of our grid + _cellsX = ceil(prosceniumWidth / _cellSize); + _cellsY = ceil(prosceniumHeight / _cellSize); + if (G.debug & G_DEBUG_FREESTYLE) { + cout << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square." << endl; + } + + // Make sure the grid exceeds the proscenium by a small amount + float safetyZone = 0.1f; + if (_cellsX * _cellSize < prosceniumWidth * (1.0 + safetyZone)) { + _cellsX = ceil(prosceniumWidth * (1.0 + safetyZone) / _cellSize); + } + if (_cellsY * _cellSize < prosceniumHeight * (1.0 + safetyZone)) { + _cellsY = ceil(prosceniumHeight * (1.0 + safetyZone) / _cellSize); + } + if (G.debug & G_DEBUG_FREESTYLE) { + cout << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square." << endl; + } + + // Find grid origin + _cellOrigin[0] = ((proscenium[0] + proscenium[1]) / 2.0) - (_cellsX / 2.0) * _cellSize; + _cellOrigin[1] = ((proscenium[2] + proscenium[3]) / 2.0) - (_cellsY / 2.0) * _cellSize; } AverageAreaGridDensityProviderFactory::AverageAreaGridDensityProviderFactory(real sizeFactor) -: sizeFactor(sizeFactor) + : sizeFactor(sizeFactor) { } -AverageAreaGridDensityProviderFactory::~AverageAreaGridDensityProviderFactory() {} +AverageAreaGridDensityProviderFactory::~AverageAreaGridDensityProviderFactory() +{ +} -AutoPtr<GridDensityProvider> -AverageAreaGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const real proscenium[4]) +AutoPtr<GridDensityProvider> AverageAreaGridDensityProviderFactory::newGridDensityProvider( + OccluderSource &source, const real proscenium[4]) { - return AutoPtr<GridDensityProvider>(new AverageAreaGridDensityProvider(source, proscenium, sizeFactor)); + return AutoPtr<GridDensityProvider>( + new AverageAreaGridDensityProvider(source, proscenium, sizeFactor)); } -AutoPtr<GridDensityProvider> -AverageAreaGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox, - const GridHelpers::Transform& transform) +AutoPtr<GridDensityProvider> AverageAreaGridDensityProviderFactory::newGridDensityProvider( + OccluderSource &source, const BBox<Vec3r> &bbox, const GridHelpers::Transform &transform) { - return AutoPtr<GridDensityProvider>(new AverageAreaGridDensityProvider(source, bbox, transform, sizeFactor)); + return AutoPtr<GridDensityProvider>( + new AverageAreaGridDensityProvider(source, bbox, transform, sizeFactor)); } -AutoPtr<GridDensityProvider> AverageAreaGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source) +AutoPtr<GridDensityProvider> AverageAreaGridDensityProviderFactory::newGridDensityProvider( + OccluderSource &source) { - return AutoPtr<GridDensityProvider>(new AverageAreaGridDensityProvider(source, sizeFactor)); + return AutoPtr<GridDensityProvider>(new AverageAreaGridDensityProvider(source, sizeFactor)); } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.h b/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.h index e422ad2ba8d..f530cf35569 100644 --- a/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.h +++ b/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.h @@ -26,38 +26,42 @@ namespace Freestyle { -class AverageAreaGridDensityProvider : public GridDensityProvider -{ - // Disallow copying and assignment - AverageAreaGridDensityProvider(const AverageAreaGridDensityProvider& other); - AverageAreaGridDensityProvider& operator=(const AverageAreaGridDensityProvider& other); - -public: - AverageAreaGridDensityProvider(OccluderSource& source, const real proscenium[4], real sizeFactor); - AverageAreaGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox, - const GridHelpers::Transform& transform, real sizeFactor); - AverageAreaGridDensityProvider(OccluderSource& source, real sizeFactor); - virtual ~AverageAreaGridDensityProvider(); - -private: - void initialize (const real proscenium[4], real sizeFactor); +class AverageAreaGridDensityProvider : public GridDensityProvider { + // Disallow copying and assignment + AverageAreaGridDensityProvider(const AverageAreaGridDensityProvider &other); + AverageAreaGridDensityProvider &operator=(const AverageAreaGridDensityProvider &other); + + public: + AverageAreaGridDensityProvider(OccluderSource &source, + const real proscenium[4], + real sizeFactor); + AverageAreaGridDensityProvider(OccluderSource &source, + const BBox<Vec3r> &bbox, + const GridHelpers::Transform &transform, + real sizeFactor); + AverageAreaGridDensityProvider(OccluderSource &source, real sizeFactor); + virtual ~AverageAreaGridDensityProvider(); + + private: + void initialize(const real proscenium[4], real sizeFactor); }; -class AverageAreaGridDensityProviderFactory : public GridDensityProviderFactory -{ -public: - AverageAreaGridDensityProviderFactory(real sizeFactor); - ~AverageAreaGridDensityProviderFactory(); +class AverageAreaGridDensityProviderFactory : public GridDensityProviderFactory { + public: + AverageAreaGridDensityProviderFactory(real sizeFactor); + ~AverageAreaGridDensityProviderFactory(); - AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const real proscenium[4]); - AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox, - const GridHelpers::Transform& transform); - AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource& source); + AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource &source, + const real proscenium[4]); + AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource &source, + const BBox<Vec3r> &bbox, + const GridHelpers::Transform &transform); + AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource &source); -protected: - real sizeFactor; + protected: + real sizeFactor; }; } /* namespace Freestyle */ -#endif // __FREESTYLE_AVERAGE_AREA_GRID_DENSITY_PROVIDER_H__ +#endif // __FREESTYLE_AVERAGE_AREA_GRID_DENSITY_PROVIDER_H__ diff --git a/source/blender/freestyle/intern/view_map/BoxGrid.cpp b/source/blender/freestyle/intern/view_map/BoxGrid.cpp index 396688fe62c..5a490e3c7cc 100644 --- a/source/blender/freestyle/intern/view_map/BoxGrid.cpp +++ b/source/blender/freestyle/intern/view_map/BoxGrid.cpp @@ -38,199 +38,217 @@ namespace Freestyle { // Cell ///////// -BoxGrid::Cell::Cell() {} +BoxGrid::Cell::Cell() +{ +} -BoxGrid::Cell::~Cell() {} +BoxGrid::Cell::~Cell() +{ +} void BoxGrid::Cell::setDimensions(real x, real y, real sizeX, real sizeY) { - const real epsilon = 1.0e-06; - boundary[0] = x - epsilon; - boundary[1] = x + sizeX + epsilon; - boundary[2] = y - epsilon; - boundary[3] = y + sizeY + epsilon; + const real epsilon = 1.0e-06; + boundary[0] = x - epsilon; + boundary[1] = x + sizeX + epsilon; + boundary[2] = y - epsilon; + boundary[3] = y + sizeY + epsilon; } -bool BoxGrid::Cell::compareOccludersByShallowestPoint(const BoxGrid::OccluderData *a, const BoxGrid::OccluderData *b) +bool BoxGrid::Cell::compareOccludersByShallowestPoint(const BoxGrid::OccluderData *a, + const BoxGrid::OccluderData *b) { - return a->shallowest < b->shallowest; + return a->shallowest < b->shallowest; } void BoxGrid::Cell::indexPolygons() { - // Sort occluders by their shallowest points. - sort(faces.begin(), faces.end(), compareOccludersByShallowestPoint); + // Sort occluders by their shallowest points. + sort(faces.begin(), faces.end(), compareOccludersByShallowestPoint); } // Iterator ////////////////// -BoxGrid::Iterator::Iterator (BoxGrid& grid, Vec3r& center, real /*epsilon*/) -: _target(grid.transform(center)), _foundOccludee(false) +BoxGrid::Iterator::Iterator(BoxGrid &grid, Vec3r ¢er, real /*epsilon*/) + : _target(grid.transform(center)), _foundOccludee(false) { - // Find target cell - _cell = grid.findCell(_target); + // Find target cell + _cell = grid.findCell(_target); #if BOX_GRID_LOGGING - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Searching for occluders of edge centered at " << _target << " in cell [" << - 1_cell->boundary[0] << ", " << _cell->boundary[1] << ", " << _cell->boundary[2] << - ", " << _cell->boundary[3] << "] (" << _cell->faces.size() << " occluders)" << endl; - } + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Searching for occluders of edge centered at " << _target << " in cell [" + << 1_cell->boundary[0] << ", " << _cell->boundary[1] << ", " << _cell->boundary[2] << ", " + << _cell->boundary[3] << "] (" << _cell->faces.size() << " occluders)" << endl; + } #endif - // Set iterator - _current = _cell->faces.begin(); + // Set iterator + _current = _cell->faces.begin(); } -BoxGrid::Iterator::~Iterator() {} +BoxGrid::Iterator::~Iterator() +{ +} // BoxGrid ///////////////// -BoxGrid::BoxGrid(OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap, Vec3r& viewpoint, +BoxGrid::BoxGrid(OccluderSource &source, + GridDensityProvider &density, + ViewMap *viewMap, + Vec3r &viewpoint, bool enableQI) -: _viewpoint(viewpoint), _enableQI(enableQI) -{ - // Generate Cell structure - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Generate Cell structure" << endl; - } - assignCells(source, density, viewMap); - - // Fill Cells - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Distribute occluders" << endl; - } - distributePolygons(source); - - // Reorganize Cells - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Reorganize cells" << endl; - } - reorganizeCells(); - - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Ready to use BoxGrid" << endl; - } -} - -BoxGrid::~BoxGrid() {} - -void BoxGrid::assignCells (OccluderSource& /*source*/, GridDensityProvider& density, ViewMap *viewMap) -{ - _cellSize = density.cellSize(); - _cellsX = density.cellsX(); - _cellsY = density.cellsY(); - _cellOrigin[0] = density.cellOrigin(0); - _cellOrigin[1] = density.cellOrigin(1); - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Using " << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square." << endl; - cout << "Cell origin: " << _cellOrigin[0] << ", " << _cellOrigin[1] << endl; - } - - // Now allocate the cell table and fill it with default (empty) cells - _cells.resize(_cellsX * _cellsY); - for (cellContainer::iterator i = _cells.begin(), end = _cells.end(); i != end; ++i) { - (*i) = NULL; - } - - // Identify cells that will be used, and set the dimensions for each - ViewMap::fedges_container& fedges = viewMap->FEdges(); - for (ViewMap::fedges_container::iterator f = fedges.begin(), fend = fedges.end(); f != fend; ++f) { - if ((*f)->isInImage()) { - Vec3r point = transform((*f)->center3d()); - unsigned int i, j; - getCellCoordinates(point, i, j); - if (_cells[i * _cellsY + j] == NULL) { - // This is an uninitialized cell - real x, y, width, height; - - x = _cellOrigin[0] + _cellSize * i; - width = _cellSize; - - y = _cellOrigin[1] + _cellSize * j; - height = _cellSize; - - // Initialize cell - Cell *b = _cells[i * _cellsY + j] = new Cell(); - b->setDimensions(x, y, width, height); - } - } - } -} - -void BoxGrid::distributePolygons(OccluderSource& source) -{ - unsigned long nFaces = 0; - unsigned long nKeptFaces = 0; - - for (source.begin(); source.isValid(); source.next()) { - OccluderData *occluder = NULL; - - try { - if (insertOccluder(source, occluder)) { - _faces.push_back(occluder); - ++nKeptFaces; - } - } - catch (...) { - // If an exception was thrown, _faces.push_back() cannot have succeeded. - // occluder is not owned by anyone, and must be deleted. - // If the exception was thrown before or during new OccluderData(), then - // occluder is NULL, and this delete is harmless. - delete occluder; - throw; - } - ++nFaces; - } - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Distributed " << nFaces << " occluders. Retained " << nKeptFaces << "." << endl; - } + : _viewpoint(viewpoint), _enableQI(enableQI) +{ + // Generate Cell structure + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Generate Cell structure" << endl; + } + assignCells(source, density, viewMap); + + // Fill Cells + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Distribute occluders" << endl; + } + distributePolygons(source); + + // Reorganize Cells + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Reorganize cells" << endl; + } + reorganizeCells(); + + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Ready to use BoxGrid" << endl; + } +} + +BoxGrid::~BoxGrid() +{ +} + +void BoxGrid::assignCells(OccluderSource & /*source*/, + GridDensityProvider &density, + ViewMap *viewMap) +{ + _cellSize = density.cellSize(); + _cellsX = density.cellsX(); + _cellsY = density.cellsY(); + _cellOrigin[0] = density.cellOrigin(0); + _cellOrigin[1] = density.cellOrigin(1); + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Using " << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square." + << endl; + cout << "Cell origin: " << _cellOrigin[0] << ", " << _cellOrigin[1] << endl; + } + + // Now allocate the cell table and fill it with default (empty) cells + _cells.resize(_cellsX * _cellsY); + for (cellContainer::iterator i = _cells.begin(), end = _cells.end(); i != end; ++i) { + (*i) = NULL; + } + + // Identify cells that will be used, and set the dimensions for each + ViewMap::fedges_container &fedges = viewMap->FEdges(); + for (ViewMap::fedges_container::iterator f = fedges.begin(), fend = fedges.end(); f != fend; + ++f) { + if ((*f)->isInImage()) { + Vec3r point = transform((*f)->center3d()); + unsigned int i, j; + getCellCoordinates(point, i, j); + if (_cells[i * _cellsY + j] == NULL) { + // This is an uninitialized cell + real x, y, width, height; + + x = _cellOrigin[0] + _cellSize * i; + width = _cellSize; + + y = _cellOrigin[1] + _cellSize * j; + height = _cellSize; + + // Initialize cell + Cell *b = _cells[i * _cellsY + j] = new Cell(); + b->setDimensions(x, y, width, height); + } + } + } +} + +void BoxGrid::distributePolygons(OccluderSource &source) +{ + unsigned long nFaces = 0; + unsigned long nKeptFaces = 0; + + for (source.begin(); source.isValid(); source.next()) { + OccluderData *occluder = NULL; + + try { + if (insertOccluder(source, occluder)) { + _faces.push_back(occluder); + ++nKeptFaces; + } + } + catch (...) { + // If an exception was thrown, _faces.push_back() cannot have succeeded. + // occluder is not owned by anyone, and must be deleted. + // If the exception was thrown before or during new OccluderData(), then + // occluder is NULL, and this delete is harmless. + delete occluder; + throw; + } + ++nFaces; + } + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Distributed " << nFaces << " occluders. Retained " << nKeptFaces << "." << endl; + } } void BoxGrid::reorganizeCells() { - // Sort the occluders by shallowest point - for (vector<Cell*>::iterator i = _cells.begin(), end = _cells.end(); i != end; ++i) { - if (*i != NULL) { - (*i)->indexPolygons(); - } - } + // Sort the occluders by shallowest point + for (vector<Cell *>::iterator i = _cells.begin(), end = _cells.end(); i != end; ++i) { + if (*i != NULL) { + (*i)->indexPolygons(); + } + } } -void BoxGrid::getCellCoordinates(const Vec3r& point, unsigned& x, unsigned& y) +void BoxGrid::getCellCoordinates(const Vec3r &point, unsigned &x, unsigned &y) { - x = min(_cellsX - 1, (unsigned) floor (max((double) 0.0f, point[0] - _cellOrigin[0]) / _cellSize)); - y = min(_cellsY - 1, (unsigned) floor (max((double) 0.0f, point[1] - _cellOrigin[1]) / _cellSize)); + x = min(_cellsX - 1, (unsigned)floor(max((double)0.0f, point[0] - _cellOrigin[0]) / _cellSize)); + y = min(_cellsY - 1, (unsigned)floor(max((double)0.0f, point[1] - _cellOrigin[1]) / _cellSize)); } -BoxGrid::Cell *BoxGrid::findCell(const Vec3r& point) +BoxGrid::Cell *BoxGrid::findCell(const Vec3r &point) { - unsigned int x, y; - getCellCoordinates(point, x, y); - return _cells[x * _cellsY + y]; + unsigned int x, y; + getCellCoordinates(point, x, y); + return _cells[x * _cellsY + y]; } bool BoxGrid::orthographicProjection() const { - return true; + return true; } -const Vec3r& BoxGrid::viewpoint() const +const Vec3r &BoxGrid::viewpoint() const { - return _viewpoint; + return _viewpoint; } bool BoxGrid::enableQI() const { - return _enableQI; + return _enableQI; } -BoxGrid::Transform::Transform() : GridHelpers::Transform() {} +BoxGrid::Transform::Transform() : GridHelpers::Transform() +{ +} -Vec3r BoxGrid::Transform::operator()(const Vec3r& point) const +Vec3r BoxGrid::Transform::operator()(const Vec3r &point) const { - return Vec3r(point[0], point[1], -point[2]); + return Vec3r(point[0], point[1], -point[2]); } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/view_map/BoxGrid.h b/source/blender/freestyle/intern/view_map/BoxGrid.h index 9d2a3c7ea4c..83c379102f5 100644 --- a/source/blender/freestyle/intern/view_map/BoxGrid.h +++ b/source/blender/freestyle/intern/view_map/BoxGrid.h @@ -45,380 +45,379 @@ #include "BKE_global.h" #ifdef WITH_CXX_GUARDEDALLOC -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif namespace Freestyle { -class BoxGrid -{ -public: - // Helper classes - struct OccluderData - { - explicit OccluderData(OccluderSource& source, Polygon3r& p); - Polygon3r poly; - Polygon3r cameraSpacePolygon; - real shallowest, deepest; - // N.B. We could, of course, store face in poly's userdata member, like the old ViewMapBuilder code does. - // However, code comments make it clear that userdata is deprecated, so we avoid the temptation - // to save 4 or 8 bytes. - WFace *face; +class BoxGrid { + public: + // Helper classes + struct OccluderData { + explicit OccluderData(OccluderSource &source, Polygon3r &p); + Polygon3r poly; + Polygon3r cameraSpacePolygon; + real shallowest, deepest; + // N.B. We could, of course, store face in poly's userdata member, like the old ViewMapBuilder code does. + // However, code comments make it clear that userdata is deprecated, so we avoid the temptation + // to save 4 or 8 bytes. + WFace *face; #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BoxGrid:OccluderData") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BoxGrid:OccluderData") #endif - }; - -private: - struct Cell - { - // Can't store Cell in a vector without copy and assign - // Cell(const Cell& other); - // Cell& operator=(const Cell& other); - - explicit Cell(); - ~Cell(); - - static bool compareOccludersByShallowestPoint(const OccluderData *a, const OccluderData *b); - - void setDimensions(real x, real y, real sizeX, real sizeY); - void checkAndInsert(OccluderSource& source, Polygon3r& poly, OccluderData*& occluder); - void indexPolygons(); - - real boundary[4]; - //deque<OccluderData*> faces; - vector<OccluderData*> faces; - }; - -public: - /* Iterator needs to allow the user to avoid full 3D comparison in two cases: - * - * (1) Where (*current)->deepest < target[2], where the occluder is unambiguously in front of the target point. - * - * (2) Where (*current)->shallowest > target[2], where the occluder is unambiguously in back of the target point. - * - * In addition, when used by OptimizedFindOccludee, Iterator should stop iterating as soon as it has an - * occludee candidate and (*current)->shallowest > candidate[2], because at that point forward no new occluder - * could possibly be a better occludee. - */ - class Iterator - { - public: - // epsilon is not used in this class, but other grids with the same interface may need an epsilon - explicit Iterator(BoxGrid& grid, Vec3r& center, real epsilon = 1.0e-06); - ~Iterator(); - void initBeforeTarget(); - void initAfterTarget(); - void nextOccluder(); - void nextOccludee(); - bool validBeforeTarget(); - bool validAfterTarget(); - WFace *getWFace() const; - Polygon3r *getCameraSpacePolygon(); - void reportDepth(Vec3r origin, Vec3r u, real t); - - private: - bool testOccluder(bool wantOccludee); - void markCurrentOccludeeCandidate(real depth); - - Cell *_cell; - Vec3r _target; - bool _foundOccludee; - real _occludeeDepth; - //deque<OccluderData*>::iterator _current, _occludeeCandidate; - vector<OccluderData*>::iterator _current, _occludeeCandidate; + }; + + private: + struct Cell { + // Can't store Cell in a vector without copy and assign + // Cell(const Cell& other); + // Cell& operator=(const Cell& other); + + explicit Cell(); + ~Cell(); + + static bool compareOccludersByShallowestPoint(const OccluderData *a, const OccluderData *b); + + void setDimensions(real x, real y, real sizeX, real sizeY); + void checkAndInsert(OccluderSource &source, Polygon3r &poly, OccluderData *&occluder); + void indexPolygons(); + + real boundary[4]; + //deque<OccluderData*> faces; + vector<OccluderData *> faces; + }; + + public: + /* Iterator needs to allow the user to avoid full 3D comparison in two cases: + * + * (1) Where (*current)->deepest < target[2], where the occluder is unambiguously in front of the target point. + * + * (2) Where (*current)->shallowest > target[2], where the occluder is unambiguously in back of the target point. + * + * In addition, when used by OptimizedFindOccludee, Iterator should stop iterating as soon as it has an + * occludee candidate and (*current)->shallowest > candidate[2], because at that point forward no new occluder + * could possibly be a better occludee. + */ + class Iterator { + public: + // epsilon is not used in this class, but other grids with the same interface may need an epsilon + explicit Iterator(BoxGrid &grid, Vec3r ¢er, real epsilon = 1.0e-06); + ~Iterator(); + void initBeforeTarget(); + void initAfterTarget(); + void nextOccluder(); + void nextOccludee(); + bool validBeforeTarget(); + bool validAfterTarget(); + WFace *getWFace() const; + Polygon3r *getCameraSpacePolygon(); + void reportDepth(Vec3r origin, Vec3r u, real t); + + private: + bool testOccluder(bool wantOccludee); + void markCurrentOccludeeCandidate(real depth); + + Cell *_cell; + Vec3r _target; + bool _foundOccludee; + real _occludeeDepth; + //deque<OccluderData*>::iterator _current, _occludeeCandidate; + vector<OccluderData *>::iterator _current, _occludeeCandidate; #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BoxGrid:Iterator") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BoxGrid:Iterator") #endif - }; - - class Transform : public GridHelpers::Transform - { - public: - explicit Transform(); - explicit Transform(Transform& other); - Vec3r operator()(const Vec3r& point) const; - }; - -private: - // Prevent implicit copies and assignments. - BoxGrid(const BoxGrid& other); - BoxGrid& operator=(const BoxGrid& other); - -public: - explicit BoxGrid(OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap, Vec3r& viewpoint, - bool enableQI); - virtual ~BoxGrid(); - - // Generate Cell structure - void assignCells(OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap); - // Fill Cells - void distributePolygons(OccluderSource& source); - // Insert one polygon into each matching cell, return true if any cell consumes the polygon - bool insertOccluder(OccluderSource& source, OccluderData*& occluder); - // Sort occluders in each cell - void reorganizeCells(); - - Cell *findCell(const Vec3r& point); - - // Accessors: - bool orthographicProjection() const; - const Vec3r& viewpoint() const; - bool enableQI() const; - Transform transform; - -private: - void getCellCoordinates(const Vec3r& point, unsigned& x, unsigned& y); - - typedef PointerSequence<vector<Cell*>, Cell*> cellContainer; - //typedef PointerSequence<deque<OccluderData*>, OccluderData*> occluderContainer; - typedef PointerSequence<vector<OccluderData*>, OccluderData*> occluderContainer; - unsigned _cellsX, _cellsY; - float _cellSize; - float _cellOrigin[2]; - cellContainer _cells; - occluderContainer _faces; - Vec3r _viewpoint; - bool _enableQI; + }; + + class Transform : public GridHelpers::Transform { + public: + explicit Transform(); + explicit Transform(Transform &other); + Vec3r operator()(const Vec3r &point) const; + }; + + private: + // Prevent implicit copies and assignments. + BoxGrid(const BoxGrid &other); + BoxGrid &operator=(const BoxGrid &other); + + public: + explicit BoxGrid(OccluderSource &source, + GridDensityProvider &density, + ViewMap *viewMap, + Vec3r &viewpoint, + bool enableQI); + virtual ~BoxGrid(); + + // Generate Cell structure + void assignCells(OccluderSource &source, GridDensityProvider &density, ViewMap *viewMap); + // Fill Cells + void distributePolygons(OccluderSource &source); + // Insert one polygon into each matching cell, return true if any cell consumes the polygon + bool insertOccluder(OccluderSource &source, OccluderData *&occluder); + // Sort occluders in each cell + void reorganizeCells(); + + Cell *findCell(const Vec3r &point); + + // Accessors: + bool orthographicProjection() const; + const Vec3r &viewpoint() const; + bool enableQI() const; + Transform transform; + + private: + void getCellCoordinates(const Vec3r &point, unsigned &x, unsigned &y); + + typedef PointerSequence<vector<Cell *>, Cell *> cellContainer; + //typedef PointerSequence<deque<OccluderData*>, OccluderData*> occluderContainer; + typedef PointerSequence<vector<OccluderData *>, OccluderData *> occluderContainer; + unsigned _cellsX, _cellsY; + float _cellSize; + float _cellOrigin[2]; + cellContainer _cells; + occluderContainer _faces; + Vec3r _viewpoint; + bool _enableQI; #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BoxGrid") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BoxGrid") #endif }; inline void BoxGrid::Iterator::initBeforeTarget() { - _current = _cell->faces.begin(); - while (_current != _cell->faces.end() && !testOccluder(false)) { - ++_current; - } + _current = _cell->faces.begin(); + while (_current != _cell->faces.end() && !testOccluder(false)) { + ++_current; + } } inline void BoxGrid::Iterator::initAfterTarget() { - if (_foundOccludee) { + if (_foundOccludee) { #if BOX_GRID_LOGGING - if (G.debug & G_DEBUG_FREESTYLE) { - std::cout << "\tStarting occludee search from occludeeCandidate at depth " << - _occludeeDepth << std::endl; - } + if (G.debug & G_DEBUG_FREESTYLE) { + std::cout << "\tStarting occludee search from occludeeCandidate at depth " << _occludeeDepth + << std::endl; + } #endif - _current = _occludeeCandidate; - return; - } + _current = _occludeeCandidate; + return; + } #if BOX_GRID_LOGGING - if (G.debug & G_DEBUG_FREESTYLE) { - std::cout << "\tStarting occludee search from current position" << std::endl; - } + if (G.debug & G_DEBUG_FREESTYLE) { + std::cout << "\tStarting occludee search from current position" << std::endl; + } #endif - while (_current != _cell->faces.end() && !testOccluder(true)) { - ++_current; - } + while (_current != _cell->faces.end() && !testOccluder(true)) { + ++_current; + } } inline bool BoxGrid::Iterator::testOccluder(bool wantOccludee) { - // End-of-list is not even a valid iterator position - if (_current == _cell->faces.end()) { - // Returning true seems strange, but it will break us out of whatever loop is calling testOccluder, - // and _current = _cell->face.end() will make the calling routine give up. - return true; - } + // End-of-list is not even a valid iterator position + if (_current == _cell->faces.end()) { + // Returning true seems strange, but it will break us out of whatever loop is calling testOccluder, + // and _current = _cell->face.end() will make the calling routine give up. + return true; + } #if BOX_GRID_LOGGING - if (G.debug & G_DEBUG_FREESTYLE) { - std::cout << "\tTesting occluder " << (*_current)->poly.getVertices()[0]; - for (unsigned int i = 1; i < (*_current)->poly.getVertices().size(); ++i) { - std::cout << ", " << (*_current)->poly.getVertices()[i]; - } - std::cout << " from shape " << (*_current)->face->GetVertex(0)->shape()->GetId() << std::endl; - } + if (G.debug & G_DEBUG_FREESTYLE) { + std::cout << "\tTesting occluder " << (*_current)->poly.getVertices()[0]; + for (unsigned int i = 1; i < (*_current)->poly.getVertices().size(); ++i) { + std::cout << ", " << (*_current)->poly.getVertices()[i]; + } + std::cout << " from shape " << (*_current)->face->GetVertex(0)->shape()->GetId() << std::endl; + } #endif - // If we have an occluder candidate and we are unambiguously after it, abort - if (_foundOccludee && (*_current)->shallowest > _occludeeDepth) { + // If we have an occluder candidate and we are unambiguously after it, abort + if (_foundOccludee && (*_current)->shallowest > _occludeeDepth) { #if BOX_GRID_LOGGING - if (G.debug & G_DEBUG_FREESTYLE) { - std::cout << "\t\tAborting: shallowest > occludeeCandidate->deepest" << std::endl; - } + if (G.debug & G_DEBUG_FREESTYLE) { + std::cout << "\t\tAborting: shallowest > occludeeCandidate->deepest" << std::endl; + } #endif - _current = _cell->faces.end(); + _current = _cell->faces.end(); - // See note above - return true; - } + // See note above + return true; + } - // Specific continue or stop conditions when searching for each type - if (wantOccludee) { - if ((*_current)->deepest < _target[2]) { + // Specific continue or stop conditions when searching for each type + if (wantOccludee) { + if ((*_current)->deepest < _target[2]) { #if BOX_GRID_LOGGING - if (G.debug & G_DEBUG_FREESTYLE) { - std::cout << "\t\tSkipping: shallower than target while looking for occludee" << std::endl; - } + if (G.debug & G_DEBUG_FREESTYLE) { + std::cout << "\t\tSkipping: shallower than target while looking for occludee" << std::endl; + } #endif - return false; - } - } - else { - if ((*_current)->shallowest > _target[2]) { + return false; + } + } + else { + if ((*_current)->shallowest > _target[2]) { #if BOX_GRID_LOGGING - if (G.debug & G_DEBUG_FREESTYLE) { - std::cout << "\t\tStopping: deeper than target while looking for occluder" << std::endl; - } + if (G.debug & G_DEBUG_FREESTYLE) { + std::cout << "\t\tStopping: deeper than target while looking for occluder" << std::endl; + } #endif - return true; - } - } + return true; + } + } - // Depthwise, this is a valid occluder. + // Depthwise, this is a valid occluder. - // Check to see if target is in the 2D bounding box - Vec3r bbMin, bbMax; - (*_current)->poly.getBBox(bbMin, bbMax); - if (_target[0] < bbMin[0] || _target[0] > bbMax[0] || _target[1] < bbMin[1] || _target[1] > bbMax[1]) { + // Check to see if target is in the 2D bounding box + Vec3r bbMin, bbMax; + (*_current)->poly.getBBox(bbMin, bbMax); + if (_target[0] < bbMin[0] || _target[0] > bbMax[0] || _target[1] < bbMin[1] || + _target[1] > bbMax[1]) { #if BOX_GRID_LOGGING - if (G.debug & G_DEBUG_FREESTYLE) { - std::cout << "\t\tSkipping: bounding box violation" << std::endl; - } + if (G.debug & G_DEBUG_FREESTYLE) { + std::cout << "\t\tSkipping: bounding box violation" << std::endl; + } #endif - return false; - } + return false; + } - // We've done all the corner cutting we can. - // Let the caller work out whether or not the geometry is correct. - return true; + // We've done all the corner cutting we can. + // Let the caller work out whether or not the geometry is correct. + return true; } inline void BoxGrid::Iterator::reportDepth(Vec3r origin, Vec3r u, real t) { - // The reported depth is the length of a ray in camera space - // We need to convert it into a Z-value in grid space - real depth = -(origin + (u * t))[2]; + // The reported depth is the length of a ray in camera space + // We need to convert it into a Z-value in grid space + real depth = -(origin + (u * t))[2]; #if BOX_GRID_LOGGING - if (G.debug & G_DEBUG_FREESTYLE) { - std::cout << "\t\tReporting depth of occluder/ee: " << depth; - } + if (G.debug & G_DEBUG_FREESTYLE) { + std::cout << "\t\tReporting depth of occluder/ee: " << depth; + } #endif - if (depth > _target[2]) { + if (depth > _target[2]) { #if BOX_GRID_LOGGING - if (G.debug & G_DEBUG_FREESTYLE) { - std::cout << " is deeper than target" << std::endl; - } + if (G.debug & G_DEBUG_FREESTYLE) { + std::cout << " is deeper than target" << std::endl; + } #endif - // If the current occluder is the best occludee so far, save it. - if (! _foundOccludee || _occludeeDepth > depth) { - markCurrentOccludeeCandidate(depth); - } - } - else { + // If the current occluder is the best occludee so far, save it. + if (!_foundOccludee || _occludeeDepth > depth) { + markCurrentOccludeeCandidate(depth); + } + } + else { #if BOX_GRID_LOGGING - if (G.debug & G_DEBUG_FREESTYLE) { - std::cout << std::endl; - } + if (G.debug & G_DEBUG_FREESTYLE) { + std::cout << std::endl; + } #endif - } + } } inline void BoxGrid::Iterator::nextOccluder() { - if (_current != _cell->faces.end()) { - do { - ++_current; - } while (_current != _cell->faces.end() && ! testOccluder(false)); - } + if (_current != _cell->faces.end()) { + do { + ++_current; + } while (_current != _cell->faces.end() && !testOccluder(false)); + } } inline void BoxGrid::Iterator::nextOccludee() { - if (_current != _cell->faces.end()) { - do { - ++_current; - } while (_current != _cell->faces.end() && ! testOccluder(true)); - } + if (_current != _cell->faces.end()) { + do { + ++_current; + } while (_current != _cell->faces.end() && !testOccluder(true)); + } } inline bool BoxGrid::Iterator::validBeforeTarget() { - return _current != _cell->faces.end() && (*_current)->shallowest <= _target[2]; + return _current != _cell->faces.end() && (*_current)->shallowest <= _target[2]; } inline bool BoxGrid::Iterator::validAfterTarget() { - return _current != _cell->faces.end(); + return _current != _cell->faces.end(); } inline void BoxGrid::Iterator::markCurrentOccludeeCandidate(real depth) { #if BOX_GRID_LOGGING - if (G.debug & G_DEBUG_FREESTYLE) { - std::cout << "\t\tFound occludeeCandidate at depth " << depth << std::endl; - } + if (G.debug & G_DEBUG_FREESTYLE) { + std::cout << "\t\tFound occludeeCandidate at depth " << depth << std::endl; + } #endif - _occludeeCandidate = _current; - _occludeeDepth = depth; - _foundOccludee = true; + _occludeeCandidate = _current; + _occludeeDepth = depth; + _foundOccludee = true; } inline WFace *BoxGrid::Iterator::getWFace() const { - return (*_current)->face; + return (*_current)->face; } inline Polygon3r *BoxGrid::Iterator::getCameraSpacePolygon() { - return &((*_current)->cameraSpacePolygon); + return &((*_current)->cameraSpacePolygon); } -inline BoxGrid::OccluderData::OccluderData(OccluderSource& source, Polygon3r& p) -: poly(p), - cameraSpacePolygon(source.getCameraSpacePolygon()), - face(source.getWFace()) +inline BoxGrid::OccluderData::OccluderData(OccluderSource &source, Polygon3r &p) + : poly(p), cameraSpacePolygon(source.getCameraSpacePolygon()), face(source.getWFace()) { - // Set shallowest and deepest based on bbox - Vec3r min, max; - poly.getBBox(min, max); - shallowest = min[2]; - deepest = max[2]; + // Set shallowest and deepest based on bbox + Vec3r min, max; + poly.getBBox(min, max); + shallowest = min[2]; + deepest = max[2]; } -inline void BoxGrid::Cell::checkAndInsert(OccluderSource& source, Polygon3r& poly, OccluderData*& occluder) +inline void BoxGrid::Cell::checkAndInsert(OccluderSource &source, + Polygon3r &poly, + OccluderData *&occluder) { - if (GridHelpers::insideProscenium (boundary, poly)) { - if (occluder == NULL) { - // Disposal of occluder will be handled in BoxGrid::distributePolygons(), - // or automatically by BoxGrid::_faces; - occluder = new OccluderData(source, poly); - } - faces.push_back(occluder); - } + if (GridHelpers::insideProscenium(boundary, poly)) { + if (occluder == NULL) { + // Disposal of occluder will be handled in BoxGrid::distributePolygons(), + // or automatically by BoxGrid::_faces; + occluder = new OccluderData(source, poly); + } + faces.push_back(occluder); + } } -inline bool BoxGrid::insertOccluder(OccluderSource& source, OccluderData*& occluder) +inline bool BoxGrid::insertOccluder(OccluderSource &source, OccluderData *&occluder) { - Polygon3r& poly(source.getGridSpacePolygon()); - occluder = NULL; - - Vec3r bbMin, bbMax; - poly.getBBox(bbMin, bbMax); - // Check overlapping cells - unsigned startX, startY, endX, endY; - getCellCoordinates(bbMin, startX, startY); - getCellCoordinates(bbMax, endX, endY); - - for (unsigned int i = startX; i <= endX; ++i) { - for (unsigned int j = startY; j <= endY; ++j) { - if (_cells[i * _cellsY + j] != NULL) { - _cells[i * _cellsY + j]->checkAndInsert(source, poly, occluder); - } - } - } - - return occluder != NULL; + Polygon3r &poly(source.getGridSpacePolygon()); + occluder = NULL; + + Vec3r bbMin, bbMax; + poly.getBBox(bbMin, bbMax); + // Check overlapping cells + unsigned startX, startY, endX, endY; + getCellCoordinates(bbMin, startX, startY); + getCellCoordinates(bbMax, endX, endY); + + for (unsigned int i = startX; i <= endX; ++i) { + for (unsigned int j = startY; j <= endY; ++j) { + if (_cells[i * _cellsY + j] != NULL) { + _cells[i * _cellsY + j]->checkAndInsert(source, poly, occluder); + } + } + } + + return occluder != NULL; } } /* namespace Freestyle */ -#endif // __FREESTYLE_BOX_GRID_H__ +#endif // __FREESTYLE_BOX_GRID_H__ diff --git a/source/blender/freestyle/intern/view_map/CulledOccluderSource.cpp b/source/blender/freestyle/intern/view_map/CulledOccluderSource.cpp index 28e4b0251de..214852001b6 100644 --- a/source/blender/freestyle/intern/view_map/CulledOccluderSource.cpp +++ b/source/blender/freestyle/intern/view_map/CulledOccluderSource.cpp @@ -27,250 +27,254 @@ namespace Freestyle { -CulledOccluderSource::CulledOccluderSource(const GridHelpers::Transform& t, WingedEdge& we, ViewMap& viewMap, +CulledOccluderSource::CulledOccluderSource(const GridHelpers::Transform &t, + WingedEdge &we, + ViewMap &viewMap, bool extensiveFEdgeSearch) -: OccluderSource(t, we), rejected(0), gridSpaceOccluderProsceniumInitialized(false) + : OccluderSource(t, we), rejected(0), gridSpaceOccluderProsceniumInitialized(false) { - cullViewEdges(viewMap, extensiveFEdgeSearch); + cullViewEdges(viewMap, extensiveFEdgeSearch); - // If we have not found any visible FEdges during our cull, then there is nothing to iterate over. - // Short-circuit everything. - valid = gridSpaceOccluderProsceniumInitialized; + // If we have not found any visible FEdges during our cull, then there is nothing to iterate over. + // Short-circuit everything. + valid = gridSpaceOccluderProsceniumInitialized; - if (valid && ! testCurrent()) { - next(); - } + if (valid && !testCurrent()) { + next(); + } } -CulledOccluderSource::~CulledOccluderSource() {} +CulledOccluderSource::~CulledOccluderSource() +{ +} bool CulledOccluderSource::testCurrent() { - if (valid) { - // The test for gridSpaceOccluderProsceniumInitialized should not be necessary - return gridSpaceOccluderProsceniumInitialized && - GridHelpers::insideProscenium(gridSpaceOccluderProscenium, cachedPolygon); - } - return false; + if (valid) { + // The test for gridSpaceOccluderProsceniumInitialized should not be necessary + return gridSpaceOccluderProsceniumInitialized && + GridHelpers::insideProscenium(gridSpaceOccluderProscenium, cachedPolygon); + } + return false; } bool CulledOccluderSource::next() { - while (OccluderSource::next()) { - if (testCurrent()) { - ++rejected; - return true; - } - } - if (G.debug & G_DEBUG_FREESTYLE) { - std::cout << "Finished generating occluders. Rejected " << rejected << " faces." << std::endl; - } - return false; + while (OccluderSource::next()) { + if (testCurrent()) { + ++rejected; + return true; + } + } + if (G.debug & G_DEBUG_FREESTYLE) { + std::cout << "Finished generating occluders. Rejected " << rejected << " faces." << std::endl; + } + return false; } void CulledOccluderSource::getOccluderProscenium(real proscenium[4]) { - for (unsigned int i = 0; i < 4; ++i) { - proscenium[i] = gridSpaceOccluderProscenium[i]; - } + for (unsigned int i = 0; i < 4; ++i) { + proscenium[i] = gridSpaceOccluderProscenium[i]; + } } -static inline real distance2D(const Vec3r & point, const real origin[2]) +static inline real distance2D(const Vec3r &point, const real origin[2]) { - return ::hypot((point[0] - origin[0]), (point[1] - origin[1])); + return ::hypot((point[0] - origin[0]), (point[1] - origin[1])); } static inline bool crossesProscenium(real proscenium[4], FEdge *fe) { - Vec2r min(proscenium[0], proscenium[2]); - Vec2r max(proscenium[1], proscenium[3]); - Vec2r A(fe->vertexA()->getProjectedX(), fe->vertexA()->getProjectedY()); - Vec2r B(fe->vertexB()->getProjectedX(), fe->vertexB()->getProjectedY()); + Vec2r min(proscenium[0], proscenium[2]); + Vec2r max(proscenium[1], proscenium[3]); + Vec2r A(fe->vertexA()->getProjectedX(), fe->vertexA()->getProjectedY()); + Vec2r B(fe->vertexB()->getProjectedX(), fe->vertexB()->getProjectedY()); - return GeomUtils::intersect2dSeg2dArea (min, max, A, B); + return GeomUtils::intersect2dSeg2dArea(min, max, A, B); } -static inline bool insideProscenium(real proscenium[4], const Vec3r& point) +static inline bool insideProscenium(real proscenium[4], const Vec3r &point) { - return !(point[0] < proscenium[0] || point[0] > proscenium[1] || - point[1] < proscenium[2] || point[1] > proscenium[3]); + return !(point[0] < proscenium[0] || point[0] > proscenium[1] || point[1] < proscenium[2] || + point[1] > proscenium[3]); } -void CulledOccluderSource::cullViewEdges(ViewMap& viewMap, bool extensiveFEdgeSearch) +void CulledOccluderSource::cullViewEdges(ViewMap &viewMap, bool extensiveFEdgeSearch) { - // Cull view edges by marking them as non-displayable. - // This avoids the complications of trying to delete edges from the ViewMap. - - // Non-displayable view edges will be skipped over during visibility calculation. - - // View edges will be culled according to their position w.r.t. the viewport proscenium (viewport + 5% border, - // or some such). - - // Get proscenium boundary for culling - real viewProscenium[4]; - GridHelpers::getDefaultViewProscenium(viewProscenium); - real prosceniumOrigin[2]; - prosceniumOrigin[0] = (viewProscenium[1] - viewProscenium[0]) / 2.0; - prosceniumOrigin[1] = (viewProscenium[3] - viewProscenium[2]) / 2.0; - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Proscenium culling:" << endl; - cout << "Proscenium: [" << viewProscenium[0] << ", " << viewProscenium[1] << ", " << viewProscenium[2] << - ", " << viewProscenium[3] << "]"<< endl; - cout << "Origin: [" << prosceniumOrigin[0] << ", " << prosceniumOrigin[1] << "]"<< endl; - } - - // A separate occluder proscenium will also be maintained, starting out the same as the viewport proscenium, and - // expanding as necessary so that it encompasses the center point of at least one feature edge in each - // retained view edge. - // The occluder proscenium will be used later to cull occluding triangles before they are inserted into the Grid. - // The occluder proscenium starts out the same size as the view proscenium - GridHelpers::getDefaultViewProscenium(occluderProscenium); - - // XXX Freestyle is inconsistent in its use of ViewMap::viewedges_container and vector<ViewEdge*>::iterator. - // Probably all occurences of vector<ViewEdge*>::iterator should be replaced ViewMap::viewedges_container - // throughout the code. - // For each view edge - ViewMap::viewedges_container::iterator ve, veend; - - for (ve = viewMap.ViewEdges().begin(), veend = viewMap.ViewEdges().end(); ve != veend; ve++) { - // Overview: - // Search for a visible feature edge - // If none: mark view edge as non-displayable - // Otherwise: - // Find a feature edge with center point inside occluder proscenium. - // If none exists, find the feature edge with center point closest to viewport origin. - // Expand occluder proscenium to enclose center point. - - // For each feature edge, while bestOccluderTarget not found and view edge not visibile - bool bestOccluderTargetFound = false; - FEdge *bestOccluderTarget = NULL; - real bestOccluderDistance = 0.0; - FEdge *festart = (*ve)->fedgeA(); - FEdge *fe = festart; - // All ViewEdges start culled - (*ve)->setIsInImage(false); - - // For simple visibility calculation: mark a feature edge that is known to have a center point inside - // the occluder proscenium. Cull all other feature edges. - do { - // All FEdges start culled - fe->setIsInImage(false); - - // Look for the visible edge that can most easily be included in the occluder proscenium. - if (!bestOccluderTargetFound) { - // If center point is inside occluder proscenium, - if (insideProscenium(occluderProscenium, fe->center2d())) { - // Use this feature edge for visibility deterimination - fe->setIsInImage(true); - expandGridSpaceOccluderProscenium(fe); - // Mark bestOccluderTarget as found - bestOccluderTargetFound = true; - bestOccluderTarget = fe; - } - else { - real d = distance2D(fe->center2d(), prosceniumOrigin); - // If center point is closer to viewport origin than current target - if (bestOccluderTarget == NULL || d < bestOccluderDistance) { - // Then store as bestOccluderTarget - bestOccluderDistance = d; - bestOccluderTarget = fe; - } - } - } - - // If feature edge crosses the view proscenium - if (!(*ve)->isInImage() && crossesProscenium(viewProscenium, fe)) { - // Then the view edge will be included in the image - (*ve)->setIsInImage(true); - } - fe = fe->nextEdge(); - } while (fe != NULL && fe != festart && !(bestOccluderTargetFound && (*ve)->isInImage())); - - // Either we have run out of FEdges, or we already have the one edge we need to determine visibility - // Cull all remaining edges. - while (fe != NULL && fe != festart) { - fe->setIsInImage(false); - fe = fe->nextEdge(); - } - - // If bestOccluderTarget was not found inside the occluder proscenium, - // we need to expand the occluder proscenium to include it. - if ((*ve)->isInImage() && bestOccluderTarget != NULL && ! bestOccluderTargetFound) { - // Expand occluder proscenium to enclose bestOccluderTarget - Vec3r point = bestOccluderTarget->center2d(); - if (point[0] < occluderProscenium[0]) { - occluderProscenium[0] = point[0]; - } - else if (point[0] > occluderProscenium[1]) { - occluderProscenium[1] = point[0]; - } - if (point[1] < occluderProscenium[2]) { - occluderProscenium[2] = point[1]; - } - else if (point[1] > occluderProscenium[3]) { - occluderProscenium[3] = point[1]; - } - // Use bestOccluderTarget for visibility determination - bestOccluderTarget->setIsInImage(true); - } - } - - // We are done calculating the occluder proscenium. - // Expand the occluder proscenium by an epsilon to avoid rounding errors. - const real epsilon = 1.0e-6; - occluderProscenium[0] -= epsilon; - occluderProscenium[1] += epsilon; - occluderProscenium[2] -= epsilon; - occluderProscenium[3] += epsilon; - - // For "Normal" or "Fast" style visibility computation only: - - // For more detailed visibility calculation, make a second pass through the view map, marking all feature edges - // with center points inside the final occluder proscenium. All of these feature edges can be considered during - // visibility calculation. - - // So far we have only found one FEdge per ViewEdge. The "Normal" and "Fast" styles of visibility computation - // want to consider many FEdges for each ViewEdge. - // Here we re-scan the view map to find any usable FEdges that we skipped on the first pass, or that have become - // usable because the occluder proscenium has been expanded since the edge was visited on the first pass. - if (extensiveFEdgeSearch) { - // For each view edge, - for (ve = viewMap.ViewEdges().begin(), veend = viewMap.ViewEdges().end(); ve != veend; ve++) { - if (!(*ve)->isInImage()) { - continue; - } - // For each feature edge, - FEdge *festart = (*ve)->fedgeA(); - FEdge *fe = festart; - do { - // If not (already) visible and center point inside occluder proscenium, - if (!fe->isInImage() && insideProscenium(occluderProscenium, fe->center2d())) { - // Use the feature edge for visibility determination - fe->setIsInImage(true); - expandGridSpaceOccluderProscenium(fe); - } - fe = fe->nextEdge(); - } while (fe != NULL && fe != festart); - } - } - - // Up until now, all calculations have been done in camera space. - // However, the occluder source's iteration and the grid that consumes the occluders both work in gridspace, - // so we need a version of the occluder proscenium in gridspace. - // Set the gridspace occlude proscenium + // Cull view edges by marking them as non-displayable. + // This avoids the complications of trying to delete edges from the ViewMap. + + // Non-displayable view edges will be skipped over during visibility calculation. + + // View edges will be culled according to their position w.r.t. the viewport proscenium (viewport + 5% border, + // or some such). + + // Get proscenium boundary for culling + real viewProscenium[4]; + GridHelpers::getDefaultViewProscenium(viewProscenium); + real prosceniumOrigin[2]; + prosceniumOrigin[0] = (viewProscenium[1] - viewProscenium[0]) / 2.0; + prosceniumOrigin[1] = (viewProscenium[3] - viewProscenium[2]) / 2.0; + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Proscenium culling:" << endl; + cout << "Proscenium: [" << viewProscenium[0] << ", " << viewProscenium[1] << ", " + << viewProscenium[2] << ", " << viewProscenium[3] << "]" << endl; + cout << "Origin: [" << prosceniumOrigin[0] << ", " << prosceniumOrigin[1] << "]" << endl; + } + + // A separate occluder proscenium will also be maintained, starting out the same as the viewport proscenium, and + // expanding as necessary so that it encompasses the center point of at least one feature edge in each + // retained view edge. + // The occluder proscenium will be used later to cull occluding triangles before they are inserted into the Grid. + // The occluder proscenium starts out the same size as the view proscenium + GridHelpers::getDefaultViewProscenium(occluderProscenium); + + // XXX Freestyle is inconsistent in its use of ViewMap::viewedges_container and vector<ViewEdge*>::iterator. + // Probably all occurences of vector<ViewEdge*>::iterator should be replaced ViewMap::viewedges_container + // throughout the code. + // For each view edge + ViewMap::viewedges_container::iterator ve, veend; + + for (ve = viewMap.ViewEdges().begin(), veend = viewMap.ViewEdges().end(); ve != veend; ve++) { + // Overview: + // Search for a visible feature edge + // If none: mark view edge as non-displayable + // Otherwise: + // Find a feature edge with center point inside occluder proscenium. + // If none exists, find the feature edge with center point closest to viewport origin. + // Expand occluder proscenium to enclose center point. + + // For each feature edge, while bestOccluderTarget not found and view edge not visibile + bool bestOccluderTargetFound = false; + FEdge *bestOccluderTarget = NULL; + real bestOccluderDistance = 0.0; + FEdge *festart = (*ve)->fedgeA(); + FEdge *fe = festart; + // All ViewEdges start culled + (*ve)->setIsInImage(false); + + // For simple visibility calculation: mark a feature edge that is known to have a center point inside + // the occluder proscenium. Cull all other feature edges. + do { + // All FEdges start culled + fe->setIsInImage(false); + + // Look for the visible edge that can most easily be included in the occluder proscenium. + if (!bestOccluderTargetFound) { + // If center point is inside occluder proscenium, + if (insideProscenium(occluderProscenium, fe->center2d())) { + // Use this feature edge for visibility deterimination + fe->setIsInImage(true); + expandGridSpaceOccluderProscenium(fe); + // Mark bestOccluderTarget as found + bestOccluderTargetFound = true; + bestOccluderTarget = fe; + } + else { + real d = distance2D(fe->center2d(), prosceniumOrigin); + // If center point is closer to viewport origin than current target + if (bestOccluderTarget == NULL || d < bestOccluderDistance) { + // Then store as bestOccluderTarget + bestOccluderDistance = d; + bestOccluderTarget = fe; + } + } + } + + // If feature edge crosses the view proscenium + if (!(*ve)->isInImage() && crossesProscenium(viewProscenium, fe)) { + // Then the view edge will be included in the image + (*ve)->setIsInImage(true); + } + fe = fe->nextEdge(); + } while (fe != NULL && fe != festart && !(bestOccluderTargetFound && (*ve)->isInImage())); + + // Either we have run out of FEdges, or we already have the one edge we need to determine visibility + // Cull all remaining edges. + while (fe != NULL && fe != festart) { + fe->setIsInImage(false); + fe = fe->nextEdge(); + } + + // If bestOccluderTarget was not found inside the occluder proscenium, + // we need to expand the occluder proscenium to include it. + if ((*ve)->isInImage() && bestOccluderTarget != NULL && !bestOccluderTargetFound) { + // Expand occluder proscenium to enclose bestOccluderTarget + Vec3r point = bestOccluderTarget->center2d(); + if (point[0] < occluderProscenium[0]) { + occluderProscenium[0] = point[0]; + } + else if (point[0] > occluderProscenium[1]) { + occluderProscenium[1] = point[0]; + } + if (point[1] < occluderProscenium[2]) { + occluderProscenium[2] = point[1]; + } + else if (point[1] > occluderProscenium[3]) { + occluderProscenium[3] = point[1]; + } + // Use bestOccluderTarget for visibility determination + bestOccluderTarget->setIsInImage(true); + } + } + + // We are done calculating the occluder proscenium. + // Expand the occluder proscenium by an epsilon to avoid rounding errors. + const real epsilon = 1.0e-6; + occluderProscenium[0] -= epsilon; + occluderProscenium[1] += epsilon; + occluderProscenium[2] -= epsilon; + occluderProscenium[3] += epsilon; + + // For "Normal" or "Fast" style visibility computation only: + + // For more detailed visibility calculation, make a second pass through the view map, marking all feature edges + // with center points inside the final occluder proscenium. All of these feature edges can be considered during + // visibility calculation. + + // So far we have only found one FEdge per ViewEdge. The "Normal" and "Fast" styles of visibility computation + // want to consider many FEdges for each ViewEdge. + // Here we re-scan the view map to find any usable FEdges that we skipped on the first pass, or that have become + // usable because the occluder proscenium has been expanded since the edge was visited on the first pass. + if (extensiveFEdgeSearch) { + // For each view edge, + for (ve = viewMap.ViewEdges().begin(), veend = viewMap.ViewEdges().end(); ve != veend; ve++) { + if (!(*ve)->isInImage()) { + continue; + } + // For each feature edge, + FEdge *festart = (*ve)->fedgeA(); + FEdge *fe = festart; + do { + // If not (already) visible and center point inside occluder proscenium, + if (!fe->isInImage() && insideProscenium(occluderProscenium, fe->center2d())) { + // Use the feature edge for visibility determination + fe->setIsInImage(true); + expandGridSpaceOccluderProscenium(fe); + } + fe = fe->nextEdge(); + } while (fe != NULL && fe != festart); + } + } + + // Up until now, all calculations have been done in camera space. + // However, the occluder source's iteration and the grid that consumes the occluders both work in gridspace, + // so we need a version of the occluder proscenium in gridspace. + // Set the gridspace occlude proscenium } void CulledOccluderSource::expandGridSpaceOccluderProscenium(FEdge *fe) { - if (gridSpaceOccluderProsceniumInitialized) { - GridHelpers::expandProscenium(gridSpaceOccluderProscenium, transform(fe->center3d())); - } - else { - const Vec3r& point = transform(fe->center3d()); - gridSpaceOccluderProscenium[0] = gridSpaceOccluderProscenium[1] = point[0]; - gridSpaceOccluderProscenium[2] = gridSpaceOccluderProscenium[3] = point[1]; - gridSpaceOccluderProsceniumInitialized = true; - } + if (gridSpaceOccluderProsceniumInitialized) { + GridHelpers::expandProscenium(gridSpaceOccluderProscenium, transform(fe->center3d())); + } + else { + const Vec3r &point = transform(fe->center3d()); + gridSpaceOccluderProscenium[0] = gridSpaceOccluderProscenium[1] = point[0]; + gridSpaceOccluderProscenium[2] = gridSpaceOccluderProscenium[3] = point[1]; + gridSpaceOccluderProsceniumInitialized = true; + } } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/view_map/CulledOccluderSource.h b/source/blender/freestyle/intern/view_map/CulledOccluderSource.h index de782eda64c..3457fb6ca10 100644 --- a/source/blender/freestyle/intern/view_map/CulledOccluderSource.h +++ b/source/blender/freestyle/intern/view_map/CulledOccluderSource.h @@ -27,34 +27,35 @@ namespace Freestyle { -class CulledOccluderSource : public OccluderSource -{ - // Disallow copying and assignment - CulledOccluderSource(const CulledOccluderSource& other); - CulledOccluderSource& operator=(const CulledOccluderSource& other); +class CulledOccluderSource : public OccluderSource { + // Disallow copying and assignment + CulledOccluderSource(const CulledOccluderSource &other); + CulledOccluderSource &operator=(const CulledOccluderSource &other); -public: - CulledOccluderSource(const GridHelpers::Transform& transform, WingedEdge& we, ViewMap& viewMap, - bool extensiveFEdgeSearch = true); - virtual ~CulledOccluderSource(); + public: + CulledOccluderSource(const GridHelpers::Transform &transform, + WingedEdge &we, + ViewMap &viewMap, + bool extensiveFEdgeSearch = true); + virtual ~CulledOccluderSource(); - void cullViewEdges(ViewMap& viewMap, bool extensiveFEdgeSearch); + void cullViewEdges(ViewMap &viewMap, bool extensiveFEdgeSearch); - bool next(); + bool next(); - void getOccluderProscenium(real proscenium[4]); + void getOccluderProscenium(real proscenium[4]); -private: - bool testCurrent(); - void expandGridSpaceOccluderProscenium(FEdge *fe); + private: + bool testCurrent(); + void expandGridSpaceOccluderProscenium(FEdge *fe); - real occluderProscenium[4]; - real gridSpaceOccluderProscenium[4]; + real occluderProscenium[4]; + real gridSpaceOccluderProscenium[4]; - unsigned long rejected; - bool gridSpaceOccluderProsceniumInitialized; + unsigned long rejected; + bool gridSpaceOccluderProsceniumInitialized; }; } /* namespace Freestyle */ -#endif // __FREESTYLE_CULLED_OCCLUDER_SOURCE_H__ +#endif // __FREESTYLE_CULLED_OCCLUDER_SOURCE_H__ diff --git a/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp b/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp index a195db76fe7..bb2b95be84e 100644 --- a/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp +++ b/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp @@ -30,511 +30,512 @@ namespace Freestyle { -void FEdgeXDetector::processShapes(WingedEdge& we) +void FEdgeXDetector::processShapes(WingedEdge &we) { - bool progressBarDisplay = false; + bool progressBarDisplay = false; #if 0 - Vec3r Min, Max; + Vec3r Min, Max; #endif - vector<WShape*> wshapes = we.getWShapes(); - WXShape *wxs; - - if (_pProgressBar != NULL) { - _pProgressBar->reset(); - _pProgressBar->setLabelText("Detecting feature lines"); - _pProgressBar->setTotalSteps(wshapes.size() * 3); - _pProgressBar->setProgress(0); - progressBarDisplay = true; - } - - for (vector<WShape*>::const_iterator it = wshapes.begin(); it != wshapes.end(); it++) { - if (_pRenderMonitor && _pRenderMonitor->testBreak()) - break; - wxs = dynamic_cast<WXShape*>(*it); + vector<WShape *> wshapes = we.getWShapes(); + WXShape *wxs; + + if (_pProgressBar != NULL) { + _pProgressBar->reset(); + _pProgressBar->setLabelText("Detecting feature lines"); + _pProgressBar->setTotalSteps(wshapes.size() * 3); + _pProgressBar->setProgress(0); + progressBarDisplay = true; + } + + for (vector<WShape *>::const_iterator it = wshapes.begin(); it != wshapes.end(); it++) { + if (_pRenderMonitor && _pRenderMonitor->testBreak()) + break; + wxs = dynamic_cast<WXShape *>(*it); #if 0 - wxs->bbox(Min, Max); - _bbox_diagonal = (Max - Min).norm(); + wxs->bbox(Min, Max); + _bbox_diagonal = (Max - Min).norm(); #endif - if (_changes) { - vector<WFace*>& wfaces = wxs->GetFaceList(); - for (vector<WFace*>::iterator wf = wfaces.begin(), wfend = wfaces.end(); wf != wfend; ++wf) { - WXFace *wxf = dynamic_cast<WXFace*>(*wf); - wxf->Clear(); - } - _computeViewIndependent = true; - } - else if (!(wxs)->getComputeViewIndependentFlag()) { - wxs->Reset(); - _computeViewIndependent = false; - } - else { - _computeViewIndependent = true; - } - preProcessShape(wxs); - if (progressBarDisplay) - _pProgressBar->setProgress(_pProgressBar->getProgress() + 1); - processBorderShape(wxs); - if (_computeMaterialBoundaries) - processMaterialBoundaryShape(wxs); - processCreaseShape(wxs); - if (_computeRidgesAndValleys) - processRidgesAndValleysShape(wxs); - if (_computeSuggestiveContours) - processSuggestiveContourShape(wxs); - processSilhouetteShape(wxs); - processEdgeMarksShape(wxs); - if (progressBarDisplay) - _pProgressBar->setProgress(_pProgressBar->getProgress() + 1); - - // build smooth edges: - buildSmoothEdges(wxs); - - // Post processing for suggestive contours - if (_computeSuggestiveContours) - postProcessSuggestiveContourShape(wxs); - if (progressBarDisplay) - _pProgressBar->setProgress(_pProgressBar->getProgress() + 1); - - wxs->setComputeViewIndependentFlag(false); - _computeViewIndependent = false; - _changes = false; - - // reset user data - (*it)->ResetUserData(); - } + if (_changes) { + vector<WFace *> &wfaces = wxs->GetFaceList(); + for (vector<WFace *>::iterator wf = wfaces.begin(), wfend = wfaces.end(); wf != wfend; + ++wf) { + WXFace *wxf = dynamic_cast<WXFace *>(*wf); + wxf->Clear(); + } + _computeViewIndependent = true; + } + else if (!(wxs)->getComputeViewIndependentFlag()) { + wxs->Reset(); + _computeViewIndependent = false; + } + else { + _computeViewIndependent = true; + } + preProcessShape(wxs); + if (progressBarDisplay) + _pProgressBar->setProgress(_pProgressBar->getProgress() + 1); + processBorderShape(wxs); + if (_computeMaterialBoundaries) + processMaterialBoundaryShape(wxs); + processCreaseShape(wxs); + if (_computeRidgesAndValleys) + processRidgesAndValleysShape(wxs); + if (_computeSuggestiveContours) + processSuggestiveContourShape(wxs); + processSilhouetteShape(wxs); + processEdgeMarksShape(wxs); + if (progressBarDisplay) + _pProgressBar->setProgress(_pProgressBar->getProgress() + 1); + + // build smooth edges: + buildSmoothEdges(wxs); + + // Post processing for suggestive contours + if (_computeSuggestiveContours) + postProcessSuggestiveContourShape(wxs); + if (progressBarDisplay) + _pProgressBar->setProgress(_pProgressBar->getProgress() + 1); + + wxs->setComputeViewIndependentFlag(false); + _computeViewIndependent = false; + _changes = false; + + // reset user data + (*it)->ResetUserData(); + } } // GENERAL STUFF //////////////// void FEdgeXDetector::preProcessShape(WXShape *iWShape) { - _meanK1 = 0; - _meanKr = 0; - _minK1 = FLT_MAX; - _maxK1 = -FLT_MAX; - _minKr = FLT_MAX; - _maxKr = -FLT_MAX; - _nPoints = 0; + _meanK1 = 0; + _meanKr = 0; + _minK1 = FLT_MAX; + _maxK1 = -FLT_MAX; + _minKr = FLT_MAX; + _maxKr = -FLT_MAX; + _nPoints = 0; #if 0 - _meanEdgeSize = iWShape->getMeanEdgeSize(); + _meanEdgeSize = iWShape->getMeanEdgeSize(); #else - _meanEdgeSize = iWShape->ComputeMeanEdgeSize(); + _meanEdgeSize = iWShape->ComputeMeanEdgeSize(); #endif - vector<WFace*>& wfaces = iWShape->GetFaceList(); - vector<WFace*>::iterator f, fend; - // view dependant stuff - for (f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) { - preProcessFace((WXFace *)(*f)); - } - - if (_computeRidgesAndValleys || _computeSuggestiveContours) { - vector<WVertex*>& wvertices = iWShape->getVertexList(); - for (vector<WVertex*>::iterator wv = wvertices.begin(), wvend = wvertices.end(); wv != wvend; ++wv) { - // Compute curvatures - WXVertex *wxv = dynamic_cast<WXVertex*>(*wv); - computeCurvatures(wxv); - } - _meanK1 /= (real)(_nPoints); - _meanKr /= (real)(_nPoints); - } + vector<WFace *> &wfaces = iWShape->GetFaceList(); + vector<WFace *>::iterator f, fend; + // view dependant stuff + for (f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) { + preProcessFace((WXFace *)(*f)); + } + + if (_computeRidgesAndValleys || _computeSuggestiveContours) { + vector<WVertex *> &wvertices = iWShape->getVertexList(); + for (vector<WVertex *>::iterator wv = wvertices.begin(), wvend = wvertices.end(); wv != wvend; + ++wv) { + // Compute curvatures + WXVertex *wxv = dynamic_cast<WXVertex *>(*wv); + computeCurvatures(wxv); + } + _meanK1 /= (real)(_nPoints); + _meanKr /= (real)(_nPoints); + } } void FEdgeXDetector::preProcessFace(WXFace *iFace) { - Vec3f firstPoint = iFace->GetVertex(0)->GetVertex(); - Vec3f N = iFace->GetNormal(); - - // Compute the dot product between V (=_Viewpoint - firstPoint) and N: - Vec3f V; - if (_orthographicProjection) { - V = Vec3f(0.0f, 0.0f, _Viewpoint.z() - firstPoint.z()); - } - else { - V = Vec3f(_Viewpoint - firstPoint); - } - N.normalize(); - V.normalize(); - iFace->setDotP(N * V); - - // compute the distance between the face center and the viewpoint: - if (_orthographicProjection) { - iFace->setZ(iFace->center().z() - _Viewpoint.z()); - } - else { - Vec3f dist_vec(iFace->center() - _Viewpoint); - iFace->setZ(dist_vec.norm()); - } + Vec3f firstPoint = iFace->GetVertex(0)->GetVertex(); + Vec3f N = iFace->GetNormal(); + + // Compute the dot product between V (=_Viewpoint - firstPoint) and N: + Vec3f V; + if (_orthographicProjection) { + V = Vec3f(0.0f, 0.0f, _Viewpoint.z() - firstPoint.z()); + } + else { + V = Vec3f(_Viewpoint - firstPoint); + } + N.normalize(); + V.normalize(); + iFace->setDotP(N * V); + + // compute the distance between the face center and the viewpoint: + if (_orthographicProjection) { + iFace->setZ(iFace->center().z() - _Viewpoint.z()); + } + else { + Vec3f dist_vec(iFace->center() - _Viewpoint); + iFace->setZ(dist_vec.norm()); + } } void FEdgeXDetector::computeCurvatures(WXVertex *vertex) { - // TODO: for some reason, the 'vertex' may have no associated edges - // (i.e., WVertex::_EdgeList is empty), which causes a crash due to - // a subsequent call of WVertex::_EdgeList.front(). - if (vertex->GetEdges().empty()) { - if (G.debug & G_DEBUG_FREESTYLE) { - printf("Warning: WVertex %d has no associated edges.\n", vertex->GetId()); - } - return; - } - - // CURVATURE LAYER - // store all the curvature datas for each vertex - - //soc unused - real K1, K2 - real cos2theta, sin2theta; - Vec3r e1, n, v; - // one vertex curvature info : - CurvatureInfo *C; - float radius = _sphereRadius * _meanEdgeSize; - - // view independent stuff - if (_computeViewIndependent) { - C = new CurvatureInfo(); - vertex->setCurvatures(C); - OGF::NormalCycle ncycle; - ncycle.begin(); - if (radius > 0) { - OGF::compute_curvature_tensor(vertex, radius, ncycle); - } - else { - OGF::compute_curvature_tensor_one_ring(vertex, ncycle); - } - ncycle.end(); - C->K1 = ncycle.kmin(); - C->K2 = ncycle.kmax(); - C->e1 = ncycle.Kmax(); //ncycle.kmin() * ncycle.Kmax(); - C->e2 = ncycle.Kmin(); //ncycle.kmax() * ncycle.Kmin(); - - real absK1 = fabs(C->K1); - _meanK1 += absK1; - if (absK1 > _maxK1) - _maxK1 = absK1; - if (absK1 < _minK1) - _minK1 = absK1; - } - // view dependant - C = vertex->curvatures(); - if (C == 0) - return; - - // compute radial curvature : - n = C->e1 ^ C->e2; - if (_orthographicProjection) { - v = Vec3r(0.0, 0.0, _Viewpoint.z() - vertex->GetVertex().z()); - } - else { - v = Vec3r(_Viewpoint - vertex->GetVertex()); - } - C->er = v - (v * n) * n; - C->er.normalize(); - e1 = C->e1; - e1.normalize(); - cos2theta = C->er * e1; - cos2theta *= cos2theta; - sin2theta = 1 - cos2theta; - C->Kr = C->K1 * cos2theta + C->K2 * sin2theta; - real absKr = fabs(C->Kr); - _meanKr += absKr; - if (absKr > _maxKr) - _maxKr = absKr; - if (absKr < _minKr) - _minKr = absKr; - - ++_nPoints; + // TODO: for some reason, the 'vertex' may have no associated edges + // (i.e., WVertex::_EdgeList is empty), which causes a crash due to + // a subsequent call of WVertex::_EdgeList.front(). + if (vertex->GetEdges().empty()) { + if (G.debug & G_DEBUG_FREESTYLE) { + printf("Warning: WVertex %d has no associated edges.\n", vertex->GetId()); + } + return; + } + + // CURVATURE LAYER + // store all the curvature datas for each vertex + + //soc unused - real K1, K2 + real cos2theta, sin2theta; + Vec3r e1, n, v; + // one vertex curvature info : + CurvatureInfo *C; + float radius = _sphereRadius * _meanEdgeSize; + + // view independent stuff + if (_computeViewIndependent) { + C = new CurvatureInfo(); + vertex->setCurvatures(C); + OGF::NormalCycle ncycle; + ncycle.begin(); + if (radius > 0) { + OGF::compute_curvature_tensor(vertex, radius, ncycle); + } + else { + OGF::compute_curvature_tensor_one_ring(vertex, ncycle); + } + ncycle.end(); + C->K1 = ncycle.kmin(); + C->K2 = ncycle.kmax(); + C->e1 = ncycle.Kmax(); //ncycle.kmin() * ncycle.Kmax(); + C->e2 = ncycle.Kmin(); //ncycle.kmax() * ncycle.Kmin(); + + real absK1 = fabs(C->K1); + _meanK1 += absK1; + if (absK1 > _maxK1) + _maxK1 = absK1; + if (absK1 < _minK1) + _minK1 = absK1; + } + // view dependant + C = vertex->curvatures(); + if (C == 0) + return; + + // compute radial curvature : + n = C->e1 ^ C->e2; + if (_orthographicProjection) { + v = Vec3r(0.0, 0.0, _Viewpoint.z() - vertex->GetVertex().z()); + } + else { + v = Vec3r(_Viewpoint - vertex->GetVertex()); + } + C->er = v - (v * n) * n; + C->er.normalize(); + e1 = C->e1; + e1.normalize(); + cos2theta = C->er * e1; + cos2theta *= cos2theta; + sin2theta = 1 - cos2theta; + C->Kr = C->K1 * cos2theta + C->K2 * sin2theta; + real absKr = fabs(C->Kr); + _meanKr += absKr; + if (absKr > _maxKr) + _maxKr = absKr; + if (absKr < _minKr) + _minKr = absKr; + + ++_nPoints; } // SILHOUETTE ///////////// void FEdgeXDetector::processSilhouetteShape(WXShape *iWShape) { - // Make a first pass on every polygons in order to compute all their silhouette relative values: - vector<WFace*>& wfaces = iWShape->GetFaceList(); - vector<WFace*>::iterator f, fend; - for (f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) { - ProcessSilhouetteFace((WXFace *)(*f)); - } - - // Make a pass on the edges to detect the silhouette edges that are not smooth - vector<WEdge*>::iterator we, weend; - vector<WEdge*> &wedges = iWShape->getEdgeList(); - for (we = wedges.begin(), weend = wedges.end(); we != weend; ++we) { - ProcessSilhouetteEdge((WXEdge *)(*we)); - } + // Make a first pass on every polygons in order to compute all their silhouette relative values: + vector<WFace *> &wfaces = iWShape->GetFaceList(); + vector<WFace *>::iterator f, fend; + for (f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) { + ProcessSilhouetteFace((WXFace *)(*f)); + } + + // Make a pass on the edges to detect the silhouette edges that are not smooth + vector<WEdge *>::iterator we, weend; + vector<WEdge *> &wedges = iWShape->getEdgeList(); + for (we = wedges.begin(), weend = wedges.end(); we != weend; ++we) { + ProcessSilhouetteEdge((WXEdge *)(*we)); + } } void FEdgeXDetector::ProcessSilhouetteFace(WXFace *iFace) { - // SILHOUETTE LAYER - Vec3f normal; - // Compute the dot products between View direction and N at each vertex of the face: - Vec3f point; - int closestPointId = 0; - float dist, minDist = FLT_MAX; - int numVertices = iFace->numberOfVertices(); - WXFaceLayer *faceLayer = new WXFaceLayer(iFace, Nature::SILHOUETTE, true); - for (int i = 0; i < numVertices; i++) { - point = iFace->GetVertex(i)->GetVertex(); - normal = iFace->GetVertexNormal(i); - normal.normalize(); - Vec3f V; - if (_orthographicProjection) { - V = Vec3f(0.0f, 0.0f, _Viewpoint.z() - point.z()); - } - else { - V = Vec3f(_Viewpoint - point); - } - V.normalize(); - float d = normal * V; - faceLayer->PushDotP(d); - // Find the point the closest to the viewpoint - if (_orthographicProjection) { - dist = point.z() - _Viewpoint.z(); - } - else { - Vec3f dist_vec(point - _Viewpoint); - dist = dist_vec.norm(); - } - if (dist < minDist) { - minDist = dist; - closestPointId = i; - } - } - // Set the closest point id: - faceLayer->setClosestPointIndex(closestPointId); - // Add this layer to the face: - iFace->AddSmoothLayer(faceLayer); + // SILHOUETTE LAYER + Vec3f normal; + // Compute the dot products between View direction and N at each vertex of the face: + Vec3f point; + int closestPointId = 0; + float dist, minDist = FLT_MAX; + int numVertices = iFace->numberOfVertices(); + WXFaceLayer *faceLayer = new WXFaceLayer(iFace, Nature::SILHOUETTE, true); + for (int i = 0; i < numVertices; i++) { + point = iFace->GetVertex(i)->GetVertex(); + normal = iFace->GetVertexNormal(i); + normal.normalize(); + Vec3f V; + if (_orthographicProjection) { + V = Vec3f(0.0f, 0.0f, _Viewpoint.z() - point.z()); + } + else { + V = Vec3f(_Viewpoint - point); + } + V.normalize(); + float d = normal * V; + faceLayer->PushDotP(d); + // Find the point the closest to the viewpoint + if (_orthographicProjection) { + dist = point.z() - _Viewpoint.z(); + } + else { + Vec3f dist_vec(point - _Viewpoint); + dist = dist_vec.norm(); + } + if (dist < minDist) { + minDist = dist; + closestPointId = i; + } + } + // Set the closest point id: + faceLayer->setClosestPointIndex(closestPointId); + // Add this layer to the face: + iFace->AddSmoothLayer(faceLayer); } void FEdgeXDetector::ProcessSilhouetteEdge(WXEdge *iEdge) { - if (iEdge->nature() & Nature::BORDER) - return; - // SILHOUETTE ? - //------------- - WXFace *fA = (WXFace *)iEdge->GetaOEdge()->GetaFace(); - WXFace *fB = (WXFace *)iEdge->GetaOEdge()->GetbFace(); - - if ((fA->front()) ^ (fB->front())) { // fA->visible XOR fB->visible (true if one is 0 and the other is 1) - // The only edges we want to set as silhouette edges in this way are the ones with 2 different normals - // for 1 vertex for these two faces - //-------------------- - // In reality we only test the normals for 1 of the 2 vertices. - if (fA->GetVertexNormal(iEdge->GetaVertex()) == fB->GetVertexNormal(iEdge->GetaVertex())) - return; - iEdge->AddNature(Nature::SILHOUETTE); - if (fB->front()) - iEdge->setOrder(1); - else - iEdge->setOrder(-1); - } + if (iEdge->nature() & Nature::BORDER) + return; + // SILHOUETTE ? + //------------- + WXFace *fA = (WXFace *)iEdge->GetaOEdge()->GetaFace(); + WXFace *fB = (WXFace *)iEdge->GetaOEdge()->GetbFace(); + + if ((fA->front()) ^ + (fB->front())) { // fA->visible XOR fB->visible (true if one is 0 and the other is 1) + // The only edges we want to set as silhouette edges in this way are the ones with 2 different normals + // for 1 vertex for these two faces + //-------------------- + // In reality we only test the normals for 1 of the 2 vertices. + if (fA->GetVertexNormal(iEdge->GetaVertex()) == fB->GetVertexNormal(iEdge->GetaVertex())) + return; + iEdge->AddNature(Nature::SILHOUETTE); + if (fB->front()) + iEdge->setOrder(1); + else + iEdge->setOrder(-1); + } } // BORDER ///////// void FEdgeXDetector::processBorderShape(WXShape *iWShape) { - if (!_computeViewIndependent) - return; - // Make a pass on the edges to detect the BORDER - vector<WEdge*>::iterator we, weend; - vector<WEdge*> &wedges = iWShape->getEdgeList(); - for (we = wedges.begin(), weend = wedges.end(); we != weend; ++we) { - ProcessBorderEdge((WXEdge *)(*we)); - } + if (!_computeViewIndependent) + return; + // Make a pass on the edges to detect the BORDER + vector<WEdge *>::iterator we, weend; + vector<WEdge *> &wedges = iWShape->getEdgeList(); + for (we = wedges.begin(), weend = wedges.end(); we != weend; ++we) { + ProcessBorderEdge((WXEdge *)(*we)); + } } void FEdgeXDetector::ProcessBorderEdge(WXEdge *iEdge) { - // first check whether it is a border edge: BORDER ? - //--------- - if (iEdge->GetaFace() == 0) { - // it is a border edge - iEdge->AddNature(Nature::BORDER); - } + // first check whether it is a border edge: BORDER ? + //--------- + if (iEdge->GetaFace() == 0) { + // it is a border edge + iEdge->AddNature(Nature::BORDER); + } } - // CREASE ///////// void FEdgeXDetector::processCreaseShape(WXShape *iWShape) { - if (!_computeViewIndependent) - return; - - // Make a pass on the edges to detect the CREASE - vector<WEdge*>::iterator we, weend; - vector<WEdge*> &wedges = iWShape->getEdgeList(); - for (we = wedges.begin(), weend = wedges.end(); we != weend; ++we) { - ProcessCreaseEdge((WXEdge *)(*we)); - } + if (!_computeViewIndependent) + return; + + // Make a pass on the edges to detect the CREASE + vector<WEdge *>::iterator we, weend; + vector<WEdge *> &wedges = iWShape->getEdgeList(); + for (we = wedges.begin(), weend = wedges.end(); we != weend; ++we) { + ProcessCreaseEdge((WXEdge *)(*we)); + } } void FEdgeXDetector::ProcessCreaseEdge(WXEdge *iEdge) { - // CREASE ? - //--------- - if (iEdge->nature() & Nature::BORDER) - return; - WXFace *fA = (WXFace *)iEdge->GetaOEdge()->GetaFace(); - WXFace *fB = (WXFace *)iEdge->GetaOEdge()->GetbFace(); - - WVertex *aVertex = iEdge->GetaVertex(); - if ((fA->GetVertexNormal(aVertex) * fB->GetVertexNormal(aVertex)) <= _creaseAngle) - iEdge->AddNature(Nature::CREASE); + // CREASE ? + //--------- + if (iEdge->nature() & Nature::BORDER) + return; + WXFace *fA = (WXFace *)iEdge->GetaOEdge()->GetaFace(); + WXFace *fB = (WXFace *)iEdge->GetaOEdge()->GetbFace(); + + WVertex *aVertex = iEdge->GetaVertex(); + if ((fA->GetVertexNormal(aVertex) * fB->GetVertexNormal(aVertex)) <= _creaseAngle) + iEdge->AddNature(Nature::CREASE); } // RIDGES AND VALLEYS ///////////////////// void FEdgeXDetector::processRidgesAndValleysShape(WXShape *iWShape) { - // Don't forget to add the built layer to the face at the end of the ProcessFace: - //iFace->AddSmoothLayer(faceLayer); - - if (!_computeViewIndependent) - return; - - // Here the curvatures must already have been computed - vector<WFace*>& wfaces = iWShape->GetFaceList(); - vector<WFace*>::iterator f, fend; - for (f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) { - ProcessRidgeFace((WXFace *)(*f)); - } + // Don't forget to add the built layer to the face at the end of the ProcessFace: + //iFace->AddSmoothLayer(faceLayer); + + if (!_computeViewIndependent) + return; + + // Here the curvatures must already have been computed + vector<WFace *> &wfaces = iWShape->GetFaceList(); + vector<WFace *>::iterator f, fend; + for (f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) { + ProcessRidgeFace((WXFace *)(*f)); + } } - // RIDGES ///////// void FEdgeXDetector::ProcessRidgeFace(WXFace *iFace) { - WXFaceLayer *flayer = new WXFaceLayer(iFace, Nature::RIDGE | Nature::VALLEY, false); - iFace->AddSmoothLayer(flayer); - - unsigned int numVertices = iFace->numberOfVertices(); - for (unsigned int i = 0; i < numVertices; ++i) { - WVertex *wv = iFace->GetVertex(i); - WXVertex *wxv = dynamic_cast<WXVertex*>(wv); - flayer->PushDotP(wxv->curvatures()->K1); - } - -#if 0 // XXX fabs(flayer->dotP(i)) < threshold cannot be true - real threshold = 0; - //real threshold = _maxK1 - (_maxK1 - _meanK1) / 20.0; - - if (flayer->nPosDotP() != numVertices) { - if ((fabs(flayer->dotP(0)) < threshold) && (fabs(flayer->dotP(1)) < threshold) && - (fabs(flayer->dotP(2)) < threshold)) - { - flayer->ReplaceDotP(0, 0); - flayer->ReplaceDotP(1, 0); - flayer->ReplaceDotP(2, 0); - } - } + WXFaceLayer *flayer = new WXFaceLayer(iFace, Nature::RIDGE | Nature::VALLEY, false); + iFace->AddSmoothLayer(flayer); + + unsigned int numVertices = iFace->numberOfVertices(); + for (unsigned int i = 0; i < numVertices; ++i) { + WVertex *wv = iFace->GetVertex(i); + WXVertex *wxv = dynamic_cast<WXVertex *>(wv); + flayer->PushDotP(wxv->curvatures()->K1); + } + +#if 0 // XXX fabs(flayer->dotP(i)) < threshold cannot be true + real threshold = 0; + //real threshold = _maxK1 - (_maxK1 - _meanK1) / 20.0; + + if (flayer->nPosDotP() != numVertices) { + if ((fabs(flayer->dotP(0)) < threshold) && (fabs(flayer->dotP(1)) < threshold) && + (fabs(flayer->dotP(2)) < threshold)) + { + flayer->ReplaceDotP(0, 0); + flayer->ReplaceDotP(1, 0); + flayer->ReplaceDotP(2, 0); + } + } #endif } #if 0 void FEdgeXDetector::ProcessRidgeFace(WXFace *iFace) { - // RIDGE LAYER - // Compute the RidgeFunction, that is the derivative of the ppal curvature along e1 at each vertex of the face - WVertex *v; - Vec3r v1v2; - real t; - vector<WXFaceLayer*> SmoothLayers; - WXFaceLayer *faceLayer; - Face_Curvature_Info *layer_info; - real K1_a(0), K1_b(0); - Vec3r Inter_a, Inter_b; - - // find the ridge layer of the face - iFace->retrieveSmoothLayers(Nature::RIDGE, SmoothLayers); - if ( SmoothLayers.size()!=1 ) - return; - faceLayer = SmoothLayers[0]; - // retrieve the curvature info of this layer - layer_info = (Face_Curvature_Info *)faceLayer->userdata; - - int numVertices = iFace->numberOfVertices(); - for (int i = 0; i < numVertices; i++) { - v = iFace->GetVertex(i); - // vec_curvature_info[i] contains the curvature info of this vertex - Vec3r e2 = layer_info->vec_curvature_info[i]->K2*layer_info->vec_curvature_info[i]->e2; - Vec3r e1 = layer_info->vec_curvature_info[i]->K1*layer_info->vec_curvature_info[i]->e1; - e2.normalize(); - - WVertex::face_iterator fit = v->faces_begin(); - WVertex::face_iterator fitend = v->faces_end(); - for (; fit != fitend; ++fit) { - WXFace *wxf = dynamic_cast<WXFace*>(*fit); - WOEdge *oppositeEdge; - if (!(wxf->getOppositeEdge(v, oppositeEdge))) - continue; - v1v2 = oppositeEdge->GetbVertex()->GetVertex() - oppositeEdge->GetaVertex()->GetVertex(); - GeomUtils::intersection_test res; - res = GeomUtils::intersectRayPlane(oppositeEdge->GetaVertex()->GetVertex(), v1v2, e2, -(v->GetVertex()*e2), - t, 1.0e-06); - if ((res == GeomUtils::DO_INTERSECT) && (t >= 0.0) && (t <= 1.0)) { - vector<WXFaceLayer*> second_ridge_layer; - wxf->retrieveSmoothLayers(Nature::RIDGE, second_ridge_layer); - if (second_ridge_layer.size() != 1) - continue; - Face_Curvature_Info *second_layer_info = (Face_Curvature_Info*)second_ridge_layer[0]->userdata; - - unsigned index1 = wxf->GetIndex(oppositeEdge->GetaVertex()); - unsigned index2 = wxf->GetIndex(oppositeEdge->GetbVertex()); - real K1_1 = second_layer_info->vec_curvature_info[index1]->K1; - real K1_2 = second_layer_info->vec_curvature_info[index2]->K1; - real K1 = (1.0 - t) * K1_1 + t * K1_2; - Vec3r inter((1.0 - t) * oppositeEdge->GetaVertex()->GetVertex() + - t * oppositeEdge->GetbVertex()->GetVertex()); - Vec3r vtmp(inter - v->GetVertex()); - // is it K1_a or K1_b ? - if (vtmp * e1 > 0) { - K1_b = K1; - Inter_b = inter; - } - else { - K1_a = K1; - Inter_a = inter; - } - } - } - // Once we have K1 along the ppal direction compute the derivative : K1b - K1a put it in DotP - //real d = fabs(K1_b) - fabs(K1_a); - real d = 0; - real threshold = _meanK1 + (_maxK1 - _meanK1) / 7.0; - //real threshold = _meanK1; - //if ((fabs(K1_b) > threshold) || ((fabs(K1_a) > threshold))) - d = (K1_b) - (K1_a) / (Inter_b - Inter_a).norm(); - faceLayer->PushDotP(d); - //faceLayer->PushDotP(layer_info->vec_curvature_info[i]->K1); - } - - // Make the values relevant by checking whether all principal directions have the "same" direction: - Vec3r e0((layer_info->vec_curvature_info[0]->K1 * layer_info->vec_curvature_info[0]->e1)); - e0.normalize(); - Vec3r e1((layer_info->vec_curvature_info[1]->K1 * layer_info->vec_curvature_info[1]->e1)); - e1.normalize(); - Vec3r e2((layer_info->vec_curvature_info[2]->K1 * layer_info->vec_curvature_info[2]->e1)); - e2.normalize(); - if (e0 * e1 < 0) - // invert dotP[1] - faceLayer->ReplaceDotP(1, -faceLayer->dotP(1)); - if (e0 * e2 < 0) - // invert dotP[2] - faceLayer->ReplaceDotP(2, -faceLayer->dotP(2)); - -#if 0 // remove the weakest values; - real minDiff = (_maxK1 - _minK1) / 10.0; - real minDiff = _meanK1; - if ((faceLayer->dotP(0) < minDiff) && (faceLayer->dotP(1) < minDiff) && (faceLayer->dotP(2) < minDiff)) { - faceLayer->ReplaceDotP(0, 0); - faceLayer->ReplaceDotP(1, 0); - faceLayer->ReplaceDotP(2, 0); - } -#endif + // RIDGE LAYER + // Compute the RidgeFunction, that is the derivative of the ppal curvature along e1 at each vertex of the face + WVertex *v; + Vec3r v1v2; + real t; + vector<WXFaceLayer*> SmoothLayers; + WXFaceLayer *faceLayer; + Face_Curvature_Info *layer_info; + real K1_a(0), K1_b(0); + Vec3r Inter_a, Inter_b; + + // find the ridge layer of the face + iFace->retrieveSmoothLayers(Nature::RIDGE, SmoothLayers); + if ( SmoothLayers.size()!=1 ) + return; + faceLayer = SmoothLayers[0]; + // retrieve the curvature info of this layer + layer_info = (Face_Curvature_Info *)faceLayer->userdata; + + int numVertices = iFace->numberOfVertices(); + for (int i = 0; i < numVertices; i++) { + v = iFace->GetVertex(i); + // vec_curvature_info[i] contains the curvature info of this vertex + Vec3r e2 = layer_info->vec_curvature_info[i]->K2*layer_info->vec_curvature_info[i]->e2; + Vec3r e1 = layer_info->vec_curvature_info[i]->K1*layer_info->vec_curvature_info[i]->e1; + e2.normalize(); + + WVertex::face_iterator fit = v->faces_begin(); + WVertex::face_iterator fitend = v->faces_end(); + for (; fit != fitend; ++fit) { + WXFace *wxf = dynamic_cast<WXFace*>(*fit); + WOEdge *oppositeEdge; + if (!(wxf->getOppositeEdge(v, oppositeEdge))) + continue; + v1v2 = oppositeEdge->GetbVertex()->GetVertex() - oppositeEdge->GetaVertex()->GetVertex(); + GeomUtils::intersection_test res; + res = GeomUtils::intersectRayPlane(oppositeEdge->GetaVertex()->GetVertex(), v1v2, e2, -(v->GetVertex()*e2), + t, 1.0e-06); + if ((res == GeomUtils::DO_INTERSECT) && (t >= 0.0) && (t <= 1.0)) { + vector<WXFaceLayer*> second_ridge_layer; + wxf->retrieveSmoothLayers(Nature::RIDGE, second_ridge_layer); + if (second_ridge_layer.size() != 1) + continue; + Face_Curvature_Info *second_layer_info = (Face_Curvature_Info*)second_ridge_layer[0]->userdata; + + unsigned index1 = wxf->GetIndex(oppositeEdge->GetaVertex()); + unsigned index2 = wxf->GetIndex(oppositeEdge->GetbVertex()); + real K1_1 = second_layer_info->vec_curvature_info[index1]->K1; + real K1_2 = second_layer_info->vec_curvature_info[index2]->K1; + real K1 = (1.0 - t) * K1_1 + t * K1_2; + Vec3r inter((1.0 - t) * oppositeEdge->GetaVertex()->GetVertex() + + t * oppositeEdge->GetbVertex()->GetVertex()); + Vec3r vtmp(inter - v->GetVertex()); + // is it K1_a or K1_b ? + if (vtmp * e1 > 0) { + K1_b = K1; + Inter_b = inter; + } + else { + K1_a = K1; + Inter_a = inter; + } + } + } + // Once we have K1 along the ppal direction compute the derivative : K1b - K1a put it in DotP + //real d = fabs(K1_b) - fabs(K1_a); + real d = 0; + real threshold = _meanK1 + (_maxK1 - _meanK1) / 7.0; + //real threshold = _meanK1; + //if ((fabs(K1_b) > threshold) || ((fabs(K1_a) > threshold))) + d = (K1_b) - (K1_a) / (Inter_b - Inter_a).norm(); + faceLayer->PushDotP(d); + //faceLayer->PushDotP(layer_info->vec_curvature_info[i]->K1); + } + + // Make the values relevant by checking whether all principal directions have the "same" direction: + Vec3r e0((layer_info->vec_curvature_info[0]->K1 * layer_info->vec_curvature_info[0]->e1)); + e0.normalize(); + Vec3r e1((layer_info->vec_curvature_info[1]->K1 * layer_info->vec_curvature_info[1]->e1)); + e1.normalize(); + Vec3r e2((layer_info->vec_curvature_info[2]->K1 * layer_info->vec_curvature_info[2]->e1)); + e2.normalize(); + if (e0 * e1 < 0) + // invert dotP[1] + faceLayer->ReplaceDotP(1, -faceLayer->dotP(1)); + if (e0 * e2 < 0) + // invert dotP[2] + faceLayer->ReplaceDotP(2, -faceLayer->dotP(2)); + +# if 0 // remove the weakest values; + real minDiff = (_maxK1 - _minK1) / 10.0; + real minDiff = _meanK1; + if ((faceLayer->dotP(0) < minDiff) && (faceLayer->dotP(1) < minDiff) && (faceLayer->dotP(2) < minDiff)) { + faceLayer->ReplaceDotP(0, 0); + faceLayer->ReplaceDotP(1, 0); + faceLayer->ReplaceDotP(2, 0); + } +# endif } #endif @@ -543,221 +544,226 @@ void FEdgeXDetector::ProcessRidgeFace(WXFace *iFace) void FEdgeXDetector::processSuggestiveContourShape(WXShape *iWShape) { - // Here the curvatures must already have been computed - vector<WFace*>& wfaces = iWShape->GetFaceList(); - vector<WFace*>::iterator f, fend; - for (f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) { - ProcessSuggestiveContourFace((WXFace *)(*f)); - } + // Here the curvatures must already have been computed + vector<WFace *> &wfaces = iWShape->GetFaceList(); + vector<WFace *>::iterator f, fend; + for (f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) { + ProcessSuggestiveContourFace((WXFace *)(*f)); + } } void FEdgeXDetector::ProcessSuggestiveContourFace(WXFace *iFace) { - WXFaceLayer *faceLayer = new WXFaceLayer(iFace, Nature::SUGGESTIVE_CONTOUR, true); - iFace->AddSmoothLayer(faceLayer); - - unsigned int numVertices = iFace->numberOfVertices(); - for (unsigned int i = 0; i < numVertices; ++i) { - WVertex *wv = iFace->GetVertex(i); - WXVertex *wxv = dynamic_cast<WXVertex*>(wv); - faceLayer->PushDotP(wxv->curvatures()->Kr); - } - -#if 0 // FIXME: find a more clever way to compute the threshold - real threshold = _meanKr; - if (faceLayer->nPosDotP()!=numVertices) { - if ((fabs(faceLayer->dotP(0)) < threshold) && (fabs(faceLayer->dotP(1)) < threshold) && - (fabs(faceLayer->dotP(2)) < threshold)) - { - faceLayer->ReplaceDotP(0, 0); - faceLayer->ReplaceDotP(1, 0); - faceLayer->ReplaceDotP(2, 0); - } - } + WXFaceLayer *faceLayer = new WXFaceLayer(iFace, Nature::SUGGESTIVE_CONTOUR, true); + iFace->AddSmoothLayer(faceLayer); + + unsigned int numVertices = iFace->numberOfVertices(); + for (unsigned int i = 0; i < numVertices; ++i) { + WVertex *wv = iFace->GetVertex(i); + WXVertex *wxv = dynamic_cast<WXVertex *>(wv); + faceLayer->PushDotP(wxv->curvatures()->Kr); + } + +#if 0 // FIXME: find a more clever way to compute the threshold + real threshold = _meanKr; + if (faceLayer->nPosDotP()!=numVertices) { + if ((fabs(faceLayer->dotP(0)) < threshold) && (fabs(faceLayer->dotP(1)) < threshold) && + (fabs(faceLayer->dotP(2)) < threshold)) + { + faceLayer->ReplaceDotP(0, 0); + faceLayer->ReplaceDotP(1, 0); + faceLayer->ReplaceDotP(2, 0); + } + } #endif } void FEdgeXDetector::postProcessSuggestiveContourShape(WXShape *iShape) { - vector<WFace*>& wfaces = iShape->GetFaceList(); - vector<WFace*>::iterator f, fend; - for (f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) { - postProcessSuggestiveContourFace((WXFace *)(*f)); - } + vector<WFace *> &wfaces = iShape->GetFaceList(); + vector<WFace *>::iterator f, fend; + for (f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) { + postProcessSuggestiveContourFace((WXFace *)(*f)); + } } void FEdgeXDetector::postProcessSuggestiveContourFace(WXFace *iFace) { - // Compute the derivative of the radial curvature in the radial direction, at the two extremities - // of the smooth edge. - // If the derivative is smaller than a given threshold _kr_derivative_epsilon, discard the edge. - - // Find the suggestive contour layer of the face (zero or one edge). - vector<WXFaceLayer*> sc_layers; - iFace->retrieveSmoothEdgesLayers(Nature::SUGGESTIVE_CONTOUR, sc_layers); - if (sc_layers.empty()) - return; - - WXFaceLayer *sc_layer; - sc_layer = sc_layers[0]; - - // Compute the derivative value at each vertex of the face, and add it in a vector. - vector<real> kr_derivatives; - - unsigned vertices_nb = iFace->numberOfVertices(); - WXVertex *v, *opposite_vertex_a, *opposite_vertex_b; - WXFace *wxf; - WOEdge *opposite_edge; - Vec3r normal_vec, radial_normal_vec, er_vec, v_vec, inter, inter1, inter2, tmp_vec; - GeomUtils::intersection_test res; - real kr(0), kr1(0), kr2(0), t; - - for (unsigned int i = 0; i < vertices_nb; ++i) { - v = (WXVertex *)(iFace->GetVertex(i)); - - // v is a singular vertex, skip it. - if (v->isBoundary()) { - kr_derivatives.push_back(0); - continue; - } - - v_vec = v->GetVertex(); - er_vec = v->curvatures()->er; - - // For each vertex, iterate on its adjacent faces. - for (WVertex::face_iterator fit = v->faces_begin(), fitend = v->faces_end(); fit != fitend; ++fit) { - wxf = dynamic_cast<WXFace*>(*fit); - if (!wxf->getOppositeEdge(v, opposite_edge)) - continue; - - opposite_vertex_a = (WXVertex *)opposite_edge->GetaVertex(); - opposite_vertex_b = (WXVertex *)opposite_edge->GetbVertex(); - normal_vec = wxf->GetVertexNormal(v); // FIXME: what about e1 ^ e2 ? - radial_normal_vec = er_vec ^ normal_vec; - - // Test whether the radial plan intersects with the edge at the opposite of v. - res = GeomUtils::intersectRayPlane(opposite_vertex_a->GetVertex(), opposite_edge->GetVec(), - radial_normal_vec, -(v_vec * radial_normal_vec), - t, 1.0e-06); - - // If there is an intersection, compute the value of the derivative ath that point. - if ((res == GeomUtils::DO_INTERSECT) && (t >= 0) && (t <= 1)) { - kr = t * opposite_vertex_a->curvatures()->Kr + (1 - t) * opposite_vertex_b->curvatures()->Kr; - inter = opposite_vertex_a->GetVertex() + t * opposite_edge->GetVec(); - tmp_vec = inter - v->GetVertex(); - // Is it kr1 or kr2? - if (tmp_vec * er_vec > 0) { - kr2 = kr; - inter2 = inter; - } - else { - kr1 = kr; - inter1 = inter; - } - } - } - - // Now we have kr1 and kr2 along the radial direction, for one vertex of iFace. - // We have to compute the derivative of kr for that vertex, equal to: - // (kr2 - kr1) / dist(inter1, inter2). - // Then we add it to the vector of derivatives. - v->curvatures()->dKr = (kr2 - kr1) / (inter2 - inter1).norm(); - kr_derivatives.push_back(v->curvatures()->dKr); - } - - // At that point, we have the derivatives for each vertex of iFace. - // All we have to do now is to use linear interpolation to compute the values at the extremities of the smooth edge. - WXSmoothEdge *sc_edge = sc_layer->getSmoothEdge(); - WOEdge *sc_oedge = sc_edge->woea(); - t = sc_edge->ta(); - if (t * kr_derivatives[iFace->GetIndex(sc_oedge->GetaVertex())] + - (1 - t) * kr_derivatives[iFace->GetIndex(sc_oedge->GetbVertex())] < _kr_derivative_epsilon) - { - sc_layer->removeSmoothEdge(); - return; - } - sc_oedge = sc_edge->woeb(); - t = sc_edge->tb(); - if (t * kr_derivatives[iFace->GetIndex(sc_oedge->GetaVertex())] + - (1 - t) * kr_derivatives[iFace->GetIndex(sc_oedge->GetbVertex())] < _kr_derivative_epsilon) - { - sc_layer->removeSmoothEdge(); - } + // Compute the derivative of the radial curvature in the radial direction, at the two extremities + // of the smooth edge. + // If the derivative is smaller than a given threshold _kr_derivative_epsilon, discard the edge. + + // Find the suggestive contour layer of the face (zero or one edge). + vector<WXFaceLayer *> sc_layers; + iFace->retrieveSmoothEdgesLayers(Nature::SUGGESTIVE_CONTOUR, sc_layers); + if (sc_layers.empty()) + return; + + WXFaceLayer *sc_layer; + sc_layer = sc_layers[0]; + + // Compute the derivative value at each vertex of the face, and add it in a vector. + vector<real> kr_derivatives; + + unsigned vertices_nb = iFace->numberOfVertices(); + WXVertex *v, *opposite_vertex_a, *opposite_vertex_b; + WXFace *wxf; + WOEdge *opposite_edge; + Vec3r normal_vec, radial_normal_vec, er_vec, v_vec, inter, inter1, inter2, tmp_vec; + GeomUtils::intersection_test res; + real kr(0), kr1(0), kr2(0), t; + + for (unsigned int i = 0; i < vertices_nb; ++i) { + v = (WXVertex *)(iFace->GetVertex(i)); + + // v is a singular vertex, skip it. + if (v->isBoundary()) { + kr_derivatives.push_back(0); + continue; + } + + v_vec = v->GetVertex(); + er_vec = v->curvatures()->er; + + // For each vertex, iterate on its adjacent faces. + for (WVertex::face_iterator fit = v->faces_begin(), fitend = v->faces_end(); fit != fitend; + ++fit) { + wxf = dynamic_cast<WXFace *>(*fit); + if (!wxf->getOppositeEdge(v, opposite_edge)) + continue; + + opposite_vertex_a = (WXVertex *)opposite_edge->GetaVertex(); + opposite_vertex_b = (WXVertex *)opposite_edge->GetbVertex(); + normal_vec = wxf->GetVertexNormal(v); // FIXME: what about e1 ^ e2 ? + radial_normal_vec = er_vec ^ normal_vec; + + // Test whether the radial plan intersects with the edge at the opposite of v. + res = GeomUtils::intersectRayPlane(opposite_vertex_a->GetVertex(), + opposite_edge->GetVec(), + radial_normal_vec, + -(v_vec * radial_normal_vec), + t, + 1.0e-06); + + // If there is an intersection, compute the value of the derivative ath that point. + if ((res == GeomUtils::DO_INTERSECT) && (t >= 0) && (t <= 1)) { + kr = t * opposite_vertex_a->curvatures()->Kr + + (1 - t) * opposite_vertex_b->curvatures()->Kr; + inter = opposite_vertex_a->GetVertex() + t * opposite_edge->GetVec(); + tmp_vec = inter - v->GetVertex(); + // Is it kr1 or kr2? + if (tmp_vec * er_vec > 0) { + kr2 = kr; + inter2 = inter; + } + else { + kr1 = kr; + inter1 = inter; + } + } + } + + // Now we have kr1 and kr2 along the radial direction, for one vertex of iFace. + // We have to compute the derivative of kr for that vertex, equal to: + // (kr2 - kr1) / dist(inter1, inter2). + // Then we add it to the vector of derivatives. + v->curvatures()->dKr = (kr2 - kr1) / (inter2 - inter1).norm(); + kr_derivatives.push_back(v->curvatures()->dKr); + } + + // At that point, we have the derivatives for each vertex of iFace. + // All we have to do now is to use linear interpolation to compute the values at the extremities of the smooth edge. + WXSmoothEdge *sc_edge = sc_layer->getSmoothEdge(); + WOEdge *sc_oedge = sc_edge->woea(); + t = sc_edge->ta(); + if (t * kr_derivatives[iFace->GetIndex(sc_oedge->GetaVertex())] + + (1 - t) * kr_derivatives[iFace->GetIndex(sc_oedge->GetbVertex())] < + _kr_derivative_epsilon) { + sc_layer->removeSmoothEdge(); + return; + } + sc_oedge = sc_edge->woeb(); + t = sc_edge->tb(); + if (t * kr_derivatives[iFace->GetIndex(sc_oedge->GetaVertex())] + + (1 - t) * kr_derivatives[iFace->GetIndex(sc_oedge->GetbVertex())] < + _kr_derivative_epsilon) { + sc_layer->removeSmoothEdge(); + } } // MATERIAL_BOUNDARY //////////////////// void FEdgeXDetector::processMaterialBoundaryShape(WXShape *iWShape) { - if (!_computeViewIndependent) - return; - // Make a pass on the edges to detect material boundaries - vector<WEdge*>::iterator we, weend; - vector<WEdge*> &wedges = iWShape->getEdgeList(); - for (we = wedges.begin(), weend = wedges.end(); we != weend; ++we) { - ProcessMaterialBoundaryEdge((WXEdge *)(*we)); - } + if (!_computeViewIndependent) + return; + // Make a pass on the edges to detect material boundaries + vector<WEdge *>::iterator we, weend; + vector<WEdge *> &wedges = iWShape->getEdgeList(); + for (we = wedges.begin(), weend = wedges.end(); we != weend; ++we) { + ProcessMaterialBoundaryEdge((WXEdge *)(*we)); + } } void FEdgeXDetector::ProcessMaterialBoundaryEdge(WXEdge *iEdge) { - // check whether the edge is a material boundary? - WFace *aFace = iEdge->GetaFace(); - WFace *bFace = iEdge->GetbFace(); - if (aFace && bFace && aFace->frs_materialIndex() != bFace->frs_materialIndex()) { - iEdge->AddNature(Nature::MATERIAL_BOUNDARY); - } + // check whether the edge is a material boundary? + WFace *aFace = iEdge->GetaFace(); + WFace *bFace = iEdge->GetbFace(); + if (aFace && bFace && aFace->frs_materialIndex() != bFace->frs_materialIndex()) { + iEdge->AddNature(Nature::MATERIAL_BOUNDARY); + } } // EDGE MARKS ///////////// void FEdgeXDetector::processEdgeMarksShape(WXShape *iShape) { - // Make a pass on the edges to detect material boundaries - vector<WEdge*>::iterator we, weend; - vector<WEdge*> &wedges = iShape->getEdgeList(); - for (we = wedges.begin(), weend = wedges.end(); we != weend; ++we) { - ProcessEdgeMarks((WXEdge *)(*we)); - } + // Make a pass on the edges to detect material boundaries + vector<WEdge *>::iterator we, weend; + vector<WEdge *> &wedges = iShape->getEdgeList(); + for (we = wedges.begin(), weend = wedges.end(); we != weend; ++we) { + ProcessEdgeMarks((WXEdge *)(*we)); + } } void FEdgeXDetector::ProcessEdgeMarks(WXEdge *iEdge) { - if (iEdge->GetMark()) { - iEdge->AddNature(Nature::EDGE_MARK); - } + if (iEdge->GetMark()) { + iEdge->AddNature(Nature::EDGE_MARK); + } } // Build Smooth edges ///////////////////// void FEdgeXDetector::buildSmoothEdges(WXShape *iShape) { - bool hasSmoothEdges = false; - - // Make a last pass to build smooth edges from the previous stored values: - //-------------------------------------------------------------------------- - vector<WFace*>& wfaces = iShape->GetFaceList(); - for (vector<WFace *>::iterator f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) { - vector<WXFaceLayer *>& faceLayers = ((WXFace *)(*f))->getSmoothLayers(); - for (vector<WXFaceLayer *>::iterator wxfl = faceLayers.begin(), wxflend = faceLayers.end(); - wxfl != wxflend; - ++wxfl) - { - if ((*wxfl)->BuildSmoothEdge()) - hasSmoothEdges = true; - } - } - - if (hasSmoothEdges && !_computeRidgesAndValleys && !_computeSuggestiveContours) { - vector<WVertex *>& wvertices = iShape->getVertexList(); - for (vector<WVertex*>::iterator wv = wvertices.begin(), wvend = wvertices.end(); wv != wvend; ++wv) { - // Compute curvatures - WXVertex *wxv = dynamic_cast<WXVertex *>(*wv); - computeCurvatures(wxv); - } - _meanK1 /= (real)(_nPoints); - _meanKr /= (real)(_nPoints); - } + bool hasSmoothEdges = false; + + // Make a last pass to build smooth edges from the previous stored values: + //-------------------------------------------------------------------------- + vector<WFace *> &wfaces = iShape->GetFaceList(); + for (vector<WFace *>::iterator f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) { + vector<WXFaceLayer *> &faceLayers = ((WXFace *)(*f))->getSmoothLayers(); + for (vector<WXFaceLayer *>::iterator wxfl = faceLayers.begin(), wxflend = faceLayers.end(); + wxfl != wxflend; + ++wxfl) { + if ((*wxfl)->BuildSmoothEdge()) + hasSmoothEdges = true; + } + } + + if (hasSmoothEdges && !_computeRidgesAndValleys && !_computeSuggestiveContours) { + vector<WVertex *> &wvertices = iShape->getVertexList(); + for (vector<WVertex *>::iterator wv = wvertices.begin(), wvend = wvertices.end(); wv != wvend; + ++wv) { + // Compute curvatures + WXVertex *wxv = dynamic_cast<WXVertex *>(*wv); + computeCurvatures(wxv); + } + _meanK1 /= (real)(_nPoints); + _meanKr /= (real)(_nPoints); + } } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/view_map/FEdgeXDetector.h b/source/blender/freestyle/intern/view_map/FEdgeXDetector.h index 9143a2b507d..61e0c9267a1 100644 --- a/source/blender/freestyle/intern/view_map/FEdgeXDetector.h +++ b/source/blender/freestyle/intern/view_map/FEdgeXDetector.h @@ -36,7 +36,7 @@ #include "BLI_math.h" #ifdef WITH_CXX_GUARDEDALLOC -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif namespace Freestyle { @@ -44,203 +44,204 @@ namespace Freestyle { using namespace Geometry; /*! This class takes as input a WXEdge structure and fills it */ -class FEdgeXDetector -{ -public: - FEdgeXDetector() - { - _pProgressBar = NULL; - _pRenderMonitor = NULL; - _computeViewIndependent = true; +class FEdgeXDetector { + public: + FEdgeXDetector() + { + _pProgressBar = NULL; + _pRenderMonitor = NULL; + _computeViewIndependent = true; #if 0 - _bbox_diagonal = 1.0; + _bbox_diagonal = 1.0; #endif - _meanEdgeSize = 0; - _computeRidgesAndValleys = true; - _computeSuggestiveContours = true; - _computeMaterialBoundaries = true; - _sphereRadius = 1.0; - _orthographicProjection = false; - _faceSmoothness = false; - _changes = false; - _kr_derivative_epsilon = 0.0; - _creaseAngle = 0.7; // angle of 134.43 degrees - } - - virtual ~FEdgeXDetector() {} - - /*! Process shapes from a WingedEdge containing a list of WShapes */ - virtual void processShapes(WingedEdge&); - - // GENERAL STUFF - virtual void preProcessShape(WXShape *iShape); - virtual void preProcessFace(WXFace *iFace); - virtual void computeCurvatures(WXVertex *iVertex); - - // SILHOUETTE - virtual void processSilhouetteShape(WXShape *iShape); - virtual void ProcessSilhouetteFace(WXFace *iFace); - virtual void ProcessSilhouetteEdge(WXEdge *iEdge); - - // CREASE - virtual void processCreaseShape(WXShape *iShape); - virtual void ProcessCreaseEdge(WXEdge *iEdge); - - /*! Sets the minimum angle for detecting crease edges - * \param angle: - * The angular threshold in degrees (between 0 and 180) for detecting crease edges. An edge is considered - * a crease edge if the angle between two faces sharing the edge is smaller than the given threshold. - */ - // XXX angle should be in radian... - inline void setCreaseAngle(float angle) - { - if (angle < 0.0) - angle = 0.0; - else if (angle > 180.0) - angle = 180.0; - angle = cos(M_PI * (180.0 - angle) / 180.0); - if (angle != _creaseAngle) { - _creaseAngle = angle; - _changes = true; - } - } - - // BORDER - virtual void processBorderShape(WXShape *iShape); - virtual void ProcessBorderEdge(WXEdge *iEdge); - - // RIDGES AND VALLEYS - virtual void processRidgesAndValleysShape(WXShape *iShape); - virtual void ProcessRidgeFace(WXFace *iFace); - - // SUGGESTIVE CONTOURS - virtual void processSuggestiveContourShape(WXShape *iShape); - virtual void ProcessSuggestiveContourFace(WXFace *iFace); - virtual void postProcessSuggestiveContourShape(WXShape *iShape); - virtual void postProcessSuggestiveContourFace(WXFace *iFace); - /*! Sets the minimal derivative of the radial curvature for suggestive contours - * \param dkr: - * The minimal derivative of the radial curvature - */ - inline void setSuggestiveContourKrDerivativeEpsilon(float dkr) - { - if (dkr != _kr_derivative_epsilon) { - _kr_derivative_epsilon = dkr; - _changes = true; - } - } - - // MATERIAL BOUNDARY - virtual void processMaterialBoundaryShape(WXShape *iWShape); - virtual void ProcessMaterialBoundaryEdge(WXEdge *iEdge); - - // EDGE MARKS - virtual void processEdgeMarksShape(WXShape *iShape); - virtual void ProcessEdgeMarks(WXEdge *iEdge); - - // EVERYBODY - virtual void buildSmoothEdges(WXShape *iShape); - - /*! Sets the current viewpoint */ - inline void setViewpoint(const Vec3f& ivp) - { - _Viewpoint = ivp; - } - - inline void enableOrthographicProjection(bool b) - { - _orthographicProjection = b; - } - - inline void enableRidgesAndValleysFlag(bool b) - { - _computeRidgesAndValleys = b; - } - - inline void enableSuggestiveContours(bool b) - { - _computeSuggestiveContours = b; - } - - inline void enableMaterialBoundaries(bool b) - { - _computeMaterialBoundaries = b; - } - - inline void enableFaceSmoothness(bool b) - { - if (b != _faceSmoothness) { - _faceSmoothness = b; - _changes = true; - } - } - - inline void enableFaceMarks(bool b) - { - if (b != _faceMarks) { - _faceMarks = b; - _changes = true; - } - } - - /*! Sets the radius of the geodesic sphere around each vertex (for the curvature computation) - * \param r: - * The radius of the sphere expressed as a ratio of the mean edge size - */ - inline void setSphereRadius(float r) - { - if (r != _sphereRadius) { - _sphereRadius = r; - _changes = true; - } - } - - inline void setProgressBar(ProgressBar *iProgressBar) - { - _pProgressBar = iProgressBar; - } - - inline void setRenderMonitor(RenderMonitor *iRenderMonitor) - { - _pRenderMonitor = iRenderMonitor; - } - -protected: - Vec3f _Viewpoint; + _meanEdgeSize = 0; + _computeRidgesAndValleys = true; + _computeSuggestiveContours = true; + _computeMaterialBoundaries = true; + _sphereRadius = 1.0; + _orthographicProjection = false; + _faceSmoothness = false; + _changes = false; + _kr_derivative_epsilon = 0.0; + _creaseAngle = 0.7; // angle of 134.43 degrees + } + + virtual ~FEdgeXDetector() + { + } + + /*! Process shapes from a WingedEdge containing a list of WShapes */ + virtual void processShapes(WingedEdge &); + + // GENERAL STUFF + virtual void preProcessShape(WXShape *iShape); + virtual void preProcessFace(WXFace *iFace); + virtual void computeCurvatures(WXVertex *iVertex); + + // SILHOUETTE + virtual void processSilhouetteShape(WXShape *iShape); + virtual void ProcessSilhouetteFace(WXFace *iFace); + virtual void ProcessSilhouetteEdge(WXEdge *iEdge); + + // CREASE + virtual void processCreaseShape(WXShape *iShape); + virtual void ProcessCreaseEdge(WXEdge *iEdge); + + /*! Sets the minimum angle for detecting crease edges + * \param angle: + * The angular threshold in degrees (between 0 and 180) for detecting crease edges. An edge is considered + * a crease edge if the angle between two faces sharing the edge is smaller than the given threshold. + */ + // XXX angle should be in radian... + inline void setCreaseAngle(float angle) + { + if (angle < 0.0) + angle = 0.0; + else if (angle > 180.0) + angle = 180.0; + angle = cos(M_PI * (180.0 - angle) / 180.0); + if (angle != _creaseAngle) { + _creaseAngle = angle; + _changes = true; + } + } + + // BORDER + virtual void processBorderShape(WXShape *iShape); + virtual void ProcessBorderEdge(WXEdge *iEdge); + + // RIDGES AND VALLEYS + virtual void processRidgesAndValleysShape(WXShape *iShape); + virtual void ProcessRidgeFace(WXFace *iFace); + + // SUGGESTIVE CONTOURS + virtual void processSuggestiveContourShape(WXShape *iShape); + virtual void ProcessSuggestiveContourFace(WXFace *iFace); + virtual void postProcessSuggestiveContourShape(WXShape *iShape); + virtual void postProcessSuggestiveContourFace(WXFace *iFace); + /*! Sets the minimal derivative of the radial curvature for suggestive contours + * \param dkr: + * The minimal derivative of the radial curvature + */ + inline void setSuggestiveContourKrDerivativeEpsilon(float dkr) + { + if (dkr != _kr_derivative_epsilon) { + _kr_derivative_epsilon = dkr; + _changes = true; + } + } + + // MATERIAL BOUNDARY + virtual void processMaterialBoundaryShape(WXShape *iWShape); + virtual void ProcessMaterialBoundaryEdge(WXEdge *iEdge); + + // EDGE MARKS + virtual void processEdgeMarksShape(WXShape *iShape); + virtual void ProcessEdgeMarks(WXEdge *iEdge); + + // EVERYBODY + virtual void buildSmoothEdges(WXShape *iShape); + + /*! Sets the current viewpoint */ + inline void setViewpoint(const Vec3f &ivp) + { + _Viewpoint = ivp; + } + + inline void enableOrthographicProjection(bool b) + { + _orthographicProjection = b; + } + + inline void enableRidgesAndValleysFlag(bool b) + { + _computeRidgesAndValleys = b; + } + + inline void enableSuggestiveContours(bool b) + { + _computeSuggestiveContours = b; + } + + inline void enableMaterialBoundaries(bool b) + { + _computeMaterialBoundaries = b; + } + + inline void enableFaceSmoothness(bool b) + { + if (b != _faceSmoothness) { + _faceSmoothness = b; + _changes = true; + } + } + + inline void enableFaceMarks(bool b) + { + if (b != _faceMarks) { + _faceMarks = b; + _changes = true; + } + } + + /*! Sets the radius of the geodesic sphere around each vertex (for the curvature computation) + * \param r: + * The radius of the sphere expressed as a ratio of the mean edge size + */ + inline void setSphereRadius(float r) + { + if (r != _sphereRadius) { + _sphereRadius = r; + _changes = true; + } + } + + inline void setProgressBar(ProgressBar *iProgressBar) + { + _pProgressBar = iProgressBar; + } + + inline void setRenderMonitor(RenderMonitor *iRenderMonitor) + { + _pRenderMonitor = iRenderMonitor; + } + + protected: + Vec3f _Viewpoint; #if 0 - real _bbox_diagonal; // diagonal of the current processed shape bbox + real _bbox_diagonal; // diagonal of the current processed shape bbox #endif - //oldtmp values - bool _computeViewIndependent; - real _meanK1; - real _meanKr; - real _minK1; - real _minKr; - real _maxK1; - real _maxKr; - unsigned _nPoints; - real _meanEdgeSize; - bool _orthographicProjection; - - bool _computeRidgesAndValleys; - bool _computeSuggestiveContours; - bool _computeMaterialBoundaries; - bool _faceSmoothness; - bool _faceMarks; - float _sphereRadius; // expressed as a ratio of the mean edge size - float _creaseAngle; // [-1, 1] compared with the inner product of face normals - bool _changes; - - float _kr_derivative_epsilon; - - ProgressBar *_pProgressBar; - RenderMonitor *_pRenderMonitor; + //oldtmp values + bool _computeViewIndependent; + real _meanK1; + real _meanKr; + real _minK1; + real _minKr; + real _maxK1; + real _maxKr; + unsigned _nPoints; + real _meanEdgeSize; + bool _orthographicProjection; + + bool _computeRidgesAndValleys; + bool _computeSuggestiveContours; + bool _computeMaterialBoundaries; + bool _faceSmoothness; + bool _faceMarks; + float _sphereRadius; // expressed as a ratio of the mean edge size + float _creaseAngle; // [-1, 1] compared with the inner product of face normals + bool _changes; + + float _kr_derivative_epsilon; + + ProgressBar *_pProgressBar; + RenderMonitor *_pRenderMonitor; #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:FEdgeXDetector") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:FEdgeXDetector") #endif }; } /* namespace Freestyle */ -#endif // __FREESTYLE_FEDGE_X_DETECTOR_H__ +#endif // __FREESTYLE_FEDGE_X_DETECTOR_H__ diff --git a/source/blender/freestyle/intern/view_map/Functions0D.cpp b/source/blender/freestyle/intern/view_map/Functions0D.cpp index aca8fce2983..5b04b66eeeb 100644 --- a/source/blender/freestyle/intern/view_map/Functions0D.cpp +++ b/source/blender/freestyle/intern/view_map/Functions0D.cpp @@ -31,336 +31,338 @@ namespace Freestyle { namespace Functions0D { // Internal function -FEdge *getFEdge(Interface0D& it1, Interface0D& it2) +FEdge *getFEdge(Interface0D &it1, Interface0D &it2) { - return it1.getFEdge(it2); + return it1.getFEdge(it2); } -void getFEdges(Interface0DIterator& it, FEdge *&fe1, FEdge *&fe2) +void getFEdges(Interface0DIterator &it, FEdge *&fe1, FEdge *&fe2) { - // count number of vertices - Interface0DIterator prev = it, next = it; - ++next; - int count = 1; - if (!it.isBegin() && !next.isEnd()) { - count = 3; - } - if (count < 3) { - // if we only have 2 vertices - FEdge *fe = 0; - Interface0DIterator tmp = it; - if (it.isBegin()) { - ++tmp; - fe = it->getFEdge(*tmp); - } - else { - --tmp; - fe = it->getFEdge(*tmp); - } - fe1 = fe; - fe2 = NULL; - } - else { - // we have more than 2 vertices - bool begin = false, last = false; - Interface0DIterator previous = it; - if (!previous.isBegin()) - --previous; - else - begin = true; - Interface0DIterator next = it; - ++next; - if (next.isEnd()) - last = true; - if (begin) { - fe1 = it->getFEdge(*next); - fe2 = NULL; - } - else if (last) { - fe1 = previous->getFEdge(*it); - fe2 = NULL; - } - else { - fe1 = previous->getFEdge(*it); - fe2 = it->getFEdge(*next); - } - } + // count number of vertices + Interface0DIterator prev = it, next = it; + ++next; + int count = 1; + if (!it.isBegin() && !next.isEnd()) { + count = 3; + } + if (count < 3) { + // if we only have 2 vertices + FEdge *fe = 0; + Interface0DIterator tmp = it; + if (it.isBegin()) { + ++tmp; + fe = it->getFEdge(*tmp); + } + else { + --tmp; + fe = it->getFEdge(*tmp); + } + fe1 = fe; + fe2 = NULL; + } + else { + // we have more than 2 vertices + bool begin = false, last = false; + Interface0DIterator previous = it; + if (!previous.isBegin()) + --previous; + else + begin = true; + Interface0DIterator next = it; + ++next; + if (next.isEnd()) + last = true; + if (begin) { + fe1 = it->getFEdge(*next); + fe2 = NULL; + } + else if (last) { + fe1 = previous->getFEdge(*it); + fe2 = NULL; + } + else { + fe1 = previous->getFEdge(*it); + fe2 = it->getFEdge(*next); + } + } } void getViewEdges(Interface0DIterator &it, ViewEdge *&ve1, ViewEdge *&ve2) { - FEdge *fe1, *fe2; - getFEdges(it, fe1, fe2); - ve1 = fe1->viewedge(); - if (fe2 != NULL) { - ve2 = fe2->viewedge(); - if (ve2 == ve1) - ve2 = NULL; - } - else { - ve2 = NULL; - } + FEdge *fe1, *fe2; + getFEdges(it, fe1, fe2); + ve1 = fe1->viewedge(); + if (fe2 != NULL) { + ve2 = fe2->viewedge(); + if (ve2 == ve1) + ve2 = NULL; + } + else { + ve2 = NULL; + } } -ViewShape *getShapeF0D(Interface0DIterator& it) +ViewShape *getShapeF0D(Interface0DIterator &it) { - ViewEdge *ve1, *ve2; - getViewEdges(it, ve1, ve2); - return ve1->viewShape(); + ViewEdge *ve1, *ve2; + getViewEdges(it, ve1, ve2); + return ve1->viewShape(); } -void getOccludersF0D(Interface0DIterator& it, set<ViewShape*>& oOccluders) +void getOccludersF0D(Interface0DIterator &it, set<ViewShape *> &oOccluders) { - ViewEdge *ve1, *ve2; - getViewEdges(it, ve1, ve2); - occluder_container::const_iterator oit = ve1->occluders_begin(); - occluder_container::const_iterator oitend = ve1->occluders_end(); - - for (; oit != oitend; ++oit) - oOccluders.insert((*oit)); - - if (ve2 != NULL) { - oit = ve2->occluders_begin(); - oitend = ve2->occluders_end(); - for (; oit != oitend; ++oit) - oOccluders.insert((*oit)); - } + ViewEdge *ve1, *ve2; + getViewEdges(it, ve1, ve2); + occluder_container::const_iterator oit = ve1->occluders_begin(); + occluder_container::const_iterator oitend = ve1->occluders_end(); + + for (; oit != oitend; ++oit) + oOccluders.insert((*oit)); + + if (ve2 != NULL) { + oit = ve2->occluders_begin(); + oitend = ve2->occluders_end(); + for (; oit != oitend; ++oit) + oOccluders.insert((*oit)); + } } -ViewShape *getOccludeeF0D(Interface0DIterator& it) +ViewShape *getOccludeeF0D(Interface0DIterator &it) { - ViewEdge *ve1, *ve2; - getViewEdges(it, ve1, ve2); - ViewShape *aShape = ve1->aShape(); - return aShape; + ViewEdge *ve1, *ve2; + getViewEdges(it, ve1, ve2); + ViewShape *aShape = ve1->aShape(); + return aShape; } // -int VertexOrientation2DF0D::operator()(Interface0DIterator& iter) +int VertexOrientation2DF0D::operator()(Interface0DIterator &iter) { - Vec2f A, C; - Vec2f B(iter->getProjectedX(), iter->getProjectedY()); - if (iter.isBegin()) { - A = Vec2f(iter->getProjectedX(), iter->getProjectedY()); - } - else { - Interface0DIterator previous = iter; - --previous ; - A = Vec2f(previous->getProjectedX(), previous->getProjectedY()); - } - Interface0DIterator next = iter; - ++next; - if (next.isEnd()) - C = Vec2f(iter->getProjectedX(), iter->getProjectedY()); - else - C = Vec2f(next->getProjectedX(), next->getProjectedY()); - - Vec2f AB(B - A); - if (AB.norm() != 0) - AB.normalize(); - Vec2f BC(C - B); - if (BC.norm() != 0) - BC.normalize(); - result = AB + BC; - if (result.norm() != 0) - result.normalize(); - return 0; + Vec2f A, C; + Vec2f B(iter->getProjectedX(), iter->getProjectedY()); + if (iter.isBegin()) { + A = Vec2f(iter->getProjectedX(), iter->getProjectedY()); + } + else { + Interface0DIterator previous = iter; + --previous; + A = Vec2f(previous->getProjectedX(), previous->getProjectedY()); + } + Interface0DIterator next = iter; + ++next; + if (next.isEnd()) + C = Vec2f(iter->getProjectedX(), iter->getProjectedY()); + else + C = Vec2f(next->getProjectedX(), next->getProjectedY()); + + Vec2f AB(B - A); + if (AB.norm() != 0) + AB.normalize(); + Vec2f BC(C - B); + if (BC.norm() != 0) + BC.normalize(); + result = AB + BC; + if (result.norm() != 0) + result.normalize(); + return 0; } -int VertexOrientation3DF0D::operator()(Interface0DIterator& iter) +int VertexOrientation3DF0D::operator()(Interface0DIterator &iter) { - Vec3r A, C; - Vec3r B(iter->getX(), iter->getY(), iter->getZ()); - if (iter.isBegin()) { - A = Vec3r(iter->getX(), iter->getY(), iter->getZ()); - } - else { - Interface0DIterator previous = iter; - --previous ; - A = Vec3r(previous->getX(), previous->getY(), previous->getZ()); - } - Interface0DIterator next = iter; - ++next ; - if (next.isEnd()) - C = Vec3r(iter->getX(), iter->getY(), iter->getZ()); - else - C = Vec3r(next->getX(), next->getY(), next->getZ()); - - Vec3r AB(B - A); - if (AB.norm() != 0) - AB.normalize(); - Vec3r BC(C - B); - if (BC.norm() != 0) - BC.normalize(); - result = AB + BC; - if (result.norm() != 0) - result.normalize(); - return 0; + Vec3r A, C; + Vec3r B(iter->getX(), iter->getY(), iter->getZ()); + if (iter.isBegin()) { + A = Vec3r(iter->getX(), iter->getY(), iter->getZ()); + } + else { + Interface0DIterator previous = iter; + --previous; + A = Vec3r(previous->getX(), previous->getY(), previous->getZ()); + } + Interface0DIterator next = iter; + ++next; + if (next.isEnd()) + C = Vec3r(iter->getX(), iter->getY(), iter->getZ()); + else + C = Vec3r(next->getX(), next->getY(), next->getZ()); + + Vec3r AB(B - A); + if (AB.norm() != 0) + AB.normalize(); + Vec3r BC(C - B); + if (BC.norm() != 0) + BC.normalize(); + result = AB + BC; + if (result.norm() != 0) + result.normalize(); + return 0; } -int Curvature2DAngleF0D::operator()(Interface0DIterator& iter) +int Curvature2DAngleF0D::operator()(Interface0DIterator &iter) { - Interface0DIterator tmp1 = iter, tmp2 = iter; - ++tmp2; - unsigned count = 1; - while ((!tmp1.isBegin()) && (count < 3)) { - --tmp1; - ++count; - } - while ((!tmp2.isEnd()) && (count < 3)) { - ++tmp2; - ++count; - } - if (count < 3) { - // if we only have 2 vertices - result = 0; - return 0; - } - - Interface0DIterator v = iter; - if (iter.isBegin()) - ++v; - Interface0DIterator next = v; - ++next; - if (next.isEnd()) { - next = v; - --v; - } - Interface0DIterator prev = v; - --prev; - - Vec2r A(prev->getProjectedX(), prev->getProjectedY()); - Vec2r B(v->getProjectedX(), v->getProjectedY()); - Vec2r C(next->getProjectedX(), next->getProjectedY()); - Vec2r AB(B - A); - Vec2r BC(C - B); - Vec2r N1(-AB[1], AB[0]); - if (N1.norm() != 0) - N1.normalize(); - Vec2r N2(-BC[1], BC[0]); - if (N2.norm() != 0) - N2.normalize(); - if ((N1.norm() == 0) && (N2.norm() == 0)) { - Exception::raiseException(); - result = 0; - return -1; - } - double cosin = N1 * N2; - if (cosin > 1) - cosin = 1; - if (cosin < -1) - cosin = -1; - result = acos(cosin); - return 0; + Interface0DIterator tmp1 = iter, tmp2 = iter; + ++tmp2; + unsigned count = 1; + while ((!tmp1.isBegin()) && (count < 3)) { + --tmp1; + ++count; + } + while ((!tmp2.isEnd()) && (count < 3)) { + ++tmp2; + ++count; + } + if (count < 3) { + // if we only have 2 vertices + result = 0; + return 0; + } + + Interface0DIterator v = iter; + if (iter.isBegin()) + ++v; + Interface0DIterator next = v; + ++next; + if (next.isEnd()) { + next = v; + --v; + } + Interface0DIterator prev = v; + --prev; + + Vec2r A(prev->getProjectedX(), prev->getProjectedY()); + Vec2r B(v->getProjectedX(), v->getProjectedY()); + Vec2r C(next->getProjectedX(), next->getProjectedY()); + Vec2r AB(B - A); + Vec2r BC(C - B); + Vec2r N1(-AB[1], AB[0]); + if (N1.norm() != 0) + N1.normalize(); + Vec2r N2(-BC[1], BC[0]); + if (N2.norm() != 0) + N2.normalize(); + if ((N1.norm() == 0) && (N2.norm() == 0)) { + Exception::raiseException(); + result = 0; + return -1; + } + double cosin = N1 * N2; + if (cosin > 1) + cosin = 1; + if (cosin < -1) + cosin = -1; + result = acos(cosin); + return 0; } -int ZDiscontinuityF0D::operator()(Interface0DIterator& iter) +int ZDiscontinuityF0D::operator()(Interface0DIterator &iter) { - FEdge *fe1, *fe2; - getFEdges(iter, fe1, fe2); - result = fe1->z_discontinuity(); - if (fe2 != NULL) { - result += fe2->z_discontinuity(); - result /= 2.0f; - } - return 0; + FEdge *fe1, *fe2; + getFEdges(iter, fe1, fe2); + result = fe1->z_discontinuity(); + if (fe2 != NULL) { + result += fe2->z_discontinuity(); + result /= 2.0f; + } + return 0; } -int Normal2DF0D::operator()(Interface0DIterator& iter) +int Normal2DF0D::operator()(Interface0DIterator &iter) { - FEdge *fe1, *fe2; - getFEdges(iter, fe1, fe2); - Vec3f e1(fe1->orientation2d()); - Vec2f n1(e1[1], -e1[0]); - Vec2f n(n1); - if (fe2 != NULL) { - Vec3f e2(fe2->orientation2d()); - Vec2f n2(e2[1], -e2[0]); - n += n2; - } - n.normalize(); - result = n; - return 0; + FEdge *fe1, *fe2; + getFEdges(iter, fe1, fe2); + Vec3f e1(fe1->orientation2d()); + Vec2f n1(e1[1], -e1[0]); + Vec2f n(n1); + if (fe2 != NULL) { + Vec3f e2(fe2->orientation2d()); + Vec2f n2(e2[1], -e2[0]); + n += n2; + } + n.normalize(); + result = n; + return 0; } -int MaterialF0D::operator()(Interface0DIterator& iter) +int MaterialF0D::operator()(Interface0DIterator &iter) { - FEdge *fe1, *fe2; - getFEdges(iter, fe1, fe2); - if (fe1 == NULL) - return -1; - if (fe1->isSmooth()) - result = ((FEdgeSmooth *)fe1)->frs_material(); - else - result = ((FEdgeSharp *)fe1)->bFrsMaterial(); + FEdge *fe1, *fe2; + getFEdges(iter, fe1, fe2); + if (fe1 == NULL) + return -1; + if (fe1->isSmooth()) + result = ((FEdgeSmooth *)fe1)->frs_material(); + else + result = ((FEdgeSharp *)fe1)->bFrsMaterial(); #if 0 - const SShape *sshape = getShapeF0D(iter); - return sshape->material(); + const SShape *sshape = getShapeF0D(iter); + return sshape->material(); #endif - return 0; + return 0; } -int ShapeIdF0D::operator()(Interface0DIterator& iter) +int ShapeIdF0D::operator()(Interface0DIterator &iter) { - ViewShape *vshape = getShapeF0D(iter); - result = vshape->getId(); - return 0; + ViewShape *vshape = getShapeF0D(iter); + result = vshape->getId(); + return 0; } -int QuantitativeInvisibilityF0D::operator()(Interface0DIterator& iter) +int QuantitativeInvisibilityF0D::operator()(Interface0DIterator &iter) { - ViewEdge *ve1, *ve2; - getViewEdges(iter, ve1, ve2); - unsigned int qi1, qi2; - qi1 = ve1->qi(); - if (ve2 != NULL) { - qi2 = ve2->qi(); - if (qi2 != qi1) { - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "QuantitativeInvisibilityF0D: ambiguous evaluation for point " << iter->getId() << endl; - } - } - } - result = qi1; - return 0; + ViewEdge *ve1, *ve2; + getViewEdges(iter, ve1, ve2); + unsigned int qi1, qi2; + qi1 = ve1->qi(); + if (ve2 != NULL) { + qi2 = ve2->qi(); + if (qi2 != qi1) { + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "QuantitativeInvisibilityF0D: ambiguous evaluation for point " << iter->getId() + << endl; + } + } + } + result = qi1; + return 0; } -int CurveNatureF0D::operator()(Interface0DIterator& iter) +int CurveNatureF0D::operator()(Interface0DIterator &iter) { - Nature::EdgeNature nat = 0; - ViewEdge *ve1, *ve2; - getViewEdges(iter, ve1, ve2); - nat |= ve1->getNature(); - if (ve2 != NULL) - nat |= ve2->getNature(); - result = nat; - return 0; + Nature::EdgeNature nat = 0; + ViewEdge *ve1, *ve2; + getViewEdges(iter, ve1, ve2); + nat |= ve1->getNature(); + if (ve2 != NULL) + nat |= ve2->getNature(); + result = nat; + return 0; } -int GetOccludersF0D::operator()(Interface0DIterator& iter) +int GetOccludersF0D::operator()(Interface0DIterator &iter) { - set<ViewShape*> occluders; - getOccludersF0D(iter, occluders); - result.clear(); - //vsOccluders.insert(vsOccluders.begin(), occluders.begin(), occluders.end()); - for (set<ViewShape*>::iterator it = occluders.begin(), itend = occluders.end(); it != itend; ++it) { - result.push_back((*it)); - } - return 0; + set<ViewShape *> occluders; + getOccludersF0D(iter, occluders); + result.clear(); + //vsOccluders.insert(vsOccluders.begin(), occluders.begin(), occluders.end()); + for (set<ViewShape *>::iterator it = occluders.begin(), itend = occluders.end(); it != itend; + ++it) { + result.push_back((*it)); + } + return 0; } -int GetShapeF0D::operator()(Interface0DIterator& iter) +int GetShapeF0D::operator()(Interface0DIterator &iter) { - result = getShapeF0D(iter); - return 0; + result = getShapeF0D(iter); + return 0; } -int GetOccludeeF0D::operator()(Interface0DIterator& iter) +int GetOccludeeF0D::operator()(Interface0DIterator &iter) { - result = getOccludeeF0D(iter); - return 0; + result = getOccludeeF0D(iter); + return 0; } -} // end of namespace Functions0D +} // end of namespace Functions0D } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/view_map/Functions0D.h b/source/blender/freestyle/intern/view_map/Functions0D.h index 108a124fe78..ecf94b29d60 100644 --- a/source/blender/freestyle/intern/view_map/Functions0D.h +++ b/source/blender/freestyle/intern/view_map/Functions0D.h @@ -37,7 +37,7 @@ #include "../system/Precision.h" #ifdef WITH_CXX_GUARDEDALLOC -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif namespace Freestyle { @@ -70,44 +70,44 @@ using namespace Geometry; * - UnaryFunction0DViewShape * - UnaryFunction0DVoid */ -template <class T> -class UnaryFunction0D -{ -public: - T result; - void *py_uf0D; - - /*! The type of the value returned by the functor. */ - typedef T ReturnedValueType; - - /*! Default constructor. */ - UnaryFunction0D() - { - py_uf0D = NULL; - } - - /*! Destructor; */ - virtual ~UnaryFunction0D() {} - - /*! Returns the string "UnaryFunction0D" */ - virtual string getName() const - { - return "UnaryFunction0D"; - } - - /*! The operator (). - * \param iter: - * An Interface0DIterator pointing onto the point at which we wish to evaluate the function. - * \return the result of the function of type T. - */ - /* FIXME move the implementation to Functions0D.cpp */ - virtual int operator()(Interface0DIterator& iter) - { - return Director_BPy_UnaryFunction0D___call__(this, py_uf0D, iter); - } +template<class T> class UnaryFunction0D { + public: + T result; + void *py_uf0D; + + /*! The type of the value returned by the functor. */ + typedef T ReturnedValueType; + + /*! Default constructor. */ + UnaryFunction0D() + { + py_uf0D = NULL; + } + + /*! Destructor; */ + virtual ~UnaryFunction0D() + { + } + + /*! Returns the string "UnaryFunction0D" */ + virtual string getName() const + { + return "UnaryFunction0D"; + } + + /*! The operator (). + * \param iter: + * An Interface0DIterator pointing onto the point at which we wish to evaluate the function. + * \return the result of the function of type T. + */ + /* FIXME move the implementation to Functions0D.cpp */ + virtual int operator()(Interface0DIterator &iter) + { + return Director_BPy_UnaryFunction0D___call__(this, py_uf0D, iter); + } #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:UnaryFunction0D") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:UnaryFunction0D") #endif }; @@ -129,7 +129,7 @@ public: %template(UnaryFunction0DId) UnaryFunction0D<Id>; %template(UnaryFunction0DViewShape) UnaryFunction0D<ViewShape*>; %template(UnaryFunction0DVectorViewShape) UnaryFunction0D<std::vector<ViewShape*> >; -#endif // SWIG +#endif // SWIG // // Functions definitions @@ -141,205 +141,194 @@ namespace Functions0D { // GetXF0D /*! Returns the X 3D coordinate of an Interface0D. */ -class GetXF0D : public UnaryFunction0D<double> -{ -public: - /*! Returns the string "GetXF0D" */ - string getName() const - { - return "GetXF0D"; - } - - /*! the () operator. */ - int operator()(Interface0DIterator& iter) - { - result = iter->getX(); - return 0; - } +class GetXF0D : public UnaryFunction0D<double> { + public: + /*! Returns the string "GetXF0D" */ + string getName() const + { + return "GetXF0D"; + } + + /*! the () operator. */ + int operator()(Interface0DIterator &iter) + { + result = iter->getX(); + return 0; + } }; // GetYF0D /*! Returns the Y 3D coordinate of an Interface0D. */ -class GetYF0D : public UnaryFunction0D<double> -{ -public: - /*! Returns the string "GetYF0D" */ - string getName() const - { - return "GetYF0D"; - } - - /*! the () operator. */ - int operator()(Interface0DIterator& iter) - { - result = iter->getY(); - return 0; - } +class GetYF0D : public UnaryFunction0D<double> { + public: + /*! Returns the string "GetYF0D" */ + string getName() const + { + return "GetYF0D"; + } + + /*! the () operator. */ + int operator()(Interface0DIterator &iter) + { + result = iter->getY(); + return 0; + } }; // GetZF0D /*! Returns the Z 3D coordinate of an Interface0D. */ -class GetZF0D : public UnaryFunction0D<double> -{ -public: - /*! Returns the string "GetZF0D" */ - string getName() const - { - return "GetZF0D"; - } - - /*! the () operator. */ - int operator()(Interface0DIterator& iter) - { - result = iter->getZ(); - return 0; - } +class GetZF0D : public UnaryFunction0D<double> { + public: + /*! Returns the string "GetZF0D" */ + string getName() const + { + return "GetZF0D"; + } + + /*! the () operator. */ + int operator()(Interface0DIterator &iter) + { + result = iter->getZ(); + return 0; + } }; // GetProjectedXF0D /*! Returns the X 3D projected coordinate of an Interface0D. */ -class GetProjectedXF0D : public UnaryFunction0D<double> -{ -public: - /*! Returns the string "GetProjectedXF0D" */ - string getName() const - { - return "GetProjectedXF0D"; - } - - /*! the () operator. */ - int operator()(Interface0DIterator& iter) - { - result = iter->getProjectedX(); - return 0; - } +class GetProjectedXF0D : public UnaryFunction0D<double> { + public: + /*! Returns the string "GetProjectedXF0D" */ + string getName() const + { + return "GetProjectedXF0D"; + } + + /*! the () operator. */ + int operator()(Interface0DIterator &iter) + { + result = iter->getProjectedX(); + return 0; + } }; // GetProjectedYF0D /*! Returns the Y projected 3D coordinate of an Interface0D. */ -class GetProjectedYF0D : public UnaryFunction0D<double> -{ -public: - /*! Returns the string "GetProjectedYF0D" */ - string getName() const - { - return "GetProjectedYF0D"; - } - - /*! the () operator. */ - int operator()(Interface0DIterator& iter) - { - result = iter->getProjectedY(); - return 0; - } +class GetProjectedYF0D : public UnaryFunction0D<double> { + public: + /*! Returns the string "GetProjectedYF0D" */ + string getName() const + { + return "GetProjectedYF0D"; + } + + /*! the () operator. */ + int operator()(Interface0DIterator &iter) + { + result = iter->getProjectedY(); + return 0; + } }; // GetProjectedZF0D /*! Returns the Z projected 3D coordinate of an Interface0D. */ -class GetProjectedZF0D : public UnaryFunction0D<double> -{ -public: - /*! Returns the string "GetProjectedZF0D" */ - string getName() const - { - return "GetProjectedZF0D"; - } - - /*! the () operator. */ - int operator()(Interface0DIterator& iter) - { - result = iter->getProjectedZ(); - return 0; - } +class GetProjectedZF0D : public UnaryFunction0D<double> { + public: + /*! Returns the string "GetProjectedZF0D" */ + string getName() const + { + return "GetProjectedZF0D"; + } + + /*! the () operator. */ + int operator()(Interface0DIterator &iter) + { + result = iter->getProjectedZ(); + return 0; + } }; // GetCurvilinearAbscissaF0D /*! Returns the curvilinear abscissa of an Interface0D in the context of its 1D element. */ -class GetCurvilinearAbscissaF0D : public UnaryFunction0D<float> -{ -public: - /*! Returns the string "GetCurvilinearAbscissaF0D" */ - string getName() const - { - return "GetCurvilinearAbscissaF0D"; - } - - /*! the () operator. */ - int operator()(Interface0DIterator& iter) - { - result = iter.t(); - return 0; - } +class GetCurvilinearAbscissaF0D : public UnaryFunction0D<float> { + public: + /*! Returns the string "GetCurvilinearAbscissaF0D" */ + string getName() const + { + return "GetCurvilinearAbscissaF0D"; + } + + /*! the () operator. */ + int operator()(Interface0DIterator &iter) + { + result = iter.t(); + return 0; + } }; // GetParameterF0D /*! Returns the parameter of an Interface0D in the context of its 1D element. */ -class GetParameterF0D : public UnaryFunction0D<float> -{ -public: - /*! Returns the string "GetCurvilinearAbscissaF0D" */ - string getName() const - { - return "GetParameterF0D"; - } - - /*! the () operator. */ - int operator()(Interface0DIterator& iter) - { - result = iter.u(); - return 0; - } +class GetParameterF0D : public UnaryFunction0D<float> { + public: + /*! Returns the string "GetCurvilinearAbscissaF0D" */ + string getName() const + { + return "GetParameterF0D"; + } + + /*! the () operator. */ + int operator()(Interface0DIterator &iter) + { + result = iter.u(); + return 0; + } }; // VertexOrientation2DF0D /*! Returns a Vec2r giving the 2D oriented tangent to the 1D element to which the Interface0DIterator& belongs to and * evaluated at the Interface0D pointed by this Interface0DIterator&. */ -class VertexOrientation2DF0D : public UnaryFunction0D<Vec2f> -{ -public: - /*! Returns the string "VertexOrientation2DF0D" */ - string getName() const - { - return "VertexOrientation2DF0D"; - } - - /*! the () operator. */ - int operator()(Interface0DIterator& iter); +class VertexOrientation2DF0D : public UnaryFunction0D<Vec2f> { + public: + /*! Returns the string "VertexOrientation2DF0D" */ + string getName() const + { + return "VertexOrientation2DF0D"; + } + + /*! the () operator. */ + int operator()(Interface0DIterator &iter); }; // VertexOrientation3DF0D /*! Returns a Vec3r giving the 3D oriented tangent to the 1D element to which the Interface0DIterator& belongs to and * evaluated at the Interface0D pointed by this Interface0DIterator&. */ -class VertexOrientation3DF0D : public UnaryFunction0D<Vec3f> -{ -public: - /*! Returns the string "VertexOrientation3DF0D" */ - string getName() const - { - return "VertexOrientation3DF0D"; - } - - /*! the () operator. */ - int operator()(Interface0DIterator& iter); +class VertexOrientation3DF0D : public UnaryFunction0D<Vec3f> { + public: + /*! Returns the string "VertexOrientation3DF0D" */ + string getName() const + { + return "VertexOrientation3DF0D"; + } + + /*! the () operator. */ + int operator()(Interface0DIterator &iter); }; // Curvature2DAngleF0D /*! Returns a real giving the 2D curvature (as an angle) of the 1D element to which the Interface0DIterator& * belongs to and evaluated at the Interface0D pointed by this Interface0DIterator&. */ -class Curvature2DAngleF0D : public UnaryFunction0D<double> -{ -public: - /*! Returns the string "Curvature2DAngleF0D" */ - string getName() const - { - return "Curvature2DAngleF0D"; - } - - /*! the () operator. */ - int operator()(Interface0DIterator& iter); +class Curvature2DAngleF0D : public UnaryFunction0D<double> { + public: + /*! Returns the string "Curvature2DAngleF0D" */ + string getName() const + { + return "Curvature2DAngleF0D"; + } + + /*! the () operator. */ + int operator()(Interface0DIterator &iter); }; // ZDiscontinuity @@ -347,34 +336,32 @@ public: * This distance is evaluated in the camera space and normalized between 0 and 1. Therefore, if no object is occluded * by the shape to which the Interface0D belongs to, 1 is returned. */ -class ZDiscontinuityF0D : public UnaryFunction0D<double> -{ -public: - /*! Returns the string "ZDiscontinuityF0D" */ - string getName() const - { - return "ZDiscontinuityF0D"; - } - - /*! the () operator. */ - int operator()(Interface0DIterator& iter); +class ZDiscontinuityF0D : public UnaryFunction0D<double> { + public: + /*! Returns the string "ZDiscontinuityF0D" */ + string getName() const + { + return "ZDiscontinuityF0D"; + } + + /*! the () operator. */ + int operator()(Interface0DIterator &iter); }; // Normal2DF0D /*! Returns a Vec2f giving the normalized 2D normal to the 1D element to which the Interface0DIterator& belongs to and * evaluated at the Interface0D pointed by this Interface0DIterator&. */ -class Normal2DF0D : public UnaryFunction0D<Vec2f> -{ -public: - /*! Returns the string "Normal2DF0D" */ - string getName() const - { - return "Normal2DF0D"; - } - - /*! the () operator. */ - int operator()(Interface0DIterator& iter); +class Normal2DF0D : public UnaryFunction0D<Vec2f> { + public: + /*! Returns the string "Normal2DF0D" */ + string getName() const + { + return "Normal2DF0D"; + } + + /*! the () operator. */ + int operator()(Interface0DIterator &iter); }; // MaterialF0D @@ -386,17 +373,16 @@ public: * However, there still can be problematic cases, and the user willing to deal with this cases in a specific way * should implement its own getMaterial functor. */ -class MaterialF0D : public UnaryFunction0D<FrsMaterial> -{ -public: - /*! Returns the string "MaterialF0D" */ - string getName() const - { - return "MaterialF0D"; - } - - /*! the () operator. */ - int operator()(Interface0DIterator& iter); +class MaterialF0D : public UnaryFunction0D<FrsMaterial> { + public: + /*! Returns the string "MaterialF0D" */ + string getName() const + { + return "MaterialF0D"; + } + + /*! the () operator. */ + int operator()(Interface0DIterator &iter); }; // ShapeIdF0D @@ -407,17 +393,16 @@ public: * However, there still can be problematic cases, and the user willing to deal with this cases in a specific way * should implement its own getShapeIdF0D functor. */ -class ShapeIdF0D : public UnaryFunction0D<Id> -{ -public: - /*! Returns the string "ShapeIdF0D" */ - string getName() const - { - return "ShapeIdF0D"; - } - - /*! the () operator. */ - int operator()(Interface0DIterator& iter); +class ShapeIdF0D : public UnaryFunction0D<Id> { + public: + /*! Returns the string "ShapeIdF0D" */ + string getName() const + { + return "ShapeIdF0D"; + } + + /*! the () operator. */ + int operator()(Interface0DIterator &iter); }; // QiF0D @@ -428,102 +413,96 @@ public: * However, there still can be problematic cases, and the user willing to deal with this cases in a specific way * should implement its own getQIF0D functor. */ -class QuantitativeInvisibilityF0D : public UnaryFunction0D<unsigned int> -{ -public: - /*! Returns the string "QuantitativeInvisibilityF0D" */ - string getName() const - { - return "QuantitativeInvisibilityF0D"; - } - - /*! the () operator. */ - int operator()(Interface0DIterator& iter); +class QuantitativeInvisibilityF0D : public UnaryFunction0D<unsigned int> { + public: + /*! Returns the string "QuantitativeInvisibilityF0D" */ + string getName() const + { + return "QuantitativeInvisibilityF0D"; + } + + /*! the () operator. */ + int operator()(Interface0DIterator &iter); }; // CurveNatureF0D /*! Returns the Nature::EdgeNature of the 1D element the Interface0DIterator& belongs to. */ -class CurveNatureF0D : public UnaryFunction0D<Nature::EdgeNature> -{ -public: - /*! Returns the string "QuantitativeInvisibilityF0D" */ - string getName() const - { - return "CurveNatureF0D"; - } - - /*! the () operator. */ - int operator()(Interface0DIterator& iter); +class CurveNatureF0D : public UnaryFunction0D<Nature::EdgeNature> { + public: + /*! Returns the string "QuantitativeInvisibilityF0D" */ + string getName() const + { + return "CurveNatureF0D"; + } + + /*! the () operator. */ + int operator()(Interface0DIterator &iter); }; // GetShapeF0D /*! Returns the ViewShape* containing the Interface0D */ -class GetShapeF0D : public UnaryFunction0D< ViewShape*> -{ -public: - /*! Returns the string "GetShapeF0D" */ - string getName() const - { - return "GetShapeF0D"; - } - - /*! the () operator. */ - int operator()(Interface0DIterator& iter); +class GetShapeF0D : public UnaryFunction0D<ViewShape *> { + public: + /*! Returns the string "GetShapeF0D" */ + string getName() const + { + return "GetShapeF0D"; + } + + /*! the () operator. */ + int operator()(Interface0DIterator &iter); }; // GetOccludersF0D /*! Returns a vector containing the ViewShape* occluding the Interface0D */ -class GetOccludersF0D : public UnaryFunction0D< std::vector<ViewShape*> > -{ -public: - /*! Returns the string "GetOccludersF0D" */ - string getName() const - { - return "GetOccludersF0D"; - } - - /*! the () operator. */ - int operator()(Interface0DIterator& iter); +class GetOccludersF0D : public UnaryFunction0D<std::vector<ViewShape *>> { + public: + /*! Returns the string "GetOccludersF0D" */ + string getName() const + { + return "GetOccludersF0D"; + } + + /*! the () operator. */ + int operator()(Interface0DIterator &iter); }; // GetOccludeeF0D /*! Returns the ViewShape* "occluded" by the Interface0D */ -class GetOccludeeF0D: public UnaryFunction0D< ViewShape*> -{ -public: - /*! Returns the string "GetOccludeeF0D" */ - string getName() const - { - return "GetOccludeeF0D"; - } - - /*! the () operator. */ - int operator()(Interface0DIterator& iter); +class GetOccludeeF0D : public UnaryFunction0D<ViewShape *> { + public: + /*! Returns the string "GetOccludeeF0D" */ + string getName() const + { + return "GetOccludeeF0D"; + } + + /*! the () operator. */ + int operator()(Interface0DIterator &iter); }; - /////////////////////////// Internal //////////////////////////// // getFEdge -FEdge *getFEdge(Interface0D& it1, Interface0D& it2); +FEdge *getFEdge(Interface0D &it1, Interface0D &it2); // getFEdges -void getFEdges(Interface0DIterator& it, FEdge *&fe1, FEdge *&fe2); +void getFEdges(Interface0DIterator &it, FEdge *&fe1, FEdge *&fe2); // getViewEdges -void getViewEdges(Interface0DIterator& it, ViewEdge *&ve1, ViewEdge *&ve2); +void getViewEdges(Interface0DIterator &it, ViewEdge *&ve1, ViewEdge *&ve2); // getShapeF0D -ViewShape *getShapeF0D(Interface0DIterator& it); +ViewShape *getShapeF0D(Interface0DIterator &it); // getOccludersF0D -void getOccludersF0D(Interface0DIterator& it, std::set<ViewShape*>& oOccluders); +void getOccludersF0D(Interface0DIterator &it, std::set<ViewShape *> &oOccluders); // getOccludeeF0D -ViewShape *getOccludeeF0D(Interface0DIterator& it); +ViewShape *getOccludeeF0D(Interface0DIterator &it); -} // end of namespace Functions0D +} // end of namespace Functions0D } /* namespace Freestyle */ -#endif // __FREESTYLE_FUNCTIONS_0D_H__ +#endif // __FREESTYLE_FUNCTIONS_0D_H__ diff --git a/source/blender/freestyle/intern/view_map/Functions1D.cpp b/source/blender/freestyle/intern/view_map/Functions1D.cpp index 31f3b65a2b7..0c0ab9fd631 100644 --- a/source/blender/freestyle/intern/view_map/Functions1D.cpp +++ b/source/blender/freestyle/intern/view_map/Functions1D.cpp @@ -27,237 +27,239 @@ namespace Freestyle { namespace Functions1D { -int GetXF1D::operator()(Interface1D& inter) +int GetXF1D::operator()(Interface1D &inter) { - result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); - return 0; + result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); + return 0; } -int GetYF1D::operator()(Interface1D& inter) +int GetYF1D::operator()(Interface1D &inter) { - result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); - return 0; + result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); + return 0; } -int GetZF1D::operator()(Interface1D& inter) +int GetZF1D::operator()(Interface1D &inter) { - result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); - return 0; + result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); + return 0; } -int GetProjectedXF1D::operator()(Interface1D& inter) +int GetProjectedXF1D::operator()(Interface1D &inter) { - result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); - return 0; + result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); + return 0; } -int GetProjectedYF1D::operator()(Interface1D& inter) +int GetProjectedYF1D::operator()(Interface1D &inter) { - result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); - return 0; + result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); + return 0; } -int GetProjectedZF1D::operator()(Interface1D& inter) +int GetProjectedZF1D::operator()(Interface1D &inter) { - result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); - return 0; + result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); + return 0; } -int Orientation2DF1D::operator()(Interface1D& inter) +int Orientation2DF1D::operator()(Interface1D &inter) { - FEdge *fe = dynamic_cast<FEdge*>(&inter); - if (fe) { - Vec3r res = fe->orientation2d(); - result = Vec2f(res[0], res[1]); - } - else { - result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); - } - return 0; + FEdge *fe = dynamic_cast<FEdge *>(&inter); + if (fe) { + Vec3r res = fe->orientation2d(); + result = Vec2f(res[0], res[1]); + } + else { + result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); + } + return 0; } -int Orientation3DF1D::operator()(Interface1D& inter) +int Orientation3DF1D::operator()(Interface1D &inter) { - result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); - return 0; + result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); + return 0; } -int ZDiscontinuityF1D::operator()(Interface1D& inter) +int ZDiscontinuityF1D::operator()(Interface1D &inter) { - result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); - return 0; + result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); + return 0; } -int QuantitativeInvisibilityF1D::operator()(Interface1D& inter) +int QuantitativeInvisibilityF1D::operator()(Interface1D &inter) { - ViewEdge *ve = dynamic_cast<ViewEdge*>(&inter); - if (ve) { - result = ve->qi(); - return 0; - } - FEdge *fe = dynamic_cast<FEdge*>(&inter); - if (fe) { - result = fe->qi(); - return 0; - } - result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); - return 0; + ViewEdge *ve = dynamic_cast<ViewEdge *>(&inter); + if (ve) { + result = ve->qi(); + return 0; + } + FEdge *fe = dynamic_cast<FEdge *>(&inter); + if (fe) { + result = fe->qi(); + return 0; + } + result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); + return 0; } -int CurveNatureF1D::operator()(Interface1D& inter) +int CurveNatureF1D::operator()(Interface1D &inter) { - ViewEdge *ve = dynamic_cast<ViewEdge*>(&inter); - if (ve) { - result = ve->getNature(); - } - else { - // we return a nature that contains every natures of the viewedges spanned by the chain. - Nature::EdgeNature nat = Nature::NO_FEATURE; - Interface0DIterator it = inter.verticesBegin(); - while (!it.isEnd()) { - nat |= _func(it); - ++it; - } - result = nat; - } - return 0; + ViewEdge *ve = dynamic_cast<ViewEdge *>(&inter); + if (ve) { + result = ve->getNature(); + } + else { + // we return a nature that contains every natures of the viewedges spanned by the chain. + Nature::EdgeNature nat = Nature::NO_FEATURE; + Interface0DIterator it = inter.verticesBegin(); + while (!it.isEnd()) { + nat |= _func(it); + ++it; + } + result = nat; + } + return 0; } -int TimeStampF1D::operator()(Interface1D& inter) +int TimeStampF1D::operator()(Interface1D &inter) { - TimeStamp *timestamp = TimeStamp::instance(); - inter.setTimeStamp(timestamp->getTimeStamp()); - return 0; + TimeStamp *timestamp = TimeStamp::instance(); + inter.setTimeStamp(timestamp->getTimeStamp()); + return 0; } -int ChainingTimeStampF1D::operator()(Interface1D& inter) +int ChainingTimeStampF1D::operator()(Interface1D &inter) { - TimeStamp *timestamp = TimeStamp::instance(); - ViewEdge *ve = dynamic_cast<ViewEdge*>(&inter); - if (ve) - ve->setChainingTimeStamp(timestamp->getTimeStamp()); - return 0; + TimeStamp *timestamp = TimeStamp::instance(); + ViewEdge *ve = dynamic_cast<ViewEdge *>(&inter); + if (ve) + ve->setChainingTimeStamp(timestamp->getTimeStamp()); + return 0; } -int IncrementChainingTimeStampF1D::operator()(Interface1D& inter) +int IncrementChainingTimeStampF1D::operator()(Interface1D &inter) { - ViewEdge *ve = dynamic_cast<ViewEdge*>(&inter); - if (ve) - ve->setChainingTimeStamp(ve->getChainingTimeStamp() + 1); - return 0; + ViewEdge *ve = dynamic_cast<ViewEdge *>(&inter); + if (ve) + ve->setChainingTimeStamp(ve->getChainingTimeStamp() + 1); + return 0; } -int GetShapeF1D::operator()(Interface1D& inter) +int GetShapeF1D::operator()(Interface1D &inter) { - vector<ViewShape*> shapesVector; - set<ViewShape*> shapesSet; - ViewEdge *ve = dynamic_cast<ViewEdge*>(&inter); - if (ve) { - shapesVector.push_back(ve->viewShape()); - } - else { - Interface0DIterator it = inter.verticesBegin(), itend = inter.verticesEnd(); - for (; it != itend; ++it) - shapesSet.insert(Functions0D::getShapeF0D(it)); - shapesVector.insert<set<ViewShape*>::iterator>(shapesVector.begin(), shapesSet.begin(), shapesSet.end()); - } - result = shapesVector; - return 0; + vector<ViewShape *> shapesVector; + set<ViewShape *> shapesSet; + ViewEdge *ve = dynamic_cast<ViewEdge *>(&inter); + if (ve) { + shapesVector.push_back(ve->viewShape()); + } + else { + Interface0DIterator it = inter.verticesBegin(), itend = inter.verticesEnd(); + for (; it != itend; ++it) + shapesSet.insert(Functions0D::getShapeF0D(it)); + shapesVector.insert<set<ViewShape *>::iterator>( + shapesVector.begin(), shapesSet.begin(), shapesSet.end()); + } + result = shapesVector; + return 0; } -int GetOccludersF1D::operator()(Interface1D& inter) +int GetOccludersF1D::operator()(Interface1D &inter) { - vector<ViewShape*> shapesVector; - set<ViewShape*> shapesSet; - ViewEdge *ve = dynamic_cast<ViewEdge*>(&inter); - if (ve) { - result = ve->occluders(); - } - else { - Interface0DIterator it = inter.verticesBegin(), itend = inter.verticesEnd(); - for (; it != itend; ++it) { - Functions0D::getOccludersF0D(it, shapesSet); - } - shapesVector.insert(shapesVector.begin(), shapesSet.begin(), shapesSet.end()); - result = shapesVector; - } - return 0; + vector<ViewShape *> shapesVector; + set<ViewShape *> shapesSet; + ViewEdge *ve = dynamic_cast<ViewEdge *>(&inter); + if (ve) { + result = ve->occluders(); + } + else { + Interface0DIterator it = inter.verticesBegin(), itend = inter.verticesEnd(); + for (; it != itend; ++it) { + Functions0D::getOccludersF0D(it, shapesSet); + } + shapesVector.insert(shapesVector.begin(), shapesSet.begin(), shapesSet.end()); + result = shapesVector; + } + return 0; } -int GetOccludeeF1D::operator()(Interface1D& inter) +int GetOccludeeF1D::operator()(Interface1D &inter) { - vector<ViewShape*> shapesVector; - set<ViewShape*> shapesSet; - ViewEdge *ve = dynamic_cast<ViewEdge*>(&inter); - if (ve) { - ViewShape *aShape = ve->aShape(); - if (aShape) { - shapesVector.push_back(aShape); - } - } - else { - Interface0DIterator it = inter.verticesBegin(), itend = inter.verticesEnd(); - for (; it != itend; ++it) { - shapesSet.insert(Functions0D::getOccludeeF0D(it)); - } - shapesVector.insert<set<ViewShape*>::iterator>(shapesVector.begin(), shapesSet.begin(), shapesSet.end()); - } - result = shapesVector; - return 0; + vector<ViewShape *> shapesVector; + set<ViewShape *> shapesSet; + ViewEdge *ve = dynamic_cast<ViewEdge *>(&inter); + if (ve) { + ViewShape *aShape = ve->aShape(); + if (aShape) { + shapesVector.push_back(aShape); + } + } + else { + Interface0DIterator it = inter.verticesBegin(), itend = inter.verticesEnd(); + for (; it != itend; ++it) { + shapesSet.insert(Functions0D::getOccludeeF0D(it)); + } + shapesVector.insert<set<ViewShape *>::iterator>( + shapesVector.begin(), shapesSet.begin(), shapesSet.end()); + } + result = shapesVector; + return 0; } // Internal //////////// -void getOccludeeF1D(Interface1D& inter, set<ViewShape*>& oShapes) +void getOccludeeF1D(Interface1D &inter, set<ViewShape *> &oShapes) { - ViewEdge *ve = dynamic_cast<ViewEdge*>(&inter); - if (ve) { - ViewShape *aShape = ve->aShape(); - if (aShape == 0) { - oShapes.insert((ViewShape*)0); - return; - } - oShapes.insert(aShape); - } - else { - Interface0DIterator it = inter.verticesBegin(), itend = inter.verticesEnd(); - for (; it != itend; ++it) - oShapes.insert(Functions0D::getOccludeeF0D(it)); - } + ViewEdge *ve = dynamic_cast<ViewEdge *>(&inter); + if (ve) { + ViewShape *aShape = ve->aShape(); + if (aShape == 0) { + oShapes.insert((ViewShape *)0); + return; + } + oShapes.insert(aShape); + } + else { + Interface0DIterator it = inter.verticesBegin(), itend = inter.verticesEnd(); + for (; it != itend; ++it) + oShapes.insert(Functions0D::getOccludeeF0D(it)); + } } -void getOccludersF1D(Interface1D& inter, set<ViewShape*>& oShapes) +void getOccludersF1D(Interface1D &inter, set<ViewShape *> &oShapes) { - ViewEdge *ve = dynamic_cast<ViewEdge*>(&inter); - if (ve) { - vector<ViewShape*>& occluders = ve->occluders(); - oShapes.insert<vector<ViewShape*>::iterator>(occluders.begin(), occluders.end()); - } - else { - Interface0DIterator it = inter.verticesBegin(), itend = inter.verticesEnd(); - for (; it != itend; ++it) { - set<ViewShape*> shapes; - Functions0D::getOccludersF0D(it, shapes); - for (set<ViewShape*>::iterator s = shapes.begin(), send = shapes.end(); s != send; ++s) - oShapes.insert(*s); - } - } + ViewEdge *ve = dynamic_cast<ViewEdge *>(&inter); + if (ve) { + vector<ViewShape *> &occluders = ve->occluders(); + oShapes.insert<vector<ViewShape *>::iterator>(occluders.begin(), occluders.end()); + } + else { + Interface0DIterator it = inter.verticesBegin(), itend = inter.verticesEnd(); + for (; it != itend; ++it) { + set<ViewShape *> shapes; + Functions0D::getOccludersF0D(it, shapes); + for (set<ViewShape *>::iterator s = shapes.begin(), send = shapes.end(); s != send; ++s) + oShapes.insert(*s); + } + } } -void getShapeF1D(Interface1D& inter, set<ViewShape*>& oShapes) +void getShapeF1D(Interface1D &inter, set<ViewShape *> &oShapes) { - ViewEdge *ve = dynamic_cast<ViewEdge*>(&inter); - if (ve) { - oShapes.insert(ve->viewShape()); - } - else { - Interface0DIterator it = inter.verticesBegin(), itend = inter.verticesEnd(); - for (; it != itend; ++it) - oShapes.insert(Functions0D::getShapeF0D(it)); - } + ViewEdge *ve = dynamic_cast<ViewEdge *>(&inter); + if (ve) { + oShapes.insert(ve->viewShape()); + } + else { + Interface0DIterator it = inter.verticesBegin(), itend = inter.verticesEnd(); + for (; it != itend; ++it) + oShapes.insert(Functions0D::getShapeF0D(it)); + } } -} // end of namespace Functions1D +} // end of namespace Functions1D } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/view_map/Functions1D.h b/source/blender/freestyle/intern/view_map/Functions1D.h index 9101e380a40..581ab9c459a 100644 --- a/source/blender/freestyle/intern/view_map/Functions1D.h +++ b/source/blender/freestyle/intern/view_map/Functions1D.h @@ -33,7 +33,7 @@ #include "../python/Director.h" #ifdef WITH_CXX_GUARDEDALLOC -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif namespace Freestyle { @@ -57,121 +57,120 @@ namespace Freestyle { * - UnaryFunction1DVectorViewShape * - UnaryFunction1DVoid */ -template <class T> -class UnaryFunction1D -{ -public: - T result; - void *py_uf1D; - - /*! The type of the value returned by the functor. */ - typedef T ReturnedValueType; - - /*! Default constructor */ - UnaryFunction1D() - { - _integration = MEAN; - } - - /*! Builds a UnaryFunction1D from an integration type. - * \param iType: - * In case the result for the Interface1D would be obtained by evaluating a 0D function over the different - * Interface0D of the Interface1D, \a iType tells which integration method to use. - * The default integration method is the MEAN. - */ - UnaryFunction1D(IntegrationType iType) - { - _integration = iType; - } - - /*! destructor. */ - virtual ~UnaryFunction1D() {} - - /*! returns the string "UnaryFunction1D". */ - virtual string getName() const - { - return "UnaryFunction1D"; - } - - /*! The operator (). - * \param inter: - * The Interface1D on which we wish to evaluate the function. - * \return the result of the function of type T. - */ - /* FIXME move the implementation to Functions1D.cpp */ - virtual int operator()(Interface1D& inter) - { - return Director_BPy_UnaryFunction1D___call__(this, py_uf1D, inter); - } - - /*! Sets the integration method */ - void setIntegrationType(IntegrationType integration) - { - _integration = integration; - } - - /*! Returns the integration method. */ - IntegrationType getIntegrationType() const - { - return _integration; - } - -protected: - IntegrationType _integration; +template<class T> class UnaryFunction1D { + public: + T result; + void *py_uf1D; + + /*! The type of the value returned by the functor. */ + typedef T ReturnedValueType; + + /*! Default constructor */ + UnaryFunction1D() + { + _integration = MEAN; + } + + /*! Builds a UnaryFunction1D from an integration type. + * \param iType: + * In case the result for the Interface1D would be obtained by evaluating a 0D function over the different + * Interface0D of the Interface1D, \a iType tells which integration method to use. + * The default integration method is the MEAN. + */ + UnaryFunction1D(IntegrationType iType) + { + _integration = iType; + } + + /*! destructor. */ + virtual ~UnaryFunction1D() + { + } + + /*! returns the string "UnaryFunction1D". */ + virtual string getName() const + { + return "UnaryFunction1D"; + } + + /*! The operator (). + * \param inter: + * The Interface1D on which we wish to evaluate the function. + * \return the result of the function of type T. + */ + /* FIXME move the implementation to Functions1D.cpp */ + virtual int operator()(Interface1D &inter) + { + return Director_BPy_UnaryFunction1D___call__(this, py_uf1D, inter); + } + + /*! Sets the integration method */ + void setIntegrationType(IntegrationType integration) + { + _integration = integration; + } + + /*! Returns the integration method. */ + IntegrationType getIntegrationType() const + { + return _integration; + } + + protected: + IntegrationType _integration; #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:UnaryFunction1D") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:UnaryFunction1D") #endif }; +class UnaryFunction1D_void { + public: + void *py_uf1D; -class UnaryFunction1D_void -{ -public: - void *py_uf1D; + UnaryFunction1D_void() + { + _integration = MEAN; + } - UnaryFunction1D_void() - { - _integration = MEAN; - } + UnaryFunction1D_void(IntegrationType iType) + { + _integration = iType; + } - UnaryFunction1D_void(IntegrationType iType) - { - _integration = iType; - } + virtual ~UnaryFunction1D_void() + { + } - virtual ~UnaryFunction1D_void() {} + virtual string getName() const + { + return "UnaryFunction1D_void"; + } - virtual string getName() const - { - return "UnaryFunction1D_void"; - } + /* FIXME move the implementation to Functions1D.cpp */ + int operator()(Interface1D &inter) + { + return Director_BPy_UnaryFunction1D___call__(this, py_uf1D, inter); + } - /* FIXME move the implementation to Functions1D.cpp */ - int operator()(Interface1D& inter) - { - return Director_BPy_UnaryFunction1D___call__(this, py_uf1D, inter); - } + void setIntegrationType(IntegrationType integration) + { + _integration = integration; + } - void setIntegrationType(IntegrationType integration) - { - _integration = integration; - } + IntegrationType getIntegrationType() const + { + return _integration; + } - IntegrationType getIntegrationType() const - { - return _integration; - } - -protected: - IntegrationType _integration; + protected: + IntegrationType _integration; #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:UnaryFunction1D_void") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:UnaryFunction1D_void") #endif }; - // // Functions definitions // @@ -181,194 +180,202 @@ namespace Functions1D { // GetXF1D /*! Returns the X 3D coordinate of an Interface1D. */ -class GetXF1D : public UnaryFunction1D<double> -{ -private: - Functions0D::GetXF0D _func; - -public: - /*! Builds the functor. - * \param iType: - * The integration method used to compute a single value from a set of values. - */ - GetXF1D(IntegrationType iType) : UnaryFunction1D<double>(iType) {} - - /*! Returns the string "GetXF1D" */ - string getName() const - { - return "GetXF1D"; - } - - /*! the () operator. */ - int operator()(Interface1D& inter); +class GetXF1D : public UnaryFunction1D<double> { + private: + Functions0D::GetXF0D _func; + + public: + /*! Builds the functor. + * \param iType: + * The integration method used to compute a single value from a set of values. + */ + GetXF1D(IntegrationType iType) : UnaryFunction1D<double>(iType) + { + } + + /*! Returns the string "GetXF1D" */ + string getName() const + { + return "GetXF1D"; + } + + /*! the () operator. */ + int operator()(Interface1D &inter); }; // GetYF1D /*! Returns the Y 3D coordinate of an Interface1D. */ -class GetYF1D : public UnaryFunction1D<double> -{ -private: -Functions0D::GetYF0D _func; - -public: - /*! Builds the functor. - * \param iType: - * The integration method used to compute a single value from a set of values. - */ - GetYF1D(IntegrationType iType = MEAN) : UnaryFunction1D<double>(iType) {} - - /*! Returns the string "GetYF1D" */ - string getName() const - { - return "GetYF1D"; - } - - /*! the () operator. */ - int operator()(Interface1D& inter); +class GetYF1D : public UnaryFunction1D<double> { + private: + Functions0D::GetYF0D _func; + + public: + /*! Builds the functor. + * \param iType: + * The integration method used to compute a single value from a set of values. + */ + GetYF1D(IntegrationType iType = MEAN) : UnaryFunction1D<double>(iType) + { + } + + /*! Returns the string "GetYF1D" */ + string getName() const + { + return "GetYF1D"; + } + + /*! the () operator. */ + int operator()(Interface1D &inter); }; // GetZF1D /*! Returns the Z 3D coordinate of an Interface1D. */ -class GetZF1D : public UnaryFunction1D<double> -{ -private: - Functions0D::GetZF0D _func; - -public: - /*! Builds the functor. - * \param iType: - * The integration method used to compute a single value from a set of values. - */ - GetZF1D(IntegrationType iType = MEAN) : UnaryFunction1D<double>(iType) {} - - /*! Returns the string "GetZF1D" */ - string getName() const - { - return "GetZF1D"; - } - - /*! the () operator. */ - int operator()(Interface1D& inter); +class GetZF1D : public UnaryFunction1D<double> { + private: + Functions0D::GetZF0D _func; + + public: + /*! Builds the functor. + * \param iType: + * The integration method used to compute a single value from a set of values. + */ + GetZF1D(IntegrationType iType = MEAN) : UnaryFunction1D<double>(iType) + { + } + + /*! Returns the string "GetZF1D" */ + string getName() const + { + return "GetZF1D"; + } + + /*! the () operator. */ + int operator()(Interface1D &inter); }; // GetProjectedXF1D /*! Returns the projected X 3D coordinate of an Interface1D. */ -class GetProjectedXF1D : public UnaryFunction1D<double> -{ -private: - Functions0D::GetProjectedXF0D _func; - -public: - /*! Builds the functor. - * \param iType: - * The integration method used to compute a single value from a set of values. - */ - GetProjectedXF1D(IntegrationType iType = MEAN) : UnaryFunction1D<double>(iType) {} - - /*! Returns the string "GetProjectedXF1D" */ - string getName() const - { - return "GetProjectedXF1D"; - } - - /*! the () operator. */ - int operator()(Interface1D& inter); +class GetProjectedXF1D : public UnaryFunction1D<double> { + private: + Functions0D::GetProjectedXF0D _func; + + public: + /*! Builds the functor. + * \param iType: + * The integration method used to compute a single value from a set of values. + */ + GetProjectedXF1D(IntegrationType iType = MEAN) : UnaryFunction1D<double>(iType) + { + } + + /*! Returns the string "GetProjectedXF1D" */ + string getName() const + { + return "GetProjectedXF1D"; + } + + /*! the () operator. */ + int operator()(Interface1D &inter); }; // GetProjectedYF1D /*! Returns the projected Y 3D coordinate of an Interface1D. */ -class GetProjectedYF1D : public UnaryFunction1D<double> -{ -private: - Functions0D::GetProjectedYF0D _func; - -public: - /*! Builds the functor. - * \param iType: - * The integration method used to compute a single value from a set of values. - */ - GetProjectedYF1D(IntegrationType iType = MEAN) : UnaryFunction1D<double>(iType) {} - - /*! Returns the string "GetProjectedYF1D" */ - string getName() const - { - return "GetProjectedYF1D"; - } - - /*! the () operator. */ - int operator()(Interface1D& inter); +class GetProjectedYF1D : public UnaryFunction1D<double> { + private: + Functions0D::GetProjectedYF0D _func; + + public: + /*! Builds the functor. + * \param iType: + * The integration method used to compute a single value from a set of values. + */ + GetProjectedYF1D(IntegrationType iType = MEAN) : UnaryFunction1D<double>(iType) + { + } + + /*! Returns the string "GetProjectedYF1D" */ + string getName() const + { + return "GetProjectedYF1D"; + } + + /*! the () operator. */ + int operator()(Interface1D &inter); }; // GetProjectedZF1D /*! Returns the projected Z 3D coordinate of an Interface1D. */ -class GetProjectedZF1D : public UnaryFunction1D<double> -{ -private: - Functions0D::GetProjectedZF0D _func; - -public: - /*! Builds the functor. - * \param iType: - * The integration method used to compute a single value from a set of values. - */ - GetProjectedZF1D(IntegrationType iType = MEAN) : UnaryFunction1D<double>(iType) {} - - /*! Returns the string "GetProjectedZF1D" */ - string getName() const - { - return "GetProjectedZF1D"; - } - - /*! the () operator. */ - int operator()(Interface1D& inter); +class GetProjectedZF1D : public UnaryFunction1D<double> { + private: + Functions0D::GetProjectedZF0D _func; + + public: + /*! Builds the functor. + * \param iType: + * The integration method used to compute a single value from a set of values. + */ + GetProjectedZF1D(IntegrationType iType = MEAN) : UnaryFunction1D<double>(iType) + { + } + + /*! Returns the string "GetProjectedZF1D" */ + string getName() const + { + return "GetProjectedZF1D"; + } + + /*! the () operator. */ + int operator()(Interface1D &inter); }; // Orientation2DF1D /*! Returns the 2D orientation as a Vec2f*/ -class Orientation2DF1D : public UnaryFunction1D<Vec2f> -{ -private: - Functions0D::VertexOrientation2DF0D _func; - -public: - /*! Builds the functor. - * \param iType: - * The integration method used to compute a single value from a set of values. - */ - Orientation2DF1D(IntegrationType iType = MEAN) : UnaryFunction1D<Vec2f>(iType) {} - - /*! Returns the string "Orientation2DF1D" */ - string getName() const - { - return "Orientation2DF1D"; - } - - /*! the () operator. */ - int operator()(Interface1D& inter); +class Orientation2DF1D : public UnaryFunction1D<Vec2f> { + private: + Functions0D::VertexOrientation2DF0D _func; + + public: + /*! Builds the functor. + * \param iType: + * The integration method used to compute a single value from a set of values. + */ + Orientation2DF1D(IntegrationType iType = MEAN) : UnaryFunction1D<Vec2f>(iType) + { + } + + /*! Returns the string "Orientation2DF1D" */ + string getName() const + { + return "Orientation2DF1D"; + } + + /*! the () operator. */ + int operator()(Interface1D &inter); }; // Orientation3DF1D /*! Returns the 3D orientation as a Vec3f. */ -class Orientation3DF1D : public UnaryFunction1D<Vec3f> -{ -private: - Functions0D::VertexOrientation3DF0D _func; - -public: - /*! Builds the functor. - * \param iType: - * The integration method used to compute a single value from a set of values. - */ - Orientation3DF1D(IntegrationType iType = MEAN) : UnaryFunction1D<Vec3f>(iType) {} - - /*! Returns the string "Orientation3DF1D" */ - string getName() const - { - return "Orientation3DF1D"; - } - - /*! the () operator. */ - int operator()(Interface1D& inter); +class Orientation3DF1D : public UnaryFunction1D<Vec3f> { + private: + Functions0D::VertexOrientation3DF0D _func; + + public: + /*! Builds the functor. + * \param iType: + * The integration method used to compute a single value from a set of values. + */ + Orientation3DF1D(IntegrationType iType = MEAN) : UnaryFunction1D<Vec3f>(iType) + { + } + + /*! Returns the string "Orientation3DF1D" */ + string getName() const + { + return "Orientation3DF1D"; + } + + /*! the () operator. */ + int operator()(Interface1D &inter); }; // ZDiscontinuityF1D @@ -376,26 +383,27 @@ public: * This distance is evaluated in the camera space and normalized between 0 and 1. Therefore, if no object is occluded * by the shape to which the Interface1D belongs to, 1 is returned. */ -class ZDiscontinuityF1D : public UnaryFunction1D<double> -{ -private: - Functions0D::ZDiscontinuityF0D _func; - -public: - /*! Builds the functor. - * \param iType: - * The integration method used to compute a single value from a set of values. - */ - ZDiscontinuityF1D(IntegrationType iType = MEAN) : UnaryFunction1D<double>(iType) {} - - /*! Returns the string "ZDiscontinuityF1D" */ - string getName() const - { - return "ZDiscontinuityF1D"; - } - - /*! the () operator. */ - int operator()(Interface1D& inter); +class ZDiscontinuityF1D : public UnaryFunction1D<double> { + private: + Functions0D::ZDiscontinuityF0D _func; + + public: + /*! Builds the functor. + * \param iType: + * The integration method used to compute a single value from a set of values. + */ + ZDiscontinuityF1D(IntegrationType iType = MEAN) : UnaryFunction1D<double>(iType) + { + } + + /*! Returns the string "ZDiscontinuityF1D" */ + string getName() const + { + return "ZDiscontinuityF1D"; + } + + /*! the () operator. */ + int operator()(Interface1D &inter); }; // QuantitativeInvisibilityF1D @@ -404,26 +412,27 @@ public: * results of a chaining (chain, stroke), then it might be made of several 1D elements of different * Quantitative Invisibilities. */ -class QuantitativeInvisibilityF1D : public UnaryFunction1D<unsigned> -{ -private: - Functions0D::QuantitativeInvisibilityF0D _func; - -public: - /*! Builds the functor. - * \param iType: - * The integration method used to compute a single value from a set of values. - */ - QuantitativeInvisibilityF1D(IntegrationType iType = MEAN) : UnaryFunction1D<unsigned int>(iType) {} - - /*! Returns the string "QuantitativeInvisibilityF1D" */ - string getName() const - { - return "QuantitativeInvisibilityF1D"; - } - - /*! the () operator. */ - int operator()(Interface1D& inter); +class QuantitativeInvisibilityF1D : public UnaryFunction1D<unsigned> { + private: + Functions0D::QuantitativeInvisibilityF0D _func; + + public: + /*! Builds the functor. + * \param iType: + * The integration method used to compute a single value from a set of values. + */ + QuantitativeInvisibilityF1D(IntegrationType iType = MEAN) : UnaryFunction1D<unsigned int>(iType) + { + } + + /*! Returns the string "QuantitativeInvisibilityF1D" */ + string getName() const + { + return "QuantitativeInvisibilityF1D"; + } + + /*! the () operator. */ + int operator()(Interface1D &inter); }; // CurveNatureF1D @@ -432,198 +441,200 @@ public: * Indeed, the Interface1D might result from the gathering of several 1D elements, each one being of a different * nature. An integration method, such as the MEAN, might give, in this case, irrelevant results. */ -class CurveNatureF1D : public UnaryFunction1D<Nature::EdgeNature> -{ -private: - Functions0D::CurveNatureF0D _func; - -public: - /*! Builds the functor. - * \param iType: - * The integration method used to compute a single value from a set of values. - */ - CurveNatureF1D(IntegrationType iType = MEAN) : UnaryFunction1D<Nature::EdgeNature>(iType) {} - - /*! Returns the string "CurveNatureF1D" */ - string getName() const - { - return "CurveNatureF1D"; - } - - /*! the () operator. */ - int operator()(Interface1D& inter); +class CurveNatureF1D : public UnaryFunction1D<Nature::EdgeNature> { + private: + Functions0D::CurveNatureF0D _func; + + public: + /*! Builds the functor. + * \param iType: + * The integration method used to compute a single value from a set of values. + */ + CurveNatureF1D(IntegrationType iType = MEAN) : UnaryFunction1D<Nature::EdgeNature>(iType) + { + } + + /*! Returns the string "CurveNatureF1D" */ + string getName() const + { + return "CurveNatureF1D"; + } + + /*! the () operator. */ + int operator()(Interface1D &inter); }; // TimeStampF1D /*! Returns the time stamp of the Interface1D. */ -class TimeStampF1D : public UnaryFunction1D_void -{ -public: - /*! Returns the string "TimeStampF1D" */ - string getName() const - { - return "TimeStampF1D"; - } - - /*! the () operator. */ - int operator()(Interface1D& inter); +class TimeStampF1D : public UnaryFunction1D_void { + public: + /*! Returns the string "TimeStampF1D" */ + string getName() const + { + return "TimeStampF1D"; + } + + /*! the () operator. */ + int operator()(Interface1D &inter); }; // IncrementChainingTimeStampF1D /*! Increments the chaining time stamp of the Interface1D. */ -class IncrementChainingTimeStampF1D : public UnaryFunction1D_void -{ -public: - /*! Returns the string "IncrementChainingTimeStampF1D" */ - string getName() const - { - return "IncrementChainingTimeStampF1D"; - } - - /*! the () operator. */ - int operator()(Interface1D& inter); +class IncrementChainingTimeStampF1D : public UnaryFunction1D_void { + public: + /*! Returns the string "IncrementChainingTimeStampF1D" */ + string getName() const + { + return "IncrementChainingTimeStampF1D"; + } + + /*! the () operator. */ + int operator()(Interface1D &inter); }; // ChainingTimeStampF1D /*! Sets the chaining time stamp of the Interface1D. */ -class ChainingTimeStampF1D : public UnaryFunction1D_void -{ -public: - /*! Returns the string "ChainingTimeStampF1D" */ - string getName() const - { - return "ChainingTimeStampF1D"; - } - - /*! the () operator. */ - int operator()(Interface1D& inter); +class ChainingTimeStampF1D : public UnaryFunction1D_void { + public: + /*! Returns the string "ChainingTimeStampF1D" */ + string getName() const + { + return "ChainingTimeStampF1D"; + } + + /*! the () operator. */ + int operator()(Interface1D &inter); }; - // Curvature2DAngleF1D /*! Returns the 2D curvature as an angle for an Interface1D. */ -class Curvature2DAngleF1D : public UnaryFunction1D<double> -{ -public: - /*! Builds the functor. - * \param iType: - * The integration method used to compute a single value from a set of values. - */ - Curvature2DAngleF1D(IntegrationType iType = MEAN) : UnaryFunction1D<double>(iType) {} - - /*! Returns the string "Curvature2DAngleF1D" */ - string getName() const - { - return "Curvature2DAngleF1D"; - } - - /*! the () operator.*/ - int operator()(Interface1D& inter) - { - result = integrate(_fun, inter.verticesBegin(), inter.verticesEnd(), _integration); - return 0; - } - -private: - Functions0D::Curvature2DAngleF0D _fun; +class Curvature2DAngleF1D : public UnaryFunction1D<double> { + public: + /*! Builds the functor. + * \param iType: + * The integration method used to compute a single value from a set of values. + */ + Curvature2DAngleF1D(IntegrationType iType = MEAN) : UnaryFunction1D<double>(iType) + { + } + + /*! Returns the string "Curvature2DAngleF1D" */ + string getName() const + { + return "Curvature2DAngleF1D"; + } + + /*! the () operator.*/ + int operator()(Interface1D &inter) + { + result = integrate(_fun, inter.verticesBegin(), inter.verticesEnd(), _integration); + return 0; + } + + private: + Functions0D::Curvature2DAngleF0D _fun; }; // Normal2DF1D /*! Returns the 2D normal for an interface 1D. */ -class Normal2DF1D : public UnaryFunction1D<Vec2f> -{ -public: - /*! Builds the functor. - * \param iType: - * The integration method used to compute a single value from a set of values. - */ - Normal2DF1D(IntegrationType iType = MEAN) : UnaryFunction1D<Vec2f>(iType) {} - - /*! Returns the string "Normal2DF1D" */ - string getName() const - { - return "Normal2DF1D"; - } - - /*! the () operator.*/ - int operator()(Interface1D& inter) - { - result = integrate(_fun, inter.verticesBegin(), inter.verticesEnd(), _integration); - return 0; - } - -private: - Functions0D::Normal2DF0D _fun; +class Normal2DF1D : public UnaryFunction1D<Vec2f> { + public: + /*! Builds the functor. + * \param iType: + * The integration method used to compute a single value from a set of values. + */ + Normal2DF1D(IntegrationType iType = MEAN) : UnaryFunction1D<Vec2f>(iType) + { + } + + /*! Returns the string "Normal2DF1D" */ + string getName() const + { + return "Normal2DF1D"; + } + + /*! the () operator.*/ + int operator()(Interface1D &inter) + { + result = integrate(_fun, inter.verticesBegin(), inter.verticesEnd(), _integration); + return 0; + } + + private: + Functions0D::Normal2DF0D _fun; }; // GetShapeF1D /*! Returns list of shapes covered by this Interface1D. */ -class GetShapeF1D : public UnaryFunction1D<std::vector<ViewShape*> > -{ -public: - /*! Builds the functor. */ - GetShapeF1D() : UnaryFunction1D<std::vector<ViewShape*> >() {} - - /*! Returns the string "GetShapeF1D" */ - string getName() const - { - return "GetShapeF1D"; - } - - /*! the () operator. */ - int operator()(Interface1D& inter); +class GetShapeF1D : public UnaryFunction1D<std::vector<ViewShape *>> { + public: + /*! Builds the functor. */ + GetShapeF1D() : UnaryFunction1D<std::vector<ViewShape *>>() + { + } + + /*! Returns the string "GetShapeF1D" */ + string getName() const + { + return "GetShapeF1D"; + } + + /*! the () operator. */ + int operator()(Interface1D &inter); }; // GetOccludersF1D /*! Returns list of occluding shapes covered by this Interface1D. */ -class GetOccludersF1D : public UnaryFunction1D<std::vector<ViewShape*> > -{ -public: - /*! Builds the functor. */ - GetOccludersF1D() : UnaryFunction1D<std::vector<ViewShape*> >() {} - - /*! Returns the string "GetOccludersF1D" */ - string getName() const - { - return "GetOccludersF1D"; - } - - /*! the () operator. */ - int operator()(Interface1D& inter); +class GetOccludersF1D : public UnaryFunction1D<std::vector<ViewShape *>> { + public: + /*! Builds the functor. */ + GetOccludersF1D() : UnaryFunction1D<std::vector<ViewShape *>>() + { + } + + /*! Returns the string "GetOccludersF1D" */ + string getName() const + { + return "GetOccludersF1D"; + } + + /*! the () operator. */ + int operator()(Interface1D &inter); }; // GetOccludeeF1D /*! Returns list of occluded shapes covered by this Interface1D. */ -class GetOccludeeF1D : public UnaryFunction1D<std::vector<ViewShape*> > -{ -public: - /*! Builds the functor. */ - GetOccludeeF1D() : UnaryFunction1D<std::vector<ViewShape*> >() {} - - /*! Returns the string "GetOccludeeF1D" */ - string getName() const - { - return "GetOccludeeF1D"; - } - - /*! the () operator. */ - int operator()(Interface1D& inter); +class GetOccludeeF1D : public UnaryFunction1D<std::vector<ViewShape *>> { + public: + /*! Builds the functor. */ + GetOccludeeF1D() : UnaryFunction1D<std::vector<ViewShape *>>() + { + } + + /*! Returns the string "GetOccludeeF1D" */ + string getName() const + { + return "GetOccludeeF1D"; + } + + /*! the () operator. */ + int operator()(Interface1D &inter); }; // internal //////////// // getOccludeeF1D -void getOccludeeF1D(Interface1D& inter, set<ViewShape*>& oShapes); +void getOccludeeF1D(Interface1D &inter, set<ViewShape *> &oShapes); // getOccludersF1D -void getOccludersF1D(Interface1D& inter, set<ViewShape*>& oShapes); +void getOccludersF1D(Interface1D &inter, set<ViewShape *> &oShapes); // getShapeF1D -void getShapeF1D(Interface1D& inter, set<ViewShape*>& oShapes); +void getShapeF1D(Interface1D &inter, set<ViewShape *> &oShapes); -} // end of namespace Functions1D +} // end of namespace Functions1D } /* namespace Freestyle */ -#endif // __FREESTYLE_FUNCTIONS_1D_H__ +#endif // __FREESTYLE_FUNCTIONS_1D_H__ diff --git a/source/blender/freestyle/intern/view_map/GridDensityProvider.h b/source/blender/freestyle/intern/view_map/GridDensityProvider.h index a01569b958a..dacdb345c86 100644 --- a/source/blender/freestyle/intern/view_map/GridDensityProvider.h +++ b/source/blender/freestyle/intern/view_map/GridDensityProvider.h @@ -34,129 +34,137 @@ #include "BKE_global.h" #ifdef WITH_CXX_GUARDEDALLOC -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif namespace Freestyle { -class GridDensityProvider -{ - // Disallow copying and assignment - GridDensityProvider(const GridDensityProvider& other); - GridDensityProvider& operator=(const GridDensityProvider& other); - -public: - GridDensityProvider(OccluderSource& source) : source(source) {} - - virtual ~GridDensityProvider() {}; - - float cellSize() - { - return _cellSize; - } - - unsigned cellsX() - { - return _cellsX; - } - - unsigned cellsY() - { - return _cellsY; - } - - float cellOrigin(int index) - { - if (index < 2) { - return _cellOrigin[index]; - } - else { - throw new out_of_range("GridDensityProvider::cellOrigin can take only indexes of 0 or 1."); - } - } - - static void calculateOptimalProscenium(OccluderSource& source, real proscenium[4]) - { - source.begin(); - if (source.isValid()) { - const Vec3r& initialPoint = source.getGridSpacePolygon().getVertices()[0]; - proscenium[0] = proscenium[1] = initialPoint[0]; - proscenium[2] = proscenium[3] = initialPoint[1]; - while (source.isValid()) { - GridHelpers::expandProscenium (proscenium, source.getGridSpacePolygon()); - source.next(); - } - } - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Proscenium: (" << proscenium[0] << ", " << proscenium[1] << ", " << proscenium[2] << - ", " << proscenium[3] << ")" << endl; - } - } - - static void calculateQuickProscenium(const GridHelpers::Transform& transform, const BBox<Vec3r>& bbox, - real proscenium[4]) - { - // Transform the coordinates of the 8 corners of the 3D bounding box - real xm = bbox.getMin()[0], xM = bbox.getMax()[0]; - real ym = bbox.getMin()[1], yM = bbox.getMax()[1]; - real zm = bbox.getMin()[2], zM = bbox.getMax()[2]; - Vec3r p1 = transform(Vec3r(xm, ym, zm)); - Vec3r p2 = transform(Vec3r(xm, ym, zM)); - Vec3r p3 = transform(Vec3r(xm, yM, zm)); - Vec3r p4 = transform(Vec3r(xm, yM, zM)); - Vec3r p5 = transform(Vec3r(xM, ym, zm)); - Vec3r p6 = transform(Vec3r(xM, ym, zM)); - Vec3r p7 = transform(Vec3r(xM, yM, zm)); - Vec3r p8 = transform(Vec3r(xM, yM, zM)); - // Determine the proscenium face according to the min and max values of the transformed x and y coordinates - proscenium[0] = std::min(std::min(std::min(p1.x(), p2.x()), std::min(p3.x(), p4.x())), - std::min(std::min(p5.x(), p6.x()), std::min(p7.x(), p8.x()))); - proscenium[1] = std::max(std::max(std::max(p1.x(), p2.x()), std::max(p3.x(), p4.x())), - std::max(std::max(p5.x(), p6.x()), std::max(p7.x(), p8.x()))); - proscenium[2] = std::min(std::min(std::min(p1.y(), p2.y()), std::min(p3.y(), p4.y())), - std::min(std::min(p5.y(), p6.y()), std::min(p7.y(), p8.y()))); - proscenium[3] = std::max(std::max(std::max(p1.y(), p2.y()), std::max(p3.y(), p4.y())), - std::max(std::max(p5.y(), p6.y()), std::max(p7.y(), p8.y()))); - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Proscenium: " << proscenium[0] << ", " << proscenium[1] << ", " << proscenium[2] << ", " << - proscenium[3] << endl; - } - } - -protected: - OccluderSource& source; - unsigned _cellsX, _cellsY; - float _cellSize; - float _cellOrigin[2]; +class GridDensityProvider { + // Disallow copying and assignment + GridDensityProvider(const GridDensityProvider &other); + GridDensityProvider &operator=(const GridDensityProvider &other); + + public: + GridDensityProvider(OccluderSource &source) : source(source) + { + } + + virtual ~GridDensityProvider(){}; + + float cellSize() + { + return _cellSize; + } + + unsigned cellsX() + { + return _cellsX; + } + + unsigned cellsY() + { + return _cellsY; + } + + float cellOrigin(int index) + { + if (index < 2) { + return _cellOrigin[index]; + } + else { + throw new out_of_range("GridDensityProvider::cellOrigin can take only indexes of 0 or 1."); + } + } + + static void calculateOptimalProscenium(OccluderSource &source, real proscenium[4]) + { + source.begin(); + if (source.isValid()) { + const Vec3r &initialPoint = source.getGridSpacePolygon().getVertices()[0]; + proscenium[0] = proscenium[1] = initialPoint[0]; + proscenium[2] = proscenium[3] = initialPoint[1]; + while (source.isValid()) { + GridHelpers::expandProscenium(proscenium, source.getGridSpacePolygon()); + source.next(); + } + } + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Proscenium: (" << proscenium[0] << ", " << proscenium[1] << ", " << proscenium[2] + << ", " << proscenium[3] << ")" << endl; + } + } + + static void calculateQuickProscenium(const GridHelpers::Transform &transform, + const BBox<Vec3r> &bbox, + real proscenium[4]) + { + // Transform the coordinates of the 8 corners of the 3D bounding box + real xm = bbox.getMin()[0], xM = bbox.getMax()[0]; + real ym = bbox.getMin()[1], yM = bbox.getMax()[1]; + real zm = bbox.getMin()[2], zM = bbox.getMax()[2]; + Vec3r p1 = transform(Vec3r(xm, ym, zm)); + Vec3r p2 = transform(Vec3r(xm, ym, zM)); + Vec3r p3 = transform(Vec3r(xm, yM, zm)); + Vec3r p4 = transform(Vec3r(xm, yM, zM)); + Vec3r p5 = transform(Vec3r(xM, ym, zm)); + Vec3r p6 = transform(Vec3r(xM, ym, zM)); + Vec3r p7 = transform(Vec3r(xM, yM, zm)); + Vec3r p8 = transform(Vec3r(xM, yM, zM)); + // Determine the proscenium face according to the min and max values of the transformed x and y coordinates + proscenium[0] = std::min(std::min(std::min(p1.x(), p2.x()), std::min(p3.x(), p4.x())), + std::min(std::min(p5.x(), p6.x()), std::min(p7.x(), p8.x()))); + proscenium[1] = std::max(std::max(std::max(p1.x(), p2.x()), std::max(p3.x(), p4.x())), + std::max(std::max(p5.x(), p6.x()), std::max(p7.x(), p8.x()))); + proscenium[2] = std::min(std::min(std::min(p1.y(), p2.y()), std::min(p3.y(), p4.y())), + std::min(std::min(p5.y(), p6.y()), std::min(p7.y(), p8.y()))); + proscenium[3] = std::max(std::max(std::max(p1.y(), p2.y()), std::max(p3.y(), p4.y())), + std::max(std::max(p5.y(), p6.y()), std::max(p7.y(), p8.y()))); + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Proscenium: " << proscenium[0] << ", " << proscenium[1] << ", " << proscenium[2] + << ", " << proscenium[3] << endl; + } + } + + protected: + OccluderSource &source; + unsigned _cellsX, _cellsY; + float _cellSize; + float _cellOrigin[2]; #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:GridDensityProvider") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:GridDensityProvider") #endif }; -class GridDensityProviderFactory -{ - // Disallow copying and assignment - GridDensityProviderFactory(const GridDensityProviderFactory& other); - GridDensityProviderFactory& operator=(const GridDensityProviderFactory& other); +class GridDensityProviderFactory { + // Disallow copying and assignment + GridDensityProviderFactory(const GridDensityProviderFactory &other); + GridDensityProviderFactory &operator=(const GridDensityProviderFactory &other); -public: - GridDensityProviderFactory() {} + public: + GridDensityProviderFactory() + { + } - virtual AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const real proscenium[4]) = 0; + virtual AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource &source, + const real proscenium[4]) = 0; - virtual AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox, - const GridHelpers::Transform& transform) = 0; + virtual AutoPtr<GridDensityProvider> newGridDensityProvider( + OccluderSource &source, + const BBox<Vec3r> &bbox, + const GridHelpers::Transform &transform) = 0; - virtual AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource& source) = 0; + virtual AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource &source) = 0; - virtual ~GridDensityProviderFactory () {} + virtual ~GridDensityProviderFactory() + { + } #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:GridDensityProviderFactory") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:GridDensityProviderFactory") #endif }; } /* namespace Freestyle */ -#endif // __FREESTYLE_GRID_DENSITY_PROVIDER_H__ +#endif // __FREESTYLE_GRID_DENSITY_PROVIDER_H__ diff --git a/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.cpp b/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.cpp index 676ce8046ad..55bc02b8358 100644 --- a/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.cpp +++ b/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.cpp @@ -23,53 +23,61 @@ namespace Freestyle { -HeuristicGridDensityProviderFactory::HeuristicGridDensityProviderFactory(real sizeFactor, unsigned numFaces) -: sizeFactor(sizeFactor), numFaces(numFaces) +HeuristicGridDensityProviderFactory::HeuristicGridDensityProviderFactory(real sizeFactor, + unsigned numFaces) + : sizeFactor(sizeFactor), numFaces(numFaces) { } -HeuristicGridDensityProviderFactory::~HeuristicGridDensityProviderFactory() {} +HeuristicGridDensityProviderFactory::~HeuristicGridDensityProviderFactory() +{ +} -AutoPtr<GridDensityProvider> -HeuristicGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const real proscenium[4]) +AutoPtr<GridDensityProvider> HeuristicGridDensityProviderFactory::newGridDensityProvider( + OccluderSource &source, const real proscenium[4]) { - AutoPtr<AverageAreaGridDensityProvider> avg(new AverageAreaGridDensityProvider(source, proscenium, sizeFactor)); - AutoPtr<Pow23GridDensityProvider> p23(new Pow23GridDensityProvider(source, proscenium, numFaces)); - if (avg->cellSize() > p23->cellSize()) { - return (AutoPtr<GridDensityProvider>) p23; - } - else { - return (AutoPtr<GridDensityProvider>) avg; - } + AutoPtr<AverageAreaGridDensityProvider> avg( + new AverageAreaGridDensityProvider(source, proscenium, sizeFactor)); + AutoPtr<Pow23GridDensityProvider> p23( + new Pow23GridDensityProvider(source, proscenium, numFaces)); + if (avg->cellSize() > p23->cellSize()) { + return (AutoPtr<GridDensityProvider>)p23; + } + else { + return (AutoPtr<GridDensityProvider>)avg; + } } -AutoPtr<GridDensityProvider> -HeuristicGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox, - const GridHelpers::Transform& transform) +AutoPtr<GridDensityProvider> HeuristicGridDensityProviderFactory::newGridDensityProvider( + OccluderSource &source, const BBox<Vec3r> &bbox, const GridHelpers::Transform &transform) { - AutoPtr<AverageAreaGridDensityProvider> avg(new AverageAreaGridDensityProvider(source, bbox, - transform, sizeFactor)); - AutoPtr<Pow23GridDensityProvider> p23(new Pow23GridDensityProvider(source, bbox, transform, numFaces)); - if (avg->cellSize() > p23->cellSize()) { - return (AutoPtr<GridDensityProvider>) p23; - } - else { - return (AutoPtr<GridDensityProvider>) avg; - } + AutoPtr<AverageAreaGridDensityProvider> avg( + new AverageAreaGridDensityProvider(source, bbox, transform, sizeFactor)); + AutoPtr<Pow23GridDensityProvider> p23( + new Pow23GridDensityProvider(source, bbox, transform, numFaces)); + if (avg->cellSize() > p23->cellSize()) { + return (AutoPtr<GridDensityProvider>)p23; + } + else { + return (AutoPtr<GridDensityProvider>)avg; + } } -AutoPtr<GridDensityProvider> HeuristicGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source) +AutoPtr<GridDensityProvider> HeuristicGridDensityProviderFactory::newGridDensityProvider( + OccluderSource &source) { - real proscenium[4]; - GridDensityProvider::calculateOptimalProscenium(source, proscenium); - AutoPtr<AverageAreaGridDensityProvider> avg(new AverageAreaGridDensityProvider(source, proscenium, sizeFactor)); - AutoPtr<Pow23GridDensityProvider> p23(new Pow23GridDensityProvider(source, proscenium, numFaces)); - if (avg->cellSize() > p23->cellSize()) { - return (AutoPtr<GridDensityProvider>) p23; - } - else { - return (AutoPtr<GridDensityProvider>) avg; - } + real proscenium[4]; + GridDensityProvider::calculateOptimalProscenium(source, proscenium); + AutoPtr<AverageAreaGridDensityProvider> avg( + new AverageAreaGridDensityProvider(source, proscenium, sizeFactor)); + AutoPtr<Pow23GridDensityProvider> p23( + new Pow23GridDensityProvider(source, proscenium, numFaces)); + if (avg->cellSize() > p23->cellSize()) { + return (AutoPtr<GridDensityProvider>)p23; + } + else { + return (AutoPtr<GridDensityProvider>)avg; + } } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.h b/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.h index 87f602945f1..b32a284cb61 100644 --- a/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.h +++ b/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.h @@ -30,22 +30,23 @@ namespace Freestyle { -class HeuristicGridDensityProviderFactory : public GridDensityProviderFactory -{ -public: - HeuristicGridDensityProviderFactory(real sizeFactor, unsigned numFaces); - ~HeuristicGridDensityProviderFactory(); - - AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const real proscenium[4]); - AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox, - const GridHelpers::Transform& transform); - AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource& source); - -protected: - real sizeFactor; - unsigned numFaces; +class HeuristicGridDensityProviderFactory : public GridDensityProviderFactory { + public: + HeuristicGridDensityProviderFactory(real sizeFactor, unsigned numFaces); + ~HeuristicGridDensityProviderFactory(); + + AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource &source, + const real proscenium[4]); + AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource &source, + const BBox<Vec3r> &bbox, + const GridHelpers::Transform &transform); + AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource &source); + + protected: + real sizeFactor; + unsigned numFaces; }; } /* namespace Freestyle */ -#endif // __FREESTYLE_HEURISTIC_GRID_DENSITY_PROVIDER_FACTORY_H__ +#endif // __FREESTYLE_HEURISTIC_GRID_DENSITY_PROVIDER_FACTORY_H__ diff --git a/source/blender/freestyle/intern/view_map/Interface0D.cpp b/source/blender/freestyle/intern/view_map/Interface0D.cpp index 17331bb613f..fc5a797cc87 100644 --- a/source/blender/freestyle/intern/view_map/Interface0D.cpp +++ b/source/blender/freestyle/intern/view_map/Interface0D.cpp @@ -28,92 +28,92 @@ namespace Freestyle { real Interface0D::getX() const { - PyErr_SetString(PyExc_TypeError, "method getX() not properly overridden"); - return 0; + PyErr_SetString(PyExc_TypeError, "method getX() not properly overridden"); + return 0; } real Interface0D::getY() const { - PyErr_SetString(PyExc_TypeError, "method getY() not properly overridden"); - return 0; + PyErr_SetString(PyExc_TypeError, "method getY() not properly overridden"); + return 0; } real Interface0D::getZ() const { - PyErr_SetString(PyExc_TypeError, "method getZ() not properly overridden"); - return 0; + PyErr_SetString(PyExc_TypeError, "method getZ() not properly overridden"); + return 0; } Geometry::Vec3r Interface0D::getPoint3D() const { - PyErr_SetString(PyExc_TypeError, "method getPoint3D() not properly overridden"); - return 0; + PyErr_SetString(PyExc_TypeError, "method getPoint3D() not properly overridden"); + return 0; } real Interface0D::getProjectedX() const { - PyErr_SetString(PyExc_TypeError, "method getProjectedX() not properly overridden"); - return 0; + PyErr_SetString(PyExc_TypeError, "method getProjectedX() not properly overridden"); + return 0; } real Interface0D::getProjectedY() const { - PyErr_SetString(PyExc_TypeError, "method getProjectedY() not properly overridden"); - return 0; + PyErr_SetString(PyExc_TypeError, "method getProjectedY() not properly overridden"); + return 0; } real Interface0D::getProjectedZ() const { - PyErr_SetString(PyExc_TypeError, "method getProjectedZ() not properly overridden"); - return 0; + PyErr_SetString(PyExc_TypeError, "method getProjectedZ() not properly overridden"); + return 0; } Geometry::Vec2r Interface0D::getPoint2D() const { - PyErr_SetString(PyExc_TypeError, "method getPoint2D() not properly overridden"); - return 0; + PyErr_SetString(PyExc_TypeError, "method getPoint2D() not properly overridden"); + return 0; } -FEdge *Interface0D::getFEdge(Interface0D&) +FEdge *Interface0D::getFEdge(Interface0D &) { - PyErr_SetString(PyExc_TypeError, "method getFEdge() not properly overridden"); - return 0; + PyErr_SetString(PyExc_TypeError, "method getFEdge() not properly overridden"); + return 0; } Id Interface0D::getId() const { - PyErr_SetString(PyExc_TypeError, "method getId() not properly overridden"); - return 0; + PyErr_SetString(PyExc_TypeError, "method getId() not properly overridden"); + return 0; } Nature::VertexNature Interface0D::getNature() const { - PyErr_SetString(PyExc_TypeError, "method getNature() not properly overridden"); - return Nature::POINT; + PyErr_SetString(PyExc_TypeError, "method getNature() not properly overridden"); + return Nature::POINT; } SVertex *Interface0D::castToSVertex() { - PyErr_SetString(PyExc_TypeError, "method castToSVertex() not properly overridden"); - return 0; + PyErr_SetString(PyExc_TypeError, "method castToSVertex() not properly overridden"); + return 0; } ViewVertex *Interface0D::castToViewVertex() { - PyErr_SetString(PyExc_TypeError, "method castToViewVertex() not properly overridden"); - return 0; + PyErr_SetString(PyExc_TypeError, "method castToViewVertex() not properly overridden"); + return 0; } NonTVertex *Interface0D::castToNonTVertex() { - PyErr_SetString(PyExc_TypeError, "method castToNonTVertex() not properly overridden"); - return 0; + PyErr_SetString(PyExc_TypeError, "method castToNonTVertex() not properly overridden"); + return 0; } TVertex *Interface0D::castToTVertex() { - PyErr_SetString(PyExc_TypeError, "method castToTVertex() not properly overridden"); - return 0; + PyErr_SetString(PyExc_TypeError, "method castToTVertex() not properly overridden"); + return 0; } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/view_map/Interface0D.h b/source/blender/freestyle/intern/view_map/Interface0D.h index 88214bb80a1..bab996d9308 100644 --- a/source/blender/freestyle/intern/view_map/Interface0D.h +++ b/source/blender/freestyle/intern/view_map/Interface0D.h @@ -34,7 +34,7 @@ #include "../winged_edge/Nature.h" #ifdef WITH_CXX_GUARDEDALLOC -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif using namespace std; @@ -53,121 +53,121 @@ class NonTVertex; class TVertex; /*! Base class for any 0D element. */ -class Interface0D -{ -public: - /*! Default constructor */ - Interface0D() {} +class Interface0D { + public: + /*! Default constructor */ + Interface0D() + { + } - /*! Destructor */ - virtual ~Interface0D() {}; + /*! Destructor */ + virtual ~Interface0D(){}; - /*! Returns the string "Interface0D". */ - virtual string getExactTypeName() const - { - return "Interface0D"; - } + /*! Returns the string "Interface0D". */ + virtual string getExactTypeName() const + { + return "Interface0D"; + } - // Data access methods + // Data access methods - /*! Returns the 3D x coordinate of the point. */ - virtual real getX() const; + /*! Returns the 3D x coordinate of the point. */ + virtual real getX() const; - /*! Returns the 3D y coordinate of the point. */ - virtual real getY() const; + /*! Returns the 3D y coordinate of the point. */ + virtual real getY() const; - /*! Returns the 3D z coordinate of the point. */ - virtual real getZ() const; + /*! Returns the 3D z coordinate of the point. */ + virtual real getZ() const; - /*! Returns the 3D point. */ - virtual Geometry::Vec3r getPoint3D() const; + /*! Returns the 3D point. */ + virtual Geometry::Vec3r getPoint3D() const; - /*! Returns the 2D x coordinate of the point. */ - virtual real getProjectedX() const; + /*! Returns the 2D x coordinate of the point. */ + virtual real getProjectedX() const; - /*! Returns the 2D y coordinate of the point. */ - virtual real getProjectedY() const; + /*! Returns the 2D y coordinate of the point. */ + virtual real getProjectedY() const; - /*! Returns the 2D z coordinate of the point. */ - virtual real getProjectedZ() const; + /*! Returns the 2D z coordinate of the point. */ + virtual real getProjectedZ() const; - /*! Returns the 2D point. */ - virtual Geometry::Vec2r getPoint2D() const; + /*! Returns the 2D point. */ + virtual Geometry::Vec2r getPoint2D() const; - /*! Returns the FEdge that lies between this Interface0D and the Interface0D given as argument. */ - virtual FEdge *getFEdge(Interface0D&); + /*! Returns the FEdge that lies between this Interface0D and the Interface0D given as argument. */ + virtual FEdge *getFEdge(Interface0D &); - /*! Returns the Id of the point. */ - virtual Id getId() const; + /*! Returns the Id of the point. */ + virtual Id getId() const; - /*! Returns the nature of the point. */ - virtual Nature::VertexNature getNature() const; + /*! Returns the nature of the point. */ + virtual Nature::VertexNature getNature() const; - /*! Cast the Interface0D in SVertex if it can be. */ - virtual SVertex *castToSVertex(); + /*! Cast the Interface0D in SVertex if it can be. */ + virtual SVertex *castToSVertex(); - /*! Cast the Interface0D in ViewVertex if it can be. */ - virtual ViewVertex *castToViewVertex(); + /*! Cast the Interface0D in ViewVertex if it can be. */ + virtual ViewVertex *castToViewVertex(); - /*! Cast the Interface0D in NonTVertex if it can be. */ - virtual NonTVertex *castToNonTVertex(); + /*! Cast the Interface0D in NonTVertex if it can be. */ + virtual NonTVertex *castToNonTVertex(); - /*! Cast the Interface0D in TVertex if it can be. */ - virtual TVertex *castToTVertex(); + /*! Cast the Interface0D in TVertex if it can be. */ + virtual TVertex *castToTVertex(); #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Interface0D") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Interface0D") #endif }; - // // Interface0DIteratorNested // ////////////////////////////////////////////////// -class Interface0DIteratorNested : public Iterator -{ -public: - virtual ~Interface0DIteratorNested() {} +class Interface0DIteratorNested : public Iterator { + public: + virtual ~Interface0DIteratorNested() + { + } - virtual string getExactTypeName() const - { - return "Interface0DIteratorNested"; - } + virtual string getExactTypeName() const + { + return "Interface0DIteratorNested"; + } - virtual Interface0D& operator*() = 0; + virtual Interface0D &operator*() = 0; - virtual Interface0D *operator->() - { - return &(operator*()); - } + virtual Interface0D *operator->() + { + return &(operator*()); + } - virtual int increment() = 0; + virtual int increment() = 0; - virtual int decrement() = 0; + virtual int decrement() = 0; - virtual bool isBegin() const = 0; + virtual bool isBegin() const = 0; - virtual bool isEnd() const = 0; + virtual bool isEnd() const = 0; - virtual bool operator==(const Interface0DIteratorNested& it) const = 0; + virtual bool operator==(const Interface0DIteratorNested &it) const = 0; - virtual bool operator!=(const Interface0DIteratorNested& it) const - { - return !(*this == it); - } + virtual bool operator!=(const Interface0DIteratorNested &it) const + { + return !(*this == it); + } - /*! Returns the curvilinear abscissa */ - virtual float t() const = 0; + /*! Returns the curvilinear abscissa */ + virtual float t() const = 0; - /*! Returns the point parameter 0<u<1 */ - virtual float u() const = 0; + /*! Returns the point parameter 0<u<1 */ + virtual float u() const = 0; - virtual Interface0DIteratorNested *copy() const = 0; + virtual Interface0DIteratorNested *copy() const = 0; }; - // // Interface0DIterator // @@ -179,163 +179,162 @@ public: * \code it2 = it1 \endcode where \a it1 and \a it2 are 2 Interface0DIterator. * Otherwise, incrementing \a it1 will also increment \a it2. */ -class Interface0DIterator : public Iterator -{ -public: - Interface0DIterator(Interface0DIteratorNested *it = NULL) - { - _iterator = it; - } - - /*! Copy constructor */ - Interface0DIterator(const Interface0DIterator& it) - { - _iterator = it._iterator->copy(); - } - - /*! Destructor */ - virtual ~Interface0DIterator() - { - if (_iterator) - delete _iterator; - } - - /*! Operator = - * \attention In the scripting language, you must call \code it2 = Interface0DIterator(it1) \endcode instead of - * \code it2 = it1 \endcode where \a it1 and \a it2 are 2 Interface0DIterator. - * Otherwise, incrementing \a it1 will also increment \a it2. - */ - Interface0DIterator& operator=(const Interface0DIterator& it) - { - if (_iterator) - delete _iterator; - _iterator = it._iterator->copy(); - return *this; - } - - /*! Returns the string "Interface0DIterator". */ - virtual string getExactTypeName() const - { - if (!_iterator) - return "Interface0DIterator"; - return _iterator->getExactTypeName() + "Proxy"; - } - - // FIXME test it != 0 (exceptions ?) - - /*! Returns a reference to the pointed Interface0D. - * In the scripting language, you must call "getObject()" instead using this operator. - */ - Interface0D& operator*() - { - return _iterator->operator*(); - } - - /*! Returns a pointer to the pointed Interface0D. - * Can't be called in the scripting language. - */ - Interface0D *operator->() - { - return &(operator*()); - } - - /*! Increments. In the scripting language, call "increment()". */ - Interface0DIterator& operator++() - { - _iterator->increment(); - return *this; - } - - /*! Increments. In the scripting language, call "increment()". */ - Interface0DIterator operator++(int) - { - Interface0DIterator ret(*this); - _iterator->increment(); - return ret; - } - - /*! Decrements. In the scripting language, call "decrement()". */ - Interface0DIterator& operator--() - { - _iterator->decrement(); - return *this; - } - - /*! Decrements. In the scripting language, call "decrement()". */ - Interface0DIterator operator--(int) - { - Interface0DIterator ret(*this); - _iterator->decrement(); - return ret; - } - - /*! Increments. */ - virtual int increment() - { - return _iterator->increment(); - } - - /*! Decrements. */ - virtual int decrement() - { - return _iterator->decrement(); - } - - /*! Returns true if the pointed Interface0D is the first of the 1D element containing the points over which - * we're iterating. - */ - virtual bool isBegin() const - { - return _iterator->isBegin(); - } - - /*! Returns true if the pointed Interface0D is after the after the last point of the 1D element we're - * iterating from. */ - virtual bool isEnd() const - { - return _iterator->isEnd(); - } - - /*! Returns true when the iterator is pointing to the final valid element. */ - virtual bool atLast() const - { - if (_iterator->isEnd()) - return false; - - _iterator->increment(); - bool result = _iterator->isEnd(); - _iterator->decrement(); - return result; - } - - /*! operator == . */ - bool operator==(const Interface0DIterator& it) const - { - return _iterator->operator==(*(it._iterator)); - } - - /*! operator != . */ - bool operator!=(const Interface0DIterator& it) const - { - return !(*this == it); - } - - /*! Returns the curvilinear abscissa. */ - inline float t() const - { - return _iterator->t(); - } - - /*! Returns the point parameter in the curve 0<=u<=1. */ - inline float u() const - { - return _iterator->u(); - } - -protected: - Interface0DIteratorNested *_iterator; +class Interface0DIterator : public Iterator { + public: + Interface0DIterator(Interface0DIteratorNested *it = NULL) + { + _iterator = it; + } + + /*! Copy constructor */ + Interface0DIterator(const Interface0DIterator &it) + { + _iterator = it._iterator->copy(); + } + + /*! Destructor */ + virtual ~Interface0DIterator() + { + if (_iterator) + delete _iterator; + } + + /*! Operator = + * \attention In the scripting language, you must call \code it2 = Interface0DIterator(it1) \endcode instead of + * \code it2 = it1 \endcode where \a it1 and \a it2 are 2 Interface0DIterator. + * Otherwise, incrementing \a it1 will also increment \a it2. + */ + Interface0DIterator &operator=(const Interface0DIterator &it) + { + if (_iterator) + delete _iterator; + _iterator = it._iterator->copy(); + return *this; + } + + /*! Returns the string "Interface0DIterator". */ + virtual string getExactTypeName() const + { + if (!_iterator) + return "Interface0DIterator"; + return _iterator->getExactTypeName() + "Proxy"; + } + + // FIXME test it != 0 (exceptions ?) + + /*! Returns a reference to the pointed Interface0D. + * In the scripting language, you must call "getObject()" instead using this operator. + */ + Interface0D &operator*() + { + return _iterator->operator*(); + } + + /*! Returns a pointer to the pointed Interface0D. + * Can't be called in the scripting language. + */ + Interface0D *operator->() + { + return &(operator*()); + } + + /*! Increments. In the scripting language, call "increment()". */ + Interface0DIterator &operator++() + { + _iterator->increment(); + return *this; + } + + /*! Increments. In the scripting language, call "increment()". */ + Interface0DIterator operator++(int) + { + Interface0DIterator ret(*this); + _iterator->increment(); + return ret; + } + + /*! Decrements. In the scripting language, call "decrement()". */ + Interface0DIterator &operator--() + { + _iterator->decrement(); + return *this; + } + + /*! Decrements. In the scripting language, call "decrement()". */ + Interface0DIterator operator--(int) + { + Interface0DIterator ret(*this); + _iterator->decrement(); + return ret; + } + + /*! Increments. */ + virtual int increment() + { + return _iterator->increment(); + } + + /*! Decrements. */ + virtual int decrement() + { + return _iterator->decrement(); + } + + /*! Returns true if the pointed Interface0D is the first of the 1D element containing the points over which + * we're iterating. + */ + virtual bool isBegin() const + { + return _iterator->isBegin(); + } + + /*! Returns true if the pointed Interface0D is after the after the last point of the 1D element we're + * iterating from. */ + virtual bool isEnd() const + { + return _iterator->isEnd(); + } + + /*! Returns true when the iterator is pointing to the final valid element. */ + virtual bool atLast() const + { + if (_iterator->isEnd()) + return false; + + _iterator->increment(); + bool result = _iterator->isEnd(); + _iterator->decrement(); + return result; + } + + /*! operator == . */ + bool operator==(const Interface0DIterator &it) const + { + return _iterator->operator==(*(it._iterator)); + } + + /*! operator != . */ + bool operator!=(const Interface0DIterator &it) const + { + return !(*this == it); + } + + /*! Returns the curvilinear abscissa. */ + inline float t() const + { + return _iterator->t(); + } + + /*! Returns the point parameter in the curve 0<=u<=1. */ + inline float u() const + { + return _iterator->u(); + } + + protected: + Interface0DIteratorNested *_iterator; }; } /* namespace Freestyle */ -#endif // __FREESTYLE_INTERFACE_0D_H__ +#endif // __FREESTYLE_INTERFACE_0D_H__ diff --git a/source/blender/freestyle/intern/view_map/Interface1D.cpp b/source/blender/freestyle/intern/view_map/Interface1D.cpp index 4f3c46bbf01..ef219365831 100644 --- a/source/blender/freestyle/intern/view_map/Interface1D.cpp +++ b/source/blender/freestyle/intern/view_map/Interface1D.cpp @@ -28,44 +28,44 @@ namespace Freestyle { Interface0DIterator Interface1D::verticesBegin() { - PyErr_SetString(PyExc_TypeError, "method verticesBegin() not properly overridden"); - return Interface0DIterator(); + PyErr_SetString(PyExc_TypeError, "method verticesBegin() not properly overridden"); + return Interface0DIterator(); } Interface0DIterator Interface1D::verticesEnd() { - PyErr_SetString(PyExc_TypeError, "method verticesEnd() not properly overridden"); - return Interface0DIterator(); + PyErr_SetString(PyExc_TypeError, "method verticesEnd() not properly overridden"); + return Interface0DIterator(); } Interface0DIterator Interface1D::pointsBegin(float /*t*/) { - PyErr_SetString(PyExc_TypeError, "method pointsBegin() not properly overridden"); - return Interface0DIterator(); + PyErr_SetString(PyExc_TypeError, "method pointsBegin() not properly overridden"); + return Interface0DIterator(); } Interface0DIterator Interface1D::pointsEnd(float /*t*/) { - PyErr_SetString(PyExc_TypeError, "method pointsEnd() not properly overridden"); - return Interface0DIterator(); + PyErr_SetString(PyExc_TypeError, "method pointsEnd() not properly overridden"); + return Interface0DIterator(); } real Interface1D::getLength2D() const { - PyErr_SetString(PyExc_TypeError, "method getLength2D() not properly overridden"); - return 0; + PyErr_SetString(PyExc_TypeError, "method getLength2D() not properly overridden"); + return 0; } Id Interface1D::getId() const { - PyErr_SetString(PyExc_TypeError, "method getId() not properly overridden"); - return Id(0, 0); + PyErr_SetString(PyExc_TypeError, "method getId() not properly overridden"); + return Id(0, 0); } Nature::EdgeNature Interface1D::getNature() const { - PyErr_SetString(PyExc_TypeError, "method getNature() not properly overridden"); - return Nature::NO_FEATURE; + PyErr_SetString(PyExc_TypeError, "method getNature() not properly overridden"); + return Nature::NO_FEATURE; } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/view_map/Interface1D.h b/source/blender/freestyle/intern/view_map/Interface1D.h index de190f22e2d..e56a58096f8 100644 --- a/source/blender/freestyle/intern/view_map/Interface1D.h +++ b/source/blender/freestyle/intern/view_map/Interface1D.h @@ -34,7 +34,7 @@ #include "../winged_edge/Nature.h" #ifdef WITH_CXX_GUARDEDALLOC -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif using namespace std; @@ -46,11 +46,11 @@ namespace Freestyle { * from each 0D element of a 1D element. */ typedef enum { - MEAN, /*!< The value computed for the 1D element is the mean of the values obtained for the 0D elements.*/ - MIN, /*!< The value computed for the 1D element is the minimum of the values obtained for the 0D elements.*/ - MAX, /*!< The value computed for the 1D element is the maximum of the values obtained for the 0D elements.*/ - FIRST, /*!< The value computed for the 1D element is the first of the values obtained for the 0D elements.*/ - LAST, /*!< The value computed for the 1D element is the last of the values obtained for the 0D elements.*/ + MEAN, /*!< The value computed for the 1D element is the mean of the values obtained for the 0D elements.*/ + MIN, /*!< The value computed for the 1D element is the minimum of the values obtained for the 0D elements.*/ + MAX, /*!< The value computed for the 1D element is the maximum of the values obtained for the 0D elements.*/ + FIRST, /*!< The value computed for the 1D element is the first of the values obtained for the 0D elements.*/ + LAST, /*!< The value computed for the 1D element is the last of the values obtained for the 0D elements.*/ } IntegrationType; /*! Returns a single value from a set of values evaluated at each 0D element of this 1D element. @@ -65,54 +65,56 @@ typedef enum { * The integration method used to compute a single value from a set of values. * \return the single value obtained for the 1D element. */ -template <class T> -T integrate(UnaryFunction0D<T>& fun, Interface0DIterator it, Interface0DIterator it_end, +template<class T> +T integrate(UnaryFunction0D<T> &fun, + Interface0DIterator it, + Interface0DIterator it_end, IntegrationType integration_type = MEAN) { - T res; - unsigned size; - switch (integration_type) { - case MIN: - fun(it); - res = fun.result; - ++it; - for (; !it.isEnd(); ++it) { - fun(it); - if (fun.result < res) - res = fun.result; - } - break; - case MAX: - fun(it); - res = fun.result; - ++it; - for (; !it.isEnd(); ++it) { - fun(it); - if (fun.result > res) - res = fun.result; - } - break; - case FIRST: - fun(it); - res = fun.result; - break; - case LAST: - fun(--it_end); - res = fun.result; - break; - case MEAN: - default: - fun(it); - res = fun.result; - ++it; - for (size = 1; !it.isEnd(); ++it, ++size) { - fun(it); - res += fun.result; - } - res /= (size ? size : 1); - break; - } - return res; + T res; + unsigned size; + switch (integration_type) { + case MIN: + fun(it); + res = fun.result; + ++it; + for (; !it.isEnd(); ++it) { + fun(it); + if (fun.result < res) + res = fun.result; + } + break; + case MAX: + fun(it); + res = fun.result; + ++it; + for (; !it.isEnd(); ++it) { + fun(it); + if (fun.result > res) + res = fun.result; + } + break; + case FIRST: + fun(it); + res = fun.result; + break; + case LAST: + fun(--it_end); + res = fun.result; + break; + case MEAN: + default: + fun(it); + res = fun.result; + ++it; + for (size = 1; !it.isEnd(); ++it, ++size) { + fun(it); + res += fun.result; + } + res /= (size ? size : 1); + break; + } + return res; } // @@ -121,80 +123,79 @@ T integrate(UnaryFunction0D<T>& fun, Interface0DIterator it, Interface0DIterator ////////////////////////////////////////////////// /*! Base class for any 1D element. */ -class Interface1D -{ -public: - /*! Default constructor */ - Interface1D() - { - _timeStamp = 0; - } - - /*! Destructor */ - virtual ~Interface1D() {}; - - /*! Returns the string "Interface1D". */ - virtual string getExactTypeName() const - { - return "Interface1D"; - } - - // Iterator access - - /*! Returns an iterator over the Interface1D vertices, pointing to the first vertex. */ - virtual Interface0DIterator verticesBegin(); - - /*! Returns an iterator over the Interface1D vertices, pointing after the last vertex. */ - virtual Interface0DIterator verticesEnd(); - - /*! Returns an iterator over the Interface1D points, pointing to the first point. The difference with - * verticesBegin() is that here we can iterate over points of the 1D element at a any given sampling. - * Indeed, for each iteration, a virtual point is created. - * \param t: - * The sampling with which we want to iterate over points of this 1D element. - */ - virtual Interface0DIterator pointsBegin(float t = 0.0f); - - /*! Returns an iterator over the Interface1D points, pointing after the last point. The difference with - * verticesEnd() is that here we can iterate over points of the 1D element at a any given sampling. - * Indeed, for each iteration, a virtual point is created. - * \param t: - * The sampling with which we want to iterate over points of this 1D element. - */ - virtual Interface0DIterator pointsEnd(float t = 0.0f); - - // Data access methods - - /*! Returns the 2D length of the 1D element. */ - virtual real getLength2D() const; - - /*! Returns the Id of the 1D element. */ - virtual Id getId() const; - - // FIXME: ce truc n'a rien a faire la...(c une requete complexe qui doit etre ds les Function1D) - /*! Returns the nature of the 1D element. */ - virtual Nature::EdgeNature getNature() const; - - /*! Returns the time stamp of the 1D element. Mainly used for selection. */ - virtual unsigned getTimeStamp() const - { - return _timeStamp; - } - - /*! Sets the time stamp for the 1D element. */ - inline void setTimeStamp(unsigned iTimeStamp) - { - _timeStamp = iTimeStamp; - } - -protected: - unsigned _timeStamp; +class Interface1D { + public: + /*! Default constructor */ + Interface1D() + { + _timeStamp = 0; + } + + /*! Destructor */ + virtual ~Interface1D(){}; + + /*! Returns the string "Interface1D". */ + virtual string getExactTypeName() const + { + return "Interface1D"; + } + + // Iterator access + + /*! Returns an iterator over the Interface1D vertices, pointing to the first vertex. */ + virtual Interface0DIterator verticesBegin(); + + /*! Returns an iterator over the Interface1D vertices, pointing after the last vertex. */ + virtual Interface0DIterator verticesEnd(); + + /*! Returns an iterator over the Interface1D points, pointing to the first point. The difference with + * verticesBegin() is that here we can iterate over points of the 1D element at a any given sampling. + * Indeed, for each iteration, a virtual point is created. + * \param t: + * The sampling with which we want to iterate over points of this 1D element. + */ + virtual Interface0DIterator pointsBegin(float t = 0.0f); + + /*! Returns an iterator over the Interface1D points, pointing after the last point. The difference with + * verticesEnd() is that here we can iterate over points of the 1D element at a any given sampling. + * Indeed, for each iteration, a virtual point is created. + * \param t: + * The sampling with which we want to iterate over points of this 1D element. + */ + virtual Interface0DIterator pointsEnd(float t = 0.0f); + + // Data access methods + + /*! Returns the 2D length of the 1D element. */ + virtual real getLength2D() const; + + /*! Returns the Id of the 1D element. */ + virtual Id getId() const; + + // FIXME: ce truc n'a rien a faire la...(c une requete complexe qui doit etre ds les Function1D) + /*! Returns the nature of the 1D element. */ + virtual Nature::EdgeNature getNature() const; + + /*! Returns the time stamp of the 1D element. Mainly used for selection. */ + virtual unsigned getTimeStamp() const + { + return _timeStamp; + } + + /*! Sets the time stamp for the 1D element. */ + inline void setTimeStamp(unsigned iTimeStamp) + { + _timeStamp = iTimeStamp; + } + + protected: + unsigned _timeStamp; #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Interface1D") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Interface1D") #endif }; } /* namespace Freestyle */ -#endif // __FREESTYLE_INTERFACE_1D_H__ +#endif // __FREESTYLE_INTERFACE_1D_H__ diff --git a/source/blender/freestyle/intern/view_map/OccluderSource.cpp b/source/blender/freestyle/intern/view_map/OccluderSource.cpp index 90393825d28..7132e0172ae 100644 --- a/source/blender/freestyle/intern/view_map/OccluderSource.cpp +++ b/source/blender/freestyle/intern/view_map/OccluderSource.cpp @@ -27,116 +27,119 @@ namespace Freestyle { -OccluderSource::OccluderSource(const GridHelpers::Transform& t, WingedEdge& we) -: wingedEdge(we), valid(false), transform(t) +OccluderSource::OccluderSource(const GridHelpers::Transform &t, WingedEdge &we) + : wingedEdge(we), valid(false), transform(t) { - begin(); + begin(); } -OccluderSource::~OccluderSource() {} +OccluderSource::~OccluderSource() +{ +} void OccluderSource::buildCachedPolygon() { - vector<Vec3r> vertices(GridHelpers::enumerateVertices((*currentFace)->getEdgeList())); - // This doesn't work, because our functor's polymorphism won't survive the copy: - // std::transform(vertices.begin(), vertices.end(), vertices.begin(), transform); - // so we have to do: - for (vector<Vec3r>::iterator i = vertices.begin(); i != vertices.end(); ++i) { - (*i) = transform(*i); - } - cachedPolygon = Polygon3r(vertices, transform((*currentFace)->GetNormal())); + vector<Vec3r> vertices(GridHelpers::enumerateVertices((*currentFace)->getEdgeList())); + // This doesn't work, because our functor's polymorphism won't survive the copy: + // std::transform(vertices.begin(), vertices.end(), vertices.begin(), transform); + // so we have to do: + for (vector<Vec3r>::iterator i = vertices.begin(); i != vertices.end(); ++i) { + (*i) = transform(*i); + } + cachedPolygon = Polygon3r(vertices, transform((*currentFace)->GetNormal())); } void OccluderSource::begin() { - vector<WShape*>& wshapes = wingedEdge.getWShapes(); - currentShape = wshapes.begin(); - shapesEnd = wshapes.end(); - valid = false; - if (currentShape != shapesEnd) { - vector<WFace*>& wFaces = (*currentShape)->GetFaceList(); - currentFace = wFaces.begin(); - facesEnd = wFaces.end(); - - if (currentFace != facesEnd) { - buildCachedPolygon(); - valid = true; - } - } + vector<WShape *> &wshapes = wingedEdge.getWShapes(); + currentShape = wshapes.begin(); + shapesEnd = wshapes.end(); + valid = false; + if (currentShape != shapesEnd) { + vector<WFace *> &wFaces = (*currentShape)->GetFaceList(); + currentFace = wFaces.begin(); + facesEnd = wFaces.end(); + + if (currentFace != facesEnd) { + buildCachedPolygon(); + valid = true; + } + } } bool OccluderSource::next() { - if (valid) { - ++currentFace; - while (currentFace == facesEnd) { - ++currentShape; - if (currentShape == shapesEnd) { - valid = false; - return false; - } - else { - vector<WFace*>& wFaces = (*currentShape)->GetFaceList(); - currentFace = wFaces.begin(); - facesEnd = wFaces.end(); - } - } - buildCachedPolygon(); - return true; - } - return false; + if (valid) { + ++currentFace; + while (currentFace == facesEnd) { + ++currentShape; + if (currentShape == shapesEnd) { + valid = false; + return false; + } + else { + vector<WFace *> &wFaces = (*currentShape)->GetFaceList(); + currentFace = wFaces.begin(); + facesEnd = wFaces.end(); + } + } + buildCachedPolygon(); + return true; + } + return false; } bool OccluderSource::isValid() { - // Or: - // return currentShapes != shapesEnd && currentFace != facesEnd; - return valid; + // Or: + // return currentShapes != shapesEnd && currentFace != facesEnd; + return valid; } WFace *OccluderSource::getWFace() { - return valid ? *currentFace : NULL; + return valid ? *currentFace : NULL; } Polygon3r OccluderSource::getCameraSpacePolygon() { - return Polygon3r(GridHelpers::enumerateVertices((*currentFace)->getEdgeList()), (*currentFace)->GetNormal()); + return Polygon3r(GridHelpers::enumerateVertices((*currentFace)->getEdgeList()), + (*currentFace)->GetNormal()); } -Polygon3r& OccluderSource::getGridSpacePolygon() +Polygon3r &OccluderSource::getGridSpacePolygon() { - return cachedPolygon; + return cachedPolygon; } void OccluderSource::getOccluderProscenium(real proscenium[4]) { - begin(); - const Vec3r& initialPoint = cachedPolygon.getVertices()[0]; - proscenium[0] = proscenium[1] = initialPoint[0]; - proscenium[2] = proscenium[3] = initialPoint[1]; - while (isValid()) { - GridHelpers::expandProscenium (proscenium, cachedPolygon); - next(); - } - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Proscenium: (" << proscenium[0] << ", " << proscenium[1] << ", " << proscenium[2] << ", " << - proscenium[3] << ")" << endl; - } + begin(); + const Vec3r &initialPoint = cachedPolygon.getVertices()[0]; + proscenium[0] = proscenium[1] = initialPoint[0]; + proscenium[2] = proscenium[3] = initialPoint[1]; + while (isValid()) { + GridHelpers::expandProscenium(proscenium, cachedPolygon); + next(); + } + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Proscenium: (" << proscenium[0] << ", " << proscenium[1] << ", " << proscenium[2] + << ", " << proscenium[3] << ")" << endl; + } } real OccluderSource::averageOccluderArea() { - real area = 0.0; - unsigned numFaces = 0; - for (begin(); isValid(); next()) { - Vec3r min, max; - cachedPolygon.getBBox(min, max); - area += (max[0] - min[0]) * (max[1] - min[1]); - ++numFaces; - } - area /= numFaces; - return area; + real area = 0.0; + unsigned numFaces = 0; + for (begin(); isValid(); next()) { + Vec3r min, max; + cachedPolygon.getBBox(min, max); + area += (max[0] - min[0]) * (max[1] - min[1]); + ++numFaces; + } + area /= numFaces; + return area; } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/view_map/OccluderSource.h b/source/blender/freestyle/intern/view_map/OccluderSource.h index fd7d9f38a0d..07df3b95347 100644 --- a/source/blender/freestyle/intern/view_map/OccluderSource.h +++ b/source/blender/freestyle/intern/view_map/OccluderSource.h @@ -27,49 +27,48 @@ #include "../winged_edge/WEdge.h" #ifdef WITH_CXX_GUARDEDALLOC -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif namespace Freestyle { -class OccluderSource -{ - // Disallow copying and assignment - OccluderSource(const OccluderSource& other); - OccluderSource& operator=(const OccluderSource& other); +class OccluderSource { + // Disallow copying and assignment + OccluderSource(const OccluderSource &other); + OccluderSource &operator=(const OccluderSource &other); -public: - OccluderSource(const GridHelpers::Transform& transform, WingedEdge& we); - virtual ~OccluderSource(); + public: + OccluderSource(const GridHelpers::Transform &transform, WingedEdge &we); + virtual ~OccluderSource(); - void begin(); - virtual bool next(); - bool isValid(); + void begin(); + virtual bool next(); + bool isValid(); - WFace *getWFace(); - Polygon3r getCameraSpacePolygon(); - Polygon3r& getGridSpacePolygon(); + WFace *getWFace(); + Polygon3r getCameraSpacePolygon(); + Polygon3r &getGridSpacePolygon(); - virtual void getOccluderProscenium(real proscenium[4]); - virtual real averageOccluderArea(); + virtual void getOccluderProscenium(real proscenium[4]); + virtual real averageOccluderArea(); -protected: - WingedEdge& wingedEdge; - vector<WShape*>::const_iterator currentShape, shapesEnd; - vector<WFace*>::const_iterator currentFace, facesEnd; + protected: + WingedEdge &wingedEdge; + vector<WShape *>::const_iterator currentShape, shapesEnd; + vector<WFace *>::const_iterator currentFace, facesEnd; - bool valid; + bool valid; - Polygon3r cachedPolygon; - const GridHelpers::Transform& transform; + Polygon3r cachedPolygon; + const GridHelpers::Transform &transform; - void buildCachedPolygon(); + void buildCachedPolygon(); #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:OccluderSource") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:OccluderSource") #endif }; } /* namespace Freestyle */ -#endif // __FREESTYLE_OCCLUDER_SOURCE_H__ +#endif // __FREESTYLE_OCCLUDER_SOURCE_H__ diff --git a/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.cpp b/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.cpp index 858e6b649eb..7e7f4e14882 100644 --- a/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.cpp +++ b/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.cpp @@ -25,90 +25,100 @@ namespace Freestyle { -Pow23GridDensityProvider::Pow23GridDensityProvider(OccluderSource& source, const real proscenium[4], unsigned numFaces) -: GridDensityProvider(source), numFaces(numFaces) +Pow23GridDensityProvider::Pow23GridDensityProvider(OccluderSource &source, + const real proscenium[4], + unsigned numFaces) + : GridDensityProvider(source), numFaces(numFaces) { - initialize (proscenium); + initialize(proscenium); } -Pow23GridDensityProvider::Pow23GridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox, - const GridHelpers::Transform& transform, unsigned numFaces) -: GridDensityProvider(source), numFaces(numFaces) +Pow23GridDensityProvider::Pow23GridDensityProvider(OccluderSource &source, + const BBox<Vec3r> &bbox, + const GridHelpers::Transform &transform, + unsigned numFaces) + : GridDensityProvider(source), numFaces(numFaces) { - real proscenium[4]; - calculateQuickProscenium(transform, bbox, proscenium); + real proscenium[4]; + calculateQuickProscenium(transform, bbox, proscenium); - initialize (proscenium); + initialize(proscenium); } -Pow23GridDensityProvider::Pow23GridDensityProvider(OccluderSource& source, unsigned numFaces) -: GridDensityProvider(source), numFaces(numFaces) +Pow23GridDensityProvider::Pow23GridDensityProvider(OccluderSource &source, unsigned numFaces) + : GridDensityProvider(source), numFaces(numFaces) { - real proscenium[4]; - calculateOptimalProscenium(source, proscenium); + real proscenium[4]; + calculateOptimalProscenium(source, proscenium); - initialize (proscenium); + initialize(proscenium); } -Pow23GridDensityProvider::~Pow23GridDensityProvider () {} +Pow23GridDensityProvider::~Pow23GridDensityProvider() +{ +} void Pow23GridDensityProvider::initialize(const real proscenium[4]) { - float prosceniumWidth = (proscenium[1] - proscenium[0]); - float prosceniumHeight = (proscenium[3] - proscenium[2]); - real cellArea = prosceniumWidth * prosceniumHeight / pow(numFaces, 2.0f / 3.0f); - if (G.debug & G_DEBUG_FREESTYLE) { - cout << prosceniumWidth << " x " << prosceniumHeight << " grid with cells of area " << cellArea << "." << endl; - } - - _cellSize = sqrt(cellArea); - // Now we know how many cells make each side of our grid - _cellsX = ceil(prosceniumWidth / _cellSize); - _cellsY = ceil(prosceniumHeight / _cellSize); - if (G.debug & G_DEBUG_FREESTYLE) { - cout << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square." << endl; - } - - // Make sure the grid exceeds the proscenium by a small amount - float safetyZone = 0.1; - if (_cellsX * _cellSize < prosceniumWidth * (1.0 + safetyZone)) { - _cellsX = ceil(prosceniumWidth * (1.0 + safetyZone) / _cellSize); - } - if (_cellsY * _cellSize < prosceniumHeight * (1.0 + safetyZone)) { - _cellsY = ceil(prosceniumHeight * (1.0 + safetyZone) / _cellSize); - } - if (G.debug & G_DEBUG_FREESTYLE) { - cout << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square." << endl; - } - - // Find grid origin - _cellOrigin[0] = ((proscenium[0] + proscenium[1]) / 2.0) - (_cellsX / 2.0) * _cellSize; - _cellOrigin[1] = ((proscenium[2] + proscenium[3]) / 2.0) - (_cellsY / 2.0) * _cellSize; + float prosceniumWidth = (proscenium[1] - proscenium[0]); + float prosceniumHeight = (proscenium[3] - proscenium[2]); + real cellArea = prosceniumWidth * prosceniumHeight / pow(numFaces, 2.0f / 3.0f); + if (G.debug & G_DEBUG_FREESTYLE) { + cout << prosceniumWidth << " x " << prosceniumHeight << " grid with cells of area " << cellArea + << "." << endl; + } + + _cellSize = sqrt(cellArea); + // Now we know how many cells make each side of our grid + _cellsX = ceil(prosceniumWidth / _cellSize); + _cellsY = ceil(prosceniumHeight / _cellSize); + if (G.debug & G_DEBUG_FREESTYLE) { + cout << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square." << endl; + } + + // Make sure the grid exceeds the proscenium by a small amount + float safetyZone = 0.1; + if (_cellsX * _cellSize < prosceniumWidth * (1.0 + safetyZone)) { + _cellsX = ceil(prosceniumWidth * (1.0 + safetyZone) / _cellSize); + } + if (_cellsY * _cellSize < prosceniumHeight * (1.0 + safetyZone)) { + _cellsY = ceil(prosceniumHeight * (1.0 + safetyZone) / _cellSize); + } + if (G.debug & G_DEBUG_FREESTYLE) { + cout << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square." << endl; + } + + // Find grid origin + _cellOrigin[0] = ((proscenium[0] + proscenium[1]) / 2.0) - (_cellsX / 2.0) * _cellSize; + _cellOrigin[1] = ((proscenium[2] + proscenium[3]) / 2.0) - (_cellsY / 2.0) * _cellSize; } Pow23GridDensityProviderFactory::Pow23GridDensityProviderFactory(unsigned numFaces) -: numFaces(numFaces) + : numFaces(numFaces) { } -Pow23GridDensityProviderFactory::~Pow23GridDensityProviderFactory () {} +Pow23GridDensityProviderFactory::~Pow23GridDensityProviderFactory() +{ +} -AutoPtr<GridDensityProvider> -Pow23GridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const real proscenium[4]) +AutoPtr<GridDensityProvider> Pow23GridDensityProviderFactory::newGridDensityProvider( + OccluderSource &source, const real proscenium[4]) { - return AutoPtr<GridDensityProvider>(new Pow23GridDensityProvider(source, proscenium, numFaces)); + return AutoPtr<GridDensityProvider>(new Pow23GridDensityProvider(source, proscenium, numFaces)); } -AutoPtr<GridDensityProvider> -Pow23GridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox, - const GridHelpers::Transform& transform) +AutoPtr<GridDensityProvider> Pow23GridDensityProviderFactory::newGridDensityProvider( + OccluderSource &source, const BBox<Vec3r> &bbox, const GridHelpers::Transform &transform) { - return AutoPtr<GridDensityProvider>(new Pow23GridDensityProvider(source, bbox, transform, numFaces)); + return AutoPtr<GridDensityProvider>( + new Pow23GridDensityProvider(source, bbox, transform, numFaces)); } -AutoPtr<GridDensityProvider> Pow23GridDensityProviderFactory::newGridDensityProvider(OccluderSource& source) +AutoPtr<GridDensityProvider> Pow23GridDensityProviderFactory::newGridDensityProvider( + OccluderSource &source) { - return AutoPtr<GridDensityProvider>(new Pow23GridDensityProvider(source, numFaces)); + return AutoPtr<GridDensityProvider>(new Pow23GridDensityProvider(source, numFaces)); } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.h b/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.h index 72fc56e4ef1..52d57e3030e 100644 --- a/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.h +++ b/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.h @@ -26,41 +26,43 @@ namespace Freestyle { -class Pow23GridDensityProvider : public GridDensityProvider -{ - // Disallow copying and assignment - Pow23GridDensityProvider(const Pow23GridDensityProvider& other); - Pow23GridDensityProvider& operator=(const Pow23GridDensityProvider& other); +class Pow23GridDensityProvider : public GridDensityProvider { + // Disallow copying and assignment + Pow23GridDensityProvider(const Pow23GridDensityProvider &other); + Pow23GridDensityProvider &operator=(const Pow23GridDensityProvider &other); -public: - Pow23GridDensityProvider(OccluderSource& source, const real proscenium[4], unsigned numFaces); - Pow23GridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox, const GridHelpers::Transform& transform, - unsigned numFaces); - Pow23GridDensityProvider(OccluderSource& source, unsigned numFaces); - virtual ~Pow23GridDensityProvider(); + public: + Pow23GridDensityProvider(OccluderSource &source, const real proscenium[4], unsigned numFaces); + Pow23GridDensityProvider(OccluderSource &source, + const BBox<Vec3r> &bbox, + const GridHelpers::Transform &transform, + unsigned numFaces); + Pow23GridDensityProvider(OccluderSource &source, unsigned numFaces); + virtual ~Pow23GridDensityProvider(); -protected: - unsigned numFaces; + protected: + unsigned numFaces; -private: - void initialize(const real proscenium[4]); + private: + void initialize(const real proscenium[4]); }; -class Pow23GridDensityProviderFactory : public GridDensityProviderFactory -{ -public: - Pow23GridDensityProviderFactory(unsigned numFaces); - ~Pow23GridDensityProviderFactory(); +class Pow23GridDensityProviderFactory : public GridDensityProviderFactory { + public: + Pow23GridDensityProviderFactory(unsigned numFaces); + ~Pow23GridDensityProviderFactory(); - AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const real proscenium[4]); - AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource& source, const BBox<Vec3r>& bbox, - const GridHelpers::Transform& transform); - AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource& source); + AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource &source, + const real proscenium[4]); + AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource &source, + const BBox<Vec3r> &bbox, + const GridHelpers::Transform &transform); + AutoPtr<GridDensityProvider> newGridDensityProvider(OccluderSource &source); -protected: - unsigned numFaces; + protected: + unsigned numFaces; }; } /* namespace Freestyle */ -#endif // __FREESTYLE_POW_23_GRID_DENSITY_PROVIDER_H__ +#endif // __FREESTYLE_POW_23_GRID_DENSITY_PROVIDER_H__ diff --git a/source/blender/freestyle/intern/view_map/Silhouette.cpp b/source/blender/freestyle/intern/view_map/Silhouette.cpp index 7934ccf8671..73bf38107cd 100644 --- a/source/blender/freestyle/intern/view_map/Silhouette.cpp +++ b/source/blender/freestyle/intern/view_map/Silhouette.cpp @@ -34,178 +34,174 @@ namespace Freestyle { Nature::VertexNature SVertex::getNature() const { - Nature::VertexNature nature = Nature::S_VERTEX; - if (_pViewVertex) - nature |= _pViewVertex->getNature(); - return nature; + Nature::VertexNature nature = Nature::S_VERTEX; + if (_pViewVertex) + nature |= _pViewVertex->getNature(); + return nature; } SVertex *SVertex::castToSVertex() { - return this; + return this; } ViewVertex *SVertex::castToViewVertex() { - return _pViewVertex; + return _pViewVertex; } NonTVertex *SVertex::castToNonTVertex() { - return dynamic_cast<NonTVertex*>(_pViewVertex); + return dynamic_cast<NonTVertex *>(_pViewVertex); } TVertex *SVertex::castToTVertex() { - return dynamic_cast<TVertex*>(_pViewVertex); + return dynamic_cast<TVertex *>(_pViewVertex); } float SVertex::shape_importance() const { - return shape()->importance(); + return shape()->importance(); } #if 0 Material SVertex::material() const { - return _Shape->material(); + return _Shape->material(); } #endif Id SVertex::shape_id() const { - return _Shape->getId(); + return _Shape->getId(); } const SShape *SVertex::shape() const { - return _Shape; + return _Shape; } const int SVertex::qi() const { - if (getNature() & Nature::T_VERTEX) - Exception::raiseException(); - return (_FEdges[0])->qi(); + if (getNature() & Nature::T_VERTEX) + Exception::raiseException(); + return (_FEdges[0])->qi(); } occluder_container::const_iterator SVertex::occluders_begin() const { - if (getNature() & Nature::T_VERTEX) - Exception::raiseException(); - return (_FEdges[0])->occluders_begin(); + if (getNature() & Nature::T_VERTEX) + Exception::raiseException(); + return (_FEdges[0])->occluders_begin(); } occluder_container::const_iterator SVertex::occluders_end() const { - if (getNature() & Nature::T_VERTEX) - Exception::raiseException(); - return (_FEdges[0])->occluders_end(); + if (getNature() & Nature::T_VERTEX) + Exception::raiseException(); + return (_FEdges[0])->occluders_end(); } bool SVertex::occluders_empty() const { - if (getNature() & Nature::T_VERTEX) - Exception::raiseException(); - return (_FEdges[0])->occluders_empty(); + if (getNature() & Nature::T_VERTEX) + Exception::raiseException(); + return (_FEdges[0])->occluders_empty(); } int SVertex::occluders_size() const { - if (getNature() & Nature::T_VERTEX) - Exception::raiseException(); - return (_FEdges[0])->occluders_size(); + if (getNature() & Nature::T_VERTEX) + Exception::raiseException(); + return (_FEdges[0])->occluders_size(); } -const Polygon3r& SVertex::occludee() const +const Polygon3r &SVertex::occludee() const { - if (getNature() & Nature::T_VERTEX) - Exception::raiseException(); - return (_FEdges[0])->occludee(); + if (getNature() & Nature::T_VERTEX) + Exception::raiseException(); + return (_FEdges[0])->occludee(); } const SShape *SVertex::occluded_shape() const { - if (getNature() & Nature::T_VERTEX) - Exception::raiseException(); - return (_FEdges[0])->occluded_shape(); + if (getNature() & Nature::T_VERTEX) + Exception::raiseException(); + return (_FEdges[0])->occluded_shape(); } const bool SVertex::occludee_empty() const { - if (getNature() & Nature::T_VERTEX) - Exception::raiseException(); - return (_FEdges[0])->occludee_empty(); + if (getNature() & Nature::T_VERTEX) + Exception::raiseException(); + return (_FEdges[0])->occludee_empty(); } real SVertex::z_discontinuity() const { - if (getNature() & Nature::T_VERTEX) - Exception::raiseException(); - return (_FEdges[0])->z_discontinuity(); + if (getNature() & Nature::T_VERTEX) + Exception::raiseException(); + return (_FEdges[0])->z_discontinuity(); } FEdge *SVertex::fedge() { - if (getNature() & Nature::T_VERTEX) - return NULL; - return _FEdges[0]; -} - -FEdge *SVertex::getFEdge(Interface0D& inter) -{ - FEdge *result = NULL; - SVertex *iVertexB = dynamic_cast<SVertex*>(&inter); - if (!iVertexB) - return result; - vector<FEdge*>::const_iterator fe = _FEdges.begin(), feend = _FEdges.end(); - for (; fe != feend; ++fe) { - if ((((*fe)->vertexA() == this) && ((*fe)->vertexB() == iVertexB)) || - (((*fe)->vertexB() == this) && ((*fe)->vertexA() == iVertexB))) - { - result = (*fe); - } - } - if ((result == 0) && (getNature() & Nature::T_VERTEX)) { - SVertex *brother; - ViewVertex *vvertex = viewvertex(); - TVertex *tvertex = dynamic_cast<TVertex*>(vvertex); - if (tvertex) { - brother = tvertex->frontSVertex(); - if (this == brother) - brother = tvertex->backSVertex(); - const vector<FEdge*>& fedges = brother->fedges(); - for (fe = fedges.begin(), feend = fedges.end(); fe != feend; ++fe) { - if ((((*fe)->vertexA() == brother) && ((*fe)->vertexB() == iVertexB)) || - (((*fe)->vertexB() == brother) && ((*fe)->vertexA() == iVertexB))) - { - result = (*fe); - } - } - } - } - if ((result == 0) && (iVertexB->getNature() & Nature::T_VERTEX)) { - SVertex *brother; - ViewVertex *vvertex = iVertexB->viewvertex(); - TVertex *tvertex = dynamic_cast<TVertex*>(vvertex); - if (tvertex) { - brother = tvertex->frontSVertex(); - if (iVertexB == brother) - brother = tvertex->backSVertex(); - for (fe = _FEdges.begin(), feend = _FEdges.end(); fe != feend; ++fe) { - if ((((*fe)->vertexA() == this) && ((*fe)->vertexB() == brother)) || - (((*fe)->vertexB() == this) && ((*fe)->vertexA() == brother))) - { - result = (*fe); - } - } - } - } - - return result; + if (getNature() & Nature::T_VERTEX) + return NULL; + return _FEdges[0]; +} + +FEdge *SVertex::getFEdge(Interface0D &inter) +{ + FEdge *result = NULL; + SVertex *iVertexB = dynamic_cast<SVertex *>(&inter); + if (!iVertexB) + return result; + vector<FEdge *>::const_iterator fe = _FEdges.begin(), feend = _FEdges.end(); + for (; fe != feend; ++fe) { + if ((((*fe)->vertexA() == this) && ((*fe)->vertexB() == iVertexB)) || + (((*fe)->vertexB() == this) && ((*fe)->vertexA() == iVertexB))) { + result = (*fe); + } + } + if ((result == 0) && (getNature() & Nature::T_VERTEX)) { + SVertex *brother; + ViewVertex *vvertex = viewvertex(); + TVertex *tvertex = dynamic_cast<TVertex *>(vvertex); + if (tvertex) { + brother = tvertex->frontSVertex(); + if (this == brother) + brother = tvertex->backSVertex(); + const vector<FEdge *> &fedges = brother->fedges(); + for (fe = fedges.begin(), feend = fedges.end(); fe != feend; ++fe) { + if ((((*fe)->vertexA() == brother) && ((*fe)->vertexB() == iVertexB)) || + (((*fe)->vertexB() == brother) && ((*fe)->vertexA() == iVertexB))) { + result = (*fe); + } + } + } + } + if ((result == 0) && (iVertexB->getNature() & Nature::T_VERTEX)) { + SVertex *brother; + ViewVertex *vvertex = iVertexB->viewvertex(); + TVertex *tvertex = dynamic_cast<TVertex *>(vvertex); + if (tvertex) { + brother = tvertex->frontSVertex(); + if (iVertexB == brother) + brother = tvertex->backSVertex(); + for (fe = _FEdges.begin(), feend = _FEdges.end(); fe != feend; ++fe) { + if ((((*fe)->vertexA() == this) && ((*fe)->vertexB() == brother)) || + (((*fe)->vertexB() == this) && ((*fe)->vertexA() == brother))) { + result = (*fe); + } + } + } + } + + return result; } - /**********************************/ /* */ /* */ @@ -214,159 +210,158 @@ FEdge *SVertex::getFEdge(Interface0D& inter) /* */ /**********************************/ - int FEdge::viewedge_nature() const { - return _ViewEdge->getNature(); + return _ViewEdge->getNature(); } #if 0 float FEdge::viewedge_length() const { - return _ViewEdge->viewedge_length(); + return _ViewEdge->viewedge_length(); } #endif const SShape *FEdge::occluded_shape() const { - ViewShape *aShape = _ViewEdge->aShape(); - if (aShape == 0) - return 0; - return aShape->sshape(); + ViewShape *aShape = _ViewEdge->aShape(); + if (aShape == 0) + return 0; + return aShape->sshape(); } float FEdge::shape_importance() const { - return _VertexA->shape()->importance(); + return _VertexA->shape()->importance(); } int FEdge::invisibility() const { - return _ViewEdge->qi(); + return _ViewEdge->qi(); } occluder_container::const_iterator FEdge::occluders_begin() const { - return _ViewEdge->occluders_begin(); + return _ViewEdge->occluders_begin(); } occluder_container::const_iterator FEdge::occluders_end() const { - return _ViewEdge->occluders_end(); + return _ViewEdge->occluders_end(); } bool FEdge::occluders_empty() const { - return _ViewEdge->occluders_empty(); + return _ViewEdge->occluders_empty(); } int FEdge::occluders_size() const { - return _ViewEdge->occluders_size(); + return _ViewEdge->occluders_size(); } -const bool FEdge::occludee_empty() const +const bool FEdge::occludee_empty() const { - return _ViewEdge->occludee_empty(); + return _ViewEdge->occludee_empty(); } Id FEdge::shape_id() const { - return _VertexA->shape()->getId(); + return _VertexA->shape()->getId(); } const SShape *FEdge::shape() const { - return _VertexA->shape(); + return _VertexA->shape(); } real FEdge::z_discontinuity() const { - if (!(getNature() & Nature::SILHOUETTE) && !(getNature() & Nature::BORDER)) { - return 0; - } + if (!(getNature() & Nature::SILHOUETTE) && !(getNature() & Nature::BORDER)) { + return 0; + } - BBox<Vec3r> box = ViewMap::getInstance()->getScene3dBBox(); + BBox<Vec3r> box = ViewMap::getInstance()->getScene3dBBox(); - Vec3r bbox_size_vec(box.getMax() - box.getMin()); - real bboxsize = bbox_size_vec.norm(); - if (occludee_empty()) { - //return FLT_MAX; - return 1.0; - //return bboxsize; - } + Vec3r bbox_size_vec(box.getMax() - box.getMin()); + real bboxsize = bbox_size_vec.norm(); + if (occludee_empty()) { + //return FLT_MAX; + return 1.0; + //return bboxsize; + } #if 0 - real result; - z_discontinuity_functor<SVertex> _functor; - Evaluate<SVertex, z_discontinuity_functor<SVertex> >(&_functor, iCombination, result); + real result; + z_discontinuity_functor<SVertex> _functor; + Evaluate<SVertex, z_discontinuity_functor<SVertex> >(&_functor, iCombination, result); #endif - Vec3r middle((_VertexB->point3d() - _VertexA->point3d())); - middle /= 2; - Vec3r disc_vec(middle - _occludeeIntersection); - real res = disc_vec.norm() / bboxsize; + Vec3r middle((_VertexB->point3d() - _VertexA->point3d())); + middle /= 2; + Vec3r disc_vec(middle - _occludeeIntersection); + real res = disc_vec.norm() / bboxsize; - return res; - //return fabs((middle.z() - _occludeeIntersection.z())); + return res; + //return fabs((middle.z() - _occludeeIntersection.z())); } #if 0 float FEdge::local_average_depth(int iCombination ) const { - float result; - local_average_depth_functor<SVertex> functor; - Evaluate(&functor, iCombination, result); + float result; + local_average_depth_functor<SVertex> functor; + Evaluate(&functor, iCombination, result); - return result; + return result; } float FEdge::local_depth_variance(int iCombination ) const { - float result; + float result; - local_depth_variance_functor<SVertex> functor; + local_depth_variance_functor<SVertex> functor; - Evaluate(&functor, iCombination, result); + Evaluate(&functor, iCombination, result); - return result; + return result; } real FEdge::local_average_density( float sigma, int iCombination) const { - float result; + float result; - density_functor<SVertex> functor(sigma); + density_functor<SVertex> functor(sigma); - Evaluate(&functor, iCombination, result); + Evaluate(&functor, iCombination, result); - return result; + return result; } Vec3r FEdge::normal(int& oException /* = Exception::NO_EXCEPTION */) { - Vec3r Na = _VertexA->normal(oException); - if (oException != Exception::NO_EXCEPTION) - return Na; - Vec3r Nb = _VertexB->normal(oException); - if (oException != Exception::NO_EXCEPTION) - return Nb; - return (Na + Nb) / 2.0; + Vec3r Na = _VertexA->normal(oException); + if (oException != Exception::NO_EXCEPTION) + return Na; + Vec3r Nb = _VertexB->normal(oException); + if (oException != Exception::NO_EXCEPTION) + return Nb; + return (Na + Nb) / 2.0; } Vec3r FEdge::curvature2d_as_vector(int iCombination) const { - Vec3r result; - curvature2d_as_vector_functor<SVertex> _functor; - Evaluate<Vec3r, curvature2d_as_vector_functor<SVertex> >(&_functor, iCombination, result); - return result; + Vec3r result; + curvature2d_as_vector_functor<SVertex> _functor; + Evaluate<Vec3r, curvature2d_as_vector_functor<SVertex> >(&_functor, iCombination, result); + return result; } real FEdge::curvature2d_as_angle(int iCombination) const { - real result; - curvature2d_as_angle_functor<SVertex> _functor; - Evaluate<real, curvature2d_as_angle_functor<SVertex> >(&_functor, iCombination, result); - return result; + real result; + curvature2d_as_angle_functor<SVertex> _functor; + Evaluate<real, curvature2d_as_angle_functor<SVertex> >(&_functor, iCombination, result); + return result; } #endif @@ -381,18 +376,18 @@ real FEdge::curvature2d_as_angle(int iCombination) const #if 0 Material FEdge::material() const { - return _VertexA->shape()->material(); + return _VertexA->shape()->material(); } #endif -const FrsMaterial& FEdgeSharp::aFrsMaterial() const +const FrsMaterial &FEdgeSharp::aFrsMaterial() const { - return _VertexA->shape()->frs_material(_aFrsMaterialIndex); + return _VertexA->shape()->frs_material(_aFrsMaterialIndex); } -const FrsMaterial& FEdgeSharp::bFrsMaterial() const +const FrsMaterial &FEdgeSharp::bFrsMaterial() const { - return _VertexA->shape()->frs_material(_bFrsMaterialIndex); + return _VertexA->shape()->frs_material(_bFrsMaterialIndex); } /**********************************/ @@ -403,9 +398,9 @@ const FrsMaterial& FEdgeSharp::bFrsMaterial() const /* */ /**********************************/ -const FrsMaterial& FEdgeSmooth::frs_material() const +const FrsMaterial &FEdgeSmooth::frs_material() const { - return _VertexA->shape()->frs_material(_FrsMaterialIndex); + return _VertexA->shape()->frs_material(_FrsMaterialIndex); } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/view_map/Silhouette.h b/source/blender/freestyle/intern/view_map/Silhouette.h index 8005203072d..510aedf6cbf 100644 --- a/source/blender/freestyle/intern/view_map/Silhouette.h +++ b/source/blender/freestyle/intern/view_map/Silhouette.h @@ -43,7 +43,7 @@ #include "../winged_edge/Curvature.h" #ifdef WITH_CXX_GUARDEDALLOC -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif using namespace std; @@ -53,7 +53,7 @@ namespace Freestyle { using namespace Geometry; class ViewShape; -typedef vector<ViewShape*> occluder_container; +typedef vector<ViewShape *> occluder_container; /**********************************/ /* */ @@ -68,387 +68,386 @@ class ViewVertex; class SShape; /*! Class to define a vertex of the embedding. */ -class SVertex : public Interface0D -{ -public: // Implementation of Interface0D - /*! Returns the string "SVertex" .*/ - virtual string getExactTypeName() const - { - return "SVertex"; - } - - // Data access methods - /*! Returns the 3D x coordinate of the vertex .*/ - virtual real getX() const - { - return _Point3D.x(); - } - - /*! Returns the 3D y coordinate of the vertex .*/ - virtual real getY() const - { - return _Point3D.y(); - } - - /*! Returns the 3D z coordinate of the vertex .*/ - virtual real getZ() const - { - return _Point3D.z(); - } - - /*! Returns the 3D point. */ - virtual Vec3r getPoint3D() const - { - return _Point3D; - } - - /*! Returns the projected 3D x coordinate of the vertex .*/ - virtual real getProjectedX() const - { - return _Point2D.x(); - } - - /*! Returns the projected 3D y coordinate of the vertex .*/ - virtual real getProjectedY() const - { - return _Point2D.y(); - } - - /*! Returns the projected 3D z coordinate of the vertex .*/ - virtual real getProjectedZ() const - { - return _Point2D.z(); - } - - /*! Returns the 2D point. */ - virtual Vec2r getPoint2D() const - { - return Vec2r(_Point2D.x(), _Point2D.y()); - } - - /*! Returns the FEdge that lies between this Svertex and the Interface0D given as argument. */ - virtual FEdge *getFEdge(Interface0D&); - - /*! Returns the Id of the vertex .*/ - virtual Id getId() const - { - return _Id; - } - - /*! Returns the nature of the vertex .*/ - virtual Nature::VertexNature getNature() const; - - /*! Cast the Interface0D in SVertex if it can be. */ - virtual SVertex *castToSVertex(); - - /*! Cast the Interface0D in ViewVertex if it can be. */ - virtual ViewVertex *castToViewVertex(); - - /*! Cast the Interface0D in NonTVertex if it can be. */ - virtual NonTVertex *castToNonTVertex(); - - /*! Cast the Interface0D in TVertex if it can be. */ - virtual TVertex *castToTVertex(); - -public: - typedef vector<FEdge*> fedges_container; - -private: - Id _Id; - Vec3r _Point3D; - Vec3r _Point2D; - set<Vec3r> _Normals; - vector<FEdge*> _FEdges; // the edges containing this vertex - SShape *_Shape; // the shape to which belongs the vertex - ViewVertex *_pViewVertex; // The associated viewvertex, in case there is one. +class SVertex : public Interface0D { + public: // Implementation of Interface0D + /*! Returns the string "SVertex" .*/ + virtual string getExactTypeName() const + { + return "SVertex"; + } + + // Data access methods + /*! Returns the 3D x coordinate of the vertex .*/ + virtual real getX() const + { + return _Point3D.x(); + } + + /*! Returns the 3D y coordinate of the vertex .*/ + virtual real getY() const + { + return _Point3D.y(); + } + + /*! Returns the 3D z coordinate of the vertex .*/ + virtual real getZ() const + { + return _Point3D.z(); + } + + /*! Returns the 3D point. */ + virtual Vec3r getPoint3D() const + { + return _Point3D; + } + + /*! Returns the projected 3D x coordinate of the vertex .*/ + virtual real getProjectedX() const + { + return _Point2D.x(); + } + + /*! Returns the projected 3D y coordinate of the vertex .*/ + virtual real getProjectedY() const + { + return _Point2D.y(); + } + + /*! Returns the projected 3D z coordinate of the vertex .*/ + virtual real getProjectedZ() const + { + return _Point2D.z(); + } + + /*! Returns the 2D point. */ + virtual Vec2r getPoint2D() const + { + return Vec2r(_Point2D.x(), _Point2D.y()); + } + + /*! Returns the FEdge that lies between this Svertex and the Interface0D given as argument. */ + virtual FEdge *getFEdge(Interface0D &); + + /*! Returns the Id of the vertex .*/ + virtual Id getId() const + { + return _Id; + } + + /*! Returns the nature of the vertex .*/ + virtual Nature::VertexNature getNature() const; + + /*! Cast the Interface0D in SVertex if it can be. */ + virtual SVertex *castToSVertex(); + + /*! Cast the Interface0D in ViewVertex if it can be. */ + virtual ViewVertex *castToViewVertex(); + + /*! Cast the Interface0D in NonTVertex if it can be. */ + virtual NonTVertex *castToNonTVertex(); + + /*! Cast the Interface0D in TVertex if it can be. */ + virtual TVertex *castToTVertex(); + + public: + typedef vector<FEdge *> fedges_container; + + private: + Id _Id; + Vec3r _Point3D; + Vec3r _Point2D; + set<Vec3r> _Normals; + vector<FEdge *> _FEdges; // the edges containing this vertex + SShape *_Shape; // the shape to which belongs the vertex + ViewVertex *_pViewVertex; // The associated viewvertex, in case there is one. #if 0 - real _curvatureFredo; - Vec2r _directionFredo; + real _curvatureFredo; + Vec2r _directionFredo; #endif - CurvatureInfo *_curvature_info; - -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 SVertex() - { - _Id = 0; - userdata = NULL; - _Shape = NULL; - _pViewVertex = 0; - _curvature_info = 0; - } - - /*! Builds a SVertex from 3D coordinates and an Id. */ - inline SVertex(const Vec3r &iPoint3D, const Id& id) - { - _Point3D = iPoint3D; - _Id = id; - userdata = NULL; - _Shape = NULL; - _pViewVertex = 0; - _curvature_info = 0; - } - - /*! Copy constructor. */ - inline SVertex(SVertex& iBrother) - { - _Id = iBrother._Id; - _Point3D = iBrother.point3D(); - _Point2D = iBrother.point2D(); - _Normals = iBrother._Normals; - _FEdges = iBrother.fedges(); - _Shape = iBrother.shape(); - _pViewVertex = iBrother._pViewVertex; - if (!(iBrother._curvature_info)) - _curvature_info = 0; - else - _curvature_info = new CurvatureInfo(*(iBrother._curvature_info)); - iBrother.userdata = this; - userdata = 0; - } - - /*! Destructor. */ - virtual ~SVertex() - { - if (_curvature_info) - delete _curvature_info; - } - - /*! Cloning method. */ - virtual SVertex *duplicate() - { - SVertex *clone = new SVertex(*this); - return clone; - } - - /*! operator == */ - virtual bool operator==(const SVertex& iBrother) - { - return ((_Point2D == iBrother._Point2D) && (_Point3D == iBrother._Point3D)); - } - - /* accessors */ - inline const Vec3r& point3D() const - { - return _Point3D; - } - - inline const Vec3r& point2D() const - { - return _Point2D; - } - - /*! Returns the set of normals for this Vertex. - * In a smooth surface, a vertex has exactly one normal. - * In a sharp surface, a vertex can have any number of normals. - */ - inline set<Vec3r> normals() - { - return _Normals; - } - - /*! Returns the number of different normals for this vertex. */ - inline unsigned normalsSize() const - { - return _Normals.size(); - } - - inline const vector<FEdge*>& fedges() - { - return _FEdges; - } - - inline fedges_container::iterator fedges_begin() - { - return _FEdges.begin(); - } - - inline fedges_container::iterator fedges_end() - { - return _FEdges.end(); - } - - inline SShape *shape() - { - return _Shape; - } - - inline real z() const - { - return _Point2D[2]; - } - - /*! If this SVertex is also a ViewVertex, this method returns a pointer onto this ViewVertex. - * 0 is returned otherwise. - */ - inline ViewVertex *viewvertex() - { - return _pViewVertex; - } - - /*! modifiers */ - /*! Sets the 3D coordinates of the SVertex. */ - inline void setPoint3D(const Vec3r &iPoint3D) - { - _Point3D = iPoint3D; - } - - /*! Sets the 3D projected coordinates of the SVertex. */ - inline void setPoint2D(const Vec3r &iPoint2D) - { - _Point2D = iPoint2D; - } - - /*! Adds a normal to the Svertex's set of normals. If the same normal is already in the set, nothing changes. */ - inline void AddNormal(const Vec3r& iNormal) - { - _Normals.insert(iNormal); // if iNormal in the set already exists, nothing is done - } - - void setCurvatureInfo(CurvatureInfo *ci) - { - if (_curvature_info) // Q. is this an error condition? (T.K. 02-May-2011) - delete _curvature_info; - _curvature_info = ci; - } - - const CurvatureInfo *getCurvatureInfo() const - { - return _curvature_info; - } + CurvatureInfo *_curvature_info; + + 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 SVertex() + { + _Id = 0; + userdata = NULL; + _Shape = NULL; + _pViewVertex = 0; + _curvature_info = 0; + } + + /*! Builds a SVertex from 3D coordinates and an Id. */ + inline SVertex(const Vec3r &iPoint3D, const Id &id) + { + _Point3D = iPoint3D; + _Id = id; + userdata = NULL; + _Shape = NULL; + _pViewVertex = 0; + _curvature_info = 0; + } + + /*! Copy constructor. */ + inline SVertex(SVertex &iBrother) + { + _Id = iBrother._Id; + _Point3D = iBrother.point3D(); + _Point2D = iBrother.point2D(); + _Normals = iBrother._Normals; + _FEdges = iBrother.fedges(); + _Shape = iBrother.shape(); + _pViewVertex = iBrother._pViewVertex; + if (!(iBrother._curvature_info)) + _curvature_info = 0; + else + _curvature_info = new CurvatureInfo(*(iBrother._curvature_info)); + iBrother.userdata = this; + userdata = 0; + } + + /*! Destructor. */ + virtual ~SVertex() + { + if (_curvature_info) + delete _curvature_info; + } + + /*! Cloning method. */ + virtual SVertex *duplicate() + { + SVertex *clone = new SVertex(*this); + return clone; + } + + /*! operator == */ + virtual bool operator==(const SVertex &iBrother) + { + return ((_Point2D == iBrother._Point2D) && (_Point3D == iBrother._Point3D)); + } + + /* accessors */ + inline const Vec3r &point3D() const + { + return _Point3D; + } + + inline const Vec3r &point2D() const + { + return _Point2D; + } + + /*! Returns the set of normals for this Vertex. + * In a smooth surface, a vertex has exactly one normal. + * In a sharp surface, a vertex can have any number of normals. + */ + inline set<Vec3r> normals() + { + return _Normals; + } + + /*! Returns the number of different normals for this vertex. */ + inline unsigned normalsSize() const + { + return _Normals.size(); + } + + inline const vector<FEdge *> &fedges() + { + return _FEdges; + } + + inline fedges_container::iterator fedges_begin() + { + return _FEdges.begin(); + } + + inline fedges_container::iterator fedges_end() + { + return _FEdges.end(); + } + + inline SShape *shape() + { + return _Shape; + } + + inline real z() const + { + return _Point2D[2]; + } + + /*! If this SVertex is also a ViewVertex, this method returns a pointer onto this ViewVertex. + * 0 is returned otherwise. + */ + inline ViewVertex *viewvertex() + { + return _pViewVertex; + } + + /*! modifiers */ + /*! Sets the 3D coordinates of the SVertex. */ + inline void setPoint3D(const Vec3r &iPoint3D) + { + _Point3D = iPoint3D; + } + + /*! Sets the 3D projected coordinates of the SVertex. */ + inline void setPoint2D(const Vec3r &iPoint2D) + { + _Point2D = iPoint2D; + } + + /*! Adds a normal to the Svertex's set of normals. If the same normal is already in the set, nothing changes. */ + inline void AddNormal(const Vec3r &iNormal) + { + _Normals.insert(iNormal); // if iNormal in the set already exists, nothing is done + } + + void setCurvatureInfo(CurvatureInfo *ci) + { + if (_curvature_info) // Q. is this an error condition? (T.K. 02-May-2011) + delete _curvature_info; + _curvature_info = ci; + } + + const CurvatureInfo *getCurvatureInfo() const + { + return _curvature_info; + } #if 0 - /* Fredo's normal and curvature*/ - void setCurvatureFredo(real c) - { - _curvatureFredo = c; - } - - void setDirectionFredo(Vec2r d) - { - _directionFredo = d; - } - - real curvatureFredo () - { - return _curvatureFredo; - } - - const Vec2r directionFredo () - { - return _directionFredo; - } + /* Fredo's normal and curvature*/ + void setCurvatureFredo(real c) + { + _curvatureFredo = c; + } + + void setDirectionFredo(Vec2r d) + { + _directionFredo = d; + } + + real curvatureFredo () + { + return _curvatureFredo; + } + + const Vec2r directionFredo () + { + return _directionFredo; + } #endif - /*! Sets the Id */ - inline void setId(const Id& id) - { - _Id = id; - } - - inline void setFEdges(const vector<FEdge*>& iFEdges) - { - _FEdges = iFEdges; - } - - inline void setShape(SShape *iShape) - { - _Shape = iShape; - } - - inline void setViewVertex(ViewVertex *iViewVertex) - { - _pViewVertex = iViewVertex; - } - - /*! Add an FEdge to the list of edges emanating from this SVertex. */ - inline void AddFEdge(FEdge *iFEdge) - { - _FEdges.push_back(iFEdge); - } - - /*! Remove an FEdge from the list of edges emanating from this SVertex. */ - inline void RemoveFEdge(FEdge *iFEdge) - { - for (vector<FEdge *>::iterator fe = _FEdges.begin(), fend = _FEdges.end(); fe != fend; fe++) { - if (iFEdge == (*fe)) { - _FEdges.erase(fe); - break; - } - } - } - - /* replaces edge 1 by edge 2 in the list of edges */ - inline void Replace(FEdge *e1, FEdge *e2) - { - vector<FEdge *>::iterator insertedfe; - for (vector<FEdge *>::iterator fe = _FEdges.begin(), fend = _FEdges.end(); fe != fend; fe++) { - if ((*fe) == e1) { - insertedfe = _FEdges.insert(fe, e2);// inserts e2 before fe. - // returns an iterator pointing toward e2. fe is invalidated. - // we want to remove e1, but we can't use fe anymore: - ++insertedfe; // insertedfe points now to e1 - _FEdges.erase(insertedfe); - return; - } - } - } - -public: - /* Information access interface */ - FEdge *fedge(); // for non T vertex - - inline const Vec3r& point2d() const - { - return point2D(); - } - - inline const Vec3r& point3d() const - { - return point3D(); - } - - inline Vec3r normal() const - { - if (_Normals.size() == 1) - return (*(_Normals.begin())); - Exception::raiseException(); - return *(_Normals.begin()); - } - - //Material material() const ; - Id shape_id() const; - const SShape *shape() const; - float shape_importance() const; - - const int qi() const; - occluder_container::const_iterator occluders_begin() const; - occluder_container::const_iterator occluders_end() const; - bool occluders_empty() const; - int occluders_size() const; - const Polygon3r& occludee() const; - const SShape *occluded_shape() const; - const bool occludee_empty() const; - real z_discontinuity() const; + /*! Sets the Id */ + inline void setId(const Id &id) + { + _Id = id; + } + + inline void setFEdges(const vector<FEdge *> &iFEdges) + { + _FEdges = iFEdges; + } + + inline void setShape(SShape *iShape) + { + _Shape = iShape; + } + + inline void setViewVertex(ViewVertex *iViewVertex) + { + _pViewVertex = iViewVertex; + } + + /*! Add an FEdge to the list of edges emanating from this SVertex. */ + inline void AddFEdge(FEdge *iFEdge) + { + _FEdges.push_back(iFEdge); + } + + /*! Remove an FEdge from the list of edges emanating from this SVertex. */ + inline void RemoveFEdge(FEdge *iFEdge) + { + for (vector<FEdge *>::iterator fe = _FEdges.begin(), fend = _FEdges.end(); fe != fend; fe++) { + if (iFEdge == (*fe)) { + _FEdges.erase(fe); + break; + } + } + } + + /* replaces edge 1 by edge 2 in the list of edges */ + inline void Replace(FEdge *e1, FEdge *e2) + { + vector<FEdge *>::iterator insertedfe; + for (vector<FEdge *>::iterator fe = _FEdges.begin(), fend = _FEdges.end(); fe != fend; fe++) { + if ((*fe) == e1) { + insertedfe = _FEdges.insert(fe, e2); // inserts e2 before fe. + // returns an iterator pointing toward e2. fe is invalidated. + // we want to remove e1, but we can't use fe anymore: + ++insertedfe; // insertedfe points now to e1 + _FEdges.erase(insertedfe); + return; + } + } + } + + public: + /* Information access interface */ + FEdge *fedge(); // for non T vertex + + inline const Vec3r &point2d() const + { + return point2D(); + } + + inline const Vec3r &point3d() const + { + return point3D(); + } + + inline Vec3r normal() const + { + if (_Normals.size() == 1) + return (*(_Normals.begin())); + Exception::raiseException(); + return *(_Normals.begin()); + } + + //Material material() const ; + Id shape_id() const; + const SShape *shape() const; + float shape_importance() const; + + const int qi() const; + occluder_container::const_iterator occluders_begin() const; + occluder_container::const_iterator occluders_end() const; + bool occluders_empty() const; + int occluders_size() const; + const Polygon3r &occludee() const; + const SShape *occluded_shape() const; + const bool occludee_empty() const; + real z_discontinuity() const; #if 0 - inline float local_average_depth() const; - inline float local_depth_variance() const; - inline real local_average_density(float sigma = 2.3f) const; - inline Vec3r shaded_color() const; - inline Vec3r orientation2d() const; - inline Vec3r orientation3d() const; - inline Vec3r curvature2d_as_vector() const; - /*! angle in radians */ - inline real curvature2d_as_angle() const; + inline float local_average_depth() const; + inline float local_depth_variance() const; + inline real local_average_density(float sigma = 2.3f) const; + inline Vec3r shaded_color() const; + inline Vec3r orientation2d() const; + inline Vec3r orientation3d() const; + inline Vec3r curvature2d_as_vector() const; + /*! angle in radians */ + inline real curvature2d_as_angle() const; #endif #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:SVertex") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:SVertex") #endif }; @@ -471,493 +470,494 @@ class ViewEdge; * This class is specialized into a smooth and a sharp version since their properties slightly vary from * one to the other. */ -class FEdge : public Interface1D -{ -public: // Implementation of Interface0D - /*! Returns the string "FEdge". */ - virtual string getExactTypeName() const - { - return "FEdge"; - } - - // Data access methods - - /*! Returns the 2D length of the FEdge. */ - virtual real getLength2D() const - { - if (!_VertexA || !_VertexB) - return 0; - return (_VertexB->getPoint2D() - _VertexA->getPoint2D()).norm(); - } - - /*! Returns the Id of the FEdge. */ - virtual Id getId() const - { - return _Id; - } - -public: - // An edge can only be of one kind (SILHOUETTE or BORDER, etc...) - // For an multi-nature edge there must be several different FEdge. - // DEBUG: - // Vec3r A; - // Vec3r u; - // vector<Polygon3r> _Occludees; - // Vec3r intersection; - // vector<Vec3i> _Cells; - -protected: - SVertex *_VertexA; - SVertex *_VertexB; - Id _Id; - Nature::EdgeNature _Nature; - //vector<Polygon3r> _Occluders; // visibility // NOT HANDLED BY THE COPY CONSTRUCTOR!! - - FEdge *_NextEdge; // next edge on the chain - FEdge *_PreviousEdge; - ViewEdge *_ViewEdge; - // Sometimes we need to deport the visibility computation onto another edge. For example the exact edges use - // edges of the mesh to compute their visibility - - Polygon3r _aFace; // The occluded face which lies on the right of a silhouette edge - Vec3r _occludeeIntersection; - bool _occludeeEmpty; - - bool _isSmooth; - - bool _isInImage; - - bool _isTemporary; - -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 FEdge() - { - userdata = NULL; - _VertexA = NULL; - _VertexB = NULL; - _Nature = Nature::NO_FEATURE; - _NextEdge = NULL; - _PreviousEdge = NULL; - _ViewEdge = NULL; - //_hasVisibilityPoint = false; - _occludeeEmpty = true; - _isSmooth = false; - _isInImage = true; - _isTemporary = false; - } - - /*! Builds an FEdge going from vA to vB. */ - inline FEdge(SVertex *vA, SVertex *vB) - { - userdata = NULL; - _VertexA = vA; - _VertexB = vB; - _Nature = Nature::NO_FEATURE; - _NextEdge = NULL; - _PreviousEdge = NULL; - _ViewEdge = NULL; - //_hasVisibilityPoint = false; - _occludeeEmpty = true; - _isSmooth = false; - _isInImage = true; - _isTemporary = false; - } - - /*! Copy constructor */ - inline FEdge(FEdge& iBrother) - { - _VertexA = iBrother.vertexA(); - _VertexB = iBrother.vertexB(); - _NextEdge = iBrother.nextEdge(); - _PreviousEdge = iBrother._PreviousEdge; - _Nature = iBrother.getNature(); - _Id = iBrother._Id; - _ViewEdge = iBrother._ViewEdge; - //_hasVisibilityPoint = iBrother._hasVisibilityPoint; - //_VisibilityPointA = iBrother._VisibilityPointA; - //_VisibilityPointB = iBrother._VisibilityPointB; - _aFace = iBrother._aFace; - _occludeeEmpty = iBrother._occludeeEmpty; - _isSmooth = iBrother._isSmooth; - _isInImage = iBrother._isInImage; - _isTemporary = iBrother._isTemporary; - iBrother.userdata = this; - userdata = 0; - } - - /*! Destructor */ - virtual ~FEdge() {} - - /*! Cloning method. */ - virtual FEdge *duplicate() - { - FEdge *clone = new FEdge(*this); - return clone; - } - - /* accessors */ - /*! Returns the first SVertex. */ - inline SVertex *vertexA() - { - return _VertexA; - } - - /*! Returns the second SVertex. */ - inline SVertex *vertexB() - { - return _VertexB; - } - - /*! Returns the first SVertex if i=0, the seccond SVertex if i=1. */ - inline SVertex *operator[](const unsigned short int& i) const - { - return (i % 2 == 0) ? _VertexA : _VertexB; - } - - /*! Returns the nature of the FEdge. */ - inline Nature::EdgeNature getNature() const - { - return _Nature; - } - - /*! Returns the FEdge following this one in the ViewEdge. - * If this FEdge is the last of the ViewEdge, 0 is returned. - */ - inline FEdge *nextEdge() - { - return _NextEdge; - } - - /*! Returns the Edge preceding this one in the ViewEdge. - * If this FEdge is the first one of the ViewEdge, 0 is returned. - */ - inline FEdge *previousEdge() - { - return _PreviousEdge; - } - - inline SShape *shape() - { - return _VertexA->shape(); - } +class FEdge : public Interface1D { + public: // Implementation of Interface0D + /*! Returns the string "FEdge". */ + virtual string getExactTypeName() const + { + return "FEdge"; + } + + // Data access methods + + /*! Returns the 2D length of the FEdge. */ + virtual real getLength2D() const + { + if (!_VertexA || !_VertexB) + return 0; + return (_VertexB->getPoint2D() - _VertexA->getPoint2D()).norm(); + } + + /*! Returns the Id of the FEdge. */ + virtual Id getId() const + { + return _Id; + } + + public: + // An edge can only be of one kind (SILHOUETTE or BORDER, etc...) + // For an multi-nature edge there must be several different FEdge. + // DEBUG: + // Vec3r A; + // Vec3r u; + // vector<Polygon3r> _Occludees; + // Vec3r intersection; + // vector<Vec3i> _Cells; + + protected: + SVertex *_VertexA; + SVertex *_VertexB; + Id _Id; + Nature::EdgeNature _Nature; + //vector<Polygon3r> _Occluders; // visibility // NOT HANDLED BY THE COPY CONSTRUCTOR!! + + FEdge *_NextEdge; // next edge on the chain + FEdge *_PreviousEdge; + ViewEdge *_ViewEdge; + // Sometimes we need to deport the visibility computation onto another edge. For example the exact edges use + // edges of the mesh to compute their visibility + + Polygon3r _aFace; // The occluded face which lies on the right of a silhouette edge + Vec3r _occludeeIntersection; + bool _occludeeEmpty; + + bool _isSmooth; + + bool _isInImage; + + bool _isTemporary; + + 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 FEdge() + { + userdata = NULL; + _VertexA = NULL; + _VertexB = NULL; + _Nature = Nature::NO_FEATURE; + _NextEdge = NULL; + _PreviousEdge = NULL; + _ViewEdge = NULL; + //_hasVisibilityPoint = false; + _occludeeEmpty = true; + _isSmooth = false; + _isInImage = true; + _isTemporary = false; + } + + /*! Builds an FEdge going from vA to vB. */ + inline FEdge(SVertex *vA, SVertex *vB) + { + userdata = NULL; + _VertexA = vA; + _VertexB = vB; + _Nature = Nature::NO_FEATURE; + _NextEdge = NULL; + _PreviousEdge = NULL; + _ViewEdge = NULL; + //_hasVisibilityPoint = false; + _occludeeEmpty = true; + _isSmooth = false; + _isInImage = true; + _isTemporary = false; + } + + /*! Copy constructor */ + inline FEdge(FEdge &iBrother) + { + _VertexA = iBrother.vertexA(); + _VertexB = iBrother.vertexB(); + _NextEdge = iBrother.nextEdge(); + _PreviousEdge = iBrother._PreviousEdge; + _Nature = iBrother.getNature(); + _Id = iBrother._Id; + _ViewEdge = iBrother._ViewEdge; + //_hasVisibilityPoint = iBrother._hasVisibilityPoint; + //_VisibilityPointA = iBrother._VisibilityPointA; + //_VisibilityPointB = iBrother._VisibilityPointB; + _aFace = iBrother._aFace; + _occludeeEmpty = iBrother._occludeeEmpty; + _isSmooth = iBrother._isSmooth; + _isInImage = iBrother._isInImage; + _isTemporary = iBrother._isTemporary; + iBrother.userdata = this; + userdata = 0; + } + + /*! Destructor */ + virtual ~FEdge() + { + } + + /*! Cloning method. */ + virtual FEdge *duplicate() + { + FEdge *clone = new FEdge(*this); + return clone; + } + + /* accessors */ + /*! Returns the first SVertex. */ + inline SVertex *vertexA() + { + return _VertexA; + } + + /*! Returns the second SVertex. */ + inline SVertex *vertexB() + { + return _VertexB; + } + + /*! Returns the first SVertex if i=0, the seccond SVertex if i=1. */ + inline SVertex *operator[](const unsigned short int &i) const + { + return (i % 2 == 0) ? _VertexA : _VertexB; + } + + /*! Returns the nature of the FEdge. */ + inline Nature::EdgeNature getNature() const + { + return _Nature; + } + + /*! Returns the FEdge following this one in the ViewEdge. + * If this FEdge is the last of the ViewEdge, 0 is returned. + */ + inline FEdge *nextEdge() + { + return _NextEdge; + } + + /*! Returns the Edge preceding this one in the ViewEdge. + * If this FEdge is the first one of the ViewEdge, 0 is returned. + */ + inline FEdge *previousEdge() + { + return _PreviousEdge; + } + + inline SShape *shape() + { + return _VertexA->shape(); + } #if 0 - inline int invisibility() const - { - return _Occluders.size(); - } + inline int invisibility() const + { + return _Occluders.size(); + } #endif - int invisibility() const; + int invisibility() const; #if 0 - inline const vector<Polygon3r>& occluders() const - { - return _Occluders; - } + inline const vector<Polygon3r>& occluders() const + { + return _Occluders; + } #endif - /*! Returns a pointer to the ViewEdge to which this FEdge belongs to. */ - inline ViewEdge *viewedge() const - { - return _ViewEdge; - } + /*! Returns a pointer to the ViewEdge to which this FEdge belongs to. */ + inline ViewEdge *viewedge() const + { + return _ViewEdge; + } - inline Vec3r center3d() - { - return Vec3r((_VertexA->point3D() + _VertexB->point3D()) / 2.0); - } + inline Vec3r center3d() + { + return Vec3r((_VertexA->point3D() + _VertexB->point3D()) / 2.0); + } - inline Vec3r center2d() - { - return Vec3r((_VertexA->point2D() + _VertexB->point2D()) / 2.0); - } + inline Vec3r center2d() + { + return Vec3r((_VertexA->point2D() + _VertexB->point2D()) / 2.0); + } #if 0 - inline bool hasVisibilityPoint() const - { - return _hasVisibilityPoint; - } - - inline Vec3r visibilityPointA() const - { - return _VisibilityPointA; - } - - inline Vec3r visibilityPointB() const - { - return _VisibilityPointB; - } + inline bool hasVisibilityPoint() const + { + return _hasVisibilityPoint; + } + + inline Vec3r visibilityPointA() const + { + return _VisibilityPointA; + } + + inline Vec3r visibilityPointB() const + { + return _VisibilityPointB; + } #endif - inline const Polygon3r& aFace() const - { - return _aFace; - } - - inline const Vec3r& getOccludeeIntersection() - { - return _occludeeIntersection; - } - - inline bool getOccludeeEmpty() - { - return _occludeeEmpty; - } - - /*! Returns true if this FEdge is a smooth FEdge. */ - inline bool isSmooth() const - { - return _isSmooth; - } - - inline bool isInImage () const - { - return _isInImage; - } - - inline bool isTemporary() const - { - return _isTemporary; - } - - /* modifiers */ - /*! Sets the first SVertex. */ - inline void setVertexA(SVertex *vA) - { - _VertexA = vA; - } - - /*! Sets the second SVertex. */ - inline void setVertexB(SVertex *vB) - { - _VertexB = vB; - } - - /*! Sets the FEdge Id . */ - inline void setId(const Id& id) - { - _Id = id; - } - - /*! Sets the pointer to the next FEdge. */ - inline void setNextEdge(FEdge *iEdge) - { - _NextEdge = iEdge; - } - - /*! Sets the pointer to the previous FEdge. */ - inline void setPreviousEdge(FEdge *iEdge) - { - _PreviousEdge = iEdge; - } - - /*! Sets the nature of this FEdge. */ - inline void setNature(Nature::EdgeNature iNature) - { - _Nature = iNature; - } + inline const Polygon3r &aFace() const + { + return _aFace; + } + + inline const Vec3r &getOccludeeIntersection() + { + return _occludeeIntersection; + } + + inline bool getOccludeeEmpty() + { + return _occludeeEmpty; + } + + /*! Returns true if this FEdge is a smooth FEdge. */ + inline bool isSmooth() const + { + return _isSmooth; + } + + inline bool isInImage() const + { + return _isInImage; + } + + inline bool isTemporary() const + { + return _isTemporary; + } + + /* modifiers */ + /*! Sets the first SVertex. */ + inline void setVertexA(SVertex *vA) + { + _VertexA = vA; + } + + /*! Sets the second SVertex. */ + inline void setVertexB(SVertex *vB) + { + _VertexB = vB; + } + + /*! Sets the FEdge Id . */ + inline void setId(const Id &id) + { + _Id = id; + } + + /*! Sets the pointer to the next FEdge. */ + inline void setNextEdge(FEdge *iEdge) + { + _NextEdge = iEdge; + } + + /*! Sets the pointer to the previous FEdge. */ + inline void setPreviousEdge(FEdge *iEdge) + { + _PreviousEdge = iEdge; + } + + /*! Sets the nature of this FEdge. */ + inline void setNature(Nature::EdgeNature iNature) + { + _Nature = iNature; + } #if 0 - inline void AddOccluder(Polygon3r& iPolygon) - { - _Occluders.push_back(iPolygon); - } + inline void AddOccluder(Polygon3r& iPolygon) + { + _Occluders.push_back(iPolygon); + } #endif - /*! Sets the ViewEdge to which this FEdge belongs to. */ - inline void setViewEdge(ViewEdge *iViewEdge) - { - _ViewEdge = iViewEdge; - } + /*! Sets the ViewEdge to which this FEdge belongs to. */ + inline void setViewEdge(ViewEdge *iViewEdge) + { + _ViewEdge = iViewEdge; + } #if 0 - inline void setHasVisibilityPoint(bool iBool) - { - _hasVisibilityPoint = iBool; - } - - inline void setVisibilityPointA(const Vec3r& iPoint) - { - _VisibilityPointA = iPoint; - } - - inline void setVisibilityPointB(const Vec3r& iPoint) - { - _VisibilityPointB = iPoint; - } + inline void setHasVisibilityPoint(bool iBool) + { + _hasVisibilityPoint = iBool; + } + + inline void setVisibilityPointA(const Vec3r& iPoint) + { + _VisibilityPointA = iPoint; + } + + inline void setVisibilityPointB(const Vec3r& iPoint) + { + _VisibilityPointB = iPoint; + } #endif - inline void setaFace(Polygon3r& iFace) - { - _aFace = iFace; - } - - inline void setOccludeeIntersection(const Vec3r& iPoint) - { - _occludeeIntersection = iPoint; - } - - inline void setOccludeeEmpty(bool iempty) - { - _occludeeEmpty = iempty; - } - - /*! Sets the flag telling whether this FEdge is smooth or sharp. - * true for Smooth, false for Sharp. - */ - inline void setSmooth(bool iFlag) - { - _isSmooth = iFlag; - } - - inline void setIsInImage (bool iFlag) - { - _isInImage = iFlag; - } - - inline void setTemporary(bool iFlag) - { - _isTemporary = iFlag; - } - - /* checks whether two FEdge have a common vertex. - * Returns a pointer on the common vertex if it exists, NULL otherwise. - */ - static inline SVertex *CommonVertex(FEdge *iEdge1, FEdge *iEdge2) - { - if ((NULL == iEdge1) || (NULL == iEdge2)) - return NULL; - - SVertex *sv1 = iEdge1->vertexA(); - SVertex *sv2 = iEdge1->vertexB(); - SVertex *sv3 = iEdge2->vertexA(); - SVertex *sv4 = iEdge2->vertexB(); - - if ((sv1 == sv3) || (sv1 == sv4)) { - return sv1; - } - else if ((sv2 == sv3) || (sv2 == sv4)) { - return sv2; - } - - return NULL; - } - - inline const SVertex *min2d() const - { - if (_VertexA->point2D() < _VertexB->point2D()) - return _VertexA; - else - return _VertexB; - } - - inline const SVertex *max2d() const - { - if (_VertexA->point2D() < _VertexB->point2D()) - return _VertexB; - else - return _VertexA; - } - - /* Information access interface */ - - //Material material() const; - Id shape_id() const; - const SShape *shape() const; - float shape_importance() const; - - inline const int qi() const - { - return invisibility(); - } - - occluder_container::const_iterator occluders_begin() const; - occluder_container::const_iterator occluders_end() const; - bool occluders_empty() const; - int occluders_size() const; - - inline const Polygon3r& occludee() const - { - return aFace(); - } - - const SShape *occluded_shape() const; + inline void setaFace(Polygon3r &iFace) + { + _aFace = iFace; + } + + inline void setOccludeeIntersection(const Vec3r &iPoint) + { + _occludeeIntersection = iPoint; + } + + inline void setOccludeeEmpty(bool iempty) + { + _occludeeEmpty = iempty; + } + + /*! Sets the flag telling whether this FEdge is smooth or sharp. + * true for Smooth, false for Sharp. + */ + inline void setSmooth(bool iFlag) + { + _isSmooth = iFlag; + } + + inline void setIsInImage(bool iFlag) + { + _isInImage = iFlag; + } + + inline void setTemporary(bool iFlag) + { + _isTemporary = iFlag; + } + + /* checks whether two FEdge have a common vertex. + * Returns a pointer on the common vertex if it exists, NULL otherwise. + */ + static inline SVertex *CommonVertex(FEdge *iEdge1, FEdge *iEdge2) + { + if ((NULL == iEdge1) || (NULL == iEdge2)) + return NULL; + + SVertex *sv1 = iEdge1->vertexA(); + SVertex *sv2 = iEdge1->vertexB(); + SVertex *sv3 = iEdge2->vertexA(); + SVertex *sv4 = iEdge2->vertexB(); + + if ((sv1 == sv3) || (sv1 == sv4)) { + return sv1; + } + else if ((sv2 == sv3) || (sv2 == sv4)) { + return sv2; + } + + return NULL; + } + + inline const SVertex *min2d() const + { + if (_VertexA->point2D() < _VertexB->point2D()) + return _VertexA; + else + return _VertexB; + } + + inline const SVertex *max2d() const + { + if (_VertexA->point2D() < _VertexB->point2D()) + return _VertexB; + else + return _VertexA; + } + + /* Information access interface */ + + //Material material() const; + Id shape_id() const; + const SShape *shape() const; + float shape_importance() const; + + inline const int qi() const + { + return invisibility(); + } + + occluder_container::const_iterator occluders_begin() const; + occluder_container::const_iterator occluders_end() const; + bool occluders_empty() const; + int occluders_size() const; + + inline const Polygon3r &occludee() const + { + return aFace(); + } + + const SShape *occluded_shape() const; #if 0 - inline const bool occludee_empty() const - { - return _occludeeEmpty; - } + inline const bool occludee_empty() const + { + return _occludeeEmpty; + } #endif - const bool occludee_empty() const; - real z_discontinuity() const; + const bool occludee_empty() const; + real z_discontinuity() const; #if 0 - inline float local_average_depth(int iCombination = 0) const; - inline float local_depth_variance(int iCombination = 0) const; - inline real local_average_density(float sigma = 2.3f, int iCombination = 0) const; - inline Vec3r shaded_color(int iCombination = 0) const {} + inline float local_average_depth(int iCombination = 0) const; + inline float local_depth_variance(int iCombination = 0) const; + inline real local_average_density(float sigma = 2.3f, int iCombination = 0) const; + inline Vec3r shaded_color(int iCombination = 0) const {} #endif - int viewedge_nature() const; + int viewedge_nature() const; - //float viewedge_length() const; + //float viewedge_length() const; - inline Vec3r orientation2d() const - { - return Vec3r(_VertexB->point2d() - _VertexA->point2d()); - } + inline Vec3r orientation2d() const + { + return Vec3r(_VertexB->point2d() - _VertexA->point2d()); + } - inline Vec3r orientation3d() const - { - return Vec3r(_VertexB->point3d() - _VertexA->point3d()); - } + inline Vec3r orientation3d() const + { + return Vec3r(_VertexB->point3d() - _VertexA->point3d()); + } #if 0 - inline real curvature2d() const - { - return viewedge()->curvature2d((_VertexA->point2d() + _VertexB->point2d()) / 2.0); - } + inline real curvature2d() const + { + return viewedge()->curvature2d((_VertexA->point2d() + _VertexB->point2d()) / 2.0); + } - inline Vec3r curvature2d_as_vector(int iCombination = 0) const; + inline Vec3r curvature2d_as_vector(int iCombination = 0) const; - /* angle in degrees*/ - inline real curvature2d_as_angle(int iCombination = 0) const; + /* angle in degrees*/ + inline real curvature2d_as_angle(int iCombination = 0) const; #endif - // Iterator access (Interface1D) - /*! Returns an iterator over the 2 (!) SVertex pointing to the first SVertex. */ - virtual inline Interface0DIterator verticesBegin(); - - /*! Returns an iterator over the 2 (!) SVertex pointing after the last SVertex. */ - virtual inline Interface0DIterator verticesEnd(); - - /*! Returns an iterator over the FEdge points, pointing to the first point. The difference with verticesBegin() - * is that here we can iterate over points of the FEdge at a any given sampling. - * Indeed, for each iteration, a virtual point is created. - * \param t: - * The sampling with which we want to iterate over points of this FEdge. - */ - virtual inline Interface0DIterator pointsBegin(float t = 0.0f); - - /*! Returns an iterator over the FEdge points, pointing after the last point. The difference with verticesEnd() - * is that here we can iterate over points of the FEdge at a any given sampling. - * Indeed, for each iteration, a virtual point is created. - * \param t: - * The sampling with which we want to iterate over points of this FEdge. - */ - virtual inline Interface0DIterator pointsEnd(float t = 0.0f); + // Iterator access (Interface1D) + /*! Returns an iterator over the 2 (!) SVertex pointing to the first SVertex. */ + virtual inline Interface0DIterator verticesBegin(); + + /*! Returns an iterator over the 2 (!) SVertex pointing after the last SVertex. */ + virtual inline Interface0DIterator verticesEnd(); + + /*! Returns an iterator over the FEdge points, pointing to the first point. The difference with verticesBegin() + * is that here we can iterate over points of the FEdge at a any given sampling. + * Indeed, for each iteration, a virtual point is created. + * \param t: + * The sampling with which we want to iterate over points of this FEdge. + */ + virtual inline Interface0DIterator pointsBegin(float t = 0.0f); + + /*! Returns an iterator over the FEdge points, pointing after the last point. The difference with verticesEnd() + * is that here we can iterate over points of the FEdge at a any given sampling. + * Indeed, for each iteration, a virtual point is created. + * \param t: + * The sampling with which we want to iterate over points of this FEdge. + */ + virtual inline Interface0DIterator pointsEnd(float t = 0.0f); #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:FEdge") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:FEdge") #endif }; @@ -968,162 +968,161 @@ public: namespace FEdgeInternal { -class SVertexIterator : public Interface0DIteratorNested -{ -public: - SVertexIterator() - { - _vertex = NULL; - _edge = NULL; - } - - SVertexIterator(const SVertexIterator& vi) - { - _vertex = vi._vertex; - _edge = vi._edge; - } - - SVertexIterator(SVertex *v, FEdge *edge) - { - _vertex = v; - _edge = edge; - } - - SVertexIterator& operator=(const SVertexIterator& vi) - { - _vertex = vi._vertex; - _edge = vi._edge; - return *this; - } - - virtual string getExactTypeName() const - { - return "SVertexIterator"; - } - - virtual SVertex& operator*() - { - return *_vertex; - } - - virtual SVertex *operator->() - { - return &(operator*()); - } - - virtual SVertexIterator& operator++() - { - increment(); - return *this; - } - - virtual SVertexIterator operator++(int) - { - SVertexIterator ret(*this); - increment(); - return ret; - } - - virtual SVertexIterator& operator--() - { - decrement(); - return *this; - } - - virtual SVertexIterator operator--(int) - { - SVertexIterator ret(*this); - decrement(); - return ret; - } - - virtual int increment() - { - if (_vertex == _edge->vertexB()) { - _vertex = 0; - return 0; - } - _vertex = _edge->vertexB(); - return 0; - } - - virtual int decrement() - { - if (_vertex == _edge->vertexA()) { - _vertex = 0; - return 0; - } - _vertex = _edge->vertexA(); - return 0; - } - - virtual bool isBegin() const - { - return _vertex == _edge->vertexA(); - } - - virtual bool isEnd() const - { - return _vertex == _edge->vertexB(); - } - - virtual bool operator==(const Interface0DIteratorNested& it) const - { - const SVertexIterator *it_exact = dynamic_cast<const SVertexIterator*>(&it); - if (!it_exact) - return false; - return ((_vertex == it_exact->_vertex) && (_edge == it_exact->_edge)); - } - - virtual float t() const - { - if (_vertex == _edge->vertexA()) { - return 0.0f; - } - return ((float)_edge->getLength2D()); - } - virtual float u() const - { - if (_vertex == _edge->vertexA()) { - return 0.0f; - } - return 1.0f; - } - - virtual SVertexIterator *copy() const - { - return new SVertexIterator(*this); - } - -private: - SVertex *_vertex; - FEdge *_edge; +class SVertexIterator : public Interface0DIteratorNested { + public: + SVertexIterator() + { + _vertex = NULL; + _edge = NULL; + } + + SVertexIterator(const SVertexIterator &vi) + { + _vertex = vi._vertex; + _edge = vi._edge; + } + + SVertexIterator(SVertex *v, FEdge *edge) + { + _vertex = v; + _edge = edge; + } + + SVertexIterator &operator=(const SVertexIterator &vi) + { + _vertex = vi._vertex; + _edge = vi._edge; + return *this; + } + + virtual string getExactTypeName() const + { + return "SVertexIterator"; + } + + virtual SVertex &operator*() + { + return *_vertex; + } + + virtual SVertex *operator->() + { + return &(operator*()); + } + + virtual SVertexIterator &operator++() + { + increment(); + return *this; + } + + virtual SVertexIterator operator++(int) + { + SVertexIterator ret(*this); + increment(); + return ret; + } + + virtual SVertexIterator &operator--() + { + decrement(); + return *this; + } + + virtual SVertexIterator operator--(int) + { + SVertexIterator ret(*this); + decrement(); + return ret; + } + + virtual int increment() + { + if (_vertex == _edge->vertexB()) { + _vertex = 0; + return 0; + } + _vertex = _edge->vertexB(); + return 0; + } + + virtual int decrement() + { + if (_vertex == _edge->vertexA()) { + _vertex = 0; + return 0; + } + _vertex = _edge->vertexA(); + return 0; + } + + virtual bool isBegin() const + { + return _vertex == _edge->vertexA(); + } + + virtual bool isEnd() const + { + return _vertex == _edge->vertexB(); + } + + virtual bool operator==(const Interface0DIteratorNested &it) const + { + const SVertexIterator *it_exact = dynamic_cast<const SVertexIterator *>(&it); + if (!it_exact) + return false; + return ((_vertex == it_exact->_vertex) && (_edge == it_exact->_edge)); + } + + virtual float t() const + { + if (_vertex == _edge->vertexA()) { + return 0.0f; + } + return ((float)_edge->getLength2D()); + } + virtual float u() const + { + if (_vertex == _edge->vertexA()) { + return 0.0f; + } + return 1.0f; + } + + virtual SVertexIterator *copy() const + { + return new SVertexIterator(*this); + } + + private: + SVertex *_vertex; + FEdge *_edge; }; -} // end of namespace FEdgeInternal +} // end of namespace FEdgeInternal // Iterator access (implementation) Interface0DIterator FEdge::verticesBegin() { - Interface0DIterator ret(new FEdgeInternal::SVertexIterator(_VertexA, this)); - return ret; + Interface0DIterator ret(new FEdgeInternal::SVertexIterator(_VertexA, this)); + return ret; } Interface0DIterator FEdge::verticesEnd() { - Interface0DIterator ret(new FEdgeInternal::SVertexIterator(0, this)); - return ret; + Interface0DIterator ret(new FEdgeInternal::SVertexIterator(0, this)); + return ret; } Interface0DIterator FEdge::pointsBegin(float /*t*/) { - return verticesBegin(); + return verticesBegin(); } Interface0DIterator FEdge::pointsEnd(float /*t*/) { - return verticesEnd(); + return verticesEnd(); } /*! Class defining a sharp FEdge. A Sharp FEdge corresponds to an initial edge of the input mesh. @@ -1131,267 +1130,268 @@ Interface0DIterator FEdge::pointsEnd(float /*t*/) * by two faces of the mesh. Face a lies on its right whereas Face b lies on its left. * If it is a border edge, then it doesn't have any face on its right, and thus Face a = 0. */ -class FEdgeSharp : public FEdge -{ -protected: - Vec3r _aNormal; // When following the edge, normal of the right face - Vec3r _bNormal; // When following the edge, normal of the left face - unsigned _aFrsMaterialIndex; - unsigned _bFrsMaterialIndex; - bool _aFaceMark; - bool _bFaceMark; - -public: - /*! Returns the string "FEdgeSharp" . */ - virtual string getExactTypeName() const - { - return "FEdgeSharp"; - } - - /*! Default constructor. */ - inline FEdgeSharp() : FEdge() - { - _aFrsMaterialIndex = _bFrsMaterialIndex = 0; - _aFaceMark = _bFaceMark = false; - } - - /*! Builds an FEdgeSharp going from vA to vB. */ - inline FEdgeSharp(SVertex *vA, SVertex *vB) : FEdge(vA, vB) - { - _aFrsMaterialIndex = _bFrsMaterialIndex = 0; - _aFaceMark = _bFaceMark = false; - } - - /*! Copy constructor. */ - inline FEdgeSharp(FEdgeSharp& iBrother) : FEdge(iBrother) - { - _aNormal = iBrother._aNormal; - _bNormal = iBrother._bNormal; - _aFrsMaterialIndex = iBrother._aFrsMaterialIndex; - _bFrsMaterialIndex = iBrother._bFrsMaterialIndex; - _aFaceMark = iBrother._aFaceMark; - _bFaceMark = iBrother._bFaceMark; - } - - /*! Destructor. */ - virtual ~FEdgeSharp() {} - - /*! Cloning method. */ - virtual FEdge *duplicate() - { - FEdge *clone = new FEdgeSharp(*this); - return clone; - } - - /*! Returns the normal to the face lying on the right of the FEdge. If this FEdge is a border, - * it has no Face on its right and therefore, no normal. - */ - inline const Vec3r& normalA() - { - return _aNormal; - } - - /*! Returns the normal to the face lying on the left of the FEdge. */ - inline const Vec3r& normalB() - { - return _bNormal; - } - - /*! Returns the index of the material of the face lying on the - * right of the FEdge. If this FEdge is a border, - * it has no Face on its right and therefore, no material. - */ - inline unsigned aFrsMaterialIndex() const - { - return _aFrsMaterialIndex; - } - - /*! Returns the material of the face lying on the right of the FEdge. If this FEdge is a border, - * it has no Face on its right and therefore, no material. - */ - const FrsMaterial& aFrsMaterial() const; - - /*! Returns the index of the material of the face lying on the left of the FEdge. */ - inline unsigned bFrsMaterialIndex() const - { - return _bFrsMaterialIndex; - } - - /*! Returns the material of the face lying on the left of the FEdge. */ - const FrsMaterial& bFrsMaterial() const; - - /*! Returns the face mark of the face lying on the right of the FEdge. - * If this FEdge is a border, it has no Face on its right and thus false is returned. - */ - inline bool aFaceMark() const - { - return _aFaceMark; - } - - /*! Returns the face mark of the face lying on the left of the FEdge. */ - inline bool bFaceMark() const - { - return _bFaceMark; - } - - /*! Sets the normal to the face lying on the right of the FEdge. */ - inline void setNormalA(const Vec3r& iNormal) - { - _aNormal = iNormal; - } - - /*! Sets the normal to the face lying on the left of the FEdge. */ - inline void setNormalB(const Vec3r& iNormal) - { - _bNormal = iNormal; - } - - /*! Sets the index of the material lying on the right of the FEdge.*/ - inline void setaFrsMaterialIndex(unsigned i) - { - _aFrsMaterialIndex = i; - } - - /*! Sets the index of the material lying on the left of the FEdge.*/ - inline void setbFrsMaterialIndex(unsigned i) - { - _bFrsMaterialIndex = i; - } - - /*! Sets the face mark of the face lying on the right of the FEdge. */ - inline void setaFaceMark(bool iFaceMark) - { - _aFaceMark = iFaceMark; - } - - /*! Sets the face mark of the face lying on the left of the FEdge. */ - inline void setbFaceMark(bool iFaceMark) - { - _bFaceMark = iFaceMark; - } +class FEdgeSharp : public FEdge { + protected: + Vec3r _aNormal; // When following the edge, normal of the right face + Vec3r _bNormal; // When following the edge, normal of the left face + unsigned _aFrsMaterialIndex; + unsigned _bFrsMaterialIndex; + bool _aFaceMark; + bool _bFaceMark; + + public: + /*! Returns the string "FEdgeSharp" . */ + virtual string getExactTypeName() const + { + return "FEdgeSharp"; + } + + /*! Default constructor. */ + inline FEdgeSharp() : FEdge() + { + _aFrsMaterialIndex = _bFrsMaterialIndex = 0; + _aFaceMark = _bFaceMark = false; + } + + /*! Builds an FEdgeSharp going from vA to vB. */ + inline FEdgeSharp(SVertex *vA, SVertex *vB) : FEdge(vA, vB) + { + _aFrsMaterialIndex = _bFrsMaterialIndex = 0; + _aFaceMark = _bFaceMark = false; + } + + /*! Copy constructor. */ + inline FEdgeSharp(FEdgeSharp &iBrother) : FEdge(iBrother) + { + _aNormal = iBrother._aNormal; + _bNormal = iBrother._bNormal; + _aFrsMaterialIndex = iBrother._aFrsMaterialIndex; + _bFrsMaterialIndex = iBrother._bFrsMaterialIndex; + _aFaceMark = iBrother._aFaceMark; + _bFaceMark = iBrother._bFaceMark; + } + + /*! Destructor. */ + virtual ~FEdgeSharp() + { + } + + /*! Cloning method. */ + virtual FEdge *duplicate() + { + FEdge *clone = new FEdgeSharp(*this); + return clone; + } + + /*! Returns the normal to the face lying on the right of the FEdge. If this FEdge is a border, + * it has no Face on its right and therefore, no normal. + */ + inline const Vec3r &normalA() + { + return _aNormal; + } + + /*! Returns the normal to the face lying on the left of the FEdge. */ + inline const Vec3r &normalB() + { + return _bNormal; + } + + /*! Returns the index of the material of the face lying on the + * right of the FEdge. If this FEdge is a border, + * it has no Face on its right and therefore, no material. + */ + inline unsigned aFrsMaterialIndex() const + { + return _aFrsMaterialIndex; + } + + /*! Returns the material of the face lying on the right of the FEdge. If this FEdge is a border, + * it has no Face on its right and therefore, no material. + */ + const FrsMaterial &aFrsMaterial() const; + + /*! Returns the index of the material of the face lying on the left of the FEdge. */ + inline unsigned bFrsMaterialIndex() const + { + return _bFrsMaterialIndex; + } + + /*! Returns the material of the face lying on the left of the FEdge. */ + const FrsMaterial &bFrsMaterial() const; + + /*! Returns the face mark of the face lying on the right of the FEdge. + * If this FEdge is a border, it has no Face on its right and thus false is returned. + */ + inline bool aFaceMark() const + { + return _aFaceMark; + } + + /*! Returns the face mark of the face lying on the left of the FEdge. */ + inline bool bFaceMark() const + { + return _bFaceMark; + } + + /*! Sets the normal to the face lying on the right of the FEdge. */ + inline void setNormalA(const Vec3r &iNormal) + { + _aNormal = iNormal; + } + + /*! Sets the normal to the face lying on the left of the FEdge. */ + inline void setNormalB(const Vec3r &iNormal) + { + _bNormal = iNormal; + } + + /*! Sets the index of the material lying on the right of the FEdge.*/ + inline void setaFrsMaterialIndex(unsigned i) + { + _aFrsMaterialIndex = i; + } + + /*! Sets the index of the material lying on the left of the FEdge.*/ + inline void setbFrsMaterialIndex(unsigned i) + { + _bFrsMaterialIndex = i; + } + + /*! Sets the face mark of the face lying on the right of the FEdge. */ + inline void setaFaceMark(bool iFaceMark) + { + _aFaceMark = iFaceMark; + } + + /*! Sets the face mark of the face lying on the left of the FEdge. */ + inline void setbFaceMark(bool iFaceMark) + { + _bFaceMark = iFaceMark; + } #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:FEdgeSharp") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:FEdgeSharp") #endif }; /*! Class defining a smooth edge. This kind of edge typically runs across a face of the input mesh. It can be * a silhouette, a ridge or valley, a suggestive contour. */ -class FEdgeSmooth : public FEdge -{ -protected: - Vec3r _Normal; - unsigned _FrsMaterialIndex; +class FEdgeSmooth : public FEdge { + protected: + Vec3r _Normal; + unsigned _FrsMaterialIndex; #if 0 - bool _hasVisibilityPoint; - Vec3r _VisibilityPointA; // The edge on which the visibility will be computed represented - Vec3r _VisibilityPointB; // using its 2 extremity points A and B + bool _hasVisibilityPoint; + Vec3r _VisibilityPointA; // The edge on which the visibility will be computed represented + Vec3r _VisibilityPointB; // using its 2 extremity points A and B #endif - void *_Face; // In case of exact silhouette, Face is the WFace crossed by Fedge - // NOT HANDLED BY THE COPY CONSTRUCTEUR - bool _FaceMark; - -public: - /*! Returns the string "FEdgeSmooth" . */ - virtual string getExactTypeName() const - { - return "FEdgeSmooth"; - } - - /*! Default constructor. */ - inline FEdgeSmooth() : FEdge() - { - _Face = NULL; - _FaceMark = false; - _FrsMaterialIndex = 0; - _isSmooth = true; - } - - /*! Builds an FEdgeSmooth going from vA to vB. */ - inline FEdgeSmooth(SVertex *vA, SVertex *vB) : FEdge(vA, vB) - { - _Face = NULL; - _FaceMark = false; - _FrsMaterialIndex = 0; - _isSmooth = true; - } - - /*! Copy constructor. */ - inline FEdgeSmooth(FEdgeSmooth& iBrother) : FEdge(iBrother) - { - _Normal = iBrother._Normal; - _Face = iBrother._Face; - _FaceMark = iBrother._FaceMark; - _FrsMaterialIndex = iBrother._FrsMaterialIndex; - _isSmooth = true; - } - - /*! Destructor. */ - virtual ~FEdgeSmooth() {} - - /*! Cloning method. */ - virtual FEdge *duplicate() - { - FEdge *clone = new FEdgeSmooth(*this); - return clone; - } - - inline void *face() const - { - return _Face; - } - - /*! Returns the face mark of the face it is running across. */ - inline bool faceMark() const - { - return _FaceMark; - } - - /*! Returns the normal to the Face it is running accross. */ - inline const Vec3r& normal() - { - return _Normal; - } - - /*! Returns the index of the material of the face it is running accross. */ - inline unsigned frs_materialIndex() const - { - return _FrsMaterialIndex; - } - - /*! Returns the material of the face it is running accross. */ - const FrsMaterial& frs_material() const; - - inline void setFace(void *iFace) - { - _Face = iFace; - } - - /*! Sets the face mark of the face it is running across. */ - inline void setFaceMark(bool iFaceMark) - { - _FaceMark = iFaceMark; - } - - /*! Sets the normal to the Face it is running accross. */ - inline void setNormal(const Vec3r& iNormal) - { - _Normal = iNormal; - } - - /*! Sets the index of the material of the face it is running accross. */ - inline void setFrsMaterialIndex(unsigned i) - { - _FrsMaterialIndex = i; - } + void *_Face; // In case of exact silhouette, Face is the WFace crossed by Fedge + // NOT HANDLED BY THE COPY CONSTRUCTEUR + bool _FaceMark; + + public: + /*! Returns the string "FEdgeSmooth" . */ + virtual string getExactTypeName() const + { + return "FEdgeSmooth"; + } + + /*! Default constructor. */ + inline FEdgeSmooth() : FEdge() + { + _Face = NULL; + _FaceMark = false; + _FrsMaterialIndex = 0; + _isSmooth = true; + } + + /*! Builds an FEdgeSmooth going from vA to vB. */ + inline FEdgeSmooth(SVertex *vA, SVertex *vB) : FEdge(vA, vB) + { + _Face = NULL; + _FaceMark = false; + _FrsMaterialIndex = 0; + _isSmooth = true; + } + + /*! Copy constructor. */ + inline FEdgeSmooth(FEdgeSmooth &iBrother) : FEdge(iBrother) + { + _Normal = iBrother._Normal; + _Face = iBrother._Face; + _FaceMark = iBrother._FaceMark; + _FrsMaterialIndex = iBrother._FrsMaterialIndex; + _isSmooth = true; + } + + /*! Destructor. */ + virtual ~FEdgeSmooth() + { + } + + /*! Cloning method. */ + virtual FEdge *duplicate() + { + FEdge *clone = new FEdgeSmooth(*this); + return clone; + } + + inline void *face() const + { + return _Face; + } + + /*! Returns the face mark of the face it is running across. */ + inline bool faceMark() const + { + return _FaceMark; + } + + /*! Returns the normal to the Face it is running accross. */ + inline const Vec3r &normal() + { + return _Normal; + } + + /*! Returns the index of the material of the face it is running accross. */ + inline unsigned frs_materialIndex() const + { + return _FrsMaterialIndex; + } + + /*! Returns the material of the face it is running accross. */ + const FrsMaterial &frs_material() const; + + inline void setFace(void *iFace) + { + _Face = iFace; + } + + /*! Sets the face mark of the face it is running across. */ + inline void setFaceMark(bool iFaceMark) + { + _FaceMark = iFaceMark; + } + + /*! Sets the normal to the Face it is running accross. */ + inline void setNormal(const Vec3r &iNormal) + { + _Normal = iNormal; + } + + /*! Sets the index of the material of the face it is running accross. */ + inline void setFrsMaterialIndex(unsigned i) + { + _FrsMaterialIndex = i; + } #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:FEdgeSmooth") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:FEdgeSmooth") #endif }; - /**********************************/ /* */ /* */ @@ -1400,540 +1400,544 @@ public: /* */ /**********************************/ - /*! Class to define a feature shape. It is the gathering of feature elements from an identified input shape */ -class SShape -{ -private: - vector<FEdge*> _chains; // list of fedges that are chains starting points. - vector<SVertex*> _verticesList; // list of all vertices - vector<FEdge*> _edgesList; // list of all edges - Id _Id; - string _Name; - string _LibraryPath; - BBox<Vec3r> _BBox; - vector<FrsMaterial> _FrsMaterials; - - float _importance; - - ViewShape *_ViewShape; - -public: - /*! A field that can be used by the user to store any data. - * This field must be reseted afterwards using ResetUserData(). - */ - void *userdata; // added by E.T. - - /*! Default constructor */ - inline SShape() - { - userdata = NULL; - _importance = 0.0f; - _ViewShape = NULL; - } - - /*! Copy constructor */ - inline SShape(SShape& iBrother) - { - userdata = NULL; - _Id = iBrother._Id; - _Name = iBrother._Name; - _LibraryPath = iBrother._LibraryPath; - _BBox = iBrother.bbox(); - _FrsMaterials = iBrother._FrsMaterials; - _importance = iBrother._importance; - _ViewShape = iBrother._ViewShape; - - //--------- - // vertices - //--------- - vector<SVertex*>::iterator sv, svend; - vector<SVertex*>& verticesList = iBrother.getVertexList(); - for (sv = verticesList.begin(), svend = verticesList.end(); sv != svend; sv++) { - SVertex *newv = new SVertex(*(*sv)); - newv->setShape(this); - _verticesList.push_back(newv); - } - - //------ - // edges - //------ - vector<FEdge*>::iterator e, eend; - vector<FEdge*>& edgesList = iBrother.getEdgeList(); - for (e = edgesList.begin(), eend = edgesList.end(); e != eend; e++) { - FEdge *newe = (*e)->duplicate(); - _edgesList.push_back(newe); - } - - //------------------------- - // starting chain edges - //------------------------- - vector<FEdge*>::iterator fe, fend; - vector<FEdge*>& fedges = iBrother.getChains(); - for (fe = fedges.begin(), fend = fedges.end(); fe != fend; fe++) { - _chains.push_back((FEdge *)((*fe)->userdata)); - } - - //------------------------- - // remap edges in vertices: - //------------------------- - for (sv = _verticesList.begin(), svend = _verticesList.end(); sv != svend; sv++) { - const vector<FEdge*>& fedgeList = (*sv)->fedges(); - vector<FEdge*> newfedgelist; - for (vector<FEdge*>::const_iterator fed = fedgeList.begin(), fedend = fedgeList.end(); - fed != fedend; - fed++) - { - FEdge *current = *fed; - newfedgelist.push_back((FEdge *)current->userdata); - } - (*sv)->setFEdges(newfedgelist); - } - - //------------------------------------- - // remap vertices and nextedge in edges: - //------------------------------------- - for (e = _edgesList.begin(), eend = _edgesList.end(); e != eend; e++) { - (*e)->setVertexA((SVertex *)((*e)->vertexA()->userdata)); - (*e)->setVertexB((SVertex *)((*e)->vertexB()->userdata)); - (*e)->setNextEdge((FEdge *)((*e)->nextEdge()->userdata)); - (*e)->setPreviousEdge((FEdge *)((*e)->previousEdge()->userdata)); - } - - // reset all brothers userdata to NULL: - //------------------------------------- - //--------- - // vertices - //--------- - for (sv = _verticesList.begin(), svend = _verticesList.end(); sv != svend; sv++) { - (*sv)->userdata = NULL; - } - - //------ - // edges - //------ - for (e = _edgesList.begin(), eend = _edgesList.end(); e != eend; e++) { - (*e)->userdata = NULL; - } - } - - /*! Cloning method. */ - virtual SShape *duplicate() - { - SShape *clone = new SShape(*this); - return clone; - } - - /*! Destructor. */ - virtual inline ~SShape() - { - vector<SVertex*>::iterator sv, svend; - vector<FEdge*>::iterator e, eend; - if (0 != _verticesList.size()) { - for (sv = _verticesList.begin(), svend = _verticesList.end(); sv != svend; sv++) { - delete (*sv); - } - _verticesList.clear(); - } - - if (0 != _edgesList.size()) { - for (e = _edgesList.begin(), eend = _edgesList.end(); e != eend; e++) { - delete (*e); - } - _edgesList.clear(); - } - - //! Clear the chains list - //----------------------- - if (0 != _chains.size()) { - _chains.clear(); - } - } - - /*! Adds a FEdge to the list of FEdges. */ - inline void AddEdge(FEdge *iEdge) - { - _edgesList.push_back(iEdge); - } - - /*! Adds a SVertex to the list of SVertex of this Shape. - * The SShape attribute of the SVertex is also set to 'this'. - */ - inline void AddNewVertex(SVertex *iv) - { - iv->setShape(this); - _verticesList.push_back(iv); - } - - inline void AddChain(FEdge *iEdge) - { - _chains.push_back(iEdge); - } - - inline SVertex *CreateSVertex(const Vec3r& P3D, const Vec3r& P2D, const Id& id) - { - SVertex *Ia = new SVertex(P3D, id); - Ia->setPoint2D(P2D); - AddNewVertex(Ia); - return Ia; - } - - /*! Splits an edge into several edges. - * The edge's vertices are passed rather than the edge itself. This way, all feature edges (SILHOUETTE, - * CREASE, BORDER) are splitted in the same time. - * The processed edges are flagged as done (using the userdata flag).One single new vertex is created whereas - * several splitted edges might created for the different kinds of edges. These new elements are added to the lists - * maintained by the shape. - * New chains are also created. - * ioA - * The first vertex for the edge that gets splitted - * ioB - * The second vertex for the edge that gets splitted - * iParameters - * A vector containing 2D real vectors indicating the parameters giving the intersections coordinates in - * 3D and in 2D. These intersections points must be sorted from B to A. - * Each parameter defines the intersection point I as I=A+T*AB. T<0 and T>1 are then incorrect insofar as - * they give intersections points that lie outside the segment. - * ioNewEdges - * The edges that are newly created (the initial edges are not included) are added to this list. - */ - inline void SplitEdge(FEdge *fe, const vector<Vec2r>& iParameters, vector<FEdge*>& ioNewEdges) - { - SVertex *ioA = fe->vertexA(); - SVertex *ioB = fe->vertexB(); - Vec3r A = ioA->point3D(); - Vec3r B = ioB->point3D(); - Vec3r a = ioA->point2D(); - Vec3r b = ioB->point2D(); - - Vec3r newpoint3d, newpoint2d; - vector<SVertex*> intersections; - real t, T; - for (vector<Vec2r>::const_iterator p = iParameters.begin(), pend = iParameters.end(); p != pend; p++) { - T = (*p)[0]; - t = (*p)[1]; - - if ((t < 0) || (t > 1)) - cerr << "Warning: Intersection out of range for edge " << ioA->getId() << " - " << ioB->getId() << endl; - - // compute the 3D and 2D coordinates for the intersections points: - newpoint3d = Vec3r(A + T * (B - A)); - newpoint2d = Vec3r(a + t * (b - a)); - - // create new SVertex: - // (we keep B's id) - SVertex *newVertex = new SVertex(newpoint3d, ioB->getId()); - newVertex->setPoint2D(newpoint2d); - - // Add this vertex to the intersections list: - intersections.push_back(newVertex); - - // Add this vertex to this sshape: - AddNewVertex(newVertex); - } - - for (vector<SVertex*>::iterator sv = intersections.begin(), svend = intersections.end(); sv != svend; sv++) { - //SVertex *svA = fe->vertexA(); - SVertex *svB = fe->vertexB(); - - // We split edge AB into AA' and A'B. A' and A'B are created. - // AB becomes (address speaking) AA'. B is updated. - //-------------------------------------------------- - // The edge AB becomes edge AA'. - (fe)->setVertexB((*sv)); - // a new edge, A'B is created. - FEdge *newEdge; - if (fe->isSmooth()) { - newEdge = new FEdgeSmooth((*sv), svB); - FEdgeSmooth *se = dynamic_cast<FEdgeSmooth*>(newEdge); - FEdgeSmooth *fes = dynamic_cast<FEdgeSmooth*>(fe); - se->setFrsMaterialIndex(fes->frs_materialIndex()); - } - else { - newEdge = new FEdgeSharp((*sv), svB); - FEdgeSharp *se = dynamic_cast<FEdgeSharp*>(newEdge); - FEdgeSharp *fes = dynamic_cast<FEdgeSharp*>(fe); - se->setaFrsMaterialIndex(fes->aFrsMaterialIndex()); - se->setbFrsMaterialIndex(fes->bFrsMaterialIndex()); - } - - newEdge->setNature((fe)->getNature()); - - // to build a new chain: - AddChain(newEdge); - // add the new edge to the sshape edges list. - AddEdge(newEdge); - // add new edge to the list of new edges passed as argument: - ioNewEdges.push_back(newEdge); - - // update edge A'B for the next pointing edge - newEdge->setNextEdge((fe)->nextEdge()); - fe->nextEdge()->setPreviousEdge(newEdge); - Id id(fe->getId().getFirst(), fe->getId().getSecond() + 1); - newEdge->setId(fe->getId()); - fe->setId(id); - - // update edge AA' for the next pointing edge - //ioEdge->setNextEdge(newEdge); - (fe)->setNextEdge(NULL); - - // update vertex pointing edges list: - // -- vertex B -- - svB->Replace((fe), newEdge); - // -- vertex A' -- - (*sv)->AddFEdge((fe)); - (*sv)->AddFEdge(newEdge); - } - } - - /* splits an edge into 2 edges. The new vertex and edge are added to the sshape list of vertices and edges - * a new chain is also created. - * returns the new edge. - * ioEdge - * The edge that gets splitted - * newpoint - * x,y,z coordinates of the new point. - */ - inline FEdge *SplitEdgeIn2(FEdge *ioEdge, SVertex *ioNewVertex) - { - //soc unused - SVertex *A = ioEdge->vertexA(); - SVertex *B = ioEdge->vertexB(); - - // We split edge AB into AA' and A'B. A' and A'B are created. - // AB becomes (address speaking) AA'. B is updated. - //-------------------------------------------------- - // a new edge, A'B is created. - FEdge *newEdge; - if (ioEdge->isSmooth()) { - newEdge = new FEdgeSmooth(ioNewVertex, B); - FEdgeSmooth *se = dynamic_cast<FEdgeSmooth*>(newEdge); - FEdgeSmooth *fes = dynamic_cast<FEdgeSmooth*>(ioEdge); - se->setNormal(fes->normal()); - se->setFrsMaterialIndex(fes->frs_materialIndex()); - se->setFaceMark(fes->faceMark()); - } - else { - newEdge = new FEdgeSharp(ioNewVertex, B); - FEdgeSharp *se = dynamic_cast<FEdgeSharp*>(newEdge); - FEdgeSharp *fes = dynamic_cast<FEdgeSharp*>(ioEdge); - se->setNormalA(fes->normalA()); - se->setNormalB(fes->normalB()); - se->setaFrsMaterialIndex(fes->aFrsMaterialIndex()); - se->setbFrsMaterialIndex(fes->bFrsMaterialIndex()); - se->setaFaceMark(fes->aFaceMark()); - se->setbFaceMark(fes->bFaceMark()); - } - newEdge->setNature(ioEdge->getNature()); - - if (ioEdge->nextEdge() != 0) - ioEdge->nextEdge()->setPreviousEdge(newEdge); - - // update edge A'B for the next pointing edge - newEdge->setNextEdge(ioEdge->nextEdge()); - // update edge A'B for the previous pointing edge - newEdge->setPreviousEdge(0); // because it is now a TVertex - Id id(ioEdge->getId().getFirst(), ioEdge->getId().getSecond() + 1); - newEdge->setId(ioEdge->getId()); - ioEdge->setId(id); - - // update edge AA' for the next pointing edge - ioEdge->setNextEdge(0); // because it is now a TVertex - - // update vertex pointing edges list: - // -- vertex B -- - B->Replace(ioEdge, newEdge); - // -- vertex A' -- - ioNewVertex->AddFEdge(ioEdge); - ioNewVertex->AddFEdge(newEdge); - - // to build a new chain: - AddChain(newEdge); - AddEdge(newEdge); // FIXME ?? - - // The edge AB becomes edge AA'. - ioEdge->setVertexB(ioNewVertex); - - if (ioEdge->isSmooth()) { - ((FEdgeSmooth *)newEdge)->setFace(((FEdgeSmooth *)ioEdge)->face()); - } - - return newEdge; - } - - /*! Sets the Bounding Box of the Shape */ - inline void setBBox(const BBox<Vec3r>& iBBox) - { - _BBox = iBBox; - } - - /*! Compute the bbox of the sshape */ - inline void ComputeBBox() - { - if (0 == _verticesList.size()) - return; - - Vec3r firstVertex = _verticesList[0]->point3D(); - real XMax = firstVertex[0]; - real YMax = firstVertex[1]; - real ZMax = firstVertex[2]; - - real XMin = firstVertex[0]; - real YMin = firstVertex[1]; - real ZMin = firstVertex[2]; - - vector<SVertex*>::iterator v, vend; - // parse all the coordinates to find the Xmax, YMax, ZMax - for (v = _verticesList.begin(), vend = _verticesList.end(); v != vend; v++) { - Vec3r vertex = (*v)->point3D(); - // X - real x = vertex[0]; - if (x > XMax) - XMax = x; - else if (x < XMin) - XMin = x; - - // Y - real y = vertex[1]; - if (y > YMax) - YMax = y; - else if (y < YMin) - YMin = y; - - // Z - real z = vertex[2]; - if (z > ZMax) - ZMax = z; - else if (z < ZMin) - ZMin = z; - } - - setBBox(BBox<Vec3r>(Vec3r(XMin, YMin, ZMin), Vec3r(XMax, YMax, ZMax))); - } - - inline void RemoveEdgeFromChain(FEdge *iEdge) - { - for (vector<FEdge*>::iterator fe = _chains.begin(), feend = _chains.end(); fe != feend; fe++) { - if (iEdge == (*fe)) { - _chains.erase(fe); - break; - } - } - } - - inline void RemoveEdge(FEdge *iEdge) - { - for (vector<FEdge*>::iterator fe = _edgesList.begin(), feend = _edgesList.end(); fe != feend; fe++) { - if (iEdge == (*fe)) { - _edgesList.erase(fe); - break; - } - } - } - - /* accessors */ - /*! Returns the list of SVertex of the Shape. */ - inline vector<SVertex*>& getVertexList() - { - return _verticesList; - } - - /*! Returns the list of FEdges of the Shape. */ - inline vector<FEdge*>& getEdgeList() - { - return _edgesList; - } - - inline vector<FEdge*>& getChains() - { - return _chains; - } - - /*! Returns the bounding box of the shape. */ - inline const BBox<Vec3r>& bbox() - { - return _BBox; - } - - /*! Returns the ith material of the shape. */ - inline const FrsMaterial& frs_material(unsigned i) const - { - return _FrsMaterials[i]; - } - - /*! Returns the list of materials of the Shape. */ - inline const vector<FrsMaterial>& frs_materials() const - { - return _FrsMaterials; - } - - inline ViewShape *viewShape() - { - return _ViewShape; - } - - inline float importance() const - { - return _importance; - } - - /*! Returns the Id of the Shape. */ - inline Id getId() const - { - return _Id; - } - - /*! Returns the name of the Shape. */ - inline const string& getName() const - { - return _Name; - } - - /*! Returns the library path of the Shape. */ - inline const string& getLibraryPath() const - { - return _LibraryPath; - } - - /* Modififers */ - /*! Sets the Id of the shape.*/ - inline void setId(Id id) - { - _Id = id; - } - - /*! Sets the name of the shape.*/ - inline void setName(const string& name) - { - _Name = name; - } - - /*! Sets the library path of the shape.*/ - inline void setLibraryPath(const string& path) - { - _LibraryPath = path; - } - - /*! Sets the list of materials for the shape */ - inline void setFrsMaterials(const vector<FrsMaterial>& iMaterials) - { - _FrsMaterials = iMaterials; - } - - inline void setViewShape(ViewShape *iShape) - { - _ViewShape = iShape; - } - - inline void setImportance(float importance) - { - _importance = importance; - } +class SShape { + private: + vector<FEdge *> _chains; // list of fedges that are chains starting points. + vector<SVertex *> _verticesList; // list of all vertices + vector<FEdge *> _edgesList; // list of all edges + Id _Id; + string _Name; + string _LibraryPath; + BBox<Vec3r> _BBox; + vector<FrsMaterial> _FrsMaterials; + + float _importance; + + ViewShape *_ViewShape; + + public: + /*! A field that can be used by the user to store any data. + * This field must be reseted afterwards using ResetUserData(). + */ + void *userdata; // added by E.T. + + /*! Default constructor */ + inline SShape() + { + userdata = NULL; + _importance = 0.0f; + _ViewShape = NULL; + } + + /*! Copy constructor */ + inline SShape(SShape &iBrother) + { + userdata = NULL; + _Id = iBrother._Id; + _Name = iBrother._Name; + _LibraryPath = iBrother._LibraryPath; + _BBox = iBrother.bbox(); + _FrsMaterials = iBrother._FrsMaterials; + _importance = iBrother._importance; + _ViewShape = iBrother._ViewShape; + + //--------- + // vertices + //--------- + vector<SVertex *>::iterator sv, svend; + vector<SVertex *> &verticesList = iBrother.getVertexList(); + for (sv = verticesList.begin(), svend = verticesList.end(); sv != svend; sv++) { + SVertex *newv = new SVertex(*(*sv)); + newv->setShape(this); + _verticesList.push_back(newv); + } + + //------ + // edges + //------ + vector<FEdge *>::iterator e, eend; + vector<FEdge *> &edgesList = iBrother.getEdgeList(); + for (e = edgesList.begin(), eend = edgesList.end(); e != eend; e++) { + FEdge *newe = (*e)->duplicate(); + _edgesList.push_back(newe); + } + + //------------------------- + // starting chain edges + //------------------------- + vector<FEdge *>::iterator fe, fend; + vector<FEdge *> &fedges = iBrother.getChains(); + for (fe = fedges.begin(), fend = fedges.end(); fe != fend; fe++) { + _chains.push_back((FEdge *)((*fe)->userdata)); + } + + //------------------------- + // remap edges in vertices: + //------------------------- + for (sv = _verticesList.begin(), svend = _verticesList.end(); sv != svend; sv++) { + const vector<FEdge *> &fedgeList = (*sv)->fedges(); + vector<FEdge *> newfedgelist; + for (vector<FEdge *>::const_iterator fed = fedgeList.begin(), fedend = fedgeList.end(); + fed != fedend; + fed++) { + FEdge *current = *fed; + newfedgelist.push_back((FEdge *)current->userdata); + } + (*sv)->setFEdges(newfedgelist); + } + + //------------------------------------- + // remap vertices and nextedge in edges: + //------------------------------------- + for (e = _edgesList.begin(), eend = _edgesList.end(); e != eend; e++) { + (*e)->setVertexA((SVertex *)((*e)->vertexA()->userdata)); + (*e)->setVertexB((SVertex *)((*e)->vertexB()->userdata)); + (*e)->setNextEdge((FEdge *)((*e)->nextEdge()->userdata)); + (*e)->setPreviousEdge((FEdge *)((*e)->previousEdge()->userdata)); + } + + // reset all brothers userdata to NULL: + //------------------------------------- + //--------- + // vertices + //--------- + for (sv = _verticesList.begin(), svend = _verticesList.end(); sv != svend; sv++) { + (*sv)->userdata = NULL; + } + + //------ + // edges + //------ + for (e = _edgesList.begin(), eend = _edgesList.end(); e != eend; e++) { + (*e)->userdata = NULL; + } + } + + /*! Cloning method. */ + virtual SShape *duplicate() + { + SShape *clone = new SShape(*this); + return clone; + } + + /*! Destructor. */ + virtual inline ~SShape() + { + vector<SVertex *>::iterator sv, svend; + vector<FEdge *>::iterator e, eend; + if (0 != _verticesList.size()) { + for (sv = _verticesList.begin(), svend = _verticesList.end(); sv != svend; sv++) { + delete (*sv); + } + _verticesList.clear(); + } + + if (0 != _edgesList.size()) { + for (e = _edgesList.begin(), eend = _edgesList.end(); e != eend; e++) { + delete (*e); + } + _edgesList.clear(); + } + + //! Clear the chains list + //----------------------- + if (0 != _chains.size()) { + _chains.clear(); + } + } + + /*! Adds a FEdge to the list of FEdges. */ + inline void AddEdge(FEdge *iEdge) + { + _edgesList.push_back(iEdge); + } + + /*! Adds a SVertex to the list of SVertex of this Shape. + * The SShape attribute of the SVertex is also set to 'this'. + */ + inline void AddNewVertex(SVertex *iv) + { + iv->setShape(this); + _verticesList.push_back(iv); + } + + inline void AddChain(FEdge *iEdge) + { + _chains.push_back(iEdge); + } + + inline SVertex *CreateSVertex(const Vec3r &P3D, const Vec3r &P2D, const Id &id) + { + SVertex *Ia = new SVertex(P3D, id); + Ia->setPoint2D(P2D); + AddNewVertex(Ia); + return Ia; + } + + /*! Splits an edge into several edges. + * The edge's vertices are passed rather than the edge itself. This way, all feature edges (SILHOUETTE, + * CREASE, BORDER) are splitted in the same time. + * The processed edges are flagged as done (using the userdata flag).One single new vertex is created whereas + * several splitted edges might created for the different kinds of edges. These new elements are added to the lists + * maintained by the shape. + * New chains are also created. + * ioA + * The first vertex for the edge that gets splitted + * ioB + * The second vertex for the edge that gets splitted + * iParameters + * A vector containing 2D real vectors indicating the parameters giving the intersections coordinates in + * 3D and in 2D. These intersections points must be sorted from B to A. + * Each parameter defines the intersection point I as I=A+T*AB. T<0 and T>1 are then incorrect insofar as + * they give intersections points that lie outside the segment. + * ioNewEdges + * The edges that are newly created (the initial edges are not included) are added to this list. + */ + inline void SplitEdge(FEdge *fe, const vector<Vec2r> &iParameters, vector<FEdge *> &ioNewEdges) + { + SVertex *ioA = fe->vertexA(); + SVertex *ioB = fe->vertexB(); + Vec3r A = ioA->point3D(); + Vec3r B = ioB->point3D(); + Vec3r a = ioA->point2D(); + Vec3r b = ioB->point2D(); + + Vec3r newpoint3d, newpoint2d; + vector<SVertex *> intersections; + real t, T; + for (vector<Vec2r>::const_iterator p = iParameters.begin(), pend = iParameters.end(); + p != pend; + p++) { + T = (*p)[0]; + t = (*p)[1]; + + if ((t < 0) || (t > 1)) + cerr << "Warning: Intersection out of range for edge " << ioA->getId() << " - " + << ioB->getId() << endl; + + // compute the 3D and 2D coordinates for the intersections points: + newpoint3d = Vec3r(A + T * (B - A)); + newpoint2d = Vec3r(a + t * (b - a)); + + // create new SVertex: + // (we keep B's id) + SVertex *newVertex = new SVertex(newpoint3d, ioB->getId()); + newVertex->setPoint2D(newpoint2d); + + // Add this vertex to the intersections list: + intersections.push_back(newVertex); + + // Add this vertex to this sshape: + AddNewVertex(newVertex); + } + + for (vector<SVertex *>::iterator sv = intersections.begin(), svend = intersections.end(); + sv != svend; + sv++) { + //SVertex *svA = fe->vertexA(); + SVertex *svB = fe->vertexB(); + + // We split edge AB into AA' and A'B. A' and A'B are created. + // AB becomes (address speaking) AA'. B is updated. + //-------------------------------------------------- + // The edge AB becomes edge AA'. + (fe)->setVertexB((*sv)); + // a new edge, A'B is created. + FEdge *newEdge; + if (fe->isSmooth()) { + newEdge = new FEdgeSmooth((*sv), svB); + FEdgeSmooth *se = dynamic_cast<FEdgeSmooth *>(newEdge); + FEdgeSmooth *fes = dynamic_cast<FEdgeSmooth *>(fe); + se->setFrsMaterialIndex(fes->frs_materialIndex()); + } + else { + newEdge = new FEdgeSharp((*sv), svB); + FEdgeSharp *se = dynamic_cast<FEdgeSharp *>(newEdge); + FEdgeSharp *fes = dynamic_cast<FEdgeSharp *>(fe); + se->setaFrsMaterialIndex(fes->aFrsMaterialIndex()); + se->setbFrsMaterialIndex(fes->bFrsMaterialIndex()); + } + + newEdge->setNature((fe)->getNature()); + + // to build a new chain: + AddChain(newEdge); + // add the new edge to the sshape edges list. + AddEdge(newEdge); + // add new edge to the list of new edges passed as argument: + ioNewEdges.push_back(newEdge); + + // update edge A'B for the next pointing edge + newEdge->setNextEdge((fe)->nextEdge()); + fe->nextEdge()->setPreviousEdge(newEdge); + Id id(fe->getId().getFirst(), fe->getId().getSecond() + 1); + newEdge->setId(fe->getId()); + fe->setId(id); + + // update edge AA' for the next pointing edge + //ioEdge->setNextEdge(newEdge); + (fe)->setNextEdge(NULL); + + // update vertex pointing edges list: + // -- vertex B -- + svB->Replace((fe), newEdge); + // -- vertex A' -- + (*sv)->AddFEdge((fe)); + (*sv)->AddFEdge(newEdge); + } + } + + /* splits an edge into 2 edges. The new vertex and edge are added to the sshape list of vertices and edges + * a new chain is also created. + * returns the new edge. + * ioEdge + * The edge that gets splitted + * newpoint + * x,y,z coordinates of the new point. + */ + inline FEdge *SplitEdgeIn2(FEdge *ioEdge, SVertex *ioNewVertex) + { + //soc unused - SVertex *A = ioEdge->vertexA(); + SVertex *B = ioEdge->vertexB(); + + // We split edge AB into AA' and A'B. A' and A'B are created. + // AB becomes (address speaking) AA'. B is updated. + //-------------------------------------------------- + // a new edge, A'B is created. + FEdge *newEdge; + if (ioEdge->isSmooth()) { + newEdge = new FEdgeSmooth(ioNewVertex, B); + FEdgeSmooth *se = dynamic_cast<FEdgeSmooth *>(newEdge); + FEdgeSmooth *fes = dynamic_cast<FEdgeSmooth *>(ioEdge); + se->setNormal(fes->normal()); + se->setFrsMaterialIndex(fes->frs_materialIndex()); + se->setFaceMark(fes->faceMark()); + } + else { + newEdge = new FEdgeSharp(ioNewVertex, B); + FEdgeSharp *se = dynamic_cast<FEdgeSharp *>(newEdge); + FEdgeSharp *fes = dynamic_cast<FEdgeSharp *>(ioEdge); + se->setNormalA(fes->normalA()); + se->setNormalB(fes->normalB()); + se->setaFrsMaterialIndex(fes->aFrsMaterialIndex()); + se->setbFrsMaterialIndex(fes->bFrsMaterialIndex()); + se->setaFaceMark(fes->aFaceMark()); + se->setbFaceMark(fes->bFaceMark()); + } + newEdge->setNature(ioEdge->getNature()); + + if (ioEdge->nextEdge() != 0) + ioEdge->nextEdge()->setPreviousEdge(newEdge); + + // update edge A'B for the next pointing edge + newEdge->setNextEdge(ioEdge->nextEdge()); + // update edge A'B for the previous pointing edge + newEdge->setPreviousEdge(0); // because it is now a TVertex + Id id(ioEdge->getId().getFirst(), ioEdge->getId().getSecond() + 1); + newEdge->setId(ioEdge->getId()); + ioEdge->setId(id); + + // update edge AA' for the next pointing edge + ioEdge->setNextEdge(0); // because it is now a TVertex + + // update vertex pointing edges list: + // -- vertex B -- + B->Replace(ioEdge, newEdge); + // -- vertex A' -- + ioNewVertex->AddFEdge(ioEdge); + ioNewVertex->AddFEdge(newEdge); + + // to build a new chain: + AddChain(newEdge); + AddEdge(newEdge); // FIXME ?? + + // The edge AB becomes edge AA'. + ioEdge->setVertexB(ioNewVertex); + + if (ioEdge->isSmooth()) { + ((FEdgeSmooth *)newEdge)->setFace(((FEdgeSmooth *)ioEdge)->face()); + } + + return newEdge; + } + + /*! Sets the Bounding Box of the Shape */ + inline void setBBox(const BBox<Vec3r> &iBBox) + { + _BBox = iBBox; + } + + /*! Compute the bbox of the sshape */ + inline void ComputeBBox() + { + if (0 == _verticesList.size()) + return; + + Vec3r firstVertex = _verticesList[0]->point3D(); + real XMax = firstVertex[0]; + real YMax = firstVertex[1]; + real ZMax = firstVertex[2]; + + real XMin = firstVertex[0]; + real YMin = firstVertex[1]; + real ZMin = firstVertex[2]; + + vector<SVertex *>::iterator v, vend; + // parse all the coordinates to find the Xmax, YMax, ZMax + for (v = _verticesList.begin(), vend = _verticesList.end(); v != vend; v++) { + Vec3r vertex = (*v)->point3D(); + // X + real x = vertex[0]; + if (x > XMax) + XMax = x; + else if (x < XMin) + XMin = x; + + // Y + real y = vertex[1]; + if (y > YMax) + YMax = y; + else if (y < YMin) + YMin = y; + + // Z + real z = vertex[2]; + if (z > ZMax) + ZMax = z; + else if (z < ZMin) + ZMin = z; + } + + setBBox(BBox<Vec3r>(Vec3r(XMin, YMin, ZMin), Vec3r(XMax, YMax, ZMax))); + } + + inline void RemoveEdgeFromChain(FEdge *iEdge) + { + for (vector<FEdge *>::iterator fe = _chains.begin(), feend = _chains.end(); fe != feend; + fe++) { + if (iEdge == (*fe)) { + _chains.erase(fe); + break; + } + } + } + + inline void RemoveEdge(FEdge *iEdge) + { + for (vector<FEdge *>::iterator fe = _edgesList.begin(), feend = _edgesList.end(); fe != feend; + fe++) { + if (iEdge == (*fe)) { + _edgesList.erase(fe); + break; + } + } + } + + /* accessors */ + /*! Returns the list of SVertex of the Shape. */ + inline vector<SVertex *> &getVertexList() + { + return _verticesList; + } + + /*! Returns the list of FEdges of the Shape. */ + inline vector<FEdge *> &getEdgeList() + { + return _edgesList; + } + + inline vector<FEdge *> &getChains() + { + return _chains; + } + + /*! Returns the bounding box of the shape. */ + inline const BBox<Vec3r> &bbox() + { + return _BBox; + } + + /*! Returns the ith material of the shape. */ + inline const FrsMaterial &frs_material(unsigned i) const + { + return _FrsMaterials[i]; + } + + /*! Returns the list of materials of the Shape. */ + inline const vector<FrsMaterial> &frs_materials() const + { + return _FrsMaterials; + } + + inline ViewShape *viewShape() + { + return _ViewShape; + } + + inline float importance() const + { + return _importance; + } + + /*! Returns the Id of the Shape. */ + inline Id getId() const + { + return _Id; + } + + /*! Returns the name of the Shape. */ + inline const string &getName() const + { + return _Name; + } + + /*! Returns the library path of the Shape. */ + inline const string &getLibraryPath() const + { + return _LibraryPath; + } + + /* Modififers */ + /*! Sets the Id of the shape.*/ + inline void setId(Id id) + { + _Id = id; + } + + /*! Sets the name of the shape.*/ + inline void setName(const string &name) + { + _Name = name; + } + + /*! Sets the library path of the shape.*/ + inline void setLibraryPath(const string &path) + { + _LibraryPath = path; + } + + /*! Sets the list of materials for the shape */ + inline void setFrsMaterials(const vector<FrsMaterial> &iMaterials) + { + _FrsMaterials = iMaterials; + } + + inline void setViewShape(ViewShape *iShape) + { + _ViewShape = iShape; + } + + inline void setImportance(float importance) + { + _importance = importance; + } #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:SShape") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:SShape") #endif }; } /* namespace Freestyle */ -#endif // __FREESTYLE_SILHOUETTE_H__ +#endif // __FREESTYLE_SILHOUETTE_H__ diff --git a/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp b/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp index 39893e61dc5..7d105a662b8 100644 --- a/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp +++ b/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp @@ -37,37 +37,37 @@ namespace Freestyle { Vec3r SilhouetteGeomEngine::_Viewpoint = Vec3r(0, 0, 0); real SilhouetteGeomEngine::_translation[3] = {0, 0, 0}; real SilhouetteGeomEngine::_modelViewMatrix[4][4] = { - {1, 0, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 0}, - {0, 0, 0, 1}, + {1, 0, 0, 0}, + {0, 1, 0, 0}, + {0, 0, 1, 0}, + {0, 0, 0, 1}, }; real SilhouetteGeomEngine::_projectionMatrix[4][4] = { - {1, 0, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 0}, - {0, 0, 0, 1}, + {1, 0, 0, 0}, + {0, 1, 0, 0}, + {0, 0, 1, 0}, + {0, 0, 0, 1}, }; real SilhouetteGeomEngine::_transform[4][4] = { - {1, 0, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 0}, - {0, 0, 0, 1}, + {1, 0, 0, 0}, + {0, 1, 0, 0}, + {0, 0, 1, 0}, + {0, 0, 0, 1}, }; int SilhouetteGeomEngine::_viewport[4] = {1, 1, 1, 1}; real SilhouetteGeomEngine::_Focal = 0.0; real SilhouetteGeomEngine::_glProjectionMatrix[4][4] = { - {1, 0, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 0}, - {0, 0, 0, 1}, + {1, 0, 0, 0}, + {0, 1, 0, 0}, + {0, 0, 1, 0}, + {0, 0, 0, 1}, }; real SilhouetteGeomEngine::_glModelViewMatrix[4][4] = { - {1, 0, 0, 0}, - {0, 1, 0, 0}, - {0, 0, 1, 0}, - {0, 0, 0, 1}, + {1, 0, 0, 0}, + {0, 1, 0, 0}, + {0, 0, 1, 0}, + {0, 0, 0, 1}, }; real SilhouetteGeomEngine::_znear = 0.0; real SilhouetteGeomEngine::_zfar = 100.0; @@ -75,214 +75,218 @@ bool SilhouetteGeomEngine::_isOrthographicProjection = false; SilhouetteGeomEngine *SilhouetteGeomEngine::_pInstance = NULL; -void SilhouetteGeomEngine::setTransform(const real iModelViewMatrix[4][4], const real iProjectionMatrix[4][4], - const int iViewport[4], real iFocal) +void SilhouetteGeomEngine::setTransform(const real iModelViewMatrix[4][4], + const real iProjectionMatrix[4][4], + const int iViewport[4], + real iFocal) { - unsigned int i, j; - _translation[0] = iModelViewMatrix[3][0]; - _translation[1] = iModelViewMatrix[3][1]; - _translation[2] = iModelViewMatrix[3][2]; + unsigned int i, j; + _translation[0] = iModelViewMatrix[3][0]; + _translation[1] = iModelViewMatrix[3][1]; + _translation[2] = iModelViewMatrix[3][2]; - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) { - _modelViewMatrix[i][j] = iModelViewMatrix[j][i]; - _glModelViewMatrix[i][j] = iModelViewMatrix[i][j]; - } - } + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + _modelViewMatrix[i][j] = iModelViewMatrix[j][i]; + _glModelViewMatrix[i][j] = iModelViewMatrix[i][j]; + } + } - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) { - _projectionMatrix[i][j] = iProjectionMatrix[j][i]; - _glProjectionMatrix[i][j] = iProjectionMatrix[i][j]; - } - } + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + _projectionMatrix[i][j] = iProjectionMatrix[j][i]; + _glProjectionMatrix[i][j] = iProjectionMatrix[i][j]; + } + } - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) { - _transform[i][j] = 0; - for (unsigned int k = 0; k < 4; k++) - _transform[i][j] += _projectionMatrix[i][k] * _modelViewMatrix[k][j]; - } - } + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + _transform[i][j] = 0; + for (unsigned int k = 0; k < 4; k++) + _transform[i][j] += _projectionMatrix[i][k] * _modelViewMatrix[k][j]; + } + } - for (i = 0; i < 4; i++) { - _viewport[i] = iViewport[i]; - } - _Focal = iFocal; + for (i = 0; i < 4; i++) { + _viewport[i] = iViewport[i]; + } + _Focal = iFocal; - _isOrthographicProjection = (iProjectionMatrix[3][3] != 0.0); + _isOrthographicProjection = (iProjectionMatrix[3][3] != 0.0); } void SilhouetteGeomEngine::setFrustum(real iZNear, real iZFar) { - _znear = iZNear; - _zfar = iZFar; + _znear = iZNear; + _zfar = iZFar; } void SilhouetteGeomEngine::retrieveViewport(int viewport[4]) { - memcpy(viewport, _viewport, 4 * sizeof(int)); + memcpy(viewport, _viewport, 4 * sizeof(int)); } -void SilhouetteGeomEngine::ProjectSilhouette(vector<SVertex*>& ioVertices) +void SilhouetteGeomEngine::ProjectSilhouette(vector<SVertex *> &ioVertices) { - Vec3r newPoint; - vector<SVertex*>::iterator sv, svend; - for (sv = ioVertices.begin(), svend = ioVertices.end(); sv != svend; sv++) { - GeomUtils::fromWorldToImage((*sv)->point3D(), newPoint, _modelViewMatrix, _projectionMatrix, _viewport); - (*sv)->setPoint2D(newPoint); - } + Vec3r newPoint; + vector<SVertex *>::iterator sv, svend; + for (sv = ioVertices.begin(), svend = ioVertices.end(); sv != svend; sv++) { + GeomUtils::fromWorldToImage( + (*sv)->point3D(), newPoint, _modelViewMatrix, _projectionMatrix, _viewport); + (*sv)->setPoint2D(newPoint); + } } void SilhouetteGeomEngine::ProjectSilhouette(SVertex *ioVertex) { - Vec3r newPoint; - GeomUtils::fromWorldToImage(ioVertex->point3D(), newPoint, _modelViewMatrix, _projectionMatrix, _viewport); - ioVertex->setPoint2D(newPoint); + Vec3r newPoint; + GeomUtils::fromWorldToImage( + ioVertex->point3D(), newPoint, _modelViewMatrix, _projectionMatrix, _viewport); + ioVertex->setPoint2D(newPoint); } real SilhouetteGeomEngine::ImageToWorldParameter(FEdge *fe, real t) { - if (_isOrthographicProjection) - return t; + if (_isOrthographicProjection) + return t; - // we need to compute for each parameter t the corresponding parameter T which gives the intersection in 3D. - real T; + // we need to compute for each parameter t the corresponding parameter T which gives the intersection in 3D. + real T; - // suffix w for world, c for camera, r for retina, i for image - Vec3r Aw = (fe)->vertexA()->point3D(); - Vec3r Bw = (fe)->vertexB()->point3D(); - Vec3r Ac, Bc; - GeomUtils::fromWorldToCamera(Aw, Ac, _modelViewMatrix); - GeomUtils::fromWorldToCamera(Bw, Bc, _modelViewMatrix); - Vec3r ABc = Bc - Ac; + // suffix w for world, c for camera, r for retina, i for image + Vec3r Aw = (fe)->vertexA()->point3D(); + Vec3r Bw = (fe)->vertexB()->point3D(); + Vec3r Ac, Bc; + GeomUtils::fromWorldToCamera(Aw, Ac, _modelViewMatrix); + GeomUtils::fromWorldToCamera(Bw, Bc, _modelViewMatrix); + Vec3r ABc = Bc - Ac; #if 0 - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Ac " << Ac << endl; - cout << "Bc " << Bc << endl; - cout << "ABc " << ABc << endl; - } + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Ac " << Ac << endl; + cout << "Bc " << Bc << endl; + cout << "ABc " << ABc << endl; + } #endif - Vec3r Ai = (fe)->vertexA()->point2D(); - Vec3r Bi = (fe)->vertexB()->point2D(); - Vec3r Ii = Ai + t * (Bi - Ai); // the intersection point in the 2D image space - Vec3r Ir, Ic; - GeomUtils::fromImageToRetina(Ii, Ir, _viewport); + Vec3r Ai = (fe)->vertexA()->point2D(); + Vec3r Bi = (fe)->vertexB()->point2D(); + Vec3r Ii = Ai + t * (Bi - Ai); // the intersection point in the 2D image space + Vec3r Ir, Ic; + GeomUtils::fromImageToRetina(Ii, Ir, _viewport); - real alpha, beta, denom; - real m11 = _projectionMatrix[0][0]; - real m13 = _projectionMatrix[0][2]; - real m22 = _projectionMatrix[1][1]; - real m23 = _projectionMatrix[1][2]; + real alpha, beta, denom; + real m11 = _projectionMatrix[0][0]; + real m13 = _projectionMatrix[0][2]; + real m22 = _projectionMatrix[1][1]; + real m23 = _projectionMatrix[1][2]; - if (fabs(ABc[0]) > 1.0e-6) { - alpha = ABc[2] / ABc[0]; - beta = Ac[2] - alpha * Ac[0]; - denom = alpha * (Ir[0] + m13) + m11; - if (fabs(denom) < 1.0e-6) - goto iter; - Ic[0] = -beta * (Ir[0] + m13) / denom; + if (fabs(ABc[0]) > 1.0e-6) { + alpha = ABc[2] / ABc[0]; + beta = Ac[2] - alpha * Ac[0]; + denom = alpha * (Ir[0] + m13) + m11; + if (fabs(denom) < 1.0e-6) + goto iter; + Ic[0] = -beta * (Ir[0] + m13) / denom; #if 0 - Ic[1] = -(Ir[1] + m23) * (alpha * Ic[0] + beta) / m22; - Ic[2] = alpha * (Ic[0] - Ac[0]) + Ac[2]; + Ic[1] = -(Ir[1] + m23) * (alpha * Ic[0] + beta) / m22; + Ic[2] = alpha * (Ic[0] - Ac[0]) + Ac[2]; #endif - T = (Ic[0] - Ac[0]) / ABc[0]; - - } - else if (fabs(ABc[1]) > 1.0e-6) { - alpha = ABc[2] / ABc[1]; - beta = Ac[2] - alpha * Ac[1]; - denom = alpha * (Ir[1] + m23) + m22; - if (fabs(denom) < 1.0e-6) - goto iter; - Ic[1] = -beta * (Ir[1] + m23) / denom; + T = (Ic[0] - Ac[0]) / ABc[0]; + } + else if (fabs(ABc[1]) > 1.0e-6) { + alpha = ABc[2] / ABc[1]; + beta = Ac[2] - alpha * Ac[1]; + denom = alpha * (Ir[1] + m23) + m22; + if (fabs(denom) < 1.0e-6) + goto iter; + Ic[1] = -beta * (Ir[1] + m23) / denom; #if 0 - Ic[0] = -(Ir[0] + m13) * (alpha * Ic[1] + beta) / m11; - Ic[2] = alpha * (Ic[1] - Ac[1]) + Ac[2]; + Ic[0] = -(Ir[0] + m13) * (alpha * Ic[1] + beta) / m11; + Ic[2] = alpha * (Ic[1] - Ac[1]) + Ac[2]; #endif - T = (Ic[1] - Ac[1]) / ABc[1]; - } - else { -iter: - bool x_coords, less_than; - if (fabs(Bi[0] - Ai[0]) > 1.0e-6) { - x_coords = true; - less_than = Ai[0] < Bi[0]; - } - else { - x_coords = false; - less_than = Ai[1] < Bi[1]; - } - Vec3r Pc, Pr, Pi; - real T_sta = 0.0; - real T_end = 1.0; - real delta_x, delta_y, dist, dist_threshold = 1.0e-6; - int i, max_iters = 100; - for (i = 0; i < max_iters; i++) { - T = T_sta + 0.5 * (T_end - T_sta); - Pc = Ac + T * ABc; - GeomUtils::fromCameraToRetina(Pc, Pr, _projectionMatrix); - GeomUtils::fromRetinaToImage(Pr, Pi, _viewport); - delta_x = Ii[0] - Pi[0]; - delta_y = Ii[1] - Pi[1]; - dist = sqrt(delta_x * delta_x + delta_y * delta_y); - if (dist < dist_threshold) - break; - if (x_coords) { - if (less_than) { - if (Pi[0] < Ii[0]) - T_sta = T; - else - T_end = T; - } - else { - if (Pi[0] > Ii[0]) - T_sta = T; - else - T_end = T; - } - } - else { - if (less_than) { - if (Pi[1] < Ii[1]) - T_sta = T; - else - T_end = T; - } - else { - if (Pi[1] > Ii[1]) - T_sta = T; - else - T_end = T; - } - } - } + T = (Ic[1] - Ac[1]) / ABc[1]; + } + else { + iter: + bool x_coords, less_than; + if (fabs(Bi[0] - Ai[0]) > 1.0e-6) { + x_coords = true; + less_than = Ai[0] < Bi[0]; + } + else { + x_coords = false; + less_than = Ai[1] < Bi[1]; + } + Vec3r Pc, Pr, Pi; + real T_sta = 0.0; + real T_end = 1.0; + real delta_x, delta_y, dist, dist_threshold = 1.0e-6; + int i, max_iters = 100; + for (i = 0; i < max_iters; i++) { + T = T_sta + 0.5 * (T_end - T_sta); + Pc = Ac + T * ABc; + GeomUtils::fromCameraToRetina(Pc, Pr, _projectionMatrix); + GeomUtils::fromRetinaToImage(Pr, Pi, _viewport); + delta_x = Ii[0] - Pi[0]; + delta_y = Ii[1] - Pi[1]; + dist = sqrt(delta_x * delta_x + delta_y * delta_y); + if (dist < dist_threshold) + break; + if (x_coords) { + if (less_than) { + if (Pi[0] < Ii[0]) + T_sta = T; + else + T_end = T; + } + else { + if (Pi[0] > Ii[0]) + T_sta = T; + else + T_end = T; + } + } + else { + if (less_than) { + if (Pi[1] < Ii[1]) + T_sta = T; + else + T_end = T; + } + else { + if (Pi[1] > Ii[1]) + T_sta = T; + else + T_end = T; + } + } + } #if 0 - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "SilhouetteGeomEngine::ImageToWorldParameter(): #iters = " << i << ", dist = " << dist << "\n"; - } + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "SilhouetteGeomEngine::ImageToWorldParameter(): #iters = " << i << ", dist = " << dist << "\n"; + } #endif - if (i == max_iters && G.debug & G_DEBUG_FREESTYLE) { - cout << "SilhouetteGeomEngine::ImageToWorldParameter(): reached to max_iters (dist = " << dist << ")\n"; - } - } + if (i == max_iters && G.debug & G_DEBUG_FREESTYLE) { + cout << "SilhouetteGeomEngine::ImageToWorldParameter(): reached to max_iters (dist = " + << dist << ")\n"; + } + } - return T; + return T; } -Vec3r SilhouetteGeomEngine::WorldToImage(const Vec3r& M) +Vec3r SilhouetteGeomEngine::WorldToImage(const Vec3r &M) { - Vec3r newPoint; - GeomUtils::fromWorldToImage(M, newPoint, _transform, _viewport); - return newPoint; + Vec3r newPoint; + GeomUtils::fromWorldToImage(M, newPoint, _transform, _viewport); + return newPoint; } -Vec3r SilhouetteGeomEngine::CameraToImage(const Vec3r& M) +Vec3r SilhouetteGeomEngine::CameraToImage(const Vec3r &M) { - Vec3r newPoint, p; - GeomUtils::fromCameraToRetina(M, p, _projectionMatrix); - GeomUtils::fromRetinaToImage(p, newPoint, _viewport); - return newPoint; + Vec3r newPoint, p; + GeomUtils::fromCameraToRetina(M, p, _projectionMatrix); + GeomUtils::fromRetinaToImage(p, newPoint, _viewport); + return newPoint; } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.h b/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.h index 6e46979026a..306eb3a55be 100644 --- a/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.h +++ b/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.h @@ -30,7 +30,7 @@ #include "../system/FreestyleConfig.h" #ifdef WITH_CXX_GUARDEDALLOC -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif namespace Freestyle { @@ -40,99 +40,100 @@ using namespace Geometry; class SVertex; class FEdge; -class SilhouetteGeomEngine -{ -private: - // The viewpoint under which the silhouette has to be computed - static Vec3r _Viewpoint; - static real _translation[3]; - // the model view matrix (_modelViewMatrix[i][j] means element of line i and column j) - static real _modelViewMatrix[4][4]; - // the projection matrix (_projectionMatrix[i][j] means element of line i and column j) - static real _projectionMatrix[4][4]; - // the global transformation from world to screen (projection included) - // (_transform[i][j] means element of line i and column j) - static real _transform[4][4]; - // the viewport - static int _viewport[4]; - static real _Focal; - - static real _znear; - static real _zfar; - - // GL style (column major) projection matrix - static real _glProjectionMatrix[4][4]; - // GL style (column major) model view matrix - static real _glModelViewMatrix[4][4]; - - static bool _isOrthographicProjection; - - static SilhouetteGeomEngine *_pInstance; - -public: - /*! retrieves an instance on the singleton */ - static SilhouetteGeomEngine *getInstance() - { - if (_pInstance == NULL) { - _pInstance = new SilhouetteGeomEngine; - } - return _pInstance; - } - - /*! Sets the current viewpoint */ - static inline void setViewpoint(const Vec3r& ivp) - { - _Viewpoint = ivp; - } - - /*! Sets the current transformation - * iModelViewMatrix - * The 4x4 model view matrix, in column major order (openGL like). - * iProjection matrix - * The 4x4 projection matrix, in column major order (openGL like). - * iViewport - * The viewport. 4 real array: origin.x, origin.y, width, length - * iFocal - * The focal length - */ - static void setTransform(const real iModelViewMatrix[4][4], const real iProjectionMatrix[4][4], - const int iViewport[4], real iFocal); - - /*! Sets the current znear and zfar */ - static void setFrustum(real iZNear, real iZFar); - - /* accessors */ - static void retrieveViewport(int viewport[4]); - - /*! Projects the silhouette in camera coordinates - * This method modifies the ioEdges passed as argument. - * ioVertices - * The vertices to project. It is modified during the operation. - */ - static void ProjectSilhouette(std::vector<SVertex*>& ioVertices); - static void ProjectSilhouette(SVertex *ioVertex); - - /*! transforms the parameter t defining a 2D intersection for edge fe in order to obtain - * the parameter giving the corresponding 3D intersection. - * Returns the 3D parameter - * fe - * The edge - * t - * The parameter for the 2D intersection. - */ - static real ImageToWorldParameter(FEdge *fe, real t); - - /*! From world to image */ - static Vec3r WorldToImage(const Vec3r& M); - - /*! From camera to image */ - static Vec3r CameraToImage(const Vec3r& M); +class SilhouetteGeomEngine { + private: + // The viewpoint under which the silhouette has to be computed + static Vec3r _Viewpoint; + static real _translation[3]; + // the model view matrix (_modelViewMatrix[i][j] means element of line i and column j) + static real _modelViewMatrix[4][4]; + // the projection matrix (_projectionMatrix[i][j] means element of line i and column j) + static real _projectionMatrix[4][4]; + // the global transformation from world to screen (projection included) + // (_transform[i][j] means element of line i and column j) + static real _transform[4][4]; + // the viewport + static int _viewport[4]; + static real _Focal; + + static real _znear; + static real _zfar; + + // GL style (column major) projection matrix + static real _glProjectionMatrix[4][4]; + // GL style (column major) model view matrix + static real _glModelViewMatrix[4][4]; + + static bool _isOrthographicProjection; + + static SilhouetteGeomEngine *_pInstance; + + public: + /*! retrieves an instance on the singleton */ + static SilhouetteGeomEngine *getInstance() + { + if (_pInstance == NULL) { + _pInstance = new SilhouetteGeomEngine; + } + return _pInstance; + } + + /*! Sets the current viewpoint */ + static inline void setViewpoint(const Vec3r &ivp) + { + _Viewpoint = ivp; + } + + /*! Sets the current transformation + * iModelViewMatrix + * The 4x4 model view matrix, in column major order (openGL like). + * iProjection matrix + * The 4x4 projection matrix, in column major order (openGL like). + * iViewport + * The viewport. 4 real array: origin.x, origin.y, width, length + * iFocal + * The focal length + */ + static void setTransform(const real iModelViewMatrix[4][4], + const real iProjectionMatrix[4][4], + const int iViewport[4], + real iFocal); + + /*! Sets the current znear and zfar */ + static void setFrustum(real iZNear, real iZFar); + + /* accessors */ + static void retrieveViewport(int viewport[4]); + + /*! Projects the silhouette in camera coordinates + * This method modifies the ioEdges passed as argument. + * ioVertices + * The vertices to project. It is modified during the operation. + */ + static void ProjectSilhouette(std::vector<SVertex *> &ioVertices); + static void ProjectSilhouette(SVertex *ioVertex); + + /*! transforms the parameter t defining a 2D intersection for edge fe in order to obtain + * the parameter giving the corresponding 3D intersection. + * Returns the 3D parameter + * fe + * The edge + * t + * The parameter for the 2D intersection. + */ + static real ImageToWorldParameter(FEdge *fe, real t); + + /*! From world to image */ + static Vec3r WorldToImage(const Vec3r &M); + + /*! From camera to image */ + static Vec3r CameraToImage(const Vec3r &M); #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:SilhouetteGeomEngine") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:SilhouetteGeomEngine") #endif }; } /* namespace Freestyle */ -#endif // __FREESTYLE_SILHOUETTE_GEOM_ENGINE_H__ +#endif // __FREESTYLE_SILHOUETTE_GEOM_ENGINE_H__ diff --git a/source/blender/freestyle/intern/view_map/SphericalGrid.cpp b/source/blender/freestyle/intern/view_map/SphericalGrid.cpp index 03a50331dc9..1a7f01d288f 100644 --- a/source/blender/freestyle/intern/view_map/SphericalGrid.cpp +++ b/source/blender/freestyle/intern/view_map/SphericalGrid.cpp @@ -38,207 +38,224 @@ namespace Freestyle { // Cell ///////// -SphericalGrid::Cell::Cell() {} +SphericalGrid::Cell::Cell() +{ +} -SphericalGrid::Cell::~Cell() {} +SphericalGrid::Cell::~Cell() +{ +} void SphericalGrid::Cell::setDimensions(real x, real y, real sizeX, real sizeY) { - const real epsilon = 1.0e-06; - boundary[0] = x - epsilon; - boundary[1] = x + sizeX + epsilon; - boundary[2] = y - epsilon; - boundary[3] = y + sizeY + epsilon; + const real epsilon = 1.0e-06; + boundary[0] = x - epsilon; + boundary[1] = x + sizeX + epsilon; + boundary[2] = y - epsilon; + boundary[3] = y + sizeY + epsilon; } bool SphericalGrid::Cell::compareOccludersByShallowestPoint(const SphericalGrid::OccluderData *a, const SphericalGrid::OccluderData *b) { - return a->shallowest < b->shallowest; + return a->shallowest < b->shallowest; } void SphericalGrid::Cell::indexPolygons() { - // Sort occluders by their shallowest points. - sort(faces.begin(), faces.end(), compareOccludersByShallowestPoint); + // Sort occluders by their shallowest points. + sort(faces.begin(), faces.end(), compareOccludersByShallowestPoint); } // Iterator ////////////////// -SphericalGrid::Iterator::Iterator(SphericalGrid& grid, Vec3r& center, real /*epsilon*/) -: _target(SphericalGrid::Transform::sphericalProjection(center)), _foundOccludee(false) +SphericalGrid::Iterator::Iterator(SphericalGrid &grid, Vec3r ¢er, real /*epsilon*/) + : _target(SphericalGrid::Transform::sphericalProjection(center)), _foundOccludee(false) { - // Find target cell - _cell = grid.findCell(_target); + // Find target cell + _cell = grid.findCell(_target); #if SPHERICAL_GRID_LOGGING - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Searching for occluders of edge centered at " << _target << " in cell [" << - _cell->boundary[0] << ", " << _cell->boundary[1] << ", " << _cell->boundary[2] << - ", " << _cell->boundary[3] << "] (" << _cell->faces.size() << " occluders)" << endl; - } + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Searching for occluders of edge centered at " << _target << " in cell [" + << _cell->boundary[0] << ", " << _cell->boundary[1] << ", " << _cell->boundary[2] << ", " + << _cell->boundary[3] << "] (" << _cell->faces.size() << " occluders)" << endl; + } #endif - // Set iterator - _current = _cell->faces.begin(); + // Set iterator + _current = _cell->faces.begin(); } -SphericalGrid::Iterator::~Iterator() {} +SphericalGrid::Iterator::~Iterator() +{ +} // SphericalGrid ///////////////// -SphericalGrid::SphericalGrid(OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap, - Vec3r& viewpoint, bool enableQI) -: _viewpoint(viewpoint), _enableQI(enableQI) -{ - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Generate Cell structure" << endl; - } - // Generate Cell structure - assignCells(source, density, viewMap); - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Distribute occluders" << endl; - } - // Fill Cells - distributePolygons(source); - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Reorganize cells" << endl; - } - // Reorganize Cells - reorganizeCells(); - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Ready to use SphericalGrid" << endl; - } -} - -SphericalGrid::~SphericalGrid() {} - -void SphericalGrid::assignCells(OccluderSource& /*source*/, GridDensityProvider& density, ViewMap *viewMap) -{ - _cellSize = density.cellSize(); - _cellsX = density.cellsX(); - _cellsY = density.cellsY(); - _cellOrigin[0] = density.cellOrigin(0); - _cellOrigin[1] = density.cellOrigin(1); - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Using " << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square." << endl; - cout << "Cell origin: " << _cellOrigin[0] << ", " << _cellOrigin[1] << endl; - } - - // Now allocate the cell table and fill it with default (empty) cells - _cells.resize(_cellsX * _cellsY); - for (cellContainer::iterator i = _cells.begin(), end = _cells.end(); i != end; ++i) { - (*i) = NULL; - } - - // Identify cells that will be used, and set the dimensions for each - ViewMap::fedges_container& fedges = viewMap->FEdges(); - for (ViewMap::fedges_container::iterator f = fedges.begin(), fend = fedges.end(); f != fend; ++f) { - if ((*f)->isInImage()) { - Vec3r point = SphericalGrid::Transform::sphericalProjection((*f)->center3d()); - unsigned i, j; - getCellCoordinates(point, i, j); - if (_cells[i * _cellsY + j] == NULL) { - // This is an uninitialized cell - real x, y, width, height; - - x = _cellOrigin[0] + _cellSize * i; - width = _cellSize; - - y = _cellOrigin[1] + _cellSize * j; - height = _cellSize; - - // Initialize cell - Cell *b = _cells[i * _cellsY + j] = new Cell(); - b->setDimensions(x, y, width, height); - } - } - } -} - -void SphericalGrid::distributePolygons(OccluderSource& source) -{ - unsigned long nFaces = 0; - unsigned long nKeptFaces = 0; - - for (source.begin(); source.isValid(); source.next()) { - OccluderData *occluder = NULL; - - try { - if (insertOccluder(source, occluder)) { - _faces.push_back(occluder); - ++nKeptFaces; - } - } - catch (...) { - // If an exception was thrown, _faces.push_back() cannot have succeeded. Occluder is not owned by anyone, - // and must be deleted. If the exception was thrown before or during new OccluderData(), then - // occluder is NULL, and this delete is harmless. - delete occluder; - throw; - } - ++nFaces; - } - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Distributed " << nFaces << " occluders. Retained " << nKeptFaces << "." << endl; - } +SphericalGrid::SphericalGrid(OccluderSource &source, + GridDensityProvider &density, + ViewMap *viewMap, + Vec3r &viewpoint, + bool enableQI) + : _viewpoint(viewpoint), _enableQI(enableQI) +{ + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Generate Cell structure" << endl; + } + // Generate Cell structure + assignCells(source, density, viewMap); + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Distribute occluders" << endl; + } + // Fill Cells + distributePolygons(source); + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Reorganize cells" << endl; + } + // Reorganize Cells + reorganizeCells(); + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Ready to use SphericalGrid" << endl; + } +} + +SphericalGrid::~SphericalGrid() +{ +} + +void SphericalGrid::assignCells(OccluderSource & /*source*/, + GridDensityProvider &density, + ViewMap *viewMap) +{ + _cellSize = density.cellSize(); + _cellsX = density.cellsX(); + _cellsY = density.cellsY(); + _cellOrigin[0] = density.cellOrigin(0); + _cellOrigin[1] = density.cellOrigin(1); + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Using " << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square." + << endl; + cout << "Cell origin: " << _cellOrigin[0] << ", " << _cellOrigin[1] << endl; + } + + // Now allocate the cell table and fill it with default (empty) cells + _cells.resize(_cellsX * _cellsY); + for (cellContainer::iterator i = _cells.begin(), end = _cells.end(); i != end; ++i) { + (*i) = NULL; + } + + // Identify cells that will be used, and set the dimensions for each + ViewMap::fedges_container &fedges = viewMap->FEdges(); + for (ViewMap::fedges_container::iterator f = fedges.begin(), fend = fedges.end(); f != fend; + ++f) { + if ((*f)->isInImage()) { + Vec3r point = SphericalGrid::Transform::sphericalProjection((*f)->center3d()); + unsigned i, j; + getCellCoordinates(point, i, j); + if (_cells[i * _cellsY + j] == NULL) { + // This is an uninitialized cell + real x, y, width, height; + + x = _cellOrigin[0] + _cellSize * i; + width = _cellSize; + + y = _cellOrigin[1] + _cellSize * j; + height = _cellSize; + + // Initialize cell + Cell *b = _cells[i * _cellsY + j] = new Cell(); + b->setDimensions(x, y, width, height); + } + } + } +} + +void SphericalGrid::distributePolygons(OccluderSource &source) +{ + unsigned long nFaces = 0; + unsigned long nKeptFaces = 0; + + for (source.begin(); source.isValid(); source.next()) { + OccluderData *occluder = NULL; + + try { + if (insertOccluder(source, occluder)) { + _faces.push_back(occluder); + ++nKeptFaces; + } + } + catch (...) { + // If an exception was thrown, _faces.push_back() cannot have succeeded. Occluder is not owned by anyone, + // and must be deleted. If the exception was thrown before or during new OccluderData(), then + // occluder is NULL, and this delete is harmless. + delete occluder; + throw; + } + ++nFaces; + } + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Distributed " << nFaces << " occluders. Retained " << nKeptFaces << "." << endl; + } } void SphericalGrid::reorganizeCells() { - // Sort the occluders by shallowest point - for (vector<Cell*>::iterator i = _cells.begin(), end = _cells.end(); i != end; ++i) { - if (*i != NULL) { - (*i)->indexPolygons(); - } - } + // Sort the occluders by shallowest point + for (vector<Cell *>::iterator i = _cells.begin(), end = _cells.end(); i != end; ++i) { + if (*i != NULL) { + (*i)->indexPolygons(); + } + } } -void SphericalGrid::getCellCoordinates(const Vec3r& point, unsigned& x, unsigned& y) +void SphericalGrid::getCellCoordinates(const Vec3r &point, unsigned &x, unsigned &y) { - x = min(_cellsX - 1, (unsigned) floor (max((double) 0.0f, point[0] - _cellOrigin[0]) / _cellSize)); - y = min(_cellsY - 1, (unsigned) floor (max((double) 0.0f, point[1] - _cellOrigin[1]) / _cellSize)); + x = min(_cellsX - 1, (unsigned)floor(max((double)0.0f, point[0] - _cellOrigin[0]) / _cellSize)); + y = min(_cellsY - 1, (unsigned)floor(max((double)0.0f, point[1] - _cellOrigin[1]) / _cellSize)); } -SphericalGrid::Cell *SphericalGrid::findCell(const Vec3r& point) +SphericalGrid::Cell *SphericalGrid::findCell(const Vec3r &point) { - unsigned x, y; - getCellCoordinates(point, x, y); - return _cells[x * _cellsY + y]; + unsigned x, y; + getCellCoordinates(point, x, y); + return _cells[x * _cellsY + y]; } bool SphericalGrid::orthographicProjection() const { - return false; + return false; } -const Vec3r& SphericalGrid::viewpoint() const +const Vec3r &SphericalGrid::viewpoint() const { - return _viewpoint; + return _viewpoint; } bool SphericalGrid::enableQI() const { - return _enableQI; + return _enableQI; } -SphericalGrid::Transform::Transform () : GridHelpers::Transform() {} +SphericalGrid::Transform::Transform() : GridHelpers::Transform() +{ +} -Vec3r SphericalGrid::Transform::operator()(const Vec3r& point) const +Vec3r SphericalGrid::Transform::operator()(const Vec3r &point) const { - return sphericalProjection(point); + return sphericalProjection(point); } -Vec3r SphericalGrid::Transform::sphericalProjection(const Vec3r& M) +Vec3r SphericalGrid::Transform::sphericalProjection(const Vec3r &M) { - Vec3r newPoint; + Vec3r newPoint; - newPoint[0] = ::atan(M[0] / M[2]); - newPoint[1] = ::atan(M[1] / M[2]); - newPoint[2] = ::sqrt(M[0] * M[0] + M[1] * M[1] + M[2] * M[2]); + newPoint[0] = ::atan(M[0] / M[2]); + newPoint[1] = ::atan(M[1] / M[2]); + newPoint[2] = ::sqrt(M[0] * M[0] + M[1] * M[1] + M[2] * M[2]); - return newPoint; + return newPoint; } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/view_map/SphericalGrid.h b/source/blender/freestyle/intern/view_map/SphericalGrid.h index 19c2461ce01..ae00c270c1d 100644 --- a/source/blender/freestyle/intern/view_map/SphericalGrid.h +++ b/source/blender/freestyle/intern/view_map/SphericalGrid.h @@ -44,388 +44,389 @@ #include "BKE_global.h" #ifdef WITH_CXX_GUARDEDALLOC -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif namespace Freestyle { -class SphericalGrid -{ -public: - // Helper classes - struct OccluderData - { - explicit OccluderData (OccluderSource& source, Polygon3r& p); - Polygon3r poly; - Polygon3r cameraSpacePolygon; - real shallowest, deepest; - // N.B. We could, of course, store face in poly's userdata member, like the old ViewMapBuilder code does. - // However, code comments make it clear that userdata is deprecated, so we avoid the temptation to save - // 4 or 8 bytes. - WFace *face; +class SphericalGrid { + public: + // Helper classes + struct OccluderData { + explicit OccluderData(OccluderSource &source, Polygon3r &p); + Polygon3r poly; + Polygon3r cameraSpacePolygon; + real shallowest, deepest; + // N.B. We could, of course, store face in poly's userdata member, like the old ViewMapBuilder code does. + // However, code comments make it clear that userdata is deprecated, so we avoid the temptation to save + // 4 or 8 bytes. + WFace *face; #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:SphericalGrid:OccluderData") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:SphericalGrid:OccluderData") #endif - }; - -private: - struct Cell - { - // Can't store Cell in a vector without copy and assign - //Cell(const Cell& other); - //Cell& operator=(const Cell& other); - - explicit Cell(); - ~Cell(); - - static bool compareOccludersByShallowestPoint(const OccluderData *a, const OccluderData *b); - - void setDimensions(real x, real y, real sizeX, real sizeY); - void checkAndInsert(OccluderSource& source, Polygon3r& poly, OccluderData*& occluder); - void indexPolygons(); - - real boundary[4]; - //deque<OccluderData*> faces; - vector<OccluderData*> faces; - }; - -public: - /*! Iterator needs to allow the user to avoid full 3D comparison in two cases: - * - * (1) Where (*current)->deepest < target[2], where the occluder is unambiguously in front of the target point. - * - * (2) Where (*current)->shallowest > target[2], where the occluder is unambiguously in back of the target point. - * - * In addition, when used by OptimizedFindOccludee, Iterator should stop iterating as soon as it has an occludee - * candidate and (*current)->shallowest > candidate[2], because at that point forward no new occluder could - * possibly be a better occludee. - */ - - class Iterator - { - public: - // epsilon is not used in this class, but other grids with the same interface may need an epsilon - explicit Iterator(SphericalGrid& grid, Vec3r& center, real epsilon = 1.0e-06); - ~Iterator(); - void initBeforeTarget(); - void initAfterTarget(); - void nextOccluder(); - void nextOccludee(); - bool validBeforeTarget(); - bool validAfterTarget(); - WFace *getWFace() const; - Polygon3r *getCameraSpacePolygon(); - void reportDepth(Vec3r origin, Vec3r u, real t); - private: - bool testOccluder(bool wantOccludee); - void markCurrentOccludeeCandidate(real depth); - - Cell *_cell; - Vec3r _target; - bool _foundOccludee; - real _occludeeDepth; - //deque<OccluderData*>::iterator _current, _occludeeCandidate; - vector<OccluderData*>::iterator _current, _occludeeCandidate; + }; + + private: + struct Cell { + // Can't store Cell in a vector without copy and assign + //Cell(const Cell& other); + //Cell& operator=(const Cell& other); + + explicit Cell(); + ~Cell(); + + static bool compareOccludersByShallowestPoint(const OccluderData *a, const OccluderData *b); + + void setDimensions(real x, real y, real sizeX, real sizeY); + void checkAndInsert(OccluderSource &source, Polygon3r &poly, OccluderData *&occluder); + void indexPolygons(); + + real boundary[4]; + //deque<OccluderData*> faces; + vector<OccluderData *> faces; + }; + + public: + /*! Iterator needs to allow the user to avoid full 3D comparison in two cases: + * + * (1) Where (*current)->deepest < target[2], where the occluder is unambiguously in front of the target point. + * + * (2) Where (*current)->shallowest > target[2], where the occluder is unambiguously in back of the target point. + * + * In addition, when used by OptimizedFindOccludee, Iterator should stop iterating as soon as it has an occludee + * candidate and (*current)->shallowest > candidate[2], because at that point forward no new occluder could + * possibly be a better occludee. + */ + + class Iterator { + public: + // epsilon is not used in this class, but other grids with the same interface may need an epsilon + explicit Iterator(SphericalGrid &grid, Vec3r ¢er, real epsilon = 1.0e-06); + ~Iterator(); + void initBeforeTarget(); + void initAfterTarget(); + void nextOccluder(); + void nextOccludee(); + bool validBeforeTarget(); + bool validAfterTarget(); + WFace *getWFace() const; + Polygon3r *getCameraSpacePolygon(); + void reportDepth(Vec3r origin, Vec3r u, real t); + + private: + bool testOccluder(bool wantOccludee); + void markCurrentOccludeeCandidate(real depth); + + Cell *_cell; + Vec3r _target; + bool _foundOccludee; + real _occludeeDepth; + //deque<OccluderData*>::iterator _current, _occludeeCandidate; + vector<OccluderData *>::iterator _current, _occludeeCandidate; #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:SphericalGrid:Iterator") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:SphericalGrid:Iterator") #endif - - }; - - class Transform : public GridHelpers::Transform - { - public: - explicit Transform(); - explicit Transform(Transform& other); - Vec3r operator()(const Vec3r& point) const; - static Vec3r sphericalProjection(const Vec3r& M); - }; - -private: - // Prevent implicit copies and assignments. - SphericalGrid(const SphericalGrid& other); - SphericalGrid& operator=(const SphericalGrid& other); - -public: - explicit SphericalGrid(OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap, - Vec3r& viewpoint, bool enableQI); - virtual ~SphericalGrid(); - - // Generate Cell structure - void assignCells(OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap); - // Fill Cells - void distributePolygons(OccluderSource& source); - // Insert one polygon into each matching cell, return true if any cell consumes the polygon - bool insertOccluder(OccluderSource& source, OccluderData*& occluder); - // Sort occluders in each cell - void reorganizeCells(); - - Cell *findCell(const Vec3r& point); - - // Accessors: - bool orthographicProjection() const; - const Vec3r& viewpoint() const; - bool enableQI() const; - -private: - void getCellCoordinates(const Vec3r& point, unsigned& x, unsigned& y); - - typedef PointerSequence<vector<Cell*>, Cell*> cellContainer; - //typedef PointerSequence<deque<OccluderData*>, OccluderData*> occluderContainer; - typedef PointerSequence<vector<OccluderData*>, OccluderData*> occluderContainer; - unsigned _cellsX, _cellsY; - float _cellSize; - float _cellOrigin[2]; - cellContainer _cells; - occluderContainer _faces; - Vec3r _viewpoint; - bool _enableQI; + }; + + class Transform : public GridHelpers::Transform { + public: + explicit Transform(); + explicit Transform(Transform &other); + Vec3r operator()(const Vec3r &point) const; + static Vec3r sphericalProjection(const Vec3r &M); + }; + + private: + // Prevent implicit copies and assignments. + SphericalGrid(const SphericalGrid &other); + SphericalGrid &operator=(const SphericalGrid &other); + + public: + explicit SphericalGrid(OccluderSource &source, + GridDensityProvider &density, + ViewMap *viewMap, + Vec3r &viewpoint, + bool enableQI); + virtual ~SphericalGrid(); + + // Generate Cell structure + void assignCells(OccluderSource &source, GridDensityProvider &density, ViewMap *viewMap); + // Fill Cells + void distributePolygons(OccluderSource &source); + // Insert one polygon into each matching cell, return true if any cell consumes the polygon + bool insertOccluder(OccluderSource &source, OccluderData *&occluder); + // Sort occluders in each cell + void reorganizeCells(); + + Cell *findCell(const Vec3r &point); + + // Accessors: + bool orthographicProjection() const; + const Vec3r &viewpoint() const; + bool enableQI() const; + + private: + void getCellCoordinates(const Vec3r &point, unsigned &x, unsigned &y); + + typedef PointerSequence<vector<Cell *>, Cell *> cellContainer; + //typedef PointerSequence<deque<OccluderData*>, OccluderData*> occluderContainer; + typedef PointerSequence<vector<OccluderData *>, OccluderData *> occluderContainer; + unsigned _cellsX, _cellsY; + float _cellSize; + float _cellOrigin[2]; + cellContainer _cells; + occluderContainer _faces; + Vec3r _viewpoint; + bool _enableQI; #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:SphericalGrid") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:SphericalGrid") #endif }; inline void SphericalGrid::Iterator::initBeforeTarget() { - _current = _cell->faces.begin(); - while (_current != _cell->faces.end() && !testOccluder(false)) { - ++_current; - } + _current = _cell->faces.begin(); + while (_current != _cell->faces.end() && !testOccluder(false)) { + ++_current; + } } inline void SphericalGrid::Iterator::initAfterTarget() { - if (_foundOccludee) { + if (_foundOccludee) { #if SPHERICAL_GRID_LOGGING - if (G.debug & G_DEBUG_FREESTYLE) { - std::cout << "\tStarting occludee search from occludeeCandidate at depth " << - _occludeeDepth << std::endl; - } + if (G.debug & G_DEBUG_FREESTYLE) { + std::cout << "\tStarting occludee search from occludeeCandidate at depth " << _occludeeDepth + << std::endl; + } #endif - _current = _occludeeCandidate; - return; - } + _current = _occludeeCandidate; + return; + } #if SPHERICAL_GRID_LOGGING - if (G.debug & G_DEBUG_FREESTYLE) { - std::cout << "\tStarting occludee search from current position" << std::endl; - } + if (G.debug & G_DEBUG_FREESTYLE) { + std::cout << "\tStarting occludee search from current position" << std::endl; + } #endif - while (_current != _cell->faces.end() && !testOccluder(true)) { - ++_current; - } + while (_current != _cell->faces.end() && !testOccluder(true)) { + ++_current; + } } inline bool SphericalGrid::Iterator::testOccluder(bool wantOccludee) { - // End-of-list is not even a valid iterator position - if (_current == _cell->faces.end()) { - // Returning true seems strange, but it will break us out of whatever loop is calling testOccluder, and - // _current=_cell->face.end() will make the calling routine give up. - return true; - } + // End-of-list is not even a valid iterator position + if (_current == _cell->faces.end()) { + // Returning true seems strange, but it will break us out of whatever loop is calling testOccluder, and + // _current=_cell->face.end() will make the calling routine give up. + return true; + } #if SPHERICAL_GRID_LOGGING - if (G.debug & G_DEBUG_FREESTYLE) { - std::cout << "\tTesting occluder " << (*_current)->poly.getVertices()[0]; - for (unsigned int i = 1; i < (*_current)->poly.getVertices().size(); ++i) { - std::cout << ", " << (*_current)->poly.getVertices()[i]; - } - std::cout << " from shape " << (*_current)->face->GetVertex(0)->shape()->GetId() << std::endl; - } + if (G.debug & G_DEBUG_FREESTYLE) { + std::cout << "\tTesting occluder " << (*_current)->poly.getVertices()[0]; + for (unsigned int i = 1; i < (*_current)->poly.getVertices().size(); ++i) { + std::cout << ", " << (*_current)->poly.getVertices()[i]; + } + std::cout << " from shape " << (*_current)->face->GetVertex(0)->shape()->GetId() << std::endl; + } #endif - // If we have an occluder candidate and we are unambiguously after it, abort - if (_foundOccludee && (*_current)->shallowest > _occludeeDepth) { + // If we have an occluder candidate and we are unambiguously after it, abort + if (_foundOccludee && (*_current)->shallowest > _occludeeDepth) { #if SPHERICAL_GRID_LOGGING - if (G.debug & G_DEBUG_FREESTYLE) { - std::cout << "\t\tAborting: shallowest > occludeeCandidate->deepest" << std::endl; - } + if (G.debug & G_DEBUG_FREESTYLE) { + std::cout << "\t\tAborting: shallowest > occludeeCandidate->deepest" << std::endl; + } #endif - _current = _cell->faces.end(); + _current = _cell->faces.end(); - // See note above - return true; - } + // See note above + return true; + } - // Specific continue or stop conditions when searching for each type - if (wantOccludee) { - if ((*_current)->deepest < _target[2]) { + // Specific continue or stop conditions when searching for each type + if (wantOccludee) { + if ((*_current)->deepest < _target[2]) { #if SPHERICAL_GRID_LOGGING - if (G.debug & G_DEBUG_FREESTYLE) { - std::cout << "\t\tSkipping: shallower than target while looking for occludee" << std::endl; - } + if (G.debug & G_DEBUG_FREESTYLE) { + std::cout << "\t\tSkipping: shallower than target while looking for occludee" << std::endl; + } #endif - return false; - } - } - else { - if ((*_current)->shallowest > _target[2]) { + return false; + } + } + else { + if ((*_current)->shallowest > _target[2]) { #if SPHERICAL_GRID_LOGGING - if (G.debug & G_DEBUG_FREESTYLE) { - std::cout << "\t\tStopping: deeper than target while looking for occluder" << std::endl; - } + if (G.debug & G_DEBUG_FREESTYLE) { + std::cout << "\t\tStopping: deeper than target while looking for occluder" << std::endl; + } #endif - return true; - } - } + return true; + } + } - // Depthwise, this is a valid occluder. + // Depthwise, this is a valid occluder. - // Check to see if target is in the 2D bounding box - Vec3r bbMin, bbMax; - (*_current)->poly.getBBox(bbMin, bbMax); - if (_target[0] < bbMin[0] || _target[0] > bbMax[0] || _target[1] < bbMin[1] || _target[1] > bbMax[1]) { + // Check to see if target is in the 2D bounding box + Vec3r bbMin, bbMax; + (*_current)->poly.getBBox(bbMin, bbMax); + if (_target[0] < bbMin[0] || _target[0] > bbMax[0] || _target[1] < bbMin[1] || + _target[1] > bbMax[1]) { #if SPHERICAL_GRID_LOGGING - if (G.debug & G_DEBUG_FREESTYLE) { - std::cout << "\t\tSkipping: bounding box violation" << std::endl; - } + if (G.debug & G_DEBUG_FREESTYLE) { + std::cout << "\t\tSkipping: bounding box violation" << std::endl; + } #endif - return false; - } + return false; + } - // We've done all the corner cutting we can. Let the caller work out whether or not the geometry is correct. - return true; + // We've done all the corner cutting we can. Let the caller work out whether or not the geometry is correct. + return true; } inline void SphericalGrid::Iterator::reportDepth(Vec3r origin, Vec3r u, real t) { - // The reported depth is the length of a ray in camera space. We need to convert it into the distance from viewpoint - // If origin is the viewpoint, depth == t. A future optimization could allow the caller to tell us if origin is - // viewponit or target, at the cost of changing the OptimizedGrid API. - real depth = (origin + u * t).norm(); + // The reported depth is the length of a ray in camera space. We need to convert it into the distance from viewpoint + // If origin is the viewpoint, depth == t. A future optimization could allow the caller to tell us if origin is + // viewponit or target, at the cost of changing the OptimizedGrid API. + real depth = (origin + u * t).norm(); #if SPHERICAL_GRID_LOGGING - if (G.debug & G_DEBUG_FREESTYLE) { - std::cout << "\t\tReporting depth of occluder/ee: " << depth; - } + if (G.debug & G_DEBUG_FREESTYLE) { + std::cout << "\t\tReporting depth of occluder/ee: " << depth; + } #endif - if (depth > _target[2]) { + if (depth > _target[2]) { #if SPHERICAL_GRID_LOGGING - if (G.debug & G_DEBUG_FREESTYLE) { - std::cout << " is deeper than target" << std::endl; - } + if (G.debug & G_DEBUG_FREESTYLE) { + std::cout << " is deeper than target" << std::endl; + } #endif - // If the current occluder is the best occludee so far, save it. - if (! _foundOccludee || _occludeeDepth > depth) { - markCurrentOccludeeCandidate(depth); - } - } - else { + // If the current occluder is the best occludee so far, save it. + if (!_foundOccludee || _occludeeDepth > depth) { + markCurrentOccludeeCandidate(depth); + } + } + else { #if SPHERICAL_GRID_LOGGING - if (G.debug & G_DEBUG_FREESTYLE) { - std::cout << std::endl; - } + if (G.debug & G_DEBUG_FREESTYLE) { + std::cout << std::endl; + } #endif - } + } } inline void SphericalGrid::Iterator::nextOccluder() { - if (_current != _cell->faces.end()) { - do { - ++_current; - } while (_current != _cell->faces.end() && !testOccluder(false)); - } + if (_current != _cell->faces.end()) { + do { + ++_current; + } while (_current != _cell->faces.end() && !testOccluder(false)); + } } inline void SphericalGrid::Iterator::nextOccludee() { - if (_current != _cell->faces.end()) { - do { - ++_current; - } while (_current != _cell->faces.end() && !testOccluder(true)); - } + if (_current != _cell->faces.end()) { + do { + ++_current; + } while (_current != _cell->faces.end() && !testOccluder(true)); + } } inline bool SphericalGrid::Iterator::validBeforeTarget() { - return _current != _cell->faces.end() && (*_current)->shallowest <= _target[2]; + return _current != _cell->faces.end() && (*_current)->shallowest <= _target[2]; } inline bool SphericalGrid::Iterator::validAfterTarget() { - return _current != _cell->faces.end(); + return _current != _cell->faces.end(); } inline void SphericalGrid::Iterator::markCurrentOccludeeCandidate(real depth) { #if SPHERICAL_GRID_LOGGING - if (G.debug & G_DEBUG_FREESTYLE) { - std::cout << "\t\tFound occludeeCandidate at depth " << depth << std::endl; - } + if (G.debug & G_DEBUG_FREESTYLE) { + std::cout << "\t\tFound occludeeCandidate at depth " << depth << std::endl; + } #endif - _occludeeCandidate = _current; - _occludeeDepth = depth; - _foundOccludee = true; + _occludeeCandidate = _current; + _occludeeDepth = depth; + _foundOccludee = true; } inline WFace *SphericalGrid::Iterator::getWFace() const { - return (*_current)->face; + return (*_current)->face; } inline Polygon3r *SphericalGrid::Iterator::getCameraSpacePolygon() { - return &((*_current)->cameraSpacePolygon); + return &((*_current)->cameraSpacePolygon); } -inline SphericalGrid::OccluderData::OccluderData (OccluderSource& source, Polygon3r& p) -: poly(p), cameraSpacePolygon(source.getCameraSpacePolygon()), face(source.getWFace()) +inline SphericalGrid::OccluderData::OccluderData(OccluderSource &source, Polygon3r &p) + : poly(p), cameraSpacePolygon(source.getCameraSpacePolygon()), face(source.getWFace()) { - const Vec3r viewpoint(0, 0, 0); - // Get the point on the camera-space polygon that is closest to the viewpoint - // shallowest is the distance from the viewpoint to that point - shallowest = GridHelpers::distancePointToPolygon(viewpoint, cameraSpacePolygon); - - // Get the point on the camera-space polygon that is furthest from the viewpoint - // deepest is the distance from the viewpoint to that point - deepest = cameraSpacePolygon.getVertices()[2].norm(); - for (unsigned int i = 0; i < 2; ++i) { - real t = cameraSpacePolygon.getVertices()[i].norm(); - if (t > deepest) { - deepest = t; - } - } + const Vec3r viewpoint(0, 0, 0); + // Get the point on the camera-space polygon that is closest to the viewpoint + // shallowest is the distance from the viewpoint to that point + shallowest = GridHelpers::distancePointToPolygon(viewpoint, cameraSpacePolygon); + + // Get the point on the camera-space polygon that is furthest from the viewpoint + // deepest is the distance from the viewpoint to that point + deepest = cameraSpacePolygon.getVertices()[2].norm(); + for (unsigned int i = 0; i < 2; ++i) { + real t = cameraSpacePolygon.getVertices()[i].norm(); + if (t > deepest) { + deepest = t; + } + } } -inline void SphericalGrid::Cell::checkAndInsert(OccluderSource& source, Polygon3r& poly, OccluderData*& occluder) +inline void SphericalGrid::Cell::checkAndInsert(OccluderSource &source, + Polygon3r &poly, + OccluderData *&occluder) { - if (GridHelpers::insideProscenium (boundary, poly)) { - if (occluder == NULL) { - // Disposal of occluder will be handled in SphericalGrid::distributePolygons(), - // or automatically by SphericalGrid::_faces; - occluder = new OccluderData(source, poly); - } - faces.push_back(occluder); - } + if (GridHelpers::insideProscenium(boundary, poly)) { + if (occluder == NULL) { + // Disposal of occluder will be handled in SphericalGrid::distributePolygons(), + // or automatically by SphericalGrid::_faces; + occluder = new OccluderData(source, poly); + } + faces.push_back(occluder); + } } -inline bool SphericalGrid::insertOccluder(OccluderSource& source, OccluderData*& occluder) +inline bool SphericalGrid::insertOccluder(OccluderSource &source, OccluderData *&occluder) { - Polygon3r& poly(source.getGridSpacePolygon()); - occluder = NULL; - - Vec3r bbMin, bbMax; - poly.getBBox(bbMin, bbMax); - // Check overlapping cells - unsigned startX, startY, endX, endY; - getCellCoordinates(bbMin, startX, startY); - getCellCoordinates(bbMax, endX, endY); - - for (unsigned int i = startX; i <= endX; ++i) { - for (unsigned int j = startY; j <= endY; ++j) { - if (_cells[i * _cellsY + j] != NULL) { - _cells[i * _cellsY + j]->checkAndInsert(source, poly, occluder); - } - } - } - - return occluder != NULL; + Polygon3r &poly(source.getGridSpacePolygon()); + occluder = NULL; + + Vec3r bbMin, bbMax; + poly.getBBox(bbMin, bbMax); + // Check overlapping cells + unsigned startX, startY, endX, endY; + getCellCoordinates(bbMin, startX, startY); + getCellCoordinates(bbMax, endX, endY); + + for (unsigned int i = startX; i <= endX; ++i) { + for (unsigned int j = startY; j <= endY; ++j) { + if (_cells[i * _cellsY + j] != NULL) { + _cells[i * _cellsY + j]->checkAndInsert(source, poly, occluder); + } + } + } + + return occluder != NULL; } } /* namespace Freestyle */ -#endif // __FREESTYLE_SPHERICAL_GRID_H__ +#endif // __FREESTYLE_SPHERICAL_GRID_H__ diff --git a/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp b/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp index bb9f8069610..94541b2c312 100644 --- a/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp +++ b/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp @@ -43,249 +43,257 @@ using namespace Geometry; SteerableViewMap::SteerableViewMap(unsigned int nbOrientations) { - _nbOrientations = nbOrientations; - _bound = cos(M_PI / (float)_nbOrientations); - for (unsigned int i = 0; i < _nbOrientations; ++i) { - _directions.push_back(Vec2d(cos((float)i * M_PI / (float)_nbOrientations), - sin((float)i * M_PI / (float)_nbOrientations))); - } - Build(); + _nbOrientations = nbOrientations; + _bound = cos(M_PI / (float)_nbOrientations); + for (unsigned int i = 0; i < _nbOrientations; ++i) { + _directions.push_back(Vec2d(cos((float)i * M_PI / (float)_nbOrientations), + sin((float)i * M_PI / (float)_nbOrientations))); + } + Build(); } void SteerableViewMap::Build() { - _imagesPyramids = new ImagePyramid *[_nbOrientations + 1]; // one more map to store the complete visible VM - memset((_imagesPyramids), 0, (_nbOrientations + 1) * sizeof(ImagePyramid *)); + _imagesPyramids = + new ImagePyramid *[_nbOrientations + 1]; // one more map to store the complete visible VM + memset((_imagesPyramids), 0, (_nbOrientations + 1) * sizeof(ImagePyramid *)); } -SteerableViewMap::SteerableViewMap(const SteerableViewMap& iBrother) +SteerableViewMap::SteerableViewMap(const SteerableViewMap &iBrother) { - _nbOrientations = iBrother._nbOrientations; - unsigned int i; - _bound = iBrother._bound; - _directions = iBrother._directions; - _mapping = iBrother._mapping; - _imagesPyramids = new ImagePyramid *[_nbOrientations + 1]; // one more map to store the complete visible VM - for (i = 0; i <= _nbOrientations; ++i) - _imagesPyramids[i] = new GaussianPyramid(*(dynamic_cast<GaussianPyramid*>(iBrother._imagesPyramids[i]))); + _nbOrientations = iBrother._nbOrientations; + unsigned int i; + _bound = iBrother._bound; + _directions = iBrother._directions; + _mapping = iBrother._mapping; + _imagesPyramids = + new ImagePyramid *[_nbOrientations + 1]; // one more map to store the complete visible VM + for (i = 0; i <= _nbOrientations; ++i) + _imagesPyramids[i] = new GaussianPyramid( + *(dynamic_cast<GaussianPyramid *>(iBrother._imagesPyramids[i]))); } SteerableViewMap::~SteerableViewMap() { - Clear(); + Clear(); } void SteerableViewMap::Clear() { - unsigned int i; - if (_imagesPyramids) { - for (i = 0; i <= _nbOrientations; ++i) { - if (_imagesPyramids[i]) - delete (_imagesPyramids)[i]; - } - delete[] _imagesPyramids; - _imagesPyramids = 0; - } - if (!_mapping.empty()) { - for (map<unsigned int, double*>::iterator m = _mapping.begin(), mend = _mapping.end(); m != mend; ++m) { - delete[] (*m).second; - } - _mapping.clear(); - } + unsigned int i; + if (_imagesPyramids) { + for (i = 0; i <= _nbOrientations; ++i) { + if (_imagesPyramids[i]) + delete (_imagesPyramids)[i]; + } + delete[] _imagesPyramids; + _imagesPyramids = 0; + } + if (!_mapping.empty()) { + for (map<unsigned int, double *>::iterator m = _mapping.begin(), mend = _mapping.end(); + m != mend; + ++m) { + delete[](*m).second; + } + _mapping.clear(); + } } void SteerableViewMap::Reset() { - Clear(); - Build(); + Clear(); + Build(); } -double SteerableViewMap::ComputeWeight(const Vec2d& dir, unsigned i) +double SteerableViewMap::ComputeWeight(const Vec2d &dir, unsigned i) { - double dotp = fabs(dir * _directions[i]); - if (dotp < _bound) - return 0.0; - if (dotp > 1.0) - dotp = 1.0; + double dotp = fabs(dir * _directions[i]); + if (dotp < _bound) + return 0.0; + if (dotp > 1.0) + dotp = 1.0; - return cos((float)_nbOrientations / 2.0 * acos(dotp)); + return cos((float)_nbOrientations / 2.0 * acos(dotp)); } double *SteerableViewMap::AddFEdge(FEdge *iFEdge) { - unsigned i; - unsigned id = iFEdge->getId().getFirst(); - map<unsigned int, double *>::iterator o = _mapping.find(id); - if (o != _mapping.end()) { - return (*o).second; - } - double *res = new double[_nbOrientations]; - for (i = 0; i < _nbOrientations; ++i) { - res[i] = 0.0; - } - Vec3r o2d3 = iFEdge->orientation2d(); - Vec2r o2d2(o2d3.x(), o2d3.y()); - real norm = o2d2.norm(); - if (norm < 1.0e-6) { - return res; - } - o2d2 /= norm; - - for (i = 0; i < _nbOrientations; ++i) { - res[i] = ComputeWeight(o2d2, i); - } - _mapping[id] = res; - return res; + unsigned i; + unsigned id = iFEdge->getId().getFirst(); + map<unsigned int, double *>::iterator o = _mapping.find(id); + if (o != _mapping.end()) { + return (*o).second; + } + double *res = new double[_nbOrientations]; + for (i = 0; i < _nbOrientations; ++i) { + res[i] = 0.0; + } + Vec3r o2d3 = iFEdge->orientation2d(); + Vec2r o2d2(o2d3.x(), o2d3.y()); + real norm = o2d2.norm(); + if (norm < 1.0e-6) { + return res; + } + o2d2 /= norm; + + for (i = 0; i < _nbOrientations; ++i) { + res[i] = ComputeWeight(o2d2, i); + } + _mapping[id] = res; + return res; } -unsigned SteerableViewMap::getSVMNumber(const Vec2f& orient) +unsigned SteerableViewMap::getSVMNumber(const Vec2f &orient) { - Vec2f dir(orient); - //soc unsigned res = 0; - real norm = dir.norm(); - if (norm < 1.0e-6) { - return _nbOrientations + 1; - } - dir /= norm; - double maxw = 0.0f; - unsigned winner = _nbOrientations + 1; - for (unsigned int i = 0; i < _nbOrientations; ++i) { - double w = ComputeWeight(dir, i); - if (w > maxw) { - maxw = w; - winner = i; - } - } - return winner; + Vec2f dir(orient); + //soc unsigned res = 0; + real norm = dir.norm(); + if (norm < 1.0e-6) { + return _nbOrientations + 1; + } + dir /= norm; + double maxw = 0.0f; + unsigned winner = _nbOrientations + 1; + for (unsigned int i = 0; i < _nbOrientations; ++i) { + double w = ComputeWeight(dir, i); + if (w > maxw) { + maxw = w; + winner = i; + } + } + return winner; } unsigned SteerableViewMap::getSVMNumber(unsigned id) { - map<unsigned int, double *>::iterator o = _mapping.find(id); - if (o != _mapping.end()) { - double *wvalues = (*o).second; - double maxw = 0.0; - unsigned winner = _nbOrientations + 1; - for (unsigned i = 0; i < _nbOrientations; ++i) { - double w = wvalues[i]; - if (w > maxw) { - maxw = w; - winner = i; - } - } - return winner; - } - return _nbOrientations + 1; + map<unsigned int, double *>::iterator o = _mapping.find(id); + if (o != _mapping.end()) { + double *wvalues = (*o).second; + double maxw = 0.0; + unsigned winner = _nbOrientations + 1; + for (unsigned i = 0; i < _nbOrientations; ++i) { + double w = wvalues[i]; + if (w > maxw) { + maxw = w; + winner = i; + } + } + return winner; + } + return _nbOrientations + 1; } -void SteerableViewMap::buildImagesPyramids(GrayImage **steerableBases, bool copy, unsigned iNbLevels, float iSigma) +void SteerableViewMap::buildImagesPyramids(GrayImage **steerableBases, + bool copy, + unsigned iNbLevels, + float iSigma) { - for (unsigned int i = 0; i <= _nbOrientations; ++i) { - ImagePyramid *svm = (_imagesPyramids)[i]; - if (svm) - delete svm; - if (copy) - svm = new GaussianPyramid(*(steerableBases[i]), iNbLevels, iSigma); - else - svm = new GaussianPyramid(steerableBases[i], iNbLevels, iSigma); - _imagesPyramids[i] = svm; - } + for (unsigned int i = 0; i <= _nbOrientations; ++i) { + ImagePyramid *svm = (_imagesPyramids)[i]; + if (svm) + delete svm; + if (copy) + svm = new GaussianPyramid(*(steerableBases[i]), iNbLevels, iSigma); + else + svm = new GaussianPyramid(steerableBases[i], iNbLevels, iSigma); + _imagesPyramids[i] = svm; + } } float SteerableViewMap::readSteerableViewMapPixel(unsigned iOrientation, int iLevel, int x, int y) { - ImagePyramid *pyramid = _imagesPyramids[iOrientation]; - if (!pyramid) { - if (G.debug & G_DEBUG_FREESTYLE) { - cout << "Warning: this steerable ViewMap level doesn't exist" << endl; - } - return 0.0f; - } - if ((x < 0) || (x >= pyramid->width()) || (y < 0) || (y >= pyramid->height())) - return 0; - //float v = pyramid->pixel(x, pyramid->height() - 1 - y, iLevel) * 255.0f; - // We encode both the directionality and the lines counting on 8 bits (because of frame buffer). Thus, we allow - // until 8 lines to pass through the same pixel, so that we can discretize the Pi/_nbOrientations angle into - // 32 slices. Therefore, for example, in the vertical direction, a vertical line will have the value 32 on - // each pixel it passes through. - float v = pyramid->pixel(x, pyramid->height() - 1 - y, iLevel) / 32.0f; - return v; + ImagePyramid *pyramid = _imagesPyramids[iOrientation]; + if (!pyramid) { + if (G.debug & G_DEBUG_FREESTYLE) { + cout << "Warning: this steerable ViewMap level doesn't exist" << endl; + } + return 0.0f; + } + if ((x < 0) || (x >= pyramid->width()) || (y < 0) || (y >= pyramid->height())) + return 0; + //float v = pyramid->pixel(x, pyramid->height() - 1 - y, iLevel) * 255.0f; + // We encode both the directionality and the lines counting on 8 bits (because of frame buffer). Thus, we allow + // until 8 lines to pass through the same pixel, so that we can discretize the Pi/_nbOrientations angle into + // 32 slices. Therefore, for example, in the vertical direction, a vertical line will have the value 32 on + // each pixel it passes through. + float v = pyramid->pixel(x, pyramid->height() - 1 - y, iLevel) / 32.0f; + return v; } float SteerableViewMap::readCompleteViewMapPixel(int iLevel, int x, int y) { - return readSteerableViewMapPixel(_nbOrientations, iLevel, x, y); + return readSteerableViewMapPixel(_nbOrientations, iLevel, x, y); } unsigned int SteerableViewMap::getNumberOfPyramidLevels() const { - if (_imagesPyramids[0]) - return _imagesPyramids[0]->getNumberOfLevels(); - return 0; + if (_imagesPyramids[0]) + return _imagesPyramids[0]->getNumberOfLevels(); + return 0; } void SteerableViewMap::saveSteerableViewMap() const { - for (unsigned int i = 0; i <= _nbOrientations; ++i) { - if (_imagesPyramids[i] == 0) { - cerr << "SteerableViewMap warning: orientation " << i << - " of steerable View Map whas not been computed yet" << endl; - continue; - } - int ow = _imagesPyramids[i]->width(0); - int oh = _imagesPyramids[i]->height(0); - - //soc QString base("SteerableViewMap"); - string base("SteerableViewMap"); - stringstream filename; - - for (int j = 0; j < _imagesPyramids[i]->getNumberOfLevels(); ++j) { //soc - float coeff = 1.0f; // 1 / 255.0f; // 100 * 255; // * pow(2, j); - //soc QImage qtmp(ow, oh, QImage::Format_RGB32); - ImBuf *ibuf = IMB_allocImBuf(ow, oh, 32, IB_rect); - int rowbytes = ow * 4; - char *pix; - - for (int y = 0; y < oh; ++y) { //soc - for (int x = 0; x < ow; ++x) { //soc - int c = (int)(coeff * _imagesPyramids[i]->pixel(x, y, j)); - if (c > 255) - c = 255; - //int c = (int)(_imagesPyramids[i]->pixel(x, y, j)); - - //soc qtmp.setPixel(x, y, qRgb(c, c, c)); - pix = (char *)ibuf->rect + y * rowbytes + x * 4; - pix[0] = pix[1] = pix[2] = c; - } - } - - //soc qtmp.save(base+QString::number(i)+"-"+QString::number(j)+".png", "PNG"); - filename << base; - filename << i << "-" << j << ".png"; - ibuf->ftype = IMB_FTYPE_PNG; - IMB_saveiff(ibuf, const_cast<char *>(filename.str().c_str()), 0); - } + for (unsigned int i = 0; i <= _nbOrientations; ++i) { + if (_imagesPyramids[i] == 0) { + cerr << "SteerableViewMap warning: orientation " << i + << " of steerable View Map whas not been computed yet" << endl; + continue; + } + int ow = _imagesPyramids[i]->width(0); + int oh = _imagesPyramids[i]->height(0); + + //soc QString base("SteerableViewMap"); + string base("SteerableViewMap"); + stringstream filename; + + for (int j = 0; j < _imagesPyramids[i]->getNumberOfLevels(); ++j) { //soc + float coeff = 1.0f; // 1 / 255.0f; // 100 * 255; // * pow(2, j); + //soc QImage qtmp(ow, oh, QImage::Format_RGB32); + ImBuf *ibuf = IMB_allocImBuf(ow, oh, 32, IB_rect); + int rowbytes = ow * 4; + char *pix; + + for (int y = 0; y < oh; ++y) { //soc + for (int x = 0; x < ow; ++x) { //soc + int c = (int)(coeff * _imagesPyramids[i]->pixel(x, y, j)); + if (c > 255) + c = 255; + //int c = (int)(_imagesPyramids[i]->pixel(x, y, j)); + + //soc qtmp.setPixel(x, y, qRgb(c, c, c)); + pix = (char *)ibuf->rect + y * rowbytes + x * 4; + pix[0] = pix[1] = pix[2] = c; + } + } + + //soc qtmp.save(base+QString::number(i)+"-"+QString::number(j)+".png", "PNG"); + filename << base; + filename << i << "-" << j << ".png"; + ibuf->ftype = IMB_FTYPE_PNG; + IMB_saveiff(ibuf, const_cast<char *>(filename.str().c_str()), 0); + } #if 0 - QString base("SteerableViewMap"); - for (unsigned j = 0; j < _imagesPyramids[i]->getNumberOfLevels(); ++j) { - GrayImage *img = _imagesPyramids[i]->getLevel(j); - int ow = img->width(); - int oh = img->height(); - float coeff = 1.0f; // 100 * 255; // * pow(2, j); - QImage qtmp(ow, oh, 32); - for (unsigned int y = 0; y < oh; ++y) { - for (unsigned int x = 0; x < ow; ++x) { - int c = (int)(coeff * img->pixel(x, y)); - if (c > 255) - c = 255; - //int c = (int)(_imagesPyramids[i]->pixel(x, y, j)); - qtmp.setPixel(x, y, qRgb(c, c, c)); - } - } - qtmp.save(base + QString::number(i) + "-" + QString::number(j) + ".png", "PNG"); - } + QString base("SteerableViewMap"); + for (unsigned j = 0; j < _imagesPyramids[i]->getNumberOfLevels(); ++j) { + GrayImage *img = _imagesPyramids[i]->getLevel(j); + int ow = img->width(); + int oh = img->height(); + float coeff = 1.0f; // 100 * 255; // * pow(2, j); + QImage qtmp(ow, oh, 32); + for (unsigned int y = 0; y < oh; ++y) { + for (unsigned int x = 0; x < ow; ++x) { + int c = (int)(coeff * img->pixel(x, y)); + if (c > 255) + c = 255; + //int c = (int)(_imagesPyramids[i]->pixel(x, y, j)); + qtmp.setPixel(x, y, qRgb(c, c, c)); + } + } + qtmp.save(base + QString::number(i) + "-" + QString::number(j) + ".png", "PNG"); + } #endif - } + } } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/view_map/SteerableViewMap.h b/source/blender/freestyle/intern/view_map/SteerableViewMap.h index 608d64703f4..16f57f39737 100644 --- a/source/blender/freestyle/intern/view_map/SteerableViewMap.h +++ b/source/blender/freestyle/intern/view_map/SteerableViewMap.h @@ -29,7 +29,7 @@ #include "../system/FreestyleConfig.h" #ifdef WITH_CXX_GUARDEDALLOC -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif using namespace std; @@ -45,109 +45,110 @@ class GrayImage; /*! This class checks for every FEdge in which steerable it belongs and stores the mapping allowing to retrieve * this information from the FEdge Id. */ -class SteerableViewMap -{ -protected: - // for each vector the list of nbOrientations weights corresponding to its contributions - // to the nbOrientations directional maps - map<unsigned int, double*> _mapping; - unsigned _nbOrientations; - ImagePyramid **_imagesPyramids; // the pyramids of images storing the different SVM - - // internal - double _bound; // cos(Pi/N) - vector<Vec2d> _directions; - -public: - SteerableViewMap(unsigned int nbOrientations = 4); - SteerableViewMap(const SteerableViewMap& iBrother); - virtual ~SteerableViewMap(); - - /*! Resets everything */ - virtual void Reset(); - - /*! Adds a FEdge to steerable VM. - * Returns the nbOrientations weights corresponding to the FEdge contributions to the nbOrientations - * directional maps. - */ - double *AddFEdge(FEdge *iFEdge); - - /*! Compute the weight of direction dir for orientation iNOrientation */ - double ComputeWeight(const Vec2d& dir, unsigned iNOrientation); - - /*! Returns the number of the SVM to which a direction belongs to. - * \param dir: - * The direction - */ - unsigned getSVMNumber(const Vec2f& dir); - - /*! Returns the number of the SVM to which a FEdge belongs most. - * \param id: - * The First element of the Id struct of the FEdge we're interested in. - */ - unsigned getSVMNumber(unsigned id); - - /*! Builds _nbOrientations+1 pyramids of images from the _nbOrientations+1 base images of the steerable viewmap. - * \param steerableBases: - * The _nbOrientations+1 images constituting the basis for the steerable pyramid. - * \param copy: - * If false, the data is not duplicated, and Canvas deals with the memory management of these - * _nbOrientations+1 images. If true, data is copied, and it's up to the caller to delete the images. - * \param iNbLevels: - * The number of levels desired for each pyramid. - * If iNbLevels == 0, the complete pyramid is built. - * \param iSigma: - * The sigma that will be used for the gaussian blur - */ - void buildImagesPyramids(GrayImage **steerableBases, bool copy = false, unsigned iNbLevels = 4, - float iSigma = 1.0f); - - /*! Reads a pixel value in one of the VewMap density steerable pyramids. - * Returns a value between 0 and 1. - * \param iOrientation: - * the number telling which orientation we need to check. - * There are _nbOrientations+1 oriented ViewMaps: - * 0 -> the ViewMap containing every horizontal lines - * 1 -> the ViewMap containing every lines whose orientation is around PI/4 - * 2 -> the ViewMap containing every vertical lines - * 3 -> the ViewMap containing every lines whose orientation is around 3PI/4 - * 4 -> the complete ViewMap - * \param iLevel: - * The level of the pyramid we want to read - * \param x: - * The abscissa of the desired pixel specified in level0 coordinate system. The origin is the lower left corner. - * \param y: - * The ordinate of the desired pixel specified in level0 coordinate system. The origin is the lower left corner. - */ - float readSteerableViewMapPixel(unsigned iOrientation, int iLevel, int x, int y); - - /*! Reads a pixel in the one of the level of the pyramid containing the images of the complete ViewMap. - * Returns a value between 0 and 1. - * Equivalent to : readSteerableViewMapPixel(nbOrientations, x, y) - */ - float readCompleteViewMapPixel(int iLevel, int x, int y); - - /*! Returns the number of levels in the pyramids */ - unsigned int getNumberOfPyramidLevels() const; - - /*! Returns the number of orientations */ - unsigned int getNumberOfOrientations() const - { - return _nbOrientations; - } - - /*! for debug purposes */ - void saveSteerableViewMap() const; - -protected: - void Clear(); - void Build(); +class SteerableViewMap { + protected: + // for each vector the list of nbOrientations weights corresponding to its contributions + // to the nbOrientations directional maps + map<unsigned int, double *> _mapping; + unsigned _nbOrientations; + ImagePyramid **_imagesPyramids; // the pyramids of images storing the different SVM + + // internal + double _bound; // cos(Pi/N) + vector<Vec2d> _directions; + + public: + SteerableViewMap(unsigned int nbOrientations = 4); + SteerableViewMap(const SteerableViewMap &iBrother); + virtual ~SteerableViewMap(); + + /*! Resets everything */ + virtual void Reset(); + + /*! Adds a FEdge to steerable VM. + * Returns the nbOrientations weights corresponding to the FEdge contributions to the nbOrientations + * directional maps. + */ + double *AddFEdge(FEdge *iFEdge); + + /*! Compute the weight of direction dir for orientation iNOrientation */ + double ComputeWeight(const Vec2d &dir, unsigned iNOrientation); + + /*! Returns the number of the SVM to which a direction belongs to. + * \param dir: + * The direction + */ + unsigned getSVMNumber(const Vec2f &dir); + + /*! Returns the number of the SVM to which a FEdge belongs most. + * \param id: + * The First element of the Id struct of the FEdge we're interested in. + */ + unsigned getSVMNumber(unsigned id); + + /*! Builds _nbOrientations+1 pyramids of images from the _nbOrientations+1 base images of the steerable viewmap. + * \param steerableBases: + * The _nbOrientations+1 images constituting the basis for the steerable pyramid. + * \param copy: + * If false, the data is not duplicated, and Canvas deals with the memory management of these + * _nbOrientations+1 images. If true, data is copied, and it's up to the caller to delete the images. + * \param iNbLevels: + * The number of levels desired for each pyramid. + * If iNbLevels == 0, the complete pyramid is built. + * \param iSigma: + * The sigma that will be used for the gaussian blur + */ + void buildImagesPyramids(GrayImage **steerableBases, + bool copy = false, + unsigned iNbLevels = 4, + float iSigma = 1.0f); + + /*! Reads a pixel value in one of the VewMap density steerable pyramids. + * Returns a value between 0 and 1. + * \param iOrientation: + * the number telling which orientation we need to check. + * There are _nbOrientations+1 oriented ViewMaps: + * 0 -> the ViewMap containing every horizontal lines + * 1 -> the ViewMap containing every lines whose orientation is around PI/4 + * 2 -> the ViewMap containing every vertical lines + * 3 -> the ViewMap containing every lines whose orientation is around 3PI/4 + * 4 -> the complete ViewMap + * \param iLevel: + * The level of the pyramid we want to read + * \param x: + * The abscissa of the desired pixel specified in level0 coordinate system. The origin is the lower left corner. + * \param y: + * The ordinate of the desired pixel specified in level0 coordinate system. The origin is the lower left corner. + */ + float readSteerableViewMapPixel(unsigned iOrientation, int iLevel, int x, int y); + + /*! Reads a pixel in the one of the level of the pyramid containing the images of the complete ViewMap. + * Returns a value between 0 and 1. + * Equivalent to : readSteerableViewMapPixel(nbOrientations, x, y) + */ + float readCompleteViewMapPixel(int iLevel, int x, int y); + + /*! Returns the number of levels in the pyramids */ + unsigned int getNumberOfPyramidLevels() const; + + /*! Returns the number of orientations */ + unsigned int getNumberOfOrientations() const + { + return _nbOrientations; + } + + /*! for debug purposes */ + void saveSteerableViewMap() const; + + protected: + void Clear(); + void Build(); #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:SteerableViewMap") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:SteerableViewMap") #endif }; } /* namespace Freestyle */ -#endif // __FREESTYLE_STEERABLE_VIEW_MAP_H__ +#endif // __FREESTYLE_STEERABLE_VIEW_MAP_H__ diff --git a/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp index 0ec008ebf2b..8896918e60d 100644 --- a/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp +++ b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp @@ -33,712 +33,721 @@ namespace Freestyle { void ViewEdgeXBuilder::Init(ViewShape *oVShape) { - if (NULL == oVShape) - return; + if (NULL == oVShape) + return; - // for design conveniance, we store the current SShape. - _pCurrentSShape = oVShape->sshape(); - if (0 == _pCurrentSShape) - return; + // for design conveniance, we store the current SShape. + _pCurrentSShape = oVShape->sshape(); + if (0 == _pCurrentSShape) + return; - _pCurrentVShape = oVShape; + _pCurrentVShape = oVShape; - // Reset previous data - //-------------------- - if (!_SVertexMap.empty()) - _SVertexMap.clear(); + // Reset previous data + //-------------------- + if (!_SVertexMap.empty()) + _SVertexMap.clear(); } -void ViewEdgeXBuilder::BuildViewEdges(WXShape *iWShape, ViewShape *oVShape, vector<ViewEdge*>& ioVEdges, - vector<ViewVertex*>& ioVVertices, vector<FEdge*>& ioFEdges, - vector<SVertex*>& ioSVertices) +void ViewEdgeXBuilder::BuildViewEdges(WXShape *iWShape, + ViewShape *oVShape, + vector<ViewEdge *> &ioVEdges, + vector<ViewVertex *> &ioVVertices, + vector<FEdge *> &ioFEdges, + vector<SVertex *> &ioSVertices) { - // Reinit structures - Init(oVShape); - - /* ViewEdge *vedge; */ /* UNUSED */ - // Let us build the smooth stuff - //---------------------------------------- - // We parse all faces to find the ones that contain smooth edges - vector<WFace*>& wfaces = iWShape->GetFaceList(); - vector<WFace*>::iterator wf, wfend; - WXFace *wxf; - for (wf = wfaces.begin(), wfend = wfaces.end(); wf != wfend; wf++) { - wxf = dynamic_cast<WXFace*>(*wf); - if (false == ((wxf))->hasSmoothEdges()) // does it contain at least one smooth edge ? - continue; - // parse all smooth layers: - vector<WXFaceLayer*>& smoothLayers = wxf->getSmoothLayers(); - for (vector<WXFaceLayer*>::iterator sl = smoothLayers.begin(), slend = smoothLayers.end(); sl != slend; ++sl) { - if (!(*sl)->hasSmoothEdge()) - continue; - if (stopSmoothViewEdge((*sl))) // has it been parsed already ? - continue; - // here we know that we're dealing with a face layer that has not been processed yet and that contains - // a smooth edge. - /* vedge =*/ /* UNUSED */ BuildSmoothViewEdge(OWXFaceLayer(*sl, true)); - } - } - - // Now let's build sharp view edges: - //---------------------------------- - // Reset all userdata for WXEdge structure - //---------------------------------------- - //iWShape->ResetUserData(); - - WXEdge *wxe; - vector<WEdge*>& wedges = iWShape->getEdgeList(); - //------------------------------ - for (vector<WEdge*>::iterator we = wedges.begin(), weend = wedges.end(); we != weend; we++) { - wxe = dynamic_cast<WXEdge*>(*we); - if (Nature::NO_FEATURE == wxe->nature()) - continue; - - if (!stopSharpViewEdge(wxe)) { - bool b = true; - if (wxe->order() == -1) - b = false; - BuildSharpViewEdge(OWXEdge(wxe, b)); - } - } - - // Reset all userdata for WXEdge structure - //---------------------------------------- - iWShape->ResetUserData(); - - // Add all these new edges to the scene's feature edges list: - //----------------------------------------------------------- - vector<FEdge*>& newedges = _pCurrentSShape->getEdgeList(); - vector<SVertex*>& newVertices = _pCurrentSShape->getVertexList(); - vector<ViewVertex*>& newVVertices = _pCurrentVShape->vertices(); - vector<ViewEdge*>& newVEdges = _pCurrentVShape->edges(); - - // inserts in ioFEdges, at its end, all the edges of newedges - ioFEdges.insert(ioFEdges.end(), newedges.begin(), newedges.end()); - ioSVertices.insert(ioSVertices.end(), newVertices.begin(), newVertices.end()); - ioVVertices.insert(ioVVertices.end(), newVVertices.begin(), newVVertices.end()); - ioVEdges.insert(ioVEdges.end(), newVEdges.begin(), newVEdges.end()); + // Reinit structures + Init(oVShape); + + /* ViewEdge *vedge; */ /* UNUSED */ + // Let us build the smooth stuff + //---------------------------------------- + // We parse all faces to find the ones that contain smooth edges + vector<WFace *> &wfaces = iWShape->GetFaceList(); + vector<WFace *>::iterator wf, wfend; + WXFace *wxf; + for (wf = wfaces.begin(), wfend = wfaces.end(); wf != wfend; wf++) { + wxf = dynamic_cast<WXFace *>(*wf); + if (false == ((wxf))->hasSmoothEdges()) // does it contain at least one smooth edge ? + continue; + // parse all smooth layers: + vector<WXFaceLayer *> &smoothLayers = wxf->getSmoothLayers(); + for (vector<WXFaceLayer *>::iterator sl = smoothLayers.begin(), slend = smoothLayers.end(); + sl != slend; + ++sl) { + if (!(*sl)->hasSmoothEdge()) + continue; + if (stopSmoothViewEdge((*sl))) // has it been parsed already ? + continue; + // here we know that we're dealing with a face layer that has not been processed yet and that contains + // a smooth edge. + /* vedge =*//* UNUSED */ BuildSmoothViewEdge(OWXFaceLayer(*sl, true)); + } + } + + // Now let's build sharp view edges: + //---------------------------------- + // Reset all userdata for WXEdge structure + //---------------------------------------- + //iWShape->ResetUserData(); + + WXEdge *wxe; + vector<WEdge *> &wedges = iWShape->getEdgeList(); + //------------------------------ + for (vector<WEdge *>::iterator we = wedges.begin(), weend = wedges.end(); we != weend; we++) { + wxe = dynamic_cast<WXEdge *>(*we); + if (Nature::NO_FEATURE == wxe->nature()) + continue; + + if (!stopSharpViewEdge(wxe)) { + bool b = true; + if (wxe->order() == -1) + b = false; + BuildSharpViewEdge(OWXEdge(wxe, b)); + } + } + + // Reset all userdata for WXEdge structure + //---------------------------------------- + iWShape->ResetUserData(); + + // Add all these new edges to the scene's feature edges list: + //----------------------------------------------------------- + vector<FEdge *> &newedges = _pCurrentSShape->getEdgeList(); + vector<SVertex *> &newVertices = _pCurrentSShape->getVertexList(); + vector<ViewVertex *> &newVVertices = _pCurrentVShape->vertices(); + vector<ViewEdge *> &newVEdges = _pCurrentVShape->edges(); + + // inserts in ioFEdges, at its end, all the edges of newedges + ioFEdges.insert(ioFEdges.end(), newedges.begin(), newedges.end()); + ioSVertices.insert(ioSVertices.end(), newVertices.begin(), newVertices.end()); + ioVVertices.insert(ioVVertices.end(), newVVertices.begin(), newVVertices.end()); + ioVEdges.insert(ioVEdges.end(), newVEdges.begin(), newVEdges.end()); } -ViewEdge *ViewEdgeXBuilder::BuildSmoothViewEdge(const OWXFaceLayer& iFaceLayer) +ViewEdge *ViewEdgeXBuilder::BuildSmoothViewEdge(const OWXFaceLayer &iFaceLayer) { - // Find first edge: - OWXFaceLayer first = iFaceLayer; - OWXFaceLayer currentFace = first; - - // bidirectional chaining. - // first direction - list<OWXFaceLayer> facesChain; - unsigned size = 0; - while (!stopSmoothViewEdge(currentFace.fl)) { - facesChain.push_back(currentFace); - ++size; - currentFace.fl->userdata = (void *)1; // processed - // Find the next edge! - currentFace = FindNextFaceLayer(currentFace); - } - OWXFaceLayer end = facesChain.back(); - // second direction - currentFace = FindPreviousFaceLayer(first); - while (!stopSmoothViewEdge(currentFace.fl)) { - facesChain.push_front(currentFace); - ++size; - currentFace.fl->userdata = (void *)1; // processed - // Find the previous edge! - currentFace = FindPreviousFaceLayer(currentFace); - } - first = facesChain.front(); - - if (iFaceLayer.fl->nature() & Nature::RIDGE) { - if (size < 4) { - return 0; - } - } - - // Start a new chain edges - ViewEdge *newVEdge = new ViewEdge; - newVEdge->setId(_currentViewId); - ++_currentViewId; - - _pCurrentVShape->AddEdge(newVEdge); - - // build FEdges - FEdge *feprevious = NULL; - FEdge *fefirst = NULL; - FEdge *fe = NULL; - for (list<OWXFaceLayer>::iterator fl = facesChain.begin(), flend = facesChain.end(); fl != flend; ++fl) { - fe = BuildSmoothFEdge(feprevious, (*fl)); - if (feprevious && fe == feprevious) - continue; - fe->setViewEdge(newVEdge); - if (!fefirst) - fefirst = fe; - feprevious = fe; - } - // Store the chain starting edge: - _pCurrentSShape->AddChain(fefirst); - newVEdge->setNature(iFaceLayer.fl->nature()); - newVEdge->setFEdgeA(fefirst); - newVEdge->setFEdgeB(fe); - - // is it a closed loop ? - if ((first == end) && (size != 1)) { - fefirst->setPreviousEdge(fe); - fe->setNextEdge(fefirst); - newVEdge->setA(0); - newVEdge->setB(0); - } - else { - ViewVertex *vva = MakeViewVertex(fefirst->vertexA()); - ViewVertex *vvb = MakeViewVertex(fe->vertexB()); - - ((NonTVertex *)vva)->AddOutgoingViewEdge(newVEdge); - ((NonTVertex *)vvb)->AddIncomingViewEdge(newVEdge); - - newVEdge->setA(vva); - newVEdge->setB(vvb); - } - - return newVEdge; + // Find first edge: + OWXFaceLayer first = iFaceLayer; + OWXFaceLayer currentFace = first; + + // bidirectional chaining. + // first direction + list<OWXFaceLayer> facesChain; + unsigned size = 0; + while (!stopSmoothViewEdge(currentFace.fl)) { + facesChain.push_back(currentFace); + ++size; + currentFace.fl->userdata = (void *)1; // processed + // Find the next edge! + currentFace = FindNextFaceLayer(currentFace); + } + OWXFaceLayer end = facesChain.back(); + // second direction + currentFace = FindPreviousFaceLayer(first); + while (!stopSmoothViewEdge(currentFace.fl)) { + facesChain.push_front(currentFace); + ++size; + currentFace.fl->userdata = (void *)1; // processed + // Find the previous edge! + currentFace = FindPreviousFaceLayer(currentFace); + } + first = facesChain.front(); + + if (iFaceLayer.fl->nature() & Nature::RIDGE) { + if (size < 4) { + return 0; + } + } + + // Start a new chain edges + ViewEdge *newVEdge = new ViewEdge; + newVEdge->setId(_currentViewId); + ++_currentViewId; + + _pCurrentVShape->AddEdge(newVEdge); + + // build FEdges + FEdge *feprevious = NULL; + FEdge *fefirst = NULL; + FEdge *fe = NULL; + for (list<OWXFaceLayer>::iterator fl = facesChain.begin(), flend = facesChain.end(); fl != flend; + ++fl) { + fe = BuildSmoothFEdge(feprevious, (*fl)); + if (feprevious && fe == feprevious) + continue; + fe->setViewEdge(newVEdge); + if (!fefirst) + fefirst = fe; + feprevious = fe; + } + // Store the chain starting edge: + _pCurrentSShape->AddChain(fefirst); + newVEdge->setNature(iFaceLayer.fl->nature()); + newVEdge->setFEdgeA(fefirst); + newVEdge->setFEdgeB(fe); + + // is it a closed loop ? + if ((first == end) && (size != 1)) { + fefirst->setPreviousEdge(fe); + fe->setNextEdge(fefirst); + newVEdge->setA(0); + newVEdge->setB(0); + } + else { + ViewVertex *vva = MakeViewVertex(fefirst->vertexA()); + ViewVertex *vvb = MakeViewVertex(fe->vertexB()); + + ((NonTVertex *)vva)->AddOutgoingViewEdge(newVEdge); + ((NonTVertex *)vvb)->AddIncomingViewEdge(newVEdge); + + newVEdge->setA(vva); + newVEdge->setB(vvb); + } + + return newVEdge; } -ViewEdge *ViewEdgeXBuilder::BuildSharpViewEdge(const OWXEdge& iWEdge) +ViewEdge *ViewEdgeXBuilder::BuildSharpViewEdge(const OWXEdge &iWEdge) { - // Start a new sharp chain edges - ViewEdge *newVEdge = new ViewEdge; - newVEdge->setId(_currentViewId); - ++_currentViewId; - unsigned size = 0; - - _pCurrentVShape->AddEdge(newVEdge); - - // Find first edge: - OWXEdge firstWEdge = iWEdge; - /* OWXEdge previousWEdge = firstWEdge; */ /* UNUSED */ - OWXEdge currentWEdge = firstWEdge; - list<OWXEdge> edgesChain; + // Start a new sharp chain edges + ViewEdge *newVEdge = new ViewEdge; + newVEdge->setId(_currentViewId); + ++_currentViewId; + unsigned size = 0; + + _pCurrentVShape->AddEdge(newVEdge); + + // Find first edge: + OWXEdge firstWEdge = iWEdge; + /* OWXEdge previousWEdge = firstWEdge; */ /* UNUSED */ + OWXEdge currentWEdge = firstWEdge; + list<OWXEdge> edgesChain; #if 0 /* TK 02-Sep-2012 Experimental fix for incorrect view edge visibility. */ - // bidirectional chaining - // first direction: - while (!stopSharpViewEdge(currentWEdge.e)) { - edgesChain.push_back(currentWEdge); - ++size; - currentWEdge.e->userdata = (void *)1; // processed - // Find the next edge! - currentWEdge = FindNextWEdge(currentWEdge); - } - OWXEdge endWEdge = edgesChain.back(); - // second direction - currentWEdge = FindPreviousWEdge(firstWEdge); - while (!stopSharpViewEdge(currentWEdge.e)) { - edgesChain.push_front(currentWEdge); - ++size; - currentWEdge.e->userdata = (void *)1; // processed - // Find the previous edge! - currentWEdge = FindPreviousWEdge(currentWEdge); - } + // bidirectional chaining + // first direction: + while (!stopSharpViewEdge(currentWEdge.e)) { + edgesChain.push_back(currentWEdge); + ++size; + currentWEdge.e->userdata = (void *)1; // processed + // Find the next edge! + currentWEdge = FindNextWEdge(currentWEdge); + } + OWXEdge endWEdge = edgesChain.back(); + // second direction + currentWEdge = FindPreviousWEdge(firstWEdge); + while (!stopSharpViewEdge(currentWEdge.e)) { + edgesChain.push_front(currentWEdge); + ++size; + currentWEdge.e->userdata = (void *)1; // processed + // Find the previous edge! + currentWEdge = FindPreviousWEdge(currentWEdge); + } #else - edgesChain.push_back(currentWEdge); - ++size; - currentWEdge.e->userdata = (void *)1; // processed - OWXEdge endWEdge = edgesChain.back(); + edgesChain.push_back(currentWEdge); + ++size; + currentWEdge.e->userdata = (void *)1; // processed + OWXEdge endWEdge = edgesChain.back(); #endif - firstWEdge = edgesChain.front(); - - // build FEdges - FEdge *feprevious = NULL; - FEdge *fefirst = NULL; - FEdge *fe = NULL; - for (list<OWXEdge>::iterator we = edgesChain.begin(), weend = edgesChain.end(); we != weend; ++we) { - fe = BuildSharpFEdge(feprevious, (*we)); - fe->setViewEdge(newVEdge); - if (!fefirst) - fefirst = fe; - feprevious = fe; - } - // Store the chain starting edge: - _pCurrentSShape->AddChain(fefirst); - newVEdge->setNature(iWEdge.e->nature()); - newVEdge->setFEdgeA(fefirst); - newVEdge->setFEdgeB(fe); - - // is it a closed loop ? - if ((firstWEdge == endWEdge) && (size != 1)) { - fefirst->setPreviousEdge(fe); - fe->setNextEdge(fefirst); - newVEdge->setA(0); - newVEdge->setB(0); - } - else { - ViewVertex *vva = MakeViewVertex(fefirst->vertexA()); - ViewVertex *vvb = MakeViewVertex(fe->vertexB()); - - ((NonTVertex *)vva)->AddOutgoingViewEdge(newVEdge); - ((NonTVertex *)vvb)->AddIncomingViewEdge(newVEdge); - - newVEdge->setA(vva); - newVEdge->setB(vvb); - } - - return newVEdge; + firstWEdge = edgesChain.front(); + + // build FEdges + FEdge *feprevious = NULL; + FEdge *fefirst = NULL; + FEdge *fe = NULL; + for (list<OWXEdge>::iterator we = edgesChain.begin(), weend = edgesChain.end(); we != weend; + ++we) { + fe = BuildSharpFEdge(feprevious, (*we)); + fe->setViewEdge(newVEdge); + if (!fefirst) + fefirst = fe; + feprevious = fe; + } + // Store the chain starting edge: + _pCurrentSShape->AddChain(fefirst); + newVEdge->setNature(iWEdge.e->nature()); + newVEdge->setFEdgeA(fefirst); + newVEdge->setFEdgeB(fe); + + // is it a closed loop ? + if ((firstWEdge == endWEdge) && (size != 1)) { + fefirst->setPreviousEdge(fe); + fe->setNextEdge(fefirst); + newVEdge->setA(0); + newVEdge->setB(0); + } + else { + ViewVertex *vva = MakeViewVertex(fefirst->vertexA()); + ViewVertex *vvb = MakeViewVertex(fe->vertexB()); + + ((NonTVertex *)vva)->AddOutgoingViewEdge(newVEdge); + ((NonTVertex *)vvb)->AddIncomingViewEdge(newVEdge); + + newVEdge->setA(vva); + newVEdge->setB(vvb); + } + + return newVEdge; } -OWXFaceLayer ViewEdgeXBuilder::FindNextFaceLayer(const OWXFaceLayer& iFaceLayer) +OWXFaceLayer ViewEdgeXBuilder::FindNextFaceLayer(const OWXFaceLayer &iFaceLayer) { - WXFace *nextFace = NULL; - WOEdge *woeend; - real tend; - if (iFaceLayer.order) { - woeend = iFaceLayer.fl->getSmoothEdge()->woeb(); - tend = iFaceLayer.fl->getSmoothEdge()->tb(); - } - else { - woeend = iFaceLayer.fl->getSmoothEdge()->woea(); - tend = iFaceLayer.fl->getSmoothEdge()->ta(); - } - // special case of EDGE_VERTEX config: - if ((tend == 0.0) || (tend == 1.0)) { - WVertex *nextVertex; - if (tend == 0.0) - nextVertex = woeend->GetaVertex(); - else - nextVertex = woeend->GetbVertex(); - if (nextVertex->isBoundary()) // if it's a non-manifold vertex -> ignore - return OWXFaceLayer(0, true); - bool found = false; - WVertex::face_iterator f = nextVertex->faces_begin(); - WVertex::face_iterator fend = nextVertex->faces_end(); - while ((!found) && (f != fend)) { - nextFace = dynamic_cast<WXFace*>(*f); - if ((0 != nextFace) && (nextFace != iFaceLayer.fl->getFace())) { - vector<WXFaceLayer*> sameNatureLayers; - nextFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers); - // don't know... Maybe should test whether this face has also a vertex_edge configuration. - if (sameNatureLayers.size() == 1) { - WXFaceLayer *winner = sameNatureLayers[0]; - // check face mark continuity - if (winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark()) - return OWXFaceLayer(NULL, true); - if (woeend == winner->getSmoothEdge()->woea()->twin()) - return OWXFaceLayer(winner, true); - else - return OWXFaceLayer(winner, false); - } - } - ++f; - } - } - else { - nextFace = dynamic_cast<WXFace*>(iFaceLayer.fl->getFace()->GetBordingFace(woeend)); - if (!nextFace) - return OWXFaceLayer(NULL, true); - // if the next face layer has either no smooth edge or no smooth edge of same nature, no next face - if (!nextFace->hasSmoothEdges()) - return OWXFaceLayer(NULL, true); - vector<WXFaceLayer*> sameNatureLayers; - nextFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers); - // don't know how to deal with several edges of same nature on a single face - if ((sameNatureLayers.empty()) || (sameNatureLayers.size() != 1)) { - return OWXFaceLayer(NULL, true); - } - else { - WXFaceLayer *winner = sameNatureLayers[0]; - // check face mark continuity - if (winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark()) - return OWXFaceLayer(NULL, true); - if (woeend == winner->getSmoothEdge()->woea()->twin()) - return OWXFaceLayer(winner, true); - else - return OWXFaceLayer(winner, false); - } - } - return OWXFaceLayer(NULL, true); + WXFace *nextFace = NULL; + WOEdge *woeend; + real tend; + if (iFaceLayer.order) { + woeend = iFaceLayer.fl->getSmoothEdge()->woeb(); + tend = iFaceLayer.fl->getSmoothEdge()->tb(); + } + else { + woeend = iFaceLayer.fl->getSmoothEdge()->woea(); + tend = iFaceLayer.fl->getSmoothEdge()->ta(); + } + // special case of EDGE_VERTEX config: + if ((tend == 0.0) || (tend == 1.0)) { + WVertex *nextVertex; + if (tend == 0.0) + nextVertex = woeend->GetaVertex(); + else + nextVertex = woeend->GetbVertex(); + if (nextVertex->isBoundary()) // if it's a non-manifold vertex -> ignore + return OWXFaceLayer(0, true); + bool found = false; + WVertex::face_iterator f = nextVertex->faces_begin(); + WVertex::face_iterator fend = nextVertex->faces_end(); + while ((!found) && (f != fend)) { + nextFace = dynamic_cast<WXFace *>(*f); + if ((0 != nextFace) && (nextFace != iFaceLayer.fl->getFace())) { + vector<WXFaceLayer *> sameNatureLayers; + nextFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers); + // don't know... Maybe should test whether this face has also a vertex_edge configuration. + if (sameNatureLayers.size() == 1) { + WXFaceLayer *winner = sameNatureLayers[0]; + // check face mark continuity + if (winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark()) + return OWXFaceLayer(NULL, true); + if (woeend == winner->getSmoothEdge()->woea()->twin()) + return OWXFaceLayer(winner, true); + else + return OWXFaceLayer(winner, false); + } + } + ++f; + } + } + else { + nextFace = dynamic_cast<WXFace *>(iFaceLayer.fl->getFace()->GetBordingFace(woeend)); + if (!nextFace) + return OWXFaceLayer(NULL, true); + // if the next face layer has either no smooth edge or no smooth edge of same nature, no next face + if (!nextFace->hasSmoothEdges()) + return OWXFaceLayer(NULL, true); + vector<WXFaceLayer *> sameNatureLayers; + nextFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers); + // don't know how to deal with several edges of same nature on a single face + if ((sameNatureLayers.empty()) || (sameNatureLayers.size() != 1)) { + return OWXFaceLayer(NULL, true); + } + else { + WXFaceLayer *winner = sameNatureLayers[0]; + // check face mark continuity + if (winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark()) + return OWXFaceLayer(NULL, true); + if (woeend == winner->getSmoothEdge()->woea()->twin()) + return OWXFaceLayer(winner, true); + else + return OWXFaceLayer(winner, false); + } + } + return OWXFaceLayer(NULL, true); } -OWXFaceLayer ViewEdgeXBuilder::FindPreviousFaceLayer(const OWXFaceLayer& iFaceLayer) +OWXFaceLayer ViewEdgeXBuilder::FindPreviousFaceLayer(const OWXFaceLayer &iFaceLayer) { - WXFace *previousFace = NULL; - WOEdge *woebegin; - real tend; - if (iFaceLayer.order) { - woebegin = iFaceLayer.fl->getSmoothEdge()->woea(); - tend = iFaceLayer.fl->getSmoothEdge()->ta(); - } - else { - woebegin = iFaceLayer.fl->getSmoothEdge()->woeb(); - tend = iFaceLayer.fl->getSmoothEdge()->tb(); - } - - // special case of EDGE_VERTEX config: - if ((tend == 0.0) || (tend == 1.0)) { - WVertex *previousVertex; - if (tend == 0.0) - previousVertex = woebegin->GetaVertex(); - else - previousVertex = woebegin->GetbVertex(); - if (previousVertex->isBoundary()) // if it's a non-manifold vertex -> ignore - return OWXFaceLayer(NULL, true); - bool found = false; - WVertex::face_iterator f = previousVertex->faces_begin(); - WVertex::face_iterator fend = previousVertex->faces_end(); - for (; (!found) && (f != fend); ++f) { - previousFace = dynamic_cast<WXFace*>(*f); - if ((0 != previousFace) && (previousFace != iFaceLayer.fl->getFace())) { - vector<WXFaceLayer*> sameNatureLayers; - previousFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers); - // don't know... Maybe should test whether this face has also a vertex_edge configuration - if (sameNatureLayers.size() == 1) { - WXFaceLayer *winner = sameNatureLayers[0]; - // check face mark continuity - if (winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark()) - return OWXFaceLayer(NULL, true); - if (woebegin == winner->getSmoothEdge()->woeb()->twin()) - return OWXFaceLayer(winner, true); - else - return OWXFaceLayer(winner, false); - } - } - } - } - else { - previousFace = dynamic_cast<WXFace*>(iFaceLayer.fl->getFace()->GetBordingFace(woebegin)); - if (0 == previousFace) - return OWXFaceLayer(NULL, true); - // if the next face layer has either no smooth edge or no smooth edge of same nature, no next face - if (!previousFace->hasSmoothEdges()) - return OWXFaceLayer(NULL, true); - vector<WXFaceLayer*> sameNatureLayers; - previousFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers); - // don't know how to deal with several edges of same nature on a single face - if ((sameNatureLayers.empty()) || (sameNatureLayers.size() != 1)) { - return OWXFaceLayer(NULL, true); - } - else { - WXFaceLayer *winner = sameNatureLayers[0]; - // check face mark continuity - if (winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark()) - return OWXFaceLayer(NULL, true); - if (woebegin == winner->getSmoothEdge()->woeb()->twin()) - return OWXFaceLayer(winner, true); - else - return OWXFaceLayer(winner, false); - } - } - return OWXFaceLayer(NULL, true); + WXFace *previousFace = NULL; + WOEdge *woebegin; + real tend; + if (iFaceLayer.order) { + woebegin = iFaceLayer.fl->getSmoothEdge()->woea(); + tend = iFaceLayer.fl->getSmoothEdge()->ta(); + } + else { + woebegin = iFaceLayer.fl->getSmoothEdge()->woeb(); + tend = iFaceLayer.fl->getSmoothEdge()->tb(); + } + + // special case of EDGE_VERTEX config: + if ((tend == 0.0) || (tend == 1.0)) { + WVertex *previousVertex; + if (tend == 0.0) + previousVertex = woebegin->GetaVertex(); + else + previousVertex = woebegin->GetbVertex(); + if (previousVertex->isBoundary()) // if it's a non-manifold vertex -> ignore + return OWXFaceLayer(NULL, true); + bool found = false; + WVertex::face_iterator f = previousVertex->faces_begin(); + WVertex::face_iterator fend = previousVertex->faces_end(); + for (; (!found) && (f != fend); ++f) { + previousFace = dynamic_cast<WXFace *>(*f); + if ((0 != previousFace) && (previousFace != iFaceLayer.fl->getFace())) { + vector<WXFaceLayer *> sameNatureLayers; + previousFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers); + // don't know... Maybe should test whether this face has also a vertex_edge configuration + if (sameNatureLayers.size() == 1) { + WXFaceLayer *winner = sameNatureLayers[0]; + // check face mark continuity + if (winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark()) + return OWXFaceLayer(NULL, true); + if (woebegin == winner->getSmoothEdge()->woeb()->twin()) + return OWXFaceLayer(winner, true); + else + return OWXFaceLayer(winner, false); + } + } + } + } + else { + previousFace = dynamic_cast<WXFace *>(iFaceLayer.fl->getFace()->GetBordingFace(woebegin)); + if (0 == previousFace) + return OWXFaceLayer(NULL, true); + // if the next face layer has either no smooth edge or no smooth edge of same nature, no next face + if (!previousFace->hasSmoothEdges()) + return OWXFaceLayer(NULL, true); + vector<WXFaceLayer *> sameNatureLayers; + previousFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers); + // don't know how to deal with several edges of same nature on a single face + if ((sameNatureLayers.empty()) || (sameNatureLayers.size() != 1)) { + return OWXFaceLayer(NULL, true); + } + else { + WXFaceLayer *winner = sameNatureLayers[0]; + // check face mark continuity + if (winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark()) + return OWXFaceLayer(NULL, true); + if (woebegin == winner->getSmoothEdge()->woeb()->twin()) + return OWXFaceLayer(winner, true); + else + return OWXFaceLayer(winner, false); + } + } + return OWXFaceLayer(NULL, true); } -FEdge *ViewEdgeXBuilder::BuildSmoothFEdge(FEdge *feprevious, const OWXFaceLayer& ifl) +FEdge *ViewEdgeXBuilder::BuildSmoothFEdge(FEdge *feprevious, const OWXFaceLayer &ifl) { - WOEdge *woea, *woeb; - real ta, tb; - SVertex *va, *vb; - FEdgeSmooth *fe; - // retrieve exact silhouette data - WXSmoothEdge *se = ifl.fl->getSmoothEdge(); - - if (ifl.order) { - woea = se->woea(); - woeb = se->woeb(); - ta = se->ta(); - tb = se->tb(); - } - else { - woea = se->woeb(); - woeb = se->woea(); - ta = se->tb(); - tb = se->ta(); - } - - Vec3r normal; - // Make the 2 Svertices - if (feprevious == 0) { // that means that we don't have any vertex already built for that face - Vec3r A1(woea->GetaVertex()->GetVertex()); - Vec3r A2(woea->GetbVertex()->GetVertex()); - Vec3r A(A1 + ta * (A2 - A1)); - - va = MakeSVertex(A, false); - // Set normal: - Vec3r NA1(ifl.fl->getFace()->GetVertexNormal(woea->GetaVertex())); - Vec3r NA2(ifl.fl->getFace()->GetVertexNormal(woea->GetbVertex())); - Vec3r na((1 - ta) * NA1 + ta * NA2); - na.normalize(); - va->AddNormal(na); - normal = na; - - // Set CurvatureInfo - CurvatureInfo *curvature_info_a = - new CurvatureInfo(*(dynamic_cast<WXVertex*>(woea->GetaVertex())->curvatures()), - *(dynamic_cast<WXVertex*>(woea->GetbVertex())->curvatures()), ta); - va->setCurvatureInfo(curvature_info_a); - } - else { - va = feprevious->vertexB(); - } - - Vec3r B1(woeb->GetaVertex()->GetVertex()); - Vec3r B2(woeb->GetbVertex()->GetVertex()); - Vec3r B(B1 + tb * (B2 - B1)); - - if (feprevious && (B - va->point3D()).norm() < 1.0e-6) - return feprevious; - - vb = MakeSVertex(B, false); - // Set normal: - Vec3r NB1(ifl.fl->getFace()->GetVertexNormal(woeb->GetaVertex())); - Vec3r NB2(ifl.fl->getFace()->GetVertexNormal(woeb->GetbVertex())); - Vec3r nb((1 - tb) * NB1 + tb * NB2); - nb.normalize(); - normal += nb; - vb->AddNormal(nb); - - // Set CurvatureInfo - CurvatureInfo *curvature_info_b = - new CurvatureInfo(*(dynamic_cast<WXVertex*>(woeb->GetaVertex())->curvatures()), - *(dynamic_cast<WXVertex*>(woeb->GetbVertex())->curvatures()), tb); - vb->setCurvatureInfo(curvature_info_b); - - // Creates the corresponding feature edge - fe = new FEdgeSmooth(va, vb); - fe->setNature(ifl.fl->nature()); - fe->setId(_currentFId); - fe->setFrsMaterialIndex(ifl.fl->getFace()->frs_materialIndex()); - fe->setFace(ifl.fl->getFace()); - fe->setFaceMark(ifl.fl->getFace()->GetMark()); - if (feprevious == 0) - normal.normalize(); - fe->setNormal(normal); - fe->setPreviousEdge(feprevious); - if (feprevious) - feprevious->setNextEdge(fe); - _pCurrentSShape->AddEdge(fe); - va->AddFEdge(fe); - vb->AddFEdge(fe); - - ++_currentFId; - ifl.fl->userdata = fe; - return fe; + WOEdge *woea, *woeb; + real ta, tb; + SVertex *va, *vb; + FEdgeSmooth *fe; + // retrieve exact silhouette data + WXSmoothEdge *se = ifl.fl->getSmoothEdge(); + + if (ifl.order) { + woea = se->woea(); + woeb = se->woeb(); + ta = se->ta(); + tb = se->tb(); + } + else { + woea = se->woeb(); + woeb = se->woea(); + ta = se->tb(); + tb = se->ta(); + } + + Vec3r normal; + // Make the 2 Svertices + if (feprevious == 0) { // that means that we don't have any vertex already built for that face + Vec3r A1(woea->GetaVertex()->GetVertex()); + Vec3r A2(woea->GetbVertex()->GetVertex()); + Vec3r A(A1 + ta * (A2 - A1)); + + va = MakeSVertex(A, false); + // Set normal: + Vec3r NA1(ifl.fl->getFace()->GetVertexNormal(woea->GetaVertex())); + Vec3r NA2(ifl.fl->getFace()->GetVertexNormal(woea->GetbVertex())); + Vec3r na((1 - ta) * NA1 + ta * NA2); + na.normalize(); + va->AddNormal(na); + normal = na; + + // Set CurvatureInfo + CurvatureInfo *curvature_info_a = new CurvatureInfo( + *(dynamic_cast<WXVertex *>(woea->GetaVertex())->curvatures()), + *(dynamic_cast<WXVertex *>(woea->GetbVertex())->curvatures()), + ta); + va->setCurvatureInfo(curvature_info_a); + } + else { + va = feprevious->vertexB(); + } + + Vec3r B1(woeb->GetaVertex()->GetVertex()); + Vec3r B2(woeb->GetbVertex()->GetVertex()); + Vec3r B(B1 + tb * (B2 - B1)); + + if (feprevious && (B - va->point3D()).norm() < 1.0e-6) + return feprevious; + + vb = MakeSVertex(B, false); + // Set normal: + Vec3r NB1(ifl.fl->getFace()->GetVertexNormal(woeb->GetaVertex())); + Vec3r NB2(ifl.fl->getFace()->GetVertexNormal(woeb->GetbVertex())); + Vec3r nb((1 - tb) * NB1 + tb * NB2); + nb.normalize(); + normal += nb; + vb->AddNormal(nb); + + // Set CurvatureInfo + CurvatureInfo *curvature_info_b = new CurvatureInfo( + *(dynamic_cast<WXVertex *>(woeb->GetaVertex())->curvatures()), + *(dynamic_cast<WXVertex *>(woeb->GetbVertex())->curvatures()), + tb); + vb->setCurvatureInfo(curvature_info_b); + + // Creates the corresponding feature edge + fe = new FEdgeSmooth(va, vb); + fe->setNature(ifl.fl->nature()); + fe->setId(_currentFId); + fe->setFrsMaterialIndex(ifl.fl->getFace()->frs_materialIndex()); + fe->setFace(ifl.fl->getFace()); + fe->setFaceMark(ifl.fl->getFace()->GetMark()); + if (feprevious == 0) + normal.normalize(); + fe->setNormal(normal); + fe->setPreviousEdge(feprevious); + if (feprevious) + feprevious->setNextEdge(fe); + _pCurrentSShape->AddEdge(fe); + va->AddFEdge(fe); + vb->AddFEdge(fe); + + ++_currentFId; + ifl.fl->userdata = fe; + return fe; } bool ViewEdgeXBuilder::stopSmoothViewEdge(WXFaceLayer *iFaceLayer) { - if (NULL == iFaceLayer) - return true; - if (iFaceLayer->userdata == 0) - return false; - return true; + if (NULL == iFaceLayer) + return true; + if (iFaceLayer->userdata == 0) + return false; + return true; } int ViewEdgeXBuilder::retrieveFaceMarks(WXEdge *iEdge) { - WFace *aFace = iEdge->GetaFace(); - WFace *bFace = iEdge->GetbFace(); - int result = 0; - if (aFace && aFace->GetMark()) - result += 1; - if (bFace && bFace->GetMark()) - result += 2; - return result; + WFace *aFace = iEdge->GetaFace(); + WFace *bFace = iEdge->GetbFace(); + int result = 0; + if (aFace && aFace->GetMark()) + result += 1; + if (bFace && bFace->GetMark()) + result += 2; + return result; } -OWXEdge ViewEdgeXBuilder::FindNextWEdge(const OWXEdge& iEdge) +OWXEdge ViewEdgeXBuilder::FindNextWEdge(const OWXEdge &iEdge) { - if (Nature::NO_FEATURE == iEdge.e->nature()) - return OWXEdge(NULL, true); - - WVertex *v; - if (true == iEdge.order) - v = iEdge.e->GetbVertex(); - else - v = iEdge.e->GetaVertex(); - - if (((WXVertex *)v)->isFeature()) - return 0; /* XXX eeek? NULL? OWXEdge(NULL, true/false)?*/ - - int faceMarks = retrieveFaceMarks(iEdge.e); - vector<WEdge*>& vEdges = (v)->GetEdges(); - for (vector<WEdge*>::iterator ve = vEdges.begin(), veend = vEdges.end(); ve != veend; ve++) { - WXEdge *wxe = dynamic_cast<WXEdge*>(*ve); - if (wxe == iEdge.e) - continue; // same edge as the one processed - - if (wxe->nature() != iEdge.e->nature()) - continue; - - // check face mark continuity - if (retrieveFaceMarks(wxe) != faceMarks) - continue; - - if (wxe->GetaVertex() == v) { - // That means that the face necesarily lies on the edge left. - // So the vertex order is OK. - return OWXEdge(wxe, true); - } - else { - // That means that the face necesarily lies on the edge left. - // So the vertex order is OK. - return OWXEdge(wxe, false); - } - } - // we did not find: - return OWXEdge(NULL, true); + if (Nature::NO_FEATURE == iEdge.e->nature()) + return OWXEdge(NULL, true); + + WVertex *v; + if (true == iEdge.order) + v = iEdge.e->GetbVertex(); + else + v = iEdge.e->GetaVertex(); + + if (((WXVertex *)v)->isFeature()) + return 0; /* XXX eeek? NULL? OWXEdge(NULL, true/false)?*/ + + int faceMarks = retrieveFaceMarks(iEdge.e); + vector<WEdge *> &vEdges = (v)->GetEdges(); + for (vector<WEdge *>::iterator ve = vEdges.begin(), veend = vEdges.end(); ve != veend; ve++) { + WXEdge *wxe = dynamic_cast<WXEdge *>(*ve); + if (wxe == iEdge.e) + continue; // same edge as the one processed + + if (wxe->nature() != iEdge.e->nature()) + continue; + + // check face mark continuity + if (retrieveFaceMarks(wxe) != faceMarks) + continue; + + if (wxe->GetaVertex() == v) { + // That means that the face necesarily lies on the edge left. + // So the vertex order is OK. + return OWXEdge(wxe, true); + } + else { + // That means that the face necesarily lies on the edge left. + // So the vertex order is OK. + return OWXEdge(wxe, false); + } + } + // we did not find: + return OWXEdge(NULL, true); } -OWXEdge ViewEdgeXBuilder::FindPreviousWEdge(const OWXEdge& iEdge) +OWXEdge ViewEdgeXBuilder::FindPreviousWEdge(const OWXEdge &iEdge) { - if (Nature::NO_FEATURE == iEdge.e->nature()) - return OWXEdge(NULL, true); - - WVertex *v; - if (true == iEdge.order) - v = iEdge.e->GetaVertex(); - else - v = iEdge.e->GetbVertex(); - - if (((WXVertex *)v)->isFeature()) - return 0; - - int faceMarks = retrieveFaceMarks(iEdge.e); - vector<WEdge *>& vEdges = (v)->GetEdges(); - for (vector<WEdge *>::iterator ve = vEdges.begin(), veend = vEdges.end(); ve != veend; ve++) { - WXEdge *wxe = dynamic_cast<WXEdge *>(*ve); - if (wxe == iEdge.e) - continue; // same edge as the one processed - - if (wxe->nature() != iEdge.e->nature()) - continue; - - // check face mark continuity - if (retrieveFaceMarks(wxe) != faceMarks) - continue; - - if (wxe->GetbVertex() == v) { - return OWXEdge(wxe, true); - } - else { - return OWXEdge(wxe, false); - } - } - // we did not find: - return OWXEdge(NULL, true); + if (Nature::NO_FEATURE == iEdge.e->nature()) + return OWXEdge(NULL, true); + + WVertex *v; + if (true == iEdge.order) + v = iEdge.e->GetaVertex(); + else + v = iEdge.e->GetbVertex(); + + if (((WXVertex *)v)->isFeature()) + return 0; + + int faceMarks = retrieveFaceMarks(iEdge.e); + vector<WEdge *> &vEdges = (v)->GetEdges(); + for (vector<WEdge *>::iterator ve = vEdges.begin(), veend = vEdges.end(); ve != veend; ve++) { + WXEdge *wxe = dynamic_cast<WXEdge *>(*ve); + if (wxe == iEdge.e) + continue; // same edge as the one processed + + if (wxe->nature() != iEdge.e->nature()) + continue; + + // check face mark continuity + if (retrieveFaceMarks(wxe) != faceMarks) + continue; + + if (wxe->GetbVertex() == v) { + return OWXEdge(wxe, true); + } + else { + return OWXEdge(wxe, false); + } + } + // we did not find: + return OWXEdge(NULL, true); } -FEdge *ViewEdgeXBuilder::BuildSharpFEdge(FEdge *feprevious, const OWXEdge& iwe) +FEdge *ViewEdgeXBuilder::BuildSharpFEdge(FEdge *feprevious, const OWXEdge &iwe) { - SVertex *va, *vb; - FEdgeSharp *fe; - Vec3r vA, vB; - if (iwe.order) { - vA = iwe.e->GetaVertex()->GetVertex(); - vB = iwe.e->GetbVertex()->GetVertex(); - } - else { - vA = iwe.e->GetbVertex()->GetVertex(); - vB = iwe.e->GetaVertex()->GetVertex(); - } - // Make the 2 SVertex - va = MakeSVertex(vA, true); - vb = MakeSVertex(vB, true); - - // get the faces normals and the material indices - Vec3r normalA, normalB; - unsigned matA(0), matB(0); - bool faceMarkA = false, faceMarkB = false; - if (iwe.order) { - normalB = (iwe.e->GetbFace()->GetNormal()); - matB = (iwe.e->GetbFace()->frs_materialIndex()); - faceMarkB = (iwe.e->GetbFace()->GetMark()); - if (!(iwe.e->nature() & Nature::BORDER)) { - normalA = (iwe.e->GetaFace()->GetNormal()); - matA = (iwe.e->GetaFace()->frs_materialIndex()); - faceMarkA = (iwe.e->GetaFace()->GetMark()); - } - } - else { - normalA = (iwe.e->GetbFace()->GetNormal()); - matA = (iwe.e->GetbFace()->frs_materialIndex()); - faceMarkA = (iwe.e->GetbFace()->GetMark()); - if (!(iwe.e->nature() & Nature::BORDER)) { - normalB = (iwe.e->GetaFace()->GetNormal()); - matB = (iwe.e->GetaFace()->frs_materialIndex()); - faceMarkB = (iwe.e->GetaFace()->GetMark()); - } - } - // Creates the corresponding feature edge - fe = new FEdgeSharp(va, vb); - fe->setNature(iwe.e->nature()); - fe->setId(_currentFId); - fe->setaFrsMaterialIndex(matA); - fe->setbFrsMaterialIndex(matB); - fe->setaFaceMark(faceMarkA); - fe->setbFaceMark(faceMarkB); - fe->setNormalA(normalA); - fe->setNormalB(normalB); - fe->setPreviousEdge(feprevious); - if (feprevious) - feprevious->setNextEdge(fe); - _pCurrentSShape->AddEdge(fe); - va->AddFEdge(fe); - vb->AddFEdge(fe); - //Add normals: - va->AddNormal(normalA); - va->AddNormal(normalB); - vb->AddNormal(normalA); - vb->AddNormal(normalB); - - ++_currentFId; - iwe.e->userdata = fe; - return fe; + SVertex *va, *vb; + FEdgeSharp *fe; + Vec3r vA, vB; + if (iwe.order) { + vA = iwe.e->GetaVertex()->GetVertex(); + vB = iwe.e->GetbVertex()->GetVertex(); + } + else { + vA = iwe.e->GetbVertex()->GetVertex(); + vB = iwe.e->GetaVertex()->GetVertex(); + } + // Make the 2 SVertex + va = MakeSVertex(vA, true); + vb = MakeSVertex(vB, true); + + // get the faces normals and the material indices + Vec3r normalA, normalB; + unsigned matA(0), matB(0); + bool faceMarkA = false, faceMarkB = false; + if (iwe.order) { + normalB = (iwe.e->GetbFace()->GetNormal()); + matB = (iwe.e->GetbFace()->frs_materialIndex()); + faceMarkB = (iwe.e->GetbFace()->GetMark()); + if (!(iwe.e->nature() & Nature::BORDER)) { + normalA = (iwe.e->GetaFace()->GetNormal()); + matA = (iwe.e->GetaFace()->frs_materialIndex()); + faceMarkA = (iwe.e->GetaFace()->GetMark()); + } + } + else { + normalA = (iwe.e->GetbFace()->GetNormal()); + matA = (iwe.e->GetbFace()->frs_materialIndex()); + faceMarkA = (iwe.e->GetbFace()->GetMark()); + if (!(iwe.e->nature() & Nature::BORDER)) { + normalB = (iwe.e->GetaFace()->GetNormal()); + matB = (iwe.e->GetaFace()->frs_materialIndex()); + faceMarkB = (iwe.e->GetaFace()->GetMark()); + } + } + // Creates the corresponding feature edge + fe = new FEdgeSharp(va, vb); + fe->setNature(iwe.e->nature()); + fe->setId(_currentFId); + fe->setaFrsMaterialIndex(matA); + fe->setbFrsMaterialIndex(matB); + fe->setaFaceMark(faceMarkA); + fe->setbFaceMark(faceMarkB); + fe->setNormalA(normalA); + fe->setNormalB(normalB); + fe->setPreviousEdge(feprevious); + if (feprevious) + feprevious->setNextEdge(fe); + _pCurrentSShape->AddEdge(fe); + va->AddFEdge(fe); + vb->AddFEdge(fe); + //Add normals: + va->AddNormal(normalA); + va->AddNormal(normalB); + vb->AddNormal(normalA); + vb->AddNormal(normalB); + + ++_currentFId; + iwe.e->userdata = fe; + return fe; } bool ViewEdgeXBuilder::stopSharpViewEdge(WXEdge *iEdge) { - if (NULL == iEdge) - return true; - if (iEdge->userdata == 0) - return false; - return true; + if (NULL == iEdge) + return true; + if (iEdge->userdata == 0) + return false; + return true; } -SVertex *ViewEdgeXBuilder::MakeSVertex(Vec3r& iPoint) +SVertex *ViewEdgeXBuilder::MakeSVertex(Vec3r &iPoint) { - SVertex *va = new SVertex(iPoint, _currentSVertexId); - SilhouetteGeomEngine::ProjectSilhouette(va); - ++_currentSVertexId; - // Add the svertex to the SShape svertex list: - _pCurrentSShape->AddNewVertex(va); - return va; + SVertex *va = new SVertex(iPoint, _currentSVertexId); + SilhouetteGeomEngine::ProjectSilhouette(va); + ++_currentSVertexId; + // Add the svertex to the SShape svertex list: + _pCurrentSShape->AddNewVertex(va); + return va; } -SVertex *ViewEdgeXBuilder::MakeSVertex(Vec3r& iPoint, bool shared) +SVertex *ViewEdgeXBuilder::MakeSVertex(Vec3r &iPoint, bool shared) { - SVertex *va; - if (!shared) { - va = MakeSVertex(iPoint); - } - else { - // Check whether the iPoint is already in the table - SVertexMap::const_iterator found = _SVertexMap.find(iPoint); - if (shared && found != _SVertexMap.end()) { - va = (*found).second; - } - else { - va = MakeSVertex(iPoint); - // Add the svertex into the table using iPoint as the key - _SVertexMap[iPoint] = va; - } - } - return va; + SVertex *va; + if (!shared) { + va = MakeSVertex(iPoint); + } + else { + // Check whether the iPoint is already in the table + SVertexMap::const_iterator found = _SVertexMap.find(iPoint); + if (shared && found != _SVertexMap.end()) { + va = (*found).second; + } + else { + va = MakeSVertex(iPoint); + // Add the svertex into the table using iPoint as the key + _SVertexMap[iPoint] = va; + } + } + return va; } ViewVertex *ViewEdgeXBuilder::MakeViewVertex(SVertex *iSVertex) { - ViewVertex *vva = iSVertex->viewvertex(); - if (vva) - return vva; - vva = new NonTVertex(iSVertex); - // Add the view vertex to the ViewShape svertex list: - _pCurrentVShape->AddVertex(vva); - return vva; + ViewVertex *vva = iSVertex->viewvertex(); + if (vva) + return vva; + vva = new NonTVertex(iSVertex); + // Add the view vertex to the ViewShape svertex list: + _pCurrentVShape->AddVertex(vva); + return vva; } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.h b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.h index fbe0ee8be0f..6f3604a1029 100644 --- a/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.h +++ b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.h @@ -26,13 +26,13 @@ #include <utility> #include <vector> -#if 0 // soc -#if defined(__GNUC__) && (__GNUC__ >= 3) +#if 0 // soc +# if defined(__GNUC__) && (__GNUC__ >= 3) //hash_map is not part of the C++ standard anymore; hash_map.h has been kept though for backward compatibility -# include <hash_map.h> -#else -# include <hash_map> -#endif +# include <hash_map.h> +# else +# include <hash_map> +# endif #endif #include "Interface1D.h" @@ -42,7 +42,7 @@ #include "../system/FreestyleConfig.h" #ifdef WITH_CXX_GUARDEDALLOC -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif using namespace std; @@ -54,117 +54,112 @@ using namespace Geometry; class SVertex; /*! Defines a hash table used for searching the SVertex */ -struct SVertexHasher -{ +struct SVertexHasher { #define _MUL 950706376UL #define _MOD 2147483647UL - inline size_t operator()(const Vec3r& p) const - { - size_t res = ((unsigned long)(p[0] * _MUL)) % _MOD; - res = ((res + (unsigned long)(p[1]) * _MUL)) % _MOD; - return ((res +(unsigned long)(p[2]) * _MUL)) % _MOD; - } + inline size_t operator()(const Vec3r &p) const + { + size_t res = ((unsigned long)(p[0] * _MUL)) % _MOD; + res = ((res + (unsigned long)(p[1]) * _MUL)) % _MOD; + return ((res + (unsigned long)(p[2]) * _MUL)) % _MOD; + } #undef _MUL #undef _MOD }; // Key_compare predicate for hash_map. In particular, return false if equal. -struct epsilonEquals -{ - bool operator()(const Vec3r& v1, const Vec3r& v2) const - { - real norm = (v1 - v2).norm(); - return (norm < 1.0e-06); - } +struct epsilonEquals { + bool operator()(const Vec3r &v1, const Vec3r &v2) const + { + real norm = (v1 - v2).norm(); + return (norm < 1.0e-06); + } }; - // typedef hash_map<Vec3r, SVertex*, SVertexHasher, epsilonEquals> SVertexMap; typedef map<Vec3r, SVertex *> SVertexMap; class WXFaceLayer; /*! class to describe an oriented smooth edge */ -class OWXFaceLayer -{ -public: - WXFaceLayer *fl; - bool order; - - OWXFaceLayer() - { - fl = NULL; - order = true; - } - - OWXFaceLayer(WXFaceLayer *ifl, bool iOrder = true) - { - fl = ifl; - order = iOrder; - } - - OWXFaceLayer& operator=(const OWXFaceLayer& iBrother) - { - fl = iBrother.fl; - order = iBrother.order; - return *this; - } - - bool operator==(const OWXFaceLayer& b) - { - return ((fl == b.fl) && (order == b.order)); - } - - bool operator!=(const OWXFaceLayer& b) - { - return !(*this == b); - } +class OWXFaceLayer { + public: + WXFaceLayer *fl; + bool order; + + OWXFaceLayer() + { + fl = NULL; + order = true; + } + + OWXFaceLayer(WXFaceLayer *ifl, bool iOrder = true) + { + fl = ifl; + order = iOrder; + } + + OWXFaceLayer &operator=(const OWXFaceLayer &iBrother) + { + fl = iBrother.fl; + order = iBrother.order; + return *this; + } + + bool operator==(const OWXFaceLayer &b) + { + return ((fl == b.fl) && (order == b.order)); + } + + bool operator!=(const OWXFaceLayer &b) + { + return !(*this == b); + } #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:OWXFaceLayer") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:OWXFaceLayer") #endif }; class WXEdge; /*! class to describe an oriented sharp edge */ -class OWXEdge -{ -public: - WXEdge *e; - bool order; - - OWXEdge() - { - e = NULL; - order = true; - } - - OWXEdge(WXEdge *ie, bool iOrder = true) - { - e = ie; - order = iOrder; - } - - OWXEdge& operator=(const OWXEdge& iBrother) - { - e = iBrother.e; - order = iBrother.order; - return *this; - } - - bool operator==(const OWXEdge& b) - { - return ((e == b.e) && (order == b.order)); - } - - bool operator!=(const OWXEdge& b) - { - return !(*this == b); - } +class OWXEdge { + public: + WXEdge *e; + bool order; + + OWXEdge() + { + e = NULL; + order = true; + } + + OWXEdge(WXEdge *ie, bool iOrder = true) + { + e = ie; + order = iOrder; + } + + OWXEdge &operator=(const OWXEdge &iBrother) + { + e = iBrother.e; + order = iBrother.order; + return *this; + } + + bool operator==(const OWXEdge &b) + { + return ((e == b.e) && (order == b.order)); + } + + bool operator!=(const OWXEdge &b) + { + return !(*this == b); + } #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:OWXEdge") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:OWXEdge") #endif }; @@ -177,117 +172,121 @@ class ViewVertex; class ViewEdge; class ViewShape; -class ViewEdgeXBuilder -{ -protected: - int _currentViewId; // Id for view edges - int _currentFId; // Id for FEdges - int _currentSVertexId; // Id for SVertex - -public: - inline ViewEdgeXBuilder() - { - _currentViewId = 1; - _currentFId = 0; - _currentSVertexId = 0; - } - - virtual ~ViewEdgeXBuilder() {} - - /*! Builds a view shape from a WXShape in which the feature edges are flagged - * Builds chains of feature edges (so ViewEdges) from a WXShape - * iWShape - * The Winged Edge structure in which all silhouette edges and vertices are flagged. - * oViewShape - * The Silhouette Shape in which the chains must be added. - * ioVEdges - * The list of new ViewEdges. - * ioVVertices - * THe new ViewVertices - * ioFEdges - * A list in which all new FEdges are added - * ioSVertices - * A list of SVertex where all created SVertex are added. - */ - virtual void BuildViewEdges(WXShape *iWShape, ViewShape *oVShape, std::vector<ViewEdge*>& ioVEdges, - std::vector<ViewVertex*>& ioVVertices, std::vector<FEdge*>& ioFEdges, - std::vector<SVertex*>& ioSVertices); - - /*! Builds a smooth view edge, starting the face iFace. */ - ViewEdge *BuildSmoothViewEdge(const OWXFaceLayer& iFaceLayer); - - /*! Makes a sharp viewedge */ - ViewEdge *BuildSharpViewEdge(const OWXEdge& iWEdge); - -public: - /*! accessors */ - inline int currentViewId() const - { - return _currentViewId; - } - - inline int currentFId() const - { - return _currentFId; - } - - inline int currentSVertexId() const - { - return _currentSVertexId; - } - - /*! modifiers */ - inline void setCurrentViewId(int id) - { - _currentViewId = id; - } - - inline void setCurrentFId(int id) - { - _currentFId = id; - } - - inline void setCurrentSVertexId(int id) - { - _currentSVertexId = id; - } - -protected: - /*! Init the view edges building */ - virtual void Init(ViewShape *oVShape); - - // SMOOTH // - /*! checks whether a face has already been processed or not */ - bool stopSmoothViewEdge(WXFaceLayer *iFaceLayer); - OWXFaceLayer FindNextFaceLayer(const OWXFaceLayer& iFaceLayer); - OWXFaceLayer FindPreviousFaceLayer(const OWXFaceLayer& iFaceLayer); - FEdge *BuildSmoothFEdge(FEdge *feprevious, const OWXFaceLayer& ifl); - - // SHARP // - /*! checks whether a WEdge has already been processed or not */ - bool stopSharpViewEdge(WXEdge *iFace); - int retrieveFaceMarks(WXEdge *iEdge); - OWXEdge FindNextWEdge(const OWXEdge& iEdge); - OWXEdge FindPreviousWEdge(const OWXEdge& iEdge); - FEdge *BuildSharpFEdge(FEdge *feprevious, const OWXEdge& iwe); - - // GENERAL // - /*! Instanciate a SVertex */ - SVertex *MakeSVertex(Vec3r& iPoint); - /*! Instanciate a SVertex if it hasn't been already created */ - SVertex *MakeSVertex(Vec3r& iPoint, bool shared); - /*! instanciate a ViewVertex from a SVertex, if it doesn't exist yet */ - ViewVertex *MakeViewVertex(SVertex *iSVertex); - - //oldtmp values - //IdHashTable _hashtable; - //VVIdHashTable _multivertexHashTable; - SVertexMap _SVertexMap; - SShape *_pCurrentSShape; - ViewShape *_pCurrentVShape; +class ViewEdgeXBuilder { + protected: + int _currentViewId; // Id for view edges + int _currentFId; // Id for FEdges + int _currentSVertexId; // Id for SVertex + + public: + inline ViewEdgeXBuilder() + { + _currentViewId = 1; + _currentFId = 0; + _currentSVertexId = 0; + } + + virtual ~ViewEdgeXBuilder() + { + } + + /*! Builds a view shape from a WXShape in which the feature edges are flagged + * Builds chains of feature edges (so ViewEdges) from a WXShape + * iWShape + * The Winged Edge structure in which all silhouette edges and vertices are flagged. + * oViewShape + * The Silhouette Shape in which the chains must be added. + * ioVEdges + * The list of new ViewEdges. + * ioVVertices + * THe new ViewVertices + * ioFEdges + * A list in which all new FEdges are added + * ioSVertices + * A list of SVertex where all created SVertex are added. + */ + virtual void BuildViewEdges(WXShape *iWShape, + ViewShape *oVShape, + std::vector<ViewEdge *> &ioVEdges, + std::vector<ViewVertex *> &ioVVertices, + std::vector<FEdge *> &ioFEdges, + std::vector<SVertex *> &ioSVertices); + + /*! Builds a smooth view edge, starting the face iFace. */ + ViewEdge *BuildSmoothViewEdge(const OWXFaceLayer &iFaceLayer); + + /*! Makes a sharp viewedge */ + ViewEdge *BuildSharpViewEdge(const OWXEdge &iWEdge); + + public: + /*! accessors */ + inline int currentViewId() const + { + return _currentViewId; + } + + inline int currentFId() const + { + return _currentFId; + } + + inline int currentSVertexId() const + { + return _currentSVertexId; + } + + /*! modifiers */ + inline void setCurrentViewId(int id) + { + _currentViewId = id; + } + + inline void setCurrentFId(int id) + { + _currentFId = id; + } + + inline void setCurrentSVertexId(int id) + { + _currentSVertexId = id; + } + + protected: + /*! Init the view edges building */ + virtual void Init(ViewShape *oVShape); + + // SMOOTH // + /*! checks whether a face has already been processed or not */ + bool stopSmoothViewEdge(WXFaceLayer *iFaceLayer); + OWXFaceLayer FindNextFaceLayer(const OWXFaceLayer &iFaceLayer); + OWXFaceLayer FindPreviousFaceLayer(const OWXFaceLayer &iFaceLayer); + FEdge *BuildSmoothFEdge(FEdge *feprevious, const OWXFaceLayer &ifl); + + // SHARP // + /*! checks whether a WEdge has already been processed or not */ + bool stopSharpViewEdge(WXEdge *iFace); + int retrieveFaceMarks(WXEdge *iEdge); + OWXEdge FindNextWEdge(const OWXEdge &iEdge); + OWXEdge FindPreviousWEdge(const OWXEdge &iEdge); + FEdge *BuildSharpFEdge(FEdge *feprevious, const OWXEdge &iwe); + + // GENERAL // + /*! Instanciate a SVertex */ + SVertex *MakeSVertex(Vec3r &iPoint); + /*! Instanciate a SVertex if it hasn't been already created */ + SVertex *MakeSVertex(Vec3r &iPoint, bool shared); + /*! instanciate a ViewVertex from a SVertex, if it doesn't exist yet */ + ViewVertex *MakeViewVertex(SVertex *iSVertex); + + //oldtmp values + //IdHashTable _hashtable; + //VVIdHashTable _multivertexHashTable; + SVertexMap _SVertexMap; + SShape *_pCurrentSShape; + ViewShape *_pCurrentVShape; #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:ViewEdgeXBuilder") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:ViewEdgeXBuilder") #endif }; diff --git a/source/blender/freestyle/intern/view_map/ViewMap.cpp b/source/blender/freestyle/intern/view_map/ViewMap.cpp index d23a87d7159..7c72e44fc10 100644 --- a/source/blender/freestyle/intern/view_map/ViewMap.cpp +++ b/source/blender/freestyle/intern/view_map/ViewMap.cpp @@ -41,230 +41,243 @@ ViewMap *ViewMap::_pInstance = NULL; 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(); + // 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(); + for (vector<ViewShape *>::iterator vs = _VShapes.begin(), vsend = _VShapes.end(); vs != vsend; + vs++) { + delete (*vs); + } + _VShapes.clear(); - _FEdges.clear(); - _SVertices.clear(); - _VEdges.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); - } + 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(unsigned id) { - int index = _shapeIdToIndex[id]; - return _VShapes[ index ]; + int index = _shapeIdToIndex[id]; + return _VShapes[index]; } void ViewMap::AddViewShape(ViewShape *iVShape) { - _shapeIdToIndex[iVShape->getId().getFirst()] = _VShapes.size(); - _VShapes.push_back(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 = NULL; - 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); - } - } + // find the closest of this candidates: + real minDist = DBL_MAX; + FEdge *winner = NULL; + 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; + return winner; } const ViewEdge *ViewMap::getClosestViewEdge(real x, real y) const { - // find the closest of this candidates: - real minDist = DBL_MAX; - FEdge *winner = NULL; - 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 NULL; - - 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 NULL; - } - FEdge *fend(NULL), *fbegin(NULL); - 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 != NULL) && (fend != NULL)) - 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() == 0) { - // 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(NULL); - fbegin->setPreviousEdge(NULL); - - // 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(NULL); - fbegin->setPreviousEdge(NULL); - - // 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; + // find the closest of this candidates: + real minDist = DBL_MAX; + FEdge *winner = NULL; + 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 NULL; + + 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 NULL; + } + FEdge *fend(NULL), *fbegin(NULL); + 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 != NULL) && (fend != NULL)) + 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() == 0) { + // 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(NULL); + fbegin->setPreviousEdge(NULL); + + // 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(NULL); + fbegin->setPreviousEdge(NULL); + + // 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; + SShape *sshape = ioEdge->shape(); + FEdge *newFEdge = sshape->SplitEdgeIn2(ioEdge, ioVertex); + AddFEdge(newFEdge); + InsertViewVertex(ioVertex, oNewVEdges); + return newFEdge; } #endif @@ -277,219 +290,231 @@ FEdge *ViewMap::Connect(FEdge *ioEdge, SVertex *ioVertex, vector<ViewEdge*>& oNe /**********************************/ // 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; - else - return (v1.x() > v2.x()); - } - else { - if (v2.y() > 0) - return false; - else - return (v1.x() < v2.x()); - } - return false; +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; + else + return (v1.x() > v2.x()); + } + else { + if (v2.y() > 0) + return false; + else + return (v1.x() < v2.x()); + } + return false; } 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); - _sortedEdges.insert( dve, &_FrontEdgeA); - } - else { - _sortedEdges.push_back(&_FrontEdgeA); - } + 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) + ; + _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); - _sortedEdges.insert(dve, &_FrontEdgeB); - } - else { - _sortedEdges.push_back(&_FrontEdgeB); - } + 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) + ; + _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); - _sortedEdges.insert(dve, &_BackEdgeA); - } - else { - _sortedEdges.push_back(&_BackEdgeA); - } + 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) + ; + _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); - _sortedEdges.insert(dve, &_BackEdgeB); - } - else { - _sortedEdges.push_back(&_BackEdgeB); - } + 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) + ; + _sortedEdges.insert(dve, &_BackEdgeB); + } + else { + _sortedEdges.push_back(&_BackEdgeB); + } } void TVertex::Replace(ViewEdge *iOld, ViewEdge *iNew) { - // theoritically, 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; - } + // theoritically, 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()); + //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()); + //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()); + //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()); + //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()); + 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); + 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()); + 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); + 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()); + return ViewVertexInternal::orientedViewEdgeIterator( + _sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin()); } ViewVertexInternal::orientedViewEdgeIterator TVertex::edgesEnd() { - return ViewVertexInternal::orientedViewEdgeIterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.end()); + 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()); + 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()); } /**********************************/ @@ -502,88 +527,98 @@ ViewVertexInternal::orientedViewEdgeIterator TVertex::edgesIterator(ViewEdge *iE 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); - _ViewEdges.insert(dve, idve); - } - else { - _ViewEdges.push_back(idve); - } + // 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) + ; + _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); - _ViewEdges.insert(dve, idve); - } - else { - _ViewEdges.push_back(idve); - } + // 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) + ; + _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()); + 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()); + 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()); + 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()); + 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()); + 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()); + 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()); + return ViewVertexInternal::orientedViewEdgeIterator( + _ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin()); } ViewVertexInternal::orientedViewEdgeIterator NonTVertex::edgesEnd() { - return ViewVertexInternal::orientedViewEdgeIterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.end()); + 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()); + 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()); } /**********************************/ @@ -596,160 +631,161 @@ ViewVertexInternal::orientedViewEdgeIterator NonTVertex::edgesIterator(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; + 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); + return edge_iterator(this); } ViewEdge::const_edge_iterator ViewEdge::ViewEdge_iterator() const { - return const_edge_iterator((ViewEdge *)this); + return const_edge_iterator((ViewEdge *)this); } //! feature edge iterator ViewEdge::fedge_iterator ViewEdge::fedge_iterator_begin() { - return fedge_iterator(this->_FEdgeA, this->_FEdgeB); + return fedge_iterator(this->_FEdgeA, this->_FEdgeB); } ViewEdge::const_fedge_iterator ViewEdge::fedge_iterator_begin() const { - return const_fedge_iterator(this->_FEdgeA, this->_FEdgeB); + return const_fedge_iterator(this->_FEdgeA, this->_FEdgeB); } ViewEdge::fedge_iterator ViewEdge::fedge_iterator_last() { - return fedge_iterator(this->_FEdgeB, this->_FEdgeB); + return fedge_iterator(this->_FEdgeB, this->_FEdgeB); } ViewEdge::const_fedge_iterator ViewEdge::fedge_iterator_last() const { - return const_fedge_iterator(this->_FEdgeB, this->_FEdgeB); + return const_fedge_iterator(this->_FEdgeB, this->_FEdgeB); } ViewEdge::fedge_iterator ViewEdge::fedge_iterator_end() { - return fedge_iterator(0, this->_FEdgeB); + return fedge_iterator(0, this->_FEdgeB); } ViewEdge::const_fedge_iterator ViewEdge::fedge_iterator_end() const { - return const_fedge_iterator(0, this->_FEdgeB); + return const_fedge_iterator(0, this->_FEdgeB); } //! embedding vertex iterator ViewEdge::const_vertex_iterator ViewEdge::vertices_begin() const { - return const_vertex_iterator(this->_FEdgeA->vertexA(), 0, _FEdgeA); + return const_vertex_iterator(this->_FEdgeA->vertexA(), 0, _FEdgeA); } ViewEdge::vertex_iterator ViewEdge::vertices_begin() { - return vertex_iterator(this->_FEdgeA->vertexA(), 0, _FEdgeA); + return vertex_iterator(this->_FEdgeA->vertexA(), 0, _FEdgeA); } ViewEdge::const_vertex_iterator ViewEdge::vertices_last() const { - return const_vertex_iterator(this->_FEdgeB->vertexB(), _FEdgeB, 0); + return const_vertex_iterator(this->_FEdgeB->vertexB(), _FEdgeB, 0); } ViewEdge::vertex_iterator ViewEdge::vertices_last() { - return vertex_iterator(this->_FEdgeB->vertexB(), _FEdgeB, 0); + return vertex_iterator(this->_FEdgeB->vertexB(), _FEdgeB, 0); } ViewEdge::const_vertex_iterator ViewEdge::vertices_end() const { - return const_vertex_iterator(0, _FEdgeB, 0); + return const_vertex_iterator(0, _FEdgeB, 0); } ViewEdge::vertex_iterator ViewEdge::vertices_end() { - return vertex_iterator(0, _FEdgeB, 0); + return vertex_iterator(0, _FEdgeB, 0); } Interface0DIterator ViewEdge::verticesBegin() { - Interface0DIterator ret(new ViewEdgeInternal::SVertexIterator(this->_FEdgeA->vertexA(), - this->_FEdgeA->vertexA(), NULL, _FEdgeA, 0.0f)); - return ret; + Interface0DIterator ret(new ViewEdgeInternal::SVertexIterator( + this->_FEdgeA->vertexA(), this->_FEdgeA->vertexA(), NULL, _FEdgeA, 0.0f)); + return ret; } Interface0DIterator ViewEdge::verticesEnd() { - Interface0DIterator ret(new ViewEdgeInternal::SVertexIterator(NULL, this->_FEdgeA->vertexA(), - _FEdgeB, NULL, getLength2D())); - return ret; + Interface0DIterator ret(new ViewEdgeInternal::SVertexIterator( + NULL, this->_FEdgeA->vertexA(), _FEdgeB, NULL, getLength2D())); + return ret; } Interface0DIterator ViewEdge::pointsBegin(float /*t*/) { - return verticesBegin(); + return verticesBegin(); } Interface0DIterator ViewEdge::pointsEnd(float /*t*/) { - return verticesEnd(); + return verticesEnd(); } - /**********************************/ - /* */ - /* */ - /* ViewShape */ - /* */ - /* */ - /**********************************/ +/**********************************/ +/* */ +/* */ +/* ViewShape */ +/* */ +/* */ +/**********************************/ ViewShape::~ViewShape() { - _Vertices.clear(); + _Vertices.clear(); - if (!(_Edges.empty())) { - for (vector<ViewEdge*>::iterator e = _Edges.begin(), eend = _Edges.end(); e != eend; e++) { - delete (*e); - } - _Edges.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 = NULL; - } + if (_SShape) { + delete _SShape; + _SShape = NULL; + } } 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; - } - } + 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; - } - } + for (vector<ViewVertex *>::iterator vv = _Vertices.begin(), vvend = _Vertices.end(); vv != vvend; + vv++) { + if (iViewVertex == (*vv)) { + _Vertices.erase(vv); + break; + } + } } /**********************************/ @@ -762,13 +798,13 @@ void ViewShape::RemoveVertex(ViewVertex *iViewVertex) void ViewEdge::UpdateFEdges() { - FEdge *currentEdge = _FEdgeA; - do { - currentEdge->setViewEdge(this); - currentEdge = currentEdge->nextEdge(); - } while ((currentEdge != NULL) && (currentEdge != _FEdgeB)); - // last one - _FEdgeB->setViewEdge(this); + FEdge *currentEdge = _FEdgeA; + do { + currentEdge->setViewEdge(this); + currentEdge = currentEdge->nextEdge(); + } while ((currentEdge != NULL) && (currentEdge != _FEdgeB)); + // last one + _FEdgeB->setViewEdge(this); } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/view_map/ViewMap.h b/source/blender/freestyle/intern/view_map/ViewMap.h index 4f0f50fbee2..b25e13d990f 100644 --- a/source/blender/freestyle/intern/view_map/ViewMap.h +++ b/source/blender/freestyle/intern/view_map/ViewMap.h @@ -26,7 +26,7 @@ #include "Interface0D.h" #include "Interface1D.h" -#include "Silhouette.h" // defines the embedding +#include "Silhouette.h" // defines the embedding #include "../geometry/GeomUtils.h" @@ -34,7 +34,7 @@ #include "../system/FreestyleConfig.h" #ifdef WITH_CXX_GUARDEDALLOC -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif namespace Freestyle { @@ -47,7 +47,6 @@ namespace Freestyle { /* */ /**********************************/ - /* Density * Mean area depth value * distance to a point @@ -59,182 +58,186 @@ 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(); +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") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:ViewMap") #endif }; @@ -256,7 +259,7 @@ class edge_nonconst_traits; template<class Traits> class edge_iterator_base; class orientedViewEdgeIterator; -} // end of namespace ViewEdgeInternal +} // namespace ViewVertexInternal /*! 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 @@ -265,106 +268,111 @@ class orientedViewEdgeIterator; * 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; +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") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:ViewVertex") #endif }; @@ -382,265 +390,264 @@ public: * 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); +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") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:TVertex") #endif }; - /**********************************/ /* */ /* */ @@ -649,210 +656,212 @@ public: /* */ /**********************************/ - // (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); +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") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:NonTVertex") #endif }; @@ -880,502 +889,499 @@ 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 +} // 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() - { +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; - } + 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 */ + // 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(); - } + inline Nature::EdgeNature viewedge_nature() const + { + return getNature(); + } - float viewedge_length() const; + float viewedge_length() const; #endif - /*! Returns the 2D length of the Viewedge. */ - real getLength2D() const; + /*! Returns the 2D length of the Viewedge. */ + real getLength2D() const; #if 0 - inline Material material() const - { - return _FEdgeA->vertexA()->shape()->material(); - } + 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); + 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") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:ViewEdge") #endif }; - /**********************************/ /* */ /* */ @@ -1385,239 +1391,235 @@ public: /**********************************/ /*! 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 name. */ - inline const string& getName() const - { - return _SShape->getName(); - } - - /*! Returns the ViewShape library path. */ - inline const string& getLibraryPath() const - { - return _SShape->getLibraryPath(); - } - - /* 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); +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 name. */ + inline const string &getName() const + { + return _SShape->getName(); + } + + /*! Returns the ViewShape library path. */ + inline const string &getLibraryPath() const + { + return _SShape->getLibraryPath(); + } + + /* 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") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:ViewShape") #endif }; - /* * ############################################# * ############################################# @@ -1631,116 +1633,118 @@ public: */ /* for inline functions */ -void ViewShape::SplitEdge(FEdge *fe, const vector<TVertex*>& iViewVertices, vector<FEdge*>& ioNewEdges, - vector<ViewEdge*>& ioNewViewEdges) +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); + 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); + 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); - } - } + 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); + } + } } /**********************************/ @@ -1754,54 +1758,54 @@ void ViewShape::SplitEdge(FEdge *fe, const vector<TVertex*>& iViewVertices, vect #if 0 inline Vec3r ViewEdge::orientation2d(int iCombination) const { - return edge_orientation2d_function<ViewEdge>(*this, iCombination); + return edge_orientation2d_function<ViewEdge>(*this, iCombination); } inline Vec3r ViewEdge::orientation3d(int iCombination) const { - return edge_orientation3d_function<ViewEdge>(*this, iCombination); + return edge_orientation3d_function<ViewEdge>(*this, iCombination); } inline real ViewEdge::z_discontinuity(int iCombination) const { - return z_discontinuity_edge_function<ViewEdge>(*this, iCombination); + 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); + 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); + 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); + 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 == _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); + 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); + return curvature2d_as_angle_edge_function<ViewEdge>(*this, iCombination); } #endif } /* namespace Freestyle */ -#endif // __FREESTYLE_VIEW_MAP_H__ +#endif // __FREESTYLE_VIEW_MAP_H__ diff --git a/source/blender/freestyle/intern/view_map/ViewMapAdvancedIterators.h b/source/blender/freestyle/intern/view_map/ViewMapAdvancedIterators.h index 1b4a98498dd..2c09bde487b 100644 --- a/source/blender/freestyle/intern/view_map/ViewMapAdvancedIterators.h +++ b/source/blender/freestyle/intern/view_map/ViewMapAdvancedIterators.h @@ -25,7 +25,7 @@ #include "ViewMap.h" -#include "../system/Iterator.h" //soc +#include "../system/Iterator.h" //soc namespace Freestyle { @@ -47,290 +47,295 @@ namespace Freestyle { namespace ViewVertexInternal { -class edge_const_traits : public Const_traits<ViewVertex::directedViewEdge> -{ -public: - typedef vector<ViewVertex::directedViewEdge> edges_container; - typedef edges_container::const_iterator edges_container_iterator; - typedef vector<ViewVertex::directedViewEdge*> edge_pointers_container; - typedef edge_pointers_container::const_iterator edge_pointers_container_iterator; +class edge_const_traits : public Const_traits<ViewVertex::directedViewEdge> { + public: + typedef vector<ViewVertex::directedViewEdge> edges_container; + typedef edges_container::const_iterator edges_container_iterator; + typedef vector<ViewVertex::directedViewEdge *> edge_pointers_container; + typedef edge_pointers_container::const_iterator edge_pointers_container_iterator; }; -class edge_nonconst_traits : public Nonconst_traits<ViewVertex::directedViewEdge> -{ -public: - typedef vector<ViewVertex::directedViewEdge> edges_container; - typedef edges_container::iterator edges_container_iterator; - typedef vector<ViewVertex::directedViewEdge*> edge_pointers_container; - typedef edge_pointers_container::iterator edge_pointers_container_iterator; +class edge_nonconst_traits : public Nonconst_traits<ViewVertex::directedViewEdge> { + public: + typedef vector<ViewVertex::directedViewEdge> edges_container; + typedef edges_container::iterator edges_container_iterator; + typedef vector<ViewVertex::directedViewEdge *> edge_pointers_container; + typedef edge_pointers_container::iterator edge_pointers_container_iterator; }; template<class Traits> -class edge_iterator_base : public IteratorBase<Traits, InputIteratorTag_Traits> -{ -public: - typedef typename Traits::value_type value_type; - typedef typename Traits::difference_type difference_type; - typedef typename Traits::pointer pointer; - typedef typename Traits::reference reference; - typedef edge_iterator_base<Traits> Self; - typedef typename Traits::edges_container_iterator edges_container_iterator; - typedef typename Traits::edge_pointers_container_iterator edge_pointers_container_iterator; - typedef edge_iterator_base<edge_nonconst_traits> iterator; - typedef edge_iterator_base<edge_const_traits> const_iterator; - -public: - friend class ViewVertex; - friend class TVertex; - friend class NonTVertex; - friend class ViewEdge; - friend class edge_iterator; - -protected: - Nature::VertexNature _Nature; // the nature of the underlying vertex - // T vertex attributes - edge_pointers_container_iterator _tbegin; - edge_pointers_container_iterator _tend; - edge_pointers_container_iterator _tvertex_iter; +class edge_iterator_base : public IteratorBase<Traits, InputIteratorTag_Traits> { + public: + typedef typename Traits::value_type value_type; + typedef typename Traits::difference_type difference_type; + typedef typename Traits::pointer pointer; + typedef typename Traits::reference reference; + typedef edge_iterator_base<Traits> Self; + typedef typename Traits::edges_container_iterator edges_container_iterator; + typedef typename Traits::edge_pointers_container_iterator edge_pointers_container_iterator; + typedef edge_iterator_base<edge_nonconst_traits> iterator; + typedef edge_iterator_base<edge_const_traits> const_iterator; + + public: + friend class ViewVertex; + friend class TVertex; + friend class NonTVertex; + friend class ViewEdge; + friend class edge_iterator; + + protected: + Nature::VertexNature _Nature; // the nature of the underlying vertex + // T vertex attributes + edge_pointers_container_iterator _tbegin; + edge_pointers_container_iterator _tend; + edge_pointers_container_iterator _tvertex_iter; #if 0 - mutable value_type _tvertex_iter; - value_type _feA; - value_type _feB; - value_type _beA; - value_type _beB; + mutable value_type _tvertex_iter; + value_type _feA; + value_type _feB; + value_type _beA; + value_type _beB; #endif - // Non TVertex attributes - edges_container_iterator _begin; - edges_container_iterator _end; - edges_container_iterator _nontvertex_iter; + // Non TVertex attributes + edges_container_iterator _begin; + edges_container_iterator _end; + edges_container_iterator _nontvertex_iter; - typedef IteratorBase<Traits, InputIteratorTag_Traits> parent_class; + typedef IteratorBase<Traits, InputIteratorTag_Traits> parent_class; -public: - inline edge_iterator_base() : parent_class() {} + public: + inline edge_iterator_base() : parent_class() + { + } - inline edge_iterator_base(Nature::VertexNature iNature) : parent_class() - { - _Nature = iNature; - } + inline edge_iterator_base(Nature::VertexNature iNature) : parent_class() + { + _Nature = iNature; + } - edge_iterator_base(const edge_iterator_base<edge_nonconst_traits>& iBrother) : parent_class(iBrother) - { - _Nature = iBrother._Nature; - if (_Nature & Nature::T_VERTEX) { + edge_iterator_base(const edge_iterator_base<edge_nonconst_traits> &iBrother) + : parent_class(iBrother) + { + _Nature = iBrother._Nature; + if (_Nature & Nature::T_VERTEX) { #if 0 - _feA = iBrother._feA; - _feB = iBrother._feB; - _beA = iBrother._beA; - _beB = iBrother._beB; - _tvertex_iter = iBrother._tvertex_iter; + _feA = iBrother._feA; + _feB = iBrother._feB; + _beA = iBrother._beA; + _beB = iBrother._beB; + _tvertex_iter = iBrother._tvertex_iter; #endif - _tbegin = iBrother._tbegin; - _tend = iBrother._tend; - _tvertex_iter = iBrother._tvertex_iter; - } - else { - _begin = iBrother._begin; - _end = iBrother._end; - _nontvertex_iter = iBrother._nontvertex_iter; - } - } - - edge_iterator_base(const edge_iterator_base<edge_const_traits>& iBrother) : parent_class(iBrother) - { - _Nature = iBrother._Nature; - if (_Nature & Nature::T_VERTEX) { + _tbegin = iBrother._tbegin; + _tend = iBrother._tend; + _tvertex_iter = iBrother._tvertex_iter; + } + else { + _begin = iBrother._begin; + _end = iBrother._end; + _nontvertex_iter = iBrother._nontvertex_iter; + } + } + + edge_iterator_base(const edge_iterator_base<edge_const_traits> &iBrother) + : parent_class(iBrother) + { + _Nature = iBrother._Nature; + if (_Nature & Nature::T_VERTEX) { #if 0 - _feA = iBrother._feA; - _feB = iBrother._feB; - _beA = iBrother._beA; - _beB = iBrother._beB; - _tvertex_iter = iBrother._tvertex_iter; + _feA = iBrother._feA; + _feB = iBrother._feB; + _beA = iBrother._beA; + _beB = iBrother._beB; + _tvertex_iter = iBrother._tvertex_iter; #endif - _tbegin = iBrother._tbegin; - _tend = iBrother._tend; - _tvertex_iter = iBrother._tvertex_iter; - } - else { - _begin = iBrother._begin; - _end = iBrother._end; - _nontvertex_iter = iBrother._nontvertex_iter; - } - } - - virtual ~edge_iterator_base() {} - -//protected://FIXME -public: + _tbegin = iBrother._tbegin; + _tend = iBrother._tend; + _tvertex_iter = iBrother._tvertex_iter; + } + else { + _begin = iBrother._begin; + _end = iBrother._end; + _nontvertex_iter = iBrother._nontvertex_iter; + } + } + + virtual ~edge_iterator_base() + { + } + + //protected://FIXME + public: #if 0 - inline edge_iterator_base(value_type ifeA, value_type ifeB, value_type ibeA, value_type ibeB, value_type iter) - : parent_class() - { - _Nature = Nature::T_VERTEX; - _feA = ifeA; - _feB = ifeB; - _beA = ibeA; - _beB = ibeB; - _tvertex_iter = iter; - } + inline edge_iterator_base(value_type ifeA, value_type ifeB, value_type ibeA, value_type ibeB, value_type iter) + : parent_class() + { + _Nature = Nature::T_VERTEX; + _feA = ifeA; + _feB = ifeB; + _beA = ibeA; + _beB = ibeB; + _tvertex_iter = iter; + } #endif - inline edge_iterator_base(edge_pointers_container_iterator begin, edge_pointers_container_iterator end, - edge_pointers_container_iterator iter) - : parent_class() - { - _Nature = Nature::T_VERTEX; - _tbegin = begin; - _tend = end; - _tvertex_iter = iter; - } - - inline edge_iterator_base(edges_container_iterator begin, edges_container_iterator end, - edges_container_iterator iter) - : parent_class() - { - _Nature = Nature::NON_T_VERTEX; - _begin = begin; - _end = end; - _nontvertex_iter = iter; - } - -public: - virtual bool begin() const - { - if (_Nature & Nature::T_VERTEX) - return (_tvertex_iter == _tbegin); - //return (_tvertex_iter == _feA); - else - return (_nontvertex_iter == _begin); - } - - virtual bool end() const - { - if (_Nature & Nature::T_VERTEX) - //return (_tvertex_iter.first == 0); - return (_tvertex_iter == _tend); - else - return (_nontvertex_iter == _end); - } - - // operators - // operator corresponding to ++i - virtual Self& operator++() - { - increment(); - return *this; - } - - // operator corresponding to i++, i.e. which returns the value *and then* increments it. - // That's why we store the value in a temp. - virtual Self operator++(int) - { - Self tmp = *this; - increment(); - return tmp; - } - - // comparibility - virtual bool operator!=(const Self& b) const - { - if (_Nature & Nature::T_VERTEX) - return (_tvertex_iter != b._tvertex_iter); - else - return (_nontvertex_iter != b._nontvertex_iter); - } - - virtual bool operator==(const Self& b) const - { - return !(*this != b); - } - - // dereferencing - virtual reference operator*() const - { - if (_Nature & Nature::T_VERTEX) - //return _tvertex_iter; - return **_tvertex_iter; - else - return (*_nontvertex_iter); - } - - virtual pointer operator->() const - { - return &(operator*()); - } - -protected: - inline void increment() - { - if (_Nature & Nature::T_VERTEX) { - value_type tmp = (**_tvertex_iter); - ++_tvertex_iter; - value_type tmp2 = (**_tvertex_iter); - if (tmp2.first == tmp.first) - ++_tvertex_iter; + inline edge_iterator_base(edge_pointers_container_iterator begin, + edge_pointers_container_iterator end, + edge_pointers_container_iterator iter) + : parent_class() + { + _Nature = Nature::T_VERTEX; + _tbegin = begin; + _tend = end; + _tvertex_iter = iter; + } + + inline edge_iterator_base(edges_container_iterator begin, + edges_container_iterator end, + edges_container_iterator iter) + : parent_class() + { + _Nature = Nature::NON_T_VERTEX; + _begin = begin; + _end = end; + _nontvertex_iter = iter; + } + + public: + virtual bool begin() const + { + if (_Nature & Nature::T_VERTEX) + return (_tvertex_iter == _tbegin); + //return (_tvertex_iter == _feA); + else + return (_nontvertex_iter == _begin); + } + + virtual bool end() const + { + if (_Nature & Nature::T_VERTEX) + //return (_tvertex_iter.first == 0); + return (_tvertex_iter == _tend); + else + return (_nontvertex_iter == _end); + } + + // operators + // operator corresponding to ++i + virtual Self &operator++() + { + increment(); + return *this; + } + + // operator corresponding to i++, i.e. which returns the value *and then* increments it. + // That's why we store the value in a temp. + virtual Self operator++(int) + { + Self tmp = *this; + increment(); + return tmp; + } + + // comparibility + virtual bool operator!=(const Self &b) const + { + if (_Nature & Nature::T_VERTEX) + return (_tvertex_iter != b._tvertex_iter); + else + return (_nontvertex_iter != b._nontvertex_iter); + } + + virtual bool operator==(const Self &b) const + { + return !(*this != b); + } + + // dereferencing + virtual reference operator*() const + { + if (_Nature & Nature::T_VERTEX) + //return _tvertex_iter; + return **_tvertex_iter; + else + return (*_nontvertex_iter); + } + + virtual pointer operator->() const + { + return &(operator*()); + } + + protected: + inline void increment() + { + if (_Nature & Nature::T_VERTEX) { + value_type tmp = (**_tvertex_iter); + ++_tvertex_iter; + value_type tmp2 = (**_tvertex_iter); + if (tmp2.first == tmp.first) + ++_tvertex_iter; #if 0 - // Hack to deal with cusp. the result of a cusp is a TVertex having two identical viewedges. - // In order to iterate properly, we chose to skip these last ones. - if (_feB.first == _beA.first) { - if (_feA.first == _beB.first) { - _tvertex_iter.first = 0; - return; - } - - if (_tvertex_iter.first == _feA.first) - _tvertex_iter.first = _beB.first; - else if (_tvertex_iter.first == _beB.first) - _tvertex_iter.first = 0; - else - _tvertex_iter.first = _feA.first; - return; - } - if (_feA.first == _beB.first) { - if (_feB.first == _beA.first) { - _tvertex_iter.first = 0; - return; - } - - if (_tvertex_iter.first == _feB.first) - _tvertex_iter.first = _beA.first; - else if (_tvertex_iter.first == _beA.first) - _tvertex_iter.first = 0; - else - _tvertex_iter.first = _feB.first; - return; - } - // End of hack - - if (_tvertex_iter.first == _feA.first) { - // we return bea or beb - // choose one of them - _tvertex_iter.first = _feB.first; - return; - } - if (_tvertex_iter.first == _feB.first) { - _tvertex_iter.first = _beA.first; - return; - } - if (_tvertex_iter.first == _beA.first) { - _tvertex_iter.first = _beB.first; - return; - } - if (_tvertex_iter.first == _beB.first) { - _tvertex_iter.first = 0; - return; - } + // Hack to deal with cusp. the result of a cusp is a TVertex having two identical viewedges. + // In order to iterate properly, we chose to skip these last ones. + if (_feB.first == _beA.first) { + if (_feA.first == _beB.first) { + _tvertex_iter.first = 0; + return; + } + + if (_tvertex_iter.first == _feA.first) + _tvertex_iter.first = _beB.first; + else if (_tvertex_iter.first == _beB.first) + _tvertex_iter.first = 0; + else + _tvertex_iter.first = _feA.first; + return; + } + if (_feA.first == _beB.first) { + if (_feB.first == _beA.first) { + _tvertex_iter.first = 0; + return; + } + + if (_tvertex_iter.first == _feB.first) + _tvertex_iter.first = _beA.first; + else if (_tvertex_iter.first == _beA.first) + _tvertex_iter.first = 0; + else + _tvertex_iter.first = _feB.first; + return; + } + // End of hack + + if (_tvertex_iter.first == _feA.first) { + // we return bea or beb + // choose one of them + _tvertex_iter.first = _feB.first; + return; + } + if (_tvertex_iter.first == _feB.first) { + _tvertex_iter.first = _beA.first; + return; + } + if (_tvertex_iter.first == _beA.first) { + _tvertex_iter.first = _beB.first; + return; + } + if (_tvertex_iter.first == _beB.first) { + _tvertex_iter.first = 0; + return; + } #endif - } - else { - ++_nontvertex_iter; - } - } + } + else { + ++_nontvertex_iter; + } + } }; -} // ViewVertexInternal namespace +} // namespace ViewVertexInternal /**********************************/ /* */ @@ -346,435 +351,453 @@ namespace ViewEdgeInternal { /*! Iterators definition */ /*!----------------------*/ template<class Traits> -class edge_iterator_base : public IteratorBase<Traits, BidirectionalIteratorTag_Traits> -{ -public: - typedef typename Traits::value_type value_type; - typedef typename Traits::difference_type difference_type; - typedef typename Traits::pointer pointer; - typedef typename Traits::reference reference; - typedef edge_iterator_base<Traits> Self; - -public: - mutable value_type _ViewEdge; - //friend class edge_iterator_base<Nonconst_traits<ViewEdge*> >; - //friend class edge_iterator_base<Const_traits<ViewEdge*> >; - value_type _first; - bool _orientation; - typedef IteratorBase<Traits, BidirectionalIteratorTag_Traits> parent_class; - -public: - friend class ViewEdge; - inline edge_iterator_base() : parent_class() - { - _orientation = true; - _first = 0; - } - - inline edge_iterator_base(const edge_iterator_base<Nonconst_traits<ViewEdge*> >& iBrother) : parent_class() - { - _ViewEdge = iBrother._ViewEdge; - _first = iBrother._first; - _orientation = iBrother._orientation; - } - - inline edge_iterator_base(const edge_iterator_base<Const_traits<ViewEdge*> >& iBrother) : parent_class() - { - _ViewEdge = iBrother._ViewEdge; - _first = iBrother._first; - _orientation = iBrother._orientation; - } - -//protected://FIXME -public: - inline edge_iterator_base(value_type iEdge, bool orientation = true) : parent_class() - { - _ViewEdge = iEdge; - _first = iEdge; - _orientation = orientation; - } - -public: - virtual Self *clone() const - { - return new edge_iterator_base(*this); - } - - virtual ~edge_iterator_base() {} - -public: - virtual bool orientation() - { - return _orientation; - } - - virtual void set_edge(value_type iVE) - { - _ViewEdge = iVE; - } - - virtual void set_orientation(bool iOrientation) - { - _orientation = iOrientation; - } - - virtual void change_orientation() - { - _orientation = !_orientation; - } - - // operators - // operator corresponding to ++i - inline Self& operator++() - { - //++_ViewEdge->getTimeStamp(); - increment(); - return *this; - } - - // operator corresponding to i++, i.e. which returns the value *and then* increments it. - // That's why we store the value in a temp. - inline Self operator++(int) - { - //++_ViewEdge->getTimeStamp(); - Self tmp = *this; - increment(); - return tmp; - } - - // operator corresponding to --i - inline Self& operator--() - { - //++_ViewEdge->getTimeStamp(); - decrement(); - return *this; - } - - // operator corresponding to i--, i.e. which returns the value *and then* increments it. - // That's why we store the value in a temp. - inline Self operator--(int) - { - //++_ViewEdge->getTimeStamp(); - Self tmp = *this; - decrement(); - return tmp; - } - - // comparibility - virtual bool operator!=(const Self& b) const - { - return (_ViewEdge != b._ViewEdge); - } - - virtual bool operator==(const Self& b) const - { - return !(*this != b); - } - - // dereferencing - virtual reference operator*() const - { - return (_ViewEdge); - } - - virtual pointer operator->() const - { - return &(operator*()); - } - -public: - virtual bool begin() const - { - return (_ViewEdge == _first) ? true : false; - } - - virtual bool end() const - { - return (_ViewEdge == 0) ? true : false; - } - -protected: - virtual void increment() {} - virtual void decrement() {} +class edge_iterator_base : public IteratorBase<Traits, BidirectionalIteratorTag_Traits> { + public: + typedef typename Traits::value_type value_type; + typedef typename Traits::difference_type difference_type; + typedef typename Traits::pointer pointer; + typedef typename Traits::reference reference; + typedef edge_iterator_base<Traits> Self; + + public: + mutable value_type _ViewEdge; + //friend class edge_iterator_base<Nonconst_traits<ViewEdge*> >; + //friend class edge_iterator_base<Const_traits<ViewEdge*> >; + value_type _first; + bool _orientation; + typedef IteratorBase<Traits, BidirectionalIteratorTag_Traits> parent_class; + + public: + friend class ViewEdge; + inline edge_iterator_base() : parent_class() + { + _orientation = true; + _first = 0; + } + + inline edge_iterator_base(const edge_iterator_base<Nonconst_traits<ViewEdge *>> &iBrother) + : parent_class() + { + _ViewEdge = iBrother._ViewEdge; + _first = iBrother._first; + _orientation = iBrother._orientation; + } + + inline edge_iterator_base(const edge_iterator_base<Const_traits<ViewEdge *>> &iBrother) + : parent_class() + { + _ViewEdge = iBrother._ViewEdge; + _first = iBrother._first; + _orientation = iBrother._orientation; + } + + //protected://FIXME + public: + inline edge_iterator_base(value_type iEdge, bool orientation = true) : parent_class() + { + _ViewEdge = iEdge; + _first = iEdge; + _orientation = orientation; + } + + public: + virtual Self *clone() const + { + return new edge_iterator_base(*this); + } + + virtual ~edge_iterator_base() + { + } + + public: + virtual bool orientation() + { + return _orientation; + } + + virtual void set_edge(value_type iVE) + { + _ViewEdge = iVE; + } + + virtual void set_orientation(bool iOrientation) + { + _orientation = iOrientation; + } + + virtual void change_orientation() + { + _orientation = !_orientation; + } + + // operators + // operator corresponding to ++i + inline Self &operator++() + { + //++_ViewEdge->getTimeStamp(); + increment(); + return *this; + } + + // operator corresponding to i++, i.e. which returns the value *and then* increments it. + // That's why we store the value in a temp. + inline Self operator++(int) + { + //++_ViewEdge->getTimeStamp(); + Self tmp = *this; + increment(); + return tmp; + } + + // operator corresponding to --i + inline Self &operator--() + { + //++_ViewEdge->getTimeStamp(); + decrement(); + return *this; + } + + // operator corresponding to i--, i.e. which returns the value *and then* increments it. + // That's why we store the value in a temp. + inline Self operator--(int) + { + //++_ViewEdge->getTimeStamp(); + Self tmp = *this; + decrement(); + return tmp; + } + + // comparibility + virtual bool operator!=(const Self &b) const + { + return (_ViewEdge != b._ViewEdge); + } + + virtual bool operator==(const Self &b) const + { + return !(*this != b); + } + + // dereferencing + virtual reference operator*() const + { + return (_ViewEdge); + } + + virtual pointer operator->() const + { + return &(operator*()); + } + + public: + virtual bool begin() const + { + return (_ViewEdge == _first) ? true : false; + } + + virtual bool end() const + { + return (_ViewEdge == 0) ? true : false; + } + + protected: + virtual void increment() + { + } + virtual void decrement() + { + } }; template<class Traits> -class fedge_iterator_base : public IteratorBase<Traits, BidirectionalIteratorTag_Traits> -{ -public: - typedef typename Traits::value_type value_type; - typedef typename Traits::difference_type difference_type; - typedef typename Traits::pointer pointer; - typedef typename Traits::reference reference; - typedef fedge_iterator_base<Traits> Self; - -public: - typedef IteratorBase<Traits, BidirectionalIteratorTag_Traits> parent_class; - mutable value_type _FEdge; - value_type _first; - value_type _FEdgeB; // last fedge of the view edge - -public: - friend class ViewEdge; - friend class fedge_iterator; - - inline fedge_iterator_base() : parent_class() {} - - inline fedge_iterator_base(const fedge_iterator_base<Nonconst_traits<FEdge*> >& iBrother) : parent_class() - { - _FEdge = iBrother._FEdge; - _first = iBrother._first; - _FEdgeB = iBrother._FEdgeB; - } - - inline fedge_iterator_base(const fedge_iterator_base<Const_traits<FEdge*> >& iBrother) : parent_class() - { - _FEdge = iBrother._FEdge; - _first = iBrother._first; - _FEdgeB = iBrother._FEdgeB; - } - -//protected://FIXME -public: - inline fedge_iterator_base(value_type iEdge, value_type iFEdgeB) : parent_class() - { - _FEdge = iEdge; - _first = iEdge; - _FEdgeB = iFEdgeB; - } - -public: - virtual ~fedge_iterator_base() {} - - // operators - // operator corresponding to ++i. - inline Self& operator++() - { - increment(); - return *this; - } - - // operator corresponding to i++, i.e. which returns the value *and then* increments it. - // That's why we store the value in a temp. - inline Self operator++(int) - { - Self tmp = *this; - increment(); - return tmp; - } - - // operator corresponding to --i - inline Self& operator--() - { - decrement(); - return *this; - } - - // operator corresponding to i--, i.e. which returns the value *and then* increments it. - // That's why we store the value in a temp. - inline Self operator--(int) - { - Self tmp = *this; - decrement(); - return tmp; - } - - // comparibility - virtual bool operator!=(const Self& b) const - { - return (_FEdge != b._FEdge); - } - - virtual bool operator==(const Self& b) const - { - return !(*this != b); - } - - // dereferencing - virtual reference operator*() const - { - return (_FEdge); - } - - virtual pointer operator->() const - { - return &(operator*()); - } - -public: - virtual bool begin() const - { - return (_FEdge == _first) ? true : false; - } - - virtual bool end() const - { - return (_FEdge == 0) ? true : false; - } - -protected: - virtual void increment() - { - _FEdge = _FEdge->nextEdge(); // we don't change or - } - - virtual void decrement() - { - if (0 == _FEdge) { - _FEdge = _FEdgeB; - return; - } - _FEdge = _FEdge->previousEdge(); // we don't change or - } +class fedge_iterator_base : public IteratorBase<Traits, BidirectionalIteratorTag_Traits> { + public: + typedef typename Traits::value_type value_type; + typedef typename Traits::difference_type difference_type; + typedef typename Traits::pointer pointer; + typedef typename Traits::reference reference; + typedef fedge_iterator_base<Traits> Self; + + public: + typedef IteratorBase<Traits, BidirectionalIteratorTag_Traits> parent_class; + mutable value_type _FEdge; + value_type _first; + value_type _FEdgeB; // last fedge of the view edge + + public: + friend class ViewEdge; + friend class fedge_iterator; + + inline fedge_iterator_base() : parent_class() + { + } + + inline fedge_iterator_base(const fedge_iterator_base<Nonconst_traits<FEdge *>> &iBrother) + : parent_class() + { + _FEdge = iBrother._FEdge; + _first = iBrother._first; + _FEdgeB = iBrother._FEdgeB; + } + + inline fedge_iterator_base(const fedge_iterator_base<Const_traits<FEdge *>> &iBrother) + : parent_class() + { + _FEdge = iBrother._FEdge; + _first = iBrother._first; + _FEdgeB = iBrother._FEdgeB; + } + + //protected://FIXME + public: + inline fedge_iterator_base(value_type iEdge, value_type iFEdgeB) : parent_class() + { + _FEdge = iEdge; + _first = iEdge; + _FEdgeB = iFEdgeB; + } + + public: + virtual ~fedge_iterator_base() + { + } + + // operators + // operator corresponding to ++i. + inline Self &operator++() + { + increment(); + return *this; + } + + // operator corresponding to i++, i.e. which returns the value *and then* increments it. + // That's why we store the value in a temp. + inline Self operator++(int) + { + Self tmp = *this; + increment(); + return tmp; + } + + // operator corresponding to --i + inline Self &operator--() + { + decrement(); + return *this; + } + + // operator corresponding to i--, i.e. which returns the value *and then* increments it. + // That's why we store the value in a temp. + inline Self operator--(int) + { + Self tmp = *this; + decrement(); + return tmp; + } + + // comparibility + virtual bool operator!=(const Self &b) const + { + return (_FEdge != b._FEdge); + } + + virtual bool operator==(const Self &b) const + { + return !(*this != b); + } + + // dereferencing + virtual reference operator*() const + { + return (_FEdge); + } + + virtual pointer operator->() const + { + return &(operator*()); + } + + public: + virtual bool begin() const + { + return (_FEdge == _first) ? true : false; + } + + virtual bool end() const + { + return (_FEdge == 0) ? true : false; + } + + protected: + virtual void increment() + { + _FEdge = _FEdge->nextEdge(); // we don't change or + } + + virtual void decrement() + { + if (0 == _FEdge) { + _FEdge = _FEdgeB; + return; + } + _FEdge = _FEdge->previousEdge(); // we don't change or + } }; template<class Traits> -class vertex_iterator_base : public IteratorBase<Traits, BidirectionalIteratorTag_Traits> -{ -public: - typedef typename Traits::value_type value_type; - typedef typename Traits::difference_type difference_type; - typedef typename Traits::pointer pointer; - typedef typename Traits::reference reference; - typedef vertex_iterator_base<Traits> Self; - -protected: - typedef IteratorBase<Traits, BidirectionalIteratorTag_Traits> parent_class; - -public: - mutable value_type _SVertex; - FEdge *_NextFEdge; - FEdge *_PreviousFEdge; - -public: - friend class ViewEdge; - friend class vertex_iterator; - - inline vertex_iterator_base() : parent_class() {} - - inline vertex_iterator_base(const vertex_iterator_base<Const_traits<SVertex*> >& iBrother) : parent_class() - { - _SVertex = iBrother._SVertex; - _NextFEdge = iBrother._NextFEdge; - _PreviousFEdge = iBrother._PreviousFEdge; - } - - inline vertex_iterator_base(const vertex_iterator_base<Nonconst_traits<SVertex*> >& iBrother) : parent_class() - { - _SVertex = iBrother._SVertex; - _NextFEdge = iBrother._NextFEdge; - _PreviousFEdge = iBrother._PreviousFEdge; - } - -//protected://FIXME -public: - inline vertex_iterator_base(value_type iVertex, FEdge *iPreviousFEdge, FEdge *iNextFEdge) : parent_class() - { - _SVertex = iVertex; - _NextFEdge = iNextFEdge; - _PreviousFEdge = iPreviousFEdge; - } - -public: - virtual ~vertex_iterator_base() {} - - virtual bool begin() const - { - return (_PreviousFEdge == 0) ? true : false; - } - - virtual bool end() const - { - return (_SVertex == 0) ? true : false; - } - - // operators - // operator corresponding to ++i - inline Self& operator++() - { - increment(); - return *this; - } - - // operator corresponding to i++, i.e. which returns the value *and then* increments it. - // That's why we store the value in a temp. - inline Self operator++(int) - { - Self tmp = *this; - increment(); - return tmp; - } - - // operator corresponding to --i - inline Self& operator--() - { - decrement(); - return *this; - } - - // operator corresponding to --i, i.e. which returns the value *and then* increments it. - // That's why we store the value in a temp. - inline Self operator--(int) - { - Self tmp = *this; - decrement(); - return tmp; - } - - // comparibility - virtual bool operator!=(const Self& b) const - { - return (_SVertex != b._SVertex); - } - - virtual bool operator==(const Self& b) const - { - return !(*this != b); - } - - // dereferencing - virtual reference operator*() const - { - return (_SVertex); - } - - virtual pointer operator->() const - { - return &(operator*()); - } - -protected: - virtual void increment() - { - if (!_NextFEdge) { - _SVertex = NULL; - return; - } - _SVertex = _NextFEdge->vertexB(); - _PreviousFEdge = _NextFEdge; - _NextFEdge = _NextFEdge->nextEdge(); - } - - virtual void decrement() - { +class vertex_iterator_base : public IteratorBase<Traits, BidirectionalIteratorTag_Traits> { + public: + typedef typename Traits::value_type value_type; + typedef typename Traits::difference_type difference_type; + typedef typename Traits::pointer pointer; + typedef typename Traits::reference reference; + typedef vertex_iterator_base<Traits> Self; + + protected: + typedef IteratorBase<Traits, BidirectionalIteratorTag_Traits> parent_class; + + public: + mutable value_type _SVertex; + FEdge *_NextFEdge; + FEdge *_PreviousFEdge; + + public: + friend class ViewEdge; + friend class vertex_iterator; + + inline vertex_iterator_base() : parent_class() + { + } + + inline vertex_iterator_base(const vertex_iterator_base<Const_traits<SVertex *>> &iBrother) + : parent_class() + { + _SVertex = iBrother._SVertex; + _NextFEdge = iBrother._NextFEdge; + _PreviousFEdge = iBrother._PreviousFEdge; + } + + inline vertex_iterator_base(const vertex_iterator_base<Nonconst_traits<SVertex *>> &iBrother) + : parent_class() + { + _SVertex = iBrother._SVertex; + _NextFEdge = iBrother._NextFEdge; + _PreviousFEdge = iBrother._PreviousFEdge; + } + + //protected://FIXME + public: + inline vertex_iterator_base(value_type iVertex, FEdge *iPreviousFEdge, FEdge *iNextFEdge) + : parent_class() + { + _SVertex = iVertex; + _NextFEdge = iNextFEdge; + _PreviousFEdge = iPreviousFEdge; + } + + public: + virtual ~vertex_iterator_base() + { + } + + virtual bool begin() const + { + return (_PreviousFEdge == 0) ? true : false; + } + + virtual bool end() const + { + return (_SVertex == 0) ? true : false; + } + + // operators + // operator corresponding to ++i + inline Self &operator++() + { + increment(); + return *this; + } + + // operator corresponding to i++, i.e. which returns the value *and then* increments it. + // That's why we store the value in a temp. + inline Self operator++(int) + { + Self tmp = *this; + increment(); + return tmp; + } + + // operator corresponding to --i + inline Self &operator--() + { + decrement(); + return *this; + } + + // operator corresponding to --i, i.e. which returns the value *and then* increments it. + // That's why we store the value in a temp. + inline Self operator--(int) + { + Self tmp = *this; + decrement(); + return tmp; + } + + // comparibility + virtual bool operator!=(const Self &b) const + { + return (_SVertex != b._SVertex); + } + + virtual bool operator==(const Self &b) const + { + return !(*this != b); + } + + // dereferencing + virtual reference operator*() const + { + return (_SVertex); + } + + virtual pointer operator->() const + { + return &(operator*()); + } + + protected: + virtual void increment() + { + if (!_NextFEdge) { + _SVertex = NULL; + return; + } + _SVertex = _NextFEdge->vertexB(); + _PreviousFEdge = _NextFEdge; + _NextFEdge = _NextFEdge->nextEdge(); + } + + virtual void decrement() + { #if 0 - if (!_SVertex) { - _SVertex = _PreviousFEdge->vertexB(); - return; - } + if (!_SVertex) { + _SVertex = _PreviousFEdge->vertexB(); + return; + } #endif - if (!_PreviousFEdge) { - _SVertex = NULL; - return; - } - _SVertex = _PreviousFEdge->vertexA(); - _NextFEdge = _PreviousFEdge; - _PreviousFEdge = _PreviousFEdge->previousEdge(); - } + if (!_PreviousFEdge) { + _SVertex = NULL; + return; + } + _SVertex = _PreviousFEdge->vertexA(); + _NextFEdge = _PreviousFEdge; + _PreviousFEdge = _PreviousFEdge->previousEdge(); + } }; -} // end of namespace ViewEdgeInternal +} // end of namespace ViewEdgeInternal } /* namespace Freestyle */ -#endif // __FREESTYLE_VIEW_MAP_ADVANCED_ITERATORS_H__ +#endif // __FREESTYLE_VIEW_MAP_ADVANCED_ITERATORS_H__ diff --git a/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp index e2bc45fc03f..ed0f5c9b0bd 100644 --- a/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp +++ b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp @@ -49,347 +49,365 @@ static const Global &_global = G; using namespace std; -template <typename G, typename I> -static void findOccludee(FEdge *fe, G& /*grid*/, I& occluders, real epsilon, WFace **oaWFace, - Vec3r& u, Vec3r& A, Vec3r& origin, Vec3r& edgeDir, vector<WVertex*>& faceVertices) +template<typename G, typename I> +static void findOccludee(FEdge *fe, + G & /*grid*/, + I &occluders, + real epsilon, + WFace **oaWFace, + Vec3r &u, + Vec3r &A, + Vec3r &origin, + Vec3r &edgeDir, + vector<WVertex *> &faceVertices) { - WFace *face = NULL; - if (fe->isSmooth()) { - FEdgeSmooth *fes = dynamic_cast<FEdgeSmooth*>(fe); - face = (WFace *)fes->face(); - } - WFace *oface; - bool skipFace; - - WVertex::incoming_edge_iterator ie; - - *oaWFace = NULL; - if (((fe)->getNature() & Nature::SILHOUETTE) || ((fe)->getNature() & Nature::BORDER)) { - // we cast a ray from A in the same direction but looking behind - Vec3r v(-u[0], -u[1], -u[2]); - bool noIntersection = true; - real mint = FLT_MAX; - - for (occluders.initAfterTarget(); occluders.validAfterTarget(); occluders.nextOccludee()) { + WFace *face = NULL; + if (fe->isSmooth()) { + FEdgeSmooth *fes = dynamic_cast<FEdgeSmooth *>(fe); + face = (WFace *)fes->face(); + } + WFace *oface; + bool skipFace; + + WVertex::incoming_edge_iterator ie; + + *oaWFace = NULL; + if (((fe)->getNature() & Nature::SILHOUETTE) || ((fe)->getNature() & Nature::BORDER)) { + // we cast a ray from A in the same direction but looking behind + Vec3r v(-u[0], -u[1], -u[2]); + bool noIntersection = true; + real mint = FLT_MAX; + + for (occluders.initAfterTarget(); occluders.validAfterTarget(); occluders.nextOccludee()) { #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\t\tEvaluating intersection for occludee " << occluders.getWFace() << " and ray " << A << - " * " << u << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\t\tEvaluating intersection for occludee " << occluders.getWFace() << " and ray " + << A << " * " << u << endl; + } #endif - oface = occluders.getWFace(); - Polygon3r *p = occluders.getCameraSpacePolygon(); - real d = -((p->getVertices())[0] * p->getNormal()); - real t, t_u, t_v; - - if (0 != face) { - skipFace = false; - - if (face == oface) - continue; - - if (faceVertices.empty()) - continue; - - for (vector<WVertex*>::iterator fv = faceVertices.begin(), fvend = faceVertices.end(); - fv != fvend; - ++fv) - { - if ((*fv)->isBoundary()) - continue; - WVertex::incoming_edge_iterator iebegin = (*fv)->incoming_edges_begin(); - WVertex::incoming_edge_iterator ieend = (*fv)->incoming_edges_end(); - for (ie = iebegin; ie != ieend; ++ie) { - if ((*ie) == 0) - continue; - - WFace *sface = (*ie)->GetbFace(); - if (sface == oface) { - skipFace = true; - break; - } - } - if (skipFace) - break; - } - if (skipFace) - continue; - } - else { - // check whether the edge and the polygon plane are coincident: - //------------------------------------------------------------- - //first let us compute the plane equation. - if (GeomUtils::COINCIDENT == GeomUtils::intersectRayPlane(origin, edgeDir, p->getNormal(), d, t, epsilon)) - { + oface = occluders.getWFace(); + Polygon3r *p = occluders.getCameraSpacePolygon(); + real d = -((p->getVertices())[0] * p->getNormal()); + real t, t_u, t_v; + + if (0 != face) { + skipFace = false; + + if (face == oface) + continue; + + if (faceVertices.empty()) + continue; + + for (vector<WVertex *>::iterator fv = faceVertices.begin(), fvend = faceVertices.end(); + fv != fvend; + ++fv) { + if ((*fv)->isBoundary()) + continue; + WVertex::incoming_edge_iterator iebegin = (*fv)->incoming_edges_begin(); + WVertex::incoming_edge_iterator ieend = (*fv)->incoming_edges_end(); + for (ie = iebegin; ie != ieend; ++ie) { + if ((*ie) == 0) + continue; + + WFace *sface = (*ie)->GetbFace(); + if (sface == oface) { + skipFace = true; + break; + } + } + if (skipFace) + break; + } + if (skipFace) + continue; + } + else { + // check whether the edge and the polygon plane are coincident: + //------------------------------------------------------------- + //first let us compute the plane equation. + if (GeomUtils::COINCIDENT == + GeomUtils::intersectRayPlane(origin, edgeDir, p->getNormal(), d, t, epsilon)) { #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\t\tRejecting occluder for target coincidence." << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\t\tRejecting occluder for target coincidence." << endl; + } #endif - continue; - } - } + continue; + } + } - if (p->rayIntersect(A, v, t, t_u, t_v)) { + if (p->rayIntersect(A, v, t, t_u, t_v)) { #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\t\tRay " << A << " * " << v << " intersects at time " << t << endl; - cout << "\t\t(v * normal) == " << (v * p->getNormal()) << " for normal " << p->getNormal() << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\t\tRay " << A << " * " << v << " intersects at time " << t << endl; + cout << "\t\t(v * normal) == " << (v * p->getNormal()) << " for normal " + << p->getNormal() << endl; + } #endif - if (fabs(v * p->getNormal()) > 0.0001) { - if ((t > 0.0)) { // && (t<1.0)) - if (t < mint) { - *oaWFace = oface; - mint = t; - noIntersection = false; - fe->setOccludeeIntersection(Vec3r(A + t * v)); + if (fabs(v * p->getNormal()) > 0.0001) { + if ((t > 0.0)) { // && (t<1.0)) + if (t < mint) { + *oaWFace = oface; + mint = t; + noIntersection = false; + fe->setOccludeeIntersection(Vec3r(A + t * v)); #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\t\tIs occludee" << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\t\tIs occludee" << endl; + } #endif - } - } - } + } + } + } - occluders.reportDepth(A, v, t); - } - } + occluders.reportDepth(A, v, t); + } + } - if (noIntersection) - *oaWFace = NULL; - } + if (noIntersection) + *oaWFace = NULL; + } } -template <typename G, typename I> -static void findOccludee(FEdge *fe, G& grid, real epsilon, ViewEdge * /*ve*/, WFace **oaFace) +template<typename G, typename I> +static void findOccludee(FEdge *fe, G &grid, real epsilon, ViewEdge * /*ve*/, WFace **oaFace) { - Vec3r A; - Vec3r edgeDir; - Vec3r origin; - A = Vec3r(((fe)->vertexA()->point3D() + (fe)->vertexB()->point3D()) / 2.0); - edgeDir = Vec3r((fe)->vertexB()->point3D() - (fe)->vertexA()->point3D()); - edgeDir.normalize(); - origin = Vec3r((fe)->vertexA()->point3D()); - Vec3r u; - if (grid.orthographicProjection()) { - u = Vec3r(0.0, 0.0, grid.viewpoint().z() - A.z()); - } - else { - u = Vec3r(grid.viewpoint() - A); - } - u.normalize(); - - vector<WVertex*> faceVertices; - - WFace *face = NULL; - if (fe->isSmooth()) { - FEdgeSmooth *fes = dynamic_cast<FEdgeSmooth*>(fe); - face = (WFace *)fes->face(); - } - - if (face) { - face->RetrieveVertexList(faceVertices); - } - - I occluders(grid, A, epsilon); - findOccludee<G, I>(fe, grid, occluders, epsilon, oaFace, u, A, origin, edgeDir, faceVertices); + Vec3r A; + Vec3r edgeDir; + Vec3r origin; + A = Vec3r(((fe)->vertexA()->point3D() + (fe)->vertexB()->point3D()) / 2.0); + edgeDir = Vec3r((fe)->vertexB()->point3D() - (fe)->vertexA()->point3D()); + edgeDir.normalize(); + origin = Vec3r((fe)->vertexA()->point3D()); + Vec3r u; + if (grid.orthographicProjection()) { + u = Vec3r(0.0, 0.0, grid.viewpoint().z() - A.z()); + } + else { + u = Vec3r(grid.viewpoint() - A); + } + u.normalize(); + + vector<WVertex *> faceVertices; + + WFace *face = NULL; + if (fe->isSmooth()) { + FEdgeSmooth *fes = dynamic_cast<FEdgeSmooth *>(fe); + face = (WFace *)fes->face(); + } + + if (face) { + face->RetrieveVertexList(faceVertices); + } + + I occluders(grid, A, epsilon); + findOccludee<G, I>(fe, grid, occluders, epsilon, oaFace, u, A, origin, edgeDir, faceVertices); } // computeVisibility takes a pointer to foundOccluders, instead of using a reference, // so that computeVeryFastVisibility can skip the AddOccluders step with minimal overhead. -template <typename G, typename I> -static int computeVisibility(ViewMap *viewMap, FEdge *fe, G& grid, real epsilon, ViewEdge * /*ve*/, WFace **oaWFace, - set<ViewShape*> *foundOccluders) +template<typename G, typename I> +static int computeVisibility(ViewMap *viewMap, + FEdge *fe, + G &grid, + real epsilon, + ViewEdge * /*ve*/, + WFace **oaWFace, + set<ViewShape *> *foundOccluders) { - int qi = 0; - - Vec3r center; - Vec3r edgeDir; - Vec3r origin; - - center = fe->center3d(); - edgeDir = Vec3r(fe->vertexB()->point3D() - fe->vertexA()->point3D()); - edgeDir.normalize(); - origin = Vec3r(fe->vertexA()->point3D()); - - Vec3r vp; - if (grid.orthographicProjection()) { - vp = Vec3r(center.x(), center.y(), grid.viewpoint().z()); - } - else { - vp = Vec3r(grid.viewpoint()); - } - Vec3r u(vp - center); - real raylength = u.norm(); - u.normalize(); - - WFace *face = NULL; - if (fe->isSmooth()) { - FEdgeSmooth *fes = dynamic_cast<FEdgeSmooth*>(fe); - face = (WFace *)fes->face(); - } - vector<WVertex*> faceVertices; - WVertex::incoming_edge_iterator ie; - - WFace *oface; - bool skipFace; - - if (face) - face->RetrieveVertexList(faceVertices); - - I occluders(grid, center, epsilon); - - for (occluders.initBeforeTarget(); occluders.validBeforeTarget(); occluders.nextOccluder()) { - // If we're dealing with an exact silhouette, check whether we must take care of this occluder of not. - // (Indeed, we don't consider the occluders that share at least one vertex with the face containing this edge). - //----------- - oface = occluders.getWFace(); - Polygon3r *p = occluders.getCameraSpacePolygon(); - real t, t_u, t_v; + int qi = 0; + + Vec3r center; + Vec3r edgeDir; + Vec3r origin; + + center = fe->center3d(); + edgeDir = Vec3r(fe->vertexB()->point3D() - fe->vertexA()->point3D()); + edgeDir.normalize(); + origin = Vec3r(fe->vertexA()->point3D()); + + Vec3r vp; + if (grid.orthographicProjection()) { + vp = Vec3r(center.x(), center.y(), grid.viewpoint().z()); + } + else { + vp = Vec3r(grid.viewpoint()); + } + Vec3r u(vp - center); + real raylength = u.norm(); + u.normalize(); + + WFace *face = NULL; + if (fe->isSmooth()) { + FEdgeSmooth *fes = dynamic_cast<FEdgeSmooth *>(fe); + face = (WFace *)fes->face(); + } + vector<WVertex *> faceVertices; + WVertex::incoming_edge_iterator ie; + + WFace *oface; + bool skipFace; + + if (face) + face->RetrieveVertexList(faceVertices); + + I occluders(grid, center, epsilon); + + for (occluders.initBeforeTarget(); occluders.validBeforeTarget(); occluders.nextOccluder()) { + // If we're dealing with an exact silhouette, check whether we must take care of this occluder of not. + // (Indeed, we don't consider the occluders that share at least one vertex with the face containing this edge). + //----------- + oface = occluders.getWFace(); + Polygon3r *p = occluders.getCameraSpacePolygon(); + real t, t_u, t_v; #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\t\tEvaluating intersection for occluder " << (p->getVertices())[0] << (p->getVertices())[1] << - (p->getVertices())[2] << endl << "\t\t\tand ray " << vp << " * " << u << " (center " << center << - ")" << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\t\tEvaluating intersection for occluder " << (p->getVertices())[0] + << (p->getVertices())[1] << (p->getVertices())[2] << endl + << "\t\t\tand ray " << vp << " * " << u << " (center " << center << ")" << endl; + } #endif #if LOGGING - Vec3r v(vp - center); - real rl = v.norm(); - v.normalize(); - vector<Vec3r> points; - // Iterate over vertices, storing projections in points - for (vector<WOEdge*>::const_iterator woe = oface->getEdgeList().begin(), woend = oface->getEdgeList().end(); - woe != woend; - woe++) - { - points.push_back(Vec3r((*woe)->GetaVertex()->GetVertex())); - } - Polygon3r p1(points, oface->GetNormal()); - Vec3r v1((p1.getVertices())[0]); - real d = -(v1 * p->getNormal()); - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\t\tp: " << (p->getVertices())[0] << (p->getVertices())[1] << (p->getVertices())[2] << ", norm: " << - p->getNormal() << endl; - cout << "\t\tp1: " << (p1.getVertices())[0] << (p1.getVertices())[1] << (p1.getVertices())[2] << ", norm: " << - p1.getNormal() << endl; - } + Vec3r v(vp - center); + real rl = v.norm(); + v.normalize(); + vector<Vec3r> points; + // Iterate over vertices, storing projections in points + for (vector<WOEdge *>::const_iterator woe = oface->getEdgeList().begin(), + woend = oface->getEdgeList().end(); + woe != woend; + woe++) { + points.push_back(Vec3r((*woe)->GetaVertex()->GetVertex())); + } + Polygon3r p1(points, oface->GetNormal()); + Vec3r v1((p1.getVertices())[0]); + real d = -(v1 * p->getNormal()); + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\t\tp: " << (p->getVertices())[0] << (p->getVertices())[1] << (p->getVertices())[2] + << ", norm: " << p->getNormal() << endl; + cout << "\t\tp1: " << (p1.getVertices())[0] << (p1.getVertices())[1] << (p1.getVertices())[2] + << ", norm: " << p1.getNormal() << endl; + } #else - real d = -((p->getVertices())[0] * p->getNormal()); + real d = -((p->getVertices())[0] * p->getNormal()); #endif - if (face) { + if (face) { #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\t\tDetermining face adjacency..."; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\t\tDetermining face adjacency..."; + } #endif - skipFace = false; + skipFace = false; - if (face == oface) { + if (face == oface) { #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << " Rejecting occluder for face concurrency." << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << " Rejecting occluder for face concurrency." << endl; + } #endif - continue; - } - - - for (vector<WVertex*>::iterator fv = faceVertices.begin(), fvend = faceVertices.end(); fv != fvend; ++fv) { - if ((*fv)->isBoundary()) - continue; - - WVertex::incoming_edge_iterator iebegin = (*fv)->incoming_edges_begin(); - WVertex::incoming_edge_iterator ieend = (*fv)->incoming_edges_end(); - for (ie = iebegin; ie != ieend; ++ie) { - if ((*ie) == 0) - continue; - - WFace *sface = (*ie)->GetbFace(); - //WFace *sfacea = (*ie)->GetaFace(); - //if ((sface == oface) || (sfacea == oface)) - if (sface == oface) { - skipFace = true; - break; - } - } - if (skipFace) - break; - } - if (skipFace) { + continue; + } + + for (vector<WVertex *>::iterator fv = faceVertices.begin(), fvend = faceVertices.end(); + fv != fvend; + ++fv) { + if ((*fv)->isBoundary()) + continue; + + WVertex::incoming_edge_iterator iebegin = (*fv)->incoming_edges_begin(); + WVertex::incoming_edge_iterator ieend = (*fv)->incoming_edges_end(); + for (ie = iebegin; ie != ieend; ++ie) { + if ((*ie) == 0) + continue; + + WFace *sface = (*ie)->GetbFace(); + //WFace *sfacea = (*ie)->GetaFace(); + //if ((sface == oface) || (sfacea == oface)) + if (sface == oface) { + skipFace = true; + break; + } + } + if (skipFace) + break; + } + if (skipFace) { #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << " Rejecting occluder for face adjacency." << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << " Rejecting occluder for face adjacency." << endl; + } #endif - continue; - } - } - else { - // check whether the edge and the polygon plane are coincident: - //------------------------------------------------------------- - //first let us compute the plane equation. - if (GeomUtils::COINCIDENT == GeomUtils::intersectRayPlane(origin, edgeDir, p->getNormal(), d, t, epsilon)) { + continue; + } + } + else { + // check whether the edge and the polygon plane are coincident: + //------------------------------------------------------------- + //first let us compute the plane equation. + if (GeomUtils::COINCIDENT == + GeomUtils::intersectRayPlane(origin, edgeDir, p->getNormal(), d, t, epsilon)) { #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\t\tRejecting occluder for target coincidence." << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\t\tRejecting occluder for target coincidence." << endl; + } #endif - continue; - } - } + continue; + } + } #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - real x; - if (p1.rayIntersect(center, v, x, t_u, t_v)) { - cout << "\t\tRay should intersect at time " << (rl - x) << ". Center: " << center << ", V: " << v << - ", RL: " << rl << ", T:" << x << endl; - } - else { - cout << "\t\tRay should not intersect. Center: " << center << ", V: " << v << ", RL: " << rl << endl; - } - } + if (_global.debug & G_DEBUG_FREESTYLE) { + real x; + if (p1.rayIntersect(center, v, x, t_u, t_v)) { + cout << "\t\tRay should intersect at time " << (rl - x) << ". Center: " << center + << ", V: " << v << ", RL: " << rl << ", T:" << x << endl; + } + else { + cout << "\t\tRay should not intersect. Center: " << center << ", V: " << v + << ", RL: " << rl << endl; + } + } #endif - if (p->rayIntersect(center, u, t, t_u, t_v)) { + if (p->rayIntersect(center, u, t, t_u, t_v)) { #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\t\tRay " << center << " * " << u << " intersects at time " << t << " (raylength is " << - raylength << ")" << endl; - cout << "\t\t(u * normal) == " << (u * p->getNormal()) << " for normal " << p->getNormal() << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\t\tRay " << center << " * " << u << " intersects at time " << t + << " (raylength is " << raylength << ")" << endl; + cout << "\t\t(u * normal) == " << (u * p->getNormal()) << " for normal " << p->getNormal() + << endl; + } #endif - if (fabs(u * p->getNormal()) > 0.0001) { - if ((t > 0.0) && (t < raylength)) { + if (fabs(u * p->getNormal()) > 0.0001) { + if ((t > 0.0) && (t < raylength)) { #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\t\tIs occluder" << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\t\tIs occluder" << endl; + } #endif - if ( foundOccluders != NULL ) { - ViewShape *vshape = viewMap->viewShape(oface->GetVertex(0)->shape()->GetId()); - foundOccluders->insert(vshape); - } - ++qi; - - if (! grid.enableQI()) - break; - } - - occluders.reportDepth(center, u, t); - } - } - } - - // Find occludee - findOccludee<G, I>(fe, grid, occluders, epsilon, oaWFace, u, center, origin, edgeDir, faceVertices); - - return qi; + if (foundOccluders != NULL) { + ViewShape *vshape = viewMap->viewShape(oface->GetVertex(0)->shape()->GetId()); + foundOccluders->insert(vshape); + } + ++qi; + + if (!grid.enableQI()) + break; + } + + occluders.reportDepth(center, u, t); + } + } + } + + // Find occludee + findOccludee<G, I>( + fe, grid, occluders, epsilon, oaWFace, u, center, origin, edgeDir, faceVertices); + + return qi; } // computeCumulativeVisibility returns the lowest x such that the majority of FEdges have QI <= x @@ -400,1052 +418,1108 @@ static int computeVisibility(ViewMap *viewMap, FEdge *fe, G& grid, real epsilon, // FEdges are heavily occluded. computeCumulativeVisibility will treat this case as a QI of 22 because 3 out of // 6 occluders have QI <= 22. -template <typename G, typename I> -static void computeCumulativeVisibility(ViewMap *ioViewMap, G& grid, real epsilon, RenderMonitor *iRenderMonitor) +template<typename G, typename I> +static void computeCumulativeVisibility(ViewMap *ioViewMap, + G &grid, + real epsilon, + RenderMonitor *iRenderMonitor) { - vector<ViewEdge*>& vedges = ioViewMap->ViewEdges(); - - FEdge *fe, *festart; - int nSamples = 0; - vector<WFace*> wFaces; - WFace *wFace = NULL; - unsigned cnt = 0; - unsigned cntStep = (unsigned)ceil(0.01f * vedges.size()); - unsigned tmpQI = 0; - unsigned qiClasses[256]; - unsigned maxIndex, maxCard; - unsigned qiMajority; - for (vector<ViewEdge*>::iterator ve = vedges.begin(), veend = vedges.end(); ve != veend; ve++) { - if (iRenderMonitor) { - if (iRenderMonitor->testBreak()) - break; - if (cnt % cntStep == 0) { - stringstream ss; - ss << "Freestyle: Visibility computations " << (100 * cnt / vedges.size()) << "%"; - iRenderMonitor->setInfo(ss.str()); - iRenderMonitor->progress((float)cnt / vedges.size()); - } - cnt++; - } + vector<ViewEdge *> &vedges = ioViewMap->ViewEdges(); + + FEdge *fe, *festart; + int nSamples = 0; + vector<WFace *> wFaces; + WFace *wFace = NULL; + unsigned cnt = 0; + unsigned cntStep = (unsigned)ceil(0.01f * vedges.size()); + unsigned tmpQI = 0; + unsigned qiClasses[256]; + unsigned maxIndex, maxCard; + unsigned qiMajority; + for (vector<ViewEdge *>::iterator ve = vedges.begin(), veend = vedges.end(); ve != veend; ve++) { + if (iRenderMonitor) { + if (iRenderMonitor->testBreak()) + break; + if (cnt % cntStep == 0) { + stringstream ss; + ss << "Freestyle: Visibility computations " << (100 * cnt / vedges.size()) << "%"; + iRenderMonitor->setInfo(ss.str()); + iRenderMonitor->progress((float)cnt / vedges.size()); + } + cnt++; + } #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "Processing ViewEdge " << (*ve)->getId() << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "Processing ViewEdge " << (*ve)->getId() << endl; + } #endif - // Find an edge to test - if (!(*ve)->isInImage()) { - // This view edge has been proscenium culled - (*ve)->setQI(255); - (*ve)->setaShape(0); + // Find an edge to test + if (!(*ve)->isInImage()) { + // This view edge has been proscenium culled + (*ve)->setQI(255); + (*ve)->setaShape(0); #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\tCulled." << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\tCulled." << endl; + } #endif - continue; - } - - // Test edge - festart = (*ve)->fedgeA(); - fe = (*ve)->fedgeA(); - qiMajority = 0; - do { - if (fe != NULL && fe->isInImage()) { - qiMajority++; - } - fe = fe->nextEdge(); - } while (fe && fe != festart); - - if (qiMajority == 0) { - // There are no occludable FEdges on this ViewEdge - // This should be impossible. - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "View Edge in viewport without occludable FEdges: " << (*ve)->getId() << endl; - } - // We can recover from this error: - // Treat this edge as fully visible with no occludee - (*ve)->setQI(0); - (*ve)->setaShape(0); - continue; - } - else { - ++qiMajority; - qiMajority >>= 1; - } + continue; + } + + // Test edge + festart = (*ve)->fedgeA(); + fe = (*ve)->fedgeA(); + qiMajority = 0; + do { + if (fe != NULL && fe->isInImage()) { + qiMajority++; + } + fe = fe->nextEdge(); + } while (fe && fe != festart); + + if (qiMajority == 0) { + // There are no occludable FEdges on this ViewEdge + // This should be impossible. + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "View Edge in viewport without occludable FEdges: " << (*ve)->getId() << endl; + } + // We can recover from this error: + // Treat this edge as fully visible with no occludee + (*ve)->setQI(0); + (*ve)->setaShape(0); + continue; + } + else { + ++qiMajority; + qiMajority >>= 1; + } #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\tqiMajority: " << qiMajority << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\tqiMajority: " << qiMajority << endl; + } #endif - tmpQI = 0; - maxIndex = 0; - maxCard = 0; - nSamples = 0; - memset(qiClasses, 0, 256 * sizeof(*qiClasses)); - set<ViewShape*> foundOccluders; - - fe = (*ve)->fedgeA(); - do { - if (!fe || !fe->isInImage()) { - fe = fe->nextEdge(); - continue; - } - if ((maxCard < qiMajority)) { - //ARB: change &wFace to wFace and use reference in called function - tmpQI = computeVisibility<G, I>(ioViewMap, fe, grid, epsilon, *ve, &wFace, &foundOccluders); + tmpQI = 0; + maxIndex = 0; + maxCard = 0; + nSamples = 0; + memset(qiClasses, 0, 256 * sizeof(*qiClasses)); + set<ViewShape *> foundOccluders; + + fe = (*ve)->fedgeA(); + do { + if (!fe || !fe->isInImage()) { + fe = fe->nextEdge(); + continue; + } + if ((maxCard < qiMajority)) { + //ARB: change &wFace to wFace and use reference in called function + tmpQI = computeVisibility<G, I>( + ioViewMap, fe, grid, epsilon, *ve, &wFace, &foundOccluders); #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\tFEdge: visibility " << tmpQI << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\tFEdge: visibility " << tmpQI << endl; + } #endif - //ARB: This is an error condition, not an alert condition. - // Some sort of recovery or abort is necessary. - if (tmpQI >= 256) { - cerr << "Warning: too many occluding levels" << endl; - //ARB: Wild guess: instead of aborting or corrupting memory, treat as tmpQI == 255 - tmpQI = 255; - } - - if (++qiClasses[tmpQI] > maxCard) { - maxCard = qiClasses[tmpQI]; - maxIndex = tmpQI; - } - } - else { - //ARB: FindOccludee is redundant if ComputeRayCastingVisibility has been called - //ARB: change &wFace to wFace and use reference in called function - findOccludee<G, I>(fe, grid, epsilon, *ve, &wFace); + //ARB: This is an error condition, not an alert condition. + // Some sort of recovery or abort is necessary. + if (tmpQI >= 256) { + cerr << "Warning: too many occluding levels" << endl; + //ARB: Wild guess: instead of aborting or corrupting memory, treat as tmpQI == 255 + tmpQI = 255; + } + + if (++qiClasses[tmpQI] > maxCard) { + maxCard = qiClasses[tmpQI]; + maxIndex = tmpQI; + } + } + else { + //ARB: FindOccludee is redundant if ComputeRayCastingVisibility has been called + //ARB: change &wFace to wFace and use reference in called function + findOccludee<G, I>(fe, grid, epsilon, *ve, &wFace); #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\tFEdge: occludee only (" << (wFace != NULL ? "found" : "not found") << ")" << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\tFEdge: occludee only (" << (wFace != NULL ? "found" : "not found") << ")" + << endl; + } #endif - } - - // Store test results - if (wFace) { - vector<Vec3r> vertices; - for (int i = 0, numEdges = wFace->numberOfEdges(); i < numEdges; ++i) { - vertices.push_back(Vec3r(wFace->GetVertex(i)->GetVertex())); - } - Polygon3r poly(vertices, wFace->GetNormal()); - poly.userdata = (void *)wFace; - fe->setaFace(poly); - wFaces.push_back(wFace); - fe->setOccludeeEmpty(false); + } + + // Store test results + if (wFace) { + vector<Vec3r> vertices; + for (int i = 0, numEdges = wFace->numberOfEdges(); i < numEdges; ++i) { + vertices.push_back(Vec3r(wFace->GetVertex(i)->GetVertex())); + } + Polygon3r poly(vertices, wFace->GetNormal()); + poly.userdata = (void *)wFace; + fe->setaFace(poly); + wFaces.push_back(wFace); + fe->setOccludeeEmpty(false); #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\tFound occludee" << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\tFound occludee" << endl; + } #endif - } - else { - fe->setOccludeeEmpty(true); - } + } + else { + fe->setOccludeeEmpty(true); + } - ++nSamples; - fe = fe->nextEdge(); - } while ((maxCard < qiMajority) && (fe) && (fe != festart)); + ++nSamples; + fe = fe->nextEdge(); + } while ((maxCard < qiMajority) && (fe) && (fe != festart)); #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\tFinished with " << nSamples << " samples, maxCard = " << maxCard << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\tFinished with " << nSamples << " samples, maxCard = " << maxCard << endl; + } #endif - // ViewEdge - // qi -- - // Find the minimum value that is >= the majority of the QI - for (unsigned count = 0, i = 0; i < 256; ++i) { - count += qiClasses[i]; - if (count >= qiMajority) { - (*ve)->setQI(i); - break; - } - } - // occluders -- - // I would rather not have to go through the effort of creating this set and then copying out its contents. - // Is there a reason why ViewEdge::_Occluders cannot be converted to a set<>? - for (set<ViewShape*>::iterator o = foundOccluders.begin(), oend = foundOccluders.end(); o != oend; ++o) { - (*ve)->AddOccluder((*o)); - } + // ViewEdge + // qi -- + // Find the minimum value that is >= the majority of the QI + for (unsigned count = 0, i = 0; i < 256; ++i) { + count += qiClasses[i]; + if (count >= qiMajority) { + (*ve)->setQI(i); + break; + } + } + // occluders -- + // I would rather not have to go through the effort of creating this set and then copying out its contents. + // Is there a reason why ViewEdge::_Occluders cannot be converted to a set<>? + for (set<ViewShape *>::iterator o = foundOccluders.begin(), oend = foundOccluders.end(); + o != oend; + ++o) { + (*ve)->AddOccluder((*o)); + } #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\tConclusion: QI = " << maxIndex << ", " << (*ve)->occluders_size() << " occluders." << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\tConclusion: QI = " << maxIndex << ", " << (*ve)->occluders_size() << " occluders." + << endl; + } #else - (void)maxIndex; + (void)maxIndex; #endif - // occludee -- - if (!wFaces.empty()) { - if (wFaces.size() <= (float)nSamples / 2.0f) { - (*ve)->setaShape(0); - } - else { - ViewShape *vshape = ioViewMap->viewShape((*wFaces.begin())->GetVertex(0)->shape()->GetId()); - (*ve)->setaShape(vshape); - } - } - - wFaces.clear(); - } - if (iRenderMonitor && vedges.size()) { - stringstream ss; - ss << "Freestyle: Visibility computations " << (100 * cnt / vedges.size()) << "%"; - iRenderMonitor->setInfo(ss.str()); - iRenderMonitor->progress((float)cnt / vedges.size()); - } + // occludee -- + if (!wFaces.empty()) { + if (wFaces.size() <= (float)nSamples / 2.0f) { + (*ve)->setaShape(0); + } + else { + ViewShape *vshape = ioViewMap->viewShape( + (*wFaces.begin())->GetVertex(0)->shape()->GetId()); + (*ve)->setaShape(vshape); + } + } + + wFaces.clear(); + } + if (iRenderMonitor && vedges.size()) { + stringstream ss; + ss << "Freestyle: Visibility computations " << (100 * cnt / vedges.size()) << "%"; + iRenderMonitor->setInfo(ss.str()); + iRenderMonitor->progress((float)cnt / vedges.size()); + } } -template <typename G, typename I> -static void computeDetailedVisibility(ViewMap *ioViewMap, G& grid, real epsilon, RenderMonitor *iRenderMonitor) +template<typename G, typename I> +static void computeDetailedVisibility(ViewMap *ioViewMap, + G &grid, + real epsilon, + RenderMonitor *iRenderMonitor) { - vector<ViewEdge*>& vedges = ioViewMap->ViewEdges(); - - FEdge *fe, *festart; - int nSamples = 0; - vector<WFace*> wFaces; - WFace *wFace = NULL; - unsigned tmpQI = 0; - unsigned qiClasses[256]; - unsigned maxIndex, maxCard; - unsigned qiMajority; - for (vector<ViewEdge*>::iterator ve = vedges.begin(), veend = vedges.end(); ve != veend; ve++) { - if (iRenderMonitor && iRenderMonitor->testBreak()) - break; + vector<ViewEdge *> &vedges = ioViewMap->ViewEdges(); + + FEdge *fe, *festart; + int nSamples = 0; + vector<WFace *> wFaces; + WFace *wFace = NULL; + unsigned tmpQI = 0; + unsigned qiClasses[256]; + unsigned maxIndex, maxCard; + unsigned qiMajority; + for (vector<ViewEdge *>::iterator ve = vedges.begin(), veend = vedges.end(); ve != veend; ve++) { + if (iRenderMonitor && iRenderMonitor->testBreak()) + break; #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "Processing ViewEdge " << (*ve)->getId() << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "Processing ViewEdge " << (*ve)->getId() << endl; + } #endif - // Find an edge to test - if (!(*ve)->isInImage()) { - // This view edge has been proscenium culled - (*ve)->setQI(255); - (*ve)->setaShape(0); + // Find an edge to test + if (!(*ve)->isInImage()) { + // This view edge has been proscenium culled + (*ve)->setQI(255); + (*ve)->setaShape(0); #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\tCulled." << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\tCulled." << endl; + } #endif - continue; - } - - // Test edge - festart = (*ve)->fedgeA(); - fe = (*ve)->fedgeA(); - qiMajority = 0; - do { - if (fe != NULL && fe->isInImage()) { - qiMajority++; - } - fe = fe->nextEdge(); - } while (fe && fe != festart); - - if (qiMajority == 0) { - // There are no occludable FEdges on this ViewEdge - // This should be impossible. - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "View Edge in viewport without occludable FEdges: " << (*ve)->getId() << endl; - } - // We can recover from this error: - // Treat this edge as fully visible with no occludee - (*ve)->setQI(0); - (*ve)->setaShape(0); - continue; - } - else { - ++qiMajority; - qiMajority >>= 1; - } + continue; + } + + // Test edge + festart = (*ve)->fedgeA(); + fe = (*ve)->fedgeA(); + qiMajority = 0; + do { + if (fe != NULL && fe->isInImage()) { + qiMajority++; + } + fe = fe->nextEdge(); + } while (fe && fe != festart); + + if (qiMajority == 0) { + // There are no occludable FEdges on this ViewEdge + // This should be impossible. + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "View Edge in viewport without occludable FEdges: " << (*ve)->getId() << endl; + } + // We can recover from this error: + // Treat this edge as fully visible with no occludee + (*ve)->setQI(0); + (*ve)->setaShape(0); + continue; + } + else { + ++qiMajority; + qiMajority >>= 1; + } #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\tqiMajority: " << qiMajority << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\tqiMajority: " << qiMajority << endl; + } #endif - tmpQI = 0; - maxIndex = 0; - maxCard = 0; - nSamples = 0; - memset(qiClasses, 0, 256 * sizeof(*qiClasses)); - set<ViewShape*> foundOccluders; - - fe = (*ve)->fedgeA(); - do { - if (fe == NULL || ! fe->isInImage()) { - fe = fe->nextEdge(); - continue; - } - if ((maxCard < qiMajority)) { - //ARB: change &wFace to wFace and use reference in called function - tmpQI = computeVisibility<G, I>(ioViewMap, fe, grid, epsilon, *ve, &wFace, &foundOccluders); + tmpQI = 0; + maxIndex = 0; + maxCard = 0; + nSamples = 0; + memset(qiClasses, 0, 256 * sizeof(*qiClasses)); + set<ViewShape *> foundOccluders; + + fe = (*ve)->fedgeA(); + do { + if (fe == NULL || !fe->isInImage()) { + fe = fe->nextEdge(); + continue; + } + if ((maxCard < qiMajority)) { + //ARB: change &wFace to wFace and use reference in called function + tmpQI = computeVisibility<G, I>( + ioViewMap, fe, grid, epsilon, *ve, &wFace, &foundOccluders); #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\tFEdge: visibility " << tmpQI << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\tFEdge: visibility " << tmpQI << endl; + } #endif - //ARB: This is an error condition, not an alert condition. - // Some sort of recovery or abort is necessary. - if (tmpQI >= 256) { - cerr << "Warning: too many occluding levels" << endl; - //ARB: Wild guess: instead of aborting or corrupting memory, treat as tmpQI == 255 - tmpQI = 255; - } - - if (++qiClasses[tmpQI] > maxCard) { - maxCard = qiClasses[tmpQI]; - maxIndex = tmpQI; - } - } - else { - //ARB: FindOccludee is redundant if ComputeRayCastingVisibility has been called - //ARB: change &wFace to wFace and use reference in called function - findOccludee<G, I>(fe, grid, epsilon, *ve, &wFace); + //ARB: This is an error condition, not an alert condition. + // Some sort of recovery or abort is necessary. + if (tmpQI >= 256) { + cerr << "Warning: too many occluding levels" << endl; + //ARB: Wild guess: instead of aborting or corrupting memory, treat as tmpQI == 255 + tmpQI = 255; + } + + if (++qiClasses[tmpQI] > maxCard) { + maxCard = qiClasses[tmpQI]; + maxIndex = tmpQI; + } + } + else { + //ARB: FindOccludee is redundant if ComputeRayCastingVisibility has been called + //ARB: change &wFace to wFace and use reference in called function + findOccludee<G, I>(fe, grid, epsilon, *ve, &wFace); #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\tFEdge: occludee only (" << (wFace != NULL ? "found" : "not found") << ")" << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\tFEdge: occludee only (" << (wFace != NULL ? "found" : "not found") << ")" + << endl; + } #endif - } - - // Store test results - if (wFace) { - vector<Vec3r> vertices; - for (int i = 0, numEdges = wFace->numberOfEdges(); i < numEdges; ++i) { - vertices.push_back(Vec3r(wFace->GetVertex(i)->GetVertex())); - } - Polygon3r poly(vertices, wFace->GetNormal()); - poly.userdata = (void *)wFace; - fe->setaFace(poly); - wFaces.push_back(wFace); - fe->setOccludeeEmpty(false); + } + + // Store test results + if (wFace) { + vector<Vec3r> vertices; + for (int i = 0, numEdges = wFace->numberOfEdges(); i < numEdges; ++i) { + vertices.push_back(Vec3r(wFace->GetVertex(i)->GetVertex())); + } + Polygon3r poly(vertices, wFace->GetNormal()); + poly.userdata = (void *)wFace; + fe->setaFace(poly); + wFaces.push_back(wFace); + fe->setOccludeeEmpty(false); #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\tFound occludee" << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\tFound occludee" << endl; + } #endif - } - else { - fe->setOccludeeEmpty(true); - } + } + else { + fe->setOccludeeEmpty(true); + } - ++nSamples; - fe = fe->nextEdge(); - } while ((maxCard < qiMajority) && (fe) && (fe != festart)); + ++nSamples; + fe = fe->nextEdge(); + } while ((maxCard < qiMajority) && (fe) && (fe != festart)); #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\tFinished with " << nSamples << " samples, maxCard = " << maxCard << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\tFinished with " << nSamples << " samples, maxCard = " << maxCard << endl; + } #endif - // ViewEdge - // qi -- - (*ve)->setQI(maxIndex); - // occluders -- - // I would rather not have to go through the effort of creating this this set and then copying out its contents. - // Is there a reason why ViewEdge::_Occluders cannot be converted to a set<>? - for (set<ViewShape*>::iterator o = foundOccluders.begin(), oend = foundOccluders.end(); o != oend; ++o) { - (*ve)->AddOccluder((*o)); - } + // ViewEdge + // qi -- + (*ve)->setQI(maxIndex); + // occluders -- + // I would rather not have to go through the effort of creating this this set and then copying out its contents. + // Is there a reason why ViewEdge::_Occluders cannot be converted to a set<>? + for (set<ViewShape *>::iterator o = foundOccluders.begin(), oend = foundOccluders.end(); + o != oend; + ++o) { + (*ve)->AddOccluder((*o)); + } #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\tConclusion: QI = " << maxIndex << ", " << (*ve)->occluders_size() << " occluders." << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\tConclusion: QI = " << maxIndex << ", " << (*ve)->occluders_size() << " occluders." + << endl; + } #endif - // occludee -- - if (!wFaces.empty()) { - if (wFaces.size() <= (float)nSamples / 2.0f) { - (*ve)->setaShape(0); - } - else { - ViewShape *vshape = ioViewMap->viewShape((*wFaces.begin())->GetVertex(0)->shape()->GetId()); - (*ve)->setaShape(vshape); - } - } - - wFaces.clear(); - } + // occludee -- + if (!wFaces.empty()) { + if (wFaces.size() <= (float)nSamples / 2.0f) { + (*ve)->setaShape(0); + } + else { + ViewShape *vshape = ioViewMap->viewShape( + (*wFaces.begin())->GetVertex(0)->shape()->GetId()); + (*ve)->setaShape(vshape); + } + } + + wFaces.clear(); + } } -template <typename G, typename I> -static void computeFastVisibility(ViewMap *ioViewMap, G& grid, real epsilon) +template<typename G, typename I> +static void computeFastVisibility(ViewMap *ioViewMap, G &grid, real epsilon) { - vector<ViewEdge*>& vedges = ioViewMap->ViewEdges(); - - FEdge *fe, *festart; - unsigned nSamples = 0; - vector<WFace*> wFaces; - WFace *wFace = NULL; - unsigned tmpQI = 0; - unsigned qiClasses[256]; - unsigned maxIndex, maxCard; - unsigned qiMajority; - bool even_test; - for (vector<ViewEdge*>::iterator ve = vedges.begin(), veend = vedges.end(); ve != veend; ve++) { - // Find an edge to test - if (!(*ve)->isInImage()) { - // This view edge has been proscenium culled - (*ve)->setQI(255); - (*ve)->setaShape(0); - continue; - } - - // Test edge - festart = (*ve)->fedgeA(); - fe = (*ve)->fedgeA(); - - even_test = true; - qiMajority = 0; - do { - if (even_test && fe && fe->isInImage()) { - qiMajority++; - even_test = !even_test; - } - fe = fe->nextEdge(); - } while (fe && fe != festart); - - if (qiMajority == 0 ) { - // There are no occludable FEdges on this ViewEdge - // This should be impossible. - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "View Edge in viewport without occludable FEdges: " << (*ve)->getId() << endl; - } - // We can recover from this error: - // Treat this edge as fully visible with no occludee - (*ve)->setQI(0); - (*ve)->setaShape(0); - continue; - } - else { - ++qiMajority; - qiMajority >>= 1; - } - - even_test = true; - maxIndex = 0; - maxCard = 0; - nSamples = 0; - memset(qiClasses, 0, 256 * sizeof(*qiClasses)); - set<ViewShape*> foundOccluders; - - fe = (*ve)->fedgeA(); - do { - if (!fe || !fe->isInImage()) { - fe = fe->nextEdge(); - continue; - } - if (even_test) { - if ((maxCard < qiMajority)) { - //ARB: change &wFace to wFace and use reference in called function - tmpQI = computeVisibility<G, I>(ioViewMap, fe, grid, epsilon, *ve, &wFace, &foundOccluders); - - //ARB: This is an error condition, not an alert condition. - // Some sort of recovery or abort is necessary. - if (tmpQI >= 256) { - cerr << "Warning: too many occluding levels" << endl; - //ARB: Wild guess: instead of aborting or corrupting memory, treat as tmpQI == 255 - tmpQI = 255; - } - - if (++qiClasses[tmpQI] > maxCard) { - maxCard = qiClasses[tmpQI]; - maxIndex = tmpQI; - } - } - else { - //ARB: FindOccludee is redundant if ComputeRayCastingVisibility has been called - //ARB: change &wFace to wFace and use reference in called function - findOccludee<G, I>(fe, grid, epsilon, *ve, &wFace); - } - - if (wFace) { - vector<Vec3r> vertices; - for (int i = 0, numEdges = wFace->numberOfEdges(); i < numEdges; ++i) { - vertices.push_back(Vec3r(wFace->GetVertex(i)->GetVertex())); - } - Polygon3r poly(vertices, wFace->GetNormal()); - poly.userdata = (void *)wFace; - fe->setaFace(poly); - wFaces.push_back(wFace); - } - ++nSamples; - } - - even_test = ! even_test; - fe = fe->nextEdge(); - } while ((maxCard < qiMajority) && (fe) && (fe != festart)); - - // qi -- - (*ve)->setQI(maxIndex); - - // occluders -- - for (set<ViewShape*>::iterator o = foundOccluders.begin(), oend = foundOccluders.end(); o != oend; ++o) { - (*ve)->AddOccluder((*o)); - } - - // occludee -- - if (!wFaces.empty()) { - if (wFaces.size() < nSamples / 2) { - (*ve)->setaShape(0); - } - else { - ViewShape *vshape = ioViewMap->viewShape((*wFaces.begin())->GetVertex(0)->shape()->GetId()); - (*ve)->setaShape(vshape); - } - } - - wFaces.clear(); - } + vector<ViewEdge *> &vedges = ioViewMap->ViewEdges(); + + FEdge *fe, *festart; + unsigned nSamples = 0; + vector<WFace *> wFaces; + WFace *wFace = NULL; + unsigned tmpQI = 0; + unsigned qiClasses[256]; + unsigned maxIndex, maxCard; + unsigned qiMajority; + bool even_test; + for (vector<ViewEdge *>::iterator ve = vedges.begin(), veend = vedges.end(); ve != veend; ve++) { + // Find an edge to test + if (!(*ve)->isInImage()) { + // This view edge has been proscenium culled + (*ve)->setQI(255); + (*ve)->setaShape(0); + continue; + } + + // Test edge + festart = (*ve)->fedgeA(); + fe = (*ve)->fedgeA(); + + even_test = true; + qiMajority = 0; + do { + if (even_test && fe && fe->isInImage()) { + qiMajority++; + even_test = !even_test; + } + fe = fe->nextEdge(); + } while (fe && fe != festart); + + if (qiMajority == 0) { + // There are no occludable FEdges on this ViewEdge + // This should be impossible. + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "View Edge in viewport without occludable FEdges: " << (*ve)->getId() << endl; + } + // We can recover from this error: + // Treat this edge as fully visible with no occludee + (*ve)->setQI(0); + (*ve)->setaShape(0); + continue; + } + else { + ++qiMajority; + qiMajority >>= 1; + } + + even_test = true; + maxIndex = 0; + maxCard = 0; + nSamples = 0; + memset(qiClasses, 0, 256 * sizeof(*qiClasses)); + set<ViewShape *> foundOccluders; + + fe = (*ve)->fedgeA(); + do { + if (!fe || !fe->isInImage()) { + fe = fe->nextEdge(); + continue; + } + if (even_test) { + if ((maxCard < qiMajority)) { + //ARB: change &wFace to wFace and use reference in called function + tmpQI = computeVisibility<G, I>( + ioViewMap, fe, grid, epsilon, *ve, &wFace, &foundOccluders); + + //ARB: This is an error condition, not an alert condition. + // Some sort of recovery or abort is necessary. + if (tmpQI >= 256) { + cerr << "Warning: too many occluding levels" << endl; + //ARB: Wild guess: instead of aborting or corrupting memory, treat as tmpQI == 255 + tmpQI = 255; + } + + if (++qiClasses[tmpQI] > maxCard) { + maxCard = qiClasses[tmpQI]; + maxIndex = tmpQI; + } + } + else { + //ARB: FindOccludee is redundant if ComputeRayCastingVisibility has been called + //ARB: change &wFace to wFace and use reference in called function + findOccludee<G, I>(fe, grid, epsilon, *ve, &wFace); + } + + if (wFace) { + vector<Vec3r> vertices; + for (int i = 0, numEdges = wFace->numberOfEdges(); i < numEdges; ++i) { + vertices.push_back(Vec3r(wFace->GetVertex(i)->GetVertex())); + } + Polygon3r poly(vertices, wFace->GetNormal()); + poly.userdata = (void *)wFace; + fe->setaFace(poly); + wFaces.push_back(wFace); + } + ++nSamples; + } + + even_test = !even_test; + fe = fe->nextEdge(); + } while ((maxCard < qiMajority) && (fe) && (fe != festart)); + + // qi -- + (*ve)->setQI(maxIndex); + + // occluders -- + for (set<ViewShape *>::iterator o = foundOccluders.begin(), oend = foundOccluders.end(); + o != oend; + ++o) { + (*ve)->AddOccluder((*o)); + } + + // occludee -- + if (!wFaces.empty()) { + if (wFaces.size() < nSamples / 2) { + (*ve)->setaShape(0); + } + else { + ViewShape *vshape = ioViewMap->viewShape( + (*wFaces.begin())->GetVertex(0)->shape()->GetId()); + (*ve)->setaShape(vshape); + } + } + + wFaces.clear(); + } } -template <typename G, typename I> -static void computeVeryFastVisibility(ViewMap *ioViewMap, G& grid, real epsilon) +template<typename G, typename I> +static void computeVeryFastVisibility(ViewMap *ioViewMap, G &grid, real epsilon) { - vector<ViewEdge*>& vedges = ioViewMap->ViewEdges(); - - FEdge *fe; - unsigned qi = 0; - WFace *wFace = 0; - - for (vector<ViewEdge*>::iterator ve = vedges.begin(), veend = vedges.end(); ve != veend; ve++) { - // Find an edge to test - if (!(*ve)->isInImage()) { - // This view edge has been proscenium culled - (*ve)->setQI(255); - (*ve)->setaShape(0); - continue; - } - fe = (*ve)->fedgeA(); - // Find a FEdge inside the occluder proscenium to test for visibility - FEdge *festart = fe; - while (fe && !fe->isInImage() && fe != festart) { - fe = fe->nextEdge(); - } - - // Test edge - if (!fe || !fe->isInImage()) { - // There are no occludable FEdges on this ViewEdge - // This should be impossible. - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "View Edge in viewport without occludable FEdges: " << (*ve)->getId() << endl; - } - // We can recover from this error: - // Treat this edge as fully visible with no occludee - qi = 0; - wFace = NULL; - } - else { - qi = computeVisibility<G, I>(ioViewMap, fe, grid, epsilon, *ve, &wFace, NULL); - } - - // Store test results - if (wFace) { - vector<Vec3r> vertices; - for (int i = 0, numEdges = wFace->numberOfEdges(); i < numEdges; ++i) { - vertices.push_back(Vec3r(wFace->GetVertex(i)->GetVertex())); - } - Polygon3r poly(vertices, wFace->GetNormal()); - poly.userdata = (void *)wFace; - fe->setaFace(poly); // This works because setaFace *copies* the polygon - ViewShape *vshape = ioViewMap->viewShape(wFace->GetVertex(0)->shape()->GetId()); - (*ve)->setaShape(vshape); - } - else { - (*ve)->setaShape(0); - } - (*ve)->setQI(qi); - } + vector<ViewEdge *> &vedges = ioViewMap->ViewEdges(); + + FEdge *fe; + unsigned qi = 0; + WFace *wFace = 0; + + for (vector<ViewEdge *>::iterator ve = vedges.begin(), veend = vedges.end(); ve != veend; ve++) { + // Find an edge to test + if (!(*ve)->isInImage()) { + // This view edge has been proscenium culled + (*ve)->setQI(255); + (*ve)->setaShape(0); + continue; + } + fe = (*ve)->fedgeA(); + // Find a FEdge inside the occluder proscenium to test for visibility + FEdge *festart = fe; + while (fe && !fe->isInImage() && fe != festart) { + fe = fe->nextEdge(); + } + + // Test edge + if (!fe || !fe->isInImage()) { + // There are no occludable FEdges on this ViewEdge + // This should be impossible. + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "View Edge in viewport without occludable FEdges: " << (*ve)->getId() << endl; + } + // We can recover from this error: + // Treat this edge as fully visible with no occludee + qi = 0; + wFace = NULL; + } + else { + qi = computeVisibility<G, I>(ioViewMap, fe, grid, epsilon, *ve, &wFace, NULL); + } + + // Store test results + if (wFace) { + vector<Vec3r> vertices; + for (int i = 0, numEdges = wFace->numberOfEdges(); i < numEdges; ++i) { + vertices.push_back(Vec3r(wFace->GetVertex(i)->GetVertex())); + } + Polygon3r poly(vertices, wFace->GetNormal()); + poly.userdata = (void *)wFace; + fe->setaFace(poly); // This works because setaFace *copies* the polygon + ViewShape *vshape = ioViewMap->viewShape(wFace->GetVertex(0)->shape()->GetId()); + (*ve)->setaShape(vshape); + } + else { + (*ve)->setaShape(0); + } + (*ve)->setQI(qi); + } } -void ViewMapBuilder::BuildGrid(WingedEdge& we, const BBox<Vec3r>& bbox, unsigned int sceneNumFaces) +void ViewMapBuilder::BuildGrid(WingedEdge &we, const BBox<Vec3r> &bbox, unsigned int sceneNumFaces) { - _Grid->clear(); - Vec3r size; - for (unsigned int i = 0; i < 3; i++) { - size[i] = fabs(bbox.getMax()[i] - bbox.getMin()[i]); - // let make the grid 1/10 bigger to avoid numerical errors while computing triangles/cells intersections. - size[i] += size[i] / 10.0; - if (size[i] == 0) { - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "Warning: the bbox size is 0 in dimension " << i << endl; - } - } - } - _Grid->configure(Vec3r(bbox.getMin() - size / 20.0), size, sceneNumFaces); - - // Fill in the grid: - WFillGrid fillGridRenderer(_Grid, &we); - fillGridRenderer.fillGrid(); - - // DEBUG - _Grid->displayDebug(); + _Grid->clear(); + Vec3r size; + for (unsigned int i = 0; i < 3; i++) { + size[i] = fabs(bbox.getMax()[i] - bbox.getMin()[i]); + // let make the grid 1/10 bigger to avoid numerical errors while computing triangles/cells intersections. + size[i] += size[i] / 10.0; + if (size[i] == 0) { + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "Warning: the bbox size is 0 in dimension " << i << endl; + } + } + } + _Grid->configure(Vec3r(bbox.getMin() - size / 20.0), size, sceneNumFaces); + + // Fill in the grid: + WFillGrid fillGridRenderer(_Grid, &we); + fillGridRenderer.fillGrid(); + + // DEBUG + _Grid->displayDebug(); } -ViewMap *ViewMapBuilder::BuildViewMap(WingedEdge& we, visibility_algo iAlgo, real epsilon, - const BBox<Vec3r>& bbox, unsigned int sceneNumFaces) +ViewMap *ViewMapBuilder::BuildViewMap(WingedEdge &we, + visibility_algo iAlgo, + real epsilon, + const BBox<Vec3r> &bbox, + unsigned int sceneNumFaces) { - _ViewMap = new ViewMap; - _currentId = 1; - _currentFId = 0; - _currentSVertexId = 0; + _ViewMap = new ViewMap; + _currentId = 1; + _currentFId = 0; + _currentSVertexId = 0; - // Builds initial view edges - computeInitialViewEdges(we); + // Builds initial view edges + computeInitialViewEdges(we); - // Detects cusps - computeCusps(_ViewMap); + // Detects cusps + computeCusps(_ViewMap); - // Compute intersections - ComputeIntersections(_ViewMap, sweep_line, epsilon); + // Compute intersections + ComputeIntersections(_ViewMap, sweep_line, epsilon); - // Compute visibility - ComputeEdgesVisibility(_ViewMap, we, bbox, sceneNumFaces, iAlgo, epsilon); + // Compute visibility + ComputeEdgesVisibility(_ViewMap, we, bbox, sceneNumFaces, iAlgo, epsilon); - return _ViewMap; + return _ViewMap; } -static inline real distance2D(const Vec3r & point, const real origin[2]) +static inline real distance2D(const Vec3r &point, const real origin[2]) { - return ::hypot((point[0] - origin[0]), (point[1] - origin[1])); + return ::hypot((point[0] - origin[0]), (point[1] - origin[1])); } static inline bool crossesProscenium(real proscenium[4], FEdge *fe) { - Vec2r min(proscenium[0], proscenium[2]); - Vec2r max(proscenium[1], proscenium[3]); - Vec2r A(fe->vertexA()->getProjectedX(), fe->vertexA()->getProjectedY()); - Vec2r B(fe->vertexB()->getProjectedX(), fe->vertexB()->getProjectedY()); + Vec2r min(proscenium[0], proscenium[2]); + Vec2r max(proscenium[1], proscenium[3]); + Vec2r A(fe->vertexA()->getProjectedX(), fe->vertexA()->getProjectedY()); + Vec2r B(fe->vertexB()->getProjectedX(), fe->vertexB()->getProjectedY()); - return GeomUtils::intersect2dSeg2dArea (min, max, A, B); + return GeomUtils::intersect2dSeg2dArea(min, max, A, B); } -static inline bool insideProscenium(real proscenium[4], const Vec3r& point) +static inline bool insideProscenium(real proscenium[4], const Vec3r &point) { - return !(point[0] < proscenium[0] || point[0] > proscenium[1] || - point[1] < proscenium[2] || point[1] > proscenium[3]); + return !(point[0] < proscenium[0] || point[0] > proscenium[1] || point[1] < proscenium[2] || + point[1] > proscenium[3]); } -void ViewMapBuilder::CullViewEdges(ViewMap *ioViewMap, real viewProscenium[4], real occluderProscenium[4], +void ViewMapBuilder::CullViewEdges(ViewMap *ioViewMap, + real viewProscenium[4], + real occluderProscenium[4], bool extensiveFEdgeSearch) { - // Cull view edges by marking them as non-displayable. - // This avoids the complications of trying to delete edges from the ViewMap. - - // Non-displayable view edges will be skipped over during visibility calculation. - - // View edges will be culled according to their position w.r.t. the viewport proscenium (viewport + 5% border, - // or some such). - - // Get proscenium boundary for culling - GridHelpers::getDefaultViewProscenium(viewProscenium); - real prosceniumOrigin[2]; - prosceniumOrigin[0] = (viewProscenium[1] - viewProscenium[0]) / 2.0; - prosceniumOrigin[1] = (viewProscenium[3] - viewProscenium[2]) / 2.0; - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "Proscenium culling:" << endl; - cout << "Proscenium: [" << viewProscenium[0] << ", " << viewProscenium[1] << ", " << viewProscenium[2] << - ", " << viewProscenium[3] << "]"<< endl; - cout << "Origin: [" << prosceniumOrigin[0] << ", " << prosceniumOrigin[1] << "]"<< endl; - } - - // A separate occluder proscenium will also be maintained, starting out the same as the viewport proscenium, and - // expanding as necessary so that it encompasses the center point of at least one feature edge in each retained view - // edge. - // The occluder proscenium will be used later to cull occluding triangles before they are inserted into the Grid. - // The occluder proscenium starts out the same size as the view proscenium - GridHelpers::getDefaultViewProscenium(occluderProscenium); - - // N.B. Freestyle is inconsistent in its use of ViewMap::viewedges_container and vector<ViewEdge*>::iterator. - // Probably all occurences of vector<ViewEdge*>::iterator should be replaced ViewMap::viewedges_container - // throughout the code. - // For each view edge - ViewMap::viewedges_container::iterator ve, veend; - - for (ve = ioViewMap->ViewEdges().begin(), veend = ioViewMap->ViewEdges().end(); ve != veend; ve++) { - // Overview: - // Search for a visible feature edge - // If none: mark view edge as non-displayable - // Otherwise: - // Find a feature edge with center point inside occluder proscenium. - // If none exists, find the feature edge with center point closest to viewport origin. - // Expand occluder proscenium to enclose center point. - - // For each feature edge, while bestOccluderTarget not found and view edge not visibile - bool bestOccluderTargetFound = false; - FEdge *bestOccluderTarget = NULL; - real bestOccluderDistance = 0.0; - FEdge *festart = (*ve)->fedgeA(); - FEdge *fe = festart; - // All ViewEdges start culled - (*ve)->setIsInImage(false); - - // For simple visibility calculation: mark a feature edge that is known to have a center point inside the - // occluder proscenium. Cull all other feature edges. - do { - // All FEdges start culled - fe->setIsInImage(false); - - // Look for the visible edge that can most easily be included in the occluder proscenium. - if (!bestOccluderTargetFound) { - // If center point is inside occluder proscenium, - if (insideProscenium(occluderProscenium, fe->center2d())) { - // Use this feature edge for visibility deterimination - fe->setIsInImage(true); - // Mark bestOccluderTarget as found - bestOccluderTargetFound = true; - bestOccluderTarget = fe; - } - else { - real d = distance2D(fe->center2d(), prosceniumOrigin); - // If center point is closer to viewport origin than current target - if (bestOccluderTarget == NULL || d < bestOccluderDistance) { - // Then store as bestOccluderTarget - bestOccluderDistance = d; - bestOccluderTarget = fe; - } - } - } - - // If feature edge crosses the view proscenium - if (!(*ve)->isInImage() && crossesProscenium(viewProscenium, fe)) { - // Then the view edge will be included in the image - (*ve)->setIsInImage(true); - } - fe = fe->nextEdge(); - } while (fe && fe != festart && !(bestOccluderTargetFound && (*ve)->isInImage())); - - // Either we have run out of FEdges, or we already have the one edge we need to determine visibility - // Cull all remaining edges. - while (fe && fe != festart) { - fe->setIsInImage(false); - fe = fe->nextEdge(); - } - - // If bestOccluderTarget was not found inside the occluder proscenium, we need to expand the occluder - // proscenium to include it. - if ((*ve)->isInImage() && bestOccluderTarget != NULL && !bestOccluderTargetFound) { - // Expand occluder proscenium to enclose bestOccluderTarget - Vec3r point = bestOccluderTarget->center2d(); - if (point[0] < occluderProscenium[0]) { - occluderProscenium[0] = point[0]; - } - else if (point[0] > occluderProscenium[1]) { - occluderProscenium[1] = point[0]; - } - if (point[1] < occluderProscenium[2]) { - occluderProscenium[2] = point[1]; - } - else if (point[1] > occluderProscenium[3]) { - occluderProscenium[3] = point[1]; - } - // Use bestOccluderTarget for visibility determination - bestOccluderTarget->setIsInImage(true); - } - } - - // We are done calculating the occluder proscenium. - // Expand the occluder proscenium by an epsilon to avoid rounding errors. - const real epsilon = 1.0e-6; - occluderProscenium[0] -= epsilon; - occluderProscenium[1] += epsilon; - occluderProscenium[2] -= epsilon; - occluderProscenium[3] += epsilon; - - // For "Normal" or "Fast" style visibility computation only: - - // For more detailed visibility calculation, make a second pass through the view map, marking all feature edges - // with center points inside the final occluder proscenium. All of these feature edges can be considered during - // visibility calculation. - - // So far we have only found one FEdge per ViewEdge. The "Normal" and "Fast" styles of visibility computation - // want to consider many FEdges for each ViewEdge. - // Here we re-scan the view map to find any usable FEdges that we skipped on the first pass, or that have become - // usable because the occluder proscenium has been expanded since the edge was visited on the first pass. - if (extensiveFEdgeSearch) { - // For each view edge, - for (ve = ioViewMap->ViewEdges().begin(), veend = ioViewMap->ViewEdges().end(); ve != veend; ve++) { - if (!(*ve)->isInImage()) { - continue; - } - // For each feature edge, - FEdge *festart = (*ve)->fedgeA(); - FEdge *fe = festart; - do { - // If not (already) visible and center point inside occluder proscenium, - if (!fe->isInImage() && insideProscenium(occluderProscenium, fe->center2d())) { - // Use the feature edge for visibility determination - fe->setIsInImage(true); - } - fe = fe->nextEdge(); - } while (fe && fe != festart); - } - } + // Cull view edges by marking them as non-displayable. + // This avoids the complications of trying to delete edges from the ViewMap. + + // Non-displayable view edges will be skipped over during visibility calculation. + + // View edges will be culled according to their position w.r.t. the viewport proscenium (viewport + 5% border, + // or some such). + + // Get proscenium boundary for culling + GridHelpers::getDefaultViewProscenium(viewProscenium); + real prosceniumOrigin[2]; + prosceniumOrigin[0] = (viewProscenium[1] - viewProscenium[0]) / 2.0; + prosceniumOrigin[1] = (viewProscenium[3] - viewProscenium[2]) / 2.0; + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "Proscenium culling:" << endl; + cout << "Proscenium: [" << viewProscenium[0] << ", " << viewProscenium[1] << ", " + << viewProscenium[2] << ", " << viewProscenium[3] << "]" << endl; + cout << "Origin: [" << prosceniumOrigin[0] << ", " << prosceniumOrigin[1] << "]" << endl; + } + + // A separate occluder proscenium will also be maintained, starting out the same as the viewport proscenium, and + // expanding as necessary so that it encompasses the center point of at least one feature edge in each retained view + // edge. + // The occluder proscenium will be used later to cull occluding triangles before they are inserted into the Grid. + // The occluder proscenium starts out the same size as the view proscenium + GridHelpers::getDefaultViewProscenium(occluderProscenium); + + // N.B. Freestyle is inconsistent in its use of ViewMap::viewedges_container and vector<ViewEdge*>::iterator. + // Probably all occurences of vector<ViewEdge*>::iterator should be replaced ViewMap::viewedges_container + // throughout the code. + // For each view edge + ViewMap::viewedges_container::iterator ve, veend; + + for (ve = ioViewMap->ViewEdges().begin(), veend = ioViewMap->ViewEdges().end(); ve != veend; + ve++) { + // Overview: + // Search for a visible feature edge + // If none: mark view edge as non-displayable + // Otherwise: + // Find a feature edge with center point inside occluder proscenium. + // If none exists, find the feature edge with center point closest to viewport origin. + // Expand occluder proscenium to enclose center point. + + // For each feature edge, while bestOccluderTarget not found and view edge not visibile + bool bestOccluderTargetFound = false; + FEdge *bestOccluderTarget = NULL; + real bestOccluderDistance = 0.0; + FEdge *festart = (*ve)->fedgeA(); + FEdge *fe = festart; + // All ViewEdges start culled + (*ve)->setIsInImage(false); + + // For simple visibility calculation: mark a feature edge that is known to have a center point inside the + // occluder proscenium. Cull all other feature edges. + do { + // All FEdges start culled + fe->setIsInImage(false); + + // Look for the visible edge that can most easily be included in the occluder proscenium. + if (!bestOccluderTargetFound) { + // If center point is inside occluder proscenium, + if (insideProscenium(occluderProscenium, fe->center2d())) { + // Use this feature edge for visibility deterimination + fe->setIsInImage(true); + // Mark bestOccluderTarget as found + bestOccluderTargetFound = true; + bestOccluderTarget = fe; + } + else { + real d = distance2D(fe->center2d(), prosceniumOrigin); + // If center point is closer to viewport origin than current target + if (bestOccluderTarget == NULL || d < bestOccluderDistance) { + // Then store as bestOccluderTarget + bestOccluderDistance = d; + bestOccluderTarget = fe; + } + } + } + + // If feature edge crosses the view proscenium + if (!(*ve)->isInImage() && crossesProscenium(viewProscenium, fe)) { + // Then the view edge will be included in the image + (*ve)->setIsInImage(true); + } + fe = fe->nextEdge(); + } while (fe && fe != festart && !(bestOccluderTargetFound && (*ve)->isInImage())); + + // Either we have run out of FEdges, or we already have the one edge we need to determine visibility + // Cull all remaining edges. + while (fe && fe != festart) { + fe->setIsInImage(false); + fe = fe->nextEdge(); + } + + // If bestOccluderTarget was not found inside the occluder proscenium, we need to expand the occluder + // proscenium to include it. + if ((*ve)->isInImage() && bestOccluderTarget != NULL && !bestOccluderTargetFound) { + // Expand occluder proscenium to enclose bestOccluderTarget + Vec3r point = bestOccluderTarget->center2d(); + if (point[0] < occluderProscenium[0]) { + occluderProscenium[0] = point[0]; + } + else if (point[0] > occluderProscenium[1]) { + occluderProscenium[1] = point[0]; + } + if (point[1] < occluderProscenium[2]) { + occluderProscenium[2] = point[1]; + } + else if (point[1] > occluderProscenium[3]) { + occluderProscenium[3] = point[1]; + } + // Use bestOccluderTarget for visibility determination + bestOccluderTarget->setIsInImage(true); + } + } + + // We are done calculating the occluder proscenium. + // Expand the occluder proscenium by an epsilon to avoid rounding errors. + const real epsilon = 1.0e-6; + occluderProscenium[0] -= epsilon; + occluderProscenium[1] += epsilon; + occluderProscenium[2] -= epsilon; + occluderProscenium[3] += epsilon; + + // For "Normal" or "Fast" style visibility computation only: + + // For more detailed visibility calculation, make a second pass through the view map, marking all feature edges + // with center points inside the final occluder proscenium. All of these feature edges can be considered during + // visibility calculation. + + // So far we have only found one FEdge per ViewEdge. The "Normal" and "Fast" styles of visibility computation + // want to consider many FEdges for each ViewEdge. + // Here we re-scan the view map to find any usable FEdges that we skipped on the first pass, or that have become + // usable because the occluder proscenium has been expanded since the edge was visited on the first pass. + if (extensiveFEdgeSearch) { + // For each view edge, + for (ve = ioViewMap->ViewEdges().begin(), veend = ioViewMap->ViewEdges().end(); ve != veend; + ve++) { + if (!(*ve)->isInImage()) { + continue; + } + // For each feature edge, + FEdge *festart = (*ve)->fedgeA(); + FEdge *fe = festart; + do { + // If not (already) visible and center point inside occluder proscenium, + if (!fe->isInImage() && insideProscenium(occluderProscenium, fe->center2d())) { + // Use the feature edge for visibility determination + fe->setIsInImage(true); + } + fe = fe->nextEdge(); + } while (fe && fe != festart); + } + } } -void ViewMapBuilder::computeInitialViewEdges(WingedEdge& we) +void ViewMapBuilder::computeInitialViewEdges(WingedEdge &we) { - vector<WShape*> wshapes = we.getWShapes(); - SShape *psShape; - - for (vector<WShape*>::const_iterator it = wshapes.begin(); it != wshapes.end(); it++) { - if (_pRenderMonitor && _pRenderMonitor->testBreak()) - break; - - // create the embedding - psShape = new SShape; - psShape->setId((*it)->GetId()); - psShape->setName((*it)->getName()); - psShape->setLibraryPath((*it)->getLibraryPath()); - psShape->setFrsMaterials((*it)->frs_materials()); // FIXME - - // create the view shape - ViewShape *vshape = new ViewShape(psShape); - // add this view shape to the view map: - _ViewMap->AddViewShape(vshape); - - // we want to number the view edges in a unique way for the while scene. - _pViewEdgeBuilder->setCurrentViewId(_currentId); - // we want to number the feature edges in a unique way for the while scene. - _pViewEdgeBuilder->setCurrentFId(_currentFId); - // we want to number the SVertex in a unique way for the while scene. - _pViewEdgeBuilder->setCurrentSVertexId(_currentFId); - _pViewEdgeBuilder->BuildViewEdges(dynamic_cast<WXShape*>(*it), vshape, _ViewMap->ViewEdges(), - _ViewMap->ViewVertices(), _ViewMap->FEdges(), _ViewMap->SVertices()); - - _currentId = _pViewEdgeBuilder->currentViewId() + 1; - _currentFId = _pViewEdgeBuilder->currentFId() + 1; - _currentSVertexId = _pViewEdgeBuilder->currentSVertexId() + 1; - - psShape->ComputeBBox(); - } + vector<WShape *> wshapes = we.getWShapes(); + SShape *psShape; + + for (vector<WShape *>::const_iterator it = wshapes.begin(); it != wshapes.end(); it++) { + if (_pRenderMonitor && _pRenderMonitor->testBreak()) + break; + + // create the embedding + psShape = new SShape; + psShape->setId((*it)->GetId()); + psShape->setName((*it)->getName()); + psShape->setLibraryPath((*it)->getLibraryPath()); + psShape->setFrsMaterials((*it)->frs_materials()); // FIXME + + // create the view shape + ViewShape *vshape = new ViewShape(psShape); + // add this view shape to the view map: + _ViewMap->AddViewShape(vshape); + + // we want to number the view edges in a unique way for the while scene. + _pViewEdgeBuilder->setCurrentViewId(_currentId); + // we want to number the feature edges in a unique way for the while scene. + _pViewEdgeBuilder->setCurrentFId(_currentFId); + // we want to number the SVertex in a unique way for the while scene. + _pViewEdgeBuilder->setCurrentSVertexId(_currentFId); + _pViewEdgeBuilder->BuildViewEdges(dynamic_cast<WXShape *>(*it), + vshape, + _ViewMap->ViewEdges(), + _ViewMap->ViewVertices(), + _ViewMap->FEdges(), + _ViewMap->SVertices()); + + _currentId = _pViewEdgeBuilder->currentViewId() + 1; + _currentFId = _pViewEdgeBuilder->currentFId() + 1; + _currentSVertexId = _pViewEdgeBuilder->currentSVertexId() + 1; + + psShape->ComputeBBox(); + } } void ViewMapBuilder::computeCusps(ViewMap *ioViewMap) { - vector<ViewVertex*> newVVertices; - vector<ViewEdge*> newVEdges; - ViewMap::viewedges_container& vedges = ioViewMap->ViewEdges(); - ViewMap::viewedges_container::iterator ve = vedges.begin(), veend = vedges.end(); - for (; ve != veend; ++ve) { - if (_pRenderMonitor && _pRenderMonitor->testBreak()) - break; - if ((!((*ve)->getNature() & Nature::SILHOUETTE)) || (!((*ve)->fedgeA()->isSmooth()))) - continue; - FEdge *fe = (*ve)->fedgeA(); - FEdge *fefirst = fe; - bool first = true; - bool positive = true; - do { - FEdgeSmooth *fes = dynamic_cast<FEdgeSmooth*>(fe); - Vec3r A((fes)->vertexA()->point3d()); - Vec3r B((fes)->vertexB()->point3d()); - Vec3r AB(B - A); - AB.normalize(); - Vec3r m((A + B) / 2.0); - Vec3r crossP(AB ^ (fes)->normal()); - crossP.normalize(); - Vec3r viewvector; - if (_orthographicProjection) { - viewvector = Vec3r(0.0, 0.0, m.z() - _viewpoint.z()); - } - else { - viewvector = Vec3r(m - _viewpoint); - } - viewvector.normalize(); - if (first) { - if (((crossP) * (viewvector)) > 0) - positive = true; - else - positive = false; - first = false; - } - // If we're in a positive part, we need a stronger negative value to change - NonTVertex *cusp = NULL; - if (positive) { - if (((crossP) * (viewvector)) < -0.1) { - // state changes - positive = false; - // creates and insert cusp - cusp = dynamic_cast<NonTVertex*>(ioViewMap->InsertViewVertex(fes->vertexA(), newVEdges)); - if (cusp) - cusp->setNature(cusp->getNature() | Nature::CUSP); - } - } - else { - // If we're in a negative part, we need a stronger negative value to change - if (((crossP) * (viewvector)) > 0.1) { - positive = true; - cusp = dynamic_cast<NonTVertex*>(ioViewMap->InsertViewVertex(fes->vertexA(), newVEdges)); - if (cusp) - cusp->setNature(cusp->getNature() | Nature::CUSP); - } - } - fe = fe->nextEdge(); - } while (fe && fe != fefirst); - } - for (ve = newVEdges.begin(), veend = newVEdges.end(); ve != veend; ++ve) { - (*ve)->viewShape()->AddEdge(*ve); - vedges.push_back(*ve); - } + vector<ViewVertex *> newVVertices; + vector<ViewEdge *> newVEdges; + ViewMap::viewedges_container &vedges = ioViewMap->ViewEdges(); + ViewMap::viewedges_container::iterator ve = vedges.begin(), veend = vedges.end(); + for (; ve != veend; ++ve) { + if (_pRenderMonitor && _pRenderMonitor->testBreak()) + break; + if ((!((*ve)->getNature() & Nature::SILHOUETTE)) || (!((*ve)->fedgeA()->isSmooth()))) + continue; + FEdge *fe = (*ve)->fedgeA(); + FEdge *fefirst = fe; + bool first = true; + bool positive = true; + do { + FEdgeSmooth *fes = dynamic_cast<FEdgeSmooth *>(fe); + Vec3r A((fes)->vertexA()->point3d()); + Vec3r B((fes)->vertexB()->point3d()); + Vec3r AB(B - A); + AB.normalize(); + Vec3r m((A + B) / 2.0); + Vec3r crossP(AB ^ (fes)->normal()); + crossP.normalize(); + Vec3r viewvector; + if (_orthographicProjection) { + viewvector = Vec3r(0.0, 0.0, m.z() - _viewpoint.z()); + } + else { + viewvector = Vec3r(m - _viewpoint); + } + viewvector.normalize(); + if (first) { + if (((crossP) * (viewvector)) > 0) + positive = true; + else + positive = false; + first = false; + } + // If we're in a positive part, we need a stronger negative value to change + NonTVertex *cusp = NULL; + if (positive) { + if (((crossP) * (viewvector)) < -0.1) { + // state changes + positive = false; + // creates and insert cusp + cusp = dynamic_cast<NonTVertex *>( + ioViewMap->InsertViewVertex(fes->vertexA(), newVEdges)); + if (cusp) + cusp->setNature(cusp->getNature() | Nature::CUSP); + } + } + else { + // If we're in a negative part, we need a stronger negative value to change + if (((crossP) * (viewvector)) > 0.1) { + positive = true; + cusp = dynamic_cast<NonTVertex *>( + ioViewMap->InsertViewVertex(fes->vertexA(), newVEdges)); + if (cusp) + cusp->setNature(cusp->getNature() | Nature::CUSP); + } + } + fe = fe->nextEdge(); + } while (fe && fe != fefirst); + } + for (ve = newVEdges.begin(), veend = newVEdges.end(); ve != veend; ++ve) { + (*ve)->viewShape()->AddEdge(*ve); + vedges.push_back(*ve); + } } -void ViewMapBuilder::ComputeCumulativeVisibility(ViewMap *ioViewMap, WingedEdge& we, const BBox<Vec3r>& bbox, - real epsilon, bool cull, GridDensityProviderFactory& factory) +void ViewMapBuilder::ComputeCumulativeVisibility(ViewMap *ioViewMap, + WingedEdge &we, + const BBox<Vec3r> &bbox, + real epsilon, + bool cull, + GridDensityProviderFactory &factory) { - AutoPtr<GridHelpers::Transform> transform; - AutoPtr<OccluderSource> source; - - if (_orthographicProjection) { - transform.reset(new BoxGrid::Transform); - } - else { - transform.reset(new SphericalGrid::Transform); - } - - if (cull) { - source.reset(new CulledOccluderSource(*transform, we, *ioViewMap, true)); - } - else { - source.reset(new OccluderSource(*transform, we)); - } - - AutoPtr<GridDensityProvider> density(factory.newGridDensityProvider(*source, bbox, *transform)); - - if (_orthographicProjection) { - BoxGrid grid(*source, *density, ioViewMap, _viewpoint, _EnableQI); - computeCumulativeVisibility<BoxGrid, BoxGrid::Iterator>(ioViewMap, grid, epsilon, _pRenderMonitor); - } - else { - SphericalGrid grid(*source, *density, ioViewMap, _viewpoint, _EnableQI); - computeCumulativeVisibility<SphericalGrid, SphericalGrid::Iterator>(ioViewMap, grid, epsilon, _pRenderMonitor); - } + AutoPtr<GridHelpers::Transform> transform; + AutoPtr<OccluderSource> source; + + if (_orthographicProjection) { + transform.reset(new BoxGrid::Transform); + } + else { + transform.reset(new SphericalGrid::Transform); + } + + if (cull) { + source.reset(new CulledOccluderSource(*transform, we, *ioViewMap, true)); + } + else { + source.reset(new OccluderSource(*transform, we)); + } + + AutoPtr<GridDensityProvider> density(factory.newGridDensityProvider(*source, bbox, *transform)); + + if (_orthographicProjection) { + BoxGrid grid(*source, *density, ioViewMap, _viewpoint, _EnableQI); + computeCumulativeVisibility<BoxGrid, BoxGrid::Iterator>( + ioViewMap, grid, epsilon, _pRenderMonitor); + } + else { + SphericalGrid grid(*source, *density, ioViewMap, _viewpoint, _EnableQI); + computeCumulativeVisibility<SphericalGrid, SphericalGrid::Iterator>( + ioViewMap, grid, epsilon, _pRenderMonitor); + } } -void ViewMapBuilder::ComputeDetailedVisibility(ViewMap *ioViewMap, WingedEdge& we, const BBox<Vec3r>& bbox, - real epsilon, bool cull, GridDensityProviderFactory& factory) +void ViewMapBuilder::ComputeDetailedVisibility(ViewMap *ioViewMap, + WingedEdge &we, + const BBox<Vec3r> &bbox, + real epsilon, + bool cull, + GridDensityProviderFactory &factory) { - AutoPtr<GridHelpers::Transform> transform; - AutoPtr<OccluderSource> source; - - if (_orthographicProjection) { - transform.reset(new BoxGrid::Transform); - } - else { - transform.reset(new SphericalGrid::Transform); - } - - if (cull) { - source.reset(new CulledOccluderSource(*transform, we, *ioViewMap, true)); - } - else { - source.reset(new OccluderSource(*transform, we)); - } - - AutoPtr<GridDensityProvider> density(factory.newGridDensityProvider(*source, bbox, *transform)); - - if (_orthographicProjection) { - BoxGrid grid(*source, *density, ioViewMap, _viewpoint, _EnableQI); - computeDetailedVisibility<BoxGrid, BoxGrid::Iterator>(ioViewMap, grid, epsilon, _pRenderMonitor); - } - else { - SphericalGrid grid(*source, *density, ioViewMap, _viewpoint, _EnableQI); - computeDetailedVisibility<SphericalGrid, SphericalGrid::Iterator>(ioViewMap, grid, epsilon, _pRenderMonitor); - } + AutoPtr<GridHelpers::Transform> transform; + AutoPtr<OccluderSource> source; + + if (_orthographicProjection) { + transform.reset(new BoxGrid::Transform); + } + else { + transform.reset(new SphericalGrid::Transform); + } + + if (cull) { + source.reset(new CulledOccluderSource(*transform, we, *ioViewMap, true)); + } + else { + source.reset(new OccluderSource(*transform, we)); + } + + AutoPtr<GridDensityProvider> density(factory.newGridDensityProvider(*source, bbox, *transform)); + + if (_orthographicProjection) { + BoxGrid grid(*source, *density, ioViewMap, _viewpoint, _EnableQI); + computeDetailedVisibility<BoxGrid, BoxGrid::Iterator>( + ioViewMap, grid, epsilon, _pRenderMonitor); + } + else { + SphericalGrid grid(*source, *density, ioViewMap, _viewpoint, _EnableQI); + computeDetailedVisibility<SphericalGrid, SphericalGrid::Iterator>( + ioViewMap, grid, epsilon, _pRenderMonitor); + } } -void ViewMapBuilder::ComputeEdgesVisibility(ViewMap *ioViewMap, WingedEdge& we, const BBox<Vec3r>& bbox, - unsigned int sceneNumFaces, visibility_algo iAlgo, real epsilon) +void ViewMapBuilder::ComputeEdgesVisibility(ViewMap *ioViewMap, + WingedEdge &we, + const BBox<Vec3r> &bbox, + unsigned int sceneNumFaces, + visibility_algo iAlgo, + real epsilon) { #if 0 - iAlgo = ray_casting; // for testing algorithms equivalence + iAlgo = ray_casting; // for testing algorithms equivalence #endif - switch (iAlgo) { - case ray_casting: - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "Using ordinary ray casting" << endl; - } - BuildGrid(we, bbox, sceneNumFaces); - ComputeRayCastingVisibility(ioViewMap, epsilon); - break; - case ray_casting_fast: - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "Using fast ray casting" << endl; - } - BuildGrid(we, bbox, sceneNumFaces); - ComputeFastRayCastingVisibility(ioViewMap, epsilon); - break; - case ray_casting_very_fast: - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "Using very fast ray casting" << endl; - } - BuildGrid(we, bbox, sceneNumFaces); - ComputeVeryFastRayCastingVisibility(ioViewMap, epsilon); - break; - case ray_casting_culled_adaptive_traditional: - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "Using culled adaptive grid with heuristic density and traditional QI calculation" << endl; - } - try { - HeuristicGridDensityProviderFactory factory(0.5f, sceneNumFaces); - ComputeDetailedVisibility(ioViewMap, we, bbox, epsilon, true, factory); - } - catch (...) { - // Last resort catch to make sure RAII semantics hold for OptimizedGrid. Can be replaced with - // try...catch block around main() if the program as a whole is converted to RAII - - // This is the little-mentioned caveat of RAII: RAII does not work unless destructors are always - // called, but destructors are only called if all exceptions are caught (or std::terminate() is - // replaced). - - // We don't actually handle the exception here, so re-throw it now that our destructors have had a - // chance to run. - throw; - } - break; - case ray_casting_adaptive_traditional: - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "Using unculled adaptive grid with heuristic density and traditional QI calculation" << endl; - } - try { - HeuristicGridDensityProviderFactory factory(0.5f, sceneNumFaces); - ComputeDetailedVisibility(ioViewMap, we, bbox, epsilon, false, factory); - } - catch (...) { - throw; - } - break; - case ray_casting_culled_adaptive_cumulative: - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "Using culled adaptive grid with heuristic density and cumulative QI calculation" << endl; - } - try { - HeuristicGridDensityProviderFactory factory(0.5f, sceneNumFaces); - ComputeCumulativeVisibility(ioViewMap, we, bbox, epsilon, true, factory); - } - catch (...) { - throw; - } - break; - case ray_casting_adaptive_cumulative: - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "Using unculled adaptive grid with heuristic density and cumulative QI calculation" << endl; - } - try { - HeuristicGridDensityProviderFactory factory(0.5f, sceneNumFaces); - ComputeCumulativeVisibility(ioViewMap, we, bbox, epsilon, false, factory); - } - catch (...) { - throw; - } - break; - default: - break; - } + switch (iAlgo) { + case ray_casting: + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "Using ordinary ray casting" << endl; + } + BuildGrid(we, bbox, sceneNumFaces); + ComputeRayCastingVisibility(ioViewMap, epsilon); + break; + case ray_casting_fast: + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "Using fast ray casting" << endl; + } + BuildGrid(we, bbox, sceneNumFaces); + ComputeFastRayCastingVisibility(ioViewMap, epsilon); + break; + case ray_casting_very_fast: + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "Using very fast ray casting" << endl; + } + BuildGrid(we, bbox, sceneNumFaces); + ComputeVeryFastRayCastingVisibility(ioViewMap, epsilon); + break; + case ray_casting_culled_adaptive_traditional: + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "Using culled adaptive grid with heuristic density and traditional QI calculation" + << endl; + } + try { + HeuristicGridDensityProviderFactory factory(0.5f, sceneNumFaces); + ComputeDetailedVisibility(ioViewMap, we, bbox, epsilon, true, factory); + } + catch (...) { + // Last resort catch to make sure RAII semantics hold for OptimizedGrid. Can be replaced with + // try...catch block around main() if the program as a whole is converted to RAII + + // This is the little-mentioned caveat of RAII: RAII does not work unless destructors are always + // called, but destructors are only called if all exceptions are caught (or std::terminate() is + // replaced). + + // We don't actually handle the exception here, so re-throw it now that our destructors have had a + // chance to run. + throw; + } + break; + case ray_casting_adaptive_traditional: + if (_global.debug & G_DEBUG_FREESTYLE) { + cout + << "Using unculled adaptive grid with heuristic density and traditional QI calculation" + << endl; + } + try { + HeuristicGridDensityProviderFactory factory(0.5f, sceneNumFaces); + ComputeDetailedVisibility(ioViewMap, we, bbox, epsilon, false, factory); + } + catch (...) { + throw; + } + break; + case ray_casting_culled_adaptive_cumulative: + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "Using culled adaptive grid with heuristic density and cumulative QI calculation" + << endl; + } + try { + HeuristicGridDensityProviderFactory factory(0.5f, sceneNumFaces); + ComputeCumulativeVisibility(ioViewMap, we, bbox, epsilon, true, factory); + } + catch (...) { + throw; + } + break; + case ray_casting_adaptive_cumulative: + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "Using unculled adaptive grid with heuristic density and cumulative QI calculation" + << endl; + } + try { + HeuristicGridDensityProviderFactory factory(0.5f, sceneNumFaces); + ComputeCumulativeVisibility(ioViewMap, we, bbox, epsilon, false, factory); + } + catch (...) { + throw; + } + break; + default: + break; + } } static const unsigned gProgressBarMaxSteps = 10; @@ -1453,960 +1527,984 @@ static const unsigned gProgressBarMinSize = 2000; void ViewMapBuilder::ComputeRayCastingVisibility(ViewMap *ioViewMap, real epsilon) { - vector<ViewEdge*>& vedges = ioViewMap->ViewEdges(); - bool progressBarDisplay = false; - unsigned progressBarStep = 0; - unsigned vEdgesSize = vedges.size(); - unsigned fEdgesSize = ioViewMap->FEdges().size(); - - if (_pProgressBar != NULL && fEdgesSize > gProgressBarMinSize) { - unsigned progressBarSteps = min(gProgressBarMaxSteps, vEdgesSize); - progressBarStep = vEdgesSize / progressBarSteps; - _pProgressBar->reset(); - _pProgressBar->setLabelText("Computing Ray casting Visibility"); - _pProgressBar->setTotalSteps(progressBarSteps); - _pProgressBar->setProgress(0); - progressBarDisplay = true; - } - - unsigned counter = progressBarStep; - FEdge *fe, *festart; - int nSamples = 0; - vector<Polygon3r*> aFaces; - Polygon3r *aFace = NULL; - unsigned tmpQI = 0; - unsigned qiClasses[256]; - unsigned maxIndex, maxCard; - unsigned qiMajority; - static unsigned timestamp = 1; - for (vector<ViewEdge*>::iterator ve = vedges.begin(), veend = vedges.end(); ve != veend; ve++) { - if (_pRenderMonitor && _pRenderMonitor->testBreak()) - break; + vector<ViewEdge *> &vedges = ioViewMap->ViewEdges(); + bool progressBarDisplay = false; + unsigned progressBarStep = 0; + unsigned vEdgesSize = vedges.size(); + unsigned fEdgesSize = ioViewMap->FEdges().size(); + + if (_pProgressBar != NULL && fEdgesSize > gProgressBarMinSize) { + unsigned progressBarSteps = min(gProgressBarMaxSteps, vEdgesSize); + progressBarStep = vEdgesSize / progressBarSteps; + _pProgressBar->reset(); + _pProgressBar->setLabelText("Computing Ray casting Visibility"); + _pProgressBar->setTotalSteps(progressBarSteps); + _pProgressBar->setProgress(0); + progressBarDisplay = true; + } + + unsigned counter = progressBarStep; + FEdge *fe, *festart; + int nSamples = 0; + vector<Polygon3r *> aFaces; + Polygon3r *aFace = NULL; + unsigned tmpQI = 0; + unsigned qiClasses[256]; + unsigned maxIndex, maxCard; + unsigned qiMajority; + static unsigned timestamp = 1; + for (vector<ViewEdge *>::iterator ve = vedges.begin(), veend = vedges.end(); ve != veend; ve++) { + if (_pRenderMonitor && _pRenderMonitor->testBreak()) + break; #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "Processing ViewEdge " << (*ve)->getId() << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "Processing ViewEdge " << (*ve)->getId() << endl; + } #endif - festart = (*ve)->fedgeA(); - fe = (*ve)->fedgeA(); - qiMajority = 1; - do { - qiMajority++; - fe = fe->nextEdge(); - } while (fe && fe != festart); - qiMajority >>= 1; + festart = (*ve)->fedgeA(); + fe = (*ve)->fedgeA(); + qiMajority = 1; + do { + qiMajority++; + fe = fe->nextEdge(); + } while (fe && fe != festart); + qiMajority >>= 1; #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\tqiMajority: " << qiMajority << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\tqiMajority: " << qiMajority << endl; + } #endif - tmpQI = 0; - maxIndex = 0; - maxCard = 0; - nSamples = 0; - fe = (*ve)->fedgeA(); - memset(qiClasses, 0, 256 * sizeof(*qiClasses)); - set<ViewShape*> occluders; - do { - if ((maxCard < qiMajority)) { - tmpQI = ComputeRayCastingVisibility(fe, _Grid, epsilon, occluders, &aFace, timestamp++); + tmpQI = 0; + maxIndex = 0; + maxCard = 0; + nSamples = 0; + fe = (*ve)->fedgeA(); + memset(qiClasses, 0, 256 * sizeof(*qiClasses)); + set<ViewShape *> occluders; + do { + if ((maxCard < qiMajority)) { + tmpQI = ComputeRayCastingVisibility(fe, _Grid, epsilon, occluders, &aFace, timestamp++); #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\tFEdge: visibility " << tmpQI << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\tFEdge: visibility " << tmpQI << endl; + } #endif - //ARB: This is an error condition, not an alert condition. - // Some sort of recovery or abort is necessary. - if (tmpQI >= 256) { - cerr << "Warning: too many occluding levels" << endl; - //ARB: Wild guess: instead of aborting or corrupting memory, treat as tmpQI == 255 - tmpQI = 255; - } - - if (++qiClasses[tmpQI] > maxCard) { - maxCard = qiClasses[tmpQI]; - maxIndex = tmpQI; - } - } - else { - //ARB: FindOccludee is redundant if ComputeRayCastingVisibility has been called - FindOccludee(fe, _Grid, epsilon, &aFace, timestamp++); + //ARB: This is an error condition, not an alert condition. + // Some sort of recovery or abort is necessary. + if (tmpQI >= 256) { + cerr << "Warning: too many occluding levels" << endl; + //ARB: Wild guess: instead of aborting or corrupting memory, treat as tmpQI == 255 + tmpQI = 255; + } + + if (++qiClasses[tmpQI] > maxCard) { + maxCard = qiClasses[tmpQI]; + maxIndex = tmpQI; + } + } + else { + //ARB: FindOccludee is redundant if ComputeRayCastingVisibility has been called + FindOccludee(fe, _Grid, epsilon, &aFace, timestamp++); #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\tFEdge: occludee only (" << (aFace != NULL ? "found" : "not found") << ")" << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\tFEdge: occludee only (" << (aFace != NULL ? "found" : "not found") << ")" + << endl; + } #endif - } + } - if (aFace) { - fe->setaFace(*aFace); - aFaces.push_back(aFace); - fe->setOccludeeEmpty(false); + if (aFace) { + fe->setaFace(*aFace); + aFaces.push_back(aFace); + fe->setOccludeeEmpty(false); #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\tFound occludee" << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\tFound occludee" << endl; + } #endif - } - else { - //ARB: We are arbitrarily using the last observed value for occludee (almost always the value observed - // for the edge before festart). Is that meaningful? - // ...in fact, _occludeeEmpty seems to be unused. - fe->setOccludeeEmpty(true); - } - - ++nSamples; - fe = fe->nextEdge(); - } while ((maxCard < qiMajority) && (fe) && (fe != festart)); + } + else { + //ARB: We are arbitrarily using the last observed value for occludee (almost always the value observed + // for the edge before festart). Is that meaningful? + // ...in fact, _occludeeEmpty seems to be unused. + fe->setOccludeeEmpty(true); + } + + ++nSamples; + fe = fe->nextEdge(); + } while ((maxCard < qiMajority) && (fe) && (fe != festart)); #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\tFinished with " << nSamples << " samples, maxCard = " << maxCard << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\tFinished with " << nSamples << " samples, maxCard = " << maxCard << endl; + } #endif - // ViewEdge - // qi -- - (*ve)->setQI(maxIndex); - // occluders -- - for (set<ViewShape*>::iterator o = occluders.begin(), oend = occluders.end(); o != oend; ++o) - (*ve)->AddOccluder((*o)); + // ViewEdge + // qi -- + (*ve)->setQI(maxIndex); + // occluders -- + for (set<ViewShape *>::iterator o = occluders.begin(), oend = occluders.end(); o != oend; ++o) + (*ve)->AddOccluder((*o)); #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\tConclusion: QI = " << maxIndex << ", " << (*ve)->occluders_size() << " occluders." << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\tConclusion: QI = " << maxIndex << ", " << (*ve)->occluders_size() << " occluders." + << endl; + } #endif - // occludee -- - if (!aFaces.empty()) { - if (aFaces.size() <= (float)nSamples / 2.0f) { - (*ve)->setaShape(0); - } - else { - vector<Polygon3r*>::iterator p = aFaces.begin(); - WFace *wface = (WFace *)((*p)->userdata); - ViewShape *vshape = ioViewMap->viewShape(wface->GetVertex(0)->shape()->GetId()); - ++p; - (*ve)->setaShape(vshape); - } - } - - if (progressBarDisplay) { - counter--; - if (counter <= 0) { - counter = progressBarStep; - _pProgressBar->setProgress(_pProgressBar->getProgress() + 1); - } - } - aFaces.clear(); - } + // occludee -- + if (!aFaces.empty()) { + if (aFaces.size() <= (float)nSamples / 2.0f) { + (*ve)->setaShape(0); + } + else { + vector<Polygon3r *>::iterator p = aFaces.begin(); + WFace *wface = (WFace *)((*p)->userdata); + ViewShape *vshape = ioViewMap->viewShape(wface->GetVertex(0)->shape()->GetId()); + ++p; + (*ve)->setaShape(vshape); + } + } + + if (progressBarDisplay) { + counter--; + if (counter <= 0) { + counter = progressBarStep; + _pProgressBar->setProgress(_pProgressBar->getProgress() + 1); + } + } + aFaces.clear(); + } } void ViewMapBuilder::ComputeFastRayCastingVisibility(ViewMap *ioViewMap, real epsilon) { - vector<ViewEdge*>& vedges = ioViewMap->ViewEdges(); - bool progressBarDisplay = false; - unsigned progressBarStep = 0; - unsigned vEdgesSize = vedges.size(); - unsigned fEdgesSize = ioViewMap->FEdges().size(); - - if (_pProgressBar != NULL && fEdgesSize > gProgressBarMinSize) { - unsigned progressBarSteps = min(gProgressBarMaxSteps, vEdgesSize); - progressBarStep = vEdgesSize / progressBarSteps; - _pProgressBar->reset(); - _pProgressBar->setLabelText("Computing Ray casting Visibility"); - _pProgressBar->setTotalSteps(progressBarSteps); - _pProgressBar->setProgress(0); - progressBarDisplay = true; - } - - unsigned counter = progressBarStep; - FEdge *fe, *festart; - unsigned nSamples = 0; - vector<Polygon3r*> aFaces; - Polygon3r *aFace = NULL; - unsigned tmpQI = 0; - unsigned qiClasses[256]; - unsigned maxIndex, maxCard; - unsigned qiMajority; - static unsigned timestamp = 1; - bool even_test; - for (vector<ViewEdge*>::iterator ve = vedges.begin(), veend = vedges.end(); ve != veend; ve++) { - if (_pRenderMonitor && _pRenderMonitor->testBreak()) - break; - - festart = (*ve)->fedgeA(); - fe = (*ve)->fedgeA(); - qiMajority = 1; - do { - qiMajority++; - fe = fe->nextEdge(); - } while (fe && fe != festart); - if (qiMajority >= 4) - qiMajority >>= 2; - else - qiMajority = 1; - - set<ViewShape*> occluders; - - even_test = true; - maxIndex = 0; - maxCard = 0; - nSamples = 0; - memset(qiClasses, 0, 256 * sizeof(*qiClasses)); - fe = (*ve)->fedgeA(); - do { - if (even_test) { - if ((maxCard < qiMajority)) { - tmpQI = ComputeRayCastingVisibility(fe, _Grid, epsilon, occluders, &aFace, timestamp++); - - //ARB: This is an error condition, not an alert condition. - // Some sort of recovery or abort is necessary. - if (tmpQI >= 256) { - cerr << "Warning: too many occluding levels" << endl; - //ARB: Wild guess: instead of aborting or corrupting memory, treat as tmpQI == 255 - tmpQI = 255; - } - - if (++qiClasses[tmpQI] > maxCard) { - maxCard = qiClasses[tmpQI]; - maxIndex = tmpQI; - } - } - else { - //ARB: FindOccludee is redundant if ComputeRayCastingVisibility has been called - FindOccludee(fe, _Grid, epsilon, &aFace, timestamp++); - } - - if (aFace) { - fe->setaFace(*aFace); - aFaces.push_back(aFace); - } - ++nSamples; - even_test = false; - } - else { - even_test = true; - } - fe = fe->nextEdge(); - } while ((maxCard < qiMajority) && (fe) && (fe != festart)); - - (*ve)->setQI(maxIndex); - - if (!aFaces.empty()) { - if (aFaces.size() < nSamples / 2) { - (*ve)->setaShape(0); - } - else { - vector<Polygon3r*>::iterator p = aFaces.begin(); - WFace *wface = (WFace *)((*p)->userdata); - ViewShape *vshape = ioViewMap->viewShape(wface->GetVertex(0)->shape()->GetId()); - ++p; + vector<ViewEdge *> &vedges = ioViewMap->ViewEdges(); + bool progressBarDisplay = false; + unsigned progressBarStep = 0; + unsigned vEdgesSize = vedges.size(); + unsigned fEdgesSize = ioViewMap->FEdges().size(); + + if (_pProgressBar != NULL && fEdgesSize > gProgressBarMinSize) { + unsigned progressBarSteps = min(gProgressBarMaxSteps, vEdgesSize); + progressBarStep = vEdgesSize / progressBarSteps; + _pProgressBar->reset(); + _pProgressBar->setLabelText("Computing Ray casting Visibility"); + _pProgressBar->setTotalSteps(progressBarSteps); + _pProgressBar->setProgress(0); + progressBarDisplay = true; + } + + unsigned counter = progressBarStep; + FEdge *fe, *festart; + unsigned nSamples = 0; + vector<Polygon3r *> aFaces; + Polygon3r *aFace = NULL; + unsigned tmpQI = 0; + unsigned qiClasses[256]; + unsigned maxIndex, maxCard; + unsigned qiMajority; + static unsigned timestamp = 1; + bool even_test; + for (vector<ViewEdge *>::iterator ve = vedges.begin(), veend = vedges.end(); ve != veend; ve++) { + if (_pRenderMonitor && _pRenderMonitor->testBreak()) + break; + + festart = (*ve)->fedgeA(); + fe = (*ve)->fedgeA(); + qiMajority = 1; + do { + qiMajority++; + fe = fe->nextEdge(); + } while (fe && fe != festart); + if (qiMajority >= 4) + qiMajority >>= 2; + else + qiMajority = 1; + + set<ViewShape *> occluders; + + even_test = true; + maxIndex = 0; + maxCard = 0; + nSamples = 0; + memset(qiClasses, 0, 256 * sizeof(*qiClasses)); + fe = (*ve)->fedgeA(); + do { + if (even_test) { + if ((maxCard < qiMajority)) { + tmpQI = ComputeRayCastingVisibility(fe, _Grid, epsilon, occluders, &aFace, timestamp++); + + //ARB: This is an error condition, not an alert condition. + // Some sort of recovery or abort is necessary. + if (tmpQI >= 256) { + cerr << "Warning: too many occluding levels" << endl; + //ARB: Wild guess: instead of aborting or corrupting memory, treat as tmpQI == 255 + tmpQI = 255; + } + + if (++qiClasses[tmpQI] > maxCard) { + maxCard = qiClasses[tmpQI]; + maxIndex = tmpQI; + } + } + else { + //ARB: FindOccludee is redundant if ComputeRayCastingVisibility has been called + FindOccludee(fe, _Grid, epsilon, &aFace, timestamp++); + } + + if (aFace) { + fe->setaFace(*aFace); + aFaces.push_back(aFace); + } + ++nSamples; + even_test = false; + } + else { + even_test = true; + } + fe = fe->nextEdge(); + } while ((maxCard < qiMajority) && (fe) && (fe != festart)); + + (*ve)->setQI(maxIndex); + + if (!aFaces.empty()) { + if (aFaces.size() < nSamples / 2) { + (*ve)->setaShape(0); + } + else { + vector<Polygon3r *>::iterator p = aFaces.begin(); + WFace *wface = (WFace *)((*p)->userdata); + ViewShape *vshape = ioViewMap->viewShape(wface->GetVertex(0)->shape()->GetId()); + ++p; #if 0 - for (; p != pend; ++p) { - WFace *f = (WFace*)((*p)->userdata); - ViewShape *vs = ioViewMap->viewShape(f->GetVertex(0)->shape()->GetId()); - if (vs != vshape) { - sameShape = false; - break; - } - } - if (sameShape) + for (; p != pend; ++p) { + WFace *f = (WFace*)((*p)->userdata); + ViewShape *vs = ioViewMap->viewShape(f->GetVertex(0)->shape()->GetId()); + if (vs != vshape) { + sameShape = false; + break; + } + } + if (sameShape) #endif - (*ve)->setaShape(vshape); - } - } - - //(*ve)->setaFace(aFace); - - if (progressBarDisplay) { - counter--; - if (counter <= 0) { - counter = progressBarStep; - _pProgressBar->setProgress(_pProgressBar->getProgress() + 1); - } - } - aFaces.clear(); - } + (*ve)->setaShape(vshape); + } + } + + //(*ve)->setaFace(aFace); + + if (progressBarDisplay) { + counter--; + if (counter <= 0) { + counter = progressBarStep; + _pProgressBar->setProgress(_pProgressBar->getProgress() + 1); + } + } + aFaces.clear(); + } } void ViewMapBuilder::ComputeVeryFastRayCastingVisibility(ViewMap *ioViewMap, real epsilon) { - vector<ViewEdge*>& vedges = ioViewMap->ViewEdges(); - bool progressBarDisplay = false; - unsigned progressBarStep = 0; - unsigned vEdgesSize = vedges.size(); - unsigned fEdgesSize = ioViewMap->FEdges().size(); - - if (_pProgressBar != NULL && fEdgesSize > gProgressBarMinSize) { - unsigned progressBarSteps = min(gProgressBarMaxSteps, vEdgesSize); - progressBarStep = vEdgesSize / progressBarSteps; - _pProgressBar->reset(); - _pProgressBar->setLabelText("Computing Ray casting Visibility"); - _pProgressBar->setTotalSteps(progressBarSteps); - _pProgressBar->setProgress(0); - progressBarDisplay = true; - } - - unsigned counter = progressBarStep; - FEdge *fe; - unsigned qi = 0; - Polygon3r *aFace = NULL; - static unsigned timestamp = 1; - for (vector<ViewEdge*>::iterator ve = vedges.begin(), veend = vedges.end(); ve != veend; ve++) { - if (_pRenderMonitor && _pRenderMonitor->testBreak()) - break; - - set<ViewShape*> occluders; - - fe = (*ve)->fedgeA(); - qi = ComputeRayCastingVisibility(fe, _Grid, epsilon, occluders, &aFace, timestamp++); - if (aFace) { - fe->setaFace(*aFace); - WFace *wface = (WFace *)(aFace->userdata); - ViewShape *vshape = ioViewMap->viewShape(wface->GetVertex(0)->shape()->GetId()); - (*ve)->setaShape(vshape); - } - else { - (*ve)->setaShape(0); - } - - (*ve)->setQI(qi); - - if (progressBarDisplay) { - counter--; - if (counter <= 0) { - counter = progressBarStep; - _pProgressBar->setProgress(_pProgressBar->getProgress() + 1); - } - } - } + vector<ViewEdge *> &vedges = ioViewMap->ViewEdges(); + bool progressBarDisplay = false; + unsigned progressBarStep = 0; + unsigned vEdgesSize = vedges.size(); + unsigned fEdgesSize = ioViewMap->FEdges().size(); + + if (_pProgressBar != NULL && fEdgesSize > gProgressBarMinSize) { + unsigned progressBarSteps = min(gProgressBarMaxSteps, vEdgesSize); + progressBarStep = vEdgesSize / progressBarSteps; + _pProgressBar->reset(); + _pProgressBar->setLabelText("Computing Ray casting Visibility"); + _pProgressBar->setTotalSteps(progressBarSteps); + _pProgressBar->setProgress(0); + progressBarDisplay = true; + } + + unsigned counter = progressBarStep; + FEdge *fe; + unsigned qi = 0; + Polygon3r *aFace = NULL; + static unsigned timestamp = 1; + for (vector<ViewEdge *>::iterator ve = vedges.begin(), veend = vedges.end(); ve != veend; ve++) { + if (_pRenderMonitor && _pRenderMonitor->testBreak()) + break; + + set<ViewShape *> occluders; + + fe = (*ve)->fedgeA(); + qi = ComputeRayCastingVisibility(fe, _Grid, epsilon, occluders, &aFace, timestamp++); + if (aFace) { + fe->setaFace(*aFace); + WFace *wface = (WFace *)(aFace->userdata); + ViewShape *vshape = ioViewMap->viewShape(wface->GetVertex(0)->shape()->GetId()); + (*ve)->setaShape(vshape); + } + else { + (*ve)->setaShape(0); + } + + (*ve)->setQI(qi); + + if (progressBarDisplay) { + counter--; + if (counter <= 0) { + counter = progressBarStep; + _pProgressBar->setProgress(_pProgressBar->getProgress() + 1); + } + } + } } -void ViewMapBuilder::FindOccludee(FEdge *fe, Grid *iGrid, real epsilon, Polygon3r **oaPolygon, unsigned timestamp, - Vec3r& u, Vec3r& A, Vec3r& origin, Vec3r& edgeDir, vector<WVertex*>& faceVertices) +void ViewMapBuilder::FindOccludee(FEdge *fe, + Grid *iGrid, + real epsilon, + Polygon3r **oaPolygon, + unsigned timestamp, + Vec3r &u, + Vec3r &A, + Vec3r &origin, + Vec3r &edgeDir, + vector<WVertex *> &faceVertices) { - WFace *face = NULL; - if (fe->isSmooth()) { - FEdgeSmooth *fes = dynamic_cast<FEdgeSmooth*>(fe); - face = (WFace *)fes->face(); - } - OccludersSet occluders; - WFace *oface; - bool skipFace; - - WVertex::incoming_edge_iterator ie; - OccludersSet::iterator p, pend; - - *oaPolygon = NULL; - if (((fe)->getNature() & Nature::SILHOUETTE) || ((fe)->getNature() & Nature::BORDER)) { - occluders.clear(); - // we cast a ray from A in the same direction but looking behind - Vec3r v(-u[0], -u[1], -u[2]); - iGrid->castInfiniteRay(A, v, occluders, timestamp); - - bool noIntersection = true; - real mint = FLT_MAX; - // we met some occluders, let us fill the aShape field with the first intersected occluder - for (p = occluders.begin(), pend = occluders.end(); p != pend; p++) { - // check whether the edge and the polygon plane are coincident: - //------------------------------------------------------------- - //first let us compute the plane equation. - oface = (WFace *)(*p)->userdata; - Vec3r v1(((*p)->getVertices())[0]); - Vec3r normal((*p)->getNormal()); - real d = -(v1 * normal); - real t, t_u, t_v; - - if (face) { - skipFace = false; - - if (face == oface) - continue; - - if (faceVertices.empty()) - continue; - - for (vector<WVertex*>::iterator fv = faceVertices.begin(), fvend = faceVertices.end(); - fv != fvend; - ++fv) - { - if ((*fv)->isBoundary()) - continue; - WVertex::incoming_edge_iterator iebegin = (*fv)->incoming_edges_begin(); - WVertex::incoming_edge_iterator ieend = (*fv)->incoming_edges_end(); - for (ie = iebegin; ie != ieend; ++ie) { - if ((*ie) == 0) - continue; - - WFace *sface = (*ie)->GetbFace(); - if (sface == oface) { - skipFace = true; - break; - } - } - if (skipFace) - break; - } - if (skipFace) - continue; - } - else { - if (GeomUtils::COINCIDENT == GeomUtils::intersectRayPlane(origin, edgeDir, normal, d, t, epsilon)) - continue; - } - if ((*p)->rayIntersect(A, v, t, t_u, t_v)) { - if (fabs(v * normal) > 0.0001) { - if (t > 0.0) { // && t < 1.0) { - if (t < mint) { - *oaPolygon = (*p); - mint = t; - noIntersection = false; - fe->setOccludeeIntersection(Vec3r(A + t * v)); - } - } - } - } - } - - if (noIntersection) - *oaPolygon = NULL; - } + WFace *face = NULL; + if (fe->isSmooth()) { + FEdgeSmooth *fes = dynamic_cast<FEdgeSmooth *>(fe); + face = (WFace *)fes->face(); + } + OccludersSet occluders; + WFace *oface; + bool skipFace; + + WVertex::incoming_edge_iterator ie; + OccludersSet::iterator p, pend; + + *oaPolygon = NULL; + if (((fe)->getNature() & Nature::SILHOUETTE) || ((fe)->getNature() & Nature::BORDER)) { + occluders.clear(); + // we cast a ray from A in the same direction but looking behind + Vec3r v(-u[0], -u[1], -u[2]); + iGrid->castInfiniteRay(A, v, occluders, timestamp); + + bool noIntersection = true; + real mint = FLT_MAX; + // we met some occluders, let us fill the aShape field with the first intersected occluder + for (p = occluders.begin(), pend = occluders.end(); p != pend; p++) { + // check whether the edge and the polygon plane are coincident: + //------------------------------------------------------------- + //first let us compute the plane equation. + oface = (WFace *)(*p)->userdata; + Vec3r v1(((*p)->getVertices())[0]); + Vec3r normal((*p)->getNormal()); + real d = -(v1 * normal); + real t, t_u, t_v; + + if (face) { + skipFace = false; + + if (face == oface) + continue; + + if (faceVertices.empty()) + continue; + + for (vector<WVertex *>::iterator fv = faceVertices.begin(), fvend = faceVertices.end(); + fv != fvend; + ++fv) { + if ((*fv)->isBoundary()) + continue; + WVertex::incoming_edge_iterator iebegin = (*fv)->incoming_edges_begin(); + WVertex::incoming_edge_iterator ieend = (*fv)->incoming_edges_end(); + for (ie = iebegin; ie != ieend; ++ie) { + if ((*ie) == 0) + continue; + + WFace *sface = (*ie)->GetbFace(); + if (sface == oface) { + skipFace = true; + break; + } + } + if (skipFace) + break; + } + if (skipFace) + continue; + } + else { + if (GeomUtils::COINCIDENT == + GeomUtils::intersectRayPlane(origin, edgeDir, normal, d, t, epsilon)) + continue; + } + if ((*p)->rayIntersect(A, v, t, t_u, t_v)) { + if (fabs(v * normal) > 0.0001) { + if (t > 0.0) { // && t < 1.0) { + if (t < mint) { + *oaPolygon = (*p); + mint = t; + noIntersection = false; + fe->setOccludeeIntersection(Vec3r(A + t * v)); + } + } + } + } + } + + if (noIntersection) + *oaPolygon = NULL; + } } -void ViewMapBuilder::FindOccludee(FEdge *fe, Grid *iGrid, real epsilon, Polygon3r **oaPolygon, unsigned timestamp) +void ViewMapBuilder::FindOccludee( + FEdge *fe, Grid *iGrid, real epsilon, Polygon3r **oaPolygon, unsigned timestamp) { - OccludersSet occluders; - - Vec3r A; - Vec3r edgeDir; - Vec3r origin; - A = Vec3r(((fe)->vertexA()->point3D() + (fe)->vertexB()->point3D()) / 2.0); - edgeDir = Vec3r((fe)->vertexB()->point3D() - (fe)->vertexA()->point3D()); - edgeDir.normalize(); - origin = Vec3r((fe)->vertexA()->point3D()); - Vec3r u; - if (_orthographicProjection) { - u = Vec3r(0.0, 0.0, _viewpoint.z() - A.z()); - } - else { - u = Vec3r(_viewpoint - A); - } - u.normalize(); - if (A < iGrid->getOrigin()) - cerr << "Warning: point is out of the grid for fedge " << fe->getId().getFirst() << "-" << - fe->getId().getSecond() << endl; - - vector<WVertex*> faceVertices; - - WFace *face = NULL; - if (fe->isSmooth()) { - FEdgeSmooth *fes = dynamic_cast<FEdgeSmooth*>(fe); - face = (WFace *)fes->face(); - } - if (face) - face->RetrieveVertexList(faceVertices); - - return FindOccludee(fe, iGrid, epsilon, oaPolygon, timestamp, u, A, origin, edgeDir, faceVertices); + OccludersSet occluders; + + Vec3r A; + Vec3r edgeDir; + Vec3r origin; + A = Vec3r(((fe)->vertexA()->point3D() + (fe)->vertexB()->point3D()) / 2.0); + edgeDir = Vec3r((fe)->vertexB()->point3D() - (fe)->vertexA()->point3D()); + edgeDir.normalize(); + origin = Vec3r((fe)->vertexA()->point3D()); + Vec3r u; + if (_orthographicProjection) { + u = Vec3r(0.0, 0.0, _viewpoint.z() - A.z()); + } + else { + u = Vec3r(_viewpoint - A); + } + u.normalize(); + if (A < iGrid->getOrigin()) + cerr << "Warning: point is out of the grid for fedge " << fe->getId().getFirst() << "-" + << fe->getId().getSecond() << endl; + + vector<WVertex *> faceVertices; + + WFace *face = NULL; + if (fe->isSmooth()) { + FEdgeSmooth *fes = dynamic_cast<FEdgeSmooth *>(fe); + face = (WFace *)fes->face(); + } + if (face) + face->RetrieveVertexList(faceVertices); + + return FindOccludee( + fe, iGrid, epsilon, oaPolygon, timestamp, u, A, origin, edgeDir, faceVertices); } -int ViewMapBuilder::ComputeRayCastingVisibility(FEdge *fe, Grid *iGrid, real epsilon, set<ViewShape*>& oOccluders, - Polygon3r **oaPolygon, unsigned timestamp) +int ViewMapBuilder::ComputeRayCastingVisibility(FEdge *fe, + Grid *iGrid, + real epsilon, + set<ViewShape *> &oOccluders, + Polygon3r **oaPolygon, + unsigned timestamp) { - OccludersSet occluders; - int qi = 0; - - Vec3r center; - Vec3r edgeDir; - Vec3r origin; - - center = fe->center3d(); - edgeDir = Vec3r(fe->vertexB()->point3D() - fe->vertexA()->point3D()); - edgeDir.normalize(); - origin = Vec3r(fe->vertexA()->point3D()); - // Is the edge outside the view frustum ? - Vec3r gridOrigin(iGrid->getOrigin()); - Vec3r gridExtremity(iGrid->getOrigin() + iGrid->gridSize()); - - if ((center.x() < gridOrigin.x()) || (center.y() < gridOrigin.y()) || (center.z() < gridOrigin.z()) || - (center.x() > gridExtremity.x()) || (center.y() > gridExtremity.y()) || (center.z() > gridExtremity.z())) - { - cerr << "Warning: point is out of the grid for fedge " << fe->getId() << endl; - //return 0; - } + OccludersSet occluders; + int qi = 0; + + Vec3r center; + Vec3r edgeDir; + Vec3r origin; + + center = fe->center3d(); + edgeDir = Vec3r(fe->vertexB()->point3D() - fe->vertexA()->point3D()); + edgeDir.normalize(); + origin = Vec3r(fe->vertexA()->point3D()); + // Is the edge outside the view frustum ? + Vec3r gridOrigin(iGrid->getOrigin()); + Vec3r gridExtremity(iGrid->getOrigin() + iGrid->gridSize()); + + if ((center.x() < gridOrigin.x()) || (center.y() < gridOrigin.y()) || + (center.z() < gridOrigin.z()) || (center.x() > gridExtremity.x()) || + (center.y() > gridExtremity.y()) || (center.z() > gridExtremity.z())) { + cerr << "Warning: point is out of the grid for fedge " << fe->getId() << endl; + //return 0; + } #if 0 - Vec3r A(fe->vertexA()->point2d()); - Vec3r B(fe->vertexB()->point2d()); - int viewport[4]; - SilhouetteGeomEngine::retrieveViewport(viewport); - if ((A.x() < viewport[0]) || (A.x() > viewport[2]) || (A.y() < viewport[1]) || (A.y() > viewport[3]) || - (B.x() < viewport[0]) || (B.x() > viewport[2]) || (B.y() < viewport[1]) || (B.y() > viewport[3])) - { - cerr << "Warning: point is out of the grid for fedge " << fe->getId() << endl; - //return 0; - } + Vec3r A(fe->vertexA()->point2d()); + Vec3r B(fe->vertexB()->point2d()); + int viewport[4]; + SilhouetteGeomEngine::retrieveViewport(viewport); + if ((A.x() < viewport[0]) || (A.x() > viewport[2]) || (A.y() < viewport[1]) || (A.y() > viewport[3]) || + (B.x() < viewport[0]) || (B.x() > viewport[2]) || (B.y() < viewport[1]) || (B.y() > viewport[3])) + { + cerr << "Warning: point is out of the grid for fedge " << fe->getId() << endl; + //return 0; + } #endif - Vec3r vp; - if (_orthographicProjection) { - vp = Vec3r(center.x(), center.y(), _viewpoint.z()); - } - else { - vp = Vec3r(_viewpoint); - } - Vec3r u(vp - center); - real raylength = u.norm(); - u.normalize(); + Vec3r vp; + if (_orthographicProjection) { + vp = Vec3r(center.x(), center.y(), _viewpoint.z()); + } + else { + vp = Vec3r(_viewpoint); + } + Vec3r u(vp - center); + real raylength = u.norm(); + u.normalize(); #if 0 - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "grid origin " << iGrid->getOrigin().x() << "," << iGrid->getOrigin().y() << "," - << iGrid->getOrigin().z() << endl; - cout << "center " << center.x() << "," << center.y() << "," << center.z() << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "grid origin " << iGrid->getOrigin().x() << "," << iGrid->getOrigin().y() << "," + << iGrid->getOrigin().z() << endl; + cout << "center " << center.x() << "," << center.y() << "," << center.z() << endl; + } #endif - iGrid->castRay(center, vp, occluders, timestamp); - - WFace *face = NULL; - if (fe->isSmooth()) { - FEdgeSmooth *fes = dynamic_cast<FEdgeSmooth *>(fe); - face = (WFace *)fes->face(); - } - vector<WVertex *> faceVertices; - WVertex::incoming_edge_iterator ie; - - WFace *oface; - bool skipFace; - OccludersSet::iterator p, pend; - if (face) - face->RetrieveVertexList(faceVertices); - - for (p = occluders.begin(), pend = occluders.end(); p != pend; p++) { - // If we're dealing with an exact silhouette, check whether we must take care of this occluder of not. - // (Indeed, we don't consider the occluders that share at least one vertex with the face containing this edge). - //----------- - oface = (WFace *)(*p)->userdata; + iGrid->castRay(center, vp, occluders, timestamp); + + WFace *face = NULL; + if (fe->isSmooth()) { + FEdgeSmooth *fes = dynamic_cast<FEdgeSmooth *>(fe); + face = (WFace *)fes->face(); + } + vector<WVertex *> faceVertices; + WVertex::incoming_edge_iterator ie; + + WFace *oface; + bool skipFace; + OccludersSet::iterator p, pend; + if (face) + face->RetrieveVertexList(faceVertices); + + for (p = occluders.begin(), pend = occluders.end(); p != pend; p++) { + // If we're dealing with an exact silhouette, check whether we must take care of this occluder of not. + // (Indeed, we don't consider the occluders that share at least one vertex with the face containing this edge). + //----------- + oface = (WFace *)(*p)->userdata; #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\t\tEvaluating intersection for occluder " << ((*p)->getVertices())[0] << - ((*p)->getVertices())[1] << ((*p)->getVertices())[2] << endl << "\t\t\tand ray " << vp << - " * " << u << " (center " << center << ")" << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\t\tEvaluating intersection for occluder " << ((*p)->getVertices())[0] + << ((*p)->getVertices())[1] << ((*p)->getVertices())[2] << endl + << "\t\t\tand ray " << vp << " * " << u << " (center " << center << ")" << endl; + } #endif - Vec3r v1(((*p)->getVertices())[0]); - Vec3r normal((*p)->getNormal()); - real d = -(v1 * normal); - real t, t_u, t_v; + Vec3r v1(((*p)->getVertices())[0]); + Vec3r normal((*p)->getNormal()); + real d = -(v1 * normal); + real t, t_u, t_v; #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\t\tp: " << ((*p)->getVertices())[0] << ((*p)->getVertices())[1] << ((*p)->getVertices())[2] << - ", norm: " << (*p)->getNormal() << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\t\tp: " << ((*p)->getVertices())[0] << ((*p)->getVertices())[1] + << ((*p)->getVertices())[2] << ", norm: " << (*p)->getNormal() << endl; + } #endif - if (face) { + if (face) { #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\t\tDetermining face adjacency..."; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\t\tDetermining face adjacency..."; + } #endif - skipFace = false; + skipFace = false; - if (face == oface) { + if (face == oface) { #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << " Rejecting occluder for face concurrency." << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << " Rejecting occluder for face concurrency." << endl; + } #endif - continue; - } - - for (vector<WVertex*>::iterator fv = faceVertices.begin(), fvend = faceVertices.end(); - fv != fvend; - ++fv) - { - if ((*fv)->isBoundary()) - continue; - - WVertex::incoming_edge_iterator iebegin = (*fv)->incoming_edges_begin(); - WVertex::incoming_edge_iterator ieend = (*fv)->incoming_edges_end(); - for (ie = iebegin; ie != ieend; ++ie) { - if ((*ie) == 0) - continue; - - WFace *sface = (*ie)->GetbFace(); - //WFace *sfacea = (*ie)->GetaFace(); - //if ((sface == oface) || (sfacea == oface)) { - if (sface == oface) { - skipFace = true; - break; - } - } - if (skipFace) - break; - } - if (skipFace) { + continue; + } + + for (vector<WVertex *>::iterator fv = faceVertices.begin(), fvend = faceVertices.end(); + fv != fvend; + ++fv) { + if ((*fv)->isBoundary()) + continue; + + WVertex::incoming_edge_iterator iebegin = (*fv)->incoming_edges_begin(); + WVertex::incoming_edge_iterator ieend = (*fv)->incoming_edges_end(); + for (ie = iebegin; ie != ieend; ++ie) { + if ((*ie) == 0) + continue; + + WFace *sface = (*ie)->GetbFace(); + //WFace *sfacea = (*ie)->GetaFace(); + //if ((sface == oface) || (sfacea == oface)) { + if (sface == oface) { + skipFace = true; + break; + } + } + if (skipFace) + break; + } + if (skipFace) { #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << " Rejecting occluder for face adjacency." << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << " Rejecting occluder for face adjacency." << endl; + } #endif - continue; - } - } - else { - // check whether the edge and the polygon plane are coincident: - //------------------------------------------------------------- - //first let us compute the plane equation. - - if (GeomUtils::COINCIDENT == GeomUtils::intersectRayPlane(origin, edgeDir, normal, d, t, epsilon)) { + continue; + } + } + else { + // check whether the edge and the polygon plane are coincident: + //------------------------------------------------------------- + //first let us compute the plane equation. + + if (GeomUtils::COINCIDENT == + GeomUtils::intersectRayPlane(origin, edgeDir, normal, d, t, epsilon)) { #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\t\tRejecting occluder for target coincidence." << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\t\tRejecting occluder for target coincidence." << endl; + } #endif - continue; - } - } + continue; + } + } - if ((*p)->rayIntersect(center, u, t, t_u, t_v)) { + if ((*p)->rayIntersect(center, u, t, t_u, t_v)) { #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\t\tRay " << vp << " * " << u << " intersects at time " << t << " (raylength is " << - raylength << ")" << endl; - cout << "\t\t(u * normal) == " << (u * normal) << " for normal " << normal << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\t\tRay " << vp << " * " << u << " intersects at time " << t << " (raylength is " + << raylength << ")" << endl; + cout << "\t\t(u * normal) == " << (u * normal) << " for normal " << normal << endl; + } #endif - if (fabs(u * normal) > 0.0001) { - if ((t>0.0) && (t<raylength)) { + if (fabs(u * normal) > 0.0001) { + if ((t > 0.0) && (t < raylength)) { #if LOGGING - if (_global.debug & G_DEBUG_FREESTYLE) { - cout << "\t\tIs occluder" << endl; - } + if (_global.debug & G_DEBUG_FREESTYLE) { + cout << "\t\tIs occluder" << endl; + } #endif - WFace *f = (WFace *)((*p)->userdata); - ViewShape *vshape = _ViewMap->viewShape(f->GetVertex(0)->shape()->GetId()); - oOccluders.insert(vshape); - ++qi; - if (!_EnableQI) - break; - } - } - } - } - - // Find occludee - FindOccludee(fe, iGrid, epsilon, oaPolygon, timestamp, u, center, origin, edgeDir, faceVertices); - - return qi; + WFace *f = (WFace *)((*p)->userdata); + ViewShape *vshape = _ViewMap->viewShape(f->GetVertex(0)->shape()->GetId()); + oOccluders.insert(vshape); + ++qi; + if (!_EnableQI) + break; + } + } + } + } + + // Find occludee + FindOccludee(fe, iGrid, epsilon, oaPolygon, timestamp, u, center, origin, edgeDir, faceVertices); + + return qi; } -void ViewMapBuilder::ComputeIntersections(ViewMap *ioViewMap, intersection_algo iAlgo, real epsilon) +void ViewMapBuilder::ComputeIntersections(ViewMap *ioViewMap, + intersection_algo iAlgo, + real epsilon) { - switch (iAlgo) { - case sweep_line: - ComputeSweepLineIntersections(ioViewMap, epsilon); - break; - default: - break; - } + switch (iAlgo) { + case sweep_line: + ComputeSweepLineIntersections(ioViewMap, epsilon); + break; + default: + break; + } #if 0 - if (_global.debug & G_DEBUG_FREESTYLE) { - ViewMap::viewvertices_container& vvertices = ioViewMap->ViewVertices(); - for (ViewMap::viewvertices_container::iterator vv = vvertices.begin(), vvend = vvertices.end(); - vv != vvend; ++vv) - { - if ((*vv)->getNature() == Nature::T_VERTEX) { - TVertex *tvertex = (TVertex *)(*vv); - cout << "TVertex " << tvertex->getId() << " has :" << endl; - cout << "FrontEdgeA: " << tvertex->frontEdgeA().first << endl; - cout << "FrontEdgeB: " << tvertex->frontEdgeB().first << endl; - cout << "BackEdgeA: " << tvertex->backEdgeA().first << endl; - cout << "BackEdgeB: " << tvertex->backEdgeB().first << endl << endl; - } - } - } + if (_global.debug & G_DEBUG_FREESTYLE) { + ViewMap::viewvertices_container& vvertices = ioViewMap->ViewVertices(); + for (ViewMap::viewvertices_container::iterator vv = vvertices.begin(), vvend = vvertices.end(); + vv != vvend; ++vv) + { + if ((*vv)->getNature() == Nature::T_VERTEX) { + TVertex *tvertex = (TVertex *)(*vv); + cout << "TVertex " << tvertex->getId() << " has :" << endl; + cout << "FrontEdgeA: " << tvertex->frontEdgeA().first << endl; + cout << "FrontEdgeB: " << tvertex->frontEdgeB().first << endl; + cout << "BackEdgeA: " << tvertex->backEdgeA().first << endl; + cout << "BackEdgeB: " << tvertex->backEdgeB().first << endl << endl; + } + } + } #endif } -struct less_SVertex2D : public binary_function<SVertex *, SVertex *, bool> -{ - real epsilon; - - less_SVertex2D(real eps) : binary_function<SVertex *, SVertex *, bool>() - { - epsilon = eps; - } - - bool operator()(SVertex *x, SVertex *y) - { - Vec3r A = x->point2D(); - Vec3r B = y->point2D(); - for (unsigned int i = 0; i < 3; i++) { - if ((fabs(A[i] - B[i])) < epsilon) - continue; - if (A[i] < B[i]) - return true; - if (A[i] > B[i]) - return false; - } - return false; - } +struct less_SVertex2D : public binary_function<SVertex *, SVertex *, bool> { + real epsilon; + + less_SVertex2D(real eps) : binary_function<SVertex *, SVertex *, bool>() + { + epsilon = eps; + } + + bool operator()(SVertex *x, SVertex *y) + { + Vec3r A = x->point2D(); + Vec3r B = y->point2D(); + for (unsigned int i = 0; i < 3; i++) { + if ((fabs(A[i] - B[i])) < epsilon) + continue; + if (A[i] < B[i]) + return true; + if (A[i] > B[i]) + return false; + } + return false; + } }; typedef Segment<FEdge *, Vec3r> segment; typedef Intersection<segment> intersection; -struct less_Intersection : public binary_function<intersection *, intersection *, bool> -{ - segment *edge; - - less_Intersection(segment *iEdge) : binary_function<intersection *, intersection *, bool>() - { - edge = iEdge; - } - - bool operator()(intersection *x, intersection *y) - { - real tx = x->getParameter(edge); - real ty = y->getParameter(edge); - if (tx > ty) - return true; - return false; - } +struct less_Intersection : public binary_function<intersection *, intersection *, bool> { + segment *edge; + + less_Intersection(segment *iEdge) : binary_function<intersection *, intersection *, bool>() + { + edge = iEdge; + } + + bool operator()(intersection *x, intersection *y) + { + real tx = x->getParameter(edge); + real ty = y->getParameter(edge); + if (tx > ty) + return true; + return false; + } }; -struct silhouette_binary_rule : public binary_rule<segment, segment> -{ - silhouette_binary_rule() : binary_rule<segment, segment>() {} +struct silhouette_binary_rule : public binary_rule<segment, segment> { + silhouette_binary_rule() : binary_rule<segment, segment>() + { + } - virtual bool operator()(segment& s1, segment& s2) - { - FEdge *f1 = s1.edge(); - FEdge *f2 = s2.edge(); + virtual bool operator()(segment &s1, segment &s2) + { + FEdge *f1 = s1.edge(); + FEdge *f2 = s2.edge(); - if ((!(((f1)->getNature() & Nature::SILHOUETTE) || ((f1)->getNature() & Nature::BORDER))) && - (!(((f2)->getNature() & Nature::SILHOUETTE) || ((f2)->getNature() & Nature::BORDER)))) - { - return false; - } + if ((!(((f1)->getNature() & Nature::SILHOUETTE) || ((f1)->getNature() & Nature::BORDER))) && + (!(((f2)->getNature() & Nature::SILHOUETTE) || ((f2)->getNature() & Nature::BORDER)))) { + return false; + } - return true; - } + return true; + } }; void ViewMapBuilder::ComputeSweepLineIntersections(ViewMap *ioViewMap, real epsilon) { - vector<SVertex *>& svertices = ioViewMap->SVertices(); - bool progressBarDisplay = false; - unsigned sVerticesSize = svertices.size(); - unsigned fEdgesSize = ioViewMap->FEdges().size(); + vector<SVertex *> &svertices = ioViewMap->SVertices(); + bool progressBarDisplay = false; + unsigned sVerticesSize = svertices.size(); + unsigned fEdgesSize = ioViewMap->FEdges().size(); #if 0 - if (_global.debug & G_DEBUG_FREESTYLE) { - ViewMap::fedges_container& fedges = ioViewMap->FEdges(); - for (ViewMap::fedges_container::const_iterator f = fedges.begin(), end = fedges.end(); f != end; ++f) { - cout << (*f)->aMaterialIndex() << "-" << (*f)->bMaterialIndex() << endl; - } - } + if (_global.debug & G_DEBUG_FREESTYLE) { + ViewMap::fedges_container& fedges = ioViewMap->FEdges(); + for (ViewMap::fedges_container::const_iterator f = fedges.begin(), end = fedges.end(); f != end; ++f) { + cout << (*f)->aMaterialIndex() << "-" << (*f)->bMaterialIndex() << endl; + } + } #endif - unsigned progressBarStep = 0; - - if (_pProgressBar != NULL && fEdgesSize > gProgressBarMinSize) { - unsigned progressBarSteps = min(gProgressBarMaxSteps, sVerticesSize); - progressBarStep = sVerticesSize / progressBarSteps; - _pProgressBar->reset(); - _pProgressBar->setLabelText("Computing Sweep Line Intersections"); - _pProgressBar->setTotalSteps(progressBarSteps); - _pProgressBar->setProgress(0); - progressBarDisplay = true; - } - - unsigned counter = progressBarStep; - - sort(svertices.begin(), svertices.end(), less_SVertex2D(epsilon)); - - SweepLine<FEdge *, Vec3r> SL; - - vector<FEdge *>& ioEdges = ioViewMap->FEdges(); - - vector<segment*> segments; - - vector<FEdge*>::iterator fe, fend; - - for (fe = ioEdges.begin(), fend = ioEdges.end(); fe != fend; fe++) { - segment *s = new segment((*fe), (*fe)->vertexA()->point2D(), (*fe)->vertexB()->point2D()); - (*fe)->userdata = s; - segments.push_back(s); - } - - vector<segment*> vsegments; - for (vector<SVertex*>::iterator sv = svertices.begin(), svend = svertices.end(); sv != svend; sv++) { - if (_pRenderMonitor && _pRenderMonitor->testBreak()) - break; - - const vector<FEdge*>& vedges = (*sv)->fedges(); - - for (vector<FEdge *>::const_iterator sve = vedges.begin(), sveend = vedges.end(); sve != sveend; sve++) { - vsegments.push_back((segment *)((*sve)->userdata)); - } - - Vec3r evt((*sv)->point2D()); - silhouette_binary_rule sbr; - SL.process(evt, vsegments, sbr, epsilon); - - if (progressBarDisplay) { - counter--; - if (counter <= 0) { - counter = progressBarStep; - _pProgressBar->setProgress(_pProgressBar->getProgress() + 1); - } - } - vsegments.clear(); - } - - if (_pRenderMonitor && _pRenderMonitor->testBreak()) { - // delete segments - if (!segments.empty()) { - vector<segment*>::iterator s, send; - for (s = segments.begin(), send = segments.end(); s != send; s++) { - delete *s; - } - } - return; - } - - // reset userdata: - for (fe = ioEdges.begin(), fend = ioEdges.end(); fe != fend; fe++) - (*fe)->userdata = NULL; - - // list containing the new edges resulting from splitting operations. - vector<FEdge*> newEdges; - - // retrieve the intersected edges: - vector<segment*>& iedges = SL.intersectedEdges(); - // retrieve the intersections: - vector<intersection*>& intersections = SL.intersections(); - - int id = 0; - // create a view vertex for each intersection and linked this one with the intersection object - vector<intersection*>::iterator i, iend; - for (i = intersections.begin(), iend = intersections.end(); i != iend; i++) { - FEdge *fA = (*i)->EdgeA->edge(); - FEdge *fB = (*i)->EdgeB->edge(); - - Vec3r A1 = fA->vertexA()->point3D(); - Vec3r A2 = fA->vertexB()->point3D(); - Vec3r B1 = fB->vertexA()->point3D(); - Vec3r B2 = fB->vertexB()->point3D(); - - Vec3r a1 = fA->vertexA()->point2D(); - Vec3r a2 = fA->vertexB()->point2D(); - Vec3r b1 = fB->vertexA()->point2D(); - Vec3r b2 = fB->vertexB()->point2D(); - - real ta = (*i)->tA; - real tb = (*i)->tB; - - if ((ta < -epsilon) || (ta > 1 + epsilon)) - cerr << "Warning: 2D intersection out of range for edge " << fA->vertexA()->getId() << " - " << - fA->vertexB()->getId() << endl; - - if ((tb < -epsilon) || (tb > 1 + epsilon)) - cerr << "Warning: 2D intersection out of range for edge " << fB->vertexA()->getId() << " - " << - fB->vertexB()->getId() << endl; - - real Ta = SilhouetteGeomEngine::ImageToWorldParameter(fA, ta); - real Tb = SilhouetteGeomEngine::ImageToWorldParameter(fB, tb); - - if ((Ta < -epsilon) || (Ta > 1 + epsilon)) - cerr << "Warning: 3D intersection out of range for edge " << fA->vertexA()->getId() << " - " << - fA->vertexB()->getId() << endl; - - if ((Tb < -epsilon) || (Tb > 1 + epsilon)) - cerr << "Warning: 3D intersection out of range for edge " << fB->vertexA()->getId() << " - " << - fB->vertexB()->getId() << endl; + unsigned progressBarStep = 0; + + if (_pProgressBar != NULL && fEdgesSize > gProgressBarMinSize) { + unsigned progressBarSteps = min(gProgressBarMaxSteps, sVerticesSize); + progressBarStep = sVerticesSize / progressBarSteps; + _pProgressBar->reset(); + _pProgressBar->setLabelText("Computing Sweep Line Intersections"); + _pProgressBar->setTotalSteps(progressBarSteps); + _pProgressBar->setProgress(0); + progressBarDisplay = true; + } + + unsigned counter = progressBarStep; + + sort(svertices.begin(), svertices.end(), less_SVertex2D(epsilon)); + + SweepLine<FEdge *, Vec3r> SL; + + vector<FEdge *> &ioEdges = ioViewMap->FEdges(); + + vector<segment *> segments; + + vector<FEdge *>::iterator fe, fend; + + for (fe = ioEdges.begin(), fend = ioEdges.end(); fe != fend; fe++) { + segment *s = new segment((*fe), (*fe)->vertexA()->point2D(), (*fe)->vertexB()->point2D()); + (*fe)->userdata = s; + segments.push_back(s); + } + + vector<segment *> vsegments; + for (vector<SVertex *>::iterator sv = svertices.begin(), svend = svertices.end(); sv != svend; + sv++) { + if (_pRenderMonitor && _pRenderMonitor->testBreak()) + break; + + const vector<FEdge *> &vedges = (*sv)->fedges(); + + for (vector<FEdge *>::const_iterator sve = vedges.begin(), sveend = vedges.end(); + sve != sveend; + sve++) { + vsegments.push_back((segment *)((*sve)->userdata)); + } + + Vec3r evt((*sv)->point2D()); + silhouette_binary_rule sbr; + SL.process(evt, vsegments, sbr, epsilon); + + if (progressBarDisplay) { + counter--; + if (counter <= 0) { + counter = progressBarStep; + _pProgressBar->setProgress(_pProgressBar->getProgress() + 1); + } + } + vsegments.clear(); + } + + if (_pRenderMonitor && _pRenderMonitor->testBreak()) { + // delete segments + if (!segments.empty()) { + vector<segment *>::iterator s, send; + for (s = segments.begin(), send = segments.end(); s != send; s++) { + delete *s; + } + } + return; + } + + // reset userdata: + for (fe = ioEdges.begin(), fend = ioEdges.end(); fe != fend; fe++) + (*fe)->userdata = NULL; + + // list containing the new edges resulting from splitting operations. + vector<FEdge *> newEdges; + + // retrieve the intersected edges: + vector<segment *> &iedges = SL.intersectedEdges(); + // retrieve the intersections: + vector<intersection *> &intersections = SL.intersections(); + + int id = 0; + // create a view vertex for each intersection and linked this one with the intersection object + vector<intersection *>::iterator i, iend; + for (i = intersections.begin(), iend = intersections.end(); i != iend; i++) { + FEdge *fA = (*i)->EdgeA->edge(); + FEdge *fB = (*i)->EdgeB->edge(); + + Vec3r A1 = fA->vertexA()->point3D(); + Vec3r A2 = fA->vertexB()->point3D(); + Vec3r B1 = fB->vertexA()->point3D(); + Vec3r B2 = fB->vertexB()->point3D(); + + Vec3r a1 = fA->vertexA()->point2D(); + Vec3r a2 = fA->vertexB()->point2D(); + Vec3r b1 = fB->vertexA()->point2D(); + Vec3r b2 = fB->vertexB()->point2D(); + + real ta = (*i)->tA; + real tb = (*i)->tB; + + if ((ta < -epsilon) || (ta > 1 + epsilon)) + cerr << "Warning: 2D intersection out of range for edge " << fA->vertexA()->getId() << " - " + << fA->vertexB()->getId() << endl; + + if ((tb < -epsilon) || (tb > 1 + epsilon)) + cerr << "Warning: 2D intersection out of range for edge " << fB->vertexA()->getId() << " - " + << fB->vertexB()->getId() << endl; + + real Ta = SilhouetteGeomEngine::ImageToWorldParameter(fA, ta); + real Tb = SilhouetteGeomEngine::ImageToWorldParameter(fB, tb); + + if ((Ta < -epsilon) || (Ta > 1 + epsilon)) + cerr << "Warning: 3D intersection out of range for edge " << fA->vertexA()->getId() << " - " + << fA->vertexB()->getId() << endl; + + if ((Tb < -epsilon) || (Tb > 1 + epsilon)) + cerr << "Warning: 3D intersection out of range for edge " << fB->vertexA()->getId() << " - " + << fB->vertexB()->getId() << endl; #if 0 - if (_global.debug & G_DEBUG_FREESTYLE) { - if ((Ta < -epsilon) || (Ta > 1 + epsilon) || (Tb < -epsilon) || (Tb > 1 + epsilon)) { - printf("ta %.12e\n", ta); - printf("tb %.12e\n", tb); - printf("a1 %e, %e -- a2 %e, %e\n", a1[0], a1[1], a2[0], a2[1]); - printf("b1 %e, %e -- b2 %e, %e\n", b1[0], b1[1], b2[0], b2[1]); - //printf("line([%e, %e], [%e, %e]);\n", a1[0], a2[0], a1[1], a2[1]); - //printf("line([%e, %e], [%e, %e]);\n", b1[0], b2[0], b1[1], b2[1]); - if ((Ta < -epsilon) || (Ta > 1 + epsilon)) - printf("Ta %.12e\n", Ta); - if ((Tb < -epsilon) || (Tb > 1 + epsilon)) - printf("Tb %.12e\n", Tb); - printf("A1 %e, %e, %e -- A2 %e, %e, %e\n", A1[0], A1[1], A1[2], A2[0], A2[1], A2[2]); - printf("B1 %e, %e, %e -- B2 %e, %e, %e\n", B1[0], B1[1], B1[2], B2[0], B2[1], B2[2]); - } - } + if (_global.debug & G_DEBUG_FREESTYLE) { + if ((Ta < -epsilon) || (Ta > 1 + epsilon) || (Tb < -epsilon) || (Tb > 1 + epsilon)) { + printf("ta %.12e\n", ta); + printf("tb %.12e\n", tb); + printf("a1 %e, %e -- a2 %e, %e\n", a1[0], a1[1], a2[0], a2[1]); + printf("b1 %e, %e -- b2 %e, %e\n", b1[0], b1[1], b2[0], b2[1]); + //printf("line([%e, %e], [%e, %e]);\n", a1[0], a2[0], a1[1], a2[1]); + //printf("line([%e, %e], [%e, %e]);\n", b1[0], b2[0], b1[1], b2[1]); + if ((Ta < -epsilon) || (Ta > 1 + epsilon)) + printf("Ta %.12e\n", Ta); + if ((Tb < -epsilon) || (Tb > 1 + epsilon)) + printf("Tb %.12e\n", Tb); + printf("A1 %e, %e, %e -- A2 %e, %e, %e\n", A1[0], A1[1], A1[2], A2[0], A2[1], A2[2]); + printf("B1 %e, %e, %e -- B2 %e, %e, %e\n", B1[0], B1[1], B1[2], B2[0], B2[1], B2[2]); + } + } #endif - TVertex *tvertex = ioViewMap->CreateTVertex(Vec3r(A1 + Ta * (A2 - A1)), Vec3r(a1 + ta * (a2 - a1)), fA, - Vec3r(B1 + Tb * (B2 - B1)), Vec3r(b1 + tb * (b2 - b1)), fB, id); - - (*i)->userdata = tvertex; - ++id; - } - - progressBarStep = 0; - - if (progressBarDisplay) { - unsigned iEdgesSize = iedges.size(); - unsigned progressBarSteps = min(gProgressBarMaxSteps, iEdgesSize); - progressBarStep = iEdgesSize / progressBarSteps; - _pProgressBar->reset(); - _pProgressBar->setLabelText("Splitting intersected edges"); - _pProgressBar->setTotalSteps(progressBarSteps); - _pProgressBar->setProgress(0); - } - - counter = progressBarStep; - - vector<TVertex*> edgeVVertices; - vector<ViewEdge*> newVEdges; - vector<segment*>::iterator s, send; - for (s = iedges.begin(), send = iedges.end(); s != send; s++) { - edgeVVertices.clear(); - newEdges.clear(); - newVEdges.clear(); - - FEdge *fedge = (*s)->edge(); - ViewEdge *vEdge = fedge->viewedge(); - ViewShape *shape = vEdge->viewShape(); - - vector<intersection*>& eIntersections = (*s)->intersections(); - // we first need to sort these intersections from farther to closer to A - sort(eIntersections.begin(), eIntersections.end(), less_Intersection(*s)); - for (i = eIntersections.begin(), iend = eIntersections.end(); i != iend; i++) - edgeVVertices.push_back((TVertex *)(*i)->userdata); - - shape->SplitEdge(fedge, edgeVVertices, ioViewMap->FEdges(), ioViewMap->ViewEdges()); - - if (progressBarDisplay) { - counter--; - if (counter <= 0) { - counter = progressBarStep; - _pProgressBar->setProgress(_pProgressBar->getProgress() + 1); - } - } - } - - // reset userdata: - for (fe = ioEdges.begin(), fend = ioEdges.end(); fe != fend; fe++) - (*fe)->userdata = NULL; - - // delete segments - if (!segments.empty()) { - for (s = segments.begin(), send = segments.end(); s != send; s++) { - delete *s; - } - } + TVertex *tvertex = ioViewMap->CreateTVertex(Vec3r(A1 + Ta * (A2 - A1)), + Vec3r(a1 + ta * (a2 - a1)), + fA, + Vec3r(B1 + Tb * (B2 - B1)), + Vec3r(b1 + tb * (b2 - b1)), + fB, + id); + + (*i)->userdata = tvertex; + ++id; + } + + progressBarStep = 0; + + if (progressBarDisplay) { + unsigned iEdgesSize = iedges.size(); + unsigned progressBarSteps = min(gProgressBarMaxSteps, iEdgesSize); + progressBarStep = iEdgesSize / progressBarSteps; + _pProgressBar->reset(); + _pProgressBar->setLabelText("Splitting intersected edges"); + _pProgressBar->setTotalSteps(progressBarSteps); + _pProgressBar->setProgress(0); + } + + counter = progressBarStep; + + vector<TVertex *> edgeVVertices; + vector<ViewEdge *> newVEdges; + vector<segment *>::iterator s, send; + for (s = iedges.begin(), send = iedges.end(); s != send; s++) { + edgeVVertices.clear(); + newEdges.clear(); + newVEdges.clear(); + + FEdge *fedge = (*s)->edge(); + ViewEdge *vEdge = fedge->viewedge(); + ViewShape *shape = vEdge->viewShape(); + + vector<intersection *> &eIntersections = (*s)->intersections(); + // we first need to sort these intersections from farther to closer to A + sort(eIntersections.begin(), eIntersections.end(), less_Intersection(*s)); + for (i = eIntersections.begin(), iend = eIntersections.end(); i != iend; i++) + edgeVVertices.push_back((TVertex *)(*i)->userdata); + + shape->SplitEdge(fedge, edgeVVertices, ioViewMap->FEdges(), ioViewMap->ViewEdges()); + + if (progressBarDisplay) { + counter--; + if (counter <= 0) { + counter = progressBarStep; + _pProgressBar->setProgress(_pProgressBar->getProgress() + 1); + } + } + } + + // reset userdata: + for (fe = ioEdges.begin(), fend = ioEdges.end(); fe != fend; fe++) + (*fe)->userdata = NULL; + + // delete segments + if (!segments.empty()) { + for (s = segments.begin(), send = segments.end(); s != send; s++) { + delete *s; + } + } } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/view_map/ViewMapBuilder.h b/source/blender/freestyle/intern/view_map/ViewMapBuilder.h index 4148ef5e436..0e3dbf9148e 100644 --- a/source/blender/freestyle/intern/view_map/ViewMapBuilder.h +++ b/source/blender/freestyle/intern/view_map/ViewMapBuilder.h @@ -47,210 +47,246 @@ #include "../winged_edge/WXEdge.h" #ifdef WITH_CXX_GUARDEDALLOC -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif namespace Freestyle { using namespace Geometry; -class ViewMapBuilder -{ -private: - ViewMap *_ViewMap; // result - //SilhouetteGeomEngine _GeomEngine; - ProgressBar *_pProgressBar; - RenderMonitor *_pRenderMonitor; - Vec3r _viewpoint; - bool _orthographicProjection; - Grid *_Grid; - ViewEdgeXBuilder *_pViewEdgeBuilder; - bool _EnableQI; - double _epsilon; - - // tmp values: - int _currentId; - int _currentFId; - int _currentSVertexId; - -public: - typedef enum { - sweep_line, - } intersection_algo; - - typedef enum { - ray_casting, - ray_casting_fast, - ray_casting_very_fast, - ray_casting_culled_adaptive_traditional, - ray_casting_adaptive_traditional, - ray_casting_culled_adaptive_cumulative, - ray_casting_adaptive_cumulative, - } visibility_algo; - - inline ViewMapBuilder() - { - _pProgressBar = NULL; - _pRenderMonitor = NULL; - _Grid = NULL; - _currentId = 1; - _currentFId = 0; - _currentSVertexId = 0; - _pViewEdgeBuilder = new ViewEdgeXBuilder; - _EnableQI = true; - } - - inline ~ViewMapBuilder() - { - if (_pViewEdgeBuilder) { - delete _pViewEdgeBuilder; - _pViewEdgeBuilder = NULL; - } - } - - /* Build Grid for ray casting */ - /*! Build non-culled Grid in camera space for ray casting */ - void BuildGrid(WingedEdge& we, const BBox<Vec3r>& bbox, unsigned int sceneNumFaces); - - /*! Compute Shapes from a WingedEdge containing a list of WShapes */ - void computeInitialViewEdges(WingedEdge&); - - /*! Compute Cusps */ - void computeCusps(ViewMap *ioViewMap); - - /*! Detects cusps (for a single ViewEdge) among SVertices and builds a ViewVertex on top of each cusp SVertex - * We use a hysteresis approach to avoid noise. - */ - void DetectCusps(ViewEdge *ioEdge); - - /*! Sets the current viewpoint */ - inline void setViewpoint(const Vec3r& ivp) - { - _viewpoint = ivp; - SilhouetteGeomEngine::setViewpoint(ivp); - } - - /*! Sets the current transformation - * iModelViewMatrix - * The 4x4 model view matrix, in column major order (openGL like). - * iProjection matrix - * The 4x4 projection matrix, in column major order (openGL like). - * iViewport - * The viewport. 4 real array: origin.x, origin.y, width, length - */ - inline void setTransform(const real iModelViewMatrix[4][4], const real iProjectionMatrix[4][4], - const int iViewport[4], real iFocalLength, real /*iAspect*/, real /*iFovy*/) - { - _orthographicProjection = (iProjectionMatrix[3][3] != 0.0); - SilhouetteGeomEngine::setTransform(iModelViewMatrix, iProjectionMatrix, iViewport, iFocalLength); - } - - inline void setFrustum(real iZnear, real iZfar) - { - SilhouetteGeomEngine::setFrustum(iZnear, iZfar); - } - - /*! Builds the scene view map returns the list the view map - * it is up to the caller to delete this ViewMap - * iWRoot - * The root group node containing the WEdge structured scene - */ - ViewMap *BuildViewMap(WingedEdge& we, visibility_algo iAlgo, real epsilon, const BBox<Vec3r>& bbox, - unsigned int sceneNumFaces); - - void CullViewEdges(ViewMap *ioViewMap, real viewProscenium[4], real occluderProscenium[4], - bool extensiveFEdgeSearch = true); - - /*! computes the intersection between all 2D feature edges of the scene. - * ioViewMap - * The view map. It is modified by the method. - * The list of all features edges of the scene. - * Each time an intersection is found, the 2 intersecting edges are splitted (creating 2 new vertices) - * At the end, this list is updated with the adding of all new created edges (resulting from splitting). - * iAlgo - * The algo to use for computing the intersections - */ - void ComputeIntersections(ViewMap *ioViewMap, intersection_algo iAlgo = sweep_line, real epsilon = 1.0e-06); - - /*! Computes the 2D scene silhouette edges visibility - * iGrid - * For the Ray Casting algorithm. - */ - void ComputeEdgesVisibility(ViewMap *ioViewMap, WingedEdge& we, const BBox<Vec3r>& bbox, unsigned int sceneNumFaces, - visibility_algo iAlgo = ray_casting, real epsilon = 1.0e-6); - - void setGrid(Grid *iGrid) - { - _Grid = iGrid; - } - - /*! accessors */ - - /*! Modifiers */ - inline void setProgressBar(ProgressBar *iProgressBar) - { - _pProgressBar = iProgressBar; - } - - inline void setRenderMonitor(RenderMonitor *iRenderMonitor) - { - _pRenderMonitor = iRenderMonitor; - } - - inline void setEnableQI(bool iBool) - { - _EnableQI = iBool; - } - -protected: - /*! Computes intersections on all edges of the scene using a sweep line algorithm */ - void ComputeSweepLineIntersections(ViewMap *ioViewMap, real epsilon = 1.0e-6); - - /*! Computes the 2D scene silhouette edges visibility using a ray casting. On each edge, a ray is cast - * to check its quantitative invisibility. The list of occluders are each time stored in the tested edge. - * ioViewMap - * The view map. - * The 2D scene silhouette edges as FEdges. - * These edges have already been splitted at their intersections points. - * Thus, these edges do not intersect anymore. - * The visibility corresponding to each edge of ioScene is set is this edge. - */ - void ComputeRayCastingVisibility(ViewMap *ioViewMap, real epsilon = 1.0e-6); - void ComputeFastRayCastingVisibility(ViewMap *ioViewMap, real epsilon = 1.0e-6); - void ComputeVeryFastRayCastingVisibility(ViewMap *ioViewMap, real epsilon = 1.0e-6); - - void ComputeCumulativeVisibility(ViewMap *ioViewMap, WingedEdge& we, const BBox<Vec3r>& bbox, real epsilon, - bool cull, GridDensityProviderFactory& factory); - void ComputeDetailedVisibility(ViewMap *ioViewMap, WingedEdge& we, const BBox<Vec3r>& bbox, real epsilon, - bool cull, GridDensityProviderFactory& factory); - - /*! Compute the visibility for the FEdge fe. - * The occluders are added to fe occluders list. - * fe - * The FEdge - * iGrid - * The grid used to compute the ray casting visibility - * epsilon - * The epsilon used for computation - * oShapeId - * fe is the border (in 2D) between 2 2D spaces. - * if fe is a silhouette, One of these 2D spaces is occupied by the shape to which fe belongs (on its left) - * and the other one is either occupied by another shape or empty or occupied by the same shape. - * We use this ray csating operation to determine which shape lies on fe's right. - * The result is the shape id stored in oShapeId - */ - int ComputeRayCastingVisibility(FEdge *fe, Grid *iGrid, real epsilon, set<ViewShape*>& oOccluders, - Polygon3r **oaPolygon, unsigned timestamp); - // FIXME - void FindOccludee(FEdge *fe, Grid *iGrid, real epsilon, Polygon3r **oaPolygon, unsigned timestamp); - void FindOccludee(FEdge *fe, Grid *iGrid, real epsilon, Polygon3r **oaPolygon, unsigned timestamp, - Vec3r& u, Vec3r& A, Vec3r& origin, Vec3r& edgeDir, vector<WVertex*>& faceVertices); +class ViewMapBuilder { + private: + ViewMap *_ViewMap; // result + //SilhouetteGeomEngine _GeomEngine; + ProgressBar *_pProgressBar; + RenderMonitor *_pRenderMonitor; + Vec3r _viewpoint; + bool _orthographicProjection; + Grid *_Grid; + ViewEdgeXBuilder *_pViewEdgeBuilder; + bool _EnableQI; + double _epsilon; + + // tmp values: + int _currentId; + int _currentFId; + int _currentSVertexId; + + public: + typedef enum { + sweep_line, + } intersection_algo; + + typedef enum { + ray_casting, + ray_casting_fast, + ray_casting_very_fast, + ray_casting_culled_adaptive_traditional, + ray_casting_adaptive_traditional, + ray_casting_culled_adaptive_cumulative, + ray_casting_adaptive_cumulative, + } visibility_algo; + + inline ViewMapBuilder() + { + _pProgressBar = NULL; + _pRenderMonitor = NULL; + _Grid = NULL; + _currentId = 1; + _currentFId = 0; + _currentSVertexId = 0; + _pViewEdgeBuilder = new ViewEdgeXBuilder; + _EnableQI = true; + } + + inline ~ViewMapBuilder() + { + if (_pViewEdgeBuilder) { + delete _pViewEdgeBuilder; + _pViewEdgeBuilder = NULL; + } + } + + /* Build Grid for ray casting */ + /*! Build non-culled Grid in camera space for ray casting */ + void BuildGrid(WingedEdge &we, const BBox<Vec3r> &bbox, unsigned int sceneNumFaces); + + /*! Compute Shapes from a WingedEdge containing a list of WShapes */ + void computeInitialViewEdges(WingedEdge &); + + /*! Compute Cusps */ + void computeCusps(ViewMap *ioViewMap); + + /*! Detects cusps (for a single ViewEdge) among SVertices and builds a ViewVertex on top of each cusp SVertex + * We use a hysteresis approach to avoid noise. + */ + void DetectCusps(ViewEdge *ioEdge); + + /*! Sets the current viewpoint */ + inline void setViewpoint(const Vec3r &ivp) + { + _viewpoint = ivp; + SilhouetteGeomEngine::setViewpoint(ivp); + } + + /*! Sets the current transformation + * iModelViewMatrix + * The 4x4 model view matrix, in column major order (openGL like). + * iProjection matrix + * The 4x4 projection matrix, in column major order (openGL like). + * iViewport + * The viewport. 4 real array: origin.x, origin.y, width, length + */ + inline void setTransform(const real iModelViewMatrix[4][4], + const real iProjectionMatrix[4][4], + const int iViewport[4], + real iFocalLength, + real /*iAspect*/, + real /*iFovy*/) + { + _orthographicProjection = (iProjectionMatrix[3][3] != 0.0); + SilhouetteGeomEngine::setTransform( + iModelViewMatrix, iProjectionMatrix, iViewport, iFocalLength); + } + + inline void setFrustum(real iZnear, real iZfar) + { + SilhouetteGeomEngine::setFrustum(iZnear, iZfar); + } + + /*! Builds the scene view map returns the list the view map + * it is up to the caller to delete this ViewMap + * iWRoot + * The root group node containing the WEdge structured scene + */ + ViewMap *BuildViewMap(WingedEdge &we, + visibility_algo iAlgo, + real epsilon, + const BBox<Vec3r> &bbox, + unsigned int sceneNumFaces); + + void CullViewEdges(ViewMap *ioViewMap, + real viewProscenium[4], + real occluderProscenium[4], + bool extensiveFEdgeSearch = true); + + /*! computes the intersection between all 2D feature edges of the scene. + * ioViewMap + * The view map. It is modified by the method. + * The list of all features edges of the scene. + * Each time an intersection is found, the 2 intersecting edges are splitted (creating 2 new vertices) + * At the end, this list is updated with the adding of all new created edges (resulting from splitting). + * iAlgo + * The algo to use for computing the intersections + */ + void ComputeIntersections(ViewMap *ioViewMap, + intersection_algo iAlgo = sweep_line, + real epsilon = 1.0e-06); + + /*! Computes the 2D scene silhouette edges visibility + * iGrid + * For the Ray Casting algorithm. + */ + void ComputeEdgesVisibility(ViewMap *ioViewMap, + WingedEdge &we, + const BBox<Vec3r> &bbox, + unsigned int sceneNumFaces, + visibility_algo iAlgo = ray_casting, + real epsilon = 1.0e-6); + + void setGrid(Grid *iGrid) + { + _Grid = iGrid; + } + + /*! accessors */ + + /*! Modifiers */ + inline void setProgressBar(ProgressBar *iProgressBar) + { + _pProgressBar = iProgressBar; + } + + inline void setRenderMonitor(RenderMonitor *iRenderMonitor) + { + _pRenderMonitor = iRenderMonitor; + } + + inline void setEnableQI(bool iBool) + { + _EnableQI = iBool; + } + + protected: + /*! Computes intersections on all edges of the scene using a sweep line algorithm */ + void ComputeSweepLineIntersections(ViewMap *ioViewMap, real epsilon = 1.0e-6); + + /*! Computes the 2D scene silhouette edges visibility using a ray casting. On each edge, a ray is cast + * to check its quantitative invisibility. The list of occluders are each time stored in the tested edge. + * ioViewMap + * The view map. + * The 2D scene silhouette edges as FEdges. + * These edges have already been splitted at their intersections points. + * Thus, these edges do not intersect anymore. + * The visibility corresponding to each edge of ioScene is set is this edge. + */ + void ComputeRayCastingVisibility(ViewMap *ioViewMap, real epsilon = 1.0e-6); + void ComputeFastRayCastingVisibility(ViewMap *ioViewMap, real epsilon = 1.0e-6); + void ComputeVeryFastRayCastingVisibility(ViewMap *ioViewMap, real epsilon = 1.0e-6); + + void ComputeCumulativeVisibility(ViewMap *ioViewMap, + WingedEdge &we, + const BBox<Vec3r> &bbox, + real epsilon, + bool cull, + GridDensityProviderFactory &factory); + void ComputeDetailedVisibility(ViewMap *ioViewMap, + WingedEdge &we, + const BBox<Vec3r> &bbox, + real epsilon, + bool cull, + GridDensityProviderFactory &factory); + + /*! Compute the visibility for the FEdge fe. + * The occluders are added to fe occluders list. + * fe + * The FEdge + * iGrid + * The grid used to compute the ray casting visibility + * epsilon + * The epsilon used for computation + * oShapeId + * fe is the border (in 2D) between 2 2D spaces. + * if fe is a silhouette, One of these 2D spaces is occupied by the shape to which fe belongs (on its left) + * and the other one is either occupied by another shape or empty or occupied by the same shape. + * We use this ray csating operation to determine which shape lies on fe's right. + * The result is the shape id stored in oShapeId + */ + int ComputeRayCastingVisibility(FEdge *fe, + Grid *iGrid, + real epsilon, + set<ViewShape *> &oOccluders, + Polygon3r **oaPolygon, + unsigned timestamp); + // FIXME + void FindOccludee( + FEdge *fe, Grid *iGrid, real epsilon, Polygon3r **oaPolygon, unsigned timestamp); + void FindOccludee(FEdge *fe, + Grid *iGrid, + real epsilon, + Polygon3r **oaPolygon, + unsigned timestamp, + Vec3r &u, + Vec3r &A, + Vec3r &origin, + Vec3r &edgeDir, + vector<WVertex *> &faceVertices); #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:ViewMapBuilder") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:ViewMapBuilder") #endif }; } /* namespace Freestyle */ -#endif // __FREESTYLE_VIEW_MAP_BUILDER_H__ +#endif // __FREESTYLE_VIEW_MAP_BUILDER_H__ diff --git a/source/blender/freestyle/intern/view_map/ViewMapIO.cpp b/source/blender/freestyle/intern/view_map/ViewMapIO.cpp index 6a37467a867..65336f593c7 100644 --- a/source/blender/freestyle/intern/view_map/ViewMapIO.cpp +++ b/source/blender/freestyle/intern/view_map/ViewMapIO.cpp @@ -31,22 +31,24 @@ # define READ(n) in.read((char *)(&(n)), sizeof((n))) #endif -#define WRITE_IF_NON_NULL(ptr) \ - if (ptr) { \ - WRITE((ptr)->userdata); \ - } \ - else { \ - WRITE(ZERO); \ - } (void)0 +#define WRITE_IF_NON_NULL(ptr) \ + if (ptr) { \ + WRITE((ptr)->userdata); \ + } \ + else { \ + WRITE(ZERO); \ + } \ + (void)0 #define READ_IF_NON_NULL(ptr, array) \ - READ(tmp); \ - if (tmp) { \ - (ptr) = (array)[tmp]; \ - } \ - else { \ - (ptr) = NULL; \ - } (void)0 + READ(tmp); \ + if (tmp) { \ + (ptr) = (array)[tmp]; \ + } \ + else { \ + (ptr) = NULL; \ + } \ + (void)0 namespace Freestyle { @@ -58,1155 +60,1170 @@ static ViewMap *g_vm; //////////////////// 'load' Functions //////////////////// -inline int load(istream& in, Vec3r& v) +inline int load(istream &in, Vec3r &v) { - if (Options::getFlags() & Options::FLOAT_VECTORS) { - float tmp; - READ(tmp); - v[0] = tmp; - READ(tmp); - v[1] = tmp; - READ(tmp); - v[2] = tmp; - } - else { - Vec3r::value_type tmp; - READ(tmp); - v[0] = tmp; - READ(tmp); - v[1] = tmp; - READ(tmp); - v[2] = tmp; - } - return 0; + if (Options::getFlags() & Options::FLOAT_VECTORS) { + float tmp; + READ(tmp); + v[0] = tmp; + READ(tmp); + v[1] = tmp; + READ(tmp); + v[2] = tmp; + } + else { + Vec3r::value_type tmp; + READ(tmp); + v[0] = tmp; + READ(tmp); + v[1] = tmp; + READ(tmp); + v[2] = tmp; + } + return 0; } -inline int load(istream& in, Polygon3r& p) +inline int load(istream &in, Polygon3r &p) { - unsigned tmp; - - // Id - READ(tmp); - p.setId(tmp); - - // vertices (List) - vector<Vec3r> tmp_vec; - Vec3r v; - READ(tmp); - for (unsigned int i = 0; i < tmp; i++) { - load(in, v); - tmp_vec.push_back(v); - } - p.setVertices(tmp_vec); - - // min & max - // Already computed (in the SetVertices() method) - - return 0; + unsigned tmp; + + // Id + READ(tmp); + p.setId(tmp); + + // vertices (List) + vector<Vec3r> tmp_vec; + Vec3r v; + READ(tmp); + for (unsigned int i = 0; i < tmp; i++) { + load(in, v); + tmp_vec.push_back(v); + } + p.setVertices(tmp_vec); + + // min & max + // Already computed (in the SetVertices() method) + + return 0; } -inline int load(istream& in, FrsMaterial& m) +inline int load(istream &in, FrsMaterial &m) { - float tmp_array[4]; - int i; - - // Diffuse - for (i = 0; i < 4; i++) - READ(tmp_array[i]); - m.setDiffuse(tmp_array[0], tmp_array[1], tmp_array[2], tmp_array[3]); - - // Specular - for (i = 0; i < 4; i++) - READ(tmp_array[i]); - m.setSpecular(tmp_array[0], tmp_array[1], tmp_array[2], tmp_array[3]); - - // Ambient - for (i = 0; i < 4; i++) - READ(tmp_array[i]); - m.setAmbient(tmp_array[0], tmp_array[1], tmp_array[2], tmp_array[3]); - - // Emission - for (i = 0; i < 4; i++) - READ(tmp_array[i]); - m.setEmission(tmp_array[0], tmp_array[1], tmp_array[2], tmp_array[3]); - - // Shininess - READ(tmp_array[0]); - m.setShininess(tmp_array[0]); - - return 0; + float tmp_array[4]; + int i; + + // Diffuse + for (i = 0; i < 4; i++) + READ(tmp_array[i]); + m.setDiffuse(tmp_array[0], tmp_array[1], tmp_array[2], tmp_array[3]); + + // Specular + for (i = 0; i < 4; i++) + READ(tmp_array[i]); + m.setSpecular(tmp_array[0], tmp_array[1], tmp_array[2], tmp_array[3]); + + // Ambient + for (i = 0; i < 4; i++) + READ(tmp_array[i]); + m.setAmbient(tmp_array[0], tmp_array[1], tmp_array[2], tmp_array[3]); + + // Emission + for (i = 0; i < 4; i++) + READ(tmp_array[i]); + m.setEmission(tmp_array[0], tmp_array[1], tmp_array[2], tmp_array[3]); + + // Shininess + READ(tmp_array[0]); + m.setShininess(tmp_array[0]); + + return 0; } -static int load(istream& in, ViewShape *vs) +static int load(istream &in, ViewShape *vs) { - if (!vs || !vs->sshape()) - return 1; - - // SShape - - // -> Id - Id::id_type id1, id2; - READ(id1); - READ(id2); - vs->sshape()->setId(Id(id1, id2)); - - // -> Importance - float importance; - READ(importance); - vs->sshape()->setImportance(importance); - - // -> BBox - // Not necessary (only used during view map computatiom) - - unsigned i, size, tmp; - - // -> Material - READ(size); - vector<FrsMaterial> frs_materials; - FrsMaterial m; - for (i = 0; i < size; ++i) { - load(in, m); - frs_materials.push_back(m); - } - vs->sshape()->setFrsMaterials(frs_materials); - - // -> VerticesList (List) - READ(size); - for (i = 0; i < size; i++) { - SVertex *sv; - READ_IF_NON_NULL(sv, g_vm->SVertices()); - vs->sshape()->AddNewVertex(sv); - } - - // -> Chains (List) - READ(size); - for (i = 0; i < size; i++) { - FEdge *fe; - READ_IF_NON_NULL(fe, g_vm->FEdges()); - vs->sshape()->AddChain(fe); - } - - // -> EdgesList (List) - READ(size); - for (i = 0; i < size; i++) { - FEdge *fe; - READ_IF_NON_NULL(fe, g_vm->FEdges()); - vs->sshape()->AddEdge(fe); - } - - // ViewEdges (List) - READ(size); - for (i = 0; i < size; i++) { - ViewEdge *ve; - READ_IF_NON_NULL(ve, g_vm->ViewEdges()); - vs->AddEdge(ve); - } - - // ViewVertices (List) - READ(size); - for (i = 0; i < size; i++) { - ViewVertex *vv; - READ_IF_NON_NULL(vv, g_vm->ViewVertices()); - vs->AddVertex(vv); - } - - return 0; + if (!vs || !vs->sshape()) + return 1; + + // SShape + + // -> Id + Id::id_type id1, id2; + READ(id1); + READ(id2); + vs->sshape()->setId(Id(id1, id2)); + + // -> Importance + float importance; + READ(importance); + vs->sshape()->setImportance(importance); + + // -> BBox + // Not necessary (only used during view map computatiom) + + unsigned i, size, tmp; + + // -> Material + READ(size); + vector<FrsMaterial> frs_materials; + FrsMaterial m; + for (i = 0; i < size; ++i) { + load(in, m); + frs_materials.push_back(m); + } + vs->sshape()->setFrsMaterials(frs_materials); + + // -> VerticesList (List) + READ(size); + for (i = 0; i < size; i++) { + SVertex *sv; + READ_IF_NON_NULL(sv, g_vm->SVertices()); + vs->sshape()->AddNewVertex(sv); + } + + // -> Chains (List) + READ(size); + for (i = 0; i < size; i++) { + FEdge *fe; + READ_IF_NON_NULL(fe, g_vm->FEdges()); + vs->sshape()->AddChain(fe); + } + + // -> EdgesList (List) + READ(size); + for (i = 0; i < size; i++) { + FEdge *fe; + READ_IF_NON_NULL(fe, g_vm->FEdges()); + vs->sshape()->AddEdge(fe); + } + + // ViewEdges (List) + READ(size); + for (i = 0; i < size; i++) { + ViewEdge *ve; + READ_IF_NON_NULL(ve, g_vm->ViewEdges()); + vs->AddEdge(ve); + } + + // ViewVertices (List) + READ(size); + for (i = 0; i < size; i++) { + ViewVertex *vv; + READ_IF_NON_NULL(vv, g_vm->ViewVertices()); + vs->AddVertex(vv); + } + + return 0; } - -static int load(istream& in, FEdge *fe) +static int load(istream &in, FEdge *fe) { - if (!fe) - return 1; - - bool b; - - FEdgeSmooth *fesmooth = NULL; - FEdgeSharp *fesharp = NULL; - if (fe->isSmooth()) { - fesmooth = dynamic_cast<FEdgeSmooth*>(fe); - } - else { - fesharp = dynamic_cast<FEdgeSharp*>(fe); - } - - // Id - Id::id_type id1, id2; - READ(id1); - READ(id2); - fe->setId(Id(id1, id2)); - - // Nature - Nature::EdgeNature nature; - READ(nature); - fe->setNature(nature); - -#if 0 // hasVisibilityPoint - bool b; - READ(b); - fe->setHasVisibilityPoint(b); + if (!fe) + return 1; + + bool b; + + FEdgeSmooth *fesmooth = NULL; + FEdgeSharp *fesharp = NULL; + if (fe->isSmooth()) { + fesmooth = dynamic_cast<FEdgeSmooth *>(fe); + } + else { + fesharp = dynamic_cast<FEdgeSharp *>(fe); + } + + // Id + Id::id_type id1, id2; + READ(id1); + READ(id2); + fe->setId(Id(id1, id2)); + + // Nature + Nature::EdgeNature nature; + READ(nature); + fe->setNature(nature); + +#if 0 // hasVisibilityPoint + bool b; + READ(b); + fe->setHasVisibilityPoint(b); #endif - Vec3r v; - unsigned int matindex; + Vec3r v; + unsigned int matindex; #if 0 - // VisibilityPointA - load(in, v); - fe->setVisibilityPointA(v); + // VisibilityPointA + load(in, v); + fe->setVisibilityPointA(v); - // VisibilityPointB - load(in, v); - fe->setVisibilityPointB(v); + // VisibilityPointB + load(in, v); + fe->setVisibilityPointB(v); #endif - if (fe->isSmooth()) { - // Normal - load(in, v); - fesmooth->setNormal(v); - - // Material - READ(matindex); - fesmooth->setFrsMaterialIndex(matindex); - } - else { - // aNormal - load(in, v); - fesharp->setNormalA(v); - - // bNormal - load(in, v); - fesharp->setNormalB(v); - - // Materials - READ(matindex); - fesharp->setaFrsMaterialIndex(matindex); - READ(matindex); - fesharp->setbFrsMaterialIndex(matindex); - } - - unsigned tmp; - - // VertexA - SVertex *sva; - READ_IF_NON_NULL(sva, g_vm->SVertices()); - fe->setVertexA(sva); - - // VertexB - SVertex *svb; - READ_IF_NON_NULL(svb, g_vm->SVertices()); - fe->setVertexB(svb); - - // NextEdge - FEdge *nfe; - READ_IF_NON_NULL(nfe, g_vm->FEdges()); - fe->setNextEdge(nfe); - - // PreviousEdge - FEdge *pfe; - READ_IF_NON_NULL(pfe, g_vm->FEdges()); - fe->setPreviousEdge(pfe); - - // ViewEdge - ViewEdge *ve; - READ_IF_NON_NULL(ve, g_vm->ViewEdges()); - fe->setViewEdge(ve); - - // Face - // Not necessary (only used during view map computatiom) - - Polygon3r p; - - // aFace - load(in, p); - fe->setaFace(p); - - // occludeeEmpty - READ(b); - fe->setOccludeeEmpty(b); - - // occludeeIntersection - load(in, v); - fe->setOccludeeIntersection(v); - - return 0; + if (fe->isSmooth()) { + // Normal + load(in, v); + fesmooth->setNormal(v); + + // Material + READ(matindex); + fesmooth->setFrsMaterialIndex(matindex); + } + else { + // aNormal + load(in, v); + fesharp->setNormalA(v); + + // bNormal + load(in, v); + fesharp->setNormalB(v); + + // Materials + READ(matindex); + fesharp->setaFrsMaterialIndex(matindex); + READ(matindex); + fesharp->setbFrsMaterialIndex(matindex); + } + + unsigned tmp; + + // VertexA + SVertex *sva; + READ_IF_NON_NULL(sva, g_vm->SVertices()); + fe->setVertexA(sva); + + // VertexB + SVertex *svb; + READ_IF_NON_NULL(svb, g_vm->SVertices()); + fe->setVertexB(svb); + + // NextEdge + FEdge *nfe; + READ_IF_NON_NULL(nfe, g_vm->FEdges()); + fe->setNextEdge(nfe); + + // PreviousEdge + FEdge *pfe; + READ_IF_NON_NULL(pfe, g_vm->FEdges()); + fe->setPreviousEdge(pfe); + + // ViewEdge + ViewEdge *ve; + READ_IF_NON_NULL(ve, g_vm->ViewEdges()); + fe->setViewEdge(ve); + + // Face + // Not necessary (only used during view map computatiom) + + Polygon3r p; + + // aFace + load(in, p); + fe->setaFace(p); + + // occludeeEmpty + READ(b); + fe->setOccludeeEmpty(b); + + // occludeeIntersection + load(in, v); + fe->setOccludeeIntersection(v); + + return 0; } -static int load(istream& in, SVertex *sv) +static int load(istream &in, SVertex *sv) { - if (!sv) - return 1; - - // Id - Id::id_type id1, id2; - READ(id1); - READ(id2); - sv->setId(Id(id1, id2)); - - Vec3r v; - - // Point3D - load(in, v); - sv->setPoint3D(v); - - // Point2D - load(in, v); - sv->setPoint2D(v); - - unsigned tmp; - - // Shape - ViewShape *vs; - READ_IF_NON_NULL(vs, g_vm->ViewShapes()); - sv->setShape(vs->sshape()); - - // pViewVertex - ViewVertex *vv; - READ_IF_NON_NULL(vv, g_vm->ViewVertices()); - sv->setViewVertex(vv); - - unsigned i, size; - - // Normals (List) - READ(size); - for (i = 0; i < size; i++) { - load(in, v); - sv->AddNormal(v); - } - - // FEdges (List) - READ(size); - FEdge *fe; - for (i = 0; i < size; i++) { - READ_IF_NON_NULL(fe, g_vm->FEdges()); - sv->AddFEdge(fe); - } - - return 0; + if (!sv) + return 1; + + // Id + Id::id_type id1, id2; + READ(id1); + READ(id2); + sv->setId(Id(id1, id2)); + + Vec3r v; + + // Point3D + load(in, v); + sv->setPoint3D(v); + + // Point2D + load(in, v); + sv->setPoint2D(v); + + unsigned tmp; + + // Shape + ViewShape *vs; + READ_IF_NON_NULL(vs, g_vm->ViewShapes()); + sv->setShape(vs->sshape()); + + // pViewVertex + ViewVertex *vv; + READ_IF_NON_NULL(vv, g_vm->ViewVertices()); + sv->setViewVertex(vv); + + unsigned i, size; + + // Normals (List) + READ(size); + for (i = 0; i < size; i++) { + load(in, v); + sv->AddNormal(v); + } + + // FEdges (List) + READ(size); + FEdge *fe; + for (i = 0; i < size; i++) { + READ_IF_NON_NULL(fe, g_vm->FEdges()); + sv->AddFEdge(fe); + } + + return 0; } - -static int load(istream& in, ViewEdge *ve) +static int load(istream &in, ViewEdge *ve) { - if (!ve) - return 1; - - unsigned tmp; - - // Id - Id::id_type id1, id2; - READ(id1); - READ(id2); - ve->setId(Id(id1, id2)); - - // Nature - Nature::EdgeNature nature; - READ(nature); - ve->setNature(nature); - - // QI - READ(tmp); - ve->setQI(tmp); - - // Shape - ViewShape *vs; - READ_IF_NON_NULL(vs, g_vm->ViewShapes()); - ve->setShape(vs); - - // aShape - ViewShape *avs; - READ_IF_NON_NULL(avs, g_vm->ViewShapes()); - ve->setaShape(avs); - - // FEdgeA - FEdge *fea; - READ_IF_NON_NULL(fea, g_vm->FEdges()); - ve->setFEdgeA(fea); - - // FEdgeB - FEdge *feb; - READ_IF_NON_NULL(feb, g_vm->FEdges()); - ve->setFEdgeB(feb); - - // A - ViewVertex *vva; - READ_IF_NON_NULL(vva, g_vm->ViewVertices()); - ve->setA(vva); - - // B - ViewVertex *vvb; - READ_IF_NON_NULL(vvb, g_vm->ViewVertices()); - ve->setB(vvb); - - // Occluders (List) - if (!(Options::getFlags() & Options::NO_OCCLUDERS)) { - unsigned size; - READ(size); - ViewShape *vso; - for (unsigned int i = 0; i < size; i++) { - READ_IF_NON_NULL(vso, g_vm->ViewShapes()); - ve->AddOccluder(vso); - } - } - - return 0; + if (!ve) + return 1; + + unsigned tmp; + + // Id + Id::id_type id1, id2; + READ(id1); + READ(id2); + ve->setId(Id(id1, id2)); + + // Nature + Nature::EdgeNature nature; + READ(nature); + ve->setNature(nature); + + // QI + READ(tmp); + ve->setQI(tmp); + + // Shape + ViewShape *vs; + READ_IF_NON_NULL(vs, g_vm->ViewShapes()); + ve->setShape(vs); + + // aShape + ViewShape *avs; + READ_IF_NON_NULL(avs, g_vm->ViewShapes()); + ve->setaShape(avs); + + // FEdgeA + FEdge *fea; + READ_IF_NON_NULL(fea, g_vm->FEdges()); + ve->setFEdgeA(fea); + + // FEdgeB + FEdge *feb; + READ_IF_NON_NULL(feb, g_vm->FEdges()); + ve->setFEdgeB(feb); + + // A + ViewVertex *vva; + READ_IF_NON_NULL(vva, g_vm->ViewVertices()); + ve->setA(vva); + + // B + ViewVertex *vvb; + READ_IF_NON_NULL(vvb, g_vm->ViewVertices()); + ve->setB(vvb); + + // Occluders (List) + if (!(Options::getFlags() & Options::NO_OCCLUDERS)) { + unsigned size; + READ(size); + ViewShape *vso; + for (unsigned int i = 0; i < size; i++) { + READ_IF_NON_NULL(vso, g_vm->ViewShapes()); + ve->AddOccluder(vso); + } + } + + return 0; } - -static int load(istream& in, ViewVertex *vv) +static int load(istream &in, ViewVertex *vv) { - if (!vv) - return 1; - - unsigned tmp; - bool b; - - // Nature - Nature::VertexNature nature; - READ(nature); - vv->setNature(nature); - - if (vv->getNature() & Nature::T_VERTEX) { - TVertex *tv = dynamic_cast<TVertex*>(vv); - - // Id - Id::id_type id1, id2; - READ(id1); - READ(id2); - tv->setId(Id(id1, id2)); - - // FrontSVertex - SVertex *fsv; - READ_IF_NON_NULL(fsv, g_vm->SVertices()); - tv->setFrontSVertex(fsv); - - // BackSVertex - SVertex *bsv; - READ_IF_NON_NULL(bsv, g_vm->SVertices()); - tv->setBackSVertex(bsv); - - // FrontEdgeA - ViewEdge *fea; - READ_IF_NON_NULL(fea, g_vm->ViewEdges()); - READ(b); - tv->setFrontEdgeA(fea, b); - - // FrontEdgeB - ViewEdge *feb; - READ_IF_NON_NULL(feb, g_vm->ViewEdges()); - READ(b); - tv->setFrontEdgeB(feb, b); - - // BackEdgeA - ViewEdge *bea; - READ_IF_NON_NULL(bea, g_vm->ViewEdges()); - READ(b); - tv->setBackEdgeA(bea, b); - - // BackEdgeB - ViewEdge *beb; - READ_IF_NON_NULL(beb, g_vm->ViewEdges()); - READ(b); - tv->setBackEdgeB(beb, b); - } - else if (vv->getNature() & Nature::NON_T_VERTEX) { - NonTVertex *ntv = dynamic_cast<NonTVertex*>(vv); - - // SVertex - SVertex *sv; - READ_IF_NON_NULL(sv, g_vm->SVertices()); - ntv->setSVertex(sv); - - // ViewEdges (List) - unsigned size; - READ(size); - ViewEdge *ve; - for (unsigned int i = 0; i < size; i++) { - READ_IF_NON_NULL(ve, g_vm->ViewEdges()); - READ(b); - ntv->AddViewEdge(ve, b); - } - } - - return 0; + if (!vv) + return 1; + + unsigned tmp; + bool b; + + // Nature + Nature::VertexNature nature; + READ(nature); + vv->setNature(nature); + + if (vv->getNature() & Nature::T_VERTEX) { + TVertex *tv = dynamic_cast<TVertex *>(vv); + + // Id + Id::id_type id1, id2; + READ(id1); + READ(id2); + tv->setId(Id(id1, id2)); + + // FrontSVertex + SVertex *fsv; + READ_IF_NON_NULL(fsv, g_vm->SVertices()); + tv->setFrontSVertex(fsv); + + // BackSVertex + SVertex *bsv; + READ_IF_NON_NULL(bsv, g_vm->SVertices()); + tv->setBackSVertex(bsv); + + // FrontEdgeA + ViewEdge *fea; + READ_IF_NON_NULL(fea, g_vm->ViewEdges()); + READ(b); + tv->setFrontEdgeA(fea, b); + + // FrontEdgeB + ViewEdge *feb; + READ_IF_NON_NULL(feb, g_vm->ViewEdges()); + READ(b); + tv->setFrontEdgeB(feb, b); + + // BackEdgeA + ViewEdge *bea; + READ_IF_NON_NULL(bea, g_vm->ViewEdges()); + READ(b); + tv->setBackEdgeA(bea, b); + + // BackEdgeB + ViewEdge *beb; + READ_IF_NON_NULL(beb, g_vm->ViewEdges()); + READ(b); + tv->setBackEdgeB(beb, b); + } + else if (vv->getNature() & Nature::NON_T_VERTEX) { + NonTVertex *ntv = dynamic_cast<NonTVertex *>(vv); + + // SVertex + SVertex *sv; + READ_IF_NON_NULL(sv, g_vm->SVertices()); + ntv->setSVertex(sv); + + // ViewEdges (List) + unsigned size; + READ(size); + ViewEdge *ve; + for (unsigned int i = 0; i < size; i++) { + READ_IF_NON_NULL(ve, g_vm->ViewEdges()); + READ(b); + ntv->AddViewEdge(ve, b); + } + } + + return 0; } //////////////////// 'save' Functions //////////////////// -inline int save(ostream& out, const Vec3r& v) +inline int save(ostream &out, const Vec3r &v) { - if (Options::getFlags() & Options::FLOAT_VECTORS) { - float tmp; - - tmp = v[0]; - WRITE(tmp); - tmp = v[1]; - WRITE(tmp); - tmp = v[2]; - WRITE(tmp); - } - else { - Vec3r::value_type tmp; - - tmp = v[0]; - WRITE(tmp); - tmp = v[1]; - WRITE(tmp); - tmp = v[2]; - WRITE(tmp); - } - return 0; + if (Options::getFlags() & Options::FLOAT_VECTORS) { + float tmp; + + tmp = v[0]; + WRITE(tmp); + tmp = v[1]; + WRITE(tmp); + tmp = v[2]; + WRITE(tmp); + } + else { + Vec3r::value_type tmp; + + tmp = v[0]; + WRITE(tmp); + tmp = v[1]; + WRITE(tmp); + tmp = v[2]; + WRITE(tmp); + } + return 0; } - -inline int save(ostream& out, const Polygon3r& p) +inline int save(ostream &out, const Polygon3r &p) { - unsigned tmp; + unsigned tmp; - // Id - tmp = p.getId(); - WRITE(tmp); + // Id + tmp = p.getId(); + WRITE(tmp); - // vertices (List) - tmp = p.getVertices().size(); - WRITE(tmp); - for (vector<Vec3r>::const_iterator i = p.getVertices().begin(); i != p.getVertices().end(); i++) { - save(out, *i); - } + // vertices (List) + tmp = p.getVertices().size(); + WRITE(tmp); + for (vector<Vec3r>::const_iterator i = p.getVertices().begin(); i != p.getVertices().end(); + i++) { + save(out, *i); + } - // min & max - // Do not need to be saved + // min & max + // Do not need to be saved - return 0; + return 0; } -inline int save(ostream& out, const FrsMaterial& m) +inline int save(ostream &out, const FrsMaterial &m) { - unsigned i; + unsigned i; - // Diffuse - for (i = 0; i < 4; i++) - WRITE(m.diffuse()[i]); + // Diffuse + for (i = 0; i < 4; i++) + WRITE(m.diffuse()[i]); - // Specular - for (i = 0; i < 4; i++) - WRITE(m.specular()[i]); + // Specular + for (i = 0; i < 4; i++) + WRITE(m.specular()[i]); - // Ambient - for (i = 0; i < 4; i++) - WRITE(m.ambient()[i]); + // Ambient + for (i = 0; i < 4; i++) + WRITE(m.ambient()[i]); - // Emission - for (i = 0; i < 4; i++) - WRITE(m.emission()[i]); + // Emission + for (i = 0; i < 4; i++) + WRITE(m.emission()[i]); - // Shininess - float shininess = m.shininess(); - WRITE(shininess); + // Shininess + float shininess = m.shininess(); + WRITE(shininess); - return 0; + return 0; } -static int save(ostream& out, ViewShape *vs) +static int save(ostream &out, ViewShape *vs) { - if (!vs || !vs->sshape()) { - cerr << "Warning: null ViewShape" << endl; - return 1; - } - - unsigned tmp; - - // SShape - - // -> Id - Id::id_type id = vs->sshape()->getId().getFirst(); - WRITE(id); - id = vs->sshape()->getId().getSecond(); - WRITE(id); - - // -> Importance - float importance = vs->sshape()->importance(); - WRITE(importance); - - // -> BBox - // Not necessary (only used during view map computatiom) - - // -> Material - unsigned int size = vs->sshape()->frs_materials().size(); - WRITE(size); - for (unsigned int i = 0; i < size; ++i) - save(out, vs->sshape()->frs_material(i)); - - // -> VerticesList (List) - tmp = vs->sshape()->getVertexList().size(); - WRITE(tmp); - for (vector<SVertex*>::const_iterator i1 = vs->sshape()->getVertexList().begin(); - i1 != vs->sshape()->getVertexList().end(); - i1++) - { - WRITE_IF_NON_NULL(*i1); - } - - // -> Chains (List) - tmp = vs->sshape()->getChains().size(); - WRITE(tmp); - for (vector<FEdge*>::const_iterator i2 = vs->sshape()->getChains().begin(); - i2 != vs->sshape()->getChains().end(); - i2++) - { - WRITE_IF_NON_NULL(*i2); - } - - // -> EdgesList (List) - tmp = vs->sshape()->getEdgeList().size(); - WRITE(tmp); - for (vector<FEdge*>::const_iterator i3 = vs->sshape()->getEdgeList().begin(); - i3 != vs->sshape()->getEdgeList().end(); - i3++) - { - WRITE_IF_NON_NULL(*i3); - } - - // ViewEdges (List) - tmp = vs->edges().size(); - WRITE(tmp); - for (vector<ViewEdge*>::const_iterator i4 = vs->edges().begin(); i4 != vs->edges().end(); i4++) { - WRITE_IF_NON_NULL(*i4); - } - - // ViewVertices (List) - tmp = vs->vertices().size(); - WRITE(tmp); - for (vector<ViewVertex*>::const_iterator i5 = vs->vertices().begin(); i5 != vs->vertices().end(); i5++) { - WRITE_IF_NON_NULL(*i5); - } - - return 0; + if (!vs || !vs->sshape()) { + cerr << "Warning: null ViewShape" << endl; + return 1; + } + + unsigned tmp; + + // SShape + + // -> Id + Id::id_type id = vs->sshape()->getId().getFirst(); + WRITE(id); + id = vs->sshape()->getId().getSecond(); + WRITE(id); + + // -> Importance + float importance = vs->sshape()->importance(); + WRITE(importance); + + // -> BBox + // Not necessary (only used during view map computatiom) + + // -> Material + unsigned int size = vs->sshape()->frs_materials().size(); + WRITE(size); + for (unsigned int i = 0; i < size; ++i) + save(out, vs->sshape()->frs_material(i)); + + // -> VerticesList (List) + tmp = vs->sshape()->getVertexList().size(); + WRITE(tmp); + for (vector<SVertex *>::const_iterator i1 = vs->sshape()->getVertexList().begin(); + i1 != vs->sshape()->getVertexList().end(); + i1++) { + WRITE_IF_NON_NULL(*i1); + } + + // -> Chains (List) + tmp = vs->sshape()->getChains().size(); + WRITE(tmp); + for (vector<FEdge *>::const_iterator i2 = vs->sshape()->getChains().begin(); + i2 != vs->sshape()->getChains().end(); + i2++) { + WRITE_IF_NON_NULL(*i2); + } + + // -> EdgesList (List) + tmp = vs->sshape()->getEdgeList().size(); + WRITE(tmp); + for (vector<FEdge *>::const_iterator i3 = vs->sshape()->getEdgeList().begin(); + i3 != vs->sshape()->getEdgeList().end(); + i3++) { + WRITE_IF_NON_NULL(*i3); + } + + // ViewEdges (List) + tmp = vs->edges().size(); + WRITE(tmp); + for (vector<ViewEdge *>::const_iterator i4 = vs->edges().begin(); i4 != vs->edges().end(); + i4++) { + WRITE_IF_NON_NULL(*i4); + } + + // ViewVertices (List) + tmp = vs->vertices().size(); + WRITE(tmp); + for (vector<ViewVertex *>::const_iterator i5 = vs->vertices().begin(); + i5 != vs->vertices().end(); + i5++) { + WRITE_IF_NON_NULL(*i5); + } + + return 0; } - -static int save(ostream& out, FEdge *fe) +static int save(ostream &out, FEdge *fe) { - if (!fe) { - cerr << "Warning: null FEdge" << endl; - return 1; - } + if (!fe) { + cerr << "Warning: null FEdge" << endl; + return 1; + } - FEdgeSmooth *fesmooth = dynamic_cast<FEdgeSmooth*>(fe); - FEdgeSharp *fesharp = dynamic_cast<FEdgeSharp*>(fe); + FEdgeSmooth *fesmooth = dynamic_cast<FEdgeSmooth *>(fe); + FEdgeSharp *fesharp = dynamic_cast<FEdgeSharp *>(fe); - // Id - Id::id_type id = fe->getId().getFirst(); - WRITE(id); - id = fe->getId().getSecond(); - WRITE(id); + // Id + Id::id_type id = fe->getId().getFirst(); + WRITE(id); + id = fe->getId().getSecond(); + WRITE(id); - // Nature - Nature::EdgeNature nature = fe->getNature(); - WRITE(nature); + // Nature + Nature::EdgeNature nature = fe->getNature(); + WRITE(nature); - bool b; + bool b; #if 0 - // hasVisibilityPoint - b = fe->hasVisibilityPoint(); - WRITE(b); + // hasVisibilityPoint + b = fe->hasVisibilityPoint(); + WRITE(b); - // VisibilityPointA - save(out, fe->visibilityPointA()); + // VisibilityPointA + save(out, fe->visibilityPointA()); - // VisibilityPointB - save(out, fe->visibilityPointB()); + // VisibilityPointB + save(out, fe->visibilityPointB()); #endif - unsigned index; - if (fe->isSmooth()) { - // normal - save(out, fesmooth->normal()); - // material - index = fesmooth->frs_materialIndex(); - WRITE(index); - } - else { - // aNormal - save(out, fesharp->normalA()); - // bNormal - save(out, fesharp->normalB()); - // aMaterial - index = fesharp->aFrsMaterialIndex(); - WRITE(index); - // bMaterial - index = fesharp->bFrsMaterialIndex(); - WRITE(index); - } - - // VertexA - WRITE_IF_NON_NULL(fe->vertexA()); - - // VertexB - WRITE_IF_NON_NULL(fe->vertexB()); - - // NextEdge - WRITE_IF_NON_NULL(fe->nextEdge()); - - // PreviousEdge - WRITE_IF_NON_NULL(fe->previousEdge()); - - // ViewEdge - WRITE_IF_NON_NULL(fe->viewedge()); - - // Face - // Not necessary (only used during view map computatiom) - - // aFace - save(out, (Polygon3r&)fe->aFace()); - - // occludeeEmpty - b = fe->getOccludeeEmpty(); - WRITE(b); - - // occludeeIntersection - save(out, fe->getOccludeeIntersection()); - - return 0; + unsigned index; + if (fe->isSmooth()) { + // normal + save(out, fesmooth->normal()); + // material + index = fesmooth->frs_materialIndex(); + WRITE(index); + } + else { + // aNormal + save(out, fesharp->normalA()); + // bNormal + save(out, fesharp->normalB()); + // aMaterial + index = fesharp->aFrsMaterialIndex(); + WRITE(index); + // bMaterial + index = fesharp->bFrsMaterialIndex(); + WRITE(index); + } + + // VertexA + WRITE_IF_NON_NULL(fe->vertexA()); + + // VertexB + WRITE_IF_NON_NULL(fe->vertexB()); + + // NextEdge + WRITE_IF_NON_NULL(fe->nextEdge()); + + // PreviousEdge + WRITE_IF_NON_NULL(fe->previousEdge()); + + // ViewEdge + WRITE_IF_NON_NULL(fe->viewedge()); + + // Face + // Not necessary (only used during view map computatiom) + + // aFace + save(out, (Polygon3r &)fe->aFace()); + + // occludeeEmpty + b = fe->getOccludeeEmpty(); + WRITE(b); + + // occludeeIntersection + save(out, fe->getOccludeeIntersection()); + + return 0; } -static int save(ostream& out, SVertex *sv) +static int save(ostream &out, SVertex *sv) { - if (!sv) { - cerr << "Warning: null SVertex" << endl; - return 1; - } - - unsigned tmp; - - // Id - Id::id_type id = sv->getId().getFirst(); - WRITE(id); - id = sv->getId().getSecond(); - WRITE(id); - - Vec3r v; - - // Point3D - v = sv->point3D(); - save(out, sv->point3D()); - - // Point2D - v = sv->point2D(); - save(out, v); - - // Shape - WRITE_IF_NON_NULL(sv->shape()); - - // pViewVertex - WRITE_IF_NON_NULL(sv->viewvertex()); - - // Normals (List) - // Note: the 'size()' method of a set doesn't seem to return the actual size of the given set, so we have to - // hack it... - set<Vec3r>::const_iterator i; - for (i = sv->normals().begin(), tmp = 0; i != sv->normals().end(); i++, tmp++); - WRITE(tmp); - for (i = sv->normals().begin(); i != sv->normals().end(); i++) - save(out, *i); - - // FEdges (List) - tmp = sv->fedges().size(); - WRITE(tmp); - for (vector<FEdge*>::const_iterator j = sv->fedges_begin(); j != sv->fedges_end(); j++) { - WRITE_IF_NON_NULL(*j); - } - - return 0; + if (!sv) { + cerr << "Warning: null SVertex" << endl; + return 1; + } + + unsigned tmp; + + // Id + Id::id_type id = sv->getId().getFirst(); + WRITE(id); + id = sv->getId().getSecond(); + WRITE(id); + + Vec3r v; + + // Point3D + v = sv->point3D(); + save(out, sv->point3D()); + + // Point2D + v = sv->point2D(); + save(out, v); + + // Shape + WRITE_IF_NON_NULL(sv->shape()); + + // pViewVertex + WRITE_IF_NON_NULL(sv->viewvertex()); + + // Normals (List) + // Note: the 'size()' method of a set doesn't seem to return the actual size of the given set, so we have to + // hack it... + set<Vec3r>::const_iterator i; + for (i = sv->normals().begin(), tmp = 0; i != sv->normals().end(); i++, tmp++) + ; + WRITE(tmp); + for (i = sv->normals().begin(); i != sv->normals().end(); i++) + save(out, *i); + + // FEdges (List) + tmp = sv->fedges().size(); + WRITE(tmp); + for (vector<FEdge *>::const_iterator j = sv->fedges_begin(); j != sv->fedges_end(); j++) { + WRITE_IF_NON_NULL(*j); + } + + return 0; } - -static int save(ostream& out, ViewEdge *ve) +static int save(ostream &out, ViewEdge *ve) { - if (!ve) { - cerr << "Warning: null ViewEdge" << endl; - return 1; - } + if (!ve) { + cerr << "Warning: null ViewEdge" << endl; + return 1; + } - unsigned tmp; + unsigned tmp; - // Id - Id::id_type id = ve->getId().getFirst(); - WRITE(id); - id = ve->getId().getSecond(); - WRITE(id); + // Id + Id::id_type id = ve->getId().getFirst(); + WRITE(id); + id = ve->getId().getSecond(); + WRITE(id); - // Nature - Nature::EdgeNature nature = ve->getNature(); - WRITE(nature); + // Nature + Nature::EdgeNature nature = ve->getNature(); + WRITE(nature); - // QI - unsigned qi = ve->qi(); - WRITE(qi); + // QI + unsigned qi = ve->qi(); + WRITE(qi); - // Shape - WRITE_IF_NON_NULL(ve->shape()); + // Shape + WRITE_IF_NON_NULL(ve->shape()); - // aShape - WRITE_IF_NON_NULL(ve->aShape()); + // aShape + WRITE_IF_NON_NULL(ve->aShape()); - // FEdgeA - WRITE_IF_NON_NULL(ve->fedgeA()); + // FEdgeA + WRITE_IF_NON_NULL(ve->fedgeA()); - // FEdgeB - WRITE_IF_NON_NULL(ve->fedgeB()); + // FEdgeB + WRITE_IF_NON_NULL(ve->fedgeB()); - // A - WRITE_IF_NON_NULL(ve->A()); + // A + WRITE_IF_NON_NULL(ve->A()); - // B - WRITE_IF_NON_NULL(ve->B()); + // B + WRITE_IF_NON_NULL(ve->B()); - // Occluders (List) - if (!(Options::getFlags() & Options::NO_OCCLUDERS)) { - tmp = ve->occluders().size(); - WRITE(tmp); - for (vector<ViewShape*>::const_iterator i = ve->occluders().begin(); i != ve->occluders().end(); i++) { - WRITE_IF_NON_NULL((*i)); - } - } + // Occluders (List) + if (!(Options::getFlags() & Options::NO_OCCLUDERS)) { + tmp = ve->occluders().size(); + WRITE(tmp); + for (vector<ViewShape *>::const_iterator i = ve->occluders().begin(); + i != ve->occluders().end(); + i++) { + WRITE_IF_NON_NULL((*i)); + } + } - return 0; + return 0; } - -static int save(ostream& out, ViewVertex *vv) +static int save(ostream &out, ViewVertex *vv) { - if (!vv) { - cerr << "Warning: null ViewVertex" << endl; - return 1; - } - - // Nature - Nature::VertexNature nature = vv->getNature(); - WRITE(nature); - - if (vv->getNature() & Nature::T_VERTEX) { - TVertex *tv = dynamic_cast<TVertex*>(vv); - - // Id - Id::id_type id = tv->getId().getFirst(); - WRITE(id); - id = tv->getId().getSecond(); - WRITE(id); - - // FrontSVertex - WRITE_IF_NON_NULL(tv->frontSVertex()); - - // BackSVertex - WRITE_IF_NON_NULL(tv->backSVertex()); - - // FrontEdgeA - WRITE_IF_NON_NULL(tv->frontEdgeA().first); - WRITE(tv->frontEdgeA().second); - - // FrontEdgeB - WRITE_IF_NON_NULL(tv->frontEdgeB().first); - WRITE(tv->frontEdgeB().second); - - // BackEdgeA - WRITE_IF_NON_NULL(tv->backEdgeA().first); - WRITE(tv->backEdgeA().second); - - // BackEdgeB - WRITE_IF_NON_NULL(tv->backEdgeB().first); - WRITE(tv->backEdgeB().second); - } - else if (vv->getNature() & Nature::NON_T_VERTEX) { - NonTVertex *ntv = dynamic_cast<NonTVertex*>(vv); - - // SVertex - WRITE_IF_NON_NULL(ntv->svertex()); - - // ViewEdges (List) - unsigned size = ntv->viewedges().size(); - WRITE(size); - vector<ViewVertex::directedViewEdge>::const_iterator i = ntv->viewedges().begin(); - for (; i != ntv->viewedges().end(); i++) { - WRITE_IF_NON_NULL(i->first); - WRITE(i->second); - } - } - else { - cerr << "Warning: unexpected ViewVertex nature" << endl; - return 1; - } - - return 0; + if (!vv) { + cerr << "Warning: null ViewVertex" << endl; + return 1; + } + + // Nature + Nature::VertexNature nature = vv->getNature(); + WRITE(nature); + + if (vv->getNature() & Nature::T_VERTEX) { + TVertex *tv = dynamic_cast<TVertex *>(vv); + + // Id + Id::id_type id = tv->getId().getFirst(); + WRITE(id); + id = tv->getId().getSecond(); + WRITE(id); + + // FrontSVertex + WRITE_IF_NON_NULL(tv->frontSVertex()); + + // BackSVertex + WRITE_IF_NON_NULL(tv->backSVertex()); + + // FrontEdgeA + WRITE_IF_NON_NULL(tv->frontEdgeA().first); + WRITE(tv->frontEdgeA().second); + + // FrontEdgeB + WRITE_IF_NON_NULL(tv->frontEdgeB().first); + WRITE(tv->frontEdgeB().second); + + // BackEdgeA + WRITE_IF_NON_NULL(tv->backEdgeA().first); + WRITE(tv->backEdgeA().second); + + // BackEdgeB + WRITE_IF_NON_NULL(tv->backEdgeB().first); + WRITE(tv->backEdgeB().second); + } + else if (vv->getNature() & Nature::NON_T_VERTEX) { + NonTVertex *ntv = dynamic_cast<NonTVertex *>(vv); + + // SVertex + WRITE_IF_NON_NULL(ntv->svertex()); + + // ViewEdges (List) + unsigned size = ntv->viewedges().size(); + WRITE(size); + vector<ViewVertex::directedViewEdge>::const_iterator i = ntv->viewedges().begin(); + for (; i != ntv->viewedges().end(); i++) { + WRITE_IF_NON_NULL(i->first); + WRITE(i->second); + } + } + else { + cerr << "Warning: unexpected ViewVertex nature" << endl; + return 1; + } + + return 0; } -} // End of namespace Internal - +} // End of namespace Internal //////////////////// "Public" 'load' and 'save' functions //////////////////// -#define SET_PROGRESS(n) \ - if (pb) { \ - pb->setProgress((n)); \ - } (void)0 +#define SET_PROGRESS(n) \ + if (pb) { \ + pb->setProgress((n)); \ + } \ + (void)0 -int load(istream& in, ViewMap *vm, ProgressBar *pb) +int load(istream &in, ViewMap *vm, ProgressBar *pb) { - if (!vm) - return 1; - - //soc unused - unsigned tmp; - int err = 0; - Internal::g_vm = vm; - - // Management of the progress bar (if present) - if (pb) { - pb->reset(); - pb->setLabelText("Loading View Map..."); - pb->setTotalSteps(6); - pb->setProgress(0); - } - - // Read and set the options - unsigned char flags; - READ(flags); - Options::setFlags(flags); - - // Read the size of the five ViewMap's lists (with some extra information for the ViewVertices) - // and instantiate them (with default costructors) - unsigned vs_s, fe_s, fe_rle1, fe_rle2, sv_s, ve_s, vv_s, vv_rle1, vv_rle2; - READ(vs_s); - READ(fe_s); - - if (fe_s) { - bool b; - READ(b); - for (READ(fe_rle1), fe_rle2 = 0; fe_rle1 <= fe_s; fe_rle2 = fe_rle1, READ(fe_rle1)) { - if (b) { - for (unsigned int i = fe_rle2; i < fe_rle1; i++) { - FEdgeSmooth *fes = new FEdgeSmooth; - vm->AddFEdge(fes); - } - b = !b; - } - else if (!b) { - for (unsigned int i = fe_rle2; i < fe_rle1; i++) { - FEdgeSharp *fes = new FEdgeSharp; - vm->AddFEdge(fes); - } - b = !b; - } - } - } - - READ(sv_s); - READ(ve_s); - READ(vv_s); - - if (vv_s) { - Nature::VertexNature nature; - READ(nature); - for (READ(vv_rle1), vv_rle2 = 0; vv_rle1 <= vv_s; vv_rle2 = vv_rle1, READ(vv_rle1)) { - if (nature & Nature::T_VERTEX) { - for (unsigned int i = vv_rle2; i < vv_rle1; i++) { - TVertex *tv = new TVertex(); - vm->AddViewVertex(tv); - } - nature = Nature::NON_T_VERTEX; - } - else if (nature & Nature::NON_T_VERTEX) { - for (unsigned int i = vv_rle2; i < vv_rle1; i++) { - NonTVertex *ntv = new NonTVertex(); - vm->AddViewVertex(ntv); - } - nature = Nature::T_VERTEX; - } - } - } - - for (unsigned int i0 = 0; i0 < vs_s; i0++) { - SShape *ss = new SShape(); - ViewShape *vs = new ViewShape(); - vs->setSShape(ss); - ss->setViewShape(vs); - vm->AddViewShape(vs); - } + if (!vm) + return 1; + + //soc unused - unsigned tmp; + int err = 0; + Internal::g_vm = vm; + + // Management of the progress bar (if present) + if (pb) { + pb->reset(); + pb->setLabelText("Loading View Map..."); + pb->setTotalSteps(6); + pb->setProgress(0); + } + + // Read and set the options + unsigned char flags; + READ(flags); + Options::setFlags(flags); + + // Read the size of the five ViewMap's lists (with some extra information for the ViewVertices) + // and instantiate them (with default costructors) + unsigned vs_s, fe_s, fe_rle1, fe_rle2, sv_s, ve_s, vv_s, vv_rle1, vv_rle2; + READ(vs_s); + READ(fe_s); + + if (fe_s) { + bool b; + READ(b); + for (READ(fe_rle1), fe_rle2 = 0; fe_rle1 <= fe_s; fe_rle2 = fe_rle1, READ(fe_rle1)) { + if (b) { + for (unsigned int i = fe_rle2; i < fe_rle1; i++) { + FEdgeSmooth *fes = new FEdgeSmooth; + vm->AddFEdge(fes); + } + b = !b; + } + else if (!b) { + for (unsigned int i = fe_rle2; i < fe_rle1; i++) { + FEdgeSharp *fes = new FEdgeSharp; + vm->AddFEdge(fes); + } + b = !b; + } + } + } + + READ(sv_s); + READ(ve_s); + READ(vv_s); + + if (vv_s) { + Nature::VertexNature nature; + READ(nature); + for (READ(vv_rle1), vv_rle2 = 0; vv_rle1 <= vv_s; vv_rle2 = vv_rle1, READ(vv_rle1)) { + if (nature & Nature::T_VERTEX) { + for (unsigned int i = vv_rle2; i < vv_rle1; i++) { + TVertex *tv = new TVertex(); + vm->AddViewVertex(tv); + } + nature = Nature::NON_T_VERTEX; + } + else if (nature & Nature::NON_T_VERTEX) { + for (unsigned int i = vv_rle2; i < vv_rle1; i++) { + NonTVertex *ntv = new NonTVertex(); + vm->AddViewVertex(ntv); + } + nature = Nature::T_VERTEX; + } + } + } + + for (unsigned int i0 = 0; i0 < vs_s; i0++) { + SShape *ss = new SShape(); + ViewShape *vs = new ViewShape(); + vs->setSShape(ss); + ss->setViewShape(vs); + vm->AddViewShape(vs); + } #if 0 - for (unsigned int i1 = 0; i1 < fe_s; i1++) { - FEdge *fe = new FEdge(); - vm->AddFEdge(fe); - } + for (unsigned int i1 = 0; i1 < fe_s; i1++) { + FEdge *fe = new FEdge(); + vm->AddFEdge(fe); + } #endif - for (unsigned int i2 = 0; i2 < sv_s; i2++) { - SVertex *sv = new SVertex(); - vm->AddSVertex(sv); - } - for (unsigned int i3 = 0; i3 < ve_s; i3++) { - ViewEdge *ve = new ViewEdge(); - vm->AddViewEdge(ve); - } - - // Read the values for all the objects created above - SET_PROGRESS(1); - for (vector<ViewShape*>::const_iterator i4 = vm->ViewShapes().begin(); i4 != vm->ViewShapes().end(); i4++) - err += Internal::load(in, *i4); - SET_PROGRESS(2); - for (vector<FEdge*>::const_iterator i5 = vm->FEdges().begin(); i5 != vm->FEdges().end(); i5++) - err += Internal::load(in, *i5); - SET_PROGRESS(3); - for (vector<SVertex*>::const_iterator i6 = vm->SVertices().begin(); i6 != vm->SVertices().end(); i6++) - err += Internal::load(in, *i6); - SET_PROGRESS(4); - for (vector<ViewEdge*>::const_iterator i7 = vm->ViewEdges().begin(); i7 != vm->ViewEdges().end(); i7++) - err += Internal::load(in, *i7); - SET_PROGRESS(5); - for (vector<ViewVertex*>::const_iterator i8 = vm->ViewVertices().begin(); i8 != vm->ViewVertices().end(); i8++) - err += Internal::load(in, *i8); - SET_PROGRESS(6); - - // Read the shape id to index mapping - unsigned map_s; - READ(map_s); - unsigned id, index; - for (unsigned int i4 = 0; i4 < map_s; ++i4) { - READ(id); - READ(index); - vm->shapeIdToIndexMap()[id] = index; - } - - return err; + for (unsigned int i2 = 0; i2 < sv_s; i2++) { + SVertex *sv = new SVertex(); + vm->AddSVertex(sv); + } + for (unsigned int i3 = 0; i3 < ve_s; i3++) { + ViewEdge *ve = new ViewEdge(); + vm->AddViewEdge(ve); + } + + // Read the values for all the objects created above + SET_PROGRESS(1); + for (vector<ViewShape *>::const_iterator i4 = vm->ViewShapes().begin(); + i4 != vm->ViewShapes().end(); + i4++) + err += Internal::load(in, *i4); + SET_PROGRESS(2); + for (vector<FEdge *>::const_iterator i5 = vm->FEdges().begin(); i5 != vm->FEdges().end(); i5++) + err += Internal::load(in, *i5); + SET_PROGRESS(3); + for (vector<SVertex *>::const_iterator i6 = vm->SVertices().begin(); i6 != vm->SVertices().end(); + i6++) + err += Internal::load(in, *i6); + SET_PROGRESS(4); + for (vector<ViewEdge *>::const_iterator i7 = vm->ViewEdges().begin(); + i7 != vm->ViewEdges().end(); + i7++) + err += Internal::load(in, *i7); + SET_PROGRESS(5); + for (vector<ViewVertex *>::const_iterator i8 = vm->ViewVertices().begin(); + i8 != vm->ViewVertices().end(); + i8++) + err += Internal::load(in, *i8); + SET_PROGRESS(6); + + // Read the shape id to index mapping + unsigned map_s; + READ(map_s); + unsigned id, index; + for (unsigned int i4 = 0; i4 < map_s; ++i4) { + READ(id); + READ(index); + vm->shapeIdToIndexMap()[id] = index; + } + + return err; } - -int save(ostream& out, ViewMap *vm, ProgressBar *pb) +int save(ostream &out, ViewMap *vm, ProgressBar *pb) { - if (!vm) - return 1; - - int err = 0; - - // Management of the progress bar (if present) - if (pb) { - pb->reset(); - pb->setLabelText("Saving View Map..."); - pb->setTotalSteps(6); - pb->setProgress(0); - } - - // For every object, initialize its userdata member to its index in the ViewMap list - for (unsigned int i0 = 0; i0 < vm->ViewShapes().size(); i0++) { - vm->ViewShapes()[i0]->userdata = POINTER_FROM_UINT(i0); - vm->ViewShapes()[i0]->sshape()->userdata = POINTER_FROM_UINT(i0); - } - for (unsigned int i1 = 0; i1 < vm->FEdges().size(); i1++) - vm->FEdges()[i1]->userdata = POINTER_FROM_UINT(i1); - for (unsigned int i2 = 0; i2 < vm->SVertices().size(); i2++) - vm->SVertices()[i2]->userdata = POINTER_FROM_UINT(i2); - for (unsigned int i3 = 0; i3 < vm->ViewEdges().size(); i3++) - vm->ViewEdges()[i3]->userdata = POINTER_FROM_UINT(i3); - for (unsigned int i4 = 0; i4 < vm->ViewVertices().size(); i4++) - vm->ViewVertices()[i4]->userdata = POINTER_FROM_UINT(i4); - - // Write the current options - unsigned char flags = Options::getFlags(); - WRITE(flags); - - // Write the size of the five lists (with some extra information for the ViewVertices) - unsigned size; - size = vm->ViewShapes().size(); - WRITE(size); - size = vm->FEdges().size(); - WRITE(size); - if (size) { - bool b = vm->FEdges()[0]->isSmooth(); - WRITE(b); - for (unsigned int i = 0; i < size; i++) { - while (i < size && (vm->FEdges()[i]->isSmooth() == b)) - i++; - if (i < size) { - WRITE(i); - b = !b; - } - } - WRITE(size); - size++; - WRITE(size); - } - size = vm->SVertices().size(); - WRITE(size); - size = vm->ViewEdges().size(); - WRITE(size); - size = vm->ViewVertices().size(); - WRITE(size); - if (size) { - Nature::VertexNature nature = vm->ViewVertices()[0]->getNature(); - WRITE(nature); - nature &= ~Nature::VIEW_VERTEX; - for (unsigned int i = 0; i < size; i++) { - while (i < size && (vm->ViewVertices()[i]->getNature() & nature)) - i++; - if (i < size) { - WRITE(i); - nature = vm->ViewVertices()[i]->getNature() & ~Nature::VIEW_VERTEX; - } - } - WRITE(size); - size++; - WRITE(size); - } - - // Write all the elts of the ViewShapes List - SET_PROGRESS(1); - for (vector<ViewShape*>::const_iterator i5 = vm->ViewShapes().begin(); i5 != vm->ViewShapes().end(); i5++) - err += Internal::save(out, *i5); - SET_PROGRESS(2); - for (vector<FEdge*>::const_iterator i6 = vm->FEdges().begin(); i6 != vm->FEdges().end(); i6++) - err += Internal::save(out, *i6); - SET_PROGRESS(3); - for (vector<SVertex*>::const_iterator i7 = vm->SVertices().begin(); i7 != vm->SVertices().end(); i7++) - err += Internal::save(out, *i7); - SET_PROGRESS(4); - for (vector<ViewEdge*>::const_iterator i8 = vm->ViewEdges().begin(); i8 != vm->ViewEdges().end(); i8++) - err += Internal::save(out, *i8); - SET_PROGRESS(5); - for (vector<ViewVertex*>::const_iterator i9 = vm->ViewVertices().begin(); i9 != vm->ViewVertices().end(); i9++) - err += Internal::save(out, *i9); - - // Write the shape id to index mapping - size = vm->shapeIdToIndexMap().size(); - WRITE(size); - unsigned int id, index; - for (ViewMap::id_to_index_map::iterator mit = vm->shapeIdToIndexMap().begin(), - mitend = vm->shapeIdToIndexMap().end(); - mit != mitend; - ++mit) - { - id = mit->first; - index = mit->second; - WRITE(id); - WRITE(index); - } - - // Reset 'userdata' members - for (vector<ViewShape*>::const_iterator j0 = vm->ViewShapes().begin(); j0 != vm->ViewShapes().end(); j0++) { - (*j0)->userdata = NULL; - (*j0)->sshape()->userdata = NULL; - } - for (vector<FEdge*>::const_iterator j1 = vm->FEdges().begin(); j1 != vm->FEdges().end(); j1++) - (*j1)->userdata = NULL; - for (vector<SVertex*>::const_iterator j2 = vm->SVertices().begin(); j2 != vm->SVertices().end(); j2++) - (*j2)->userdata = NULL; - for (vector<ViewEdge*>::const_iterator j3 = vm->ViewEdges().begin(); j3 != vm->ViewEdges().end(); j3++) - (*j3)->userdata = NULL; - for (vector<ViewVertex*>::const_iterator j4 = vm->ViewVertices().begin(); j4 != vm->ViewVertices().end(); j4++) - (*j4)->userdata = NULL; - SET_PROGRESS(6); - - return err; + if (!vm) + return 1; + + int err = 0; + + // Management of the progress bar (if present) + if (pb) { + pb->reset(); + pb->setLabelText("Saving View Map..."); + pb->setTotalSteps(6); + pb->setProgress(0); + } + + // For every object, initialize its userdata member to its index in the ViewMap list + for (unsigned int i0 = 0; i0 < vm->ViewShapes().size(); i0++) { + vm->ViewShapes()[i0]->userdata = POINTER_FROM_UINT(i0); + vm->ViewShapes()[i0]->sshape()->userdata = POINTER_FROM_UINT(i0); + } + for (unsigned int i1 = 0; i1 < vm->FEdges().size(); i1++) + vm->FEdges()[i1]->userdata = POINTER_FROM_UINT(i1); + for (unsigned int i2 = 0; i2 < vm->SVertices().size(); i2++) + vm->SVertices()[i2]->userdata = POINTER_FROM_UINT(i2); + for (unsigned int i3 = 0; i3 < vm->ViewEdges().size(); i3++) + vm->ViewEdges()[i3]->userdata = POINTER_FROM_UINT(i3); + for (unsigned int i4 = 0; i4 < vm->ViewVertices().size(); i4++) + vm->ViewVertices()[i4]->userdata = POINTER_FROM_UINT(i4); + + // Write the current options + unsigned char flags = Options::getFlags(); + WRITE(flags); + + // Write the size of the five lists (with some extra information for the ViewVertices) + unsigned size; + size = vm->ViewShapes().size(); + WRITE(size); + size = vm->FEdges().size(); + WRITE(size); + if (size) { + bool b = vm->FEdges()[0]->isSmooth(); + WRITE(b); + for (unsigned int i = 0; i < size; i++) { + while (i < size && (vm->FEdges()[i]->isSmooth() == b)) + i++; + if (i < size) { + WRITE(i); + b = !b; + } + } + WRITE(size); + size++; + WRITE(size); + } + size = vm->SVertices().size(); + WRITE(size); + size = vm->ViewEdges().size(); + WRITE(size); + size = vm->ViewVertices().size(); + WRITE(size); + if (size) { + Nature::VertexNature nature = vm->ViewVertices()[0]->getNature(); + WRITE(nature); + nature &= ~Nature::VIEW_VERTEX; + for (unsigned int i = 0; i < size; i++) { + while (i < size && (vm->ViewVertices()[i]->getNature() & nature)) + i++; + if (i < size) { + WRITE(i); + nature = vm->ViewVertices()[i]->getNature() & ~Nature::VIEW_VERTEX; + } + } + WRITE(size); + size++; + WRITE(size); + } + + // Write all the elts of the ViewShapes List + SET_PROGRESS(1); + for (vector<ViewShape *>::const_iterator i5 = vm->ViewShapes().begin(); + i5 != vm->ViewShapes().end(); + i5++) + err += Internal::save(out, *i5); + SET_PROGRESS(2); + for (vector<FEdge *>::const_iterator i6 = vm->FEdges().begin(); i6 != vm->FEdges().end(); i6++) + err += Internal::save(out, *i6); + SET_PROGRESS(3); + for (vector<SVertex *>::const_iterator i7 = vm->SVertices().begin(); i7 != vm->SVertices().end(); + i7++) + err += Internal::save(out, *i7); + SET_PROGRESS(4); + for (vector<ViewEdge *>::const_iterator i8 = vm->ViewEdges().begin(); + i8 != vm->ViewEdges().end(); + i8++) + err += Internal::save(out, *i8); + SET_PROGRESS(5); + for (vector<ViewVertex *>::const_iterator i9 = vm->ViewVertices().begin(); + i9 != vm->ViewVertices().end(); + i9++) + err += Internal::save(out, *i9); + + // Write the shape id to index mapping + size = vm->shapeIdToIndexMap().size(); + WRITE(size); + unsigned int id, index; + for (ViewMap::id_to_index_map::iterator mit = vm->shapeIdToIndexMap().begin(), + mitend = vm->shapeIdToIndexMap().end(); + mit != mitend; + ++mit) { + id = mit->first; + index = mit->second; + WRITE(id); + WRITE(index); + } + + // Reset 'userdata' members + for (vector<ViewShape *>::const_iterator j0 = vm->ViewShapes().begin(); + j0 != vm->ViewShapes().end(); + j0++) { + (*j0)->userdata = NULL; + (*j0)->sshape()->userdata = NULL; + } + for (vector<FEdge *>::const_iterator j1 = vm->FEdges().begin(); j1 != vm->FEdges().end(); j1++) + (*j1)->userdata = NULL; + for (vector<SVertex *>::const_iterator j2 = vm->SVertices().begin(); j2 != vm->SVertices().end(); + j2++) + (*j2)->userdata = NULL; + for (vector<ViewEdge *>::const_iterator j3 = vm->ViewEdges().begin(); + j3 != vm->ViewEdges().end(); + j3++) + (*j3)->userdata = NULL; + for (vector<ViewVertex *>::const_iterator j4 = vm->ViewVertices().begin(); + j4 != vm->ViewVertices().end(); + j4++) + (*j4)->userdata = NULL; + SET_PROGRESS(6); + + return err; } - //////////////////// Options //////////////////// namespace Options { @@ -1216,40 +1233,40 @@ namespace Internal { static unsigned char g_flags = 0; static string g_models_path; -} // End of namespace Internal +} // End of namespace Internal void setFlags(const unsigned char flags) { - Internal::g_flags = flags; + Internal::g_flags = flags; } void addFlags(const unsigned char flags) { - Internal::g_flags |= flags; + Internal::g_flags |= flags; } void rmFlags(const unsigned char flags) { - Internal::g_flags &= ~flags; + Internal::g_flags &= ~flags; } unsigned char getFlags() { - return Internal::g_flags; + return Internal::g_flags; } -void setModelsPath(const string& path) +void setModelsPath(const string &path) { - Internal::g_models_path = path; + Internal::g_models_path = path; } string getModelsPath() { - return Internal::g_models_path; + return Internal::g_models_path; } -} // End of namepace Options +} // namespace Options -} // End of namespace ViewMapIO +} // End of namespace ViewMapIO } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/view_map/ViewMapIO.h b/source/blender/freestyle/intern/view_map/ViewMapIO.h index 57eb450d45b..98d27852c8d 100644 --- a/source/blender/freestyle/intern/view_map/ViewMapIO.h +++ b/source/blender/freestyle/intern/view_map/ViewMapIO.h @@ -36,9 +36,9 @@ namespace ViewMapIO { static const unsigned ZERO = UINT_MAX; -int load(istream& in, ViewMap *vm, ProgressBar *pb = NULL); +int load(istream &in, ViewMap *vm, ProgressBar *pb = NULL); -int save(ostream& out, ViewMap *vm, ProgressBar *pb = NULL); +int save(ostream &out, ViewMap *vm, ProgressBar *pb = NULL); namespace Options { @@ -53,60 +53,54 @@ void rmFlags(const unsigned char flags); unsigned char getFlags(); -void setModelsPath(const string& path); +void setModelsPath(const string &path); string getModelsPath(); -}; // End of namepace Options +}; // namespace Options #ifdef IRIX namespace Internal { -template <unsigned S> -ostream& write(ostream& out, const char *str) +template<unsigned S> ostream &write(ostream &out, const char *str) { - out.put(str[S - 1]); - return write<S - 1>(out, str); + out.put(str[S - 1]); + return write<S - 1>(out, str); } -template<> -ostream& write<1>(ostream& out, const char *str) +template<> ostream &write<1>(ostream &out, const char *str) { - return out.put(str[0]); + return out.put(str[0]); } -template<> -ostream& write<0>(ostream& out, const char *) +template<> ostream &write<0>(ostream &out, const char *) { - return out; + return out; } -template <unsigned S> -istream& read(istream& in, char *str) +template<unsigned S> istream &read(istream &in, char *str) { - in.get(str[S - 1]); - return read<S - 1>(in, str); + in.get(str[S - 1]); + return read<S - 1>(in, str); } -template<> -istream& read<1>(istream& in, char *str) +template<> istream &read<1>(istream &in, char *str) { - return in.get(str[0]); + return in.get(str[0]); } -template<> -istream& read<0>(istream& in, char *) +template<> istream &read<0>(istream &in, char *) { - return in; + return in; } -} // End of namespace Internal +} // End of namespace Internal -#endif // IRIX +#endif // IRIX -} // End of namespace ViewMapIO +} // End of namespace ViewMapIO } /* namespace Freestyle */ -#endif // __FREESTYLE_VIEW_MAP_IO_H__ +#endif // __FREESTYLE_VIEW_MAP_IO_H__ diff --git a/source/blender/freestyle/intern/view_map/ViewMapIterators.h b/source/blender/freestyle/intern/view_map/ViewMapIterators.h index c8a5b6e5d42..7182c5d3362 100644 --- a/source/blender/freestyle/intern/view_map/ViewMapIterators.h +++ b/source/blender/freestyle/intern/view_map/ViewMapIterators.h @@ -24,7 +24,7 @@ #include "ViewMap.h" -#include "../system/Iterator.h" //soc +#include "../system/Iterator.h" //soc namespace Freestyle { @@ -51,176 +51,180 @@ namespace ViewVertexInternal { * An instance of an orientedViewEdgeIterator can only be obtained from a ViewVertex by calling edgesBegin() * or edgesEnd(). */ -class orientedViewEdgeIterator : public Iterator -{ -public: - friend class ViewVertex; - friend class TVertex; - friend class NonTVertex; - friend class ViewEdge; - - // FIXME - typedef TVertex::edge_pointers_container edge_pointers_container; - typedef NonTVertex::edges_container edges_container; - -protected: - Nature::VertexNature _Nature; // the nature of the underlying vertex - // T vertex attributes - edge_pointers_container::iterator _tbegin; - edge_pointers_container::iterator _tend; - edge_pointers_container::iterator _tvertex_iter; - - // Non TVertex attributes - edges_container::iterator _begin; - edges_container::iterator _end; - edges_container::iterator _nontvertex_iter; - -public: - /*! Default constructor */ - inline orientedViewEdgeIterator() {} - - inline orientedViewEdgeIterator(Nature::VertexNature iNature) - { - _Nature = iNature; - } - - /*! Copy constructor */ - orientedViewEdgeIterator(const orientedViewEdgeIterator& iBrother) - { - _Nature = iBrother._Nature; - if (_Nature & Nature::T_VERTEX) { - _tbegin = iBrother._tbegin; - _tend = iBrother._tend; - _tvertex_iter = iBrother._tvertex_iter; - } - else { - _begin = iBrother._begin; - _end = iBrother._end; - _nontvertex_iter = iBrother._nontvertex_iter; - } - } - - virtual ~orientedViewEdgeIterator() {} - -public: - inline orientedViewEdgeIterator(edge_pointers_container::iterator begin, edge_pointers_container::iterator end, - edge_pointers_container::iterator iter) - { - _Nature = Nature::T_VERTEX; - _tbegin = begin; - _tend = end; - _tvertex_iter = iter; - } - - inline orientedViewEdgeIterator(edges_container::iterator begin, edges_container::iterator end, - edges_container::iterator iter) - { - _Nature = Nature::NON_T_VERTEX; - _begin = begin; - _end = end; - _nontvertex_iter = iter; - } - -public: - /*! Tells whether the ViewEdge pointed by this iterator is the first one of the iteration list or not. */ - virtual bool isBegin() const - { - if (_Nature & Nature::T_VERTEX) - return (_tvertex_iter == _tbegin); - else - return (_nontvertex_iter == _begin); - } - - /*! Tells whether the ViewEdge pointed by this iterator is after the last one of the iteration list or not. */ - virtual bool isEnd() const - { - if (_Nature & Nature::T_VERTEX) - return (_tvertex_iter == _tend); - else - return (_nontvertex_iter == _end); - } - - // operators - /*! Increments. In the scripting language, call "increment()". */ - // operator corresponding to ++i - virtual orientedViewEdgeIterator& operator++() - { - increment(); - return *this; - } - - // operator corresponding to i++, i.e. which returns the value *and then* increments. - // That's why we store the value in a temp. - virtual orientedViewEdgeIterator operator++(int) - { - orientedViewEdgeIterator tmp = *this; - increment(); - return tmp; - } - - // comparibility - /*! operator != */ - virtual bool operator!=(const orientedViewEdgeIterator& b) const - { - if (_Nature & Nature::T_VERTEX) - return (_tvertex_iter != b._tvertex_iter); - else - return (_nontvertex_iter != b._nontvertex_iter); - } - - /*! operator == */ - virtual bool operator==(const orientedViewEdgeIterator& b) const - { - return !(*this != b); - } - - // dereferencing - /*! Returns a reference to the pointed orientedViewEdge. - * In the scripting language, you must call "getObject()" instead. - */ - virtual ViewVertex::directedViewEdge& operator*() const - { - if (_Nature & Nature::T_VERTEX) - //return _tvertex_iter; - return **_tvertex_iter; - else - return (*_nontvertex_iter); - } - /*! Returns a pointer to the pointed orientedViewEdge. - * Can't be called in the scripting language. - */ - virtual ViewVertex::directedViewEdge *operator->() const - { - return &(operator*()); - } - -public: - /*! increments.*/ - virtual inline int increment() - { - if (_Nature & Nature::T_VERTEX) { - ViewVertex::directedViewEdge tmp = (**_tvertex_iter); - ++_tvertex_iter; - if (_tvertex_iter != _tend) { - // FIXME : pquoi deja ? - ViewVertex::directedViewEdge tmp2 = (**_tvertex_iter); - if (tmp2.first == tmp.first) - ++_tvertex_iter; - } - } - else { - ++_nontvertex_iter; - } - return 0; - } +class orientedViewEdgeIterator : public Iterator { + public: + friend class ViewVertex; + friend class TVertex; + friend class NonTVertex; + friend class ViewEdge; + + // FIXME + typedef TVertex::edge_pointers_container edge_pointers_container; + typedef NonTVertex::edges_container edges_container; + + protected: + Nature::VertexNature _Nature; // the nature of the underlying vertex + // T vertex attributes + edge_pointers_container::iterator _tbegin; + edge_pointers_container::iterator _tend; + edge_pointers_container::iterator _tvertex_iter; + + // Non TVertex attributes + edges_container::iterator _begin; + edges_container::iterator _end; + edges_container::iterator _nontvertex_iter; + + public: + /*! Default constructor */ + inline orientedViewEdgeIterator() + { + } + + inline orientedViewEdgeIterator(Nature::VertexNature iNature) + { + _Nature = iNature; + } + + /*! Copy constructor */ + orientedViewEdgeIterator(const orientedViewEdgeIterator &iBrother) + { + _Nature = iBrother._Nature; + if (_Nature & Nature::T_VERTEX) { + _tbegin = iBrother._tbegin; + _tend = iBrother._tend; + _tvertex_iter = iBrother._tvertex_iter; + } + else { + _begin = iBrother._begin; + _end = iBrother._end; + _nontvertex_iter = iBrother._nontvertex_iter; + } + } + + virtual ~orientedViewEdgeIterator() + { + } + + public: + inline orientedViewEdgeIterator(edge_pointers_container::iterator begin, + edge_pointers_container::iterator end, + edge_pointers_container::iterator iter) + { + _Nature = Nature::T_VERTEX; + _tbegin = begin; + _tend = end; + _tvertex_iter = iter; + } + + inline orientedViewEdgeIterator(edges_container::iterator begin, + edges_container::iterator end, + edges_container::iterator iter) + { + _Nature = Nature::NON_T_VERTEX; + _begin = begin; + _end = end; + _nontvertex_iter = iter; + } + + public: + /*! Tells whether the ViewEdge pointed by this iterator is the first one of the iteration list or not. */ + virtual bool isBegin() const + { + if (_Nature & Nature::T_VERTEX) + return (_tvertex_iter == _tbegin); + else + return (_nontvertex_iter == _begin); + } + + /*! Tells whether the ViewEdge pointed by this iterator is after the last one of the iteration list or not. */ + virtual bool isEnd() const + { + if (_Nature & Nature::T_VERTEX) + return (_tvertex_iter == _tend); + else + return (_nontvertex_iter == _end); + } + + // operators + /*! Increments. In the scripting language, call "increment()". */ + // operator corresponding to ++i + virtual orientedViewEdgeIterator &operator++() + { + increment(); + return *this; + } + + // operator corresponding to i++, i.e. which returns the value *and then* increments. + // That's why we store the value in a temp. + virtual orientedViewEdgeIterator operator++(int) + { + orientedViewEdgeIterator tmp = *this; + increment(); + return tmp; + } + + // comparibility + /*! operator != */ + virtual bool operator!=(const orientedViewEdgeIterator &b) const + { + if (_Nature & Nature::T_VERTEX) + return (_tvertex_iter != b._tvertex_iter); + else + return (_nontvertex_iter != b._nontvertex_iter); + } + + /*! operator == */ + virtual bool operator==(const orientedViewEdgeIterator &b) const + { + return !(*this != b); + } + + // dereferencing + /*! Returns a reference to the pointed orientedViewEdge. + * In the scripting language, you must call "getObject()" instead. + */ + virtual ViewVertex::directedViewEdge &operator*() const + { + if (_Nature & Nature::T_VERTEX) + //return _tvertex_iter; + return **_tvertex_iter; + else + return (*_nontvertex_iter); + } + /*! Returns a pointer to the pointed orientedViewEdge. + * Can't be called in the scripting language. + */ + virtual ViewVertex::directedViewEdge *operator->() const + { + return &(operator*()); + } + + public: + /*! increments.*/ + virtual inline int increment() + { + if (_Nature & Nature::T_VERTEX) { + ViewVertex::directedViewEdge tmp = (**_tvertex_iter); + ++_tvertex_iter; + if (_tvertex_iter != _tend) { + // FIXME : pquoi deja ? + ViewVertex::directedViewEdge tmp2 = (**_tvertex_iter); + if (tmp2.first == tmp.first) + ++_tvertex_iter; + } + } + else { + ++_nontvertex_iter; + } + return 0; + } #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:orientedViewEdgeIterator") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:orientedViewEdgeIterator") #endif - }; -} // ViewVertexInternal namespace +} // namespace ViewVertexInternal /**********************************/ /* */ @@ -237,166 +241,165 @@ namespace ViewEdgeInternal { // ///////////////////////////////////////////////// -class SVertexIterator : public Interface0DIteratorNested -{ -public: - SVertexIterator() - { - _vertex = NULL; - _begin = NULL; - _previous_edge = NULL; - _next_edge = NULL; - _t = 0; - } - - SVertexIterator(const SVertexIterator& vi) - { - _vertex = vi._vertex; - _begin = vi._begin; - _previous_edge = vi._previous_edge; - _next_edge = vi._next_edge; - _t = vi._t; - } - - SVertexIterator(SVertex *v, SVertex *begin, FEdge *prev, FEdge *next, float t) - { - _vertex = v; - _begin = begin; - _previous_edge = prev; - _next_edge = next; - _t = t; - } - - SVertexIterator& operator=(const SVertexIterator& vi) - { - _vertex = vi._vertex; - _begin = vi._begin; - _previous_edge = vi._previous_edge; - _next_edge = vi._next_edge; - _t = vi._t; - return *this; - } - - virtual ~SVertexIterator() {} - - virtual string getExactTypeName() const - { - return "SVertexIterator"; - } - - virtual SVertex& operator*() - { - return *_vertex; - } - - virtual SVertex *operator->() - { - return &(operator*()); - } - - virtual SVertexIterator& operator++() - { - increment(); - return *this; - } - - virtual SVertexIterator operator++(int) - { - SVertexIterator ret(*this); - increment(); - return ret; - } - - virtual SVertexIterator& operator--() - { - decrement(); - return *this; - } - - virtual SVertexIterator operator--(int) - { - SVertexIterator ret(*this); - decrement(); - return ret; - } - - virtual int increment() - { - if (!_next_edge) { - _vertex = NULL; - return 0; - } - _t += (float)_next_edge->getLength2D(); - _vertex = _next_edge->vertexB(); - _previous_edge = _next_edge; - _next_edge = _next_edge->nextEdge(); - return 0; - } - - virtual int decrement() - { - if (!_previous_edge) { - _vertex = NULL; - return 0; - } - if ((!_next_edge) && (!_vertex)) { - _vertex = _previous_edge->vertexB(); - return 0; - } - _t -= (float)_previous_edge->getLength2D(); - _vertex = _previous_edge->vertexA(); - _next_edge = _previous_edge; - _previous_edge = _previous_edge->previousEdge(); - return 0; - } - - virtual bool isBegin() const - { - return _vertex == _begin; - } - - virtual bool isEnd() const - { - return (!_vertex) || (_vertex == _begin && _previous_edge); - } - - virtual float t() const - { - return _t; - } - - virtual float u() const - { - return _t / (float)_next_edge->viewedge()->getLength2D(); - } - - virtual bool operator==(const Interface0DIteratorNested& it) const - { - const SVertexIterator *it_exact = dynamic_cast<const SVertexIterator*>(&it); - if (!it_exact) - return false; - return (_vertex == it_exact->_vertex); - } - - virtual SVertexIterator *copy() const - { - return new SVertexIterator(*this); - } - -private: - SVertex *_vertex; - SVertex *_begin; - FEdge *_previous_edge; - FEdge *_next_edge; - float _t; // curvilinear abscissa +class SVertexIterator : public Interface0DIteratorNested { + public: + SVertexIterator() + { + _vertex = NULL; + _begin = NULL; + _previous_edge = NULL; + _next_edge = NULL; + _t = 0; + } + + SVertexIterator(const SVertexIterator &vi) + { + _vertex = vi._vertex; + _begin = vi._begin; + _previous_edge = vi._previous_edge; + _next_edge = vi._next_edge; + _t = vi._t; + } + + SVertexIterator(SVertex *v, SVertex *begin, FEdge *prev, FEdge *next, float t) + { + _vertex = v; + _begin = begin; + _previous_edge = prev; + _next_edge = next; + _t = t; + } + + SVertexIterator &operator=(const SVertexIterator &vi) + { + _vertex = vi._vertex; + _begin = vi._begin; + _previous_edge = vi._previous_edge; + _next_edge = vi._next_edge; + _t = vi._t; + return *this; + } + + virtual ~SVertexIterator() + { + } + + virtual string getExactTypeName() const + { + return "SVertexIterator"; + } + + virtual SVertex &operator*() + { + return *_vertex; + } + + virtual SVertex *operator->() + { + return &(operator*()); + } + + virtual SVertexIterator &operator++() + { + increment(); + return *this; + } + + virtual SVertexIterator operator++(int) + { + SVertexIterator ret(*this); + increment(); + return ret; + } + + virtual SVertexIterator &operator--() + { + decrement(); + return *this; + } + + virtual SVertexIterator operator--(int) + { + SVertexIterator ret(*this); + decrement(); + return ret; + } + + virtual int increment() + { + if (!_next_edge) { + _vertex = NULL; + return 0; + } + _t += (float)_next_edge->getLength2D(); + _vertex = _next_edge->vertexB(); + _previous_edge = _next_edge; + _next_edge = _next_edge->nextEdge(); + return 0; + } + + virtual int decrement() + { + if (!_previous_edge) { + _vertex = NULL; + return 0; + } + if ((!_next_edge) && (!_vertex)) { + _vertex = _previous_edge->vertexB(); + return 0; + } + _t -= (float)_previous_edge->getLength2D(); + _vertex = _previous_edge->vertexA(); + _next_edge = _previous_edge; + _previous_edge = _previous_edge->previousEdge(); + return 0; + } + + virtual bool isBegin() const + { + return _vertex == _begin; + } + + virtual bool isEnd() const + { + return (!_vertex) || (_vertex == _begin && _previous_edge); + } + + virtual float t() const + { + return _t; + } + + virtual float u() const + { + return _t / (float)_next_edge->viewedge()->getLength2D(); + } + + virtual bool operator==(const Interface0DIteratorNested &it) const + { + const SVertexIterator *it_exact = dynamic_cast<const SVertexIterator *>(&it); + if (!it_exact) + return false; + return (_vertex == it_exact->_vertex); + } + + virtual SVertexIterator *copy() const + { + return new SVertexIterator(*this); + } + + private: + SVertex *_vertex; + SVertex *_begin; + FEdge *_previous_edge; + FEdge *_next_edge; + float _t; // curvilinear abscissa #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:SVertexIterator") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:SVertexIterator") #endif - }; - // // ViewEdgeIterator (base class) // @@ -407,173 +410,173 @@ private: * ViewEdge) to go when pointing on a given ViewEdge. * ::Caution::: the dereferencing operator returns a *pointer* to the pointed ViewEdge. */ -class ViewEdgeIterator : public Iterator -{ -public: - /*! Builds a ViewEdgeIterator from a starting ViewEdge and its orientation. - * \param begin: - * The ViewEdge from where to start the iteration. - * \param orientation: - * If true, we'll look for the next ViewEdge among the ViewEdges that surround the ending ViewVertex of begin. - * If false, we'll search over the ViewEdges surrounding the ending ViewVertex of begin. - */ - ViewEdgeIterator(ViewEdge *begin = NULL, bool orientation = true) - { - _orientation = orientation; - _edge = begin; - _begin = begin; - } - - /*! Copy constructor */ - ViewEdgeIterator(const ViewEdgeIterator& it) - { - _orientation = it._orientation; - _edge = it._edge; - _begin = it._begin; - } - - virtual ~ViewEdgeIterator() {} - - /*! Returns the string "ViewEdgeIterator" */ - virtual string getExactTypeName() const - { - return "ViewEdgeIterator"; - } - - /*! Returns the current pointed ViewEdge. */ - ViewEdge *getCurrentEdge() - { - return _edge; - } - - /*! Sets the current pointed ViewEdge. */ - void setCurrentEdge(ViewEdge *edge) - { - _edge = edge; - } - - /*! Returns the first ViewEdge used for the iteration. */ - ViewEdge *getBegin() - { - return _begin; - } - - /*! Sets the first ViewEdge used for the iteration. */ - void setBegin(ViewEdge *begin) - { - _begin = begin; - } - - /*! Gets the orientation of the pointed ViewEdge in the iteration. */ - bool getOrientation() const - { - return _orientation; - } - - /*! Sets the orientation of the pointed ViewEdge in the iteration. */ - void setOrientation(bool orientation) - { - _orientation = orientation; - } - - /*! Changes the current orientation. */ - void changeOrientation() - { - _orientation = !_orientation; - } - - /*! Returns a *pointer* to the pointed ViewEdge. */ - virtual ViewEdge *operator*() - { - return _edge; - } - - virtual ViewEdge *operator->() - { - return operator*(); - } - - /*! Increments. In the scripting language, call "increment()". */ - virtual ViewEdgeIterator& operator++() - { - increment(); - return *this; - } - - /*! Increments. In the scripting language, call "increment()". */ - virtual ViewEdgeIterator operator++(int) - { - ViewEdgeIterator tmp(*this); - increment(); - return tmp; - } - - /*! increments. */ - virtual int increment() - { - cerr << "Warning: method increment() not implemented" << endl; - return 0; - } - - /*! Decrements. In the scripting language, call "decrement()". */ - virtual ViewEdgeIterator& operator--() - { - decrement(); - return *this; - } - - /*! Decrements. In the scripting language, call "decrement()". */ - virtual ViewEdgeIterator operator--(int) - { - ViewEdgeIterator tmp(*this); - decrement(); - return tmp; - } - - /*! decrements. */ - virtual int decrement() - { - cerr << "Warning: method decrement() not implemented" << endl; - return 0; - } - - /*! Returns true if the pointed ViewEdge is the first one used for the iteration. */ - virtual bool isBegin() const - { - return _edge == _begin; - } - - /*! Returns true if the pointed ViewEdge* equals 0. */ - virtual bool isEnd() const - { - return !_edge; - } - - /*! operator == */ - virtual bool operator==(ViewEdgeIterator& it) const - { - return _edge == it._edge; - } - - /*! operator != */ - virtual bool operator!=(ViewEdgeIterator& it) const - { - return !(*this == it); - } - -protected: - bool _orientation; - ViewEdge *_edge; - ViewEdge *_begin; +class ViewEdgeIterator : public Iterator { + public: + /*! Builds a ViewEdgeIterator from a starting ViewEdge and its orientation. + * \param begin: + * The ViewEdge from where to start the iteration. + * \param orientation: + * If true, we'll look for the next ViewEdge among the ViewEdges that surround the ending ViewVertex of begin. + * If false, we'll search over the ViewEdges surrounding the ending ViewVertex of begin. + */ + ViewEdgeIterator(ViewEdge *begin = NULL, bool orientation = true) + { + _orientation = orientation; + _edge = begin; + _begin = begin; + } + + /*! Copy constructor */ + ViewEdgeIterator(const ViewEdgeIterator &it) + { + _orientation = it._orientation; + _edge = it._edge; + _begin = it._begin; + } + + virtual ~ViewEdgeIterator() + { + } + + /*! Returns the string "ViewEdgeIterator" */ + virtual string getExactTypeName() const + { + return "ViewEdgeIterator"; + } + + /*! Returns the current pointed ViewEdge. */ + ViewEdge *getCurrentEdge() + { + return _edge; + } + + /*! Sets the current pointed ViewEdge. */ + void setCurrentEdge(ViewEdge *edge) + { + _edge = edge; + } + + /*! Returns the first ViewEdge used for the iteration. */ + ViewEdge *getBegin() + { + return _begin; + } + + /*! Sets the first ViewEdge used for the iteration. */ + void setBegin(ViewEdge *begin) + { + _begin = begin; + } + + /*! Gets the orientation of the pointed ViewEdge in the iteration. */ + bool getOrientation() const + { + return _orientation; + } + + /*! Sets the orientation of the pointed ViewEdge in the iteration. */ + void setOrientation(bool orientation) + { + _orientation = orientation; + } + + /*! Changes the current orientation. */ + void changeOrientation() + { + _orientation = !_orientation; + } + + /*! Returns a *pointer* to the pointed ViewEdge. */ + virtual ViewEdge *operator*() + { + return _edge; + } + + virtual ViewEdge *operator->() + { + return operator*(); + } + + /*! Increments. In the scripting language, call "increment()". */ + virtual ViewEdgeIterator &operator++() + { + increment(); + return *this; + } + + /*! Increments. In the scripting language, call "increment()". */ + virtual ViewEdgeIterator operator++(int) + { + ViewEdgeIterator tmp(*this); + increment(); + return tmp; + } + + /*! increments. */ + virtual int increment() + { + cerr << "Warning: method increment() not implemented" << endl; + return 0; + } + + /*! Decrements. In the scripting language, call "decrement()". */ + virtual ViewEdgeIterator &operator--() + { + decrement(); + return *this; + } + + /*! Decrements. In the scripting language, call "decrement()". */ + virtual ViewEdgeIterator operator--(int) + { + ViewEdgeIterator tmp(*this); + decrement(); + return tmp; + } + + /*! decrements. */ + virtual int decrement() + { + cerr << "Warning: method decrement() not implemented" << endl; + return 0; + } + + /*! Returns true if the pointed ViewEdge is the first one used for the iteration. */ + virtual bool isBegin() const + { + return _edge == _begin; + } + + /*! Returns true if the pointed ViewEdge* equals 0. */ + virtual bool isEnd() const + { + return !_edge; + } + + /*! operator == */ + virtual bool operator==(ViewEdgeIterator &it) const + { + return _edge == it._edge; + } + + /*! operator != */ + virtual bool operator!=(ViewEdgeIterator &it) const + { + return !(*this == it); + } + + protected: + bool _orientation; + ViewEdge *_edge; + ViewEdge *_begin; #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:ViewEdgeIterator") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:ViewEdgeIterator") #endif - }; -} // end of namespace ViewEdgeInternal +} // end of namespace ViewEdgeInternal } /* namespace Freestyle */ -#endif // __FREESTYLE_VIEW_MAP_ITERATORS_H__ +#endif // __FREESTYLE_VIEW_MAP_ITERATORS_H__ diff --git a/source/blender/freestyle/intern/view_map/ViewMapTesselator.cpp b/source/blender/freestyle/intern/view_map/ViewMapTesselator.cpp index 62656c6ade6..8abd464b0cf 100644 --- a/source/blender/freestyle/intern/view_map/ViewMapTesselator.cpp +++ b/source/blender/freestyle/intern/view_map/ViewMapTesselator.cpp @@ -25,16 +25,16 @@ namespace Freestyle { NodeGroup *ViewMapTesselator::Tesselate(ViewMap *iViewMap) { - if (0 == iViewMap->ViewEdges().size()) - return NULL; + if (0 == iViewMap->ViewEdges().size()) + return NULL; - const vector<ViewEdge*>& viewedges = iViewMap->ViewEdges(); - return Tesselate(viewedges.begin(), viewedges.end()); + const vector<ViewEdge *> &viewedges = iViewMap->ViewEdges(); + return Tesselate(viewedges.begin(), viewedges.end()); } NodeGroup *ViewMapTesselator::Tesselate(WShape *) { - return NULL; + return NULL; } } /* namespace Freestyle */ diff --git a/source/blender/freestyle/intern/view_map/ViewMapTesselator.h b/source/blender/freestyle/intern/view_map/ViewMapTesselator.h index a24a7cfdf18..2173ea42fab 100644 --- a/source/blender/freestyle/intern/view_map/ViewMapTesselator.h +++ b/source/blender/freestyle/intern/view_map/ViewMapTesselator.h @@ -34,7 +34,7 @@ #include "../winged_edge/WEdge.h" #ifdef WITH_CXX_GUARDEDALLOC -#include "MEM_guardedalloc.h" +# include "MEM_guardedalloc.h" #endif namespace Freestyle { @@ -44,100 +44,105 @@ class NodeGroup; class SShape; class WShape; -class ViewMapTesselator -{ -public: - inline ViewMapTesselator() - { - _nature = Nature::SILHOUETTE | Nature::BORDER | Nature::CREASE; - _FrsMaterial.setDiffuse(0, 0, 0, 1); - _overloadFrsMaterial = false; - } - - virtual ~ViewMapTesselator() {} - - /*! Builds a set of lines rep contained under a a NodeShape, itself contained under a NodeGroup from a ViewMap */ - NodeGroup *Tesselate(ViewMap *iViewMap); - - /*! Builds a set of lines rep contained under a a NodeShape, itself contained under a NodeGroup from a set of - * view edges - */ - template<class ViewEdgesIterator> - NodeGroup *Tesselate(ViewEdgesIterator begin, ViewEdgesIterator end); - - /*! Builds a set of lines rep contained among a NodeShape, from a WShape */ - NodeGroup *Tesselate(WShape *iWShape); - - inline void setNature(Nature::EdgeNature iNature) - { - _nature = iNature; - } - - inline void setFrsMaterial(const FrsMaterial& iMaterial) - { - _FrsMaterial = iMaterial; - _overloadFrsMaterial = true; - } - - inline Nature::EdgeNature nature() - { - return _nature; - } - - inline const FrsMaterial& frs_material() const - { - return _FrsMaterial; - } - -protected: - virtual void AddVertexToLine(LineRep *iLine, SVertex *v) = 0; - -private: - Nature::EdgeNature _nature; - FrsMaterial _FrsMaterial; - bool _overloadFrsMaterial; +class ViewMapTesselator { + public: + inline ViewMapTesselator() + { + _nature = Nature::SILHOUETTE | Nature::BORDER | Nature::CREASE; + _FrsMaterial.setDiffuse(0, 0, 0, 1); + _overloadFrsMaterial = false; + } + + virtual ~ViewMapTesselator() + { + } + + /*! Builds a set of lines rep contained under a a NodeShape, itself contained under a NodeGroup from a ViewMap */ + NodeGroup *Tesselate(ViewMap *iViewMap); + + /*! Builds a set of lines rep contained under a a NodeShape, itself contained under a NodeGroup from a set of + * view edges + */ + template<class ViewEdgesIterator> + NodeGroup *Tesselate(ViewEdgesIterator begin, ViewEdgesIterator end); + + /*! Builds a set of lines rep contained among a NodeShape, from a WShape */ + NodeGroup *Tesselate(WShape *iWShape); + + inline void setNature(Nature::EdgeNature iNature) + { + _nature = iNature; + } + + inline void setFrsMaterial(const FrsMaterial &iMaterial) + { + _FrsMaterial = iMaterial; + _overloadFrsMaterial = true; + } + + inline Nature::EdgeNature nature() + { + return _nature; + } + + inline const FrsMaterial &frs_material() const + { + return _FrsMaterial; + } + + protected: + virtual void AddVertexToLine(LineRep *iLine, SVertex *v) = 0; + + private: + Nature::EdgeNature _nature; + FrsMaterial _FrsMaterial; + bool _overloadFrsMaterial; #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:ViewMapTesselator") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:ViewMapTesselator") #endif }; /*! Class to tesselate the 2D projected silhouette */ -class ViewMapTesselator2D : public ViewMapTesselator -{ -public: - inline ViewMapTesselator2D() : ViewMapTesselator() {} - virtual ~ViewMapTesselator2D() {} - -protected: - virtual void AddVertexToLine(LineRep *iLine, SVertex *v) - { - iLine->AddVertex(v->point2D()); - } +class ViewMapTesselator2D : public ViewMapTesselator { + public: + inline ViewMapTesselator2D() : ViewMapTesselator() + { + } + virtual ~ViewMapTesselator2D() + { + } + + protected: + virtual void AddVertexToLine(LineRep *iLine, SVertex *v) + { + iLine->AddVertex(v->point2D()); + } #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:ViewMapTesselator2D") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:ViewMapTesselator2D") #endif - }; /*! Class to tesselate the 3D silhouette */ -class ViewMapTesselator3D : public ViewMapTesselator -{ -public: - inline ViewMapTesselator3D() : ViewMapTesselator() {} - virtual ~ViewMapTesselator3D() {} - -protected: - virtual void AddVertexToLine(LineRep *iLine, SVertex *v) - { - iLine->AddVertex(v->point3D()); - } +class ViewMapTesselator3D : public ViewMapTesselator { + public: + inline ViewMapTesselator3D() : ViewMapTesselator() + { + } + virtual ~ViewMapTesselator3D() + { + } + + protected: + virtual void AddVertexToLine(LineRep *iLine, SVertex *v) + { + iLine->AddVertex(v->point3D()); + } #ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:ViewMapTesselator3D") + MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:ViewMapTesselator3D") #endif - }; // @@ -148,73 +153,73 @@ protected: template<class ViewEdgesIterator> NodeGroup *ViewMapTesselator::Tesselate(ViewEdgesIterator begin, ViewEdgesIterator end) { - NodeGroup *group = new NodeGroup; - NodeShape *tshape = new NodeShape; - group->AddChild(tshape); - //tshape->frs_material().setDiffuse(0.0f, 0.0f, 0.0f, 1.0f); - tshape->setFrsMaterial(_FrsMaterial); + NodeGroup *group = new NodeGroup; + NodeShape *tshape = new NodeShape; + group->AddChild(tshape); + //tshape->frs_material().setDiffuse(0.0f, 0.0f, 0.0f, 1.0f); + tshape->setFrsMaterial(_FrsMaterial); - LineRep *line; + LineRep *line; - FEdge *firstEdge; - FEdge *nextFEdge, *currentEdge; + FEdge *firstEdge; + FEdge *nextFEdge, *currentEdge; - int id = 0; - //for (vector<ViewEdge*>::const_iterator c = viewedges.begin(), cend = viewedges.end(); c != cend; c++) - for (ViewEdgesIterator c = begin, cend = end; c != cend; c++) { + int id = 0; + //for (vector<ViewEdge*>::const_iterator c = viewedges.begin(), cend = viewedges.end(); c != cend; c++) + for (ViewEdgesIterator c = begin, cend = end; c != cend; c++) { #if 0 - if ((*c)->qi() > 0) { - continue; - } - if (!((*c)->nature() & (_nature))) { - continue; - } + if ((*c)->qi() > 0) { + continue; + } + if (!((*c)->nature() & (_nature))) { + continue; + } #endif - firstEdge = (*c)->fedgeA(); + firstEdge = (*c)->fedgeA(); #if 0 - if (firstEdge->invisibility() > 0) - continue; + if (firstEdge->invisibility() > 0) + continue; #endif - line = new OrientedLineRep(); - if (_overloadFrsMaterial) - line->setFrsMaterial(_FrsMaterial); - - // there might be chains containing a single element - if (0 == (firstEdge)->nextEdge()) { - line->setStyle(LineRep::LINES); - //line->AddVertex((*c)->vertexA()->point3D()); - //line->AddVertex((*c)->vertexB()->point3D()); - AddVertexToLine(line, firstEdge->vertexA()); - AddVertexToLine(line, firstEdge->vertexB()); - } - else { - line->setStyle(LineRep::LINE_STRIP); - - //firstEdge = (*c); - nextFEdge = firstEdge; - currentEdge = firstEdge; - do { - //line->AddVertex(nextFEdge->vertexA()->point3D()); - AddVertexToLine(line, nextFEdge->vertexA()); - currentEdge = nextFEdge; - nextFEdge = nextFEdge->nextEdge(); - } while ((nextFEdge != NULL) && (nextFEdge != firstEdge)); - // Add the last vertex - //line->AddVertex(currentEdge->vertexB()->point3D()); - AddVertexToLine(line, currentEdge->vertexB()); - } - - line->setId((*c)->getId().getFirst()); - line->ComputeBBox(); - tshape->AddRep(line); - id++; - } - - return group; + line = new OrientedLineRep(); + if (_overloadFrsMaterial) + line->setFrsMaterial(_FrsMaterial); + + // there might be chains containing a single element + if (0 == (firstEdge)->nextEdge()) { + line->setStyle(LineRep::LINES); + //line->AddVertex((*c)->vertexA()->point3D()); + //line->AddVertex((*c)->vertexB()->point3D()); + AddVertexToLine(line, firstEdge->vertexA()); + AddVertexToLine(line, firstEdge->vertexB()); + } + else { + line->setStyle(LineRep::LINE_STRIP); + + //firstEdge = (*c); + nextFEdge = firstEdge; + currentEdge = firstEdge; + do { + //line->AddVertex(nextFEdge->vertexA()->point3D()); + AddVertexToLine(line, nextFEdge->vertexA()); + currentEdge = nextFEdge; + nextFEdge = nextFEdge->nextEdge(); + } while ((nextFEdge != NULL) && (nextFEdge != firstEdge)); + // Add the last vertex + //line->AddVertex(currentEdge->vertexB()->point3D()); + AddVertexToLine(line, currentEdge->vertexB()); + } + + line->setId((*c)->getId().getFirst()); + line->ComputeBBox(); + tshape->AddRep(line); + id++; + } + + return group; } } /* namespace Freestyle */ -#endif // __FREESTYLE_VIEW_MAP_TESSELATOR_H__ +#endif // __FREESTYLE_VIEW_MAP_TESSELATOR_H__ |