OpenTracker

An Open Architecture for Reconfigurable Tracking based on XML | Contact

QtAppScreen.cxx

Go to the documentation of this file.
00001 /* ========================================================================
00002  * Copyright (c) 2006,
00003  * Institute for Computer Graphics and Vision
00004  * Graz University of Technology
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions are
00009  * met:
00010  *
00011  * Redistributions of source code must retain the above copyright notice,
00012  * this list of conditions and the following disclaimer.
00013  *
00014  * Redistributions in binary form must reproduce the above copyright
00015  * notice, this list of conditions and the following disclaimer in the
00016  * documentation and/or other materials provided with the distribution.
00017  *
00018  * Neither the name of the Graz University of Technology nor the names of
00019  * its contributors may be used to endorse or promote products derived from
00020  * this software without specific prior written permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
00023  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00024  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00025  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
00026  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00027  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00028  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00029  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00030  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00031  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00032  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033  * ========================================================================
00034  * PROJECT: OpenTracker
00035  * ======================================================================== */
00045 #include <dllinclude.h>
00046 #if USE_OTQT
00047 
00048 #include "QtAppScreen.h"
00049 #include <qapplication.h>
00050 #include <math.h>
00051 
00052 namespace ot {
00053 
00054 //--------------------------------------------------------------------------------
00055 QtAppScreen::QtAppScreen(StringTable & table)
00056   : ConfigNode(table)
00057 {
00059 
00060   attributes.get("CSOrientationQuat", calib_out_.as_cs_orient, 4);
00061   attributes.get("CSRoot2ScreenRootVec", calib_out_.as_cs_root_to_screen_root, 3);
00062   attributes.get("ASWidthVec", calib_out_.as_width_vec, 3);
00063   attributes.get("ASHeightVec", calib_out_.as_height_vec, 3);
00064 
00066 
00067   // CS root / screen root position
00068   for (int i = 0; i < 4; i++) {
00069     as_data_init_.as_cs_root.getOrientation()[i] = calib_out_.as_cs_orient[i];
00070     as_data_init_.as_screen_root.getOrientation()[i] = calib_out_.as_cs_orient[i];
00071   }
00072   // CS root / screen root position, screen plane span vectors
00073   for (int i = 0; i < 3; i++) {
00074     as_data_init_.as_cs_root.getPosition()[i] = 0;
00075     as_data_init_.as_screen_root.getPosition()[i] = calib_out_.as_cs_root_to_screen_root[i];
00076     as_data_init_.as_width_vec[i] = calib_out_.as_width_vec[i];
00077     as_data_init_.as_height_vec[i] = calib_out_.as_height_vec[i];
00078   }
00079 
00080   // compute screen depth scale
00081   float tracking_one_meter;
00082   attributes.get("TrackingSystemScaleOneMeter", &tracking_one_meter);
00083   float as_depth_front_in_meter, as_depth_back_in_meter;
00084   attributes.get("ScreenDepthFrontInMeter", &as_depth_front_in_meter);
00085   attributes.get("ScreenDepthBackInMeter", &as_depth_back_in_meter);
00086   as_data_init_.as_depth_scalar_front = tracking_one_meter * as_depth_front_in_meter;
00087   as_data_init_.as_depth_scalar_back = tracking_one_meter * as_depth_back_in_meter;
00088 
00090 
00091   as_data_.as_cs_root = as_data_init_.as_cs_root;
00092   as_data_.as_screen_root = as_data_init_.as_screen_root;
00093   as_data_.as_depth_scalar_front = as_data_init_.as_depth_scalar_front;
00094   as_data_.as_depth_scalar_back = as_data_init_.as_depth_scalar_back;
00095   for (int i = 0; i < 3; i++) {
00096     as_data_.as_width_vec[i] = as_data_init_.as_width_vec[i];
00097     as_data_.as_height_vec[i] = as_data_init_.as_height_vec[i];
00098   }
00099 
00101 
00102   updateMPD(Event::null);
00103 }
00104 
00105 //--------------------------------------------------------------------------------
00106 void QtAppScreen::convert(CalibOutputData const & out, StringTable & table)
00107 {
00108   // generate attributes from calibration output data
00109   float tmp3[3], tmp4[4];
00110   table.put("CSOrientationQuat", ot::copyV2A(out.as_cs_orient, tmp4), 4);
00111   table.put("CSRoot2ScreenRootVec", ot::copyV2A(out.as_cs_root_to_screen_root, tmp3), 3);
00112   table.put("ASWidthVec", ot::copyV2A(out.as_width_vec, tmp3), 3);
00113   table.put("ASHeightVec", ot::copyV2A(out.as_height_vec, tmp3), 3);
00114 }
00115 
00116 
00117 //--------------------------------------------------------------------------------
00118 void QtAppScreen::convert(CalibInputData const & in, CalibOutputData & out)
00119 {
00121 
00122   CalibInputData in_final;
00123   in_final.as_cs_root = in.as_cs_root;
00124 
00125   // top / left
00126   OTQtMath::transformVectorFromCSToCS(in.top_left.local_cs_root, in_final.as_cs_root,
00127                                       in.top_left.corner, in_final.top_left.corner);
00128   in_final.top_left.local_cs_root = in_final.as_cs_root;
00129   // top / right
00130   OTQtMath::transformVectorFromCSToCS(in.top_right.local_cs_root, in_final.as_cs_root,
00131                                       in.top_right.corner, in_final.top_right.corner);
00132   in_final.top_right.local_cs_root = in_final.as_cs_root;
00133   // bottom / right
00134   OTQtMath::transformVectorFromCSToCS(in.bottom_right.local_cs_root, in_final.as_cs_root,
00135                                       in.bottom_right.corner, in_final.bottom_right.corner);
00136   in_final.bottom_right.local_cs_root = in_final.as_cs_root;
00137   // bottom / left
00138   OTQtMath::transformVectorFromCSToCS(in.bottom_left.local_cs_root, in_final.as_cs_root,
00139                                       in.bottom_left.corner, in_final.bottom_left.corner);
00140   in_final.bottom_left.local_cs_root = in_final.as_cs_root;
00141 
00142 
00144 
00145   //  out.as_cs_orient.resize(4);
00146   OTQT_DEBUG("QtAppScreen::convert(): out.as_cs_orient.size() = %i\n", out.as_cs_orient.size());
00147   for (int i = 0; i < 4; i++) {
00148     out.as_cs_orient[i] = in_final.as_cs_root.getOrientation()[i];
00149   }
00150 
00152 
00153   //  out.as_cs_root_to_screen_root.resize(3);
00154   for (int i = 0; i < 3; i++) {
00155     out.as_cs_root_to_screen_root[i] =
00156       in_final.top_left.corner.getPosition()[i] - in_final.as_cs_root.getPosition()[i];
00157   }
00158 
00160 
00161 
00162   // +++ Coordinate System
00163   //
00164   //   ASP (coordinate system root (pos/orient)
00165   //   /
00166   //  /
00167   // SR (screen root == top/left)
00168   //
00169   // +++ Screen plane and corners
00170   //
00171   // P1 (top/left) ----- P2 (top/right)
00172   // |                   |
00173   // |   screen plane    |
00174   // |                   |
00175   // P4 (bottom/left) -- P3 (bottom/right)
00176   //
00177   // +++ Base Vectors
00178   //
00179   // P1 -> P2, P4 -> P3: "x-axis" : v1 (vec_tl_tr)
00180   // P1 -> P4, P2 -> P3 : "y-axis" : v2 (vec_tl_tr)
00181 
00182   // corners of screen
00183   RowVector tl(3); // P1
00184   float tmp[3];
00185   tl << ot::copyV2A(in_final.top_left.corner.getPosition(), tmp);
00186   RowVector tr(3); // P2
00187   tr << ot::copyV2A(in_final.top_right.corner.getPosition(), tmp);
00188   RowVector br(3); // P3
00189   br << ot::copyV2A(in_final.bottom_right.corner.getPosition(), tmp);
00190   RowVector bl(3); // P4
00191   bl << ot::copyV2A(in_final.bottom_left.corner.getPosition(), tmp);
00192 
00193   // vectors which span screen plane (cuboid)
00194   RowVector vec_tl_tr(3); // x - direction, v1
00195   RowVector vec_tl_bl(3); // y - direction, v2
00196 
00197   // base vector v1: top/left -> top/right
00198   vec_tl_tr = tr - tl;
00199 
00200   // diagonal vector: top/left -> bottom/right
00201   RowVector diag_tl_br = br - tl;
00202   // length parameter for diagonal vector, resets bottom/right corner position, difference
00203   // vector between bottom/right and top/right is normal on v1
00204   float k = DotProduct(vec_tl_tr, vec_tl_tr) / DotProduct(vec_tl_tr, diag_tl_br);
00205   // base vector v2: top/right -> (transformed) bottom/right
00206   vec_tl_bl = k * diag_tl_br - vec_tl_tr;
00207 
00208   //  out.as_width_vec.resize(3);
00209   // out.as_height_vec.resize(3);
00210   for (int i = 0; i < 3; i++) {
00211     out.as_width_vec[i] = vec_tl_tr(i+1);
00212     out.as_height_vec[i] = vec_tl_bl(i+1);
00213   }
00214 }
00215 
00216 //--------------------------------------------------------------------------------
00217 void QtAppScreen::updateASPD(Event const & as_cs_root_curr)
00218 {
00220 
00221   Event as_screen_root_curr;
00222   OTQtMath::transformVectorFromCSToCS(as_data_init_.as_cs_root, as_cs_root_curr,
00223                                       as_data_init_.as_screen_root, as_screen_root_curr);
00224   as_data_.as_screen_root = as_screen_root_curr;
00225 
00227   std::vector<float> as_width_vec_curr(3);
00228   OTQtMath::rotateVectorFromCSToCS(as_data_init_.as_cs_root, as_cs_root_curr,
00229                                    as_data_init_.as_width_vec, as_width_vec_curr);
00230   std::vector<float> as_height_vec_curr(3);
00231   OTQtMath::rotateVectorFromCSToCS(as_data_init_.as_cs_root, as_cs_root_curr,
00232                                    as_data_init_.as_height_vec, as_height_vec_curr);
00233   for (int i = 0; i < 3; i++) {
00234     as_data_.as_width_vec[i] = as_width_vec_curr[i];
00235     as_data_.as_height_vec[i] = as_height_vec_curr[i];
00236   }
00237 
00238   // set current CS root
00239   as_data_.as_cs_root = as_cs_root_curr;
00240 }
00241 
00242 //--------------------------------------------------------------------------------
00243 void QtAppScreen::updateMPD(Event const & mpd_pos)
00244 {
00245 
00246   // save current MPD pos
00247   mp_data_.position = mpd_pos;
00248 
00250 
00251   // base vector "x-axis"
00252   RowVector width(3);
00253   float tmp3[3];
00254   width << ot::copyV2A(as_data_.as_width_vec, tmp3);
00255   // base vector "y-axis"
00256   RowVector height(3);
00257   height << ot::copyV2A(as_data_.as_height_vec, tmp3);
00258 
00259   // base vector "z-axis" as cross product width x height
00260   RowVector depth = - OTQtMath::crossProductR3(width, height);
00261   OTQT_DEBUG("QtAppScreen::updateMPD(): depth = width x height = %f %f %f\n",
00262              depth(1), depth(2), depth(3));
00263   RowVector depth1 = depth / depth.NormFrobenius();
00264   // add negative depth (back side of screen depth)
00265   depth = depth1 * (as_data_.as_depth_scalar_front + as_data_.as_depth_scalar_back);
00266 
00267   // screen root
00268   RowVector screen_root(3);
00269   screen_root << ot::copyV2A(as_data_.as_screen_root.getPosition(), tmp3);
00270   RowVector depth_screen_root = screen_root - (depth1 * as_data_.as_depth_scalar_back);
00271 
00272   // given MPD position
00273   RowVector mpos(3);
00274   mpos << ot::copyV2A(mpd_pos.getPosition(), tmp3);
00275 
00277 
00278   RowVector distances_width(2);
00279   RowVector distances_height(2);
00280   RowVector distances_depth(2);
00281   if (!OTQtMath::isWithinPlaneBorders(mpos, width, screen_root, distances_width) ||
00282       !OTQtMath::isWithinPlaneBorders(mpos, height, screen_root, distances_height) ||
00283       !OTQtMath::isWithinPlaneBorders(mpos, depth, depth_screen_root, distances_depth))
00284   {
00285     // transition inside -> outside: MPD location changed
00286     bool mpd_loc_changed_this_cycle = (mp_data_.mpd_loc_inside_screen_cuboid);
00287     // MPD is located outside SC
00288     mp_data_.mpd_loc_inside_screen_cuboid = false;
00289 
00290     if (OTQT_DEBUG_ON && mpd_loc_changed_this_cycle) {
00291       OTQT_DEBUG("QtAppScreen::updateMPD(): depth = %f %f %f\n",
00292           depth(1), depth(2), depth(3));
00293       OTQT_DEBUG("QtAppScreen::updateMPD(): width = %f, distances_width() = %f %f\n",
00294           width.NormFrobenius(), distances_width(1), distances_width(2));
00295       OTQT_DEBUG("QtAppScreen::updateMPD(): height = %f, distances_height() = %f %f\n",
00296           height.NormFrobenius(), distances_height(1), distances_height(2));
00297       OTQT_DEBUG("QtAppScreen::updateMPD(): depth = %f, distances_depth() = %f %f\n",
00298           depth.NormFrobenius(), distances_depth(1), distances_depth(2));
00299     }
00300     return;
00301   }
00302 
00303   // NOTE: MPD position is within screen cuboid
00304 
00306 
00307   RowVector mpos_screen_coords(2);
00308   mpos_screen_coords(1) = distances_width(1);
00309   mpos_screen_coords(2) = distances_height(1);
00310   OTQT_DEBUG("QtAppScreen::isMPDWithinScreenCuboid(): mpos_screen_coords = %f %f\n",
00311              mpos_screen_coords(1), mpos_screen_coords(2));
00312 
00313   // convert to Qt desktop coordinates
00314   QPoint desktop_coords_new;
00315   QRect const & desktop = QApplication::desktop()->screenGeometry();
00316   OTQT_DEBUG("QtAppScreen::isMPDWithinScreenCuboid(): desktop = %d %d\n",
00317              desktop.width(), desktop.height());
00318 #ifdef WIN32
00319   desktop_coords_new.setX((int)floor((mpos_screen_coords(1) / width.NormFrobenius()) * (float)desktop.width()) - 1);
00320   desktop_coords_new.setY((int)floor((mpos_screen_coords(2) / height.NormFrobenius()) * (float)desktop.height()) - 1);
00321 #else
00322   desktop_coords_new.setX((int)round((mpos_screen_coords(1) / width.NormFrobenius()) * (float)desktop.width()) - 1);
00323   desktop_coords_new.setY((int)round((mpos_screen_coords(2) / height.NormFrobenius()) * (float)desktop.height()) - 1);
00324 #endif
00325 
00327 
00328   // transition outside -> inside: MPD location changed
00329   bool mpd_loc_changed_this_cycle = !(mp_data_.mpd_loc_inside_screen_cuboid);
00330   // MPD is located INSIDE SC
00331   mp_data_.mpd_loc_inside_screen_cuboid = true;
00332   // desktop mouse cursor coordinates
00333   mp_data_.desktop_coords = desktop_coords_new;
00334 
00335   if (OTQT_DEBUG_ON && mpd_loc_changed_this_cycle) {
00336     OTQT_DEBUG("QtAppScreen::updateMPD(): width = %f, distances_width() = %f %f\n",
00337               width.NormFrobenius(), distances_width(1), distances_width(2));
00338     OTQT_DEBUG("QtAppScreen::updateMPD(): height = %f, distances_height() = %f %f\n",
00339               height.NormFrobenius(), distances_height(1), distances_height(2));
00340     OTQT_DEBUG("QtAppScreen::updateMPD(): depth = %f, distances_depth() = %f %f\n",
00341               depth.NormFrobenius(), distances_depth(1), distances_depth(2));
00342   }
00343 
00344   return;
00345 }
00346 
00347 //--------------------------------------------------------------------------------
00348 QtAppScreen::MPDLocationState
00349 QtAppScreen::getMPDLocation() const
00350 {
00351   MPDLocationState ret = MPD_LOC_UNKNOWN;
00352 
00353   if (mp_data_.mpd_loc_inside_screen_cuboid)
00354     ret = MPD_LOC_INSIDE_SC;
00355   else
00356     ret = MPD_LOC_OUTSIDE_SC;
00357 
00358   return ret;
00359 }
00360 
00361 } // namespace ot
00362 
00363 #endif // USE_OTQT
00364 
00365 
00366 /*
00367  * ------------------------------------------------------------
00368  *   End of QtAppScreen.cxx
00369  * ------------------------------------------------------------
00370  *   Automatic Emacs configuration follows.
00371  *   Local Variables:
00372  *   mode:c++
00373  *   c-basic-offset: 4
00374  *   eval: (c-set-offset 'substatement-open 0)
00375  *   eval: (c-set-offset 'case-label '+)
00376  *   eval: (c-set-offset 'statement 'c-lineup-runin-statements)
00377  *   eval: (setq indent-tabs-mode nil)
00378  *   End:
00379  * ------------------------------------------------------------
00380  */

copyright (c) 2006 Graz University of Technology