File: plane.c

package info (click to toggle)
mccode 3.5.19%2Bds5-2
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 1,113,256 kB
  • sloc: ansic: 40,697; python: 25,137; yacc: 8,438; sh: 5,405; javascript: 4,596; lex: 1,632; cpp: 742; perl: 296; lisp: 273; makefile: 226; fortran: 132
file content (132 lines) | stat: -rw-r--r-- 4,364 bytes parent folder | download
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
/****************************************************************************
*
* McStas, neutron ray-tracing package
*         Copyright 1997-2006, All rights reserved
*         Risoe National Laboratory, Roskilde, Denmark
*         Institut Laue Langevin, Grenoble, France
*
* Library: plane.c
*
* %Identification
* Written by: Hal Lee
* Date: July, 2023
* Origin: ESS
* Release: McStas 2.7x, 3.1x
* Version: $Revision$
*
* plane geometry and intersection functions
*
* Usage: within SHARE
* %include "plane"
*
****************************************************************************/

#ifndef PLANE_H
#include "plane.h"
#endif

#ifndef PLANE_C
#define PLANE_C

//Calculates signed distance of a point to a plane defined by its normal and point on plane
//returns positive value if point is at the normal vector side of the plane
//returns positive value if point is behind the normal vector side of the plane
//returns 0 if point is on the plane
double point_to_plane_signed_distance(Coords point, Coords plane_normal, Coords plane_point) {
	//+ve = point at +ve side of normal 
	//  0 = point on plane 
	//-ve = point at -ve side of normal 

	double dd = -coords_sp(plane_normal, coords_sub(plane_point, point));

	return dd;

}

//calculate line-plane intersect
//input: position (line_p) and velocity (line_v), plane normal and point on plane, maximum normal distance from plane to be considered on plane
//output: user passes pointers to receive dt, dp, point_direction between position line_p to intersect
//returns 1 if line intersects plane, 0 if not
int line_plane_intersect(Coords line_p, Coords line_v, Coords plane_normal, Coords plane_point, double maximum_on_plane_distance, 
		double *dt, Coords *d_intersect_point) 
{
	
	double max_on_plane_d = fabs(maximum_on_plane_distance) > DBL_EPSILON ? fabs(maximum_on_plane_distance) : DBL_EPSILON;
	
	double n_dot_v = coords_sp(plane_normal, line_v); 

	if (fabs(n_dot_v) < DBL_EPSILON) {
		//v parallel to plane
		return 0;
	}
	
	double n_dot_dp = point_to_plane_signed_distance(line_p, plane_normal, plane_point);
	
	if (fabs(n_dot_dp) <= max_on_plane_d) {
		(*d_intersect_point).x = 0; 
		(*d_intersect_point).y = 0; 
		(*d_intersect_point).z = 0; 
		*dt = 0; 
	}
	else {
		(*d_intersect_point).x = line_v.x * (-n_dot_dp) / n_dot_v; 
		(*d_intersect_point).y = line_v.y * (-n_dot_dp) / n_dot_v; 
		(*d_intersect_point).z = line_v.z * (-n_dot_dp) / n_dot_v; 
		*dt = -n_dot_dp / n_dot_v; 
	}
}

//rotate a plane around a rotation axis by an angle, right hand rule applies
//returns 1 if operation succeed, 0 if not
int rotate_plane(Coords plane_normal_in, Coords plane_point_in, Coords rot_axis, double angle_in_degree, Coords *plane_normal_out, Coords *plane_point_out) {
	if (coords_len(rot_axis) < DBL_EPSILON)
		return 0;
	coords_norm(&(rot_axis));
	rotate( plane_normal_out->x, plane_normal_out->y, plane_normal_out->z,
			plane_normal_in.x, plane_normal_in.y, plane_normal_in.z, 
			angle_in_degree * DEG2RAD, 
			rot_axis.x, rot_axis.y, rot_axis.z);
	rotate( plane_point_out->x, plane_point_out->y, plane_point_out->z,
			plane_point_in.x, plane_point_in.y, plane_point_in.z, 
			angle_in_degree * DEG2RAD, 
			rot_axis.x, rot_axis.y, rot_axis.z);
	return 1;
}

/*********/
/* Tools */
/*********/
//Calculate the determinant of a 3x3 matrix
double det3x3(	double a11, double a12, double a13,
				double a21, double a22, double a23,
				double a31, double a32, double a33) 
{
	return    a11 * (a22 * a33 - a32 * a23)
			+ a21 * (a32 * a13 - a12 * a33)
			+ a31 * (a12 * a23 - a22 * a13);
}

//Find the vertex of three planes each defined by a normal and a point on the plane
//returns 1 if succeed, 0 if any two of the three faces are parallel
int getVertexOfThreePlanes(Coords n1,Coords p1, Coords n2,Coords p2, Coords n3,Coords p3, Coords *v) {
	double denom = det3x3(	n1.x, n1.y, n1.z, 
							n2.x, n2.y, n2.z, 
							n3.x, n3.y, n3.z);
	if (fabs(denom) < DBL_EPSILON) return 0;
	double 	d1 = coords_sp(n1,p1),
			d2 = coords_sp(n2,p2),
			d3 = coords_sp(n3,p3);
	(*v).x =  det3x3(	d1, n1.y, n1.z, 
						d2, n2.y, n2.z, 
						d3, n3.y, n3.z)/denom;
	(*v).y =  det3x3(	n1.x, d1, n1.z, 
						n2.x, d2, n2.z, 
						n3.x, d3, n3.z)/denom;
	(*v).z =  det3x3(	n1.x, n1.y, d1, 
						n2.x, n2.y, d2, 
						n3.x, n3.y, d3)/denom;
	return 1;
}

#endif //end of PLANE_C
/* end of plane.c */