Crypto++ 을 이용한 암호화/복호화 예제

출처: https://lyb1495.tistory.com/25

가끔 텍스트 파일을 감추고 싶을때.. 이용하면 좋음.

#include <iostream>
#include <iomanip>

#include "cryptopp/cryptlib.h"
#include "cryptopp/modes.h"
#include "cryptopp/aes.h"
#include "cryptopp/filters.h"
#include "cryptopp/base64.h"

void hex2byte(const char *in, uint len, byte *out)
{
	for (uint i = 0; i < len; i+=2) {
		char c0 = in[i+0];
		char c1 = in[i+1];
		byte c = (
			((c0 & 0x40 ? (c0 & 0x20 ? c0-0x57 : c0-0x37) : c0-0x30)<<4) |
			((c1 & 0x40 ? (c1 & 0x20 ? c1-0x57 : c1-0x37) : c1-0x30))
			);
		out[i/2] = c;
	}
}

int main(int argc, char* argv[]) {
	// 키 할당
	byte key[CryptoPP::AES::DEFAULT_KEYLENGTH];
	memset(key, 0x00, CryptoPP::AES::DEFAULT_KEYLENGTH );
	char* rawKey="f4150d4a1ac5708c29e437749045a39a";
	hex2byte(rawKey, strlen(rawKey), key);

	// 초기벡터 할당
	byte iv[CryptoPP::AES::BLOCKSIZE];
	memset(iv, 0x00, CryptoPP::AES::BLOCKSIZE );
	char* rawIv="86afc43868fea6abd40fbf6d5ed50905";
	hex2byte(rawIv, strlen(rawIv), iv);

	// 평문 할당
	std::string plaintext = "http://sopt.org/";
	std::string ciphertext;
	std::string base64encodedciphertext;
	std::string decryptedtext;
	std::string base64decryptedciphertext;

	// 평문 출력
	std::cout << "Plain Text (" << plaintext.size() <<
		" bytes)" << std::endl;
	std::cout << plaintext;
	std::cout << std::endl << std::endl;

	unsigned int plainTextLength = plaintext.length();

	// AES 암호화 수행
	CryptoPP::AES::Encryption 
		aesEncryption(key, CryptoPP::AES::DEFAULT_KEYLENGTH);
	CryptoPP::CBC_Mode_ExternalCipher::Encryption 
		cbcEncryption(aesEncryption, iv);

	CryptoPP::StreamTransformationFilter 
		stfEncryptor(cbcEncryption, new CryptoPP::StringSink( ciphertext));
	stfEncryptor.Put(reinterpret_cast<const unsigned="" char*="">
		(plaintext.c_str()), plainTextLength + 1);
	stfEncryptor.MessageEnd();

	// Base64 인코딩
	CryptoPP::StringSource(ciphertext, true,
		new CryptoPP::Base64Encoder(
		new CryptoPP::StringSink(base64encodedciphertext)
		) // Base64Encoder
		); // StringSource

	// Base64 인코딩 문자열 출력
	std::cout << "Cipher Text (" << base64encodedciphertext.size() 
		<< " bytes)" << std::endl;
	std::cout << "cipher : " << base64encodedciphertext << std::endl;
	std::cout << std::endl << std::endl;

	// Base64 디코딩
	CryptoPP::StringSource(base64encodedciphertext, true,
		new CryptoPP::Base64Decoder(
		new CryptoPP::StringSink( base64decryptedciphertext)
		) // Base64Encoder
		); // StringSource

	// AES 복호화
	CryptoPP::AES::Decryption aesDecryption(key, 
		CryptoPP::AES::DEFAULT_KEYLENGTH);
	CryptoPP::CBC_Mode_ExternalCipher::Decryption 
		cbcDecryption(aesDecryption, iv );

	CryptoPP::StreamTransformationFilter 
		stfDecryptor(cbcDecryption, new CryptoPP::StringSink(decryptedtext));
	stfDecryptor.Put( reinterpret_cast<const unsigned="" char*="">
		(base64decryptedciphertext.c_str()), base64decryptedciphertext.size());
	stfDecryptor.MessageEnd();

	// 복호화 문자열 출력
	std::cout << "Decrypted Text: " << std::endl;
	std::cout << decryptedtext;
	std::cout << std::endl << std::endl;
	return 0;
}

