volume.hpp 6.17 KB
Newer Older
Pierre Kraemer's avatar
Pierre Kraemer committed
1 2 3
/*******************************************************************************
 * CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps  *
 * version 0.1                                                                  *
4
 * Copyright (C) 2009-2012, IGG Team, LSIIT, University of Strasbourg           *
Pierre Kraemer's avatar
Pierre Kraemer committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 *                                                                              *
 * This library is free software; you can redistribute it and/or modify it      *
 * under the terms of the GNU Lesser General Public License as published by the *
 * Free Software Foundation; either version 2.1 of the License, or (at your     *
 * option) any later version.                                                   *
 *                                                                              *
 * This library 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 Lesser General Public License  *
 * for more details.                                                            *
 *                                                                              *
 * You should have received a copy of the GNU Lesser General Public License     *
 * along with this library; if not, write to the Free Software Foundation,      *
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.           *
 *                                                                              *
20
 * Web site: http://cgogn.unistra.fr/                                           *
Pierre Kraemer's avatar
Pierre Kraemer committed
21 22 23 24
 * Contact information: cgogn@unistra.fr                                        *
 *                                                                              *
 *******************************************************************************/

25
#include "Topology/generic/traversorCell.h"
Pierre Kraemer's avatar
Pierre Kraemer committed
26
#include "Algo/Geometry/centroid.h"
Thomas's avatar
Thomas committed
27
#include "Algo/Modelisation/tetrahedralization.h"
Pierre Kraemer's avatar
Pierre Kraemer committed
28 29 30 31 32 33 34 35 36 37 38

