File: mathfuncs.c

package info (click to toggle)
lbreakouthd 1.2-2
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 9,908 kB
  • sloc: cpp: 6,527; ansic: 5,444; sh: 4,755; makefile: 247; sed: 16
file content (262 lines) | stat: -rw-r--r-- 8,030 bytes parent folder | download | duplicates (2)
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
/***************************************************************************
                          mathfuncs.c  -  description
                             -------------------
    begin                : Thu Sep 6 2001
    copyright            : (C) 2001 by Michael Speck
    email                : kulkanie@gmx.net
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 3 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include "gamedefs.h"
#include "mathfuncs.h"

/*
====================================================================
Return vector struct with the specified coordinates.
====================================================================
*/
Vector vector_get( double x, double y )
{
    Vector v = { x, y };
    return v;
}
/*
====================================================================
Give vector the normed length of 1.
====================================================================
*/
void vector_norm( Vector *v )
{
    double length;
    if ( v->x == 0 && v->y == 0 ) return; /* NULL vector may not be normed */
    length = sqrt( v->x * v->x + v->y * v->y );
    v->x /= length;
    v->y /= length;
}
/*
====================================================================
Return monotony of vector. If vertical return 0
====================================================================
*/
double vector_monotony( Vector v )
{
    if ( v.x == 0 ) return 0;
    return v.y / v.x;
}
/*
====================================================================
Set length of a vector.
====================================================================
*/
void vector_set_length( Vector *v, double length )
{
    vector_norm( v );
    v->x *= length; v->y *= length;
}

/*
====================================================================
Initiate a line struct.
====================================================================
*/
void line_set( Line *line, double x, double y, double m )
{
    line->vertical = 0;
    line->m = m;
    line->n = y - m*x;
}
void line_set_vert( Line *line, double x )
{
    line->vertical = 1;
    line->x = x;
}
void line_set_hori( Line *line, double y )
{
    line->vertical = 0;
    line->m = 0;
    line->n = y;
}
/*
====================================================================
Intersect lines and set 'pos' to intersecting point.
Return Value: True if lines intersect.
====================================================================
*/
int line_intersect( Line *line, Line *target, Coord *pos )
{
    /* reset pos */
    pos->x = pos->y = 0;
    /* if lines are parallel return False */
    if ( line->vertical && target->vertical ) return 0; /* vertical parallels */ 
    if ( !line->vertical &&  !target->vertical && line->m == target->m ) return 0; /* non-vertical parallels */
    /* right now only one thing is supported: line horizontal */
    if ( line->m == 0 && line->vertical == 0 ) {
        pos->y = line->n;
        if ( target->vertical )
            pos->x = target->x;
        else
            pos->x = ( pos->y - target->n ) / target->m;
        return 1;
    }
    if ( line->vertical ) {
        if ( target->vertical ) return 0;
        pos->x = line->x;
        pos->y = target->m * pos->x + target->n;
        return 1;
    }
    if ( target->vertical ) {
        printf( "line_intersect: line non-vertical and target vertical not supported yet\n" );
        return 1;
    }
    /* compute if both lines are neither vertical nor horizontal */
    pos->x = ( line->n - target->n ) / ( target->m - line->m );
    pos->y = line->m * pos->x + line->n;
    return 1;
}

/*
====================================================================
Initiate a line struct.
====================================================================
*/
void iline_set( ILine *line, int x, int y, int m_4096 )
{
    line->vertical = 0;
    line->m_4096 = m_4096;
    line->n = y - ((m_4096*x)>>12);
}
void iline_set_vert( ILine *line, int x )
{
    line->vertical = 1;
    line->x = x;
}
void iline_set_hori( ILine *line, int y )
{
    line->vertical = 0;
    line->m_4096 = 0;
    line->n = y;
}
/*
====================================================================
Intersect lines and set 'pos' to intersecting point.
Return Value: True if lines intersect.
====================================================================
*/
int iline_intersect( ILine *line, ILine *target, ICoord *pos )
{
    /* reset pos */
    pos->x = pos->y = 0;
    /* if lines are parallel return False */
    if ( line->vertical && target->vertical ) return 0; /* vertical parallels */ 
    if ( !line->vertical &&  !target->vertical )
    if ( line->m_4096 == target->m_4096 ) return 0; /* non-vertical parallels */
    /* right now only one thing is supported: line horizontal */
    if ( line->m_4096 == 0 && line->vertical == 0 ) {
        pos->y = line->n;
        if ( target->vertical )
            pos->x = target->x;
        else
            pos->x = (( pos->y - target->n )<<12) / target->m_4096;
        return 1;
    }
    if ( line->vertical ) {
        if ( target->vertical ) return 0;
        pos->x = line->x;
        pos->y = ((target->m_4096 * pos->x)>>12) + target->n;
        return 1;
    }
    if ( target->vertical ) {
        printf( "line_intersect: line non-vertical and target vertical not supported yet\n" );
        return 1;
    }
    /* compute if both lines are neither vertical nor horizontal */
    pos->x = (( line->n - target->n )<<12) / ( target->m_4096 - line->m_4096 );
    pos->y = ((line->m_4096 * pos->x)>>12) + line->n;
    return 1;
}

/*
====================================================================
Intersect line pos+t*v with circle (x+m)�=r�
Important length of v MUST be 1.
Return Value: True if intersecting, Intersecting points
====================================================================
*/
int circle_intersect( Vector m, int r, Vector pos, Vector v, Vector *t1, Vector *t2 )
{
    Vector delta = { pos.x - m.x, pos.y - m.y };
    double  delta_v = delta.x * v.x + delta.y * v.y;
    double dis = delta_v * delta_v + r * r - ( delta.x * delta.x + delta.y * delta.y );
    double t;

    if (dis < 0)
        return 0;

    dis = sqrt(dis);

    t = -delta_v + dis;
    t1->x = pos.x + t * v.x; t1->y = pos.y + t * v.y;
    t = -delta_v - dis;
    t2->x = pos.x + t * v.x; t2->y = pos.y + t * v.y;
    return 1;
}

/* convert vector to angle/2 0-180 and vice versa */
static Vector impact_vectors[180]; /* clockwise impact vectors in 2 degree steps */

void init_angles( void )
{
	int i;
	
	/* create vectors for all degrees in 2� steps */
	for ( i = 0; i < 180; i++ ) {
		impact_vectors[i].x = cos( 6.28 * i / 180 );
		impact_vectors[i].y = sin( 6.28 * i / 180 );
	}
}

int vec2angle( Vector *vec )
{
	int degrees = 0;
	
	/* translate impact vector (src-center) into degrees 
	 * (0�: horizontally right, clockwise going) */
	if ( vec->x == 0 )
		degrees = 90; /* basically impossible as we mask this out */
	else
		degrees = (int)(360 * atan( (double)(fabs(vec->y))/fabs(vec->x) ) / 6.28);
	/* get the proper quartal */
	if ( vec->x > 0 ) {
		if ( vec->y < 0 )
			degrees = 360 - degrees;
	}
	else {
		if ( vec->y >= 0 )
			degrees = 180 - degrees;
		else
			degrees = 180 + degrees;
	}

	return degrees/2;
}

void angle2vec( int angle, Vector *vec )
{
	vec->x = 0; 
	vec->y = 0;

	if ( angle < 0 ) return;
	if ( angle > 179 ) return;

	*vec = impact_vectors[angle];
}