-
Notifications
You must be signed in to change notification settings - Fork 1
/
cylinder_intersection.c
135 lines (124 loc) · 4.11 KB
/
cylinder_intersection.c
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* cylinder_intersection.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mghalmi <[email protected]> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/01/27 14:44:22 by mghalmi #+# #+# */
/* Updated: 2024/02/08 13:40:17 by mghalmi ### ########.fr */
/* */
/* ************************************************************************** */
#include "main.h"
int solve_cylinder(double x[2], t_point o, t_point d, t_obj *lst)
{
t_point v;
t_point u;
double a;
double b;
double c;
v = scal_x_vec(dot(d, lst->fig.cy.nv), lst->fig.cy.nv);
v = vsubstr(d, v);
u = scal_x_vec(dot(vsubstr(o, lst->fig.cy.c), lst->fig.cy.nv), \
lst->fig.cy.nv);
u = vsubstr(vsubstr(o, lst->fig.cy.c), u);
a = dot(v, v);
b = 2 * dot(v, u);
c = dot(u, u) - pow(lst->fig.cy.r, 2);
x[0] = (-b + sqrt(pow(b, 2) - 4 * a * c)) / (2 * a);
x[1] = (-b - sqrt(pow(b, 2) - 4 * a * c)) / (2 * a);
if ((x[0] != x[0] && x[1] != x[1]) || (x[0] < EPSILON && x[1] < EPSILON))
{
x[0] = INFINITY;
x[1] = INFINITY;
return (0);
}
return (1);
}
t_point calc_cy_normal(double x2[2], t_point o, t_point d, t_obj *lst)
{
double dist;
double x;
if ((lst->fig.cy.dist1 >= 0 && lst->fig.cy.dist1 <= lst->fig.cy.h \
&& x2[0] > EPSILON) && (lst->fig.cy.dist2 >= 0 \
&& lst->fig.cy.dist2 <= lst->fig.cy.h && x2[1] > EPSILON))
{
dist = check_dist(x2, lst);
x = check_x(x2);
}
else if (lst->fig.cy.dist1 >= 0 && lst->fig.cy.dist1 <= lst->fig.cy.h \
&& x2[0] > EPSILON)
{
dist = lst->fig.cy.dist1;
x = x2[0];
}
else
{
dist = lst->fig.cy.dist2;
x = x2[1];
}
x2[0] = x;
return (normalize(vsubstr(vsubstr(scal_x_vec(x, d), \
scal_x_vec(dist, lst->fig.cy.nv)), vsubstr(lst->fig.cy.c, o))));
}
double cy_intersection(t_point o, t_point d, t_point *normal, t_obj *lst)
{
double x2[2];
if (solve_cylinder(x2, o, d, lst) == 0)
return (INFINITY);
lst->fig.cy.dist1 = dot(lst->fig.cy.nv, vsubstr(scal_x_vec(x2[0], d), \
vsubstr(lst->fig.cy.c, o)));
lst->fig.cy.dist2 = dot(lst->fig.cy.nv, vsubstr(scal_x_vec(x2[1], d), \
vsubstr(lst->fig.cy.c, o)));
if (!((lst->fig.cy.dist1 >= 0 && lst->fig.cy.dist1 <= lst->fig.cy.h \
&& x2[0] > EPSILON) || (lst->fig.cy.dist2 >= 0 \
&& lst->fig.cy.dist2 <= lst->fig.cy.h && x2[0] > EPSILON)))
return (INFINITY);
*normal = calc_cy_normal(x2, o, d, lst);
return (x2[0]);
}
double caps_intersection(t_point o, t_point d, t_obj *lst)
{
double id1;
double id2;
t_point ip1;
t_point ip2;
t_point c2;
c2 = vadd(lst->fig.cy.c, scal_x_vec(lst->fig.cy.h, lst->fig.cy.nv));
id1 = solve_plane(o, d, lst->fig.cy.c, lst->fig.cy.nv);
id2 = solve_plane(o, d, c2, lst->fig.cy.nv);
if (id1 < INFINITY || id2 < INFINITY)
{
ip1 = vadd(o, scal_x_vec(id1, d));
ip2 = vadd(o, scal_x_vec(id2, d));
if ((id1 < INFINITY && distance(ip1, lst->fig.cy.c) <= lst->fig.cy.r) \
&& (id2 < INFINITY && distance(ip2, c2) <= lst->fig.cy.r))
select_closest(id1, id2);
else if (id1 < INFINITY \
&& distance(ip1, lst->fig.cy.c) <= lst->fig.cy.r)
return (id1);
else if (id2 < INFINITY && distance(ip2, c2) <= lst->fig.cy.r)
return (id2);
return (INFINITY);
}
return (INFINITY);
}
double cylinder_intersection(t_point o, t_point d, t_obj *lst)
{
double cylinder_inter;
double caps_inter;
t_point cy_normal;
cylinder_inter = cy_intersection(o, d, &cy_normal, lst);
caps_inter = caps_intersection(o, d, lst);
if (cylinder_inter < INFINITY || caps_inter < INFINITY)
{
if (cylinder_inter < caps_inter)
{
lst->normal = cy_normal;
return (cylinder_inter);
}
lst->normal = lst->fig.cy.nv;
return (caps_inter);
}
return (INFINITY);
}