namespace CGoGN
{

namespace Algo
{

namespace Geometry
{

template <typename PFP>
39
typename PFP::REAL tetrahedronSignedVolume(typename PFP::MAP& map, Dart d, const VertexAttribute<typename PFP::VEC3>& position)
Pierre Kraemer's avatar
Pierre Kraemer committed
40 41 42 43 44 45 46 47 48 49
{
	typename PFP::VEC3 p1 = position[d] ;
	typename PFP::VEC3 p2 = position[map.phi1(d)] ;
	typename PFP::VEC3 p3 = position[map.phi_1(d)] ;
	typename PFP::VEC3 p4 = position[map.phi_1(map.phi2(d))] ;

	return Geom::tetraSignedVolume(p1, p2, p3, p4) ;
}

template <typename PFP>
50
typename PFP::REAL tetrahedronVolume(typename PFP::MAP& map, Dart d, const VertexAttribute<typename PFP::VEC3>& position)
Pierre Kraemer's avatar
Pierre Kraemer committed
51 52 53 54 55 56 57 58 59 60
{
	typename PFP::VEC3 p1 = position[d] ;
	typename PFP::VEC3 p2 = position[map.phi1(d)] ;
	typename PFP::VEC3 p3 = position[map.phi_1(d)] ;
	typename PFP::VEC3 p4 = position[map.phi_1(map.phi2(d))] ;

	return Geom::tetraVolume(p1, p2, p3, p4) ;
}

template <typename PFP>
61
typename PFP::REAL convexPolyhedronVolume(typename PFP::MAP& map, Dart d, const VertexAttribute<typename PFP::VEC3>& position, unsigned int thread)
Pierre Kraemer's avatar
Pierre Kraemer committed
62 63 64
{
	typedef typename PFP::VEC3 VEC3;

65
	if(Modelisation::Tetrahedralization::isTetrahedron<PFP>(map,d,thread))
Pierre Kraemer's avatar
Pierre Kraemer committed
66 67 68 69
		return tetrahedronVolume<PFP>(map,d,position) ;
	else
	{
		typename PFP::REAL vol = 0 ;
70
		VEC3 vCentroid = Algo::Geometry::volumeCentroid<PFP>(map, d, position, thread) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
71

72
		DartMarkerStore mark(map,thread);		// Lock a marker
Pierre Kraemer's avatar
Pierre Kraemer committed
73 74 75

		std::vector<Dart> visitedFaces ;
		visitedFaces.reserve(100) ;
76

Pierre Kraemer's avatar
Pierre Kraemer committed
77
		visitedFaces.push_back(d) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
78
		mark.markOrbit<FACE>(d) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
79 80 81 82

		for(typename std::vector<Dart>::iterator face = visitedFaces.begin(); face != visitedFaces.end(); ++face)
		{
			Dart e = *face ;
83
			if(map.isCycleTriangle(e))
Pierre Kraemer's avatar
Pierre Kraemer committed
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
			{
				VEC3 p1 = position[e] ;
				VEC3 p2 = position[map.phi1(e)] ;
				VEC3 p3 = position[map.phi_1(e)] ;
				vol += Geom::tetraVolume(p1, p2, p3, vCentroid) ;
			}
			else
			{
				VEC3 fCentroid = Algo::Geometry::faceCentroid<PFP>(map, e, position) ;
				Dart f = e ;
				do
				{
					VEC3 p1 = position[f] ;
					VEC3 p2 = position[map.phi1(f)] ;
					vol += Geom::tetraVolume(p1, p2, fCentroid, vCentroid) ;
					f = map.phi1(f) ;
				} while(f != e) ;
			}
			do	// add all face neighbours to the table
			{
				Dart ee = map.phi2(e) ;
				if(!mark.isMarked(ee)) // not already marked
				{
					visitedFaces.push_back(ee) ;
108
					mark.markOrbit<FACE>(ee) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
109 110 111 112 113 114 115 116 117 118
				}
				e = map.phi1(e) ;
			} while(e != *face) ;
		}

		return vol ;
	}
}

template <typename PFP>
119
typename PFP::REAL totalVolume(typename PFP::MAP& map, const VertexAttribute<typename PFP::VEC3>& position, const FunctorSelect& select, unsigned int thread)
Pierre Kraemer's avatar
Pierre Kraemer committed
120
{
121 122 123
//	typename PFP::REAL vol = 0 ;
	double vol = 0 ;

124
	TraversorW<typename PFP::MAP> t(map, select, thread) ;
125
	for(Dart d = t.begin(); d != t.end(); d = t.next())
126
		vol += convexPolyhedronVolume<PFP>(map, d, position,thread) ;
127
	return typename PFP::REAL(vol) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
128 129
}

130 131 132 133 134 135 136 137

namespace Parallel
{

template <typename PFP>
class FunctorTotalVolume: public FunctorMapThreaded<typename PFP::MAP >
{
	 const VertexAttribute<typename PFP::VEC3>& m_position;
138 139
//	 typename PFP::REAL m_vol;
	 double m_vol;
140 141 142 143 144
public:
	 FunctorTotalVolume<PFP>( typename PFP::MAP& map, const VertexAttribute<typename PFP::VEC3>& position):
	 	 FunctorMapThreaded<typename PFP::MAP>(map), m_position(position), m_vol(0.0)
	 { }

145
	void run(Dart d, unsigned int threadID)
146 147 148 149
	{
		m_vol += convexPolyhedronVolume<PFP>(this->m_map, d, m_position,threadID) ;
	}

150 151
//	typename PFP::REAL getVol() const
	double getVol() const
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
	{
		return m_vol;
	}
};



template <typename PFP>
typename PFP::REAL totalVolume(typename PFP::MAP& map, const VertexAttribute<typename PFP::VEC3>& position, const FunctorSelect& select, unsigned int nbth, unsigned int current_thread)
{
	if (nbth==0)
		nbth = Algo::Parallel::optimalNbThreads();


	std::vector<FunctorMapThreaded<typename PFP::MAP>*> functs;
	for (unsigned int i=0; i < nbth; ++i)
	{
		functs.push_back(new FunctorTotalVolume<PFP>(map,position));
	}

172
	double total=0.0;
173 174 175 176 177 178 179 180

	Algo::Parallel::foreach_cell<typename PFP::MAP,VOLUME>(map, functs, nbth, true, select, current_thread);

	for (unsigned int i=0; i < nbth; ++i)
	{
		total += reinterpret_cast<FunctorTotalVolume<PFP>*>(functs[i])->getVol();
		delete functs[i];
	}
181
	return typename PFP::REAL(total);
182 183 184 185
}

}

Pierre Kraemer's avatar
Pierre Kraemer committed
186 187 188 189 190
} // namespace Geometry

} // namespace Algo

} // namespace CGoGN