pacman 패키지 삭제하기

우선.. 버전을 빼고 설치된 패키지 목록을 보기..

% pacman -Q|cut -f 1 -d " "
apr
apr-devel
apr-util
apr-util-devel
asciidoc
aspell
aspell-devel
autoconf
autoconf2.13
autogen
automake-wrapper
automake1.1
...

다음.. 의존성 걸린 패키지들까지 몽땅 삭제하기..

% pacman -Rcn mingw-w64-i686-SDL2 mingw-w64-i686-allegro mingw-w64-i686-boost mingw-w64-i686-cgal mingw-w64-i686-clblast mingw-w64-i686-doxygen mingw-w64-i686-eigen3 mingw-w64-i686-ffmpeg mingw-w64-i686-fftw mingw-w64-i686-fontconfig mingw-w64-i686-freealut mingw-w64-i686-freeimage mingw-w64-i686-ftgl mingw-w64-i686-glew mingw-w64-i686-glfw mingw-w64-i686-glm mingw-w64-i686-imagemagick mingw-w64-i686-intel-tbb mingw-w64-i686-liblas mingw-w64-i686-libmariadbclient mingw-w64-i686-libssh2 mingw-w64-i686-libzip mingw-w64-i686-magnum mingw-w64-i686-magnum-integration mingw-w64-i686-magnum-plugins mingw-w64-i686-oce mingw-w64-i686-pdcurses mingw-w64-i686-physfs mingw-w64-i686-pkg-config mingw-w64-i686-python2 mingw-w64-i686-qt-creator mingw-w64-i686-qt5 mingw-w64-i686-wxWidgets mingw-w64-i686-zeromq
checking dependencies...
:: mingw-w64-i686-harfbuzz optionally requires mingw-w64-i686-cairo: hb-view program
:: mingw-w64-i686-libde265 optionally requires mingw-w64-i686-ffmpeg: sherlock265
:: mingw-w64-i686-libde265 optionally requires mingw-w64-i686-qt5: sherlock265
warning: dependency cycle detected:
warning: mingw-w64-i686-ffms2 will be removed after its mingw-w64-i686-ffmpeg dependency

Packages (47) mingw-w64-i686-cairo-1.16.0-1  mingw-w64-i686-curl-7.69.1-2
              mingw-w64-i686-ffms2-2.23.1-1  mingw-w64-i686-flif-0.3-1
              mingw-w64-i686-gdal-3.0.4-2  mingw-w64-i686-libass-0.14.0-1
              mingw-w64-i686-libcaca-0.99.beta19-5
              mingw-w64-i686-libkml-1.3.0-8  mingw-w64-i686-netcdf-4.7.3-1
              mingw-w64-i686-poppler-0.86.1-1  mingw-w64-i686-qbs-1.15.0-1
              mingw-w64-i686-ttf-dejavu-2.37-2
              mingw-w64-i686-x264-git-r2991.1771b556-1
              mingw-w64-i686-SDL2-2.0.12-1  mingw-w64-i686-allegro-5.2.6.0-1
              mingw-w64-i686-boost-1.72.0-1  mingw-w64-i686-cgal-5.0-1
              mingw-w64-i686-clblast-1.5.1-1  mingw-w64-i686-doxygen-1.8.17-1
              mingw-w64-i686-eigen3-3.3.7-1  mingw-w64-i686-ffmpeg-4.2.2-2
              mingw-w64-i686-fftw-3.3.8-1  mingw-w64-i686-fontconfig-2.13.1-1
              mingw-w64-i686-freealut-1.1.0-1
              mingw-w64-i686-freeimage-3.18.0-3  mingw-w64-i686-ftgl-2.4.0-1
              mingw-w64-i686-glew-2.1.0-1  mingw-w64-i686-glfw-3.3.2-1
              mingw-w64-i686-glm-0.9.9.7-1
              mingw-w64-i686-imagemagick-7.0.9.17-1
              mingw-w64-i686-intel-tbb-1~2020.2-1
              mingw-w64-i686-liblas-1.8.1-1
              mingw-w64-i686-libmariadbclient-2.3.7-1
              mingw-w64-i686-libssh2-1.9.0-1  mingw-w64-i686-libzip-1.6.1-1
              mingw-w64-i686-magnum-2019.10-1
              mingw-w64-i686-magnum-integration-2019.01-2
              mingw-w64-i686-magnum-plugins-2019.10-1
              mingw-w64-i686-oce-0.18.3-3  mingw-w64-i686-pdcurses-4.1.0-3
              mingw-w64-i686-physfs-3.0.2-1  mingw-w64-i686-pkg-config-0.29.2-1
              mingw-w64-i686-python2-2.7.17-1
              mingw-w64-i686-qt-creator-4.11.1-1  mingw-w64-i686-qt5-5.14.1-3
              mingw-w64-i686-wxWidgets-3.0.4-3  mingw-w64-i686-zeromq-4.3.2-1

