collector.h 14.8 KB
Newer Older
Pierre Kraemer's avatar
Pierre Kraemer committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps  *
* version 0.1                                                                  *
* Copyright (C) 2009, IGG Team, LSIIT, University of Strasbourg                *
*                                                                              *
* 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
* Contact information: cgogn@unistra.fr                                        *
*                                                                              *
*******************************************************************************/

#ifndef __COLLECTOR_H__
#define __COLLECTOR_H__

Sylvain Thery's avatar
Sylvain Thery committed
28
#include "Container/fakeAttribute.h"
Sylvain Thery's avatar
Sylvain Thery committed
29
#include "Geometry/basic.h"
Sylvain Thery's avatar
Sylvain Thery committed
30

Pierre Kraemer's avatar
Pierre Kraemer committed
31
32
33
34
35
36
37
38
39
40
/*****************************************
 * Class hierarchy :
 * Collector (virtual)
 * - Collector_WithinSphere
 * - Collector_OneRing
 ****************************************/

namespace CGoGN
{

41
42
43
namespace Algo
{

Pierre Kraemer's avatar
Pierre Kraemer committed
44
45
46
47
namespace Selection
{

/*********************************************************
48
 * Generic Collector
Pierre Kraemer's avatar
Pierre Kraemer committed
49
 *********************************************************/
50

Pierre Kraemer's avatar
Pierre Kraemer committed
51
52
53
54
55
56
57
58
template <typename PFP>
class Collector
{
protected:
	typedef typename PFP::VEC3 VEC3;
	typedef typename PFP::REAL REAL;

	typename PFP::MAP& map;
Sylvain Thery's avatar
Sylvain Thery committed
59
	unsigned int m_thread;
Pierre Kraemer's avatar
Pierre Kraemer committed
60
61
62
63
64
65
66
67
68

	Dart centerDart;

	std::vector<Dart> insideVertices;
	std::vector<Dart> insideEdges;
	std::vector<Dart> insideFaces;
	std::vector<Dart> border;

public:
Sylvain Thery's avatar
Sylvain Thery committed
69
	Collector(typename PFP::MAP& m, unsigned int thread =0);
Pierre Kraemer's avatar
Pierre Kraemer committed
70

Pierre Kraemer's avatar
Pierre Kraemer committed
71
72
73
74
75
76
77
78
	inline void init(Dart d)
	{
		centerDart = d;
		insideVertices.clear();
		insideEdges.clear();
		insideFaces.clear();
		border.clear();
	}
Pierre Kraemer's avatar
Pierre Kraemer committed
79

Pierre Kraemer's avatar
Pierre Kraemer committed
80
81
	virtual void collectAll(Dart d) = 0;
	virtual void collectBorder(Dart d) = 0;
Pierre Kraemer's avatar
Pierre Kraemer committed
82

Pierre Kraemer's avatar
Pierre Kraemer committed
83
84
85
86
	bool applyOnInsideVertices(FunctorType& f);
	bool applyOnInsideEdges(FunctorType& f);
	bool applyOnInsideFaces(FunctorType& f);
	bool applyOnBorder(FunctorType& f);
87

Pierre Kraemer's avatar
Pierre Kraemer committed
88
	inline void sort()
Pierre Kraemer's avatar
Pierre Kraemer committed
89
90
91
92
93
94
95
	{
		std::sort(insideVertices.begin(), insideVertices.end());
		std::sort(insideEdges.begin(), insideEdges.end());
		std::sort(insideFaces.begin(), insideFaces.end());
		std::sort(border.begin(), border.end());
	}

Pierre Kraemer's avatar
Pierre Kraemer committed
96
	inline typename PFP::MAP& getMap() { return map; }
Pierre Kraemer's avatar
Pierre Kraemer committed
97

Pierre Kraemer's avatar
Pierre Kraemer committed
98
	inline Dart getCenterDart() const { return centerDart; }
Pierre Kraemer's avatar
Pierre Kraemer committed
99

Pierre Kraemer's avatar
Pierre Kraemer committed
100
101
102
103
	inline const std::vector<Dart>& getInsideVertices() const { return insideVertices; }
	inline const std::vector<Dart>& getInsideEdges() const { return insideEdges; }
	inline const std::vector<Dart>& getInsideFaces() const { return insideFaces; }
	inline const std::vector<Dart>& getBorder() const { return border; }
Pierre Kraemer's avatar
Pierre Kraemer committed
104

Pierre Kraemer's avatar
Pierre Kraemer committed
105
106
107
108
	inline unsigned int getNbInsideVertices() const { return insideVertices.size(); }
	inline unsigned int getNbInsideEdges() const { return insideEdges.size(); }
	inline unsigned int getNbInsideFaces() const { return insideFaces.size(); }
	inline unsigned int getNbBorder() const { return border.size(); }
Pierre Kraemer's avatar
Pierre Kraemer committed
109
110
111
112
113
114
115
116
117
118
119
120
121

