48 static constexpr double MARGIN = 0.25;
57 const std::vector<std::size_t>& visible)
58 : x_(x), y_(y), visible_(visible) {
59 min_x_ = std::numeric_limits<double>::max();
60 max_x_ = std::numeric_limits<double>::denorm_min();
61 min_y_ = std::numeric_limits<double>::max();
62 max_y_ = std::numeric_limits<double>::denorm_min();
63 for (std::size_t v : visible_) {
73 std::vector<TikzPoint> wp;
74 if (from == to)
return wp;
75 const TikzPoint f{x_[from], y_[from]}, t{x_[to], y_[to]};
83 std::vector<std::size_t> obstacles;
84 for (std::size_t v : visible_) {
85 if (v == from || v == to)
continue;
86 if (line_intersects_node(f, t, v)) obstacles.push_back(v);
88 std::stable_sort(obstacles.begin(), obstacles.end(),
89 [&](std::size_t a, std::size_t b) { return x_[a] < x_[b]; });
90 if (obstacles.empty())
return wp;
91 return route_forward(f, t, obstacles);
96 std::vector<TikzPoint> wp;
98 const bool above = f.
y >= t.
y;
99 const int ch = backward_;
105 if (!above) dy = -dy;
106 const double target_y = t.
y + dy;
108 wp.push_back(TikzPoint{exit_x, route_y});
109 wp.push_back(TikzPoint{entry_x, route_y});
110 wp.push_back(TikzPoint{entry_x, target_y});
114 std::vector<TikzPoint> route_forward(
const TikzPoint& f,
const TikzPoint& t,
115 const std::vector<std::size_t>& obstacles)
const {
116 std::vector<TikzPoint> wp;
118 for (std::size_t v : obstacles) avg += y_[v];
119 avg /=
static_cast<double>(obstacles.size());
120 const double mid = (f.y + t.y) / 2.0;
121 const bool above = mid >= avg;
123 const double route_y = avg + offset;
124 double minx = std::numeric_limits<double>::max();
125 double maxx = std::numeric_limits<double>::denorm_min();
126 for (std::size_t v : obstacles) {
130 const double entry_x = std::max(f.x + 0.3, minx - 0.3);
131 wp.push_back(TikzPoint{entry_x, route_y});
132 const double exit_x = std::min(t.x - 0.3, maxx + 0.3);
133 if (exit_x > entry_x + 0.1) wp.push_back(TikzPoint{exit_x, route_y});
137 bool line_intersects_node(
const TikzPoint& s,
const TikzPoint& e, std::size_t v)
const {
139 const double left = x_[v] - hw, right = x_[v] + hw;
140 const double bottom = y_[v] - hh, top = y_[v] + hh;
141 const double x1 = s.x, y1 = s.y, x2 = e.x, y2 = e.y;
142 if ((x1 < left && x2 < left) || (x1 > right && x2 > right))
return false;
143 if ((y1 < bottom && y2 < bottom) || (y1 > top && y2 > top))
return false;
144 if (in_box(x1, y1, left, right, bottom, top) || in_box(x2, y2, left, right, bottom, top))
146 return seg(x1, y1, x2, y2, left, bottom, left, top) ||
147 seg(x1, y1, x2, y2, right, bottom, right, top) ||
148 seg(x1, y1, x2, y2, left, bottom, right, bottom) ||
149 seg(x1, y1, x2, y2, left, top, right, top);
152 static bool in_box(
double x,
double y,
double l,
double r,
double b,
double t) {
153 return x >= l && x <= r && y >= b && y <= t;
156 static bool seg(
double x1,
double y1,
double x2,
double y2,
double x3,
double y3,
double x4,
158 const double den = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
159 if (std::fabs(den) < 1e-10)
return false;
160 const double t = ((x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4)) / den;
161 const double u = -((x1 - x2) * (y1 - y3) - (y1 - y2) * (x1 - x3)) / den;
162 return t >= 0 && t <= 1 && u >= 0 && u <= 1;
165 const std::vector<double>& x_;
166 const std::vector<double>& y_;
167 std::vector<std::size_t> visible_;
168 double min_x_, max_x_, min_y_, max_y_;
std::string tikz_render_routed_edge(const std::string &from_id, const std::string &to_id, const std::string &from_anchor, const std::string &to_anchor, const std::vector< TikzPoint > &wp, double prob, const TikzOptions &opt)
TikZEdgeRouter.renderRoutedEdge.