00001
00002
00023 #ifdef __WXMAC__
00024 #include "panoinc_WX.h"
00025 #include "panoinc.h"
00026 #endif
00027
00028 #include <math.h>
00029 #include "MeshRemapper.h"
00030 #include "ViewState.h"
00031
00032 MeshRemapper::MeshRemapper(HuginBase::Panorama *m_pano_in,
00033 HuginBase::SrcPanoImage * image_in,
00034 VisualizationState *visualization_state_in)
00035 {
00036 m_pano = m_pano_in;
00037 image = image_in;
00038 visualization_state = visualization_state_in;
00039 }
00040
00041 MeshRemapper::~MeshRemapper()
00042 {
00043 }
00044
00045 void MeshRemapper::UpdateAndResetIndex()
00046 {
00047
00048
00049
00050 width = (double) image->getSize().width();
00051 height = (double) image->getSize().height();
00052
00053
00054
00055 scale = visualization_state->GetScale();
00056
00057
00058
00059 }
00060
00061 void MeshRemapper::SetCrop()
00062 {
00063
00064 crop_mode = image->getCropMode();
00065 crop_x1 = (double) image->getCropRect().left() / width;
00066 crop_x2 = (double) image->getCropRect().right() / width;
00067 crop_y1 = (double) image->getCropRect().top() / height;
00068 crop_y2 = (double) image->getCropRect().bottom() / height;
00069
00070 circle_crop = image->getCropMode() == HuginBase::SrcPanoImage::CROP_CIRCLE;
00071 if (circle_crop)
00072 {
00073 circle_crop_centre_x = (crop_x1 + crop_x2) / 2.0;
00074 circle_crop_centre_y = (crop_y1 + crop_y2) / 2.0;
00075 double crop_width_px = (double) image->getCropRect().width(),
00076 crop_hieght_px = (double) image->getCropRect().height(),
00077 crop_radius = (crop_width_px < crop_hieght_px ?
00078 crop_width_px : crop_hieght_px) / 2.0;
00079 circle_crop_radius_x = crop_radius / width;
00080 circle_crop_radius_y = crop_radius / height;
00081 }
00082
00083
00084 if (crop_x1 < 0.0) crop_x1 = 0.0; if (crop_x1 > 1.0) crop_x1 = 1.0;
00085 if (crop_x2 < 0.0) crop_x2 = 0.0; if (crop_x2 > 1.0) crop_x2 = 1.0;
00086 if (crop_y1 < 0.0) crop_y1 = 0.0; if (crop_y1 > 1.0) crop_y1 = 1.0;
00087 if (crop_y2 < 0.0) crop_y2 = 0.0; if (crop_y2 > 1.0) crop_y2 = 1.0;
00088 }
00089
00090
00091
00092
00093
00094
00095 class Vertex
00096 {
00097 public:
00098 Vertex(double vx, double vy, double tx, double ty);
00099 Vertex() {}
00100 double vertex_c[2];
00101 double tex_c[2];
00102 };
00103
00104 Vertex::Vertex(double vx, double vy, double tx, double ty)
00105 {
00106 vertex_c[0] = vx;
00107 vertex_c[1] = vy;
00108 tex_c[0] = tx;
00109 tex_c[1] = ty;
00110 }
00111
00112
00113
00114
00115 class A_Polygon
00116 {
00117 public:
00118
00119 A_Polygon(MeshRemapper::Coords *face);
00120 A_Polygon() {}
00121
00122
00123 A_Polygon Clip(const double clip_line[3]);
00124
00125
00126 inline void AddVertex(Vertex v);
00127
00128 std::vector<MeshRemapper::ArrayCoords> ConvertToQuads();
00129 private:
00130
00131 std::vector<Vertex> verts;
00132
00133 inline bool Inside(const unsigned int vertex,
00134 const double clip_line[3]) const;
00135
00136
00137 Vertex Intersect(const unsigned int v1, const unsigned int v2,
00138 const double clip_line[3]) const;
00139 };
00140
00141 A_Polygon::A_Polygon(MeshRemapper::Coords *face)
00142 {
00143 verts.resize(4);
00144 for (unsigned short int v = 0; v < 4; v++)
00145 {
00146
00147 unsigned short int x = (v == 2 || v==3) ? 1 : 0,
00148 y = (v == 1 || v==2) ? 1 : 0;
00149 for (unsigned short int a = 0; a < 2; a++)
00150 {
00151 verts[v].vertex_c[a] = face->vertex_c[x][y][a];
00152 verts[v].tex_c[a] = face->tex_c[x][y][a];
00153 }
00154 }
00155 }
00156
00157 inline void A_Polygon::AddVertex(Vertex v)
00158 {
00159 verts.push_back(v);
00160 }
00161
00162 inline bool A_Polygon::Inside(const unsigned int v, const double l[3]) const
00163 {
00164 return verts[v].tex_c[0] * l[0] + verts[v].tex_c[1] * l[1] + l[2] > 0;
00165 }
00166
00167 Vertex A_Polygon::Intersect(const unsigned int v1_index,
00168 const unsigned int v2_index,
00169 const double cl[3]) const
00170 {
00171
00172
00173
00174 const Vertex *v1 = &verts[v1_index],
00175
00176 *v2 = &verts[v2_index];
00177
00178 double dx = v2->tex_c[0] - v1->tex_c[0],
00179 dy = v2->tex_c[1] - v1->tex_c[1];
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194 double t = (-cl[0] * v1->tex_c[0] - cl[1] * v1->tex_c[1] - cl[2]) /
00195 (cl[0] * dx + cl[1] * dy),
00196
00197 x = dx * t + v1->tex_c[0],
00198 y = dy * t + v1->tex_c[1],
00199
00200
00201 td1 = 1.0 - t,
00202 xc = v1->vertex_c[0] * td1 + v2->vertex_c[0] * t,
00203 yc = v1->vertex_c[1] * td1 + v2->vertex_c[1] * t;
00204
00205 return Vertex(xc, yc, x, y);
00206 }
00207
00208 A_Polygon A_Polygon::Clip(const double clip_line[3])
00209 {
00210
00211
00212 A_Polygon result;
00213 unsigned int vertices_count = verts.size(),
00214 v_previous = vertices_count - 1;
00215
00216 for (unsigned int v_index = 0; v_index < vertices_count; v_index++)
00217 {
00218 bool v_index_inside = Inside(v_index, clip_line),
00219 v_previous_inside = Inside(v_previous, clip_line);
00220 if (v_index_inside != v_previous_inside)
00221 {
00222
00223 result.AddVertex(Intersect(v_previous, v_index, clip_line));
00224 }
00225 if (v_index_inside)
00226 {
00227
00228 result.AddVertex(verts[v_index]);
00229 }
00230 v_previous = v_index;
00231 }
00232 return result;
00233 }
00234
00235 std::vector<MeshRemapper::ArrayCoords> A_Polygon::ConvertToQuads()
00236 {
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252 std::vector<MeshRemapper::ArrayCoords> result;
00253 unsigned int vertices_count = verts.size();
00254 unsigned int i = 2;
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266 while (i < vertices_count)
00267 {
00268 if (i < vertices_count - 1)
00269 {
00270
00271 MeshRemapper::ArrayCoords quad;
00272 for (unsigned short int c = 0; c < 2; c++)
00273 {
00274 quad.vertex_c[0][0][c] = verts[ 0 ].vertex_c[c];
00275 quad.tex_c [0][0][c] = verts[ 0 ].tex_c [c];
00276 quad.vertex_c[0][1][c] = verts[i - 1].vertex_c[c];
00277 quad.tex_c [0][1][c] = verts[i - 1].tex_c [c];
00278 quad.vertex_c[1][1][c] = verts[ i ].vertex_c[c];
00279 quad.tex_c [1][1][c] = verts[ i ].tex_c [c];
00280 quad.vertex_c[1][0][c] = verts[i + 1].vertex_c[c];
00281 quad.tex_c [1][0][c] = verts[i + 1].tex_c [c];
00282 }
00283 result.push_back(quad);
00284 i += 2;
00285 }
00286 else
00287 {
00288
00289 MeshRemapper::ArrayCoords quad;
00290 for (unsigned short int c = 0; c < 2; c++)
00291 {
00292 quad.vertex_c[0][0][c] = verts[ 0 ].vertex_c[c];
00293 quad.tex_c [0][0][c] = verts[ 0 ].tex_c [c];
00294 quad.vertex_c[0][1][c] = verts[i - 1].vertex_c[c];
00295 quad.tex_c [0][1][c] = verts[i - 1].tex_c [c];
00296 quad.vertex_c[1][1][c] = verts[ i ].vertex_c[c];
00297 quad.tex_c [1][1][c] = verts[ i ].tex_c [c];
00298 quad.vertex_c[1][0][c] = verts[ i ].vertex_c[c];
00299 quad.tex_c [1][0][c] = verts[ i ].tex_c [c];
00300 }
00301 result.push_back(quad);
00302 i ++;
00303 }
00304 }
00305 return result;
00306 }
00307
00308 void MeshRemapper::ClipFace(MeshRemapper::Coords *face)
00309 {
00310
00311
00312
00313
00314
00315
00316 A_Polygon poly(face);
00317
00318 double clip_lines[4][3] = {{ 1.0, 0.0, -crop_x1},
00319 {-1.0, 0.0, crop_x2},
00320 { 0.0, 1.0, -crop_y1},
00321 { 0.0, -1.0, crop_y2}};
00322
00323 poly = poly.Clip(clip_lines[0]);
00324 poly = poly.Clip(clip_lines[1]);
00325 poly = poly.Clip(clip_lines[2]);
00326 poly = poly.Clip(clip_lines[3]);
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337 if (circle_crop)
00338 {
00339 for (unsigned int edge = 0; edge < 4; edge++)
00340 {
00341 double angle = M_PI + atan2(face->tex_c[edge % 2][edge / 2][1]
00342 - circle_crop_centre_y,
00343 face->tex_c[edge % 2][edge / 2][0]
00344 - circle_crop_centre_x),
00345 ac_x = cos(angle) / circle_crop_radius_x,
00346 ac_y = sin(angle) / circle_crop_radius_y,
00347 clip_line[3] = {ac_x, ac_y, 1.0 - ac_x * circle_crop_centre_x
00348 - ac_y * circle_crop_centre_y};
00349 poly = poly.Clip(clip_line);
00350 }
00351 }
00352
00353 face_list = poly.ConvertToQuads();
00354 }
00355
00356 bool MeshRemapper::GiveClipFaceResult(Coords * result)
00357 {
00358 if (face_list.empty())
00359 {
00360
00361 return false;
00362 } else {
00363
00364 for (unsigned short int x = 0; x < 2; x++)
00365 {
00366 for (unsigned short int y = 0; y < 2; y++)
00367 {
00368 for (unsigned short int c = 0; c < 2; c++)
00369 {
00370 result->tex_c[x][y][c] = face_list.back().tex_c[x][y][c];
00371 result->vertex_c[x][y][c] = face_list.back().vertex_c[x][y][c];
00372 }
00373 }
00374 }
00375 face_list.pop_back();
00376 return true;
00377 }
00378 }
00379