]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - libs/math/line.h
GTK: wrap gtk_widget_set_size_request
[xonotic/netradiant.git] / libs / math / line.h
1 /*
2    Copyright (C) 2001-2006, William Joseph.
3    All Rights Reserved.
4
5    This file is part of GtkRadiant.
6
7    GtkRadiant is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    GtkRadiant is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GtkRadiant; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 #if !defined( INCLUDED_MATH_LINE_H )
23 #define INCLUDED_MATH_LINE_H
24
25 /// \file
26 /// \brief Line data types and related operations.
27
28 #include "math/vector.h"
29 #include "math/plane.h"
30
31 /// \brief A line segment defined by a start point and and end point.
32 class Line
33 {
34 public:
35 Vector3 start, end;
36
37 Line(){
38 }
39 Line( const Vector3& start_, const Vector3& end_ ) : start( start_ ), end( end_ ){
40 }
41 };
42
43 inline Vector3 line_closest_point( const Line& line, const Vector3& point ){
44         Vector3 v = line.end - line.start;
45         Vector3 w = point - line.start;
46
47         double c1 = vector3_dot( w,v );
48         if ( c1 <= 0 ) {
49                 return line.start;
50         }
51
52         double c2 = vector3_dot( v,v );
53         if ( c2 <= c1 ) {
54                 return line.end;
55         }
56
57         return Vector3( line.start + v * ( c1 / c2 ) );
58 }
59
60
61 class Segment
62 {
63 public:
64 Vector3 origin, extents;
65
66 Segment(){
67 }
68 Segment( const Vector3& origin_, const Vector3& extents_ ) :
69         origin( origin_ ), extents( extents_ ){
70 }
71 };
72
73
74 inline Segment segment_for_startend( const Vector3& start, const Vector3& end ){
75         Segment segment;
76         segment.origin = vector3_mid( start, end );
77         segment.extents = vector3_subtracted( end, segment.origin );
78         return segment;
79 }
80
81 inline unsigned int segment_classify_plane( const Segment& segment, const Plane3& plane ){
82         double distance_origin = vector3_dot( plane.normal(), segment.origin ) + plane.dist();
83
84         if ( fabs( distance_origin ) < fabs( vector3_dot( plane.normal(), segment.extents ) ) ) {
85                 return 1; // partially inside
86         }
87         else if ( distance_origin < 0 ) {
88                 return 2; // totally inside
89         }
90         return 0; // totally outside
91 }
92
93
94 class Ray
95 {
96 public:
97 Vector3 origin, direction;
98
99 Ray(){
100 }
101 Ray( const Vector3& origin_, const Vector3& direction_ ) :
102         origin( origin_ ), direction( direction_ ){
103 }
104 };
105
106 inline Ray ray_for_points( const Vector3& origin, const Vector3& p2 ){
107         return Ray( origin, vector3_normalised( vector3_subtracted( p2, origin ) ) );
108 }
109
110 inline void ray_transform( Ray& ray, const Matrix4& matrix ){
111         matrix4_transform_point( matrix, ray.origin );
112         matrix4_transform_direction( matrix, ray.direction );
113 }
114
115 // closest-point-on-line
116 inline double ray_squared_distance_to_point( const Ray& ray, const Vector3& point ){
117         return vector3_length_squared(
118                            vector3_subtracted(
119                                    point,
120                                    vector3_added(
121                                            ray.origin,
122                                            vector3_scaled(
123                                                    ray.direction,
124                                                    vector3_dot(
125                                                            vector3_subtracted( point, ray.origin ),
126                                                            ray.direction
127                                                            )
128                                                    )
129                                            )
130                                    )
131                            );
132 }
133
134 inline double ray_distance_to_plane( const Ray& ray, const Plane3& plane ){
135         return -( vector3_dot( plane.normal(), ray.origin ) - plane.dist() ) / vector3_dot( ray.direction, plane.normal() );
136 }
137
138 #endif