	template <typename PPFP>
	friend std::ostream& operator<<(std::ostream &out, const Collector<PPFP>& c);
};

/*********************************************************
 * Collector One Ring
 *********************************************************/

/*
 * insideVertices = centerDart
 * insideEdges = star (edges incident to centerDart)
 * insideFaces = triangles incident to centerDart
122
 * border = vertices of 1-ring -> link (set of adjacent vertices)
Pierre Kraemer's avatar
Pierre Kraemer committed
123
124
125
126
127
128
 *        = edges of 1-ring
 */
template <typename PFP>
class Collector_OneRing : public Collector<PFP>
{
public:
Sylvain Thery's avatar
Sylvain Thery committed
129
130
	Collector_OneRing(typename PFP::MAP& m, unsigned int thread=0):
		Collector<PFP>(m, thread) {}
Pierre Kraemer's avatar
Pierre Kraemer committed
131
132
	void collectAll(Dart d);
	void collectBorder(Dart d);
Pierre Kraemer's avatar
Pierre Kraemer committed
133
134
135
136
137
138
139
140
141
142
};

/*********************************************************
 * Collector Within Sphere
 *********************************************************/

/*
 * collect all primitives of the connected component containing "centerDart"
 * within the sphere of radius "radius" and center "position[centerDart]"
 * (hopefully) it defines a 2-manifold (if inserting border-vertices along the border-edges)
Basile Sauvage's avatar
Basile Sauvage committed
143
 * NB : is equivalent to Collector_Vertices with CollectorCriterion_VertexWithinSphere
Pierre Kraemer's avatar
Pierre Kraemer committed
144
145
146
147
148
 */
template <typename PFP>
class Collector_WithinSphere : public Collector<PFP>
{
protected:
149
	const VertexAttribute<typename PFP::VEC3>& position;
Pierre Kraemer's avatar
Pierre Kraemer committed
150
	typename PFP::REAL radius;
Pierre Kraemer's avatar
Pierre Kraemer committed
151
	typename PFP::REAL area;
152

Pierre Kraemer's avatar
Pierre Kraemer committed
153
public:
154
	Collector_WithinSphere(typename PFP::MAP& m, const VertexAttribute<typename PFP::VEC3>& p, typename PFP::REAL r = 0, unsigned int thread=0) :
Sylvain Thery's avatar
Sylvain Thery committed
155
		Collector<PFP>(m, thread),
Pierre Kraemer's avatar
Pierre Kraemer committed
156
157
158
		position(p),
		radius(r),
		area(0)
Pierre Kraemer's avatar
Pierre Kraemer committed
159
	{}
Pierre Kraemer's avatar
Pierre Kraemer committed
160
161
	inline void setRadius(typename PFP::REAL r) { radius = r; }
	inline typename PFP::REAL getRadius() const { return radius; }
162
	inline const VertexAttribute<typename PFP::VEC3>& getPosition() const { return position; }
Pierre Kraemer's avatar
Pierre Kraemer committed
163
164
165
166