Total Removed Size:  2425.99 MiB

:: Do you want to remove these packages? [Y/n]
...

PMP 라이브러리 Half Edge 테스트

폴리곤 메시 처리 라이브러리중 PMP 라이브러리가 있음..

https://www.pmp-library.org/

OpenMesh 와 비교하여 비교적 심플한 사용법과..상당히 구조적으로 잘 짜여져 있음..
근데 사실.. half edge 의 특성상 half edge 한개가 2개 이상의 face를 공유할수 없는 문제로..
실제 mesh 편집 프로그램에서는 사용하기가 어렵다..

예를 들어 Solid 메시는 한개의 half edge를 두고 2개 이상을 공유해야 하는 문제가 허다하고..
shell 메세중.. 2개이상을 지원해야 하는 경우도 종종있다..

암튼.. 난 이런 사실을 모른체.. 이걸 써야겠다하고.. 맘먹고 테스트해본 코드임..
그냥 이런 라이브러리가 있구나.. 하는 정도만.. 기억할것임.
지금은 직접 만들어 쓰고 있다..

#include <SurfaceMesh.h>

int main(void)
{
	pmp::SurfaceMesh mesh;

	pmp::Vertex v0,v1,v2,v3;

    // add 4 vertices
    v0 = mesh.add_vertex(pmp::Point(0,0,0));
    v1 = mesh.add_vertex(pmp::Point(1,0,0));
    v2 = mesh.add_vertex(pmp::Point(0,1,0));
    v3 = mesh.add_vertex(pmp::Point(0,0,1));

	// temp 노드 셋팅
	pmp::VertexProperty<bool> vtmp;
    vtmp = mesh.add_vertex_property<bool>("v:temp", false);
	vtmp[v0] = true;
	vtmp[v2] = true;
	
	// solver id 셋팅
	pmp::VertexProperty<unsigned int> vsolver;
    vsolver = mesh.add_vertex_property<unsigned int>("v:solver");
	vsolver[v0] = 100;
	vsolver[v1] = 101;
	vsolver[v2] = 102;
	vsolver[v3] = 103;
    //mesh.remove_vertex_property(vsolver);

    auto points = mesh.get_vertex_property<bool>("v:temp");

    for (auto v : mesh.vertices())
    {
        if ( points[v] ) {
			printf("%d : temp node, solver id: %d\n", v.idx(), vsolver[v]);
		} else {
			printf("%d : node, solver id: %d\n", v.idx(), vsolver[v]);
		}
    }

    // add 4 triangular faces
	pmp::Face f0 = mesh.add_triangle(v0,v1,v3);
    mesh.add_triangle(v1,v2,v3);
    mesh.add_triangle(v2,v0,v3);
    mesh.add_triangle(v0,v2,v1);
	
	// face에 대한 solver id 셋팅
	pmp::FaceProperty<unsigned int> fsolver;
    fsolver = mesh.add_face_property<unsigned int>("f:solver");
	fsolver[f0] = 10000;
	
	// face에 대한 part id 셋팅
	pmp::FaceProperty<unsigned int> fpart;
    fpart = mesh.add_face_property<unsigned int>("f:part");
	fpart[f0] = 1001;

	// part 1001 번에 대한 opengl 출력용 tri indices
	std::map<unsigned int, std::vector<unsigned int>> indices;
	std::map<pmp::Face, unsigned int> offset;
	offset[f0].push_back(indices[1001].size());
	indices[1001].push_back(v0.idx());
	indices[1001].push_back(v1.idx());
	indices[1001].push_back(v3.idx());
	offset[f1].push_back(indices[1001].size());
	indices[1001].push_back(v1.idx());
	indices[1001].push_back(v2.idx());
	indices[1001].push_back(v3.idx());

    std::cout << "vertices: " << mesh.n_vertices() << std::endl;
    std::cout << "edges: "    << mesh.n_edges()    << std::endl;
    std::cout << "faces: "    << mesh.n_faces()    << std::endl;
}

