//////////////////////////////////////////////////////////////////////////////// // // Paella // Copyright (C) 2015 - Thomas FORGIONE, Emilie JALRAS, Marion LENFANT, Thierry MALON, Amandine PAILLOUX // Authors : // Thomas FORGIONE // Emilie JALRAS // Marion LENFANT // Thierry MALON // Amandine PAILLOUX // // This file is part of the project Paella // This software is provided 'as-is', without any express or implied warranty. // In no event will the authors be held liable for any damages arising from the use of this software. // // Permission is granted to anyone to use this software for any purpose, // including commercial applications, and to alter it and redistribute it freely, // subject to the following restrictions: // // 1. The origin of this software must not be misrepresented; // you must not claim that you wrote the original software. // If you use this software in a product, an acknowledgment // in the product documentation would be appreciated but is not required. // // 2. Altered source versions must be plainly marked as such, // and must not be misrepresented as being the original software. // // 3. This notice may not be removed or altered from any source distribution. //////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include namespace pae { std::pair>, geo::Vector3> click(Skeleton3D const& skel) { // Initialization of the window where clicks have to be done sf::RenderWindow window{sf::VideoMode{800,600},"Click on the rotation points"}; std::vector> ret{}; std::vector> skelToDraw{}; std::vector> splines; std::vector> pointsIndexes{}; for (auto const& spline : skel.splines) { auto pt1 = std::get<0>(spline(0)); auto pt2 = std::get<0>(spline(1)); skelToDraw.push_back({sf::Vertex(sf::Vector2f(pt1.x(), -pt1.y()), sf::Color::Red), sf::Vertex(sf::Vector2f(pt2.x(), -pt2.y()), sf::Color::Red)}); splines.push_back({}); skelToDraw[skelToDraw.size()-1].push_back({}); pointsIndexes.push_back({0,202}); splines[splines.size()-1].push_back(sf::Vertex(sf::Vector2f(pt1.x(), -pt1.y()))); for (float t = 0; t <1; t+=0.01) { auto v = std::get<0>(spline(t)); splines[splines.size()-1].push_back(sf::Vertex(sf::Vector2f(v.x(),-v.y()))); splines[splines.size()-1].push_back(sf::Vertex(sf::Vector2f(v.x(),-v.y()))); } } // Compute the 2D bounding box of the skeleton float xmin, xmax, ymin, ymax; xmin = std::numeric_limits::max(); xmax = std::numeric_limits::min(); ymin = std::numeric_limits::max(); ymax = std::numeric_limits::min(); for (unsigned int i = 0; i < splines.size(); i++) { for (unsigned int j = 0; j < splines[i].size(); j++) { xmin = std::min(xmin, splines[i][j].position.x); ymin = std::min(ymin, splines[i][j].position.y); xmax = std::max(xmax, splines[i][j].position.x); ymax = std::max(ymax, splines[i][j].position.y); } } auto horizontalSize = xmax - xmin; auto verticalSize = ymax - ymin; xmin -= horizontalSize/10; xmax += horizontalSize/10; ymin -= verticalSize/10; ymax += verticalSize/10; // Setting the view sf::View view; view.setSize(xmax-xmin, ymax-ymin); view.setCenter(0.5*(xmin+xmax),0.5*(ymin+ymax)); window.setView(view); bool captureRequired = false; bool running = true; sf::Vector2f lastClick; while (running) { sf::Event event; while (window.pollEvent(event)) { // End the program when the window is closed if (event.type == sf::Event::Closed) { running = false; window.close(); } else if (event.type == sf::Event::KeyPressed) { if (event.key.code == sf::Keyboard::P) { captureRequired = true; } } else if (event.type == sf::Event::MouseButtonReleased) { if (event.mouseButton.button == sf::Mouse::Left) { auto ptx = event.mouseButton.x; auto pty = event.mouseButton.y; auto clicks = window.mapPixelToCoords(sf::Vector2i(ptx,pty)); float bestDistance = std::numeric_limits::max(); unsigned int bestSpline; unsigned int bestPoint; for (unsigned int i = 0; i < splines.size(); i++) { for (unsigned int j = 0; j < splines[i].size(); j++) { float currentDistance = sft::norm2(clicks - splines[i][j].position); if (currentDistance < bestDistance) { bestDistance = currentDistance; bestSpline = i; bestPoint = j; } } } if (std::find(pointsIndexes[bestSpline].begin(), pointsIndexes[bestSpline].end(), bestPoint) == pointsIndexes[bestSpline].end()) { unsigned int k = 0; while (k < pointsIndexes[bestSpline].size() && bestPoint > pointsIndexes[bestSpline][k]) { k++; } pointsIndexes[bestSpline].insert(pointsIndexes[bestSpline].begin()+k, bestPoint); skelToDraw[bestSpline].insert(skelToDraw[bestSpline].begin()+2*k-1,splines[bestSpline][bestPoint].position); skelToDraw[bestSpline].insert(skelToDraw[bestSpline].begin()+2*k,splines[bestSpline][bestPoint].position); skelToDraw[bestSpline][2*k-1].color = sf::Color::Red; skelToDraw[bestSpline][2*k].color = sf::Color::Red; } } else if (event.mouseButton.button == sf::Mouse::Right) { lastClick = window.mapPixelToCoords(sf::Vector2i(event.mouseButton.x,event.mouseButton.y)); running = false; } } } window.clear(sf::Color::Black); for (unsigned int i = 0; i < splines.size(); i++) { window.draw(&splines[i][0], splines[i].size(), sf::Lines); } for (unsigned int i = 0; i < skelToDraw.size(); i++) { window.draw(&skelToDraw[i][0], skelToDraw[i].size(), sf::Lines); } if (captureRequired) { sf::Vector2u windowSize = window.getSize(); sf::Texture texture; texture.create(windowSize.x, windowSize.y); texture.update(window); sf::Image screenshot = texture.copyToImage(); screenshot.saveToFile("capture.jpg"); captureRequired = false; } window.display(); } std::cout << "Done" << std::endl; for (unsigned int i = 0; i < splines.size(); i++) { for (unsigned int j = 0; j < skelToDraw[i].size()-1; j+=2) { ret.push_back({geo::Vector3{skelToDraw[i][j].position.x, -skelToDraw[i][j].position.y, 0}, geo::Vector3{skelToDraw[i][j+1].position.x, -skelToDraw[i][j+1].position.y, 0}}); } } geo::Vector3 mainPatella{0,0,0}; geo::Vector3 clickCoordinates{lastClick.x,-lastClick.y,0}; float bestDistance = std::numeric_limits::max(); // Searching of the main patella point for (auto const& elt : ret) { float currentDistance = (lastClick.x-elt.first.x())*(lastClick.x-elt.first.x()) + (-lastClick.y-elt.first.y())*(-lastClick.y-elt.first.y()); if (currentDistance < bestDistance) { mainPatella = elt.first; bestDistance = currentDistance; } currentDistance = (lastClick.x-elt.second.x())*(lastClick.x-elt.second.x()) + (-lastClick.y-elt.second.y())*(-lastClick.y-elt.second.y()); if (currentDistance < bestDistance) { mainPatella = elt.second; bestDistance = currentDistance; } } return std::make_pair(ret, mainPatella); } geo::Tree>& listToTree(std::list>& list, geo::Tree>& tree) { constexpr float eps = 0.00001; for (auto it = std::begin(list), end = std::end(list); it != end;) { if ((it->first - tree.node).norm2() < eps) { tree.children.push_back(geo::Tree>{it->second}); it = list.erase(it); continue; } else if ((it->second - tree.node).norm2() < eps) { tree.children.push_back(geo::Tree>{it->first}); it = list.erase(it); continue; } ++it; } for (auto& child : tree.children) { listToTree(list, child); } return tree; } geo::Tree>& listToTree(std::vector> const& vector, geo::Tree>& tree) { std::list> list; std::copy(std::begin(vector), std::end(vector), std::back_inserter(list)); return listToTree(list, tree); } }