Skip to content

Latest commit

ย 

History

History

convex-hull

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
ย 
ย 
ย 
ย 
ย 
ย 

Convex Hull

  • ์ถ”์ฒœ ๋ฌธ์ œ - Convex Hull



Convex Hull

  1. 2์ฐจ์› ํ‰๋ฉด ์ƒ์— ์ขŒํ‘œ x, y๊ฐ€ ์ฃผ์–ด์งˆ ๋•Œ, y ์ขŒํ‘œ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์˜ค๋ฆ„์ฐจ์ˆœ ์ •๋ ฌํ•˜๋˜, y ์ขŒํ‘œ๊ฐ€ ๋™์ผํ•˜๋‹ค๋ฉด x ์ขŒํ‘œ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์˜ค๋ฆ„์ฐจ์ˆœ ์ •๋ ฌํ•œ๋‹ค.
  2. ๊ธฐ์ค€ ์ขŒํ‘œ(๋ณดํ†ต 0 ๋ฒˆ์งธ index๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ •ํ•จ)๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋ฐ˜์‹œ๊ณ„ ๋ฐฉํ–ฅ์œผ๋กœ ์ •๋ ฌํ•œ๋‹ค:
  • CCW ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ–ˆ์„ ๋•Œ ์–‘์ˆ˜๋Š” ๋ฐ˜์‹œ๊ณ„ ๋ฐฉํ–ฅ, ์Œ์ˆ˜๋Š” ์‹œ๊ณ„ ๋ฐฉํ–ฅ์„ ๋‚˜ํƒ€๋ƒ„
  • ๋งŒ์•ฝ 0์ด ๋‚˜์˜จ๋‹ค๋ฉด, ๊ธฐ์ค€ ์ขŒํ‘œ๋กœ๋ถ€ํ„ฐ ๊ฐ€๊นŒ์šด ๊ฑฐ๋ฆฌ ์ˆœ์œผ๋กœ ์ •๋ ฌ
  1. Graham's Scan์„ ์‚ฌ์šฉํ•ด ์™ธ๊ณฝ ์ขŒํ‘œ๋ฅผ ์ฐพ๋Š”๋‹ค:

    graham-s-scan

์—ฐ์Šต๋ฌธ์ œ

#include <iostream>
#include <vector>
#include <utility>
#include <algorithm>

// iostream
using std::cin;
using std::cout;

// vector
using std::vector;

// utility
using std::pair;

// algorithm
using std::sort;

pair<int, int> starting_point;

bool CmpCoor(const pair<int, int>&,
             const pair<int, int>&);
bool CmpCcw(const pair<int, int>&,
            const pair<int, int>&);
int64_t CalcCcw(const pair<int, int>&,
                const pair<int, int>&,
                const pair<int, int>&);
int64_t CalcSqDist(const pair<int, int>&,
                   const pair<int, int>&);

int main() {
  int n;
  cin >> n;
  vector<pair<int, int>> v(n);
  for (int i = 0; i < n; ++i)
    cin >> v[i].first >> v[i].second;

  // find the point with the lowest y-coordinate. (v[0], starting_point)
  sort(v.begin(), v.end(), CmpCoor);
  starting_point = v.front();
  // the set of points must be sorted in increasing order of the angle they and
  // the point P make with the x-axis
  sort(v.begin() + 1, v.end(), CmpCcw);

  // Graham's scan
  vector<pair<int, int>> convex_hull;
  for (const auto& p : v) {
    while (convex_hull.size() >= 2) {
      if (CalcCcw(convex_hull[convex_hull.size()-2], convex_hull.back(), p) > 0)
        break;
      convex_hull.pop_back();
    }
    convex_hull.push_back(p);
  }
  cout << convex_hull.size();

  return 0;
}

bool CmpCoor(const pair<int, int>& s,
             const pair<int, int>& t) {
  if (s.second < t.second)
    return true;

  if (s.second == t.second && s.first < t.first)
    return true;

  return false;
}

bool CmpCcw(const pair<int, int>& s,
            const pair<int, int>& t) {
  int64_t res = CalcCcw(starting_point, s, t);

  if (res)
    return res > 0;  // ccw : true, cw : false

  // res = 0
  int64_t dist1 = CalcSqDist(s, starting_point);
  int64_t dist2 = CalcSqDist(t, starting_point);

  return dist1 < dist2;
}

