inclusion.hpp 9.66 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>
45
bool isConvex(typename PFP::MAP& map, Vol v, const VertexAttribute<typename PFP::VEC3, typename PFP::MAP>& 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>
69
bool isPointInVolume(typename PFP::MAP& map, Vol v, const VertexAttribute<typename PFP::VEC3, typename PFP::MAP>& 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);
78

Pierre Kraemer's avatar
Pierre Kraemer committed
79
	std::vector<VEC3> interPrec;
Sylvain Thery's avatar
Sylvain Thery committed
80
	interPrec.reserve(16);
81 82

	std::vector<Face> visitedFaces;			// Faces that are traversed
83
	visitedFaces.reserve(64);
84 85 86
	Face f(v.dart);
	visitedFaces.push_back(f);				// Start with the first face of v

Pierre Kraemer's avatar
Pierre Kraemer committed
87
	DartMarkerStore<typename PFP::MAP> mark(map);
88 89 90
	mark.markOrbit(f) ;

	for(unsigned int iface = 0; iface != visitedFaces.size(); ++iface)
Pierre Kraemer's avatar
Pierre Kraemer committed
91
	{
92
		f = visitedFaces[iface];
93
		VEC3 inter;
94
		bool interRes = intersectionLineConvexFace<PFP>(map, f, position, point, dir, inter);
95
		if (interRes)
Pierre Kraemer's avatar
Pierre Kraemer committed
96
		{
Sylvain Thery's avatar
Sylvain Thery committed
97
			// check if already intersect on same point (a vertex certainly)
Pierre Kraemer's avatar
Pierre Kraemer committed
98
			bool alreadyfound = false;
Sylvain Thery's avatar
Sylvain Thery committed
99 100
			for(typename std::vector<VEC3>::iterator it = interPrec.begin(); !alreadyfound && it != interPrec.end(); ++it)
			{
101 102
				if (Geom::arePointsEquals(*it, inter))
					alreadyfound = true;
Sylvain Thery's avatar
Sylvain Thery committed
103 104 105
			}

			if (!alreadyfound)
Pierre Kraemer's avatar
Pierre Kraemer committed
106
			{
107 108
				float v = dir * (inter - point);
				if (v > 0)
109
					++countInter;
110
				if (v < 0)
111
					++countInter2;
Sylvain Thery's avatar
Sylvain Thery committed
112
				interPrec.push_back(inter);
Pierre Kraemer's avatar
Pierre Kraemer committed
113 114
			}
		}
115
		// add all face neighbours to the table
116
		foreach_adjacent2<EDGE>(map, f, [&] (Face ff)
117
		{
118
			if(!mark.isMarked(ff)) // not already marked
119
			{
120 121
				visitedFaces.push_back(ff) ;
				mark.markOrbit(ff) ;
122
			}
123
		});
Pierre Kraemer's avatar
Pierre Kraemer committed
124
	}
125

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

template <typename PFP>
131
bool isPointInConvexVolume(typename PFP::MAP& map, Vol v, const VertexAttribute<typename PFP::VEC3, typename PFP::MAP>& position, const typename PFP::VEC3& point, bool CCW)
Pierre Kraemer's avatar
Pierre Kraemer committed
132 133 134 135
{
	typedef typename PFP::VEC3 VEC3 ;
	typedef typename PFP::REAL REAL;

136 137 138 139
	std::vector<Face> visitedFaces;			// Faces that are traversed
	visitedFaces.reserve(64);
	Face f(v.dart);
	visitedFaces.push_back(f);				// Start with the first face of v
Pierre Kraemer's avatar
Pierre Kraemer committed
140

Pierre Kraemer's avatar
Pierre Kraemer committed
141
	DartMarkerStore<typename PFP::MAP> mark(map);		// Lock a marker
142 143

	for (std::vector<Face>::iterator face = visitedFaces.begin(); face != visitedFaces.end(); ++face)
Pierre Kraemer's avatar
Pierre Kraemer committed
144
	{
145 146
		f = *face;
		if (!mark.isMarked(f))
Pierre Kraemer's avatar
Pierre Kraemer committed
147
		{
148 149 150
			mark.markOrbit(f);

			Geom::Plane3D<REAL> p = facePlane<PFP>(map, f, position);
Pierre Kraemer's avatar
Pierre Kraemer committed
151 152 153 154
			Geom::Orientation3D o3d = p.orient(point);
			if(CCW)
			{
				if(o3d == Geom::OVER)
155
					return false;
Pierre Kraemer's avatar
Pierre Kraemer committed
156 157
			}
			else if(o3d == Geom::UNDER)
158
				return false;
Pierre Kraemer's avatar
Pierre Kraemer committed
159

160 161
			// add all face neighbours to the table
			foreach_adjacent2<EDGE>(map, f, [&] (Face ff)
Pierre Kraemer's avatar
Pierre Kraemer committed
162
			{
163 164 165
				if(!mark.isMarked(ff)) // not already marked
					visitedFaces.push_back(ff) ;
			});
Pierre Kraemer's avatar
Pierre Kraemer committed
166 167 168
		}
	}

169
	return true;
Pierre Kraemer's avatar
Pierre Kraemer committed
170 171 172
}

template <typename PFP>
173
bool isPointInConvexFace(typename PFP::MAP& map, Face f, const VertexAttribute<typename PFP::VEC3, typename PFP::MAP>& position, const typename PFP::VEC3& point, bool CCW)
Pierre Kraemer's avatar
Pierre Kraemer committed
174 175 176 177
{
	typedef typename PFP::VEC3 VEC3 ;
	typedef typename PFP::REAL REAL;

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

	return false;
}

template <typename PFP>
205
bool isPointInConvexFace2D(typename PFP::MAP& map, Face f, const VertexAttribute<typename PFP::VEC3, typename PFP::MAP>& position, const typename PFP::VEC3& point, bool CCW )
Pierre Kraemer's avatar
Pierre Kraemer committed
206 207 208 209
{
	typedef typename PFP::VEC3 VEC3 ;
	typedef typename PFP::REAL REAL;

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

	Geom::Orientation2D o2d;
213

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

227
	return true;
Pierre Kraemer's avatar
Pierre Kraemer committed
228 229 230
}

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

244 245
	Dart d = e.dart;

246
	if(
247 248 249
		( 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)
250
	)
Pierre Kraemer's avatar
Pierre Kraemer committed
251
		return true;
252 253
	else
	{
254
		CGoGNout << " point " << point << CGoGNendl;
255
		CGoGNout << " d1 " << position[d] << " d2 " << position[map.phi2(d)] << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
256 257 258 259 260
		return false;
	}
}

