summaryrefslogtreecommitdiff
path: root/content/geometry/circle.cpp
blob: 155b55ccf3aa97e4d54473fd0021e4567a2a5a53 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// berechnet die Schnittpunkte von zwei Kreisen
// (Kreise dürfen nicht gleich sein!)
vector<pt> circleIntersection(pt c1, double r1,
	                          pt c2, double r2) {
	double d = abs(c1 - c2);
	if (d < abs(r1 - r2) || d > abs(r1 + r2)) return {};
	double a = (r1 * r1 - r2 * r2 + d * d) / (2 * d);
	pt p = (c2 - c1) * a / d + c1;
	if (d == abs(r1 - r2) || d == abs(r1 + r2)) return {p};
	double h = sqrt(r1 * r1 - a * a);
	return {p + pt{0, 1} * (c2 - c1) * h / d,
	        p - pt{0, 1} * (c2 - c1) * h / d};
}

// berechnet die Schnittpunkte zwischen
// einem Kreis(Kugel) und einem Strahl (2D und 3D)
vector<pt> circleRayIntersection(pt center, double r,
	                             pt orig, pt dir) {
	vector<pt> result;
	double a = norm(dir);
	double b = 2 * dot(dir, orig - center);
	double c = norm(orig - center) - r * r;
	double discr = b * b - 4 * a * c;
	if (discr >= 0) {
		//t in [0, 1] => Schnitt mit Segment [orig, orig + dir]
		double t1 = -(b + sqrt(discr)) / (2 * a);
		double t2 = -(b - sqrt(discr)) / (2 * a);
		if (t1 >= 0) result.push_back(t1 * dir + orig);
		if (t2 >= 0 && abs(t1 - t2) > EPS) {
			result.push_back(t2 * dir + orig);
	}}
	return result;
}