// ccw         : pos.
// on the line : 0
// cw          : neg.
int64_t CalcCcw(const pair<int, int>& a,
                const pair<int, int>& b,
                const pair<int, int>& c) {
  int64_t u1 = b.first - a.first;
  int64_t v1 = b.second - a.second;
  int64_t u2 = c.first - a.first;
  int64_t v2 = c.second - a.second;

  return u1 * v2 - u2 * v1;
}

int64_t CalcSqDist(const pair<int, int>& s,
                   const pair<int, int>& t) {
  int64_t diff_x = s.first - t.first;
  int64_t diff_y = s.second - t.second;

  return diff_x * diff_x + diff_y * diff_y;
}

Rotating Calipers

  1. ์ปจ๋ฒก์Šค ํ—์„ ํ†ตํ•ด ์™ธ๊ฐ ์ ๋“ค์„ ๊ตฌํ•œ๋‹ค.
  2. x์ถ•์„ ๊ธฐ์ค€์œผ๋กœ ๊ฐ€์žฅ ์™ผํŽธ์— ์œ„์น˜ํ•˜๋Š” ์ ๊ณผ ๊ฐ€์žฅ ์˜ค๋ฅธํŽธ์— ์œ„์น˜ํ•˜๋Š” ์ ์„ ๊ตฌํ•œ๋‹ค.
  • 0, 1, ..., idx_l, idx_l+1, ..., idx_r, idx_r+1, ...
  1. ๊ฐ€์žฅ ์™ผํŽธ ๋ฒกํ„ฐ(idx_l+1 - idx_l)์™€ ๊ฐ€์žฅ ์˜ค๋ฅธํŽธ ๋ฒกํ„ฐ(idx_r - idx_r+1)๋ฅผ ์‚ฌ์šฉํ•ด ๊ธฐ์ค€ ๋ฒกํ„ฐ(์ตœ์ดˆ์˜ ๊ธฐ์ค€ ๋ฒกํ„ฐ๋Š” x์ถ• ๋ฒ•์„ ๋ฒกํ„ฐ)์™€์˜ ๊ฐ์„ ๊ณ„์‚ฐํ•œ ๋’ค, ๊ฐ์ด ๋” ์ž‘์€ ๋ฐฉํ–ฅ์œผ๋กœ ํƒ์ƒ‰์„ ์ง„ํ–‰ํ•œ๋‹ค.
  2. ๋งŒ์•ฝ ๊ธฐ์ค€ ๋ฒกํ„ฐ์™€ ์™ผํŽธ ๋ฒกํ„ฐ ์‚ฌ์ด์˜ ๊ฐ์ด ๋” ์ž‘์•˜์„ ๊ฒฝ์šฐ, ์™ผํŽธ ๋ฒกํ„ฐ๋Š” idx_l+2 - idx_l+1๋กœ ๊ฐฑ์‹ ๋˜๋ฉฐ, ๊ธฐ์ค€ ๋ฒกํ„ฐ๋Š” idx_l+1 - idx_l๋กœ ๊ฐฑ์‹ 
  3. ๋งŒ์•ฝ ๊ธฐ์ค€ ๋ฒกํ„ฐ์™€ ์˜ค๋ฅธํŽธ ๋ฒกํ„ฐ ์‚ฌ์ด์˜ ๊ฐ์ด ๋” ์ž‘์•˜์„ ๊ฒฝ์šฐ, ์˜ค๋ฅธํŽธ ๋ฒกํ„ฐ๋Š” idx_r-1 - idx_r๋กœ ๊ฐฑ์‹ ๋˜๋ฉฐ, ๊ธฐ์ค€ ๋ฒกํ„ฐ๋Š” idx_r - idx_r+1๋กœ ๊ฐฑ์‹ 
  4. 3๋ฒˆ ๊ณผ์ •์„ ํ†ตํ•ด ์™ธ๊ฐ ์ ๋“ค๋กœ ๊ตฌ์„ฑ๋œ ๋„ํ˜•์˜ ๋ณ€ ์ˆ˜๋งŒํผ ์ง„ํ–‰ํ•œ๋‹ค.
  • ์œ„ ๊ณผ์ •์˜ ๋ฌธ์ œ์ :

    • ๊ธฐ์ค€ ๋ฒกํ„ฐ์™€ ๋Œ€์ƒ ๋ฒกํ„ฐ์™€์˜ ๊ฐ์„ ๊ณ„์‚ฐํ•˜๋Š” ๊ณผ์ •์˜ ๊ฒฐ๊ณผ๋Š” double์ด๋ฉฐ, ์ด๋Š” ์‹ค์ˆ˜๋ฒ”์œ„ ์˜ค์ฐจ๊ฐ€ ๋ฐœ์ƒํ•ด ๊ฒฐ๊ณผ๊ฐ€ ์ž˜๋ชป ๋‚˜์˜ฌ ์ˆ˜ ์žˆ์Œ

    • ๋‘ ๋ฒกํ„ฐ์˜ ์™ธ์ ์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ฒฐ๊ณผ๋Š” ์ •์ˆ˜ํ˜•์ด๋ฉฐ, ์˜ค์ฐจ ๋ฐœ์ƒ์— ์˜ํ•œ ์ž˜๋ชป๋œ ๊ฒฐ๊ณผ๋ฅผ ์˜ˆ๋ฐฉํ•  ์ˆ˜ ์žˆ์Œ

    • ๊ธฐ์ค€ ๋ฒกํ„ฐ์™€์˜ ๊ฐ์„ ๊ตฌํ•˜๊ณ ์ž ํ•˜๋Š” ๋‘ ๋ฒกํ„ฐ ๊ฐ„ ์™ธ์  ๊ฒฐ๊ณผ๋ฅผ ํ†ตํ•ด ๊ธฐ์ค€ ๋ฒกํ„ฐ์™€์˜ ๊ฐ์ด ๋” ์ž‘์€ ๋ฒกํ„ฐ๋ฅผ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ์Œ:

      • ์™ผํŽธ ๋ฒกํ„ฐ๋ฅผ i, ์˜ค๋ฅธํŽธ ๋ฒกํ„ฐ๋ฅผ j์ด๋ผ๊ณ  ํ•œ๋‹ค๋ฉด, ๋‘ ๋ฒกํ„ฐ์˜ ์™ธ์  ๊ฒฐ๊ณผ๊ฐ€ ์–‘์ˆ˜์ผ ๋•Œ i ๋ฒกํ„ฐ๋ฅผ, ๋‘ ๋ฒกํ„ฐ์˜ ์™ธ์  ๊ฒฐ๊ณผ๊ฐ€ ์Œ์ˆ˜์ผ ๋•Œ j ๋ฒกํ„ฐ๋ฅผ ๊ฐฑ์‹ 

      rotating-calipers

    • ์œ„ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ ๋‘ ๋ฒกํ„ฐ์˜ ์™ธ์  ๊ฒฐ๊ณผ์— ๋”ฐ๋ฅธ ๋ฒกํ„ฐ ๊ฐฑ์‹ ๋งŒ ์ง„ํ–‰ํ•˜๋ฉด ๋˜๋ฉฐ, ๊ธฐ์ค€ ๋ฒกํ„ฐ์˜ ๊ฐฑ์‹ ์€ ํ•„์š”ํ•˜์ง€ ์•Š์Œ

  • ์ž‘์€ ๊ฐ์„ ๊ธฐ์ค€์œผ๋กœ ๋ฒกํ„ฐ๋ฅผ ๊ฐฑ์‹ ํ•˜๋Š” ์ด์œ ๋Š”, ํฐ ๊ฐ์„ ๊ธฐ์ค€์œผ๋กœ ๋ฒกํ„ฐ๋ฅผ ๊ฐฑ์‹ ํ•  ๊ฒฝ์šฐ ๋‘ ๋ฒกํ„ฐ ์ค‘ ํ•˜๋‚˜๊ฐ€ ๊ธฐ์ค€ ๋ฒกํ„ฐ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์Œ๊ฐ์ด ๋‚˜์˜ฌ ์ˆ˜ ์žˆ์Œ

