inclusion.hpp 9.73 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 25 26 27 28 29 30 31 32 33 34 35 36 37
 * Contact information: cgogn@unistra.fr                                        *
 *                                                                              *
 *******************************************************************************/

#include "Algo/Geometry/intersection.h"
#include "Algo/Geometry/orientation.h"
#include "Algo/Geometry/basic.h"
#include "Algo/Geometry/plane.h"

#include <limits>

namespace CGoGN
{

namespace Algo
{

38 39 40
namespace Surface
{

Pierre Kraemer's avatar
Pierre Kraemer committed
41 42 43 44
namespace Geometry
{

template <typename PFP>
Pierre Kraemer's avatar
Pierre Kraemer committed
45
bool isConvex(typename PFP::MAP& map, Vol v, const VertexAttribute<typename PFP::VEC3, typename PFP::MAP::IMPL>& position, bool CCW, unsigned int thread)
Pierre Kraemer's avatar
Pierre Kraemer committed
46 47 48
{
	//get all the dart of the volume
	std::vector<Dart> vStore;
Pierre Kraemer's avatar
Pierre Kraemer committed
49
	map.foreach_dart_of_orbit(v, [&] (Dart d) { vStore.push_back(d); }, thread);
Pierre Kraemer's avatar
Pierre Kraemer committed
50 51 52

	bool convex = true;

Pierre Kraemer's avatar
Pierre Kraemer committed
53
	DartMarkerStore<typename PFP::MAP> m(map, thread);
Pierre Kraemer's avatar
Pierre Kraemer committed
54 55 56 57 58
	for (std::vector<Dart>::iterator it = vStore.begin() ; it != vStore.end() && convex ; ++it)
	{
		Dart e = *it;
		if (!m.isMarked(e))
		{
Pierre Kraemer's avatar
Pierre Kraemer committed
59
			m.markOrbit<EDGE>(e) ;
60
			convex = isTetrahedronWellOriented<PFP>(map, e, position, CCW) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
61 62 63 64 65 66
		}
	}

	return convex;
}

Sylvain Thery's avatar
Sylvain Thery committed
67
// TODO add thread Pameter
Pierre Kraemer's avatar
Pierre Kraemer committed
68
template <typename PFP>
Pierre Kraemer's avatar
Pierre Kraemer committed
69
bool isPointInVolume(typename PFP::MAP& map, Dart d, const VertexAttribute<typename PFP::VEC3, typename PFP::MAP::IMPL>& position, const typename PFP::VEC3& point)
Pierre Kraemer's avatar
Pierre Kraemer committed
70 71 72 73 74
{
	typedef typename PFP::VEC3 VEC3;

	//number of intersection between a ray and the volume must be odd
	int countInter = 0;
75
	int countInter2 = 0;
Pierre Kraemer's avatar
Pierre Kraemer committed
76

77
	VEC3 dir(0.9f,1.1f,1.3f);
Pierre Kraemer's avatar
Pierre Kraemer committed
78
	std::vector<VEC3> interPrec;
Sylvain Thery's avatar
Sylvain Thery committed
79
	interPrec.reserve(16);
80 81 82
	std::vector<Dart> visitedFaces;			// Faces that are traversed
	visitedFaces.reserve(64);
	visitedFaces.push_back(d);				// Start with the face of d
Pierre Kraemer's avatar
Pierre Kraemer committed
83
	DartMarkerStore<typename PFP::MAP> mark(map);
84 85
	mark.markOrbit<FACE>(d) ;
	for(unsigned int  iface = 0; iface != visitedFaces.size(); ++iface)
Pierre Kraemer's avatar
Pierre Kraemer committed
86
	{
87 88
		Dart e = visitedFaces[iface];
		VEC3 inter;
89
		bool interRes = intersectionLineConvexFace<PFP>(map, e, position, point, dir, inter);
90
		if (interRes)
Pierre Kraemer's avatar
Pierre Kraemer committed
91
		{
Sylvain Thery's avatar
Sylvain Thery committed
92
			// check if already intersect on same point (a vertex certainly)
Pierre Kraemer's avatar
Pierre Kraemer committed
93
			bool alreadyfound = false;
Sylvain Thery's avatar
Sylvain Thery committed
94 95 96 97 98 99 100
			for(typename std::vector<VEC3>::iterator it = interPrec.begin(); !alreadyfound && it != interPrec.end(); ++it)
			{
				if (Geom::arePointsEquals(*it,inter))
						alreadyfound = true;
			}

			if (!alreadyfound)
Pierre Kraemer's avatar
Pierre Kraemer committed
101
			{
102 103 104 105 106
				float v = dir * (inter-point);
				if (v>0)
					++countInter;
				if (v<0)
					++countInter2;
Sylvain Thery's avatar
Sylvain Thery committed
107
				interPrec.push_back(inter);
Pierre Kraemer's avatar
Pierre Kraemer committed
108 109
			}
		}
110 111 112 113 114 115 116 117 118 119 120 121
		// add all face neighbours to the table
		Dart currentFace = e;
		do
		{
			Dart ee = map.phi2(e) ;
			if(!mark.isMarked(ee)) // not already marked
			{
				visitedFaces.push_back(ee) ;
				mark.markOrbit<FACE>(ee) ;
			}
			e = map.phi1(e) ;
		} while(e != currentFace) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
122
	}
123

Pierre Kraemer's avatar
Pierre Kraemer committed
124
	//if the point is in the volume there is an odd number of intersection with all faces with any direction
125 126
	return ((countInter % 2) != 0) && ((countInter2 % 2) != 0); //	return (countInter % 2) == 1;

Pierre Kraemer's avatar
Pierre Kraemer committed
127 128 129
}

template <typename PFP>
Pierre Kraemer's avatar
Pierre Kraemer committed
130
bool isPointInConvexVolume(typename PFP::MAP& map, Dart d, const VertexAttribute<typename PFP::VEC3, typename PFP::MAP::IMPL>& position, const typename PFP::VEC3& point, bool CCW)
Pierre Kraemer's avatar
Pierre Kraemer committed
131 132 133 134 135 136 137 138 139
{
	typedef typename PFP::VEC3 VEC3 ;
	typedef typename PFP::REAL REAL;

	std::list<Dart> visitedFaces;			// Faces that are traversed
	visitedFaces.push_back(d);				// Start with the face of d
	std::list<Dart>::iterator face;
	VEC3 N;

Pierre Kraemer's avatar
Pierre Kraemer committed
140
	DartMarkerStore<typename PFP::MAP> mark(map);		// Lock a marker
141
	for (face = visitedFaces.begin(); face != visitedFaces.end(); ++face)
Pierre Kraemer's avatar
Pierre Kraemer committed
142 143 144
	{
		if (!mark.isMarked(*face))
		{
145
			Geom::Plane3D<REAL> p = facePlane<PFP>(map, *face, position);
Pierre Kraemer's avatar
Pierre Kraemer committed
146 147 148 149
			Geom::Orientation3D o3d = p.orient(point);
			if(CCW)
			{
				if(o3d == Geom::OVER)
150
					return false;
Pierre Kraemer's avatar
Pierre Kraemer committed
151 152
			}
			else if(o3d == Geom::UNDER)
153
				return false;
Pierre Kraemer's avatar
Pierre Kraemer committed
154 155 156 157 158 159 160 161 162 163 164 165 166

			Dart dNext = *face ;
			do
			{
				mark.mark(dNext);					// Mark
				Dart adj = map.phi2(dNext);			// Get adjacent face
				if (adj != dNext && !mark.isMarked(adj))
					visitedFaces.push_back(adj);	// Add it
				dNext = map.phi1(dNext) ;
			} while(dNext != *face) ;
		}
	}

167
	return true;
Pierre Kraemer's avatar
Pierre Kraemer committed
168 169 170
}

template <typename PFP>
Pierre Kraemer's avatar
Pierre Kraemer committed
171
bool isPointInConvexFace(typename PFP::MAP& map, Dart d, const VertexAttribute<typename PFP::VEC3, typename PFP::MAP::IMPL>& position, const typename PFP::VEC3& point, bool CCW)
Pierre Kraemer's avatar
Pierre Kraemer committed
172 173 174 175
{
	typedef typename PFP::VEC3 VEC3 ;
	typedef typename PFP::REAL REAL;

176
	Geom::Plane3D<REAL> pl = Geometry::facePlane<PFP>(map, d, position);
Pierre Kraemer's avatar
Pierre Kraemer committed
177 178 179
	Geom::Orientation3D o3d = pl.orient(point);
	if(o3d == Geom::ON)
	{
180 181
		Traversor2FV<typename PFP::MAP> tfv(map, d) ;
		for(Dart it = tfv.begin(); it != tfv.end(); it = tfv.next())
Pierre Kraemer's avatar
Pierre Kraemer committed
182 183
		{
			VEC3 N = pl.normal();
184
			VEC3 v2(position[map.phi1(it)] - position[it]);
Pierre Kraemer's avatar
Pierre Kraemer committed
185
			VEC3 norm2 = N^v2;
186
			Geom::Plane3D<REAL> pl2(norm2, position[it]);
Pierre Kraemer's avatar
Pierre Kraemer committed
187 188 189 190
			o3d = pl2.orient(point);
			if(CCW)
			{
				if(o3d == Geom::UNDER)
191
					return false;
Pierre Kraemer's avatar
Pierre Kraemer committed
192 193
			}
			else if(o3d == Geom::OVER)
194
				return false;
195
		}
196
		return true;
Pierre Kraemer's avatar
Pierre Kraemer committed
197 198 199 200 201 202
	}

	return false;
}

template <typename PFP>
Pierre Kraemer's avatar
Pierre Kraemer committed
203
bool isPointInConvexFace2D(typename PFP::MAP& map, Dart d, const VertexAttribute<typename PFP::VEC3, typename PFP::MAP::IMPL>& position, const typename PFP::VEC3& point, bool CCW )
Pierre Kraemer's avatar
Pierre Kraemer committed
204 205 206 207
{
	typedef typename PFP::VEC3 VEC3 ;
	typedef typename PFP::REAL REAL;

208
// 	CGoGNout << "point " << point << "d " << d << "faceDeg " << map.faceDegree(d) << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
209 210

	Geom::Orientation2D o2d;
211 212 213

	Traversor2FV<typename PFP::MAP> tfv(map, d) ;
	for(Dart it = tfv.begin(); it != tfv.end(); it = tfv.next())
Pierre Kraemer's avatar
Pierre Kraemer committed
214
	{
215
		o2d = Geom::testOrientation2D(point, position[it], position[map.phi1(it)]);
Pierre Kraemer's avatar
Pierre Kraemer committed
216 217 218
		if(CCW)
		{
			if(o2d == Geom::RIGHT)
219
				return false;
Pierre Kraemer's avatar
Pierre Kraemer committed
220 221 222
		}
		else if(o2d == Geom::LEFT)
			return false;
223
	}
Pierre Kraemer's avatar
Pierre Kraemer committed
224

225
	return true;
Pierre Kraemer's avatar
Pierre Kraemer committed
226 227 228
}

template <typename PFP>
Pierre Kraemer's avatar
Pierre Kraemer committed
229
bool isPointOnEdge(typename PFP::MAP& map, Dart d, const VertexAttribute<typename PFP::VEC3, typename PFP::MAP::IMPL>& position, const typename PFP::VEC3& point)
Pierre Kraemer's avatar
Pierre Kraemer committed
230 231 232 233
{
// 	typedef typename PFP::REAL REAL;
// 	typedef typename PFP::VEC3 VEC3 ;
// 
234
// 	VEC3 v1 = vectorOutOfDart<PFP>(map, d, positions);
Pierre Kraemer's avatar
Pierre Kraemer committed
235 236 237 238 239 240 241
// 	VEC3 v2(point - positions[d]);
// 
// 	v1.normalize();
// 	v2.normalize();
// 
// 	return fabs(REAL(1) - (v1*v2)) < std::numeric_limits<REAL>::min();

242
	if(
243 244 245
		( isPointOnHalfEdge<PFP>(map,d,position,point) && isPointOnHalfEdge<PFP>(map,map.phi2(d),position,point) ) ||
		isPointOnVertex<PFP>(map,d,position,point) ||
		isPointOnVertex<PFP>(map,map.phi1(d),position,point)
246
	)
Pierre Kraemer's avatar
Pierre Kraemer committed
247
		return true;
248 249
	else
	{
250
		CGoGNout << " point " << point << CGoGNendl;
251
		CGoGNout << " d1 " << position[d] << " d2 " << position[map.phi2(d)] << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
252 253 254 255 256
		return false;
	}
}

template <typename PFP>
Pierre Kraemer's avatar
Pierre Kraemer committed
257
bool isPointOnHalfEdge(typename PFP::MAP& map, Dart d, const VertexAttribute<typename PFP::VEC3, typename PFP::MAP::IMPL>& position, const typename PFP::VEC3& point)
Pierre Kraemer's avatar
Pierre Kraemer committed
258 259 260 261
{
	typedef typename PFP::REAL REAL;
	typedef typename PFP::VEC3 VEC3;

262
	VEC3 v1 = vectorOutOfDart<PFP>(map, d, position);
263
	VEC3 v2(point - position[d]);
Pierre Kraemer's avatar
Pierre Kraemer committed
264 265 266 267 268 269 270 271

	v1.normalize();
	v2.normalize();

	return (v1*v2) >= -REAL(0.00001);
}

template <typename PFP>
Pierre Kraemer's avatar
Pierre Kraemer committed
272
bool isPointOnVertex(typename PFP::MAP& map, Dart d, const VertexAttribute<typename PFP::VEC3, typename PFP::MAP::IMPL>& position, const typename PFP::VEC3& point)
Pierre Kraemer's avatar
Pierre Kraemer committed
273
{
274
	return Geom::arePointsEquals(point, position[d]);
Pierre Kraemer's avatar
Pierre Kraemer committed
275 276 277
}

template <typename PFP>
Pierre Kraemer's avatar
Pierre Kraemer committed
278
bool isConvexFaceInOrIntersectingTetrahedron(typename PFP::MAP& map, Dart d, const VertexAttribute<typename PFP::VEC3, typename PFP::MAP::IMPL>& position, const typename PFP::VEC3 points[4], bool CCW)
Pierre Kraemer's avatar
Pierre Kraemer committed
279 280 281
{
	typedef typename PFP::VEC3 VEC3 ;

282 283
	Traversor2FV<typename PFP::MAP> tfv(map, d) ;
	for(Dart it = tfv.begin(); it != tfv.end(); it = tfv.next())
Pierre Kraemer's avatar
Pierre Kraemer committed
284
	{
285
		if(Geom::isPointInTetrahedron(points, position[it], CCW))
Pierre Kraemer's avatar
Pierre Kraemer committed
286
			return true;
287
	}
Pierre Kraemer's avatar
Pierre Kraemer committed
288 289

	VEC3 inter;
290 291 292 293 294 295
	if( intersectionSegmentConvexFace(map, d, position, points[0], points[1], inter)
	|| 	intersectionSegmentConvexFace(map, d, position, points[1], points[2], inter)
	|| 	intersectionSegmentConvexFace(map, d, position, points[2], points[0], inter)
	|| 	intersectionSegmentConvexFace(map, d, position, points[0], points[3], inter)
	|| 	intersectionSegmentConvexFace(map, d, position, points[1], points[3], inter)
	|| 	intersectionSegmentConvexFace(map, d, position, points[2], points[3], inter)
Pierre Kraemer's avatar
Pierre Kraemer committed
296 297 298 299 300 301
	)
		return true;

	return false;
}

302
} // namespace Geometry
Pierre Kraemer's avatar
Pierre Kraemer committed
303

304
} // namespace Surface
305

306
} // namspace Algo
Pierre Kraemer's avatar
Pierre Kraemer committed
307

308
} // namespace CGoGN