From 699da2fb0d9012cef5e45cc1b547a01fd92dbc1c Mon Sep 17 00:00:00 2001 From: Tamito Kajiyama Date: Wed, 2 Jan 2013 01:55:30 +0000 Subject: Yet another big style clean-up patch by Bastien Montagne, thanks a lot! Now the code style is acceptable for the merge now, according to Bastien. Thanks again Bastien for having this done! :) --- .../view_map/ArbitraryGridDensityProvider.cpp | 102 +- .../intern/view_map/ArbitraryGridDensityProvider.h | 88 +- .../view_map/AverageAreaGridDensityProvider.cpp | 108 +- .../view_map/AverageAreaGridDensityProvider.h | 91 +- .../blender/freestyle/intern/view_map/BoxGrid.cpp | 169 +- source/blender/freestyle/intern/view_map/BoxGrid.h | 316 +- .../intern/view_map/CulledOccluderSource.cpp | 236 +- .../intern/view_map/CulledOccluderSource.h | 82 +- .../freestyle/intern/view_map/FEdgeXDetector.cpp | 1342 ++++--- .../freestyle/intern/view_map/FEdgeXDetector.h | 422 ++- .../freestyle/intern/view_map/Functions0D.cpp | 638 ++-- .../freestyle/intern/view_map/Functions0D.h | 950 ++--- .../freestyle/intern/view_map/Functions1D.cpp | 444 ++- .../freestyle/intern/view_map/Functions1D.h | 1060 +++--- .../intern/view_map/GridDensityProvider.h | 137 +- .../HeuristicGridDensityProviderFactory.cpp | 92 +- .../view_map/HeuristicGridDensityProviderFactory.h | 88 +- .../freestyle/intern/view_map/Interface0D.h | 630 ++-- .../freestyle/intern/view_map/Interface1D.h | 382 +- .../freestyle/intern/view_map/OccluderSource.cpp | 120 +- .../freestyle/intern/view_map/OccluderSource.h | 78 +- .../intern/view_map/Pow23GridDensityProvider.cpp | 96 +- .../intern/view_map/Pow23GridDensityProvider.h | 90 +- .../freestyle/intern/view_map/Silhouette.cpp | 680 ++-- .../blender/freestyle/intern/view_map/Silhouette.h | 3163 +++++++++------- .../intern/view_map/SilhouetteGeomEngine.cpp | 361 +- .../intern/view_map/SilhouetteGeomEngine.h | 235 +- .../freestyle/intern/view_map/SphericalGrid.cpp | 166 +- .../freestyle/intern/view_map/SphericalGrid.h | 322 +- .../freestyle/intern/view_map/SteerableViewMap.cpp | 477 +-- .../freestyle/intern/view_map/SteerableViewMap.h | 271 +- .../freestyle/intern/view_map/ViewEdgeXBuilder.cpp | 1403 +++---- .../freestyle/intern/view_map/ViewEdgeXBuilder.h | 414 +- .../blender/freestyle/intern/view_map/ViewMap.cpp | 1278 ++++--- source/blender/freestyle/intern/view_map/ViewMap.h | 3019 ++++++++------- .../intern/view_map/ViewMapAdvancedIterators.h | 1464 ++++---- .../freestyle/intern/view_map/ViewMapBuilder.cpp | 3934 ++++++++++---------- .../freestyle/intern/view_map/ViewMapBuilder.h | 471 +-- .../freestyle/intern/view_map/ViewMapIO.cpp | 2365 ++++++------ .../blender/freestyle/intern/view_map/ViewMapIO.h | 233 +- .../freestyle/intern/view_map/ViewMapIterators.h | 1065 +++--- .../intern/view_map/ViewMapTesselator.cpp | 65 +- .../freestyle/intern/view_map/ViewMapTesselator.h | 329 +- .../freestyle/intern/winged_edge/Curvature.cpp | 1112 +++--- .../freestyle/intern/winged_edge/Curvature.h | 243 +- .../blender/freestyle/intern/winged_edge/Nature.h | 138 +- .../blender/freestyle/intern/winged_edge/WEdge.cpp | 1179 +++--- .../blender/freestyle/intern/winged_edge/WEdge.h | 2183 ++++++----- .../freestyle/intern/winged_edge/WFillGrid.cpp | 118 +- .../freestyle/intern/winged_edge/WFillGrid.h | 132 +- .../freestyle/intern/winged_edge/WSFillGrid.cpp | 117 +- .../freestyle/intern/winged_edge/WSFillGrid.h | 130 +- .../freestyle/intern/winged_edge/WXEdge.cpp | 550 +-- .../blender/freestyle/intern/winged_edge/WXEdge.h | 1295 ++++--- .../freestyle/intern/winged_edge/WXEdgeBuilder.cpp | 90 +- .../freestyle/intern/winged_edge/WXEdgeBuilder.h | 79 +- .../intern/winged_edge/WingedEdgeBuilder.cpp | 665 ++-- .../intern/winged_edge/WingedEdgeBuilder.h | 318 +- 58 files changed, 19902 insertions(+), 17923 deletions(-) diff --git a/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.cpp b/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.cpp index 15b2b3343cc..c7925026cd5 100644 --- a/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.cpp +++ b/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.cpp @@ -1,52 +1,58 @@ -// -// Filename : ArbitraryGridDensityProvider.cpp -// Author(s) : Alexander Beels -// Purpose : Class to define a cell grid surrounding -// the projected image of a scene -// Date of creation : 2011-2-5 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.cpp + * \ingroup freestyle + * \brief Class to define a cell grid surrounding the projected image of a scene + * \author Alexander Beels + * \date 2011-2-5 + */ #include "ArbitraryGridDensityProvider.h" -ArbitraryGridDensityProvider::ArbitraryGridDensityProvider(OccluderSource& source, const real proscenium[4], unsigned numCells) - : GridDensityProvider(source), numCells(numCells) +ArbitraryGridDensityProvider::ArbitraryGridDensityProvider(OccluderSource& source, const real proscenium[4], + unsigned numCells) +: GridDensityProvider(source), numCells(numCells) { initialize (proscenium); } -ArbitraryGridDensityProvider::ArbitraryGridDensityProvider(OccluderSource& source, const BBox& bbox, const GridHelpers::Transform& transform, unsigned numCells) - : GridDensityProvider(source), numCells(numCells) +ArbitraryGridDensityProvider::ArbitraryGridDensityProvider(OccluderSource& source, const BBox& bbox, + const GridHelpers::Transform& transform, unsigned numCells) +: GridDensityProvider(source), numCells(numCells) { real proscenium[4]; calculateQuickProscenium(transform, bbox, 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); @@ -54,9 +60,9 @@ ArbitraryGridDensityProvider::ArbitraryGridDensityProvider(OccluderSource& sourc initialize (proscenium); } -ArbitraryGridDensityProvider::~ArbitraryGridDensityProvider () {} +ArbitraryGridDensityProvider::~ArbitraryGridDensityProvider() {} -void ArbitraryGridDensityProvider::initialize (const real proscenium[4]) +void ArbitraryGridDensityProvider::initialize(const real proscenium[4]) { float prosceniumWidth = (proscenium[1] - proscenium[0]); float prosceniumHeight = (proscenium[3] - proscenium[2]); @@ -70,11 +76,11 @@ void ArbitraryGridDensityProvider::initialize (const real proscenium[4]) 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) ) { + float safetyZone = 0.1f; + if (_cellsX * _cellSize < prosceniumWidth * (1.0 + safetyZone)) { _cellsX = prosceniumWidth * (1.0 + safetyZone) / _cellSize; } - if ( _cellsY * _cellSize < prosceniumHeight * (1.0 + safetyZone) ) { + if (_cellsY * _cellSize < prosceniumHeight * (1.0 + safetyZone)) { _cellsY = prosceniumHeight * (1.0 + safetyZone) / _cellSize; } cout << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square." << endl; @@ -85,24 +91,26 @@ void ArbitraryGridDensityProvider::initialize (const real proscenium[4]) } ArbitraryGridDensityProviderFactory::ArbitraryGridDensityProviderFactory(unsigned numCells) - : numCells(numCells) +: numCells(numCells) { } -ArbitraryGridDensityProviderFactory::~ArbitraryGridDensityProviderFactory () {} +ArbitraryGridDensityProviderFactory::~ArbitraryGridDensityProviderFactory() {} -auto_ptr ArbitraryGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const real proscenium[4]) +auto_ptr ArbitraryGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, + const real proscenium[4]) { return auto_ptr(new ArbitraryGridDensityProvider(source, proscenium, numCells)); } -auto_ptr ArbitraryGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const BBox& bbox, const GridHelpers::Transform& transform) +auto_ptr +ArbitraryGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const BBox& bbox, + const GridHelpers::Transform& transform) { return auto_ptr(new ArbitraryGridDensityProvider(source, bbox, transform, numCells)); } -auto_ptr ArbitraryGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source) +auto_ptr ArbitraryGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source) { return auto_ptr(new ArbitraryGridDensityProvider(source, numCells)); } - diff --git a/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.h b/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.h index f863b2132a7..f8d43f19936 100644 --- a/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.h +++ b/source/blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.h @@ -1,48 +1,54 @@ -// -// Filename : ArbitraryGridDensityProvider.h -// Author(s) : Alexander Beels -// Purpose : Class to define a cell grid surrounding -// the projected image of a scene -// Date of creation : 2011-2-5 -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef __FREESTYLE_ARBITRARY_GRID_DENSITY_PROVIDER_H__ +#define __FREESTYLE_ARBITRARY_GRID_DENSITY_PROVIDER_H__ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef ARBITRARYGRIDDENSITYPROVIDER_H -#define ARBITRARYGRIDDENSITYPROVIDER_H +/** \file blender/freestyle/intern/view_map/ArbitraryGridDensityProvider.h + * \ingroup freestyle + * \brief Class to define a cell grid surrounding the projected image of a scene + * \author Alexander Beels + * \date 2011-2-5 + */ #include "GridDensityProvider.h" -class ArbitraryGridDensityProvider : public GridDensityProvider { +class ArbitraryGridDensityProvider : public GridDensityProvider +{ // Disallow copying and assignment - ArbitraryGridDensityProvider (const ArbitraryGridDensityProvider& other); - ArbitraryGridDensityProvider& operator= (const ArbitraryGridDensityProvider& other); + ArbitraryGridDensityProvider(const ArbitraryGridDensityProvider& other); + ArbitraryGridDensityProvider& operator=(const ArbitraryGridDensityProvider& other); public: ArbitraryGridDensityProvider(OccluderSource& source, const real proscenium[4], unsigned numCells); - ArbitraryGridDensityProvider(OccluderSource& source, const BBox& bbox, const GridHelpers::Transform& transform, unsigned numCells); + ArbitraryGridDensityProvider(OccluderSource& source, const BBox& bbox, + const GridHelpers::Transform& transform, unsigned numCells); ArbitraryGridDensityProvider(OccluderSource& source, unsigned numCells); - virtual ~ArbitraryGridDensityProvider (); + virtual ~ArbitraryGridDensityProvider(); protected: unsigned numCells; @@ -51,17 +57,19 @@ private: void initialize (const real proscenium[4]); }; -class ArbitraryGridDensityProviderFactory : public GridDensityProviderFactory { +class ArbitraryGridDensityProviderFactory : public GridDensityProviderFactory +{ public: ArbitraryGridDensityProviderFactory(unsigned numCells); - ~ArbitraryGridDensityProviderFactory (); + ~ArbitraryGridDensityProviderFactory(); auto_ptr newGridDensityProvider(OccluderSource& source, const real proscenium[4]); - auto_ptr newGridDensityProvider(OccluderSource& source, const BBox& bbox, const GridHelpers::Transform& transform); + auto_ptr newGridDensityProvider(OccluderSource& source, const BBox& bbox, + const GridHelpers::Transform& transform); auto_ptr newGridDensityProvider(OccluderSource& source); + protected: unsigned numCells; }; -#endif // ARBITRARYGRIDDENSITYPROVIDER_H - +#endif // __FREESTYLE_ARBITRARY_GRID_DENSITY_PROVIDER_H__ diff --git a/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.cpp b/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.cpp index 8b4c60a7fea..4832d08f2bc 100644 --- a/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.cpp +++ b/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.cpp @@ -1,69 +1,75 @@ -// -// Filename : AverageAreaGridDensityProvider.cpp -// Author(s) : Alexander Beels -// Purpose : Class to define a cell grid surrounding -// the projected image of a scene -// Date of creation : 2011-2-9 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.cpp + * \ingroup freestyle + * \brief Class to define a cell grid surrounding the projected image of a scene + * \author Alexander Beels + * \date 2011-2-9 + */ #include "AverageAreaGridDensityProvider.h" -AverageAreaGridDensityProvider::AverageAreaGridDensityProvider(OccluderSource& source, const real proscenium[4], real sizeFactor) - : GridDensityProvider(source) +AverageAreaGridDensityProvider::AverageAreaGridDensityProvider(OccluderSource& source, const real proscenium[4], + real sizeFactor) +: GridDensityProvider(source) { initialize (proscenium, sizeFactor); } -AverageAreaGridDensityProvider::AverageAreaGridDensityProvider(OccluderSource& source, const BBox& bbox, const GridHelpers::Transform& transform, real sizeFactor) - : GridDensityProvider(source) +AverageAreaGridDensityProvider::AverageAreaGridDensityProvider(OccluderSource& source, const BBox& bbox, + const GridHelpers::Transform& transform, real sizeFactor) +: GridDensityProvider(source) { 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); - initialize (proscenium, sizeFactor); + initialize(proscenium, sizeFactor); } -AverageAreaGridDensityProvider::~AverageAreaGridDensityProvider () {} +AverageAreaGridDensityProvider::~AverageAreaGridDensityProvider() {} -void AverageAreaGridDensityProvider::initialize (const real proscenium[4], real sizeFactor) +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() ) { + for (source.begin(); source.isValid(); source.next()) { Polygon3r& poly(source.getGridSpacePolygon()); Vec3r min, max; poly.getBBox(min, max); @@ -82,11 +88,11 @@ void AverageAreaGridDensityProvider::initialize (const real proscenium[4], real 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) ) { + float safetyZone = 0.1f; + if (_cellsX * _cellSize < prosceniumWidth * (1.0 + safetyZone)) { _cellsX = prosceniumWidth * (1.0 + safetyZone) / _cellSize; } - if ( _cellsY * _cellSize < prosceniumHeight * (1.0 + safetyZone) ) { + if (_cellsY * _cellSize < prosceniumHeight * (1.0 + safetyZone)) { _cellsY = prosceniumHeight * (1.0 + safetyZone) / _cellSize; } cout << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square." << endl; @@ -97,24 +103,26 @@ void AverageAreaGridDensityProvider::initialize (const real proscenium[4], real } AverageAreaGridDensityProviderFactory::AverageAreaGridDensityProviderFactory(real sizeFactor) - : sizeFactor(sizeFactor) +: sizeFactor(sizeFactor) { } -AverageAreaGridDensityProviderFactory::~AverageAreaGridDensityProviderFactory () {} +AverageAreaGridDensityProviderFactory::~AverageAreaGridDensityProviderFactory() {} -auto_ptr AverageAreaGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const real proscenium[4]) +auto_ptr +AverageAreaGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const real proscenium[4]) { return auto_ptr(new AverageAreaGridDensityProvider(source, proscenium, sizeFactor)); } -auto_ptr AverageAreaGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const BBox& bbox, const GridHelpers::Transform& transform) +auto_ptr +AverageAreaGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const BBox& bbox, + const GridHelpers::Transform& transform) { return auto_ptr(new AverageAreaGridDensityProvider(source, bbox, transform, sizeFactor)); } -auto_ptr AverageAreaGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source) +auto_ptr AverageAreaGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source) { return auto_ptr(new AverageAreaGridDensityProvider(source, sizeFactor)); } - diff --git a/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.h b/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.h index 73d28f006a7..05d2ae1ed9d 100644 --- a/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.h +++ b/source/blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.h @@ -1,67 +1,72 @@ -// -// Filename : AverageAreaGridDensityProvider.h -// Author(s) : Alexander Beels -// Purpose : Class to define a cell grid surrounding -// the projected image of a scene -// Date of creation : 2011-2-9 -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef __FREESTYLE_AVERAGE_AREA_GRID_DENSITY_PROVIDER_H__ +#define __FREESTYLE_AVERAGE_AREA_GRID_DENSITY_PROVIDER_H__ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef AVERAGEAREAGRIDDENSITYPROVIDER_H -#define AVERAGEAREAGRIDDENSITYPROVIDER_H +/** \file blender/freestyle/intern/view_map/AverageAreaGridDensityProvider.h + * \ingroup freestyle + * \brief Class to define a cell grid surrounding the projected image of a scene + * \author Alexander Beels + * \date 2011-2-9 + */ #include "GridDensityProvider.h" -class AverageAreaGridDensityProvider : public GridDensityProvider { +class AverageAreaGridDensityProvider : public GridDensityProvider +{ // Disallow copying and assignment - AverageAreaGridDensityProvider (const AverageAreaGridDensityProvider& other); - AverageAreaGridDensityProvider& operator= (const AverageAreaGridDensityProvider& other); + AverageAreaGridDensityProvider(const AverageAreaGridDensityProvider& other); + AverageAreaGridDensityProvider& operator=(const AverageAreaGridDensityProvider& other); public: AverageAreaGridDensityProvider(OccluderSource& source, const real proscenium[4], real sizeFactor); - AverageAreaGridDensityProvider(OccluderSource& source, const BBox& bbox, const GridHelpers::Transform& transform, real sizeFactor); + AverageAreaGridDensityProvider(OccluderSource& source, const BBox& bbox, + const GridHelpers::Transform& transform, real sizeFactor); AverageAreaGridDensityProvider(OccluderSource& source, real sizeFactor); - virtual ~AverageAreaGridDensityProvider (); - -protected: + virtual ~AverageAreaGridDensityProvider(); private: - void initialize (const real proscenium[4], real sizeFactor); + void initialize (const real proscenium[4], real sizeFactor); }; -class AverageAreaGridDensityProviderFactory : public GridDensityProviderFactory { +class AverageAreaGridDensityProviderFactory : public GridDensityProviderFactory +{ public: AverageAreaGridDensityProviderFactory(real sizeFactor); - ~AverageAreaGridDensityProviderFactory (); + ~AverageAreaGridDensityProviderFactory(); auto_ptr newGridDensityProvider(OccluderSource& source, const real proscenium[4]); - auto_ptr newGridDensityProvider(OccluderSource& source, const BBox& bbox, const GridHelpers::Transform& transform); + auto_ptr newGridDensityProvider(OccluderSource& source, const BBox& bbox, + const GridHelpers::Transform& transform); auto_ptr newGridDensityProvider(OccluderSource& source); protected: real sizeFactor; }; -#endif // AVERAGEAREAGRIDDENSITYPROVIDER_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 757cf7b6559..6b2804b17ce 100644 --- a/source/blender/freestyle/intern/view_map/BoxGrid.cpp +++ b/source/blender/freestyle/intern/view_map/BoxGrid.cpp @@ -1,36 +1,41 @@ -// -// Filename : BoxGrid.cpp -// Author(s) : Alexander Beels -// Purpose : Class to define a cell grid surrounding -// the projected image of a scene -// Date of creation : 2011-1-29 -// -/////////////////////////////////////////////////////////////////////////////// - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/freestyle/intern/view_map/BoxGrid.cpp + * \ingroup freestyle + * \brief Class to define a cell grid surrounding the projected image of a scene + * \author Alexander Beels + * \date 2011-1-29 + */ -#include "BoxGrid.h" - -#include #include +#include + +#include "BoxGrid.h" using namespace std; @@ -42,11 +47,12 @@ using namespace std; // 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) { +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; @@ -54,11 +60,13 @@ void BoxGrid::Cell::setDimensions(real x, real y, real sizeX, real sizeY) { 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; } -void BoxGrid::Cell::indexPolygons() { +void BoxGrid::Cell::indexPolygons() +{ // Sort occluders by their shallowest points. sort(faces.begin(), faces.end(), compareOccludersByShallowestPoint); } @@ -66,47 +74,49 @@ void BoxGrid::Cell::indexPolygons() { // Iterator ////////////////// -BoxGrid::Iterator::Iterator (BoxGrid& grid, Vec3r& center, real epsilon) - : _target(grid.transform(center)), - _foundOccludee(false) +BoxGrid::Iterator::Iterator (BoxGrid& grid, Vec3r& center, real epsilon) +: _target(grid.transform(center)), _foundOccludee(false) { // Find target cell _cell = grid.findCell(_target); - #if boxgridlogging == 1 - 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 BOX_GRID_LOGGING + 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(); } -BoxGrid::Iterator::~Iterator () {} +BoxGrid::Iterator::~Iterator() {} // BoxGrid ///////////////// -BoxGrid::BoxGrid(OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap, Vec3r& viewpoint, bool enableQI) - : _viewpoint(viewpoint), - _enableQI(enableQI) +BoxGrid::BoxGrid(OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap, Vec3r& viewpoint, + bool enableQI) +: _viewpoint(viewpoint), _enableQI(enableQI) { - cout << "Generate Cell structure" << endl; // Generate Cell structure + cout << "Generate Cell structure" << endl; assignCells(source, density, viewMap); - cout << "Distribute occluders" << endl; + // Fill Cells + cout << "Distribute occluders" << endl; distributePolygons(source); - cout << "Reorganize cells" << endl; + // Reorganize Cells + cout << "Reorganize cells" << endl; reorganizeCells(); + cout << "Ready to use BoxGrid" << endl; } -BoxGrid::~BoxGrid () { -} +BoxGrid::~BoxGrid() {} -void BoxGrid::assignCells (OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap) { +void BoxGrid::assignCells (OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap) +{ _cellSize = density.cellSize(); _cellsX = density.cellsX(); _cellsY = density.cellsY(); @@ -115,20 +125,19 @@ void BoxGrid::assignCells (OccluderSource& source, GridDensityProvider& density, // 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 ) { + 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() ) { + for (ViewMap::fedges_container::iterator f = fedges.begin(), fend = fedges.end(); f != fend; ++f) { + if ((*f)->isInImage()) { Vec3r point = transform((*f)->center3d()); - unsigned i, j; + unsigned int i, j; getCellCoordinates(point, i, j); - if ( _cells[i * _cellsY + j] == NULL ) { + if (_cells[i * _cellsY + j] == NULL) { // This is an uninitialized cell - real x, y, width, height; x = _cellOrigin[0] + _cellSize * i; @@ -145,19 +154,21 @@ void BoxGrid::assignCells (OccluderSource& source, GridDensityProvider& density, } } -void BoxGrid::distributePolygons (OccluderSource& source) { +void BoxGrid::distributePolygons(OccluderSource& source) +{ unsigned long nFaces = 0; unsigned long nKeptFaces = 0; - for ( source.begin(); source.isValid(); source.next() ) { - OccluderData* occluder = NULL; + for (source.begin(); source.isValid(); source.next()) { + OccluderData *occluder = NULL; try { - if ( insertOccluder(source, occluder) ) { + if (insertOccluder(source, occluder)) { _faces.push_back(occluder); ++nKeptFaces; } - } catch (...) { + } + 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 @@ -170,41 +181,47 @@ void BoxGrid::distributePolygons (OccluderSource& source) { cout << "Distributed " << nFaces << " occluders. Retained " << nKeptFaces << "." << endl; } -void BoxGrid::reorganizeCells () { +void BoxGrid::reorganizeCells() +{ // Sort the occluders by shallowest point - for ( vector::iterator i = _cells.begin(), end = _cells.end(); i != end; ++i ) { - if ( *i != NULL ) { + for (vector::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)); } -BoxGrid::Cell* BoxGrid::findCell(const Vec3r& point) { - unsigned x, y; +BoxGrid::Cell* BoxGrid::findCell(const Vec3r& point) +{ + unsigned int x, y; getCellCoordinates(point, x, y); return _cells[x * _cellsY + y]; } -bool BoxGrid::orthographicProjection () const { +bool BoxGrid::orthographicProjection() const +{ return true; } -const Vec3r& BoxGrid::viewpoint() const { +const Vec3r& BoxGrid::viewpoint() const +{ return _viewpoint; } -bool BoxGrid::enableQI() const { +bool BoxGrid::enableQI() const +{ 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]); } - diff --git a/source/blender/freestyle/intern/view_map/BoxGrid.h b/source/blender/freestyle/intern/view_map/BoxGrid.h index 43de8d713d5..9c8875865ef 100644 --- a/source/blender/freestyle/intern/view_map/BoxGrid.h +++ b/source/blender/freestyle/intern/view_map/BoxGrid.h @@ -1,78 +1,87 @@ -// -// Filename : BoxGrid.h -// Author(s) : Alexander Beels -// Purpose : Class to define a cell grid surrounding -// the projected image of a scene -// Date of creation : 2011-1-29 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef BOXGRID_H -#define BOXGRID_H - -#define boxgridlogging 0 +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_BOX_GRID_H__ +#define __FREESTYLE_BOX_GRID_H__ + +/** \file blender/freestyle/intern/view_map/BoxGrid.h + * \ingroup freestyle + * \brief Class to define a cell grid surrounding the projected image of a scene + * \author Alexander Beels + * \date 2011-1-29 + */ + +#define BOX_GRID_LOGGING FALSE // I would like to avoid using deque because including ViewMap.h and or -// separately results in redefinitions of identifiers. ViewMap.h already includes +// separately results in redefinitions of identifiers. ViewMap.h already includes // so it should be a safe fall-back. //#include //#include + +#include "GridDensityProvider.h" +#include "OccluderSource.h" #include "ViewMap.h" -#include "../winged_edge/WEdge.h" -#include "../geometry/Polygon.h" -#include "../system/PointerSequence.h" + #include "../geometry/BBox.h" #include "../geometry/GridHelpers.h" -#include "OccluderSource.h" -#include "GridDensityProvider.h" +#include "../geometry/Polygon.h" + +#include "../system/PointerSequence.h" + +#include "../winged_edge/WEdge.h" class BoxGrid { public: // Helper classes - struct OccluderData { - explicit OccluderData (OccluderSource& source, Polygon3r& p); + 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. + // 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; }; private: - struct Cell { + struct Cell + { // Can't store Cell in a vector without copy and assign - //Cell(const Cell& other); - //Cell& operator= (const Cell& other); + // Cell(const Cell& other); + // Cell& operator=(const Cell& other); - explicit Cell (); - ~Cell (); + explicit Cell(); + ~Cell(); - static bool compareOccludersByShallowestPoint (const OccluderData* a, const OccluderData* b); + 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); @@ -84,43 +93,37 @@ private: }; 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 { + /* 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=1e-06); - ~Iterator (); - void initBeforeTarget (); - void initAfterTarget (); - void nextOccluder (); - void nextOccludee (); + 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(); + WFace *getWFace() const; + Polygon3r *getCameraSpacePolygon(); void reportDepth(Vec3r origin, Vec3r u, real t); + private: bool testOccluder(bool wantOccludee); void markCurrentOccludeeCandidate(real depth); - Cell* _cell; + Cell *_cell; Vec3r _target; bool _foundOccludee; real _occludeeDepth; @@ -128,37 +131,39 @@ public: vector::iterator _current, _occludeeCandidate; }; - class Transform : public GridHelpers::Transform { + class Transform : public GridHelpers::Transform + { public: - explicit Transform (); - explicit Transform (Transform& other); - Vec3r operator() (const Vec3r& point) const; + 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); + BoxGrid& operator=(const BoxGrid& other); + public: - explicit BoxGrid (OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap, Vec3r& viewpoint, bool enableQI); + 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 + // 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); + Cell *findCell(const Vec3r& point); // Accessors: bool orthographicProjection() const; const Vec3r& viewpoint() const; - bool enableQI() const; + bool enableQI() const; Transform transform; private: @@ -176,51 +181,52 @@ private: bool _enableQI; }; -inline void BoxGrid::Iterator::initBeforeTarget () { +inline void BoxGrid::Iterator::initBeforeTarget() +{ _current = _cell->faces.begin(); - while ( _current != _cell->faces.end() && ! testOccluder(false) ) { + while (_current != _cell->faces.end() && !testOccluder(false)) { ++_current; } } -inline void BoxGrid::Iterator::initAfterTarget () { - if ( _foundOccludee ) { - #if boxgridlogging == 1 +inline void BoxGrid::Iterator::initAfterTarget() +{ + if (_foundOccludee) { + #if BOX_GRID_LOGGING std::cout << "\tStarting occludee search from occludeeCandidate at depth " << _occludeeDepth << std::endl; #endif _current = _occludeeCandidate; return; } - #if boxgridlogging == 1 + #if BOX_GRID_LOGGING std::cout << "\tStarting occludee search from current position" << std::endl; #endif - while ( _current != _cell->faces.end() && ! testOccluder(true) ) { + while (_current != _cell->faces.end() && !testOccluder(true)) { ++_current; } } -inline bool BoxGrid::Iterator::testOccluder (bool wantOccludee) { +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. + 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 boxgridlogging == 1 + #if BOX_GRID_LOGGING std::cout << "\tTesting occluder " << (*_current)->poly.getVertices()[0]; - for ( unsigned i = 1; i < (*_current)->poly.getVertices().size(); ++i ) { + 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 boxgridlogging == 1 + if (_foundOccludee && (*_current)->shallowest > _occludeeDepth) { + #if BOX_GRID_LOGGING std::cout << "\t\tAborting: shallowest > occludeeCandidate->deepest" << std::endl; #endif _current = _cell->faces.end(); @@ -230,16 +236,17 @@ inline bool BoxGrid::Iterator::testOccluder (bool wantOccludee) { } // Specific continue or stop conditions when searching for each type - if ( wantOccludee ) { - if ( (*_current)->deepest < _target[2] ) { - #if boxgridlogging == 1 + if (wantOccludee) { + if ((*_current)->deepest < _target[2]) { + #if BOX_GRID_LOGGING std::cout << "\t\tSkipping: shallower than target while looking for occludee" << std::endl; #endif return false; } - } else { - if ( (*_current)->shallowest > _target[2] ) { - #if boxgridlogging == 1 + } + else { + if ((*_current)->shallowest > _target[2]) { + #if BOX_GRID_LOGGING std::cout << "\t\tStopping: deeper than target while looking for occluder" << std::endl; #endif return true; @@ -251,67 +258,73 @@ inline bool BoxGrid::Iterator::testOccluder (bool wantOccludee) { // 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 boxgridlogging == 1 + if (_target[0] < bbMin[0] || _target[0] > bbMax[0] || _target[1] < bbMin[1] || _target[1] > bbMax[1]) { + #if BOX_GRID_LOGGING std::cout << "\t\tSkipping: bounding box violation" << std::endl; #endif return false; } // We've done all the corner cutting we can. - // Let the caller work out whether or not - // the geometry is correct. + // 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) { +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]; - #if boxgridlogging == 1 + #if BOX_GRID_LOGGING std::cout << "\t\tReporting depth of occluder/ee: " << depth; #endif - if ( depth > _target[2] ) { - #if boxgridlogging == 1 + if (depth > _target[2]) { + #if BOX_GRID_LOGGING 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 ) { + if (! _foundOccludee || _occludeeDepth > depth) { markCurrentOccludeeCandidate(depth); - } - } else { - #if boxgridlogging == 1 + } + } + else { + #if BOX_GRID_LOGGING std::cout << std::endl; #endif } } -inline void BoxGrid::Iterator::nextOccluder () { - if ( _current != _cell->faces.end() ) { +inline void BoxGrid::Iterator::nextOccluder() +{ + if (_current != _cell->faces.end()) { do { ++_current; - } while ( _current != _cell->faces.end() && ! testOccluder(false) ); + } while (_current != _cell->faces.end() && ! testOccluder(false)); } } -inline void BoxGrid::Iterator::nextOccludee () { - if ( _current != _cell->faces.end() ) { +inline void BoxGrid::Iterator::nextOccludee() +{ + if (_current != _cell->faces.end()) { do { ++_current; - } while ( _current != _cell->faces.end() && ! testOccluder(true) ); + } while (_current != _cell->faces.end() && ! testOccluder(true)); } } -inline bool BoxGrid::Iterator::validBeforeTarget () { +inline bool BoxGrid::Iterator::validBeforeTarget() +{ return _current != _cell->faces.end() && (*_current)->shallowest <= _target[2]; } -inline bool BoxGrid::Iterator::validAfterTarget () { +inline bool BoxGrid::Iterator::validAfterTarget() +{ return _current != _cell->faces.end(); } -inline void BoxGrid::Iterator::markCurrentOccludeeCandidate(real depth) { - #if boxgridlogging == 1 +inline void BoxGrid::Iterator::markCurrentOccludeeCandidate(real depth) +{ + #if BOX_GRID_LOGGING std::cout << "\t\tFound occludeeCandidate at depth " << depth << std::endl; #endif _occludeeCandidate = _current; @@ -319,18 +332,20 @@ inline void BoxGrid::Iterator::markCurrentOccludeeCandidate(real depth) { _foundOccludee = true; } -inline WFace* BoxGrid::Iterator::getWFace() const { +inline WFace* BoxGrid::Iterator::getWFace() const +{ return (*_current)->face; } -inline Polygon3r* BoxGrid::Iterator::getCameraSpacePolygon() { +inline Polygon3r* BoxGrid::Iterator::getCameraSpacePolygon() +{ 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; @@ -339,9 +354,10 @@ inline BoxGrid::OccluderData::OccluderData (OccluderSource& source, Polygon3r& p deepest = max[2]; } -inline void BoxGrid::Cell::checkAndInsert(OccluderSource& source, Polygon3r& poly, OccluderData*& occluder) { - if ( GridHelpers::insideProscenium (boundary, poly) ) { - if ( occluder == NULL) { +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); @@ -350,7 +366,8 @@ inline void BoxGrid::Cell::checkAndInsert(OccluderSource& source, Polygon3r& pol } } -inline bool BoxGrid::insertOccluder(OccluderSource& source, OccluderData*& occluder) { +inline bool BoxGrid::insertOccluder(OccluderSource& source, OccluderData*& occluder) +{ Polygon3r& poly(source.getGridSpacePolygon()); occluder = NULL; @@ -361,9 +378,9 @@ inline bool BoxGrid::insertOccluder(OccluderSource& source, OccluderData*& occlu getCellCoordinates(bbMin, startX, startY); getCellCoordinates(bbMax, endX, endY); - for ( unsigned i = startX; i <= endX; ++i ) { - for ( unsigned j = startY; j <= endY; ++j ) { - if ( _cells[i * _cellsY + j] != NULL ) { + 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); } } @@ -372,5 +389,4 @@ inline bool BoxGrid::insertOccluder(OccluderSource& source, OccluderData*& occlu return occluder != NULL; } -#endif // BOXGRID_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 ea57da93347..0e01a70181a 100644 --- a/source/blender/freestyle/intern/view_map/CulledOccluderSource.cpp +++ b/source/blender/freestyle/intern/view_map/CulledOccluderSource.cpp @@ -1,67 +1,74 @@ -// -// Filename : CulledOccluderSource.h -// Author(s) : Alexander Beels -// Purpose : Class to define a cell grid surrounding -// the projected image of a scene -// Date of creation : 2010-12-21 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/freestyle/intern/view_map/CulledOccluderSource.cpp + * \ingroup freestyle + * \brief Class to define a cell grid surrounding the projected image of a scene + * \author Alexander Beels + * \date 2010-12-21 + */ #include "CulledOccluderSource.h" -#include "../geometry/GridHelpers.h" + #include "FRS_freestyle.h" -CulledOccluderSource::CulledOccluderSource (const GridHelpers::Transform& t, WingedEdge& we, ViewMap& viewMap, bool extensiveFEdgeSearch) - : OccluderSource(t, we), - rejected(0), - gridSpaceOccluderProsceniumInitialized(false) +#include "../geometry/GridHelpers.h" + +CulledOccluderSource::CulledOccluderSource(const GridHelpers::Transform& t, WingedEdge& we, ViewMap& viewMap, + bool extensiveFEdgeSearch) +: OccluderSource(t, we), rejected(0), gridSpaceOccluderProsceniumInitialized(false) { cullViewEdges(viewMap, extensiveFEdgeSearch); - // If we have not found any visible FEdges during our cull, then there is nothing - // to iterate over. Short-circuit everything. + // 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() ) { + if (valid && ! testCurrent()) { next(); } } -CulledOccluderSource::~CulledOccluderSource() { -} +CulledOccluderSource::~CulledOccluderSource() {} -bool CulledOccluderSource::testCurrent() { - if ( valid ) { +bool CulledOccluderSource::testCurrent() +{ + if (valid) { // The test for gridSpaceOccluderProsceniumInitialized should not be necessary - return gridSpaceOccluderProsceniumInitialized && GridHelpers::insideProscenium (gridSpaceOccluderProscenium, cachedPolygon); + return gridSpaceOccluderProsceniumInitialized && + GridHelpers::insideProscenium(gridSpaceOccluderProscenium, cachedPolygon); } return false; } -bool CulledOccluderSource::next() { - while ( OccluderSource::next() ) { - if ( testCurrent() ) { +bool CulledOccluderSource::next() +{ + while (OccluderSource::next()) { + if (testCurrent()) { ++rejected; return true; } @@ -70,17 +77,20 @@ bool CulledOccluderSource::next() { return false; } -void CulledOccluderSource::getOccluderProscenium(real proscenium[4]) { - for ( unsigned i = 0; i < 4; ++i ) { +void CulledOccluderSource::getOccluderProscenium(real proscenium[4]) +{ + 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])); } -static inline bool crossesProscenium(real proscenium[4], FEdge *fe) { +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()); @@ -89,20 +99,20 @@ static inline bool crossesProscenium(real proscenium[4], FEdge *fe) { return GeomUtils::intersect2dSeg2dArea (min, max, A, B); } -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] ); +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]); } -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. + // This avoids the complications of trying to delete edges from the ViewMap. - // Non-displayable view edges will be skipped over during - // visibility calculation. + // 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, + // 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 @@ -112,34 +122,30 @@ void CulledOccluderSource::cullViewEdges(ViewMap& viewMap, bool extensiveFEdgeSe prosceniumOrigin[0] = (viewProscenium[1] - viewProscenium[0]) / 2.0; prosceniumOrigin[1] = (viewProscenium[3] - viewProscenium[2]) / 2.0; cout << "Proscenium culling:" << endl; - cout << "Proscenium: [" << viewProscenium[0] << ", " << viewProscenium[1] << ", " << viewProscenium[2] << ", " << viewProscenium[3] << "]"<< 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 + // 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::iterator. Probably all occurences of vector::iterator - // should be replaced ViewMap::viewedges_container throughout the code. + // XXX Freestyle is inconsistent in its use of ViewMap::viewedges_container and vector::iterator. + // Probably all occurences of vector::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++) { + 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. + // 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 @@ -151,28 +157,27 @@ void CulledOccluderSource::cullViewEdges(ViewMap& viewMap, bool extensiveFEdgeSe // 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. + // 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()) ) { + // 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 { + } + else { real d = distance2D(fe->center2d(), prosceniumOrigin); // If center point is closer to viewport origin than current target - if ( bestOccluderTarget == NULL || d < bestOccluderDistance ) { + if (bestOccluderTarget == NULL || d < bestOccluderDistance) { // Then store as bestOccluderTarget bestOccluderDistance = d; bestOccluderTarget = fe; @@ -181,33 +186,35 @@ void CulledOccluderSource::cullViewEdges(ViewMap& viewMap, bool extensiveFEdgeSe } // If feature edge crosses the view proscenium - if ( ! (*ve)->isInImage() && crossesProscenium(viewProscenium, fe) ) { + 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() ) ); + } 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 ) { + 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 ) { + if ((*ve)->isInImage() && bestOccluderTarget != NULL && ! bestOccluderTargetFound) { // Expand occluder proscenium to enclose bestOccluderTarget Vec3r point = bestOccluderTarget->center2d(); - if ( point[0] < occluderProscenium[0] ) { + if (point[0] < occluderProscenium[0]) { occluderProscenium[0] = point[0]; - } else if ( point[0] > occluderProscenium[1] ) { + } + else if (point[0] > occluderProscenium[1]) { occluderProscenium[1] = point[0]; } - if ( point[1] < occluderProscenium[2] ) { + if (point[1] < occluderProscenium[2]) { occluderProscenium[2] = point[1]; - } else if ( point[1] > occluderProscenium[3] ) { + } + else if (point[1] > occluderProscenium[3]) { occluderProscenium[3] = point[1]; } // Use bestOccluderTarget for visibility determination @@ -225,22 +232,18 @@ void CulledOccluderSource::cullViewEdges(ViewMap& viewMap, bool extensiveFEdgeSe // 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 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() ) { + for (ve = viewMap.ViewEdges().begin(), veend = viewMap.ViewEdges().end(); ve != veend; ve++) { + if (!(*ve)->isInImage()) { continue; } // For each feature edge, @@ -248,30 +251,31 @@ void CulledOccluderSource::cullViewEdges(ViewMap& viewMap, bool extensiveFEdgeSe FEdge *fe = festart; do { // If not (already) visible and center point inside occluder proscenium, - if ( ! fe->isInImage() && insideProscenium(occluderProscenium, fe->center2d()) ) { + 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 ); + } 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. + // 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 { +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; } } - diff --git a/source/blender/freestyle/intern/view_map/CulledOccluderSource.h b/source/blender/freestyle/intern/view_map/CulledOccluderSource.h index 3c00d5e34ad..a9c5484ca9c 100644 --- a/source/blender/freestyle/intern/view_map/CulledOccluderSource.h +++ b/source/blender/freestyle/intern/view_map/CulledOccluderSource.h @@ -1,46 +1,52 @@ -// -// Filename : CulledOccluderSource.h -// Author(s) : Alexander Beels -// Purpose : Class to define a cell grid surrounding -// the projected image of a scene -// Date of creation : 2010-12-21 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef CULLEDOCCLUDERSOURCE_H -#define CULLEDOCCLUDERSOURCE_H +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_CULLED_OCCLUDER_SOURCE_H__ +#define __FREESTYLE_CULLED_OCCLUDER_SOURCE_H__ + +/** \file blender/freestyle/intern/view_map/CulledOccluderSource.h + * \ingroup freestyle + * \brief Class to define a cell grid surrounding the projected image of a scene + * \author Alexander Beels + * \date 2010-12-21 + */ #include "OccluderSource.h" #include "ViewMap.h" -class CulledOccluderSource : public OccluderSource { +class CulledOccluderSource : public OccluderSource +{ // Disallow copying and assignment - CulledOccluderSource (const CulledOccluderSource& other); - CulledOccluderSource& operator= (const CulledOccluderSource& other); + CulledOccluderSource(const CulledOccluderSource& other); + CulledOccluderSource& operator=(const CulledOccluderSource& other); public: - CulledOccluderSource (const GridHelpers::Transform& transform, WingedEdge& we, ViewMap& viewMap, bool extensiveFEdgeSearch = true); + CulledOccluderSource(const GridHelpers::Transform& transform, WingedEdge& we, ViewMap& viewMap, + bool extensiveFEdgeSearch = true); virtual ~CulledOccluderSource(); void cullViewEdges(ViewMap& viewMap, bool extensiveFEdgeSearch); @@ -51,7 +57,7 @@ public: private: bool testCurrent(); - void expandGridSpaceOccluderProscenium(FEdge* fe); + void expandGridSpaceOccluderProscenium(FEdge *fe); real occluderProscenium[4]; real gridSpaceOccluderProscenium[4]; @@ -60,4 +66,4 @@ private: bool gridSpaceOccluderProsceniumInitialized; }; -#endif // CULLEDOCCLUDERSOURCE_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 1d52f37236e..9631c93cd7e 100644 --- a/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp +++ b/source/blender/freestyle/intern/view_map/FEdgeXDetector.cpp @@ -1,767 +1,749 @@ - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/freestyle/intern/view_map/FEdgeXDetector.cpp + * \ingroup freestyle + * \brief Detects/flags/builds extended features edges on the WXEdge structure + * \author Stephane Grabli + * \date 26/10/2003 + */ + +#include +#include #include "FEdgeXDetector.h" -#include "float.h" + #include "../geometry/GeomUtils.h" -#include #include "../geometry/normal_cycle.h" -void FEdgeXDetector::processShapes(WingedEdge& we) { - bool progressBarDisplay = false; - Vec3r Min, Max; - vector 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::const_iterator it = wshapes.begin(); - it != wshapes.end(); - it++){ - if (_pRenderMonitor && _pRenderMonitor->testBreak()) - break; - wxs = dynamic_cast(*it); - wxs->bbox(Min, Max); - _bbox_diagonal = (Max-Min).norm(); - if(_changes){ - vector& wfaces = wxs->GetFaceList(); - for(vector::iterator wf=wfaces.begin(), wfend=wfaces.end(); - wf!=wfend; - ++wf){ - WXFace* wxf = dynamic_cast(*wf); - wxf->Clear(); - } - _computeViewIndependant = true; - } else if (!(wxs)->getComputeViewIndependantFlag()) { - wxs->Reset(); - _computeViewIndependant = false; - } else { - _computeViewIndependant = 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->setComputeViewIndependantFlag(false); - _computeViewIndependant = false; - _changes = false; - - // reset user data - (*it)->ResetUserData(); - } +void FEdgeXDetector::processShapes(WingedEdge& we) +{ + bool progressBarDisplay = false; + Vec3r Min, Max; + vector 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::const_iterator it = wshapes.begin(); it != wshapes.end(); it++) { + if (_pRenderMonitor && _pRenderMonitor->testBreak()) + break; + wxs = dynamic_cast(*it); + wxs->bbox(Min, Max); + _bbox_diagonal = (Max - Min).norm(); + if (_changes) { + vector& wfaces = wxs->GetFaceList(); + for (vector::iterator wf = wfaces.begin(), wfend = wfaces.end(); wf != wfend; ++wf) { + WXFace *wxf = dynamic_cast(*wf); + wxf->Clear(); + } + _computeViewIndependant = true; + } + else if (!(wxs)->getComputeViewIndependantFlag()) { + wxs->Reset(); + _computeViewIndependant = false; + } + else { + _computeViewIndependant = 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->setComputeViewIndependantFlag(false); + _computeViewIndependant = 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; - _meanEdgeSize = iWShape->getMeanEdgeSize(); - - vector& wfaces = iWShape->GetFaceList(); - vector::iterator f,fend; - // view dependant stuff - for(f=wfaces.begin(), fend=wfaces.end(); - f!=fend; - ++f){ - preProcessFace((WXFace*)(*f)); - } - - if(_computeRidgesAndValleys || _computeSuggestiveContours ) { - vector& wvertices = iWShape->getVertexList(); - for(vector::iterator wv=wvertices.begin(), wvend=wvertices.end(); - wv!=wvend; - ++wv){ - // Compute curvatures - WXVertex * wxv = dynamic_cast(*wv); - computeCurvatures(wxv); - } - _meanK1 /= (real)(_nPoints); - _meanKr /= (real)(_nPoints); - } +void FEdgeXDetector::preProcessShape(WXShape *iWShape) +{ + _meanK1 = 0; + _meanKr = 0; + _minK1 = FLT_MAX; + _maxK1 = -FLT_MAX; + _minKr = FLT_MAX; + _maxKr = -FLT_MAX; + _nPoints = 0; + _meanEdgeSize = iWShape->getMeanEdgeSize(); + + vector& wfaces = iWShape->GetFaceList(); + vector::iterator f, fend; + // view dependant stuff + for (f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) { + preProcessFace((WXFace*)(*f)); + } + + if (_computeRidgesAndValleys || _computeSuggestiveContours) { + vector& wvertices = iWShape->getVertexList(); + for (vector::iterator wv = wvertices.begin(), wvend = wvertices.end(); wv != wvend; ++wv) { + // Compute curvatures + WXVertex *wxv = dynamic_cast(*wv); + computeCurvatures(wxv); + } + _meanK1 /= (real)(_nPoints); + _meanKr /= (real)(_nPoints); + } } -void FEdgeXDetector::preProcessFace(WXFace *iFace){ - Vec3r firstPoint = iFace->GetVertex(0)->GetVertex(); - Vec3r N = iFace->GetNormal(); - - // Compute the dot product between V (=_Viewpoint - firstPoint) and N: - Vec3r V; - if (_orthographicProjection) { - V = Vec3r(0.0, 0.0, _Viewpoint.z() - firstPoint.z()); - } else { - V = Vec3r(_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 { - Vec3r dist_vec(iFace->center() - _Viewpoint); - iFace->setZ(dist_vec.norm()); - } +void FEdgeXDetector::preProcessFace(WXFace *iFace) +{ + Vec3r firstPoint = iFace->GetVertex(0)->GetVertex(); + Vec3r N = iFace->GetNormal(); + + // Compute the dot product between V (=_Viewpoint - firstPoint) and N: + Vec3r V; + if (_orthographicProjection) { + V = Vec3r(0.0, 0.0, _Viewpoint.z() - firstPoint.z()); + } + else { + V = Vec3r(_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 { + Vec3r dist_vec(iFace->center() - _Viewpoint); + iFace->setZ(dist_vec.norm()); + } } -void FEdgeXDetector::computeCurvatures(WXVertex *vertex){ - // 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 independant stuff - if(_computeViewIndependant){ - 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; +void FEdgeXDetector::computeCurvatures(WXVertex *vertex) +{ + // 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 independant stuff + if (_computeViewIndependant) { + 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& wfaces = iWShape->GetFaceList(); - vector::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::iterator we, weend; - vector &wedges = iWShape->getEdgeList(); - for(we=wedges.begin(), weend=wedges.end(); - we!=weend; - ++we) - { - ProcessSilhouetteEdge((WXEdge*)(*we)); - } +void FEdgeXDetector::processSilhouetteShape(WXShape *iWShape) +{ + // Make a first pass on every polygons in order to compute all their silhouette relative values: + vector& wfaces = iWShape->GetFaceList(); + vector::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::iterator we, weend; + vector &wedges = iWShape->getEdgeList(); + for (we = wedges.begin(), weend = wedges.end(); we != weend; ++we) { + ProcessSilhouetteEdge((WXEdge*)(*we)); + } } void FEdgeXDetector::ProcessSilhouetteFace(WXFace *iFace) { - - // SILHOUETTE LAYER - Vec3r normal; - // Compute the dot products between View direction and N at each vertex - // of the face: - Vec3r point; - int closestPointId = 0; - real dist, minDist = FLT_MAX; - int numVertices = iFace->numberOfVertices(); - WXFaceLayer * faceLayer = new WXFaceLayer(iFace, Nature::SILHOUETTE, true); - for(int i=0; iGetVertex(i)->GetVertex(); - normal = iFace->GetVertexNormal(i); - normal.normalize(); - Vec3r V; - if (_orthographicProjection) { - V = Vec3r(0.0, 0.0, _Viewpoint.z() - point.z()); - } else { - V = Vec3r(_Viewpoint - point); - } - V.normalize(); - real d = normal * V; - faceLayer->PushDotP(d); - // Find the point the closest to the viewpoint - if (_orthographicProjection) { - dist = point.z() - _Viewpoint.z(); - } else { - Vec3r 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 + Vec3r normal; + // Compute the dot products between View direction and N at each vertex of the face: + Vec3r point; + int closestPointId = 0; + real 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(); + Vec3r V; + if (_orthographicProjection) { + V = Vec3r(0.0, 0.0, _Viewpoint.z() - point.z()); + } + else { + V = Vec3r(_Viewpoint - point); + } + V.normalize(); + real d = normal * V; + faceLayer->PushDotP(d); + // Find the point the closest to the viewpoint + if (_orthographicProjection) { + dist = point.z() - _Viewpoint.z(); + } + else { + Vec3r 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(!_computeViewIndependant) - return; - // Make a pass on the edges to detect - // the BORDER - // -------------------- - vector::iterator we, weend; - vector &wedges = iWShape->getEdgeList(); - for(we=wedges.begin(), weend=wedges.end(); - we!=weend; - ++we){ - ProcessBorderEdge((WXEdge*)(*we)); - } +void FEdgeXDetector::processBorderShape(WXShape *iWShape) +{ + if (!_computeViewIndependant) + return; + // Make a pass on the edges to detect the BORDER + vector::iterator we, weend; + vector &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(!_computeViewIndependant) - return; - - // Make a pass on the edges to detect - // the CREASE - // -------------------- - vector::iterator we, weend; - vector &wedges = iWShape->getEdgeList(); - for(we=wedges.begin(), weend=wedges.end(); - we!=weend; - ++we){ - ProcessCreaseEdge((WXEdge*)(*we)); - } +void FEdgeXDetector::processCreaseShape(WXShape *iWShape) +{ + if (!_computeViewIndependant) + return; + + // Make a pass on the edges to detect the CREASE + vector::iterator we, weend; + vector &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); -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((!_computeViewIndependant)) - return; - - // Here the curvatures must already have been computed - vector& wfaces = iWShape->GetFaceList(); - vector::iterator f, fend; - for(f=wfaces.begin(), fend=wfaces.end(); - f!=fend; - ++f) - { - ProcessRidgeFace((WXFace*)(*f)); - } + if (!_computeViewIndependant) + return; + + // Here the curvatures must already have been computed + vector& wfaces = iWShape->GetFaceList(); + vector::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; iGetVertex(i); - WXVertex * wxv = dynamic_cast(wv); - flayer->PushDotP(wxv->curvatures()->K1); - } - - 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(wv); + flayer->PushDotP(wxv->curvatures()->K1); + } + + 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); + } + } } -// 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 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; iGetVertex(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(*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.e-06); -// if((res == GeomUtils::DO_INTERSECT) && (t>=0.0) && (t<=1.0)){ -// vector 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 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)); - -// // 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); -// // } -// } +#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 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(*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 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 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 // SUGGESTIVE CONTOURS ////////////////////// -void FEdgeXDetector::processSuggestiveContourShape(WXShape* iWShape) { - - // Here the curvatures must already have been computed - vector& wfaces = iWShape->GetFaceList(); - vector::iterator f, fend; - for(f=wfaces.begin(), fend=wfaces.end(); - f!=fend; - ++f) - { - ProcessSuggestiveContourFace((WXFace*)(*f)); - } +void FEdgeXDetector::processSuggestiveContourShape(WXShape *iWShape) +{ + // Here the curvatures must already have been computed + vector& wfaces = iWShape->GetFaceList(); + vector::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; iGetVertex(i); - WXVertex * wxv = dynamic_cast(wv); - faceLayer->PushDotP(wxv->curvatures()->Kr); - } - - // 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(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& wfaces = iShape->GetFaceList(); - vector::iterator f, fend; - for(f=wfaces.begin(), fend=wfaces.end(); - f!=fend; - ++f) - { - postProcessSuggestiveContourFace((WXFace*)(*f)); - } +void FEdgeXDetector::postProcessSuggestiveContourShape(WXShape *iShape) +{ + vector& wfaces = iShape->GetFaceList(); + vector::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 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 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 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(*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 wether 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.e-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(); +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 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 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(*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 wether 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(!_computeViewIndependant) - return; - // Make a pass on the edges to detect material boundaries - vector::iterator we, weend; - vector &wedges = iWShape->getEdgeList(); - for(we=wedges.begin(), weend=wedges.end(); - we!=weend; - ++we){ - ProcessMaterialBoundaryEdge((WXEdge*)(*we)); - } +void FEdgeXDetector::processMaterialBoundaryShape(WXShape *iWShape) +{ + if (!_computeViewIndependant) + return; + // Make a pass on the edges to detect material boundaries + vector::iterator we, weend; + vector &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::iterator we, weend; - vector &wedges = iShape->getEdgeList(); - for(we=wedges.begin(), weend=wedges.end(); - we!=weend; - ++we){ - ProcessEdgeMarks((WXEdge*)(*we)); - } +void FEdgeXDetector::processEdgeMarksShape(WXShape *iShape) +{ + // Make a pass on the edges to detect material boundaries + vector::iterator we, weend; + vector &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); - } +void FEdgeXDetector::ProcessEdgeMarks(WXEdge *iEdge) +{ + 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& wfaces = iShape->GetFaceList(); - for(vector::iterator f=wfaces.begin(), fend=wfaces.end(); - f!=fend; - ++f) - { - vector& faceLayers = ((WXFace*)(*f))->getSmoothLayers(); - for(vector::iterator wxfl = faceLayers.begin(), wxflend=faceLayers.end(); - wxfl!=wxflend; - ++wxfl){ - if ((*wxfl)->BuildSmoothEdge()) - hasSmoothEdges = true; - } - } - - if (hasSmoothEdges && !_computeRidgesAndValleys && !_computeSuggestiveContours) { - vector& wvertices = iShape->getVertexList(); - for(vector::iterator wv=wvertices.begin(), wvend=wvertices.end(); - wv!=wvend; - ++wv){ - // Compute curvatures - WXVertex * wxv = dynamic_cast(*wv); - computeCurvatures(wxv); - } - _meanK1 /= (real)(_nPoints); - _meanKr /= (real)(_nPoints); - } +void FEdgeXDetector::buildSmoothEdges(WXShape *iShape) +{ + bool hasSmoothEdges = false; + + // Make a last pass to build smooth edges from the previous stored values: + //-------------------------------------------------------------------------- + vector& wfaces = iShape->GetFaceList(); + for (vector::iterator f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) { + vector& faceLayers = ((WXFace*)(*f))->getSmoothLayers(); + for (vector::iterator wxfl = faceLayers.begin(), wxflend = faceLayers.end(); + wxfl != wxflend; + ++wxfl) + { + if ((*wxfl)->BuildSmoothEdge()) + hasSmoothEdges = true; + } + } + + if (hasSmoothEdges && !_computeRidgesAndValleys && !_computeSuggestiveContours) { + vector& wvertices = iShape->getVertexList(); + for (vector::iterator wv = wvertices.begin(), wvend = wvertices.end(); wv != wvend; ++wv) { + // Compute curvatures + WXVertex *wxv = dynamic_cast(*wv); + computeCurvatures(wxv); + } + _meanK1 /= (real)(_nPoints); + _meanKr /= (real)(_nPoints); + } } diff --git a/source/blender/freestyle/intern/view_map/FEdgeXDetector.h b/source/blender/freestyle/intern/view_map/FEdgeXDetector.h index 2fd6a4a1e8f..1b211264402 100644 --- a/source/blender/freestyle/intern/view_map/FEdgeXDetector.h +++ b/source/blender/freestyle/intern/view_map/FEdgeXDetector.h @@ -1,203 +1,241 @@ -// -// Filename : FEdgeXDetector.h -// Author(s) : Stephane Grabli -// Purpose : Detects/flags/builds extended features edges on the -// WXEdge structure -// Date of creation : 26/10/2003 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - - -#ifndef FEDGEXDETECTOR_H -# define FEDGEXDETECTOR_H - -# include -# include "../system/FreestyleConfig.h" -# include "../geometry/Geom.h" -# include "../winged_edge/WXEdge.h" -# include "../winged_edge/Curvature.h" -# include "../system/ProgressBar.h" -# include "../system/RenderMonitor.h" +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ -using namespace Geometry; +#ifndef __FREESTYLE_FEDGE_X_DETECTOR_H__ +#define __FREESTYLE_FEDGE_X_DETECTOR_H__ -/*! This class takes as input a WXEdge structure and fills it +/** \file blender/freestyle/intern/view_map/FEdgeXDetector.h + * \ingroup freestyle + * \brief Detects/flags/builds extended features edges on the WXEdge structure + * \author Stephane Grabli + * \date 26/10/2003 */ +#include + +#include "../geometry/Geom.h" + +#include "../system/FreestyleConfig.h" +#include "../system/ProgressBar.h" +#include "../system/RenderMonitor.h" + +#include "../winged_edge/Curvature.h" +#include "../winged_edge/WXEdge.h" + +using namespace Geometry; + +/*! This class takes as input a WXEdge structure and fills it */ class LIB_VIEW_MAP_EXPORT FEdgeXDetector { public: - - FEdgeXDetector() { - _pProgressBar = 0; - _pRenderMonitor = 0; - _computeViewIndependant = true; - _bbox_diagonal = 1.0; - _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. - */ - inline void setCreaseAngle(real 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(real 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 Vec3r& 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(real r) { - if(r!=_sphereRadius){ - _sphereRadius = r; - _changes=true; - } - } - - inline void setProgressBar(ProgressBar *iProgressBar) {_pProgressBar = iProgressBar;} - - inline void setRenderMonitor(RenderMonitor *iRenderMonitor) {_pRenderMonitor = iRenderMonitor;} + FEdgeXDetector() + { + _pProgressBar = NULL; + _pRenderMonitor = NULL; + _computeViewIndependant = true; + _bbox_diagonal = 1.0; + _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(real 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(real 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 Vec3r& 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(real r) + { + if (r != _sphereRadius) { + _sphereRadius = r; + _changes=true; + } + } + + inline void setProgressBar(ProgressBar *iProgressBar) + { + _pProgressBar = iProgressBar; + } + + inline void setRenderMonitor(RenderMonitor *iRenderMonitor) + { + _pRenderMonitor = iRenderMonitor; + } protected: - - Vec3r _Viewpoint; - real _bbox_diagonal; // diagonal of the current processed shape bbox - //oldtmp values - bool _computeViewIndependant; - 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; - real _sphereRadius; // expressed as a ratio of the mean edge size - real _creaseAngle; // [-1, 1] compared with the inner product of face normals - bool _changes; - - real _kr_derivative_epsilon; - - ProgressBar *_pProgressBar; - RenderMonitor *_pRenderMonitor; + Vec3r _Viewpoint; + real _bbox_diagonal; // diagonal of the current processed shape bbox + //oldtmp values + bool _computeViewIndependant; + 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; + real _sphereRadius; // expressed as a ratio of the mean edge size + real _creaseAngle; // [-1, 1] compared with the inner product of face normals + bool _changes; + + real _kr_derivative_epsilon; + + ProgressBar *_pProgressBar; + RenderMonitor *_pRenderMonitor; }; -#endif // FEDGEDXETECTOR_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 a9f997e66b0..b6821afcb93 100644 --- a/source/blender/freestyle/intern/view_map/Functions0D.cpp +++ b/source/blender/freestyle/intern/view_map/Functions0D.cpp @@ -1,357 +1,371 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/** \file blender/freestyle/intern/view_map/Functions0D.cpp + * \ingroup freestyle + * \brief Functions taking 0D input + * \author Stephane Grabli + * \author Emmanuel Turquin + * \date 01/07/2003 + */ -# include "Functions0D.h" -# include "ViewMap.h" +#include "Functions0D.h" +#include "ViewMap.h" using namespace std; namespace Functions0D { - // Internal function - FEdge* getFEdge(Interface0D& it1, Interface0D& it2){ - return it1.getFEdge(it2); - } +// Internal function +FEdge *getFEdge(Interface0D& it1, Interface0D& it2) +{ + return it1.getFEdge(it2); +} - 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 = 0; - } - 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 = 0; - } - else if(last) - { - fe1 = previous->getFEdge(*it); - fe2 = 0; - } - else - { - fe1 = previous->getFEdge(*it); - fe2 = it->getFEdge(*next); - } - } - } +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); + } + } +} - void getViewEdges(Interface0DIterator &it, - ViewEdge *&ve1, - ViewEdge *&ve2) - { - FEdge * fe1, *fe2; - getFEdges(it, fe1, fe2); - ve1 = fe1->viewedge(); - if(fe2 != 0) - { - ve2 = fe2->viewedge(); - if(ve2 == ve1) - ve2 = 0; - } - else - ve2 = 0; - } +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; + } +} - ViewShape* getShapeF0D(Interface0DIterator& it) - { - ViewEdge *ve1, *ve2; - getViewEdges(it, ve1, ve2); - return ve1->viewShape(); - } +ViewShape *getShapeF0D(Interface0DIterator& it) +{ + ViewEdge *ve1, *ve2; + getViewEdges(it, ve1, ve2); + return ve1->viewShape(); +} - void getOccludersF0D(Interface0DIterator& it, set& oOccluders){ - ViewEdge * ve1, *ve2; - getViewEdges(it, ve1, ve2); - occluder_container::const_iterator oit = ve1->occluders_begin(); - occluder_container::const_iterator oitend = ve1->occluders_end(); +void getOccludersF0D(Interface0DIterator& it, set& 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)); + for (; oit != oitend; ++oit) + oOccluders.insert((*oit)); - if(ve2!=0){ - oit = ve2->occluders_begin(); - oitend = ve2->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){ - ViewEdge * ve1, *ve2; - getViewEdges(it, ve1, ve2); - ViewShape *aShape = ve1->aShape(); - return aShape; - } - - // - 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()); +ViewShape *getOccludeeF0D(Interface0DIterator& it) +{ + ViewEdge *ve1, *ve2; + getViewEdges(it, ve1, ve2); + ViewShape *aShape = ve1->aShape(); + return aShape; +} - 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 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()); - 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 - { + 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) +{ + 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()); + } + 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 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) { - Interface0DIterator tmp1 = iter, tmp2 = iter; - ++tmp2; - unsigned count = 1; - while((!tmp1.isBegin()) && (count < 3)) - { - --tmp1; - ++count; - } - while((!tmp2.isEnd()) && (count < 3)) - { +int Curvature2DAngleF0D::operator()(Interface0DIterator& iter) +{ + Interface0DIterator tmp1 = iter, tmp2 = iter; ++tmp2; - ++count; - } - if(count < 3) { - // if we only have 2 vertices - result = 0; - return 0; + 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; + 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); + 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) { - FEdge *fe1, *fe2; - getFEdges(iter, fe1, fe2); - result = fe1->z_discontinuity(); - if(fe2!=0){ - result += fe2->z_discontinuity(); - result /= 2.f; - } - return 0; - } +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; +} - 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 != 0) - { - Vec3f e2(fe2->orientation2d()); - Vec2f n2(e2[1], -e2[0]); - n += n2; - } - n.normalize(); - result = n; +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; - } +} - int MaterialF0D::operator()(Interface0DIterator& iter) { - FEdge *fe1, *fe2; - getFEdges(iter,fe1,fe2); - if(fe1 == 0) - return -1; - if(fe1->isSmooth()) - result = ((FEdgeSmooth*)fe1)->frs_material(); - else - result = ((FEdgeSharp*)fe1)->bFrsMaterial(); - // const SShape * sshape = getShapeF0D(iter); - // return sshape->material(); - return 0; - } +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(); +#if 0 + const SShape *sshape = getShapeF0D(iter); + return sshape->material(); +#endif + return 0; +} - int ShapeIdF0D::operator()(Interface0DIterator& iter) { - ViewShape * vshape = getShapeF0D(iter); - result = vshape->getId(); +int ShapeIdF0D::operator()(Interface0DIterator& iter) +{ + ViewShape *vshape = getShapeF0D(iter); + result = vshape->getId(); return 0; - } +} - int QuantitativeInvisibilityF0D::operator()(Interface0DIterator& iter) { - ViewEdge * ve1, *ve2; - getViewEdges(iter,ve1,ve2); - unsigned int qi1, qi2; - qi1 = ve1->qi(); - if(ve2 != 0){ - qi2 = ve2->qi(); - if(qi2!=qi1) - cout << "QuantitativeInvisibilityF0D: ambiguous evaluation for point " << iter->getId() << endl; - } - result = qi1; +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) + cout << "QuantitativeInvisibilityF0D: ambiguous evaluation for point " << iter->getId() << endl; + } + result = qi1; return 0; - } +} - int CurveNatureF0D::operator()(Interface0DIterator& iter) { - Nature::EdgeNature nat = 0; - ViewEdge * ve1, *ve2; - getViewEdges(iter, ve1, ve2); - nat |= ve1->getNature(); - if(ve2!=0) - nat |= ve2->getNature(); - result = nat; +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; - } +} - int GetOccludersF0D::operator()(Interface0DIterator& iter) { - set occluders; - getOccludersF0D(iter,occluders); +int GetOccludersF0D::operator()(Interface0DIterator& iter) +{ + set occluders; + getOccludersF0D(iter, occluders); result.clear(); - // vsOccluders.insert(vsOccluders.begin(), occluders.begin(), occluders.end()); - for(set::iterator it=occluders.begin(), itend=occluders.end(); - it!=itend; - ++it){ - result.push_back((*it)); - } + //vsOccluders.insert(vsOccluders.begin(), occluders.begin(), occluders.end()); + for (set::iterator it = occluders.begin(), itend = occluders.end(); it != itend; ++it) { + result.push_back((*it)); + } return 0; - } +} - int GetShapeF0D::operator()(Interface0DIterator& iter) { - result = getShapeF0D(iter); +int GetShapeF0D::operator()(Interface0DIterator& iter) +{ + result = getShapeF0D(iter); return 0; - } +} - int GetOccludeeF0D::operator()(Interface0DIterator& iter) { - result = getOccludeeF0D(iter); +int GetOccludeeF0D::operator()(Interface0DIterator& iter) +{ + result = getOccludeeF0D(iter); return 0; - } +} } // end of namespace Functions0D diff --git a/source/blender/freestyle/intern/view_map/Functions0D.h b/source/blender/freestyle/intern/view_map/Functions0D.h index 4adbc8a1bf5..03ab008736c 100644 --- a/source/blender/freestyle/intern/view_map/Functions0D.h +++ b/source/blender/freestyle/intern/view_map/Functions0D.h @@ -1,64 +1,70 @@ -// -// Filename : Functions0D.h -// Author(s) : Stephane Grabli, Emmanuel Turquin -// Purpose : Functions taking 0D input -// Date of creation : 01/07/2003 -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef __FREESTYLE_FUNCTIONS_0D_H__ +#define __FREESTYLE_FUNCTIONS_0D_H__ + +/** \file blender/freestyle/intern/view_map/Functions0D.h + * \ingroup freestyle + * \brief Functions taking 0D input + * \author Stephane Grabli + * \author Emmanuel Turquin + * \date 01/07/2003 + */ + +#include +#include + +#include "Interface0D.h" + +#include "../geometry/Geom.h" + +#include "../python/Director.h" + +#include "../scene_graph/FrsMaterial.h" + +#include "../system/Exception.h" +#include "../system/Precision.h" -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef FUNCTIONS0D_H -# define FUNCTIONS0D_H - -# include "../system/Precision.h" -# include "Interface0D.h" -# include "../geometry/Geom.h" -# include "../system/Exception.h" -# include "../scene_graph/FrsMaterial.h" -# include -# include class FEdge; class ViewEdge; class SShape; using namespace Geometry; -#include "../python/Director.h" - // // UnaryFunction0D (base class for functions in 0D) // /////////////////////////////////////////////////////////// -template -/*! Base class for Unary Functions (functors) working - * on Interface0DIterator. - * A unary function will be used by calling - * its operator() on an Interface0DIterator. - * \attention In the scripting language, there exists - * several prototypes depending on the returned value type. - * For example, you would inherit from a UnaryFunction0DDouble - * if you wish to define a function that returns a double. +/*! Base class for Unary Functions (functors) working on Interface0DIterator. + * A unary function will be used by calling its operator() on an Interface0DIterator. + * \attention In the scripting language, there exists several prototypes depending on the returned value type. + * For example, you would inherit from a UnaryFunction0DDouble if you wish to define a function that returns a double. * The different existing prototypes are: * - UnaryFunction0DVoid * - UnaryFunction0DUnsigned @@ -68,433 +74,459 @@ template * - UnaryFunction0DVec2f * - UnaryFunction0DVec3f */ +template class /*LIB_VIEW_MAP_EXPORT*/ UnaryFunction0D { public: - T result; PyObject *py_uf0D; - /*! The type of the value - * returned by the functor. - */ - typedef T ReturnedValueType; - /*! Default constructor. */ -UnaryFunction0D() { py_uf0D = 0;} - /*! 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. - */ - virtual int operator()(Interface0DIterator& iter) { - return Director_BPy_UnaryFunction0D___call__( this, py_uf0D, iter ); - } - + /*! 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. + */ + virtual int operator()(Interface0DIterator& iter) + { + return Director_BPy_UnaryFunction0D___call__(this, py_uf0D, iter); + } }; -# ifdef SWIG -%feature("director") UnaryFunction0D; -%feature("director") UnaryFunction0D; -%feature("director") UnaryFunction0D; -%feature("director") UnaryFunction0D; -%feature("director") UnaryFunction0D; -%feature("director") UnaryFunction0D; -%feature("director") UnaryFunction0D; - -%template(UnaryFunction0DVoid) UnaryFunction0D; -%template(UnaryFunction0DUnsigned) UnaryFunction0D; -%template(UnaryFunction0DFloat) UnaryFunction0D; -%template(UnaryFunction0DDouble) UnaryFunction0D; -%template(UnaryFunction0DVec2f) UnaryFunction0D; -%template(UnaryFunction0DVec3f) UnaryFunction0D; -%template(UnaryFunction0DId) UnaryFunction0D; -%template(UnaryFunction0DViewShape) UnaryFunction0D; -%template(UnaryFunction0DVectorViewShape) UnaryFunction0D >; -# endif // SWIG - +#ifdef SWIG +%feature("director") UnaryFunction0D; +%feature("director") UnaryFunction0D; +%feature("director") UnaryFunction0D; +%feature("director") UnaryFunction0D; +%feature("director") UnaryFunction0D; +%feature("director") UnaryFunction0D; +%feature("director") UnaryFunction0D; + +%template(UnaryFunction0DVoid) UnaryFunction0D; +%template(UnaryFunction0DUnsigned) UnaryFunction0D; +%template(UnaryFunction0DFloat) UnaryFunction0D; +%template(UnaryFunction0DDouble) UnaryFunction0D; +%template(UnaryFunction0DVec2f) UnaryFunction0D; +%template(UnaryFunction0DVec3f) UnaryFunction0D; +%template(UnaryFunction0DId) UnaryFunction0D; +%template(UnaryFunction0DViewShape) UnaryFunction0D; +%template(UnaryFunction0DVectorViewShape) UnaryFunction0D >; +#endif // SWIG // // Functions definitions // /////////////////////////////////////////////////////////// class ViewShape; + namespace Functions0D { - // GetXF0D - /*! Returns the X 3D coordinate of an Interface0D. */ - class LIB_VIEW_MAP_EXPORT GetXF0D : public UnaryFunction0D - { - 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 LIB_VIEW_MAP_EXPORT GetYF0D : public UnaryFunction0D - { - 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 LIB_VIEW_MAP_EXPORT GetZF0D : public UnaryFunction0D - { - 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 LIB_VIEW_MAP_EXPORT GetProjectedXF0D : public UnaryFunction0D - { - 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 LIB_VIEW_MAP_EXPORT GetProjectedYF0D : public UnaryFunction0D - { - 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 LIB_VIEW_MAP_EXPORT GetProjectedZF0D : public UnaryFunction0D - { - 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 LIB_VIEW_MAP_EXPORT GetCurvilinearAbscissaF0D : public UnaryFunction0D - { - 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 LIB_VIEW_MAP_EXPORT GetParameterF0D : public UnaryFunction0D - { - 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 LIB_VIEW_MAP_EXPORT VertexOrientation2DF0D : public UnaryFunction0D - { - 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 LIB_VIEW_MAP_EXPORT VertexOrientation3DF0D : public UnaryFunction0D - { - 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 LIB_VIEW_MAP_EXPORT Curvature2DAngleF0D : public UnaryFunction0D - { - public: - /*! Returns the string "Curvature2DAngleF0D"*/ - string getName() const { - return "Curvature2DAngleF0D"; - } - /*! the () operator.*/ - int operator()(Interface0DIterator& iter); - }; - - // ZDiscontinuity - /*! Returns a real giving the distance between - * and Interface0D and the shape that lies behind (occludee). - * This distance is evaluated in the camera space and normalized - * between 0 and 1. Therefore, if no oject is occluded by the - * shape to which the Interface0D belongs to, 1 is returned. - */ - class LIB_VIEW_MAP_EXPORT ZDiscontinuityF0D : public UnaryFunction0D - { - 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 LIB_VIEW_MAP_EXPORT Normal2DF0D : public UnaryFunction0D - { - public: - /*! Returns the string "Normal2DF0D"*/ - string getName() const { - return "Normal2DF0D"; - } - /*! the () operator.*/ - int operator()(Interface0DIterator& iter); - }; - - // MaterialF0D - /*! Returns the material of the object evaluated at the Interface0D. - * This evaluation can be ambiguous (in the case of a TVertex for example. - * This functor tries to remove this ambiguity using the context - * offered by the 1D element to which the Interface0DIterator& belongs - * to and by arbitrary chosing the material of the face - * that lies on its left when following the 1D element if there - * are two different materials on each side of the point. - * 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 LIB_VIEW_MAP_EXPORT MaterialF0D : public UnaryFunction0D - { - public: - /*! Returns the string "MaterialF0D"*/ - string getName() const { - return "MaterialF0D"; - } - /*! the () operator.*/ - int operator()(Interface0DIterator& iter); - }; - - // ShapeIdF0D - /*! Returns the Id of the Shape the Interface0D belongs to. - * This evaluation can be ambiguous (in the case of a TVertex for example). - * This functor tries to remove this ambiguity using the context - * offered by the 1D element to which the Interface0DIterator& belongs - * to. - * 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 LIB_VIEW_MAP_EXPORT ShapeIdF0D : public UnaryFunction0D - { - public: - /*! Returns the string "ShapeIdF0D"*/ - string getName() const { - return "ShapeIdF0D"; - } - /*! the () operator.*/ - int operator()(Interface0DIterator& iter); - }; - - // QiF0D - /*! Returns the quantitative invisibility of this Interface0D. - * This evaluation can be ambiguous (in the case of a TVertex for example). - * This functor tries to remove this ambiguity using the context - * offered by the 1D element to which the Interface0DIterator& belongs - * to. - * 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 LIB_VIEW_MAP_EXPORT QuantitativeInvisibilityF0D : public UnaryFunction0D - { - 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 LIB_VIEW_MAP_EXPORT CurveNatureF0D : public UnaryFunction0D - { - public: - /*! Returns the string "QuantitativeInvisibilityF0D"*/ - string getName() const { - return "CurveNatureF0D"; - } - /*! the () operator.*/ - int operator()(Interface0DIterator& iter); - }; - - // GetShapeF0D - /*! Returns the ViewShape* - * containing the Interface0D - */ - class LIB_VIEW_MAP_EXPORT 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 LIB_VIEW_MAP_EXPORT GetOccludersF0D : public UnaryFunction0D< std::vector > - { - 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 LIB_VIEW_MAP_EXPORT GetOccludeeF0D: public UnaryFunction0D< ViewShape*> - { - public: - /*! Returns the string "GetOccludeeF0D"*/ - string getName() const { - return "GetOccludeeF0D"; - } - /*! the () operator.*/ - int operator()(Interface0DIterator& iter); - }; - - - - /////////////////////////// Internal //////////////////////////// - - // getFEdge - LIB_VIEW_MAP_EXPORT - FEdge* getFEdge(Interface0D& it1, Interface0D& it2); - - // getFEdges - LIB_VIEW_MAP_EXPORT - void getFEdges(Interface0DIterator& it, - FEdge*& fe1, - FEdge*& fe2); - - // getViewEdges - LIB_VIEW_MAP_EXPORT - void getViewEdges(Interface0DIterator& it, - ViewEdge *&ve1, - ViewEdge *&ve2); - - // getShapeF0D - LIB_VIEW_MAP_EXPORT - ViewShape* getShapeF0D(Interface0DIterator& it); - - // getOccludersF0D - LIB_VIEW_MAP_EXPORT - void getOccludersF0D(Interface0DIterator& it, std::set& oOccluders); - - // getOccludeeF0D - LIB_VIEW_MAP_EXPORT - ViewShape* getOccludeeF0D(Interface0DIterator& it); +// GetXF0D +/*! Returns the X 3D coordinate of an Interface0D. */ +class LIB_VIEW_MAP_EXPORT GetXF0D : public UnaryFunction0D +{ +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 LIB_VIEW_MAP_EXPORT GetYF0D : public UnaryFunction0D +{ +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 LIB_VIEW_MAP_EXPORT GetZF0D : public UnaryFunction0D +{ +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 LIB_VIEW_MAP_EXPORT GetProjectedXF0D : public UnaryFunction0D +{ +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 LIB_VIEW_MAP_EXPORT GetProjectedYF0D : public UnaryFunction0D +{ +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 LIB_VIEW_MAP_EXPORT GetProjectedZF0D : public UnaryFunction0D +{ +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 LIB_VIEW_MAP_EXPORT GetCurvilinearAbscissaF0D : public UnaryFunction0D +{ +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 LIB_VIEW_MAP_EXPORT GetParameterF0D : public UnaryFunction0D +{ +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 LIB_VIEW_MAP_EXPORT VertexOrientation2DF0D : public UnaryFunction0D +{ +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 LIB_VIEW_MAP_EXPORT VertexOrientation3DF0D : public UnaryFunction0D +{ +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 LIB_VIEW_MAP_EXPORT Curvature2DAngleF0D : public UnaryFunction0D +{ +public: + /*! Returns the string "Curvature2DAngleF0D" */ + string getName() const + { + return "Curvature2DAngleF0D"; + } + + /*! the () operator. */ + int operator()(Interface0DIterator& iter); +}; + +// ZDiscontinuity +/*! Returns a real giving the distance between and Interface0D and the shape that lies behind (occludee). + * This distance is evaluated in the camera space and normalized between 0 and 1. Therefore, if no oject is occluded + * by the shape to which the Interface0D belongs to, 1 is returned. + */ +class LIB_VIEW_MAP_EXPORT ZDiscontinuityF0D : public UnaryFunction0D +{ +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 LIB_VIEW_MAP_EXPORT Normal2DF0D : public UnaryFunction0D +{ +public: + /*! Returns the string "Normal2DF0D" */ + string getName() const + { + return "Normal2DF0D"; + } + + /*! the () operator. */ + int operator()(Interface0DIterator& iter); +}; + +// MaterialF0D +/*! Returns the material of the object evaluated at the Interface0D. + * This evaluation can be ambiguous (in the case of a TVertex for example. + * This functor tries to remove this ambiguity using the context offered by the 1D element to which the + * Interface0DIterator& belongs to and by arbitrary chosing the material of the face that lies on its left when + * following the 1D element if there are two different materials on each side of the point. + * 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 LIB_VIEW_MAP_EXPORT MaterialF0D : public UnaryFunction0D +{ +public: + /*! Returns the string "MaterialF0D" */ + string getName() const + { + return "MaterialF0D"; + } + + /*! the () operator. */ + int operator()(Interface0DIterator& iter); +}; + +// ShapeIdF0D +/*! Returns the Id of the Shape the Interface0D belongs to. + * This evaluation can be ambiguous (in the case of a TVertex for example). + * This functor tries to remove this ambiguity using the context offered by the 1D element to which the + * Interface0DIterator& belongs to. + * 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 LIB_VIEW_MAP_EXPORT ShapeIdF0D : public UnaryFunction0D +{ +public: + /*! Returns the string "ShapeIdF0D" */ + string getName() const + { + return "ShapeIdF0D"; + } + + /*! the () operator. */ + int operator()(Interface0DIterator& iter); +}; + +// QiF0D +/*! Returns the quantitative invisibility of this Interface0D. +* This evaluation can be ambiguous (in the case of a TVertex for example). +* This functor tries to remove this ambiguity using the context offered by the 1D element to which the +* Interface0DIterator& belongs to. +* 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 LIB_VIEW_MAP_EXPORT QuantitativeInvisibilityF0D : public UnaryFunction0D +{ +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 LIB_VIEW_MAP_EXPORT CurveNatureF0D : public UnaryFunction0D +{ +public: + /*! Returns the string "QuantitativeInvisibilityF0D" */ + string getName() const + { + return "CurveNatureF0D"; + } + + /*! the () operator. */ + int operator()(Interface0DIterator& iter); +}; + +// GetShapeF0D +/*! Returns the ViewShape* containing the Interface0D */ +class LIB_VIEW_MAP_EXPORT 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 LIB_VIEW_MAP_EXPORT GetOccludersF0D : public UnaryFunction0D< std::vector > +{ +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 LIB_VIEW_MAP_EXPORT GetOccludeeF0D: public UnaryFunction0D< ViewShape*> +{ +public: + /*! Returns the string "GetOccludeeF0D" */ + string getName() const + { + return "GetOccludeeF0D"; + } + + /*! the () operator. */ + int operator()(Interface0DIterator& iter); +}; + + +/////////////////////////// Internal //////////////////////////// + +// getFEdge +LIB_VIEW_MAP_EXPORT +FEdge *getFEdge(Interface0D& it1, Interface0D& it2); + +// getFEdges +LIB_VIEW_MAP_EXPORT +void getFEdges(Interface0DIterator& it, FEdge *&fe1, FEdge *&fe2); + +// getViewEdges +LIB_VIEW_MAP_EXPORT +void getViewEdges(Interface0DIterator& it, ViewEdge *&ve1, ViewEdge *&ve2); + +// getShapeF0D +LIB_VIEW_MAP_EXPORT +ViewShape *getShapeF0D(Interface0DIterator& it); + +// getOccludersF0D +LIB_VIEW_MAP_EXPORT +void getOccludersF0D(Interface0DIterator& it, std::set& oOccluders); + +// getOccludeeF0D +LIB_VIEW_MAP_EXPORT +ViewShape *getOccludeeF0D(Interface0DIterator& it); } // end of namespace Functions0D -#endif // FUNCTIONS0D_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 8545c660084..f17a568ffee 100644 --- a/source/blender/freestyle/intern/view_map/Functions1D.cpp +++ b/source/blender/freestyle/intern/view_map/Functions1D.cpp @@ -1,231 +1,271 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/** \file blender/freestyle/intern/view_map/Functions1D.cpp + * \ingroup freestyle + * \brief Functions taking 1D input + * \author Stephane Grabli + * \author Emmanuel Turquin + * \date 01/07/2003 + */ # include "Functions1D.h" + using namespace std; namespace Functions1D { - int GetXF1D::operator()(Interface1D& inter) { - result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); +int GetXF1D::operator()(Interface1D& inter) +{ + result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); return 0; - } +} - int GetYF1D::operator()(Interface1D& inter) { - result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); +int GetYF1D::operator()(Interface1D& inter) +{ + result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); return 0; - } +} - int GetZF1D::operator()(Interface1D& inter) { - result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); +int GetZF1D::operator()(Interface1D& inter) +{ + result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); return 0; - } +} - int GetProjectedXF1D::operator()(Interface1D& inter) { - result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); +int GetProjectedXF1D::operator()(Interface1D& inter) +{ + result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); return 0; - } +} - int GetProjectedYF1D::operator()(Interface1D& inter) { - result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); +int GetProjectedYF1D::operator()(Interface1D& inter) +{ + result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); return 0; - } +} - int GetProjectedZF1D::operator()(Interface1D& inter) { - result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); +int GetProjectedZF1D::operator()(Interface1D& inter) +{ + result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); return 0; - } +} - int Orientation2DF1D::operator()(Interface1D& inter) { - FEdge * fe = dynamic_cast(&inter); - if(fe){ - Vec3r res = fe->orientation2d(); - result = Vec2f(res[0], res[1]); - } else { - result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); +int Orientation2DF1D::operator()(Interface1D& inter) +{ + FEdge *fe = dynamic_cast(&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) { - result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); +int Orientation3DF1D::operator()(Interface1D& inter) +{ + result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); return 0; - } +} - int ZDiscontinuityF1D::operator()(Interface1D& inter) { - result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); +int ZDiscontinuityF1D::operator()(Interface1D& inter) +{ + result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); return 0; - } - - int QuantitativeInvisibilityF1D::operator()(Interface1D& inter) { - ViewEdge* ve = dynamic_cast(&inter); +} + +int QuantitativeInvisibilityF1D::operator()(Interface1D& inter) +{ + ViewEdge *ve = dynamic_cast(&inter); if (ve) { - result = ve->qi(); - return 0; + result = ve->qi(); + return 0; } - FEdge *fe = dynamic_cast(&inter); + FEdge *fe = dynamic_cast(&inter); if (fe) { - result = ve->qi(); - return 0; - } - result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); - return 0; - } - - int CurveNatureF1D::operator()(Interface1D& inter) { - ViewEdge* ve = dynamic_cast(&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) { - TimeStamp *timestamp = TimeStamp::instance(); - inter.setTimeStamp(timestamp->getTimeStamp()); - return 0; - } - - int ChainingTimeStampF1D::operator()(Interface1D& inter) { - TimeStamp *timestamp = TimeStamp::instance(); - ViewEdge *ve = dynamic_cast(&inter); - if(ve) - ve->setChainingTimeStamp(timestamp->getTimeStamp()); - return 0; - } - - int IncrementChainingTimeStampF1D::operator()(Interface1D& inter) { - ViewEdge *ve = dynamic_cast(&inter); - if(ve) - ve->setChainingTimeStamp(ve->getChainingTimeStamp()+1); - return 0; - } - - int GetShapeF1D::operator()(Interface1D& inter) { - vector shapesVector; - set shapesSet; - ViewEdge* ve = dynamic_cast(&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::iterator>(shapesVector.begin(), shapesSet.begin(), shapesSet.end()); - } - result = shapesVector; - return 0; - } - - int GetOccludersF1D::operator()(Interface1D& inter) { - vector shapesVector; - set shapesSet; - ViewEdge* ve = dynamic_cast(&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) { - vector shapesVector; - set shapesSet; - ViewEdge* ve = dynamic_cast(&inter); - if (ve){ - ViewShape * aShape = ve->aShape(); - shapesVector.push_back(aShape); - }else{ - Interface0DIterator it=inter.verticesBegin(), itend=inter.verticesEnd(); - for(;it!=itend;++it){ - shapesSet.insert(Functions0D::getOccludeeF0D(it)); - } - shapesVector.insert::iterator>(shapesVector.begin(), shapesSet.begin(), shapesSet.end()); - } - result = shapesVector; - return 0; - } - // Internal - //////////// - - void getOccludeeF1D(Interface1D& inter, set& oShapes){ - ViewEdge* ve = dynamic_cast(&inter); - if (ve){ - ViewShape * aShape = ve->aShape(); - if(aShape == 0){ - oShapes.insert(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& oShapes){ - ViewEdge* ve = dynamic_cast(&inter); - if (ve){ - vector& occluders = ve->occluders(); - oShapes.insert::iterator>(occluders.begin(), occluders.end()); - } - else{ - Interface0DIterator it=inter.verticesBegin(), itend=inter.verticesEnd(); - for(;it!=itend;++it){ - set shapes; - Functions0D::getOccludersF0D(it, shapes); - for(set::iterator s=shapes.begin(), send=shapes.end(); - s!=send; - ++s) - oShapes.insert(*s); - } - } - } - - void getShapeF1D(Interface1D& inter, set& oShapes){ - ViewEdge* ve = dynamic_cast(&inter); - if (ve){ - oShapes.insert(ve->viewShape()); - }else{ - Interface0DIterator it=inter.verticesBegin(), itend=inter.verticesEnd(); - for(;it!=itend;++it) - oShapes.insert(Functions0D::getShapeF0D(it)); - } - } + result = ve->qi(); + return 0; + } + result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); + return 0; +} + +int CurveNatureF1D::operator()(Interface1D& inter) +{ + ViewEdge *ve = dynamic_cast(&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) +{ + TimeStamp *timestamp = TimeStamp::instance(); + inter.setTimeStamp(timestamp->getTimeStamp()); + return 0; +} + +int ChainingTimeStampF1D::operator()(Interface1D& inter) +{ + TimeStamp *timestamp = TimeStamp::instance(); + ViewEdge *ve = dynamic_cast(&inter); + if (ve) + ve->setChainingTimeStamp(timestamp->getTimeStamp()); + return 0; +} + +int IncrementChainingTimeStampF1D::operator()(Interface1D& inter) +{ + ViewEdge *ve = dynamic_cast(&inter); + if (ve) + ve->setChainingTimeStamp(ve->getChainingTimeStamp()+1); + return 0; +} + +int GetShapeF1D::operator()(Interface1D& inter) +{ + vector shapesVector; + set shapesSet; + ViewEdge *ve = dynamic_cast(&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::iterator>(shapesVector.begin(), shapesSet.begin(), shapesSet.end()); + } + result = shapesVector; + return 0; +} + +int GetOccludersF1D::operator()(Interface1D& inter) +{ + vector shapesVector; + set shapesSet; + ViewEdge *ve = dynamic_cast(&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) +{ + vector shapesVector; + set shapesSet; + ViewEdge *ve = dynamic_cast(&inter); + if (ve) { + ViewShape *aShape = ve->aShape(); + shapesVector.push_back(aShape); + } + else { + Interface0DIterator it = inter.verticesBegin(), itend = inter.verticesEnd(); + for (; it != itend; ++it) { + shapesSet.insert(Functions0D::getOccludeeF0D(it)); + } + shapesVector.insert::iterator>(shapesVector.begin(), shapesSet.begin(), shapesSet.end()); + } + result = shapesVector; + return 0; +} + +// Internal +//////////// + +void getOccludeeF1D(Interface1D& inter, set& oShapes) +{ + ViewEdge *ve = dynamic_cast(&inter); + if (ve) { + ViewShape *aShape = ve->aShape(); + if (aShape == 0) { + oShapes.insert(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& oShapes) +{ + ViewEdge *ve = dynamic_cast(&inter); + if (ve) { + vector& occluders = ve->occluders(); + oShapes.insert::iterator>(occluders.begin(), occluders.end()); + } + else { + Interface0DIterator it = inter.verticesBegin(), itend = inter.verticesEnd(); + for (; it != itend; ++it) { + set shapes; + Functions0D::getOccludersF0D(it, shapes); + for (set::iterator s = shapes.begin(), send = shapes.end(); s != send; ++s) + oShapes.insert(*s); + } + } +} + +void getShapeF1D(Interface1D& inter, set& oShapes) +{ + ViewEdge *ve = dynamic_cast(&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 diff --git a/source/blender/freestyle/intern/view_map/Functions1D.h b/source/blender/freestyle/intern/view_map/Functions1D.h index ba42b25b47e..f1885aa1762 100644 --- a/source/blender/freestyle/intern/view_map/Functions1D.h +++ b/source/blender/freestyle/intern/view_map/Functions1D.h @@ -1,41 +1,48 @@ -// -// Filename : Functions1D.h -// Author(s) : Stephane Grabli, Emmanuel Turquin -// Purpose : Functions taking 1D input -// Date of creation : 01/07/2003 -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef __FREESTYLE_FUNCTIONS_1D_H__ +#define __FREESTYLE_FUNCTIONS_1D_H__ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/** \file blender/freestyle/intern/view_map/Functions1D.h + * \ingroup freestyle + * \brief Functions taking 1D input + * \author Stephane Grabli + * \author Emmanuel Turquin + * \date 01/07/2003 + */ -#ifndef FUNCTIONS1D_HPP -# define FUNCTIONS1D_HPP +#include "Functions0D.h" +#include "Interface1D.h" +#include "ViewMap.h" -# include "ViewMap.h" -# include "Functions0D.h" -# include "Interface1D.h" -# include "../system/Precision.h" -# include "../system/TimeStamp.h" -# include "../system/FreestyleConfig.h" +#include "../system/FreestyleConfig.h" +#include "../system/Precision.h" +#include "../system/TimeStamp.h" #include "../python/Director.h" @@ -44,14 +51,10 @@ // /////////////////////////////////////////////////////////// -/*! Base class for Unary Functions (functors) working - * on Interface1D. - * A unary function will be used by calling - * its operator() on an Interface1D. - * \attention In the scripting language, there exists - * several prototypes depending on the returned value type. - * For example, you would inherit from a UnaryFunction1DDouble - * if you wish to define a function that returns a double. +/*! Base class for Unary Functions (functors) working on Interface1D. + * A unary function will be used by calling its operator() on an Interface1D. + * \attention In the scripting language, there exists several prototypes depending on the returned value type. + * For example, you would inherit from a UnaryFunction1DDouble if you wish to define a function that returns a double. * The different existing prototypes are: * - UnaryFunction1DVoid * - UnaryFunction1DUnsigned @@ -65,81 +68,104 @@ template class /*LIB_VIEW_MAP_EXPORT*/ UnaryFunction1D { public: - T result; PyObject *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. - */ - 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; - } + /*! The type of the value returned by the functor. */ + typedef T ReturnedValueType; -protected: + /*! 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. + */ + 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; + } - IntegrationType _integration; +protected: + IntegrationType _integration; }; class UnaryFunction1D_void { public: - PyObject *py_uf1D; - UnaryFunction1D_void(){_integration = MEAN;} - UnaryFunction1D_void(IntegrationType iType){_integration = iType;} + UnaryFunction1D_void() + { + _integration = MEAN; + } + + UnaryFunction1D_void(IntegrationType iType) + { + _integration = iType; + } + virtual ~UnaryFunction1D_void() {} - - virtual string getName() const { + + virtual string getName() const + { return "UnaryFunction1D_void"; } - - int operator()(Interface1D& inter) { - return Director_BPy_UnaryFunction1D___call__( this, py_uf1D, inter ); + + int operator()(Interface1D& inter) + { + return Director_BPy_UnaryFunction1D___call__(this, py_uf1D, inter); + } + + void setIntegrationType(IntegrationType integration) + { + _integration = integration; + } + + IntegrationType getIntegrationType() const + { + return _integration; } - - void setIntegrationType(IntegrationType integration) { _integration = integration; } - IntegrationType getIntegrationType() const { return _integration; } - - protected: - IntegrationType _integration; + +protected: + IntegrationType _integration; }; @@ -150,406 +176,452 @@ public: namespace Functions1D { - // GetXF1D - /*! Returns the X 3D coordinate of an Interface1D. */ - class LIB_VIEW_MAP_EXPORT GetXF1D : public UnaryFunction1D - { - 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(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 LIB_VIEW_MAP_EXPORT GetYF1D : public UnaryFunction1D - { - 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(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 LIB_VIEW_MAP_EXPORT GetZF1D : public UnaryFunction1D - { - 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(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 LIB_VIEW_MAP_EXPORT GetProjectedXF1D : public UnaryFunction1D - { - 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(iType){} - public: - /*! 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 LIB_VIEW_MAP_EXPORT GetProjectedYF1D : public UnaryFunction1D - { - 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(iType){} - public: - /*! 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 LIB_VIEW_MAP_EXPORT GetProjectedZF1D : public UnaryFunction1D - { - 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(iType){} - public: - /*! Returns the string "GetProjectedZF1D"*/ - string getName() const { - return "GetProjectedZF1D"; - } - /*! the () operator.*/ - int operator()(Interface1D& inter); - }; - - // Orientation2DF1D - /*! Returns the 2D orientation as a Vec2f*/ - class LIB_VIEW_MAP_EXPORT Orientation2DF1D : public UnaryFunction1D - { - 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(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 LIB_VIEW_MAP_EXPORT Orientation3DF1D : public UnaryFunction1D - { - 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(iType){} - /*! Returns the string "Orientation3DF1D"*/ - string getName() const { - return "Orientation3DF1D"; - } - /*! the () operator.*/ - int operator()(Interface1D& inter); - }; - - // ZDiscontinuityF1D - /*! Returns a real giving the distance between - * and Interface1D and the shape that lies behind (occludee). - * This distance is evaluated in the camera space and normalized - * between 0 and 1. Therefore, if no oject is occluded by the - * shape to which the Interface1D belongs to, 1 is returned. - */ - class LIB_VIEW_MAP_EXPORT ZDiscontinuityF1D : public UnaryFunction1D - { - 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(iType){} - /*! Returns the string "ZDiscontinuityF1D"*/ - string getName() const { - return "ZDiscontinuityF1D"; - } - /*! the () operator.*/ - int operator()(Interface1D& inter); - }; - - // QuantitativeInvisibilityF1D - /*! Returns the Quantitative Invisibility of an Interface1D element. - * If the Interface1D is a ViewEdge, then there is no ambiguity - * concerning the result. But, if the Interface1D results of a chaining - * (chain, stroke), then it might be made of several 1D elements - * of different Quantitative Invisibilities. - */ - class LIB_VIEW_MAP_EXPORT QuantitativeInvisibilityF1D : public UnaryFunction1D - { - 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(iType) {} - /*! Returns the string "QuantitativeInvisibilityF1D"*/ - string getName() const { - return "QuantitativeInvisibilityF1D"; - } - /*! the () operator.*/ - int operator()(Interface1D& inter); - }; - - // CurveNatureF1D +// GetXF1D +/*! Returns the X 3D coordinate of an Interface1D. */ +class LIB_VIEW_MAP_EXPORT GetXF1D : public UnaryFunction1D +{ +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(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 LIB_VIEW_MAP_EXPORT GetYF1D : public UnaryFunction1D +{ +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(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 LIB_VIEW_MAP_EXPORT GetZF1D : public UnaryFunction1D +{ +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(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 LIB_VIEW_MAP_EXPORT GetProjectedXF1D : public UnaryFunction1D +{ +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(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 LIB_VIEW_MAP_EXPORT GetProjectedYF1D : public UnaryFunction1D +{ +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(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 LIB_VIEW_MAP_EXPORT GetProjectedZF1D : public UnaryFunction1D +{ +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(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 LIB_VIEW_MAP_EXPORT Orientation2DF1D : public UnaryFunction1D +{ +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(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 LIB_VIEW_MAP_EXPORT Orientation3DF1D : public UnaryFunction1D +{ +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(iType) {} + + /*! Returns the string "Orientation3DF1D" */ + string getName() const + { + return "Orientation3DF1D"; + } + + /*! the () operator. */ + int operator()(Interface1D& inter); +}; + +// ZDiscontinuityF1D +/*! Returns a real giving the distance between and Interface1D and the shape that lies behind (occludee). + * This distance is evaluated in the camera space and normalized between 0 and 1. Therefore, if no oject is occluded + * by the shape to which the Interface1D belongs to, 1 is returned. + */ +class LIB_VIEW_MAP_EXPORT ZDiscontinuityF1D : public UnaryFunction1D +{ +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(iType) {} + + /*! Returns the string "ZDiscontinuityF1D" */ + string getName() const + { + return "ZDiscontinuityF1D"; + } + + /*! the () operator. */ + int operator()(Interface1D& inter); +}; + +// QuantitativeInvisibilityF1D +/*! Returns the Quantitative Invisibility of an Interface1D element. + * If the Interface1D is a ViewEdge, then there is no ambiguity concerning the result. But, if the Interface1D + * results of a chaining (chain, stroke), then it might be made of several 1D elements of different + * Quantitative Invisibilities. + */ +class LIB_VIEW_MAP_EXPORT QuantitativeInvisibilityF1D : public UnaryFunction1D +{ +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(iType) {} + + /*! Returns the string "QuantitativeInvisibilityF1D" */ + string getName() const + { + return "QuantitativeInvisibilityF1D"; + } + + /*! the () operator. */ + int operator()(Interface1D& inter); +}; + +// CurveNatureF1D /*! Returns the nature of the Interface1D (silhouette, ridge, crease...). * Except if the Interface1D is a ViewEdge, this result might be ambiguous. - * 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. + * 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 LIB_VIEW_MAP_EXPORT CurveNatureF1D : public UnaryFunction1D - { - 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(iType) {} - /*! Returns the string "CurveNatureF1D"*/ - string getName() const { - return "CurveNatureF1D"; - } - /*! the () operator.*/ - int operator()(Interface1D& inter); - }; - - // TimeStampF1D +class LIB_VIEW_MAP_EXPORT CurveNatureF1D : public UnaryFunction1D +{ +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(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 LIB_VIEW_MAP_EXPORT TimeStampF1D : public UnaryFunction1D_void - { - public: - /*! Returns the string "TimeStampF1D"*/ - string getName() const { - return "TimeStampF1D"; - } - /*! the () operator.*/ - int operator()(Interface1D& inter); - }; - - // IncrementChainingTimeStampF1D +class LIB_VIEW_MAP_EXPORT 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 LIB_VIEW_MAP_EXPORT IncrementChainingTimeStampF1D : public UnaryFunction1D_void - { - public: - /*! Returns the string "IncrementChainingTimeStampF1D"*/ - string getName() const { - return "IncrementChainingTimeStampF1D"; - } - /*! the () operator.*/ - int operator()(Interface1D& inter); - }; - - // ChainingTimeStampF1D +class LIB_VIEW_MAP_EXPORT 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 LIB_VIEW_MAP_EXPORT ChainingTimeStampF1D : public UnaryFunction1D_void - { - public: - /*! Returns the string "ChainingTimeStampF1D"*/ - string getName() const { - return "ChainingTimeStampF1D"; - } - /*! the () operator.*/ - int operator()(Interface1D& inter); - }; - - - // Curvature2DAngleF1D +class LIB_VIEW_MAP_EXPORT 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 LIB_VIEW_MAP_EXPORT Curvature2DAngleF1D : public UnaryFunction1D - { - 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(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 LIB_VIEW_MAP_EXPORT Normal2DF1D : public UnaryFunction1D - { - 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(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 LIB_VIEW_MAP_EXPORT GetShapeF1D : public UnaryFunction1D > - { - public: - /*! Builds the functor. - */ - GetShapeF1D() : UnaryFunction1D >() {} - /*! 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 LIB_VIEW_MAP_EXPORT GetOccludersF1D : public UnaryFunction1D > - { - public: - /*! Builds the functor. - */ - GetOccludersF1D() : UnaryFunction1D >() {} - /*! 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 LIB_VIEW_MAP_EXPORT GetOccludeeF1D : public UnaryFunction1D > - { - public: - /*! Builds the functor. - */ - GetOccludeeF1D() : UnaryFunction1D >() {} - /*! Returns the string "GetOccludeeF1D"*/ - string getName() const { - return "GetOccludeeF1D"; - } - /*! the () operator.*/ - int operator()(Interface1D& inter); - }; - - // internal - //////////// - - // getOccludeeF1D - LIB_VIEW_MAP_EXPORT - void getOccludeeF1D(Interface1D& inter, set& oShapes); - - // getOccludersF1D - LIB_VIEW_MAP_EXPORT - void getOccludersF1D(Interface1D& inter, set& oShapes); - - // getShapeF1D - LIB_VIEW_MAP_EXPORT - void getShapeF1D(Interface1D& inter, set& oShapes); - +class LIB_VIEW_MAP_EXPORT Curvature2DAngleF1D : public UnaryFunction1D +{ +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(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 LIB_VIEW_MAP_EXPORT Normal2DF1D : public UnaryFunction1D +{ +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(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 LIB_VIEW_MAP_EXPORT GetShapeF1D : public UnaryFunction1D > +{ +public: + /*! Builds the functor. */ + GetShapeF1D() : UnaryFunction1D >() {} + + /*! 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 LIB_VIEW_MAP_EXPORT GetOccludersF1D : public UnaryFunction1D > +{ +public: + /*! Builds the functor. */ + GetOccludersF1D() : UnaryFunction1D >() {} + + /*! 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 LIB_VIEW_MAP_EXPORT GetOccludeeF1D : public UnaryFunction1D > +{ +public: + /*! Builds the functor. */ + GetOccludeeF1D() : UnaryFunction1D >() {} + + /*! Returns the string "GetOccludeeF1D" */ + string getName() const + { + return "GetOccludeeF1D"; + } + + /*! the () operator. */ + int operator()(Interface1D& inter); +}; + +// internal +//////////// + +// getOccludeeF1D +LIB_VIEW_MAP_EXPORT +void getOccludeeF1D(Interface1D& inter, set& oShapes); + +// getOccludersF1D +LIB_VIEW_MAP_EXPORT +void getOccludersF1D(Interface1D& inter, set& oShapes); + +// getShapeF1D +LIB_VIEW_MAP_EXPORT +void getShapeF1D(Interface1D& inter, set& oShapes); + } // end of namespace Functions1D -#endif // FUNCTIONS1D_HPP +#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 078fc5f2c98..cc711fedece 100644 --- a/source/blender/freestyle/intern/view_map/GridDensityProvider.h +++ b/source/blender/freestyle/intern/view_map/GridDensityProvider.h @@ -1,93 +1,108 @@ -// -// Filename : GridDensityProvider.h -// Author(s) : Alexander Beels -// Purpose : Class to define a cell grid surrounding -// the projected image of a scene -// Date of creation : 2011-2-5 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef GRIDDENSITYPROVIDER_H -#define GRIDDENSITYPROVIDER_H +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_GRID_DENSITY_PROVIDER_H__ +#define __FREESTYLE_GRID_DENSITY_PROVIDER_H__ + +/** \file blender/freestyle/intern/view_map/GridDensityProvider.h + * \ingroup freestyle + * \brief Class to define a cell grid surrounding the projected image of a scene + * \author Alexander Beels + * \date 2011-2-5 + */ #include #include + #include "OccluderSource.h" + #include "../geometry/BBox.h" -class GridDensityProvider { +class GridDensityProvider +{ // Disallow copying and assignment - GridDensityProvider (const GridDensityProvider& other); - GridDensityProvider& operator= (const GridDensityProvider& other); + GridDensityProvider(const GridDensityProvider& other); + GridDensityProvider& operator=(const GridDensityProvider& other); public: - GridDensityProvider (OccluderSource& source) - : source(source) { - } + GridDensityProvider(OccluderSource& source) : source(source) {} virtual ~GridDensityProvider() {}; - float cellSize() { + float cellSize() + { return _cellSize; } - unsigned cellsX() { + unsigned cellsX() + { return _cellsX; } - unsigned cellsY() { + unsigned cellsY() + { return _cellsY; } - float cellOrigin(int index) { - if ( index < 2 ) { + float cellOrigin(int index) + { + if (index < 2) { return _cellOrigin[index]; - } else { + } + else { throw new out_of_range("GridDensityProvider::cellOrigin can take only indexes of 0 or 1."); } } - static void calculateOptimalProscenium(OccluderSource& source, real proscenium[4]) { + static void calculateOptimalProscenium(OccluderSource& source, real proscenium[4]) + { source.begin(); - if ( source.isValid() ) { + 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() ) { + while (source.isValid()) { GridHelpers::expandProscenium (proscenium, source.getGridSpacePolygon()); source.next(); } } - cout << "Proscenium: (" << proscenium[0] << ", " << proscenium[1] << ", " << proscenium[2] << ", " << proscenium[3] << ")" << endl; + cout << "Proscenium: (" << proscenium[0] << ", " << proscenium[1] << ", " << proscenium[2] + << ", " << proscenium[3] << ")" << endl; } - static void calculateQuickProscenium(const GridHelpers::Transform& transform, const BBox& bbox, real proscenium[4]) { + static void calculateQuickProscenium(const GridHelpers::Transform& transform, const BBox& bbox, + real proscenium[4]) + { real z; // We want to use the z-coordinate closest to the camera to determine the proscenium face - if ( ::fabs(bbox.getMin()[2]) < ::fabs(bbox.getMax()[2]) ) { + if (::fabs(bbox.getMin()[2]) < ::fabs(bbox.getMax()[2])) { z = bbox.getMin()[2]; - } else { + } + else { z = bbox.getMax()[2]; } // Now calculate the proscenium according to the min and max values of the x and y coordinates @@ -98,7 +113,8 @@ public: proscenium[1] = std::max(minPoint[0], maxPoint[0]); proscenium[2] = std::min(minPoint[1], maxPoint[1]); proscenium[3] = std::max(minPoint[1], maxPoint[1]); - cout << "Proscenium : " << proscenium[0] << ", " << proscenium[1] << ", " << proscenium[2] << ", " << proscenium[3] << endl; + cout << "Proscenium : " << proscenium[0] << ", " << proscenium[1] << ", " << proscenium[2] << ", " + << proscenium[3] << endl; } protected: @@ -108,24 +124,23 @@ protected: float _cellOrigin[2]; }; -class GridDensityProviderFactory { +class GridDensityProviderFactory +{ // Disallow copying and assignment GridDensityProviderFactory (const GridDensityProviderFactory& other); GridDensityProviderFactory& operator= (const GridDensityProviderFactory& other); public: - GridDensityProviderFactory() - { - } + GridDensityProviderFactory() {} - virtual auto_ptr newGridDensityProvider(OccluderSource& source, const real proscenium[4]) =0; + virtual auto_ptr newGridDensityProvider(OccluderSource& source, const real proscenium[4]) = 0; - virtual auto_ptr newGridDensityProvider(OccluderSource& source, const BBox& bbox, const GridHelpers::Transform& transform) =0; + virtual auto_ptr newGridDensityProvider(OccluderSource& source, const BBox& bbox, + const GridHelpers::Transform& transform) = 0; - virtual auto_ptr newGridDensityProvider(OccluderSource& source) =0; + virtual auto_ptr newGridDensityProvider(OccluderSource& source) = 0; virtual ~GridDensityProviderFactory () {} }; -#endif // GRIDDENSITYPROVIDER_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 05b70af90b3..5e17c85808b 100644 --- a/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.cpp +++ b/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.cpp @@ -1,74 +1,84 @@ -// -// Filename : HeuristicGridDensityProviderFactory.cpp -// Author(s) : Alexander Beels -// Purpose : Class to define a cell grid surrounding -// the projected image of a scene -// Date of creation : 2011-2-8 -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/** \file blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.cpp + * \ingroup freestyle + * \brief Class to define a cell grid surrounding the projected image of a scene + * \author Alexander Beels + * \date 2011-2-8 + */ #include "HeuristicGridDensityProviderFactory.h" HeuristicGridDensityProviderFactory::HeuristicGridDensityProviderFactory(real sizeFactor, unsigned numFaces) - : sizeFactor(sizeFactor), numFaces(numFaces) +: sizeFactor(sizeFactor), numFaces(numFaces) { } -HeuristicGridDensityProviderFactory::~HeuristicGridDensityProviderFactory () {} +HeuristicGridDensityProviderFactory::~HeuristicGridDensityProviderFactory() {} -auto_ptr HeuristicGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const real proscenium[4]) +auto_ptr +HeuristicGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const real proscenium[4]) { auto_ptr avg(new AverageAreaGridDensityProvider(source, proscenium, sizeFactor)); auto_ptr p23(new Pow23GridDensityProvider(source, proscenium, numFaces)); - if ( avg->cellSize() > p23->cellSize() ) { + if (avg->cellSize() > p23->cellSize()) { return (auto_ptr) p23; - } else { + } + else { return (auto_ptr) avg; } } -auto_ptr HeuristicGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const BBox& bbox, const GridHelpers::Transform& transform) +auto_ptr +HeuristicGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const BBox& bbox, + const GridHelpers::Transform& transform) { - auto_ptr avg(new AverageAreaGridDensityProvider(source, bbox, transform, sizeFactor)); + auto_ptr avg(new AverageAreaGridDensityProvider(source, bbox, + transform, sizeFactor)); auto_ptr p23(new Pow23GridDensityProvider(source, bbox, transform, numFaces)); - if ( avg->cellSize() > p23->cellSize() ) { + if (avg->cellSize() > p23->cellSize()) { return (auto_ptr) p23; - } else { + } + else { return (auto_ptr) avg; } } -auto_ptr HeuristicGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source) +auto_ptr HeuristicGridDensityProviderFactory::newGridDensityProvider(OccluderSource& source) { real proscenium[4]; GridDensityProvider::calculateOptimalProscenium(source, proscenium); auto_ptr avg(new AverageAreaGridDensityProvider(source, proscenium, sizeFactor)); auto_ptr p23(new Pow23GridDensityProvider(source, proscenium, numFaces)); - if ( avg->cellSize() > p23->cellSize() ) { + if (avg->cellSize() > p23->cellSize()) { return (auto_ptr) p23; - } else { + } + else { return (auto_ptr) avg; } } - diff --git a/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.h b/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.h index d32c4ae4407..a7557f04565 100644 --- a/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.h +++ b/source/blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.h @@ -1,48 +1,55 @@ -// -// Filename : HeuristicGridDensityProviderFactory.h -// Author(s) : Alexander Beels -// Purpose : Class to define a cell grid surrounding -// the projected image of a scene -// Date of creation : 2011-2-8 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef HEURISTICGRIDDENSITYPROVIDERFACTORY_H -#define HEURISTICGRIDDENSITYPROVIDERFACTORY_H - -// #include // provided by GridDensityProvider.h -// #include "GridDensityProvider.h" // provided by *GridDensityProvider.h below -#include "Pow23GridDensityProvider.h" +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_HEURISTIC_GRID_DENSITY_PROVIDER_FACTORY_H__ +#define __FREESTYLE_HEURISTIC_GRID_DENSITY_PROVIDER_FACTORY_H__ + +/** \file blender/freestyle/intern/view_map/HeuristicGridDensityProviderFactory.h + * \ingroup freestyle + * \brief Class to define a cell grid surrounding the projected image of a scene + * \author Alexander Beels + * \date 2011-2-8 + */ + +//#include // provided by GridDensityProvider.h + #include "AverageAreaGridDensityProvider.h" +//#include "GridDensityProvider.h" // provided by *GridDensityProvider.h below +#include "Pow23GridDensityProvider.h" -class HeuristicGridDensityProviderFactory : public GridDensityProviderFactory { +class HeuristicGridDensityProviderFactory : public GridDensityProviderFactory +{ public: HeuristicGridDensityProviderFactory(real sizeFactor, unsigned numFaces); - ~HeuristicGridDensityProviderFactory (); + ~HeuristicGridDensityProviderFactory(); auto_ptr newGridDensityProvider(OccluderSource& source, const real proscenium[4]); - auto_ptr newGridDensityProvider(OccluderSource& source, const BBox& bbox, const GridHelpers::Transform& transform); + auto_ptr newGridDensityProvider(OccluderSource& source, const BBox& bbox, + const GridHelpers::Transform& transform); auto_ptr newGridDensityProvider(OccluderSource& source); protected: @@ -50,5 +57,4 @@ protected: unsigned numFaces; }; -#endif // HEURISTICGRIDDENSITYPROVIDERFACTORY_H - +#endif // __FREESTYLE_HEURISTIC_GRID_DENSITY_PROVIDER_FACTORY_H__ diff --git a/source/blender/freestyle/intern/view_map/Interface0D.h b/source/blender/freestyle/intern/view_map/Interface0D.h index 48d956eec19..bbf93deadb7 100644 --- a/source/blender/freestyle/intern/view_map/Interface0D.h +++ b/source/blender/freestyle/intern/view_map/Interface0D.h @@ -1,45 +1,53 @@ -// -// Filename : Interface0D.h -// Author(s) : Emmanuel Turquin -// Purpose : Interface to 0D elts -// Date of creation : 01/07/2003 -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef __FREESTYLE_INTERFACE_0D_H__ +#define __FREESTYLE_INTERFACE_0D_H__ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef INTERFACE0D_H -# define INTERFACE0D_H - -# include -# include -# include -# include "../system/Id.h" -# include "../system/Precision.h" -# include "../winged_edge/Nature.h" -# include "../geometry/Geom.h" -using namespace std; +/** \file blender/freestyle/intern/view_map/Interface0D.h + * \ingroup freestyle + * \brief Interface to 0D elts + * \author Emmanuel Turquin + * \date 01/07/2003 + */ + +#include +#include +#include + +#include "../geometry/Geom.h" +#include "../system/Id.h" #include "../system/Iterator.h" //soc +#include "../system/Precision.h" + +#include "../winged_edge/Nature.h" + +using namespace std; // // Interface0D @@ -51,114 +59,128 @@ class SVertex; class ViewVertex; class NonTVertex; class TVertex; + /*! Base class for any 0D element. */ class Interface0D { public: - - /*! Default constructor */ - Interface0D() {} - virtual ~Interface0D() {}; //soc - - /*! Returns the string "Interface0D".*/ - virtual string getExactTypeName() const { - return "Interface0D"; - } - - // Data access methods - - /*! Returns the 3D x coordinate of the point. */ - virtual real getX() const { - PyErr_SetString(PyExc_TypeError, "method getX() not properly overridden"); - return 0; - } - - /*! Returns the 3D y coordinate of the point. */ - virtual real getY() const { - PyErr_SetString(PyExc_TypeError, "method getY() not properly overridden"); - return 0; - } - - /*! Returns the 3D z coordinate of the point. */ - virtual real getZ() const { - PyErr_SetString(PyExc_TypeError, "method getZ() not properly overridden"); - return 0; - } - - /*! Returns the 3D point. */ - virtual Geometry::Vec3f getPoint3D() const { - PyErr_SetString(PyExc_TypeError, "method getPoint3D() not properly overridden"); - return 0; - } - - /*! Returns the 2D x coordinate of the point. */ - virtual real getProjectedX() const { - PyErr_SetString(PyExc_TypeError, "method getProjectedX() not properly overridden"); - return 0; - } - - /*! Returns the 2D y coordinate of the point. */ - virtual real getProjectedY() const { - PyErr_SetString(PyExc_TypeError, "method getProjectedY() not properly overridden"); - return 0; - } - - /*! Returns the 2D z coordinate of the point. */ - virtual real getProjectedZ() const { - PyErr_SetString(PyExc_TypeError, "method getProjectedZ() not properly overridden"); - return 0; - } - - /*! Returns the 2D point. */ - virtual Geometry::Vec2f getPoint2D() const { - PyErr_SetString(PyExc_TypeError, "method getPoint2D() not properly overridden"); - return 0; - } - - /*! Returns the FEdge that lies between this Interface0D and the - * Interface0D given as argument. */ - virtual FEdge* getFEdge(Interface0D&) { - PyErr_SetString(PyExc_TypeError, "method getFEdge() not properly overridden"); - return 0; - } - - /*! Returns the Id of the point. */ - virtual Id getId() const { - PyErr_SetString(PyExc_TypeError, "method getId() not properly overridden"); - return 0; - } - - /*! Returns the nature of the point. */ - virtual Nature::VertexNature getNature() const { - PyErr_SetString(PyExc_TypeError, "method getNature() not properly overridden"); - return Nature::POINT; - } - - - /*! Cast the Interface0D in SVertex if it can be. */ - virtual SVertex * castToSVertex(){ - PyErr_SetString(PyExc_TypeError, "method castToSVertex() not properly overridden"); - return 0; - } - - /*! Cast the Interface0D in ViewVertex if it can be. */ - virtual ViewVertex * castToViewVertex(){ - PyErr_SetString(PyExc_TypeError, "method castToViewVertex() not properly overridden"); - return 0; - } - - /*! Cast the Interface0D in NonTVertex if it can be. */ - virtual NonTVertex * castToNonTVertex(){ - PyErr_SetString(PyExc_TypeError, "method castToNonTVertex() not properly overridden"); - return 0; - } - - /*! Cast the Interface0D in TVertex if it can be. */ - virtual TVertex * castToTVertex(){ - PyErr_SetString(PyExc_TypeError, "method castToTVertex() not properly overridden"); - return 0; - } - + /*! Default constructor */ + Interface0D() {} + virtual ~Interface0D() {}; //soc + + /*! Returns the string "Interface0D". */ + virtual string getExactTypeName() const + { + return "Interface0D"; + } + + // Data access methods + + /*! Returns the 3D x coordinate of the point. */ + virtual real getX() const + { + PyErr_SetString(PyExc_TypeError, "method getX() not properly overridden"); + return 0; + } + + /*! Returns the 3D y coordinate of the point. */ + virtual real getY() const + { + PyErr_SetString(PyExc_TypeError, "method getY() not properly overridden"); + return 0; + } + + /*! Returns the 3D z coordinate of the point. */ + virtual real getZ() const + { + PyErr_SetString(PyExc_TypeError, "method getZ() not properly overridden"); + return 0; + } + + /*! Returns the 3D point. */ + virtual Geometry::Vec3f getPoint3D() const + { + PyErr_SetString(PyExc_TypeError, "method getPoint3D() not properly overridden"); + return 0; + } + + /*! Returns the 2D x coordinate of the point. */ + virtual real getProjectedX() const + { + PyErr_SetString(PyExc_TypeError, "method getProjectedX() not properly overridden"); + return 0; + } + + /*! Returns the 2D y coordinate of the point. */ + virtual real getProjectedY() const + { + PyErr_SetString(PyExc_TypeError, "method getProjectedY() not properly overridden"); + return 0; + } + + /*! Returns the 2D z coordinate of the point. */ + virtual real getProjectedZ() const + { + PyErr_SetString(PyExc_TypeError, "method getProjectedZ() not properly overridden"); + return 0; + } + + /*! Returns the 2D point. */ + virtual Geometry::Vec2f getPoint2D() const + { + PyErr_SetString(PyExc_TypeError, "method getPoint2D() not properly overridden"); + return 0; + } + + /*! Returns the FEdge that lies between this Interface0D and the Interface0D given as argument. */ + virtual FEdge* getFEdge(Interface0D&) + { + PyErr_SetString(PyExc_TypeError, "method getFEdge() not properly overridden"); + return 0; + } + + /*! Returns the Id of the point. */ + virtual Id getId() const + { + PyErr_SetString(PyExc_TypeError, "method getId() not properly overridden"); + return 0; + } + + /*! Returns the nature of the point. */ + virtual Nature::VertexNature getNature() const + { + PyErr_SetString(PyExc_TypeError, "method getNature() not properly overridden"); + return Nature::POINT; + } + + + /*! Cast the Interface0D in SVertex if it can be. */ + virtual SVertex *castToSVertex() + { + PyErr_SetString(PyExc_TypeError, "method castToSVertex() not properly overridden"); + return 0; + } + + /*! Cast the Interface0D in ViewVertex if it can be. */ + virtual ViewVertex * castToViewVertex() + { + PyErr_SetString(PyExc_TypeError, "method castToViewVertex() not properly overridden"); + return 0; + } + + /*! Cast the Interface0D in NonTVertex if it can be. */ + virtual NonTVertex *castToNonTVertex() + { + PyErr_SetString(PyExc_TypeError, "method castToNonTVertex() not properly overridden"); + return 0; + } + + /*! Cast the Interface0D in TVertex if it can be. */ + virtual TVertex *castToTVertex() + { + PyErr_SetString(PyExc_TypeError, "method castToTVertex() not properly overridden"); + return 0; + } }; @@ -170,39 +192,42 @@ public: class Interface0DIteratorNested : public Iterator { public: + virtual ~Interface0DIteratorNested() {} - 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 0copy(); + } + + /*! 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(); + } + + /*! 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(); + } - 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(); - } - - /*! 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; + Interface0DIteratorNested *_iterator; }; -#endif // INTERFACE0D_H +#endif // __FREESTYLE_INTERFACE_0D_H__ diff --git a/source/blender/freestyle/intern/view_map/Interface1D.h b/source/blender/freestyle/intern/view_map/Interface1D.h index 60cc0ebcb7e..440c6f275b8 100644 --- a/source/blender/freestyle/intern/view_map/Interface1D.h +++ b/source/blender/freestyle/intern/view_map/Interface1D.h @@ -1,125 +1,126 @@ -// -// Filename : Interface1D.h -// Author(s) : Emmanuel Turquin -// Purpose : Interface to 1D elts -// Date of creation : 01/07/2003 -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef __FREESTYLE_INTERFACE_1D_H__ +#define __FREESTYLE_INTERFACE_1D_H__ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/** \file blender/freestyle/intern/view_map/Interface1D.h + * \ingroup freestyle + * \brief Interface 1D and related tools definitions + * \author Emmanuel Turquin + * \date 01/07/2003 + */ + +#include +#include +#include +#include -#ifndef INTERFACE1D_H -# define INTERFACE1D_H +#include "Functions0D.h" -# include -# include -# include -# include -# include "../system/Id.h" -# include "../system/Precision.h" -# include "../winged_edge/Nature.h" -# include "Functions0D.h" +#include "../system/Id.h" +#include "../system/Precision.h" + +#include "../winged_edge/Nature.h" using namespace std; -/*! \file Interface1D.h - * Interface1D and related tools definitions - */ + // Integration method -/*! The different integration - * methods that can be invoked - * to integrate into a single value the set of values obtained +/*! The different integration methods that can be invoked to integrate into a single value the set of values obtained * 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. +/*! Returns a single value from a set of values evaluated at each 0D element of this 1D element. * \param fun * The UnaryFunction0D used to compute a value at each Interface0D. * \param it - * The Interface0DIterator used to iterate over the 0D elements of - * this 1D element. The integration will occur over the 0D elements - * starting from the one pointed by it. + * The Interface0DIterator used to iterate over the 0D elements of this 1D element. The integration will occur + * over the 0D elements starting from the one pointed by it. * \param it_end - * The Interface0DIterator pointing the end of the 0D elements of the - * 1D element. + * The Interface0DIterator pointing the end of the 0D elements of the 1D element. * \param integration_type - * The integration method used to compute a single value from - * a set of values. + * The integration method used to compute a single value from a set of values. * \return the single value obtained for the 1D element. */ template -T integrate(UnaryFunction0D& 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; +T integrate(UnaryFunction0D& 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; } - res /= (size ? size : 1); - break; - } - return res; + return res; } // @@ -131,96 +132,99 @@ T integrate(UnaryFunction0D& fun, class Interface1D { public: + /*! Default constructor */ + Interface1D() + { + _timeStamp = 0; + } + + virtual ~Interface1D() {}; //soc + + /*! Returns the string "Interface1D". */ + virtual string getExactTypeName() const + { + return "Interface1D"; + } + + // Iterator access - /*! Default constructor */ - Interface1D() {_timeStamp=0;} - virtual ~Interface1D() {}; //soc - - /*! 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() { - PyErr_SetString(PyExc_TypeError, "method verticesBegin() not properly overridden"); - return Interface0DIterator(); - } - - /*! Returns an iterator over the Interface1D vertices, - * pointing after the last vertex. - */ - virtual Interface0DIterator verticesEnd(){ - PyErr_SetString(PyExc_TypeError, "method verticesEnd() not properly overridden"); - return Interface0DIterator(); - } - - /*! 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.f) { - PyErr_SetString(PyExc_TypeError, "method pointsBegin() not properly overridden"); - return Interface0DIterator(); - } - - /*! 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.f) { - PyErr_SetString(PyExc_TypeError, "method pointsEnd() not properly overridden"); - return Interface0DIterator(); - } - - // Data access methods - - /*! Returns the 2D length of the 1D element. */ - virtual real getLength2D() const { - PyErr_SetString(PyExc_TypeError, "method getLength2D() not properly overridden"); - return 0; - } - - /*! Returns the Id of the 1D element .*/ - virtual Id getId() const { - PyErr_SetString(PyExc_TypeError, "method getId() not properly overridden"); - return Id(0, 0); - } - - - // 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 { - PyErr_SetString(PyExc_TypeError, "method getNature() not properly overridden"); - return Nature::NO_FEATURE; - } - - /*! 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; - } + /*! Returns an iterator over the Interface1D vertices, pointing to the first vertex. */ + virtual Interface0DIterator verticesBegin() + { + PyErr_SetString(PyExc_TypeError, "method verticesBegin() not properly overridden"); + return Interface0DIterator(); + } + + /*! Returns an iterator over the Interface1D vertices, pointing after the last vertex. */ + virtual Interface0DIterator verticesEnd() + { + PyErr_SetString(PyExc_TypeError, "method verticesEnd() not properly overridden"); + return Interface0DIterator(); + } + + /*! 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) + { + PyErr_SetString(PyExc_TypeError, "method pointsBegin() not properly overridden"); + return Interface0DIterator(); + } + + /*! 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) + { + PyErr_SetString(PyExc_TypeError, "method pointsEnd() not properly overridden"); + return Interface0DIterator(); + } + + // Data access methods + + /*! Returns the 2D length of the 1D element. */ + virtual real getLength2D() const + { + PyErr_SetString(PyExc_TypeError, "method getLength2D() not properly overridden"); + return 0; + } + + /*! Returns the Id of the 1D element. */ + virtual Id getId() const + { + PyErr_SetString(PyExc_TypeError, "method getId() not properly overridden"); + return Id(0, 0); + } + + + // 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 + { + PyErr_SetString(PyExc_TypeError, "method getNature() not properly overridden"); + return Nature::NO_FEATURE; + } + + /*! 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; + unsigned _timeStamp; }; -#endif // INTERFACE1D_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 356e281be4b..5af618dd6f6 100644 --- a/source/blender/freestyle/intern/view_map/OccluderSource.cpp +++ b/source/blender/freestyle/intern/view_map/OccluderSource.cpp @@ -1,65 +1,73 @@ -// -// Filename : OccluderSource.h -// Author(s) : Alexander Beels -// Purpose : Class to define a cell grid surrounding -// the projected image of a scene -// Date of creation : 2010-12-21 -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/freestyle/intern/view_map/OccluderSource.cpp + * \ingroup freestyle + * \brief Class to define a cell grid surrounding the projected image of a scene + * \author Alexander Beels + * \date 2010-12-21 + */ - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +#include #include "OccluderSource.h" -#include -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(); } -OccluderSource::~OccluderSource() { -} +OccluderSource::~OccluderSource() {} -void OccluderSource::buildCachedPolygon() { +void OccluderSource::buildCachedPolygon() +{ vector 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::iterator i = vertices.begin(); i != vertices.end(); ++i ) { + for (vector::iterator i = vertices.begin(); i != vertices.end(); ++i) { (*i) = transform(*i); } cachedPolygon = Polygon3r(vertices, transform((*currentFace)->GetNormal())); } -void OccluderSource::begin() { - vector& wshapes = wingedEdge.getWShapes(); +void OccluderSource::begin() +{ + vector& wshapes = wingedEdge.getWShapes(); currentShape = wshapes.begin(); shapesEnd = wshapes.end(); valid = false; - if ( currentShape != shapesEnd ) { + if (currentShape != shapesEnd) { vector& wFaces = (*currentShape)->GetFaceList(); currentFace = wFaces.begin(); facesEnd = wFaces.end(); - if ( currentFace != facesEnd ) { + if (currentFace != facesEnd) { buildCachedPolygon(); valid = true; } @@ -67,14 +75,15 @@ void OccluderSource::begin() { } bool OccluderSource::next() { - if ( valid ) { + if (valid) { ++currentFace; - while ( currentFace == facesEnd ) { + while (currentFace == facesEnd) { ++currentShape; - if ( currentShape == shapesEnd ) { + if (currentShape == shapesEnd) { valid = false; return false; - } else { + } + else { vector& wFaces = (*currentShape)->GetFaceList(); currentFace = wFaces.begin(); facesEnd = wFaces.end(); @@ -86,40 +95,47 @@ bool OccluderSource::next() { return false; } -bool OccluderSource::isValid() { +bool OccluderSource::isValid() +{ // Or: // return currentShapes != shapesEnd && currentFace != facesEnd; return valid; } -WFace* OccluderSource::getWFace() { +WFace *OccluderSource::getWFace() +{ return valid ? *currentFace : NULL; } -Polygon3r OccluderSource::getCameraSpacePolygon() { +Polygon3r OccluderSource::getCameraSpacePolygon() +{ return Polygon3r(GridHelpers::enumerateVertices((*currentFace)->getEdgeList()), (*currentFace)->GetNormal()); } -Polygon3r& OccluderSource::getGridSpacePolygon() { +Polygon3r& OccluderSource::getGridSpacePolygon() +{ return cachedPolygon; } -void OccluderSource::getOccluderProscenium(real proscenium[4]) { +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() ) { + while (isValid()) { GridHelpers::expandProscenium (proscenium, cachedPolygon); next(); } - cout << "Proscenium: (" << proscenium[0] << ", " << proscenium[1] << ", " << proscenium[2] << ", " << proscenium[3] << ")" << endl; + cout << "Proscenium: (" << proscenium[0] << ", " << proscenium[1] << ", " << proscenium[2] << ", " + << proscenium[3] << ")" << endl; } -real OccluderSource::averageOccluderArea() { +real OccluderSource::averageOccluderArea() +{ real area = 0.0; unsigned numFaces = 0; - for ( begin(); isValid(); next() ) { + for (begin(); isValid(); next()) { Vec3r min, max; cachedPolygon.getBBox(min, max); area += (max[0] - min[0]) * (max[1] - min[1]); @@ -128,5 +144,3 @@ real OccluderSource::averageOccluderArea() { area /= numFaces; return area; } - - diff --git a/source/blender/freestyle/intern/view_map/OccluderSource.h b/source/blender/freestyle/intern/view_map/OccluderSource.h index d623cc63fed..14f8f54fa1a 100644 --- a/source/blender/freestyle/intern/view_map/OccluderSource.h +++ b/source/blender/freestyle/intern/view_map/OccluderSource.h @@ -1,53 +1,59 @@ -// -// Filename : OccluderSource.h -// Author(s) : Alexander Beels -// Purpose : Class to define a cell grid surrounding -// the projected image of a scene -// Date of creation : 2010-12-21 -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef __FREESTYLE_OCCLUDER_SOURCE_H__ +#define __FREESTYLE_OCCLUDER_SOURCE_H__ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/** \file blender/freestyle/intern/view_map/OccluderSource.h + * \ingroup freestyle + * \brief Class to define a cell grid surrounding the projected image of a scene + * \author Alexander Beels + * \date 2010-12-21 + */ -#ifndef OCCLUDERSOURCE_H -#define OCCLUDERSOURCE_H +#include "../geometry/GridHelpers.h" #include "../winged_edge/WEdge.h" -#include "../geometry/GridHelpers.h" -class OccluderSource { +class OccluderSource +{ // Disallow copying and assignment - OccluderSource (const OccluderSource& other); - OccluderSource& operator= (const OccluderSource& other); + OccluderSource(const OccluderSource& other); + OccluderSource& operator=(const OccluderSource& other); public: - OccluderSource (const GridHelpers::Transform& transform, WingedEdge& we); + OccluderSource(const GridHelpers::Transform& transform, WingedEdge& we); virtual ~OccluderSource(); void begin(); virtual bool next(); bool isValid(); - WFace* getWFace(); + WFace *getWFace(); Polygon3r getCameraSpacePolygon(); Polygon3r& getGridSpacePolygon(); @@ -67,4 +73,4 @@ protected: void buildCachedPolygon(); }; -#endif // OCCLUDERSOURCE_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 2e506da9ee9..1a15fc849a6 100644 --- a/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.cpp +++ b/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.cpp @@ -1,52 +1,57 @@ -// -// Filename : Pow23GridDensityProvider.cpp -// Author(s) : Alexander Beels -// Purpose : Class to define a cell grid surrounding -// the projected image of a scene -// Date of creation : 2011-2-8 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/freestyle/intern/view_map/Pow23GridDensityProvider.cpp + * \ingroup freestyle + * \brief Class to define a cell grid surrounding the projected image of a scene + * \author Alexander Beels + * \date 2011-2-8 + */ #include "Pow23GridDensityProvider.h" -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); } -Pow23GridDensityProvider::Pow23GridDensityProvider(OccluderSource& source, const BBox& bbox, const GridHelpers::Transform& transform, unsigned numFaces) - : GridDensityProvider(source), numFaces(numFaces) +Pow23GridDensityProvider::Pow23GridDensityProvider(OccluderSource& source, const BBox& bbox, + const GridHelpers::Transform& transform, unsigned numFaces) +: GridDensityProvider(source), numFaces(numFaces) { real proscenium[4]; calculateQuickProscenium(transform, bbox, 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); @@ -56,7 +61,7 @@ Pow23GridDensityProvider::Pow23GridDensityProvider(OccluderSource& source, unsig Pow23GridDensityProvider::~Pow23GridDensityProvider () {} -void Pow23GridDensityProvider::initialize (const real proscenium[4]) +void Pow23GridDensityProvider::initialize(const real proscenium[4]) { float prosceniumWidth = (proscenium[1] - proscenium[0]); float prosceniumHeight = (proscenium[3] - proscenium[2]); @@ -71,10 +76,10 @@ void Pow23GridDensityProvider::initialize (const real proscenium[4]) // Make sure the grid exceeds the proscenium by a small amount float safetyZone = 0.1; - if ( _cellsX * _cellSize < prosceniumWidth * (1.0 + safetyZone) ) { + if (_cellsX * _cellSize < prosceniumWidth * (1.0 + safetyZone)) { _cellsX = prosceniumWidth * (1.0 + safetyZone) / _cellSize; } - if ( _cellsY * _cellSize < prosceniumHeight * (1.0 + safetyZone) ) { + if (_cellsY * _cellSize < prosceniumHeight * (1.0 + safetyZone)) { _cellsY = prosceniumHeight * (1.0 + safetyZone) / _cellSize; } cout << _cellsX << "x" << _cellsY << " cells of size " << _cellSize << " square." << endl; @@ -85,25 +90,26 @@ void Pow23GridDensityProvider::initialize (const real proscenium[4]) } Pow23GridDensityProviderFactory::Pow23GridDensityProviderFactory(unsigned numFaces) - : numFaces(numFaces) +: numFaces(numFaces) { } Pow23GridDensityProviderFactory::~Pow23GridDensityProviderFactory () {} -auto_ptr Pow23GridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const real proscenium[4]) +auto_ptr +Pow23GridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const real proscenium[4]) { return auto_ptr(new Pow23GridDensityProvider(source, proscenium, numFaces)); } -auto_ptr Pow23GridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const BBox& bbox, const GridHelpers::Transform& transform) +auto_ptr +Pow23GridDensityProviderFactory::newGridDensityProvider(OccluderSource& source, const BBox& bbox, + const GridHelpers::Transform& transform) { return auto_ptr(new Pow23GridDensityProvider(source, bbox, transform, numFaces)); } -auto_ptr Pow23GridDensityProviderFactory::newGridDensityProvider(OccluderSource& source) +auto_ptr Pow23GridDensityProviderFactory::newGridDensityProvider(OccluderSource& source) { return auto_ptr(new Pow23GridDensityProvider(source, numFaces)); } - - diff --git a/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.h b/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.h index c398a1643a4..0e26793cec7 100644 --- a/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.h +++ b/source/blender/freestyle/intern/view_map/Pow23GridDensityProvider.h @@ -1,67 +1,75 @@ -// -// Filename : Pow23GridDensityProvider.h -// Author(s) : Alexander Beels -// Purpose : Class to define a cell grid surrounding -// the projected image of a scene -// Date of creation : 2011-2-8 -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef __FREESTYLE_POW_23_GRID_DENSITY_PROVIDER_H__ +#define __FREESTYLE_POW_23_GRID_DENSITY_PROVIDER_H__ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef POW23GRIDDENSITYPROVIDER_H -#define POW23GRIDDENSITYPROVIDER_H +/** \file blender/freestyle/intern/view_map/Pow23GridDensityProvider.h + * \ingroup freestyle + * \brief Class to define a cell grid surrounding the projected image of a scene + * \author Alexander Beels + * \date 2011-2-8 + */ #include "GridDensityProvider.h" -class Pow23GridDensityProvider : public GridDensityProvider { +class Pow23GridDensityProvider : public GridDensityProvider +{ // Disallow copying and assignment - Pow23GridDensityProvider (const Pow23GridDensityProvider& other); - Pow23GridDensityProvider& operator= (const Pow23GridDensityProvider& other); + Pow23GridDensityProvider(const Pow23GridDensityProvider& other); + Pow23GridDensityProvider& operator=(const Pow23GridDensityProvider& other); public: Pow23GridDensityProvider(OccluderSource& source, const real proscenium[4], unsigned numFaces); - Pow23GridDensityProvider(OccluderSource& source, const BBox& bbox, const GridHelpers::Transform& transform, unsigned numFaces); + Pow23GridDensityProvider(OccluderSource& source, const BBox& bbox, const GridHelpers::Transform& transform, + unsigned numFaces); Pow23GridDensityProvider(OccluderSource& source, unsigned numFaces); - virtual ~Pow23GridDensityProvider (); + virtual ~Pow23GridDensityProvider(); protected: unsigned numFaces; private: - void initialize (const real proscenium[4]); + void initialize(const real proscenium[4]); }; -class Pow23GridDensityProviderFactory : public GridDensityProviderFactory { +class Pow23GridDensityProviderFactory : public GridDensityProviderFactory +{ public: Pow23GridDensityProviderFactory(unsigned numFaces); - ~Pow23GridDensityProviderFactory (); + ~Pow23GridDensityProviderFactory(); auto_ptr newGridDensityProvider(OccluderSource& source, const real proscenium[4]); - auto_ptr newGridDensityProvider(OccluderSource& source, const BBox& bbox, const GridHelpers::Transform& transform); + auto_ptr newGridDensityProvider(OccluderSource& source, const BBox& bbox, + const GridHelpers::Transform& transform); auto_ptr newGridDensityProvider(OccluderSource& source); + protected: unsigned numFaces; }; -#endif // POW23GRIDDENSITYPROVIDER_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 7a7d0a51d4b..104040fd2a5 100644 --- a/source/blender/freestyle/intern/view_map/Silhouette.cpp +++ b/source/blender/freestyle/intern/view_map/Silhouette.cpp @@ -1,370 +1,414 @@ - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/freestyle/intern/view_map/Silhouette.cpp + * \ingroup freestyle + * \brief Classes to define a silhouette structure + * \author Stephane Grabli + * \date 25/03/2002 + */ #include "Silhouette.h" #include "ViewMap.h" - /**********************************/ - /* */ - /* */ - /* SVertex */ - /* */ - /* */ - /**********************************/ +/**********************************/ +/* */ +/* */ +/* SVertex */ +/* */ +/* */ +/**********************************/ + +Nature::VertexNature SVertex::getNature() const +{ + Nature::VertexNature nature = Nature::S_VERTEX; + if (_pViewVertex) + nature |= _pViewVertex->getNature(); + return nature; +} + +SVertex *SVertex::castToSVertex() +{ + return this; +} + +ViewVertex *SVertex::castToViewVertex() +{ + return _pViewVertex; +} + +NonTVertex *SVertex::castToNonTVertex() +{ + return dynamic_cast(_pViewVertex); +} + +TVertex *SVertex::castToTVertex() +{ + return dynamic_cast(_pViewVertex); +} -Nature::VertexNature SVertex::getNature() const { - Nature::VertexNature nature = Nature::S_VERTEX; - if (_pViewVertex) - nature |= _pViewVertex->getNature(); - return nature; +float SVertex::shape_importance() const +{ + return shape()->importance(); } -SVertex * SVertex::castToSVertex(){ - return this; +#if 0 +Material SVertex::material() const +{ + return _Shape->material(); } +#endif -ViewVertex * SVertex::castToViewVertex(){ - return _pViewVertex; +Id SVertex::shape_id() const +{ + return _Shape->getId(); } -NonTVertex * SVertex::castToNonTVertex(){ - return dynamic_cast(_pViewVertex); +const SShape *SVertex::shape() const +{ + return _Shape; } -TVertex * SVertex::castToTVertex(){ - return dynamic_cast(_pViewVertex); +const int SVertex::qi() const +{ + if (getNature() & Nature::T_VERTEX) + Exception::raiseException(); + return (_FEdges[0])->qi(); } -float SVertex::shape_importance() const +occluder_container::const_iterator SVertex::occluders_begin() const { - return shape()->importance(); + if (getNature() & Nature::T_VERTEX) + Exception::raiseException(); + return (_FEdges[0])->occluders_begin(); } - -//Material SVertex::material() const {return _Shape->material();} -Id SVertex::shape_id() const {return _Shape->getId();} -const SShape * SVertex::shape() const {return _Shape;} -const int SVertex::qi() const +occluder_container::const_iterator SVertex::occluders_end() const { - if (getNature() & Nature::T_VERTEX) - Exception::raiseException(); - return (_FEdges[0])->qi(); + if (getNature() & Nature::T_VERTEX) + Exception::raiseException(); + return (_FEdges[0])->occluders_end(); } -occluder_container::const_iterator SVertex::occluders_begin() const +bool SVertex::occluders_empty() const { - if (getNature() & Nature::T_VERTEX) - Exception::raiseException(); - return (_FEdges[0])->occluders_begin(); + if (getNature() & Nature::T_VERTEX) + Exception::raiseException(); + return (_FEdges[0])->occluders_empty(); } -occluder_container::const_iterator SVertex::occluders_end() const +int SVertex::occluders_size() const { - if (getNature() & Nature::T_VERTEX) - Exception::raiseException(); - return (_FEdges[0])->occluders_end(); + if (getNature() & Nature::T_VERTEX) + Exception::raiseException(); + return (_FEdges[0])->occluders_size(); } -bool SVertex::occluders_empty() const +const Polygon3r& SVertex::occludee() const { - if (getNature() & Nature::T_VERTEX) - Exception::raiseException(); - return (_FEdges[0])->occluders_empty(); + if (getNature() & Nature::T_VERTEX) + Exception::raiseException(); + return (_FEdges[0])->occludee(); } -int SVertex::occluders_size() const +const SShape *SVertex::occluded_shape() const { - if (getNature() & Nature::T_VERTEX) - Exception::raiseException(); - return (_FEdges[0])->occluders_size(); + if (getNature() & Nature::T_VERTEX) + Exception::raiseException(); + return (_FEdges[0])->occluded_shape(); } -const Polygon3r& SVertex::occludee() const +const bool SVertex::occludee_empty() const { - if (getNature() & Nature::T_VERTEX) - Exception::raiseException(); - return (_FEdges[0])->occludee(); + if (getNature() & Nature::T_VERTEX) + Exception::raiseException(); + return (_FEdges[0])->occludee_empty(); } -const SShape* SVertex::occluded_shape() const +real SVertex::z_discontinuity() const { - if (getNature() & Nature::T_VERTEX) - Exception::raiseException(); - return (_FEdges[0])->occluded_shape(); + if (getNature() & Nature::T_VERTEX) + Exception::raiseException(); + return (_FEdges[0])->z_discontinuity(); } -const bool SVertex::occludee_empty() const +FEdge *SVertex::fedge() { - if (getNature() & Nature::T_VERTEX) - Exception::raiseException(); - return (_FEdges[0])->occludee_empty(); + if (getNature() & Nature::T_VERTEX) + return NULL; + return _FEdges[0]; } -real SVertex::z_discontinuity() const +FEdge *SVertex::getFEdge(Interface0D& inter) { - if (getNature() & Nature::T_VERTEX) - Exception::raiseException(); - return (_FEdges[0])->z_discontinuity(); + FEdge *result = NULL; + SVertex *iVertexB = dynamic_cast(&inter); + if (!iVertexB) + return result; + vector::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(vvertex); + if (tvertex) { + brother = tvertex->frontSVertex(); + if (this == brother) + brother = tvertex->backSVertex(); + const vector& 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(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; } -FEdge* SVertex::fedge() + +/**********************************/ +/* */ +/* */ +/* FEdge */ +/* */ +/* */ +/**********************************/ + + +int FEdge::viewedge_nature() const { - if (getNature() & Nature::T_VERTEX) - return 0; - return _FEdges[0]; + return _ViewEdge->getNature(); } -FEdge* SVertex::getFEdge(Interface0D& inter) +#if 0 +float FEdge::viewedge_length() const { - FEdge * result = 0; - SVertex* iVertexB = dynamic_cast(&inter); - if (!iVertexB) - return result; - vector::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(vvertex); - if(tvertex) - { - brother = tvertex->frontSVertex(); - if(this == brother) - brother = tvertex->backSVertex(); - const vector& 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(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; -} - - - /**********************************/ - /* */ - /* */ - /* FEdge */ - /* */ - /* */ - /**********************************/ - - -int FEdge::viewedge_nature() const {return _ViewEdge->getNature();} -//float FEdge::viewedge_length() const {return _ViewEdge->viewedge_length();} -const SShape* FEdge::occluded_shape() const -{ - ViewShape * aShape = _ViewEdge->aShape(); - if(aShape == 0) - return 0; - return aShape->sshape(); -} - -float FEdge::shape_importance() const -{ - return _VertexA->shape()->importance(); -} - -int FEdge::invisibility() const -{ - return _ViewEdge->qi(); -} - -occluder_container::const_iterator FEdge::occluders_begin() const {return _ViewEdge->occluders_begin();} -occluder_container::const_iterator FEdge::occluders_end() const {return _ViewEdge->occluders_end();} -bool FEdge::occluders_empty() const {return _ViewEdge->occluders_empty();} -int FEdge::occluders_size() const {return _ViewEdge->occluders_size();} + return _ViewEdge->viewedge_length(); +} +#endif + +const SShape *FEdge::occluded_shape() const +{ + ViewShape *aShape = _ViewEdge->aShape(); + if (aShape == 0) + return 0; + return aShape->sshape(); +} + +float FEdge::shape_importance() const +{ + return _VertexA->shape()->importance(); +} + +int FEdge::invisibility() const +{ + return _ViewEdge->qi(); +} + +occluder_container::const_iterator FEdge::occluders_begin() const +{ + return _ViewEdge->occluders_begin(); +} + +occluder_container::const_iterator FEdge::occluders_end() const +{ + return _ViewEdge->occluders_end(); +} + +bool FEdge::occluders_empty() const +{ + return _ViewEdge->occluders_empty(); +} + +int FEdge::occluders_size() const +{ + return _ViewEdge->occluders_size(); +} + const bool FEdge::occludee_empty() const { - return _ViewEdge->occludee_empty(); -} - - - -Id FEdge::shape_id() const -{ - return _VertexA->shape()->getId(); -} -const SShape* FEdge::shape() const -{ - return _VertexA->shape(); -} - -real FEdge::z_discontinuity() const -{ - if(!(getNature() & Nature::SILHOUETTE) && !(getNature() & Nature::BORDER)) - { - return 0; - } - - BBox 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; - - } - // real result; - // z_discontinuity_functor _functor; - - // Evaluate >(&_functor, iCombination, result ) - 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())); -} - - -//float FEdge::local_average_depth(int iCombination ) const -//{ -// -// float result; -// local_average_depth_functor functor; -// Evaluate(&functor, iCombination, result); -// -// return result; -//} -//float FEdge::local_depth_variance(int iCombination ) const -//{ -// float result; -// -// local_depth_variance_functor functor; -// -// Evaluate(&functor, iCombination, result); -// -// return result; -//} -// -// -//real FEdge::local_average_density( float sigma, int iCombination) const -//{ -// float result; -// -// density_functor functor(sigma); -// -// Evaluate(&functor, iCombination, 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 FEdge::curvature2d_as_vector(int iCombination) const -//{ -// Vec3r result; -// curvature2d_as_vector_functor _functor; -// Evaluate >(&_functor, iCombination, result ); -// return result; -//} -// -//real FEdge::curvature2d_as_angle(int iCombination) const -//{ -// real result; -// curvature2d_as_angle_functor _functor; -// Evaluate >(&_functor, iCombination, result ); -// return result; -//} - - /**********************************/ - /* */ - /* */ - /* FEdgeSharp */ - /* */ - /* */ - /**********************************/ - -//Material FEdge::material() const -//{ -// return _VertexA->shape()->material(); -//} -const FrsMaterial& FEdgeSharp::aFrsMaterial() const { - return _VertexA->shape()->frs_material(_aFrsMaterialIndex); -} - -const FrsMaterial& FEdgeSharp::bFrsMaterial() const { - return _VertexA->shape()->frs_material(_bFrsMaterialIndex); -} - - /**********************************/ - /* */ - /* */ - /* FEdgeSmooth */ - /* */ - /* */ - /**********************************/ - -const FrsMaterial& FEdgeSmooth::frs_material() const { - return _VertexA->shape()->frs_material(_FrsMaterialIndex); + return _ViewEdge->occludee_empty(); +} + +Id FEdge::shape_id() const +{ + return _VertexA->shape()->getId(); +} + +const SShape *FEdge::shape() const +{ + return _VertexA->shape(); +} + +real FEdge::z_discontinuity() const +{ + if (!(getNature() & Nature::SILHOUETTE) && !(getNature() & Nature::BORDER)) { + return 0; + } + + BBox 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; + } + +#if 0 + real result; + z_discontinuity_functor _functor; + Evaluate >(&_functor, iCombination, result); +#endif + 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())); +} + +#if 0 +float FEdge::local_average_depth(int iCombination ) const +{ + float result; + local_average_depth_functor functor; + Evaluate(&functor, iCombination, result); + + return result; +} + +float FEdge::local_depth_variance(int iCombination ) const +{ + float result; + + local_depth_variance_functor functor; + + Evaluate(&functor, iCombination, result); + + return result; +} + +real FEdge::local_average_density( float sigma, int iCombination) const +{ + float result; + + density_functor functor(sigma); + + Evaluate(&functor, iCombination, 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 FEdge::curvature2d_as_vector(int iCombination) const +{ + Vec3r result; + curvature2d_as_vector_functor _functor; + Evaluate >(&_functor, iCombination, result); + return result; +} + +real FEdge::curvature2d_as_angle(int iCombination) const +{ + real result; + curvature2d_as_angle_functor _functor; + Evaluate >(&_functor, iCombination, result); + return result; +} +#endif + +/**********************************/ +/* */ +/* */ +/* FEdgeSharp */ +/* */ +/* */ +/**********************************/ + +#if 0 +Material FEdge::material() const +{ + return _VertexA->shape()->material(); +} +#endif + +const FrsMaterial& FEdgeSharp::aFrsMaterial() const +{ + return _VertexA->shape()->frs_material(_aFrsMaterialIndex); +} + +const FrsMaterial& FEdgeSharp::bFrsMaterial() const +{ + return _VertexA->shape()->frs_material(_bFrsMaterialIndex); +} + +/**********************************/ +/* */ +/* */ +/* FEdgeSmooth */ +/* */ +/* */ +/**********************************/ + +const FrsMaterial& FEdgeSmooth::frs_material() const +{ + return _VertexA->shape()->frs_material(_FrsMaterialIndex); } diff --git a/source/blender/freestyle/intern/view_map/Silhouette.h b/source/blender/freestyle/intern/view_map/Silhouette.h index 369267af8d9..2efe111add5 100644 --- a/source/blender/freestyle/intern/view_map/Silhouette.h +++ b/source/blender/freestyle/intern/view_map/Silhouette.h @@ -1,49 +1,59 @@ -// -// Filename : Silhouette.h -// Author(s) : Stephane Grabli -// Purpose : Classes to define a silhouette structure -// Date of creation : 25/03/2002 -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef __FREESTYLE_SILHOUETTE_H__ +#define __FREESTYLE_SILHOUETTE_H__ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef SILHOUETTE_H -# define SILHOUETTE_H - -# include "Interface0D.h" -# include "Interface1D.h" -# include -# include -# include -# include -# include -# include "../system/FreestyleConfig.h" -# include "../geometry/Geom.h" -# include "../geometry/BBox.h" -# include "../scene_graph/FrsMaterial.h" -# include "../geometry/Polygon.h" -# include "../system/Exception.h" -# include "../winged_edge/Curvature.h" +/** \file blender/freestyle/intern/view_map/Silhouette.h + * \ingroup freestyle + * \brief Classes to define a silhouette structure + * \author Stephane Grabli + * \date 25/03/2002 + */ + +#include +#include +#include +#include +#include + +#include "Interface0D.h" +#include "Interface1D.h" + +#include "../geometry/BBox.h" +#include "../geometry/Geom.h" +#include "../geometry/Polygon.h" + +#include "../scene_graph/FrsMaterial.h" + +#include "../system/Exception.h" +#include "../system/FreestyleConfig.h" + +#include "../winged_edge/Curvature.h" using namespace std; using namespace Geometry; @@ -51,13 +61,13 @@ using namespace Geometry; class ViewShape; typedef vector occluder_container; - /**********************************/ - /* */ - /* */ - /* SVertex */ - /* */ - /* */ - /**********************************/ +/**********************************/ +/* */ +/* */ +/* SVertex */ +/* */ +/* */ +/**********************************/ class FEdge; class ViewVertex; @@ -67,574 +77,856 @@ class SShape; class LIB_VIEW_MAP_EXPORT 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 Vec3f 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 Vec2f getPoint2D() const { - return Vec2f((float)_Point2D.x(),(float)_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(); + /*! 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 Vec3f 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 Vec2f getPoint2D() const + { + return Vec2f((float)_Point2D.x(), (float)_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 fedges_container; + typedef vector fedges_container; private: - - Id _Id; - Vec3r _Point3D; - Vec3r _Point2D; - set _Normals; - vector _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. - real _curvatureFredo; - Vec2r _directionFredo; - CurvatureInfo* _curvature_info; + Id _Id; + Vec3r _Point3D; + Vec3r _Point2D; + set _Normals; + vector _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. + real _curvatureFredo; + Vec2r _directionFredo; + 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 normals() {return _Normals;} - /*! Returns the number of different normals for this vertex. */ - inline unsigned normalsSize() const {return _Normals.size();} - inline const vector& 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; - } - - /* 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;} - - /*! Sets the Id */ - inline void setId(const Id& id) {_Id = id;} - inline void setFEdges(const vector& 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);} - /* replaces edge 1 by edge 2 in the list of edges */ - inline void Replace(FEdge *e1, FEdge *e2) - { - vector::iterator insertedfe; - for(vector::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; - } - } - } + /*! 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 normals() + { + return _Normals; + } + + /*! Returns the number of different normals for this vertex. */ + inline unsigned normalsSize() const + { + return _Normals.size(); + } + + inline const vector& 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; + } + + /* 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; + } + + /*! Sets the Id */ + inline void setId(const Id& id) + { + _Id = id; + } + + inline void setFEdges(const vector& 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); + } + + /* replaces edge 1 by edge 2 in the list of edges */ + inline void Replace(FEdge *e1, FEdge *e2) + { + vector::iterator insertedfe; + for (vector::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 ; - //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 ; - + /* 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; +#endif }; - /**********************************/ - /* */ - /* */ - /* FEdge */ - /* */ - /* */ - /**********************************/ - +/**********************************/ +/* */ +/* */ +/* FEdge */ +/* */ +/* */ +/**********************************/ class ViewEdge; + /*! Base Class for feature edges. - * This FEdge can represent a silhouette, a crease, - * a ridge/valley, a border or a suggestive contour. - * For silhouettes, the FEdge is oriented - * such as, the visible face lies on the left of the edge. - * For borders, the FEdge is oriented - * such as, the face lies on the left of the edge. - * An FEdge can represent an initial edge of the mesh - * or runs accross a face of the initial mesh depending + * This FEdge can represent a silhouette, a crease, a ridge/valley, a border or a suggestive contour. + * For silhouettes, the FEdge is oriented such as, the visible face lies on the left of the edge. + * For borders, the FEdge is oriented such as, the face lies on the left of the edge. + * An FEdge can represent an initial edge of the mesh or runs accross a face of the initial mesh depending * on the smoothness or sharpness of the mesh. - * This class is specialized into a smooth and a sharp - * version since their properties slightly vary from + * This class is specialized into a smooth and a sharp version since their properties slightly vary from * one to the other. */ class LIB_VIEW_MAP_EXPORT 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; + } - /*! Returns the string "FEdge" . */ - virtual string getExactTypeName() const { - return "FEdge"; - } - - // Data access methods +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 _Occludees; + // Vec3r intersection; + // vector _Cells; - /*! Returns the 2D length of the FEdge. */ - virtual real getLength2D() const { - if (!_VertexA || !_VertexB) - return 0; - return (_VertexB->getPoint2D() - _VertexA->getPoint2D()).norm(); - } +protected: + SVertex *_VertexA; + SVertex *_VertexB; + Id _Id; + Nature::EdgeNature _Nature; + //vector _Occluders; // visibility // NOT HANDLED BY THE COPY CONSTRUCTOR!! - /*! Returns the Id of the FEdge. */ - virtual Id getId() const { - return _Id; - } + 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 -public: + Polygon3r _aFace; // The occluded face which lies on the right of a silhouette edge + Vec3r _occludeeIntersection; + bool _occludeeEmpty; - // 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 _Occludees; - // Vec3r intersection; - // vector _Cells; + bool _isSmooth; -protected: - SVertex *_VertexA; - SVertex *_VertexB; - Id _Id; - Nature::EdgeNature _Nature; - //vector _Occluders; // visibility // NON GERE PAR LE 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 _isInImage; 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; - } - /*! 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; - } - /*! 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; - 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();} - //inline int invisibility() const {return _Occluders.size();} - int invisibility() const ; - //inline const vector& occluders() const {return _Occluders;} - /*! 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 center2d() {return Vec3r((_VertexA->point2D()+_VertexB->point2D())/2.0);} - // inline bool hasVisibilityPoint() const {return _hasVisibilityPoint;} - // inline Vec3r visibilityPointA() const {return _VisibilityPointA;} - // inline Vec3r visibilityPointB() const {return _VisibilityPointB;} - 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; } - - /* 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 void AddOccluder(Polygon3r& iPolygon) {_Occluders.push_back(iPolygon);} - /*! Sets the ViewEdge to which this FEdge belongs to. */ - inline void setViewEdge(ViewEdge *iViewEdge) {_ViewEdge = iViewEdge;} - // 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 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; } - - /* 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 */ - /* 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 const bool occludee_empty() const {return _occludeeEmpty;} - const bool occludee_empty() const ; - real z_discontinuity() 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 {} - int viewedge_nature() const ; - //float viewedge_length() const ; - inline Vec3r orientation2d() const {return Vec3r(_VertexB->point2d()-_VertexA->point2d());} - inline Vec3r orientation3d() const {return Vec3r(_VertexB->point3d()-_VertexA->point3d());} - // //inline real curvature2d() const {return viewedge()->curvature2d((_VertexA->point2d()+_VertexB->point2d())/2.0);} - // inline Vec3r curvature2d_as_vector(int iCombination = 0) const ; - // /* angle in degrees*/ - // inline real curvature2d_as_angle(int iCombination = 0) const ; - - - // 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.f); - /*! 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.f); + /*! 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; + } + + /*! 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; + } + + /*! 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; + 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(); + } +#endif + + int invisibility() const; + +#if 0 + inline const vector& occluders() const + { + return _Occluders; + } +#endif + + /*! 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 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; + } +#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; + } + + /* 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); + } +#endif + + /*! 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; + } +#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; + } + + /* 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; + } +#endif + + 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 {} +#endif + + int viewedge_nature() const; + + //float viewedge_length() const; + + inline Vec3r orientation2d() const + { + return Vec3r(_VertexB->point2d() - _VertexA->point2d()); + } + + 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 Vec3r curvature2d_as_vector(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); }; // @@ -644,828 +936,941 @@ 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(&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; - } - return ((float)_edge->getLength2D()); - } - virtual float u() const{ - if(_vertex == _edge->vertexA()){ - return 0; - } - return 1.0; - } - 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(&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 // Iterator access (implementation) -Interface0DIterator FEdge::verticesBegin() { - Interface0DIterator ret(new FEdgeInternal::SVertexIterator(_VertexA, this)); - return ret; +Interface0DIterator FEdge::verticesBegin() +{ + Interface0DIterator ret(new FEdgeInternal::SVertexIterator(_VertexA, this)); + return ret; } -Interface0DIterator FEdge::verticesEnd() { - Interface0DIterator ret(new FEdgeInternal::SVertexIterator(0, this)); - return ret; +Interface0DIterator FEdge::verticesEnd() +{ + Interface0DIterator ret(new FEdgeInternal::SVertexIterator(0, this)); + return ret; } -Interface0DIterator FEdge::pointsBegin(float t) { - return verticesBegin(); +Interface0DIterator FEdge::pointsBegin(float t) +{ + return verticesBegin(); } -Interface0DIterator FEdge::pointsEnd(float t) { - return verticesEnd(); +Interface0DIterator FEdge::pointsEnd(float t) +{ + return verticesEnd(); } -/*! Class defining a sharp FEdge. A Sharp FEdge - * corresponds to an initial edge of the input mesh. - * It can be a silhouette, a crease or a border. - * If it is a crease edge, then it is borded - * 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 defining a sharp FEdge. A Sharp FEdge corresponds to an initial edge of the input mesh. + * It can be a silhouette, a crease or a border. If it is a crease edge, then it is borded + * 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 LIB_VIEW_MAP_EXPORT 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; - + 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;} - + /*! 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 defining a smooth edge. This kind of edge typically - * runs across a face of the input mesh. It can be +/*! 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 LIB_VIEW_MAP_EXPORT FEdgeSmooth : public FEdge { protected: - Vec3r _Normal; - unsigned _FrsMaterialIndex; - // bool _hasVisibilityPoint; - // Vec3r _VisibilityPointA; // The edge on which the visibility will be computed represented - // Vec3r _VisibilityPointB; // using its 2 extremity points A and B - void * _Face; // In case of exact silhouette, Face is the WFace crossed by Fedge - // NON GERE PAR LE COPY CONSTRUCTEUR - bool _FaceMark; + 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 +#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=0; - _FaceMark = false; - _FrsMaterialIndex = 0; - _isSmooth = true; - } - /*! Builds an FEdgeSmooth going from vA to vB. */ - inline FEdgeSmooth(SVertex *vA, SVertex *vB) : FEdge(vA, vB){ - _Face=0; - _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;} + /*! 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; + } }; - /**********************************/ - /* */ - /* */ - /* SShape */ - /* */ - /* */ - /**********************************/ -/*! Class to define a feature shape. It is the gathering - * of feature elements from an identified input shape - */ +/**********************************/ +/* */ +/* */ +/* SShape */ +/* */ +/* */ +/**********************************/ + + +/*! Class to define a feature shape. It is the gathering of feature elements from an identified input shape */ class LIB_VIEW_MAP_EXPORT SShape { private: - vector _chains; // list of fedges that are chains starting points. - vector _verticesList; // list of all vertices - vector _edgesList; // list of all edges - Id _Id; - string _Name; - BBox _BBox; - vector _FrsMaterials; + vector _chains; // list of fedges that are chains starting points. + vector _verticesList; // list of all vertices + vector _edgesList; // list of all edges + Id _Id; + string _Name; + BBox _BBox; + vector _FrsMaterials; - float _importance; + float _importance; - ViewShape *_ViewShape; + 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 = 0; - - _importance = 0.f; - _ViewShape = 0; - } - /*! Copy constructor */ - inline SShape(SShape& iBrother) - { - userdata = 0; - _Id = iBrother._Id; - _Name = iBrother._Name; - _BBox = iBrother.bbox(); - _FrsMaterials = iBrother._FrsMaterials; - - _importance = iBrother._importance; - - _ViewShape = iBrother._ViewShape; - - - //--------- - // vertices - //--------- - vector::iterator sv,svend; - vector& 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::iterator e,eend; - vector& 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::iterator fe,fend; - vector& 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& fedgeList = (*sv)->fedges(); - vector newfedgelist; - for(vector::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::iterator sv,svend; - vector::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& iParameters, vector& 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 intersections; - real t,T; - for(vector::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::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(newEdge); - FEdgeSmooth * fes = dynamic_cast(fe); - se->setFrsMaterialIndex(fes->frs_materialIndex()); - }else{ - newEdge = new FEdgeSharp((*sv), svB); - FEdgeSharp * se = dynamic_cast(newEdge); - FEdgeSharp * fes = dynamic_cast(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(newEdge); - FEdgeSmooth * fes = dynamic_cast(ioEdge); - se->setNormal(fes->normal()); - se->setFrsMaterialIndex(fes->frs_materialIndex()); - }else{ - newEdge = new FEdgeSharp(ioNewVertex, B); - FEdgeSharp * se = dynamic_cast(newEdge); - FEdgeSharp * fes = dynamic_cast(ioEdge); - se->setNormalA(fes->normalA()); - se->setNormalB(fes->normalB()); - se->setaFrsMaterialIndex(fes->aFrsMaterialIndex()); - se->setbFrsMaterialIndex(fes->bFrsMaterialIndex()); - } - 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& 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::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; - if(x < XMin) - XMin = x; - - // Y - real y = vertex[1]; - if(y > YMax) - YMax = y; - if(y < YMin) - YMin = y; - - // Z - real z = vertex[2]; - if(z > ZMax) - ZMax = z; - if(z < ZMin) - ZMin = z; - } - - - setBBox(BBox(Vec3r(XMin, YMin, ZMin), Vec3r(XMax, YMax, ZMax))); - } - - inline void RemoveEdgeFromChain(FEdge *iEdge) - { - for(vector::iterator fe=_chains.begin(), feend=_chains.end(); - fe!=feend; - fe++) - { - if(iEdge == (*fe)) - { - _chains.erase(fe); - break; - } - } - } - - inline void RemoveEdge(FEdge *iEdge) - { - for(vector::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& getVertexList() {return _verticesList;} // Get vertices list - /*! Returns the list of FEdges of the Shape. */ - inline vector& getEdgeList() {return _edgesList;} // Get edges list - inline vector& getChains() {return _chains;} - /*! Returns the bounding box of the shape. */ - inline const BBox& 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& 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; } - - /* 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 list of materials for the shape */ - inline void setFrsMaterials(const vector& iMaterials) {_FrsMaterials = iMaterials;} - inline void setViewShape(ViewShape *iShape) {_ViewShape = iShape;} - inline void setImportance(float importance){_importance = importance;} + /*! 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; + _BBox = iBrother.bbox(); + _FrsMaterials = iBrother._FrsMaterials; + _importance = iBrother._importance; + _ViewShape = iBrother._ViewShape; + + //--------- + // vertices + //--------- + vector::iterator sv, svend; + vector& 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::iterator e, eend; + vector& 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::iterator fe, fend; + vector& 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& fedgeList = (*sv)->fedges(); + vector newfedgelist; + for (vector::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::iterator sv, svend; + vector::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& iParameters, vector& 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 intersections; + real t, T; + for (vector::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::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(newEdge); + FEdgeSmooth *fes = dynamic_cast(fe); + se->setFrsMaterialIndex(fes->frs_materialIndex()); + } + else { + newEdge = new FEdgeSharp((*sv), svB); + FEdgeSharp *se = dynamic_cast(newEdge); + FEdgeSharp *fes = dynamic_cast(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(newEdge); + FEdgeSmooth *fes = dynamic_cast(ioEdge); + se->setNormal(fes->normal()); + se->setFrsMaterialIndex(fes->frs_materialIndex()); + } + else { + newEdge = new FEdgeSharp(ioNewVertex, B); + FEdgeSharp *se = dynamic_cast(newEdge); + FEdgeSharp *fes = dynamic_cast(ioEdge); + se->setNormalA(fes->normalA()); + se->setNormalB(fes->normalB()); + se->setaFrsMaterialIndex(fes->aFrsMaterialIndex()); + se->setbFrsMaterialIndex(fes->bFrsMaterialIndex()); + } + 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& 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::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(XMin, YMin, ZMin), Vec3r(XMax, YMax, ZMax))); + } + + inline void RemoveEdgeFromChain(FEdge *iEdge) + { + for (vector::iterator fe = _chains.begin(), feend = _chains.end(); fe != feend; fe++) { + if (iEdge == (*fe)) { + _chains.erase(fe); + break; + } + } + } + + inline void RemoveEdge(FEdge *iEdge) + { + for (vector::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& getVertexList() + { + return _verticesList; + } + + /*! Returns the list of FEdges of the Shape. */ + inline vector& getEdgeList() + { + return _edgesList; + } + + inline vector& getChains() + { + return _chains; + } + + /*! Returns the bounding box of the shape. */ + inline const BBox& 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& 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; + } + + /* 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 list of materials for the shape */ + inline void setFrsMaterials(const vector& iMaterials) + { + _FrsMaterials = iMaterials; + } + + inline void setViewShape(ViewShape *iShape) + { + _ViewShape = iShape; + } + + inline void setImportance(float importance) + { + _importance = importance; + } }; -#endif // 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 6327956ca80..06cbd85d863 100644 --- a/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp +++ b/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp @@ -1,163 +1,191 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/** \file blender/freestyle/intern/view_map/SilhouetteGeomEngine.cpp + * \ingroup freestyle + * \brief Class to perform all geometric operations dedicated to silhouette. That, for example, implies that + * this geom engine has as member data the viewpoint, transformations, projections... + * \author Stephane Grabli + * \date 03/09/2002 + */ #include "Silhouette.h" #include "SilhouetteGeomEngine.h" + #include "../geometry/GeomUtils.h" using namespace std; -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}}; -real SilhouetteGeomEngine::_projectionMatrix[4][4] = {{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}}; -int SilhouetteGeomEngine::_viewport[4] = {1,1,1,1}; // the viewport +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} +}; +real SilhouetteGeomEngine::_projectionMatrix[4][4] = { + {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} +}; +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}}; -real SilhouetteGeomEngine::_glModelViewMatrix[4][4] = {{1,0,0,0}, - {0,1,0,0}, - {0,0,1,0}, - {0,0,0,1}}; + +real SilhouetteGeomEngine::_glProjectionMatrix[4][4] = { + {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} +}; real SilhouetteGeomEngine::_znear = 0.0; real SilhouetteGeomEngine::_zfar = 100.0; -bool SilhouetteGeomEngine::_isOrthographicProjection = false; +bool SilhouetteGeomEngine::_isOrthographicProjection = false; -SilhouetteGeomEngine * SilhouetteGeomEngine::_pInstance = 0; +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]; - - for(i=0; i<4; i++){ - for(j=0; j<4; j++) - { - _modelViewMatrix[i][j] = iModelViewMatrix[j][i]; - _glModelViewMatrix[i][j] = iModelViewMatrix[i][j]; - } - } + 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++) { + _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++) - { - _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++){ - _viewport[i] = iViewport[i]; - } - _Focal = iFocal; + for (i = 0; i < 4; i++) { + _viewport[i] = iViewport[i]; + } + _Focal = iFocal; _isOrthographicProjection = (iProjectionMatrix[3][3] != 0.0); } -void SilhouetteGeomEngine::setFrustum(real iZNear, real iZFar) +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)); +void SilhouetteGeomEngine::retrieveViewport(int viewport[4]) +{ + memcpy(viewport, _viewport, 4 * sizeof(int)); } -//#define HUGE 1e9 + +//#define HUGE 1.0e9 void SilhouetteGeomEngine::ProjectSilhouette(vector& ioVertices) { - Vec3r newPoint; - // real min=HUGE; - // real max=-HUGE; - vector::iterator sv, svend; - const real depth = _zfar - _znear; - const real fac = (depth < 1e-6) ? 1.0 : 1.0 / depth; - - for(sv=ioVertices.begin(), svend=ioVertices.end(); - sv!=svend; - sv++) - { - GeomUtils::fromWorldToImage((*sv)->point3D(), newPoint, _modelViewMatrix, _projectionMatrix, _viewport); - newPoint[2] = (-newPoint[2]-_znear) * fac; // normalize Z between 0 and 1 - (*sv)->setPoint2D(newPoint); - //cerr << (*sv)->point2d().z() << " "; - // real d=(*sv)->point2d()[2]; - // if (d>max) max =d; - // if (dpoint2d()); - // (*sv)->setPoint2D(Vec3r(P[0], P[1], 1.0-(P[2]-min)/(max-min))); - // //cerr<<(*sv)->point2d()[2]<<" "; - // } + Vec3r newPoint; +#if 0 + real min = HUGE; + real max = -HUGE; +#endif + vector::iterator sv, svend; + const real depth = _zfar - _znear; + const real fac = (depth < 1.0e-6) ? 1.0 : 1.0 / depth; + + for (sv = ioVertices.begin(), svend = ioVertices.end(); sv != svend; sv++) { + GeomUtils::fromWorldToImage((*sv)->point3D(), newPoint, _modelViewMatrix, _projectionMatrix, _viewport); + newPoint[2] = (-newPoint[2] - _znear) * fac; // normalize Z between 0 and 1 + (*sv)->setPoint2D(newPoint); +#if 0 + cerr << (*sv)->point2d().z() << " "; + real d = (*sv)->point2d()[2]; + if (d > max) + max =d; + if (d < min) + min =d; +#endif + } +#if 0 + for (sv = ioVertices.begin(), svend = ioVertices.end(); sv != svend; sv++) { + Vec3r P((*sv)->point2d()); + (*sv)->setPoint2D(Vec3r(P[0], P[1], 1.0 - (P[2] - min) / (max - min))); + //cerr << (*sv)->point2d()[2] << " "; + } +#endif } -void SilhouetteGeomEngine::ProjectSilhouette(SVertex* ioVertex) +void SilhouetteGeomEngine::ProjectSilhouette(SVertex *ioVertex) { - Vec3r newPoint; - // real min=HUGE; - // real max=-HUGE; - vector::iterator sv, svend; - const real depth = _zfar - _znear; - const real fac = (depth < 1e-6) ? 1.0 : 1.0 / depth; - GeomUtils::fromWorldToImage(ioVertex->point3D(), newPoint, _modelViewMatrix, _projectionMatrix, _viewport); - newPoint[2] = (-newPoint[2]-_znear) * fac; // normalize Z between 0 and 1 - ioVertex->setPoint2D(newPoint); + Vec3r newPoint; +#if 0 + real min = HUGE; + real max = -HUGE; + vector::iterator sv, svend; +#endif + const real depth = _zfar - _znear; + const real fac = (depth < 1.0e-6) ? 1.0 : 1.0 / depth; + GeomUtils::fromWorldToImage(ioVertex->point3D(), newPoint, _modelViewMatrix, _projectionMatrix, _viewport); + newPoint[2] = (-newPoint[2] - _znear) * fac; // normalize Z between 0 and 1 + ioVertex->setPoint2D(newPoint); } real SilhouetteGeomEngine::ImageToWorldParameter(FEdge *fe, real t) { - if( _isOrthographicProjection ) + if (_isOrthographicProjection) return t; - // we need to compute for each parameter t the corresponding - // parameter T which gives the intersection in 3D. + // 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 @@ -184,44 +212,48 @@ real SilhouetteGeomEngine::ImageToWorldParameter(FEdge *fe, real t) real m22 = _projectionMatrix[1][1]; real m23 = _projectionMatrix[1][2]; - if (fabs(ABc[0]) > 1e-6) { - + 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) < 1e-6) + if (fabs(denom) < 1.0e-6) goto iter; Ic[0] = -beta * (Ir[0] + m13) / denom; -// Ic[1] = -(Ir[1] + m23) * (alpha * Ic[0] + beta) / m22; -// Ic[2] = alpha * (Ic[0] - Ac[0]) + Ac[2]; +#if 0 + 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]) > 1e-6) { - + } + 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) < 1e-6) + if (fabs(denom) < 1.0e-6) goto iter; Ic[1] = -beta * (Ir[1] + m23) / denom; -// Ic[0] = -(Ir[0] + m13) * (alpha * Ic[1] + beta) / m11; -// Ic[2] = alpha * (Ic[1] - Ac[1]) + Ac[2]; +#if 0 + 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]) > 1e-6) { + } + 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 { + } + 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 = 1e-6; + 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); @@ -235,15 +267,30 @@ iter: bool x_coords, less_than; 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; } + if (Pi[0] < Ii[0]) + T_sta = T; + else + T_end = T; } - } else { + 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 (Pi[1] < Ii[1]) + T_sta = T; + else + T_end = T; + } + else { + if (Pi[1] > Ii[1]) + T_sta = T; + else + T_end = T; } } } @@ -258,15 +305,11 @@ iter: bool x_coords, less_than; } Vec3r SilhouetteGeomEngine::WorldToImage(const Vec3r& M) - { - - const real depth = _zfar - _znear; - const real fac = (depth < 1e-6) ? 1.0 : 1.0 / depth; - Vec3r newPoint; - GeomUtils::fromWorldToImage(M, newPoint, _transform, _viewport); - newPoint[2] = (-newPoint[2]-_znear) * fac; // normalize Z between 0 and 1 - return newPoint; - + const real depth = _zfar - _znear; + const real fac = (depth < 1.0e-6) ? 1.0 : 1.0 / depth; + Vec3r newPoint; + GeomUtils::fromWorldToImage(M, newPoint, _transform, _viewport); + newPoint[2] = (-newPoint[2] - _znear) * fac; // normalize Z between 0 and 1 + return newPoint; } - diff --git a/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.h b/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.h index 5bd89f8a162..d6ee159fe88 100644 --- a/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.h +++ b/source/blender/freestyle/intern/view_map/SilhouetteGeomEngine.h @@ -1,41 +1,46 @@ -// -// Filename : SilhouetteGeomEngine.h -// Author(s) : Stephane Grabli -// Purpose : Class to perform all geometric operations dedicated -// to silhouette. That, for example, implies that -// this geom engine has as member data the viewpoint, -// transformations, projections... -// Date of creation : 03/09/2002 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef SILHOUETTEGEOMENGINE_H -# define SILHOUETTEGEOMENGINE_H - -# include -# include "../system/FreestyleConfig.h" -# include "../geometry/Geom.h" +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_SILHOUETTE_GEOM_ENGINE_H__ +#define __FREESTYLE_SILHOUETTE_GEOM_ENGINE_H__ + +/** \file blender/freestyle/intern/view_map/SilhouetteGeomEngine.h + * \ingroup freestyle + * \brief Class to perform all geometric operations dedicated to silhouette. That, for example, implies that + * this geom engine has as member data the viewpoint, transformations, projections... + * \author Stephane Grabli + * \date 03/09/2002 + */ + +#include + +#include "../geometry/Geom.h" + +#include "../system/FreestyleConfig.h" using namespace Geometry; @@ -45,79 +50,87 @@ class FEdge; class LIB_VIEW_MAP_EXPORT SilhouetteGeomEngine { private: - static Vec3r _Viewpoint; // The viewpoint under which the silhouette has to be computed - static real _translation[3]; - static real _modelViewMatrix[4][4]; // the model view matrix (_modelViewMatrix[i][j] means element of line i and column j) - static real _projectionMatrix[4][4]; // the projection matrix (_projectionMatrix[i][j] means element of line i and column j) - static real _transform[4][4]; // the global transformation from world to screen (projection included) (_transform[i][j] means element of line i and column j) - static int _viewport[4]; // the viewport - static real _Focal; - - static real _znear; - static real _zfar; - - static real _glProjectionMatrix[4][4]; // GL style (column major) projection matrix - static real _glModelViewMatrix[4][4]; // GL style (column major) model view matrix - -static bool _isOrthographicProjection; - - - static SilhouetteGeomEngine *_pInstance; + // 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(0 == _pInstance) - { - _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& 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); + /*! retrieves an instance on the singleton */ + static SilhouetteGeomEngine *getInstance() + { + if(0 == _pInstance) { + _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& 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); }; -#endif // SILHOUETTEGEOMENGINE_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 c1647050d0d..1052965d472 100644 --- a/source/blender/freestyle/intern/view_map/SphericalGrid.cpp +++ b/source/blender/freestyle/intern/view_map/SphericalGrid.cpp @@ -1,36 +1,41 @@ -// -// Filename : SphericalGrid.h -// Author(s) : Alexander Beels -// Purpose : Class to define a cell grid surrounding -// the projected image of a scene -// Date of creation : 2010-12-19 -// -/////////////////////////////////////////////////////////////////////////////// - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/freestyle/intern/view_map/SphericalGrid.cpp + * \ingroup freestyle + * \brief Class to define a cell grid surrounding the projected image of a scene + * \author Alexander Beels + * \date 2010-12-19 + */ -#include "SphericalGrid.h" - -#include #include +#include + +#include "SphericalGrid.h" using namespace std; @@ -42,11 +47,12 @@ using namespace std; // 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) { +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; @@ -54,11 +60,14 @@ void SphericalGrid::Cell::setDimensions(real x, real y, real sizeX, real sizeY) boundary[3] = y + sizeY + epsilon; } -bool SphericalGrid::Cell::compareOccludersByShallowestPoint (const SphericalGrid::OccluderData* a, const SphericalGrid::OccluderData* b) { +bool SphericalGrid::Cell::compareOccludersByShallowestPoint(const SphericalGrid::OccluderData *a, + const SphericalGrid::OccluderData *b) +{ return a->shallowest < b->shallowest; } -void SphericalGrid::Cell::indexPolygons() { +void SphericalGrid::Cell::indexPolygons() +{ // Sort occluders by their shallowest points. sort(faces.begin(), faces.end(), compareOccludersByShallowestPoint); } @@ -66,30 +75,29 @@ void SphericalGrid::Cell::indexPolygons() { // Iterator ////////////////// -SphericalGrid::Iterator::Iterator (SphericalGrid& grid, Vec3r& center, real epsilon) - : _target(SphericalGrid::Transform::sphericalProjection(center)), - _foundOccludee(false) +SphericalGrid::Iterator::Iterator(SphericalGrid& grid, Vec3r& center, real epsilon) +: _target(SphericalGrid::Transform::sphericalProjection(center)), _foundOccludee(false) { // Find target cell _cell = grid.findCell(_target); - #if sphericalgridlogging == 1 - 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 SPHERICAL_GRID_LOGGING + 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(); } -SphericalGrid::Iterator::~Iterator () {} +SphericalGrid::Iterator::~Iterator() {} // SphericalGrid ///////////////// -SphericalGrid::SphericalGrid(OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap, Vec3r& viewpoint, bool enableQI) - : _viewpoint(viewpoint), - _enableQI(enableQI) +SphericalGrid::SphericalGrid(OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap, + Vec3r& viewpoint, bool enableQI) +: _viewpoint(viewpoint), _enableQI(enableQI) { cout << "Generate Cell structure" << endl; // Generate Cell structure @@ -103,10 +111,10 @@ SphericalGrid::SphericalGrid(OccluderSource& source, GridDensityProvider& densit cout << "Ready to use SphericalGrid" << endl; } -SphericalGrid::~SphericalGrid () { -} +SphericalGrid::~SphericalGrid() {} -void SphericalGrid::assignCells (OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap) { +void SphericalGrid::assignCells(OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap) +{ _cellSize = density.cellSize(); _cellsX = density.cellsX(); _cellsY = density.cellsY(); @@ -115,20 +123,19 @@ void SphericalGrid::assignCells (OccluderSource& source, GridDensityProvider& de // 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 ) { + 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() ) { + 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 ) { + if (_cells[i * _cellsY + j] == NULL) { // This is an uninitialized cell - real x, y, width, height; x = _cellOrigin[0] + _cellSize * i; @@ -145,22 +152,23 @@ void SphericalGrid::assignCells (OccluderSource& source, GridDensityProvider& de } } -void SphericalGrid::distributePolygons (OccluderSource& source) { +void SphericalGrid::distributePolygons(OccluderSource& source) +{ unsigned long nFaces = 0; unsigned long nKeptFaces = 0; - for ( source.begin(); source.isValid(); source.next() ) { - OccluderData* occluder = NULL; + for (source.begin(); source.isValid(); source.next()) { + OccluderData *occluder = NULL; try { - if ( insertOccluder(source, occluder) ) { + 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 + } + 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; @@ -170,46 +178,53 @@ void SphericalGrid::distributePolygons (OccluderSource& source) { cout << "Distributed " << nFaces << " occluders. Retained " << nKeptFaces << "." << endl; } -void SphericalGrid::reorganizeCells () { +void SphericalGrid::reorganizeCells() +{ // Sort the occluders by shallowest point - for ( vector::iterator i = _cells.begin(), end = _cells.end(); i != end; ++i ) { - if ( *i != NULL ) { + for (vector::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)); } -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]; } -bool SphericalGrid::orthographicProjection () const { +bool SphericalGrid::orthographicProjection() const +{ return false; } -const Vec3r& SphericalGrid::viewpoint() const { +const Vec3r& SphericalGrid::viewpoint() const +{ return _viewpoint; } -bool SphericalGrid::enableQI() const { +bool SphericalGrid::enableQI() const +{ 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); } -Vec3r SphericalGrid::Transform::sphericalProjection(const Vec3r& M) { +Vec3r SphericalGrid::Transform::sphericalProjection(const Vec3r& M) +{ Vec3r newPoint; newPoint[0] = ::atan(M[0] / M[2]); @@ -218,4 +233,3 @@ Vec3r SphericalGrid::Transform::sphericalProjection(const Vec3r& M) { return newPoint; } - diff --git a/source/blender/freestyle/intern/view_map/SphericalGrid.h b/source/blender/freestyle/intern/view_map/SphericalGrid.h index 55cdee19a80..0f369b4b686 100644 --- a/source/blender/freestyle/intern/view_map/SphericalGrid.h +++ b/source/blender/freestyle/intern/view_map/SphericalGrid.h @@ -1,78 +1,86 @@ -// -// Filename : SphericalGrid.h -// Author(s) : Alexander Beels -// Purpose : Class to define a cell grid surrounding -// the projected image of a scene -// Date of creation : 2010-12-19 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef SPHERICALGRID_H -#define SPHERICALGRID_H - -#define sphericalgridlogging 0 - -// I would like to avoid using deque because including ViewMap.h and or -// separately results in redefinitions of identifiers. ViewMap.h already includes -// so it should be a safe fall-back. +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_SPHERICAL_GRID_H__ +#define __FREESTYLE_SPHERICAL_GRID_H__ + +/** \file blender/freestyle/intern/view_map/SphericalGrid.h + * \ingroup freestyle + * \brief Class to define a cell grid surrounding the projected image of a scene + * \author Alexander Beels + * \date 2010-12-19 + */ + +#define SPHERICAL_GRID_LOGGING FALSE + +// I would like to avoid using deque because including ViewMap.h and or separately results in +// redefinitions of identifiers. ViewMap.h already includes so it should be a safe fall-back. //#include //#include + +#include "GridDensityProvider.h" +#include "OccluderSource.h" #include "ViewMap.h" -#include "../winged_edge/WEdge.h" + #include "../geometry/Polygon.h" -#include "../system/PointerSequence.h" #include "../geometry/BBox.h" #include "../geometry/GridHelpers.h" -#include "OccluderSource.h" -#include "GridDensityProvider.h" + +#include "../system/PointerSequence.h" + +#include "../winged_edge/WEdge.h" class SphericalGrid { public: // Helper classes - struct OccluderData { + 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; + // 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; }; private: - struct Cell { + struct Cell + { // Can't store Cell in a vector without copy and assign //Cell(const Cell& other); - //Cell& operator= (const Cell& other); + //Cell& operator=(const Cell& other); - explicit Cell (); - ~Cell (); + explicit Cell(); + ~Cell(); - static bool compareOccludersByShallowestPoint (const OccluderData* a, const OccluderData* b); + 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); @@ -84,43 +92,37 @@ private: }; 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 { + /*! 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=1e-06); - ~Iterator (); - void initBeforeTarget (); - void initAfterTarget (); - void nextOccluder (); - void nextOccludee (); + 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(); + WFace *getWFace() const; + Polygon3r *getCameraSpacePolygon(); void reportDepth(Vec3r origin, Vec3r u, real t); private: bool testOccluder(bool wantOccludee); void markCurrentOccludeeCandidate(real depth); - Cell* _cell; + Cell *_cell; Vec3r _target; bool _foundOccludee; real _occludeeDepth; @@ -128,33 +130,35 @@ public: vector::iterator _current, _occludeeCandidate; }; - class Transform : public GridHelpers::Transform { + class Transform : public GridHelpers::Transform + { public: - explicit Transform (); - explicit Transform (Transform& other); - Vec3r operator() (const Vec3r& point) const; + 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); + SphericalGrid& operator=(const SphericalGrid& other); + public: - explicit SphericalGrid (OccluderSource& source, GridDensityProvider& density, ViewMap *viewMap, Vec3r& viewpoint, bool enableQI); + 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 + // 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); + Cell *findCell(const Vec3r& point); // Accessors: bool orthographicProjection() const; @@ -176,51 +180,52 @@ private: bool _enableQI; }; -inline void SphericalGrid::Iterator::initBeforeTarget () { +inline void SphericalGrid::Iterator::initBeforeTarget() +{ _current = _cell->faces.begin(); - while ( _current != _cell->faces.end() && ! testOccluder(false) ) { + while (_current != _cell->faces.end() && !testOccluder(false)) { ++_current; } } -inline void SphericalGrid::Iterator::initAfterTarget () { - if ( _foundOccludee ) { - #if sphericalgridlogging == 1 +inline void SphericalGrid::Iterator::initAfterTarget() +{ + if (_foundOccludee) { + #if SPHERICAL_GRID_LOGGING std::cout << "\tStarting occludee search from occludeeCandidate at depth " << _occludeeDepth << std::endl; #endif _current = _occludeeCandidate; return; } - #if sphericalgridlogging == 1 + #if SPHERICAL_GRID_LOGGING std::cout << "\tStarting occludee search from current position" << std::endl; #endif - while ( _current != _cell->faces.end() && ! testOccluder(true) ) { + while (_current != _cell->faces.end() && !testOccluder(true)) { ++_current; } } -inline bool SphericalGrid::Iterator::testOccluder (bool wantOccludee) { +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. + 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 sphericalgridlogging == 1 + #if SPHERICAL_GRID_LOGGING std::cout << "\tTesting occluder " << (*_current)->poly.getVertices()[0]; - for ( unsigned i = 1; i < (*_current)->poly.getVertices().size(); ++i ) { + 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 sphericalgridlogging == 1 + if (_foundOccludee && (*_current)->shallowest > _occludeeDepth) { + #if SPHERICAL_GRID_LOGGING std::cout << "\t\tAborting: shallowest > occludeeCandidate->deepest" << std::endl; #endif _current = _cell->faces.end(); @@ -230,16 +235,17 @@ inline bool SphericalGrid::Iterator::testOccluder (bool wantOccludee) { } // Specific continue or stop conditions when searching for each type - if ( wantOccludee ) { - if ( (*_current)->deepest < _target[2] ) { - #if sphericalgridlogging == 1 + if (wantOccludee) { + if ((*_current)->deepest < _target[2]) { + #if SPHERICAL_GRID_LOGGING std::cout << "\t\tSkipping: shallower than target while looking for occludee" << std::endl; #endif return false; } - } else { - if ( (*_current)->shallowest > _target[2] ) { - #if sphericalgridlogging == 1 + } + else { + if ((*_current)->shallowest > _target[2]) { + #if SPHERICAL_GRID_LOGGING std::cout << "\t\tStopping: deeper than target while looking for occluder" << std::endl; #endif return true; @@ -251,70 +257,73 @@ inline bool SphericalGrid::Iterator::testOccluder (bool wantOccludee) { // 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 sphericalgridlogging == 1 + if (_target[0] < bbMin[0] || _target[0] > bbMax[0] || _target[1] < bbMin[1] || _target[1] > bbMax[1]) { + #if SPHERICAL_GRID_LOGGING std::cout << "\t\tSkipping: bounding box violation" << std::endl; #endif return false; } - // We've done all the corner cutting we can. - // Let the caller work out whether or not - // the geometry is correct. + // 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. +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(); - #if sphericalgridlogging == 1 + #if SPHERICAL_GRID_LOGGING std::cout << "\t\tReporting depth of occluder/ee: " << depth; #endif - if ( depth > _target[2] ) { - #if sphericalgridlogging == 1 + if (depth > _target[2]) { + #if SPHERICAL_GRID_LOGGING 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 ) { + if (! _foundOccludee || _occludeeDepth > depth) { markCurrentOccludeeCandidate(depth); } - } else { - #if sphericalgridlogging == 1 + } + else { + #if SPHERICAL_GRID_LOGGING std::cout << std::endl; #endif } } -inline void SphericalGrid::Iterator::nextOccluder () { - if ( _current != _cell->faces.end() ) { +inline void SphericalGrid::Iterator::nextOccluder() +{ + if (_current != _cell->faces.end()) { do { ++_current; - } while ( _current != _cell->faces.end() && ! testOccluder(false) ); + } while (_current != _cell->faces.end() && !testOccluder(false)); } } -inline void SphericalGrid::Iterator::nextOccludee () { - if ( _current != _cell->faces.end() ) { +inline void SphericalGrid::Iterator::nextOccludee() +{ + if (_current != _cell->faces.end()) { do { ++_current; - } while ( _current != _cell->faces.end() && ! testOccluder(true) ); + } while (_current != _cell->faces.end() && !testOccluder(true)); } } -inline bool SphericalGrid::Iterator::validBeforeTarget () { +inline bool SphericalGrid::Iterator::validBeforeTarget() +{ return _current != _cell->faces.end() && (*_current)->shallowest <= _target[2]; } -inline bool SphericalGrid::Iterator::validAfterTarget () { +inline bool SphericalGrid::Iterator::validAfterTarget() +{ return _current != _cell->faces.end(); } -inline void SphericalGrid::Iterator::markCurrentOccludeeCandidate(real depth) { - #if sphericalgridlogging == 1 +inline void SphericalGrid::Iterator::markCurrentOccludeeCandidate(real depth) +{ + #if SPHERICAL_GRID_LOGGING std::cout << "\t\tFound occludeeCandidate at depth " << depth << std::endl; #endif _occludeeCandidate = _current; @@ -322,18 +331,18 @@ inline void SphericalGrid::Iterator::markCurrentOccludeeCandidate(real depth) { _foundOccludee = true; } -inline WFace* SphericalGrid::Iterator::getWFace() const { +inline WFace *SphericalGrid::Iterator::getWFace() const +{ return (*_current)->face; } -inline Polygon3r* SphericalGrid::Iterator::getCameraSpacePolygon() { +inline Polygon3r *SphericalGrid::Iterator::getCameraSpacePolygon() +{ return &((*_current)->cameraSpacePolygon); } inline SphericalGrid::OccluderData::OccluderData (OccluderSource& source, Polygon3r& p) - : poly(p), - cameraSpacePolygon(source.getCameraSpacePolygon()), - face(source.getWFace()) +: 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 @@ -343,17 +352,18 @@ inline SphericalGrid::OccluderData::OccluderData (OccluderSource& source, Polygo // 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 i = 0; i < 2; ++i ) { + for (unsigned int i = 0; i < 2; ++i) { real t = cameraSpacePolygon.getVertices()[i].norm(); - if ( t > deepest ) { + if (t > deepest) { deepest = t; } } } -inline void SphericalGrid::Cell::checkAndInsert(OccluderSource& source, Polygon3r& poly, OccluderData*& occluder) { - if ( GridHelpers::insideProscenium (boundary, poly) ) { - if ( occluder == NULL) { +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); @@ -362,7 +372,8 @@ inline void SphericalGrid::Cell::checkAndInsert(OccluderSource& source, Polygon3 } } -inline bool SphericalGrid::insertOccluder(OccluderSource& source, OccluderData*& occluder) { +inline bool SphericalGrid::insertOccluder(OccluderSource& source, OccluderData*& occluder) +{ Polygon3r& poly(source.getGridSpacePolygon()); occluder = NULL; @@ -373,9 +384,9 @@ inline bool SphericalGrid::insertOccluder(OccluderSource& source, OccluderData*& getCellCoordinates(bbMin, startX, startY); getCellCoordinates(bbMax, endX, endY); - for ( unsigned i = startX; i <= endX; ++i ) { - for ( unsigned j = startY; j <= endY; ++j ) { - if ( _cells[i * _cellsY + j] != NULL ) { + 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); } } @@ -384,5 +395,4 @@ inline bool SphericalGrid::insertOccluder(OccluderSource& source, OccluderData*& return occluder != NULL; } -#endif // SPHERICALGRID_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 6b76c2512f0..e39181e335d 100644 --- a/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp +++ b/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp @@ -1,267 +1,298 @@ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/freestyle/intern/view_map/SteerbaleViewMap.cpp + * \ingroup freestyle + * \brief Convenient access to the steerable ViewMap to which any element of the ViewMap belongs to. + * \author Stephane Grabli + * \date 01/07/2003 + */ + +#include +//soc #include +//soc #include +#include #include "Silhouette.h" #include "SteerableViewMap.h" -#include "../image/ImagePyramid.h" -#include "../image/Image.h" -#include + #include "../geometry/Geom.h" -using namespace Geometry; -//soc #include -//soc #include -#include +#include "../image/ImagePyramid.h" +#include "../image/Image.h" extern "C" { #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" } -SteerableViewMap::SteerableViewMap(unsigned int nbOrientations){ - _nbOrientations = nbOrientations; - _bound = cos(M_PI/(float)_nbOrientations); - for(unsigned i=0; i<_nbOrientations; ++i){ - _directions.push_back(Vec2d(cos((float)i*M_PI/(float)_nbOrientations), sin((float)i*M_PI/(float)_nbOrientations))); - } - Build(); +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(); } -void SteerableViewMap::Build(){ - _imagesPyramids = new ImagePyramid*[_nbOrientations+1]; // one more map to store the complete visible VM - memset((_imagesPyramids),0,(_nbOrientations+1)*sizeof(ImagePyramid*)); +void SteerableViewMap::Build() +{ + _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){ - _nbOrientations = iBrother._nbOrientations; - unsigned 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+1;++i) - _imagesPyramids[i] = new GaussianPyramid(*(dynamic_cast(iBrother._imagesPyramids[i]))); +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 + 1; ++i) + _imagesPyramids[i] = new GaussianPyramid(*(dynamic_cast(iBrother._imagesPyramids[i]))); } -SteerableViewMap::~SteerableViewMap(){ - Clear(); +SteerableViewMap::~SteerableViewMap() +{ + Clear(); } -void SteerableViewMap::Clear(){ - unsigned i; - if(_imagesPyramids){ - for(i=0; i<=_nbOrientations; ++i){ - if(_imagesPyramids[i]) - delete (_imagesPyramids)[i]; - } - delete [] _imagesPyramids; - _imagesPyramids = 0; - } - if(!_mapping.empty()){ - for(map::iterator m=_mapping.begin(), mend=_mapping.end(); - m!=mend; - ++m){ - delete [] (*m).second; - } - _mapping.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::iterator m = _mapping.begin(), mend = _mapping.end(); m != mend; ++m) { + delete[] (*m).second; + } + _mapping.clear(); + } } -void SteerableViewMap::Reset(){ - Clear(); - Build(); +void SteerableViewMap::Reset() +{ + Clear(); + Build(); } -double SteerableViewMap::ComputeWeight(const Vec2d& dir, unsigned i){ - double dotp = fabs(dir*_directions[i]); - if(dotp < _bound) - return 0; - if(dotp>1) - dotp = 1; +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; - 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::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; - } - Vec3r o2d3 = iFEdge->orientation2d(); - Vec2r o2d2(o2d3.x(), o2d3.y()); - real norm = o2d2.norm(); - if(norm < 1e-6){ - return res; - } - o2d2/=norm; +double *SteerableViewMap::AddFEdge(FEdge *iFEdge) +{ + unsigned i; + unsigned id = iFEdge->getId().getFirst(); + map::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; + for (i = 0; i < _nbOrientations; ++i) { + res[i] = ComputeWeight(o2d2, i); + } + _mapping[id] = res; + return res; } -unsigned SteerableViewMap::getSVMNumber(const Vec2f& orient){ - Vec2f dir(orient); - //soc unsigned res = 0; - real norm = dir.norm(); - if(norm < 1e-6){ - return _nbOrientations+1; - } - dir/=norm; - double maxw = 0.f; - unsigned winner = _nbOrientations+1; - for(unsigned i=0; i<_nbOrientations; ++i){ - double w = ComputeWeight(dir, i); - if(w>maxw){ - maxw = w; - winner = i; - } - } - return winner; +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; } - -unsigned SteerableViewMap::getSVMNumber(unsigned id){ - map::iterator o = _mapping.find(id); - if(o!=_mapping.end()){ - double* wvalues= (*o).second; - double maxw = 0.f; - 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; +unsigned SteerableViewMap::getSVMNumber(unsigned id) +{ + map::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){ - for(unsigned 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; - } +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; + } } -float SteerableViewMap::readSteerableViewMapPixel(unsigned iOrientation, int iLevel, int x, int y){ - ImagePyramid *pyramid = _imagesPyramids[iOrientation]; - if(pyramid==0){ - cout << "Warning: this steerable ViewMap level doesn't exist" << endl; - return 0; - } - if((x<0) || (x>=pyramid->width()) || (y<0) || (y>=pyramid->height())) - return 0; - //float v = pyramid->pixel(x,pyramid->height()-1-y,iLevel)*255.f; - float v = pyramid->pixel(x,pyramid->height()-1-y,iLevel)/32.f; // 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. - return v; +float SteerableViewMap::readSteerableViewMapPixel(unsigned iOrientation, int iLevel, int x, int y) +{ + ImagePyramid *pyramid = _imagesPyramids[iOrientation]; + if (pyramid == 0) { + cout << "Warning: this steerable ViewMap level doesn't exist" << endl; + return 0; + } + 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); +float SteerableViewMap::readCompleteViewMapPixel(int iLevel, int x, int y) +{ + return readSteerableViewMapPixel(_nbOrientations, iLevel, x, y); } -unsigned int SteerableViewMap::getNumberOfPyramidLevels() const{ - if(_imagesPyramids[0]) - return _imagesPyramids[0]->getNumberOfLevels(); - return 0; +unsigned int SteerableViewMap::getNumberOfPyramidLevels() const +{ + if (_imagesPyramids[0]) + return _imagesPyramids[0]->getNumberOfLevels(); + return 0; } -void SteerableViewMap::saveSteerableViewMap() const { - for(unsigned 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); +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 QString base("SteerableViewMap"); - string base("SteerableViewMap"); - stringstream filename; - - for(int j=0; j<_imagesPyramids[i]->getNumberOfLevels(); ++j){ //soc - float coeff = 1;//1/255.f; //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;ypixel(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.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= PNG; - IMB_saveiff(ibuf, const_cast(filename.str().c_str()), 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; //100*255;//*pow(2,j); - // QImage qtmp(ow, oh, 32); - // for(unsigned y=0;ypixel(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"); - // } - // - } + //soc qtmp.save(base+QString::number(i)+"-"+QString::number(j)+".png", "PNG"); + filename << base; + filename << i << "-" << j << ".png"; + ibuf->ftype = PNG; + IMB_saveiff(ibuf, const_cast(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"); + } +#endif + } } diff --git a/source/blender/freestyle/intern/view_map/SteerableViewMap.h b/source/blender/freestyle/intern/view_map/SteerableViewMap.h index fe7c2493752..a4a67c3fa7e 100644 --- a/source/blender/freestyle/intern/view_map/SteerableViewMap.h +++ b/source/blender/freestyle/intern/view_map/SteerableViewMap.h @@ -1,38 +1,46 @@ -// -// Filename : SteerbaleViewMap.h -// Author(s) : Stephane Grabli -// Purpose : Convenient access to the steerable ViewMap -// to which any element of the ViewMap belongs to. -// Date of creation : 01/07/2003 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// -#ifndef STEERABLEVIEWMAP_H -# define STEERABLEVIEWMAP_H - +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_STEERABLE_VIEW_MAP_H__ +#define __FREESTYLE_STEERABLE_VIEW_MAP_H__ + +/** \file blender/freestyle/intern/view_map/SteerbaleViewMap.h + * \ingroup freestyle + * \brief Convenient access to the steerable ViewMap to which any element of the ViewMap belongs to. + * \author Stephane Grabli + * \date 01/07/2003 + */ + #include -#include "../system/FreestyleConfig.h" + #include "../geometry/Geom.h" + +#include "../system/FreestyleConfig.h" + using namespace Geometry; using namespace std; @@ -40,114 +48,107 @@ using namespace std; class FEdge; class ImagePyramid; 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 + +/*! 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 LIB_VIEW_MAP_EXPORT SteerableViewMap{ +class LIB_VIEW_MAP_EXPORT SteerableViewMap +{ protected: - map _mapping; // for each vector the list of nbOrientations weigths corresponding to its contributions to the nbOrientations directional maps - unsigned _nbOrientations; - ImagePyramid **_imagesPyramids; // the pyramids of images storing the different SVM + // for each vector the list of nbOrientations weigths corresponding to its contributions + // to the nbOrientations directional maps + map _mapping; + unsigned _nbOrientations; + ImagePyramid **_imagesPyramids; // the pyramids of images storing the different SVM - // internal - double _bound; // cos(Pi/N) - vector _directions; + // internal + double _bound; // cos(Pi/N) + vector _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 weigths 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 intersted 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 constituing 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. - * \params 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.f); - - /*! 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 ; + 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 weigths 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 intersted 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 constituing 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. + * \params 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(); - - + void Clear(); + void Build(); }; -#endif // STEERABLEVIEWMAP_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 4cb48d6613e..f3ab3c6d94a 100644 --- a/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp +++ b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp @@ -1,736 +1,753 @@ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp + * \ingroup freestyle + * \brief Class to build view edges and the underlying chains of feature edges... + * \author Stephane Grabli + * \date 27/10/2003 + */ -#include "ViewMap.h" +#include + +#include "SilhouetteGeomEngine.h" #include "ViewEdgeXBuilder.h" +#include "ViewMap.h" + #include "../winged_edge/WXEdge.h" -#include "SilhouetteGeomEngine.h" -#include using namespace std; -void ViewEdgeXBuilder::Init(ViewShape *oVShape){ - if(0 == oVShape) - return; - - // for design conveniance, we store the current SShape. - _pCurrentSShape = oVShape->sshape(); - if(0 == _pCurrentSShape) - return; - - _pCurrentVShape = oVShape; - - // Reset previous data - //-------------------- - if(!_SVertexMap.empty()) - _SVertexMap.clear(); +void ViewEdgeXBuilder::Init(ViewShape *oVShape) +{ + if (0 == oVShape) + return; + + // for design conveniance, we store the current SShape. + _pCurrentSShape = oVShape->sshape(); + if (0 == _pCurrentSShape) + return; + + _pCurrentVShape = oVShape; + + // Reset previous data + //-------------------- + if (!_SVertexMap.empty()) + _SVertexMap.clear(); } -void ViewEdgeXBuilder::BuildViewEdges( WXShape *iWShape, ViewShape *oVShape, - vector& ioVEdges, - vector& ioVVertices, - vector& ioFEdges, - vector& ioSVertices){ - // Reinit structures - Init(oVShape); - - ViewEdge *vedge ; - // Let us build the smooth stuff - //---------------------------------------- - // We parse all faces to find the ones - // that contain smooth edges - vector& wfaces = iWShape->GetFaceList(); - vector::iterator wf, wfend; - WXFace *wxf; - for(wf=wfaces.begin(), wfend=wfaces.end(); - wf!=wfend; - wf++){ - wxf = dynamic_cast(*wf); - if(false == ((wxf))->hasSmoothEdges()) // does it contain at least one smooth edge ? - continue; - // parse all smooth layers: - vector& smoothLayers = wxf->getSmoothLayers(); - for(vector::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 = BuildSmoothViewEdge(OWXFaceLayer(*sl, true)); - } - } - - // Now let's build sharp view edges: - //---------------------------------- - // Reset all userdata for WXEdge structure - //---------------------------------------- - //iWShape->ResetUserData(); - - WXEdge * wxe; - vector& wedges = iWShape->getEdgeList(); - // - //------------------------------ - for(vector::iterator we=wedges.begin(),weend=wedges.end(); - we!=weend; - we++){ - wxe = dynamic_cast(*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& newedges = _pCurrentSShape->getEdgeList(); - vector& newVertices = _pCurrentSShape->getVertexList(); - vector& newVVertices = _pCurrentVShape->vertices(); - vector& 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()); +void ViewEdgeXBuilder::BuildViewEdges(WXShape *iWShape, ViewShape *oVShape, vector& ioVEdges, + vector& ioVVertices, vector& ioFEdges, + vector& ioSVertices) +{ + // Reinit structures + Init(oVShape); + + ViewEdge *vedge; + // Let us build the smooth stuff + //---------------------------------------- + // We parse all faces to find the ones that contain smooth edges + vector& wfaces = iWShape->GetFaceList(); + vector::iterator wf, wfend; + WXFace *wxf; + for (wf = wfaces.begin(), wfend = wfaces.end(); wf != wfend; wf++) { + wxf = dynamic_cast(*wf); + if (false == ((wxf))->hasSmoothEdges()) // does it contain at least one smooth edge ? + continue; + // parse all smooth layers: + vector& smoothLayers = wxf->getSmoothLayers(); + for (vector::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 = BuildSmoothViewEdge(OWXFaceLayer(*sl, true)); + } + } + // Now let's build sharp view edges: + //---------------------------------- + // Reset all userdata for WXEdge structure + //---------------------------------------- + //iWShape->ResetUserData(); + + WXEdge *wxe; + vector& wedges = iWShape->getEdgeList(); + //------------------------------ + for (vector::iterator we = wedges.begin(), weend = wedges.end(); we != weend; we++) { + wxe = dynamic_cast(*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& newedges = _pCurrentSShape->getEdgeList(); + vector& newVertices = _pCurrentSShape->getVertexList(); + vector& newVVertices = _pCurrentVShape->vertices(); + vector& 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){ - // Find first edge: - OWXFaceLayer first = iFaceLayer; - OWXFaceLayer currentFace = first; - - // bidirectional chaining. - // first direction - list 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 = 0; - FEdge * fefirst = 0; - FEdge * fe = 0; - for(list::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::BuildSmoothViewEdge(const OWXFaceLayer& iFaceLayer) +{ + // Find first edge: + OWXFaceLayer first = iFaceLayer; + OWXFaceLayer currentFace = first; + + // bidirectional chaining. + // first direction + list 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::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) { - // 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; - OWXEdge currentWEdge = firstWEdge; - list edgesChain; +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; + OWXEdge currentWEdge = firstWEdge; + list 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 = 0; - FEdge * fefirst = 0; - FEdge * fe = 0; - for(list::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::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){ - WXFace *nextFace = 0; - 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(*f); - if((0 != nextFace) && (nextFace!=iFaceLayer.fl->getFace())){ - vector sameNatureLayers; - nextFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers); - if(sameNatureLayers.size() == 1) {// don't know - // maybe should test whether this face has - // also a vertex_edge configuration - WXFaceLayer * winner = sameNatureLayers[0]; - // check face mark continuity - if(winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark()) - return OWXFaceLayer(0,true); - if(woeend == winner->getSmoothEdge()->woea()->twin()) - return OWXFaceLayer(winner,true); - else - return OWXFaceLayer(winner,false); - } - } - ++f; - } - }else{ - nextFace = dynamic_cast(iFaceLayer.fl->getFace()->GetBordingFace(woeend)); - if(0 == nextFace) - return OWXFaceLayer(0,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(0,true); - vector sameNatureLayers; - nextFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers); - if((sameNatureLayers.empty()) || (sameNatureLayers.size() != 1)) // don't know how to deal with several edges of same nature on a single face - return OWXFaceLayer(0,true); - else{ - WXFaceLayer * winner = sameNatureLayers[0]; - // check face mark continuity - if(winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark()) - return OWXFaceLayer(0,true); - if(woeend == winner->getSmoothEdge()->woea()->twin()) - return OWXFaceLayer(winner,true); - else - return OWXFaceLayer(winner,false); - } - } - return OWXFaceLayer(0,true); +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(*f); + if ((0 != nextFace) && (nextFace != iFaceLayer.fl->getFace())) { + vector 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(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 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) { - WXFace *previousFace = 0; - 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(0,true); - bool found = false; - WVertex::face_iterator f=previousVertex->faces_begin(); - WVertex::face_iterator fend=previousVertex->faces_end(); - while((!found) && (f!=fend)){ - previousFace = dynamic_cast(*f); - if((0 != previousFace) && (previousFace!=iFaceLayer.fl->getFace())){ - vector sameNatureLayers; - previousFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers); - if(sameNatureLayers.size() == 1) {// don't know - // maybe should test whether this face has - // also a vertex_edge configuration - WXFaceLayer * winner = sameNatureLayers[0]; - // check face mark continuity - if(winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark()) - return OWXFaceLayer(0,true); - if(woebegin == winner->getSmoothEdge()->woeb()->twin()) - return OWXFaceLayer(winner,true); - else - return OWXFaceLayer(winner,false); - } - } - ++f; - } - }else{ - previousFace = dynamic_cast(iFaceLayer.fl->getFace()->GetBordingFace(woebegin)); - if(0 == previousFace) - return OWXFaceLayer(0,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(0,true); - vector sameNatureLayers; - previousFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers); - if((sameNatureLayers.empty()) || (sameNatureLayers.size() != 1)) // don't know how to deal with several edges of same nature on a single face - return OWXFaceLayer(0,true); - else{ - WXFaceLayer * winner = sameNatureLayers[0]; - // check face mark continuity - if(winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark()) - return OWXFaceLayer(0,true); - if(woebegin == winner->getSmoothEdge()->woeb()->twin()) - return OWXFaceLayer(winner,true); - else - return OWXFaceLayer(winner,false); - } - } - return OWXFaceLayer(0,true); +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(*f); + if ((0 != previousFace) && (previousFace!=iFaceLayer.fl->getFace())) { + vector 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(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 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){ - 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(woea->GetaVertex())->curvatures()), - *(dynamic_cast(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() < 1e-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(woeb->GetaVertex())->curvatures()), - *(dynamic_cast(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; +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(woea->GetaVertex())->curvatures()), + *(dynamic_cast(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(woeb->GetaVertex())->curvatures()), + *(dynamic_cast(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(0 == iFaceLayer) - return true; - if(iFaceLayer->userdata == 0) - return false; - return true; +bool ViewEdgeXBuilder::stopSmoothViewEdge(WXFaceLayer *iFaceLayer) +{ + if (0 == 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){ - if(Nature::NO_FEATURE == iEdge.e->nature()) - return OWXEdge(0, true); - - WVertex *v; - if(true == iEdge.order) - v = iEdge.e->GetbVertex(); - else - v = iEdge.e->GetaVertex(); - - if(((WXVertex*)v)->isFeature()) - return 0; - - - int faceMarks = retrieveFaceMarks(iEdge.e); - vector& vEdges = (v)->GetEdges(); - for(vector::iterator ve=vEdges.begin(),veend=vEdges.end(); - ve!=veend; - ve++){ - WXEdge *wxe = dynamic_cast(*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(0, true); +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& vEdges = (v)->GetEdges(); + for (vector::iterator ve = vEdges.begin(), veend = vEdges.end(); ve != veend; ve++) { + WXEdge *wxe = dynamic_cast(*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){ - if(Nature::NO_FEATURE == iEdge.e->nature()) - return OWXEdge(0, 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& vEdges = (v)->GetEdges(); - for(vector::iterator ve=vEdges.begin(),veend=vEdges.end(); - ve!=veend; - ve++){ - WXEdge *wxe = dynamic_cast(*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(0, true); +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& vEdges = (v)->GetEdges(); + for (vector::iterator ve = vEdges.begin(), veend = vEdges.end(); ve != veend; ve++) { + WXEdge *wxe = dynamic_cast(*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){ - SVertex *va, *vb; - FEdgeSharp *fe; - WXVertex *wxVA, *wxVB; - if(iwe.order){ - wxVA = (WXVertex*)iwe.e->GetaVertex(); - wxVB = (WXVertex*)iwe.e->GetbVertex(); - }else{ - wxVA = (WXVertex*)iwe.e->GetbVertex(); - wxVB = (WXVertex*)iwe.e->GetaVertex(); - } - // Make the 2 SVertex - va = MakeSVertex(wxVA->GetVertex(), true); - vb = MakeSVertex(wxVB->GetVertex(), 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 - // 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; +FEdge *ViewEdgeXBuilder::BuildSharpFEdge(FEdge *feprevious, const OWXEdge& iwe) +{ + SVertex *va, *vb; + FEdgeSharp *fe; + WXVertex *wxVA, *wxVB; + if (iwe.order) { + wxVA = (WXVertex *)iwe.e->GetaVertex(); + wxVB = (WXVertex *)iwe.e->GetbVertex(); + } + else { + wxVA = (WXVertex *)iwe.e->GetbVertex(); + wxVB = (WXVertex *)iwe.e->GetaVertex(); + } + // Make the 2 SVertex + va = MakeSVertex(wxVA->GetVertex(), true); + vb = MakeSVertex(wxVB->GetVertex(), 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(0 == iEdge) - return true; - if(iEdge->userdata == 0) - return false; - return true; +bool ViewEdgeXBuilder::stopSharpViewEdge(WXEdge *iEdge) +{ + if (0 == iEdge) + return true; + if (iEdge->userdata == 0) + return false; + return true; } -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 *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 * 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 *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; } -ViewVertex * ViewEdgeXBuilder::MakeViewVertex(SVertex *iSVertex){ - ViewVertex *vva = iSVertex->viewvertex(); - if(vva != 0) - return vva; - vva = new NonTVertex(iSVertex); - // Add the view vertex to the ViewShape svertex list: - _pCurrentVShape->AddVertex(vva); - return vva; +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; } - diff --git a/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.h b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.h index 744cc520b2b..2883919a852 100644 --- a/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.h +++ b/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.h @@ -1,73 +1,87 @@ -// -// Filename : ViewEdgeXBuilder.h -// Author(s) : Stephane Grabli -// Purpose : Class to build view edges and the underlying chains -// of feature edges... -// Date of creation : 27/10/2003 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef VIEWEDGEXBUILDER_H -# define VIEWEDGEXBUILDER_H - -# include -# include -# include - -// 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 -// # else -// # include -// # endif - -# include "../system/FreestyleConfig.h" -# include "../geometry/Geom.h" -# include "Interface1D.h" +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_VIEW_EDGE_X_BUILDER_H__ +#define __FREESTYLE_VIEW_EDGE_X_BUILDER_H__ + +/** \file blender/freestyle/intern/view_map/ViewEdgeXBuilder.h + * \ingroup freestyle + * \brief Class to build view edges and the underlying chains of feature edges... + * \author Stephane Grabli + * \date 27/10/2003 + */ + +#include +#include +#include + +#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 +#else +# include +#endif +#endif + +#include "Interface1D.h" + +#include "../geometry/Geom.h" + +#include "../system/FreestyleConfig.h" using namespace Geometry; using namespace std; 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<1e-06); - } +struct epsilonEquals +{ + bool operator()(const Vec3r& v1, const Vec3r& v2) const + { + real norm = (v1 - v2).norm(); + return (norm < 1.0e-06); + } }; @@ -75,47 +89,81 @@ struct epsilonEquals{ typedef map SVertexMap; class WXFaceLayer; + /*! class to describe an oriented smooth edge */ -class OWXFaceLayer{ +class OWXFaceLayer +{ public: - WXFaceLayer * fl; - bool order; - - OWXFaceLayer() {fl=0;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); - } + 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 WXEdge; + /*! class to describe an oriented sharp edge */ -class OWXEdge{ +class OWXEdge +{ public: - WXEdge * e; - bool order; - - OWXEdge() {e=0;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); - } + 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 WOEdge; @@ -126,93 +174,115 @@ class FEdge; class ViewVertex; class ViewEdge; class ViewShape; + class LIB_VIEW_MAP_EXPORT ViewEdgeXBuilder { protected: - int _currentViewId; // Id for view edges - int _currentFId; // Id for FEdges - int _currentSVertexId; // Id for SVertex + 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& ioVEdges, - std::vector& ioVVertices, - std::vector& ioFEdges, - std::vector& ioSVertices) ; - - /*! Builds a smooth view edge, starting the face iFace.*/ - ViewEdge * BuildSmoothViewEdge(const OWXFaceLayer& iFaceLayer); - - /*! Makes a sharp viewedge - */ - ViewEdge * BuildSharpViewEdge(const OWXEdge& iWEdge) ; + 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& ioVEdges, + std::vector& ioVVertices, std::vector& ioFEdges, + std::vector& 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; } + /*! 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; -}; + /*! Init the view edges building */ + virtual void Init(ViewShape *oVShape); -#endif + // 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; +}; +#endif // __FREESTYLE_VIEW_EDGE_X_BUILDER_H__ diff --git a/source/blender/freestyle/intern/view_map/ViewMap.cpp b/source/blender/freestyle/intern/view_map/ViewMap.cpp index e6c5d55f765..9f8b5e08200 100644 --- a/source/blender/freestyle/intern/view_map/ViewMap.cpp +++ b/source/blender/freestyle/intern/view_map/ViewMap.cpp @@ -1,623 +1,690 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/freestyle/intern/view_map/ViewMap.cpp + * \ingroup freestyle + * \brief Classes to define a View Map (ViewVertex, ViewEdge, etc.) + * \author Stephane Grabli + * \date 03/09/2002 + */ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +#include #include "ViewMap.h" -#include "../geometry/GeomUtils.h" -#include -#include "ViewMapIterators.h" #include "ViewMapAdvancedIterators.h" +#include "ViewMapIterators.h" - /**********************************/ - /* */ - /* */ - /* ViewMap */ - /* */ - /* */ - /**********************************/ +#include "../geometry/GeomUtils.h" -ViewMap * ViewMap::_pInstance = 0; - -ViewMap::~ViewMap() -{ - // The view vertices must be deleted here as some of them - // are shared between two shapes: - for(vector::iterator vv=_VVertices.begin(), vvend=_VVertices.end(); - vv!=vvend; - vv++) - { - delete (*vv); - } - _VVertices.clear(); - - for(vector::iterator vs=_VShapes.begin(),vsend=_VShapes.end(); - vs!=vsend; - vs++) - { - delete (*vs); - } - _VShapes.clear(); - - _FEdges.clear(); - _SVertices.clear(); - _VEdges.clear(); -} - -ViewShape * ViewMap::viewShape(unsigned id) -{ - int index = _shapeIdToIndex[id]; - return _VShapes[ index ]; -} -void ViewMap::AddViewShape(ViewShape *iVShape) { - _shapeIdToIndex[iVShape->getId().getFirst()] = _VShapes.size(); - _VShapes.push_back(iVShape); -} -const FEdge * ViewMap::getClosestFEdge(real x, real y) const -{ - // find the closest of this candidates: - real minDist = DBL_MAX; - FEdge * winner = 0; - 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(x,y),A, B); - if(dist < minDist) - { - minDist = dist; - winner = (*fe); - } - - } - if(winner==0) - return 0; - - return winner; -} - -const ViewEdge * ViewMap::getClosestViewEdge(real x, real y) const -{ - // find the closest of this candidates: - real minDist = DBL_MAX; - FEdge * winner = 0; - 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(x,y),A, B); - if(dist < minDist) - { - minDist = dist; - winner = (*fe); - } - - } - if(winner==0) - return 0; - - 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& newViewEdges){ - NonTVertex *vva = dynamic_cast(iVertex->viewvertex()); - if(vva != 0) - return vva; - // beacuse 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& fedges = iVertex->fedges(); - if(fedges.size()!=2){ - cerr << "ViewMap warning: Can't split the ViewEdge" << endl; - return 0; - } - FEdge * fend(0), * fbegin(0); - for(vector::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!=0) && (fend!=0)) - 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(0); - fbegin->setPreviousEdge(0); - - // 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(0); - fbegin->setPreviousEdge(0); - - // update new View Vertex: - vva->AddOutgoingViewEdge(newVEdge); - vva->AddIncomingViewEdge(ioEdge); - // 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; -} - -//FEdge * ViewMap::Connect(FEdge *ioEdge, SVertex *ioVertex, vector& oNewVEdges){ -// SShape * sshape = ioEdge->shape(); -// FEdge *newFEdge = sshape->SplitEdgeIn2(ioEdge, ioVertex); -// AddFEdge(newFEdge); -// InsertViewVertex(ioVertex, oNewVEdges); -// return newFEdge; -//} +/**********************************/ +/* */ +/* */ +/* ViewMap */ +/* */ +/* */ +/**********************************/ - /**********************************/ - /* */ - /* */ - /* TVertex */ - /* */ - /* */ - /**********************************/ +ViewMap *ViewMap::_pInstance = NULL; + +ViewMap::~ViewMap() +{ + // The view vertices must be deleted here as some of them are shared between two shapes: + for (vector::iterator vv = _VVertices.begin(), vvend = _VVertices.end(); vv != vvend; vv++) { + delete (*vv); + } + _VVertices.clear(); + + for (vector::iterator vs = _VShapes.begin(), vsend = _VShapes.end(); vs != vsend; vs++) { + delete (*vs); + } + _VShapes.clear(); + + _FEdges.clear(); + _SVertices.clear(); + _VEdges.clear(); +} + +ViewShape *ViewMap::viewShape(unsigned id) +{ + int index = _shapeIdToIndex[id]; + return _VShapes[ index ]; +} + +void ViewMap::AddViewShape(ViewShape *iVShape) +{ + _shapeIdToIndex[iVShape->getId().getFirst()] = _VShapes.size(); + _VShapes.push_back(iVShape); +} + +const FEdge *ViewMap::getClosestFEdge(real x, real y) const +{ + // find the closest of this candidates: + real minDist = DBL_MAX; + FEdge *winner = 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(x, y), A, B); + if (dist < minDist) { + minDist = dist; + winner = (*fe); + } + } + + return winner; +} + +const ViewEdge *ViewMap::getClosestViewEdge(real x, real y) const +{ + // find the closest of this candidates: + real minDist = DBL_MAX; + FEdge *winner = 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(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& newViewEdges) +{ + NonTVertex *vva = dynamic_cast(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& fedges = iVertex->fedges(); + if (fedges.size() != 2) { + cerr << "ViewMap warning: Can't split the ViewEdge" << endl; + return NULL; + } + FEdge *fend(0), *fbegin(0); + for (vector::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!=0) && (fend!=0)) + 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); + // 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& oNewVEdges) +{ + SShape *sshape = ioEdge->shape(); + FEdge *newFEdge = sshape->SplitEdgeIn2(ioEdge, ioVertex); + AddFEdge(newFEdge); + InsertViewVertex(ioVertex, oNewVEdges); + return newFEdge; +} +#endif + +/**********************************/ +/* */ +/* */ +/* TVertex */ +/* */ +/* */ +/**********************************/ // is dve1 before dve2 ? (does it have a smaller angle ?) -static bool ViewEdgeComp(ViewVertex::directedViewEdge& dve1, ViewVertex::directedViewEdge& dve2){ - FEdge *fe1; - if(dve1.second) - fe1 = dve1.first->fedgeB(); - else - fe1 = dve1.first->fedgeA(); - FEdge *fe2; - if(dve2.second) - fe2 = dve2.first->fedgeB(); - else - fe2 = dve2.first->fedgeA(); - - Vec3r V1 = fe1->orientation2d(); - Vec2r v1(V1.x(), V1.y());v1.normalize(); - Vec3r V2 = fe2->orientation2d(); - Vec2r v2(V2.x(), V2.y());v2.normalize(); - if(v1.y() > 0){ - if(v2.y() < 0) - return true; - 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(); - while((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(); - while((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(); - while((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(); - while((dve!=dveend) && ViewEdgeComp(**dve, _BackEdgeB)){ - ++dve; - } - _sortedEdges.insert(dve, &_BackEdgeB); - } - else - _sortedEdges.push_back(&_BackEdgeB); +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); + } +} + +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); + } +} + +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); + } +} + +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); + } } + 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()); - - // 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); +{ + for (edge_pointers_container::iterator it = _sortedEdges.begin(), itend = _sortedEdges.end(); it != itend; it++) { + if ((*it)->first == iEdge) + return edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), it); + } + return edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin()); + +#if 0 + directedViewEdge dEdge; + if (_FrontEdgeA.first == iEdge) + dEdge = _FrontEdgeA; + else if (_FrontEdgeB.first == iEdge) + dEdge = _FrontEdgeB; + else if (_BackEdgeA.first == iEdge) + dEdge = _BackEdgeA; + else if (_BackEdgeB.first == iEdge) + dEdge = _BackEdgeB; + return edge_iterator(_FrontEdgeA, _FrontEdgeB, _BackEdgeA, _BackEdgeB, dEdge); +#endif } + ViewVertex::const_edge_iterator TVertex::edges_iterator(ViewEdge *iEdge) const -{ - for(edge_pointers_container::const_iterator it=_sortedEdges.begin(), itend=_sortedEdges.end(); - it!=itend; - it++) - { - if((*it)->first == iEdge) - return const_edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), it); - } - return const_edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin()); - - // 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); -} - -ViewVertexInternal::orientedViewEdgeIterator TVertex::edgesBegin() { - return ViewVertexInternal::orientedViewEdgeIterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin()); -} -ViewVertexInternal::orientedViewEdgeIterator TVertex::edgesEnd() { - return ViewVertexInternal::orientedViewEdgeIterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.end()); -} -ViewVertexInternal::orientedViewEdgeIterator TVertex::edgesIterator(ViewEdge *iEdge) { - for(edge_pointers_container::iterator it=_sortedEdges.begin(), itend=_sortedEdges.end(); - it!=itend; - it++) - { - if((*it)->first == iEdge) - return ViewVertexInternal::orientedViewEdgeIterator(_sortedEdges.begin(), _sortedEdges.end(), it); - } - return ViewVertexInternal::orientedViewEdgeIterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin()); +{ + for (edge_pointers_container::const_iterator it = _sortedEdges.begin(), itend = _sortedEdges.end(); + it != itend; + it++) + { + if ((*it)->first == iEdge) + return const_edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), it); + } + return const_edge_iterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin()); + +#if 0 + directedViewEdge dEdge; + if (_FrontEdgeA.first == iEdge) + dEdge = _FrontEdgeA; + else if (_FrontEdgeB.first == iEdge) + dEdge = _FrontEdgeB; + else if (_BackEdgeA.first == iEdge) + dEdge = _BackEdgeA; + else if (_BackEdgeB.first == iEdge) + dEdge = _BackEdgeB; + return const_edge_iterator(_FrontEdgeA, _FrontEdgeB, _BackEdgeA, _BackEdgeB, dEdge); +#endif +} + +ViewVertexInternal::orientedViewEdgeIterator TVertex::edgesBegin() +{ + return ViewVertexInternal::orientedViewEdgeIterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin()); } - /**********************************/ - /* */ - /* */ - /* NonTVertex */ - /* */ - /* */ - /**********************************/ -void NonTVertex::AddOutgoingViewEdge(ViewEdge * iVEdge){ - // let's keep the viewedges ordered in CCW order - // in the 2D image plan - directedViewEdge idve(iVEdge, false); - if(!_ViewEdges.empty()){ - edges_container::iterator dve = _ViewEdges.begin(), dveend = _ViewEdges.end(); - while((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(); - while((dve!=dveend) && ViewEdgeComp(*dve, idve)){ - ++dve; - } - _ViewEdges.insert(dve, idve); - } - else - _ViewEdges.push_back(idve); +ViewVertexInternal::orientedViewEdgeIterator TVertex::edgesEnd() +{ + return ViewVertexInternal::orientedViewEdgeIterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.end()); +} + +ViewVertexInternal::orientedViewEdgeIterator TVertex::edgesIterator(ViewEdge *iEdge) +{ + for (edge_pointers_container::iterator it = _sortedEdges.begin(), itend = _sortedEdges.end(); it != itend; it++) { + if ((*it)->first == iEdge) + return ViewVertexInternal::orientedViewEdgeIterator(_sortedEdges.begin(), _sortedEdges.end(), it); + } + return ViewVertexInternal::orientedViewEdgeIterator(_sortedEdges.begin(), _sortedEdges.end(), _sortedEdges.begin()); +} + +/**********************************/ +/* */ +/* */ +/* NonTVertex */ +/* */ +/* */ +/**********************************/ + +void NonTVertex::AddOutgoingViewEdge(ViewEdge *iVEdge){ + // let's keep the viewedges ordered in CCW order in the 2D image plan + directedViewEdge idve(iVEdge, false); + if (!_ViewEdges.empty()) { + edges_container::iterator dve = _ViewEdges.begin(), dveend = _ViewEdges.end(); + for (; (dve != dveend) && ViewEdgeComp(*dve, idve); ++dve); + _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); + } } /*! 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()); +ViewVertexInternal::orientedViewEdgeIterator NonTVertex::edgesBegin() +{ + return ViewVertexInternal::orientedViewEdgeIterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin()); } -ViewVertexInternal::orientedViewEdgeIterator NonTVertex::edgesEnd() { - return ViewVertexInternal::orientedViewEdgeIterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.end()); + +ViewVertexInternal::orientedViewEdgeIterator NonTVertex::edgesEnd() +{ + return ViewVertexInternal::orientedViewEdgeIterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.end()); } -ViewVertexInternal::orientedViewEdgeIterator NonTVertex::edgesIterator(ViewEdge *iEdge) { - for(edges_container::iterator it=_ViewEdges.begin(), itend=_ViewEdges.end(); - it!=itend; - it++) - { - if((it)->first == iEdge) - return ViewVertexInternal::orientedViewEdgeIterator(_ViewEdges.begin(), _ViewEdges.end(), it); - } - return ViewVertexInternal::orientedViewEdgeIterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin()); + +ViewVertexInternal::orientedViewEdgeIterator NonTVertex::edgesIterator(ViewEdge *iEdge) +{ + for (edges_container::iterator it = _ViewEdges.begin(), itend = _ViewEdges.end(); it != itend; it++) { + if ((it)->first == iEdge) + return ViewVertexInternal::orientedViewEdgeIterator(_ViewEdges.begin(), _ViewEdges.end(), it); + } + return ViewVertexInternal::orientedViewEdgeIterator(_ViewEdges.begin(), _ViewEdges.end(), _ViewEdges.begin()); +} + +/**********************************/ +/* */ +/* */ +/* ViewEdge */ +/* */ +/* */ +/**********************************/ + +real ViewEdge::getLength2D() const +{ + float length = 0.0f; + ViewEdge::const_fedge_iterator itlast = fedge_iterator_last(); + ViewEdge::const_fedge_iterator it = fedge_iterator_begin(), itend = fedge_iterator_end(); + Vec2r seg; + do { + seg = Vec2r((*it)->orientation2d()[0], (*it)->orientation2d()[1]); + length += seg.norm(); + ++it; + } while ((it != itend) && (it != itlast)); + return length; } - /**********************************/ - /* */ - /* */ - /* ViewEdge */ - /* */ - /* */ - /**********************************/ -real ViewEdge::getLength2D() const +//! view edge iterator +ViewEdge::edge_iterator ViewEdge::ViewEdge_iterator() { - float length = 0.f; - 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; + return edge_iterator(this); } +ViewEdge::const_edge_iterator ViewEdge::ViewEdge_iterator() const +{ + return const_edge_iterator((ViewEdge*)this); +} -//! view edge iterator -ViewEdge::edge_iterator ViewEdge::ViewEdge_iterator() {return edge_iterator(this);} -ViewEdge::const_edge_iterator ViewEdge::ViewEdge_iterator() const {return const_edge_iterator((ViewEdge*)this);} //! feature edge iterator -ViewEdge::fedge_iterator ViewEdge::fedge_iterator_begin() {return fedge_iterator(this->_FEdgeA, this->_FEdgeB);} -ViewEdge::const_fedge_iterator ViewEdge::fedge_iterator_begin() const {return const_fedge_iterator(this->_FEdgeA, this->_FEdgeB);} -ViewEdge::fedge_iterator ViewEdge::fedge_iterator_last() {return fedge_iterator(this->_FEdgeB, this->_FEdgeB);} -ViewEdge::const_fedge_iterator ViewEdge::fedge_iterator_last() const {return const_fedge_iterator(this->_FEdgeB, this->_FEdgeB);} -ViewEdge::fedge_iterator ViewEdge::fedge_iterator_end() {return fedge_iterator(0, this->_FEdgeB);} -ViewEdge::const_fedge_iterator ViewEdge::fedge_iterator_end() const {return const_fedge_iterator(0, this->_FEdgeB);} +ViewEdge::fedge_iterator ViewEdge::fedge_iterator_begin() +{ + return fedge_iterator(this->_FEdgeA, this->_FEdgeB); +} + +ViewEdge::const_fedge_iterator ViewEdge::fedge_iterator_begin() const +{ + return const_fedge_iterator(this->_FEdgeA, this->_FEdgeB); +} + +ViewEdge::fedge_iterator ViewEdge::fedge_iterator_last() +{ + return fedge_iterator(this->_FEdgeB, this->_FEdgeB); +} + +ViewEdge::const_fedge_iterator ViewEdge::fedge_iterator_last() const +{ + return const_fedge_iterator(this->_FEdgeB, this->_FEdgeB); +} + +ViewEdge::fedge_iterator ViewEdge::fedge_iterator_end() +{ + return fedge_iterator(0, this->_FEdgeB); +} + +ViewEdge::const_fedge_iterator ViewEdge::fedge_iterator_end() const +{ + 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);} -ViewEdge::vertex_iterator ViewEdge::vertices_begin() {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);} -ViewEdge::vertex_iterator ViewEdge::vertices_last() {return vertex_iterator(this->_FEdgeB->vertexB(), _FEdgeB, 0);} -ViewEdge::const_vertex_iterator ViewEdge::vertices_end() const {return const_vertex_iterator(0, _FEdgeB, 0);} -ViewEdge::vertex_iterator ViewEdge::vertices_end() {return vertex_iterator(0, _FEdgeB, 0);} +ViewEdge::const_vertex_iterator ViewEdge::vertices_begin() const +{ + return const_vertex_iterator(this->_FEdgeA->vertexA(), 0, _FEdgeA); +} +ViewEdge::vertex_iterator ViewEdge::vertices_begin() +{ + return vertex_iterator(this->_FEdgeA->vertexA(), 0, _FEdgeA); +} -Interface0DIterator ViewEdge::verticesBegin() { - Interface0DIterator ret(new ViewEdgeInternal::SVertexIterator(this->_FEdgeA->vertexA(), this->_FEdgeA->vertexA(), 0, _FEdgeA, 0.f)); - return ret; +ViewEdge::const_vertex_iterator ViewEdge::vertices_last() const +{ + return const_vertex_iterator(this->_FEdgeB->vertexB(), _FEdgeB, 0); } -Interface0DIterator ViewEdge::verticesEnd() { - Interface0DIterator ret(new ViewEdgeInternal::SVertexIterator(0, this->_FEdgeA->vertexA(), _FEdgeB, 0, getLength2D())); - return ret; +ViewEdge::vertex_iterator ViewEdge::vertices_last() +{ + return vertex_iterator(this->_FEdgeB->vertexB(), _FEdgeB, 0); } -Interface0DIterator ViewEdge::pointsBegin(float t) { - return verticesBegin(); +ViewEdge::const_vertex_iterator ViewEdge::vertices_end() const +{ + return const_vertex_iterator(0, _FEdgeB, 0); } -Interface0DIterator ViewEdge::pointsEnd(float t) { - return verticesEnd(); +ViewEdge::vertex_iterator ViewEdge::vertices_end() +{ + 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 ViewEdge::verticesEnd() +{ + Interface0DIterator ret(new ViewEdgeInternal::SVertexIterator(NULL, this->_FEdgeA->vertexA(), + _FEdgeB, NULL, getLength2D())); + return ret; +} + +Interface0DIterator ViewEdge::pointsBegin(float t) +{ + return verticesBegin(); +} + +Interface0DIterator ViewEdge::pointsEnd(float t) +{ + return verticesEnd(); +} /**********************************/ /* */ @@ -627,77 +694,60 @@ Interface0DIterator ViewEdge::pointsEnd(float t) { /* */ /**********************************/ - ViewShape::~ViewShape() { - _Vertices.clear(); - - if(!(_Edges.empty())) - { - for(vector::iterator e=_Edges.begin(), eend=_Edges.end(); - e!=eend; - e++) - { - delete (*e); - } - _Edges.clear(); - } - - if(0 != _SShape) - { - delete _SShape; - _SShape = 0; - } -} - -void ViewShape::RemoveEdge(ViewEdge * iViewEdge) -{ - FEdge * fedge = iViewEdge->fedgeA(); - for(vector::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::iterator vv=_Vertices.begin(), vvend=_Vertices.end(); - vv!=vvend; - vv++) - { - if(iViewVertex == (*vv)) - { - _Vertices.erase(vv); - break; - } - } + _Vertices.clear(); + + if (!(_Edges.empty())) { + for (vector::iterator e = _Edges.begin(), eend = _Edges.end(); e != eend; e++) { + delete (*e); + } + _Edges.clear(); + } + + if (_SShape) { + delete _SShape; + _SShape = NULL; + } } - /**********************************/ - /* */ - /* */ - /* ViewEdge */ - /* */ - /* */ - /**********************************/ +void ViewShape::RemoveEdge(ViewEdge *iViewEdge) +{ + FEdge *fedge = iViewEdge->fedgeA(); + for (vector::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::iterator vv = _Vertices.begin(), vvend = _Vertices.end(); vv != vvend; vv++) { + if (iViewVertex == (*vv)) { + _Vertices.erase(vv); + break; + } + } +} + +/**********************************/ +/* */ +/* */ +/* ViewEdge */ +/* */ +/* */ +/**********************************/ void ViewEdge::UpdateFEdges() { - FEdge *currentEdge = _FEdgeA; - do - { - currentEdge->setViewEdge(this); - currentEdge = currentEdge->nextEdge(); - }while((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); } diff --git a/source/blender/freestyle/intern/view_map/ViewMap.h b/source/blender/freestyle/intern/view_map/ViewMap.h index d2d7a9a5341..e29b2ae7cd6 100644 --- a/source/blender/freestyle/intern/view_map/ViewMap.h +++ b/source/blender/freestyle/intern/view_map/ViewMap.h @@ -1,56 +1,64 @@ -// -// Filename : ViewMap.h -// Author(s) : Stephane Grabli -// Purpose : Classes to define a View Map (ViewVertex, ViewEdge, etc.) -// Date of creation : 03/09/2002 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef VIEWMAP_H -# define VIEWMAP_H - -# include "Interface0D.h" -# include "Interface1D.h" -# include "Silhouette.h" // defines the embedding -# include "../system/BaseIterator.h" -# include "../system/FreestyleConfig.h" -# include "../geometry/GeomUtils.h" -# include - - /**********************************/ - /* */ - /* */ - /* ViewMap */ - /* */ - /* */ - /**********************************/ - - -/* Density - Mean area depth value - distance to a point - */ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_VIEW_MAP_H__ +#define __FREESTYLE_VIEW_MAP_H__ + +/** \file blender/freestyle/intern/view_map/ViewMap.h + * \ingroup freestyle + * \brief Classes to define a View Map (ViewVertex, ViewEdge, etc.) + * \author Stephane Grabli + * \date 03/09/2002 + */ + +#include + +#include "Interface0D.h" +#include "Interface1D.h" +#include "Silhouette.h" // defines the embedding + +#include "../geometry/GeomUtils.h" + +#include "../system/BaseIterator.h" +#include "../system/FreestyleConfig.h" + +/**********************************/ +/* */ +/* */ +/* ViewMap */ +/* */ +/* */ +/**********************************/ + + +/* Density + * Mean area depth value + * distance to a point + */ class ViewVertex; class ViewEdge; @@ -58,500 +66,580 @@ class ViewShape; class TVertex; /*! Class defining the ViewMap.*/ -class LIB_VIEW_MAP_EXPORT ViewMap +class LIB_VIEW_MAP_EXPORT ViewMap { public: - - typedef vector viewedges_container; - typedef vector viewvertices_container; - typedef vector viewshapes_container; - typedef vector svertices_container; - typedef vector fedges_container; - typedef map id_to_index_map; + typedef vector viewedges_container; + typedef vector viewvertices_container; + typedef vector viewshapes_container; + typedef vector svertices_container; + typedef vector fedges_container; + typedef map 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 _scene3DBBox; - id_to_index_map _shapeIdToIndex; // 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. + 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 _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 = 0; - } - /*! 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 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& 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& newViewEdges); - - /* connects a FEdge to the graph trough a SVertex */ - //FEdge * Connect(FEdge *ioEdge, SVertex *ioVertex); + /*! 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 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& 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& newViewEdges); + + /* connects a FEdge to the graph trough a SVertex */ + //FEdge *Connect(FEdge *ioEdge, SVertex *ioVertex); }; - /**********************************/ - /* */ - /* */ - /* ViewVertex */ - /* */ - /* */ - /**********************************/ +/**********************************/ +/* */ +/* */ +/* ViewVertex */ +/* */ +/* */ +/**********************************/ class ViewEdge; class SShape; namespace ViewVertexInternal { - class edge_const_traits; - class edge_nonconst_traits; - template class edge_iterator_base ; - class orientedViewEdgeIterator; + +class edge_const_traits; +class edge_nonconst_traits; +template class edge_iterator_base; +class orientedViewEdgeIterator; + } // end of namespace ViewEdgeInternal -/*! Class to define a view vertex - * A view vertex is a feature vertex corresponding - * to a point of the image graph, where the characteristics of an + +/*! Class to define a view vertex. + * A view vertex is a feature vertex corresponding to a point of the image graph, where the characteristics of an * edge might change (nature, visibility, ...). - * A ViewVertex can be of two kinds: a TVertex when - * it corresponds to the intersection between two - * ViewEdges or a NonTVertex when it corresponds to a - * vertex of the initial input mesh (it is the case - * for vertices such as corners for example). - * Thus, this class can be specialized into two classes, - * the TVertex class and the NonTVertex class. + * A ViewVertex can be of two kinds: a TVertex when it corresponds to the intersection between two ViewEdges or a + * NonTVertex when it corresponds to a vertex of the initial input mesh (it is the case for vertices such as corners + * for example). Thus, this class can be specialized into two classes, the TVertex class and the NonTVertex class. */ class LIB_VIEW_MAP_EXPORT ViewVertex : public Interface0D { public: // Implementation of Interface0D + /*! Returns the string "ViewVertex". */ + virtual string getExactTypeName() const + { + return "ViewVertex"; + } - /*! Returns the string "ViewVertex" .*/ - virtual string getExactTypeName() const { - return "ViewVertex"; - } - -public: - friend class ViewShape; - typedef pair directedViewEdge; // if bool = true, the ViewEdge is incoming +public: + friend class ViewShape; + typedef pair directedViewEdge; // if bool = true, the ViewEdge is incoming - typedef vector edges_container; + typedef vector edges_container; - typedef ViewVertexInternal::edge_iterator_base edge_iterator; - typedef ViewVertexInternal::edge_iterator_base const_edge_iterator; + typedef ViewVertexInternal::edge_iterator_base edge_iterator; + typedef ViewVertexInternal::edge_iterator_base const_edge_iterator; private: - - Nature::VertexNature _Nature; + 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 = 0;_Nature = Nature::VIEW_VERTEX; } - inline ViewVertex(Nature::VertexNature nature) { - userdata = 0; - _Nature = Nature::VIEW_VERTEX | nature; - } + /*! 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 = 0; - } - /*! Cloning method. */ - virtual ViewVertex * duplicate() = 0; - + /*! 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 *) {} + /*! 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. - */ + /* 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. - */ + /*! Returns an orientedViewEdgeIterator pointing to the ViewEdge given as argument. */ virtual ViewVertexInternal::orientedViewEdgeIterator edgesIterator(ViewEdge *iEdge) = 0; - }; - /**********************************/ - /* */ - /* */ - /* TVertex */ - /* */ - /* */ - /**********************************/ +/**********************************/ +/* */ +/* */ +/* TVertex */ +/* */ +/* */ +/**********************************/ -/*! class to define a T vertex, i.e. an intersection between - * two edges. +/*! class to define a T vertex, i.e. an intersection between two edges. * It points towards 2 SVertex and 4 View edges. * Among these ViewEdges, 2 are front and 2 are back. * Basically the front edge hides part of the back edge. - * So, among the back edges, 1 is of invisibility n - * and the other of visibility n+1 + * So, among the back edges, 1 is of invisibility n and the other of visibility n+1 */ class LIB_VIEW_MAP_EXPORT TVertex : public ViewVertex { public: - typedef vector edge_pointers_container; -public: // Implementation of Interface0D + typedef vector edge_pointers_container; - /*! 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 Vec3f 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 Vec2f 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 - /*! Cast the Interface0D in ViewVertex if it can be. */ - virtual ViewVertex * castToViewVertex(){ - return this; - } - - /*! Cast the Interface0D in TVertex if it can be. */ - virtual TVertex * castToTVertex(){ - return this; - } +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 Vec3f 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 Vec2f 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) - + 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 = 0; - _BackSVertex = 0; - _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); - } + /*! 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; - } + /*! 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& vfEdges = _FrontSVertex->fedges(); - vector::const_iterator fe,fend; - for(fe=vfEdges.begin(),fend=vfEdges.end(); - fe!=fend; - fe++) - { - if((*fe) == iFEdge) - return _FrontSVertex; - } - - const vector& vbEdges = _BackSVertex->fedges(); - for(fe=vbEdges.begin(),fend=vbEdges.end(); - fe!=fend; - fe++) - { - if((*fe) == iFEdge) - return _BackSVertex; - } - return 0; - } - - 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 0; - } - - /* 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) ; + /* 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& vfEdges = _FrontSVertex->fedges(); + vector::const_iterator fe, fend; + for (fe = vfEdges.begin(), fend = vfEdges.end(); fe != fend; fe++) { + if ((*fe) == iFEdge) + return _FrontSVertex; + } + + const vector& 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); }; - /**********************************/ - /* */ - /* */ - /* NonTVertex */ - /* */ - /* */ - /**********************************/ +/**********************************/ +/* */ +/* */ +/* NonTVertex */ +/* */ +/* */ +/**********************************/ // (non T vertex) @@ -562,744 +650,949 @@ public: class LIB_VIEW_MAP_EXPORT NonTVertex : public ViewVertex { public: - typedef vector edges_container; + typedef vector 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 Vec3f 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 Vec2f 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; - } + /*! 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 Vec3f 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 Vec2f 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; + SVertex *_SVertex; + edges_container _ViewEdges; + public: - /*! Default constructor.*/ - inline NonTVertex() : ViewVertex(Nature::NON_T_VERTEX) { _SVertex = 0; } - /*! Builds a NonTVertex from a SVertex. */ - inline NonTVertex(SVertex* iSVertex) : ViewVertex(Nature::NON_T_VERTEX) - { - _SVertex = iSVertex; - _SVertex->setViewVertex(this); - } + /*! 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; - } + /*! 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& 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) ; + /*! 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& 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); }; - /**********************************/ - /* */ - /* */ - /* ViewEdge */ - /* */ - /* */ - /**********************************/ +/**********************************/ +/* */ +/* */ +/* ViewEdge */ +/* */ +/* */ +/**********************************/ /* Geometry(normals...) - Nature of edges - 2D spaces (1or2, material, z...) - Parent Shape - 3D Shading, material - Importance - Occluders - */ + * Nature of edges + * 2D spaces (1or2, material, z...) + * Parent Shape + * 3D Shading, material + * Importance + * Occluders + */ class ViewShape; namespace ViewEdgeInternal { - template class edge_iterator_base ; - template class fedge_iterator_base ; - template class vertex_iterator_base ; + +template class edge_iterator_base; +template class fedge_iterator_base; +template class vertex_iterator_base; + } // end of namespace ViewEdgeInternal -/*! Class defining a ViewEdge. A ViewEdge in an edge - * of the image graph. it connnects two ViewVertex. +/*! Class defining a ViewEdge. A ViewEdge in an edge of the image graph. it connnects two ViewVertex. * It is made by connecting a set of FEdges. */ class LIB_VIEW_MAP_EXPORT 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; - } + /*! 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 > edge_iterator; - typedef ViewEdgeInternal::edge_iterator_base > const_edge_iterator; - // for fedge iterator - typedef ViewEdgeInternal::fedge_iterator_base > fedge_iterator; - typedef ViewEdgeInternal::fedge_iterator_base > const_fedge_iterator; - // for svertex iterator - typedef ViewEdgeInternal::vertex_iterator_base > vertex_iterator; - typedef ViewEdgeInternal::vertex_iterator_base > const_vertex_iterator; -private: + typedef SVertex vertex_type; + friend class ViewShape; + // for ViewEdge iterator + typedef ViewEdgeInternal::edge_iterator_base > edge_iterator; + typedef ViewEdgeInternal::edge_iterator_base > const_edge_iterator; + // for fedge iterator + typedef ViewEdgeInternal::fedge_iterator_base > fedge_iterator; + typedef ViewEdgeInternal::fedge_iterator_base > const_fedge_iterator; + // for svertex iterator + typedef ViewEdgeInternal::vertex_iterator_base > vertex_iterator; + typedef ViewEdgeInternal::vertex_iterator_base > const_vertex_iterator; - 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; - ViewShape *_aShape; // 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 // NON GERE PAR LE COPY CONSTRUCTEUR - int _qi; - vector _Occluders; - bool _isInImage; - - // tmp - Id * _splittingId; +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 _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=0; - __B=0; - _FEdgeA = 0; - _FEdgeB = 0; - _ChainingTimeStamp = 0; - _qi = 0; - _aShape=0; - userdata = 0; - _splittingId = 0; - _isInImage = true; - } - inline ViewEdge(ViewVertex* iA, ViewVertex *iB) - { - __A = iA; - __B = iB; - _FEdgeA = 0; - _FEdgeB = 0; - _Shape = 0; - _ChainingTimeStamp = 0; - _aShape = 0; - _qi = 0; - userdata = 0; - _splittingId = 0; - _isInImage = true; - } - inline ViewEdge(ViewVertex* iA, ViewVertex *iB, FEdge *iFEdgeA) - { - __A = iA; - __B = iB; - _FEdgeA = iFEdgeA; - _FEdgeB = 0; - _Shape = 0; - _ChainingTimeStamp = 0; - _aShape = 0; - _qi = 0; - userdata = 0; - _splittingId = 0; - _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; - _aShape = 0; - _qi = 0; - userdata = 0; - _splittingId = 0; - _isInImage = true; - UpdateFEdges(); // tells every FEdge between iFEdgeA and iFEdgeB that this is theit ViewEdge - } + /*! 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 = 0; - _Id = iBrother._Id; - _ChainingTimeStamp = iBrother._ChainingTimeStamp; - _aShape = iBrother._aShape; - _qi = iBrother._qi; - _splittingId = 0; - _isInImage = iBrother._isInImage; - iBrother.userdata = this; - userdata = 0; - } - /*! Cloning method. */ - virtual ViewEdge * duplicate() - { - ViewEdge *clone = new ViewEdge(*this); - return clone; - } + /*! 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 != _aFace) - // { - // delete _aFace; - // _aFace = 0; - // } - // 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, - * 0 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 == 0) - 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& 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 */ - - //inline Nature::EdgeNature viewedge_nature() const {return getNature();} - //float viewedge_length() const ; - /*! Returns the 2D length of the Viewedge. */ - real getLength2D() const; - //inline Material material() const {return _FEdgeA->vertexA()->shape()->material();} - 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 constituing 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 constituing 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.f); - /*! 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.f); + /*! Destructor. */ + virtual ~ViewEdge() + { +#if 0 + if (_aFace) { + delete _aFace; + _aFace = NULL; + } +#endif + // only the last splitted deletes this id + if (_splittingId) { + if (*_splittingId == _Id) + delete _splittingId; + } + } + + /* accessors */ + /*! Returns the first ViewVertex. */ + inline ViewVertex *A() + { + return __A; + } + + /*! Returns the second ViewVertex. */ + inline ViewVertex *B() + { + return __B; + } + + /*! Returns the first FEdge that constitues this ViewEdge. */ + inline FEdge *fedgeA() + { + return _FEdgeA; + } + + /*! Returns the last FEdge that constitues this ViewEdge. */ + inline FEdge *fedgeB() + { + return _FEdgeB; + } + + /*! Returns the ViewShape to which this ViewEdge belongs to .*/ + inline ViewShape *viewShape() + { + return _Shape; + } + + /*! Returns the shape that is occluded by the ViewShape to which this ViewEdge belongs to. If no object is occluded, + * NULL is returned. + * \return The occluded ViewShape. + */ + inline ViewShape *aShape() + { + return _aShape; + } + + /*! Tells whether this ViewEdge forms a closed loop or not. */ + inline bool isClosed() + { + if (!__B) + return true; + return false; + } + + /*! Returns the time stamp of this ViewEdge. */ + inline unsigned getChainingTimeStamp() + { + return _ChainingTimeStamp; + } + + inline const ViewShape *aShape() const + { + return _aShape; + } + + inline const ViewShape *bShape() const + { + return _Shape; + } + + inline vector& occluders() + { + return _Occluders; + } + + inline Id *splittingId() + { + return _splittingId; + } + + inline bool isInImage() const + { + return _isInImage; + } + + /* modifiers */ + /*! Sets the first ViewVertex of the ViewEdge. */ + inline void setA(ViewVertex *iA) + { + __A = iA; + } + + /*! Sets the last ViewVertex of the ViewEdge. */ + inline void setB(ViewVertex *iB) + { + __B = iB; + } + + /*! Sets the nature of the ViewEdge. */ + inline void setNature(Nature::EdgeNature iNature) + { + _Nature = iNature; + } + + /*! Sets the first FEdge of the ViewEdge. */ + inline void setFEdgeA(FEdge *iFEdge) + { + _FEdgeA = iFEdge; + } + + /*! Sets the last FEdge of the ViewEdge. */ + inline void setFEdgeB(FEdge *iFEdge) + { + _FEdgeB = iFEdge; + } + + /*! Sets the ViewShape to which this ViewEdge belongs to.*/ + inline void setShape(ViewShape *iVShape) + { + _Shape = iVShape; + } + + /*! Sets the ViewEdge id. */ + inline void setId(const Id& id) + { + _Id = id; + } + + /*! Sets Viewedge to this for all embedded fedges */ + void UpdateFEdges(); + + /*! Sets the occluded ViewShape */ + inline void setaShape(ViewShape *iShape) + { + _aShape = iShape; + } + + /*! Sets the quantitative invisibility value. */ + inline void setQI(int qi) + { + _qi = qi; + } + + /*! Sets the time stamp value. */ + inline void setChainingTimeStamp(unsigned ts) + { + _ChainingTimeStamp = ts; + } + + inline void AddOccluder(ViewShape *iShape) + { + _Occluders.push_back(iShape); + } + + inline void setSplittingId(Id *id) + { + _splittingId = id; + } + + inline void setIsInImage(bool iFlag) + { + _isInImage = iFlag; + } + + /* stroke interface definition */ + inline bool intersect_2d_area(const Vec2r& iMin, const Vec2r& iMax) const + { + // parse edges to check if one of them is intersection the region: + FEdge *current = _FEdgeA; + do { + if (GeomUtils::intersect2dSeg2dArea(iMin, iMax, + Vec2r(current->vertexA()->point2D()[0], + current->vertexA()->point2D()[1]), + Vec2r(current->vertexB()->point2D()[0], + current->vertexB()->point2D()[1]))) + { + return true; + } + current = current->nextEdge(); + } while ((current != 0) && (current != _FEdgeA)); + + return false; + } + + inline bool include_in_2d_area(const Vec2r& iMin, const Vec2r& iMax) const + { + // parse edges to check if all of them are intersection the region: + FEdge *current = _FEdgeA; + + do { + if (!GeomUtils::include2dSeg2dArea(iMin, iMax, + Vec2r(current->vertexA()->point2D()[0], + current->vertexA()->point2D()[1]), + Vec2r(current->vertexB()->point2D()[0], + current->vertexB()->point2D()[1]))) + { + return false; + } + current = current->nextEdge(); + } while ((current != 0) && (current != _FEdgeA)); + + return true; + } + + /* Information access interface */ + +#if 0 + inline Nature::EdgeNature viewedge_nature() const + { + return getNature(); + } + + float viewedge_length() const; +#endif + + /*! Returns the 2D length of the Viewedge. */ + real getLength2D() const; + +#if 0 + inline Material material() const + { + return _FEdgeA->vertexA()->shape()->material(); + } +#endif + + inline int qi() const + { + return _qi; + } + + inline occluder_container::const_iterator occluders_begin() const + { + return _Occluders.begin(); + } + + inline occluder_container::const_iterator occluders_end() const + { + return _Occluders.end(); + } + + inline int occluders_size() const + { + return _Occluders.size(); + } + + inline bool occluders_empty() const + { + return _Occluders.empty(); + } + + inline const Polygon3r& occludee() const + { + return (_FEdgeA->aFace()); + } + + inline const SShape *occluded_shape() const; + + inline const bool occludee_empty() const + { + if (_aShape == 0) + return true; + return false; + } + + //inline real z_discontinuity(int iCombination = 0) const; + + inline Id shape_id() const + { + return _FEdgeA->vertexA()->shape()->getId(); + } + + inline const SShape *shape() const + { + return _FEdgeA->vertexA()->shape(); + } + + inline float shape_importance() const + { + return _FEdgeA->shape_importance(); + } + + /* iterators access */ + // view edge iterator + edge_iterator ViewEdge_iterator(); + const_edge_iterator ViewEdge_iterator() const; + // feature edge iterator + fedge_iterator fedge_iterator_begin(); + const_fedge_iterator fedge_iterator_begin() const; + fedge_iterator fedge_iterator_last(); + const_fedge_iterator fedge_iterator_last() const; + fedge_iterator fedge_iterator_end(); + const_fedge_iterator fedge_iterator_end() const; + // embedding vertex iterator + const_vertex_iterator vertices_begin() const; + vertex_iterator vertices_begin(); + const_vertex_iterator vertices_last() const; + vertex_iterator vertices_last(); + const_vertex_iterator vertices_end() const; + vertex_iterator vertices_end(); + + // Iterator access (Interface1D) + /*! Returns an Interface0DIterator to iterate over the SVertex constituing 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 constituing 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); }; - - /**********************************/ - /* */ - /* */ - /* ViewShape */ - /* */ - /* */ - /**********************************/ +/**********************************/ +/* */ +/* */ +/* ViewShape */ +/* */ +/* */ +/**********************************/ -/*! Class gathering the elements of the ViewMap (ViewVertex, ViewEdge) - * that are issued from the same input shape. - */ +/*! Class gathering the elements of the ViewMap (ViewVertex, ViewEdge) that are issued from the same input shape. */ class LIB_VIEW_MAP_EXPORT ViewShape { private: - vector _Vertices; - vector _Edges; - SShape * _SShape; - + vector _Vertices; + vector _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 = 0; _SShape = 0;} - /*! Builds a ViewShape from a SShape. */ - inline ViewShape(SShape *iSShape) {userdata = 0; _SShape = iSShape;}//_SShape->setViewShape(this);} - /*! Copy constructor. */ - inline ViewShape(ViewShape& iBrother) - { - userdata = 0; - vector::iterator vv,vvend; - vector::iterator ve, veend; - - _SShape = iBrother._SShape; - - vector& vvertices = iBrother.vertices(); - // duplicate vertices - for(vv=vvertices.begin(), vvend=vvertices.end(); - vv!=vvend; - vv++) - { - ViewVertex * newVertex = (*vv)->duplicate(); - AddVertex(newVertex); - } - - vector& 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& vedges = (v)->viewedges(); - vector newEdges; - for(vector::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: - ; - } - } - - //------------------------------------- - // 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& iViewVertices, - vector& ioNewEdges, - vector& 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& vertices() {return _Vertices;} - /*! Returns the list of ViewEdge contained in this ViewShape. */ - inline vector& edges() {return _Edges;} - /*! Returns the ViewShape id. */ - inline Id getId() const {return _SShape->getId();} - /*! Returns the ViewShape id. */ - inline const string& getName() const {return _SShape->getName();} - - /* modifiers */ - /*! Sets the SShape on top of which the ViewShape is built. */ - inline void setSShape(SShape* iSShape) {_SShape = iSShape;} - /*! Sets the list of ViewVertex contained in this ViewShape. */ - inline void setVertices(const vector& iVertices) {_Vertices = iVertices;} - /*! Sets the list of ViewEdge contained in this ViewShape. */ - inline void setEdges(const vector& 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); + /*! 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::iterator vv,vvend; + vector::iterator ve, veend; + + _SShape = iBrother._SShape; + + vector& vvertices = iBrother.vertices(); + // duplicate vertices + for (vv = vvertices.begin(), vvend = vvertices.end(); vv != vvend; vv++) { + ViewVertex *newVertex = (*vv)->duplicate(); + AddVertex(newVertex); + } + + vector& 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& vedges = (v)->viewedges(); + vector newEdges; + for (vector::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& iViewVertices, vector& ioNewEdges, + vector& 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& vertices() + { + return _Vertices; + } + + /*! Returns the list of ViewEdge contained in this ViewShape. */ + inline vector& edges() + { + return _Edges; + } + + /*! Returns the ViewShape id. */ + inline Id getId() const + { + return _SShape->getId(); + } + + /*! Returns the ViewShape id. */ + inline const string& getName() const + { + return _SShape->getName(); + } + + /* modifiers */ + /*! Sets the SShape on top of which the ViewShape is built. */ + inline void setSShape(SShape *iSShape) + { + _SShape = iSShape; + } + + /*! Sets the list of ViewVertex contained in this ViewShape. */ + inline void setVertices(const vector& iVertices) + { + _Vertices = iVertices; + } + + /*! Sets the list of ViewEdge contained in this ViewShape. */ + inline void setEdges(const vector& 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); }; - /* - ############################################# ############################################# ############################################# @@ -1309,198 +1602,178 @@ public: ############################################# ############################################# ############################################# - */ /* for inline functions */ -void ViewShape::SplitEdge(FEdge *fe, - const vector& iViewVertices, - vector& ioNewEdges, - vector& 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::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); - // Id id(vEdge->getId().getFirst(), vEdge->getId().getSecond()+1); - // newVEdge->setId(vEdge->getId()); - // vEdge->setId(id); - - AddEdge(newVEdge); // here this shape is set as the edge's shape - - // add new edge to the list of new edges passed as argument: - ioNewViewEdges.push_back(newVEdge); - - - - if(0 != vvb) - vvb->Replace((vEdge), newVEdge); - - // we split the view edge: - vEdge->setB((*vv)); - vEdge->setFEdgeB(fe); //MODIF - - // Update fedges so that they point to the new viewedge: - newVEdge->UpdateFEdges(); - - } - // check whether this vertex is a front vertex or a back - // one - - if(sv == (*vv)->frontSVertex()) - { - // -- View Vertex A' -- - (*vv)->setFrontEdgeA(vEdge, true); - (*vv)->setFrontEdgeB(newVEdge, false); - } - else - { - // -- View Vertex A' -- - (*vv)->setBackEdgeA(vEdge, true); - (*vv)->setBackEdgeB(newVEdge, false); - } - } -} - - /**********************************/ - /* */ - /* */ - /* ViewEdge */ - /* */ - /* */ - /**********************************/ - - -// inline Vec3r ViewEdge::orientation2d(int iCombination) const -// { -// return edge_orientation2d_function(*this, iCombination); -// } - -// inline Vec3r ViewEdge::orientation3d(int iCombination) const -// { -// return edge_orientation3d_function(*this, iCombination); -// } - -// inline real ViewEdge::z_discontinuity(int iCombination) const -// { -// return z_discontinuity_edge_function(*this, iCombination); -// } - -// inline float ViewEdge::local_average_depth(int iCombination ) const -// { -// return local_average_depth_edge_function(*this, iCombination); -// } - -// inline float ViewEdge::local_depth_variance(int iCombination) const -// { -// return local_depth_variance_edge_function(*this, iCombination); -// } - -// inline real ViewEdge::local_average_density(float sigma, int iCombination) const -// { -// return density_edge_function(*this, iCombination); -// } - -inline const SShape * ViewEdge::occluded_shape() const +void ViewShape::SplitEdge(FEdge *fe, const vector& iViewVertices, vector& ioNewEdges, + vector& ioNewViewEdges) { - if(0 == _aShape) - return 0; - return _aShape->sshape(); -} + 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::const_iterator vv, vvend; + for (vv = iViewVertices.begin(), vvend = iViewVertices.end(); vv != vvend; vv++) { + // Add the viewvertices to the ViewShape + AddVertex((*vv)); + + // retrieve the correct SVertex from the view vertex + //-------------------------------------------------- + sv = (*vv)->frontSVertex(); + sv2 = (*vv)->backSVertex(); + + if (sv->shape() != sv2->shape()) { + if (sv->shape() != _SShape) + sv = sv2; + } + else { + // if the shape is the same we can safely differ the two vertices using their ids: + if (sv->getId() != fe->vertexA()->getId()) + sv = sv2; + } + + vva = vEdge->A(); + vvb = vEdge->B(); + + // We split Fedge AB into AA' and A'B. A' and A'B are created. + // AB becomes (address speaking) AA'. B is updated. + //-------------------------------------------------- + SShape *shape = fe->shape(); + + // a new edge, A'B is created. + FEdge *newEdge = shape->SplitEdgeIn2(fe, sv); + /* One of the two FEdges (fe and newEdge) may have a 2D length less than M_EPSILON. + * (22 Feb 2011, T.K.) + */ + + ioNewEdges.push_back(newEdge); + ViewEdge *newVEdge; + + if ((vva == 0) || (vvb == 0)) { // that means we're dealing with a closed viewedge (loop) + // remove the chain that was starting by the fedge A of vEdge (which is different from fe !!!!) + shape->RemoveEdgeFromChain(vEdge->fedgeA()); + // we set + vEdge->setA(*vv); + vEdge->setB(*vv); + vEdge->setFEdgeA(newEdge); + //FEdge *previousEdge = newEdge->previousEdge(); + vEdge->setFEdgeB(fe); + newVEdge = vEdge; + vEdge->fedgeA()->setViewEdge(newVEdge); + } + else { + // while we create the view edge, it updates the "ViewEdge" pointer of every underlying FEdges to this. + newVEdge = new ViewEdge((*vv), vvb); //, newEdge, vEdge->fedgeB()); + newVEdge->setNature((fe)->getNature()); + newVEdge->setFEdgeA(newEdge); + //newVEdge->setFEdgeB(fe); + // If our original viewedge is made of one FEdge, then + if ((vEdge->fedgeA() == vEdge->fedgeB()) || (fe == vEdge->fedgeB())) + newVEdge->setFEdgeB(newEdge); + else + newVEdge->setFEdgeB(vEdge->fedgeB()); //MODIF + + Id *newId = vEdge->splittingId(); + if (newId == 0) { + newId = new Id(vEdge->getId()); + vEdge->setSplittingId(newId); + } + newId->setSecond(newId->getSecond() + 1); + newVEdge->setId(*newId); + newVEdge->setSplittingId(newId); +#if 0 + Id id(vEdge->getId().getFirst(), vEdge->getId().getSecond() + 1); + newVEdge->setId(vEdge->getId()); + vEdge->setId(id); +#endif + + AddEdge(newVEdge); // here this shape is set as the edge's shape + + // add new edge to the list of new edges passed as argument: + ioNewViewEdges.push_back(newVEdge); + + if (0 != vvb) + vvb->Replace((vEdge), newVEdge); + + // we split the view edge: + vEdge->setB((*vv)); + vEdge->setFEdgeB(fe); //MODIF + + // Update fedges so that they point to the new viewedge: + newVEdge->UpdateFEdges(); + } + // check whether this vertex is a front vertex or a back one + if (sv == (*vv)->frontSVertex()) { + // -- View Vertex A' -- + (*vv)->setFrontEdgeA(vEdge, true); + (*vv)->setFrontEdgeB(newVEdge, false); + } + else { + // -- View Vertex A' -- + (*vv)->setBackEdgeA(vEdge, true); + (*vv)->setBackEdgeB(newVEdge, false); + } + } +} + +/**********************************/ +/* */ +/* */ +/* ViewEdge */ +/* */ +/* */ +/**********************************/ + +#if 0 +inline Vec3r ViewEdge::orientation2d(int iCombination) const +{ + return edge_orientation2d_function(*this, iCombination); +} + +inline Vec3r ViewEdge::orientation3d(int iCombination) const +{ + return edge_orientation3d_function(*this, iCombination); +} + +inline real ViewEdge::z_discontinuity(int iCombination) const +{ + return z_discontinuity_edge_function(*this, iCombination); +} + +inline float ViewEdge::local_average_depth(int iCombination ) const +{ + return local_average_depth_edge_function(*this, iCombination); +} -// inline Vec3r ViewEdge::curvature2d_as_vector(int iCombination) const -// { -// return curvature2d_as_vector_edge_function(*this, iCombination); -// } +inline float ViewEdge::local_depth_variance(int iCombination) const +{ + return local_depth_variance_edge_function(*this, iCombination); +} + +inline real ViewEdge::local_average_density(float sigma, int iCombination) const +{ + return density_edge_function(*this, iCombination); +} +#endif -// inline real ViewEdge::curvature2d_as_angle(int iCombination) const -// { -// return curvature2d_as_angle_edge_function(*this, iCombination); -// } +inline const SShape * ViewEdge::occluded_shape() const +{ + if (0 == _aShape) + return 0; + return _aShape->sshape(); +} +#if 0 +inline Vec3r ViewEdge::curvature2d_as_vector(int iCombination) const +{ + return curvature2d_as_vector_edge_function(*this, iCombination); +} + +inline real ViewEdge::curvature2d_as_angle(int iCombination) const +{ + return curvature2d_as_angle_edge_function(*this, iCombination); +} +#endif -#endif // VIEWMAP_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 adffc46ec74..ff6557b7d86 100644 --- a/source/blender/freestyle/intern/view_map/ViewMapAdvancedIterators.h +++ b/source/blender/freestyle/intern/view_map/ViewMapAdvancedIterators.h @@ -1,691 +1,789 @@ -// -// Filename : ViewMapAdvancedIterators.h -// Author(s) : Stephane Grabli -// Purpose : Iterators used to iterate over the various elements of the ViewMap -// These iterators can't be exported to python. -// Date of creation : 01/07/2003 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef VIEWMAPADVANCEDITERATORS_H -# define VIEWMAPADVANCEDITERATORS_H +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_VIEW_MAP_ADVANCED_ITERATORS_H__ +#define __FREESTYLE_VIEW_MAP_ADVANCED_ITERATORS_H__ + +/** \file blender/freestyle/intern/view_map/ViewMapAdvancedIterators.h + * \ingroup freestyle + * \brief Iterators used to iterate over the various elements of the ViewMap. + * These iterators can't be exported to python. + * \author Stephane Grabli + * \date 01/07/2003 + */ #include "ViewMap.h" -#include "../system/Iterator.h" //soc - - /**********************************/ - /* */ - /* */ - /* ViewMap */ - /* */ - /* */ - /**********************************/ - - /**********************************/ - /* */ - /* */ - /* ViewVertex */ - /* */ - /* */ - /**********************************/ - -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_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 ; - }; - + +#include "../system/Iterator.h" //soc + +/**********************************/ +/* */ +/* */ +/* ViewMap */ +/* */ +/* */ +/**********************************/ + +/**********************************/ +/* */ +/* */ +/* ViewVertex */ +/* */ +/* */ +/**********************************/ + +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_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 edge_iterator_base : public IteratorBase - { - 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 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 iterator; - typedef edge_iterator_base 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; - - // mutable value_type _tvertex_iter; - // value_type _feA; - // value_type _feB; - // value_type _beA; - // value_type _beB; - - // Non TVertex attributes - edges_container_iterator _begin; - edges_container_iterator _end; - edges_container_iterator _nontvertex_iter; - - typedef IteratorBase parent_class; - - public: - inline edge_iterator_base() : parent_class() {} - inline edge_iterator_base(Nature::VertexNature iNature) - : parent_class() - {_Nature = iNature;} - edge_iterator_base(const edge_iterator_base& iBrother) - : parent_class(iBrother) - { - _Nature = iBrother._Nature; - if(_Nature & Nature::T_VERTEX) - { - // _feA = iBrother._feA; - // _feB = iBrother._feB; - // _beA = iBrother._beA; - // _beB = iBrother._beB; - // _tvertex_iter = iBrother._tvertex_iter; - _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& iBrother) - : parent_class(iBrother) - { - _Nature = iBrother._Nature; - if(_Nature & Nature::T_VERTEX) - { - // _feA = iBrother._feA; - // _feB = iBrother._feB; - // _beA = iBrother._beA; - // _beB = iBrother._beB; - // _tvertex_iter = iBrother._tvertex_iter; - _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: - // 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(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 - virtual Self& operator++() // operator corresponding to ++i - { - increment(); - return *this; - } - virtual Self operator++(int) // opérateur correspondant à i++ - { // c.a.d qui renvoie la valeur *puis* incrémente. - Self tmp = *this; // C'est pour cela qu'on stocke la valeur - increment(); // dans un temporaire. - 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; - // // 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 - // // 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; - // } - } - else - ++_nontvertex_iter; - } - }; - - } - /**********************************/ - /* */ - /* */ - /* ViewEdge */ - /* */ - /* */ - /**********************************/ +class edge_iterator_base : public IteratorBase +{ +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 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 iterator; + typedef edge_iterator_base 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; +#endif + + // Non TVertex attributes + edges_container_iterator _begin; + edges_container_iterator _end; + edges_container_iterator _nontvertex_iter; + + typedef IteratorBase parent_class; + +public: + inline edge_iterator_base() : parent_class() {} + + inline edge_iterator_base(Nature::VertexNature iNature) : parent_class() + { + _Nature = iNature; + } + + edge_iterator_base(const edge_iterator_base& 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; +#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& 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; +#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: +#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; + } +#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) // opérateur correspondant à i++ + { + 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 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; + } + } +}; + +} // ViewVertexInternal namespace + +/**********************************/ +/* */ +/* */ +/* ViewEdge */ +/* */ +/* */ +/**********************************/ namespace ViewEdgeInternal { - /*!----------------------*/ - /*! Iterators definition */ - /*!----------------------*/ - template - class edge_iterator_base : public IteratorBase - { - 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 Self; - public: - mutable value_type _ViewEdge; - //friend class edge_iterator_base >; - //friend class edge_iterator_base >; - value_type _first; - bool _orientation; - typedef IteratorBase parent_class; - - public: - friend class ViewEdge; - inline edge_iterator_base() - : parent_class() - {_orientation=true;_first=0;} - - inline edge_iterator_base(const edge_iterator_base >& iBrother) - : parent_class() - { - _ViewEdge = iBrother._ViewEdge; - _first = iBrother._first; - _orientation = iBrother._orientation; - } - - inline edge_iterator_base(const edge_iterator_base >& 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 - inline Self& operator++() // operator corresponding to ++i - { - //++_ViewEdge->getTimeStamp(); - increment(); - return *this; - } - inline Self operator++(int) // opérateur correspondant à i++ - { // c.a.d qui renvoie la valeur *puis* incrémente. - //++_ViewEdge->getTimeStamp(); - Self tmp = *this; // C'est pour cela qu'on stocke la valeur - increment(); // dans un temporaire. - return tmp; - } - inline Self& operator--() // operator corresponding to ++i - { - //++_ViewEdge->getTimeStamp(); - decrement(); - return *this; - } - inline Self operator--(int) // opérateur correspondant à i++ - { // c.a.d qui renvoie la valeur *puis* incrémente. - //++_ViewEdge->getTimeStamp(); - Self tmp = *this; // C'est pour cela qu'on stocke la valeur - decrement(); // dans un temporaire. - 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 fedge_iterator_base : public IteratorBase - { - 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 Self; - public: - typedef IteratorBase 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 >& iBrother) - : parent_class() - { - _FEdge = iBrother._FEdge; - _first = iBrother._first; - _FEdgeB = iBrother._FEdgeB; - } - inline fedge_iterator_base(const fedge_iterator_base >& 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 - inline Self& operator++() // operator corresponding to ++i - { - increment(); - return *this; - } - inline Self operator++(int) // opérateur correspondant à i++ - { // c.a.d qui renvoie la valeur *puis* incrémente. - Self tmp = *this; // C'est pour cela qu'on stocke la valeur - increment(); // dans un temporaire. - return tmp; - } - inline Self& operator--() // operator corresponding to ++i - { - decrement(); - return *this; - } - inline Self operator--(int) // opérateur correspondant à i++ - { // c.a.d qui renvoie la valeur *puis* incrémente. - Self tmp = *this; // C'est pour cela qu'on stocke la valeur - decrement(); // dans un temporaire. - 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 vertex_iterator_base : public IteratorBase - { - 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 Self; - protected: - typedef IteratorBase 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 >& iBrother) - : parent_class() - { - _SVertex = iBrother._SVertex; - _NextFEdge = iBrother._NextFEdge; - _PreviousFEdge = iBrother._PreviousFEdge; - } - inline vertex_iterator_base(const vertex_iterator_base >& 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 - inline Self& operator++() // operator corresponding to ++i - { - increment(); - return *this; - } - inline Self operator++(int) // opérateur correspondant à i++ - { // c.a.d qui renvoie la valeur *puis* incrémente. - Self tmp = *this; // C'est pour cela qu'on stocke la valeur - increment(); // dans un temporaire. - return tmp; - } - inline Self& operator--() // operator corresponding to ++i - { - decrement(); - return *this; - } - inline Self operator--(int) // opérateur correspondant à i++ - { // c.a.d qui renvoie la valeur *puis* incrémente. - Self tmp = *this; // C'est pour cela qu'on stocke la valeur - decrement(); // dans un temporaire. - 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(0 == _NextFEdge) - { - _SVertex = 0; - return; - } - - _SVertex = _NextFEdge->vertexB(); - _PreviousFEdge = _NextFEdge; - _NextFEdge = _NextFEdge->nextEdge(); - - } - virtual void decrement() - { - // if(0 == _SVertex) - // { - // _SVertex = _PreviousFEdge->vertexB(); - // return; - // } - if(0 == _PreviousFEdge) - { - _SVertex = 0; - return; - } - _SVertex = _PreviousFEdge->vertexA(); - _NextFEdge = _PreviousFEdge; - _PreviousFEdge = _PreviousFEdge->previousEdge(); - } - }; - - +/*!----------------------*/ +/*! Iterators definition */ +/*!----------------------*/ +template +class edge_iterator_base : public IteratorBase +{ +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 Self; + +public: + mutable value_type _ViewEdge; + //friend class edge_iterator_base >; + //friend class edge_iterator_base >; + value_type _first; + bool _orientation; + typedef IteratorBase parent_class; + +public: + friend class ViewEdge; + inline edge_iterator_base() : parent_class() + { + _orientation = true; + _first = 0; + } + + inline edge_iterator_base(const edge_iterator_base >& iBrother) : parent_class() + { + _ViewEdge = iBrother._ViewEdge; + _first = iBrother._first; + _orientation = iBrother._orientation; + } + + inline edge_iterator_base(const edge_iterator_base >& 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 fedge_iterator_base : public IteratorBase +{ +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 Self; + +public: + typedef IteratorBase 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 >& iBrother) : parent_class() + { + _FEdge = iBrother._FEdge; + _first = iBrother._first; + _FEdgeB = iBrother._FEdgeB; + } + + inline fedge_iterator_base(const fedge_iterator_base >& 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 vertex_iterator_base : public IteratorBase +{ +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 Self; + +protected: + typedef IteratorBase 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 >& iBrother) : parent_class() + { + _SVertex = iBrother._SVertex; + _NextFEdge = iBrother._NextFEdge; + _PreviousFEdge = iBrother._PreviousFEdge; + } + + inline vertex_iterator_base(const vertex_iterator_base >& 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; + } +#endif + if (!_PreviousFEdge) { + _SVertex = NULL; + return; + } + _SVertex = _PreviousFEdge->vertexA(); + _NextFEdge = _PreviousFEdge; + _PreviousFEdge = _PreviousFEdge->previousEdge(); + } +}; + } // end of namespace ViewEdgeInternal -#endif // VIEWMAPADVANCEDITERATORS_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 d503daa3696..84cd166dca0 100644 --- a/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp +++ b/source/blender/freestyle/intern/view_map/ViewMapBuilder.cpp @@ -1,828 +1,827 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/freestyle/intern/view_map/ViewMapBuilder.cpp + * \ingroup freestyle + * \brief Class to build silhouette edges from a Winged-Edge structure + * \author Stephane Grabli + * \date 25/03/2002 + */ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#include "ViewMapBuilder.h" #include -#include #include -#include "../winged_edge/WFillGrid.h" -#include "../../FRS_freestyle.h" -#include "../geometry/GeomUtils.h" -#include "../geometry/GridHelpers.h" +#include + +#include "FRS_freestyle.h" + #include "BoxGrid.h" -#include "SphericalGrid.h" -#include "OccluderSource.h" #include "CulledOccluderSource.h" #include "HeuristicGridDensityProviderFactory.h" +#include "OccluderSource.h" +#include "SphericalGrid.h" +#include "ViewMapBuilder.h" -#define logging 0 +#include "../geometry/GridHelpers.h" +#include "../geometry/GeomUtils.h" + +#include "../winged_edge/WFillGrid.h" + +#define LOGGING FALSE using namespace std; template -static void findOccludee(FEdge *fe, G& grid, I& occluders, real epsilon, WFace** oaWFace, - Vec3r& u, Vec3r& A, Vec3r& origin, Vec3r& edge, vector& faceVertices) +static void findOccludee(FEdge *fe, G& grid, I& occluders, real epsilon, WFace **oaWFace, + Vec3r& u, Vec3r& A, Vec3r& origin, Vec3r& edge, vector& faceVertices) { - WFace *face = 0; - if(fe->isSmooth()){ - FEdgeSmooth * fes = dynamic_cast(fe); - face = (WFace*)fes->face(); - } - WFace * oface; - bool skipFace; - - WVertex::incoming_edge_iterator ie; - - *oaWFace = 0; - 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 > 0 - 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::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, edge, p->getNormal(), d, t, epsilon)) { -#if logging > 0 -cout << "\t\tRejecting occluder for target coincidence." << endl; -#endif - continue; - } - } - - if(p->rayIntersect(A, v, t, t_u, t_v)) - { -#if logging > 0 -cout << "\t\tRay " << A << " * " << v << " intersects at time " << t << endl; -#endif -#if logging > 0 -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 (tsetOccludeeIntersection(Vec3r(A+t*v)); -#if logging > 0 -cout << "\t\tIs occludee" << endl; -#endif - } - } + WFace *face = NULL; + if (fe->isSmooth()) { + FEdgeSmooth *fes = dynamic_cast(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 + 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::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, edge, p->getNormal(), d, t, epsilon)) + { + #if LOGGING + cout << "\t\tRejecting occluder for target coincidence." << endl; + #endif + continue; + } + } - occluders.reportDepth(A, v, t); - } + if (p->rayIntersect(A, v, t, t_u, t_v)) { + #if LOGGING + 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 LOGGING + cout << "\t\tIs occludee" << endl; + #endif + } + } + } - } - - if(noIntersection) - *oaWFace = 0; - } + occluders.reportDepth(A, v, t); + } + } + + if (noIntersection) + *oaWFace = NULL; + } } template -static void findOccludee(FEdge *fe, G& grid, real epsilon, ViewEdge* ve, WFace** oaFace) +static void findOccludee(FEdge *fe, G& grid, real epsilon, ViewEdge *ve, WFace **oaFace) { - Vec3r A; - Vec3r edge; - Vec3r origin; - A = Vec3r(((fe)->vertexA()->point3D() + (fe)->vertexB()->point3D()) / 2.0); - edge = Vec3r((fe)->vertexB()->point3D()-(fe)->vertexA()->point3D()); - 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 faceVertices; - - WFace *face = 0; - if(fe->isSmooth()) { - FEdgeSmooth * fes = dynamic_cast(fe); - face = (WFace*)fes->face(); - } - - if(0 != face) { - face->RetrieveVertexList(faceVertices); - } - - I occluders(grid, A, epsilon); - findOccludee(fe, grid, occluders, epsilon, oaFace, u, A, origin, edge, faceVertices); + Vec3r A; + Vec3r edge; + Vec3r origin; + A = Vec3r(((fe)->vertexA()->point3D() + (fe)->vertexB()->point3D()) / 2.0); + edge = Vec3r((fe)->vertexB()->point3D() - (fe)->vertexA()->point3D()); + 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 faceVertices; + + WFace *face = NULL; + if (fe->isSmooth()) { + FEdgeSmooth *fes = dynamic_cast(fe); + face = (WFace*)fes->face(); + } + + if (face) { + face->RetrieveVertexList(faceVertices); + } + + I occluders(grid, A, epsilon); + findOccludee(fe, grid, occluders, epsilon, oaFace, u, A, origin, edge, faceVertices); } // computeVisibility takes a pointer to foundOccluders, instead of using a reference, // so that computeVeryFastVisibility can skip the AddOccluders step with minimal overhead. template -static int computeVisibility(ViewMap* viewMap, FEdge *fe, G& grid, real epsilon, ViewEdge* ve, WFace** oaWFace, set* foundOccluders) +static int computeVisibility(ViewMap *viewMap, FEdge *fe, G& grid, real epsilon, ViewEdge *ve, WFace **oaWFace, + set *foundOccluders) { - int qi = 0; - - Vec3r center; - Vec3r edge; - Vec3r origin; - - center = fe->center3d(); - edge = Vec3r(fe->vertexB()->point3D() - fe->vertexA()->point3D()); - 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 = 0; - if(fe->isSmooth()){ - FEdgeSmooth * fes = dynamic_cast(fe); - face = (WFace*)fes->face(); - } - vector 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 > 0 - 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 + int qi = 0; -#if logging > 0 - Vec3r v(vp - center); - real rl = v.norm(); - v.normalize(); - vector points; - // Iterate over vertices, storing projections in points - for(vector::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()); - 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()); -#endif - - if(0 != face) - { -#if logging > 0 -cout << "\t\tDetermining face adjacency..."; -#endif - skipFace = false; - - if(face == oface) { -#if logging > 0 -cout << " Rejecting occluder for face concurrency." << endl; -#endif - continue; - } - - - for(vector::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 > 0 -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, edge, p->getNormal(), d, t, epsilon)) { -#if logging > 0 -cout << "\t\tRejecting occluder for target coincidence." << endl; -#endif - continue; - } - } + Vec3r center; + Vec3r edge; + Vec3r origin; -#if logging > 0 + center = fe->center3d(); + edge = Vec3r(fe->vertexB()->point3D() - fe->vertexA()->point3D()); + origin = Vec3r(fe->vertexA()->point3D()); - 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; + 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(fe); + face = (WFace*)fes->face(); + } + vector 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 + 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 points; + // Iterate over vertices, storing projections in points + for (vector::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()); + 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()); + #endif + + if (face) + { + #if LOGGING + cout << "\t\tDetermining face adjacency..."; + #endif + skipFace = false; + + if (face == oface) { + #if LOGGING + cout << " Rejecting occluder for face concurrency." << endl; + #endif + continue; + } -#endif - if(p->rayIntersect(center, u, t, t_u, t_v)) - { -#if logging > 0 -cout << "\t\tRay " << center << " * " << u << " intersects at time " << t << " (raylength is " << raylength << ")" << endl; -#endif -#if logging > 0 -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 0 -cout << "\t\tIs occluder" << endl; -#endif - if ( foundOccluders != NULL ) { - ViewShape *vshape = viewMap->viewShape(oface->GetVertex(0)->shape()->GetId()); - foundOccluders->insert(vshape); - } + for (vector::iterator fv = faceVertices.begin(), fvend = faceVertices.end(); fv != fvend; ++fv) { + if ((*fv)->isBoundary()) + continue; - ++qi; + 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 + 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, edge, p->getNormal(), d, t, epsilon)) { + #if LOGGING + cout << "\t\tRejecting occluder for target coincidence." << endl; + #endif + continue; + } + } + + #if LOGGING + 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 LOGGING + 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 LOGGING + 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; - } + if (! grid.enableQI()) + break; + } - occluders.reportDepth(center, u, t); + occluders.reportDepth(center, u, t); + } + } } - } - // Find occludee - findOccludee(fe, grid, occluders, epsilon, oaWFace, u, center, origin, edge, faceVertices); + // Find occludee + findOccludee(fe, grid, occluders, epsilon, oaWFace, u, center, origin, edge, faceVertices); - return qi; + return qi; } -// computeCumulativeVisibility returns the lowest x such that the majority -// of FEdges have QI <= x +// computeCumulativeVisibility returns the lowest x such that the majority of FEdges have QI <= x // -// This was probably the original intention of the "normal" algorithm -// on which computeDetailedVisibility is based. But because the "normal" -// algorithm chooses the most popular QI, without considering any other -// values, a ViewEdge with FEdges having QIs of 0, 21, 22, 23, 24 and 25 -// will end up having a total QI of 0, even though most of the FEdges are -// heavily occluded. computeCumulativeVisibility will treat this case as -// a QI of 22 because 3 out of 6 occluders have QI <= 22. +// This was probably the original intention of the "normal" algorithm on which computeDetailedVisibility is based. +// But because the "normal" algorithm chooses the most popular QI, without considering any other values, a ViewEdge +// with FEdges having QIs of 0, 21, 22, 23, 24 and 25 will end up having a total QI of 0, even though most of the +// FEdges are heavily occluded. computeCumulativeVisibility will treat this case as a QI of 22 because 3 out of +// 6 occluders have QI <= 22. template static void computeCumulativeVisibility(ViewMap *ioViewMap, G& grid, real epsilon, RenderMonitor *iRenderMonitor) { - vector& vedges = ioViewMap->ViewEdges(); - - FEdge * fe, *festart; - int nSamples = 0; - vector wFaces; - WFace *wFace = 0; - unsigned tmpQI = 0; - unsigned qiClasses[256]; - unsigned maxIndex, maxCard; - unsigned qiMajority; - for(vector::iterator ve=vedges.begin(), veend=vedges.end(); ve!=veend; ve++) { - if (iRenderMonitor && iRenderMonitor->testBreak()) - break; -#if logging > 0 -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); -#if logging > 0 -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. - 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 > 0 -cout << "\tqiMajority: " << qiMajority << endl; -#endif + vector& vedges = ioViewMap->ViewEdges(); - tmpQI = 0; - maxIndex = 0; - maxCard = 0; - nSamples = 0; - memset(qiClasses, 0, 256 * sizeof(*qiClasses)); - set foundOccluders; - - fe = (*ve)->fedgeA(); - do - { - if ( fe == NULL || ! fe->isInImage() ) { - fe = fe->nextEdge(); - continue; - } - if((maxCard < qiMajority)) { - tmpQI = computeVisibility(ioViewMap, fe, grid, epsilon, *ve, &wFace, &foundOccluders); //ARB: change &wFace to wFace and use reference in called function -#if logging > 0 -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, *ve, &wFace); //ARB: change &wFace to wFace and use reference in called function -#if logging > 0 -cout << "\tFEdge: occludee only (" << (wFace != NULL ? "found" : "not found") << ")" << endl; -#endif - } - - // Store test results - if(wFace) { - vector 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 > 0 -cout << "\tFound occludee" << endl; -#endif - } else { - fe->setOccludeeEmpty(true); - } - - ++nSamples; - fe = fe->nextEdge(); - } - while((maxCard < qiMajority) && (0!=fe) && (fe!=festart)); -#if logging > 0 -cout << "\tFinished with " << nSamples << " samples, maxCard = " << maxCard << endl; -#endif + FEdge *fe, *festart; + int nSamples = 0; + vector wFaces; + WFace *wFace = NULL; + unsigned tmpQI = 0; + unsigned qiClasses[256]; + unsigned maxIndex, maxCard; + unsigned qiMajority; + for (vector::iterator ve = vedges.begin(), veend = vedges.end(); ve != veend; ve++) { + if (iRenderMonitor && iRenderMonitor->testBreak()) + break; + #if LOGGING + 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); + #if LOGGING + cout << "\tCulled." << endl; + #endif + continue; + } - // 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 - // this set and then copying out its contents. Is there a reason why - // ViewEdge::_Occluders cannot be converted to a set<>? - for(set::iterator o=foundOccluders.begin(), oend=foundOccluders.end(); o!=oend; ++o) { - (*ve)->AddOccluder((*o)); - } -#if logging > 0 -cout << "\tConclusion: QI = " << maxIndex << ", " << (*ve)->occluders_size() << " occluders." << endl; -#endif - // occludee -- - if(!wFaces.empty()) - { - if(wFaces.size() <= (float)nSamples/2.f) - { - (*ve)->setaShape(0); - } - else - { - ViewShape *vshape = ioViewMap->viewShape((*wFaces.begin())->GetVertex(0)->shape()->GetId()); - (*ve)->setaShape(vshape); - } - } - - wFaces.clear(); - } + // 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. + 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 + cout << "\tqiMajority: " << qiMajority << endl; + #endif + + tmpQI = 0; + maxIndex = 0; + maxCard = 0; + nSamples = 0; + memset(qiClasses, 0, 256 * sizeof(*qiClasses)); + set 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(ioViewMap, fe, grid, epsilon, *ve, &wFace, &foundOccluders); + #if LOGGING + 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(fe, grid, epsilon, *ve, &wFace); + #if LOGGING + cout << "\tFEdge: occludee only (" << (wFace != NULL ? "found" : "not found") << ")" << endl; + #endif + } + + // Store test results + if (wFace) { + vector 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 + cout << "\tFound occludee" << endl; + #endif + } + else { + fe->setOccludeeEmpty(true); + } + + ++nSamples; + fe = fe->nextEdge(); + } while ((maxCard < qiMajority) && (fe) && (fe != festart)); + + #if LOGGING + 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::iterator o = foundOccluders.begin(), oend = foundOccluders.end(); o != oend; ++o) { + (*ve)->AddOccluder((*o)); + } + #if LOGGING + 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(); + } } template static void computeDetailedVisibility(ViewMap *ioViewMap, G& grid, real epsilon, RenderMonitor *iRenderMonitor) { - vector& vedges = ioViewMap->ViewEdges(); - - FEdge * fe, *festart; - int nSamples = 0; - vector wFaces; - WFace *wFace = 0; - unsigned tmpQI = 0; - unsigned qiClasses[256]; - unsigned maxIndex, maxCard; - unsigned qiMajority; - for(vector::iterator ve=vedges.begin(), veend=vedges.end(); ve!=veend; ve++) { - if (iRenderMonitor && iRenderMonitor->testBreak()) - break; -#if logging > 0 -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); -#if logging > 0 -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. - 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 > 0 -cout << "\tqiMajority: " << qiMajority << endl; -#endif + vector& vedges = ioViewMap->ViewEdges(); - tmpQI = 0; - maxIndex = 0; - maxCard = 0; - nSamples = 0; - memset(qiClasses, 0, 256 * sizeof(*qiClasses)); - set foundOccluders; - - fe = (*ve)->fedgeA(); - do - { - if ( fe == NULL || ! fe->isInImage() ) { - fe = fe->nextEdge(); - continue; - } - if((maxCard < qiMajority)) { - tmpQI = computeVisibility(ioViewMap, fe, grid, epsilon, *ve, &wFace, &foundOccluders); //ARB: change &wFace to wFace and use reference in called function -#if logging > 0 -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, *ve, &wFace); //ARB: change &wFace to wFace and use reference in called function -#if logging > 0 -cout << "\tFEdge: occludee only (" << (wFace != NULL ? "found" : "not found") << ")" << endl; -#endif - } - - // Store test results - if(wFace) { - vector 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 > 0 -cout << "\tFound occludee" << endl; -#endif - } else { - fe->setOccludeeEmpty(true); - } - - ++nSamples; - fe = fe->nextEdge(); - } - while((maxCard < qiMajority) && (0!=fe) && (fe!=festart)); -#if logging > 0 -cout << "\tFinished with " << nSamples << " samples, maxCard = " << maxCard << endl; -#endif + FEdge *fe, *festart; + int nSamples = 0; + vector wFaces; + WFace *wFace = NULL; + unsigned tmpQI = 0; + unsigned qiClasses[256]; + unsigned maxIndex, maxCard; + unsigned qiMajority; + for (vector::iterator ve = vedges.begin(), veend = vedges.end(); ve != veend; ve++) { + if (iRenderMonitor && iRenderMonitor->testBreak()) + break; + #if LOGGING + 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); + #if LOGGING + cout << "\tCulled." << endl; + #endif + continue; + } - // 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::iterator o=foundOccluders.begin(), oend=foundOccluders.end(); o!=oend; ++o) { - (*ve)->AddOccluder((*o)); - } -#if logging > 0 -cout << "\tConclusion: QI = " << maxIndex << ", " << (*ve)->occluders_size() << " occluders." << endl; -#endif - // occludee -- - if(!wFaces.empty()) - { - if(wFaces.size() <= (float)nSamples/2.f) - { - (*ve)->setaShape(0); - } - else - { - ViewShape *vshape = ioViewMap->viewShape((*wFaces.begin())->GetVertex(0)->shape()->GetId()); - (*ve)->setaShape(vshape); - } - } - - wFaces.clear(); - } + // 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. + 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 + cout << "\tqiMajority: " << qiMajority << endl; + #endif + + tmpQI = 0; + maxIndex = 0; + maxCard = 0; + nSamples = 0; + memset(qiClasses, 0, 256 * sizeof(*qiClasses)); + set 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(ioViewMap, fe, grid, epsilon, *ve, &wFace, &foundOccluders); + #if LOGGING + 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(fe, grid, epsilon, *ve, &wFace); + #if LOGGING + cout << "\tFEdge: occludee only (" << (wFace != NULL ? "found" : "not found") << ")" << endl; + #endif + } + + // Store test results + if (wFace) { + vector 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 + cout << "\tFound occludee" << endl; + #endif + } + else { + fe->setOccludeeEmpty(true); + } + + ++nSamples; + fe = fe->nextEdge(); + } while ((maxCard < qiMajority) && (fe) && (fe != festart)); + + #if LOGGING + 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::iterator o = foundOccluders.begin(), oend = foundOccluders.end(); o != oend; ++o) { + (*ve)->AddOccluder((*o)); + } + #if LOGGING + 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(); + } } template static void computeFastVisibility(ViewMap *ioViewMap, G& grid, real epsilon) { - vector& vedges = ioViewMap->ViewEdges(); - - FEdge * fe, *festart; - unsigned nSamples = 0; - vector wFaces; - WFace *wFace = 0; - unsigned tmpQI = 0; - unsigned qiClasses[256]; - unsigned maxIndex, maxCard; - unsigned qiMajority; - bool even_test; - for(vector::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 != NULL && 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. - 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 foundOccluders; - - fe = (*ve)->fedgeA(); - do - { - if ( fe == NULL || ! fe->isInImage() ) { - fe = fe->nextEdge(); - continue; - } - if (even_test) - { - if((maxCard < qiMajority)) { - tmpQI = computeVisibility(ioViewMap, fe, grid, epsilon, *ve, &wFace, &foundOccluders); //ARB: change &wFace to wFace and use reference in called function - - //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, *ve, &wFace); //ARB: change &wFace to wFace and use reference in called function - } - - if(wFace) - { - vector 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) && (0!=fe) && (fe!=festart)); - - // qi -- - (*ve)->setQI(maxIndex); - - // occluders -- - for(set::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& vedges = ioViewMap->ViewEdges(); + + FEdge *fe, *festart; + unsigned nSamples = 0; + vector wFaces; + WFace *wFace = NULL; + unsigned tmpQI = 0; + unsigned qiClasses[256]; + unsigned maxIndex, maxCard; + unsigned qiMajority; + bool even_test; + for (vector::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. + 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 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(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(fe, grid, epsilon, *ve, &wFace); + } + + if (wFace) { + vector 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::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 @@ -830,14 +829,13 @@ static void computeVeryFastVisibility(ViewMap *ioViewMap, G& grid, real epsilon) { vector& vedges = ioViewMap->ViewEdges(); - FEdge* fe; + FEdge *fe; unsigned qi = 0; - WFace* wFace = 0; + WFace *wFace = 0; - for(vector::iterator ve=vedges.begin(), veend=vedges.end(); ve!=veend; ve++) - { + for (vector::iterator ve = vedges.begin(), veend = vedges.end(); ve != veend; ve++) { // Find an edge to test - if ( ! (*ve)->isInImage() ) { + if (!(*ve)->isInImage()) { // This view edge has been proscenium culled (*ve)->setQI(255); (*ve)->setaShape(0); @@ -845,16 +843,13 @@ static void computeVeryFastVisibility(ViewMap *ioViewMap, G& grid, real epsilon) } fe = (*ve)->fedgeA(); // Find a FEdge inside the occluder proscenium to test for visibility - FEdge* festart = fe; - while ( fe != NULL && ! fe->isInImage() ) { + FEdge *festart = fe; + while (fe && !fe->isInImage() && fe != festart) { fe = fe->nextEdge(); - if ( fe == festart ) { - break; - } } // Test edge - if ( fe == NULL || ! fe->isInImage() ) { + if (!fe || !fe->isInImage()) { // There are no occludable FEdges on this ViewEdge // This should be impossible. cout << "View Edge in viewport without occludable FEdges: " << (*ve)->getId() << endl; @@ -862,80 +857,81 @@ static void computeVeryFastVisibility(ViewMap *ioViewMap, G& grid, real epsilon) // Treat this edge as fully visible with no occludee qi = 0; wFace = NULL; - } else { + } + else { qi = computeVisibility(ioViewMap, fe, grid, epsilon, *ve, &wFace, NULL); } // Store test results - if(wFace) - { + if (wFace) { vector vertices; - for ( int i = 0, numEdges = wFace->numberOfEdges(); i < numEdges; ++i ) { + 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; + 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 - { + } + else { (*ve)->setaShape(0); } (*ve)->setQI(qi); - } - + } } -void ViewMapBuilder::BuildGrid(WingedEdge& we, const BBox& 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]); - size[i] += size[i]/10.0; // let make the grid 1/10 bigger to avoid numerical errors while computing triangles/cells intersections - if(size[i]==0){ - cout << "Warning: the bbox size is 0 in dimension "<configure(Vec3r(bbox.getMin() - size / 20.0), size, sceneNumFaces); - - // Fill in the grid: - WFillGrid fillGridRenderer(_Grid, &we); - fillGridRenderer.fillGrid(); - - // DEBUG - _Grid->displayDebug(); +void ViewMapBuilder::BuildGrid(WingedEdge& we, const BBox& 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]); + size[i] += size[i]/10.0; // let make the grid 1/10 bigger to avoid numerical errors while computing triangles/cells intersections + if (size[i] == 0) { + 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& bbox, unsigned int sceneNumFaces) { - _ViewMap = new ViewMap; - _currentId = 1; - _currentFId = 0; - _currentSVertexId = 0; - - // Builds initial view edges - computeInitialViewEdges(we); - - // Detects cusps - computeCusps(_ViewMap); - - // Compute intersections - ComputeIntersections(_ViewMap, sweep_line, epsilon); - - // Compute visibility - ComputeEdgesVisibility(_ViewMap, we, bbox, sceneNumFaces, iAlgo, epsilon); - - return _ViewMap; +ViewMap *ViewMapBuilder::BuildViewMap(WingedEdge& we, visibility_algo iAlgo, real epsilon, + const BBox& bbox, unsigned int sceneNumFaces) +{ + _ViewMap = new ViewMap; + _currentId = 1; + _currentFId = 0; + _currentSVertexId = 0; + + // Builds initial view edges + computeInitialViewEdges(we); + + // Detects cusps + computeCusps(_ViewMap); + + // Compute intersections + ComputeIntersections(_ViewMap, sweep_line, epsilon); + + // Compute visibility + ComputeEdgesVisibility(_ViewMap, we, bbox, sceneNumFaces, iAlgo, epsilon); + + 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])); } -static inline bool crossesProscenium(real proscenium[4], FEdge *fe) { +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()); @@ -944,20 +940,21 @@ static inline bool crossesProscenium(real proscenium[4], FEdge *fe) { return GeomUtils::intersect2dSeg2dArea (min, max, A, B); } -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] ); +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]); } -void ViewMapBuilder::CullViewEdges(ViewMap *ioViewMap, real viewProscenium[4], real occluderProscenium[4], bool extensiveFEdgeSearch) { +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. + // This avoids the complications of trying to delete edges from the ViewMap. - // Non-displayable view edges will be skipped over during - // visibility calculation. + // 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, + // 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 @@ -966,34 +963,30 @@ void ViewMapBuilder::CullViewEdges(ViewMap *ioViewMap, real viewProscenium[4], r prosceniumOrigin[0] = (viewProscenium[1] - viewProscenium[0]) / 2.0; prosceniumOrigin[1] = (viewProscenium[3] - viewProscenium[2]) / 2.0; cout << "Proscenium culling:" << endl; - cout << "Proscenium: [" << viewProscenium[0] << ", " << viewProscenium[1] << ", " << viewProscenium[2] << ", " << viewProscenium[3] << "]"<< 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 + + // 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 + // 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::iterator. Probably all occurences of vector::iterator - // should be replaced ViewMap::viewedges_container throughout the code. + // N.B. Freestyle is inconsistent in its use of ViewMap::viewedges_container and vector::iterator. + // Probably all occurences of vector::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++) { + 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. + // 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 @@ -1005,27 +998,26 @@ void ViewMapBuilder::CullViewEdges(ViewMap *ioViewMap, real viewProscenium[4], r // 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. + // 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()) ) { + // 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 { + } + else { real d = distance2D(fe->center2d(), prosceniumOrigin); // If center point is closer to viewport origin than current target - if ( bestOccluderTarget == NULL || d < bestOccluderDistance ) { + if (bestOccluderTarget == NULL || d < bestOccluderDistance) { // Then store as bestOccluderTarget bestOccluderDistance = d; bestOccluderTarget = fe; @@ -1034,33 +1026,35 @@ void ViewMapBuilder::CullViewEdges(ViewMap *ioViewMap, real viewProscenium[4], r } // If feature edge crosses the view proscenium - if ( ! (*ve)->isInImage() && crossesProscenium(viewProscenium, fe) ) { + 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() ) ); + } 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 != NULL && fe != festart ) { + 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 ) { + // 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] ) { + if (point[0] < occluderProscenium[0]) { occluderProscenium[0] = point[0]; - } else if ( point[0] > occluderProscenium[1] ) { + } + else if (point[0] > occluderProscenium[1]) { occluderProscenium[1] = point[0]; } - if ( point[1] < occluderProscenium[2] ) { + if (point[1] < occluderProscenium[2]) { occluderProscenium[2] = point[1]; - } else if ( point[1] > occluderProscenium[3] ) { + } + else if (point[1] > occluderProscenium[3]) { occluderProscenium[3] = point[1]; } // Use bestOccluderTarget for visibility determination @@ -1078,22 +1072,18 @@ void ViewMapBuilder::CullViewEdges(ViewMap *ioViewMap, real viewProscenium[4], r // 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 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() ) { + for (ve = ioViewMap->ViewEdges().begin(), veend = ioViewMap->ViewEdges().end(); ve != veend; ve++) { + if (!(*ve)->isInImage()) { continue; } // For each feature edge, @@ -1101,255 +1091,257 @@ void ViewMapBuilder::CullViewEdges(ViewMap *ioViewMap, real viewProscenium[4], r FEdge *fe = festart; do { // If not (already) visible and center point inside occluder proscenium, - if ( ! fe->isInImage() && insideProscenium(occluderProscenium, fe->center2d()) ) { + if (!fe->isInImage() && insideProscenium(occluderProscenium, fe->center2d())) { // Use the feature edge for visibility determination fe->setIsInImage(true); } fe = fe->nextEdge(); - } while ( fe != NULL && fe != festart ); + } while (fe && fe != festart); } } } void ViewMapBuilder::computeInitialViewEdges(WingedEdge& we) { - vector wshapes = we.getWShapes(); - SShape* psShape; - - for (vector::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->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); - - _pViewEdgeBuilder->setCurrentViewId(_currentId); // we want to number the view edges in a unique way for the while scene. - _pViewEdgeBuilder->setCurrentFId(_currentFId); // we want to number the feature edges in a unique way for the while scene. - _pViewEdgeBuilder->setCurrentSVertexId(_currentFId); // we want to number the SVertex in a unique way for the while scene. - _pViewEdgeBuilder->BuildViewEdges(dynamic_cast(*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 wshapes = we.getWShapes(); + SShape *psShape; + + for (vector::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->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(*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 newVVertices; - vector 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(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 = 0; - if(positive){ - if(((crossP)*(viewvector)) < -0.1){ - // state changes - positive = false; - // creates and insert cusp - cusp = dynamic_cast(ioViewMap->InsertViewVertex(fes->vertexA(), newVEdges)); - if(cusp!=0) - 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(ioViewMap->InsertViewVertex(fes->vertexA(), newVEdges)); - if(cusp!=0) - cusp->setNature(cusp->getNature()|Nature::CUSP); - } - } - fe = fe->nextEdge(); - }while((fe!=0) && (fe!=fefirst)); - } - for(ve=newVEdges.begin(), veend=newVEdges.end(); - ve!=veend; - ++ve){ - (*ve)->viewShape()->AddEdge(*ve); - vedges.push_back(*ve); - } +void ViewMapBuilder::computeCusps(ViewMap *ioViewMap) +{ + vector newVVertices; + vector 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(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(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(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& bbox, real epsilon, bool cull, GridDensityProviderFactory& factory) +void ViewMapBuilder::ComputeCumulativeVisibility(ViewMap *ioViewMap, WingedEdge& we, const BBox& bbox, + real epsilon, bool cull, GridDensityProviderFactory& factory) { auto_ptr transform; auto_ptr source; - if ( _orthographicProjection ) { + if (_orthographicProjection) { transform.reset(new BoxGrid::Transform); - } else { + } + else { transform.reset(new SphericalGrid::Transform); } - if ( cull ) { + if (cull) { source.reset(new CulledOccluderSource(*transform, we, *ioViewMap, true)); - } else { + } + else { source.reset(new OccluderSource(*transform, we)); } auto_ptr density(factory.newGridDensityProvider(*source, bbox, *transform)); - if ( _orthographicProjection ) { + if (_orthographicProjection) { BoxGrid grid(*source, *density, ioViewMap, _viewpoint, _EnableQI); computeCumulativeVisibility(ioViewMap, grid, epsilon, _pRenderMonitor); - } else { + } + else { SphericalGrid grid(*source, *density, ioViewMap, _viewpoint, _EnableQI); computeCumulativeVisibility(ioViewMap, grid, epsilon, _pRenderMonitor); } } -void ViewMapBuilder::ComputeDetailedVisibility(ViewMap *ioViewMap, - WingedEdge& we, const BBox& bbox, real epsilon, bool cull, GridDensityProviderFactory& factory) +void ViewMapBuilder::ComputeDetailedVisibility(ViewMap *ioViewMap, WingedEdge& we, const BBox& bbox, + real epsilon, bool cull, GridDensityProviderFactory& factory) { auto_ptr transform; auto_ptr source; - if ( _orthographicProjection ) { + if (_orthographicProjection) { transform.reset(new BoxGrid::Transform); - } else { + } + else { transform.reset(new SphericalGrid::Transform); } - if ( cull ) { + if (cull) { source.reset(new CulledOccluderSource(*transform, we, *ioViewMap, true)); - } else { + } + else { source.reset(new OccluderSource(*transform, we)); } auto_ptr density(factory.newGridDensityProvider(*source, bbox, *transform)); - if ( _orthographicProjection ) { + if (_orthographicProjection) { BoxGrid grid(*source, *density, ioViewMap, _viewpoint, _EnableQI); computeDetailedVisibility(ioViewMap, grid, epsilon, _pRenderMonitor); - } else { + } + else { SphericalGrid grid(*source, *density, ioViewMap, _viewpoint, _EnableQI); computeDetailedVisibility(ioViewMap, grid, epsilon, _pRenderMonitor); } } -void ViewMapBuilder::ComputeEdgesVisibility(ViewMap *ioViewMap, - WingedEdge& we, const BBox& bbox, unsigned int sceneNumFaces, visibility_algo iAlgo, real epsilon) +void ViewMapBuilder::ComputeEdgesVisibility(ViewMap *ioViewMap, WingedEdge& we, const BBox& bbox, + unsigned int sceneNumFaces, visibility_algo iAlgo, real epsilon) { - switch(iAlgo) - { - case ray_casting: - cout << "Using ordinary ray casting" << endl; - BuildGrid(we, bbox, sceneNumFaces); - ComputeRayCastingVisibility(ioViewMap, epsilon); - break; - case ray_casting_fast: - cout << "Using fast ray casting" << endl; - BuildGrid(we, bbox, sceneNumFaces); - ComputeFastRayCastingVisibility(ioViewMap, epsilon); - break; - case ray_casting_very_fast: - cout << "Using very fast ray casting" << endl; - BuildGrid(we, bbox, sceneNumFaces); - ComputeVeryFastRayCastingVisibility(ioViewMap, epsilon); - break; - case ray_casting_culled_adaptive_traditional: - 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: - 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: - 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: - 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: + cout << "Using ordinary ray casting" << endl; + BuildGrid(we, bbox, sceneNumFaces); + ComputeRayCastingVisibility(ioViewMap, epsilon); + break; + case ray_casting_fast: + cout << "Using fast ray casting" << endl; + BuildGrid(we, bbox, sceneNumFaces); + ComputeFastRayCastingVisibility(ioViewMap, epsilon); + break; + case ray_casting_very_fast: + cout << "Using very fast ray casting" << endl; + BuildGrid(we, bbox, sceneNumFaces); + ComputeVeryFastRayCastingVisibility(ioViewMap, epsilon); + break; + case ray_casting_culled_adaptive_traditional: + 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: + 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: + 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: + 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; @@ -1357,977 +1349,913 @@ static const unsigned gProgressBarMinSize = 2000; void ViewMapBuilder::ComputeRayCastingVisibility(ViewMap *ioViewMap, real epsilon) { - vector& 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 aFaces; - Polygon3r *aFace = 0; - unsigned tmpQI = 0; - unsigned qiClasses[256]; - unsigned maxIndex, maxCard; - unsigned qiMajority; - static unsigned timestamp = 1; - for(vector::iterator ve=vedges.begin(), veend=vedges.end(); - ve!=veend; - ve++) - { - if (_pRenderMonitor && _pRenderMonitor->testBreak()) - break; -#if logging > 0 -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; -#if logging > 0 -cout << "\tqiMajority: " << qiMajority << endl; -#endif + vector& 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; + } - tmpQI = 0; - maxIndex = 0; - maxCard = 0; - nSamples = 0; - fe = (*ve)->fedgeA(); - memset(qiClasses, 0, 256 * sizeof(*qiClasses)); - set occluders; - do - { - if((maxCard < qiMajority)) { - tmpQI = ComputeRayCastingVisibility(fe, _Grid, epsilon, occluders, &aFace, timestamp++); - -#if logging > 0 -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++); -#if logging > 0 -cout << "\tFEdge: occludee only (" << (aFace != NULL ? "found" : "not found") << ")" << endl; -#endif - } - - if(aFace) { - fe->setaFace(*aFace); - aFaces.push_back(aFace); - fe->setOccludeeEmpty(false); -#if logging > 0 -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) && (0!=fe) && (fe!=festart)); -#if logging > 0 -cout << "\tFinished with " << nSamples << " samples, maxCard = " << maxCard << endl; -#endif + unsigned counter = progressBarStep; + FEdge *fe, *festart; + int nSamples = 0; + vector aFaces; + Polygon3r *aFace = NULL; + unsigned tmpQI = 0; + unsigned qiClasses[256]; + unsigned maxIndex, maxCard; + unsigned qiMajority; + static unsigned timestamp = 1; + for (vector::iterator ve = vedges.begin(), veend = vedges.end(); ve != veend; ve++) { + if (_pRenderMonitor && _pRenderMonitor->testBreak()) + break; + #if LOGGING + 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; + #if LOGGING + cout << "\tqiMajority: " << qiMajority << endl; + #endif + + tmpQI = 0; + maxIndex = 0; + maxCard = 0; + nSamples = 0; + fe = (*ve)->fedgeA(); + memset(qiClasses, 0, 256 * sizeof(*qiClasses)); + set occluders; + do { + if ((maxCard < qiMajority)) { + tmpQI = ComputeRayCastingVisibility(fe, _Grid, epsilon, occluders, &aFace, timestamp++); + + #if LOGGING + 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; + } - // ViewEdge - // qi -- - (*ve)->setQI(maxIndex); - // occluders -- - for(set::iterator o=occluders.begin(), oend=occluders.end(); - o!=oend; - ++o) - (*ve)->AddOccluder((*o)); -#if logging > 0 -cout << "\tConclusion: QI = " << maxIndex << ", " << (*ve)->occluders_size() << " occluders." << endl; -#endif - // occludee -- - if(!aFaces.empty()) - { - if(aFaces.size() <= (float)nSamples/2.f) - { - (*ve)->setaShape(0); - } - else - { - vector::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(); - } + 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 + cout << "\tFEdge: occludee only (" << (aFace != NULL ? "found" : "not found") << ")" << endl; + #endif + } + + if (aFace) { + fe->setaFace(*aFace); + aFaces.push_back(aFace); + fe->setOccludeeEmpty(false); + #if LOGGING + 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)); + #if LOGGING + cout << "\tFinished with " << nSamples << " samples, maxCard = " << maxCard << endl; + #endif + + // ViewEdge + // qi -- + (*ve)->setQI(maxIndex); + // occluders -- + for (set::iterator o = occluders.begin(), oend = occluders.end(); o != oend; ++o) + (*ve)->AddOccluder((*o)); + #if LOGGING + 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::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& 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 aFaces; - Polygon3r *aFace = 0; - unsigned tmpQI = 0; - unsigned qiClasses[256]; - unsigned maxIndex, maxCard; - unsigned qiMajority; - static unsigned timestamp = 1; - bool even_test; - for(vector::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 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) && (0!=fe) && (fe!=festart)); - - (*ve)->setQI(maxIndex); - - if(!aFaces.empty()) - { - if(aFaces.size() < nSamples / 2) - { - (*ve)->setaShape(0); - } - else - { - vector::iterator p = aFaces.begin(); - WFace * wface = (WFace*)((*p)->userdata); - ViewShape *vshape = ioViewMap->viewShape(wface->GetVertex(0)->shape()->GetId()); - ++p; - // 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) - (*ve)->setaShape(vshape); - } - } - - //(*ve)->setaFace(aFace); - - if(progressBarDisplay) { - counter--; - if (counter <= 0) { - counter = progressBarStep; - _pProgressBar->setProgress(_pProgressBar->getProgress() + 1); - } - } - aFaces.clear(); - } + vector& 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 aFaces; + Polygon3r *aFace = NULL; + unsigned tmpQI = 0; + unsigned qiClasses[256]; + unsigned maxIndex, maxCard; + unsigned qiMajority; + static unsigned timestamp = 1; + bool even_test; + for (vector::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 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::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) +#endif + (*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& 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 = 0; - static unsigned timestamp = 1; - for(vector::iterator ve=vedges.begin(), veend=vedges.end(); - ve!=veend; - ve++) - { - if (_pRenderMonitor && _pRenderMonitor->testBreak()) - break; - - set 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& 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::iterator ve = vedges.begin(), veend = vedges.end(); ve != veend; ve++) { + if (_pRenderMonitor && _pRenderMonitor->testBreak()) + break; + + set 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& edge, vector& faceVertices) +void ViewMapBuilder::FindOccludee(FEdge *fe, Grid *iGrid, real epsilon, Polygon3r **oaPolygon, unsigned timestamp, + Vec3r& u, Vec3r& A, Vec3r& origin, Vec3r& edge, vector& faceVertices) { - WFace *face = 0; - if(fe->isSmooth()){ - FEdgeSmooth * fes = dynamic_cast(fe); - face = (WFace*)fes->face(); - } - OccludersSet occluders; - WFace * oface; - bool skipFace; - - WVertex::incoming_edge_iterator ie; - OccludersSet::iterator p, pend; - - *oaPolygon = 0; - 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(0 != face) - { - skipFace = false; - - if(face == oface) - continue; - - if(faceVertices.empty()) - continue; - - for(vector::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, edge, 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 (tsetOccludeeIntersection(Vec3r(A+t*v)); - } - } - } - } - - if(noIntersection) - *oaPolygon = 0; - } + WFace *face = NULL; + if (fe->isSmooth()) { + FEdgeSmooth *fes = dynamic_cast(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::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, edge, 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 edge; - Vec3r origin; - A = Vec3r(((fe)->vertexA()->point3D() + (fe)->vertexB()->point3D())/2.0); - edge = Vec3r((fe)->vertexB()->point3D()-(fe)->vertexA()->point3D()); - 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 faceVertices; - - WFace *face = 0; - if(fe->isSmooth()){ - FEdgeSmooth * fes = dynamic_cast(fe); - face = (WFace*)fes->face(); - } - if(0 != face) - face->RetrieveVertexList(faceVertices); - - return FindOccludee(fe,iGrid, epsilon, oaPolygon, timestamp, - u, A, origin, edge, faceVertices); + OccludersSet occluders; + + Vec3r A; + Vec3r edge; + Vec3r origin; + A = Vec3r(((fe)->vertexA()->point3D() + (fe)->vertexB()->point3D()) / 2.0); + edge = Vec3r((fe)->vertexB()->point3D() - (fe)->vertexA()->point3D()); + 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 faceVertices; + + WFace *face = NULL; + if (fe->isSmooth()) { + FEdgeSmooth *fes = dynamic_cast(fe); + face = (WFace*)fes->face(); + } + if (face) + face->RetrieveVertexList(faceVertices); + + return FindOccludee(fe, iGrid, epsilon, oaPolygon, timestamp, u, A, origin, edge, faceVertices); } -int ViewMapBuilder::ComputeRayCastingVisibility(FEdge *fe, Grid* iGrid, real epsilon, set& oOccluders, - Polygon3r** oaPolygon, unsigned timestamp) +int ViewMapBuilder::ComputeRayCastingVisibility(FEdge *fe, Grid *iGrid, real epsilon, set& oOccluders, + Polygon3r **oaPolygon, unsigned timestamp) { - OccludersSet occluders; - int qi = 0; - - Vec3r center; - Vec3r edge; - Vec3r origin; - - center = fe->center3d(); - edge = Vec3r(fe->vertexB()->point3D() - fe->vertexA()->point3D()); - 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; - } - - - // 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 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(); - //cout << "grid origin " << iGrid->getOrigin().x() << "," << iGrid->getOrigin().y() << "," << iGrid->getOrigin().z() << endl; - //cout << "center " << center.x() << "," << center.y() << "," << center.z() << endl; - - iGrid->castRay(center, vp, occluders, timestamp); - - WFace *face = 0; - if(fe->isSmooth()){ - FEdgeSmooth * fes = dynamic_cast(fe); - face = (WFace*)fes->face(); - } - vector 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 > 1 -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; - -#if logging > 1 -cout << "\t\tp: " << ((*p)->getVertices())[0] << ((*p)->getVertices())[1] << ((*p)->getVertices())[2] << ", norm: " << (*p)->getNormal() << endl; -#endif + OccludersSet occluders; + int qi = 0; + + Vec3r center; + Vec3r edge; + Vec3r origin; + + center = fe->center3d(); + edge = Vec3r(fe->vertexB()->point3D() - fe->vertexA()->point3D()); + 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 != face) - { -#if logging > 1 -cout << "\t\tDetermining face adjacency..."; -#endif - skipFace = false; - - if(face == oface) { -#if logging > 1 -cout << " Rejecting occluder for face concurrency." << endl; -#endif - continue; - } - - - for(vector::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 > 1 -cout << " Rejecting occluder for face adjacency." << endl; +#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; + } #endif - continue; - } + + Vec3r vp; + if (_orthographicProjection) { + vp = Vec3r(center.x(), center.y(), _viewpoint.z()); } - else - { - // check whether the edge and the polygon plane are coincident: - //------------------------------------------------------------- - //first let us compute the plane equation. - - if(GeomUtils::COINCIDENT == GeomUtils::intersectRayPlane(origin, edge, normal, d, t, epsilon)) { -#if logging > 1 -cout << "\t\tRejecting occluder for target coincidence." << endl; + else { + vp = Vec3r(_viewpoint); + } + Vec3r u(vp - center); + real raylength = u.norm(); + u.normalize(); +#if 0 + cout << "grid origin " << iGrid->getOrigin().x() << "," << iGrid->getOrigin().y() << "," + << iGrid->getOrigin().z() << endl; + cout << "center " << center.x() << "," << center.y() << "," << center.z() << endl; #endif - continue; - } + + iGrid->castRay(center, vp, occluders, timestamp); + + WFace *face = NULL; + if (fe->isSmooth()) { + FEdgeSmooth *fes = dynamic_cast(fe); + face = (WFace*)fes->face(); } + vector 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 + 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; + + #if LOGGING + cout << "\t\tp: " << ((*p)->getVertices())[0] << ((*p)->getVertices())[1] << ((*p)->getVertices())[2] + << ", norm: " << (*p)->getNormal() << endl; + #endif + + if (face) { + #if LOGGING + cout << "\t\tDetermining face adjacency..."; + #endif + skipFace = false; + + if (face == oface) { + #if LOGGING + cout << " Rejecting occluder for face concurrency." << endl; + #endif + continue; + } - if((*p)->rayIntersect(center, u, t, t_u, t_v)) - { -#if logging > 1 -cout << "\t\tRay " << vp << " * " << u << " intersects at time " << t << " (raylength is " << raylength << ")" << endl; -#endif -#if logging > 1 -cout << "\t\t(u * normal) == " << (u * normal) << " for normal " << normal << endl; -#endif - if (fabs(u * normal) > 0.0001) - if ((t>0.0) && (t 1 -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; - } + for (vector::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 + 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, edge, normal, d, t, epsilon)) { + #if LOGGING + cout << "\t\tRejecting occluder for target coincidence." << endl; + #endif + continue; + } + } + + if ((*p)->rayIntersect(center, u, t, t_u, t_v)) { + #if LOGGING + 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) && (tuserdata); + 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, edge, origin, faceVertices); + // Find occludee + FindOccludee(fe, iGrid, epsilon, oaPolygon, timestamp, u, center, edge, origin, faceVertices); - return qi; + return qi; } void ViewMapBuilder::ComputeIntersections(ViewMap *ioViewMap, intersection_algo iAlgo, real epsilon) { - switch(iAlgo) - { - case sweep_line: - ComputeSweepLineIntersections(ioViewMap, epsilon); - break; - default: - break; - } - 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; - } - } + switch (iAlgo) { + case sweep_line: + ComputeSweepLineIntersections(ioViewMap, epsilon); + break; + default: + break; + } + 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; + } + } } -struct less_SVertex2D : public binary_function +struct less_SVertex2D : public binary_function { - real epsilon; - less_SVertex2D(real eps) - : binary_function() - { - 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; - } + real epsilon; + + less_SVertex2D(real eps) : binary_function() + { + 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 segment; +typedef Segment segment; typedef Intersection intersection; -struct less_Intersection : public binary_function +struct less_Intersection : public binary_function { - segment *edge; - less_Intersection(segment *iEdge) - : binary_function() - { - 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; - } + segment *edge; + + less_Intersection(segment *iEdge) : binary_function() + { + 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 +struct silhouette_binary_rule : public binary_rule { - silhouette_binary_rule() : binary_rule() {} - 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; - - return true; - } + silhouette_binary_rule() : binary_rule() {} + + 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; + } + + return true; + } }; void ViewMapBuilder::ComputeSweepLineIntersections(ViewMap *ioViewMap, real epsilon) { - vector& svertices = ioViewMap->SVertices(); - bool progressBarDisplay = false; - unsigned sVerticesSize = svertices.size(); - unsigned fEdgesSize = ioViewMap->FEdges().size(); - // 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; - // } - - 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 SL; - - vector& ioEdges = ioViewMap->FEdges(); - - vector segments; - - vector::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 vsegments; - for(vector::iterator sv=svertices.begin(),svend=svertices.end(); - sv!=svend; - sv++) - { - if (_pRenderMonitor && _pRenderMonitor->testBreak()) - break; - - const vector& vedges = (*sv)->fedges(); - - for(vector::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::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 newEdges; - - // retrieve the intersected edges: - vector& iedges = SL.intersectedEdges(); - // retrieve the intersections: - vector& intersections = SL.intersections(); - - int id=0; - // create a view vertex for each intersection and linked this one - // with the intersection object - vector::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; + vector& svertices = ioViewMap->SVertices(); + bool progressBarDisplay = false; + unsigned sVerticesSize = svertices.size(); + unsigned fEdgesSize = ioViewMap->FEdges().size(); +#if 0 + 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 SL; + + vector& ioEdges = ioViewMap->FEdges(); + + vector segments; + + vector::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 vsegments; + for (vector::iterator sv = svertices.begin(), svend = svertices.end(); sv != svend; sv++) { + if (_pRenderMonitor && _pRenderMonitor->testBreak()) + break; + + const vector& vedges = (*sv)->fedges(); + + for (vector::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::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 newEdges; + + // retrieve the intersected edges: + vector& iedges = SL.intersectedEdges(); + // retrieve the intersections: + vector& intersections = SL.intersections(); + + int id = 0; + // create a view vertex for each intersection and linked this one with the intersection object + vector::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((Ta < -epsilon) || (Ta > 1+epsilon) || (Tb < -epsilon) || (Tb > 1+epsilon)) { - printf("ta %.12e\n", ta); - printf("tb %.12e\n", tb); - printf("a1 %e, %e -- b1 %e, %e\n", a1[0], a1[1], b1[0], b1[1]); - printf("a2 %e, %e -- b2 %e, %e\n", a2[0], a2[1], b2[0], 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 -- B1 %e, %e, %e\n", A1[0], A1[1], A1[2], B1[0], B1[1], B1[2]); - printf("A2 %e, %e, %e -- B2 %e, %e, %e\n", A2[0], A2[1], A2[2], B2[0], B2[1], B2[2]); - } + 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 -- b1 %e, %e\n", a1[0], a1[1], b1[0], b1[1]); + printf("a2 %e, %e -- b2 %e, %e\n", a2[0], a2[1], b2[0], 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 -- B1 %e, %e, %e\n", A1[0], A1[1], A1[2], B1[0], B1[1], B1[2]); + printf("A2 %e, %e, %e -- B2 %e, %e, %e\n", A2[0], A2[1], A2[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 edgeVVertices; - vector newVEdges; - vector::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& 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) { + 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; - _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; - } - } -} + vector edgeVVertices; + vector newVEdges; + vector::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& 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; + } + } +} diff --git a/source/blender/freestyle/intern/view_map/ViewMapBuilder.h b/source/blender/freestyle/intern/view_map/ViewMapBuilder.h index a41df92062e..2d5d24a0ffe 100644 --- a/source/blender/freestyle/intern/view_map/ViewMapBuilder.h +++ b/source/blender/freestyle/intern/view_map/ViewMapBuilder.h @@ -1,248 +1,257 @@ -// -// Filename : ViewMapBuilder.h -// Author(s) : Stephane Grabli -// Purpose : Class to build silhouette edges from a -// Winged-Edge structure -// Date of creation : 25/03/2002 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef VIEWMAPBUILDER_H -# define VIEWMAPBUILDER_H - -# include "Silhouette.h" -# include -# include "../system/FreestyleConfig.h" -# include "../geometry/Geom.h" -# include "../scene_graph/NodeGroup.h" -# include "../winged_edge/WXEdge.h" -# include "../geometry/GeomUtils.h" -# include "../geometry/Grid.h" -# include "../system/ProgressBar.h" -# include "../system/RenderMonitor.h" -# include "../geometry/SweepLine.h" -# include "ViewMap.h" -# include "SilhouetteGeomEngine.h" -# include "../scene_graph/TriangleRep.h" -# include "../winged_edge/WEdge.h" -# include "ViewEdgeXBuilder.h" -# include "../system/TimeUtils.h" -# include "GridDensityProvider.h" +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_VIEW_MAP_BUILDER_H__ +#define __FREESTYLE_VIEW_MAP_BUILDER_H__ + +/** \file blender/freestyle/intern/view_map/ViewMapBuilder.h + * \ingroup freestyle + * \brief Class to build silhouette edges from a Winged-Edge structure + * \author Stephane Grabli + * \date 25/03/2002 + */ + +#include + +#include "GridDensityProvider.h" +#include "Silhouette.h" +#include "SilhouetteGeomEngine.h" +#include "ViewEdgeXBuilder.h" +#include "ViewMap.h" + +#include "../geometry/Geom.h" +#include "../geometry/GeomUtils.h" +#include "../geometry/Grid.h" +#include "../geometry/SweepLine.h" + +#include "../scene_graph/NodeGroup.h" +#include "../scene_graph/TriangleRep.h" + +#include "../system/FreestyleConfig.h" +#include "../system/ProgressBar.h" +#include "../system/RenderMonitor.h" +#include "../system/TimeUtils.h" + +#include "../winged_edge/WEdge.h" +#include "../winged_edge/WXEdge.h" using namespace Geometry; class LIB_VIEW_MAP_EXPORT 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; - ViewMap * _ViewMap; // result - //SilhouetteGeomEngine _GeomEngine; - ProgressBar *_pProgressBar; - RenderMonitor *_pRenderMonitor; - Vec3r _viewpoint; - bool _orthographicProjection; - Grid* _Grid; - ViewEdgeXBuilder *_pViewEdgeBuilder; - bool _EnableQI; - double _epsilon; +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; - // tmp values: - int _currentId; - int _currentFId; - int _currentSVertexId; - + inline ViewMapBuilder() + { + _pProgressBar = NULL; + _pRenderMonitor = NULL; + _Grid = NULL; + _currentId = 1; + _currentFId = 0; + _currentSVertexId = 0; + _pViewEdgeBuilder = new ViewEdgeXBuilder; + _EnableQI = true; + } -public: + 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& bbox, unsigned int sceneNumFaces); + + /*! Compute Shapes from a WingedEdge containing a list of WShapes */ + void computeInitialViewEdges(WingedEdge&); + + /*! Compute Cusps */ + void computeCusps(ViewMap *ioViewMap); - 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 = 0; - _pRenderMonitor = 0; - _Grid = 0; - _currentId = 1; - _currentFId = 0; - _currentSVertexId = 0; - _pViewEdgeBuilder = new ViewEdgeXBuilder; - _EnableQI = true; - } - - inline ~ViewMapBuilder() - { - if(_pViewEdgeBuilder){ - delete _pViewEdgeBuilder; - _pViewEdgeBuilder = 0; - } - } - - /* Build Grid for ray casting */ - /*! Build non-culled Grid in camera space for ray casting */ - void BuildGrid(WingedEdge& we, const BBox& 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& 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=1e-06); - - /*! Computes the 2D scene silhouette edges visibility - * iGrid - * For the Ray Casting algorithm. - */ - void ComputeEdgesVisibility(ViewMap *ioViewMap, WingedEdge& we, const BBox& bbox, unsigned int sceneNumFaces, - visibility_algo iAlgo= ray_casting, real epsilon=1e-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;} + /*! 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& 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& 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); - /*! Computes intersections on all edges of the scene using a sweep line - * algorithm*/ - void ComputeSweepLineIntersections(ViewMap *ioViewMap, real epsilon = 1e-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=1e-6); - void ComputeFastRayCastingVisibility(ViewMap *ioViewMap, real epsilon=1e-6); - void ComputeVeryFastRayCastingVisibility(ViewMap *ioViewMap, real epsilon=1e-6); - -void ComputeCumulativeVisibility(ViewMap *ioViewMap, WingedEdge& we, - const BBox& bbox, real epsilon, bool cull, GridDensityProviderFactory& factory); -void ComputeDetailedVisibility(ViewMap *ioViewMap, WingedEdge& we, - const BBox& 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& 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& edge, vector& faceVertices); + void ComputeCumulativeVisibility(ViewMap *ioViewMap, WingedEdge& we, const BBox& bbox, real epsilon, + bool cull, GridDensityProviderFactory& factory); + void ComputeDetailedVisibility(ViewMap *ioViewMap, WingedEdge& we, const BBox& 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& 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& edge, vector& faceVertices); }; -#endif // VIEWMAPBUILDER_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 210bb3b8750..978272848ec 100644 --- a/source/blender/freestyle/intern/view_map/ViewMapIO.cpp +++ b/source/blender/freestyle/intern/view_map/ViewMapIO.cpp @@ -1,1245 +1,1258 @@ - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/freestyle/intern/view_map/ViewMapIO.cpp + * \ingroup freestyle + * \brief Functions to manage I/O for the view map + * \author Emmanuel Turquin + * \date 09/01/2003 + */ #include "ViewMapIO.h" #ifdef IRIX -# define WRITE(n) Internal::write(out, (const char*)(&(n))) -# define READ(n) Internal::read(in, (char*)(&(n))) +# define WRITE(n) Internal::write(out, (const char *)(&(n))) +# define READ(n) Internal::read(in, (char *)(&(n))) #else -# define WRITE(n) out.write((const char*)(&(n)), sizeof((n))) -# define READ(n) in.read((char*)(&(n)), sizeof((n))) +# define WRITE(n) out.write((const char *)(&(n)), sizeof((n))) +# define READ(n) in.read((char *)(&(n)), sizeof((n))) #endif -#define WRITE_IF_NON_NULL(ptr) if ((ptr) == NULL) { WRITE(ZERO); } else { WRITE((ptr)->userdata); } -#define READ_IF_NON_NULL(ptr, array) READ(tmp); if (tmp == ZERO) { (ptr) = NULL; } else { (ptr) = (array)[tmp]; } +#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 namespace ViewMapIO { - namespace Internal { +namespace Internal { - ViewMap* g_vm; +ViewMap* g_vm; - //////////////////// 'load' Functions //////////////////// +//////////////////// '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; +inline int load(istream& in, Polygon3r& p) +{ + unsigned tmp; + + // Id READ(tmp); - v[1] = tmp; + p.setId(tmp); + + // vertices (List) + vector tmp_vec; + Vec3r v; READ(tmp); - v[2] = tmp; - } - return 0; - } + 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) - inline - int load(istream& in, Polygon3r& p) { + return 0; +} - unsigned tmp; +inline int load(istream& in, FrsMaterial& m) +{ + float tmp_array[4]; + int i; - // Id - READ(tmp); - p.setId(tmp); + // 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]); - // vertices (List) - vector tmp_vec; - Vec3r v; - READ(tmp); - for (unsigned 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) { - - 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) { - - 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 frs_materials; - FrsMaterial m; - for(i=0; isshape()->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); - } + // 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]); - // 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) { - - if (!fe) - return 1; - - bool b; - - FEdgeSmooth *fesmooth = 0; - FEdgeSharp * fesharp = 0; - if(fe->isSmooth()){ - fesmooth = dynamic_cast(fe); - }else{ - fesharp = dynamic_cast(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); - - // hasVisibilityPoint - // bool b; - // READ(b); - // fe->setHasVisibilityPoint(b); - - Vec3r v; - unsigned int matindex; - - // VisibilityPointA - // load(in, v); - // fe->setVisibilityPointA(v); - - // VisibilityPointB - // load(in, v); - // fe->setVisibilityPointB(v); - - 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) { - - 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) { - - 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; + // 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) +{ + 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 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); - ViewShape* vso; - for (unsigned i = 0; i < size; i++) { - READ_IF_NON_NULL(vso, g_vm->ViewShapes()); - ve->AddOccluder(vso); - } - } + for (i = 0; i < size; i++) { + FEdge *fe; + READ_IF_NON_NULL(fe, g_vm->FEdges()); + vs->sshape()->AddChain(fe); + } - return 0; - } + // -> 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); + } - static int load(istream& in, ViewVertex* vv) { + // ViewVertices (List) + READ(size); + for (i = 0; i < size; i++) { + ViewVertex *vv; + READ_IF_NON_NULL(vv, g_vm->ViewVertices()); + vs->AddVertex(vv); + } - if (!vv) - return 1; + return 0; +} - unsigned tmp; - bool b; - // Nature - Nature::VertexNature nature; - READ(nature); - vv->setNature(nature); - - if (vv->getNature() & Nature::T_VERTEX) { - TVertex* tv = dynamic_cast(vv); +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(fe); + } + else { + fesharp = dynamic_cast(fe); + } // Id Id::id_type id1, id2; READ(id1); READ(id2); - tv->setId(Id(id1, id2)); + fe->setId(Id(id1, id2)); - // FrontSVertex - SVertex* fsv; - READ_IF_NON_NULL(fsv, g_vm->SVertices()); - tv->setFrontSVertex(fsv); + // Nature + Nature::EdgeNature nature; + READ(nature); + fe->setNature(nature); - // 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()); +#if 0 // hasVisibilityPoint + bool b; READ(b); - tv->setFrontEdgeA(fea, b); + fe->setHasVisibilityPoint(b); +#endif - // FrontEdgeB - ViewEdge* feb; - READ_IF_NON_NULL(feb, g_vm->ViewEdges()); - READ(b); - tv->setFrontEdgeB(feb, b); + Vec3r v; + unsigned int matindex; - // BackEdgeA - ViewEdge* bea; - READ_IF_NON_NULL(bea, g_vm->ViewEdges()); - READ(b); - tv->setBackEdgeA(bea, b); +#if 0 + // VisibilityPointA + load(in, v); + fe->setVisibilityPointA(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; - // BackEdgeB - ViewEdge* beb; - READ_IF_NON_NULL(beb, g_vm->ViewEdges()); + // aFace + load(in, p); + fe->setaFace(p); + + // occludeeEmpty READ(b); - tv->setBackEdgeB(beb, b); - } - else if (vv->getNature() & Nature::NON_T_VERTEX) { - NonTVertex* ntv = dynamic_cast(vv); - - // SVertex - SVertex* sv; - READ_IF_NON_NULL(sv, g_vm->SVertices()); - ntv->setSVertex(sv); - - // ViewEdges (List) - unsigned size; + fe->setOccludeeEmpty(b); + + // occludeeIntersection + load(in, v); + fe->setOccludeeIntersection(v); + + return 0; +} + +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); - ViewEdge* ve; - for (unsigned i = 0; i < size; i++) { - READ_IF_NON_NULL(ve, g_vm->ViewEdges()); - READ(b); - ntv->AddViewEdge(ve, b); + 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) +{ + 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) +{ + 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(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(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) +{ + 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) +{ + unsigned tmp; + + // Id + tmp = p.getId(); + WRITE(tmp); + + // vertices (List) + tmp = p.getVertices().size(); + WRITE(tmp); + for (vector::const_iterator i = p.getVertices().begin(); i != p.getVertices().end(); i++) { + save(out, *i); + } + + // min & max + // Do not need to be saved + + return 0; +} + +inline int save(ostream& out, const FrsMaterial& m) +{ + unsigned i; + + // Diffuse + for (i = 0; i < 4; i++) + WRITE(m.diffuse()[i]); + + // Specular + for (i = 0; i < 4; i++) + WRITE(m.specular()[i]); + + // Ambient + for (i = 0; i < 4; i++) + WRITE(m.ambient()[i]); + + // Emission + for (i = 0; i < 4; i++) + WRITE(m.emission()[i]); + + // Shininess + float shininess = m.shininess(); + WRITE(shininess); + + return 0; +} + +static int save(ostream& out, ViewShape *vs) +{ + if (!vs || !vs->sshape()) { + cerr << "Warning: null ViewShape" << endl; + return 1; } - } - - return 0; - } - //////////////////// 'save' Functions //////////////////// + unsigned tmp; - inline - int save(ostream& out, const Vec3r& v) { + // SShape - if (Options::getFlags() & Options::FLOAT_VECTORS) { - float tmp; + // -> 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); - tmp = v[0]; + // -> 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); - tmp = v[1]; + for (vector::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); - tmp = v[2]; + for (vector::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::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); - } else { - Vec3r::value_type tmp; + for (vector::const_iterator i4 = vs->edges().begin(); i4 != vs->edges().end(); i4++) + WRITE_IF_NON_NULL(*i4); - tmp = v[0]; + // ViewVertices (List) + tmp = vs->vertices().size(); WRITE(tmp); - tmp = v[1]; + for (vector::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) +{ + if (!fe) { + cerr << "Warning: null FEdge" << endl; + return 1; + } + + FEdgeSmooth *fesmooth = dynamic_cast(fe); + FEdgeSharp *fesharp = dynamic_cast(fe); + + // Id + Id::id_type id = fe->getId().getFirst(); + WRITE(id); + id = fe->getId().getSecond(); + WRITE(id); + + // Nature + Nature::EdgeNature nature = fe->getNature(); + WRITE(nature); + + bool b; + +#if 0 + // hasVisibilityPoint + b = fe->hasVisibilityPoint(); + WRITE(b); + + // VisibilityPointA + save(out, fe->visibilityPointA()); + + // 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; +} + +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::const_iterator i; + for (i = sv->normals().begin(), tmp = 0; i != sv->normals().end(); i++, tmp++); WRITE(tmp); - tmp = v[2]; + for (i = sv->normals().begin(); i != sv->normals().end(); i++) + save(out, *i); + + // FEdges (List) + tmp = sv->fedges().size(); WRITE(tmp); - } - return 0; - } - - - inline - int save(ostream& out, const Polygon3r& p) { - - unsigned tmp; - - // Id - tmp = p.getId(); - WRITE(tmp); - - // vertices (List) - tmp = p.getVertices().size(); - WRITE(tmp); - for (vector::const_iterator i = p.getVertices().begin(); - i != p.getVertices().end(); i++) { - save(out, *i); - } - - // min & max - // Do not need to be saved - - return 0; - } - - - inline - int save(ostream& out, const FrsMaterial& m) { - - unsigned i; - - // Diffuse - for (i = 0; i < 4; i++) - WRITE(m.diffuse()[i]); - - // Specular - for (i = 0; i < 4; i++) - WRITE(m.specular()[i]); - - // Ambient - for (i = 0; i < 4; i++) - WRITE(m.ambient()[i]); - - // Emission - for (i = 0; i < 4; i++) - WRITE(m.emission()[i]); - - // Shininess - float shininess = m.shininess(); - WRITE(shininess); - - return 0; - } - - - 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 size = vs->sshape()->frs_materials().size(); - WRITE(size); - for(unsigned i=0; isshape()->frs_material(i)); - - // -> VerticesList (List) - tmp = vs->sshape()->getVertexList().size(); - WRITE(tmp); - for (vector::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::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::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::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::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) { - - if (!fe) { - cerr << "Warning: null FEdge" << endl; - return 1; - } - - FEdgeSmooth * fesmooth = dynamic_cast(fe); - FEdgeSharp * fesharp = dynamic_cast(fe); - - // Id - Id::id_type id = fe->getId().getFirst(); - WRITE(id); - id = fe->getId().getSecond(); - WRITE(id); - - // Nature - Nature::EdgeNature nature = fe->getNature(); - WRITE(nature); - - bool b; - - // hasVisibilityPoint - // b = fe->hasVisibilityPoint(); - // WRITE(b); - - // VisibilityPointA - // save(out, fe->visibilityPointA()); - // - // // VisibilityPointB - // save(out, fe->visibilityPointB()); - - 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) { - - 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::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::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) { - - if (!ve) { - cerr << "Warning: null ViewEdge" << endl; - return 1; - } - - unsigned tmp; - - // Id - Id::id_type id = ve->getId().getFirst(); - WRITE(id); - id = ve->getId().getSecond(); - WRITE(id); + for (vector::const_iterator j = sv->fedges_begin(); j != sv->fedges_end(); j++) + WRITE_IF_NON_NULL(*j); - // Nature - Nature::EdgeNature nature = ve->getNature(); - WRITE(nature); + return 0; +} - // QI - unsigned qi = ve->qi(); - WRITE(qi); - // Shape - WRITE_IF_NON_NULL(ve->shape()); +static int save(ostream& out, ViewEdge *ve) +{ + if (!ve) { + cerr << "Warning: null ViewEdge" << endl; + return 1; + } + + unsigned tmp; - // aShape - WRITE_IF_NON_NULL(ve->aShape()); - - // FEdgeA - WRITE_IF_NON_NULL(ve->fedgeA()); - - // FEdgeB - WRITE_IF_NON_NULL(ve->fedgeB()); - - // A - WRITE_IF_NON_NULL(ve->A()); - - // B - WRITE_IF_NON_NULL(ve->B()); - - // Occluders (List) - if (!(Options::getFlags() & Options::NO_OCCLUDERS)) { - tmp = ve->occluders().size(); - WRITE(tmp); - for (vector::const_iterator i = ve->occluders().begin(); - i != ve->occluders().end(); i++) - WRITE_IF_NON_NULL((*i)); - } - - return 0; - } - - - 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(vv); - // Id - Id::id_type id = tv->getId().getFirst(); + Id::id_type id = ve->getId().getFirst(); WRITE(id); - id = tv->getId().getSecond(); + id = ve->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(vv); - - // SVertex - WRITE_IF_NON_NULL(ntv->svertex()); - - // ViewEdges (List) - unsigned size = ntv->viewedges().size(); + // Nature + Nature::EdgeNature nature = ve->getNature(); + WRITE(nature); + + // QI + unsigned qi = ve->qi(); + WRITE(qi); + + // Shape + WRITE_IF_NON_NULL(ve->shape()); + + // aShape + WRITE_IF_NON_NULL(ve->aShape()); + + // FEdgeA + WRITE_IF_NON_NULL(ve->fedgeA()); + + // FEdgeB + WRITE_IF_NON_NULL(ve->fedgeB()); + + // A + WRITE_IF_NON_NULL(ve->A()); + + // B + WRITE_IF_NON_NULL(ve->B()); + + // Occluders (List) + if (!(Options::getFlags() & Options::NO_OCCLUDERS)) { + tmp = ve->occluders().size(); + WRITE(tmp); + for (vector::const_iterator i = ve->occluders().begin(); i != ve->occluders().end(); i++) + WRITE_IF_NON_NULL((*i)); + } + + return 0; +} + + +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(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(vv); + + // SVertex + WRITE_IF_NON_NULL(ntv->svertex()); + + // ViewEdges (List) + unsigned size = ntv->viewedges().size(); + WRITE(size); + vector::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 + + +//////////////////// "Public" 'load' and 'save' functions //////////////////// + +#define SET_PROGRESS(n) \ + if (pb) { \ + pb->setProgress((n)); \ + } (void)0 + +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 informations 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 + 1; 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 + 1; 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); + } +#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::const_iterator i4 = vm->ViewShapes().begin(); i4 != vm->ViewShapes().end(); i4++) + err += Internal::load(in, *i4); + SET_PROGRESS(2); + for (vector::const_iterator i5 = vm->FEdges().begin(); i5 != vm->FEdges().end(); i5++) + err += Internal::load(in, *i5); + SET_PROGRESS(3); + for (vector::const_iterator i6 = vm->SVertices().begin(); i6 != vm->SVertices().end(); i6++) + err += Internal::load(in, *i6); + SET_PROGRESS(4); + for (vector::const_iterator i7 = vm->ViewEdges().begin(); i7 != vm->ViewEdges().end(); i7++) + err += Internal::load(in, *i7); + SET_PROGRESS(5); + for (vector::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) +{ + 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 = (void *)i0; + vm->ViewShapes()[i0]->sshape()->userdata = (void *)i0; + } + for (unsigned int i1 = 0; i1 < vm->FEdges().size(); i1++) + vm->FEdges()[i1]->userdata = (void *)i1; + for (unsigned int i2 = 0; i2 < vm->SVertices().size(); i2++) + vm->SVertices()[i2]->userdata = (void *)i2; + for (unsigned int i3 = 0; i3 < vm->ViewEdges().size(); i3++) + vm->ViewEdges()[i3]->userdata = (void *)i3; + for (unsigned int i4 = 0; i4 < vm->ViewVertices().size(); i4++) + vm->ViewVertices()[i4]->userdata = (void *)i4; + + // Write the current options + unsigned char flags = Options::getFlags(); + WRITE(flags); + + // Write the size of the five lists (with some extra informations 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); - vector::const_iterator i = ntv->viewedges().begin(); - for ( ; i != ntv->viewedges().end(); i++){ - WRITE_IF_NON_NULL(i->first); - WRITE(i->second); + 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); } - } else { - cerr << "Warning: unexpected ViewVertex nature" << endl; - return 1; - } - - return 0; - } - - } // End of namespace Internal - - - //////////////////// "Public" 'load' and 'save' functions //////////////////// - -#define SET_PROGRESS(n) if (pb) pb->setProgress((n)) - - 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 informations 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+1; - fe_rle2 = fe_rle1, READ(fe_rle1)) { - if (b) { - for (unsigned i = fe_rle2; i < fe_rle1; i++) { - FEdgeSmooth * fes = new FEdgeSmooth; - vm->AddFEdge(fes); - } - b = !b; - } - else if (!b) { - for (unsigned 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+1; - vv_rle2 = vv_rle1, READ(vv_rle1)) { - if (nature & Nature::T_VERTEX) { - for (unsigned 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 i = vv_rle2; i < vv_rle1; i++) { - NonTVertex* ntv = new NonTVertex(); - vm->AddViewVertex(ntv); - } - nature = Nature::T_VERTEX; - } - } - } - - for (unsigned i0 = 0; i0 < vs_s; i0++) { - SShape* ss = new SShape(); - ViewShape* vs = new ViewShape(); - vs->setSShape(ss); - ss->setViewShape(vs); - vm->AddViewShape(vs); - } - // for (unsigned i1 = 0; i1 < fe_s; i1++) { - // FEdge* fe = new FEdge(); - // vm->AddFEdge(fe); - // } - for (unsigned i2 = 0; i2 < sv_s; i2++) { - SVertex* sv = new SVertex(); - vm->AddSVertex(sv); - } - for (unsigned 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::const_iterator i4 = vm->ViewShapes().begin(); - i4 != vm->ViewShapes().end(); i4++) - err += Internal::load(in, *i4); - SET_PROGRESS(2); - for (vector::const_iterator i5 = vm->FEdges().begin(); - i5 != vm->FEdges().end(); i5++) - err += Internal::load(in, *i5); - SET_PROGRESS(3); - for (vector::const_iterator i6 = vm->SVertices().begin(); - i6 != vm->SVertices().end(); i6++) - err += Internal::load(in, *i6); - SET_PROGRESS(4); - for (vector::const_iterator i7 = vm->ViewEdges().begin(); - i7 != vm->ViewEdges().end(); i7++) - err += Internal::load(in, *i7); - SET_PROGRESS(5); - for (vector::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 i4=0;i4shapeIdToIndexMap()[id] = index; - } - - return err; - } - - - 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 i0 = 0; i0 < vm->ViewShapes().size(); i0++) { - vm->ViewShapes()[i0]->userdata = (void*)i0; - vm->ViewShapes()[i0]->sshape()->userdata = (void*)i0; - } - for (unsigned i1 = 0; i1 < vm->FEdges().size(); i1++) - vm->FEdges()[i1]->userdata = (void*)i1; - for (unsigned i2 = 0; i2 < vm->SVertices().size(); i2++) - vm->SVertices()[i2]->userdata = (void*)i2; - for (unsigned i3 = 0; i3 < vm->ViewEdges().size(); i3++) - vm->ViewEdges()[i3]->userdata = (void*)i3; - for (unsigned i4 = 0; i4 < vm->ViewVertices().size(); i4++) - vm->ViewVertices()[i4]->userdata = (void*)i4; - - // Write the current options - unsigned char flags = Options::getFlags(); - WRITE(flags); - - // Write the size of the five lists (with some extra informations 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 i = 0; i < size; i++) { - while (i < size && (vm->FEdges()[i]->isSmooth() == b)) - i++; - if (i < size) { - WRITE(i); - b = !b; + // Write all the elts of the ViewShapes List + SET_PROGRESS(1); + for (vector::const_iterator i5 = vm->ViewShapes().begin(); i5 != vm->ViewShapes().end(); i5++) + err += Internal::save(out, *i5); + SET_PROGRESS(2); + for (vector::const_iterator i6 = vm->FEdges().begin(); i6 != vm->FEdges().end(); i6++) + err += Internal::save(out, *i6); + SET_PROGRESS(3); + for (vector::const_iterator i7 = vm->SVertices().begin(); i7 != vm->SVertices().end(); i7++) + err += Internal::save(out, *i7); + SET_PROGRESS(4); + for (vector::const_iterator i8 = vm->ViewEdges().begin(); i8 != vm->ViewEdges().end(); i8++) + err += Internal::save(out, *i8); + SET_PROGRESS(5); + for (vector::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); } - } - 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 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; + + // Reset 'userdata' members + for (vector::const_iterator j0 = vm->ViewShapes().begin(); j0 != vm->ViewShapes().end(); j0++) { + (*j0)->userdata = NULL; + (*j0)->sshape()->userdata = NULL; } - } - WRITE(size); - size++; - WRITE(size); - } - - - // Write all the elts of the ViewShapes List - SET_PROGRESS(1); - for (vector::const_iterator i5 = vm->ViewShapes().begin(); - i5 != vm->ViewShapes().end(); i5++) - err += Internal::save(out, *i5); - SET_PROGRESS(2); - for (vector::const_iterator i6 = vm->FEdges().begin(); - i6 != vm->FEdges().end(); i6++) - err += Internal::save(out, *i6); - SET_PROGRESS(3); - for (vector::const_iterator i7 = vm->SVertices().begin(); - i7 != vm->SVertices().end(); i7++) - err += Internal::save(out, *i7); - SET_PROGRESS(4); - for (vector::const_iterator i8 = vm->ViewEdges().begin(); - i8 != vm->ViewEdges().end(); i8++) - err += Internal::save(out, *i8); - SET_PROGRESS(5); - for (vector::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 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::const_iterator j0 = vm->ViewShapes().begin(); - j0 != vm->ViewShapes().end(); j0++) { - (*j0)->userdata = 0; - (*j0)->sshape()->userdata = 0; - } - for (vector::const_iterator j1 = vm->FEdges().begin(); - j1 != vm->FEdges().end(); j1++) - (*j1)->userdata = 0; - for (vector::const_iterator j2 = vm->SVertices().begin(); - j2 != vm->SVertices().end(); j2++) - (*j2)->userdata = 0; - for (vector::const_iterator j3 = vm->ViewEdges().begin(); - j3 != vm->ViewEdges().end(); j3++) - (*j3)->userdata = 0; - for (vector::const_iterator j4 = vm->ViewVertices().begin(); - j4 != vm->ViewVertices().end(); j4++) - (*j4)->userdata = 0; - SET_PROGRESS(6); - - return err; - } - - - //////////////////// Options //////////////////// - - namespace Options { - - namespace Internal { - - static unsigned char g_flags = 0; - static string g_models_path; - - } // End of namespace Internal - - void setFlags(const unsigned char flags) { - Internal::g_flags = flags; - } - - void addFlags(const unsigned char flags) { - Internal::g_flags |= flags; - } - - void rmFlags(const unsigned char flags) { - Internal::g_flags &= ~flags; - } - - unsigned char getFlags() { - return Internal::g_flags; - } - - void setModelsPath(const string& path) { - Internal::g_models_path = path; - } - - string getModelsPath() { - return Internal::g_models_path; - } - - }; // End of namepace Options + for (vector::const_iterator j1 = vm->FEdges().begin(); j1 != vm->FEdges().end(); j1++) + (*j1)->userdata = NULL; + for (vector::const_iterator j2 = vm->SVertices().begin(); j2 != vm->SVertices().end(); j2++) + (*j2)->userdata = NULL; + for (vector::const_iterator j3 = vm->ViewEdges().begin(); j3 != vm->ViewEdges().end(); j3++) + (*j3)->userdata = NULL; + for (vector::const_iterator j4 = vm->ViewVertices().begin(); j4 != vm->ViewVertices().end(); j4++) + (*j4)->userdata = NULL; + SET_PROGRESS(6); + + return err; +} + + +//////////////////// Options //////////////////// + +namespace Options { + +namespace Internal { + +static unsigned char g_flags = 0; +static string g_models_path; + +} // End of namespace Internal + +void setFlags(const unsigned char flags) +{ + Internal::g_flags = flags; +} + +void addFlags(const unsigned char flags) +{ + Internal::g_flags |= flags; +} + +void rmFlags(const unsigned char flags) +{ + Internal::g_flags &= ~flags; +} + +unsigned char getFlags() +{ + return Internal::g_flags; +} + +void setModelsPath(const string& path) +{ + Internal::g_models_path = path; +} + +string getModelsPath() +{ + return Internal::g_models_path; +} + +} // End of namepace Options } // End of namespace ViewMapIO diff --git a/source/blender/freestyle/intern/view_map/ViewMapIO.h b/source/blender/freestyle/intern/view_map/ViewMapIO.h index 185841a90ec..44521f03317 100644 --- a/source/blender/freestyle/intern/view_map/ViewMapIO.h +++ b/source/blender/freestyle/intern/view_map/ViewMapIO.h @@ -1,116 +1,129 @@ -// -// Filename : ViewMapIO.h -// Author(s) : Emmanuel Turquin -// Purpose : Functions to manage I/O for the view map -// Date of creation : 09/01/2003 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef VIEWMAPIO_H -# define VIEWMAPIO_H - -# include "ViewMap.h" -# include -# include -# include "../system/FreestyleConfig.h" -# include "../system/ProgressBar.h" +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_VIEW_MAP_IO_H__ +#define __FREESTYLE_VIEW_MAP_IO_H__ + +/** \file blender/freestyle/intern/view_map/ViewMapIO.h + * \ingroup freestyle + * \brief Functions to manage I/O for the view map + * \author Emmanuel Turquin + * \date 09/01/2003 + */ + +#include +#include + +#include "ViewMap.h" + +#include "../system/FreestyleConfig.h" +#include "../system/ProgressBar.h" namespace ViewMapIO { - static const unsigned ZERO = UINT_MAX; - - LIB_VIEW_MAP_EXPORT - int load(istream& in, ViewMap* vm, ProgressBar* pb = NULL); - - LIB_VIEW_MAP_EXPORT - int save(ostream& out, ViewMap* vm, ProgressBar* pb = NULL); - - namespace Options { - - static const unsigned char FLOAT_VECTORS = 1; - static const unsigned char NO_OCCLUDERS = 2; - - LIB_VIEW_MAP_EXPORT - void setFlags(const unsigned char flags); - - LIB_VIEW_MAP_EXPORT - void addFlags(const unsigned char flags); - - LIB_VIEW_MAP_EXPORT - void rmFlags(const unsigned char flags); - - LIB_VIEW_MAP_EXPORT - unsigned char getFlags(); - - LIB_VIEW_MAP_EXPORT - void setModelsPath(const string& path); - - LIB_VIEW_MAP_EXPORT - string getModelsPath(); - - }; // End of namepace Options - -# ifdef IRIX - - namespace Internal { - - template - ostream& write(ostream& out, const char* str) { - out.put(str[S - 1]); - return write(out, str); - } - - template<> - ostream& write<1>(ostream& out, const char* str) { - return out.put(str[0]); - } - - template<> - ostream& write<0>(ostream& out, const char*) { - return out; - } - - template - istream& read(istream& in, char* str) { - in.get(str[S - 1]); - return read(in, str); - } - - template<> - istream& read<1>(istream& in, char* str) { - return in.get(str[0]); - } - - template<> - istream& read<0>(istream& in, char*) { - return in; - } - - } // End of namespace Internal - -# endif // IRIX +static const unsigned ZERO = UINT_MAX; + +LIB_VIEW_MAP_EXPORT +int load(istream& in, ViewMap *vm, ProgressBar *pb = NULL); + +LIB_VIEW_MAP_EXPORT +int save(ostream& out, ViewMap *vm, ProgressBar *pb = NULL); + +namespace Options { + +static const unsigned char FLOAT_VECTORS = 1; +static const unsigned char NO_OCCLUDERS = 2; + +LIB_VIEW_MAP_EXPORT +void setFlags(const unsigned char flags); + +LIB_VIEW_MAP_EXPORT +void addFlags(const unsigned char flags); + +LIB_VIEW_MAP_EXPORT +void rmFlags(const unsigned char flags); + +LIB_VIEW_MAP_EXPORT +unsigned char getFlags(); + +LIB_VIEW_MAP_EXPORT +void setModelsPath(const string& path); + +LIB_VIEW_MAP_EXPORT +string getModelsPath(); + +}; // End of namepace Options + +#ifdef IRIX + +namespace Internal { + +template +ostream& write(ostream& out, const char *str) +{ + out.put(str[S - 1]); + return write(out, str); +} + +template<> +ostream& write<1>(ostream& out, const char *str) +{ + return out.put(str[0]); +} + +template<> +ostream& write<0>(ostream& out, const char*) +{ + return out; +} + +template +istream& read(istream& in, char *str) +{ + in.get(str[S - 1]); + return read(in, str); +} + +template<> +istream& read<1>(istream& in, char *str) +{ + return in.get(str[0]); +} + +template<> +istream& read<0>(istream& in, char*) +{ + return in; +} + +} // End of namespace Internal + +#endif // IRIX } // End of namespace ViewMapIO -#endif // VIEWMAPIO_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 7ef2fe5fbe0..78c09c863cc 100644 --- a/source/blender/freestyle/intern/view_map/ViewMapIterators.h +++ b/source/blender/freestyle/intern/view_map/ViewMapIterators.h @@ -1,381 +1,402 @@ -// -// Filename : ViewMapIterators.h -// Author(s) : Stephane Grabli -// Purpose : Iterators used to iterate over the various elements -// of the ViewMap -// Date of creation : 01/07/2003 -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_VIEW_MAP_ITERATORS_H__ +#define __FREESTYLE_VIEW_MAP_ITERATORS_H__ + +/** \file blender/freestyle/intern/view_map/ViewMapIterators.h + * \ingroup freestyle + * \brief Iterators used to iterate over the various elements of the ViewMap + * \author Stephane Grabli + * \date 01/07/2003 + */ +#include "ViewMap.h" -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +#include "../system/Iterator.h" //soc -#ifndef VIEWMAPITERATORS_H -# define VIEWMAPITERATORS_H -#include "ViewMap.h" -#include "../system/Iterator.h" //soc +/**********************************/ +/* */ +/* */ +/* ViewMap */ +/* */ +/* */ +/**********************************/ + +/**********************************/ +/* */ +/* */ +/* ViewVertex */ +/* */ +/* */ +/**********************************/ + +namespace ViewVertexInternal { + +/*! Class representing an iterator over oriented ViewEdges around a ViewVertex. This iterator allows a CCW iteration + * (in the image plane). + * 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; + } +}; + +} // ViewVertexInternal namespace - /**********************************/ - /* */ - /* */ - /* ViewMap */ - /* */ - /* */ - /**********************************/ - - /**********************************/ - /* */ - /* */ - /* ViewVertex */ - /* */ - /* */ - /**********************************/ - -namespace ViewVertexInternal{ - - /*! Class representing an iterator over oriented ViewEdges - * around a ViewVertex. This iterator allows a CCW iteration - * (in the image plane). - * 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()". - */ - virtual orientedViewEdgeIterator& operator++() // operator corresponding to ++i - { - increment(); - return *this; - } - /*! Increments.In the scripting language, call - * "increment()". - */ - virtual orientedViewEdgeIterator operator++(int) // opérateur correspondant à i++ - { // c.a.d qui renvoie la valeur *puis* incrémente. - orientedViewEdgeIterator tmp = *this; // C'est pour cela qu'on stocke la valeur - increment(); // dans un temporaire. - 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; - } - }; - - } - /**********************************/ - /* */ - /* */ - /* ViewEdge */ - /* */ - /* */ - /**********************************/ +/**********************************/ +/* */ +/* */ +/* ViewEdge */ +/* */ +/* */ +/**********************************/ namespace ViewEdgeInternal { + // // SVertexIterator // ///////////////////////////////////////////////// - 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 = 0; - 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 = 0; - 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(&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(&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 +}; // @@ -383,167 +404,171 @@ namespace ViewEdgeInternal { // /////////////////////////////////////////////////////////// - /*! Base class for iterators over ViewEdges of the ViewMap Graph. - * Basically the "increment()" operator of this class should - * be able to take the decision of "where" (on which ViewEdge) to go - * when pointing on a given ViewEdge. - * ::Caution::: the dereferencing operator returns a *pointer* to - * the pointed ViewEdge. - */ +/*! Base class for iterators over ViewEdges of the ViewMap Graph. + * Basically the "increment()" operator of this class should be able to take the decision of "where" (on which + * 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 = 0, 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); - } + /*! 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; + bool _orientation; + ViewEdge *_edge; + ViewEdge *_begin; }; } // end of namespace ViewEdgeInternal -#endif // VIEWMAPITERATORS_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 6041f527d17..d1adc55d3ac 100644 --- a/source/blender/freestyle/intern/view_map/ViewMapTesselator.cpp +++ b/source/blender/freestyle/intern/view_map/ViewMapTesselator.cpp @@ -1,36 +1,49 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/** \file blender/freestyle/intern/view_map/ViewMapTesselator.cpp + * \ingroup freestyle + * \brief Class to build a Node Tree designed to be displayed from a Silhouette View Map structure. + * \author Stephane Grabli + * \date 26/03/2002 + */ #include "ViewMapTesselator.h" -NodeGroup* ViewMapTesselator::Tesselate(ViewMap *iViewMap) +NodeGroup *ViewMapTesselator::Tesselate(ViewMap *iViewMap) { - if(0 == iViewMap->ViewEdges().size()) - return NULL; + if (0 == iViewMap->ViewEdges().size()) + return NULL; - const vector& viewedges = iViewMap->ViewEdges(); - return Tesselate(viewedges.begin(), viewedges.end()); + const vector& viewedges = iViewMap->ViewEdges(); + return Tesselate(viewedges.begin(), viewedges.end()); } -NodeGroup* ViewMapTesselator::Tesselate(WShape *) +NodeGroup *ViewMapTesselator::Tesselate(WShape *) { - return NULL; + return NULL; } diff --git a/source/blender/freestyle/intern/view_map/ViewMapTesselator.h b/source/blender/freestyle/intern/view_map/ViewMapTesselator.h index 0177dc630b8..c1ed7e3926a 100644 --- a/source/blender/freestyle/intern/view_map/ViewMapTesselator.h +++ b/source/blender/freestyle/intern/view_map/ViewMapTesselator.h @@ -1,44 +1,50 @@ -// -// Filename : ViewMapTesselator.h -// Author(s) : Stephane Grabli -// Purpose : Class to build a Node Tree designed to be displayed -// from a Silhouette View Map structure. -// Date of creation : 26/03/2002 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef VIEWMAPTESSELATOR_H -# define VIEWMAPTESSELATOR_H - -# include "Silhouette.h" -# include "ViewMap.h" -# include "../scene_graph/NodeShape.h" -# include "../winged_edge/WEdge.h" -# include "../scene_graph/NodeGroup.h" -# include "../scene_graph/LineRep.h" -# include "../scene_graph/OrientedLineRep.h" -# include "../scene_graph/VertexRep.h" +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_VIEW_MAP_TESSELATOR_H__ +#define __FREESTYLE_VIEW_MAP_TESSELATOR_H__ + +/** \file blender/freestyle/intern/view_map/ViewMapTesselator.h + * \ingroup freestyle + * \brief Class to build a Node Tree designed to be displayed from a Silhouette View Map structure. + * \author Stephane Grabli + * \date 26/03/2002 + */ + +#include "Silhouette.h" +#include "ViewMap.h" + +#include "../scene_graph/LineRep.h" +#include "../scene_graph/NodeShape.h" +#include "../scene_graph/NodeGroup.h" +#include "../scene_graph/OrientedLineRep.h" +#include "../scene_graph/VertexRep.h" + +#include "../winged_edge/WEdge.h" class NodeShape; class NodeGroup; @@ -48,68 +54,83 @@ class WShape; class LIB_VIEW_MAP_EXPORT 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 - NodeGroup* Tesselate(ViewEdgesIterator begin, ViewEdgesIterator end) ; - - /*! Builds a set of lines rep contained among a - * 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;} + 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 + 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; - + virtual void AddVertexToLine(LineRep *iLine, SVertex *v) = 0; + private: - Nature::EdgeNature _nature; - FrsMaterial _FrsMaterial; - bool _overloadFrsMaterial; + Nature::EdgeNature _nature; + FrsMaterial _FrsMaterial; + bool _overloadFrsMaterial; }; /*! Class to tesselate the 2D projected silhouette */ class ViewMapTesselator2D : public ViewMapTesselator { public: - inline ViewMapTesselator2D() : ViewMapTesselator() {} - virtual ~ViewMapTesselator2D() {} + inline ViewMapTesselator2D() : ViewMapTesselator() {} + virtual ~ViewMapTesselator2D() {} protected: - virtual void AddVertexToLine(LineRep *iLine, SVertex *v) - { - iLine->AddVertex(v->point2D()); - } + virtual void AddVertexToLine(LineRep *iLine, SVertex *v) + { + iLine->AddVertex(v->point2D()); + } }; /*! Class to tesselate the 3D silhouette */ class ViewMapTesselator3D : public ViewMapTesselator { public: - inline ViewMapTesselator3D() : ViewMapTesselator() {} - virtual ~ViewMapTesselator3D() {} + inline ViewMapTesselator3D() : ViewMapTesselator() {} + virtual ~ViewMapTesselator3D() {} protected: - virtual void AddVertexToLine(LineRep *iLine, SVertex *v) - { - iLine->AddVertex(v->point3D()); - } + virtual void AddVertexToLine(LineRep *iLine, SVertex *v) + { + iLine->AddVertex(v->point3D()); + } }; // @@ -118,79 +139,73 @@ protected: /////////////////////////////////////////////// template -NodeGroup * ViewMapTesselator::Tesselate(ViewEdgesIterator begin, ViewEdgesIterator end) +NodeGroup *ViewMapTesselator::Tesselate(ViewEdgesIterator begin, ViewEdgesIterator end) { - NodeGroup *group = new NodeGroup; - NodeShape *tshape = new NodeShape; - group->AddChild(tshape); - //tshape->frs_material().setDiffuse(0.f, 0.f, 0.f, 1.f); - tshape->setFrsMaterial(_FrsMaterial); - - LineRep* line; - - - FEdge *firstEdge; - FEdge *nextFEdge, *currentEdge; - - int id=0; - // for(vector::const_iterator c=viewedges.begin(),cend=viewedges.end(); - // c!=cend; - // c++) - for(ViewEdgesIterator c=begin, cend=end; - c!=cend; - c++) - { - // if((*c)->qi() > 0){ - // continue; - // } - // if(!((*c)->nature() & (_nature))) - // continue; - // - firstEdge = (*c)->fedgeA(); - - // if(firstEdge->invisibility() > 0) - // continue; - - 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; + 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; + + FEdge *firstEdge; + FEdge *nextFEdge, *currentEdge; + + int id = 0; + //for (vector::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; + } +#endif + firstEdge = (*c)->fedgeA(); + +#if 0 + 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; } -#endif // VIEWMAPTESSELATOR_H +#endif // __FREESTYLE_VIEW_MAP_TESSELATOR_H__ diff --git a/source/blender/freestyle/intern/winged_edge/Curvature.cpp b/source/blender/freestyle/intern/winged_edge/Curvature.cpp index ce8fc5b98fa..acefe1aa5fc 100644 --- a/source/blender/freestyle/intern/winged_edge/Curvature.cpp +++ b/source/blender/freestyle/intern/winged_edge/Curvature.cpp @@ -1,646 +1,642 @@ -/* GTS - Library for the manipulation of triangulated surfaces - * Copyright (C) 1999-2002 Ray Jones, Stéphane Popinet +/* + * ***** BEGIN GPL LICENSE BLOCK ***** * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. * - * This library is distributed in the hope that it will be useful, + * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * This Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: + * GTS - Library for the manipulation of triangulated surfaces + * Copyright (C) 1999 Stephane Popinet + * and: + * OGF/Graphite: Geometry and Graphics Programming Library + Utilities + * Copyright (C) 2000-2003 Bruno Levy + * Contact: Bruno Levy levy@loria.fr + * ISA Project + * LORIA, INRIA Lorraine, + * Campus Scientifique, BP 239 + * 54506 VANDOEUVRE LES NANCY CEDEX + * FRANCE + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** */ +/** \file blender/freestyle/intern/winged_edge/Curvature.cpp + * \ingroup freestyle + * \brief GTS - Library for the manipulation of triangulated surfaces + * \author Stephane Popinet + * \date 1999 + * \brief OGF/Graphite: Geometry and Graphics Programming Library + Utilities + * \author Bruno Levy + * \date 2000-2003 + */ + +#include #include // for malloc and free -#include "Curvature.h" #include -#include -#include "WEdge.h" -#include "../system/FreestyleConfig.h" -#include "../geometry/normal_cycle.h" #include #include -static bool angle_obtuse (WVertex * v, WFace * f) +#include "Curvature.h" +#include "WEdge.h" + +#include "../geometry/normal_cycle.h" + +#include "../system/FreestyleConfig.h" + +static bool angle_obtuse(WVertex *v, WFace *f) { - WOEdge * e; - f->getOppositeEdge (v, e); - - Vec3r vec1(e->GetaVertex()->GetVertex()-v->GetVertex()); - Vec3r vec2(e->GetbVertex()->GetVertex()-v->GetVertex()); - return ((vec1 * vec2) < 0); + WOEdge *e; + f->getOppositeEdge(v, e); + + Vec3r vec1(e->GetaVertex()->GetVertex()-v->GetVertex()); + Vec3r vec2(e->GetbVertex()->GetVertex()-v->GetVertex()); + return ((vec1 * vec2) < 0); } // FIXME // WVvertex is useless but kept for history reasons -static bool triangle_obtuse (WVertex*, WFace * f) +static bool triangle_obtuse(WVertex *, WFace *f) { - bool b=false; - for (int i=0; i<3; i++) - b = b || - ((f->getEdgeList()[i]->GetVec() * f->getEdgeList()[(i+1)%3]->GetVec()) < 0); - return b; + bool b = false; + for (int i = 0; i < 3; i++) + b = b || ((f->getEdgeList()[i]->GetVec() * f->getEdgeList()[(i + 1) % 3]->GetVec()) < 0); + return b; } -static real cotan (WVertex * vo, WVertex * v1, WVertex * v2) +static real cotan(WVertex *vo, WVertex *v1, WVertex *v2) { - /* cf. Appendix B of [Meyer et al 2002] */ - real udotv, denom; - - Vec3r u(v1->GetVertex()- vo->GetVertex()); - Vec3r v(v2->GetVertex()- vo->GetVertex()); + /* cf. Appendix B of [Meyer et al 2002] */ + real udotv, denom; - udotv = u * v; - denom = sqrt(u.squareNorm() * v.squareNorm() - udotv * udotv); + Vec3r u(v1->GetVertex() - vo->GetVertex()); + Vec3r v(v2->GetVertex() - vo->GetVertex()); - /* denom can be zero if u==v. Returning 0 is acceptable, based on - * the callers of this function below. */ - if (denom == 0.0) return (0.0); + udotv = u * v; + denom = sqrt(u.squareNorm() * v.squareNorm() - udotv * udotv); - return (udotv / denom); + /* denom can be zero if u==v. Returning 0 is acceptable, based on the callers of this function below. */ + if (denom == 0.0) + return 0.0; + return (udotv / denom); } -static real angle_from_cotan (WVertex * vo, WVertex * v1, WVertex * v2) +static real angle_from_cotan(WVertex *vo, WVertex *v1, WVertex *v2) { - /* cf. Appendix B and the caption of Table 1 from [Meyer et al 2002] */ - real udotv, denom; + /* cf. Appendix B and the caption of Table 1 from [Meyer et al 2002] */ + real udotv, denom; - Vec3r u (v1->GetVertex()-vo->GetVertex()); - Vec3r v(v2->GetVertex()-vo->GetVertex()); + Vec3r u (v1->GetVertex() - vo->GetVertex()); + Vec3r v(v2->GetVertex() - vo->GetVertex()); - udotv = u * v; - denom = sqrt(u.squareNorm() * v.squareNorm() - udotv * udotv); + udotv = u * v; + denom = sqrt(u.squareNorm() * v.squareNorm() - udotv * udotv); - /* Note: I assume this is what they mean by using atan2 (). -Ray Jones */ + /* Note: I assume this is what they mean by using atan2(). -Ray Jones */ - /* tan = denom/udotv = y/x (see man page for atan2) */ - return (fabs (atan2 (denom, udotv))); + /* tan = denom/udotv = y/x (see man page for atan2) */ + return (fabs(atan2(denom, udotv))); } -/** - * gts_vertex_mean_curvature_normal: - * @v: a #WVertex. - * @s: a #GtsSurface. - * @Kh: the Mean Curvature Normal at @v. +/*! gts_vertex_mean_curvature_normal: + * @v: a #WVertex. + * @s: a #GtsSurface. + * @Kh: the Mean Curvature Normal at @v. * - * Computes the Discrete Mean Curvature Normal approximation at @v. - * The mean curvature at @v is half the magnitude of the vector @Kh. + * Computes the Discrete Mean Curvature Normal approximation at @v. + * The mean curvature at @v is half the magnitude of the vector @Kh. * - * Note: the normal computed is not unit length, and may point either - * into or out of the surface, depending on the curvature at @v. It - * is the responsibility of the caller of the function to use the mean - * curvature normal appropriately. + * Note: the normal computed is not unit length, and may point either into or out of the surface, depending on + * the curvature at @v. It is the responsibility of the caller of the function to use the mean curvature normal + * appropriately. * - * This approximation is from the paper: - * Discrete Differential-Geometry Operators for Triangulated 2-Manifolds - * Mark Meyer, Mathieu Desbrun, Peter Schroder, Alan H. Barr - * VisMath '02, Berlin (Germany) - * http://www-grail.usc.edu/pubs.html + * This approximation is from the paper: + * Discrete Differential-Geometry Operators for Triangulated 2-Manifolds + * Mark Meyer, Mathieu Desbrun, Peter Schroder, Alan H. Barr + * VisMath '02, Berlin (Germany) + * http://www-grail.usc.edu/pubs.html * - * Returns: %TRUE if the operator could be evaluated, %FALSE if the - * evaluation failed for some reason (@v is boundary or is the - * endpoint of a non-manifold edge.) + * Returns: %TRUE if the operator could be evaluated, %FALSE if the evaluation failed for some reason (@v is + * boundary or is the endpoint of a non-manifold edge.) */ -bool gts_vertex_mean_curvature_normal (WVertex * v, Vec3r &Kh) +bool gts_vertex_mean_curvature_normal(WVertex *v, Vec3r &Kh) { real area = 0.0; - if (!v) return false; + if (!v) + return false; /* this operator is not defined for boundary edges */ - if (v->isBoundary()) return false; - - WVertex::incoming_edge_iterator itE; - - for (itE=v->incoming_edges_begin(); - itE!=v->incoming_edges_end(); itE++) - area+=(*itE)->GetaFace()->getArea(); - - Kh=Vec3r(0.0, 0.0, 0.0); - - for (itE=v->incoming_edges_begin(); - itE!=v->incoming_edges_end(); itE++) - { - WOEdge * e = (*itE)->getPrevOnFace(); - //if ((e->GetaVertex()==v) || (e->GetbVertex()==v)) cerr<< "BUG "; + if (v->isBoundary()) + return false; - WVertex * v1 = e->GetaVertex(); - WVertex * v2 = e->GetbVertex(); - real temp; - - temp = cotan (v1, v, v2); - Kh = Vec3r(Kh+temp*(v2->GetVertex()-v->GetVertex())); + WVertex::incoming_edge_iterator itE; - temp = cotan (v2, v, v1); - Kh = Vec3r(Kh+temp*(v1->GetVertex()-v->GetVertex())); - } - if (area > 0.0) - { - Kh[0] /= 2*area; - Kh[1] /= 2*area; - Kh[2] /= 2*area; - } - else return false; + for (itE=v->incoming_edges_begin(); itE != v->incoming_edges_end(); itE++) + area += (*itE)->GetaFace()->getArea(); + + Kh = Vec3r(0.0, 0.0, 0.0); + + for (itE=v->incoming_edges_begin(); itE != v->incoming_edges_end(); itE++) { + WOEdge *e = (*itE)->getPrevOnFace(); +#if 0 + if ((e->GetaVertex() == v) || (e->GetbVertex() == v)) + cerr<< "BUG "; +#endif + WVertex *v1 = e->GetaVertex(); + WVertex *v2 = e->GetbVertex(); + real temp; + + temp = cotan(v1, v, v2); + Kh = Vec3r(Kh + temp * (v2->GetVertex() - v->GetVertex())); + + temp = cotan(v2, v, v1); + Kh = Vec3r(Kh + temp * (v1->GetVertex() - v->GetVertex())); + } + if (area > 0.0) { + Kh[0] /= 2 * area; + Kh[1] /= 2 * area; + Kh[2] /= 2 * area; + } + else { + return false; + } return true; } -/** - * gts_vertex_gaussian_curvature: - * @v: a #WVertex. - * @s: a #GtsSurface. - * @Kg: the Discrete Gaussian Curvature approximation at @v. +/*! gts_vertex_gaussian_curvature: + * @v: a #WVertex. + * @s: a #GtsSurface. + * @Kg: the Discrete Gaussian Curvature approximation at @v. * - * Computes the Discrete Gaussian Curvature approximation at @v. + * Computes the Discrete Gaussian Curvature approximation at @v. * - * This approximation is from the paper: - * Discrete Differential-Geometry Operators for Triangulated 2-Manifolds - * Mark Meyer, Mathieu Desbrun, Peter Schroder, Alan H. Barr - * VisMath '02, Berlin (Germany) - * http://www-grail.usc.edu/pubs.html + * This approximation is from the paper: + * Discrete Differential-Geometry Operators for Triangulated 2-Manifolds + * Mark Meyer, Mathieu Desbrun, Peter Schroder, Alan H. Barr + * VisMath '02, Berlin (Germany) + * http://www-grail.usc.edu/pubs.html * - * Returns: %TRUE if the operator could be evaluated, %FALSE if the - * evaluation failed for some reason (@v is boundary or is the - * endpoint of a non-manifold edge.) + * Returns: %TRUE if the operator could be evaluated, %FALSE if the evaluation failed for some reason (@v is + * boundary or is the endpoint of a non-manifold edge.) */ -bool gts_vertex_gaussian_curvature (WVertex * v, real * Kg) +bool gts_vertex_gaussian_curvature(WVertex *v, real *Kg) { real area = 0.0; real angle_sum = 0.0; - if (!v) return false; - if (!Kg) return false; + if (!v) + return false; + if (!Kg) + return false; + + /* this operator is not defined for boundary edges */ + if (v->isBoundary()) { + *Kg = 0.0; + return false; + } - /* this operator is not defined for boundary edges */ - if (v->isBoundary()) {*Kg=0.0 ;return false;} - WVertex::incoming_edge_iterator itE; - for (itE=v->incoming_edges_begin(); - itE!=v->incoming_edges_end(); itE++) - area+=(*itE)->GetaFace()->getArea(); - - for (itE=v->incoming_edges_begin(); - itE!=v->incoming_edges_end(); itE++) - { - WOEdge * e = (*itE)->getPrevOnFace(); - WVertex * v1 = e->GetaVertex(); - WVertex * v2 = e->GetbVertex(); - angle_sum += angle_from_cotan (v, v1, v2); - } - - *Kg = (2.0*M_PI - angle_sum)/area; + for (itE = v->incoming_edges_begin(); itE != v->incoming_edges_end(); itE++) + area += (*itE)->GetaFace()->getArea(); + + for (itE = v->incoming_edges_begin(); itE != v->incoming_edges_end(); itE++) { + WOEdge *e = (*itE)->getPrevOnFace(); + WVertex *v1 = e->GetaVertex(); + WVertex *v2 = e->GetbVertex(); + angle_sum += angle_from_cotan(v, v1, v2); + } + + *Kg = (2.0 * M_PI - angle_sum) / area; return true; } -/** - * gts_vertex_principal_curvatures: - * @Kh: mean curvature. - * @Kg: Gaussian curvature. - * @K1: first principal curvature. - * @K2: second principal curvature. +/*! gts_vertex_principal_curvatures: + * @Kh: mean curvature. + * @Kg: Gaussian curvature. + * @K1: first principal curvature. + * @K2: second principal curvature. * - * Computes the principal curvatures at a point given the mean and - * Gaussian curvatures at that point. + * Computes the principal curvatures at a point given the mean and Gaussian curvatures at that point. * - * The mean curvature can be computed as one-half the magnitude of the - * vector computed by gts_vertex_mean_curvature_normal(). + * The mean curvature can be computed as one-half the magnitude of the vector computed by + * gts_vertex_mean_curvature_normal(). * - * The Gaussian curvature can be computed with - * gts_vertex_gaussian_curvature(). + * The Gaussian curvature can be computed with gts_vertex_gaussian_curvature(). */ -void gts_vertex_principal_curvatures (real Kh, real Kg, - real * K1, real * K2) +void gts_vertex_principal_curvatures (real Kh, real Kg, real *K1, real *K2) { - real temp = Kh*Kh - Kg; + real temp = Kh * Kh - Kg; - if (!K1) return; - if (!K1) return; + if (!K1 || !K2) + return; - if (temp < 0.0) temp = 0.0; - temp = sqrt (temp); - *K1 = Kh + temp; - *K2 = Kh - temp; + if (temp < 0.0) + temp = 0.0; + temp = sqrt (temp); + *K1 = Kh + temp; + *K2 = Kh - temp; } /* from Maple */ -static void linsolve (real m11, real m12, real b1, - real m21, real m22, real b2, - real * x1, real * x2) +static void linsolve(real m11, real m12, real b1, real m21, real m22, real b2, real *x1, real *x2) { - real temp; + real temp; - temp = 1.0 / (m21*m12 - m11*m22); - *x1 = (m12*b2 - m22*b1)*temp; - *x2 = (m11*b2 - m21*b1)*temp; + temp = 1.0 / (m21 * m12 - m11 * m22); + *x1 = (m12 * b2 - m22 * b1) * temp; + *x2 = (m11 * b2 - m21 * b1) * temp; } - + /* from Maple - largest eigenvector of [a b; b c] */ -static void eigenvector (real a, real b, real c, - Vec3r e) +static void eigenvector(real a, real b, real c, Vec3r e) { - if (b == 0.0) { - e[0] = 0.0; - } else { - e[0] = -(c - a - sqrt (c*c - 2*a*c + a*a + 4*b*b))/(2*b); - } - e[1] = 1.0; - e[2] = 0.0; + if (b == 0.0) { + e[0] = 0.0; + } + else { + e[0] = -(c - a - sqrt(c * c - 2 * a * c + a * a + 4 * b * b)) / (2 * b); + } + e[1] = 1.0; + e[2] = 0.0; } -/** - * gts_vertex_principal_directions: - * @v: a #WVertex. - * @s: a #GtsSurface. - * @Kh: mean curvature normal (a #Vec3r). - * @Kg: Gaussian curvature (a real). - * @e1: first principal curvature direction (direction of largest curvature). - * @e2: second principal curvature direction. +/*! gts_vertex_principal_directions: + * @v: a #WVertex. + * @s: a #GtsSurface. + * @Kh: mean curvature normal (a #Vec3r). + * @Kg: Gaussian curvature (a real). + * @e1: first principal curvature direction (direction of largest curvature). + * @e2: second principal curvature direction. * - * Computes the principal curvature directions at a point given @Kh - * and @Kg, the mean curvature normal and Gaussian curvatures at that - * point, computed with gts_vertex_mean_curvature_normal() and - * gts_vertex_gaussian_curvature(), respectively. + * Computes the principal curvature directions at a point given @Kh and @Kg, the mean curvature normal and + * Gaussian curvatures at that point, computed with gts_vertex_mean_curvature_normal() and + * gts_vertex_gaussian_curvature(), respectively. * - * Note that this computation is very approximate and tends to be - * unstable. Smoothing of the surface or the principal directions may - * be necessary to achieve reasonable results. + * Note that this computation is very approximate and tends to be unstable. Smoothing of the surface or the principal + * directions may be necessary to achieve reasonable results. */ -void gts_vertex_principal_directions (WVertex * v, - Vec3r Kh, real Kg, - Vec3r &e1, Vec3r &e2) +void gts_vertex_principal_directions(WVertex *v, Vec3r Kh, real Kg, Vec3r &e1, Vec3r &e2) { - Vec3r N; - real normKh; - - Vec3r basis1, basis2, d, eig; - real ve2, vdotN; - real aterm_da, bterm_da, cterm_da, const_da; - real aterm_db, bterm_db, cterm_db, const_db; - real a, b, c; - real K1, K2; - real *weights, *kappas, *d1s, *d2s; - int edge_count; - real err_e1, err_e2; - int e; - WVertex::incoming_edge_iterator itE; - - /* compute unit normal */ - normKh = Kh.norm(); - - if (normKh > 0.0) { - Kh.normalize(); - } else { - /* This vertex is a point of zero mean curvature (flat or saddle - * point). Compute a normal by averaging the adjacent triangles - */ - N[0] = N[1] = N[2] = 0.0; - - for (itE=v->incoming_edges_begin(); - itE!=v->incoming_edges_end(); itE++) - N=Vec3r(N+(*itE)->GetaFace()->GetNormal()); - real normN = N.norm(); - if (normN <= 0.0) - return; - N.normalize(); - } - - - /* construct a basis from N: */ - /* set basis1 to any component not the largest of N */ - basis1[0] = basis1[1] = basis1[2] = 0.0; - if (fabs (N[0]) > fabs (N[1])) - basis1[1] = 1.0; - else - basis1[0] = 1.0; - - /* make basis2 orthogonal to N */ - basis2 = (N ^ basis1); - basis2.normalize(); - - /* make basis1 orthogonal to N and basis2 */ - basis1 = (N ^ basis2); - basis1.normalize(); - - aterm_da = bterm_da = cterm_da = const_da = 0.0; - aterm_db = bterm_db = cterm_db = const_db = 0.0; - int nb_edges=v->GetEdges().size(); - - weights = (real *) malloc (sizeof (real)*nb_edges); - kappas = (real*) malloc (sizeof (real)*nb_edges); - d1s = (real*) malloc (sizeof (real)*nb_edges); - d2s = (real*) malloc (sizeof (real)*nb_edges); - edge_count = 0; - - for (itE=v->incoming_edges_begin(); - itE!=v->incoming_edges_end(); itE++) - { - WOEdge * e; - WFace * f1, * f2; - real weight, kappa, d1, d2; - Vec3r vec_edge; - if (! *itE) continue; - e = *itE; - - /* since this vertex passed the tests in - * gts_vertex_mean_curvature_normal(), this should be true. */ - //g_assert (gts_edge_face_number (e, s) == 2); - - /* identify the two triangles bordering e in s */ - f1=e->GetaFace(); - f2=e->GetbFace(); - - /* We are solving for the values of the curvature tensor - * B = [ a b ; b c ]. - * The computations here are from section 5 of [Meyer et al 2002]. - * - * The first step is to calculate the linear equations governing - * the values of (a,b,c). These can be computed by setting the - * derivatives of the error E to zero (section 5.3). - * - * Since a + c = norm(Kh), we only compute the linear equations - * for dE/da and dE/db. (NB: [Meyer et al 2002] has the - * equation a + b = norm(Kh), but I'm almost positive this is - * incorrect.) - * - * Note that the w_ij (defined in section 5.2) are all scaled by - * (1/8*A_mixed). We drop this uniform scale factor because the - * solution of the linear equations doesn't rely on it. - * - * The terms of the linear equations are xterm_dy with x in - * {a,b,c} and y in {a,b}. There are also const_dy terms that are - * the constant factors in the equations. - */ - - /* find the vector from v along edge e */ - vec_edge=Vec3r(-1*e->GetVec()); - - ve2 = vec_edge.squareNorm(); - vdotN = vec_edge * N; - - /* section 5.2 - There is a typo in the computation of kappa. The - * edges should be x_j-x_i. - */ - kappa = 2.0 * vdotN / ve2; - - /* section 5.2 */ - - /* I don't like performing a minimization where some of the - * weights can be negative (as can be the case if f1 or f2 are - * obtuse). To ensure all-positive weights, we check for - * obtuseness. */ - weight = 0.0; - if (! triangle_obtuse(v, f1)) { - weight += ve2 * - cotan (f1->GetNextOEdge(e->twin())->GetbVertex(), - e->GetaVertex(), e->GetbVertex()) / 8.0; - } else { - if (angle_obtuse (v, f1)) { - weight += ve2 * f1->getArea() / 4.0; - } else { - weight += ve2 * f1->getArea() / 8.0; - } - } - - if (! triangle_obtuse(v, f2)) { - weight += ve2 * - cotan (f2->GetNextOEdge(e)->GetbVertex(), - e->GetaVertex(), e->GetbVertex()) / 8.0; - } else { - if (angle_obtuse (v, f2)) { - weight += ve2 * f1->getArea() / 4.0; - } else { - weight += ve2 * f1->getArea() / 8.0; - } - } - - /* projection of edge perpendicular to N (section 5.3) */ - d[0] = vec_edge[0] - vdotN * N[0]; - d[1] = vec_edge[1] - vdotN * N[1]; - d[2] = vec_edge[2] - vdotN * N[2]; - d.normalize(); - - /* not explicit in the paper, but necessary. Move d to 2D basis. */ - d1 = d * basis1; - d2 = d * basis2; - - /* store off the curvature, direction of edge, and weights for later use */ - weights[edge_count] = weight; - kappas[edge_count] = kappa; - d1s[edge_count] = d1; - d2s[edge_count] = d2; - edge_count++; - - /* Finally, update the linear equations */ - aterm_da += weight * d1 * d1 * d1 * d1; - bterm_da += weight * d1 * d1 * 2 * d1 * d2; - cterm_da += weight * d1 * d1 * d2 * d2; - const_da += weight * d1 * d1 * (- kappa); - - aterm_db += weight * d1 * d2 * d1 * d1; - bterm_db += weight * d1 * d2 * 2 * d1 * d2; - cterm_db += weight * d1 * d2 * d2 * d2; - const_db += weight * d1 * d2 * (- kappa); - - } - - /* now use the identity (Section 5.3) a + c = |Kh| = 2 * kappa_h */ - aterm_da -= cterm_da; - const_da += cterm_da * normKh; - - aterm_db -= cterm_db; - const_db += cterm_db * normKh; - - /* check for solvability of the linear system */ - if (((aterm_da * bterm_db - aterm_db * bterm_da) != 0.0) && - ((const_da != 0.0) || (const_db != 0.0))) { - linsolve (aterm_da, bterm_da, -const_da, - aterm_db, bterm_db, -const_db, - &a, &b); - - c = normKh - a; - - eigenvector (a, b, c, eig); - } else { - /* region of v is planar */ - eig[0] = 1.0; - eig[1] = 0.0; - } - - /* Although the eigenvectors of B are good estimates of the - * principal directions, it seems that which one is attached to - * which curvature direction is a bit arbitrary. This may be a bug - * in my implementation, or just a side-effect of the inaccuracy of - * B due to the discrete nature of the sampling. - * - * To overcome this behavior, we'll evaluate which assignment best - * matches the given eigenvectors by comparing the curvature - * estimates computed above and the curvatures calculated from the - * discrete differential operators. */ - - gts_vertex_principal_curvatures (0.5 * normKh, Kg, &K1, &K2); - - err_e1 = err_e2 = 0.0; - /* loop through the values previously saved */ - for (e = 0; e < edge_count; e++) { - real weight, kappa, d1, d2; - real temp1, temp2; - real delta; - - weight = weights[e]; - kappa = kappas[e]; - d1 = d1s[e]; - d2 = d2s[e]; - - temp1 = fabs (eig[0] * d1 + eig[1] * d2); - temp1 = temp1 * temp1; - temp2 = fabs (eig[1] * d1 - eig[0] * d2); - temp2 = temp2 * temp2; - - /* err_e1 is for K1 associated with e1 */ - delta = K1 * temp1 + K2 * temp2 - kappa; - err_e1 += weight * delta * delta; - - /* err_e2 is for K1 associated with e2 */ - delta = K2 * temp1 + K1 * temp2 - kappa; - err_e2 += weight * delta * delta; - } - free (weights); - free (kappas); - free (d1s); - free (d2s); - - /* rotate eig by a right angle if that would decrease the error */ - if (err_e2 < err_e1) { - real temp = eig[0]; - - eig[0] = eig[1]; - eig[1] = -temp; - } - - e1[0] = eig[0] * basis1[0] + eig[1] * basis2[0]; - e1[1] = eig[0] * basis1[1] + eig[1] * basis2[1]; - e1[2] = eig[0] * basis1[2] + eig[1] * basis2[2]; - e1.normalize(); - - /* make N,e1,e2 a right handed coordinate sytem */ - e2 = N ^ e1; - e2.normalize(); + Vec3r N; + real normKh; + + Vec3r basis1, basis2, d, eig; + real ve2, vdotN; + real aterm_da, bterm_da, cterm_da, const_da; + real aterm_db, bterm_db, cterm_db, const_db; + real a, b, c; + real K1, K2; + real *weights, *kappas, *d1s, *d2s; + int edge_count; + real err_e1, err_e2; + int e; + WVertex::incoming_edge_iterator itE; + + /* compute unit normal */ + normKh = Kh.norm(); + + if (normKh > 0.0) { + Kh.normalize(); + } + else { + /* This vertex is a point of zero mean curvature (flat or saddle point). Compute a normal by averaging + * the adjacent triangles + */ + N[0] = N[1] = N[2] = 0.0; + + for (itE = v->incoming_edges_begin(); itE != v->incoming_edges_end(); itE++) + N = Vec3r(N + (*itE)->GetaFace()->GetNormal()); + real normN = N.norm(); + if (normN <= 0.0) + return; + N.normalize(); + } + + /* construct a basis from N: */ + /* set basis1 to any component not the largest of N */ + basis1[0] = basis1[1] = basis1[2] = 0.0; + if (fabs (N[0]) > fabs (N[1])) + basis1[1] = 1.0; + else + basis1[0] = 1.0; + + /* make basis2 orthogonal to N */ + basis2 = (N ^ basis1); + basis2.normalize(); + + /* make basis1 orthogonal to N and basis2 */ + basis1 = (N ^ basis2); + basis1.normalize(); + + aterm_da = bterm_da = cterm_da = const_da = 0.0; + aterm_db = bterm_db = cterm_db = const_db = 0.0; + int nb_edges=v->GetEdges().size(); + + weights = (real *)malloc(sizeof (real) * nb_edges); + kappas = (real *)malloc(sizeof (real) * nb_edges); + d1s = (real *)malloc(sizeof (real) * nb_edges); + d2s = (real *)malloc(sizeof (real) * nb_edges); + edge_count = 0; + + for (itE = v->incoming_edges_begin(); itE != v->incoming_edges_end(); itE++) { + WOEdge *e; + WFace *f1, *f2; + real weight, kappa, d1, d2; + Vec3r vec_edge; + if (!*itE) + continue; + e = *itE; + + /* since this vertex passed the tests in gts_vertex_mean_curvature_normal(), this should be true. */ + //g_assert(gts_edge_face_number (e, s) == 2); + + /* identify the two triangles bordering e in s */ + f1 = e->GetaFace(); + f2 = e->GetbFace(); + + /* We are solving for the values of the curvature tensor + * B = [ a b ; b c ]. + * The computations here are from section 5 of [Meyer et al 2002]. + * + * The first step is to calculate the linear equations governing the values of (a,b,c). These can be computed + * by setting the derivatives of the error E to zero (section 5.3). + * + * Since a + c = norm(Kh), we only compute the linear equations for dE/da and dE/db. (NB: [Meyer et al 2002] + * has the equation a + b = norm(Kh), but I'm almost positive this is incorrect). + * + * Note that the w_ij (defined in section 5.2) are all scaled by (1/8*A_mixed). We drop this uniform scale + * factor because the solution of the linear equations doesn't rely on it. + * + * The terms of the linear equations are xterm_dy with x in {a,b,c} and y in {a,b}. There are also const_dy + * terms that are the constant factors in the equations. + */ + + /* find the vector from v along edge e */ + vec_edge = Vec3r(-1 * e->GetVec()); + + ve2 = vec_edge.squareNorm(); + vdotN = vec_edge * N; + + /* section 5.2 - There is a typo in the computation of kappa. The edges should be x_j-x_i. */ + kappa = 2.0 * vdotN / ve2; + + /* section 5.2 */ + + /* I don't like performing a minimization where some of the weights can be negative (as can be the case + * if f1 or f2 are obtuse). To ensure all-positive weights, we check for obtuseness. */ + weight = 0.0; + if (!triangle_obtuse(v, f1)) { + weight += ve2 * cotan(f1->GetNextOEdge(e->twin())->GetbVertex(), e->GetaVertex(), e->GetbVertex()) / 8.0; + } + else { + if (angle_obtuse(v, f1)) { + weight += ve2 * f1->getArea() / 4.0; + } + else { + weight += ve2 * f1->getArea() / 8.0; + } + } + + if (!triangle_obtuse(v, f2)) { + weight += ve2 * cotan (f2->GetNextOEdge(e)->GetbVertex(), e->GetaVertex(), e->GetbVertex()) / 8.0; + } + else { + if (angle_obtuse(v, f2)) { + weight += ve2 * f1->getArea() / 4.0; + } + else { + weight += ve2 * f1->getArea() / 8.0; + } + } + + /* projection of edge perpendicular to N (section 5.3) */ + d[0] = vec_edge[0] - vdotN * N[0]; + d[1] = vec_edge[1] - vdotN * N[1]; + d[2] = vec_edge[2] - vdotN * N[2]; + d.normalize(); + + /* not explicit in the paper, but necessary. Move d to 2D basis. */ + d1 = d * basis1; + d2 = d * basis2; + + /* store off the curvature, direction of edge, and weights for later use */ + weights[edge_count] = weight; + kappas[edge_count] = kappa; + d1s[edge_count] = d1; + d2s[edge_count] = d2; + edge_count++; + + /* Finally, update the linear equations */ + aterm_da += weight * d1 * d1 * d1 * d1; + bterm_da += weight * d1 * d1 * 2 * d1 * d2; + cterm_da += weight * d1 * d1 * d2 * d2; + const_da += weight * d1 * d1 * (-kappa); + + aterm_db += weight * d1 * d2 * d1 * d1; + bterm_db += weight * d1 * d2 * 2 * d1 * d2; + cterm_db += weight * d1 * d2 * d2 * d2; + const_db += weight * d1 * d2 * (-kappa); + } + + /* now use the identity (Section 5.3) a + c = |Kh| = 2 * kappa_h */ + aterm_da -= cterm_da; + const_da += cterm_da * normKh; + + aterm_db -= cterm_db; + const_db += cterm_db * normKh; + + /* check for solvability of the linear system */ + if (((aterm_da * bterm_db - aterm_db * bterm_da) != 0.0) && ((const_da != 0.0) || (const_db != 0.0))) { + linsolve(aterm_da, bterm_da, -const_da, aterm_db, bterm_db, -const_db, &a, &b); + + c = normKh - a; + + eigenvector(a, b, c, eig); + } + else { + /* region of v is planar */ + eig[0] = 1.0; + eig[1] = 0.0; + } + + /* Although the eigenvectors of B are good estimates of the principal directions, it seems that which one is + * attached to which curvature direction is a bit arbitrary. This may be a bug in my implementation, or just + * a side-effect of the inaccuracy of B due to the discrete nature of the sampling. + * + * To overcome this behavior, we'll evaluate which assignment best matches the given eigenvectors by comparing + * the curvature estimates computed above and the curvatures calculated from the discrete differential operators. + */ + + gts_vertex_principal_curvatures(0.5 * normKh, Kg, &K1, &K2); + + err_e1 = err_e2 = 0.0; + /* loop through the values previously saved */ + for (e = 0; e < edge_count; e++) { + real weight, kappa, d1, d2; + real temp1, temp2; + real delta; + + weight = weights[e]; + kappa = kappas[e]; + d1 = d1s[e]; + d2 = d2s[e]; + + temp1 = fabs (eig[0] * d1 + eig[1] * d2); + temp1 = temp1 * temp1; + temp2 = fabs (eig[1] * d1 - eig[0] * d2); + temp2 = temp2 * temp2; + + /* err_e1 is for K1 associated with e1 */ + delta = K1 * temp1 + K2 * temp2 - kappa; + err_e1 += weight * delta * delta; + + /* err_e2 is for K1 associated with e2 */ + delta = K2 * temp1 + K1 * temp2 - kappa; + err_e2 += weight * delta * delta; + } + free (weights); + free (kappas); + free (d1s); + free (d2s); + + /* rotate eig by a right angle if that would decrease the error */ + if (err_e2 < err_e1) { + real temp = eig[0]; + + eig[0] = eig[1]; + eig[1] = -temp; + } + + e1[0] = eig[0] * basis1[0] + eig[1] * basis2[0]; + e1[1] = eig[0] * basis1[1] + eig[1] * basis2[1]; + e1[2] = eig[0] * basis1[2] + eig[1] * basis2[2]; + e1.normalize(); + + /* make N,e1,e2 a right handed coordinate sytem */ + e2 = N ^ e1; + e2.normalize(); } namespace OGF { - inline static real angle(WOEdge * h) { - const Vec3r& n1 = h->GetbFace()->GetNormal(); - const Vec3r& n2 = h->GetaFace()->GetNormal(); - const Vec3r v = h->getVec3r(); - real sine = (n1 ^ n2) * v / v.norm() ; - if(sine >= 1.0) { - return M_PI / 2.0 ; - } - if(sine <= -1.0) { - return -M_PI / 2.0 ; - } - return ::asin(sine) ; - } - - // precondition1: P is inside the sphere - // precondition2: P,V points to the outside of - // the sphere (i.e. OP.V > 0) - static bool sphere_clip_vector( - const Vec3r& O, real r, - const Vec3r& P, Vec3r& V - ) { - - Vec3r W = P - O ; - real a = V.squareNorm() ; - real b = 2.0 * V * W ; - real c = W.squareNorm() - r*r ; - real delta = b*b - 4*a*c ; - if(delta < 0) { - // Should not happen, but happens sometimes (numerical precision) - return true ; - } - real t = - b + ::sqrt(delta) / (2.0 * a) ; - if(t < 0.0) { - // Should not happen, but happens sometimes (numerical precision) - return true ; - } - if(t >= 1.0) { - // Inside the sphere - return false ; - } - - V[0] = (t * V.x()) ; - V[1] = (t * V.y()) ; - V[2] = (t * V.z()) ; - - return true ; - } - - // TODO: check optimizations: - // use marking ? (measure *timings* ...) - void compute_curvature_tensor( - WVertex* start, real radius, NormalCycle& nc - ) { - // in case we have a non-manifold vertex, skip it... - if(start->isBoundary()) - return; - - std::set vertices ; - const Vec3r& O = start->GetVertex() ; - std::stack S ; - S.push(start) ; - vertices.insert(start) ; - while(!S.empty()) { - WVertex* v = S.top() ; - S.pop() ; - if(v->isBoundary()) - continue; - const Vec3r& P = v->GetVertex() ; - WVertex::incoming_edge_iterator woeit = v->incoming_edges_begin(); - WVertex::incoming_edge_iterator woeitend = v->incoming_edges_end(); - for(;woeit!=woeitend; ++woeit){ - WOEdge *h = *woeit; - if((v == start) || h->GetVec() * (O - P) > 0.0) { - Vec3r V(-1 * h->GetVec()); - bool isect = sphere_clip_vector(O, radius, P, V) ; - assert (h->GetOwner()->GetNumberOfOEdges() == 2); // Because otherwise v->isBoundary() would be true - nc.accumulate_dihedral_angle(V, h->GetAngle()) ; - - if(!isect) { - WVertex* w = h->GetaVertex() ; - if(vertices.find(w) == vertices.end()) { - vertices.insert(w) ; - S.push(w) ; - } - } - } - } - } - } - - - void compute_curvature_tensor_one_ring( - WVertex* start, NormalCycle& nc - ) { - // in case we have a non-manifold vertex, skip it... - if(start->isBoundary()) - return; - - WVertex::incoming_edge_iterator woeit = start->incoming_edges_begin(); - WVertex::incoming_edge_iterator woeitend = start->incoming_edges_end(); - for(;woeit!=woeitend; ++woeit){ - WOEdge *h = (*woeit)->twin(); - nc.accumulate_dihedral_angle(h->GetVec(), h->GetAngle()) ; - WOEdge *hprev = h->getPrevOnFace(); - nc.accumulate_dihedral_angle(hprev->GetVec(), hprev->GetAngle()) ; - } - } +inline static real angle(WOEdge *h) +{ + const Vec3r& n1 = h->GetbFace()->GetNormal(); + const Vec3r& n2 = h->GetaFace()->GetNormal(); + const Vec3r v = h->getVec3r(); + real sine = (n1 ^ n2) * v / v.norm(); + if (sine >= 1.0) { + return M_PI / 2.0; + } + if (sine <= -1.0) { + return -M_PI / 2.0; + } + return ::asin(sine); +} + +// precondition1: P is inside the sphere +// precondition2: P,V points to the outside of the sphere (i.e. OP.V > 0) +static bool sphere_clip_vector(const Vec3r& O, real r, const Vec3r& P, Vec3r& V) +{ + Vec3r W = P - O; + real a = V.squareNorm(); + real b = 2.0 * V * W; + real c = W.squareNorm() - r * r; + real delta = b * b - 4 * a * c; + if (delta < 0) { + // Should not happen, but happens sometimes (numerical precision) + return true; + } + real t = - b + ::sqrt(delta) / (2.0 * a); + if (t < 0.0) { + // Should not happen, but happens sometimes (numerical precision) + return true; + } + if (t >= 1.0) { + // Inside the sphere + return false; + } + + V[0] = (t * V.x()); + V[1] = (t * V.y()); + V[2] = (t * V.z()); + + return true; +} + +// TODO: check optimizations: +// use marking ? (measure *timings* ...) +void compute_curvature_tensor(WVertex *start, real radius, NormalCycle& nc) +{ + // in case we have a non-manifold vertex, skip it... + if(start->isBoundary()) + return; + + std::set vertices; + const Vec3r& O = start->GetVertex(); + std::stack S; + S.push(start); + vertices.insert(start); + while (!S.empty()) { + WVertex *v = S.top(); + S.pop(); + if (v->isBoundary()) + continue; + const Vec3r& P = v->GetVertex(); + WVertex::incoming_edge_iterator woeit = v->incoming_edges_begin(); + WVertex::incoming_edge_iterator woeitend = v->incoming_edges_end(); + for (; woeit != woeitend; ++woeit) { + WOEdge *h = *woeit; + if ((v == start) || h->GetVec() * (O - P) > 0.0) { + Vec3r V(-1 * h->GetVec()); + bool isect = sphere_clip_vector(O, radius, P, V); + assert (h->GetOwner()->GetNumberOfOEdges() == 2); // Because otherwise v->isBoundary() would be true + nc.accumulate_dihedral_angle(V, h->GetAngle()); + + if (!isect) { + WVertex *w = h->GetaVertex(); + if (vertices.find(w) == vertices.end()) { + vertices.insert(w); + S.push(w); + } + } + } + } + } } + +void compute_curvature_tensor_one_ring(WVertex *start, NormalCycle& nc) +{ + // in case we have a non-manifold vertex, skip it... + if (start->isBoundary()) + return; + + WVertex::incoming_edge_iterator woeit = start->incoming_edges_begin(); + WVertex::incoming_edge_iterator woeitend = start->incoming_edges_end(); + for (; woeit != woeitend; ++woeit) { + WOEdge *h = (*woeit)->twin(); + nc.accumulate_dihedral_angle(h->GetVec(), h->GetAngle()); + WOEdge *hprev = h->getPrevOnFace(); + nc.accumulate_dihedral_angle(hprev->GetVec(), hprev->GetAngle()); + } +} + +} // OGF namespace diff --git a/source/blender/freestyle/intern/winged_edge/Curvature.h b/source/blender/freestyle/intern/winged_edge/Curvature.h index b14a5a38337..20450dbdb38 100644 --- a/source/blender/freestyle/intern/winged_edge/Curvature.h +++ b/source/blender/freestyle/intern/winged_edge/Curvature.h @@ -1,29 +1,59 @@ - -/* GTS - Library for the manipulation of triangulated surfaces - * Copyright (C) 1999 Stéphane Popinet +/* + * ***** BEGIN GPL LICENSE BLOCK ***** * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. * - * This library is distributed in the hope that it will be useful, + * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * This Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: + * GTS - Library for the manipulation of triangulated surfaces + * Copyright (C) 1999 Stephane Popinet + * and: + * OGF/Graphite: Geometry and Graphics Programming Library + Utilities + * Copyright (C) 2000-2003 Bruno Levy + * Contact: Bruno Levy levy@loria.fr + * ISA Project + * LORIA, INRIA Lorraine, + * Campus Scientifique, BP 239 + * 54506 VANDOEUVRE LES NANCY CEDEX + * FRANCE + * + * Contributor(s): none yet. * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * ***** END GPL LICENSE BLOCK ***** */ -#ifndef __CURVATURE_H__ -#define __CURVATURE_H__ +#ifndef __FREESTYLE_CURVATURE_H__ +#define __FREESTYLE_CURVATURE_H__ + +/** \file blender/freestyle/intern/winged_edge/Curvature.h + * \ingroup freestyle + * \brief GTS - Library for the manipulation of triangulated surfaces + * \author Stephane Popinet + * \date 1999 + * \brief OGF/Graphite: Geometry and Graphics Programming Library + Utilities + * \author Bruno Levy + * \date 2000-2003 + */ + +#include "../geometry/Geom.h" + +#include "../system/FreestyleConfig.h" +#include "../system/Precision.h" -# include "../system/FreestyleConfig.h" -# include "../system/Precision.h" -# include "../geometry/Geom.h" using namespace Geometry; class WVertex; @@ -31,126 +61,83 @@ class WVertex; class LIB_WINGED_EDGE_EXPORT CurvatureInfo { public: - - CurvatureInfo() - { - K1 = 0.0; - K2 = 0.0; - e1 = Vec3r(0.0,0.0,0.0); - e2 = Vec3r(0.0,0.0,0.0); - Kr = 0.0; - dKr = 0.0; - er = Vec3r(0.0,0.0,0.0); - } - - CurvatureInfo(const CurvatureInfo& iBrother){ - K1 = iBrother.K1; - K2 = iBrother.K2; - e1 = iBrother.e1; - e2 = iBrother.e2; - Kr = iBrother.Kr; - dKr = iBrother.dKr; - er = iBrother.er; - } - - CurvatureInfo(const CurvatureInfo& ca, const CurvatureInfo& cb, real t) { - K1 = ca.K1 + t * (cb.K1 - ca.K1); - K2 = ca.K2 + t * (cb.K2 - ca.K2); - e1 = ca.e1 + t * (cb.e1 - ca.e1); - e2 = ca.e2 + t * (cb.e2 - ca.e2); - Kr = ca.Kr + t * (cb.Kr - ca.Kr); - dKr = ca.dKr + t * (cb.dKr - ca.dKr); - er = ca.er + t * (cb.er - ca.er); - } - - real K1; // maximum curvature - real K2; // minimum curvature - Vec3r e1; // maximum curvature direction - Vec3r e2; // minimum curvature direction - real Kr; // radial curvature - real dKr; // radial curvature - Vec3r er; // radial curvature direction + CurvatureInfo() + { + K1 = 0.0; + K2 = 0.0; + e1 = Vec3r(0.0, 0.0, 0.0); + e2 = Vec3r(0.0, 0.0, 0.0); + Kr = 0.0; + dKr = 0.0; + er = Vec3r(0.0, 0.0, 0.0); + } + + CurvatureInfo(const CurvatureInfo& iBrother) + { + K1 = iBrother.K1; + K2 = iBrother.K2; + e1 = iBrother.e1; + e2 = iBrother.e2; + Kr = iBrother.Kr; + dKr = iBrother.dKr; + er = iBrother.er; + } + + CurvatureInfo(const CurvatureInfo& ca, const CurvatureInfo& cb, real t) + { + K1 = ca.K1 + t * (cb.K1 - ca.K1); + K2 = ca.K2 + t * (cb.K2 - ca.K2); + e1 = ca.e1 + t * (cb.e1 - ca.e1); + e2 = ca.e2 + t * (cb.e2 - ca.e2); + Kr = ca.Kr + t * (cb.Kr - ca.Kr); + dKr = ca.dKr + t * (cb.dKr - ca.dKr); + er = ca.er + t * (cb.er - ca.er); + } + + real K1; // maximum curvature + real K2; // minimum curvature + Vec3r e1; // maximum curvature direction + Vec3r e2; // minimum curvature direction + real Kr; // radial curvature + real dKr; // radial curvature + Vec3r er; // radial curvature direction }; -class Face_Curvature_Info{ +class Face_Curvature_Info +{ public: - Face_Curvature_Info() {} - ~Face_Curvature_Info(){ - for(vector::iterator ci=vec_curvature_info.begin(), ciend=vec_curvature_info.end(); - ci!=ciend; - ++ci){ - delete (*ci); - } - vec_curvature_info.clear(); - } - vector vec_curvature_info; + Face_Curvature_Info() {} + + ~Face_Curvature_Info() + { + for (vector::iterator ci = vec_curvature_info.begin(), ciend = vec_curvature_info.end(); + ci != ciend; + ++ci) + { + delete (*ci); + } + vec_curvature_info.clear(); + } + + vector vec_curvature_info; }; -bool LIB_WINGED_EDGE_EXPORT gts_vertex_mean_curvature_normal (WVertex * v, - Vec3r &n); +bool LIB_WINGED_EDGE_EXPORT gts_vertex_mean_curvature_normal(WVertex *v, Vec3r &n); -bool LIB_WINGED_EDGE_EXPORT gts_vertex_gaussian_curvature (WVertex * v, - real * Kg); +bool LIB_WINGED_EDGE_EXPORT gts_vertex_gaussian_curvature(WVertex *v, real *Kg); -void LIB_WINGED_EDGE_EXPORT gts_vertex_principal_curvatures (real Kh, - real Kg, - real * K1, - real * K2); +void LIB_WINGED_EDGE_EXPORT gts_vertex_principal_curvatures(real Kh, real Kg, real *K1, real *K2); -void LIB_WINGED_EDGE_EXPORT gts_vertex_principal_directions (WVertex * v, - Vec3r Kh, - real Kg, - Vec3r &e1, - Vec3r &e2); - -/* - * OGF/Graphite: Geometry and Graphics Programming Library + Utilities - * Copyright (C) 2000-2003 Bruno Levy - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * If you modify this software, you should include a notice giving the - * name of the person performing the modification, the date of modification, - * and the reason for such modification. - * - * Contact: Bruno Levy - * - * levy@loria.fr - * - * ISA Project - * LORIA, INRIA Lorraine, - * Campus Scientifique, BP 239 - * 54506 VANDOEUVRE LES NANCY CEDEX - * FRANCE - * - * Note that the GNU General Public License does not permit incorporating - * the Software into proprietary programs. - */ - namespace OGF { +void LIB_WINGED_EDGE_EXPORT gts_vertex_principal_directions(WVertex *v, Vec3r Kh, real Kg, Vec3r &e1, Vec3r &e2); - class NormalCycle ; +namespace OGF { - void LIB_WINGED_EDGE_EXPORT compute_curvature_tensor( - WVertex* start, double radius, NormalCycle& nc - ) ; +class NormalCycle ; - void LIB_WINGED_EDGE_EXPORT compute_curvature_tensor_one_ring( - WVertex* start, NormalCycle& nc - ) ; - } +void LIB_WINGED_EDGE_EXPORT compute_curvature_tensor( WVertex *start, double radius, NormalCycle& nc); +void LIB_WINGED_EDGE_EXPORT compute_curvature_tensor_one_ring(WVertex *start, NormalCycle& nc); -#endif /* __CURVATURE_H__ */ +} // OGF namespace +#endif /* __FREESTYLE_CURVATURE_H__ */ diff --git a/source/blender/freestyle/intern/winged_edge/Nature.h b/source/blender/freestyle/intern/winged_edge/Nature.h index 62171fae111..0ce64f3f1cb 100644 --- a/source/blender/freestyle/intern/winged_edge/Nature.h +++ b/source/blender/freestyle/intern/winged_edge/Nature.h @@ -1,79 +1,79 @@ -// -// Filename : Nature.h -// Author(s) : Emmanuel Turquin -// Purpose : Different natures for both vertices and edges -// Date of creation : 01/07/2003 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ -#ifndef NATURE_H -# define NATURE_H +#ifndef __FREESTYLE_NATURE_H__ +#define __FREESTYLE_NATURE_H__ -/*! \file Nature.h - * Definitions of Natures of the ViewMap's elements +/** \file blender/freestyle/intern/winged_edge/Nature.h + * \ingroup freestyle + * \brief Different natures for both vertices and edges + * \author Emmanuel Turquin + * \date 01/07/2003 */ -/*! Namespace gathering the different possible - * natures of 0D and 1D elements of the ViewMap - */ +/*! Namespace gathering the different possible natures of 0D and 1D elements of the ViewMap */ namespace Nature { - - typedef unsigned short VertexNature; - /*! true for any 0D element */ - static const VertexNature POINT = 0; // 0 - /*! true for SVertex */ - static const VertexNature S_VERTEX = (1 << 0); // 1 - /*! true for ViewVertex */ - static const VertexNature VIEW_VERTEX = (1 << 1); // 2 - /*! true for NonTVertex */ - static const VertexNature NON_T_VERTEX = (1 << 2); // 4 - /*! true for TVertex */ - static const VertexNature T_VERTEX = (1 << 3); // 8 - /*! true for CUSP */ - static const VertexNature CUSP = (1 << 4); // 16 +/* XXX Why not using enums??? */ + +typedef unsigned short VertexNature; +/*! true for any 0D element */ +static const VertexNature POINT = 0; // 0 +/*! true for SVertex */ +static const VertexNature S_VERTEX = (1 << 0); // 1 +/*! true for ViewVertex */ +static const VertexNature VIEW_VERTEX = (1 << 1); // 2 +/*! true for NonTVertex */ +static const VertexNature NON_T_VERTEX = (1 << 2); // 4 +/*! true for TVertex */ +static const VertexNature T_VERTEX = (1 << 3); // 8 +/*! true for CUSP */ +static const VertexNature CUSP = (1 << 4); // 16 - typedef unsigned short EdgeNature; - /*! true for non feature edges (always false for 1D elements of the ViewMap) */ - static const EdgeNature NO_FEATURE = 0; // 0 - /*! true for silhouettes */ - static const EdgeNature SILHOUETTE = (1 << 0); // 1 - /*! true for borders */ - static const EdgeNature BORDER = (1 << 1); // 2 - /*! true for creases */ - static const EdgeNature CREASE = (1 << 2); // 4 - /*! true for ridges */ - static const EdgeNature RIDGE = (1 << 3); // 8 - /*! true for valleys */ - static const EdgeNature VALLEY = (1 << 4); // 16 - /*! true for suggestive contours */ - static const EdgeNature SUGGESTIVE_CONTOUR = (1 << 5); // 32 - /*! true for material boundaries */ - static const EdgeNature MATERIAL_BOUNDARY = (1 << 6); // 64 - /*! true for user-defined edge marks */ - static const EdgeNature EDGE_MARK = (1 << 7); // 128 +typedef unsigned short EdgeNature; +/*! true for non feature edges (always false for 1D elements of the ViewMap) */ +static const EdgeNature NO_FEATURE = 0; // 0 +/*! true for silhouettes */ +static const EdgeNature SILHOUETTE = (1 << 0); // 1 +/*! true for borders */ +static const EdgeNature BORDER = (1 << 1); // 2 +/*! true for creases */ +static const EdgeNature CREASE = (1 << 2); // 4 +/*! true for ridges */ +static const EdgeNature RIDGE = (1 << 3); // 8 +/*! true for valleys */ +static const EdgeNature VALLEY = (1 << 4); // 16 +/*! true for suggestive contours */ +static const EdgeNature SUGGESTIVE_CONTOUR = (1 << 5); // 32 +/*! true for material boundaries */ +static const EdgeNature MATERIAL_BOUNDARY = (1 << 6); // 64 +/*! true for user-defined edge marks */ +static const EdgeNature EDGE_MARK = (1 << 7); // 128 } // end of namespace Nature -#endif // NATURE_H +#endif // __FREESTYLE_NATURE_H__ diff --git a/source/blender/freestyle/intern/winged_edge/WEdge.cpp b/source/blender/freestyle/intern/winged_edge/WEdge.cpp index 6ef99186a2c..6201d23f9bf 100644 --- a/source/blender/freestyle/intern/winged_edge/WEdge.cpp +++ b/source/blender/freestyle/intern/winged_edge/WEdge.cpp @@ -1,752 +1,713 @@ - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/freestyle/intern/winged_edge/WEdge.cpp + * \ingroup freestyle + * \brief Classes to define a Winged Edge data structure. + * \author Stephane Grabli + * \date 18/02/2002 + */ #include + #include "WEdge.h" /*! Temporary structures */ class vertexdata { public: - WVertex *_copy; + WVertex *_copy; }; class oedgedata { public: - WOEdge *_copy; + WOEdge *_copy; }; class edgedata { public: - WEdge *_copy; + WEdge *_copy; }; class facedata { public: - WFace *_copy; + WFace *_copy; }; - /**********************************/ - /* */ - /* */ - /* WVertex */ - /* */ - /* */ - /**********************************/ +/********************************** + * * + * * + * WVertex * + * * + * * + **********************************/ WVertex::WVertex(WVertex& iBrother) { - _Id = iBrother._Id; - _Vertex = iBrother._Vertex; - _EdgeList = iBrother._EdgeList; - - _Shape = iBrother._Shape; - _Smooth = iBrother._Smooth; - _Border = iBrother._Border; - userdata = NULL; - iBrother.userdata = new vertexdata; - ((vertexdata*)(iBrother.userdata))->_copy = this; + _Id = iBrother._Id; + _Vertex = iBrother._Vertex; + _EdgeList = iBrother._EdgeList; + + _Shape = iBrother._Shape; + _Smooth = iBrother._Smooth; + _Border = iBrother._Border; + userdata = NULL; + iBrother.userdata = new vertexdata; + ((vertexdata *)(iBrother.userdata))->_copy = this; } -WVertex* WVertex::duplicate() +WVertex *WVertex::duplicate() { - WVertex *clone = new WVertex(*this); - return clone; + WVertex *clone = new WVertex(*this); + return clone; } - -WOEdge* WVertex::incoming_edge_iterator::operator*() - -{ - return _current; +WOEdge *WVertex::incoming_edge_iterator::operator*() +{ + return _current; } -void WVertex::incoming_edge_iterator::increment(){ - WOEdge *twin = _current->twin(); - if(!twin){ - // we reached a hole - _current = 0; - return; - } - WOEdge *next = twin->getPrevOnFace(); - if(next == _begin){ - next = 0; - } - _current = next; + +void WVertex::incoming_edge_iterator::increment() +{ + WOEdge *twin = _current->twin(); + if (!twin) { + // we reached a hole + _current = 0; + return; + } + WOEdge *next = twin->getPrevOnFace(); + if (next == _begin) { + next = NULL; + } + _current = next; } -WFace* WVertex::face_iterator::operator*(){ - WOEdge * woedge = *_edge_it; - if(woedge == 0) - return 0; - return (woedge)->GetbFace(); +WFace *WVertex::face_iterator::operator*() +{ + WOEdge *woedge = *_edge_it; + if (!woedge) + return NULL; + return (woedge)->GetbFace(); } -//bool WVertex::isBoundary () const{ -// return _Border; -//} +#if 0 +bool WVertex::isBoundary () const +{ + return _Border; +} +#endif bool WVertex::isBoundary () { - if(_Border == 1) - return true; - else if(_Border == 0) - return false; - + if (_Border == 1) + return true; + else if (_Border == 0) + return false; + vector::const_iterator it; - for(it=_EdgeList.begin(); it!=_EdgeList.end(); it++){ - if((*it)->GetNumberOfOEdges() == 1){ - _Border = 1; - return true; - } - } - //if (!(*it)->GetaOEdge()->GetaFace()) return true; - _Border = 0; + for (it = _EdgeList.begin(); it != _EdgeList.end(); it++) { + if ((*it)->GetNumberOfOEdges() == 1) { + _Border = 1; + return true; + } + } +#if 0 + if (!(*it)->GetaOEdge()->GetaFace()) + return true; +#endif + _Border = 0; return false; } -void WVertex::AddEdge(WEdge *iEdge) { - _EdgeList.push_back(iEdge); +void WVertex::AddEdge(WEdge *iEdge) +{ + _EdgeList.push_back(iEdge); } -WVertex::incoming_edge_iterator WVertex::incoming_edges_begin(){ - WOEdge *begin; - WEdge * wedge = _EdgeList.front(); - WOEdge* aOEdge = wedge->GetaOEdge(); - if(aOEdge->GetbVertex() == this) - begin = aOEdge; - else - begin = _EdgeList.front()->GetbOEdge(); - return incoming_edge_iterator(this, begin, begin); +WVertex::incoming_edge_iterator WVertex::incoming_edges_begin() +{ + WOEdge *begin; + WEdge *wedge = _EdgeList.front(); + WOEdge *aOEdge = wedge->GetaOEdge(); + if (aOEdge->GetbVertex() == this) + begin = aOEdge; + else + begin = _EdgeList.front()->GetbOEdge(); + return incoming_edge_iterator(this, begin, begin); +} + +WVertex::incoming_edge_iterator WVertex::incoming_edges_end() +{ + WOEdge *begin; + WOEdge *aOEdge = _EdgeList.front()->GetaOEdge(); + if (aOEdge->GetbVertex() == this) + begin = aOEdge; + else + begin = _EdgeList.front()->GetbOEdge(); + return incoming_edge_iterator(this, begin, 0); } -WVertex::incoming_edge_iterator WVertex::incoming_edges_end(){ - WOEdge *begin; - WOEdge* aOEdge = _EdgeList.front()->GetaOEdge(); - if(aOEdge->GetbVertex() == this) - begin = aOEdge; - else - begin = _EdgeList.front()->GetbOEdge(); - return incoming_edge_iterator(this, begin, 0); +#if 0 +WOEdge **WVertex::incoming_edge_iterator::operator->() +{ + WOEdge **ppaOEdge = (*_iter)->GetaOEdge(); + if (aOEdge->GetbVertex() == _vertex) { + return ppaOEdge; + } + else { + WOEdge *bOEdge = (*_iter)->GetbOEdge(); + return &bOEdge; + } } -//WOEdge** WVertex::incoming_edge_iterator::operator->() -//{ -// WOEdge ** ppaOEdge = (*_iter)->GetaOEdge(); -// if(aOEdge->GetbVertex() == _vertex) -// return ppaOEdge; -// else -// { -// WOEdge *bOEdge = (*_iter)->GetbOEdge(); -// return &bOEdge; -// } -// -//} - /**********************************/ - /* */ - /* */ - /* WOEdge */ - /* */ - /* */ - /**********************************/ +#endif + +/********************************** + * * + * * + * WOEdge * + * * + * * + **********************************/ WOEdge::WOEdge(WOEdge& iBrother) { - _paVertex = iBrother.GetaVertex(); - _pbVertex = iBrother.GetbVertex(); - _paFace = iBrother.GetaFace(); - _pbFace = iBrother.GetbFace(); - _pOwner = iBrother.GetOwner(); - userdata = NULL; - iBrother.userdata = new oedgedata; - ((oedgedata*)(iBrother.userdata))->_copy = this; - - _vec = iBrother._vec; - _angle = iBrother._angle; + _paVertex = iBrother.GetaVertex(); + _pbVertex = iBrother.GetbVertex(); + _paFace = iBrother.GetaFace(); + _pbFace = iBrother.GetbFace(); + _pOwner = iBrother.GetOwner(); + userdata = NULL; + iBrother.userdata = new oedgedata; + ((oedgedata *)(iBrother.userdata))->_copy = this; + + _vec = iBrother._vec; + _angle = iBrother._angle; } -WOEdge * WOEdge::duplicate() +WOEdge *WOEdge::duplicate() { - WOEdge *clone = new WOEdge(*this); - return clone; + WOEdge *clone = new WOEdge(*this); + return clone; } -Vec3r -WOEdge::getVec3r () +Vec3r WOEdge::getVec3r () { - return Vec3r(_pbVertex->GetVertex() - _paVertex->GetVertex()); -} + return Vec3r(_pbVertex->GetVertex() - _paVertex->GetVertex()); +} -WOEdge * WOEdge::twin () +WOEdge *WOEdge::twin () { - return GetOwner()->GetOtherOEdge(this); + return GetOwner()->GetOtherOEdge(this); } -WOEdge * -WOEdge::getPrevOnFace() +WOEdge *WOEdge::getPrevOnFace() { return _pbFace->GetPrevOEdge(this); } - /**********************************/ - /* */ - /* */ - /* WEdge */ - /* */ - /* */ - /**********************************/ +/********************************** + * * + * * + * WEdge * + * * + * * + **********************************/ WEdge::WEdge(WEdge& iBrother) { - _paOEdge = NULL; - _pbOEdge = NULL; - WOEdge *aoedge = iBrother.GetaOEdge(); - WOEdge *boedge = iBrother.GetbOEdge(); - userdata = NULL; - - if(NULL != aoedge) - //_paOEdge = new WOEdge(*aoedge); - _paOEdge = aoedge->duplicate(); - if(NULL != boedge) - //_pbOEdge = new WOEdge(*boedge); - _pbOEdge = boedge->duplicate(); - - _nOEdges = iBrother.GetNumberOfOEdges(); - _Id = iBrother.GetId(); - iBrother.userdata = new edgedata; - ((edgedata*)(iBrother.userdata))->_copy = this; + _paOEdge = NULL; + _pbOEdge = NULL; + WOEdge *aoedge = iBrother.GetaOEdge(); + WOEdge *boedge = iBrother.GetbOEdge(); + userdata = NULL; + + if (aoedge) + //_paOEdge = new WOEdge(*aoedge); + _paOEdge = aoedge->duplicate(); + if (boedge) + //_pbOEdge = new WOEdge(*boedge); + _pbOEdge = boedge->duplicate(); + + _nOEdges = iBrother.GetNumberOfOEdges(); + _Id = iBrother.GetId(); + iBrother.userdata = new edgedata; + ((edgedata *)(iBrother.userdata))->_copy = this; } -WEdge * WEdge::duplicate() +WEdge *WEdge::duplicate() { - WEdge *clone = new WEdge(*this); - return clone; + WEdge *clone = new WEdge(*this); + return clone; } - /**********************************/ - /* */ - /* */ - /* WFace */ - /* */ - /* */ - /**********************************/ - +/********************************** + * * + * * + * WFace * + * * + * * + **********************************/ WFace::WFace(WFace& iBrother) { - _OEdgeList = iBrother.getEdgeList(); - _Normal = iBrother.GetNormal(); - _VerticesNormals = iBrother._VerticesNormals; - _VerticesTexCoords = iBrother._VerticesTexCoords; - _Id = iBrother.GetId(); - _FrsMaterialIndex = iBrother._FrsMaterialIndex; - _Mark = iBrother._Mark; - userdata = NULL; - iBrother.userdata = new facedata; - ((facedata*)(iBrother.userdata))->_copy = this; + _OEdgeList = iBrother.getEdgeList(); + _Normal = iBrother.GetNormal(); + _VerticesNormals = iBrother._VerticesNormals; + _VerticesTexCoords = iBrother._VerticesTexCoords; + _Id = iBrother.GetId(); + _FrsMaterialIndex = iBrother._FrsMaterialIndex; + _Mark = iBrother._Mark; + userdata = NULL; + iBrother.userdata = new facedata; + ((facedata *)(iBrother.userdata))->_copy = this; } -WFace * WFace::duplicate() +WFace *WFace::duplicate() { - WFace * clone = new WFace(*this); - return clone; + WFace *clone = new WFace(*this); + return clone; } -const FrsMaterial& WFace::frs_material() { - return getShape()->frs_material(_FrsMaterialIndex); +const FrsMaterial& WFace::frs_material() +{ + return getShape()->frs_material(_FrsMaterialIndex); } -WOEdge * WFace::MakeEdge(WVertex *v1, WVertex *v2) -{ - // First check whether the same oriented edge already exists - // or not: - vector& v1Edges = v1->GetEdges(); - for(vector::iterator it1=v1Edges.begin(), end=v1Edges.end(); - it1!=end; - it1++) - { - - WEdge *we=(*it1); - - WOEdge *woea = we->GetaOEdge(); - - if((woea->GetaVertex() == v1) && (woea->GetbVertex() == v2)) - //if((*it1)->GetbVertex() == v2) - { - // The oriented edge already exists - cerr << "Warning: edge " << v1->GetId() << " - " << v2->GetId() << " appears twice, correcting" << endl; - // Adds the edge to the face - //AddEdge((*it1)->GetaOEdge()); - AddEdge(woea); - (*it1)->setNumberOfOEdges((*it1)->GetNumberOfOEdges()+1); - //sets these vertices as border: - v1->setBorder(true); - v2->setBorder(true); - //return (*it1)->GetaOEdge(); - return woea; - } - - WOEdge *woeb = we->GetbOEdge(); - if((woeb != 0) && (woeb->GetaVertex() == v1) && (woeb->GetbVertex() == v2)) - - //if((*it1)->GetbVertex() == v2) - - { - // The oriented edge already exists - cerr << "Warning: edge " << v1->GetId() << " - " << v2->GetId() << " appears twice, correcting" << endl; - // Adds the edge to the face - //AddEdge((*it1)->GetaOEdge()); - AddEdge(woeb); - (*it1)->setNumberOfOEdges((*it1)->GetNumberOfOEdges()+1); - //sets these vertices as border: - v1->setBorder(true); - v2->setBorder(true); - //return (*it1)->GetaOEdge(); - return woeb; - } - } - - // the oriented edge we're about to build - WOEdge *pOEdge = new WOEdge; - - WEdge * edge; // The edge containing the oriented edge. - - // checks whether this edge already exists or not - // If it exists, it points outward v2 - - bool exist = false; - WOEdge *pInvertEdge = NULL; // The inverted edge if it exists - vector& v2Edges = v2->GetEdges(); - vector::iterator it; - for(it=v2Edges.begin(); it!=v2Edges.end(); it++) - { - if((*it)->GetbVertex() == v1) - { - // The invert edge already exists - exist = true; - pInvertEdge = (*it)->GetaOEdge(); - break; - } - } - - //DEBUG: - - - if(true == exist) // The invert edge already exists - { - // Retrieves the corresponding edge - edge = pInvertEdge->GetOwner(); - - // Sets the a Face (retrieved from pInvertEdge - pOEdge->setaFace(pInvertEdge->GetbFace()); - - // Updates the invert edge: - pInvertEdge->setaFace(this); - } - else // The invert edge does not exist yet - { - // we must create a new edge - //edge = new WEdge; - edge = instanciateEdge(); - - // updates the a,b vertex edges list: - v1->AddEdge(edge); - v2->AddEdge(edge); - - } - - pOEdge->setOwner(edge); - // Add the vertices: - pOEdge->setaVertex(v1); - pOEdge->setbVertex(v2); - - // Debug: - if(v1->GetId() == v2->GetId()) - cerr << "Warning: edge " << this << " null with vertex " << v1->GetId() << endl; - - edge->AddOEdge(pOEdge); - //edge->setNumberOfOEdges(edge->GetNumberOfOEdges()+1); - - // Add this face (the b face) - pOEdge->setbFace(this); - - // Adds the edge to the face - AddEdge(pOEdge); - - return pOEdge; +WOEdge *WFace::MakeEdge(WVertex *v1, WVertex *v2) +{ + // First check whether the same oriented edge already exists or not: + vector& v1Edges = v1->GetEdges(); + for (vector::iterator it1 = v1Edges.begin(), end = v1Edges.end(); it1 != end; it1++) { + WEdge *we = (*it1); + WOEdge *woea = we->GetaOEdge(); + + //if ((*it1)->GetbVertex() == v2) { + if ((woea->GetaVertex() == v1) && (woea->GetbVertex() == v2)) { + // The oriented edge already exists + cerr << "Warning: edge " << v1->GetId() << " - " << v2->GetId() << " appears twice, correcting" << endl; + // Adds the edge to the face + //AddEdge((*it1)->GetaOEdge()); + AddEdge(woea); + (*it1)->setNumberOfOEdges((*it1)->GetNumberOfOEdges()+1); + //sets these vertices as border: + v1->setBorder(true); + v2->setBorder(true); + //return (*it1)->GetaOEdge(); + return woea; + } + + WOEdge *woeb = we->GetbOEdge(); + //if ((*it1)->GetbVertex() == v2) + if (woeb && (woeb->GetaVertex() == v1) && (woeb->GetbVertex() == v2)) { + // The oriented edge already exists + cerr << "Warning: edge " << v1->GetId() << " - " << v2->GetId() << " appears twice, correcting" << endl; + // Adds the edge to the face + //AddEdge((*it1)->GetaOEdge()); + AddEdge(woeb); + (*it1)->setNumberOfOEdges((*it1)->GetNumberOfOEdges()+1); + //sets these vertices as border: + v1->setBorder(true); + v2->setBorder(true); + //return (*it1)->GetaOEdge(); + return woeb; + } + } + + // the oriented edge we're about to build + WOEdge *pOEdge = new WOEdge; + // The edge containing the oriented edge. + WEdge *edge; + + // checks whether this edge already exists or not + // If it exists, it points outward v2 + bool exist = false; + WOEdge *pInvertEdge = NULL; // The inverted edge if it exists + vector& v2Edges = v2->GetEdges(); + vector::iterator it; + for (it = v2Edges.begin(); it != v2Edges.end(); it++) { + if ((*it)->GetbVertex() == v1) { + // The invert edge already exists + exist = true; + pInvertEdge = (*it)->GetaOEdge(); + break; + } + } + + //DEBUG: + if (true == exist) { // The invert edge already exists + // Retrieves the corresponding edge + edge = pInvertEdge->GetOwner(); + + // Sets the a Face (retrieved from pInvertEdge + pOEdge->setaFace(pInvertEdge->GetbFace()); + + // Updates the invert edge: + pInvertEdge->setaFace(this); + } + else { // The invert edge does not exist yet + // we must create a new edge + //edge = new WEdge; + edge = instanciateEdge(); + + // updates the a,b vertex edges list: + v1->AddEdge(edge); + v2->AddEdge(edge); + } + + pOEdge->setOwner(edge); + // Add the vertices: + pOEdge->setaVertex(v1); + pOEdge->setbVertex(v2); + + // Debug: + if (v1->GetId() == v2->GetId()) + cerr << "Warning: edge " << this << " null with vertex " << v1->GetId() << endl; + + edge->AddOEdge(pOEdge); + //edge->setNumberOfOEdges(edge->GetNumberOfOEdges() + 1); + + // Add this face (the b face) + pOEdge->setbFace(this); + + // Adds the edge to the face + AddEdge(pOEdge); + + return pOEdge; } -bool -WFace::getOppositeEdge (const WVertex *v, WOEdge* &e) +bool WFace::getOppositeEdge (const WVertex *v, WOEdge *&e) { - if (_OEdgeList.size()!=3) return false; + if (_OEdgeList.size() != 3) + return false; vector::iterator it; - e=NULL; - for(it=_OEdgeList.begin(); it!=_OEdgeList.end(); it++) - if ((*it)->GetaVertex()==v) e=*it; - if (!e) return false; - e=NULL; - for(it=_OEdgeList.begin(); it!=_OEdgeList.end(); it++) - if (((*it)->GetaVertex()!=v) && ((*it)->GetbVertex()!=v)) e=*it; - if (!e) return false; - else return true; + e = NULL; + for (it = _OEdgeList.begin(); it != _OEdgeList.end(); it++) { + if ((*it)->GetaVertex() == v) + e = *it; + } + if (!e) + return false; + e = NULL; + for (it = _OEdgeList.begin(); it != _OEdgeList.end(); it++) { + if (((*it)->GetaVertex() != v) && ((*it)->GetbVertex() != v)) + e = *it; + } + if (!e) + return false; + else + return true; } -real -WFace::getArea () +real WFace::getArea () { vector::iterator it; - Vec3r origin=(*(_OEdgeList.begin()))->GetaVertex()->GetVertex(); - it=_OEdgeList.begin(); - real a=0; - for (it=it++; it!=_OEdgeList.end(); it++) { - Vec3r v1=Vec3r((*it)->GetaVertex()->GetVertex() - origin); - Vec3r v2=Vec3r((*it)->GetbVertex()->GetVertex() - origin); - a += (v1 ^ v2).norm() / 2.0; + Vec3r origin = (*(_OEdgeList.begin()))->GetaVertex()->GetVertex(); + it = _OEdgeList.begin(); + real a = 0; + for (it = it++; it != _OEdgeList.end(); it++) { + Vec3r v1 = Vec3r((*it)->GetaVertex()->GetVertex() - origin); + Vec3r v2 = Vec3r((*it)->GetbVertex()->GetVertex() - origin); + a += (v1 ^ v2).norm() / 2.0; } return a; } -WOEdge* -WFace::GetPrevOEdge(WOEdge* iOEdge) - { - vector::iterator woe,woend, woefirst; - woefirst = _OEdgeList.begin(); - woend=_OEdgeList.end(); - WOEdge *prev =*woefirst; - woe=woefirst; - woe++; - for(; - woe!=woend; - woe++) - { - if((*woe) == iOEdge) - return prev; - prev= *woe; +WOEdge *WFace::GetPrevOEdge(WOEdge* iOEdge) +{ + vector::iterator woe, woend, woefirst; + woefirst = _OEdgeList.begin(); + woend = _OEdgeList.end(); + WOEdge *prev = *woefirst; + woe = woefirst; + ++woe; + for (; woe != woend; woe++) { + if ((*woe) == iOEdge) + return prev; + prev = *woe; } - // We left the loop. That means that the first - // OEdge was the good one: - if((*woefirst)==iOEdge) - return prev; + // We left the loop. That means that the first OEdge was the good one: + if ((*woefirst) == iOEdge) + return prev; - return NULL; - } + return NULL; +} -WShape * WFace::getShape() +WShape *WFace::getShape() { - return GetVertex(0)->shape(); + return GetVertex(0)->shape(); } - /**********************************/ - /* */ - /* */ - /* WShape */ - /* */ - /* */ - /**********************************/ +/********************************** + * * + * * + * WShape * + * * + * * + **********************************/ LIB_WINGED_EDGE_EXPORT unsigned WShape::_SceneCurrentId = 0; -WShape * WShape::duplicate() +WShape *WShape::duplicate() { - WShape *clone = new WShape(*this); - return clone; + WShape *clone = new WShape(*this); + return clone; } WShape::WShape(WShape& iBrother) { - _Id = iBrother.GetId(); - _Name = iBrother._Name; - _FrsMaterials = iBrother._FrsMaterials; - _meanEdgeSize = iBrother._meanEdgeSize; - iBrother.bbox(_min, _max); - vector& vertexList = iBrother.getVertexList(); - vector::iterator v=vertexList.begin(), vend=vertexList.end(); - for(; - v!=vend; - v++) - { - //WVertex *newVertex = new WVertex(*(*v)); - WVertex *newVertex = (*v)->duplicate(); - - newVertex->setShape(this); - AddVertex(newVertex); - } - - vector& edgeList = iBrother.getEdgeList(); - vector::iterator e=edgeList.begin(), eend=edgeList.end(); - for(; - e!=eend; - e++) - { - //WEdge *newEdge = new WEdge(*(*e)); - WEdge *newEdge = (*e)->duplicate(); - AddEdge(newEdge); - } - - vector& faceList = iBrother.GetFaceList(); - vector::iterator f=faceList.begin(), fend=faceList.end(); - for(; - f!=fend; - f++) - { - //WFace *newFace = new WFace(*(*f)); - WFace *newFace = (*f)->duplicate(); - AddFace(newFace); - } - - // update all pointed addresses thanks to the newly created objects: - vend=_VertexList.end(); - for(v=_VertexList.begin(); - v!=vend; - v++) - { - const vector& vedgeList = (*v)->GetEdges(); - vector newvedgelist; - unsigned int i; - for(i=0; iuserdata; - newvedgelist.push_back(currentvedata->_copy); - } - (*v)->setEdges(newvedgelist); - } - - eend = _EdgeList.end(); - for(e=_EdgeList.begin(); - e!=eend; - e++) - { - // update aOedge: - WOEdge *aoEdge = (*e)->GetaOEdge(); - aoEdge->setaVertex(((vertexdata*)(aoEdge->GetaVertex()->userdata))->_copy); - aoEdge->setbVertex(((vertexdata*)(aoEdge->GetbVertex()->userdata))->_copy); - if(NULL != aoEdge->GetaFace()) - aoEdge->setaFace(((facedata*)(aoEdge->GetaFace()->userdata))->_copy); - aoEdge->setbFace(((facedata*)(aoEdge->GetbFace()->userdata))->_copy); - aoEdge->setOwner(((edgedata*)(aoEdge->GetOwner()->userdata))->_copy); - // update bOedge: - - WOEdge *boEdge = (*e)->GetbOEdge(); - if(boEdge != 0) - { - boEdge->setaVertex(((vertexdata*)(boEdge->GetaVertex()->userdata))->_copy); - boEdge->setbVertex(((vertexdata*)(boEdge->GetbVertex()->userdata))->_copy); - if(NULL != boEdge->GetaFace()) - boEdge->setaFace(((facedata*)(boEdge->GetaFace()->userdata))->_copy); - boEdge->setbFace(((facedata*)(boEdge->GetbFace()->userdata))->_copy); - boEdge->setOwner(((edgedata*)(boEdge->GetOwner()->userdata))->_copy); - } - } - - fend = _FaceList.end(); - for(f=_FaceList.begin(); - f!=fend; - f++) - { - unsigned i; - const vector& oedgeList = (*f)->getEdgeList(); - vector newoedgelist; - - unsigned n = oedgeList.size(); - for(i=0; iuserdata; - newoedgelist.push_back(currentoedata->_copy); - //oedgeList[i] = currentoedata->_copy; - //oedgeList[i] = ((oedgedata*)(oedgeList[i]->userdata))->_copy; - } - (*f)->setEdgeList(newoedgelist); - } - - // Free all memory (arghh!) - // Vertex - vend = iBrother.getVertexList().end(); - for(v=iBrother.getVertexList().begin(); - v!=vend; - v++) - { - delete (vertexdata*)((*v)->userdata); - (*v)->userdata = NULL; - } - - // Edges and OEdges: - eend = iBrother.getEdgeList().end(); - for(e=iBrother.getEdgeList().begin(); - e!=eend; - e++) - { - delete (edgedata*)((*e)->userdata); - (*e)->userdata = NULL; - // OEdge a : - delete (oedgedata*)((*e)->GetaOEdge()->userdata); - (*e)->GetaOEdge()->userdata = NULL; - // OEdge b: - WOEdge* oedgeb = (*e)->GetbOEdge(); - if(NULL != oedgeb) - { - delete (oedgedata*)(oedgeb->userdata); - oedgeb->userdata = NULL; - } - } - // Faces - fend = iBrother.GetFaceList().end(); - for(f=iBrother.GetFaceList().begin(); - f!=fend; - f++) - { - delete (facedata*)((*f)->userdata); - (*f)->userdata = NULL; - } -} + _Id = iBrother.GetId(); + _Name = iBrother._Name; + _FrsMaterials = iBrother._FrsMaterials; + _meanEdgeSize = iBrother._meanEdgeSize; + iBrother.bbox(_min, _max); + vector& vertexList = iBrother.getVertexList(); + vector::iterator v = vertexList.begin(), vend = vertexList.end(); + for (; v != vend; ++v) { + //WVertex *newVertex = new WVertex(*(*v)); + WVertex *newVertex = (*v)->duplicate(); + + newVertex->setShape(this); + AddVertex(newVertex); + } -WFace* WShape::MakeFace(vector& iVertexList, vector& iFaceEdgeMarksList, unsigned iMaterial) -{ - // allocate the new face - WFace *face = instanciateFace(); + vector& edgeList = iBrother.getEdgeList(); + vector::iterator e = edgeList.begin(), eend = edgeList.end(); + for (; e != eend; ++e) { + //WEdge *newEdge = new WEdge(*(*e)); + WEdge *newEdge = (*e)->duplicate(); + AddEdge(newEdge); + } - WFace *result = MakeFace(iVertexList, iFaceEdgeMarksList, iMaterial, face); - if (0 == result) { - delete face; - return 0; - } - return result; -} + vector& faceList = iBrother.GetFaceList(); + vector::iterator f = faceList.begin(), fend = faceList.end(); + for (; f != fend; ++f) { + //WFace *newFace = new WFace(*(*f)); + WFace *newFace = (*f)->duplicate(); + AddFace(newFace); + } -WFace * WShape::MakeFace(vector& iVertexList, vector& iNormalsList, vector& iTexCoordsList, vector& iFaceEdgeMarksList, unsigned iMaterial) -{ - // allocate the new face - WFace *face = MakeFace(iVertexList, iFaceEdgeMarksList, iMaterial); + // update all pointed addresses thanks to the newly created objects: + vend = _VertexList.end(); + for (v = _VertexList.begin(); v != vend; ++v) { + const vector& vedgeList = (*v)->GetEdges(); + vector newvedgelist; + unsigned int i; + for (i = 0; i < vedgeList.size(); i++) { + WEdge *current = vedgeList[i]; + edgedata *currentvedata = (edgedata *)current->userdata; + newvedgelist.push_back(currentvedata->_copy); + } + (*v)->setEdges(newvedgelist); + } + + eend = _EdgeList.end(); + for (e = _EdgeList.begin(); e != eend; ++e) { + // update aOedge: + WOEdge *aoEdge = (*e)->GetaOEdge(); + aoEdge->setaVertex(((vertexdata *)(aoEdge->GetaVertex()->userdata))->_copy); + aoEdge->setbVertex(((vertexdata *)(aoEdge->GetbVertex()->userdata))->_copy); + if (aoEdge->GetaFace()) + aoEdge->setaFace(((facedata *)(aoEdge->GetaFace()->userdata))->_copy); + aoEdge->setbFace(((facedata *)(aoEdge->GetbFace()->userdata))->_copy); + aoEdge->setOwner(((edgedata *)(aoEdge->GetOwner()->userdata))->_copy); + + // update bOedge: + WOEdge *boEdge = (*e)->GetbOEdge(); + if (boEdge) { + boEdge->setaVertex(((vertexdata *)(boEdge->GetaVertex()->userdata))->_copy); + boEdge->setbVertex(((vertexdata *)(boEdge->GetbVertex()->userdata))->_copy); + if (boEdge->GetaFace()) + boEdge->setaFace(((facedata *)(boEdge->GetaFace()->userdata))->_copy); + boEdge->setbFace(((facedata *)(boEdge->GetbFace()->userdata))->_copy); + boEdge->setOwner(((edgedata *)(boEdge->GetOwner()->userdata))->_copy); + } + } - if(0 == face) + fend = _FaceList.end(); + for (f = _FaceList.begin(); f != fend; ++f) { + unsigned int i; + const vector& oedgeList = (*f)->getEdgeList(); + vector newoedgelist; + + unsigned int n = oedgeList.size(); + for (i = 0; i < n; i++) { + WOEdge *current = oedgeList[i]; + oedgedata *currentoedata = (oedgedata *)current->userdata; + newoedgelist.push_back(currentoedata->_copy); + //oedgeList[i] = currentoedata->_copy; + //oedgeList[i] = ((oedgedata *)(oedgeList[i]->userdata))->_copy; + } + (*f)->setEdgeList(newoedgelist); + } - return 0; + // Free all memory (arghh!) + // Vertex + vend = iBrother.getVertexList().end(); + for (v = iBrother.getVertexList().begin(); v != vend; ++v) { + delete (vertexdata *)((*v)->userdata); + (*v)->userdata = NULL; + } - // set the list of per-vertex normals - face->setNormalList(iNormalsList); - // set the list of per-vertex tex coords - face->setTexCoordsList(iTexCoordsList); + // Edges and OEdges: + eend = iBrother.getEdgeList().end(); + for (e = iBrother.getEdgeList().begin(); e != eend; ++e) { + delete (edgedata *)((*e)->userdata); + (*e)->userdata = NULL; + // OEdge a: + delete (oedgedata *)((*e)->GetaOEdge()->userdata); + (*e)->GetaOEdge()->userdata = NULL; + // OEdge b: + WOEdge *oedgeb = (*e)->GetbOEdge(); + if (oedgeb) { + delete (oedgedata *)(oedgeb->userdata); + oedgeb->userdata = NULL; + } + } - return face; + // Faces + fend = iBrother.GetFaceList().end(); + for (f = iBrother.GetFaceList().begin(); f != fend; ++f) { + delete (facedata *)((*f)->userdata); + (*f)->userdata = NULL; + } } -WFace* WShape::MakeFace(vector& iVertexList, vector& iFaceEdgeMarksList, unsigned iMaterial, WFace *face) +WFace *WShape::MakeFace(vector& iVertexList, vector& iFaceEdgeMarksList, unsigned iMaterial) { + // allocate the new face + WFace *face = instanciateFace(); - int id = _FaceList.size(); - - face->setFrsMaterialIndex(iMaterial); - - // Check whether we have a degenerated face: - - // LET'S HACK IT FOR THE TRIANGLE CASE: - - if(3 == iVertexList.size()) - - { - - if((iVertexList[0] == iVertexList[1]) - - || (iVertexList[0] == iVertexList[2]) - - || (iVertexList[2] == iVertexList[1])) - - { - - cerr << "Warning: degenerated triangle detected, correcting" << endl; - return 0; - - } + WFace *result = MakeFace(iVertexList, iFaceEdgeMarksList, iMaterial, face); + if (!result) + delete face; + return result; +} - } +WFace *WShape::MakeFace(vector& iVertexList, vector& iNormalsList, vector& iTexCoordsList, + vector& iFaceEdgeMarksList, unsigned iMaterial) +{ + // allocate the new face + WFace *face = MakeFace(iVertexList, iFaceEdgeMarksList, iMaterial); - vector::iterator it; + if (!face) + return NULL; - // compute the face normal (v1v2 ^ v1v3) - WVertex *v1, *v2, *v3; - it = iVertexList.begin(); - v1 = *it; - it++; - v2 = *it; - it++; - v3 = *it; + // set the list of per-vertex normals + face->setNormalList(iNormalsList); + // set the list of per-vertex tex coords + face->setTexCoordsList(iTexCoordsList); - Vec3r vector1(v2->GetVertex()-v1->GetVertex()); - Vec3r vector2(v3->GetVertex()-v1->GetVertex()); + return face; +} - Vec3r normal(vector1 ^ vector2); - normal.normalize(); - face->setNormal(normal); +WFace *WShape::MakeFace(vector& iVertexList, vector& iFaceEdgeMarksList, unsigned iMaterial, + WFace *face) +{ + int id = _FaceList.size(); - vector::iterator mit = iFaceEdgeMarksList.begin(); - face->setMark(*mit); - mit++; + face->setFrsMaterialIndex(iMaterial); - // vertex pointers used to build each edge - vector::iterator va, vb; + // Check whether we have a degenerated face: - va = iVertexList.begin(); - vb = va; - for(; va != iVertexList.end(); va = vb) - { - vb++; - // Adds va to the vertex list: - //face->AddVertex(*va); + // LET'S HACK IT FOR THE TRIANGLE CASE: - WOEdge * oedge; - if(*va == iVertexList.back()) - oedge = face->MakeEdge(*va, iVertexList.front()); //for the last (closing) edge - else - oedge = face->MakeEdge(*va, *vb); + if (3 == iVertexList.size()) { + if ((iVertexList[0] == iVertexList[1]) || + (iVertexList[0] == iVertexList[2]) || + (iVertexList[2] == iVertexList[1])) { + cerr << "Warning: degenerated triangle detected, correcting" << endl; + return NULL; + } + } + vector::iterator it; - if(oedge == 0) - return 0; + // compute the face normal (v1v2 ^ v1v3) + WVertex *v1, *v2, *v3; + it = iVertexList.begin(); + v1 = *it; + it++; + v2 = *it; + it++; + v3 = *it; + Vec3r vector1(v2->GetVertex() - v1->GetVertex()); + Vec3r vector2(v3->GetVertex() - v1->GetVertex()); - WEdge *edge = oedge->GetOwner(); - if(1 == edge->GetNumberOfOEdges()) - { - // means that we just created a new edge and that we must add it to the - // shape's edges list - edge->setId(_EdgeList.size()); - AddEdge(edge); - // compute the mean edge value: - _meanEdgeSize += edge->GetaOEdge()->GetVec().norm(); - } + Vec3r normal(vector1 ^ vector2); + normal.normalize(); + face->setNormal(normal); - edge->setMark(*mit); + vector::iterator mit = iFaceEdgeMarksList.begin(); + face->setMark(*mit); mit++; - } - // Add the face to the shape's faces list: - face->setId(id); - AddFace(face); + // vertex pointers used to build each edge + vector::iterator va, vb; + + va = iVertexList.begin(); + vb = va; + for (; va != iVertexList.end(); va = vb) { + ++vb; + // Adds va to the vertex list: + //face->AddVertex(*va); + + WOEdge *oedge; + if (*va == iVertexList.back()) + oedge = face->MakeEdge(*va, iVertexList.front()); //for the last (closing) edge + else + oedge = face->MakeEdge(*va, *vb); + + if (!oedge) + return NULL; + + WEdge *edge = oedge->GetOwner(); + if (1 == edge->GetNumberOfOEdges()) { + // means that we just created a new edge and that we must add it to the shape's edges list + edge->setId(_EdgeList.size()); + AddEdge(edge); + // compute the mean edge value: + _meanEdgeSize += edge->GetaOEdge()->GetVec().norm(); + } + + edge->setMark(*mit); + ++mit; + } + + // Add the face to the shape's faces list: + face->setId(id); + AddFace(face); - return face; -} + return face; +} \ No newline at end of file diff --git a/source/blender/freestyle/intern/winged_edge/WEdge.h b/source/blender/freestyle/intern/winged_edge/WEdge.h index dc920448add..be9181329d6 100644 --- a/source/blender/freestyle/intern/winged_edge/WEdge.h +++ b/source/blender/freestyle/intern/winged_edge/WEdge.h @@ -1,991 +1,1344 @@ -// -// Filename : WEdge.h -// Author(s) : Stephane Grabli -// Purpose : Classes to define a Winged Edge data structure. -// Date of creation : 18/02/2002 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef WEDGE_H -# define WEDGE_H - -# include -# include -# include -# include "../system/FreestyleConfig.h" -# include "../geometry/Geom.h" -# include "../scene_graph/FrsMaterial.h" +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_W_EDGE_H__ +#define __FREESTYLE_W_EDGE_H__ + +/** \file blender/freestyle/intern/winged_edge/WEdge.h + * \ingroup freestyle + * \brief Classes to define a Winged Edge data structure. + * \author Stephane Grabli + * \date 18/02/2002 + */ + +#include +#include +#include + +#include "../geometry/Geom.h" + +#include "../scene_graph/FrsMaterial.h" + +#include "../system/FreestyleConfig.h" using namespace std; using namespace Geometry; - /**********************************/ - /* */ - /* */ - /* WVertex */ - /* */ - /* */ - /**********************************/ +/********************************** + * * + * * + * WVertex * + * * + * * + **********************************/ class WOEdge; class WEdge; class WShape; class WFace; + class LIB_WINGED_EDGE_EXPORT WVertex { protected: - int _Id; // an identificator - Vec3r _Vertex; - vector _EdgeList; - WShape * _Shape; // the shape to which the vertex belongs - bool _Smooth; // flag to indicate whether the Vertex belongs to a smooth edge or not - int _Border; // 1 -> border, 0 -> no border, -1 -> not set - -public: - void * userdata; // designed to store specific user data - inline WVertex(const Vec3r &v) {_Id = 0; _Vertex = v; userdata = NULL; _Shape = NULL;_Smooth=true;_Border=-1;} - /*! Copy constructor */ - WVertex(WVertex& iBrother); - virtual WVertex * duplicate(); - virtual ~WVertex() {} - - /*! accessors */ - inline Vec3r& GetVertex() {return _Vertex;} - inline vector& GetEdges() {return _EdgeList;} - inline int GetId() {return _Id;} - inline WShape * shape() const {return _Shape;} - inline bool isSmooth() const {return _Smooth;} - bool isBoundary(); - - /*! modifiers */ - inline void setVertex(const Vec3r& v) {_Vertex = v;} - inline void setEdges(const vector& iEdgeList) {_EdgeList = iEdgeList;} - inline void setId(int id) {_Id = id;} - inline void setShape(WShape *iShape) {_Shape = iShape;} - inline void setSmooth(bool b) {_Smooth = b;} - inline void setBorder(bool b) {if(b) _Border= 1; else _Border = 0;} - - /*! Adds an edge to the edges list */ - void AddEdge(WEdge *iEdge) ; - - virtual void ResetUserData() {userdata = 0;} - - + int _Id; // an identificator + Vec3r _Vertex; + vector _EdgeList; + WShape *_Shape; // the shape to which the vertex belongs + bool _Smooth; // flag to indicate whether the Vertex belongs to a smooth edge or not + int _Border; // 1 -> border, 0 -> no border, -1 -> not set public: + void *userdata; // designed to store specific user data + inline WVertex(const Vec3r &v) + { + _Id = 0; + _Vertex = v; + userdata = NULL; + _Shape = NULL; + _Smooth = true; + _Border = -1; + } + + /*! Copy constructor */ + WVertex(WVertex& iBrother); + virtual WVertex *duplicate(); + virtual ~WVertex() {} + + /*! accessors */ + inline Vec3r& GetVertex() + { + return _Vertex; + } + + inline vector& GetEdges() + { + return _EdgeList; + } + + inline int GetId() + { + return _Id; + } + + inline WShape *shape() const + { + return _Shape; + } + + inline bool isSmooth() const + { + return _Smooth; + } + + bool isBoundary(); + + /*! modifiers */ + inline void setVertex(const Vec3r& v) + { + _Vertex = v; + } + + inline void setEdges(const vector& iEdgeList) + { + _EdgeList = iEdgeList; + } + + inline void setId(int id) + { + _Id = id; + } + + inline void setShape(WShape *iShape) + { + _Shape = iShape; + } + + inline void setSmooth(bool b) + { + _Smooth = b; + } + + inline void setBorder(bool b) + { + if (b) + _Border = 1; + else + _Border = 0; + } + + /*! Adds an edge to the edges list */ + void AddEdge(WEdge *iEdge); + + virtual void ResetUserData() + { + userdata = NULL; + } - - - /*! Iterator to iterate over a vertex incoming edges in the CCW order*/ -# if defined(__GNUC__) && (__GNUC__ < 3) - class incoming_edge_iterator : public input_iterator -# else - class LIB_WINGED_EDGE_EXPORT incoming_edge_iterator : public iterator -# endif - { - private: - WVertex *_vertex; - // - WOEdge *_begin; - WOEdge *_current; - - public: -# if defined(__GNUC__) && (__GNUC__ < 3) - inline incoming_edge_iterator() : input_iterator() {} -# else - inline incoming_edge_iterator() : iterator() {} -# endif - virtual ~incoming_edge_iterator() {}; //soc - - protected: - friend class WVertex; - inline incoming_edge_iterator( - WVertex *iVertex, - WOEdge * iBegin, - WOEdge * iCurrent) -# if defined(__GNUC__) && (__GNUC__ < 3) - : input_iterator() -# else - : iterator() -# endif - { - _vertex = iVertex; - _begin = iBegin; - _current = iCurrent; - } - - public: - inline incoming_edge_iterator(const incoming_edge_iterator& iBrother) -# if defined(__GNUC__) && (__GNUC__ < 3) - : input_iterator(iBrother) -# else - : iterator(iBrother) -# endif - { - _vertex = iBrother._vertex; - _begin = iBrother._begin; - _current = iBrother._current; - } - - public: - // operators - virtual incoming_edge_iterator& operator++() // operator corresponding to ++i - { - increment(); - return *this; - } - virtual incoming_edge_iterator operator++(int) // operator corresponding to i++ - { - incoming_edge_iterator tmp = *this; - increment(); - return tmp; - } - - // comparibility - virtual bool operator!=(const incoming_edge_iterator& b) const - { - return ((_current) != (b._current)); - } - - virtual bool operator==(const incoming_edge_iterator& b) const - { - return ((_current)== (b._current)); - } - - // dereferencing - virtual WOEdge* operator*(); - //virtual WOEdge** operator->(); - protected: - virtual void increment(); - }; - - - /*! Iterator to iterate over a vertex faces in the CCW order */ -# if defined(__GNUC__) && (__GNUC__ < 3) - class face_iterator : public input_iterator -# else - class LIB_WINGED_EDGE_EXPORT face_iterator : public iterator -# endif - { - private: - incoming_edge_iterator _edge_it; - - public: -# if defined(__GNUC__) && (__GNUC__ < 3) - inline face_iterator() : input_iterator() {} -# else - inline face_iterator() : iterator() {} -# endif - virtual ~face_iterator() {}; //soc - - protected: - friend class WVertex; - inline face_iterator( - incoming_edge_iterator it) -# if defined(__GNUC__) && (__GNUC__ < 3) - : input_iterator() -# else - : iterator() -# endif - { - _edge_it = it; - } - - public: - inline face_iterator(const face_iterator& iBrother) -# if defined(__GNUC__) && (__GNUC__ < 3) - : input_iterator(iBrother) -# else - : iterator(iBrother) -# endif - { - _edge_it = iBrother._edge_it; - } - - public: - // operators - virtual face_iterator& operator++() // operator corresponding to ++i - { - increment(); - return *this; - } - virtual face_iterator operator++(int) // operator corresponding to i++ - { - face_iterator tmp = *this; - increment(); - return tmp; - } - - // comparibility - virtual bool operator!=(const face_iterator& b) const - { - return ((_edge_it) != (b._edge_it)); - } - - virtual bool operator==(const face_iterator& b) const - { - return ((_edge_it)== (b._edge_it)); - } - - // dereferencing - virtual WFace* operator*(); - //virtual WOEdge** operator->(); - protected: - inline void increment(){ - ++_edge_it; - } - }; +public: + /*! Iterator to iterate over a vertex incoming edges in the CCW order*/ +#if defined(__GNUC__) && (__GNUC__ < 3) + class incoming_edge_iterator : public input_iterator +#else + class LIB_WINGED_EDGE_EXPORT incoming_edge_iterator + : public iterator +#endif + { + private: + WVertex *_vertex; + // + WOEdge *_begin; + WOEdge *_current; + + public: +#if defined(__GNUC__) && (__GNUC__ < 3) + inline incoming_edge_iterator() : input_iterator() {} +#else + inline incoming_edge_iterator() : iterator() {} +#endif + virtual ~incoming_edge_iterator() {}; //soc + + protected: + friend class WVertex; + inline incoming_edge_iterator(WVertex *iVertex, WOEdge *iBegin, WOEdge *iCurrent) +#if defined(__GNUC__) && (__GNUC__ < 3) + : input_iterator() +#else + : iterator() +#endif + { + _vertex = iVertex; + _begin = iBegin; + _current = iCurrent; + } + + public: + inline incoming_edge_iterator(const incoming_edge_iterator& iBrother) +#if defined(__GNUC__) && (__GNUC__ < 3) + : input_iterator(iBrother) +#else + : iterator(iBrother) +#endif + { + _vertex = iBrother._vertex; + _begin = iBrother._begin; + _current = iBrother._current; + } + + public: + // operators + // operator corresponding to ++i + virtual incoming_edge_iterator& operator++() + { + increment(); + return *this; + } + + // operator corresponding to i++ + virtual incoming_edge_iterator operator++(int) + { + incoming_edge_iterator tmp = *this; + increment(); + return tmp; + } + + // comparibility + virtual bool operator!=(const incoming_edge_iterator& b) const + { + return ((_current) != (b._current)); + } + + virtual bool operator==(const incoming_edge_iterator& b) const + { + return ((_current)== (b._current)); + } + + // dereferencing + virtual WOEdge *operator*(); + //virtual WOEdge **operator->(); + protected: + virtual void increment(); + }; + + /*! Iterator to iterate over a vertex faces in the CCW order */ +#if defined(__GNUC__) && (__GNUC__ < 3) + class face_iterator : public input_iterator +#else + class LIB_WINGED_EDGE_EXPORT face_iterator : public iterator +#endif + { + private: + incoming_edge_iterator _edge_it; + + public: +#if defined(__GNUC__) && (__GNUC__ < 3) + inline face_iterator() : input_iterator() {} +#else + inline face_iterator() : iterator() {} +#endif + virtual ~face_iterator() {}; //soc + + protected: + friend class WVertex; + inline face_iterator(incoming_edge_iterator it) +#if defined(__GNUC__) && (__GNUC__ < 3) + : input_iterator() +#else + : iterator() +#endif + { + _edge_it = it; + } + + public: + inline face_iterator(const face_iterator& iBrother) +#if defined(__GNUC__) && (__GNUC__ < 3) + : input_iterator(iBrother) +#else + : iterator(iBrother) +#endif + { + _edge_it = iBrother._edge_it; + } + + public: + // operators + // operator corresponding to ++i + virtual face_iterator& operator++() + { + increment(); + return *this; + } + + // operator corresponding to i++ + virtual face_iterator operator++(int) + { + face_iterator tmp = *this; + increment(); + return tmp; + } + + // comparibility + virtual bool operator!=(const face_iterator& b) const + { + return ((_edge_it) != (b._edge_it)); + } + + virtual bool operator==(const face_iterator& b) const + { + return ((_edge_it)== (b._edge_it)); + } + + // dereferencing + virtual WFace *operator*(); + //virtual WOEdge **operator->(); + + protected: + inline void increment() + { + ++_edge_it; + } + }; public: - /*! iterators access */ - virtual incoming_edge_iterator incoming_edges_begin(); - virtual incoming_edge_iterator incoming_edges_end() ; - - virtual face_iterator faces_begin() { - return face_iterator(incoming_edges_begin()); - } - virtual face_iterator faces_end() { - return face_iterator(incoming_edges_end()); - } + /*! iterators access */ + virtual incoming_edge_iterator incoming_edges_begin(); + virtual incoming_edge_iterator incoming_edges_end(); + + virtual face_iterator faces_begin() + { + return face_iterator(incoming_edges_begin()); + } + + virtual face_iterator faces_end() + { + return face_iterator(incoming_edges_end()); + } }; - /**********************************/ - /* */ - /* */ - /* WOEdge */ - /* */ - /* */ - /**********************************/ +/********************************** + * * + * * + * WOEdge * + * * + * * + **********************************/ + class WFace; class WEdge; class LIB_WINGED_EDGE_EXPORT WOEdge { protected: - // WOEdge *_paCWEdge; // edge reached when traveling clockwise on aFace from the edge - // WOEdge *_pbCWEdge; // edge reached when traveling clockwise on bFace from the edge - // WOEdge *_paCCWEdge; // edge reached when traveling counterclockwise on aFace from the edge - // WOEdge *_pbCCWEdge; // edge reached when traveling counterclockwise on bFace from the edge - WVertex *_paVertex; // starting vertex - WVertex *_pbVertex; // ending vertex - WFace *_paFace; // when following the edge, face on the right - WFace *_pbFace; // when following the edge, face on the left - WEdge *_pOwner; // Edge - - Vec3r _vec; - real _angle; +#if 0 + WOEdge *_paCWEdge; // edge reached when traveling clockwise on aFace from the edge + WOEdge *_pbCWEdge; // edge reached when traveling clockwise on bFace from the edge + WOEdge *_paCCWEdge; // edge reached when traveling counterclockwise on aFace from the edge + WOEdge *_pbCCWEdge; // edge reached when traveling counterclockwise on bFace from the edge +#endif + WVertex *_paVertex; // starting vertex + WVertex *_pbVertex; // ending vertex + WFace *_paFace; // when following the edge, face on the right + WFace *_pbFace; // when following the edge, face on the left + WEdge *_pOwner; // Edge + + Vec3r _vec; + real _angle; public: - - void *userdata; - inline WOEdge() - { - // _paCWEdge = NULL; - // _pbCWEdge = NULL; - // _paCCWEdge = NULL; - // _pbCCWEdge = NULL; - _paVertex = NULL; - _pbVertex = NULL; - _paFace = NULL; - _pbFace = NULL; - _pOwner = NULL; - userdata = NULL; - } - virtual ~WOEdge() {}; //soc - - /*! copy constructor */ - WOEdge(WOEdge& iBrother); - virtual WOEdge * duplicate(); - - /*! accessors */ - // inline WOEdge *GetaCWEdge() {return _paCWEdge;} - // inline WOEdge *GetbCWEdge() {return _pbCWEdge;} - // inline WOEdge *GetaCCWEdge() {return _paCCWEdge;} - // inline WOEdge *GetbCCWEdge() {return _pbCCWEdge;} - inline WVertex *GetaVertex() {return _paVertex;} - inline WVertex *GetbVertex() {return _pbVertex;} - inline WFace *GetaFace() {return _paFace;} - inline WFace *GetbFace() {return _pbFace;} - inline WEdge *GetOwner() {return _pOwner;} - - inline const Vec3r& GetVec() { return _vec; } - inline const real GetAngle() { return _angle; } - - - /*! modifiers */ - // inline void SetaCWEdge(WOEdge *pe) {_paCWEdge = pe;} - // inline void SetbCWEdge(WOEdge *pe) {_pbCWEdge = pe;} - // inline void SetaCCWEdge(WOEdge *pe) {_paCCWEdge = pe;} - // inline void SetbCCCWEdge(WOEdge *pe) {_pbCCWEdge = pe;} - inline void setVecAndAngle(); - inline void setaVertex(WVertex *pv) {_paVertex = pv; setVecAndAngle(); } - inline void setbVertex(WVertex *pv) {_pbVertex = pv; setVecAndAngle(); } - inline void setaFace(WFace *pf) {_paFace = pf; setVecAndAngle(); } - inline void setbFace(WFace *pf) {_pbFace = pf; setVecAndAngle(); } - inline void setOwner(WEdge *pe) {_pOwner = pe;} - - /*! Retrieves the list of edges in CW order */ - inline void RetrieveCWOrderedEdges(vector& oEdges); - /*! returns the vector between the two vertices */ - Vec3r getVec3r (); - WOEdge * twin (); - WOEdge * getPrevOnFace(); - virtual void ResetUserData() {userdata = 0;} + void *userdata; + + inline WOEdge() + { +#if 0 + _paCWEdge = NULL; + _pbCWEdge = NULL; + _paCCWEdge = NULL; + _pbCCWEdge = NULL; +#endif + _paVertex = NULL; + _pbVertex = NULL; + _paFace = NULL; + _pbFace = NULL; + _pOwner = NULL; + userdata = NULL; + } + + virtual ~WOEdge() {}; //soc + + /*! copy constructor */ + WOEdge(WOEdge& iBrother); + virtual WOEdge *duplicate(); + + /*! accessors */ +#if 0 + inline WOEdge *GetaCWEdge() + { + return _paCWEdge; + } + + inline WOEdge *GetbCWEdge() + { + return _pbCWEdge; + } + + inline WOEdge *GetaCCWEdge() + { + return _paCCWEdge; + } + + inline WOEdge *GetbCCWEdge() + { + return _pbCCWEdge; + } +#endif + + inline WVertex *GetaVertex() + { + return _paVertex; + } + + inline WVertex *GetbVertex() + { + return _pbVertex; + } + + inline WFace *GetaFace() + { + return _paFace; + } + + inline WFace *GetbFace() + { + return _pbFace; + } + + inline WEdge *GetOwner() + { + return _pOwner; + } + + inline const Vec3r& GetVec() + { + return _vec; + } + + inline const real GetAngle() + { + return _angle; + } + + + /*! modifiers */ +#if 0 + inline void SetaCWEdge(WOEdge *pe) + { + _paCWEdge = pe; + } + + inline void SetbCWEdge(WOEdge *pe) + { + _pbCWEdge = pe; + } + + inline void SetaCCWEdge(WOEdge *pe) + { + _paCCWEdge = pe; + } + + inline void SetbCCCWEdge(WOEdge *pe) + { + _pbCCWEdge = pe; + } +#endif + + inline void setVecAndAngle(); + + inline void setaVertex(WVertex *pv) + { + _paVertex = pv; + setVecAndAngle(); + } + + inline void setbVertex(WVertex *pv) + { + _pbVertex = pv; + setVecAndAngle(); + } + + inline void setaFace(WFace *pf) + { + _paFace = pf; + setVecAndAngle(); + } + + inline void setbFace(WFace *pf) + { + _pbFace = pf; + setVecAndAngle(); + } + + inline void setOwner(WEdge *pe) + { + _pOwner = pe; + } + + /*! Retrieves the list of edges in CW order */ + inline void RetrieveCWOrderedEdges(vector& oEdges); + + /*! returns the vector between the two vertices */ + Vec3r getVec3r (); + WOEdge *twin (); + WOEdge *getPrevOnFace(); + + virtual void ResetUserData() + { + userdata = NULL; + } }; - /**********************************/ - /* */ - /* */ - /* WEdge */ - /* */ - /* */ - /**********************************/ +/********************************** + * * + * * + * WEdge * + * * + * * + **********************************/ class LIB_WINGED_EDGE_EXPORT WEdge { protected: - WOEdge *_paOEdge; // first oriented edge - WOEdge *_pbOEdge; // second oriented edge - int _nOEdges; // number of oriented edges associated with this edge. (1 means border edge) - bool _Mark; // user-specified edge mark for feature edge detection - int _Id; // Identifier for the edge - + WOEdge *_paOEdge; // first oriented edge + WOEdge *_pbOEdge; // second oriented edge + int _nOEdges; // number of oriented edges associated with this edge. (1 means border edge) + bool _Mark; // user-specified edge mark for feature edge detection + int _Id; // Identifier for the edge + public: - void * userdata; // designed to store specific user data - inline WEdge() - { - _paOEdge = NULL; - _pbOEdge = NULL; - _nOEdges = 0; - userdata = NULL; - } - - inline WEdge(WOEdge *iOEdge) - { - _paOEdge = iOEdge; - _pbOEdge = NULL; - _nOEdges = 1; - userdata = NULL; - } - - inline WEdge(WOEdge *iaOEdge, WOEdge *ibOEdge) - { - _paOEdge = iaOEdge; - _pbOEdge = ibOEdge; - _nOEdges = 2; - userdata = NULL; - } - - /*! Copy constructor */ - WEdge(WEdge& iBrother); - virtual WEdge * duplicate(); - - virtual ~WEdge() - { - if(NULL != _paOEdge) - { - delete _paOEdge; - _paOEdge = NULL; - } - - if(NULL != _pbOEdge) - { - delete _pbOEdge; - _pbOEdge = NULL; - } - } - - /*! checks whether two WEdge have a common vertex. - * Returns a pointer on the common vertex if it exists, - * NULL otherwise. - */ - static inline WVertex* CommonVertex(WEdge *iEdge1, WEdge* iEdge2) - { - if((NULL == iEdge1) || (NULL == iEdge2)) - return NULL; - - WVertex *wv1 = iEdge1->GetaOEdge()->GetaVertex(); - WVertex *wv2 = iEdge1->GetaOEdge()->GetbVertex(); - WVertex *wv3 = iEdge2->GetaOEdge()->GetaVertex(); - WVertex *wv4 = iEdge2->GetaOEdge()->GetbVertex(); - - if((wv1 == wv3) || (wv1 == wv4)) - { - return wv1; - } - else if((wv2 == wv3) || (wv2 == wv4)) - { - return wv2; - } - - return NULL; - } - /*! accessors */ - inline WOEdge * GetaOEdge() {return _paOEdge;} - inline WOEdge * GetbOEdge() {return _pbOEdge;} - inline int GetNumberOfOEdges() {return _nOEdges;} - inline bool GetMark() {return _Mark;} - inline int GetId() {return _Id;} - inline WVertex * GetaVertex() {return _paOEdge->GetaVertex();} - inline WVertex * GetbVertex() {return _paOEdge->GetbVertex();} - inline WFace * GetaFace() {return _paOEdge->GetaFace();} - inline WFace * GetbFace() {return _paOEdge->GetbFace();} - inline WOEdge* GetOtherOEdge(WOEdge* iOEdge) - { - if(iOEdge == _paOEdge) - return _pbOEdge; - else - return _paOEdge; - } - - /*! modifiers */ - inline void setaOEdge(WOEdge *iEdge) {_paOEdge = iEdge;} - inline void setbOEdge(WOEdge *iEdge) {_pbOEdge = iEdge;} - inline void AddOEdge(WOEdge *iEdge) - { - if(NULL == _paOEdge) - { - _paOEdge = iEdge; - _nOEdges++; - return; - } - if(NULL == _pbOEdge) - { - _pbOEdge = iEdge; - _nOEdges++; - return; - } - } - inline void setNumberOfOEdges(int n) {_nOEdges = n;} - inline void setMark(bool mark) {_Mark = mark;} - inline void setId(int id) {_Id = id;} - virtual void ResetUserData() {userdata = 0;} + void *userdata; // designed to store specific user data + + inline WEdge() + { + _paOEdge = NULL; + _pbOEdge = NULL; + _nOEdges = 0; + userdata = NULL; + } + + inline WEdge(WOEdge *iOEdge) + { + _paOEdge = iOEdge; + _pbOEdge = NULL; + _nOEdges = 1; + userdata = NULL; + } + + inline WEdge(WOEdge *iaOEdge, WOEdge *ibOEdge) + { + _paOEdge = iaOEdge; + _pbOEdge = ibOEdge; + _nOEdges = 2; + userdata = NULL; + } + + /*! Copy constructor */ + WEdge(WEdge& iBrother); + virtual WEdge *duplicate(); + + virtual ~WEdge() + { + if (_paOEdge) { + delete _paOEdge; + _paOEdge = NULL; + } + + if (_pbOEdge) { + delete _pbOEdge; + _pbOEdge = NULL; + } + } + + /*! checks whether two WEdge have a common vertex. + * Returns a pointer on the common vertex if it exists, NULL otherwise. + */ + static inline WVertex *CommonVertex(WEdge *iEdge1, WEdge *iEdge2) + { + if (!iEdge1 || !iEdge2) + return NULL; + + WVertex *wv1 = iEdge1->GetaOEdge()->GetaVertex(); + WVertex *wv2 = iEdge1->GetaOEdge()->GetbVertex(); + WVertex *wv3 = iEdge2->GetaOEdge()->GetaVertex(); + WVertex *wv4 = iEdge2->GetaOEdge()->GetbVertex(); + + if ((wv1 == wv3) || (wv1 == wv4)) { + return wv1; + } + else if ((wv2 == wv3) || (wv2 == wv4)) { + return wv2; + } + return NULL; + } + + /*! accessors */ + inline WOEdge *GetaOEdge() + { + return _paOEdge; + } + + inline WOEdge *GetbOEdge() + { + return _pbOEdge; + } + + inline int GetNumberOfOEdges() + { + return _nOEdges; + } + + inline bool GetMark() + { + return _Mark; + } + + inline int GetId() + { + return _Id; + } + + inline WVertex *GetaVertex() + { + return _paOEdge->GetaVertex(); + } + + inline WVertex *GetbVertex() + { + return _paOEdge->GetbVertex(); + } + + inline WFace *GetaFace() + { + return _paOEdge->GetaFace(); + } + + inline WFace *GetbFace() + { + return _paOEdge->GetbFace(); + } + + inline WOEdge *GetOtherOEdge(WOEdge *iOEdge) { + if (iOEdge == _paOEdge) + return _pbOEdge; + else + return _paOEdge; + } + + /*! modifiers */ + inline void setaOEdge(WOEdge *iEdge) + { + _paOEdge = iEdge; + } + + inline void setbOEdge(WOEdge *iEdge) + { + _pbOEdge = iEdge; + } + + inline void AddOEdge(WOEdge *iEdge) + { + if (!_paOEdge) { + _paOEdge = iEdge; + _nOEdges++; + return; + } + if (!_pbOEdge) { + _pbOEdge = iEdge; + _nOEdges++; + return; + } + } + + inline void setNumberOfOEdges(int n) + { + _nOEdges = n; + } + + inline void setMark(bool mark) + { + _Mark = mark; + } + + inline void setId(int id) + { + _Id = id; + } + + virtual void ResetUserData() + { + userdata = NULL; + } }; - /**********************************/ - /* */ - /* */ - /* WFace */ - /* */ - /* */ - /**********************************/ + +/********************************** + * * + * * + * WFace * + * * + * * + **********************************/ class LIB_WINGED_EDGE_EXPORT WFace { protected: - vector _OEdgeList; // list of oriented edges of bording the face - Vec3r _Normal; // normal to the face - vector _VerticesNormals; // in case there is a normal per vertex. - // The normal number i corresponds to the - // aVertex of the oedge number i, for that face - vector _VerticesTexCoords; + vector _OEdgeList; // list of oriented edges of bording the face + Vec3r _Normal; // normal to the face + // in case there is a normal per vertex. + // The normal number i corresponds to the aVertex of the oedge number i, for that face + vector _VerticesNormals; + vector _VerticesTexCoords; - int _Id; - unsigned _FrsMaterialIndex; - bool _Mark; // Freestyle face mark (if true, feature edges on this face are ignored) + int _Id; + unsigned _FrsMaterialIndex; + bool _Mark; // Freestyle face mark (if true, feature edges on this face are ignored) public: - void *userdata; - inline WFace() {userdata = NULL;_FrsMaterialIndex = 0;} - /*! copy constructor */ - WFace(WFace& iBrother); - virtual WFace * duplicate(); - virtual ~WFace() {} - - /*! accessors */ - inline const vector& getEdgeList() {return _OEdgeList;} - inline WOEdge * GetOEdge(int i) {return _OEdgeList[i];} - inline Vec3r& GetNormal() {return _Normal;} - inline int GetId() {return _Id;} - inline unsigned frs_materialIndex() const {return _FrsMaterialIndex;} - inline bool GetMark() const {return _Mark;} - const FrsMaterial& frs_material() ; - - /*! The vertex of index i corresponds to the a vertex - * of the edge of index i - */ - inline WVertex* GetVertex(unsigned int index) - { - // if(index >= _OEdgeList.size()) - // return NULL; - return _OEdgeList[index]->GetaVertex(); - } - /*! returns the index at which iVertex is stored in the - * array. - * returns -1 if iVertex doesn't belong to the face. - */ - inline int GetIndex(WVertex *iVertex){ - int index = 0; - for(vector::iterator woe=_OEdgeList.begin(), woend=_OEdgeList.end(); - woe!=woend; - woe++){ - if((*woe)->GetaVertex() == iVertex) - return index; - ++index; - } - return -1; - } - inline void RetrieveVertexList(vector& oVertices) - { - for(vector::iterator woe=_OEdgeList.begin(), woend=_OEdgeList.end(); - woe!=woend; - woe++) - { - oVertices.push_back((*woe)->GetaVertex()); - } - } - inline void RetrieveBorderFaces(vector& oWFaces) - { - for(vector::iterator woe=_OEdgeList.begin(), woend=_OEdgeList.end(); - woe!=woend; - woe++) - { - WFace *af; - if(NULL != (af = (*woe)->GetaFace())) - oWFaces.push_back(af); - } - } - inline WFace * GetBordingFace(int index) - { - // if(index >= _OEdgeList.size()) - // return 0; - return _OEdgeList[index]->GetaFace(); - } - inline WFace * GetBordingFace(WOEdge *iOEdge) - { - return iOEdge->GetaFace(); - } - inline vector& GetPerVertexNormals() - { - return _VerticesNormals; - } - inline vector& GetPerVertexTexCoords() - { - return _VerticesTexCoords; - } - /*! Returns the normal of the vertex of index index */ - inline Vec3r& GetVertexNormal(int index) - { - return _VerticesNormals[index]; - } - /*! Returns the tex coords of the vertex of index index */ - inline Vec2r& GetVertexTexCoords(int index) - { - return _VerticesTexCoords[index]; - } - /*! Returns the normal of the vertex iVertex for that face */ - inline Vec3r& GetVertexNormal(WVertex *iVertex) - { - int i = 0; - int index = 0; - for(vector::const_iterator woe=_OEdgeList.begin(), woend=_OEdgeList.end(); - woe!=woend; - woe++) - { - if((*woe)->GetaVertex() == iVertex) - { - index = i; - break; - } - ++i; - } - - return _VerticesNormals[index]; - } - inline WOEdge* GetNextOEdge(WOEdge* iOEdge) - { - bool found = false; - vector::iterator woe,woend, woefirst; - woefirst = _OEdgeList.begin(); - for(woe=woefirst,woend=_OEdgeList.end(); - woe!=woend; - woe++) - { - if(true == found) - return (*woe); - - if((*woe) == iOEdge) - { - found = true; - } - } - - // We left the loop. That means that the first - // OEdge was the good one: - if(found) - return (*woefirst); - - return NULL; - } - WOEdge* GetPrevOEdge(WOEdge* iOEdge); - - inline int numberOfEdges() const { return _OEdgeList.size();} - inline int numberOfVertices() const { return _OEdgeList.size();} - /*! Returns true if the face has one ot its edge which is a border - * edge - */ - inline bool isBorder() const - { - for(vector::const_iterator woe=_OEdgeList.begin(), woeend=_OEdgeList.end(); - woe!=woeend; - ++woe) - { - if((*woe)->GetOwner()->GetbOEdge() == 0) - return true; - } - return false; - } - /*! modifiers */ - inline void setEdgeList(const vector& iEdgeList) {_OEdgeList = iEdgeList;} - inline void setNormal(const Vec3r& iNormal) {_Normal = iNormal;} - inline void setNormalList(const vector& iNormalsList) {_VerticesNormals = iNormalsList;} - inline void setTexCoordsList(const vector& iTexCoordsList) {_VerticesTexCoords = iTexCoordsList;} - inline void setId(int id) {_Id = id;} - inline void setFrsMaterialIndex(unsigned iMaterialIndex) {_FrsMaterialIndex = iMaterialIndex;} - inline void setMark(bool iMark) {_Mark = iMark;} - - /*! designed to build a specialized WEdge - * for use in MakeEdge - */ - virtual WEdge * instanciateEdge() const {return new WEdge;} - - /*! Builds an oriented edge - * Returns the built edge. - * v1, v2 - * Vertices at the edge's extremities - * The edge is oriented from v1 to v2. - */ - virtual WOEdge * MakeEdge(WVertex *v1, WVertex *v2); - - /*! Adds an edge to the edges list */ - inline void AddEdge(WOEdge *iEdge) {_OEdgeList.push_back(iEdge);} - - /*! For triangles, returns the edge opposite to the vertex in e. - returns flase if the face is not a triangle or if the vertex is not found*/ - bool getOppositeEdge (const WVertex *v, WOEdge* &e); - - /*! compute the area of the face */ - real getArea (); - - WShape * getShape() ; - virtual void ResetUserData() {userdata = 0;} + void *userdata; + inline WFace() + { + userdata = NULL; + _FrsMaterialIndex = 0; + } + + /*! copy constructor */ + WFace(WFace& iBrother); + virtual WFace *duplicate(); + virtual ~WFace() {} + + /*! accessors */ + inline const vector& getEdgeList() + { + return _OEdgeList; + } + + inline WOEdge *GetOEdge(int i) + { + return _OEdgeList[i]; + } + + inline Vec3r& GetNormal() + { + return _Normal; + } + + inline int GetId() + { + return _Id; + } + + inline unsigned frs_materialIndex() const + { + return _FrsMaterialIndex; + } + + inline bool GetMark() const + { + return _Mark; + } + + const FrsMaterial& frs_material(); + + /*! The vertex of index i corresponds to the a vertex of the edge of index i */ + inline WVertex *GetVertex(unsigned int index) + { +#if 0 + if (index >= _OEdgeList.size()) + return NULL; +#endif + return _OEdgeList[index]->GetaVertex(); + } + + /*! returns the index at which iVertex is stored in the array. + * returns -1 if iVertex doesn't belong to the face. + */ + inline int GetIndex(WVertex *iVertex) + { + int index = 0; + for (vector::iterator woe = _OEdgeList.begin(), woend = _OEdgeList.end(); woe != woend; woe++) { + if ((*woe)->GetaVertex() == iVertex) + return index; + ++index; + } + return -1; + } + + inline void RetrieveVertexList(vector& oVertices) + { + for (vector::iterator woe = _OEdgeList.begin(), woend = _OEdgeList.end(); woe != woend; woe++) { + oVertices.push_back((*woe)->GetaVertex()); + } + } + + inline void RetrieveBorderFaces(vector& oWFaces) + { + for (vector::iterator woe = _OEdgeList.begin(), woend = _OEdgeList.end(); woe != woend; woe++) { + WFace *af; + if ((af = (*woe)->GetaFace())) + oWFaces.push_back(af); + } + } + + inline WFace *GetBordingFace(int index) + { +#if 0 + if (index >= _OEdgeList.size()) + return NULL; +#endif + return _OEdgeList[index]->GetaFace(); + } + + inline WFace *GetBordingFace(WOEdge *iOEdge) + { + return iOEdge->GetaFace(); + } + + inline vector& GetPerVertexNormals() + { + return _VerticesNormals; + } + + inline vector& GetPerVertexTexCoords() + { + return _VerticesTexCoords; + } + + /*! Returns the normal of the vertex of index index */ + inline Vec3r& GetVertexNormal(int index) + { + return _VerticesNormals[index]; + } + + /*! Returns the tex coords of the vertex of index index */ + inline Vec2r& GetVertexTexCoords(int index) + { + return _VerticesTexCoords[index]; + } + + /*! Returns the normal of the vertex iVertex for that face */ + inline Vec3r& GetVertexNormal(WVertex *iVertex) + { + int i = 0; + int index = 0; + for (vector::const_iterator woe = _OEdgeList.begin(), woend = _OEdgeList.end(); woe != woend; woe++) { + if ((*woe)->GetaVertex() == iVertex) { + index = i; + break; + } + ++i; + } + + return _VerticesNormals[index]; + } + + inline WOEdge *GetNextOEdge(WOEdge *iOEdge) + { + bool found = false; + vector::iterator woe, woend, woefirst; + woefirst = _OEdgeList.begin(); + for (woe = woefirst, woend = _OEdgeList.end(); woe != woend; ++woe) { + if (found) + return (*woe); + + if ((*woe) == iOEdge) { + found = true; + } + } + + // We left the loop. That means that the first OEdge was the good one: + if (found) + return (*woefirst); + + return NULL; + } + + WOEdge *GetPrevOEdge(WOEdge *iOEdge); + + inline int numberOfEdges() const + { + return _OEdgeList.size(); + } + + inline int numberOfVertices() const + { + return _OEdgeList.size(); + } + + /*! Returns true if the face has one ot its edge which is a border edge */ + inline bool isBorder() const + { + for (vector::const_iterator woe = _OEdgeList.begin(), woeend = _OEdgeList.end(); + woe != woeend; + ++woe) + { + if ((*woe)->GetOwner()->GetbOEdge() == 0) + return true; + } + return false; + } + + /*! modifiers */ + inline void setEdgeList(const vector& iEdgeList) + { + _OEdgeList = iEdgeList; + } + + inline void setNormal(const Vec3r& iNormal) + { + _Normal = iNormal; + } + + inline void setNormalList(const vector& iNormalsList) + { + _VerticesNormals = iNormalsList; + } + + inline void setTexCoordsList(const vector& iTexCoordsList) + { + _VerticesTexCoords = iTexCoordsList; + } + + inline void setId(int id) + { + _Id = id; + } + + inline void setFrsMaterialIndex(unsigned iMaterialIndex) + { + _FrsMaterialIndex = iMaterialIndex; + } + + inline void setMark(bool iMark) + { + _Mark = iMark; + } + + /*! designed to build a specialized WEdge for use in MakeEdge */ + virtual WEdge *instanciateEdge() const + { + return new WEdge; + } + + /*! Builds an oriented edge + * Returns the built edge. + * v1, v2 + * Vertices at the edge's extremities + * The edge is oriented from v1 to v2. + */ + virtual WOEdge *MakeEdge(WVertex *v1, WVertex *v2); + + /*! Adds an edge to the edges list */ + inline void AddEdge(WOEdge *iEdge) + { + _OEdgeList.push_back(iEdge); + } + + /*! For triangles, returns the edge opposite to the vertex in e. + * returns flase if the face is not a triangle or if the vertex is not found + */ + bool getOppositeEdge (const WVertex *v, WOEdge* &e); + + /*! compute the area of the face */ + real getArea (); + + WShape *getShape(); + virtual void ResetUserData() + { + userdata = NULL; + } }; - /**********************************/ - /* */ - /* */ - /* WShape */ - /* */ - /* */ - /**********************************/ +/********************************** + * * + * * + * WShape * + * * + * * + **********************************/ class LIB_WINGED_EDGE_EXPORT WShape { protected: - vector _VertexList; - vector _EdgeList; - vector _FaceList; - int _Id; - string _Name; - static unsigned _SceneCurrentId; - Vec3r _min; - Vec3r _max; - vector _FrsMaterials; - real _meanEdgeSize; + vector _VertexList; + vector _EdgeList; + vector _FaceList; + int _Id; + string _Name; + static unsigned _SceneCurrentId; + Vec3r _min; + Vec3r _max; + vector _FrsMaterials; + real _meanEdgeSize; public: - inline WShape() {_meanEdgeSize = 0;_Id = _SceneCurrentId; _SceneCurrentId++;} - /*! copy constructor */ - WShape(WShape& iBrother); - virtual WShape * duplicate(); - virtual ~WShape() - { - if(_EdgeList.size() != 0) - { - vector::iterator e; - for(e=_EdgeList.begin(); e!=_EdgeList.end(); e++) - { - delete (*e); - } - _EdgeList.clear(); - } - - if(_VertexList.size() != 0) - { - vector::iterator v; - for(v=_VertexList.begin(); v!=_VertexList.end(); v++) - { - delete (*v); - } - _VertexList.clear(); - } - - if(_FaceList.size() != 0) - { - vector::iterator f; - for(f=_FaceList.begin(); f!=_FaceList.end(); f++) - { - delete (*f); - } - _FaceList.clear(); - } - } - - /*! accessors */ - inline vector& getEdgeList() {return _EdgeList;} - inline vector& getVertexList() {return _VertexList;} - inline vector& GetFaceList() {return _FaceList;} - inline unsigned GetId() {return _Id;} - inline void bbox(Vec3r& min, Vec3r& max) {min=_min; max=_max;} - inline const FrsMaterial& frs_material(unsigned i) const {return _FrsMaterials[i];} - inline const vector& frs_materials() const {return _FrsMaterials;} - inline const real getMeanEdgeSize() const {return _meanEdgeSize;} - inline const string& getName() const {return _Name;} - /*! modifiers */ - static inline void setCurrentId(const unsigned id) { _SceneCurrentId = id; } - inline void setEdgeList(const vector& iEdgeList) {_EdgeList = iEdgeList;} - inline void setVertexList(const vector& iVertexList) {_VertexList = iVertexList;} - inline void setFaceList(const vector& iFaceList) {_FaceList = iFaceList;} - inline void setId(int id) {_Id = id;} - inline void setBBox(const Vec3r& min, const Vec3r& max) {_min = min; _max=max;} - inline void setFrsMaterial(const FrsMaterial& frs_material, unsigned i) {_FrsMaterials[i]=frs_material;} - inline void setFrsMaterials(const vector& iMaterials) {_FrsMaterials = iMaterials;} - inline void setName(const string& name) {_Name = name;} - - /*! designed to build a specialized WFace - * for use in MakeFace - */ - virtual WFace * instanciateFace() const {return new WFace;} - - /*! adds a new face to the shape - * returns the built face. - * iVertexList - * List of face's vertices. These vertices are - * not added to the WShape vertex list; they are - * supposed to be already stored when calling MakeFace. - * The order in which the vertices are stored in the list - * determines the face's edges orientation and (so) the - * face orientation. - * iMaterialIndex - * The material index for this face - */ - virtual WFace * MakeFace(vector& iVertexList, vector& iFaceEdgeMarksList, unsigned iMaterialIndex); - - /*! adds a new face to the shape. The difference with - * the previous method is that this one is designed - * to build a WingedEdge structure for which there are - * per vertex normals, opposed to per face normals. - * returns the built face. - * iVertexList - * List of face's vertices. These vertices are - * not added to the WShape vertex list; they are - * supposed to be already stored when calling MakeFace. - * The order in which the vertices are stored in the list - * determines the face's edges orientation and (so) the - * face orientation. - * iMaterialIndex - * The materialIndex for this face - * iNormalsList - * The list of normals, iNormalsList[i] corresponding to the - * normal of the vertex iVertexList[i] for that face. - * iTexCoordsList - * The list of tex coords, iTexCoordsList[i] corresponding to the - * normal of the vertex iVertexList[i] for that face. - */ - virtual WFace * MakeFace(vector& iVertexList, vector& iNormalsList, vector& iTexCoordsList, vector& iFaceEdgeMarksList, unsigned iMaterialIndex); - - inline void AddEdge(WEdge *iEdge) {_EdgeList.push_back(iEdge);} - inline void AddFace(WFace* iFace) {_FaceList.push_back(iFace);} - inline void AddVertex(WVertex *iVertex) {iVertex->setShape(this); _VertexList.push_back(iVertex);} - - inline void ResetUserData() - { - for(vector::iterator v=_VertexList.begin(),vend=_VertexList.end(); - v!=vend; - v++) - { - (*v)->ResetUserData(); - } - - for(vector::iterator e=_EdgeList.begin(),eend=_EdgeList.end(); - e!=eend; - e++) - { - (*e)->ResetUserData(); - // manages WOEdge: - WOEdge *oe = (*e)->GetaOEdge(); - if(oe != NULL) - oe->ResetUserData(); - oe = (*e)->GetbOEdge(); - if(oe != NULL) - oe->ResetUserData(); - } - - for(vector::iterator f=_FaceList.begin(),fend=_FaceList.end(); - f!=fend; - f++) - { - (*f)->ResetUserData(); - } - - } - - inline void ComputeBBox() - { - _min = _VertexList[0]->GetVertex(); - _max = _VertexList[0]->GetVertex(); - - Vec3r v; - for(vector::iterator wv=_VertexList.begin(), wvend=_VertexList.end(); - wv!=wvend; - wv++) - { - for(unsigned int i=0; i<3; i++) - { - v = (*wv)->GetVertex(); - if(v[i] < _min[i]) - _min[i] = v[i]; - if(v[i] > _max[i]) - _max[i] = v[i]; - } - } - } - - inline real ComputeMeanEdgeSize(){ - _meanEdgeSize = _meanEdgeSize/(_EdgeList.size()); - return _meanEdgeSize; - } + inline WShape() + { + _meanEdgeSize = 0; + _Id = _SceneCurrentId; + _SceneCurrentId++; + } + + /*! copy constructor */ + WShape(WShape& iBrother); + virtual WShape *duplicate(); + + virtual ~WShape() + { + if (_EdgeList.size() != 0) { + vector::iterator e; + for (e = _EdgeList.begin(); e != _EdgeList.end(); ++e) { + delete (*e); + } + _EdgeList.clear(); + } + + if (_VertexList.size() != 0) { + vector::iterator v; + for (v = _VertexList.begin(); v != _VertexList.end(); ++v) { + delete (*v); + } + _VertexList.clear(); + } + + if (_FaceList.size() != 0) { + vector::iterator f; + for (f = _FaceList.begin(); f != _FaceList.end(); ++f) { + delete (*f); + } + _FaceList.clear(); + } + } + + /*! accessors */ + inline vector& getEdgeList() + { + return _EdgeList; + } + + inline vector& getVertexList() + { + return _VertexList; + } + + inline vector& GetFaceList() + { + return _FaceList; + } + + inline unsigned GetId() + { + return _Id; + } + + inline void bbox(Vec3r& min, Vec3r& max) + { + min = _min; + max = _max; + } + + inline const FrsMaterial& frs_material(unsigned i) const + { + return _FrsMaterials[i]; + } + + inline const vector& frs_materials() const + { + return _FrsMaterials; + } + + inline const real getMeanEdgeSize() const + { + return _meanEdgeSize; + } + + inline const string& getName() const + { + return _Name; + } + + /*! modifiers */ + static inline void setCurrentId(const unsigned id) + { + _SceneCurrentId = id; + } + + inline void setEdgeList(const vector& iEdgeList) + { + _EdgeList = iEdgeList; + } + + inline void setVertexList(const vector& iVertexList) + { + _VertexList = iVertexList; + } + + inline void setFaceList(const vector& iFaceList) + { + _FaceList = iFaceList; + } + + inline void setId(int id) + { + _Id = id; + } + + inline void setBBox(const Vec3r& min, const Vec3r& max) + { + _min = min; + _max = max; + } + + inline void setFrsMaterial(const FrsMaterial& frs_material, unsigned i) + { + _FrsMaterials[i] = frs_material; + } + + inline void setFrsMaterials(const vector& iMaterials) + { + _FrsMaterials = iMaterials; + } + + inline void setName(const string& name) + { + _Name = name; + } + + /*! designed to build a specialized WFace for use in MakeFace */ + virtual WFace *instanciateFace() const + { + return new WFace; + } + + /*! adds a new face to the shape + * returns the built face. + * iVertexList + * List of face's vertices. These vertices are not added to the WShape vertex list; they are supposed to be + * already stored when calling MakeFace. + * The order in which the vertices are stored in the list determines the face's edges orientation and (so) the + * face orientation. + * iMaterialIndex + * The material index for this face + */ + virtual WFace *MakeFace(vector& iVertexList, vector& iFaceEdgeMarksList, unsigned iMaterialIndex); + + /*! adds a new face to the shape. The difference with the previous method is that this one is designed + * to build a WingedEdge structure for which there are per vertex normals, opposed to per face normals. + * returns the built face. + * iVertexList + * List of face's vertices. These vertices are not added to the WShape vertex list; they are supposed to be + * already stored when calling MakeFace. + * The order in which the vertices are stored in the list determines the face's edges orientation and (so) the + * face orientation. + * iMaterialIndex + * The materialIndex for this face + * iNormalsList + * The list of normals, iNormalsList[i] corresponding to the normal of the vertex iVertexList[i] for that face. + * iTexCoordsList + * The list of tex coords, iTexCoordsList[i] corresponding to the normal of the vertex iVertexList[i] for + * that face. + */ + virtual WFace *MakeFace(vector& iVertexList, vector& iNormalsList, vector& iTexCoordsList, + vector& iFaceEdgeMarksList, unsigned iMaterialIndex); + + inline void AddEdge(WEdge *iEdge) + { + _EdgeList.push_back(iEdge); + } + + inline void AddFace(WFace *iFace) + { + _FaceList.push_back(iFace); + } + + inline void AddVertex(WVertex *iVertex) + { + iVertex->setShape(this); + _VertexList.push_back(iVertex); + } + + inline void ResetUserData() + { + for (vector::iterator v = _VertexList.begin(), vend = _VertexList.end(); v != vend; v++) { + (*v)->ResetUserData(); + } + + for (vector::iterator e = _EdgeList.begin(), eend = _EdgeList.end(); e != eend; e++) { + (*e)->ResetUserData(); + // manages WOEdge: + WOEdge *oe = (*e)->GetaOEdge(); + if (oe) + oe->ResetUserData(); + oe = (*e)->GetbOEdge(); + if (oe) + oe->ResetUserData(); + } + + for (vector::iterator f = _FaceList.begin(), fend = _FaceList.end(); f != fend; f++) { + (*f)->ResetUserData(); + } + } + + inline void ComputeBBox() + { + _min = _VertexList[0]->GetVertex(); + _max = _VertexList[0]->GetVertex(); + + Vec3r v; + for (vector::iterator wv = _VertexList.begin(), wvend = _VertexList.end(); wv != wvend; wv++) { + for (unsigned int i = 0; i < 3; i++) { + v = (*wv)->GetVertex(); + if (v[i] < _min[i]) + _min[i] = v[i]; + if (v[i] > _max[i]) + _max[i] = v[i]; + } + } + } + + inline real ComputeMeanEdgeSize() + { + _meanEdgeSize = _meanEdgeSize / _EdgeList.size(); + return _meanEdgeSize; + } protected: - /*! Builds the face passed as argument (which as already been allocated) - * iVertexList - * List of face's vertices. These vertices are - * not added to the WShape vertex list; they are - * supposed to be already stored when calling MakeFace. - * The order in which the vertices are stored in the list - * determines the face's edges orientation and (so) the - * face orientation. - * iMaterialIndex - * The material index for this face - * face - * The Face that is filled in - */ - virtual WFace * MakeFace(vector& iVertexList, vector& iFaceEdgeMarksList, unsigned iMaterialIndex, WFace *face); + /*! Builds the face passed as argument (which as already been allocated) + * iVertexList + * List of face's vertices. These vertices are not added to the WShape vertex list; they are supposed to be + * already stored when calling MakeFace. + * The order in which the vertices are stored in the list determines the face's edges orientation and (so) the + * face orientation. + * iMaterialIndex + * The material index for this face + * face + * The Face that is filled in + */ + virtual WFace *MakeFace(vector& iVertexList, vector& iFaceEdgeMarksList, unsigned iMaterialIndex, + WFace *face); }; - /**********************************/ - /* */ - /* */ - /* WingedEdge */ - /* */ - /* */ - /**********************************/ - -class WingedEdge { - - public: +/********************************** + * * + * * + * WingedEdge * + * * + * * + **********************************/ - WingedEdge() {} - - ~WingedEdge() { - clear(); - } - - void clear() { - for (vector::iterator it = _wshapes.begin(); - it != _wshapes.end(); - it++) - delete *it; - _wshapes.clear(); - } - - void addWShape(WShape* wshape) { - _wshapes.push_back(wshape); - } - - vector& getWShapes() { - return _wshapes; - } - - private: - - vector _wshapes; +class WingedEdge +{ +public: + WingedEdge() {} + + ~WingedEdge() + { + clear(); + } + + void clear() + { + for (vector::iterator it = _wshapes.begin(); it != _wshapes.end(); it++) + delete *it; + _wshapes.clear(); + } + + void addWShape(WShape *wshape) + { + _wshapes.push_back(wshape); + } + + vector& getWShapes() + { + return _wshapes; + } + +private: + vector _wshapes; }; /* - - ############################################# - ############################################# - ############################################# - ###### ###### - ###### I M P L E M E N T A T I O N ###### - ###### ###### - ############################################# - ############################################# - ############################################# - + +############################################# +############################################# +############################################# +###### ###### +###### I M P L E M E N T A T I O N ###### +###### ###### +############################################# +############################################# +############################################# + */ /* for inline functions */ -void WOEdge::RetrieveCWOrderedEdges(vector& oEdges) +void WOEdge::RetrieveCWOrderedEdges(vector& oEdges) { - - WOEdge *currentOEdge = this; - do - { - WOEdge* nextOEdge = currentOEdge->GetbFace()->GetNextOEdge(currentOEdge); - oEdges.push_back(nextOEdge->GetOwner()); - currentOEdge = nextOEdge->GetOwner()->GetOtherOEdge(nextOEdge); - - } while((currentOEdge != NULL) && (currentOEdge->GetOwner() != GetOwner())); + WOEdge *currentOEdge = this; + do { + WOEdge *nextOEdge = currentOEdge->GetbFace()->GetNextOEdge(currentOEdge); + oEdges.push_back(nextOEdge->GetOwner()); + currentOEdge = nextOEdge->GetOwner()->GetOtherOEdge(nextOEdge); + } while (currentOEdge && (currentOEdge->GetOwner() != GetOwner())); } -inline void WOEdge::setVecAndAngle() { - if ( _paVertex != NULL && _pbVertex != NULL ) { - _vec = _pbVertex->GetVertex() - _paVertex->GetVertex(); - if ( _paFace != NULL && _pbFace != NULL ) { - real sine = (_pbFace->GetNormal() ^ _paFace->GetNormal()) * _vec / _vec.norm() ; - if(sine >= 1.0) { - _angle = M_PI / 2.0 ; - return; - } - if(sine <= -1.0) { - _angle = -M_PI / 2.0 ; - return; - } - _angle = ::asin(sine); - } - } +inline void WOEdge::setVecAndAngle() +{ + if (_paVertex && _pbVertex) { + _vec = _pbVertex->GetVertex() - _paVertex->GetVertex(); + if (_paFace && _pbFace) { + real sine = (_pbFace->GetNormal() ^ _paFace->GetNormal()) * _vec / _vec.norm(); + if (sine >= 1.0) { + _angle = M_PI / 2.0; + return; + } + if (sine <= -1.0) { + _angle = -M_PI / 2.0; + return; + } + _angle = ::asin(sine); + } + } } -#endif // WEDGE_H +#endif // __FREESTYLE_W_EDGE_H__ \ No newline at end of file diff --git a/source/blender/freestyle/intern/winged_edge/WFillGrid.cpp b/source/blender/freestyle/intern/winged_edge/WFillGrid.cpp index 7d0a2d3c561..8b446791efc 100644 --- a/source/blender/freestyle/intern/winged_edge/WFillGrid.cpp +++ b/source/blender/freestyle/intern/winged_edge/WFillGrid.cpp @@ -1,60 +1,68 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/** \file blender/freestyle/intern/winged_edge/WFillGrid.cpp + * \ingroup freestyle + * \brief Class to fill in a grid from a SceneGraph (uses only the WingedEdge structures) + * \author Emmanuel Turquin + * \author Stephane Grabli + * \date 03/05/2003 + */ #include "WEdge.h" #include "WFillGrid.h" -void WFillGrid::fillGrid() { - if (!_winged_edge || !_grid) - return; - - vector wshapes = _winged_edge->getWShapes(); - vector fvertices; - vector vectors; - vector faces; - - for (vector::const_iterator it = wshapes.begin(); - it != wshapes.end(); - it++) { - faces = (*it)->GetFaceList(); - - for (vector::const_iterator f = faces.begin(); - f != faces.end(); - f++) { - (*f)->RetrieveVertexList(fvertices); - - for (vector::const_iterator wv = fvertices.begin(); - wv != fvertices.end(); - wv++) - vectors.push_back(Vec3r((*wv)->GetVertex())); - - // occluder will be deleted by the grid - Polygon3r *occluder = - new Polygon3r(vectors, (*f)->GetNormal()); - occluder->setId(_polygon_id++); - occluder->userdata = (void*)(*f); - _grid->insertOccluder(occluder); - vectors.clear(); - fvertices.clear(); - } - faces.clear(); - } -} +void WFillGrid::fillGrid() +{ + if (!_winged_edge || !_grid) + return; + + vector wshapes = _winged_edge->getWShapes(); + vector fvertices; + vector vectors; + vector faces; + + for (vector::const_iterator it = wshapes.begin(); it != wshapes.end(); ++it) { + faces = (*it)->GetFaceList(); + + for (vector::const_iterator f = faces.begin(); f != faces.end(); ++f) { + (*f)->RetrieveVertexList(fvertices); + + for (vector::const_iterator wv = fvertices.begin(); wv != fvertices.end(); ++wv) + vectors.push_back(Vec3r((*wv)->GetVertex())); + + // occluder will be deleted by the grid + Polygon3r *occluder = new Polygon3r(vectors, (*f)->GetNormal()); + occluder->setId(_polygon_id++); + occluder->userdata = (void *)(*f); + _grid->insertOccluder(occluder); + vectors.clear(); + fvertices.clear(); + } + faces.clear(); + } +} \ No newline at end of file diff --git a/source/blender/freestyle/intern/winged_edge/WFillGrid.h b/source/blender/freestyle/intern/winged_edge/WFillGrid.h index 2ebbc2f359a..223c5a786d8 100644 --- a/source/blender/freestyle/intern/winged_edge/WFillGrid.h +++ b/source/blender/freestyle/intern/winged_edge/WFillGrid.h @@ -1,80 +1,88 @@ -// -// Filename : WFillGrid.h -// Author(s) : Stephane Grabli -// Emmanuel Turquin -// Purpose : Class to fill in a grid from a SceneGraph -// (uses only the WingedEdge structures) -// Date of creation : 03/05/2003 -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef __FREESTYLE_W_FILL_GRID_H__ +#define __FREESTYLE_W_FILL_GRID_H__ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/** \file blender/freestyle/intern/winged_edge/WFillGrid.h + * \ingroup freestyle + * \brief Class to fill in a grid from a SceneGraph (uses only the WingedEdge structures) + * \author Emmanuel Turquin + * \author Stephane Grabli + * \date 03/05/2003 + */ -#ifndef W_FILL_GRID_H -# define W_FILL_GRID_H +#include "WEdge.h" -# include "../geometry/Grid.h" -# include "../geometry/Polygon.h" -# include "WEdge.h" +#include "../geometry/Grid.h" +#include "../geometry/Polygon.h" class LIB_WINGED_EDGE_EXPORT WFillGrid { public: + inline WFillGrid(Grid *grid = NULL, WingedEdge *winged_edge = NULL) + { + _winged_edge = winged_edge; + _grid = grid; + _polygon_id = 0; + } - inline WFillGrid(Grid* grid = 0, WingedEdge* winged_edge = 0) { - _winged_edge = winged_edge; - _grid = grid; - _polygon_id = 0; - } + virtual ~WFillGrid() {} - virtual ~WFillGrid() {} + void fillGrid(); - void fillGrid(); + /*! Accessors */ + WingedEdge *getWingedEdge() + { + return _winged_edge; + } - /*! Accessors */ - WingedEdge* getWingedEdge() { - return _winged_edge; - } + Grid *getGrid() + { + return _grid; + } - Grid* getGrid() { - return _grid; - } + /*! Modifiers */ + void setWingedEdge(WingedEdge *winged_edge) + { + if (winged_edge) + _winged_edge = winged_edge; + } - /*! Modifiers */ - void setWingedEdge(WingedEdge* winged_edge) { - if (winged_edge) - _winged_edge = winged_edge; - } - - void setGrid(Grid* grid) { - if (grid) - _grid = grid; - } + void setGrid(Grid *grid) + { + if (grid) + _grid = grid; + } private: - - Grid* _grid; - WingedEdge* _winged_edge; - unsigned _polygon_id; + Grid *_grid; + WingedEdge *_winged_edge; + unsigned _polygon_id; }; -#endif // WS_FILL_GRID_H +#endif // __FREESTYLE_W_FILL_GRID_H__ \ No newline at end of file diff --git a/source/blender/freestyle/intern/winged_edge/WSFillGrid.cpp b/source/blender/freestyle/intern/winged_edge/WSFillGrid.cpp index 55fa418d4f5..3504a8ab179 100644 --- a/source/blender/freestyle/intern/winged_edge/WSFillGrid.cpp +++ b/source/blender/freestyle/intern/winged_edge/WSFillGrid.cpp @@ -1,60 +1,67 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/** \file blender/freestyle/intern/winged_edge/WSFillGrid.cpp + * \ingroup freestyle + * \brief Class to fill in a grid from a SceneGraph (uses only the WingedEdge structures) + * \author Stephane Grabli + * \date 03/05/2003 + */ #include "WEdge.h" #include "WSFillGrid.h" -void WSFillGrid::fillGrid() { - if (!_winged_edge || !_grid) - return; - - vector wshapes = _winged_edge->getWShapes(); - vector fvertices; - vector vectors; - vector faces; - - for (vector::const_iterator it = wshapes.begin(); - it != wshapes.end(); - it++) { - faces = (*it)->GetFaceList(); - - for (vector::const_iterator f = faces.begin(); - f != faces.end(); - f++) { - (*f)->RetrieveVertexList(fvertices); - - for (vector::const_iterator wv = fvertices.begin(); - wv != fvertices.end(); - wv++) - vectors.push_back(Vec3r((*wv)->GetVertex())); - - // occluder will be deleted by the grid - Polygon3r *occluder = - new Polygon3r(vectors, (*f)->GetNormal()); - occluder->setId(_polygon_id++); - occluder->userdata = (void*)(*f); - _grid->insertOccluder(occluder); - vectors.clear(); - fvertices.clear(); - } - faces.clear(); - } -} +void WSFillGrid::fillGrid() +{ + if (!_winged_edge || !_grid) + return; + + vector wshapes = _winged_edge->getWShapes(); + vector fvertices; + vector vectors; + vector faces; + + for (vector::const_iterator it = wshapes.begin(); it != wshapes.end(); ++it) { + faces = (*it)->GetFaceList(); + + for (vector::const_iterator f = faces.begin(); f != faces.end(); ++f) { + (*f)->RetrieveVertexList(fvertices); + + for (vector::const_iterator wv = fvertices.begin(); wv != fvertices.end(); ++wv) + vectors.push_back(Vec3r((*wv)->GetVertex())); + + // occluder will be deleted by the grid + Polygon3r *occluder = new Polygon3r(vectors, (*f)->GetNormal()); + occluder->setId(_polygon_id++); + occluder->userdata = (void *)(*f); + _grid->insertOccluder(occluder); + vectors.clear(); + fvertices.clear(); + } + faces.clear(); + } +} \ No newline at end of file diff --git a/source/blender/freestyle/intern/winged_edge/WSFillGrid.h b/source/blender/freestyle/intern/winged_edge/WSFillGrid.h index 2ea5bc6c621..55bedd83cce 100644 --- a/source/blender/freestyle/intern/winged_edge/WSFillGrid.h +++ b/source/blender/freestyle/intern/winged_edge/WSFillGrid.h @@ -1,79 +1,87 @@ -// -// Filename : WSFillGrid.h -// Author(s) : Stephane Grabli -// Purpose : Class to fill in a grid from a SceneGraph -// (uses only the WingedEdge structures) -// Date of creation : 03/05/2003 -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef __FREESTYLE_WS_FILL_GRID_H__ +#define __FREESTYLE_WS_FILL_GRID_H__ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/** \file blender/freestyle/intern/winged_edge/WSFillGrid.h + * \ingroup freestyle + * \brief Class to fill in a grid from a SceneGraph (uses only the WingedEdge structures) + * \author Stephane Grabli + * \date 03/05/2003 + */ -#ifndef WS_FILL_GRID_H -# define WS_FILL_GRID_H +#include "WEdge.h" -# include "../geometry/Grid.h" -# include "../geometry/Polygon.h" -# include "WEdge.h" +#include "../geometry/Grid.h" +#include "../geometry/Polygon.h" class LIB_WINGED_EDGE_EXPORT WSFillGrid { public: + inline WSFillGrid(Grid *grid = NULL, WingedEdge *winged_edge = NULL) + { + _winged_edge = winged_edge; + _grid = grid; + _polygon_id = 0; + } - inline WSFillGrid(Grid* grid = 0, WingedEdge* winged_edge = 0) { - _winged_edge = winged_edge; - _grid = grid; - _polygon_id = 0; - } + virtual ~WSFillGrid() {} - virtual ~WSFillGrid() {} + void fillGrid(); - void fillGrid(); + /*! Accessors */ + WingedEdge *getWingedEdge() + { + return _winged_edge; + } - /*! Accessors */ - WingedEdge* getWingedEdge() { - return _winged_edge; - } + Grid *getGrid() + { + return _grid; + } - Grid* getGrid() { - return _grid; - } + /*! Modifiers */ + void setWingedEdge(WingedEdge *winged_edge) + { + if (winged_edge) + _winged_edge = winged_edge; + } - /*! Modifiers */ - void setWingedEdge(WingedEdge* winged_edge) { - if (winged_edge) - _winged_edge = winged_edge; - } - - void setGrid(Grid* grid) { - if (grid) - _grid = grid; - } + void setGrid(Grid *grid) + { + if (grid) + _grid = grid; + } private: - - Grid* _grid; - WingedEdge* _winged_edge; - unsigned _polygon_id; + Grid *_grid; + WingedEdge *_winged_edge; + unsigned _polygon_id; }; -#endif // WS_FILL_GRID_H +#endif // __FREESTYLE_WS_FILL_GRID_H__ \ No newline at end of file diff --git a/source/blender/freestyle/intern/winged_edge/WXEdge.cpp b/source/blender/freestyle/intern/winged_edge/WXEdge.cpp index d238749570c..fed9a1588bb 100644 --- a/source/blender/freestyle/intern/winged_edge/WXEdge.cpp +++ b/source/blender/freestyle/intern/winged_edge/WXEdge.cpp @@ -1,296 +1,298 @@ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/freestyle/intern/winged_edge/WXEdge.cpp + * \ingroup freestyle + * \brief Classes to define an Extended Winged Edge data structure. + * \author Stephane Grabli + * \date 26/10/2003 + */ #include "WXEdge.h" - /**********************************/ - /* */ - /* */ - /* WXFace */ - /* */ - /* */ - /**********************************/ +/********************************** + * * + * * + * WXFace * + * * + * * + **********************************/ -unsigned int WXFaceLayer::Get0VertexIndex() const { - int i = 0; - int nEdges = _pWXFace->numberOfEdges(); - for(i=0; inumberOfEdges(); + for (i = 0; i < nEdges; ++i) { + if (_DotP[i] == 0) { + return i; + } + } + return -1; } -unsigned int WXFaceLayer::GetSmoothEdgeIndex() const{ - int i = 0; - int nEdges = _pWXFace->numberOfEdges(); - for(i=0; inumberOfEdges(); + for (i = 0; i < nEdges; ++i) { + if ((_DotP[i] == 0) && (_DotP[(i+1)%nEdges] == 0)) { + return i; + } + } + return -1; } -void WXFaceLayer::RetrieveCuspEdgesIndices(vector& oCuspEdges){ - int i = 0; - int nEdges = _pWXFace->numberOfEdges(); - for(i=0; i& oCuspEdges) +{ + int i = 0; + int nEdges = _pWXFace->numberOfEdges(); + for (i = 0; i < nEdges; ++i) { + if (_DotP[i] * _DotP[(i + 1) % nEdges] < 0) { + // we got one + oCuspEdges.push_back(i); + } + } } - -WXSmoothEdge* WXFaceLayer::BuildSmoothEdge(){ - // if the smooth edge has already been - // built: exit - if(0 != _pSmoothEdge) - return _pSmoothEdge; - real ta, tb; - WOEdge *woea(0), *woeb(0); - bool ok = false; - vector cuspEdgesIndices; - int indexStart, indexEnd; - unsigned nedges = _pWXFace->numberOfEdges(); - if(_nNullDotP == nedges){ - _pSmoothEdge = 0; - return _pSmoothEdge; - } - if((_nPosDotP != 0) && (_nPosDotP != _DotP.size()) && (_nNullDotP == 0)){ - // that means that we have a smooth edge that starts from - // an edge and ends at an edge - //----------------------------- - // We retrieve the 2 edges for which we have - // opposite signs for each extremity - RetrieveCuspEdgesIndices(cuspEdgesIndices); - if(cuspEdgesIndices.size() != 2) // we necessarly have 2 cusp edges - return 0; - - // let us determine which cusp edge corresponds to the starting: - // We can do that because we defined that - // a silhouette edge had the back facing part on its right. - // So if the WOEdge woea is such that woea[0].dotp > 0 and - // woea[1].dotp < 0, it is the starting edge. - //------------------------------------------- - - if(_DotP[cuspEdgesIndices[0]] > 0){ - woea = _pWXFace->GetOEdge(cuspEdgesIndices[0]); - woeb = _pWXFace->GetOEdge(cuspEdgesIndices[1]); - indexStart = cuspEdgesIndices[0]; - indexEnd = cuspEdgesIndices[1]; - }else{ - woea = _pWXFace->GetOEdge(cuspEdgesIndices[1]); - woeb = _pWXFace->GetOEdge(cuspEdgesIndices[0]); - indexStart = cuspEdgesIndices[1]; - indexEnd = cuspEdgesIndices[0]; - } - - // Compute the interpolation: - ta = _DotP[indexStart]/(_DotP[indexStart]-_DotP[(indexStart+1)%nedges]); - tb = _DotP[indexEnd]/(_DotP[indexEnd]-_DotP[(indexEnd+1)%nedges]); - ok = true; - }else if(_nNullDotP == 1){ - // that means that we have exactly one of the - // 2 extremities of our silhouette edge is - // a vertex of the mesh - if((_nPosDotP == 2) || (_nPosDotP == 0)){ - _pSmoothEdge = 0; - return _pSmoothEdge; - } - RetrieveCuspEdgesIndices(cuspEdgesIndices); - // We should have only one EdgeCusp: - if(cuspEdgesIndices.size() != 1){ - cout << "Warning in BuildSmoothEdge: weird WXFace configuration" << endl; - _pSmoothEdge = 0; - return 0; - } - unsigned index0 = Get0VertexIndex(); // retrieve the 0 vertex index - unsigned nedges = _pWXFace->numberOfEdges(); - if(_DotP[cuspEdgesIndices[0]] > 0){ - woea = _pWXFace->GetOEdge(cuspEdgesIndices[0]); - woeb = _pWXFace->GetOEdge(index0); - indexStart = cuspEdgesIndices[0]; - ta = _DotP[indexStart]/(_DotP[indexStart]-_DotP[(indexStart+1)%nedges]); - tb = 0.0; - }else{ - woea = _pWXFace->GetOEdge(index0); - woeb = _pWXFace->GetOEdge(cuspEdgesIndices[0]); - indexEnd = cuspEdgesIndices[0]; - ta = 0.0; - tb = _DotP[indexEnd]/(_DotP[indexEnd]-_DotP[(indexEnd+1)%nedges]); - } - ok = true; - }else if(_nNullDotP == 2){ - // that means that the silhouette edge - // is an edge of the mesh - int index = GetSmoothEdgeIndex(); - if(!_pWXFace->front()) {// is it in the right order ? - // the order of the WOEdge index is wrong - woea = _pWXFace->GetOEdge((index+1)%nedges); - woeb = _pWXFace->GetOEdge((index-1)%nedges); - ta = 0; - tb = 1; - ok = true; - }else{ - // here it's not good, our edge is a single point -> skip that face - ok = false; - // the order of the WOEdge index is good - // woea = _pWXFace->GetOEdge((index-1)%nedges); - // woeb = _pWXFace->GetOEdge((index+1)%nedges); - // ta = 1; - // tb = 0; - } - } - if(ok){ - _pSmoothEdge = new WXSmoothEdge; - _pSmoothEdge->setWOeA(woea); - _pSmoothEdge->setWOeB(woeb); - _pSmoothEdge->setTa(ta); - _pSmoothEdge->setTb(tb); - if(_Nature & Nature::SILHOUETTE){ - if(_nNullDotP != 2){ - if(_DotP[_ClosestPointIndex] + 0.01 > 0) - _pSmoothEdge->setFront(true); - else - _pSmoothEdge->setFront(false); - } - } - } - - // check bording edges to see if they have different dotp values - // in bording faces. - // for(int i=0; ifront())) // fA->front XOR fB->front (true if one is 0 and the other is 1) - // { - // // that means that the edge i of the face is - // // a silhouette edge - // // TESTER D'ABORD SI LE EXACTSILHOUETTEEDGE N'A PAS - // // ETE CONSTRUIT SUR L'AUTRE FACE.(1 suffit) - // if(0 != ((WSExactFace*)bface)->exactSilhouetteEdge()) - // { - // // that means that this silhouette edge has already been built - // return ((WSExactFace*)bface)->exactSilhouetteEdge(); - // } - // // Else we must build it - // WOEdge *woea, *woeb; - // real ta, tb; - // if(!front()) // is it in the right order ? - // { - // // the order of the WOEdge index is wrong - // woea = _OEdgeList[(i+1)%numberOfEdges()]; - // if(0 == i) - // woeb = _OEdgeList[numberOfEdges()-1]; - // else - // woeb = _OEdgeList[(i-1)]; - // ta = 0; - // tb = 1; - // } - // else - // { - // // the order of the WOEdge index is good - // if(0 == i) - // woea = _OEdgeList[numberOfEdges()-1]; - // else - // woea = _OEdgeList[(i-1)]; - // woeb = _OEdgeList[(i+1)%numberOfEdges()]; - // ta = 1; - // tb = 0; - // } - // - // _pSmoothEdge = new ExactSilhouetteEdge(ExactSilhouetteEdge::VERTEX_VERTEX); - // _pSmoothEdge->setWOeA(woea); - // _pSmoothEdge->setWOeA(woeb); - // _pSmoothEdge->setTa(ta); - // _pSmoothEdge->setTb(tb); - // - // return _pSmoothEdge; - // } - // } - //} - return _pSmoothEdge; + +WXSmoothEdge *WXFaceLayer::BuildSmoothEdge() +{ + // if the smooth edge has already been built: exit + if (_pSmoothEdge) + return _pSmoothEdge; + real ta, tb; + WOEdge *woea(0), *woeb(0); + bool ok = false; + vector cuspEdgesIndices; + int indexStart, indexEnd; + unsigned nedges = _pWXFace->numberOfEdges(); + if (_nNullDotP == nedges) { + _pSmoothEdge = NULL; + return _pSmoothEdge; + } + if ((_nPosDotP != 0) && (_nPosDotP != _DotP.size()) && (_nNullDotP == 0)) { + // that means that we have a smooth edge that starts from an edge and ends at an edge + //----------------------------- + // We retrieve the 2 edges for which we have opposite signs for each extremity + RetrieveCuspEdgesIndices(cuspEdgesIndices); + if (cuspEdgesIndices.size() != 2) // we necessarly have 2 cusp edges + return 0; + + // let us determine which cusp edge corresponds to the starting: + // We can do that because we defined that a silhouette edge had the back facing part on its right. + // So if the WOEdge woea is such that woea[0].dotp > 0 and woea[1].dotp < 0, it is the starting edge. + //------------------------------------------- + + if (_DotP[cuspEdgesIndices[0]] > 0) { + woea = _pWXFace->GetOEdge(cuspEdgesIndices[0]); + woeb = _pWXFace->GetOEdge(cuspEdgesIndices[1]); + indexStart = cuspEdgesIndices[0]; + indexEnd = cuspEdgesIndices[1]; + } + else { + woea = _pWXFace->GetOEdge(cuspEdgesIndices[1]); + woeb = _pWXFace->GetOEdge(cuspEdgesIndices[0]); + indexStart = cuspEdgesIndices[1]; + indexEnd = cuspEdgesIndices[0]; + } + + // Compute the interpolation: + ta = _DotP[indexStart] / (_DotP[indexStart] - _DotP[(indexStart + 1) % nedges]); + tb = _DotP[indexEnd] / (_DotP[indexEnd] - _DotP[(indexEnd + 1) % nedges]); + ok = true; + } + else if (_nNullDotP == 1) { + // that means that we have exactly one of the 2 extremities of our silhouette edge is a vertex of the mesh + if ((_nPosDotP == 2) || (_nPosDotP == 0)) { + _pSmoothEdge = NULL; + return _pSmoothEdge; + } + RetrieveCuspEdgesIndices(cuspEdgesIndices); + // We should have only one EdgeCusp: + if (cuspEdgesIndices.size() != 1) { + cout << "Warning in BuildSmoothEdge: weird WXFace configuration" << endl; + _pSmoothEdge = NULL; + return NULL; + } + unsigned index0 = Get0VertexIndex(); // retrieve the 0 vertex index + unsigned nedges = _pWXFace->numberOfEdges(); + if (_DotP[cuspEdgesIndices[0]] > 0) { + woea = _pWXFace->GetOEdge(cuspEdgesIndices[0]); + woeb = _pWXFace->GetOEdge(index0); + indexStart = cuspEdgesIndices[0]; + ta = _DotP[indexStart] / (_DotP[indexStart] - _DotP[(indexStart + 1) % nedges]); + tb = 0.0; + } + else { + woea = _pWXFace->GetOEdge(index0); + woeb = _pWXFace->GetOEdge(cuspEdgesIndices[0]); + indexEnd = cuspEdgesIndices[0]; + ta = 0.0; + tb = _DotP[indexEnd] / (_DotP[indexEnd] - _DotP[(indexEnd + 1) % nedges]); + } + ok = true; + } + else if (_nNullDotP == 2) { + // that means that the silhouette edge is an edge of the mesh + int index = GetSmoothEdgeIndex(); + if (!_pWXFace->front()) { // is it in the right order ? + // the order of the WOEdge index is wrong + woea = _pWXFace->GetOEdge((index + 1) % nedges); + woeb = _pWXFace->GetOEdge((index - 1) % nedges); + ta = 0; + tb = 1; + ok = true; + } + else { + // here it's not good, our edge is a single point -> skip that face + ok = false; +#if 0 + // the order of the WOEdge index is good + woea = _pWXFace->GetOEdge((index - 1) % nedges); + woeb = _pWXFace->GetOEdge((index + 1) % nedges); + ta = 1; + tb = 0; +#endif + } + } + if (ok) { + _pSmoothEdge = new WXSmoothEdge; + _pSmoothEdge->setWOeA(woea); + _pSmoothEdge->setWOeB(woeb); + _pSmoothEdge->setTa(ta); + _pSmoothEdge->setTb(tb); + if (_Nature & Nature::SILHOUETTE) { + if (_nNullDotP != 2) { + if (_DotP[_ClosestPointIndex] + 0.01 > 0) + _pSmoothEdge->setFront(true); + else + _pSmoothEdge->setFront(false); + } + } + } + +#if 0 + // check bording edges to see if they have different dotp values in bording faces. + for (int i = 0; i < numberOfEdges(); i++) { + WSFace *bface = (WSFace *)GetBordingFace(i); + if (bface) { + if ((front()) ^ (bface->front())) { // fA->front XOR fB->front (true if one is 0 and the other is 1) + // that means that the edge i of the face is a silhouette edge + // CHECK FIRST WHETHER THE EXACTSILHOUETTEEDGE HAS NOT YET BEEN BUILT ON THE OTHER FACE (1 is enough). + if (((WSExactFace *)bface)->exactSilhouetteEdge()) { + // that means that this silhouette edge has already been built + return ((WSExactFace *)bface)->exactSilhouetteEdge(); + } + // Else we must build it + WOEdge *woea, *woeb; + real ta, tb; + if (!front()) { // is it in the right order ? + // the order of the WOEdge index is wrong + woea = _OEdgeList[(i + 1) % numberOfEdges()]; + if (0 == i) + woeb = _OEdgeList[numberOfEdges() - 1]; + else + woeb = _OEdgeList[(i - 1)]; + ta = 0; + tb = 1; + } + else { + // the order of the WOEdge index is good + if (0 == i) + woea = _OEdgeList[numberOfEdges() - 1]; + else + woea = _OEdgeList[(i - 1)]; + woeb = _OEdgeList[(i + 1) % numberOfEdges()]; + ta = 1; + tb = 0; + } + + _pSmoothEdge = new ExactSilhouetteEdge(ExactSilhouetteEdge::VERTEX_VERTEX); + _pSmoothEdge->setWOeA(woea); + _pSmoothEdge->setWOeA(woeb); + _pSmoothEdge->setTa(ta); + _pSmoothEdge->setTb(tb); + + return _pSmoothEdge; + } + } + } +#endif + return _pSmoothEdge; } - + void WXFace::ComputeCenter() { - vector iVertexList; - RetrieveVertexList(iVertexList); - Vec3r center; - for(vector::iterator wv=iVertexList.begin(),wvend=iVertexList.end(); - wv!=wvend; - wv++) - { - center += (*wv)->GetVertex(); - } - center /= (real)iVertexList.size(); - setCenter(center); + vector iVertexList; + RetrieveVertexList(iVertexList); + Vec3r center; + for (vector::iterator wv = iVertexList.begin(), wvend = iVertexList.end(); wv != wvend; ++wv) { + center += (*wv)->GetVertex(); + } + center /= (real)iVertexList.size(); + setCenter(center); } - /**********************************/ - /* */ - /* */ - /* WXShape */ - /* */ - /* */ - /**********************************/ - +/********************************** + * * + * * + * WXShape * + * * + * * + **********************************/ -WFace* WXShape::MakeFace(vector& iVertexList, vector& iFaceEdgeMarksList, unsigned iMaterialIndex) +WFace *WXShape::MakeFace(vector& iVertexList, vector& iFaceEdgeMarksList, unsigned iMaterialIndex) { - WFace *face = WShape::MakeFace(iVertexList, iFaceEdgeMarksList, iMaterialIndex); - if(0 == face) - return 0; - - Vec3r center; - for(vector::iterator wv=iVertexList.begin(),wvend=iVertexList.end(); - wv!=wvend; - wv++) - { - center += (*wv)->GetVertex(); - } - center /= (real)iVertexList.size(); - ((WXFace*)face)->setCenter(center); + WFace *face = WShape::MakeFace(iVertexList, iFaceEdgeMarksList, iMaterialIndex); + if (!face) + return NULL; - return face; + Vec3r center; + for (vector::iterator wv = iVertexList.begin(), wvend = iVertexList.end(); wv != wvend; ++wv) { + center += (*wv)->GetVertex(); + } + center /= (real)iVertexList.size(); + ((WXFace *)face)->setCenter(center); + + return face; } -WFace * WXShape::MakeFace(vector& iVertexList, vector& iNormalsList, vector& iTexCoordsList, vector& iFaceEdgeMarksList, unsigned iMaterialIndex) +WFace *WXShape::MakeFace(vector& iVertexList, vector& iNormalsList, vector& iTexCoordsList, + vector& iFaceEdgeMarksList, unsigned iMaterialIndex) { - WFace *face = WShape::MakeFace(iVertexList, iNormalsList, iTexCoordsList, iFaceEdgeMarksList, iMaterialIndex); - - // Vec3r center; - // for(vector::iterator wv=iVertexList.begin(),wvend=iVertexList.end(); - // wv!=wvend; - // wv++) - // { - // center += (*wv)->GetVertex(); - // } - // center /= (real)iVertexList.size(); - // ((WSFace*)face)->setCenter(center); + WFace *face = WShape::MakeFace(iVertexList, iNormalsList, iTexCoordsList, iFaceEdgeMarksList, iMaterialIndex); - return face; -} +#if 0 + Vec3r center; + for (vector::iterator wv = iVertexList.begin(), wvend = iVertexList.end(); wv != wvend; ++wv) { + center += (*wv)->GetVertex(); + } + center /= (real)iVertexList.size(); + ((WSFace *)face)->setCenter(center); +#endif + return face; +} \ No newline at end of file diff --git a/source/blender/freestyle/intern/winged_edge/WXEdge.h b/source/blender/freestyle/intern/winged_edge/WXEdge.h index c51b6a84a98..9f3522e4e70 100644 --- a/source/blender/freestyle/intern/winged_edge/WXEdge.h +++ b/source/blender/freestyle/intern/winged_edge/WXEdge.h @@ -1,582 +1,809 @@ -// -// Filename : WXEdge.h -// Author(s) : Stephane Grabli -// Purpose : Classes to define an Extended Winged Edge data structure. -// Date of creation : 26/10/2003 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef WXEDGE_H -# define WXEDGE_H - -# include "WEdge.h" -# include "Nature.h" -# include "Curvature.h" +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_WX_EDGE_H__ +#define __FREESTYLE_WX_EDGE_H__ + +/** \file blender/freestyle/intern/winged_edge/WXEdge.h + * \ingroup freestyle + * \brief Classes to define an Extended Winged Edge data structure. + * \author Stephane Grabli + * \date 26/10/2003 + */ + +#include "Curvature.h" +#include "Nature.h" +#include "WEdge.h" typedef Nature::EdgeNature WXNature; - /**********************************/ - /* */ - /* */ - /* WXVertex */ - /* */ - /* */ - /**********************************/ +/********************************** + * * + * * + * WXVertex * + * * + * * + **********************************/ class WXVertex : public WVertex -{ +{ private: - // Curvature info - CurvatureInfo *_curvatures; + // Curvature info + CurvatureInfo *_curvatures; public: - inline WXVertex(const Vec3r &v) - : WVertex(v) - {_curvatures = 0;} - /*! Copy constructor */ - WXVertex(WXVertex& iBrother) - : WVertex(iBrother) - {_curvatures = new CurvatureInfo(*iBrother._curvatures);} - virtual WVertex * duplicate() - { - WXVertex *clone = new WXVertex(*this); - return clone; - } - virtual ~WXVertex() {if(_curvatures) delete _curvatures;} - virtual void Reset() {if(_curvatures) _curvatures->Kr = 0.0;} - inline void setCurvatures(CurvatureInfo *ci) {_curvatures = ci;} - - inline bool isFeature(); - inline CurvatureInfo* curvatures() {return _curvatures;} - + inline WXVertex(const Vec3r &v) : WVertex(v) + { + _curvatures = NULL; + } + + /*! Copy constructor */ + WXVertex(WXVertex& iBrother) : WVertex(iBrother) + { + _curvatures = new CurvatureInfo(*iBrother._curvatures); + } + + virtual WVertex *duplicate() + { + WXVertex *clone = new WXVertex(*this); + return clone; + } + + virtual ~WXVertex() + { + if (_curvatures) + delete _curvatures; + } + + virtual void Reset() + { + if (_curvatures) + _curvatures->Kr = 0.0; + } + + inline void setCurvatures(CurvatureInfo *ci) + { + _curvatures = ci; + } + + inline bool isFeature(); + + inline CurvatureInfo *curvatures() + { + return _curvatures; + } }; +/********************************** + * * + * * + * WXEdge * + * * + * * + **********************************/ - /**********************************/ - /* */ - /* */ - /* WXEdge */ - /* */ - /* */ - /**********************************/ class WXEdge : public WEdge { private: - WXNature _nature; // flag to indicate whether the edge is a silhouette edge or not - int _order; // 0: the order doesn't matter. 1: the order is the orginal one. -1: the order is not good - bool _front; // a front facing edge is an edge for which the bording face which is the nearest - // from the viewpoint is front. A back facing edge is the opposite. - + // flag to indicate whether the edge is a silhouette edge or not + WXNature _nature; + // 0: the order doesn't matter. 1: the order is the orginal one. -1: the order is not good + int _order; + // A front facing edge is an edge for which the bording face which is the nearest from the viewpoint is front. + // A back facing edge is the opposite. + bool _front; + public: - inline WXEdge() - : WEdge(){ - _nature = Nature::NO_FEATURE; - _front = false; - _order=0; - } - - inline WXEdge(WOEdge *iOEdge) - : WEdge(iOEdge) - { _nature = Nature::NO_FEATURE;_front = false;_order=0;} - - inline WXEdge(WOEdge *iaOEdge, WOEdge *ibOEdge) - : WEdge(iaOEdge, ibOEdge) - { _nature = Nature::NO_FEATURE;_front = false;_order=0;} - - /*! Copy constructor */ - inline WXEdge(WXEdge& iBrother) - : WEdge(iBrother) - {_nature = iBrother.nature();_front = iBrother._front;_order = iBrother._order;} - virtual WEdge * duplicate() - { - WXEdge *clone = new WXEdge(*this); - return clone; - } - - virtual ~WXEdge() - {} - - virtual void Reset(){ - _nature = _nature & ~Nature::SILHOUETTE; - _nature = _nature & ~Nature::SUGGESTIVE_CONTOUR; - } - - /*! accessors */ - inline WXNature nature() {return _nature;} - inline bool front() {return _front;} - inline int order() const {return _order;} - - /*! modifiers */ - inline void setFront(bool iFront) {_front = iFront;} - inline void setNature(WXNature iNature) {_nature = iNature;} - inline void AddNature(WXNature iNature) {_nature = _nature|iNature;} - inline void setOrder(int i) {_order = i;} - + inline WXEdge() : WEdge() + { + _nature = Nature::NO_FEATURE; + _front = false; + _order = 0; + } + + inline WXEdge(WOEdge *iOEdge) : WEdge(iOEdge) + { + _nature = Nature::NO_FEATURE; + _front = false; + _order = 0; + } + + inline WXEdge(WOEdge *iaOEdge, WOEdge *ibOEdge) : WEdge(iaOEdge, ibOEdge) + { + _nature = Nature::NO_FEATURE; + _front = false; + _order = 0; + } + + /*! Copy constructor */ + inline WXEdge(WXEdge& iBrother) : WEdge(iBrother) + { + _nature = iBrother.nature(); + _front = iBrother._front; + _order = iBrother._order; + } + + virtual WEdge *duplicate() + { + WXEdge *clone = new WXEdge(*this); + return clone; + } + + virtual ~WXEdge() {} + + virtual void Reset() + { + _nature = _nature & ~Nature::SILHOUETTE; + _nature = _nature & ~Nature::SUGGESTIVE_CONTOUR; + } + + /*! accessors */ + inline WXNature nature() + { + return _nature; + } + + inline bool front() + { + return _front; + } + + inline int order() const + { + return _order; + } + + /*! modifiers */ + inline void setFront(bool iFront) + { + _front = iFront; + } + + inline void setNature(WXNature iNature) + { + _nature = iNature; + } + + inline void AddNature(WXNature iNature) + { + _nature = _nature | iNature; + } + + inline void setOrder(int i) + { + _order = i; + } }; - /**********************************/ - /* */ - /* */ - /* WXFace */ - /* */ - /* */ - /**********************************/ +/********************************** + * * + * * + * WXFace * + * * + * * + **********************************/ /*! Class to store a smooth edge (i.e Hertzman & Zorin smooth silhouette edges) */ -class WXSmoothEdge{ +class WXSmoothEdge +{ public: - typedef enum{ - EDGE_EDGE, - VERTEX_EDGE, - EDGE_VERTEX - } Configuration; - - WOEdge *_woea; // Oriented edge from which the silhouette edge starts - WOEdge *_woeb; // Oriented edge where the silhouette edge ends - real _ta; // The silhouette starting point's coordinates are : _woea[0]+ta*(_woea[1]-_woea[0]) - real _tb; // The silhouette ending point's coordinates are : _woeb[0]+ta*(_woeb[1]-_woeb[0]) - bool _front; - Configuration _config; - - WXSmoothEdge(){ - _woea = 0; - _woeb = 0; - _ta = 0; - _tb = 0; - _front = false; - _config = EDGE_EDGE; - } - WXSmoothEdge(const WXSmoothEdge& iBrother){ - _woea = iBrother._woea; - _woeb = iBrother._woeb; - _ta = iBrother._ta; - _tb = iBrother._tb; - _config = iBrother._config; - _front = iBrother._front; - } - ~WXSmoothEdge() {} - - inline WOEdge * woea() {return _woea;} - inline WOEdge * woeb() {return _woeb;} - inline real ta() const {return _ta;} - inline real tb() const {return _tb;} - inline bool front() const {return _front;} - inline Configuration configuration() const {return _config;} - - /*! modifiers */ - inline void setWOeA(WOEdge *iwoea) {_woea = iwoea;} - inline void setWOeB(WOEdge *iwoeb) {_woeb = iwoeb;} - inline void setTa(real ta) {_ta = ta;} - inline void setTb(real tb) {_tb = tb;} - inline void setFront(bool iFront) {_front = iFront;} - inline void setConfiguration(Configuration iConf) {_config = iConf;} - + typedef enum { + EDGE_EDGE, + VERTEX_EDGE, + EDGE_VERTEX, + } Configuration; + + WOEdge *_woea; // Oriented edge from which the silhouette edge starts + WOEdge *_woeb; // Oriented edge where the silhouette edge ends + real _ta; // The silhouette starting point's coordinates are : _woea[0]+ta*(_woea[1]-_woea[0]) + real _tb; // The silhouette ending point's coordinates are : _woeb[0]+ta*(_woeb[1]-_woeb[0]) + bool _front; + Configuration _config; + + WXSmoothEdge() + { + _woea = NULL; + _woeb = NULL; + _ta = 0; + _tb = 0; + _front = false; + _config = EDGE_EDGE; + } + + WXSmoothEdge(const WXSmoothEdge& iBrother) + { + _woea = iBrother._woea; + _woeb = iBrother._woeb; + _ta = iBrother._ta; + _tb = iBrother._tb; + _config = iBrother._config; + _front = iBrother._front; + } + + ~WXSmoothEdge() {} + + inline WOEdge *woea() + { + return _woea; + } + + inline WOEdge *woeb() + { + return _woeb; + } + + inline real ta() const + { + return _ta; + } + + inline real tb() const + { + return _tb; + } + + inline bool front() const + { + return _front; + } + + inline Configuration configuration() const + { + return _config; + } + + /*! modifiers */ + inline void setWOeA(WOEdge *iwoea) + { + _woea = iwoea; + } + + inline void setWOeB(WOEdge *iwoeb) + { + _woeb = iwoeb; + } + + inline void setTa(real ta) + { + _ta = ta; + } + + inline void setTb(real tb) + { + _tb = tb; + } + + inline void setFront(bool iFront) + { + _front = iFront; + } + + inline void setConfiguration(Configuration iConf) + { + _config = iConf; + } }; -/* Class to store a value per vertex and a smooth edge. - * The WXFace stores a list of these + +/* Class to store a value per vertex and a smooth edge. + * The WXFace stores a list of these */ class WXFace; -class LIB_WINGED_EDGE_EXPORT WXFaceLayer{ + +class LIB_WINGED_EDGE_EXPORT WXFaceLayer +{ public: - void * userdata; - WXFace * _pWXFace; - vector _DotP;// in case of silhouette: the values obtained when computing the normal-view direction - // dot product. _DotP[i] is this value for the vertex i for that - // face. - WXSmoothEdge * _pSmoothEdge; - WXNature _Nature; - - //oldtmp values - unsigned _nPosDotP; // count the number of positive dot products for vertices. - // if this number is != 0 and !=_DotP.size() -> it is a silhouette fac - - unsigned _nNullDotP; // count the number of null dot products for vertices. - unsigned _ClosestPointIndex; - bool _viewDependant; - - WXFaceLayer(WXFace *iFace, WXNature iNature, bool viewDependant){ - _pWXFace = iFace; - _pSmoothEdge = 0; - _nPosDotP = 0; - _nNullDotP=0; - _Nature = iNature; - _viewDependant = viewDependant; - userdata = 0; - } - WXFaceLayer(const WXFaceLayer& iBrother){ - _pWXFace = iBrother._pWXFace; - _pSmoothEdge = 0; - _DotP = iBrother._DotP; - _nPosDotP = iBrother._nPosDotP; - _nNullDotP = iBrother._nNullDotP; - _Nature = iBrother._Nature; - if(0 != iBrother._pSmoothEdge) - { - _pSmoothEdge = new WXSmoothEdge(*(iBrother._pSmoothEdge)); - } - _viewDependant = iBrother._viewDependant; - userdata = 0; - } - virtual ~WXFaceLayer() { - if(!_DotP.empty()) - _DotP.clear(); - if(0 != _pSmoothEdge){ - delete _pSmoothEdge; - _pSmoothEdge = 0; - } - } - inline const real dotP(int i) const {return _DotP[i];} - inline unsigned nPosDotP() const {return _nPosDotP;} - inline unsigned nNullDotP() const {return _nNullDotP;} - inline int closestPointIndex() const {return _ClosestPointIndex;} - inline Nature::EdgeNature nature() const {return _Nature;} - inline bool hasSmoothEdge() const {if(_pSmoothEdge) return true; return false;} - inline WXFace * getFace() {return _pWXFace;} - inline WXSmoothEdge * getSmoothEdge() {return _pSmoothEdge;} - inline bool isViewDependant() const {return _viewDependant;} - inline void setClosestPointIndex(int iIndex) {_ClosestPointIndex = iIndex;} - - inline void removeSmoothEdge() { - if(!_DotP.empty()) - _DotP.clear(); - if (_pSmoothEdge) { - delete _pSmoothEdge; - _pSmoothEdge = 0; - } - } - - /*! If one of the face layer vertex has a DotP equal - * to 0, this method returns the vertex where it happens - */ - unsigned int Get0VertexIndex() const ; - - /*! In case one of the edge of the triangle - * is a smooth edge, this method - * allows to retrieve the concerned edge - */ - unsigned int GetSmoothEdgeIndex() const; - /*! retrieves the edges of the triangle for which - * the signs are different (a null value is not considered) for the dotp - * values at each edge extrimity - */ - void RetrieveCuspEdgesIndices(vector& oCuspEdges); - WXSmoothEdge * BuildSmoothEdge(); - inline void setDotP(const vector& iDotP) {_DotP = iDotP;} - inline void PushDotP(real iDotP) { - _DotP.push_back(iDotP); - if(iDotP > 0) - ++_nPosDotP; - if(iDotP == 0) - ++_nNullDotP; - } - inline void ReplaceDotP(unsigned int index, real newDotP){ - _DotP[index] = newDotP; - updateDotPInfos(); - } - inline void updateDotPInfos() { - _nPosDotP = 0; - _nNullDotP = 0; - for(vector::iterator d=_DotP.begin(), dend=_DotP.end(); - d!=dend; - ++d){ - if((*d) > 0) - ++_nPosDotP; - if((*d) == 0) - ++_nNullDotP; - } - } + void *userdata; + WXFace *_pWXFace; + // in case of silhouette: the values obtained when computing the normal-view direction dot product. _DotP[i] is + // this value for the vertex i for that face. + vector _DotP; + WXSmoothEdge *_pSmoothEdge; + WXNature _Nature; + + //oldtmp values + // count the number of positive dot products for vertices. + // if this number is != 0 and !=_DotP.size() -> it is a silhouette fac + unsigned _nPosDotP; + + unsigned _nNullDotP; // count the number of null dot products for vertices. + unsigned _ClosestPointIndex; + bool _viewDependant; + + WXFaceLayer(WXFace *iFace, WXNature iNature, bool viewDependant) + { + _pWXFace = iFace; + _pSmoothEdge = NULL; + _nPosDotP = 0; + _nNullDotP = 0; + _Nature = iNature; + _viewDependant = viewDependant; + userdata = NULL; + } + + WXFaceLayer(const WXFaceLayer& iBrother) + { + _pWXFace = iBrother._pWXFace; + _pSmoothEdge = NULL; + _DotP = iBrother._DotP; + _nPosDotP = iBrother._nPosDotP; + _nNullDotP = iBrother._nNullDotP; + _Nature = iBrother._Nature; + if (iBrother._pSmoothEdge) { // XXX ? It's set to null a few lines above! + _pSmoothEdge = new WXSmoothEdge(*(iBrother._pSmoothEdge)); + } + _viewDependant = iBrother._viewDependant; + userdata = NULL; + } + + virtual ~WXFaceLayer() + { + if (!_DotP.empty()) + _DotP.clear(); + if (_pSmoothEdge) { + delete _pSmoothEdge; + _pSmoothEdge = NULL; + } + } + + inline const real dotP(int i) const + { + return _DotP[i]; + } + + inline unsigned nPosDotP() const + { + return _nPosDotP; + } + + inline unsigned nNullDotP() const + { + return _nNullDotP; + } + + inline int closestPointIndex() const + { + return _ClosestPointIndex; + } + + inline Nature::EdgeNature nature() const + { + return _Nature; + } + + inline bool hasSmoothEdge() const + { + if (_pSmoothEdge) + return true; + return false; + } + + inline WXFace *getFace() + { + return _pWXFace; + } + + inline WXSmoothEdge *getSmoothEdge() + { + return _pSmoothEdge; + } + + inline bool isViewDependant() const + { + return _viewDependant; + } + + inline void setClosestPointIndex(int iIndex) + { + _ClosestPointIndex = iIndex; + } + + inline void removeSmoothEdge() + { + if (!_DotP.empty()) + _DotP.clear(); + if (_pSmoothEdge) { + delete _pSmoothEdge; + _pSmoothEdge = NULL; + } + } + + /*! If one of the face layer vertex has a DotP equal to 0, this method returns the vertex where it happens */ + unsigned int Get0VertexIndex() const; + + /*! In case one of the edge of the triangle is a smooth edge, this method allows to retrieve the concerned edge */ + unsigned int GetSmoothEdgeIndex() const; + + /*! retrieves the edges of the triangle for which the signs are different (a null value is not considered) for + * the dotp values at each edge extrimity + */ + void RetrieveCuspEdgesIndices(vector& oCuspEdges); + + WXSmoothEdge *BuildSmoothEdge(); + + inline void setDotP(const vector& iDotP) + { + _DotP = iDotP; + } + + inline void PushDotP(real iDotP) + { + _DotP.push_back(iDotP); + if (iDotP > 0) + ++_nPosDotP; + if (iDotP == 0) + ++_nNullDotP; + } + + inline void ReplaceDotP(unsigned int index, real newDotP) + { + _DotP[index] = newDotP; + updateDotPInfos(); + } + + inline void updateDotPInfos() + { + _nPosDotP = 0; + _nNullDotP = 0; + for (vector::iterator d = _DotP.begin(), dend = _DotP.end(); d != dend; ++d) { + if ((*d) > 0) + ++_nPosDotP; + if ((*d) == 0) + ++_nNullDotP; + } + } }; - class WXFace : public WFace { protected: - Vec3r _center; // center of the face - real _Z; // distance from viewpoint to the center of the face - bool _front; // flag to tell whether the face is front facing or back facing - real _dotp; // value obtained when computing the normal-viewpoint dot product - - vector _SmoothLayers; // The data needed to store one or several smooth edges that traverse the face + Vec3r _center; // center of the face + real _Z; // distance from viewpoint to the center of the face + bool _front; // flag to tell whether the face is front facing or back facing + real _dotp; // value obtained when computing the normal-viewpoint dot product + + vector _SmoothLayers; // The data needed to store one or several smooth edges that traverse the face + public: - inline WXFace() : WFace() {_Z=0.0;_front = false;} - /*! Copy constructor */ - WXFace(WXFace& iBrother) - : WFace(iBrother) - { - _center = iBrother.center(); - _Z = iBrother.Z(); - _front = iBrother.front(); - for(vector::iterator wxf = iBrother._SmoothLayers.begin(), wxfend = iBrother._SmoothLayers.end(); - wxf != wxfend; - ++wxf){ - _SmoothLayers.push_back(new WXFaceLayer(**wxf)); - } - } - virtual WFace * duplicate() - { - WXFace * clone = new WXFace(*this); - return clone; - } - - virtual ~WXFace() { - if(!_SmoothLayers.empty()){ - for(vector::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end(); - wxf != wxfend; - ++wxf){ - delete (*wxf); - } - _SmoothLayers.clear(); - } - } - - /*! designed to build a specialized WEdge - * for use in MakeEdge - */ - virtual WEdge * instanciateEdge() const {return new WXEdge;} - - /*! accessors */ - inline Vec3r& center() {return _center;} - inline real Z() {return _Z;} - inline bool front() {return _front;} - inline real dotp() {return _dotp;} - inline bool hasSmoothEdges() const { - for(vector::const_iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end(); - wxf != wxfend; - ++wxf){ - if( ((*wxf)->hasSmoothEdge())){ - return true; - } - } - return false; - } - vector& getSmoothLayers() {return _SmoothLayers;} - /*! retrieve the smooth edges that match the Nature given as argument */ - void retrieveSmoothEdges(WXNature iNature, vector& oSmoothEdges){ - for(vector::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end(); - wxf != wxfend; - ++wxf){ - if( ((*wxf)->hasSmoothEdge()) && ((*wxf)->_Nature & iNature) ){ - oSmoothEdges.push_back((*wxf)->_pSmoothEdge); - } - } - } - void retrieveSmoothEdgesLayers(WXNature iNature, vector& oSmoothEdgesLayers){ - for(vector::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end(); - wxf != wxfend; - ++wxf){ - if( ((*wxf)->hasSmoothEdge()) && ((*wxf)->_Nature & iNature) ){ - oSmoothEdgesLayers.push_back((*wxf)); - } - } - } - void retrieveSmoothLayers(WXNature iNature, vector& oSmoothLayers){ - for(vector::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end(); - wxf != wxfend; - ++wxf){ - if((*wxf)->_Nature & iNature){ - oSmoothLayers.push_back(*wxf); - } - } - } - /*! modifiers */ - inline void setCenter(const Vec3r& iCenter) {_center = iCenter;} - void ComputeCenter(); - inline void setZ(real z) {_Z = z;} - inline void setFront(bool iFront) {_front = iFront;} - inline void setDotP(real iDotP) - { - _dotp = iDotP; - if(_dotp > 0) - _front = true; - else - _front = false; - } - inline void AddSmoothLayer(WXFaceLayer * iLayer){ - _SmoothLayers.push_back(iLayer); - } - inline void Reset() { - vector layersToKeep; - for(vector::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end(); - wxf != wxfend; - ++wxf){ - if((*wxf)->isViewDependant()) - delete (*wxf); - else - layersToKeep.push_back(*wxf); - } - _SmoothLayers = layersToKeep; - } - /*! Clears everything */ - inline void Clear() { - for(vector::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end(); - wxf != wxfend; - ++wxf){ - delete (*wxf); - } - _SmoothLayers.clear(); - } - virtual void ResetUserData() { - WFace::ResetUserData(); - for(vector::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end(); - wxf != wxfend; - ++wxf){ - (*wxf)->userdata = 0; - } - } + inline WXFace() : WFace() + { + _Z = 0.0; + _front = false; + } + + /*! Copy constructor */ + WXFace(WXFace& iBrother) : WFace(iBrother) + { + _center = iBrother.center(); + _Z = iBrother.Z(); + _front = iBrother.front(); + for (vector::iterator wxf = iBrother._SmoothLayers.begin(), wxfend = iBrother._SmoothLayers.end(); + wxf != wxfend; + ++wxf) + { + _SmoothLayers.push_back(new WXFaceLayer(**wxf)); + } + } + + virtual WFace *duplicate() + { + WXFace *clone = new WXFace(*this); + return clone; + } + + virtual ~WXFace() + { + if (!_SmoothLayers.empty()) { + for (vector::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end(); + wxf != wxfend; + ++wxf) + { + delete (*wxf); + } + _SmoothLayers.clear(); + } + } + + /*! designed to build a specialized WEdge for use in MakeEdge */ + virtual WEdge *instanciateEdge() const + { + return new WXEdge; + } + + /*! accessors */ + inline Vec3r& center() + { + return _center; + } + + inline real Z() + { + return _Z; + } + + inline bool front() + { + return _front; + } + + inline real dotp() + { + return _dotp; + } + + inline bool hasSmoothEdges() const + { + for (vector::const_iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end(); + wxf != wxfend; + ++wxf) + { + if ((*wxf)->hasSmoothEdge()) { + return true; + } + } + return false; + } + + vector& getSmoothLayers() + { + return _SmoothLayers; + } + + /*! retrieve the smooth edges that match the Nature given as argument */ + void retrieveSmoothEdges(WXNature iNature, vector& oSmoothEdges) + { + for (vector::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end(); + wxf != wxfend; + ++wxf) + { + if ((*wxf)->hasSmoothEdge() && ((*wxf)->_Nature & iNature)) { + oSmoothEdges.push_back((*wxf)->_pSmoothEdge); + } + } + } + + void retrieveSmoothEdgesLayers(WXNature iNature, vector& oSmoothEdgesLayers) + { + for (vector::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end(); + wxf != wxfend; + ++wxf) + { + if ((*wxf)->hasSmoothEdge() && ((*wxf)->_Nature & iNature)) { + oSmoothEdgesLayers.push_back((*wxf)); + } + } + } + + void retrieveSmoothLayers(WXNature iNature, vector& oSmoothLayers) + { + for (vector::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end(); + wxf != wxfend; + ++wxf) + { + if ((*wxf)->_Nature & iNature) { + oSmoothLayers.push_back(*wxf); + } + } + } + + /*! modifiers */ + inline void setCenter(const Vec3r& iCenter) + { + _center = iCenter; + } + + void ComputeCenter(); + + inline void setZ(real z) + { + _Z = z; + } + + inline void setFront(bool iFront) + { + _front = iFront; + } + + inline void setDotP(real iDotP) + { + _dotp = iDotP; + if (_dotp > 0) + _front = true; + else + _front = false; + } + + inline void AddSmoothLayer(WXFaceLayer *iLayer) + { + _SmoothLayers.push_back(iLayer); + } + + inline void Reset() + { + vector layersToKeep; + for (vector::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end(); + wxf != wxfend; + ++wxf) + { + if ((*wxf)->isViewDependant()) + delete (*wxf); + else + layersToKeep.push_back(*wxf); + } + _SmoothLayers = layersToKeep; + } + + /*! Clears everything */ + inline void Clear() + { + for (vector::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end(); + wxf != wxfend; + ++wxf) + { + delete (*wxf); + } + _SmoothLayers.clear(); + } + + virtual void ResetUserData() + { + WFace::ResetUserData(); + for (vector::iterator wxf = _SmoothLayers.begin(), wxfend = _SmoothLayers.end(); + wxf != wxfend; + ++wxf) + { + (*wxf)->userdata = NULL; + } + } }; - /**********************************/ - /* */ - /* */ - /* WXShape */ - /* */ - /* */ - /**********************************/ - +/********************************** + * * + * * + * WXShape * + * * + * * + **********************************/ class WXShape : public WShape { public: - typedef WXShape type_name; + typedef WXShape type_name; + protected: - bool _computeViewIndependant; // flag to indicate whether the view independant stuff must be computed or not + bool _computeViewIndependant; // flag to indicate whether the view independant stuff must be computed or not + public: - inline WXShape() : WShape() {_computeViewIndependant = true;} - /*! copy constructor */ - inline WXShape(WXShape& iBrother) - :WShape(iBrother) - { - _computeViewIndependant = iBrother._computeViewIndependant; - } - virtual WShape * duplicate() - { - WXShape *clone = new WXShape(*this); - return clone; - } - - virtual ~WXShape() - { - } - - inline bool getComputeViewIndependantFlag() const {return _computeViewIndependant;} - inline void setComputeViewIndependantFlag(bool iFlag) {_computeViewIndependant = iFlag;} - - /*! designed to build a specialized WFace - * for use in MakeFace - */ - virtual WFace * instanciateFace() const {return new WXFace;} - - /*! adds a new face to the shape - * returns the built face. - * iVertexList - * List of face's vertices. These vertices are - * not added to the WShape vertex list; they are - * supposed to be already stored when calling MakeFace. - * The order in which the vertices are stored in the list - * determines the face's edges orientation and (so) the - * face orientation. - */ - virtual WFace * MakeFace(vector& iVertexList, vector& iFaceEdgeMarksList, unsigned iMaterialIndex); - - /*! adds a new face to the shape. The difference with - * the previous method is that this one is designed - * to build a WingedEdge structure for which there are - * per vertex normals, opposed to per face normals. - * returns the built face. - * iVertexList - * List of face's vertices. These vertices are - * not added to the WShape vertex list; they are - * supposed to be already stored when calling MakeFace. - * The order in which the vertices are stored in the list - * determines the face's edges orientation and (so) the - * face orientation. - * iNormalsList - * The list of normals, iNormalsList[i] corresponding to the - * normal of the vertex iVertexList[i] for that face. - * iTexCoordsList - * The list of tex coords, iTexCoordsList[i] corresponding to the - * normal of the vertex iVertexList[i] for that face. - */ - virtual WFace * MakeFace(vector& iVertexList, vector& iNormalsList, vector& iTexCoordsList, vector& iFaceEdgeMarksList, unsigned iMaterialIndex); - - /*! Reset all edges and vertices flags (which might - * have been set up on a previous pass) - */ - virtual void Reset(){ - // Reset Edges - vector& wedges = getEdgeList(); - for(vector::iterator we=wedges.begin(),weend=wedges.end(); - we!=weend; - we++){ - ((WXEdge*)(*we))->Reset(); - } - - //Reset faces: - vector& wfaces = GetFaceList(); - for(vector::iterator wf=wfaces.begin(),wfend=wfaces.end(); - wf!=wfend; - wf++){ - ((WXFace*)(*wf))->Reset(); - } - } - /*! accessors */ + inline WXShape() : WShape() + { + _computeViewIndependant = true; + } + + /*! copy constructor */ + inline WXShape(WXShape& iBrother) : WShape(iBrother) + { + _computeViewIndependant = iBrother._computeViewIndependant; + } + + virtual WShape *duplicate() + { + WXShape *clone = new WXShape(*this); + return clone; + } + + virtual ~WXShape() {} + + inline bool getComputeViewIndependantFlag() const + { + return _computeViewIndependant; + } + + inline void setComputeViewIndependantFlag(bool iFlag) + { + _computeViewIndependant = iFlag; + } + + /*! designed to build a specialized WFace for use in MakeFace */ + virtual WFace *instanciateFace() const + { + return new WXFace; + } + + /*! adds a new face to the shape returns the built face. + * iVertexList + * List of face's vertices. These vertices are not added to the WShape vertex list; they are supposed + * to be already stored when calling MakeFace. The order in which the vertices are stored in the list + * determines the face's edges orientation and (so) the face orientation. + */ + virtual WFace *MakeFace(vector& iVertexList, vector& iFaceEdgeMarksList, unsigned iMaterialIndex); + + /*! adds a new face to the shape. The difference with the previous method is that this one is designed to build + * a WingedEdge structure for which there are per vertex normals, opposed to per face normals. + * returns the built face. + * iVertexList + * List of face's vertices. These vertices are not added to the WShape vertex list; they are supposed to be + * already stored when calling MakeFace. + * The order in which the vertices are stored in the list determines the face's edges orientation and (so) the + * face orientation. + * iNormalsList + * The list of normals, iNormalsList[i] corresponding to the normal of the vertex iVertexList[i] for that face. + * iTexCoordsList + * The list of tex coords, iTexCoordsList[i] corresponding to the normal of the vertex iVertexList[i] for + * that face. + */ + virtual WFace *MakeFace(vector& iVertexList, vector& iNormalsList, vector& iTexCoordsList, + vector& iFaceEdgeMarksList, unsigned iMaterialIndex); + + /*! Reset all edges and vertices flags (which might have been set up on a previous pass) */ + virtual void Reset() + { + // Reset Edges + vector& wedges = getEdgeList(); + for (vector::iterator we = wedges.begin(), weend = wedges.end(); we != weend; ++we) { + ((WXEdge*)(*we))->Reset(); + } + + //Reset faces: + vector& wfaces = GetFaceList(); + for (vector::iterator wf = wfaces.begin(), wfend = wfaces.end(); wf != wfend; ++wf) { + ((WXFace*)(*wf))->Reset(); + } + } + /*! accessors */ }; /* - - ############################################# - ############################################# - ############################################# - ###### ###### - ###### I M P L E M E N T A T I O N ###### - ###### ###### - ############################################# - ############################################# - ############################################# - + +############################################# +############################################# +############################################# +###### ###### +###### I M P L E M E N T A T I O N ###### +###### ###### +############################################# +############################################# +############################################# + */ /* for inline functions */ -bool WXVertex::isFeature() -{ - int counter = 0; - vector& vedges = GetEdges(); - for(vector::iterator ve=vedges.begin(), vend=vedges.end(); - ve!=vend; - ve++) - { - if(((WXEdge*)(*ve))->nature() != Nature::NO_FEATURE) - counter++; - } - - if((counter == 1) || (counter > 2)) - return true; - - return false; +bool WXVertex::isFeature() +{ + int counter = 0; + vector& vedges = GetEdges(); + for (vector::iterator ve = vedges.begin(), vend = vedges.end(); ve != vend; ++ve) { + if (((WXEdge *)(*ve))->nature() != Nature::NO_FEATURE) + counter++; + } + + if ((counter == 1) || (counter > 2)) + return true; + return false; } - -#endif +#endif // __FREESTYLE_WX_EDGE_H__ \ No newline at end of file diff --git a/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp b/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp index b29f0c7e9ee..51e93f34fa3 100644 --- a/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp +++ b/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.cpp @@ -1,46 +1,58 @@ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/freestyle/intern/winged_edge/WSBuilder.cpp + * \ingroup freestyle + * \brief Class inherited from WingedEdgeBuilder and designed to build a WX (WingedEdge + extended info + * (silhouette etc...)) structure from a polygonal model + * \author Stephane Grabli + * \date 28/05/2003 + */ -#include "WXEdgeBuilder.h" #include "WXEdge.h" +#include "WXEdgeBuilder.h" void WXEdgeBuilder::visitIndexedFaceSet(IndexedFaceSet& ifs) { - if (_pRenderMonitor && _pRenderMonitor->testBreak()) - return; - WXShape *shape = new WXShape; - buildWShape(*shape, ifs); - shape->setId(ifs.getId().getFirst()); - shape->setName(ifs.getName()); - //ifs.setId(shape->GetId()); + if (_pRenderMonitor && _pRenderMonitor->testBreak()) + return; + WXShape *shape = new WXShape; + buildWShape(*shape, ifs); + shape->setId(ifs.getId().getFirst()); + shape->setName(ifs.getName()); + //ifs.setId(shape->GetId()); } -void WXEdgeBuilder::buildWVertices(WShape& shape, - const real *vertices, - unsigned vsize) { - WXVertex *vertex; - for (unsigned i = 0; i < vsize; i += 3) { - vertex = new WXVertex(Vec3r(vertices[i], - vertices[i + 1], - vertices[i + 2])); - vertex->setId(i / 3); - shape.AddVertex(vertex); - } -} +void WXEdgeBuilder::buildWVertices(WShape& shape, const real *vertices, unsigned vsize) +{ + WXVertex *vertex; + for (unsigned int i = 0; i < vsize; i += 3) { + vertex = new WXVertex(Vec3r(vertices[i], vertices[i + 1], vertices[i + 2])); + vertex->setId(i / 3); + shape.AddVertex(vertex); + } +} \ No newline at end of file diff --git a/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.h b/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.h index b646d66a285..91e9b389f7c 100644 --- a/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.h +++ b/source/blender/freestyle/intern/winged_edge/WXEdgeBuilder.h @@ -1,51 +1,54 @@ -#ifndef WXEDGEBUILDER_H -# define WXEDGEBUILDER_H +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ -// -// Filename : WSBuilder.h -// Author(s) : Stephane Grabli -// Purpose : Class inherited from WingedEdgeBuilder and -// designed to build a WX (WingedEdge + extended info(silhouette etc...)) -// structure from a polygonal model -// Date of creation : 28/05/03 -// -/////////////////////////////////////////////////////////////////////////////// +#ifndef __FREESTYLE_WX_EDGE_BUILDER_H__ +#define __FREESTYLE_WX_EDGE_BUILDER_H__ +/** \file blender/freestyle/intern/winged_edge/WSBuilder.h + * \ingroup freestyle + * \brief Class inherited from WingedEdgeBuilder and designed to build a WX (WingedEdge + extended info + * (silhouette etc...)) structure from a polygonal model + * \author Stephane Grabli + * \date 28/05/2003 + */ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +#include "WingedEdgeBuilder.h" -# include "WingedEdgeBuilder.h" -# include "../scene_graph/IndexedFaceSet.h" +#include "../scene_graph/IndexedFaceSet.h" class LIB_WINGED_EDGE_EXPORT WXEdgeBuilder : public WingedEdgeBuilder { public: WXEdgeBuilder() : WingedEdgeBuilder() {} - virtual ~WXEdgeBuilder() {} - VISIT_DECL(IndexedFaceSet) + virtual ~WXEdgeBuilder() {} + VISIT_DECL(IndexedFaceSet) protected: - virtual void buildWVertices(WShape& shape, - const real *vertices, - unsigned vsize); + virtual void buildWVertices(WShape& shape, const real *vertices, unsigned vsize); }; -#endif // WXEDGEBUILDER_H +#endif // __FREESTYLE_WX_EDGE_BUILDER_H__ \ No newline at end of file diff --git a/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp index e56ac0f9c42..4ef34bbe3ee 100644 --- a/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp +++ b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp @@ -1,386 +1,373 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/freestyle/intern/winged_edge/WingedEdgeBuilder.cpp + * \ingroup freestyle + * \brief Class to render a WingedEdge data structure from a polyhedral data structure organized in nodes + * of a scene graph + * \author Stephane Grabli + * \date 28/05/2003 + */ -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// +#include + +#include "WingedEdgeBuilder.h" #include "../geometry/GeomUtils.h" + #include "../scene_graph/NodeShape.h" -#include "WingedEdgeBuilder.h" -#include + using namespace std; -void WingedEdgeBuilder::visitIndexedFaceSet(IndexedFaceSet& ifs) { - if (_pRenderMonitor && _pRenderMonitor->testBreak()) - return; - WShape *shape = new WShape; - buildWShape(*shape, ifs); - shape->setId(ifs.getId().getFirst()); - //ifs.setId(shape->GetId()); +void WingedEdgeBuilder::visitIndexedFaceSet(IndexedFaceSet& ifs) +{ + if (_pRenderMonitor && _pRenderMonitor->testBreak()) + return; + WShape *shape = new WShape; + buildWShape(*shape, ifs); + shape->setId(ifs.getId().getFirst()); + //ifs.setId(shape->GetId()); } -void WingedEdgeBuilder::visitNodeShape(NodeShape& ns) { - //Sets the current material to iShapeode->material: - _current_frs_material = &(ns.frs_material()); +void WingedEdgeBuilder::visitNodeShape(NodeShape& ns) +{ + //Sets the current material to iShapeode->material: + _current_frs_material = &(ns.frs_material()); } -void WingedEdgeBuilder::visitNodeTransform(NodeTransform& tn) { - if(!_current_matrix) { - _current_matrix = new Matrix44r(tn.matrix()); - return; - } +void WingedEdgeBuilder::visitNodeTransform(NodeTransform& tn) +{ + if (!_current_matrix) { + _current_matrix = new Matrix44r(tn.matrix()); + return; + } - _matrices_stack.push_back(_current_matrix); - Matrix44r *new_matrix = new Matrix44r(*_current_matrix * tn.matrix()); - _current_matrix = new_matrix; + _matrices_stack.push_back(_current_matrix); + Matrix44r *new_matrix = new Matrix44r(*_current_matrix * tn.matrix()); + _current_matrix = new_matrix; } -void WingedEdgeBuilder::visitNodeTransformAfter(NodeTransform&) { - if(_current_matrix) - delete _current_matrix; +void WingedEdgeBuilder::visitNodeTransformAfter(NodeTransform&) +{ + if (_current_matrix) + delete _current_matrix; - if(_matrices_stack.empty()) { - _current_matrix = NULL; - return; - } + if (_matrices_stack.empty()) { + _current_matrix = NULL; + return; + } - _current_matrix = _matrices_stack.back(); - _matrices_stack.pop_back(); + _current_matrix = _matrices_stack.back(); + _matrices_stack.pop_back(); } -void WingedEdgeBuilder::buildWShape(WShape& shape, IndexedFaceSet& ifs) { - unsigned vsize = ifs.vsize(); - unsigned nsize = ifs.nsize(); - //soc unused - unsigned tsize = ifs.tsize(); +void WingedEdgeBuilder::buildWShape(WShape& shape, IndexedFaceSet& ifs) +{ + unsigned int vsize = ifs.vsize(); + unsigned int nsize = ifs.nsize(); + //soc unused - unsigned tsize = ifs.tsize(); - const real* vertices = ifs.vertices(); - const real* normals = ifs.normals(); - const real* texCoords = ifs.texCoords(); + const real *vertices = ifs.vertices(); + const real *normals = ifs.normals(); + const real *texCoords = ifs.texCoords(); - real* new_vertices; - real* new_normals; + real *new_vertices; + real *new_normals; new_vertices = new real[vsize]; new_normals = new real[nsize]; - // transform coordinates from local to world system - if(_current_matrix) { - transformVertices(vertices, vsize, *_current_matrix, new_vertices); - transformNormals(normals, nsize, *_current_matrix, new_normals); - } - else { - memcpy(new_vertices, vertices, vsize * sizeof(*new_vertices)); - memcpy(new_normals, normals, nsize * sizeof(*new_normals)); - } + // transform coordinates from local to world system + if (_current_matrix) { + transformVertices(vertices, vsize, *_current_matrix, new_vertices); + transformNormals(normals, nsize, *_current_matrix, new_normals); + } + else { + memcpy(new_vertices, vertices, vsize * sizeof(*new_vertices)); + memcpy(new_normals, normals, nsize * sizeof(*new_normals)); + } - const IndexedFaceSet::TRIANGLES_STYLE* faceStyle = ifs.trianglesStyle(); + const IndexedFaceSet::TRIANGLES_STYLE *faceStyle = ifs.trianglesStyle(); vector frs_materials; - if(ifs.msize()){ - const FrsMaterial*const* mats = ifs.frs_materials(); - for(unsigned i=0; i normalsSet; - vector& wvertices = shape.getVertexList(); - for(vector::iterator wv=wvertices.begin(), wvend=wvertices.end(); - wv!=wvend; - ++wv){ - if((*wv)->isBoundary()) - continue; - if ((*wv)->GetEdges().size() == 0) // This means that the WVertex has no incoming edges... (12-Sep-2011 T.K.) - continue; - normalsSet.clear(); - WVertex::face_iterator fit = (*wv)->faces_begin(); - WVertex::face_iterator fitend = (*wv)->faces_end(); - while(fit!=fitend){ - WFace *face = *fit; - normalsSet.insert(face->GetVertexNormal(*wv)); - if(normalsSet.size()!=1){ - break; - } - ++fit; - } - if(normalsSet.size()!=1){ - (*wv)->setSmooth(false); - } - } - // Adds the new WShape to the WingedEdge structure - _winged_edge->addWShape(&shape); + if (tindices) + tindices += numVertexPerFace[index]; + faceEdgeMarks++; + } + + delete[] new_vertices; + delete[] new_normals; + + // compute bbox + shape.ComputeBBox(); + // compute mean edge size: + shape.ComputeMeanEdgeSize(); + + // Parse the built winged-edge shape to update post-flags + set normalsSet; + vector& wvertices = shape.getVertexList(); + for (vector::iterator wv = wvertices.begin(), wvend = wvertices.end(); wv != wvend; ++wv) { + if ((*wv)->isBoundary()) + continue; + if ((*wv)->GetEdges().size() == 0) // This means that the WVertex has no incoming edges... (12-Sep-2011 T.K.) + continue; + normalsSet.clear(); + WVertex::face_iterator fit = (*wv)->faces_begin(); + WVertex::face_iterator fitend = (*wv)->faces_end(); + for (; fit != fitend; ++fit) { + WFace *face = *fit; + normalsSet.insert(face->GetVertexNormal(*wv)); + if (normalsSet.size() != 1) { + break; + } + } + if (normalsSet.size() !=1 ) { + (*wv)->setSmooth(false); + } + } + // Adds the new WShape to the WingedEdge structure + _winged_edge->addWShape(&shape); } -void WingedEdgeBuilder::buildWVertices(WShape& shape, - const real *vertices, - unsigned vsize) { - WVertex *vertex; - for (unsigned i = 0; i < vsize; i += 3) { - vertex = new WVertex(Vec3r(vertices[i], - vertices[i + 1], - vertices[i + 2])); - vertex->setId(i / 3); - shape.AddVertex(vertex); - } +void WingedEdgeBuilder::buildWVertices(WShape& shape, const real *vertices, unsigned vsize) +{ + WVertex *vertex; + for (unsigned int i = 0; i < vsize; i += 3) { + vertex = new WVertex(Vec3r(vertices[i], vertices[i + 1], vertices[i + 2])); + vertex->setId(i / 3); + shape.AddVertex(vertex); + } } -void WingedEdgeBuilder::buildTriangleStrip( const real *vertices, - const real *normals, - vector& iMaterials, - const real *texCoords, - const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks, - const unsigned *vindices, - const unsigned *nindices, - const unsigned *mindices, - const unsigned *tindices, - const unsigned nvertices) { - unsigned nDoneVertices = 2; // number of vertices already treated - unsigned nTriangle = 0; // number of the triangle currently being treated - //int nVertex = 0; // vertex number - - WShape* currentShape = _current_wshape; // the current shape being built - vector triangleVertices; - vector triangleNormals; - vector triangleTexCoords; - vector triangleFaceEdgeMarks; - - while(nDoneVertices < nvertices) - { - //clear the vertices list: - triangleVertices.clear(); - //Then rebuild it: - if(0 == nTriangle%2) // if nTriangle is even - { - triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle]/3]); - triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle+1]/3]); - triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle+2]/3]); - - triangleNormals.push_back(Vec3r(normals[nindices[nTriangle]],normals[nindices[nTriangle]+1], normals[nindices[nTriangle]+2])); - triangleNormals.push_back(Vec3r(normals[nindices[nTriangle+1]],normals[nindices[nTriangle+1]+1],normals[nindices[nTriangle+1]+2])); - triangleNormals.push_back(Vec3r(normals[nindices[nTriangle+2]], normals[nindices[nTriangle+2]+1], normals[nindices[nTriangle+2]+2])); - - if(texCoords){ - triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle]],texCoords[tindices[nTriangle]+1])); - triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle+1]],texCoords[tindices[nTriangle+1]+1])); - triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle+2]], texCoords[tindices[nTriangle+2]+1])); - } - } - else // if nTriangle is odd - { - triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle]/3]); - triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle+2]/3]); - triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle+1]/3]); - - triangleNormals.push_back(Vec3r(normals[nindices[nTriangle]],normals[nindices[nTriangle]+1], normals[nindices[nTriangle]+2])); - triangleNormals.push_back(Vec3r(normals[nindices[nTriangle+2]],normals[nindices[nTriangle+2]+1],normals[nindices[nTriangle+2]+2])); - triangleNormals.push_back(Vec3r(normals[nindices[nTriangle+1]], normals[nindices[nTriangle+1]+1], normals[nindices[nTriangle+1]+2])); - - if(texCoords){ - triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle]],texCoords[tindices[nTriangle]+1])); - triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle+2]],texCoords[tindices[nTriangle+2]+1])); - triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle+1]], texCoords[tindices[nTriangle+1]+1])); - } - } - triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[nTriangle/3] & IndexedFaceSet::FACE_MARK) != 0); - triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[nTriangle/3] & IndexedFaceSet::EDGE_MARK_V1V2) != 0); - triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[nTriangle/3] & IndexedFaceSet::EDGE_MARK_V2V3) != 0); - triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[nTriangle/3] & IndexedFaceSet::EDGE_MARK_V3V1) != 0); - if(mindices) - currentShape->MakeFace(triangleVertices, triangleNormals, triangleTexCoords, triangleFaceEdgeMarks, mindices[nTriangle/3]); - else +void WingedEdgeBuilder::buildTriangleStrip(const real *vertices, const real *normals, vector& iMaterials, + const real *texCoords, const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks, + const unsigned *vindices, const unsigned *nindices, const unsigned *mindices, + const unsigned *tindices, const unsigned nvertices) +{ + unsigned nDoneVertices = 2; // number of vertices already treated + unsigned nTriangle = 0; // number of the triangle currently being treated + //int nVertex = 0; // vertex number + + WShape *currentShape = _current_wshape; // the current shape being built + vector triangleVertices; + vector triangleNormals; + vector triangleTexCoords; + vector triangleFaceEdgeMarks; + + while (nDoneVertices < nvertices) { + //clear the vertices list: + triangleVertices.clear(); + //Then rebuild it: + if (0 == nTriangle % 2) { // if nTriangle is even + triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle] / 3]); + triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle + 1] / 3]); + triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle + 2] / 3]); + + triangleNormals.push_back(Vec3r(normals[nindices[nTriangle]], normals[nindices[nTriangle] + 1], + normals[nindices[nTriangle] + 2])); + triangleNormals.push_back(Vec3r(normals[nindices[nTriangle + 1]], normals[nindices[nTriangle + 1] + 1], + normals[nindices[nTriangle + 1] + 2])); + triangleNormals.push_back(Vec3r(normals[nindices[nTriangle + 2]], normals[nindices[nTriangle + 2] + 1], + normals[nindices[nTriangle + 2] + 2])); + + if (texCoords) { + triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle]], texCoords[tindices[nTriangle] + 1])); + triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle + 1]], + texCoords[tindices[nTriangle + 1] + 1])); + triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle + 2]], + texCoords[tindices[nTriangle + 2] + 1])); + } + } + else { // if nTriangle is odd + triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle] / 3]); + triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle + 2] / 3]); + triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle + 1] / 3]); + + triangleNormals.push_back(Vec3r(normals[nindices[nTriangle]], normals[nindices[nTriangle] + 1], + normals[nindices[nTriangle] + 2])); + triangleNormals.push_back(Vec3r(normals[nindices[nTriangle + 2]], normals[nindices[nTriangle + 2] + 1], + normals[nindices[nTriangle + 2] + 2])); + triangleNormals.push_back(Vec3r(normals[nindices[nTriangle + 1]], normals[nindices[nTriangle + 1] + 1], + normals[nindices[nTriangle + 1] + 2])); + + if (texCoords) { + triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle]], texCoords[tindices[nTriangle] + 1])); + triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle + 2]], + texCoords[tindices[nTriangle + 2] + 1])); + triangleTexCoords.push_back(Vec2r(texCoords[tindices[nTriangle + 1]], + texCoords[tindices[nTriangle + 1] + 1])); + } + } + triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[nTriangle / 3] & IndexedFaceSet::FACE_MARK) != 0); + triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[nTriangle / 3] & IndexedFaceSet::EDGE_MARK_V1V2) != 0); + triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[nTriangle / 3] & IndexedFaceSet::EDGE_MARK_V2V3) != 0); + triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[nTriangle / 3] & IndexedFaceSet::EDGE_MARK_V3V1) != 0); + if (mindices) { + currentShape->MakeFace(triangleVertices, triangleNormals, triangleTexCoords, triangleFaceEdgeMarks, + mindices[nTriangle / 3]); + } + else { currentShape->MakeFace(triangleVertices, triangleNormals, triangleTexCoords, triangleFaceEdgeMarks, 0); - nDoneVertices++; // with a strip, each triangle is one vertex more - nTriangle++; - } + } + nDoneVertices++; // with a strip, each triangle is one vertex more + nTriangle++; + } } -void WingedEdgeBuilder::buildTriangleFan( const real *vertices, - const real *normals, - vector& iMaterials, - const real *texCoords, - const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks, - const unsigned *vindices, - const unsigned *nindices, - const unsigned *mindices, - const unsigned *tindices, - const unsigned nvertices) { - // Nothing to be done +void WingedEdgeBuilder::buildTriangleFan(const real *vertices, const real *normals, vector& iMaterials, + const real *texCoords, const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks, + const unsigned *vindices, const unsigned *nindices, const unsigned *mindices, + const unsigned *tindices, const unsigned nvertices) +{ + // Nothing to be done } -void WingedEdgeBuilder::buildTriangles(const real *vertices, - const real *normals, - vector& iMaterials, - const real *texCoords, - const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks, - const unsigned *vindices, - const unsigned *nindices, - const unsigned *mindices, - const unsigned *tindices, - const unsigned nvertices) { - WShape * currentShape = _current_wshape; // the current shape begin built - vector triangleVertices; - vector triangleNormals; - vector triangleTexCoords; - vector triangleFaceEdgeMarks; - - // Each triplet of vertices is considered as an independent triangle - for(unsigned i = 0; i < nvertices / 3; i++) - { - triangleVertices.push_back(currentShape->getVertexList()[vindices[3*i]/3]); - triangleVertices.push_back(currentShape->getVertexList()[vindices[3*i+1]/3]); - triangleVertices.push_back(currentShape->getVertexList()[vindices[3*i+2]/3]); - - triangleNormals.push_back(Vec3r(normals[nindices[3*i]],normals[nindices[3*i]+1], normals[nindices[3*i]+2])); - triangleNormals.push_back(Vec3r(normals[nindices[3*i+1]],normals[nindices[3*i+1]+1],normals[nindices[3*i+1]+2])); - triangleNormals.push_back(Vec3r(normals[nindices[3*i+2]], normals[nindices[3*i+2]+1], normals[nindices[3*i+2]+2])); - - if(texCoords){ - triangleTexCoords.push_back(Vec2r(texCoords[tindices[3*i]],texCoords[tindices[3*i]+1])); - triangleTexCoords.push_back(Vec2r(texCoords[tindices[3*i+1]],texCoords[tindices[3*i+1]+1])); - triangleTexCoords.push_back(Vec2r(texCoords[tindices[3*i+2]], texCoords[tindices[3*i+2]+1])); - } - - triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[i] & IndexedFaceSet::FACE_MARK) != 0); - triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[i] & IndexedFaceSet::EDGE_MARK_V1V2) != 0); - triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[i] & IndexedFaceSet::EDGE_MARK_V2V3) != 0); - triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[i] & IndexedFaceSet::EDGE_MARK_V3V1) != 0); - } - if(mindices) - currentShape->MakeFace(triangleVertices, triangleNormals, triangleTexCoords, triangleFaceEdgeMarks, mindices[0]); +void WingedEdgeBuilder::buildTriangles(const real *vertices, const real *normals, vector& iMaterials, + const real *texCoords, const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks, + const unsigned *vindices, const unsigned *nindices, const unsigned *mindices, + const unsigned *tindices, const unsigned nvertices) +{ + WShape *currentShape = _current_wshape; // the current shape begin built + vector triangleVertices; + vector triangleNormals; + vector triangleTexCoords; + vector triangleFaceEdgeMarks; + + // Each triplet of vertices is considered as an independent triangle + for (unsigned int i = 0; i < nvertices / 3; i++) { + triangleVertices.push_back(currentShape->getVertexList()[vindices[3 * i] / 3]); + triangleVertices.push_back(currentShape->getVertexList()[vindices[3 * i + 1] / 3]); + triangleVertices.push_back(currentShape->getVertexList()[vindices[3 * i + 2] / 3]); + + triangleNormals.push_back(Vec3r(normals[nindices[3 * i]], normals[nindices[3 * i] + 1], + normals[nindices[3 * i] + 2])); + triangleNormals.push_back(Vec3r(normals[nindices[3 * i + 1]], normals[nindices[3 * i + 1] + 1], + normals[nindices[3 * i + 1] + 2])); + triangleNormals.push_back(Vec3r(normals[nindices[3 * i + 2]], normals[nindices[3 * i + 2] + 1], + normals[nindices[3 * i + 2] + 2])); + + if (texCoords) { + triangleTexCoords.push_back(Vec2r(texCoords[tindices[3 * i]], texCoords[tindices[3 * i] + 1])); + triangleTexCoords.push_back(Vec2r(texCoords[tindices[3 * i + 1]], texCoords[tindices[3 * i + 1] + 1])); + triangleTexCoords.push_back(Vec2r(texCoords[tindices[3 * i + 2]], texCoords[tindices[3 * i + 2] + 1])); + } + + triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[i] & IndexedFaceSet::FACE_MARK) != 0); + triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[i] & IndexedFaceSet::EDGE_MARK_V1V2) != 0); + triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[i] & IndexedFaceSet::EDGE_MARK_V2V3) != 0); + triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[i] & IndexedFaceSet::EDGE_MARK_V3V1) != 0); + } + if (mindices) + currentShape->MakeFace(triangleVertices, triangleNormals, triangleTexCoords, triangleFaceEdgeMarks, + mindices[0]); else currentShape->MakeFace(triangleVertices, triangleNormals, triangleTexCoords, triangleFaceEdgeMarks, 0); - } -void WingedEdgeBuilder::transformVertices(const real *vertices, - unsigned vsize, - const Matrix44r& transform, - real *res) { - const real *v = vertices; - real *pv = res; - - for (unsigned i = 0; i < vsize / 3; i++) { - HVec3r hv_tmp(v[0], v[1], v[2]); - HVec3r hv(transform * hv_tmp); - for (unsigned j = 0; j < 3; j++) - pv[j] = hv[j] / hv[3]; - v += 3; - pv += 3; - } +void WingedEdgeBuilder::transformVertices(const real *vertices, unsigned vsize, const Matrix44r& transform, real *res) +{ + const real *v = vertices; + real *pv = res; + + for (unsigned int i = 0; i < vsize / 3; i++) { + HVec3r hv_tmp(v[0], v[1], v[2]); + HVec3r hv(transform * hv_tmp); + for (unsigned int j = 0; j < 3; j++) + pv[j] = hv[j] / hv[3]; + v += 3; + pv += 3; + } } -void WingedEdgeBuilder::transformNormals(const real *normals, - unsigned nsize, - const Matrix44r& transform, - real* res) { - const real *n = normals; - real *pn = res; - - for (unsigned i = 0; i < nsize / 3; i++) { - Vec3r hn(n[0], n[1], n[2]); - hn = GeomUtils::rotateVector(transform, hn); - for (unsigned j = 0; j < 3; j++) - pn[j] = hn[j]; - n += 3; - pn += 3; - } -} +void WingedEdgeBuilder::transformNormals(const real *normals, unsigned nsize, const Matrix44r& transform, real *res) +{ + const real *n = normals; + real *pn = res; + + for (unsigned int i = 0; i < nsize / 3; i++) { + Vec3r hn(n[0], n[1], n[2]); + hn = GeomUtils::rotateVector(transform, hn); + for (unsigned int j = 0; j < 3; j++) + pn[j] = hn[j]; + n += 3; + pn += 3; + } +} \ No newline at end of file diff --git a/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.h b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.h index 972d67355d2..cf32c1191b2 100644 --- a/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.h +++ b/source/blender/freestyle/intern/winged_edge/WingedEdgeBuilder.h @@ -1,171 +1,157 @@ -// -// Filename : WingedEdgeBuilder.h -// Author(s) : Stephane Grabli -// Purpose : Class to render a WingedEdge data structure -// from a polyhedral data structure organized in -// nodes of a scene graph -// Date of creation : 28/05/03 -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Copyright (C) : Please refer to the COPYRIGHT file distributed -// with this source distribution. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef WINGED_EDGE_BUILDER_H -# define WINGED_EDGE_BUILDER_H - -# include "../system/FreestyleConfig.h" -# include "../system/RenderMonitor.h" -# include "../scene_graph/SceneVisitor.h" -# include "WEdge.h" -# include "../scene_graph/IndexedFaceSet.h" -# include "../scene_graph/NodeTransform.h" +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2010 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __FREESTYLE_WINGED_EDGE_BUILDER_H__ +#define __FREESTYLE_WINGED_EDGE_BUILDER_H__ + +/** \file blender/freestyle/intern/winged_edge/WingedEdgeBuilder.h + * \ingroup freestyle + * \brief Class to render a WingedEdge data structure from a polyhedral data structure organized in nodes + * of a scene graph + * \author Stephane Grabli + * \date 28/05/2003 + */ + +#include "WEdge.h" + +#include "../scene_graph/IndexedFaceSet.h" +#include "../scene_graph/NodeTransform.h" +#include "../scene_graph/SceneVisitor.h" + +#include "../system/FreestyleConfig.h" +#include "../system/RenderMonitor.h" class LIB_WINGED_EDGE_EXPORT WingedEdgeBuilder : public SceneVisitor { - public: - - inline WingedEdgeBuilder() : SceneVisitor() { - _current_wshape = NULL; - _current_frs_material = NULL; - _current_matrix = NULL; - _winged_edge = new WingedEdge; // Not deleted by the destructor - _pRenderMonitor = NULL; - } - - virtual ~WingedEdgeBuilder() { - for (vector::iterator it = _matrices_stack.begin(); - it != _matrices_stack.end(); - it++) - delete *it; - _matrices_stack.clear(); - } - - VISIT_DECL(IndexedFaceSet) - VISIT_DECL(NodeShape) - VISIT_DECL(NodeTransform) - - virtual void visitNodeTransformAfter(NodeTransform&); - - // - // Accessors - // - ///////////////////////////////////////////////////////////////////////////// - - inline WingedEdge* getWingedEdge() { - return _winged_edge; - } - - inline WShape* getCurrentWShape() { - return _current_wshape; - } - - inline FrsMaterial* getCurrentFrsMaterial() { - return _current_frs_material; - } - - inline Matrix44r* getCurrentMatrix() { - return _current_matrix; - } - - // - // Modifiers - // - ///////////////////////////////////////////////////////////////////////////// - - inline void setCurrentWShape(WShape* wshape) { - _current_wshape = wshape; - } - - inline void setCurrentFrsMaterial(FrsMaterial* mat) { - _current_frs_material = mat; - } - - // inline void setCurrentMatrix(Matrix44r* matrix) { - // _current_matrix = matrix; - // } - - inline void setRenderMonitor(RenderMonitor *iRenderMonitor) { - _pRenderMonitor = iRenderMonitor; - } - - protected: - - virtual void buildWShape(WShape& shape, IndexedFaceSet& ifs); - virtual void buildWVertices(WShape& shape, - const real *vertices, - unsigned vsize); - - RenderMonitor *_pRenderMonitor; - - private: - - void buildTriangleStrip(const real *vertices, - const real *normals, - vector& iMaterials, - const real *texCoords, - const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks, - const unsigned *vindices, - const unsigned *nindices, - const unsigned *mindices, - const unsigned *tindices, - const unsigned nvertices); - - void buildTriangleFan(const real *vertices, - const real *normals, - vector& iMaterials, - const real *texCoords, - const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks, - const unsigned *vindices, - const unsigned *nindices, - const unsigned *mindices, - const unsigned *tindices, - const unsigned nvertices); - - void buildTriangles(const real *vertices, - const real *normals, - vector& iMaterials, - const real *texCoords, - const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks, - const unsigned *vindices, - const unsigned *nindices, - const unsigned *mindices, - const unsigned *tindices, - const unsigned nvertices); - - void transformVertices(const real *vertices, - unsigned vsize, - const Matrix44r& transform, - real *res); - - void transformNormals(const real *normals, - unsigned nsize, - const Matrix44r& transform, - real *res); - - WShape* _current_wshape; - FrsMaterial* _current_frs_material; - WingedEdge* _winged_edge; - Matrix44r* _current_matrix; - vector _matrices_stack; +public: + inline WingedEdgeBuilder() : SceneVisitor() + { + _current_wshape = NULL; + _current_frs_material = NULL; + _current_matrix = NULL; + _winged_edge = new WingedEdge; // Not deleted by the destructor + _pRenderMonitor = NULL; + } + + virtual ~WingedEdgeBuilder() + { + for (vector::iterator it = _matrices_stack.begin(); it != _matrices_stack.end(); ++it) + delete *it; + _matrices_stack.clear(); + } + + VISIT_DECL(IndexedFaceSet) + VISIT_DECL(NodeShape) + VISIT_DECL(NodeTransform) + + virtual void visitNodeTransformAfter(NodeTransform&); + + // + // Accessors + // + ///////////////////////////////////////////////////////////////////////////// + + inline WingedEdge *getWingedEdge() + { + return _winged_edge; + } + + inline WShape *getCurrentWShape() + { + return _current_wshape; + } + + inline FrsMaterial *getCurrentFrsMaterial() + { + return _current_frs_material; + } + + inline Matrix44r *getCurrentMatrix() + { + return _current_matrix; + } + + // + // Modifiers + // + ///////////////////////////////////////////////////////////////////////////// + + inline void setCurrentWShape(WShape *wshape) + { + _current_wshape = wshape; + } + + inline void setCurrentFrsMaterial(FrsMaterial *mat) + { + _current_frs_material = mat; + } + +#if 0 + inline void setCurrentMatrix(Matrix44r *matrix) + { + _current_matrix = matrix; + } +#endif + + inline void setRenderMonitor(RenderMonitor *iRenderMonitor) { + _pRenderMonitor = iRenderMonitor; + } + +protected: + virtual void buildWShape(WShape& shape, IndexedFaceSet& ifs); + virtual void buildWVertices(WShape& shape, const real *vertices, unsigned vsize); + + RenderMonitor *_pRenderMonitor; + +private: + void buildTriangleStrip(const real *vertices, const real *normals, vector& iMaterials, + const real *texCoords, const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks, + const unsigned *vindices, const unsigned *nindices, const unsigned *mindices, + const unsigned *tindices, const unsigned nvertices); + + void buildTriangleFan(const real *vertices, const real *normals, vector& iMaterials, + const real *texCoords, const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks, + const unsigned *vindices, const unsigned *nindices, const unsigned *mindices, + const unsigned *tindices, const unsigned nvertices); + + void buildTriangles(const real *vertices, const real *normals, vector& iMaterials, + const real *texCoords, const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks, + const unsigned *vindices, const unsigned *nindices, const unsigned *mindices, + const unsigned *tindices, const unsigned nvertices); + + void transformVertices(const real *vertices, unsigned vsize, const Matrix44r& transform, real *res); + + void transformNormals(const real *normals, unsigned nsize, const Matrix44r& transform, real *res); + + WShape *_current_wshape; + FrsMaterial *_current_frs_material; + WingedEdge *_winged_edge; + Matrix44r *_current_matrix; + vector _matrices_stack; }; -#endif // WINGED_EDGE_BUILDER_H +#endif // __FREESTYLE_WINGED_EDGE_BUILDER_H__ \ No newline at end of file -- cgit v1.2.3