Using STL algorithms

xx.xx·2023년 8월 28일
1

오픈매쉬

목록 보기
4/5

Open Mesh

Using STL algorithms


STL for_each구문을 사용하는 방법을 보여준다.
STL 구문은 손으로 작성한 루프보다 읽기 쉽고 효율적일 수 있기 때문이다.

SmootherT 클래스에는 두 개의 함수가 있습니다. 하나는 주어진 정점에 대한 무게 중심을 계산하는 함수이고, 다른 하나는 정점 위치를 해당 무게 중심으로 설정하는 함수다.

다음은 함수 객체(operator())를 정의하는 것으로, 이 함수 객체는 OpenMesh의 Vertex Handle에 대해 중심점을 계산하고 해당 속성을 설정하는 역할을 수행한다.

 void operator()(const typename Mesh::VertexHandle& _vh)
{
    typename Mesh::VertexVertexIter vv_it; // 이웃 정점 반복자
    typename Mesh::Scalar valence(0.0); // 인접 정점 수를 나타내는 변수
    
    mesh_.property(cog_, _vh) = typename Mesh::Point(0.0, 0.0, 0.0); // 중심점 속성 초기화
    for (vv_it = mesh_.vv_iter(_vh); vv_it.is_valid(); ++vv_it)
    {
        mesh_.property(cog_, _vh) += mesh_.point(*vv_it); // 이웃 정점 위치 누적
        ++valence; // 인접 정점 수 증가
    }
    mesh_.property(cog_, _vh) /= valence; // 중심점 계산 및 속성 설정
}

full code

template <class Mesh>
class SmootherT
{
public:
	typedef typename Mesh::Point  cog_t;
	typedef OpenMesh::VPropHandleT< cog_t > Property_cog;

public:
	explicit SmootherT(Mesh& _mesh) : mesh_(_mesh)
	{
		mesh_.add_property(cog_);
	}

	~SmootherT()
	{
		mesh_.remove_property(cog_);
	}

	void smooth(unsigned int _iterations)
	{
		for (unsigned int i = 0; i < _iterations; ++i)
		{
			for_each(mesh_.vertices_begin(), mesh_.vertices_end(), ComputeCOG(mesh_, cog_));
			for_each(mesh_.vertices_begin(), mesh_.vertices_end(), SetCOG(mesh_, cog_));
		}
	}

private:
	class ComputeCOG
	{
	public:
		ComputeCOG(Mesh& _mesh, Property_cog& _cog) : mesh_(_mesh), cog_(_cog)
		{}

		void operator()(const typename Mesh::VertexHandle& _vh)
		{
			typename Mesh::VertexVertexIter vv_it;
			typename Mesh::Scalar valence(0.0);

			cog_[_vh] = typename Mesh::Point(0.0, 0.0, 0.0);
			for (vv_it = mesh_.vv_iter(_vh); vv_it.is_valid(); ++vv_it)
			{
				cog_[_vh] += mesh_.point(*vv_it);
				++valence;
			}
			cog_[_vh] /= valence;
		}

	private:
		Mesh& mesh_;
		Property_cog& cog_;
	};

	class SetCOG
	{
	public:
		SetCOG(Mesh& _mesh, Property_cog& _cog)	: mesh_(_mesh), cog_(_cog) {}

		void operator()(const typename Mesh::VertexHandle& _vh)
		{
			if (!mesh_.is_boundary(_vh))
				mesh_.set_point(_vh, cog_[_vh]);
		}

	private:
		Mesh& mesh_;
		Property_cog& cog_;
	};

private:
	Mesh& mesh_;
	Property_cog cog_;
};

foreach(mesh.verticesbegin(), mesh.verticesend(), ComputeCOG(mesh, cog_));
for_each를 처음 봐서 for와 다른 점이 뭐지? 했는데
for_each는 주로 범위 내요소에 대해 특정 동작을 적용하는 것이다.

for_each(start_iter, end_iter, function_or_function_object);

for (initialization; condition; update)

하지만 생성자에 아무것도 구현하지 않고 operator를 추가로 구현한 이유를... 잘 모르겠음... ㅜㅜ
.....흠...................
SmootherT 클래스는 메시를 입력으로 받아 그 메시의 정점들을 부드럽게 조정하는 기능을 제공하며, 내부적으로 ComputeCOG와 SetCOG 클래스를 사용하여 스무딩 작업을 구현한다는데 잘... 와닿지는 않음.
다시 공부하기...

0개의 댓글