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
13namespace taichi {
14
15inline 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
27inline 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
36inline 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
46inline 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
56inline 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
72inline std::vector<Vector2> points_inside_sphere(std::vector<float> x_range,
73 std::vector<float> y_range,
74 const Vector2 &center,
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