1/*
2 * Copyright 2006-2009, Haiku.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Stephan Aßmus <superstippi@gmx.de>
7 */
8
9#include "support.h"
10
11#include <math.h>
12#include <stdio.h>
13#include <string.h>
14
15#include <DataIO.h>
16#include <Point.h>
17#include <String.h>
18
19
20// point_line_distance
21double
22point_line_distance(double x1, double y1, double x2, double y2, double x,
23	double y)
24{
25	double dx = x2 - x1;
26	double dy = y2 - y1;
27	return ((x - x2) * dy - (y - y2) * dx) / sqrt(dx * dx + dy * dy);
28}
29
30
31// point_line_distance
32double
33point_line_distance(BPoint point, BPoint pa, BPoint pb)
34{
35	// first figure out if point is between segment start and end points
36	double a = point_point_distance(point, pb);
37	double b = point_point_distance(point, pa);
38	double c = point_point_distance(pa, pb);
39
40	float currentDist = min_c(a, b);
41
42	if (a > 0.0 && b > 0.0) {
43		double alpha = acos((b*b + c*c - a*a) / (2*b*c));
44		double beta = acos((a*a + c*c - b*b) / (2*a*c));
45
46		if (alpha <= M_PI_2 && beta <= M_PI_2) {
47			currentDist = fabs(point_line_distance(pa.x, pa.y, pb.x, pb.y,
48				point.x, point.y));
49		}
50	}
51
52	return currentDist;
53}
54
55
56// calc_angle
57double
58calc_angle(BPoint origin, BPoint from, BPoint to, bool degree)
59{
60	double angle = 0.0;
61
62	double d = point_line_distance(from.x, from.y, origin.x, origin.y,
63		to.x, to.y);
64	if (d != 0.0) {
65		double a = point_point_distance(from, to);
66		double b = point_point_distance(from, origin);
67		double c = point_point_distance(to, origin);
68		if (a > 0.0 && b > 0.0 && c > 0.0) {
69			angle = acos((b*b + c*c - a*a) / (2.0*b*c));
70
71			if (d < 0.0)
72				angle = -angle;
73
74			if (degree)
75				angle = angle * 180.0 / M_PI;
76		}
77	}
78	return angle;
79}
80
81
82// write_string
83status_t
84write_string(BPositionIO* stream, BString& string)
85{
86	if (!stream)
87		return B_BAD_VALUE;
88
89	ssize_t written = stream->Write(string.String(), string.Length());
90	if (written > B_OK && written < string.Length())
91		written = B_ERROR;
92	string.SetTo("");
93	return written;
94}
95
96
97// append_float
98void
99append_float(BString& string, float n, int32 maxDigits)
100{
101	int32 rounded = n >= 0.0 ? (int32)fabs(floorf(n)) : (int32)fabs(ceilf(n));
102
103	if (n < 0.0) {
104		string << "-";
105		n *= -1.0;
106	}
107	string << rounded;
108
109	if ((float)rounded != n) {
110		// find out how many digits remain
111		n = n - rounded;
112		rounded = (int32)(n * pow(10, maxDigits));
113		char tmp[maxDigits + 1];
114		sprintf(tmp, "%0*" B_PRId32, (int)maxDigits, rounded);
115		tmp[maxDigits] = 0;
116		int32 digits = strlen(tmp);
117		for (int32 i = strlen(tmp) - 1; i >= 0; i--) {
118			if (tmp[i] == '0')
119				digits--;
120			else
121				break;
122		}
123		// write after decimal
124		if (digits > 0) {
125			string << ".";
126			for (int32 i = 0; i < digits; i++) {
127				string << tmp[i];
128			}
129		}
130	}
131}
132
133
134//// gauss
135//double
136//gauss(double f)
137//{
138//	// this aint' a real gauss function
139///*	if (f >= -1.0 && f <= 1.0) {
140//		if (f < -0.5) {
141//			f = -1.0 - f;
142//			return (2.0 * f*f);
143//		}
144//
145//		if (f < 0.5)
146//			return (1.0 - 2.0 * f*f);
147//
148//		f = 1.0 - f;
149//		return (2.0 * f*f);
150//	}*/
151//	if (f > 0.0) {
152//		if (f < 0.5)
153//			return (1.0 - 2.0 * f*f);
154//
155//		f = 1.0 - f;
156//		return (2.0 * f*f);
157//	}
158//	return 1.0;
159//}
160