์—ฐ์Šต๋ฌธ์ œ

#include <iostream>
#include <vector>
#include <utility>
#include <algorithm>

// iostream
using std::cin;
using std::cout;

// vector
using std::vector;

// utility
using std::pair;

// algorithm
using std::sort;

pair<int, int> starting_point;

bool CmpCoor(const pair<int, int>&,
             const pair<int, int>&);
bool CmpCcw(const pair<int, int>&,
            const pair<int, int>&);
int64_t CalcCcw(const pair<int, int>&,
                const pair<int, int>&,
                const pair<int, int>&);
int64_t CalcSqDist(const pair<int, int>&,
                   const pair<int, int>&);

int main() {
  int n;
  cin >> n;
  vector<pair<int, int>> v(n);
  for (int i = 0; i < n; ++i)
    cin >> v[i].first >> v[i].second;

  // find the point with the lowest y-coordinate. (v[0], starting_point)
  sort(v.begin(), v.end(), CmpCoor);
  starting_point = v.front();
  // the set of points must be sorted in increasing order of the angle they
  // and the point P make with the x-axis
  sort(v.begin() + 1, v.end(), CmpCcw);

  // Graham's scan
  vector<pair<int, int>> convex_hull;
  for (const auto& p : v) {
    while (convex_hull.size() >= 2) {
      if (CalcCcw(convex_hull[convex_hull.size()-2], convex_hull.back(), p) > 0)
        break;
      convex_hull.pop_back();
    }
    convex_hull.push_back(p);
  }

  // Rotating calipers
  int left_i = 0;
  int right_i = 0;
  int n_edge = convex_hull.size();
  for (int i = 0; i < n_edge; ++i) {
    if (convex_hull[i].first < convex_hull[left_i].first)
      left_i = i;
    if (convex_hull[i].first > convex_hull[right_i].first)
      right_i = i;
  }

  int64_t longest_dist = CalcSqDist(convex_hull[left_i], convex_hull[right_i]);
  pair<int, int> left_coor = convex_hull[left_i];
  pair<int, int> right_coor = convex_hull[right_i];
  pair<int, int> origin = { 0, 0 };
  for (int i = 0; i < n_edge; ++i) {
    pair<int, int> left_vector = {
      convex_hull[(left_i + 1)%n_edge].first - convex_hull[left_i].first,
      convex_hull[(left_i + 1)%n_edge].second - convex_hull[left_i].second
    };
    pair<int, int> right_vector = {
      convex_hull[right_i].first - convex_hull[(right_i + 1)%n_edge].first,
      convex_hull[right_i].second - convex_hull[(right_i + 1)%n_edge].second
    };

    if (CalcCcw(origin, left_vector, right_vector) > 0)
      left_i = (left_i + 1) % n_edge;
    else
      right_i = (right_i + 1) % n_edge;

    if (longest_dist < CalcSqDist(convex_hull[left_i], convex_hull[right_i])) {
      longest_dist = CalcSqDist(convex_hull[left_i], convex_hull[right_i]);
      left_coor = convex_hull[left_i];
      right_coor = convex_hull[right_i];
    }
  }
  cout << longest_dist;

  return 0;
}

