circle_tangent.cpp

#include "Geometry.cpp"

template <typename real_t>
std::vector<Line<real_t>> tangent_cp(const Circle<real_t> &c,
                                     const Point<real_t> &p) {
  std::vector<Line<real_t>> res;
  Vector<real_t> v = c.p - p;
  real_t d = abs(v), len = sqrt(norm(v) - c.r * c.r);
  if (isnan(len)) {
    return res;
  }
  const auto v1 = v * Vector<real_t>(len / d, c.r / d);
  const auto v2 = v * Vector<real_t>(len / d, -c.r / d);
  res.emplace_back(p, p + v1);
  if (len <= 0) return res;
  res.emplace_back(p, p + v2);
  return res;
}

template <typename real_t>
std::vector<Line<real_t>> tangent_cc(const Circle<real_t> &c1,
                                     const Circle<real_t> &c2) {
  std::vector<Line<real_t>> res;
  if (abs(c1.p - c2.p) - (c1.r + c2.r) >= 0) {
    Point<real_t> center = average(c1.p, c2.p, c2.r, c1.r);
    res = tangent_cp(c1, center);
  }
  if (c1.r - c2.r != 0) {
    const Point<real_t> out = average(c1.p, c2.p, -c2.r, c1.r);
    const std::vector<Line<real_t>> nres = tangent_cp(c1, out);
    res.insert(res.end(), begin(nres), end(nres));
  }
  else {
    Vector<real_t> v = c2.p - c1.p;
    v /= abs(v);
    Point<real_t> q1 = c1.p + v * Vector<real_t>(0, 1) * c1.r;
    Point<real_t> q2 = c1.p + v * Vector<real_t>(0, -1) * c1.r;
    res.emplace_back(q1, q1 + v);
    res.emplace_back(q2, q2 + v);
  }
  return res;
}

Includes

Back