	void collectAll(Dart d);
	void collectBorder(Dart d);

Pierre Kraemer's avatar
Pierre Kraemer committed
167
	void computeArea();
Pierre Kraemer's avatar
Pierre Kraemer committed
168
	inline typename PFP::REAL getArea() const { return area; }
Pierre Kraemer's avatar
Pierre Kraemer committed
169
170
};

171
/*********************************************************
172
 * Collector Normal Angle (Vertices)
173
174
175
176
177
178
 *********************************************************/

/*
 * collect all primitives of the connected component containing "centerDart"
 * the angle between the included vertices normal vectors and the central normal vector
 * stays under a given threshold
Basile Sauvage's avatar
Basile Sauvage committed
179
 * NB : is equivalent to Collector_Vertices with CollectorCriterion_VertexNormalAngle
180
181
182
183
184
185
186
187
188
189
190
191
 */
template <typename PFP>
class Collector_NormalAngle : public Collector<PFP>
{
protected:
	const VertexAttribute<typename PFP::VEC3>& normal ;
	typename PFP::REAL angleThreshold ;

public:
	Collector_NormalAngle(
		typename PFP::MAP& m,
		const VertexAttribute<typename PFP::VEC3>& n,
Sylvain Thery's avatar
Sylvain Thery committed
192
193
		typename PFP::REAL a,
		unsigned int thread=0
194
	) :	Collector<PFP>(m,thread), normal(n), angleThreshold(a)
195
196
197
198
199
200
201
202
203
	{}
	inline void setAngleThreshold(typename PFP::REAL a) { angleThreshold = a; }
	inline typename PFP::REAL getAngleThreshold() const { return angleThreshold; }
	inline const VertexAttribute<typename PFP::VEC3>& getNormal() const { return normal ; }

	void collectAll(Dart d) ;
	void collectBorder(Dart d) ;
};

Basile Sauvage's avatar
Basile Sauvage committed
204
/*********************************************************
Basile Sauvage's avatar
Basile Sauvage committed
205
 * Collector Criterions
Basile Sauvage's avatar
Basile Sauvage committed
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
 *********************************************************/
class CollectorCriterion
{
public :
	CollectorCriterion() {};
	virtual void init(Dart center) = 0;
	virtual bool isInside(Dart d) = 0;

};

template <typename PFP>
class CollectorCriterion_VertexNormalAngle : public CollectorCriterion
{ // tests if the angle between vertex normals is below some threshold
private :
	typedef typename PFP::VEC3 VEC3;
	typedef typename PFP::REAL REAL;

	const VertexAttribute<VEC3> & vertexNormals;
	REAL threshold;
	VEC3 centerNormal;
public :
	CollectorCriterion_VertexNormalAngle(const VertexAttribute<VEC3> & n, REAL th) :
		vertexNormals(n), threshold(th), centerNormal(0) {}

	void init (Dart center) {centerNormal = vertexNormals[center];}
	bool isInside (Dart d) {
		return ( Geom::angle(centerNormal, vertexNormals[d]) < threshold);
	}
};

Basile Sauvage's avatar
Basile Sauvage committed
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
template <typename PFP>
class CollectorCriterion_TriangleNormalAngle : public CollectorCriterion
{ // tests if the angle between vertex normals is below some threshold
private :
	typedef typename PFP::VEC3 VEC3;
	typedef typename PFP::REAL REAL;

	const FaceAttribute<VEC3> & faceNormals;
	REAL threshold;
	VEC3 centerNormal;
public :
	CollectorCriterion_TriangleNormalAngle(const FaceAttribute<VEC3> & n, REAL th) :
		faceNormals(n), threshold(th), centerNormal(0) {}

	void init (Dart center) {centerNormal = faceNormals[center];}
	bool isInside (Dart d) {
		return ( Geom::angle(centerNormal, faceNormals[d]) < threshold);
	}
};

Basile Sauvage's avatar
Basile Sauvage committed
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
template <typename PFP>
class CollectorCriterion_VertexWithinSphere : public CollectorCriterion
{ // tests if the distance between vertices is below some threshold
private :
	typedef typename PFP::VEC3 VEC3;
	typedef typename PFP::REAL REAL;

	const VertexAttribute<VEC3> & vertexPositions;
	REAL threshold;
	VEC3 centerPosition;
public :
	CollectorCriterion_VertexWithinSphere(const VertexAttribute<VEC3> & p, REAL th) :
		vertexPositions(p), threshold(th), centerPosition(0) {}

