1 |
|
5 |
|
2 |
|
|
#include <stdio.h>
|
3 |
|
|
#include <math.h>
|
4 |
|
|
#include "p3d_cst.h"
|
5 |
|
|
#include "m3d_struct.h"
|
6 |
|
|
#include "m3d_hotes.h"
|
7 |
|
|
#include "prototype.h"
|
8 |
|
|
extern int debug ;
|
9 |
|
|
void p3d_inter(float *coord,int *tabele,SURFACE *surf,ELEMENT *ele,int *nb_inter,int *nb_reel,int *nb_neg,float *vec_posi,int *ierr)
|
10 |
|
|
{
|
11 |
|
|
/* ************************************************* */
|
12 |
|
|
/* declaration des variables internes a la procedure */
|
13 |
|
|
float vec_j1j2[3], vec_n[3], vec_b[3], norme, vec_o[3], vec_j1j3[3] ;
|
14 |
|
|
int j1, j2, j3, i, i1, i2, i3, iordre[NB_MAX_INTER] ;
|
15 |
|
|
int icont,gtrouve, position ;
|
16 |
|
|
float vl1, vl2, vl3 ;
|
17 |
|
|
ELEMENT *tete ;
|
18 |
|
|
float vec_oi1[3],vec_g[3], vec_gj1[3], vec_gj2[3], vec_gj3[3] ;
|
19 |
|
|
float vec_i[3], vn[3], vec_i1i2[3], vec_i1i3[3] ;
|
20 |
|
|
float prosca, dist ;
|
21 |
|
|
|
22 |
|
|
/* ************************************************* */
|
23 |
|
|
/* debut du code executable */
|
24 |
|
|
|
25 |
|
|
*nb_inter = 0 ;
|
26 |
|
|
/* calcul des parametres de l'element */
|
27 |
|
|
|
28 |
|
|
/* numero des sommets */
|
29 |
|
|
/* tete de liste des elements */
|
30 |
|
|
|
31 |
|
|
/* ********************************* */
|
32 |
|
|
/* element j1,j2,j3 de normale vec_n */
|
33 |
|
|
/* ********************************* */
|
34 |
|
|
j1 = tabele[3*(ele->num)] ;
|
35 |
|
|
j2 = tabele[3*(ele->num)+1] ;
|
36 |
|
|
j3 = tabele[3*(ele->num)+2] ;
|
37 |
|
|
|
38 |
|
|
vec_j1j2[0]=coord[x(j2)]-coord[x(j1)] ;
|
39 |
|
|
vec_j1j2[1]=coord[y(j2)]-coord[y(j1)] ;
|
40 |
|
|
vec_j1j2[2]=coord[z(j2)]-coord[z(j1)] ;
|
41 |
|
|
|
42 |
|
|
vec_j1j3[0]=coord[x(j3)]-coord[x(j1)] ;
|
43 |
|
|
vec_j1j3[1]=coord[y(j3)]-coord[y(j1)] ;
|
44 |
|
|
vec_j1j3[2]=coord[z(j3)]-coord[z(j1)] ;
|
45 |
|
|
|
46 |
|
|
/* normale a l'element triangulaire */
|
47 |
|
|
|
48 |
|
|
vec_n[0] = PVECX(vec_j1j2,vec_j1j3) ;
|
49 |
|
|
vec_n[1] = PVECY(vec_j1j2,vec_j1j3) ;
|
50 |
|
|
vec_n[2] = PVECZ(vec_j1j2,vec_j1j3) ;
|
51 |
|
|
|
52 |
|
|
norme = NORME(vec_n) ;
|
53 |
|
|
if (norme<EPSILON)
|
54 |
|
|
{
|
55 |
|
|
*ierr = VRAI ;
|
56 |
|
|
if (debug) printf("%s\n"," erreur norme nulle P3D_INTER ") ;
|
57 |
|
|
return ;
|
58 |
|
|
}
|
59 |
|
|
/* on norme le vecteur normal */
|
60 |
|
|
for (i=0;i<3;i++) vec_n[i] = vec_n[i]/norme ;
|
61 |
|
|
|
62 |
|
|
norme = NORME(vec_j1j2) ;
|
63 |
|
|
if (norme<EPSILON)
|
64 |
|
|
{
|
65 |
|
|
*ierr = VRAI ;
|
66 |
|
|
if (debug) printf("%s\n"," erreur norme nulle P3D_INTER ") ;
|
67 |
|
|
return ;
|
68 |
|
|
}
|
69 |
|
|
/* on norme le vecteur vec_j1j2 */
|
70 |
|
|
for (i=0;i<3;i++) vec_j1j2[i] = vec_j1j2[i]/norme ;
|
71 |
|
|
|
72 |
|
|
vec_b[0] = PVECX(vec_n,vec_j1j2) ;
|
73 |
|
|
vec_b[1] = PVECY(vec_n,vec_j1j2) ;
|
74 |
|
|
vec_b[2] = PVECZ(vec_n,vec_j1j2) ;
|
75 |
|
|
/* barycentre de la face j1,j2,j3 */
|
76 |
|
|
vec_g[0]=(coord[x(j1)]+coord[x(j2)]+coord[x(j3)])/3. ;
|
77 |
|
|
vec_g[1]=(coord[y(j1)]+coord[y(j2)]+coord[y(j3)])/3. ;
|
78 |
|
|
vec_g[2]=(coord[z(j1)]+coord[z(j2)]+coord[z(j3)])/3. ;
|
79 |
|
|
|
80 |
|
|
vec_gj1[0]= coord[x(j1)] - vec_g[0] ;
|
81 |
|
|
vec_gj1[1]= coord[y(j1)] - vec_g[1] ;
|
82 |
|
|
vec_gj1[2]= coord[z(j1)] - vec_g[2] ;
|
83 |
|
|
|
84 |
|
|
vec_gj2[0]= coord[x(j2)] - vec_g[0] ;
|
85 |
|
|
vec_gj2[1]= coord[y(j2)] - vec_g[1] ;
|
86 |
|
|
vec_gj2[2]= coord[z(j2)] - vec_g[2] ;
|
87 |
|
|
|
88 |
|
|
vec_gj3[0]= coord[x(j3)] - vec_g[0] ;
|
89 |
|
|
vec_gj3[1]= coord[y(j3)] - vec_g[1] ;
|
90 |
|
|
vec_gj3[2]= coord[z(j3)] - vec_g[2] ;
|
91 |
|
|
|
92 |
|
|
icont = 0 ;/* compteur */
|
93 |
|
|
gtrouve=FAUX ;
|
94 |
|
|
/* si la postion du point origine ne permet pas de conclure, on change cette position en restant
|
95 |
|
|
proche du centre de gravite */
|
96 |
|
|
/* on dispose de 4 points, si on ne peut conclure, il faut alors changer d'element */
|
97 |
|
|
while ((gtrouve==FAUX)&&(icont<4))
|
98 |
|
|
{
|
99 |
|
|
*nb_inter = 0 ;
|
100 |
|
|
if (icont==0)
|
101 |
|
|
{
|
102 |
|
|
vl1 = 0. ;
|
103 |
|
|
vl2 = 0. ;
|
104 |
|
|
vl3 = 0. ;
|
105 |
|
|
}
|
106 |
|
|
if (icont==1)
|
107 |
|
|
{
|
108 |
|
|
vl1 = 0.1 ;
|
109 |
|
|
vl2 = 0. ;
|
110 |
|
|
vl3 = 0. ;
|
111 |
|
|
}
|
112 |
|
|
if (icont==2)
|
113 |
|
|
{
|
114 |
|
|
vl1 = 0. ;
|
115 |
|
|
vl2 = 0.1 ;
|
116 |
|
|
vl3 = 0. ;
|
117 |
|
|
}
|
118 |
|
|
if (icont==3)
|
119 |
|
|
{
|
120 |
|
|
vl1 = 0. ;
|
121 |
|
|
vl2 = 0. ;
|
122 |
|
|
vl3 = 0.1 ;
|
123 |
|
|
}
|
124 |
|
|
|
125 |
|
|
/* position du point origine sur la facette j1,j2,j3 */
|
126 |
|
|
/* si tous les vli sont nuls : centre de gravite */
|
127 |
|
|
vec_o[0]= vec_g[0] + (vl1 * vec_gj1[0]) + (vl2 * vec_gj2[0]) + (vl3 * vec_gj3[0]) ;
|
128 |
|
|
vec_o[1]= vec_g[1] + (vl1 * vec_gj1[1]) + (vl2 * vec_gj2[1]) + (vl3 * vec_gj3[1]) ;
|
129 |
|
|
vec_o[2]= vec_g[2] + (vl1 * vec_gj1[2]) + (vl2 * vec_gj2[2]) + (vl3 * vec_gj3[2]) ;
|
130 |
|
|
|
131 |
|
|
/* parcours des elements de la surface */
|
132 |
|
|
tete = surf->ele ; /* on se place en tete de liste des elements de la surface */
|
133 |
|
|
while (tete!=NULL)/* parcours des elements */
|
134 |
|
|
{
|
135 |
|
|
if (tete==ele)/* l'element est sur la surface */
|
136 |
|
|
{
|
137 |
|
|
if (*nb_inter>=NB_MAX_INTER)
|
138 |
|
|
{
|
139 |
|
|
*ierr = VRAI ;
|
140 |
|
|
if (debug) printf("%s\n"," erreur tableau P3D_INTER") ;
|
141 |
|
|
return ;
|
142 |
|
|
}
|
143 |
|
|
vec_posi[*nb_inter] = 0. ;
|
144 |
|
|
*nb_inter = (*nb_inter) + 1 ;
|
145 |
|
|
}
|
146 |
|
|
else
|
147 |
|
|
{
|
148 |
|
|
/* sommets */
|
149 |
|
|
|
150 |
|
|
/* calcul du point intersection sur le plan */
|
151 |
|
|
|
152 |
|
|
/* numero du triangle courant */
|
153 |
|
|
i1 = tabele[3*(tete->num)] ;
|
154 |
|
|
i2 = tabele[3*(tete->num)+1] ;
|
155 |
|
|
i3 = tabele[3*(tete->num)+2] ;
|
156 |
|
|
|
157 |
|
|
/* calcul de la normale a la facette */
|
158 |
|
|
|
159 |
|
|
vec_i1i2[0]=coord[x(i2)]-coord[x(i1)] ;
|
160 |
|
|
vec_i1i2[1]=coord[y(i2)]-coord[y(i1)] ;
|
161 |
|
|
vec_i1i2[2]=coord[z(i2)]-coord[z(i1)] ;
|
162 |
|
|
|
163 |
|
|
vec_i1i3[0]=coord[x(i3)]-coord[x(i1)] ;
|
164 |
|
|
vec_i1i3[1]=coord[y(i3)]-coord[y(i1)] ;
|
165 |
|
|
vec_i1i3[2]=coord[z(i3)]-coord[z(i1)] ;
|
166 |
|
|
|
167 |
|
|
/* normale a la facette i1,i2,i3 */
|
168 |
|
|
vn[0] = PVECX(vec_i1i2,vec_i1i3) ;
|
169 |
|
|
vn[1] = PVECY(vec_i1i2,vec_i1i3) ;
|
170 |
|
|
vn[2] = PVECZ(vec_i1i2,vec_i1i3) ;
|
171 |
|
|
|
172 |
|
|
norme = NORME(vn) ;
|
173 |
|
|
if (norme<EPSILON)
|
174 |
|
|
{
|
175 |
|
|
*ierr = VRAI ;
|
176 |
|
|
if (debug) printf("%s\n"," erreur norme nulle P3D_INTER ") ;
|
177 |
|
|
return ;
|
178 |
|
|
}
|
179 |
|
|
/* on norme le vecteur normal */
|
180 |
|
|
for (i=0;i<3;i++) vn[i] = vn[i]/norme ;
|
181 |
|
|
/* produit scalaire des normales */
|
182 |
|
|
|
183 |
|
|
prosca = PROSCA(vec_n,vn) ;
|
184 |
|
|
|
185 |
|
|
vec_oi1[0] = coord[x(i1)]-vec_o[0] ;
|
186 |
|
|
vec_oi1[1] = coord[y(i1)]-vec_o[1] ;
|
187 |
|
|
vec_oi1[2] = coord[z(i1)]-vec_o[2] ;
|
188 |
|
|
/* la normale a la face j1,j2,j3 est parallele a la facette i1,i2,i3 de la surface
|
189 |
|
|
par consequent, il est delicat de determiner le nombre d'intersection de la droite
|
190 |
|
|
avec la surface dont la facette i1,i2,i3 fait partie */
|
191 |
|
|
if ((float)fabs((double)prosca)<EPSILON)
|
192 |
|
|
{
|
193 |
|
|
/* tester la distance de la droite (o,vec_n) issue de j1,j2,j3
|
194 |
|
|
au plan de normal vn de la facette i1,i2,i3 */
|
195 |
|
|
/* si cette distance est non nulle il est clair que meme si la normale est parallele
|
196 |
|
|
a la facette, il n'y a pas intersection */
|
197 |
|
|
prosca = PROSCA(vec_oi1,vn) ;
|
198 |
|
|
prosca = (float)fabs((double)prosca) ;
|
199 |
|
|
if (prosca<EPSILON)
|
200 |
|
|
{
|
201 |
|
|
*nb_inter = UNKNOWN ;
|
202 |
|
|
/* on ne peut pas conclure
|
203 |
|
|
la droite issue de vec_o et de normale vec_n : la droite issue de j1 ,j2,j3
|
204 |
|
|
est dans le plan de la facette, on ne peut conclure quant au nombre de points
|
205 |
|
|
d'intersection, il faut deplacer le centre vec_o en conservant bien sur l'orientation
|
206 |
|
|
de la facette j1,j2,j3( on a 4 essais) */
|
207 |
|
|
}
|
208 |
|
|
/* sinon pas d'intersection */
|
209 |
|
|
}
|
210 |
|
|
else
|
211 |
|
|
{
|
212 |
|
|
/* projection sur le plan */
|
213 |
|
|
|
214 |
|
|
dist = PROSCA(vec_oi1,vn)/prosca ;
|
215 |
|
|
/* point intersection avec la facette i1,i2,i3*/
|
216 |
|
|
vec_i[0] = dist*vec_n[0] + vec_o[0] ;
|
217 |
|
|
vec_i[1] = dist*vec_n[1] + vec_o[1] ;
|
218 |
|
|
vec_i[2] = dist*vec_n[2] + vec_o[2] ;
|
219 |
|
|
|
220 |
|
|
/* le point I appartient il au triangle i1, i2, i3 */
|
221 |
|
|
position = m3d_pt_tri(coord,vec_i,i1,i2,i3,vn) ;
|
222 |
|
|
if ((position==INTERIEUR)||(position==DESSUS))
|
223 |
|
|
/* en fait vmin>=0.*/
|
224 |
|
|
{
|
225 |
|
|
if (*nb_inter>=NB_MAX_INTER)
|
226 |
|
|
{
|
227 |
|
|
*ierr = VRAI ;
|
228 |
|
|
return ;
|
229 |
|
|
}
|
230 |
|
|
if (*nb_inter!=UNKNOWN)
|
231 |
|
|
{
|
232 |
|
|
vec_posi[*nb_inter] = dist ;
|
233 |
|
|
*nb_inter = (*nb_inter) + 1. ;
|
234 |
|
|
}
|
235 |
|
|
}
|
236 |
|
|
}
|
237 |
|
|
}
|
238 |
|
|
tete=tete->suivant ;/* on passe a l'element suivant sur la surface */
|
239 |
|
|
/* cas ou il n'a pas ete possible de conclure, on fait un essai avec un nouveau point */
|
240 |
|
|
if (*nb_inter==UNKNOWN) tete=NULL ;/* fin de parcours, on passe au point origine suivant */
|
241 |
|
|
}
|
242 |
|
|
|
243 |
|
|
*nb_reel = *nb_inter ;
|
244 |
|
|
*nb_neg = *nb_inter ;
|
245 |
|
|
|
246 |
|
|
if (*nb_inter>1)
|
247 |
|
|
{
|
248 |
|
|
/* collage en fin de parcours, il se peut qu'une intersection,soit commune a plusieurs elements */
|
249 |
|
|
/* tri croissant des distances sur la droite, le tableau est modifie */
|
250 |
|
|
for (i=0;i<*nb_inter;i++) iordre[i] = i+1 ;/* attention passage c fortran */
|
251 |
|
|
trirea(vec_posi,nb_inter,iordre) ;
|
252 |
|
|
for (i=0;i<*nb_inter-1;i++)
|
253 |
|
|
{
|
254 |
|
|
/* attention au choix de EPSILON */
|
255 |
|
|
if ((vec_posi[i+1]-vec_posi[i])<100.*EPSILON)
|
256 |
|
|
{
|
257 |
|
|
*nb_reel = (*nb_reel) - 1 ;
|
258 |
|
|
*nb_neg = (*nb_neg) -1 ;
|
259 |
|
|
}
|
260 |
|
|
else
|
261 |
|
|
{
|
262 |
|
|
if (vec_posi[i]>-EPSILON) *nb_neg = (*nb_neg) -1 ;
|
263 |
|
|
}
|
264 |
|
|
}
|
265 |
|
|
if (vec_posi[*nb_inter-1]>-EPSILON) *nb_neg = (*nb_neg) -1 ;
|
266 |
|
|
/* on teste les points doubles pour eviter les ambiguites */
|
267 |
|
|
if (*nb_reel!=*nb_inter) *nb_inter = UNKNOWN ;
|
268 |
|
|
}
|
269 |
|
|
if (*nb_inter!=UNKNOWN) gtrouve=VRAI ;/* on peut conclure */
|
270 |
|
|
icont ++ ;
|
271 |
|
|
}
|
272 |
|
|
/* l'element n'a pas permis de conclure */
|
273 |
|
|
if ((icont==4)&&(gtrouve==FAUX))
|
274 |
|
|
{
|
275 |
|
|
*ierr=VRAI ;
|
276 |
|
|
if (debug) printf("%s\n"," erreur systeme P3D_INTER") ;
|
277 |
|
|
*nb_inter = UNKNOWN ;
|
278 |
|
|
return ;
|
279 |
|
|
}
|
280 |
|
|
return ;
|
281 |
|
|
}
|