1 | /******************************************************************************* |
2 | Copyright (c) The Taichi Authors (2016- ). All Rights Reserved. |
3 | The use of this software is governed by the LICENSE file. |
4 | *******************************************************************************/ |
5 | |
6 | #pragma once |
7 | |
8 | #include <vector> |
9 | |
10 | #include "taichi/common/core.h" |
11 | #include "linalg.h" |
12 | |
13 | namespace taichi { |
14 | |
15 | inline bool intersect(const Vector2 &a, |
16 | const Vector2 &b, |
17 | const Vector2 &c, |
18 | const Vector2 &d) { |
19 | if (cross(c - a, b - a) * cross(b - a, d - a) > 0 && |
20 | cross(a - d, c - d) * cross(c - d, b - d) > 0) { |
21 | return true; |
22 | } else { |
23 | return false; |
24 | } |
25 | } |
26 | |
27 | inline real nearest_distance(const Vector2 &p, |
28 | const Vector2 &a, |
29 | const Vector2 &b) { |
30 | real ab = length(a - b); |
31 | Vector2 dir = normalized(b - a); |
32 | real pos = clamp(dot(p - a, dir), 0.0_f, ab); |
33 | return length(a + pos * dir - p); |
34 | } |
35 | |
36 | inline real nearest_distance(const Vector2 &p, |
37 | const std::vector<Vector2> &polygon) { |
38 | real dist = std::numeric_limits<float>::infinity(); |
39 | for (int i = 0; i < (int)polygon.size(); i++) { |
40 | dist = std::min(dist, nearest_distance(p, polygon[i], |
41 | polygon[(i + 1) % polygon.size()])); |
42 | } |
43 | return dist; |
44 | } |
45 | |
46 | inline bool inside_polygon(const Vector2 &p, |
47 | const std::vector<Vector2> &polygon) { |
48 | int count = 0; |
49 | static const Vector2 q(123532_f, 532421123_f); |
50 | for (int i = 0; i < (int)polygon.size(); i++) { |
51 | count += intersect(p, q, polygon[i], polygon[(i + 1) % polygon.size()]); |
52 | } |
53 | return count % 2 == 1; |
54 | } |
55 | |
56 | inline std::vector<Vector2> points_inside_polygon( |
57 | std::vector<float> x_range, |
58 | std::vector<float> y_range, |
59 | const std::vector<Vector2> &polygon) { |
60 | std::vector<Vector2> ret; |
61 | for (float x = x_range[0]; x < x_range[1]; x += x_range[2]) { |
62 | for (float y = y_range[0]; y < y_range[1]; y += y_range[2]) { |
63 | Vector2 p(x, y); |
64 | if (inside_polygon(p, polygon)) { |
65 | ret.push_back(p); |
66 | } |
67 | } |
68 | } |
69 | return ret; |
70 | } |
71 | |
72 | inline std::vector<Vector2> points_inside_sphere(std::vector<float> x_range, |
73 | std::vector<float> y_range, |
74 | const Vector2 ¢er, |
75 | float radius) { |
76 | std::vector<Vector2> ret; |
77 | for (float x = x_range[0]; x < x_range[1]; x += x_range[2]) { |
78 | for (float y = y_range[0]; y < y_range[1]; y += y_range[2]) { |
79 | Vector2 p(x, y); |
80 | if (length(p - center) < radius) { |
81 | ret.push_back(p); |
82 | } |
83 | } |
84 | } |
85 | return ret; |
86 | } |
87 | |
88 | } // namespace taichi |
89 | |