Welcome to mirror list, hosted at ThFree Co, Russian Federation.

bindings.cpp « pytrack_generator « track_generator - github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: d256942d62cc61ddd55e173352c6f8a826c3c47b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#include "routing/route.hpp"
#include "routing/routing_callbacks.hpp"
#include "routing/routing_quality/utils.hpp"

#include "platform/platform.hpp"

#include "geometry/latlon.hpp"

#include <exception>
#include <sstream>
#include <string>
#include <vector>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wreorder"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-local-typedef"
#endif

#include "pyhelpers/module_version.hpp"
#include "pyhelpers/vector_list_conversion.hpp"

#include <boost/python.hpp>
#include <boost/python/exception_translator.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>

using namespace std;

namespace
{
class RouteNotFoundException : public exception
{
public:
  RouteNotFoundException(string const & msg) : m_msg(msg) {}

  virtual ~RouteNotFoundException() noexcept = default;

  char const * what() const noexcept override { return m_msg.c_str(); }

private:
  string m_msg;
};

PyObject * kRouteNotFoundException = nullptr;

PyObject * CreateExceptionClass(char const * name)
{
  using namespace boost::python;
  string const scopeName = extract<string>(scope().attr("__name__"));
  string const qualifiedName = scopeName + "." + name;
  PyObject * ex = PyErr_NewException(qualifiedName.c_str(), PyExc_Exception, nullptr);
  CHECK(ex, ());
  scope().attr(name) = handle<>(borrowed(ex));
  return ex;
}

template <typename Exception>
void Translate(PyObject * object, Exception const & e)
{
  PyErr_SetString(object, e.what());
}

struct Params
{
  Params(string const & data, string const & userResources) : m_dataPath(data), m_userResourcesPath(userResources)
  {
    if (m_dataPath.empty())
      throw runtime_error("data_path parameter not specified");

    if (m_userResourcesPath.empty())
      throw runtime_error("user_resources_path parameter not specified");
  }

  string DebugPrint() const
  {
    ostringstream ss;
    ss << "Params(data path: " << m_dataPath << ", user resources path: " << m_userResourcesPath << ")";
    return ss.str();
  }

  string m_dataPath;
  string m_userResourcesPath;
};

using Track = vector<ms::LatLon>;

Track GetTrackFrom(routing::Route const & route)
{
  CHECK(route.IsValid(), ());
  auto const & segments = route.GetRouteSegments();
  Track res;
  res.reserve(segments.size());
  for (auto const & s : segments)
    res.emplace_back(MercatorBounds::ToLatLon(s.GetJunction().GetPoint()));

  return res;
}

struct Generator
{
  explicit Generator(Params const & params) : m_params(params)
  {
    Platform & pl = GetPlatform();
    pl.SetWritableDirForTests(m_params.m_dataPath);
    pl.SetResourceDir(m_params.m_userResourcesPath);
  }

  Track Generate(boost::python::object const & iterable) const
  {
    using namespace routing_quality;

    Track const coordinates = python_list_to_std_vector<ms::LatLon>(iterable);
    auto result = GetRoute(FromLatLon(coordinates), routing::VehicleType::Pedestrian);
    if (result.m_code != routing::RouterResultCode::NoError)
      throw RouteNotFoundException("Can't build route");

    return GetTrackFrom(result.m_route);
  }

  Params m_params;
};
}  // namespace

using namespace boost::python;

BOOST_PYTHON_MODULE(pytrack_generator)
{
  scope().attr("__version__") = PYBINDINGS_VERSION;
  register_exception_translator<runtime_error>([](auto const & e) { Translate(PyExc_RuntimeError, e); });

  kRouteNotFoundException = CreateExceptionClass("RouteNotFoundException");
  register_exception_translator<RouteNotFoundException>([](auto const & e) { Translate(kRouteNotFoundException, e); });

  class_<Params>("Params", init<string, string>())
      .def("__str__", &Params::DebugPrint)
      .def_readonly("data_path", &Params::m_dataPath)
      .def_readonly("user_resources_path", &Params::m_userResourcesPath);

  class_<ms::LatLon>("LatLon", init<double, double>())
      .def("__str__", &ms::DebugPrint)
      .def_readonly("lat", &ms::LatLon::lat)
      .def_readonly("lon", &ms::LatLon::lon);

  class_<vector<ms::LatLon>>("LatLonList")
      .def(vector_indexing_suite<vector<ms::LatLon>>());

  class_<Generator>("Generator", init<Params>())
      .def("generate", &Generator::Generate)
      .def_readonly("params", &Generator::m_params);
}