robin hood hashing

https://github.com/Tessil/robin-map

std::map과 std::unordered_map 을 속도면에서 발라버리는.. 헤쉬맵..
사용법은 std와 동일하다..

단순히 std::map과 std::unordered_map 을 tsl::robin_map 으로 바꾸어서 컴파일하니..
노드 1488581 개를 가진 메시를 기준으로..
메시 구조를 빌딩하는 타임이 26초 걸리던것이.. 18초가 되었다.. 지쟈스..

clear도 빨라졌네.. ㅎㅎ

여러 해쉬 라이브러리와 비교한 밴치마킹 사이트..
https://martin.ankerl.com/2019/04/01/hashmap-benchmarks-03-01-result-InsertHugeInt/

‘좋은 Mesh’에 대한 5가지 오해

출처: https://support.functionbay.com/ko/technical-tip/single/33/%EC%A2%8B%EC%9D%80-mesh%EC%97%90-%EB%8C%80%ED%95%9C-5%EA%B0%80%EC%A7%80-%EC%A3%BC%EC%9A%94-%EC%98%A4%ED%95%B4

#1. 좋은 mesh는 CAD형상에 가까운 형상이어야 한다. (Good mesh must follow CAD model well.)
좋은 mesh는 CAD형상에 가까워야 하는 것이 아니라, 물리 문제를 풀 수 있어야 한다.
너무 세세한 부분은 해석에 필요하지 않으며 해석에 불필요한 영향을 끼칠 뿐이다.
따라서 좋은 Mesh는 CAD모델을 단순화하고 물리적인 요소에 기반하여 노드가 위치해야 한다.

예를 들어, 시뮬레이션에 별 영향을 주지 않는 구멍이나, 필렛(Fillet)을 비롯한 형상은 Mesh생성에 오히려 악영향을 줄 수 있다.
이러한 불필요한 형상 데이터를 단순화한 후 Mesh를 하면 좋다.
RecurDyn에서는 이를 위해 Delete Face, Delete Edge 등의 기능을 이용하여 불필요한 형상을 제거한 후 Mesh를 할 수 있게 해준다.

#2. 좋은 mesh는 언제나 좋다. (Good mesh is always good.)
많은 CAE 사용자들은 고품질의 mesh를 얻기 위해 meshing size를 변경하고, 형상을 나누고, mesh quality 체크 기능을 이용하여 품질을 확인한다.
이는 필요한 과정이지만, 과해서는 안된다.

예를 들어, 에어포일 주변의 유동과 힘을 완벽하게 계산할 수 있는 좋은 mesh를 생성했다고 하자.
그리고 만일 Attack angle을 0도에서 45도로 변경한다고 하면 동일한 mesh가 여전히 좋은 mesh라고 할 수 있는가? 그렇지 않을 것이다.

