1 /***************************************************************************
2                           mathfuncs.c  -  description
3                              -------------------
4     begin                : Thu Sep 6 2001
5     copyright            : (C) 2001 by Michael Speck
6     email                : kulkanie@gmx.net
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #include "../client/lbreakout.h"
19 #include "mathfuncs.h"
20 
21 char circle_msg[256];
22 
23 /*
24 ====================================================================
25 Return vector struct with the specified coordinates.
26 ====================================================================
27 */
vector_get(float x,float y)28 Vector vector_get( float x, float y )
29 {
30     Vector v = { x, y };
31     return v;
32 }
33 /*
34 ====================================================================
35 Give vector the normed length of 1.
36 ====================================================================
37 */
vector_norm(Vector * v)38 void vector_norm( Vector *v )
39 {
40     float length;
41     if ( v->x == 0 && v->y == 0 ) return; /* NULL vector may not be normed */
42     length = sqrt( v->x * v->x + v->y * v->y );
43     v->x /= length;
44     v->y /= length;
45 }
46 /*
47 ====================================================================
48 Return monotony of vector. If vertical return 0
49 ====================================================================
50 */
vector_monotony(Vector v)51 float vector_monotony( Vector v )
52 {
53     if ( v.x == 0 ) return 0;
54     return v.y / v.x;
55 }
56 /*
57 ====================================================================
58 Set length of a vector.
59 ====================================================================
60 */
vector_set_length(Vector * v,float length)61 void vector_set_length( Vector *v, float length )
62 {
63     vector_norm( v );
64     v->x *= length; v->y *= length;
65 }
66 
67 /*
68 ====================================================================
69 Initiate a line struct.
70 ====================================================================
71 */
line_set(Line * line,float x,float y,float m)72 void line_set( Line *line, float x, float y, float m )
73 {
74     line->vertical = 0;
75     line->m = m;
76     line->n = y - m*x;
77 }
line_set_vert(Line * line,float x)78 void line_set_vert( Line *line, float x )
79 {
80     line->vertical = 1;
81     line->x = x;
82 }
line_set_hori(Line * line,float y)83 void line_set_hori( Line *line, float y )
84 {
85     line->vertical = 0;
86     line->m = 0;
87     line->n = y;
88 }
89 /*
90 ====================================================================
91 Intersect lines and set 'pos' to intersecting point.
92 Return Value: True if lines intersect.
93 ====================================================================
94 */
line_intersect(Line * line,Line * target,Coord * pos)95 int line_intersect( Line *line, Line *target, Coord *pos )
96 {
97     /* reset pos */
98     pos->x = pos->y = 0;
99     /* if lines are parallel return False */
100     if ( line->vertical && target->vertical ) return 0; /* vertical parallels */
101     if ( !line->vertical &&  !target->vertical && line->m == target->m ) return 0; /* non-vertical parallels */
102     /* right now only one thing is supported: line horizontal */
103     if ( line->m == 0 && line->vertical == 0 ) {
104         pos->y = line->n;
105         if ( target->vertical )
106             pos->x = target->x;
107         else
108             pos->x = ( pos->y - target->n ) / target->m;
109         return 1;
110     }
111     if ( line->vertical ) {
112         if ( target->vertical ) return 0;
113         pos->x = line->x;
114         pos->y = target->m * pos->x + target->n;
115         return 1;
116     }
117     if ( target->vertical ) {
118         printf( "line_intersect: line non-vertical and target vertical not supported yet\n" );
119         return 1;
120     }
121     /* compute if both lines are neither vertical nor horizontal */
122     pos->x = ( line->n - target->n ) / ( target->m - line->m );
123     pos->y = line->m * pos->x + line->n;
124     return 1;
125 }
126 
127 /*
128 ====================================================================
129 Initiate a line struct.
130 ====================================================================
131 */
iline_set(ILine * line,int x,int y,int m_4096)132 void iline_set( ILine *line, int x, int y, int m_4096 )
133 {
134     line->vertical = 0;
135     line->m_4096 = m_4096;
136     line->n = y - ((m_4096*x)>>12);
137 }
iline_set_vert(ILine * line,int x)138 void iline_set_vert( ILine *line, int x )
139 {
140     line->vertical = 1;
141     line->x = x;
142 }
iline_set_hori(ILine * line,int y)143 void iline_set_hori( ILine *line, int y )
144 {
145     line->vertical = 0;
146     line->m_4096 = 0;
147     line->n = y;
148 }
149 /*
150 ====================================================================
151 Intersect lines and set 'pos' to intersecting point.
152 Return Value: True if lines intersect.
153 ====================================================================
154 */
iline_intersect(ILine * line,ILine * target,ICoord * pos)155 int iline_intersect( ILine *line, ILine *target, ICoord *pos )
156 {
157     /* reset pos */
158     pos->x = pos->y = 0;
159     /* if lines are parallel return False */
160     if ( line->vertical && target->vertical ) return 0; /* vertical parallels */
161     if ( !line->vertical &&  !target->vertical )
162     if ( line->m_4096 == target->m_4096 ) return 0; /* non-vertical parallels */
163     /* right now only one thing is supported: line horizontal */
164     if ( line->m_4096 == 0 && line->vertical == 0 ) {
165         pos->y = line->n;
166         if ( target->vertical )
167             pos->x = target->x;
168         else
169             pos->x = (( pos->y - target->n )<<12) / target->m_4096;
170         return 1;
171     }
172     if ( line->vertical ) {
173         if ( target->vertical ) return 0;
174         pos->x = line->x;
175         pos->y = ((target->m_4096 * pos->x)>>12) + target->n;
176         return 1;
177     }
178     if ( target->vertical ) {
179         printf( "line_intersect: line non-vertical and target vertical not supported yet\n" );
180         return 1;
181     }
182     /* compute if both lines are neither vertical nor horizontal */
183     pos->x = (( line->n - target->n )<<12) / ( target->m_4096 - line->m_4096 );
184     pos->y = ((line->m_4096 * pos->x)>>12) + line->n;
185     return 1;
186 }
187 
188 /*
189 ====================================================================
190 Intersect line pos+t*v with circle (x+m)�=r�
191 Important length of v MUST be 1.
192 Return Value: True if intersecting, Intersecting points
193 ====================================================================
194 */
circle_intersect(Vector m,int r,Vector pos,Vector v,Vector * t1,Vector * t2)195 int circle_intersect( Vector m, int r, Vector pos, Vector v, Vector *t1, Vector *t2 )
196 {
197     Vector delta = { pos.x - m.x, pos.y - m.y };
198     float  delta_v = delta.x * v.x + delta.y * v.y;
199     float dis = delta_v * delta_v + r * r - ( delta.x * delta.x + delta.y * delta.y );
200     float t;
201 
202     if ( dis < 0 ) {
203 #ifdef WITH_BUG_REPORT
204 		sprintf( circle_msg, "Diskriminante < 0" );
205 #endif
206 		return 0;
207 	}
208 	dis = sqrt( dis );
209 
210     t = -delta_v + dis;
211     t1->x = pos.x + t * v.x; t1->y = pos.y + t * v.y;
212     t = -delta_v - dis;
213     t2->x = pos.x + t * v.x; t2->y = pos.y + t * v.y;
214 #ifdef WITH_BUG_REPORT
215 	sprintf( circle_msg, "Intersection points: (%4.2f,%4.2f), (%4.2f,%4.2f)", t1->x, t1->y, t2->x, t2->y );
216 #endif
217     return 1;
218 }
219 
220 /* convert vector to angle/2 0-180 and vice versa */
221 static Vector impact_vectors[180]; /* clockwise impact vectors in 2 degree steps */
222 
init_angles(void)223 void init_angles( void )
224 {
225 	int i;
226 
227 	/* create vectors for all degrees in 2� steps */
228 	for ( i = 0; i < 180; i++ ) {
229 		impact_vectors[i].x = cos( 6.28 * i / 180 );
230 		impact_vectors[i].y = sin( 6.28 * i / 180 );
231 	}
232 }
233 
vec2angle(Vector * vec)234 int vec2angle( Vector *vec )
235 {
236 	int degrees = 0;
237 
238 	/* translate impact vector (src-center) into degrees
239 	 * (0�: horizontally right, clockwise going) */
240 	if ( vec->x == 0 )
241 		degrees = 90; /* basically impossible as we mask this out */
242 	else
243 		degrees = (int)(360 * atan( (double)(fabs(vec->y))/fabs(vec->x) ) / 6.28);
244 	/* get the proper quartal */
245 	if ( vec->x > 0 ) {
246 		if ( vec->y < 0 )
247 			degrees = 360 - degrees;
248 	}
249 	else {
250 		if ( vec->y >= 0 )
251 			degrees = 180 - degrees;
252 		else
253 			degrees = 180 + degrees;
254 	}
255 
256 	return degrees/2;
257 }
258 
angle2vec(int angle,Vector * vec)259 void angle2vec( int angle, Vector *vec )
260 {
261 	vec->x = 0;
262 	vec->y = 0;
263 
264 	if ( angle < 0 ) return;
265 	if ( angle > 179 ) return;
266 
267 	*vec = impact_vectors[angle];
268 }
269 
270 
271