	void init (Dart center) {centerPosition = vertexPositions[center];}
	bool isInside (Dart d) {
		return (vertexPositions[d] - centerPosition).norm() < threshold ;
	}
};


Basile Sauvage's avatar
Basile Sauvage committed
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
/*********************************************************
 * Collector Vertices
 *********************************************************/

/*
 * collect all vertices of the connected component containing "centerDart"
 * within a distance to centerDart defined by the CollectorCriterion
 * (hopefully) it defines a 2-manifold (if inserting border-vertices along the border-edges)
 */
template <typename PFP>
class Collector_Vertices : public Collector<PFP>
{
protected:
	CollectorCriterion & crit;

public:
	Collector_Vertices(typename PFP::MAP& m, CollectorCriterion& c, unsigned int thread=0) :
		Collector<PFP>(m, thread),
		crit(c)
	{}

	void collectAll(Dart d);
	void collectBorder(Dart d);
};


303
304
305
306
307
308
309
310
/*********************************************************
 * Collector Normal Angle (Triangles)
 *********************************************************/

/*
 * collect all primitives of the connected component containing "centerDart"
 * the angle between the included triangles normal vectors and the central normal vector
 * stays under a given threshold
Basile Sauvage's avatar
Basile Sauvage committed
311
 * NB : is equivalent to Collector_Triangles with CollectorCriterion_TriangleNormalAngle
312
313
314
315
316
317
318
319
320
321
322
323
 */
template <typename PFP>
class Collector_NormalAngle_Triangles : public Collector<PFP>
{
protected:
	const FaceAttribute<typename PFP::VEC3>& normal ;
	typename PFP::REAL angleThreshold ;

public:
	Collector_NormalAngle_Triangles(
		typename PFP::MAP& m,
		const FaceAttribute<typename PFP::VEC3>& n,
324
325
326
		typename PFP::REAL a,
		unsigned int thread=0
	) :	Collector<PFP>(m,thread), normal(n), angleThreshold(a)
327
328
329
330
331
332
333
334
335
	{}
	inline void setAngleThreshold(typename PFP::REAL a) { angleThreshold = a; }
	inline typename PFP::REAL getAngleThreshold() const { return angleThreshold; }
	inline const VertexAttribute<typename PFP::VEC3>& getNormal() const { return normal ; }

	void collectAll(Dart d) ;
	void collectBorder(Dart d) ;
};

Basile Sauvage's avatar
Basile Sauvage committed
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
/*********************************************************
 * Collector Triangles
 *********************************************************/

/*
 * collect all triangles of the connected component containing "centerDart"
 * within a distance to centerDart defined by the CollectorCriterion
 */
template <typename PFP>
class Collector_Triangles : public Collector<PFP>
{
protected:
	CollectorCriterion & crit;

public:
	Collector_Triangles(typename PFP::MAP& m, CollectorCriterion& c, unsigned int thread=0) :
		Collector<PFP>(m,thread), crit(c)
	{}

