<commit_before>/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps  *
* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France       *
*                                                                              *
* 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.           *
*                                                                              *
* Web site: http://cgogn.unistra.fr/                                           *
* Contact information: <EMAIL>                                        *
*                                                                              *
*******************************************************************************/

#include <gtest/gtest.h>

#include <core/cmap/cmap2.h>
#include <core/cmap/cmap2_builder.h>

namespace cgogn
{

#define NB_MAX 1000

/*!
 * \brief The CMap2TopoTest class implements topological tests on CMap2
 * It derives from CMap2 to allow the test of protected methods
 *
 * Note that these tests, check that the topological operators perform as wanted
 * but do neither tests the containers (refs_, used_, etc.) or the iterators.
 * These last tests are implemented in another test suite.
 */
class CMap2TopoTest : public CMap2<DefaultMapTraits>, public ::testing::Test
{

public:

	using Inherit = CMap2<DefaultMapTraits>;
	using MapBuilder = CMap2Builder_T<DefaultMapTraits>;
	using Vertex = CMap2TopoTest::Vertex;
	using Edge   = CMap2TopoTest::Edge;
	using Face   = CMap2TopoTest::Face;
	using Volume   = CMap2TopoTest::Volume;
	using VertexMarker = CMap2TopoTest::CellMarker<Vertex::ORBIT>;

protected:

	/*!
	 * \brief A vector of darts on which the methods are tested.
	 */
	std::vector<Dart> darts_;

	/*!
	 * \brief Generate a random set of faces.
	*/
	CMap2TopoTest()
	{
		darts_.reserve(NB_MAX);
		std::srand(static_cast<unsigned int>(std::time(0)));
	}

	/*!
	 * \brief Tests if the open vertex of d contains a specified dart e.
	 * The method supposes that the given dart d is the first dart
	 * of the open PHI21 orbit (i.e. phi2(d) == d)
	 */
	bool same_open_vertex(Dart d, Dart e)
	{
		cgogn_assert(phi2(d) == d);
		Dart it = d;
		Dart it1 = phi_1(it);

		while (it != e && phi2(it1) != it1)
		{
			it = phi2(it1);
			it1 = phi_1(it);
		}
		if (it == e) return true;
		return false;
	}

	/*!
	 * \brief Tests if the volume of d contains a specified dart e.
	 * The method does not exploit the indexing information
	 */
	bool same_volume(Dart d, Dart e)
	{
		bool result = false;

		foreach_dart_of_orbit_until(Volume(d), [&](Dart vit)
		{
			if (vit == e) result = true;
			return !result;
		});

		return result;
	}

	/*!
	 * \brief Embed an open vertex d on a new attribute.
	 * The method supposes that the given dart d is the first dart
	 * of the open PHI21 orbit (i.e. phi2(d) == d)
	 */
	void new_open_vertex_embedding(Dart d)
	{
		cgogn_assert(phi2(d) == d);
		const unsigned int emb = add_attribute_element<Vertex::ORBIT>();

		Dart it = d;
		Dart it1 = phi_1(it);

		set_embedding<Vertex>(it, emb);
		while (phi2(it1) != it1)
		{
			it = phi2(it1);
			it1 = phi_1(it);
			set_embedding<Vertex>(it, emb);
		}
	}

	/*!
	 * \brief Generate a random set of faces and put them in darts_
	 * \return The total number of added vertices.
	 * The face size ranges from 1 to 10.
	 * A random dart of each face is put in the darts_ array.
	 */
	unsigned int add_faces(unsigned int n)
	{
		darts_.clear();
		unsigned int count = 0u;
		for (unsigned int i = 0u; i < n; ++i)
		{
			unsigned int n = 1u + std::rand() % 10u;
			Dart d = add_face_topo(n);
			count += n;

			n = std::rand() % 10u;
			while (n-- > 0u) d = phi1(d);

			darts_.push_back(d);
		}
		return count;
	}

