/* **************************************************************************** * Copyright (c) 2014 Uriah Liggett * * This file is part of FreeLSS. * * * * FreeLSS is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * FreeLSS is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with FreeLSS. If not, see . * **************************************************************************** */ #include "Main.h" #include "WebContent.h" #include "PresetManager.h" #include "Setup.h" #include "Laser.h" #include "Camera.h" namespace freelss { const std::string WebContent::CSS = "\ "; const std::string WebContent::JAVASCRIPT= "\ "; const std::string WebContent::PROFILE_NAME = "PROFILE_NAME"; const std::string WebContent::CAMERA_X = "CAMERA_X"; const std::string WebContent::CAMERA_Y = "CAMERA_Y"; const std::string WebContent::CAMERA_Z = "CAMERA_Z"; const std::string WebContent::CAMERA_MODE = "CAMERA_MODE"; const std::string WebContent::RIGHT_LASER_X = "RIGHT_LASER_X"; const std::string WebContent::RIGHT_LASER_Y = "RIGHT_LASER_Y"; const std::string WebContent::RIGHT_LASER_Z = "RIGHT_LASER_Z"; const std::string WebContent::RIGHT_LASER_PIN = "RIGHT_LASER_PIN"; const std::string WebContent::LEFT_LASER_X = "LEFT_LASER_X"; const std::string WebContent::LEFT_LASER_Y = "LEFT_LASER_Y"; const std::string WebContent::LEFT_LASER_Z = "LEFT_LASER_Z"; const std::string WebContent::LEFT_LASER_PIN = "LEFT_LASER_PIN"; const std::string WebContent::LASER_MAGNITUDE_THRESHOLD = "LASER_MAGNITUDE_THRESHOLD"; const std::string WebContent::LASER_DELAY = "LASER_DELAY"; const std::string WebContent::LASER_ON_VALUE = "LASER_ON_VALUE"; const std::string WebContent::LASER_SELECTION = "LASER_SELECTION"; const std::string WebContent::STABILITY_DELAY = "STABILITY_DELAY"; const std::string WebContent::MAX_LASER_WIDTH = "MAX_LASER_WIDTH"; const std::string WebContent::MIN_LASER_WIDTH = "MIN_LASER_WIDTH"; const std::string WebContent::STEPS_PER_REVOLUTION = "STEPS_PER_REVOLUTION"; const std::string WebContent::ENABLE_PIN = "ENABLE_PIN"; const std::string WebContent::STEP_PIN = "STEP_PIN"; const std::string WebContent::DIRECTION_PIN = "DIRECTION_PIN"; const std::string WebContent::DIRECTION_VALUE = "DIRECTION_VALUE"; const std::string WebContent::RESPONSE_DELAY = "RESPONSE_DELAY"; const std::string WebContent::STEP_DELAY = "STEP_DELAY"; const std::string WebContent::FRAMES_PER_REVOLUTION = "FRAMES_PER_REVOLUTION"; const std::string WebContent::GENERATE_XYZ = "GENERATE_XYZ"; const std::string WebContent::GENERATE_STL = "GENERATE_STL"; const std::string WebContent::GENERATE_PLY = "GENERATE_PLY"; const std::string WebContent::SEPARATE_LASERS_BY_COLOR = "SEPARATE_LASERS_BY_COLOR"; const std::string WebContent::CAMERA_X_DESCR = "X-compoment of camera location. ie: The camera is always at X = 0."; const std::string WebContent::CAMERA_Y_DESCR = "Y-component of camera location. ie: The distance from camera center to the XZ plane"; const std::string WebContent::CAMERA_Z_DESCR = "Z-component of camera location. ie: The distance from camera center to origin"; const std::string WebContent::RIGHT_LASER_X_DESCR = "X coordinate of the right laser. This is how far the laser is from the camera."; const std::string WebContent::RIGHT_LASER_Y_DESCR = "Y coordinate of the right laser"; const std::string WebContent::RIGHT_LASER_Z_DESCR = "Z coordinate of the right laser. The laser is parallel with the camera focal point"; const std::string WebContent::LEFT_LASER_X_DESCR = "X coordinate of the right laser. This is how far the laser is from the camera."; const std::string WebContent::LEFT_LASER_Y_DESCR = "Y coordinate of the right laser"; const std::string WebContent::LEFT_LASER_Z_DESCR = "Z coordinate of the right laser. The laser is parallel with the camera focal point"; const std::string WebContent::LASER_MAGNITUDE_THRESHOLD_DESCR = "How bright the difference between a laser on and laser off pixel must be in order to be detected as part of the laser"; const std::string WebContent::LASER_DELAY_DESCR = "The time to delay after turning the laser on or off"; const std::string WebContent::RIGHT_LASER_PIN_DESCR = "The wiringPi pin number for controlling the right laser"; const std::string WebContent::LEFT_LASER_PIN_DESCR = "The wiringPi pin number for controlling the left laser"; const std::string WebContent::LASER_ON_VALUE_DESCR = "Set to 1 if setting the laser pin HIGH turns if on and 0 if LOW turns it on"; const std::string WebContent::STABILITY_DELAY_DESCR = "The time in microseconds to delay after moving the turntable and before taking a picture"; const std::string WebContent::MAX_LASER_WIDTH_DESCR = "Maximum laser width in pixels"; const std::string WebContent::MIN_LASER_WIDTH_DESCR = "Minimum laser width in pixels"; const std::string WebContent::STEPS_PER_REVOLUTION_DESCR = "The number of motor steps before the turntable spins 360 degrees"; const std::string WebContent::ENABLE_PIN_DESCR = "The wiringPi pin number for enabling the stepper motor"; const std::string WebContent::STEP_PIN_DESCR = "The wiringPi pin number for stepping the stepper motor"; const std::string WebContent::STEP_DELAY_DESCR = "The amount of time between steps in microseconds"; const std::string WebContent::DIRECTION_PIN_DESCR = "The wiringPi pin number for the stepper motor direction or rotation"; const std::string WebContent::RESPONSE_DELAY_DESCR = "The time it takes for the stepper controller to recognize a pin value change in microseconds"; const std::string WebContent::FRAMES_PER_REVOLUTION_DESCR = "The number of frames that should be taken for a scan. Default is 800."; const std::string WebContent::GENERATE_XYZ_DESCR = "Whether to generate an XYZ point cloud file from the scan."; const std::string WebContent::GENERATE_STL_DESCR = "Whether to generate an STL mesh from the scan."; const std::string WebContent::GENERATE_PLY_DESCR = "Whether to generate a PLY point clould from the scan."; const std::string WebContent::SEPARATE_LASERS_BY_COLOR_DESCR = "Calibration debugging option to separate the results from different lasers by color (requires PLY)."; std::string WebContent::scan(const std::vector& pastScans) { std::stringstream sstr; sstr << "" << CSS << std::endl << JAVASCRIPT << std::endl << "" << "\ \ \

