2 # eosPointICP : $Revision$
14 #define GLOBAL_DECLARATION
15 #include "../inc/config.h"
19 static int __debug_mode__=0;
23 typedef struct leosPointICPInfo {
28 typedef enum leosPointICPMode {
35 double trace(int cnt_row, double matrix[cnt_row][cnt_row])
40 for (i = 0; i < cnt_row; i++) {
47 int countPoint(eosPoint point)
51 while(point.current != NULL){
58 //inP_updに対するrefPの最近傍点の特定 -線形探索
59 void identifyCP(eosPoint *inP, eosPoint *refP, int *closest_index_pair)
62 double pair[2]; //0:index 1:distance
64 eosPoint *_inP, *_refP;
67 for (_inP = inP;; eosPointNext(_inP)) {
69 pair[1] = sqrt( SQR(refP->top->p.coord.data[0] - _inP->current->p.coord.data[0]) +
70 SQR(refP->top->p.coord.data[1] - _inP->current->p.coord.data[1]) +
71 SQR(refP->top->p.coord.data[2] - _inP->current->p.coord.data[2]));
76 for (_refP = refP;; eosPointNext(_refP)){
77 distance = sqrt(SQR(refP->current->p.coord.data[0] - _inP->current->p.coord.data[0]) +
78 SQR(refP->current->p.coord.data[1] - _inP->current->p.coord.data[1]) +
79 SQR(refP->current->p.coord.data[2] - _inP->current->p.coord.data[2]));
80 if (pair[1] > distance){
85 if (_refP->current == refP->bottom){
89 closest_index_pair[i] = (int)pair[0];
92 if (_inP->current == inP->bottom){
99 eosPointCoord calculatePointsG(eosPoint *P, int count)
103 eosPointCoordInit(&g, 4); //第2引数は意味なし
105 for (i = 0; i < 3; i++){
108 for (i = 0; i < count; i++){
109 for (j = 0; j < 3; j++){
110 g.coord.data[j] += P->current->p.coord.data[j];
114 for (i = 0; i < 3; i++){
115 g.coord.data[i] /= count;
120 //in_updに対する最近傍点であるrefに対応するようにrefのポインタを移動
121 void moveRefAccordingToCP(int closest_index_pair_value, eosPoint *refP)
125 for (i = 0; i < closest_index_pair_value; i++){
131 void generateCovM(double covm[3][3], int cnt_in_point, int *closest_index_pair, eosPoint *inP_upd, eosPoint *refP, eosPointCoord inP_upd_G, eosPointCoord refP_G)
134 for (i = 0; i < 3; i++){
135 for (j = 0; j < 3; j++){
139 eosPointTop(inP_upd);
140 for (i = 0; i < cnt_in_point; i++){
141 moveRefAccordingToCP(closest_index_pair[i], refP);
142 covm[0][0] += refP->current->p.coord.data[0] * inP_upd->current->p.coord.data[0] - refP_G.coord.data[0] * inP_upd_G.coord.data[0];
143 covm[0][1] += refP->current->p.coord.data[0] * inP_upd->current->p.coord.data[1] - refP_G.coord.data[0] * inP_upd_G.coord.data[1];
144 covm[0][2] += refP->current->p.coord.data[0] * inP_upd->current->p.coord.data[2] - refP_G.coord.data[0] * inP_upd_G.coord.data[2];
146 covm[1][0] += refP->current->p.coord.data[1] * inP_upd->current->p.coord.data[0] - refP_G.coord.data[1] * inP_upd_G.coord.data[0];
147 covm[1][1] += refP->current->p.coord.data[1] * inP_upd->current->p.coord.data[1] - refP_G.coord.data[1] * inP_upd_G.coord.data[1];
148 covm[1][2] += refP->current->p.coord.data[1] * inP_upd->current->p.coord.data[2] - refP_G.coord.data[1] * inP_upd_G.coord.data[2];
150 covm[2][0] += refP->current->p.coord.data[2] * inP_upd->current->p.coord.data[0] - refP_G.coord.data[2] * inP_upd_G.coord.data[0];
151 covm[2][1] += refP->current->p.coord.data[2] * inP_upd->current->p.coord.data[1] - refP_G.coord.data[2] * inP_upd_G.coord.data[1];
152 covm[2][2] += refP->current->p.coord.data[2] * inP_upd->current->p.coord.data[2] - refP_G.coord.data[2] * inP_upd_G.coord.data[2];
153 eosPointNext(inP_upd);
155 for (i = 0; i < 3; i++){
156 for (j = 0; j < 3; j++){
157 covm[i][j] /= cnt_in_point;
163 void generateSymM(double symm[4][4], double covm[3][3])
166 for (i = 0; i < 4; i++){
167 for (j = 0; j < 4; j++){
172 symm[0][0] = trace(3, covm);
173 symm[0][1] = covm[1][2] - covm[2][1];
174 symm[0][2] = covm[2][0] - covm[0][2];
175 symm[0][3] = covm[0][1] - covm[1][0];
177 symm[1][0] = covm[1][2] - covm[2][1];
178 symm[1][1] = 2 * covm[0][0] - trace(3, covm);
179 symm[1][2] = covm[0][1] - covm[1][0];
180 symm[1][3] = covm[0][2] - covm[2][0];
182 symm[2][0] = covm[2][0] - covm[0][2];
183 symm[2][1] = covm[0][1] - covm[1][0];
184 symm[2][2] = 2 * covm[1][1] - trace(3, covm);
185 symm[2][3] = covm[1][2] - covm[2][1];
187 symm[3][0] = covm[0][1] - covm[1][0];
188 symm[3][1] = covm[0][2] - covm[2][0];
189 symm[3][2] = covm[1][2] - covm[2][1];
190 symm[3][3] = 2 * covm[2][2] - trace(3, covm);
193 //対称行列から絶対値最大の固有値に対応する固有ベクトル(正規化)を求める。
194 void jacobi(double symm[4][4], double *eigen_vector)
200 double P[4][4]; //ギブンス回転行列
201 double Ps[4][4]; //Pの積み重ね
202 double Ps_cache[4][4]; //Psのキャッシュ
203 double B[4][4]; //更新される行列
204 double B_cache[4][4]; //Bの更新で一つ前のBを使うのでキャッシュする
210 for (i = 0; i < 4; i++){
211 for (j = 0; j < 4; j++){
212 B[i][j] = symm[i][j];
219 //行列の絶対値最大のnondiagonal-indexを探索-線形探索
223 for (i = 0; i < 4; i++){
224 for (j = 0; j < 4; j++){
225 if (i != j && max < fabs(B[i][j])){
232 // printf("max=B[%d][%d]\n", p, q);
233 //maxindexが更新されない maxがない
234 if (p == 0 && q == 0){
240 for (i = 0; i < 4; i++){
241 for (j = 0; j < 4; j++){
242 B_cache[i][j] = B[i][j];
243 Ps_cache[i][j] = Ps[i][j];
248 if (B[p][p] != B[q][q]){
249 theta = atan(-1 * 2 * B[p][q] / (B[p][p] - B[q][q])) / 2;
255 for (i = 0; i < 4; i++){
256 for (j = 0; j < 4; j++){
257 if ((i == p && j == q) || (i == q && j == p)){
259 }else if (i == p && j == p){
260 B[i][j] = (B_cache[p][p] + B_cache[q][q]) / 2.0 + (B_cache[p][p] - B_cache[q][q]) / 2.0 * cos(2.0 * theta) - B_cache[p][q] * sin(2.0 * theta);
261 }else if (i == q && j == q){
262 B[i][j] = (B_cache[p][p] + B_cache[q][q]) / 2.0 - (B_cache[p][p] - B_cache[q][q]) / 2.0 * cos(2.0 * theta) + B_cache[p][q] * sin(2.0 * theta);
263 }else if (i == p || j == p){
265 B[i][j] = B_cache[p][j] * cos(theta) - B_cache[q][j] * sin(theta);
267 B[i][j] = B_cache[i][p] * cos(theta) - B_cache[i][q] * sin(theta);
269 }else if (i == q || j == q){
271 B[i][j] = B_cache[p][j] * sin(theta) + B_cache[q][j] * cos(theta);
273 B[i][j] = B_cache[i][p] * sin(theta) + B_cache[i][q] * cos(theta);
276 B[i][j] = B_cache[i][j];
282 for (i = 0; i < 4; i++){
284 for (j = 3; j > i; j--){
285 P[i][j] = P[j][i] = 0;
288 P[p][p] = cos(theta);
289 P[p][q] = (q > p) ? sin(theta) : -1 * sin(theta);
290 P[q][p] = (q > p) ? -1 * sin(theta) : sin(theta);
291 P[q][q] = cos(theta);
293 //ギブンスの積み重ね 行列の掛け算 P = P1・P2...Pn
294 for (i = 0; i < 4; i++){
295 for (j = 0; j < 4; j++){
297 for (k = 0; k < 4; k++){
298 Ps[i][j] += Ps_cache[i][k] * P[k][j];
306 for (i = 0; i < 4; i++){
307 for (j = 3; j > i; j--){
308 if (fabs(B[j][i]) >= 0.00001 || fabs(B[i][j]) >= 0.00001){
314 if (end_flag || loop_count >= 50){
315 // 対角化された行列に現れる固有値の絶対値最大が現れる列に対応する固有ベクトルを正規化してeigen_vectorにする。
318 for (i = 1; i < 4; i++){
319 if (max < fabs(B[i][i])){
324 norm = sqrt(SQR(Ps[0][max_columns]) + SQR(Ps[1][max_columns]) + SQR(Ps[2][max_columns]) + SQR(Ps[3][max_columns]));
325 // printf("norm=%lf\n",norm);
326 for (i = 0; i < 4; i++){
327 eigen_vector[i] = Ps[i][max_columns] / norm;
328 // printf("eigen_vec[%d]=%lf\n", i, eigen_vector[i]);
337 void generateRotationMatrix(double rotation_mat[3][3], double qr[4])
339 rotation_mat[0][0] = SQR(qr[0]) + SQR(qr[1]) - SQR(qr[2]) - SQR(qr[3]);
340 rotation_mat[0][1] = 2 * (qr[1] * qr[2] - qr[0] * qr[3]);
341 rotation_mat[0][2] = 2 * (qr[1] * qr[3] + qr[0] * qr[2]);
342 rotation_mat[1][0] = 2 * (qr[1] * qr[2] + qr[0] * qr[3]);
343 rotation_mat[1][1] = SQR(qr[0]) + SQR(qr[2]) - SQR(qr[1]) - SQR(qr[3]);
344 rotation_mat[1][2] = 2 * (qr[2] * qr[3] - qr[0] * qr[1]);
345 rotation_mat[2][0] = 2 * (qr[1] * qr[3] - qr[0] * qr[2]);
346 rotation_mat[2][1] = 2 * (qr[2] * qr[3] + qr[0] * qr[1]);
347 rotation_mat[2][2] = SQR(qr[0]) + SQR(qr[3]) - SQR(qr[1]) - SQR(qr[2]);
351 void calculateTranslation(eosPointCoord *inP_upd_G, eosPointCoord *refP_G, double rotation_mat[3][3], double qt[3])
353 qt[0] = refP_G->coord.data[0] - (rotation_mat[0][0] * inP_upd_G->coord.data[0] +
354 rotation_mat[0][1] * inP_upd_G->coord.data[1] +
355 rotation_mat[0][2] * inP_upd_G->coord.data[2] );
356 qt[1] = refP_G->coord.data[1] - (rotation_mat[1][0] * inP_upd_G->coord.data[0] +
357 rotation_mat[1][1] * inP_upd_G->coord.data[1] +
358 rotation_mat[1][2] * inP_upd_G->coord.data[2] );
359 qt[2] = refP_G->coord.data[2] - (rotation_mat[2][0] * inP_upd_G->coord.data[0] +
360 rotation_mat[2][1] * inP_upd_G->coord.data[1] +
361 rotation_mat[2][2] * inP_upd_G->coord.data[2] );
366 void applyMatrix(eosPoint *inP_upd, double rotation_mat[3][3], double qt[3], int cnt_in_point)
370 eosPointCopy(&cacheP, inP_upd);
371 eosPointTop(inP_upd);
372 eosPointTop(&cacheP);
373 for (i = 0; i < cnt_in_point; i++){
374 inP_upd->current->p.coord.data[0] = rotation_mat[0][0] * cacheP.current->p.coord.data[0] +
375 rotation_mat[0][1] * cacheP.current->p.coord.data[1] +
376 rotation_mat[0][2] * cacheP.current->p.coord.data[2] +
379 inP_upd->current->p.coord.data[1] = rotation_mat[1][0] * cacheP.current->p.coord.data[0] +
380 rotation_mat[1][1] * cacheP.current->p.coord.data[1] +
381 rotation_mat[1][2] * cacheP.current->p.coord.data[2] +
384 inP_upd->current->p.coord.data[2] = rotation_mat[2][0] * cacheP.current->p.coord.data[0] +
385 rotation_mat[2][1] * cacheP.current->p.coord.data[1] +
386 rotation_mat[2][2] * cacheP.current->p.coord.data[2] +
388 eosPointNext(inP_upd);
389 eosPointNext(&cacheP);
394 void calculateRmax(eosPoint inP,eosPointCoord inP_upd_G, double* r_max, int cnt_in_point)
400 for(i=0;i<cnt_in_point; i++){
401 r = sqrt(SQR(inP.current->p.coord.data[0] - inP_upd_G.coord.data[0]) +
402 SQR(inP.current->p.coord.data[1] - inP_upd_G.coord.data[1]) +
403 SQR(inP.current->p.coord.data[2] - inP_upd_G.coord.data[2]));
413 double calculateScore(eosPoint *inP_upd, eosPoint *refP, int cnt_in_point, int *closest_index_pair, double r_max, double omit, int mode)
420 eosPointTop(inP_upd);
421 for (i = 0, count=0; i < cnt_in_point; i++){
422 moveRefAccordingToCP(closest_index_pair[i], refP);
423 dis = SQR(inP_upd->current->p.coord.data[0] - refP->current->p.coord.data[0])
424 + SQR(inP_upd->current->p.coord.data[1] - refP->current->p.coord.data[1])
425 + SQR(inP_upd->current->p.coord.data[2] - refP->current->p.coord.data[2]);
427 if(sqrt(dis)<=omit) {
431 eosPointNext(inP_upd);
433 // se = se/cnt_in_point;
434 se = sqrt(se/cnt_in_point);
436 seRobust = sqrt(seRobust/count);
451 fprintf(stderr, "Not supported mode: %d\n", mode);
459 double calculateScore2D(eosPoint *inP_upd, eosPoint *refP, int cnt_in_point, int *closest_index_pair, double r_max, double omit, int mode)
466 eosPointTop(inP_upd);
467 for (i = 0, count=0; i < cnt_in_point; i++, count++){
468 moveRefAccordingToCP(closest_index_pair[i], refP);
469 dis = SQR(inP_upd->current->p.coord.data[0] - refP->current->p.coord.data[0])
470 + SQR(inP_upd->current->p.coord.data[1] - refP->current->p.coord.data[1]);
472 if(sqrt(dis)<=omit) {
475 eosPointNext(inP_upd);
477 // se = se/cnt_in_point;
478 se = sqrt(se/cnt_in_point);
480 seRobust = sqrt(seRobust/count);
495 fprintf(stderr, "Not supported mode: %d\n", mode);
504 void MakeAffine(eosPointIcpResult* icp_result_set, double rotation_matrix[3][3], double* translation)
507 Matrix3D affine_matrix;
508 matrix3DInit(affine_matrix);
511 affine_matrix[i][j] = rotation_matrix[j][i];
513 affine_matrix[3][i] = translation[i];
515 matrix3DMultiplyInv(affine_matrix, icp_result_set->matrix);
519 void MemorizeStateOfMinimumScore(eosPointIcpResult* icp_result_set, eosPointIcpResult icp_current_set, int count)
522 if( count==1 || icp_result_set->score > icp_current_set.score){
523 eosPointCopy(&icp_result_set->resultP, &icp_current_set.resultP);
526 icp_result_set->matrix[i][j] = icp_current_set.matrix[i][j];
529 icp_result_set->score = icp_current_set.score;
534 void icpAlgorhythm(eosPoint *inP, eosPoint *refP, double score_threshold, int iteration_limit, eosPointIcpResult* icp_result_set, double omit, int flag2D, int mode)
536 eosPointCoord inP_upd_G, refP_G;
537 eosPointIcpResult icp_current_set;
539 double covm[3][3]; //相互共分散行列(Covariance matrix)
540 double symm[4][4]; //qR,qT算出のための行列-対称行列(Symmetric matrix)
541 double qr[4]; //四元数 回転パラメータ
542 double rotation_mat[3][3]; //回転行列
543 double qt[3]; //平行移動パラメータ
544 double r_max; //重心からの最大距離
545 double score; //独自スコア
546 int count = 1; //アルゴリズム反復回数カウント
547 double min_score; //反復の中での最小二乗法の最小スコア
548 int cnt_in_point = countPoint(*inP);
549 int cnt_ref_point = countPoint(*refP);
550 int closest_index_pair[cnt_in_point]; //inとrefの最近傍点のindexのペア
551 matrix3DInit(icp_current_set.matrix);
552 eosPointCopy(&icp_current_set.resultP, inP);
553 identifyCP(&icp_current_set.resultP, refP, closest_index_pair);
554 inP_upd_G = calculatePointsG(&icp_current_set.resultP, cnt_in_point);
555 refP_G = calculatePointsG(refP, cnt_ref_point);
556 calculateRmax(icp_current_set.resultP, inP_upd_G, &r_max, cnt_in_point);
559 inP_upd_G = calculatePointsG(&icp_current_set.resultP, cnt_in_point);
560 generateCovM(covm, cnt_in_point, closest_index_pair, &icp_current_set.resultP, refP, inP_upd_G, refP_G);
561 generateSymM(symm, covm);
563 generateRotationMatrix(rotation_mat, qr);
564 calculateTranslation(&inP_upd_G, &refP_G, rotation_mat, qt);
565 MakeAffine(&icp_current_set, rotation_mat, qt);
566 applyMatrix(&icp_current_set.resultP, rotation_mat, qt, cnt_in_point);
567 identifyCP(&icp_current_set.resultP, refP, closest_index_pair);
569 if( iteration_limit*0.5<count || icp_result_set->score < score_threshold*10){
570 icp_current_set.score = calculateScore2D(&icp_current_set.resultP, refP, cnt_in_point, closest_index_pair, r_max, omit, mode);
572 icp_current_set.score = calculateScore2D(&icp_current_set.resultP, refP, cnt_in_point, closest_index_pair, r_max, omit, 0);
575 if( iteration_limit*0.5<count || icp_result_set->score < score_threshold*10){
576 icp_current_set.score = calculateScore(&icp_current_set.resultP, refP, cnt_in_point, closest_index_pair, r_max, omit, mode);
578 icp_current_set.score = calculateScore(&icp_current_set.resultP, refP, cnt_in_point, closest_index_pair, r_max, omit, 0);
581 MemorizeStateOfMinimumScore(icp_result_set, icp_current_set, count);
582 if( count==iteration_limit || icp_result_set->score < score_threshold){
589 //座標をピックアップする pickup_percentの割合でflagが立つ
590 void pickupPoint(eosPoint* inP, eosPoint* pickup_inP, int cnt_in_point, double pickup_percent)
592 int i, j, pickup_flag;
596 eosPointInit(pickup_inP, NULL);
597 eosPointTop(pickup_inP);
598 while(inP->current!=NULL){
599 p = randomUniformGet(0,100,0);
600 pickup_flag = (p<pickup_percent) ? 1 : 0;
602 eosPointAppend(pickup_inP, &(inP->current->p), 0);
609 void writeOutput(eosPointICPInfo* info, eosPointIcpResult best_icp_result_set, eosPoint* inP, eosPoint* refP, char* euler_angle_Mode)
612 matrix3DParaTypeReal rot1, rot2, rot3;
614 eosPointCopy(&final_inP, inP);
615 fprintf(info->fptOut,"Result eosPointICP\n\n");
616 fprintf(info->fptOut,"In file: %s\ttype: %ld\n",info->In,info->InType);
617 fprintf(info->fptOut,"Ref file: %s\ttype: %ld\n\n",info->Ref, info->RefType);
620 if(info->flagScoreThreshold){
621 fprintf(info->fptOut, "SCORE threshold: %.2f\n", info->ScoreThreshold);
623 fprintf(info->fptOut, "SCORE Threshold: Not set\n");
625 fprintf(info->fptOut, "SCORE: %lf\n\n", best_icp_result_set.score);
627 fprintf(info->fptOut, "Affine transformation matrix: \n");
629 fprintf(info->fptOut, "%f\t%f\t%f\t%f\n", best_icp_result_set.matrix[0][i],
630 best_icp_result_set.matrix[1][i],
631 best_icp_result_set.matrix[2][i],
632 best_icp_result_set.matrix[3][i]);
634 //EAMODE,EulerAngleとTranslationを表示
635 matrix3DEulerAngleGetFromMatrix3D( best_icp_result_set.matrix, euler_angle_Mode, &rot1, &rot2, &rot3, 1);
636 fprintf(info->fptOut, "\nRotation angle(Euler Angle):\n");
637 fprintf(info->fptOut, "MODE: %s\nRot1: %.2f, Rot2: %.2f, Rot3: %.2f\n\n", euler_angle_Mode, rot1*DEGREE, rot2*DEGREE, rot3*DEGREE);
638 fprintf(info->fptOut, "Translation:\n");
639 fprintf(info->fptOut, "\tx: %lf\ty: %lf\tz: %lf\n\n",best_icp_result_set.matrix[3][0],best_icp_result_set.matrix[3][1],best_icp_result_set.matrix[3][2]);
640 fflush(info->fptOut);
642 eosPointTop(&final_inP);
644 while(inP->current != NULL){
646 final_inP.current->p.coord.data[i] = best_icp_result_set.matrix[0][i] * inP->current->p.coord.data[0] +
647 best_icp_result_set.matrix[1][i] * inP->current->p.coord.data[1] +
648 best_icp_result_set.matrix[2][i] * inP->current->p.coord.data[2] +
649 best_icp_result_set.matrix[3][i];
651 eosPointNext(&final_inP);
655 int closest_index_pair[count];
657 identifyCP(&final_inP, refP, closest_index_pair);
659 eosPointTop(&final_inP);
660 eosPointTop(&best_icp_result_set.resultP);
662 fprintf(info->fptOut,"Coordinate\n");
663 fprintf(info->fptOut,"ref\t\t\t\ticp_result(in)\n");
664 for (i = 0; i < count; i++){
665 moveRefAccordingToCP(closest_index_pair[i], refP);
666 fprintf(info->fptOut, "%lf %lf %lf\t%lf %lf %lf\n",
667 refP->current->p.coord.data[0],
668 refP->current->p.coord.data[1],
669 refP->current->p.coord.data[2],
670 final_inP.current->p.coord.data[0],
671 final_inP.current->p.coord.data[1],
672 final_inP.current->p.coord.data[2]);
673 eosPointNext(&final_inP);
677 void progressBar(int now, int end)
680 int count = now * 10 / end;
682 for(i=0;i<count;i++){
685 for(i=count;i<10;i++){
697 printf("\nError: The number of coordinate(in) over the number of coordinate(ref).\n");
698 printf(" You must set the number of coordinate(ref) graeter than or equal to the number of coordinate(in).\n");
699 printf(" in <= ref\n\n");
703 int main(int argc, char *argv[])
707 eosPointICPInfo info;
709 int cnt_in_point, cnt_ref_point;
710 eosPoint inP, refP, pickup_inP;
711 eosPointIcpResult icp_result_set, best_icp_result_set;
716 argCheck(&info, argc, argv);
719 DEBUGPRINT("Program Start\n");
720 __debug_mode__ = info.Debug;
722 eosPointRead(info.fptIn, &inP, info.InType);
723 if(1<=__debug_mode__) {
724 eosPointWrite(stderr, &inP, info.InType);
728 matrix3DFileRead(info.fptInMat, inMat);
731 matrix3DScale(inMat, info.Ratio);
733 eosPointRotate(&inP, inMat);
735 if(1<=__debug_mode__) {
736 eosPointWrite(stderr, &inP, info.InType);
739 eosPointRead(info.fptRef, &refP, info.RefType);
740 matrix3DInit(refMat);
741 if(info.flagRefMat) {
742 matrix3DFileRead(info.fptRefMat, refMat);
745 matrix3DScale(refMat, info.Ratio);
747 eosPointRotate(&refP, refMat);
749 matrix3DInit(icp_result_set.matrix);
750 matrix3DInit(best_icp_result_set.matrix);
752 cnt_in_point = countPoint(inP);
753 cnt_ref_point = countPoint(refP);
754 if (cnt_in_point > cnt_ref_point){
758 for(icp_pattern=1;icp_pattern<=info.Pattern;icp_pattern++){
759 progressBar(icp_pattern, info.Pattern);
760 pickupPoint(&inP, &pickup_inP, cnt_in_point, info.Pickup);
762 icpAlgorhythm(&pickup_inP, &refP, info.ScoreThreshold, info.IterationLimit, &icp_result_set, info.Omit, info.flag2D, info.mode);
763 MemorizeStateOfMinimumScore(&best_icp_result_set, icp_result_set, icp_pattern);
766 writeOutput(&info, best_icp_result_set, &inP, &refP, info.EAMode);
770 void additionalUsage()
772 fprintf(stderr, "----- Additional Usage -----\n");
773 fprintf(stderr, "eosPointFormat\n");
774 eosPointFileFormatUsage(stderr);