PageRenderTime 44ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/branches/FREEFEM/freefem/lib/adapt/cad.cxx

#
C++ | 544 lines | 407 code | 28 blank | 109 comment | 82 complexity | 1b7134a2a187ee8a11a9c9747ee8ead6 MD5 | raw file
Possible License(s): AGPL-1.0, GPL-2.0, MPL-2.0-no-copyleft-exception
  1. /*
  2. * ADAPT2D : a software for automatic mesh adaptation in 2D
  3. *
  4. * AUTHOR : Manuel J. Castro Diaz(e-mail:castro@gamba.cie.uma.es)
  5. * ADAPTED FOR FREEFEM : Prud'homme Christophe (e-mail:prudhomm@ann.jussieu.fr)
  6. *
  7. * this code is public domain
  8. *
  9. * You may copy freely these files and use it for
  10. * teaching or research. These or part of these may
  11. * not be sold or used for a commercial purpose without
  12. * our consent
  13. *
  14. * Any problems should be reported to the AUTHOR
  15. * at the following address : castro@gamba.cie.uma.es
  16. */
  17. #include <cad.hxx>
  18. /*
  19. ________________________________________________________________________
  20. SUBRRUTINA TESTEO
  21. Testea si se puden ir uniendo trozos de frontera para formar una
  22. curva cerrada. Si los puede unir los unira en un sentido y otro
  23. segun pueda. El resultado final se una lista (CAD)
  24. cuyos elementos seran a su vez una lista de aristas, estas ordenadas
  25. y de tal manera que forman curvas. El numero de elementos de la
  26. lista (CAD) nos da el numero de componentes conexas
  27. de la frontera.
  28. Entrada: Una lista desordenada de aristas...
  29. Salida: Las aristas ordenadas formando curvas.
  30. */
  31. Boolean CAD::testeo() {
  32. FraristaCAD_link* aux,*aux1,*sig;
  33. Arista_CAD_dlist *l0_aux;
  34. Arista_CAD_dlink *lk_aux,*prev0;
  35. R2 c0,c1;
  36. int ref;
  37. Boolean modif=FALSE;
  38. aux=begin;
  39. while(aux) {
  40. aux1=aux->suc;
  41. while (aux1) {
  42. if ((*aux)<(*aux1)) {
  43. sig=aux1;
  44. aux1=aux1->suc;
  45. enlaza(aux,sig,1);
  46. delete sig;
  47. modif=TRUE;
  48. }
  49. else {
  50. if ((*aux1)<(*aux)) {
  51. sig=aux1;
  52. aux1=aux1->suc;
  53. enlaza (aux,sig,-1);
  54. delete sig;
  55. modif=TRUE;
  56. }
  57. else {
  58. c0=aux->Aretelist->last->a->c[1];
  59. c1=aux1->Aretelist->last->a->c[1];
  60. if (c0==c1) {
  61. l0_aux=aux1->Aretelist;
  62. prev0=NIL;
  63. lk_aux=l0_aux->last;
  64. l0_aux->last=l0_aux->begin;
  65. l0_aux->begin=lk_aux;
  66. while (lk_aux) {
  67. c0=lk_aux->a->c[0];
  68. lk_aux->a->c[0]=lk_aux->a->c[1];
  69. lk_aux->a->c[1]=c0;
  70. ref=lk_aux->a->refv[0];
  71. lk_aux->a->refv[0]=lk_aux->a->refv[1];
  72. lk_aux->a->refv[1]=ref;
  73. lk_aux->suc=lk_aux->prev;
  74. lk_aux->prev=prev0;
  75. prev0=lk_aux;
  76. lk_aux=lk_aux->sig();
  77. }
  78. sig=aux1;
  79. aux1=aux1->suc;
  80. enlaza (aux,sig,1);
  81. delete sig;
  82. modif=TRUE;
  83. }
  84. else {
  85. c0=aux->Aretelist->begin->a->c[0];
  86. c1=aux1->Aretelist->begin->a->c[0];
  87. if (c0==c1) {
  88. l0_aux=aux->Aretelist;
  89. prev0=NIL;
  90. lk_aux=l0_aux->last;
  91. l0_aux->last=l0_aux->begin;
  92. l0_aux->begin=lk_aux;
  93. while (lk_aux) {
  94. c0=lk_aux->a->c[0];
  95. lk_aux->a->c[0]=lk_aux->a->c[1];
  96. lk_aux->a->c[1]=c0;
  97. ref=lk_aux->a->refv[0];
  98. lk_aux->a->refv[0]=lk_aux->a->refv[1];
  99. lk_aux->a->refv[1]=ref;
  100. lk_aux->suc=lk_aux->prev;
  101. lk_aux->prev=prev0;
  102. prev0=lk_aux;
  103. lk_aux=lk_aux->sig();
  104. }
  105. sig=aux1;
  106. aux1=aux1->suc;
  107. enlaza (aux,sig,1);
  108. delete sig;
  109. modif=TRUE;
  110. }
  111. else aux1=aux1->suc;
  112. }
  113. }
  114. }
  115. }
  116. aux=aux->suc;
  117. }
  118. return modif;
  119. }
  120. /* --------------------------------------------------------------------
  121. SUBRRUTINA D_FRONTERA
  122. Proposito: Dado un punto y la Frontera de un dominio, busco la
  123. --------- arista y por tanto, el elemento mas proximo al punto
  124. dado. Calcularemos tambien el proyectado sobre la arista.
  125. Entrada: pt= Punto dado.
  126. ------- - Frontera apuntada por this.
  127. dista=distancia inicial, si no se conoce
  128. poner infinito.
  129. Salida: proyec= proyectado sobre la frontera.
  130. ------ aret= arista mas cercana.
  131. trian= elemento que contine la arista.
  132. Scalar CAD::d_frontera(R2 pt, R2& proyec,\
  133. Arista_T0& arete, Triangulo_T0& triangle,const Scalar& dista) {
  134. FraristaT0_link* aux1;
  135. AristaT0_list* comp_conex;
  136. AristaT0_link* aux;
  137. Arista_T0* aret;
  138. Scalar d0,dist=dista;
  139. R2 pr_pt(0,0);
  140. aux1=begin;
  141. while (aux1) {
  142. comp_conex=aux1->Aretelist;
  143. aux=comp_conex->principio();
  144. while(aux) {
  145. aret=aux->a;
  146. d0=d_arete(*aret,pt,pr_pt);
  147. if (d0<dist) {
  148. dist=d0;
  149. arete=*aret;
  150. triangle=*(aret->tr);
  151. proyec=pr_pt;
  152. }
  153. aux=aux->sig();
  154. }
  155. aux1=aux1->sig();
  156. }
  157. return dist;
  158. }
  159. */
  160. void CAD::write (ostream& os) {
  161. int num=0,i=0;
  162. FraristaCAD_link* aux;
  163. num=this->num_elem();
  164. os <<endl<<"Numero de curvas de la frontera:"<<num<<endl;
  165. aux=begin;
  166. while (aux) {
  167. i++;
  168. os <<aux<<" Curva:"<<i<<" constituida por las Aristas"<<endl;
  169. os <<(*(aux->Aretelist))<<endl;
  170. aux=aux->suc;
  171. }
  172. }
  173. ostream& operator<<(ostream& os, CAD& fl)
  174. { fl.write (os); return os;}
  175. CAD* crea_frontera(Mallado_T0* malla,int angulo) {
  176. CAD* fr_aux,*fr;
  177. FraristaCAD_link* comp_conex,*cc;
  178. Arista_CAD_dlist* arete_list,*al;
  179. Arista_CAD_dlink* arete,*arete_sig,*aa;
  180. Triangulo_T0* t0;
  181. Arista_T0* a0;
  182. Arista_CAD* a_cad;
  183. int nba=malla->nbaa();
  184. int i,ref0,ref1,pos0,nbcc,ang0;
  185. Boolean modif,fin;
  186. fr_aux=new CAD;
  187. if (fr_aux==NIL) ERROR();
  188. for (i=0; i<nba; i++) {
  189. a0=malla->saca_arete(i);
  190. if (a0->front==TRUE) {
  191. a_cad=new Arista_CAD;
  192. if (a_cad==NIL) ERROR();
  193. a_cad->set(a0->s[0]->c,a0->s[1]->c,a0->s[0]->ref,a0->s[1]->ref,a0->ref,1);
  194. arete=new Arista_CAD_dlink;
  195. if (arete==NIL) ERROR();
  196. arete->set(a_cad,NIL,NIL);
  197. arete_list=new Arista_CAD_dlist;
  198. if (arete_list==NIL) ERROR();
  199. arete_list->append(arete);
  200. comp_conex=new FraristaCAD_link;
  201. if (comp_conex==NIL) ERROR();
  202. comp_conex->set(arete_list,NIL,NIL);
  203. fr_aux->append(comp_conex);
  204. modif=fr_aux->testeo();
  205. }
  206. }
  207. for (i=0; i<nba; i++) {
  208. a0=malla->saca_arete(i);
  209. if (a0->front==FALSE) {
  210. t0=a0->tr;
  211. ref0=t0->ref;
  212. pos0=t0->arista(a0);
  213. if (pos0<0) {
  214. cerr<<"Edge is not in triangle."<<endl;
  215. cerr<<a0<<" "<<t0<<endl;
  216. cerr<<"Error in crea_frontera. (Frontera_CAD.C)"<<endl;
  217. exit(-1);
  218. }
  219. ref1=t0->t[pos0]->ref;
  220. if (ref0!=ref1) {
  221. a_cad=new Arista_CAD;
  222. if (a_cad==NIL) ERROR();
  223. a_cad->set(a0->s[0]->c,a0->s[1]->c,a0->s[0]->ref,a0->s[1]->ref,a0->ref,2);
  224. arete=new Arista_CAD_dlink;
  225. if (arete==NIL) ERROR();
  226. arete->set(a_cad,NIL,NIL);
  227. arete_list=new Arista_CAD_dlist;
  228. if (arete_list==NIL) ERROR();
  229. arete_list->append(arete);
  230. comp_conex=new FraristaCAD_link;
  231. if (comp_conex==NIL) ERROR();
  232. comp_conex->set(arete_list,NIL,NIL);
  233. fr_aux->append(comp_conex);
  234. modif=fr_aux->testeo();
  235. }
  236. }
  237. }
  238. modif=TRUE;
  239. while (modif) {modif=fr_aux->testeo();}
  240. fr=new CAD;
  241. if (fr==NIL) ERROR();
  242. nbcc=fr_aux->num_elem();
  243. comp_conex=fr_aux->principio();//cojo la primera componente
  244. // conexa de la frontera.
  245. for (i=0; i<nbcc; i++) {
  246. arete_list=comp_conex->Aretelist; //cojo la lista de aristas de la
  247. // i-esima comp. conexa.
  248. arete=arete_list->principio(); //cojo el principio de la lista de
  249. // aristas.
  250. a_cad=new Arista_CAD;
  251. if (a_cad==NIL) ERROR();
  252. *a_cad=*arete->a;
  253. aa=new Arista_CAD_dlink;
  254. if (aa==NIL) ERROR();
  255. aa->set(a_cad,NIL,NIL);
  256. al=new Arista_CAD_dlist;
  257. if (al==NIL) ERROR();
  258. al->append(aa);
  259. cc=new FraristaCAD_link;
  260. if (cc==NIL) ERROR();
  261. cc->set(al,NIL,NIL);
  262. fr->append(cc);
  263. fin=FALSE;
  264. while (arete) {
  265. arete_sig=arete->sig();
  266. if (arete_sig!=NIL) {
  267. ang0=int(angle(arete->a,arete_sig->a));
  268. if (ang0<=angulo) {
  269. a_cad=new Arista_CAD;
  270. if (a_cad==NIL) ERROR();
  271. *a_cad=*arete_sig->a;
  272. aa=new Arista_CAD_dlink;
  273. if (aa==NIL) ERROR();
  274. aa->set(a_cad,NIL,NIL);
  275. al->append(aa);
  276. }
  277. else {
  278. a_cad=new Arista_CAD;
  279. if (a_cad==NIL) ERROR();
  280. *a_cad=*arete_sig->a;
  281. aa=new Arista_CAD_dlink;
  282. if ( aa==NIL) ERROR();
  283. aa->set(a_cad,NIL,NIL);
  284. al=new Arista_CAD_dlist;
  285. if (al==NIL) ERROR();
  286. al->append(aa);
  287. cc=new FraristaCAD_link;
  288. if (cc==NIL) ERROR();
  289. cc->set(al,NIL,NIL);
  290. fr->append(cc);
  291. }
  292. }
  293. arete=arete->sig();
  294. }
  295. comp_conex=comp_conex->sig();
  296. }
  297. delete fr_aux;
  298. return fr;
  299. }
  300. CAD* build(Triangulation* t_cad, int angulo, Scalar Scale) {
  301. Mallado_T0* m_cad;
  302. CAD* cad=NIL;
  303. m_cad=new Mallado_T0;
  304. if (m_cad==NIL) ERROR();
  305. m_cad->build(int(t_cad->np),int(t_cad->nt),t_cad->rp,t_cad->ng,t_cad->tr,t_cad->ngt,Scale);
  306. if (m_cad->m) {delete[] m_cad->m; m_cad->m=NIL;}
  307. cad=crea_frontera(m_cad,angulo);
  308. cad->set_angulo(angulo);
  309. delete m_cad;
  310. cad->P_control();
  311. return cad;
  312. }
  313. /*
  314. -----------------------------------------------------------------------------
  315. SUBRRUTINA TANGENTES
  316. A cada arista que esta en la frontera asocia en cada vertice dos
  317. tangentes. Estas se utilizaran a la hora de definir la geometria, para
  318. hacer pasar una curva C1 por el borde.
  319. Parametros de entrada: angulo de conservacion de las esquinas.
  320. Salida las tangentes en cada arista. Ademas los vertices que sean
  321. el vertice de un angulo seran marcados con una referencia negativa.
  322. */
  323. void CAD::Tangentes (int ang) {
  324. FraristaCAD_link* comp_conex;
  325. Arista_CAD_dlist* arete_list;
  326. Arista_CAD_dlink* arete,*arete_sig,*arete_ant;
  327. R2 c0,c1;
  328. R2 tang0,tang1;
  329. R2 rc0,rc1,rc2,rc3;
  330. int i,nbcc;
  331. int ang0,ang1;
  332. Boolean fin=FALSE,cerrada;
  333. if (begin!=NIL) {
  334. nbcc=this->num_elem();
  335. comp_conex=this->principio();//cojo la primera componente
  336. // conexa de la frontera.
  337. for (i=0; i<nbcc; i++) {
  338. arete_list=comp_conex->Aretelist; //cojo la lista de aristas de la
  339. // i-esima comp. conexa.
  340. arete=arete_list->principio(); //cojo el principio de la lista de
  341. // aristas.
  342. arete_ant=arete_list->fin();
  343. c0=arete->a->c[0];
  344. c1=arete_ant->a->c[1];
  345. if (c0==c1) { // la curva es cerrada
  346. ang0=int(angle(arete_ant->a,arete->a));
  347. cerrada=TRUE;
  348. }
  349. else{
  350. cerrada=FALSE;
  351. ang0=360;
  352. }
  353. fin=FALSE;
  354. while (fin==FALSE) {
  355. arete_sig=arete->sig();
  356. if (arete_sig==NIL) {
  357. arete_sig=arete_list->principio();
  358. fin=TRUE;
  359. }
  360. rc1=arete->a->c[0];
  361. rc2=arete->a->c[1];
  362. rc0=arete_ant->a->c[0];
  363. rc3=arete_sig->a->c[1];
  364. if (fin==TRUE && cerrada==FALSE)
  365. ang1=360;
  366. else
  367. ang1=int(angle(arete->a,arete_sig->a));
  368. if (ang0<=ang)
  369. tang0=rc2-rc0;
  370. else {
  371. tang0=rc2-rc1;
  372. }
  373. if (ang1<=ang)
  374. tang1=rc3-rc1;
  375. else {
  376. tang1=rc2-rc1;
  377. }
  378. // tang=new Tangente;
  379. // if (tang==NIL) ERROR();
  380. // tang->set(tang0,tang1);
  381. arete->a->tg.set(tang0,tang1);
  382. arete_ant=arete;
  383. arete=arete_sig;
  384. ang0=ang1;
  385. }
  386. comp_conex=comp_conex->sig();
  387. }
  388. }
  389. }
  390. void CAD::P_control () {
  391. FraristaCAD_link* comp_conex;
  392. Arista_CAD_dlist* arete_list;
  393. Arista_CAD_dlink* arete,*aux;
  394. R2 p_ini,p_fin,p,psig;
  395. Scalar m[4][4],cox,coy;
  396. int i,j,k,l,nbcc,nba,cont;
  397. Boolean cerrada,modif;
  398. m[0][0]=-1;m[0][1]=2;m[0][2]=-1;m[0][3]=0;
  399. m[1][0]=3;m[1][1]=-5;m[1][2]=0;m[1][3]=2;
  400. m[2][0]=-3;m[2][1]=4;m[2][2]=1;m[2][3]=0;
  401. m[3][0]=1;m[3][1]=-1;m[3][2]=0;m[3][3]=0;
  402. if (begin!=NIL) {
  403. nbcc=this->num_elem();
  404. comp_conex=this->principio();//cojo la primera componente
  405. // conexa de la frontera.
  406. for (i=0; i<nbcc; i++) {
  407. arete_list=comp_conex->Aretelist; //cojo la lista de aristas de la
  408. // i-esima comp. conexa.
  409. arete=arete_list->principio(); //cojo el principio de la lista de
  410. cerrada=FALSE; // aristas.
  411. aux=arete_list->fin();
  412. if (arete->a->c[0]==aux->a->c[1]) cerrada=TRUE;
  413. if (cerrada==TRUE) {
  414. p_ini=aux->a->c[0];
  415. p_fin=arete->a->c[1];
  416. }
  417. else {
  418. p_ini=arete->a->c[0]*2-arete->a->c[1];
  419. p_fin=aux->a->c[1]*2-aux->a->c[0];
  420. }
  421. nba=arete_list->num_elem();
  422. for (j=0;j<nba;j++) {
  423. // cout<<" j:"<<j<<" --------------------------------------------------"<<endl;
  424. for (k=0; k<4; k++) {
  425. cox=coy=0.0;
  426. aux=arete->ant();
  427. if (aux==NIL){
  428. p=p_ini;
  429. psig=arete->a->c[0];
  430. }
  431. else {
  432. p=aux->a->c[0];
  433. psig=aux->a->c[1];
  434. }
  435. cont=0;
  436. for (l=0; l<4; l++) {
  437. // if (k==0) cout<<p<<endl;
  438. cox+=m[l][k]*p.x;
  439. coy+=m[l][k]*p.y;
  440. if (arete->ant()==NIL && aux==NIL) {
  441. aux=arete;
  442. }
  443. else {
  444. if (aux) aux=aux->sig();
  445. }
  446. if (aux) {
  447. p=aux->a->c[0];
  448. psig=aux->a->c[1];
  449. }
  450. else {
  451. if (cont==0){
  452. p=psig;
  453. cont=1;
  454. }
  455. else
  456. p=p_fin;
  457. }
  458. }
  459. if (arete) arete->a->cf[k].set(cox,coy);
  460. }
  461. arete=arete->sig();
  462. }
  463. comp_conex=comp_conex->sig();
  464. }
  465. modif=TRUE;
  466. while (modif) {modif=this->testeo();}
  467. }
  468. }
  469. void CAD::Pinta (int np) {
  470. FraristaCAD_link* comp_conex;
  471. Arista_CAD_dlist* arete_list;
  472. Arista_CAD_dlink* arete;
  473. Arista_CAD* a0;
  474. R2 pt;
  475. Scalar temp;
  476. int j,i,nbcc;
  477. char path[72]="spline";
  478. if (begin!=NIL) {
  479. OPEN(escritura, path);
  480. escritura.setf(ios::scientific,ios::floatfield);
  481. nbcc=this->num_elem();
  482. comp_conex=this->principio();//cojo la primera componente
  483. // conexa de la frontera.
  484. for (i=0; i<nbcc; i++) {
  485. arete_list=comp_conex->Aretelist; //cojo la lista de aristas de la
  486. // i-esima comp. conexa.
  487. arete=arete_list->principio(); //cojo el principio de la lista de
  488. // aristas.
  489. while (arete) {
  490. a0=arete->a;
  491. for (j=0; j<np; j++) {
  492. temp=j/Scalar(np-1);
  493. pt=(a0->cf[3]+a0->cf[2]*temp+a0->cf[1]*(temp*temp)+a0->cf[0]*(temp*temp*temp))*0.5;
  494. escritura<<""<<setw(15)<<pt.x<<setw(15)<<pt.y<<endl;
  495. }
  496. arete=arete->sig();
  497. }
  498. comp_conex=comp_conex->sig();
  499. }
  500. escritura.close();
  501. }
  502. }