/freefem++-3.19-1/src/femlib/Mesh2dn.cpp

# · C++ · 455 lines · 287 code · 74 blank · 94 comment · 49 complexity · b837bb49d0adaec9b12d6c8ad3faaa35 MD5 · raw file

  1. // ORIG-DATE: Dec 2007
  2. // -*- Mode : c++ -*-
  3. //
  4. // SUMMARY : Model mesh 2d
  5. // USAGE : LGPL
  6. // ORG : LJLL Universite Pierre et Marie Curi, Paris, FRANCE
  7. // AUTHOR : Frederic Hecht
  8. // E-MAIL : frederic.hecht@ann.jussieu.fr
  9. //
  10. /*
  11. This file is part of Freefem++
  12. Freefem++ is free software; you can redistribute it and/or modify
  13. it under the terms of the GNU Lesser General Public License as published by
  14. the Free Software Foundation; either version 2.1 of the License, or
  15. (at your option) any later version.
  16. Freefem++ is distributed in the hope that it will be useful,
  17. but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. GNU Lesser General Public License for more details.
  20. You should have received a copy of the GNU Lesser General Public License
  21. along with Freefem++; if not, write to the Free Software
  22. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  23. Thank to the ARN () FF2A3 grant
  24. ref:ANR-07-CIS7-002-01
  25. */
  26. #include <fstream>
  27. #include <iostream>
  28. #include "ufunction.hpp"
  29. #include "error.hpp"
  30. #include "RNM.hpp"
  31. #include "libmesh5.h"
  32. #include "Mesh2dn.hpp"
  33. // for plotStream (a change)
  34. #include "Mesh3dn.hpp"
  35. #include "rgraph.hpp"
  36. #include "fem.hpp"
  37. #include "PlotStream.hpp"
  38. namespace Fem2D {
  39. long verbosity=1;
  40. // const R1 R1::KHat[2]={R1(0),R1(1)};
  41. // const R2 R2::KHat[3]={R2(0,0),R2(1,0),R2(0,1)};
  42. // const R3 R3::KHat[4]={R3(0,0,0),R3(1,0,0),R3(0,1,0),R3(0,0,1)};
  43. static const int nvfaceTet[4][3] = { {2,1,3},{0,2,3},{1,0,3},{0,1,2} };
  44. static const int nvedgeTet[6][2] = { {0,1},{0,2},{0,3},{0,1},{1,2},{2,3} };
  45. static const int nvfaceTria[1][3] = { {0,1,2} };
  46. static const int nvedgeTria[3][2] = { {1,2},{2,0},{0,1}}; // tourne de le sens trigo donc Normal ext vect(1,0) ^ perp
  47. static const int nvfaceSeg[1][3] = {{-1,-1,1}};
  48. static const int nvedgeSeg[1][2] = { {0,1} };
  49. static const int nvadjSeg[2][1] = { {0},{1} };
  50. template<> const int (* const GenericElement<DataSeg2>::nvface)[3] = 0 ;
  51. template<> const int (* const GenericElement<DataSeg2>::nvedge)[2] = nvedgeSeg; //nvedgeTria ;
  52. template<> const int (* const GenericElement<DataSeg2>::nvadj)[1] = nvadjSeg ;
  53. template<> const int (* const GenericElement<DataTriangle2>::nvface)[3] = nvfaceTria ;
  54. template<> const int (* const GenericElement<DataTriangle2>::nvedge)[2] = nvedgeTria ;
  55. template<> const int (* const GenericElement<DataTriangle2>::nvadj)[2] = nvedgeTria ;
  56. template<> const int GenericElement<DataTriangle2>::nitemdim[4] = {3,3,1,0 } ;
  57. static const int onWhatIsEdge2d[3][7] = { {0,1,3, 2,0,0, 0}, // edge 0
  58. {3,0,1, 0,2,0, 0},
  59. {1,3,0, 0,0,2, 0}};
  60. template<>
  61. const int (* const GenericElement<DataTriangle2>::onWhatBorder)[7] = onWhatIsEdge2d ;
  62. template<> int GenericMesh<Triangle2,BoundaryEdge2,Vertex2>::kfind=0;
  63. template<> int GenericMesh<Triangle2,BoundaryEdge2,Vertex2>::kthrough=0;
  64. Mesh2::Mesh2(const char * filename)
  65. { // read the mesh
  66. int nt,nv,nbe;
  67. int ok=load(filename);
  68. if(ok)
  69. {
  70. ifstream f(filename);
  71. if(!f) {cerr << "Mesh2::Mesh2 Erreur openning " << filename<<endl;exit(1);}
  72. if(verbosity)
  73. cout << " Read On file \"" <<filename<<"\""<< endl;
  74. f >> nv >> nt >> nbe ;
  75. this->set(nv,nt,nbe);
  76. if(verbosity)
  77. cout << " -- Nb of Vertex " << nv << " " << " Nb of Triangles " << nt
  78. << " , Nb of border edges " << nbe << endl;
  79. assert(f.good() && nt && nv) ;
  80. for (int i=0;i<nv;i++)
  81. {
  82. f >> this->vertices[i];
  83. assert(f.good());
  84. }
  85. mes=0;
  86. for (int i=0;i<nt;i++)
  87. {
  88. this->t(i).Read1(f,this->vertices,nv);
  89. mes += t(i).mesure();
  90. }
  91. mesb=0.;
  92. for (int i=0;i<nbe;i++)
  93. {
  94. this->be(i).Read1(f,this->vertices,nv);
  95. mesb += be(i).mesure();
  96. }
  97. }
  98. BuildBound();
  99. BuildAdj();
  100. Buildbnormalv();
  101. BuildjElementConteningVertex();
  102. if(verbosity)
  103. cout << " - mesh mesure = " << mes << " border mesure: " << mesb << endl;
  104. }
  105. int Mesh2::load(const string & filename)
  106. {
  107. int bin;
  108. int ver,inm,dim;
  109. int lf=filename.size()+20;
  110. KN<char> fileb(lf),filef(lf);
  111. char * pfile;
  112. strcpy(filef,filename.c_str());
  113. strcpy(fileb,filef);
  114. strcat(filef,".mesh");
  115. strcat(fileb,".meshb");
  116. if( (inm=GmfOpenMesh(pfile=fileb, GmfRead,&ver,&dim)) )
  117. bin=true;
  118. else if( (inm=GmfOpenMesh(pfile=filef, GmfRead,&ver,&dim)) )
  119. bin=false;
  120. else
  121. { cerr << " Erreur ouverture file " << (char *) fileb << " " << (char *) filef << endl;
  122. return 1;
  123. }
  124. int nv,nt,neb;
  125. nv = GmfStatKwd(inm,GmfVertices);
  126. nt = GmfStatKwd(inm,GmfTriangles);
  127. neb=GmfStatKwd(inm,GmfEdges);
  128. this->set(nv,nt,neb);
  129. if(verbosity)
  130. cout << pfile <<": ver " << ver << ", d "<< dim << ", nt " << nt << ", nv " << nv << " nbe: = " << nbe << endl;
  131. if(dim != Rd::d) {
  132. cerr << "Err dim == " << dim << " != " << Rd::d << endl;
  133. return 2; }
  134. if( nv<=0 && nt <=0 ) {
  135. cerr << " missing data "<< endl;
  136. return 3;
  137. }
  138. int iv[4],lab;
  139. float cr[3];
  140. // read vertices
  141. GmfGotoKwd(inm,GmfVertices);
  142. int mxlab=0;
  143. int mnlab=0;
  144. for(int i=0;i<nv;++i)
  145. {
  146. if(ver<2) {
  147. GmfGetLin(inm,GmfVertices,&cr[0],&cr[1],&cr[2],&lab);
  148. vertices[i].x=cr[0];
  149. vertices[i].y=cr[1];
  150. // vertices[i].z=cr[2];
  151. }
  152. else
  153. GmfGetLin(inm,GmfVertices,&vertices[i].x,&vertices[i].y,&lab);
  154. vertices[i].lab=lab;
  155. mxlab= max(mxlab,lab);
  156. mnlab= min(mnlab,lab);
  157. }
  158. // /* read mesh triangles */
  159. if(mnlab==0 &&mxlab==0 )
  160. {
  161. mes=0;
  162. GmfGotoKwd(inm,GmfTriangles);
  163. for(int i=0;i<nbe;++i)
  164. {
  165. GmfGetLin(inm,GmfTriangles,&iv[0],&iv[1],&iv[2],&lab);
  166. for (int j=0;j<3;++j)
  167. iv[j]--;
  168. this->elements[i].set(this->vertices,iv,lab);
  169. mes += this->elements[i].mesure();
  170. }
  171. }
  172. /* read mesh segement */
  173. mesb=0;
  174. GmfGotoKwd(inm,GmfEdges);
  175. for(int i=0;i<nbe;++i)
  176. {
  177. GmfGetLin(inm,GmfEdges,&iv[0],&iv[1],&lab);
  178. assert( iv[0]>0 && iv[0]<=nv && iv[1]>0 && iv[1]<=nv);
  179. for (int j=0;j<2;j++) iv[j]--;
  180. this->borderelements[i].set(vertices,iv,lab);
  181. mesb += this->borderelements[i].mesure();
  182. }
  183. GmfCloseMesh(inm);
  184. return(0); // OK
  185. }
  186. int Mesh2::Save(const string & filename)
  187. {
  188. int ver = GmfFloat, outm;
  189. if ( !(outm = GmfOpenMesh(filename.c_str(),GmfWrite,ver,2)) ) {
  190. cerr <<" -- Mesh2::Save UNABLE TO OPEN :"<< filename << endl;
  191. return(1);
  192. }
  193. float fx,fy;
  194. GmfSetKwd(outm,GmfVertices,this->nv);
  195. for (int k=0; k<nv; k++) {
  196. const Vertex & P = this->vertices[k];
  197. GmfSetLin(outm,GmfVertices,fx=P.x,fy=P.y,P.lab);
  198. }
  199. GmfSetKwd(outm,GmfTriangles,nt);
  200. for (int k=0; k<nt; k++) {
  201. const Element & K(this->elements[k]);
  202. int i0=this->operator()(K[0])+1;
  203. int i1=this->operator()(K[1])+1;
  204. int i2=this->operator()(K[2])+1;
  205. int lab=K.lab;
  206. GmfSetLin(outm,GmfTriangles,i0,i1,i2,lab);
  207. }
  208. GmfSetKwd(outm,GmfEdges,nbe);
  209. for (int k=0; k<nbe; k++) {
  210. const BorderElement & K(this->borderelements[k]);
  211. int i0=this->operator()(K[0])+1;
  212. int i1=this->operator()(K[1])+1;
  213. int lab=K.lab;
  214. GmfSetLin(outm,GmfEdges,i0,i1,lab);
  215. }
  216. GmfCloseMesh(outm);
  217. return (0);
  218. }
  219. const string Gsbegin="Mesh2::GSave v0",Gsend="end";
  220. template<class Mesh>
  221. void GSave2(FILE * ff,const Mesh & Th)
  222. {
  223. PlotStream f(ff);
  224. f << Gsbegin ;
  225. int nbe=Th.nbBrdElmts();
  226. f << Th.nv << Th.nt << nbe;
  227. for (int k=0; k<Th.nv; k++) {
  228. const typename Mesh::Vertex & P = Th(k);
  229. f << P.x <<P.y << P.lab ;
  230. }
  231. for (int k=0; k<Th.nt; k++) {
  232. const typename Mesh::Element & K(Th[k]);
  233. int i0=Th(K[0]);
  234. int i1=Th(K[1]);
  235. int i2=Th(K[2]);
  236. int lab=K.lab;
  237. f << i0 << i1 << i2 << lab;
  238. }
  239. for (int k=0; k<nbe; k++) {
  240. const typename Mesh::BorderElement & K(Th.be(k));
  241. int i0=Th(K[0]);
  242. int i1=Th(K[1]);
  243. int lab=K.lab;
  244. f << i0 << i1 << lab;
  245. }
  246. f << Gsend;
  247. }
  248. //template void GSave2<Mesh2>(FILE * ff,const Mesh2 & Th) ;
  249. template void GSave2<Mesh>(FILE * ff,const Mesh & Th) ;
  250. Mesh2::Mesh2(FILE *f)
  251. {
  252. GRead(f);
  253. assert( (nt >= 0 || nbe>=0) && nv>0) ;
  254. BuildBound();
  255. if(verbosity>1)
  256. cout << " -- End of read: mesure = " << mes << " border mesure " << mesb << endl;
  257. if(nt > 0){
  258. BuildAdj();
  259. Buildbnormalv();
  260. BuildjElementConteningVertex();
  261. }
  262. if(verbosity>1)
  263. cout << " -- Mesh2 (File *), d "<< 2 << ", n Tet " << nt << ", n Vtx "
  264. << nv << " n Bord " << nbe << endl;
  265. }
  266. void Mesh2::GRead(FILE * ff)
  267. {
  268. PlotStream f(ff);
  269. string s;
  270. f >> s;
  271. ffassert( s== Gsbegin);
  272. f >> nv >> nt >> nbe;
  273. if(verbosity>1)
  274. cout << " GRead : nv " << nv << " " << nt << " " << nbe << endl;
  275. this->vertices = new Vertex[nv];
  276. this->elements = new Element [nt];
  277. this->borderelements = new BorderElement[nbe];
  278. for (int k=0; k<nv; k++) {
  279. Vertex & P = this->vertices[k];
  280. f >> P.x >>P.y >> P.lab ;
  281. }
  282. mes=0.;
  283. mesb=0.;
  284. if(nt != 0)
  285. {
  286. for (int k=0; k<nt; k++) {
  287. int i[4],lab;
  288. Element & K(this->elements[k]);
  289. f >> i[0] >> i[1] >> i[2] >> lab;
  290. K.set(this->vertices,i,lab);
  291. mes += K.mesure();
  292. }
  293. }
  294. for (int k=0; k<nbe; k++) {
  295. int i[4],lab;
  296. BorderElement & K(this->borderelements[k]);
  297. f >> i[0] >> i[1] >> lab;
  298. K.set(this->vertices,i,lab);
  299. mesb += K.mesure();
  300. }
  301. f >> s;
  302. ffassert( s== Gsend);
  303. }
  304. /*
  305. int Mesh2::Popen(const FILE *namestream)
  306. {
  307. int ver = GmfFloat;
  308. int dimp =2;
  309. float fx,fy;
  310. FILE *popenstream;
  311. popenstream = namestream;
  312. fprintf(popenstream,"MeshVersionFormatted\n");
  313. fprintf(popenstream,"%i\n",ver);
  314. fprintf(popenstream,"Dimension\n");
  315. fprintf(popenstream,"%i\n",dimp);
  316. fprintf(popenstream,"Vertices\n");
  317. fprintf(popenstream,"%i\n",this->nv);
  318. for (int k=0; k<nv; k++) {
  319. const Vertex & P = this->vertices[k];
  320. fx=P.x; fy=P.y;
  321. fprintf(popenstream,"%f %f %i\n",fx,fy,P.lab);
  322. }
  323. fprintf(popenstream,"Triangles\n");
  324. fprintf(popenstream,"%i\n",this->nt);
  325. for (int k=0; k<nt; k++) {
  326. const Element & K(this->elements[k]);
  327. int i0=this->operator()(K[0])+1;
  328. int i1=this->operator()(K[1])+1;
  329. int i2=this->operator()(K[2])+1;
  330. int lab=K.lab;
  331. fprintf(popenstream,"%i %i %i %i\n",i0,i1,i2,lab);
  332. }
  333. fprintf(popenstream,"Edges\n");
  334. for (int k=0; k<nbe; k++) {
  335. const BorderElement & K(this->borderelements[k]);
  336. int i0=this->operator()(K[0])+1;
  337. int i1=this->operator()(K[1])+1;
  338. int lab=K.lab;
  339. fprintf(popenstream,"%i %i %i\n",i0,i1,lab);
  340. }
  341. return (0);
  342. }
  343. */
  344. Mesh2::Mesh2(int nnv, int nnt, int nnbe, Vertex2 *vv, Triangle2 *tt, BoundaryEdge2 *bb)
  345. {
  346. nv = nnv;
  347. nt = nnt;
  348. nbe =nnbe;
  349. vertices = vv;
  350. elements = tt;
  351. borderelements = bb;
  352. mes=0.;
  353. mesb=0.;
  354. for (int i=0;i<nt;i++)
  355. mes += this->elements[i].mesure();
  356. for (int i=0;i<nbe;i++)
  357. mesb += this->be(i).mesure();
  358. //if(nnt !=0){
  359. //BuildBound();
  360. //BuildAdj();
  361. //Buildbnormalv();
  362. //BuildjElementConteningVertex();
  363. //BuildGTree();
  364. //decrement();
  365. //}
  366. if(verbosity>1)
  367. cout << " -- End of read: mesure = " << mes << " border mesure " << mesb << endl;
  368. }
  369. }