Click the button to start the scan

\
\
Degrees
degrees
\ \ \
"; for (size_t iRt = 0; iRt < pastScans.size(); iRt++) { sstr << WebContent::scanResult(iRt + 1, pastScans[iRt]); } sstr << ""; return sstr.str(); } std::string WebContent::scanResult(size_t index, const ScanResult& result) { std::stringstream sstr; time_t scanDate = result.getScanDate(); struct tm * tp = localtime (&scanDate); std::string dateStr = asctime(tp); std::stringstream deleteUrl; std::stringstream thumbnail; thumbnail << "/dl/" << result.getScanDate() << ".png"; deleteUrl << "/del?id=" << result.getScanDate(); sstr << "" << index << "\
\
\ \
"; const std::vector& files = result.files; for (size_t iFil = 0; iFil < files.size(); iFil++) { const ScanResultFile& file = files[iFil]; if (file.extension != "png") { std::string upperExtension = file.extension; std::transform(upperExtension.begin(), upperExtension.end(), upperExtension.begin(), toupper); // Format the file size std::stringstream fileSize; if (file.fileSize > 1024 * 1024) { fileSize << file.fileSize / (1024 * 1024) << " MB"; } else if (file.fileSize > 1024) { fileSize << file.fileSize / 1024 << " KB"; } else { fileSize << file.fileSize << " B"; } sstr << " " << upperExtension << " [" << fileSize.str() << "]"; } } sstr << "

\
\ \
\
" << dateStr << "\
\
\
"; return sstr.str(); } std::string WebContent::scanRunning(real progress, real remainingTime) { std::stringstream sstr; sstr << "" << "" << CSS << std::endl << JAVASCRIPT << std::endl << "" << "

Scan is " << progress << "% complete with " << (remainingTime / 60.0) << " minutes remaining.

