xcoll 0.5.4__py3-none-any.whl → 0.5.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of xcoll might be problematic. Click here for more details.
- xcoll/__init__.py +12 -3
- xcoll/beam_elements/__init__.py +2 -0
- xcoll/beam_elements/base.py +28 -0
- xcoll/colldb.py +2 -3
- xcoll/general.py +1 -1
- xcoll/initial_distribution.py +5 -6
- xcoll/install.py +19 -163
- xcoll/line_tools.py +286 -62
- {xcoll-0.5.4.dist-info → xcoll-0.5.6.dist-info}/METADATA +1 -1
- {xcoll-0.5.4.dist-info → xcoll-0.5.6.dist-info}/RECORD +13 -14
- xcoll/scattering_routines/geometry/temp.c +0 -953
- {xcoll-0.5.4.dist-info → xcoll-0.5.6.dist-info}/LICENSE +0 -0
- {xcoll-0.5.4.dist-info → xcoll-0.5.6.dist-info}/NOTICE +0 -0
- {xcoll-0.5.4.dist-info → xcoll-0.5.6.dist-info}/WHEEL +0 -0
|
@@ -1,953 +0,0 @@
|
|
|
1
|
-
#include <stdint.h>
|
|
2
|
-
#ifndef XOBJ_TYPEDEF_GeomCInit
|
|
3
|
-
#define XOBJ_TYPEDEF_GeomCInit
|
|
4
|
-
typedef struct GeomCInit_s * GeomCInit;
|
|
5
|
-
static inline GeomCInit GeomCInit_getp(GeomCInit restrict obj){
|
|
6
|
-
int64_t offset=0;
|
|
7
|
-
return (GeomCInit)(( char*) obj+offset);
|
|
8
|
-
}
|
|
9
|
-
#endif
|
|
10
|
-
// copyright ############################### #
|
|
11
|
-
// This file is part of the Xcoll package. #
|
|
12
|
-
// Copyright (c) CERN, 2024. #
|
|
13
|
-
// ######################################### #
|
|
14
|
-
|
|
15
|
-
#ifndef XCOLL_GEOM_DEFINES_H
|
|
16
|
-
#define XCOLL_GEOM_DEFINES_H
|
|
17
|
-
#include <math.h>
|
|
18
|
-
#include <stdio.h>
|
|
19
|
-
#include <stdint.h>
|
|
20
|
-
#include <stdlib.h>
|
|
21
|
-
|
|
22
|
-
#define XC_EPSILON 1.e-12
|
|
23
|
-
#define XC_S_MAX 1.e21
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
#endif /* XCOLL_GEOM_DEFINES_H */
|
|
27
|
-
// copyright ############################### #
|
|
28
|
-
// This file is part of the Xcoll package. #
|
|
29
|
-
// Copyright (c) CERN, 2024. #
|
|
30
|
-
// ######################################### #
|
|
31
|
-
|
|
32
|
-
#ifndef XCOLL_GEOM_SORT_H
|
|
33
|
-
#define XCOLL_GEOM_SORT_H
|
|
34
|
-
|
|
35
|
-
#pragma GCC diagnostic push
|
|
36
|
-
#pragma GCC diagnostic ignored "-Warray-bounds"
|
|
37
|
-
|
|
38
|
-
#ifdef MAX
|
|
39
|
-
#undef MAX
|
|
40
|
-
#pragma message ("Xcoll geometry: Compiler macro MAX redefined")
|
|
41
|
-
#endif
|
|
42
|
-
#define MAX(x, y) ({const __typeof__ (x) _x = (x); \
|
|
43
|
-
const __typeof__ (y) _y = (y); \
|
|
44
|
-
_x > _y ? _x : _y; })
|
|
45
|
-
#ifdef MIN
|
|
46
|
-
#undef MIN
|
|
47
|
-
#pragma message ("Xcoll geometry: Compiler macro MIN redefined")
|
|
48
|
-
#endif
|
|
49
|
-
#define MIN(x, y) ({const __typeof__ (x) _x = (x); \
|
|
50
|
-
const __typeof__ (y) _y = (y); \
|
|
51
|
-
_x < _y ? _x : _y; })
|
|
52
|
-
#ifdef SWAP
|
|
53
|
-
#error "Xcoll geometry: Compiler macro SWAP already defined!"
|
|
54
|
-
#endif
|
|
55
|
-
#define SWAP(d,x,y) ({const __typeof__(*d) _x = MIN(d[x], d[y]); \
|
|
56
|
-
const __typeof__(*d) _y = MAX(d[x], d[y]); \
|
|
57
|
-
d[x] = _x; d[y] = _y; })
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
// Fast methods
|
|
61
|
-
// ------------
|
|
62
|
-
|
|
63
|
-
static inline void sort_array_of_2_double(double* d){
|
|
64
|
-
SWAP(d, 0, 1);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
static inline void sort_array_of_3_double(double* d){
|
|
68
|
-
SWAP(d, 0, 1); SWAP(d, 1, 2); SWAP(d, 0, 1);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
static inline void sort_array_of_4_double(double* d){
|
|
72
|
-
SWAP(d, 0, 1); SWAP(d, 2, 3); SWAP(d, 0, 2); SWAP(d, 1, 3); SWAP(d, 1, 2);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
static inline void sort_array_of_5_double(double* d){
|
|
76
|
-
SWAP(d, 0, 1); SWAP(d, 3, 4); SWAP(d, 2, 4); SWAP(d, 2, 3); SWAP(d, 1, 4);
|
|
77
|
-
SWAP(d, 0, 3); SWAP(d, 0, 2); SWAP(d, 1, 3); SWAP(d, 1, 2);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
static inline void sort_array_of_6_double(double* d){
|
|
81
|
-
SWAP(d, 1, 2); SWAP(d, 4, 5); SWAP(d, 0, 2); SWAP(d, 3, 5); SWAP(d, 0, 1);
|
|
82
|
-
SWAP(d, 3, 4); SWAP(d, 1, 4); SWAP(d, 0, 3); SWAP(d, 2, 5); SWAP(d, 1, 3);
|
|
83
|
-
SWAP(d, 2, 4); SWAP(d, 2, 3);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
static inline void sort_array_of_7_double(double* d){
|
|
87
|
-
SWAP(d, 1, 2); SWAP(d, 3, 4); SWAP(d, 5, 6); SWAP(d, 0, 2); SWAP(d, 3, 5);
|
|
88
|
-
SWAP(d, 4, 6); SWAP(d, 0, 1); SWAP(d, 4, 5); SWAP(d, 2, 6); SWAP(d, 0, 4);
|
|
89
|
-
SWAP(d, 1, 5); SWAP(d, 0, 3); SWAP(d, 2, 5); SWAP(d, 1, 3); SWAP(d, 2, 4);
|
|
90
|
-
SWAP(d, 2, 3);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
static inline void sort_array_of_8_double(double* d){
|
|
94
|
-
SWAP(d, 0, 1); SWAP(d, 2, 3); SWAP(d, 4, 5); SWAP(d, 6, 7); SWAP(d, 0, 2);
|
|
95
|
-
SWAP(d, 1, 3); SWAP(d, 4, 6); SWAP(d, 5, 7); SWAP(d, 1, 2); SWAP(d, 5, 6);
|
|
96
|
-
SWAP(d, 0, 4); SWAP(d, 3, 7); SWAP(d, 1, 5); SWAP(d, 2, 6); SWAP(d, 1, 4);
|
|
97
|
-
SWAP(d, 3, 6); SWAP(d, 2, 4); SWAP(d, 3, 5); SWAP(d, 3, 4);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
static inline void sort_array_of_2_int64(int64_t* d){
|
|
101
|
-
SWAP(d, 0, 1);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
static inline void sort_array_of_3_int64(int64_t* d){
|
|
105
|
-
SWAP(d, 0, 1); SWAP(d, 1, 2); SWAP(d, 0, 1);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
static inline void sort_array_of_4_int64(int64_t* d){
|
|
109
|
-
SWAP(d, 0, 1); SWAP(d, 2, 3); SWAP(d, 0, 2); SWAP(d, 1, 3); SWAP(d, 1, 2);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
static inline void sort_array_of_5_int64(int64_t* d){
|
|
113
|
-
SWAP(d, 0, 1); SWAP(d, 3, 4); SWAP(d, 2, 4); SWAP(d, 2, 3); SWAP(d, 1, 4);
|
|
114
|
-
SWAP(d, 0, 3); SWAP(d, 0, 2); SWAP(d, 1, 3); SWAP(d, 1, 2);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
static inline void sort_array_of_6_int64(int64_t* d){
|
|
118
|
-
SWAP(d, 1, 2); SWAP(d, 4, 5); SWAP(d, 0, 2); SWAP(d, 3, 5); SWAP(d, 0, 1);
|
|
119
|
-
SWAP(d, 3, 4); SWAP(d, 1, 4); SWAP(d, 0, 3); SWAP(d, 2, 5); SWAP(d, 1, 3);
|
|
120
|
-
SWAP(d, 2, 4); SWAP(d, 2, 3);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
static inline void sort_array_of_7_int64(int64_t* d){
|
|
124
|
-
SWAP(d, 1, 2); SWAP(d, 3, 4); SWAP(d, 5, 6); SWAP(d, 0, 2); SWAP(d, 3, 5);
|
|
125
|
-
SWAP(d, 4, 6); SWAP(d, 0, 1); SWAP(d, 4, 5); SWAP(d, 2, 6); SWAP(d, 0, 4);
|
|
126
|
-
SWAP(d, 1, 5); SWAP(d, 0, 3); SWAP(d, 2, 5); SWAP(d, 1, 3); SWAP(d, 2, 4);
|
|
127
|
-
SWAP(d, 2, 3);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
static inline void sort_array_of_8_int64(int64_t* d){
|
|
131
|
-
SWAP(d, 0, 1); SWAP(d, 2, 3); SWAP(d, 4, 5); SWAP(d, 6, 7); SWAP(d, 0, 2);
|
|
132
|
-
SWAP(d, 1, 3); SWAP(d, 4, 6); SWAP(d, 5, 7); SWAP(d, 1, 2); SWAP(d, 5, 6);
|
|
133
|
-
SWAP(d, 0, 4); SWAP(d, 3, 7); SWAP(d, 1, 5); SWAP(d, 2, 6); SWAP(d, 1, 4);
|
|
134
|
-
SWAP(d, 3, 6); SWAP(d, 2, 4); SWAP(d, 3, 5); SWAP(d, 3, 4);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
// Generic methods
|
|
139
|
-
// ---------------
|
|
140
|
-
|
|
141
|
-
int cmpfunc_double(const void * a, const void * b) {
|
|
142
|
-
return ( *(double*)a - *(double*)b );
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
static inline void sort_array_of_double(double* arr, int64_t length){
|
|
146
|
-
switch(length){
|
|
147
|
-
case 2:
|
|
148
|
-
sort_array_of_2_double(arr);
|
|
149
|
-
break;
|
|
150
|
-
case 3:
|
|
151
|
-
sort_array_of_3_double(arr);
|
|
152
|
-
break;
|
|
153
|
-
case 4:
|
|
154
|
-
sort_array_of_4_double(arr);
|
|
155
|
-
break;
|
|
156
|
-
case 5:
|
|
157
|
-
sort_array_of_5_double(arr);
|
|
158
|
-
break;
|
|
159
|
-
case 6:
|
|
160
|
-
sort_array_of_6_double(arr);
|
|
161
|
-
break;
|
|
162
|
-
case 7:
|
|
163
|
-
sort_array_of_7_double(arr);
|
|
164
|
-
break;
|
|
165
|
-
case 8:
|
|
166
|
-
sort_array_of_8_double(arr);
|
|
167
|
-
break;
|
|
168
|
-
default:
|
|
169
|
-
qsort(arr, length, sizeof(double), cmpfunc_double);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
int cmpfunc_int64(const void * a, const void * b) {
|
|
174
|
-
return ( *(int64_t*)a - *(int64_t*)b );
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
static inline void sort_array_of_int64(int64_t* arr, int64_t length){
|
|
178
|
-
switch(length){
|
|
179
|
-
case 2:
|
|
180
|
-
sort_array_of_2_int64(arr);
|
|
181
|
-
break;
|
|
182
|
-
case 3:
|
|
183
|
-
sort_array_of_3_int64(arr);
|
|
184
|
-
break;
|
|
185
|
-
case 4:
|
|
186
|
-
sort_array_of_4_int64(arr);
|
|
187
|
-
break;
|
|
188
|
-
case 5:
|
|
189
|
-
sort_array_of_5_int64(arr);
|
|
190
|
-
break;
|
|
191
|
-
case 6:
|
|
192
|
-
sort_array_of_6_int64(arr);
|
|
193
|
-
break;
|
|
194
|
-
case 7:
|
|
195
|
-
sort_array_of_7_int64(arr);
|
|
196
|
-
break;
|
|
197
|
-
case 8:
|
|
198
|
-
sort_array_of_8_int64(arr);
|
|
199
|
-
break;
|
|
200
|
-
default:
|
|
201
|
-
qsort(arr, length, sizeof(int64_t), cmpfunc_int64);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
#pragma GCC diagnostic pop
|
|
206
|
-
#endif /* XCOLL_GEOM_SORT_H */
|
|
207
|
-
// copyright ############################### #
|
|
208
|
-
// This file is part of the Xcoll package. #
|
|
209
|
-
// Copyright (c) CERN, 2024. #
|
|
210
|
-
// ######################################### #
|
|
211
|
-
|
|
212
|
-
#ifndef XCOLL_GEOM_METHODS_H
|
|
213
|
-
#define XCOLL_GEOM_METHODS_H
|
|
214
|
-
|
|
215
|
-
// This function calculates the overlap between an array and a given interval.
|
|
216
|
-
// The array comes in pairs of points, e.g. in-out-in-out... or out-in-out-in...
|
|
217
|
-
// IMPORTANT:
|
|
218
|
-
// The array and interval are assumed to be sorted!
|
|
219
|
-
// Furthermore, the array should have one extra slot allocated at the end, in case it needs to be expanded..
|
|
220
|
-
// This is always true for the arrays created by get_s, as we create them with 2*n_segments slots.
|
|
221
|
-
static inline
|
|
222
|
-
void calculate_overlap_array_interval(double* arr, int8_t* length, double* interval){
|
|
223
|
-
if (arr[0] > interval[1]){
|
|
224
|
-
// No overlap
|
|
225
|
-
*length = 0;
|
|
226
|
-
}
|
|
227
|
-
if ((*length)%2 == 1){
|
|
228
|
-
// Special case: last interval of array is open until infinity,
|
|
229
|
-
// so we add an extra point at the end to represent infinity.
|
|
230
|
-
arr[*length] = XC_S_MAX*0.1;
|
|
231
|
-
(*length)++;
|
|
232
|
-
} else if (arr[*length-1] < interval[0]){
|
|
233
|
-
// No overlap
|
|
234
|
-
*length = 0;
|
|
235
|
-
}
|
|
236
|
-
int8_t i_start = 0;
|
|
237
|
-
// Find the start of overlap
|
|
238
|
-
for (int8_t i=0; i<*length; i++){
|
|
239
|
-
if (arr[i] >= interval[0]){
|
|
240
|
-
if (i%2 == 0){
|
|
241
|
-
// This is the first point of overlap
|
|
242
|
-
i_start = i;
|
|
243
|
-
} else {
|
|
244
|
-
// The vertical restriction is the first point of overlap
|
|
245
|
-
i_start = i-1;
|
|
246
|
-
arr[i_start] = interval[0];
|
|
247
|
-
}
|
|
248
|
-
break;
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
// Find the end of overlap
|
|
252
|
-
int8_t i_stop = *length - 1;
|
|
253
|
-
for (int8_t i=0; i<*length; i++){
|
|
254
|
-
if (arr[i] >= interval[1]){
|
|
255
|
-
if (i%2 == 0){
|
|
256
|
-
// The previous point is the last point of overlap
|
|
257
|
-
i_stop = i-1;
|
|
258
|
-
} else {
|
|
259
|
-
// The vertical restriction is the first point of overlap
|
|
260
|
-
i_stop = i;
|
|
261
|
-
arr[i_stop] = interval[1];
|
|
262
|
-
}
|
|
263
|
-
break;
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
*length = i_stop - i_start + 1;
|
|
267
|
-
if (i_start > 0){
|
|
268
|
-
for (int8_t i=0; i<*length; i++){
|
|
269
|
-
arr[i] = arr[i+i_start];
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
#endif /* XCOLL_GEOM_METHODS_H */
|
|
276
|
-
#ifndef XOBJ_TYPEDEF_LineSegment
|
|
277
|
-
#define XOBJ_TYPEDEF_LineSegment
|
|
278
|
-
typedef struct LineSegment_s * LineSegment;
|
|
279
|
-
static inline LineSegment LineSegment_getp(LineSegment restrict obj){
|
|
280
|
-
int64_t offset=0;
|
|
281
|
-
return (LineSegment)(( char*) obj+offset);
|
|
282
|
-
}
|
|
283
|
-
static inline double LineSegment_get_s1(const LineSegment restrict obj){
|
|
284
|
-
int64_t offset=0;
|
|
285
|
-
return *( double*)(( char*) obj+offset);
|
|
286
|
-
}
|
|
287
|
-
static inline void LineSegment_set_s1(LineSegment restrict obj, double value){
|
|
288
|
-
int64_t offset=0;
|
|
289
|
-
*( double*)(( char*) obj+offset)=value;
|
|
290
|
-
}
|
|
291
|
-
static inline double* LineSegment_getp_s1(LineSegment restrict obj){
|
|
292
|
-
int64_t offset=0;
|
|
293
|
-
return ( double*)(( char*) obj+offset);
|
|
294
|
-
}
|
|
295
|
-
static inline double LineSegment_get_x1(const LineSegment restrict obj){
|
|
296
|
-
int64_t offset=0;
|
|
297
|
-
offset+=8;
|
|
298
|
-
return *( double*)(( char*) obj+offset);
|
|
299
|
-
}
|
|
300
|
-
static inline void LineSegment_set_x1(LineSegment restrict obj, double value){
|
|
301
|
-
int64_t offset=0;
|
|
302
|
-
offset+=8;
|
|
303
|
-
*( double*)(( char*) obj+offset)=value;
|
|
304
|
-
}
|
|
305
|
-
static inline double* LineSegment_getp_x1(LineSegment restrict obj){
|
|
306
|
-
int64_t offset=0;
|
|
307
|
-
offset+=8;
|
|
308
|
-
return ( double*)(( char*) obj+offset);
|
|
309
|
-
}
|
|
310
|
-
static inline double LineSegment_get_s2(const LineSegment restrict obj){
|
|
311
|
-
int64_t offset=0;
|
|
312
|
-
offset+=16;
|
|
313
|
-
return *( double*)(( char*) obj+offset);
|
|
314
|
-
}
|
|
315
|
-
static inline void LineSegment_set_s2(LineSegment restrict obj, double value){
|
|
316
|
-
int64_t offset=0;
|
|
317
|
-
offset+=16;
|
|
318
|
-
*( double*)(( char*) obj+offset)=value;
|
|
319
|
-
}
|
|
320
|
-
static inline double* LineSegment_getp_s2(LineSegment restrict obj){
|
|
321
|
-
int64_t offset=0;
|
|
322
|
-
offset+=16;
|
|
323
|
-
return ( double*)(( char*) obj+offset);
|
|
324
|
-
}
|
|
325
|
-
static inline double LineSegment_get_x2(const LineSegment restrict obj){
|
|
326
|
-
int64_t offset=0;
|
|
327
|
-
offset+=24;
|
|
328
|
-
return *( double*)(( char*) obj+offset);
|
|
329
|
-
}
|
|
330
|
-
static inline void LineSegment_set_x2(LineSegment restrict obj, double value){
|
|
331
|
-
int64_t offset=0;
|
|
332
|
-
offset+=24;
|
|
333
|
-
*( double*)(( char*) obj+offset)=value;
|
|
334
|
-
}
|
|
335
|
-
static inline double* LineSegment_getp_x2(LineSegment restrict obj){
|
|
336
|
-
int64_t offset=0;
|
|
337
|
-
offset+=24;
|
|
338
|
-
return ( double*)(( char*) obj+offset);
|
|
339
|
-
}
|
|
340
|
-
#endif
|
|
341
|
-
|
|
342
|
-
static inline
|
|
343
|
-
void LineSegment_crossing_drift(LineSegment seg, int8_t* n_hit, double* s, double s0, double x0, double m){
|
|
344
|
-
// Get segment data
|
|
345
|
-
double s1 = LineSegment_get_s1(seg);
|
|
346
|
-
double x1 = LineSegment_get_x1(seg);
|
|
347
|
-
double s2 = LineSegment_get_s2(seg);
|
|
348
|
-
double x2 = LineSegment_get_x2(seg);
|
|
349
|
-
double denom = (x2 - x1) - (s2 - s1)*m;
|
|
350
|
-
if (fabs(denom) < XC_EPSILON){
|
|
351
|
-
// Trajectory is parallel to the segment
|
|
352
|
-
if (fabs((x0 - x1)/(s0 - s1) - m) < XC_EPSILON){
|
|
353
|
-
// Trajectory overlaps with the segment
|
|
354
|
-
// TODO: This is situational; we should return s1 if get_s_first and current_s if after current_s
|
|
355
|
-
// For now we hit twice (because we go nor IN nor OUT)
|
|
356
|
-
s[*n_hit] = s1;
|
|
357
|
-
(*n_hit)++;
|
|
358
|
-
s[*n_hit] = s2;
|
|
359
|
-
(*n_hit)++;
|
|
360
|
-
} else {
|
|
361
|
-
// No crossing
|
|
362
|
-
return;
|
|
363
|
-
}
|
|
364
|
-
} else {
|
|
365
|
-
double t = (x0 - x1 - (s0 - s1)*m) / denom;
|
|
366
|
-
if (t >= 0 && t <= 1){
|
|
367
|
-
s[*n_hit] = s1*(1-t) + s2*t;
|
|
368
|
-
(*n_hit)++;
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
#ifndef XOBJ_TYPEDEF_HalfOpenLineSegment
|
|
374
|
-
#define XOBJ_TYPEDEF_HalfOpenLineSegment
|
|
375
|
-
typedef struct HalfOpenLineSegment_s * HalfOpenLineSegment;
|
|
376
|
-
static inline HalfOpenLineSegment HalfOpenLineSegment_getp(HalfOpenLineSegment restrict obj){
|
|
377
|
-
int64_t offset=0;
|
|
378
|
-
return (HalfOpenLineSegment)(( char*) obj+offset);
|
|
379
|
-
}
|
|
380
|
-
static inline double HalfOpenLineSegment_get_s(const HalfOpenLineSegment restrict obj){
|
|
381
|
-
int64_t offset=0;
|
|
382
|
-
return *( double*)(( char*) obj+offset);
|
|
383
|
-
}
|
|
384
|
-
static inline void HalfOpenLineSegment_set_s(HalfOpenLineSegment restrict obj, double value){
|
|
385
|
-
int64_t offset=0;
|
|
386
|
-
*( double*)(( char*) obj+offset)=value;
|
|
387
|
-
}
|
|
388
|
-
static inline double* HalfOpenLineSegment_getp_s(HalfOpenLineSegment restrict obj){
|
|
389
|
-
int64_t offset=0;
|
|
390
|
-
return ( double*)(( char*) obj+offset);
|
|
391
|
-
}
|
|
392
|
-
static inline double HalfOpenLineSegment_get_x(const HalfOpenLineSegment restrict obj){
|
|
393
|
-
int64_t offset=0;
|
|
394
|
-
offset+=8;
|
|
395
|
-
return *( double*)(( char*) obj+offset);
|
|
396
|
-
}
|
|
397
|
-
static inline void HalfOpenLineSegment_set_x(HalfOpenLineSegment restrict obj, double value){
|
|
398
|
-
int64_t offset=0;
|
|
399
|
-
offset+=8;
|
|
400
|
-
*( double*)(( char*) obj+offset)=value;
|
|
401
|
-
}
|
|
402
|
-
static inline double* HalfOpenLineSegment_getp_x(HalfOpenLineSegment restrict obj){
|
|
403
|
-
int64_t offset=0;
|
|
404
|
-
offset+=8;
|
|
405
|
-
return ( double*)(( char*) obj+offset);
|
|
406
|
-
}
|
|
407
|
-
static inline double HalfOpenLineSegment_get_t(const HalfOpenLineSegment restrict obj){
|
|
408
|
-
int64_t offset=0;
|
|
409
|
-
offset+=16;
|
|
410
|
-
return *( double*)(( char*) obj+offset);
|
|
411
|
-
}
|
|
412
|
-
static inline void HalfOpenLineSegment_set_t(HalfOpenLineSegment restrict obj, double value){
|
|
413
|
-
int64_t offset=0;
|
|
414
|
-
offset+=16;
|
|
415
|
-
*( double*)(( char*) obj+offset)=value;
|
|
416
|
-
}
|
|
417
|
-
static inline double* HalfOpenLineSegment_getp_t(HalfOpenLineSegment restrict obj){
|
|
418
|
-
int64_t offset=0;
|
|
419
|
-
offset+=16;
|
|
420
|
-
return ( double*)(( char*) obj+offset);
|
|
421
|
-
}
|
|
422
|
-
#endif
|
|
423
|
-
|
|
424
|
-
static inline
|
|
425
|
-
void HalfOpenLineSegment_crossing_drift(HalfOpenLineSegment seg, int8_t* n_hit, double* s, double s0, double x0, double m){
|
|
426
|
-
// Get segment data
|
|
427
|
-
double s1 = HalfOpenLineSegment_get_s(seg);
|
|
428
|
-
double x1 = HalfOpenLineSegment_get_x(seg);
|
|
429
|
-
double s2 = s1 + cos(HalfOpenLineSegment_get_t(seg));
|
|
430
|
-
double x2 = x1 + sin(HalfOpenLineSegment_get_t(seg));
|
|
431
|
-
double denom = (x2 - x1) - (s2 - s1)*m;
|
|
432
|
-
if (fabs(denom) < XC_EPSILON){
|
|
433
|
-
// Trajectory is parallel to the segment
|
|
434
|
-
if (fabs((x0 - x1)/(s0 - s1) - m) < XC_EPSILON){
|
|
435
|
-
// Trajectory overlaps with the segment
|
|
436
|
-
// TODO: This is situational; we should return s1 if get_s_first and current_s if after current_s
|
|
437
|
-
// For now we hit twice (because we go nor IN nor OUT)
|
|
438
|
-
s[*n_hit] = s1;
|
|
439
|
-
(*n_hit)++;
|
|
440
|
-
s[*n_hit] = s2;
|
|
441
|
-
(*n_hit)++;
|
|
442
|
-
} else {
|
|
443
|
-
// No hit
|
|
444
|
-
return;
|
|
445
|
-
}
|
|
446
|
-
} else {
|
|
447
|
-
double t = (x0 - x1 - (s0 - s1)*m) / denom;
|
|
448
|
-
if (t >= 0){ // We do not check for t<=1 as it is a half-open segment
|
|
449
|
-
s[*n_hit] = s1*(1-t) + s2*t;
|
|
450
|
-
(*n_hit)++;
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
#ifndef XOBJ_TYPEDEF_CircularSegment
|
|
456
|
-
#define XOBJ_TYPEDEF_CircularSegment
|
|
457
|
-
typedef struct CircularSegment_s * CircularSegment;
|
|
458
|
-
static inline CircularSegment CircularSegment_getp(CircularSegment restrict obj){
|
|
459
|
-
int64_t offset=0;
|
|
460
|
-
return (CircularSegment)(( char*) obj+offset);
|
|
461
|
-
}
|
|
462
|
-
static inline double CircularSegment_get_R(const CircularSegment restrict obj){
|
|
463
|
-
int64_t offset=0;
|
|
464
|
-
return *( double*)(( char*) obj+offset);
|
|
465
|
-
}
|
|
466
|
-
static inline void CircularSegment_set_R(CircularSegment restrict obj, double value){
|
|
467
|
-
int64_t offset=0;
|
|
468
|
-
*( double*)(( char*) obj+offset)=value;
|
|
469
|
-
}
|
|
470
|
-
static inline double* CircularSegment_getp_R(CircularSegment restrict obj){
|
|
471
|
-
int64_t offset=0;
|
|
472
|
-
return ( double*)(( char*) obj+offset);
|
|
473
|
-
}
|
|
474
|
-
static inline double CircularSegment_get_s(const CircularSegment restrict obj){
|
|
475
|
-
int64_t offset=0;
|
|
476
|
-
offset+=8;
|
|
477
|
-
return *( double*)(( char*) obj+offset);
|
|
478
|
-
}
|
|
479
|
-
static inline void CircularSegment_set_s(CircularSegment restrict obj, double value){
|
|
480
|
-
int64_t offset=0;
|
|
481
|
-
offset+=8;
|
|
482
|
-
*( double*)(( char*) obj+offset)=value;
|
|
483
|
-
}
|
|
484
|
-
static inline double* CircularSegment_getp_s(CircularSegment restrict obj){
|
|
485
|
-
int64_t offset=0;
|
|
486
|
-
offset+=8;
|
|
487
|
-
return ( double*)(( char*) obj+offset);
|
|
488
|
-
}
|
|
489
|
-
static inline double CircularSegment_get_x(const CircularSegment restrict obj){
|
|
490
|
-
int64_t offset=0;
|
|
491
|
-
offset+=16;
|
|
492
|
-
return *( double*)(( char*) obj+offset);
|
|
493
|
-
}
|
|
494
|
-
static inline void CircularSegment_set_x(CircularSegment restrict obj, double value){
|
|
495
|
-
int64_t offset=0;
|
|
496
|
-
offset+=16;
|
|
497
|
-
*( double*)(( char*) obj+offset)=value;
|
|
498
|
-
}
|
|
499
|
-
static inline double* CircularSegment_getp_x(CircularSegment restrict obj){
|
|
500
|
-
int64_t offset=0;
|
|
501
|
-
offset+=16;
|
|
502
|
-
return ( double*)(( char*) obj+offset);
|
|
503
|
-
}
|
|
504
|
-
static inline double CircularSegment_get_t1(const CircularSegment restrict obj){
|
|
505
|
-
int64_t offset=0;
|
|
506
|
-
offset+=24;
|
|
507
|
-
return *( double*)(( char*) obj+offset);
|
|
508
|
-
}
|
|
509
|
-
static inline void CircularSegment_set_t1(CircularSegment restrict obj, double value){
|
|
510
|
-
int64_t offset=0;
|
|
511
|
-
offset+=24;
|
|
512
|
-
*( double*)(( char*) obj+offset)=value;
|
|
513
|
-
}
|
|
514
|
-
static inline double* CircularSegment_getp_t1(CircularSegment restrict obj){
|
|
515
|
-
int64_t offset=0;
|
|
516
|
-
offset+=24;
|
|
517
|
-
return ( double*)(( char*) obj+offset);
|
|
518
|
-
}
|
|
519
|
-
static inline double CircularSegment_get_t2(const CircularSegment restrict obj){
|
|
520
|
-
int64_t offset=0;
|
|
521
|
-
offset+=32;
|
|
522
|
-
return *( double*)(( char*) obj+offset);
|
|
523
|
-
}
|
|
524
|
-
static inline void CircularSegment_set_t2(CircularSegment restrict obj, double value){
|
|
525
|
-
int64_t offset=0;
|
|
526
|
-
offset+=32;
|
|
527
|
-
*( double*)(( char*) obj+offset)=value;
|
|
528
|
-
}
|
|
529
|
-
static inline double* CircularSegment_getp_t2(CircularSegment restrict obj){
|
|
530
|
-
int64_t offset=0;
|
|
531
|
-
offset+=32;
|
|
532
|
-
return ( double*)(( char*) obj+offset);
|
|
533
|
-
}
|
|
534
|
-
#endif
|
|
535
|
-
|
|
536
|
-
static inline
|
|
537
|
-
void CircularSegment_crossing_drift(CircularSegment seg, int8_t* n_hit, double* s, double s0, double x0, double m){
|
|
538
|
-
// Get segment data
|
|
539
|
-
double R = CircularSegment_get_R(seg);
|
|
540
|
-
double sC = CircularSegment_get_s(seg);
|
|
541
|
-
double xC = CircularSegment_get_x(seg);
|
|
542
|
-
double t1 = CircularSegment_get_t1(seg);
|
|
543
|
-
double t2 = CircularSegment_get_t2(seg);
|
|
544
|
-
// Calculate crossings
|
|
545
|
-
int8_t reversed = 0;
|
|
546
|
-
if (t2 < t1){
|
|
547
|
-
reversed = 1;
|
|
548
|
-
}
|
|
549
|
-
double a = 1 + m*m;
|
|
550
|
-
double bb = sC - m*(x0 - xC - m*s0); // This is -b/2 with b from the quadratic formula
|
|
551
|
-
double c = sC*sC + (x0 - xC - m*s0)*(x0 - xC - m*s0) - R*R;
|
|
552
|
-
double disc = bb*bb - a*c; // This is 2*discriminant**2
|
|
553
|
-
if (disc < 0){
|
|
554
|
-
// No crossing
|
|
555
|
-
return;
|
|
556
|
-
}
|
|
557
|
-
for (int8_t i = 0; i < 2; i++) {
|
|
558
|
-
double sgnD = i*2-1; // negative and positive solutions; if multiplicity 2, we add the same solution twice
|
|
559
|
-
double new_s = (bb + sgnD*sqrt(fabs(disc)))/a;
|
|
560
|
-
double new_x = x0 + (new_s - s0)*m;
|
|
561
|
-
double t = atan2(new_x - xC, new_s - sC);
|
|
562
|
-
if (reversed){
|
|
563
|
-
// t2 < t1, so we are looking at the inverted region of angles
|
|
564
|
-
if (t1 >= t || t >= t2){
|
|
565
|
-
s[*n_hit] = new_s;
|
|
566
|
-
(*n_hit)++;
|
|
567
|
-
}
|
|
568
|
-
} else {
|
|
569
|
-
if (t1 <= t && t <= t2){
|
|
570
|
-
s[*n_hit] = new_s;
|
|
571
|
-
(*n_hit)++;
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
#ifndef XOBJ_TYPEDEF_BezierSegment
|
|
578
|
-
#define XOBJ_TYPEDEF_BezierSegment
|
|
579
|
-
typedef struct BezierSegment_s * BezierSegment;
|
|
580
|
-
static inline BezierSegment BezierSegment_getp(BezierSegment restrict obj){
|
|
581
|
-
int64_t offset=0;
|
|
582
|
-
return (BezierSegment)(( char*) obj+offset);
|
|
583
|
-
}
|
|
584
|
-
static inline double BezierSegment_get_s1(const BezierSegment restrict obj){
|
|
585
|
-
int64_t offset=0;
|
|
586
|
-
return *( double*)(( char*) obj+offset);
|
|
587
|
-
}
|
|
588
|
-
static inline void BezierSegment_set_s1(BezierSegment restrict obj, double value){
|
|
589
|
-
int64_t offset=0;
|
|
590
|
-
*( double*)(( char*) obj+offset)=value;
|
|
591
|
-
}
|
|
592
|
-
static inline double* BezierSegment_getp_s1(BezierSegment restrict obj){
|
|
593
|
-
int64_t offset=0;
|
|
594
|
-
return ( double*)(( char*) obj+offset);
|
|
595
|
-
}
|
|
596
|
-
static inline double BezierSegment_get_x1(const BezierSegment restrict obj){
|
|
597
|
-
int64_t offset=0;
|
|
598
|
-
offset+=8;
|
|
599
|
-
return *( double*)(( char*) obj+offset);
|
|
600
|
-
}
|
|
601
|
-
static inline void BezierSegment_set_x1(BezierSegment restrict obj, double value){
|
|
602
|
-
int64_t offset=0;
|
|
603
|
-
offset+=8;
|
|
604
|
-
*( double*)(( char*) obj+offset)=value;
|
|
605
|
-
}
|
|
606
|
-
static inline double* BezierSegment_getp_x1(BezierSegment restrict obj){
|
|
607
|
-
int64_t offset=0;
|
|
608
|
-
offset+=8;
|
|
609
|
-
return ( double*)(( char*) obj+offset);
|
|
610
|
-
}
|
|
611
|
-
static inline double BezierSegment_get_s2(const BezierSegment restrict obj){
|
|
612
|
-
int64_t offset=0;
|
|
613
|
-
offset+=16;
|
|
614
|
-
return *( double*)(( char*) obj+offset);
|
|
615
|
-
}
|
|
616
|
-
static inline void BezierSegment_set_s2(BezierSegment restrict obj, double value){
|
|
617
|
-
int64_t offset=0;
|
|
618
|
-
offset+=16;
|
|
619
|
-
*( double*)(( char*) obj+offset)=value;
|
|
620
|
-
}
|
|
621
|
-
static inline double* BezierSegment_getp_s2(BezierSegment restrict obj){
|
|
622
|
-
int64_t offset=0;
|
|
623
|
-
offset+=16;
|
|
624
|
-
return ( double*)(( char*) obj+offset);
|
|
625
|
-
}
|
|
626
|
-
static inline double BezierSegment_get_x2(const BezierSegment restrict obj){
|
|
627
|
-
int64_t offset=0;
|
|
628
|
-
offset+=24;
|
|
629
|
-
return *( double*)(( char*) obj+offset);
|
|
630
|
-
}
|
|
631
|
-
static inline void BezierSegment_set_x2(BezierSegment restrict obj, double value){
|
|
632
|
-
int64_t offset=0;
|
|
633
|
-
offset+=24;
|
|
634
|
-
*( double*)(( char*) obj+offset)=value;
|
|
635
|
-
}
|
|
636
|
-
static inline double* BezierSegment_getp_x2(BezierSegment restrict obj){
|
|
637
|
-
int64_t offset=0;
|
|
638
|
-
offset+=24;
|
|
639
|
-
return ( double*)(( char*) obj+offset);
|
|
640
|
-
}
|
|
641
|
-
static inline double BezierSegment_get_cs1(const BezierSegment restrict obj){
|
|
642
|
-
int64_t offset=0;
|
|
643
|
-
offset+=32;
|
|
644
|
-
return *( double*)(( char*) obj+offset);
|
|
645
|
-
}
|
|
646
|
-
static inline void BezierSegment_set_cs1(BezierSegment restrict obj, double value){
|
|
647
|
-
int64_t offset=0;
|
|
648
|
-
offset+=32;
|
|
649
|
-
*( double*)(( char*) obj+offset)=value;
|
|
650
|
-
}
|
|
651
|
-
static inline double* BezierSegment_getp_cs1(BezierSegment restrict obj){
|
|
652
|
-
int64_t offset=0;
|
|
653
|
-
offset+=32;
|
|
654
|
-
return ( double*)(( char*) obj+offset);
|
|
655
|
-
}
|
|
656
|
-
static inline double BezierSegment_get_cx1(const BezierSegment restrict obj){
|
|
657
|
-
int64_t offset=0;
|
|
658
|
-
offset+=40;
|
|
659
|
-
return *( double*)(( char*) obj+offset);
|
|
660
|
-
}
|
|
661
|
-
static inline void BezierSegment_set_cx1(BezierSegment restrict obj, double value){
|
|
662
|
-
int64_t offset=0;
|
|
663
|
-
offset+=40;
|
|
664
|
-
*( double*)(( char*) obj+offset)=value;
|
|
665
|
-
}
|
|
666
|
-
static inline double* BezierSegment_getp_cx1(BezierSegment restrict obj){
|
|
667
|
-
int64_t offset=0;
|
|
668
|
-
offset+=40;
|
|
669
|
-
return ( double*)(( char*) obj+offset);
|
|
670
|
-
}
|
|
671
|
-
static inline double BezierSegment_get_cs2(const BezierSegment restrict obj){
|
|
672
|
-
int64_t offset=0;
|
|
673
|
-
offset+=48;
|
|
674
|
-
return *( double*)(( char*) obj+offset);
|
|
675
|
-
}
|
|
676
|
-
static inline void BezierSegment_set_cs2(BezierSegment restrict obj, double value){
|
|
677
|
-
int64_t offset=0;
|
|
678
|
-
offset+=48;
|
|
679
|
-
*( double*)(( char*) obj+offset)=value;
|
|
680
|
-
}
|
|
681
|
-
static inline double* BezierSegment_getp_cs2(BezierSegment restrict obj){
|
|
682
|
-
int64_t offset=0;
|
|
683
|
-
offset+=48;
|
|
684
|
-
return ( double*)(( char*) obj+offset);
|
|
685
|
-
}
|
|
686
|
-
static inline double BezierSegment_get_cx2(const BezierSegment restrict obj){
|
|
687
|
-
int64_t offset=0;
|
|
688
|
-
offset+=56;
|
|
689
|
-
return *( double*)(( char*) obj+offset);
|
|
690
|
-
}
|
|
691
|
-
static inline void BezierSegment_set_cx2(BezierSegment restrict obj, double value){
|
|
692
|
-
int64_t offset=0;
|
|
693
|
-
offset+=56;
|
|
694
|
-
*( double*)(( char*) obj+offset)=value;
|
|
695
|
-
}
|
|
696
|
-
static inline double* BezierSegment_getp_cx2(BezierSegment restrict obj){
|
|
697
|
-
int64_t offset=0;
|
|
698
|
-
offset+=56;
|
|
699
|
-
return ( double*)(( char*) obj+offset);
|
|
700
|
-
}
|
|
701
|
-
#endif
|
|
702
|
-
|
|
703
|
-
static inline
|
|
704
|
-
void _hit_s_bezier(BezierSegment seg, double t, double multiplicity, int8_t* n_hit, double* s){
|
|
705
|
-
double s1 = BezierSegment_get_s1(seg);
|
|
706
|
-
double s2 = BezierSegment_get_s2(seg);
|
|
707
|
-
double cs1 = BezierSegment_get_cs1(seg);
|
|
708
|
-
double cs2 = BezierSegment_get_cs2(seg);
|
|
709
|
-
double new_s = (1-t)*(1-t)*(1-t)*s1 + 3*(1-t)*(1-t)*t*cs1 + 3*(1-t)*t*t*cs2 + t*t*t*s2;
|
|
710
|
-
for (int8_t i = 0; i < multiplicity; i++) {
|
|
711
|
-
s[*n_hit] = new_s;
|
|
712
|
-
(*n_hit)++;
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
|
|
716
|
-
static inline
|
|
717
|
-
void BezierSegment_crossing_drift(BezierSegment seg, int8_t* n_hit, double* s, double s0, double x0, double m){
|
|
718
|
-
// Get segment data
|
|
719
|
-
double s1 = BezierSegment_get_s1(seg);
|
|
720
|
-
double x1 = BezierSegment_get_x1(seg);
|
|
721
|
-
double s2 = BezierSegment_get_s2(seg);
|
|
722
|
-
double x2 = BezierSegment_get_x2(seg);
|
|
723
|
-
double cs1 = BezierSegment_get_cs1(seg);
|
|
724
|
-
double cx1 = BezierSegment_get_cx1(seg);
|
|
725
|
-
double cs2 = BezierSegment_get_cs2(seg);
|
|
726
|
-
double cx2 = BezierSegment_get_cx2(seg);
|
|
727
|
-
// The Bézier curve is defined by the parametric equations (with t in [0, 1]):
|
|
728
|
-
// s(t) = (1-t)^3*s1 + 3(1-t)^2*t*cs1 + 3(1-t)*t^2*cs2 + t^3*s2
|
|
729
|
-
// x(t) = (1-t)^3*x1 + 3(1-t)^2*t*cx1 + 3(1-t)*t^2*cx2 + t^3*x2
|
|
730
|
-
// Plug the parametric eqs into the drift trajectory x(t) = m*(s(t) - s0) + x0 and solve for t
|
|
731
|
-
// The solutions for t (which we get by Cardano's method) are valid if in [0, 1]
|
|
732
|
-
double a = (m*s1 - x1) - (m*s2 - x2) - 3*(m*cs1 - cx1) + 3*(m*cs2 - cx2);
|
|
733
|
-
double b = 6*(m*cs1 - cx1) - 3*(m*cs2 - cx2) - 3*(m*s1 - x1);
|
|
734
|
-
double c = 3*(m*s1 - x1) - 3*(m*cs1 - cx1);
|
|
735
|
-
double d = (m*s0 - x0) - (m*s1 - x1);
|
|
736
|
-
double t;
|
|
737
|
-
// Edge cases
|
|
738
|
-
if (fabs(a) < XC_EPSILON){
|
|
739
|
-
if (fabs(b) < XC_EPSILON){
|
|
740
|
-
if (fabs(c) < XC_EPSILON){
|
|
741
|
-
if (fabs(d) < XC_EPSILON){
|
|
742
|
-
// The trajectory is on the Bézier curve
|
|
743
|
-
// TODO: This cannot happen because we don't have a cubic trajectory.
|
|
744
|
-
// Adapt if these ever would be implemented.
|
|
745
|
-
return;
|
|
746
|
-
} else {
|
|
747
|
-
// No solutions
|
|
748
|
-
return;
|
|
749
|
-
}
|
|
750
|
-
} else {
|
|
751
|
-
// This is a linear equation
|
|
752
|
-
t = -d/c;
|
|
753
|
-
if (0 <= t && t <= 1){
|
|
754
|
-
_hit_s_bezier(seg, t, 1, n_hit, s);
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
} else {
|
|
758
|
-
// This is a quadratic equation
|
|
759
|
-
double disc = c*c - 4*b*d;
|
|
760
|
-
if (disc < 0){
|
|
761
|
-
// No solutions
|
|
762
|
-
return;
|
|
763
|
-
}
|
|
764
|
-
for (int8_t i = 0; i < 2; i++) {
|
|
765
|
-
double sgnD = i*2-1; // negative and positive solutions; if multiplicity 2, we add the same solution twice
|
|
766
|
-
t = (-c + sgnD*sqrt(fabs(disc)))/(2*b);
|
|
767
|
-
if (0 <= t && t <= 1){
|
|
768
|
-
_hit_s_bezier(seg, t, 1, n_hit, s);
|
|
769
|
-
}
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
} else {
|
|
773
|
-
// Full cubic equation. Coefficients for the depressed cubic t^3 + p*t + q = 0:
|
|
774
|
-
double p = (3*a*c - b*b)/(3*a*a);
|
|
775
|
-
double q = (2*b*b*b - 9*a*b*c + 27*a*a*d)/(27*a*a*a);
|
|
776
|
-
double disc = -p*p*p/27 - q*q/4; // This is the discriminant of the depressed cubic but divided by (4*27)
|
|
777
|
-
if (fabs(disc) < XC_EPSILON){
|
|
778
|
-
if (fabs(p) < XC_EPSILON){
|
|
779
|
-
// One real root with multiplicity 3
|
|
780
|
-
t = -b/(3*a);
|
|
781
|
-
if (0 <= t && t <= 1){
|
|
782
|
-
_hit_s_bezier(seg, t, 3, n_hit, s);
|
|
783
|
-
}
|
|
784
|
-
} else {
|
|
785
|
-
// Two real roots (one simple and one with multiplicity 2)
|
|
786
|
-
t = 3*q/p - b/(3*a);
|
|
787
|
-
if (0 <= t && t <= 1){
|
|
788
|
-
_hit_s_bezier(seg, t, 1, n_hit, s);
|
|
789
|
-
}
|
|
790
|
-
t = -3*q/(2*p) - b/(3*a);
|
|
791
|
-
if (0 <= t && t <= 1){
|
|
792
|
-
_hit_s_bezier(seg, t, 2, n_hit, s);
|
|
793
|
-
}
|
|
794
|
-
}
|
|
795
|
-
} else if (disc < 0){
|
|
796
|
-
// One real root
|
|
797
|
-
t = cbrt(-q/2 + sqrt(fabs(disc))) + cbrt(-q/2 - sqrt(fabs(disc))) - b/(3*a);
|
|
798
|
-
if (0 <= t && t <= 1){
|
|
799
|
-
_hit_s_bezier(seg, t, 1, n_hit, s);
|
|
800
|
-
}
|
|
801
|
-
} else {
|
|
802
|
-
// Three real roots
|
|
803
|
-
double phi = acos(3*q/(2*p)*sqrt(fabs(3/p)));
|
|
804
|
-
t = 2*sqrt(fabs(p/3))*cos(phi/3) - b/(3*a);
|
|
805
|
-
if (0 <= t && t <= 1){
|
|
806
|
-
_hit_s_bezier(seg, t, 1, n_hit, s);
|
|
807
|
-
}
|
|
808
|
-
t = 2*sqrt(fabs(p/3))*cos((phi + 2*M_PI)/3) - b/(3*a);
|
|
809
|
-
if (0 <= t && t <= 1){
|
|
810
|
-
_hit_s_bezier(seg, t, 1, n_hit, s);
|
|
811
|
-
}
|
|
812
|
-
t = 2*sqrt(fabs(p/3))*cos((phi + 4*M_PI)/3) - b/(3*a);
|
|
813
|
-
if (0 <= t && t <= 1){
|
|
814
|
-
_hit_s_bezier(seg, t, 1, n_hit, s);
|
|
815
|
-
}
|
|
816
|
-
}
|
|
817
|
-
}
|
|
818
|
-
}
|
|
819
|
-
|
|
820
|
-
#ifndef XOBJ_TYPEDEF_Segment
|
|
821
|
-
#define XOBJ_TYPEDEF_Segment
|
|
822
|
-
typedef struct Segment_s * Segment;
|
|
823
|
-
enum Segment_e{Segment_LineSegment_t,Segment_HalfOpenLineSegment_t,Segment_CircularSegment_t,Segment_BezierSegment_t};
|
|
824
|
-
static inline Segment Segment_getp(Segment restrict obj){
|
|
825
|
-
int64_t offset=0;
|
|
826
|
-
return (Segment)(( char*) obj+offset);
|
|
827
|
-
}
|
|
828
|
-
static inline int64_t Segment_typeid(const Segment restrict obj){
|
|
829
|
-
int64_t offset=0;
|
|
830
|
-
offset+=8;
|
|
831
|
-
return *( int64_t*)(( char*) obj+offset);
|
|
832
|
-
}
|
|
833
|
-
static inline void* Segment_member(const Segment restrict obj){
|
|
834
|
-
int64_t offset=0;
|
|
835
|
-
offset+=*( int64_t*)(( char*) obj+offset);
|
|
836
|
-
return ( void*)(( char*) obj+offset);
|
|
837
|
-
}
|
|
838
|
-
static inline void Segment_crossing_drift(const Segment restrict obj, int8_t* restrict n_hit, double* restrict s, double s0, double x0, double m){
|
|
839
|
-
void* member = Segment_member(obj);
|
|
840
|
-
switch (Segment_typeid(obj)){
|
|
841
|
-
#ifndef SEGMENT_SKIP_LINESEGMENT
|
|
842
|
-
case Segment_LineSegment_t:
|
|
843
|
-
return LineSegment_crossing_drift((LineSegment) member,n_hit,s,s0,x0,m);
|
|
844
|
-
break;
|
|
845
|
-
#endif
|
|
846
|
-
#ifndef SEGMENT_SKIP_HALFOPENLINESEGMENT
|
|
847
|
-
case Segment_HalfOpenLineSegment_t:
|
|
848
|
-
return HalfOpenLineSegment_crossing_drift((HalfOpenLineSegment) member,n_hit,s,s0,x0,m);
|
|
849
|
-
break;
|
|
850
|
-
#endif
|
|
851
|
-
#ifndef SEGMENT_SKIP_CIRCULARSEGMENT
|
|
852
|
-
case Segment_CircularSegment_t:
|
|
853
|
-
return CircularSegment_crossing_drift((CircularSegment) member,n_hit,s,s0,x0,m);
|
|
854
|
-
break;
|
|
855
|
-
#endif
|
|
856
|
-
#ifndef SEGMENT_SKIP_BEZIERSEGMENT
|
|
857
|
-
case Segment_BezierSegment_t:
|
|
858
|
-
return BezierSegment_crossing_drift((BezierSegment) member,n_hit,s,s0,x0,m);
|
|
859
|
-
break;
|
|
860
|
-
#endif
|
|
861
|
-
}
|
|
862
|
-
return;
|
|
863
|
-
}
|
|
864
|
-
#endif
|
|
865
|
-
#ifndef XOBJ_TYPEDEF_ArrNSegment
|
|
866
|
-
#define XOBJ_TYPEDEF_ArrNSegment
|
|
867
|
-
typedef struct ArrNSegment_s * ArrNSegment;
|
|
868
|
-
static inline ArrNSegment ArrNSegment_getp(ArrNSegment restrict obj){
|
|
869
|
-
int64_t offset=0;
|
|
870
|
-
return (ArrNSegment)(( char*) obj+offset);
|
|
871
|
-
}
|
|
872
|
-
static inline int64_t ArrNSegment_len(ArrNSegment restrict obj){
|
|
873
|
-
int64_t offset=0;
|
|
874
|
-
int64_t* arr = ( int64_t*)(( char*) obj+offset);
|
|
875
|
-
return arr[1];
|
|
876
|
-
}
|
|
877
|
-
static inline Segment ArrNSegment_getp1(ArrNSegment restrict obj, int64_t i0){
|
|
878
|
-
int64_t offset=0;
|
|
879
|
-
offset+=16+i0*16;
|
|
880
|
-
return (Segment)(( char*) obj+offset);
|
|
881
|
-
}
|
|
882
|
-
static inline int64_t ArrNSegment_typeid(const ArrNSegment restrict obj, int64_t i0){
|
|
883
|
-
int64_t offset=0;
|
|
884
|
-
offset+=16+i0*16;
|
|
885
|
-
offset+=8;
|
|
886
|
-
return *( int64_t*)(( char*) obj+offset);
|
|
887
|
-
}
|
|
888
|
-
static inline void* ArrNSegment_member(const ArrNSegment restrict obj, int64_t i0){
|
|
889
|
-
int64_t offset=0;
|
|
890
|
-
offset+=16+i0*16;
|
|
891
|
-
offset+=*( int64_t*)(( char*) obj+offset);
|
|
892
|
-
return ( void*)(( char*) obj+offset);
|
|
893
|
-
}
|
|
894
|
-
#endif
|
|
895
|
-
#ifndef XOBJ_TYPEDEF_Segments
|
|
896
|
-
#define XOBJ_TYPEDEF_Segments
|
|
897
|
-
typedef struct Segments_s * Segments;
|
|
898
|
-
static inline Segments Segments_getp(Segments restrict obj){
|
|
899
|
-
int64_t offset=0;
|
|
900
|
-
return (Segments)(( char*) obj+offset);
|
|
901
|
-
}
|
|
902
|
-
static inline ArrNSegment Segments_getp_data(Segments restrict obj){
|
|
903
|
-
int64_t offset=0;
|
|
904
|
-
offset+=8;
|
|
905
|
-
return (ArrNSegment)(( char*) obj+offset);
|
|
906
|
-
}
|
|
907
|
-
static inline int64_t Segments_len_data(Segments restrict obj){
|
|
908
|
-
int64_t offset=0;
|
|
909
|
-
offset+=8;
|
|
910
|
-
int64_t* arr = ( int64_t*)(( char*) obj+offset);
|
|
911
|
-
return arr[1];
|
|
912
|
-
}
|
|
913
|
-
static inline Segment Segments_getp1_data(Segments restrict obj, int64_t i0){
|
|
914
|
-
int64_t offset=0;
|
|
915
|
-
offset+=8;
|
|
916
|
-
offset+=16+i0*16;
|
|
917
|
-
return (Segment)(( char*) obj+offset);
|
|
918
|
-
}
|
|
919
|
-
static inline int64_t Segments_typeid_data(const Segments restrict obj, int64_t i0){
|
|
920
|
-
int64_t offset=0;
|
|
921
|
-
offset+=8;
|
|
922
|
-
offset+=16+i0*16;
|
|
923
|
-
offset+=8;
|
|
924
|
-
return *( int64_t*)(( char*) obj+offset);
|
|
925
|
-
}
|
|
926
|
-
static inline void* Segments_member_data(const Segments restrict obj, int64_t i0){
|
|
927
|
-
int64_t offset=0;
|
|
928
|
-
offset+=8;
|
|
929
|
-
offset+=16+i0*16;
|
|
930
|
-
offset+=*( int64_t*)(( char*) obj+offset);
|
|
931
|
-
return ( void*)(( char*) obj+offset);
|
|
932
|
-
}
|
|
933
|
-
#endif
|
|
934
|
-
|
|
935
|
-
static inline
|
|
936
|
-
void Segments_crossing_drift(Segments segs, int8_t* n_hit, double* s, double s0, double x0, double m){
|
|
937
|
-
int64_t n_segments = Segments_len_data(segs);
|
|
938
|
-
for (int8_t i=0; i<n_segments;i++) {
|
|
939
|
-
Segment seg = Segments_getp1_data(segs, i);
|
|
940
|
-
Segment_crossing_drift(seg, n_hit, s, s0, x0, m);
|
|
941
|
-
}
|
|
942
|
-
sort_array_of_double(s, (int64_t) *n_hit);
|
|
943
|
-
}
|
|
944
|
-
|
|
945
|
-
static inline
|
|
946
|
-
void Segments_crossing_drift_vlimit(Segments segs, int8_t* n_hit, double* s, double s0, double x0, double m){
|
|
947
|
-
int64_t n_segments = Segments_len_data(segs);
|
|
948
|
-
for (int8_t i=0; i<n_segments;i++) {
|
|
949
|
-
Segment seg = Segments_getp1_data(segs, i);
|
|
950
|
-
Segment_crossing_drift(seg, n_hit, s, s0, x0, m);
|
|
951
|
-
}
|
|
952
|
-
sort_array_of_double(s, (int64_t) *n_hit);
|
|
953
|
-
}
|