bool CmpCoor(const pair<int, int>& s,
             const pair<int, int>& t) {
  if (s.second < t.second)
    return true;

  if (s.second == t.second && s.first < t.first)
    return true;

  return false;
}

bool CmpCcw(const pair<int, int>& s,
            const pair<int, int>& t) {
  int64_t res = CalcCcw(starting_point, s, t);

  if (res)
    return res > 0;  // ccw : true, cw : false

  // res = 0
  int64_t dist1 = CalcSqDist(s, starting_point);
  int64_t dist2 = CalcSqDist(t, starting_point);

  return dist1 < dist2;
}

// ccw         : pos.
// on the line : 0
// cw          : neg.
int64_t CalcCcw(const pair<int, int>& a,
                const pair<int, int>& b,
                const pair<int, int>& c) {
  int64_t u1 = b.first - a.first;
  int64_t v1 = b.second - a.second;
  int64_t u2 = c.first - a.first;
  int64_t v2 = c.second - a.second;

  return u1 * v2 - u2 * v1;
}

int64_t CalcSqDist(const pair<int, int>& s,
                   const pair<int, int>& t) {
  int64_t diff_x = s.first - t.first;
  int64_t diff_y = s.second - t.second;

  return diff_x * diff_x + diff_y * diff_y;
}

