[Tutorial] Tangents of a Polygon in O(log n)

Правка en16, от Jose_17, 2025-03-03 10:32:55

In one of the last stages of the 3rd Universal Cup, there was a not-so-nice problem (it required using fractions) that involved an algorithm for which I hadn't found a tutorial or much information on popular blogs. This approach was developed by me, and I appreciate any feedback on it or its implementation.

https://codeforces.net/gym/105657/problem/C

Parameters

  • The polygon is convex
  • The point is not strictly inside

What are the tangents to a polygon from a point?

The tangents of a polygon with respect to a point are the lines that pass through the point outside the polygon and touch the polygon at exactly one vertex or along one side, without crossing its interior.

Why are these useful?

  • Solve difficult problems
  • Solve problems related to visibility or trajectory where the polygon cannot be crossed.

Algorithm

To describe the algorithm, only the left tangent will be specified. At the end, it will be indicated what changes with respect to the right tangent.

The left tangent can be described using the cross product. For a point $$$P_i$$$ and the point $$$p$$$ (for which the tangents are computed), it can be considered the tangent if the cross product with respect to points $$$P_{i+1}$$$ and $$$P_{i-1}$$$ is less than or equal to zero:

$$$ (P_{i} - p) \times (P_{i+1} - p) \leq 0 $$$
$$$ (P_{i} - p) \times (P_{i-1} - p) \leq 0 $$$

Now, we will analyze the behavior of these signs in the following example.

Let us observe that the signs for point C are exactly as we require.
For points G, F, and E, the second condition is satisfied, and for points A, M, T, U, and V, the first condition is satisfied.
However, we can notice that it behaves like a unimodal function.

Thus, it is enough to find the first point for which the first condition is satisfied (in a counterclockwise direction).
To do this, we will do two things.

  • Divide the convex hull into its lower and upper layers.
  • Divide each layer into two parts to find the left and right tangents.

There will be cases where it would not be necessary to use a layer, as in the previous example. Determining when it would be necessary or not would only add more complexity and does not ultimately change the complexity.

The same example illustrated on the division.

When dividing the convex hull, we must take into account that if it is a single point that is farthest to the left (smallest x), it must be in both layers, and the same applies to the point farthest to the right (largest x).

To divide each layer into two parts, a binary search will be used.

Finally, the complexity analysis: a total of six binary searches will be performed, one for each layer and one for each of the four divisions of the polygon, resulting in $$$O(\log n)$$$.

Implementation

Musical recommendation: New Kid in Town ^^

Теги geometry, binary search

История

 
 
 
 
Правки
 
 
  Rev. Язык Кто Когда Δ Комментарий
en26 Английский Jose_17 2025-03-03 22:48:56 0 (published)
en25 Английский Jose_17 2025-03-03 22:47:32 227 Tiny change: 'ambre ^^\nhttps://' -> 'ambre ^^\n\nhttps://'
en24 Английский Jose_17 2025-03-03 22:24:09 48 Marckess
en23 Английский Jose_17 2025-03-03 21:25:44 0 Marckess
en22 Английский Jose_17 2025-03-03 21:23:48 3 Tiny change: ', Enjambre' -> ', Enjambre ^^'
en21 Английский Jose_17 2025-03-03 11:04:58 160
en20 Английский Jose_17 2025-03-03 10:57:53 57 Tiny change: '/details> ```cpp\n\n' -> '/details> \n```cpp\n\n'
en19 Английский Jose_17 2025-03-03 10:43:08 13 Tiny change: '">\n<br>\n#include' -> '">\n<br>\n```cpp\n#include'
en18 Английский Jose_17 2025-03-03 10:39:45 6 Tiny change: 'tation">\n\n\n#include' -> 'tation">\n<br>\n#include'
en17 Английский Jose_17 2025-03-03 10:36:15 52
en16 Английский Jose_17 2025-03-03 10:32:55 254
en15 Английский Jose_17 2025-03-03 10:29:49 102
en14 Английский Jose_17 2025-03-03 10:28:20 344
en13 Английский Jose_17 2025-03-03 10:25:19 2 Tiny change: 'tation">\nvector<p' -> 'tation">\n\nvector<p'
en12 Английский Jose_17 2025-03-03 10:23:55 10
en11 Английский Jose_17 2025-03-03 10:23:37 2365
en10 Английский Jose_17 2025-03-03 08:09:19 179
en9 Английский Jose_17 2025-03-03 08:03:12 817
en8 Английский Jose_17 2025-03-01 04:25:17 60
en7 Английский Jose_17 2025-03-01 04:23:19 4 Tiny change: 'le="width:350px; height:300px;" />\n' -> 'le="width:500px; height:350px;" />\n'
en6 Английский Jose_17 2025-03-01 04:22:53 196 Tiny change: '\n\n\n$$\n(P_{i} -' -> '\n\n\n$$\n\newline \n(P_{i} -'
en5 Английский Jose_17 2025-03-01 03:59:13 2 Tiny change: ' zero:\n\n$$\n(P' -> ' zero:\n\n\n$$\n(P'
en4 Английский Jose_17 2025-03-01 03:58:35 302
en3 Английский Jose_17 2025-03-01 03:55:45 469
en2 Английский Jose_17 2025-02-27 22:35:03 153 Tiny change: 'le="width:500px; heigh' -> 'le="width:350px; heigh'
en1 Английский Jose_17 2025-02-27 22:27:51 820 Initial revision (saved to drafts)