template <typename PFP>
261
bool isPointOnHalfEdge(typename PFP::MAP& map, Dart d, const VertexAttribute<typename PFP::VEC3, typename PFP::MAP>& position, const typename PFP::VEC3& point)
Pierre Kraemer's avatar
Pierre Kraemer committed
262 263 264 265
{
	typedef typename PFP::REAL REAL;
	typedef typename PFP::VEC3 VEC3;

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

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

272
	return abs(v1*v2) <= REAL(0.00001);
Pierre Kraemer's avatar
Pierre Kraemer committed
273 274 275
}

template <typename PFP>
276
bool isPointOnVertex(typename PFP::MAP& map, Vertex v, const VertexAttribute<typename PFP::VEC3, typename PFP::MAP>& position, const typename PFP::VEC3& point)
Pierre Kraemer's avatar
Pierre Kraemer committed
277
{
278
	return Geom::arePointsEquals(point, position[v]);
Pierre Kraemer's avatar
Pierre Kraemer committed
279 280 281
}

template <typename PFP>
282
bool isConvexFaceInOrIntersectingTetrahedron(typename PFP::MAP& map, Face f, const VertexAttribute<typename PFP::VEC3, typename PFP::MAP>& position, const typename PFP::VEC3 points[4], bool CCW)
Pierre Kraemer's avatar
Pierre Kraemer committed
283 284 285
{
	typedef typename PFP::VEC3 VEC3 ;

286
	Traversor2FV<typename PFP::MAP> tfv(map, f) ;
Pierre Kraemer's avatar
Pierre Kraemer committed
287
	for(Vertex v = tfv.begin(); v.dart != tfv.end(); v = tfv.next())
Pierre Kraemer's avatar
Pierre Kraemer committed
288
	{
289
		if(Geom::isPointInTetrahedron(points, position[v], CCW))
Pierre Kraemer's avatar
Pierre Kraemer committed
290
			return true;
291
	}
Pierre Kraemer's avatar
Pierre Kraemer committed
292 293

	VEC3 inter;
294 295 296 297 298 299
	if( intersectionSegmentConvexFace(map, f, position, points[0], points[1], inter)
	|| 	intersectionSegmentConvexFace(map, f, position, points[1], points[2], inter)
	|| 	intersectionSegmentConvexFace(map, f, position, points[2], points[0], inter)
	|| 	intersectionSegmentConvexFace(map, f, position, points[0], points[3], inter)
	|| 	intersectionSegmentConvexFace(map, f, position, points[1], points[3], inter)
	|| 	intersectionSegmentConvexFace(map, f, position, points[2], points[3], inter)
Pierre Kraemer's avatar
Pierre Kraemer committed
300 301 302 303 304 305
	)
		return true;

	return false;
}

306
} // namespace Geometry
Pierre Kraemer's avatar
Pierre Kraemer committed
307

308
} // namespace Surface
309

310
} // namspace Algo
Pierre Kraemer's avatar
Pierre Kraemer committed
311

312
} // namespace CGoGN