	void collectAll(Dart d) ;
	void collectBorder(Dart d) ;
};

Basile Sauvage's avatar
Basile Sauvage committed
359
/*********************************************************
360
 * Collector Dijkstra_Vertices
Basile Sauvage's avatar
Basile Sauvage committed
361
362
363
364
365
 *********************************************************/

/*
 * collect all primitives of the connected component containing "centerDart"
 * within a distance < maxDist (the shortest path follows edges)
366
 * the edge length is specified in edge_cost attribute
Basile Sauvage's avatar
Basile Sauvage committed
367
 */
368

Basile Sauvage's avatar
Basile Sauvage committed
369
template <typename PFP>
370
class Collector_Dijkstra_Vertices : public Collector<PFP>
Basile Sauvage's avatar
Basile Sauvage committed
371
372
{
protected:
373
	const EdgeAttribute<typename PFP::REAL>& edge_cost;
Basile Sauvage's avatar
Basile Sauvage committed
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
	typename PFP::REAL maxDist;

	typedef struct
	{
		typename std::multimap<float,Dart>::iterator it ;
		bool valid ;
		static std::string CGoGNnameOfType() { return "DijkstraVertexInfo" ; }
	} DijkstraVertexInfo ;
	typedef NoMathIOAttribute<DijkstraVertexInfo> VertexInfo ;

	VertexAttribute<VertexInfo> vertexInfo ;

	std::multimap<float,Dart> front ;

public:
389
	Collector_Dijkstra_Vertices(typename PFP::MAP& m, const EdgeAttribute<typename PFP::REAL>& c, typename PFP::REAL d = 0, unsigned int thread=0) :
390
		Collector<PFP>(m,thread),
391
		edge_cost(c),
Basile Sauvage's avatar
Basile Sauvage committed
392
393
394
395
		maxDist(d)
	{
		vertexInfo = m.template addAttribute<VertexInfo, VERTEX>("vertexInfo");
	}
396
	~Collector_Dijkstra_Vertices(){
Basile Sauvage's avatar
Basile Sauvage committed
397
398
399
400
401
402
403
404
405
		this->map.removeAttribute(vertexInfo);
	}
	inline void init (Dart d) {Collector<PFP>::init(d); front.clear();}
	inline void setMaxDistance(typename PFP::REAL d) { maxDist = d; }
	inline typename PFP::REAL getMaxDist() const { return maxDist; }

	void collectAll(Dart d);
	void collectBorder(Dart d);
};
406
407


Basile Sauvage's avatar
Basile Sauvage committed
408
/*********************************************************
409
 * Collector Dijkstra
Basile Sauvage's avatar
Basile Sauvage committed
410
411
412
413
414
415
416
 *********************************************************/

/*
 * collect all primitives of the connected component containing "centerDart"
 * within a distance < maxDist (the shortest path follows edges)
 */
template <typename PFP>
417
class Collector_Dijkstra : public Collector<PFP>
Basile Sauvage's avatar
Basile Sauvage committed
418
419
{
protected:
420
	const VertexAttribute<typename PFP::VEC3>& position;
Basile Sauvage's avatar
Basile Sauvage committed
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
	typename PFP::REAL maxDist;

	typedef struct
	{
		typename std::multimap<float,Dart>::iterator it ;
		bool valid ;
		static std::string CGoGNnameOfType() { return "DijkstraVertexInfo" ; }
	} DijkstraVertexInfo ;
	typedef NoMathIOAttribute<DijkstraVertexInfo> VertexInfo ;

	VertexAttribute<VertexInfo> vertexInfo ;

	std::multimap<float,Dart> front ;

public:
436
	Collector_Dijkstra(typename PFP::MAP& m, const VertexAttribute<typename PFP::VEC3>& p, typename PFP::REAL d = 0, unsigned int thread=0) :
Basile Sauvage's avatar
Basile Sauvage committed
437
		Collector<PFP>(m,thread),
438
		position(p),
Basile Sauvage's avatar
Basile Sauvage committed
439
440
441
442
		maxDist(d)
	{
		vertexInfo = m.template addAttribute<VertexInfo, VERTEX>("vertexInfo");
	}
443
	~Collector_Dijkstra(){
Basile Sauvage's avatar
Basile Sauvage committed
444
445
446
447
448
		this->map.removeAttribute(vertexInfo);
	}
	inline void init (Dart d) {Collector<PFP>::init(d); front.clear();}
	inline void setMaxDistance(typename PFP::REAL d) { maxDist = d; }
	inline typename PFP::REAL getMaxDist() const { return maxDist; }
449
	inline const VertexAttribute<typename PFP::VEC3>& getPosition() const { return position; }
Basile Sauvage's avatar
Basile Sauvage committed
450
451
452

	void collectAll(Dart d);
	void collectBorder(Dart d);
453
454
455
private :
	inline float edgeLength (Dart d);
//	inline Dart oppositeVertex (Dart d);
Basile Sauvage's avatar
Basile Sauvage committed
456
457
458
};


459

Pierre Kraemer's avatar
Pierre Kraemer committed
460
461
} // namespace Selection

462
463
} // namespace Algo

Pierre Kraemer's avatar
Pierre Kraemer committed
464
465
466
467
468
} // namespace CGoGN

#include "Algo/Selection/collector.hpp"

#endif