bool Calibrator::finish(int width, int height) { if (get_numclicks() != NUM_POINTS) { return false; } // new axis origin and scaling // based on old_axys: inversion/swapping is relative to the old axis XYinfo new_axis(old_axys); // calculate average of clicks float x_min = (clicked.x[UL] + clicked.x[LL])/2.0; float x_max = (clicked.x[UR] + clicked.x[LR])/2.0; float y_min = (clicked.y[UL] + clicked.y[UR])/2.0; float y_max = (clicked.y[LL] + clicked.y[LR])/2.0; // Should x and y be swapped? if (abs(clicked.x[UL] - clicked.x[UR]) < abs(clicked.y[UL] - clicked.y[UR])) { new_axis.swap_xy = !new_axis.swap_xy; std::swap(x_min, y_min); std::swap(x_max, y_max); } // the screen was divided in num_blocks blocks, and the touch points were at // one block away from the true edges of the screen. const float block_x = width/(float)num_blocks; const float block_y = height/(float)num_blocks; // rescale these blocks from the range of the drawn touchpoints to the range of the // actually clicked coordinates, and substract/add from the clicked coordinates // to obtain the coordinates corresponding to the edges of the screen. float scale_x = (x_max - x_min)/(width - 2*block_x); x_min -= block_x * scale_x; x_max += block_x * scale_x; float scale_y = (y_max - y_min)/(height - 2*block_y); y_min -= block_y * scale_y; y_max += block_y * scale_y; // now, undo the transformations done by the X server, to obtain the true 'raw' value in X. // The raw value was scaled from old_axis to the device min/max, and from the device min/max // to the screen min/max // hence, the reverse transformation is from screen to old_axis x_min = scaleAxis(x_min, old_axys.x.max, old_axys.x.min, width, 0); x_max = scaleAxis(x_max, old_axys.x.max, old_axys.x.min, width, 0); y_min = scaleAxis(y_min, old_axys.y.max, old_axys.y.min, height, 0); y_max = scaleAxis(y_max, old_axys.y.max, old_axys.y.min, height, 0); // round and put in new_axis struct new_axis.x.min = round(x_min); new_axis.x.max = round(x_max); new_axis.y.min = round(y_min); new_axis.y.max = round(y_max); if (output_type == OUTYPE_CALIBRATOR) { output_restore_file(width, height); } // finish the data, driver/calibrator specific return finish_data(new_axis); }
bool Calibrator::finish() { int width; int height; if (get_numclicks() != 4) { return false; } width = abs(old_axys.x_max - old_axys.x_min) + 1; height = abs(old_axys.y_max - old_axys.y_min) + 1; // Should x and y be swapped? const bool swap_xy = (abs (clicked_x [UL] - clicked_x [UR]) < abs (clicked_y [UL] - clicked_y [UR])); if (swap_xy) { std::swap(clicked_x[LL], clicked_x[UR]); std::swap(clicked_y[LL], clicked_y[UR]); } // Compute min/max coordinates. XYinfo axys; // These are scaled using the values of old_axys const float scale_x = (old_axys.x_max - old_axys.x_min)/(float)width; axys.x_min = ((clicked_x[UL] + clicked_x[LL]) * scale_x/2) + old_axys.x_min; axys.x_max = ((clicked_x[UR] + clicked_x[LR]) * scale_x/2) + old_axys.x_min; const float scale_y = (old_axys.y_max - old_axys.y_min)/(float)height; axys.y_min = ((clicked_y[UL] + clicked_y[UR]) * scale_y/2) + old_axys.y_min; axys.y_max = ((clicked_y[LL] + clicked_y[LR]) * scale_y/2) + old_axys.y_min; // Add/subtract the offset that comes from not having the points in the // corners (using the same coordinate system they are currently in) const int delta_x = (axys.x_max - axys.x_min) / (float)(num_blocks - 2); axys.x_min -= delta_x; axys.x_max += delta_x; const int delta_y = (axys.y_max - axys.y_min) / (float)(num_blocks - 2); axys.y_min -= delta_y; axys.y_max += delta_y; // If x and y has to be swapped we also have to swap the parameters if (swap_xy) { std::swap(axys.x_min, axys.y_max); std::swap(axys.y_min, axys.x_max); } // finish the data, driver/calibrator specific return finish_data(axys, swap_xy); }
// From Calibrator but with evdev specific invertion option // KEEP IN SYNC with Calibrator::finish() !! bool CalibratorEvdev::finish(int width, int height) { if (get_numclicks() != NUM_POINTS) { return false; } // new axis origin and scaling // based on old_axys: inversion/swapping is relative to the old axis XYinfo new_axis(old_axys); // calculate average of clicks float x_min = (clicked.x[UL] + clicked.x[LL])/2.0; float x_max = (clicked.x[UR] + clicked.x[LR])/2.0; float y_min = (clicked.y[UL] + clicked.y[UR])/2.0; float y_max = (clicked.y[LL] + clicked.y[LR])/2.0; // When evdev detects an invert_X/Y option, // it performs the following *crazy* code just before returning // val = (pEvdev->absinfo[i].maximum - val + pEvdev->absinfo[i].minimum); // undo this crazy step before doing the regular calibration routine if (old_axys.x.invert) { x_min = width - x_min; x_max = width - x_max; // avoid invert_x property from here on, // the calibration code can handle this dynamically! new_axis.x.invert = false; } if (old_axys.y.invert) { y_min = height - y_min; y_max = height - y_max; // avoid invert_y property from here on, // the calibration code can handle this dynamically! new_axis.y.invert = false; } // end of evdev inversion crazyness // Should x and y be swapped? if (abs(clicked.x[UL] - clicked.x[UR]) < abs(clicked.y[UL] - clicked.y[UR])) { new_axis.swap_xy = !new_axis.swap_xy; std::swap(x_min, y_min); std::swap(x_max, y_max); } // the screen was divided in num_blocks blocks, and the touch points were at // one block away from the true edges of the screen. const float block_x = width/(float)num_blocks; const float block_y = height/(float)num_blocks; // rescale these blocks from the range of the drawn touchpoints to the range of the // actually clicked coordinates, and substract/add from the clicked coordinates // to obtain the coordinates corresponding to the edges of the screen. float scale_x = (x_max - x_min)/(width - 2*block_x); x_min -= block_x * scale_x; x_max += block_x * scale_x; float scale_y = (y_max - y_min)/(height - 2*block_y); y_min -= block_y * scale_y; y_max += block_y * scale_y; // now, undo the transformations done by the X server, to obtain the true 'raw' value in X. // The raw value was scaled from old_axis to the device min/max, and from the device min/max // to the screen min/max // hence, the reverse transformation is from screen to old_axis x_min = scaleAxis(x_min, old_axys.x.max, old_axys.x.min, width, 0); x_max = scaleAxis(x_max, old_axys.x.max, old_axys.x.min, width, 0); y_min = scaleAxis(y_min, old_axys.y.max, old_axys.y.min, height, 0); y_max = scaleAxis(y_max, old_axys.y.max, old_axys.y.min, height, 0); // round and put in new_axis struct new_axis.x.min = round(x_min); new_axis.x.max = round(x_max); new_axis.y.min = round(y_min); new_axis.y.max = round(y_max); // finish the data, driver/calibrator specific return finish_data(new_axis); }