[WIP]Point in Convex Polygon

  • ์˜ค๋ฅ˜ ์ˆ˜์ •: idx = 0, ๊ทธ๋ฆผ
  1. ์ปจ๋ฒก์Šค ํ—์„ ํ†ตํ•ด ์™ธ๊ฐ ์ ๋“ค์„ ๊ตฌํ•œ๋‹ค.

  2. ์ ์ด ์ปจ๋ฒก์Šค ํ— ๋‚ด์— ์กด์žฌํ•˜๋Š”์ง€ ํŒ๋ณ„ํ•œ๋‹ค:

    1. ๋ชจ๋“  ๋ฒกํ„ฐ์˜ ๊ธฐ์ค€์ ์€ ์ปจ๋ฒก์Šค ํ—์˜ 0๋ฒˆ ์ขŒํ‘œ์ด๋‹ค.
    2. ์ž„์˜์˜ ์ ์ด ๊ธฐ์ค€์ ์˜ ์™ผ์ชฝ ๋ฒกํ„ฐ์™€์˜ ์™ธ์  ๊ฒฐ๊ณผ๊ฐ€ ์Œ์ˆ˜๋ผ๋ฉด, ํ•ด๋‹น ์ ์€ ๋„ํ˜• ์™ธ๋ถ€์— ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.
    3. ์ž„์˜์˜ ์ ์ด ๊ธฐ์ค€์ ์˜ ์˜ค๋ฅธ์ชฝ ๋ฒกํ„ฐ์™€์˜ ์™ธ์  ๊ฒฐ๊ณผ๊ฐ€ ์–‘์ˆ˜๋ผ๋ฉด, ํ•ด๋‹น ์ ์€ ๋„ํ˜• ์™ธ๋ถ€์— ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.
    4. ์ด๋ถ„ํƒ์ƒ‰์„ ํ†ตํ•ด ์ ์ด ์œ„์น˜ํ•  ์ˆ˜ ์žˆ๋Š” ์˜์—ญ์„ ์ฐพ๋Š”๋‹ค. ๋งŒ์•ฝ ์ปจ๋ฒก์Šค ํ—์˜ ๊ฐœ์ˆ˜๊ฐ€ n๊ฐœ๋ผ๋ฉด, ์ด๋ถ„ํƒ์ƒ‰์˜ ๋ฒ”์œ„๋Š” [1, n)์ด ๋œ๋‹ค.
    5. ์ž„์˜์˜ ์ (p)์ด ์œ„์น˜ํ•  ์ˆ˜ ์žˆ๋Š” ์˜์—ญ์„ ๋ฐœ๊ฒฌํ–ˆ๋‹ค๋ฉด, convex_hull[idx], p, convex_hull[idx+1] ์„ธ ์ ์— ๋Œ€ํ•ด ์™ธ์ ํ•œ๋‹ค:
      1. ์™ธ์  ๊ฒฐ๊ณผ๊ฐ€ ์–‘์ˆ˜๋ผ๋ฉด ํ•ด๋‹น ์ ์€ ๋„ํ˜• ์™ธ๋ถ€์— ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.
      2. ์™ธ์  ๊ฒฐ๊ณผ๊ฐ€ ์–‘์ˆ˜๋ผ๋ฉด ํ•ด๋‹น ์ ์€ ๋„ํ˜• ๋‚ด๋ถ€์—, 0์ด๋ผ๋ฉด ํ•ด๋‹น ์ ์€ ๋„ํ˜• ๊ฒฝ๊ณ„์— ๊ฑธ์ฒ˜์žˆ๋Š” ๊ฒƒ์ด๋‹ค.

์—ฐ์Šต๋ฌธ์ œ

/*
  Copyright 2022 Ryan M. Jeong <[email protected]>
*/

// CP
#define CP do {                     \
  std::ios::sync_with_stdio(false); \
  std::cin.tie(NULL);               \
} while (0)

#include <iostream>
#include <vector>
#include <utility>
#include <algorithm>

// iostream
using std::cin;
using std::cout;
using std::fixed;

// vector
using std::vector;

// utility
using std::pair;

// algorithm
using std::sort;

pair<int, int> starting_point;

bool CmpCoor(const pair<int, int>&,
             const pair<int, int>&);
