1 /*
2  * Copyright (c) 2019 Kevin Townsend (KTOWN)
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <math.h>
8 #include <errno.h>
9 #include <zsl/zsl.h>
10 #include <zsl/physics/projectiles.h>
11 
12 int
zsl_phy_proj_init_vel(zsl_real_t vi,zsl_real_t theta,zsl_real_t * vih,zsl_real_t * viv)13 zsl_phy_proj_init_vel(zsl_real_t vi, zsl_real_t theta, zsl_real_t *vih,
14 		      zsl_real_t *viv)
15 {
16 	*vih = vi * ZSL_COS(theta);
17 	*viv = vi * ZSL_SIN(theta);
18 
19 	return 0;
20 }
21 
22 int
zsl_phy_proj_time(zsl_real_t viv,zsl_real_t yi,zsl_real_t yf,zsl_real_t * t)23 zsl_phy_proj_time(zsl_real_t viv, zsl_real_t yi, zsl_real_t yf,
24 		  zsl_real_t *t)
25 {
26 	zsl_real_t disc = viv * viv + 2.0 * ZSL_GRAV_EARTH * (yi - yf);
27 
28 	if (disc < 0) {
29 		*t = NAN;
30 		return -EINVAL;
31 	}
32 
33 	*t = (viv + ZSL_SQRT(disc)) / ZSL_GRAV_EARTH;
34 
35 	return 0;
36 }
37 
zsl_phy_proj_time_first(zsl_real_t viv,zsl_real_t yi,zsl_real_t yf,zsl_real_t * t)38 int zsl_phy_proj_time_first(zsl_real_t viv, zsl_real_t yi, zsl_real_t yf,
39 			    zsl_real_t *t)
40 {
41 	zsl_real_t disc = viv * viv + 2.0 * ZSL_GRAV_EARTH * (yi - yf);
42 
43 	if (disc < 0) {
44 		*t = NAN;
45 		return -EINVAL;
46 	}
47 
48 	*t = (viv - ZSL_SQRT(disc)) / ZSL_GRAV_EARTH;
49 
50 	if (*t < 0) {
51 		*t = NAN;
52 		return -EINVAL;
53 	}
54 
55 	return 0;
56 }
57 
58 int
zsl_phy_proj_time2(zsl_real_t viv,zsl_real_t vfv,zsl_real_t * t)59 zsl_phy_proj_time2(zsl_real_t viv, zsl_real_t vfv, zsl_real_t *t)
60 {
61 	*t = (viv - vfv) / ZSL_GRAV_EARTH;
62 
63 	if (*t < 0) {
64 		*t = NAN;
65 		return -EINVAL;
66 	}
67 
68 	return 0;
69 }
70 
71 int
zsl_phy_proj_ver_motion(zsl_real_t viv,zsl_real_t t,zsl_real_t yi,zsl_real_t * yf)72 zsl_phy_proj_ver_motion(zsl_real_t viv, zsl_real_t t, zsl_real_t yi,
73 			zsl_real_t *yf)
74 {
75 	if (t < 0) {
76 		*yf = NAN;
77 		return -EINVAL;
78 	}
79 
80 	*yf = yi + viv * t - (ZSL_GRAV_EARTH * t * t) / 2.0;
81 
82 	return 0;
83 }
84 
85 int
zsl_phy_proj_ver_vel(zsl_real_t viv,zsl_real_t t,zsl_real_t * vfv)86 zsl_phy_proj_ver_vel(zsl_real_t viv, zsl_real_t t, zsl_real_t *vfv)
87 {
88 	if (t < 0) {
89 		*vfv = NAN;
90 		return -EINVAL;
91 	}
92 
93 	*vfv = viv - ZSL_GRAV_EARTH * t;
94 
95 	return 0;
96 }
97 
98 int
zsl_phy_proj_hor_motion(zsl_real_t vih,zsl_real_t t,zsl_real_t xi,zsl_real_t * xf)99 zsl_phy_proj_hor_motion(zsl_real_t vih, zsl_real_t t, zsl_real_t xi,
100 			zsl_real_t *xf)
101 {
102 	*xf = xi + vih * t;
103 
104 	if (t < 0) {
105 		*xf = NAN;
106 		return -EINVAL;
107 	}
108 
109 	return 0;
110 }
111 
112 int
zsl_phy_proj_trajectory(zsl_real_t vih,zsl_real_t viv,zsl_real_t xi,zsl_real_t yi,zsl_real_t xf,zsl_real_t * yf)113 zsl_phy_proj_trajectory(zsl_real_t vih, zsl_real_t viv, zsl_real_t xi,
114 			zsl_real_t yi, zsl_real_t xf, zsl_real_t *yf)
115 {
116 	zsl_real_t t = (xf - xi) / vih;
117 
118 	if (vih == 0 || t < 0) {
119 		*yf = NAN;
120 		return -EINVAL;
121 	}
122 
123 	zsl_phy_proj_ver_motion(viv, t, yi, yf);
124 
125 	return 0;
126 }
127 
128 int
zsl_phy_proj_vel(zsl_real_t vfh,zsl_real_t vfv,zsl_real_t * vf)129 zsl_phy_proj_vel(zsl_real_t vfh, zsl_real_t vfv, zsl_real_t *vf)
130 {
131 	*vf = ZSL_SQRT(vfh * vfh + vfv * vfv);
132 
133 	return 0;
134 }
135 
136 int
zsl_phy_proj_angle(zsl_real_t vfh,zsl_real_t vfv,zsl_real_t * theta)137 zsl_phy_proj_angle(zsl_real_t vfh, zsl_real_t vfv, zsl_real_t *theta)
138 {
139 	if (vfh == 0) {
140 		*theta = ZSL_PI / 2.0;
141 		return 0;
142 	}
143 
144 	*theta = ZSL_ATAN(vfv / vfh);
145 
146 	return 0;
147 }
148 
149 int
zsl_phy_proj_range(zsl_real_t vih,zsl_real_t viv,zsl_real_t xi,zsl_real_t yi,zsl_real_t * dist)150 zsl_phy_proj_range(zsl_real_t vih, zsl_real_t viv, zsl_real_t xi,
151 		   zsl_real_t yi, zsl_real_t *dist)
152 {
153 	zsl_real_t t, xf;
154 
155 	zsl_phy_proj_time(viv, yi, 0.0, &t);
156 
157 	zsl_phy_proj_hor_motion(vih, t, xi, &xf);
158 
159 	*dist = xf - xi;
160 
161 	return 0;
162 }
163