path_xy.cpp 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. /*
  2. * path_xy.cpp - get path's y at given x
  3. * Copyright (C) 2016-2017 caryoscelus
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <algorithm>
  19. #include <fmt/format.h>
  20. #include <fmt/ostream.h>
  21. #include <core/all_types.h>
  22. #include <core/node_info.h>
  23. #include <core/node/proxy_node.h>
  24. #include <core/node/property.h>
  25. #include <core/time/format.h>
  26. #include <core/context.h>
  27. #include <geom_helpers/knots.h>
  28. namespace rainynite::core {
  29. namespace nodes {
  30. class PathXY : public Node<double> {
  31. public:
  32. PathXY() {
  33. init<Geom::BezierKnots>(path, {});
  34. init<double>(x, 0);
  35. }
  36. public:
  37. double get(shared_ptr<Context> ctx) const override {
  38. auto path = Geom::knots_to_path(get_path()->get(ctx));
  39. auto x = std::max(
  40. path.initialPoint().x(),
  41. std::min(
  42. path.finalPoint().x(),
  43. get_x()->get(ctx)
  44. )
  45. );
  46. auto path_roots = path.roots(x, Geom::X);
  47. // since x is in range between initial and final point, we should always get a root
  48. if (path_roots.size() < 1) {
  49. throw std::runtime_error("TimeCurve: no roots found at time: {}"_format(ctx->get_time()));
  50. return 0;
  51. }
  52. // enable this when upstream issue is resolved
  53. // https://github.com/inkscape/lib2geom/issues/14
  54. // if (path_roots.size() > 1)
  55. // throw std::runtime_error("TimeCurve: too much roots found at time: {}"_format(t));
  56. auto path_t = path_roots[0];
  57. return path.valueAt(path_t, Geom::Y);
  58. }
  59. private:
  60. NODE_PROPERTY(path, Geom::BezierKnots);
  61. NODE_PROPERTY(x, double);
  62. };
  63. REGISTER_NODE(PathXY);
  64. } // namespace nodes
  65. } // namespace rainynite::core