bool CmpCcw(const pair<int, int>&,
            const pair<int, int>&);
int64_t CalcCcw(const pair<int, int>&,
                const pair<int, int>&,
                const pair<int, int>&);
int64_t CalcSqDist(const pair<int, int>&,
                   const pair<int, int>&);
int64_t PointInPolygon(const vector<pair<int, int>>& convex_hull,
                       const pair<int, int>&);

int main() {
  CP;

  int n = 3;
  vector<pair<int, int>> v(n);
  for (auto& i : v)
    cin >> i.first >> i.second;

  // find the point with the lowest y-coordinate. (v[0], starting_point)
  sort(v.begin(), v.end(), CmpCoor);
  starting_point = v.front();
  // the set of points must be sorted in increasing order of the angle they and
  // the point P make with the x-axis
  sort(v.begin() + 1, v.end(), CmpCcw);

  // Graham's scan
  vector<pair<int, int>> convex_hull;
  for (const auto& p : v) {
    while (convex_hull.size() >= 2) {
      if (CalcCcw(convex_hull[convex_hull.size()-2], convex_hull.back(), p) > 0)
        break;
      convex_hull.pop_back();
    }
    convex_hull.push_back(p);
  }

  int m;
  cin >> m;
  // Determine if a point is inside a polygon
  int cnt = 0;
  while (m--) {
    static pair<int, int> p;
    cin >> p.first >> p.second;
    if (PointInPolygon(convex_hull, p) > 0)
      continue;
    ++cnt;
  }
  cout << fixed;
  cout.precision(1);
  cout << static_cast<double>(CalcCcw(
      convex_hull[0], convex_hull[1], convex_hull[2])) / 2 << '\n';
  cout << cnt;

  return 0;
}

bool CmpCoor(const pair<int, int>& s,
             const pair<int, int>& t) {
  if (s.second < t.second)
    return true;

  if (s.second == t.second && s.first < t.first)
    return true;

  return false;
}

bool CmpCcw(const pair<int, int>& s,
            const pair<int, int>& t) {
  int64_t res = CalcCcw(starting_point, s, t);

  if (res)
    return res > 0;  // ccw : true, cw : false

  // res = 0
  int64_t dist1 = CalcSqDist(s, starting_point);
  int64_t dist2 = CalcSqDist(t, starting_point);

  return dist1 < dist2;
}

/* ccw         : pos.
   on the line : 0
   cw          : neg. */
int64_t CalcCcw(const pair<int, int>& a,
                const pair<int, int>& b,
                const pair<int, int>& c) {
  int64_t u1 = b.first - a.first;
  int64_t v1 = b.second - a.second;
  int64_t u2 = c.first - a.first;
  int64_t v2 = c.second - a.second;

  return u1 * v2 - u2 * v1;
}

int64_t CalcSqDist(const pair<int, int>& s,
                   const pair<int, int>& t) {
  int64_t diff_x = s.first - t.first;
  int64_t diff_y = s.second - t.second;

  return diff_x * diff_x + diff_y * diff_y;
}

// the value of return is positive: outside of the polygon
// the value of return is zero: lie on the line of the polygon
// the value of return is negative: inside of the polygon
int64_t PointInPolygon(const vector<pair<int, int>>& convex_hull,
                       const pair<int, int>& p) {
  // check right-side
  if (CalcCcw(convex_hull.front(), convex_hull[1], p) < 0)
    return 1;

  // check left-side
  if (CalcCcw(convex_hull.front(), convex_hull.back(), p) > 0)
    return 1;

  // find a section which contains the point:
  // direction: ccw
  // low: right-side
  // high: left-side
  // idx: 1, For the case where the point lies on the line(a vector from 0 to 1)
  int low = 1;
  int high = convex_hull.size();  // [low, high)
  int idx = 1;
  while (low < high) {
    int mid = (low + high) / 2;
    if (CalcCcw(convex_hull.front(), convex_hull[mid], p) > 0) {
      idx = mid;
      low = mid + 1;
    } else {
      high = mid;
    }
  }

  return CalcCcw(convex_hull[idx], p, convex_hull[idx+1]);
}

์ด์ „ - String ๋ชฉ๋ก ๋‹ค์Œ - ์—†์Œ