1 |
|
5 |
|
2 |
|
|
#include <stdio.h>
|
3 |
|
|
#include <math.h>
|
4 |
|
|
#include <stdlib.h>
|
5 |
|
|
#include "p3d_cst.h"
|
6 |
|
|
#include "m3d_struct.h"
|
7 |
|
|
#include "m3d_hotes.h"
|
8 |
|
|
#include "m3d_erreur.h"
|
9 |
|
|
#include "prototype.h"
|
10 |
|
|
extern GEST_MEM *gest ;
|
11 |
|
|
extern int debug ;
|
12 |
|
|
int p3d_envel(void)
|
13 |
|
|
{
|
14 |
|
|
/* ************************************************* */
|
15 |
|
|
/* declaration des variables internes a la procedure */
|
16 |
|
|
ELEMENT *tete;/* tete des elements du front */
|
17 |
|
|
SURFACE *surf, *surf_ext ;
|
18 |
|
|
int i, num, gtrouve, k, ierr ;
|
19 |
|
|
int is_ok, nb_inter, nb, j, nb_reel, jmax ;
|
20 |
|
|
float vec_posi[NB_MAX_INTER], vmax, *v_inter ;
|
21 |
|
|
int iordre[NB_MAX_INTER], is ;
|
22 |
|
|
int ipair, nb_neg, k1, k2 ;
|
23 |
|
|
|
24 |
|
|
/* debut du code executable */
|
25 |
|
|
|
26 |
|
|
ierr = 0 ;
|
27 |
|
|
gest->nb_surf = 0 ;
|
28 |
|
|
/* determination du nombre de surfaces par un algorithme frontal */
|
29 |
|
|
if (!p3d_nbsurf())
|
30 |
|
|
{
|
31 |
|
|
if (debug) printf("%s\n"," erreur p3d_nbsurf P3D_ENVEL ") ;
|
32 |
|
|
return(FAUX) ;
|
33 |
|
|
}
|
34 |
|
|
|
35 |
|
|
/* creation et orientation des surfaces, creations des volumes enveloppes */
|
36 |
|
|
gest->tab_surf = (SURFACE *)calloc(gest->nb_surf,sizeof(SURFACE)) ;
|
37 |
|
|
ERREUR_ALLOC(gest->tab_surf)
|
38 |
|
|
|
39 |
|
|
for (i=0;i<gest->nb_surf;i++)
|
40 |
|
|
{
|
41 |
|
|
(gest->tab_surf[i]).etat = UNKNOWN ;
|
42 |
|
|
(gest->tab_surf[i]).ele = NULL ;
|
43 |
|
|
(gest->tab_surf[i]).suivant = NULL ;
|
44 |
|
|
(gest->tab_surf[i]).envel = NULL ;
|
45 |
|
|
}
|
46 |
|
|
|
47 |
|
|
/* affecter les elements aux surfaces */
|
48 |
|
|
for (i=0;i<gest->nb_2d;i++)
|
49 |
|
|
{
|
50 |
|
|
/* pointeur element i */
|
51 |
|
|
tete = &(gest->tab_ele[i]) ;
|
52 |
|
|
/* surface d'appartenance */
|
53 |
|
|
surf = &(gest->tab_surf[(tete->mark)-1]) ;/* pointeur sur la surface */
|
54 |
|
|
INSERE_TETE(surf->ele,tete)
|
55 |
|
|
/* insertion en tete de l'element tete dans la liste d'elements surface->ele */
|
56 |
|
|
}
|
57 |
|
|
|
58 |
|
|
for (i=0;i<gest->nb_2d;i++) (gest->tab_ele[i]).mark = 0 ;
|
59 |
|
|
|
60 |
|
|
/* a ce stade. on a cree des surfaces reperees dans tab_surf et on leur a affecte des listes d'elements */
|
61 |
|
|
/* orientation des surfaces */
|
62 |
|
|
for (is=0;is<gest->nb_surf;is++)
|
63 |
|
|
{
|
64 |
|
|
surf = &(gest->tab_surf[is]) ;
|
65 |
|
|
/* on choisit un element sur la surface */
|
66 |
|
|
tete = surf->ele ;
|
67 |
|
|
/* tete de liste des elements de la surface */
|
68 |
|
|
/* orientation de la surface surf */
|
69 |
|
|
while (tete!=NULL)
|
70 |
|
|
{
|
71 |
|
|
nb = 0 ;
|
72 |
|
|
nb_reel = 0 ;
|
73 |
|
|
nb_neg = 0 ;
|
74 |
|
|
/* INTERSECTION entre la droite passant par le barycentre de l'element et
|
75 |
|
|
de vecteur directeur la normale a l'element et la surface reperee par tab_surf[j] */
|
76 |
|
|
/* en sortie nb, nombre de points d'intersection */
|
77 |
|
|
/* strategie pour les points doubles : on les evite pour le moment en choisissant
|
78 |
|
|
un autre element sur la surface */
|
79 |
|
|
/* on pourra par la suite trier les points doubles, voir triples */
|
80 |
|
|
p3d_inter(gest->vcorg,gest->tabele,surf,tete,&nb,&nb_reel,&nb_neg,vec_posi,&ierr) ;
|
81 |
|
|
/* erreur */
|
82 |
|
|
if (ierr==VRAI)
|
83 |
|
|
{
|
84 |
|
|
if (debug) printf("%s\n"," erreur p3d_inter P3D_ENVEL ") ;
|
85 |
|
|
return(FAUX) ;
|
86 |
|
|
}
|
87 |
|
|
if (nb==UNKNOWN)
|
88 |
|
|
{
|
89 |
|
|
tete=tete->suivant ;
|
90 |
|
|
}
|
91 |
|
|
else
|
92 |
|
|
{
|
93 |
|
|
/* l'element n'a pas permis de conclure (is_ok==FAUX), il faut passer au suivant
|
94 |
|
|
sinon on passe a la surface suivante */
|
95 |
|
|
|
96 |
|
|
for (i=0;i<nb_reel;i++) iordre[i] = i+1 ;/* attention passage c fortran */
|
97 |
|
|
trirea(vec_posi,&nb_reel,iordre) ;
|
98 |
|
|
/* on oriente la surface */
|
99 |
|
|
/* test sur la parite du nombre d'intersections */
|
100 |
|
|
/* recherche dans vec_posi */
|
101 |
|
|
i = 0 ;
|
102 |
|
|
while (i<=nb_reel)
|
103 |
|
|
{
|
104 |
|
|
i++ ;
|
105 |
|
|
if ((float)fabs((double)vec_posi[i-1])<EPSILON)
|
106 |
|
|
{
|
107 |
|
|
break ;
|
108 |
|
|
}
|
109 |
|
|
}
|
110 |
|
|
ipair = i - 2 *(int)(i/2) ;
|
111 |
|
|
if (ipair==1) /* normale interieure */
|
112 |
|
|
{
|
113 |
|
|
/* on change l'orientation d'un element en inversant une arete */
|
114 |
|
|
num = gest->tabele[3*(tete->num)] ;
|
115 |
|
|
/* premier noeud de l'element */
|
116 |
|
|
gest->tabele[3*(tete->num)]=gest->tabele[3*(tete->num)+1] ;
|
117 |
|
|
gest->tabele[3*(tete->num)+1] = num ;
|
118 |
|
|
}
|
119 |
|
|
/* ORIENTATION SUIVANT UN ALGORITHME FRONTAL */
|
120 |
|
|
if (!p3d_orient(tete->num))
|
121 |
|
|
{
|
122 |
|
|
if (debug) printf("%s\n"," erreur p3d_orient P3D_ENVEL ") ;
|
123 |
|
|
return(FAUX) ;
|
124 |
|
|
}
|
125 |
|
|
break ;
|
126 |
|
|
}
|
127 |
|
|
}
|
128 |
|
|
}
|
129 |
|
|
/* position relative des surfaces */
|
130 |
|
|
/* pour chacune des surfaces, on doit determiner si la surface est exterieur, ou interieur */
|
131 |
|
|
/* pour chacune des surfaces, on determine le nombre d'intersections dont l'abscisse curviligne est
|
132 |
|
|
strictement negative :
|
133 |
|
|
- avec toutes les autres surfaces --------> k1
|
134 |
|
|
- avec la surface elle meme --------------> k2
|
135 |
|
|
|
136 |
|
|
si k1 + k2 est pair, la surface est exterieure et on peut creer un volume sinon la surface est exterieure
|
137 |
|
|
et on chaine celle ci avec la surface exterieure associee */
|
138 |
|
|
/* parcours de tab_surf */
|
139 |
|
|
|
140 |
|
|
gest->v_inter = (float*)calloc(gest->nb_surf * gest->nb_surf,sizeof(float)) ;
|
141 |
|
|
ERREUR_ALLOC(gest->v_inter) ;
|
142 |
|
|
if (gest->nb_surf>1)
|
143 |
|
|
{
|
144 |
|
|
for (i=0;i<gest->nb_surf;i++)
|
145 |
|
|
{
|
146 |
|
|
/* changer l'implementation voir ci dessus */
|
147 |
|
|
k1 = 0 ;/* nombre d'intersections avec toutes les autres surfaces */
|
148 |
|
|
k2 = 0 ;/* nombre d'intersections avec la surface elle meme */
|
149 |
|
|
surf = &(gest->tab_surf[i]) ;
|
150 |
|
|
/* on choisit un element sur la surface */
|
151 |
|
|
tete = surf->ele ;/* tete de liste des elements de la surface */
|
152 |
|
|
/* boucle sur les autres surfaces */
|
153 |
|
|
for (j=0;j<gest->nb_surf;j++)
|
154 |
|
|
{
|
155 |
|
|
nb = 0 ;
|
156 |
|
|
nb_reel = 0 ;
|
157 |
|
|
nb_neg = 0 ;
|
158 |
|
|
/* intersection surface i, surface j */
|
159 |
|
|
p3d_inter(gest->vcorg,gest->tabele,&(gest->tab_surf[j]),tete,&nb,&nb_reel,&nb_neg,vec_posi,&ierr) ;
|
160 |
|
|
if ((ierr==VRAI) || (nb==UNKNOWN))
|
161 |
|
|
{
|
162 |
|
|
if (debug) printf("%s\n"," erreur p3d_inter P3D_ENVEL ") ;
|
163 |
|
|
return(FAUX) ;
|
164 |
|
|
}
|
165 |
|
|
/* tester la parite de nb_neg */
|
166 |
|
|
ipair = nb_neg - 2 * (int)(nb_neg/2) ;
|
167 |
|
|
if (ipair==0)
|
168 |
|
|
{
|
169 |
|
|
/* nombre d'intersections paire */
|
170 |
|
|
gest->v_inter[gest->nb_surf*j+i] = 123456789. ;
|
171 |
|
|
}
|
172 |
|
|
else gest->v_inter[gest->nb_surf*j+i] = vec_posi[0] ;/* valeur mini car vec_posi est trie */
|
173 |
|
|
if (i==j)
|
174 |
|
|
{
|
175 |
|
|
k2 = nb_neg ;
|
176 |
|
|
}
|
177 |
|
|
k1 = k1 + nb_neg ;
|
178 |
|
|
}
|
179 |
|
|
ipair = (k1 + k2) - 2 *(int)((k1+k2)/2) ;
|
180 |
|
|
if (ipair==0)
|
181 |
|
|
{
|
182 |
|
|
(gest->tab_surf[i]).etat= EXTERIEUR ;
|
183 |
|
|
}
|
184 |
|
|
else (gest->tab_surf[i]).etat = INTERIEUR ;
|
185 |
|
|
}
|
186 |
|
|
}
|
187 |
|
|
else (gest->tab_surf[0]).etat = EXTERIEUR ;
|
188 |
|
|
|
189 |
|
|
gest->envel = p3d_c_envel() ;/* creation du volume enveloppe */
|
190 |
|
|
surf_ext = NULL ;
|
191 |
|
|
if (gest->envel == NULL)
|
192 |
|
|
{
|
193 |
|
|
if (debug) printf("%s\n"," erreur P3D_ENVEL ") ;
|
194 |
|
|
return(FAUX) ;
|
195 |
|
|
}
|
196 |
|
|
i = 0 ;
|
197 |
|
|
while ((i<gest->nb_surf) /*&& (surf_ext == NULL)*/)
|
198 |
|
|
{
|
199 |
|
|
if ((gest->tab_surf[i]).etat == EXTERIEUR)
|
200 |
|
|
{
|
201 |
|
|
surf_ext = &(gest->tab_surf[i]) ;
|
202 |
|
|
surf_ext->suivant=(gest->envel)->surf_ext;
|
203 |
|
|
(gest->envel)->surf_ext = surf_ext ;/* on affecte la surface ext au volume */
|
204 |
|
|
surf_ext->envel = gest->envel ;/* puis on affecte le volume a la surface ext */
|
205 |
|
|
}
|
206 |
|
|
i++ ;
|
207 |
|
|
}
|
208 |
|
|
if (surf_ext == NULL)
|
209 |
|
|
{
|
210 |
|
|
return(FAUX) ;
|
211 |
|
|
}
|
212 |
|
|
|
213 |
|
|
/* traitement des surfaces interieures */
|
214 |
|
|
for (i=0;i<gest->nb_surf;i++)
|
215 |
|
|
{
|
216 |
|
|
if ((gest->tab_surf[i]).etat == INTERIEUR)
|
217 |
|
|
{
|
218 |
|
|
surf = &(gest->tab_surf[i]) ;/* surface interieure */
|
219 |
|
|
/* insertion en tete de liste des surfaces interieures liees au volume enveloppe */
|
220 |
|
|
surf->suivant = (gest->envel)->surf_int ;
|
221 |
|
|
(gest->envel)->surf_int = surf ;
|
222 |
|
|
}
|
223 |
|
|
}
|
224 |
|
|
|
225 |
|
|
free(gest->v_inter) ;
|
226 |
|
|
gest->v_inter = NULL ;
|
227 |
|
|
return(VRAI) ;
|
228 |
|
|
}
|
229 |
|
|
|