" << "
" << "" << "" << "
" << ""; return sstr.str(); } std::string WebContent::cal1(const std::string& inMessage) { std::string message = inMessage.empty() ? std::string("") : ("

" + inMessage + "

"); std::stringstream sstr; sstr << "" << CSS << std::endl << JAVASCRIPT << std::endl << "" << "\ \ " << message << "\
\
\
\
\ \ \
\
\
\
\
\
\
\ \ \ \
\
\
Rotates the turntable in degrees.
\
\
\
\ \
\
\
\
\
\
\
"; return sstr.str(); } std::string WebContent::setup(const std::string& message) { const Setup * setup = Setup::get(); std::stringstream sstr; sstr << "" << CSS << std::endl << JAVASCRIPT << std::endl << "" << "\ \ "; if (!message.empty()) { sstr << "

" << message << "

"; } sstr << "
"; sstr << "

"; sstr << setting(WebContent::CAMERA_X, "Camera X", setup->cameraLocation.x / 25.4f, CAMERA_X_DESCR, "in.", true); sstr << setting(WebContent::CAMERA_Y, "Camera Y", setup->cameraLocation.y / 25.4f, CAMERA_Y_DESCR, "in."); sstr << setting(WebContent::CAMERA_Z, "Camera Z", setup->cameraLocation.z / 25.4f, CAMERA_Z_DESCR, "in."); sstr << setting(WebContent::RIGHT_LASER_X, "Right Laser X", setup->rightLaserLocation.x / 25.4f, RIGHT_LASER_X_DESCR, "in."); sstr << setting(WebContent::RIGHT_LASER_Y, "Right Laser Y", setup->rightLaserLocation.y / 25.4f, RIGHT_LASER_Y_DESCR, "in.", true); sstr << setting(WebContent::RIGHT_LASER_Z, "Right Laser Z", setup->rightLaserLocation.z / 25.4f, RIGHT_LASER_Z_DESCR, "in.", true); sstr << setting(WebContent::LEFT_LASER_X, "Left Laser X", setup->leftLaserLocation.x / 25.4f, LEFT_LASER_X_DESCR, "in."); sstr << setting(WebContent::LEFT_LASER_Y, "Left Laser Y", setup->leftLaserLocation.y / 25.4f, LEFT_LASER_Y_DESCR, "in.", true); sstr << setting(WebContent::LEFT_LASER_Z, "Left Laser Z", setup->leftLaserLocation.z / 25.4f, LEFT_LASER_Z_DESCR, "in.", true); sstr << setting(WebContent::RIGHT_LASER_PIN, "Right Laser Pin", setup->rightLaserPin, RIGHT_LASER_PIN_DESCR); sstr << setting(WebContent::LEFT_LASER_PIN, "Left Laser Pin", setup->leftLaserPin, LEFT_LASER_PIN_DESCR); sstr << setting(WebContent::LASER_ON_VALUE, "Laser On Value", setup->laserOnValue, LASER_ON_VALUE_DESCR); sstr << setting(WebContent::STEPS_PER_REVOLUTION, "Steps Per Revolution", setup->stepsPerRevolution, STEPS_PER_REVOLUTION_DESCR); sstr << setting(WebContent::ENABLE_PIN, "Motor Enable Pin", setup->motorEnablePin, ENABLE_PIN_DESCR); sstr << setting(WebContent::STEP_PIN, "Motor Step Pin", setup->motorStepPin, STEP_PIN_DESCR); sstr << setting(WebContent::STEP_DELAY, "Motor Step Delay", setup->motorStepDelay, STEP_DELAY_DESCR, "μs"); sstr << setting(WebContent::DIRECTION_PIN, "Motor Direction Pin", setup->motorDirPin, DIRECTION_PIN_DESCR); sstr << setting(WebContent::RESPONSE_DELAY, "Motor Response Delay", setup->motorResponseDelay, RESPONSE_DELAY_DESCR, "μs"); sstr << "

\ \

\ "; return sstr.str(); } std::string WebContent::settings(const std::string& message) { const Preset& preset = PresetManager::get()->getActivePreset(); std::stringstream sstr; sstr << "" << CSS << std::endl << JAVASCRIPT << std::endl << "" << "\ \ "; if (!message.empty()) { sstr << "

" << message << "

