1 /****************************************************************************
2 * VCGLib                                                            o o     *
3 * Visual and Computer Graphics Library                            o     o   *
4 *                                                                _   O  _   *
5 * Copyright(C) 2004-2017                                           \/)\/    *
6 * Visual Computing Lab                                            /\/|      *
7 * ISTI - Italian National Research Council                           |      *
8 *                                                                    \      *
9 * All rights reserved.                                                      *
10 *                                                                           *
11 * This program is free software; you can redistribute it and/or modify      *
12 * it under the terms of the GNU General Public License as published by      *
13 * the Free Software Foundation; either version 2 of the License, or         *
14 * (at your option) any later version.                                       *
15 *                                                                           *
16 * This program is distributed in the hope that it will be useful,           *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
19 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
20 * for more details.                                                         *
21 *                                                                           *
22 ****************************************************************************/
23 
24 #ifndef _VCGLIB_VORONOI_REMESHER_H
25 #define _VCGLIB_VORONOI_REMESHER_H
26 
27 #include <vcg/complex/complex.h>
28 #include <vcg/complex/algorithms/update/topology.h>
29 #include <vcg/complex/algorithms/refine.h>
30 #include <vcg/complex/algorithms/clean.h>
31 #include <vcg/complex/algorithms/voronoi_processing.h>
32 #include <vcg/complex/algorithms/point_sampling.h>
33 #include <vcg/complex/algorithms/crease_cut.h>
34 //#include <vcg/complex/algorithms/curve_on_manifold.h>
35 
36 #include <memory>
37 #include <string>
38 #include <vector>
39 #include <map>
40 #include <unordered_map>
41 #include <unordered_set>
42 #include <cmath>
43 #include <array>
44 #include <utility>
45 
46 
47 //#define DEBUG_VORO 1
48 
49 #ifdef DEBUG_VORO
50 #include <wrap/io_trimesh/export.h>
51 #include <QString>
52 #include <QElapsedTimer>
53 #endif
54 
55 namespace vcg {
56 namespace tri {
57 
58 class VoroEdgeMeshAux
59 {
60 	class EmEdgeType;
61 	class EmVertexType;
62 	class EUsedTypes : public vcg::UsedTypes<vcg::Use<EmVertexType>::AsVertexType,
63 	                                         vcg::Use<EmEdgeType>::AsEdgeType> {};
64 	class EmVertexType : public vcg::Vertex<EUsedTypes
65        ,vcg::vertex::Normal3d
66 	                          , vcg::vertex::Coord3d
67 	                          , vcg::vertex::BitFlags
68 	                          , vcg::vertex::VEAdj> {};
69 	class EmEdgeType   : public vcg::Edge<EUsedTypes
70 	        , vcg::edge::VertexRef
71 	        , vcg::edge::BitFlags
72 	        , vcg::edge::EEAdj
73 	        , vcg::edge::VEAdj> {};
74 public:
75 	class EdgeMeshType : public vcg::tri::TriMesh<std::vector<EmVertexType>, std::vector<EmEdgeType> >
76 	{
77 	public:
~EdgeMeshType()78 		~EdgeMeshType()
79 		{
80 			this->Clear();
81 			this->ClearAttributes();
82 		}
83 	};
84 };
85 
86 template <class MeshType>
87 class Remesher
88 {
89 public:
90 	typedef Remesher                  ThisType;
91 
92 	typedef MeshType                      Mesh;
93 	typedef typename Mesh::ScalarType     ScalarType;
94 	typedef typename Mesh::CoordType      CoordType;
95 	typedef typename Mesh::FaceType       FaceType;
96 	typedef typename Mesh::FacePointer    FacePointer;
97 	typedef typename Mesh::VertexType     VertexType;
98 	typedef typename Mesh::VertexPointer  VertexPointer;
99 	typedef typename Mesh::FaceIterator   FaceIterator;
100 	typedef typename Mesh::VertexIterator VertexIterator;
101 
102 	typedef std::shared_ptr<Mesh>         MeshPtr;
103 
104 protected:
105 	typedef face::Pos<FaceType>                    PosType;
106 
107 	typedef typename VoroEdgeMeshAux::EdgeMeshType EdgeMeshType;
108 
109 	/// \brief splitCC split the provided mesh into connected components.
110 	/// \param mesh the inputMesh.
111 	/// \return the vector of connected components (meshes) for the input model
112 	/// (if the input mesh is a single connected component returns an empty vector).
113 	///
splitCC(MeshType & mesh)114 	inline static std::vector<MeshPtr> splitCC(MeshType & mesh)
115 	{
116 		std::vector<MeshPtr> ret;
117 
118 		// find the connected components
119 		std::vector<std::pair<int, typename MeshType::FacePointer> > CCV;
120 		Clean<MeshType>::ConnectedComponents(mesh, CCV);
121 
122 		if (CCV.size() == 1)
123 			return ret;
124 		for(size_t i=0; i<CCV.size(); ++i)
125 		{
126 			UpdateSelection<MeshType>::Clear(mesh);
127 			CCV[i].second->SetS();
128 			UpdateSelection<MeshType>::FaceConnectedFF(mesh);
129 			ret.push_back(std::make_shared<MeshType>());
130 			Append<MeshType, MeshType>::MeshCopy(*(ret.back()), mesh, true);
131 		}
132 
133 		return ret;
134 	}
135 
136 public:
137 	static const int VoroRelaxationStep = 10;
138 
139 	///
140 	/// \brief Remesh the main function that remeshes a mesh preserving creases.
141 	/// \param original the mesh
142 	/// \param samplingRadius is the sampling radius for remeshing
143 	/// \param borderCreaseAngleDeg is the angle treshold for preserving corner points on the mesh boundary
144 	/// \param internalCreaseAngleDeg is the angle treshold for preserving creases on the mesh surface (if this value is < 0 it is set to borderCreaseAngleDeg)
145 	/// \return the remeshed mesh
146 	///
147 	static inline MeshPtr Remesh(Mesh & original, const ScalarType samplingRadius, const ScalarType borderCreaseAngleDeg = 0.0, const ScalarType internalCreaseAngleDeg = -1.0)
148 	{
149 		RequireFFAdjacency(original);
150 		RequireVFAdjacency(original);
151 
152 		UpdateTopology<Mesh>::FaceFace(original);
153 		UpdateFlags<Mesh>::FaceBorderFromFF(original);
154 		UpdateFlags<Mesh>::VertexBorderFromFaceAdj(original);
155 
156 		if (Clean<Mesh>::CountNonManifoldEdgeFF(original) > 0)
157 		{
158 			std::cout << "Input mesh has non manifold edges" << std::endl;
159 			return nullptr;
160 		}
161 
162 		const ScalarType borderAngleDeg = std::max(ScalarType(0), borderCreaseAngleDeg);
163 		const ScalarType creaseAngleDeg = internalCreaseAngleDeg < 0 ? borderAngleDeg : internalCreaseAngleDeg;
164 
165 		// split on creases
166 		if (creaseAngleDeg > 0)
167 		{
168 			CreaseCut<Mesh>(original, vcg::math::ToRad(creaseAngleDeg));
169 			Allocator<Mesh>::CompactEveryVector(original);
170 			UpdateTopology<Mesh>::FaceFace(original);
171 			UpdateFlags<Mesh>::FaceBorderFromFF(original);
172 			UpdateFlags<Mesh>::VertexBorderFromFaceAdj(original);
173 		}
174 
175 		// Mark the non manifold border vertices as visited on the input mesh
176 		// TODO maybe optimize this
177 		{
178 			// extract border mesh
179 			EdgeMeshType em;
180 			ThisType::ExtractMeshBorders(original, em);
181 
182 			// get the border edge mesh and leave the non manifold vertices only
183 			tri::Allocator<EdgeMeshType>::CompactEveryVector(em);
184 			vcg::tri::Clean<EdgeMeshType>::SelectNonManifoldVertexOnEdgeMesh(em);
185 			for (EdgeMeshType::VertexType & v : em.vert)
186 			{
187 				if (!v.IsS())
188 				{
189 					tri::Allocator<EdgeMeshType>::DeleteVertex(em, v);
190 				}
191 			}
192 			tri::Allocator<EdgeMeshType>::CompactVertexVector(em);
193 
194 
195 			// clear visited vertices
196 			tri::UpdateFlags<Mesh>::VertexClearV(original);
197 			if (em.vn != 0)
198 			{
199 				// iterate over the mesh and mark as visited all the matching vertices with the non manifold border
200 				tri::UpdateBounding<EdgeMeshType>::Box(em);
201 				EdgeMeshType::BoxType bbox = em.bbox;
202 				bbox.Offset(bbox.Diag()/1000.0);
203 				typedef SpatialHashTable<EdgeMeshType::VertexType, EdgeMeshType::ScalarType> HashVertexGrid;
204 				HashVertexGrid HG;
205 				HG.Set(em.vert.begin(), em.vert.end(), bbox);
206 
207 				typedef EdgeMeshType::CoordType Coord;
208 				EdgeMeshType::ScalarType dist_upper_bound = bbox.Diag()/1000.0;
209 				for (VertexType & v : original.vert)
210 				{
211 					EdgeMeshType::ScalarType dist;
212 					EdgeMeshType::VertexType * nonManifoldVertex = GetClosestVertex<EdgeMeshType,HashVertexGrid>(em, HG, Coord::Construct(v.cP()), dist_upper_bound, dist);
213 					if (nonManifoldVertex != NULL && dist == 0)
214 					{
215 						v.SetV();
216 					}
217 				}
218 			}
219 
220 		}
221 #ifdef DEBUG_VORO
222 		io::Exporter<Mesh>::Save(original, "creaseSplit.ply", io::Mask::IOM_VERTCOLOR);
223 #endif
224 
225 		// One CC
226 		std::vector<MeshPtr> ccs = splitCC(original);
227 		if (ccs.empty())
228 		{
229 			return RemeshOneCC(original, samplingRadius, borderAngleDeg);
230 		}
231 
232 		// Multiple CCs
233 //		std::cout << "Remeshing " << ccs.size() << " components" << std::endl;
234 		for (size_t i=0; i<ccs.size(); i++)
235 		{
236 //			std::cout << "Remeshing component " << (i+1) << "/" << ccs.size() << std::endl;
237 			ccs[i] = RemeshOneCC(*ccs[i], samplingRadius, borderAngleDeg, i);
238 		}
239 
240 		MeshPtr ret = std::make_shared<Mesh>();
241 		for (MeshPtr & mesh : ccs)
242 		{
243 			Append<Mesh,Mesh>::Mesh(*ret, *mesh);
244 		}
245 		Clean<Mesh>::RemoveDuplicateVertex(*ret, true);
246 		return ret;
247 	}
248 
249 protected:
debugCallBack(const int pos,const char * str)250   static bool debugCallBack(const int pos, const char * str) { printf("Processing: %s \n",str); fflush(stdout); return true;}
251 
252 	///
253 	/// \brief RemeshOneCC the function that remeshes a single connected component mesh preserving its boundary (consistently for eventually adjacent meshes).
254 	/// \param original the mesh
255 	/// \param samplingRadius is the sampling radius for remeshing
256 	/// \param borderCreaseAngleDeg is the angle treshold for preserving corner points on the mesh boundary
257 	/// \return the remeshed mesh
258 	///
259 	static inline MeshPtr RemeshOneCC(Mesh & original, const ScalarType samplingRadius, const ScalarType borderCreaseAngleDeg = 0.0, int idx = 0)
260 	{
261 //		double timeBorders = 0;
262 //		double timePoisson = 0;
263 //		double timeRelax = 0;
264 //		double timeSeed = 0;
265 //		double timeSources = 0;
266 //		double timeDelaunay = 0;
267 //		QElapsedTimer timer;
268 //		timer.start();
269 
270 		(void)idx;
271 
272 		RequireCompactness(original);
273 		RequirePerFaceFlags(original);
274 
275 		UpdateTopology<Mesh>::FaceFace(original);
276 		UpdateFlags<Mesh>::FaceBorderFromFF(original);
277 		UpdateFlags<Mesh>::VertexBorderFromFaceAdj(original);
278 
279 #ifdef DEBUG_VORO
280 		io::ExporterPLY<MeshType>::Save(original, QString("cc_%1.ply").arg(idx).toStdString().c_str(), io::Mask::IOM_VERTCOLOR);
281 #endif
282 
283 		// Resample border
284 		Mesh poissonEdgeMesh;
285 		{
286 			typedef typename EdgeMeshType::CoordType Coord;
287 
288 			EdgeMeshType em;
289 			ThisType::ExtractMeshBorders(original, em);
290 			Allocator<EdgeMeshType>::CompactVertexVector(em);
291 			Allocator<EdgeMeshType>::CompactEdgeVector(em);
292 			// split on non manifold vertices of edgemesh
293 			vcg::tri::Clean<EdgeMeshType>::SelectNonManifoldVertexOnEdgeMesh(em);
294 			{
295 				// select also the visited vertices (coming from the non manifold vertices of the whole crease-cut mesh)
296 				for (auto & v : em.vert)
297 				{
298 					if (v.IsV()) { v.SetS(); }
299 				}
300 			}
301 			const int manifoldSplits = vcg::tri::Clean<EdgeMeshType>::SplitSelectedVertexOnEdgeMesh(em);
302 			(void)manifoldSplits;
303 
304 #ifdef DEBUG_VORO
305 			std::cout << manifoldSplits << " non-manifold splits" << std::endl;
306 			io::ExporterOBJ<EdgeMeshType>::Save(em, QString("edgeMesh_%1.obj").arg(idx).toStdString().c_str(), io::Mask::IOM_EDGEINDEX);
307 #endif
308 
309 			// eventually split on 'creases'
310 			if (borderCreaseAngleDeg > 0.0)
311 			{
312 				// split creases
313 				UpdateFlags<EdgeMeshType>::VertexClearS(em);
314 				UpdateFlags<EdgeMeshType>::VertexClearV(em);
315 				Clean<EdgeMeshType>::SelectCreaseVertexOnEdgeMesh(em, vcg::math::ToRad(borderCreaseAngleDeg));
316 				const int splits = Clean<EdgeMeshType>::SplitSelectedVertexOnEdgeMesh(em);
317 				(void)splits;
318 
319 #ifdef DEBUG_VORO
320 				std::cout << splits << " splits" << std::endl;
321 				io::ExporterOBJ<EdgeMeshType>::Save(em, QString("edgeMesh_split_%1.obj").arg(idx).toStdString().c_str(), io::Mask::IOM_EDGEINDEX);
322 #endif
323 			}
324 
325 			// Samples vector
326 			std::vector<Coord> borderSamples;
327 			TrivialSampler<EdgeMeshType> ps(borderSamples);
328 
329 			// uniform edge sampling
330 			UpdateTopology<EdgeMeshType>::EdgeEdge(em);
331 			SurfaceSampling<EdgeMeshType>::EdgeMeshUniform(em, ps, samplingRadius, SurfaceSampling<EdgeMeshType>::Round);
332 			BuildMeshFromCoordVector(poissonEdgeMesh, borderSamples);
333 			UpdateBounding<Mesh>::Box(poissonEdgeMesh);
334 
335 			// remove duplicate vertices
336 			Clean<Mesh>::RemoveDuplicateVertex(poissonEdgeMesh, false);
337 			Allocator<Mesh>::CompactVertexVector(poissonEdgeMesh);
338 
339 			// select all vertices (to mark them fixed)
340 			UpdateFlags<Mesh>::VertexSetS(poissonEdgeMesh);
341 
342 #ifdef DEBUG_VORO
343 			io::ExporterPLY<MeshType>::Save(poissonEdgeMesh, QString("borderMesh_%1.ply").arg(idx).toStdString().c_str(), io::Mask::IOM_VERTCOLOR);
344 #endif
345 		}
346 
347 //		timeBorders = timer.restart() / 1000.0;
348 
349 		typedef VoronoiProcessing<Mesh>            Voronoi;
350 		typedef TrivialSampler<Mesh>               BaseSampler;
351 		typedef SurfaceSampling<Mesh, BaseSampler> SurfaceSampler;
352 		typedef SurfaceSampling<Mesh, FixSampler>  SurfaceFixSampler;
353 
354 		// copy original mesh
355 		Mesh baseMesh;
356 		Append<Mesh, Mesh>::MeshCopy(baseMesh, original, false, true);
357 
358 		// refine to obtain a base mesh
359 		VoronoiProcessingParameter vpp;
360 		vpp.refinementRatio = 5.0f;
361     vpp.lcb = debugCallBack;
362 
363 		Voronoi::PreprocessForVoronoi(baseMesh, samplingRadius, vpp);
364 
365 		// Poisson sampling preserving border
366 		std::vector<CoordType> seedPointVec;
367 		std::vector<bool>      seedFixedVec;
368 		FixSampler fix_sampler(seedPointVec, seedFixedVec);
369 
370 		// montecarlo sampler
371 		std::vector<CoordType> sampleVec;
372 		BaseSampler mps(sampleVec);
373 
374 		// NOTE in order to make the results consistent the random sampling generator is initialized with the same value
375 		SurfaceSampler::SamplingRandomGenerator().initialize(5489u);
376 
377 		// Montecarlo oversampling
378 		Mesh montecarloMesh;
379 //		const int poissonCount = SurfaceSampler::ComputePoissonSampleNum(original, samplingRadius)/* * 0.7*/;
380 		int poissonCount = 0;
381 		{
382 			const ScalarType meshArea = Stat<Mesh>::ComputeMeshArea(original);
383 			const ScalarType meshBoundary = Stat<Mesh>::ComputeBorderLength(original);
384 			const double factor = math::Sqrt(3)/2;
385 			const ScalarType areaPerSample = samplingRadius*samplingRadius * factor;
386 			poissonCount = meshArea / areaPerSample - meshBoundary * samplingRadius * factor * 0.5; // totalArea / (r^2 * sqrt(3)/2) - (totalBoundary * r * sqrt(3)/4)
387 		}
388 
389 //		std::cout << "poisson Count: " << poissonCount << std::endl;
390 		if (poissonCount <= 0)
391 		{
392 			// no need for internal sampling
393 			for (auto vi = poissonEdgeMesh.vert.begin(); vi != poissonEdgeMesh.vert.end(); vi++)
394 			{
395 				fix_sampler.AddVert(*vi);
396 			}
397 		}
398 		else
399 		{
400 			// Montecarlo poisson sampling
401 			SurfaceSampler::MontecarloPoisson(original, mps, poissonCount * 50);
402 			BuildMeshFromCoordVector(montecarloMesh,sampleVec);
403 
404 #ifdef DEBUG_VORO
405 			io::ExporterPLY<MeshType>::Save(montecarloMesh, QString("montecarloMesh_%1.ply").arg(idx).toStdString().c_str());
406 #endif
407 
408 			// Poisson disk pruning initialized with edges
409 			typename SurfaceFixSampler::PoissonDiskParam pp;
410 			pp.preGenMesh = &poissonEdgeMesh;
411 			pp.preGenFlag = true;
412 			pp.bestSampleChoiceFlag = true;
413 			pp.bestSamplePoolSize = 10;
414 			pp.randomSeed = 7;
415 			SurfaceFixSampler::PoissonDiskPruning(fix_sampler, montecarloMesh, samplingRadius, pp);
416 
417 		}
418 
419 #ifdef DEBUG_VORO
420 			Mesh poissonMesh;
421 			BuildMeshFromCoordVector(poissonMesh,seedPointVec);
422 			io::ExporterPLY<MeshType>::Save(poissonMesh, QString("poissonMesh_%1.ply").arg(idx).toStdString().c_str());
423 #endif
424 
425 //		timePoisson = timer.restart() / 1000.0;
426 
427 //		std::cout << "poisson samples " << seedPointVec.size() << std::endl;
428 
429 		// not enough points
430 		if (seedPointVec.size() < 3)
431 		{
432 			return std::make_shared<Mesh>();
433 		}
434 
435 		// TODO: rimettere a posto
436 		// restricted relaxation with fixed points
437 		Voronoi::RandomGenerator().initialize(5489u);
438 		vpp.seedPerturbationProbability = 0.2f;
439 		vpp.seedPerturbationAmount      = 0.005f;
440 		Voronoi::RestrictedVoronoiRelaxing(baseMesh, seedPointVec, seedFixedVec, VoroRelaxationStep, vpp);
441 		vpp.seedPerturbationProbability = 0.0f;
442 		Voronoi::RestrictedVoronoiRelaxing(baseMesh, seedPointVec, seedFixedVec, VoroRelaxationStep/2, vpp);
443 //		Voronoi::RestrictedVoronoiRelaxing(baseMesh, seedPointVec, seedFixedVec, VoroRelaxationStep, vpp);
444 
445 
446 #ifdef DEBUG_VORO
447 		BuildMeshFromCoordVector(poissonMesh,seedPointVec);
448 		io::ExporterPLY<MeshType>::Save(poissonMesh, QString("relaxedMesh_%1.ply").arg(idx).toStdString().c_str());
449 #endif
450 
451 //		timeRelax = timer.restart() / 1000.0;
452 
453 		// FAIL?
454 		MeshPtr finalMeshPtr = std::make_shared<Mesh>();
455 		std::vector<VertexType *> seedVertexVec;
456 //				Voronoi::SeedToVertexConversion(baseMesh, seedPointVec, seedVertexVec, false);
457 		ThisType::SeedToFixedBorderVertexConversion(baseMesh, samplingRadius, seedPointVec, seedFixedVec, seedVertexVec);
458 		EuclideanDistance<Mesh> dd;
459 //		timeSeed = timer.restart() / 1000.0;
460 
461 //		std::cout << "BEGIN compute vertex sources (basemesh vn:" << baseMesh.VN() << " fn:" << baseMesh.FN() << ")" << std::endl;
462 		Voronoi::ComputePerVertexSources(baseMesh, seedVertexVec, dd);
463 //		std::cout << "END   compute vertex sources" << std::endl;
464 //		timeSources = timer.restart() / 1000.0;
465 		// traditional
466 //		Voronoi::ConvertDelaunayTriangulationToMesh(baseMesh, *finalMeshPtr, seedVertexVec, false);
467 		// border-preserving
468 		Voronoi::ConvertDelaunayTriangulationExtendedToMesh(baseMesh, *finalMeshPtr, seedVertexVec);
469 
470 #ifdef DEBUG_VORO
471 		io::ExporterPLY<MeshType>::Save(*finalMeshPtr, QString("voroMesh_%1.ply").arg(idx).toStdString().c_str());
472 		io::ExporterPLY<MeshType>::Save(baseMesh, QString("baseMesh_%1.ply").arg(idx).toStdString().c_str(), io::Mask::IOM_VERTCOLOR);
473 #endif
474 
475 //		timeDelaunay = timer.elapsed() / 1000.0;
476 
477 //		std::cout << "border:   " << timeBorders  << std::endl
478 //		          << "poisson:  " << timePoisson  << std::endl
479 //		          << "relax:    " << timeRelax    << std::endl
480 //		          << "seed:     " << timeSeed     << std::endl
481 //		          << "sources:  " << timeSources  << std::endl
482 //		          << "delaunay: " << timeDelaunay << std::endl;
483 
484 		return finalMeshPtr;
485 	}
486 
ExtractMeshBorders(Mesh & mesh,EdgeMeshType & sides)487 	static inline void ExtractMeshBorders(Mesh & mesh, EdgeMeshType & sides)
488 	{
489 		RequireFFAdjacency(mesh);
490 
491 		// clean the edge mesh containing the borders
492 		sides.Clear();
493 
494 		// gather into separate vertices lists
495 		std::vector<std::vector<VertexType *> > edges;
496 
497 		for (auto fi = mesh.face.begin(); fi != mesh.face.end(); fi++)
498 		{
499 			for (int e=0; e<fi->VN(); e++)
500 			{
501 				if (vcg::face::IsBorder(*fi, e))
502 				{
503 					std::vector<VertexType *> tmp;
504 					tmp.push_back(fi->V(e));
505 					tmp.push_back(fi->V((e+1)%fi->VN()));
506 					edges.push_back(tmp);
507 				}
508 			}
509 		}
510 
511 		// convert to edge mesh
512 		for (auto & e : edges)
513 		{
514 			assert(e.size() >= 2);
515 
516 			std::vector<typename EdgeMeshType::VertexType *> newVtx;
517 
518 			// insert new vertices and store their pointer
519 			auto vi = Allocator<EdgeMeshType>::AddVertices(sides, e.size());
520 			for (const auto & v : e)
521 			{
522 				vi->ImportData(*v);
523 				newVtx.push_back(&(*vi++));
524 			}
525 
526 			auto ei = Allocator<EdgeMeshType>::AddEdges(sides, e.size() - 1);
527 			for (int i=0; i<static_cast<int>(e.size() - 1); i++)
528 			{
529 				ei->V(0) = newVtx[i];
530 				ei->V(1) = newVtx[i+1];
531 				ei++;
532 			}
533 		}
534 
535 		Clean<EdgeMeshType>::RemoveDuplicateVertex(sides);
536 	}
537 
SeedToFixedBorderVertexConversion(MeshType & m,const ScalarType samplingRadius,const std::vector<CoordType> & seedPVec,const std::vector<bool> & seedFixed,std::vector<VertexType * > & seedVVec)538 	static void SeedToFixedBorderVertexConversion(MeshType & m,
539 	                                              const ScalarType samplingRadius,
540 	                                              const std::vector<CoordType> & seedPVec,
541 	                                              const std::vector<bool> & seedFixed,
542 	                                              std::vector<VertexType *> & seedVVec)
543 	{
544 		typedef typename vcg::SpatialHashTable<VertexType, ScalarType> HashVertexGrid;
545 		seedVVec.clear();
546 
547 		UpdateTopology<MeshType>::FaceFace(m);
548 		UpdateFlags<MeshType>::VertexBorderFromFaceAdj(m);
549 
550 		typename MeshType::BoxType bbox = m.bbox;
551 		bbox.Offset(bbox.Diag()/100.0);
552 
553 		// internal vertices grid
554 		HashVertexGrid HG;
555 		HG.Set(m.vert.begin(),m.vert.end(), bbox);
556 
557 		// boundary vertices grid
558 		MeshType borderMesh;
559 		HashVertexGrid borderHG;
560 		{
561 			// get border vertices and build another mesh
562 			std::vector<CoordType> borderPts;
563 			for (auto vit=m.vert.begin(); vit!=m.vert.end(); vit++)
564 			{
565 				if (!vit->IsD() && vit->IsB())
566 					borderPts.push_back(vit->cP());
567 			}
568 			if (!borderPts.empty())
569 			{
570 				BuildMeshFromCoordVector(borderMesh,borderPts);
571 				borderMesh.bbox = m.bbox;
572 				borderHG.Set(borderMesh.vert.begin(), borderMesh.vert.end(), bbox);
573 			}
574 		}
575 
576 		const ScalarType dist_upper_bound=samplingRadius*4;
577 		VertexType * vp = NULL;
578 
579 		for( size_t i = 0; i < seedPVec.size(); i++)
580 		{
581 			const CoordType & p = seedPVec[i];
582 			const bool fixed    = seedFixed[i];
583 			if (!fixed)
584 			{
585 				ScalarType dist;
586 				vp = GetClosestVertex<MeshType,HashVertexGrid>(m, HG, p, dist_upper_bound, dist);
587 				if (vp)
588 				{
589 					seedVVec.push_back(vp);
590 				}
591 			}
592 			else
593 			{
594 				vp = NULL;
595 
596 				ScalarType dist;
597 				VertexType * borderVp = GetClosestVertex<MeshType,HashVertexGrid>(borderMesh, borderHG, p, dist_upper_bound, dist);
598 
599 				if (borderVp)
600 				{
601 					std::vector<ScalarType>   dist;
602 					std::vector<VertexType *> vps;
603 					std::vector<CoordType>    pts;
604 
605 					//			vp = GetClosestVertex<MeshType,HashVertexGrid>(m, HG, borderVp->cP(), dist_upper_bound, dist);
606 					unsigned int n = GetKClosestVertex<MeshType,HashVertexGrid>(m, HG, 16, borderVp->cP(), dist_upper_bound, vps, dist, pts);
607 					if (n>0)
608 					{
609 						ScalarType d = dist[0];
610 						seedVVec.push_back(vps[0]);
611 						assert(dist.size() == size_t(n));
612 						for (size_t j=1; j<dist.size(); j++)
613 						{
614 							if (dist[j] <= d)
615 							{
616 								seedVVec.push_back(vps[j]);
617 								d = dist[j];
618 							}
619 							else
620 							{
621 								break;
622 							}
623 						}
624 					}
625 				}
626 			}
627 		}
628 	}
629 
630 
631 
632 	///
633 	/// \brief The FixSampler class is used with poisson disk pruning to preserve selected vertices and
634 	/// keep an auxiliary vector indicating wether the sample is fixed or not
635 	///
636 	class FixSampler
637 	{
638 	public:
639 		typedef typename MeshType::CoordType  CoordType;
640 		typedef typename MeshType::VertexType VertexType;
641 
FixSampler(std::vector<CoordType> & samples,std::vector<bool> & fixed)642 		FixSampler(std::vector<CoordType> & samples, std::vector<bool> & fixed)
643 		    : sampleVec(samples)
644 		    , fixedVec (fixed)
645 		{
646 			reset();
647 		}
648 
reset()649 		void reset()
650 		{
651 			sampleVec.clear();
652 			fixedVec .clear();
653 		}
654 
AddVert(const VertexType & p)655 		void AddVert(const VertexType &p)
656 		{
657 			sampleVec.push_back(p.cP());
658 			fixedVec .push_back(p.IsS());
659 		}
660 
661 	private:
662 		std::vector<CoordType> & sampleVec;
663 		std::vector<bool>      & fixedVec;
664 	};
665 
666 };
667 } // end namespace tri
668 } // end namespace vcg
669 
670 #endif // _VCGLIB_VORONOI_REMESHER_H
671