경계조건을 바꾸거나, 하중 조건을 바꾸거나, 해석 타입을 바꾸거나, 유동 모델을 바꾸게 되면 좋은 mesh가 안좋은 mesh가 될 수도 있다.

#3. 6면체(Hexa) 요소가 4면체(Tetra)요소보다 항상 좋다. (Hexahedron is always better than tetrahedron.)
대부분의 오래된 교과서에서는 hexa (quad) mesh가 tetra (tri) 보다 좋다고 이야기한다. 그리고 tetra (tri) 요소를 쓰면 더 큰 수치 에러가 발생할 수 있다는 것을 보여준다.
15~20년 전에는 이것이 참이었을 수도 있지만, 지금은 대부분의 경우 Hexa mesh에 장점이 없다.
tetra가 여전히 더 많은 계산 리소스를 사용하지만, 대신 mesh 생성 시간 절감을 통해 보상받을 수 있다.

대부분의 FEA, CFD 사용자에게 있어서, 만일 형상이 다소 복잡하다면, hexa mesh는 단순히 시간 낭비일 수 있다.

#4. auto-mesh로는 좋은 mesh를 생성할 수 없다. (Good mesh can only not be generated by automatic meshing.)
매일 소프트웨어를 사용하고, 수년간 비슷한 형상으로 작업을 하는 능숙한 사용자들의 경우에는 수작업을 활용한 Mesh생성이 유리할 수 있지만,
대부분의 비숙련 사용자들에게는 auto-mesh로도 상당히 좋은 품질의 mesh를 생성할 수 있다.

#5. 좋은 mesh는 cell과 node 수가 많아야 한다. ( Good mesh must have a large cell/node count.)
HPC에 대한 접근이 용이해지면서 학생들조차도 1천만~2천만개의 요소짜리 CFD 문제를 풀려고 한다. 대부분의 CAE사용자들의 눈에는 많은 수의 요소는 곧 높은 신뢰도를 의미하며 모든 물리 문제를 풀 수 있을 것처럼 보인다.
하지만 조밀한 mesh가 항상 좋은 mesh를 의미하진 않는다. mesh의 목적은 이상화된 위치에서 결과를 얻는 것이다. 좋은 mesh는 목적에 부합하는 mesh이다. 따라서 결과가 물리적으로 옳고, 목적에 맞는 정확도를 보여준다면 사용된 mesh는 충분히 좋다고 할 수 있다.
오히려 조밀한 mesh가 해석결과를 나쁘게 만들기도 한다.

현재 CAE는 여전히 mesh의 영향을 받고 있으며, 좋은 mesh는 다음과 같아야 한다.
– 타겟 물리 문제를 풀 수 있어야 함
– 솔버가 계산 실패하지 않을 정도의 합리적인 품질
– 물리문제에 기반한 형상 단순화
– 문제에 따라 품질을 결정해야 함
– 풀고자 하는 문제의 요구조건을 만족해야 함

Line to Quad shader

OpenGL에서 Line을 Quad로 변경하는 OpenGL Geometry 쉐이더..
screen_size 는 viewport width, height 의 값.

아래는 메시의 edge (wireframe) 를 그린것인데..

line_width를 1.0으로 하면.. Line 처럼 보이지만..

10.0으로 변경하면..

요렇게 Quad Primitive 로 라인을 그린걸 볼수 있음.

이렇게 Line을 Quad로 그리는 이유는
1. 속도 때문. 태초에 OpenGL 은 Triangle (Quad는 내부적으로 Triangle 두개로 표현됨) 을 그리는데 빠른 성능을 내기때문임.
2. Line은 offset (glPolygonOffset)을 할수 없어서 Face 위에 정확하게 라인을 그리기가 어려움. 이렇게 Quad로 변경해서 그리면 Offset 이 가능하므로 선을 surface 위에 이쁘게 그릴수가 있음.

#version 400 compatibility
layout(lines) in;
layout(triangle_strip, max_vertices = 4) out;

uniform float line_width;
uniform vec2 screen_size;