	/*!
	 * \brief Generate a set of closed surfaces with arbitrary genus.
	 */
	void add_closed_surfaces()
	{
		darts_.clear();
		unsigned int n;

		// Generate NB_MAX random 1-faces (without boundary)
		for (unsigned int i = 0u; i < NB_MAX; ++i)
		{
			n = 1u + std::rand() % 10;
			Dart d = Inherit::Inherit::add_face_topo(n);
			darts_.push_back(d);
		}
		// Sew some pairs off 1-edges
		for (unsigned int i = 0u; i < 3u * NB_MAX; ++i)
		{
			Dart e1 = darts_[std::rand() % NB_MAX];
			n = std::rand() % 10u;
			while (n-- > 0u) e1 = phi1(e1);

			Dart e2 = darts_[std::rand() % NB_MAX];
			n = std::rand() % 10u;
			while (n-- > 0u) e2 = phi1(e2);

			n = 1 + std::rand() % 3u;
			while (n-- > 0u && phi2(e1) == e1 && phi2(e2) == e2 && e2 != e1)
			{
				phi2_sew(e2, e1);
				e1 = phi1(e1);
				e2 = phi_1(e2);
			}
		}
		// Close de map
		MapBuilder mbuild(*this);
		foreach_dart([&](Dart d)
		{
			if (phi2(d) == d) mbuild.close_hole_topo(d);
		});
	}
};

/*!
 * \brief The random generated maps used in the tests are sound.
 */
TEST_F(CMap2TopoTest, random_map_generators)
{
	EXPECT_EQ(nb_darts(), 0u);

	add_faces(NB_MAX);
	EXPECT_TRUE(check_map_integrity());

	add_closed_surfaces();
	EXPECT_TRUE(check_map_integrity());
}

/*!
 * \brief Sewing and unsewing darts correctly changes the topological relations.
 * The test performs NB_MAX sewing and unsewing on randomly chosen dart of darts_.
 * The map integrity is not preserved (this test creates fixed points for PHI2).
 */
TEST_F(CMap2TopoTest, phi2_sew_unsew)
{<commit_msg>using close_map in cmap2 test<commit_after>/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps  *
* Copyright (C) 2015, IGG Group, ICube, University of Strasbourg, France       *
*                                                                              *
* 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.           *
*                                                                              *
* Web site: http://cgogn.unistra.fr/                                           *
* Contact information: <EMAIL>                                        *
*                                                                              *
*******************************************************************************/

#include <gtest/gtest.h>

#include <core/cmap/cmap2.h>
#include <core/cmap/cmap2_builder.h>

namespace cgogn
{

#define NB_MAX 1000

/*!
 * \brief The CMap2TopoTest class implements topological tests on CMap2
 * It derives from CMap2 to allow the test of protected methods
 *
 * Note that these tests, check that the topological operators perform as wanted
 * but do neither tests the containers (refs_, used_, etc.) or the iterators.
 * These last tests are implemented in another test suite.
 */
class CMap2TopoTest : public CMap2<DefaultMapTraits>, public ::testing::Test
{

public:

	using Inherit = CMap2<DefaultMapTraits>;
	using MapBuilder = CMap2Builder_T<DefaultMapTraits>;
	using Vertex = CMap2TopoTest::Vertex;
	using Edge   = CMap2TopoTest::Edge;
	using Face   = CMap2TopoTest::Face;
	using Volume   = CMap2TopoTest::Volume;
	using VertexMarker = CMap2TopoTest::CellMarker<Vertex::ORBIT>;

protected:

	/*!
	 * \brief A vector of darts on which the methods are tested.
	 */
	std::vector<Dart> darts_;

	/*!
	 * \brief Generate a random set of faces.
	*/
	CMap2TopoTest()
	{
		darts_.reserve(NB_MAX);
		std::srand(static_cast<unsigned int>(std::time(0)));
	}

	/*!
	 * \brief Tests if the open vertex of d contains a specified dart e.
	 * The method supposes that the given dart d is the first dart
	 * of the open PHI21 orbit (i.e. phi2(d) == d)
	 */
	bool same_open_vertex(Dart d, Dart e)
	{
		cgogn_assert(phi2(d) == d);
		Dart it = d;
		Dart it1 = phi_1(it);

		while (it != e && phi2(it1) != it1)
		{
			it = phi2(it1);
			it1 = phi_1(it);
		}
		if (it == e) return true;
		return false;
	}

	/*!
	 * \brief Tests if the volume of d contains a specified dart e.
	 * The method does not exploit the indexing information
	 */
	bool same_volume(Dart d, Dart e)
	{
		bool result = false;

		foreach_dart_of_orbit_until(Volume(d), [&](Dart vit)
		{
			if (vit == e) result = true;
			return !result;
		});

		return result;
	}

	/*!
	 * \brief Embed an open vertex d on a new attribute.
	 * The method supposes that the given dart d is the first dart
	 * of the open PHI21 orbit (i.e. phi2(d) == d)
	 */
	void new_open_vertex_embedding(Dart d)
	{
		cgogn_assert(phi2(d) == d);
		const unsigned int emb = add_attribute_element<Vertex::ORBIT>();

		Dart it = d;
		Dart it1 = phi_1(it);

		set_embedding<Vertex>(it, emb);
		while (phi2(it1) != it1)
		{
			it = phi2(it1);
			it1 = phi_1(it);
			set_embedding<Vertex>(it, emb);
		}
	}

	/*!
	 * \brief Generate a random set of faces and put them in darts_
	 * \return The total number of added vertices.
	 * The face size ranges from 1 to 10.
	 * A random dart of each face is put in the darts_ array.
	 */
	unsigned int add_faces(unsigned int n)
	{
		darts_.clear();
		unsigned int count = 0u;
		for (unsigned int i = 0u; i < n; ++i)
		{
			unsigned int n = 1u + std::rand() % 10u;
			Dart d = add_face_topo(n);
			count += n;

			n = std::rand() % 10u;
			while (n-- > 0u) d = phi1(d);

			darts_.push_back(d);
		}
		return count;
	}

	/*!
	 * \brief Generate a set of closed surfaces with arbitrary genus.
	 */
	void add_closed_surfaces()
	{
		darts_.clear();
		unsigned int n;

		// Generate NB_MAX random 1-faces (without boundary)
		for (unsigned int i = 0u; i < NB_MAX; ++i)
		{
			n = 1u + std::rand() % 10;
			Dart d = Inherit::Inherit::add_face_topo(n);
			darts_.push_back(d);
		}
		// Sew some pairs off 1-edges
		for (unsigned int i = 0u; i < 3u * NB_MAX; ++i)
		{
			Dart e1 = darts_[std::rand() % NB_MAX];
			n = std::rand() % 10u;
			while (n-- > 0u) e1 = phi1(e1);

			Dart e2 = darts_[std::rand() % NB_MAX];
			n = std::rand() % 10u;
			while (n-- > 0u) e2 = phi1(e2);

			n = 1 + std::rand() % 3u;
			while (n-- > 0u && phi2(e1) == e1 && phi2(e2) == e2 && e2 != e1)
			{
				phi2_sew(e2, e1);
				e1 = phi1(e1);
				e2 = phi_1(e2);
			}
		}
		// Close de map
		MapBuilder mbuild(*this);
		mbuild.close_map();
	}
};

/*!
 * \brief The random generated maps used in the tests are sound.
 */
TEST_F(CMap2TopoTest, random_map_generators)
{
	EXPECT_EQ(nb_darts(), 0u);

	add_faces(NB_MAX);
	EXPECT_TRUE(check_map_integrity());

	add_closed_surfaces();
	EXPECT_TRUE(check_map_integrity());
}

/*!
 * \brief Sewing and unsewing darts correctly changes the topological relations.
 * The test performs NB_MAX sewing and unsewing on randomly chosen dart of darts_.
 * The map integrity is not preserved (this test creates fixed points for PHI2).
 */
TEST_F(CMap2TopoTest, phi2_sew_unsew)
{
{'fraction_non_alphanumeric': 0.13342863950440792, 'fraction_numerical': 0.0195377650702883, 'mean_word_length': 2.3507184672698243, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 42, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5988907', 'n_tokens_mistral': 4457, 'n_tokens_neox': 3990, 'n_words': 1319}