00001
00002
00023 #ifdef __WXMAC__
00024 #include "panoinc_WX.h"
00025 #include "panoinc.h"
00026 #endif
00027
00028 #include "VertexCoordRemapper.h"
00029 #include <math.h>
00030 #include <iostream>
00031 #include "ViewState.h"
00032
00033 #include "panodata/SrcPanoImage.h"
00034
00035
00036
00037
00038
00039 const unsigned short int split_flag_x = 1;
00040
00041
00042
00043
00044 const unsigned short int patch_flag_x = 2;
00045
00046 const unsigned short int split_flag_y = 4;
00047
00048 const unsigned short int patch_flag_y = 8;
00049
00050
00051
00052
00053 const unsigned short int vertex_side_flag_start = 16;
00054
00055
00056
00057 const unsigned short int transform_fail_flag = 256;
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 const unsigned int min_depth = 4;
00073
00074
00075
00076
00077
00078 const unsigned int max_depth = 6;
00079
00080
00081
00082
00083 const double min_length = 14.0;
00084
00085
00086 const double min_angle = 0.06;
00087
00088
00089
00090
00091 const double min_length_difference = 3.0;
00092
00093
00094
00095
00096
00097 const double offscreen_safety_margin = 10.0;
00098
00099 template <class T>
00100 inline T sqr(T val)
00101 {
00102 return val * val;
00103 };
00104
00105 VertexCoordRemapper::VertexCoordRemapper(HuginBase::Panorama *m_pano_in,
00106 HuginBase::SrcPanoImage *image,
00107 VisualizationState *visualization_state_in)
00108 : MeshRemapper(m_pano_in, image, visualization_state_in)
00109 {
00110
00111 }
00112
00113 void VertexCoordRemapper::UpdateAndResetIndex()
00114 {
00115 DEBUG_DEBUG("mesh update update reset index");
00116
00117 MeshRemapper::UpdateAndResetIndex();
00118
00119 output_projection = visualization_state->GetOptions()->getProjection();
00120 o_width = visualization_state->GetOptions()->getWidth();
00121 o_height = visualization_state->GetOptions()->getHeight();
00122
00123
00124 transform.createInvTransform(*image, *(visualization_state->GetOptions()));
00125
00126
00127
00128
00129
00130
00131
00132 OutputProjectionInfo *info = visualization_state->GetProjectionInfo();
00133 x_add_360 = info->GetXAdd360();
00134 radius = info->GetRadius();
00135 y_add_360 = info->GetYAdd360();
00136 x_midpoint = info->GetMiddleX();
00137 y_midpoint = info->GetMiddleY();
00138 lower_bound = info->GetLowerX();
00139 upper_bound = info->GetUpperX();
00140 lower_bound_h = info->GetLowerY();
00141 upper_bound_h = info->GetUpperY();
00142
00143
00144 SetCrop();
00145
00146 tree.x_crop_scale = crop_x2 - crop_x1;
00147 tree.x_crop_offs = crop_x1;
00148 tree.y_crop_scale = crop_y2 - crop_y1;
00149 tree.y_crop_offs = crop_y1;
00150
00151 RecursiveUpdate(0, 0, 0);
00152
00153 tree.ResetIndex();
00154 done_node = true;
00155 }
00156
00157 bool VertexCoordRemapper::GetNextFaceCoordinates(Coords *result)
00158 {
00159
00160 result->tex_c = tex_coords;
00161 result->vertex_c = s_vertex_coords;
00162
00163
00164 if (GiveClipFaceResult(result)) return true;
00165
00166 if (done_node)
00167 {
00168 do
00169 {
00170
00171 tree_node_id = tree.GetNext();
00172 if (!tree_node_id)
00173 {
00174
00175 return false;
00176 }
00177 }
00178
00179
00180 while ((tree.nodes[tree_node_id].flags & (transform_fail_flag * 15)));
00181
00182
00183 result->vertex_c = tree.nodes[tree_node_id].verts;
00184
00185
00186 tree.GetInputCoordinates(tree_node_id, tex_coords);
00187
00188
00189 discontinuity_flags =
00190 (tree.nodes[tree_node_id].flags / vertex_side_flag_start) % 16;
00191 if (discontinuity_flags)
00192 {
00193 done_node = false;
00194
00195 result->vertex_c = s_vertex_coords;
00196 for (short unsigned int x = 0; x < 2; x++)
00197 {
00198 for (short unsigned int y = 0; y < 2; y++)
00199 {
00200 s_vertex_coords[x][y][0] =
00201 tree.nodes[tree_node_id].verts[x][y][0];
00202 s_vertex_coords[x][y][1] =
00203 tree.nodes[tree_node_id].verts[x][y][1];
00204 if (discontinuity_flags & (1 << (x*2 + y)))
00205 {
00206 DiscontinuityFlip(s_vertex_coords[x][y]);
00207 }
00208 }
00209 }
00210 }
00211 } else {
00212
00213 done_node = true;
00214 for (short unsigned int x = 0; x < 2; x++)
00215 {
00216 for (short unsigned int y = 0; y < 2; y++)
00217 {
00218 s_vertex_coords[x][y][0] =
00219 tree.nodes[tree_node_id].verts[x][y][0];
00220 s_vertex_coords[x][y][1] =
00221 tree.nodes[tree_node_id].verts[x][y][1];
00222 if (!(discontinuity_flags & (1 << (x*2 + y))))
00223 {
00224 DiscontinuityFlip(s_vertex_coords[x][y]);
00225 }
00226 }
00227 }
00228 }
00229
00230 if (circle_crop)
00231 {
00232
00233
00234 if ( image->isInside(vigra::Point2D(int(result->tex_c[0][0][0] * width),
00235 int(result->tex_c[0][0][1] * height)))
00236 && image->isInside(vigra::Point2D(int(result->tex_c[0][1][0] * width),
00237 int(result->tex_c[0][1][1] * height)))
00238 && image->isInside(vigra::Point2D(int(result->tex_c[1][0][0] * width),
00239 int(result->tex_c[1][0][1] * height)))
00240 && image->isInside(vigra::Point2D(int(result->tex_c[1][1][0] * width),
00241 int(result->tex_c[1][1][1] * height))))
00242 {
00243
00244 return true;
00245 }
00246
00247 ClipFace(result);
00248
00249
00250 if (GiveClipFaceResult(result)) return true;
00251
00252 return (GetNextFaceCoordinates(result));
00253 }
00254 return true;
00255 }
00256
00257 void VertexCoordRemapper::DiscontinuityFlip(double vertex_c[2])
00258 {
00259
00260
00261 switch (output_projection)
00262 {
00263 case HuginBase::PanoramaOptions::RECTILINEAR:
00264
00265
00267 break;
00268 case HuginBase::PanoramaOptions::FULL_FRAME_FISHEYE:
00269 case HuginBase::PanoramaOptions::STEREOGRAPHIC:
00270 case HuginBase::PanoramaOptions::LAMBERT_AZIMUTHAL:
00271 case HuginBase::PanoramaOptions::HAMMER_AITOFF:
00272 case HuginBase::PanoramaOptions::ORTHOGRAPHIC:
00273 case HuginBase::PanoramaOptions::EQUISOLID:
00274 case HuginBase::PanoramaOptions::THOBY_PROJECTION:
00275
00276
00277
00278 break;
00279 case HuginBase::PanoramaOptions::CYLINDRICAL:
00280 case HuginBase::PanoramaOptions::EQUIRECTANGULAR:
00281 case HuginBase::PanoramaOptions::MERCATOR:
00282 case HuginBase::PanoramaOptions::LAMBERT:
00283 case HuginBase::PanoramaOptions::MILLER_CYLINDRICAL:
00284 case HuginBase::PanoramaOptions::ARCHITECTURAL:
00285
00286 if (vertex_c[0] < x_midpoint) vertex_c[0] += x_add_360;
00287 else vertex_c[0] -= x_add_360;
00288 break;
00289 case HuginBase::PanoramaOptions::SINUSOIDAL:
00290 case HuginBase::PanoramaOptions::ALBERS_EQUAL_AREA_CONIC:
00291 if (vertex_c[0] < x_midpoint)
00292 {
00293 vertex_c[0] +=
00294 visualization_state->GetProjectionInfo()->GetXAdd360(vertex_c[1]);
00295 } else {
00296 vertex_c[0] -=
00297 visualization_state->GetProjectionInfo()->GetXAdd360(vertex_c[1]);
00298 }
00299 break;
00300 case HuginBase::PanoramaOptions::TRANSVERSE_MERCATOR:
00301
00302 if (vertex_c[1] < y_midpoint) vertex_c[1] += y_add_360;
00303 else vertex_c[1] -= y_add_360;
00304 break;
00305
00306 }
00307 }
00308
00309 void VertexCoordRemapper::RecursiveUpdate(unsigned int node_num,
00310 unsigned int stretch_x, unsigned stretch_y)
00311 {
00312
00313
00314 unsigned int x, y, row_size, depth;
00315 tree.GetPosition(node_num, x, y, row_size, depth);
00316 tree.GetInputCoordinates(node_num, tex_coords);
00317 TreeNode *node = &tree.nodes[node_num],
00318 *parent = (depth) ?
00319 &tree.nodes[tree.GetParentId(x, y, row_size, depth)] : 0,
00320 *left = (x % 2) ?
00321 &tree.nodes[tree.GetIndex(x-1, y, row_size, depth)] : 0,
00322 *top = (y % 2) ?
00323 &tree.nodes[tree.GetIndex(x, y-1, row_size, depth)] : 0;
00324 bool valid[2][2];
00325 for (unsigned short int i = 0; i < 2; i++)
00326 {
00327 for (unsigned short int j = 0; j < 2; j++)
00328 {
00329 if (depth == 0)
00330 {
00331
00332 valid[i][j] =
00333 transform.transformImgCoord(node->verts[i][j][0],
00334 node->verts[i][j][1],
00335 tex_coords[i][j][0] * width,
00336 tex_coords[i][j][1] * height);
00337 } else
00338
00339
00340 if (i == x %2 && j == y%2 && depth)
00341 {
00342
00343 node->verts[i][j][0] = parent->verts[i][j][0];
00344 node->verts[i][j][1] = parent->verts[i][j][1];
00345 valid[i][j] = !(parent->flags & (transform_fail_flag << (j*2 +i)));
00346 } else if (x % 2 && !i) {
00347
00348 node->verts[0][j][0] = left->verts[1][j][0];
00349 node->verts[0][j][1] = left->verts[1][j][1];
00350 valid[i][j] = !(left->flags & (transform_fail_flag << (j *2 + 1)));
00351 } else if (y % 2 && !j) {
00352
00353 node->verts[i][0][0] = top->verts[i][1][0];
00354 node->verts[i][0][1] = top->verts[i][1][1];
00355 valid[i][j] = !(top->flags & (transform_fail_flag << (2 + i)));
00356 } else {
00357
00358
00359
00360
00361 if (!tree.GetTransform(x + i * (1 << stretch_x),
00362 y + j * (1 << stretch_y),
00363 depth, x, y, node->verts[i][j][0],
00364 node->verts[i][j][1]))
00365 {
00366
00367 valid[i][j] =
00368 transform.transformImgCoord(node->verts[i][j][0],
00369 node->verts[i][j][1],
00370 tex_coords[i][j][0] * width,
00371 tex_coords[i][j][1] * height);
00372
00373
00374
00375
00376
00377
00378
00379 if ( depth
00380
00381 && (parent->flags & patch_flag_x)
00382
00383
00384 && ((i + x) % 2)
00385
00386
00387 && j
00388
00389
00390 && (!((parent->flags & split_flag_y) && !(y % 2)))
00391
00392 && (!(parent->flags & (vertex_side_flag_start * 15))))
00393 {
00394 node->verts[i][1][0] = (parent->verts[0][1][0]
00395 + parent->verts[1][1][0]) / 2.0;
00396 node->verts[i][1][1] = (parent->verts[0][1][1]
00397 + parent->verts[1][1][1]) / 2.0;
00398 }
00399
00400 if ( depth
00401 && (parent->flags & patch_flag_y)
00402 && ((j + y) % 2)
00403 && i
00404 && (!((parent->flags & split_flag_x) && !(x % 2)))
00405 && (!(parent->flags & (vertex_side_flag_start * 15))))
00406 {
00407 node->verts[1][j][0] = (parent->verts[1][0][0]
00408 + parent->verts[1][1][0]) / 2.0;
00409 node->verts[1][j][1] = (parent->verts[1][0][1]
00410 + parent->verts[1][1][1]) / 2.0;
00411 }
00412 } else {
00413
00414 valid[i][j] = true;
00415 }
00416 }
00417 }
00418 }
00419
00420
00421
00422 TestSubdivide(node_num);
00423
00424 for (unsigned int i = 0; i < 2; i++)
00425 {
00426 for (unsigned int j = 0; j < 2; j++)
00427 {
00428 if (!valid[i][j])
00429 {
00430 node->flags |= transform_fail_flag << (j * 2 + i);
00431 }
00432 }
00433 }
00434
00435 if (node->flags & (split_flag_x | split_flag_y))
00436 {
00437
00438 if (!(node->flags & split_flag_x))
00439 {
00440
00441
00442 stretch_x++;
00443 }
00444 else if (!(node->flags & split_flag_y))
00445 {
00446 stretch_y++;
00447 }
00448
00449 x *= 2;
00450 y *= 2;
00451 row_size *= 2;
00452 depth++;
00453
00454 RecursiveUpdate(tree.GetIndex(x, y, row_size, depth),
00455 stretch_x, stretch_y);
00456
00457 if (node->flags & split_flag_x)
00458 {
00459 RecursiveUpdate(tree.GetIndex(x + 1, y, row_size, depth),
00460 stretch_x, stretch_y);
00461 }
00462
00463 if (node->flags & split_flag_y)
00464 {
00465 RecursiveUpdate(tree.GetIndex(x, y + 1, row_size, depth),
00466 stretch_x, stretch_y);
00467
00468 if (node->flags & split_flag_x)
00469 {
00470 RecursiveUpdate(tree.GetIndex(x + 1, y + 1, row_size, depth),
00471 stretch_x, stretch_y);
00472 }
00473 }
00474 }
00475 }
00476
00477 void VertexCoordRemapper::TestSubdivide(unsigned int node_id)
00478 {
00479 TreeNode *node = &tree.nodes[node_id];
00480 unsigned int x, y, row_size, depth;
00481 tree.GetPosition(node_id, x, y, row_size, depth);
00482 unsigned short int flags = 0;
00483 if (depth < min_depth)
00484 {
00485
00486
00487 SetLengthAndAngle(node);
00488 flags |= split_flag_x | split_flag_y;
00489 } else {
00490 unsigned int parent_id = tree.GetParentId(node_id);
00491 TreeNode *parent = &tree.nodes[parent_id];
00492
00493
00494
00495 SetLengthAndAngle(node);
00496 bool do_not_split_x = node->length_x * scale < min_length,
00497 do_not_split_y = node->length_y * scale < min_length;
00498 if (depth == max_depth)
00499 {
00500
00501 do_not_split_x = true;
00502 do_not_split_y = true;
00503 }
00504
00505
00506 if (!(tree.nodes[parent_id].flags & split_flag_x))
00507 {
00508 do_not_split_x = true;
00509 }
00510 else if (!(tree.nodes[parent_id].flags & split_flag_y))
00511 {
00512 do_not_split_y = true;
00513 }
00514
00515
00516 if (tree.nodes[parent_id].flags & patch_flag_x)
00517 {
00518 do_not_split_x = true;
00519 }
00520 else if (tree.nodes[parent_id].flags & patch_flag_y)
00521 {
00522 do_not_split_y = true;
00523 }
00524
00525
00526
00527
00528
00529
00530
00531
00532 float ang_x = node->angle_x - parent->angle_x;
00533 if (ang_x < 0) ang_x = -ang_x;
00534 if (ang_x > M_PI) ang_x = 2 * M_PI - ang_x;
00535 float length_difference_x
00536 = (parent->length_x - (2.0 * node->length_x)) * scale;
00537 if (length_difference_x < 0.0)
00538 {
00539 length_difference_x = -length_difference_x;
00540 }
00541 if (ang_x < min_angle && length_difference_x < min_length_difference)
00542 {
00543 do_not_split_x = true;
00544 }
00545 float ang_y = node->angle_y - parent->angle_y;
00546 if (ang_y < 0) ang_y = -ang_y;
00547 if (ang_y > M_PI) ang_y = 2 * M_PI - ang_y;
00548 float length_difference_y
00549 = (parent->length_y - (2.0 * node->length_y)) * scale;
00550 if (length_difference_y < 0.0)
00551 {
00552 length_difference_y = -length_difference_y;
00553 }
00554 if (ang_y < min_angle && length_difference_y < min_length_difference)
00555 {
00556 do_not_split_y = true;
00557 }
00558
00559
00560 vigra::Rect2D viewport = visualization_state->GetVisibleArea();
00561
00562
00563
00564
00565
00566 viewport.addBorder((int) (2.0 + offscreen_safety_margin * scale));
00567 bool all_left = true, all_right = true,
00568 all_above = true, all_bellow = true;
00569 for (unsigned int ix = 0; ix < 2; ix++)
00570 {
00571 for (unsigned int iy = 0; iy < 2; iy++)
00572 {
00573 if (node->verts[ix][iy][0] > viewport.left())
00574 all_left = false;
00575 if (node->verts[ix][iy][0] < viewport.right())
00576 all_right = false;
00577 if (node->verts[ix][iy][1] > viewport.top())
00578 all_above = false;
00579 if (node->verts[ix][iy][1] < viewport.bottom())
00580 all_bellow = false;
00581 }
00582 }
00583 if (all_left || all_right || all_bellow || all_above)
00584 {
00585
00586
00587 do_not_split_x = true;
00588 do_not_split_y = true;
00589 }
00590 if (!do_not_split_x) flags |= split_flag_x;
00591 if (!do_not_split_y) flags |= split_flag_y;
00592 }
00593
00594
00595
00596
00597
00598
00599 if (depth >= min_depth)
00600 {
00601
00602
00603
00604
00605 bool noncontinuous = false;
00606 OutputProjectionInfo *i = visualization_state->GetProjectionInfo();
00607 switch (output_projection)
00608 {
00609 case HuginBase::PanoramaOptions::RECTILINEAR:
00610
00611
00612
00613 break;
00614 case HuginBase::PanoramaOptions::FULL_FRAME_FISHEYE:
00615 case HuginBase::PanoramaOptions::STEREOGRAPHIC:
00616 case HuginBase::PanoramaOptions::LAMBERT_AZIMUTHAL:
00617 case HuginBase::PanoramaOptions::HAMMER_AITOFF:
00618
00619
00620
00621 break;
00622 case HuginBase::PanoramaOptions::CYLINDRICAL:
00623 case HuginBase::PanoramaOptions::EQUIRECTANGULAR:
00624 case HuginBase::PanoramaOptions::MERCATOR:
00625 case HuginBase::PanoramaOptions::LAMBERT:
00626 case HuginBase::PanoramaOptions::MILLER_CYLINDRICAL:
00627 case HuginBase::PanoramaOptions::PANINI:
00628 case HuginBase::PanoramaOptions::BIPLANE:
00629 case HuginBase::PanoramaOptions::TRIPLANE:
00630 case HuginBase::PanoramaOptions::GENERAL_PANINI:
00631
00632
00633
00634 if ( node->verts[0][0][0] < lower_bound
00635 || node->verts[0][0][0] > upper_bound
00636 || node->verts[1][0][0] < lower_bound
00637 || node->verts[1][0][0] > upper_bound
00638 || node->verts[0][1][0] < lower_bound
00639 || node->verts[0][1][0] > upper_bound
00640 || node->verts[1][1][0] < lower_bound
00641 || node->verts[1][1][0] > upper_bound)
00642 {
00643 noncontinuous = true;
00644
00645 if (node->verts[0][0][0] > x_midpoint)
00646 {
00647 flags |= vertex_side_flag_start;
00648 }
00649 if (node->verts[0][1][0] > x_midpoint)
00650 {
00651 flags |= vertex_side_flag_start * 2;
00652 }
00653 if (node->verts[1][0][0] > x_midpoint)
00654 {
00655 flags |= vertex_side_flag_start * 4;
00656 }
00657 if (node->verts[1][1][0] > x_midpoint)
00658 {
00659 flags |= vertex_side_flag_start * 8;
00660 }
00661 }
00662 break;
00663 case HuginBase::PanoramaOptions::SINUSOIDAL:
00664
00665 if ( node->verts[0][0][0] < i->GetLowerX(node->verts[0][0][1])
00666 || node->verts[0][0][0] > i->GetUpperX(node->verts[0][0][1])
00667 || node->verts[1][0][0] < i->GetLowerX(node->verts[1][0][1])
00668 || node->verts[1][0][0] > i->GetUpperX(node->verts[1][0][1])
00669 || node->verts[0][1][0] < i->GetLowerX(node->verts[0][1][1])
00670 || node->verts[0][1][0] > i->GetUpperX(node->verts[0][1][1])
00671 || node->verts[1][1][0] < i->GetLowerX(node->verts[1][1][1])
00672 || node->verts[1][1][0] > i->GetUpperX(node->verts[1][1][1])
00673 )
00674 {
00675 noncontinuous = true;
00676
00677 if (node->verts[0][0][0] > x_midpoint)
00678 {
00679 flags |= vertex_side_flag_start;
00680 }
00681 if (node->verts[0][1][0] > x_midpoint)
00682 {
00683 flags |= vertex_side_flag_start * 2;
00684 }
00685 if (node->verts[1][0][0] > x_midpoint)
00686 {
00687 flags |= vertex_side_flag_start * 4;
00688 }
00689 if (node->verts[1][1][0] > x_midpoint)
00690 {
00691 flags |= vertex_side_flag_start * 8;
00692 }
00693 }
00694 break;
00695 case HuginBase::PanoramaOptions::TRANSVERSE_MERCATOR:
00696
00697 if ( node->verts[0][0][1] < lower_bound_h
00698 || node->verts[0][0][1] > upper_bound_h
00699 || node->verts[1][0][1] < lower_bound_h
00700 || node->verts[1][0][1] > upper_bound_h
00701 || node->verts[0][1][1] < lower_bound_h
00702 || node->verts[0][1][1] > upper_bound_h
00703 || node->verts[1][1][1] < lower_bound_h
00704 || node->verts[1][1][1] > upper_bound_h)
00705 {
00706 noncontinuous = true;
00707
00708 if (node->verts[0][0][1] > y_midpoint)
00709 {
00710 flags |= vertex_side_flag_start;
00711 }
00712 if (node->verts[0][1][1] > y_midpoint)
00713 {
00714 flags |= vertex_side_flag_start * 2;
00715 }
00716 if (node->verts[1][0][1] > y_midpoint)
00717 {
00718 flags |= vertex_side_flag_start * 4;
00719 }
00720 if (node->verts[1][1][1] > y_midpoint)
00721 {
00722 flags |= vertex_side_flag_start * 8;
00723 }
00724 }
00725 break;
00726 case HuginBase::PanoramaOptions::ALBERS_EQUAL_AREA_CONIC:
00727 break;
00728 }
00729 if (noncontinuous)
00730 {
00731
00732
00733
00734 if ((flags / vertex_side_flag_start) % 16 == 15)
00735 {
00736 flags &= ~(vertex_side_flag_start * 15);
00737 }
00738 }
00739 }
00740
00741 node->flags = flags;
00742
00743 if (x && !(flags & split_flag_y) && (depth < max_depth))
00744 {
00745
00746 double dest_x, dest_y;
00747 unsigned int subdiv_node;
00748 subdiv_node = tree.GetTransform(x * 2, y * 2 + 1,
00749 depth * 2,
00750 x * 2, y * 2, dest_x, dest_y);
00751 if (subdiv_node > node_id)
00752 {
00753
00754
00755 node->flags |= split_flag_y | patch_flag_y;
00756 }
00757 }
00758 if (y && !(flags & split_flag_x) && (depth < max_depth))
00759 {
00760
00761 double dest_x, dest_y;
00762 unsigned int subdiv_node;
00763 subdiv_node = tree.GetTransform(x * 2 + 1, y * 2,
00764 depth * 2,
00765 x * 2, y * 2, dest_x, dest_y);
00766 if (subdiv_node > node_id)
00767 {
00768
00769
00770 node->flags |= split_flag_x | patch_flag_x;
00771 }
00772 }
00773 }
00774
00775 void VertexCoordRemapper::SetLengthAndAngle(TreeNode *node)
00776 {
00777 float xdx = node->verts[0][0][0] - node->verts[1][0][0],
00778 xdy = node->verts[0][0][1] - node->verts[1][0][1],
00779 ydx = node->verts[0][0][0] - node->verts[0][1][0],
00780 ydy = node->verts[0][0][1] - node->verts[0][1][1];
00781
00782 node->length_x = sqrt(sqr(xdx) + sqr(xdy));
00783
00784 node->length_y = sqrt(sqr(ydx) + sqr(ydy));
00785
00786 node->angle_x = atan2(xdy, xdx);
00787 node->angle_y = atan2(ydy, ydx);
00788 }
00789
00790 unsigned int VertexCoordRemapper::Tree::GetParentId(const unsigned int nodenum)
00791 {
00792
00793 unsigned int x, y, row_size, depth;
00794 GetPosition(nodenum, x, y, row_size, depth);
00795 return GetParentId(x, y, row_size, depth);
00796 }
00797
00798 unsigned int VertexCoordRemapper::Tree::GetParentId(unsigned int x,
00799 unsigned int y,
00800 unsigned int row_size,
00801 unsigned int depth)
00802 {
00803
00804
00805
00806 x /= 2;
00807 y /= 2;
00808 row_size /= 2;
00809 depth--;
00810 return GetIndex(x, y, row_size, depth);
00811 }
00812
00813 unsigned int VertexCoordRemapper::Tree::GetDepth(const unsigned int node_num)
00814 {
00815 unsigned int depth = 0, count = 0;
00816 while (node_num > count)
00817 {
00818 depth++;
00819 count += 1 << (depth * 2);
00820 }
00821 return depth;
00822 }
00823
00824 void VertexCoordRemapper::Tree::GetPosition(const unsigned int node_num,
00825 unsigned int &x, unsigned int &y,
00826 unsigned int &row_size,
00827 unsigned int &depth)
00828 {
00829 depth = GetDepth(node_num);
00830 row_size = 1 << depth;
00831 unsigned int sub = 0;
00832 if (depth)
00833 {
00834 for (unsigned int d = 0; d < depth; d++)
00835 {
00836 sub += (1 << (d * 2));
00837 }
00838 }
00839 unsigned int position_id = node_num - sub;
00840 x = position_id % row_size;
00841 y = position_id / row_size;
00842 }
00843
00844 unsigned int VertexCoordRemapper::Tree::GetIndex(const unsigned int x,
00845 const unsigned int y,
00846 const unsigned int row_size,
00847 unsigned int depth)
00848 {
00849 unsigned int add = 0;
00850 while (depth)
00851 {
00852 depth--;
00853 add += 1 << (depth * 2);
00854 }
00855 return add + x + y * row_size;
00856 }
00857
00858 void VertexCoordRemapper::Tree::GetInputCoordinates(const unsigned int node_num,
00859 double coords[2][2][2])
00860 {
00861
00862
00863
00864
00865 unsigned int x, y, row_size, depth;
00866 GetPosition(node_num, x, y, row_size, depth);
00867
00868 double row_spacing = 1.0 / (double) row_size;
00869 coords[0][0][0] = row_spacing * (double) x;
00870 coords[0][0][1] = row_spacing * (double) y;
00871
00872
00873
00874 bool scale_x = false;
00875 double opp = 1.0;
00876 if (node_num != 0)
00877 {
00878 unsigned int parent_id = GetParentId(x, y, row_size, depth);
00879 if (!(nodes[parent_id].flags & split_flag_x))
00880 {
00881 while (!(nodes[parent_id].flags & split_flag_x))
00882 {
00883 parent_id = GetParentId(parent_id);
00884 opp *= 2.0;
00885 }
00886 scale_x = true;
00887 } else {
00888 while (!(nodes[parent_id].flags & split_flag_y))
00889 {
00890 parent_id = GetParentId(parent_id);
00891 opp *= 2.0;
00892 }
00893 }
00894 }
00895 opp *= row_spacing;
00896 coords[1][0][0] = coords[0][0][0] + (scale_x ? opp : row_spacing);
00897 coords[1][0][1] = coords[0][0][1];
00898 coords[0][1][0] = coords[0][0][0];
00899 coords[0][1][1] = coords[0][0][1] + (scale_x ? row_spacing : opp);
00900 coords[1][1][0] = coords[1][0][0];
00901 coords[1][1][1] = coords[0][1][1];
00902
00903
00904 for (unsigned int i = 0; i < 2; i++)
00905 {
00906 for (unsigned int j = 0; j < 2; j++)
00907 {
00908 coords[i][j][0] = coords[i][j][0] * x_crop_scale + x_crop_offs;
00909 coords[i][j][1] = coords[i][j][1] * y_crop_scale + y_crop_offs;
00910 }
00911 }
00912 }
00913
00914 void VertexCoordRemapper::Tree::ResetIndex()
00915 {
00916 cur_tree_node = 0;
00917 }
00918
00919 unsigned int VertexCoordRemapper::Tree::GetNext()
00920 {
00921
00922 unsigned int x, y, row_size, depth;
00923 GetPosition(cur_tree_node, x, y, row_size, depth);
00924
00925
00926 if (cur_tree_node != 0)
00927 {
00928 unsigned int xd = 0, yd = 0;
00929 bool done = false;
00930 while (!done && cur_tree_node != 0)
00931 {
00932 xd = x % 2;
00933 yd = y % 2;
00934 x /= 2;
00935 y /= 2;
00936 row_size /= 2;
00937 depth--;
00938 cur_tree_node = GetIndex(x, y, row_size, depth);
00939 if (cur_tree_node == 0 && xd == 1 && yd == 1)
00940 {
00941
00942 return 0;
00943 }
00944
00945 bool sx = ((nodes[cur_tree_node].flags & split_flag_x) != 0);
00946 bool sy = ((nodes[cur_tree_node].flags & split_flag_y) != 0);
00947
00948 if (!(((sx && xd) || !sx) && ((sy && yd) || !sy)))
00949 {
00950
00951 done = true;
00952 x *= 2;
00953 y *= 2;
00954 row_size *= 2;
00955 depth++;
00956 if (sx && !xd && !yd) {
00957 x++;
00958 } else if ((sx && xd && sy && !yd) || (!sx && sy && !yd)) {
00959 y++;
00960 } else if (sx && sy && !xd && yd) {
00961 x++; y++;
00962 }
00963 cur_tree_node = GetIndex(x, y, row_size, depth);
00964
00965
00966 if (cur_tree_node == 0)
00967 {
00968 return 0;
00969 }
00970 };
00971 }
00972 }
00973
00974 while (nodes[cur_tree_node].flags & (split_flag_x | split_flag_y))
00975 {
00976 x *= 2;
00977 y *= 2;
00978 row_size *= 2;
00979 depth++;
00980 cur_tree_node = GetIndex(x, y, row_size, depth);
00981 }
00982 return cur_tree_node;
00983 }
00984
00985 unsigned int VertexCoordRemapper::Tree::GetTransform(unsigned int src_x, unsigned int src_y,
00986 unsigned int max_depth,
00987 unsigned int stop_x, unsigned int stop_y,
00988 double &dest_x, double &dest_y)
00989 {
00990
00991
00992
00993 unsigned int no_x = 0, no_y = 0, row_size = 1, depth = 0,
00994 rem_x = src_x, rem_y = src_y,
00995 step_x = 1 << max_depth, step_y = 1 << max_depth,
00996 node_id = GetIndex(no_x, no_y, row_size, depth);
00997 while ( !( (rem_x == 0 || rem_x == step_x)
00998 && (rem_y == 0 || rem_y == step_y))
00999 && (nodes[node_id].flags & (split_flag_x | split_flag_y)))
01000 {
01001
01002 depth++;
01003 no_x *= 2;
01004 no_y *= 2;
01005 row_size *= 2;
01006 if (nodes[node_id].flags & split_flag_x)
01007 {
01008 step_x /= 2;
01009 if (rem_x > step_x)
01010 {
01011 no_x ++;
01012 rem_x -= step_x;
01013 }
01014 }
01015 if (nodes[node_id].flags & split_flag_y)
01016 {
01017 step_y /= 2;
01018 if (rem_y > step_y)
01019 {
01020 no_y ++;
01021 rem_y -= step_y;
01022 }
01023 }
01024
01025
01026 if (depth > max_depth) return 0;
01027 node_id = GetIndex(no_x, no_y, row_size, depth);
01028 if (depth == max_depth && no_x >= stop_x && no_y >= stop_y) return 0;
01029 }
01030
01031
01032 if (nodes[node_id].flags & (transform_fail_flag * 15)) return 0;
01033
01034
01035 if (nodes[node_id].flags & (vertex_side_flag_start * 15)) return 0;
01036
01037
01038
01039
01040
01041
01042
01043 double xf = (double) rem_x / (double) step_x;
01044 double yf = (double) rem_y / (double) step_y;
01045
01046 double top_x = (1.0 - xf) * nodes[node_id].verts[0][0][0]
01047 + xf * nodes[node_id].verts[1][0][0],
01048 bottom_x = (1-.0 - xf) * nodes[node_id].verts[0][1][0]
01049 + xf * nodes[node_id].verts[1][1][0],
01050 top_y = (1.0 - xf) * nodes[node_id].verts[0][0][1]
01051 + xf * nodes[node_id].verts[1][0][1],
01052 bottom_y = (1.0 - xf) * nodes[node_id].verts[0][1][1]
01053 + xf * nodes[node_id].verts[1][1][1];
01054 dest_x = top_x * (1.0 - yf) + bottom_x * yf;
01055 dest_y = top_y * (1.0 - yf) + bottom_y* yf;
01056 return node_id;
01057 }
01058