void main()
{
  // start/end points of line
  vec4 p0 = gl_in[0].gl_Position;
  vec4 p1 = gl_in[1].gl_Position;
  
  // convert to screen space
  p0.xy = p0.xy / p0.w * screen_size;
  p1.xy = p1.xy / p1.w * screen_size;

  // compute dir and normal
  vec2 lineDir = p1.xy - p0.xy;
  vec2 lineNormal = normalize(vec2(-lineDir.y, lineDir.x));
  
  
  // create screen-aligned quad
  vec2 offset = lineNormal * line_width;


  gl_Position = vec4( (p0.xy + offset) * p0.w / screen_size, p0.z, p0.w);
  EmitVertex();
  
  gl_Position = vec4( (p0.xy - offset) * p0.w / screen_size, p0.z, p0.w);
  EmitVertex();
  
  gl_Position = vec4( (p1.xy + offset) * p1.w / screen_size, p1.z, p1.w);
  EmitVertex();
  
  gl_Position = vec4( (p1.xy - offset) * p1.w / screen_size, p1.z, p1.w);
  EmitVertex();
  
  EndPrimitive();
}

KD-Tree 예제

공간 검색에 탁월하다는 KD-Tree 알고리즘..
http://blog.daum.net/pg365/140 이 싸이트에 간단하게 구현해놓은 코드가 있어 테스트해봄.

kd_tree.h 다운로드

이 코드의 문제점은..
1. insert 속도가 너무 느리다
2. 밸런싱 기능이 없다
3. 삭제 기능이 없다

#include <stdio.h>
#include <assert.h>
#include <time.h>
#include <windows.h>
#include "kd_tree.h"

unsigned int get_msec(void)
{
	return GetTickCount ();
}

class KDTree : public kd_tree<double, 3>
{
public:
	void insert_xyz (double x, double y, double z, void *data)
	{
		double buf[3] = { x, y, z };
		
		insert (buf, data);
	}

	kd_node *nearest_neighbour_search (double x, double y, double z)
	{
		double pos[3] = {x, y, z};
		
		return nn_search (pos);
	}

	list<kd_node *> *bounding_box_search (double lx, double ly, double lz, double hx, double hy, double hz)
	{
		double low[3]  = { lx, ly, lz };
		double high[3] = { hx, hy, hz };

		return range_search (low, high);
	}
};


int main(int argc, char **argv)
{
	KDTree kd;

	unsigned int start = get_msec();

	int point_id = 0;

	printf("-- insert points ... \n"); fflush(stdout);

	for(int i=0; i<1000; i++) {

		for (int x=0; x < 10; x++) {
			for (int y=0; y < 10; y++) {
				for (int z=0; z < 10; z++) {
					kd.insert_xyz (x, y, z, (void *)point_id);
					point_id++;
				}
			}
		}

		for (int x=20; x < 30; x++) {
			for (int y=20; y < 30; y++) {
				for (int z=0; z < 10; z++) {
					kd.insert_xyz (x, y, z, (void *)point_id);
					point_id++;
				}
			}
		}

		for (int x=0; x < 10; x++) {
			for (int y=20; y < 30; y++) {
				for (int z=0; z < 10; z++) {
					kd.insert_xyz (x, y, z, (void *)point_id);
					point_id++;
				}
			}
		}

		for (int x=20; x < 30; x++) {
			for (int y=0; y < 10; y++) {
				for (int z=0; z < 10; z++) {
					kd.insert_xyz (x, y, z, (void *)point_id);
					point_id++;
				}
			}
		}
	}

	unsigned int msec = get_msec() - start;
	printf("inserting %d points... %.3f sec\n", point_id, msec/1000.0);

	start = get_msec();

	list<kd_tree<double,3>::kd_node *> *ret = kd.bounding_box_search(0, 0, 0, 10, 10, 10);
#if 1
	for (list<kd_tree<double,3>::kd_node *>::iterator it = ret->begin (); it != ret->end(); it++) {
		kd_tree<double,3>::kd_node *n = *it;
		printf ("(%g, %g, %g) \n", n->_pos[0], n->_pos[1], n->_pos[2]);
	}
#endif

	msec = get_msec() - start;
	printf("range query returned %d items in %.5f sec\n", ret->size(), msec/1000.0);
	return 0;
}