"; } sstr << "
"; sstr << "\
\
Preset
\
\
\
"; const std::vector& profs = PresetManager::get()->getPresets(); for (size_t iProf = 0; iProf < profs.size(); iProf++) { const Preset& prof = profs[iProf]; sstr << "
" << "
" << (iProf + 1) << ".  " << prof.name << "
" << "
"; } sstr << "
"; // // Laser selection UI // Laser::LaserSide laserSel = preset.laserSide; std::string leftSel = laserSel == Laser::LEFT_LASER ? " SELECTED" : ""; std::string rightSel = laserSel == Laser::RIGHT_LASER ? " SELECTED" : ""; std::string bothSel = laserSel == Laser::ALL_LASERS ? " SELECTED" : ""; sstr << "
Laser Selection
"; sstr << "
"; sstr << "
The laser(s) that will be used when scanning.
\n"; // // Camera Mode UI // Camera::CameraMode cameraMode = preset.cameraMode; std::string still5Sel = cameraMode == Camera::CM_STILL_5MP ? " SELECTED" : ""; std::string video5Sel = cameraMode == Camera::CM_VIDEO_5MP ? " SELECTED" : ""; std::string videoHDSel = cameraMode == Camera::CM_VIDEO_HD ? " SELECTED" : ""; std::string video1P2Sel = cameraMode == Camera::CM_VIDEO_1P2MP ? " SELECTED" : ""; std::string videoVGASel = cameraMode == Camera::CM_VIDEO_VGA ? " SELECTED" : ""; sstr << "
Camera Mode
"; sstr << "
"; sstr << "
The camera mode to use. Video mode is faster but Still mode results in higher quality scans.
\n"; sstr << setting(WebContent::FRAMES_PER_REVOLUTION, "Frames Per Revolution", preset.framesPerRevolution, FRAMES_PER_REVOLUTION_DESCR); sstr << setting(WebContent::LASER_MAGNITUDE_THRESHOLD, "Laser Threshold", preset.laserThreshold, LASER_MAGNITUDE_THRESHOLD_DESCR); sstr << setting(WebContent::LASER_DELAY, "Laser Delay", preset.laserDelay, LASER_DELAY_DESCR, "μs"); sstr << setting(WebContent::STABILITY_DELAY, "Stability Delay", preset.stabilityDelay, STABILITY_DELAY_DESCR, "μs"); sstr << setting(WebContent::MAX_LASER_WIDTH, "Max Laser Width", preset.maxLaserWidth, MAX_LASER_WIDTH_DESCR, "px."); sstr << setting(WebContent::MIN_LASER_WIDTH, "Min Laser Width", preset.minLaserWidth, MIN_LASER_WIDTH_DESCR, "px."); sstr << checkbox(WebContent::GENERATE_PLY, "Generate PLY File", preset.generatePly, GENERATE_PLY_DESCR); sstr << checkbox(WebContent::GENERATE_STL, "Generate STL File", preset.generateStl, GENERATE_STL_DESCR); sstr << checkbox(WebContent::GENERATE_XYZ, "Generate XYZ File", preset.generateXyz, GENERATE_XYZ_DESCR); sstr << checkbox(WebContent::SEPARATE_LASERS_BY_COLOR, "Separate the Lasers", preset.laserMergeAction == Preset::LMA_SEPARATE_BY_COLOR, SEPARATE_LASERS_BY_COLOR_DESCR); sstr << "
\
\




\

\ "; return sstr.str(); } std::string WebContent::setting(const std::string& name, const std::string& label, const std::string& value, const std::string& description, const std::string& units, bool readOnly) { std::stringstream sstr; sstr << "
" << label << "
"; if (!units.empty()) { sstr << units; } sstr << "
" << description << "
\n"; return sstr.str(); } std::string WebContent::checkbox(const std::string& name, const std::string& label, bool checked, const std::string& description) { std::stringstream sstr; sstr << "
" << label << "
"; sstr << "
" << description << "
\n"; return sstr.str(); } std::string WebContent::setting(const std::string& name, const std::string& label, int value, const std::string& description, const std::string& units, bool readOnly) { std::stringstream sstr; sstr << value; return setting(name, label, sstr.str(), description, units, readOnly); } std::string WebContent::setting(const std::string& name, const std::string& label, real value, const std::string& description, const std::string& units, bool readOnly) { std::stringstream sstr; sstr << value; return setting(name, label, sstr.str(), description, units, readOnly); } }