OpenGL 로 만드는 해석 모델 편집기..

요즘 짜투리 시간을 이용해서..
OpenGL로 해석 모델을 편집하는 프로그램을 만들고 있다..
이래저래 문제도 많았는데..
하나둘씩 해결이 되고 있다..

투명문제도.. 텍스트 출력 속도도.. 해결이 되었음..

파트가 너무 많으면.. 인덱스 트랜스퍼가 너무 많다보니.. 느림..
이건 꼭 해결하고 넘어가야할 산…

아래는 인터넷상에 굴러다니는 모델을 불러온 화면..

가장 근접 거리의 포인트 검색

가장 근접거리의 포인트를 단시간내에 찾는 알고리즘중에..
octree, kd-tree 가 제일 유명한듯하다..
은근히 이 알고리즘이 구현된 쓸만한 라이브러리가 없다..
찾아보다 결국 PCL (Point cloud library) 이라는 라이브러리가 제일 유명하더라는..
모든 포인트를 클라우드라는 영역에 집어넣고 특정 포인트에서 쿼리를 때리면..
가장 근접한 몇개의 포인트를 찾아준다..

보통 octree나 kd-tree는 방향성을 주어 검색을 할 수 없다..
PCL은 다행히 octree 에 한정하여 원점과 방향을 지정하여 근접 포인트 쿼리가 가능하다.

아래는 테스트한 코드..

pcl::PointCloud<pcl::PointXYZL>::Ptr m_point_cloud (new pcl::PointCloud<pcl::PointXYZL> ());
pcl::octree::OctreePointCloudSearch<pcl::PointXYZL> m_octree_search (0.2f);

// 포인트와 해당 ID를 집어넣는다.
for(int i=0; i<10000; i++) {
	...
	m_point_cloud->push_back (pcl::PointXYZL ((float)px, (float)py, (float)pz, id));
}

// 원점 지정
Eigen::Vector3f _origin (origin[0],origin[1],origin[2]);
// 방향 지정
Eigen::Vector3f _ray (ray[0],ray[1],ray[2]);

// resolution 지정 (반지름 30을 갖는 sphre 정도라고 생각하면 될려나?)
float resolution = 30.f;

printf("octree ray intersection with resolution %f\n", resolution); 
fflush(stdout);

// 쿼리
std::vector<int> indicesInRay;
pcl::octree::OctreePointCloudSearch<pcl::PointXYZL> octree(resolution);
octree.setInputCloud (m_point_cloud);
octree.addPointsFromInputCloud ();
octree.getIntersectedVoxelIndices (_origin, _ray, indicesInRay);

// 탐색된 포인트 확인
for(int i=0; i<indicesInRay.size(); i++) {
	int idx = indicesInRay[i];
	pcl::PointXYZL pt = m_point_cloud->points[idx];
	//printf("[%d]: %d: %f, %f, %f\n", idx, pt.label, pt.x, pt.y, pt.z);
}

octree.deleteTree();

Outline 그리기

opengl 에서 outline을 그리는 몇가지 방법중의 하나..
바로 stencil buffer 를 이용함.

glPushAttrib(GL_ALL_ATTRIB_BITS);

glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT);
glEnable(GL_STENCIL_TEST);
// Set the stencil buffer to write a 1 in every time
// a pixel is written to the screen
glStencilFunc(GL_ALWAYS, 1, 0xFFFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glColor3f(1.0f, 0.0f, 0.0f);

...draw primitive...

glStencilFunc(GL_NOTEQUAL, 1, 0xFFFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
// Draw the object with thick lines
glLineWidth(4.0f);
glDisable (GL_LINE_SMOOTH);
glDisable(GL_LIGHTING);

glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glColor3f(1.0f, 1.0f, 1.0f);

...draw primitive...

glPopAttrib();